]>
Commit | Line | Data |
---|---|---|
0c8151b6 NTND |
1 | #!/bin/sh |
2 | ||
3 | test_description='basic git gc tests | |
4 | ' | |
5 | ||
6 | . ./test-lib.sh | |
6b89a34c | 7 | . "$TEST_DIRECTORY"/lib-terminal.sh |
0c8151b6 | 8 | |
9806f5a7 NTND |
9 | test_expect_success 'setup' ' |
10 | # do not let the amount of physical memory affects gc | |
11 | # behavior, make sure we always pack everything to one pack by | |
12 | # default | |
368f3cb0 | 13 | git config gc.bigPackThreshold 2g && |
77257e3c | 14 | test_oid_init |
9806f5a7 NTND |
15 | ' |
16 | ||
0c8151b6 NTND |
17 | test_expect_success 'gc empty repository' ' |
18 | git gc | |
19 | ' | |
20 | ||
4c5baf02 JN |
21 | test_expect_success 'gc does not leave behind pid file' ' |
22 | git gc && | |
23 | test_path_is_missing .git/gc.pid | |
24 | ' | |
25 | ||
0c8151b6 NTND |
26 | test_expect_success 'gc --gobbledegook' ' |
27 | test_expect_code 129 git gc --nonsense 2>err && | |
6789275d | 28 | test_grep "[Uu]sage: git gc" err |
0c8151b6 NTND |
29 | ' |
30 | ||
31 | test_expect_success 'gc -h with invalid configuration' ' | |
32 | mkdir broken && | |
33 | ( | |
34 | cd broken && | |
35 | git init && | |
36 | echo "[gc] pruneexpire = CORRUPT" >>.git/config && | |
37 | test_expect_code 129 git gc -h >usage 2>&1 | |
38 | ) && | |
6789275d | 39 | test_grep "[Uu]sage" broken/usage |
0c8151b6 NTND |
40 | ' |
41 | ||
14886b40 | 42 | test_expect_success 'gc is not aborted due to a stale symref' ' |
8c845cde JS |
43 | git init remote && |
44 | ( | |
45 | cd remote && | |
46 | test_commit initial && | |
47 | git clone . ../client && | |
48 | git branch -m develop && | |
49 | cd ../client && | |
50 | git fetch --prune && | |
51 | git gc | |
52 | ) | |
53 | ' | |
54 | ||
ae4e89e5 NTND |
55 | test_expect_success 'gc --keep-largest-pack' ' |
56 | test_create_repo keep-pack && | |
57 | ( | |
58 | cd keep-pack && | |
59 | test_commit one && | |
60 | test_commit two && | |
61 | test_commit three && | |
62 | git gc && | |
63 | ( cd .git/objects/pack && ls *.pack ) >pack-list && | |
64 | test_line_count = 1 pack-list && | |
45a26864 | 65 | cp pack-list base-pack-list && |
ae4e89e5 NTND |
66 | test_commit four && |
67 | git repack -d && | |
68 | test_commit five && | |
69 | git repack -d && | |
70 | ( cd .git/objects/pack && ls *.pack ) >pack-list && | |
71 | test_line_count = 3 pack-list && | |
72 | git gc --keep-largest-pack && | |
73 | ( cd .git/objects/pack && ls *.pack ) >pack-list && | |
74 | test_line_count = 2 pack-list && | |
e941c48d EW |
75 | awk "/^P /{print \$2}" <.git/objects/info/packs >pack-info && |
76 | test_line_count = 2 pack-info && | |
45a26864 | 77 | test_path_is_file .git/objects/pack/$(cat base-pack-list) && |
ae4e89e5 NTND |
78 | git fsck |
79 | ) | |
80 | ' | |
81 | ||
9eb542f2 ÆAB |
82 | test_expect_success 'pre-auto-gc hook can stop auto gc' ' |
83 | cat >err.expect <<-\EOF && | |
84 | no gc for you | |
85 | EOF | |
86 | ||
87 | git init pre-auto-gc-hook && | |
d7ef0368 ÆAB |
88 | test_hook -C pre-auto-gc-hook pre-auto-gc <<-\EOF && |
89 | echo >&2 no gc for you && | |
90 | exit 1 | |
91 | EOF | |
9eb542f2 ÆAB |
92 | ( |
93 | cd pre-auto-gc-hook && | |
9eb542f2 ÆAB |
94 | |
95 | git config gc.auto 3 && | |
96 | git config gc.autoDetach false && | |
97 | ||
98 | # We need to create two object whose sha1s start with 17 | |
99 | # since this is what git gc counts. As it happens, these | |
100 | # two blobs will do so. | |
77257e3c PS |
101 | test_commit "$(test_oid blob17_1)" && |
102 | test_commit "$(test_oid blob17_2)" && | |
9eb542f2 ÆAB |
103 | |
104 | git gc --auto >../out.actual 2>../err.actual | |
105 | ) && | |
106 | test_must_be_empty out.actual && | |
107 | test_cmp err.expect err.actual && | |
108 | ||
109 | cat >err.expect <<-\EOF && | |
110 | will gc for you | |
111 | Auto packing the repository for optimum performance. | |
112 | See "git help gc" for manual housekeeping. | |
113 | EOF | |
114 | ||
d7ef0368 ÆAB |
115 | test_hook -C pre-auto-gc-hook --clobber pre-auto-gc <<-\EOF && |
116 | echo >&2 will gc for you && | |
117 | exit 0 | |
118 | EOF | |
119 | ||
120 | git -C pre-auto-gc-hook gc --auto >out.actual 2>err.actual && | |
9eb542f2 ÆAB |
121 | |
122 | test_must_be_empty out.actual && | |
123 | test_cmp err.expect err.actual | |
124 | ' | |
125 | ||
bdf56de8 DT |
126 | test_expect_success 'auto gc with too many loose objects does not attempt to create bitmaps' ' |
127 | test_config gc.auto 3 && | |
128 | test_config gc.autodetach false && | |
129 | test_config pack.writebitmaps true && | |
130 | # We need to create two object whose sha1s start with 17 | |
131 | # since this is what git gc counts. As it happens, these | |
132 | # two blobs will do so. | |
77257e3c PS |
133 | test_commit "$(test_oid blob17_1)" && |
134 | test_commit "$(test_oid blob17_2)" && | |
bdf56de8 DT |
135 | # Our first gc will create a pack; our second will create a second pack |
136 | git gc --auto && | |
35a8a354 | 137 | ls .git/objects/pack/pack-*.pack | sort >existing_packs && |
77257e3c PS |
138 | test_commit "$(test_oid blob17_3)" && |
139 | test_commit "$(test_oid blob17_4)" && | |
bdf56de8 DT |
140 | |
141 | git gc --auto 2>err && | |
6789275d | 142 | test_grep ! "^warning:" err && |
35a8a354 | 143 | ls .git/objects/pack/pack-*.pack | sort >post_packs && |
bdf56de8 DT |
144 | comm -1 -3 existing_packs post_packs >new && |
145 | comm -2 -3 existing_packs post_packs >del && | |
146 | test_line_count = 0 del && # No packs are deleted | |
35a8a354 | 147 | test_line_count = 1 new # There is one new pack |
bdf56de8 DT |
148 | ' |
149 | ||
6b89a34c | 150 | test_expect_success 'gc --no-quiet' ' |
44a4693b | 151 | GIT_PROGRESS_DELAY=0 git -c gc.writeCommitGraph=true gc --no-quiet >stdout 2>stderr && |
6b89a34c | 152 | test_must_be_empty stdout && |
6789275d | 153 | test_grep "Computing commit graph generation numbers" stderr |
6b89a34c ÆAB |
154 | ' |
155 | ||
156 | test_expect_success TTY 'with TTY: gc --no-quiet' ' | |
ecc08690 DS |
157 | test_terminal env GIT_PROGRESS_DELAY=0 \ |
158 | git -c gc.writeCommitGraph=true gc --no-quiet >stdout 2>stderr && | |
6b89a34c | 159 | test_must_be_empty stdout && |
6789275d JH |
160 | test_grep "Enumerating objects" stderr && |
161 | test_grep "Computing commit graph generation numbers" stderr | |
6b89a34c ÆAB |
162 | ' |
163 | ||
164 | test_expect_success 'gc --quiet' ' | |
165 | git -c gc.writeCommitGraph=true gc --quiet >stdout 2>stderr && | |
166 | test_must_be_empty stdout && | |
167 | test_must_be_empty stderr | |
168 | ' | |
169 | ||
bf3d70fe ÆAB |
170 | test_expect_success 'gc.reflogExpire{Unreachable,}=never skips "expire" via "gc"' ' |
171 | test_config gc.reflogExpire never && | |
172 | test_config gc.reflogExpireUnreachable never && | |
173 | ||
174 | GIT_TRACE=$(pwd)/trace.out git gc && | |
175 | ||
176 | # Check that git-pack-refs is run as a sanity check (done via | |
177 | # gc_before_repack()) but that git-expire is not. | |
178 | grep -E "^trace: (built-in|exec|run_command): git pack-refs --" trace.out && | |
179 | ! grep -E "^trace: (built-in|exec|run_command): git reflog expire --" trace.out | |
180 | ' | |
181 | ||
182 | test_expect_success 'one of gc.reflogExpire{Unreachable,}=never does not skip "expire" via "gc"' ' | |
183 | >trace.out && | |
184 | test_config gc.reflogExpire never && | |
185 | GIT_TRACE=$(pwd)/trace.out git gc && | |
186 | grep -E "^trace: (built-in|exec|run_command): git reflog expire --" trace.out | |
187 | ' | |
188 | ||
1cd43a9e | 189 | test_expect_success 'gc.repackFilter launches repack with a filter' ' |
1cd43a9e CC |
190 | git clone --no-local --bare . bare.git && |
191 | ||
192 | git -C bare.git -c gc.cruftPacks=false gc && | |
193 | test_stdout_line_count = 1 ls bare.git/objects/pack/*.pack && | |
194 | ||
195 | GIT_TRACE=$(pwd)/trace.out git -C bare.git -c gc.repackFilter=blob:none \ | |
196 | -c repack.writeBitmaps=false -c gc.cruftPacks=false gc && | |
197 | test_stdout_line_count = 2 ls bare.git/objects/pack/*.pack && | |
198 | grep -E "^trace: (built-in|exec|run_command): git repack .* --filter=blob:none ?.*" trace.out | |
199 | ' | |
200 | ||
9b96046b CC |
201 | test_expect_success 'gc.repackFilterTo store filtered out objects' ' |
202 | test_when_finished "rm -rf bare.git filtered.git" && | |
203 | ||
204 | git init --bare filtered.git && | |
205 | git -C bare.git -c gc.repackFilter=blob:none \ | |
206 | -c gc.repackFilterTo=../filtered.git/objects/pack/pack \ | |
207 | -c repack.writeBitmaps=false -c gc.cruftPacks=false gc && | |
208 | ||
209 | test_stdout_line_count = 1 ls bare.git/objects/pack/*.pack && | |
210 | test_stdout_line_count = 1 ls filtered.git/objects/pack/*.pack | |
211 | ' | |
212 | ||
12253ab6 ES |
213 | prepare_cruft_history () { |
214 | test_commit base && | |
215 | ||
216 | test_commit --no-tag foo && | |
217 | test_commit --no-tag bar && | |
218 | git reset HEAD^^ | |
219 | } | |
220 | ||
c6955928 ES |
221 | assert_no_cruft_packs () { |
222 | find .git/objects/pack -name "*.mtimes" >mtimes && | |
223 | test_must_be_empty mtimes | |
224 | } | |
225 | ||
50685e0e | 226 | for argv in \ |
e3e24de1 | 227 | "gc" \ |
50685e0e | 228 | "-c gc.cruftPacks=true gc" \ |
e3e24de1 | 229 | "-c gc.cruftPacks=false gc --cruft" |
50685e0e TB |
230 | do |
231 | test_expect_success "git $argv generates a cruft pack" ' | |
232 | test_when_finished "rm -fr repo" && | |
233 | git init repo && | |
234 | ( | |
235 | cd repo && | |
236 | ||
237 | prepare_cruft_history && | |
238 | git $argv && | |
239 | ||
240 | find .git/objects/pack -name "*.mtimes" >mtimes && | |
241 | sed -e 's/\.mtimes$/\.pack/g' mtimes >packs && | |
242 | ||
243 | test_file_not_empty packs && | |
244 | while read pack | |
245 | do | |
246 | test_path_is_file "$pack" || return 1 | |
247 | done <packs | |
248 | ) | |
249 | ' | |
250 | done | |
251 | ||
252 | for argv in \ | |
e3e24de1 | 253 | "gc --no-cruft" \ |
b9061bc6 | 254 | "-c gc.cruftPacks=false gc" \ |
e3e24de1 | 255 | "-c gc.cruftPacks=true gc --no-cruft" |
50685e0e TB |
256 | do |
257 | test_expect_success "git $argv does not generate a cruft pack" ' | |
258 | test_when_finished "rm -fr repo" && | |
259 | git init repo && | |
260 | ( | |
261 | cd repo && | |
262 | ||
263 | prepare_cruft_history && | |
264 | git $argv && | |
265 | ||
266 | assert_no_cruft_packs | |
267 | ) | |
268 | ' | |
269 | done | |
c6955928 | 270 | |
05b9013b TB |
271 | test_expect_success '--keep-largest-pack ignores cruft packs' ' |
272 | test_when_finished "rm -fr repo" && | |
273 | git init repo && | |
274 | ( | |
275 | cd repo && | |
276 | ||
277 | # Generate a pack for reachable objects (of which there | |
278 | # are 3), and one for unreachable objects (of which | |
279 | # there are 6). | |
280 | prepare_cruft_history && | |
281 | git gc --cruft && | |
282 | ||
283 | mtimes="$(find .git/objects/pack -type f -name "pack-*.mtimes")" && | |
284 | sz="$(test_file_size "${mtimes%.mtimes}.pack")" && | |
285 | ||
286 | # Ensure that the cruft pack gets removed (due to | |
287 | # `--prune=now`) despite it being the largest pack. | |
288 | git -c gc.bigPackThreshold=$sz gc --cruft --prune=now && | |
289 | ||
290 | assert_no_cruft_packs | |
291 | ) | |
292 | ' | |
293 | ||
294 | test_expect_success 'gc.bigPackThreshold ignores cruft packs' ' | |
295 | test_when_finished "rm -fr repo" && | |
296 | git init repo && | |
297 | ( | |
298 | cd repo && | |
299 | ||
300 | # Generate a pack for reachable objects (of which there | |
301 | # are 3), and one for unreachable objects (of which | |
302 | # there are 6). | |
303 | prepare_cruft_history && | |
304 | git gc --cruft && | |
305 | ||
306 | # Ensure that the cruft pack gets removed (due to | |
307 | # `--prune=now`) despite it being the largest pack. | |
308 | git gc --cruft --prune=now --keep-largest-pack && | |
309 | ||
310 | assert_no_cruft_packs | |
311 | ) | |
312 | ' | |
313 | ||
37dc6d81 TB |
314 | cruft_max_size_opts="git repack -d -l --cruft --cruft-expiration=2.weeks.ago" |
315 | ||
316 | test_expect_success 'setup for --max-cruft-size tests' ' | |
317 | git init cruft--max-size && | |
318 | ( | |
319 | cd cruft--max-size && | |
320 | prepare_cruft_history | |
321 | ) | |
322 | ' | |
323 | ||
324 | test_expect_success '--max-cruft-size sets appropriate repack options' ' | |
325 | GIT_TRACE2_EVENT=$(pwd)/trace2.txt git -C cruft--max-size \ | |
326 | gc --cruft --max-cruft-size=1M && | |
327 | test_subcommand $cruft_max_size_opts --max-cruft-size=1048576 <trace2.txt | |
328 | ' | |
329 | ||
330 | test_expect_success 'gc.maxCruftSize sets appropriate repack options' ' | |
331 | GIT_TRACE2_EVENT=$(pwd)/trace2.txt \ | |
332 | git -C cruft--max-size -c gc.maxCruftSize=2M gc --cruft && | |
333 | test_subcommand $cruft_max_size_opts --max-cruft-size=2097152 <trace2.txt && | |
334 | ||
335 | GIT_TRACE2_EVENT=$(pwd)/trace2.txt \ | |
336 | git -C cruft--max-size -c gc.maxCruftSize=2M gc --cruft \ | |
337 | --max-cruft-size=3M && | |
338 | test_subcommand $cruft_max_size_opts --max-cruft-size=3145728 <trace2.txt | |
339 | ' | |
340 | ||
ef09036c SG |
341 | run_and_wait_for_auto_gc () { |
342 | # We read stdout from gc for the side effect of waiting until the | |
343 | # background gc process exits, closing its fd 9. Furthermore, the | |
344 | # variable assignment from a command substitution preserves the | |
345 | # exit status of the main gc process. | |
346 | # Note: this fd trickery doesn't work on Windows, but there is no | |
347 | # need to, because on Win the auto gc always runs in the foreground. | |
348 | doesnt_matter=$(git gc --auto 9>&1) | |
349 | } | |
350 | ||
a831c06a DT |
351 | test_expect_success 'background auto gc does not run if gc.log is present and recent but does if it is old' ' |
352 | test_commit foo && | |
353 | test_commit bar && | |
354 | git repack && | |
355 | test_config gc.autopacklimit 1 && | |
356 | test_config gc.autodetach true && | |
357 | echo fleem >.git/gc.log && | |
30299702 | 358 | git gc --auto 2>err && |
6789275d | 359 | test_grep "^warning:" err && |
a831c06a | 360 | test_config gc.logexpiry 5.days && |
0e496492 | 361 | test-tool chmtime =-345600 .git/gc.log && |
30299702 | 362 | git gc --auto && |
a831c06a | 363 | test_config gc.logexpiry 2.days && |
ef09036c SG |
364 | run_and_wait_for_auto_gc && |
365 | ls .git/objects/pack/pack-*.pack >packs && | |
366 | test_line_count = 1 packs | |
a831c06a | 367 | ' |
bdf56de8 | 368 | |
c45af94d JK |
369 | test_expect_success 'background auto gc respects lock for all operations' ' |
370 | # make sure we run a background auto-gc | |
371 | test_commit make-pack && | |
372 | git repack && | |
373 | test_config gc.autopacklimit 1 && | |
374 | test_config gc.autodetach true && | |
375 | ||
376 | # create a ref whose loose presence we can use to detect a pack-refs run | |
377 | git update-ref refs/heads/should-be-loose HEAD && | |
f95661b7 | 378 | (ls -1 .git/refs/heads .git/reftable >expect || true) && |
c45af94d JK |
379 | |
380 | # now fake a concurrent gc that holds the lock; we can use our | |
381 | # shell pid so that it looks valid. | |
382 | hostname=$(hostname || echo unknown) && | |
c871fbee JS |
383 | shell_pid=$$ && |
384 | if test_have_prereq MINGW && test -f /proc/$shell_pid/winpid | |
385 | then | |
386 | # In Git for Windows, Bash (actually, the MSYS2 runtime) has a | |
387 | # different idea of PIDs than git.exe (actually Windows). Use | |
388 | # the Windows PID in this case. | |
389 | shell_pid=$(cat /proc/$shell_pid/winpid) | |
390 | fi && | |
391 | printf "%d %s" "$shell_pid" "$hostname" >.git/gc.pid && | |
c45af94d JK |
392 | |
393 | # our gc should exit zero without doing anything | |
394 | run_and_wait_for_auto_gc && | |
f95661b7 HWN |
395 | (ls -1 .git/refs/heads .git/reftable >actual || true) && |
396 | test_cmp expect actual | |
c45af94d JK |
397 | ' |
398 | ||
ef09036c SG |
399 | # DO NOT leave a detached auto gc process running near the end of the |
400 | # test script: it can run long enough in the background to racily | |
401 | # interfere with the cleanup in 'test_done'. | |
402 | ||
0c8151b6 | 403 | test_done |