odb/source-packed: flag known-bad objects as corrupt and not missing
When reading packed objects we know to tell apart missing objects and corrupt objects by returning a positive error code in the former case, and a negative one in the latter case. We do that by distinguishing between errors returned by `find_pack_entry()`, which yields the offset of the object, and `packed_object_info()`, which reads the object contents. But even though we already distinguish those cases when reading packed objects, the logic is broken in case a caller tries to read an object that has been marked as corrupt. In that case, `find_pack_entry()` will tell us that the object in question does not exist, and consequently we'll not flag the object as corrupt but as missing. Fix this issue by bubbling up whether the object is corrupt and, if so, which packfile contains the corrupted object. Note that we don't yet need the information about the specific packfile, so we could've just as well made this a `bool *corrupted` pointer. But we'll need information about the containing packfile in a subsequent commit so that we can generate a proper error message telling the user which packfile contains the broken object. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>main
parent
dea0ea3582
commit
47ef2193b3
|
|
@ -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;
|
||||
|
|
|
|||
10
midx.c
10
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;
|
||||
|
|
|
|||
3
midx.h
3
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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
10
packfile.c
10
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue