]> git.ipfire.org Git - thirdparty/git.git/blobdiff - t/t0610-reftable-basics.sh
Merge branch 'ps/ci-test-with-jgit'
[thirdparty/git.git] / t / t0610-reftable-basics.sh
index dfa7e274ea26944aaeaff69f3cc4a898b2ee4adf..cc5bbfd732e2acd715b0bd749f55b67b764f03d8 100755 (executable)
@@ -93,23 +93,54 @@ test_expect_perms () {
        esac
 }
 
-for umask in 002 022
-do
-       test_expect_success POSIXPERM 'init: honors core.sharedRepository' '
+test_expect_reftable_perms () {
+       local umask="$1"
+       local shared="$2"
+       local expect="$3"
+
+       test_expect_success POSIXPERM "init: honors --shared=$shared with umask $umask" '
                test_when_finished "rm -rf repo" &&
                (
                        umask $umask &&
-                       git init --shared=true repo &&
-                       test 1 = "$(git -C repo config core.sharedrepository)"
+                       git init --shared=$shared repo
                ) &&
-               test_expect_perms "-rw-rw-r--" repo/.git/reftable/tables.list &&
+               test_expect_perms "$expect" repo/.git/reftable/tables.list &&
                for table in repo/.git/reftable/*.ref
                do
-                       test_expect_perms "-rw-rw-r--" "$table" ||
+                       test_expect_perms "$expect" "$table" ||
                        return 1
                done
        '
-done
+
+       test_expect_success POSIXPERM "pack-refs: honors --shared=$shared with umask $umask" '
+               test_when_finished "rm -rf repo" &&
+               (
+                       umask $umask &&
+                       git init --shared=$shared repo &&
+                       test_commit -C repo A &&
+                       test_line_count = 2 repo/.git/reftable/tables.list &&
+                       git -C repo pack-refs
+               ) &&
+               test_expect_perms "$expect" repo/.git/reftable/tables.list &&
+               for table in repo/.git/reftable/*.ref
+               do
+                       test_expect_perms "$expect" "$table" ||
+                       return 1
+               done
+       '
+}
+
+test_expect_reftable_perms 002 umask "-rw-rw-r--"
+test_expect_reftable_perms 022 umask "-rw-r--r--"
+test_expect_reftable_perms 027 umask "-rw-r-----"
+
+test_expect_reftable_perms 002 group "-rw-rw-r--"
+test_expect_reftable_perms 022 group "-rw-rw-r--"
+test_expect_reftable_perms 027 group "-rw-rw----"
+
+test_expect_reftable_perms 002 world "-rw-rw-r--"
+test_expect_reftable_perms 022 world "-rw-rw-r--"
+test_expect_reftable_perms 027 world "-rw-rw-r--"
 
 test_expect_success 'clone: can clone reftable repository' '
        test_when_finished "rm -rf repo clone" &&
@@ -252,7 +283,7 @@ test_expect_success 'ref transaction: creating symbolic ref fails with F/D confl
        git init repo &&
        test_commit -C repo A &&
        cat >expect <<-EOF &&
-       error: unable to write symref for refs/heads: file/directory conflict
+       error: ${SQ}refs/heads/main${SQ} exists; cannot create ${SQ}refs/heads${SQ}
        EOF
        test_must_fail git -C repo symbolic-ref refs/heads refs/heads/foo 2>err &&
        test_cmp expect err
@@ -290,12 +321,46 @@ test_expect_success 'ref transaction: writes cause auto-compaction' '
        test_line_count = 1 repo/.git/reftable/tables.list &&
 
        test_commit -C repo --no-tag A &&
-       test_line_count = 2 repo/.git/reftable/tables.list &&
+       test_line_count = 1 repo/.git/reftable/tables.list &&
 
        test_commit -C repo --no-tag B &&
        test_line_count = 1 repo/.git/reftable/tables.list
 '
 
+test_expect_success 'ref transaction: env var disables compaction' '
+       test_when_finished "rm -rf repo" &&
+
+       git init repo &&
+       test_commit -C repo A &&
+
+       start=$(wc -l <repo/.git/reftable/tables.list) &&
+       iterations=5 &&
+       expected=$((start + iterations)) &&
+
+       for i in $(test_seq $iterations)
+       do
+               GIT_TEST_REFTABLE_AUTOCOMPACTION=false \
+               git -C repo update-ref branch-$i HEAD || return 1
+       done &&
+       test_line_count = $expected repo/.git/reftable/tables.list &&
+
+       git -C repo update-ref foo HEAD &&
+       test_line_count -lt $expected repo/.git/reftable/tables.list
+'
+
+test_expect_success 'ref transaction: alternating table sizes are compacted' '
+       test_when_finished "rm -rf repo" &&
+
+       git init repo &&
+       test_commit -C repo A &&
+       for i in $(test_seq 5)
+       do
+               git -C repo branch -f foo &&
+               git -C repo branch -d foo || return 1
+       done &&
+       test_line_count = 2 repo/.git/reftable/tables.list
+'
+
 check_fsync_events () {
        local trace="$1" &&
        shift &&
@@ -321,7 +386,7 @@ test_expect_success 'ref transaction: writes are synced' '
                git -C repo -c core.fsync=reference \
                -c core.fsyncMethod=fsync update-ref refs/heads/branch HEAD &&
        check_fsync_events trace2.txt <<-EOF
-       "name":"hardware-flush","count":2
+       "name":"hardware-flush","count":4
        EOF
 '
 
@@ -337,14 +402,34 @@ test_expect_success 'ref transaction: empty transaction in empty repo' '
        EOF
 '
 
+test_expect_success 'ref transaction: fails gracefully when auto compaction fails' '
+       test_when_finished "rm -rf repo" &&
+       git init repo &&
+       (
+               cd repo &&
+
+               test_commit A &&
+               for i in $(test_seq 10)
+               do
+                       git branch branch-$i &&
+                       for table in .git/reftable/*.ref
+                       do
+                               touch "$table.lock" || exit 1
+                       done ||
+                       exit 1
+               done &&
+               test_line_count = 10 .git/reftable/tables.list
+       )
+'
+
 test_expect_success 'pack-refs: compacts tables' '
        test_when_finished "rm -rf repo" &&
        git init repo &&
 
        test_commit -C repo A &&
        ls -1 repo/.git/reftable >table-files &&
-       test_line_count = 4 table-files &&
-       test_line_count = 3 repo/.git/reftable/tables.list &&
+       test_line_count = 3 table-files &&
+       test_line_count = 2 repo/.git/reftable/tables.list &&
 
        git -C repo pack-refs &&
        ls -1 repo/.git/reftable >table-files &&
@@ -352,6 +437,65 @@ test_expect_success 'pack-refs: compacts tables' '
        test_line_count = 1 repo/.git/reftable/tables.list
 '
 
+test_expect_success 'pack-refs: compaction raises locking errors' '
+       test_when_finished "rm -rf repo" &&
+       git init repo &&
+       test_commit -C repo A &&
+       touch repo/.git/reftable/tables.list.lock &&
+       cat >expect <<-EOF &&
+       error: unable to compact stack: data is locked
+       EOF
+       test_must_fail git -C repo pack-refs 2>err &&
+       test_cmp expect err
+'
+
+for command in pack-refs gc "maintenance run --task=pack-refs"
+do
+test_expect_success "$command: auto compaction" '
+       test_when_finished "rm -rf repo" &&
+       git init repo &&
+       (
+               cd repo &&
+
+               test_commit A &&
+
+               # We need a bit of setup to ensure that git-gc(1) actually
+               # triggers, and that it does not write anything to the refdb.
+               git config gc.auto 1 &&
+               git config gc.autoDetach 0 &&
+               git config gc.reflogExpire never &&
+               git config gc.reflogExpireUnreachable never &&
+               test_oid blob17_1 | git hash-object -w --stdin &&
+
+               # The tables should have been auto-compacted, and thus auto
+               # compaction should not have to do anything.
+               ls -1 .git/reftable >tables-expect &&
+               test_line_count = 3 tables-expect &&
+               git $command --auto &&
+               ls -1 .git/reftable >tables-actual &&
+               test_cmp tables-expect tables-actual &&
+
+               test_oid blob17_2 | git hash-object -w --stdin &&
+
+               # Lock all tables write some refs. Auto-compaction will be
+               # unable to compact tables and thus fails gracefully, leaving
+               # the stack in a sub-optimal state.
+               ls .git/reftable/*.ref |
+               while read table
+               do
+                       touch "$table.lock" || exit 1
+               done &&
+               git branch B &&
+               git branch C &&
+               rm .git/reftable/*.lock &&
+               test_line_count = 4 .git/reftable/tables.list &&
+
+               git $command --auto &&
+               test_line_count = 1 .git/reftable/tables.list
+       )
+'
+done
+
 test_expect_success 'pack-refs: prunes stale tables' '
        test_when_finished "rm -rf repo" &&
        git init repo &&
@@ -368,26 +512,6 @@ test_expect_success 'pack-refs: does not prune non-table files' '
        test_path_is_file repo/.git/reftable/garbage
 '
 
-for umask in 002 022
-do
-       test_expect_success POSIXPERM 'pack-refs: honors core.sharedRepository' '
-               test_when_finished "rm -rf repo" &&
-               (
-                       umask $umask &&
-                       git init --shared=true repo &&
-                       test_commit -C repo A &&
-                       test_line_count = 3 repo/.git/reftable/tables.list
-               ) &&
-               git -C repo pack-refs &&
-               test_expect_perms "-rw-rw-r--" repo/.git/reftable/tables.list &&
-               for table in repo/.git/reftable/*.ref
-               do
-                       test_expect_perms "-rw-rw-r--" "$table" ||
-                       return 1
-               done
-       '
-done
-
 test_expect_success 'packed-refs: writes are synced' '
        test_when_finished "rm -rf repo" &&
        git init repo &&
@@ -727,6 +851,39 @@ test_expect_success 'reflog: updates via HEAD update HEAD reflog' '
        )
 '
 
+test_expect_success 'branch: copying branch with D/F conflict' '
+       test_when_finished "rm -rf repo" &&
+       git init repo &&
+       (
+               cd repo &&
+               test_commit A &&
+               git branch branch &&
+               cat >expect <<-EOF &&
+               error: ${SQ}refs/heads/branch${SQ} exists; cannot create ${SQ}refs/heads/branch/moved${SQ}
+               fatal: branch copy failed
+               EOF
+               test_must_fail git branch -c branch branch/moved 2>err &&
+               test_cmp expect err
+       )
+'
+
+test_expect_success 'branch: moving branch with D/F conflict' '
+       test_when_finished "rm -rf repo" &&
+       git init repo &&
+       (
+               cd repo &&
+               test_commit A &&
+               git branch branch &&
+               git branch conflict &&
+               cat >expect <<-EOF &&
+               error: ${SQ}refs/heads/conflict${SQ} exists; cannot create ${SQ}refs/heads/conflict/moved${SQ}
+               fatal: branch rename failed
+               EOF
+               test_must_fail git branch -m branch conflict/moved 2>err &&
+               test_cmp expect err
+       )
+'
+
 test_expect_success 'worktree: adding worktree creates separate stack' '
        test_when_finished "rm -rf repo worktree" &&
        git init repo &&
@@ -744,12 +901,16 @@ test_expect_success 'worktree: pack-refs in main repo packs main refs' '
        test_when_finished "rm -rf repo worktree" &&
        git init repo &&
        test_commit -C repo A &&
+
+       GIT_TEST_REFTABLE_AUTOCOMPACTION=false \
        git -C repo worktree add ../worktree &&
+       GIT_TEST_REFTABLE_AUTOCOMPACTION=false \
+       git -C worktree update-ref refs/worktree/per-worktree HEAD &&
 
-       test_line_count = 3 repo/.git/worktrees/worktree/reftable/tables.list &&
-       test_line_count = 4 repo/.git/reftable/tables.list &&
+       test_line_count = 4 repo/.git/worktrees/worktree/reftable/tables.list &&
+       test_line_count = 3 repo/.git/reftable/tables.list &&
        git -C repo pack-refs &&
-       test_line_count = 3 repo/.git/worktrees/worktree/reftable/tables.list &&
+       test_line_count = 4 repo/.git/worktrees/worktree/reftable/tables.list &&
        test_line_count = 1 repo/.git/reftable/tables.list
 '
 
@@ -757,13 +918,17 @@ test_expect_success 'worktree: pack-refs in worktree packs worktree refs' '
        test_when_finished "rm -rf repo worktree" &&
        git init repo &&
        test_commit -C repo A &&
+
+       GIT_TEST_REFTABLE_AUTOCOMPACTION=false \
        git -C repo worktree add ../worktree &&
+       GIT_TEST_REFTABLE_AUTOCOMPACTION=false \
+       git -C worktree update-ref refs/worktree/per-worktree HEAD &&
 
-       test_line_count = 3 repo/.git/worktrees/worktree/reftable/tables.list &&
-       test_line_count = 4 repo/.git/reftable/tables.list &&
+       test_line_count = 4 repo/.git/worktrees/worktree/reftable/tables.list &&
+       test_line_count = 3 repo/.git/reftable/tables.list &&
        git -C worktree pack-refs &&
        test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
-       test_line_count = 4 repo/.git/reftable/tables.list
+       test_line_count = 3 repo/.git/reftable/tables.list
 '
 
 test_expect_success 'worktree: creating shared ref updates main stack' '
@@ -777,6 +942,7 @@ test_expect_success 'worktree: creating shared ref updates main stack' '
        test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
        test_line_count = 1 repo/.git/reftable/tables.list &&
 
+       GIT_TEST_REFTABLE_AUTOCOMPACTION=false \
        git -C worktree update-ref refs/heads/shared HEAD &&
        test_line_count = 1 repo/.git/worktrees/worktree/reftable/tables.list &&
        test_line_count = 2 repo/.git/reftable/tables.list