Jeff King | 9eb0986 | 2018-08-16 08:13:11 +0200 | [diff] [blame] | 1 | #!/bin/sh |
| 2 | |
| 3 | test_description='exercise delta islands' |
Ævar Arnfjörð Bjarmason | e75d2f7 | 2022-04-13 22:01:48 +0200 | [diff] [blame] | 4 | |
| 5 | TEST_PASSES_SANITIZE_LEAK=true |
Jeff King | 9eb0986 | 2018-08-16 08:13:11 +0200 | [diff] [blame] | 6 | . ./test-lib.sh |
| 7 | |
| 8 | # returns true iff $1 is a delta based on $2 |
| 9 | is_delta_base () { |
| 10 | delta_base=$(echo "$1" | git cat-file --batch-check='%(deltabase)') && |
| 11 | echo >&2 "$1 has base $delta_base" && |
| 12 | test "$delta_base" = "$2" |
| 13 | } |
| 14 | |
| 15 | # generate a commit on branch $1 with a single file, "file", whose |
| 16 | # content is mostly based on the seed $2, but with a unique bit |
| 17 | # of content $3 appended. This should allow us to see whether |
| 18 | # blobs of different refs delta against each other. |
| 19 | commit() { |
| 20 | blob=$({ test-tool genrandom "$2" 10240 && echo "$3"; } | |
| 21 | git hash-object -w --stdin) && |
| 22 | tree=$(printf '100644 blob %s\tfile\n' "$blob" | git mktree) && |
| 23 | commit=$(echo "$2-$3" | git commit-tree "$tree" ${4:+-p "$4"}) && |
| 24 | git update-ref "refs/heads/$1" "$commit" && |
| 25 | eval "$1"'=$(git rev-parse $1:file)' && |
| 26 | eval "echo >&2 $1=\$$1" |
| 27 | } |
| 28 | |
| 29 | test_expect_success 'setup commits' ' |
| 30 | commit one seed 1 && |
| 31 | commit two seed 12 |
| 32 | ' |
| 33 | |
| 34 | # Note: This is heavily dependent on the "prefer larger objects as base" |
| 35 | # heuristic. |
| 36 | test_expect_success 'vanilla repack deltas one against two' ' |
| 37 | git repack -adf && |
| 38 | is_delta_base $one $two |
| 39 | ' |
| 40 | |
| 41 | test_expect_success 'island repack with no island definition is vanilla' ' |
| 42 | git repack -adfi && |
| 43 | is_delta_base $one $two |
| 44 | ' |
| 45 | |
| 46 | test_expect_success 'island repack with no matches is vanilla' ' |
| 47 | git -c "pack.island=refs/foo" repack -adfi && |
| 48 | is_delta_base $one $two |
| 49 | ' |
| 50 | |
| 51 | test_expect_success 'separate islands disallows delta' ' |
| 52 | git -c "pack.island=refs/heads/(.*)" repack -adfi && |
| 53 | ! is_delta_base $one $two && |
| 54 | ! is_delta_base $two $one |
| 55 | ' |
| 56 | |
| 57 | test_expect_success 'same island allows delta' ' |
| 58 | git -c "pack.island=refs/heads" repack -adfi && |
| 59 | is_delta_base $one $two |
| 60 | ' |
| 61 | |
| 62 | test_expect_success 'coalesce same-named islands' ' |
| 63 | git \ |
| 64 | -c "pack.island=refs/(.*)/one" \ |
| 65 | -c "pack.island=refs/(.*)/two" \ |
| 66 | repack -adfi && |
| 67 | is_delta_base $one $two |
| 68 | ' |
| 69 | |
| 70 | test_expect_success 'island restrictions drop reused deltas' ' |
| 71 | git repack -adfi && |
| 72 | is_delta_base $one $two && |
| 73 | git -c "pack.island=refs/heads/(.*)" repack -adi && |
| 74 | ! is_delta_base $one $two && |
| 75 | ! is_delta_base $two $one |
| 76 | ' |
| 77 | |
| 78 | test_expect_success 'island regexes are left-anchored' ' |
| 79 | git -c "pack.island=heads/(.*)" repack -adfi && |
| 80 | is_delta_base $one $two |
| 81 | ' |
| 82 | |
| 83 | test_expect_success 'island regexes follow last-one-wins scheme' ' |
| 84 | git \ |
| 85 | -c "pack.island=refs/heads/(.*)" \ |
| 86 | -c "pack.island=refs/heads/" \ |
| 87 | repack -adfi && |
| 88 | is_delta_base $one $two |
| 89 | ' |
| 90 | |
| 91 | test_expect_success 'setup shared history' ' |
| 92 | commit root shared root && |
| 93 | commit one shared 1 root && |
| 94 | commit two shared 12-long root |
| 95 | ' |
| 96 | |
| 97 | # We know that $two will be preferred as a base from $one, |
| 98 | # because we can transform it with a pure deletion. |
| 99 | # |
| 100 | # We also expect $root as a delta against $two by the "longest is base" rule. |
| 101 | test_expect_success 'vanilla delta goes between branches' ' |
| 102 | git repack -adf && |
| 103 | is_delta_base $one $two && |
| 104 | is_delta_base $root $two |
| 105 | ' |
| 106 | |
| 107 | # Here we should allow $one to base itself on $root; even though |
| 108 | # they are in different islands, the objects in $root are in a superset |
| 109 | # of islands compared to those in $one. |
| 110 | # |
| 111 | # Similarly, $two can delta against $root by our rules. And unlike $one, |
| 112 | # in which we are just allowing it, the island rules actually put $root |
| 113 | # as a possible base for $two, which it would not otherwise be (due to the size |
| 114 | # sorting). |
| 115 | test_expect_success 'deltas allowed against superset islands' ' |
| 116 | git -c "pack.island=refs/heads/(.*)" repack -adfi && |
| 117 | is_delta_base $one $root && |
| 118 | is_delta_base $two $root |
| 119 | ' |
| 120 | |
| 121 | # We are going to test the packfile order here, so we again have to make some |
| 122 | # assumptions. We assume that "$root", as part of our core "one", must come |
| 123 | # before "$two". This should be guaranteed by the island code. However, for |
| 124 | # this test to fail without islands, we are also assuming that it would not |
| 125 | # otherwise do so. This is true by the current write order, which will put |
| 126 | # commits (and their contents) before their parents. |
| 127 | test_expect_success 'island core places core objects first' ' |
| 128 | cat >expect <<-EOF && |
| 129 | $root |
| 130 | $two |
| 131 | EOF |
| 132 | git -c "pack.island=refs/heads/(.*)" \ |
| 133 | -c "pack.islandcore=one" \ |
| 134 | repack -adfi && |
| 135 | git verify-pack -v .git/objects/pack/*.pack | |
| 136 | cut -d" " -f1 | |
Đoàn Trần Công Danh | 81580fa | 2022-09-21 20:02:31 +0700 | [diff] [blame] | 137 | grep -E "$root|$two" >actual && |
Jeff King | 9eb0986 | 2018-08-16 08:13:11 +0200 | [diff] [blame] | 138 | test_cmp expect actual |
| 139 | ' |
| 140 | |
| 141 | test_expect_success 'unmatched island core is not fatal' ' |
| 142 | git -c "pack.islandcore=one" repack -adfi |
| 143 | ' |
| 144 | |
| 145 | test_done |