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