If there is nothing wrong when parsing the raw file "packed-refs", we could then iterate the "entries" to check the object consistency. There are two kinds of ref entry: one is the normal and another is peeled. For both situations, we need to use "parse_object" function to parse the object id to get the object. If the object does not exist, we will report an error to the user. Create a new function "packed_fsck_ref_oid" to do above then update the unit test to exercise the code. Mentored-by: Patrick Steinhardt <ps@xxxxxx> Mentored-by: Karthik Nayak <karthik.188@xxxxxxxxx> Signed-off-by: shejialuo <shejialuo@xxxxxxxxx> --- refs/packed-backend.c | 50 +++++++++++++++++++++++++++++++++++++++- t/t0602-reffiles-fsck.sh | 35 ++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/refs/packed-backend.c b/refs/packed-backend.c index 7386e6bfce..d83ce2838f 100644 --- a/refs/packed-backend.c +++ b/refs/packed-backend.c @@ -13,6 +13,7 @@ #include "../iterator.h" #include "../lockfile.h" #include "../chdir-notify.h" +#include "../packfile.h" #include "../statinfo.h" #include "../worktree.h" #include "../wrapper.h" @@ -1933,6 +1934,52 @@ static int packed_fsck_ref_main_line(struct fsck_options *o, return ret; } +static int packed_fsck_ref_oid(struct fsck_options *o, struct ref_store *ref_store, + struct fsck_packed_ref_entry **entries, int nr) +{ + struct strbuf packed_entry = STRBUF_INIT; + struct fsck_ref_report report = { 0 }; + struct object *obj; + int ret = 0; + + for (int i = 0; i < nr; i++) { + struct fsck_packed_ref_entry *entry = entries[i]; + + strbuf_release(&packed_entry); + strbuf_addf(&packed_entry, "packed-refs line %d", entry->line_number); + report.path = packed_entry.buf; + + if (is_promisor_object(ref_store->repo, &entry->oid)) + continue; + + obj = parse_object(ref_store->repo, &entry->oid); + if (!obj) { + ret |= fsck_report_ref(o, &report, + FSCK_MSG_BAD_PACKED_REF_ENTRY, + "'%s' is not a valid object", + oid_to_hex(&entry->oid)); + } + if (entry->has_peeled) { + strbuf_reset(&packed_entry); + strbuf_addf(&packed_entry, "packed-refs line %d", + entry->line_number + 1); + report.path = packed_entry.buf; + + obj = parse_object(ref_store->repo, &entry->peeled); + if (!obj) { + ret |= fsck_report_ref(o, &report, + FSCK_MSG_BAD_PACKED_REF_ENTRY, + "'%s' is not a valid object", + oid_to_hex(&entry->peeled)); + } + } + + } + + strbuf_release(&packed_entry); + return ret; +} + static int packed_fsck_ref_content(struct fsck_options *o, struct ref_store *ref_store, const char *start, const char *eof) @@ -1986,7 +2033,8 @@ static int packed_fsck_ref_content(struct fsck_options *o, */ if (ret) o->safe_object_check = 0; - + else + ret |= packed_fsck_ref_oid(o, ref_store, entries, entry_nr); free_fsck_packed_ref_entries(entries, entry_nr); return ret; diff --git a/t/t0602-reffiles-fsck.sh b/t/t0602-reffiles-fsck.sh index 7e8b329425..faa7c80356 100755 --- a/t/t0602-reffiles-fsck.sh +++ b/t/t0602-reffiles-fsck.sh @@ -730,4 +730,39 @@ test_expect_success 'packed-refs content should be checked' ' test_cmp expect err ' +test_expect_success 'packed-refs objects should be checked' ' + test_when_finished "rm -rf repo" && + git init repo && + cd repo && + test_commit default && + git tag -a annotated-tag-1 -m tag-1 && + + tag_1_oid=$(git rev-parse annotated-tag-1) && + + for non_existing_oid in "$(test_oid 001)" "$(test_oid 002)" + do + printf "# pack-refs with: peeled fully-peeled sorted \n" >.git/packed-refs && + printf "%s refs/heads/foo\n" "$non_existing_oid" >>.git/packed-refs && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: packed-refs line 2: badPackedRefEntry: '\''$non_existing_oid'\'' is not a valid object + EOF + rm .git/packed-refs && + test_cmp expect err || return 1 + done && + + for non_existing_oid in "$(test_oid 001)" "$(test_oid 002)" + do + printf "# pack-refs with: peeled fully-peeled sorted \n" >.git/packed-refs && + printf "%s refs/tags/foo\n" "$tag_1_oid" >>.git/packed-refs && + printf "^$non_existing_oid\n" >>.git/packed-refs && + test_must_fail git refs verify 2>err && + cat >expect <<-EOF && + error: packed-refs line 3: badPackedRefEntry: '\''$non_existing_oid'\'' is not a valid object + EOF + rm .git/packed-refs && + test_cmp expect err || return 1 + done +' + test_done -- 2.47.1