8d46df6c3abd0643031106dac15758fdbe5f2ccd
   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 'shrink file with tons of missing blanks at end of file' '
 334        { echo a; echo b; echo c; } >one &&
 335        cp one no-blank-lines &&
 336        for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; do
 337                echo; echo; echo; echo;
 338        done >>one &&
 339        git add one &&
 340        echo a >one &&
 341        cp one expect &&
 342        git diff -- one >patch &&
 343        cp no-blank-lines one &&
 344        test_must_fail git apply patch &&
 345        git apply --whitespace=fix patch &&
 346        test_cmp one expect &&
 347        mv no-blank-lines one &&
 348        git apply --ignore-space-change --whitespace=fix patch &&
 349        test_cmp one expect
 350'
 351
 352test_expect_success 'missing blanks at EOF must only match blank lines' '
 353        { echo a; echo b; } >one &&
 354        git add one &&
 355        { echo c; echo d; } >>one &&
 356        git diff -- one >patch &&
 357
 358        echo a >one &&
 359        test_must_fail git apply patch
 360        test_must_fail git apply --whitespace=fix patch &&
 361        test_must_fail git apply --ignore-space-change --whitespace=fix patch
 362'
 363
 364sed -e's/Z//' >one <<EOF
 365a
 366b
 367c
 368                      Z
 369EOF
 370
 371test_expect_success 'missing blank line should match context line with spaces' '
 372        git add one &&
 373        echo d >>one &&
 374        git diff -- one >patch &&
 375        { echo a; echo b; echo c; } >one &&
 376        cp one expect &&
 377        { echo; echo d; } >>expect &&
 378        git add one &&
 379
 380        git apply --whitespace=fix patch &&
 381        test_cmp one expect
 382'
 383
 384sed -e's/Z//' >one <<EOF
 385a
 386b
 387c
 388                      Z
 389EOF
 390
 391test_expect_success 'same, but with the --ignore-space-option' '
 392        git add one &&
 393        echo d >>one &&
 394        cp one expect &&
 395        git diff -- one >patch &&
 396        { echo a; echo b; echo c; } >one &&
 397        git add one &&
 398
 399        git checkout-index -f one &&
 400        git apply --ignore-space-change --whitespace=fix patch &&
 401        test_cmp one expect
 402'
 403
 404test_expect_success 'same, but with CR-LF line endings && cr-at-eol set' '
 405        git config core.whitespace cr-at-eol &&
 406        printf "a\r\n" >one &&
 407        printf "b\r\n" >>one &&
 408        printf "c\r\n" >>one &&
 409        cp one save-one &&
 410        printf "                 \r\n" >>one
 411        git add one &&
 412        printf "d\r\n" >>one &&
 413        cp one expect &&
 414        git diff -- one >patch &&
 415        mv save-one one &&
 416
 417        git apply --ignore-space-change --whitespace=fix patch &&
 418        test_cmp one expect
 419'
 420
 421test_expect_success 'same, but with CR-LF line endings && cr-at-eol unset' '
 422        git config --unset core.whitespace &&
 423        printf "a\r\n" >one &&
 424        printf "b\r\n" >>one &&
 425        printf "c\r\n" >>one &&
 426        cp one save-one &&
 427        printf "                 \r\n" >>one
 428        git add one &&
 429        cp one expect &&
 430        printf "d\r\n" >>one &&
 431        git diff -- one >patch &&
 432        mv save-one one &&
 433        echo d >>expect &&
 434
 435        git apply --ignore-space-change --whitespace=fix patch &&
 436        test_cmp one expect
 437'
 438
 439test_done