add git-check-ignore sub-command

This works in a similar manner to git-check-attr.

Thanks to Jeff King and Junio C Hamano for the idea:
http://thread.gmane.org/gmane.comp.version-control.git/108671/focus=108815

Signed-off-by: Adam Spiers <git@adamspiers.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Adam Spiers 2013-01-06 16:58:13 +00:00 committed by Junio C Hamano
parent 1794e6e097
commit 368aa52952
11 changed files with 905 additions and 3 deletions

1
.gitignore vendored
View File

@ -19,6 +19,7 @@
/git-bundle
/git-cat-file
/git-check-attr
/git-check-ignore
/git-check-ref-format
/git-checkout
/git-checkout-index

View File

@ -0,0 +1,89 @@
git-check-ignore(1)
===================
NAME
----
git-check-ignore - Debug gitignore / exclude files
SYNOPSIS
--------
[verse]
'git check-ignore' [options] pathname...
'git check-ignore' [options] --stdin < <list-of-paths>
DESCRIPTION
-----------
For each pathname given via the command-line or from a file via
`--stdin`, show the pattern from .gitignore (or other input files to
the exclude mechanism) that decides if the pathname is excluded or
included. Later patterns within a file take precedence over earlier
ones.
OPTIONS
-------
-q, --quiet::
Don't output anything, just set exit status. This is only
valid with a single pathname.
-v, --verbose::
Also output details about the matching pattern (if any)
for each given pathname.
--stdin::
Read file names from stdin instead of from the command-line.
-z::
The output format is modified to be machine-parseable (see
below). If `--stdin` is also given, input paths are separated
with a NUL character instead of a linefeed character.
OUTPUT
------
By default, any of the given pathnames which match an ignore pattern
will be output, one per line. If no pattern matches a given path,
nothing will be output for that path; this means that path will not be
ignored.
If `--verbose` is specified, the output is a series of lines of the form:
<source> <COLON> <linenum> <COLON> <pattern> <HT> <pathname>
<pathname> is the path of a file being queried, <pattern> is the
matching pattern, <source> is the pattern's source file, and <linenum>
is the line number of the pattern within that source. If the pattern
contained a `!` prefix or `/` suffix, it will be preserved in the
output. <source> will be an absolute path when referring to the file
configured by `core.excludesfile`, or relative to the repository root
when referring to `.git/info/exclude` or a per-directory exclude file.
If `-z` is specified, the pathnames in the output are delimited by the
null character; if `--verbose` is also specified then null characters
are also used instead of colons and hard tabs:
<source> <NULL> <linenum> <NULL> <pattern> <NULL> <pathname> <NULL>
EXIT STATUS
-----------
0::
One or more of the provided paths is ignored.
1::
None of the provided paths are ignored.
128::
A fatal error was encountered.
SEE ALSO
--------
linkgit:gitignore[5]
linkgit:gitconfig[5]
linkgit:git-ls-files[5]
GIT
---
Part of the linkgit:git[1] suite

View File

@ -153,8 +153,10 @@ The second .gitignore prevents git from ignoring
SEE ALSO
--------
linkgit:git-rm[1], linkgit:git-update-index[1],
linkgit:gitrepository-layout[5]
linkgit:git-rm[1],
linkgit:git-update-index[1],
linkgit:gitrepository-layout[5],
linkgit:git-check-ignore[1]
GIT
---

View File

@ -81,6 +81,6 @@ marked. If you to exclude files, make sure you have loaded index first.
* Use `dir.entries[]`.
* Call `free_directory()` when none of the contained elements are no longer in use.
* Call `clear_directory()` when none of the contained elements are no longer in use.
(JC)

View File

@ -822,6 +822,7 @@ BUILTIN_OBJS += builtin/branch.o
BUILTIN_OBJS += builtin/bundle.o
BUILTIN_OBJS += builtin/cat-file.o
BUILTIN_OBJS += builtin/check-attr.o
BUILTIN_OBJS += builtin/check-ignore.o
BUILTIN_OBJS += builtin/check-ref-format.o
BUILTIN_OBJS += builtin/checkout-index.o
BUILTIN_OBJS += builtin/checkout.o

