reftable/stack: add env to disable autocompaction
[git.git] / t / t0610-reftable-basics.sh
blobc9e10b34684d4447f8a3a914412e69665739fbbc
1 #!/bin/sh
3 # Copyright (c) 2020 Google LLC
6 test_description='reftable basics'
7 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
8 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
10 . ./test-lib.sh
12 if ! test_have_prereq REFTABLE
13 then
14 skip_all='skipping reftable tests; set GIT_TEST_DEFAULT_REF_FORMAT=reftable'
15 test_done
18 INVALID_OID=$(test_oid 001)
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
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
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
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 &&
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
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 &&
68 cp repo/.git/HEAD expect &&
69 test_must_fail git init --ref-format=reftable repo &&
70 test_cmp expect repo/.git/HEAD
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 &&
78 cp repo/.git/HEAD expect &&
79 test_must_fail git init --ref-format=files repo &&
80 test_cmp expect repo/.git/HEAD
83 test_expect_perms () {
84 local perms="$1"
85 local file="$2"
86 local actual=$(ls -l "$file") &&
88 case "$actual" in
89 $perms*)
90 : happy
93 echo "$(basename $2) is not $perms but $actual"
94 false
96 esac
99 for umask in 002 022
101 test_expect_success POSIXPERM 'init: honors core.sharedRepository' '
102 test_when_finished "rm -rf repo" &&
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
111 test_expect_perms "-rw-rw-r--" "$table" ||
112 return 1
113 done
115 done
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 &&
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
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 &&
135 git -C reffiles rev-parse HEAD >expect &&
136 git -C reftable rev-parse HEAD >actual &&
137 test_cmp expect actual &&
139 git -C reftable rev-parse --show-ref-format >actual &&
140 echo reftable >expect &&
141 test_cmp expect actual &&
143 git -C reffiles rev-parse --show-ref-format >actual &&
144 echo files >expect &&
145 test_cmp expect actual
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 &&
154 git -C reftable rev-parse HEAD >expect &&
155 git -C reffiles rev-parse HEAD >actual &&
156 test_cmp expect actual &&
158 git -C reftable rev-parse --show-ref-format >actual &&
159 echo reftable >expect &&
160 test_cmp expect actual &&
162 git -C reffiles rev-parse --show-ref-format >actual &&
163 echo files >expect &&
164 test_cmp expect actual
167 test_expect_success 'ref transaction: corrupted tables cause failure' '
168 test_when_finished "rm -rf repo" &&
169 git init repo &&
171 cd repo &&
172 test_commit file1 &&
173 for f in .git/reftable/*.ref
175 : >"$f" || return 1
176 done &&
177 test_must_fail git update-ref refs/heads/main HEAD
181 test_expect_success 'ref transaction: corrupted tables.list cause failure' '
182 test_when_finished "rm -rf repo" &&
183 git init repo &&
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
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
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
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
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
221 cat >expect <<-EOF &&
222 fatal: multiple updates for ref ${SQ}refs/heads/main${SQ} not allowed
224 test_must_fail git -C repo update-ref --stdin <updates 2>err &&
225 test_cmp expect err
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
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
242 test_must_fail git -C repo update-ref -d refs/heads/self 2>err &&
243 test_cmp expect err
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
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
260 test_must_fail git -C repo symbolic-ref refs/heads refs/heads/foo 2>err &&
261 test_cmp expect err
264 test_expect_success 'ref transaction: ref deletion' '
265 test_when_finished "rm -rf repo" &&
266 git init repo &&
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
275 git show-ref >actual &&
276 test_cmp expect actual &&
278 test_must_fail git update-ref -d refs/tags/file $INVALID_OID &&
279 git show-ref >actual &&
280 test_cmp expect actual &&
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
289 test_expect_success 'ref transaction: writes cause auto-compaction' '
290 test_when_finished "rm -rf repo" &&
292 git init repo &&
293 test_line_count = 1 repo/.git/reftable/tables.list &&
295 test_commit -C repo --no-tag A &&
296 test_line_count = 2 repo/.git/reftable/tables.list &&
298 test_commit -C repo --no-tag B &&
299 test_line_count = 1 repo/.git/reftable/tables.list
302 test_expect_success 'ref transaction: env var disables compaction' '
303 test_when_finished "rm -rf repo" &&
305 git init repo &&
306 test_commit -C repo A &&
308 start=$(wc -l <repo/.git/reftable/tables.list) &&
309 iterations=5 &&
310 expected=$((start + iterations)) &&
312 for i in $(test_seq $iterations)
314 GIT_TEST_REFTABLE_AUTOCOMPACTION=false \
315 git -C repo update-ref branch-$i HEAD || return 1
316 done &&
317 test_line_count = $expected repo/.git/reftable/tables.list &&
319 git -C repo update-ref foo HEAD &&
320 test_line_count -lt $expected repo/.git/reftable/tables.list
323 check_fsync_events () {
324 local trace="$1" &&
325 shift &&
327 cat >expect &&
328 sed -n \
329 -e '/^{"event":"counter",.*"category":"fsync",/ {
330 s/.*"category":"fsync",//;
331 s/}$//;
333 }' \
334 <"$trace" >actual &&
335 test_cmp expect actual
338 test_expect_success 'ref transaction: writes are synced' '
339 test_when_finished "rm -rf repo" &&
340 git init repo &&
341 test_commit -C repo initial &&
343 GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
344 GIT_TEST_FSYNC=true \
345 git -C repo -c core.fsync=reference \
346 -c core.fsyncMethod=fsync update-ref refs/heads/branch HEAD &&
347 check_fsync_events trace2.txt <<-EOF
348 "name":"hardware-flush","count":2
352 test_expect_success 'ref transaction: empty transaction in empty repo' '
353 test_when_finished "rm -rf repo" &&
354 git init repo &&
355 test_commit -C repo --no-tag A &&
356 git -C repo update-ref -d refs/heads/main &&
357 test-tool -C repo ref-store main delete-refs REF_NO_DEREF msg HEAD &&
358 git -C repo update-ref --stdin <<-EOF
359 prepare
360 commit
364 test_expect_success 'ref transaction: fails gracefully when auto compaction fails' '
365 test_when_finished "rm -rf repo" &&
366 git init repo &&
368 cd repo &&
370 test_commit A &&
371 for i in $(test_seq 10)
373 git branch branch-$i &&
374 for table in .git/reftable/*.ref
376 touch "$table.lock" || exit 1
377 done ||
378 exit 1
379 done &&
380 test_line_count = 13 .git/reftable/tables.list
384 test_expect_success 'pack-refs: compacts tables' '
385 test_when_finished "rm -rf repo" &&
386 git init repo &&
388 test_commit -C repo A &&
389 ls -1 repo/.git/reftable >table-files &&
390 test_line_count = 4 table-files &&
391 test_line_count = 3 repo/.git/reftable/tables.list &&
393 git -C repo pack-refs &&
394 ls -1 repo/.git/reftable >table-files &&
395 test_line_count = 2 table-files &&
396 test_line_count = 1 repo/.git/reftable/tables.list
399 test_expect_success 'pack-refs: compaction raises locking errors' '
400 test_when_finished "rm -rf repo" &&
401 git init repo &&
402 test_commit -C repo A &&
403 touch repo/.git/reftable/tables.list.lock &&
404 cat >expect <<-EOF &&
405 error: unable to compact stack: data is locked
407 test_must_fail git -C repo pack-refs 2>err &&
408 test_cmp expect err
411 for command in pack-refs gc "maintenance run --task=pack-refs"
413 test_expect_success "$command: auto compaction" '
414 test_when_finished "rm -rf repo" &&
415 git init repo &&
417 cd repo &&
419 test_commit A &&
421 # We need a bit of setup to ensure that git-gc(1) actually
422 # triggers, and that it does not write anything to the refdb.
423 git config gc.auto 1 &&
424 git config gc.autoDetach 0 &&
425 git config gc.reflogExpire never &&
426 git config gc.reflogExpireUnreachable never &&
427 test_oid blob17_1 | git hash-object -w --stdin &&
429 # The tables should have been auto-compacted, and thus auto
430 # compaction should not have to do anything.
431 ls -1 .git/reftable >tables-expect &&
432 test_line_count = 4 tables-expect &&
433 git $command --auto &&
434 ls -1 .git/reftable >tables-actual &&
435 test_cmp tables-expect tables-actual &&
437 test_oid blob17_2 | git hash-object -w --stdin &&
439 # Lock all tables write some refs. Auto-compaction will be
440 # unable to compact tables and thus fails gracefully, leaving
441 # the stack in a sub-optimal state.
442 ls .git/reftable/*.ref |
443 while read table
445 touch "$table.lock" || exit 1
446 done &&
447 git branch B &&
448 git branch C &&
449 rm .git/reftable/*.lock &&
450 test_line_count = 5 .git/reftable/tables.list &&
452 git $command --auto &&
453 test_line_count = 1 .git/reftable/tables.list
456 done
458 test_expect_success 'pack-refs: prunes stale tables' '
459 test_when_finished "rm -rf repo" &&
460 git init repo &&
461 touch repo/.git/reftable/stale-table.ref &&
462 git -C repo pack-refs &&
463 test_path_is_missing repo/.git/reftable/stable-ref.ref
466 test_expect_success 'pack-refs: does not prune non-table files' '
467 test_when_finished "rm -rf repo" &&
468 git init repo &&
469 touch repo/.git/reftable/garbage &&
470 git -C repo pack-refs &&
471 test_path_is_file repo/.git/reftable/garbage
474 for umask in 002 022
476 test_expect_success POSIXPERM 'pack-refs: honors core.sharedRepository' '
477 test_when_finished "rm -rf repo" &&
479 umask $umask &&
480 git init --shared=true repo &&
481 test_commit -C repo A &&
482 test_line_count = 3 repo/.git/reftable/tables.list
483 ) &&
484 git -C repo pack-refs &&
485 test_expect_perms "-rw-rw-r--" repo/.git/reftable/tables.list &&
486 for table in repo/.git/reftable/*.ref
488 test_expect_perms "-rw-rw-r--" "$table" ||
489 return 1
490 done
492 done
494 test_expect_success 'packed-refs: writes are synced' '
495 test_when_finished "rm -rf repo" &&
496 git init repo &&
497 test_commit -C repo initial &&
498 test_line_count = 2 table-files &&
500 : >trace2.txt &&
501 GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
502 GIT_TEST_FSYNC=true \
503 git -C repo -c core.fsync=reference \
504 -c core.fsyncMethod=fsync pack-refs &&
505 check_fsync_events trace2.txt <<-EOF
506 "name":"hardware-flush","count":2
510 test_expect_success 'ref iterator: bogus names are flagged' '
511 test_when_finished "rm -rf repo" &&
512 git init repo &&
514 cd repo &&
515 test_commit --no-tag file &&
516 test-tool ref-store main update-ref msg "refs/heads/bogus..name" $(git rev-parse HEAD) $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
518 cat >expect <<-EOF &&
519 $ZERO_OID refs/heads/bogus..name 0xc
520 $(git rev-parse HEAD) refs/heads/main 0x0
522 test-tool ref-store main for-each-ref "" >actual &&
523 test_cmp expect actual
527 test_expect_success 'ref iterator: missing object IDs are not flagged' '
528 test_when_finished "rm -rf repo" &&
529 git init repo &&
531 cd repo &&
532 test-tool ref-store main update-ref msg "refs/heads/broken-hash" $INVALID_OID $ZERO_OID REF_SKIP_OID_VERIFICATION &&
534 cat >expect <<-EOF &&
535 $INVALID_OID refs/heads/broken-hash 0x0
537 test-tool ref-store main for-each-ref "" >actual &&
538 test_cmp expect actual
542 test_expect_success 'basic: commit and list refs' '
543 test_when_finished "rm -rf repo" &&
544 git init repo &&
545 test_commit -C repo file &&
546 test_write_lines refs/heads/main refs/tags/file >expect &&
547 git -C repo for-each-ref --format="%(refname)" >actual &&
548 test_cmp actual expect
551 test_expect_success 'basic: can write large commit message' '
552 test_when_finished "rm -rf repo" &&
553 git init repo &&
554 perl -e "
555 print \"this is a long commit message\" x 50000
556 " >commit-msg &&
557 git -C repo commit --allow-empty --file=../commit-msg
560 test_expect_success 'basic: show-ref fails with empty repository' '
561 test_when_finished "rm -rf repo" &&
562 git init repo &&
563 test_must_fail git -C repo show-ref >actual &&
564 test_must_be_empty actual
567 test_expect_success 'basic: can check out unborn branch' '
568 test_when_finished "rm -rf repo" &&
569 git init repo &&
570 git -C repo checkout -b main
573 test_expect_success 'basic: peeled tags are stored' '
574 test_when_finished "rm -rf repo" &&
575 git init repo &&
576 test_commit -C repo file &&
577 git -C repo tag -m "annotated tag" test_tag HEAD &&
578 for ref in refs/heads/main refs/tags/file refs/tags/test_tag refs/tags/test_tag^{}
580 echo "$(git -C repo rev-parse "$ref") $ref" || return 1
581 done >expect &&
582 git -C repo show-ref -d >actual &&
583 test_cmp expect actual
586 test_expect_success 'basic: for-each-ref can print symrefs' '
587 test_when_finished "rm -rf repo" &&
588 git init repo &&
590 cd repo &&
591 test_commit file &&
592 git branch &&
593 git symbolic-ref refs/heads/sym refs/heads/main &&
594 cat >expected <<-EOF &&
595 refs/heads/main
597 git for-each-ref --format="%(symref)" refs/heads/sym >actual &&
598 test_cmp expected actual
602 test_expect_success 'basic: notes' '
603 test_when_finished "rm -rf repo" &&
604 git init repo &&
606 write_script fake_editor <<-\EOF &&
607 echo "$MSG" >"$1"
608 echo "$MSG" >&2
611 test_commit 1st &&
612 test_commit 2nd &&
613 GIT_EDITOR=./fake_editor MSG=b4 git notes add &&
614 GIT_EDITOR=./fake_editor MSG=b3 git notes edit &&
615 echo b4 >expect &&
616 git notes --ref commits@{1} show >actual &&
617 test_cmp expect actual
621 test_expect_success 'basic: stash' '
622 test_when_finished "rm -rf repo" &&
623 git init repo &&
625 cd repo &&
626 test_commit file &&
627 git stash list >expect &&
628 test_line_count = 0 expect &&
630 echo hoi >>file.t &&
631 git stash push -m stashed &&
632 git stash list >expect &&
633 test_line_count = 1 expect &&
635 git stash clear &&
636 git stash list >expect &&
637 test_line_count = 0 expect
641 test_expect_success 'basic: cherry-pick' '
642 test_when_finished "rm -rf repo" &&
643 git init repo &&
645 cd repo &&
646 test_commit message1 file1 &&
647 test_commit message2 file2 &&
648 git branch source &&
649 git checkout HEAD^ &&
650 test_commit message3 file3 &&
651 git cherry-pick source &&
652 test_path_is_file file2
656 test_expect_success 'basic: rebase' '
657 test_when_finished "rm -rf repo" &&
658 git init repo &&
660 cd repo &&
661 test_commit message1 file1 &&
662 test_commit message2 file2 &&
663 git branch source &&
664 git checkout HEAD^ &&
665 test_commit message3 file3 &&
666 git rebase source &&
667 test_path_is_file file2
671 test_expect_success 'reflog: can delete separate reflog entries' '
672 test_when_finished "rm -rf repo" &&
673 git init repo &&
675 cd repo &&
677 test_commit file &&
678 test_commit file2 &&
679 test_commit file3 &&
680 test_commit file4 &&
681 git reflog >actual &&
682 grep file3 actual &&
684 git reflog delete HEAD@{1} &&
685 git reflog >actual &&
686 ! grep file3 actual
690 test_expect_success 'reflog: can switch to previous branch' '
691 test_when_finished "rm -rf repo" &&
692 git init repo &&
694 cd repo &&
695 test_commit file1 &&
696 git checkout -b branch1 &&
697 test_commit file2 &&
698 git checkout -b branch2 &&
699 git switch - &&
700 git rev-parse --symbolic-full-name HEAD >actual &&
701 echo refs/heads/branch1 >expect &&
702 test_cmp actual expect
706 test_expect_success 'reflog: copying branch writes reflog entry' '
707 test_when_finished "rm -rf repo" &&
708 git init repo &&
710 cd repo &&
711 test_commit file1 &&
712 test_commit file2 &&
713 oid=$(git rev-parse --short HEAD) &&
714 git branch src &&
715 cat >expect <<-EOF &&
716 ${oid} dst@{0}: Branch: copied refs/heads/src to refs/heads/dst
717 ${oid} dst@{1}: branch: Created from main
719 git branch -c src dst &&
720 git reflog dst >actual &&
721 test_cmp expect actual
725 test_expect_success 'reflog: renaming branch writes reflog entry' '
726 test_when_finished "rm -rf repo" &&
727 git init repo &&
729 cd repo &&
730 git symbolic-ref HEAD refs/heads/before &&
731 test_commit file &&
732 git show-ref >expected.refs &&
733 sed s/before/after/g <expected.refs >expected &&
734 git branch -M after &&
735 git show-ref >actual &&
736 test_cmp expected actual &&
737 echo refs/heads/after >expected &&
738 git symbolic-ref HEAD >actual &&
739 test_cmp expected actual
743 test_expect_success 'reflog: can store empty logs' '
744 test_when_finished "rm -rf repo" &&
745 git init repo &&
747 cd repo &&
749 test_must_fail test-tool ref-store main reflog-exists refs/heads/branch &&
750 test-tool ref-store main create-reflog refs/heads/branch &&
751 test-tool ref-store main reflog-exists refs/heads/branch &&
752 test-tool ref-store main for-each-reflog-ent-reverse refs/heads/branch >actual &&
753 test_must_be_empty actual
757 test_expect_success 'reflog: expiry empties reflog' '
758 test_when_finished "rm -rf repo" &&
759 git init repo &&
761 cd repo &&
763 test_commit initial &&
764 git checkout -b branch &&
765 test_commit fileA &&
766 test_commit fileB &&
768 cat >expect <<-EOF &&
769 commit: fileB
770 commit: fileA
771 branch: Created from HEAD
773 git reflog show --format="%gs" refs/heads/branch >actual &&
774 test_cmp expect actual &&
776 git reflog expire branch --expire=all &&
777 git reflog show --format="%gs" refs/heads/branch >actual &&
778 test_must_be_empty actual &&
779 test-tool ref-store main reflog-exists refs/heads/branch
783 test_expect_success 'reflog: can be deleted' '
784 test_when_finished "rm -rf repo" &&
785 git init repo &&
787 cd repo &&
788 test_commit initial &&
789 test-tool ref-store main reflog-exists refs/heads/main &&
790 test-tool ref-store main delete-reflog refs/heads/main &&
791 test_must_fail test-tool ref-store main reflog-exists refs/heads/main
795 test_expect_success 'reflog: garbage collection deletes reflog entries' '
796 test_when_finished "rm -rf repo" &&
797 git init repo &&
799 cd repo &&
801 for count in $(test_seq 1 10)
803 test_commit "number $count" file.t $count number-$count ||
804 return 1
805 done &&
806 git reflog refs/heads/main >actual &&
807 test_line_count = 10 actual &&
808 grep "commit (initial): number 1" actual &&
809 grep "commit: number 10" actual &&
811 git gc &&
812 git reflog refs/heads/main >actual &&
813 test_line_count = 0 actual
817 test_expect_success 'reflog: updates via HEAD update HEAD reflog' '
818 test_when_finished "rm -rf repo" &&
819 git init repo &&
821 cd repo &&
822 test_commit main-one &&
823 git checkout -b new-branch &&
824 test_commit new-one &&
825 test_commit new-two &&
827 echo new-one >expect &&
828 git log -1 --format=%s HEAD@{1} >actual &&
829 test_cmp expect actual
833 test_expect_success 'worktree: adding worktree creates separate stack' '
834 test_when_finished "rm -rf repo worktree" &&
835 git init repo &&
836 test_commit -C repo A &&
838 git -C repo worktree add ../worktree &&
839 test_path_is_file repo/.git/worktrees/worktree/refs/heads &&
840 echo "ref: refs/heads/.invalid" >expect &&
841 test_cmp expect repo/.git/worktrees/worktree/HEAD &&
842 test_path_is_dir repo/.git/worktrees/worktree/reftable &&
843 test_path_is_file repo/.git/worktrees/worktree/reftable/tables.list
846 test_expect_success 'worktree: pack-refs in main repo packs main refs' '
847 test_when_finished "rm -rf repo worktree" &&
848 git init repo &&
849 test_commit -C repo A &&
850 git -C repo worktree add ../worktree &&
852 test_line_count = 3 repo/.git/worktrees/worktree/reftable/tables.list &&
853 test_line_count = 4 repo/.git/reftable/tables.list &&
854 git -C repo pack-refs &&
855 test_line_count = 3 repo/.git/worktrees/worktree/reftable/tables.list &&
856 test_line_count = 1 repo/.git/reftable/tables.list
859 test_expect_success 'worktree: pack-refs in worktree packs worktree refs' '
860 test_when_finished "rm -rf repo worktree" &&
861 git init repo &&
862 test_commit -C repo A &&
863 git -C repo worktree add ../worktree &&
865 test_line_count = 3 repo/.git/worktrees/worktree/reftable/tables.list &&
866 test_line_count = 4 repo/.git/reftable/tables.list &&
867 git -C worktree pack-refs &&
868 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
869 test_line_count = 4 repo/.git/reftable/tables.list
872 test_expect_success 'worktree: creating shared ref updates main stack' '
873 test_when_finished "rm -rf repo worktree" &&
874 git init repo &&
875 test_commit -C repo A &&
877 git -C repo worktree add ../worktree &&
878 git -C repo pack-refs &&
879 git -C worktree pack-refs &&
880 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
881 test_line_count = 1 repo/.git/reftable/tables.list &&
883 git -C worktree update-ref refs/heads/shared HEAD &&
884 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
885 test_line_count = 2 repo/.git/reftable/tables.list
888 test_expect_success 'worktree: creating per-worktree ref updates worktree stack' '
889 test_when_finished "rm -rf repo worktree" &&
890 git init repo &&
891 test_commit -C repo A &&
893 git -C repo worktree add ../worktree &&
894 git -C repo pack-refs &&
895 git -C worktree pack-refs &&
896 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
897 test_line_count = 1 repo/.git/reftable/tables.list &&
899 git -C worktree update-ref refs/bisect/per-worktree HEAD &&
900 test_line_count = 2 repo/.git/worktrees/worktree/reftable/tables.list &&
901 test_line_count = 1 repo/.git/reftable/tables.list
904 test_expect_success 'worktree: creating per-worktree ref from main repo' '
905 test_when_finished "rm -rf repo worktree" &&
906 git init repo &&
907 test_commit -C repo A &&
909 git -C repo worktree add ../worktree &&
910 git -C repo pack-refs &&
911 git -C worktree pack-refs &&
912 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
913 test_line_count = 1 repo/.git/reftable/tables.list &&
915 git -C repo update-ref worktrees/worktree/refs/bisect/per-worktree HEAD &&
916 test_line_count = 2 repo/.git/worktrees/worktree/reftable/tables.list &&
917 test_line_count = 1 repo/.git/reftable/tables.list
920 test_expect_success 'worktree: creating per-worktree ref from second worktree' '
921 test_when_finished "rm -rf repo wt1 wt2" &&
922 git init repo &&
923 test_commit -C repo A &&
925 git -C repo worktree add ../wt1 &&
926 git -C repo worktree add ../wt2 &&
927 git -C repo pack-refs &&
928 git -C wt1 pack-refs &&
929 git -C wt2 pack-refs &&
930 test_line_count = 1 repo/.git/worktrees/wt1/reftable/tables.list &&
931 test_line_count = 1 repo/.git/worktrees/wt2/reftable/tables.list &&
932 test_line_count = 1 repo/.git/reftable/tables.list &&
934 git -C wt1 update-ref worktrees/wt2/refs/bisect/per-worktree HEAD &&
935 test_line_count = 1 repo/.git/worktrees/wt1/reftable/tables.list &&
936 test_line_count = 2 repo/.git/worktrees/wt2/reftable/tables.list &&
937 test_line_count = 1 repo/.git/reftable/tables.list
940 test_expect_success 'worktree: can create shared and per-worktree ref in one transaction' '
941 test_when_finished "rm -rf repo worktree" &&
942 git init repo &&
943 test_commit -C repo A &&
945 git -C repo worktree add ../worktree &&
946 git -C repo pack-refs &&
947 git -C worktree pack-refs &&
948 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
949 test_line_count = 1 repo/.git/reftable/tables.list &&
951 cat >stdin <<-EOF &&
952 create worktrees/worktree/refs/bisect/per-worktree HEAD
953 create refs/branches/shared HEAD
955 git -C repo update-ref --stdin <stdin &&
956 test_line_count = 2 repo/.git/worktrees/worktree/reftable/tables.list &&
957 test_line_count = 2 repo/.git/reftable/tables.list
960 test_expect_success 'worktree: can access common refs' '
961 test_when_finished "rm -rf repo worktree" &&
962 git init repo &&
963 test_commit -C repo file1 &&
964 git -C repo branch branch1 &&
965 git -C repo worktree add ../worktree &&
967 echo refs/heads/worktree >expect &&
968 git -C worktree symbolic-ref HEAD >actual &&
969 test_cmp expect actual &&
970 git -C worktree checkout branch1
973 test_expect_success 'worktree: adds worktree with detached HEAD' '
974 test_when_finished "rm -rf repo worktree" &&
976 git init repo &&
977 test_commit -C repo A &&
978 git -C repo rev-parse main >expect &&
980 git -C repo worktree add --detach ../worktree main &&
981 git -C worktree rev-parse HEAD >actual &&
982 test_cmp expect actual
985 test_expect_success 'fetch: accessing FETCH_HEAD special ref works' '
986 test_when_finished "rm -rf repo sub" &&
988 git init sub &&
989 test_commit -C sub two &&
990 git -C sub rev-parse HEAD >expect &&
992 git init repo &&
993 test_commit -C repo one &&
994 git -C repo fetch ../sub &&
995 git -C repo rev-parse FETCH_HEAD >actual &&
996 test_cmp expect actual
999 test_done