Merge branch 'ab/fsck-unexpected-type'

"git fsck" has been taught to report mismatch between expected and
actual types of an object better.

* ab/fsck-unexpected-type:
  fsck: report invalid object type-path combinations
  fsck: don't hard die on invalid object types
  object-file.c: stop dying in parse_loose_header()
  object-file.c: return ULHR_TOO_LONG on "header too long"
  object-file.c: use "enum" return type for unpack_loose_header()
  object-file.c: simplify unpack_loose_short_header()
  object-file.c: make parse_loose_header_extended() public
  object-file.c: return -1, not "status" from unpack_loose_header()
  object-file.c: don't set "typep" when returning non-zero
  cat-file tests: test for current --allow-unknown-type behavior
  cat-file tests: add corrupt loose object test
  cat-file tests: test for missing/bogus object with -t, -s and -p
  cat-file tests: move bogus_* variable declarations earlier
  fsck tests: test for garbage appended to a loose object
  fsck tests: test current hash/type mismatch behavior
  fsck tests: refactor one test to use a sub-repo
  fsck tests: add test for fsck-ing an unknown type
This commit is contained in:
Junio C Hamano
2021-10-25 16:06:56 -07:00
13 changed files with 478 additions and 162 deletions

View File

@ -593,18 +593,43 @@ static void get_default_heads(void)
}
}
struct for_each_loose_cb
{
struct progress *progress;
struct strbuf obj_type;
};
static int fsck_loose(const struct object_id *oid, const char *path, void *data)
{
struct for_each_loose_cb *cb_data = data;
struct object *obj;
enum object_type type;
enum object_type type = OBJ_NONE;
unsigned long size;
void *contents;
int eaten;
struct object_info oi = OBJECT_INFO_INIT;
struct object_id real_oid = *null_oid();
int err = 0;
if (read_loose_object(path, oid, &type, &size, &contents) < 0) {
strbuf_reset(&cb_data->obj_type);
oi.type_name = &cb_data->obj_type;
oi.sizep = &size;
oi.typep = &type;
if (read_loose_object(path, oid, &real_oid, &contents, &oi) < 0) {
if (contents && !oideq(&real_oid, oid))
err = error(_("%s: hash-path mismatch, found at: %s"),
oid_to_hex(&real_oid), path);
else
err = error(_("%s: object corrupt or missing: %s"),
oid_to_hex(oid), path);
}
if (type != OBJ_NONE && type < 0)
err = error(_("%s: object is of unknown type '%s': %s"),
oid_to_hex(&real_oid), cb_data->obj_type.buf,
path);
if (err < 0) {
errors_found |= ERROR_OBJECT;
error(_("%s: object corrupt or missing: %s"),
oid_to_hex(oid), path);
return 0; /* keep checking other objects */
}
@ -640,8 +665,10 @@ static int fsck_cruft(const char *basename, const char *path, void *data)
return 0;
}
static int fsck_subdir(unsigned int nr, const char *path, void *progress)
static int fsck_subdir(unsigned int nr, const char *path, void *data)
{
struct for_each_loose_cb *cb_data = data;
struct progress *progress = cb_data->progress;
display_progress(progress, nr + 1);
return 0;
}
@ -649,6 +676,10 @@ static int fsck_subdir(unsigned int nr, const char *path, void *progress)
static void fsck_object_dir(const char *path)
{
struct progress *progress = NULL;
struct for_each_loose_cb cb_data = {
.obj_type = STRBUF_INIT,
.progress = progress,
};
if (verbose)
fprintf_ln(stderr, _("Checking object directory"));
@ -657,9 +688,10 @@ static void fsck_object_dir(const char *path)
progress = start_progress(_("Checking object directories"), 256);
for_each_loose_file_in_objdir(path, fsck_loose, fsck_cruft, fsck_subdir,
progress);
&cb_data);
display_progress(progress, 256);
stop_progress(&progress);
strbuf_release(&cb_data.obj_type);
}
static int fsck_head_link(const char *head_ref_name,