Raw
1 #!/bin/sh
2
3 test_description='multi-pack-index compaction'
4
5 . ./test-lib.sh
6 . "$TEST_DIRECTORY"/lib-midx.sh
7
8 GIT_TEST_MULTI_PACK_INDEX=0
9 GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0
10 GIT_TEST_MULTI_PACK_INDEX_WRITE_INCREMENTAL=0
11
12 objdir=.git/objects
13 packdir=$objdir/pack
14 midxdir=$packdir/multi-pack-index.d
15 midx_chain=$midxdir/multi-pack-index-chain
16
17 write_packs () {
18 for c in "$@"
19 do
20 test_commit "$c" &&
21
22 git pack-objects --all --unpacked $packdir/pack-$c &&
23 git prune-packed &&
24
25 git multi-pack-index write --incremental --bitmap || return 1
26 done
27 }
28
29 test_midx_layer_packs () {
30 local checksum="$1" &&
31 shift &&
32
33 test-tool read-midx $objdir "$checksum" >out &&
34
35 printf "%s\n" "$@" >expect &&
36 # NOTE: do *not* pipe through sort here, we want to ensure the
37 # order of packs is preserved during compaction.
38 grep "^pack-" out | cut -d"-" -f2 >actual &&
39
40 test_cmp expect actual
41 }
42
43 test_midx_layer_object_uniqueness () {
44 : >objs.all
45 while read layer
46 do
47 test-tool read-midx --show-objects $objdir "$layer" >out &&
48 grep "\.pack$" out | cut -d" " -f1 | sort >objs.layer &&
49 test_stdout_line_count = 0 comm -12 objs.all objs.layer &&
50 cat objs.all objs.layer | sort >objs.tmp &&
51 mv objs.tmp objs.all || return 1
52 done <$midx_chain
53 }
54
55 test_expect_success 'MIDX compaction with lex-ordered pack names' '
56 git init midx-compact-lex-order &&
57 (
58 cd midx-compact-lex-order &&
59
60 git config maintenance.auto false &&
61
62 write_packs A B C D E &&
63 test_line_count = 5 $midx_chain &&
64
65 git multi-pack-index compact --incremental --bitmap \
66 "$(nth_line 2 "$midx_chain")" \
67 "$(nth_line 4 "$midx_chain")" &&
68 test_line_count = 3 $midx_chain &&
69
70 test_midx_layer_packs "$(nth_line 1 "$midx_chain")" A &&
71 test_midx_layer_packs "$(nth_line 2 "$midx_chain")" B C D &&
72 test_midx_layer_packs "$(nth_line 3 "$midx_chain")" E &&
73
74 test_midx_layer_object_uniqueness
75 )
76 '
77
78 test_expect_success 'MIDX compaction with non-lex-ordered pack names' '
79 git init midx-compact-non-lex-order &&
80 (
81 cd midx-compact-non-lex-order &&
82
83 git config maintenance.auto false &&
84
85 write_packs D C A B E &&
86 test_line_count = 5 $midx_chain &&
87
88 git multi-pack-index compact --incremental --bitmap \
89 "$(nth_line 2 "$midx_chain")" \
90 "$(nth_line 4 "$midx_chain")" &&
91 test_line_count = 3 $midx_chain &&
92
93 test_midx_layer_packs "$(nth_line 1 "$midx_chain")" D &&
94 test_midx_layer_packs "$(nth_line 2 "$midx_chain")" C A B &&
95 test_midx_layer_packs "$(nth_line 3 "$midx_chain")" E &&
96
97 test_midx_layer_object_uniqueness
98 )
99 '
100
101 test_expect_success 'setup for bogus MIDX compaction scenarios' '
102 git init midx-compact-bogus &&
103 (
104 cd midx-compact-bogus &&
105
106 git config maintenance.auto false &&
107
108 write_packs A B C
109 )
110 '
111
112 test_expect_success 'MIDX compaction with missing endpoints' '
113 (
114 cd midx-compact-bogus &&
115
116 test_must_fail git multi-pack-index compact --incremental \
117 "<missing>" "<missing>" 2>err &&
118 test_grep "could not find MIDX: <missing>" err &&
119
120 test_must_fail git multi-pack-index compact --incremental \
121 "<missing>" "$(nth_line 2 "$midx_chain")" 2>err &&
122 test_grep "could not find MIDX: <missing>" err &&
123
124 test_must_fail git multi-pack-index compact --incremental \
125 "$(nth_line 2 "$midx_chain")" "<missing>" 2>err &&
126 test_grep "could not find MIDX: <missing>" err
127 )
128 '
129
130 test_expect_success 'MIDX compaction with reversed endpoints' '
131 (
132 cd midx-compact-bogus &&
133
134 from="$(nth_line 3 "$midx_chain")" &&
135 to="$(nth_line 1 "$midx_chain")" &&
136
137 test_must_fail git multi-pack-index compact --incremental \
138 "$from" "$to" 2>err &&
139
140 test_grep "MIDX $from must be an ancestor of $to" err
141 )
142 '
143
144 test_expect_success 'MIDX compaction with identical endpoints' '
145 (
146 cd midx-compact-bogus &&
147
148 from="$(nth_line 3 "$midx_chain")" &&
149 to="$(nth_line 3 "$midx_chain")" &&
150
151 test_must_fail git multi-pack-index compact --incremental \
152 "$from" "$to" 2>err &&
153
154 test_grep "MIDX compaction endpoints must be unique" err
155 )
156 '
157
158 test_expect_success 'MIDX compaction with midx.version=1' '
159 (
160 cd midx-compact-bogus &&
161
162 test_must_fail git -c midx.version=1 multi-pack-index compact \
163 "$(nth_line 1 "$midx_chain")" \
164 "$(nth_line 2 "$midx_chain")" 2>err &&
165
166 test_grep "fatal: cannot perform MIDX compaction with v1 format" err
167 )
168 '
169
170 midx_objs_by_pack () {
171 awk '/\.pack$/ { split($3, a, "-"); print a[2], $1 }' | sort
172 }
173
174 tag_objs_from_pack () {
175 objs="$(git rev-list --objects --no-object-names "$2")" &&
176 printf "$1 %s\n" $objs | sort
177 }
178
179 test_expect_success 'MIDX compaction preserves pack object selection' '
180 git init midx-compact-preserve-selection &&
181 (
182 cd midx-compact-preserve-selection &&
183
184 git config maintenance.auto false &&
185
186 test_commit A &&
187 test_commit B &&
188
189 # Create two packs, one containing just the objects from
190 # A, and another containing all objects from the
191 # repository.
192 p1="$(echo A | git pack-objects --revs --delta-base-offset \
193 $packdir/pack-1)" &&
194 p0="$(echo B | git pack-objects --revs --delta-base-offset \
195 $packdir/pack-0)" &&
196
197 echo "pack-1-$p1.idx" | git multi-pack-index write \
198 --incremental --bitmap --stdin-packs &&
199 echo "pack-0-$p0.idx" | git multi-pack-index write \
200 --incremental --bitmap --stdin-packs &&
201
202 write_packs C &&
203
204 git multi-pack-index compact --incremental --bitmap \
205 "$(nth_line 1 "$midx_chain")" \
206 "$(nth_line 2 "$midx_chain")" &&
207
208
209 test-tool read-midx --show-objects $objdir \
210 "$(nth_line 1 "$midx_chain")" >AB.info &&
211 test-tool read-midx --show-objects $objdir \
212 "$(nth_line 2 "$midx_chain")" >C.info &&
213
214 midx_objs_by_pack <AB.info >AB.actual &&
215 midx_objs_by_pack <C.info >C.actual &&
216
217 {
218 tag_objs_from_pack 1 A &&
219 tag_objs_from_pack 0 A..B
220 } | sort >AB.expect &&
221 tag_objs_from_pack C B..C >C.expect &&
222
223 test_cmp AB.expect AB.actual &&
224 test_cmp C.expect C.actual
225 )
226 '
227
228 test_expect_success 'MIDX compaction with bitmaps' '
229 git init midx-compact-with-bitmaps &&
230 (
231 cd midx-compact-with-bitmaps &&
232
233 git config maintenance.auto false &&
234
235 write_packs foo bar baz quux woot &&
236
237 test-tool read-midx --bitmap $objdir >bitmap.expect &&
238 git multi-pack-index compact --incremental --bitmap \
239 "$(nth_line 2 "$midx_chain")" \
240 "$(nth_line 4 "$midx_chain")" &&
241 test-tool read-midx --bitmap $objdir >bitmap.actual &&
242
243 test_cmp bitmap.expect bitmap.actual &&
244
245 true
246 )
247 '
248
249 test_expect_success 'MIDX compaction with bitmaps (non-trivial)' '
250 git init midx-compact-with-bitmaps-non-trivial &&
251 (
252 cd midx-compact-with-bitmaps-non-trivial &&
253
254 git config maintenance.auto false &&
255
256 git branch -m main &&
257
258 # D(4)
259 # /
260 # A(1) --- B(2) --- C(3) --- G(7)
261 # \
262 # E(5) --- F(6)
263 write_packs A B C &&
264 git checkout -b side &&
265 write_packs D &&
266 git checkout -b other B &&
267 write_packs E F &&
268 git checkout main &&
269 write_packs G &&
270
271 # Compact layers 2-4, leaving us with:
272 #
273 # [A, [B, C, D], E, F, G]
274 git multi-pack-index compact --incremental --bitmap \
275 "$(nth_line 2 "$midx_chain")" \
276 "$(nth_line 4 "$midx_chain")" &&
277
278 # Then compact the top two layers, condensing the above
279 # such that the new 4th layer contains F and G.
280 #
281 # [A, [B, C, D], E, [F, G]]
282 git multi-pack-index compact --incremental --bitmap \
283 "$(nth_line 4 "$midx_chain")" \
284 "$(nth_line 5 "$midx_chain")"
285 )
286 '
287
288 test_expect_success 'MIDX compaction with --no-write-chain-file' '
289 git init midx-compact-with--no-write-chain-file &&
290 (
291 cd midx-compact-with--no-write-chain-file &&
292
293 git config maintenance.auto false &&
294
295 write_packs A B C D &&
296
297 test_line_count = 4 $midx_chain &&
298 cp "$midx_chain" "$midx_chain".bak &&
299
300 layer="$(git multi-pack-index compact --incremental \
301 --no-write-chain-file \
302 --base="$(nth_line 1 "$midx_chain")" \
303 "$(nth_line 2 "$midx_chain")" \
304 "$(nth_line 3 "$midx_chain")")" &&
305
306 test_cmp "$midx_chain.bak" "$midx_chain" &&
307
308 # After writing the new layer, insert it into the chain
309 # manually. This is done in order to make $layer visible
310 # to the read-midx test helper below, and matches what
311 # the MIDX command would do without --no-write-chain-file.
312 {
313 nth_line 1 "$midx_chain.bak" &&
314 echo $layer &&
315 nth_line 4 "$midx_chain.bak"
316 } >$midx_chain &&
317
318 test-tool read-midx $objdir $layer >midx.data &&
319 test_grep "^pack-B-.*\.idx" midx.data &&
320 test_grep "^pack-C-.*\.idx" midx.data
321
322 )
323 '
324
325 test_expect_success 'MIDX compaction with --base' '
326 git init midx-compact-with--base &&
327 (
328 cd midx-compact-with--base &&
329
330 git config maintenance.auto false &&
331
332 write_packs A B C D &&
333
334 test_line_count = 4 "$midx_chain" &&
335
336 cp "$midx_chain" "$midx_chain.bak" &&
337
338 git multi-pack-index compact --incremental \
339 --base="$(nth_line 1 "$midx_chain")" \
340 "$(nth_line 3 "$midx_chain")" \
341 "$(nth_line 4 "$midx_chain")" &&
342 test_line_count = 2 $midx_chain &&
343
344 nth_line 1 "$midx_chain.bak" >expect &&
345 nth_line 1 "$midx_chain" >actual &&
346
347 test_cmp expect actual
348 )
349 '
350
351 test_expect_success 'MIDX compaction with --base=none' '
352 git init midx-compact-base-none &&
353 (
354 cd midx-compact-base-none &&
355
356 git config maintenance.auto false &&
357
358 write_packs A B C D &&
359
360 test_line_count = 4 $midx_chain &&
361
362 cp "$midx_chain" "$midx_chain".bak &&
363
364 # Compact the two bottommost layers (A and B) into a new
365 # root layer with no parent.
366 git multi-pack-index compact --incremental \
367 --base=none \
368 "$(nth_line 1 "$midx_chain")" \
369 "$(nth_line 2 "$midx_chain")" &&
370
371 test_line_count = 3 $midx_chain &&
372
373 # The upper layers (C and D) should be preserved
374 # unchanged.
375 nth_line 3 "$midx_chain.bak" >expect &&
376 nth_line 4 "$midx_chain.bak" >>expect &&
377 nth_line 2 "$midx_chain" >actual &&
378 nth_line 3 "$midx_chain" >>actual &&
379
380 test_cmp expect actual
381 )
382 '
383
384 test_expect_success 'MIDX compaction with bogus --base checksum' '
385 git init midx-compact-bogus-base &&
386 (
387 cd midx-compact-bogus-base &&
388
389 git config maintenance.auto false &&
390
391 write_packs A B C &&
392
393 test_must_fail git multi-pack-index compact --incremental \
394 --base=deadbeef \
395 "$(nth_line 2 "$midx_chain")" \
396 "$(nth_line 3 "$midx_chain")" 2>err &&
397 test_grep "could not find base MIDX" err
398 )
399 '
400
401 test_done