]>
Commit | Line | Data |
---|---|---|
8b43fb18 JK |
1 | #!/bin/sh |
2 | ||
3 | test_description=' | |
4 | Test pruning of repositories with minor corruptions. The goal | |
5 | here is that we should always be erring on the side of safety. So | |
6 | if we see, for example, a ref with a bogus name, it is OK either to | |
7 | bail out or to proceed using it as a reachable tip, but it is _not_ | |
8 | OK to proceed as if it did not exist. Otherwise we might silently | |
9 | delete objects that cannot be recovered. | |
5b062e1f JK |
10 | |
11 | Note that we do assert command failure in these cases, because that is | |
12 | what currently happens. If that changes, these tests should be revisited. | |
8b43fb18 | 13 | ' |
966b4be2 | 14 | GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main |
334afbc7 JS |
15 | export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME |
16 | ||
90428ddc | 17 | TEST_PASSES_SANITIZE_LEAK=true |
8b43fb18 JK |
18 | . ./test-lib.sh |
19 | ||
20 | test_expect_success 'disable reflogs' ' | |
21 | git config core.logallrefupdates false && | |
d0ab0584 | 22 | git reflog expire --expire=all --all |
8b43fb18 JK |
23 | ' |
24 | ||
f8058446 | 25 | create_bogus_ref () { |
eaf0e830 HWN |
26 | test-tool ref-store main update-ref msg "refs/heads/bogus..name" $bogus $ZERO_OID REF_SKIP_REFNAME_VERIFICATION && |
27 | test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/bogus..name" | |
f8058446 JK |
28 | } |
29 | ||
8b43fb18 | 30 | test_expect_success 'create history reachable only from a bogus-named ref' ' |
966b4be2 | 31 | test_tick && git commit --allow-empty -m main && |
8b43fb18 JK |
32 | base=$(git rev-parse HEAD) && |
33 | test_tick && git commit --allow-empty -m bogus && | |
34 | bogus=$(git rev-parse HEAD) && | |
35 | git cat-file commit $bogus >saved && | |
8b43fb18 JK |
36 | git reset --hard HEAD^ |
37 | ' | |
38 | ||
ff4056bb | 39 | test_expect_success 'pruning does not drop bogus object' ' |
8b43fb18 | 40 | test_when_finished "git hash-object -w -t commit saved" && |
f8058446 | 41 | create_bogus_ref && |
5b062e1f | 42 | test_must_fail git prune --expire=now && |
2ac0cbc9 | 43 | git cat-file -e $bogus |
8b43fb18 JK |
44 | ' |
45 | ||
46 | test_expect_success 'put bogus object into pack' ' | |
47 | git tag reachable $bogus && | |
48 | git repack -ad && | |
49 | git tag -d reachable && | |
2ac0cbc9 | 50 | git cat-file -e $bogus |
8b43fb18 JK |
51 | ' |
52 | ||
968f12fd | 53 | test_expect_success 'non-destructive repack bails on bogus ref' ' |
078eecbc | 54 | create_bogus_ref && |
968f12fd | 55 | test_must_fail git repack -adk |
078eecbc JK |
56 | ' |
57 | ||
968f12fd JK |
58 | test_expect_success 'GIT_REF_PARANOIA=0 overrides safety' ' |
59 | create_bogus_ref && | |
60 | GIT_REF_PARANOIA=0 git repack -adk | |
61 | ' | |
62 | ||
63 | ||
8d422993 | 64 | test_expect_success 'destructive repack keeps packed object' ' |
f8058446 | 65 | create_bogus_ref && |
5b062e1f | 66 | test_must_fail git repack -Ad --unpack-unreachable=now && |
2ac0cbc9 | 67 | git cat-file -e $bogus && |
5b062e1f | 68 | test_must_fail git repack -ad && |
2ac0cbc9 | 69 | git cat-file -e $bogus |
8b43fb18 JK |
70 | ' |
71 | ||
6d751be4 JK |
72 | test_expect_success 'destructive repack not confused by dangling symref' ' |
73 | test_when_finished "git symbolic-ref -d refs/heads/dangling" && | |
74 | git symbolic-ref refs/heads/dangling refs/heads/does-not-exist && | |
75 | git repack -ad && | |
76 | test_must_fail git cat-file -e $bogus | |
77 | ' | |
78 | ||
8b43fb18 | 79 | # We create two new objects here, "one" and "two". Our |
966b4be2 | 80 | # main branch points to "two", which is deleted, |
8b43fb18 JK |
81 | # corrupting the repository. But we'd like to make sure |
82 | # that the otherwise unreachable "one" is not pruned | |
83 | # (since it is the user's best bet for recovering | |
84 | # from the corruption). | |
85 | # | |
86 | # Note that we also point HEAD somewhere besides "two", | |
87 | # as we want to make sure we test the case where we | |
88 | # pick up the reference to "two" by iterating the refs, | |
89 | # not by resolving HEAD. | |
90 | test_expect_success 'create history with missing tip commit' ' | |
91 | test_tick && git commit --allow-empty -m one && | |
92 | recoverable=$(git rev-parse HEAD) && | |
93 | git cat-file commit $recoverable >saved && | |
94 | test_tick && git commit --allow-empty -m two && | |
95 | missing=$(git rev-parse HEAD) && | |
96 | git checkout --detach $base && | |
97 | rm .git/objects/$(echo $missing | sed "s,..,&/,") && | |
98 | test_must_fail git cat-file -e $missing | |
99 | ' | |
100 | ||
ff4056bb | 101 | test_expect_success 'pruning with a corrupted tip does not drop history' ' |
8b43fb18 | 102 | test_when_finished "git hash-object -w -t commit saved" && |
5b062e1f | 103 | test_must_fail git prune --expire=now && |
2ac0cbc9 | 104 | git cat-file -e $recoverable |
8b43fb18 JK |
105 | ' |
106 | ||
107 | test_expect_success 'pack-refs does not silently delete broken loose ref' ' | |
108 | git pack-refs --all --prune && | |
109 | echo $missing >expect && | |
966b4be2 | 110 | git rev-parse refs/heads/main >actual && |
8b43fb18 JK |
111 | test_cmp expect actual |
112 | ' | |
113 | ||
8b43fb18 | 114 | test_done |