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