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