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