summaryrefslogtreecommitdiffstats
path: root/t/t5504-fetch-receive-strict.sh
blob: ac4099ca8931930989eece26fa735e2f6c00bbc3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
#!/bin/sh

test_description='fetch/receive strict mode'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME

. ./test-lib.sh

test_expect_success 'setup and inject "corrupt or missing" object' '
	echo hello >greetings &&
	git add greetings &&
	git commit -m greetings &&

	S=$(git rev-parse :greetings | sed -e "s|^..|&/|") &&
	X=$(echo bye | git hash-object -w --stdin | sed -e "s|^..|&/|") &&
	echo $S >S &&
	echo $X >X &&
	cp .git/objects/$S .git/objects/$S.back &&
	mv -f .git/objects/$X .git/objects/$S &&

	test_must_fail git fsck
'

test_expect_success 'fetch without strict' '
	rm -rf dst &&
	git init dst &&
	(
		cd dst &&
		git config fetch.fsckobjects false &&
		git config transfer.fsckobjects false &&
		test_must_fail git fetch ../.git main
	)
'

test_expect_success 'fetch with !fetch.fsckobjects' '
	rm -rf dst &&
	git init dst &&
	(
		cd dst &&
		git config fetch.fsckobjects false &&
		git config transfer.fsckobjects true &&
		test_must_fail git fetch ../.git main
	)
'

test_expect_success 'fetch with fetch.fsckobjects' '
	rm -rf dst &&
	git init dst &&
	(
		cd dst &&
		git config fetch.fsckobjects true &&
		git config transfer.fsckobjects false &&
		test_must_fail git fetch ../.git main
	)
'

test_expect_success 'fetch with transfer.fsckobjects' '
	rm -rf dst &&
	git init dst &&
	(
		cd dst &&
		git config transfer.fsckobjects true &&
		test_must_fail git fetch ../.git main
	)
'

cat >exp <<EOF
To dst
!	refs/heads/main:refs/heads/test	[remote rejected] (missing necessary objects)
Done
EOF

test_expect_success 'push without strict' '
	rm -rf dst &&
	git init dst &&
	(
		cd dst &&
		git config fetch.fsckobjects false &&
		git config transfer.fsckobjects false
	) &&
	test_must_fail git push --porcelain dst main:refs/heads/test >act &&
	test_cmp exp act
'

test_expect_success 'push with !receive.fsckobjects' '
	rm -rf dst &&
	git init dst &&
	(
		cd dst &&
		git config receive.fsckobjects false &&
		git config transfer.fsckobjects true
	) &&
	test_must_fail git push --porcelain dst main:refs/heads/test >act &&
	test_cmp exp act
'

cat >exp <<EOF
To dst
!	refs/heads/main:refs/heads/test	[remote rejected] (unpacker error)
EOF

test_expect_success 'push with receive.fsckobjects' '
	rm -rf dst &&
	git init dst &&
	(
		cd dst &&
		git config receive.fsckobjects true &&
		git config transfer.fsckobjects false
	) &&
	test_must_fail git push --porcelain dst main:refs/heads/test >act &&
	test_cmp exp act
'

test_expect_success 'push with transfer.fsckobjects' '
	rm -rf dst &&
	git init dst &&
	(
		cd dst &&
		git config transfer.fsckobjects true
	) &&
	test_must_fail git push --porcelain dst main:refs/heads/test >act &&
	test_cmp exp act
'

test_expect_success 'repair the "corrupt or missing" object' '
	mv -f .git/objects/$(cat S) .git/objects/$(cat X) &&
	mv .git/objects/$(cat S).back .git/objects/$(cat S) &&
	rm -rf .git/objects/$(cat X) &&
	git fsck
'

cat >bogus-commit <<EOF
tree $EMPTY_TREE
author Bugs Bunny 1234567890 +0000
committer Bugs Bunny <bugs@bun.ni> 1234567890 +0000

This commit object intentionally broken
EOF

test_expect_success 'setup bogus commit' '
	commit="$(git hash-object -t commit -w --stdin <bogus-commit)"
'

test_expect_success 'fsck with no skipList input' '
	test_must_fail git fsck 2>err &&
	test_i18ngrep "missingEmail" err
'

test_expect_success 'setup sorted and unsorted skipLists' '
	cat >SKIP.unsorted <<-EOF &&
	$(test_oid 004)
	$(test_oid 002)
	$commit
	$(test_oid 001)
	$(test_oid 003)
	EOF
	sort SKIP.unsorted >SKIP.sorted
'

test_expect_success 'fsck with sorted skipList' '
	git -c fsck.skipList=SKIP.sorted fsck
