diff: correct interaction between --exit-code and -I<pattern>
[git] / t / t4015-diff-whitespace.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2006 Johannes E. Schindelin
4 #
5
6 test_description='Test special whitespace in diff engine.
7
8 '
9 . ./test-lib.sh
10 . "$TEST_DIRECTORY"/diff-lib.sh
11
12 test_expect_success "Ray Lehtiniemi's example" '
13         cat <<-\EOF >x &&
14         do {
15            nothing;
16         } while (0);
17         EOF
18         git update-index --add x &&
19         old_hash_x=$(git hash-object x) &&
20         before=$(git rev-parse --short "$old_hash_x") &&
21
22         cat <<-\EOF >x &&
23         do
24         {
25            nothing;
26         }
27         while (0);
28         EOF
29         new_hash_x=$(git hash-object x) &&
30         after=$(git rev-parse --short "$new_hash_x") &&
31
32         cat <<-EOF >expect &&
33         diff --git a/x b/x
34         index $before..$after 100644
35         --- a/x
36         +++ b/x
37         @@ -1,3 +1,5 @@
38         -do {
39         +do
40         +{
41             nothing;
42         -} while (0);
43         +}
44         +while (0);
45         EOF
46
47         git diff >out &&
48         test_cmp expect out &&
49
50         git diff -w >out &&
51         test_cmp expect out &&
52
53         git diff -b >out &&
54         test_cmp expect out
55 '
56
57 test_expect_success 'another test, without options' '
58         tr Q "\015" <<-\EOF >x &&
59         whitespace at beginning
60         whitespace change
61         whitespace in the middle
62         whitespace at end
63         unchanged line
64         CR at endQ
65         EOF
66
67         git update-index x &&
68         old_hash_x=$(git hash-object x) &&
69         before=$(git rev-parse --short "$old_hash_x") &&
70
71         tr "_" " " <<-\EOF >x &&
72         _       whitespace at beginning
73         whitespace       change
74         white space in the middle
75         whitespace at end__
76         unchanged line
77         CR at end
78         EOF
79         new_hash_x=$(git hash-object x) &&
80         after=$(git rev-parse --short "$new_hash_x") &&
81
82         tr "Q_" "\015 " <<-EOF >expect &&
83         diff --git a/x b/x
84         index $before..$after 100644
85         --- a/x
86         +++ b/x
87         @@ -1,6 +1,6 @@
88         -whitespace at beginning
89         -whitespace change
90         -whitespace in the middle
91         -whitespace at end
92         +       whitespace at beginning
93         +whitespace      change
94         +white space in the middle
95         +whitespace at end__
96          unchanged line
97         -CR at endQ
98         +CR at end
99         EOF
100
101         git diff >out &&
102         test_cmp expect out &&
103
104         git diff -w >out &&
105         test_must_be_empty out &&
106
107         git diff -w -b >out &&
108         test_must_be_empty out &&
109
110         git diff -w --ignore-space-at-eol >out &&
111         test_must_be_empty out &&
112
113         git diff -w -b --ignore-space-at-eol >out &&
114         test_must_be_empty out &&
115
116         git diff -w --ignore-cr-at-eol >out &&
117         test_must_be_empty out &&
118
119         tr "Q_" "\015 " <<-EOF >expect &&
120         diff --git a/x b/x
121         index $before..$after 100644
122         --- a/x
123         +++ b/x
124         @@ -1,6 +1,6 @@
125         -whitespace at beginning
126         +_      whitespace at beginning
127          whitespace      change
128         -whitespace in the middle
129         +white space in the middle
130          whitespace at end__
131          unchanged line
132          CR at end
133         EOF
134         git diff -b >out &&
135         test_cmp expect out &&
136
137         git diff -b --ignore-space-at-eol >out &&
138         test_cmp expect out &&
139
140         git diff -b --ignore-cr-at-eol >out &&
141         test_cmp expect out &&
142
143         tr "Q_" "\015 " <<-EOF >expect &&
144         diff --git a/x b/x
145         index $before..$after 100644
146         --- a/x
147         +++ b/x
148         @@ -1,6 +1,6 @@
149         -whitespace at beginning
150         -whitespace change
151         -whitespace in the middle
152         +_      whitespace at beginning
153         +whitespace      change
154         +white space in the middle
155          whitespace at end__
156          unchanged line
157          CR at end
158         EOF
159         git diff --ignore-space-at-eol >out &&
160         test_cmp expect out &&
161
162         git diff --ignore-space-at-eol --ignore-cr-at-eol >out &&
163         test_cmp expect out &&
164
165         tr "Q_" "\015 " <<-EOF >expect &&
166         diff --git a/x b/x
167         index_$before..$after 100644
168         --- a/x
169         +++ b/x
170         @@ -1,6 +1,6 @@
171         -whitespace at beginning
172         -whitespace change
173         -whitespace in the middle
174         -whitespace at end
175         +_      whitespace at beginning
176         +whitespace_    _change
177         +white space in the middle
178         +whitespace at end__
179          unchanged line
180          CR at end
181         EOF
182         git diff --ignore-cr-at-eol >out &&
183         test_cmp expect out
184 '
185
186 test_expect_success 'ignore-blank-lines: only new lines' '
187         test_seq 5 >x &&
188         git update-index x &&
189         test_seq 5 | sed "/3/i\\
190 " >x &&
191         git diff --ignore-blank-lines >out &&
192         test_must_be_empty out
193 '
194
195 test_expect_success 'ignore-blank-lines: only new lines with space' '
196         test_seq 5 >x &&
197         git update-index x &&
198         test_seq 5 | sed "/3/i\\
199  " >x &&
200         git diff -w --ignore-blank-lines >out &&
201         test_must_be_empty out
202 '
203
204 test_expect_success 'ignore-blank-lines: after change' '
205         cat <<-\EOF >x &&
206         1
207         2
208
209         3
210         4
211         5
212
213         6
214         7
215         EOF
216         git update-index x &&
217         cat <<-\EOF >x &&
218         change
219
220         1
221         2
222         3
223         4
224         5
225         6
226
227         7
228         EOF
229         git diff --inter-hunk-context=100 --ignore-blank-lines >out.tmp &&
230         cat <<-\EOF >expected &&
231         diff --git a/x b/x
232         --- a/x
233         +++ b/x
234         @@ -1,6 +1,7 @@
235         +change
236         +
237          1
238          2
239         -
240          3
241          4
242          5
243         EOF
244         compare_diff_patch expected out.tmp
245 '
246
247 test_expect_success 'ignore-blank-lines: before change' '
248         cat <<-\EOF >x &&
249         1
250         2
251
252         3
253         4
254         5
255         6
256         7
257         EOF
258         git update-index x &&
259         cat <<-\EOF >x &&
260
261         1
262         2
263         3
264         4
265         5
266
267         6
268         7
269         change
270         EOF
271         git diff --inter-hunk-context=100 --ignore-blank-lines >out.tmp &&
272         cat <<-\EOF >expected &&
273         diff --git a/x b/x
274         --- a/x
275         +++ b/x
276         @@ -4,5 +4,7 @@
277          3
278          4
279          5
280         +
281          6
282          7
283         +change
284         EOF
285         compare_diff_patch expected out.tmp
286 '
287
288 test_expect_success 'ignore-blank-lines: between changes' '
289         cat <<-\EOF >x &&
290         1
291         2
292         3
293         4
294         5
295
296
297         6
298         7
299         8
300         9
301         10
302         EOF
303         git update-index x &&
304         cat <<-\EOF >x &&
305         change
306         1
307         2
308
309         3
310         4
311         5
312         6
313         7
314         8
315
316         9
317         10
318         change
319         EOF
320         git diff --ignore-blank-lines >out.tmp &&
321         cat <<-\EOF >expected &&
322         diff --git a/x b/x
323         --- a/x
324         +++ b/x
325         @@ -1,5 +1,7 @@
326         +change
327          1
328          2
329         +
330          3
331          4
332          5
333         @@ -8,5 +8,7 @@
334          6
335          7
336          8
337         +
338          9
339          10
340         +change
341         EOF
342         compare_diff_patch expected out.tmp
343 '
344
345 test_expect_success 'ignore-blank-lines: between changes (with interhunkctx)' '
346         test_seq 10 >x &&
347         git update-index x &&
348         cat <<-\EOF >x &&
349         change
350         1
351         2
352
353         3
354         4
355         5
356
357         6
358         7
359         8
360         9
361
362         10
363         change
364         EOF
365         git diff --inter-hunk-context=2 --ignore-blank-lines >out.tmp &&
366         cat <<-\EOF >expected &&
367         diff --git a/x b/x
368         --- a/x
369         +++ b/x
370         @@ -1,10 +1,15 @@
371         +change
372          1
373          2
374         +
375          3
376          4
377          5
378         +
379          6
380          7
381          8
382          9
383         +
384          10
385         +change
386         EOF
387         compare_diff_patch expected out.tmp
388 '
389
390 test_expect_success 'ignore-blank-lines: scattered spaces' '
391         test_seq 10 >x &&
392         git update-index x &&
393         cat <<-\EOF >x &&
394         change
395         1
396         2
397         3
398
399         4
400
401         5
402
403         6
404
405
406         7
407
408         8
409         9
410         10
411         change
412         EOF
413         git diff --inter-hunk-context=4 --ignore-blank-lines >out.tmp &&
414         cat <<-\EOF >expected &&
415         diff --git a/x b/x
416         --- a/x
417         +++ b/x
418         @@ -1,3 +1,4 @@
419         +change
420          1
421          2
422          3
423         @@ -8,3 +15,4 @@
424          8
425          9
426          10
427         +change
428         EOF
429         compare_diff_patch expected out.tmp
430 '
431
432 test_expect_success 'ignore-blank-lines: spaces coalesce' '
433         test_seq 6 >x &&
434         git update-index x &&
435         cat <<-\EOF >x &&
436         change
437         1
438         2
439         3
440
441         4
442
443         5
444
445         6
446         change
447         EOF
448         git diff --inter-hunk-context=4 --ignore-blank-lines >out.tmp &&
449         cat <<-\EOF >expected &&
450         diff --git a/x b/x
451         --- a/x
452         +++ b/x
453         @@ -1,6 +1,11 @@
454         +change
455          1
456          2
457          3
458         +
459          4
460         +
461          5
462         +
463          6
464         +change
465         EOF
466         compare_diff_patch expected out.tmp
467 '
468
469 test_expect_success 'ignore-blank-lines: mix changes and blank lines' '
470         test_seq 16 >x &&
471         git update-index x &&
472         cat <<-\EOF >x &&
473         change
474         1
475         2
476
477         3
478         4
479         5
480         change
481         6
482         7
483         8
484
485         9
486         10
487         11
488         change
489         12
490         13
491         14
492
493         15
494         16
495         change
496         EOF
497         git diff --ignore-blank-lines >out.tmp &&
498         cat <<-\EOF >expected &&
499         diff --git a/x b/x
500         --- a/x
501         +++ b/x
502         @@ -1,8 +1,11 @@
503         +change
504          1
505          2
506         +
507          3
508          4
509          5
510         +change
511          6
512          7
513          8
514         @@ -9,8 +13,11 @@
515          9
516          10
517          11
518         +change
519          12
520          13
521          14
522         +
523          15
524          16
525         +change
526         EOF
527         compare_diff_patch expected out.tmp
528 '
529
530 test_expect_success 'check mixed spaces and tabs in indent' '
531         # This is indented with SP HT SP.
532         echo "   foo();" >x &&
533         test_must_fail git diff --check >check &&
534         grep "space before tab in indent" check
535 '
536
537 test_expect_success 'check mixed tabs and spaces in indent' '
538         # This is indented with HT SP HT.
539         echo "          foo();" >x &&
540         test_must_fail git diff --check >check &&
541         grep "space before tab in indent" check
542 '
543
544 test_expect_success 'check with no whitespace errors' '
545         git commit -m "snapshot" &&
546         echo "foo();" >x &&
547         git diff --check
548 '
549
550 test_expect_success 'check with trailing whitespace' '
551         echo "foo(); " >x &&
552         test_must_fail git diff --check
553 '
554
555 test_expect_success 'check with space before tab in indent' '
556         # indent has space followed by hard tab
557         echo "  foo();" >x &&
558         test_must_fail git diff --check
559 '
560
561 test_expect_success '--check and --exit-code are not exclusive' '
562         git checkout x &&
563         git diff --check --exit-code
564 '
565
566 test_expect_success '--check and --quiet are not exclusive' '
567         git diff --check --quiet
568 '
569
570 test_expect_success '-w and --exit-code interact sensibly' '
571         test_when_finished "git checkout x" &&
572         {
573                 test_seq 15 &&
574                 echo " 16"
575         } >x &&
576         test_must_fail git diff --exit-code &&
577         git diff -w >actual &&
578         test_must_be_empty actual &&
579         git diff -w --exit-code
580 '
581
582 test_expect_success '-I and --exit-code interact sensibly' '
583         test_when_finished "git checkout x" &&
584         {
585                 test_seq 15 &&
586                 echo " 16"
587         } >x &&
588         test_must_fail git diff --exit-code &&
589         git diff -I. >actual &&
590         test_must_be_empty actual &&
591         git diff -I. --exit-code
592 '
593
594 test_expect_success 'check staged with no whitespace errors' '
595         echo "foo();" >x &&
596         git add x &&
597         git diff --cached --check
598 '
599
600 test_expect_success 'check staged with trailing whitespace' '
601         echo "foo(); " >x &&
602         git add x &&
603         test_must_fail git diff --cached --check
604 '
605
606 test_expect_success 'check staged with space before tab in indent' '
607         # indent has space followed by hard tab
608         echo "  foo();" >x &&
609         git add x &&
610         test_must_fail git diff --cached --check
611 '
612
613 test_expect_success 'check with no whitespace errors (diff-index)' '
614         echo "foo();" >x &&
615         git add x &&
616         git diff-index --check HEAD
617 '
618
619 test_expect_success 'check with trailing whitespace (diff-index)' '
620         echo "foo(); " >x &&
621         git add x &&
622         test_must_fail git diff-index --check HEAD
623 '
624
625 test_expect_success 'check with space before tab in indent (diff-index)' '
626         # indent has space followed by hard tab
627         echo "  foo();" >x &&
628         git add x &&
629         test_must_fail git diff-index --check HEAD
630 '
631
632 test_expect_success 'check staged with no whitespace errors (diff-index)' '
633         echo "foo();" >x &&
634         git add x &&
635         git diff-index --cached --check HEAD
636 '
637
638 test_expect_success 'check staged with trailing whitespace (diff-index)' '
639         echo "foo(); " >x &&
640         git add x &&
641         test_must_fail git diff-index --cached --check HEAD
642 '
643
644 test_expect_success 'check staged with space before tab in indent (diff-index)' '
645         # indent has space followed by hard tab
646         echo "  foo();" >x &&
647         git add x &&
648         test_must_fail git diff-index --cached --check HEAD
649 '
650
651 test_expect_success 'check with no whitespace errors (diff-tree)' '
652         echo "foo();" >x &&
653         git commit -m "new commit" x &&
654         git diff-tree --check HEAD^ HEAD
655 '
656
657 test_expect_success 'check with trailing whitespace (diff-tree)' '
658         echo "foo(); " >x &&
659         git commit -m "another commit" x &&
660         test_must_fail git diff-tree --check HEAD^ HEAD
661 '
662
663 test_expect_success 'check with space before tab in indent (diff-tree)' '
664         # indent has space followed by hard tab
665         echo "  foo();" >x &&
666         git commit -m "yet another" x &&
667         test_must_fail git diff-tree --check HEAD^ HEAD
668 '
669
670 test_expect_success 'check with ignored trailing whitespace attr (diff-tree)' '
671         test_when_finished "git reset --hard HEAD^" &&
672
673         # create a whitespace error that should be ignored
674         echo "* -whitespace" >.gitattributes &&
675         git add .gitattributes &&
676         echo "foo(); " >x &&
677         git add x &&
678         git commit -m "add trailing space" &&
679
680         # with a worktree diff-tree ignores the whitespace error
681         git diff-tree --root --check HEAD &&
682
683         # without a worktree diff-tree still ignores the whitespace error
684         git -C .git diff-tree --root --check HEAD
685 '
686
687 test_expect_success 'check trailing whitespace (trailing-space: off)' '
688         git config core.whitespace "-trailing-space" &&
689         echo "foo ();   " >x &&
690         git diff --check
691 '
692
693 test_expect_success 'check trailing whitespace (trailing-space: on)' '
694         git config core.whitespace "trailing-space" &&
695         echo "foo ();   " >x &&
696         test_must_fail git diff --check
697 '
698
699 test_expect_success 'check space before tab in indent (space-before-tab: off)' '
700         # indent contains space followed by HT
701         git config core.whitespace "-space-before-tab" &&
702         echo "  foo ();" >x &&
703         git diff --check
704 '
705
706 test_expect_success 'check space before tab in indent (space-before-tab: on)' '
707         # indent contains space followed by HT
708         git config core.whitespace "space-before-tab" &&
709         echo "  foo ();   " >x &&
710         test_must_fail git diff --check
711 '
712
713 test_expect_success 'check spaces as indentation (indent-with-non-tab: off)' '
714         git config core.whitespace "-indent-with-non-tab" &&
715         echo "        foo ();" >x &&
716         git diff --check
717 '
718
719 test_expect_success 'check spaces as indentation (indent-with-non-tab: on)' '
720         git config core.whitespace "indent-with-non-tab" &&
721         echo "        foo ();" >x &&
722         test_must_fail git diff --check
723 '
724
725 test_expect_success 'ditto, but tabwidth=9' '
726         git config core.whitespace "indent-with-non-tab,tabwidth=9" &&
727         git diff --check
728 '
729
730 test_expect_success 'check tabs and spaces as indentation (indent-with-non-tab: on)' '
731         git config core.whitespace "indent-with-non-tab" &&
732         echo "                  foo ();" >x &&
733         test_must_fail git diff --check
734 '
735
736 test_expect_success 'ditto, but tabwidth=10' '
737         git config core.whitespace "indent-with-non-tab,tabwidth=10" &&
738         test_must_fail git diff --check
739 '
740
741 test_expect_success 'ditto, but tabwidth=20' '
742         git config core.whitespace "indent-with-non-tab,tabwidth=20" &&
743         git diff --check
744 '
745
746 test_expect_success 'check tabs as indentation (tab-in-indent: off)' '
747         git config core.whitespace "-tab-in-indent" &&
748         echo "  foo ();" >x &&
749         git diff --check
750 '
751
752 test_expect_success 'check tabs as indentation (tab-in-indent: on)' '
753         git config core.whitespace "tab-in-indent" &&
754         echo "  foo ();" >x &&
755         test_must_fail git diff --check
756 '
757
758 test_expect_success 'check tabs and spaces as indentation (tab-in-indent: on)' '
759         git config core.whitespace "tab-in-indent" &&
760         echo "                  foo ();" >x &&
761         test_must_fail git diff --check
762 '
763
764 test_expect_success 'ditto, but tabwidth=1 (must be irrelevant)' '
765         git config core.whitespace "tab-in-indent,tabwidth=1" &&
766         test_must_fail git diff --check
767 '
768
769 test_expect_success 'check tab-in-indent and indent-with-non-tab conflict' '
770         git config core.whitespace "tab-in-indent,indent-with-non-tab" &&
771         echo "foo ();" >x &&
772         test_must_fail git diff --check
773 '
774
775 test_expect_success 'check tab-in-indent excluded from wildcard whitespace attribute' '
776         git config --unset core.whitespace &&
777         echo "x whitespace" >.gitattributes &&
778         echo "    foo ();" >x &&
779         git diff --check &&
780         rm -f .gitattributes
781 '
782
783 test_expect_success 'line numbers in --check output are correct' '
784         echo "" >x &&
785         echo "foo(); " >>x &&
786         test_must_fail git diff --check >check &&
787         grep "x:2:" check
788 '
789
790 test_expect_success 'checkdiff detects new trailing blank lines (1)' '
791         echo "foo();" >x &&
792         echo "" >>x &&
793         test_must_fail git diff --check >check &&
794         grep "new blank line" check
795 '
796
797 test_expect_success 'checkdiff detects new trailing blank lines (2)' '
798         test_write_lines a b "" "" >x &&
799         git add x &&
800         test_write_lines a "" "" "" "" >x &&
801         test_must_fail git diff --check >check &&
802         grep "new blank line" check
803 '
804
805 test_expect_success 'checkdiff allows new blank lines' '
806         git checkout x &&
807         mv x y &&
808         (
809                 echo "/* This is new */" &&
810                 echo "" &&
811                 cat y
812         ) >x &&
813         git diff --check
814 '
815
816 test_expect_success 'whitespace-only changes not reported' '
817         git reset --hard &&
818         echo >x "hello world" &&
819         git add x &&
820         git commit -m "hello 1" &&
821         echo >x "hello  world" &&
822         git diff -b >actual &&
823         test_must_be_empty actual
824 '
825
826 test_expect_success 'whitespace-only changes reported across renames' '
827         git reset --hard &&
828         for i in 1 2 3 4 5 6 7 8 9; do echo "$i$i$i$i$i$i"; done >x &&
829         git add x &&
830         hash_x=$(git hash-object x) &&
831         before=$(git rev-parse --short "$hash_x") &&
832         git commit -m "base" &&
833         sed -e "5s/^/ /" x >z &&
834         git rm x &&
835         git add z &&
836         hash_z=$(git hash-object z) &&
837         after=$(git rev-parse --short "$hash_z") &&
838         git diff -w -M --cached >actual.raw &&
839         sed -e "/^similarity index /s/[0-9][0-9]*/NUM/" actual.raw >actual &&
840         cat <<-EOF >expect &&
841         diff --git a/x b/z
842         similarity index NUM%
843         rename from x
844         rename to z
845         index $before..$after 100644
846         EOF
847         test_cmp expect actual
848 '
849
850 cat >expected <<\EOF
851 diff --git a/empty b/void
852 similarity index 100%
853 rename from empty
854 rename to void
855 EOF
856
857 test_expect_success 'rename empty' '
858         git reset --hard &&
859         >empty &&
860         git add empty &&
861         git commit -m empty &&
862         git mv empty void &&
863         git diff -w --cached -M >current &&
864         test_cmp expected current
865 '
866
867 test_expect_success 'combined diff with autocrlf conversion' '
868
869         git reset --hard &&
870         echo >x hello &&
871         git commit -m "one side" x &&
872         git checkout HEAD^ &&
873         echo >x goodbye &&
874         git commit -m "the other side" x &&
875         git config core.autocrlf true &&
876         test_must_fail git merge master &&
877
878         git diff >actual.raw &&
879         sed -e "1,/^@@@/d" actual.raw >actual &&
880         ! grep "^-" actual
881
882 '
883
884 # Start testing the colored format for whitespace checks
885
886 test_expect_success 'setup diff colors' '
887         git config color.diff.plain normal &&
888         git config color.diff.meta bold &&
889         git config color.diff.frag cyan &&
890         git config color.diff.func normal &&
891         git config color.diff.old red &&
892         git config color.diff.new green &&
893         git config color.diff.commit yellow &&
894         git config color.diff.whitespace blue &&
895
896         git config core.autocrlf false
897 '
898
899 test_expect_success 'diff that introduces a line with only tabs' '
900         git config core.whitespace blank-at-eol &&
901         git reset --hard &&
902         echo "test" >x &&
903         old_hash_x=$(git hash-object x) &&
904         before=$(git rev-parse --short "$old_hash_x") &&
905         git commit -m "initial" x &&
906         echo "{NTN}" | tr "NT" "\n\t" >>x &&
907         new_hash_x=$(git hash-object x) &&
908         after=$(git rev-parse --short "$new_hash_x") &&
909         git diff --color >current.raw &&
910         test_decode_color <current.raw >current &&
911
912         cat >expected <<-EOF &&
913         <BOLD>diff --git a/x b/x<RESET>
914         <BOLD>index $before..$after 100644<RESET>
915         <BOLD>--- a/x<RESET>
916         <BOLD>+++ b/x<RESET>
917         <CYAN>@@ -1 +1,4 @@<RESET>
918          test<RESET>
919         <GREEN>+<RESET><GREEN>{<RESET>
920         <GREEN>+<RESET><BLUE>   <RESET>
921         <GREEN>+<RESET><GREEN>}<RESET>
922         EOF
923
924         test_cmp expected current
925 '
926
927 test_expect_success 'diff that introduces and removes ws breakages' '
928         git reset --hard &&
929         {
930                 echo "0. blank-at-eol " &&
931                 echo "1. blank-at-eol "
932         } >x &&
933         old_hash_x=$(git hash-object x) &&
934         before=$(git rev-parse --short "$old_hash_x") &&
935         git commit -a --allow-empty -m preimage &&
936         {
937                 echo "0. blank-at-eol " &&
938                 echo "1. still-blank-at-eol " &&
939                 echo "2. and a new line "
940         } >x &&
941         new_hash_x=$(git hash-object x) &&
942         after=$(git rev-parse --short "$new_hash_x") &&
943
944         git diff --color >current.raw &&
945         test_decode_color <current.raw >current &&
946
947         cat >expected <<-EOF &&
948         <BOLD>diff --git a/x b/x<RESET>
949         <BOLD>index $before..$after 100644<RESET>
950         <BOLD>--- a/x<RESET>
951         <BOLD>+++ b/x<RESET>
952         <CYAN>@@ -1,2 +1,3 @@<RESET>
953          0. blank-at-eol <RESET>
954         <RED>-1. blank-at-eol <RESET>
955         <GREEN>+<RESET><GREEN>1. still-blank-at-eol<RESET><BLUE> <RESET>
956         <GREEN>+<RESET><GREEN>2. and a new line<RESET><BLUE> <RESET>
957         EOF
958
959         test_cmp expected current
960 '
961
962 test_expect_success 'ws-error-highlight test setup' '
963
964         git reset --hard &&
965         {
966                 echo "0. blank-at-eol " &&
967                 echo "1. blank-at-eol "
968         } >x &&
969         old_hash_x=$(git hash-object x) &&
970         before=$(git rev-parse --short "$old_hash_x") &&
971         git commit -a --allow-empty -m preimage &&
972         {
973                 echo "0. blank-at-eol " &&
974                 echo "1. still-blank-at-eol " &&
975                 echo "2. and a new line "
976         } >x &&
977         new_hash_x=$(git hash-object x) &&
978         after=$(git rev-parse --short "$new_hash_x") &&
979
980         cat >expect.default-old <<-EOF &&
981         <BOLD>diff --git a/x b/x<RESET>
982         <BOLD>index $before..$after 100644<RESET>
983         <BOLD>--- a/x<RESET>
984         <BOLD>+++ b/x<RESET>
985         <CYAN>@@ -1,2 +1,3 @@<RESET>
986          0. blank-at-eol <RESET>
987         <RED>-<RESET><RED>1. blank-at-eol<RESET><BLUE> <RESET>
988         <GREEN>+<RESET><GREEN>1. still-blank-at-eol<RESET><BLUE> <RESET>
989         <GREEN>+<RESET><GREEN>2. and a new line<RESET><BLUE> <RESET>
990         EOF
991
992         cat >expect.all <<-EOF &&
993         <BOLD>diff --git a/x b/x<RESET>
994         <BOLD>index $before..$after 100644<RESET>
995         <BOLD>--- a/x<RESET>
996         <BOLD>+++ b/x<RESET>
997         <CYAN>@@ -1,2 +1,3 @@<RESET>
998          <RESET>0. blank-at-eol<RESET><BLUE> <RESET>
999         <RED>-<RESET><RED>1. blank-at-eol<RESET><BLUE> <RESET>
1000         <GREEN>+<RESET><GREEN>1. still-blank-at-eol<RESET><BLUE> <RESET>
1001         <GREEN>+<RESET><GREEN>2. and a new line<RESET><BLUE> <RESET>
1002         EOF
1003
1004         cat >expect.none <<-EOF
1005         <BOLD>diff --git a/x b/x<RESET>
1006         <BOLD>index $before..$after 100644<RESET>
1007         <BOLD>--- a/x<RESET>
1008         <BOLD>+++ b/x<RESET>
1009         <CYAN>@@ -1,2 +1,3 @@<RESET>
1010          0. blank-at-eol <RESET>
1011         <RED>-1. blank-at-eol <RESET>
1012         <GREEN>+1. still-blank-at-eol <RESET>
1013         <GREEN>+2. and a new line <RESET>
1014         EOF
1015
1016 '
1017
1018 test_expect_success 'test --ws-error-highlight option' '
1019
1020         git diff --color --ws-error-highlight=default,old >current.raw &&
1021         test_decode_color <current.raw >current &&
1022         test_cmp expect.default-old current &&
1023
1024         git diff --color --ws-error-highlight=all >current.raw &&
1025         test_decode_color <current.raw >current &&
1026         test_cmp expect.all current &&
1027
1028         git diff --color --ws-error-highlight=none >current.raw &&
1029         test_decode_color <current.raw >current &&
1030         test_cmp expect.none current
1031
1032 '
1033
1034 test_expect_success 'test diff.wsErrorHighlight config' '
1035
1036         git -c diff.wsErrorHighlight=default,old diff --color >current.raw &&
1037         test_decode_color <current.raw >current &&
1038         test_cmp expect.default-old current &&
1039
1040         git -c diff.wsErrorHighlight=all diff --color >current.raw &&
1041         test_decode_color <current.raw >current &&
1042         test_cmp expect.all current &&
1043
1044         git -c diff.wsErrorHighlight=none diff --color >current.raw &&
1045         test_decode_color <current.raw >current &&
1046         test_cmp expect.none current
1047
1048 '
1049
1050 test_expect_success 'option overrides diff.wsErrorHighlight' '
1051
1052         git -c diff.wsErrorHighlight=none \
1053                 diff --color --ws-error-highlight=default,old >current.raw &&
1054         test_decode_color <current.raw >current &&
1055         test_cmp expect.default-old current &&
1056
1057         git -c diff.wsErrorHighlight=default \
1058                 diff --color --ws-error-highlight=all >current.raw &&
1059         test_decode_color <current.raw >current &&
1060         test_cmp expect.all current &&
1061
1062         git -c diff.wsErrorHighlight=all \
1063                 diff --color --ws-error-highlight=none >current.raw &&
1064         test_decode_color <current.raw >current &&
1065         test_cmp expect.none current
1066
1067 '
1068
1069 test_expect_success 'detect moved code, complete file' '
1070         git reset --hard &&
1071         cat <<-\EOF >test.c &&
1072         #include<stdio.h>
1073         main()
1074         {
1075         printf("Hello World");
1076         }
1077         EOF
1078         git add test.c &&
1079         git commit -m "add main function" &&
1080         file=$(git rev-parse --short HEAD:test.c) &&
1081         git mv test.c main.c &&
1082         test_config color.diff.oldMoved "normal red" &&
1083         test_config color.diff.newMoved "normal green" &&
1084         git diff HEAD --color-moved=zebra --color --no-renames >actual.raw &&
1085         test_decode_color <actual.raw >actual &&
1086         cat >expected <<-EOF &&
1087         <BOLD>diff --git a/main.c b/main.c<RESET>
1088         <BOLD>new file mode 100644<RESET>
1089         <BOLD>index 0000000..$file<RESET>
1090         <BOLD>--- /dev/null<RESET>
1091         <BOLD>+++ b/main.c<RESET>
1092         <CYAN>@@ -0,0 +1,5 @@<RESET>
1093         <BGREEN>+<RESET><BGREEN>#include<stdio.h><RESET>
1094         <BGREEN>+<RESET><BGREEN>main()<RESET>
1095         <BGREEN>+<RESET><BGREEN>{<RESET>
1096         <BGREEN>+<RESET><BGREEN>printf("Hello World");<RESET>
1097         <BGREEN>+<RESET><BGREEN>}<RESET>
1098         <BOLD>diff --git a/test.c b/test.c<RESET>
1099         <BOLD>deleted file mode 100644<RESET>
1100         <BOLD>index $file..0000000<RESET>
1101         <BOLD>--- a/test.c<RESET>
1102         <BOLD>+++ /dev/null<RESET>
1103         <CYAN>@@ -1,5 +0,0 @@<RESET>
1104         <BRED>-#include<stdio.h><RESET>
1105         <BRED>-main()<RESET>
1106         <BRED>-{<RESET>
1107         <BRED>-printf("Hello World");<RESET>
1108         <BRED>-}<RESET>
1109         EOF
1110
1111         test_cmp expected actual
1112 '
1113
1114 test_expect_success 'detect malicious moved code, inside file' '
1115         test_config color.diff.oldMoved "normal red" &&
1116         test_config color.diff.newMoved "normal green" &&
1117         test_config color.diff.oldMovedAlternative "blue" &&
1118         test_config color.diff.newMovedAlternative "yellow" &&
1119         git reset --hard &&
1120         cat <<-\EOF >main.c &&
1121                 #include<stdio.h>
1122                 int stuff()
1123                 {
1124                         printf("Hello ");
1125                         printf("World\n");
1126                 }
1127
1128                 int secure_foo(struct user *u)
1129                 {
1130                         if (!u->is_allowed_foo)
1131                                 return;
1132                         foo(u);
1133                 }
1134
1135                 int main()
1136                 {
1137                         foo();
1138                 }
1139         EOF
1140         cat <<-\EOF >test.c &&
1141                 #include<stdio.h>
1142                 int bar()
1143                 {
1144                         printf("Hello World, but different\n");
1145                 }
1146
1147                 int another_function()
1148                 {
1149                         bar();
1150                 }
1151         EOF
1152         git add main.c test.c &&
1153         git commit -m "add main and test file" &&
1154         before_main=$(git rev-parse --short HEAD:main.c) &&
1155         before_test=$(git rev-parse --short HEAD:test.c) &&
1156         cat <<-\EOF >main.c &&
1157                 #include<stdio.h>
1158                 int stuff()
1159                 {
1160                         printf("Hello ");
1161                         printf("World\n");
1162                 }
1163
1164                 int main()
1165                 {
1166                         foo();
1167                 }
1168         EOF
1169         cat <<-\EOF >test.c &&
1170                 #include<stdio.h>
1171                 int bar()
1172                 {
1173                         printf("Hello World, but different\n");
1174                 }
1175
1176                 int secure_foo(struct user *u)
1177                 {
1178                         foo(u);
1179                         if (!u->is_allowed_foo)
1180                                 return;
1181                 }
1182
1183                 int another_function()
1184                 {
1185                         bar();
1186                 }
1187         EOF
1188         hash_main=$(git hash-object main.c) &&
1189         after_main=$(git rev-parse --short "$hash_main") &&
1190         hash_test=$(git hash-object test.c) &&
1191         after_test=$(git rev-parse --short "$hash_test") &&
1192         git diff HEAD --no-renames --color-moved=zebra --color >actual.raw &&
1193         test_decode_color <actual.raw >actual &&
1194         cat <<-EOF >expected &&
1195         <BOLD>diff --git a/main.c b/main.c<RESET>
1196         <BOLD>index $before_main..$after_main 100644<RESET>
1197         <BOLD>--- a/main.c<RESET>
1198         <BOLD>+++ b/main.c<RESET>
1199         <CYAN>@@ -5,13 +5,6 @@<RESET> <RESET>printf("Hello ");<RESET>
1200          printf("World\n");<RESET>
1201          }<RESET>
1202          <RESET>
1203         <BRED>-int secure_foo(struct user *u)<RESET>
1204         <BRED>-{<RESET>
1205         <BLUE>-if (!u->is_allowed_foo)<RESET>
1206         <BLUE>-return;<RESET>
1207         <RED>-foo(u);<RESET>
1208         <RED>-}<RESET>
1209         <RED>-<RESET>
1210          int main()<RESET>
1211          {<RESET>
1212          foo();<RESET>
1213         <BOLD>diff --git a/test.c b/test.c<RESET>
1214         <BOLD>index $before_test..$after_test 100644<RESET>
1215         <BOLD>--- a/test.c<RESET>
1216         <BOLD>+++ b/test.c<RESET>
1217         <CYAN>@@ -4,6 +4,13 @@<RESET> <RESET>int bar()<RESET>
1218          printf("Hello World, but different\n");<RESET>
1219          }<RESET>
1220          <RESET>
1221         <BGREEN>+<RESET><BGREEN>int secure_foo(struct user *u)<RESET>
1222         <BGREEN>+<RESET><BGREEN>{<RESET>
1223         <GREEN>+<RESET><GREEN>foo(u);<RESET>
1224         <BGREEN>+<RESET><BGREEN>if (!u->is_allowed_foo)<RESET>
1225         <BGREEN>+<RESET><BGREEN>return;<RESET>
1226         <GREEN>+<RESET><GREEN>}<RESET>
1227         <GREEN>+<RESET>
1228          int another_function()<RESET>
1229          {<RESET>
1230          bar();<RESET>
1231         EOF
1232
1233         test_cmp expected actual
1234 '
1235
1236 test_expect_success 'plain moved code, inside file' '
1237         test_config color.diff.oldMoved "normal red" &&
1238         test_config color.diff.newMoved "normal green" &&
1239         test_config color.diff.oldMovedAlternative "blue" &&
1240         test_config color.diff.newMovedAlternative "yellow" &&
1241         # needs previous test as setup
1242         git diff HEAD --no-renames --color-moved=plain --color >actual.raw &&
1243         test_decode_color <actual.raw >actual &&
1244         cat <<-EOF >expected &&
1245         <BOLD>diff --git a/main.c b/main.c<RESET>
1246         <BOLD>index $before_main..$after_main 100644<RESET>
1247         <BOLD>--- a/main.c<RESET>
1248         <BOLD>+++ b/main.c<RESET>
1249         <CYAN>@@ -5,13 +5,6 @@<RESET> <RESET>printf("Hello ");<RESET>
1250          printf("World\n");<RESET>
1251          }<RESET>
1252          <RESET>
1253         <BRED>-int secure_foo(struct user *u)<RESET>
1254         <BRED>-{<RESET>
1255         <BRED>-if (!u->is_allowed_foo)<RESET>
1256         <BRED>-return;<RESET>
1257         <BRED>-foo(u);<RESET>
1258         <BRED>-}<RESET>
1259         <BRED>-<RESET>
1260          int main()<RESET>
1261          {<RESET>
1262          foo();<RESET>
1263         <BOLD>diff --git a/test.c b/test.c<RESET>
1264         <BOLD>index $before_test..$after_test 100644<RESET>
1265         <BOLD>--- a/test.c<RESET>
1266         <BOLD>+++ b/test.c<RESET>
1267         <CYAN>@@ -4,6 +4,13 @@<RESET> <RESET>int bar()<RESET>
1268          printf("Hello World, but different\n");<RESET>
1269          }<RESET>
1270          <RESET>
1271         <BGREEN>+<RESET><BGREEN>int secure_foo(struct user *u)<RESET>
1272         <BGREEN>+<RESET><BGREEN>{<RESET>
1273         <BGREEN>+<RESET><BGREEN>foo(u);<RESET>
1274         <BGREEN>+<RESET><BGREEN>if (!u->is_allowed_foo)<RESET>
1275         <BGREEN>+<RESET><BGREEN>return;<RESET>
1276         <BGREEN>+<RESET><BGREEN>}<RESET>
1277         <BGREEN>+<RESET>
1278          int another_function()<RESET>
1279          {<RESET>
1280          bar();<RESET>
1281         EOF
1282
1283         test_cmp expected actual
1284 '
1285
1286 test_expect_success 'detect blocks of moved code' '
1287         git reset --hard &&
1288         cat <<-\EOF >lines.txt &&
1289                 long line 1
1290                 long line 2
1291                 long line 3
1292                 line 4
1293                 line 5
1294                 line 6
1295                 line 7
1296                 line 8
1297                 line 9
1298                 line 10
1299                 line 11
1300                 line 12
1301                 line 13
1302                 long line 14
1303                 long line 15
1304                 long line 16
1305         EOF
1306         git add lines.txt &&
1307         git commit -m "add poetry" &&
1308         cat <<-\EOF >lines.txt &&
1309                 line 4
1310                 line 5
1311                 line 6
1312                 line 7
1313                 line 8
1314                 line 9
1315                 long line 1
1316                 long line 2
1317                 long line 3
1318                 long line 14
1319                 long line 15
1320                 long line 16
1321                 line 10
1322                 line 11
1323                 line 12
1324                 line 13
1325         EOF
1326         test_config color.diff.oldMoved "magenta" &&
1327         test_config color.diff.newMoved "cyan" &&
1328         test_config color.diff.oldMovedAlternative "blue" &&
1329         test_config color.diff.newMovedAlternative "yellow" &&
1330         test_config color.diff.oldMovedDimmed "normal magenta" &&
1331         test_config color.diff.newMovedDimmed "normal cyan" &&
1332         test_config color.diff.oldMovedAlternativeDimmed "normal blue" &&
1333         test_config color.diff.newMovedAlternativeDimmed "normal yellow" &&
1334         git diff HEAD --no-renames --color-moved=blocks --color >actual.raw &&
1335         grep -v "index" actual.raw | test_decode_color >actual &&
1336         cat <<-\EOF >expected &&
1337         <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1338         <BOLD>--- a/lines.txt<RESET>
1339         <BOLD>+++ b/lines.txt<RESET>
1340         <CYAN>@@ -1,16 +1,16 @@<RESET>
1341         <MAGENTA>-long line 1<RESET>
1342         <MAGENTA>-long line 2<RESET>
1343         <MAGENTA>-long line 3<RESET>
1344          line 4<RESET>
1345          line 5<RESET>
1346          line 6<RESET>
1347          line 7<RESET>
1348          line 8<RESET>
1349          line 9<RESET>
1350         <CYAN>+<RESET><CYAN>long line 1<RESET>
1351         <CYAN>+<RESET><CYAN>long line 2<RESET>
1352         <CYAN>+<RESET><CYAN>long line 3<RESET>
1353         <CYAN>+<RESET><CYAN>long line 14<RESET>
1354         <CYAN>+<RESET><CYAN>long line 15<RESET>
1355         <CYAN>+<RESET><CYAN>long line 16<RESET>
1356          line 10<RESET>
1357          line 11<RESET>
1358          line 12<RESET>
1359          line 13<RESET>
1360         <MAGENTA>-long line 14<RESET>
1361         <MAGENTA>-long line 15<RESET>
1362         <MAGENTA>-long line 16<RESET>
1363         EOF
1364         test_cmp expected actual
1365
1366 '
1367
1368 test_expect_success 'detect permutations inside moved code -- dimmed-zebra' '
1369         # reuse setup from test before!
1370         test_config color.diff.oldMoved "magenta" &&
1371         test_config color.diff.newMoved "cyan" &&
1372         test_config color.diff.oldMovedAlternative "blue" &&
1373         test_config color.diff.newMovedAlternative "yellow" &&
1374         test_config color.diff.oldMovedDimmed "normal magenta" &&
1375         test_config color.diff.newMovedDimmed "normal cyan" &&
1376         test_config color.diff.oldMovedAlternativeDimmed "normal blue" &&
1377         test_config color.diff.newMovedAlternativeDimmed "normal yellow" &&
1378         git diff HEAD --no-renames --color-moved=dimmed-zebra --color >actual.raw &&
1379         grep -v "index" actual.raw | test_decode_color >actual &&
1380         cat <<-\EOF >expected &&
1381         <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1382         <BOLD>--- a/lines.txt<RESET>
1383         <BOLD>+++ b/lines.txt<RESET>
1384         <CYAN>@@ -1,16 +1,16 @@<RESET>
1385         <BMAGENTA>-long line 1<RESET>
1386         <BMAGENTA>-long line 2<RESET>
1387         <BMAGENTA>-long line 3<RESET>
1388          line 4<RESET>
1389          line 5<RESET>
1390          line 6<RESET>
1391          line 7<RESET>
1392          line 8<RESET>
1393          line 9<RESET>
1394         <BCYAN>+<RESET><BCYAN>long line 1<RESET>
1395         <BCYAN>+<RESET><BCYAN>long line 2<RESET>
1396         <CYAN>+<RESET><CYAN>long line 3<RESET>
1397         <YELLOW>+<RESET><YELLOW>long line 14<RESET>
1398         <BYELLOW>+<RESET><BYELLOW>long line 15<RESET>
1399         <BYELLOW>+<RESET><BYELLOW>long line 16<RESET>
1400          line 10<RESET>
1401          line 11<RESET>
1402          line 12<RESET>
1403          line 13<RESET>
1404         <BMAGENTA>-long line 14<RESET>
1405         <BMAGENTA>-long line 15<RESET>
1406         <BMAGENTA>-long line 16<RESET>
1407         EOF
1408         test_cmp expected actual
1409 '
1410
1411 test_expect_success 'cmd option assumes configured colored-moved' '
1412         test_config color.diff.oldMoved "magenta" &&
1413         test_config color.diff.newMoved "cyan" &&
1414         test_config color.diff.oldMovedAlternative "blue" &&
1415         test_config color.diff.newMovedAlternative "yellow" &&
1416         test_config color.diff.oldMovedDimmed "normal magenta" &&
1417         test_config color.diff.newMovedDimmed "normal cyan" &&
1418         test_config color.diff.oldMovedAlternativeDimmed "normal blue" &&
1419         test_config color.diff.newMovedAlternativeDimmed "normal yellow" &&
1420         test_config diff.colorMoved zebra &&
1421         git diff HEAD --no-renames --color-moved --color >actual.raw &&
1422         grep -v "index" actual.raw | test_decode_color >actual &&
1423         cat <<-\EOF >expected &&
1424         <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1425         <BOLD>--- a/lines.txt<RESET>
1426         <BOLD>+++ b/lines.txt<RESET>
1427         <CYAN>@@ -1,16 +1,16 @@<RESET>
1428         <MAGENTA>-long line 1<RESET>
1429         <MAGENTA>-long line 2<RESET>
1430         <MAGENTA>-long line 3<RESET>
1431          line 4<RESET>
1432          line 5<RESET>
1433          line 6<RESET>
1434          line 7<RESET>
1435          line 8<RESET>
1436          line 9<RESET>
1437         <CYAN>+<RESET><CYAN>long line 1<RESET>
1438         <CYAN>+<RESET><CYAN>long line 2<RESET>
1439         <CYAN>+<RESET><CYAN>long line 3<RESET>
1440         <YELLOW>+<RESET><YELLOW>long line 14<RESET>
1441         <YELLOW>+<RESET><YELLOW>long line 15<RESET>
1442         <YELLOW>+<RESET><YELLOW>long line 16<RESET>
1443          line 10<RESET>
1444          line 11<RESET>
1445          line 12<RESET>
1446          line 13<RESET>
1447         <MAGENTA>-long line 14<RESET>
1448         <MAGENTA>-long line 15<RESET>
1449         <MAGENTA>-long line 16<RESET>
1450         EOF
1451         test_cmp expected actual
1452 '
1453
1454 test_expect_success 'no effect from --color-moved with --word-diff' '
1455         cat <<-\EOF >text.txt &&
1456         Lorem Ipsum is simply dummy text of the printing and typesetting industry.
1457         EOF
1458         git add text.txt &&
1459         git commit -a -m "clean state" &&
1460         cat <<-\EOF >text.txt &&
1461         simply Lorem Ipsum dummy is text of the typesetting and printing industry.
1462         EOF
1463         git diff --color-moved --word-diff >actual &&
1464         git diff --word-diff >expect &&
1465         test_cmp expect actual
1466 '
1467
1468 test_expect_success 'set up whitespace tests' '
1469         git reset --hard &&
1470         # Note that these lines have no leading or trailing whitespace.
1471         cat <<-\EOF >lines.txt &&
1472         line 1
1473         line 2
1474         line 3
1475         line 4
1476         line 5
1477         long line 6
1478         long line 7
1479         long line 8
1480         long line 9
1481         EOF
1482         git add lines.txt &&
1483         git commit -m "add poetry" &&
1484         git config color.diff.oldMoved "magenta" &&
1485         git config color.diff.newMoved "cyan"
1486 '
1487
1488 test_expect_success 'move detection ignoring whitespace ' '
1489         q_to_tab <<-\EOF >lines.txt &&
1490         Qlong line 6
1491         Qlong line 7
1492         Qlong line 8
1493         Qchanged long line 9
1494         line 1
1495         line 2
1496         line 3
1497         line 4
1498         line 5
1499         EOF
1500         git diff HEAD --no-renames --color-moved --color >actual.raw &&
1501         grep -v "index" actual.raw | test_decode_color >actual &&
1502         cat <<-\EOF >expected &&
1503         <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1504         <BOLD>--- a/lines.txt<RESET>
1505         <BOLD>+++ b/lines.txt<RESET>
1506         <CYAN>@@ -1,9 +1,9 @@<RESET>
1507         <GREEN>+<RESET> <GREEN>long line 6<RESET>
1508         <GREEN>+<RESET> <GREEN>long line 7<RESET>
1509         <GREEN>+<RESET> <GREEN>long line 8<RESET>
1510         <GREEN>+<RESET> <GREEN>changed long line 9<RESET>
1511          line 1<RESET>
1512          line 2<RESET>
1513          line 3<RESET>
1514          line 4<RESET>
1515          line 5<RESET>
1516         <RED>-long line 6<RESET>
1517         <RED>-long line 7<RESET>
1518         <RED>-long line 8<RESET>
1519         <RED>-long line 9<RESET>
1520         EOF
1521         test_cmp expected actual &&
1522
1523         git diff HEAD --no-renames --color-moved --color \
1524                 --color-moved-ws=ignore-all-space >actual.raw &&
1525         grep -v "index" actual.raw | test_decode_color >actual &&
1526         cat <<-\EOF >expected &&
1527         <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1528         <BOLD>--- a/lines.txt<RESET>
1529         <BOLD>+++ b/lines.txt<RESET>
1530         <CYAN>@@ -1,9 +1,9 @@<RESET>
1531         <CYAN>+<RESET>  <CYAN>long line 6<RESET>
1532         <CYAN>+<RESET>  <CYAN>long line 7<RESET>
1533         <CYAN>+<RESET>  <CYAN>long line 8<RESET>
1534         <GREEN>+<RESET> <GREEN>changed long line 9<RESET>
1535          line 1<RESET>
1536          line 2<RESET>
1537          line 3<RESET>
1538          line 4<RESET>
1539          line 5<RESET>
1540         <MAGENTA>-long line 6<RESET>
1541         <MAGENTA>-long line 7<RESET>
1542         <MAGENTA>-long line 8<RESET>
1543         <RED>-long line 9<RESET>
1544         EOF
1545         test_cmp expected actual
1546 '
1547
1548 test_expect_success 'move detection ignoring whitespace changes' '
1549         git reset --hard &&
1550         # Lines 6-8 have a space change, but 9 is new whitespace
1551         q_to_tab <<-\EOF >lines.txt &&
1552         longQline 6
1553         longQline 7
1554         longQline 8
1555         long liQne 9
1556         line 1
1557         line 2
1558         line 3
1559         line 4
1560         line 5
1561         EOF
1562
1563         git diff HEAD --no-renames --color-moved --color >actual.raw &&
1564         grep -v "index" actual.raw | test_decode_color >actual &&
1565         cat <<-\EOF >expected &&
1566         <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1567         <BOLD>--- a/lines.txt<RESET>
1568         <BOLD>+++ b/lines.txt<RESET>
1569         <CYAN>@@ -1,9 +1,9 @@<RESET>
1570         <GREEN>+<RESET><GREEN>long      line 6<RESET>
1571         <GREEN>+<RESET><GREEN>long      line 7<RESET>
1572         <GREEN>+<RESET><GREEN>long      line 8<RESET>
1573         <GREEN>+<RESET><GREEN>long li   ne 9<RESET>
1574          line 1<RESET>
1575          line 2<RESET>
1576          line 3<RESET>
1577          line 4<RESET>
1578          line 5<RESET>
1579         <RED>-long line 6<RESET>
1580         <RED>-long line 7<RESET>
1581         <RED>-long line 8<RESET>
1582         <RED>-long line 9<RESET>
1583         EOF
1584         test_cmp expected actual &&
1585
1586         git diff HEAD --no-renames --color-moved --color \
1587                 --color-moved-ws=ignore-space-change >actual.raw &&
1588         grep -v "index" actual.raw | test_decode_color >actual &&
1589         cat <<-\EOF >expected &&
1590         <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1591         <BOLD>--- a/lines.txt<RESET>
1592         <BOLD>+++ b/lines.txt<RESET>
1593         <CYAN>@@ -1,9 +1,9 @@<RESET>
1594         <CYAN>+<RESET><CYAN>long        line 6<RESET>
1595         <CYAN>+<RESET><CYAN>long        line 7<RESET>
1596         <CYAN>+<RESET><CYAN>long        line 8<RESET>
1597         <GREEN>+<RESET><GREEN>long li   ne 9<RESET>
1598          line 1<RESET>
1599          line 2<RESET>
1600          line 3<RESET>
1601          line 4<RESET>
1602          line 5<RESET>
1603         <MAGENTA>-long line 6<RESET>
1604         <MAGENTA>-long line 7<RESET>
1605         <MAGENTA>-long line 8<RESET>
1606         <RED>-long line 9<RESET>
1607         EOF
1608         test_cmp expected actual
1609 '
1610
1611 test_expect_success 'move detection ignoring whitespace at eol' '
1612         git reset --hard &&
1613         # Lines 6-9 have new eol whitespace, but 9 also has it in the middle
1614         q_to_tab <<-\EOF >lines.txt &&
1615         long line 6Q
1616         long line 7Q
1617         long line 8Q
1618         longQline 9Q
1619         line 1
1620         line 2
1621         line 3
1622         line 4
1623         line 5
1624         EOF
1625
1626         # avoid cluttering the output with complaints about our eol whitespace
1627         test_config core.whitespace -blank-at-eol &&
1628
1629         git diff HEAD --no-renames --color-moved --color >actual.raw &&
1630         grep -v "index" actual.raw | test_decode_color >actual &&
1631         cat <<-\EOF >expected &&
1632         <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1633         <BOLD>--- a/lines.txt<RESET>
1634         <BOLD>+++ b/lines.txt<RESET>
1635         <CYAN>@@ -1,9 +1,9 @@<RESET>
1636         <GREEN>+<RESET><GREEN>long line 6       <RESET>
1637         <GREEN>+<RESET><GREEN>long line 7       <RESET>
1638         <GREEN>+<RESET><GREEN>long line 8       <RESET>
1639         <GREEN>+<RESET><GREEN>long      line 9  <RESET>
1640          line 1<RESET>
1641          line 2<RESET>
1642          line 3<RESET>
1643          line 4<RESET>
1644          line 5<RESET>
1645         <RED>-long line 6<RESET>
1646         <RED>-long line 7<RESET>
1647         <RED>-long line 8<RESET>
1648         <RED>-long line 9<RESET>
1649         EOF
1650         test_cmp expected actual &&
1651
1652         git diff HEAD --no-renames --color-moved --color \
1653                 --color-moved-ws=ignore-space-at-eol >actual.raw &&
1654         grep -v "index" actual.raw | test_decode_color >actual &&
1655         cat <<-\EOF >expected &&
1656         <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1657         <BOLD>--- a/lines.txt<RESET>
1658         <BOLD>+++ b/lines.txt<RESET>
1659         <CYAN>@@ -1,9 +1,9 @@<RESET>
1660         <CYAN>+<RESET><CYAN>long line 6 <RESET>
1661         <CYAN>+<RESET><CYAN>long line 7 <RESET>
1662         <CYAN>+<RESET><CYAN>long line 8 <RESET>
1663         <GREEN>+<RESET><GREEN>long      line 9  <RESET>
1664          line 1<RESET>
1665          line 2<RESET>
1666          line 3<RESET>
1667          line 4<RESET>
1668          line 5<RESET>
1669         <MAGENTA>-long line 6<RESET>
1670         <MAGENTA>-long line 7<RESET>
1671         <MAGENTA>-long line 8<RESET>
1672         <RED>-long line 9<RESET>
1673         EOF
1674         test_cmp expected actual
1675 '
1676
1677 test_expect_success 'clean up whitespace-test colors' '
1678         git config --unset color.diff.oldMoved &&
1679         git config --unset color.diff.newMoved
1680 '
1681
1682 test_expect_success '--color-moved block at end of diff output respects MIN_ALNUM_COUNT' '
1683         git reset --hard &&
1684         >bar &&
1685         cat <<-\EOF >foo &&
1686         irrelevant_line
1687         line1
1688         EOF
1689         git add foo bar &&
1690         git commit -m x &&
1691
1692         cat <<-\EOF >bar &&
1693         line1
1694         EOF
1695         cat <<-\EOF >foo &&
1696         irrelevant_line
1697         EOF
1698
1699         git diff HEAD --color-moved=zebra --color --no-renames >actual.raw &&
1700         grep -v "index" actual.raw | test_decode_color >actual &&
1701         cat >expected <<-\EOF &&
1702         <BOLD>diff --git a/bar b/bar<RESET>
1703         <BOLD>--- a/bar<RESET>
1704         <BOLD>+++ b/bar<RESET>
1705         <CYAN>@@ -0,0 +1 @@<RESET>
1706         <GREEN>+<RESET><GREEN>line1<RESET>
1707         <BOLD>diff --git a/foo b/foo<RESET>
1708         <BOLD>--- a/foo<RESET>
1709         <BOLD>+++ b/foo<RESET>
1710         <CYAN>@@ -1,2 +1 @@<RESET>
1711          irrelevant_line<RESET>
1712         <RED>-line1<RESET>
1713         EOF
1714
1715         test_cmp expected actual
1716 '
1717
1718 test_expect_success '--color-moved respects MIN_ALNUM_COUNT' '
1719         git reset --hard &&
1720         cat <<-\EOF >foo &&
1721         nineteen chars 456789
1722         irrelevant_line
1723         twenty chars 234567890
1724         EOF
1725         >bar &&
1726         git add foo bar &&
1727         git commit -m x &&
1728
1729         cat <<-\EOF >foo &&
1730         irrelevant_line
1731         EOF
1732         cat <<-\EOF >bar &&
1733         twenty chars 234567890
1734         nineteen chars 456789
1735         EOF
1736
1737         git diff HEAD --color-moved=zebra --color --no-renames >actual.raw &&
1738         grep -v "index" actual.raw | test_decode_color >actual &&
1739         cat >expected <<-\EOF &&
1740         <BOLD>diff --git a/bar b/bar<RESET>
1741         <BOLD>--- a/bar<RESET>
1742         <BOLD>+++ b/bar<RESET>
1743         <CYAN>@@ -0,0 +1,2 @@<RESET>
1744         <BOLD;CYAN>+<RESET><BOLD;CYAN>twenty chars 234567890<RESET>
1745         <GREEN>+<RESET><GREEN>nineteen chars 456789<RESET>
1746         <BOLD>diff --git a/foo b/foo<RESET>
1747         <BOLD>--- a/foo<RESET>
1748         <BOLD>+++ b/foo<RESET>
1749         <CYAN>@@ -1,3 +1 @@<RESET>
1750         <RED>-nineteen chars 456789<RESET>
1751          irrelevant_line<RESET>
1752         <BOLD;MAGENTA>-twenty chars 234567890<RESET>
1753         EOF
1754
1755         test_cmp expected actual
1756 '
1757
1758 test_expect_success '--color-moved treats adjacent blocks as separate for MIN_ALNUM_COUNT' '
1759         git reset --hard &&
1760         cat <<-\EOF >foo &&
1761         7charsA
1762         irrelevant_line
1763         7charsB
1764         7charsC
1765         EOF
1766         >bar &&
1767         git add foo bar &&
1768         git commit -m x &&
1769
1770         cat <<-\EOF >foo &&
1771         irrelevant_line
1772         EOF
1773         cat <<-\EOF >bar &&
1774         7charsB
1775         7charsC
1776         7charsA
1777         EOF
1778
1779         git diff HEAD --color-moved=zebra --color --no-renames >actual.raw &&
1780         grep -v "index" actual.raw | test_decode_color >actual &&
1781         cat >expected <<-\EOF &&
1782         <BOLD>diff --git a/bar b/bar<RESET>
1783         <BOLD>--- a/bar<RESET>
1784         <BOLD>+++ b/bar<RESET>
1785         <CYAN>@@ -0,0 +1,3 @@<RESET>
1786         <GREEN>+<RESET><GREEN>7charsB<RESET>
1787         <GREEN>+<RESET><GREEN>7charsC<RESET>
1788         <GREEN>+<RESET><GREEN>7charsA<RESET>
1789         <BOLD>diff --git a/foo b/foo<RESET>
1790         <BOLD>--- a/foo<RESET>
1791         <BOLD>+++ b/foo<RESET>
1792         <CYAN>@@ -1,4 +1 @@<RESET>
1793         <RED>-7charsA<RESET>
1794          irrelevant_line<RESET>
1795         <RED>-7charsB<RESET>
1796         <RED>-7charsC<RESET>
1797         EOF
1798
1799         test_cmp expected actual
1800 '
1801
1802 test_expect_success 'move detection with submodules' '
1803         test_create_repo bananas &&
1804         echo ripe >bananas/recipe &&
1805         git -C bananas add recipe &&
1806         test_commit fruit &&
1807         test_commit -C bananas recipe &&
1808         git submodule add ./bananas &&
1809         git add bananas &&
1810         git commit -a -m "bananas are like a heavy library?" &&
1811         echo foul >bananas/recipe &&
1812         echo ripe >fruit.t &&
1813
1814         git diff --submodule=diff --color-moved --color >actual &&
1815
1816         # no move detection as the moved line is across repository boundaries.
1817         test_decode_color <actual >decoded_actual &&
1818         ! grep BGREEN decoded_actual &&
1819         ! grep BRED decoded_actual &&
1820
1821         # nor did we mess with it another way
1822         git diff --submodule=diff --color >expect.raw &&
1823         test_decode_color <expect.raw >expect &&
1824         test_cmp expect decoded_actual &&
1825         rm -rf bananas &&
1826         git submodule deinit bananas
1827 '
1828
1829 test_expect_success 'only move detection ignores white spaces' '
1830         git reset --hard &&
1831         q_to_tab <<-\EOF >text.txt &&
1832                 a long line to exceed per-line minimum
1833                 another long line to exceed per-line minimum
1834                 original file
1835         EOF
1836         git add text.txt &&
1837         git commit -m "add text" &&
1838         q_to_tab <<-\EOF >text.txt &&
1839                 Qa long line to exceed per-line minimum
1840                 Qanother long line to exceed per-line minimum
1841                 new file
1842         EOF
1843
1844         # Make sure we get a different diff using -w
1845         git diff --color --color-moved -w >actual.raw &&
1846         grep -v "index" actual.raw | test_decode_color >actual &&
1847         q_to_tab <<-\EOF >expected &&
1848         <BOLD>diff --git a/text.txt b/text.txt<RESET>
1849         <BOLD>--- a/text.txt<RESET>
1850         <BOLD>+++ b/text.txt<RESET>
1851         <CYAN>@@ -1,3 +1,3 @@<RESET>
1852          Qa long line to exceed per-line minimum<RESET>
1853          Qanother long line to exceed per-line minimum<RESET>
1854         <RED>-original file<RESET>
1855         <GREEN>+<RESET><GREEN>new file<RESET>
1856         EOF
1857         test_cmp expected actual &&
1858
1859         # And now ignoring white space only in the move detection
1860         git diff --color --color-moved \
1861                 --color-moved-ws=ignore-all-space,ignore-space-change,ignore-space-at-eol >actual.raw &&
1862         grep -v "index" actual.raw | test_decode_color >actual &&
1863         q_to_tab <<-\EOF >expected &&
1864         <BOLD>diff --git a/text.txt b/text.txt<RESET>
1865         <BOLD>--- a/text.txt<RESET>
1866         <BOLD>+++ b/text.txt<RESET>
1867         <CYAN>@@ -1,3 +1,3 @@<RESET>
1868         <BOLD;MAGENTA>-a long line to exceed per-line minimum<RESET>
1869         <BOLD;MAGENTA>-another long line to exceed per-line minimum<RESET>
1870         <RED>-original file<RESET>
1871         <BOLD;CYAN>+<RESET>Q<BOLD;CYAN>a long line to exceed per-line minimum<RESET>
1872         <BOLD;CYAN>+<RESET>Q<BOLD;CYAN>another long line to exceed per-line minimum<RESET>
1873         <GREEN>+<RESET><GREEN>new file<RESET>
1874         EOF
1875         test_cmp expected actual
1876 '
1877
1878 test_expect_success 'compare whitespace delta across moved blocks' '
1879
1880         git reset --hard &&
1881         q_to_tab <<-\EOF >text.txt &&
1882         QIndented
1883         QText across
1884         Qsome lines
1885         QBut! <- this stands out
1886         QAdjusting with
1887         QQdifferent starting
1888         Qwhite spaces
1889         QAnother outlier
1890         QQQIndented
1891         QQQText across
1892         QQQfive lines
1893         QQQthat has similar lines
1894         QQQto previous blocks, but with different indent
1895         QQQYetQAnotherQoutlierQ
1896         QLine with internal w h i t e s p a c e change
1897         EOF
1898
1899         git add text.txt &&
1900         git commit -m "add text.txt" &&
1901
1902         q_to_tab <<-\EOF >text.txt &&
1903         QQIndented
1904         QQText across
1905         QQsome lines
1906         QQQBut! <- this stands out
1907         Adjusting with
1908         Qdifferent starting
1909         white spaces
1910         AnotherQoutlier
1911         QQIndented
1912         QQText across
1913         QQfive lines
1914         QQthat has similar lines
1915         QQto previous blocks, but with different indent
1916         QQYetQAnotherQoutlier
1917         QLine with internal whitespace change
1918         EOF
1919
1920         git diff --color --color-moved --color-moved-ws=allow-indentation-change >actual.raw &&
1921         grep -v "index" actual.raw | test_decode_color >actual &&
1922
1923         q_to_tab <<-\EOF >expected &&
1924                 <BOLD>diff --git a/text.txt b/text.txt<RESET>
1925                 <BOLD>--- a/text.txt<RESET>
1926                 <BOLD>+++ b/text.txt<RESET>
1927                 <CYAN>@@ -1,15 +1,15 @@<RESET>
1928                 <BOLD;MAGENTA>-QIndented<RESET>
1929                 <BOLD;MAGENTA>-QText across<RESET>
1930                 <BOLD;MAGENTA>-Qsome lines<RESET>
1931                 <RED>-QBut! <- this stands out<RESET>
1932                 <BOLD;MAGENTA>-QAdjusting with<RESET>
1933                 <BOLD;MAGENTA>-QQdifferent starting<RESET>
1934                 <BOLD;MAGENTA>-Qwhite spaces<RESET>
1935                 <RED>-QAnother outlier<RESET>
1936                 <BOLD;MAGENTA>-QQQIndented<RESET>
1937                 <BOLD;MAGENTA>-QQQText across<RESET>
1938                 <BOLD;MAGENTA>-QQQfive lines<RESET>
1939                 <BOLD;MAGENTA>-QQQthat has similar lines<RESET>
1940                 <BOLD;MAGENTA>-QQQto previous blocks, but with different indent<RESET>
1941                 <RED>-QQQYetQAnotherQoutlierQ<RESET>
1942                 <RED>-QLine with internal w h i t e s p a c e change<RESET>
1943                 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>Indented<RESET>
1944                 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>Text across<RESET>
1945                 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>some lines<RESET>
1946                 <GREEN>+<RESET>QQQ<GREEN>But! <- this stands out<RESET>
1947                 <BOLD;CYAN>+<RESET><BOLD;CYAN>Adjusting with<RESET>
1948                 <BOLD;CYAN>+<RESET>Q<BOLD;CYAN>different starting<RESET>
1949                 <BOLD;CYAN>+<RESET><BOLD;CYAN>white spaces<RESET>
1950                 <GREEN>+<RESET><GREEN>AnotherQoutlier<RESET>
1951                 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>Indented<RESET>
1952                 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>Text across<RESET>
1953                 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>five lines<RESET>
1954                 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>that has similar lines<RESET>
1955                 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>to previous blocks, but with different indent<RESET>
1956                 <GREEN>+<RESET>QQ<GREEN>YetQAnotherQoutlier<RESET>
1957                 <GREEN>+<RESET>Q<GREEN>Line with internal whitespace change<RESET>
1958         EOF
1959
1960         test_cmp expected actual
1961 '
1962
1963 test_expect_success 'bogus settings in move detection erroring out' '
1964         test_must_fail git diff --color-moved=bogus 2>err &&
1965         test_i18ngrep "must be one of" err &&
1966         test_i18ngrep bogus err &&
1967
1968         test_must_fail git -c diff.colormoved=bogus diff 2>err &&
1969         test_i18ngrep "must be one of" err &&
1970         test_i18ngrep "from command-line config" err &&
1971
1972         test_must_fail git diff --color-moved-ws=bogus 2>err &&
1973         test_i18ngrep "possible values" err &&
1974         test_i18ngrep bogus err &&
1975
1976         test_must_fail git -c diff.colormovedws=bogus diff 2>err &&
1977         test_i18ngrep "possible values" err &&
1978         test_i18ngrep "from command-line config" err
1979 '
1980
1981 test_expect_success 'compare whitespace delta incompatible with other space options' '
1982         test_must_fail git diff \
1983                 --color-moved-ws=allow-indentation-change,ignore-all-space \
1984                 2>err &&
1985         test_i18ngrep allow-indentation-change err
1986 '
1987
1988 EMPTY=''
1989 test_expect_success 'compare mixed whitespace delta across moved blocks' '
1990
1991         git reset --hard &&
1992         tr Q_ "\t " <<-EOF >text.txt &&
1993         ${EMPTY}
1994         ____too short without
1995         ${EMPTY}
1996         ___being grouped across blank line
1997         ${EMPTY}
1998         context
1999         lines
2000         to
2001         anchor
2002         ____Indented text to
2003         _Q____be further indented by four spaces across
2004         ____Qseveral lines
2005         QQ____These two lines have had their
2006         ____indentation reduced by four spaces
2007         Qdifferent indentation change
2008         ____too short
2009         EOF
2010
2011         git add text.txt &&
2012         git commit -m "add text.txt" &&
2013
2014         tr Q_ "\t " <<-EOF >text.txt &&
2015         context
2016         lines
2017         to
2018         anchor
2019         QIndented text to
2020         QQbe further indented by four spaces across
2021         Q____several lines
2022         ${EMPTY}
2023         QQtoo short without
2024         ${EMPTY}
2025         Q_______being grouped across blank line
2026         ${EMPTY}
2027         Q_QThese two lines have had their
2028         indentation reduced by four spaces
2029         QQdifferent indentation change
2030         __Qtoo short
2031         EOF
2032
2033         git -c color.diff.whitespace="normal red" \
2034                 -c core.whitespace=space-before-tab \
2035                 diff --color --color-moved --ws-error-highlight=all \
2036                 --color-moved-ws=allow-indentation-change >actual.raw &&
2037         grep -v "index" actual.raw | test_decode_color >actual &&
2038
2039         cat <<-\EOF >expected &&
2040         <BOLD>diff --git a/text.txt b/text.txt<RESET>
2041         <BOLD>--- a/text.txt<RESET>
2042         <BOLD>+++ b/text.txt<RESET>
2043         <CYAN>@@ -1,16 +1,16 @@<RESET>
2044         <BOLD;MAGENTA>-<RESET>
2045         <BOLD;MAGENTA>-<RESET><BOLD;MAGENTA>    too short without<RESET>
2046         <BOLD;MAGENTA>-<RESET>
2047         <BOLD;MAGENTA>-<RESET><BOLD;MAGENTA>   being grouped across blank line<RESET>
2048         <BOLD;MAGENTA>-<RESET>
2049          <RESET>context<RESET>
2050          <RESET>lines<RESET>
2051          <RESET>to<RESET>
2052          <RESET>anchor<RESET>
2053         <BOLD;MAGENTA>-<RESET><BOLD;MAGENTA>    Indented text to<RESET>
2054         <BOLD;MAGENTA>-<RESET><BRED> <RESET>    <BOLD;MAGENTA>    be further indented by four spaces across<RESET>
2055         <BOLD;MAGENTA>-<RESET><BRED>    <RESET> <BOLD;MAGENTA>several lines<RESET>
2056         <BOLD;BLUE>-<RESET>             <BOLD;BLUE>    These two lines have had their<RESET>
2057         <BOLD;BLUE>-<RESET><BOLD;BLUE>    indentation reduced by four spaces<RESET>
2058         <BOLD;MAGENTA>-<RESET>  <BOLD;MAGENTA>different indentation change<RESET>
2059         <RED>-<RESET><RED>    too short<RESET>
2060         <BOLD;CYAN>+<RESET>     <BOLD;CYAN>Indented text to<RESET>
2061         <BOLD;CYAN>+<RESET>             <BOLD;CYAN>be further indented by four spaces across<RESET>
2062         <BOLD;CYAN>+<RESET>     <BOLD;CYAN>    several lines<RESET>
2063         <BOLD;YELLOW>+<RESET>
2064         <BOLD;YELLOW>+<RESET>           <BOLD;YELLOW>too short without<RESET>
2065         <BOLD;YELLOW>+<RESET>
2066         <BOLD;YELLOW>+<RESET>   <BOLD;YELLOW>       being grouped across blank line<RESET>
2067         <BOLD;YELLOW>+<RESET>
2068         <BOLD;CYAN>+<RESET>     <BRED> <RESET>  <BOLD;CYAN>These two lines have had their<RESET>
2069         <BOLD;CYAN>+<RESET><BOLD;CYAN>indentation reduced by four spaces<RESET>
2070         <BOLD;YELLOW>+<RESET>           <BOLD;YELLOW>different indentation change<RESET>
2071         <GREEN>+<RESET><BRED>  <RESET>  <GREEN>too short<RESET>
2072         EOF
2073
2074         test_cmp expected actual
2075 '
2076
2077 test_expect_success 'combine --ignore-blank-lines with --function-context' '
2078         test_write_lines 1 "" 2 3 4 5 >a &&
2079         test_write_lines 1    2 3 4   >b &&
2080         test_must_fail git diff --no-index \
2081                 --ignore-blank-lines --function-context a b >actual.raw &&
2082         sed -n "/@@/,\$p" <actual.raw >actual &&
2083         cat <<-\EOF >expect &&
2084         @@ -1,6 +1,4 @@
2085          1
2086         -
2087          2
2088          3
2089          4
2090         -5
2091         EOF
2092         test_cmp expect actual
2093 '
2094
2095 test_expect_success 'combine --ignore-blank-lines with --function-context 2' '
2096         test_write_lines    a b c "" function 1 2 3 4 5 "" 6 7 8 9 >a &&
2097         test_write_lines "" a b c "" function 1 2 3 4 5    6 7 8   >b &&
2098         test_must_fail git diff --no-index \
2099                 --ignore-blank-lines --function-context a b >actual.raw &&
2100         sed -n "/@@/,\$p" <actual.raw >actual &&
2101         cat <<-\EOF >expect &&
2102         @@ -5,11 +6,9 @@ c
2103          function
2104          1
2105          2
2106          3
2107          4
2108          5
2109         -
2110          6
2111          7
2112          8
2113         -9
2114         EOF
2115         test_cmp expect actual
2116 '
2117
2118 test_done