1#!/bin/sh
   2#
   3# Copyright (c) 2006 Johannes E. Schindelin
   4#
   5test_description='Test special whitespace in diff engine.
   7'
   9. ./test-lib.sh
  10. "$TEST_DIRECTORY"/diff-lib.sh
  11# Ray Lehtiniemi's example
  13cat << EOF > x
  15do {
  16   nothing;
  17} while (0);
  18EOF
  19git update-index --add x
  21cat << EOF > x
  23do
  24{
  25   nothing;
  26}
  27while (0);
  28EOF
  29cat << EOF > expect
  31diff --git a/x b/x
  32index adf3937..6edc172 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);
  43EOF
  44git diff > out
  46test_expect_success "Ray's example without options" 'test_cmp expect out'
  47git diff -w > out
  49test_expect_success "Ray's example with -w" 'test_cmp expect out'
  50git diff -b > out
  52test_expect_success "Ray's example with -b" 'test_cmp expect out'
  53tr 'Q' '\015' << EOF > x
  55whitespace at beginning
  56whitespace change
  57whitespace in the middle
  58whitespace at end
  59unchanged line
  60CR at endQ
  61EOF
  62git update-index x
  64tr '_' ' ' << EOF > x
  66        whitespace at beginning
  67whitespace       change
  68white space in the middle
  69whitespace at end__
  70unchanged line
  71CR at end
  72EOF
  73tr 'Q_' '\015 ' << EOF > expect
  75diff --git a/x b/x
  76index d99af23..8b32fb5 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
  91EOF
  92git diff > out
  93test_expect_success 'another test, without options' 'test_cmp expect out'
  94cat << EOF > expect
  96EOF
  97git diff -w > out
  98test_expect_success 'another test, with -w' 'test_cmp expect out'
  99git diff -w -b > out
 100test_expect_success 'another test, with -w -b' 'test_cmp expect out'
 101git diff -w --ignore-space-at-eol > out
 102test_expect_success 'another test, with -w --ignore-space-at-eol' 'test_cmp expect out'
 103git diff -w -b --ignore-space-at-eol > out
 104test_expect_success 'another test, with -w -b --ignore-space-at-eol' 'test_cmp expect out'
 105tr 'Q_' '\015 ' << EOF > expect
 107diff --git a/x b/x
 108index d99af23..8b32fb5 100644
 109--- a/x
 110+++ b/x
 111@@ -1,6 +1,6 @@
 112-whitespace at beginning
 113+       whitespace at beginning
 114 whitespace      change
 115-whitespace in the middle
 116+white space in the middle
 117 whitespace at end__
 118 unchanged line
 119 CR at end
 120EOF
 121git diff -b > out
 122test_expect_success 'another test, with -b' 'test_cmp expect out'
 123git diff -b --ignore-space-at-eol > out
 124test_expect_success 'another test, with -b --ignore-space-at-eol' 'test_cmp expect out'
 125tr 'Q_' '\015 ' << EOF > expect
 127diff --git a/x b/x
 128index d99af23..8b32fb5 100644
 129--- a/x
 130+++ b/x
 131@@ -1,6 +1,6 @@
 132-whitespace at beginning
 133-whitespace change
 134-whitespace in the middle
 135+       whitespace at beginning
 136+whitespace      change
 137+white space in the middle
 138 whitespace at end__
 139 unchanged line
 140 CR at end
 141EOF
 142git diff --ignore-space-at-eol > out
 143test_expect_success 'another test, with --ignore-space-at-eol' 'test_cmp expect out'
 144test_expect_success 'ignore-blank-lines: only new lines' '
 146        test_seq 5 >x &&
 147        git update-index x &&
 148        test_seq 5 | sed "/3/i\\
 149" >x &&
 150        git diff --ignore-blank-lines >out &&
 151        >expect &&
 152        test_cmp out expect
 153'
 154test_expect_success 'ignore-blank-lines: only new lines with space' '
 156        test_seq 5 >x &&
 157        git update-index x &&
 158        test_seq 5 | sed "/3/i\\
 159 " >x &&
 160        git diff -w --ignore-blank-lines >out &&
 161        >expect &&
 162        test_cmp out expect
 163'
 164test_expect_success 'ignore-blank-lines: after change' '
 166        cat <<-\EOF >x &&
 167        1
 168        2
 169        3
 171        4
 172        5
 173        6
 175        7
 176        EOF
 177        git update-index x &&
 178        cat <<-\EOF >x &&
 179        change
 180        1
 182        2
 183        3
 184        4
 185        5
 186        6
 187        7
 189        EOF
 190        git diff --inter-hunk-context=100 --ignore-blank-lines >out.tmp &&
 191        cat <<-\EOF >expected &&
 192        diff --git a/x b/x
 193        --- a/x
 194        +++ b/x
 195        @@ -1,6 +1,7 @@
 196        +change
 197        +
 198         1
 199         2
 200        -
 201         3
 202         4
 203         5
 204        EOF
 205        compare_diff_patch expected out.tmp
 206'
 207test_expect_success 'ignore-blank-lines: before change' '
 209        cat <<-\EOF >x &&
 210        1
 211        2
 212        3
 214        4
 215        5
 216        6
 217        7
 218        EOF
 219        git update-index x &&
 220        cat <<-\EOF >x &&
 221        1
 223        2
 224        3
 225        4
 226        5
 227        6
 229        7
 230        change
 231        EOF
 232        git diff --inter-hunk-context=100 --ignore-blank-lines >out.tmp &&
 233        cat <<-\EOF >expected &&
 234        diff --git a/x b/x
 235        --- a/x
 236        +++ b/x
 237        @@ -4,5 +4,7 @@
 238         3
 239         4
 240         5
 241        +
 242         6
 243         7
 244        +change
 245        EOF
 246        compare_diff_patch expected out.tmp
 247'
 248test_expect_success 'ignore-blank-lines: between changes' '
 250        cat <<-\EOF >x &&
 251        1
 252        2
 253        3
 254        4
 255        5
 256        6
 259        7
 260        8
 261        9
 262        10
 263        EOF
 264        git update-index x &&
 265        cat <<-\EOF >x &&
 266        change
 267        1
 268        2
 269        3
 271        4
 272        5
 273        6
 274        7
 275        8
 276        9
 278        10
 279        change
 280        EOF
 281        git diff --ignore-blank-lines >out.tmp &&
 282        cat <<-\EOF >expected &&
 283        diff --git a/x b/x
 284        --- a/x
 285        +++ b/x
 286        @@ -1,5 +1,7 @@
 287        +change
 288         1
 289         2
 290        +
 291         3
 292         4
 293         5
 294        @@ -8,5 +8,7 @@
 295         6
 296         7
 297         8
 298        +
 299         9
 300         10
 301        +change
 302        EOF
 303        compare_diff_patch expected out.tmp
 304'
 305test_expect_success 'ignore-blank-lines: between changes (with interhunkctx)' '
 307        test_seq 10 >x &&
 308        git update-index x &&
 309        cat <<-\EOF >x &&
 310        change
 311        1
 312        2
 313        3
 315        4
 316        5
 317        6
 319        7
 320        8
 321        9
 322        10
 324        change
 325        EOF
 326        git diff --inter-hunk-context=2 --ignore-blank-lines >out.tmp &&
 327        cat <<-\EOF >expected &&
 328        diff --git a/x b/x
 329        --- a/x
 330        +++ b/x
 331        @@ -1,10 +1,15 @@
 332        +change
 333         1
 334         2
 335        +
 336         3
 337         4
 338         5
 339        +
 340         6
 341         7
 342         8
 343         9
 344        +
 345         10
 346        +change
 347        EOF
 348        compare_diff_patch expected out.tmp
 349'
 350test_expect_success 'ignore-blank-lines: scattered spaces' '
 352        test_seq 10 >x &&
 353        git update-index x &&
 354        cat <<-\EOF >x &&
 355        change
 356        1
 357        2
 358        3
 359        4
 361        5
 363        6
 365        7
 368        8
 370        9
 371        10
 372        change
 373        EOF
 374        git diff --inter-hunk-context=4 --ignore-blank-lines >out.tmp &&
 375        cat <<-\EOF >expected &&
 376        diff --git a/x b/x
 377        --- a/x
 378        +++ b/x
 379        @@ -1,3 +1,4 @@
 380        +change
 381         1
 382         2
 383         3
 384        @@ -8,3 +15,4 @@
 385         8
 386         9
 387         10
 388        +change
 389        EOF
 390        compare_diff_patch expected out.tmp
 391'
 392test_expect_success 'ignore-blank-lines: spaces coalesce' '
 394        test_seq 6 >x &&
 395        git update-index x &&
 396        cat <<-\EOF >x &&
 397        change
 398        1
 399        2
 400        3
 401        4
 403        5
 405        6
 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,6 +1,11 @@
 415        +change
 416         1
 417         2
 418         3
 419        +
 420         4
 421        +
 422         5
 423        +
 424         6
 425        +change
 426        EOF
 427        compare_diff_patch expected out.tmp
 428'
 429test_expect_success 'ignore-blank-lines: mix changes and blank lines' '
 431        test_seq 16 >x &&
 432        git update-index x &&
 433        cat <<-\EOF >x &&
 434        change
 435        1
 436        2
 437        3
 439        4
 440        5
 441        change
 442        6
 443        7
 444        8
 445        9
 447        10
 448        11
 449        change
 450        12
 451        13
 452        14
 453        15
 455        16
 456        change
 457        EOF
 458        git diff --ignore-blank-lines >out.tmp &&
 459        cat <<-\EOF >expected &&
 460        diff --git a/x b/x
 461        --- a/x
 462        +++ b/x
 463        @@ -1,8 +1,11 @@
 464        +change
 465         1
 466         2
 467        +
 468         3
 469         4
 470         5
 471        +change
 472         6
 473         7
 474         8
 475        @@ -9,8 +13,11 @@
 476         9
 477         10
 478         11
 479        +change
 480         12
 481         13
 482         14
 483        +
 484         15
 485         16
 486        +change
 487        EOF
 488        compare_diff_patch expected out.tmp
 489'
 490test_expect_success 'check mixed spaces and tabs in indent' '
 492        # This is indented with SP HT SP.
 494        echo "   foo();" > x &&
 495        git diff --check | grep "space before tab in indent"
 496'
 498test_expect_success 'check mixed tabs and spaces in indent' '
 500        # This is indented with HT SP HT.
 502        echo "          foo();" > x &&
 503        git diff --check | grep "space before tab in indent"
 504'
 506test_expect_success 'check with no whitespace errors' '
 508        git commit -m "snapshot" &&
 510        echo "foo();" > x &&
 511        git diff --check
 512'
 514test_expect_success 'check with trailing whitespace' '
 516        echo "foo(); " > x &&
 518        test_must_fail git diff --check
 519'
 521test_expect_success 'check with space before tab in indent' '
 523        # indent has space followed by hard tab
 525        echo "  foo();" > x &&
 526        test_must_fail git diff --check
 527'
 529test_expect_success '--check and --exit-code are not exclusive' '
 531        git checkout x &&
 533        git diff --check --exit-code
 534'
 536test_expect_success '--check and --quiet are not exclusive' '
 538        git diff --check --quiet
 540'
 542test_expect_success 'check staged with no whitespace errors' '
 544        echo "foo();" > x &&
 546        git add x &&
 547        git diff --cached --check
 548'
 550test_expect_success 'check staged with trailing whitespace' '
 552        echo "foo(); " > x &&
 554        git add x &&
 555        test_must_fail git diff --cached --check
 556'
 558test_expect_success 'check staged with space before tab in indent' '
 560        # indent has space followed by hard tab
 562        echo "  foo();" > x &&
 563        git add x &&
 564        test_must_fail git diff --cached --check
 565'
 567test_expect_success 'check with no whitespace errors (diff-index)' '
 569        echo "foo();" > x &&
 571        git add x &&
 572        git diff-index --check HEAD
 573'
 575test_expect_success 'check with trailing whitespace (diff-index)' '
 577        echo "foo(); " > x &&
 579        git add x &&
 580        test_must_fail git diff-index --check HEAD
 581'
 583test_expect_success 'check with space before tab in indent (diff-index)' '
 585        # indent has space followed by hard tab
 587        echo "  foo();" > x &&
 588        git add x &&
 589        test_must_fail git diff-index --check HEAD
 590'
 592test_expect_success 'check staged with no whitespace errors (diff-index)' '
 594        echo "foo();" > x &&
 596        git add x &&
 597        git diff-index --cached --check HEAD
 598'
 600test_expect_success 'check staged with trailing whitespace (diff-index)' '
 602        echo "foo(); " > x &&
 604        git add x &&
 605        test_must_fail git diff-index --cached --check HEAD
 606'
 608test_expect_success 'check staged with space before tab in indent (diff-index)' '
 610        # indent has space followed by hard tab
 612        echo "  foo();" > x &&
 613        git add x &&
 614        test_must_fail git diff-index --cached --check HEAD
 615'
 617test_expect_success 'check with no whitespace errors (diff-tree)' '
 619        echo "foo();" > x &&
 621        git commit -m "new commit" x &&
 622        git diff-tree --check HEAD^ HEAD
 623'
 625test_expect_success 'check with trailing whitespace (diff-tree)' '
 627        echo "foo(); " > x &&
 629        git commit -m "another commit" x &&
 630        test_must_fail git diff-tree --check HEAD^ HEAD
 631'
 633test_expect_success 'check with space before tab in indent (diff-tree)' '
 635        # indent has space followed by hard tab
 637        echo "  foo();" > x &&
 638        git commit -m "yet another" x &&
 639        test_must_fail git diff-tree --check HEAD^ HEAD
 640'
 642test_expect_success 'check trailing whitespace (trailing-space: off)' '
 644        git config core.whitespace "-trailing-space" &&
 646        echo "foo ();   " > x &&
 647        git diff --check
 648'
 650test_expect_success 'check trailing whitespace (trailing-space: on)' '
 652        git config core.whitespace "trailing-space" &&
 654        echo "foo ();   " > x &&
 655        test_must_fail git diff --check
 656'
 658test_expect_success 'check space before tab in indent (space-before-tab: off)' '
 660        # indent contains space followed by HT
 662        git config core.whitespace "-space-before-tab" &&
 663        echo "  foo ();" > x &&
 664        git diff --check
 665'
 667test_expect_success 'check space before tab in indent (space-before-tab: on)' '
 669        # indent contains space followed by HT
 671        git config core.whitespace "space-before-tab" &&
 672        echo "  foo ();   " > x &&
 673        test_must_fail git diff --check
 674'
 676test_expect_success 'check spaces as indentation (indent-with-non-tab: off)' '
 678        git config core.whitespace "-indent-with-non-tab" &&
 680        echo "        foo ();" > x &&
 681        git diff --check
 682'
 684test_expect_success 'check spaces as indentation (indent-with-non-tab: on)' '
 686        git config core.whitespace "indent-with-non-tab" &&
 688        echo "        foo ();" > x &&
 689        test_must_fail git diff --check
 690'
 692test_expect_success 'ditto, but tabwidth=9' '
 694        git config core.whitespace "indent-with-non-tab,tabwidth=9" &&
 696        git diff --check
 697'
 699test_expect_success 'check tabs and spaces as indentation (indent-with-non-tab: on)' '
 701        git config core.whitespace "indent-with-non-tab" &&
 703        echo "                  foo ();" > x &&
 704        test_must_fail git diff --check
 705'
 707test_expect_success 'ditto, but tabwidth=10' '
 709        git config core.whitespace "indent-with-non-tab,tabwidth=10" &&
 711        test_must_fail git diff --check
 712'
 714test_expect_success 'ditto, but tabwidth=20' '
 716        git config core.whitespace "indent-with-non-tab,tabwidth=20" &&
 718        git diff --check
 719'
 721test_expect_success 'check tabs as indentation (tab-in-indent: off)' '
 723        git config core.whitespace "-tab-in-indent" &&
 725        echo "  foo ();" > x &&
 726        git diff --check
 727'
 729test_expect_success 'check tabs as indentation (tab-in-indent: on)' '
 731        git config core.whitespace "tab-in-indent" &&
 733        echo "  foo ();" > x &&
 734        test_must_fail git diff --check
 735'
 737test_expect_success 'check tabs and spaces as indentation (tab-in-indent: on)' '
 739        git config core.whitespace "tab-in-indent" &&
 741        echo "                  foo ();" > x &&
 742        test_must_fail git diff --check
 743'
 745test_expect_success 'ditto, but tabwidth=1 (must be irrelevant)' '
 747        git config core.whitespace "tab-in-indent,tabwidth=1" &&
 749        test_must_fail git diff --check
 750'
 752test_expect_success 'check tab-in-indent and indent-with-non-tab conflict' '
 754        git config core.whitespace "tab-in-indent,indent-with-non-tab" &&
 756        echo "foo ();" > x &&
 757        test_must_fail git diff --check
 758'
 760test_expect_success 'check tab-in-indent excluded from wildcard whitespace attribute' '
 762        git config --unset core.whitespace &&
 764        echo "x whitespace" > .gitattributes &&
 765        echo "    foo ();" > x &&
 766        git diff --check &&
 767        rm -f .gitattributes
 768'
 770test_expect_success 'line numbers in --check output are correct' '
 772        echo "" > x &&
 774        echo "foo(); " >> x &&
 775        git diff --check | grep "x:2:"
 776'
 778test_expect_success 'checkdiff detects new trailing blank lines (1)' '
 780        echo "foo();" >x &&
 781        echo "" >>x &&
 782        git diff --check | grep "new blank line"
 783'
 784test_expect_success 'checkdiff detects new trailing blank lines (2)' '
 786        { echo a; echo b; echo; echo; } >x &&
 787        git add x &&
 788        { echo a; echo; echo; echo; echo; } >x &&
 789        git diff --check | grep "new blank line"
 790'
 791test_expect_success 'checkdiff allows new blank lines' '
 793        git checkout x &&
 794        mv x y &&
 795        (
 796                echo "/* This is new */" &&
 797                echo "" &&
 798                cat y
 799        ) >x &&
 800        git diff --check
 801'
 802cat <<EOF >expect
 804EOF
 805test_expect_success 'whitespace-only changes not reported' '
 806        git reset --hard &&
 807        echo >x "hello world" &&
 808        git add x &&
 809        git commit -m "hello 1" &&
 810        echo >x "hello  world" &&
 811        git diff -b >actual &&
 812        test_cmp expect actual
 813'
 814cat <<EOF >expect
 816diff --git a/x b/z
 817similarity index NUM%
 818rename from x
 819rename to z
 820index 380c32a..a97b785 100644
 821EOF
 822test_expect_success 'whitespace-only changes reported across renames' '
 823        git reset --hard &&
 824        for i in 1 2 3 4 5 6 7 8 9; do echo "$i$i$i$i$i$i"; done >x &&
 825        git add x &&
 826        git commit -m "base" &&
 827        sed -e "5s/^/ /" x >z &&
 828        git rm x &&
 829        git add z &&
 830        git diff -w -M --cached |
 831        sed -e "/^similarity index /s/[0-9][0-9]*/NUM/" >actual &&
 832        test_cmp expect actual
 833'
 834cat >expected <<\EOF
 836diff --git a/empty b/void
 837similarity index 100%
 838rename from empty
 839rename to void
 840EOF
 841test_expect_success 'rename empty' '
 843        git reset --hard &&
 844        >empty &&
 845        git add empty &&
 846        git commit -m empty &&
 847        git mv empty void &&
 848        git diff -w --cached -M >current &&
 849        test_cmp expected current
 850'
 851test_expect_success 'combined diff with autocrlf conversion' '
 853        git reset --hard &&
 855        echo >x hello &&
 856        git commit -m "one side" x &&
 857        git checkout HEAD^ &&
 858        echo >x goodbye &&
 859        git commit -m "the other side" x &&
 860        git config core.autocrlf true &&
 861        test_must_fail git merge master &&
 862        git diff | sed -e "1,/^@@@/d" >actual &&
 864        ! grep "^-" actual
 865'
 867# Start testing the colored format for whitespace checks
 869test_expect_success 'setup diff colors' '
 871        git config color.diff always &&
 872        git config color.diff.plain normal &&
 873        git config color.diff.meta bold &&
 874        git config color.diff.frag cyan &&
 875        git config color.diff.func normal &&
 876        git config color.diff.old red &&
 877        git config color.diff.new green &&
 878        git config color.diff.commit yellow &&
 879        git config color.diff.whitespace "normal red" &&
 880        git config core.autocrlf false
 882'
 883cat >expected <<\EOF
 884<BOLD>diff --git a/x b/x<RESET>
 885<BOLD>index 9daeafb..2874b91 100644<RESET>
 886<BOLD>--- a/x<RESET>
 887<BOLD>+++ b/x<RESET>
 888<CYAN>@@ -1 +1,4 @@<RESET>
 889 test<RESET>
 890<GREEN>+<RESET><GREEN>{<RESET>
 891<GREEN>+<RESET><BRED>   <RESET>
 892<GREEN>+<RESET><GREEN>}<RESET>
 893EOF
 894test_expect_success 'diff that introduces a line with only tabs' '
 896        git config core.whitespace blank-at-eol &&
 897        git reset --hard &&
 898        echo "test" > x &&
 899        git commit -m "initial" x &&
 900        echo "{NTN}" | tr "NT" "\n\t" >> x &&
 901        git -c color.diff=always diff | test_decode_color >current &&
 902        test_cmp expected current
 903'
 904test_done