Raw
1 #!/bin/sh
2 #
3 # Copyright (c) 2018 Jiang Xin
4 #
5
6 test_description='Test git pack-redundant
7
8 In order to test git-pack-redundant, we will create a number of objects and
9 packs in the repository `main.git`. The relationship between packs (P1-P8)
10 and objects (T, A-R) is showed in the following chart. Objects of a pack will
11 be marked with letter x, while objects of redundant packs will be marked with
12 exclamation point, and redundant pack itself will be marked with asterisk.
13
14 | T A B C D E F G H I J K L M N O P Q R
15 ----+--------------------------------------
16 P1 | x x x x x x x x
17 P2* | ! ! ! ! ! ! !
18 P3 | x x x x x x
19 P4* | ! ! ! ! !
20 P5 | x x x x
21 P6* | ! ! !
22 P7 | x x
23 P8* | !
24 ----+--------------------------------------
25 ALL | x x x x x x x x x x x x x x x x x x x
26
27 Another repository `shared.git` has unique objects (X-Z), while other objects
28 (marked with letter s) are shared through alt-odb (of `main.git`). The
29 relationship between packs and objects is as follows:
30
31 | T A B C D E F G H I J K L M N O P Q R X Y Z
32 ----+----------------------------------------------
33 Px1 | s s s x x x
34 Px2 | s s s x x x
35 '
36
37 . ./test-lib.sh
38
39 if test_have_prereq WITH_BREAKING_CHANGES
40 then
41 skip_all='skipping git-pack-redundant tests; built with breaking changes'
42 test_done
43 fi
44
45 main_repo=main.git
46 shared_repo=shared.git
47
48 test_expect_success 'pack-redundant needs --i-still-use-this' '
49 test_must_fail git pack-redundant >message 2>&1 &&
50 test_grep "nominated for removal" message
51 '
52
53 git_pack_redundant='git pack-redundant --i-still-use-this'
54
55 # Create commits in <repo> and assign each commit's oid to shell variables
56 # given in the arguments (A, B, and C). E.g.:
57 #
58 # create_commits_in <repo> A B C
59 #
60 # NOTE: Avoid calling this function from a subshell since variable
61 # assignments will disappear when subshell exits.
62 create_commits_in () {
63 repo="$1" &&
64 if ! parent=$(git -C "$repo" rev-parse HEAD^{} 2>/dev/null)
65 then
66 parent=
67 fi &&
68 T=$(git -C "$repo" write-tree) &&
69 shift &&
70 while test $# -gt 0
71 do
72 name=$1 &&
73 test_tick &&
74 if test -z "$parent"
75 then
76 oid=$(echo $name | git -C "$repo" commit-tree $T)
77 else
78 oid=$(echo $name | git -C "$repo" commit-tree -p $parent $T)
79 fi &&
80 eval $name=$oid &&
81 parent=$oid &&
82 shift ||
83 return 1
84 done &&
85 git -C "$repo" update-ref refs/heads/main $oid
86 }
87
88 # Create pack in <repo> and assign pack id to variable given in the 2nd argument
89 # (<name>). Commits in the pack will be read from stdin. E.g.:
90 #
91 # create_pack_in <repo> <name> <<-EOF
92 # ...
93 # EOF
94 #
95 # NOTE: commits from stdin should be given using heredoc, not using pipe, and
96 # avoid calling this function from a subshell since variable assignments will
97 # disappear when subshell exits.
98 create_pack_in () {
99 repo="$1" &&
100 name="$2" &&
101 pack=$(git -C "$repo/objects/pack" pack-objects -q pack) &&
102 eval $name=$pack &&
103 eval P$pack=$name:$pack
104 }
105
106 format_packfiles () {
107 sed \
108 -e "s#.*/pack-\(.*\)\.idx#\1#" \
109 -e "s#.*/pack-\(.*\)\.pack#\1#" |
110 sort -u |
111 while read p
112 do
113 if test -z "$(eval echo \${P$p})"
114 then
115 echo $p
116 else
117 eval echo "\${P$p}"
118 fi
119 done |
120 sort
121 }
122
123 test_expect_success 'setup main repo' '
124 git init --bare "$main_repo" &&
125 create_commits_in "$main_repo" A B C D E F G H I J K L M N O P Q R
126 '
127
128 test_expect_success 'main: pack-redundant works with no packfile' '
129 (
130 cd "$main_repo" &&
131 cat >expect <<-EOF &&
132 fatal: Zero packs found!
133 EOF
134 test_must_fail $git_pack_redundant --all >actual 2>&1 &&
135 test_cmp expect actual
136 )
137 '
138
139 #############################################################################
140 # Chart of packs and objects for this test case
141 #
142 # | T A B C D E F G H I J K L M N O P Q R
143 # ----+--------------------------------------
144 # P1 | x x x x x x x x
145 # ----+--------------------------------------
146 # ALL | x x x x x x x x
147 #
148 #############################################################################
149 test_expect_success 'main: pack-redundant works with one packfile' '
150 create_pack_in "$main_repo" P1 <<-EOF &&
151 $T
152 $A
153 $B
154 $C
155 $D
156 $E
157 $F
158 $R
159 EOF
160 (
161 cd "$main_repo" &&
162 $git_pack_redundant --all >out &&
163 test_must_be_empty out
164 )
165 '
166
167 #############################################################################
168 # Chart of packs and objects for this test case
169 #
170 # | T A B C D E F G H I J K L M N O P Q R
171 # ----+--------------------------------------
172 # P1 | x x x x x x x x
173 # P2 | x x x x x x x
174 # P3 | x x x x x x
175 # ----+--------------------------------------
176 # ALL | x x x x x x x x x x x x x x x
177 #
178 #############################################################################
179 test_expect_success 'main: no redundant for pack 1, 2, 3' '
180 create_pack_in "$main_repo" P2 <<-EOF &&
181 $B
182 $C
183 $D
184 $E
185 $G
186 $H
187 $I
188 EOF
189 create_pack_in "$main_repo" P3 <<-EOF &&
190 $F
191 $I
192 $J
193 $K
194 $L
195 $M
196 EOF
197 (
198 cd "$main_repo" &&
199 $git_pack_redundant --all >out &&
200 test_must_be_empty out
201 )
202 '
203
204 #############################################################################
205 # Chart of packs and objects for this test case
206 #
207 # | T A B C D E F G H I J K L M N O P Q R
208 # ----+--------------------------------------
209 # P1 | x x x x x x x x
210 # P2 | x x x x x x x
211 # P3* | ! ! ! ! ! !
212 # P4 | x x x x x
213 # P5 | x x x x
214 # ----+--------------------------------------
215 # ALL | x x x x x x x x x x x x x x x x x x
216 #
217 #############################################################################
218 test_expect_success 'main: one of pack-2/pack-3 is redundant' '
219 create_pack_in "$main_repo" P4 <<-EOF &&
220 $J
221 $K
222 $L
223 $M
224 $P
225 EOF
226 create_pack_in "$main_repo" P5 <<-EOF &&
227 $G
228 $H
229 $N
230 $O
231 EOF
232 (
233 cd "$main_repo" &&
234 cat >expect <<-EOF &&
235 P3:$P3
236 EOF
237 $git_pack_redundant --all >out &&
238 format_packfiles <out >actual &&
239 test_cmp expect actual
240 )
241 '
242
243 #############################################################################
244 # Chart of packs and objects for this test case
245 #
246 # | T A B C D E F G H I J K L M N O P Q R
247 # ----+--------------------------------------
248 # P1 | x x x x x x x x
249 # P2* | ! ! ! ! ! ! !
250 # P3 | x x x x x x
251 # P4* | ! ! ! ! !
252 # P5 | x x x x
253 # P6* | ! ! !
254 # P7 | x x
255 # ----+--------------------------------------
256 # ALL | x x x x x x x x x x x x x x x x x x x
257 #
258 #############################################################################
259 test_expect_success 'main: pack 2, 4, and 6 are redundant' '
260 create_pack_in "$main_repo" P6 <<-EOF &&
261 $N
262 $O
263 $Q
264 EOF
265 create_pack_in "$main_repo" P7 <<-EOF &&
266 $P
267 $Q
268 EOF
269 (
270 cd "$main_repo" &&
271 cat >expect <<-EOF &&
272 P2:$P2
273 P4:$P4
274 P6:$P6
275 EOF
276 $git_pack_redundant --all >out &&
277 format_packfiles <out >actual &&
278 test_cmp expect actual
279 )
280 '
281
282 #############################################################################
283 # Chart of packs and objects for this test case
284 #
285 # | T A B C D E F G H I J K L M N O P Q R
286 # ----+--------------------------------------
287 # P1 | x x x x x x x x
288 # P2* | ! ! ! ! ! ! !
289 # P3 | x x x x x x
290 # P4* | ! ! ! ! !
291 # P5 | x x x x
292 # P6* | ! ! !
293 # P7 | x x
294 # P8* | !
295 # ----+--------------------------------------
296 # ALL | x x x x x x x x x x x x x x x x x x x
297 #
298 #############################################################################
299 test_expect_success 'main: pack-8 (subset of pack-1) is also redundant' '
300 create_pack_in "$main_repo" P8 <<-EOF &&
301 $A
302 EOF
303 (
304 cd "$main_repo" &&
305 cat >expect <<-EOF &&
306 P2:$P2
307 P4:$P4
308 P6:$P6
309 P8:$P8
310 EOF
311 $git_pack_redundant --all >out &&
312 format_packfiles <out >actual &&
313 test_cmp expect actual
314 )
315 '
316
317 test_expect_success 'main: clean loose objects' '
318 (
319 cd "$main_repo" &&
320 git prune-packed &&
321 find objects -type f | sed -e "/objects\/pack\//d" >out &&
322 test_must_be_empty out
323 )
324 '
325
326 test_expect_success 'main: remove redundant packs and pass fsck' '
327 (
328 cd "$main_repo" &&
329 $git_pack_redundant --all | xargs rm &&
330 git fsck &&
331 $git_pack_redundant --all >out &&
332 test_must_be_empty out
333 )
334 '
335
336 # The following test cases will execute inside `shared.git`, instead of
337 # inside `main.git`.
338 test_expect_success 'setup shared.git' '
339 git clone --mirror "$main_repo" "$shared_repo" &&
340 (
341 cd "$shared_repo" &&
342 printf "../../$main_repo/objects\n" >objects/info/alternates
343 )
344 '
345
346 test_expect_success 'shared: all packs are redundant, but no output without --alt-odb' '
347 (
348 cd "$shared_repo" &&
349 $git_pack_redundant --all >out &&
350 test_must_be_empty out
351 )
352 '
353
354 #############################################################################
355 # Chart of packs and objects for this test case
356 #
357 # ================= main.git ================
358 # | T A B C D E F G H I J K L M N O P Q R <----------+
359 # ----+-------------------------------------- |
360 # P1 | x x x x x x x x |
361 # P3 | x x x x x x |
362 # P5 | x x x x |
363 # P7 | x x |
364 # ----+-------------------------------------- |
365 # ALL | x x x x x x x x x x x x x x x x x x x |
366 # |
367 # |
368 # ================ shared.git =============== |
369 # | T A B C D E F G H I J K L M N O P Q R <objects/info/alternates>
370 # ----+--------------------------------------
371 # P1* | s s s s s s s s
372 # P3* | s s s s s s
373 # P5* | s s s s
374 # P7* | s s
375 # ----+--------------------------------------
376 # ALL | x x x x x x x x x x x x x x x x x x x
377 #
378 #############################################################################
379 test_expect_success 'shared: show redundant packs in stderr for verbose mode' '
380 (
381 cd "$shared_repo" &&
382 cat >expect <<-EOF &&
383 P1:$P1
384 P3:$P3
385 P5:$P5
386 P7:$P7
387 EOF
388 $git_pack_redundant --all --verbose >out 2>out.err &&
389 test_must_be_empty out &&
390 grep "pack$" out.err | format_packfiles >actual &&
391 test_cmp expect actual
392 )
393 '
394
395 test_expect_success 'shared: remove redundant packs, no packs left' '
396 (
397 cd "$shared_repo" &&
398 cat >expect <<-EOF &&
399 fatal: Zero packs found!
400 EOF
401 $git_pack_redundant --all --alt-odb | xargs rm &&
402 git fsck &&
403 test_must_fail $git_pack_redundant --all --alt-odb >actual 2>&1 &&
404 test_cmp expect actual
405 )
406 '
407
408 test_expect_success 'shared: create new objects and packs' '
409 create_commits_in "$shared_repo" X Y Z &&
410 create_pack_in "$shared_repo" Px1 <<-EOF &&
411 $X
412 $Y
413 $Z
414 $A
415 $B
416 $C
417 EOF
418 create_pack_in "$shared_repo" Px2 <<-EOF
419 $X
420 $Y
421 $Z
422 $D
423 $E
424 $F
425 EOF
426 '
427
428 test_expect_success 'shared: no redundant without --alt-odb' '
429 (
430 cd "$shared_repo" &&
431 $git_pack_redundant --all >out &&
432 test_must_be_empty out
433 )
434 '
435
436 #############################################################################
437 # Chart of packs and objects for this test case
438 #
439 # ================= main.git ================
440 # | T A B C D E F G H I J K L M N O P Q R <----------------+
441 # ----+-------------------------------------- |
442 # P1 | x x x x x x x x |
443 # P3 | x x x x x x |
444 # P5 | x x x x |
445 # P7 | x x |
446 # ----+-------------------------------------- |
447 # ALL | x x x x x x x x x x x x x x x x x x x |
448 # |
449 # |
450 # ================ shared.git ======================= |
451 # | T A B C D E F G H I J K L M N O P Q R X Y Z <objects/info/alternates>
452 # ----+----------------------------------------------
453 # Px1 | s s s x x x
454 # Px2*| s s s ! ! !
455 # ----+----------------------------------------------
456 # ALL | s s s s s s s s s s s s s s s s s s s x x x
457 #
458 #############################################################################
459 test_expect_success 'shared: one pack is redundant with --alt-odb' '
460 (
461 cd "$shared_repo" &&
462 $git_pack_redundant --all --alt-odb >out &&
463 format_packfiles <out >actual &&
464 test_line_count = 1 actual
465 )
466 '
467
468 #############################################################################
469 # Chart of packs and objects for this test case
470 #
471 # ================= main.git ================
472 # | T A B C D E F G H I J K L M N O P Q R <----------------+
473 # ----+-------------------------------------- |
474 # P1 | x x x x x x x x |
475 # P3 | x x x x x x |
476 # P5 | x x x x |
477 # P7 | x x |
478 # ----+-------------------------------------- |
479 # ALL | x x x x x x x x x x x x x x x x x x x |
480 # |
481 # |
482 # ================ shared.git ======================= |
483 # | T A B C D E F G H I J K L M N O P Q R X Y Z <objects/info/alternates>
484 # ----+----------------------------------------------
485 # Px1*| s s s i i i
486 # Px2*| s s s i i i
487 # ----+----------------------------------------------
488 # ALL | s s s s s s s s s s s s s s s s s s s i i i
489 # (ignored objects, marked with i)
490 #
491 #############################################################################
492 test_expect_success 'shared: ignore unique objects and all two packs are redundant' '
493 (
494 cd "$shared_repo" &&
495 cat >expect <<-EOF &&
496 Px1:$Px1
497 Px2:$Px2
498 EOF
499 $git_pack_redundant --all --alt-odb >out <<-EOF &&
500 $X
501 $Y
502 $Z
503 EOF
504 format_packfiles <out >actual &&
505 test_cmp expect actual
506 )
507 '
508
509 test_done