t / t0008-ignores.shon commit t0008: avoid brace expansion (6f53fea)
   1#!/bin/sh
   2
   3test_description=check-ignore
   4
   5. ./test-lib.sh
   6
   7init_vars () {
   8        global_excludes="$(pwd)/global-excludes"
   9}
  10
  11enable_global_excludes () {
  12        init_vars &&
  13        git config core.excludesfile "$global_excludes"
  14}
  15
  16expect_in () {
  17        dest="$HOME/expected-$1" text="$2"
  18        if test -z "$text"
  19        then
  20                >"$dest" # avoid newline
  21        else
  22                echo "$text" >"$dest"
  23        fi
  24}
  25
  26expect () {
  27        expect_in stdout "$1"
  28}
  29
  30expect_from_stdin () {
  31        cat >"$HOME/expected-stdout"
  32}
  33
  34test_stderr () {
  35        expected="$1"
  36        expect_in stderr "$1" &&
  37        test_cmp "$HOME/expected-stderr" "$HOME/stderr"
  38}
  39
  40stderr_contains () {
  41        regexp="$1"
  42        if grep "$regexp" "$HOME/stderr"
  43        then
  44                return 0
  45        else
  46                echo "didn't find /$regexp/ in $HOME/stderr"
  47                cat "$HOME/stderr"
  48                return 1
  49        fi
  50}
  51
  52stderr_empty_on_success () {
  53        expect_code="$1"
  54        if test $expect_code = 0
  55        then
  56                test_stderr ""
  57        else
  58                # If we expect failure then stderr might or might not be empty
  59                # due to --quiet - the caller can check its contents
  60                return 0
  61        fi
  62}
  63
  64test_check_ignore () {
  65        args="$1" expect_code="${2:-0}" global_args="$3"
  66
  67        init_vars &&
  68        rm -f "$HOME/stdout" "$HOME/stderr" "$HOME/cmd" &&
  69        echo git $global_args check-ignore $quiet_opt $verbose_opt $args \
  70                >"$HOME/cmd" &&
  71        test_expect_code "$expect_code" \
  72                git $global_args check-ignore $quiet_opt $verbose_opt $args \
  73                >"$HOME/stdout" 2>"$HOME/stderr" &&
  74        test_cmp "$HOME/expected-stdout" "$HOME/stdout" &&
  75        stderr_empty_on_success "$expect_code"
  76}
  77
  78test_expect_success_multi () {
  79        prereq=
  80        if test $# -eq 4
  81        then
  82                prereq=$1
  83                shift
  84        fi
  85        testname="$1" expect_verbose="$2" code="$3"
  86
  87        expect=$( echo "$expect_verbose" | sed -e 's/.* //' )
  88
  89        test_expect_success $prereq "$testname" '
  90                expect "$expect" &&
  91                eval "$code"
  92        '
  93
  94        for quiet_opt in '-q' '--quiet'
  95        do
  96                test_expect_success $prereq "$testname${quiet_opt:+ with $quiet_opt}" "
  97                        expect '' &&
  98                        $code
  99                "
 100        done
 101        quiet_opt=
 102
 103        for verbose_opt in '-v' '--verbose'
 104        do
 105                test_expect_success $prereq "$testname${verbose_opt:+ with $verbose_opt}" "
 106                        expect '$expect_verbose' &&
 107                        $code
 108                "
 109        done
 110        verbose_opt=
 111}
 112
 113test_expect_success 'setup' '
 114        init_vars &&
 115        mkdir -p a/b/ignored-dir a/submodule b &&
 116        if test_have_prereq SYMLINKS
 117        then
 118                ln -s b a/symlink
 119        fi &&
 120        (
 121                cd a/submodule &&
 122                git init &&
 123                echo a >a &&
 124                git add a &&
 125                git commit -m"commit in submodule"
 126        ) &&
 127        git add a/submodule &&
 128        cat <<-\EOF >.gitignore &&
 129                one
 130                ignored-*
 131        EOF
 132        for dir in . a
 133        do
 134                : >$dir/not-ignored &&
 135                : >$dir/ignored-and-untracked &&
 136                : >$dir/ignored-but-in-index
 137        done &&
 138        git add -f ignored-but-in-index a/ignored-but-in-index &&
 139        cat <<-\EOF >a/.gitignore &&
 140                two*
 141                *three
 142        EOF
 143        cat <<-\EOF >a/b/.gitignore &&
 144                four
 145                five
 146                # this comment should affect the line numbers
 147                six
 148                ignored-dir/
 149                # and so should this blank line:
 150
 151                !on*
 152                !two
 153        EOF
 154        echo "seven" >a/b/ignored-dir/.gitignore &&
 155        test -n "$HOME" &&
 156        cat <<-\EOF >"$global_excludes" &&
 157                globalone
 158                !globaltwo
 159                globalthree
 160        EOF
 161        cat <<-\EOF >>.git/info/exclude
 162                per-repo
 163        EOF
 164'
 165
 166############################################################################
 167#
 168# test invalid inputs
 169
 170test_expect_success_multi 'empty command line' '' '
 171        test_check_ignore "" 128 &&
 172        stderr_contains "fatal: no path specified"
 173'
 174
 175test_expect_success_multi '--stdin with empty STDIN' '' '
 176        test_check_ignore "--stdin" 1 </dev/null &&
 177        if test -n "$quiet_opt"; then
 178                test_stderr ""
 179        else
 180                test_stderr "no pathspec given."
 181        fi
 182'
 183
 184test_expect_success '-q with multiple args' '
 185        expect "" &&
 186        test_check_ignore "-q one two" 128 &&
 187        stderr_contains "fatal: --quiet is only valid with a single pathname"
 188'
 189
 190test_expect_success '--quiet with multiple args' '
 191        expect "" &&
 192        test_check_ignore "--quiet one two" 128 &&
 193        stderr_contains "fatal: --quiet is only valid with a single pathname"
 194'
 195
 196for verbose_opt in '-v' '--verbose'
 197do
 198        for quiet_opt in '-q' '--quiet'
 199        do
 200                test_expect_success "$quiet_opt $verbose_opt" "
 201                        expect '' &&
 202                        test_check_ignore '$quiet_opt $verbose_opt foo' 128 &&
 203                        stderr_contains 'fatal: cannot have both --quiet and --verbose'
 204                "
 205        done
 206done
 207
 208test_expect_success '--quiet with multiple args' '
 209        expect "" &&
 210        test_check_ignore "--quiet one two" 128 &&
 211        stderr_contains "fatal: --quiet is only valid with a single pathname"
 212'
 213
 214test_expect_success_multi 'erroneous use of --' '' '
 215        test_check_ignore "--" 128 &&
 216        stderr_contains "fatal: no path specified"
 217'
 218
 219test_expect_success_multi '--stdin with superfluous arg' '' '
 220        test_check_ignore "--stdin foo" 128 &&
 221        stderr_contains "fatal: cannot specify pathnames with --stdin"
 222'
 223
 224test_expect_success_multi '--stdin -z with superfluous arg' '' '
 225        test_check_ignore "--stdin -z foo" 128 &&
 226        stderr_contains "fatal: cannot specify pathnames with --stdin"
 227'
 228
 229test_expect_success_multi '-z without --stdin' '' '
 230        test_check_ignore "-z" 128 &&
 231        stderr_contains "fatal: -z only makes sense with --stdin"
 232'
 233
 234test_expect_success_multi '-z without --stdin and superfluous arg' '' '
 235        test_check_ignore "-z foo" 128 &&
 236        stderr_contains "fatal: -z only makes sense with --stdin"
 237'
 238
 239test_expect_success_multi 'needs work tree' '' '
 240        (
 241                cd .git &&
 242                test_check_ignore "foo" 128
 243        ) &&
 244        stderr_contains "fatal: This operation must be run in a work tree"
 245'
 246
 247############################################################################
 248#
 249# test standard ignores
 250
 251# First make sure that the presence of a file in the working tree
 252# does not impact results, but that the presence of a file in the
 253# index does.
 254
 255for subdir in '' 'a/'
 256do
 257        if test -z "$subdir"
 258        then
 259                where="at top-level"
 260        else
 261                where="in subdir $subdir"
 262        fi
 263
 264        test_expect_success_multi "non-existent file $where not ignored" '' "
 265                test_check_ignore '${subdir}non-existent' 1
 266        "
 267
 268        test_expect_success_multi "non-existent file $where ignored" \
 269                ".gitignore:1:one       ${subdir}one" "
 270                test_check_ignore '${subdir}one'
 271        "
 272
 273        test_expect_success_multi "existing untracked file $where not ignored" '' "
 274                test_check_ignore '${subdir}not-ignored' 1
 275        "
 276
 277        test_expect_success_multi "existing tracked file $where not ignored" '' "
 278                test_check_ignore '${subdir}ignored-but-in-index' 1
 279        "
 280
 281        test_expect_success_multi "existing untracked file $where ignored" \
 282                ".gitignore:2:ignored-* ${subdir}ignored-and-untracked" "
 283                test_check_ignore '${subdir}ignored-and-untracked'
 284        "
 285done
 286
 287# Having established the above, from now on we mostly test against
 288# files which do not exist in the working tree or index.
 289
 290test_expect_success 'sub-directory local ignore' '
 291        expect "a/3-three" &&
 292        test_check_ignore "a/3-three a/three-not-this-one"
 293'
 294
 295test_expect_success 'sub-directory local ignore with --verbose'  '
 296        expect "a/.gitignore:2:*three   a/3-three" &&
 297        test_check_ignore "--verbose a/3-three a/three-not-this-one"
 298'
 299
 300test_expect_success 'local ignore inside a sub-directory' '
 301        expect "3-three" &&
 302        (
 303                cd a &&
 304                test_check_ignore "3-three three-not-this-one"
 305        )
 306'
 307test_expect_success 'local ignore inside a sub-directory with --verbose' '
 308        expect "a/.gitignore:2:*three   3-three" &&
 309        (
 310                cd a &&
 311                test_check_ignore "--verbose 3-three three-not-this-one"
 312        )
 313'
 314
 315test_expect_success_multi 'nested include' \
 316        'a/b/.gitignore:8:!on*  a/b/one' '
 317        test_check_ignore "a/b/one"
 318'
 319
 320############################################################################
 321#
 322# test ignored sub-directories
 323
 324test_expect_success_multi 'ignored sub-directory' \
 325        'a/b/.gitignore:5:ignored-dir/  a/b/ignored-dir' '
 326        test_check_ignore "a/b/ignored-dir"
 327'
 328
 329test_expect_success 'multiple files inside ignored sub-directory' '
 330        expect_from_stdin <<-\EOF &&
 331                a/b/ignored-dir/foo
 332                a/b/ignored-dir/twoooo
 333                a/b/ignored-dir/seven
 334        EOF
 335        test_check_ignore "a/b/ignored-dir/foo a/b/ignored-dir/twoooo a/b/ignored-dir/seven"
 336'
 337
 338test_expect_success 'multiple files inside ignored sub-directory with -v' '
 339        expect_from_stdin <<-\EOF &&
 340                a/b/.gitignore:5:ignored-dir/   a/b/ignored-dir/foo
 341                a/b/.gitignore:5:ignored-dir/   a/b/ignored-dir/twoooo
 342                a/b/.gitignore:5:ignored-dir/   a/b/ignored-dir/seven
 343        EOF
 344        test_check_ignore "-v a/b/ignored-dir/foo a/b/ignored-dir/twoooo a/b/ignored-dir/seven"
 345'
 346
 347test_expect_success 'cd to ignored sub-directory' '
 348        expect_from_stdin <<-\EOF &&
 349                foo
 350                twoooo
 351                ../one
 352                seven
 353                ../../one
 354        EOF
 355        (
 356                cd a/b/ignored-dir &&
 357                test_check_ignore "foo twoooo ../one seven ../../one"
 358        )
 359'
 360
 361test_expect_success 'cd to ignored sub-directory with -v' '
 362        expect_from_stdin <<-\EOF &&
 363                a/b/.gitignore:5:ignored-dir/   foo
 364                a/b/.gitignore:5:ignored-dir/   twoooo
 365                a/b/.gitignore:8:!on*   ../one
 366                a/b/.gitignore:5:ignored-dir/   seven
 367                .gitignore:1:one        ../../one
 368        EOF
 369        (
 370                cd a/b/ignored-dir &&
 371                test_check_ignore "-v foo twoooo ../one seven ../../one"
 372        )
 373'
 374
 375############################################################################
 376#
 377# test handling of symlinks
 378
 379test_expect_success_multi SYMLINKS 'symlink' '' '
 380        test_check_ignore "a/symlink" 1
 381'
 382
 383test_expect_success_multi SYMLINKS 'beyond a symlink' '' '
 384        test_check_ignore "a/symlink/foo" 128 &&
 385        test_stderr "fatal: '\''a/symlink/foo'\'' is beyond a symbolic link"
 386'
 387
 388test_expect_success_multi SYMLINKS 'beyond a symlink from subdirectory' '' '
 389        (
 390                cd a &&
 391                test_check_ignore "symlink/foo" 128
 392        ) &&
 393        test_stderr "fatal: '\''symlink/foo'\'' is beyond a symbolic link"
 394'
 395
 396############################################################################
 397#
 398# test handling of submodules
 399
 400test_expect_success_multi 'submodule' '' '
 401        test_check_ignore "a/submodule/one" 128 &&
 402        test_stderr "fatal: Path '\''a/submodule/one'\'' is in submodule '\''a/submodule'\''"
 403'
 404
 405test_expect_success_multi 'submodule from subdirectory' '' '
 406        (
 407                cd a &&
 408                test_check_ignore "submodule/one" 128
 409        ) &&
 410        test_stderr "fatal: Path '\''a/submodule/one'\'' is in submodule '\''a/submodule'\''"
 411'
 412
 413############################################################################
 414#
 415# test handling of global ignore files
 416
 417test_expect_success 'global ignore not yet enabled' '
 418        expect_from_stdin <<-\EOF &&
 419                .git/info/exclude:7:per-repo    per-repo
 420                a/.gitignore:2:*three   a/globalthree
 421                .git/info/exclude:7:per-repo    a/per-repo
 422        EOF
 423        test_check_ignore "-v globalone per-repo a/globalthree a/per-repo not-ignored a/globaltwo"
 424'
 425
 426test_expect_success 'global ignore' '
 427        enable_global_excludes &&
 428        expect_from_stdin <<-\EOF &&
 429                globalone
 430                per-repo
 431                globalthree
 432                a/globalthree
 433                a/per-repo
 434                globaltwo
 435        EOF
 436        test_check_ignore "globalone per-repo globalthree a/globalthree a/per-repo not-ignored globaltwo"
 437'
 438
 439test_expect_success 'global ignore with -v' '
 440        enable_global_excludes &&
 441        expect_from_stdin <<-EOF &&
 442                $global_excludes:1:globalone    globalone
 443                .git/info/exclude:7:per-repo    per-repo
 444                $global_excludes:3:globalthree  globalthree
 445                a/.gitignore:2:*three   a/globalthree
 446                .git/info/exclude:7:per-repo    a/per-repo
 447                $global_excludes:2:!globaltwo   globaltwo
 448        EOF
 449        test_check_ignore "-v globalone per-repo globalthree a/globalthree a/per-repo not-ignored globaltwo"
 450'
 451
 452############################################################################
 453#
 454# test --stdin
 455
 456cat <<-\EOF >stdin
 457        one
 458        not-ignored
 459        a/one
 460        a/not-ignored
 461        a/b/on
 462        a/b/one
 463        a/b/one one
 464        "a/b/one two"
 465        "a/b/one\"three"
 466        a/b/not-ignored
 467        a/b/two
 468        a/b/twooo
 469        globaltwo
 470        a/globaltwo
 471        a/b/globaltwo
 472        b/globaltwo
 473EOF
 474cat <<-\EOF >expected-default
 475        one
 476        a/one
 477        a/b/on
 478        a/b/one
 479        a/b/one one
 480        a/b/one two
 481        "a/b/one\"three"
 482        a/b/two
 483        a/b/twooo
 484        globaltwo
 485        a/globaltwo
 486        a/b/globaltwo
 487        b/globaltwo
 488EOF
 489cat <<-EOF >expected-verbose
 490        .gitignore:1:one        one
 491        .gitignore:1:one        a/one
 492        a/b/.gitignore:8:!on*   a/b/on
 493        a/b/.gitignore:8:!on*   a/b/one
 494        a/b/.gitignore:8:!on*   a/b/one one
 495        a/b/.gitignore:8:!on*   a/b/one two
 496        a/b/.gitignore:8:!on*   "a/b/one\"three"
 497        a/b/.gitignore:9:!two   a/b/two
 498        a/.gitignore:1:two*     a/b/twooo
 499        $global_excludes:2:!globaltwo   globaltwo
 500        $global_excludes:2:!globaltwo   a/globaltwo
 501        $global_excludes:2:!globaltwo   a/b/globaltwo
 502        $global_excludes:2:!globaltwo   b/globaltwo
 503EOF
 504
 505sed -e 's/^"//' -e 's/\\//' -e 's/"$//' stdin | \
 506        tr "\n" "\0" >stdin0
 507sed -e 's/^"//' -e 's/\\//' -e 's/"$//' expected-default | \
 508        tr "\n" "\0" >expected-default0
 509sed -e 's/      "/      /' -e 's/\\//' -e 's/"$//' expected-verbose | \
 510        tr ":\t\n" "\0" >expected-verbose0
 511
 512test_expect_success '--stdin' '
 513        expect_from_stdin <expected-default &&
 514        test_check_ignore "--stdin" <stdin
 515'
 516
 517test_expect_success '--stdin -q' '
 518        expect "" &&
 519        test_check_ignore "-q --stdin" <stdin
 520'
 521
 522test_expect_success '--stdin -v' '
 523        expect_from_stdin <expected-verbose &&
 524        test_check_ignore "-v --stdin" <stdin
 525'
 526
 527for opts in '--stdin -z' '-z --stdin'
 528do
 529        test_expect_success "$opts" "
 530                expect_from_stdin <expected-default0 &&
 531                test_check_ignore '$opts' <stdin0
 532        "
 533
 534        test_expect_success "$opts -q" "
 535                expect "" &&
 536                test_check_ignore '-q $opts' <stdin0
 537        "
 538
 539        test_expect_success "$opts -v" "
 540                expect_from_stdin <expected-verbose0 &&
 541                test_check_ignore '-v $opts' <stdin0
 542        "
 543done
 544
 545cat <<-\EOF >stdin
 546        ../one
 547        ../not-ignored
 548        one
 549        not-ignored
 550        b/on
 551        b/one
 552        b/one one
 553        "b/one two"
 554        "b/one\"three"
 555        b/two
 556        b/not-ignored
 557        b/twooo
 558        ../globaltwo
 559        globaltwo
 560        b/globaltwo
 561        ../b/globaltwo
 562EOF
 563cat <<-\EOF >expected-default
 564        ../one
 565        one
 566        b/on
 567        b/one
 568        b/one one
 569        b/one two
 570        "b/one\"three"
 571        b/two
 572        b/twooo
 573        ../globaltwo
 574        globaltwo
 575        b/globaltwo
 576        ../b/globaltwo
 577EOF
 578cat <<-EOF >expected-verbose
 579        .gitignore:1:one        ../one
 580        .gitignore:1:one        one
 581        a/b/.gitignore:8:!on*   b/on
 582        a/b/.gitignore:8:!on*   b/one
 583        a/b/.gitignore:8:!on*   b/one one
 584        a/b/.gitignore:8:!on*   b/one two
 585        a/b/.gitignore:8:!on*   "b/one\"three"
 586        a/b/.gitignore:9:!two   b/two
 587        a/.gitignore:1:two*     b/twooo
 588        $global_excludes:2:!globaltwo   ../globaltwo
 589        $global_excludes:2:!globaltwo   globaltwo
 590        $global_excludes:2:!globaltwo   b/globaltwo
 591        $global_excludes:2:!globaltwo   ../b/globaltwo
 592EOF
 593
 594sed -e 's/^"//' -e 's/\\//' -e 's/"$//' stdin | \
 595        tr "\n" "\0" >stdin0
 596sed -e 's/^"//' -e 's/\\//' -e 's/"$//' expected-default | \
 597        tr "\n" "\0" >expected-default0
 598sed -e 's/      "/      /' -e 's/\\//' -e 's/"$//' expected-verbose | \
 599        tr ":\t\n" "\0" >expected-verbose0
 600
 601test_expect_success '--stdin from subdirectory' '
 602        expect_from_stdin <expected-default &&
 603        (
 604                cd a &&
 605                test_check_ignore "--stdin" <../stdin
 606        )
 607'
 608
 609test_expect_success '--stdin from subdirectory with -v' '
 610        expect_from_stdin <expected-verbose &&
 611        (
 612                cd a &&
 613                test_check_ignore "--stdin -v" <../stdin
 614        )
 615'
 616
 617for opts in '--stdin -z' '-z --stdin'
 618do
 619        test_expect_success "$opts from subdirectory" '
 620                expect_from_stdin <expected-default0 &&
 621                (
 622                        cd a &&
 623                        test_check_ignore "'"$opts"'" <../stdin0
 624                )
 625        '
 626
 627        test_expect_success "$opts from subdirectory with -v" '
 628                expect_from_stdin <expected-verbose0 &&
 629                (
 630                        cd a &&
 631                        test_check_ignore "'"$opts"' -v" <../stdin0
 632                )
 633        '
 634done
 635
 636
 637test_done