sparse-index: loose integration with cache_tree_verify()
[git] / t / t5504-fetch-receive-strict.sh
1 #!/bin/sh
2
3 test_description='fetch/receive strict mode'
4 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
5 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
6
7 . ./test-lib.sh
8
9 test_expect_success 'setup and inject "corrupt or missing" object' '
10         echo hello >greetings &&
11         git add greetings &&
12         git commit -m greetings &&
13
14         S=$(git rev-parse :greetings | sed -e "s|^..|&/|") &&
15         X=$(echo bye | git hash-object -w --stdin | sed -e "s|^..|&/|") &&
16         echo $S >S &&
17         echo $X >X &&
18         cp .git/objects/$S .git/objects/$S.back &&
19         mv -f .git/objects/$X .git/objects/$S &&
20
21         test_must_fail git fsck
22 '
23
24 test_expect_success 'fetch without strict' '
25         rm -rf dst &&
26         git init dst &&
27         (
28                 cd dst &&
29                 git config fetch.fsckobjects false &&
30                 git config transfer.fsckobjects false &&
31                 test_must_fail git fetch ../.git main
32         )
33 '
34
35 test_expect_success 'fetch with !fetch.fsckobjects' '
36         rm -rf dst &&
37         git init dst &&
38         (
39                 cd dst &&
40                 git config fetch.fsckobjects false &&
41                 git config transfer.fsckobjects true &&
42                 test_must_fail git fetch ../.git main
43         )
44 '
45
46 test_expect_success 'fetch with fetch.fsckobjects' '
47         rm -rf dst &&
48         git init dst &&
49         (
50                 cd dst &&
51                 git config fetch.fsckobjects true &&
52                 git config transfer.fsckobjects false &&
53                 test_must_fail git fetch ../.git main
54         )
55 '
56
57 test_expect_success 'fetch with transfer.fsckobjects' '
58         rm -rf dst &&
59         git init dst &&
60         (
61                 cd dst &&
62                 git config transfer.fsckobjects true &&
63                 test_must_fail git fetch ../.git main
64         )
65 '
66
67 cat >exp <<EOF
68 To dst
69 !       refs/heads/main:refs/heads/test [remote rejected] (missing necessary objects)
70 Done
71 EOF
72
73 test_expect_success 'push without strict' '
74         rm -rf dst &&
75         git init dst &&
76         (
77                 cd dst &&
78                 git config fetch.fsckobjects false &&
79                 git config transfer.fsckobjects false
80         ) &&
81         test_must_fail git push --porcelain dst main:refs/heads/test >act &&
82         test_cmp exp act
83 '
84
85 test_expect_success 'push with !receive.fsckobjects' '
86         rm -rf dst &&
87         git init dst &&
88         (
89                 cd dst &&
90                 git config receive.fsckobjects false &&
91                 git config transfer.fsckobjects true
92         ) &&
93         test_must_fail git push --porcelain dst main:refs/heads/test >act &&
94         test_cmp exp act
95 '
96
97 cat >exp <<EOF
98 To dst
99 !       refs/heads/main:refs/heads/test [remote rejected] (unpacker error)
100 EOF
101
102 test_expect_success 'push with receive.fsckobjects' '
103         rm -rf dst &&
104         git init dst &&
105         (
106                 cd dst &&
107                 git config receive.fsckobjects true &&
108                 git config transfer.fsckobjects false
109         ) &&
110         test_must_fail git push --porcelain dst main:refs/heads/test >act &&
111         test_cmp exp act
112 '
113
114 test_expect_success 'push with transfer.fsckobjects' '
115         rm -rf dst &&
116         git init dst &&
117         (
118                 cd dst &&
119                 git config transfer.fsckobjects true
120         ) &&
121         test_must_fail git push --porcelain dst main:refs/heads/test >act &&
122         test_cmp exp act
123 '
124
125 test_expect_success 'repair the "corrupt or missing" object' '
126         mv -f .git/objects/$(cat S) .git/objects/$(cat X) &&
127         mv .git/objects/$(cat S).back .git/objects/$(cat S) &&
128         rm -rf .git/objects/$(cat X) &&
129         git fsck
130 '
131
132 cat >bogus-commit <<EOF
133 tree $EMPTY_TREE
134 author Bugs Bunny 1234567890 +0000
135 committer Bugs Bunny <bugs@bun.ni> 1234567890 +0000
136
137 This commit object intentionally broken
138 EOF
139
140 test_expect_success 'setup bogus commit' '
141         commit="$(git hash-object -t commit -w --stdin <bogus-commit)"
142 '
143
144 test_expect_success 'fsck with no skipList input' '
145         test_must_fail git fsck 2>err &&
146         test_i18ngrep "missingEmail" err
147 '
148
149 test_expect_success 'setup sorted and unsorted skipLists' '
150         cat >SKIP.unsorted <<-EOF &&
151         $(test_oid 004)
152         $(test_oid 002)
153         $commit
154         $(test_oid 001)
155         $(test_oid 003)
156         EOF
157         sort SKIP.unsorted >SKIP.sorted
158 '
159
160 test_expect_success 'fsck with sorted skipList' '
161         git -c fsck.skipList=SKIP.sorted fsck
162 '
163
164 test_expect_success 'fsck with unsorted skipList' '
165         git -c fsck.skipList=SKIP.unsorted fsck
166 '
167
168 test_expect_success 'fsck with invalid or bogus skipList input' '
169         git -c fsck.skipList=/dev/null -c fsck.missingEmail=ignore fsck &&
170         test_must_fail git -c fsck.skipList=does-not-exist -c fsck.missingEmail=ignore fsck 2>err &&
171         test_i18ngrep "could not open.*: does-not-exist" err &&
172         test_must_fail git -c fsck.skipList=.git/config -c fsck.missingEmail=ignore fsck 2>err &&
173         test_i18ngrep "invalid object name: \[core\]" err
174 '
175
176 test_expect_success 'fsck with other accepted skipList input (comments & empty lines)' '
177         cat >SKIP.with-comment <<-EOF &&
178         # Some bad commit
179         $(test_oid 001)
180         EOF
181         test_must_fail git -c fsck.skipList=SKIP.with-comment fsck 2>err-with-comment &&
182         test_i18ngrep "missingEmail" err-with-comment &&
183         cat >SKIP.with-empty-line <<-EOF &&
184         $(test_oid 001)
185
186         $(test_oid 002)
187         EOF
188         test_must_fail git -c fsck.skipList=SKIP.with-empty-line fsck 2>err-with-empty-line &&
189         test_i18ngrep "missingEmail" err-with-empty-line
190 '
191
192 test_expect_success 'fsck no garbage output from comments & empty lines errors' '
193         test_line_count = 1 err-with-comment &&
194         test_line_count = 1 err-with-empty-line
195 '
196
197 test_expect_success 'fsck with invalid abbreviated skipList input' '
198         echo $commit | test_copy_bytes 20 >SKIP.abbreviated &&
199         test_must_fail git -c fsck.skipList=SKIP.abbreviated fsck 2>err-abbreviated &&
200         test_i18ngrep "^fatal: invalid object name: " err-abbreviated
201 '
202
203 test_expect_success 'fsck with exhaustive accepted skipList input (various types of comments etc.)' '
204         >SKIP.exhaustive &&
205         echo "# A commented line" >>SKIP.exhaustive &&
206         echo "" >>SKIP.exhaustive &&
207         echo " " >>SKIP.exhaustive &&
208         echo " # Comment after whitespace" >>SKIP.exhaustive &&
209         echo "$commit # Our bad commit (with leading whitespace and trailing comment)" >>SKIP.exhaustive &&
210         echo "# Some bad commit (leading whitespace)" >>SKIP.exhaustive &&
211         echo "  $(test_oid 001)" >>SKIP.exhaustive &&
212         git -c fsck.skipList=SKIP.exhaustive fsck 2>err &&
213         test_must_be_empty err
214 '
215
216 test_expect_success 'push with receive.fsck.skipList' '
217         git push . $commit:refs/heads/bogus &&
218         rm -rf dst &&
219         git init dst &&
220         git --git-dir=dst/.git config receive.fsckObjects true &&
221         test_must_fail git push --porcelain dst bogus &&
222         echo $commit >dst/.git/SKIP &&
223
224         # receive.fsck.* does not fall back on fsck.*
225         git --git-dir=dst/.git config fsck.skipList SKIP &&
226         test_must_fail git push --porcelain dst bogus &&
227
228         # Invalid and/or bogus skipList input
229         git --git-dir=dst/.git config receive.fsck.skipList /dev/null &&
230         test_must_fail git push --porcelain dst bogus &&
231         git --git-dir=dst/.git config receive.fsck.skipList does-not-exist &&
232         test_must_fail git push --porcelain dst bogus 2>err &&
233         test_i18ngrep "could not open.*: does-not-exist" err &&
234         git --git-dir=dst/.git config receive.fsck.skipList config &&
235         test_must_fail git push --porcelain dst bogus 2>err &&
236         test_i18ngrep "invalid object name: \[core\]" err &&
237
238         git --git-dir=dst/.git config receive.fsck.skipList SKIP &&
239         git push --porcelain dst bogus
240 '
241
242 test_expect_success 'fetch with fetch.fsck.skipList' '
243         refspec=refs/heads/bogus:refs/heads/bogus &&
244         git push . $commit:refs/heads/bogus &&
245         rm -rf dst &&
246         git init dst &&
247         git --git-dir=dst/.git config fetch.fsckObjects true &&
248         test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec &&
249         git --git-dir=dst/.git config fetch.fsck.skipList /dev/null &&
250         test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec &&
251         echo $commit >dst/.git/SKIP &&
252
253         # fetch.fsck.* does not fall back on fsck.*
254         git --git-dir=dst/.git config fsck.skipList dst/.git/SKIP &&
255         test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec &&
256
257         # Invalid and/or bogus skipList input
258         git --git-dir=dst/.git config fetch.fsck.skipList /dev/null &&
259         test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec &&
260         git --git-dir=dst/.git config fetch.fsck.skipList does-not-exist &&
261         test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec 2>err &&
262         test_i18ngrep "could not open.*: does-not-exist" err &&
263         git --git-dir=dst/.git config fetch.fsck.skipList dst/.git/config &&
264         test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec 2>err &&
265         test_i18ngrep "invalid object name: \[core\]" err &&
266
267         git --git-dir=dst/.git config fetch.fsck.skipList dst/.git/SKIP &&
268         git --git-dir=dst/.git fetch "file://$(pwd)" $refspec
269 '
270
271 test_expect_success 'fsck.<unknownmsg-id> dies' '
272         test_must_fail git -c fsck.whatEver=ignore fsck 2>err &&
273         test_i18ngrep "Unhandled message id: whatever" err
274 '
275
276 test_expect_success 'push with receive.fsck.missingEmail=warn' '
277         git push . $commit:refs/heads/bogus &&
278         rm -rf dst &&
279         git init dst &&
280         git --git-dir=dst/.git config receive.fsckobjects true &&
281         test_must_fail git push --porcelain dst bogus &&
282
283         # receive.fsck.<msg-id> does not fall back on fsck.<msg-id>
284         git --git-dir=dst/.git config fsck.missingEmail warn &&
285         test_must_fail git push --porcelain dst bogus &&
286
287         # receive.fsck.<unknownmsg-id> warns
288         git --git-dir=dst/.git config \
289                 receive.fsck.whatEver error &&
290
291         git --git-dir=dst/.git config \
292                 receive.fsck.missingEmail warn &&
293         git push --porcelain dst bogus >act 2>&1 &&
294         grep "missingEmail" act &&
295         test_i18ngrep "Skipping unknown msg id.*whatever" act &&
296         git --git-dir=dst/.git branch -D bogus &&
297         git --git-dir=dst/.git config --add \
298                 receive.fsck.missingEmail ignore &&
299         git push --porcelain dst bogus >act 2>&1 &&
300         ! grep "missingEmail" act
301 '
302
303 test_expect_success 'fetch with fetch.fsck.missingEmail=warn' '
304         refspec=refs/heads/bogus:refs/heads/bogus &&
305         git push . $commit:refs/heads/bogus &&
306         rm -rf dst &&
307         git init dst &&
308         git --git-dir=dst/.git config fetch.fsckobjects true &&
309         test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec &&
310
311         # fetch.fsck.<msg-id> does not fall back on fsck.<msg-id>
312         git --git-dir=dst/.git config fsck.missingEmail warn &&
313         test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec &&
314
315         # receive.fsck.<unknownmsg-id> warns
316         git --git-dir=dst/.git config \
317                 fetch.fsck.whatEver error &&
318
319         git --git-dir=dst/.git config \
320                 fetch.fsck.missingEmail warn &&
321         git --git-dir=dst/.git fetch "file://$(pwd)" $refspec >act 2>&1 &&
322         grep "missingEmail" act &&
323         test_i18ngrep "Skipping unknown msg id.*whatever" act &&
324         rm -rf dst &&
325         git init dst &&
326         git --git-dir=dst/.git config fetch.fsckobjects true &&
327         git --git-dir=dst/.git config \
328                 fetch.fsck.missingEmail ignore &&
329         git --git-dir=dst/.git fetch "file://$(pwd)" $refspec >act 2>&1 &&
330         ! grep "missingEmail" act
331 '
332
333 test_expect_success \
334         'receive.fsck.unterminatedHeader=warn triggers error' '
335         rm -rf dst &&
336         git init dst &&
337         git --git-dir=dst/.git config receive.fsckobjects true &&
338         git --git-dir=dst/.git config \
339                 receive.fsck.unterminatedheader warn &&
340         test_must_fail git push --porcelain dst HEAD >act 2>&1 &&
341         grep "Cannot demote unterminatedheader" act
342 '
343
344 test_expect_success \
345         'fetch.fsck.unterminatedHeader=warn triggers error' '
346         rm -rf dst &&
347         git init dst &&
348         git --git-dir=dst/.git config fetch.fsckobjects true &&
349         git --git-dir=dst/.git config \
350                 fetch.fsck.unterminatedheader warn &&
351         test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" HEAD &&
352         grep "Cannot demote unterminatedheader" act
353 '
354
355 test_done