]>
Commit | Line | Data |
---|---|---|
1389d9dd JH |
1 | #!/bin/sh |
2 | # | |
3 | # Copyright (c) 2007 Junio C Hamano | |
4 | # | |
5 | ||
6 | test_description='Test prune and reflog expiration' | |
06d53148 | 7 | GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main |
334afbc7 JS |
8 | export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME |
9 | ||
b2e5d75d | 10 | TEST_PASSES_SANITIZE_LEAK=true |
1389d9dd JH |
11 | . ./test-lib.sh |
12 | ||
13 | check_have () { | |
14 | gaah= && | |
15 | for N in "$@" | |
16 | do | |
17 | eval "o=\$$N" && git cat-file -t $o || { | |
18 | echo Gaah $N | |
19 | gaah=$N | |
20 | break | |
21 | } | |
22 | done && | |
23 | test -z "$gaah" | |
24 | } | |
25 | ||
26 | check_fsck () { | |
674ba340 | 27 | git fsck --full >fsck.output |
1389d9dd JH |
28 | case "$1" in |
29 | '') | |
674ba340 | 30 | test_must_be_empty fsck.output ;; |
1389d9dd | 31 | *) |
6789275d | 32 | test_grep "$1" fsck.output ;; |
1389d9dd JH |
33 | esac |
34 | } | |
35 | ||
36 | corrupt () { | |
ff4cb42e | 37 | mv .git/objects/$(test_oid_to_path $1) .git/$1 |
1389d9dd JH |
38 | } |
39 | ||
40 | recover () { | |
ff4cb42e | 41 | aa=$(echo $1 | cut -c 1-2) |
1389d9dd | 42 | mkdir -p .git/objects/$aa |
ff4cb42e | 43 | mv .git/$1 .git/objects/$(test_oid_to_path $1) |
1389d9dd JH |
44 | } |
45 | ||
46 | check_dont_have () { | |
47 | gaah= && | |
48 | for N in "$@" | |
49 | do | |
50 | eval "o=\$$N" | |
51 | git cat-file -t $o && { | |
52 | echo Gaah $N | |
53 | gaah=$N | |
54 | break | |
55 | } | |
56 | done | |
57 | test -z "$gaah" | |
58 | } | |
59 | ||
60 | test_expect_success setup ' | |
61 | mkdir -p A/B && | |
62 | echo rat >C && | |
63 | echo ox >A/D && | |
64 | echo tiger >A/B/E && | |
65 | git add . && | |
66 | ||
67 | test_tick && git commit -m rabbit && | |
2c25eaa1 EP |
68 | H=$(git rev-parse --verify HEAD) && |
69 | A=$(git rev-parse --verify HEAD:A) && | |
70 | B=$(git rev-parse --verify HEAD:A/B) && | |
71 | C=$(git rev-parse --verify HEAD:C) && | |
72 | D=$(git rev-parse --verify HEAD:A/D) && | |
73 | E=$(git rev-parse --verify HEAD:A/B/E) && | |
1389d9dd JH |
74 | check_fsck && |
75 | ||
1f553918 | 76 | test_chmod +x C && |
1389d9dd JH |
77 | git add C && |
78 | test_tick && git commit -m dragon && | |
2c25eaa1 | 79 | L=$(git rev-parse --verify HEAD) && |
1389d9dd JH |
80 | check_fsck && |
81 | ||
82 | rm -f C A/B/E && | |
83 | echo snake >F && | |
84 | echo horse >A/G && | |
85 | git add F A/G && | |
86 | test_tick && git commit -a -m sheep && | |
2c25eaa1 EP |
87 | F=$(git rev-parse --verify HEAD:F) && |
88 | G=$(git rev-parse --verify HEAD:A/G) && | |
89 | I=$(git rev-parse --verify HEAD:A) && | |
90 | J=$(git rev-parse --verify HEAD) && | |
1389d9dd JH |
91 | check_fsck && |
92 | ||
93 | rm -f A/G && | |
94 | test_tick && git commit -a -m monkey && | |
2c25eaa1 | 95 | K=$(git rev-parse --verify HEAD) && |
1389d9dd JH |
96 | check_fsck && |
97 | ||
98 | check_have A B C D E F G H I J K L && | |
99 | ||
026aa938 | 100 | git prune && |
1389d9dd JH |
101 | |
102 | check_have A B C D E F G H I J K L && | |
103 | ||
104 | check_fsck && | |
105 | ||
06d53148 | 106 | git reflog refs/heads/main >output && |
d0ab0584 | 107 | test_line_count = 4 output |
1389d9dd JH |
108 | ' |
109 | ||
e3c36758 ÆAB |
110 | test_expect_success 'correct usage on sub-command -h' ' |
111 | test_expect_code 129 git reflog expire -h >err && | |
112 | grep "git reflog expire" err | |
113 | ' | |
114 | ||
fbc15b13 ÆAB |
115 | test_expect_success 'correct usage on "git reflog show -h"' ' |
116 | test_expect_code 129 git reflog show -h >err && | |
117 | grep -F "git reflog [show]" err | |
118 | ' | |
119 | ||
e3c36758 ÆAB |
120 | test_expect_success 'pass through -- to sub-command' ' |
121 | test_when_finished "rm -rf repo" && | |
122 | git init repo && | |
123 | test_commit -C repo message --a-file contents dash-tag && | |
124 | ||
125 | git -C repo reflog show -- --does-not-exist >out && | |
126 | test_must_be_empty out && | |
127 | git -C repo reflog show >expect && | |
128 | git -C repo reflog show -- --a-file >actual && | |
129 | test_cmp expect actual | |
130 | ' | |
131 | ||
1389d9dd JH |
132 | test_expect_success rewind ' |
133 | test_tick && git reset --hard HEAD~2 && | |
134 | test -f C && | |
135 | test -f A/B/E && | |
136 | ! test -f F && | |
137 | ! test -f A/G && | |
138 | ||
139 | check_have A B C D E F G H I J K L && | |
140 | ||
026aa938 | 141 | git prune && |
1389d9dd JH |
142 | |
143 | check_have A B C D E F G H I J K L && | |
144 | ||
06d53148 | 145 | git reflog refs/heads/main >output && |
d0ab0584 | 146 | test_line_count = 5 output |
1389d9dd JH |
147 | ' |
148 | ||
149 | test_expect_success 'corrupt and check' ' | |
150 | ||
151 | corrupt $F && | |
152 | check_fsck "missing blob $F" | |
153 | ||
154 | ' | |
155 | ||
156 | test_expect_success 'reflog expire --dry-run should not touch reflog' ' | |
157 | ||
158 | git reflog expire --dry-run \ | |
159 | --expire=$(($test_tick - 10000)) \ | |
160 | --expire-unreachable=$(($test_tick - 10000)) \ | |
161 | --stale-fix \ | |
162 | --all && | |
163 | ||
06d53148 | 164 | git reflog refs/heads/main >output && |
d0ab0584 | 165 | test_line_count = 5 output && |
1389d9dd JH |
166 | |
167 | check_fsck "missing blob $F" | |
168 | ' | |
169 | ||
170 | test_expect_success 'reflog expire' ' | |
171 | ||
172 | git reflog expire --verbose \ | |
173 | --expire=$(($test_tick - 10000)) \ | |
174 | --expire-unreachable=$(($test_tick - 10000)) \ | |
175 | --stale-fix \ | |
176 | --all && | |
177 | ||
06d53148 | 178 | git reflog refs/heads/main >output && |
d0ab0584 | 179 | test_line_count = 2 output && |
1389d9dd JH |
180 | |
181 | check_fsck "dangling commit $K" | |
182 | ' | |
183 | ||
c809798b JS |
184 | test_expect_success '--stale-fix handles missing objects generously' ' |
185 | git -c core.logAllRefUpdates=false fast-import --date-format=now <<-EOS && | |
186 | commit refs/heads/stale-fix | |
187 | mark :1 | |
188 | committer Author <a@uth.or> now | |
189 | data <<EOF | |
190 | start stale fix | |
191 | EOF | |
192 | M 100644 inline file | |
193 | data <<EOF | |
194 | contents | |
195 | EOF | |
196 | commit refs/heads/stale-fix | |
197 | committer Author <a@uth.or> now | |
198 | data <<EOF | |
199 | stale fix branch tip | |
200 | EOF | |
201 | from :1 | |
202 | EOS | |
203 | ||
204 | parent_oid=$(git rev-parse stale-fix^) && | |
205 | test_when_finished "recover $parent_oid" && | |
206 | corrupt $parent_oid && | |
207 | git reflog expire --stale-fix | |
208 | ' | |
209 | ||
1389d9dd JH |
210 | test_expect_success 'prune and fsck' ' |
211 | ||
026aa938 | 212 | git prune && |
1389d9dd JH |
213 | check_fsck && |
214 | ||
215 | check_have A B C D E H L && | |
216 | check_dont_have F G I J K | |
217 | ||
218 | ' | |
219 | ||
220 | test_expect_success 'recover and check' ' | |
221 | ||
222 | recover $F && | |
223 | check_fsck "dangling blob $F" | |
224 | ||
225 | ' | |
226 | ||
55beff4f | 227 | test_expect_success 'delete' ' |
552cecc2 JS |
228 | echo 1 > C && |
229 | test_tick && | |
230 | git commit -m rat C && | |
231 | ||
232 | echo 2 > C && | |
233 | test_tick && | |
234 | git commit -m ox C && | |
235 | ||
236 | echo 3 > C && | |
237 | test_tick && | |
238 | git commit -m tiger C && | |
239 | ||
a48fcd83 | 240 | HEAD_entry_count=$(git reflog | wc -l) && |
06d53148 | 241 | main_entry_count=$(git reflog show main | wc -l) && |
38881a90 PB |
242 | |
243 | test $HEAD_entry_count = 5 && | |
06d53148 | 244 | test $main_entry_count = 5 && |
38881a90 | 245 | |
552cecc2 | 246 | |
06d53148 JS |
247 | git reflog delete main@{1} && |
248 | git reflog show main > output && | |
249 | test_line_count = $(($main_entry_count - 1)) output && | |
38881a90 | 250 | test $HEAD_entry_count = $(git reflog | wc -l) && |
552cecc2 JS |
251 | ! grep ox < output && |
252 | ||
06d53148 | 253 | main_entry_count=$(wc -l < output) && |
38881a90 PB |
254 | |
255 | git reflog delete HEAD@{1} && | |
256 | test $(($HEAD_entry_count -1)) = $(git reflog | wc -l) && | |
06d53148 | 257 | test $main_entry_count = $(git reflog show main | wc -l) && |
38881a90 | 258 | |
a48fcd83 | 259 | HEAD_entry_count=$(git reflog | wc -l) && |
38881a90 | 260 | |
06d53148 JS |
261 | git reflog delete main@{07.04.2005.15:15:00.-0700} && |
262 | git reflog show main > output && | |
263 | test_line_count = $(($main_entry_count - 1)) output && | |
552cecc2 | 264 | ! grep dragon < output |
50f3ac29 JH |
265 | |
266 | ' | |
267 | ||
4a9f4394 AS |
268 | test_expect_success 'rewind2' ' |
269 | ||
270 | test_tick && git reset --hard HEAD~2 && | |
06d53148 | 271 | git reflog refs/heads/main >output && |
d0ab0584 | 272 | test_line_count = 4 output |
4a9f4394 AS |
273 | ' |
274 | ||
275 | test_expect_success '--expire=never' ' | |
276 | ||
277 | git reflog expire --verbose \ | |
278 | --expire=never \ | |
279 | --expire-unreachable=never \ | |
280 | --all && | |
06d53148 | 281 | git reflog refs/heads/main >output && |
d0ab0584 | 282 | test_line_count = 4 output |
4a9f4394 AS |
283 | ' |
284 | ||
285 | test_expect_success 'gc.reflogexpire=never' ' | |
a65bf78c ÆAB |
286 | test_config gc.reflogexpire never && |
287 | test_config gc.reflogexpireunreachable never && | |
4a9f4394 | 288 | |
978f4307 ÆAB |
289 | git reflog expire --verbose --all >output && |
290 | test_line_count = 9 output && | |
291 | ||
06d53148 | 292 | git reflog refs/heads/main >output && |
d0ab0584 | 293 | test_line_count = 4 output |
4a9f4394 AS |
294 | ' |
295 | ||
296 | test_expect_success 'gc.reflogexpire=false' ' | |
a65bf78c ÆAB |
297 | test_config gc.reflogexpire false && |
298 | test_config gc.reflogexpireunreachable false && | |
4a9f4394 | 299 | |
4a9f4394 | 300 | git reflog expire --verbose --all && |
06d53148 | 301 | git reflog refs/heads/main >output && |
a65bf78c | 302 | test_line_count = 4 output |
4a9f4394 AS |
303 | |
304 | ' | |
305 | ||
fe66776d ÆAB |
306 | test_expect_success 'git reflog expire unknown reference' ' |
307 | test_config gc.reflogexpire never && | |
308 | test_config gc.reflogexpireunreachable never && | |
309 | ||
06d53148 | 310 | test_must_fail git reflog expire main@{123} 2>stderr && |
6789275d | 311 | test_grep "points nowhere" stderr && |
fe66776d | 312 | test_must_fail git reflog expire does-not-exist 2>stderr && |
6789275d | 313 | test_grep "points nowhere" stderr |
fe66776d ÆAB |
314 | ' |
315 | ||
482b8f32 | 316 | test_expect_success 'checkout should not delete log for packed ref' ' |
06d53148 | 317 | test $(git reflog main | wc -l) = 4 && |
482b8f32 RS |
318 | git branch foo && |
319 | git pack-refs --all && | |
320 | git checkout foo && | |
06d53148 | 321 | test $(git reflog main | wc -l) = 4 |
482b8f32 RS |
322 | ' |
323 | ||
9233887c | 324 | test_expect_success 'stale dirs do not cause d/f conflicts (reflogs on)' ' |
aae828b9 | 325 | test_when_finished "git branch -d one || git branch -d one/two" && |
9233887c | 326 | |
06d53148 JS |
327 | git branch one/two main && |
328 | echo "one/two@{0} branch: Created from main" >expect && | |
aae828b9 | 329 | git log -g --format="%gd %gs" one/two >actual && |
9233887c | 330 | test_cmp expect actual && |
aae828b9 | 331 | git branch -d one/two && |
9233887c | 332 | |
aae828b9 JK |
333 | # now logs/refs/heads/one is a stale directory, but |
334 | # we should move it out of the way to create "one" reflog | |
06d53148 JS |
335 | git branch one main && |
336 | echo "one@{0} branch: Created from main" >expect && | |
aae828b9 | 337 | git log -g --format="%gd %gs" one >actual && |
9233887c JK |
338 | test_cmp expect actual |
339 | ' | |
340 | ||
341 | test_expect_success 'stale dirs do not cause d/f conflicts (reflogs off)' ' | |
aae828b9 | 342 | test_when_finished "git branch -d one || git branch -d one/two" && |
9233887c | 343 | |
06d53148 JS |
344 | git branch one/two main && |
345 | echo "one/two@{0} branch: Created from main" >expect && | |
aae828b9 | 346 | git log -g --format="%gd %gs" one/two >actual && |
9233887c | 347 | test_cmp expect actual && |
aae828b9 | 348 | git branch -d one/two && |
9233887c | 349 | |
aae828b9 | 350 | # same as before, but we only create a reflog for "one" if |
9233887c | 351 | # it already exists, which it does not |
06d53148 | 352 | git -c core.logallrefupdates=false branch one main && |
aae828b9 | 353 | git log -g --format="%gd %gs" one >actual && |
1c5e94f4 | 354 | test_must_be_empty actual |
9233887c JK |
355 | ' |
356 | ||
aecad374 DK |
357 | test_expect_success 'no segfaults for reflog containing non-commit sha1s' ' |
358 | git update-ref --create-reflog -m "Creating ref" \ | |
359 | refs/tests/tree-in-reflog HEAD && | |
360 | git update-ref -m "Forcing tree" refs/tests/tree-in-reflog HEAD^{tree} && | |
361 | git update-ref -m "Restoring to commit" refs/tests/tree-in-reflog HEAD && | |
362 | git reflog refs/tests/tree-in-reflog | |
363 | ' | |
364 | ||
365 | test_expect_failure 'reflog with non-commit entries displays all entries' ' | |
366 | git reflog refs/tests/tree-in-reflog >actual && | |
367 | test_line_count = 3 actual | |
368 | ' | |
369 | ||
71abeb75 SG |
370 | test_expect_success 'continue walking past root commits' ' |
371 | git init orphanage && | |
372 | ( | |
373 | cd orphanage && | |
374 | cat >expect <<-\EOF && | |
375 | HEAD@{0} commit (initial): orphan2-1 | |
376 | HEAD@{1} commit: orphan1-2 | |
377 | HEAD@{2} commit (initial): orphan1-1 | |
378 | HEAD@{3} commit (initial): initial | |
379 | EOF | |
380 | test_commit initial && | |
71abeb75 SG |
381 | git checkout --orphan orphan1 && |
382 | test_commit orphan1-1 && | |
383 | test_commit orphan1-2 && | |
384 | git checkout --orphan orphan2 && | |
385 | test_commit orphan2-1 && | |
386 | git log -g --format="%gd %gs" >actual && | |
387 | test_cmp expect actual | |
388 | ) | |
389 | ' | |
390 | ||
c9ef0d95 NTND |
391 | test_expect_success 'expire with multiple worktrees' ' |
392 | git init main-wt && | |
393 | ( | |
394 | cd main-wt && | |
395 | test_tick && | |
396 | test_commit foo && | |
397 | git worktree add link-wt && | |
398 | test_tick && | |
399 | test_commit -C link-wt foobar && | |
400 | test_tick && | |
401 | git reflog expire --verbose --all --expire=$test_tick && | |
8c2d8d04 HWN |
402 | test-tool ref-store worktree:link-wt for-each-reflog-ent HEAD >actual && |
403 | test_must_be_empty actual | |
c9ef0d95 NTND |
404 | ) |
405 | ' | |
406 | ||
26d4c51d RS |
407 | test_expect_success 'expire one of multiple worktrees' ' |
408 | git init main-wt2 && | |
409 | ( | |
410 | cd main-wt2 && | |
411 | test_tick && | |
412 | test_commit foo && | |
413 | git worktree add link-wt && | |
414 | test_tick && | |
415 | test_commit -C link-wt foobar && | |
416 | test_tick && | |
417 | test-tool ref-store worktree:link-wt for-each-reflog-ent HEAD \ | |
418 | >expect-link-wt && | |
419 | git reflog expire --verbose --all --expire=$test_tick \ | |
420 | --single-worktree && | |
421 | test-tool ref-store worktree:main for-each-reflog-ent HEAD \ | |
422 | >actual-main && | |
423 | test-tool ref-store worktree:link-wt for-each-reflog-ent HEAD \ | |
424 | >actual-link-wt && | |
425 | test_must_be_empty actual-main && | |
426 | test_cmp expect-link-wt actual-link-wt | |
427 | ) | |
428 | ' | |
429 | ||
88121d93 | 430 | test_expect_success 'empty reflog' ' |
57be9c6d ÆAB |
431 | test_when_finished "rm -rf empty" && |
432 | git init empty && | |
433 | test_commit -C empty A && | |
88121d93 | 434 | test-tool ref-store main create-reflog refs/heads/foo && |
57be9c6d ÆAB |
435 | git -C empty reflog expire --all 2>err && |
436 | test_must_be_empty err | |
437 | ' | |
438 | ||
d699d15c PS |
439 | test_expect_success 'list reflogs' ' |
440 | test_when_finished "rm -rf repo" && | |
441 | git init repo && | |
442 | ( | |
443 | cd repo && | |
444 | git reflog list >actual && | |
445 | test_must_be_empty actual && | |
446 | ||
447 | test_commit A && | |
448 | cat >expect <<-EOF && | |
449 | HEAD | |
450 | refs/heads/main | |
451 | EOF | |
452 | git reflog list >actual && | |
453 | test_cmp expect actual && | |
454 | ||
455 | git branch b && | |
456 | cat >expect <<-EOF && | |
457 | HEAD | |
458 | refs/heads/b | |
459 | refs/heads/main | |
460 | EOF | |
461 | git reflog list >actual && | |
462 | test_cmp expect actual | |
463 | ) | |
464 | ' | |
465 | ||
466 | test_expect_success 'list reflogs with worktree' ' | |
467 | test_when_finished "rm -rf repo" && | |
468 | git init repo && | |
469 | ( | |
470 | cd repo && | |
471 | ||
472 | test_commit A && | |
473 | git worktree add wt && | |
474 | git -c core.logAllRefUpdates=always \ | |
475 | update-ref refs/worktree/main HEAD && | |
476 | git -c core.logAllRefUpdates=always \ | |
477 | update-ref refs/worktree/per-worktree HEAD && | |
478 | git -c core.logAllRefUpdates=always -C wt \ | |
479 | update-ref refs/worktree/per-worktree HEAD && | |
480 | git -c core.logAllRefUpdates=always -C wt \ | |
481 | update-ref refs/worktree/worktree HEAD && | |
482 | ||
483 | cat >expect <<-EOF && | |
484 | HEAD | |
485 | refs/heads/main | |
486 | refs/heads/wt | |
487 | refs/worktree/main | |
488 | refs/worktree/per-worktree | |
489 | EOF | |
490 | git reflog list >actual && | |
491 | test_cmp expect actual && | |
492 | ||
493 | cat >expect <<-EOF && | |
494 | HEAD | |
495 | refs/heads/main | |
496 | refs/heads/wt | |
497 | refs/worktree/per-worktree | |
498 | refs/worktree/worktree | |
499 | EOF | |
500 | git -C wt reflog list >actual && | |
501 | test_cmp expect actual | |
502 | ) | |
503 | ' | |
504 | ||
505 | test_expect_success 'reflog list returns error with additional args' ' | |
506 | cat >expect <<-EOF && | |
507 | error: list does not accept arguments: ${SQ}bogus${SQ} | |
508 | EOF | |
509 | test_must_fail git reflog list bogus 2>err && | |
510 | test_cmp expect err | |
511 | ' | |
512 | ||
513 | test_expect_success 'reflog for symref with unborn target can be listed' ' | |
514 | test_when_finished "rm -rf repo" && | |
515 | git init repo && | |
516 | ( | |
517 | cd repo && | |
518 | test_commit A && | |
519 | git symbolic-ref HEAD refs/heads/unborn && | |
520 | cat >expect <<-EOF && | |
521 | HEAD | |
522 | refs/heads/main | |
523 | EOF | |
524 | git reflog list >actual && | |
525 | test_cmp expect actual | |
526 | ) | |
527 | ' | |
528 | ||
529 | test_expect_success 'reflog with invalid object ID can be listed' ' | |
530 | test_when_finished "rm -rf repo" && | |
531 | git init repo && | |
532 | ( | |
533 | cd repo && | |
534 | test_commit A && | |
535 | test-tool ref-store main update-ref msg refs/heads/missing \ | |
536 | $(test_oid deadbeef) "$ZERO_OID" REF_SKIP_OID_VERIFICATION && | |
537 | cat >expect <<-EOF && | |
538 | HEAD | |
539 | refs/heads/main | |
540 | refs/heads/missing | |
541 | EOF | |
542 | git reflog list >actual && | |
543 | test_cmp expect actual | |
544 | ) | |
545 | ' | |
546 | ||
1389d9dd | 547 | test_done |