t / t4124-apply-ws-rule.shon commit merge-one-file: fix broken merges with alternate work trees (6aaeca9)
   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        sed -e "s/_/ /g" -e "s/>/       /" <<-\EOF
  15                An_SP in an ordinary line>and a HT.
  16                >A HT.
  17                _>A SP and a HT (@).
  18                _>_A SP, a HT and a SP (@).
  19                _______Seven SP.
  20                ________Eight SP (#).
  21                _______>Seven SP and a HT (@).
  22                ________>Eight SP and a HT (@#).
  23                _______>_Seven SP, a HT and a SP (@).
  24                ________>_Eight SP, a HT and a SP (@#).
  25                _______________Fifteen SP (#).
  26                _______________>Fifteen SP and a HT (@#).
  27                ________________Sixteen SP (#).
  28                ________________>Sixteen SP and a HT (@#).
  29                _____a__Five SP, a non WS, two SP.
  30                A line with a (!) trailing SP_
  31                A line with a (!) trailing HT>
  32        EOF
  33}
  34
  35apply_patch () {
  36        >target &&
  37        sed -e "s|\([ab]\)/file|\1/target|" <patch |
  38        git apply "$@"
  39}
  40
  41test_fix () {
  42
  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                        rule=${t}trailing,${s}space,${i}indent
 134
 135                        rm -f .gitattributes
 136                        test_expect_success "rule=$rule" '
 137                                git config core.whitespace "$rule" &&
 138                                test_fix "$tt$ts$ti"
 139                        '
 140
 141                        test_expect_success "rule=$rule (attributes)" '
 142                                git config --unset core.whitespace &&
 143                                echo "target whitespace=$rule" >.gitattributes &&
 144                                test_fix "$tt$ts$ti"
 145                        '
 146
 147                done
 148        done
 149done
 150
 151create_patch () {
 152        sed -e "s/_/ /" <<-\EOF
 153                diff --git a/target b/target
 154                index e69de29..8bd6648 100644
 155                --- a/target
 156                +++ b/target
 157                @@ -0,0 +1,3 @@
 158                +An empty line follows
 159                +
 160                +A line with trailing whitespace and no newline_
 161                \ No newline at end of file
 162        EOF
 163}
 164
 165test_expect_success 'trailing whitespace & no newline at the end of file' '
 166        >target &&
 167        create_patch >patch-file &&
 168        git apply --whitespace=fix patch-file &&
 169        grep "newline$" target &&
 170        grep "^$" target
 171'
 172
 173test_expect_success 'blank at EOF with --whitespace=fix (1)' '
 174        : these can fail depending on what we did before
 175        git config --unset core.whitespace
 176        rm -f .gitattributes
 177
 178        { echo a; echo b; echo c; } >one &&
 179        git add one &&
 180        { echo a; echo b; echo c; } >expect &&
 181        { cat expect; echo; } >one &&
 182        git diff -- one >patch &&
 183
 184        git checkout one &&
 185        git apply --whitespace=fix patch &&
 186        test_cmp expect one
 187'
 188
 189test_expect_success 'blank at EOF with --whitespace=fix (2)' '
 190        { echo a; echo b; echo c; } >one &&
 191        git add one &&
 192        { echo a; echo c; } >expect &&
 193        { cat expect; echo; echo; } >one &&
 194        git diff -- one >patch &&
 195
 196        git checkout one &&
 197        git apply --whitespace=fix patch &&
 198        test_cmp expect one
 199'
 200
 201test_expect_success 'blank at EOF with --whitespace=fix (3)' '
 202        { echo a; echo b; echo; } >one &&
 203        git add one &&
 204        { echo a; echo c; echo; } >expect &&
 205        { cat expect; echo; echo; } >one &&
 206        git diff -- one >patch &&
 207
 208        git checkout one &&
 209        git apply --whitespace=fix patch &&
 210        test_cmp expect one
 211'
 212
 213test_expect_success 'blank at end of hunk, not at EOF with --whitespace=fix' '
 214        { echo a; echo b; echo; echo; echo; echo; echo; echo d; } >one &&
 215        git add one &&
 216        { echo a; echo c; echo; echo; echo; echo; echo; echo; echo d; } >expect &&
 217        cp expect one &&
 218        git diff -- one >patch &&
 219
 220        git checkout one &&
 221        git apply --whitespace=fix patch &&
 222        test_cmp expect one
 223'
 224
 225test_expect_success 'blank at EOF with --whitespace=warn' '
 226        { echo a; echo b; echo c; } >one &&
 227        git add one &&
 228        echo >>one &&
 229        cat one >expect &&
 230        git diff -- one >patch &&
 231
 232        git checkout one &&
 233        git apply --whitespace=warn patch 2>error &&
 234        test_cmp expect one &&
 235        grep "new blank line at EOF" error
 236'
 237
 238test_expect_success 'blank at EOF with --whitespace=error' '
 239        { echo a; echo b; echo c; } >one &&
 240        git add one &&
 241        cat one >expect &&
 242        echo >>one &&
 243        git diff -- one >patch &&
 244
 245        git checkout one &&
 246        test_must_fail git apply --whitespace=error patch 2>error &&
 247        test_cmp expect one &&
 248        grep "new blank line at EOF" error
 249'
 250
 251test_expect_success 'blank but not empty at EOF' '
 252        { echo a; echo b; echo c; } >one &&
 253        git add one &&
 254        echo "   " >>one &&
 255        cat one >expect &&
 256        git diff -- one >patch &&
 257
 258        git checkout one &&
 259        git apply --whitespace=warn patch 2>error &&
 260        test_cmp expect one &&
 261        grep "new blank line at EOF" error
 262'
 263
 264test_expect_success 'applying beyond EOF requires one non-blank context line' '
 265        { echo; echo; echo; echo; } >one &&
 266        git add one &&
 267        { echo b; } >>one &&
 268        git diff -- one >patch &&
 269
 270        git checkout one &&
 271        { echo a; echo; } >one &&
 272        cp one expect &&
 273        test_must_fail git apply --whitespace=fix patch &&
 274        test_cmp one expect &&
 275        test_must_fail git apply --ignore-space-change --whitespace=fix patch &&
 276        test_cmp one expect
 277'
 278
 279test_expect_success 'tons of blanks at EOF should not apply' '
 280        for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; do
 281                echo; echo; echo; echo;
 282        done >one &&
 283        git add one &&
 284        echo a >>one &&
 285        git diff -- one >patch &&
 286
 287        >one &&
 288        test_must_fail git apply --whitespace=fix patch &&
 289        test_must_fail git apply --ignore-space-change --whitespace=fix patch
 290'
 291
 292test_expect_success 'missing blank line at end with --whitespace=fix' '
 293        echo a >one &&
 294        echo >>one &&
 295        git add one &&
 296        echo b >>one &&
 297        cp one expect &&
 298        git diff -- one >patch &&
 299        echo a >one &&
 300        cp one saved-one &&
 301        test_must_fail git apply patch &&
 302        git apply --whitespace=fix patch &&
 303        test_cmp one expect &&
 304        mv saved-one one &&
 305        git apply --ignore-space-change --whitespace=fix patch &&
 306        test_cmp one expect
 307'
 308
 309test_expect_success 'two missing blank lines at end with --whitespace=fix' '
 310        { echo a; echo; echo b; echo c; } >one &&
 311        cp one no-blank-lines &&
 312        { echo; echo; } >>one &&
 313        git add one &&
 314        echo d >>one &&
 315        cp one expect &&
 316        echo >>one &&
 317        git diff -- one >patch &&
 318        cp no-blank-lines one &&
 319        test_must_fail git apply patch &&
 320        git apply --whitespace=fix patch &&
 321        test_cmp one expect &&
 322        mv no-blank-lines one &&
 323        test_must_fail git apply patch &&
 324        git apply --ignore-space-change --whitespace=fix patch &&
 325        test_cmp one expect
 326'
 327
 328test_expect_success 'shrink file with tons of missing blanks at end of file' '
 329        { echo a; echo b; echo c; } >one &&
 330        cp one no-blank-lines &&
 331        for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; do
 332                echo; echo; echo; echo;
 333        done >>one &&
 334        git add one &&
 335        echo a >one &&
 336        cp one expect &&
 337        git diff -- one >patch &&
 338        cp no-blank-lines one &&
 339        test_must_fail git apply patch &&
 340        git apply --whitespace=fix patch &&
 341        test_cmp one expect &&
 342        mv no-blank-lines one &&
 343        git apply --ignore-space-change --whitespace=fix patch &&
 344        test_cmp one expect
 345'
 346
 347test_expect_success 'missing blanks at EOF must only match blank lines' '
 348        { echo a; echo b; } >one &&
 349        git add one &&
 350        { echo c; echo d; } >>one &&
 351        git diff -- one >patch &&
 352
 353        echo a >one &&
 354        test_must_fail git apply patch
 355        test_must_fail git apply --whitespace=fix patch &&
 356        test_must_fail git apply --ignore-space-change --whitespace=fix patch
 357'
 358
 359sed -e's/Z//' >one <<EOF
 360a
 361b
 362c
 363                      Z
 364EOF
 365
 366test_expect_success 'missing blank line should match context line with spaces' '
 367        git add one &&
 368        echo d >>one &&
 369        git diff -- one >patch &&
 370        { echo a; echo b; echo c; } >one &&
 371        cp one expect &&
 372        { echo; echo d; } >>expect &&
 373        git add one &&
 374
 375        git apply --whitespace=fix patch &&
 376        test_cmp one expect
 377'
 378
 379sed -e's/Z//' >one <<EOF
 380a
 381b
 382c
 383                      Z
 384EOF
 385
 386test_expect_success 'same, but with the --ignore-space-option' '
 387        git add one &&
 388        echo d >>one &&
 389        cp one expect &&
 390        git diff -- one >patch &&
 391        { echo a; echo b; echo c; } >one &&
 392        git add one &&
 393
 394        git checkout-index -f one &&
 395        git apply --ignore-space-change --whitespace=fix patch &&
 396        test_cmp one expect
 397'
 398
 399test_expect_success 'same, but with CR-LF line endings && cr-at-eol set' '
 400        git config core.whitespace cr-at-eol &&
 401        printf "a\r\n" >one &&
 402        printf "b\r\n" >>one &&
 403        printf "c\r\n" >>one &&
 404        cp one save-one &&
 405        printf "                 \r\n" >>one
 406        git add one &&
 407        printf "d\r\n" >>one &&
 408        cp one expect &&
 409        git diff -- one >patch &&
 410        mv save-one one &&
 411
 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 unset' '
 417        git config --unset core.whitespace &&
 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        cp one expect &&
 425        printf "d\r\n" >>one &&
 426        git diff -- one >patch &&
 427        mv save-one one &&
 428        echo d >>expect &&
 429
 430        git apply --ignore-space-change --whitespace=fix patch &&
 431        test_cmp one expect
 432'
 433
 434test_done