3 test_description=check-ignore
8 global_excludes="$(pwd)/global-excludes"
11 enable_global_excludes () {
13 git config core.excludesfile "$global_excludes"
17 dest="$HOME/expected-$1" text="$2"
20 >"$dest" # avoid newline
30 expect_from_stdin () {
31 cat >"$HOME/expected-stdout"
36 expect_in stderr "$1" &&
37 test_cmp "$HOME/expected-stderr" "$HOME/stderr"
42 if grep "$regexp" "$HOME/stderr"
46 echo "didn't find /$regexp/ in $HOME/stderr"
52 stderr_empty_on_success () {
54 if test $expect_code = 0
58 # If we expect failure then stderr might or might not be empty
59 # due to --quiet - the caller can check its contents
64 test_check_ignore () {
65 args="$1" expect_code="${2:-0}" global_args="$3"
68 rm -f "$HOME/stdout" "$HOME/stderr" "$HOME/cmd" &&
69 echo git $global_args check-ignore $quiet_opt $verbose_opt $non_matching_opt $args \
71 echo "$expect_code" >"$HOME/expected-exit-code" &&
72 test_expect_code "$expect_code" \
73 git $global_args check-ignore $quiet_opt $verbose_opt $non_matching_opt $args \
74 >"$HOME/stdout" 2>"$HOME/stderr" &&
75 test_cmp "$HOME/expected-stdout" "$HOME/stdout" &&
76 stderr_empty_on_success "$expect_code"
79 # Runs the same code with 4 different levels of output verbosity:
81 # 1. with -q / --quiet
82 # 2. with default verbosity
83 # 3. with -v / --verbose
84 # 4. with -v / --verbose, *and* -n / --non-matching
86 # expecting success each time. Takes advantage of the fact that
87 # check-ignore --verbose output is the same as normal output except
88 # for the extra first column.
91 # - (optional) prereqs for this test, e.g. 'SYMLINKS'
93 # - output to expect from the fourth verbosity mode (the output
94 # from the other verbosity modes is automatically inferred
96 # - code to run (should invoke test_check_ignore)
97 test_expect_success_multi () {
104 testname="$1" expect_all="$2" code="$3"
106 expect_verbose=$( echo "$expect_all" | grep -v '^:: ' )
107 expect=$( echo "$expect_verbose" | sed -e 's/.* //' )
109 test_expect_success $prereq "$testname" '
114 # --quiet is only valid when a single pattern is passed
115 if test $( echo "$expect_all" | wc -l ) = 1
117 for quiet_opt in '-q' '--quiet'
119 test_expect_success $prereq "$testname${quiet_opt:+ with $quiet_opt}" "
127 for verbose_opt in '-v' '--verbose'
129 for non_matching_opt in '' ' -n' ' --non-matching'
131 if test -n "$non_matching_opt"
133 my_expect="$expect_all"
135 my_expect="$expect_verbose"
139 expect '$my_expect' &&
142 opts="$verbose_opt$non_matching_opt"
143 test_expect_success $prereq "$testname${opts:+ with $opts}" "$test_code"
150 test_expect_success 'setup' '
152 mkdir -p a/b/ignored-dir a/submodule b &&
153 if test_have_prereq SYMLINKS
162 git commit -m"commit in submodule"
164 git add a/submodule &&
165 cat <<-\EOF >.gitignore &&
172 : >$dir/not-ignored &&
173 : >$dir/ignored-and-untracked &&
174 : >$dir/ignored-but-in-index
176 git add -f ignored-but-in-index a/ignored-but-in-index &&
177 cat <<-\EOF >a/.gitignore &&
181 cat <<-\EOF >a/b/.gitignore &&
184 # this comment should affect the line numbers
187 # and so should this blank line:
192 echo "seven" >a/b/ignored-dir/.gitignore &&
194 cat <<-\EOF >"$global_excludes" &&
199 cat <<-\EOF >>.git/info/exclude
204 ############################################################################
206 # test invalid inputs
208 test_expect_success_multi '. corner-case' ':: .' '
209 test_check_ignore . 1
212 test_expect_success_multi 'empty command line' '' '
213 test_check_ignore "" 128 &&
214 stderr_contains "fatal: no path specified"
217 test_expect_success_multi '--stdin with empty STDIN' '' '
218 test_check_ignore "--stdin" 1 </dev/null &&
222 test_expect_success '-q with multiple args' '
224 test_check_ignore "-q one two" 128 &&
225 stderr_contains "fatal: --quiet is only valid with a single pathname"
228 test_expect_success '--quiet with multiple args' '
230 test_check_ignore "--quiet one two" 128 &&
231 stderr_contains "fatal: --quiet is only valid with a single pathname"
234 for verbose_opt in '-v' '--verbose'
236 for quiet_opt in '-q' '--quiet'
238 test_expect_success "$quiet_opt $verbose_opt" "
240 test_check_ignore '$quiet_opt $verbose_opt foo' 128 &&
241 stderr_contains 'fatal: cannot have both --quiet and --verbose'
246 test_expect_success '--quiet with multiple args' '
248 test_check_ignore "--quiet one two" 128 &&
249 stderr_contains "fatal: --quiet is only valid with a single pathname"
252 test_expect_success_multi 'erroneous use of --' '' '
253 test_check_ignore "--" 128 &&
254 stderr_contains "fatal: no path specified"
257 test_expect_success_multi '--stdin with superfluous arg' '' '
258 test_check_ignore "--stdin foo" 128 &&
259 stderr_contains "fatal: cannot specify pathnames with --stdin"
262 test_expect_success_multi '--stdin -z with superfluous arg' '' '
263 test_check_ignore "--stdin -z foo" 128 &&
264 stderr_contains "fatal: cannot specify pathnames with --stdin"
267 test_expect_success_multi '-z without --stdin' '' '
268 test_check_ignore "-z" 128 &&
269 stderr_contains "fatal: -z only makes sense with --stdin"
272 test_expect_success_multi '-z without --stdin and superfluous arg' '' '
273 test_check_ignore "-z foo" 128 &&
274 stderr_contains "fatal: -z only makes sense with --stdin"
277 test_expect_success_multi 'needs work tree' '' '
280 test_check_ignore "foo" 128
282 stderr_contains "fatal: This operation must be run in a work tree"
285 ############################################################################
287 # test standard ignores
289 # First make sure that the presence of a file in the working tree
290 # does not impact results, but that the presence of a file in the
293 for subdir in '' 'a/'
299 where="in subdir $subdir"
302 test_expect_success_multi "non-existent file $where not ignored" \
303 ":: ${subdir}non-existent" \
304 "test_check_ignore '${subdir}non-existent' 1"
306 test_expect_success_multi "non-existent file $where ignored" \
307 ".gitignore:1:one ${subdir}one" \
308 "test_check_ignore '${subdir}one'"
310 test_expect_success_multi "existing untracked file $where not ignored" \
311 ":: ${subdir}not-ignored" \
312 "test_check_ignore '${subdir}not-ignored' 1"
314 test_expect_success_multi "existing tracked file $where not ignored" \
315 ":: ${subdir}ignored-but-in-index" \
316 "test_check_ignore '${subdir}ignored-but-in-index' 1"
318 test_expect_success_multi "existing untracked file $where ignored" \
319 ".gitignore:2:ignored-* ${subdir}ignored-and-untracked" \
320 "test_check_ignore '${subdir}ignored-and-untracked'"
322 test_expect_success_multi "mix of file types $where" \
323 ":: ${subdir}non-existent
324 .gitignore:1:one ${subdir}one
325 :: ${subdir}not-ignored
326 :: ${subdir}ignored-but-in-index
327 .gitignore:2:ignored-* ${subdir}ignored-and-untracked" \
329 ${subdir}non-existent
332 ${subdir}ignored-but-in-index
333 ${subdir}ignored-and-untracked'
337 # Having established the above, from now on we mostly test against
338 # files which do not exist in the working tree or index.
340 test_expect_success 'sub-directory local ignore' '
341 expect "a/3-three" &&
342 test_check_ignore "a/3-three a/three-not-this-one"
345 test_expect_success 'sub-directory local ignore with --verbose' '
346 expect "a/.gitignore:2:*three a/3-three" &&
347 test_check_ignore "--verbose a/3-three a/three-not-this-one"
350 test_expect_success 'local ignore inside a sub-directory' '
354 test_check_ignore "3-three three-not-this-one"
357 test_expect_success 'local ignore inside a sub-directory with --verbose' '
358 expect "a/.gitignore:2:*three 3-three" &&
361 test_check_ignore "--verbose 3-three three-not-this-one"
365 test_expect_success_multi 'nested include' \
366 'a/b/.gitignore:8:!on* a/b/one' '
367 test_check_ignore "a/b/one"
370 ############################################################################
372 # test ignored sub-directories
374 test_expect_success_multi 'ignored sub-directory' \
375 'a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir' '
376 test_check_ignore "a/b/ignored-dir"
379 test_expect_success 'multiple files inside ignored sub-directory' '
380 expect_from_stdin <<-\EOF &&
382 a/b/ignored-dir/twoooo
383 a/b/ignored-dir/seven
385 test_check_ignore "a/b/ignored-dir/foo a/b/ignored-dir/twoooo a/b/ignored-dir/seven"
388 test_expect_success 'multiple files inside ignored sub-directory with -v' '
389 expect_from_stdin <<-\EOF &&
390 a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir/foo
391 a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir/twoooo
392 a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir/seven
394 test_check_ignore "-v a/b/ignored-dir/foo a/b/ignored-dir/twoooo a/b/ignored-dir/seven"
397 test_expect_success 'cd to ignored sub-directory' '
398 expect_from_stdin <<-\EOF &&
406 cd a/b/ignored-dir &&
407 test_check_ignore "foo twoooo ../one seven ../../one"
411 test_expect_success 'cd to ignored sub-directory with -v' '
412 expect_from_stdin <<-\EOF &&
413 a/b/.gitignore:5:ignored-dir/ foo
414 a/b/.gitignore:5:ignored-dir/ twoooo
415 a/b/.gitignore:8:!on* ../one
416 a/b/.gitignore:5:ignored-dir/ seven
417 .gitignore:1:one ../../one
420 cd a/b/ignored-dir &&
421 test_check_ignore "-v foo twoooo ../one seven ../../one"
425 ############################################################################
427 # test handling of symlinks
429 test_expect_success_multi SYMLINKS 'symlink' ':: a/symlink' '
430 test_check_ignore "a/symlink" 1
433 test_expect_success_multi SYMLINKS 'beyond a symlink' '' '
434 test_check_ignore "a/symlink/foo" 128 &&
435 test_stderr "fatal: '\''a/symlink/foo'\'' is beyond a symbolic link"
438 test_expect_success_multi SYMLINKS 'beyond a symlink from subdirectory' '' '
441 test_check_ignore "symlink/foo" 128
443 test_stderr "fatal: '\''symlink/foo'\'' is beyond a symbolic link"
446 ############################################################################
448 # test handling of submodules
450 test_expect_success_multi 'submodule' '' '
451 test_check_ignore "a/submodule/one" 128 &&
452 test_stderr "fatal: Path '\''a/submodule/one'\'' is in submodule '\''a/submodule'\''"
455 test_expect_success_multi 'submodule from subdirectory' '' '
458 test_check_ignore "submodule/one" 128
460 test_stderr "fatal: Path '\''a/submodule/one'\'' is in submodule '\''a/submodule'\''"
463 ############################################################################
465 # test handling of global ignore files
467 test_expect_success 'global ignore not yet enabled' '
468 expect_from_stdin <<-\EOF &&
469 .git/info/exclude:7:per-repo per-repo
470 a/.gitignore:2:*three a/globalthree
471 .git/info/exclude:7:per-repo a/per-repo
473 test_check_ignore "-v globalone per-repo a/globalthree a/per-repo not-ignored a/globaltwo"
476 test_expect_success 'global ignore' '
477 enable_global_excludes &&
478 expect_from_stdin <<-\EOF &&
486 test_check_ignore "globalone per-repo globalthree a/globalthree a/per-repo not-ignored globaltwo"
489 test_expect_success 'global ignore with -v' '
490 enable_global_excludes &&
491 expect_from_stdin <<-EOF &&
492 $global_excludes:1:globalone globalone
493 .git/info/exclude:7:per-repo per-repo
494 $global_excludes:3:globalthree globalthree
495 a/.gitignore:2:*three a/globalthree
496 .git/info/exclude:7:per-repo a/per-repo
497 $global_excludes:2:!globaltwo globaltwo
499 test_check_ignore "-v globalone per-repo globalthree a/globalthree a/per-repo not-ignored globaltwo"
502 ############################################################################
524 cat <<-\EOF >expected-default
539 cat <<-EOF >expected-verbose
541 .gitignore:1:one a/one
542 a/b/.gitignore:8:!on* a/b/on
543 a/b/.gitignore:8:!on* a/b/one
544 a/b/.gitignore:8:!on* a/b/one one
545 a/b/.gitignore:8:!on* a/b/one two
546 a/b/.gitignore:8:!on* "a/b/one\"three"
547 a/b/.gitignore:9:!two a/b/two
548 a/.gitignore:1:two* a/b/twooo
549 $global_excludes:2:!globaltwo globaltwo
550 $global_excludes:2:!globaltwo a/globaltwo
551 $global_excludes:2:!globaltwo a/b/globaltwo
552 $global_excludes:2:!globaltwo b/globaltwo
555 sed -e 's/^"//' -e 's/\\//' -e 's/"$//' stdin | \
557 sed -e 's/^"//' -e 's/\\//' -e 's/"$//' expected-default | \
558 tr "\n" "\0" >expected-default0
559 sed -e 's/ "/ /' -e 's/\\//' -e 's/"$//' expected-verbose | \
560 tr ":\t\n" "\0" >expected-verbose0
562 test_expect_success '--stdin' '
563 expect_from_stdin <expected-default &&
564 test_check_ignore "--stdin" <stdin
567 test_expect_success '--stdin -q' '
569 test_check_ignore "-q --stdin" <stdin
572 test_expect_success '--stdin -v' '
573 expect_from_stdin <expected-verbose &&
574 test_check_ignore "-v --stdin" <stdin
577 for opts in '--stdin -z' '-z --stdin'
579 test_expect_success "$opts" "
580 expect_from_stdin <expected-default0 &&
581 test_check_ignore '$opts' <stdin0
584 test_expect_success "$opts -q" "
586 test_check_ignore '-q $opts' <stdin0
589 test_expect_success "$opts -v" "
590 expect_from_stdin <expected-verbose0 &&
591 test_check_ignore '-v $opts' <stdin0
614 # N.B. we deliberately end STDIN with a non-matching pattern in order
615 # to test that the exit code indicates that one or more of the
616 # provided paths is ignored - in other words, that it represents an
617 # aggregation of all the results, not just the final result.
619 cat <<-EOF >expected-all
620 .gitignore:1:one ../one
624 a/b/.gitignore:8:!on* b/on
625 a/b/.gitignore:8:!on* b/one
626 a/b/.gitignore:8:!on* b/one one
627 a/b/.gitignore:8:!on* b/one two
628 a/b/.gitignore:8:!on* "b/one\"three"
629 a/b/.gitignore:9:!two b/two
631 a/.gitignore:1:two* b/twooo
632 $global_excludes:2:!globaltwo ../globaltwo
633 $global_excludes:2:!globaltwo globaltwo
634 $global_excludes:2:!globaltwo b/globaltwo
635 $global_excludes:2:!globaltwo ../b/globaltwo
638 grep -v '^:: ' expected-all >expected-verbose
639 sed -e 's/.* //' expected-verbose >expected-default
641 sed -e 's/^"//' -e 's/\\//' -e 's/"$//' stdin | \
643 sed -e 's/^"//' -e 's/\\//' -e 's/"$//' expected-default | \
644 tr "\n" "\0" >expected-default0
645 sed -e 's/ "/ /' -e 's/\\//' -e 's/"$//' expected-verbose | \
646 tr ":\t\n" "\0" >expected-verbose0
648 test_expect_success '--stdin from subdirectory' '
649 expect_from_stdin <expected-default &&
652 test_check_ignore "--stdin" <../stdin
656 test_expect_success '--stdin from subdirectory with -v' '
657 expect_from_stdin <expected-verbose &&
660 test_check_ignore "--stdin -v" <../stdin
664 test_expect_success '--stdin from subdirectory with -v -n' '
665 expect_from_stdin <expected-all &&
668 test_check_ignore "--stdin -v -n" <../stdin
672 for opts in '--stdin -z' '-z --stdin'
674 test_expect_success "$opts from subdirectory" '
675 expect_from_stdin <expected-default0 &&
678 test_check_ignore "'"$opts"'" <../stdin0
682 test_expect_success "$opts from subdirectory with -v" '
683 expect_from_stdin <expected-verbose0 &&
686 test_check_ignore "'"$opts"' -v" <../stdin0
691 test_expect_success PIPE 'streaming support for --stdin' '
693 (git check-ignore -n -v --stdin <in >out &) &&
695 # We cannot just "echo >in" because check-ignore would get EOF
696 # after echo exited; instead we open the descriptor in our
697 # shell, and then echo to the fd. We make sure to close it at
698 # the end, so that the subprocess does get EOF and dies
701 test_when_finished "exec 9>&-" &&
703 read response <out &&
704 echo "$response" | grep "^\.gitignore:1:one one" &&
706 read response <out &&
707 echo "$response" | grep "^:: two"