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