patch-id-test: test stable and unstable behaviour
[git/raj.git] / t / t0008-ignores.sh
blobb4d98e602f7422009599e58f0a7ae943476b1c7e
1 #!/bin/sh
3 test_description=check-ignore
5 . ./test-lib.sh
7 init_vars () {
8 global_excludes="$(pwd)/global-excludes"
11 enable_global_excludes () {
12 init_vars &&
13 git config core.excludesfile "$global_excludes"
16 expect_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"
26 expect () {
27 expect_in stdout "$1"
30 expect_from_stdin () {
31 cat >"$HOME/expected-stdout"
34 test_stderr () {
35 expected="$1"
36 expect_in stderr "$1" &&
37 test_cmp "$HOME/expected-stderr" "$HOME/stderr"
40 broken_c_unquote () {
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/' "$@"
48 stderr_contains () {
49 regexp="$1"
50 if grep "$regexp" "$HOME/stderr"
51 then
52 return 0
53 else
54 echo "didn't find /$regexp/ in $HOME/stderr"
55 cat "$HOME/stderr"
56 return 1
60 stderr_empty_on_success () {
61 expect_code="$1"
62 if test $expect_code = 0
63 then
64 test_stderr ""
65 else
66 # If we expect failure then stderr might or might not be empty
67 # due to --quiet - the caller can check its contents
68 return 0
72 test_check_ignore () {
73 args="$1" expect_code="${2:-0}" global_args="$3"
75 init_vars &&
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 \
78 >"$HOME/cmd" &&
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.
101 # Arguments:
102 # - (optional) prereqs for this test, e.g. 'SYMLINKS'
103 # - test name
104 # - output to expect from the fourth verbosity mode (the output
105 # from the other verbosity modes is automatically inferred
106 # from this value)
107 # - code to run (should invoke test_check_ignore)
108 # - index option: --index or --no-index
109 test_expect_success_multiple () {
110 prereq=
111 if test $# -eq 5
112 then
113 prereq=$1
114 shift
116 if test "$4" = "--index"
117 then
118 no_index_opt=
119 else
120 no_index_opt=$4
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}" '
128 expect "$expect" &&
129 eval "$code"
132 # --quiet is only valid when a single pattern is passed
133 if test $( echo "$expect_all" | wc -l ) = 1
134 then
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}" "
139 expect '' &&
140 $code
142 done
143 quiet_opt=
146 for verbose_opt in '-v' '--verbose'
148 for non_matching_opt in '' '-n' '--non-matching'
150 if test -n "$non_matching_opt"
151 then
152 my_expect="$expect_all"
153 else
154 my_expect="$expect_verbose"
157 test_code="
158 expect '$my_expect' &&
159 $code
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"
163 done
164 done
165 verbose_opt=
166 non_matching_opt=
167 no_index_opt=
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' '
179 init_vars &&
180 mkdir -p a/b/ignored-dir a/submodule b &&
181 if test_have_prereq SYMLINKS
182 then
183 ln -s b a/symlink
184 fi &&
186 cd a/submodule &&
187 git init &&
188 echo a >a &&
189 git add a &&
190 git commit -m"commit in submodule"
191 ) &&
192 git add a/submodule &&
193 cat <<-\EOF >.gitignore &&
195 ignored-*
196 top-level-dir/
198 for dir in . a
200 : >$dir/not-ignored &&
201 : >$dir/ignored-and-untracked &&
202 : >$dir/ignored-but-in-index
203 done &&
204 git add -f ignored-but-in-index a/ignored-but-in-index &&
205 cat <<-\EOF >a/.gitignore &&
206 two*
207 *three
209 cat <<-\EOF >a/b/.gitignore &&
210 four
211 five
212 # this comment should affect the line numbers
214 ignored-dir/
215 # and so should this blank line:
217 !on*
218 !two
220 echo "seven" >a/b/ignored-dir/.gitignore &&
221 test -n "$HOME" &&
222 cat <<-\EOF >"$global_excludes" &&
223 globalone
224 !globaltwo
225 globalthree
227 cat <<-\EOF >>.git/info/exclude
228 per-repo
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 &&
247 test_stderr ""
250 test_expect_success '-q with multiple args' '
251 expect "" &&
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' '
257 expect "" &&
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" "
267 expect '' &&
268 test_check_ignore '$quiet_opt $verbose_opt foo' 128 &&
269 stderr_contains 'fatal: cannot have both --quiet and --verbose'
271 done
272 done
274 test_expect_success '--quiet with multiple args' '
275 expect "" &&
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' '' '
307 cd .git &&
308 test_check_ignore "foo" 128
309 ) &&
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/'
323 if test -z "$subdir"
324 then
325 where="at top-level"
326 else
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" \
376 "test_check_ignore '
377 ${subdir}non-existent
378 ${subdir}one
379 ${subdir}not-ignored
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" \
390 "test_check_ignore '
391 ${subdir}non-existent
392 ${subdir}one
393 ${subdir}not-ignored
394 ${subdir}ignored-but-in-index
395 ${subdir}ignored-and-untracked'
397 done
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' '
413 expect "3-three" &&
415 cd a &&
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" &&
422 cd a &&
423 test_check_ignore "--verbose 3-three three-not-this-one"
427 test_expect_success_multi 'nested include' \
428 'a/b/.gitignore:8:!on* a/b/one' '
429 test_check_ignore "a/b/one"
432 ############################################################################
434 # test ignored sub-directories
436 test_expect_success_multi 'ignored sub-directory' \
437 'a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir' '
438 test_check_ignore "a/b/ignored-dir"
441 test_expect_success 'multiple files inside ignored sub-directory' '
442 expect_from_stdin <<-\EOF &&
443 a/b/ignored-dir/foo
444 a/b/ignored-dir/twoooo
445 a/b/ignored-dir/seven
447 test_check_ignore "a/b/ignored-dir/foo a/b/ignored-dir/twoooo a/b/ignored-dir/seven"
450 test_expect_success 'multiple files inside ignored sub-directory with -v' '
451 expect_from_stdin <<-\EOF &&
452 a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir/foo
453 a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir/twoooo
454 a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir/seven
456 test_check_ignore "-v a/b/ignored-dir/foo a/b/ignored-dir/twoooo a/b/ignored-dir/seven"
459 test_expect_success 'cd to ignored sub-directory' '
460 expect_from_stdin <<-\EOF &&
462 twoooo
463 ../one
464 seven
465 ../../one
468 cd a/b/ignored-dir &&
469 test_check_ignore "foo twoooo ../one seven ../../one"
473 test_expect_success 'cd to ignored sub-directory with -v' '
474 expect_from_stdin <<-\EOF &&
475 a/b/.gitignore:5:ignored-dir/ foo
476 a/b/.gitignore:5:ignored-dir/ twoooo
477 a/b/.gitignore:8:!on* ../one
478 a/b/.gitignore:5:ignored-dir/ seven
479 .gitignore:1:one ../../one
482 cd a/b/ignored-dir &&
483 test_check_ignore "-v foo twoooo ../one seven ../../one"
487 ############################################################################
489 # test handling of symlinks
491 test_expect_success_multi SYMLINKS 'symlink' ':: a/symlink' '
492 test_check_ignore "a/symlink" 1
495 test_expect_success_multi SYMLINKS 'beyond a symlink' '' '
496 test_check_ignore "a/symlink/foo" 128 &&
497 test_stderr "fatal: pathspec '\''a/symlink/foo'\'' is beyond a symbolic link"
500 test_expect_success_multi SYMLINKS 'beyond a symlink from subdirectory' '' '
502 cd a &&
503 test_check_ignore "symlink/foo" 128
504 ) &&
505 test_stderr "fatal: pathspec '\''symlink/foo'\'' is beyond a symbolic link"
508 ############################################################################
510 # test handling of submodules
512 test_expect_success_multi 'submodule' '' '
513 test_check_ignore "a/submodule/one" 128 &&
514 test_stderr "fatal: Pathspec '\''a/submodule/one'\'' is in submodule '\''a/submodule'\''"
517 test_expect_success_multi 'submodule from subdirectory' '' '
519 cd a &&
520 test_check_ignore "submodule/one" 128
521 ) &&
522 test_stderr "fatal: Pathspec '\''submodule/one'\'' is in submodule '\''a/submodule'\''"
525 ############################################################################
527 # test handling of global ignore files
529 test_expect_success 'global ignore not yet enabled' '
530 expect_from_stdin <<-\EOF &&
531 .git/info/exclude:7:per-repo per-repo
532 a/.gitignore:2:*three a/globalthree
533 .git/info/exclude:7:per-repo a/per-repo
535 test_check_ignore "-v globalone per-repo a/globalthree a/per-repo not-ignored a/globaltwo"
538 test_expect_success 'global ignore' '
539 enable_global_excludes &&
540 expect_from_stdin <<-\EOF &&
541 globalone
542 per-repo
543 globalthree
544 a/globalthree
545 a/per-repo
546 globaltwo
548 test_check_ignore "globalone per-repo globalthree a/globalthree a/per-repo not-ignored globaltwo"
551 test_expect_success 'global ignore with -v' '
552 enable_global_excludes &&
553 expect_from_stdin <<-EOF &&
554 $global_excludes:1:globalone globalone
555 .git/info/exclude:7:per-repo per-repo
556 $global_excludes:3:globalthree globalthree
557 a/.gitignore:2:*three a/globalthree
558 .git/info/exclude:7:per-repo a/per-repo
559 $global_excludes:2:!globaltwo globaltwo
561 test_check_ignore "-v globalone per-repo globalthree a/globalthree a/per-repo not-ignored globaltwo"
564 ############################################################################
566 # test --stdin
568 cat <<-\EOF >stdin
570 not-ignored
571 a/one
572 a/not-ignored
573 a/b/on
574 a/b/one
575 a/b/one one
576 "a/b/one two"
577 "a/b/one\"three"
578 a/b/not-ignored
579 a/b/two
580 a/b/twooo
581 globaltwo
582 a/globaltwo
583 a/b/globaltwo
584 b/globaltwo
586 cat <<-\EOF >expected-default
588 a/one
589 a/b/on
590 a/b/one
591 a/b/one one
592 a/b/one two
593 "a/b/one\"three"
594 a/b/two
595 a/b/twooo
596 globaltwo
597 a/globaltwo
598 a/b/globaltwo
599 b/globaltwo
601 cat <<-EOF >expected-verbose
602 .gitignore:1:one one
603 .gitignore:1:one a/one
604 a/b/.gitignore:8:!on* a/b/on
605 a/b/.gitignore:8:!on* a/b/one
606 a/b/.gitignore:8:!on* a/b/one one
607 a/b/.gitignore:8:!on* a/b/one two
608 a/b/.gitignore:8:!on* "a/b/one\"three"
609 a/b/.gitignore:9:!two a/b/two
610 a/.gitignore:1:two* a/b/twooo
611 $global_excludes:2:!globaltwo globaltwo
612 $global_excludes:2:!globaltwo a/globaltwo
613 $global_excludes:2:!globaltwo a/b/globaltwo
614 $global_excludes:2:!globaltwo b/globaltwo
617 broken_c_unquote stdin >stdin0
619 broken_c_unquote expected-default >expected-default0
621 broken_c_unquote_verbose expected-verbose >expected-verbose0
623 test_expect_success '--stdin' '
624 expect_from_stdin <expected-default &&
625 test_check_ignore "--stdin" <stdin
628 test_expect_success '--stdin -q' '
629 expect "" &&
630 test_check_ignore "-q --stdin" <stdin
633 test_expect_success '--stdin -v' '
634 expect_from_stdin <expected-verbose &&
635 test_check_ignore "-v --stdin" <stdin
638 for opts in '--stdin -z' '-z --stdin'
640 test_expect_success "$opts" "
641 expect_from_stdin <expected-default0 &&
642 test_check_ignore '$opts' <stdin0
645 test_expect_success "$opts -q" "
646 expect "" &&
647 test_check_ignore '-q $opts' <stdin0
650 test_expect_success "$opts -v" "
651 expect_from_stdin <expected-verbose0 &&
652 test_check_ignore '-v $opts' <stdin0
654 done
656 cat <<-\EOF >stdin
657 ../one
658 ../not-ignored
660 not-ignored
661 b/on
662 b/one
663 b/one one
664 "b/one two"
665 "b/one\"three"
666 b/two
667 b/not-ignored
668 b/twooo
669 ../globaltwo
670 globaltwo
671 b/globaltwo
672 ../b/globaltwo
673 c/not-ignored
675 # N.B. we deliberately end STDIN with a non-matching pattern in order
676 # to test that the exit code indicates that one or more of the
677 # provided paths is ignored - in other words, that it represents an
678 # aggregation of all the results, not just the final result.
680 cat <<-EOF >expected-all
681 .gitignore:1:one ../one
682 :: ../not-ignored
683 .gitignore:1:one one
684 :: not-ignored
685 a/b/.gitignore:8:!on* b/on
686 a/b/.gitignore:8:!on* b/one
687 a/b/.gitignore:8:!on* b/one one
688 a/b/.gitignore:8:!on* b/one two
689 a/b/.gitignore:8:!on* "b/one\"three"
690 a/b/.gitignore:9:!two b/two
691 :: b/not-ignored
692 a/.gitignore:1:two* b/twooo
693 $global_excludes:2:!globaltwo ../globaltwo
694 $global_excludes:2:!globaltwo globaltwo
695 $global_excludes:2:!globaltwo b/globaltwo
696 $global_excludes:2:!globaltwo ../b/globaltwo
697 :: c/not-ignored
699 grep -v '^:: ' expected-all >expected-verbose
700 sed -e 's/.* //' expected-verbose >expected-default
702 broken_c_unquote stdin >stdin0
704 broken_c_unquote expected-default >expected-default0
706 broken_c_unquote_verbose expected-verbose >expected-verbose0
708 test_expect_success '--stdin from subdirectory' '
709 expect_from_stdin <expected-default &&
711 cd a &&
712 test_check_ignore "--stdin" <../stdin
716 test_expect_success '--stdin from subdirectory with -v' '
717 expect_from_stdin <expected-verbose &&
719 cd a &&
720 test_check_ignore "--stdin -v" <../stdin
724 test_expect_success '--stdin from subdirectory with -v -n' '
725 expect_from_stdin <expected-all &&
727 cd a &&
728 test_check_ignore "--stdin -v -n" <../stdin
732 for opts in '--stdin -z' '-z --stdin'
734 test_expect_success "$opts from subdirectory" '
735 expect_from_stdin <expected-default0 &&
737 cd a &&
738 test_check_ignore "'"$opts"'" <../stdin0
742 test_expect_success "$opts from subdirectory with -v" '
743 expect_from_stdin <expected-verbose0 &&
745 cd a &&
746 test_check_ignore "'"$opts"' -v" <../stdin0
749 done
751 test_expect_success PIPE 'streaming support for --stdin' '
752 mkfifo in out &&
753 (git check-ignore -n -v --stdin <in >out &) &&
755 # We cannot just "echo >in" because check-ignore would get EOF
756 # after echo exited; instead we open the descriptor in our
757 # shell, and then echo to the fd. We make sure to close it at
758 # the end, so that the subprocess does get EOF and dies
759 # properly.
761 # Similarly, we must keep "out" open so that check-ignore does
762 # not ever get SIGPIPE trying to write to us. Not only would that
763 # produce incorrect results, but then there would be no writer on the
764 # other end of the pipe, and we would potentially block forever trying
765 # to open it.
766 exec 9>in &&
767 exec 8<out &&
768 test_when_finished "exec 9>&-" &&
769 test_when_finished "exec 8<&-" &&
770 echo >&9 one &&
771 read response <&8 &&
772 echo "$response" | grep "^\.gitignore:1:one one" &&
773 echo >&9 two &&
774 read response <&8 &&
775 echo "$response" | grep "^:: two"
778 test_done