]> git.ipfire.org Git - thirdparty/git.git/blame - t/t0021-conversion.sh
Merge branch 'zh/difftool-skip-to'
[thirdparty/git.git] / t / t0021-conversion.sh
CommitLineData
3fed15f5
JH
1#!/bin/sh
2
3test_description='blob conversion via gitattributes'
4
06d53148 5GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
334afbc7
JS
6export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
7
3fed15f5
JH
8. ./test-lib.sh
9
71dd5047 10TEST_ROOT="$PWD"
30030a36 11PATH=$TEST_ROOT:$PATH
edcc8581 12
cbb6707b 13write_script <<\EOF "$TEST_ROOT/rot13.sh"
7339eb08
JK
14tr \
15 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' \
16 'nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM'
aa4ed402 17EOF
edcc8581 18
f272696a
JK
19write_script rot13-filter.pl "$PERL_PATH" \
20 <"$TEST_DIRECTORY"/t0021/rot13-filter.pl
edcc8581
LS
21
22generate_random_characters () {
23 LEN=$1
24 NAME=$2
c680668d 25 test-tool genrandom some-seed $LEN |
edcc8581
LS
26 perl -pe "s/./chr((ord($&) % 26) + ord('a'))/sge" >"$TEST_ROOT/$NAME"
27}
28
edcc8581 29filter_git () {
e1ec4721 30 rm -f *.log &&
a0d8b60d 31 git "$@"
edcc8581
LS
32}
33
34# Compare two files and ensure that `clean` and `smudge` respectively are
35# called at least once if specified in the `expect` file. The actual
36# invocation count is not relevant because their number can vary.
6eda9ac9 37# c.f. https://lore.kernel.org/git/xmqqshv18i8i.fsf@gitster.mtv.corp.google.com/
edcc8581
LS
38test_cmp_count () {
39 expect=$1
40 actual=$2
41 for FILE in "$expect" "$actual"
42 do
038212c4 43 sort "$FILE" | uniq -c |
58ec9cb3 44 sed -e "s/^ *[0-9][0-9]*[ ]*IN: /x IN: /" >"$FILE.tmp"
edcc8581 45 done &&
58ec9cb3
LS
46 test_cmp "$expect.tmp" "$actual.tmp" &&
47 rm "$expect.tmp" "$actual.tmp"
edcc8581
LS
48}
49
50# Compare two files but exclude all `clean` invocations because Git can
51# call `clean` zero or more times.
6eda9ac9 52# c.f. https://lore.kernel.org/git/xmqqshv18i8i.fsf@gitster.mtv.corp.google.com/
edcc8581
LS
53test_cmp_exclude_clean () {
54 expect=$1
55 actual=$2
56 for FILE in "$expect" "$actual"
57 do
58ec9cb3 58 grep -v "IN: clean" "$FILE" >"$FILE.tmp"
edcc8581 59 done &&
58ec9cb3
LS
60 test_cmp "$expect.tmp" "$actual.tmp" &&
61 rm "$expect.tmp" "$actual.tmp"
edcc8581
LS
62}
63
64# Check that the contents of two files are equal and that their rot13 version
65# is equal to the committed content.
66test_cmp_committed_rot13 () {
67 test_cmp "$1" "$2" &&
30030a36 68 rot13.sh <"$1" >expected &&
edcc8581
LS
69 git cat-file blob :"$2" >actual &&
70 test_cmp expected actual
71}
aa4ed402 72
3fed15f5 73test_expect_success setup '
aa4ed402
JH
74 git config filter.rot13.smudge ./rot13.sh &&
75 git config filter.rot13.clean ./rot13.sh &&
76
3fed15f5 77 {
aa4ed402 78 echo "*.t filter=rot13"
3fed15f5
JH
79 echo "*.i ident"
80 } >.gitattributes &&
81
82 {
83 echo a b c d e f g h i j k l m
84 echo n o p q r s t u v w x y z
af9b54bb 85 echo '\''$Id$'\''
3fed15f5
JH
86 } >test &&
87 cat test >test.t &&
88 cat test >test.o &&
89 cat test >test.i &&
90 git add test test.t test.i &&
91 rm -f test test.t test.i &&
edcc8581
LS
92 git checkout -- test test.t test.i &&
93
94 echo "content-test2" >test2.o &&
c6b0831c 95 echo "content-test3 - filename with special characters" >"test3 '\''sq'\'',\$x=.o"
3fed15f5
JH
96'
97
af9b54bb 98script='s/^\$Id: \([0-9a-f]*\) \$/\1/p'
3fed15f5
JH
99
100test_expect_success check '
101
ed549703
LS
102 test_cmp test.o test &&
103 test_cmp test.o test.t &&
3fed15f5
JH
104
105 # ident should be stripped in the repository
106 git diff --raw --exit-code :test :test.i &&
107 id=$(git rev-parse --verify :test) &&
108 embedded=$(sed -ne "$script" test.i) &&
a0ae35ae
JS
109 test "z$id" = "z$embedded" &&
110
ed549703 111 git cat-file blob :test.t >test.r &&
a0ae35ae 112
ed549703
LS
113 ./rot13.sh <test.o >test.t &&
114 test_cmp test.r test.t
3fed15f5
JH
115'
116
dfab71cb
AP
117# If an expanded ident ever gets into the repository, we want to make sure that
118# it is collapsed before being expanded again on checkout
119test_expect_success expanded_in_repo '
120 {
121 echo "File with expanded keywords"
122 echo "\$Id\$"
123 echo "\$Id:\$"
124 echo "\$Id: 0000000000000000000000000000000000000000 \$"
125 echo "\$Id: NoSpaceAtEnd\$"
126 echo "\$Id:NoSpaceAtFront \$"
127 echo "\$Id:NoSpaceAtEitherEnd\$"
128 echo "\$Id: NoTerminatingSymbol"
a9f3049f 129 echo "\$Id: Foreign Commit With Spaces \$"
6b6cab3f 130 } >expanded-keywords.0 &&
dfab71cb 131
6b6cab3f
JH
132 {
133 cat expanded-keywords.0 &&
134 printf "\$Id: NoTerminatingSymbolAtEOF"
135 } >expanded-keywords &&
136 cat expanded-keywords >expanded-keywords-crlf &&
137 git add expanded-keywords expanded-keywords-crlf &&
dd555d8b
RS
138 git commit -m "File with keywords expanded" &&
139 id=$(git rev-parse --verify :expanded-keywords) &&
140
dfab71cb
AP
141 {
142 echo "File with expanded keywords"
dd555d8b
RS
143 echo "\$Id: $id \$"
144 echo "\$Id: $id \$"
145 echo "\$Id: $id \$"
146 echo "\$Id: $id \$"
147 echo "\$Id: $id \$"
148 echo "\$Id: $id \$"
dfab71cb 149 echo "\$Id: NoTerminatingSymbol"
07814d90 150 echo "\$Id: Foreign Commit With Spaces \$"
6b6cab3f
JH
151 } >expected-output.0 &&
152 {
153 cat expected-output.0 &&
dd555d8b 154 printf "\$Id: NoTerminatingSymbolAtEOF"
6b6cab3f
JH
155 } >expected-output &&
156 {
157 append_cr <expected-output.0 &&
158 printf "\$Id: NoTerminatingSymbolAtEOF"
159 } >expected-output-crlf &&
160 {
161 echo "expanded-keywords ident"
162 echo "expanded-keywords-crlf ident text eol=crlf"
163 } >>.gitattributes &&
dfab71cb 164
6b6cab3f 165 rm -f expanded-keywords expanded-keywords-crlf &&
dfab71cb 166
dfab71cb 167 git checkout -- expanded-keywords &&
dcbaa0b3 168 test_cmp expected-output expanded-keywords &&
6b6cab3f
JH
169
170 git checkout -- expanded-keywords-crlf &&
dcbaa0b3 171 test_cmp expected-output-crlf expanded-keywords-crlf
dfab71cb
AP
172'
173
a2b665de
PW
174# The use of %f in a filter definition is expanded to the path to
175# the filename being smudged or cleaned. It must be shell escaped.
176# First, set up some interesting file names and pet them in
177# .gitattributes.
178test_expect_success 'filter shell-escaped filenames' '
179 cat >argc.sh <<-EOF &&
180 #!$SHELL_PATH
4290f690 181 cat >/dev/null
a2b665de
PW
182 echo argc: \$# "\$@"
183 EOF
184 normal=name-no-magic &&
185 special="name with '\''sq'\'' and \$x" &&
186 echo some test text >"$normal" &&
187 echo some test text >"$special" &&
188 git add "$normal" "$special" &&
189 git commit -q -m "add files" &&
190 echo "name* filter=argc" >.gitattributes &&
191
192 # delete the files and check them out again, using a smudge filter
193 # that will count the args and echo the command-line back to us
ed549703 194 test_config filter.argc.smudge "sh ./argc.sh %f" &&
a2b665de
PW
195 rm "$normal" "$special" &&
196 git checkout -- "$normal" "$special" &&
197
198 # make sure argc.sh counted the right number of args
199 echo "argc: 1 $normal" >expect &&
200 test_cmp expect "$normal" &&
201 echo "argc: 1 $special" >expect &&
202 test_cmp expect "$special" &&
203
204 # do the same thing, but with more args in the filter expression
ed549703 205 test_config filter.argc.smudge "sh ./argc.sh %f --my-extra-arg" &&
a2b665de
PW
206 rm "$normal" "$special" &&
207 git checkout -- "$normal" "$special" &&
208
209 # make sure argc.sh counted the right number of args
210 echo "argc: 2 $normal --my-extra-arg" >expect &&
211 test_cmp expect "$normal" &&
212 echo "argc: 2 $special --my-extra-arg" >expect &&
213 test_cmp expect "$special" &&
214 :
215'
216
9035d75a 217test_expect_success 'required filter should filter data' '
ed549703
LS
218 test_config filter.required.smudge ./rot13.sh &&
219 test_config filter.required.clean ./rot13.sh &&
220 test_config filter.required.required true &&
36daaaca
JB
221
222 echo "*.r filter=required" >.gitattributes &&
223
9035d75a 224 cat test.o >test.r &&
36daaaca 225 git add test.r &&
9035d75a 226
36daaaca 227 rm -f test.r &&
9035d75a 228 git checkout -- test.r &&
ed549703 229 test_cmp test.o test.r &&
9035d75a
SP
230
231 ./rot13.sh <test.o >expected &&
232 git cat-file blob :test.r >actual &&
ed549703 233 test_cmp expected actual
36daaaca
JB
234'
235
236test_expect_success 'required filter smudge failure' '
ed549703
LS
237 test_config filter.failsmudge.smudge false &&
238 test_config filter.failsmudge.clean cat &&
239 test_config filter.failsmudge.required true &&
36daaaca
JB
240
241 echo "*.fs filter=failsmudge" >.gitattributes &&
242
243 echo test >test.fs &&
244 git add test.fs &&
245 rm -f test.fs &&
246 test_must_fail git checkout -- test.fs
247'
248
249test_expect_success 'required filter clean failure' '
ed549703
LS
250 test_config filter.failclean.smudge cat &&
251 test_config filter.failclean.clean false &&
252 test_config filter.failclean.required true &&
36daaaca
JB
253
254 echo "*.fc filter=failclean" >.gitattributes &&
255
256 echo test >test.fc &&
257 test_must_fail git add test.fc
258'
259
9035d75a 260test_expect_success 'filtering large input to small output should use little memory' '
ed549703
LS
261 test_config filter.devnull.clean "cat >/dev/null" &&
262 test_config filter.devnull.required true &&
9035d75a
SP
263 for i in $(test_seq 1 30); do printf "%1048576d" 1; done >30MB &&
264 echo "30MB filter=devnull" >.gitattributes &&
265 GIT_MMAP_LIMIT=1m GIT_ALLOC_LIMIT=1m git add 30MB
266'
267
0c4dd67a 268test_expect_success 'filter that does not read is fine' '
c680668d 269 test-tool genrandom foo $((128 * 1024 + 1)) >big &&
0c4dd67a 270 echo "big filter=epipe" >.gitattributes &&
ed549703 271 test_config filter.epipe.clean "echo xyzzy" &&
0c4dd67a
JH
272 git add big &&
273 git cat-file blob :big >actual &&
274 echo xyzzy >expect &&
275 test_cmp expect actual
276'
277
0b6806b9 278test_expect_success EXPENSIVE 'filter large file' '
ed549703
LS
279 test_config filter.largefile.smudge cat &&
280 test_config filter.largefile.clean cat &&
0b6806b9
SP
281 for i in $(test_seq 1 2048); do printf "%1048576d" 1; done >2GB &&
282 echo "2GB filter=largefile" >.gitattributes &&
283 git add 2GB 2>err &&
ed549703 284 test_must_be_empty err &&
0b6806b9
SP
285 rm -f 2GB &&
286 git checkout -- 2GB 2>err &&
ed549703 287 test_must_be_empty err
0b6806b9
SP
288'
289
f6a1e1e2 290test_expect_success "filter: clean empty file" '
ed549703
LS
291 test_config filter.in-repo-header.clean "echo cleaned && cat" &&
292 test_config filter.in-repo-header.smudge "sed 1d" &&
f6a1e1e2
JH
293
294 echo "empty-in-worktree filter=in-repo-header" >>.gitattributes &&
295 >empty-in-worktree &&
296
297 echo cleaned >expected &&
298 git add empty-in-worktree &&
299 git show :empty-in-worktree >actual &&
300 test_cmp expected actual
301'
302
303test_expect_success "filter: smudge empty file" '
ed549703
LS
304 test_config filter.empty-in-repo.clean "cat >/dev/null" &&
305 test_config filter.empty-in-repo.smudge "echo smudged && cat" &&
f6a1e1e2
JH
306
307 echo "empty-in-repo filter=empty-in-repo" >>.gitattributes &&
308 echo dead data walking >empty-in-repo &&
309 git add empty-in-repo &&
310
311 echo smudged >expected &&
312 git checkout-index --prefix=filtered- empty-in-repo &&
313 test_cmp expected filtered-empty-in-repo
314'
315
1a8630dc
LS
316test_expect_success 'disable filter with empty override' '
317 test_config_global filter.disable.smudge false &&
318 test_config_global filter.disable.clean false &&
319 test_config filter.disable.smudge false &&
320 test_config filter.disable.clean false &&
321
322 echo "*.disable filter=disable" >.gitattributes &&
323
324 echo test >test.disable &&
325 git -c filter.disable.clean= add test.disable 2>err &&
326 test_must_be_empty err &&
327 rm -f test.disable &&
328 git -c filter.disable.smudge= checkout -- test.disable 2>err &&
329 test_must_be_empty err
330'
331
06dec439
JK
332test_expect_success 'diff does not reuse worktree files that need cleaning' '
333 test_config filter.counter.clean "echo . >>count; sed s/^/clean:/" &&
334 echo "file filter=counter" >.gitattributes &&
335 test_commit one file &&
336 test_commit two file &&
337
338 >count &&
339 git diff-tree -p HEAD &&
340 test_line_count = 0 count
341'
342
edcc8581 343test_expect_success PERL 'required process filter should filter data' '
e1ec4721 344 test_config_global filter.protocol.process "rot13-filter.pl debug.log clean smudge" &&
edcc8581
LS
345 test_config_global filter.protocol.required true &&
346 rm -rf repo &&
347 mkdir repo &&
348 (
349 cd repo &&
350 git init &&
351
edcc8581
LS
352 echo "*.r filter=protocol" >.gitattributes &&
353 git add . &&
9c48b4fb 354 git commit -m "test commit 1" &&
edcc8581
LS
355 git branch empty-branch &&
356
357 cp "$TEST_ROOT/test.o" test.r &&
358 cp "$TEST_ROOT/test2.o" test2.r &&
359 mkdir testsubdir &&
c6b0831c 360 cp "$TEST_ROOT/test3 '\''sq'\'',\$x=.o" "testsubdir/test3 '\''sq'\'',\$x=.r" &&
edcc8581
LS
361 >test4-empty.r &&
362
53b67a80
JS
363 S=$(test_file_size test.r) &&
364 S2=$(test_file_size test2.r) &&
365 S3=$(test_file_size "testsubdir/test3 '\''sq'\'',\$x=.r") &&
13e7ed6a 366 M=$(git hash-object test.r) &&
367 M2=$(git hash-object test2.r) &&
368 M3=$(git hash-object "testsubdir/test3 '\''sq'\'',\$x=.r") &&
369 EMPTY=$(git hash-object /dev/null) &&
edcc8581
LS
370
371 filter_git add . &&
372 cat >expected.log <<-EOF &&
373 START
374 init handshake complete
375 IN: clean test.r $S [OK] -- OUT: $S . [OK]
376 IN: clean test2.r $S2 [OK] -- OUT: $S2 . [OK]
377 IN: clean test4-empty.r 0 [OK] -- OUT: 0 [OK]
c6b0831c 378 IN: clean testsubdir/test3 '\''sq'\'',\$x=.r $S3 [OK] -- OUT: $S3 . [OK]
edcc8581
LS
379 STOP
380 EOF
e1ec4721 381 test_cmp_count expected.log debug.log &&
edcc8581 382
7eeda8b8 383 git commit -m "test commit 2" &&
06d53148
JS
384 MAIN=$(git rev-parse --verify main) &&
385 META="ref=refs/heads/main treeish=$MAIN" &&
c6b0831c 386 rm -f test2.r "testsubdir/test3 '\''sq'\'',\$x=.r" &&
edcc8581
LS
387
388 filter_git checkout --quiet --no-progress . &&
389 cat >expected.log <<-EOF &&
390 START
391 init handshake complete
13e7ed6a 392 IN: smudge test2.r blob=$M2 $S2 [OK] -- OUT: $S2 . [OK]
393 IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r blob=$M3 $S3 [OK] -- OUT: $S3 . [OK]
edcc8581
LS
394 STOP
395 EOF
e1ec4721 396 test_cmp_exclude_clean expected.log debug.log &&
edcc8581 397
58166c2e
TG
398 # Make sure that the file appears dirty, so checkout below has to
399 # run the configured filter.
400 touch test.r &&
edcc8581
LS
401 filter_git checkout --quiet --no-progress empty-branch &&
402 cat >expected.log <<-EOF &&
403 START
404 init handshake complete
405 IN: clean test.r $S [OK] -- OUT: $S . [OK]
406 STOP
407 EOF
e1ec4721 408 test_cmp_exclude_clean expected.log debug.log &&
edcc8581 409
06d53148 410 filter_git checkout --quiet --no-progress main &&
edcc8581
LS
411 cat >expected.log <<-EOF &&
412 START
413 init handshake complete
13e7ed6a 414 IN: smudge test.r $META blob=$M $S [OK] -- OUT: $S . [OK]
415 IN: smudge test2.r $META blob=$M2 $S2 [OK] -- OUT: $S2 . [OK]
416 IN: smudge test4-empty.r $META blob=$EMPTY 0 [OK] -- OUT: 0 [OK]
417 IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r $META blob=$M3 $S3 [OK] -- OUT: $S3 . [OK]
edcc8581
LS
418 STOP
419 EOF
e1ec4721 420 test_cmp_exclude_clean expected.log debug.log &&
edcc8581
LS
421
422 test_cmp_committed_rot13 "$TEST_ROOT/test.o" test.r &&
423 test_cmp_committed_rot13 "$TEST_ROOT/test2.o" test2.r &&
c6b0831c 424 test_cmp_committed_rot13 "$TEST_ROOT/test3 '\''sq'\'',\$x=.o" "testsubdir/test3 '\''sq'\'',\$x=.r"
edcc8581
LS
425 )
426'
427
3f267856 428test_expect_success PERL 'required process filter should filter data for various subcommands' '
429 test_config_global filter.protocol.process "rot13-filter.pl debug.log clean smudge" &&
430 test_config_global filter.protocol.required true &&
431 (
432 cd repo &&
433
53b67a80
JS
434 S=$(test_file_size test.r) &&
435 S2=$(test_file_size test2.r) &&
436 S3=$(test_file_size "testsubdir/test3 '\''sq'\'',\$x=.r") &&
3f267856 437 M=$(git hash-object test.r) &&
438 M2=$(git hash-object test2.r) &&
439 M3=$(git hash-object "testsubdir/test3 '\''sq'\'',\$x=.r") &&
440 EMPTY=$(git hash-object /dev/null) &&
441
06d53148 442 MAIN=$(git rev-parse --verify main) &&
3f267856 443
444 cp "$TEST_ROOT/test.o" test5.r &&
445 git add test5.r &&
446 git commit -m "test commit 3" &&
447 git checkout empty-branch &&
06d53148
JS
448 filter_git rebase --onto empty-branch main^^ main &&
449 MAIN2=$(git rev-parse --verify main) &&
450 META="ref=refs/heads/main treeish=$MAIN2" &&
3f267856 451 cat >expected.log <<-EOF &&
452 START
453 init handshake complete
454 IN: smudge test.r $META blob=$M $S [OK] -- OUT: $S . [OK]
455 IN: smudge test2.r $META blob=$M2 $S2 [OK] -- OUT: $S2 . [OK]
456 IN: smudge test4-empty.r $META blob=$EMPTY 0 [OK] -- OUT: 0 [OK]
457 IN: smudge test5.r $META blob=$M $S [OK] -- OUT: $S . [OK]
458 IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r $META blob=$M3 $S3 [OK] -- OUT: $S3 . [OK]
459 STOP
460 EOF
4cf76f6b 461 test_cmp_exclude_clean expected.log debug.log &&
462
463 git reset --hard empty-branch &&
06d53148
JS
464 filter_git reset --hard $MAIN &&
465 META="treeish=$MAIN" &&
4cf76f6b 466 cat >expected.log <<-EOF &&
467 START
468 init handshake complete
469 IN: smudge test.r $META blob=$M $S [OK] -- OUT: $S . [OK]
470 IN: smudge test2.r $META blob=$M2 $S2 [OK] -- OUT: $S2 . [OK]
471 IN: smudge test4-empty.r $META blob=$EMPTY 0 [OK] -- OUT: 0 [OK]
472 IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r $META blob=$M3 $S3 [OK] -- OUT: $S3 . [OK]
473 STOP
474 EOF
475 test_cmp_exclude_clean expected.log debug.log &&
476
06d53148 477 git branch old-main $MAIN &&
4cf76f6b 478 git reset --hard empty-branch &&
06d53148
JS
479 filter_git reset --hard old-main &&
480 META="ref=refs/heads/old-main treeish=$MAIN" &&
4cf76f6b 481 cat >expected.log <<-EOF &&
482 START
483 init handshake complete
484 IN: smudge test.r $META blob=$M $S [OK] -- OUT: $S . [OK]
485 IN: smudge test2.r $META blob=$M2 $S2 [OK] -- OUT: $S2 . [OK]
486 IN: smudge test4-empty.r $META blob=$EMPTY 0 [OK] -- OUT: 0 [OK]
487 IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r $META blob=$M3 $S3 [OK] -- OUT: $S3 . [OK]
488 STOP
489 EOF
0c0f8a7f 490 test_cmp_exclude_clean expected.log debug.log &&
491
492 git checkout -b merge empty-branch &&
06d53148
JS
493 git branch -f main $MAIN2 &&
494 filter_git merge main &&
495 META="treeish=$MAIN2" &&
0c0f8a7f 496 cat >expected.log <<-EOF &&
497 START
498 init handshake complete
499 IN: smudge test.r $META blob=$M $S [OK] -- OUT: $S . [OK]
500 IN: smudge test2.r $META blob=$M2 $S2 [OK] -- OUT: $S2 . [OK]
501 IN: smudge test4-empty.r $META blob=$EMPTY 0 [OK] -- OUT: 0 [OK]
502 IN: smudge test5.r $META blob=$M $S [OK] -- OUT: $S . [OK]
503 IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r $META blob=$M3 $S3 [OK] -- OUT: $S3 . [OK]
504 STOP
505 EOF
506 test_cmp_exclude_clean expected.log debug.log &&
507
06d53148
JS
508 filter_git archive main >/dev/null &&
509 META="ref=refs/heads/main treeish=$MAIN2" &&
0c0f8a7f 510 cat >expected.log <<-EOF &&
511 START
512 init handshake complete
513 IN: smudge test.r $META blob=$M $S [OK] -- OUT: $S . [OK]
514 IN: smudge test2.r $META blob=$M2 $S2 [OK] -- OUT: $S2 . [OK]
515 IN: smudge test4-empty.r $META blob=$EMPTY 0 [OK] -- OUT: 0 [OK]
516 IN: smudge test5.r $META blob=$M $S [OK] -- OUT: $S . [OK]
517 IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r $META blob=$M3 $S3 [OK] -- OUT: $S3 . [OK]
518 STOP
519 EOF
520 test_cmp_exclude_clean expected.log debug.log &&
521
06d53148 522 TREE="$(git rev-parse $MAIN2^{tree})" &&
0c0f8a7f 523 filter_git archive $TREE >/dev/null &&
524 META="treeish=$TREE" &&
525 cat >expected.log <<-EOF &&
526 START
527 init handshake complete
528 IN: smudge test.r $META blob=$M $S [OK] -- OUT: $S . [OK]
529 IN: smudge test2.r $META blob=$M2 $S2 [OK] -- OUT: $S2 . [OK]
530 IN: smudge test4-empty.r $META blob=$EMPTY 0 [OK] -- OUT: 0 [OK]
531 IN: smudge test5.r $META blob=$M $S [OK] -- OUT: $S . [OK]
532 IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r $META blob=$M3 $S3 [OK] -- OUT: $S3 . [OK]
533 STOP
534 EOF
3f267856 535 test_cmp_exclude_clean expected.log debug.log
536 )
537'
538
edcc8581
LS
539test_expect_success PERL 'required process filter takes precedence' '
540 test_config_global filter.protocol.clean false &&
e1ec4721 541 test_config_global filter.protocol.process "rot13-filter.pl debug.log clean" &&
edcc8581
LS
542 test_config_global filter.protocol.required true &&
543 rm -rf repo &&
544 mkdir repo &&
545 (
546 cd repo &&
547 git init &&
548
549 echo "*.r filter=protocol" >.gitattributes &&
550 cp "$TEST_ROOT/test.o" test.r &&
53b67a80 551 S=$(test_file_size test.r) &&
edcc8581
LS
552
553 # Check that the process filter is invoked here
554 filter_git add . &&
555 cat >expected.log <<-EOF &&
556 START
557 init handshake complete
558 IN: clean test.r $S [OK] -- OUT: $S . [OK]
559 STOP
560 EOF
e1ec4721 561 test_cmp_count expected.log debug.log
edcc8581
LS
562 )
563'
564
565test_expect_success PERL 'required process filter should be used only for "clean" operation only' '
e1ec4721 566 test_config_global filter.protocol.process "rot13-filter.pl debug.log clean" &&
edcc8581
LS
567 rm -rf repo &&
568 mkdir repo &&
569 (
570 cd repo &&
571 git init &&
572
573 echo "*.r filter=protocol" >.gitattributes &&
574 cp "$TEST_ROOT/test.o" test.r &&
53b67a80 575 S=$(test_file_size test.r) &&
edcc8581
LS
576
577 filter_git add . &&
578 cat >expected.log <<-EOF &&
579 START
580 init handshake complete
581 IN: clean test.r $S [OK] -- OUT: $S . [OK]
582 STOP
583 EOF
e1ec4721 584 test_cmp_count expected.log debug.log &&
edcc8581
LS
585
586 rm test.r &&
587
588 filter_git checkout --quiet --no-progress . &&
589 # If the filter would be used for "smudge", too, we would see
590 # "IN: smudge test.r 57 [OK] -- OUT: 57 . [OK]" here
591 cat >expected.log <<-EOF &&
592 START
593 init handshake complete
594 STOP
595 EOF
e1ec4721 596 test_cmp_exclude_clean expected.log debug.log
edcc8581
LS
597 )
598'
599
600test_expect_success PERL 'required process filter should process multiple packets' '
e1ec4721 601 test_config_global filter.protocol.process "rot13-filter.pl debug.log clean smudge" &&
edcc8581
LS
602 test_config_global filter.protocol.required true &&
603
604 rm -rf repo &&
605 mkdir repo &&
606 (
607 cd repo &&
608 git init &&
609
610 # Generate data requiring 1, 2, 3 packets
611 S=65516 && # PKTLINE_DATA_MAXLEN -> Maximal size of a packet
612 generate_random_characters $(($S )) 1pkt_1__.file &&
613 generate_random_characters $(($S +1)) 2pkt_1+1.file &&
614 generate_random_characters $(($S*2-1)) 2pkt_2-1.file &&
615 generate_random_characters $(($S*2 )) 2pkt_2__.file &&
616 generate_random_characters $(($S*2+1)) 3pkt_2+1.file &&
617
618 for FILE in "$TEST_ROOT"/*.file
619 do
620 cp "$FILE" . &&
30030a36 621 rot13.sh <"$FILE" >"$FILE.rot13"
edcc8581
LS
622 done &&
623
624 echo "*.file filter=protocol" >.gitattributes &&
625 filter_git add *.file .gitattributes &&
626 cat >expected.log <<-EOF &&
627 START
628 init handshake complete
629 IN: clean 1pkt_1__.file $(($S )) [OK] -- OUT: $(($S )) . [OK]
630 IN: clean 2pkt_1+1.file $(($S +1)) [OK] -- OUT: $(($S +1)) .. [OK]
631 IN: clean 2pkt_2-1.file $(($S*2-1)) [OK] -- OUT: $(($S*2-1)) .. [OK]
632 IN: clean 2pkt_2__.file $(($S*2 )) [OK] -- OUT: $(($S*2 )) .. [OK]
633 IN: clean 3pkt_2+1.file $(($S*2+1)) [OK] -- OUT: $(($S*2+1)) ... [OK]
634 STOP
635 EOF
e1ec4721 636 test_cmp_count expected.log debug.log &&
edcc8581 637
13e7ed6a 638 M1="blob=$(git hash-object 1pkt_1__.file)" &&
639 M2="blob=$(git hash-object 2pkt_1+1.file)" &&
640 M3="blob=$(git hash-object 2pkt_2-1.file)" &&
641 M4="blob=$(git hash-object 2pkt_2__.file)" &&
642 M5="blob=$(git hash-object 3pkt_2+1.file)" &&
643 rm -f *.file debug.log &&
edcc8581
LS
644
645 filter_git checkout --quiet --no-progress -- *.file &&
646 cat >expected.log <<-EOF &&
647 START
648 init handshake complete
13e7ed6a 649 IN: smudge 1pkt_1__.file $M1 $(($S )) [OK] -- OUT: $(($S )) . [OK]
650 IN: smudge 2pkt_1+1.file $M2 $(($S +1)) [OK] -- OUT: $(($S +1)) .. [OK]
651 IN: smudge 2pkt_2-1.file $M3 $(($S*2-1)) [OK] -- OUT: $(($S*2-1)) .. [OK]
652 IN: smudge 2pkt_2__.file $M4 $(($S*2 )) [OK] -- OUT: $(($S*2 )) .. [OK]
653 IN: smudge 3pkt_2+1.file $M5 $(($S*2+1)) [OK] -- OUT: $(($S*2+1)) ... [OK]
edcc8581
LS
654 STOP
655 EOF
e1ec4721 656 test_cmp_exclude_clean expected.log debug.log &&
edcc8581
LS
657
658 for FILE in *.file
659 do
660 test_cmp_committed_rot13 "$TEST_ROOT/$FILE" $FILE
661 done
662 )
663'
664
665test_expect_success PERL 'required process filter with clean error should fail' '
e1ec4721 666 test_config_global filter.protocol.process "rot13-filter.pl debug.log clean smudge" &&
edcc8581
LS
667 test_config_global filter.protocol.required true &&
668 rm -rf repo &&
669 mkdir repo &&
670 (
671 cd repo &&
672 git init &&
673
674 echo "*.r filter=protocol" >.gitattributes &&
675
676 cp "$TEST_ROOT/test.o" test.r &&
677 echo "this is going to fail" >clean-write-fail.r &&
678 echo "content-test3-subdir" >test3.r &&
679
680 test_must_fail git add .
681 )
682'
683
684test_expect_success PERL 'process filter should restart after unexpected write failure' '
e1ec4721 685 test_config_global filter.protocol.process "rot13-filter.pl debug.log clean smudge" &&
edcc8581
LS
686 rm -rf repo &&
687 mkdir repo &&
688 (
689 cd repo &&
690 git init &&
691
692 echo "*.r filter=protocol" >.gitattributes &&
693
694 cp "$TEST_ROOT/test.o" test.r &&
695 cp "$TEST_ROOT/test2.o" test2.r &&
696 echo "this is going to fail" >smudge-write-fail.o &&
697 cp smudge-write-fail.o smudge-write-fail.r &&
698
53b67a80
JS
699 S=$(test_file_size test.r) &&
700 S2=$(test_file_size test2.r) &&
701 SF=$(test_file_size smudge-write-fail.r) &&
13e7ed6a 702 M=$(git hash-object test.r) &&
703 M2=$(git hash-object test2.r) &&
704 MF=$(git hash-object smudge-write-fail.r) &&
705 rm -f debug.log &&
edcc8581
LS
706
707 git add . &&
708 rm -f *.r &&
709
e1ec4721 710 rm -f debug.log &&
edcc8581
LS
711 git checkout --quiet --no-progress . 2>git-stderr.log &&
712
713 grep "smudge write error at" git-stderr.log &&
d26a328e 714 test_i18ngrep "error: external filter" git-stderr.log &&
edcc8581
LS
715
716 cat >expected.log <<-EOF &&
717 START
718 init handshake complete
13e7ed6a 719 IN: smudge smudge-write-fail.r blob=$MF $SF [OK] -- [WRITE FAIL]
edcc8581
LS
720 START
721 init handshake complete
13e7ed6a 722 IN: smudge test.r blob=$M $S [OK] -- OUT: $S . [OK]
723 IN: smudge test2.r blob=$M2 $S2 [OK] -- OUT: $S2 . [OK]
edcc8581
LS
724 STOP
725 EOF
e1ec4721 726 test_cmp_exclude_clean expected.log debug.log &&
edcc8581
LS
727
728 test_cmp_committed_rot13 "$TEST_ROOT/test.o" test.r &&
729 test_cmp_committed_rot13 "$TEST_ROOT/test2.o" test2.r &&
730
731 # Smudge failed
732 ! test_cmp smudge-write-fail.o smudge-write-fail.r &&
30030a36 733 rot13.sh <smudge-write-fail.o >expected &&
edcc8581
LS
734 git cat-file blob :smudge-write-fail.r >actual &&
735 test_cmp expected actual
736 )
737'
738
739test_expect_success PERL 'process filter should not be restarted if it signals an error' '
e1ec4721 740 test_config_global filter.protocol.process "rot13-filter.pl debug.log clean smudge" &&
edcc8581
LS
741 rm -rf repo &&
742 mkdir repo &&
743 (
744 cd repo &&
745 git init &&
746
747 echo "*.r filter=protocol" >.gitattributes &&
748
749 cp "$TEST_ROOT/test.o" test.r &&
750 cp "$TEST_ROOT/test2.o" test2.r &&
751 echo "this will cause an error" >error.o &&
752 cp error.o error.r &&
753
53b67a80
JS
754 S=$(test_file_size test.r) &&
755 S2=$(test_file_size test2.r) &&
756 SE=$(test_file_size error.r) &&
13e7ed6a 757 M=$(git hash-object test.r) &&
758 M2=$(git hash-object test2.r) &&
759 ME=$(git hash-object error.r) &&
760 rm -f debug.log &&
edcc8581
LS
761
762 git add . &&
763 rm -f *.r &&
764
765 filter_git checkout --quiet --no-progress . &&
766 cat >expected.log <<-EOF &&
767 START
768 init handshake complete
13e7ed6a 769 IN: smudge error.r blob=$ME $SE [OK] -- [ERROR]
770 IN: smudge test.r blob=$M $S [OK] -- OUT: $S . [OK]
771 IN: smudge test2.r blob=$M2 $S2 [OK] -- OUT: $S2 . [OK]
edcc8581
LS
772 STOP
773 EOF
e1ec4721 774 test_cmp_exclude_clean expected.log debug.log &&
edcc8581
LS
775
776 test_cmp_committed_rot13 "$TEST_ROOT/test.o" test.r &&
777 test_cmp_committed_rot13 "$TEST_ROOT/test2.o" test2.r &&
778 test_cmp error.o error.r
779 )
780'
781
782test_expect_success PERL 'process filter abort stops processing of all further files' '
e1ec4721 783 test_config_global filter.protocol.process "rot13-filter.pl debug.log clean smudge" &&
edcc8581
LS
784 rm -rf repo &&
785 mkdir repo &&
786 (
787 cd repo &&
788 git init &&
789
790 echo "*.r filter=protocol" >.gitattributes &&
791
792 cp "$TEST_ROOT/test.o" test.r &&
793 cp "$TEST_ROOT/test2.o" test2.r &&
794 echo "error this blob and all future blobs" >abort.o &&
795 cp abort.o abort.r &&
796
13e7ed6a 797 M="blob=$(git hash-object abort.r)" &&
798 rm -f debug.log &&
53b67a80 799 SA=$(test_file_size abort.r) &&
edcc8581
LS
800
801 git add . &&
802 rm -f *.r &&
803
13e7ed6a 804
edcc8581
LS
805 # Note: This test assumes that Git filters files in alphabetical
806 # order ("abort.r" before "test.r").
807 filter_git checkout --quiet --no-progress . &&
808 cat >expected.log <<-EOF &&
809 START
810 init handshake complete
13e7ed6a 811 IN: smudge abort.r $M $SA [OK] -- [ABORT]
edcc8581
LS
812 STOP
813 EOF
e1ec4721 814 test_cmp_exclude_clean expected.log debug.log &&
edcc8581
LS
815
816 test_cmp "$TEST_ROOT/test.o" test.r &&
817 test_cmp "$TEST_ROOT/test2.o" test2.r &&
818 test_cmp abort.o abort.r
819 )
820'
821
822test_expect_success PERL 'invalid process filter must fail (and not hang!)' '
823 test_config_global filter.protocol.process cat &&
824 test_config_global filter.protocol.required true &&
825 rm -rf repo &&
826 mkdir repo &&
827 (
828 cd repo &&
829 git init &&
830
831 echo "*.r filter=protocol" >.gitattributes &&
832
833 cp "$TEST_ROOT/test.o" test.r &&
834 test_must_fail git add . 2>git-stderr.log &&
fa64a2fd 835 grep "expected git-filter-server" git-stderr.log
edcc8581
LS
836 )
837'
838
2841e8f8
LS
839test_expect_success PERL 'delayed checkout in process filter' '
840 test_config_global filter.a.process "rot13-filter.pl a.log clean smudge delay" &&
841 test_config_global filter.a.required true &&
842 test_config_global filter.b.process "rot13-filter.pl b.log clean smudge delay" &&
843 test_config_global filter.b.required true &&
844
845 rm -rf repo &&
846 mkdir repo &&
847 (
848 cd repo &&
849 git init &&
850 echo "*.a filter=a" >.gitattributes &&
851 echo "*.b filter=b" >>.gitattributes &&
852 cp "$TEST_ROOT/test.o" test.a &&
853 cp "$TEST_ROOT/test.o" test-delay10.a &&
854 cp "$TEST_ROOT/test.o" test-delay11.a &&
855 cp "$TEST_ROOT/test.o" test-delay20.a &&
856 cp "$TEST_ROOT/test.o" test-delay10.b &&
857 git add . &&
858 git commit -m "test commit"
859 ) &&
860
53b67a80 861 S=$(test_file_size "$TEST_ROOT/test.o") &&
06d53148
JS
862 PM="ref=refs/heads/main treeish=$(git -C repo rev-parse --verify main) " &&
863 M="${PM}blob=$(git -C repo rev-parse --verify main:test.a)" &&
2841e8f8
LS
864 cat >a.exp <<-EOF &&
865 START
866 init handshake complete
13e7ed6a 867 IN: smudge test.a $M $S [OK] -- OUT: $S . [OK]
868 IN: smudge test-delay10.a $M $S [OK] -- [DELAYED]
869 IN: smudge test-delay11.a $M $S [OK] -- [DELAYED]
870 IN: smudge test-delay20.a $M $S [OK] -- [DELAYED]
2841e8f8 871 IN: list_available_blobs test-delay10.a test-delay11.a [OK]
13e7ed6a 872 IN: smudge test-delay10.a $M 0 [OK] -- OUT: $S . [OK]
873 IN: smudge test-delay11.a $M 0 [OK] -- OUT: $S . [OK]
2841e8f8 874 IN: list_available_blobs test-delay20.a [OK]
13e7ed6a 875 IN: smudge test-delay20.a $M 0 [OK] -- OUT: $S . [OK]
2841e8f8
LS
876 IN: list_available_blobs [OK]
877 STOP
878 EOF
879 cat >b.exp <<-EOF &&
880 START
881 init handshake complete
13e7ed6a 882 IN: smudge test-delay10.b $M $S [OK] -- [DELAYED]
2841e8f8 883 IN: list_available_blobs test-delay10.b [OK]
13e7ed6a 884 IN: smudge test-delay10.b $M 0 [OK] -- OUT: $S . [OK]
2841e8f8
LS
885 IN: list_available_blobs [OK]
886 STOP
887 EOF
888
889 rm -rf repo-cloned &&
890 filter_git clone repo repo-cloned &&
891 test_cmp_count a.exp repo-cloned/a.log &&
892 test_cmp_count b.exp repo-cloned/b.log &&
893
894 (
895 cd repo-cloned &&
896 test_cmp_committed_rot13 "$TEST_ROOT/test.o" test.a &&
897 test_cmp_committed_rot13 "$TEST_ROOT/test.o" test-delay10.a &&
898 test_cmp_committed_rot13 "$TEST_ROOT/test.o" test-delay11.a &&
899 test_cmp_committed_rot13 "$TEST_ROOT/test.o" test-delay20.a &&
900 test_cmp_committed_rot13 "$TEST_ROOT/test.o" test-delay10.b &&
901
902 rm *.a *.b &&
903 filter_git checkout . &&
dfc8cdc6 904 # We are not checking out a ref here, so filter out ref metadata.
905 sed -e "s!$PM!!" ../a.exp >a.exp.filtered &&
906 sed -e "s!$PM!!" ../b.exp >b.exp.filtered &&
907 test_cmp_count a.exp.filtered a.log &&
908 test_cmp_count b.exp.filtered b.log &&
2841e8f8
LS
909
910 test_cmp_committed_rot13 "$TEST_ROOT/test.o" test.a &&
911 test_cmp_committed_rot13 "$TEST_ROOT/test.o" test-delay10.a &&
912 test_cmp_committed_rot13 "$TEST_ROOT/test.o" test-delay11.a &&
913 test_cmp_committed_rot13 "$TEST_ROOT/test.o" test-delay20.a &&
914 test_cmp_committed_rot13 "$TEST_ROOT/test.o" test-delay10.b
915 )
916'
917
918test_expect_success PERL 'missing file in delayed checkout' '
919 test_config_global filter.bug.process "rot13-filter.pl bug.log clean smudge delay" &&
920 test_config_global filter.bug.required true &&
921
922 rm -rf repo &&
923 mkdir repo &&
924 (
925 cd repo &&
926 git init &&
927 echo "*.a filter=bug" >.gitattributes &&
75651fd7 928 cp "$TEST_ROOT/test.o" missing-delay.a &&
2841e8f8
LS
929 git add . &&
930 git commit -m "test commit"
931 ) &&
932
933 rm -rf repo-cloned &&
934 test_must_fail git clone repo repo-cloned 2>git-stderr.log &&
2841e8f8
LS
935 grep "error: .missing-delay\.a. was not filtered properly" git-stderr.log
936'
937
938test_expect_success PERL 'invalid file in delayed checkout' '
939 test_config_global filter.bug.process "rot13-filter.pl bug.log clean smudge delay" &&
940 test_config_global filter.bug.required true &&
941
942 rm -rf repo &&
943 mkdir repo &&
944 (
945 cd repo &&
946 git init &&
947 echo "*.a filter=bug" >.gitattributes &&
948 cp "$TEST_ROOT/test.o" invalid-delay.a &&
75651fd7 949 cp "$TEST_ROOT/test.o" unfiltered &&
2841e8f8
LS
950 git add . &&
951 git commit -m "test commit"
952 ) &&
953
954 rm -rf repo-cloned &&
955 test_must_fail git clone repo repo-cloned 2>git-stderr.log &&
956 grep "error: external filter .* signaled that .unfiltered. is now available although it has not been delayed earlier" git-stderr.log
957'
958
3fed15f5 959test_done