]> git.ipfire.org Git - thirdparty/git.git/blob - t/t0610-reftable-basics.sh
Merge branch 'ml/log-merge-with-cherry-pick-and-other-pseudo-heads'
[thirdparty/git.git] / t / t0610-reftable-basics.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2020 Google LLC
4 #
5
6 test_description='reftable basics'
7 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
8 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
9
10 . ./test-lib.sh
11
12 if ! test_have_prereq REFTABLE
13 then
14 skip_all='skipping reftable tests; set GIT_TEST_DEFAULT_REF_FORMAT=reftable'
15 test_done
16 fi
17
18 INVALID_OID=$(test_oid 001)
19
20 test_expect_success 'init: creates basic reftable structures' '
21 test_when_finished "rm -rf repo" &&
22 git init repo &&
23 test_path_is_dir repo/.git/reftable &&
24 test_path_is_file repo/.git/reftable/tables.list &&
25 echo reftable >expect &&
26 git -C repo rev-parse --show-ref-format >actual &&
27 test_cmp expect actual
28 '
29
30 test_expect_success 'init: sha256 object format via environment variable' '
31 test_when_finished "rm -rf repo" &&
32 GIT_DEFAULT_HASH=sha256 git init repo &&
33 cat >expect <<-EOF &&
34 sha256
35 reftable
36 EOF
37 git -C repo rev-parse --show-object-format --show-ref-format >actual &&
38 test_cmp expect actual
39 '
40
41 test_expect_success 'init: sha256 object format via option' '
42 test_when_finished "rm -rf repo" &&
43 git init --object-format=sha256 repo &&
44 cat >expect <<-EOF &&
45 sha256
46 reftable
47 EOF
48 git -C repo rev-parse --show-object-format --show-ref-format >actual &&
49 test_cmp expect actual
50 '
51
52 test_expect_success 'init: reinitializing reftable backend succeeds' '
53 test_when_finished "rm -rf repo" &&
54 git init repo &&
55 test_commit -C repo A &&
56
57 git -C repo for-each-ref >expect &&
58 git init --ref-format=reftable repo &&
59 git -C repo for-each-ref >actual &&
60 test_cmp expect actual
61 '
62
63 test_expect_success 'init: reinitializing files with reftable backend fails' '
64 test_when_finished "rm -rf repo" &&
65 git init --ref-format=files repo &&
66 test_commit -C repo file &&
67
68 cp repo/.git/HEAD expect &&
69 test_must_fail git init --ref-format=reftable repo &&
70 test_cmp expect repo/.git/HEAD
71 '
72
73 test_expect_success 'init: reinitializing reftable with files backend fails' '
74 test_when_finished "rm -rf repo" &&
75 git init --ref-format=reftable repo &&
76 test_commit -C repo file &&
77
78 cp repo/.git/HEAD expect &&
79 test_must_fail git init --ref-format=files repo &&
80 test_cmp expect repo/.git/HEAD
81 '
82
83 test_expect_perms () {
84 local perms="$1"
85 local file="$2"
86 local actual=$(ls -l "$file") &&
87
88 case "$actual" in
89 $perms*)
90 : happy
91 ;;
92 *)
93 echo "$(basename $2) is not $perms but $actual"
94 false
95 ;;
96 esac
97 }
98
99 for umask in 002 022
100 do
101 test_expect_success POSIXPERM 'init: honors core.sharedRepository' '
102 test_when_finished "rm -rf repo" &&
103 (
104 umask $umask &&
105 git init --shared=true repo &&
106 test 1 = "$(git -C repo config core.sharedrepository)"
107 ) &&
108 test_expect_perms "-rw-rw-r--" repo/.git/reftable/tables.list &&
109 for table in repo/.git/reftable/*.ref
110 do
111 test_expect_perms "-rw-rw-r--" "$table" ||
112 return 1
113 done
114 '
115 done
116
117 test_expect_success 'clone: can clone reftable repository' '
118 test_when_finished "rm -rf repo clone" &&
119 git init repo &&
120 test_commit -C repo message1 file1 &&
121
122 git clone repo cloned &&
123 echo reftable >expect &&
124 git -C cloned rev-parse --show-ref-format >actual &&
125 test_cmp expect actual &&
126 test_path_is_file cloned/file1
127 '
128
129 test_expect_success 'clone: can clone reffiles into reftable repository' '
130 test_when_finished "rm -rf reffiles reftable" &&
131 git init --ref-format=files reffiles &&
132 test_commit -C reffiles A &&
133 git clone --ref-format=reftable ./reffiles reftable &&
134
135 git -C reffiles rev-parse HEAD >expect &&
136 git -C reftable rev-parse HEAD >actual &&
137 test_cmp expect actual &&
138
139 git -C reftable rev-parse --show-ref-format >actual &&
140 echo reftable >expect &&
141 test_cmp expect actual &&
142
143 git -C reffiles rev-parse --show-ref-format >actual &&
144 echo files >expect &&
145 test_cmp expect actual
146 '
147
148 test_expect_success 'clone: can clone reftable into reffiles repository' '
149 test_when_finished "rm -rf reffiles reftable" &&
150 git init --ref-format=reftable reftable &&
151 test_commit -C reftable A &&
152 git clone --ref-format=files ./reftable reffiles &&
153
154 git -C reftable rev-parse HEAD >expect &&
155 git -C reffiles rev-parse HEAD >actual &&
156 test_cmp expect actual &&
157
158 git -C reftable rev-parse --show-ref-format >actual &&
159 echo reftable >expect &&
160 test_cmp expect actual &&
161
162 git -C reffiles rev-parse --show-ref-format >actual &&
163 echo files >expect &&
164 test_cmp expect actual
165 '
166
167 test_expect_success 'ref transaction: corrupted tables cause failure' '
168 test_when_finished "rm -rf repo" &&
169 git init repo &&
170 (
171 cd repo &&
172 test_commit file1 &&
173 for f in .git/reftable/*.ref
174 do
175 : >"$f" || return 1
176 done &&
177 test_must_fail git update-ref refs/heads/main HEAD
178 )
179 '
180
181 test_expect_success 'ref transaction: corrupted tables.list cause failure' '
182 test_when_finished "rm -rf repo" &&
183 git init repo &&
184 (
185 cd repo &&
186 test_commit file1 &&
187 echo garbage >.git/reftable/tables.list &&
188 test_must_fail git update-ref refs/heads/main HEAD
189 )
190 '
191
192 test_expect_success 'ref transaction: refuses to write ref causing F/D conflict' '
193 test_when_finished "rm -rf repo" &&
194 git init repo &&
195 test_commit -C repo file &&
196 test_must_fail git -C repo update-ref refs/heads/main/forbidden
197 '
198
199 test_expect_success 'ref transaction: deleting ref with invalid name fails' '
200 test_when_finished "rm -rf repo" &&
201 git init repo &&
202 test_commit -C repo file &&
203 test_must_fail git -C repo update-ref -d ../../my-private-file
204 '
205
206 test_expect_success 'ref transaction: can skip object ID verification' '
207 test_when_finished "rm -rf repo" &&
208 git init repo &&
209 test_must_fail test-tool -C repo ref-store main update-ref msg refs/heads/branch $INVALID_OID $ZERO_OID 0 &&
210 test-tool -C repo ref-store main update-ref msg refs/heads/branch $INVALID_OID $ZERO_OID REF_SKIP_OID_VERIFICATION
211 '
212
213 test_expect_success 'ref transaction: updating same ref multiple times fails' '
214 test_when_finished "rm -rf repo" &&
215 git init repo &&
216 test_commit -C repo A &&
217 cat >updates <<-EOF &&
218 update refs/heads/main $A
219 update refs/heads/main $A
220 EOF
221 cat >expect <<-EOF &&
222 fatal: multiple updates for ref ${SQ}refs/heads/main${SQ} not allowed
223 EOF
224 test_must_fail git -C repo update-ref --stdin <updates 2>err &&
225 test_cmp expect err
226 '
227
228 test_expect_success 'ref transaction: can delete symbolic self-reference with git-symbolic-ref(1)' '
229 test_when_finished "rm -rf repo" &&
230 git init repo &&
231 git -C repo symbolic-ref refs/heads/self refs/heads/self &&
232 git -C repo symbolic-ref -d refs/heads/self
233 '
234
235 test_expect_success 'ref transaction: deleting symbolic self-reference without --no-deref fails' '
236 test_when_finished "rm -rf repo" &&
237 git init repo &&
238 git -C repo symbolic-ref refs/heads/self refs/heads/self &&
239 cat >expect <<-EOF &&
240 error: multiple updates for ${SQ}refs/heads/self${SQ} (including one via symref ${SQ}refs/heads/self${SQ}) are not allowed
241 EOF
242 test_must_fail git -C repo update-ref -d refs/heads/self 2>err &&
243 test_cmp expect err
244 '
245
246 test_expect_success 'ref transaction: deleting symbolic self-reference with --no-deref succeeds' '
247 test_when_finished "rm -rf repo" &&
248 git init repo &&
249 git -C repo symbolic-ref refs/heads/self refs/heads/self &&
250 git -C repo update-ref -d --no-deref refs/heads/self
251 '
252
253 test_expect_success 'ref transaction: creating symbolic ref fails with F/D conflict' '
254 test_when_finished "rm -rf repo" &&
255 git init repo &&
256 test_commit -C repo A &&
257 cat >expect <<-EOF &&
258 error: unable to write symref for refs/heads: file/directory conflict
259 EOF
260 test_must_fail git -C repo symbolic-ref refs/heads refs/heads/foo 2>err &&
261 test_cmp expect err
262 '
263
264 test_expect_success 'ref transaction: ref deletion' '
265 test_when_finished "rm -rf repo" &&
266 git init repo &&
267 (
268 cd repo &&
269 test_commit file &&
270 HEAD_OID=$(git show-ref -s --verify HEAD) &&
271 cat >expect <<-EOF &&
272 $HEAD_OID refs/heads/main
273 $HEAD_OID refs/tags/file
274 EOF
275 git show-ref >actual &&
276 test_cmp expect actual &&
277
278 test_must_fail git update-ref -d refs/tags/file $INVALID_OID &&
279 git show-ref >actual &&
280 test_cmp expect actual &&
281
282 git update-ref -d refs/tags/file $HEAD_OID &&
283 echo "$HEAD_OID refs/heads/main" >expect &&
284 git show-ref >actual &&
285 test_cmp expect actual
286 )
287 '
288
289 test_expect_success 'ref transaction: writes cause auto-compaction' '
290 test_when_finished "rm -rf repo" &&
291
292 git init repo &&
293 test_line_count = 1 repo/.git/reftable/tables.list &&
294
295 test_commit -C repo --no-tag A &&
296 test_line_count = 2 repo/.git/reftable/tables.list &&
297
298 test_commit -C repo --no-tag B &&
299 test_line_count = 1 repo/.git/reftable/tables.list
300 '
301
302 check_fsync_events () {
303 local trace="$1" &&
304 shift &&
305
306 cat >expect &&
307 sed -n \
308 -e '/^{"event":"counter",.*"category":"fsync",/ {
309 s/.*"category":"fsync",//;
310 s/}$//;
311 p;
312 }' \
313 <"$trace" >actual &&
314 test_cmp expect actual
315 }
316
317 test_expect_success 'ref transaction: writes are synced' '
318 test_when_finished "rm -rf repo" &&
319 git init repo &&
320 test_commit -C repo initial &&
321
322 GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
323 GIT_TEST_FSYNC=true \
324 git -C repo -c core.fsync=reference \
325 -c core.fsyncMethod=fsync update-ref refs/heads/branch HEAD &&
326 check_fsync_events trace2.txt <<-EOF
327 "name":"hardware-flush","count":2
328 EOF
329 '
330
331 test_expect_success 'pack-refs: compacts tables' '
332 test_when_finished "rm -rf repo" &&
333 git init repo &&
334
335 test_commit -C repo A &&
336 ls -1 repo/.git/reftable >table-files &&
337 test_line_count = 4 table-files &&
338 test_line_count = 3 repo/.git/reftable/tables.list &&
339
340 git -C repo pack-refs &&
341 ls -1 repo/.git/reftable >table-files &&
342 test_line_count = 2 table-files &&
343 test_line_count = 1 repo/.git/reftable/tables.list
344 '
345
346 test_expect_success 'pack-refs: prunes stale tables' '
347 test_when_finished "rm -rf repo" &&
348 git init repo &&
349 touch repo/.git/reftable/stale-table.ref &&
350 git -C repo pack-refs &&
351 test_path_is_missing repo/.git/reftable/stable-ref.ref
352 '
353
354 test_expect_success 'pack-refs: does not prune non-table files' '
355 test_when_finished "rm -rf repo" &&
356 git init repo &&
357 touch repo/.git/reftable/garbage &&
358 git -C repo pack-refs &&
359 test_path_is_file repo/.git/reftable/garbage
360 '
361
362 for umask in 002 022
363 do
364 test_expect_success POSIXPERM 'pack-refs: honors core.sharedRepository' '
365 test_when_finished "rm -rf repo" &&
366 (
367 umask $umask &&
368 git init --shared=true repo &&
369 test_commit -C repo A &&
370 test_line_count = 3 repo/.git/reftable/tables.list
371 ) &&
372 git -C repo pack-refs &&
373 test_expect_perms "-rw-rw-r--" repo/.git/reftable/tables.list &&
374 for table in repo/.git/reftable/*.ref
375 do
376 test_expect_perms "-rw-rw-r--" "$table" ||
377 return 1
378 done
379 '
380 done
381
382 test_expect_success 'packed-refs: writes are synced' '
383 test_when_finished "rm -rf repo" &&
384 git init repo &&
385 test_commit -C repo initial &&
386 test_line_count = 2 table-files &&
387
388 : >trace2.txt &&
389 GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
390 GIT_TEST_FSYNC=true \
391 git -C repo -c core.fsync=reference \
392 -c core.fsyncMethod=fsync pack-refs &&
393 check_fsync_events trace2.txt <<-EOF
394 "name":"hardware-flush","count":2
395 EOF
396 '
397
398 test_expect_success 'ref iterator: bogus names are flagged' '
399 test_when_finished "rm -rf repo" &&
400 git init repo &&
401 (
402 cd repo &&
403 test_commit --no-tag file &&
404 test-tool ref-store main update-ref msg "refs/heads/bogus..name" $(git rev-parse HEAD) $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
405
406 cat >expect <<-EOF &&
407 $ZERO_OID refs/heads/bogus..name 0xc
408 $(git rev-parse HEAD) refs/heads/main 0x0
409 EOF
410 test-tool ref-store main for-each-ref "" >actual &&
411 test_cmp expect actual
412 )
413 '
414
415 test_expect_success 'ref iterator: missing object IDs are not flagged' '
416 test_when_finished "rm -rf repo" &&
417 git init repo &&
418 (
419 cd repo &&
420 test-tool ref-store main update-ref msg "refs/heads/broken-hash" $INVALID_OID $ZERO_OID REF_SKIP_OID_VERIFICATION &&
421
422 cat >expect <<-EOF &&
423 $INVALID_OID refs/heads/broken-hash 0x0
424 EOF
425 test-tool ref-store main for-each-ref "" >actual &&
426 test_cmp expect actual
427 )
428 '
429
430 test_expect_success 'basic: commit and list refs' '
431 test_when_finished "rm -rf repo" &&
432 git init repo &&
433 test_commit -C repo file &&
434 test_write_lines refs/heads/main refs/tags/file >expect &&
435 git -C repo for-each-ref --format="%(refname)" >actual &&
436 test_cmp actual expect
437 '
438
439 test_expect_success 'basic: can write large commit message' '
440 test_when_finished "rm -rf repo" &&
441 git init repo &&
442 perl -e "
443 print \"this is a long commit message\" x 50000
444 " >commit-msg &&
445 git -C repo commit --allow-empty --file=../commit-msg
446 '
447
448 test_expect_success 'basic: show-ref fails with empty repository' '
449 test_when_finished "rm -rf repo" &&
450 git init repo &&
451 test_must_fail git -C repo show-ref >actual &&
452 test_must_be_empty actual
453 '
454
455 test_expect_success 'basic: can check out unborn branch' '
456 test_when_finished "rm -rf repo" &&
457 git init repo &&
458 git -C repo checkout -b main
459 '
460
461 test_expect_success 'basic: peeled tags are stored' '
462 test_when_finished "rm -rf repo" &&
463 git init repo &&
464 test_commit -C repo file &&
465 git -C repo tag -m "annotated tag" test_tag HEAD &&
466 for ref in refs/heads/main refs/tags/file refs/tags/test_tag refs/tags/test_tag^{}
467 do
468 echo "$(git -C repo rev-parse "$ref") $ref" || return 1
469 done >expect &&
470 git -C repo show-ref -d >actual &&
471 test_cmp expect actual
472 '
473
474 test_expect_success 'basic: for-each-ref can print symrefs' '
475 test_when_finished "rm -rf repo" &&
476 git init repo &&
477 (
478 cd repo &&
479 test_commit file &&
480 git branch &&
481 git symbolic-ref refs/heads/sym refs/heads/main &&
482 cat >expected <<-EOF &&
483 refs/heads/main
484 EOF
485 git for-each-ref --format="%(symref)" refs/heads/sym >actual &&
486 test_cmp expected actual
487 )
488 '
489
490 test_expect_success 'basic: notes' '
491 test_when_finished "rm -rf repo" &&
492 git init repo &&
493 (
494 write_script fake_editor <<-\EOF &&
495 echo "$MSG" >"$1"
496 echo "$MSG" >&2
497 EOF
498
499 test_commit 1st &&
500 test_commit 2nd &&
501 GIT_EDITOR=./fake_editor MSG=b4 git notes add &&
502 GIT_EDITOR=./fake_editor MSG=b3 git notes edit &&
503 echo b4 >expect &&
504 git notes --ref commits@{1} show >actual &&
505 test_cmp expect actual
506 )
507 '
508
509 test_expect_success 'basic: stash' '
510 test_when_finished "rm -rf repo" &&
511 git init repo &&
512 (
513 cd repo &&
514 test_commit file &&
515 git stash list >expect &&
516 test_line_count = 0 expect &&
517
518 echo hoi >>file.t &&
519 git stash push -m stashed &&
520 git stash list >expect &&
521 test_line_count = 1 expect &&
522
523 git stash clear &&
524 git stash list >expect &&
525 test_line_count = 0 expect
526 )
527 '
528
529 test_expect_success 'basic: cherry-pick' '
530 test_when_finished "rm -rf repo" &&
531 git init repo &&
532 (
533 cd repo &&
534 test_commit message1 file1 &&
535 test_commit message2 file2 &&
536 git branch source &&
537 git checkout HEAD^ &&
538 test_commit message3 file3 &&
539 git cherry-pick source &&
540 test_path_is_file file2
541 )
542 '
543
544 test_expect_success 'basic: rebase' '
545 test_when_finished "rm -rf repo" &&
546 git init repo &&
547 (
548 cd repo &&
549 test_commit message1 file1 &&
550 test_commit message2 file2 &&
551 git branch source &&
552 git checkout HEAD^ &&
553 test_commit message3 file3 &&
554 git rebase source &&
555 test_path_is_file file2
556 )
557 '
558
559 test_expect_success 'reflog: can delete separate reflog entries' '
560 test_when_finished "rm -rf repo" &&
561 git init repo &&
562 (
563 cd repo &&
564
565 test_commit file &&
566 test_commit file2 &&
567 test_commit file3 &&
568 test_commit file4 &&
569 git reflog >actual &&
570 grep file3 actual &&
571
572 git reflog delete HEAD@{1} &&
573 git reflog >actual &&
574 ! grep file3 actual
575 )
576 '
577
578 test_expect_success 'reflog: can switch to previous branch' '
579 test_when_finished "rm -rf repo" &&
580 git init repo &&
581 (
582 cd repo &&
583 test_commit file1 &&
584 git checkout -b branch1 &&
585 test_commit file2 &&
586 git checkout -b branch2 &&
587 git switch - &&
588 git rev-parse --symbolic-full-name HEAD >actual &&
589 echo refs/heads/branch1 >expect &&
590 test_cmp actual expect
591 )
592 '
593
594 test_expect_success 'reflog: copying branch writes reflog entry' '
595 test_when_finished "rm -rf repo" &&
596 git init repo &&
597 (
598 cd repo &&
599 test_commit file1 &&
600 test_commit file2 &&
601 oid=$(git rev-parse --short HEAD) &&
602 git branch src &&
603 cat >expect <<-EOF &&
604 ${oid} dst@{0}: Branch: copied refs/heads/src to refs/heads/dst
605 ${oid} dst@{1}: branch: Created from main
606 EOF
607 git branch -c src dst &&
608 git reflog dst >actual &&
609 test_cmp expect actual
610 )
611 '
612
613 test_expect_success 'reflog: renaming branch writes reflog entry' '
614 test_when_finished "rm -rf repo" &&
615 git init repo &&
616 (
617 cd repo &&
618 git symbolic-ref HEAD refs/heads/before &&
619 test_commit file &&
620 git show-ref >expected.refs &&
621 sed s/before/after/g <expected.refs >expected &&
622 git branch -M after &&
623 git show-ref >actual &&
624 test_cmp expected actual &&
625 echo refs/heads/after >expected &&
626 git symbolic-ref HEAD >actual &&
627 test_cmp expected actual
628 )
629 '
630
631 test_expect_success 'reflog: can store empty logs' '
632 test_when_finished "rm -rf repo" &&
633 git init repo &&
634 (
635 cd repo &&
636
637 test_must_fail test-tool ref-store main reflog-exists refs/heads/branch &&
638 test-tool ref-store main create-reflog refs/heads/branch &&
639 test-tool ref-store main reflog-exists refs/heads/branch &&
640 test-tool ref-store main for-each-reflog-ent-reverse refs/heads/branch >actual &&
641 test_must_be_empty actual
642 )
643 '
644
645 test_expect_success 'reflog: expiry empties reflog' '
646 test_when_finished "rm -rf repo" &&
647 git init repo &&
648 (
649 cd repo &&
650
651 test_commit initial &&
652 git checkout -b branch &&
653 test_commit fileA &&
654 test_commit fileB &&
655
656 cat >expect <<-EOF &&
657 commit: fileB
658 commit: fileA
659 branch: Created from HEAD
660 EOF
661 git reflog show --format="%gs" refs/heads/branch >actual &&
662 test_cmp expect actual &&
663
664 git reflog expire branch --expire=all &&
665 git reflog show --format="%gs" refs/heads/branch >actual &&
666 test_must_be_empty actual &&
667 test-tool ref-store main reflog-exists refs/heads/branch
668 )
669 '
670
671 test_expect_success 'reflog: can be deleted' '
672 test_when_finished "rm -rf repo" &&
673 git init repo &&
674 (
675 cd repo &&
676 test_commit initial &&
677 test-tool ref-store main reflog-exists refs/heads/main &&
678 test-tool ref-store main delete-reflog refs/heads/main &&
679 test_must_fail test-tool ref-store main reflog-exists refs/heads/main
680 )
681 '
682
683 test_expect_success 'reflog: garbage collection deletes reflog entries' '
684 test_when_finished "rm -rf repo" &&
685 git init repo &&
686 (
687 cd repo &&
688
689 for count in $(test_seq 1 10)
690 do
691 test_commit "number $count" file.t $count number-$count ||
692 return 1
693 done &&
694 git reflog refs/heads/main >actual &&
695 test_line_count = 10 actual &&
696 grep "commit (initial): number 1" actual &&
697 grep "commit: number 10" actual &&
698
699 git gc &&
700 git reflog refs/heads/main >actual &&
701 test_line_count = 0 actual
702 )
703 '
704
705 test_expect_success 'reflog: updates via HEAD update HEAD reflog' '
706 test_when_finished "rm -rf repo" &&
707 git init repo &&
708 (
709 cd repo &&
710 test_commit main-one &&
711 git checkout -b new-branch &&
712 test_commit new-one &&
713 test_commit new-two &&
714
715 echo new-one >expect &&
716 git log -1 --format=%s HEAD@{1} >actual &&
717 test_cmp expect actual
718 )
719 '
720
721 test_expect_success 'worktree: adding worktree creates separate stack' '
722 test_when_finished "rm -rf repo worktree" &&
723 git init repo &&
724 test_commit -C repo A &&
725
726 git -C repo worktree add ../worktree &&
727 test_path_is_file repo/.git/worktrees/worktree/refs/heads &&
728 echo "ref: refs/heads/.invalid" >expect &&
729 test_cmp expect repo/.git/worktrees/worktree/HEAD &&
730 test_path_is_dir repo/.git/worktrees/worktree/reftable &&
731 test_path_is_file repo/.git/worktrees/worktree/reftable/tables.list
732 '
733
734 test_expect_success 'worktree: pack-refs in main repo packs main refs' '
735 test_when_finished "rm -rf repo worktree" &&
736 git init repo &&
737 test_commit -C repo A &&
738 git -C repo worktree add ../worktree &&
739
740 test_line_count = 3 repo/.git/worktrees/worktree/reftable/tables.list &&
741 test_line_count = 4 repo/.git/reftable/tables.list &&
742 git -C repo pack-refs &&
743 test_line_count = 3 repo/.git/worktrees/worktree/reftable/tables.list &&
744 test_line_count = 1 repo/.git/reftable/tables.list
745 '
746
747 test_expect_success 'worktree: pack-refs in worktree packs worktree refs' '
748 test_when_finished "rm -rf repo worktree" &&
749 git init repo &&
750 test_commit -C repo A &&
751 git -C repo worktree add ../worktree &&
752
753 test_line_count = 3 repo/.git/worktrees/worktree/reftable/tables.list &&
754 test_line_count = 4 repo/.git/reftable/tables.list &&
755 git -C worktree pack-refs &&
756 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
757 test_line_count = 4 repo/.git/reftable/tables.list
758 '
759
760 test_expect_success 'worktree: creating shared ref updates main stack' '
761 test_when_finished "rm -rf repo worktree" &&
762 git init repo &&
763 test_commit -C repo A &&
764
765 git -C repo worktree add ../worktree &&
766 git -C repo pack-refs &&
767 git -C worktree pack-refs &&
768 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
769 test_line_count = 1 repo/.git/reftable/tables.list &&
770
771 git -C worktree update-ref refs/heads/shared HEAD &&
772 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
773 test_line_count = 2 repo/.git/reftable/tables.list
774 '
775
776 test_expect_success 'worktree: creating per-worktree ref updates worktree stack' '
777 test_when_finished "rm -rf repo worktree" &&
778 git init repo &&
779 test_commit -C repo A &&
780
781 git -C repo worktree add ../worktree &&
782 git -C repo pack-refs &&
783 git -C worktree pack-refs &&
784 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
785 test_line_count = 1 repo/.git/reftable/tables.list &&
786
787 git -C worktree update-ref refs/bisect/per-worktree HEAD &&
788 test_line_count = 2 repo/.git/worktrees/worktree/reftable/tables.list &&
789 test_line_count = 1 repo/.git/reftable/tables.list
790 '
791
792 test_expect_success 'worktree: creating per-worktree ref from main repo' '
793 test_when_finished "rm -rf repo worktree" &&
794 git init repo &&
795 test_commit -C repo A &&
796
797 git -C repo worktree add ../worktree &&
798 git -C repo pack-refs &&
799 git -C worktree pack-refs &&
800 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
801 test_line_count = 1 repo/.git/reftable/tables.list &&
802
803 git -C repo update-ref worktrees/worktree/refs/bisect/per-worktree HEAD &&
804 test_line_count = 2 repo/.git/worktrees/worktree/reftable/tables.list &&
805 test_line_count = 1 repo/.git/reftable/tables.list
806 '
807
808 test_expect_success 'worktree: creating per-worktree ref from second worktree' '
809 test_when_finished "rm -rf repo wt1 wt2" &&
810 git init repo &&
811 test_commit -C repo A &&
812
813 git -C repo worktree add ../wt1 &&
814 git -C repo worktree add ../wt2 &&
815 git -C repo pack-refs &&
816 git -C wt1 pack-refs &&
817 git -C wt2 pack-refs &&
818 test_line_count = 1 repo/.git/worktrees/wt1/reftable/tables.list &&
819 test_line_count = 1 repo/.git/worktrees/wt2/reftable/tables.list &&
820 test_line_count = 1 repo/.git/reftable/tables.list &&
821
822 git -C wt1 update-ref worktrees/wt2/refs/bisect/per-worktree HEAD &&
823 test_line_count = 1 repo/.git/worktrees/wt1/reftable/tables.list &&
824 test_line_count = 2 repo/.git/worktrees/wt2/reftable/tables.list &&
825 test_line_count = 1 repo/.git/reftable/tables.list
826 '
827
828 test_expect_success 'worktree: can create shared and per-worktree ref in one transaction' '
829 test_when_finished "rm -rf repo worktree" &&
830 git init repo &&
831 test_commit -C repo A &&
832
833 git -C repo worktree add ../worktree &&
834 git -C repo pack-refs &&
835 git -C worktree pack-refs &&
836 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
837 test_line_count = 1 repo/.git/reftable/tables.list &&
838
839 cat >stdin <<-EOF &&
840 create worktrees/worktree/refs/bisect/per-worktree HEAD
841 create refs/branches/shared HEAD
842 EOF
843 git -C repo update-ref --stdin <stdin &&
844 test_line_count = 2 repo/.git/worktrees/worktree/reftable/tables.list &&
845 test_line_count = 2 repo/.git/reftable/tables.list
846 '
847
848 test_expect_success 'worktree: can access common refs' '
849 test_when_finished "rm -rf repo worktree" &&
850 git init repo &&
851 test_commit -C repo file1 &&
852 git -C repo branch branch1 &&
853 git -C repo worktree add ../worktree &&
854
855 echo refs/heads/worktree >expect &&
856 git -C worktree symbolic-ref HEAD >actual &&
857 test_cmp expect actual &&
858 git -C worktree checkout branch1
859 '
860
861 test_expect_success 'worktree: adds worktree with detached HEAD' '
862 test_when_finished "rm -rf repo worktree" &&
863
864 git init repo &&
865 test_commit -C repo A &&
866 git -C repo rev-parse main >expect &&
867
868 git -C repo worktree add --detach ../worktree main &&
869 git -C worktree rev-parse HEAD >actual &&
870 test_cmp expect actual
871 '
872
873 test_expect_success 'fetch: accessing FETCH_HEAD special ref works' '
874 test_when_finished "rm -rf repo sub" &&
875
876 git init sub &&
877 test_commit -C sub two &&
878 git -C sub rev-parse HEAD >expect &&
879
880 git init repo &&
881 test_commit -C repo one &&
882 git -C repo fetch ../sub &&
883 git -C repo rev-parse FETCH_HEAD >actual &&
884 test_cmp expect actual
885 '
886
887 test_done