Merge 'normalize-win-paths' into HEAD
[git/mingw/4msysgit.git] / t / t0008-ignores.sh
blobd14a549a8f1c3a6ad7842dcd5de5524dcd79deb5
1 #!/bin/sh
3 test_description=check-ignore
5 . ./test-lib.sh
7 init_vars () {
8 # On Windows, avoid using "C:" in the global-excludes paths.
9 if test_have_prereq MINGW
10 then
11 global_excludes="global-excludes"
12 else
13 global_excludes="$(pwd)/global-excludes"
17 enable_global_excludes () {
18 init_vars &&
19 git config core.excludesfile "$global_excludes"
22 expect_in () {
23 dest="$HOME/expected-$1" text="$2"
24 if test -z "$text"
25 then
26 >"$dest" # avoid newline
27 else
28 echo "$text" >"$dest"
32 expect () {
33 expect_in stdout "$1"
36 expect_from_stdin () {
37 cat >"$HOME/expected-stdout"
40 test_stderr () {
41 expected="$1"
42 expect_in stderr "$1" &&
43 test_cmp "$HOME/expected-stderr" "$HOME/stderr"
46 broken_c_unquote () {
47 "$PERL_PATH" -pe 's/^"//; s/\\//; s/"$//; tr/\n/\0/' "$@"
50 broken_c_unquote_verbose () {
51 "$PERL_PATH" -pe 's/ "/ /; s/\\//; s/"$//; tr/:\t\n/\0/' "$@"
54 stderr_contains () {
55 regexp="$1"
56 if grep "$regexp" "$HOME/stderr"
57 then
58 return 0
59 else
60 echo "didn't find /$regexp/ in $HOME/stderr"
61 cat "$HOME/stderr"
62 return 1
66 stderr_empty_on_success () {
67 expect_code="$1"
68 if test $expect_code = 0
69 then
70 test_stderr ""
71 else
72 # If we expect failure then stderr might or might not be empty
73 # due to --quiet - the caller can check its contents
74 return 0
78 test_check_ignore () {
79 args="$1" expect_code="${2:-0}" global_args="$3"
81 init_vars &&
82 rm -f "$HOME/stdout" "$HOME/stderr" "$HOME/cmd" &&
83 echo git $global_args check-ignore $quiet_opt $verbose_opt $non_matching_opt $no_index_opt $args \
84 >"$HOME/cmd" &&
85 echo "$expect_code" >"$HOME/expected-exit-code" &&
86 test_expect_code "$expect_code" \
87 git $global_args check-ignore $quiet_opt $verbose_opt $non_matching_opt $no_index_opt $args \
88 >"$HOME/stdout" 2>"$HOME/stderr" &&
89 test_cmp "$HOME/expected-stdout" "$HOME/stdout" &&
90 stderr_empty_on_success "$expect_code"
93 # Runs the same code with 4 different levels of output verbosity:
95 # 1. with -q / --quiet
96 # 2. with default verbosity
97 # 3. with -v / --verbose
98 # 4. with -v / --verbose, *and* -n / --non-matching
100 # expecting success each time. Takes advantage of the fact that
101 # check-ignore --verbose output is the same as normal output except
102 # for the extra first column.
104 # A parameter is used to determine if the tests are run with the
105 # normal case (using the index), or with the --no-index option.
107 # Arguments:
108 # - (optional) prereqs for this test, e.g. 'SYMLINKS'
109 # - test name
110 # - output to expect from the fourth verbosity mode (the output
111 # from the other verbosity modes is automatically inferred
112 # from this value)
113 # - code to run (should invoke test_check_ignore)
114 # - index option: --index or --no-index
115 test_expect_success_multiple () {
116 prereq=
117 if test $# -eq 5
118 then
119 prereq=$1
120 shift
122 if test "$4" = "--index"
123 then
124 no_index_opt=
125 else
126 no_index_opt=$4
128 testname="$1" expect_all="$2" code="$3"
130 expect_verbose=$( echo "$expect_all" | grep -v '^:: ' )
131 expect=$( echo "$expect_verbose" | sed -e 's/.* //' )
133 test_expect_success $prereq "$testname${no_index_opt:+ with $no_index_opt}" '
134 expect "$expect" &&
135 eval "$code"
138 # --quiet is only valid when a single pattern is passed
139 if test $( echo "$expect_all" | wc -l ) = 1
140 then
141 for quiet_opt in '-q' '--quiet'
143 opts="${no_index_opt:+$no_index_opt }$quiet_opt"
144 test_expect_success $prereq "$testname${opts:+ with $opts}" "
145 expect '' &&
146 $code
148 done
149 quiet_opt=
152 for verbose_opt in '-v' '--verbose'
154 for non_matching_opt in '' '-n' '--non-matching'
156 if test -n "$non_matching_opt"
157 then
158 my_expect="$expect_all"
159 else
160 my_expect="$expect_verbose"
163 test_code="
164 expect '$my_expect' &&
165 $code
167 opts="${no_index_opt:+$no_index_opt }$verbose_opt${non_matching_opt:+ $non_matching_opt}"
168 test_expect_success $prereq "$testname${opts:+ with $opts}" "$test_code"
169 done
170 done
171 verbose_opt=
172 non_matching_opt=
173 no_index_opt=
176 test_expect_success_multi () {
177 test_expect_success_multiple "$@" "--index"
180 test_expect_success_no_index_multi () {
181 test_expect_success_multiple "$@" "--no-index"
184 test_expect_success 'setup' '
185 init_vars &&
186 mkdir -p a/b/ignored-dir a/submodule b &&
187 if test_have_prereq SYMLINKS
188 then
189 ln -s b a/symlink
190 fi &&
192 cd a/submodule &&
193 git init &&
194 echo a >a &&
195 git add a &&
196 git commit -m"commit in submodule"
197 ) &&
198 git add a/submodule &&
199 cat <<-\EOF >.gitignore &&
201 ignored-*
202 top-level-dir/
204 for dir in . a
206 : >$dir/not-ignored &&
207 : >$dir/ignored-and-untracked &&
208 : >$dir/ignored-but-in-index
209 done &&
210 git add -f ignored-but-in-index a/ignored-but-in-index &&
211 cat <<-\EOF >a/.gitignore &&
212 two*
213 *three
215 cat <<-\EOF >a/b/.gitignore &&
216 four
217 five
218 # this comment should affect the line numbers
220 ignored-dir/
221 # and so should this blank line:
223 !on*
224 !two
226 echo "seven" >a/b/ignored-dir/.gitignore &&
227 test -n "$HOME" &&
228 cat <<-\EOF >"$global_excludes" &&
229 globalone
230 !globaltwo
231 globalthree
233 cat <<-\EOF >>.git/info/exclude
234 per-repo
238 ############################################################################
240 # test invalid inputs
242 test_expect_success_multi '. corner-case' ':: .' '
243 test_check_ignore . 1
246 test_expect_success_multi 'empty command line' '' '
247 test_check_ignore "" 128 &&
248 stderr_contains "fatal: no path specified"
251 test_expect_success_multi '--stdin with empty STDIN' '' '
252 test_check_ignore "--stdin" 1 </dev/null &&
253 test_stderr ""
256 test_expect_success '-q with multiple args' '
257 expect "" &&
258 test_check_ignore "-q one two" 128 &&
259 stderr_contains "fatal: --quiet is only valid with a single pathname"
262 test_expect_success '--quiet with multiple args' '
263 expect "" &&
264 test_check_ignore "--quiet one two" 128 &&
265 stderr_contains "fatal: --quiet is only valid with a single pathname"
268 for verbose_opt in '-v' '--verbose'
270 for quiet_opt in '-q' '--quiet'
272 test_expect_success "$quiet_opt $verbose_opt" "
273 expect '' &&
274 test_check_ignore '$quiet_opt $verbose_opt foo' 128 &&
275 stderr_contains 'fatal: cannot have both --quiet and --verbose'
277 done
278 done
280 test_expect_success '--quiet with multiple args' '
281 expect "" &&
282 test_check_ignore "--quiet one two" 128 &&
283 stderr_contains "fatal: --quiet is only valid with a single pathname"
286 test_expect_success_multi 'erroneous use of --' '' '
287 test_check_ignore "--" 128 &&
288 stderr_contains "fatal: no path specified"
291 test_expect_success_multi '--stdin with superfluous arg' '' '
292 test_check_ignore "--stdin foo" 128 &&
293 stderr_contains "fatal: cannot specify pathnames with --stdin"
296 test_expect_success_multi '--stdin -z with superfluous arg' '' '
297 test_check_ignore "--stdin -z foo" 128 &&
298 stderr_contains "fatal: cannot specify pathnames with --stdin"
301 test_expect_success_multi '-z without --stdin' '' '
302 test_check_ignore "-z" 128 &&
303 stderr_contains "fatal: -z only makes sense with --stdin"
306 test_expect_success_multi '-z without --stdin and superfluous arg' '' '
307 test_check_ignore "-z foo" 128 &&
308 stderr_contains "fatal: -z only makes sense with --stdin"
311 test_expect_success_multi 'needs work tree' '' '
313 cd .git &&
314 test_check_ignore "foo" 128
315 ) &&
316 stderr_contains "fatal: This operation must be run in a work tree"
319 ############################################################################
321 # test standard ignores
323 # First make sure that the presence of a file in the working tree
324 # does not impact results, but that the presence of a file in the
325 # index does unless the --no-index option is used.
327 for subdir in '' 'a/'
329 if test -z "$subdir"
330 then
331 where="at top-level"
332 else
333 where="in subdir $subdir"
336 test_expect_success_multi "non-existent file $where not ignored" \
337 ":: ${subdir}non-existent" \
338 "test_check_ignore '${subdir}non-existent' 1"
340 test_expect_success_no_index_multi "non-existent file $where not ignored" \
341 ":: ${subdir}non-existent" \
342 "test_check_ignore '${subdir}non-existent' 1"
344 test_expect_success_multi "non-existent file $where ignored" \
345 ".gitignore:1:one ${subdir}one" \
346 "test_check_ignore '${subdir}one'"
348 test_expect_success_no_index_multi "non-existent file $where ignored" \
349 ".gitignore:1:one ${subdir}one" \
350 "test_check_ignore '${subdir}one'"
352 test_expect_success_multi "existing untracked file $where not ignored" \
353 ":: ${subdir}not-ignored" \
354 "test_check_ignore '${subdir}not-ignored' 1"
356 test_expect_success_no_index_multi "existing untracked file $where not ignored" \
357 ":: ${subdir}not-ignored" \
358 "test_check_ignore '${subdir}not-ignored' 1"
360 test_expect_success_multi "existing tracked file $where not ignored" \
361 ":: ${subdir}ignored-but-in-index" \
362 "test_check_ignore '${subdir}ignored-but-in-index' 1"
364 test_expect_success_no_index_multi "existing tracked file $where shown as ignored" \
365 ".gitignore:2:ignored-* ${subdir}ignored-but-in-index" \
366 "test_check_ignore '${subdir}ignored-but-in-index'"
368 test_expect_success_multi "existing untracked file $where ignored" \
369 ".gitignore:2:ignored-* ${subdir}ignored-and-untracked" \
370 "test_check_ignore '${subdir}ignored-and-untracked'"
372 test_expect_success_no_index_multi "existing untracked file $where ignored" \
373 ".gitignore:2:ignored-* ${subdir}ignored-and-untracked" \
374 "test_check_ignore '${subdir}ignored-and-untracked'"
376 test_expect_success_multi "mix of file types $where" \
377 ":: ${subdir}non-existent
378 .gitignore:1:one ${subdir}one
379 :: ${subdir}not-ignored
380 :: ${subdir}ignored-but-in-index
381 .gitignore:2:ignored-* ${subdir}ignored-and-untracked" \
382 "test_check_ignore '
383 ${subdir}non-existent
384 ${subdir}one
385 ${subdir}not-ignored
386 ${subdir}ignored-but-in-index
387 ${subdir}ignored-and-untracked'
390 test_expect_success_no_index_multi "mix of file types $where" \
391 ":: ${subdir}non-existent
392 .gitignore:1:one ${subdir}one
393 :: ${subdir}not-ignored
394 .gitignore:2:ignored-* ${subdir}ignored-but-in-index
395 .gitignore:2:ignored-* ${subdir}ignored-and-untracked" \
396 "test_check_ignore '
397 ${subdir}non-existent
398 ${subdir}one
399 ${subdir}not-ignored
400 ${subdir}ignored-but-in-index
401 ${subdir}ignored-and-untracked'
403 done
405 # Having established the above, from now on we mostly test against
406 # files which do not exist in the working tree or index.
408 test_expect_success 'sub-directory local ignore' '
409 expect "a/3-three" &&
410 test_check_ignore "a/3-three a/three-not-this-one"
413 test_expect_success 'sub-directory local ignore with --verbose' '
414 expect "a/.gitignore:2:*three a/3-three" &&
415 test_check_ignore "--verbose a/3-three a/three-not-this-one"
418 test_expect_success 'local ignore inside a sub-directory' '
419 expect "3-three" &&
421 cd a &&
422 test_check_ignore "3-three three-not-this-one"
425 test_expect_success 'local ignore inside a sub-directory with --verbose' '
426 expect "a/.gitignore:2:*three 3-three" &&
428 cd a &&
429 test_check_ignore "--verbose 3-three three-not-this-one"
433 test_expect_success_multi 'nested include' \
434 'a/b/.gitignore:8:!on* a/b/one' '
435 test_check_ignore "a/b/one"
438 ############################################################################
440 # test ignored sub-directories
442 test_expect_success_multi 'ignored sub-directory' \
443 'a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir' '
444 test_check_ignore "a/b/ignored-dir"
447 test_expect_success 'multiple files inside ignored sub-directory' '
448 expect_from_stdin <<-\EOF &&
449 a/b/ignored-dir/foo
450 a/b/ignored-dir/twoooo
451 a/b/ignored-dir/seven
453 test_check_ignore "a/b/ignored-dir/foo a/b/ignored-dir/twoooo a/b/ignored-dir/seven"
456 test_expect_success 'multiple files inside ignored sub-directory with -v' '
457 expect_from_stdin <<-\EOF &&
458 a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir/foo
459 a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir/twoooo
460 a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir/seven
462 test_check_ignore "-v a/b/ignored-dir/foo a/b/ignored-dir/twoooo a/b/ignored-dir/seven"
465 test_expect_success 'cd to ignored sub-directory' '
466 expect_from_stdin <<-\EOF &&
468 twoooo
469 ../one
470 seven
471 ../../one
474 cd a/b/ignored-dir &&
475 test_check_ignore "foo twoooo ../one seven ../../one"
479 test_expect_success 'cd to ignored sub-directory with -v' '
480 expect_from_stdin <<-\EOF &&
481 a/b/.gitignore:5:ignored-dir/ foo
482 a/b/.gitignore:5:ignored-dir/ twoooo
483 a/b/.gitignore:8:!on* ../one
484 a/b/.gitignore:5:ignored-dir/ seven
485 .gitignore:1:one ../../one
488 cd a/b/ignored-dir &&
489 test_check_ignore "-v foo twoooo ../one seven ../../one"
493 ############################################################################
495 # test handling of symlinks
497 test_expect_success_multi SYMLINKS 'symlink' ':: a/symlink' '
498 test_check_ignore "a/symlink" 1
501 test_expect_success_multi SYMLINKS 'beyond a symlink' '' '
502 test_check_ignore "a/symlink/foo" 128 &&
503 test_stderr "fatal: pathspec '\''a/symlink/foo'\'' is beyond a symbolic link"
506 test_expect_success_multi SYMLINKS 'beyond a symlink from subdirectory' '' '
508 cd a &&
509 test_check_ignore "symlink/foo" 128
510 ) &&
511 test_stderr "fatal: pathspec '\''symlink/foo'\'' is beyond a symbolic link"
514 ############################################################################
516 # test handling of submodules
518 test_expect_success_multi 'submodule' '' '
519 test_check_ignore "a/submodule/one" 128 &&
520 test_stderr "fatal: Pathspec '\''a/submodule/one'\'' is in submodule '\''a/submodule'\''"
523 test_expect_success_multi 'submodule from subdirectory' '' '
525 cd a &&
526 test_check_ignore "submodule/one" 128
527 ) &&
528 test_stderr "fatal: Pathspec '\''submodule/one'\'' is in submodule '\''a/submodule'\''"
531 ############################################################################
533 # test handling of global ignore files
535 test_expect_success 'global ignore not yet enabled' '
536 expect_from_stdin <<-\EOF &&
537 .git/info/exclude:7:per-repo per-repo
538 a/.gitignore:2:*three a/globalthree
539 .git/info/exclude:7:per-repo a/per-repo
541 test_check_ignore "-v globalone per-repo a/globalthree a/per-repo not-ignored a/globaltwo"
544 test_expect_success 'global ignore' '
545 enable_global_excludes &&
546 expect_from_stdin <<-\EOF &&
547 globalone
548 per-repo
549 globalthree
550 a/globalthree
551 a/per-repo
552 globaltwo
554 test_check_ignore "globalone per-repo globalthree a/globalthree a/per-repo not-ignored globaltwo"
557 test_expect_success 'global ignore with -v' '
558 enable_global_excludes &&
559 expect_from_stdin <<-EOF &&
560 $global_excludes:1:globalone globalone
561 .git/info/exclude:7:per-repo per-repo
562 $global_excludes:3:globalthree globalthree
563 a/.gitignore:2:*three a/globalthree
564 .git/info/exclude:7:per-repo a/per-repo
565 $global_excludes:2:!globaltwo globaltwo
567 test_check_ignore "-v globalone per-repo globalthree a/globalthree a/per-repo not-ignored globaltwo"
570 ############################################################################
572 # test --stdin
574 cat <<-\EOF >stdin
576 not-ignored
577 a/one
578 a/not-ignored
579 a/b/on
580 a/b/one
581 a/b/one one
582 "a/b/one two"
583 "a/b/one\"three"
584 a/b/not-ignored
585 a/b/two
586 a/b/twooo
587 globaltwo
588 a/globaltwo
589 a/b/globaltwo
590 b/globaltwo
592 cat <<-\EOF >expected-default
594 a/one
595 a/b/on
596 a/b/one
597 a/b/one one
598 a/b/one two
599 "a/b/one\"three"
600 a/b/two
601 a/b/twooo
602 globaltwo
603 a/globaltwo
604 a/b/globaltwo
605 b/globaltwo
607 cat <<-EOF >expected-verbose
608 .gitignore:1:one one
609 .gitignore:1:one a/one
610 a/b/.gitignore:8:!on* a/b/on
611 a/b/.gitignore:8:!on* a/b/one
612 a/b/.gitignore:8:!on* a/b/one one
613 a/b/.gitignore:8:!on* a/b/one two
614 a/b/.gitignore:8:!on* "a/b/one\"three"
615 a/b/.gitignore:9:!two a/b/two
616 a/.gitignore:1:two* a/b/twooo
617 $global_excludes:2:!globaltwo globaltwo
618 $global_excludes:2:!globaltwo a/globaltwo
619 $global_excludes:2:!globaltwo a/b/globaltwo
620 $global_excludes:2:!globaltwo b/globaltwo
623 broken_c_unquote stdin >stdin0
625 broken_c_unquote expected-default >expected-default0
627 broken_c_unquote_verbose expected-verbose >expected-verbose0
629 test_expect_success '--stdin' '
630 expect_from_stdin <expected-default &&
631 test_check_ignore "--stdin" <stdin
634 test_expect_success '--stdin -q' '
635 expect "" &&
636 test_check_ignore "-q --stdin" <stdin
639 test_expect_success '--stdin -v' '
640 expect_from_stdin <expected-verbose &&
641 test_check_ignore "-v --stdin" <stdin
644 for opts in '--stdin -z' '-z --stdin'
646 test_expect_success "$opts" "
647 expect_from_stdin <expected-default0 &&
648 test_check_ignore '$opts' <stdin0
651 test_expect_success "$opts -q" "
652 expect "" &&
653 test_check_ignore '-q $opts' <stdin0
656 test_expect_success "$opts -v" "
657 expect_from_stdin <expected-verbose0 &&
658 test_check_ignore '-v $opts' <stdin0
660 done
662 cat <<-\EOF >stdin
663 ../one
664 ../not-ignored
666 not-ignored
667 b/on
668 b/one
669 b/one one
670 "b/one two"
671 "b/one\"three"
672 b/two
673 b/not-ignored
674 b/twooo
675 ../globaltwo
676 globaltwo
677 b/globaltwo
678 ../b/globaltwo
679 c/not-ignored
681 # N.B. we deliberately end STDIN with a non-matching pattern in order
682 # to test that the exit code indicates that one or more of the
683 # provided paths is ignored - in other words, that it represents an
684 # aggregation of all the results, not just the final result.
686 cat <<-EOF >expected-all
687 .gitignore:1:one ../one
688 :: ../not-ignored
689 .gitignore:1:one one
690 :: not-ignored
691 a/b/.gitignore:8:!on* b/on
692 a/b/.gitignore:8:!on* b/one
693 a/b/.gitignore:8:!on* b/one one
694 a/b/.gitignore:8:!on* b/one two
695 a/b/.gitignore:8:!on* "b/one\"three"
696 a/b/.gitignore:9:!two b/two
697 :: b/not-ignored
698 a/.gitignore:1:two* b/twooo
699 $global_excludes:2:!globaltwo ../globaltwo
700 $global_excludes:2:!globaltwo globaltwo
701 $global_excludes:2:!globaltwo b/globaltwo
702 $global_excludes:2:!globaltwo ../b/globaltwo
703 :: c/not-ignored
705 grep -v '^:: ' expected-all >expected-verbose
706 sed -e 's/.* //' expected-verbose >expected-default
708 broken_c_unquote stdin >stdin0
710 broken_c_unquote expected-default >expected-default0
712 broken_c_unquote_verbose expected-verbose >expected-verbose0
714 test_expect_success '--stdin from subdirectory' '
715 expect_from_stdin <expected-default &&
717 cd a &&
718 test_check_ignore "--stdin" <../stdin
722 test_expect_success '--stdin from subdirectory with -v' '
723 expect_from_stdin <expected-verbose &&
725 cd a &&
726 test_check_ignore "--stdin -v" <../stdin
730 test_expect_success '--stdin from subdirectory with -v -n' '
731 expect_from_stdin <expected-all &&
733 cd a &&
734 test_check_ignore "--stdin -v -n" <../stdin
738 for opts in '--stdin -z' '-z --stdin'
740 test_expect_success "$opts from subdirectory" '
741 expect_from_stdin <expected-default0 &&
743 cd a &&
744 test_check_ignore "'"$opts"'" <../stdin0
748 test_expect_success "$opts from subdirectory with -v" '
749 expect_from_stdin <expected-verbose0 &&
751 cd a &&
752 test_check_ignore "'"$opts"' -v" <../stdin0
755 done
757 test_expect_success PIPE 'streaming support for --stdin' '
758 mkfifo in out &&
759 (git check-ignore -n -v --stdin <in >out &) &&
761 # We cannot just "echo >in" because check-ignore would get EOF
762 # after echo exited; instead we open the descriptor in our
763 # shell, and then echo to the fd. We make sure to close it at
764 # the end, so that the subprocess does get EOF and dies
765 # properly.
767 # Similarly, we must keep "out" open so that check-ignore does
768 # not ever get SIGPIPE trying to write to us. Not only would that
769 # produce incorrect results, but then there would be no writer on the
770 # other end of the pipe, and we would potentially block forever trying
771 # to open it.
772 exec 9>in &&
773 exec 8<out &&
774 test_when_finished "exec 9>&-" &&
775 test_when_finished "exec 8<&-" &&
776 echo >&9 one &&
777 read response <&8 &&
778 echo "$response" | grep "^\.gitignore:1:one one" &&
779 echo >&9 two &&
780 read response <&8 &&
781 echo "$response" | grep "^:: two"
784 test_done