t / t4015-diff-whitespace.shon commit Merge branch 'sb/pull-rebase-submodule' (ce9c6a3)
   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
 779cat <<EOF >expect
 780EOF
 781test_expect_success 'whitespace-only changes not reported' '
 782        git reset --hard &&
 783        echo >x "hello world" &&
 784        git add x &&
 785        git commit -m "hello 1" &&
 786        echo >x "hello  world" &&
 787        git diff -b >actual &&
 788        test_cmp expect actual
 789'
 790
 791cat <<EOF >expect
 792diff --git a/x b/z
 793similarity index NUM%
 794rename from x
 795rename to z
 796index 380c32a..a97b785 100644
 797EOF
 798test_expect_success 'whitespace-only changes reported across renames' '
 799        git reset --hard &&
 800        for i in 1 2 3 4 5 6 7 8 9; do echo "$i$i$i$i$i$i"; done >x &&
 801        git add x &&
 802        git commit -m "base" &&
 803        sed -e "5s/^/ /" x >z &&
 804        git rm x &&
 805        git add z &&
 806        git diff -w -M --cached |
 807        sed -e "/^similarity index /s/[0-9][0-9]*/NUM/" >actual &&
 808        test_cmp expect actual
 809'
 810
 811cat >expected <<\EOF
 812diff --git a/empty b/void
 813similarity index 100%
 814rename from empty
 815rename to void
 816EOF
 817
 818test_expect_success 'rename empty' '
 819        git reset --hard &&
 820        >empty &&
 821        git add empty &&
 822        git commit -m empty &&
 823        git mv empty void &&
 824        git diff -w --cached -M >current &&
 825        test_cmp expected current
 826'
 827
 828test_expect_success 'combined diff with autocrlf conversion' '
 829
 830        git reset --hard &&
 831        echo >x hello &&
 832        git commit -m "one side" x &&
 833        git checkout HEAD^ &&
 834        echo >x goodbye &&
 835        git commit -m "the other side" x &&
 836        git config core.autocrlf true &&
 837        test_must_fail git merge master &&
 838
 839        git diff | sed -e "1,/^@@@/d" >actual &&
 840        ! grep "^-" actual
 841
 842'
 843
 844# Start testing the colored format for whitespace checks
 845
 846test_expect_success 'setup diff colors' '
 847        git config color.diff.plain normal &&
 848        git config color.diff.meta bold &&
 849        git config color.diff.frag cyan &&
 850        git config color.diff.func normal &&
 851        git config color.diff.old red &&
 852        git config color.diff.new green &&
 853        git config color.diff.commit yellow &&
 854        git config color.diff.whitespace blue &&
 855
 856        git config core.autocrlf false
 857'
 858
 859test_expect_success 'diff that introduces a line with only tabs' '
 860        git config core.whitespace blank-at-eol &&
 861        git reset --hard &&
 862        echo "test" >x &&
 863        git commit -m "initial" x &&
 864        echo "{NTN}" | tr "NT" "\n\t" >>x &&
 865        git diff --color | test_decode_color >current &&
 866
 867        cat >expected <<-\EOF &&
 868        <BOLD>diff --git a/x b/x<RESET>
 869        <BOLD>index 9daeafb..2874b91 100644<RESET>
 870        <BOLD>--- a/x<RESET>
 871        <BOLD>+++ b/x<RESET>
 872        <CYAN>@@ -1 +1,4 @@<RESET>
 873         test<RESET>
 874        <GREEN>+<RESET><GREEN>{<RESET>
 875        <GREEN>+<RESET><BLUE>   <RESET>
 876        <GREEN>+<RESET><GREEN>}<RESET>
 877        EOF
 878
 879        test_cmp expected current
 880'
 881
 882test_expect_success 'diff that introduces and removes ws breakages' '
 883        git reset --hard &&
 884        {
 885                echo "0. blank-at-eol " &&
 886                echo "1. blank-at-eol "
 887        } >x &&
 888        git commit -a --allow-empty -m preimage &&
 889        {
 890                echo "0. blank-at-eol " &&
 891                echo "1. still-blank-at-eol " &&
 892                echo "2. and a new line "
 893        } >x &&
 894
 895        git diff --color |
 896        test_decode_color >current &&
 897
 898        cat >expected <<-\EOF &&
 899        <BOLD>diff --git a/x b/x<RESET>
 900        <BOLD>index d0233a2..700886e 100644<RESET>
 901        <BOLD>--- a/x<RESET>
 902        <BOLD>+++ b/x<RESET>
 903        <CYAN>@@ -1,2 +1,3 @@<RESET>
 904         0. blank-at-eol <RESET>
 905        <RED>-1. blank-at-eol <RESET>
 906        <GREEN>+<RESET><GREEN>1. still-blank-at-eol<RESET><BLUE> <RESET>
 907        <GREEN>+<RESET><GREEN>2. and a new line<RESET><BLUE> <RESET>
 908        EOF
 909
 910        test_cmp expected current
 911'
 912
 913test_expect_success 'ws-error-highlight test setup' '
 914
 915        git reset --hard &&
 916        {
 917                echo "0. blank-at-eol " &&
 918                echo "1. blank-at-eol "
 919        } >x &&
 920        git commit -a --allow-empty -m preimage &&
 921        {
 922                echo "0. blank-at-eol " &&
 923                echo "1. still-blank-at-eol " &&
 924                echo "2. and a new line "
 925        } >x &&
 926
 927        cat >expect.default-old <<-\EOF &&
 928        <BOLD>diff --git a/x b/x<RESET>
 929        <BOLD>index d0233a2..700886e 100644<RESET>
 930        <BOLD>--- a/x<RESET>
 931        <BOLD>+++ b/x<RESET>
 932        <CYAN>@@ -1,2 +1,3 @@<RESET>
 933         0. blank-at-eol <RESET>
 934        <RED>-<RESET><RED>1. blank-at-eol<RESET><BLUE> <RESET>
 935        <GREEN>+<RESET><GREEN>1. still-blank-at-eol<RESET><BLUE> <RESET>
 936        <GREEN>+<RESET><GREEN>2. and a new line<RESET><BLUE> <RESET>
 937        EOF
 938
 939        cat >expect.all <<-\EOF &&
 940        <BOLD>diff --git a/x b/x<RESET>
 941        <BOLD>index d0233a2..700886e 100644<RESET>
 942        <BOLD>--- a/x<RESET>
 943        <BOLD>+++ b/x<RESET>
 944        <CYAN>@@ -1,2 +1,3 @@<RESET>
 945         <RESET>0. blank-at-eol<RESET><BLUE> <RESET>
 946        <RED>-<RESET><RED>1. blank-at-eol<RESET><BLUE> <RESET>
 947        <GREEN>+<RESET><GREEN>1. still-blank-at-eol<RESET><BLUE> <RESET>
 948        <GREEN>+<RESET><GREEN>2. and a new line<RESET><BLUE> <RESET>
 949        EOF
 950
 951        cat >expect.none <<-\EOF
 952        <BOLD>diff --git a/x b/x<RESET>
 953        <BOLD>index d0233a2..700886e 100644<RESET>
 954        <BOLD>--- a/x<RESET>
 955        <BOLD>+++ b/x<RESET>
 956        <CYAN>@@ -1,2 +1,3 @@<RESET>
 957         0. blank-at-eol <RESET>
 958        <RED>-1. blank-at-eol <RESET>
 959        <GREEN>+1. still-blank-at-eol <RESET>
 960        <GREEN>+2. and a new line <RESET>
 961        EOF
 962
 963'
 964
 965test_expect_success 'test --ws-error-highlight option' '
 966
 967        git diff --color --ws-error-highlight=default,old |
 968        test_decode_color >current &&
 969        test_cmp expect.default-old current &&
 970
 971        git diff --color --ws-error-highlight=all |
 972        test_decode_color >current &&
 973        test_cmp expect.all current &&
 974
 975        git diff --color --ws-error-highlight=none |
 976        test_decode_color >current &&
 977        test_cmp expect.none current
 978
 979'
 980
 981test_expect_success 'test diff.wsErrorHighlight config' '
 982
 983        git -c diff.wsErrorHighlight=default,old diff --color |
 984        test_decode_color >current &&
 985        test_cmp expect.default-old current &&
 986
 987        git -c diff.wsErrorHighlight=all diff --color |
 988        test_decode_color >current &&
 989        test_cmp expect.all current &&
 990
 991        git -c diff.wsErrorHighlight=none diff --color |
 992        test_decode_color >current &&
 993        test_cmp expect.none current
 994
 995'
 996
 997test_expect_success 'option overrides diff.wsErrorHighlight' '
 998
 999        git -c diff.wsErrorHighlight=none \
