t / t4124-apply-ws-rule.shon commit Documentation/everyday: match undefline with the text (f3f38c7)
   1#!/bin/sh
   2
   3test_description='core.whitespace rules and git apply'
   4
   5. ./test-lib.sh
   6
   7prepare_test_file () {
   8
   9        # A line that has character X is touched iff RULE is in effect:
  10        #       X  RULE
  11        #       !  trailing-space
  12        #       @  space-before-tab
  13        #       #  indent-with-non-tab (default tab width 8)
  14        #       =  indent-with-non-tab,tabwidth=16
  15        #       %  tab-in-indent
  16        sed -e "s/_/ /g" -e "s/>/       /" <<-\EOF
  17                An_SP in an ordinary line>and a HT.
  18                >A HT (%).
  19                _>A SP and a HT (@%).
  20                _>_A SP, a HT and a SP (@%).
  21                _______Seven SP.
  22                ________Eight SP (#).
  23                _______>Seven SP and a HT (@%).
  24                ________>Eight SP and a HT (@#%).
  25                _______>_Seven SP, a HT and a SP (@%).
  26                ________>_Eight SP, a HT and a SP (@#%).
  27                _______________Fifteen SP (#).
  28                _______________>Fifteen SP and a HT (@#%).
  29                ________________Sixteen SP (#=).
  30                ________________>Sixteen SP and a HT (@#%=).
  31                _____a__Five SP, a non WS, two SP.
  32                A line with a (!) trailing SP_
  33                A line with a (!) trailing HT>
  34        EOF
  35}
  36
  37apply_patch () {
  38        >target &&
  39        sed -e "s|\([ab]\)/file|\1/target|" <patch |
  40        git apply "$@"
  41}
  42
  43test_fix () {
  44        # fix should not barf
  45        apply_patch --whitespace=fix || return 1
  46
  47        # find touched lines
  48        $DIFF file target | sed -n -e "s/^> //p" >fixed
  49
  50        # the changed lines are all expected to change
  51        fixed_cnt=$(wc -l <fixed)
  52        case "$1" in
  53        '') expect_cnt=$fixed_cnt ;;
  54        ?*) expect_cnt=$(grep "[$1]" <fixed | wc -l) ;;
  55        esac
  56        test $fixed_cnt -eq $expect_cnt || return 1
  57
  58        # and we are not missing anything
  59        case "$1" in
  60        '') expect_cnt=0 ;;
  61        ?*) expect_cnt=$(grep "[$1]" <file | wc -l) ;;
  62        esac
  63        test $fixed_cnt -eq $expect_cnt || return 1
  64
  65        # Get the patch actually applied
  66        git diff-files -p target >fixed-patch
  67        test -s fixed-patch && return 0
  68
  69        # Make sure it is complaint-free
  70        >target
  71        git apply --whitespace=error-all <fixed-patch
  72
  73}
  74
  75test_expect_success setup '
  76
  77        >file &&
  78        git add file &&
  79        prepare_test_file >file &&
  80        git diff-files -p >patch &&
  81        >target &&
  82        git add target
  83
  84'
  85
  86test_expect_success 'whitespace=nowarn, default rule' '
  87
  88        apply_patch --whitespace=nowarn &&
  89        test_cmp file target
  90
  91'
  92
  93test_expect_success 'whitespace=warn, default rule' '
  94
  95        apply_patch --whitespace=warn &&
  96        test_cmp file target
  97
  98'
  99
 100test_expect_success 'whitespace=error-all, default rule' '
 101
 102        apply_patch --whitespace=error-all && return 1
 103        test -s target && return 1
 104        : happy
 105
 106'
 107
 108test_expect_success 'whitespace=error-all, no rule' '
 109
 110        git config core.whitespace -trailing,-space-before,-indent &&
 111        apply_patch --whitespace=error-all &&
 112        test_cmp file target
 113
 114'
 115
 116test_expect_success 'whitespace=error-all, no rule (attribute)' '
 117
 118        git config --unset core.whitespace &&
 119        echo "target -whitespace" >.gitattributes &&
 120        apply_patch --whitespace=error-all &&
 121        test_cmp file target
 122
 123'
 124
 125test_expect_success 'spaces inserted by tab-in-indent' '
 126
 127        git config core.whitespace -trailing,-space,-indent,tab &&
 128        rm -f .gitattributes &&
 129        test_fix % &&
 130        sed -e "s/_/ /g" -e "s/>/       /" <<-\EOF >expect &&
 131                An_SP in an ordinary line>and a HT.
 132                ________A HT (%).
 133                ________A SP and a HT (@%).
 134                _________A SP, a HT and a SP (@%).
 135                _______Seven SP.
 136                ________Eight SP (#).
 137                ________Seven SP and a HT (@%).
 138                ________________Eight SP and a HT (@#%).
 139                _________Seven SP, a HT and a SP (@%).
 140                _________________Eight SP, a HT and a SP (@#%).
 141                _______________Fifteen SP (#).
 142                ________________Fifteen SP and a HT (@#%).
 143                ________________Sixteen SP (#=).
 144                ________________________Sixteen SP and a HT (@#%=).
 145                _____a__Five SP, a non WS, two SP.
 146                A line with a (!) trailing SP_
 147                A line with a (!) trailing HT>
 148        EOF
 149        test_cmp expect target
 150
 151'
 152
 153for t in - ''
 154do
 155        case "$t" in '') tt='!' ;; *) tt= ;; esac
 156        for s in - ''
 157        do
 158                case "$s" in '') ts='@' ;; *) ts= ;; esac
 159                for i in - ''
 160                do
 161                        case "$i" in '') ti='#' ti16='=';; *) ti= ti16= ;; esac
 162                        for h in - ''
 163                        do
 164                                [ -z "$h$i" ] && continue
 165                                case "$h" in '') th='%' ;; *) th= ;; esac
 166                                rule=${t}trailing,${s}space,${i}indent,${h}tab
 167
 168                                rm -f .gitattributes
 169                                test_expect_success "rule=$rule" '
 170                                        git config core.whitespace "$rule" &&
 171                                        test_fix "$tt$ts$ti$th"
 172                                '
 173
 174                                test_expect_success "rule=$rule,tabwidth=16" '
 175                                        git config core.whitespace "$rule,tabwidth=16" &&
 176                                        test_fix "$tt$ts$ti16$th"
 177                                '
 178
 179                                test_expect_success "rule=$rule (attributes)" '
 180                                        git config --unset core.whitespace &&
 181                                        echo "target whitespace=$rule" >.gitattributes &&
 182                                        test_fix "$tt$ts$ti$th"
 183                                '
 184
 185                                test_expect_success "rule=$rule,tabwidth=16 (attributes)" '
 186                                        echo "target whitespace=$rule,tabwidth=16" >.gitattributes &&
 187                                        test_fix "$tt$ts$ti16$th"
 188                                '
 189
 190                        done
 191                done
 192        done
 193done
 194
 195create_patch () {
 196        sed -e "s/_/ /" <<-\EOF
 197                diff --git a/target b/target
 198                index e69de29..8bd6648 100644
 199                --- a/target
 200                +++ b/target
 201                @@ -0,0 +1,3 @@
 202                +An empty line follows
 203                +
 204                +A line with trailing whitespace and no newline_
 205                \ No newline at end of file
 206        EOF
 207}
 208
 209test_expect_success 'trailing whitespace & no newline at the end of file' '
 210        >target &&
 211        create_patch >patch-file &&
 212        git apply --whitespace=fix patch-file &&
 213        grep "newline$" target &&
 214        grep "^$" target
 215'
 216
 217test_expect_success 'blank at EOF with --whitespace=fix (1)' '
 218        test_might_fail git config --unset core.whitespace &&
 219        rm -f .gitattributes &&
 220
 221        { echo a; echo b; echo c; } >one &&
 222        git add one &&
 223        { echo a; echo b; echo c; } >expect &&
 224        { cat expect; echo; } >one &&
 225        git diff -- one >patch &&
 226
 227        git checkout one &&
 228        git apply --whitespace=fix patch &&
 229        test_cmp expect one
 230'
 231
 232test_expect_success 'blank at EOF with --whitespace=fix (2)' '
 233        { echo a; echo b; echo c; } >one &&
 234        git add one &&
 235        { echo a; echo c; } >expect &&
 236        { cat expect; echo; echo; } >one &&
 237        git diff -- one >patch &&
 238
 239        git checkout one &&
 240        git apply --whitespace=fix patch &&
 241        test_cmp expect one
 242'
 243
 244test_expect_success 'blank at EOF with --whitespace=fix (3)' '
 245        { echo a; echo b; echo; } >one &&
 246        git add one &&
 247        { echo a; echo c; echo; } >expect &&
 248        { cat expect; echo; echo; } >one &&
 249        git diff -- one >patch &&
 250
 251        git checkout one &&
 252        git apply --whitespace=fix patch &&
 253        test_cmp expect one
 254'
 255
 256test_expect_success 'blank at end of hunk, not at EOF with --whitespace=fix' '
 257        { echo a; echo b; echo; echo; echo; echo; echo; echo d; } >one &&
 258        git add one &&
 259        { echo a; echo c; echo; echo; echo; echo; echo; echo; echo d; } >expect &&
 260        cp expect one &&
 261        git diff -- one >patch &&
 262
 263        git checkout one &&
 264        git apply --whitespace=fix patch &&
 265        test_cmp expect one
 266'
 267
 268test_expect_success 'blank at EOF with --whitespace=warn' '
 269        { echo a; echo b; echo c; } >one &&
 270        git add one &&
 271        echo >>one &&
 272        cat one >expect &&
 273        git diff -- one >patch &&
 274
 275        git checkout one &&
 276        git apply --whitespace=warn patch 2>error &&
 277        test_cmp expect one &&
 278        grep "new blank line at EOF" error
 279'
 280
 281test_expect_success 'blank at EOF with --whitespace=error' '
 282        { echo a; echo b; echo c; } >one &&
 283        git add one &&
 284        cat one >expect &&
 285        echo >>one &&
 286        git diff -- one >patch &&
 287
 288        git checkout one &&
 289        test_must_fail git apply --whitespace=error patch 2>error &&
 290        test_cmp expect one &&
 291        grep "new blank line at EOF" error
 292'
 293
 294test_expect_success 'blank but not empty at EOF' '
 295        { echo a; echo b; echo c; } >one &&
 296        git add one &&
 297        echo "   " >>one &&
 298        cat one >expect &&
 299        git diff -- one >patch &&
 300
 301        git checkout one &&
 302        git apply --whitespace=warn patch 2>error &&
 303        test_cmp expect one &&
 304        grep "new blank line at EOF" error
 305'
 306
 307test_expect_success 'applying beyond EOF requires one non-blank context line' '
 308        { echo; echo; echo; echo; } >one &&
 309        git add one &&
 310        { echo b; } >>one &&
 311        git diff -- one >patch &&
 312
 313        git checkout one &&
 314        { echo a; echo; } >one &&
 315        cp one expect &&
 316        test_must_fail git apply --whitespace=fix patch &&
 317        test_cmp one expect &&
 318        test_must_fail git apply --ignore-space-change --whitespace=fix patch &&
 319        test_cmp one expect
 320'
 321
 322test_expect_success 'tons of blanks at EOF should not apply' '
 323        for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; do
 324                echo; echo; echo; echo;
 325        done >one &&
 326        git add one &&
 327        echo a >>one &&
 328        git diff -- one >patch &&
 329
 330        >one &&
 331        test_must_fail git apply --whitespace=fix patch &&
 332        test_must_fail git apply --ignore-space-change --whitespace=fix patch
 333'
 334
 335test_expect_success 'missing blank line at end with --whitespace=fix' '
 336        echo a >one &&
 337        echo >>one &&
 338        git add one &&
 339        echo b >>one &&
 340        cp one expect &&
 341        git diff -- one >patch &&
 342        echo a >one &&
 343        cp one saved-one &&
 344        test_must_fail git apply patch &&
 345        git apply --whitespace=fix patch &&
 346        test_cmp one expect &&
 347        mv saved-one one &&
 348        git apply --ignore-space-change --whitespace=fix patch &&
 349        test_cmp one expect
 350'
 351
 352test_expect_success 'two missing blank lines at end with --whitespace=fix' '
 353        { echo a; echo; echo b; echo c; } >one &&
 354        cp one no-blank-lines &&
 355        { echo; echo; } >>one &&
 356        git add one &&
 357        echo d >>one &&
 358        cp one expect &&
 359        echo >>one &&
 360        git diff -- one >patch &&
 361        cp no-blank-lines one &&
 362        test_must_fail git apply patch &&
 363        git apply --whitespace=fix patch &&
 364        test_cmp one expect &&
 365        mv no-blank-lines one &&
 366        test_must_fail git apply patch &&
 367        git apply --ignore-space-change --whitespace=fix patch &&
 368        test_cmp one expect
 369'
 370
 371test_expect_success 'missing blank line at end, insert before end, --whitespace=fix' '
 372        { echo a; echo; } >one &&
 373        git add one &&
 374        { echo b; echo a; echo; } >one &&
 375        cp one expect &&
 376        git diff -- one >patch &&
 377        echo a >one &&
 378        test_must_fail git apply patch &&
 379        git apply --whitespace=fix patch &&
 380        test_cmp one expect
 381'
 382
 383test_expect_success 'shrink file with tons of missing blanks at end of file' '
 384        { echo a; echo b; echo c; } >one &&
 385        cp one no-blank-lines &&
 386        for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; do
 387                echo; echo; echo; echo;
 388        done >>one &&
 389        git add one &&
 390        echo a >one &&
 391        cp one expect &&
 392        git diff -- one >patch &&
 393        cp no-blank-lines one &&
 394        test_must_fail git apply patch &&
 395        git apply --whitespace=fix patch &&
 396        test_cmp one expect &&
 397        mv no-blank-lines one &&
 398        git apply --ignore-space-change --whitespace=fix patch &&
 399        test_cmp one expect
 400'
 401
 402test_expect_success 'missing blanks at EOF must only match blank lines' '
 403        { echo a; echo b; } >one &&
 404        git add one &&
 405        { echo c; echo d; } >>one &&
 406        git diff -- one >patch &&
 407
 408        echo a >one &&
 409        test_must_fail git apply patch &&
 410        test_must_fail git apply --whitespace=fix patch &&
 411        test_must_fail git apply --ignore-space-change --whitespace=fix patch
 412'
 413
 414sed -e's/Z//' >one <<EOF
 415a
 416b
 417c
 418                      Z
 419EOF
 420
 421test_expect_success 'missing blank line should match context line with spaces' '
 422        git add one &&
 423        echo d >>one &&
 424        git diff -- one >patch &&
 425        { echo a; echo b; echo c; } >one &&
 426        cp one expect &&
 427        { echo; echo d; } >>expect &&
 428        git add one &&
 429
 430        git apply --whitespace=fix patch &&
 431        test_cmp one expect
 432'
 433
 434sed -e's/Z//' >one <<EOF
 435a
 436b
 437c
 438                      Z
 439EOF
 440
 441test_expect_success 'same, but with the --ignore-space-option' '
 442        git add one &&
 443        echo d >>one &&
 444        cp one expect &&
 445        git diff -- one >patch &&
 446        { echo a; echo b; echo c; } >one &&
 447        git add one &&
 448
 449        git checkout-index -f one &&
 450        git apply --ignore-space-change --whitespace=fix patch &&
 451        test_cmp one expect
 452'
 453
 454test_expect_success 'same, but with CR-LF line endings && cr-at-eol set' '
 455        git config core.whitespace cr-at-eol &&
 456        printf "a\r\n" >one &&
 457        printf "b\r\n" >>one &&
 458        printf "c\r\n" >>one &&
 459        cp one save-one &&
 460        printf "                 \r\n" >>one &&
 461        git add one &&
 462        printf "d\r\n" >>one &&
 463        cp one expect &&
 464        git diff -- one >patch &&
 465        mv save-one one &&
 466
 467        git apply --ignore-space-change --whitespace=fix patch &&
 468        test_cmp one expect
 469'
 470
 471test_expect_success 'same, but with CR-LF line endings && cr-at-eol unset' '
 472        git config --unset core.whitespace &&
 473        printf "a\r\n" >one &&
 474        printf "b\r\n" >>one &&
 475        printf "c\r\n" >>one &&
 476        cp one save-one &&
 477        printf "                 \r\n" >>one &&
 478        git add one &&
 479        cp one expect &&
 480        printf "d\r\n" >>one &&
 481        git diff -- one >patch &&
 482        mv save-one one &&
 483        echo d >>expect &&
 484
 485        git apply --ignore-space-change --whitespace=fix patch &&
 486        test_cmp one expect
 487'
 488
 489test_expect_success 'whitespace=fix to expand' '
 490        qz_to_tab_space >preimage <<-\EOF &&
 491        QQa
 492        QQb
 493        QQc
 494        ZZZZZZZZZZZZZZZZd
 495        QQe
 496        QQf
 497        QQg
 498        EOF
 499        qz_to_tab_space >patch <<-\EOF &&
 500        diff --git a/preimage b/preimage
 501        --- a/preimage
 502        +++ b/preimage
 503        @@ -1,7 +1,6 @@
 504         QQa
 505         QQb
 506         QQc
 507        -QQd
 508         QQe
 509         QQf
 510         QQg
 511        EOF
 512        git -c core.whitespace=tab-in-indent apply --whitespace=fix patch
 513'
 514
 515test_expect_success 'whitespace check skipped for excluded paths' '
 516        git config core.whitespace blank-at-eol &&
 517        >used &&
 518        >unused &&
 519        git add used unused &&
 520        echo "used" >used &&
 521        echo "unused " >unused &&
 522        git diff-files -p used unused >patch &&
 523        git apply --include=used --stat --whitespace=error <patch
 524'
 525
 526test_done