Raw
1 #!/bin/sh
2
3 test_description='Test reffiles backend consistency check'
4
5 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
6 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
7 GIT_TEST_DEFAULT_REF_FORMAT=files
8 export GIT_TEST_DEFAULT_REF_FORMAT
9
10 . ./test-lib.sh
11
12 test_expect_success 'ref name should be checked' '
13 test_when_finished "rm -rf repo" &&
14 git init repo &&
15 branch_dir_prefix=.git/refs/heads &&
16 tag_dir_prefix=.git/refs/tags &&
17 (
18 cd repo &&
19
20 git commit --allow-empty -m initial &&
21 git checkout -b default-branch &&
22 git tag default-tag &&
23 git tag multi_hierarchy/default-tag &&
24
25 cp $branch_dir_prefix/default-branch $branch_dir_prefix/@ &&
26 git refs verify 2>err &&
27 test_must_be_empty err &&
28 rm $branch_dir_prefix/@ &&
29
30 cp $tag_dir_prefix/default-tag $tag_dir_prefix/tag-1.lock &&
31 git refs verify 2>err &&
32 rm $tag_dir_prefix/tag-1.lock &&
33 test_must_be_empty err &&
34
35 cp $tag_dir_prefix/default-tag $tag_dir_prefix/.lock &&
36 test_must_fail git refs verify 2>err &&
37 cat >expect <<-EOF &&
38 error: refs/tags/.lock: badRefName: invalid refname format
39 EOF
40 rm $tag_dir_prefix/.lock &&
41 test_cmp expect err &&
42
43 for refname in ".refname-starts-with-dot" "~refname-has-stride"
44 do
45 cp $branch_dir_prefix/default-branch "$branch_dir_prefix/$refname" &&
46 test_must_fail git refs verify 2>err &&
47 cat >expect <<-EOF &&
48 error: refs/heads/$refname: badRefName: invalid refname format
49 EOF
50 rm "$branch_dir_prefix/$refname" &&
51 test_cmp expect err || return 1
52 done &&
53
54 for refname in ".refname-starts-with-dot" "~refname-has-stride"
55 do
56 cp $tag_dir_prefix/default-tag "$tag_dir_prefix/$refname" &&
57 test_must_fail git refs verify 2>err &&
58 cat >expect <<-EOF &&
59 error: refs/tags/$refname: badRefName: invalid refname format
60 EOF
61 rm "$tag_dir_prefix/$refname" &&
62 test_cmp expect err || return 1
63 done &&
64
65 for refname in ".refname-starts-with-dot" "~refname-has-stride"
66 do
67 cp $tag_dir_prefix/multi_hierarchy/default-tag "$tag_dir_prefix/multi_hierarchy/$refname" &&
68 test_must_fail git refs verify 2>err &&
69 cat >expect <<-EOF &&
70 error: refs/tags/multi_hierarchy/$refname: badRefName: invalid refname format
71 EOF
72 rm "$tag_dir_prefix/multi_hierarchy/$refname" &&
73 test_cmp expect err || return 1
74 done &&
75
76 for refname in ".refname-starts-with-dot" "~refname-has-stride"
77 do
78 mkdir "$branch_dir_prefix/$refname" &&
79 cp $branch_dir_prefix/default-branch "$branch_dir_prefix/$refname/default-branch" &&
80 test_must_fail git refs verify 2>err &&
81 cat >expect <<-EOF &&
82 error: refs/heads/$refname/default-branch: badRefName: invalid refname format
83 EOF
84 rm -r "$branch_dir_prefix/$refname" &&
85 test_cmp expect err || return 1
86 done
87 )
88 '
89
90 test_expect_success 'lock files should be ignored' '
91 test_when_finished "rm -rf repo" &&
92 git init repo &&
93 (
94 cd repo &&
95 git commit --allow-empty -m initial &&
96 git checkout -b branch-1 &&
97
98 touch .git/refs/heads/branch-1.lock &&
99 git refs verify 2>err &&
100 test_must_be_empty err &&
101
102 echo "foobar" >.git/refs/heads/branch-2 &&
103 test_must_fail git refs verify 2>err &&
104 cat >expect <<-EOF &&
105 error: refs/heads/branch-2: badRefContent: foobar
106 EOF
107 test_cmp expect err
108 )
109 '
110
111 test_expect_success 'bare lock files should not be ignored' '
112 test_when_finished "rm -rf repo" &&
113 git init repo &&
114 (
115 cd repo &&
116 git commit --allow-empty -m initial &&
117 git checkout -b branch-1 &&
118
119 # invalid refname should be reported
120 cp .git/refs/heads/branch-1 .git/refs/heads/.branch-1.lock &&
121 # invalid refname and content should be reported
122 touch .git/refs/heads/.lock &&
123
124 test_must_fail git refs verify 2>err &&
125 test_grep "error: refs/heads/.branch-1.lock: badRefName: invalid refname format" err &&
126 test_grep "error: refs/heads/.lock: badRefName: invalid refname format" err &&
127 test_grep "error: refs/heads/.lock: badRefContent: " err
128 )
129 '
130
131 test_expect_success 'ref name check should be adapted into fsck messages' '
132 test_when_finished "rm -rf repo" &&
133 git init repo &&
134 branch_dir_prefix=.git/refs/heads &&
135 (
136 cd repo &&
137 git commit --allow-empty -m initial &&
138 git checkout -b branch-1 &&
139
140 cp $branch_dir_prefix/branch-1 $branch_dir_prefix/.branch-1 &&
141 git -c fsck.badRefName=warn refs verify 2>err &&
142 cat >expect <<-EOF &&
143 warning: refs/heads/.branch-1: badRefName: invalid refname format
144 EOF
145 rm $branch_dir_prefix/.branch-1 &&
146 test_cmp expect err &&
147
148 cp $branch_dir_prefix/branch-1 $branch_dir_prefix/.branch-1 &&
149 git -c fsck.badRefName=ignore refs verify 2>err &&
150 test_must_be_empty err
151 )
152 '
153
154 test_expect_success 'no refs directory of worktree should not cause problems' '
155 test_when_finished "rm -rf repo" &&
156 git init repo &&
157 (
158 cd repo &&
159 test_commit initial &&
160 git worktree add --detach ./worktree &&
161
162 (
163 cd worktree &&
164 worktree_refdir="$(git rev-parse --git-dir)/refs" &&
165 # Simulate old directory layout
166 rmdir "$worktree_refdir" &&
167 git refs verify 2>err &&
168 test_must_be_empty err
169 )
170 )
171 '
172
173 test_expect_success 'ref name check should work for multiple worktrees' '
174 test_when_finished "rm -rf repo" &&
175 git init repo &&
176 (
177 cd repo &&
178 test_commit initial &&
179 git checkout -b branch-1 &&
180 test_commit second &&
181 git checkout -b branch-2 &&
182 test_commit third &&
183 git checkout -b branch-3 &&
184 git worktree add ./worktree-1 branch-1 &&
185 git worktree add ./worktree-2 branch-2 &&
186 worktree1_refdir_prefix=.git/worktrees/worktree-1/refs/worktree &&
187 worktree2_refdir_prefix=.git/worktrees/worktree-2/refs/worktree &&
188
189 (
190 cd worktree-1 &&
191 git update-ref refs/worktree/branch-4 refs/heads/branch-3
192 ) &&
193 (
194 cd worktree-2 &&
195 git update-ref refs/worktree/branch-4 refs/heads/branch-3
196 ) &&
197
198 cp $worktree1_refdir_prefix/branch-4 $worktree1_refdir_prefix/'\'' branch-5'\'' &&
199 cp $worktree2_refdir_prefix/branch-4 $worktree2_refdir_prefix/'\''~branch-6'\'' &&
200
201 test_must_fail git refs verify 2>err &&
202 cat >expect <<-EOF &&
203 error: worktrees/worktree-1/refs/worktree/ branch-5: badRefName: invalid refname format
204 error: worktrees/worktree-2/refs/worktree/~branch-6: badRefName: invalid refname format
205 EOF
206 sort err >sorted_err &&
207 test_cmp expect sorted_err &&
208
209 for worktree in "worktree-1" "worktree-2"
210 do
211 (
212 cd $worktree &&
213 test_must_fail git refs verify 2>err &&
214 cat >expect <<-EOF &&
215 error: worktrees/worktree-1/refs/worktree/ branch-5: badRefName: invalid refname format
216 error: worktrees/worktree-2/refs/worktree/~branch-6: badRefName: invalid refname format
217 EOF
218 sort err >sorted_err &&
219 test_cmp expect sorted_err || return 1
220 )
221 done
222 )
223 '
224
225 test_expect_success 'regular ref content should be checked (individual)' '
226 test_when_finished "rm -rf repo" &&
227 git init repo &&
228 branch_dir_prefix=.git/refs/heads &&
229 (
230 cd repo &&
231 test_commit default &&
232 mkdir -p "$branch_dir_prefix/a/b" &&
233
234 git refs verify 2>err &&
235 test_must_be_empty err &&
236
237 for bad_content in "$(git rev-parse main)x" "xfsazqfxcadas" "Xfsazqfxcadas"
238 do
239 printf "%s" $bad_content >$branch_dir_prefix/branch-bad &&
240 test_must_fail git refs verify 2>err &&
241 cat >expect <<-EOF &&
242 error: refs/heads/branch-bad: badRefContent: $bad_content
243 EOF
244 rm $branch_dir_prefix/branch-bad &&
245 test_cmp expect err || return 1
246 done &&
247
248 for bad_content in "$(git rev-parse main)x" "xfsazqfxcadas" "Xfsazqfxcadas"
249 do
250 printf "%s" $bad_content >$branch_dir_prefix/a/b/branch-bad &&
251 test_must_fail git refs verify 2>err &&
252 cat >expect <<-EOF &&
253 error: refs/heads/a/b/branch-bad: badRefContent: $bad_content
254 EOF
255 rm $branch_dir_prefix/a/b/branch-bad &&
256 test_cmp expect err || return 1
257 done &&
258
259 printf "%s" "$(git rev-parse main)" >$branch_dir_prefix/branch-no-newline &&
260 git refs verify 2>err &&
261 cat >expect <<-EOF &&
262 warning: refs/heads/branch-no-newline: refMissingNewline: misses LF at the end
263 EOF
264 rm $branch_dir_prefix/branch-no-newline &&
265 test_cmp expect err &&
266
267 for trailing_content in " garbage" " more garbage"
268 do
269 printf "%s" "$(git rev-parse main)$trailing_content" >$branch_dir_prefix/branch-garbage &&
270 git refs verify 2>err &&
271 cat >expect <<-EOF &&
272 warning: refs/heads/branch-garbage: trailingRefContent: has trailing garbage: '\''$trailing_content'\''
273 EOF
274 rm $branch_dir_prefix/branch-garbage &&
275 test_cmp expect err || return 1
276 done &&
277
278 printf "%s\n\n\n" "$(git rev-parse main)" >$branch_dir_prefix/branch-garbage-special &&
279 git refs verify 2>err &&
280 cat >expect <<-EOF &&
281 warning: refs/heads/branch-garbage-special: trailingRefContent: has trailing garbage: '\''
282
283
284 '\''
285 EOF
286 rm $branch_dir_prefix/branch-garbage-special &&
287 test_cmp expect err &&
288
289 printf "%s\n\n\n garbage" "$(git rev-parse main)" >$branch_dir_prefix/branch-garbage-special &&
290 git refs verify 2>err &&
291 cat >expect <<-EOF &&
292 warning: refs/heads/branch-garbage-special: trailingRefContent: has trailing garbage: '\''
293
294
295 garbage'\''
296 EOF
297 rm $branch_dir_prefix/branch-garbage-special &&
298 test_cmp expect err
299 )
300 '
301
302 test_expect_success 'regular ref content should be checked (aggregate)' '
303 test_when_finished "rm -rf repo" &&
304 git init repo &&
305 branch_dir_prefix=.git/refs/heads &&
306 tag_dir_prefix=.git/refs/tags &&
307 (
308 cd repo &&
309 test_commit default &&
310 mkdir -p "$branch_dir_prefix/a/b" &&
311
312 bad_content_1=$(git rev-parse main)x &&
313 bad_content_2=xfsazqfxcadas &&
314 bad_content_3=Xfsazqfxcadas &&
315 printf "%s" $bad_content_1 >$tag_dir_prefix/tag-bad-1 &&
316 printf "%s" $bad_content_2 >$tag_dir_prefix/tag-bad-2 &&
317 printf "%s" $bad_content_3 >$branch_dir_prefix/a/b/branch-bad &&
318 printf "%s" "$(git rev-parse main)" >$branch_dir_prefix/branch-no-newline &&
319 printf "%s garbage" "$(git rev-parse main)" >$branch_dir_prefix/branch-garbage &&
320
321 test_must_fail git refs verify 2>err &&
322 cat >expect <<-EOF &&
323 error: refs/heads/a/b/branch-bad: badRefContent: $bad_content_3
324 error: refs/tags/tag-bad-1: badRefContent: $bad_content_1
325 error: refs/tags/tag-bad-2: badRefContent: $bad_content_2
326 warning: refs/heads/branch-garbage: trailingRefContent: has trailing garbage: '\'' garbage'\''
327 warning: refs/heads/branch-no-newline: refMissingNewline: misses LF at the end
328 EOF
329 sort err >sorted_err &&
330 test_cmp expect sorted_err
331 )
332 '
333
334 test_expect_success 'textual symref content should be checked (individual)' '
335 test_when_finished "rm -rf repo" &&
336 git init repo &&
337 branch_dir_prefix=.git/refs/heads &&
338 (
339 cd repo &&
340 test_commit default &&
341 mkdir -p "$branch_dir_prefix/a/b" &&
342
343 for good_referent in "refs/heads/branch" "HEAD"
344 do
345 printf "ref: %s\n" $good_referent >$branch_dir_prefix/branch-good &&
346 git refs verify 2>err &&
347 rm $branch_dir_prefix/branch-good &&
348 test_must_be_empty err || return 1
349 done &&
350
351 for bad_referent in "refs/heads/.branch" "refs/heads/~branch" "refs/heads/?branch"
352 do
353 printf "ref: %s\n" $bad_referent >$branch_dir_prefix/branch-bad &&
354 test_must_fail git refs verify 2>err &&
355 cat >expect <<-EOF &&
356 error: refs/heads/branch-bad: badReferentName: points to invalid refname '\''$bad_referent'\''
357 EOF
358 rm $branch_dir_prefix/branch-bad &&
359 test_cmp expect err || return 1
360 done &&
361
362 printf "ref: refs/heads/branch" >$branch_dir_prefix/branch-no-newline &&
363 git refs verify 2>err &&
364 cat >expect <<-EOF &&
365 warning: refs/heads/branch-no-newline: refMissingNewline: misses LF at the end
366 EOF
367 rm $branch_dir_prefix/branch-no-newline &&
368 test_cmp expect err &&
369
370 printf "ref: refs/heads/branch " >$branch_dir_prefix/a/b/branch-trailing-1 &&
371 git refs verify 2>err &&
372 cat >expect <<-EOF &&
373 warning: refs/heads/a/b/branch-trailing-1: refMissingNewline: misses LF at the end
374 warning: refs/heads/a/b/branch-trailing-1: trailingRefContent: has trailing whitespaces or newlines
375 EOF
376 rm $branch_dir_prefix/a/b/branch-trailing-1 &&
377 test_cmp expect err &&
378
379 printf "ref: refs/heads/branch\n\n" >$branch_dir_prefix/a/b/branch-trailing-2 &&
380 git refs verify 2>err &&
381 cat >expect <<-EOF &&
382 warning: refs/heads/a/b/branch-trailing-2: trailingRefContent: has trailing whitespaces or newlines
383 EOF
384 rm $branch_dir_prefix/a/b/branch-trailing-2 &&
385 test_cmp expect err &&
386
387 printf "ref: refs/heads/branch \n" >$branch_dir_prefix/a/b/branch-trailing-3 &&
388 git refs verify 2>err &&
389 cat >expect <<-EOF &&
390 warning: refs/heads/a/b/branch-trailing-3: trailingRefContent: has trailing whitespaces or newlines
391 EOF
392 rm $branch_dir_prefix/a/b/branch-trailing-3 &&
393 test_cmp expect err &&
394
395 printf "ref: refs/heads/branch \n " >$branch_dir_prefix/a/b/branch-complicated &&
396 git refs verify 2>err &&
397 cat >expect <<-EOF &&
398 warning: refs/heads/a/b/branch-complicated: refMissingNewline: misses LF at the end
399 warning: refs/heads/a/b/branch-complicated: trailingRefContent: has trailing whitespaces or newlines
400 EOF
401 rm $branch_dir_prefix/a/b/branch-complicated &&
402 test_cmp expect err
403 )
404 '
405
406 test_expect_success 'textual symref content should be checked (aggregate)' '
407 test_when_finished "rm -rf repo" &&
408 git init repo &&
409 branch_dir_prefix=.git/refs/heads &&
410 tag_dir_prefix=.git/refs/tags &&
411 (
412 cd repo &&
413 test_commit default &&
414 mkdir -p "$branch_dir_prefix/a/b" &&
415
416 printf "ref: refs/heads/branch\n" >$branch_dir_prefix/branch-good &&
417 printf "ref: HEAD\n" >$branch_dir_prefix/branch-head &&
418 printf "ref: refs/heads/branch" >$branch_dir_prefix/branch-no-newline-1 &&
419 printf "ref: refs/heads/branch " >$branch_dir_prefix/a/b/branch-trailing-1 &&
420 printf "ref: refs/heads/branch\n\n" >$branch_dir_prefix/a/b/branch-trailing-2 &&
421 printf "ref: refs/heads/branch \n" >$branch_dir_prefix/a/b/branch-trailing-3 &&
422 printf "ref: refs/heads/branch \n " >$branch_dir_prefix/a/b/branch-complicated &&
423 printf "ref: refs/heads/.branch\n" >$branch_dir_prefix/branch-bad-1 &&
424
425 test_must_fail git refs verify 2>err &&
426 cat >expect <<-EOF &&
427 error: refs/heads/branch-bad-1: badReferentName: points to invalid refname '\''refs/heads/.branch'\''
428 warning: refs/heads/a/b/branch-complicated: refMissingNewline: misses LF at the end
429 warning: refs/heads/a/b/branch-complicated: trailingRefContent: has trailing whitespaces or newlines
430 warning: refs/heads/a/b/branch-trailing-1: refMissingNewline: misses LF at the end
431 warning: refs/heads/a/b/branch-trailing-1: trailingRefContent: has trailing whitespaces or newlines
432 warning: refs/heads/a/b/branch-trailing-2: trailingRefContent: has trailing whitespaces or newlines
433 warning: refs/heads/a/b/branch-trailing-3: trailingRefContent: has trailing whitespaces or newlines
434 warning: refs/heads/branch-no-newline-1: refMissingNewline: misses LF at the end
435 EOF
436 sort err >sorted_err &&
437 test_cmp expect sorted_err
438 )
439 '
440
441 test_expect_success 'the target of the textual symref should be checked' '
442 test_when_finished "rm -rf repo" &&
443 git init repo &&
444 branch_dir_prefix=.git/refs/heads &&
445 tag_dir_prefix=.git/refs/tags &&
446 (
447 cd repo &&
448 test_commit default &&
449 mkdir -p "$branch_dir_prefix/a/b" &&
450
451 for good_referent in "refs/heads/branch" "HEAD" "refs/tags/tag"
452 do
453 printf "ref: %s\n" $good_referent >$branch_dir_prefix/branch-good &&
454 git refs verify 2>err &&
455 rm $branch_dir_prefix/branch-good &&
456 test_must_be_empty err || return 1
457 done &&
458
459 for nonref_referent in "refs-back/heads/branch" "refs-back/tags/tag" "reflogs/refs/heads/branch"
460 do
461 printf "ref: %s\n" $nonref_referent >$branch_dir_prefix/branch-bad-1 &&
462 git refs verify 2>err &&
463 cat >expect <<-EOF &&
464 warning: refs/heads/branch-bad-1: symrefTargetIsNotARef: points to non-ref target '\''$nonref_referent'\''
465 EOF
466 rm $branch_dir_prefix/branch-bad-1 &&
467 test_cmp expect err || return 1
468 done
469 )
470 '
471
472 test_expect_success SYMLINKS 'symlink symref content should be checked' '
473 test_when_finished "rm -rf repo" &&
474 git init repo &&
475 branch_dir_prefix=.git/refs/heads &&
476 tag_dir_prefix=.git/refs/tags &&
477 (
478 cd repo &&
479 test_commit default &&
480 mkdir -p "$branch_dir_prefix/a/b" &&
481
482 ln -sf ./main $branch_dir_prefix/branch-symbolic-good &&
483 git refs verify 2>err &&
484 cat >expect <<-EOF &&
485 warning: refs/heads/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref
486 EOF
487 rm $branch_dir_prefix/branch-symbolic-good &&
488 test_cmp expect err &&
489
490 ln -sf ../../logs/branch-escape $branch_dir_prefix/branch-symbolic &&
491 git refs verify 2>err &&
492 cat >expect <<-EOF &&
493 warning: refs/heads/branch-symbolic: symlinkRef: use deprecated symbolic link for symref
494 warning: refs/heads/branch-symbolic: symrefTargetIsNotARef: points to non-ref target '\''logs/branch-escape'\''
495 EOF
496 rm $branch_dir_prefix/branch-symbolic &&
497 test_cmp expect err &&
498
499 ln -sf ./"branch " $branch_dir_prefix/branch-symbolic-bad &&
500 test_must_fail git refs verify 2>err &&
501 cat >expect <<-EOF &&
502 warning: refs/heads/branch-symbolic-bad: symlinkRef: use deprecated symbolic link for symref
503 error: refs/heads/branch-symbolic-bad: badReferentName: points to invalid refname '\''refs/heads/branch '\''
504 EOF
505 rm $branch_dir_prefix/branch-symbolic-bad &&
506 test_cmp expect err &&
507
508 ln -sf ./".tag" $tag_dir_prefix/tag-symbolic-1 &&
509 test_must_fail git refs verify 2>err &&
510 cat >expect <<-EOF &&
511 warning: refs/tags/tag-symbolic-1: symlinkRef: use deprecated symbolic link for symref
512 error: refs/tags/tag-symbolic-1: badReferentName: points to invalid refname '\''refs/tags/.tag'\''
513 EOF
514 rm $tag_dir_prefix/tag-symbolic-1 &&
515 test_cmp expect err
516 )
517 '
518
519 test_expect_success SYMLINKS 'symlink symref content should be checked (worktree)' '
520 test_when_finished "rm -rf repo" &&
521 git init repo &&
522 (
523 cd repo &&
524 test_commit default &&
525 git branch branch-1 &&
526 git branch branch-2 &&
527 git branch branch-3 &&
528 git worktree add ./worktree-1 branch-2 &&
529 git worktree add ./worktree-2 branch-3 &&
530 main_worktree_refdir_prefix=.git/refs/heads &&
531 worktree1_refdir_prefix=.git/worktrees/worktree-1/refs/worktree &&
532 worktree2_refdir_prefix=.git/worktrees/worktree-2/refs/worktree &&
533
534 (
535 cd worktree-1 &&
536 git update-ref refs/worktree/branch-4 refs/heads/branch-1
537 ) &&
538 (
539 cd worktree-2 &&
540 git update-ref refs/worktree/branch-4 refs/heads/branch-1
541 ) &&
542
543 ln -sf ../../../../refs/heads/good-branch $worktree1_refdir_prefix/branch-symbolic-good &&
544 git refs verify 2>err &&
545 cat >expect <<-EOF &&
546 warning: worktrees/worktree-1/refs/worktree/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref
547 EOF
548 rm $worktree1_refdir_prefix/branch-symbolic-good &&
549 test_cmp expect err &&
550
551 ln -sf ../../../../worktrees/worktree-1/good-branch $worktree2_refdir_prefix/branch-symbolic-good &&
552 git refs verify 2>err &&
553 cat >expect <<-EOF &&
554 warning: worktrees/worktree-2/refs/worktree/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref
555 EOF
556 rm $worktree2_refdir_prefix/branch-symbolic-good &&
557 test_cmp expect err &&
558
559 ln -sf ../../worktrees/worktree-2/good-branch $main_worktree_refdir_prefix/branch-symbolic-good &&
560 git refs verify 2>err &&
561 cat >expect <<-EOF &&
562 warning: refs/heads/branch-symbolic-good: symlinkRef: use deprecated symbolic link for symref
563 EOF
564 rm $main_worktree_refdir_prefix/branch-symbolic-good &&
565 test_cmp expect err &&
566
567 ln -sf ../../../../logs/branch-escape $worktree1_refdir_prefix/branch-symbolic &&
568 git refs verify 2>err &&
569 cat >expect <<-EOF &&
570 warning: worktrees/worktree-1/refs/worktree/branch-symbolic: symlinkRef: use deprecated symbolic link for symref
571 warning: worktrees/worktree-1/refs/worktree/branch-symbolic: symrefTargetIsNotARef: points to non-ref target '\''logs/branch-escape'\''
572 EOF
573 rm $worktree1_refdir_prefix/branch-symbolic &&
574 test_cmp expect err &&
575
576 for bad_referent_name in ".tag" "branch "
577 do
578 ln -sf ./"$bad_referent_name" $worktree1_refdir_prefix/bad-symbolic &&
579 test_must_fail git refs verify 2>err &&
580 cat >expect <<-EOF &&
581 warning: worktrees/worktree-1/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref
582 error: worktrees/worktree-1/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''worktrees/worktree-1/refs/worktree/$bad_referent_name'\''
583 EOF
584 rm $worktree1_refdir_prefix/bad-symbolic &&
585 test_cmp expect err &&
586
587 ln -sf ../../../../refs/heads/"$bad_referent_name" $worktree1_refdir_prefix/bad-symbolic &&
588 test_must_fail git refs verify 2>err &&
589 cat >expect <<-EOF &&
590 warning: worktrees/worktree-1/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref
591 error: worktrees/worktree-1/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''refs/heads/$bad_referent_name'\''
592 EOF
593 rm $worktree1_refdir_prefix/bad-symbolic &&
594 test_cmp expect err &&
595
596 ln -sf ./"$bad_referent_name" $worktree2_refdir_prefix/bad-symbolic &&
597 test_must_fail git refs verify 2>err &&
598 cat >expect <<-EOF &&
599 warning: worktrees/worktree-2/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref
600 error: worktrees/worktree-2/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''worktrees/worktree-2/refs/worktree/$bad_referent_name'\''
601 EOF
602 rm $worktree2_refdir_prefix/bad-symbolic &&
603 test_cmp expect err &&
604
605 ln -sf ../../../../refs/heads/"$bad_referent_name" $worktree2_refdir_prefix/bad-symbolic &&
606 test_must_fail git refs verify 2>err &&
607 cat >expect <<-EOF &&
608 warning: worktrees/worktree-2/refs/worktree/bad-symbolic: symlinkRef: use deprecated symbolic link for symref
609 error: worktrees/worktree-2/refs/worktree/bad-symbolic: badReferentName: points to invalid refname '\''refs/heads/$bad_referent_name'\''
610 EOF
611 rm $worktree2_refdir_prefix/bad-symbolic &&
612 test_cmp expect err || return 1
613 done
614 )
615 '
616
617 test_expect_success 'ref content checks should work with worktrees' '
618 test_when_finished "rm -rf repo" &&
619 git init repo &&
620 (
621 cd repo &&
622 test_commit default &&
623 git branch branch-1 &&
624 git branch branch-2 &&
625 git branch branch-3 &&
626 git worktree add ./worktree-1 branch-2 &&
627 git worktree add ./worktree-2 branch-3 &&
628 worktree1_refdir_prefix=.git/worktrees/worktree-1/refs/worktree &&
629 worktree2_refdir_prefix=.git/worktrees/worktree-2/refs/worktree &&
630
631 (
632 cd worktree-1 &&
633 git update-ref refs/worktree/branch-4 refs/heads/branch-1
634 ) &&
635 (
636 cd worktree-2 &&
637 git update-ref refs/worktree/branch-4 refs/heads/branch-1
638 ) &&
639
640 for bad_content in "$(git rev-parse HEAD)x" "xfsazqfxcadas" "Xfsazqfxcadas"
641 do
642 printf "%s" $bad_content >$worktree1_refdir_prefix/bad-branch-1 &&
643 test_must_fail git refs verify 2>err &&
644 cat >expect <<-EOF &&
645 error: worktrees/worktree-1/refs/worktree/bad-branch-1: badRefContent: $bad_content
646 EOF
647 rm $worktree1_refdir_prefix/bad-branch-1 &&
648 test_cmp expect err || return 1
649 done &&
650
651 for bad_content in "$(git rev-parse HEAD)x" "xfsazqfxcadas" "Xfsazqfxcadas"
652 do
653 printf "%s" $bad_content >$worktree2_refdir_prefix/bad-branch-2 &&
654 test_must_fail git refs verify 2>err &&
655 cat >expect <<-EOF &&
656 error: worktrees/worktree-2/refs/worktree/bad-branch-2: badRefContent: $bad_content
657 EOF
658 rm $worktree2_refdir_prefix/bad-branch-2 &&
659 test_cmp expect err || return 1
660 done &&
661
662 printf "%s" "$(git rev-parse HEAD)" >$worktree1_refdir_prefix/branch-no-newline &&
663 git refs verify 2>err &&
664 cat >expect <<-EOF &&
665 warning: worktrees/worktree-1/refs/worktree/branch-no-newline: refMissingNewline: misses LF at the end
666 EOF
667 rm $worktree1_refdir_prefix/branch-no-newline &&
668 test_cmp expect err &&
669
670 printf "%s garbage" "$(git rev-parse HEAD)" >$worktree1_refdir_prefix/branch-garbage &&
671 git refs verify 2>err &&
672 cat >expect <<-EOF &&
673 warning: worktrees/worktree-1/refs/worktree/branch-garbage: trailingRefContent: has trailing garbage: '\'' garbage'\''
674 EOF
675 rm $worktree1_refdir_prefix/branch-garbage &&
676 test_cmp expect err
677 )
678 '
679
680 test_expect_success SYMLINKS 'the filetype of packed-refs should be checked' '
681 test_when_finished "rm -rf repo" &&
682 git init repo &&
683 (
684 cd repo &&
685 test_commit default &&
686 git branch branch-1 &&
687 git branch branch-2 &&
688 git branch branch-3 &&
689 git pack-refs --all &&
690
691 mv .git/packed-refs .git/packed-refs-back &&
692 ln -sf packed-refs-back .git/packed-refs &&
693 test_must_fail git refs verify 2>err &&
694 cat >expect <<-EOF &&
695 error: packed-refs: badRefFiletype: not a regular file but a symlink
696 EOF
697 rm .git/packed-refs &&
698 test_cmp expect err &&
699
700 mkdir .git/packed-refs &&
701 test_must_fail git refs verify 2>err &&
702 cat >expect <<-EOF &&
703 error: packed-refs: badRefFiletype: not a regular file
704 EOF
705 rm -r .git/packed-refs &&
706 test_cmp expect err
707 )
708 '
709
710 test_expect_success 'empty packed-refs should be reported' '
711 test_when_finished "rm -rf repo" &&
712 git init repo &&
713 (
714 cd repo &&
715 test_commit default &&
716
717 >.git/packed-refs &&
718 git refs verify 2>err &&
719 cat >expect <<-EOF &&
720 warning: packed-refs: emptyPackedRefsFile: file is empty
721 EOF
722 rm .git/packed-refs &&
723 test_cmp expect err
724 )
725 '
726
727 test_expect_success 'packed-refs header should be checked' '
728 test_when_finished "rm -rf repo" &&
729 git init repo &&
730 (
731 cd repo &&
732 test_commit default &&
733
734 git refs verify 2>err &&
735 test_must_be_empty err &&
736
737 for bad_header in "# pack-refs wit: peeled fully-peeled sorted " \
738 "# pack-refs with traits: peeled fully-peeled sorted " \
739 "# pack-refs with a: peeled fully-peeled" \
740 "# pack-refs with:peeled fully-peeled sorted"
741 do
742 printf "%s\n" "$bad_header" >.git/packed-refs &&
743 test_must_fail git refs verify 2>err &&
744 cat >expect <<-EOF &&
745 error: packed-refs.header: badPackedRefHeader: '\''$bad_header'\'' does not start with '\''# pack-refs with: '\''
746 EOF
747 rm .git/packed-refs &&
748 test_cmp expect err || return 1
749 done
750 )
751 '
752
753 test_expect_success 'packed-refs missing header should not be reported' '
754 test_when_finished "rm -rf repo" &&
755 git init repo &&
756 (
757 cd repo &&
758 test_commit default &&
759
760 printf "$(git rev-parse HEAD) refs/heads/main\n" >.git/packed-refs &&
761 git refs verify 2>err &&
762 test_must_be_empty err
763 )
764 '
765
766 test_expect_success 'packed-refs unknown traits should not be reported' '
767 test_when_finished "rm -rf repo" &&
768 git init repo &&
769 (
770 cd repo &&
771 test_commit default &&
772
773 printf "# pack-refs with: peeled fully-peeled sorted foo\n" >.git/packed-refs &&
774 git refs verify 2>err &&
775 test_must_be_empty err
776 )
777 '
778
779 test_expect_success 'packed-refs content should be checked' '
780 test_when_finished "rm -rf repo" &&
781 git init repo &&
782 (
783 cd repo &&
784 test_commit default &&
785 git branch branch-1 &&
786 git branch branch-2 &&
787 git tag -a annotated-tag-1 -m tag-1 &&
788 git tag -a annotated-tag-2 -m tag-2 &&
789
790 branch_1_oid=$(git rev-parse branch-1) &&
791 branch_2_oid=$(git rev-parse branch-2) &&
792 tag_1_oid=$(git rev-parse annotated-tag-1) &&
793 tag_2_oid=$(git rev-parse annotated-tag-2) &&
794 tag_1_peeled_oid=$(git rev-parse annotated-tag-1^{}) &&
795 tag_2_peeled_oid=$(git rev-parse annotated-tag-2^{}) &&
796 short_oid=$(printf "%s" $tag_1_peeled_oid | cut -c 1-4) &&
797
798 cat >.git/packed-refs <<-EOF &&
799 # pack-refs with: peeled fully-peeled sorted
800 $short_oid refs/heads/branch-1
801 ${branch_1_oid}x
802 $branch_2_oid refs/heads/bad-branch
803 $branch_2_oid refs/heads/branch.
804 $tag_1_oid refs/tags/annotated-tag-3
805 ^$short_oid
806 $tag_2_oid refs/tags/annotated-tag-4.
807 ^$tag_2_peeled_oid garbage
808 EOF
809 test_must_fail git refs verify 2>err &&
810 cat >expect <<-EOF &&
811 error: packed-refs line 2: badPackedRefEntry: '\''$short_oid refs/heads/branch-1'\'' has invalid oid
812 error: packed-refs line 3: badPackedRefEntry: has no space after oid '\''$branch_1_oid'\'' but with '\''x'\''
813 error: packed-refs line 4: badRefName: has bad refname '\'' refs/heads/bad-branch'\''
814 error: packed-refs line 5: badRefName: has bad refname '\''refs/heads/branch.'\''
815 error: packed-refs line 7: badPackedRefEntry: '\''$short_oid'\'' has invalid peeled oid
816 error: packed-refs line 8: badRefName: has bad refname '\''refs/tags/annotated-tag-4.'\''
817 error: packed-refs line 9: badPackedRefEntry: has trailing garbage after peeled oid '\'' garbage'\''
818 EOF
819 test_cmp expect err
820 )
821 '
822
823 test_expect_success 'packed-ref with sorted trait should be checked' '
824 test_when_finished "rm -rf repo" &&
825 git init repo &&
826 (
827 cd repo &&
828 test_commit default &&
829 git branch branch-1 &&
830 git branch branch-2 &&
831 git tag -a annotated-tag-1 -m tag-1 &&
832 branch_1_oid=$(git rev-parse branch-1) &&
833 branch_2_oid=$(git rev-parse branch-2) &&
834 tag_1_oid=$(git rev-parse annotated-tag-1) &&
835 tag_1_peeled_oid=$(git rev-parse annotated-tag-1^{}) &&
836 refname1="refs/heads/main" &&
837 refname2="refs/heads/foo" &&
838 refname3="refs/tags/foo" &&
839
840 cat >.git/packed-refs <<-EOF &&
841 # pack-refs with: peeled fully-peeled sorted
842 EOF
843 git refs verify 2>err &&
844 rm .git/packed-refs &&
845 test_must_be_empty err &&
846
847 cat >.git/packed-refs <<-EOF &&
848 # pack-refs with: peeled fully-peeled sorted
849 $branch_2_oid $refname1
850 EOF
851 git refs verify 2>err &&
852 rm .git/packed-refs &&
853 test_must_be_empty err &&
854
855 cat >.git/packed-refs <<-EOF &&
856 # pack-refs with: peeled fully-peeled sorted
857 $branch_2_oid $refname1
858 $branch_1_oid $refname2
859 $tag_1_oid $refname3
860 EOF
861 test_must_fail git refs verify 2>err &&
862 cat >expect <<-EOF &&
863 error: packed-refs line 3: packedRefUnsorted: refname '\''$refname2'\'' is less than previous refname '\''$refname1'\''
864 EOF
865 rm .git/packed-refs &&
866 test_cmp expect err &&
867
868 cat >.git/packed-refs <<-EOF &&
869 # pack-refs with: peeled fully-peeled sorted
870 $tag_1_oid $refname3
871 ^$tag_1_peeled_oid
872 $branch_2_oid $refname2
873 EOF
874 test_must_fail git refs verify 2>err &&
875 cat >expect <<-EOF &&
876 error: packed-refs line 4: packedRefUnsorted: refname '\''$refname2'\'' is less than previous refname '\''$refname3'\''
877 EOF
878 rm .git/packed-refs &&
879 test_cmp expect err
880 )
881 '
882
883 test_expect_success 'packed-ref without sorted trait should not be checked' '
884 test_when_finished "rm -rf repo" &&
885 git init repo &&
886 (
887 cd repo &&
888 test_commit default &&
889 git branch branch-1 &&
890 git branch branch-2 &&
891 git tag -a annotated-tag-1 -m tag-1 &&
892 branch_1_oid=$(git rev-parse branch-1) &&
893 branch_2_oid=$(git rev-parse branch-2) &&
894 tag_1_oid=$(git rev-parse annotated-tag-1) &&
895 tag_1_peeled_oid=$(git rev-parse annotated-tag-1^{}) &&
896 refname1="refs/heads/main" &&
897 refname2="refs/heads/foo" &&
898 refname3="refs/tags/foo" &&
899
900 cat >.git/packed-refs <<-EOF &&
901 # pack-refs with: peeled fully-peeled
902 $branch_2_oid $refname1
903 $branch_1_oid $refname2
904 EOF
905 git refs verify 2>err &&
906 test_must_be_empty err
907 )
908 '
909
910 test_expect_success '--[no-]references option should apply to fsck' '
911 test_when_finished "rm -rf repo" &&
912 git init repo &&
913 branch_dir_prefix=.git/refs/heads &&
914 (
915 cd repo &&
916 test_commit default &&
917 for trailing_content in " garbage" " more garbage"
918 do
919 printf "%s" "$(git rev-parse HEAD)$trailing_content" >$branch_dir_prefix/branch-garbage &&
920 git fsck 2>err &&
921 cat >expect <<-EOF &&
922 warning: refs/heads/branch-garbage: trailingRefContent: has trailing garbage: '\''$trailing_content'\''
923 EOF
924 rm $branch_dir_prefix/branch-garbage &&
925 test_cmp expect err || return 1
926 done &&
927
928 for trailing_content in " garbage" " more garbage"
929 do
930 printf "%s" "$(git rev-parse HEAD)$trailing_content" >$branch_dir_prefix/branch-garbage &&
931 git fsck --references 2>err &&
932 cat >expect <<-EOF &&
933 warning: refs/heads/branch-garbage: trailingRefContent: has trailing garbage: '\''$trailing_content'\''
934 EOF
935 rm $branch_dir_prefix/branch-garbage &&
936 test_cmp expect err || return 1
937 done &&
938
939 for trailing_content in " garbage" " more garbage"
940 do
941 printf "%s" "$(git rev-parse HEAD)$trailing_content" >$branch_dir_prefix/branch-garbage &&
942 git fsck --no-references 2>err &&
943 rm $branch_dir_prefix/branch-garbage &&
944 test_must_be_empty err || return 1
945 done
946 )
947 '
948
949 test_expect_success 'complains about broken root ref' '
950 test_when_finished "rm -rf repo" &&
951 git init repo &&
952 (
953 cd repo &&
954 echo "ref: refs/heads/../HEAD" >.git/HEAD &&
955 test_must_fail git refs verify 2>err &&
956 cat >expect <<-EOF &&
957 error: HEAD: badReferentName: points to invalid refname ${SQ}refs/heads/../HEAD${SQ}
958 EOF
959 test_cmp expect err
960 )
961 '
962
963 test_expect_success 'complains about broken root ref in worktree' '
964 test_when_finished "rm -rf repo worktree" &&
965 git init repo &&
966 (
967 cd repo &&
968 test_commit initial &&
969 git worktree add ../worktree &&
970 echo "ref: refs/heads/../HEAD" >.git/worktrees/worktree/HEAD &&
971 test_must_fail git refs verify 2>err &&
972 cat >expect <<-EOF &&
973 error: worktrees/worktree/HEAD: badReferentName: points to invalid refname ${SQ}refs/heads/../HEAD${SQ}
974 EOF
975 test_cmp expect err
976 )
977 '
978
979 test_done