View File

@ -58,6 +58,7 @@ extern int cmd_cat_file(int argc, const char **argv, const char *prefix);
extern int cmd_checkout(int argc, const char **argv, const char *prefix);
extern int cmd_checkout_index(int argc, const char **argv, const char *prefix);
extern int cmd_check_attr(int argc, const char **argv, const char *prefix);
extern int cmd_check_ignore(int argc, const char **argv, const char *prefix);
extern int cmd_check_ref_format(int argc, const char **argv, const char *prefix);
extern int cmd_cherry(int argc, const char **argv, const char *prefix);
extern int cmd_cherry_pick(int argc, const char **argv, const char *prefix);

173
builtin/check-ignore.c Normal file
View File

@ -0,0 +1,173 @@
#include "builtin.h"
#include "cache.h"
#include "dir.h"
#include "quote.h"
#include "pathspec.h"
#include "parse-options.h"
static int quiet, verbose, stdin_paths;
static const char * const check_ignore_usage[] = {
"git check-ignore [options] pathname...",
"git check-ignore [options] --stdin < <list-of-paths>",
NULL
};
static int null_term_line;
static const struct option check_ignore_options[] = {
OPT__QUIET(&quiet, N_("suppress progress reporting")),
OPT__VERBOSE(&verbose, N_("be verbose")),
OPT_GROUP(""),
OPT_BOOLEAN(0, "stdin", &stdin_paths,
N_("read file names from stdin")),
OPT_BOOLEAN('z', NULL, &null_term_line,
N_("input paths are terminated by a null character")),
OPT_END()
};
static void output_exclude(const char *path, struct exclude *exclude)
{
char *bang = exclude->flags & EXC_FLAG_NEGATIVE ? "!" : "";
char *slash = exclude->flags & EXC_FLAG_MUSTBEDIR ? "/" : "";
if (!null_term_line) {
if (!verbose) {
write_name_quoted(path, stdout, '\n');
} else {
quote_c_style(exclude->el->src, NULL, stdout, 0);
printf(":%d:%s%s%s\t",
exclude->srcpos,
bang, exclude->pattern, slash);
quote_c_style(path, NULL, stdout, 0);
fputc('\n', stdout);
}
} else {
if (!verbose) {
printf("%s%c", path, '\0');
} else {
printf("%s%c%d%c%s%s%s%c%s%c",
exclude->el->src, '\0',
exclude->srcpos, '\0',
bang, exclude->pattern, slash, '\0',
path, '\0');
}
}
}
static int check_ignore(const char *prefix, const char **pathspec)
{
struct dir_struct dir;
const char *path, *full_path;
char *seen;
int num_ignored = 0, dtype = DT_UNKNOWN, i;
struct path_exclude_check check;
struct exclude *exclude;
/* read_cache() is only necessary so we can watch out for submodules. */
if (read_cache() < 0)
die(_("index file corrupt"));
memset(&dir, 0, sizeof(dir));
dir.flags |= DIR_COLLECT_IGNORED;
setup_standard_excludes(&dir);
if (!pathspec || !*pathspec) {
if (!quiet)
fprintf(stderr, "no pathspec given.\n");
return 0;
}
path_exclude_check_init(&check, &dir);
/*
* look for pathspecs matching entries in the index, since these
* should not be ignored, in order to be consistent with
* 'git status', 'git add' etc.
*/
seen = find_pathspecs_matching_against_index(pathspec);
for (i = 0; pathspec[i]; i++) {
path = pathspec[i];
full_path = prefix_path(prefix, prefix
? strlen(prefix) : 0, path);
full_path = check_path_for_gitlink(full_path);
die_if_path_beyond_symlink(full_path, prefix);
if (!seen[i] && path[0]) {
exclude = last_exclude_matching_path(&check, full_path,
-1, &dtype);
if (exclude) {
if (!quiet)
output_exclude(path, exclude);
num_ignored++;
}
}
}
free(seen);
clear_directory(&dir);
path_exclude_check_clear(&check);
return num_ignored;
}
static int check_ignore_stdin_paths(const char *prefix)
{
struct strbuf buf, nbuf;
char **pathspec = NULL;
size_t nr = 0, alloc = 0;
int line_termination = null_term_line ? 0 : '\n';
int num_ignored;
strbuf_init(&buf, 0);
strbuf_init(&nbuf, 0);
while (strbuf_getline(&buf, stdin, line_termination) != EOF) {
if (line_termination && buf.buf[0] == '"') {
strbuf_reset(&nbuf);
if (unquote_c_style(&nbuf, buf.buf, NULL))
die("line is badly quoted");
strbuf_swap(&buf, &nbuf);
}
ALLOC_GROW(pathspec, nr + 1, alloc);
pathspec[nr] = xcalloc(strlen(buf.buf) + 1, sizeof(*buf.buf));
strcpy(pathspec[nr++], buf.buf);
}
ALLOC_GROW(pathspec, nr + 1, alloc);
pathspec[nr] = NULL;
num_ignored = check_ignore(prefix, (const char **)pathspec);
maybe_flush_or_die(stdout, "attribute to stdout");
strbuf_release(&buf);
strbuf_release(&nbuf);
free(pathspec);
return num_ignored;
}
int cmd_check_ignore(int argc, const char **argv, const char *prefix)
{
int num_ignored;
git_config(git_default_config, NULL);
argc = parse_options(argc, argv, prefix, check_ignore_options,
check_ignore_usage, 0);
if (stdin_paths) {
if (argc > 0)
die(_("cannot specify pathnames with --stdin"));
} else {
if (null_term_line)
die(_("-z only makes sense with --stdin"));
if (argc == 0)
die(_("no path specified"));
}
if (quiet) {
if (argc > 1)
die(_("--quiet is only valid with a single pathname"));
if (verbose)
die(_("cannot have both --quiet and --verbose"));
}
if (stdin_paths) {
num_ignored = check_ignore_stdin_paths(prefix);
} else {
num_ignored = check_ignore(prefix, argv);
maybe_flush_or_die(stdout, "ignore to stdout");
}
return !num_ignored;
}

