diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 1ec5b6f206..10c2471024 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1786,7 +1786,7 @@ static int want_object_in_pack_mtime(const struct object_id *oid, struct multi_pack_index *m = get_multi_pack_index(files->packed); struct pack_entry e; - if (m && fill_midx_entry(m, oid, &e)) { + if (m && fill_midx_entry(m, oid, &e, NULL)) { want = want_object_in_pack_one(e.p, oid, exclude, found_pack, found_offset, found_mtime); if (want != -1) return want; diff --git a/midx.c b/midx.c index 76c3f92cc3..37f082dbdd 100644 --- a/midx.c +++ b/midx.c @@ -591,7 +591,8 @@ uint32_t nth_midxed_pack_int_id(struct multi_pack_index *m, uint32_t pos) int fill_midx_entry(struct multi_pack_index *m, const struct object_id *oid, - struct pack_entry *e) + struct pack_entry *e, + struct packed_git **bad_pack) { uint32_t pos; uint32_t pack_int_id; @@ -618,8 +619,11 @@ int fill_midx_entry(struct multi_pack_index *m, return 0; if (oidset_size(&p->bad_objects) && - oidset_contains(&p->bad_objects, oid)) + oidset_contains(&p->bad_objects, oid)) { + if (bad_pack && !*bad_pack) + *bad_pack = p; return 0; + } e->offset = nth_midxed_offset(m, pos); e->p = p; @@ -1028,7 +1032,7 @@ int verify_midx_file(struct odb_source_packed *source, unsigned flags) nth_midxed_object_oid(&oid, m, pairs[i].pos); - if (!fill_midx_entry(m, &oid, &e)) { + if (!fill_midx_entry(m, &oid, &e, NULL)) { midx_report(_("failed to load pack entry for oid[%d] = %s"), pairs[i].pos, oid_to_hex(&oid)); continue; diff --git a/midx.h b/midx.h index 939c18e588..1f2f2d5321 100644 --- a/midx.h +++ b/midx.h @@ -117,7 +117,8 @@ uint32_t nth_midxed_pack_int_id(struct multi_pack_index *m, uint32_t pos); struct object_id *nth_midxed_object_oid(struct object_id *oid, struct multi_pack_index *m, uint32_t n); -int fill_midx_entry(struct multi_pack_index *m, const struct object_id *oid, struct pack_entry *e); +int fill_midx_entry(struct multi_pack_index *m, const struct object_id *oid, + struct pack_entry *e, struct packed_git **bad_pack); int midx_contains_pack(struct multi_pack_index *m, const char *idx_or_pack_name); int midx_layer_contains_pack(struct multi_pack_index *m, diff --git a/odb/source-packed.c b/odb/source-packed.c index 0890704e76..16fa4f5769 100644 --- a/odb/source-packed.c +++ b/odb/source-packed.c @@ -13,18 +13,19 @@ static int find_pack_entry(struct odb_source_packed *store, const struct object_id *oid, - struct pack_entry *e) + struct pack_entry *e, + struct packed_git **bad_pack) { struct packfile_list_entry *l; odb_source_prepare(&store->base, 0); - if (store->midx && fill_midx_entry(store->midx, oid, e)) + if (store->midx && fill_midx_entry(store->midx, oid, e, bad_pack)) return 1; for (l = store->packs.head; l; l = l->next) { struct packed_git *p = l->pack; - if (!p->multi_pack_index && packfile_fill_entry(p, oid, e)) { + if (!p->multi_pack_index && packfile_fill_entry(p, oid, e, bad_pack)) { if (!store->skip_mru_updates) packfile_list_prepend(&store->packs, p); return 1; @@ -40,6 +41,7 @@ static int odb_source_packed_read_object_info(struct odb_source *source, enum object_info_flags flags) { struct odb_source_packed *packed = odb_source_packed_downcast(source); + struct packed_git *bad_pack = NULL; struct pack_entry e; int ret; @@ -51,8 +53,16 @@ static int odb_source_packed_read_object_info(struct odb_source *source, if (flags & OBJECT_INFO_SECOND_READ) odb_source_prepare(source, ODB_PREPARE_FLUSH_CACHES); - if (!find_pack_entry(packed, oid, &e)) + if (!find_pack_entry(packed, oid, &e, &bad_pack)) { + /* + * The lookup may have failed because the object is known to be + * corrupt in one of the packfiles. Report the object as + * corrupt instead of missing in that case. + */ + if (bad_pack) + return -1; return 1; + } /* * We know that the caller doesn't actually need the @@ -77,7 +87,7 @@ static int odb_source_packed_read_object_stream(struct odb_read_stream **out, struct odb_source_packed *packed = odb_source_packed_downcast(source); struct pack_entry e; - if (!find_pack_entry(packed, oid, &e)) + if (!find_pack_entry(packed, oid, &e, NULL)) return -1; return packfile_read_object_stream(out, oid, e.p, e.offset); @@ -583,7 +593,7 @@ static int odb_source_packed_freshen_object(struct odb_source *source, timesp = × } - if (!find_pack_entry(packed, oid, &e)) + if (!find_pack_entry(packed, oid, &e, NULL)) return 0; if (e.p->is_cruft) return 0; diff --git a/packfile.c b/packfile.c index 0eee45055f..34e2f9bb8b 100644 --- a/packfile.c +++ b/packfile.c @@ -1859,13 +1859,17 @@ int is_pack_valid(struct packed_git *p) int packfile_fill_entry(struct packed_git *p, const struct object_id *oid, - struct pack_entry *e) + struct pack_entry *e, + struct packed_git **bad_pack) { off_t offset; if (oidset_size(&p->bad_objects) && - oidset_contains(&p->bad_objects, oid)) + oidset_contains(&p->bad_objects, oid)) { + if (bad_pack && !*bad_pack) + *bad_pack = p; return 0; + } offset = find_pack_entry_one(oid, p); if (!offset) @@ -1962,7 +1966,7 @@ int has_object_kept_pack(struct repository *r, const struct object_id *oid, for (; *cache; cache++) { struct packed_git *p = *cache; - if (packfile_fill_entry(p, oid, &e)) + if (packfile_fill_entry(p, oid, &e, NULL)) return 1; } } diff --git a/packfile.h b/packfile.h index e1f77152b5..3229a6ed47 100644 --- a/packfile.h +++ b/packfile.h @@ -294,7 +294,8 @@ off_t find_pack_entry_one(const struct object_id *oid, struct packed_git *); int packfile_fill_entry(struct packed_git *p, const struct object_id *oid, - struct pack_entry *e); + struct pack_entry *e, + struct packed_git **bad_pack); int is_pack_valid(struct packed_git *); void *unpack_entry(struct repository *r, struct packed_git *, off_t, diff --git a/t/helper/test-read-midx.c b/t/helper/test-read-midx.c index fb16ec0176..27a05da957 100644 --- a/t/helper/test-read-midx.c +++ b/t/helper/test-read-midx.c @@ -82,7 +82,7 @@ static int read_midx_file(const char *object_dir, const char *checksum, for (i = 0; i < m->num_objects; i++) { nth_midxed_object_oid(&oid, m, i + m->num_objects_in_base); - fill_midx_entry(m, &oid, &e); + fill_midx_entry(m, &oid, &e, NULL); printf("%s %"PRIu64"\t%s\n", oid_to_hex(&oid), e.offset, e.p->pack_name);