Raw
1 #!/bin/sh
2
3 test_description='see how we handle various forms of corruption'
4
5 . ./test-lib.sh
6
7 # convert "1234abcd" to ".git/objects/12/34abcd"
8 obj_to_file() {
9 echo "$(git rev-parse --git-dir)/objects/$(git rev-parse "$1" | sed 's,..,&/,')"
10 }
11
12 # Convert byte at offset "$2" of object "$1" into '\0'
13 corrupt_byte() {
14 obj_file=$(obj_to_file "$1") &&
15 chmod +w "$obj_file" &&
16 printf '\0' | dd of="$obj_file" bs=1 seek="$2" conv=notrunc
17 }
18
19 test_expect_success 'setup corrupt repo' '
20 git init bit-error &&
21 (
22 cd bit-error &&
23 test_commit content &&
24 corrupt_byte HEAD:content.t 10
25 ) &&
26 git init no-bit-error &&
27 (
28 # distinct commit from bit-error, but containing a
29 # non-corrupted version of the same blob
30 cd no-bit-error &&
31 test_tick &&
32 test_commit content
33 )
34 '
35
36 test_expect_success 'setup repo with missing object' '
37 git init missing &&
38 (
39 cd missing &&
40 test_commit content &&
41 rm -f "$(obj_to_file HEAD:content.t)"
42 )
43 '
44
45 test_expect_success 'setup repo with misnamed object' '
46 git init misnamed &&
47 (
48 cd misnamed &&
49 test_commit content &&
50 good=$(obj_to_file HEAD:content.t) &&
51 blob=$(echo corrupt | git hash-object -w --stdin) &&
52 bad=$(obj_to_file $blob) &&
53 rm -f "$good" &&
54 mv "$bad" "$good"
55 )
56 '
57
58 test_expect_success 'streaming a corrupt blob fails' '
59 (
60 cd bit-error &&
61 test_must_fail git cat-file blob HEAD:content.t
62 )
63 '
64
65 test_expect_success 'getting type of a corrupt blob fails' '
66 (
67 cd bit-error &&
68 test_must_fail git cat-file -s HEAD:content.t
69 )
70 '
71
72 test_expect_success 'read-tree -u detects bit-errors in blobs' '
73 (
74 cd bit-error &&
75 rm -f content.t &&
76 test_must_fail git read-tree --reset -u HEAD
77 )
78 '
79
80 test_expect_success 'read-tree -u detects missing objects' '
81 (
82 cd missing &&
83 rm -f content.t &&
84 test_must_fail git read-tree --reset -u HEAD
85 )
86 '
87
88 # We use --bare to make sure that the transport detects it, not the checkout
89 # phase.
90 test_expect_success 'clone --no-local --bare detects corruption' '
91 test_must_fail git clone --no-local --bare bit-error corrupt-transport
92 '
93
94 test_expect_success 'clone --no-local --bare detects missing object' '
95 test_must_fail git clone --no-local --bare missing missing-transport
96 '
97
98 test_expect_success 'clone --no-local --bare detects misnamed object' '
99 test_must_fail git clone --no-local --bare misnamed misnamed-transport
100 '
101
102 # We do not expect --local to detect corruption at the transport layer,
103 # so we are really checking the checkout() code path.
104 test_expect_success 'clone --local detects corruption' '
105 test_must_fail git clone --local bit-error corrupt-checkout
106 '
107
108 test_expect_success 'error detected during checkout leaves repo intact' '
109 test_path_is_dir corrupt-checkout/.git
110 '
111
112 test_expect_success 'clone --local detects missing objects' '
113 test_must_fail git clone --local missing missing-checkout
114 '
115
116 test_expect_failure 'clone --local detects misnamed objects' '
117 test_must_fail git clone --local misnamed misnamed-checkout
118 '
119
120 test_expect_success 'fetch into corrupted repo with index-pack' '
121 cp -R bit-error bit-error-cp &&
122 test_when_finished "rm -rf bit-error-cp" &&
123 (
124 cd bit-error-cp &&
125 test_must_fail git -c transfer.unpackLimit=1 \
126 fetch ../no-bit-error 2>stderr &&
127 test_grep ! -i collision stderr
128 )
129 '
130
131 test_expect_success 'internal tree objects are not "missing"' '
132 git init missing-empty &&
133 (
134 cd missing-empty &&
135 empty_tree=$(git hash-object -t tree /dev/null) &&
136 commit=$(echo foo | git commit-tree $empty_tree) &&
137 git rev-list --objects $commit
138 )
139 '
140
141 test_expect_success 'partial clone of corrupted repository' '
142 test_config -C misnamed uploadpack.allowFilter true &&
143 git clone --no-local --no-checkout --filter=blob:none \
144 misnamed corrupt-partial && \
145 test_must_fail git -C corrupt-partial checkout --force
146 '
147
148 test_done