You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
652 lines
15 KiB
652 lines
15 KiB
#!/bin/sh |
|
|
|
test_description=check-ignore |
|
|
|
. ./test-lib.sh |
|
|
|
init_vars () { |
|
global_excludes="$(pwd)/global-excludes" |
|
} |
|
|
|
enable_global_excludes () { |
|
init_vars && |
|
git config core.excludesfile "$global_excludes" |
|
} |
|
|
|
expect_in () { |
|
dest="$HOME/expected-$1" text="$2" |
|
if test -z "$text" |
|
then |
|
>"$dest" # avoid newline |
|
else |
|
echo "$text" >"$dest" |
|
fi |
|
} |
|
|
|
expect () { |
|
expect_in stdout "$1" |
|
} |
|
|
|
expect_from_stdin () { |
|
cat >"$HOME/expected-stdout" |
|
} |
|
|
|
test_stderr () { |
|
expected="$1" |
|
expect_in stderr "$1" && |
|
test_cmp "$HOME/expected-stderr" "$HOME/stderr" |
|
} |
|
|
|
stderr_contains () { |
|
regexp="$1" |
|
if grep "$regexp" "$HOME/stderr" |
|
then |
|
return 0 |
|
else |
|
echo "didn't find /$regexp/ in $HOME/stderr" |
|
cat "$HOME/stderr" |
|
return 1 |
|
fi |
|
} |
|
|
|
stderr_empty_on_success () { |
|
expect_code="$1" |
|
if test $expect_code = 0 |
|
then |
|
test_stderr "" |
|
else |
|
# If we expect failure then stderr might or might not be empty |
|
# due to --quiet - the caller can check its contents |
|
return 0 |
|
fi |
|
} |
|
|
|
test_check_ignore () { |
|
args="$1" expect_code="${2:-0}" global_args="$3" |
|
|
|
init_vars && |
|
rm -f "$HOME/stdout" "$HOME/stderr" "$HOME/cmd" && |
|
echo git $global_args check-ignore $quiet_opt $verbose_opt $args \ |
|
>"$HOME/cmd" && |
|
test_expect_code "$expect_code" \ |
|
git $global_args check-ignore $quiet_opt $verbose_opt $args \ |
|
>"$HOME/stdout" 2>"$HOME/stderr" && |
|
test_cmp "$HOME/expected-stdout" "$HOME/stdout" && |
|
stderr_empty_on_success "$expect_code" |
|
} |
|
|
|
# Runs the same code with 3 different levels of output verbosity, |
|
# expecting success each time. Takes advantage of the fact that |
|
# check-ignore --verbose output is the same as normal output except |
|
# for the extra first column. |
|
# |
|
# Arguments: |
|
# - (optional) prereqs for this test, e.g. 'SYMLINKS' |
|
# - test name |
|
# - output to expect from -v / --verbose mode |
|
# - code to run (should invoke test_check_ignore) |
|
test_expect_success_multi () { |
|
prereq= |
|
if test $# -eq 4 |
|
then |
|
prereq=$1 |
|
shift |
|
fi |
|
testname="$1" expect_verbose="$2" code="$3" |
|
|
|
expect=$( echo "$expect_verbose" | sed -e 's/.* //' ) |
|
|
|
test_expect_success $prereq "$testname" ' |
|
expect "$expect" && |
|
eval "$code" |
|
' |
|
|
|
for quiet_opt in '-q' '--quiet' |
|
do |
|
test_expect_success $prereq "$testname${quiet_opt:+ with $quiet_opt}" " |
|
expect '' && |
|
$code |
|
" |
|
done |
|
quiet_opt= |
|
|
|
for verbose_opt in '-v' '--verbose' |
|
do |
|
test_expect_success $prereq "$testname${verbose_opt:+ with $verbose_opt}" " |
|
expect '$expect_verbose' && |
|
$code |
|
" |
|
done |
|
verbose_opt= |
|
} |
|
|
|
test_expect_success 'setup' ' |
|
init_vars && |
|
mkdir -p a/b/ignored-dir a/submodule b && |
|
if test_have_prereq SYMLINKS |
|
then |
|
ln -s b a/symlink |
|
fi && |
|
( |
|
cd a/submodule && |
|
git init && |
|
echo a >a && |
|
git add a && |
|
git commit -m"commit in submodule" |
|
) && |
|
git add a/submodule && |
|
cat <<-\EOF >.gitignore && |
|
one |
|
ignored-* |
|
top-level-dir/ |
|
EOF |
|
for dir in . a |
|
do |
|
: >$dir/not-ignored && |
|
: >$dir/ignored-and-untracked && |
|
: >$dir/ignored-but-in-index |
|
done && |
|
git add -f ignored-but-in-index a/ignored-but-in-index && |
|
cat <<-\EOF >a/.gitignore && |
|
two* |
|
*three |
|
EOF |
|
cat <<-\EOF >a/b/.gitignore && |
|
four |
|
five |
|
# this comment should affect the line numbers |
|
six |
|
ignored-dir/ |
|
# and so should this blank line: |
|
|
|
!on* |
|
!two |
|
EOF |
|
echo "seven" >a/b/ignored-dir/.gitignore && |
|
test -n "$HOME" && |
|
cat <<-\EOF >"$global_excludes" && |
|
globalone |
|
!globaltwo |
|
globalthree |
|
EOF |
|
cat <<-\EOF >>.git/info/exclude |
|
per-repo |
|
EOF |
|
' |
|
|
|
############################################################################ |
|
# |
|
# test invalid inputs |
|
|
|
test_expect_success_multi '. corner-case' '' ' |
|
test_check_ignore . 1 |
|
' |
|
|
|
test_expect_success_multi 'empty command line' '' ' |
|
test_check_ignore "" 128 && |
|
stderr_contains "fatal: no path specified" |
|
' |
|
|
|
test_expect_success_multi '--stdin with empty STDIN' '' ' |
|
test_check_ignore "--stdin" 1 </dev/null && |
|
if test -n "$quiet_opt"; then |
|
test_stderr "" |
|
else |
|
test_stderr "no pathspec given." |
|
fi |
|
' |
|
|
|
test_expect_success '-q with multiple args' ' |
|
expect "" && |
|
test_check_ignore "-q one two" 128 && |
|
stderr_contains "fatal: --quiet is only valid with a single pathname" |
|
' |
|
|
|
test_expect_success '--quiet with multiple args' ' |
|
expect "" && |
|
test_check_ignore "--quiet one two" 128 && |
|
stderr_contains "fatal: --quiet is only valid with a single pathname" |
|
' |
|
|
|
for verbose_opt in '-v' '--verbose' |
|
do |
|
for quiet_opt in '-q' '--quiet' |
|
do |
|
test_expect_success "$quiet_opt $verbose_opt" " |
|
expect '' && |
|
test_check_ignore '$quiet_opt $verbose_opt foo' 128 && |
|
stderr_contains 'fatal: cannot have both --quiet and --verbose' |
|
" |
|
done |
|
done |
|
|
|
test_expect_success '--quiet with multiple args' ' |
|
expect "" && |
|
test_check_ignore "--quiet one two" 128 && |
|
stderr_contains "fatal: --quiet is only valid with a single pathname" |
|
' |
|
|
|
test_expect_success_multi 'erroneous use of --' '' ' |
|
test_check_ignore "--" 128 && |
|
stderr_contains "fatal: no path specified" |
|
' |
|
|
|
test_expect_success_multi '--stdin with superfluous arg' '' ' |
|
test_check_ignore "--stdin foo" 128 && |
|
stderr_contains "fatal: cannot specify pathnames with --stdin" |
|
' |
|
|
|
test_expect_success_multi '--stdin -z with superfluous arg' '' ' |
|
test_check_ignore "--stdin -z foo" 128 && |
|
stderr_contains "fatal: cannot specify pathnames with --stdin" |
|
' |
|
|
|
test_expect_success_multi '-z without --stdin' '' ' |
|
test_check_ignore "-z" 128 && |
|
stderr_contains "fatal: -z only makes sense with --stdin" |
|
' |
|
|
|
test_expect_success_multi '-z without --stdin and superfluous arg' '' ' |
|
test_check_ignore "-z foo" 128 && |
|
stderr_contains "fatal: -z only makes sense with --stdin" |
|
' |
|
|
|
test_expect_success_multi 'needs work tree' '' ' |
|
( |
|
cd .git && |
|
test_check_ignore "foo" 128 |
|
) && |
|
stderr_contains "fatal: This operation must be run in a work tree" |
|
' |
|
|
|
############################################################################ |
|
# |
|
# test standard ignores |
|
|
|
# First make sure that the presence of a file in the working tree |
|
# does not impact results, but that the presence of a file in the |
|
# index does. |
|
|
|
for subdir in '' 'a/' |
|
do |
|
if test -z "$subdir" |
|
then |
|
where="at top-level" |
|
else |
|
where="in subdir $subdir" |
|
fi |
|
|
|
test_expect_success_multi "non-existent file $where not ignored" '' " |
|
test_check_ignore '${subdir}non-existent' 1 |
|
" |
|
|
|
test_expect_success_multi "non-existent file $where ignored" \ |
|
".gitignore:1:one ${subdir}one" " |
|
test_check_ignore '${subdir}one' |
|
" |
|
|
|
test_expect_success_multi "existing untracked file $where not ignored" '' " |
|
test_check_ignore '${subdir}not-ignored' 1 |
|
" |
|
|
|
test_expect_success_multi "existing tracked file $where not ignored" '' " |
|
test_check_ignore '${subdir}ignored-but-in-index' 1 |
|
" |
|
|
|
test_expect_success_multi "existing untracked file $where ignored" \ |
|
".gitignore:2:ignored-* ${subdir}ignored-and-untracked" " |
|
test_check_ignore '${subdir}ignored-and-untracked' |
|
" |
|
done |
|
|
|
# Having established the above, from now on we mostly test against |
|
# files which do not exist in the working tree or index. |
|
|
|
test_expect_success 'sub-directory local ignore' ' |
|
expect "a/3-three" && |
|
test_check_ignore "a/3-three a/three-not-this-one" |
|
' |
|
|
|
test_expect_success 'sub-directory local ignore with --verbose' ' |
|
expect "a/.gitignore:2:*three a/3-three" && |
|
test_check_ignore "--verbose a/3-three a/three-not-this-one" |
|
' |
|
|
|
test_expect_success 'local ignore inside a sub-directory' ' |
|
expect "3-three" && |
|
( |
|
cd a && |
|
test_check_ignore "3-three three-not-this-one" |
|
) |
|
' |
|
test_expect_success 'local ignore inside a sub-directory with --verbose' ' |
|
expect "a/.gitignore:2:*three 3-three" && |
|
( |
|
cd a && |
|
test_check_ignore "--verbose 3-three three-not-this-one" |
|
) |
|
' |
|
|
|
test_expect_success_multi 'nested include' \ |
|
'a/b/.gitignore:8:!on* a/b/one' ' |
|
test_check_ignore "a/b/one" |
|
' |
|
|
|
############################################################################ |
|
# |
|
# test ignored sub-directories |
|
|
|
test_expect_success_multi 'ignored sub-directory' \ |
|
'a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir' ' |
|
test_check_ignore "a/b/ignored-dir" |
|
' |
|
|
|
test_expect_success 'multiple files inside ignored sub-directory' ' |
|
expect_from_stdin <<-\EOF && |
|
a/b/ignored-dir/foo |
|
a/b/ignored-dir/twoooo |
|
a/b/ignored-dir/seven |
|
EOF |
|
test_check_ignore "a/b/ignored-dir/foo a/b/ignored-dir/twoooo a/b/ignored-dir/seven" |
|
' |
|
|
|
test_expect_success 'multiple files inside ignored sub-directory with -v' ' |
|
expect_from_stdin <<-\EOF && |
|
a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir/foo |
|
a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir/twoooo |
|
a/b/.gitignore:5:ignored-dir/ a/b/ignored-dir/seven |
|
EOF |
|
test_check_ignore "-v a/b/ignored-dir/foo a/b/ignored-dir/twoooo a/b/ignored-dir/seven" |
|
' |
|
|
|
test_expect_success 'cd to ignored sub-directory' ' |
|
expect_from_stdin <<-\EOF && |
|
foo |
|
twoooo |
|
../one |
|
seven |
|
../../one |
|
EOF |
|
( |
|
cd a/b/ignored-dir && |
|
test_check_ignore "foo twoooo ../one seven ../../one" |
|
) |
|
' |
|
|
|
test_expect_success 'cd to ignored sub-directory with -v' ' |
|
expect_from_stdin <<-\EOF && |
|
a/b/.gitignore:5:ignored-dir/ foo |
|
a/b/.gitignore:5:ignored-dir/ twoooo |
|
a/b/.gitignore:8:!on* ../one |
|
a/b/.gitignore:5:ignored-dir/ seven |
|
.gitignore:1:one ../../one |
|
EOF |
|
( |
|
cd a/b/ignored-dir && |
|
test_check_ignore "-v foo twoooo ../one seven ../../one" |
|
) |
|
' |
|
|
|
############################################################################ |
|
# |
|
# test handling of symlinks |
|
|
|
test_expect_success_multi SYMLINKS 'symlink' '' ' |
|
test_check_ignore "a/symlink" 1 |
|
' |
|
|
|
test_expect_success_multi SYMLINKS 'beyond a symlink' '' ' |
|
test_check_ignore "a/symlink/foo" 128 && |
|
test_stderr "fatal: '\''a/symlink/foo'\'' is beyond a symbolic link" |
|
' |
|
|
|
test_expect_success_multi SYMLINKS 'beyond a symlink from subdirectory' '' ' |
|
( |
|
cd a && |
|
test_check_ignore "symlink/foo" 128 |
|
) && |
|
test_stderr "fatal: '\''symlink/foo'\'' is beyond a symbolic link" |
|
' |
|
|
|
############################################################################ |
|
# |
|
# test handling of submodules |
|
|
|
test_expect_success_multi 'submodule' '' ' |
|
test_check_ignore "a/submodule/one" 128 && |
|
test_stderr "fatal: Path '\''a/submodule/one'\'' is in submodule '\''a/submodule'\''" |
|
' |
|
|
|
test_expect_success_multi 'submodule from subdirectory' '' ' |
|
( |
|
cd a && |
|
test_check_ignore "submodule/one" 128 |
|
) && |
|
test_stderr "fatal: Path '\''a/submodule/one'\'' is in submodule '\''a/submodule'\''" |
|
' |
|
|
|
############################################################################ |
|
# |
|
# test handling of global ignore files |
|
|
|
test_expect_success 'global ignore not yet enabled' ' |
|
expect_from_stdin <<-\EOF && |
|
.git/info/exclude:7:per-repo per-repo |
|
a/.gitignore:2:*three a/globalthree |
|
.git/info/exclude:7:per-repo a/per-repo |
|
EOF |
|
test_check_ignore "-v globalone per-repo a/globalthree a/per-repo not-ignored a/globaltwo" |
|
' |
|
|
|
test_expect_success 'global ignore' ' |
|
enable_global_excludes && |
|
expect_from_stdin <<-\EOF && |
|
globalone |
|
per-repo |
|
globalthree |
|
a/globalthree |
|
a/per-repo |
|
globaltwo |
|
EOF |
|
test_check_ignore "globalone per-repo globalthree a/globalthree a/per-repo not-ignored globaltwo" |
|
' |
|
|
|
test_expect_success 'global ignore with -v' ' |
|
enable_global_excludes && |
|
expect_from_stdin <<-EOF && |
|
$global_excludes:1:globalone globalone |
|
.git/info/exclude:7:per-repo per-repo |
|
$global_excludes:3:globalthree globalthree |
|
a/.gitignore:2:*three a/globalthree |
|
.git/info/exclude:7:per-repo a/per-repo |
|
$global_excludes:2:!globaltwo globaltwo |
|
EOF |
|
test_check_ignore "-v globalone per-repo globalthree a/globalthree a/per-repo not-ignored globaltwo" |
|
' |
|
|
|
############################################################################ |
|
# |
|
# test --stdin |
|
|
|
cat <<-\EOF >stdin |
|
one |
|
not-ignored |
|
a/one |
|
a/not-ignored |
|
a/b/on |
|
a/b/one |
|
a/b/one one |
|
"a/b/one two" |
|
"a/b/one\"three" |
|
a/b/not-ignored |
|
a/b/two |
|
a/b/twooo |
|
globaltwo |
|
a/globaltwo |
|
a/b/globaltwo |
|
b/globaltwo |
|
EOF |
|
cat <<-\EOF >expected-default |
|
one |
|
a/one |
|
a/b/on |
|
a/b/one |
|
a/b/one one |
|
a/b/one two |
|
"a/b/one\"three" |
|
a/b/two |
|
a/b/twooo |
|
globaltwo |
|
a/globaltwo |
|
a/b/globaltwo |
|
b/globaltwo |
|
EOF |
|
cat <<-EOF >expected-verbose |
|
.gitignore:1:one one |
|
.gitignore:1:one a/one |
|
a/b/.gitignore:8:!on* a/b/on |
|
a/b/.gitignore:8:!on* a/b/one |
|
a/b/.gitignore:8:!on* a/b/one one |
|
a/b/.gitignore:8:!on* a/b/one two |
|
a/b/.gitignore:8:!on* "a/b/one\"three" |
|
a/b/.gitignore:9:!two a/b/two |
|
a/.gitignore:1:two* a/b/twooo |
|
$global_excludes:2:!globaltwo globaltwo |
|
$global_excludes:2:!globaltwo a/globaltwo |
|
$global_excludes:2:!globaltwo a/b/globaltwo |
|
$global_excludes:2:!globaltwo b/globaltwo |
|
EOF |
|
|
|
sed -e 's/^"//' -e 's/\\//' -e 's/"$//' stdin | \ |
|
tr "\n" "\0" >stdin0 |
|
sed -e 's/^"//' -e 's/\\//' -e 's/"$//' expected-default | \ |
|
tr "\n" "\0" >expected-default0 |
|
sed -e 's/ "/ /' -e 's/\\//' -e 's/"$//' expected-verbose | \ |
|
tr ":\t\n" "\0" >expected-verbose0 |
|
|
|
test_expect_success '--stdin' ' |
|
expect_from_stdin <expected-default && |
|
test_check_ignore "--stdin" <stdin |
|
' |
|
|
|
test_expect_success '--stdin -q' ' |
|
expect "" && |
|
test_check_ignore "-q --stdin" <stdin |
|
' |
|
|
|
test_expect_success '--stdin -v' ' |
|
expect_from_stdin <expected-verbose && |
|
test_check_ignore "-v --stdin" <stdin |
|
' |
|
|
|
for opts in '--stdin -z' '-z --stdin' |
|
do |
|
test_expect_success "$opts" " |
|
expect_from_stdin <expected-default0 && |
|
test_check_ignore '$opts' <stdin0 |
|
" |
|
|
|
test_expect_success "$opts -q" " |
|
expect "" && |
|
test_check_ignore '-q $opts' <stdin0 |
|
" |
|
|
|
test_expect_success "$opts -v" " |
|
expect_from_stdin <expected-verbose0 && |
|
test_check_ignore '-v $opts' <stdin0 |
|
" |
|
done |
|
|
|
cat <<-\EOF >stdin |
|
../one |
|
../not-ignored |
|
one |
|
not-ignored |
|
b/on |
|
b/one |
|
b/one one |
|
"b/one two" |
|
"b/one\"three" |
|
b/two |
|
b/not-ignored |
|
b/twooo |
|
../globaltwo |
|
globaltwo |
|
b/globaltwo |
|
../b/globaltwo |
|
EOF |
|
cat <<-\EOF >expected-default |
|
../one |
|
one |
|
b/on |
|
b/one |
|
b/one one |
|
b/one two |
|
"b/one\"three" |
|
b/two |
|
b/twooo |
|
../globaltwo |
|
globaltwo |
|
b/globaltwo |
|
../b/globaltwo |
|
EOF |
|
cat <<-EOF >expected-verbose |
|
.gitignore:1:one ../one |
|
.gitignore:1:one one |
|
a/b/.gitignore:8:!on* b/on |
|
a/b/.gitignore:8:!on* b/one |
|
a/b/.gitignore:8:!on* b/one one |
|
a/b/.gitignore:8:!on* b/one two |
|
a/b/.gitignore:8:!on* "b/one\"three" |
|
a/b/.gitignore:9:!two b/two |
|
a/.gitignore:1:two* b/twooo |
|
$global_excludes:2:!globaltwo ../globaltwo |
|
$global_excludes:2:!globaltwo globaltwo |
|
$global_excludes:2:!globaltwo b/globaltwo |
|
$global_excludes:2:!globaltwo ../b/globaltwo |
|
EOF |
|
|
|
sed -e 's/^"//' -e 's/\\//' -e 's/"$//' stdin | \ |
|
tr "\n" "\0" >stdin0 |
|
sed -e 's/^"//' -e 's/\\//' -e 's/"$//' expected-default | \ |
|
tr "\n" "\0" >expected-default0 |
|
sed -e 's/ "/ /' -e 's/\\//' -e 's/"$//' expected-verbose | \ |
|
tr ":\t\n" "\0" >expected-verbose0 |
|
|
|
test_expect_success '--stdin from subdirectory' ' |
|
expect_from_stdin <expected-default && |
|
( |
|
cd a && |
|
test_check_ignore "--stdin" <../stdin |
|
) |
|
' |
|
|
|
test_expect_success '--stdin from subdirectory with -v' ' |
|
expect_from_stdin <expected-verbose && |
|
( |
|
cd a && |
|
test_check_ignore "--stdin -v" <../stdin |
|
) |
|
' |
|
|
|
for opts in '--stdin -z' '-z --stdin' |
|
do |
|
test_expect_success "$opts from subdirectory" ' |
|
expect_from_stdin <expected-default0 && |
|
( |
|
cd a && |
|
test_check_ignore "'"$opts"'" <../stdin0 |
|
) |
|
' |
|
|
|
test_expect_success "$opts from subdirectory with -v" ' |
|
expect_from_stdin <expected-verbose0 && |
|
( |
|
cd a && |
|
test_check_ignore "'"$opts"' -v" <../stdin0 |
|
) |
|
' |
|
done |
|
|
|
|
|
test_done
|
|
|