t / t4124-apply-ws-rule.shon commit Merge branch 'jn/fsck-ident' (4cbf42e)
   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
 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        : these can fail depending on what we did before
 180        git config --unset core.whitespace
 181        rm -f .gitattributes
 182
 183        { echo a; echo b; echo c; } >one &&
 184        git add one &&
 185        { echo a; echo b; echo c; } >expect &&
 186        { cat expect; echo; } >one &&
 187        git diff -- one >patch &&
 188
 189        git checkout one &&
 190        git apply --whitespace=fix patch &&
 191        test_cmp expect one
 192'
 193
 194test_expect_success 'blank at EOF with --whitespace=fix (2)' '
 195        { echo a; echo b; echo c; } >one &&
 196        git add one &&
 197        { echo a; echo c; } >expect &&
 198        { cat expect; echo; echo; } >one &&
 199        git diff -- one >patch &&
 200
 201        git checkout one &&
 202        git apply --whitespace=fix patch &&
 203        test_cmp expect one
 204'
 205
 206test_expect_success 'blank at EOF with --whitespace=fix (3)' '
 207        { echo a; echo b; echo; } >one &&
 208        git add one &&
 209        { echo a; echo c; echo; } >expect &&
 210        { cat expect; echo; echo; } >one &&
 211        git diff -- one >patch &&
 212
 213        git checkout one &&
 214        git apply --whitespace=fix patch &&
 215        test_cmp expect one
 216'
 217
 218test_expect_success 'blank at end of hunk, not at EOF with --whitespace=fix' '
 219        { echo a; echo b; echo; echo; echo; echo; echo; echo d; } >one &&
 220        git add one &&
 221        { echo a; echo c; echo; echo; echo; echo; echo; echo; echo d; } >expect &&
 222        cp expect one &&
 223        git diff -- one >patch &&
 224
 225        git checkout one &&
 226        git apply --whitespace=fix patch &&
 227        test_cmp expect one
 228'
 229
 230test_expect_success 'blank at EOF with --whitespace=warn' '
 231        { echo a; echo b; echo c; } >one &&
 232        git add one &&
 233        echo >>one &&
 234        cat one >expect &&
 235        git diff -- one >patch &&
 236
 237        git checkout one &&
 238        git apply --whitespace=warn patch 2>error &&
 239        test_cmp expect one &&
 240        grep "new blank line at EOF" error
 241'
 242
 243test_expect_success 'blank at EOF with --whitespace=error' '
 244        { echo a; echo b; echo c; } >one &&
 245        git add one &&
 246        cat one >expect &&
 247        echo >>one &&
 248        git diff -- one >patch &&
 249
 250        git checkout one &&
 251        test_must_fail git apply --whitespace=error patch 2>error &&
 252        test_cmp expect one &&
 253        grep "new blank line at EOF" error
 254'
 255
 256test_expect_success 'blank but not empty at EOF' '
 257        { echo a; echo b; echo c; } >one &&
 258        git add one &&
 259        echo "   " >>one &&
 260        cat one >expect &&
 261        git diff -- one >patch &&
 262
 263        git checkout one &&
 264        git apply --whitespace=warn patch 2>error &&
 265        test_cmp expect one &&
 266        grep "new blank line at EOF" error
 267'
 268
 269test_expect_success 'applying beyond EOF requires one non-blank context line' '
 270        { echo; echo; echo; echo; } >one &&
 271        git add one &&
 272        { echo b; } >>one &&
 273        git diff -- one >patch &&
 274
 275        git checkout one &&
 276        { echo a; echo; } >one &&
 277        cp one expect &&
 278        test_must_fail git apply --whitespace=fix patch &&
 279        test_cmp one expect &&
 280        test_must_fail git apply --ignore-space-change --whitespace=fix patch &&
 281        test_cmp one expect
 282'
 283
 284test_expect_success 'tons of blanks at EOF should not apply' '
 285        for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; do
 286                echo; echo; echo; echo;
 287        done >one &&
 288        git add one &&
 289        echo a >>one &&
 290        git diff -- one >patch &&
 291
 292        >one &&
 293        test_must_fail git apply --whitespace=fix patch &&
 294        test_must_fail git apply --ignore-space-change --whitespace=fix patch
 295'
 296
 297test_expect_success 'missing blank line at end with --whitespace=fix' '
 298        echo a >one &&
 299        echo >>one &&
 300        git add one &&
 301        echo b >>one &&
 302        cp one expect &&
 303        git diff -- one >patch &&
 304        echo a >one &&
 305        cp one saved-one &&
 306        test_must_fail git apply patch &&
 307        git apply --whitespace=fix patch &&
 308        test_cmp one expect &&
 309        mv saved-one one &&
 310        git apply --ignore-space-change --whitespace=fix patch &&
 311        test_cmp one expect
 312'
 313
 314test_expect_success 'two missing blank lines at end with --whitespace=fix' '
 315        { echo a; echo; echo b; echo c; } >one &&
 316        cp one no-blank-lines &&
 317        { echo; echo; } >>one &&
 318        git add one &&
 319        echo d >>one &&
 320        cp one expect &&
 321        echo >>one &&
 322        git diff -- one >patch &&
 323        cp no-blank-lines one &&
 324        test_must_fail git apply patch &&
 325        git apply --whitespace=fix patch &&
 326        test_cmp one expect &&
 327        mv no-blank-lines one &&
 328        test_must_fail git apply patch &&
 329        git apply --ignore-space-change --whitespace=fix patch &&
 330        test_cmp one expect
 331'
 332
 333test_expect_success 'missing blank line at end, insert before end, --whitespace=fix' '
 334        { echo a; echo; } >one &&
 335        git add one &&
 336        { echo b; echo a; echo; } >one &&
 337        cp one expect &&
 338        git diff -- one >patch &&
 339        echo a >one &&
 340        test_must_fail git apply patch &&
 341        git apply --whitespace=fix patch &&
 342        test_cmp one expect
 343'
 344
 345test_expect_success 'shrink file with tons of missing blanks at end of file' '
 346        { echo a; echo b; echo c; } >one &&
 347        cp one no-blank-lines &&
 348        for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; do
 349                echo; echo; echo; echo;
 350        done >>one &&
 351        git add one &&
 352        echo a >one &&
 353        cp one expect &&
 354        git diff -- one >patch &&
 355        cp no-blank-lines one &&
 356        test_must_fail git apply patch &&
 357        git apply --whitespace=fix patch &&
 358        test_cmp one expect &&
 359        mv no-blank-lines one &&
 360        git apply --ignore-space-change --whitespace=fix patch &&
 361        test_cmp one expect
 362'
 363
 364test_expect_success 'missing blanks at EOF must only match blank lines' '
 365        { echo a; echo b; } >one &&
 366        git add one &&
 367        { echo c; echo d; } >>one &&
 368        git diff -- one >patch &&
 369
 370        echo a >one &&
 371        test_must_fail git apply patch
 372        test_must_fail git apply --whitespace=fix patch &&
 373        test_must_fail git apply --ignore-space-change --whitespace=fix patch
 374'
 375
 376sed -e's/Z//' >one <<EOF
 377a
 378b
 379c
 380                      Z
 381EOF
 382
 383test_expect_success 'missing blank line should match context line with spaces' '
 384        git add one &&
 385        echo d >>one &&
 386        git diff -- one >patch &&
 387        { echo a; echo b; echo c; } >one &&
 388        cp one expect &&
 389        { echo; echo d; } >>expect &&
 390        git add one &&
 391
 392        git apply --whitespace=fix patch &&
 393        test_cmp one expect
 394'
 395
 396sed -e's/Z//' >one <<EOF
 397a
 398b
 399c
 400                      Z
 401EOF
 402
 403test_expect_success 'same, but with the --ignore-space-option' '
 404        git add one &&
 405        echo d >>one &&
 406        cp one expect &&
 407        git diff -- one >patch &&
 408        { echo a; echo b; echo c; } >one &&
 409        git add one &&
 410
 411        git checkout-index -f one &&
 412        git apply --ignore-space-change --whitespace=fix patch &&
 413        test_cmp one expect
 414'
 415
 416test_expect_success 'same, but with CR-LF line endings && cr-at-eol set' '
 417        git config core.whitespace cr-at-eol &&
 418        printf "a\r\n" >one &&
 419        printf "b\r\n" >>one &&
 420        printf "c\r\n" >>one &&
 421        cp one save-one &&
 422        printf "                 \r\n" >>one
 423        git add one &&
 424        printf "d\r\n" >>one &&
 425        cp one expect &&
 426        git diff -- one >patch &&
 427        mv save-one one &&
 428
 429        git apply --ignore-space-change --whitespace=fix patch &&
 430        test_cmp one expect
 431'
 432
 433test_expect_success 'same, but with CR-LF line endings && cr-at-eol unset' '
 434        git config --unset core.whitespace &&
 435        printf "a\r\n" >one &&
 436        printf "b\r\n" >>one &&
 437        printf "c\r\n" >>one &&
 438        cp one save-one &&
 439        printf "                 \r\n" >>one
 440        git add one &&
 441        cp one expect &&
 442        printf "d\r\n" >>one &&
 443        git diff -- one >patch &&
 444        mv save-one one &&
 445        echo d >>expect &&
 446
 447        git apply --ignore-space-change --whitespace=fix patch &&
 448        test_cmp one expect
 449'
 450
 451test_done