'

test_expect_success 'fsck with unsorted skipList' '
	git -c fsck.skipList=SKIP.unsorted fsck
'

test_expect_success 'fsck with invalid or bogus skipList input' '
	git -c fsck.skipList=/dev/null -c fsck.missingEmail=ignore fsck &&
	test_must_fail git -c fsck.skipList=does-not-exist -c fsck.missingEmail=ignore fsck 2>err &&
	test_i18ngrep "could not open.*: does-not-exist" err &&
	test_must_fail git -c fsck.skipList=.git/config -c fsck.missingEmail=ignore fsck 2>err &&
	test_i18ngrep "invalid object name: \[core\]" err
'

test_expect_success 'fsck with other accepted skipList input (comments & empty lines)' '
	cat >SKIP.with-comment <<-EOF &&
	# Some bad commit
	$(test_oid 001)
	EOF
	test_must_fail git -c fsck.skipList=SKIP.with-comment fsck 2>err-with-comment &&
	test_i18ngrep "missingEmail" err-with-comment &&
	cat >SKIP.with-empty-line <<-EOF &&
	$(test_oid 001)

	$(test_oid 002)
	EOF
	test_must_fail git -c fsck.skipList=SKIP.with-empty-line fsck 2>err-with-empty-line &&
	test_i18ngrep "missingEmail" err-with-empty-line
'

test_expect_success 'fsck no garbage output from comments & empty lines errors' '
	test_line_count = 1 err-with-comment &&
	test_line_count = 1 err-with-empty-line
'

test_expect_success 'fsck with invalid abbreviated skipList input' '
	echo $commit | test_copy_bytes 20 >SKIP.abbreviated &&
	test_must_fail git -c fsck.skipList=SKIP.abbreviated fsck 2>err-abbreviated &&
	test_i18ngrep "^fatal: invalid object name: " err-abbreviated
'

test_expect_success 'fsck with exhaustive accepted skipList input (various types of comments etc.)' '
	>SKIP.exhaustive &&
	echo "# A commented line" >>SKIP.exhaustive &&
	echo "" >>SKIP.exhaustive &&
	echo " " >>SKIP.exhaustive &&
	echo " # Comment after whitespace" >>SKIP.exhaustive &&
	echo "$commit # Our bad commit (with leading whitespace and trailing comment)" >>SKIP.exhaustive &&
	echo "# Some bad commit (leading whitespace)" >>SKIP.exhaustive &&
	echo "  $(test_oid 001)" >>SKIP.exhaustive &&
	git -c fsck.skipList=SKIP.exhaustive fsck 2>err &&
	test_must_be_empty err
'

test_expect_success 'push with receive.fsck.skipList' '
	git push . $commit:refs/heads/bogus &&
	rm -rf dst &&
	git init dst &&
	git --git-dir=dst/.git config receive.fsckObjects true &&
	test_must_fail git push --porcelain dst bogus &&
	echo $commit >dst/.git/SKIP &&

	# receive.fsck.* does not fall back on fsck.*
	git --git-dir=dst/.git config fsck.skipList SKIP &&
	test_must_fail git push --porcelain dst bogus &&

	# Invalid and/or bogus skipList input
	git --git-dir=dst/.git config receive.fsck.skipList /dev/null &&
	test_must_fail git push --porcelain dst bogus &&
	git --git-dir=dst/.git config receive.fsck.skipList does-not-exist &&
	test_must_fail git push --porcelain dst bogus 2>err &&
	test_i18ngrep "could not open.*: does-not-exist" err &&
	git --git-dir=dst/.git config receive.fsck.skipList config &&
	test_must_fail git push --porcelain dst bogus 2>err &&
	test_i18ngrep "invalid object name: \[core\]" err &&

	git --git-dir=dst/.git config receive.fsck.skipList SKIP &&
	git push --porcelain dst bogus
'

test_expect_success 'fetch with fetch.fsck.skipList' '
	refspec=refs/heads/bogus:refs/heads/bogus &&
	git push . $commit:refs/heads/bogus &&
	rm -rf dst &&
	git init dst &&
	git --git-dir=dst/.git config fetch.fsckObjects true &&
	test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec &&
	git --git-dir=dst/.git config fetch.fsck.skipList /dev/null &&
	test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec &&
	echo $commit >dst/.git/SKIP &&

	# fetch.fsck.* does not fall back on fsck.*
	git --git-dir=dst/.git config fsck.skipList dst/.git/SKIP &&
	test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec &&

	# Invalid and/or bogus skipList input
	git --git-dir=dst/.git config fetch.fsck.skipList /dev/null &&
	test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec &&
	git --git-dir=dst/.git config fetch.fsck.skipList does-not-exist &&
	test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec 2>err &&
	test_i18ngrep "could not open.*: does-not-exist" err &&
	git --git-dir=dst/.git config fetch.fsck.skipList dst/.git/config &&
	test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec 2>err &&
	test_i18ngrep "invalid object name: \[core\]" err &&

	git --git-dir=dst/.git config fetch.fsck.skipList dst/.git/SKIP &&
	git --git-dir=dst/.git fetch "file://$(pwd)" $refspec
