mirror of
https://github.com/git/git.git
synced 2026-01-10 01:56:42 +00:00
"git-fsck(1)" implicitly checks the ref content by passing the callback "fsck_handle_ref" to the "refs.c::refs_for_each_rawref". Then, it will check whether the ref content (eventually "oid") is valid. If not, it will report the following error to the user. error: refs/heads/main: invalid sha1 pointer 0000... And it will also report above errors when there are dangling symrefs in the repository wrongly. This does not align with the behavior of the "git symbolic-ref" command which allows users to create dangling symrefs. As we have already introduced the "git refs verify" command, we'd better check the ref content explicitly in the "git refs verify" command thus later we could remove these checks in "git-fsck(1)" and launch a subprocess to call "git refs verify" in "git-fsck(1)" to make the "git-fsck(1)" more clean. Following what "git-fsck(1)" does, add a similar check to "git refs verify". Then add a new fsck error message "badRefContent(ERROR)" to represent that a ref has an invalid content. Mentored-by: Patrick Steinhardt <ps@pks.im> Mentored-by: Karthik Nayak <karthik.188@gmail.com> Signed-off-by: shejialuo <shejialuo@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
267 lines
8.1 KiB
Bash
Executable File
267 lines
8.1 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
test_description='Test reffiles backend consistency check'
|
|
|
|
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
|
|
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
|
GIT_TEST_DEFAULT_REF_FORMAT=files
|
|
export GIT_TEST_DEFAULT_REF_FORMAT
|
|
TEST_PASSES_SANITIZE_LEAK=true
|
|
|
|
. ./test-lib.sh
|
|
|
|
test_expect_success 'ref name should be checked' '
|
|
test_when_finished "rm -rf repo" &&
|
|
git init repo &&
|
|
branch_dir_prefix=.git/refs/heads &&
|
|
tag_dir_prefix=.git/refs/tags &&
|
|
cd repo &&
|
|
|
|
git commit --allow-empty -m initial &&
|
|
git checkout -b default-branch &&
|
|
git tag default-tag &&
|
|
git tag multi_hierarchy/default-tag &&
|
|
|
|
cp $branch_dir_prefix/default-branch $branch_dir_prefix/@ &&
|
|
git refs verify 2>err &&
|
|
test_must_be_empty err &&
|
|
rm $branch_dir_prefix/@ &&
|
|
|
|
cp $tag_dir_prefix/default-tag $tag_dir_prefix/tag-1.lock &&
|
|
git refs verify 2>err &&
|
|
rm $tag_dir_prefix/tag-1.lock &&
|
|
test_must_be_empty err &&
|
|
|
|
cp $tag_dir_prefix/default-tag $tag_dir_prefix/.lock &&
|
|
test_must_fail git refs verify 2>err &&
|
|
cat >expect <<-EOF &&
|
|
error: refs/tags/.lock: badRefName: invalid refname format
|
|
EOF
|
|
rm $tag_dir_prefix/.lock &&
|
|
test_cmp expect err &&
|
|
|
|
for refname in ".refname-starts-with-dot" "~refname-has-stride"
|
|
do
|
|
cp $branch_dir_prefix/default-branch "$branch_dir_prefix/$refname" &&
|
|
test_must_fail git refs verify 2>err &&
|
|
cat >expect <<-EOF &&
|
|
error: refs/heads/$refname: badRefName: invalid refname format
|
|
EOF
|
|
rm "$branch_dir_prefix/$refname" &&
|
|
test_cmp expect err || return 1
|
|
done &&
|
|
|
|
for refname in ".refname-starts-with-dot" "~refname-has-stride"
|
|
do
|
|
cp $tag_dir_prefix/default-tag "$tag_dir_prefix/$refname" &&
|
|
test_must_fail git refs verify 2>err &&
|
|
cat >expect <<-EOF &&
|
|
error: refs/tags/$refname: badRefName: invalid refname format
|
|
EOF
|
|
rm "$tag_dir_prefix/$refname" &&
|
|
test_cmp expect err || return 1
|
|
done &&
|
|
|
|
for refname in ".refname-starts-with-dot" "~refname-has-stride"
|
|
do
|
|
cp $tag_dir_prefix/multi_hierarchy/default-tag "$tag_dir_prefix/multi_hierarchy/$refname" &&
|
|
test_must_fail git refs verify 2>err &&
|
|
cat >expect <<-EOF &&
|
|
error: refs/tags/multi_hierarchy/$refname: badRefName: invalid refname format
|
|
EOF
|
|
rm "$tag_dir_prefix/multi_hierarchy/$refname" &&
|
|
test_cmp expect err || return 1
|
|
done &&
|
|
|
|
for refname in ".refname-starts-with-dot" "~refname-has-stride"
|
|
do
|
|
mkdir "$branch_dir_prefix/$refname" &&
|
|
cp $branch_dir_prefix/default-branch "$branch_dir_prefix/$refname/default-branch" &&
|
|
test_must_fail git refs verify 2>err &&
|
|
cat >expect <<-EOF &&
|
|
error: refs/heads/$refname/default-branch: badRefName: invalid refname format
|
|
EOF
|
|
rm -r "$branch_dir_prefix/$refname" &&
|
|
test_cmp expect err || return 1
|
|
done
|
|
'
|
|
|
|
test_expect_success 'ref name check should be adapted into fsck messages' '
|
|
test_when_finished "rm -rf repo" &&
|
|
git init repo &&
|
|
branch_dir_prefix=.git/refs/heads &&
|
|
cd repo &&
|
|
git commit --allow-empty -m initial &&
|
|
git checkout -b branch-1 &&
|
|
|
|
cp $branch_dir_prefix/branch-1 $branch_dir_prefix/.branch-1 &&
|
|
git -c fsck.badRefName=warn refs verify 2>err &&
|
|
cat >expect <<-EOF &&
|
|
warning: refs/heads/.branch-1: badRefName: invalid refname format
|
|
EOF
|
|
rm $branch_dir_prefix/.branch-1 &&
|
|
test_cmp expect err &&
|
|
|
|
cp $branch_dir_prefix/branch-1 $branch_dir_prefix/.branch-1 &&
|
|
git -c fsck.badRefName=ignore refs verify 2>err &&
|
|
test_must_be_empty err
|
|
'
|
|
|
|
test_expect_success 'ref name check should work for multiple worktrees' '
|
|
test_when_finished "rm -rf repo" &&
|
|
git init repo &&
|
|
|
|
cd repo &&
|
|
test_commit initial &&
|
|
git checkout -b branch-1 &&
|
|
test_commit second &&
|
|
git checkout -b branch-2 &&
|
|
test_commit third &&
|
|
git checkout -b branch-3 &&
|
|
git worktree add ./worktree-1 branch-1 &&
|
|
git worktree add ./worktree-2 branch-2 &&
|
|
worktree1_refdir_prefix=.git/worktrees/worktree-1/refs/worktree &&
|
|
worktree2_refdir_prefix=.git/worktrees/worktree-2/refs/worktree &&
|
|
|
|
(
|
|
cd worktree-1 &&
|
|
git update-ref refs/worktree/branch-4 refs/heads/branch-3
|
|
) &&
|
|
(
|
|
cd worktree-2 &&
|
|
git update-ref refs/worktree/branch-4 refs/heads/branch-3
|
|
) &&
|
|
|
|
cp $worktree1_refdir_prefix/branch-4 $worktree1_refdir_prefix/'\'' branch-5'\'' &&
|
|
cp $worktree2_refdir_prefix/branch-4 $worktree2_refdir_prefix/'\''~branch-6'\'' &&
|
|
|
|
test_must_fail git refs verify 2>err &&
|
|
cat >expect <<-EOF &&
|
|
error: worktrees/worktree-1/refs/worktree/ branch-5: badRefName: invalid refname format
|
|
error: worktrees/worktree-2/refs/worktree/~branch-6: badRefName: invalid refname format
|
|
EOF
|
|
sort err >sorted_err &&
|
|
test_cmp expect sorted_err &&
|
|
|
|
for worktree in "worktree-1" "worktree-2"
|
|
do
|
|
(
|
|
cd $worktree &&
|
|
test_must_fail git refs verify 2>err &&
|
|
cat >expect <<-EOF &&
|
|
error: worktrees/worktree-1/refs/worktree/ branch-5: badRefName: invalid refname format
|
|
error: worktrees/worktree-2/refs/worktree/~branch-6: badRefName: invalid refname format
|
|
EOF
|
|
sort err >sorted_err &&
|
|
test_cmp expect sorted_err || return 1
|
|
)
|
|
done
|
|
'
|
|
|
|
test_expect_success 'regular ref content should be checked (individual)' '
|
|
test_when_finished "rm -rf repo" &&
|
|
git init repo &&
|
|
branch_dir_prefix=.git/refs/heads &&
|
|
cd repo &&
|
|
test_commit default &&
|
|
mkdir -p "$branch_dir_prefix/a/b" &&
|
|
|
|
git refs verify 2>err &&
|
|
test_must_be_empty err &&
|
|
|
|
for bad_content in "$(git rev-parse main)x" "xfsazqfxcadas" "Xfsazqfxcadas"
|
|
do
|
|
printf "%s" $bad_content >$branch_dir_prefix/branch-bad &&
|
|
test_must_fail git refs verify 2>err &&
|
|
cat >expect <<-EOF &&
|
|
error: refs/heads/branch-bad: badRefContent: $bad_content
|
|
EOF
|
|
rm $branch_dir_prefix/branch-bad &&
|
|
test_cmp expect err || return 1
|
|
done &&
|
|
|
|
for bad_content in "$(git rev-parse main)x" "xfsazqfxcadas" "Xfsazqfxcadas"
|
|
do
|
|
printf "%s" $bad_content >$branch_dir_prefix/a/b/branch-bad &&
|
|
test_must_fail git refs verify 2>err &&
|
|
cat >expect <<-EOF &&
|
|
error: refs/heads/a/b/branch-bad: badRefContent: $bad_content
|
|
EOF
|
|
rm $branch_dir_prefix/a/b/branch-bad &&
|
|
test_cmp expect err || return 1
|
|
done
|
|
'
|
|
|
|
test_expect_success 'regular ref content should be checked (aggregate)' '
|
|
test_when_finished "rm -rf repo" &&
|
|
git init repo &&
|
|
branch_dir_prefix=.git/refs/heads &&
|
|
tag_dir_prefix=.git/refs/tags &&
|
|
cd repo &&
|
|
test_commit default &&
|
|
mkdir -p "$branch_dir_prefix/a/b" &&
|
|
|
|
bad_content_1=$(git rev-parse main)x &&
|
|
bad_content_2=xfsazqfxcadas &&
|
|
bad_content_3=Xfsazqfxcadas &&
|
|
printf "%s" $bad_content_1 >$tag_dir_prefix/tag-bad-1 &&
|
|
printf "%s" $bad_content_2 >$tag_dir_prefix/tag-bad-2 &&
|
|
printf "%s" $bad_content_3 >$branch_dir_prefix/a/b/branch-bad &&
|
|
|
|
test_must_fail git refs verify 2>err &&
|
|
cat >expect <<-EOF &&
|
|
error: refs/heads/a/b/branch-bad: badRefContent: $bad_content_3
|
|
error: refs/tags/tag-bad-1: badRefContent: $bad_content_1
|
|
error: refs/tags/tag-bad-2: badRefContent: $bad_content_2
|
|
EOF
|
|
sort err >sorted_err &&
|
|
test_cmp expect sorted_err
|
|
'
|
|
|
|
test_expect_success 'ref content checks should work with worktrees' '
|
|
test_when_finished "rm -rf repo" &&
|
|
git init repo &&
|
|
cd repo &&
|
|
test_commit default &&
|
|
git branch branch-1 &&
|
|
git branch branch-2 &&
|
|
git branch branch-3 &&
|
|
git worktree add ./worktree-1 branch-2 &&
|
|
git worktree add ./worktree-2 branch-3 &&
|
|
worktree1_refdir_prefix=.git/worktrees/worktree-1/refs/worktree &&
|
|
worktree2_refdir_prefix=.git/worktrees/worktree-2/refs/worktree &&
|
|
|
|
(
|
|
cd worktree-1 &&
|
|
git update-ref refs/worktree/branch-4 refs/heads/branch-1
|
|
) &&
|
|
(
|
|
cd worktree-2 &&
|
|
git update-ref refs/worktree/branch-4 refs/heads/branch-1
|
|
) &&
|
|
|
|
for bad_content in "$(git rev-parse HEAD)x" "xfsazqfxcadas" "Xfsazqfxcadas"
|
|
do
|
|
printf "%s" $bad_content >$worktree1_refdir_prefix/bad-branch-1 &&
|
|
test_must_fail git refs verify 2>err &&
|
|
cat >expect <<-EOF &&
|
|
error: worktrees/worktree-1/refs/worktree/bad-branch-1: badRefContent: $bad_content
|
|
EOF
|
|
rm $worktree1_refdir_prefix/bad-branch-1 &&
|
|
test_cmp expect err || return 1
|
|
done &&
|
|
|
|
for bad_content in "$(git rev-parse HEAD)x" "xfsazqfxcadas" "Xfsazqfxcadas"
|
|
do
|
|
printf "%s" $bad_content >$worktree2_refdir_prefix/bad-branch-2 &&
|
|
test_must_fail git refs verify 2>err &&
|
|
cat >expect <<-EOF &&
|
|
error: worktrees/worktree-2/refs/worktree/bad-branch-2: badRefContent: $bad_content
|
|
EOF
|
|
rm $worktree2_refdir_prefix/bad-branch-2 &&
|
|
test_cmp expect err || return 1
|
|
done
|
|
'
|
|
|
|
test_done
|