Merge branch 'ds/reprepare-alternates-when-repreparing-packfiles'
[alt-git.git] / t / t5320-delta-islands.sh
blob406363381f10bcc6ee4f8040afadcc362d85fc29
1 #!/bin/sh
3 test_description='exercise delta islands'
5 TEST_PASSES_SANITIZE_LEAK=true
6 . ./test-lib.sh
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"
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"
29 test_expect_success 'setup commits' '
30 commit one seed 1 &&
31 commit two seed 12
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
41 test_expect_success 'island repack with no island definition is vanilla' '
42 git repack -adfi &&
43 is_delta_base $one $two
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
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
57 test_expect_success 'same island allows delta' '
58 git -c "pack.island=refs/heads" repack -adfi &&
59 is_delta_base $one $two
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
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
78 test_expect_success 'island regexes are left-anchored' '
79 git -c "pack.island=heads/(.*)" repack -adfi &&
80 is_delta_base $one $two
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
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
97 # We know that $two will be preferred as a base from $one,
98 # because we can transform it with a pure deletion.
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
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.
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
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
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 |
137 grep -E "$root|$two" >actual &&
138 test_cmp expect actual
141 test_expect_success 'unmatched island core is not fatal' '
142 git -c "pack.islandcore=one" repack -adfi
145 test_done