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