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