3 # Copyright (c) 2020 Google LLC
6 test_description
='reftable basics'
8 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
=main
9 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
10 GIT_TEST_DEFAULT_REF_FORMAT
=reftable
11 export GIT_TEST_DEFAULT_REF_FORMAT
13 TEST_PASSES_SANITIZE_LEAK
=true
16 INVALID_OID
=$
(test_oid
001)
18 test_expect_success
'init: creates basic reftable structures' '
19 test_when_finished "rm -rf repo" &&
21 test_path_is_dir repo/.git/reftable &&
22 test_path_is_file repo/.git/reftable/tables.list &&
23 echo reftable >expect &&
24 git -C repo rev-parse --show-ref-format >actual &&
25 test_cmp expect actual
28 test_expect_success
'init: sha256 object format via environment variable' '
29 test_when_finished "rm -rf repo" &&
30 GIT_DEFAULT_HASH=sha256 git init repo &&
35 git -C repo rev-parse --show-object-format --show-ref-format >actual &&
36 test_cmp expect actual
39 test_expect_success
'init: sha256 object format via option' '
40 test_when_finished "rm -rf repo" &&
41 git init --object-format=sha256 repo &&
46 git -C repo rev-parse --show-object-format --show-ref-format >actual &&
47 test_cmp expect actual
50 test_expect_success
'init: reinitializing reftable backend succeeds' '
51 test_when_finished "rm -rf repo" &&
53 test_commit -C repo A &&
55 git -C repo for-each-ref >expect &&
56 git init --ref-format=reftable repo &&
57 git -C repo for-each-ref >actual &&
58 test_cmp expect actual
61 test_expect_success
'init: reinitializing files with reftable backend fails' '
62 test_when_finished "rm -rf repo" &&
63 git init --ref-format=files repo &&
64 test_commit -C repo file &&
66 cp repo/.git/HEAD expect &&
67 test_must_fail git init --ref-format=reftable repo &&
68 test_cmp expect repo/.git/HEAD
71 test_expect_success
'init: reinitializing reftable with files backend fails' '
72 test_when_finished "rm -rf repo" &&
73 git init --ref-format=reftable repo &&
74 test_commit -C repo file &&
76 cp repo/.git/HEAD expect &&
77 test_must_fail git init --ref-format=files repo &&
78 test_cmp expect repo/.git/HEAD
81 test_expect_perms
() {
84 local actual
="$(ls -l "$file")" &&
91 echo "$(basename $2) is not $perms but $actual"
97 test_expect_reftable_perms
() {
102 test_expect_success POSIXPERM
"init: honors --shared=$shared with umask $umask" '
103 test_when_finished "rm -rf repo" &&
106 git init --shared=$shared repo
108 test_expect_perms "$expect" repo/.git/reftable/tables.list &&
109 for table in repo/.git/reftable/*.ref
111 test_expect_perms "$expect" "$table" ||
116 test_expect_success POSIXPERM
"pack-refs: honors --shared=$shared with umask $umask" '
117 test_when_finished "rm -rf repo" &&
120 git init --shared=$shared repo &&
121 test_commit -C repo A &&
122 test_line_count = 2 repo/.git/reftable/tables.list &&
123 git -C repo pack-refs
125 test_expect_perms "$expect" repo/.git/reftable/tables.list &&
126 for table in repo/.git/reftable/*.ref
128 test_expect_perms "$expect" "$table" ||
134 test_expect_reftable_perms
002 umask "-rw-rw-r--"
135 test_expect_reftable_perms
022 umask "-rw-r--r--"
136 test_expect_reftable_perms
027 umask "-rw-r-----"
138 test_expect_reftable_perms
002 group
"-rw-rw-r--"
139 test_expect_reftable_perms
022 group
"-rw-rw-r--"
140 test_expect_reftable_perms
027 group
"-rw-rw----"
142 test_expect_reftable_perms
002 world
"-rw-rw-r--"
143 test_expect_reftable_perms
022 world
"-rw-rw-r--"
144 test_expect_reftable_perms
027 world
"-rw-rw-r--"
146 test_expect_success
'clone: can clone reftable repository' '
147 test_when_finished "rm -rf repo clone" &&
149 test_commit -C repo message1 file1 &&
151 git clone repo cloned &&
152 echo reftable >expect &&
153 git -C cloned rev-parse --show-ref-format >actual &&
154 test_cmp expect actual &&
155 test_path_is_file cloned/file1
158 test_expect_success
'clone: can clone reffiles into reftable repository' '
159 test_when_finished "rm -rf reffiles reftable" &&
160 git init --ref-format=files reffiles &&
161 test_commit -C reffiles A &&
162 git clone --ref-format=reftable ./reffiles reftable &&
164 git -C reffiles rev-parse HEAD >expect &&
165 git -C reftable rev-parse HEAD >actual &&
166 test_cmp expect actual &&
168 git -C reftable rev-parse --show-ref-format >actual &&
169 echo reftable >expect &&
170 test_cmp expect actual &&
172 git -C reffiles rev-parse --show-ref-format >actual &&
173 echo files >expect &&
174 test_cmp expect actual
177 test_expect_success
'clone: can clone reftable into reffiles repository' '
178 test_when_finished "rm -rf reffiles reftable" &&
179 git init --ref-format=reftable reftable &&
180 test_commit -C reftable A &&
181 git clone --ref-format=files ./reftable reffiles &&
183 git -C reftable rev-parse HEAD >expect &&
184 git -C reffiles rev-parse HEAD >actual &&
185 test_cmp expect actual &&
187 git -C reftable rev-parse --show-ref-format >actual &&
188 echo reftable >expect &&
189 test_cmp expect actual &&
191 git -C reffiles rev-parse --show-ref-format >actual &&
192 echo files >expect &&
193 test_cmp expect actual
196 test_expect_success
'ref transaction: corrupted tables cause failure' '
197 test_when_finished "rm -rf repo" &&
202 for f in .git/reftable/*.ref
206 test_must_fail git update-ref refs/heads/main HEAD
210 test_expect_success
'ref transaction: corrupted tables.list cause failure' '
211 test_when_finished "rm -rf repo" &&
216 echo garbage >.git/reftable/tables.list &&
217 test_must_fail git update-ref refs/heads/main HEAD
221 test_expect_success
'ref transaction: refuses to write ref causing F/D conflict' '
222 test_when_finished "rm -rf repo" &&
224 test_commit -C repo file &&
225 test_must_fail git -C repo update-ref refs/heads/main/forbidden
228 test_expect_success
'ref transaction: deleting ref with invalid name fails' '
229 test_when_finished "rm -rf repo" &&
231 test_commit -C repo file &&
232 test_must_fail git -C repo update-ref -d ../../my-private-file
235 test_expect_success
'ref transaction: can skip object ID verification' '
236 test_when_finished "rm -rf repo" &&
238 test_must_fail test-tool -C repo ref-store main update-ref msg refs/heads/branch $INVALID_OID $ZERO_OID 0 &&
239 test-tool -C repo ref-store main update-ref msg refs/heads/branch $INVALID_OID $ZERO_OID REF_SKIP_OID_VERIFICATION
242 test_expect_success
'ref transaction: updating same ref multiple times fails' '
243 test_when_finished "rm -rf repo" &&
245 test_commit -C repo A &&
246 cat >updates <<-EOF &&
247 update refs/heads/main $A
248 update refs/heads/main $A
250 cat >expect <<-EOF &&
251 fatal: multiple updates for ref ${SQ}refs/heads/main${SQ} not allowed
253 test_must_fail git -C repo update-ref --stdin <updates 2>err &&
257 test_expect_success
'ref transaction: can delete symbolic self-reference with git-symbolic-ref(1)' '
258 test_when_finished "rm -rf repo" &&
260 git -C repo symbolic-ref refs/heads/self refs/heads/self &&
261 git -C repo symbolic-ref -d refs/heads/self
264 test_expect_success
'ref transaction: deleting symbolic self-reference without --no-deref fails' '
265 test_when_finished "rm -rf repo" &&
267 git -C repo symbolic-ref refs/heads/self refs/heads/self &&
268 cat >expect <<-EOF &&
269 error: multiple updates for ${SQ}refs/heads/self${SQ} (including one via symref ${SQ}refs/heads/self${SQ}) are not allowed
271 test_must_fail git -C repo update-ref -d refs/heads/self 2>err &&
275 test_expect_success
'ref transaction: deleting symbolic self-reference with --no-deref succeeds' '
276 test_when_finished "rm -rf repo" &&
278 git -C repo symbolic-ref refs/heads/self refs/heads/self &&
279 git -C repo update-ref -d --no-deref refs/heads/self
282 test_expect_success
'ref transaction: creating symbolic ref fails with F/D conflict' '
283 test_when_finished "rm -rf repo" &&
285 test_commit -C repo A &&
286 cat >expect <<-EOF &&
287 error: ${SQ}refs/heads/main${SQ} exists; cannot create ${SQ}refs/heads${SQ}
289 test_must_fail git -C repo symbolic-ref refs/heads refs/heads/foo 2>err &&
293 test_expect_success
'ref transaction: ref deletion' '
294 test_when_finished "rm -rf repo" &&
299 HEAD_OID=$(git show-ref -s --verify HEAD) &&
300 cat >expect <<-EOF &&
301 $HEAD_OID refs/heads/main
302 $HEAD_OID refs/tags/file
304 git show-ref >actual &&
305 test_cmp expect actual &&
307 test_must_fail git update-ref -d refs/tags/file $INVALID_OID &&
308 git show-ref >actual &&
309 test_cmp expect actual &&
311 git update-ref -d refs/tags/file $HEAD_OID &&
312 echo "$HEAD_OID refs/heads/main" >expect &&
313 git show-ref >actual &&
314 test_cmp expect actual
318 test_expect_success
'ref transaction: writes cause auto-compaction' '
319 test_when_finished "rm -rf repo" &&
322 test_line_count = 1 repo/.git/reftable/tables.list &&
324 test_commit -C repo --no-tag A &&
325 test_line_count = 1 repo/.git/reftable/tables.list &&
327 test_commit -C repo --no-tag B &&
328 test_line_count = 1 repo/.git/reftable/tables.list
331 test_expect_success
'ref transaction: env var disables compaction' '
332 test_when_finished "rm -rf repo" &&
335 test_commit -C repo A &&
337 start=$(wc -l <repo/.git/reftable/tables.list) &&
339 expected=$((start + iterations)) &&
341 for i in $(test_seq $iterations)
343 GIT_TEST_REFTABLE_AUTOCOMPACTION=false \
344 git -C repo update-ref branch-$i HEAD || return 1
346 test_line_count = $expected repo/.git/reftable/tables.list &&
348 git -C repo update-ref foo HEAD &&
349 test_line_count -lt $expected repo/.git/reftable/tables.list
352 test_expect_success
'ref transaction: alternating table sizes are compacted' '
353 test_when_finished "rm -rf repo" &&
356 test_commit -C repo A &&
357 for i in $(test_seq 5)
359 git -C repo branch -f foo &&
360 git -C repo branch -d foo || return 1
362 test_line_count = 2 repo/.git/reftable/tables.list
365 check_fsync_events
() {
371 -e '/^{"event":"counter",.*"category":"fsync",/ {
372 s/.*"category":"fsync",//;
377 test_cmp expect actual
380 test_expect_success
'ref transaction: writes are synced' '
381 test_when_finished "rm -rf repo" &&
383 test_commit -C repo initial &&
385 GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
386 GIT_TEST_FSYNC=true \
387 git -C repo -c core.fsync=reference \
388 -c core.fsyncMethod=fsync update-ref refs/heads/branch HEAD &&
389 check_fsync_events trace2.txt <<-EOF
390 "name":"hardware-flush","count":4
394 test_expect_success
'ref transaction: empty transaction in empty repo' '
395 test_when_finished "rm -rf repo" &&
397 test_commit -C repo --no-tag A &&
398 git -C repo update-ref -d refs/heads/main &&
399 test-tool -C repo ref-store main delete-refs REF_NO_DEREF msg HEAD &&
400 git -C repo update-ref --stdin <<-EOF
406 test_expect_success
'ref transaction: fails gracefully when auto compaction fails' '
407 test_when_finished "rm -rf repo" &&
413 for i in $(test_seq 10)
415 git branch branch-$i &&
416 for table in .git/reftable/*.ref
418 touch "$table.lock" || exit 1
422 test_line_count = 10 .git/reftable/tables.list
426 test_expect_success
'ref transaction: timeout acquiring tables.list lock' '
427 test_when_finished "rm -rf repo" &&
431 test_commit initial &&
432 >.git/reftable/tables.list.lock &&
433 test_must_fail git update-ref refs/heads/branch HEAD 2>err &&
434 test_grep "cannot lock references" err
438 test_expect_success
'ref transaction: retry acquiring tables.list lock' '
439 test_when_finished "rm -rf repo" &&
443 test_commit initial &&
444 LOCK=.git/reftable/tables.list.lock &&
447 ( sleep 1 && rm -f $LOCK ) &
449 git -c reftable.lockTimeout=5000 update-ref refs/heads/branch HEAD
453 # This test fails most of the time on Cygwin systems. The root cause is
454 # that Windows does not allow us to rename the "tables.list.lock" file into
455 # place when "tables.list" is open for reading by a concurrent process. We have
456 # worked around that in our MinGW-based rename emulation, but the Cygwin
457 # emulation seems to be insufficient.
458 test_expect_success
!CYGWIN
'ref transaction: many concurrent writers' '
459 test_when_finished "rm -rf repo" &&
463 # Set a high timeout. While a couple of seconds should be
464 # plenty, using the address sanitizer will significantly slow
465 # us down here. So we are aiming way higher than you would ever
466 # think is necessary just to keep us from flaking. We could
467 # also lock indefinitely by passing -1, but that could
468 # potentially block CI jobs indefinitely if there was a bug
470 git config set reftable.lockTimeout 300000 &&
471 test_commit --no-tag initial &&
473 head=$(git rev-parse HEAD) &&
474 for i in $(test_seq 100)
476 printf "%s commit\trefs/heads/branch-%s\n" "$head" "$i" ||
479 printf "%s commit\trefs/heads/main\n" "$head" >>expect &&
481 for i in $(test_seq 100)
483 { git update-ref refs/heads/branch-$i HEAD& } ||
488 git for-each-ref --sort=v:refname >actual &&
489 test_cmp expect actual
493 test_expect_success
'pack-refs: compacts tables' '
494 test_when_finished "rm -rf repo" &&
497 test_commit -C repo A &&
498 ls -1 repo/.git/reftable >table-files &&
499 test_line_count = 3 table-files &&
500 test_line_count = 2 repo/.git/reftable/tables.list &&
502 git -C repo pack-refs &&
503 ls -1 repo/.git/reftable >table-files &&
504 test_line_count = 2 table-files &&
505 test_line_count = 1 repo/.git/reftable/tables.list
508 test_expect_success
'pack-refs: compaction raises locking errors' '
509 test_when_finished "rm -rf repo" &&
511 test_commit -C repo A &&
512 touch repo/.git/reftable/tables.list.lock &&
513 cat >expect <<-EOF &&
514 error: unable to compact stack: data is locked
516 test_must_fail git -C repo pack-refs 2>err &&
520 for command in pack-refs gc
"maintenance run --task=pack-refs"
522 test_expect_success
"$command: auto compaction" '
523 test_when_finished "rm -rf repo" &&
530 # We need a bit of setup to ensure that git-gc(1) actually
531 # triggers, and that it does not write anything to the refdb.
532 git config gc.auto 1 &&
533 git config gc.autoDetach 0 &&
534 git config gc.reflogExpire never &&
535 git config gc.reflogExpireUnreachable never &&
536 test_oid blob17_1 | git hash-object -w --stdin &&
538 # The tables should have been auto-compacted, and thus auto
539 # compaction should not have to do anything.
540 ls -1 .git/reftable >tables-expect &&
541 test_line_count = 3 tables-expect &&
542 git $command --auto &&
543 ls -1 .git/reftable >tables-actual &&
544 test_cmp tables-expect tables-actual &&
546 test_oid blob17_2 | git hash-object -w --stdin &&
548 # Lock all tables, write some refs. Auto-compaction will be
549 # unable to compact tables and thus fails gracefully,
550 # compacting only those tables which are not locked.
551 ls .git/reftable/*.ref | sort |
554 touch "$table.lock" &&
555 basename "$table" >>tables.expect || exit 1
557 test_line_count = 2 .git/reftable/tables.list &&
561 # The new tables are auto-compacted, but the locked tables are
563 test_line_count = 3 .git/reftable/tables.list &&
564 head -n 2 .git/reftable/tables.list >tables.head &&
565 test_cmp tables.expect tables.head &&
567 rm .git/reftable/*.lock &&
568 git $command --auto &&
569 test_line_count = 1 .git/reftable/tables.list
574 test_expect_success
'pack-refs: prunes stale tables' '
575 test_when_finished "rm -rf repo" &&
577 touch repo/.git/reftable/stale-table.ref &&
578 git -C repo pack-refs &&
579 test_path_is_missing repo/.git/reftable/stable-ref.ref
582 test_expect_success
'pack-refs: does not prune non-table files' '
583 test_when_finished "rm -rf repo" &&
585 touch repo/.git/reftable/garbage &&
586 git -C repo pack-refs &&
587 test_path_is_file repo/.git/reftable/garbage
590 test_expect_success
'packed-refs: writes are synced' '
591 test_when_finished "rm -rf repo" &&
593 test_commit -C repo initial &&
594 test_line_count = 2 table-files &&
597 GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
598 GIT_TEST_FSYNC=true \
599 git -C repo -c core.fsync=reference \
600 -c core.fsyncMethod=fsync pack-refs &&
601 check_fsync_events trace2.txt <<-EOF
602 "name":"hardware-flush","count":2
606 test_expect_success
'ref iterator: bogus names are flagged' '
607 test_when_finished "rm -rf repo" &&
611 test_commit --no-tag file &&
612 test-tool ref-store main update-ref msg "refs/heads/bogus..name" $(git rev-parse HEAD) $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
614 cat >expect <<-EOF &&
615 $ZERO_OID refs/heads/bogus..name 0xc
616 $(git rev-parse HEAD) refs/heads/main 0x0
618 test-tool ref-store main for-each-ref "" >actual &&
619 test_cmp expect actual
623 test_expect_success
'ref iterator: missing object IDs are not flagged' '
624 test_when_finished "rm -rf repo" &&
628 test-tool ref-store main update-ref msg "refs/heads/broken-hash" $INVALID_OID $ZERO_OID REF_SKIP_OID_VERIFICATION &&
630 cat >expect <<-EOF &&
631 $INVALID_OID refs/heads/broken-hash 0x0
633 test-tool ref-store main for-each-ref "" >actual &&
634 test_cmp expect actual
638 test_expect_success
'basic: commit and list refs' '
639 test_when_finished "rm -rf repo" &&
641 test_commit -C repo file &&
642 test_write_lines refs/heads/main refs/tags/file >expect &&
643 git -C repo for-each-ref --format="%(refname)" >actual &&
644 test_cmp actual expect
647 test_expect_success
'basic: can write large commit message' '
648 test_when_finished "rm -rf repo" &&
651 print \"this is a long commit message\" x 50000
653 git -C repo commit --allow-empty --file=../commit-msg
656 test_expect_success
'basic: show-ref fails with empty repository' '
657 test_when_finished "rm -rf repo" &&
659 test_must_fail git -C repo show-ref >actual &&
660 test_must_be_empty actual
663 test_expect_success
'basic: can check out unborn branch' '
664 test_when_finished "rm -rf repo" &&
666 git -C repo checkout -b main
669 test_expect_success
'basic: peeled tags are stored' '
670 test_when_finished "rm -rf repo" &&
672 test_commit -C repo file &&
673 git -C repo tag -m "annotated tag" test_tag HEAD &&
674 for ref in refs/heads/main refs/tags/file refs/tags/test_tag refs/tags/test_tag^{}
676 echo "$(git -C repo rev-parse "$ref") $ref" || return 1
678 git -C repo show-ref -d >actual &&
679 test_cmp expect actual
682 test_expect_success
'basic: for-each-ref can print symrefs' '
683 test_when_finished "rm -rf repo" &&
689 git symbolic-ref refs/heads/sym refs/heads/main &&
690 cat >expected <<-EOF &&
693 git for-each-ref --format="%(symref)" refs/heads/sym >actual &&
694 test_cmp expected actual
698 test_expect_success
'basic: notes' '
699 test_when_finished "rm -rf repo" &&
702 write_script fake_editor <<-\EOF &&
709 GIT_EDITOR=./fake_editor MSG=b4 git notes add &&
710 GIT_EDITOR=./fake_editor MSG=b3 git notes edit &&
712 git notes --ref commits@{1} show >actual &&
713 test_cmp expect actual
717 test_expect_success
'basic: stash' '
718 test_when_finished "rm -rf repo" &&
723 git stash list >expect &&
724 test_line_count = 0 expect &&
727 git stash push -m stashed &&
728 git stash list >expect &&
729 test_line_count = 1 expect &&
732 git stash list >expect &&
733 test_line_count = 0 expect
737 test_expect_success
'basic: cherry-pick' '
738 test_when_finished "rm -rf repo" &&
742 test_commit message1 file1 &&
743 test_commit message2 file2 &&
745 git checkout HEAD^ &&
746 test_commit message3 file3 &&
747 git cherry-pick source &&
748 test_path_is_file file2
752 test_expect_success
'basic: rebase' '
753 test_when_finished "rm -rf repo" &&
757 test_commit message1 file1 &&
758 test_commit message2 file2 &&
760 git checkout HEAD^ &&
761 test_commit message3 file3 &&
763 test_path_is_file file2
767 test_expect_success
'reflog: can delete separate reflog entries' '
768 test_when_finished "rm -rf repo" &&
777 git reflog >actual &&
780 git reflog delete HEAD@{1} &&
781 git reflog >actual &&
786 test_expect_success
'reflog: can switch to previous branch' '
787 test_when_finished "rm -rf repo" &&
792 git checkout -b branch1 &&
794 git checkout -b branch2 &&
796 git rev-parse --symbolic-full-name HEAD >actual &&
797 echo refs/heads/branch1 >expect &&
798 test_cmp actual expect
802 test_expect_success
'reflog: copying branch writes reflog entry' '
803 test_when_finished "rm -rf repo" &&
809 oid=$(git rev-parse --short HEAD) &&
811 cat >expect <<-EOF &&
812 ${oid} dst@{0}: Branch: copied refs/heads/src to refs/heads/dst
813 ${oid} dst@{1}: branch: Created from main
815 git branch -c src dst &&
816 git reflog dst >actual &&
817 test_cmp expect actual
821 test_expect_success
'reflog: renaming branch writes reflog entry' '
822 test_when_finished "rm -rf repo" &&
826 git symbolic-ref HEAD refs/heads/before &&
828 git show-ref >expected.refs &&
829 sed s/before/after/g <expected.refs >expected &&
830 git branch -M after &&
831 git show-ref >actual &&
832 test_cmp expected actual &&
833 echo refs/heads/after >expected &&
834 git symbolic-ref HEAD >actual &&
835 test_cmp expected actual
839 test_expect_success
'reflog: can store empty logs' '
840 test_when_finished "rm -rf repo" &&
845 test_must_fail test-tool ref-store main reflog-exists refs/heads/branch &&
846 test-tool ref-store main create-reflog refs/heads/branch &&
847 test-tool ref-store main reflog-exists refs/heads/branch &&
848 test-tool ref-store main for-each-reflog-ent-reverse refs/heads/branch >actual &&
849 test_must_be_empty actual
853 test_expect_success
'reflog: expiry empties reflog' '
854 test_when_finished "rm -rf repo" &&
859 test_commit initial &&
860 git checkout -b branch &&
864 cat >expect <<-EOF &&
867 branch: Created from HEAD
869 git reflog show --format="%gs" refs/heads/branch >actual &&
870 test_cmp expect actual &&
872 git reflog expire branch --expire=all &&
873 git reflog show --format="%gs" refs/heads/branch >actual &&
874 test_must_be_empty actual &&
875 test-tool ref-store main reflog-exists refs/heads/branch
879 test_expect_success
'reflog: can be deleted' '
880 test_when_finished "rm -rf repo" &&
884 test_commit initial &&
885 test-tool ref-store main reflog-exists refs/heads/main &&
886 test-tool ref-store main delete-reflog refs/heads/main &&
887 test_must_fail test-tool ref-store main reflog-exists refs/heads/main
891 test_expect_success
'reflog: garbage collection deletes reflog entries' '
892 test_when_finished "rm -rf repo" &&
897 for count in $(test_seq 1 10)
899 test_commit "number $count" file.t $count number-$count ||
902 git reflog refs/heads/main >actual &&
903 test_line_count = 10 actual &&
904 grep "commit (initial): number 1" actual &&
905 grep "commit: number 10" actual &&
908 git reflog refs/heads/main >actual &&
909 test_line_count = 0 actual
913 test_expect_success
'reflog: updates via HEAD update HEAD reflog' '
914 test_when_finished "rm -rf repo" &&
918 test_commit main-one &&
919 git checkout -b new-branch &&
920 test_commit new-one &&
921 test_commit new-two &&
923 echo new-one >expect &&
924 git log -1 --format=%s HEAD@{1} >actual &&
925 test_cmp expect actual
929 test_expect_success
'branch: copying branch with D/F conflict' '
930 test_when_finished "rm -rf repo" &&
936 cat >expect <<-EOF &&
937 error: ${SQ}refs/heads/branch${SQ} exists; cannot create ${SQ}refs/heads/branch/moved${SQ}
938 fatal: branch copy failed
940 test_must_fail git branch -c branch branch/moved 2>err &&
945 test_expect_success
'branch: moving branch with D/F conflict' '
946 test_when_finished "rm -rf repo" &&
952 git branch conflict &&
953 cat >expect <<-EOF &&
954 error: ${SQ}refs/heads/conflict${SQ} exists; cannot create ${SQ}refs/heads/conflict/moved${SQ}
955 fatal: branch rename failed
957 test_must_fail git branch -m branch conflict/moved 2>err &&
962 test_expect_success
'worktree: adding worktree creates separate stack' '
963 test_when_finished "rm -rf repo worktree" &&
965 test_commit -C repo A &&
967 git -C repo worktree add ../worktree &&
968 test_path_is_file repo/.git/worktrees/worktree/refs/heads &&
969 echo "ref: refs/heads/.invalid" >expect &&
970 test_cmp expect repo/.git/worktrees/worktree/HEAD &&
971 test_path_is_dir repo/.git/worktrees/worktree/reftable &&
972 test_path_is_file repo/.git/worktrees/worktree/reftable/tables.list
975 test_expect_success
'worktree: pack-refs in main repo packs main refs' '
976 test_when_finished "rm -rf repo worktree" &&
978 test_commit -C repo A &&
980 GIT_TEST_REFTABLE_AUTOCOMPACTION=false \
981 git -C repo worktree add ../worktree &&
982 GIT_TEST_REFTABLE_AUTOCOMPACTION=false \
983 git -C worktree update-ref refs/worktree/per-worktree HEAD &&
985 test_line_count = 4 repo/.git/worktrees/worktree/reftable/tables.list &&
986 test_line_count = 3 repo/.git/reftable/tables.list &&
987 git -C repo pack-refs &&
988 test_line_count = 4 repo/.git/worktrees/worktree/reftable/tables.list &&
989 test_line_count = 1 repo/.git/reftable/tables.list
992 test_expect_success
'worktree: pack-refs in worktree packs worktree refs' '
993 test_when_finished "rm -rf repo worktree" &&
995 test_commit -C repo A &&
997 GIT_TEST_REFTABLE_AUTOCOMPACTION=false \
998 git -C repo worktree add ../worktree &&
999 GIT_TEST_REFTABLE_AUTOCOMPACTION=false \
1000 git -C worktree update-ref refs/worktree/per-worktree HEAD &&
1002 test_line_count = 4 repo/.git/worktrees/worktree/reftable/tables.list &&
1003 test_line_count = 3 repo/.git/reftable/tables.list &&
1004 git -C worktree pack-refs &&
1005 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
1006 test_line_count = 3 repo/.git/reftable/tables.list
1009 test_expect_success
'worktree: creating shared ref updates main stack' '
1010 test_when_finished "rm -rf repo worktree" &&
1012 test_commit -C repo A &&
1014 git -C repo worktree add ../worktree &&
1015 git -C repo pack-refs &&
1016 git -C worktree pack-refs &&
1017 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
1018 test_line_count = 1 repo/.git/reftable/tables.list &&
1020 GIT_TEST_REFTABLE_AUTOCOMPACTION=false \
1021 git -C worktree update-ref refs/heads/shared HEAD &&
1022 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
1023 test_line_count = 2 repo/.git/reftable/tables.list
1026 test_expect_success
'worktree: creating per-worktree ref updates worktree stack' '
1027 test_when_finished "rm -rf repo worktree" &&
1029 test_commit -C repo A &&
1031 git -C repo worktree add ../worktree &&
1032 git -C repo pack-refs &&
1033 git -C worktree pack-refs &&
1034 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
1035 test_line_count = 1 repo/.git/reftable/tables.list &&
1037 git -C worktree update-ref refs/bisect/per-worktree HEAD &&
1038 test_line_count = 2 repo/.git/worktrees/worktree/reftable/tables.list &&
1039 test_line_count = 1 repo/.git/reftable/tables.list
1042 test_expect_success
'worktree: creating per-worktree ref from main repo' '
1043 test_when_finished "rm -rf repo worktree" &&
1045 test_commit -C repo A &&
1047 git -C repo worktree add ../worktree &&
1048 git -C repo pack-refs &&
1049 git -C worktree pack-refs &&
1050 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
1051 test_line_count = 1 repo/.git/reftable/tables.list &&
1053 git -C repo update-ref worktrees/worktree/refs/bisect/per-worktree HEAD &&
1054 test_line_count = 2 repo/.git/worktrees/worktree/reftable/tables.list &&
1055 test_line_count = 1 repo/.git/reftable/tables.list
1058 test_expect_success
'worktree: creating per-worktree ref from second worktree' '
1059 test_when_finished "rm -rf repo wt1 wt2" &&
1061 test_commit -C repo A &&
1063 git -C repo worktree add ../wt1 &&
1064 git -C repo worktree add ../wt2 &&
1065 git -C repo pack-refs &&
1066 git -C wt1 pack-refs &&
1067 git -C wt2 pack-refs &&
1068 test_line_count = 1 repo/.git/worktrees/wt1/reftable/tables.list &&
1069 test_line_count = 1 repo/.git/worktrees/wt2/reftable/tables.list &&
1070 test_line_count = 1 repo/.git/reftable/tables.list &&
1072 git -C wt1 update-ref worktrees/wt2/refs/bisect/per-worktree HEAD &&
1073 test_line_count = 1 repo/.git/worktrees/wt1/reftable/tables.list &&
1074 test_line_count = 2 repo/.git/worktrees/wt2/reftable/tables.list &&
1075 test_line_count = 1 repo/.git/reftable/tables.list
1078 test_expect_success
'worktree: can create shared and per-worktree ref in one transaction' '
1079 test_when_finished "rm -rf repo worktree" &&
1081 test_commit -C repo A &&
1083 git -C repo worktree add ../worktree &&
1084 git -C repo pack-refs &&
1085 git -C worktree pack-refs &&
1086 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
1087 test_line_count = 1 repo/.git/reftable/tables.list &&
1089 cat >stdin <<-EOF &&
1090 create worktrees/worktree/refs/bisect/per-worktree HEAD
1091 create refs/branches/shared HEAD
1093 git -C repo update-ref --stdin <stdin &&
1094 test_line_count = 2 repo/.git/worktrees/worktree/reftable/tables.list &&
1095 test_line_count = 2 repo/.git/reftable/tables.list
1098 test_expect_success
'worktree: can access common refs' '
1099 test_when_finished "rm -rf repo worktree" &&
1101 test_commit -C repo file1 &&
1102 git -C repo branch branch1 &&
1103 git -C repo worktree add ../worktree &&
1105 echo refs/heads/worktree >expect &&
1106 git -C worktree symbolic-ref HEAD >actual &&
1107 test_cmp expect actual &&
1108 git -C worktree checkout branch1
1111 test_expect_success
'worktree: adds worktree with detached HEAD' '
1112 test_when_finished "rm -rf repo worktree" &&
1115 test_commit -C repo A &&
1116 git -C repo rev-parse main >expect &&
1118 git -C repo worktree add --detach ../worktree main &&
1119 git -C worktree rev-parse HEAD >actual &&
1120 test_cmp expect actual
1123 test_expect_success
'fetch: accessing FETCH_HEAD special ref works' '
1124 test_when_finished "rm -rf repo sub" &&
1127 test_commit -C sub two &&
1128 git -C sub rev-parse HEAD >expect &&
1131 test_commit -C repo one &&
1132 git -C repo fetch ../sub &&
1133 git -C repo rev-parse FETCH_HEAD >actual &&
1134 test_cmp expect actual