9b0fcd610d2fe0bd6e2dae1303dd3c49492ac283
1#!/bin/sh
2
3test_description=check-ignore
4
5. ./test-lib.sh
6
7init_vars () {
8 global_excludes="$(pwd)/global-excludes"
9}
10
11enable_global_excludes () {
12 init_vars &&
13 git config core.excludesfile "$global_excludes"
14}
15
16expect_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"
23 fi
24}
25
26expect () {
27 expect_in stdout "$1"
28}
29
30expect_from_stdin () {
31 cat >"$HOME/expected-stdout"
32}
33
34test_stderr () {
35 expected="$1"
36 expect_in stderr "$1" &&
37 test_cmp "$HOME/expected-stderr" "$HOME/stderr"
38}
39
40stderr_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
49 fi
50}
51
52stderr_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
61 fi
62}
63
64test_check_ignore () {
65 args="$1" expect_code="${2:-0}" global_args="$3"
66
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"
76}
77
78test_expect_success_multi () {
79 prereq=
80 if test $# -eq 4
81 then
82 prereq=$1
83 shift
84 fi
85 testname="$1" expect_verbose="$2" code="$3"
86
87 expect=$( echo "$expect_verbose" | sed -e 's/.* //' )
88
89 test_expect_success $prereq "$testname" '
90 expect "$expect" &&
91 eval "$code"
92 '
93
94 for quiet_opt in '-q' '--quiet'
95 do
96 test_expect_success $prereq "$testname${quiet_opt:+ with $quiet_opt}" "
97 expect '' &&
98 $code
99 "
100 done
101 quiet_opt=
102
103 for verbose_opt in '-v' '--verbose'
104 do
105 test_expect_success $prereq "$testname${verbose_opt:+ with $verbose_opt}" "
106 expect '$expect_verbose' &&
107 $code
108 "
109 done
110 verbose_opt=
111}
112
113test_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 &&
120 (
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 &&
129 one
130 ignored-*
131 EOF
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
137 EOF
138 cat <<-\EOF >a/b/.gitignore &&
139 four
140 five
141 # this comment should affect the line numbers
142 six
143 ignored-dir/
144 # and so should this blank line:
145
146 !on*
147 !two
148 EOF
149 echo "seven" >a/b/ignored-dir/.gitignore &&
150 test -n "$HOME" &&
151 cat <<-\EOF >"$global_excludes" &&
152 globalone
153 !globaltwo
154 globalthree
155 EOF
156 cat <<-\EOF >>.git/info/exclude
157 per-repo
158 EOF
159'
160
161############################################################################
162#
163# test invalid inputs
164
165test_expect_success_multi 'empty command line' '' '
166 test_check_ignore "" 128 &&
167 stderr_contains "fatal: no path specified"
168'
169
170test_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."
176 fi
177'
178
179test_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"
183'
184
185test_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"
189'
190
191for verbose_opt in '-v' '--verbose'
192do
193 for quiet_opt in '-q' '--quiet'
194 do
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'
199 "
200 done
201done
202
203test_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"
207'
208
209test_expect_success_multi 'erroneous use of --' '' '
210 test_check_ignore "--" 128 &&
211 stderr_contains "fatal: no path specified"
212'
213
214test_expect_success_multi '--stdin with superfluous arg' '' '
215 test_check_ignore "--stdin foo" 128 &&
216 stderr_contains "fatal: cannot specify pathnames with --stdin"
217'
218
219test_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"
222'
223
224test_expect_success_multi '-z without --stdin' '' '
225 test_check_ignore "-z" 128 &&
226 stderr_contains "fatal: -z only makes sense with --stdin"
227'
228
229test_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"
232'
233
234test_expect_success_multi 'needs work tree' '' '
235 (
236 cd .git &&
237 test_check_ignore "foo" 128
238 ) &&
239 stderr_contains "fatal: This operation must be run in a work tree"
240'
241
242############################################################################
243#
244# test standard ignores
245
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.
249
250for subdir in '' 'a/'
251do
252 if test -z "$subdir"
253 then
254 where="at top-level"
255 else
256 where="in subdir $subdir"
257 fi
258
259 test_expect_success_multi "non-existent file $where not ignored" '' "
260 test_check_ignore '${subdir}non-existent' 1
261 "
262
263 test_expect_success_multi "non-existent file $where ignored" \
264 ".gitignore:1:one ${subdir}one" "
265 test_check_ignore '${subdir}one'
266 "
267
268 test_expect_success_multi "existing untracked file $where not ignored" '' "
269 test_check_ignore '${subdir}not-ignored' 1
270 "
271
272 test_expect_success_multi "existing tracked file $where not ignored" '' "
273 test_check_ignore '${subdir}ignored-but-in-index' 1
274 "
275
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'
279 "
280done
281
282# Having established the above, from now on we mostly test against
283# files which do not exist in the working tree or index.
284
285test_expect_success 'sub-directory local ignore' '
286 expect "a/3-three" &&
287 test_check_ignore "a/3-three a/three-not-this-one"
288'
289
290test_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"
293'
294
295test_expect_success 'local ignore inside a sub-directory' '
296 expect "3-three" &&
297 (
298 cd a &&
299 test_check_ignore "3-three three-not-this-one"
300 )
301'
302test_expect_success 'local ignore inside a sub-directory with --verbose' '
303 expect "a/.gitignore:2:*three 3-three" &&
304 (
305 cd a &&
306 test_check_ignore "--verbose 3-three three-not-this-one"
307 )
308'
309
310test_expect_success_multi 'nested include' \
311 'a/b/.gitignore:8:!on* a/b/one' '
312 test_check_ignore "a/b/one"
313'
314
315############################################################################
316#
317# test ignored sub-directories
318
319test_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"
322'
323
324test_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
329 EOF
330 test_check_ignore "a/b/ignored-dir/foo a/b/ignored-dir/twoooo a/b/ignored-dir/seven"
331'
332
333test_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
338 EOF
339 test_check_ignore "-v a/b/ignored-dir/foo a/b/ignored-dir/twoooo a/b/ignored-dir/seven"
340'
341
342test_expect_success 'cd to ignored sub-directory' '
343 expect_from_stdin <<-\EOF &&
344 foo
345 twoooo
346 ../one
347 seven
348 ../../one
349 EOF
350 (
351 cd a/b/ignored-dir &&
352 test_check_ignore "foo twoooo ../one seven ../../one"
353 )
354'
355
356test_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
363 EOF
364 (
365 cd a/b/ignored-dir &&
366 test_check_ignore "-v foo twoooo ../one seven ../../one"
367 )
368'
369
370############################################################################
371#
372# test handling of symlinks
373
374test_expect_success_multi SYMLINKS 'symlink' '' '
375 test_check_ignore "a/symlink" 1
376'
377
378test_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"
381'
382
383test_expect_success_multi SYMLINKS 'beyond a symlink from subdirectory' '' '
384 (
385 cd a &&
386 test_check_ignore "symlink/foo" 128
387 ) &&
388 test_stderr "fatal: '\''symlink/foo'\'' is beyond a symbolic link"
389'
390
391############################################################################
392#
393# test handling of submodules
394
395test_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'\''"
398'
399
400test_expect_success_multi 'submodule from subdirectory' '' '
401 (
402 cd a &&
403 test_check_ignore "submodule/one" 128
404 ) &&
405 test_stderr "fatal: Path '\''a/submodule/one'\'' is in submodule '\''a/submodule'\''"
406'
407
408############################################################################
409#
410# test handling of global ignore files
411
412test_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
417 EOF
418 test_check_ignore "-v globalone per-repo a/globalthree a/per-repo not-ignored a/globaltwo"
419'
420
421test_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
430 EOF
431 test_check_ignore "globalone per-repo globalthree a/globalthree a/per-repo not-ignored globaltwo"
432'
433
434test_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
443 EOF
444 test_check_ignore "-v globalone per-repo globalthree a/globalthree a/per-repo not-ignored globaltwo"
445'
446
447############################################################################
448#
449# test --stdin
450
451cat <<-\EOF >stdin
452 one
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
468EOF
469cat <<-\EOF >expected-default
470 one
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
483EOF
484cat <<-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
498EOF
499
500sed -e 's/^"//' -e 's/\\//' -e 's/"$//' stdin | \
501 tr "\n" "\0" >stdin0
502sed -e 's/^"//' -e 's/\\//' -e 's/"$//' expected-default | \
503 tr "\n" "\0" >expected-default0
504sed -e 's/ "/ /' -e 's/\\//' -e 's/"$//' expected-verbose | \
505 tr ":\t\n" "\0" >expected-verbose0
506
507test_expect_success '--stdin' '
508 expect_from_stdin <expected-default &&
509 test_check_ignore "--stdin" <stdin
510'
511
512test_expect_success '--stdin -q' '
513 expect "" &&
514 test_check_ignore "-q --stdin" <stdin
515'
516
517test_expect_success '--stdin -v' '
518 expect_from_stdin <expected-verbose &&
519 test_check_ignore "-v --stdin" <stdin
520'
521
522for opts in '--stdin -z' '-z --stdin'
523do
524 test_expect_success "$opts" "
525 expect_from_stdin <expected-default0 &&
526 test_check_ignore '$opts' <stdin0
527 "
528
529 test_expect_success "$opts -q" "
530 expect "" &&
531 test_check_ignore '-q $opts' <stdin0
532 "
533
534 test_expect_success "$opts -v" "
535 expect_from_stdin <expected-verbose0 &&
536 test_check_ignore '-v $opts' <stdin0
537 "
538done
539
540cat <<-\EOF >stdin
541 ../one
542 ../not-ignored
543 one
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
557EOF
558cat <<-\EOF >expected-default
559 ../one
560 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
572EOF
573cat <<-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
587EOF
588
589sed -e 's/^"//' -e 's/\\//' -e 's/"$//' stdin | \
590 tr "\n" "\0" >stdin0
591sed -e 's/^"//' -e 's/\\//' -e 's/"$//' expected-default | \
592 tr "\n" "\0" >expected-default0
593sed -e 's/ "/ /' -e 's/\\//' -e 's/"$//' expected-verbose | \
594 tr ":\t\n" "\0" >expected-verbose0
595
596test_expect_success '--stdin from subdirectory' '
597 expect_from_stdin <expected-default &&
598 (
599 cd a &&
600 test_check_ignore "--stdin" <../stdin
601 )
602'
603
604test_expect_success '--stdin from subdirectory with -v' '
605 expect_from_stdin <expected-verbose &&
606 (
607 cd a &&
608 test_check_ignore "--stdin -v" <../stdin
609 )
610'
611
612for opts in '--stdin -z' '-z --stdin'
613do
614 test_expect_success "$opts from subdirectory" '
615 expect_from_stdin <expected-default0 &&
616 (
617 cd a &&
618 test_check_ignore "'"$opts"'" <../stdin0
619 )
620 '
621
622 test_expect_success "$opts from subdirectory with -v" '
623 expect_from_stdin <expected-verbose0 &&
624 (
625 cd a &&
626 test_check_ignore "'"$opts"' -v" <../stdin0
627 )
628 '
629done
630
631
632test_done