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