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 &&
97 test_must_be_empty out &&
99 git diff -w -b >out &&
100 test_must_be_empty out &&
102 git diff -w --ignore-space-at-eol >out &&
103 test_must_be_empty out &&
105 git diff -w -b --ignore-space-at-eol >out &&
106 test_must_be_empty out &&
108 git diff -w --ignore-cr-at-eol >out &&
109 test_must_be_empty out &&
111 tr "Q_" "\015 " <<-\EOF >expect &&
113 index d99af23..22d9f73 100644
117 -whitespace at beginning
118 +_ whitespace at beginning
120 -whitespace in the middle
121 +white space in the middle
127 test_cmp expect out &&
129 git diff -b --ignore-space-at-eol >out &&
130 test_cmp expect out &&
132 git diff -b --ignore-cr-at-eol >out &&
133 test_cmp expect out &&
135 tr "Q_" "\015 " <<-\EOF >expect &&
137 index d99af23..22d9f73 100644
141 -whitespace at beginning
143 -whitespace in the middle
144 +_ whitespace at beginning
146 +white space in the middle
151 git diff --ignore-space-at-eol >out &&
152 test_cmp expect out &&
154 git diff --ignore-space-at-eol --ignore-cr-at-eol >out &&
155 test_cmp expect out &&
157 tr "Q_" "\015 " <<-\EOF >expect &&
159 index_d99af23..22d9f73 100644
163 -whitespace at beginning
165 -whitespace in the middle
167 +_ whitespace at beginning
169 +white space in the middle
174 git diff --ignore-cr-at-eol >out &&
178 test_expect_success
'ignore-blank-lines: only new lines' '
180 git update-index x &&
181 test_seq 5 | sed "/3/i\\
183 git diff --ignore-blank-lines >out &&
184 test_must_be_empty out
187 test_expect_success
'ignore-blank-lines: only new lines with space' '
189 git update-index x &&
190 test_seq 5 | sed "/3/i\\
192 git diff -w --ignore-blank-lines >out &&
193 test_must_be_empty out
196 test_expect_success
'ignore-blank-lines: after change' '
208 git update-index x &&
221 git diff --inter-hunk-context=100 --ignore-blank-lines >out.tmp &&
222 cat <<-\EOF >expected &&
236 compare_diff_patch expected out.tmp
239 test_expect_success
'ignore-blank-lines: before change' '
250 git update-index x &&
263 git diff --inter-hunk-context=100 --ignore-blank-lines >out.tmp &&
264 cat <<-\EOF >expected &&
277 compare_diff_patch expected out.tmp
280 test_expect_success
'ignore-blank-lines: between changes' '
295 git update-index x &&
312 git diff --ignore-blank-lines >out.tmp &&
313 cat <<-\EOF >expected &&
334 compare_diff_patch expected out.tmp
337 test_expect_success
'ignore-blank-lines: between changes (with interhunkctx)' '
339 git update-index x &&
357 git diff --inter-hunk-context=2 --ignore-blank-lines >out.tmp &&
358 cat <<-\EOF >expected &&
379 compare_diff_patch expected out.tmp
382 test_expect_success
'ignore-blank-lines: scattered spaces' '
384 git update-index x &&
405 git diff --inter-hunk-context=4 --ignore-blank-lines >out.tmp &&
406 cat <<-\EOF >expected &&
421 compare_diff_patch expected out.tmp
424 test_expect_success
'ignore-blank-lines: spaces coalesce' '
426 git update-index x &&
440 git diff --inter-hunk-context=4 --ignore-blank-lines >out.tmp &&
441 cat <<-\EOF >expected &&
458 compare_diff_patch expected out.tmp
461 test_expect_success
'ignore-blank-lines: mix changes and blank lines' '
463 git update-index x &&
489 git diff --ignore-blank-lines >out.tmp &&
490 cat <<-\EOF >expected &&
519 compare_diff_patch expected out.tmp
522 test_expect_success
'check mixed spaces and tabs in indent' '
523 # This is indented with SP HT SP.
525 git diff --check | grep "space before tab in indent"
528 test_expect_success
'check mixed tabs and spaces in indent' '
529 # This is indented with HT SP HT.
531 git diff --check | grep "space before tab in indent"
534 test_expect_success
'check with no whitespace errors' '
535 git commit -m "snapshot" &&
540 test_expect_success
'check with trailing whitespace' '
542 test_must_fail git diff --check
545 test_expect_success
'check with space before tab in indent' '
546 # indent has space followed by hard tab
548 test_must_fail git diff --check
551 test_expect_success
'--check and --exit-code are not exclusive' '
553 git diff --check --exit-code
556 test_expect_success
'--check and --quiet are not exclusive' '
557 git diff --check --quiet
560 test_expect_success
'check staged with no whitespace errors' '
563 git diff --cached --check
566 test_expect_success
'check staged with trailing whitespace' '
569 test_must_fail git diff --cached --check
572 test_expect_success
'check staged with space before tab in indent' '
573 # indent has space followed by hard tab
576 test_must_fail git diff --cached --check
579 test_expect_success
'check with no whitespace errors (diff-index)' '
582 git diff-index --check HEAD
585 test_expect_success
'check with trailing whitespace (diff-index)' '
588 test_must_fail git diff-index --check HEAD
591 test_expect_success
'check with space before tab in indent (diff-index)' '
592 # indent has space followed by hard tab
595 test_must_fail git diff-index --check HEAD
598 test_expect_success
'check staged with no whitespace errors (diff-index)' '
601 git diff-index --cached --check HEAD
604 test_expect_success
'check staged with trailing whitespace (diff-index)' '
607 test_must_fail git diff-index --cached --check HEAD
610 test_expect_success
'check staged with space before tab in indent (diff-index)' '
611 # indent has space followed by hard tab
614 test_must_fail git diff-index --cached --check HEAD
617 test_expect_success
'check with no whitespace errors (diff-tree)' '
619 git commit -m "new commit" x &&
620 git diff-tree --check HEAD^ HEAD
623 test_expect_success
'check with trailing whitespace (diff-tree)' '
625 git commit -m "another commit" x &&
626 test_must_fail git diff-tree --check HEAD^ HEAD
629 test_expect_success
'check with space before tab in indent (diff-tree)' '
630 # indent has space followed by hard tab
632 git commit -m "yet another" x &&
633 test_must_fail git diff-tree --check HEAD^ HEAD
636 test_expect_success
'check with ignored trailing whitespace attr (diff-tree)' '
637 test_when_finished "git reset --hard HEAD^" &&
639 # create a whitespace error that should be ignored
640 echo "* -whitespace" >.gitattributes &&
641 git add .gitattributes &&
644 git commit -m "add trailing space" &&
646 # with a worktree diff-tree ignores the whitespace error
647 git diff-tree --root --check HEAD &&
649 # without a worktree diff-tree still ignores the whitespace error
650 git -C .git diff-tree --root --check HEAD
653 test_expect_success
'check trailing whitespace (trailing-space: off)' '
654 git config core.whitespace "-trailing-space" &&
655 echo "foo (); " >x &&
659 test_expect_success
'check trailing whitespace (trailing-space: on)' '
660 git config core.whitespace "trailing-space" &&
661 echo "foo (); " >x &&
662 test_must_fail git diff --check
665 test_expect_success
'check space before tab in indent (space-before-tab: off)' '
666 # indent contains space followed by HT
667 git config core.whitespace "-space-before-tab" &&
668 echo " foo ();" >x &&
672 test_expect_success
'check space before tab in indent (space-before-tab: on)' '
673 # indent contains space followed by HT
674 git config core.whitespace "space-before-tab" &&
675 echo " foo (); " >x &&
676 test_must_fail git diff --check
679 test_expect_success
'check spaces as indentation (indent-with-non-tab: off)' '
680 git config core.whitespace "-indent-with-non-tab" &&
681 echo " foo ();" >x &&
685 test_expect_success
'check spaces as indentation (indent-with-non-tab: on)' '
686 git config core.whitespace "indent-with-non-tab" &&
687 echo " foo ();" >x &&
688 test_must_fail git diff --check
691 test_expect_success
'ditto, but tabwidth=9' '
692 git config core.whitespace "indent-with-non-tab,tabwidth=9" &&
696 test_expect_success
'check tabs and spaces as indentation (indent-with-non-tab: on)' '
697 git config core.whitespace "indent-with-non-tab" &&
698 echo " foo ();" >x &&
699 test_must_fail git diff --check
702 test_expect_success
'ditto, but tabwidth=10' '
703 git config core.whitespace "indent-with-non-tab,tabwidth=10" &&
704 test_must_fail git diff --check
707 test_expect_success
'ditto, but tabwidth=20' '
708 git config core.whitespace "indent-with-non-tab,tabwidth=20" &&
712 test_expect_success
'check tabs as indentation (tab-in-indent: off)' '
713 git config core.whitespace "-tab-in-indent" &&
714 echo " foo ();" >x &&
718 test_expect_success
'check tabs as indentation (tab-in-indent: on)' '
719 git config core.whitespace "tab-in-indent" &&
720 echo " foo ();" >x &&
721 test_must_fail git diff --check
724 test_expect_success
'check tabs and spaces as indentation (tab-in-indent: on)' '
725 git config core.whitespace "tab-in-indent" &&
726 echo " foo ();" >x &&
727 test_must_fail git diff --check
730 test_expect_success
'ditto, but tabwidth=1 (must be irrelevant)' '
731 git config core.whitespace "tab-in-indent,tabwidth=1" &&
732 test_must_fail git diff --check
735 test_expect_success
'check tab-in-indent and indent-with-non-tab conflict' '
736 git config core.whitespace "tab-in-indent,indent-with-non-tab" &&
738 test_must_fail git diff --check
741 test_expect_success
'check tab-in-indent excluded from wildcard whitespace attribute' '
742 git config --unset core.whitespace &&
743 echo "x whitespace" >.gitattributes &&
744 echo " foo ();" >x &&
749 test_expect_success
'line numbers in --check output are correct' '
751 echo "foo(); " >>x &&
752 git diff --check | grep "x:2:"
755 test_expect_success
'checkdiff detects new trailing blank lines (1)' '
758 git diff --check | grep "new blank line"
761 test_expect_success
'checkdiff detects new trailing blank lines (2)' '
762 { echo a; echo b; echo; echo; } >x &&
764 { echo a; echo; echo; echo; echo; } >x &&
765 git diff --check | grep "new blank line"
768 test_expect_success
'checkdiff allows new blank lines' '
772 echo "/* This is new */" &&
781 test_expect_success
'whitespace-only changes not reported' '
783 echo >x "hello world" &&
785 git commit -m "hello 1" &&
786 echo >x "hello world" &&
787 git diff -b >actual &&
788 test_cmp expect actual
793 similarity index NUM%
796 index 380c32a..a97b785 100644
798 test_expect_success
'whitespace-only changes reported across renames' '
800 for i in 1 2 3 4 5 6 7 8 9; do echo "$i$i$i$i$i$i"; done >x &&
802 git commit -m "base" &&
803 sed -e "5s/^/ /" x >z &&
806 git diff -w -M --cached |
807 sed -e "/^similarity index /s/[0-9][0-9]*/NUM/" >actual &&
808 test_cmp expect actual
812 diff --git a
/empty b
/void
813 similarity index
100%
818 test_expect_success
'rename empty' '
822 git commit -m empty &&
824 git diff -w --cached -M >current &&
825 test_cmp expected current
828 test_expect_success
'combined diff with autocrlf conversion' '
832 git commit -m "one side" x &&
833 git checkout HEAD^ &&
835 git commit -m "the other side" x &&
836 git config core.autocrlf true &&
837 test_must_fail git merge master &&
839 git diff | sed -e "1,/^@@@/d" >actual &&
844 # Start testing the colored format for whitespace checks
846 test_expect_success
'setup diff colors' '
847 git config color.diff.plain normal &&
848 git config color.diff.meta bold &&
849 git config color.diff.frag cyan &&
850 git config color.diff.func normal &&
851 git config color.diff.old red &&
852 git config color.diff.new green &&
853 git config color.diff.commit yellow &&
854 git config color.diff.whitespace blue &&
856 git config core.autocrlf false
859 test_expect_success
'diff that introduces a line with only tabs' '
860 git config core.whitespace blank-at-eol &&
863 git commit -m "initial" x &&
864 echo "{NTN}" | tr "NT" "\n\t" >>x &&
865 git diff --color | test_decode_color >current &&
867 cat >expected <<-\EOF &&
868 <BOLD>diff --git a/x b/x<RESET>
869 <BOLD>index 9daeafb..2874b91 100644<RESET>
872 <CYAN>@@ -1 +1,4 @@<RESET>
874 <GREEN>+<RESET><GREEN>{<RESET>
875 <GREEN>+<RESET><BLUE> <RESET>
876 <GREEN>+<RESET><GREEN>}<RESET>
879 test_cmp expected current
882 test_expect_success
'diff that introduces and removes ws breakages' '
885 echo "0. blank-at-eol " &&
886 echo "1. blank-at-eol "
888 git commit -a --allow-empty -m preimage &&
890 echo "0. blank-at-eol " &&
891 echo "1. still-blank-at-eol " &&
892 echo "2. and a new line "
896 test_decode_color >current &&
898 cat >expected <<-\EOF &&
899 <BOLD>diff --git a/x b/x<RESET>
900 <BOLD>index d0233a2..700886e 100644<RESET>
903 <CYAN>@@ -1,2 +1,3 @@<RESET>
904 0. blank-at-eol <RESET>
905 <RED>-1. blank-at-eol <RESET>
906 <GREEN>+<RESET><GREEN>1. still-blank-at-eol<RESET><BLUE> <RESET>
907 <GREEN>+<RESET><GREEN>2. and a new line<RESET><BLUE> <RESET>
910 test_cmp expected current
913 test_expect_success
'ws-error-highlight test setup' '
917 echo "0. blank-at-eol " &&
918 echo "1. blank-at-eol "
920 git commit -a --allow-empty -m preimage &&
922 echo "0. blank-at-eol " &&
923 echo "1. still-blank-at-eol " &&
924 echo "2. and a new line "
927 cat >expect.default-old <<-\EOF &&
928 <BOLD>diff --git a/x b/x<RESET>
929 <BOLD>index d0233a2..700886e 100644<RESET>
932 <CYAN>@@ -1,2 +1,3 @@<RESET>
933 0. blank-at-eol <RESET>
934 <RED>-<RESET><RED>1. blank-at-eol<RESET><BLUE> <RESET>
935 <GREEN>+<RESET><GREEN>1. still-blank-at-eol<RESET><BLUE> <RESET>
936 <GREEN>+<RESET><GREEN>2. and a new line<RESET><BLUE> <RESET>
939 cat >expect.all <<-\EOF &&
940 <BOLD>diff --git a/x b/x<RESET>
941 <BOLD>index d0233a2..700886e 100644<RESET>
944 <CYAN>@@ -1,2 +1,3 @@<RESET>
945 <RESET>0. blank-at-eol<RESET><BLUE> <RESET>
946 <RED>-<RESET><RED>1. blank-at-eol<RESET><BLUE> <RESET>
947 <GREEN>+<RESET><GREEN>1. still-blank-at-eol<RESET><BLUE> <RESET>
948 <GREEN>+<RESET><GREEN>2. and a new line<RESET><BLUE> <RESET>
951 cat >expect.none <<-\EOF
952 <BOLD>diff --git a/x b/x<RESET>
953 <BOLD>index d0233a2..700886e 100644<RESET>
956 <CYAN>@@ -1,2 +1,3 @@<RESET>
957 0. blank-at-eol <RESET>
958 <RED>-1. blank-at-eol <RESET>
959 <GREEN>+1. still-blank-at-eol <RESET>
960 <GREEN>+2. and a new line <RESET>
965 test_expect_success
'test --ws-error-highlight option' '
967 git diff --color --ws-error-highlight=default,old |
968 test_decode_color >current &&
969 test_cmp expect.default-old current &&
971 git diff --color --ws-error-highlight=all |
972 test_decode_color >current &&
973 test_cmp expect.all current &&
975 git diff --color --ws-error-highlight=none |
976 test_decode_color >current &&
977 test_cmp expect.none current
981 test_expect_success
'test diff.wsErrorHighlight config' '
983 git -c diff.wsErrorHighlight=default,old diff --color |
984 test_decode_color >current &&
985 test_cmp expect.default-old current &&
987 git -c diff.wsErrorHighlight=all diff --color |
988 test_decode_color >current &&
989 test_cmp expect.all current &&
991 git -c diff.wsErrorHighlight=none diff --color |
992 test_decode_color >current &&
993 test_cmp expect.none current
997 test_expect_success
'option overrides diff.wsErrorHighlight' '
999 git -c diff.wsErrorHighlight=none \
1000 diff --color --ws-error-highlight=default,old |
1001 test_decode_color >current &&
1002 test_cmp expect.default-old current &&
1004 git -c diff.wsErrorHighlight=default \
1005 diff --color --ws-error-highlight=all |
1006 test_decode_color >current &&
1007 test_cmp expect.all current &&
1009 git -c diff.wsErrorHighlight=all \
1010 diff --color --ws-error-highlight=none |
1011 test_decode_color >current &&
1012 test_cmp expect.none current
1016 test_expect_success
'detect moved code, complete file' '
1018 cat <<-\EOF >test.c &&
1022 printf("Hello World");
1026 git commit -m "add main function" &&
1027 git mv test.c main.c &&
1028 test_config color.diff.oldMoved "normal red" &&
1029 test_config color.diff.newMoved "normal green" &&
1030 git diff HEAD --color-moved=zebra --color --no-renames | test_decode_color >actual &&
1031 cat >expected <<-\EOF &&
1032 <BOLD>diff --git a/main.c b/main.c<RESET>
1033 <BOLD>new file mode 100644<RESET>
1034 <BOLD>index 0000000..a986c57<RESET>
1035 <BOLD>--- /dev/null<RESET>
1036 <BOLD>+++ b/main.c<RESET>
1037 <CYAN>@@ -0,0 +1,5 @@<RESET>
1038 <BGREEN>+<RESET><BGREEN>#include<stdio.h><RESET>
1039 <BGREEN>+<RESET><BGREEN>main()<RESET>
1040 <BGREEN>+<RESET><BGREEN>{<RESET>
1041 <BGREEN>+<RESET><BGREEN>printf("Hello World");<RESET>
1042 <BGREEN>+<RESET><BGREEN>}<RESET>
1043 <BOLD>diff --git a/test.c b/test.c<RESET>
1044 <BOLD>deleted file mode 100644<RESET>
1045 <BOLD>index a986c57..0000000<RESET>
1046 <BOLD>--- a/test.c<RESET>
1047 <BOLD>+++ /dev/null<RESET>
1048 <CYAN>@@ -1,5 +0,0 @@<RESET>
1049 <BRED>-#include<stdio.h><RESET>
1050 <BRED>-main()<RESET>
1052 <BRED>-printf("Hello World");<RESET>
1056 test_cmp expected actual
1059 test_expect_success
'detect malicious moved code, inside file' '
1060 test_config color.diff.oldMoved "normal red" &&
1061 test_config color.diff.newMoved "normal green" &&
1062 test_config color.diff.oldMovedAlternative "blue" &&
1063 test_config color.diff.newMovedAlternative "yellow" &&
1065 cat <<-\EOF >main.c &&
1073 int secure_foo(struct user *u)
1075 if (!u->is_allowed_foo)
1085 cat <<-\EOF >test.c &&
1089 printf("Hello World, but different\n");
1092 int another_function()
1097 git add main.c test.c &&
1098 git commit -m "add main and test file" &&
1099 cat <<-\EOF >main.c &&
1112 cat <<-\EOF >test.c &&
1116 printf("Hello World, but different\n");
1119 int secure_foo(struct user *u)
1122 if (!u->is_allowed_foo)
1126 int another_function()
1131 git diff HEAD --no-renames --color-moved=zebra --color | test_decode_color >actual &&
1132 cat <<-\EOF >expected &&
1133 <BOLD>diff --git a/main.c b/main.c<RESET>
1134 <BOLD>index 27a619c..7cf9336 100644<RESET>
1135 <BOLD>--- a/main.c<RESET>
1136 <BOLD>+++ b/main.c<RESET>
1137 <CYAN>@@ -5,13 +5,6 @@<RESET> <RESET>printf("Hello ");<RESET>
1138 printf("World\n");<RESET>
1141 <BRED>-int secure_foo(struct user *u)<RESET>
1143 <BLUE>-if (!u->is_allowed_foo)<RESET>
1144 <BLUE>-return;<RESET>
1145 <RED>-foo(u);<RESET>
1151 <BOLD>diff --git a/test.c b/test.c<RESET>
1152 <BOLD>index 1dc1d85..2bedec9 100644<RESET>
1153 <BOLD>--- a/test.c<RESET>
1154 <BOLD>+++ b/test.c<RESET>
1155 <CYAN>@@ -4,6 +4,13 @@<RESET> <RESET>int bar()<RESET>
1156 printf("Hello World, but different\n");<RESET>
1159 <BGREEN>+<RESET><BGREEN>int secure_foo(struct user *u)<RESET>
1160 <BGREEN>+<RESET><BGREEN>{<RESET>
1161 <GREEN>+<RESET><GREEN>foo(u);<RESET>
1162 <BGREEN>+<RESET><BGREEN>if (!u->is_allowed_foo)<RESET>
1163 <BGREEN>+<RESET><BGREEN>return;<RESET>
1164 <GREEN>+<RESET><GREEN>}<RESET>
1166 int another_function()<RESET>
1171 test_cmp expected actual
1174 test_expect_success
'plain moved code, inside file' '
1175 test_config color.diff.oldMoved "normal red" &&
1176 test_config color.diff.newMoved "normal green" &&
1177 test_config color.diff.oldMovedAlternative "blue" &&
1178 test_config color.diff.newMovedAlternative "yellow" &&
1179 # needs previous test as setup
1180 git diff HEAD --no-renames --color-moved=plain --color | test_decode_color >actual &&
1181 cat <<-\EOF >expected &&
1182 <BOLD>diff --git a/main.c b/main.c<RESET>
1183 <BOLD>index 27a619c..7cf9336 100644<RESET>
1184 <BOLD>--- a/main.c<RESET>
1185 <BOLD>+++ b/main.c<RESET>
1186 <CYAN>@@ -5,13 +5,6 @@<RESET> <RESET>printf("Hello ");<RESET>
1187 printf("World\n");<RESET>
1190 <BRED>-int secure_foo(struct user *u)<RESET>
1192 <BRED>-if (!u->is_allowed_foo)<RESET>
1193 <BRED>-return;<RESET>
1194 <BRED>-foo(u);<RESET>
1200 <BOLD>diff --git a/test.c b/test.c<RESET>
1201 <BOLD>index 1dc1d85..2bedec9 100644<RESET>
1202 <BOLD>--- a/test.c<RESET>
1203 <BOLD>+++ b/test.c<RESET>
1204 <CYAN>@@ -4,6 +4,13 @@<RESET> <RESET>int bar()<RESET>
1205 printf("Hello World, but different\n");<RESET>
1208 <BGREEN>+<RESET><BGREEN>int secure_foo(struct user *u)<RESET>
1209 <BGREEN>+<RESET><BGREEN>{<RESET>
1210 <BGREEN>+<RESET><BGREEN>foo(u);<RESET>
1211 <BGREEN>+<RESET><BGREEN>if (!u->is_allowed_foo)<RESET>
1212 <BGREEN>+<RESET><BGREEN>return;<RESET>
1213 <BGREEN>+<RESET><BGREEN>}<RESET>
1215 int another_function()<RESET>
1220 test_cmp expected actual
1223 test_expect_success
'detect blocks of moved code' '
1225 cat <<-\EOF >lines.txt &&
1243 git add lines.txt &&
1244 git commit -m "add poetry" &&
1245 cat <<-\EOF >lines.txt &&
1263 test_config color.diff.oldMoved "magenta" &&
1264 test_config color.diff.newMoved "cyan" &&
1265 test_config color.diff.oldMovedAlternative "blue" &&
1266 test_config color.diff.newMovedAlternative "yellow" &&
1267 test_config color.diff.oldMovedDimmed "normal magenta" &&
1268 test_config color.diff.newMovedDimmed "normal cyan" &&
1269 test_config color.diff.oldMovedAlternativeDimmed "normal blue" &&
1270 test_config color.diff.newMovedAlternativeDimmed "normal yellow" &&
1271 git diff HEAD --no-renames --color-moved=blocks --color >actual.raw &&
1272 grep -v "index" actual.raw | test_decode_color >actual &&
1273 cat <<-\EOF >expected &&
1274 <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1275 <BOLD>--- a/lines.txt<RESET>
1276 <BOLD>+++ b/lines.txt<RESET>
1277 <CYAN>@@ -1,16 +1,16 @@<RESET>
1278 <MAGENTA>-long line 1<RESET>
1279 <MAGENTA>-long line 2<RESET>
1280 <MAGENTA>-long line 3<RESET>
1287 <CYAN>+<RESET><CYAN>long line 1<RESET>
1288 <CYAN>+<RESET><CYAN>long line 2<RESET>
1289 <CYAN>+<RESET><CYAN>long line 3<RESET>
1290 <CYAN>+<RESET><CYAN>long line 14<RESET>
1291 <CYAN>+<RESET><CYAN>long line 15<RESET>
1292 <CYAN>+<RESET><CYAN>long line 16<RESET>
1297 <MAGENTA>-long line 14<RESET>
1298 <MAGENTA>-long line 15<RESET>
1299 <MAGENTA>-long line 16<RESET>
1301 test_cmp expected actual
1305 test_expect_success
'detect permutations inside moved code -- dimmed-zebra' '
1306 # reuse setup from test before!
1307 test_config color.diff.oldMoved "magenta" &&
1308 test_config color.diff.newMoved "cyan" &&
1309 test_config color.diff.oldMovedAlternative "blue" &&
1310 test_config color.diff.newMovedAlternative "yellow" &&
1311 test_config color.diff.oldMovedDimmed "normal magenta" &&
1312 test_config color.diff.newMovedDimmed "normal cyan" &&
1313 test_config color.diff.oldMovedAlternativeDimmed "normal blue" &&
1314 test_config color.diff.newMovedAlternativeDimmed "normal yellow" &&
1315 git diff HEAD --no-renames --color-moved=dimmed-zebra --color >actual.raw &&
1316 grep -v "index" actual.raw | test_decode_color >actual &&
1317 cat <<-\EOF >expected &&
1318 <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1319 <BOLD>--- a/lines.txt<RESET>
1320 <BOLD>+++ b/lines.txt<RESET>
1321 <CYAN>@@ -1,16 +1,16 @@<RESET>
1322 <BMAGENTA>-long line 1<RESET>
1323 <BMAGENTA>-long line 2<RESET>
1324 <BMAGENTA>-long line 3<RESET>
1331 <BCYAN>+<RESET><BCYAN>long line 1<RESET>
1332 <BCYAN>+<RESET><BCYAN>long line 2<RESET>
1333 <CYAN>+<RESET><CYAN>long line 3<RESET>
1334 <YELLOW>+<RESET><YELLOW>long line 14<RESET>
1335 <BYELLOW>+<RESET><BYELLOW>long line 15<RESET>
1336 <BYELLOW>+<RESET><BYELLOW>long line 16<RESET>
1341 <BMAGENTA>-long line 14<RESET>
1342 <BMAGENTA>-long line 15<RESET>
1343 <BMAGENTA>-long line 16<RESET>
1345 test_cmp expected actual
1348 test_expect_success
'cmd option assumes configured colored-moved' '
1349 test_config color.diff.oldMoved "magenta" &&
1350 test_config color.diff.newMoved "cyan" &&
1351 test_config color.diff.oldMovedAlternative "blue" &&
1352 test_config color.diff.newMovedAlternative "yellow" &&
1353 test_config color.diff.oldMovedDimmed "normal magenta" &&
1354 test_config color.diff.newMovedDimmed "normal cyan" &&
1355 test_config color.diff.oldMovedAlternativeDimmed "normal blue" &&
1356 test_config color.diff.newMovedAlternativeDimmed "normal yellow" &&
1357 test_config diff.colorMoved zebra &&
1358 git diff HEAD --no-renames --color-moved --color >actual.raw &&
1359 grep -v "index" actual.raw | test_decode_color >actual &&
1360 cat <<-\EOF >expected &&
1361 <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1362 <BOLD>--- a/lines.txt<RESET>
1363 <BOLD>+++ b/lines.txt<RESET>
1364 <CYAN>@@ -1,16 +1,16 @@<RESET>
1365 <MAGENTA>-long line 1<RESET>
1366 <MAGENTA>-long line 2<RESET>
1367 <MAGENTA>-long line 3<RESET>
1374 <CYAN>+<RESET><CYAN>long line 1<RESET>
1375 <CYAN>+<RESET><CYAN>long line 2<RESET>
1376 <CYAN>+<RESET><CYAN>long line 3<RESET>
1377 <YELLOW>+<RESET><YELLOW>long line 14<RESET>
1378 <YELLOW>+<RESET><YELLOW>long line 15<RESET>
1379 <YELLOW>+<RESET><YELLOW>long line 16<RESET>
1384 <MAGENTA>-long line 14<RESET>
1385 <MAGENTA>-long line 15<RESET>
1386 <MAGENTA>-long line 16<RESET>
1388 test_cmp expected actual
1391 test_expect_success
'no effect from --color-moved with --word-diff' '
1392 cat <<-\EOF >text.txt &&
1393 Lorem Ipsum is simply dummy text of the printing and typesetting industry.
1396 git commit -a -m "clean state" &&
1397 cat <<-\EOF >text.txt &&
1398 simply Lorem Ipsum dummy is text of the typesetting and printing industry.
1400 git diff --color-moved --word-diff >actual &&
1401 git diff --word-diff >expect &&
1402 test_cmp expect actual
1405 test_expect_success
'set up whitespace tests' '
1407 # Note that these lines have no leading or trailing whitespace.
1408 cat <<-\EOF >lines.txt &&
1419 git add lines.txt &&
1420 git commit -m "add poetry" &&
1421 git config color.diff.oldMoved "magenta" &&
1422 git config color.diff.newMoved "cyan"
1425 test_expect_success
'move detection ignoring whitespace ' '
1426 q_to_tab <<-\EOF >lines.txt &&
1430 Qchanged long line 9
1437 git diff HEAD --no-renames --color-moved --color >actual.raw &&
1438 grep -v "index" actual.raw | test_decode_color >actual &&
1439 cat <<-\EOF >expected &&
1440 <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1441 <BOLD>--- a/lines.txt<RESET>
1442 <BOLD>+++ b/lines.txt<RESET>
1443 <CYAN>@@ -1,9 +1,9 @@<RESET>
1444 <GREEN>+<RESET> <GREEN>long line 6<RESET>
1445 <GREEN>+<RESET> <GREEN>long line 7<RESET>
1446 <GREEN>+<RESET> <GREEN>long line 8<RESET>
1447 <GREEN>+<RESET> <GREEN>changed long line 9<RESET>
1453 <RED>-long line 6<RESET>
1454 <RED>-long line 7<RESET>
1455 <RED>-long line 8<RESET>
1456 <RED>-long line 9<RESET>
1458 test_cmp expected actual &&
1460 git diff HEAD --no-renames --color-moved --color \
1461 --color-moved-ws=ignore-all-space >actual.raw &&
1462 grep -v "index" actual.raw | test_decode_color >actual &&
1463 cat <<-\EOF >expected &&
1464 <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1465 <BOLD>--- a/lines.txt<RESET>
1466 <BOLD>+++ b/lines.txt<RESET>
1467 <CYAN>@@ -1,9 +1,9 @@<RESET>
1468 <CYAN>+<RESET> <CYAN>long line 6<RESET>
1469 <CYAN>+<RESET> <CYAN>long line 7<RESET>
1470 <CYAN>+<RESET> <CYAN>long line 8<RESET>
1471 <GREEN>+<RESET> <GREEN>changed long line 9<RESET>
1477 <MAGENTA>-long line 6<RESET>
1478 <MAGENTA>-long line 7<RESET>
1479 <MAGENTA>-long line 8<RESET>
1480 <RED>-long line 9<RESET>
1482 test_cmp expected actual
1485 test_expect_success
'move detection ignoring whitespace changes' '
1487 # Lines 6-8 have a space change, but 9 is new whitespace
1488 q_to_tab <<-\EOF >lines.txt &&
1500 git diff HEAD --no-renames --color-moved --color >actual.raw &&
1501 grep -v "index" actual.raw | test_decode_color >actual &&
1502 cat <<-\EOF >expected &&
1503 <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1504 <BOLD>--- a/lines.txt<RESET>
1505 <BOLD>+++ b/lines.txt<RESET>
1506 <CYAN>@@ -1,9 +1,9 @@<RESET>
1507 <GREEN>+<RESET><GREEN>long line 6<RESET>
1508 <GREEN>+<RESET><GREEN>long line 7<RESET>
1509 <GREEN>+<RESET><GREEN>long line 8<RESET>
1510 <GREEN>+<RESET><GREEN>long li ne 9<RESET>
1516 <RED>-long line 6<RESET>
1517 <RED>-long line 7<RESET>
1518 <RED>-long line 8<RESET>
1519 <RED>-long line 9<RESET>
1521 test_cmp expected actual &&
1523 git diff HEAD --no-renames --color-moved --color \
1524 --color-moved-ws=ignore-space-change >actual.raw &&
1525 grep -v "index" actual.raw | test_decode_color >actual &&
1526 cat <<-\EOF >expected &&
1527 <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1528 <BOLD>--- a/lines.txt<RESET>
1529 <BOLD>+++ b/lines.txt<RESET>
1530 <CYAN>@@ -1,9 +1,9 @@<RESET>
1531 <CYAN>+<RESET><CYAN>long line 6<RESET>
1532 <CYAN>+<RESET><CYAN>long line 7<RESET>
1533 <CYAN>+<RESET><CYAN>long line 8<RESET>
1534 <GREEN>+<RESET><GREEN>long li ne 9<RESET>
1540 <MAGENTA>-long line 6<RESET>
1541 <MAGENTA>-long line 7<RESET>
1542 <MAGENTA>-long line 8<RESET>
1543 <RED>-long line 9<RESET>
1545 test_cmp expected actual
1548 test_expect_success
'move detection ignoring whitespace at eol' '
1550 # Lines 6-9 have new eol whitespace, but 9 also has it in the middle
1551 q_to_tab <<-\EOF >lines.txt &&
1563 # avoid cluttering the output with complaints about our eol whitespace
1564 test_config core.whitespace -blank-at-eol &&
1566 git diff HEAD --no-renames --color-moved --color >actual.raw &&
1567 grep -v "index" actual.raw | test_decode_color >actual &&
1568 cat <<-\EOF >expected &&
1569 <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1570 <BOLD>--- a/lines.txt<RESET>
1571 <BOLD>+++ b/lines.txt<RESET>
1572 <CYAN>@@ -1,9 +1,9 @@<RESET>
1573 <GREEN>+<RESET><GREEN>long line 6 <RESET>
1574 <GREEN>+<RESET><GREEN>long line 7 <RESET>
1575 <GREEN>+<RESET><GREEN>long line 8 <RESET>
1576 <GREEN>+<RESET><GREEN>long line 9 <RESET>
1582 <RED>-long line 6<RESET>
1583 <RED>-long line 7<RESET>
1584 <RED>-long line 8<RESET>
1585 <RED>-long line 9<RESET>
1587 test_cmp expected actual &&
1589 git diff HEAD --no-renames --color-moved --color \
1590 --color-moved-ws=ignore-space-at-eol >actual.raw &&
1591 grep -v "index" actual.raw | test_decode_color >actual &&
1592 cat <<-\EOF >expected &&
1593 <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1594 <BOLD>--- a/lines.txt<RESET>
1595 <BOLD>+++ b/lines.txt<RESET>
1596 <CYAN>@@ -1,9 +1,9 @@<RESET>
1597 <CYAN>+<RESET><CYAN>long line 6 <RESET>
1598 <CYAN>+<RESET><CYAN>long line 7 <RESET>
1599 <CYAN>+<RESET><CYAN>long line 8 <RESET>
1600 <GREEN>+<RESET><GREEN>long line 9 <RESET>
1606 <MAGENTA>-long line 6<RESET>
1607 <MAGENTA>-long line 7<RESET>
1608 <MAGENTA>-long line 8<RESET>
1609 <RED>-long line 9<RESET>
1611 test_cmp expected actual
1614 test_expect_success
'clean up whitespace-test colors' '
1615 git config --unset color.diff.oldMoved &&
1616 git config --unset color.diff.newMoved
1619 test_expect_success
'--color-moved block at end of diff output respects MIN_ALNUM_COUNT' '
1636 git diff HEAD --color-moved=zebra --color --no-renames >actual.raw &&
1637 grep -v "index" actual.raw | test_decode_color >actual &&
1638 cat >expected <<-\EOF &&
1639 <BOLD>diff --git a/bar b/bar<RESET>
1640 <BOLD>--- a/bar<RESET>
1641 <BOLD>+++ b/bar<RESET>
1642 <CYAN>@@ -0,0 +1 @@<RESET>
1643 <GREEN>+<RESET><GREEN>line1<RESET>
1644 <BOLD>diff --git a/foo b/foo<RESET>
1645 <BOLD>--- a/foo<RESET>
1646 <BOLD>+++ b/foo<RESET>
1647 <CYAN>@@ -1,2 +1 @@<RESET>
1648 irrelevant_line<RESET>
1652 test_cmp expected actual
1655 test_expect_success
'--color-moved respects MIN_ALNUM_COUNT' '
1658 nineteen chars 456789
1660 twenty chars 234567890
1670 twenty chars 234567890
1671 nineteen chars 456789
1674 git diff HEAD --color-moved=zebra --color --no-renames >actual.raw &&
1675 grep -v "index" actual.raw | test_decode_color >actual &&
1676 cat >expected <<-\EOF &&
1677 <BOLD>diff --git a/bar b/bar<RESET>
1678 <BOLD>--- a/bar<RESET>
1679 <BOLD>+++ b/bar<RESET>
1680 <CYAN>@@ -0,0 +1,2 @@<RESET>
1681 <BOLD;CYAN>+<RESET><BOLD;CYAN>twenty chars 234567890<RESET>
1682 <GREEN>+<RESET><GREEN>nineteen chars 456789<RESET>
1683 <BOLD>diff --git a/foo b/foo<RESET>
1684 <BOLD>--- a/foo<RESET>
1685 <BOLD>+++ b/foo<RESET>
1686 <CYAN>@@ -1,3 +1 @@<RESET>
1687 <RED>-nineteen chars 456789<RESET>
1688 irrelevant_line<RESET>
1689 <BOLD;MAGENTA>-twenty chars 234567890<RESET>
1692 test_cmp expected actual
1695 test_expect_success
'--color-moved treats adjacent blocks as separate for MIN_ALNUM_COUNT' '
1716 git diff HEAD --color-moved=zebra --color --no-renames >actual.raw &&
1717 grep -v "index" actual.raw | test_decode_color >actual &&
1718 cat >expected <<-\EOF &&
1719 <BOLD>diff --git a/bar b/bar<RESET>
1720 <BOLD>--- a/bar<RESET>
1721 <BOLD>+++ b/bar<RESET>
1722 <CYAN>@@ -0,0 +1,3 @@<RESET>
1723 <GREEN>+<RESET><GREEN>7charsB<RESET>
1724 <GREEN>+<RESET><GREEN>7charsC<RESET>
1725 <GREEN>+<RESET><GREEN>7charsA<RESET>
1726 <BOLD>diff --git a/foo b/foo<RESET>
1727 <BOLD>--- a/foo<RESET>
1728 <BOLD>+++ b/foo<RESET>
1729 <CYAN>@@ -1,4 +1 @@<RESET>
1730 <RED>-7charsA<RESET>
1731 irrelevant_line<RESET>
1732 <RED>-7charsB<RESET>
1733 <RED>-7charsC<RESET>
1736 test_cmp expected actual
1739 test_expect_success
'move detection with submodules' '
1740 test_create_repo bananas &&
1741 echo ripe >bananas/recipe &&
1742 git -C bananas add recipe &&
1743 test_commit fruit &&
1744 test_commit -C bananas recipe &&
1745 git submodule add ./bananas &&
1747 git commit -a -m "bananas are like a heavy library?" &&
1748 echo foul >bananas/recipe &&
1749 echo ripe >fruit.t &&
1751 git diff --submodule=diff --color-moved --color >actual &&
1753 # no move detection as the moved line is across repository boundaries.
1754 test_decode_color <actual >decoded_actual &&
1755 ! grep BGREEN decoded_actual &&
1756 ! grep BRED decoded_actual &&
1758 # nor did we mess with it another way
1759 git diff --submodule=diff --color | test_decode_color >expect &&
1760 test_cmp expect decoded_actual &&
1762 git submodule deinit bananas
1765 test_expect_success
'only move detection ignores white spaces' '
1767 q_to_tab <<-\EOF >text.txt &&
1768 a long line to exceed per-line minimum
1769 another long line to exceed per-line minimum
1773 git commit -m "add text" &&
1774 q_to_tab <<-\EOF >text.txt &&
1775 Qa long line to exceed per-line minimum
1776 Qanother long line to exceed per-line minimum
1780 # Make sure we get a different diff using -w
1781 git diff --color --color-moved -w >actual.raw &&
1782 grep -v "index" actual.raw | test_decode_color >actual &&
1783 q_to_tab <<-\EOF >expected &&
1784 <BOLD>diff --git a/text.txt b/text.txt<RESET>
1785 <BOLD>--- a/text.txt<RESET>
1786 <BOLD>+++ b/text.txt<RESET>
1787 <CYAN>@@ -1,3 +1,3 @@<RESET>
1788 Qa long line to exceed per-line minimum<RESET>
1789 Qanother long line to exceed per-line minimum<RESET>
1790 <RED>-original file<RESET>
1791 <GREEN>+<RESET><GREEN>new file<RESET>
1793 test_cmp expected actual &&
1795 # And now ignoring white space only in the move detection
1796 git diff --color --color-moved \
1797 --color-moved-ws=ignore-all-space,ignore-space-change,ignore-space-at-eol >actual.raw &&
1798 grep -v "index" actual.raw | test_decode_color >actual &&
1799 q_to_tab <<-\EOF >expected &&
1800 <BOLD>diff --git a/text.txt b/text.txt<RESET>
1801 <BOLD>--- a/text.txt<RESET>
1802 <BOLD>+++ b/text.txt<RESET>
1803 <CYAN>@@ -1,3 +1,3 @@<RESET>
1804 <BOLD;MAGENTA>-a long line to exceed per-line minimum<RESET>
1805 <BOLD;MAGENTA>-another long line to exceed per-line minimum<RESET>
1806 <RED>-original file<RESET>
1807 <BOLD;YELLOW>+<RESET>Q<BOLD;YELLOW>a long line to exceed per-line minimum<RESET>
1808 <BOLD;YELLOW>+<RESET>Q<BOLD;YELLOW>another long line to exceed per-line minimum<RESET>
1809 <GREEN>+<RESET><GREEN>new file<RESET>
1811 test_cmp expected actual
1814 test_expect_success
'compare whitespace delta across moved blocks' '
1817 q_to_tab <<-\EOF >text.txt &&
1821 QBut! <- this stands out
1823 QQdifferent starting
1829 QQQthat has similar lines
1830 QQQto previous blocks, but with different indent
1831 QQQYetQAnotherQoutlierQ
1835 git commit -m "add text.txt" &&
1837 q_to_tab <<-\EOF >text.txt &&
1841 QQQBut! <- this stands out
1849 QQthat has similar lines
1850 QQto previous blocks, but with different indent
1851 QQYetQAnotherQoutlier
1854 git diff --color --color-moved --color-moved-ws=allow-indentation-change >actual.raw &&
1855 grep -v "index" actual.raw | test_decode_color >actual &&
1857 q_to_tab <<-\EOF >expected &&
1858 <BOLD>diff --git a/text.txt b/text.txt<RESET>
1859 <BOLD>--- a/text.txt<RESET>
1860 <BOLD>+++ b/text.txt<RESET>
1861 <CYAN>@@ -1,14 +1,14 @@<RESET>
1862 <BOLD;MAGENTA>-QIndented<RESET>
1863 <BOLD;MAGENTA>-QText across<RESET>
1864 <BOLD;MAGENTA>-Qsome lines<RESET>
1865 <RED>-QBut! <- this stands out<RESET>
1866 <BOLD;MAGENTA>-QAdjusting with<RESET>
1867 <BOLD;MAGENTA>-QQdifferent starting<RESET>
1868 <BOLD;MAGENTA>-Qwhite spaces<RESET>
1869 <RED>-QAnother outlier<RESET>
1870 <BOLD;MAGENTA>-QQQIndented<RESET>
1871 <BOLD;MAGENTA>-QQQText across<RESET>
1872 <BOLD;MAGENTA>-QQQfive lines<RESET>
1873 <BOLD;MAGENTA>-QQQthat has similar lines<RESET>
1874 <BOLD;MAGENTA>-QQQto previous blocks, but with different indent<RESET>
1875 <RED>-QQQYetQAnotherQoutlierQ<RESET>
1876 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>Indented<RESET>
1877 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>Text across<RESET>
1878 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>some lines<RESET>
1879 <GREEN>+<RESET>QQQ<GREEN>But! <- this stands out<RESET>
1880 <BOLD;CYAN>+<RESET><BOLD;CYAN>Adjusting with<RESET>
1881 <BOLD;CYAN>+<RESET>Q<BOLD;CYAN>different starting<RESET>
1882 <BOLD;CYAN>+<RESET><BOLD;CYAN>white spaces<RESET>
1883 <GREEN>+<RESET><GREEN>AnotherQoutlier<RESET>
1884 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>Indented<RESET>
1885 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>Text across<RESET>
1886 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>five lines<RESET>
1887 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>that has similar lines<RESET>
1888 <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>to previous blocks, but with different indent<RESET>
1889 <GREEN>+<RESET>QQ<GREEN>YetQAnotherQoutlier<RESET>
1892 test_cmp expected actual
1895 test_expect_success
'compare whitespace delta incompatible with other space options' '
1896 test_must_fail git diff \
1897 --color-moved-ws=allow-indentation-change,ignore-all-space \
1899 test_i18ngrep allow-indentation-change err