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