View File

@ -12,6 +12,7 @@ git-branch mainporcelain common
git-bundle mainporcelain
git-cat-file plumbinginterrogators
git-check-attr purehelpers
git-check-ignore purehelpers
git-checkout mainporcelain common
git-checkout-index plumbingmanipulators
git-check-ref-format purehelpers

View File

@ -842,6 +842,7 @@ __git_list_porcelain_commands ()
archimport) : import;;
cat-file) : plumbing;;
check-attr) : plumbing;;
check-ignore) : plumbing;;
check-ref-format) : plumbing;;
checkout-index) : plumbing;;
commit-tree) : plumbing;;

1
git.c
View File

@ -340,6 +340,7 @@ static void handle_internal_command(int argc, const char **argv)
{ "bundle", cmd_bundle, RUN_SETUP_GENTLY },
{ "cat-file", cmd_cat_file, RUN_SETUP },
{ "check-attr", cmd_check_attr, RUN_SETUP },
{ "check-ignore", cmd_check_ignore, RUN_SETUP | NEED_WORK_TREE },
{ "check-ref-format", cmd_check_ref_format },
{ "checkout", cmd_checkout, RUN_SETUP | NEED_WORK_TREE },
{ "checkout-index", cmd_checkout_index,

632
t/t0008-ignores.sh Executable file
View File

@ -0,0 +1,632 @@
#!/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"
}
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-*
EOF
touch {,a/}{not-ignored,ignored-{and-untracked,but-in-index}} &&
git add -f {,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 '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