Files
git-mirror/t/t0602-reffiles-fsck.sh
shejialuo c1cf918d3a builtin/fsck: add git refs verify child process
At now, we have already implemented the ref consistency checks for both
"files-backend" and "packed-backend". Although we would check some
redundant things, it won't cause trouble. So, let's integrate it into
the "git-fsck(1)" command to get feedback from the users. And also by
calling "git refs verify" in "git-fsck(1)", we make sure that the new
added checks don't break.

Introduce a new function "fsck_refs" that initializes and runs a child
process to execute the "git refs verify" command. In order to provide
the user interface create a progress which makes the total task be 1.
It's hard to know how many loose refs we will check now. We might
improve this later.

Then, introduce the option to allow the user to disable checking ref
database consistency. Put this function in the very first execution
sequence of "git-fsck(1)" due to that we don't want the existing code of
"git-fsck(1)" which would implicitly check the consistency of refs to
die the program.

Last, update the 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>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-02-27 14:03:10 -08:00

873 lines
29 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-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 &&
printf "%s" "$(git rev-parse main)" >$branch_dir_prefix/branch-no-newline &&
git refs verify 2>err &&
cat >expect <<-EOF &&
warning: refs/heads/branch-no-newline: refMissingNewline: misses LF at the end
EOF
rm $branch_dir_prefix/branch-no-newline &&
test_cmp expect err &&
for trailing_content in " garbage" " more garbage"
do
printf "%s" "$(git rev-parse main)$trailing_content" >$branch_dir_prefix/branch-garbage &&
git refs verify 2>err &&
cat >expect <<-EOF &&
warning: refs/heads/branch-garbage: trailingRefContent: has trailing garbage: '\''$trailing_content'\''
EOF
rm $branch_dir_prefix/branch-garbage &&
test_cmp expect err || return 1
done &&
printf "%s\n\n\n" "$(git rev-parse main)" >$branch_dir_prefix/branch-garbage-special &&
git refs verify 2>err &&
cat >expect <<-EOF &&
warning: refs/heads/branch-garbage-special: trailingRefContent: has trailing garbage: '\''
'\''
EOF
rm $branch_dir_prefix/branch-garbage-special &&
test_cmp expect err &&
printf "%s\n\n\n garbage" "$(git rev-parse main)" >$branch_dir_prefix/branch-garbage-special &&
git refs verify 2>err &&
cat >expect <<-EOF &&
warning: refs/heads/branch-garbage-special: trailingRefContent: has trailing garbage: '\''
garbage'\''
EOF
rm $branch_dir_prefix/branch-garbage-special &&
test_cmp expect err
)
'
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 &&
printf "%s" "$(git rev-parse main)" >$branch_dir_prefix/branch-no-newline &&
printf "%s garbage" "$(git rev-parse main)" >$branch_dir_prefix/branch-garbage &&
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
warning: refs/heads/branch-garbage: trailingRefContent: has trailing garbage: '\'' garbage'\''
warning: refs/heads/branch-no-newline: refMissingNewline: misses LF at the end
EOF
sort err >sorted_err &&
test_cmp expect sorted_err
)
'
test_expect_success 'textual symref 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" &&
for good_referent in "refs/heads/branch" "HEAD"
do
printf "ref: %s\n" $good_referent >$branch_dir_prefix/branch-good &&
git refs verify 2>err &&
rm $branch_dir_prefix/branch-good &&
test_must_be_empty err || return 1
done &&
for bad_referent in "refs/heads/.branch" "refs/heads/~branch" "refs/heads/?branch"
do
printf "ref: %s\n" $bad_referent >$branch_dir_prefix/branch-bad &&
test_must_fail git refs verify 2>err &&
cat >expect <<-EOF &&
error: refs/heads/branch-bad: badReferentName: points to invalid refname '\''$bad_referent'\''
EOF
rm $branch_dir_prefix/branch-bad &&
test_cmp expect err || return 1
done &&
printf "ref: refs/heads/branch" >$branch_dir_prefix/branch-no-newline &&
git refs verify 2>err &&
cat >expect <<-EOF &&
warning: refs/heads/branch-no-newline: refMissingNewline: misses LF at the end
EOF
rm $branch_dir_prefix/branch-no-newline &&
test_cmp expect err &&
printf "ref: refs/heads/branch " >$branch_dir_prefix/a/b/branch-trailing-1 &&
git refs verify 2>err &&
cat >expect <<-EOF &&
warning: refs/heads/a/b/branch-trailing-1: refMissingNewline: misses LF at the end
warning: refs/heads/a/b/branch-trailing-1: trailingRefContent: has trailing whitespaces or newlines
EOF
rm $branch_dir_prefix/a/b/branch-trailing-1 &&
test_cmp expect err &&
printf "ref: refs/heads/branch\n\n" >$branch_dir_prefix/a/b/branch-trailing-2 &&
git refs verify 2>err &&
cat >expect <<-EOF &&
warning: refs/heads/a/b/branch-trailing-2: trailingRefContent: has trailing whitespaces or newlines
EOF
rm $branch_dir_prefix/a/b/branch-trailing-2 &&
test_cmp expect err &&
printf "ref: refs/heads/branch \n" >$branch_dir_prefix/a/b/branch-trailing-3 &&
git refs verify 2>err &&
cat >expect <<-EOF &&
warning: refs/heads/a/b/branch-trailing-3: trailingRefContent: has trailing whitespaces or newlines
EOF
rm $branch_dir_prefix/a/b/branch-trailing-3 &&
test_cmp expect err &&
printf "ref: refs/heads/branch \n " >$branch_dir_prefix/a/b/branch-complicated &&
git refs verify 2>err &&
cat >expect <<-EOF &&
warning: refs/heads/a/b/branch-complicated: refMissingNewline: misses LF at the end
warning: refs/heads/a/b/branch-complicated: trailingRefContent: has trailing whitespaces or newlines
EOF
rm $branch_dir_prefix/a/b/branch-complicated &&
test_cmp expect err
)
'
test_expect_success 'textual symref 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" &&
printf "ref: refs/heads/branch\n" >$branch_dir_prefix/branch-good &&
printf "ref: HEAD\n" >$branch_dir_prefix/branch-head &&
printf "ref: refs/heads/branch" >$branch_dir_prefix/branch-no-newline-1 &&
printf "ref: refs/heads/branch " >$branch_dir_prefix/a/b/branch-trailing-1 &&
printf "ref: refs/heads/branch\n\n" >$branch_dir_prefix/a/b/branch-trailing-2 &&
printf "ref: refs/heads/branch \n" >$branch_dir_prefix/a/b/branch-trailing-3 &&
printf "ref: refs/heads/branch \n " >$branch_dir_prefix/a/b/branch-complicated &&
printf "ref: refs/heads/.branch\n" >$branch_dir_prefix/branch-bad-1 &&
test_must_fail git refs verify 2>err &&
cat >expect <<-EOF &&
error: refs/heads/branch-bad-1: badReferentName: points to invalid refname '\''refs/heads/.branch'\''
warning: refs/heads/a/b/branch-complicated: refMissingNewline: misses LF at the end
warning: refs/heads/a/b/branch-complicated: trailingRefContent: has trailing whitespaces or newlines
warning: refs/heads/a/b/branch-trailing-1: refMissingNewline: misses LF at the end
warning: refs/heads/a/b/branch-trailing-1: trailingRefContent: has trailing whitespaces or newlines
warning: refs/heads/a/b/branch-trailing-2: trailingRefContent: has trailing whitespaces or newlines
warning: refs/heads/a/b/branch-trailing-3: trailingRefContent: has trailing whitespaces or newlines
warning: refs/heads/branch-no-newline-1: refMissingNewline: misses LF at the end
EOF
sort err >sorted_err &&
test_cmp expect sorted_err
)
'
test_expect_success 'the target of the textual symref 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 &&
test_commit default &&
mkdir -p "$branch_dir_prefix/a/b" &&
for good_referent in "refs/heads/branch" "HEAD" "refs/tags/tag"
do
printf "ref: %s\n" $good_referent >$branch_dir_prefix/branch-good &&
git refs verify 2>err &&
rm $branch_dir_prefix/branch-good &&
test_must_be_empty err || return 1
done &&
for nonref_referent in "refs-back/heads/branch" "refs-back/tags/tag" "reflogs/refs/heads/branch"
do
printf "ref: %s\n" $nonref_referent >$branch_dir_prefix/branch-bad-1 &&
git refs verify 2>err &&
cat >expect <<-EOF &&
warning: refs/heads/branch-bad-1: symrefTargetIsNotARef: points to non-ref target '\''$nonref_referent'\''
EOF
rm $branch_dir_prefix/branch-bad-1 &&
test_cmp expect err || return 1
done
)
'
test_expect_success SYMLINKS 'symlink symref content 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 &&
test_commit default &&
mkdir -p "$branch_dir_prefix/a/b" &&
ln -sf ./main $branch_dir_prefix/branch-symbolic-good &&
git refs verify 2>err &&
cat >expect <<-EOF &&
warning: refs/heads/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref
EOF
rm $branch_dir_prefix/branch-symbolic-good &&
test_cmp expect err &&
ln -sf ../../logs/branch-escape $branch_dir_prefix/branch-symbolic &&
git refs verify 2>err &&
cat >expect <<-EOF &&
warning: refs/heads/branch-symbolic: symlinkRef: use deprecated symbolic link for symref
warning: refs/heads/branch-symbolic: symrefTargetIsNotARef: points to non-ref target '\''logs/branch-escape'\''
EOF
rm $branch_dir_prefix/branch-symbolic &&
test_cmp expect err &&
ln -sf ./"branch " $branch_dir_prefix/branch-symbolic-bad &&
test_must_fail git refs verify 2>err &&
cat >expect <<-EOF &&
warning: refs/heads/branch-symbolic-bad: symlinkRef: use deprecated symbolic link for symref
error: refs/heads/branch-symbolic-bad: badReferentName: points to invalid refname '\''refs/heads/branch '\''
EOF
rm $branch_dir_prefix/branch-symbolic-bad &&
test_cmp expect err &&
ln -sf ./".tag" $tag_dir_prefix/tag-symbolic-1 &&
test_must_fail git refs verify 2>err &&
cat >expect <<-EOF &&
warning: refs/tags/tag-symbolic-1: symlinkRef: use deprecated symbolic link for symref
error: refs/tags/tag-symbolic-1: badReferentName: points to invalid refname '\''refs/tags/.tag'\''
EOF
rm $tag_dir_prefix/tag-symbolic-1 &&
test_cmp expect err
)
'
test_expect_success SYMLINKS 'symlink symref content should be checked (worktree)' '
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 &&
main_worktree_refdir_prefix=.git/refs/heads &&
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
) &&
ln -sf ../../../../refs/heads/good-branch $worktree1_refdir_prefix/branch-symbolic-good &&
git refs verify 2>err &&
cat >expect <<-EOF &&
warning: worktrees/worktree-1/refs/worktree/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref
EOF
rm $worktree1_refdir_prefix/branch-symbolic-good &&
test_cmp expect err &&
ln -sf ../../../../worktrees/worktree-1/good-branch $worktree2_refdir_prefix/branch-symbolic-good &&
git refs verify 2>err &&
cat >expect <<-EOF &&
warning: worktrees/worktree-2/refs/worktree/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref
EOF
rm $worktree2_refdir_prefix/branch-symbolic-good &&
test_cmp expect err &&
ln -sf ../../worktrees/worktree-2/good-branch $main_worktree_refdir_prefix/branch-symbolic-good &&
git refs verify 2>err &&
cat >expect <<-EOF &&
warning: refs/heads/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref
EOF
rm $main_worktree_refdir_prefix/branch-symbolic-good &&
test_cmp expect err &&
ln -sf ../../../../logs/branch-escape $worktree1_refdir_prefix/branch-symbolic &&
git refs verify 2>err &&
cat >expect <<-EOF &&
warning: worktrees/worktree-1/refs/worktree/branch-symbolic: symlinkRef: use deprecated symbolic link for symref
warning: worktrees/worktree-1/refs/worktree/branch-symbolic: symrefTargetIsNotARef: points to non-ref target '\''logs/branch-escape'\''
EOF
rm $worktree1_refdir_prefix/branch-symbolic &&
test_cmp expect err &&
for bad_referent_name in ".tag" "branch "
do
ln -sf ./"$bad_referent_name" $worktree1_refdir_prefix/bad-symbolic &&
test_must_fail git refs verify 2>err &&
cat >expect <<-EOF &&
warning: worktrees/worktree-1/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref
error: worktrees/worktree-1/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''worktrees/worktree-1/refs/worktree/$bad_referent_name'\''
EOF
rm $worktree1_refdir_prefix/bad-symbolic &&
test_cmp expect err &&
ln -sf ../../../../refs/heads/"$bad_referent_name" $worktree1_refdir_prefix/bad-symbolic &&
test_must_fail git refs verify 2>err &&
cat >expect <<-EOF &&
warning: worktrees/worktree-1/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref
error: worktrees/worktree-1/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''refs/heads/$bad_referent_name'\''
EOF
rm $worktree1_refdir_prefix/bad-symbolic &&
test_cmp expect err &&
ln -sf ./"$bad_referent_name" $worktree2_refdir_prefix/bad-symbolic &&
test_must_fail git refs verify 2>err &&
cat >expect <<-EOF &&
warning: worktrees/worktree-2/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref
error: worktrees/worktree-2/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''worktrees/worktree-2/refs/worktree/$bad_referent_name'\''
EOF
rm $worktree2_refdir_prefix/bad-symbolic &&
test_cmp expect err &&
ln -sf ../../../../refs/heads/"$bad_referent_name" $worktree2_refdir_prefix/bad-symbolic &&
test_must_fail git refs verify 2>err &&
cat >expect <<-EOF &&
warning: worktrees/worktree-2/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref
error: worktrees/worktree-2/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''refs/heads/$bad_referent_name'\''
EOF
rm $worktree2_refdir_prefix/bad-symbolic &&
test_cmp expect err || return 1
done
)
'
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 &&
printf "%s" "$(git rev-parse HEAD)" >$worktree1_refdir_prefix/branch-no-newline &&
git refs verify 2>err &&
cat >expect <<-EOF &&
warning: worktrees/worktree-1/refs/worktree/branch-no-newline: refMissingNewline: misses LF at the end
EOF
rm $worktree1_refdir_prefix/branch-no-newline &&
test_cmp expect err &&
printf "%s garbage" "$(git rev-parse HEAD)" >$worktree1_refdir_prefix/branch-garbage &&
git refs verify 2>err &&
cat >expect <<-EOF &&
warning: worktrees/worktree-1/refs/worktree/branch-garbage: trailingRefContent: has trailing garbage: '\'' garbage'\''
EOF
rm $worktree1_refdir_prefix/branch-garbage &&
test_cmp expect err
)
'
test_expect_success SYMLINKS 'the filetype of packed-refs should be checked' '
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 pack-refs --all &&
mv .git/packed-refs .git/packed-refs-back &&
ln -sf packed-refs-back .git/packed-refs &&
test_must_fail git refs verify 2>err &&
cat >expect <<-EOF &&
error: packed-refs: badRefFiletype: not a regular file but a symlink
EOF
rm .git/packed-refs &&
test_cmp expect err &&
mkdir .git/packed-refs &&
test_must_fail git refs verify 2>err &&
cat >expect <<-EOF &&
error: packed-refs: badRefFiletype: not a regular file
EOF
rm -r .git/packed-refs &&
test_cmp expect err
)
'
test_expect_success 'packed-refs header should be checked' '
test_when_finished "rm -rf repo" &&
git init repo &&
(
cd repo &&
test_commit default &&
git refs verify 2>err &&
test_must_be_empty err &&
for bad_header in "# pack-refs wit: peeled fully-peeled sorted " \
"# pack-refs with traits: peeled fully-peeled sorted " \
"# pack-refs with a: peeled fully-peeled" \
"# pack-refs with:peeled fully-peeled sorted"
do
printf "%s\n" "$bad_header" >.git/packed-refs &&
test_must_fail git refs verify 2>err &&
cat >expect <<-EOF &&
error: packed-refs.header: badPackedRefHeader: '\''$bad_header'\'' does not start with '\''# pack-refs with: '\''
EOF
rm .git/packed-refs &&
test_cmp expect err || return 1
done
)
'
test_expect_success 'packed-refs missing header should not be reported' '
test_when_finished "rm -rf repo" &&
git init repo &&
(
cd repo &&
test_commit default &&
printf "$(git rev-parse HEAD) refs/heads/main\n" >.git/packed-refs &&
git refs verify 2>err &&
test_must_be_empty err
)
'
test_expect_success 'packed-refs unknown traits should not be reported' '
test_when_finished "rm -rf repo" &&
git init repo &&
(
cd repo &&
test_commit default &&
printf "# pack-refs with: peeled fully-peeled sorted foo\n" >.git/packed-refs &&
git refs verify 2>err &&
test_must_be_empty err
)
'
test_expect_success 'packed-refs content should be checked' '
test_when_finished "rm -rf repo" &&
git init repo &&
(
cd repo &&
test_commit default &&
git branch branch-1 &&
git branch branch-2 &&
git tag -a annotated-tag-1 -m tag-1 &&
git tag -a annotated-tag-2 -m tag-2 &&
branch_1_oid=$(git rev-parse branch-1) &&
branch_2_oid=$(git rev-parse branch-2) &&
tag_1_oid=$(git rev-parse annotated-tag-1) &&
tag_2_oid=$(git rev-parse annotated-tag-2) &&
tag_1_peeled_oid=$(git rev-parse annotated-tag-1^{}) &&
tag_2_peeled_oid=$(git rev-parse annotated-tag-2^{}) &&
short_oid=$(printf "%s" $tag_1_peeled_oid | cut -c 1-4) &&
cat >.git/packed-refs <<-EOF &&
# pack-refs with: peeled fully-peeled sorted
$short_oid refs/heads/branch-1
${branch_1_oid}x
$branch_2_oid refs/heads/bad-branch
$branch_2_oid refs/heads/branch.
$tag_1_oid refs/tags/annotated-tag-3
^$short_oid
$tag_2_oid refs/tags/annotated-tag-4.
^$tag_2_peeled_oid garbage
EOF
test_must_fail git refs verify 2>err &&
cat >expect <<-EOF &&
error: packed-refs line 2: badPackedRefEntry: '\''$short_oid refs/heads/branch-1'\'' has invalid oid
error: packed-refs line 3: badPackedRefEntry: has no space after oid '\''$branch_1_oid'\'' but with '\''x'\''
error: packed-refs line 4: badRefName: has bad refname '\'' refs/heads/bad-branch'\''
error: packed-refs line 5: badRefName: has bad refname '\''refs/heads/branch.'\''
error: packed-refs line 7: badPackedRefEntry: '\''$short_oid'\'' has invalid peeled oid
error: packed-refs line 8: badRefName: has bad refname '\''refs/tags/annotated-tag-4.'\''
error: packed-refs line 9: badPackedRefEntry: has trailing garbage after peeled oid '\'' garbage'\''
EOF
test_cmp expect err
)
'
test_expect_success 'packed-ref with sorted trait should be checked' '
test_when_finished "rm -rf repo" &&
git init repo &&
(
cd repo &&
test_commit default &&
git branch branch-1 &&
git branch branch-2 &&
git tag -a annotated-tag-1 -m tag-1 &&
branch_1_oid=$(git rev-parse branch-1) &&
branch_2_oid=$(git rev-parse branch-2) &&
tag_1_oid=$(git rev-parse annotated-tag-1) &&
tag_1_peeled_oid=$(git rev-parse annotated-tag-1^{}) &&
refname1="refs/heads/main" &&
refname2="refs/heads/foo" &&
refname3="refs/tags/foo" &&
cat >.git/packed-refs <<-EOF &&
# pack-refs with: peeled fully-peeled sorted
EOF
git refs verify 2>err &&
rm .git/packed-refs &&
test_must_be_empty err &&
cat >.git/packed-refs <<-EOF &&
# pack-refs with: peeled fully-peeled sorted
$branch_2_oid $refname1
EOF
git refs verify 2>err &&
rm .git/packed-refs &&
test_must_be_empty err &&
cat >.git/packed-refs <<-EOF &&
# pack-refs with: peeled fully-peeled sorted
$branch_2_oid $refname1
$branch_1_oid $refname2
$tag_1_oid $refname3
EOF
test_must_fail git refs verify 2>err &&
cat >expect <<-EOF &&
error: packed-refs line 3: packedRefUnsorted: refname '\''$refname2'\'' is less than previous refname '\''$refname1'\''
EOF
rm .git/packed-refs &&
test_cmp expect err &&
cat >.git/packed-refs <<-EOF &&
# pack-refs with: peeled fully-peeled sorted
$tag_1_oid $refname3
^$tag_1_peeled_oid
$branch_2_oid $refname2
EOF
test_must_fail git refs verify 2>err &&
cat >expect <<-EOF &&
error: packed-refs line 4: packedRefUnsorted: refname '\''$refname2'\'' is less than previous refname '\''$refname3'\''
EOF
rm .git/packed-refs &&
test_cmp expect err
)
'
test_expect_success 'packed-ref without sorted trait should not be checked' '
test_when_finished "rm -rf repo" &&
git init repo &&
(
cd repo &&
test_commit default &&
git branch branch-1 &&
git branch branch-2 &&
git tag -a annotated-tag-1 -m tag-1 &&
branch_1_oid=$(git rev-parse branch-1) &&
branch_2_oid=$(git rev-parse branch-2) &&
tag_1_oid=$(git rev-parse annotated-tag-1) &&
tag_1_peeled_oid=$(git rev-parse annotated-tag-1^{}) &&
refname1="refs/heads/main" &&
refname2="refs/heads/foo" &&
refname3="refs/tags/foo" &&
cat >.git/packed-refs <<-EOF &&
# pack-refs with: peeled fully-peeled
$branch_2_oid $refname1
$branch_1_oid $refname2
EOF
git refs verify 2>err &&
test_must_be_empty err
)
'
test_expect_success '--[no-]references option should apply to fsck' '
test_when_finished "rm -rf repo" &&
git init repo &&
branch_dir_prefix=.git/refs/heads &&
(
cd repo &&
test_commit default &&
for trailing_content in " garbage" " more garbage"
do
printf "%s" "$(git rev-parse HEAD)$trailing_content" >$branch_dir_prefix/branch-garbage &&
git fsck 2>err &&
cat >expect <<-EOF &&
warning: refs/heads/branch-garbage: trailingRefContent: has trailing garbage: '\''$trailing_content'\''
EOF
rm $branch_dir_prefix/branch-garbage &&
test_cmp expect err || return 1
done &&
for trailing_content in " garbage" " more garbage"
do
printf "%s" "$(git rev-parse HEAD)$trailing_content" >$branch_dir_prefix/branch-garbage &&
git fsck --references 2>err &&
cat >expect <<-EOF &&
warning: refs/heads/branch-garbage: trailingRefContent: has trailing garbage: '\''$trailing_content'\''
EOF
rm $branch_dir_prefix/branch-garbage &&
test_cmp expect err || return 1
done &&
for trailing_content in " garbage" " more garbage"
do
printf "%s" "$(git rev-parse HEAD)$trailing_content" >$branch_dir_prefix/branch-garbage &&
git fsck --no-references 2>err &&
rm $branch_dir_prefix/branch-garbage &&
test_must_be_empty err || return 1
done
)
'
test_done