add git-check-ignore sub-command
[git/jnareb-git.git] / t / t0008-ignores.sh
blob9b0fcd610d2fe0bd6e2dae1303dd3c49492ac283
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 test_expect_success_multi () {
79 prereq=
80 if test $# -eq 4
81 then
82 prereq=$1
83 shift
85 testname="$1" expect_verbose="$2" code="$3"
87 expect=$( echo "$expect_verbose" | sed -e 's/.* //' )
89 test_expect_success $prereq "$testname" '
90 expect "$expect" &&
91 eval "$code"
94 for quiet_opt in '-q' '--quiet'
96 test_expect_success $prereq "$testname${quiet_opt:+ with $quiet_opt}" "
97 expect '' &&
98 $code
100 done
101 quiet_opt=
103 for verbose_opt in '-v' '--verbose'
105 test_expect_success $prereq "$testname${verbose_opt:+ with $verbose_opt}" "
106 expect '$expect_verbose' &&
107 $code
109 done
110 verbose_opt=
113 test_expect_success 'setup' '
114 init_vars &&
115 mkdir -p a/b/ignored-dir a/submodule b &&
116 if test_have_prereq SYMLINKS
117 then
118 ln -s b a/symlink
119 fi &&
121 cd a/submodule &&
122 git init &&
123 echo a >a &&
124 git add a &&
125 git commit -m"commit in submodule"
126 ) &&
127 git add a/submodule &&
128 cat <<-\EOF >.gitignore &&
130 ignored-*
132 touch {,a/}{not-ignored,ignored-{and-untracked,but-in-index}} &&
133 git add -f {,a/}ignored-but-in-index
134 cat <<-\EOF >a/.gitignore &&
135 two*
136 *three
138 cat <<-\EOF >a/b/.gitignore &&
139 four
140 five
141 # this comment should affect the line numbers
143 ignored-dir/
144 # and so should this blank line:
146 !on*
147 !two
149 echo "seven" >a/b/ignored-dir/.gitignore &&
150 test -n "$HOME" &&
151 cat <<-\EOF >"$global_excludes" &&
152 globalone
153 !globaltwo
154 globalthree
156 cat <<-\EOF >>.git/info/exclude
157 per-repo
161 ############################################################################
163 # test invalid inputs
165 test_expect_success_multi 'empty command line' '' '
166 test_check_ignore "" 128 &&
167 stderr_contains "fatal: no path specified"
170 test_expect_success_multi '--stdin with empty STDIN' '' '
171 test_check_ignore "--stdin" 1 </dev/null &&
172 if test -n "$quiet_opt"; then
173 test_stderr ""
174 else
175 test_stderr "no pathspec given."
179 test_expect_success '-q with multiple args' '
180 expect "" &&
181 test_check_ignore "-q one two" 128 &&
182 stderr_contains "fatal: --quiet is only valid with a single pathname"
185 test_expect_success '--quiet with multiple args' '
186 expect "" &&
187 test_check_ignore "--quiet one two" 128 &&
188 stderr_contains "fatal: --quiet is only valid with a single pathname"
191 for verbose_opt in '-v' '--verbose'
193 for quiet_opt in '-q' '--quiet'
195 test_expect_success "$quiet_opt $verbose_opt" "
196 expect '' &&
197 test_check_ignore '$quiet_opt $verbose_opt foo' 128 &&
198 stderr_contains 'fatal: cannot have both --quiet and --verbose'
200 done
201 done
203 test_expect_success '--quiet with multiple args' '
204 expect "" &&
205 test_check_ignore "--quiet one two" 128 &&
206 stderr_contains "fatal: --quiet is only valid with a single pathname"
209 test_expect_success_multi 'erroneous use of --' '' '
210 test_check_ignore "--" 128 &&
211 stderr_contains "fatal: no path specified"
214 test_expect_success_multi '--stdin with superfluous arg' '' '
215 test_check_ignore "--stdin foo" 128 &&
216 stderr_contains "fatal: cannot specify pathnames with --stdin"
219 test_expect_success_multi '--stdin -z with superfluous arg' '' '
220 test_check_ignore "--stdin -z foo" 128 &&
221 stderr_contains "fatal: cannot specify pathnames with --stdin"
224 test_expect_success_multi '-z without --stdin' '' '
225 test_check_ignore "-z" 128 &&
226 stderr_contains "fatal: -z only makes sense with --stdin"
229 test_expect_success_multi '-z without --stdin and superfluous arg' '' '
230 test_check_ignore "-z foo" 128 &&
231 stderr_contains "fatal: -z only makes sense with --stdin"
234 test_expect_success_multi 'needs work tree' '' '
236 cd .git &&
237 test_check_ignore "foo" 128
238 ) &&
239 stderr_contains "fatal: This operation must be run in a work tree"
242 ############################################################################
244 # test standard ignores
246 # First make sure that the presence of a file in the working tree
247 # does not impact results, but that the presence of a file in the
248 # index does.
250 for subdir in '' 'a/'
252 if test -z "$subdir"
253 then
254 where="at top-level"
255 else
256 where="in subdir $subdir"
259 test_expect_success_multi "non-existent file $where not ignored" '' "
260 test_check_ignore '${subdir}non-existent' 1
263 test_expect_success_multi "non-existent file $where ignored" \
264 ".gitignore:1:one ${subdir}one" "
265 test_check_ignore '${subdir}one'
268 test_expect_success_multi "existing untracked file $where not ignored" '' "
269 test_check_ignore '${subdir}not-ignored' 1
272 test_expect_success_multi "existing tracked file $where not ignored" '' "
273 test_check_ignore '${subdir}ignored-but-in-index' 1
276 test_expect_success_multi "existing untracked file $where ignored" \
277 ".gitignore:2:ignored-* ${subdir}ignored-and-untracked" "
278 test_check_ignore '${subdir}ignored-and-untracked'
280 done
282 # Having established the above, from now on we mostly test against
283 # files which do not exist in the working tree or index.
285 test_expect_success 'sub-directory local ignore' '
286 expect "a/3-three" &&
287 test_check_ignore "a/3-three a/three-not-this-one"
290 test_expect_success 'sub-directory local ignore with --verbose' '
291 expect "a/.gitignore:2:*three a/3-three" &&
292 test_check_ignore "--verbose a/3-three a/three-not-this-one"
295 test_expect_success 'local ignore inside a sub-directory' '
296 expect "3-three" &&
298 cd a &&
299 test_check_ignore "3-three three-not-this-one"
302 test_expect_success 'local ignore inside a sub-directory with --verbose' '
303 expect "a/.gitignore:2:*three 3-three" &&
305 cd a &&
306 test_check_ignore "--verbose 3-three three-not-this-one"
310 test_expect_success_multi 'nested include' \
311 'a/b/.gitignore:8:!on* a/b/one' '
312 test_check_ignore "a/b/one"
315 ############################################################################
317 # test ignored sub-directories
319 test_expect_success_multi 'ignored sub-directory' \
320 'a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir' '
321 test_check_ignore "a/b/ignored-dir"
324 test_expect_success 'multiple files inside ignored sub-directory' '
325 expect_from_stdin <<-\EOF &&
326 a/b/ignored-dir/foo
327 a/b/ignored-dir/twoooo
328 a/b/ignored-dir/seven
330 test_check_ignore "a/b/ignored-dir/foo a/b/ignored-dir/twoooo a/b/ignored-dir/seven"
333 test_expect_success 'multiple files inside ignored sub-directory with -v' '
334 expect_from_stdin <<-\EOF &&
335 a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir/foo
336 a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir/twoooo
337 a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir/seven
339 test_check_ignore "-v a/b/ignored-dir/foo a/b/ignored-dir/twoooo a/b/ignored-dir/seven"
342 test_expect_success 'cd to ignored sub-directory' '
343 expect_from_stdin <<-\EOF &&
345 twoooo
346 ../one
347 seven
348 ../../one
351 cd a/b/ignored-dir &&
352 test_check_ignore "foo twoooo ../one seven ../../one"
356 test_expect_success 'cd to ignored sub-directory with -v' '
357 expect_from_stdin <<-\EOF &&
358 a/b/.gitignore:5:ignored-dir/ foo
359 a/b/.gitignore:5:ignored-dir/ twoooo
360 a/b/.gitignore:8:!on* ../one
361 a/b/.gitignore:5:ignored-dir/ seven
362 .gitignore:1:one ../../one
365 cd a/b/ignored-dir &&
366 test_check_ignore "-v foo twoooo ../one seven ../../one"
370 ############################################################################
372 # test handling of symlinks
374 test_expect_success_multi SYMLINKS 'symlink' '' '
375 test_check_ignore "a/symlink" 1
378 test_expect_success_multi SYMLINKS 'beyond a symlink' '' '
379 test_check_ignore "a/symlink/foo" 128 &&
380 test_stderr "fatal: '\''a/symlink/foo'\'' is beyond a symbolic link"
383 test_expect_success_multi SYMLINKS 'beyond a symlink from subdirectory' '' '
385 cd a &&
386 test_check_ignore "symlink/foo" 128
387 ) &&
388 test_stderr "fatal: '\''symlink/foo'\'' is beyond a symbolic link"
391 ############################################################################
393 # test handling of submodules
395 test_expect_success_multi 'submodule' '' '
396 test_check_ignore "a/submodule/one" 128 &&
397 test_stderr "fatal: Path '\''a/submodule/one'\'' is in submodule '\''a/submodule'\''"
400 test_expect_success_multi 'submodule from subdirectory' '' '
402 cd a &&
403 test_check_ignore "submodule/one" 128
404 ) &&
405 test_stderr "fatal: Path '\''a/submodule/one'\'' is in submodule '\''a/submodule'\''"
408 ############################################################################
410 # test handling of global ignore files
412 test_expect_success 'global ignore not yet enabled' '
413 expect_from_stdin <<-\EOF &&
414 .git/info/exclude:7:per-repo per-repo
415 a/.gitignore:2:*three a/globalthree
416 .git/info/exclude:7:per-repo a/per-repo
418 test_check_ignore "-v globalone per-repo a/globalthree a/per-repo not-ignored a/globaltwo"
421 test_expect_success 'global ignore' '
422 enable_global_excludes &&
423 expect_from_stdin <<-\EOF &&
424 globalone
425 per-repo
426 globalthree
427 a/globalthree
428 a/per-repo
429 globaltwo
431 test_check_ignore "globalone per-repo globalthree a/globalthree a/per-repo not-ignored globaltwo"
434 test_expect_success 'global ignore with -v' '
435 enable_global_excludes &&
436 expect_from_stdin <<-EOF &&
437 $global_excludes:1:globalone globalone
438 .git/info/exclude:7:per-repo per-repo
439 $global_excludes:3:globalthree globalthree
440 a/.gitignore:2:*three a/globalthree
441 .git/info/exclude:7:per-repo a/per-repo
442 $global_excludes:2:!globaltwo globaltwo
444 test_check_ignore "-v globalone per-repo globalthree a/globalthree a/per-repo not-ignored globaltwo"
447 ############################################################################
449 # test --stdin
451 cat <<-\EOF >stdin
453 not-ignored
454 a/one
455 a/not-ignored
456 a/b/on
457 a/b/one
458 a/b/one one
459 "a/b/one two"
460 "a/b/one\"three"
461 a/b/not-ignored
462 a/b/two
463 a/b/twooo
464 globaltwo
465 a/globaltwo
466 a/b/globaltwo
467 b/globaltwo
469 cat <<-\EOF >expected-default
471 a/one
472 a/b/on
473 a/b/one
474 a/b/one one
475 a/b/one two
476 "a/b/one\"three"
477 a/b/two
478 a/b/twooo
479 globaltwo
480 a/globaltwo
481 a/b/globaltwo
482 b/globaltwo
484 cat <<-EOF >expected-verbose
485 .gitignore:1:one one
486 .gitignore:1:one a/one
487 a/b/.gitignore:8:!on* a/b/on
488 a/b/.gitignore:8:!on* a/b/one
489 a/b/.gitignore:8:!on* a/b/one one
490 a/b/.gitignore:8:!on* a/b/one two
491 a/b/.gitignore:8:!on* "a/b/one\"three"
492 a/b/.gitignore:9:!two a/b/two
493 a/.gitignore:1:two* a/b/twooo
494 $global_excludes:2:!globaltwo globaltwo
495 $global_excludes:2:!globaltwo a/globaltwo
496 $global_excludes:2:!globaltwo a/b/globaltwo
497 $global_excludes:2:!globaltwo b/globaltwo
500 sed -e 's/^"//' -e 's/\\//' -e 's/"$//' stdin | \
501 tr "\n" "\0" >stdin0
502 sed -e 's/^"//' -e 's/\\//' -e 's/"$//' expected-default | \
503 tr "\n" "\0" >expected-default0
504 sed -e 's/ "/ /' -e 's/\\//' -e 's/"$//' expected-verbose | \
505 tr ":\t\n" "\0" >expected-verbose0
507 test_expect_success '--stdin' '
508 expect_from_stdin <expected-default &&
509 test_check_ignore "--stdin" <stdin
512 test_expect_success '--stdin -q' '
513 expect "" &&
514 test_check_ignore "-q --stdin" <stdin
517 test_expect_success '--stdin -v' '
518 expect_from_stdin <expected-verbose &&
519 test_check_ignore "-v --stdin" <stdin
522 for opts in '--stdin -z' '-z --stdin'
524 test_expect_success "$opts" "
525 expect_from_stdin <expected-default0 &&
526 test_check_ignore '$opts' <stdin0
529 test_expect_success "$opts -q" "
530 expect "" &&
531 test_check_ignore '-q $opts' <stdin0
534 test_expect_success "$opts -v" "
535 expect_from_stdin <expected-verbose0 &&
536 test_check_ignore '-v $opts' <stdin0
538 done
540 cat <<-\EOF >stdin
541 ../one
542 ../not-ignored
544 not-ignored
545 b/on
546 b/one
547 b/one one
548 "b/one two"
549 "b/one\"three"
550 b/two
551 b/not-ignored
552 b/twooo
553 ../globaltwo
554 globaltwo
555 b/globaltwo
556 ../b/globaltwo
558 cat <<-\EOF >expected-default
559 ../one
561 b/on
562 b/one
563 b/one one
564 b/one two
565 "b/one\"three"
566 b/two
567 b/twooo
568 ../globaltwo
569 globaltwo
570 b/globaltwo
571 ../b/globaltwo
573 cat <<-EOF >expected-verbose
574 .gitignore:1:one ../one
575 .gitignore:1:one one
576 a/b/.gitignore:8:!on* b/on
577 a/b/.gitignore:8:!on* b/one
578 a/b/.gitignore:8:!on* b/one one
579 a/b/.gitignore:8:!on* b/one two
580 a/b/.gitignore:8:!on* "b/one\"three"
581 a/b/.gitignore:9:!two b/two
582 a/.gitignore:1:two* b/twooo
583 $global_excludes:2:!globaltwo ../globaltwo
584 $global_excludes:2:!globaltwo globaltwo
585 $global_excludes:2:!globaltwo b/globaltwo
586 $global_excludes:2:!globaltwo ../b/globaltwo
589 sed -e 's/^"//' -e 's/\\//' -e 's/"$//' stdin | \
590 tr "\n" "\0" >stdin0
591 sed -e 's/^"//' -e 's/\\//' -e 's/"$//' expected-default | \
592 tr "\n" "\0" >expected-default0
593 sed -e 's/ "/ /' -e 's/\\//' -e 's/"$//' expected-verbose | \
594 tr ":\t\n" "\0" >expected-verbose0
596 test_expect_success '--stdin from subdirectory' '
597 expect_from_stdin <expected-default &&
599 cd a &&
600 test_check_ignore "--stdin" <../stdin
604 test_expect_success '--stdin from subdirectory with -v' '
605 expect_from_stdin <expected-verbose &&
607 cd a &&
608 test_check_ignore "--stdin -v" <../stdin
612 for opts in '--stdin -z' '-z --stdin'
614 test_expect_success "$opts from subdirectory" '
615 expect_from_stdin <expected-default0 &&
617 cd a &&
618 test_check_ignore "'"$opts"'" <../stdin0
622 test_expect_success "$opts from subdirectory with -v" '
623 expect_from_stdin <expected-verbose0 &&
625 cd a &&
626 test_check_ignore "'"$opts"' -v" <../stdin0
629 done
632 test_done