@@ -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;
@@ -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
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@pks.im> Mentored-by: Karthik Nayak <karthik.188@gmail.com> Signed-off-by: shejialuo <shejialuo@gmail.com> --- refs/packed-backend.c | 50 +++++++++++++++++++++++++++++++++++++++- t/t0602-reffiles-fsck.sh | 35 ++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-)