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