Merge branch 'cr/git-work-tree-sans-git-dir' into maint
[git] / t / t0008-ignores.sh
1 #!/bin/sh
2
3 test_description=check-ignore
4
5 . ./test-lib.sh
6
7 init_vars () {
8         global_excludes="$(pwd)/global-excludes"
9 }
10
11 enable_global_excludes () {
12         init_vars &&
13         git config core.excludesfile "$global_excludes"
14 }
15
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"
23         fi
24 }
25
26 expect () {
27         expect_in stdout "$1"
28 }
29
30 expect_from_stdin () {
31         cat >"$HOME/expected-stdout"
32 }
33
34 test_stderr () {
35         expected="$1"
36         expect_in stderr "$1" &&
37         test_cmp "$HOME/expected-stderr" "$HOME/stderr"
38 }
39
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
49         fi
50 }
51
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
61         fi
62 }
63
64 test_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)
88 test_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
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 &&
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                 top-level-dir/
142         EOF
143         for dir in . a
144         do
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
153         EOF
154         cat <<-\EOF >a/b/.gitignore &&
155                 four
156                 five
157                 # this comment should affect the line numbers
158                 six
159                 ignored-dir/
160                 # and so should this blank line:
161
162                 !on*
163                 !two
164         EOF
165         echo "seven" >a/b/ignored-dir/.gitignore &&
166         test -n "$HOME" &&
167         cat <<-\EOF >"$global_excludes" &&
168                 globalone
169                 !globaltwo
170                 globalthree
171         EOF
172         cat <<-\EOF >>.git/info/exclude
173                 per-repo
174         EOF
175 '
176
177 ############################################################################
178 #
179 # test invalid inputs
180
181 test_expect_success_multi '. corner-case' '' '
182         test_check_ignore . 1
183 '
184
185 test_expect_success_multi 'empty command line' '' '
186         test_check_ignore "" 128 &&
187         stderr_contains "fatal: no path specified"
188 '
189
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."
196         fi
197 '
198
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"
203 '
204
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"
209 '
210
211 for verbose_opt in '-v' '--verbose'
212 do
213         for quiet_opt in '-q' '--quiet'
214         do
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'
219                 "
220         done
221 done
222
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"
227 '
228
229 test_expect_success_multi 'erroneous use of --' '' '
230         test_check_ignore "--" 128 &&
231         stderr_contains "fatal: no path specified"
232 '
233
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"
237 '
238
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"
242 '
243
244 test_expect_success_multi '-z without --stdin' '' '
245         test_check_ignore "-z" 128 &&
246         stderr_contains "fatal: -z only makes sense with --stdin"
247 '
248
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"
252 '
253
254 test_expect_success_multi 'needs work tree' '' '
255         (
256                 cd .git &&
257                 test_check_ignore "foo" 128
258         ) &&
259         stderr_contains "fatal: This operation must be run in a work tree"
260 '
261
262 ############################################################################
263 #
264 # test standard ignores
265
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.
269
270 for subdir in '' 'a/'
271 do
272         if test -z "$subdir"
273         then
274                 where="at top-level"
275         else
276                 where="in subdir $subdir"
277         fi
278
279         test_expect_success_multi "non-existent file $where not ignored" '' "
280                 test_check_ignore '${subdir}non-existent' 1
281         "
282
283         test_expect_success_multi "non-existent file $where ignored" \
284                 ".gitignore:1:one       ${subdir}one" "
285                 test_check_ignore '${subdir}one'
286         "
287
288         test_expect_success_multi "existing untracked file $where not ignored" '' "
289                 test_check_ignore '${subdir}not-ignored' 1
290         "
291
292         test_expect_success_multi "existing tracked file $where not ignored" '' "
293                 test_check_ignore '${subdir}ignored-but-in-index' 1
294         "
295
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'
299         "
300 done
301
302 # Having established the above, from now on we mostly test against
303 # files which do not exist in the working tree or index.
304
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"
308 '
309
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"
313 '
314
315 test_expect_success 'local ignore inside a sub-directory' '
316         expect "3-three" &&
317         (
318                 cd a &&
319                 test_check_ignore "3-three three-not-this-one"
320         )
321 '
322 test_expect_success 'local ignore inside a sub-directory with --verbose' '
323         expect "a/.gitignore:2:*three   3-three" &&
324         (
325                 cd a &&
326                 test_check_ignore "--verbose 3-three three-not-this-one"
327         )
328 '
329
330 test_expect_success_multi 'nested include' \
331         'a/b/.gitignore:8:!on*  a/b/one' '
332         test_check_ignore "a/b/one"
333 '
334
335 ############################################################################
336 #
337 # test ignored sub-directories
338
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"
342 '
343
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
349         EOF
350         test_check_ignore "a/b/ignored-dir/foo a/b/ignored-dir/twoooo a/b/ignored-dir/seven"
351 '
352
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
358         EOF
359         test_check_ignore "-v a/b/ignored-dir/foo a/b/ignored-dir/twoooo a/b/ignored-dir/seven"
360 '
361
362 test_expect_success 'cd to ignored sub-directory' '
363         expect_from_stdin <<-\EOF &&
364                 foo
365                 twoooo
366                 ../one
367                 seven
368                 ../../one
369         EOF
370         (
371                 cd a/b/ignored-dir &&
372                 test_check_ignore "foo twoooo ../one seven ../../one"
373         )
374 '
375
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
383         EOF
384         (
385                 cd a/b/ignored-dir &&
386                 test_check_ignore "-v foo twoooo ../one seven ../../one"
387         )
388 '
389
390 ############################################################################
391 #
392 # test handling of symlinks
393
394 test_expect_success_multi SYMLINKS 'symlink' '' '
395         test_check_ignore "a/symlink" 1
396 '
397
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"
401 '
402
403 test_expect_success_multi SYMLINKS 'beyond a symlink from subdirectory' '' '
404         (
405                 cd a &&
406                 test_check_ignore "symlink/foo" 128
407         ) &&
408         test_stderr "fatal: '\''symlink/foo'\'' is beyond a symbolic link"
409 '
410
411 ############################################################################
412 #
413 # test handling of submodules
414
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'\''"
418 '
419
420 test_expect_success_multi 'submodule from subdirectory' '' '
421         (
422                 cd a &&
423                 test_check_ignore "submodule/one" 128
424         ) &&
425         test_stderr "fatal: Path '\''a/submodule/one'\'' is in submodule '\''a/submodule'\''"
426 '
427
428 ############################################################################
429 #
430 # test handling of global ignore files
431
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
437         EOF
438         test_check_ignore "-v globalone per-repo a/globalthree a/per-repo not-ignored a/globaltwo"
439 '
440
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
450         EOF
451         test_check_ignore "globalone per-repo globalthree a/globalthree a/per-repo not-ignored globaltwo"
452 '
453
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
463         EOF
464         test_check_ignore "-v globalone per-repo globalthree a/globalthree a/per-repo not-ignored globaltwo"
465 '
466
467 ############################################################################
468 #
469 # test --stdin
470
471 cat <<-\EOF >stdin
472         one
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
488 EOF
489 cat <<-\EOF >expected-default
490         one
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
503 EOF
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
518 EOF
519
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
526
527 test_expect_success '--stdin' '
528         expect_from_stdin <expected-default &&
529         test_check_ignore "--stdin" <stdin
530 '
531
532 test_expect_success '--stdin -q' '
533         expect "" &&
534         test_check_ignore "-q --stdin" <stdin
535 '
536
537 test_expect_success '--stdin -v' '
538         expect_from_stdin <expected-verbose &&
539         test_check_ignore "-v --stdin" <stdin
540 '
541
542 for opts in '--stdin -z' '-z --stdin'
543 do
544         test_expect_success "$opts" "
545                 expect_from_stdin <expected-default0 &&
546                 test_check_ignore '$opts' <stdin0
547         "
548
549         test_expect_success "$opts -q" "
550                 expect "" &&
551                 test_check_ignore '-q $opts' <stdin0
552         "
553
554         test_expect_success "$opts -v" "
555                 expect_from_stdin <expected-verbose0 &&
556                 test_check_ignore '-v $opts' <stdin0
557         "
558 done
559
560 cat <<-\EOF >stdin
561         ../one
562         ../not-ignored
563         one
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
577 EOF
578 cat <<-\EOF >expected-default
579         ../one
580         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
592 EOF
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
607 EOF
608
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
615
616 test_expect_success '--stdin from subdirectory' '
617         expect_from_stdin <expected-default &&
618         (
619                 cd a &&
620                 test_check_ignore "--stdin" <../stdin
621         )
622 '
623
624 test_expect_success '--stdin from subdirectory with -v' '
625         expect_from_stdin <expected-verbose &&
626         (
627                 cd a &&
628                 test_check_ignore "--stdin -v" <../stdin
629         )
630 '
631
632 for opts in '--stdin -z' '-z --stdin'
633 do
634         test_expect_success "$opts from subdirectory" '
635                 expect_from_stdin <expected-default0 &&
636                 (
637                         cd a &&
638                         test_check_ignore "'"$opts"'" <../stdin0
639                 )
640         '
641
642         test_expect_success "$opts from subdirectory with -v" '
643                 expect_from_stdin <expected-verbose0 &&
644                 (
645                         cd a &&
646                         test_check_ignore "'"$opts"' -v" <../stdin0
647                 )
648         '
649 done
650
651
652 test_done