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