1#!/bin/sh
2#
3# Copyright (c) 2006 Johannes E. Schindelin
4#
5
6test_description='Test special whitespace in diff engine.
7
8'
9. ./test-lib.sh
10. "$TEST_DIRECTORY"/diff-lib.sh
11
12test_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
20 cat <<-\EOF >x &&
21 do
22 {
23 nothing;
24 }
25 while (0);
26 EOF
27
28 cat <<-\EOF >expect &&
29 diff --git a/x b/x
30 index adf3937..6edc172 100644
31 --- a/x
32 +++ b/x
33 @@ -1,3 +1,5 @@
34 -do {
35 +do
36 +{
37 nothing;
38 -} while (0);
39 +}
40 +while (0);
41 EOF
42
43 git diff >out &&
44 test_cmp expect out &&
45
46 git diff -w >out &&
47 test_cmp expect out &&
48
49 git diff -b >out &&
50 test_cmp expect out
51'
52
53test_expect_success 'another test, without options' '
54 tr Q "\015" <<-\EOF >x &&
55 whitespace at beginning
56 whitespace change
57 whitespace in the middle
58 whitespace at end
59 unchanged line
60 CR at endQ
61 EOF
62
63 git update-index x &&
64
65 tr "_" " " <<-\EOF >x &&
66 _ whitespace at beginning
67 whitespace change
68 white space in the middle
69 whitespace at end__
70 unchanged line
71 CR at end
72 EOF
73
74 tr "Q_" "\015 " <<-\EOF >expect &&
75 diff --git a/x b/x
76 index d99af23..22d9f73 100644
77 --- a/x
78 +++ b/x
79 @@ -1,6 +1,6 @@
80 -whitespace at beginning
81 -whitespace change
82 -whitespace in the middle
83 -whitespace at end
84 + whitespace at beginning
85 +whitespace change
86 +white space in the middle
87 +whitespace at end__
88 unchanged line
89 -CR at endQ
90 +CR at end
91 EOF
92
93 git diff >out &&
94 test_cmp expect out &&
95
96 >expect &&
97 git diff -w >out &&
98 test_cmp expect out &&
99
100 git diff -w -b >out &&
101 test_cmp expect out &&
102
103 git diff -w --ignore-space-at-eol >out &&
104 test_cmp expect out &&
105
106 git diff -w -b --ignore-space-at-eol >out &&
107 test_cmp expect out &&
108
109
110 tr "Q_" "\015 " <<-\EOF >expect &&
111 diff --git a/x b/x
112 index d99af23..22d9f73 100644
113 --- a/x
114 +++ b/x
115 @@ -1,6 +1,6 @@
116 -whitespace at beginning
117 +_ whitespace at beginning
118 whitespace change
119 -whitespace in the middle
120 +white space in the middle
121 whitespace at end__
122 unchanged line
123 CR at end
124 EOF
125 git diff -b >out &&
126 test_cmp expect out &&
127
128 git diff -b --ignore-space-at-eol >out &&
129 test_cmp expect out &&
130
131 tr "Q_" "\015 " <<-\EOF >expect &&
132 diff --git a/x b/x
133 index d99af23..22d9f73 100644
134 --- a/x
135 +++ b/x
136 @@ -1,6 +1,6 @@
137 -whitespace at beginning
138 -whitespace change
139 -whitespace in the middle
140 +_ whitespace at beginning
141 +whitespace change
142 +white space in the middle
143 whitespace at end__
144 unchanged line
145 CR at end
146 EOF
147 git diff --ignore-space-at-eol >out &&
148 test_cmp expect out
149'
150
151test_expect_success 'ignore-blank-lines: only new lines' '
152 test_seq 5 >x &&
153 git update-index x &&
154 test_seq 5 | sed "/3/i\\
155" >x &&
156 git diff --ignore-blank-lines >out &&
157 >expect &&
158 test_cmp expect out
159'
160
161test_expect_success 'ignore-blank-lines: only new lines with space' '
162 test_seq 5 >x &&
163 git update-index x &&
164 test_seq 5 | sed "/3/i\\
165 " >x &&
166 git diff -w --ignore-blank-lines >out &&
167 >expect &&
168 test_cmp expect out
169'
170
171test_expect_success 'ignore-blank-lines: after change' '
172 cat <<-\EOF >x &&
173 1
174 2
175
176 3
177 4
178 5
179
180 6
181 7
182 EOF
183 git update-index x &&
184 cat <<-\EOF >x &&
185 change
186
187 1
188 2
189 3
190 4
191 5
192 6
193
194 7
195 EOF
196 git diff --inter-hunk-context=100 --ignore-blank-lines >out.tmp &&
197 cat <<-\EOF >expected &&
198 diff --git a/x b/x
199 --- a/x
200 +++ b/x
201 @@ -1,6 +1,7 @@
202 +change
203 +
204 1
205 2
206 -
207 3
208 4
209 5
210 EOF
211 compare_diff_patch expected out.tmp
212'
213
214test_expect_success 'ignore-blank-lines: before change' '
215 cat <<-\EOF >x &&
216 1
217 2
218
219 3
220 4
221 5
222 6
223 7
224 EOF
225 git update-index x &&
226 cat <<-\EOF >x &&
227
228 1
229 2
230 3
231 4
232 5
233
234 6
235 7
236 change
237 EOF
238 git diff --inter-hunk-context=100 --ignore-blank-lines >out.tmp &&
239 cat <<-\EOF >expected &&
240 diff --git a/x b/x
241 --- a/x
242 +++ b/x
243 @@ -4,5 +4,7 @@
244 3
245 4
246 5
247 +
248 6
249 7
250 +change
251 EOF
252 compare_diff_patch expected out.tmp
253'
254
255test_expect_success 'ignore-blank-lines: between changes' '
256 cat <<-\EOF >x &&
257 1
258 2
259 3
260 4
261 5
262
263
264 6
265 7
266 8
267 9
268 10
269 EOF
270 git update-index x &&
271 cat <<-\EOF >x &&
272 change
273 1
274 2
275
276 3
277 4
278 5
279 6
280 7
281 8
282
283 9
284 10
285 change
286 EOF
287 git diff --ignore-blank-lines >out.tmp &&
288 cat <<-\EOF >expected &&
289 diff --git a/x b/x
290 --- a/x
291 +++ b/x
292 @@ -1,5 +1,7 @@
293 +change
294 1
295 2
296 +
297 3
298 4
299 5
300 @@ -8,5 +8,7 @@
301 6
302 7
303 8
304 +
305 9
306 10
307 +change
308 EOF
309 compare_diff_patch expected out.tmp
310'
311
312test_expect_success 'ignore-blank-lines: between changes (with interhunkctx)' '
313 test_seq 10 >x &&
314 git update-index x &&
315 cat <<-\EOF >x &&
316 change
317 1
318 2
319
320 3
321 4
322 5
323
324 6
325 7
326 8
327 9
328
329 10
330 change
331 EOF
332 git diff --inter-hunk-context=2 --ignore-blank-lines >out.tmp &&
333 cat <<-\EOF >expected &&
334 diff --git a/x b/x
335 --- a/x
336 +++ b/x
337 @@ -1,10 +1,15 @@
338 +change
339 1
340 2
341 +
342 3
343 4
344 5
345 +
346 6
347 7
348 8
349 9
350 +
351 10
352 +change
353 EOF
354 compare_diff_patch expected out.tmp
355'
356
357test_expect_success 'ignore-blank-lines: scattered spaces' '
358 test_seq 10 >x &&
359 git update-index x &&
360 cat <<-\EOF >x &&
361 change
362 1
363 2
364 3
365
366 4
367
368 5
369
370 6
371
372
373 7
374
375 8
376 9
377 10
378 change
379 EOF
380 git diff --inter-hunk-context=4 --ignore-blank-lines >out.tmp &&
381 cat <<-\EOF >expected &&
382 diff --git a/x b/x
383 --- a/x
384 +++ b/x
385 @@ -1,3 +1,4 @@
386 +change
387 1
388 2
389 3
390 @@ -8,3 +15,4 @@
391 8
392 9
393 10
394 +change
395 EOF
396 compare_diff_patch expected out.tmp
397'
398
399test_expect_success 'ignore-blank-lines: spaces coalesce' '
400 test_seq 6 >x &&
401 git update-index x &&
402 cat <<-\EOF >x &&
403 change
404 1
405 2
406 3
407
408 4
409
410 5
411
412 6
413 change
414 EOF
415 git diff --inter-hunk-context=4 --ignore-blank-lines >out.tmp &&
416 cat <<-\EOF >expected &&
417 diff --git a/x b/x
418 --- a/x
419 +++ b/x
420 @@ -1,6 +1,11 @@
421 +change
422 1
423 2
424 3
425 +
426 4
427 +
428 5
429 +
430 6
431 +change
432 EOF
433 compare_diff_patch expected out.tmp
434'
435
436test_expect_success 'ignore-blank-lines: mix changes and blank lines' '
437 test_seq 16 >x &&
438 git update-index x &&
439 cat <<-\EOF >x &&
440 change
441 1
442 2
443
444 3
445 4
446 5
447 change
448 6
449 7
450 8
451
452 9
453 10
454 11
455 change
456 12
457 13
458 14
459
460 15
461 16
462 change
463 EOF
464 git diff --ignore-blank-lines >out.tmp &&
465 cat <<-\EOF >expected &&
466 diff --git a/x b/x
467 --- a/x
468 +++ b/x
469 @@ -1,8 +1,11 @@
470 +change
471 1
472 2
473 +
474 3
475 4
476 5
477 +change
478 6
479 7
480 8
481 @@ -9,8 +13,11 @@
482 9
483 10
484 11
485 +change
486 12
487 13
488 14
489 +
490 15
491 16
492 +change
493 EOF
494 compare_diff_patch expected out.tmp
495'
496
497test_expect_success 'check mixed spaces and tabs in indent' '
498 # This is indented with SP HT SP.
499 echo " foo();" >x &&
500 git diff --check | grep "space before tab in indent"
501'
502
503test_expect_success 'check mixed tabs and spaces in indent' '
504 # This is indented with HT SP HT.
505 echo " foo();" >x &&
506 git diff --check | grep "space before tab in indent"
507'
508
509test_expect_success 'check with no whitespace errors' '
510 git commit -m "snapshot" &&
511 echo "foo();" >x &&
512 git diff --check
513'
514
515test_expect_success 'check with trailing whitespace' '
516 echo "foo(); " >x &&
517 test_must_fail git diff --check
518'
519
520test_expect_success 'check with space before tab in indent' '
521 # indent has space followed by hard tab
522 echo " foo();" >x &&
523 test_must_fail git diff --check
524'
525
526test_expect_success '--check and --exit-code are not exclusive' '
527 git checkout x &&
528 git diff --check --exit-code
529'
530
531test_expect_success '--check and --quiet are not exclusive' '
532 git diff --check --quiet
533'
534
535test_expect_success 'check staged with no whitespace errors' '
536 echo "foo();" >x &&
537 git add x &&
538 git diff --cached --check
539'
540
541test_expect_success 'check staged with trailing whitespace' '
542 echo "foo(); " >x &&
543 git add x &&
544 test_must_fail git diff --cached --check
545'
546
547test_expect_success 'check staged with space before tab in indent' '
548 # indent has space followed by hard tab
549 echo " foo();" >x &&
550 git add x &&
551 test_must_fail git diff --cached --check
552'
553
554test_expect_success 'check with no whitespace errors (diff-index)' '
555 echo "foo();" >x &&
556 git add x &&
557 git diff-index --check HEAD
558'
559
560test_expect_success 'check with trailing whitespace (diff-index)' '
561 echo "foo(); " >x &&
562 git add x &&
563 test_must_fail git diff-index --check HEAD
564'
565
566test_expect_success 'check with space before tab in indent (diff-index)' '
567 # indent has space followed by hard tab
568 echo " foo();" >x &&
569 git add x &&
570 test_must_fail git diff-index --check HEAD
571'
572
573test_expect_success 'check staged with no whitespace errors (diff-index)' '
574 echo "foo();" >x &&
575 git add x &&
576 git diff-index --cached --check HEAD
577'
578
579test_expect_success 'check staged with trailing whitespace (diff-index)' '
580 echo "foo(); " >x &&
581 git add x &&
582 test_must_fail git diff-index --cached --check HEAD
583'
584
585test_expect_success 'check staged with space before tab in indent (diff-index)' '
586 # indent has space followed by hard tab
587 echo " foo();" >x &&
588 git add x &&
589 test_must_fail git diff-index --cached --check HEAD
590'
591
592test_expect_success 'check with no whitespace errors (diff-tree)' '
593 echo "foo();" >x &&
594 git commit -m "new commit" x &&
595 git diff-tree --check HEAD^ HEAD
596'
597
598test_expect_success 'check with trailing whitespace (diff-tree)' '
599 echo "foo(); " >x &&
600 git commit -m "another commit" x &&
601 test_must_fail git diff-tree --check HEAD^ HEAD
602'
603
604test_expect_success 'check with space before tab in indent (diff-tree)' '
605 # indent has space followed by hard tab
606 echo " foo();" >x &&
607 git commit -m "yet another" x &&
608 test_must_fail git diff-tree --check HEAD^ HEAD
609'
610
611test_expect_success 'check trailing whitespace (trailing-space: off)' '
612 git config core.whitespace "-trailing-space" &&
613 echo "foo (); " >x &&
614 git diff --check
615'
616
617test_expect_success 'check trailing whitespace (trailing-space: on)' '
618 git config core.whitespace "trailing-space" &&
619 echo "foo (); " >x &&
620 test_must_fail git diff --check
621'
622
623test_expect_success 'check space before tab in indent (space-before-tab: off)' '
624 # indent contains space followed by HT
625 git config core.whitespace "-space-before-tab" &&
626 echo " foo ();" >x &&
627 git diff --check
628'
629
630test_expect_success 'check space before tab in indent (space-before-tab: on)' '
631 # indent contains space followed by HT
632 git config core.whitespace "space-before-tab" &&
633 echo " foo (); " >x &&
634 test_must_fail git diff --check
635'
636
637test_expect_success 'check spaces as indentation (indent-with-non-tab: off)' '
638 git config core.whitespace "-indent-with-non-tab" &&
639 echo " foo ();" >x &&
640 git diff --check
641'
642
643test_expect_success 'check spaces as indentation (indent-with-non-tab: on)' '
644 git config core.whitespace "indent-with-non-tab" &&
645 echo " foo ();" >x &&
646 test_must_fail git diff --check
647'
648
649test_expect_success 'ditto, but tabwidth=9' '
650 git config core.whitespace "indent-with-non-tab,tabwidth=9" &&
651 git diff --check
652'
653
654test_expect_success 'check tabs and spaces as indentation (indent-with-non-tab: on)' '
655 git config core.whitespace "indent-with-non-tab" &&
656 echo " foo ();" >x &&
657 test_must_fail git diff --check
658'
659
660test_expect_success 'ditto, but tabwidth=10' '
661 git config core.whitespace "indent-with-non-tab,tabwidth=10" &&
662 test_must_fail git diff --check
663'
664
665test_expect_success 'ditto, but tabwidth=20' '
666 git config core.whitespace "indent-with-non-tab,tabwidth=20" &&
667 git diff --check
668'
669
670test_expect_success 'check tabs as indentation (tab-in-indent: off)' '
671 git config core.whitespace "-tab-in-indent" &&
672 echo " foo ();" >x &&
673 git diff --check
674'
675
676test_expect_success 'check tabs as indentation (tab-in-indent: on)' '
677 git config core.whitespace "tab-in-indent" &&
678 echo " foo ();" >x &&
679 test_must_fail git diff --check
680'
681
682test_expect_success 'check tabs and spaces as indentation (tab-in-indent: on)' '
683 git config core.whitespace "tab-in-indent" &&
684 echo " foo ();" >x &&
685 test_must_fail git diff --check
686'
687
688test_expect_success 'ditto, but tabwidth=1 (must be irrelevant)' '
689 git config core.whitespace "tab-in-indent,tabwidth=1" &&
690 test_must_fail git diff --check
691'
692
693test_expect_success 'check tab-in-indent and indent-with-non-tab conflict' '
694 git config core.whitespace "tab-in-indent,indent-with-non-tab" &&
695 echo "foo ();" >x &&
696 test_must_fail git diff --check
697'
698
699test_expect_success 'check tab-in-indent excluded from wildcard whitespace attribute' '
700 git config --unset core.whitespace &&
701 echo "x whitespace" >.gitattributes &&
702 echo " foo ();" >x &&
703 git diff --check &&
704 rm -f .gitattributes
705'
706
707test_expect_success 'line numbers in --check output are correct' '
708 echo "" >x &&
709 echo "foo(); " >>x &&
710 git diff --check | grep "x:2:"
711'
712
713test_expect_success 'checkdiff detects new trailing blank lines (1)' '
714 echo "foo();" >x &&
715 echo "" >>x &&
716 git diff --check | grep "new blank line"
717'
718
719test_expect_success 'checkdiff detects new trailing blank lines (2)' '
720 { echo a; echo b; echo; echo; } >x &&
721 git add x &&
722 { echo a; echo; echo; echo; echo; } >x &&
723 git diff --check | grep "new blank line"
724'
725
726test_expect_success 'checkdiff allows new blank lines' '
727 git checkout x &&
728 mv x y &&
729 (
730 echo "/* This is new */" &&
731 echo "" &&
732 cat y
733 ) >x &&
734 git diff --check
735'
736
737cat <<EOF >expect
738EOF
739test_expect_success 'whitespace-only changes not reported' '
740 git reset --hard &&
741 echo >x "hello world" &&
742 git add x &&
743 git commit -m "hello 1" &&
744 echo >x "hello world" &&
745 git diff -b >actual &&
746 test_cmp expect actual
747'
748
749cat <<EOF >expect
750diff --git a/x b/z
751similarity index NUM%
752rename from x
753rename to z
754index 380c32a..a97b785 100644
755EOF
756test_expect_success 'whitespace-only changes reported across renames' '
757 git reset --hard &&
758 for i in 1 2 3 4 5 6 7 8 9; do echo "$i$i$i$i$i$i"; done >x &&
759 git add x &&
760 git commit -m "base" &&
761 sed -e "5s/^/ /" x >z &&
762 git rm x &&
763 git add z &&
764 git diff -w -M --cached |
765 sed -e "/^similarity index /s/[0-9][0-9]*/NUM/" >actual &&
766 test_cmp expect actual
767'
768
769cat >expected <<\EOF
770diff --git a/empty b/void
771similarity index 100%
772rename from empty
773rename to void
774EOF
775
776test_expect_success 'rename empty' '
777 git reset --hard &&
778 >empty &&
779 git add empty &&
780 git commit -m empty &&
781 git mv empty void &&
782 git diff -w --cached -M >current &&
783 test_cmp expected current
784'
785
786test_expect_success 'combined diff with autocrlf conversion' '
787
788 git reset --hard &&
789 echo >x hello &&
790 git commit -m "one side" x &&
791 git checkout HEAD^ &&
792 echo >x goodbye &&
793 git commit -m "the other side" x &&
794 git config core.autocrlf true &&
795 test_must_fail git merge master &&
796
797 git diff | sed -e "1,/^@@@/d" >actual &&
798 ! grep "^-" actual
799
800'
801
802# Start testing the colored format for whitespace checks
803
804test_expect_success 'setup diff colors' '
805 git config color.diff.plain normal &&
806 git config color.diff.meta bold &&
807 git config color.diff.frag cyan &&
808 git config color.diff.func normal &&
809 git config color.diff.old red &&
810 git config color.diff.new green &&
811 git config color.diff.commit yellow &&
812 git config color.diff.whitespace blue &&
813
814 git config core.autocrlf false
815'
816
817test_expect_success 'diff that introduces a line with only tabs' '
818 git config core.whitespace blank-at-eol &&
819 git reset --hard &&
820 echo "test" >x &&
821 git commit -m "initial" x &&
822 echo "{NTN}" | tr "NT" "\n\t" >>x &&
823 git diff --color | test_decode_color >current &&
824
825 cat >expected <<-\EOF &&
826 <BOLD>diff --git a/x b/x<RESET>
827 <BOLD>index 9daeafb..2874b91 100644<RESET>
828 <BOLD>--- a/x<RESET>
829 <BOLD>+++ b/x<RESET>
830 <CYAN>@@ -1 +1,4 @@<RESET>
831 test<RESET>
832 <GREEN>+<RESET><GREEN>{<RESET>
833 <GREEN>+<RESET><BLUE> <RESET>
834 <GREEN>+<RESET><GREEN>}<RESET>
835 EOF
836
837 test_cmp expected current
838'
839
840test_expect_success 'diff that introduces and removes ws breakages' '
841 git reset --hard &&
842 {
843 echo "0. blank-at-eol " &&
844 echo "1. blank-at-eol "
845 } >x &&
846 git commit -a --allow-empty -m preimage &&
847 {
848 echo "0. blank-at-eol " &&
849 echo "1. still-blank-at-eol " &&
850 echo "2. and a new line "
851 } >x &&
852
853 git diff --color |
854 test_decode_color >current &&
855
856 cat >expected <<-\EOF &&
857 <BOLD>diff --git a/x b/x<RESET>
858 <BOLD>index d0233a2..700886e 100644<RESET>
859 <BOLD>--- a/x<RESET>
860 <BOLD>+++ b/x<RESET>
861 <CYAN>@@ -1,2 +1,3 @@<RESET>
862 0. blank-at-eol <RESET>
863 <RED>-1. blank-at-eol <RESET>
864 <GREEN>+<RESET><GREEN>1. still-blank-at-eol<RESET><BLUE> <RESET>
865 <GREEN>+<RESET><GREEN>2. and a new line<RESET><BLUE> <RESET>
866 EOF
867
868 test_cmp expected current
869'
870
871test_expect_success 'ws-error-highlight test setup' '
872
873 git reset --hard &&
874 {
875 echo "0. blank-at-eol " &&
876 echo "1. blank-at-eol "
877 } >x &&
878 git commit -a --allow-empty -m preimage &&
879 {
880 echo "0. blank-at-eol " &&
881 echo "1. still-blank-at-eol " &&
882 echo "2. and a new line "
883 } >x &&
884
885 cat >expect.default-old <<-\EOF &&
886 <BOLD>diff --git a/x b/x<RESET>
887 <BOLD>index d0233a2..700886e 100644<RESET>
888 <BOLD>--- a/x<RESET>
889 <BOLD>+++ b/x<RESET>
890 <CYAN>@@ -1,2 +1,3 @@<RESET>
891 0. blank-at-eol <RESET>
892 <RED>-<RESET><RED>1. blank-at-eol<RESET><BLUE> <RESET>
893 <GREEN>+<RESET><GREEN>1. still-blank-at-eol<RESET><BLUE> <RESET>
894 <GREEN>+<RESET><GREEN>2. and a new line<RESET><BLUE> <RESET>
895 EOF
896
897 cat >expect.all <<-\EOF &&
898 <BOLD>diff --git a/x b/x<RESET>
899 <BOLD>index d0233a2..700886e 100644<RESET>
900 <BOLD>--- a/x<RESET>
901 <BOLD>+++ b/x<RESET>
902 <CYAN>@@ -1,2 +1,3 @@<RESET>
903 <RESET>0. blank-at-eol<RESET><BLUE> <RESET>
904 <RED>-<RESET><RED>1. blank-at-eol<RESET><BLUE> <RESET>
905 <GREEN>+<RESET><GREEN>1. still-blank-at-eol<RESET><BLUE> <RESET>
906 <GREEN>+<RESET><GREEN>2. and a new line<RESET><BLUE> <RESET>
907 EOF
908
909 cat >expect.none <<-\EOF
910 <BOLD>diff --git a/x b/x<RESET>
911 <BOLD>index d0233a2..700886e 100644<RESET>
912 <BOLD>--- a/x<RESET>
913 <BOLD>+++ b/x<RESET>
914 <CYAN>@@ -1,2 +1,3 @@<RESET>
915 0. blank-at-eol <RESET>
916 <RED>-1. blank-at-eol <RESET>
917 <GREEN>+1. still-blank-at-eol <RESET>
918 <GREEN>+2. and a new line <RESET>
919 EOF
920
921'
922
923test_expect_success 'test --ws-error-highlight option' '
924
925 git diff --color --ws-error-highlight=default,old |
926 test_decode_color >current &&
927 test_cmp expect.default-old current &&
928
929 git diff --color --ws-error-highlight=all |
930 test_decode_color >current &&
931 test_cmp expect.all current &&
932
933 git diff --color --ws-error-highlight=none |
934 test_decode_color >current &&
935 test_cmp expect.none current
936
937'
938
939test_expect_success 'test diff.wsErrorHighlight config' '
940
941 git -c diff.wsErrorHighlight=default,old diff --color |
942 test_decode_color >current &&
943 test_cmp expect.default-old current &&
944
945 git -c diff.wsErrorHighlight=all diff --color |
946 test_decode_color >current &&
947 test_cmp expect.all current &&
948
949 git -c diff.wsErrorHighlight=none diff --color |
950 test_decode_color >current &&
951 test_cmp expect.none current
952
953'
954
955test_expect_success 'option overrides diff.wsErrorHighlight' '
956
957 git -c diff.wsErrorHighlight=none \
958 diff --color --ws-error-highlight=default,old |
959 test_decode_color >current &&
960 test_cmp expect.default-old current &&
961
962 git -c diff.wsErrorHighlight=default \
963 diff --color --ws-error-highlight=all |
964 test_decode_color >current &&
965 test_cmp expect.all current &&
966
967 git -c diff.wsErrorHighlight=all \
968 diff --color --ws-error-highlight=none |
969 test_decode_color >current &&
970 test_cmp expect.none current
971
972'
973
974test_expect_success 'detect moved code, complete file' '
975 git reset --hard &&
976 cat <<-\EOF >test.c &&
977 #include<stdio.h>
978 main()
979 {
980 printf("Hello World");
981 }
982 EOF
983 git add test.c &&
984 git commit -m "add main function" &&
985 git mv test.c main.c &&
986 test_config color.diff.oldMoved "normal red" &&
987 test_config color.diff.newMoved "normal green" &&
988 git diff HEAD --color-moved=zebra --color --no-renames | test_decode_color >actual &&
989 cat >expected <<-\EOF &&
990 <BOLD>diff --git a/main.c b/main.c<RESET>
991 <BOLD>new file mode 100644<RESET>
992 <BOLD>index 0000000..a986c57<RESET>
993 <BOLD>--- /dev/null<RESET>
994 <BOLD>+++ b/main.c<RESET>
995 <CYAN>@@ -0,0 +1,5 @@<RESET>
996 <BGREEN>+<RESET><BGREEN>#include<stdio.h><RESET>
997 <BGREEN>+<RESET><BGREEN>main()<RESET>
998 <BGREEN>+<RESET><BGREEN>{<RESET>
999 <BGREEN>+<RESET><BGREEN>printf("Hello World");<RESET>
1000 <BGREEN>+<RESET><BGREEN>}<RESET>
1001 <BOLD>diff --git a/test.c b/test.c<RESET>
1002 <BOLD>deleted file mode 100644<RESET>
1003 <BOLD>index a986c57..0000000<RESET>
1004 <BOLD>--- a/test.c<RESET>
1005 <BOLD>+++ /dev/null<RESET>
1006 <CYAN>@@ -1,5 +0,0 @@<RESET>
1007 <BRED>-#include<stdio.h><RESET>
1008 <BRED>-main()<RESET>
1009 <BRED>-{<RESET>
1010 <BRED>-printf("Hello World");<RESET>
1011 <BRED>-}<RESET>
1012 EOF
1013
1014 test_cmp expected actual
1015'
1016
1017test_expect_success 'detect malicious moved code, inside file' '
1018 test_config color.diff.oldMoved "normal red" &&
1019 test_config color.diff.newMoved "normal green" &&
1020 test_config color.diff.oldMovedAlternative "blue" &&
1021 test_config color.diff.newMovedAlternative "yellow" &&
1022 git reset --hard &&
1023 cat <<-\EOF >main.c &&
1024 #include<stdio.h>
1025 int stuff()
1026 {
1027 printf("Hello ");
1028 printf("World\n");
1029 }
1030
1031 int secure_foo(struct user *u)
1032 {
1033 if (!u->is_allowed_foo)
1034 return;
1035 foo(u);
1036 }
1037
1038 int main()
1039 {
1040 foo();
1041 }
1042 EOF
1043 cat <<-\EOF >test.c &&
1044 #include<stdio.h>
1045 int bar()
1046 {
1047 printf("Hello World, but different\n");
1048 }
1049
1050 int another_function()
1051 {
1052 bar();
1053 }
1054 EOF
1055 git add main.c test.c &&
1056 git commit -m "add main and test file" &&
1057 cat <<-\EOF >main.c &&
1058 #include<stdio.h>
1059 int stuff()
1060 {
1061 printf("Hello ");
1062 printf("World\n");
1063 }
1064
1065 int main()
1066 {
1067 foo();
1068 }
1069 EOF
1070 cat <<-\EOF >test.c &&
1071 #include<stdio.h>
1072 int bar()
1073 {
1074 printf("Hello World, but different\n");
1075 }
1076
1077 int secure_foo(struct user *u)
1078 {
1079 foo(u);
1080 if (!u->is_allowed_foo)
1081 return;
1082 }
1083
1084 int another_function()
1085 {
1086 bar();
1087 }
1088 EOF
1089 git diff HEAD --no-renames --color-moved=zebra --color | test_decode_color >actual &&
1090 cat <<-\EOF >expected &&
1091 <BOLD>diff --git a/main.c b/main.c<RESET>
1092 <BOLD>index 27a619c..7cf9336 100644<RESET>
1093 <BOLD>--- a/main.c<RESET>
1094 <BOLD>+++ b/main.c<RESET>
1095 <CYAN>@@ -5,13 +5,6 @@<RESET> <RESET>printf("Hello ");<RESET>
1096 printf("World\n");<RESET>
1097 }<RESET>
1098 <RESET>
1099 <BRED>-int secure_foo(struct user *u)<RESET>
1100 <BRED>-{<RESET>
1101 <BLUE>-if (!u->is_allowed_foo)<RESET>
1102 <BLUE>-return;<RESET>
1103 <RED>-foo(u);<RESET>
1104 <RED>-}<RESET>
1105 <RED>-<RESET>
1106 int main()<RESET>
1107 {<RESET>
1108 foo();<RESET>
1109 <BOLD>diff --git a/test.c b/test.c<RESET>
1110 <BOLD>index 1dc1d85..2bedec9 100644<RESET>
1111 <BOLD>--- a/test.c<RESET>
1112 <BOLD>+++ b/test.c<RESET>
1113 <CYAN>@@ -4,6 +4,13 @@<RESET> <RESET>int bar()<RESET>
1114 printf("Hello World, but different\n");<RESET>
1115 }<RESET>
1116 <RESET>
1117 <BGREEN>+<RESET><BGREEN>int secure_foo(struct user *u)<RESET>
1118 <BGREEN>+<RESET><BGREEN>{<RESET>
1119 <GREEN>+<RESET><GREEN>foo(u);<RESET>
1120 <BGREEN>+<RESET><BGREEN>if (!u->is_allowed_foo)<RESET>
1121 <BGREEN>+<RESET><BGREEN>return;<RESET>
1122 <GREEN>+<RESET><GREEN>}<RESET>
1123 <GREEN>+<RESET>
1124 int another_function()<RESET>
1125 {<RESET>
1126 bar();<RESET>
1127 EOF
1128
1129 test_cmp expected actual
1130'
1131
1132test_expect_success 'plain moved code, inside file' '
1133 test_config color.diff.oldMoved "normal red" &&
1134 test_config color.diff.newMoved "normal green" &&
1135 test_config color.diff.oldMovedAlternative "blue" &&
1136 test_config color.diff.newMovedAlternative "yellow" &&
1137 # needs previous test as setup
1138 git diff HEAD --no-renames --color-moved=plain --color | test_decode_color >actual &&
1139 cat <<-\EOF >expected &&
1140 <BOLD>diff --git a/main.c b/main.c<RESET>
1141 <BOLD>index 27a619c..7cf9336 100644<RESET>
1142 <BOLD>--- a/main.c<RESET>
1143 <BOLD>+++ b/main.c<RESET>
1144 <CYAN>@@ -5,13 +5,6 @@<RESET> <RESET>printf("Hello ");<RESET>
1145 printf("World\n");<RESET>
1146 }<RESET>
1147 <RESET>
1148 <BRED>-int secure_foo(struct user *u)<RESET>
1149 <BRED>-{<RESET>
1150 <BRED>-if (!u->is_allowed_foo)<RESET>
1151 <BRED>-return;<RESET>
1152 <BRED>-foo(u);<RESET>
1153 <BRED>-}<RESET>
1154 <BRED>-<RESET>
1155 int main()<RESET>
1156 {<RESET>
1157 foo();<RESET>
1158 <BOLD>diff --git a/test.c b/test.c<RESET>
1159 <BOLD>index 1dc1d85..2bedec9 100644<RESET>
1160 <BOLD>--- a/test.c<RESET>
1161 <BOLD>+++ b/test.c<RESET>
1162 <CYAN>@@ -4,6 +4,13 @@<RESET> <RESET>int bar()<RESET>
1163 printf("Hello World, but different\n");<RESET>
1164 }<RESET>
1165 <RESET>
1166 <BGREEN>+<RESET><BGREEN>int secure_foo(struct user *u)<RESET>
1167 <BGREEN>+<RESET><BGREEN>{<RESET>
1168 <BGREEN>+<RESET><BGREEN>foo(u);<RESET>
1169 <BGREEN>+<RESET><BGREEN>if (!u->is_allowed_foo)<RESET>
1170 <BGREEN>+<RESET><BGREEN>return;<RESET>
1171 <BGREEN>+<RESET><BGREEN>}<RESET>
1172 <BGREEN>+<RESET>
1173 int another_function()<RESET>
1174 {<RESET>
1175 bar();<RESET>
1176 EOF
1177
1178 test_cmp expected actual
1179'
1180
1181test_expect_success 'detect permutations inside moved code -- dimmed_zebra' '
1182 git reset --hard &&
1183 cat <<-\EOF >lines.txt &&
1184 long line 1
1185 long line 2
1186 long line 3
1187 line 4
1188 line 5
1189 line 6
1190 line 7
1191 line 8
1192 line 9
1193 line 10
1194 line 11
1195 line 12
1196 line 13
1197 long line 14
1198 long line 15
1199 long line 16
1200 EOF
1201 git add lines.txt &&
1202 git commit -m "add poetry" &&
1203 cat <<-\EOF >lines.txt &&
1204 line 4
1205 line 5
1206 line 6
1207 line 7
1208 line 8
1209 line 9
1210 long line 1
1211 long line 2
1212 long line 3
1213 long line 14
1214 long line 15
1215 long line 16
1216 line 10
1217 line 11
1218 line 12
1219 line 13
1220 EOF
1221 test_config color.diff.oldMoved "magenta" &&
1222 test_config color.diff.newMoved "cyan" &&
1223 test_config color.diff.oldMovedAlternative "blue" &&
1224 test_config color.diff.newMovedAlternative "yellow" &&
1225 test_config color.diff.oldMovedDimmed "normal magenta" &&
1226 test_config color.diff.newMovedDimmed "normal cyan" &&
1227 test_config color.diff.oldMovedAlternativeDimmed "normal blue" &&
1228 test_config color.diff.newMovedAlternativeDimmed "normal yellow" &&
1229 git diff HEAD --no-renames --color-moved=dimmed_zebra --color |
1230 grep -v "index" |
1231 test_decode_color >actual &&
1232 cat <<-\EOF >expected &&
1233 <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1234 <BOLD>--- a/lines.txt<RESET>
1235 <BOLD>+++ b/lines.txt<RESET>
1236 <CYAN>@@ -1,16 +1,16 @@<RESET>
1237 <BMAGENTA>-long line 1<RESET>
1238 <BMAGENTA>-long line 2<RESET>
1239 <BMAGENTA>-long line 3<RESET>
1240 line 4<RESET>
1241 line 5<RESET>
1242 line 6<RESET>
1243 line 7<RESET>
1244 line 8<RESET>
1245 line 9<RESET>
1246 <BCYAN>+<RESET><BCYAN>long line 1<RESET>
1247 <BCYAN>+<RESET><BCYAN>long line 2<RESET>
1248 <CYAN>+<RESET><CYAN>long line 3<RESET>
1249 <YELLOW>+<RESET><YELLOW>long line 14<RESET>
1250 <BYELLOW>+<RESET><BYELLOW>long line 15<RESET>
1251 <BYELLOW>+<RESET><BYELLOW>long line 16<RESET>
1252 line 10<RESET>
1253 line 11<RESET>
1254 line 12<RESET>
1255 line 13<RESET>
1256 <BMAGENTA>-long line 14<RESET>
1257 <BMAGENTA>-long line 15<RESET>
1258 <BMAGENTA>-long line 16<RESET>
1259 EOF
1260 test_cmp expected actual
1261'
1262
1263test_expect_success 'cmd option assumes configured colored-moved' '
1264 test_config color.diff.oldMoved "magenta" &&
1265 test_config color.diff.newMoved "cyan" &&
1266 test_config color.diff.oldMovedAlternative "blue" &&
1267 test_config color.diff.newMovedAlternative "yellow" &&
1268 test_config color.diff.oldMovedDimmed "normal magenta" &&
1269 test_config color.diff.newMovedDimmed "normal cyan" &&
1270 test_config color.diff.oldMovedAlternativeDimmed "normal blue" &&
1271 test_config color.diff.newMovedAlternativeDimmed "normal yellow" &&
1272 test_config diff.colorMoved zebra &&
1273 git diff HEAD --no-renames --color-moved --color |
1274 grep -v "index" |
1275 test_decode_color >actual &&
1276 cat <<-\EOF >expected &&
1277 <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1278 <BOLD>--- a/lines.txt<RESET>
1279 <BOLD>+++ b/lines.txt<RESET>
1280 <CYAN>@@ -1,16 +1,16 @@<RESET>
1281 <MAGENTA>-long line 1<RESET>
1282 <MAGENTA>-long line 2<RESET>
1283 <MAGENTA>-long line 3<RESET>
1284 line 4<RESET>
1285 line 5<RESET>
1286 line 6<RESET>
1287 line 7<RESET>
1288 line 8<RESET>
1289 line 9<RESET>
1290 <CYAN>+<RESET><CYAN>long line 1<RESET>
1291 <CYAN>+<RESET><CYAN>long line 2<RESET>
1292 <CYAN>+<RESET><CYAN>long line 3<RESET>
1293 <YELLOW>+<RESET><YELLOW>long line 14<RESET>
1294 <YELLOW>+<RESET><YELLOW>long line 15<RESET>
1295 <YELLOW>+<RESET><YELLOW>long line 16<RESET>
1296 line 10<RESET>
1297 line 11<RESET>
1298 line 12<RESET>
1299 line 13<RESET>
1300 <MAGENTA>-long line 14<RESET>
1301 <MAGENTA>-long line 15<RESET>
1302 <MAGENTA>-long line 16<RESET>
1303 EOF
1304 test_cmp expected actual
1305'
1306
1307test_expect_success 'no effect from --color-moved with --word-diff' '
1308 cat <<-\EOF >text.txt &&
1309 Lorem Ipsum is simply dummy text of the printing and typesetting industry.
1310 EOF
1311 git add text.txt &&
1312 git commit -a -m "clean state" &&
1313 cat <<-\EOF >text.txt &&
1314 simply Lorem Ipsum dummy is text of the typesetting and printing industry.
1315 EOF
1316 git diff --color-moved --word-diff >actual &&
1317 git diff --word-diff >expect &&
1318 test_cmp expect actual
1319'
1320
1321test_expect_success 'move detection ignoring whitespace ' '
1322 git reset --hard &&
1323 cat <<\EOF >lines.txt &&
1324line 1
1325line 2
1326line 3
1327line 4
1328long line 5
1329long line 6
1330long line 7
1331EOF
1332 git add lines.txt &&
1333 git commit -m "add poetry" &&
1334 cat <<\EOF >lines.txt &&
1335 long line 5
1336 long line 6
1337 long line 7
1338line 1
1339line 2
1340line 3
1341line 4
1342EOF
1343 test_config color.diff.oldMoved "magenta" &&
1344 test_config color.diff.newMoved "cyan" &&
1345 git diff HEAD --no-renames --color-moved --color |
1346 grep -v "index" |
1347 test_decode_color >actual &&
1348 cat <<-\EOF >expected &&
1349 <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1350 <BOLD>--- a/lines.txt<RESET>
1351 <BOLD>+++ b/lines.txt<RESET>
1352 <CYAN>@@ -1,7 +1,7 @@<RESET>
1353 <GREEN>+<RESET> <GREEN>long line 5<RESET>
1354 <GREEN>+<RESET> <GREEN>long line 6<RESET>
1355 <GREEN>+<RESET> <GREEN>long line 7<RESET>
1356 line 1<RESET>
1357 line 2<RESET>
1358 line 3<RESET>
1359 line 4<RESET>
1360 <RED>-long line 5<RESET>
1361 <RED>-long line 6<RESET>
1362 <RED>-long line 7<RESET>
1363 EOF
1364 test_cmp expected actual &&
1365
1366 git diff HEAD --no-renames -w --color-moved --color |
1367 grep -v "index" |
1368 test_decode_color >actual &&
1369 cat <<-\EOF >expected &&
1370 <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1371 <BOLD>--- a/lines.txt<RESET>
1372 <BOLD>+++ b/lines.txt<RESET>
1373 <CYAN>@@ -1,7 +1,7 @@<RESET>
1374 <CYAN>+<RESET> <CYAN>long line 5<RESET>
1375 <CYAN>+<RESET> <CYAN>long line 6<RESET>
1376 <CYAN>+<RESET> <CYAN>long line 7<RESET>
1377 line 1<RESET>
1378 line 2<RESET>
1379 line 3<RESET>
1380 line 4<RESET>
1381 <MAGENTA>-long line 5<RESET>
1382 <MAGENTA>-long line 6<RESET>
1383 <MAGENTA>-long line 7<RESET>
1384 EOF
1385 test_cmp expected actual
1386'
1387
1388test_expect_success '--color-moved block at end of diff output respects MIN_ALNUM_COUNT' '
1389 git reset --hard &&
1390 >bar &&
1391 cat <<-\EOF >foo &&
1392 irrelevant_line
1393 line1
1394 EOF
1395 git add foo bar &&
1396 git commit -m x &&
1397
1398 cat <<-\EOF >bar &&
1399 line1
1400 EOF
1401 cat <<-\EOF >foo &&
1402 irrelevant_line
1403 EOF
1404
1405 git diff HEAD --color-moved=zebra --color --no-renames |
1406 grep -v "index" |
1407 test_decode_color >actual &&
1408 cat >expected <<-\EOF &&
1409 <BOLD>diff --git a/bar b/bar<RESET>
1410 <BOLD>--- a/bar<RESET>
1411 <BOLD>+++ b/bar<RESET>
1412 <CYAN>@@ -0,0 +1 @@<RESET>
1413 <GREEN>+<RESET><GREEN>line1<RESET>
1414 <BOLD>diff --git a/foo b/foo<RESET>
1415 <BOLD>--- a/foo<RESET>
1416 <BOLD>+++ b/foo<RESET>
1417 <CYAN>@@ -1,2 +1 @@<RESET>
1418 irrelevant_line<RESET>
1419 <RED>-line1<RESET>
1420 EOF
1421
1422 test_cmp expected actual
1423'
1424
1425test_expect_success '--color-moved respects MIN_ALNUM_COUNT' '
1426 git reset --hard &&
1427 cat <<-\EOF >foo &&
1428 nineteen chars 456789
1429 irrelevant_line
1430 twenty chars 234567890
1431 EOF
1432 >bar &&
1433 git add foo bar &&
1434 git commit -m x &&
1435
1436 cat <<-\EOF >foo &&
1437 irrelevant_line
1438 EOF
1439 cat <<-\EOF >bar &&
1440 twenty chars 234567890
1441 nineteen chars 456789
1442 EOF
1443
1444 git diff HEAD --color-moved=zebra --color --no-renames |
1445 grep -v "index" |
1446 test_decode_color >actual &&
1447 cat >expected <<-\EOF &&
1448 <BOLD>diff --git a/bar b/bar<RESET>
1449 <BOLD>--- a/bar<RESET>
1450 <BOLD>+++ b/bar<RESET>
1451 <CYAN>@@ -0,0 +1,2 @@<RESET>
1452 <BOLD;CYAN>+<RESET><BOLD;CYAN>twenty chars 234567890<RESET>
1453 <GREEN>+<RESET><GREEN>nineteen chars 456789<RESET>
1454 <BOLD>diff --git a/foo b/foo<RESET>
1455 <BOLD>--- a/foo<RESET>
1456 <BOLD>+++ b/foo<RESET>
1457 <CYAN>@@ -1,3 +1 @@<RESET>
1458 <RED>-nineteen chars 456789<RESET>
1459 irrelevant_line<RESET>
1460 <BOLD;MAGENTA>-twenty chars 234567890<RESET>
1461 EOF
1462
1463 test_cmp expected actual
1464'
1465
1466test_expect_success '--color-moved treats adjacent blocks as separate for MIN_ALNUM_COUNT' '
1467 git reset --hard &&
1468 cat <<-\EOF >foo &&
1469 7charsA
1470 irrelevant_line
1471 7charsB
1472 7charsC
1473 EOF
1474 >bar &&
1475 git add foo bar &&
1476 git commit -m x &&
1477
1478 cat <<-\EOF >foo &&
1479 irrelevant_line
1480 EOF
1481 cat <<-\EOF >bar &&
1482 7charsB
1483 7charsC
1484 7charsA
1485 EOF
1486
1487 git diff HEAD --color-moved=zebra --color --no-renames | grep -v "index" | test_decode_color >actual &&
1488 cat >expected <<-\EOF &&
1489 <BOLD>diff --git a/bar b/bar<RESET>
1490 <BOLD>--- a/bar<RESET>
1491 <BOLD>+++ b/bar<RESET>
1492 <CYAN>@@ -0,0 +1,3 @@<RESET>
1493 <GREEN>+<RESET><GREEN>7charsB<RESET>
1494 <GREEN>+<RESET><GREEN>7charsC<RESET>
1495 <GREEN>+<RESET><GREEN>7charsA<RESET>
1496 <BOLD>diff --git a/foo b/foo<RESET>
1497 <BOLD>--- a/foo<RESET>
1498 <BOLD>+++ b/foo<RESET>
1499 <CYAN>@@ -1,4 +1 @@<RESET>
1500 <RED>-7charsA<RESET>
1501 irrelevant_line<RESET>
1502 <RED>-7charsB<RESET>
1503 <RED>-7charsC<RESET>
1504 EOF
1505
1506 test_cmp expected actual
1507'
1508
1509test_expect_success 'move detection with submodules' '
1510 test_create_repo bananas &&
1511 echo ripe >bananas/recipe &&
1512 git -C bananas add recipe &&
1513 test_commit fruit &&
1514 test_commit -C bananas recipe &&
1515 git submodule add ./bananas &&
1516 git add bananas &&
1517 git commit -a -m "bananas are like a heavy library?" &&
1518 echo foul >bananas/recipe &&
1519 echo ripe >fruit.t &&
1520
1521 git diff --submodule=diff --color-moved --color >actual &&
1522
1523 # no move detection as the moved line is across repository boundaries.
1524 test_decode_color <actual >decoded_actual &&
1525 ! grep BGREEN decoded_actual &&
1526 ! grep BRED decoded_actual &&
1527
1528 # nor did we mess with it another way
1529 git diff --submodule=diff --color | test_decode_color >expect &&
1530 test_cmp expect decoded_actual
1531'
1532
1533test_expect_success 'move detection with whitespace changes' '
1534 test_when_finished "git reset --hard" &&
1535 test_seq 10 >test &&
1536 git add test &&
1537 sed s/3/42/ <test >test.tmp &&
1538 mv test.tmp test &&
1539 git -c diff.colormoved diff --ignore-space-change -- test
1540'
1541
1542test_done