Merge branch 'rj/add-p-typo-reaction'
[git/gitster.git] / t / t0610-reftable-basics.sh
blobcc5bbfd732e2acd715b0bd749f55b67b764f03d8
1 #!/bin/sh
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-lib.sh
15 INVALID_OID=$(test_oid 001)
17 test_expect_success 'init: creates basic reftable structures' '
18 test_when_finished "rm -rf repo" &&
19 git init repo &&
20 test_path_is_dir repo/.git/reftable &&
21 test_path_is_file repo/.git/reftable/tables.list &&
22 echo reftable >expect &&
23 git -C repo rev-parse --show-ref-format >actual &&
24 test_cmp expect actual
27 test_expect_success 'init: sha256 object format via environment variable' '
28 test_when_finished "rm -rf repo" &&
29 GIT_DEFAULT_HASH=sha256 git init repo &&
30 cat >expect <<-EOF &&
31 sha256
32 reftable
33 EOF
34 git -C repo rev-parse --show-object-format --show-ref-format >actual &&
35 test_cmp expect actual
38 test_expect_success 'init: sha256 object format via option' '
39 test_when_finished "rm -rf repo" &&
40 git init --object-format=sha256 repo &&
41 cat >expect <<-EOF &&
42 sha256
43 reftable
44 EOF
45 git -C repo rev-parse --show-object-format --show-ref-format >actual &&
46 test_cmp expect actual
49 test_expect_success 'init: reinitializing reftable backend succeeds' '
50 test_when_finished "rm -rf repo" &&
51 git init repo &&
52 test_commit -C repo A &&
54 git -C repo for-each-ref >expect &&
55 git init --ref-format=reftable repo &&
56 git -C repo for-each-ref >actual &&
57 test_cmp expect actual
60 test_expect_success 'init: reinitializing files with reftable backend fails' '
61 test_when_finished "rm -rf repo" &&
62 git init --ref-format=files repo &&
63 test_commit -C repo file &&
65 cp repo/.git/HEAD expect &&
66 test_must_fail git init --ref-format=reftable repo &&
67 test_cmp expect repo/.git/HEAD
70 test_expect_success 'init: reinitializing reftable with files backend fails' '
71 test_when_finished "rm -rf repo" &&
72 git init --ref-format=reftable repo &&
73 test_commit -C repo file &&
75 cp repo/.git/HEAD expect &&
76 test_must_fail git init --ref-format=files repo &&
77 test_cmp expect repo/.git/HEAD
80 test_expect_perms () {
81 local perms="$1" &&
82 local file="$2" &&
83 local actual="$(ls -l "$file")" &&
85 case "$actual" in
86 $perms*)
87 : happy
90 echo "$(basename $2) is not $perms but $actual"
91 false
93 esac
96 test_expect_reftable_perms () {
97 local umask="$1"
98 local shared="$2"
99 local expect="$3"
101 test_expect_success POSIXPERM "init: honors --shared=$shared with umask $umask" '
102 test_when_finished "rm -rf repo" &&
104 umask $umask &&
105 git init --shared=$shared repo
106 ) &&
107 test_expect_perms "$expect" repo/.git/reftable/tables.list &&
108 for table in repo/.git/reftable/*.ref
110 test_expect_perms "$expect" "$table" ||
111 return 1
112 done
115 test_expect_success POSIXPERM "pack-refs: honors --shared=$shared with umask $umask" '
116 test_when_finished "rm -rf repo" &&
118 umask $umask &&
119 git init --shared=$shared repo &&
120 test_commit -C repo A &&
121 test_line_count = 2 repo/.git/reftable/tables.list &&
122 git -C repo pack-refs
123 ) &&
124 test_expect_perms "$expect" repo/.git/reftable/tables.list &&
125 for table in repo/.git/reftable/*.ref
127 test_expect_perms "$expect" "$table" ||
128 return 1
129 done
133 test_expect_reftable_perms 002 umask "-rw-rw-r--"
134 test_expect_reftable_perms 022 umask "-rw-r--r--"
135 test_expect_reftable_perms 027 umask "-rw-r-----"
137 test_expect_reftable_perms 002 group "-rw-rw-r--"
138 test_expect_reftable_perms 022 group "-rw-rw-r--"
139 test_expect_reftable_perms 027 group "-rw-rw----"
141 test_expect_reftable_perms 002 world "-rw-rw-r--"
142 test_expect_reftable_perms 022 world "-rw-rw-r--"
143 test_expect_reftable_perms 027 world "-rw-rw-r--"
145 test_expect_success 'clone: can clone reftable repository' '
146 test_when_finished "rm -rf repo clone" &&
147 git init repo &&
148 test_commit -C repo message1 file1 &&
150 git clone repo cloned &&
151 echo reftable >expect &&
152 git -C cloned rev-parse --show-ref-format >actual &&
153 test_cmp expect actual &&
154 test_path_is_file cloned/file1
157 test_expect_success 'clone: can clone reffiles into reftable repository' '
158 test_when_finished "rm -rf reffiles reftable" &&
159 git init --ref-format=files reffiles &&
160 test_commit -C reffiles A &&
161 git clone --ref-format=reftable ./reffiles reftable &&
163 git -C reffiles rev-parse HEAD >expect &&
164 git -C reftable rev-parse HEAD >actual &&
165 test_cmp expect actual &&
167 git -C reftable rev-parse --show-ref-format >actual &&
168 echo reftable >expect &&
169 test_cmp expect actual &&
171 git -C reffiles rev-parse --show-ref-format >actual &&
172 echo files >expect &&
173 test_cmp expect actual
176 test_expect_success 'clone: can clone reftable into reffiles repository' '
177 test_when_finished "rm -rf reffiles reftable" &&
178 git init --ref-format=reftable reftable &&
179 test_commit -C reftable A &&
180 git clone --ref-format=files ./reftable reffiles &&
182 git -C reftable rev-parse HEAD >expect &&
183 git -C reffiles rev-parse HEAD >actual &&
184 test_cmp expect actual &&
186 git -C reftable rev-parse --show-ref-format >actual &&
187 echo reftable >expect &&
188 test_cmp expect actual &&
190 git -C reffiles rev-parse --show-ref-format >actual &&
191 echo files >expect &&
192 test_cmp expect actual
195 test_expect_success 'ref transaction: corrupted tables cause failure' '
196 test_when_finished "rm -rf repo" &&
197 git init repo &&
199 cd repo &&
200 test_commit file1 &&
201 for f in .git/reftable/*.ref
203 : >"$f" || return 1
204 done &&
205 test_must_fail git update-ref refs/heads/main HEAD
209 test_expect_success 'ref transaction: corrupted tables.list cause failure' '
210 test_when_finished "rm -rf repo" &&
211 git init repo &&
213 cd repo &&
214 test_commit file1 &&
215 echo garbage >.git/reftable/tables.list &&
216 test_must_fail git update-ref refs/heads/main HEAD
220 test_expect_success 'ref transaction: refuses to write ref causing F/D conflict' '
221 test_when_finished "rm -rf repo" &&
222 git init repo &&
223 test_commit -C repo file &&
224 test_must_fail git -C repo update-ref refs/heads/main/forbidden
227 test_expect_success 'ref transaction: deleting ref with invalid name fails' '
228 test_when_finished "rm -rf repo" &&
229 git init repo &&
230 test_commit -C repo file &&
231 test_must_fail git -C repo update-ref -d ../../my-private-file
234 test_expect_success 'ref transaction: can skip object ID verification' '
235 test_when_finished "rm -rf repo" &&
236 git init repo &&
237 test_must_fail test-tool -C repo ref-store main update-ref msg refs/heads/branch $INVALID_OID $ZERO_OID 0 &&
238 test-tool -C repo ref-store main update-ref msg refs/heads/branch $INVALID_OID $ZERO_OID REF_SKIP_OID_VERIFICATION
241 test_expect_success 'ref transaction: updating same ref multiple times fails' '
242 test_when_finished "rm -rf repo" &&
243 git init repo &&
244 test_commit -C repo A &&
245 cat >updates <<-EOF &&
246 update refs/heads/main $A
247 update refs/heads/main $A
249 cat >expect <<-EOF &&
250 fatal: multiple updates for ref ${SQ}refs/heads/main${SQ} not allowed
252 test_must_fail git -C repo update-ref --stdin <updates 2>err &&
253 test_cmp expect err
256 test_expect_success 'ref transaction: can delete symbolic self-reference with git-symbolic-ref(1)' '
257 test_when_finished "rm -rf repo" &&
258 git init repo &&
259 git -C repo symbolic-ref refs/heads/self refs/heads/self &&
260 git -C repo symbolic-ref -d refs/heads/self
263 test_expect_success 'ref transaction: deleting symbolic self-reference without --no-deref fails' '
264 test_when_finished "rm -rf repo" &&
265 git init repo &&
266 git -C repo symbolic-ref refs/heads/self refs/heads/self &&
267 cat >expect <<-EOF &&
268 error: multiple updates for ${SQ}refs/heads/self${SQ} (including one via symref ${SQ}refs/heads/self${SQ}) are not allowed
270 test_must_fail git -C repo update-ref -d refs/heads/self 2>err &&
271 test_cmp expect err
274 test_expect_success 'ref transaction: deleting symbolic self-reference with --no-deref succeeds' '
275 test_when_finished "rm -rf repo" &&
276 git init repo &&
277 git -C repo symbolic-ref refs/heads/self refs/heads/self &&
278 git -C repo update-ref -d --no-deref refs/heads/self
281 test_expect_success 'ref transaction: creating symbolic ref fails with F/D conflict' '
282 test_when_finished "rm -rf repo" &&
283 git init repo &&
284 test_commit -C repo A &&
285 cat >expect <<-EOF &&
286 error: ${SQ}refs/heads/main${SQ} exists; cannot create ${SQ}refs/heads${SQ}
288 test_must_fail git -C repo symbolic-ref refs/heads refs/heads/foo 2>err &&
289 test_cmp expect err
292 test_expect_success 'ref transaction: ref deletion' '
293 test_when_finished "rm -rf repo" &&
294 git init repo &&
296 cd repo &&
297 test_commit file &&
298 HEAD_OID=$(git show-ref -s --verify HEAD) &&
299 cat >expect <<-EOF &&
300 $HEAD_OID refs/heads/main
301 $HEAD_OID refs/tags/file
303 git show-ref >actual &&
304 test_cmp expect actual &&
306 test_must_fail git update-ref -d refs/tags/file $INVALID_OID &&
307 git show-ref >actual &&
308 test_cmp expect actual &&
310 git update-ref -d refs/tags/file $HEAD_OID &&
311 echo "$HEAD_OID refs/heads/main" >expect &&
312 git show-ref >actual &&
313 test_cmp expect actual
317 test_expect_success 'ref transaction: writes cause auto-compaction' '
318 test_when_finished "rm -rf repo" &&
320 git init repo &&
321 test_line_count = 1 repo/.git/reftable/tables.list &&
323 test_commit -C repo --no-tag A &&
324 test_line_count = 1 repo/.git/reftable/tables.list &&
326 test_commit -C repo --no-tag B &&
327 test_line_count = 1 repo/.git/reftable/tables.list
330 test_expect_success 'ref transaction: env var disables compaction' '
331 test_when_finished "rm -rf repo" &&
333 git init repo &&
334 test_commit -C repo A &&
336 start=$(wc -l <repo/.git/reftable/tables.list) &&
337 iterations=5 &&
338 expected=$((start + iterations)) &&
340 for i in $(test_seq $iterations)
342 GIT_TEST_REFTABLE_AUTOCOMPACTION=false \
343 git -C repo update-ref branch-$i HEAD || return 1
344 done &&
345 test_line_count = $expected repo/.git/reftable/tables.list &&
347 git -C repo update-ref foo HEAD &&
348 test_line_count -lt $expected repo/.git/reftable/tables.list
351 test_expect_success 'ref transaction: alternating table sizes are compacted' '
352 test_when_finished "rm -rf repo" &&
354 git init repo &&
355 test_commit -C repo A &&
356 for i in $(test_seq 5)
358 git -C repo branch -f foo &&
359 git -C repo branch -d foo || return 1
360 done &&
361 test_line_count = 2 repo/.git/reftable/tables.list
364 check_fsync_events () {
365 local trace="$1" &&
366 shift &&
368 cat >expect &&
369 sed -n \
370 -e '/^{"event":"counter",.*"category":"fsync",/ {
371 s/.*"category":"fsync",//;
372 s/}$//;
374 }' \
375 <"$trace" >actual &&
376 test_cmp expect actual
379 test_expect_success 'ref transaction: writes are synced' '
380 test_when_finished "rm -rf repo" &&
381 git init repo &&
382 test_commit -C repo initial &&
384 GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
385 GIT_TEST_FSYNC=true \
386 git -C repo -c core.fsync=reference \
387 -c core.fsyncMethod=fsync update-ref refs/heads/branch HEAD &&
388 check_fsync_events trace2.txt <<-EOF
389 "name":"hardware-flush","count":4
393 test_expect_success 'ref transaction: empty transaction in empty repo' '
394 test_when_finished "rm -rf repo" &&
395 git init repo &&
396 test_commit -C repo --no-tag A &&
397 git -C repo update-ref -d refs/heads/main &&
398 test-tool -C repo ref-store main delete-refs REF_NO_DEREF msg HEAD &&
399 git -C repo update-ref --stdin <<-EOF
400 prepare
401 commit
405 test_expect_success 'ref transaction: fails gracefully when auto compaction fails' '
406 test_when_finished "rm -rf repo" &&
407 git init repo &&
409 cd repo &&
411 test_commit A &&
412 for i in $(test_seq 10)
414 git branch branch-$i &&
415 for table in .git/reftable/*.ref
417 touch "$table.lock" || exit 1
418 done ||
419 exit 1
420 done &&
421 test_line_count = 10 .git/reftable/tables.list
425 test_expect_success 'pack-refs: compacts tables' '
426 test_when_finished "rm -rf repo" &&
427 git init repo &&
429 test_commit -C repo A &&
430 ls -1 repo/.git/reftable >table-files &&
431 test_line_count = 3 table-files &&
432 test_line_count = 2 repo/.git/reftable/tables.list &&
434 git -C repo pack-refs &&
435 ls -1 repo/.git/reftable >table-files &&
436 test_line_count = 2 table-files &&
437 test_line_count = 1 repo/.git/reftable/tables.list
440 test_expect_success 'pack-refs: compaction raises locking errors' '
441 test_when_finished "rm -rf repo" &&
442 git init repo &&
443 test_commit -C repo A &&
444 touch repo/.git/reftable/tables.list.lock &&
445 cat >expect <<-EOF &&
446 error: unable to compact stack: data is locked
448 test_must_fail git -C repo pack-refs 2>err &&
449 test_cmp expect err
452 for command in pack-refs gc "maintenance run --task=pack-refs"
454 test_expect_success "$command: auto compaction" '
455 test_when_finished "rm -rf repo" &&
456 git init repo &&
458 cd repo &&
460 test_commit A &&
462 # We need a bit of setup to ensure that git-gc(1) actually
463 # triggers, and that it does not write anything to the refdb.
464 git config gc.auto 1 &&
465 git config gc.autoDetach 0 &&
466 git config gc.reflogExpire never &&
467 git config gc.reflogExpireUnreachable never &&
468 test_oid blob17_1 | git hash-object -w --stdin &&
470 # The tables should have been auto-compacted, and thus auto
471 # compaction should not have to do anything.
472 ls -1 .git/reftable >tables-expect &&
473 test_line_count = 3 tables-expect &&
474 git $command --auto &&
475 ls -1 .git/reftable >tables-actual &&
476 test_cmp tables-expect tables-actual &&
478 test_oid blob17_2 | git hash-object -w --stdin &&
480 # Lock all tables write some refs. Auto-compaction will be
481 # unable to compact tables and thus fails gracefully, leaving
482 # the stack in a sub-optimal state.
483 ls .git/reftable/*.ref |
484 while read table
486 touch "$table.lock" || exit 1
487 done &&
488 git branch B &&
489 git branch C &&
490 rm .git/reftable/*.lock &&
491 test_line_count = 4 .git/reftable/tables.list &&
493 git $command --auto &&
494 test_line_count = 1 .git/reftable/tables.list
497 done
499 test_expect_success 'pack-refs: prunes stale tables' '
500 test_when_finished "rm -rf repo" &&
501 git init repo &&
502 touch repo/.git/reftable/stale-table.ref &&
503 git -C repo pack-refs &&
504 test_path_is_missing repo/.git/reftable/stable-ref.ref
507 test_expect_success 'pack-refs: does not prune non-table files' '
508 test_when_finished "rm -rf repo" &&
509 git init repo &&
510 touch repo/.git/reftable/garbage &&
511 git -C repo pack-refs &&
512 test_path_is_file repo/.git/reftable/garbage
515 test_expect_success 'packed-refs: writes are synced' '
516 test_when_finished "rm -rf repo" &&
517 git init repo &&
518 test_commit -C repo initial &&
519 test_line_count = 2 table-files &&
521 : >trace2.txt &&
522 GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
523 GIT_TEST_FSYNC=true \
524 git -C repo -c core.fsync=reference \
525 -c core.fsyncMethod=fsync pack-refs &&
526 check_fsync_events trace2.txt <<-EOF
527 "name":"hardware-flush","count":2
531 test_expect_success 'ref iterator: bogus names are flagged' '
532 test_when_finished "rm -rf repo" &&
533 git init repo &&
535 cd repo &&
536 test_commit --no-tag file &&
537 test-tool ref-store main update-ref msg "refs/heads/bogus..name" $(git rev-parse HEAD) $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
539 cat >expect <<-EOF &&
540 $ZERO_OID refs/heads/bogus..name 0xc
541 $(git rev-parse HEAD) refs/heads/main 0x0
543 test-tool ref-store main for-each-ref "" >actual &&
544 test_cmp expect actual
548 test_expect_success 'ref iterator: missing object IDs are not flagged' '
549 test_when_finished "rm -rf repo" &&
550 git init repo &&
552 cd repo &&
553 test-tool ref-store main update-ref msg "refs/heads/broken-hash" $INVALID_OID $ZERO_OID REF_SKIP_OID_VERIFICATION &&
555 cat >expect <<-EOF &&
556 $INVALID_OID refs/heads/broken-hash 0x0
558 test-tool ref-store main for-each-ref "" >actual &&
559 test_cmp expect actual
563 test_expect_success 'basic: commit and list refs' '
564 test_when_finished "rm -rf repo" &&
565 git init repo &&
566 test_commit -C repo file &&
567 test_write_lines refs/heads/main refs/tags/file >expect &&
568 git -C repo for-each-ref --format="%(refname)" >actual &&
569 test_cmp actual expect
572 test_expect_success 'basic: can write large commit message' '
573 test_when_finished "rm -rf repo" &&
574 git init repo &&
575 perl -e "
576 print \"this is a long commit message\" x 50000
577 " >commit-msg &&
578 git -C repo commit --allow-empty --file=../commit-msg
581 test_expect_success 'basic: show-ref fails with empty repository' '
582 test_when_finished "rm -rf repo" &&
583 git init repo &&
584 test_must_fail git -C repo show-ref >actual &&
585 test_must_be_empty actual
588 test_expect_success 'basic: can check out unborn branch' '
589 test_when_finished "rm -rf repo" &&
590 git init repo &&
591 git -C repo checkout -b main
594 test_expect_success 'basic: peeled tags are stored' '
595 test_when_finished "rm -rf repo" &&
596 git init repo &&
597 test_commit -C repo file &&
598 git -C repo tag -m "annotated tag" test_tag HEAD &&
599 for ref in refs/heads/main refs/tags/file refs/tags/test_tag refs/tags/test_tag^{}
601 echo "$(git -C repo rev-parse "$ref") $ref" || return 1
602 done >expect &&
603 git -C repo show-ref -d >actual &&
604 test_cmp expect actual
607 test_expect_success 'basic: for-each-ref can print symrefs' '
608 test_when_finished "rm -rf repo" &&
609 git init repo &&
611 cd repo &&
612 test_commit file &&
613 git branch &&
614 git symbolic-ref refs/heads/sym refs/heads/main &&
615 cat >expected <<-EOF &&
616 refs/heads/main
618 git for-each-ref --format="%(symref)" refs/heads/sym >actual &&
619 test_cmp expected actual
623 test_expect_success 'basic: notes' '
624 test_when_finished "rm -rf repo" &&
625 git init repo &&
627 write_script fake_editor <<-\EOF &&
628 echo "$MSG" >"$1"
629 echo "$MSG" >&2
632 test_commit 1st &&
633 test_commit 2nd &&
634 GIT_EDITOR=./fake_editor MSG=b4 git notes add &&
635 GIT_EDITOR=./fake_editor MSG=b3 git notes edit &&
636 echo b4 >expect &&
637 git notes --ref commits@{1} show >actual &&
638 test_cmp expect actual
642 test_expect_success 'basic: stash' '
643 test_when_finished "rm -rf repo" &&
644 git init repo &&
646 cd repo &&
647 test_commit file &&
648 git stash list >expect &&
649 test_line_count = 0 expect &&
651 echo hoi >>file.t &&
652 git stash push -m stashed &&
653 git stash list >expect &&
654 test_line_count = 1 expect &&
656 git stash clear &&
657 git stash list >expect &&
658 test_line_count = 0 expect
662 test_expect_success 'basic: cherry-pick' '
663 test_when_finished "rm -rf repo" &&
664 git init repo &&
666 cd repo &&
667 test_commit message1 file1 &&
668 test_commit message2 file2 &&
669 git branch source &&
670 git checkout HEAD^ &&
671 test_commit message3 file3 &&
672 git cherry-pick source &&
673 test_path_is_file file2
677 test_expect_success 'basic: rebase' '
678 test_when_finished "rm -rf repo" &&
679 git init repo &&
681 cd repo &&
682 test_commit message1 file1 &&
683 test_commit message2 file2 &&
684 git branch source &&
685 git checkout HEAD^ &&
686 test_commit message3 file3 &&
687 git rebase source &&
688 test_path_is_file file2
692 test_expect_success 'reflog: can delete separate reflog entries' '
693 test_when_finished "rm -rf repo" &&
694 git init repo &&
696 cd repo &&
698 test_commit file &&
699 test_commit file2 &&
700 test_commit file3 &&
701 test_commit file4 &&
702 git reflog >actual &&
703 grep file3 actual &&
705 git reflog delete HEAD@{1} &&
706 git reflog >actual &&
707 ! grep file3 actual
711 test_expect_success 'reflog: can switch to previous branch' '
712 test_when_finished "rm -rf repo" &&
713 git init repo &&
715 cd repo &&
716 test_commit file1 &&
717 git checkout -b branch1 &&
718 test_commit file2 &&
719 git checkout -b branch2 &&
720 git switch - &&
721 git rev-parse --symbolic-full-name HEAD >actual &&
722 echo refs/heads/branch1 >expect &&
723 test_cmp actual expect
727 test_expect_success 'reflog: copying branch writes reflog entry' '
728 test_when_finished "rm -rf repo" &&
729 git init repo &&
731 cd repo &&
732 test_commit file1 &&
733 test_commit file2 &&
734 oid=$(git rev-parse --short HEAD) &&
735 git branch src &&
736 cat >expect <<-EOF &&
737 ${oid} dst@{0}: Branch: copied refs/heads/src to refs/heads/dst
738 ${oid} dst@{1}: branch: Created from main
740 git branch -c src dst &&
741 git reflog dst >actual &&
742 test_cmp expect actual
746 test_expect_success 'reflog: renaming branch writes reflog entry' '
747 test_when_finished "rm -rf repo" &&
748 git init repo &&
750 cd repo &&
751 git symbolic-ref HEAD refs/heads/before &&
752 test_commit file &&
753 git show-ref >expected.refs &&
754 sed s/before/after/g <expected.refs >expected &&
755 git branch -M after &&
756 git show-ref >actual &&
757 test_cmp expected actual &&
758 echo refs/heads/after >expected &&
759 git symbolic-ref HEAD >actual &&
760 test_cmp expected actual
764 test_expect_success 'reflog: can store empty logs' '
765 test_when_finished "rm -rf repo" &&
766 git init repo &&
768 cd repo &&
770 test_must_fail test-tool ref-store main reflog-exists refs/heads/branch &&
771 test-tool ref-store main create-reflog refs/heads/branch &&
772 test-tool ref-store main reflog-exists refs/heads/branch &&
773 test-tool ref-store main for-each-reflog-ent-reverse refs/heads/branch >actual &&
774 test_must_be_empty actual
778 test_expect_success 'reflog: expiry empties reflog' '
779 test_when_finished "rm -rf repo" &&
780 git init repo &&
782 cd repo &&
784 test_commit initial &&
785 git checkout -b branch &&
786 test_commit fileA &&
787 test_commit fileB &&
789 cat >expect <<-EOF &&
790 commit: fileB
791 commit: fileA
792 branch: Created from HEAD
794 git reflog show --format="%gs" refs/heads/branch >actual &&
795 test_cmp expect actual &&
797 git reflog expire branch --expire=all &&
798 git reflog show --format="%gs" refs/heads/branch >actual &&
799 test_must_be_empty actual &&
800 test-tool ref-store main reflog-exists refs/heads/branch
804 test_expect_success 'reflog: can be deleted' '
805 test_when_finished "rm -rf repo" &&
806 git init repo &&
808 cd repo &&
809 test_commit initial &&
810 test-tool ref-store main reflog-exists refs/heads/main &&
811 test-tool ref-store main delete-reflog refs/heads/main &&
812 test_must_fail test-tool ref-store main reflog-exists refs/heads/main
816 test_expect_success 'reflog: garbage collection deletes reflog entries' '
817 test_when_finished "rm -rf repo" &&
818 git init repo &&
820 cd repo &&
822 for count in $(test_seq 1 10)
824 test_commit "number $count" file.t $count number-$count ||
825 return 1
826 done &&
827 git reflog refs/heads/main >actual &&
828 test_line_count = 10 actual &&
829 grep "commit (initial): number 1" actual &&
830 grep "commit: number 10" actual &&
832 git gc &&
833 git reflog refs/heads/main >actual &&
834 test_line_count = 0 actual
838 test_expect_success 'reflog: updates via HEAD update HEAD reflog' '
839 test_when_finished "rm -rf repo" &&
840 git init repo &&
842 cd repo &&
843 test_commit main-one &&
844 git checkout -b new-branch &&
845 test_commit new-one &&
846 test_commit new-two &&
848 echo new-one >expect &&
849 git log -1 --format=%s HEAD@{1} >actual &&
850 test_cmp expect actual
854 test_expect_success 'branch: copying branch with D/F conflict' '
855 test_when_finished "rm -rf repo" &&
856 git init repo &&
858 cd repo &&
859 test_commit A &&
860 git branch branch &&
861 cat >expect <<-EOF &&
862 error: ${SQ}refs/heads/branch${SQ} exists; cannot create ${SQ}refs/heads/branch/moved${SQ}
863 fatal: branch copy failed
865 test_must_fail git branch -c branch branch/moved 2>err &&
866 test_cmp expect err
870 test_expect_success 'branch: moving branch with D/F conflict' '
871 test_when_finished "rm -rf repo" &&
872 git init repo &&
874 cd repo &&
875 test_commit A &&
876 git branch branch &&
877 git branch conflict &&
878 cat >expect <<-EOF &&
879 error: ${SQ}refs/heads/conflict${SQ} exists; cannot create ${SQ}refs/heads/conflict/moved${SQ}
880 fatal: branch rename failed
882 test_must_fail git branch -m branch conflict/moved 2>err &&
883 test_cmp expect err
887 test_expect_success 'worktree: adding worktree creates separate stack' '
888 test_when_finished "rm -rf repo worktree" &&
889 git init repo &&
890 test_commit -C repo A &&
892 git -C repo worktree add ../worktree &&
893 test_path_is_file repo/.git/worktrees/worktree/refs/heads &&
894 echo "ref: refs/heads/.invalid" >expect &&
895 test_cmp expect repo/.git/worktrees/worktree/HEAD &&
896 test_path_is_dir repo/.git/worktrees/worktree/reftable &&
897 test_path_is_file repo/.git/worktrees/worktree/reftable/tables.list
900 test_expect_success 'worktree: pack-refs in main repo packs main refs' '
901 test_when_finished "rm -rf repo worktree" &&
902 git init repo &&
903 test_commit -C repo A &&
905 GIT_TEST_REFTABLE_AUTOCOMPACTION=false \
906 git -C repo worktree add ../worktree &&
907 GIT_TEST_REFTABLE_AUTOCOMPACTION=false \
908 git -C worktree update-ref refs/worktree/per-worktree HEAD &&
910 test_line_count = 4 repo/.git/worktrees/worktree/reftable/tables.list &&
911 test_line_count = 3 repo/.git/reftable/tables.list &&
912 git -C repo pack-refs &&
913 test_line_count = 4 repo/.git/worktrees/worktree/reftable/tables.list &&
914 test_line_count = 1 repo/.git/reftable/tables.list
917 test_expect_success 'worktree: pack-refs in worktree packs worktree refs' '
918 test_when_finished "rm -rf repo worktree" &&
919 git init repo &&
920 test_commit -C repo A &&
922 GIT_TEST_REFTABLE_AUTOCOMPACTION=false \
923 git -C repo worktree add ../worktree &&
924 GIT_TEST_REFTABLE_AUTOCOMPACTION=false \
925 git -C worktree update-ref refs/worktree/per-worktree HEAD &&
927 test_line_count = 4 repo/.git/worktrees/worktree/reftable/tables.list &&
928 test_line_count = 3 repo/.git/reftable/tables.list &&
929 git -C worktree pack-refs &&
930 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
931 test_line_count = 3 repo/.git/reftable/tables.list
934 test_expect_success 'worktree: creating shared ref updates main stack' '
935 test_when_finished "rm -rf repo worktree" &&
936 git init repo &&
937 test_commit -C repo A &&
939 git -C repo worktree add ../worktree &&
940 git -C repo pack-refs &&
941 git -C worktree pack-refs &&
942 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
943 test_line_count = 1 repo/.git/reftable/tables.list &&
945 GIT_TEST_REFTABLE_AUTOCOMPACTION=false \
946 git -C worktree update-ref refs/heads/shared HEAD &&
947 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
948 test_line_count = 2 repo/.git/reftable/tables.list
951 test_expect_success 'worktree: creating per-worktree ref updates worktree stack' '
952 test_when_finished "rm -rf repo worktree" &&
953 git init repo &&
954 test_commit -C repo A &&
956 git -C repo worktree add ../worktree &&
957 git -C repo pack-refs &&
958 git -C worktree pack-refs &&
959 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
960 test_line_count = 1 repo/.git/reftable/tables.list &&
962 git -C worktree update-ref refs/bisect/per-worktree HEAD &&
963 test_line_count = 2 repo/.git/worktrees/worktree/reftable/tables.list &&
964 test_line_count = 1 repo/.git/reftable/tables.list
967 test_expect_success 'worktree: creating per-worktree ref from main repo' '
968 test_when_finished "rm -rf repo worktree" &&
969 git init repo &&
970 test_commit -C repo A &&
972 git -C repo worktree add ../worktree &&
973 git -C repo pack-refs &&
974 git -C worktree pack-refs &&
975 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
976 test_line_count = 1 repo/.git/reftable/tables.list &&
978 git -C repo update-ref worktrees/worktree/refs/bisect/per-worktree HEAD &&
979 test_line_count = 2 repo/.git/worktrees/worktree/reftable/tables.list &&
980 test_line_count = 1 repo/.git/reftable/tables.list
983 test_expect_success 'worktree: creating per-worktree ref from second worktree' '
984 test_when_finished "rm -rf repo wt1 wt2" &&
985 git init repo &&
986 test_commit -C repo A &&
988 git -C repo worktree add ../wt1 &&
989 git -C repo worktree add ../wt2 &&
990 git -C repo pack-refs &&
991 git -C wt1 pack-refs &&
992 git -C wt2 pack-refs &&
993 test_line_count = 1 repo/.git/worktrees/wt1/reftable/tables.list &&
994 test_line_count = 1 repo/.git/worktrees/wt2/reftable/tables.list &&
995 test_line_count = 1 repo/.git/reftable/tables.list &&
997 git -C wt1 update-ref worktrees/wt2/refs/bisect/per-worktree HEAD &&
998 test_line_count = 1 repo/.git/worktrees/wt1/reftable/tables.list &&
999 test_line_count = 2 repo/.git/worktrees/wt2/reftable/tables.list &&
1000 test_line_count = 1 repo/.git/reftable/tables.list
1003 test_expect_success 'worktree: can create shared and per-worktree ref in one transaction' '
1004 test_when_finished "rm -rf repo worktree" &&
1005 git init repo &&
1006 test_commit -C repo A &&
1008 git -C repo worktree add ../worktree &&
1009 git -C repo pack-refs &&
1010 git -C worktree pack-refs &&
1011 test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
1012 test_line_count = 1 repo/.git/reftable/tables.list &&
1014 cat >stdin <<-EOF &&
1015 create worktrees/worktree/refs/bisect/per-worktree HEAD
1016 create refs/branches/shared HEAD
1018 git -C repo update-ref --stdin <stdin &&
1019 test_line_count = 2 repo/.git/worktrees/worktree/reftable/tables.list &&
1020 test_line_count = 2 repo/.git/reftable/tables.list
1023 test_expect_success 'worktree: can access common refs' '
1024 test_when_finished "rm -rf repo worktree" &&
1025 git init repo &&
1026 test_commit -C repo file1 &&
1027 git -C repo branch branch1 &&
1028 git -C repo worktree add ../worktree &&
1030 echo refs/heads/worktree >expect &&
1031 git -C worktree symbolic-ref HEAD >actual &&
1032 test_cmp expect actual &&
1033 git -C worktree checkout branch1
1036 test_expect_success 'worktree: adds worktree with detached HEAD' '
1037 test_when_finished "rm -rf repo worktree" &&
1039 git init repo &&
1040 test_commit -C repo A &&
1041 git -C repo rev-parse main >expect &&
1043 git -C repo worktree add --detach ../worktree main &&
1044 git -C worktree rev-parse HEAD >actual &&
1045 test_cmp expect actual
1048 test_expect_success 'fetch: accessing FETCH_HEAD special ref works' '
1049 test_when_finished "rm -rf repo sub" &&
1051 git init sub &&
1052 test_commit -C sub two &&
1053 git -C sub rev-parse HEAD >expect &&
1055 git init repo &&
1056 test_commit -C repo one &&
1057 git -C repo fetch ../sub &&
1058 git -C repo rev-parse FETCH_HEAD >actual &&
1059 test_cmp expect actual
1062 test_done