Raw
1 #!/bin/sh
2
3 test_description=check-ignore
4
5 TEST_CREATE_REPO_NO_TEMPLATE=1
6 . ./test-lib.sh
7
8 init_vars () {
9 global_excludes="global-excludes"
10 }
11
12 enable_global_excludes () {
13 init_vars &&
14 git config core.excludesfile "$global_excludes"
15 }
16
17 expect_in () {
18 dest="$HOME/expected-$1" text="$2"
19 if test -z "$text"
20 then
21 >"$dest" # avoid newline
22 else
23 echo "$text" >"$dest"
24 fi
25 }
26
27 expect () {
28 expect_in stdout "$1"
29 }
30
31 expect_from_stdin () {
32 cat >"$HOME/expected-stdout"
33 }
34
35 test_stderr () {
36 expected="$1"
37 expect_in stderr "$1" &&
38 test_cmp "$HOME/expected-stderr" "$HOME/stderr"
39 }
40
41 broken_c_unquote () {
42 sed -e 's/^"//' -e 's/\\//' -e 's/"$//' "$1" | tr '\n' '\0'
43 }
44
45 broken_c_unquote_verbose () {
46 sed -e 's/ "/ /' -e 's/\\//' -e 's/"$//' "$1" | tr ':\t\n' '\000'
47 }
48
49 stderr_contains () {
50 regexp="$1"
51 if test_grep "$regexp" "$HOME/stderr"
52 then
53 return 0
54 else
55 echo "didn't find /$regexp/ in $HOME/stderr"
56 cat "$HOME/stderr"
57 return 1
58 fi
59 }
60
61 stderr_empty_on_success () {
62 expect_code="$1"
63 if test $expect_code = 0
64 then
65 test_stderr ""
66 else
67 # If we expect failure then stderr might or might not be empty
68 # due to --quiet - the caller can check its contents
69 return 0
70 fi
71 }
72
73 test_check_ignore () {
74 args="$1" expect_code="${2:-0}" global_args="$3"
75
76 init_vars &&
77 rm -f "$HOME/stdout" "$HOME/stderr" "$HOME/cmd" &&
78 echo git $global_args check-ignore $quiet_opt $verbose_opt $non_matching_opt $no_index_opt $args \
79 >"$HOME/cmd" &&
80 echo "$expect_code" >"$HOME/expected-exit-code" &&
81 test_expect_code "$expect_code" \
82 git $global_args check-ignore $quiet_opt $verbose_opt $non_matching_opt $no_index_opt $args \
83 >"$HOME/stdout" 2>"$HOME/stderr" &&
84 test_cmp "$HOME/expected-stdout" "$HOME/stdout" &&
85 stderr_empty_on_success "$expect_code"
86 }
87
88 # Runs the same code with 4 different levels of output verbosity:
89 #
90 # 1. with -q / --quiet
91 # 2. with default verbosity
92 # 3. with -v / --verbose
93 # 4. with -v / --verbose, *and* -n / --non-matching
94 #
95 # expecting success each time. Takes advantage of the fact that
96 # check-ignore --verbose output is the same as normal output except
97 # for the extra first column.
98 #
99 # A parameter is used to determine if the tests are run with the
100 # normal case (using the index), or with the --no-index option.
101 #
102 # Arguments:
103 # - (optional) prereqs for this test, e.g. 'SYMLINKS'
104 # - test name
105 # - output to expect from the fourth verbosity mode (the output
106 # from the other verbosity modes is automatically inferred
107 # from this value)
108 # - code to run (should invoke test_check_ignore)
109 # - index option: --index or --no-index
110 test_expect_success_multiple () {
111 prereq=
112 if test $# -eq 5
113 then
114 prereq=$1
115 shift
116 fi
117 if test "$4" = "--index"
118 then
119 no_index_opt=
120 else
121 no_index_opt=$4
122 fi
123 testname="$1" expect_all="$2" code="$3"
124
125 expect_verbose=$(echo "$expect_all" | grep -v '^:: ' || :)
126 expect=$(echo "$expect_verbose" | sed -e 's/.* //')
127
128 test_expect_success $prereq "$testname${no_index_opt:+ with $no_index_opt}" '
129 expect "$expect" &&
130 eval "$code"
131 '
132
133 # --quiet is only valid when a single pattern is passed
134 if test $( echo "$expect_all" | wc -l ) = 1
135 then
136 for quiet_opt in '-q' '--quiet'
137 do
138 opts="${no_index_opt:+$no_index_opt }$quiet_opt"
139 test_expect_success $prereq "$testname${opts:+ with $opts}" "
140 expect '' &&
141 $code
142 "
143 done
144 quiet_opt=
145 fi
146
147 for verbose_opt in '-v' '--verbose'
148 do
149 for non_matching_opt in '' '-n' '--non-matching'
150 do
151 if test -n "$non_matching_opt"
152 then
153 my_expect="$expect_all"
154 else
155 my_expect="$expect_verbose"
156 fi
157
158 test_code="
159 expect '$my_expect' &&
160 $code
161 "
162 opts="${no_index_opt:+$no_index_opt }$verbose_opt${non_matching_opt:+ $non_matching_opt}"
163 test_expect_success $prereq "$testname${opts:+ with $opts}" "$test_code"
164 done
165 done
166 verbose_opt=
167 non_matching_opt=
168 no_index_opt=
169 }
170
171 test_expect_success_multi () {
172 test_expect_success_multiple "$@" "--index"
173 }
174
175 test_expect_success_no_index_multi () {
176 test_expect_success_multiple "$@" "--no-index"
177 }
178
179 test_expect_success 'setup' '
180 init_vars &&
181 mkdir -p a/b/ignored-dir a/submodule b &&
182 if test_have_prereq SYMLINKS
183 then
184 ln -s b a/symlink
185 fi &&
186 (
187 cd a/submodule &&
188 git init &&
189 echo a >a &&
190 git add a &&
191 git commit -m"commit in submodule"
192 ) &&
193 git add a/submodule &&
194 cat <<-\EOF >.gitignore &&
195 one
196 ignored-*
197 top-level-dir/
198 EOF
199 for dir in . a
200 do
201 : >$dir/not-ignored &&
202 : >$dir/ignored-and-untracked &&
203 : >$dir/ignored-but-in-index || return 1
204 done &&
205 git add -f ignored-but-in-index a/ignored-but-in-index &&
206 cat <<-\EOF >a/.gitignore &&
207 two*
208 *three
209 EOF
210 cat <<-\EOF >a/b/.gitignore &&
211 four
212 five
213 # this comment should affect the line numbers
214 six
215 ignored-dir/
216 # and so should this blank line:
217
218 !on*
219 !two
220 EOF
221 echo "seven" >a/b/ignored-dir/.gitignore &&
222 test -n "$HOME" &&
223 cat <<-\EOF >"$global_excludes" &&
224 globalone
225 !globaltwo
226 globalthree
227 EOF
228 mkdir .git/info &&
229 cat <<-\EOF >.git/info/exclude
230 per-repo
231 EOF
232 '
233
234 ############################################################################
235 #
236 # test invalid inputs
237
238 test_expect_success_multi '. corner-case' ':: .' '
239 test_check_ignore . 1
240 '
241
242 test_expect_success_multi 'empty command line' '' '
243 test_check_ignore "" 128 &&
244 stderr_contains "fatal: no path specified"
245 '
246
247 test_expect_success_multi '--stdin with empty STDIN' '' '
248 test_check_ignore "--stdin" 1 </dev/null &&
249 test_stderr ""
250 '
251
252 test_expect_success '-q with multiple args' '
253 expect "" &&
254 test_check_ignore "-q one two" 128 &&
255 stderr_contains "fatal: --quiet is only valid with a single pathname"
256 '
257
258 test_expect_success '--quiet with multiple args' '
259 expect "" &&
260 test_check_ignore "--quiet one two" 128 &&
261 stderr_contains "fatal: --quiet is only valid with a single pathname"
262 '
263
264 for verbose_opt in '-v' '--verbose'
265 do
266 for quiet_opt in '-q' '--quiet'
267 do
268 test_expect_success "$quiet_opt $verbose_opt" "
269 expect '' &&
270 test_check_ignore '$quiet_opt $verbose_opt foo' 128 &&
271 stderr_contains 'fatal: cannot have both --quiet and --verbose'
272 "
273 done
274 done
275
276 test_expect_success '--quiet with multiple args' '
277 expect "" &&
278 test_check_ignore "--quiet one two" 128 &&
279 stderr_contains "fatal: --quiet is only valid with a single pathname"
280 '
281
282 test_expect_success_multi 'erroneous use of --' '' '
283 test_check_ignore "--" 128 &&
284 stderr_contains "fatal: no path specified"
285 '
286
287 test_expect_success_multi '--stdin with superfluous arg' '' '
288 test_check_ignore "--stdin foo" 128 &&
289 stderr_contains "fatal: cannot specify pathnames with --stdin"
290 '
291
292 test_expect_success_multi '--stdin -z with superfluous arg' '' '
293 test_check_ignore "--stdin -z foo" 128 &&
294 stderr_contains "fatal: cannot specify pathnames with --stdin"
295 '
296
297 test_expect_success_multi '-z without --stdin' '' '
298 test_check_ignore "-z" 128 &&
299 stderr_contains "fatal: -z only makes sense with --stdin"
300 '
301
302 test_expect_success_multi '-z without --stdin and superfluous arg' '' '
303 test_check_ignore "-z foo" 128 &&
304 stderr_contains "fatal: -z only makes sense with --stdin"
305 '
306
307 test_expect_success_multi 'needs work tree' '' '
308 (
309 cd .git &&
310 test_check_ignore "foo" 128
311 ) &&
312 stderr_contains "fatal: this operation must be run in a work tree"
313 '
314
315 ############################################################################
316 #
317 # test standard ignores
318
319 # First make sure that the presence of a file in the working tree
320 # does not impact results, but that the presence of a file in the
321 # index does unless the --no-index option is used.
322
323 for subdir in '' 'a/'
324 do
325 if test -z "$subdir"
326 then
327 where="at top-level"
328 else
329 where="in subdir $subdir"
330 fi
331
332 test_expect_success_multi "non-existent file $where not ignored" \
333 ":: ${subdir}non-existent" \
334 "test_check_ignore '${subdir}non-existent' 1"
335
336 test_expect_success_no_index_multi "non-existent file $where not ignored" \
337 ":: ${subdir}non-existent" \
338 "test_check_ignore '${subdir}non-existent' 1"
339
340 test_expect_success_multi "non-existent file $where ignored" \
341 ".gitignore:1:one ${subdir}one" \
342 "test_check_ignore '${subdir}one'"
343
344 test_expect_success_no_index_multi "non-existent file $where ignored" \
345 ".gitignore:1:one ${subdir}one" \
346 "test_check_ignore '${subdir}one'"
347
348 test_expect_success_multi "existing untracked file $where not ignored" \
349 ":: ${subdir}not-ignored" \
350 "test_check_ignore '${subdir}not-ignored' 1"
351
352 test_expect_success_no_index_multi "existing untracked file $where not ignored" \
353 ":: ${subdir}not-ignored" \
354 "test_check_ignore '${subdir}not-ignored' 1"
355
356 test_expect_success_multi "existing tracked file $where not ignored" \
357 ":: ${subdir}ignored-but-in-index" \
358 "test_check_ignore '${subdir}ignored-but-in-index' 1"
359
360 test_expect_success_no_index_multi "existing tracked file $where shown as ignored" \
361 ".gitignore:2:ignored-* ${subdir}ignored-but-in-index" \
362 "test_check_ignore '${subdir}ignored-but-in-index'"
363
364 test_expect_success_multi "existing untracked file $where ignored" \
365 ".gitignore:2:ignored-* ${subdir}ignored-and-untracked" \
366 "test_check_ignore '${subdir}ignored-and-untracked'"
367
368 test_expect_success_no_index_multi "existing untracked file $where ignored" \
369 ".gitignore:2:ignored-* ${subdir}ignored-and-untracked" \
370 "test_check_ignore '${subdir}ignored-and-untracked'"
371
372 test_expect_success_multi "mix of file types $where" \
373 ":: ${subdir}non-existent
374 .gitignore:1:one ${subdir}one
375 :: ${subdir}not-ignored
376 :: ${subdir}ignored-but-in-index
377 .gitignore:2:ignored-* ${subdir}ignored-and-untracked" \
378 "test_check_ignore '
379 ${subdir}non-existent
380 ${subdir}one
381 ${subdir}not-ignored
382 ${subdir}ignored-but-in-index
383 ${subdir}ignored-and-untracked'
384 "
385
386 test_expect_success_no_index_multi "mix of file types $where" \
387 ":: ${subdir}non-existent
388 .gitignore:1:one ${subdir}one
389 :: ${subdir}not-ignored
390 .gitignore:2:ignored-* ${subdir}ignored-but-in-index
391 .gitignore:2:ignored-* ${subdir}ignored-and-untracked" \
392 "test_check_ignore '
393 ${subdir}non-existent
394 ${subdir}one
395 ${subdir}not-ignored
396 ${subdir}ignored-but-in-index
397 ${subdir}ignored-and-untracked'
398 "
399 done
400
401 # Having established the above, from now on we mostly test against
402 # files which do not exist in the working tree or index.
403
404 test_expect_success 'sub-directory local ignore' '
405 expect "a/3-three" &&
406 test_check_ignore "a/3-three a/three-not-this-one"
407 '
408
409 test_expect_success 'sub-directory local ignore with --verbose' '
410 expect "a/.gitignore:2:*three a/3-three" &&
411 test_check_ignore "--verbose a/3-three a/three-not-this-one"
412 '
413
414 test_expect_success 'local ignore inside a sub-directory' '
415 expect "3-three" &&
416 (
417 cd a &&
418 test_check_ignore "3-three three-not-this-one"
419 )
420 '
421 test_expect_success 'local ignore inside a sub-directory with --verbose' '
422 expect "a/.gitignore:2:*three 3-three" &&
423 (
424 cd a &&
425 test_check_ignore "--verbose 3-three three-not-this-one"
426 )
427 '
428
429 test_expect_success 'nested include of negated pattern' '
430 expect "" &&
431 test_check_ignore "a/b/one" 1
432 '
433
434 test_expect_success 'nested include of negated pattern with -q' '
435 expect "" &&
436 test_check_ignore "-q a/b/one" 1
437 '
438
439 test_expect_success 'nested include of negated pattern with -v' '
440 expect "a/b/.gitignore:8:!on* a/b/one" &&
441 test_check_ignore "-v a/b/one" 0
442 '
443
444 test_expect_success 'nested include of negated pattern with -v -n' '
445 expect "a/b/.gitignore:8:!on* a/b/one" &&
446 test_check_ignore "-v -n a/b/one" 0
447 '
448
449 ############################################################################
450 #
451 # test ignored sub-directories
452
453 test_expect_success_multi 'ignored sub-directory' \
454 'a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir' '
455 test_check_ignore "a/b/ignored-dir"
456 '
457
458 test_expect_success 'multiple files inside ignored sub-directory' '
459 expect_from_stdin <<-\EOF &&
460 a/b/ignored-dir/foo
461 a/b/ignored-dir/twoooo
462 a/b/ignored-dir/seven
463 EOF
464 test_check_ignore "a/b/ignored-dir/foo a/b/ignored-dir/twoooo a/b/ignored-dir/seven"
465 '
466
467 test_expect_success 'multiple files inside ignored sub-directory with -v' '
468 expect_from_stdin <<-\EOF &&
469 a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir/foo
470 a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir/twoooo
471 a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir/seven
472 EOF
473 test_check_ignore "-v a/b/ignored-dir/foo a/b/ignored-dir/twoooo a/b/ignored-dir/seven"
474 '
475
476 test_expect_success 'cd to ignored sub-directory' '
477 expect_from_stdin <<-\EOF &&
478 foo
479 twoooo
480 seven
481 ../../one
482 EOF
483 (
484 cd a/b/ignored-dir &&
485 test_check_ignore "foo twoooo ../one seven ../../one"
486 )
487 '
488
489 test_expect_success 'cd to ignored sub-directory with -v' '
490 expect_from_stdin <<-\EOF &&
491 a/b/.gitignore:5:ignored-dir/ foo
492 a/b/.gitignore:5:ignored-dir/ twoooo
493 a/b/.gitignore:8:!on* ../one
494 a/b/.gitignore:5:ignored-dir/ seven
495 .gitignore:1:one ../../one
496 EOF
497 (
498 cd a/b/ignored-dir &&
499 test_check_ignore "-v foo twoooo ../one seven ../../one"
500 )
501 '
502
503 ############################################################################
504 #
505 # test handling of symlinks
506
507 test_expect_success_multi SYMLINKS 'symlink' ':: a/symlink' '
508 test_check_ignore "a/symlink" 1
509 '
510
511 test_expect_success_multi SYMLINKS 'beyond a symlink' '' '
512 test_check_ignore "a/symlink/foo" 128 &&
513 test_stderr "fatal: pathspec '\''a/symlink/foo'\'' is beyond a symbolic link"
514 '
515
516 test_expect_success_multi SYMLINKS 'beyond a symlink from subdirectory' '' '
517 (
518 cd a &&
519 test_check_ignore "symlink/foo" 128
520 ) &&
521 test_stderr "fatal: pathspec '\''symlink/foo'\'' is beyond a symbolic link"
522 '
523
524 ############################################################################
525 #
526 # test handling of submodules
527
528 test_expect_success_multi 'submodule' '' '
529 test_check_ignore "a/submodule/one" 128 &&
530 test_stderr "fatal: Pathspec '\''a/submodule/one'\'' is in submodule '\''a/submodule'\''"
531 '
532
533 test_expect_success_multi 'submodule from subdirectory' '' '
534 (
535 cd a &&
536 test_check_ignore "submodule/one" 128
537 ) &&
538 test_stderr "fatal: Pathspec '\''submodule/one'\'' is in submodule '\''a/submodule'\''"
539 '
540
541 ############################################################################
542 #
543 # test handling of global ignore files
544
545 test_expect_success 'global ignore not yet enabled' '
546 expect_from_stdin <<-\EOF &&
547 .git/info/exclude:1:per-repo per-repo
548 a/.gitignore:2:*three a/globalthree
549 .git/info/exclude:1:per-repo a/per-repo
550 EOF
551 test_check_ignore "-v globalone per-repo a/globalthree a/per-repo not-ignored a/globaltwo"
552 '
553
554 test_expect_success 'global ignore' '
555 enable_global_excludes &&
556 expect_from_stdin <<-\EOF &&
557 globalone
558 per-repo
559 globalthree
560 a/globalthree
561 a/per-repo
562 EOF
563 test_check_ignore "globalone per-repo globalthree a/globalthree a/per-repo not-ignored globaltwo"
564 '
565
566 test_expect_success 'global ignore with -v' '
567 enable_global_excludes &&
568 expect_from_stdin <<-EOF &&
569 $global_excludes:1:globalone globalone
570 .git/info/exclude:1:per-repo per-repo
571 $global_excludes:3:globalthree globalthree
572 a/.gitignore:2:*three a/globalthree
573 .git/info/exclude:1:per-repo a/per-repo
574 $global_excludes:2:!globaltwo globaltwo
575 EOF
576 test_check_ignore "-v globalone per-repo globalthree a/globalthree a/per-repo not-ignored globaltwo"
577 '
578
579 ############################################################################
580 #
581 # test --stdin
582
583 cat <<-\EOF >stdin
584 one
585 not-ignored
586 a/one
587 a/not-ignored
588 a/b/on
589 a/b/one
590 a/b/one one
591 "a/b/one two"
592 "a/b/one\"three"
593 a/b/not-ignored
594 a/b/two
595 a/b/twooo
596 globaltwo
597 a/globaltwo
598 a/b/globaltwo
599 b/globaltwo
600 EOF
601 cat <<-\EOF >expected-default
602 one
603 a/one
604 a/b/twooo
605 EOF
606 cat <<-EOF >expected-verbose
607 .gitignore:1:one one
608 .gitignore:1:one a/one
609 a/b/.gitignore:8:!on* a/b/on
610 a/b/.gitignore:8:!on* a/b/one
611 a/b/.gitignore:8:!on* a/b/one one
612 a/b/.gitignore:8:!on* a/b/one two
613 a/b/.gitignore:8:!on* "a/b/one\\"three"
614 a/b/.gitignore:9:!two a/b/two
615 a/.gitignore:1:two* a/b/twooo
616 $global_excludes:2:!globaltwo globaltwo
617 $global_excludes:2:!globaltwo a/globaltwo
618 $global_excludes:2:!globaltwo a/b/globaltwo
619 $global_excludes:2:!globaltwo b/globaltwo
620 EOF
621
622 broken_c_unquote stdin >stdin0
623
624 broken_c_unquote expected-default >expected-default0
625
626 broken_c_unquote_verbose expected-verbose >expected-verbose0
627
628 test_expect_success '--stdin' '
629 expect_from_stdin <expected-default &&
630 test_check_ignore "--stdin" <stdin
631 '
632
633 test_expect_success '--stdin -q' '
634 expect "" &&
635 test_check_ignore "-q --stdin" <stdin
636 '
637
638 test_expect_success '--stdin -v' '
639 expect_from_stdin <expected-verbose &&
640 test_check_ignore "-v --stdin" <stdin
641 '
642
643 for opts in '--stdin -z' '-z --stdin'
644 do
645 test_expect_success "$opts" "
646 expect_from_stdin <expected-default0 &&
647 test_check_ignore '$opts' <stdin0
648 "
649
650 test_expect_success "$opts -q" "
651 expect "" &&
652 test_check_ignore '-q $opts' <stdin0
653 "
654
655 test_expect_success "$opts -v" "
656 expect_from_stdin <expected-verbose0 &&
657 test_check_ignore '-v $opts' <stdin0
658 "
659 done
660
661 cat <<-\EOF >stdin
662 ../one
663 ../not-ignored
664 one
665 not-ignored
666 b/on
667 b/one
668 b/one one
669 "b/one two"
670 "b/one\"three"
671 b/two
672 b/not-ignored
673 b/twooo
674 ../globaltwo
675 globaltwo
676 b/globaltwo
677 ../b/globaltwo
678 c/not-ignored
679 EOF
680 # N.B. we deliberately end STDIN with a non-matching pattern in order
681 # to test that the exit code indicates that one or more of the
682 # provided paths is ignored - in other words, that it represents an
683 # aggregation of all the results, not just the final result.
684
685 cat <<-EOF >expected-all
686 .gitignore:1:one ../one
687 :: ../not-ignored
688 .gitignore:1:one one
689 :: not-ignored
690 a/b/.gitignore:8:!on* b/on
691 a/b/.gitignore:8:!on* b/one
692 a/b/.gitignore:8:!on* b/one one
693 a/b/.gitignore:8:!on* b/one two
694 a/b/.gitignore:8:!on* "b/one\\"three"
695 a/b/.gitignore:9:!two b/two
696 :: b/not-ignored
697 a/.gitignore:1:two* b/twooo
698 $global_excludes:2:!globaltwo ../globaltwo
699 $global_excludes:2:!globaltwo globaltwo
700 $global_excludes:2:!globaltwo b/globaltwo
701 $global_excludes:2:!globaltwo ../b/globaltwo
702 :: c/not-ignored
703 EOF
704 cat <<-EOF >expected-default
705 ../one
706 one
707 b/twooo
708 EOF
709 grep -v '^:: ' expected-all >expected-verbose
710
711 broken_c_unquote stdin >stdin0
712
713 broken_c_unquote expected-default >expected-default0
714
715 broken_c_unquote_verbose expected-verbose >expected-verbose0
716
717 test_expect_success '--stdin from subdirectory' '
718 expect_from_stdin <expected-default &&
719 (
720 cd a &&
721 test_check_ignore "--stdin" <../stdin
722 )
723 '
724
725 test_expect_success '--stdin from subdirectory with -v' '
726 expect_from_stdin <expected-verbose &&
727 (
728 cd a &&
729 test_check_ignore "--stdin -v" <../stdin
730 )
731 '
732
733 test_expect_success '--stdin from subdirectory with -v -n' '
734 expect_from_stdin <expected-all &&
735 (
736 cd a &&
737 test_check_ignore "--stdin -v -n" <../stdin
738 )
739 '
740
741 for opts in '--stdin -z' '-z --stdin'
742 do
743 test_expect_success "$opts from subdirectory" '
744 expect_from_stdin <expected-default0 &&
745 (
746 cd a &&
747 test_check_ignore "'"$opts"'" <../stdin0
748 )
749 '
750
751 test_expect_success "$opts from subdirectory with -v" '
752 expect_from_stdin <expected-verbose0 &&
753 (
754 cd a &&
755 test_check_ignore "'"$opts"' -v" <../stdin0
756 )
757 '
758 done
759
760 test_expect_success PIPE 'streaming support for --stdin' '
761 mkfifo in out &&
762 (git check-ignore -n -v --stdin <in >out &) &&
763
764 # We cannot just "echo >in" because check-ignore would get EOF
765 # after echo exited; instead we open the descriptor in our
766 # shell, and then echo to the fd. We make sure to close it at
767 # the end, so that the subprocess does get EOF and dies
768 # properly.
769 #
770 # Similarly, we must keep "out" open so that check-ignore does
771 # not ever get SIGPIPE trying to write to us. Not only would that
772 # produce incorrect results, but then there would be no writer on the
773 # other end of the pipe, and we would potentially block forever trying
774 # to open it.
775 exec 9>in &&
776 exec 8<out &&
777 test_when_finished "exec 9>&-" &&
778 test_when_finished "exec 8<&-" &&
779 echo >&9 one &&
780 read response <&8 &&
781 echo "$response" | grep "^\.gitignore:1:one one" &&
782 echo >&9 two &&
783 read response <&8 &&
784 echo "$response" | grep "^:: two"
785 '
786
787 test_expect_success 'existing file and directory' '
788 test_when_finished "rm one" &&
789 test_when_finished "rmdir top-level-dir" &&
790 >one &&
791 mkdir top-level-dir &&
792 git check-ignore one top-level-dir >actual &&
793 grep one actual &&
794 grep top-level-dir actual
795 '
796
797 test_expect_success 'existing directory and file' '
798 test_when_finished "rm one" &&
799 test_when_finished "rmdir top-level-dir" &&
800 >one &&
801 mkdir top-level-dir &&
802 git check-ignore top-level-dir one >actual &&
803 grep one actual &&
804 grep top-level-dir actual
805 '
806
807 test_expect_success 'exact prefix matching (with root)' '
808 test_when_finished rm -r a &&
809 mkdir -p a/git a/git-foo &&
810 touch a/git/foo a/git-foo/bar &&
811 echo /git/ >a/.gitignore &&
812 git check-ignore a/git a/git/foo a/git-foo a/git-foo/bar >actual &&
813 cat >expect <<-\EOF &&
814 a/git
815 a/git/foo
816 EOF
817 test_cmp expect actual
818 '
819
820 test_expect_success 'exact prefix matching (without root)' '
821 test_when_finished rm -r a &&
822 mkdir -p a/git a/git-foo &&
823 touch a/git/foo a/git-foo/bar &&
824 echo git/ >a/.gitignore &&
825 git check-ignore a/git a/git/foo a/git-foo a/git-foo/bar >actual &&
826 cat >expect <<-\EOF &&
827 a/git
828 a/git/foo
829 EOF
830 test_cmp expect actual
831 '
832
833 test_expect_success 'directories and ** matches' '
834 cat >.gitignore <<-\EOF &&
835 data/**
836 !data/**/
837 !data/**/*.txt
838 EOF
839 git check-ignore file \
840 data/file data/data1/file1 data/data1/file1.txt \
841 data/data2/file2 data/data2/file2.txt >actual &&
842 cat >expect <<-\EOF &&
843 data/file
844 data/data1/file1
845 data/data2/file2
846 EOF
847 test_cmp expect actual
848 '
849
850 test_expect_success '** not confused by matching leading prefix' '
851 cat >.gitignore <<-\EOF &&
852 foo**/bar
853 EOF
854 git check-ignore foobar foo/bar >actual &&
855 cat >expect <<-\EOF &&
856 foo/bar
857 EOF
858 test_cmp expect actual
859 '
860
861 ############################################################################
862 #
863 # test whitespace handling
864
865 test_expect_success 'trailing whitespace is ignored' '
866 mkdir whitespace &&
867 >whitespace/trailing &&
868 >whitespace/untracked &&
869 echo "whitespace/trailing " >ignore &&
870 cat >expect <<EOF &&
871 whitespace/untracked
872 EOF
873 git ls-files -o -X ignore whitespace >actual 2>err &&
874 test_cmp expect actual &&
875 test_must_be_empty err
876 '
877
878 test_expect_success !MINGW 'quoting allows trailing whitespace' '
879 rm -rf whitespace &&
880 mkdir whitespace &&
881 >"whitespace/trailing " &&
882 >whitespace/untracked &&
883 echo "whitespace/trailing\\ \\ " >ignore &&
884 echo whitespace/untracked >expect &&
885 git ls-files -o -X ignore whitespace >actual 2>err &&
886 test_cmp expect actual &&
887 test_must_be_empty err
888 '
889
890 test_expect_success !MINGW,!CYGWIN 'correct handling of backslashes' '
891 rm -rf whitespace &&
892 mkdir whitespace &&
893 >"whitespace/trailing 1 " &&
894 >"whitespace/trailing 2 \\\\" &&
895 >"whitespace/trailing 3 \\\\" &&
896 >"whitespace/trailing 4 \\ " &&
897 >"whitespace/trailing 5 \\ \\ " &&
898 >"whitespace/trailing 6 \\a\\" &&
899 >whitespace/untracked &&
900 sed -e "s/Z$//" >ignore <<-\EOF &&
901 whitespace/trailing 1 \ Z
902 whitespace/trailing 2 \\\\Z
903 whitespace/trailing 3 \\\\ Z
904 whitespace/trailing 4 \\\ Z
905 whitespace/trailing 5 \\ \\\ Z
906 whitespace/trailing 6 \\a\\Z
907 EOF
908 echo whitespace/untracked >expect &&
909 git ls-files -o -X ignore whitespace >actual 2>err &&
910 test_cmp expect actual &&
911 test_must_be_empty err
912 '
913
914 test_expect_success 'info/exclude trumps core.excludesfile' '
915 echo >>global-excludes usually-ignored &&
916 echo >>.git/info/exclude "!usually-ignored" &&
917 >usually-ignored &&
918 echo "?? usually-ignored" >expect &&
919
920 git status --porcelain usually-ignored >actual &&
921 test_cmp expect actual
922 '
923
924 test_expect_success SYMLINKS 'set up ignore file for symlink tests' '
925 echo "*" >ignore &&
926 rm -f .gitignore .git/info/exclude
927 '
928
929 test_expect_success SYMLINKS 'symlinks respected in core.excludesFile' '
930 test_when_finished "rm symlink" &&
931 ln -s ignore symlink &&
932 test_config core.excludesFile "$(pwd)/symlink" &&
933 echo file >expect &&
934 git check-ignore file >actual 2>err &&
935 test_cmp expect actual &&
936 test_must_be_empty err
937 '
938
939 test_expect_success SYMLINKS 'symlinks respected in info/exclude' '
940 test_when_finished "rm .git/info/exclude" &&
941 ln -s ../../ignore .git/info/exclude &&
942 echo file >expect &&
943 git check-ignore file >actual 2>err &&
944 test_cmp expect actual &&
945 test_must_be_empty err
946 '
947
948 test_expect_success SYMLINKS 'symlinks not respected in-tree' '
949 test_when_finished "rm -rf subdir .gitignore err actual" &&
950 ln -s ignore .gitignore &&
951 mkdir subdir &&
952 ln -s ignore subdir/.gitignore &&
953 test_must_fail git check-ignore subdir/file >actual 2>err &&
954 test_must_be_empty actual &&
955 test_grep "unable to access.*gitignore" err
956 '
957
958 test_expect_success EXPENSIVE 'large exclude file ignored in tree' '
959 test_when_finished "rm .gitignore" &&
960 find . -name .gitignore -exec rm "{}" ";" &&
961 dd if=/dev/zero of=.gitignore bs=101M count=1 &&
962 git ls-files -o --exclude-standard 2>err &&
963 echo "warning: ignoring excessively large pattern file: .gitignore" >expect &&
964 test_cmp expect err
965 '
966
967 test_done