Merge branch 'rr/push-head' into maint
[git/mjg.git] / t / t0008-ignores.sh
blob9c1bde1fd6e6424f7af732556656a9daf9be350b
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 stderr_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
52 stderr_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
64 test_check_ignore () {
65 args="$1" expect_code="${2:-0}" global_args="$3"
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"
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.
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)
88 test_expect_success_multi () {
89 prereq=
90 if test $# -eq 4
91 then
92 prereq=$1
93 shift
95 testname="$1" expect_verbose="$2" code="$3"
97 expect=$( echo "$expect_verbose" | sed -e 's/.* //' )
99 test_expect_success $prereq "$testname" '
100 expect "$expect" &&
101 eval "$code"
104 for quiet_opt in '-q' '--quiet'
106 test_expect_success $prereq "$testname${quiet_opt:+ with $quiet_opt}" "
107 expect '' &&
108 $code
110 done
111 quiet_opt=
113 for verbose_opt in '-v' '--verbose'
115 test_expect_success $prereq "$testname${verbose_opt:+ with $verbose_opt}" "
116 expect '$expect_verbose' &&
117 $code
119 done
120 verbose_opt=
123 test_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 &&
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 &&
140 ignored-*
141 top-level-dir/
143 for dir in . a
145 : >$dir/not-ignored &&
146 : >$dir/ignored-and-untracked &&
147 : >$dir/ignored-but-in-index
148 done &&
149 git add -f ignored-but-in-index a/ignored-but-in-index &&
150 cat <<-\EOF >a/.gitignore &&
151 two*
152 *three
154 cat <<-\EOF >a/b/.gitignore &&
155 four
156 five
157 # this comment should affect the line numbers
159 ignored-dir/
160 # and so should this blank line:
162 !on*
163 !two
165 echo "seven" >a/b/ignored-dir/.gitignore &&
166 test -n "$HOME" &&
167 cat <<-\EOF >"$global_excludes" &&
168 globalone
169 !globaltwo
170 globalthree
172 cat <<-\EOF >>.git/info/exclude
173 per-repo
177 ############################################################################
179 # test invalid inputs
181 test_expect_success_multi '. corner-case' '' '
182 test_check_ignore . 1
185 test_expect_success_multi 'empty command line' '' '
186 test_check_ignore "" 128 &&
187 stderr_contains "fatal: no path specified"
190 test_expect_success_multi '--stdin with empty STDIN' '' '
191 test_check_ignore "--stdin" 1 </dev/null &&
192 if test -n "$quiet_opt"; then
193 test_stderr ""
194 else
195 test_stderr "no pathspec given."
199 test_expect_success '-q with multiple args' '
200 expect "" &&
201 test_check_ignore "-q one two" 128 &&
202 stderr_contains "fatal: --quiet is only valid with a single pathname"
205 test_expect_success '--quiet with multiple args' '
206 expect "" &&
207 test_check_ignore "--quiet one two" 128 &&
208 stderr_contains "fatal: --quiet is only valid with a single pathname"
211 for verbose_opt in '-v' '--verbose'
213 for quiet_opt in '-q' '--quiet'
215 test_expect_success "$quiet_opt $verbose_opt" "
216 expect '' &&
217 test_check_ignore '$quiet_opt $verbose_opt foo' 128 &&
218 stderr_contains 'fatal: cannot have both --quiet and --verbose'
220 done
221 done
223 test_expect_success '--quiet with multiple args' '
224 expect "" &&
225 test_check_ignore "--quiet one two" 128 &&
226 stderr_contains "fatal: --quiet is only valid with a single pathname"
229 test_expect_success_multi 'erroneous use of --' '' '
230 test_check_ignore "--" 128 &&
231 stderr_contains "fatal: no path specified"
234 test_expect_success_multi '--stdin with superfluous arg' '' '
235 test_check_ignore "--stdin foo" 128 &&
236 stderr_contains "fatal: cannot specify pathnames with --stdin"
239 test_expect_success_multi '--stdin -z with superfluous arg' '' '
240 test_check_ignore "--stdin -z foo" 128 &&
241 stderr_contains "fatal: cannot specify pathnames with --stdin"
244 test_expect_success_multi '-z without --stdin' '' '
245 test_check_ignore "-z" 128 &&
246 stderr_contains "fatal: -z only makes sense with --stdin"
249 test_expect_success_multi '-z without --stdin and superfluous arg' '' '
250 test_check_ignore "-z foo" 128 &&
251 stderr_contains "fatal: -z only makes sense with --stdin"
254 test_expect_success_multi 'needs work tree' '' '
256 cd .git &&
257 test_check_ignore "foo" 128
258 ) &&
259 stderr_contains "fatal: This operation must be run in a work tree"
262 ############################################################################
264 # test standard ignores
266 # First make sure that the presence of a file in the working tree
267 # does not impact results, but that the presence of a file in the
268 # index does.
270 for subdir in '' 'a/'
272 if test -z "$subdir"
273 then
274 where="at top-level"
275 else
276 where="in subdir $subdir"
279 test_expect_success_multi "non-existent file $where not ignored" '' "
280 test_check_ignore '${subdir}non-existent' 1
283 test_expect_success_multi "non-existent file $where ignored" \
284 ".gitignore:1:one ${subdir}one" "
285 test_check_ignore '${subdir}one'
288 test_expect_success_multi "existing untracked file $where not ignored" '' "
289 test_check_ignore '${subdir}not-ignored' 1
292 test_expect_success_multi "existing tracked file $where not ignored" '' "
293 test_check_ignore '${subdir}ignored-but-in-index' 1
296 test_expect_success_multi "existing untracked file $where ignored" \
297 ".gitignore:2:ignored-* ${subdir}ignored-and-untracked" "
298 test_check_ignore '${subdir}ignored-and-untracked'
300 done
302 # Having established the above, from now on we mostly test against
303 # files which do not exist in the working tree or index.
305 test_expect_success 'sub-directory local ignore' '
306 expect "a/3-three" &&
307 test_check_ignore "a/3-three a/three-not-this-one"
310 test_expect_success 'sub-directory local ignore with --verbose' '
311 expect "a/.gitignore:2:*three a/3-three" &&
312 test_check_ignore "--verbose a/3-three a/three-not-this-one"
315 test_expect_success 'local ignore inside a sub-directory' '
316 expect "3-three" &&
318 cd a &&
319 test_check_ignore "3-three three-not-this-one"
322 test_expect_success 'local ignore inside a sub-directory with --verbose' '
323 expect "a/.gitignore:2:*three 3-three" &&
325 cd a &&
326 test_check_ignore "--verbose 3-three three-not-this-one"
330 test_expect_success_multi 'nested include' \
331 'a/b/.gitignore:8:!on* a/b/one' '
332 test_check_ignore "a/b/one"
335 ############################################################################
337 # test ignored sub-directories
339 test_expect_success_multi 'ignored sub-directory' \
340 'a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir' '
341 test_check_ignore "a/b/ignored-dir"
344 test_expect_success 'multiple files inside ignored sub-directory' '
345 expect_from_stdin <<-\EOF &&
346 a/b/ignored-dir/foo
347 a/b/ignored-dir/twoooo
348 a/b/ignored-dir/seven
350 test_check_ignore "a/b/ignored-dir/foo a/b/ignored-dir/twoooo a/b/ignored-dir/seven"
353 test_expect_success 'multiple files inside ignored sub-directory with -v' '
354 expect_from_stdin <<-\EOF &&
355 a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir/foo
356 a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir/twoooo
357 a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir/seven
359 test_check_ignore "-v a/b/ignored-dir/foo a/b/ignored-dir/twoooo a/b/ignored-dir/seven"
362 test_expect_success 'cd to ignored sub-directory' '
363 expect_from_stdin <<-\EOF &&
365 twoooo
366 ../one
367 seven
368 ../../one
371 cd a/b/ignored-dir &&
372 test_check_ignore "foo twoooo ../one seven ../../one"
376 test_expect_success 'cd to ignored sub-directory with -v' '
377 expect_from_stdin <<-\EOF &&
378 a/b/.gitignore:5:ignored-dir/ foo
379 a/b/.gitignore:5:ignored-dir/ twoooo
380 a/b/.gitignore:8:!on* ../one
381 a/b/.gitignore:5:ignored-dir/ seven
382 .gitignore:1:one ../../one
385 cd a/b/ignored-dir &&
386 test_check_ignore "-v foo twoooo ../one seven ../../one"
390 ############################################################################
392 # test handling of symlinks
394 test_expect_success_multi SYMLINKS 'symlink' '' '
395 test_check_ignore "a/symlink" 1
398 test_expect_success_multi SYMLINKS 'beyond a symlink' '' '
399 test_check_ignore "a/symlink/foo" 128 &&
400 test_stderr "fatal: '\''a/symlink/foo'\'' is beyond a symbolic link"
403 test_expect_success_multi SYMLINKS 'beyond a symlink from subdirectory' '' '
405 cd a &&
406 test_check_ignore "symlink/foo" 128
407 ) &&
408 test_stderr "fatal: '\''symlink/foo'\'' is beyond a symbolic link"
411 ############################################################################
413 # test handling of submodules
415 test_expect_success_multi 'submodule' '' '
416 test_check_ignore "a/submodule/one" 128 &&
417 test_stderr "fatal: Path '\''a/submodule/one'\'' is in submodule '\''a/submodule'\''"
420 test_expect_success_multi 'submodule from subdirectory' '' '
422 cd a &&
423 test_check_ignore "submodule/one" 128
424 ) &&
425 test_stderr "fatal: Path '\''a/submodule/one'\'' is in submodule '\''a/submodule'\''"
428 ############################################################################
430 # test handling of global ignore files
432 test_expect_success 'global ignore not yet enabled' '
433 expect_from_stdin <<-\EOF &&
434 .git/info/exclude:7:per-repo per-repo
435 a/.gitignore:2:*three a/globalthree
436 .git/info/exclude:7:per-repo a/per-repo
438 test_check_ignore "-v globalone per-repo a/globalthree a/per-repo not-ignored a/globaltwo"
441 test_expect_success 'global ignore' '
442 enable_global_excludes &&
443 expect_from_stdin <<-\EOF &&
444 globalone
445 per-repo
446 globalthree
447 a/globalthree
448 a/per-repo
449 globaltwo
451 test_check_ignore "globalone per-repo globalthree a/globalthree a/per-repo not-ignored globaltwo"
454 test_expect_success 'global ignore with -v' '
455 enable_global_excludes &&
456 expect_from_stdin <<-EOF &&
457 $global_excludes:1:globalone globalone
458 .git/info/exclude:7:per-repo per-repo
459 $global_excludes:3:globalthree globalthree
460 a/.gitignore:2:*three a/globalthree
461 .git/info/exclude:7:per-repo a/per-repo
462 $global_excludes:2:!globaltwo globaltwo
464 test_check_ignore "-v globalone per-repo globalthree a/globalthree a/per-repo not-ignored globaltwo"
467 ############################################################################
469 # test --stdin
471 cat <<-\EOF >stdin
473 not-ignored
474 a/one
475 a/not-ignored
476 a/b/on
477 a/b/one
478 a/b/one one
479 "a/b/one two"
480 "a/b/one\"three"
481 a/b/not-ignored
482 a/b/two
483 a/b/twooo
484 globaltwo
485 a/globaltwo
486 a/b/globaltwo
487 b/globaltwo
489 cat <<-\EOF >expected-default
491 a/one
492 a/b/on
493 a/b/one
494 a/b/one one
495 a/b/one two
496 "a/b/one\"three"
497 a/b/two
498 a/b/twooo
499 globaltwo
500 a/globaltwo
501 a/b/globaltwo
502 b/globaltwo
504 cat <<-EOF >expected-verbose
505 .gitignore:1:one one
506 .gitignore:1:one a/one
507 a/b/.gitignore:8:!on* a/b/on
508 a/b/.gitignore:8:!on* a/b/one
509 a/b/.gitignore:8:!on* a/b/one one
510 a/b/.gitignore:8:!on* a/b/one two
511 a/b/.gitignore:8:!on* "a/b/one\"three"
512 a/b/.gitignore:9:!two a/b/two
513 a/.gitignore:1:two* a/b/twooo
514 $global_excludes:2:!globaltwo globaltwo
515 $global_excludes:2:!globaltwo a/globaltwo
516 $global_excludes:2:!globaltwo a/b/globaltwo
517 $global_excludes:2:!globaltwo b/globaltwo
520 sed -e 's/^"//' -e 's/\\//' -e 's/"$//' stdin | \
521 tr "\n" "\0" >stdin0
522 sed -e 's/^"//' -e 's/\\//' -e 's/"$//' expected-default | \
523 tr "\n" "\0" >expected-default0
524 sed -e 's/ "/ /' -e 's/\\//' -e 's/"$//' expected-verbose | \
525 tr ":\t\n" "\0" >expected-verbose0
527 test_expect_success '--stdin' '
528 expect_from_stdin <expected-default &&
529 test_check_ignore "--stdin" <stdin
532 test_expect_success '--stdin -q' '
533 expect "" &&
534 test_check_ignore "-q --stdin" <stdin
537 test_expect_success '--stdin -v' '
538 expect_from_stdin <expected-verbose &&
539 test_check_ignore "-v --stdin" <stdin
542 for opts in '--stdin -z' '-z --stdin'
544 test_expect_success "$opts" "
545 expect_from_stdin <expected-default0 &&
546 test_check_ignore '$opts' <stdin0
549 test_expect_success "$opts -q" "
550 expect "" &&
551 test_check_ignore '-q $opts' <stdin0
554 test_expect_success "$opts -v" "
555 expect_from_stdin <expected-verbose0 &&
556 test_check_ignore '-v $opts' <stdin0
558 done
560 cat <<-\EOF >stdin
561 ../one
562 ../not-ignored
564 not-ignored
565 b/on
566 b/one
567 b/one one
568 "b/one two"
569 "b/one\"three"
570 b/two
571 b/not-ignored
572 b/twooo
573 ../globaltwo
574 globaltwo
575 b/globaltwo
576 ../b/globaltwo
578 cat <<-\EOF >expected-default
579 ../one
581 b/on
582 b/one
583 b/one one
584 b/one two
585 "b/one\"three"
586 b/two
587 b/twooo
588 ../globaltwo
589 globaltwo
590 b/globaltwo
591 ../b/globaltwo
593 cat <<-EOF >expected-verbose
594 .gitignore:1:one ../one
595 .gitignore:1:one one
596 a/b/.gitignore:8:!on* b/on
597 a/b/.gitignore:8:!on* b/one
598 a/b/.gitignore:8:!on* b/one one
599 a/b/.gitignore:8:!on* b/one two
600 a/b/.gitignore:8:!on* "b/one\"three"
601 a/b/.gitignore:9:!two b/two
602 a/.gitignore:1:two* b/twooo
603 $global_excludes:2:!globaltwo ../globaltwo
604 $global_excludes:2:!globaltwo globaltwo
605 $global_excludes:2:!globaltwo b/globaltwo
606 $global_excludes:2:!globaltwo ../b/globaltwo
609 sed -e 's/^"//' -e 's/\\//' -e 's/"$//' stdin | \
610 tr "\n" "\0" >stdin0
611 sed -e 's/^"//' -e 's/\\//' -e 's/"$//' expected-default | \
612 tr "\n" "\0" >expected-default0
613 sed -e 's/ "/ /' -e 's/\\//' -e 's/"$//' expected-verbose | \
614 tr ":\t\n" "\0" >expected-verbose0
616 test_expect_success '--stdin from subdirectory' '
617 expect_from_stdin <expected-default &&
619 cd a &&
620 test_check_ignore "--stdin" <../stdin
624 test_expect_success '--stdin from subdirectory with -v' '
625 expect_from_stdin <expected-verbose &&
627 cd a &&
628 test_check_ignore "--stdin -v" <../stdin
632 for opts in '--stdin -z' '-z --stdin'
634 test_expect_success "$opts from subdirectory" '
635 expect_from_stdin <expected-default0 &&
637 cd a &&
638 test_check_ignore "'"$opts"'" <../stdin0
642 test_expect_success "$opts from subdirectory with -v" '
643 expect_from_stdin <expected-verbose0 &&
645 cd a &&
646 test_check_ignore "'"$opts"' -v" <../stdin0
649 done
652 test_done