3 test_description
='git repack --geometric works correctly'
7 GIT_TEST_MULTI_PACK_INDEX
=0
11 midx
=$objdir/pack
/multi-pack-index
13 test_expect_success
'--geometric with no packs' '
15 test_when_finished "rm -fr 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' '
26 test_when_finished "rm -fr geometric" &&
33 git repack --geometric 2 >out &&
35 test_i18ngrep "Nothing new to pack" out
39 test_expect_success
'--geometric with an intact progression' '
41 test_when_finished "rm -fr 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' '
60 test_when_finished "rm -fr 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
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' '
91 test_when_finished "rm -fr 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
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" &&
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" &&
145 test_commit kept && # 3 objects
146 test_commit pack && # 3 objects
148 KEPT=$(git pack-objects --revs $objdir/pack/pack <<-EOF
152 PACK=$(git pack-objects --revs $objdir/pack/pack <<-EOF
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
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
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
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" &&
194 # Create two equal-sized packs
195 test_commit kept && # 3 objects
197 test_commit pack && # 3 objects
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 &&
216 test_expect_success
'--geometric chooses largest MIDX preferred pack' '
217 git init geometric &&
218 test_when_finished "rm -fr 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" &&
244 test-tool genrandom foo 1048576 >foo &&
245 test-tool genrandom bar 1048576 >bar &&
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).
264 # Both p1 and p2 will be rolled up, but pack-objects will write
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
278 # If `repack` fails to do that, we will incorrectly delete p2,
279 # causing object corruption.