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