t / t4124-apply-ws-rule.shon commit apply --whitespace=fix: fix tab-in-indent (d35711a)
   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        diff file target
  89
  90'
  91
  92test_expect_success 'whitespace=warn, default rule' '
  93
  94        apply_patch --whitespace=warn &&
  95        diff 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        diff 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        diff file target
 121
 122'
 123
 124test_expect_success 'spaces inserted by tab-in-indent' '
 125
 126        git config core.whitespace -trailing,-space,-indent,tab &&
 127        rm -f .gitattributes &&
 128        test_fix % &&
 129        sed -e "s/_/ /g" -e "s/>/       /" <<-\EOF >expect &&
 130                An_SP in an ordinary line>and a HT.
 131                ________A HT (%).
 132                ________A SP and a HT (@%).
 133                _________A SP, a HT and a SP (@%).
 134                _______Seven SP.
 135                ________Eight SP (#).
 136                ________Seven SP and a HT (@%).
 137                ________________Eight SP and a HT (@#%).
 138                _________Seven SP, a HT and a SP (@%).
 139                _________________Eight SP, a HT and a SP (@#%).
 140                _______________Fifteen SP (#).
 141                ________________Fifteen SP and a HT (@#%).
 142                ________________Sixteen SP (#).
 143                ________________________Sixteen SP and a HT (@#%).
 144                _____a__Five SP, a non WS, two SP.
 145                A line with a (!) trailing SP_
 146                A line with a (!) trailing HT>
 147        EOF
 148        test_cmp expect target
 149
 150'
 151
 152for t in - ''
 153do
 154        case "$t" in '') tt='!' ;; *) tt= ;; esac
 155        for s in - ''
 156        do
 157                case "$s" in '') ts='@' ;; *) ts= ;; esac
 158                for i in - ''
 159                do
 160                        case "$i" in '') ti='#' ;; *) ti= ;; esac
 161                        for h in - ''
 162                        do
 163                                [ -z "$h$i" ] && continue
 164                                case "$h" in '') th='%' ;; *) th= ;; esac
 165                                rule=${t}trailing,${s}space,${i}indent,${h}tab
 166
 167                                rm -f .gitattributes
 168                                test_expect_success "rule=$rule" '
 169                                        git config core.whitespace "$rule" &&
 170                                        test_fix "$tt$ts$ti$th"
 171                                '
 172
 173                                test_expect_success "rule=$rule (attributes)" '
 174                                        git config --unset core.whitespace &&
 175                                        echo "target whitespace=$rule" >.gitattributes &&
 176                                        test_fix "$tt$ts$ti$th"
 177                                '
 178
 179                        done
 180                done
 181        done
 182done
 183
 184create_patch () {
 185        sed -e "s/_/ /" <<-\EOF
 186                diff --git a/target b/target
 187                index e69de29..8bd6648 100644
 188                --- a/target
 189                +++ b/target
 190                @@ -0,0 +1,3 @@
 191                +An empty line follows
 192                +
 193                +A line with trailing whitespace and no newline_
 194                \ No newline at end of file
 195        EOF
 196}
 197
 198test_expect_success 'trailing whitespace & no newline at the end of file' '
 199        >target &&
 200        create_patch >patch-file &&
 201        git apply --whitespace=fix patch-file &&
 202        grep "newline$" target &&
 203        grep "^$" target
 204'
 205
 206test_expect_success 'blank at EOF with --whitespace=fix (1)' '
 207        : these can fail depending on what we did before
 208        git config --unset core.whitespace
 209        rm -f .gitattributes
 210
 211        { echo a; echo b; echo c; } >one &&
 212        git add one &&
 213        { echo a; echo b; echo c; } >expect &&
 214        { cat expect; echo; } >one &&
 215        git diff -- one >patch &&
 216
 217        git checkout one &&
 218        git apply --whitespace=fix patch &&
 219        test_cmp expect one
 220'
 221
 222test_expect_success 'blank at EOF with --whitespace=fix (2)' '
 223        { echo a; echo b; echo c; } >one &&
 224        git add one &&
 225        { echo a; echo c; } >expect &&
 226        { cat expect; echo; echo; } >one &&
 227        git diff -- one >patch &&
 228
 229        git checkout one &&
 230        git apply --whitespace=fix patch &&
 231        test_cmp expect one
 232'
 233
 234test_expect_success 'blank at EOF with --whitespace=fix (3)' '
 235        { echo a; echo b; echo; } >one &&
 236        git add one &&
 237        { echo a; echo c; echo; } >expect &&
 238        { cat expect; echo; echo; } >one &&
 239        git diff -- one >patch &&
 240
 241        git checkout one &&
 242        git apply --whitespace=fix patch &&
 243        test_cmp expect one
 244'
 245
 246test_expect_success 'blank at end of hunk, not at EOF with --whitespace=fix' '
 247        { echo a; echo b; echo; echo; echo; echo; echo; echo d; } >one &&
 248        git add one &&
 249        { echo a; echo c; echo; echo; echo; echo; echo; echo; echo d; } >expect &&
 250        cp expect one &&
 251        git diff -- one >patch &&
 252
 253        git checkout one &&
 254        git apply --whitespace=fix patch &&
 255        test_cmp expect one
 256'
 257
 258test_expect_success 'blank at EOF with --whitespace=warn' '
 259        { echo a; echo b; echo c; } >one &&
 260        git add one &&
 261        echo >>one &&
 262        cat one >expect &&
 263        git diff -- one >patch &&
 264
 265        git checkout one &&
 266        git apply --whitespace=warn patch 2>error &&
 267        test_cmp expect one &&
 268        grep "new blank line at EOF" error
 269'
 270
 271test_expect_success 'blank at EOF with --whitespace=error' '
 272        { echo a; echo b; echo c; } >one &&
 273        git add one &&
 274        cat one >expect &&
 275        echo >>one &&
 276        git diff -- one >patch &&
 277
 278        git checkout one &&
 279        test_must_fail git apply --whitespace=error patch 2>error &&
 280        test_cmp expect one &&
 281        grep "new blank line at EOF" error
 282'
 283
 284test_expect_success 'blank but not empty at EOF' '
 285        { echo a; echo b; echo c; } >one &&
 286        git add one &&
 287        echo "   " >>one &&
 288        cat one >expect &&
 289        git diff -- one >patch &&
 290
 291        git checkout one &&
 292        git apply --whitespace=warn patch 2>error &&
 293        test_cmp expect one &&
 294        grep "new blank line at EOF" error
 295'
 296
 297test_expect_success 'applying beyond EOF requires one non-blank context line' '
 298        { echo; echo; echo; echo; } >one &&
 299        git add one &&
 300        { echo b; } >>one &&
 301        git diff -- one >patch &&
 302
 303        git checkout one &&
 304        { echo a; echo; } >one &&
 305        cp one expect &&
 306        test_must_fail git apply --whitespace=fix patch &&
 307        test_cmp one expect &&
 308        test_must_fail git apply --ignore-space-change --whitespace=fix patch &&
 309        test_cmp one expect
 310'
 311
 312test_expect_success 'tons of blanks at EOF should not apply' '
 313        for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; do
 314                echo; echo; echo; echo;
 315        done >one &&
 316        git add one &&
 317        echo a >>one &&
 318        git diff -- one >patch &&
 319
 320        >one &&
 321        test_must_fail git apply --whitespace=fix patch &&
 322        test_must_fail git apply --ignore-space-change --whitespace=fix patch
 323'
 324
 325test_expect_success 'missing blank line at end with --whitespace=fix' '
 326        echo a >one &&
 327        echo >>one &&
 328        git add one &&
 329        echo b >>one &&
 330        cp one expect &&
 331        git diff -- one >patch &&
 332        echo a >one &&
 333        cp one saved-one &&
 334        test_must_fail git apply patch &&
 335        git apply --whitespace=fix patch &&
 336        test_cmp one expect &&
 337        mv saved-one one &&
 338        git apply --ignore-space-change --whitespace=fix patch &&
 339        test_cmp one expect
 340'
 341
 342test_expect_success 'two missing blank lines at end with --whitespace=fix' '
 343        { echo a; echo; echo b; echo c; } >one &&
 344        cp one no-blank-lines &&
 345        { echo; echo; } >>one &&
 346        git add one &&
 347        echo d >>one &&
 348        cp one expect &&
 349        echo >>one &&
 350        git diff -- one >patch &&
 351        cp no-blank-lines one &&
 352        test_must_fail git apply patch &&
 353        git apply --whitespace=fix patch &&
 354        test_cmp one expect &&
 355        mv no-blank-lines one &&
 356        test_must_fail git apply patch &&
 357        git apply --ignore-space-change --whitespace=fix patch &&
 358        test_cmp one expect
 359'
 360
 361test_expect_success 'shrink file with tons of missing blanks at end of file' '
 362        { echo a; echo b; echo c; } >one &&
 363        cp one no-blank-lines &&
 364        for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; do
 365                echo; echo; echo; echo;
 366        done >>one &&
 367        git add one &&
 368        echo a >one &&
 369        cp one expect &&
 370        git diff -- one >patch &&
 371        cp no-blank-lines one &&
 372        test_must_fail git apply patch &&
 373        git apply --whitespace=fix patch &&
 374        test_cmp one expect &&
 375        mv no-blank-lines one &&
 376        git apply --ignore-space-change --whitespace=fix patch &&
 377        test_cmp one expect
 378'
 379
 380test_expect_success 'missing blanks at EOF must only match blank lines' '
 381        { echo a; echo b; } >one &&
 382        git add one &&
 383        { echo c; echo d; } >>one &&
 384        git diff -- one >patch &&
 385
 386        echo a >one &&
 387        test_must_fail git apply patch
 388        test_must_fail git apply --whitespace=fix patch &&
 389        test_must_fail git apply --ignore-space-change --whitespace=fix patch
 390'
 391
 392sed -e's/Z//' >one <<EOF
 393a
 394b
 395c
 396                      Z
 397EOF
 398
 399test_expect_success 'missing blank line should match context line with spaces' '
 400        git add one &&
 401        echo d >>one &&
 402        git diff -- one >patch &&
 403        { echo a; echo b; echo c; } >one &&
 404        cp one expect &&
 405        { echo; echo d; } >>expect &&
 406        git add one &&
 407
 408        git apply --whitespace=fix patch &&
 409        test_cmp one expect
 410'
 411
 412sed -e's/Z//' >one <<EOF
 413a
 414b
 415c
 416                      Z
 417EOF
 418
 419test_expect_success 'same, but with the --ignore-space-option' '
 420        git add one &&
 421        echo d >>one &&
 422        cp one expect &&
 423        git diff -- one >patch &&
 424        { echo a; echo b; echo c; } >one &&
 425        git add one &&
 426
 427        git checkout-index -f one &&
 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 set' '
 433        git config core.whitespace cr-at-eol &&
 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        printf "d\r\n" >>one &&
 441        cp one expect &&
 442        git diff -- one >patch &&
 443        mv save-one one &&
 444
 445        git apply --ignore-space-change --whitespace=fix patch &&
 446        test_cmp one expect
 447'
 448
 449test_expect_success 'same, but with CR-LF line endings && cr-at-eol unset' '
 450        git config --unset core.whitespace &&
 451        printf "a\r\n" >one &&
 452        printf "b\r\n" >>one &&
 453        printf "c\r\n" >>one &&
 454        cp one save-one &&
 455        printf "                 \r\n" >>one
 456        git add one &&
 457        cp one expect &&
 458        printf "d\r\n" >>one &&
 459        git diff -- one >patch &&
 460        mv save-one one &&
 461        echo d >>expect &&
 462
 463        git apply --ignore-space-change --whitespace=fix patch &&
 464        test_cmp one expect
 465'
 466
 467test_done