809 lines
29 KiB
Bash
Executable File
809 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 &&
|
|
tag_dir_prefix=.git/refs/tags &&
|
|
cd repo &&
|
|
test_commit default &&
|
|
git branch branch-1 &&
|
|
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 non_existing_oid in "$(test_oid 001)" "$(test_oid 002)"
|
|
do
|
|
printf "%s\n" $non_existing_oid >$branch_dir_prefix/invalid-commit &&
|
|
test_must_fail git refs verify 2>err &&
|
|
cat >expect <<-EOF &&
|
|
error: refs/heads/invalid-commit: badRefContent: points to non-existing object $non_existing_oid
|
|
EOF
|
|
rm $branch_dir_prefix/invalid-commit &&
|
|
test_cmp expect err || return 1
|
|
done &&
|
|
|
|
for tree_oid in "$(git rev-parse main^{tree})" "$(git rev-parse branch-1^{tree})"
|
|
do
|
|
printf "%s\n" $tree_oid >$branch_dir_prefix/branch-tree &&
|
|
test_must_fail git refs verify 2>err &&
|
|
cat >expect <<-EOF &&
|
|
error: refs/heads/branch-tree: badRefContent: points to non-commit object $tree_oid
|
|
EOF
|
|
rm $branch_dir_prefix/branch-tree &&
|
|
test_cmp expect err || return 1
|
|
done &&
|
|
|
|
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 &&
|
|
non_existing_oid=$(test_oid 001) &&
|
|
tree_oid=$(git rev-parse main^{tree}) &&
|
|
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 &&
|
|
printf "%s\n" $non_existing_oid >$branch_dir_prefix/branch-non-existing-oid &&
|
|
printf "%s\n" $tree_oid >$branch_dir_prefix/branch-tree &&
|
|
|
|
test_must_fail git refs verify 2>err &&
|
|
cat >expect <<-EOF &&
|
|
error: refs/heads/a/b/branch-bad: badRefContent: $bad_content_3
|
|
error: refs/heads/branch-non-existing-oid: badRefContent: points to non-existing object $non_existing_oid
|
|
error: refs/heads/branch-tree: badRefContent: points to non-commit object $tree_oid
|
|
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-bak .git/packed-refs &&
|
|
test_must_fail git refs verify 2>err &&
|
|
cat >expect <<-EOF &&
|
|
error: packed-refs: badRefFiletype: not a regular file
|
|
EOF
|
|
rm .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 &&
|
|
|
|
printf "$(git rev-parse main) refs/heads/main\n" >.git/packed-refs &&
|
|
git refs verify 2>err &&
|
|
cat >expect <<-EOF &&
|
|
warning: packed-refs: packedRefMissingHeader: missing header line
|
|
EOF
|
|
rm .git/packed-refs &&
|
|
test_cmp expect 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"
|
|
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 &&
|
|
|
|
for unknown_header in "# pack-refs with: peeled fully-peeled sorted garbage" \
|
|
"# pack-refs with: peeled" \
|
|
"# pack-refs with: peeled peeled-fully sort"
|
|
do
|
|
printf "%s\n" "$unknown_header" >.git/packed-refs &&
|
|
git refs verify 2>err &&
|
|
cat >expect <<-EOF &&
|
|
warning: packed-refs.header: unknownPackedRefHeader: '\''$unknown_header'\'' is not the official packed-refs header
|
|
EOF
|
|
rm .git/packed-refs &&
|
|
test_cmp expect err || return 1
|
|
done
|
|
'
|
|
|
|
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) &&
|
|
|
|
printf "# pack-refs with: peeled fully-peeled sorted \n" >.git/packed-refs &&
|
|
printf "%s\n" "$short_oid refs/heads/branch-1" >>.git/packed-refs &&
|
|
printf "%sx\n" "$branch_1_oid" >>.git/packed-refs &&
|
|
printf "%s refs/heads/bad-branch\n" "$branch_2_oid" >>.git/packed-refs &&
|
|
printf "%s refs/heads/branch.\n" "$branch_2_oid" >>.git/packed-refs &&
|
|
printf "%s refs/tags/annotated-tag-3\n" "$tag_1_oid" >>.git/packed-refs &&
|
|
printf "^%s\n" "$short_oid" >>.git/packed-refs &&
|
|
printf "%s refs/tags/annotated-tag-4.\n" "$tag_2_oid" >>.git/packed-refs &&
|
|
printf "^%s garbage\n" "$tag_2_peeled_oid" >>.git/packed-refs &&
|
|
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-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_expect_success 'packed-ref sorted 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" &&
|
|
|
|
printf "# pack-refs with: peeled fully-peeled sorted \n" >.git/packed-refs &&
|
|
printf "%s %s\n" "$branch_2_oid" "$refname1" >>.git/packed-refs &&
|
|
printf "%s %s\n" "$branch_1_oid" "$refname2" >>.git/packed-refs &&
|
|
test_must_fail git refs verify 2>err &&
|
|
cat >expect <<-EOF &&
|
|
error: packed-refs line 2: packedRefUnsorted: refname '\''$refname1'\'' is not less than next refname '\''$refname2'\''
|
|
EOF
|
|
rm .git/packed-refs &&
|
|
test_cmp expect err &&
|
|
|
|
printf "# pack-refs with: peeled fully-peeled sorted \n" >.git/packed-refs &&
|
|
printf "%s %s\n" "$tag_1_oid" "$refname3" >>.git/packed-refs &&
|
|
printf "^%s\n" "$tag_1_peeled_oid" >>.git/packed-refs &&
|
|
printf "%s %s\n" "$branch_2_oid" "$refname2" >>.git/packed-refs &&
|
|
test_must_fail git refs verify 2>err &&
|
|
cat >expect <<-EOF &&
|
|
error: packed-refs line 2: packedRefUnsorted: refname '\''$refname3'\'' is not less than next refname '\''$refname2'\''
|
|
EOF
|
|
rm .git/packed-refs &&
|
|
test_cmp expect err
|
|
'
|
|
|
|
test_done
|