'

test_expect_success 'fsck.<unknownmsg-id> dies' '
	test_must_fail git -c fsck.whatEver=ignore fsck 2>err &&
	test_i18ngrep "Unhandled message id: whatever" err
'

test_expect_success 'push with receive.fsck.missingEmail=warn' '
	git push . $commit:refs/heads/bogus &&
	rm -rf dst &&
	git init dst &&
	git --git-dir=dst/.git config receive.fsckobjects true &&
	test_must_fail git push --porcelain dst bogus &&

	# receive.fsck.<msg-id> does not fall back on fsck.<msg-id>
	git --git-dir=dst/.git config fsck.missingEmail warn &&
	test_must_fail git push --porcelain dst bogus &&

	# receive.fsck.<unknownmsg-id> warns
	git --git-dir=dst/.git config \
		receive.fsck.whatEver error &&

	git --git-dir=dst/.git config \
		receive.fsck.missingEmail warn &&
	git push --porcelain dst bogus >act 2>&1 &&
	grep "missingEmail" act &&
	test_i18ngrep "skipping unknown msg id.*whatever" act &&
	git --git-dir=dst/.git branch -D bogus &&
	git --git-dir=dst/.git config --add \
		receive.fsck.missingEmail ignore &&
	git push --porcelain dst bogus >act 2>&1 &&
	! grep "missingEmail" act
'

test_expect_success 'fetch with fetch.fsck.missingEmail=warn' '
	refspec=refs/heads/bogus:refs/heads/bogus &&
	git push . $commit:refs/heads/bogus &&
	rm -rf dst &&
	git init dst &&
	git --git-dir=dst/.git config fetch.fsckobjects true &&
	test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec &&

	# fetch.fsck.<msg-id> does not fall back on fsck.<msg-id>
	git --git-dir=dst/.git config fsck.missingEmail warn &&
	test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec &&

	# receive.fsck.<unknownmsg-id> warns
	git --git-dir=dst/.git config \
		fetch.fsck.whatEver error &&

	git --git-dir=dst/.git config \
		fetch.fsck.missingEmail warn &&
	git --git-dir=dst/.git fetch "file://$(pwd)" $refspec >act 2>&1 &&
	grep "missingEmail" act &&
	test_i18ngrep "Skipping unknown msg id.*whatever" act &&
	rm -rf dst &&
	git init dst &&
	git --git-dir=dst/.git config fetch.fsckobjects true &&
	git --git-dir=dst/.git config \
		fetch.fsck.missingEmail ignore &&
	git --git-dir=dst/.git fetch "file://$(pwd)" $refspec >act 2>&1 &&
	! grep "missingEmail" act
'

test_expect_success \
	'receive.fsck.unterminatedHeader=warn triggers error' '
	rm -rf dst &&
	git init dst &&
	git --git-dir=dst/.git config receive.fsckobjects true &&
	git --git-dir=dst/.git config \
		receive.fsck.unterminatedheader warn &&
	test_must_fail git push --porcelain dst HEAD >act 2>&1 &&
	grep "Cannot demote unterminatedheader" act
'

test_expect_success \
	'fetch.fsck.unterminatedHeader=warn triggers error' '
	rm -rf dst &&
	git init dst &&
	git --git-dir=dst/.git config fetch.fsckobjects true &&
	git --git-dir=dst/.git config \
		fetch.fsck.unterminatedheader warn &&
	test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" HEAD &&
	grep "Cannot demote unterminatedheader" act
'

test_expect_success 'badFilemode is not a strict error' '
	git init --bare badmode.git &&
	tree=$(
		cd badmode.git &&
		blob=$(echo blob | git hash-object -w --stdin | hex2oct) &&
		printf "123456 foo\0${blob}" |
		git hash-object -t tree --stdin -w --literally
	) &&

	rm -rf dst.git &&
	git init --bare dst.git &&
	git -C dst.git config transfer.fsckObjects true &&

	git -C badmode.git push ../dst.git $tree:refs/tags/tree 2>err &&
	grep "$tree: badFilemode" err
'

test_done