3 test_description
=check-ignore
8 global_excludes
="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_i18ncmp
"$HOME/expected-stderr" "$HOME/stderr"
41 "$PERL_PATH" -pe 's/^"//; s/\\//; s/"$//; tr/\n/\0/' "$@"
44 broken_c_unquote_verbose
() {
45 "$PERL_PATH" -pe 's/ "/ /; s/\\//; s/"$//; tr/:\t\n/\0/' "$@"
50 if test_i18ngrep
"$regexp" "$HOME/stderr"
54 echo "didn't find /$regexp/ in $HOME/stderr"
60 stderr_empty_on_success
() {
62 if test $expect_code = 0
66 # If we expect failure then stderr might or might not be empty
67 # due to --quiet - the caller can check its contents
72 test_check_ignore
() {
73 args
="$1" expect_code
="${2:-0}" global_args
="$3"
76 rm -f "$HOME/stdout" "$HOME/stderr" "$HOME/cmd" &&
77 echo git
$global_args check-ignore
$quiet_opt $verbose_opt $non_matching_opt $no_index_opt $args \
79 echo "$expect_code" >"$HOME/expected-exit-code" &&
80 test_expect_code
"$expect_code" \
81 git
$global_args check-ignore
$quiet_opt $verbose_opt $non_matching_opt $no_index_opt $args \
82 >"$HOME/stdout" 2>"$HOME/stderr" &&
83 test_cmp
"$HOME/expected-stdout" "$HOME/stdout" &&
84 stderr_empty_on_success
"$expect_code"
87 # Runs the same code with 4 different levels of output verbosity:
89 # 1. with -q / --quiet
90 # 2. with default verbosity
91 # 3. with -v / --verbose
92 # 4. with -v / --verbose, *and* -n / --non-matching
94 # expecting success each time. Takes advantage of the fact that
95 # check-ignore --verbose output is the same as normal output except
96 # for the extra first column.
98 # A parameter is used to determine if the tests are run with the
99 # normal case (using the index), or with the --no-index option.
102 # - (optional) prereqs for this test, e.g. 'SYMLINKS'
104 # - output to expect from the fourth verbosity mode (the output
105 # from the other verbosity modes is automatically inferred
107 # - code to run (should invoke test_check_ignore)
108 # - index option: --index or --no-index
109 test_expect_success_multiple
() {
116 if test "$4" = "--index"
122 testname
="$1" expect_all
="$2" code
="$3"
124 expect_verbose
=$
( echo "$expect_all" |
grep -v '^:: ' )
125 expect
=$
( echo "$expect_verbose" |
sed -e 's/.* //' )
127 test_expect_success
$prereq "$testname${no_index_opt:+ with $no_index_opt}" '
132 # --quiet is only valid when a single pattern is passed
133 if test $
( echo "$expect_all" |
wc -l ) = 1
135 for quiet_opt
in '-q' '--quiet'
137 opts
="${no_index_opt:+$no_index_opt }$quiet_opt"
138 test_expect_success
$prereq "$testname${opts:+ with $opts}" "
146 for verbose_opt
in '-v' '--verbose'
148 for non_matching_opt
in '' '-n' '--non-matching'
150 if test -n "$non_matching_opt"
152 my_expect
="$expect_all"
154 my_expect
="$expect_verbose"
158 expect '$my_expect' &&
161 opts
="${no_index_opt:+$no_index_opt }$verbose_opt${non_matching_opt:+ $non_matching_opt}"
162 test_expect_success
$prereq "$testname${opts:+ with $opts}" "$test_code"
170 test_expect_success_multi
() {
171 test_expect_success_multiple
"$@" "--index"
174 test_expect_success_no_index_multi
() {
175 test_expect_success_multiple
"$@" "--no-index"
178 test_expect_success
'setup' '
180 mkdir -p a/b/ignored-dir a/submodule b &&
181 if test_have_prereq SYMLINKS
190 git commit -m"commit in submodule"
192 git add a/submodule &&
193 cat <<-\EOF >.gitignore &&
200 : >$dir/not-ignored &&
201 : >$dir/ignored-and-untracked &&
202 : >$dir/ignored-but-in-index
204 git add -f ignored-but-in-index a/ignored-but-in-index &&
205 cat <<-\EOF >a/.gitignore &&
209 cat <<-\EOF >a/b/.gitignore &&
212 # this comment should affect the line numbers
215 # and so should this blank line:
220 echo "seven" >a/b/ignored-dir/.gitignore &&
222 cat <<-\EOF >"$global_excludes" &&
227 cat <<-\EOF >>.git/info/exclude
232 ############################################################################
234 # test invalid inputs
236 test_expect_success_multi
'. corner-case' ':: .' '
237 test_check_ignore . 1
240 test_expect_success_multi
'empty command line' '' '
241 test_check_ignore "" 128 &&
242 stderr_contains "fatal: no path specified"
245 test_expect_success_multi
'--stdin with empty STDIN' '' '
246 test_check_ignore "--stdin" 1 </dev/null &&
250 test_expect_success
'-q with multiple args' '
252 test_check_ignore "-q one two" 128 &&
253 stderr_contains "fatal: --quiet is only valid with a single pathname"
256 test_expect_success
'--quiet with multiple args' '
258 test_check_ignore "--quiet one two" 128 &&
259 stderr_contains "fatal: --quiet is only valid with a single pathname"
262 for verbose_opt
in '-v' '--verbose'
264 for quiet_opt
in '-q' '--quiet'
266 test_expect_success
"$quiet_opt $verbose_opt" "
268 test_check_ignore '$quiet_opt $verbose_opt foo' 128 &&
269 stderr_contains 'fatal: cannot have both --quiet and --verbose'
274 test_expect_success
'--quiet with multiple args' '
276 test_check_ignore "--quiet one two" 128 &&
277 stderr_contains "fatal: --quiet is only valid with a single pathname"
280 test_expect_success_multi
'erroneous use of --' '' '
281 test_check_ignore "--" 128 &&
282 stderr_contains "fatal: no path specified"
285 test_expect_success_multi
'--stdin with superfluous arg' '' '
286 test_check_ignore "--stdin foo" 128 &&
287 stderr_contains "fatal: cannot specify pathnames with --stdin"
290 test_expect_success_multi
'--stdin -z with superfluous arg' '' '
291 test_check_ignore "--stdin -z foo" 128 &&
292 stderr_contains "fatal: cannot specify pathnames with --stdin"
295 test_expect_success_multi
'-z without --stdin' '' '
296 test_check_ignore "-z" 128 &&
297 stderr_contains "fatal: -z only makes sense with --stdin"
300 test_expect_success_multi
'-z without --stdin and superfluous arg' '' '
301 test_check_ignore "-z foo" 128 &&
302 stderr_contains "fatal: -z only makes sense with --stdin"
305 test_expect_success_multi
'needs work tree' '' '
308 test_check_ignore "foo" 128
310 stderr_contains "fatal: this operation must be run in a work tree"
313 ############################################################################
315 # test standard ignores
317 # First make sure that the presence of a file in the working tree
318 # does not impact results, but that the presence of a file in the
319 # index does unless the --no-index option is used.
321 for subdir
in '' 'a/'
327 where
="in subdir $subdir"
330 test_expect_success_multi
"non-existent file $where not ignored" \
331 ":: ${subdir}non-existent" \
332 "test_check_ignore '${subdir}non-existent' 1"
334 test_expect_success_no_index_multi
"non-existent file $where not ignored" \
335 ":: ${subdir}non-existent" \
336 "test_check_ignore '${subdir}non-existent' 1"
338 test_expect_success_multi
"non-existent file $where ignored" \
339 ".gitignore:1:one ${subdir}one" \
340 "test_check_ignore '${subdir}one'"
342 test_expect_success_no_index_multi
"non-existent file $where ignored" \
343 ".gitignore:1:one ${subdir}one" \
344 "test_check_ignore '${subdir}one'"
346 test_expect_success_multi
"existing untracked file $where not ignored" \
347 ":: ${subdir}not-ignored" \
348 "test_check_ignore '${subdir}not-ignored' 1"
350 test_expect_success_no_index_multi
"existing untracked file $where not ignored" \
351 ":: ${subdir}not-ignored" \
352 "test_check_ignore '${subdir}not-ignored' 1"
354 test_expect_success_multi
"existing tracked file $where not ignored" \
355 ":: ${subdir}ignored-but-in-index" \
356 "test_check_ignore '${subdir}ignored-but-in-index' 1"
358 test_expect_success_no_index_multi
"existing tracked file $where shown as ignored" \
359 ".gitignore:2:ignored-* ${subdir}ignored-but-in-index" \
360 "test_check_ignore '${subdir}ignored-but-in-index'"
362 test_expect_success_multi
"existing untracked file $where ignored" \
363 ".gitignore:2:ignored-* ${subdir}ignored-and-untracked" \
364 "test_check_ignore '${subdir}ignored-and-untracked'"
366 test_expect_success_no_index_multi
"existing untracked file $where ignored" \
367 ".gitignore:2:ignored-* ${subdir}ignored-and-untracked" \
368 "test_check_ignore '${subdir}ignored-and-untracked'"
370 test_expect_success_multi
"mix of file types $where" \
371 ":: ${subdir}non-existent
372 .gitignore:1:one ${subdir}one
373 :: ${subdir}not-ignored
374 :: ${subdir}ignored-but-in-index
375 .gitignore:2:ignored-* ${subdir}ignored-and-untracked" \
377 ${subdir}non-existent
380 ${subdir}ignored-but-in-index
381 ${subdir}ignored-and-untracked'
384 test_expect_success_no_index_multi
"mix of file types $where" \
385 ":: ${subdir}non-existent
386 .gitignore:1:one ${subdir}one
387 :: ${subdir}not-ignored
388 .gitignore:2:ignored-* ${subdir}ignored-but-in-index
389 .gitignore:2:ignored-* ${subdir}ignored-and-untracked" \
391 ${subdir}non-existent
394 ${subdir}ignored-but-in-index
395 ${subdir}ignored-and-untracked'
399 # Having established the above, from now on we mostly test against
400 # files which do not exist in the working tree or index.
402 test_expect_success
'sub-directory local ignore' '
403 expect "a/3-three" &&
404 test_check_ignore "a/3-three a/three-not-this-one"
407 test_expect_success
'sub-directory local ignore with --verbose' '
408 expect "a/.gitignore:2:*three a/3-three" &&
409 test_check_ignore "--verbose a/3-three a/three-not-this-one"
412 test_expect_success
'local ignore inside a sub-directory' '
416 test_check_ignore "3-three three-not-this-one"
419 test_expect_success
'local ignore inside a sub-directory with --verbose' '
420 expect "a/.gitignore:2:*three 3-three" &&
423 test_check_ignore "--verbose 3-three three-not-this-one"
427 test_expect_success
'nested include of negated pattern' '
429 test_check_ignore "a/b/one" 1
432 test_expect_success
'nested include of negated pattern with -q' '
434 test_check_ignore "-q a/b/one" 1
437 test_expect_success
'nested include of negated pattern with -v' '
438 expect "a/b/.gitignore:8:!on* a/b/one" &&
439 test_check_ignore "-v a/b/one" 0
442 test_expect_success
'nested include of negated pattern with -v -n' '
443 expect "a/b/.gitignore:8:!on* a/b/one" &&
444 test_check_ignore "-v -n a/b/one" 0
447 ############################################################################
449 # test ignored sub-directories
451 test_expect_success_multi
'ignored sub-directory' \
452 'a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir' '
453 test_check_ignore "a/b/ignored-dir"
456 test_expect_success
'multiple files inside ignored sub-directory' '
457 expect_from_stdin <<-\EOF &&
459 a/b/ignored-dir/twoooo
460 a/b/ignored-dir/seven
462 test_check_ignore "a/b/ignored-dir/foo a/b/ignored-dir/twoooo a/b/ignored-dir/seven"
465 test_expect_success
'multiple files inside ignored sub-directory with -v' '
466 expect_from_stdin <<-\EOF &&
467 a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir/foo
468 a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir/twoooo
469 a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir/seven
471 test_check_ignore "-v a/b/ignored-dir/foo a/b/ignored-dir/twoooo a/b/ignored-dir/seven"
474 test_expect_success
'cd to ignored sub-directory' '
475 expect_from_stdin <<-\EOF &&
482 cd a/b/ignored-dir &&
483 test_check_ignore "foo twoooo ../one seven ../../one"
487 test_expect_success
'cd to ignored sub-directory with -v' '
488 expect_from_stdin <<-\EOF &&
489 a/b/.gitignore:5:ignored-dir/ foo
490 a/b/.gitignore:5:ignored-dir/ twoooo
491 a/b/.gitignore:8:!on* ../one
492 a/b/.gitignore:5:ignored-dir/ seven
493 .gitignore:1:one ../../one
496 cd a/b/ignored-dir &&
497 test_check_ignore "-v foo twoooo ../one seven ../../one"
501 ############################################################################
503 # test handling of symlinks
505 test_expect_success_multi SYMLINKS
'symlink' ':: a/symlink' '
506 test_check_ignore "a/symlink" 1
509 test_expect_success_multi SYMLINKS
'beyond a symlink' '' '
510 test_check_ignore "a/symlink/foo" 128 &&
511 test_stderr "fatal: pathspec '\''a/symlink/foo'\'' is beyond a symbolic link"
514 test_expect_success_multi SYMLINKS
'beyond a symlink from subdirectory' '' '
517 test_check_ignore "symlink/foo" 128
519 test_stderr "fatal: pathspec '\''symlink/foo'\'' is beyond a symbolic link"
522 ############################################################################
524 # test handling of submodules
526 test_expect_success_multi
'submodule' '' '
527 test_check_ignore "a/submodule/one" 128 &&
528 test_stderr "fatal: Pathspec '\''a/submodule/one'\'' is in submodule '\''a/submodule'\''"
531 test_expect_success_multi
'submodule from subdirectory' '' '
534 test_check_ignore "submodule/one" 128
536 test_stderr "fatal: Pathspec '\''submodule/one'\'' is in submodule '\''a/submodule'\''"
539 ############################################################################
541 # test handling of global ignore files
543 test_expect_success
'global ignore not yet enabled' '
544 expect_from_stdin <<-\EOF &&
545 .git/info/exclude:7:per-repo per-repo
546 a/.gitignore:2:*three a/globalthree
547 .git/info/exclude:7:per-repo a/per-repo
549 test_check_ignore "-v globalone per-repo a/globalthree a/per-repo not-ignored a/globaltwo"
552 test_expect_success
'global ignore' '
553 enable_global_excludes &&
554 expect_from_stdin <<-\EOF &&
561 test_check_ignore "globalone per-repo globalthree a/globalthree a/per-repo not-ignored globaltwo"
564 test_expect_success
'global ignore with -v' '
565 enable_global_excludes &&
566 expect_from_stdin <<-EOF &&
567 $global_excludes:1:globalone globalone
568 .git/info/exclude:7:per-repo per-repo
569 $global_excludes:3:globalthree globalthree
570 a/.gitignore:2:*three a/globalthree
571 .git/info/exclude:7:per-repo a/per-repo
572 $global_excludes:2:!globaltwo globaltwo
574 test_check_ignore "-v globalone per-repo globalthree a/globalthree a/per-repo not-ignored globaltwo"
577 ############################################################################
599 cat <<-\
EOF >expected-default
604 cat <<-EOF >expected-verbose
606 .gitignore:1:one a/one
607 a/b/.gitignore:8:!on* a/b/on
608 a/b/.gitignore:8:!on* a/b/one
609 a/b/.gitignore:8:!on* a/b/one one
610 a/b/.gitignore:8:!on* a/b/one two
611 a/b/.gitignore:8:!on* "a/b/one\\"three"
612 a/b/.gitignore:9:!two a/b/two
613 a/.gitignore:1:two* a/b/twooo
614 $global_excludes:2:!globaltwo globaltwo
615 $global_excludes:2:!globaltwo a/globaltwo
616 $global_excludes:2:!globaltwo a/b/globaltwo
617 $global_excludes:2:!globaltwo b/globaltwo
620 broken_c_unquote stdin >stdin0
622 broken_c_unquote expected-default >expected-default0
624 broken_c_unquote_verbose expected-verbose >expected-verbose0
626 test_expect_success '--stdin' '
627 expect_from_stdin <expected-default &&
628 test_check_ignore "--stdin" <stdin
631 test_expect_success '--stdin -q' '
633 test_check_ignore "-q --stdin" <stdin
636 test_expect_success '--stdin -v' '
637 expect_from_stdin <expected-verbose &&
638 test_check_ignore "-v --stdin" <stdin
641 for opts in '--stdin -z' '-z --stdin'
643 test_expect_success "$opts" "
644 expect_from_stdin <expected-default0 &&
645 test_check_ignore '$opts' <stdin0
648 test_expect_success "$opts -q" "
650 test_check_ignore '-q $opts' <stdin0
653 test_expect_success "$opts -v" "
654 expect_from_stdin <expected-verbose0 &&
655 test_check_ignore '-v $opts' <stdin0
678 # N.B. we deliberately end STDIN with a non-matching pattern in order
679 # to test that the exit code indicates that one or more of the
680 # provided paths is ignored - in other words
, that it represents an
681 # aggregation of all the results, not just the final result.
683 cat <<-EOF >expected-all
684 .gitignore:1:one ../one
688 a/b/.gitignore:8:!on* b/on
689 a/b/.gitignore:8:!on* b/one
690 a/b/.gitignore:8:!on* b/one one
691 a/b/.gitignore:8:!on* b/one two
692 a/b/.gitignore:8:!on* "b/one\\"three"
693 a/b/.gitignore:9:!two b/two
695 a/.gitignore:1:two* b/twooo
696 $global_excludes:2:!globaltwo ../globaltwo
697 $global_excludes:2:!globaltwo globaltwo
698 $global_excludes:2:!globaltwo b/globaltwo
699 $global_excludes:2:!globaltwo ../b/globaltwo
702 cat <<-EOF >expected-default
707 grep -v '^:: ' expected-all
>expected-verbose
709 broken_c_unquote stdin
>stdin0
711 broken_c_unquote expected-default
>expected-default0
713 broken_c_unquote_verbose expected-verbose
>expected-verbose0
715 test_expect_success
'--stdin from subdirectory' '
716 expect_from_stdin <expected-default &&
719 test_check_ignore "--stdin" <../stdin
723 test_expect_success
'--stdin from subdirectory with -v' '
724 expect_from_stdin <expected-verbose &&
727 test_check_ignore "--stdin -v" <../stdin
731 test_expect_success
'--stdin from subdirectory with -v -n' '
732 expect_from_stdin <expected-all &&
735 test_check_ignore "--stdin -v -n" <../stdin
739 for opts
in '--stdin -z' '-z --stdin'
741 test_expect_success
"$opts from subdirectory" '
742 expect_from_stdin <expected-default0 &&
745 test_check_ignore "'"$opts"'" <../stdin0
749 test_expect_success
"$opts from subdirectory with -v" '
750 expect_from_stdin <expected-verbose0 &&
753 test_check_ignore "'"$opts"' -v" <../stdin0
758 test_expect_success PIPE
'streaming support for --stdin' '
760 (git check-ignore -n -v --stdin <in >out &) &&
762 # We cannot just "echo >in" because check-ignore would get EOF
763 # after echo exited; instead we open the descriptor in our
764 # shell, and then echo to the fd. We make sure to close it at
765 # the end, so that the subprocess does get EOF and dies
768 # Similarly, we must keep "out" open so that check-ignore does
769 # not ever get SIGPIPE trying to write to us. Not only would that
770 # produce incorrect results, but then there would be no writer on the
771 # other end of the pipe, and we would potentially block forever trying
775 test_when_finished "exec 9>&-" &&
776 test_when_finished "exec 8<&-" &&
779 echo "$response" | grep "^\.gitignore:1:one one" &&
782 echo "$response" | grep "^:: two"
785 test_expect_success
'existing file and directory' '
786 test_when_finished "rm one" &&
787 test_when_finished "rmdir top-level-dir" &&
789 mkdir top-level-dir &&
790 git check-ignore one top-level-dir >actual &&
792 grep top-level-dir actual
795 test_expect_success
'existing directory and file' '
796 test_when_finished "rm one" &&
797 test_when_finished "rmdir top-level-dir" &&
799 mkdir top-level-dir &&
800 git check-ignore top-level-dir one >actual &&
802 grep top-level-dir actual
805 ############################################################################
807 # test whitespace handling
809 test_expect_success
'trailing whitespace is ignored' '
811 >whitespace/trailing &&
812 >whitespace/untracked &&
813 echo "whitespace/trailing " >ignore &&
817 git ls-files -o -X ignore whitespace >actual 2>err &&
818 test_cmp expect actual &&
819 test_must_be_empty err
822 test_expect_success
!MINGW
'quoting allows trailing whitespace' '
825 >"whitespace/trailing " &&
826 >whitespace/untracked &&
827 echo "whitespace/trailing\\ \\ " >ignore &&
828 echo whitespace/untracked >expect &&
829 git ls-files -o -X ignore whitespace >actual 2>err &&
830 test_cmp expect actual &&
831 test_must_be_empty err
834 test_expect_success
!MINGW
,!CYGWIN
'correct handling of backslashes' '
837 >"whitespace/trailing 1 " &&
838 >"whitespace/trailing 2 \\\\" &&
839 >"whitespace/trailing 3 \\\\" &&
840 >"whitespace/trailing 4 \\ " &&
841 >"whitespace/trailing 5 \\ \\ " &&
842 >"whitespace/trailing 6 \\a\\" &&
843 >whitespace/untracked &&
844 sed -e "s/Z$//" >ignore <<-\EOF &&
845 whitespace/trailing 1 \ Z
846 whitespace/trailing 2 \\\\Z
847 whitespace/trailing 3 \\\\ Z
848 whitespace/trailing 4 \\\ Z
849 whitespace/trailing 5 \\ \\\ Z
850 whitespace/trailing 6 \\a\\Z
852 echo whitespace/untracked >expect &&
853 git ls-files -o -X ignore whitespace >actual 2>err &&
854 test_cmp expect actual &&
855 test_must_be_empty err
858 test_expect_success
'info/exclude trumps core.excludesfile' '
859 echo >>global-excludes usually-ignored &&
860 echo >>.git/info/exclude "!usually-ignored" &&
862 echo "?? usually-ignored" >expect &&
864 git status --porcelain usually-ignored >actual &&
865 test_cmp expect actual