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