Git fork
1#!/bin/sh
2#
3# Copyright (c) 2018 Jiang Xin
4#
5
6test_description='Test git pack-redundant
7
8In order to test git-pack-redundant, we will create a number of objects and
9packs in the repository `main.git`. The relationship between packs (P1-P8)
10and objects (T, A-R) is showed in the following chart. Objects of a pack will
11be marked with letter x, while objects of redundant packs will be marked with
12exclamation 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
27Another 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
29relationship 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
39if test_have_prereq WITH_BREAKING_CHANGES
40then
41 skip_all='skipping git-pack-redundant tests; built with breaking changes'
42 test_done
43fi
44
45main_repo=main.git
46shared_repo=shared.git
47
48test_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
53git_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.
62create_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.
98create_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
106format_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
123test_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
128test_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#############################################################################
149test_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#############################################################################
179test_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#############################################################################
218test_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#############################################################################
259test_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#############################################################################
299test_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
317test_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
326test_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`.
338test_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
346test_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#############################################################################
379test_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
395test_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
408test_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
428test_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#############################################################################
459test_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#############################################################################
492test_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
509test_done