]> git.ipfire.org Git - thirdparty/git.git/blame - t/t0610-reftable-basics.sh
Merge branch 'ps/reftable-repo-init-fix'
[thirdparty/git.git] / t / t0610-reftable-basics.sh
CommitLineData
57db2a09
PS
1#!/bin/sh
2#
3# Copyright (c) 2020 Google LLC
4#
5
6test_description='reftable basics'
7GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
8export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
9
10. ./test-lib.sh
11
12if ! test_have_prereq REFTABLE
13then
14 skip_all='skipping reftable tests; set GIT_TEST_DEFAULT_REF_FORMAT=reftable'
15 test_done
16fi
17
18INVALID_OID=$(test_oid 001)
19
20test_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
30test_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
41test_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
52test_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
63test_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
73test_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
83test_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
99for umask in 002 022
100do
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 '
115done
116
117test_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
129test_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
148test_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
167test_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
181test_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
192test_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
199test_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
206test_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
213test_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
228test_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
235test_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
246test_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
253test_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
264test_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
289test_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
302check_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
317test_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
b0f6b6b5
PS
331test_expect_success 'ref transaction: empty transaction in empty repo' '
332 test_when_finished "rm -rf repo" &&
333 git init repo &&
334 test_commit -C repo --no-tag A &&
b0f6b6b5
PS
335 git -C repo update-ref -d refs/heads/main &&
336 test-tool -C repo ref-store main delete-refs REF_NO_DEREF msg HEAD &&
337 git -C repo update-ref --stdin <<-EOF
338 prepare
339 commit
340 EOF
341'
342
57db2a09
PS
343test_expect_success 'pack-refs: compacts tables' '
344 test_when_finished "rm -rf repo" &&
345 git init repo &&
346
347 test_commit -C repo A &&
348 ls -1 repo/.git/reftable >table-files &&
349 test_line_count = 4 table-files &&
350 test_line_count = 3 repo/.git/reftable/tables.list &&
351
352 git -C repo pack-refs &&
353 ls -1 repo/.git/reftable >table-files &&
354 test_line_count = 2 table-files &&
355 test_line_count = 1 repo/.git/reftable/tables.list
356'
357
358test_expect_success 'pack-refs: prunes stale tables' '
359 test_when_finished "rm -rf repo" &&
360 git init repo &&
361 touch repo/.git/reftable/stale-table.ref &&
362 git -C repo pack-refs &&
363 test_path_is_missing repo/.git/reftable/stable-ref.ref
364'
365
366test_expect_success 'pack-refs: does not prune non-table files' '
367 test_when_finished "rm -rf repo" &&
368 git init repo &&
369 touch repo/.git/reftable/garbage &&
370 git -C repo pack-refs &&
371 test_path_is_file repo/.git/reftable/garbage
372'
373
374for umask in 002 022
375do
376 test_expect_success POSIXPERM 'pack-refs: honors core.sharedRepository' '
377 test_when_finished "rm -rf repo" &&
378 (
379 umask $umask &&
380 git init --shared=true repo &&
381 test_commit -C repo A &&
382 test_line_count = 3 repo/.git/reftable/tables.list
383 ) &&
384 git -C repo pack-refs &&
385 test_expect_perms "-rw-rw-r--" repo/.git/reftable/tables.list &&
386 for table in repo/.git/reftable/*.ref
387 do
388 test_expect_perms "-rw-rw-r--" "$table" ||
389 return 1
390 done
391 '
392done
393
394test_expect_success 'packed-refs: writes are synced' '
395 test_when_finished "rm -rf repo" &&
396 git init repo &&
397 test_commit -C repo initial &&
398 test_line_count = 2 table-files &&
399
400 : >trace2.txt &&
401 GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
402 GIT_TEST_FSYNC=true \
403 git -C repo -c core.fsync=reference \
404 -c core.fsyncMethod=fsync pack-refs &&
405 check_fsync_events trace2.txt <<-EOF
406 "name":"hardware-flush","count":2
407 EOF
408'
409
410test_expect_success 'ref iterator: bogus names are flagged' '
411 test_when_finished "rm -rf repo" &&
412 git init repo &&
413 (
414 cd repo &&
415 test_commit --no-tag file &&
416 test-tool ref-store main update-ref msg "refs/heads/bogus..name" $(git rev-parse HEAD) $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
417
418 cat >expect <<-EOF &&
419 $ZERO_OID refs/heads/bogus..name 0xc
420 $(git rev-parse HEAD) refs/heads/main 0x0
421 EOF
422 test-tool ref-store main for-each-ref "" >actual &&
423 test_cmp expect actual
424 )
425'
426
427test_expect_success 'ref iterator: missing object IDs are not flagged' '
428 test_when_finished "rm -rf repo" &&
429 git init repo &&
430 (
431 cd repo &&
432 test-tool ref-store main update-ref msg "refs/heads/broken-hash" $INVALID_OID $ZERO_OID REF_SKIP_OID_VERIFICATION &&
433
434 cat >expect <<-EOF &&
435 $INVALID_OID refs/heads/broken-hash 0x0
436 EOF
437 test-tool ref-store main for-each-ref "" >actual &&
438 test_cmp expect actual
439 )
440'
441
442test_expect_success 'basic: commit and list refs' '
443 test_when_finished "rm -rf repo" &&
444 git init repo &&
445 test_commit -C repo file &&
446 test_write_lines refs/heads/main refs/tags/file >expect &&
447 git -C repo for-each-ref --format="%(refname)" >actual &&
448 test_cmp actual expect
449'
450
451test_expect_success 'basic: can write large commit message' '
452 test_when_finished "rm -rf repo" &&
453 git init repo &&
454 perl -e "
455 print \"this is a long commit message\" x 50000
456 " >commit-msg &&
457 git -C repo commit --allow-empty --file=../commit-msg
458'
459
460test_expect_success 'basic: show-ref fails with empty repository' '
461 test_when_finished "rm -rf repo" &&
462 git init repo &&
463 test_must_fail git -C repo show-ref >actual &&
464 test_must_be_empty actual
465'
466
467test_expect_success 'basic: can check out unborn branch' '
468 test_when_finished "rm -rf repo" &&
469 git init repo &&
470 git -C repo checkout -b main
471'
472
473test_expect_success 'basic: peeled tags are stored' '
474 test_when_finished "rm -rf repo" &&
475 git init repo &&
476 test_commit -C repo file &&
477 git -C repo tag -m "annotated tag" test_tag HEAD &&
478 for ref in refs/heads/main refs/tags/file refs/tags/test_tag refs/tags/test_tag^{}
479 do
480 echo "$(git -C repo rev-parse "$ref") $ref" || return 1
481 done >expect &&
482 git -C repo show-ref -d >actual &&
483 test_cmp expect actual
484'
485
486test_expect_success 'basic: for-each-ref can print symrefs' '
487 test_when_finished "rm -rf repo" &&
488 git init repo &&
489 (
490 cd repo &&
491 test_commit file &&
492 git branch &&
493 git symbolic-ref refs/heads/sym refs/heads/main &&
494 cat >expected <<-EOF &&
495 refs/heads/main
496 EOF
497 git for-each-ref --format="%(symref)" refs/heads/sym >actual &&
498 test_cmp expected actual
499 )
500'
501
502test_expect_success 'basic: notes' '
503 test_when_finished "rm -rf repo" &&
504 git init repo &&
505 (
506 write_script fake_editor <<-\EOF &&
507 echo "$MSG" >"$1"
508 echo "$MSG" >&2
509 EOF
510
511 test_commit 1st &&
512 test_commit 2nd &&
513 GIT_EDITOR=./fake_editor MSG=b4 git notes add &&
514 GIT_EDITOR=./fake_editor MSG=b3 git notes edit &&
515 echo b4 >expect &&
516 git notes --ref commits@{1} show >actual &&
517 test_cmp expect actual
518 )
519'
520
521test_expect_success 'basic: stash' '
522 test_when_finished "rm -rf repo" &&
523 git init repo &&
524 (
525 cd repo &&
526 test_commit file &&
527 git stash list >expect &&
528 test_line_count = 0 expect &&
529
530 echo hoi >>file.t &&
531 git stash push -m stashed &&
532 git stash list >expect &&
533 test_line_count = 1 expect &&
534
535 git stash clear &&
536 git stash list >expect &&
537 test_line_count = 0 expect
538 )
539'
540
541test_expect_success 'basic: cherry-pick' '
542 test_when_finished "rm -rf repo" &&
543 git init repo &&
544 (
545 cd repo &&
546 test_commit message1 file1 &&
547 test_commit message2 file2 &&
548 git branch source &&
549 git checkout HEAD^ &&
550 test_commit message3 file3 &&
551 git cherry-pick source &&
552 test_path_is_file file2
553 )
554'
555
556test_expect_success 'basic: rebase' '
557 test_when_finished "rm -rf repo" &&
558 git init repo &&
559 (
560 cd repo &&
561 test_commit message1 file1 &&
562 test_commit message2 file2 &&
563 git branch source &&
564 git checkout HEAD^ &&
565 test_commit message3 file3 &&
566 git rebase source &&
567 test_path_is_file file2
568 )
569'
570
571test_expect_success 'reflog: can delete separate reflog entries' '
572 test_when_finished "rm -rf repo" &&
573 git init repo &&
574 (
575 cd repo &&
576
577 test_commit file &&
578 test_commit file2 &&
579 test_commit file3 &&
580 test_commit file4 &&
581 git reflog >actual &&
582 grep file3 actual &&
583
584 git reflog delete HEAD@{1} &&
585 git reflog >actual &&
586 ! grep file3 actual
587 )
588'
589
590test_expect_success 'reflog: can switch to previous branch' '
591 test_when_finished "rm -rf repo" &&
592 git init repo &&
593 (
594 cd repo &&
595 test_commit file1 &&
596 git checkout -b branch1 &&
597 test_commit file2 &&
598 git checkout -b branch2 &&
599 git switch - &&
600 git rev-parse --symbolic-full-name HEAD >actual &&
601 echo refs/heads/branch1 >expect &&
602 test_cmp actual expect
603 )
604'
605
606test_expect_success 'reflog: copying branch writes reflog entry' '
607 test_when_finished "rm -rf repo" &&
608 git init repo &&
609 (
610 cd repo &&
611 test_commit file1 &&
612 test_commit file2 &&
613 oid=$(git rev-parse --short HEAD) &&
614 git branch src &&
615 cat >expect <<-EOF &&
616 ${oid} dst@{0}: Branch: copied refs/heads/src to refs/heads/dst
617 ${oid} dst@{1}: branch: Created from main
618 EOF
619 git branch -c src dst &&
620 git reflog dst >actual &&
621 test_cmp expect actual
622 )
623'
624
625test_expect_success 'reflog: renaming branch writes reflog entry' '
626 test_when_finished "rm -rf repo" &&
627 git init repo &&
628 (
629 cd repo &&
630 git symbolic-ref HEAD refs/heads/before &&
631 test_commit file &&
632 git show-ref >expected.refs &&
633 sed s/before/after/g <expected.refs >expected &&
634 git branch -M after &&
635 git show-ref >actual &&
636 test_cmp expected actual &&
637 echo refs/heads/after >expected &&
638 git symbolic-ref HEAD >actual &&
639 test_cmp expected actual
640 )
641'
642
643test_expect_success 'reflog: can store empty logs' '
644 test_when_finished "rm -rf repo" &&
645 git init repo &&
646 (
647 cd repo &&
648
649 test_must_fail test-tool ref-store main reflog-exists refs/heads/branch &&
650 test-tool ref-store main create-reflog refs/heads/branch &&
651 test-tool ref-store main reflog-exists refs/heads/branch &&
652 test-tool ref-store main for-each-reflog-ent-reverse refs/heads/branch >actual &&
653 test_must_be_empty actual
654 )
655'
656
657test_expect_success 'reflog: expiry empties reflog' '
658 test_when_finished "rm -rf repo" &&
659 git init repo &&
660 (
661 cd repo &&
662
663 test_commit initial &&
664 git checkout -b branch &&
665 test_commit fileA &&
666 test_commit fileB &&
667
668 cat >expect <<-EOF &&
669 commit: fileB
670 commit: fileA
671 branch: Created from HEAD
672 EOF
673 git reflog show --format="%gs" refs/heads/branch >actual &&
674 test_cmp expect actual &&
675
676 git reflog expire branch --expire=all &&
677 git reflog show --format="%gs" refs/heads/branch >actual &&
678 test_must_be_empty actual &&
679 test-tool ref-store main reflog-exists refs/heads/branch
680 )
681'
682
683test_expect_success 'reflog: can be deleted' '
684 test_when_finished "rm -rf repo" &&
685 git init repo &&
686 (
687 cd repo &&
688 test_commit initial &&
689 test-tool ref-store main reflog-exists refs/heads/main &&
690 test-tool ref-store main delete-reflog refs/heads/main &&
691 test_must_fail test-tool ref-store main reflog-exists refs/heads/main
692 )
693'
694
695test_expect_success 'reflog: garbage collection deletes reflog entries' '
696 test_when_finished "rm -rf repo" &&
697 git init repo &&
698 (
699 cd repo &&
700
701 for count in $(test_seq 1 10)
702 do
703 test_commit "number $count" file.t $count number-$count ||
704 return 1
705 done &&
706 git reflog refs/heads/main >actual &&
707 test_line_count = 10 actual &&
708 grep "commit (initial): number 1" actual &&
709 grep "commit: number 10" actual &&
710
711 git gc &&
712 git reflog refs/heads/main >actual &&
713 test_line_count = 0 actual
714 )
715'
716
717test_expect_success 'reflog: updates via HEAD update HEAD reflog' '
718 test_when_finished "rm -rf repo" &&
719 git init repo &&
720 (
721 cd repo &&
722 test_commit main-one &&
723 git checkout -b new-branch &&
724 test_commit new-one &&
725 test_commit new-two &&
726
727 echo new-one >expect &&
728 git log -1 --format=%s HEAD@{1} >actual &&
729 test_cmp expect actual
730 )
731'
732
733test_expect_success 'worktree: adding worktree creates separate stack' '
734 test_when_finished "rm -rf repo worktree" &&
735 git init repo &&
736 test_commit -C repo A &&
737
738 git -C repo worktree add ../worktree &&
739 test_path_is_file repo/.git/worktrees/worktree/refs/heads &&
740 echo "ref: refs/heads/.invalid" >expect &&
741 test_cmp expect repo/.git/worktrees/worktree/HEAD &&
742 test_path_is_dir repo/.git/worktrees/worktree/reftable &&
743 test_path_is_file repo/.git/worktrees/worktree/reftable/tables.list
744'
745
746test_expect_success 'worktree: pack-refs in main repo packs main refs' '
747 test_when_finished "rm -rf repo worktree" &&
748 git init repo &&
749 test_commit -C repo A &&
750 git -C repo worktree add ../worktree &&
751
752 test_line_count = 3 repo/.git/worktrees/worktree/reftable/tables.list &&
753 test_line_count = 4 repo/.git/reftable/tables.list &&
754 git -C repo pack-refs &&
755 test_line_count = 3 repo/.git/worktrees/worktree/reftable/tables.list &&
756 test_line_count = 1 repo/.git/reftable/tables.list
757'
758
759test_expect_success 'worktree: pack-refs in worktree packs worktree refs' '
760 test_when_finished "rm -rf repo worktree" &&
761 git init repo &&
762 test_commit -C repo A &&
763 git -C repo worktree add ../worktree &&
764
765 test_line_count = 3 repo/.git/worktrees/worktree/reftable/tables.list &&
766 test_line_count = 4 repo/.git/reftable/tables.list &&
767 git -C worktree pack-refs &&
768 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
769 test_line_count = 4 repo/.git/reftable/tables.list
770'
771
772test_expect_success 'worktree: creating shared ref updates main stack' '
773 test_when_finished "rm -rf repo worktree" &&
774 git init repo &&
775 test_commit -C repo A &&
776
777 git -C repo worktree add ../worktree &&
778 git -C repo pack-refs &&
779 git -C worktree pack-refs &&
780 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
781 test_line_count = 1 repo/.git/reftable/tables.list &&
782
783 git -C worktree update-ref refs/heads/shared HEAD &&
784 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
785 test_line_count = 2 repo/.git/reftable/tables.list
786'
787
788test_expect_success 'worktree: creating per-worktree ref updates worktree stack' '
789 test_when_finished "rm -rf repo worktree" &&
790 git init repo &&
791 test_commit -C repo A &&
792
793 git -C repo worktree add ../worktree &&
794 git -C repo pack-refs &&
795 git -C worktree pack-refs &&
796 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
797 test_line_count = 1 repo/.git/reftable/tables.list &&
798
799 git -C worktree update-ref refs/bisect/per-worktree HEAD &&
800 test_line_count = 2 repo/.git/worktrees/worktree/reftable/tables.list &&
801 test_line_count = 1 repo/.git/reftable/tables.list
802'
803
804test_expect_success 'worktree: creating per-worktree ref from main repo' '
805 test_when_finished "rm -rf repo worktree" &&
806 git init repo &&
807 test_commit -C repo A &&
808
809 git -C repo worktree add ../worktree &&
810 git -C repo pack-refs &&
811 git -C worktree pack-refs &&
812 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
813 test_line_count = 1 repo/.git/reftable/tables.list &&
814
815 git -C repo update-ref worktrees/worktree/refs/bisect/per-worktree HEAD &&
816 test_line_count = 2 repo/.git/worktrees/worktree/reftable/tables.list &&
817 test_line_count = 1 repo/.git/reftable/tables.list
818'
819
820test_expect_success 'worktree: creating per-worktree ref from second worktree' '
821 test_when_finished "rm -rf repo wt1 wt2" &&
822 git init repo &&
823 test_commit -C repo A &&
824
825 git -C repo worktree add ../wt1 &&
826 git -C repo worktree add ../wt2 &&
827 git -C repo pack-refs &&
828 git -C wt1 pack-refs &&
829 git -C wt2 pack-refs &&
830 test_line_count = 1 repo/.git/worktrees/wt1/reftable/tables.list &&
831 test_line_count = 1 repo/.git/worktrees/wt2/reftable/tables.list &&
832 test_line_count = 1 repo/.git/reftable/tables.list &&
833
834 git -C wt1 update-ref worktrees/wt2/refs/bisect/per-worktree HEAD &&
835 test_line_count = 1 repo/.git/worktrees/wt1/reftable/tables.list &&
836 test_line_count = 2 repo/.git/worktrees/wt2/reftable/tables.list &&
837 test_line_count = 1 repo/.git/reftable/tables.list
838'
839
840test_expect_success 'worktree: can create shared and per-worktree ref in one transaction' '
841 test_when_finished "rm -rf repo worktree" &&
842 git init repo &&
843 test_commit -C repo A &&
844
845 git -C repo worktree add ../worktree &&
846 git -C repo pack-refs &&
847 git -C worktree pack-refs &&
848 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
849 test_line_count = 1 repo/.git/reftable/tables.list &&
850
851 cat >stdin <<-EOF &&
852 create worktrees/worktree/refs/bisect/per-worktree HEAD
853 create refs/branches/shared HEAD
854 EOF
855 git -C repo update-ref --stdin <stdin &&
856 test_line_count = 2 repo/.git/worktrees/worktree/reftable/tables.list &&
857 test_line_count = 2 repo/.git/reftable/tables.list
858'
859
860test_expect_success 'worktree: can access common refs' '
861 test_when_finished "rm -rf repo worktree" &&
862 git init repo &&
863 test_commit -C repo file1 &&
864 git -C repo branch branch1 &&
865 git -C repo worktree add ../worktree &&
866
867 echo refs/heads/worktree >expect &&
868 git -C worktree symbolic-ref HEAD >actual &&
869 test_cmp expect actual &&
870 git -C worktree checkout branch1
871'
872
873test_expect_success 'worktree: adds worktree with detached HEAD' '
874 test_when_finished "rm -rf repo worktree" &&
875
876 git init repo &&
877 test_commit -C repo A &&
878 git -C repo rev-parse main >expect &&
879
880 git -C repo worktree add --detach ../worktree main &&
881 git -C worktree rev-parse HEAD >actual &&
882 test_cmp expect actual
883'
884
885test_expect_success 'fetch: accessing FETCH_HEAD special ref works' '
886 test_when_finished "rm -rf repo sub" &&
887
888 git init sub &&
889 test_commit -C sub two &&
890 git -C sub rev-parse HEAD >expect &&
891
892 git init repo &&
893 test_commit -C repo one &&
894 git -C repo fetch ../sub &&
895 git -C repo rev-parse FETCH_HEAD >actual &&
896 test_cmp expect actual
897'
898
899test_done