Skip to content

Commit 4ae0e94

Browse files
peffgitster
authored andcommitted
fsck: stop using object_info->type_name strbuf
When fsck-ing a loose object, we use object_info's type_name strbuf to record the parsed object type as a string. For most objects this is redundant with the object_type enum, but it does let us report the string when we encounter an object with an unknown type (for which there is no matching enum value). There are a few downsides, though: 1. The code to report these cases is not actually robust. Since we did not pass a strbuf to unpack_loose_header(), we only retrieved types from headers up to 32 bytes. In longer cases, we'd simply say "object corrupt or missing". 2. This is the last caller that uses object_info's type_name strbuf support. It would be nice to refactor it so that we can simplify that code. 3. Likewise, we'll check the hash of the object using its unknown type (again, as long as that type is short enough). That depends on the hash_object_file_literally() code, which we'd eventually like to get rid of. So we can simplify things by bailing immediately in read_loose_object() when we encounter an unknown type. This has a few user-visible effects: a. Instead of producing a single line of error output like this: error: 26ed13ce3564fbbb44e35bde42c7da717ea004a6: object is of unknown type 'bogus': .git/objects/26/ed13ce3564fbbb44e35bde42c7da717ea004a6 we'll now issue two lines (the first from read_loose_object() when we see the unparsable header, and the second from the fsck code, since we couldn't read the object): error: unable to parse type from header 'bogus 4' of .git/objects/26/ed13ce3564fbbb44e35bde42c7da717ea004a6 error: 26ed13ce3564fbbb44e35bde42c7da717ea004a6: object corrupt or missing: .git/objects/26/ed13ce3564fbbb44e35bde42c7da717ea004a6 This is a little more verbose, but this sort of error should be rare (such objects are almost impossible to work with, and cannot be transferred between repositories as they are not representable in packfiles). And as a bonus, reporting the broken header in full could help with debugging other cases (e.g., a header like "blob xyzzy\0" would fail in parsing the size, but previously we'd not have showed the offending bytes). b. An object with an unknown type will be reported as corrupt, without actually doing a hash check. Again, I think this is unlikely to matter in practice since such objects are totally unusable. We'll update one fsck test to match the new error strings. And we can remove another test that covered the case of an object with an unknown type _and_ a hash corruption. Since we'll skip the hash check now in this case, the test is no longer interesting. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent b32b434 commit 4ae0e94

File tree

3 files changed

+14
-40
lines changed

3 files changed

+14
-40
lines changed

builtin/fsck.c

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -614,12 +614,11 @@ static void get_default_heads(void)
614614
struct for_each_loose_cb
615615
{
616616
struct progress *progress;
617-
struct strbuf obj_type;
618617
};
619618

620-
static int fsck_loose(const struct object_id *oid, const char *path, void *data)
619+
static int fsck_loose(const struct object_id *oid, const char *path,
620+
void *data UNUSED)
621621
{
622-
struct for_each_loose_cb *cb_data = data;
623622
struct object *obj;
624623
enum object_type type = OBJ_NONE;
625624
unsigned long size;
@@ -629,8 +628,6 @@ static int fsck_loose(const struct object_id *oid, const char *path, void *data)
629628
struct object_id real_oid = *null_oid(the_hash_algo);
630629
int err = 0;
631630

632-
strbuf_reset(&cb_data->obj_type);
633-
oi.type_name = &cb_data->obj_type;
634631
oi.sizep = &size;
635632
oi.typep = &type;
636633

@@ -642,10 +639,6 @@ static int fsck_loose(const struct object_id *oid, const char *path, void *data)
642639
err = error(_("%s: object corrupt or missing: %s"),
643640
oid_to_hex(oid), path);
644641
}
645-
if (type != OBJ_NONE && type < 0)
646-
err = error(_("%s: object is of unknown type '%s': %s"),
647-
oid_to_hex(&real_oid), cb_data->obj_type.buf,
648-
path);
649642
if (err < 0) {
650643
errors_found |= ERROR_OBJECT;
651644
free(contents);
@@ -697,7 +690,6 @@ static void fsck_object_dir(const char *path)
697690
{
698691
struct progress *progress = NULL;
699692
struct for_each_loose_cb cb_data = {
700-
.obj_type = STRBUF_INIT,
701693
.progress = progress,
702694
};
703695

@@ -712,7 +704,6 @@ static void fsck_object_dir(const char *path)
712704
&cb_data);
713705
display_progress(progress, 256);
714706
stop_progress(&progress);
715-
strbuf_release(&cb_data.obj_type);
716707
}
717708

