t0021: compute file size with a single process instead of a pipeline
[git] / t / t0021-conversion.sh
1 #!/bin/sh
2
3 test_description='blob conversion via gitattributes'
4
5 . ./test-lib.sh
6
7 TEST_ROOT="$(pwd)"
8
9 cat <<EOF >"$TEST_ROOT/rot13.sh"
10 #!$SHELL_PATH
11 tr \
12   'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' \
13   'nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM'
14 EOF
15 chmod +x "$TEST_ROOT/rot13.sh"
16
17 generate_random_characters () {
18         LEN=$1
19         NAME=$2
20         test-genrandom some-seed $LEN |
21                 perl -pe "s/./chr((ord($&) % 26) + ord('a'))/sge" >"$TEST_ROOT/$NAME"
22 }
23
24 file_size () {
25         perl -e 'print -s $ARGV[0]' "$1"
26 }
27
28 filter_git () {
29         rm -f rot13-filter.log &&
30         git "$@" 2>git-stderr.log &&
31         rm -f git-stderr.log
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.
37 # c.f. http://public-inbox.org/git/xmqqshv18i8i.fsf@gitster.mtv.corp.google.com/
38 test_cmp_count () {
39         expect=$1
40         actual=$2
41         for FILE in "$expect" "$actual"
42         do
43                 sort "$FILE" | uniq -c |
44                 sed -e "s/^ *[0-9][0-9]*[       ]*IN: /x IN: /" >"$FILE.tmp" &&
45                 mv "$FILE.tmp" "$FILE" || return
46         done &&
47         test_cmp "$expect" "$actual"
48 }
49
50 # Compare two files but exclude all `clean` invocations because Git can
51 # call `clean` zero or more times.
52 # c.f. http://public-inbox.org/git/xmqqshv18i8i.fsf@gitster.mtv.corp.google.com/
53 test_cmp_exclude_clean () {
54         expect=$1
55         actual=$2
56         for FILE in "$expect" "$actual"
57         do
58                 grep -v "IN: clean" "$FILE" >"$FILE.tmp" &&
59                 mv "$FILE.tmp" "$FILE"
60         done &&
61         test_cmp "$expect" "$actual"
62 }
63
64 # Check that the contents of two files are equal and that their rot13 version
65 # is equal to the committed content.
66 test_cmp_committed_rot13 () {
67         test_cmp "$1" "$2" &&
68         "$TEST_ROOT/rot13.sh" <"$1" >expected &&
69         git cat-file blob :"$2" >actual &&
70         test_cmp expected actual
71 }
72
73 test_expect_success setup '
74         git config filter.rot13.smudge ./rot13.sh &&
75         git config filter.rot13.clean ./rot13.sh &&
76
77         {
78             echo "*.t filter=rot13"
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
85             echo '\''$Id$'\''
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 &&
92         git checkout -- test test.t test.i &&
93
94         echo "content-test2" >test2.o &&
95         echo "content-test3 - filename with special characters" >"test3 '\''sq'\'',\$x.o"
96 '
97
98 script='s/^\$Id: \([0-9a-f]*\) \$/\1/p'
99
100 test_expect_success check '
101
102         test_cmp test.o test &&
103         test_cmp test.o test.t &&
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) &&
109         test "z$id" = "z$embedded" &&
110
111         git cat-file blob :test.t >test.r &&
112
113         ./rot13.sh <test.o >test.t &&
114         test_cmp test.r test.t
115 '
116
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
119 test_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"
129                 echo "\$Id: Foreign Commit With Spaces \$"
130         } >expanded-keywords.0 &&
131
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 &&
138         git commit -m "File with keywords expanded" &&
139         id=$(git rev-parse --verify :expanded-keywords) &&
140
141         {
142                 echo "File with expanded keywords"
143                 echo "\$Id: $id \$"
144                 echo "\$Id: $id \$"
145                 echo "\$Id: $id \$"
146                 echo "\$Id: $id \$"
147                 echo "\$Id: $id \$"
148                 echo "\$Id: $id \$"
149                 echo "\$Id: NoTerminatingSymbol"
150                 echo "\$Id: Foreign Commit With Spaces \$"
151         } >expected-output.0 &&
152         {
153                 cat expected-output.0 &&
154                 printf "\$Id: NoTerminatingSymbolAtEOF"
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 &&
164
165         rm -f expanded-keywords expanded-keywords-crlf &&
166
167         git checkout -- expanded-keywords &&
168         test_cmp expanded-keywords expected-output &&
169
170         git checkout -- expanded-keywords-crlf &&
171         test_cmp expanded-keywords-crlf expected-output-crlf
172 '
173
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.
178 test_expect_success 'filter shell-escaped filenames' '
179         cat >argc.sh <<-EOF &&
180         #!$SHELL_PATH
181         cat >/dev/null
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
194         test_config filter.argc.smudge "sh ./argc.sh %f" &&
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
205         test_config filter.argc.smudge "sh ./argc.sh %f --my-extra-arg" &&
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
217 test_expect_success 'required filter should filter data' '
218         test_config filter.required.smudge ./rot13.sh &&
219         test_config filter.required.clean ./rot13.sh &&
220         test_config filter.required.required true &&
221
222         echo "*.r filter=required" >.gitattributes &&
223
224         cat test.o >test.r &&
225         git add test.r &&
226
227         rm -f test.r &&
228         git checkout -- test.r &&
229         test_cmp test.o test.r &&
230
231         ./rot13.sh <test.o >expected &&
232         git cat-file blob :test.r >actual &&
233         test_cmp expected actual
234 '
235
236 test_expect_success 'required filter smudge failure' '
237         test_config filter.failsmudge.smudge false &&
238         test_config filter.failsmudge.clean cat &&
239         test_config filter.failsmudge.required true &&
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
249 test_expect_success 'required filter clean failure' '
250         test_config filter.failclean.smudge cat &&
251         test_config filter.failclean.clean false &&
252         test_config filter.failclean.required true &&
253
254         echo "*.fc filter=failclean" >.gitattributes &&
255
256         echo test >test.fc &&
257         test_must_fail git add test.fc
258 '
259
260 test_expect_success 'filtering large input to small output should use little memory' '
261         test_config filter.devnull.clean "cat >/dev/null" &&
262         test_config filter.devnull.required true &&
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
268 test_expect_success 'filter that does not read is fine' '
269         test-genrandom foo $((128 * 1024 + 1)) >big &&
270         echo "big filter=epipe" >.gitattributes &&
271         test_config filter.epipe.clean "echo xyzzy" &&
272         git add big &&
273         git cat-file blob :big >actual &&
274         echo xyzzy >expect &&
275         test_cmp expect actual
276 '
277
278 test_expect_success EXPENSIVE 'filter large file' '
279         test_config filter.largefile.smudge cat &&
280         test_config filter.largefile.clean cat &&
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 &&
284         test_must_be_empty err &&
285         rm -f 2GB &&
286         git checkout -- 2GB 2>err &&
287         test_must_be_empty err
288 '
289
290 test_expect_success "filter: clean empty file" '
291         test_config filter.in-repo-header.clean  "echo cleaned && cat" &&
292         test_config filter.in-repo-header.smudge "sed 1d" &&
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
303 test_expect_success "filter: smudge empty file" '
304         test_config filter.empty-in-repo.clean "cat >/dev/null" &&
305         test_config filter.empty-in-repo.smudge "echo smudged && cat" &&
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
316 test_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
332 test_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
343 test_expect_success PERL 'required process filter should filter data' '
344         test_config_global filter.protocol.process "$TEST_DIRECTORY/t0021/rot13-filter.pl clean smudge" &&
345         test_config_global filter.protocol.required true &&
346         rm -rf repo &&
347         mkdir repo &&
348         (
349                 cd repo &&
350                 git init &&
351
352                 echo "git-stderr.log" >.gitignore &&
353                 echo "*.r filter=protocol" >.gitattributes &&
354                 git add . &&
355                 git commit . -m "test commit 1" &&
356                 git branch empty-branch &&
357
358                 cp "$TEST_ROOT/test.o" test.r &&
359                 cp "$TEST_ROOT/test2.o" test2.r &&
360                 mkdir testsubdir &&
361                 cp "$TEST_ROOT/test3 '\''sq'\'',\$x.o" "testsubdir/test3 '\''sq'\'',\$x.r" &&
362                 >test4-empty.r &&
363
364                 S=$(file_size test.r) &&
365                 S2=$(file_size test2.r) &&
366                 S3=$(file_size "testsubdir/test3 '\''sq'\'',\$x.r") &&
367
368                 filter_git add . &&
369                 cat >expected.log <<-EOF &&
370                         START
371                         init handshake complete
372                         IN: clean test.r $S [OK] -- OUT: $S . [OK]
373                         IN: clean test2.r $S2 [OK] -- OUT: $S2 . [OK]
374                         IN: clean test4-empty.r 0 [OK] -- OUT: 0  [OK]
375                         IN: clean testsubdir/test3 '\''sq'\'',\$x.r $S3 [OK] -- OUT: $S3 . [OK]
376                         STOP
377                 EOF
378                 test_cmp_count expected.log rot13-filter.log &&
379
380                 filter_git commit . -m "test commit 2" &&
381                 cat >expected.log <<-EOF &&
382                         START
383                         init handshake complete
384                         IN: clean test.r $S [OK] -- OUT: $S . [OK]
385                         IN: clean test2.r $S2 [OK] -- OUT: $S2 . [OK]
386                         IN: clean test4-empty.r 0 [OK] -- OUT: 0  [OK]
387                         IN: clean testsubdir/test3 '\''sq'\'',\$x.r $S3 [OK] -- OUT: $S3 . [OK]
388                         IN: clean test.r $S [OK] -- OUT: $S . [OK]
389                         IN: clean test2.r $S2 [OK] -- OUT: $S2 . [OK]
390                         IN: clean test4-empty.r 0 [OK] -- OUT: 0  [OK]
391                         IN: clean testsubdir/test3 '\''sq'\'',\$x.r $S3 [OK] -- OUT: $S3 . [OK]
392                         STOP
393                 EOF
394                 test_cmp_count expected.log rot13-filter.log &&
395
396                 rm -f test2.r "testsubdir/test3 '\''sq'\'',\$x.r" &&
397
398                 filter_git checkout --quiet --no-progress . &&
399                 cat >expected.log <<-EOF &&
400                         START
401                         init handshake complete
402                         IN: smudge test2.r $S2 [OK] -- OUT: $S2 . [OK]
403                         IN: smudge testsubdir/test3 '\''sq'\'',\$x.r $S3 [OK] -- OUT: $S3 . [OK]
404                         STOP
405                 EOF
406                 test_cmp_exclude_clean expected.log rot13-filter.log &&
407
408                 filter_git checkout --quiet --no-progress empty-branch &&
409                 cat >expected.log <<-EOF &&
410                         START
411                         init handshake complete
412                         IN: clean test.r $S [OK] -- OUT: $S . [OK]
413                         STOP
414                 EOF
415                 test_cmp_exclude_clean expected.log rot13-filter.log &&
416
417                 filter_git checkout --quiet --no-progress master &&
418                 cat >expected.log <<-EOF &&
419                         START
420                         init handshake complete
421                         IN: smudge test.r $S [OK] -- OUT: $S . [OK]
422                         IN: smudge test2.r $S2 [OK] -- OUT: $S2 . [OK]
423                         IN: smudge test4-empty.r 0 [OK] -- OUT: 0  [OK]
424                         IN: smudge testsubdir/test3 '\''sq'\'',\$x.r $S3 [OK] -- OUT: $S3 . [OK]
425                         STOP
426                 EOF
427                 test_cmp_exclude_clean expected.log rot13-filter.log &&
428
429                 test_cmp_committed_rot13 "$TEST_ROOT/test.o" test.r &&
430                 test_cmp_committed_rot13 "$TEST_ROOT/test2.o" test2.r &&
431                 test_cmp_committed_rot13 "$TEST_ROOT/test3 '\''sq'\'',\$x.o" "testsubdir/test3 '\''sq'\'',\$x.r"
432         )
433 '
434
435 test_expect_success PERL 'required process filter takes precedence' '
436         test_config_global filter.protocol.clean false &&
437         test_config_global filter.protocol.process "$TEST_DIRECTORY/t0021/rot13-filter.pl clean" &&
438         test_config_global filter.protocol.required true &&
439         rm -rf repo &&
440         mkdir repo &&
441         (
442                 cd repo &&
443                 git init &&
444
445                 echo "*.r filter=protocol" >.gitattributes &&
446                 cp "$TEST_ROOT/test.o" test.r &&
447                 S=$(file_size test.r) &&
448
449                 # Check that the process filter is invoked here
450                 filter_git add . &&
451                 cat >expected.log <<-EOF &&
452                         START
453                         init handshake complete
454                         IN: clean test.r $S [OK] -- OUT: $S . [OK]
455                         STOP
456                 EOF
457                 test_cmp_count expected.log rot13-filter.log
458         )
459 '
460
461 test_expect_success PERL 'required process filter should be used only for "clean" operation only' '
462         test_config_global filter.protocol.process "$TEST_DIRECTORY/t0021/rot13-filter.pl clean" &&
463         rm -rf repo &&
464         mkdir repo &&
465         (
466                 cd repo &&
467                 git init &&
468
469                 echo "*.r filter=protocol" >.gitattributes &&
470                 cp "$TEST_ROOT/test.o" test.r &&
471                 S=$(file_size test.r) &&
472
473                 filter_git add . &&
474                 cat >expected.log <<-EOF &&
475                         START
476                         init handshake complete
477                         IN: clean test.r $S [OK] -- OUT: $S . [OK]
478                         STOP
479                 EOF
480                 test_cmp_count expected.log rot13-filter.log &&
481
482                 rm test.r &&
483
484                 filter_git checkout --quiet --no-progress . &&
485                 # If the filter would be used for "smudge", too, we would see
486                 # "IN: smudge test.r 57 [OK] -- OUT: 57 . [OK]" here
487                 cat >expected.log <<-EOF &&
488                         START
489                         init handshake complete
490                         STOP
491                 EOF
492                 test_cmp_exclude_clean expected.log rot13-filter.log
493         )
494 '
495
496 test_expect_success PERL 'required process filter should process multiple packets' '
497         test_config_global filter.protocol.process "$TEST_DIRECTORY/t0021/rot13-filter.pl clean smudge" &&
498         test_config_global filter.protocol.required true &&
499
500         rm -rf repo &&
501         mkdir repo &&
502         (
503                 cd repo &&
504                 git init &&
505
506                 # Generate data requiring 1, 2, 3 packets
507                 S=65516 && # PKTLINE_DATA_MAXLEN -> Maximal size of a packet
508                 generate_random_characters $(($S    )) 1pkt_1__.file &&
509                 generate_random_characters $(($S  +1)) 2pkt_1+1.file &&
510                 generate_random_characters $(($S*2-1)) 2pkt_2-1.file &&
511                 generate_random_characters $(($S*2  )) 2pkt_2__.file &&
512                 generate_random_characters $(($S*2+1)) 3pkt_2+1.file &&
513
514                 for FILE in "$TEST_ROOT"/*.file
515                 do
516                         cp "$FILE" . &&
517                         "$TEST_ROOT/rot13.sh" <"$FILE" >"$FILE.rot13"
518                 done &&
519
520                 echo "*.file filter=protocol" >.gitattributes &&
521                 filter_git add *.file .gitattributes &&
522                 cat >expected.log <<-EOF &&
523                         START
524                         init handshake complete
525                         IN: clean 1pkt_1__.file $(($S    )) [OK] -- OUT: $(($S    )) . [OK]
526                         IN: clean 2pkt_1+1.file $(($S  +1)) [OK] -- OUT: $(($S  +1)) .. [OK]
527                         IN: clean 2pkt_2-1.file $(($S*2-1)) [OK] -- OUT: $(($S*2-1)) .. [OK]
528                         IN: clean 2pkt_2__.file $(($S*2  )) [OK] -- OUT: $(($S*2  )) .. [OK]
529                         IN: clean 3pkt_2+1.file $(($S*2+1)) [OK] -- OUT: $(($S*2+1)) ... [OK]
530                         STOP
531                 EOF
532                 test_cmp_count expected.log rot13-filter.log &&
533
534                 rm -f *.file &&
535
536                 filter_git checkout --quiet --no-progress -- *.file &&
537                 cat >expected.log <<-EOF &&
538                         START
539                         init handshake complete
540                         IN: smudge 1pkt_1__.file $(($S    )) [OK] -- OUT: $(($S    )) . [OK]
541                         IN: smudge 2pkt_1+1.file $(($S  +1)) [OK] -- OUT: $(($S  +1)) .. [OK]
542                         IN: smudge 2pkt_2-1.file $(($S*2-1)) [OK] -- OUT: $(($S*2-1)) .. [OK]
543                         IN: smudge 2pkt_2__.file $(($S*2  )) [OK] -- OUT: $(($S*2  )) .. [OK]
544                         IN: smudge 3pkt_2+1.file $(($S*2+1)) [OK] -- OUT: $(($S*2+1)) ... [OK]
545                         STOP
546                 EOF
547                 test_cmp_exclude_clean expected.log rot13-filter.log &&
548
549                 for FILE in *.file
550                 do
551                         test_cmp_committed_rot13 "$TEST_ROOT/$FILE" $FILE
552                 done
553         )
554 '
555
556 test_expect_success PERL 'required process filter with clean error should fail' '
557         test_config_global filter.protocol.process "$TEST_DIRECTORY/t0021/rot13-filter.pl clean smudge" &&
558         test_config_global filter.protocol.required true &&
559         rm -rf repo &&
560         mkdir repo &&
561         (
562                 cd repo &&
563                 git init &&
564
565                 echo "*.r filter=protocol" >.gitattributes &&
566
567                 cp "$TEST_ROOT/test.o" test.r &&
568                 echo "this is going to fail" >clean-write-fail.r &&
569                 echo "content-test3-subdir" >test3.r &&
570
571                 test_must_fail git add .
572         )
573 '
574
575 test_expect_success PERL 'process filter should restart after unexpected write failure' '
576         test_config_global filter.protocol.process "$TEST_DIRECTORY/t0021/rot13-filter.pl clean smudge" &&
577         rm -rf repo &&
578         mkdir repo &&
579         (
580                 cd repo &&
581                 git init &&
582
583                 echo "*.r filter=protocol" >.gitattributes &&
584
585                 cp "$TEST_ROOT/test.o" test.r &&
586                 cp "$TEST_ROOT/test2.o" test2.r &&
587                 echo "this is going to fail" >smudge-write-fail.o &&
588                 cp smudge-write-fail.o smudge-write-fail.r &&
589
590                 S=$(file_size test.r) &&
591                 S2=$(file_size test2.r) &&
592                 SF=$(file_size smudge-write-fail.r) &&
593
594                 git add . &&
595                 rm -f *.r &&
596
597                 rm -f rot13-filter.log &&
598                 git checkout --quiet --no-progress . 2>git-stderr.log &&
599
600                 grep "smudge write error at" git-stderr.log &&
601                 grep "error: external filter" git-stderr.log &&
602
603                 cat >expected.log <<-EOF &&
604                         START
605                         init handshake complete
606                         IN: smudge smudge-write-fail.r $SF [OK] -- OUT: $SF [WRITE FAIL]
607                         START
608                         init handshake complete
609                         IN: smudge test.r $S [OK] -- OUT: $S . [OK]
610                         IN: smudge test2.r $S2 [OK] -- OUT: $S2 . [OK]
611                         STOP
612                 EOF
613                 test_cmp_exclude_clean expected.log rot13-filter.log &&
614
615                 test_cmp_committed_rot13 "$TEST_ROOT/test.o" test.r &&
616                 test_cmp_committed_rot13 "$TEST_ROOT/test2.o" test2.r &&
617
618                 # Smudge failed
619                 ! test_cmp smudge-write-fail.o smudge-write-fail.r &&
620                 "$TEST_ROOT/rot13.sh" <smudge-write-fail.o >expected &&
621                 git cat-file blob :smudge-write-fail.r >actual &&
622                 test_cmp expected actual
623         )
624 '
625
626 test_expect_success PERL 'process filter should not be restarted if it signals an error' '
627         test_config_global filter.protocol.process "$TEST_DIRECTORY/t0021/rot13-filter.pl clean smudge" &&
628         rm -rf repo &&
629         mkdir repo &&
630         (
631                 cd repo &&
632                 git init &&
633
634                 echo "*.r filter=protocol" >.gitattributes &&
635
636                 cp "$TEST_ROOT/test.o" test.r &&
637                 cp "$TEST_ROOT/test2.o" test2.r &&
638                 echo "this will cause an error" >error.o &&
639                 cp error.o error.r &&
640
641                 S=$(file_size test.r) &&
642                 S2=$(file_size test2.r) &&
643                 SE=$(file_size error.r) &&
644
645                 git add . &&
646                 rm -f *.r &&
647
648                 filter_git checkout --quiet --no-progress . &&
649                 cat >expected.log <<-EOF &&
650                         START
651                         init handshake complete
652                         IN: smudge error.r $SE [OK] -- OUT: 0 [ERROR]
653                         IN: smudge test.r $S [OK] -- OUT: $S . [OK]
654                         IN: smudge test2.r $S2 [OK] -- OUT: $S2 . [OK]
655                         STOP
656                 EOF
657                 test_cmp_exclude_clean expected.log rot13-filter.log &&
658
659                 test_cmp_committed_rot13 "$TEST_ROOT/test.o" test.r &&
660                 test_cmp_committed_rot13 "$TEST_ROOT/test2.o" test2.r &&
661                 test_cmp error.o error.r
662         )
663 '
664
665 test_expect_success PERL 'process filter abort stops processing of all further files' '
666         test_config_global filter.protocol.process "$TEST_DIRECTORY/t0021/rot13-filter.pl clean smudge" &&
667         rm -rf repo &&
668         mkdir repo &&
669         (
670                 cd repo &&
671                 git init &&
672
673                 echo "*.r filter=protocol" >.gitattributes &&
674
675                 cp "$TEST_ROOT/test.o" test.r &&
676                 cp "$TEST_ROOT/test2.o" test2.r &&
677                 echo "error this blob and all future blobs" >abort.o &&
678                 cp abort.o abort.r &&
679
680                 SA=$(file_size abort.r) &&
681
682                 git add . &&
683                 rm -f *.r &&
684
685                 # Note: This test assumes that Git filters files in alphabetical
686                 # order ("abort.r" before "test.r").
687                 filter_git checkout --quiet --no-progress . &&
688                 cat >expected.log <<-EOF &&
689                         START
690                         init handshake complete
691                         IN: smudge abort.r $SA [OK] -- OUT: 0 [ABORT]
692                         STOP
693                 EOF
694                 test_cmp_exclude_clean expected.log rot13-filter.log &&
695
696                 test_cmp "$TEST_ROOT/test.o" test.r &&
697                 test_cmp "$TEST_ROOT/test2.o" test2.r &&
698                 test_cmp abort.o abort.r
699         )
700 '
701
702 test_expect_success PERL 'invalid process filter must fail (and not hang!)' '
703         test_config_global filter.protocol.process cat &&
704         test_config_global filter.protocol.required true &&
705         rm -rf repo &&
706         mkdir repo &&
707         (
708                 cd repo &&
709                 git init &&
710
711                 echo "*.r filter=protocol" >.gitattributes &&
712
713                 cp "$TEST_ROOT/test.o" test.r &&
714                 test_must_fail git add . 2>git-stderr.log &&
715                 grep "does not support filter protocol version" git-stderr.log
716         )
717 '
718
719 test_done