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