config: unify code paths to get global config paths
[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"/lib-diff.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 (diff)' '
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 not reported (diffstat)' '
827         # reuse state from previous test
828         git diff --stat -b >actual &&
829         test_must_be_empty actual
830 '
831
832 test_expect_success 'whitespace changes with modification reported (diffstat)' '
833         git reset --hard &&
834         echo >x "hello  world" &&
835         git update-index --chmod=+x x &&
836         git diff --stat --cached -b >actual &&
837         cat <<-EOF >expect &&
838          x | 0
839          1 file changed, 0 insertions(+), 0 deletions(-)
840         EOF
841         test_cmp expect actual
842 '
843
844 test_expect_success 'whitespace-only changes reported across renames (diffstat)' '
845         git reset --hard &&
846         for i in 1 2 3 4 5 6 7 8 9; do echo "$i$i$i$i$i$i"; done >x &&
847         git add x &&
848         git commit -m "base" &&
849         sed -e "5s/^/ /" x >z &&
850         git rm x &&
851         git add z &&
852         git diff -w -M --cached --stat >actual &&
853         cat <<-EOF >expect &&
854          x => z | 0
855          1 file changed, 0 insertions(+), 0 deletions(-)
856         EOF
857         test_cmp expect actual
858 '
859
860 test_expect_success 'whitespace-only changes reported across renames' '
861         git reset --hard HEAD~1 &&
862         for i in 1 2 3 4 5 6 7 8 9; do echo "$i$i$i$i$i$i"; done >x &&
863         git add x &&
864         hash_x=$(git hash-object x) &&
865         before=$(git rev-parse --short "$hash_x") &&
866         git commit -m "base" &&
867         sed -e "5s/^/ /" x >z &&
868         git rm x &&
869         git add z &&
870         hash_z=$(git hash-object z) &&
871         after=$(git rev-parse --short "$hash_z") &&
872         git diff -w -M --cached >actual.raw &&
873         sed -e "/^similarity index /s/[0-9][0-9]*/NUM/" actual.raw >actual &&
874         cat <<-EOF >expect &&
875         diff --git a/x b/z
876         similarity index NUM%
877         rename from x
878         rename to z
879         index $before..$after 100644
880         EOF
881         test_cmp expect actual
882 '
883
884 cat >expected <<\EOF
885 diff --git a/empty b/void
886 similarity index 100%
887 rename from empty
888 rename to void
889 EOF
890
891 test_expect_success 'rename empty' '
892         git reset --hard &&
893         >empty &&
894         git add empty &&
895         git commit -m empty &&
896         git mv empty void &&
897         git diff -w --cached -M >current &&
898         test_cmp expected current
899 '
900
901 test_expect_success 'combined diff with autocrlf conversion' '
902
903         git reset --hard &&
904         test_commit "one side" x hello one-side &&
905         git checkout HEAD^ &&
906         echo >x goodbye &&
907         git commit -m "the other side" x &&
908         git config core.autocrlf true &&
909         test_must_fail git merge one-side >actual &&
910         test_i18ngrep "Automatic merge failed" actual &&
911
912         git diff >actual.raw &&
913         sed -e "1,/^@@@/d" actual.raw >actual &&
914         ! grep "^-" actual
915
916 '
917
918 # Start testing the colored format for whitespace checks
919
920 test_expect_success 'setup diff colors' '
921         git config color.diff.plain normal &&
922         git config color.diff.meta bold &&
923         git config color.diff.frag cyan &&
924         git config color.diff.func normal &&
925         git config color.diff.old red &&
926         git config color.diff.new green &&
927         git config color.diff.commit yellow &&
928         git config color.diff.whitespace blue &&
929
930         git config core.autocrlf false
931 '
932
933 test_expect_success 'diff that introduces a line with only tabs' '
934         git config core.whitespace blank-at-eol &&
935         git reset --hard &&
936         echo "test" >x &&
937         old_hash_x=$(git hash-object x) &&
938         before=$(git rev-parse --short "$old_hash_x") &&
939         git commit -m "initial" x &&
940         echo "{NTN}" | tr "NT" "\n\t" >>x &&
941         new_hash_x=$(git hash-object x) &&
942         after=$(git rev-parse --short "$new_hash_x") &&
943         git diff --color >current.raw &&
944         test_decode_color <current.raw >current &&
945
946         cat >expected <<-EOF &&
947         <BOLD>diff --git a/x b/x<RESET>
948         <BOLD>index $before..$after 100644<RESET>
949         <BOLD>--- a/x<RESET>
950         <BOLD>+++ b/x<RESET>
951         <CYAN>@@ -1 +1,4 @@<RESET>
952          test<RESET>
953         <GREEN>+<RESET><GREEN>{<RESET>
954         <GREEN>+<RESET><BLUE>   <RESET>
955         <GREEN>+<RESET><GREEN>}<RESET>
956         EOF
957
958         test_cmp expected current
959 '
960
961 test_expect_success 'diff that introduces and removes ws breakages' '
962         git reset --hard &&
963         {
964                 echo "0. blank-at-eol " &&
965                 echo "1. blank-at-eol "
966         } >x &&
967         old_hash_x=$(git hash-object x) &&
968         before=$(git rev-parse --short "$old_hash_x") &&
969         git commit -a --allow-empty -m preimage &&
970         {
971                 echo "0. blank-at-eol " &&
972                 echo "1. still-blank-at-eol " &&
973                 echo "2. and a new line "
974         } >x &&
975         new_hash_x=$(git hash-object x) &&
976         after=$(git rev-parse --short "$new_hash_x") &&
977
978         git diff --color >current.raw &&
979         test_decode_color <current.raw >current &&
980
981         cat >expected <<-EOF &&
982         <BOLD>diff --git a/x b/x<RESET>
983         <BOLD>index $before..$after 100644<RESET>
984         <BOLD>--- a/x<RESET>
985         <BOLD>+++ b/x<RESET>
986         <CYAN>@@ -1,2 +1,3 @@<RESET>
987          0. blank-at-eol <RESET>
988         <RED>-1. blank-at-eol <RESET>
989         <GREEN>+<RESET><GREEN>1. still-blank-at-eol<RESET><BLUE> <RESET>
990         <GREEN>+<RESET><GREEN>2. and a new line<RESET><BLUE> <RESET>
991         EOF
992
993         test_cmp expected current
994 '
995
996 test_expect_success 'ws-error-highlight test setup' '
997
998         git reset --hard &&
999         {
1000                 echo "0. blank-at-eol " &&
1001                 echo "1. blank-at-eol "
1002         } >x &&
1003         old_hash_x=$(git hash-object x) &&
1004         before=$(git rev-parse --short "$old_hash_x") &&
1005         git commit -a --allow-empty -m preimage &&
1006         {
1007                 echo "0. blank-at-eol " &&
1008                 echo "1. still-blank-at-eol " &&
1009                 echo "2. and a new line "
1010         } >x &&
1011         new_hash_x=$(git hash-object x) &&
1012         after=$(git rev-parse --short "$new_hash_x") &&
1013
1014         cat >expect.default-old <<-EOF &&
1015         <BOLD>diff --git a/x b/x<RESET>
1016         <BOLD>index $before..$after 100644<RESET>
1017         <BOLD>--- a/x<RESET>
1018         <BOLD>+++ b/x<RESET>
1019         <CYAN>@@ -1,2 +1,3 @@<RESET>
1020          0. blank-at-eol <RESET>
1021         <RED>-<RESET><RED>1. blank-at-eol<RESET><BLUE> <RESET>
1022         <GREEN>+<RESET><GREEN>1. still-blank-at-eol<RESET><BLUE> <RESET>
1023         <GREEN>+<RESET><GREEN>2. and a new line<RESET><BLUE> <RESET>
1024         EOF
1025
1026         cat >expect.all <<-EOF &&
1027         <BOLD>diff --git a/x b/x<RESET>
1028         <BOLD>index $before..$after 100644<RESET>
1029         <BOLD>--- a/x<RESET>
1030         <BOLD>+++ b/x<RESET>
1031         <CYAN>@@ -1,2 +1,3 @@<RESET>
1032          <RESET>0. blank-at-eol<RESET><BLUE> <RESET>
1033         <RED>-<RESET><RED>1. blank-at-eol<RESET><BLUE> <RESET>
1034         <GREEN>+<RESET><GREEN>1. still-blank-at-eol<RESET><BLUE> <RESET>
1035         <GREEN>+<RESET><GREEN>2. and a new line<RESET><BLUE> <RESET>
1036         EOF
1037
1038         cat >expect.none <<-EOF
1039         <BOLD>diff --git a/x b/x<RESET>
1040         <BOLD>index $before..$after 100644<RESET>
1041         <BOLD>--- a/x<RESET>
1042         <BOLD>+++ b/x<RESET>
1043         <CYAN>@@ -1,2 +1,3 @@<RESET>
1044          0. blank-at-eol <RESET>
1045         <RED>-1. blank-at-eol <RESET>
1046         <GREEN>+1. still-blank-at-eol <RESET>
1047         <GREEN>+2. and a new line <RESET>
1048         EOF
1049
1050 '
1051
1052 test_expect_success 'test --ws-error-highlight option' '
1053
1054         git diff --color --ws-error-highlight=default,old >current.raw &&
1055         test_decode_color <current.raw >current &&
1056         test_cmp expect.default-old current &&
1057
1058         git diff --color --ws-error-highlight=all >current.raw &&
1059         test_decode_color <current.raw >current &&
1060         test_cmp expect.all current &&
1061
1062         git diff --color --ws-error-highlight=none >current.raw &&
1063         test_decode_color <current.raw >current &&
1064         test_cmp expect.none current
1065
1066 '
1067
1068 test_expect_success 'test diff.wsErrorHighlight config' '
1069
1070         git -c diff.wsErrorHighlight=default,old diff --color >current.raw &&
1071         test_decode_color <current.raw >current &&
1072         test_cmp expect.default-old current &&
1073
1074         git -c diff.wsErrorHighlight=all diff --color >current.raw &&
1075         test_decode_color <current.raw >current &&
1076         test_cmp expect.all current &&
1077
1078         git -c diff.wsErrorHighlight=none diff --color >current.raw &&
1079         test_decode_color <current.raw >current &&
1080         test_cmp expect.none current
1081
1082 '
1083
1084 test_expect_success 'option overrides diff.wsErrorHighlight' '
1085
1086         git -c diff.wsErrorHighlight=none \
1087                 diff --color --ws-error-highlight=default,old >current.raw &&
1088         test_decode_color <current.raw >current &&
1089         test_cmp expect.default-old current &&
1090
1091         git -c diff.wsErrorHighlight=default \
1092                 diff --color --ws-error-highlight=all >current.raw &&
1093         test_decode_color <current.raw >current &&
1094         test_cmp expect.all current &&
1095
1096         git -c diff.wsErrorHighlight=all \
1097                 diff --color --ws-error-highlight=none >current.raw &&
1098         test_decode_color <current.raw >current &&
1099         test_cmp expect.none current
1100
1101 '
1102
1103 test_expect_success 'detect moved code, complete file' '
1104         git reset --hard &&
1105         cat <<-\EOF >test.c &&
1106         #include<stdio.h>
1107         main()
1108         {
1109         printf("Hello World");
1110         }
1111         EOF
1112         git add test.c &&
1113         git commit -m "add main function" &&
1114         file=$(git rev-parse --short HEAD:test.c) &&
1115         git mv test.c main.c &&
1116         test_config color.diff.oldMoved "normal red" &&
1117         test_config color.diff.newMoved "normal green" &&
1118         git diff HEAD --color-moved=zebra --color --no-renames >actual.raw &&
1119         test_decode_color <actual.raw >actual &&
1120         cat >expected <<-EOF &&
1121         <BOLD>diff --git a/main.c b/main.c<RESET>
1122         <BOLD>new file mode 100644<RESET>
1123         <BOLD>index 0000000..$file<RESET>
1124         <BOLD>--- /dev/null<RESET>
1125         <BOLD>+++ b/main.c<RESET>
1126         <CYAN>@@ -0,0 +1,5 @@<RESET>
1127         <BGREEN>+<RESET><BGREEN>#include<stdio.h><RESET>
1128         <BGREEN>+<RESET><BGREEN>main()<RESET>
1129         <BGREEN>+<RESET><BGREEN>{<RESET>
1130         <BGREEN>+<RESET><BGREEN>printf("Hello World");<RESET>
1131         <BGREEN>+<RESET><BGREEN>}<RESET>
1132         <BOLD>diff --git a/test.c b/test.c<RESET>
1133         <BOLD>deleted file mode 100644<RESET>
1134         <BOLD>index $file..0000000<RESET>
1135         <BOLD>--- a/test.c<RESET>
1136         <BOLD>+++ /dev/null<RESET>
1137         <CYAN>@@ -1,5 +0,0 @@<RESET>
1138         <BRED>-#include<stdio.h><RESET>
1139         <BRED>-main()<RESET>
1140         <BRED>-{<RESET>
1141         <BRED>-printf("Hello World");<RESET>
1142         <BRED>-}<RESET>
1143         EOF
1144
1145         test_cmp expected actual
1146 '
1147
1148 test_expect_success 'detect malicious moved code, inside file' '
1149         test_config color.diff.oldMoved "normal red" &&
1150         test_config color.diff.newMoved "normal green" &&
1151         test_config color.diff.oldMovedAlternative "blue" &&
1152         test_config color.diff.newMovedAlternative "yellow" &&
1153         git reset --hard &&
1154         cat <<-\EOF >main.c &&
1155                 #include<stdio.h>
1156                 int stuff()
1157                 {
1158                         printf("Hello ");
1159                         printf("World\n");
1160                 }
1161
1162                 int secure_foo(struct user *u)
1163                 {
1164                         if (!u->is_allowed_foo)
1165                                 return;
1166                         foo(u);
1167                 }
1168
1169                 int main()
1170                 {
1171                         foo();
1172                 }
1173         EOF
1174         cat <<-\EOF >test.c &&
1175                 #include<stdio.h>
1176                 int bar()
1177                 {
1178                         printf("Hello World, but different\n");
1179                 }
1180
1181                 int another_function()
1182                 {
1183                         bar();
1184                 }
1185         EOF
1186         git add main.c test.c &&
1187         git commit -m "add main and test file" &&
1188         before_main=$(git rev-parse --short HEAD:main.c) &&
1189         before_test=$(git rev-parse --short HEAD:test.c) &&
1190         cat <<-\EOF >main.c &&
1191                 #include<stdio.h>
1192                 int stuff()
1193                 {
1194                         printf("Hello ");
1195                         printf("World\n");
1196                 }
1197
1198                 int main()
1199                 {
1200                         foo();
1201                 }
1202         EOF
1203         cat <<-\EOF >test.c &&
1204                 #include<stdio.h>
1205                 int bar()
1206                 {
1207                         printf("Hello World, but different\n");
1208                 }
1209
1210                 int secure_foo(struct user *u)
1211                 {
1212                         foo(u);
1213                         if (!u->is_allowed_foo)
1214                                 return;
1215                 }
1216
1217                 int another_function()
1218                 {
1219                         bar();
1220                 }
1221         EOF
1222         hash_main=$(git hash-object main.c) &&
1223         after_main=$(git rev-parse --short "$hash_main") &&
1224         hash_test=$(git hash-object test.c) &&
1225         after_test=$(git rev-parse --short "$hash_test") &&
1226         git diff HEAD --no-renames --color-moved=zebra --color >actual.raw &&
1227         test_decode_color <actual.raw >actual &&
1228         cat <<-EOF >expected &&
1229         <BOLD>diff --git a/main.c b/main.c<RESET>
1230         <BOLD>index $before_main..$after_main 100644<RESET>
1231         <BOLD>--- a/main.c<RESET>
1232         <BOLD>+++ b/main.c<RESET>
1233         <CYAN>@@ -5,13 +5,6 @@<RESET> <RESET>printf("Hello ");<RESET>
1234          printf("World\n");<RESET>
1235          }<RESET>
1236          <RESET>
1237         <BRED>-int secure_foo(struct user *u)<RESET>
1238         <BRED>-{<RESET>
1239         <BLUE>-if (!u->is_allowed_foo)<RESET>
1240         <BLUE>-return;<RESET>
1241         <RED>-foo(u);<RESET>
1242         <RED>-}<RESET>
1243         <RED>-<RESET>
1244          int main()<RESET>
1245          {<RESET>
1246          foo();<RESET>
1247         <BOLD>diff --git a/test.c b/test.c<RESET>
1248         <BOLD>index $before_test..$after_test 100644<RESET>
1249         <BOLD>--- a/test.c<RESET>
1250         <BOLD>+++ b/test.c<RESET>
1251         <CYAN>@@ -4,6 +4,13 @@<RESET> <RESET>int bar()<RESET>
1252          printf("Hello World, but different\n");<RESET>
1253          }<RESET>
1254          <RESET>
1255         <BGREEN>+<RESET><BGREEN>int secure_foo(struct user *u)<RESET>
1256         <BGREEN>+<RESET><BGREEN>{<RESET>
1257         <GREEN>+<RESET><GREEN>foo(u);<RESET>
1258         <BGREEN>+<RESET><BGREEN>if (!u->is_allowed_foo)<RESET>
1259         <BGREEN>+<RESET><BGREEN>return;<RESET>
1260         <GREEN>+<RESET><GREEN>}<RESET>
1261         <GREEN>+<RESET>
1262          int another_function()<RESET>
1263          {<RESET>
1264          bar();<RESET>
1265         EOF
1266
1267         test_cmp expected actual
1268 '
1269
1270 test_expect_success 'plain moved code, inside file' '
1271         test_config color.diff.oldMoved "normal red" &&
1272         test_config color.diff.newMoved "normal green" &&
1273         test_config color.diff.oldMovedAlternative "blue" &&
1274         test_config color.diff.newMovedAlternative "yellow" &&
1275         # needs previous test as setup
1276         git diff HEAD --no-renames --color-moved=plain --color >actual.raw &&
1277         test_decode_color <actual.raw >actual &&
1278         cat <<-EOF >expected &&
1279         <BOLD>diff --git a/main.c b/main.c<RESET>
1280         <BOLD>index $before_main..$after_main 100644<RESET>
1281         <BOLD>--- a/main.c<RESET>
1282         <BOLD>+++ b/main.c<RESET>
1283         <CYAN>@@ -5,13 +5,6 @@<RESET> <RESET>printf("Hello ");<RESET>
1284          printf("World\n");<RESET>
1285          }<RESET>
1286          <RESET>
1287         <BRED>-int secure_foo(struct user *u)<RESET>
1288         <BRED>-{<RESET>
1289         <BRED>-if (!u->is_allowed_foo)<RESET>
1290         <BRED>-return;<RESET>
1291         <BRED>-foo(u);<RESET>
1292         <BRED>-}<RESET>
1293         <BRED>-<RESET>
1294          int main()<RESET>
1295          {<RESET>
1296          foo();<RESET>
1297         <BOLD>diff --git a/test.c b/test.c<RESET>
1298         <BOLD>index $before_test..$after_test 100644<RESET>
1299         <BOLD>--- a/test.c<RESET>
1300         <BOLD>+++ b/test.c<RESET>
1301         <CYAN>@@ -4,6 +4,13 @@<RESET> <RESET>int bar()<RESET>
1302          printf("Hello World, but different\n");<RESET>
1303          }<RESET>
1304          <RESET>
1305         <BGREEN>+<RESET><BGREEN>int secure_foo(struct user *u)<RESET>
1306         <BGREEN>+<RESET><BGREEN>{<RESET>
1307         <BGREEN>+<RESET><BGREEN>foo(u);<RESET>
1308         <BGREEN>+<RESET><BGREEN>if (!u->is_allowed_foo)<RESET>
1309         <BGREEN>+<RESET><BGREEN>return;<RESET>
1310         <BGREEN>+<RESET><BGREEN>}<RESET>
1311         <BGREEN>+<RESET>
1312          int another_function()<RESET>
1313          {<RESET>
1314          bar();<RESET>
1315         EOF
1316
1317         test_cmp expected actual
1318 '
1319
1320 test_expect_success 'detect blocks of moved code' '
1321         git reset --hard &&
1322         cat <<-\EOF >lines.txt &&
1323                 long line 1
1324                 long line 2
1325                 long line 3
1326                 line 4
1327                 line 5
1328                 line 6
1329                 line 7
1330                 line 8
1331                 line 9
1332                 line 10
1333                 line 11
1334                 line 12
1335                 line 13
1336                 long line 14
1337                 long line 15
1338                 long line 16
1339         EOF
1340         git add lines.txt &&
1341         git commit -m "add poetry" &&
1342         cat <<-\EOF >lines.txt &&
1343                 line 4
1344                 line 5
1345                 line 6
1346                 line 7
1347                 line 8
1348                 line 9
1349                 long line 1
1350                 long line 2
1351                 long line 3
1352                 long line 14
1353                 long line 15
1354                 long line 16
1355                 line 10
1356                 line 11
1357                 line 12
1358                 line 13
1359         EOF
1360         test_config color.diff.oldMoved "magenta" &&
1361         test_config color.diff.newMoved "cyan" &&
1362         test_config color.diff.oldMovedAlternative "blue" &&
1363         test_config color.diff.newMovedAlternative "yellow" &&
1364         test_config color.diff.oldMovedDimmed "normal magenta" &&
1365         test_config color.diff.newMovedDimmed "normal cyan" &&
1366         test_config color.diff.oldMovedAlternativeDimmed "normal blue" &&
1367         test_config color.diff.newMovedAlternativeDimmed "normal yellow" &&
1368         git diff HEAD --no-renames --color-moved=blocks --color >actual.raw &&
1369         grep -v "index" actual.raw | test_decode_color >actual &&
1370         cat <<-\EOF >expected &&
1371         <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1372         <BOLD>--- a/lines.txt<RESET>
1373         <BOLD>+++ b/lines.txt<RESET>
1374         <CYAN>@@ -1,16 +1,16 @@<RESET>
1375         <MAGENTA>-long line 1<RESET>
1376         <MAGENTA>-long line 2<RESET>
1377         <MAGENTA>-long line 3<RESET>
1378          line 4<RESET>
1379          line 5<RESET>
1380          line 6<RESET>
1381          line 7<RESET>
1382          line 8<RESET>
1383          line 9<RESET>
1384         <CYAN>+<RESET><CYAN>long line 1<RESET>
1385         <CYAN>+<RESET><CYAN>long line 2<RESET>
1386         <CYAN>+<RESET><CYAN>long line 3<RESET>
1387         <CYAN>+<RESET><CYAN>long line 14<RESET>
1388         <CYAN>+<RESET><CYAN>long line 15<RESET>
1389         <CYAN>+<RESET><CYAN>long line 16<RESET>
1390          line 10<RESET>
1391          line 11<RESET>
1392          line 12<RESET>
1393          line 13<RESET>
1394         <MAGENTA>-long line 14<RESET>
1395         <MAGENTA>-long line 15<RESET>
1396         <MAGENTA>-long line 16<RESET>
1397         EOF
1398         test_cmp expected actual
1399
1400 '
1401
1402 test_expect_success 'detect permutations inside moved code -- dimmed-zebra' '
1403         # reuse setup from test before!
1404         test_config color.diff.oldMoved "magenta" &&
1405         test_config color.diff.newMoved "cyan" &&
1406         test_config color.diff.oldMovedAlternative "blue" &&
1407         test_config color.diff.newMovedAlternative "yellow" &&
1408         test_config color.diff.oldMovedDimmed "normal magenta" &&
1409         test_config color.diff.newMovedDimmed "normal cyan" &&
1410         test_config color.diff.oldMovedAlternativeDimmed "normal blue" &&
1411         test_config color.diff.newMovedAlternativeDimmed "normal yellow" &&
1412         git diff HEAD --no-renames --color-moved=dimmed-zebra --color >actual.raw &&
1413         grep -v "index" actual.raw | test_decode_color >actual &&
1414         cat <<-\EOF >expected &&
1415         <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1416         <BOLD>--- a/lines.txt<RESET>
1417         <BOLD>+++ b/lines.txt<RESET>
1418         <CYAN>@@ -1,16 +1,16 @@<RESET>
1419         <BMAGENTA>-long line 1<RESET>
1420         <BMAGENTA>-long line 2<RESET>
1421         <BMAGENTA>-long line 3<RESET>
1422          line 4<RESET>
1423          line 5<RESET>
1424          line 6<RESET>
1425          line 7<RESET>
1426          line 8<RESET>
1427          line 9<RESET>
1428         <BCYAN>+<RESET><BCYAN>long line 1<RESET>
1429         <BCYAN>+<RESET><BCYAN>long line 2<RESET>
1430         <CYAN>+<RESET><CYAN>long line 3<RESET>
1431         <YELLOW>+<RESET><YELLOW>long line 14<RESET>
1432         <BYELLOW>+<RESET><BYELLOW>long line 15<RESET>
1433         <BYELLOW>+<RESET><BYELLOW>long line 16<RESET>
1434          line 10<RESET>
1435          line 11<RESET>
1436          line 12<RESET>
1437          line 13<RESET>
1438         <BMAGENTA>-long line 14<RESET>
1439         <BMAGENTA>-long line 15<RESET>
1440         <BMAGENTA>-long line 16<RESET>
1441         EOF
1442         test_cmp expected actual
1443 '
1444
1445 test_expect_success 'cmd option assumes configured colored-moved' '
1446         test_config color.diff.oldMoved "magenta" &&
1447         test_config color.diff.newMoved "cyan" &&
1448         test_config color.diff.oldMovedAlternative "blue" &&
1449         test_config color.diff.newMovedAlternative "yellow" &&
1450         test_config color.diff.oldMovedDimmed "normal magenta" &&
1451         test_config color.diff.newMovedDimmed "normal cyan" &&
1452         test_config color.diff.oldMovedAlternativeDimmed "normal blue" &&
1453         test_config color.diff.newMovedAlternativeDimmed "normal yellow" &&
1454         test_config diff.colorMoved zebra &&
1455         git diff HEAD --no-renames --color-moved --color >actual.raw &&
1456         grep -v "index" actual.raw | test_decode_color >actual &&
1457         cat <<-\EOF >expected &&
1458         <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1459         <BOLD>--- a/lines.txt<RESET>
1460         <BOLD>+++ b/lines.txt<RESET>
1461         <CYAN>@@ -1,16 +1,16 @@<RESET>
1462         <MAGENTA>-long line 1<RESET>
1463         <MAGENTA>-long line 2<RESET>
1464         <MAGENTA>-long line 3<RESET>
1465          line 4<RESET>
1466          line 5<RESET>
1467          line 6<RESET>
1468          line 7<RESET>
1469          line 8<RESET>
1470          line 9<RESET>
1471         <CYAN>+<RESET><CYAN>long line 1<RESET>
1472         <CYAN>+<RESET><CYAN>long line 2<RESET>
1473         <CYAN>+<RESET><CYAN>long line 3<RESET>
1474         <YELLOW>+<RESET><YELLOW>long line 14<RESET>
1475         <YELLOW>+<RESET><YELLOW>long line 15<RESET>
1476         <YELLOW>+<RESET><YELLOW>long line 16<RESET>
1477          line 10<RESET>
1478          line 11<RESET>
1479          line 12<RESET>
1480          line 13<RESET>
1481         <MAGENTA>-long line 14<RESET>
1482         <MAGENTA>-long line 15<RESET>
1483         <MAGENTA>-long line 16<RESET>
1484         EOF
1485         test_cmp expected actual
1486 '
1487
1488 test_expect_success 'no effect from --color-moved with --word-diff' '
1489         cat <<-\EOF >text.txt &&
1490         Lorem Ipsum is simply dummy text of the printing and typesetting industry.
1491         EOF
1492         git add text.txt &&
1493         git commit -a -m "clean state" &&
1494         cat <<-\EOF >text.txt &&
1495         simply Lorem Ipsum dummy is text of the typesetting and printing industry.
1496         EOF
1497         git diff --color-moved --word-diff >actual &&
1498         git diff --word-diff >expect &&
1499         test_cmp expect actual
1500 '
1501
1502 test_expect_success 'set up whitespace tests' '
1503         git reset --hard &&
1504         # Note that these lines have no leading or trailing whitespace.
1505         cat <<-\EOF >lines.txt &&
1506         line 1
1507         line 2
1508         line 3
1509         line 4
1510         line 5
1511         long line 6
1512         long line 7
1513         long line 8
1514         long line 9
1515         EOF
1516         git add lines.txt &&
1517         git commit -m "add poetry" &&
1518         git config color.diff.oldMoved "magenta" &&
1519         git config color.diff.newMoved "cyan"
1520 '
1521
1522 test_expect_success 'move detection ignoring whitespace ' '
1523         q_to_tab <<-\EOF >lines.txt &&
1524         Qlong line 6
1525         Qlong line 7
1526         Qlong line 8
1527         Qchanged long line 9
1528         line 1
1529         line 2
1530         line 3
1531         line 4
1532         line 5
1533         EOF
1534         git diff HEAD --no-renames --color-moved --color >actual.raw &&
1535         grep -v "index" actual.raw | test_decode_color >actual &&
1536         cat <<-\EOF >expected &&
1537         <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1538         <BOLD>--- a/lines.txt<RESET>
1539         <BOLD>+++ b/lines.txt<RESET>
1540         <CYAN>@@ -1,9 +1,9 @@<RESET>
1541         <GREEN>+<RESET> <GREEN>long line 6<RESET>
1542         <GREEN>+<RESET> <GREEN>long line 7<RESET>
1543         <GREEN>+<RESET> <GREEN>long line 8<RESET>
1544         <GREEN>+<RESET> <GREEN>changed long line 9<RESET>
1545          line 1<RESET>
1546          line 2<RESET>
1547          line 3<RESET>
1548          line 4<RESET>
1549          line 5<RESET>
1550         <RED>-long line 6<RESET>
1551         <RED>-long line 7<RESET>
1552         <RED>-long line 8<RESET>
1553         <RED>-long line 9<RESET>
1554         EOF
1555         test_cmp expected actual &&
1556
1557         git diff HEAD --no-renames --color-moved --color \
1558                 --color-moved-ws=ignore-all-space >actual.raw &&
1559         grep -v "index" actual.raw | test_decode_color >actual &&
1560         cat <<-\EOF >expected &&
1561         <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1562         <BOLD>--- a/lines.txt<RESET>
1563         <BOLD>+++ b/lines.txt<RESET>
1564         <CYAN>@@ -1,9 +1,9 @@<RESET>
1565         <CYAN>+<RESET>  <CYAN>long line 6<RESET>
1566         <CYAN>+<RESET>  <CYAN>long line 7<RESET>
1567         <CYAN>+<RESET>  <CYAN>long line 8<RESET>
1568         <GREEN>+<RESET> <GREEN>changed long line 9<RESET>
1569          line 1<RESET>
1570          line 2<RESET>
1571          line 3<RESET>
1572          line 4<RESET>
1573          line 5<RESET>
1574         <MAGENTA>-long line 6<RESET>
1575         <MAGENTA>-long line 7<RESET>
1576         <MAGENTA>-long line 8<RESET>
1577         <RED>-long line 9<RESET>
1578         EOF
1579         test_cmp expected actual
1580 '
1581
1582 test_expect_success 'move detection ignoring whitespace changes' '
1583         git reset --hard &&
1584         # Lines 6-8 have a space change, but 9 is new whitespace
1585         q_to_tab <<-\EOF >lines.txt &&
1586         longQline 6
1587         longQline 7
1588         longQline 8
1589         long liQne 9
1590         line 1
1591         line 2
1592         line 3
1593         line 4
1594         line 5
1595         EOF
1596
1597         git diff HEAD --no-renames --color-moved --color >actual.raw &&
1598         grep -v "index" actual.raw | test_decode_color >actual &&
1599         cat <<-\EOF >expected &&
1600         <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1601         <BOLD>--- a/lines.txt<RESET>
1602         <BOLD>+++ b/lines.txt<RESET>
1603         <CYAN>@@ -1,9 +1,9 @@<RESET>
1604         <GREEN>+<RESET><GREEN>long      line 6<RESET>
1605         <GREEN>+<RESET><GREEN>long      line 7<RESET>
1606         <GREEN>+<RESET><GREEN>long      line 8<RESET>
1607         <GREEN>+<RESET><GREEN>long li   ne 9<RESET>
1608          line 1<RESET>
1609          line 2<RESET>
1610          line 3<RESET>
1611          line 4<RESET>
1612          line 5<RESET>
1613         <RED>-long line 6<RESET>
1614         <RED>-long line 7<RESET>
1615         <RED>-long line 8<RESET>
1616         <RED>-long line 9<RESET>
1617         EOF
1618         test_cmp expected actual &&
1619
1620         git diff HEAD --no-renames --color-moved --color \
1621                 --color-moved-ws=ignore-space-change >actual.raw &&
1622         grep -v "index" actual.raw | test_decode_color >actual &&
1623         cat <<-\EOF >expected &&
1624         <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1625         <BOLD>--- a/lines.txt<RESET>
1626         <BOLD>+++ b/lines.txt<RESET>
1627         <CYAN>@@ -1,9 +1,9 @@<RESET>
1628         <CYAN>+<RESET><CYAN>long        line 6<RESET>
1629         <CYAN>+<RESET><CYAN>long        line 7<RESET>
1630         <CYAN>+<RESET><CYAN>long        line 8<RESET>
1631         <GREEN>+<RESET><GREEN>long li   ne 9<RESET>
1632          line 1<RESET>
1633          line 2<RESET>
1634          line 3<RESET>
1635          line 4<RESET>
1636          line 5<RESET>
1637         <MAGENTA>-long line 6<RESET>
1638         <MAGENTA>-long line 7<RESET>
1639         <MAGENTA>-long line 8<RESET>
1640         <RED>-long line 9<RESET>
1641         EOF
1642         test_cmp expected actual
1643 '
1644
1645 test_expect_success 'move detection ignoring whitespace at eol' '
1646         git reset --hard &&
1647         # Lines 6-9 have new eol whitespace, but 9 also has it in the middle
1648         q_to_tab <<-\EOF >lines.txt &&
1649         long line 6Q
1650         long line 7Q
1651         long line 8Q
1652         longQline 9Q
1653         line 1
1654         line 2
1655         line 3
1656         line 4
1657         line 5
1658         EOF
1659
1660         # avoid cluttering the output with complaints about our eol whitespace
1661         test_config core.whitespace -blank-at-eol &&
1662
1663         git diff HEAD --no-renames --color-moved --color >actual.raw &&
1664         grep -v "index" actual.raw | test_decode_color >actual &&
1665         cat <<-\EOF >expected &&
1666         <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1667         <BOLD>--- a/lines.txt<RESET>
1668         <BOLD>+++ b/lines.txt<RESET>
1669         <CYAN>@@ -1,9 +1,9 @@<RESET>
1670         <GREEN>+<RESET><GREEN>long line 6       <RESET>
1671         <GREEN>+<RESET><GREEN>long line 7       <RESET>
1672         <GREEN>+<RESET><GREEN>long line 8       <RESET>
1673         <GREEN>+<RESET><GREEN>long      line 9  <RESET>
1674          line 1<RESET>
1675          line 2<RESET>
1676          line 3<RESET>
1677          line 4<RESET>
1678          line 5<RESET>
1679         <RED>-long line 6<RESET>
1680         <RED>-long line 7<RESET>
1681         <RED>-long line 8<RESET>
1682         <RED>-long line 9<RESET>
1683         EOF
1684         test_cmp expected actual &&
1685
1686         git diff HEAD --no-renames --color-moved --color \
1687                 --color-moved-ws=ignore-space-at-eol >actual.raw &&
1688         grep -v "index" actual.raw | test_decode_color >actual &&
1689         cat <<-\EOF >expected &&
1690         <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1691         <BOLD>--- a/lines.txt<RESET>
1692         <BOLD>+++ b/lines.txt<RESET>
1693         <CYAN>@@ -1,9 +1,9 @@<RESET>
1694         <CYAN>+<RESET><CYAN>long line 6 <RESET>
1695         <CYAN>+<RESET><CYAN>long line 7 <RESET>
1696         <CYAN>+<RESET><CYAN>long line 8 <RESET>
1697         <GREEN>+<RESET><GREEN>long      line 9  <RESET>
1698          line 1<RESET>
1699          line 2<RESET>
1700          line 3<RESET>
1701          line 4<RESET>
1702          line 5<RESET>
1703         <MAGENTA>-long line 6<RESET>
1704         <MAGENTA>-long line 7<RESET>
1705         <MAGENTA>-long line 8<RESET>
1706         <RED>-long line 9<RESET>
1707         EOF
1708         test_cmp expected actual
1709 '
1710
1711 test_expect_success 'clean up whitespace-test colors' '
1712         git config --unset color.diff.oldMoved &&
1713         git config --unset color.diff.newMoved
1714 '
1715
1716 test_expect_success '--color-moved block at end of diff output respects MIN_ALNUM_COUNT' '
1717         git reset --hard &&
1718         >bar &&
1719         cat <<-\EOF >foo &&
1720         irrelevant_line
1721         line1
1722         EOF
1723         git add foo bar &&
1724         git commit -m x &&
1725
1726         cat <<-\EOF >bar &&
1727         line1
1728         EOF
1729         cat <<-\EOF >foo &&
1730         irrelevant_line
1731         EOF
1732
1733         git diff HEAD --color-moved=zebra --color --no-renames >actual.raw &&
1734         grep -v "index" actual.raw | test_decode_color >actual &&
1735         cat >expected <<-\EOF &&
1736         <BOLD>diff --git a/bar b/bar<RESET>
1737         <BOLD>--- a/bar<RESET>
1738         <BOLD>+++ b/bar<RESET>
1739         <CYAN>@@ -0,0 +1 @@<RESET>
1740         <GREEN>+<RESET><GREEN>line1<RESET>
1741         <BOLD>diff --git a/foo b/foo<RESET>
1742         <BOLD>--- a/foo<RESET>
1743         <BOLD>+++ b/foo<RESET>
1744         <CYAN>@@ -1,2 +1 @@<RESET>
1745          irrelevant_line<RESET>
1746         <RED>-line1<RESET>
1747         EOF
1748
1749         test_cmp expected actual
1750 '
1751
1752 test_expect_success '--color-moved respects MIN_ALNUM_COUNT' '
1753         git reset --hard &&
1754         cat <<-\EOF >foo &&
1755         nineteen chars 456789
1756         irrelevant_line
1757         twenty chars 234567890
1758         EOF
1759         >bar &&
1760         git add foo bar &&
1761         git commit -m x &&
1762
1763         cat <<-\EOF >foo &&
1764         irrelevant_line
1765         EOF
1766         cat <<-\EOF >bar &&
1767         twenty chars 234567890
1768         nineteen chars 456789
1769         EOF
1770
1771         git diff HEAD --color-moved=zebra --color --no-renames >actual.raw &&
1772         grep -v "index" actual.raw | test_decode_color >actual &&
1773         cat >expected <<-\EOF &&
1774         <BOLD>diff --git a/bar b/bar<RESET>
1775         <BOLD>--- a/bar<RESET>
1776         <BOLD>+++ b/bar<RESET>
1777         <CYAN>@@ -0,0 +1,2 @@<RESET>
1778         <BOLD;CYAN>+<RESET><BOLD;CYAN>twenty chars 234567890<RESET>
1779         <GREEN>+<RESET><GREEN>nineteen chars 456789<RESET>
1780         <BOLD>diff --git a/foo b/foo<RESET>
1781         <BOLD>--- a/foo<RESET>
1782         <BOLD>+++ b/foo<RESET>
1783         <CYAN>@@ -1,3 +1 @@<RESET>
1784         <RED>-nineteen chars 456789<RESET>
1785          irrelevant_line<RESET>
1786         <BOLD;MAGENTA>-twenty chars 234567890<RESET>
1787         EOF
1788
1789         test_cmp expected actual
1790 '
1791
1792 test_expect_success '--color-moved treats adjacent blocks as separate for MIN_ALNUM_COUNT' '
1793         git reset --hard &&
1794         cat <<-\EOF >foo &&
1795         7charsA
1796         irrelevant_line
1797         7charsB
1798         7charsC
1799         EOF
1800         >bar &&
1801         git add foo bar &&
1802         git commit -m x &&
1803
1804         cat <<-\EOF >foo &&
1805         irrelevant_line
1806         EOF
1807         cat <<-\EOF >bar &&
1808         7charsB
1809         7charsC
1810         7charsA
1811         EOF
1812
1813         git diff HEAD --color-moved=zebra --color --no-renames >actual.raw &&
1814         grep -v "index" actual.raw | test_decode_color >actual &&
1815         cat >expected <<-\EOF &&
1816         <BOLD>diff --git a/bar b/bar<RESET>
1817         <BOLD>--- a/bar<RESET>
1818         <BOLD>+++ b/bar<RESET>
1819         <CYAN>@@ -0,0 +1,3 @@<RESET>
1820         <GREEN>+<RESET><GREEN>7charsB<RESET>
1821         <GREEN>+<RESET><GREEN>7charsC<RESET>
1822         <GREEN>+<RESET><GREEN>7charsA<RESET>
1823         <BOLD>diff --git a/foo b/foo<RESET>
1824         <BOLD>--- a/foo<RESET>
1825         <BOLD>+++ b/foo<RESET>
1826         <CYAN>@@ -1,4 +1 @@<RESET>
1827         <RED>-7charsA<RESET>
1828          irrelevant_line<RESET>
1829         <RED>-7charsB<RESET>
1830         <RED>-7charsC<RESET>
1831         EOF
1832
1833         test_cmp expected actual
1834 '
1835
1836 test_expect_success 'move detection with submodules' '
1837         test_create_repo bananas &&
1838         echo ripe >bananas/recipe &&
1839         git -C bananas add recipe &&
1840         test_commit fruit &&
1841         test_commit -C bananas recipe &&
1842         git submodule add ./bananas &&
1843         git add bananas &&
1844         git commit -a -m "bananas are like a heavy library?" &&
1845         echo foul >bananas/recipe &&
1846         echo ripe >fruit.t &&
1847
1848         git diff --submodule=diff --color-moved --color >actual &&
1849
1850         # no move detection as the moved line is across repository boundaries.
1851         test_decode_color <actual >decoded_actual &&
1852         ! grep BGREEN decoded_actual &&
1853         ! grep BRED decoded_actual &&
1854
1855         # nor did we mess with it another way
1856         git diff --submodule=diff --color >expect.raw &&
1857         test_decode_color <expect.raw >expect &&
1858         test_cmp expect decoded_actual &&
1859         rm -rf bananas &&
1860         git submodule deinit bananas
1861 '
1862
1863 test_expect_success 'only move detection ignores white spaces' '
1864         git reset --hard &&
1865         q_to_tab <<-\EOF >text.txt &&
1866                 a long line to exceed per-line minimum
1867                 another long line to exceed per-line minimum
1868                 original file
1869         EOF
1870         git add text.txt &&
1871         git commit -m "add text" &&
1872         q_to_tab <<-\EOF >text.txt &&
1873                 Qa long line to exceed per-line minimum
1874                 Qanother long line to exceed per-line minimum
1875                 new file
1876         EOF
1877
1878         # Make sure we get a different diff using -w
1879         git diff --color --color-moved -w >actual.raw &&
1880         grep -v "index" actual.raw | test_decode_color >actual &&
1881         q_to_tab <<-\EOF >expected &&
1882         <BOLD>diff --git a/text.txt b/text.txt<RESET>
1883         <BOLD>--- a/text.txt<RESET>
1884         <BOLD>+++ b/text.txt<RESET>
1885         <CYAN>@@ -1,3 +1,3 @@<RESET>
1886          Qa long line to exceed per-line minimum<RESET>
1887          Qanother long line to exceed per-line minimum<RESET>
1888         <RED>-original file<RESET>
1889         <GREEN>+<RESET><GREEN>new file<RESET>
1890         EOF
1891         test_cmp expected actual &&
1892
1893         # And now ignoring white space only in the move detection
1894         git diff --color --color-moved \
1895                 --color-moved-ws=ignore-all-space,ignore-space-change,ignore-space-at-eol >actual.raw &&
1896         grep -v "index" actual.raw | test_decode_color >actual &&
1897         q_to_tab <<-\EOF >expected &&
1898         <BOLD>diff --git a/text.txt b/text.txt<RESET>
1899         <BOLD>--- a/text.txt<RESET>
1900         <BOLD>+++ b/text.txt<RESET>
1901         <CYAN>@@ -1,3 +1,3 @@<RESET>
1902         <BOLD;MAGENTA>-a long line to exceed per-line minimum<RESET>
1903         <BOLD;MAGENTA>-another long line to exceed per-line minimum<RESET>
1904         <RED>-original file<RESET>
1905         <BOLD;CYAN>+<RESET>Q<BOLD;CYAN>a long line to exceed per-line minimum<RESET>
1906         <BOLD;CYAN>+<RESET>Q<BOLD;CYAN>another long line to exceed per-line minimum<RESET>
1907         <GREEN>+<RESET><GREEN>new file<RESET>
1908         EOF
1909         test_cmp expected actual
1910 '
1911
1912 test_expect_success 'compare whitespace delta across moved blocks' '
1913
1914         git reset --hard &&
1915         q_to_tab <<-\EOF >text.txt &&
1916         QIndented
1917         QText across
1918         Qsome lines
1919         QBut! <- this stands out
1920         QAdjusting with
1921         QQdifferent starting
1922         Qwhite spaces
1923         QAnother outlier
1924         QQQIndented
1925         QQQText across
1926         QQQfive lines
1927         QQQthat has similar lines
1928         QQQto previous blocks, but with different indent
1929         QQQYetQAnotherQoutlierQ
1930         QLine with internal w h i t e s p a c e change
1931         EOF
1932
1933         git add text.txt &&
1934         git commit -m "add text.txt" &&
1935
1936         q_to_tab <<-\EOF >text.txt &&
1937         QQIndented
1938         QQText across
1939         QQsome lines
1940         QQQBut! <- this stands out
1941         Adjusting with
1942         Qdifferent starting
1943         white spaces
1944         AnotherQoutlier
1945         QQIndented
1946         QQText across
1947         QQfive lines
1948         QQthat has similar lines
1949         QQto previous blocks, but with different indent
1950         QQYetQAnotherQoutlier
1951         QLine with internal whitespace change
1952         EOF
1953
1954         git diff --color --color-moved --color-moved-ws=allow-indentation-change >actual.raw &&
1955         grep -v "index" actual.raw | test_decode_color >actual &&
1956
1957         q_to_tab <<-\EOF >expected &&
1958                 <BOLD>diff --git a/text.txt b/text.txt<RESET>
1959                 <BOLD>--- a/text.txt<RESET>
1960                 <BOLD>+++ b/text.txt<RESET>
1961                 <CYAN>@@ -1,15 +1,15 @@<RESET>
1962                 <BOLD;MAGENTA>-QIndented<RESET>
1963                 <BOLD;MAGENTA>-QText across<RESET>
1964                 <BOLD;MAGENTA>-Qsome lines<RESET>
1965                 <RED>-QBut! <- this stands out<RESET>
1966                 <BOLD;MAGENTA>-QAdjusting with<RESET>
1967                 <BOLD;MAGENTA>-QQdifferent starting<RESET>
1968                 <BOLD;MAGENTA>-Qwhite spaces<RESET>
1969                 <RED>-QAnother outlier<RESET>
1970                 <BOLD;MAGENTA>-QQQIndented<RESET>
1971                 <BOLD;MAGENTA>-QQQText across<RESET>
1972                 <BOLD;MAGENTA>-QQQfive lines<RESET>
1973                 <BOLD;MAGENTA>-QQQthat has similar lines<RESET>
1974                 <BOLD;MAGENTA>-QQQto previous blocks, but with different indent<RESET>
1975                 <RED>-QQQYetQAnotherQoutlierQ<RESET>
1976                 <RED>-QLine with internal w h i t e s p a c e change<RESET>
1977                 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>Indented<RESET>
1978                 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>Text across<RESET>
1979                 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>some lines<RESET>
1980                 <GREEN>+<RESET>QQQ<GREEN>But! <- this stands out<RESET>
1981                 <BOLD;CYAN>+<RESET><BOLD;CYAN>Adjusting with<RESET>
1982                 <BOLD;CYAN>+<RESET>Q<BOLD;CYAN>different starting<RESET>
1983                 <BOLD;CYAN>+<RESET><BOLD;CYAN>white spaces<RESET>
1984                 <GREEN>+<RESET><GREEN>AnotherQoutlier<RESET>
1985                 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>Indented<RESET>
1986                 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>Text across<RESET>
1987                 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>five lines<RESET>
1988                 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>that has similar lines<RESET>
1989                 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>to previous blocks, but with different indent<RESET>
1990                 <GREEN>+<RESET>QQ<GREEN>YetQAnotherQoutlier<RESET>
1991                 <GREEN>+<RESET>Q<GREEN>Line with internal whitespace change<RESET>
1992         EOF
1993
1994         test_cmp expected actual
1995 '
1996
1997 test_expect_success 'bogus settings in move detection erroring out' '
1998         test_must_fail git diff --color-moved=bogus 2>err &&
1999         test_i18ngrep "must be one of" err &&
2000         test_i18ngrep bogus err &&
2001
2002         test_must_fail git -c diff.colormoved=bogus diff 2>err &&
2003         test_i18ngrep "must be one of" err &&
2004         test_i18ngrep "from command-line config" err &&
2005
2006         test_must_fail git diff --color-moved-ws=bogus 2>err &&
2007         test_i18ngrep "possible values" err &&
2008         test_i18ngrep bogus err &&
2009
2010         test_must_fail git -c diff.colormovedws=bogus diff 2>err &&
2011         test_i18ngrep "possible values" err &&
2012         test_i18ngrep "from command-line config" err
2013 '
2014
2015 test_expect_success 'compare whitespace delta incompatible with other space options' '
2016         test_must_fail git diff \
2017                 --color-moved-ws=allow-indentation-change,ignore-all-space \
2018                 2>err &&
2019         test_i18ngrep allow-indentation-change err
2020 '
2021
2022 EMPTY=''
2023 test_expect_success 'compare mixed whitespace delta across moved blocks' '
2024
2025         git reset --hard &&
2026         tr Q_ "\t " <<-EOF >text.txt &&
2027         ${EMPTY}
2028         ____too short without
2029         ${EMPTY}
2030         ___being grouped across blank line
2031         ${EMPTY}
2032         context
2033         lines
2034         to
2035         anchor
2036         ____Indented text to
2037         _Q____be further indented by four spaces across
2038         ____Qseveral lines
2039         QQ____These two lines have had their
2040         ____indentation reduced by four spaces
2041         Qdifferent indentation change
2042         ____too short
2043         EOF
2044
2045         git add text.txt &&
2046         git commit -m "add text.txt" &&
2047
2048         tr Q_ "\t " <<-EOF >text.txt &&
2049         context
2050         lines
2051         to
2052         anchor
2053         QIndented text to
2054         QQbe further indented by four spaces across
2055         Q____several lines
2056         ${EMPTY}
2057         QQtoo short without
2058         ${EMPTY}
2059         Q_______being grouped across blank line
2060         ${EMPTY}
2061         Q_QThese two lines have had their
2062         indentation reduced by four spaces
2063         QQdifferent indentation change
2064         __Qtoo short
2065         EOF
2066
2067         git -c color.diff.whitespace="normal red" \
2068                 -c core.whitespace=space-before-tab \
2069                 diff --color --color-moved --ws-error-highlight=all \
2070                 --color-moved-ws=allow-indentation-change >actual.raw &&
2071         grep -v "index" actual.raw | test_decode_color >actual &&
2072
2073         cat <<-\EOF >expected &&
2074         <BOLD>diff --git a/text.txt b/text.txt<RESET>
2075         <BOLD>--- a/text.txt<RESET>
2076         <BOLD>+++ b/text.txt<RESET>
2077         <CYAN>@@ -1,16 +1,16 @@<RESET>
2078         <BOLD;MAGENTA>-<RESET>
2079         <BOLD;MAGENTA>-<RESET><BOLD;MAGENTA>    too short without<RESET>
2080         <BOLD;MAGENTA>-<RESET>
2081         <BOLD;MAGENTA>-<RESET><BOLD;MAGENTA>   being grouped across blank line<RESET>
2082         <BOLD;MAGENTA>-<RESET>
2083          <RESET>context<RESET>
2084          <RESET>lines<RESET>
2085          <RESET>to<RESET>
2086          <RESET>anchor<RESET>
2087         <BOLD;MAGENTA>-<RESET><BOLD;MAGENTA>    Indented text to<RESET>
2088         <BOLD;MAGENTA>-<RESET><BRED> <RESET>    <BOLD;MAGENTA>    be further indented by four spaces across<RESET>
2089         <BOLD;MAGENTA>-<RESET><BRED>    <RESET> <BOLD;MAGENTA>several lines<RESET>
2090         <BOLD;BLUE>-<RESET>             <BOLD;BLUE>    These two lines have had their<RESET>
2091         <BOLD;BLUE>-<RESET><BOLD;BLUE>    indentation reduced by four spaces<RESET>
2092         <BOLD;MAGENTA>-<RESET>  <BOLD;MAGENTA>different indentation change<RESET>
2093         <RED>-<RESET><RED>    too short<RESET>
2094         <BOLD;CYAN>+<RESET>     <BOLD;CYAN>Indented text to<RESET>
2095         <BOLD;CYAN>+<RESET>             <BOLD;CYAN>be further indented by four spaces across<RESET>
2096         <BOLD;CYAN>+<RESET>     <BOLD;CYAN>    several lines<RESET>
2097         <BOLD;YELLOW>+<RESET>
2098         <BOLD;YELLOW>+<RESET>           <BOLD;YELLOW>too short without<RESET>
2099         <BOLD;YELLOW>+<RESET>
2100         <BOLD;YELLOW>+<RESET>   <BOLD;YELLOW>       being grouped across blank line<RESET>
2101         <BOLD;YELLOW>+<RESET>
2102         <BOLD;CYAN>+<RESET>     <BRED> <RESET>  <BOLD;CYAN>These two lines have had their<RESET>
2103         <BOLD;CYAN>+<RESET><BOLD;CYAN>indentation reduced by four spaces<RESET>
2104         <BOLD;YELLOW>+<RESET>           <BOLD;YELLOW>different indentation change<RESET>
2105         <GREEN>+<RESET><BRED>  <RESET>  <GREEN>too short<RESET>
2106         EOF
2107
2108         test_cmp expected actual
2109 '
2110
2111 test_expect_success 'combine --ignore-blank-lines with --function-context' '
2112         test_write_lines 1 "" 2 3 4 5 >a &&
2113         test_write_lines 1    2 3 4   >b &&
2114         test_must_fail git diff --no-index \
2115                 --ignore-blank-lines --function-context a b >actual.raw &&
2116         sed -n "/@@/,\$p" <actual.raw >actual &&
2117         cat <<-\EOF >expect &&
2118         @@ -1,6 +1,4 @@
2119          1
2120         -
2121          2
2122          3
2123          4
2124         -5
2125         EOF
2126         test_cmp expect actual
2127 '
2128
2129 test_expect_success 'combine --ignore-blank-lines with --function-context 2' '
2130         test_write_lines    a b c "" function 1 2 3 4 5 "" 6 7 8 9 >a &&
2131         test_write_lines "" a b c "" function 1 2 3 4 5    6 7 8   >b &&
2132         test_must_fail git diff --no-index \
2133                 --ignore-blank-lines --function-context a b >actual.raw &&
2134         sed -n "/@@/,\$p" <actual.raw >actual &&
2135         cat <<-\EOF >expect &&
2136         @@ -5,11 +6,9 @@ c
2137          function
2138          1
2139          2
2140          3
2141          4
2142          5
2143         -
2144          6
2145          7
2146          8
2147         -9
2148         EOF
2149         test_cmp expect actual
2150 '
2151
2152 test_done