Raw
1 #!/bin/sh
2
3 test_description='pack-objects multi-pack reuse'
4
5 . ./test-lib.sh
6 . "$TEST_DIRECTORY"/lib-bitmap.sh
7
8 GIT_TEST_MULTI_PACK_INDEX=0
9 GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL=0
10
11 # The --path-walk option does not consider the preferred pack
12 # at all for reusing deltas, so this variable changes the
13 # behavior of this test, if enabled.
14 GIT_TEST_PACK_PATH_WALK=0
15 export GIT_TEST_PACK_PATH_WALK
16
17 objdir=.git/objects
18 packdir=$objdir/pack
19
20 test_pack_reused () {
21 test_trace2_data pack-objects pack-reused "$1"
22 }
23
24 test_packs_reused () {
25 test_trace2_data pack-objects packs-reused "$1"
26 }
27
28
29 # pack_position <object> </path/to/pack.idx
30 pack_position () {
31 git show-index >objects &&
32 grep "$1" objects | cut -d" " -f1
33 }
34
35 # test_pack_objects_reused_all <pack-reused> <packs-reused>
36 test_pack_objects_reused_all () {
37 : >trace2.txt &&
38 GIT_TRACE2_EVENT="$PWD/trace2.txt" \
39 git pack-objects --stdout --revs --all --delta-base-offset \
40 >got.pack &&
41
42 test_pack_reused "$1" <trace2.txt &&
43 test_packs_reused "$2" <trace2.txt &&
44
45 git index-pack --strict -o got.idx got.pack
46 }
47
48 # test_pack_objects_reused <pack-reused> <packs-reused>
49 test_pack_objects_reused () {
50 : >trace2.txt &&
51 GIT_TRACE2_EVENT="$PWD/trace2.txt" \
52 git pack-objects --stdout --revs >got.pack &&
53
54 test_pack_reused "$1" <trace2.txt &&
55 test_packs_reused "$2" <trace2.txt &&
56
57 git index-pack --strict -o got.idx got.pack
58 }
59
60 test_expect_success 'preferred pack is reused for single-pack reuse' '
61 test_config pack.allowPackReuse single &&
62 git config set maintenance.auto false &&
63
64 for i in A B
65 do
66 test_commit "$i" &&
67 git repack -d || return 1
68 done &&
69
70 git multi-pack-index write --bitmap &&
71
72 test_pack_objects_reused_all 3 1
73 '
74
75 test_expect_success 'multi-pack reuse is disabled by default' '
76 test_pack_objects_reused_all 3 1
77 '
78
79 test_expect_success 'feature.experimental implies multi-pack reuse' '
80 test_config feature.experimental true &&
81
82 test_pack_objects_reused_all 6 2
83 '
84
85 test_expect_success 'multi-pack reuse can be disabled with feature.experimental' '
86 test_config feature.experimental true &&
87 test_config pack.allowPackReuse single &&
88
89 test_pack_objects_reused_all 3 1
90 '
91
92 test_expect_success 'enable multi-pack reuse' '
93 git config pack.allowPackReuse multi
94 '
95
96 test_expect_success 'reuse all objects from subset of bitmapped packs' '
97 test_commit C &&
98 git repack -d &&
99
100 git multi-pack-index write --bitmap &&
101
102 cat >in <<-EOF &&
103 $(git rev-parse C)
104 ^$(git rev-parse A)
105 EOF
106
107 test_pack_objects_reused 6 2 <in
108 '
109
110 test_expect_success 'reuse all objects from all packs' '
111 test_pack_objects_reused_all 9 3
112 '
113
114 test_expect_success '--no-ref-delta reuses REF_DELTA-free bitmapped packs' '
115 # Whole-word reuse is unavailable under --no-ref-delta, so reusing
116 # every object below exercises the per-object bitmap path.
117 : >trace2.txt &&
118 GIT_TRACE2_EVENT="$PWD/trace2.txt" \
119 git pack-objects --stdout --revs --all --delta-base-offset \
120 --no-ref-delta >got.pack &&
121
122 test_pack_reused 9 <trace2.txt &&
123 test_packs_reused 3 <trace2.txt &&
124
125 git index-pack --strict -o got.idx got.pack &&
126 test-tool pack-deltas --list-deltas got.idx >deltas &&
127 test_grep ! " REF_DELTA " deltas
128 '
129
130 test_expect_success 'reuse objects from first pack with middle gap' '
131 for i in D E F
132 do
133 test_commit "$i" || return 1
134 done &&
135
136 # Set "pack.window" to zero to ensure that we do not create any
137 # deltas, which could alter the amount of pack reuse we perform
138 # (if, for e.g., we are not sending one or more bases).
139 D="$(git -c pack.window=0 pack-objects --all --unpacked $packdir/pack)" &&
140
141 d_pos="$(pack_position $(git rev-parse D) <$packdir/pack-$D.idx)" &&
142 e_pos="$(pack_position $(git rev-parse E) <$packdir/pack-$D.idx)" &&
143 f_pos="$(pack_position $(git rev-parse F) <$packdir/pack-$D.idx)" &&
144
145 # commits F, E, and D, should appear in that order at the
146 # beginning of the pack
147 test $f_pos -lt $e_pos &&
148 test $e_pos -lt $d_pos &&
149
150 # Ensure that the pack we are constructing sorts ahead of any
151 # other packs in lexical/bitmap order by choosing it as the
152 # preferred pack.
153 git multi-pack-index write --bitmap --preferred-pack="pack-$D.idx" &&
154
155 cat >in <<-EOF &&
156 $(git rev-parse E)
157 ^$(git rev-parse D)
158 EOF
159
160 test_pack_objects_reused 3 1 <in
161 '
162
163 test_expect_success 'reuse objects from middle pack with middle gap' '
164 rm -fr $packdir/multi-pack-index* &&
165
166 # Ensure that the pack we are constructing sort into any
167 # position *but* the first one, by choosing a different pack as
168 # the preferred one.
169 git multi-pack-index write --bitmap --preferred-pack="pack-$A.idx" &&
170
171 cat >in <<-EOF &&
172 $(git rev-parse E)
173 ^$(git rev-parse D)
174 EOF
175
176 test_pack_objects_reused 3 1 <in
177 '
178
179 test_expect_success 'omit delta with uninteresting base (same pack)' '
180 git repack -adk &&
181
182 test_seq 32 >f &&
183 git add f &&
184 test_tick &&
185 git commit -m "delta" &&
186 delta="$(git rev-parse HEAD)" &&
187
188 test_seq 64 >f &&
189 test_tick &&
190 git commit -a -m "base" &&
191 base="$(git rev-parse HEAD)" &&
192
193 test_commit other &&
194
195 git repack -d &&
196
197 have_delta "$(git rev-parse $delta:f)" "$(git rev-parse $base:f)" &&
198
199 git multi-pack-index write --bitmap &&
200
201 cat >in <<-EOF &&
202 $(git rev-parse other)
203 ^$base
204 EOF
205
206 # We can only reuse the 3 objects corresponding to "other" from
207 # the latest pack.
208 #
209 # This is because even though we want "delta", we do not want
210 # "base", meaning that we have to inflate the delta/base-pair
211 # corresponding to the blob in commit "delta", which bypasses
212 # the pack-reuse mechanism.
213 #
214 # The remaining objects from the other pack are similarly not
215 # reused because their objects are on the uninteresting side of
216 # the query.
217 test_pack_objects_reused 3 1 <in
218 '
219
220 test_expect_success 'omit delta from uninteresting base (cross pack)' '
221 cat >in <<-EOF &&
222 $(git rev-parse $base)
223 ^$(git rev-parse $delta)
224 EOF
225
226 P="$(git pack-objects --revs $packdir/pack <in)" &&
227
228 git multi-pack-index write --bitmap --preferred-pack="pack-$P.idx" &&
229
230 packs_nr="$(find $packdir -type f -name "pack-*.pack" | wc -l)" &&
231 objects_nr="$(git rev-list --count --all --objects)" &&
232
233 test_pack_objects_reused_all $(($objects_nr - 1)) $packs_nr
234 '
235
236 test_expect_success 'non-omitted delta in MIDX preferred pack' '
237 test_config pack.allowPackReuse single &&
238
239 cat >p1.objects <<-EOF &&
240 $(git rev-parse $base)
241 ^$(git rev-parse $delta^)
242 EOF
243 cat >p2.objects <<-EOF &&
244 $(git rev-parse F)
245 EOF
246
247 p1="$(git pack-objects --revs $packdir/pack <p1.objects)" &&
248 p2="$(git pack-objects --revs $packdir/pack <p2.objects)" &&
249
250 cat >in <<-EOF &&
251 pack-$p1.idx
252 pack-$p2.idx
253 EOF
254 git multi-pack-index write --bitmap --stdin-packs \
255 --preferred-pack=pack-$p1.pack <in &&
256
257 git show-index <$packdir/pack-$p1.idx >expect &&
258
259 test_pack_objects_reused_all $(wc -l <expect) 1
260 '
261
262 test_expect_success 'duplicate objects' '
263 git init duplicate-objects &&
264 (
265 cd duplicate-objects &&
266
267 git config pack.allowPackReuse multi &&
268
269 test_commit base &&
270
271 git repack -a &&
272
273 git rev-parse HEAD^{tree} >in &&
274 p="$(git pack-objects $packdir/pack <in)" &&
275
276 git multi-pack-index write --bitmap --preferred-pack=pack-$p.idx &&
277
278 objects_nr="$(git rev-list --count --all --objects)" &&
279 packs_nr="$(find $packdir -type f -name "pack-*.pack" | wc -l)" &&
280
281 test_pack_objects_reused_all $objects_nr $packs_nr
282 )
283 '
284
285 test_expect_success 'duplicate objects with verbatim reuse' '
286 git init duplicate-objects-verbatim &&
287 (
288 cd duplicate-objects-verbatim &&
289
290 git config pack.allowPackReuse multi &&
291
292 test_commit_bulk 64 &&
293
294 # take the first object from the main pack...
295 git show-index <$(ls $packdir/pack-*.idx) >obj.raw &&
296 sort -nk1 <obj.raw | head -n1 | cut -d" " -f2 >in &&
297
298 # ...and create a separate pack containing just that object
299 p="$(git pack-objects $packdir/pack <in)" &&
300
301 git multi-pack-index write --bitmap --preferred-pack=pack-$p.idx &&
302
303 test_pack_objects_reused_all 192 2
304 )
305 '
306
307 test_done