Git 2.45
[git/gitster.git] / t / t0610-reftable-basics.sh
blob178791e0862e7c746443e4f38b7971d41d669b95
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 test_expect_reftable_perms () {
100 local umask="$1"
101 local shared="$2"
102 local expect="$3"
104 test_expect_success POSIXPERM "init: honors --shared=$shared with umask $umask" '
105 test_when_finished "rm -rf repo" &&
107 umask $umask &&
108 git init --shared=$shared repo
109 ) &&
110 test_expect_perms "$expect" repo/.git/reftable/tables.list &&
111 for table in repo/.git/reftable/*.ref
113 test_expect_perms "$expect" "$table" ||
114 return 1
115 done
118 test_expect_success POSIXPERM "pack-refs: honors --shared=$shared with umask $umask" '
119 test_when_finished "rm -rf repo" &&
121 umask $umask &&
122 git init --shared=$shared repo &&
123 test_commit -C repo A &&
124 test_line_count = 2 repo/.git/reftable/tables.list &&
125 git -C repo pack-refs
126 ) &&
127 test_expect_perms "$expect" repo/.git/reftable/tables.list &&
128 for table in repo/.git/reftable/*.ref
130 test_expect_perms "$expect" "$table" ||
131 return 1
132 done
136 test_expect_reftable_perms 002 umask "-rw-rw-r--"
137 test_expect_reftable_perms 022 umask "-rw-r--r--"
138 test_expect_reftable_perms 027 umask "-rw-r-----"
140 test_expect_reftable_perms 002 group "-rw-rw-r--"
141 test_expect_reftable_perms 022 group "-rw-rw-r--"
142 test_expect_reftable_perms 027 group "-rw-rw----"
144 test_expect_reftable_perms 002 world "-rw-rw-r--"
145 test_expect_reftable_perms 022 world "-rw-rw-r--"
146 test_expect_reftable_perms 027 world "-rw-rw-r--"
148 test_expect_success 'clone: can clone reftable repository' '
149 test_when_finished "rm -rf repo clone" &&
150 git init repo &&
151 test_commit -C repo message1 file1 &&
153 git clone repo cloned &&
154 echo reftable >expect &&
155 git -C cloned rev-parse --show-ref-format >actual &&
156 test_cmp expect actual &&
157 test_path_is_file cloned/file1
160 test_expect_success 'clone: can clone reffiles into reftable repository' '
161 test_when_finished "rm -rf reffiles reftable" &&
162 git init --ref-format=files reffiles &&
163 test_commit -C reffiles A &&
164 git clone --ref-format=reftable ./reffiles reftable &&
166 git -C reffiles rev-parse HEAD >expect &&
167 git -C reftable rev-parse HEAD >actual &&
168 test_cmp expect actual &&
170 git -C reftable rev-parse --show-ref-format >actual &&
171 echo reftable >expect &&
172 test_cmp expect actual &&
174 git -C reffiles rev-parse --show-ref-format >actual &&
175 echo files >expect &&
176 test_cmp expect actual
179 test_expect_success 'clone: can clone reftable into reffiles repository' '
180 test_when_finished "rm -rf reffiles reftable" &&
181 git init --ref-format=reftable reftable &&
182 test_commit -C reftable A &&
183 git clone --ref-format=files ./reftable reffiles &&
185 git -C reftable rev-parse HEAD >expect &&
186 git -C reffiles rev-parse HEAD >actual &&
187 test_cmp expect actual &&
189 git -C reftable rev-parse --show-ref-format >actual &&
190 echo reftable >expect &&
191 test_cmp expect actual &&
193 git -C reffiles rev-parse --show-ref-format >actual &&
194 echo files >expect &&
195 test_cmp expect actual
198 test_expect_success 'ref transaction: corrupted tables cause failure' '
199 test_when_finished "rm -rf repo" &&
200 git init repo &&
202 cd repo &&
203 test_commit file1 &&
204 for f in .git/reftable/*.ref
206 : >"$f" || return 1
207 done &&
208 test_must_fail git update-ref refs/heads/main HEAD
212 test_expect_success 'ref transaction: corrupted tables.list cause failure' '
213 test_when_finished "rm -rf repo" &&
214 git init repo &&
216 cd repo &&
217 test_commit file1 &&
218 echo garbage >.git/reftable/tables.list &&
219 test_must_fail git update-ref refs/heads/main HEAD
223 test_expect_success 'ref transaction: refuses to write ref causing F/D conflict' '
224 test_when_finished "rm -rf repo" &&
225 git init repo &&
226 test_commit -C repo file &&
227 test_must_fail git -C repo update-ref refs/heads/main/forbidden
230 test_expect_success 'ref transaction: deleting ref with invalid name fails' '
231 test_when_finished "rm -rf repo" &&
232 git init repo &&
233 test_commit -C repo file &&
234 test_must_fail git -C repo update-ref -d ../../my-private-file
237 test_expect_success 'ref transaction: can skip object ID verification' '
238 test_when_finished "rm -rf repo" &&
239 git init repo &&
240 test_must_fail test-tool -C repo ref-store main update-ref msg refs/heads/branch $INVALID_OID $ZERO_OID 0 &&
241 test-tool -C repo ref-store main update-ref msg refs/heads/branch $INVALID_OID $ZERO_OID REF_SKIP_OID_VERIFICATION
244 test_expect_success 'ref transaction: updating same ref multiple times fails' '
245 test_when_finished "rm -rf repo" &&
246 git init repo &&
247 test_commit -C repo A &&
248 cat >updates <<-EOF &&
249 update refs/heads/main $A
250 update refs/heads/main $A
252 cat >expect <<-EOF &&
253 fatal: multiple updates for ref ${SQ}refs/heads/main${SQ} not allowed
255 test_must_fail git -C repo update-ref --stdin <updates 2>err &&
256 test_cmp expect err
259 test_expect_success 'ref transaction: can delete symbolic self-reference with git-symbolic-ref(1)' '
260 test_when_finished "rm -rf repo" &&
261 git init repo &&
262 git -C repo symbolic-ref refs/heads/self refs/heads/self &&
263 git -C repo symbolic-ref -d refs/heads/self
266 test_expect_success 'ref transaction: deleting symbolic self-reference without --no-deref fails' '
267 test_when_finished "rm -rf repo" &&
268 git init repo &&
269 git -C repo symbolic-ref refs/heads/self refs/heads/self &&
270 cat >expect <<-EOF &&
271 error: multiple updates for ${SQ}refs/heads/self${SQ} (including one via symref ${SQ}refs/heads/self${SQ}) are not allowed
273 test_must_fail git -C repo update-ref -d refs/heads/self 2>err &&
274 test_cmp expect err
277 test_expect_success 'ref transaction: deleting symbolic self-reference with --no-deref succeeds' '
278 test_when_finished "rm -rf repo" &&
279 git init repo &&
280 git -C repo symbolic-ref refs/heads/self refs/heads/self &&
281 git -C repo update-ref -d --no-deref refs/heads/self
284 test_expect_success 'ref transaction: creating symbolic ref fails with F/D conflict' '
285 test_when_finished "rm -rf repo" &&
286 git init repo &&
287 test_commit -C repo A &&
288 cat >expect <<-EOF &&
289 error: unable to write symref for refs/heads: file/directory conflict
291 test_must_fail git -C repo symbolic-ref refs/heads refs/heads/foo 2>err &&
292 test_cmp expect err
295 test_expect_success 'ref transaction: ref deletion' '
296 test_when_finished "rm -rf repo" &&
297 git init repo &&
299 cd repo &&
300 test_commit file &&
301 HEAD_OID=$(git show-ref -s --verify HEAD) &&
302 cat >expect <<-EOF &&
303 $HEAD_OID refs/heads/main
304 $HEAD_OID refs/tags/file
306 git show-ref >actual &&
307 test_cmp expect actual &&
309 test_must_fail git update-ref -d refs/tags/file $INVALID_OID &&
310 git show-ref >actual &&
311 test_cmp expect actual &&
313 git update-ref -d refs/tags/file $HEAD_OID &&
314 echo "$HEAD_OID refs/heads/main" >expect &&
315 git show-ref >actual &&
316 test_cmp expect actual
320 test_expect_success 'ref transaction: writes cause auto-compaction' '
321 test_when_finished "rm -rf repo" &&
323 git init repo &&
324 test_line_count = 1 repo/.git/reftable/tables.list &&
326 test_commit -C repo --no-tag A &&
327 test_line_count = 1 repo/.git/reftable/tables.list &&
329 test_commit -C repo --no-tag B &&
330 test_line_count = 1 repo/.git/reftable/tables.list
333 test_expect_success 'ref transaction: env var disables compaction' '
334 test_when_finished "rm -rf repo" &&
336 git init repo &&
337 test_commit -C repo A &&
339 start=$(wc -l <repo/.git/reftable/tables.list) &&
340 iterations=5 &&
341 expected=$((start + iterations)) &&
343 for i in $(test_seq $iterations)
345 GIT_TEST_REFTABLE_AUTOCOMPACTION=false \
346 git -C repo update-ref branch-$i HEAD || return 1
347 done &&
348 test_line_count = $expected repo/.git/reftable/tables.list &&
350 git -C repo update-ref foo HEAD &&
351 test_line_count -lt $expected repo/.git/reftable/tables.list
354 test_expect_success 'ref transaction: alternating table sizes are compacted' '
355 test_when_finished "rm -rf repo" &&
357 git init repo &&
358 test_commit -C repo A &&
359 for i in $(test_seq 5)
361 git -C repo branch -f foo &&
362 git -C repo branch -d foo || return 1
363 done &&
364 test_line_count = 2 repo/.git/reftable/tables.list
367 check_fsync_events () {
368 local trace="$1" &&
369 shift &&
371 cat >expect &&
372 sed -n \
373 -e '/^{"event":"counter",.*"category":"fsync",/ {
374 s/.*"category":"fsync",//;
375 s/}$//;
377 }' \
378 <"$trace" >actual &&
379 test_cmp expect actual
382 test_expect_success 'ref transaction: writes are synced' '
383 test_when_finished "rm -rf repo" &&
384 git init repo &&
385 test_commit -C repo initial &&
387 GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
388 GIT_TEST_FSYNC=true \
389 git -C repo -c core.fsync=reference \
390 -c core.fsyncMethod=fsync update-ref refs/heads/branch HEAD &&
391 check_fsync_events trace2.txt <<-EOF
392 "name":"hardware-flush","count":4
396 test_expect_success 'ref transaction: empty transaction in empty repo' '
397 test_when_finished "rm -rf repo" &&
398 git init repo &&
399 test_commit -C repo --no-tag A &&
400 git -C repo update-ref -d refs/heads/main &&
401 test-tool -C repo ref-store main delete-refs REF_NO_DEREF msg HEAD &&
402 git -C repo update-ref --stdin <<-EOF
403 prepare
404 commit
408 test_expect_success 'ref transaction: fails gracefully when auto compaction fails' '
409 test_when_finished "rm -rf repo" &&
410 git init repo &&
412 cd repo &&
414 test_commit A &&
415 for i in $(test_seq 10)
417 git branch branch-$i &&
418 for table in .git/reftable/*.ref
420 touch "$table.lock" || exit 1
421 done ||
422 exit 1
423 done &&
424 test_line_count = 10 .git/reftable/tables.list
428 test_expect_success 'pack-refs: compacts tables' '
429 test_when_finished "rm -rf repo" &&
430 git init repo &&
432 test_commit -C repo A &&
433 ls -1 repo/.git/reftable >table-files &&
434 test_line_count = 3 table-files &&
435 test_line_count = 2 repo/.git/reftable/tables.list &&
437 git -C repo pack-refs &&
438 ls -1 repo/.git/reftable >table-files &&
439 test_line_count = 2 table-files &&
440 test_line_count = 1 repo/.git/reftable/tables.list
443 test_expect_success 'pack-refs: compaction raises locking errors' '
444 test_when_finished "rm -rf repo" &&
445 git init repo &&
446 test_commit -C repo A &&
447 touch repo/.git/reftable/tables.list.lock &&
448 cat >expect <<-EOF &&
449 error: unable to compact stack: data is locked
451 test_must_fail git -C repo pack-refs 2>err &&
452 test_cmp expect err
455 for command in pack-refs gc "maintenance run --task=pack-refs"
457 test_expect_success "$command: auto compaction" '
458 test_when_finished "rm -rf repo" &&
459 git init repo &&
461 cd repo &&
463 test_commit A &&
465 # We need a bit of setup to ensure that git-gc(1) actually
466 # triggers, and that it does not write anything to the refdb.
467 git config gc.auto 1 &&
468 git config gc.autoDetach 0 &&
469 git config gc.reflogExpire never &&
470 git config gc.reflogExpireUnreachable never &&
471 test_oid blob17_1 | git hash-object -w --stdin &&
473 # The tables should have been auto-compacted, and thus auto
474 # compaction should not have to do anything.
475 ls -1 .git/reftable >tables-expect &&
476 test_line_count = 3 tables-expect &&
477 git $command --auto &&
478 ls -1 .git/reftable >tables-actual &&
479 test_cmp tables-expect tables-actual &&
481 test_oid blob17_2 | git hash-object -w --stdin &&
483 # Lock all tables write some refs. Auto-compaction will be
484 # unable to compact tables and thus fails gracefully, leaving
485 # the stack in a sub-optimal state.
486 ls .git/reftable/*.ref |
487 while read table
489 touch "$table.lock" || exit 1
490 done &&
491 git branch B &&
492 git branch C &&
493 rm .git/reftable/*.lock &&
494 test_line_count = 4 .git/reftable/tables.list &&
496 git $command --auto &&
497 test_line_count = 1 .git/reftable/tables.list
500 done
502 test_expect_success 'pack-refs: prunes stale tables' '
503 test_when_finished "rm -rf repo" &&
504 git init repo &&
505 touch repo/.git/reftable/stale-table.ref &&
506 git -C repo pack-refs &&
507 test_path_is_missing repo/.git/reftable/stable-ref.ref
510 test_expect_success 'pack-refs: does not prune non-table files' '
511 test_when_finished "rm -rf repo" &&
512 git init repo &&
513 touch repo/.git/reftable/garbage &&
514 git -C repo pack-refs &&
515 test_path_is_file repo/.git/reftable/garbage
518 test_expect_success 'packed-refs: writes are synced' '
519 test_when_finished "rm -rf repo" &&
520 git init repo &&
521 test_commit -C repo initial &&
522 test_line_count = 2 table-files &&
524 : >trace2.txt &&
525 GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
526 GIT_TEST_FSYNC=true \
527 git -C repo -c core.fsync=reference \
528 -c core.fsyncMethod=fsync pack-refs &&
529 check_fsync_events trace2.txt <<-EOF
530 "name":"hardware-flush","count":2
534 test_expect_success 'ref iterator: bogus names are flagged' '
535 test_when_finished "rm -rf repo" &&
536 git init repo &&
538 cd repo &&
539 test_commit --no-tag file &&
540 test-tool ref-store main update-ref msg "refs/heads/bogus..name" $(git rev-parse HEAD) $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
542 cat >expect <<-EOF &&
543 $ZERO_OID refs/heads/bogus..name 0xc
544 $(git rev-parse HEAD) refs/heads/main 0x0
546 test-tool ref-store main for-each-ref "" >actual &&
547 test_cmp expect actual
551 test_expect_success 'ref iterator: missing object IDs are not flagged' '
552 test_when_finished "rm -rf repo" &&
553 git init repo &&
555 cd repo &&
556 test-tool ref-store main update-ref msg "refs/heads/broken-hash" $INVALID_OID $ZERO_OID REF_SKIP_OID_VERIFICATION &&
558 cat >expect <<-EOF &&
559 $INVALID_OID refs/heads/broken-hash 0x0
561 test-tool ref-store main for-each-ref "" >actual &&
562 test_cmp expect actual
566 test_expect_success 'basic: commit and list refs' '
567 test_when_finished "rm -rf repo" &&
568 git init repo &&
569 test_commit -C repo file &&
570 test_write_lines refs/heads/main refs/tags/file >expect &&
571 git -C repo for-each-ref --format="%(refname)" >actual &&
572 test_cmp actual expect
575 test_expect_success 'basic: can write large commit message' '
576 test_when_finished "rm -rf repo" &&
577 git init repo &&
578 perl -e "
579 print \"this is a long commit message\" x 50000
580 " >commit-msg &&
581 git -C repo commit --allow-empty --file=../commit-msg
584 test_expect_success 'basic: show-ref fails with empty repository' '
585 test_when_finished "rm -rf repo" &&
586 git init repo &&
587 test_must_fail git -C repo show-ref >actual &&
588 test_must_be_empty actual
591 test_expect_success 'basic: can check out unborn branch' '
592 test_when_finished "rm -rf repo" &&
593 git init repo &&
594 git -C repo checkout -b main
597 test_expect_success 'basic: peeled tags are stored' '
598 test_when_finished "rm -rf repo" &&
599 git init repo &&
600 test_commit -C repo file &&
601 git -C repo tag -m "annotated tag" test_tag HEAD &&
602 for ref in refs/heads/main refs/tags/file refs/tags/test_tag refs/tags/test_tag^{}
604 echo "$(git -C repo rev-parse "$ref") $ref" || return 1
605 done >expect &&
606 git -C repo show-ref -d >actual &&
607 test_cmp expect actual
610 test_expect_success 'basic: for-each-ref can print symrefs' '
611 test_when_finished "rm -rf repo" &&
612 git init repo &&
614 cd repo &&
615 test_commit file &&
616 git branch &&
617 git symbolic-ref refs/heads/sym refs/heads/main &&
618 cat >expected <<-EOF &&
619 refs/heads/main
621 git for-each-ref --format="%(symref)" refs/heads/sym >actual &&
622 test_cmp expected actual
626 test_expect_success 'basic: notes' '
627 test_when_finished "rm -rf repo" &&
628 git init repo &&
630 write_script fake_editor <<-\EOF &&
631 echo "$MSG" >"$1"
632 echo "$MSG" >&2
635 test_commit 1st &&
636 test_commit 2nd &&
637 GIT_EDITOR=./fake_editor MSG=b4 git notes add &&
638 GIT_EDITOR=./fake_editor MSG=b3 git notes edit &&
639 echo b4 >expect &&
640 git notes --ref commits@{1} show >actual &&
641 test_cmp expect actual
645 test_expect_success 'basic: stash' '
646 test_when_finished "rm -rf repo" &&
647 git init repo &&
649 cd repo &&
650 test_commit file &&
651 git stash list >expect &&
652 test_line_count = 0 expect &&
654 echo hoi >>file.t &&
655 git stash push -m stashed &&
656 git stash list >expect &&
657 test_line_count = 1 expect &&
659 git stash clear &&
660 git stash list >expect &&
661 test_line_count = 0 expect
665 test_expect_success 'basic: cherry-pick' '
666 test_when_finished "rm -rf repo" &&
667 git init repo &&
669 cd repo &&
670 test_commit message1 file1 &&
671 test_commit message2 file2 &&
672 git branch source &&
673 git checkout HEAD^ &&
674 test_commit message3 file3 &&
675 git cherry-pick source &&
676 test_path_is_file file2
680 test_expect_success 'basic: rebase' '
681 test_when_finished "rm -rf repo" &&
682 git init repo &&
684 cd repo &&
685 test_commit message1 file1 &&
686 test_commit message2 file2 &&
687 git branch source &&
688 git checkout HEAD^ &&
689 test_commit message3 file3 &&
690 git rebase source &&
691 test_path_is_file file2
695 test_expect_success 'reflog: can delete separate reflog entries' '
696 test_when_finished "rm -rf repo" &&
697 git init repo &&
699 cd repo &&
701 test_commit file &&
702 test_commit file2 &&
703 test_commit file3 &&
704 test_commit file4 &&
705 git reflog >actual &&
706 grep file3 actual &&
708 git reflog delete HEAD@{1} &&
709 git reflog >actual &&
710 ! grep file3 actual
714 test_expect_success 'reflog: can switch to previous branch' '
715 test_when_finished "rm -rf repo" &&
716 git init repo &&
718 cd repo &&
719 test_commit file1 &&
720 git checkout -b branch1 &&
721 test_commit file2 &&
722 git checkout -b branch2 &&
723 git switch - &&
724 git rev-parse --symbolic-full-name HEAD >actual &&
725 echo refs/heads/branch1 >expect &&
726 test_cmp actual expect
730 test_expect_success 'reflog: copying branch writes reflog entry' '
731 test_when_finished "rm -rf repo" &&
732 git init repo &&
734 cd repo &&
735 test_commit file1 &&
736 test_commit file2 &&
737 oid=$(git rev-parse --short HEAD) &&
738 git branch src &&
739 cat >expect <<-EOF &&
740 ${oid} dst@{0}: Branch: copied refs/heads/src to refs/heads/dst
741 ${oid} dst@{1}: branch: Created from main
743 git branch -c src dst &&
744 git reflog dst >actual &&
745 test_cmp expect actual
749 test_expect_success 'reflog: renaming branch writes reflog entry' '
750 test_when_finished "rm -rf repo" &&
751 git init repo &&
753 cd repo &&
754 git symbolic-ref HEAD refs/heads/before &&
755 test_commit file &&
756 git show-ref >expected.refs &&
757 sed s/before/after/g <expected.refs >expected &&
758 git branch -M after &&
759 git show-ref >actual &&
760 test_cmp expected actual &&
761 echo refs/heads/after >expected &&
762 git symbolic-ref HEAD >actual &&
763 test_cmp expected actual
767 test_expect_success 'reflog: can store empty logs' '
768 test_when_finished "rm -rf repo" &&
769 git init repo &&
771 cd repo &&
773 test_must_fail test-tool ref-store main reflog-exists refs/heads/branch &&
774 test-tool ref-store main create-reflog refs/heads/branch &&
775 test-tool ref-store main reflog-exists refs/heads/branch &&
776 test-tool ref-store main for-each-reflog-ent-reverse refs/heads/branch >actual &&
777 test_must_be_empty actual
781 test_expect_success 'reflog: expiry empties reflog' '
782 test_when_finished "rm -rf repo" &&
783 git init repo &&
785 cd repo &&
787 test_commit initial &&
788 git checkout -b branch &&
789 test_commit fileA &&
790 test_commit fileB &&
792 cat >expect <<-EOF &&
793 commit: fileB
794 commit: fileA
795 branch: Created from HEAD
797 git reflog show --format="%gs" refs/heads/branch >actual &&
798 test_cmp expect actual &&
800 git reflog expire branch --expire=all &&
801 git reflog show --format="%gs" refs/heads/branch >actual &&
802 test_must_be_empty actual &&
803 test-tool ref-store main reflog-exists refs/heads/branch
807 test_expect_success 'reflog: can be deleted' '
808 test_when_finished "rm -rf repo" &&
809 git init repo &&
811 cd repo &&
812 test_commit initial &&
813 test-tool ref-store main reflog-exists refs/heads/main &&
814 test-tool ref-store main delete-reflog refs/heads/main &&
815 test_must_fail test-tool ref-store main reflog-exists refs/heads/main
819 test_expect_success 'reflog: garbage collection deletes reflog entries' '
820 test_when_finished "rm -rf repo" &&
821 git init repo &&
823 cd repo &&
825 for count in $(test_seq 1 10)
827 test_commit "number $count" file.t $count number-$count ||
828 return 1
829 done &&
830 git reflog refs/heads/main >actual &&
831 test_line_count = 10 actual &&
832 grep "commit (initial): number 1" actual &&
833 grep "commit: number 10" actual &&
835 git gc &&
836 git reflog refs/heads/main >actual &&
837 test_line_count = 0 actual
841 test_expect_success 'reflog: updates via HEAD update HEAD reflog' '
842 test_when_finished "rm -rf repo" &&
843 git init repo &&
845 cd repo &&
846 test_commit main-one &&
847 git checkout -b new-branch &&
848 test_commit new-one &&
849 test_commit new-two &&
851 echo new-one >expect &&
852 git log -1 --format=%s HEAD@{1} >actual &&
853 test_cmp expect actual
857 test_expect_success 'worktree: adding worktree creates separate stack' '
858 test_when_finished "rm -rf repo worktree" &&
859 git init repo &&
860 test_commit -C repo A &&
862 git -C repo worktree add ../worktree &&
863 test_path_is_file repo/.git/worktrees/worktree/refs/heads &&
864 echo "ref: refs/heads/.invalid" >expect &&
865 test_cmp expect repo/.git/worktrees/worktree/HEAD &&
866 test_path_is_dir repo/.git/worktrees/worktree/reftable &&
867 test_path_is_file repo/.git/worktrees/worktree/reftable/tables.list
870 test_expect_success 'worktree: pack-refs in main repo packs main refs' '
871 test_when_finished "rm -rf repo worktree" &&
872 git init repo &&
873 test_commit -C repo A &&
875 GIT_TEST_REFTABLE_AUTOCOMPACTION=false \
876 git -C repo worktree add ../worktree &&
877 GIT_TEST_REFTABLE_AUTOCOMPACTION=false \
878 git -C worktree update-ref refs/worktree/per-worktree HEAD &&
880 test_line_count = 4 repo/.git/worktrees/worktree/reftable/tables.list &&
881 test_line_count = 3 repo/.git/reftable/tables.list &&
882 git -C repo pack-refs &&
883 test_line_count = 4 repo/.git/worktrees/worktree/reftable/tables.list &&
884 test_line_count = 1 repo/.git/reftable/tables.list
887 test_expect_success 'worktree: pack-refs in worktree packs worktree refs' '
888 test_when_finished "rm -rf repo worktree" &&
889 git init repo &&
890 test_commit -C repo A &&
892 GIT_TEST_REFTABLE_AUTOCOMPACTION=false \
893 git -C repo worktree add ../worktree &&
894 GIT_TEST_REFTABLE_AUTOCOMPACTION=false \
895 git -C worktree update-ref refs/worktree/per-worktree HEAD &&
897 test_line_count = 4 repo/.git/worktrees/worktree/reftable/tables.list &&
898 test_line_count = 3 repo/.git/reftable/tables.list &&
899 git -C worktree pack-refs &&
900 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
901 test_line_count = 3 repo/.git/reftable/tables.list
904 test_expect_success 'worktree: creating shared ref updates main stack' '
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_TEST_REFTABLE_AUTOCOMPACTION=false \
916 git -C worktree update-ref refs/heads/shared HEAD &&
917 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
918 test_line_count = 2 repo/.git/reftable/tables.list
921 test_expect_success 'worktree: creating per-worktree ref updates worktree stack' '
922 test_when_finished "rm -rf repo worktree" &&
923 git init repo &&
924 test_commit -C repo A &&
926 git -C repo worktree add ../worktree &&
927 git -C repo pack-refs &&
928 git -C worktree pack-refs &&
929 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
930 test_line_count = 1 repo/.git/reftable/tables.list &&
932 git -C worktree update-ref refs/bisect/per-worktree HEAD &&
933 test_line_count = 2 repo/.git/worktrees/worktree/reftable/tables.list &&
934 test_line_count = 1 repo/.git/reftable/tables.list
937 test_expect_success 'worktree: creating per-worktree ref from main repo' '
938 test_when_finished "rm -rf repo worktree" &&
939 git init repo &&
940 test_commit -C repo A &&
942 git -C repo worktree add ../worktree &&
943 git -C repo pack-refs &&
944 git -C worktree pack-refs &&
945 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
946 test_line_count = 1 repo/.git/reftable/tables.list &&
948 git -C repo update-ref worktrees/worktree/refs/bisect/per-worktree HEAD &&
949 test_line_count = 2 repo/.git/worktrees/worktree/reftable/tables.list &&
950 test_line_count = 1 repo/.git/reftable/tables.list
953 test_expect_success 'worktree: creating per-worktree ref from second worktree' '
954 test_when_finished "rm -rf repo wt1 wt2" &&
955 git init repo &&
956 test_commit -C repo A &&
958 git -C repo worktree add ../wt1 &&
959 git -C repo worktree add ../wt2 &&
960 git -C repo pack-refs &&
961 git -C wt1 pack-refs &&
962 git -C wt2 pack-refs &&
963 test_line_count = 1 repo/.git/worktrees/wt1/reftable/tables.list &&
964 test_line_count = 1 repo/.git/worktrees/wt2/reftable/tables.list &&
965 test_line_count = 1 repo/.git/reftable/tables.list &&
967 git -C wt1 update-ref worktrees/wt2/refs/bisect/per-worktree HEAD &&
968 test_line_count = 1 repo/.git/worktrees/wt1/reftable/tables.list &&
969 test_line_count = 2 repo/.git/worktrees/wt2/reftable/tables.list &&
970 test_line_count = 1 repo/.git/reftable/tables.list
973 test_expect_success 'worktree: can create shared and per-worktree ref in one transaction' '
974 test_when_finished "rm -rf repo worktree" &&
975 git init repo &&
976 test_commit -C repo A &&
978 git -C repo worktree add ../worktree &&
979 git -C repo pack-refs &&
980 git -C worktree pack-refs &&
981 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
982 test_line_count = 1 repo/.git/reftable/tables.list &&
984 cat >stdin <<-EOF &&
985 create worktrees/worktree/refs/bisect/per-worktree HEAD
986 create refs/branches/shared HEAD
988 git -C repo update-ref --stdin <stdin &&
989 test_line_count = 2 repo/.git/worktrees/worktree/reftable/tables.list &&
990 test_line_count = 2 repo/.git/reftable/tables.list
993 test_expect_success 'worktree: can access common refs' '
994 test_when_finished "rm -rf repo worktree" &&
995 git init repo &&
996 test_commit -C repo file1 &&
997 git -C repo branch branch1 &&
998 git -C repo worktree add ../worktree &&
1000 echo refs/heads/worktree >expect &&
1001 git -C worktree symbolic-ref HEAD >actual &&
1002 test_cmp expect actual &&
1003 git -C worktree checkout branch1
1006 test_expect_success 'worktree: adds worktree with detached HEAD' '
1007 test_when_finished "rm -rf repo worktree" &&
1009 git init repo &&
1010 test_commit -C repo A &&
1011 git -C repo rev-parse main >expect &&
1013 git -C repo worktree add --detach ../worktree main &&
1014 git -C worktree rev-parse HEAD >actual &&
1015 test_cmp expect actual
1018 test_expect_success 'fetch: accessing FETCH_HEAD special ref works' '
1019 test_when_finished "rm -rf repo sub" &&
1021 git init sub &&
1022 test_commit -C sub two &&
1023 git -C sub rev-parse HEAD >expect &&
1025 git init repo &&
1026 test_commit -C repo one &&
1027 git -C repo fetch ../sub &&
1028 git -C repo rev-parse FETCH_HEAD >actual &&
1029 test_cmp expect actual
1032 test_done