t / t4015-diff-whitespace.shon commit Merge branch 'jk/diff-algo' into maint (b28325d)
   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
  12# Ray Lehtiniemi's example
  13
  14cat << EOF > x
  15do {
  16   nothing;
  17} while (0);
  18EOF
  19
  20git update-index --add x
  21
  22cat << EOF > x
  23do
  24{
  25   nothing;
  26}
  27while (0);
  28EOF
  29
  30cat << 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
  44
  45git diff > out
  46test_expect_success "Ray's example without options" 'test_cmp expect out'
  47
  48git diff -w > out
  49test_expect_success "Ray's example with -w" 'test_cmp expect out'
  50
  51git diff -b > out
  52test_expect_success "Ray's example with -b" 'test_cmp expect out'
  53
  54tr 'Q' '\015' << EOF > x
  55whitespace at beginning
  56whitespace change
  57whitespace in the middle
  58whitespace at end
  59unchanged line
  60CR at endQ
  61EOF
  62
  63git update-index x
  64
  65tr '_' ' ' << EOF > x
  66        whitespace at beginning
  67whitespace       change
  68white space in the middle
  69whitespace at end__
  70unchanged line
  71CR at end
  72EOF
  73
  74tr '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'
  94
  95cat << 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'
 105
 106tr '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'
 125
 126tr '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'
 144
 145test_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'
 154
 155test_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 \ " >x &&
 159        git diff -w --ignore-blank-lines >out &&
 160        >expect &&
 161        test_cmp out expect
 162'
 163
 164test_expect_success 'ignore-blank-lines: after change' '
 165        cat <<-\EOF >x &&
 166        1
 167        2
 168
 169        3
 170        4
 171        5
 172
 173        6
 174        7
 175        EOF
 176        git update-index x &&
 177        cat <<-\EOF >x &&
 178        change
 179
 180        1
 181        2
 182        3
 183        4
 184        5
 185        6
 186
 187        7
 188        EOF
 189        git diff --inter-hunk-context=100 --ignore-blank-lines >out.tmp &&
 190        cat <<-\EOF >expected &&
 191        diff --git a/x b/x
 192        --- a/x
 193        +++ b/x
 194        @@ -1,6 +1,7 @@
 195        +change
 196        +
 197         1
 198         2
 199        -
 200         3
 201         4
 202         5
 203        EOF
 204        compare_diff_patch expected out.tmp
 205'
 206
 207test_expect_success 'ignore-blank-lines: before change' '
 208        cat <<-\EOF >x &&
 209        1
 210        2
 211
 212        3
 213        4
 214        5
 215        6
 216        7
 217        EOF
 218        git update-index x &&
 219        cat <<-\EOF >x &&
 220
 221        1
 222        2
 223        3
 224        4
 225        5
 226
 227        6
 228        7
 229        change
 230        EOF
 231        git diff --inter-hunk-context=100 --ignore-blank-lines >out.tmp &&
 232        cat <<-\EOF >expected &&
 233        diff --git a/x b/x
 234        --- a/x
 235        +++ b/x
 236        @@ -4,5 +4,7 @@
 237         3
 238         4
 239         5
 240        +
 241         6
 242         7
 243        +change
 244        EOF
 245        compare_diff_patch expected out.tmp
 246'
 247
 248test_expect_success 'ignore-blank-lines: between changes' '
 249        cat <<-\EOF >x &&
 250        1
 251        2
 252        3
 253        4
 254        5
 255
 256
 257        6
 258        7
 259        8
 260        9
 261        10
 262        EOF
 263        git update-index x &&
 264        cat <<-\EOF >x &&
 265        change
 266        1
 267        2
 268
 269        3
 270        4
 271        5
 272        6
 273        7
 274        8
 275
 276        9
 277        10
 278        change
 279        EOF
 280        git diff --ignore-blank-lines >out.tmp &&
 281        cat <<-\EOF >expected &&
 282        diff --git a/x b/x
 283        --- a/x
 284        +++ b/x
 285        @@ -1,5 +1,7 @@
 286        +change
 287         1
 288         2
 289        +
 290         3
 291         4
 292         5
 293        @@ -8,5 +8,7 @@
 294         6
 295         7
 296         8
 297        +
 298         9
 299         10
 300        +change
 301        EOF
 302        compare_diff_patch expected out.tmp
 303'
 304
 305test_expect_success 'ignore-blank-lines: between changes (with interhunkctx)' '
 306        test_seq 10 >x &&
 307        git update-index x &&
 308        cat <<-\EOF >x &&
 309        change
 310        1
 311        2
 312
 313        3
 314        4
 315        5
 316
 317        6
 318        7
 319        8
 320        9
 321
 322        10
 323        change
 324        EOF
 325        git diff --inter-hunk-context=2 --ignore-blank-lines >out.tmp &&
 326        cat <<-\EOF >expected &&
 327        diff --git a/x b/x
 328        --- a/x
 329        +++ b/x
 330        @@ -1,10 +1,15 @@
 331        +change
 332         1
 333         2
 334        +
 335         3
 336         4
 337         5
 338        +
 339         6
 340         7
 341         8
 342         9
 343        +
 344         10
 345        +change
 346        EOF
 347        compare_diff_patch expected out.tmp
 348'
 349
 350test_expect_success 'ignore-blank-lines: scattered spaces' '
 351        test_seq 10 >x &&
 352        git update-index x &&
 353        cat <<-\EOF >x &&
 354        change
 355        1
 356        2
 357        3
 358
 359        4
 360
 361        5
 362
 363        6
 364
 365
 366        7
 367
 368        8
 369        9
 370        10
 371        change
 372        EOF
 373        git diff --inter-hunk-context=4 --ignore-blank-lines >out.tmp &&
 374        cat <<-\EOF >expected &&
 375        diff --git a/x b/x
 376        --- a/x
 377        +++ b/x
 378        @@ -1,3 +1,4 @@
 379        +change
 380         1
 381         2
 382         3
 383        @@ -8,3 +15,4 @@
 384         8
 385         9
 386         10
 387        +change
 388        EOF
 389        compare_diff_patch expected out.tmp
 390'
 391
 392test_expect_success 'ignore-blank-lines: spaces coalesce' '
 393        test_seq 6 >x &&
 394        git update-index x &&
 395        cat <<-\EOF >x &&
 396        change
 397        1
 398        2
 399        3
 400
 401        4
 402
 403        5
 404
 405        6
 406        change
 407        EOF
 408        git diff --inter-hunk-context=4 --ignore-blank-lines >out.tmp &&
 409        cat <<-\EOF >expected &&
 410        diff --git a/x b/x
 411        --- a/x
 412        +++ b/x
 413        @@ -1,6 +1,11 @@
 414        +change
 415         1
 416         2
 417         3
 418        +
 419         4
 420        +
 421         5
 422        +
 423         6
 424        +change
 425        EOF
 426        compare_diff_patch expected out.tmp
 427'
 428
 429test_expect_success 'ignore-blank-lines: mix changes and blank lines' '
 430        test_seq 16 >x &&
 431        git update-index x &&
 432        cat <<-\EOF >x &&
 433        change
 434        1
 435        2
 436
 437        3
 438        4
 439        5
 440        change
 441        6
 442        7
 443        8
 444
 445        9
 446        10
 447        11
 448        change
 449        12
 450        13
 451        14
 452
 453        15
 454        16
 455        change
 456        EOF
 457        git diff --ignore-blank-lines >out.tmp &&
 458        cat <<-\EOF >expected &&
 459        diff --git a/x b/x
 460        --- a/x
 461        +++ b/x
 462        @@ -1,8 +1,11 @@
 463        +change
 464         1
 465         2
 466        +
 467         3
 468         4
 469         5
 470        +change
 471         6
 472         7
 473         8
 474        @@ -9,8 +13,11 @@
 475         9
 476         10
 477         11
 478        +change
 479         12
 480         13
 481         14
 482        +
 483         15
 484         16
 485        +change
 486        EOF
 487        compare_diff_patch expected out.tmp
 488'
 489
 490test_expect_success 'check mixed spaces and tabs in indent' '
 491
 492        # This is indented with SP HT SP.
 493        echo "   foo();" > x &&
 494        git diff --check | grep "space before tab in indent"
 495
 496'
 497
 498test_expect_success 'check mixed tabs and spaces in indent' '
 499
 500        # This is indented with HT SP HT.
 501        echo "          foo();" > x &&
 502        git diff --check | grep "space before tab in indent"
 503
 504'
 505
 506test_expect_success 'check with no whitespace errors' '
 507
 508        git commit -m "snapshot" &&
 509        echo "foo();" > x &&
 510        git diff --check
 511
 512'
 513
 514test_expect_success 'check with trailing whitespace' '
 515
 516        echo "foo(); " > x &&
 517        test_must_fail git diff --check
 518
 519'
 520
 521test_expect_success 'check with space before tab in indent' '
 522
 523        # indent has space followed by hard tab
 524        echo "  foo();" > x &&
 525        test_must_fail git diff --check
 526
 527'
 528
 529test_expect_success '--check and --exit-code are not exclusive' '
 530
 531        git checkout x &&
 532        git diff --check --exit-code
 533
 534'
 535
 536test_expect_success '--check and --quiet are not exclusive' '
 537
 538        git diff --check --quiet
 539
 540'
 541
 542test_expect_success 'check staged with no whitespace errors' '
 543
 544        echo "foo();" > x &&
 545        git add x &&
 546        git diff --cached --check
 547
 548'
 549
 550test_expect_success 'check staged with trailing whitespace' '
 551
 552        echo "foo(); " > x &&
 553        git add x &&
 554        test_must_fail git diff --cached --check
 555
 556'
 557
 558test_expect_success 'check staged with space before tab in indent' '
 559
 560        # indent has space followed by hard tab
 561        echo "  foo();" > x &&
 562        git add x &&
 563        test_must_fail git diff --cached --check
 564
 565'
 566
 567test_expect_success 'check with no whitespace errors (diff-index)' '
 568
 569        echo "foo();" > x &&
 570        git add x &&
 571        git diff-index --check HEAD
 572
 573'
 574
 575test_expect_success 'check with trailing whitespace (diff-index)' '
 576
 577        echo "foo(); " > x &&
 578        git add x &&
 579        test_must_fail git diff-index --check HEAD
 580
 581'
 582
 583test_expect_success 'check with space before tab in indent (diff-index)' '
 584
 585        # indent has space followed by hard tab
 586        echo "  foo();" > x &&
 587        git add x &&
 588        test_must_fail git diff-index --check HEAD
 589
 590'
 591
 592test_expect_success 'check staged with no whitespace errors (diff-index)' '
 593
 594        echo "foo();" > x &&
 595        git add x &&
 596        git diff-index --cached --check HEAD
 597
 598'
 599
 600test_expect_success 'check staged with trailing whitespace (diff-index)' '
 601
 602        echo "foo(); " > x &&
 603        git add x &&
 604        test_must_fail git diff-index --cached --check HEAD
 605
 606'
 607
 608test_expect_success 'check staged with space before tab in indent (diff-index)' '
 609
 610        # indent has space followed by hard tab
 611        echo "  foo();" > x &&
 612        git add x &&
 613        test_must_fail git diff-index --cached --check HEAD
 614
 615'
 616
 617test_expect_success 'check with no whitespace errors (diff-tree)' '
 618
 619        echo "foo();" > x &&
 620        git commit -m "new commit" x &&
 621        git diff-tree --check HEAD^ HEAD
 622
 623'
 624
 625test_expect_success 'check with trailing whitespace (diff-tree)' '
 626
 627        echo "foo(); " > x &&
 628        git commit -m "another commit" x &&
 629        test_must_fail git diff-tree --check HEAD^ HEAD
 630
 631'
 632
 633test_expect_success 'check with space before tab in indent (diff-tree)' '
 634
 635        # indent has space followed by hard tab
 636        echo "  foo();" > x &&
 637        git commit -m "yet another" x &&
 638        test_must_fail git diff-tree --check HEAD^ HEAD
 639
 640'
 641
 642test_expect_success 'check trailing whitespace (trailing-space: off)' '
 643
 644        git config core.whitespace "-trailing-space" &&
 645        echo "foo ();   " > x &&
 646        git diff --check
 647
 648'
 649
 650test_expect_success 'check trailing whitespace (trailing-space: on)' '
 651
 652        git config core.whitespace "trailing-space" &&
 653        echo "foo ();   " > x &&
 654        test_must_fail git diff --check
 655
 656'
 657
 658test_expect_success 'check space before tab in indent (space-before-tab: off)' '
 659
 660        # indent contains space followed by HT
 661        git config core.whitespace "-space-before-tab" &&
 662        echo "  foo ();" > x &&
 663        git diff --check
 664
 665'
 666
 667test_expect_success 'check space before tab in indent (space-before-tab: on)' '
 668
 669        # indent contains space followed by HT
 670        git config core.whitespace "space-before-tab" &&
 671        echo "  foo ();   " > x &&
 672        test_must_fail git diff --check
 673
 674'
 675
 676test_expect_success 'check spaces as indentation (indent-with-non-tab: off)' '
 677
 678        git config core.whitespace "-indent-with-non-tab" &&
 679        echo "        foo ();" > x &&
 680        git diff --check
 681
 682'
 683
 684test_expect_success 'check spaces as indentation (indent-with-non-tab: on)' '
 685
 686        git config core.whitespace "indent-with-non-tab" &&
 687        echo "        foo ();" > x &&
 688        test_must_fail git diff --check
 689
 690'
 691
 692test_expect_success 'ditto, but tabwidth=9' '
 693
 694        git config core.whitespace "indent-with-non-tab,tabwidth=9" &&
 695        git diff --check
 696
 697'
 698
 699test_expect_success 'check tabs and spaces as indentation (indent-with-non-tab: on)' '
 700
 701        git config core.whitespace "indent-with-non-tab" &&
 702        echo "                  foo ();" > x &&
 703        test_must_fail git diff --check
 704
 705'
 706
 707test_expect_success 'ditto, but tabwidth=10' '
 708
 709        git config core.whitespace "indent-with-non-tab,tabwidth=10" &&
 710        test_must_fail git diff --check
 711
 712'
 713
 714test_expect_success 'ditto, but tabwidth=20' '
 715
 716        git config core.whitespace "indent-with-non-tab,tabwidth=20" &&
 717        git diff --check
 718
 719'
 720
 721test_expect_success 'check tabs as indentation (tab-in-indent: off)' '
 722
 723        git config core.whitespace "-tab-in-indent" &&
 724        echo "  foo ();" > x &&
 725        git diff --check
 726
 727'
 728
 729test_expect_success 'check tabs as indentation (tab-in-indent: on)' '
 730
 731        git config core.whitespace "tab-in-indent" &&
 732        echo "  foo ();" > x &&
 733        test_must_fail git diff --check
 734
 735'
 736
 737test_expect_success 'check tabs and spaces as indentation (tab-in-indent: on)' '
 738
 739        git config core.whitespace "tab-in-indent" &&
 740        echo "                  foo ();" > x &&
 741        test_must_fail git diff --check
 742
 743'
 744
 745test_expect_success 'ditto, but tabwidth=1 (must be irrelevant)' '
 746
 747        git config core.whitespace "tab-in-indent,tabwidth=1" &&
 748        test_must_fail git diff --check
 749
 750'
 751
 752test_expect_success 'check tab-in-indent and indent-with-non-tab conflict' '
 753
 754        git config core.whitespace "tab-in-indent,indent-with-non-tab" &&
 755        echo "foo ();" > x &&
 756        test_must_fail git diff --check
 757
 758'
 759
 760test_expect_success 'check tab-in-indent excluded from wildcard whitespace attribute' '
 761
 762        git config --unset core.whitespace &&
 763        echo "x whitespace" > .gitattributes &&
 764        echo "    foo ();" > x &&
 765        git diff --check &&
 766        rm -f .gitattributes
 767
 768'
 769
 770test_expect_success 'line numbers in --check output are correct' '
 771
 772        echo "" > x &&
 773        echo "foo(); " >> x &&
 774        git diff --check | grep "x:2:"
 775
 776'
 777
 778test_expect_success 'checkdiff detects new trailing blank lines (1)' '
 779        echo "foo();" >x &&
 780        echo "" >>x &&
 781        git diff --check | grep "new blank line"
 782'
 783
 784test_expect_success 'checkdiff detects new trailing blank lines (2)' '
 785        { echo a; echo b; echo; echo; } >x &&
 786        git add x &&
 787        { echo a; echo; echo; echo; echo; } >x &&
 788        git diff --check | grep "new blank line"
 789'
 790
 791test_expect_success 'checkdiff allows new blank lines' '
 792        git checkout x &&
 793        mv x y &&
 794        (
 795                echo "/* This is new */" &&
 796                echo "" &&
 797                cat y
 798        ) >x &&
 799        git diff --check
 800'
 801
 802cat <<EOF >expect
 803EOF
 804test_expect_success 'whitespace-only changes not reported' '
 805        git reset --hard &&
 806        echo >x "hello world" &&
 807        git add x &&
 808        git commit -m "hello 1" &&
 809        echo >x "hello  world" &&
 810        git diff -b >actual &&
 811        test_cmp expect actual
 812'
 813
 814cat <<EOF >expect
 815diff --git a/x b/z
 816similarity index NUM%
 817rename from x
 818rename to z
 819index 380c32a..a97b785 100644
 820EOF
 821test_expect_success 'whitespace-only changes reported across renames' '
 822        git reset --hard &&
 823        for i in 1 2 3 4 5 6 7 8 9; do echo "$i$i$i$i$i$i"; done >x &&
 824        git add x &&
 825        git commit -m "base" &&
 826        sed -e "5s/^/ /" x >z &&
 827        git rm x &&
 828        git add z &&
 829        git diff -w -M --cached |
 830        sed -e "/^similarity index /s/[0-9][0-9]*/NUM/" >actual &&
 831        test_cmp expect actual
 832'
 833
 834cat >expected <<\EOF
 835diff --git a/empty b/void
 836similarity index 100%
 837rename from empty
 838rename to void
 839EOF
 840
 841test_expect_success 'rename empty' '
 842        git reset --hard &&
 843        >empty &&
 844        git add empty &&
 845        git commit -m empty &&
 846        git mv empty void &&
 847        git diff -w --cached -M >current &&
 848        test_cmp expected current
 849'
 850
 851test_expect_success 'combined diff with autocrlf conversion' '
 852
 853        git reset --hard &&
 854        echo >x hello &&
 855        git commit -m "one side" x &&
 856        git checkout HEAD^ &&
 857        echo >x goodbye &&
 858        git commit -m "the other side" x &&
 859        git config core.autocrlf true &&
 860        test_must_fail git merge master &&
 861
 862        git diff | sed -e "1,/^@@@/d" >actual &&
 863        ! grep "^-" actual
 864
 865'
 866
 867# Start testing the colored format for whitespace checks
 868
 869test_expect_success 'setup diff colors' '
 870        git config color.diff always &&
 871        git config color.diff.plain normal &&
 872        git config color.diff.meta bold &&
 873        git config color.diff.frag cyan &&
 874        git config color.diff.func normal &&
 875        git config color.diff.old red &&
 876        git config color.diff.new green &&
 877        git config color.diff.commit yellow &&
 878        git config color.diff.whitespace "normal red" &&
 879
 880        git config core.autocrlf false
 881'
 882cat >expected <<\EOF
 883<BOLD>diff --git a/x b/x<RESET>
 884<BOLD>index 9daeafb..2874b91 100644<RESET>
 885<BOLD>--- a/x<RESET>
 886<BOLD>+++ b/x<RESET>
 887<CYAN>@@ -1 +1,4 @@<RESET>
 888 test<RESET>
 889<GREEN>+<RESET><GREEN>{<RESET>
 890<GREEN>+<RESET><BRED>   <RESET>
 891<GREEN>+<RESET><GREEN>}<RESET>
 892EOF
 893
 894test_expect_success 'diff that introduces a line with only tabs' '
 895        git config core.whitespace blank-at-eol &&
 896        git reset --hard &&
 897        echo "test" > x &&
 898        git commit -m "initial" x &&
 899        echo "{NTN}" | tr "NT" "\n\t" >> x &&
 900        git -c color.diff=always diff | test_decode_color >current &&
 901        test_cmp expected current
 902'
 903
 904test_done