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