ebe7c701fece257db1defdbbcd2b43105956875b
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
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.
82#
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)
88test_expect_success_multi () {
89 prereq=
90 if test $# -eq 4
91 then
92 prereq=$1
93 shift
94 fi
95 testname="$1" expect_verbose="$2" code="$3"
96
97 expect=$( echo "$expect_verbose" | sed -e 's/.* //' )
98
99 test_expect_success $prereq "$testname" '
100 expect "$expect" &&
101 eval "$code"
102 '
103
104 for quiet_opt in '-q' '--quiet'
105 do
106 test_expect_success $prereq "$testname${quiet_opt:+ with $quiet_opt}" "
107 expect '' &&
108 $code
109 "
110 done
111 quiet_opt=
112
113 for verbose_opt in '-v' '--verbose'
114 do
115 test_expect_success $prereq "$testname${verbose_opt:+ with $verbose_opt}" "
116 expect '$expect_verbose' &&
117 $code
118 "
119 done
120 verbose_opt=
121}
122
123test_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 &&
130 (
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 &&
139 one
140 ignored-*
141 EOF
142 for dir in . a
143 do
144 : >$dir/not-ignored &&
145 : >$dir/ignored-and-untracked &&
146 : >$dir/ignored-but-in-index
147 done &&
148 git add -f ignored-but-in-index a/ignored-but-in-index &&
149 cat <<-\EOF >a/.gitignore &&
150 two*
151 *three
152 EOF
153 cat <<-\EOF >a/b/.gitignore &&
154 four
155 five
156 # this comment should affect the line numbers
157 six
158 ignored-dir/
159 # and so should this blank line:
160
161 !on*
162 !two
163 EOF
164 echo "seven" >a/b/ignored-dir/.gitignore &&
165 test -n "$HOME" &&
166 cat <<-\EOF >"$global_excludes" &&
167 globalone
168 !globaltwo
169 globalthree
170 EOF
171 cat <<-\EOF >>.git/info/exclude
172 per-repo
173 EOF
174'
175
176############################################################################
177#
178# test invalid inputs
179
180test_expect_success_multi 'empty command line' '' '
181 test_check_ignore "" 128 &&
182 stderr_contains "fatal: no path specified"
183'
184
185test_expect_success_multi '--stdin with empty STDIN' '' '
186 test_check_ignore "--stdin" 1 </dev/null &&
187 if test -n "$quiet_opt"; then
188 test_stderr ""
189 else
190 test_stderr "no pathspec given."
191 fi
192'
193
194test_expect_success '-q with multiple args' '
195 expect "" &&
196 test_check_ignore "-q one two" 128 &&
197 stderr_contains "fatal: --quiet is only valid with a single pathname"
198'
199
200test_expect_success '--quiet with multiple args' '
201 expect "" &&
202 test_check_ignore "--quiet one two" 128 &&
203 stderr_contains "fatal: --quiet is only valid with a single pathname"
204'
205
206for verbose_opt in '-v' '--verbose'
207do
208 for quiet_opt in '-q' '--quiet'
209 do
210 test_expect_success "$quiet_opt $verbose_opt" "
211 expect '' &&
212 test_check_ignore '$quiet_opt $verbose_opt foo' 128 &&
213 stderr_contains 'fatal: cannot have both --quiet and --verbose'
214 "
215 done
216done
217
218test_expect_success '--quiet with multiple args' '
219 expect "" &&
220 test_check_ignore "--quiet one two" 128 &&
221 stderr_contains "fatal: --quiet is only valid with a single pathname"
222'
223
224test_expect_success_multi 'erroneous use of --' '' '
225 test_check_ignore "--" 128 &&
226 stderr_contains "fatal: no path specified"
227'
228
229test_expect_success_multi '--stdin with superfluous arg' '' '
230 test_check_ignore "--stdin foo" 128 &&
231 stderr_contains "fatal: cannot specify pathnames with --stdin"
232'
233
234test_expect_success_multi '--stdin -z with superfluous arg' '' '
235 test_check_ignore "--stdin -z foo" 128 &&
236 stderr_contains "fatal: cannot specify pathnames with --stdin"
237'
238
239test_expect_success_multi '-z without --stdin' '' '
240 test_check_ignore "-z" 128 &&
241 stderr_contains "fatal: -z only makes sense with --stdin"
242'
243
244test_expect_success_multi '-z without --stdin and superfluous arg' '' '
245 test_check_ignore "-z foo" 128 &&
246 stderr_contains "fatal: -z only makes sense with --stdin"
247'
248
249test_expect_success_multi 'needs work tree' '' '
250 (
251 cd .git &&
252 test_check_ignore "foo" 128
253 ) &&
254 stderr_contains "fatal: This operation must be run in a work tree"
255'
256
257############################################################################
258#
259# test standard ignores
260
261# First make sure that the presence of a file in the working tree
262# does not impact results, but that the presence of a file in the
263# index does.
264
265for subdir in '' 'a/'
266do
267 if test -z "$subdir"
268 then
269 where="at top-level"
270 else
271 where="in subdir $subdir"
272 fi
273
274 test_expect_success_multi "non-existent file $where not ignored" '' "
275 test_check_ignore '${subdir}non-existent' 1
276 "
277
278 test_expect_success_multi "non-existent file $where ignored" \
279 ".gitignore:1:one ${subdir}one" "
280 test_check_ignore '${subdir}one'
281 "
282
283 test_expect_success_multi "existing untracked file $where not ignored" '' "
284 test_check_ignore '${subdir}not-ignored' 1
285 "
286
287 test_expect_success_multi "existing tracked file $where not ignored" '' "
288 test_check_ignore '${subdir}ignored-but-in-index' 1
289 "
290
291 test_expect_success_multi "existing untracked file $where ignored" \
292 ".gitignore:2:ignored-* ${subdir}ignored-and-untracked" "
293 test_check_ignore '${subdir}ignored-and-untracked'
294 "
295done
296
297# Having established the above, from now on we mostly test against
298# files which do not exist in the working tree or index.
299
300test_expect_success 'sub-directory local ignore' '
301 expect "a/3-three" &&
302 test_check_ignore "a/3-three a/three-not-this-one"
303'
304
305test_expect_success 'sub-directory local ignore with --verbose' '
306 expect "a/.gitignore:2:*three a/3-three" &&
307 test_check_ignore "--verbose a/3-three a/three-not-this-one"
308'
309
310test_expect_success 'local ignore inside a sub-directory' '
311 expect "3-three" &&
312 (
313 cd a &&
314 test_check_ignore "3-three three-not-this-one"
315 )
316'
317test_expect_success 'local ignore inside a sub-directory with --verbose' '
318 expect "a/.gitignore:2:*three 3-three" &&
319 (
320 cd a &&
321 test_check_ignore "--verbose 3-three three-not-this-one"
322 )
323'
324
325test_expect_success_multi 'nested include' \
326 'a/b/.gitignore:8:!on* a/b/one' '
327 test_check_ignore "a/b/one"
328'
329
330############################################################################
331#
332# test ignored sub-directories
333
334test_expect_success_multi 'ignored sub-directory' \
335 'a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir' '
336 test_check_ignore "a/b/ignored-dir"
337'
338
339test_expect_success 'multiple files inside ignored sub-directory' '
340 expect_from_stdin <<-\EOF &&
341 a/b/ignored-dir/foo
342 a/b/ignored-dir/twoooo
343 a/b/ignored-dir/seven
344 EOF
345 test_check_ignore "a/b/ignored-dir/foo a/b/ignored-dir/twoooo a/b/ignored-dir/seven"
346'
347
348test_expect_success 'multiple files inside ignored sub-directory with -v' '
349 expect_from_stdin <<-\EOF &&
350 a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir/foo
351 a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir/twoooo
352 a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir/seven
353 EOF
354 test_check_ignore "-v a/b/ignored-dir/foo a/b/ignored-dir/twoooo a/b/ignored-dir/seven"
355'
356
357test_expect_success 'cd to ignored sub-directory' '
358 expect_from_stdin <<-\EOF &&
359 foo
360 twoooo
361 ../one
362 seven
363 ../../one
364 EOF
365 (
366 cd a/b/ignored-dir &&
367 test_check_ignore "foo twoooo ../one seven ../../one"
368 )
369'
370
371test_expect_success 'cd to ignored sub-directory with -v' '
372 expect_from_stdin <<-\EOF &&
373 a/b/.gitignore:5:ignored-dir/ foo
374 a/b/.gitignore:5:ignored-dir/ twoooo
375 a/b/.gitignore:8:!on* ../one
376 a/b/.gitignore:5:ignored-dir/ seven
377 .gitignore:1:one ../../one
378 EOF
379 (
380 cd a/b/ignored-dir &&
381 test_check_ignore "-v foo twoooo ../one seven ../../one"
382 )
383'
384
385############################################################################
386#
387# test handling of symlinks
388
389test_expect_success_multi SYMLINKS 'symlink' '' '
390 test_check_ignore "a/symlink" 1
391'
392
393test_expect_success_multi SYMLINKS 'beyond a symlink' '' '
394 test_check_ignore "a/symlink/foo" 128 &&
395 test_stderr "fatal: '\''a/symlink/foo'\'' is beyond a symbolic link"
396'
397
398test_expect_success_multi SYMLINKS 'beyond a symlink from subdirectory' '' '
399 (
400 cd a &&
401 test_check_ignore "symlink/foo" 128
402 ) &&
403 test_stderr "fatal: '\''symlink/foo'\'' is beyond a symbolic link"
404'
405
406############################################################################
407#
408# test handling of submodules
409
410test_expect_success_multi 'submodule' '' '
411 test_check_ignore "a/submodule/one" 128 &&
412 test_stderr "fatal: Path '\''a/submodule/one'\'' is in submodule '\''a/submodule'\''"
413'
414
415test_expect_success_multi 'submodule from subdirectory' '' '
416 (
417 cd a &&
418 test_check_ignore "submodule/one" 128
419 ) &&
420 test_stderr "fatal: Path '\''a/submodule/one'\'' is in submodule '\''a/submodule'\''"
421'
422
423############################################################################
424#
425# test handling of global ignore files
426
427test_expect_success 'global ignore not yet enabled' '
428 expect_from_stdin <<-\EOF &&
429 .git/info/exclude:7:per-repo per-repo
430 a/.gitignore:2:*three a/globalthree
431 .git/info/exclude:7:per-repo a/per-repo
432 EOF
433 test_check_ignore "-v globalone per-repo a/globalthree a/per-repo not-ignored a/globaltwo"
434'
435
436test_expect_success 'global ignore' '
437 enable_global_excludes &&
438 expect_from_stdin <<-\EOF &&
439 globalone
440 per-repo
441 globalthree
442 a/globalthree
443 a/per-repo
444 globaltwo
445 EOF
446 test_check_ignore "globalone per-repo globalthree a/globalthree a/per-repo not-ignored globaltwo"
447'
448
449test_expect_success 'global ignore with -v' '
450 enable_global_excludes &&
451 expect_from_stdin <<-EOF &&
452 $global_excludes:1:globalone globalone
453 .git/info/exclude:7:per-repo per-repo
454 $global_excludes:3:globalthree globalthree
455 a/.gitignore:2:*three a/globalthree
456 .git/info/exclude:7:per-repo a/per-repo
457 $global_excludes:2:!globaltwo globaltwo
458 EOF
459 test_check_ignore "-v globalone per-repo globalthree a/globalthree a/per-repo not-ignored globaltwo"
460'
461
462############################################################################
463#
464# test --stdin
465
466cat <<-\EOF >stdin
467 one
468 not-ignored
469 a/one
470 a/not-ignored
471 a/b/on
472 a/b/one
473 a/b/one one
474 "a/b/one two"
475 "a/b/one\"three"
476 a/b/not-ignored
477 a/b/two
478 a/b/twooo
479 globaltwo
480 a/globaltwo
481 a/b/globaltwo
482 b/globaltwo
483EOF
484cat <<-\EOF >expected-default
485 one
486 a/one
487 a/b/on
488 a/b/one
489 a/b/one one
490 a/b/one two
491 "a/b/one\"three"
492 a/b/two
493 a/b/twooo
494 globaltwo
495 a/globaltwo
496 a/b/globaltwo
497 b/globaltwo
498EOF
499cat <<-EOF >expected-verbose
500 .gitignore:1:one one
501 .gitignore:1:one a/one
502 a/b/.gitignore:8:!on* a/b/on
503 a/b/.gitignore:8:!on* a/b/one
504 a/b/.gitignore:8:!on* a/b/one one
505 a/b/.gitignore:8:!on* a/b/one two
506 a/b/.gitignore:8:!on* "a/b/one\"three"
507 a/b/.gitignore:9:!two a/b/two
508 a/.gitignore:1:two* a/b/twooo
509 $global_excludes:2:!globaltwo globaltwo
510 $global_excludes:2:!globaltwo a/globaltwo
511 $global_excludes:2:!globaltwo a/b/globaltwo
512 $global_excludes:2:!globaltwo b/globaltwo
513EOF
514
515sed -e 's/^"//' -e 's/\\//' -e 's/"$//' stdin | \
516 tr "\n" "\0" >stdin0
517sed -e 's/^"//' -e 's/\\//' -e 's/"$//' expected-default | \
518 tr "\n" "\0" >expected-default0
519sed -e 's/ "/ /' -e 's/\\//' -e 's/"$//' expected-verbose | \
520 tr ":\t\n" "\0" >expected-verbose0
521
522test_expect_success '--stdin' '
523 expect_from_stdin <expected-default &&
524 test_check_ignore "--stdin" <stdin
525'
526
527test_expect_success '--stdin -q' '
528 expect "" &&
529 test_check_ignore "-q --stdin" <stdin
530'
531
532test_expect_success '--stdin -v' '
533 expect_from_stdin <expected-verbose &&
534 test_check_ignore "-v --stdin" <stdin
535'
536
537for opts in '--stdin -z' '-z --stdin'
538do
539 test_expect_success "$opts" "
540 expect_from_stdin <expected-default0 &&
541 test_check_ignore '$opts' <stdin0
542 "
543
544 test_expect_success "$opts -q" "
545 expect "" &&
546 test_check_ignore '-q $opts' <stdin0
547 "
548
549 test_expect_success "$opts -v" "
550 expect_from_stdin <expected-verbose0 &&
551 test_check_ignore '-v $opts' <stdin0
552 "
553done
554
555cat <<-\EOF >stdin
556 ../one
557 ../not-ignored
558 one
559 not-ignored
560 b/on
561 b/one
562 b/one one
563 "b/one two"
564 "b/one\"three"
565 b/two
566 b/not-ignored
567 b/twooo
568 ../globaltwo
569 globaltwo
570 b/globaltwo
571 ../b/globaltwo
572EOF
573cat <<-\EOF >expected-default
574 ../one
575 one
576 b/on
577 b/one
578 b/one one
579 b/one two
580 "b/one\"three"
581 b/two
582 b/twooo
583 ../globaltwo
584 globaltwo
585 b/globaltwo
586 ../b/globaltwo
587EOF
588cat <<-EOF >expected-verbose
589 .gitignore:1:one ../one
590 .gitignore:1:one one
591 a/b/.gitignore:8:!on* b/on
592 a/b/.gitignore:8:!on* b/one
593 a/b/.gitignore:8:!on* b/one one
594 a/b/.gitignore:8:!on* b/one two
595 a/b/.gitignore:8:!on* "b/one\"three"
596 a/b/.gitignore:9:!two b/two
597 a/.gitignore:1:two* b/twooo
598 $global_excludes:2:!globaltwo ../globaltwo
599 $global_excludes:2:!globaltwo globaltwo
600 $global_excludes:2:!globaltwo b/globaltwo
601 $global_excludes:2:!globaltwo ../b/globaltwo
602EOF
603
604sed -e 's/^"//' -e 's/\\//' -e 's/"$//' stdin | \
605 tr "\n" "\0" >stdin0
606sed -e 's/^"//' -e 's/\\//' -e 's/"$//' expected-default | \
607 tr "\n" "\0" >expected-default0
608sed -e 's/ "/ /' -e 's/\\//' -e 's/"$//' expected-verbose | \
609 tr ":\t\n" "\0" >expected-verbose0
610
611test_expect_success '--stdin from subdirectory' '
612 expect_from_stdin <expected-default &&
613 (
614 cd a &&
615 test_check_ignore "--stdin" <../stdin
616 )
617'
618
619test_expect_success '--stdin from subdirectory with -v' '
620 expect_from_stdin <expected-verbose &&
621 (
622 cd a &&
623 test_check_ignore "--stdin -v" <../stdin
624 )
625'
626
627for opts in '--stdin -z' '-z --stdin'
628do
629 test_expect_success "$opts from subdirectory" '
630 expect_from_stdin <expected-default0 &&
631 (
632 cd a &&
633 test_check_ignore "'"$opts"'" <../stdin0
634 )
635 '
636
637 test_expect_success "$opts from subdirectory with -v" '
638 expect_from_stdin <expected-verbose0 &&
639 (
640 cd a &&
641 test_check_ignore "'"$opts"' -v" <../stdin0
642 )
643 '
644done
645
646
647test_done