1000                diff --color --ws-error-highlight=default,old |
1001        test_decode_color >current &&
1002        test_cmp expect.default-old current &&
1003
1004        git -c diff.wsErrorHighlight=default \
1005                diff --color --ws-error-highlight=all |
1006        test_decode_color >current &&
1007        test_cmp expect.all current &&
1008
1009        git -c diff.wsErrorHighlight=all \
1010                diff --color --ws-error-highlight=none |
1011        test_decode_color >current &&
1012        test_cmp expect.none current
1013
1014'
1015
1016test_expect_success 'detect moved code, complete file' '
1017        git reset --hard &&
1018        cat <<-\EOF >test.c &&
1019        #include<stdio.h>
1020        main()
1021        {
1022        printf("Hello World");
1023        }
1024        EOF
1025        git add test.c &&
1026        git commit -m "add main function" &&
1027        git mv test.c main.c &&
1028        test_config color.diff.oldMoved "normal red" &&
1029        test_config color.diff.newMoved "normal green" &&
1030        git diff HEAD --color-moved=zebra --color --no-renames | test_decode_color >actual &&
1031        cat >expected <<-\EOF &&
1032        <BOLD>diff --git a/main.c b/main.c<RESET>
1033        <BOLD>new file mode 100644<RESET>
1034        <BOLD>index 0000000..a986c57<RESET>
1035        <BOLD>--- /dev/null<RESET>
1036        <BOLD>+++ b/main.c<RESET>
1037        <CYAN>@@ -0,0 +1,5 @@<RESET>
1038        <BGREEN>+<RESET><BGREEN>#include<stdio.h><RESET>
1039        <BGREEN>+<RESET><BGREEN>main()<RESET>
1040        <BGREEN>+<RESET><BGREEN>{<RESET>
1041        <BGREEN>+<RESET><BGREEN>printf("Hello World");<RESET>
1042        <BGREEN>+<RESET><BGREEN>}<RESET>
1043        <BOLD>diff --git a/test.c b/test.c<RESET>
1044        <BOLD>deleted file mode 100644<RESET>
1045        <BOLD>index a986c57..0000000<RESET>
1046        <BOLD>--- a/test.c<RESET>
1047        <BOLD>+++ /dev/null<RESET>
1048        <CYAN>@@ -1,5 +0,0 @@<RESET>
1049        <BRED>-#include<stdio.h><RESET>
1050        <BRED>-main()<RESET>
1051        <BRED>-{<RESET>
1052        <BRED>-printf("Hello World");<RESET>
1053        <BRED>-}<RESET>
1054        EOF
1055
1056        test_cmp expected actual
1057'
1058
1059test_expect_success 'detect malicious moved code, inside file' '
1060        test_config color.diff.oldMoved "normal red" &&
1061        test_config color.diff.newMoved "normal green" &&
1062        test_config color.diff.oldMovedAlternative "blue" &&
1063        test_config color.diff.newMovedAlternative "yellow" &&
1064        git reset --hard &&
1065        cat <<-\EOF >main.c &&
1066                #include<stdio.h>
1067                int stuff()
1068                {
1069                        printf("Hello ");
1070                        printf("World\n");
1071                }
1072
1073                int secure_foo(struct user *u)
1074                {
1075                        if (!u->is_allowed_foo)
1076                                return;
1077                        foo(u);
1078                }
1079
1080                int main()
1081                {
1082                        foo();
1083                }
1084        EOF
1085        cat <<-\EOF >test.c &&
1086                #include<stdio.h>
1087                int bar()
1088                {
1089                        printf("Hello World, but different\n");
1090                }
1091
1092                int another_function()
1093                {
1094                        bar();
1095                }
1096        EOF
1097        git add main.c test.c &&
1098        git commit -m "add main and test file" &&
1099        cat <<-\EOF >main.c &&
1100                #include<stdio.h>
1101                int stuff()
1102                {
1103                        printf("Hello ");
1104                        printf("World\n");
1105                }
1106
1107                int main()
1108                {
1109                        foo();
1110                }
1111        EOF
1112        cat <<-\EOF >test.c &&
1113                #include<stdio.h>
1114                int bar()
1115                {
1116                        printf("Hello World, but different\n");
1117                }
1118
1119                int secure_foo(struct user *u)
1120                {
1121                        foo(u);
1122                        if (!u->is_allowed_foo)
1123                                return;
1124                }
1125
1126                int another_function()
1127                {
1128                        bar();
1129                }
1130        EOF
1131        git diff HEAD --no-renames --color-moved=zebra --color | test_decode_color >actual &&
1132        cat <<-\EOF >expected &&
1133        <BOLD>diff --git a/main.c b/main.c<RESET>
1134        <BOLD>index 27a619c..7cf9336 100644<RESET>
1135        <BOLD>--- a/main.c<RESET>
1136        <BOLD>+++ b/main.c<RESET>
1137        <CYAN>@@ -5,13 +5,6 @@<RESET> <RESET>printf("Hello ");<RESET>
1138         printf("World\n");<RESET>
1139         }<RESET>
1140         <RESET>
1141        <BRED>-int secure_foo(struct user *u)<RESET>
1142        <BRED>-{<RESET>
1143        <BLUE>-if (!u->is_allowed_foo)<RESET>
1144        <BLUE>-return;<RESET>
1145        <RED>-foo(u);<RESET>
1146        <RED>-}<RESET>
1147        <RED>-<RESET>
1148         int main()<RESET>
1149         {<RESET>
1150         foo();<RESET>
1151        <BOLD>diff --git a/test.c b/test.c<RESET>
1152        <BOLD>index 1dc1d85..2bedec9 100644<RESET>
1153        <BOLD>--- a/test.c<RESET>
1154        <BOLD>+++ b/test.c<RESET>
1155        <CYAN>@@ -4,6 +4,13 @@<RESET> <RESET>int bar()<RESET>
1156         printf("Hello World, but different\n");<RESET>
1157         }<RESET>
1158         <RESET>
1159        <BGREEN>+<RESET><BGREEN>int secure_foo(struct user *u)<RESET>
1160        <BGREEN>+<RESET><BGREEN>{<RESET>
1161        <GREEN>+<RESET><GREEN>foo(u);<RESET>
1162        <BGREEN>+<RESET><BGREEN>if (!u->is_allowed_foo)<RESET>
1163        <BGREEN>+<RESET><BGREEN>return;<RESET>
1164        <GREEN>+<RESET><GREEN>}<RESET>
1165        <GREEN>+<RESET>
1166         int another_function()<RESET>
1167         {<RESET>
1168         bar();<RESET>
1169        EOF
1170
1171        test_cmp expected actual
1172'
1173
1174test_expect_success 'plain moved code, inside file' '
1175        test_config color.diff.oldMoved "normal red" &&
1176        test_config color.diff.newMoved "normal green" &&
1177        test_config color.diff.oldMovedAlternative "blue" &&
1178        test_config color.diff.newMovedAlternative "yellow" &&
1179        # needs previous test as setup
1180        git diff HEAD --no-renames --color-moved=plain --color | test_decode_color >actual &&
1181        cat <<-\EOF >expected &&
1182        <BOLD>diff --git a/main.c b/main.c<RESET>
1183        <BOLD>index 27a619c..7cf9336 100644<RESET>
1184        <BOLD>--- a/main.c<RESET>
1185        <BOLD>+++ b/main.c<RESET>
1186        <CYAN>@@ -5,13 +5,6 @@<RESET> <RESET>printf("Hello ");<RESET>
1187         printf("World\n");<RESET>
1188         }<RESET>
1189         <RESET>
1190        <BRED>-int secure_foo(struct user *u)<RESET>
1191        <BRED>-{<RESET>
1192        <BRED>-if (!u->is_allowed_foo)<RESET>
1193        <BRED>-return;<RESET>
1194        <BRED>-foo(u);<RESET>
1195        <BRED>-}<RESET>
1196        <BRED>-<RESET>
1197         int main()<RESET>
1198         {<RESET>
1199         foo();<RESET>
1200        <BOLD>diff --git a/test.c b/test.c<RESET>
1201        <BOLD>index 1dc1d85..2bedec9 100644<RESET>
1202        <BOLD>--- a/test.c<RESET>
1203        <BOLD>+++ b/test.c<RESET>
1204        <CYAN>@@ -4,6 +4,13 @@<RESET> <RESET>int bar()<RESET>
1205         printf("Hello World, but different\n");<RESET>
1206         }<RESET>
1207         <RESET>
1208        <BGREEN>+<RESET><BGREEN>int secure_foo(struct user *u)<RESET>
1209        <BGREEN>+<RESET><BGREEN>{<RESET>
1210        <BGREEN>+<RESET><BGREEN>foo(u);<RESET>
1211        <BGREEN>+<RESET><BGREEN>if (!u->is_allowed_foo)<RESET>
1212        <BGREEN>+<RESET><BGREEN>return;<RESET>
1213        <BGREEN>+<RESET><BGREEN>}<RESET>
1214        <BGREEN>+<RESET>
1215         int another_function()<RESET>
1216         {<RESET>
1217         bar();<RESET>
1218        EOF
1219
1220        test_cmp expected actual
1221'
1222
1223test_expect_success 'detect blocks of moved code' '
1224        git reset --hard &&
1225        cat <<-\EOF >lines.txt &&
1226                long line 1
1227                long line 2
1228                long line 3
1229                line 4
1230                line 5
1231                line 6
1232                line 7
1233                line 8
1234                line 9
1235                line 10
1236                line 11
1237                line 12
1238                line 13
1239                long line 14
1240                long line 15
1241                long line 16
1242        EOF
1243        git add lines.txt &&
1244        git commit -m "add poetry" &&
1245        cat <<-\EOF >lines.txt &&
1246                line 4
1247                line 5
1248                line 6
1249                line 7
1250                line 8
1251                line 9
1252                long line 1
1253                long line 2
1254                long line 3
1255                long line 14
1256                long line 15
1257                long line 16
1258                line 10
1259                line 11
1260                line 12
1261                line 13
1262        EOF
1263        test_config color.diff.oldMoved "magenta" &&
1264        test_config color.diff.newMoved "cyan" &&
1265        test_config color.diff.oldMovedAlternative "blue" &&
1266        test_config color.diff.newMovedAlternative "yellow" &&
1267        test_config color.diff.oldMovedDimmed "normal magenta" &&
1268        test_config color.diff.newMovedDimmed "normal cyan" &&
1269        test_config color.diff.oldMovedAlternativeDimmed "normal blue" &&
1270        test_config color.diff.newMovedAlternativeDimmed "normal yellow" &&
1271        git diff HEAD --no-renames --color-moved=blocks --color >actual.raw &&
1272        grep -v "index" actual.raw | test_decode_color >actual &&
1273        cat <<-\EOF >expected &&
1274        <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1275        <BOLD>--- a/lines.txt<RESET>
1276        <BOLD>+++ b/lines.txt<RESET>
1277        <CYAN>@@ -1,16 +1,16 @@<RESET>
1278        <MAGENTA>-long line 1<RESET>
1279        <MAGENTA>-long line 2<RESET>
1280        <MAGENTA>-long line 3<RESET>
1281         line 4<RESET>
1282         line 5<RESET>
1283         line 6<RESET>
1284         line 7<RESET>
1285         line 8<RESET>
1286         line 9<RESET>
1287        <CYAN>+<RESET><CYAN>long line 1<RESET>
1288        <CYAN>+<RESET><CYAN>long line 2<RESET>
1289        <CYAN>+<RESET><CYAN>long line 3<RESET>
1290        <CYAN>+<RESET><CYAN>long line 14<RESET>
1291        <CYAN>+<RESET><CYAN>long line 15<RESET>
1292        <CYAN>+<RESET><CYAN>long line 16<RESET>
1293         line 10<RESET>
1294         line 11<RESET>
1295         line 12<RESET>
1296         line 13<RESET>
1297        <MAGENTA>-long line 14<RESET>
1298        <MAGENTA>-long line 15<RESET>
1299        <MAGENTA>-long line 16<RESET>
1300        EOF
1301        test_cmp expected actual
1302
1303'
1304
1305test_expect_success 'detect permutations inside moved code -- dimmed-zebra' '
1306        # reuse setup from test before!
1307        test_config color.diff.oldMoved "magenta" &&
1308        test_config color.diff.newMoved "cyan" &&
1309        test_config color.diff.oldMovedAlternative "blue" &&
1310        test_config color.diff.newMovedAlternative "yellow" &&
1311        test_config color.diff.oldMovedDimmed "normal magenta" &&
1312        test_config color.diff.newMovedDimmed "normal cyan" &&
1313        test_config color.diff.oldMovedAlternativeDimmed "normal blue" &&
1314        test_config color.diff.newMovedAlternativeDimmed "normal yellow" &&
1315        git diff HEAD --no-renames --color-moved=dimmed-zebra --color >actual.raw &&
1316        grep -v "index" actual.raw | test_decode_color >actual &&
1317        cat <<-\EOF >expected &&
1318        <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1319        <BOLD>--- a/lines.txt<RESET>
1320        <BOLD>+++ b/lines.txt<RESET>
1321        <CYAN>@@ -1,16 +1,16 @@<RESET>
1322        <BMAGENTA>-long line 1<RESET>
1323        <BMAGENTA>-long line 2<RESET>
1324        <BMAGENTA>-long line 3<RESET>
1325         line 4<RESET>
1326         line 5<RESET>
1327         line 6<RESET>
1328         line 7<RESET>
1329         line 8<RESET>
1330         line 9<RESET>
1331        <BCYAN>+<RESET><BCYAN>long line 1<RESET>
1332        <BCYAN>+<RESET><BCYAN>long line 2<RESET>
1333        <CYAN>+<RESET><CYAN>long line 3<RESET>
1334        <YELLOW>+<RESET><YELLOW>long line 14<RESET>
1335        <BYELLOW>+<RESET><BYELLOW>long line 15<RESET>
1336        <BYELLOW>+<RESET><BYELLOW>long line 16<RESET>
1337         line 10<RESET>
1338         line 11<RESET>
1339         line 12<RESET>
1340         line 13<RESET>
1341        <BMAGENTA>-long line 14<RESET>
1342        <BMAGENTA>-long line 15<RESET>
1343        <BMAGENTA>-long line 16<RESET>
1344        EOF
1345        test_cmp expected actual
1346'
1347
1348test_expect_success 'cmd option assumes configured colored-moved' '
1349        test_config color.diff.oldMoved "magenta" &&
1350        test_config color.diff.newMoved "cyan" &&
1351        test_config color.diff.oldMovedAlternative "blue" &&
1352        test_config color.diff.newMovedAlternative "yellow" &&
1353        test_config color.diff.oldMovedDimmed "normal magenta" &&
1354        test_config color.diff.newMovedDimmed "normal cyan" &&
1355        test_config color.diff.oldMovedAlternativeDimmed "normal blue" &&
1356        test_config color.diff.newMovedAlternativeDimmed "normal yellow" &&
1357        test_config diff.colorMoved zebra &&
1358        git diff HEAD --no-renames --color-moved --color >actual.raw &&
1359        grep -v "index" actual.raw | test_decode_color >actual &&
1360        cat <<-\EOF >expected &&
1361        <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1362        <BOLD>--- a/lines.txt<RESET>
1363        <BOLD>+++ b/lines.txt<RESET>
1364        <CYAN>@@ -1,16 +1,16 @@<RESET>
1365        <MAGENTA>-long line 1<RESET>
1366        <MAGENTA>-long line 2<RESET>
1367        <MAGENTA>-long line 3<RESET>
1368         line 4<RESET>
1369         line 5<RESET>
1370         line 6<RESET>
1371         line 7<RESET>
1372         line 8<RESET>
1373         line 9<RESET>
1374        <CYAN>+<RESET><CYAN>long line 1<RESET>
1375        <CYAN>+<RESET><CYAN>long line 2<RESET>
1376        <CYAN>+<RESET><CYAN>long line 3<RESET>
1377        <YELLOW>+<RESET><YELLOW>long line 14<RESET>
1378        <YELLOW>+<RESET><YELLOW>long line 15<RESET>
1379        <YELLOW>+<RESET><YELLOW>long line 16<RESET>
1380         line 10<RESET>
1381         line 11<RESET>
1382         line 12<RESET>
1383         line 13<RESET>
1384        <MAGENTA>-long line 14<RESET>
1385        <MAGENTA>-long line 15<RESET>
1386        <MAGENTA>-long line 16<RESET>
1387        EOF
1388        test_cmp expected actual
1389'
1390
1391test_expect_success 'no effect from --color-moved with --word-diff' '
1392        cat <<-\EOF >text.txt &&
1393        Lorem Ipsum is simply dummy text of the printing and typesetting industry.
1394        EOF
1395        git add text.txt &&
1396        git commit -a -m "clean state" &&
1397        cat <<-\EOF >text.txt &&
1398        simply Lorem Ipsum dummy is text of the typesetting and printing industry.
1399        EOF
1400        git diff --color-moved --word-diff >actual &&
1401        git diff --word-diff >expect &&
1402        test_cmp expect actual
1403'
1404
1405test_expect_success 'set up whitespace tests' '
1406        git reset --hard &&
1407        # Note that these lines have no leading or trailing whitespace.
1408        cat <<-\EOF >lines.txt &&
1409        line 1
1410        line 2
1411        line 3
1412        line 4
1413        line 5
1414        long line 6
1415        long line 7
1416        long line 8
1417        long line 9
1418        EOF
1419        git add lines.txt &&
1420        git commit -m "add poetry" &&
1421        git config color.diff.oldMoved "magenta" &&
1422        git config color.diff.newMoved "cyan"
1423'
1424
1425test_expect_success 'move detection ignoring whitespace ' '
1426        q_to_tab <<-\EOF >lines.txt &&
1427        Qlong line 6
1428        Qlong line 7
1429        Qlong line 8
1430        Qchanged long line 9
1431        line 1
1432        line 2
1433        line 3
1434        line 4
1435        line 5
1436        EOF
1437        git diff HEAD --no-renames --color-moved --color >actual.raw &&
1438        grep -v "index" actual.raw | test_decode_color >actual &&
1439        cat <<-\EOF >expected &&
1440        <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1441        <BOLD>--- a/lines.txt<RESET>
1442        <BOLD>+++ b/lines.txt<RESET>
1443        <CYAN>@@ -1,9 +1,9 @@<RESET>
1444        <GREEN>+<RESET> <GREEN>long line 6<RESET>
1445        <GREEN>+<RESET> <GREEN>long line 7<RESET>
1446        <GREEN>+<RESET> <GREEN>long line 8<RESET>
1447        <GREEN>+<RESET> <GREEN>changed long line 9<RESET>
1448         line 1<RESET>
1449         line 2<RESET>
1450         line 3<RESET>
1451         line 4<RESET>
1452         line 5<RESET>
1453        <RED>-long line 6<RESET>
1454        <RED>-long line 7<RESET>
1455        <RED>-long line 8<RESET>
1456        <RED>-long line 9<RESET>
1457        EOF
1458        test_cmp expected actual &&
1459
1460        git diff HEAD --no-renames --color-moved --color \
1461                --color-moved-ws=ignore-all-space >actual.raw &&
1462        grep -v "index" actual.raw | test_decode_color >actual &&
1463        cat <<-\EOF >expected &&
1464        <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1465        <BOLD>--- a/lines.txt<RESET>
1466        <BOLD>+++ b/lines.txt<RESET>
1467        <CYAN>@@ -1,9 +1,9 @@<RESET>
1468        <CYAN>+<RESET>  <CYAN>long line 6<RESET>
1469        <CYAN>+<RESET>  <CYAN>long line 7<RESET>
1470        <CYAN>+<RESET>  <CYAN>long line 8<RESET>
1471        <GREEN>+<RESET> <GREEN>changed long line 9<RESET>
1472         line 1<RESET>
1473         line 2<RESET>
1474         line 3<RESET>
1475         line 4<RESET>
1476         line 5<RESET>
1477        <MAGENTA>-long line 6<RESET>
1478        <MAGENTA>-long line 7<RESET>
1479        <MAGENTA>-long line 8<RESET>
1480        <RED>-long line 9<RESET>
1481        EOF
1482        test_cmp expected actual
1483'
1484
1485test_expect_success 'move detection ignoring whitespace changes' '
1486        git reset --hard &&
1487        # Lines 6-8 have a space change, but 9 is new whitespace
1488        q_to_tab <<-\EOF >lines.txt &&
1489        longQline 6
1490        longQline 7
1491        longQline 8
1492        long liQne 9
1493        line 1
1494        line 2
1495        line 3
1496        line 4
1497        line 5
1498        EOF
1499
1500        git diff HEAD --no-renames --color-moved --color >actual.raw &&
1501        grep -v "index" actual.raw | test_decode_color >actual &&
1502        cat <<-\EOF >expected &&
1503        <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1504        <BOLD>--- a/lines.txt<RESET>
1505        <BOLD>+++ b/lines.txt<RESET>
1506        <CYAN>@@ -1,9 +1,9 @@<RESET>
1507        <GREEN>+<RESET><GREEN>long      line 6<RESET>
1508        <GREEN>+<RESET><GREEN>long      line 7<RESET>
1509        <GREEN>+<RESET><GREEN>long      line 8<RESET>
1510        <GREEN>+<RESET><GREEN>long li   ne 9<RESET>
1511         line 1<RESET>
1512         line 2<RESET>
1513         line 3<RESET>
1514         line 4<RESET>
1515         line 5<RESET>
1516        <RED>-long line 6<RESET>
1517        <RED>-long line 7<RESET>
1518        <RED>-long line 8<RESET>
1519        <RED>-long line 9<RESET>
1520        EOF
1521        test_cmp expected actual &&
1522
1523        git diff HEAD --no-renames --color-moved --color \
1524                --color-moved-ws=ignore-space-change >actual.raw &&
1525        grep -v "index" actual.raw | test_decode_color >actual &&
1526        cat <<-\EOF >expected &&
1527        <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1528        <BOLD>--- a/lines.txt<RESET>
1529        <BOLD>+++ b/lines.txt<RESET>
1530        <CYAN>@@ -1,9 +1,9 @@<RESET>
1531        <CYAN>+<RESET><CYAN>long        line 6<RESET>
1532        <CYAN>+<RESET><CYAN>long        line 7<RESET>
1533        <CYAN>+<RESET><CYAN>long        line 8<RESET>
1534        <GREEN>+<RESET><GREEN>long li   ne 9<RESET>
1535         line 1<RESET>
1536         line 2<RESET>
1537         line 3<RESET>
1538         line 4<RESET>
1539         line 5<RESET>
1540        <MAGENTA>-long line 6<RESET>
1541        <MAGENTA>-long line 7<RESET>
1542        <MAGENTA>-long line 8<RESET>
1543        <RED>-long line 9<RESET>
1544        EOF
1545        test_cmp expected actual
1546'
1547
1548test_expect_success 'move detection ignoring whitespace at eol' '
1549        git reset --hard &&
1550        # Lines 6-9 have new eol whitespace, but 9 also has it in the middle
1551        q_to_tab <<-\EOF >lines.txt &&
1552        long line 6Q
1553        long line 7Q
1554        long line 8Q
1555        longQline 9Q
1556        line 1
1557        line 2
1558        line 3
1559        line 4
1560        line 5
1561        EOF
1562
1563        # avoid cluttering the output with complaints about our eol whitespace
1564        test_config core.whitespace -blank-at-eol &&
1565
1566        git diff HEAD --no-renames --color-moved --color >actual.raw &&
1567        grep -v "index" actual.raw | test_decode_color >actual &&
1568        cat <<-\EOF >expected &&
1569        <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1570        <BOLD>--- a/lines.txt<RESET>
1571        <BOLD>+++ b/lines.txt<RESET>
1572        <CYAN>@@ -1,9 +1,9 @@<RESET>
1573        <GREEN>+<RESET><GREEN>long line 6       <RESET>
1574        <GREEN>+<RESET><GREEN>long line 7       <RESET>
1575        <GREEN>+<RESET><GREEN>long line 8       <RESET>
1576        <GREEN>+<RESET><GREEN>long      line 9  <RESET>
1577         line 1<RESET>
1578         line 2<RESET>
1579         line 3<RESET>
1580         line 4<RESET>
1581         line 5<RESET>
1582        <RED>-long line 6<RESET>
1583        <RED>-long line 7<RESET>
1584        <RED>-long line 8<RESET>
1585        <RED>-long line 9<RESET>
1586        EOF
1587        test_cmp expected actual &&
1588
1589        git diff HEAD --no-renames --color-moved --color \
1590                --color-moved-ws=ignore-space-at-eol >actual.raw &&
1591        grep -v "index" actual.raw | test_decode_color >actual &&
1592        cat <<-\EOF >expected &&
1593        <BOLD>diff --git a/lines.txt b/lines.txt<RESET>
1594        <BOLD>--- a/lines.txt<RESET>
1595        <BOLD>+++ b/lines.txt<RESET>
1596        <CYAN>@@ -1,9 +1,9 @@<RESET>
1597        <CYAN>+<RESET><CYAN>long line 6 <RESET>
1598        <CYAN>+<RESET><CYAN>long line 7 <RESET>
1599        <CYAN>+<RESET><CYAN>long line 8 <RESET>
1600        <GREEN>+<RESET><GREEN>long      line 9  <RESET>
1601         line 1<RESET>
1602         line 2<RESET>
1603         line 3<RESET>
1604         line 4<RESET>
1605         line 5<RESET>
1606        <MAGENTA>-long line 6<RESET>
1607        <MAGENTA>-long line 7<RESET>
1608        <MAGENTA>-long line 8<RESET>
1609        <RED>-long line 9<RESET>
1610        EOF
1611        test_cmp expected actual
1612'
1613
1614test_expect_success 'clean up whitespace-test colors' '
1615        git config --unset color.diff.oldMoved &&
1616        git config --unset color.diff.newMoved
1617'
1618
1619test_expect_success '--color-moved block at end of diff output respects MIN_ALNUM_COUNT' '
1620        git reset --hard &&
1621        >bar &&
1622        cat <<-\EOF >foo &&
1623        irrelevant_line
1624        line1
1625        EOF
1626        git add foo bar &&
1627        git commit -m x &&
1628
1629        cat <<-\EOF >bar &&
1630        line1
1631        EOF
1632        cat <<-\EOF >foo &&
1633        irrelevant_line
1634        EOF
1635
1636        git diff HEAD --color-moved=zebra --color --no-renames >actual.raw &&
1637        grep -v "index" actual.raw | test_decode_color >actual &&
1638        cat >expected <<-\EOF &&
1639        <BOLD>diff --git a/bar b/bar<RESET>
1640        <BOLD>--- a/bar<RESET>
1641        <BOLD>+++ b/bar<RESET>
1642        <CYAN>@@ -0,0 +1 @@<RESET>
1643        <GREEN>+<RESET><GREEN>line1<RESET>
1644        <BOLD>diff --git a/foo b/foo<RESET>
1645        <BOLD>--- a/foo<RESET>
1646        <BOLD>+++ b/foo<RESET>
1647        <CYAN>@@ -1,2 +1 @@<RESET>
1648         irrelevant_line<RESET>
1649        <RED>-line1<RESET>
1650        EOF
1651
1652        test_cmp expected actual
1653'
1654
1655test_expect_success '--color-moved respects MIN_ALNUM_COUNT' '
1656        git reset --hard &&
1657        cat <<-\EOF >foo &&
1658        nineteen chars 456789
1659        irrelevant_line
1660        twenty chars 234567890
1661        EOF
1662        >bar &&
1663        git add foo bar &&
1664        git commit -m x &&
1665
1666        cat <<-\EOF >foo &&
1667        irrelevant_line
1668        EOF
1669        cat <<-\EOF >bar &&
1670        twenty chars 234567890
1671        nineteen chars 456789
1672        EOF
1673
1674        git diff HEAD --color-moved=zebra --color --no-renames >actual.raw &&
1675        grep -v "index" actual.raw | test_decode_color >actual &&
1676        cat >expected <<-\EOF &&
1677        <BOLD>diff --git a/bar b/bar<RESET>
1678        <BOLD>--- a/bar<RESET>
1679        <BOLD>+++ b/bar<RESET>
1680        <CYAN>@@ -0,0 +1,2 @@<RESET>
1681        <BOLD;CYAN>+<RESET><BOLD;CYAN>twenty chars 234567890<RESET>
1682        <GREEN>+<RESET><GREEN>nineteen chars 456789<RESET>
1683        <BOLD>diff --git a/foo b/foo<RESET>
1684        <BOLD>--- a/foo<RESET>
1685        <BOLD>+++ b/foo<RESET>
1686        <CYAN>@@ -1,3 +1 @@<RESET>
1687        <RED>-nineteen chars 456789<RESET>
1688         irrelevant_line<RESET>
1689        <BOLD;MAGENTA>-twenty chars 234567890<RESET>
1690        EOF
1691
1692        test_cmp expected actual
1693'
1694
1695test_expect_success '--color-moved treats adjacent blocks as separate for MIN_ALNUM_COUNT' '
1696        git reset --hard &&
1697        cat <<-\EOF >foo &&
1698        7charsA
1699        irrelevant_line
1700        7charsB
1701        7charsC
1702        EOF
1703        >bar &&
1704        git add foo bar &&
1705        git commit -m x &&
1706
1707        cat <<-\EOF >foo &&
1708        irrelevant_line
1709        EOF
1710        cat <<-\EOF >bar &&
1711        7charsB
1712        7charsC
1713        7charsA
1714        EOF
1715
1716        git diff HEAD --color-moved=zebra --color --no-renames >actual.raw &&
1717        grep -v "index" actual.raw | test_decode_color >actual &&
1718        cat >expected <<-\EOF &&
1719        <BOLD>diff --git a/bar b/bar<RESET>
1720        <BOLD>--- a/bar<RESET>
1721        <BOLD>+++ b/bar<RESET>
1722        <CYAN>@@ -0,0 +1,3 @@<RESET>
1723        <GREEN>+<RESET><GREEN>7charsB<RESET>
1724        <GREEN>+<RESET><GREEN>7charsC<RESET>
1725        <GREEN>+<RESET><GREEN>7charsA<RESET>
1726        <BOLD>diff --git a/foo b/foo<RESET>
1727        <BOLD>--- a/foo<RESET>
1728        <BOLD>+++ b/foo<RESET>
1729        <CYAN>@@ -1,4 +1 @@<RESET>
1730        <RED>-7charsA<RESET>
1731         irrelevant_line<RESET>
1732        <RED>-7charsB<RESET>
1733        <RED>-7charsC<RESET>
1734        EOF
1735
1736        test_cmp expected actual
1737'
1738
1739test_expect_success 'move detection with submodules' '
1740        test_create_repo bananas &&
1741        echo ripe >bananas/recipe &&
1742        git -C bananas add recipe &&
1743        test_commit fruit &&
1744        test_commit -C bananas recipe &&
1745        git submodule add ./bananas &&
1746        git add bananas &&
1747        git commit -a -m "bananas are like a heavy library?" &&
1748        echo foul >bananas/recipe &&
1749        echo ripe >fruit.t &&
1750
1751        git diff --submodule=diff --color-moved --color >actual &&
1752
1753        # no move detection as the moved line is across repository boundaries.
1754        test_decode_color <actual >decoded_actual &&
1755        ! grep BGREEN decoded_actual &&
1756        ! grep BRED decoded_actual &&
1757
1758        # nor did we mess with it another way
1759        git diff --submodule=diff --color | test_decode_color >expect &&
1760        test_cmp expect decoded_actual &&
1761        rm -rf bananas &&
1762        git submodule deinit bananas
1763'
1764
1765test_expect_success 'only move detection ignores white spaces' '
1766        git reset --hard &&
1767        q_to_tab <<-\EOF >text.txt &&
1768                a long line to exceed per-line minimum
1769                another long line to exceed per-line minimum
1770                original file
1771        EOF
1772        git add text.txt &&
1773        git commit -m "add text" &&
1774        q_to_tab <<-\EOF >text.txt &&
1775                Qa long line to exceed per-line minimum
1776                Qanother long line to exceed per-line minimum
1777                new file
1778        EOF
1779
1780        # Make sure we get a different diff using -w
1781        git diff --color --color-moved -w >actual.raw &&
1782        grep -v "index" actual.raw | test_decode_color >actual &&
1783        q_to_tab <<-\EOF >expected &&
1784        <BOLD>diff --git a/text.txt b/text.txt<RESET>
1785        <BOLD>--- a/text.txt<RESET>
1786        <BOLD>+++ b/text.txt<RESET>
1787        <CYAN>@@ -1,3 +1,3 @@<RESET>
1788         Qa long line to exceed per-line minimum<RESET>
1789         Qanother long line to exceed per-line minimum<RESET>
1790        <RED>-original file<RESET>
1791        <GREEN>+<RESET><GREEN>new file<RESET>
1792        EOF
1793        test_cmp expected actual &&
1794
1795        # And now ignoring white space only in the move detection
1796        git diff --color --color-moved \
1797                --color-moved-ws=ignore-all-space,ignore-space-change,ignore-space-at-eol >actual.raw &&
1798        grep -v "index" actual.raw | test_decode_color >actual &&
1799        q_to_tab <<-\EOF >expected &&
1800        <BOLD>diff --git a/text.txt b/text.txt<RESET>
1801        <BOLD>--- a/text.txt<RESET>
1802        <BOLD>+++ b/text.txt<RESET>
1803        <CYAN>@@ -1,3 +1,3 @@<RESET>
1804        <BOLD;MAGENTA>-a long line to exceed per-line minimum<RESET>
1805        <BOLD;MAGENTA>-another long line to exceed per-line minimum<RESET>
1806        <RED>-original file<RESET>
1807        <BOLD;YELLOW>+<RESET>Q<BOLD;YELLOW>a long line to exceed per-line minimum<RESET>
1808        <BOLD;YELLOW>+<RESET>Q<BOLD;YELLOW>another long line to exceed per-line minimum<RESET>
1809        <GREEN>+<RESET><GREEN>new file<RESET>
1810        EOF
1811        test_cmp expected actual
1812'
1813
1814test_expect_success 'compare whitespace delta across moved blocks' '
1815
1816        git reset --hard &&
1817        q_to_tab <<-\EOF >text.txt &&
1818        QIndented
1819        QText across
1820        Qsome lines
1821        QBut! <- this stands out
1822        QAdjusting with
1823        QQdifferent starting
1824        Qwhite spaces
1825        QAnother outlier
1826        QQQIndented
1827        QQQText across
1828        QQQfive lines
1829        QQQthat has similar lines
1830        QQQto previous blocks, but with different indent
1831        QQQYetQAnotherQoutlierQ
1832        EOF
1833
1834        git add text.txt &&
1835        git commit -m "add text.txt" &&
1836
1837        q_to_tab <<-\EOF >text.txt &&
1838        QQIndented
1839        QQText across
1840        QQsome lines
1841        QQQBut! <- this stands out
1842        Adjusting with
1843        Qdifferent starting
1844        white spaces
1845        AnotherQoutlier
1846        QQIndented
1847        QQText across
1848        QQfive lines
1849        QQthat has similar lines
1850        QQto previous blocks, but with different indent
1851        QQYetQAnotherQoutlier
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,14 +1,14 @@<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                <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>Indented<RESET>
1877                <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>Text across<RESET>
1878                <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>some lines<RESET>
1879                <GREEN>+<RESET>QQQ<GREEN>But! <- this stands out<RESET>
1880                <BOLD;CYAN>+<RESET><BOLD;CYAN>Adjusting with<RESET>
1881                <BOLD;CYAN>+<RESET>Q<BOLD;CYAN>different starting<RESET>
1882                <BOLD;CYAN>+<RESET><BOLD;CYAN>white spaces<RESET>
1883                <GREEN>+<RESET><GREEN>AnotherQoutlier<RESET>
1884                <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>Indented<RESET>
1885                <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>Text across<RESET>
1886                <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>five lines<RESET>
1887                <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>that has similar lines<RESET>
1888                <BOLD;CYAN>+<RESET>QQ<BOLD;CYAN>to previous blocks, but with different indent<RESET>
1889                <GREEN>+<RESET>QQ<GREEN>YetQAnotherQoutlier<RESET>
1890        EOF
1891
1892        test_cmp expected actual
1893'
1894
1895test_expect_success 'compare whitespace delta incompatible with other space options' '
1896        test_must_fail git diff \
1897                --color-moved-ws=allow-indentation-change,ignore-all-space \
1898                2>err &&
1899        test_i18ngrep allow-indentation-change err
1900'
1901
1902test_done