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