Merge branch 'ps/receive-pack-unlock-before-die'
[git/gitster.git] / t / t7703-repack-geometric.sh
blob8821fbd2dd55844e54f55553b442ec419755546c
1 #!/bin/sh
3 test_description='git repack --geometric works correctly'
5 . ./test-lib.sh
7 GIT_TEST_MULTI_PACK_INDEX=0
9 objdir=.git/objects
10 packdir=$objdir/pack
11 midx=$objdir/pack/multi-pack-index
13 test_expect_success '--geometric with no packs' '
14 git init geometric &&
15 test_when_finished "rm -fr geometric" &&
17 cd geometric &&
19 git repack --write-midx --geometric 2 >out &&
20 test_i18ngrep "Nothing new to pack" out
24 test_expect_success '--geometric with one pack' '
25 git init geometric &&
26 test_when_finished "rm -fr geometric" &&
28 cd geometric &&
30 test_commit "base" &&
31 git repack -d &&
33 git repack --geometric 2 >out &&
35 test_i18ngrep "Nothing new to pack" out
39 test_expect_success '--geometric with an intact progression' '
40 git init geometric &&
41 test_when_finished "rm -fr geometric" &&
43 cd geometric &&
45 # These packs already form a geometric progression.
46 test_commit_bulk --start=1 1 && # 3 objects
47 test_commit_bulk --start=2 2 && # 6 objects
48 test_commit_bulk --start=4 4 && # 12 objects
50 find $objdir/pack -name "*.pack" | sort >expect &&
51 git repack --geometric 2 -d &&
52 find $objdir/pack -name "*.pack" | sort >actual &&
54 test_cmp expect actual
58 test_expect_success '--geometric with loose objects' '
59 git init geometric &&
60 test_when_finished "rm -fr geometric" &&
62 cd geometric &&
64 # These packs already form a geometric progression.
65 test_commit_bulk --start=1 1 && # 3 objects
66 test_commit_bulk --start=2 2 && # 6 objects
67 # The loose objects are packed together, breaking the
68 # progression.
69 test_commit loose && # 3 objects
71 find $objdir/pack -name "*.pack" | sort >before &&
72 git repack --geometric 2 -d &&
73 find $objdir/pack -name "*.pack" | sort >after &&
75 comm -13 before after >new &&
76 comm -23 before after >removed &&
78 test_line_count = 1 new &&
79 test_must_be_empty removed &&
81 git repack --geometric 2 -d &&
82 find $objdir/pack -name "*.pack" | sort >after &&
84 # The progression (3, 3, 6) is combined into one new pack.
85 test_line_count = 1 after
89 test_expect_success '--geometric with small-pack rollup' '
90 git init geometric &&
91 test_when_finished "rm -fr geometric" &&
93 cd geometric &&
95 test_commit_bulk --start=1 1 && # 3 objects
96 test_commit_bulk --start=2 1 && # 3 objects
97 find $objdir/pack -name "*.pack" | sort >small &&
98 test_commit_bulk --start=3 4 && # 12 objects
99 test_commit_bulk --start=7 8 && # 24 objects
100 find $objdir/pack -name "*.pack" | sort >before &&
102 git repack --geometric 2 -d &&
104 # Three packs in total; two of the existing large ones, and one
105 # new one.
106 find $objdir/pack -name "*.pack" | sort >after &&
107 test_line_count = 3 after &&
108 comm -3 small before | tr -d "\t" >large &&
109 grep -qFf large after
113 test_expect_success '--geometric with small- and large-pack rollup' '
114 git init geometric &&
115 test_when_finished "rm -fr geometric" &&
117 cd geometric &&
119 # size(small1) + size(small2) > size(medium) / 2
120 test_commit_bulk --start=1 1 && # 3 objects
121 test_commit_bulk --start=2 1 && # 3 objects
122 test_commit_bulk --start=2 3 && # 7 objects
123 test_commit_bulk --start=6 9 && # 27 objects &&
125 find $objdir/pack -name "*.pack" | sort >before &&
127 git repack --geometric 2 -d &&
129 find $objdir/pack -name "*.pack" | sort >after &&
130 comm -12 before after >untouched &&
132 # Two packs in total; the largest pack from before running "git
133 # repack", and one new one.
134 test_line_count = 1 untouched &&
135 test_line_count = 2 after
139 test_expect_success '--geometric ignores kept packs' '
140 git init geometric &&
141 test_when_finished "rm -fr geometric" &&
143 cd geometric &&
145 test_commit kept && # 3 objects
146 test_commit pack && # 3 objects
148 KEPT=$(git pack-objects --revs $objdir/pack/pack <<-EOF
149 refs/tags/kept
151 ) &&
152 PACK=$(git pack-objects --revs $objdir/pack/pack <<-EOF
153 refs/tags/pack
154 ^refs/tags/kept
156 ) &&
158 # neither pack contains more than twice the number of objects in
159 # the other, so they should be combined. but, marking one as
160 # .kept on disk will "freeze" it, so the pack structure should
161 # remain unchanged.
162 touch $objdir/pack/pack-$KEPT.keep &&
164 find $objdir/pack -name "*.pack" | sort >before &&
165 git repack --geometric 2 -d &&
166 find $objdir/pack -name "*.pack" | sort >after &&
168 # both packs should still exist
169 test_path_is_file $objdir/pack/pack-$KEPT.pack &&
170 test_path_is_file $objdir/pack/pack-$PACK.pack &&
172 # and no new packs should be created
173 test_cmp before after &&
175 # Passing --pack-kept-objects causes packs with a .keep file to
176 # be repacked, too.
177 git repack --geometric 2 -d --pack-kept-objects &&
179 # After repacking, two packs remain: one new one (containing the
180 # objects in both the .keep and non-kept pack), and the .keep
181 # pack (since `--pack-kept-objects -d` does not actually delete
182 # the kept pack).
183 find $objdir/pack -name "*.pack" >after &&
184 test_line_count = 2 after
188 test_expect_success '--geometric ignores --keep-pack packs' '
189 git init geometric &&
190 test_when_finished "rm -fr geometric" &&
192 cd geometric &&
194 # Create two equal-sized packs
195 test_commit kept && # 3 objects
196 git repack -d &&
197 test_commit pack && # 3 objects
198 git repack -d &&
200 find $objdir/pack -type f -name "*.pack" | sort >packs.before &&
201 git repack --geometric 2 -dm \
202 --keep-pack="$(basename "$(head -n 1 packs.before)")" >out &&
203 find $objdir/pack -type f -name "*.pack" | sort >packs.after &&
205 # Packs should not have changed (only one non-kept pack, no
206 # loose objects), but $midx should now exist.
207 grep "Nothing new to pack" out &&
208 test_path_is_file $midx &&
210 test_cmp packs.before packs.after &&
212 git fsck
216 test_expect_success '--geometric chooses largest MIDX preferred pack' '
217 git init geometric &&
218 test_when_finished "rm -fr geometric" &&
220 cd geometric &&
222 # These packs already form a geometric progression.
223 test_commit_bulk --start=1 1 && # 3 objects
224 test_commit_bulk --start=2 2 && # 6 objects
225 ls $objdir/pack/pack-*.idx >before &&
226 test_commit_bulk --start=4 4 && # 12 objects
227 ls $objdir/pack/pack-*.idx >after &&
229 git repack --geometric 2 -dbm &&
231 comm -3 before after | xargs -n 1 basename >expect &&
232 test-tool read-midx --preferred-pack $objdir >actual &&
234 test_cmp expect actual
238 test_expect_success '--geometric with pack.packSizeLimit' '
239 git init pack-rewrite &&
240 test_when_finished "rm -fr pack-rewrite" &&
242 cd pack-rewrite &&
244 test-tool genrandom foo 1048576 >foo &&
245 test-tool genrandom bar 1048576 >bar &&
247 git add foo bar &&
248 test_tick &&
249 git commit -m base &&
251 git rev-parse HEAD:foo HEAD:bar >p1.objects &&
252 git rev-parse HEAD HEAD^{tree} >p2.objects &&
254 # These two packs each contain two objects, so the following
255 # `--geometric` repack will try to combine them.
256 p1="$(git pack-objects $packdir/pack <p1.objects)" &&
257 p2="$(git pack-objects $packdir/pack <p2.objects)" &&
259 # Remove any loose objects in packs, since we do not want extra
260 # copies around (which would mask over potential object
261 # corruption issues).
262 git prune-packed &&
264 # Both p1 and p2 will be rolled up, but pack-objects will write
265 # three packs:
267 # - one containing object "foo",
268 # - another containing object "bar",
269 # - a final pack containing the commit and tree objects
270 # (identical to p2 above)
271 git repack --geometric 2 -d --max-pack-size=1048576 &&
273 # Ensure `repack` can detect that the third pack it wrote
274 # (containing just the tree and commit objects) was identical to
275 # one that was below the geometric split, so that we can save it
276 # from deletion.
278 # If `repack` fails to do that, we will incorrectly delete p2,
279 # causing object corruption.
280 git fsck
284 test_done