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