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