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