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