]> git.ipfire.org Git - thirdparty/git.git/blob - t/t5312-prune-corruption.sh
t5312: prepare for reftable
[thirdparty/git.git] / t / t5312-prune-corruption.sh
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.
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.
13 '
14 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
15 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
16
17 . ./test-lib.sh
18
19 test_expect_success 'disable reflogs' '
20 git config core.logallrefupdates false &&
21 git reflog expire --expire=all --all
22 '
23
24 create_bogus_ref () {
25 test-tool ref-store main update-ref msg "refs/heads/bogus..name" $bogus $ZERO_OID REF_SKIP_REFNAME_VERIFICATION &&
26 test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/bogus..name"
27 }
28
29 test_expect_success 'create history reachable only from a bogus-named ref' '
30 test_tick && git commit --allow-empty -m main &&
31 base=$(git rev-parse HEAD) &&
32 test_tick && git commit --allow-empty -m bogus &&
33 bogus=$(git rev-parse HEAD) &&
34 git cat-file commit $bogus >saved &&
35 git reset --hard HEAD^
36 '
37
38 test_expect_success 'pruning does not drop bogus object' '
39 test_when_finished "git hash-object -w -t commit saved" &&
40 create_bogus_ref &&
41 test_must_fail git prune --expire=now &&
42 git cat-file -e $bogus
43 '
44
45 test_expect_success 'put bogus object into pack' '
46 git tag reachable $bogus &&
47 git repack -ad &&
48 git tag -d reachable &&
49 git cat-file -e $bogus
50 '
51
52 test_expect_success 'non-destructive repack bails on bogus ref' '
53 create_bogus_ref &&
54 test_must_fail git repack -adk
55 '
56
57 test_expect_success 'GIT_REF_PARANOIA=0 overrides safety' '
58 create_bogus_ref &&
59 GIT_REF_PARANOIA=0 git repack -adk
60 '
61
62
63 test_expect_success 'destructive repack keeps packed object' '
64 create_bogus_ref &&
65 test_must_fail git repack -Ad --unpack-unreachable=now &&
66 git cat-file -e $bogus &&
67 test_must_fail git repack -ad &&
68 git cat-file -e $bogus
69 '
70
71 test_expect_success 'destructive repack not confused by dangling symref' '
72 test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
73 git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
74 git repack -ad &&
75 test_must_fail git cat-file -e $bogus
76 '
77
78 # We create two new objects here, "one" and "two". Our
79 # main branch points to "two", which is deleted,
80 # corrupting the repository. But we'd like to make sure
81 # that the otherwise unreachable "one" is not pruned
82 # (since it is the user's best bet for recovering
83 # from the corruption).
84 #
85 # Note that we also point HEAD somewhere besides "two",
86 # as we want to make sure we test the case where we
87 # pick up the reference to "two" by iterating the refs,
88 # not by resolving HEAD.
89 test_expect_success 'create history with missing tip commit' '
90 test_tick && git commit --allow-empty -m one &&
91 recoverable=$(git rev-parse HEAD) &&
92 git cat-file commit $recoverable >saved &&
93 test_tick && git commit --allow-empty -m two &&
94 missing=$(git rev-parse HEAD) &&
95 git checkout --detach $base &&
96 rm .git/objects/$(echo $missing | sed "s,..,&/,") &&
97 test_must_fail git cat-file -e $missing
98 '
99
100 test_expect_success 'pruning with a corrupted tip does not drop history' '
101 test_when_finished "git hash-object -w -t commit saved" &&
102 test_must_fail git prune --expire=now &&
103 git cat-file -e $recoverable
104 '
105
106 test_expect_success 'pack-refs does not silently delete broken loose ref' '
107 git pack-refs --all --prune &&
108 echo $missing >expect &&
109 git rev-parse refs/heads/main >actual &&
110 test_cmp expect actual
111 '
112
113 # we do not want to count on running pack-refs to
114 # actually pack it, as it is perfectly reasonable to
115 # skip processing a broken ref
116 test_expect_success REFFILES 'create packed-refs file with broken ref' '
117 rm -f .git/refs/heads/main &&
118 cat >.git/packed-refs <<-EOF &&
119 $missing refs/heads/main
120 $recoverable refs/heads/other
121 EOF
122 echo $missing >expect &&
123 git rev-parse refs/heads/main >actual &&
124 test_cmp expect actual
125 '
126
127 test_expect_success REFFILES 'pack-refs does not silently delete broken packed ref' '
128 git pack-refs --all --prune &&
129 git rev-parse refs/heads/main >actual &&
130 test_cmp expect actual
131 '
132
133 test_expect_success REFFILES 'pack-refs does not drop broken refs during deletion' '
134 git update-ref -d refs/heads/other &&
135 git rev-parse refs/heads/main >actual &&
136 test_cmp expect actual
137 '
138
139 test_done