Skip to content

Commit 8173c11

Browse files
shejialuogitster
authored andcommitted
ref: port git-fsck(1) regular refs check for files backend
We implicitly rely on "git-fsck(1)" to check the consistency of regular refs. However, we have already set up the infrastructure of the ref consistency checks. We need to port original checks from "git-fsck(1)". Thus, we could clean the "git-fsck(1)" code by removing these implicit checks. The "git-fsck(1)" command reports an error when the ref content is invalid. Following this, add a similar check to "git refs verify". Add a new fsck error message called "badRefContent(ERROR)" to represent that a ref has an invalid content. Mentored-by: Patrick Steinhardt <[email protected]> Mentored-by: Karthik Nayak <[email protected]> Signed-off-by: shejialuo <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent bd8d4dc commit 8173c11

File tree

4 files changed

+107
-0
lines changed

4 files changed

+107
-0
lines changed

Documentation/fsck-msgids.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
`badParentSha1`::
2020
(ERROR) A commit object has a bad parent sha1.
2121

22+
`badRefContent`::
23+
(ERROR) A ref has bad content.
24+
2225
`badRefFiletype`::
2326
(ERROR) A ref has a bad file type.
2427

fsck.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ enum fsck_msg_type {
3131
FUNC(BAD_NAME, ERROR) \
3232
FUNC(BAD_OBJECT_SHA1, ERROR) \
3333
FUNC(BAD_PARENT_SHA1, ERROR) \
34+
FUNC(BAD_REF_CONTENT, ERROR) \
3435
FUNC(BAD_REF_FILETYPE, ERROR) \
3536
FUNC(BAD_REF_NAME, ERROR) \
3637
FUNC(BAD_TIMEZONE, ERROR) \

refs/files-backend.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3430,6 +3430,48 @@ typedef int (*files_fsck_refs_fn)(struct ref_store *ref_store,
34303430
const char *refs_check_dir,
34313431
struct dir_iterator *iter);
34323432

3433+
static int files_fsck_refs_content(struct ref_store *ref_store,
3434+
struct fsck_options *o,
3435+
const char *refs_check_dir,
3436+
struct dir_iterator *iter)
3437+
{
3438+
struct strbuf ref_content = STRBUF_INIT;
3439+
struct strbuf referent = STRBUF_INIT;
3440+
struct strbuf refname = STRBUF_INIT;
3441+
struct fsck_ref_report report = {0};
3442+
unsigned int type = 0;
3443+
int failure_errno = 0;
3444+
struct object_id oid;
3445+
int ret = 0;
3446+
3447+
strbuf_addf(&refname, "%s/%s", refs_check_dir, iter->relative_path);
3448+
report.path = refname.buf;
3449+
3450+
if (S_ISLNK(iter->st.st_mode))
3451+
goto cleanup;
3452+
3453+
if (strbuf_read_file(&ref_content, iter->path.buf, 0) < 0) {
3454+
ret = error_errno(_("unable to read ref '%s/%s'"),
3455+
refs_check_dir, iter->relative_path);
3456+
goto cleanup;
3457+
}
3458+
3459+
if (parse_loose_ref_contents(ref_store->repo->hash_algo,
3460+
ref_content.buf, &oid, &referent,
3461+
&type, &failure_errno)) {
3462+
ret = fsck_report_ref(o, &report,
3463+
FSCK_MSG_BAD_REF_CONTENT,
3464+
"invalid ref content");
3465+
goto cleanup;
3466+
}
3467+
3468+
cleanup:
3469+
strbuf_release(&refname);
3470+
strbuf_release(&ref_content);
3471+
strbuf_release(&referent);
3472+
return ret;
3473+
}
3474+
34333475
static int files_fsck_refs_name(struct ref_store *ref_store UNUSED,
34343476
struct fsck_options *o,
34353477
const char *refs_check_dir,
@@ -3512,6 +3554,7 @@ static int files_fsck_refs(struct ref_store *ref_store,
35123554
{
35133555
files_fsck_refs_fn fsck_refs_fn[]= {
35143556
files_fsck_refs_name,
3557+
files_fsck_refs_content,
35153558
NULL,
35163559
};
35173560

t/t0602-reffiles-fsck.sh

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,64 @@ test_expect_success 'ref name check should be adapted into fsck messages' '
8989
test_must_be_empty err
9090
'
9191

92+
test_expect_success 'regular ref content should be checked (individual)' '
93+
test_when_finished "rm -rf repo" &&
94+
git init repo &&
95+
branch_dir_prefix=.git/refs/heads &&
96+
tag_dir_prefix=.git/refs/tags &&
97+
cd repo &&
98+
test_commit default &&
99+
mkdir -p "$branch_dir_prefix/a/b" &&
100+
101+
git refs verify 2>err &&
102+
test_must_be_empty err &&
103+
104+
printf "%sx" "$(git rev-parse main)" >$tag_dir_prefix/tag-bad-1 &&
105+
test_must_fail git refs verify 2>err &&
106+
cat >expect <<-EOF &&
107+
error: refs/tags/tag-bad-1: badRefContent: invalid ref content
108+
EOF
109+
rm $tag_dir_prefix/tag-bad-1 &&
110+
test_cmp expect err &&
111+
112+
printf "xfsazqfxcadas" >$tag_dir_prefix/tag-bad-2 &&
113+
test_must_fail git refs verify 2>err &&
114+
cat >expect <<-EOF &&
115+
error: refs/tags/tag-bad-2: badRefContent: invalid ref content
116+
EOF
117+
rm $tag_dir_prefix/tag-bad-2 &&
118+
test_cmp expect err &&
119+
120+
printf "xfsazqfxcadas" >$branch_dir_prefix/a/b/branch-bad &&
121+
test_must_fail git refs verify 2>err &&
122+
cat >expect <<-EOF &&
123+
error: refs/heads/a/b/branch-bad: badRefContent: invalid ref content
124+
EOF
125+
rm $branch_dir_prefix/a/b/branch-bad &&
126+
test_cmp expect err
127+
'
128+
129+
test_expect_success 'regular ref content should be checked (aggregate)' '
130+
test_when_finished "rm -rf repo" &&
131+
git init repo &&
132+
branch_dir_prefix=.git/refs/heads &&
133+
tag_dir_prefix=.git/refs/tags &&
134+
cd repo &&
135+
test_commit default &&
136+
mkdir -p "$branch_dir_prefix/a/b" &&
137+
138+
printf "%sx" "$(git rev-parse main)" >$tag_dir_prefix/tag-bad-1 &&
139+
printf "xfsazqfxcadas" >$tag_dir_prefix/tag-bad-2 &&
140+
printf "xfsazqfxcadas" >$branch_dir_prefix/a/b/branch-bad &&
141+
142+
test_must_fail git refs verify 2>err &&
143+
cat >expect <<-EOF &&
144+
error: refs/heads/a/b/branch-bad: badRefContent: invalid ref content
145+
error: refs/tags/tag-bad-1: badRefContent: invalid ref content
146+
error: refs/tags/tag-bad-2: badRefContent: invalid ref content
147+
EOF
148+
sort err >sorted_err &&
149+
test_cmp expect sorted_err
150+
'
151+
92152
test_done

0 commit comments

Comments
 (0)