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