718709
static int fsck_head_link(const char *head_ref_name,

object-file.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1662,6 +1662,12 @@ int read_loose_object(const char *path,
16621662
goto out_inflate;
16631663
}
16641664

1665+
if (*oi->typep < 0) {
1666+
error(_("unable to parse type from header '%s' of %s"),
1667+
hdr, path);
1668+
goto out_inflate;
1669+
}
1670+
16651671
if (*oi->typep == OBJ_BLOB &&
16661672
*size > repo_settings_get_big_file_threshold(the_repository)) {
16671673
if (check_stream_oid(&stream, hdr, *size, path, expected_oid) < 0)
@@ -1672,9 +1678,9 @@ int read_loose_object(const char *path,
16721678
error(_("unable to unpack contents of %s"), path);
16731679
goto out_inflate;
16741680
}
1675-
hash_object_file_literally(the_repository->hash_algo,
1676-
*contents, *size,
1677-
oi->type_name->buf, real_oid);
1681+
hash_object_file(the_repository->hash_algo,
1682+
*contents, *size,
1683+
*oi->typep, real_oid);
16781684
if (!oideq(expected_oid, real_oid))
16791685
goto out_inflate;
16801686
}

t/t1450-fsck.sh

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -71,30 +71,6 @@ test_expect_success 'object with hash mismatch' '
7171
)
7272
'
7373

74-
test_expect_success 'object with hash and type mismatch' '
75-
git init --bare hash-type-mismatch &&
76-
(
77-
cd hash-type-mismatch &&
78-
79-
oid=$(echo blob | git hash-object -w --stdin -t garbage --literally) &&
80-
oldoid=$oid &&
81-
old=$(test_oid_to_path "$oid") &&
82-
new=$(dirname $old)/$(test_oid ff_2) &&
83-
oid="$(dirname $new)$(basename $new)" &&
84-
85-
mv objects/$old objects/$new &&
86-
git update-index --add --cacheinfo 100644 $oid foo &&
87-
tree=$(git write-tree) &&
88-
cmt=$(echo bogus | git commit-tree $tree) &&
89-
git update-ref refs/heads/bogus $cmt &&
90-
91-
92-
test_must_fail git fsck 2>out &&
93-
grep "^error: $oldoid: hash-path mismatch, found at: .*$new" out &&
94-
grep "^error: $oldoid: object is of unknown type '"'"'garbage'"'"'" out
95-
)
96-
'
97-
9874
test_expect_success 'zlib corrupt loose object output ' '
9975
git init --bare corrupt-loose-output &&
10076
(
@@ -1001,8 +977,9 @@ test_expect_success 'fsck error and recovery on invalid object type' '
1001977
1002978
test_must_fail git fsck 2>err &&
1003979
grep -e "^error" -e "^fatal" err >errors &&
1004-
test_line_count = 1 errors &&
1005-
grep "$garbage_blob: object is of unknown type '"'"'garbage'"'"':" err
980+
test_line_count = 2 errors &&
981+
test_grep "unable to parse type from header .garbage" err &&
982+
test_grep "$garbage_blob: object corrupt or missing:" err
1006983
)
1007984
'
1008985

0 commit comments

Comments
 (0)