3 # Copyright (c) 2006 Johannes E. Schindelin
6 test_description
='Test special whitespace in diff engine.
10 TEST_PASSES_SANITIZE_LEAK
=true
12 .
"$TEST_DIRECTORY"/lib-diff.sh
14 test_expect_success
"Ray Lehtiniemi's example" '
20 git update-index --add x &&
21 old_hash_x=$(git hash-object x) &&
22 before=$(git rev-parse --short "$old_hash_x") &&
31 new_hash_x=$(git hash-object x) &&
32 after=$(git rev-parse --short "$new_hash_x") &&
36 index $before..$after 100644
50 test_cmp expect out &&
53 test_cmp expect out &&
59 test_expect_success
'another test, without options' '
60 tr Q "\015" <<-\EOF >x &&
61 whitespace at beginning
63 whitespace in the middle
70 old_hash_x=$(git hash-object x) &&
71 before=$(git rev-parse --short "$old_hash_x") &&
73 tr "_" " " <<-\EOF >x &&
74 _ whitespace at beginning
76 white space in the middle
81 new_hash_x=$(git hash-object x) &&
82 after=$(git rev-parse --short "$new_hash_x") &&
84 tr "Q_" "\015 " <<-EOF >expect &&
86 index $before..$after 100644
90 -whitespace at beginning
92 -whitespace in the middle
94 + whitespace at beginning
96 +white space in the middle
104 test_cmp expect out &&
107 test_must_be_empty out &&
109 git diff -w -b >out &&
110 test_must_be_empty out &&
112 git diff -w --ignore-space-at-eol >out &&
113 test_must_be_empty out &&
115 git diff -w -b --ignore-space-at-eol >out &&
116 test_must_be_empty out &&
118 git diff -w --ignore-cr-at-eol >out &&
119 test_must_be_empty out &&
121 tr "Q_" "\015 " <<-EOF >expect &&
123 index $before..$after 100644
127 -whitespace at beginning
128 +_ whitespace at beginning
130 -whitespace in the middle
131 +white space in the middle
137 test_cmp expect out &&
139 git diff -b --ignore-space-at-eol >out &&
140 test_cmp expect out &&
142 git diff -b --ignore-cr-at-eol >out &&
143 test_cmp expect out &&
145 tr "Q_" "\015 " <<-EOF >expect &&
147 index $before..$after 100644
151 -whitespace at beginning
153 -whitespace in the middle
154 +_ whitespace at beginning
156 +white space in the middle
161 git diff --ignore-space-at-eol >out &&
162 test_cmp expect out &&
164 git diff --ignore-space-at-eol --ignore-cr-at-eol >out &&
165 test_cmp expect out &&
167 tr "Q_" "\015 " <<-EOF >expect &&
169 index_$before..$after 100644
173 -whitespace at beginning
175 -whitespace in the middle
177 +_ whitespace at beginning
179 +white space in the middle
184 git diff --ignore-cr-at-eol >out &&
188 test_expect_success
'ignore-blank-lines: only new lines' '
190 git update-index x &&
191 test_seq 5 | sed "/3/i\\
193 git diff --ignore-blank-lines >out &&
194 test_must_be_empty out
197 test_expect_success
'ignore-blank-lines: only new lines with space' '
199 git update-index x &&
200 test_seq 5 | sed "/3/i\\
202 git diff -w --ignore-blank-lines >out &&
203 test_must_be_empty out
206 test_expect_success
'ignore-blank-lines: after change' '
218 git update-index x &&
231 git diff --inter-hunk-context=100 --ignore-blank-lines >out.tmp &&
232 cat <<-\EOF >expected &&
246 compare_diff_patch expected out.tmp
249 test_expect_success
'ignore-blank-lines: before change' '
260 git update-index x &&
273 git diff --inter-hunk-context=100 --ignore-blank-lines >out.tmp &&
274 cat <<-\EOF >expected &&
287 compare_diff_patch expected out.tmp
290 test_expect_success
'ignore-blank-lines: between changes' '
305 git update-index x &&
322 git diff --ignore-blank-lines >out.tmp &&
323 cat <<-\EOF >expected &&
344 compare_diff_patch expected out.tmp
347 test_expect_success
'ignore-blank-lines: between changes (with interhunkctx)' '
349 git update-index x &&
367 git diff --inter-hunk-context=2 --ignore-blank-lines >out.tmp &&
368 cat <<-\EOF >expected &&
389 compare_diff_patch expected out.tmp
392 test_expect_success
'ignore-blank-lines: scattered spaces' '
394 git update-index x &&
415 git diff --inter-hunk-context=4 --ignore-blank-lines >out.tmp &&
416 cat <<-\EOF >expected &&
431 compare_diff_patch expected out.tmp
434 test_expect_success
'ignore-blank-lines: spaces coalesce' '
436 git update-index x &&
450 git diff --inter-hunk-context=4 --ignore-blank-lines >out.tmp &&
451 cat <<-\EOF >expected &&
468 compare_diff_patch expected out.tmp
471 test_expect_success
'ignore-blank-lines: mix changes and blank lines' '
473 git update-index x &&
499 git diff --ignore-blank-lines >out.tmp &&
500 cat <<-\EOF >expected &&
529 compare_diff_patch expected out.tmp
532 test_expect_success
'check mixed spaces and tabs in indent' '
533 # This is indented with SP HT SP.
535 test_must_fail git diff --check >check &&
536 grep "space before tab in indent" check
539 test_expect_success
'check mixed tabs and spaces in indent' '
540 # This is indented with HT SP HT.
542 test_must_fail git diff --check >check &&
543 grep "space before tab in indent" check
546 test_expect_success
'check with no whitespace errors' '
547 git commit -m "snapshot" &&
552 test_expect_success
'check with trailing whitespace' '
554 test_must_fail git diff --check
557 test_expect_success
'check with space before tab in indent' '
558 # indent has space followed by hard tab
560 test_must_fail git diff --check
563 test_expect_success
'--check and --exit-code are not exclusive' '
565 git diff --check --exit-code
568 test_expect_success
'--check and --quiet are not exclusive' '
569 git diff --check --quiet
572 test_expect_success
'-w and --exit-code interact sensibly' '
573 test_when_finished "git checkout 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
584 test_expect_success
'-I and --exit-code interact sensibly' '
585 test_when_finished "git checkout 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
596 test_expect_success
'check staged with no whitespace errors' '
599 git diff --cached --check
602 test_expect_success
'check staged with trailing whitespace' '
605 test_must_fail git diff --cached --check
608 test_expect_success
'check staged with space before tab in indent' '
609 # indent has space followed by hard tab
612 test_must_fail git diff --cached --check
615 test_expect_success
'check with no whitespace errors (diff-index)' '
618 git diff-index --check HEAD
621 test_expect_success
'check with trailing whitespace (diff-index)' '
624 test_must_fail git diff-index --check HEAD
627 test_expect_success
'check with space before tab in indent (diff-index)' '
628 # indent has space followed by hard tab
631 test_must_fail git diff-index --check HEAD
634 test_expect_success
'check staged with no whitespace errors (diff-index)' '
637 git diff-index --cached --check HEAD
640 test_expect_success
'check staged with trailing whitespace (diff-index)' '
643 test_must_fail git diff-index --cached --check HEAD
646 test_expect_success
'check staged with space before tab in indent (diff-index)' '
647 # indent has space followed by hard tab
650 test_must_fail git diff-index --cached --check HEAD
653 test_expect_success
'check with no whitespace errors (diff-tree)' '
655 git commit -m "new commit" x &&
656 git diff-tree --check HEAD^ HEAD
659 test_expect_success
'check with trailing whitespace (diff-tree)' '
661 git commit -m "another commit" x &&
662 test_must_fail git diff-tree --check HEAD^ HEAD
665 test_expect_success
'check with space before tab in indent (diff-tree)' '
666 # indent has space followed by hard tab
668 git commit -m "yet another" x &&
669 test_must_fail git diff-tree --check HEAD^ HEAD
672 test_expect_success
'check with ignored trailing whitespace attr (diff-tree)' '
673 test_when_finished "git reset --hard HEAD^" &&
675 # create a whitespace error that should be ignored
676 echo "* -whitespace" >.gitattributes &&
677 git add .gitattributes &&
680 git commit -m "add trailing space" &&
682 # with a worktree diff-tree ignores the whitespace error
683 git diff-tree --root --check HEAD &&
685 # without a worktree diff-tree still ignores the whitespace error
686 git -C .git diff-tree --root --check HEAD
689 test_expect_success
'check trailing whitespace (trailing-space: off)' '
690 git config core.whitespace "-trailing-space" &&
691 echo "foo (); " >x &&
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
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 &&
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
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 &&
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
727 test_expect_success
'ditto, but tabwidth=9' '
728 git config core.whitespace "indent-with-non-tab,tabwidth=9" &&
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
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
743 test_expect_success
'ditto, but tabwidth=20' '
744 git config core.whitespace "indent-with-non-tab,tabwidth=20" &&
748 test_expect_success
'check tabs as indentation (tab-in-indent: off)' '
749 git config core.whitespace "-tab-in-indent" &&
750 echo " foo ();" >x &&
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
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
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
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" &&
774 test_must_fail git diff --check
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 &&
785 test_expect_success
'line numbers in --check output are correct' '
787 echo "foo(); " >>x &&
788 test_must_fail git diff --check >check &&
792 test_expect_success
'checkdiff detects new trailing blank lines (1)' '
795 test_must_fail git diff --check >check &&
796 grep "new blank line" check
799 test_expect_success
'checkdiff detects new trailing blank lines (2)' '
800 test_write_lines a b "" "" >x &&
802 test_write_lines a "" "" "" "" >x &&
803 test_must_fail git diff --check >check &&
804 grep "new blank line" check
807 test_expect_success
'checkdiff allows new blank lines' '
811 echo "/* This is new */" &&
818 test_expect_success
'whitespace-only changes not reported (diff)' '
820 echo >x "hello world" &&
822 git commit -m "hello 1" &&
823 echo >x "hello world" &&
824 git diff -b >actual &&
825 test_must_be_empty actual
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
834 test_expect_success
'whitespace changes with modification reported (diffstat)' '
836 echo >x "hello world" &&
837 git update-index --chmod=+x x &&
838 git diff --stat --cached -b >actual &&
839 cat <<-EOF >expect &&
841 1 file changed, 0 insertions(+), 0 deletions(-)
843 test_cmp expect actual
846 test_expect_success
'whitespace-only changes reported across renames (diffstat)' '
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 &&
850 git commit -m "base" &&
851 sed -e "5s/^/ /" x >z &&
854 git diff -w -M --cached --stat >actual &&
855 cat <<-EOF >expect &&
857 1 file changed, 0 insertions(+), 0 deletions(-)
859 test_cmp expect actual
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 &&
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 &&
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 &&
878 similarity index NUM%
881 index $before..$after 100644
883 test_cmp expect actual
887 diff --git a
/empty b
/void
888 similarity index
100%
893 test_expect_success
'rename empty' '
897 git commit -m empty &&
899 git diff -w --cached -M >current &&
900 test_cmp expected current
903 test_expect_success
'combined diff with autocrlf conversion' '
906 test_commit "one side" x hello one-side &&
907 git checkout HEAD^ &&
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 &&
914 git diff >actual.raw &&
915 sed -e "1,/^@@@/d" actual.raw >actual &&
920 # Start testing the colored format for whitespace checks
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 &&
932 git config core.autocrlf false
935 test_expect_success
'diff that introduces a line with only tabs' '
936 git config core.whitespace blank-at-eol &&
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 &&
948 cat >expected <<-EOF &&
949 <BOLD>diff --git a/x b/x<RESET>
950 <BOLD>index $before..$after 100644<RESET>
953 <CYAN>@@ -1 +1,4 @@<RESET>
955 <GREEN>+<RESET><GREEN>{<RESET>
956 <GREEN>+<RESET><BLUE> <RESET>
957 <GREEN>+<RESET><GREEN>}<RESET>
960 test_cmp expected current
963 test_expect_success
'diff that introduces and removes ws breakages' '
966 echo "0. blank-at-eol " &&
967 echo "1. blank-at-eol "
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 &&
973 echo "0. blank-at-eol " &&
974 echo "1. still-blank-at-eol " &&
975 echo "2. and a new line "
977 new_hash_x=$(git hash-object x) &&
978 after=$(git rev-parse --short "$new_hash_x") &&
980 git diff --color >current.raw &&
981 test_decode_color <current.raw >current &&
983 cat >expected <<-EOF &&
984 <BOLD>diff --git a/x b/x<RESET>
985 <BOLD>index $before..$after 100644<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>
995 test_cmp expected current
998 test_expect_success
'ws-error-highlight test setup' '
1002 echo "0. blank-at-eol " &&
1003 echo "1. blank-at-eol "
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 &&
1009 echo "0. blank-at-eol " &&
1010 echo "1. still-blank-at-eol " &&
1011 echo "2. and a new line "
1013 new_hash_x=$(git hash-object x) &&
1014 after=$(git rev-parse --short "$new_hash_x") &&
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>
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>
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>
1054 test_expect_success
'test --ws-error-highlight option' '
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 &&
1060 git diff --color --ws-error-highlight=all >current.raw &&
1061 test_decode_color <current.raw >current &&
1062 test_cmp expect.all current &&
1064 git diff --color --ws-error-highlight=none >current.raw &&
1065 test_decode_color <current.raw >current &&
1066 test_cmp expect.none current
1070 test_expect_success
'test diff.wsErrorHighlight config' '
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 &&
1076 git -c diff.wsErrorHighlight=all diff --color >current.raw &&
1077 test_decode_color <current.raw >current &&
1078 test_cmp expect.all current &&
1080 git -c diff.wsErrorHighlight=none diff --color >current.raw &&
1081 test_decode_color <current.raw >current &&
1082 test_cmp expect.none current
1086 test_expect_success
'option overrides diff.wsErrorHighlight' '
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 &&
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 &&
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
1105 test_expect_success
'detect moved code, complete file' '
1107 cat <<-\EOF >test.c &&
1111 printf("Hello World");
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>
1143 <BRED>-printf("Hello World");<RESET>
1147 test_cmp expected actual
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" &&
1156 cat <<-\EOF >main.c &&
1164 int secure_foo(struct user *u)
1166 if (!u->is_allowed_foo)
1176 cat <<-\EOF >test.c &&
1180 printf("Hello World, but different\n");
1183 int another_function()
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 &&
1205 cat <<-\EOF >test.c &&
1209 printf("Hello World, but different\n");
1212 int secure_foo(struct user *u)
1215 if (!u->is_allowed_foo)
1219 int another_function()
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>
1239 <BRED>-int secure_foo(struct user *u)<RESET>
1241 <BLUE>-if (!u->is_allowed_foo)<RESET>
1242 <BLUE>-return;<RESET>
1243 <RED>-foo(u);<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>
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>
1264 int another_function()<RESET>
1269 test_cmp expected actual
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>
1289 <BRED>-int secure_foo(struct user *u)<RESET>
1291 <BRED>-if (!u->is_allowed_foo)<RESET>
1292 <BRED>-return;<RESET>
1293 <BRED>-foo(u);<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>
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>
1314 int another_function()<RESET>
1319 test_cmp expected actual
1322 test_expect_success
'detect blocks of moved code' '
1324 cat <<-\EOF >lines.txt &&
1342 git add lines.txt &&
1343 git commit -m "add poetry" &&
1344 cat <<-\EOF >lines.txt &&
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>
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>
1396 <MAGENTA>-long line 14<RESET>
1397 <MAGENTA>-long line 15<RESET>
1398 <MAGENTA>-long line 16<RESET>
1400 test_cmp expected actual
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>
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>
1440 <BMAGENTA>-long line 14<RESET>
1441 <BMAGENTA>-long line 15<RESET>
1442 <BMAGENTA>-long line 16<RESET>
1444 test_cmp expected actual
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
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
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
1464 cat >new.txt <<-\EOF &&
1465 line 1A should be marked as oldMoved newMovedAlternate
1466 line 1B should be marked as oldMoved newMovedAlternate
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
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
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>
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>
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>
1516 test_cmp expected actual
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
1527 this line should be marked as oldMoved newMoved
1528 this line should be marked as oldMovedAlternate newMoved
1533 this line should be marked as oldMoved newMoved/newMovedAlternate
1535 cat >new.txt <<-\EOF &&
1539 this line should be marked as moved
1543 this line should be marked as oldMoved newMoved/newMovedAlternate
1546 this line should be marked as oldMovedAlternate newMoved
1547 this line should be marked as oldMoved newMoved/newMovedAlternate
1549 this line should be marked as oldMoved newMoved
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>
1564 <BOLD;CYAN>+<RESET><BOLD;CYAN>this line should be marked as moved<RESET>
1565 <GREEN>+<RESET><GREEN>too short<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>
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>
1577 <BOLD;CYAN>+<RESET><BOLD;CYAN>this line should be marked as oldMoved newMoved<RESET>
1579 <BOLD;MAGENTA>-this line should be marked as oldMoved newMoved/newMovedAlternate<RESET>
1581 test_cmp expect actual
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>
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>
1620 <MAGENTA>-long line 14<RESET>
1621 <MAGENTA>-long line 15<RESET>
1622 <MAGENTA>-long line 16<RESET>
1624 test_cmp expected actual
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.
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.
1636 git diff --color-moved --word-diff >actual &&
1637 git diff --word-diff >expect &&
1638 test_cmp expect actual
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
1647 test_expect_success
'set up whitespace tests' '
1649 # Note that these lines have no leading or trailing whitespace.
1650 cat <<-\EOF >lines.txt &&
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"
1667 test_expect_success
'move detection ignoring whitespace ' '
1668 q_to_tab <<-\EOF >lines.txt &&
1672 Qchanged long line 9
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>
1695 <RED>-long line 6<RESET>
1696 <RED>-long line 7<RESET>
1697 <RED>-long line 8<RESET>
1698 <RED>-long line 9<RESET>
1700 test_cmp expected actual &&
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>
1719 <MAGENTA>-long line 6<RESET>
1720 <MAGENTA>-long line 7<RESET>
1721 <MAGENTA>-long line 8<RESET>
1722 <RED>-long line 9<RESET>
1724 test_cmp expected actual
1727 test_expect_success
'move detection ignoring whitespace changes' '
1729 # Lines 6-8 have a space change, but 9 is new whitespace
1730 q_to_tab <<-\EOF >lines.txt &&
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>
1758 <RED>-long line 6<RESET>
1759 <RED>-long line 7<RESET>
1760 <RED>-long line 8<RESET>
1761 <RED>-long line 9<RESET>
1763 test_cmp expected actual &&
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>
1782 <MAGENTA>-long line 6<RESET>
1783 <MAGENTA>-long line 7<RESET>
1784 <MAGENTA>-long line 8<RESET>
1785 <RED>-long line 9<RESET>
1787 test_cmp expected actual
1790 test_expect_success
'move detection ignoring whitespace at eol' '
1792 # Lines 6-9 have new eol whitespace, but 9 also has it in the middle
1793 q_to_tab <<-\EOF >lines.txt &&
1805 # avoid cluttering the output with complaints about our eol whitespace
1806 test_config core.whitespace -blank-at-eol &&
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>
1824 <RED>-long line 6<RESET>
1825 <RED>-long line 7<RESET>
1826 <RED>-long line 8<RESET>
1827 <RED>-long line 9<RESET>
1829 test_cmp expected actual &&
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>
1848 <MAGENTA>-long line 6<RESET>
1849 <MAGENTA>-long line 7<RESET>
1850 <MAGENTA>-long line 8<RESET>
1851 <RED>-long line 9<RESET>
1853 test_cmp expected actual
1856 test_expect_success
'clean up whitespace-test colors' '
1857 git config --unset color.diff.oldMoved &&
1858 git config --unset color.diff.newMoved
1861 test_expect_success
'--color-moved block at end of diff output respects MIN_ALNUM_COUNT' '
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>
1894 test_cmp expected actual
1897 test_expect_success
'--color-moved respects MIN_ALNUM_COUNT' '
1900 nineteen chars 456789
1902 twenty chars 234567890
1912 twenty chars 234567890
1913 nineteen chars 456789
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>
1934 test_cmp expected actual
1937 test_expect_success
'--color-moved treats adjacent blocks as separate for MIN_ALNUM_COUNT' '
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>
1978 test_cmp expected actual
1981 test_expect_success
'--color-moved rewinds for MIN_ALNUM_COUNT' '
1983 test_write_lines >file \
1984 A B C one two three four five six seven D E F G H I J &&
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 &&
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>
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>
2012 <CYAN>@@ -15,3 +10,9 @@<RESET> <RESET>G<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>
2024 test_cmp expected actual
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 &&
2035 git commit -a -m "bananas are like a heavy library?" &&
2036 echo foul >bananas/recipe &&
2037 echo ripe >fruit.t &&
2039 git diff --submodule=diff --color-moved --color >actual &&
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 &&
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 &&
2051 git submodule deinit bananas
2054 test_expect_success
'only move detection ignores white spaces' '
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
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
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>
2082 test_cmp expected actual &&
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>
2100 test_cmp expected actual
2103 test_expect_success
'compare whitespace delta across moved blocks' '
2106 q_to_tab <<-\EOF >text.txt &&
2110 QBut! <- this stands out
2112 QQdifferent starting
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
2125 git commit -m "add text.txt" &&
2127 q_to_tab <<-\EOF >text.txt &&
2131 QQQBut! <- this stands out
2139 QQthat has similar lines
2140 QQto previous blocks, but with different indent
2141 QQYetQAnotherQoutlier
2142 QLine with internal whitespace change
2145 git diff --color --color-moved --color-moved-ws=allow-indentation-change >actual.raw &&
2146 grep -v "index" actual.raw | test_decode_color >actual &&
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>
2185 test_cmp expected actual
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 &&
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 &&
2197 test_must_fail git diff --color-moved-ws=bogus 2>err &&
2198 test_i18ngrep "possible values" err &&
2199 test_i18ngrep bogus err &&
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
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 \
2210 test_i18ngrep allow-indentation-change err
2214 test_expect_success
'compare mixed whitespace delta across moved blocks' '
2217 tr "^|Q_" "\f\v\t " <<-EOF >text.txt &&
2219 |____too short without
2221 ___being grouped across blank line
2227 ____Indented text to
2228 _Q____be further indented by four spaces across
2230 QQ____These two lines have had their
2231 ____indentation reduced by four spaces
2232 Qdifferent indentation change
2237 git commit -m "add text.txt" &&
2239 tr "^|Q_" "\f\v\t " <<-EOF >text.txt &&
2245 QQbe further indented by four spaces across
2250 ^Q_______being grouped across blank line
2252 Q_QThese two lines have had their
2253 indentation reduced by four spaces
2254 QQdifferent indentation change
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 &&
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>
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>
2299 test_cmp expected actual
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 &&
2317 test_cmp expect actual
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 &&
2340 test_cmp expect actual