3 # Copyright (c) 2006 Johannes E. Schindelin
6 test_description
='Test special whitespace in diff engine.
10 .
"$TEST_DIRECTORY"/diff-lib.sh
12 test_expect_success
"Ray Lehtiniemi's example" '
18 git update-index --add x &&
28 cat <<-\EOF >expect &&
30 index adf3937..6edc172 100644
44 test_cmp expect out &&
47 test_cmp expect out &&
53 test_expect_success
'another test, without options' '
54 tr Q "\015" <<-\EOF >x &&
55 whitespace at beginning
57 whitespace in the middle
65 tr "_" " " <<-\EOF >x &&
66 _ whitespace at beginning
68 white space in the middle
74 tr "Q_" "\015 " <<-\EOF >expect &&
76 index d99af23..22d9f73 100644
80 -whitespace at beginning
82 -whitespace in the middle
84 + whitespace at beginning
86 +white space in the middle
94 test_cmp expect out &&
98 test_cmp expect out &&
100 git diff -w -b >out &&
101 test_cmp expect out &&
103 git diff -w --ignore-space-at-eol >out &&
104 test_cmp expect out &&
106 git diff -w -b --ignore-space-at-eol >out &&
107 test_cmp expect out &&
109 git diff -w --ignore-cr-at-eol >out &&
110 test_cmp expect out &&
112 tr "Q_" "\015 " <<-\EOF >expect &&
114 index d99af23..22d9f73 100644
118 -whitespace at beginning
119 +_ whitespace at beginning
121 -whitespace in the middle
122 +white space in the middle
128 test_cmp expect out &&
130 git diff -b --ignore-space-at-eol >out &&
131 test_cmp expect out &&
133 git diff -b --ignore-cr-at-eol >out &&
134 test_cmp expect out &&
136 tr "Q_" "\015 " <<-\EOF >expect &&
138 index d99af23..22d9f73 100644
142 -whitespace at beginning
144 -whitespace in the middle
145 +_ whitespace at beginning
147 +white space in the middle
152 git diff --ignore-space-at-eol >out &&
153 test_cmp expect out &&
155 git diff --ignore-space-at-eol --ignore-cr-at-eol >out &&
156 test_cmp expect out &&
158 tr "Q_" "\015 " <<-\EOF >expect &&
160 index_d99af23..22d9f73 100644
164 -whitespace at beginning
166 -whitespace in the middle
168 +_ whitespace at beginning
170 +white space in the middle
175 git diff --ignore-cr-at-eol >out &&
179 test_expect_success
'ignore-blank-lines: only new lines' '
181 git update-index x &&
182 test_seq 5 | sed "/3/i\\
184 git diff --ignore-blank-lines >out &&
189 test_expect_success
'ignore-blank-lines: only new lines with space' '
191 git update-index x &&
192 test_seq 5 | sed "/3/i\\
194 git diff -w --ignore-blank-lines >out &&
199 test_expect_success
'ignore-blank-lines: after change' '
211 git update-index x &&
224 git diff --inter-hunk-context=100 --ignore-blank-lines >out.tmp &&
225 cat <<-\EOF >expected &&
239 compare_diff_patch expected out.tmp
242 test_expect_success
'ignore-blank-lines: before change' '
253 git update-index x &&
266 git diff --inter-hunk-context=100 --ignore-blank-lines >out.tmp &&
267 cat <<-\EOF >expected &&
280 compare_diff_patch expected out.tmp
283 test_expect_success
'ignore-blank-lines: between changes' '
298 git update-index x &&
315 git diff --ignore-blank-lines >out.tmp &&
316 cat <<-\EOF >expected &&
337 compare_diff_patch expected out.tmp
340 test_expect_success
'ignore-blank-lines: between changes (with interhunkctx)' '
342 git update-index x &&
360 git diff --inter-hunk-context=2 --ignore-blank-lines >out.tmp &&
361 cat <<-\EOF >expected &&
382 compare_diff_patch expected out.tmp
385 test_expect_success
'ignore-blank-lines: scattered spaces' '
387 git update-index x &&
408 git diff --inter-hunk-context=4 --ignore-blank-lines >out.tmp &&
409 cat <<-\EOF >expected &&
424 compare_diff_patch expected out.tmp
427 test_expect_success
'ignore-blank-lines: spaces coalesce' '
429 git update-index x &&
443 git diff --inter-hunk-context=4 --ignore-blank-lines >out.tmp &&
444 cat <<-\EOF >expected &&
461 compare_diff_patch expected out.tmp
464 test_expect_success
'ignore-blank-lines: mix changes and blank lines' '
466 git update-index x &&
492 git diff --ignore-blank-lines >out.tmp &&
493 cat <<-\EOF >expected &&
522 compare_diff_patch expected out.tmp
525 test_expect_success
'check mixed spaces and tabs in indent' '
526 # This is indented with SP HT SP.
528 git diff --check | grep "space before tab in indent"
531 test_expect_success
'check mixed tabs and spaces in indent' '
532 # This is indented with HT SP HT.
534 git diff --check | grep "space before tab in indent"
537 test_expect_success
'check with no whitespace errors' '
538 git commit -m "snapshot" &&
543 test_expect_success
'check with trailing whitespace' '
545 test_must_fail git diff --check
548 test_expect_success
'check with space before tab in indent' '
549 # indent has space followed by hard tab
551 test_must_fail git diff --check
554 test_expect_success
'--check and --exit-code are not exclusive' '
556 git diff --check --exit-code
559 test_expect_success
'--check and --quiet are not exclusive' '
560 git diff --check --quiet
563 test_expect_success
'check staged with no whitespace errors' '
566 git diff --cached --check
569 test_expect_success
'check staged with trailing whitespace' '
572 test_must_fail git diff --cached --check
575 test_expect_success
'check staged with space before tab in indent' '
576 # indent has space followed by hard tab
579 test_must_fail git diff --cached --check
582 test_expect_success
'check with no whitespace errors (diff-index)' '
585 git diff-index --check HEAD
588 test_expect_success
'check with trailing whitespace (diff-index)' '
591 test_must_fail git diff-index --check HEAD
594 test_expect_success
'check with space before tab in indent (diff-index)' '
595 # indent has space followed by hard tab
598 test_must_fail git diff-index --check HEAD
601 test_expect_success
'check staged with no whitespace errors (diff-index)' '
604 git diff-index --cached --check HEAD
607 test_expect_success
'check staged with trailing whitespace (diff-index)' '
610 test_must_fail git diff-index --cached --check HEAD
613 test_expect_success
'check staged with space before tab in indent (diff-index)' '
614 # indent has space followed by hard tab
617 test_must_fail git diff-index --cached --check HEAD
620 test_expect_success
'check with no whitespace errors (diff-tree)' '
622 git commit -m "new commit" x &&
623 git diff-tree --check HEAD^ HEAD
626 test_expect_success
'check with trailing whitespace (diff-tree)' '
628 git commit -m "another commit" x &&
629 test_must_fail git diff-tree --check HEAD^ HEAD
632 test_expect_success
'check with space before tab in indent (diff-tree)' '
633 # indent has space followed by hard tab
635 git commit -m "yet another" x &&
636 test_must_fail git diff-tree --check HEAD^ HEAD
639 test_expect_success
'check with ignored trailing whitespace attr (diff-tree)' '
640 test_when_finished "git reset --hard HEAD^" &&
642 # create a whitespace error that should be ignored
643 echo "* -whitespace" >.gitattributes &&
644 git add .gitattributes &&
647 git commit -m "add trailing space" &&
649 # with a worktree diff-tree ignores the whitespace error
650 git diff-tree --root --check HEAD &&
652 # without a worktree diff-tree still ignores the whitespace error
653 git -C .git diff-tree --root --check HEAD
656 test_expect_success
'check trailing whitespace (trailing-space: off)' '
657 git config core.whitespace "-trailing-space" &&
658 echo "foo (); " >x &&
662 test_expect_success
'check trailing whitespace (trailing-space: on)' '
663 git config core.whitespace "trailing-space" &&
664 echo "foo (); " >x &&
665 test_must_fail git diff --check
668 test_expect_success
'check space before tab in indent (space-before-tab: off)' '
669 # indent contains space followed by HT
670 git config core.whitespace "-space-before-tab" &&
671 echo " foo ();" >x &&
675 test_expect_success
'check space before tab in indent (space-before-tab: on)' '
676 # indent contains space followed by HT
677 git config core.whitespace "space-before-tab" &&
678 echo " foo (); " >x &&
679 test_must_fail git diff --check
682 test_expect_success
'check spaces as indentation (indent-with-non-tab: off)' '
683 git config core.whitespace "-indent-with-non-tab" &&
684 echo " foo ();" >x &&
688 test_expect_success
'check spaces as indentation (indent-with-non-tab: on)' '
689 git config core.whitespace "indent-with-non-tab" &&
690 echo " foo ();" >x &&
691 test_must_fail git diff --check
694 test_expect_success
'ditto, but tabwidth=9' '
695 git config core.whitespace "indent-with-non-tab,tabwidth=9" &&
699 test_expect_success
'check tabs and spaces as indentation (indent-with-non-tab: on)' '
700 git config core.whitespace "indent-with-non-tab" &&
701 echo " foo ();" >x &&
702 test_must_fail git diff --check
705 test_expect_success
'ditto, but tabwidth=10' '
706 git config core.whitespace "indent-with-non-tab,tabwidth=10" &&
707 test_must_fail git diff --check
710 test_expect_success
'ditto, but tabwidth=20' '
711 git config core.whitespace "indent-with-non-tab,tabwidth=20" &&
715 test_expect_success
'check tabs as indentation (tab-in-indent: off)' '
716 git config core.whitespace "-tab-in-indent" &&
717 echo " foo ();" >x &&
721 test_expect_success
'check tabs as indentation (tab-in-indent: on)' '
722 git config core.whitespace "tab-in-indent" &&
723 echo " foo ();" >x &&
724 test_must_fail git diff --check
727 test_expect_success
'check tabs and spaces as indentation (tab-in-indent: on)' '
728 git config core.whitespace "tab-in-indent" &&
729 echo " foo ();" >x &&
730 test_must_fail git diff --check
733 test_expect_success
'ditto, but tabwidth=1 (must be irrelevant)' '
734 git config core.whitespace "tab-in-indent,tabwidth=1" &&
735 test_must_fail git diff --check
738 test_expect_success
'check tab-in-indent and indent-with-non-tab conflict' '
739 git config core.whitespace "tab-in-indent,indent-with-non-tab" &&
741 test_must_fail git diff --check
744 test_expect_success
'check tab-in-indent excluded from wildcard whitespace attribute' '
745 git config --unset core.whitespace &&
746 echo "x whitespace" >.gitattributes &&
747 echo " foo ();" >x &&
752 test_expect_success
'line numbers in --check output are correct' '
754 echo "foo(); " >>x &&
755 git diff --check | grep "x:2:"
758 test_expect_success
'checkdiff detects new trailing blank lines (1)' '
761 git diff --check | grep "new blank line"
764 test_expect_success
'checkdiff detects new trailing blank lines (2)' '
765 { echo a; echo b; echo; echo; } >x &&
767 { echo a; echo; echo; echo; echo; } >x &&
768 git diff --check | grep "new blank line"
771 test_expect_success
'checkdiff allows new blank lines' '
775 echo "/* This is new */" &&
784 test_expect_success
'whitespace-only changes not reported' '
786 echo >x "hello world" &&
788 git commit -m "hello 1" &&
789 echo >x "hello world" &&
790 git diff -b >actual &&
791 test_cmp expect actual
796 similarity index NUM%
799 index 380c32a..a97b785 100644
801 test_expect_success
'whitespace-only changes reported across renames' '
803 for i in 1 2 3 4 5 6 7 8 9; do echo "$i$i$i$i$i$i"; done >x &&
805 git commit -m "base" &&
806 sed -e "5s/^/ /" x >z &&
809 git diff -w -M --cached |
810 sed -e "/^similarity index /s/[0-9][0-9]*/NUM/" >actual &&
811 test_cmp expect actual
815 diff --git a
/empty b
/void
816 similarity index
100%
821 test_expect_success
'rename empty' '
825 git commit -m empty &&
827 git diff -w --cached -M >current &&
828 test_cmp expected current
831 test_expect_success
'combined diff with autocrlf conversion' '
835 git commit -m "one side" x &&
836 git checkout HEAD^ &&
838 git commit -m "the other side" x &&
839 git config core.autocrlf true &&
840 test_must_fail git merge master &&
842 git diff | sed -e "1,/^@@@/d" >actual &&
847 # Start testing the colored format for whitespace checks
849 test_expect_success
'setup diff colors' '
850 git config color.diff.plain normal &&
851 git config color.diff.meta bold &&
852 git config color.diff.frag cyan &&
853 git config color.diff.func normal &&
854 git config color.diff.old red &&
855 git config color.diff.new green &&
856 git config color.diff.commit yellow &&
857 git config color.diff.whitespace blue &&
859 git config core.autocrlf false
862 test_expect_success
'diff that introduces a line with only tabs' '
863 git config core.whitespace blank-at-eol &&
866 git commit -m "initial" x &&
867 echo "{NTN}" | tr "NT" "\n\t" >>x &&
868 git diff --color | test_decode_color >current &&
870 cat >expected <<-\EOF &&
871 <BOLD>diff --git a/x b/x<RESET>
872 <BOLD>index 9daeafb..2874b91 100644<RESET>
875 <CYAN>@@ -1 +1,4 @@<RESET>
877 <GREEN>+<RESET><GREEN>{<RESET>
878 <GREEN>+<RESET><BLUE> <RESET>
879 <GREEN>+<RESET><GREEN>}<RESET>
882 test_cmp expected current
885 test_expect_success
'diff that introduces and removes ws breakages' '
888 echo "0. blank-at-eol " &&
889 echo "1. blank-at-eol "
891 git commit -a --allow-empty -m preimage &&
893 echo "0. blank-at-eol " &&
894 echo "1. still-blank-at-eol " &&
895 echo "2. and a new line "
899 test_decode_color >current &&
901 cat >expected <<-\EOF &&
902 <BOLD>diff --git a/x b/x<RESET>
903 <BOLD>index d0233a2..700886e 100644<RESET>
906 <CYAN>@@ -1,2 +1,3 @@<RESET>
907 0. blank-at-eol <RESET>
908 <RED>-1. blank-at-eol <RESET>
909 <GREEN>+<RESET><GREEN>1. still-blank-at-eol<RESET><BLUE> <RESET>
910 <GREEN>+<RESET><GREEN>2. and a new line<RESET><BLUE> <RESET>
913 test_cmp expected current
916 test_expect_success
'ws-error-highlight test setup' '
920 echo "0. blank-at-eol " &&
921 echo "1. blank-at-eol "
923 git commit -a --allow-empty -m preimage &&
925 echo "0. blank-at-eol " &&
926 echo "1. still-blank-at-eol " &&
927 echo "2. and a new line "
930 cat >expect.default-old <<-\EOF &&
931 <BOLD>diff --git a/x b/x<RESET>
932 <BOLD>index d0233a2..700886e 100644<RESET>
935 <CYAN>@@ -1,2 +1,3 @@<RESET>
936 0. blank-at-eol <RESET>
937 <RED>-<RESET><RED>1. blank-at-eol<RESET><BLUE> <RESET>
938 <GREEN>+<RESET><GREEN>1. still-blank-at-eol<RESET><BLUE> <RESET>
939 <GREEN>+<RESET><GREEN>2. and a new line<RESET><BLUE> <RESET>
942 cat >expect.all <<-\EOF &&
943 <BOLD>diff --git a/x b/x<RESET>
944 <BOLD>index d0233a2..700886e 100644<RESET>
947 <CYAN>@@ -1,2 +1,3 @@<RESET>
948 <RESET>0. blank-at-eol<RESET><BLUE> <RESET>
949 <RED>-<RESET><RED>1. blank-at-eol<RESET><BLUE> <RESET>
950 <GREEN>+<RESET><GREEN>1. still-blank-at-eol<RESET><BLUE> <RESET>
951 <GREEN>+<RESET><GREEN>2. and a new line<RESET><BLUE> <RESET>
954 cat >expect.none <<-\EOF
955 <BOLD>diff --git a/x b/x<RESET>
956 <BOLD>index d0233a2..700886e 100644<RESET>
959 <CYAN>@@ -1,2 +1,3 @@<RESET>
960 0. blank-at-eol <RESET>
961 <RED>-1. blank-at-eol <RESET>
962 <GREEN>+1. still-blank-at-eol <RESET>
963 <GREEN>+2. and a new line <RESET>
968 test_expect_success
'test --ws-error-highlight option' '
970 git diff --color --ws-error-highlight=default,old |
971 test_decode_color >current &&
972 test_cmp expect.default-old current &&
974 git diff --color --ws-error-highlight=all |
975 test_decode_color >current &&
976 test_cmp expect.all current &&
978 git diff --color --ws-error-highlight=none |
979 test_decode_color >current &&
980 test_cmp expect.none current
984 test_expect_success
'test diff.wsErrorHighlight config' '
986 git -c diff.wsErrorHighlight=default,old diff --color |
987 test_decode_color >current &&
988 test_cmp expect.default-old current &&
990 git -c diff.wsErrorHighlight=all diff --color |
991 test_decode_color >current &&
992 test_cmp expect.all current &&
994 git -c diff.wsErrorHighlight=none diff --color |
995 test_decode_color >current &&
996 test_cmp expect.none current
1000 test_expect_success
'option overrides diff.wsErrorHighlight' '
1002 git -c diff.wsErrorHighlight=none \
1003 diff --color --ws-error-highlight=default,old |
1004 test_decode_color >current &&
1005 test_cmp expect.default-old current &&
1007 git -c diff.wsErrorHighlight=default \
1008 diff --color --ws-error-highlight=all |
1009 test_decode_color >current &&
1010 test_cmp expect.all current &&
1012 git -c diff.wsErrorHighlight=all \
1013 diff --color --ws-error-highlight=none |
1014 test_decode_color >current &&
1015 test_cmp expect.none current
1019 test_expect_success
'detect moved code, complete file' '
1021 cat <<-\EOF >test.c &&
1025 printf("Hello World");
1029 git commit -m "add main function" &&
1030 git mv test.c main.c &&
1031 test_config color.diff.oldMoved "normal red" &&
1032 test_config color.diff.newMoved "normal green" &&
1033 git diff HEAD --color-moved=zebra --color --no-renames | test_decode_color >actual &&
1034 cat >expected <<-\EOF &&
1035 <BOLD>diff --git a/main.c b/main.c<RESET>
1036 <BOLD>new file mode 100644<RESET>
1037 <BOLD>index 0000000..a986c57<RESET>
1038 <BOLD>--- /dev/null<RESET>
1039 <BOLD>+++ b/main.c<RESET>
1040 <CYAN>@@ -0,0 +1,5 @@<RESET>
1041 <BGREEN>+<RESET><BGREEN>#include<stdio.h><RESET>
1042 <BGREEN>+<RESET><BGREEN>main()<RESET>
1043 <BGREEN>+<RESET><BGREEN>{<RESET>
1044 <BGREEN>+<RESET><BGREEN>printf("Hello World");<RESET>
1045 <BGREEN>+<RESET><BGREEN>}<RESET>
1046 <BOLD>diff --git a/test.c b/test.c<RESET>
1047 <BOLD>deleted file mode 100644<RESET>
1048 <BOLD>index a986c57..0000000<RESET>
1049 <BOLD>--- a/test.c<RESET>
1050 <BOLD>+++ /dev/null<RESET>
1051 <CYAN>@@ -1,5 +0,0 @@<RESET>
1052 <BRED>-#include<stdio.h><RESET>
1053 <BRED>-main()<RESET>
1055 <BRED>-printf("Hello World");<RESET>
1059 test_cmp expected actual
1062 test_expect_success
'detect malicious moved code, inside file' '
1063 test_config color.diff.oldMoved "normal red" &&
1064 test_config color.diff.newMoved "normal green" &&
1065 test_config color.diff.oldMovedAlternative "blue" &&
1066 test_config color.diff.newMovedAlternative "yellow" &&
1068 cat <<-\EOF >main.c &&
1076 int secure_foo(struct user *u)
1078 if (!u->is_allowed_foo)
1088 cat <<-\EOF >test.c &&
1092 printf("Hello World, but different\n");
1095 int another_function()
1100 git add main.c test.c &&
1101 git commit -m "add main and test file" &&
1102 cat <<-\EOF >main.c &&
1115 cat <<-\EOF >test.c &&
1119 printf("Hello World, but different\n");
1122 int secure_foo(struct user *u)
1125 if (!u->is_allowed_foo)
1129 int another_function()
1134 git diff HEAD --no-renames --color-moved=zebra --color | test_decode_color >actual &&
1135 cat <<-\EOF >expected &&
1136 <BOLD>diff --git a/main.c b/main.c<RESET>
1137 <BOLD>index 27a619c..7cf9336 100644<RESET>
1138 <BOLD>--- a/main.c<RESET>
1139 <BOLD>+++ b/main.c<RESET>
1140 <CYAN>@@ -5,13 +5,6 @@<RESET> <RESET>printf("Hello ");<RESET>
1141 printf("World\n");<RESET>
1144 <BRED>-int secure_foo(struct user *u)<RESET>
1146 <BLUE>-if (!u->is_allowed_foo)<RESET>
1147 <BLUE>-return;<RESET>
1148 <RED>-foo(u);<RESET>
1154 <BOLD>diff --git a/test.c b/test.c<RESET>
1155 <BOLD>index 1dc1d85..2bedec9 100644<RESET>
1156 <BOLD>--- a/test.c<RESET>
1157 <BOLD>+++ b/test.c<RESET>
1158 <CYAN>@@ -4,6 +4,13 @@<RESET> <RESET>int bar()<RESET>
1159 printf("Hello World, but different\n");<RESET>
1162 <BGREEN>+<RESET><BGREEN>int secure_foo(struct user *u)<RESET>
1163 <BGREEN>+<RESET><BGREEN>{<RESET>
1164 <GREEN>+<RESET><GREEN>foo(u);<RESET>
1165 <BGREEN>+<RESET><BGREEN>if (!u->is_allowed_foo)<RESET>
1166 <BGREEN>+<RESET><BGREEN>return;<RESET>
1167 <GREEN>+<RESET><GREEN>}<RESET>
1169 int another_function()<RESET>
1174 test_cmp expected actual
1177 test_expect_success
'plain moved code, inside file' '
1178 test_config color.diff.oldMoved "normal red" &&
1179 test_config color.diff.newMoved "normal green" &&
1180 test_config color.diff.oldMovedAlternative "blue" &&
1181 test_config color.diff.newMovedAlternative "yellow" &&
1182 # needs previous test as setup
1183 git diff HEAD --no-renames --color-moved=plain --color | test_decode_color >actual &&
1184 cat <<-\EOF >expected &&
1185 <BOLD>diff --git a/main.c b/main.c<RESET>
1186 <BOLD>index 27a619c..7cf9336 100644<RESET>
1187 <BOLD>--- a/main.c<RESET>
1188 <BOLD>+++ b/main.c<RESET>
1189 <CYAN>@@ -5,13 +5,6 @@<RESET> <RESET>printf("Hello ");<RESET>
1190 printf("World\n");<RESET>
1193 <BRED>-int secure_foo(struct user *u)<RESET>
1195 <BRED>-if (!u->is_allowed_foo)<RESET>
1196 <BRED>-return;<RESET>
1197 <BRED>-foo(u);<RESET>
1203 <BOLD>diff --git a/test.c b/test.c<RESET>
1204 <BOLD>index 1dc1d85..2bedec9 100644<RESET>
1205 <BOLD>--- a/test.c<RESET>
1206 <BOLD>+++ b/test.c<RESET>
1207 <CYAN>@@ -4,6 +4,13 @@<RESET> <RESET>int bar()<RESET>
1208 printf("Hello World, but different\n");<RESET>
1211 <BGREEN>+<RESET><BGREEN>int secure_foo(struct user *u)<RESET>
1212 <BGREEN>+<RESET><BGREEN>{<RESET>
1213 <BGREEN>+<RESET><BGREEN>foo(u);<RESET>
1214 <BGREEN>+<RESET><BGREEN>if (!u->is_allowed_foo)<RESET>
1215 <BGREEN>+<RESET><BGREEN>return;<RESET>
1216 <BGREEN>+<RESET><BGREEN>}<RESET>
1218 int another_function()<RESET>
1223 test_cmp expected actual
1226 test_expect_success
'detect blocks of moved code' '
1228 cat <<-\EOF >lines.txt &&
1246 git add lines.txt &&
1247 git commit -m "add poetry" &&
1248 cat <<-\EOF >lines.txt &&
1266 test_config color.diff.oldMoved "magenta" &&
1267 test_config color.diff.newMoved "cyan" &&
1268 test_config color.diff.oldMovedAlternative "blue" &&
1269 test_config color.diff.newMovedAlternative "yellow" &&
1270 test_config color.diff.oldMovedDimmed "normal magenta" &&
1271 test_config color.diff.newMovedDimmed "normal cyan" &&
1272 test_config color.diff.oldMovedAlternativeDimmed "normal blue" &&
1273 test_config color.diff.newMovedAlternativeDimmed "normal yellow" &&
1274 git diff HEAD --no-renames --color-moved=blocks --color >actual.raw &&
1275 grep -v "index" actual.raw | test_decode_color >actual &&
1276 cat <<-\EOF >expected &&
1277 <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1278 <BOLD>--- a/lines.txt<RESET>
1279 <BOLD>+++ b/lines.txt<RESET>
1280 <CYAN>@@ -1,16 +1,16 @@<RESET>
1281 <MAGENTA>-long line 1<RESET>
1282 <MAGENTA>-long line 2<RESET>
1283 <MAGENTA>-long line 3<RESET>
1290 <CYAN>+<RESET><CYAN>long line 1<RESET>
1291 <CYAN>+<RESET><CYAN>long line 2<RESET>
1292 <CYAN>+<RESET><CYAN>long line 3<RESET>
1293 <CYAN>+<RESET><CYAN>long line 14<RESET>
1294 <CYAN>+<RESET><CYAN>long line 15<RESET>
1295 <CYAN>+<RESET><CYAN>long line 16<RESET>
1300 <MAGENTA>-long line 14<RESET>
1301 <MAGENTA>-long line 15<RESET>
1302 <MAGENTA>-long line 16<RESET>
1304 test_cmp expected actual
1308 test_expect_success
'detect permutations inside moved code -- dimmed_zebra' '
1309 # reuse setup from test before!
1310 test_config color.diff.oldMoved "magenta" &&
1311 test_config color.diff.newMoved "cyan" &&
1312 test_config color.diff.oldMovedAlternative "blue" &&
1313 test_config color.diff.newMovedAlternative "yellow" &&
1314 test_config color.diff.oldMovedDimmed "normal magenta" &&
1315 test_config color.diff.newMovedDimmed "normal cyan" &&
1316 test_config color.diff.oldMovedAlternativeDimmed "normal blue" &&
1317 test_config color.diff.newMovedAlternativeDimmed "normal yellow" &&
1318 git diff HEAD --no-renames --color-moved=dimmed_zebra --color >actual.raw &&
1319 grep -v "index" actual.raw | test_decode_color >actual &&
1320 cat <<-\EOF >expected &&
1321 <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1322 <BOLD>--- a/lines.txt<RESET>
1323 <BOLD>+++ b/lines.txt<RESET>
1324 <CYAN>@@ -1,16 +1,16 @@<RESET>
1325 <BMAGENTA>-long line 1<RESET>
1326 <BMAGENTA>-long line 2<RESET>
1327 <BMAGENTA>-long line 3<RESET>
1334 <BCYAN>+<RESET><BCYAN>long line 1<RESET>
1335 <BCYAN>+<RESET><BCYAN>long line 2<RESET>
1336 <CYAN>+<RESET><CYAN>long line 3<RESET>
1337 <YELLOW>+<RESET><YELLOW>long line 14<RESET>
1338 <BYELLOW>+<RESET><BYELLOW>long line 15<RESET>
1339 <BYELLOW>+<RESET><BYELLOW>long line 16<RESET>
1344 <BMAGENTA>-long line 14<RESET>
1345 <BMAGENTA>-long line 15<RESET>
1346 <BMAGENTA>-long line 16<RESET>
1348 test_cmp expected actual
1351 test_expect_success
'cmd option assumes configured colored-moved' '
1352 test_config color.diff.oldMoved "magenta" &&
1353 test_config color.diff.newMoved "cyan" &&
1354 test_config color.diff.oldMovedAlternative "blue" &&
1355 test_config color.diff.newMovedAlternative "yellow" &&
1356 test_config color.diff.oldMovedDimmed "normal magenta" &&
1357 test_config color.diff.newMovedDimmed "normal cyan" &&
1358 test_config color.diff.oldMovedAlternativeDimmed "normal blue" &&
1359 test_config color.diff.newMovedAlternativeDimmed "normal yellow" &&
1360 test_config diff.colorMoved zebra &&
1361 git diff HEAD --no-renames --color-moved --color >actual.raw &&
1362 grep -v "index" actual.raw | test_decode_color >actual &&
1363 cat <<-\EOF >expected &&
1364 <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1365 <BOLD>--- a/lines.txt<RESET>
1366 <BOLD>+++ b/lines.txt<RESET>
1367 <CYAN>@@ -1,16 +1,16 @@<RESET>
1368 <MAGENTA>-long line 1<RESET>
1369 <MAGENTA>-long line 2<RESET>
1370 <MAGENTA>-long line 3<RESET>
1377 <CYAN>+<RESET><CYAN>long line 1<RESET>
1378 <CYAN>+<RESET><CYAN>long line 2<RESET>
1379 <CYAN>+<RESET><CYAN>long line 3<RESET>
1380 <YELLOW>+<RESET><YELLOW>long line 14<RESET>
1381 <YELLOW>+<RESET><YELLOW>long line 15<RESET>
1382 <YELLOW>+<RESET><YELLOW>long line 16<RESET>
1387 <MAGENTA>-long line 14<RESET>
1388 <MAGENTA>-long line 15<RESET>
1389 <MAGENTA>-long line 16<RESET>
1391 test_cmp expected actual
1394 test_expect_success
'no effect from --color-moved with --word-diff' '
1395 cat <<-\EOF >text.txt &&
1396 Lorem Ipsum is simply dummy text of the printing and typesetting industry.
1399 git commit -a -m "clean state" &&
1400 cat <<-\EOF >text.txt &&
1401 simply Lorem Ipsum dummy is text of the typesetting and printing industry.
1403 git diff --color-moved --word-diff >actual &&
1404 git diff --word-diff >expect &&
1405 test_cmp expect actual
1408 test_expect_success
'set up whitespace tests' '
1410 # Note that these lines have no leading or trailing whitespace.
1411 cat <<-\EOF >lines.txt &&
1422 git add lines.txt &&
1423 git commit -m "add poetry" &&
1424 git config color.diff.oldMoved "magenta" &&
1425 git config color.diff.newMoved "cyan"
1428 test_expect_success
'move detection ignoring whitespace ' '
1429 q_to_tab <<-\EOF >lines.txt &&
1433 Qchanged long line 9
1440 git diff HEAD --no-renames --color-moved --color >actual.raw &&
1441 grep -v "index" actual.raw | test_decode_color >actual &&
1442 cat <<-\EOF >expected &&
1443 <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1444 <BOLD>--- a/lines.txt<RESET>
1445 <BOLD>+++ b/lines.txt<RESET>
1446 <CYAN>@@ -1,9 +1,9 @@<RESET>
1447 <GREEN>+<RESET> <GREEN>long line 6<RESET>
1448 <GREEN>+<RESET> <GREEN>long line 7<RESET>
1449 <GREEN>+<RESET> <GREEN>long line 8<RESET>
1450 <GREEN>+<RESET> <GREEN>changed long line 9<RESET>
1456 <RED>-long line 6<RESET>
1457 <RED>-long line 7<RESET>
1458 <RED>-long line 8<RESET>
1459 <RED>-long line 9<RESET>
1461 test_cmp expected actual &&
1463 git diff HEAD --no-renames --color-moved --color \
1464 --color-moved-ws=ignore-all-space >actual.raw &&
1465 grep -v "index" actual.raw | test_decode_color >actual &&
1466 cat <<-\EOF >expected &&
1467 <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1468 <BOLD>--- a/lines.txt<RESET>
1469 <BOLD>+++ b/lines.txt<RESET>
1470 <CYAN>@@ -1,9 +1,9 @@<RESET>
1471 <CYAN>+<RESET> <CYAN>long line 6<RESET>
1472 <CYAN>+<RESET> <CYAN>long line 7<RESET>
1473 <CYAN>+<RESET> <CYAN>long line 8<RESET>
1474 <GREEN>+<RESET> <GREEN>changed long line 9<RESET>
1480 <MAGENTA>-long line 6<RESET>
1481 <MAGENTA>-long line 7<RESET>
1482 <MAGENTA>-long line 8<RESET>
1483 <RED>-long line 9<RESET>
1485 test_cmp expected actual
1488 test_expect_success
'move detection ignoring whitespace changes' '
1490 # Lines 6-8 have a space change, but 9 is new whitespace
1491 q_to_tab <<-\EOF >lines.txt &&
1503 git diff HEAD --no-renames --color-moved --color >actual.raw &&
1504 grep -v "index" actual.raw | test_decode_color >actual &&
1505 cat <<-\EOF >expected &&
1506 <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1507 <BOLD>--- a/lines.txt<RESET>
1508 <BOLD>+++ b/lines.txt<RESET>
1509 <CYAN>@@ -1,9 +1,9 @@<RESET>
1510 <GREEN>+<RESET><GREEN>long line 6<RESET>
1511 <GREEN>+<RESET><GREEN>long line 7<RESET>
1512 <GREEN>+<RESET><GREEN>long line 8<RESET>
1513 <GREEN>+<RESET><GREEN>long li ne 9<RESET>
1519 <RED>-long line 6<RESET>
1520 <RED>-long line 7<RESET>
1521 <RED>-long line 8<RESET>
1522 <RED>-long line 9<RESET>
1524 test_cmp expected actual &&
1526 git diff HEAD --no-renames --color-moved --color \
1527 --color-moved-ws=ignore-space-change >actual.raw &&
1528 grep -v "index" actual.raw | test_decode_color >actual &&
1529 cat <<-\EOF >expected &&
1530 <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1531 <BOLD>--- a/lines.txt<RESET>
1532 <BOLD>+++ b/lines.txt<RESET>
1533 <CYAN>@@ -1,9 +1,9 @@<RESET>
1534 <CYAN>+<RESET><CYAN>long line 6<RESET>
1535 <CYAN>+<RESET><CYAN>long line 7<RESET>
1536 <CYAN>+<RESET><CYAN>long line 8<RESET>
1537 <GREEN>+<RESET><GREEN>long li ne 9<RESET>
1543 <MAGENTA>-long line 6<RESET>
1544 <MAGENTA>-long line 7<RESET>
1545 <MAGENTA>-long line 8<RESET>
1546 <RED>-long line 9<RESET>
1548 test_cmp expected actual
1551 test_expect_success
'move detection ignoring whitespace at eol' '
1553 # Lines 6-9 have new eol whitespace, but 9 also has it in the middle
1554 q_to_tab <<-\EOF >lines.txt &&
1566 # avoid cluttering the output with complaints about our eol whitespace
1567 test_config core.whitespace -blank-at-eol &&
1569 git diff HEAD --no-renames --color-moved --color >actual.raw &&
1570 grep -v "index" actual.raw | test_decode_color >actual &&
1571 cat <<-\EOF >expected &&
1572 <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1573 <BOLD>--- a/lines.txt<RESET>
1574 <BOLD>+++ b/lines.txt<RESET>
1575 <CYAN>@@ -1,9 +1,9 @@<RESET>
1576 <GREEN>+<RESET><GREEN>long line 6 <RESET>
1577 <GREEN>+<RESET><GREEN>long line 7 <RESET>
1578 <GREEN>+<RESET><GREEN>long line 8 <RESET>
1579 <GREEN>+<RESET><GREEN>long line 9 <RESET>
1585 <RED>-long line 6<RESET>
1586 <RED>-long line 7<RESET>
1587 <RED>-long line 8<RESET>
1588 <RED>-long line 9<RESET>
1590 test_cmp expected actual &&
1592 git diff HEAD --no-renames --color-moved --color \
1593 --color-moved-ws=ignore-space-at-eol >actual.raw &&
1594 grep -v "index" actual.raw | test_decode_color >actual &&
1595 cat <<-\EOF >expected &&
1596 <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1597 <BOLD>--- a/lines.txt<RESET>
1598 <BOLD>+++ b/lines.txt<RESET>
1599 <CYAN>@@ -1,9 +1,9 @@<RESET>
1600 <CYAN>+<RESET><CYAN>long line 6 <RESET>
1601 <CYAN>+<RESET><CYAN>long line 7 <RESET>
1602 <CYAN>+<RESET><CYAN>long line 8 <RESET>
1603 <GREEN>+<RESET><GREEN>long line 9 <RESET>
1609 <MAGENTA>-long line 6<RESET>
1610 <MAGENTA>-long line 7<RESET>
1611 <MAGENTA>-long line 8<RESET>
1612 <RED>-long line 9<RESET>
1614 test_cmp expected actual
1617 test_expect_success
'clean up whitespace-test colors' '
1618 git config --unset color.diff.oldMoved &&
1619 git config --unset color.diff.newMoved
1622 test_expect_success
'--color-moved block at end of diff output respects MIN_ALNUM_COUNT' '
1639 git diff HEAD --color-moved=zebra --color --no-renames >actual.raw &&
1640 grep -v "index" actual.raw | test_decode_color >actual &&
1641 cat >expected <<-\EOF &&
1642 <BOLD>diff --git a/bar b/bar<RESET>
1643 <BOLD>--- a/bar<RESET>
1644 <BOLD>+++ b/bar<RESET>
1645 <CYAN>@@ -0,0 +1 @@<RESET>
1646 <GREEN>+<RESET><GREEN>line1<RESET>
1647 <BOLD>diff --git a/foo b/foo<RESET>
1648 <BOLD>--- a/foo<RESET>
1649 <BOLD>+++ b/foo<RESET>
1650 <CYAN>@@ -1,2 +1 @@<RESET>
1651 irrelevant_line<RESET>
1655 test_cmp expected actual
1658 test_expect_success
'--color-moved respects MIN_ALNUM_COUNT' '
1661 nineteen chars 456789
1663 twenty chars 234567890
1673 twenty chars 234567890
1674 nineteen chars 456789
1677 git diff HEAD --color-moved=zebra --color --no-renames >actual.raw &&
1678 grep -v "index" actual.raw | test_decode_color >actual &&
1679 cat >expected <<-\EOF &&
1680 <BOLD>diff --git a/bar b/bar<RESET>
1681 <BOLD>--- a/bar<RESET>
1682 <BOLD>+++ b/bar<RESET>
1683 <CYAN>@@ -0,0 +1,2 @@<RESET>
1684 <BOLD;CYAN>+<RESET><BOLD;CYAN>twenty chars 234567890<RESET>
1685 <GREEN>+<RESET><GREEN>nineteen chars 456789<RESET>
1686 <BOLD>diff --git a/foo b/foo<RESET>
1687 <BOLD>--- a/foo<RESET>
1688 <BOLD>+++ b/foo<RESET>
1689 <CYAN>@@ -1,3 +1 @@<RESET>
1690 <RED>-nineteen chars 456789<RESET>
1691 irrelevant_line<RESET>
1692 <BOLD;MAGENTA>-twenty chars 234567890<RESET>
1695 test_cmp expected actual
1698 test_expect_success
'--color-moved treats adjacent blocks as separate for MIN_ALNUM_COUNT' '
1719 git diff HEAD --color-moved=zebra --color --no-renames >actual.raw &&
1720 grep -v "index" actual.raw | test_decode_color >actual &&
1721 cat >expected <<-\EOF &&
1722 <BOLD>diff --git a/bar b/bar<RESET>
1723 <BOLD>--- a/bar<RESET>
1724 <BOLD>+++ b/bar<RESET>
1725 <CYAN>@@ -0,0 +1,3 @@<RESET>
1726 <GREEN>+<RESET><GREEN>7charsB<RESET>
1727 <GREEN>+<RESET><GREEN>7charsC<RESET>
1728 <GREEN>+<RESET><GREEN>7charsA<RESET>
1729 <BOLD>diff --git a/foo b/foo<RESET>
1730 <BOLD>--- a/foo<RESET>
1731 <BOLD>+++ b/foo<RESET>
1732 <CYAN>@@ -1,4 +1 @@<RESET>
1733 <RED>-7charsA<RESET>
1734 irrelevant_line<RESET>
1735 <RED>-7charsB<RESET>
1736 <RED>-7charsC<RESET>
1739 test_cmp expected actual
1742 test_expect_success
'move detection with submodules' '
1743 test_create_repo bananas &&
1744 echo ripe >bananas/recipe &&
1745 git -C bananas add recipe &&
1746 test_commit fruit &&
1747 test_commit -C bananas recipe &&
1748 git submodule add ./bananas &&
1750 git commit -a -m "bananas are like a heavy library?" &&
1751 echo foul >bananas/recipe &&
1752 echo ripe >fruit.t &&
1754 git diff --submodule=diff --color-moved --color >actual &&
1756 # no move detection as the moved line is across repository boundaries.
1757 test_decode_color <actual >decoded_actual &&
1758 ! grep BGREEN decoded_actual &&
1759 ! grep BRED decoded_actual &&
1761 # nor did we mess with it another way
1762 git diff --submodule=diff --color | test_decode_color >expect &&
1763 test_cmp expect decoded_actual &&
1765 git submodule deinit bananas
1768 test_expect_success
'only move detection ignores white spaces' '
1770 q_to_tab <<-\EOF >text.txt &&
1771 a long line to exceed per-line minimum
1772 another long line to exceed per-line minimum
1776 git commit -m "add text" &&
1777 q_to_tab <<-\EOF >text.txt &&
1778 Qa long line to exceed per-line minimum
1779 Qanother long line to exceed per-line minimum
1783 # Make sure we get a different diff using -w
1784 git diff --color --color-moved -w >actual.raw &&
1785 grep -v "index" actual.raw | test_decode_color >actual &&
1786 q_to_tab <<-\EOF >expected &&
1787 <BOLD>diff --git a/text.txt b/text.txt<RESET>
1788 <BOLD>--- a/text.txt<RESET>
1789 <BOLD>+++ b/text.txt<RESET>
1790 <CYAN>@@ -1,3 +1,3 @@<RESET>
1791 Qa long line to exceed per-line minimum<RESET>
1792 Qanother long line to exceed per-line minimum<RESET>
1793 <RED>-original file<RESET>
1794 <GREEN>+<RESET><GREEN>new file<RESET>
1796 test_cmp expected actual &&
1798 # And now ignoring white space only in the move detection
1799 git diff --color --color-moved \
1800 --color-moved-ws=ignore-all-space,ignore-space-change,ignore-space-at-eol >actual.raw &&
1801 grep -v "index" actual.raw | test_decode_color >actual &&
1802 q_to_tab <<-\EOF >expected &&
1803 <BOLD>diff --git a/text.txt b/text.txt<RESET>
1804 <BOLD>--- a/text.txt<RESET>
1805 <BOLD>+++ b/text.txt<RESET>
1806 <CYAN>@@ -1,3 +1,3 @@<RESET>
1807 <BOLD;MAGENTA>-a long line to exceed per-line minimum<RESET>
1808 <BOLD;MAGENTA>-another long line to exceed per-line minimum<RESET>
1809 <RED>-original file<RESET>
1810 <BOLD;YELLOW>+<RESET>Q<BOLD;YELLOW>a long line to exceed per-line minimum<RESET>
1811 <BOLD;YELLOW>+<RESET>Q<BOLD;YELLOW>another long line to exceed per-line minimum<RESET>
1812 <GREEN>+<RESET><GREEN>new file<RESET>
1814 test_cmp expected actual
1817 test_expect_success
'compare whitespace delta across moved blocks' '
1820 q_to_tab <<-\EOF >text.txt &&
1824 QBut! <- this stands out
1826 QQdifferent starting
1832 QQQthat has similar lines
1833 QQQto previous blocks, but with different indent
1834 QQQYetQAnotherQoutlierQ
1838 git commit -m "add text.txt" &&
1840 q_to_tab <<-\EOF >text.txt &&
1844 QQQBut! <- this stands out
1852 QQthat has similar lines
1853 QQto previous blocks, but with different indent
1854 QQYetQAnotherQoutlier
1857 git diff --color --color-moved --color-moved-ws=allow-indentation-change >actual.raw &&
1858 grep -v "index" actual.raw | test_decode_color >actual &&
1860 q_to_tab <<-\EOF >expected &&
1861 <BOLD>diff --git a/text.txt b/text.txt<RESET>
1862 <BOLD>--- a/text.txt<RESET>
1863 <BOLD>+++ b/text.txt<RESET>
1864 <CYAN>@@ -1,14 +1,14 @@<RESET>
1865 <BOLD;MAGENTA>-QIndented<RESET>
1866 <BOLD;MAGENTA>-QText across<RESET>
1867 <BOLD;MAGENTA>-Qsome lines<RESET>
1868 <RED>-QBut! <- this stands out<RESET>
1869 <BOLD;MAGENTA>-QAdjusting with<RESET>
1870 <BOLD;MAGENTA>-QQdifferent starting<RESET>
1871 <BOLD;MAGENTA>-Qwhite spaces<RESET>
1872 <RED>-QAnother outlier<RESET>
1873 <BOLD;MAGENTA>-QQQIndented<RESET>
1874 <BOLD;MAGENTA>-QQQText across<RESET>
1875 <BOLD;MAGENTA>-QQQfive lines<RESET>
1876 <BOLD;MAGENTA>-QQQthat has similar lines<RESET>
1877 <BOLD;MAGENTA>-QQQto previous blocks, but with different indent<RESET>
1878 <RED>-QQQYetQAnotherQoutlierQ<RESET>
1879 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>Indented<RESET>
1880 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>Text across<RESET>
1881 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>some lines<RESET>
1882 <GREEN>+<RESET>QQQ<GREEN>But! <- this stands out<RESET>
1883 <BOLD;CYAN>+<RESET><BOLD;CYAN>Adjusting with<RESET>
1884 <BOLD;CYAN>+<RESET>Q<BOLD;CYAN>different starting<RESET>
1885 <BOLD;CYAN>+<RESET><BOLD;CYAN>white spaces<RESET>
1886 <GREEN>+<RESET><GREEN>AnotherQoutlier<RESET>
1887 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>Indented<RESET>
1888 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>Text across<RESET>
1889 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>five lines<RESET>
1890 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>that has similar lines<RESET>
1891 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>to previous blocks, but with different indent<RESET>
1892 <GREEN>+<RESET>QQ<GREEN>YetQAnotherQoutlier<RESET>
1895 test_cmp expected actual
1898 test_expect_success
'compare whitespace delta incompatible with other space options' '
1899 test_must_fail git diff \
1900 --color-moved-ws=allow-indentation-change,ignore-all-space \
1902 test_i18ngrep allow-indentation-change err