]>
Commit | Line | Data |
---|---|---|
8464010f DST |
1 | #!/bin/sh |
2 | # | |
3 | # Copyright (c) 2008 Johannes E. Schindelin | |
4 | # | |
5 | ||
6 | test_description='prune' | |
966b4be2 | 7 | GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main |
334afbc7 JS |
8 | export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME |
9 | ||
8464010f DST |
10 | . ./test-lib.sh |
11 | ||
98df233e CB |
12 | day=$((60*60*24)) |
13 | week=$(($day*7)) | |
14 | ||
15 | add_blob() { | |
16 | before=$(git count-objects | sed "s/ .*//") && | |
17 | BLOB=$(echo aleph_0 | git hash-object -w --stdin) && | |
18 | BLOB_FILE=.git/objects/$(echo $BLOB | sed "s/^../&\//") && | |
8ad16524 | 19 | verbose test $((1 + $before)) = $(git count-objects | sed "s/ .*//") && |
f1dd90bd | 20 | test_path_is_file $BLOB_FILE && |
0e496492 | 21 | test-tool chmtime =+0 $BLOB_FILE |
98df233e CB |
22 | } |
23 | ||
8464010f DST |
24 | test_expect_success setup ' |
25 | ||
26 | : > file && | |
27 | git add file && | |
28 | test_tick && | |
29 | git commit -m initial && | |
30 | git gc | |
31 | ||
32 | ' | |
33 | ||
34 | test_expect_success 'prune stale packs' ' | |
35 | ||
36 | orig_pack=$(echo .git/objects/pack/*.pack) && | |
37 | : > .git/objects/tmp_1.pack && | |
38 | : > .git/objects/tmp_2.pack && | |
0e496492 | 39 | test-tool chmtime =-86501 .git/objects/tmp_1.pack && |
8464010f | 40 | git prune --expire 1.day && |
f1dd90bd JK |
41 | test_path_is_file $orig_pack && |
42 | test_path_is_file .git/objects/tmp_2.pack && | |
43 | test_path_is_missing .git/objects/tmp_1.pack | |
8464010f DST |
44 | |
45 | ' | |
46 | ||
25ee9731 JS |
47 | test_expect_success 'prune --expire' ' |
48 | ||
98df233e | 49 | add_blob && |
25ee9731 | 50 | git prune --expire=1.hour.ago && |
8ad16524 | 51 | verbose test $((1 + $before)) = $(git count-objects | sed "s/ .*//") && |
f1dd90bd | 52 | test_path_is_file $BLOB_FILE && |
0e496492 | 53 | test-tool chmtime =-86500 $BLOB_FILE && |
25ee9731 | 54 | git prune --expire 1.day && |
8ad16524 | 55 | verbose test $before = $(git count-objects | sed "s/ .*//") && |
f1dd90bd | 56 | test_path_is_missing $BLOB_FILE |
25ee9731 JS |
57 | |
58 | ' | |
59 | ||
60 | test_expect_success 'gc: implicit prune --expire' ' | |
61 | ||
98df233e | 62 | add_blob && |
0e496492 | 63 | test-tool chmtime =-$((2*$week-30)) $BLOB_FILE && |
25ee9731 | 64 | git gc && |
8ad16524 | 65 | verbose test $((1 + $before)) = $(git count-objects | sed "s/ .*//") && |
f1dd90bd | 66 | test_path_is_file $BLOB_FILE && |
0e496492 | 67 | test-tool chmtime =-$((2*$week+1)) $BLOB_FILE && |
25ee9731 | 68 | git gc && |
8ad16524 | 69 | verbose test $before = $(git count-objects | sed "s/ .*//") && |
f1dd90bd | 70 | test_path_is_missing $BLOB_FILE |
25ee9731 JS |
71 | |
72 | ' | |
73 | ||
74 | test_expect_success 'gc: refuse to start with invalid gc.pruneExpire' ' | |
75 | ||
76 | git config gc.pruneExpire invalid && | |
77 | test_must_fail git gc | |
78 | ||
79 | ' | |
80 | ||
81 | test_expect_success 'gc: start with ok gc.pruneExpire' ' | |
82 | ||
83 | git config gc.pruneExpire 2.days.ago && | |
84 | git gc | |
85 | ||
86 | ' | |
87 | ||
0c62705a MB |
88 | test_expect_success 'prune: prune nonsense parameters' ' |
89 | ||
90 | test_must_fail git prune garbage && | |
91 | test_must_fail git prune --- && | |
92 | test_must_fail git prune --no-such-option | |
93 | ||
94 | ' | |
95 | ||
96 | test_expect_success 'prune: prune unreachable heads' ' | |
97 | ||
98 | git config core.logAllRefUpdates false && | |
99 | mv .git/logs .git/logs.old && | |
100 | : > file2 && | |
101 | git add file2 && | |
102 | git commit -m temporary && | |
103 | tmp_head=$(git rev-list -1 HEAD) && | |
104 | git reset HEAD^ && | |
105 | git prune && | |
106 | test_must_fail git reset $tmp_head -- | |
107 | ||
108 | ' | |
109 | ||
c40fdd01 MK |
110 | test_expect_success 'prune: do not prune detached HEAD with no reflog' ' |
111 | ||
112 | git checkout --detach --quiet && | |
113 | git commit --allow-empty -m "detached commit" && | |
114 | # verify that there is no reflogs | |
115 | # (should be removed and disabled by previous test) | |
f1dd90bd | 116 | test_path_is_missing .git/logs && |
c40fdd01 | 117 | git prune -n >prune_actual && |
1c5e94f4 | 118 | test_must_be_empty prune_actual |
c40fdd01 MK |
119 | |
120 | ' | |
121 | ||
122 | test_expect_success 'prune: prune former HEAD after checking out branch' ' | |
123 | ||
cc80c95f | 124 | head_oid=$(git rev-parse HEAD) && |
966b4be2 | 125 | git checkout --quiet main && |
c40fdd01 | 126 | git prune -v >prune_actual && |
cc80c95f | 127 | grep "$head_oid" prune_actual |
c40fdd01 MK |
128 | |
129 | ' | |
130 | ||
fe308f53 | 131 | test_expect_success 'prune: do not prune heads listed as an argument' ' |
0c62705a MB |
132 | |
133 | : > file2 && | |
134 | git add file2 && | |
135 | git commit -m temporary && | |
136 | tmp_head=$(git rev-list -1 HEAD) && | |
137 | git reset HEAD^ && | |
138 | git prune -- $tmp_head && | |
139 | git reset $tmp_head -- | |
140 | ||
141 | ' | |
142 | ||
58e9d9d4 JS |
143 | test_expect_success 'gc --no-prune' ' |
144 | ||
98df233e | 145 | add_blob && |
0e496492 | 146 | test-tool chmtime =-$((5001*$day)) $BLOB_FILE && |
58e9d9d4 JS |
147 | git config gc.pruneExpire 2.days.ago && |
148 | git gc --no-prune && | |
8ad16524 | 149 | verbose test 1 = $(git count-objects | sed "s/ .*//") && |
f1dd90bd | 150 | test_path_is_file $BLOB_FILE |
58e9d9d4 JS |
151 | |
152 | ' | |
153 | ||
154 | test_expect_success 'gc respects gc.pruneExpire' ' | |
155 | ||
156 | git config gc.pruneExpire 5002.days.ago && | |
157 | git gc && | |
f1dd90bd | 158 | test_path_is_file $BLOB_FILE && |
58e9d9d4 JS |
159 | git config gc.pruneExpire 5000.days.ago && |
160 | git gc && | |
f1dd90bd | 161 | test_path_is_missing $BLOB_FILE |
58e9d9d4 JS |
162 | |
163 | ' | |
164 | ||
165 | test_expect_success 'gc --prune=<date>' ' | |
166 | ||
98df233e | 167 | add_blob && |
0e496492 | 168 | test-tool chmtime =-$((5001*$day)) $BLOB_FILE && |
58e9d9d4 | 169 | git gc --prune=5002.days.ago && |
f1dd90bd | 170 | test_path_is_file $BLOB_FILE && |
58e9d9d4 | 171 | git gc --prune=5000.days.ago && |
f1dd90bd | 172 | test_path_is_missing $BLOB_FILE |
58e9d9d4 JS |
173 | |
174 | ' | |
175 | ||
cbf731ed AS |
176 | test_expect_success 'gc --prune=never' ' |
177 | ||
178 | add_blob && | |
179 | git gc --prune=never && | |
f1dd90bd | 180 | test_path_is_file $BLOB_FILE && |
cbf731ed | 181 | git gc --prune=now && |
f1dd90bd | 182 | test_path_is_missing $BLOB_FILE |
cbf731ed AS |
183 | |
184 | ' | |
185 | ||
186 | test_expect_success 'gc respects gc.pruneExpire=never' ' | |
187 | ||
188 | git config gc.pruneExpire never && | |
189 | add_blob && | |
190 | git gc && | |
f1dd90bd | 191 | test_path_is_file $BLOB_FILE && |
cbf731ed AS |
192 | git config gc.pruneExpire now && |
193 | git gc && | |
f1dd90bd | 194 | test_path_is_missing $BLOB_FILE |
cbf731ed AS |
195 | |
196 | ' | |
197 | ||
198 | test_expect_success 'prune --expire=never' ' | |
199 | ||
200 | add_blob && | |
201 | git prune --expire=never && | |
f1dd90bd | 202 | test_path_is_file $BLOB_FILE && |
cbf731ed | 203 | git prune && |
f1dd90bd | 204 | test_path_is_missing $BLOB_FILE |
cbf731ed AS |
205 | |
206 | ' | |
207 | ||
98df233e CB |
208 | test_expect_success 'gc: prune old objects after local clone' ' |
209 | add_blob && | |
0e496492 | 210 | test-tool chmtime =-$((2*$week+1)) $BLOB_FILE && |
98df233e CB |
211 | git clone --no-hardlinks . aclone && |
212 | ( | |
213 | cd aclone && | |
8ad16524 | 214 | verbose test 1 = $(git count-objects | sed "s/ .*//") && |
f1dd90bd | 215 | test_path_is_file $BLOB_FILE && |
98df233e | 216 | git gc --prune && |
8ad16524 | 217 | verbose test 0 = $(git count-objects | sed "s/ .*//") && |
f1dd90bd | 218 | test_path_is_missing $BLOB_FILE |
98df233e CB |
219 | ) |
220 | ' | |
221 | ||
543c5caa | 222 | test_expect_success 'garbage report in count-objects -v' ' |
f813e9ea | 223 | test_when_finished "rm -f .git/objects/pack/fake*" && |
e6d65c9a | 224 | test_when_finished "rm -f .git/objects/pack/foo*" && |
543c5caa NTND |
225 | : >.git/objects/pack/foo && |
226 | : >.git/objects/pack/foo.bar && | |
227 | : >.git/objects/pack/foo.keep && | |
228 | : >.git/objects/pack/foo.pack && | |
229 | : >.git/objects/pack/fake.bar && | |
230 | : >.git/objects/pack/fake.keep && | |
231 | : >.git/objects/pack/fake.pack && | |
232 | : >.git/objects/pack/fake.idx && | |
233 | : >.git/objects/pack/fake2.keep && | |
234 | : >.git/objects/pack/fake3.idx && | |
235 | git count-objects -v 2>stderr && | |
236 | grep "index file .git/objects/pack/fake.idx is too small" stderr && | |
237 | grep "^warning:" stderr | sort >actual && | |
238 | cat >expected <<\EOF && | |
239 | warning: garbage found: .git/objects/pack/fake.bar | |
240 | warning: garbage found: .git/objects/pack/foo | |
241 | warning: garbage found: .git/objects/pack/foo.bar | |
235e8d59 | 242 | warning: no corresponding .idx or .pack: .git/objects/pack/fake2.keep |
543c5caa NTND |
243 | warning: no corresponding .idx: .git/objects/pack/foo.keep |
244 | warning: no corresponding .idx: .git/objects/pack/foo.pack | |
245 | warning: no corresponding .pack: .git/objects/pack/fake3.idx | |
246 | EOF | |
247 | test_cmp expected actual | |
248 | ' | |
249 | ||
478f34d2 | 250 | test_expect_success 'clean pack garbage with gc' ' |
e6d65c9a DK |
251 | test_when_finished "rm -f .git/objects/pack/fake*" && |
252 | test_when_finished "rm -f .git/objects/pack/foo*" && | |
253 | : >.git/objects/pack/foo.keep && | |
254 | : >.git/objects/pack/foo.pack && | |
255 | : >.git/objects/pack/fake.idx && | |
256 | : >.git/objects/pack/fake2.keep && | |
257 | : >.git/objects/pack/fake2.idx && | |
258 | : >.git/objects/pack/fake3.keep && | |
259 | git gc && | |
260 | git count-objects -v 2>stderr && | |
261 | grep "^warning:" stderr | sort >actual && | |
262 | cat >expected <<\EOF && | |
263 | warning: no corresponding .idx or .pack: .git/objects/pack/fake3.keep | |
264 | warning: no corresponding .idx: .git/objects/pack/foo.keep | |
265 | warning: no corresponding .idx: .git/objects/pack/foo.pack | |
266 | EOF | |
267 | test_cmp expected actual | |
268 | ' | |
269 | ||
eab3296c | 270 | test_expect_success 'prune .git/shallow' ' |
cc80c95f JK |
271 | oid=$(echo hi|git commit-tree HEAD^{tree}) && |
272 | echo $oid >.git/shallow && | |
eab3296c | 273 | git prune --dry-run >out && |
cc80c95f JK |
274 | grep $oid .git/shallow && |
275 | grep $oid out && | |
eab3296c | 276 | git prune && |
f1dd90bd | 277 | test_path_is_missing .git/shallow |
eab3296c NTND |
278 | ' |
279 | ||
d55a30bb | 280 | test_expect_success 'prune .git/shallow when there are no loose objects' ' |
cc80c95f JK |
281 | oid=$(echo hi|git commit-tree HEAD^{tree}) && |
282 | echo $oid >.git/shallow && | |
283 | git update-ref refs/heads/shallow-tip $oid && | |
d55a30bb JK |
284 | git repack -ad && |
285 | # verify assumption that all loose objects are gone | |
286 | git count-objects | grep ^0 && | |
287 | git prune && | |
cc80c95f | 288 | echo $oid >expect && |
d55a30bb JK |
289 | test_cmp expect .git/shallow |
290 | ' | |
291 | ||
b0a42642 JM |
292 | test_expect_success 'prune: handle alternate object database' ' |
293 | test_create_repo A && | |
294 | git -C A commit --allow-empty -m "initial commit" && | |
295 | git clone --shared A B && | |
296 | git -C B commit --allow-empty -m "next commit" && | |
297 | git -C B prune | |
298 | ' | |
299 | ||
be489d02 NTND |
300 | test_expect_success 'prune: handle index in multiple worktrees' ' |
301 | git worktree add second-worktree && | |
302 | echo "new blob for second-worktree" >second-worktree/blob && | |
303 | git -C second-worktree add blob && | |
304 | git prune --expire=now && | |
305 | git -C second-worktree show :blob >actual && | |
306 | test_cmp second-worktree/blob actual | |
307 | ' | |
308 | ||
d0c39a49 NTND |
309 | test_expect_success 'prune: handle HEAD in multiple worktrees' ' |
310 | git worktree add --detach third-worktree && | |
311 | echo "new blob for third-worktree" >third-worktree/blob && | |
312 | git -C third-worktree add blob && | |
313 | git -C third-worktree commit -m "third" && | |
314 | rm .git/worktrees/third-worktree/index && | |
315 | test_must_fail git -C third-worktree show :blob && | |
316 | git prune --expire=now && | |
317 | git -C third-worktree show HEAD:blob >actual && | |
318 | test_cmp third-worktree/blob actual | |
319 | ' | |
320 | ||
acd9544a NTND |
321 | test_expect_success 'prune: handle HEAD reflog in multiple worktrees' ' |
322 | git config core.logAllRefUpdates true && | |
323 | echo "lost blob for third-worktree" >expected && | |
324 | ( | |
325 | cd third-worktree && | |
326 | cat ../expected >blob && | |
327 | git add blob && | |
328 | git commit -m "second commit in third" && | |
329 | git reset --hard HEAD^ | |
330 | ) && | |
331 | git prune --expire=now && | |
cc80c95f JK |
332 | oid=`git hash-object expected` && |
333 | git -C third-worktree show "$oid" >actual && | |
acd9544a NTND |
334 | test_cmp expected actual |
335 | ' | |
336 | ||
8ab5aa4b JH |
337 | test_expect_success 'prune: handle expire option correctly' ' |
338 | test_must_fail git prune --expire 2>error && | |
339 | test_i18ngrep "requires a value" error && | |
340 | ||
341 | test_must_fail git prune --expire=nyah 2>error && | |
342 | test_i18ngrep "malformed expiration" error && | |
343 | ||
344 | git prune --no-expire | |
345 | ' | |
346 | ||
fe6f2b08 JK |
347 | test_expect_success 'trivial prune with bitmaps enabled' ' |
348 | git repack -adb && | |
349 | blob=$(echo bitmap-unreachable-blob | git hash-object -w --stdin) && | |
350 | git prune --expire=now && | |
351 | git cat-file -e HEAD && | |
352 | test_must_fail git cat-file -e $blob | |
353 | ' | |
354 | ||
8464010f | 355 | test_done |