check-ignore: Add option to ignore index contents

check-ignore currently shows how .gitignore rules would treat untracked
paths. Tracked paths do not generate useful output.  This prevents
debugging of why a path became tracked unexpectedly unless that path is
first removed from the index with `git rm --cached <path>`.

The option --no-index tells the command to bypass the check for the
path being in the index and hence allows tracked paths to be checked
too.

Whilst this behaviour deviates from the characteristics of `git add` and
`git status` its use case is unlikely to cause any user confusion.

Test scripts are augmented to check this option against the standard
ignores to ensure correct behaviour.

Signed-off-by: Dave Williams <dave@opensourcesolutions.co.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Dave Williams 2013-09-05 17:08:01 +01:00 committed by Junio C Hamano
parent 57e4c1783f
commit 8231fa6ae1
3 changed files with 74 additions and 11 deletions

View file

@ -45,6 +45,13 @@ OPTIONS
not be possible to distinguish between paths which match a
pattern and those which don't.
--no-index::
Don't look in the index when undertaking the checks. This can
be used to debug why a path became tracked by e.g. `git add .`
and was not ignored by the rules as expected by the user or when
developing patterns including negation to match a path previously
added with `git add -f`.
OUTPUT
------

View file

@ -5,7 +5,7 @@
#include "pathspec.h"
#include "parse-options.h"
static int quiet, verbose, stdin_paths, show_non_matching;
static int quiet, verbose, stdin_paths, show_non_matching, no_index;
static const char * const check_ignore_usage[] = {
"git check-ignore [options] pathname...",
"git check-ignore [options] --stdin < <list-of-paths>",
@ -24,6 +24,8 @@ static const struct option check_ignore_options[] = {
N_("terminate input and output records by a NUL character")),
OPT_BOOL('n', "non-matching", &show_non_matching,
N_("show non-matching input paths")),
OPT_BOOL(0, "no-index", &no_index,
N_("ignore index when checking")),
OPT_END()
};
@ -157,7 +159,7 @@ int cmd_check_ignore(int argc, const char **argv, const char *prefix)
die(_("--non-matching is only valid with --verbose"));
/* read_cache() is only necessary so we can watch out for submodules. */
if (read_cache() < 0)
if (!no_index && read_cache() < 0)
die(_("index file corrupt"));
memset(&dir, 0, sizeof(dir));

View file

@ -66,11 +66,11 @@ test_check_ignore () {
init_vars &&
rm -f "$HOME/stdout" "$HOME/stderr" "$HOME/cmd" &&
echo git $global_args check-ignore $quiet_opt $verbose_opt $non_matching_opt $args \
echo git $global_args check-ignore $quiet_opt $verbose_opt $non_matching_opt $no_index_opt $args \
>"$HOME/cmd" &&
echo "$expect_code" >"$HOME/expected-exit-code" &&
test_expect_code "$expect_code" \
git $global_args check-ignore $quiet_opt $verbose_opt $non_matching_opt $args \
git $global_args check-ignore $quiet_opt $verbose_opt $non_matching_opt $no_index_opt $args \
>"$HOME/stdout" 2>"$HOME/stderr" &&
test_cmp "$HOME/expected-stdout" "$HOME/stdout" &&
stderr_empty_on_success "$expect_code"
@ -87,6 +87,9 @@ test_check_ignore () {
# check-ignore --verbose output is the same as normal output except
# for the extra first column.
#
# A parameter is used to determine if the tests are run with the
# normal case (using the index), or with the --no-index option.
#
# Arguments:
# - (optional) prereqs for this test, e.g. 'SYMLINKS'
# - test name
@ -94,19 +97,26 @@ test_check_ignore () {
# from the other verbosity modes is automatically inferred
# from this value)
# - code to run (should invoke test_check_ignore)
test_expect_success_multi () {
# - index option: --index or --no-index
test_expect_success_multiple () {
prereq=
if test $# -eq 4
if test $# -eq 5
then
prereq=$1
shift
fi
if test "$4" = "--index"
then
no_index_opt=
else
no_index_opt=$4
fi
testname="$1" expect_all="$2" code="$3"
expect_verbose=$( echo "$expect_all" | grep -v '^:: ' )
expect=$( echo "$expect_verbose" | sed -e 's/.* //' )
test_expect_success $prereq "$testname" '
test_expect_success $prereq "$testname${no_index_opt:+ with $no_index_opt}" '
expect "$expect" &&
eval "$code"
'
@ -116,7 +126,8 @@ test_expect_success_multi () {
then
for quiet_opt in '-q' '--quiet'
do
test_expect_success $prereq "$testname${quiet_opt:+ with $quiet_opt}" "
opts="${no_index_opt:+$no_index_opt }$quiet_opt"
test_expect_success $prereq "$testname${opts:+ with $opts}" "
expect '' &&
$code
"
@ -126,7 +137,7 @@ test_expect_success_multi () {
for verbose_opt in '-v' '--verbose'
do
for non_matching_opt in '' ' -n' ' --non-matching'
for non_matching_opt in '' '-n' '--non-matching'
do
if test -n "$non_matching_opt"
then
@ -139,12 +150,21 @@ test_expect_success_multi () {
expect '$my_expect' &&
$code
"
opts="$verbose_opt$non_matching_opt"
opts="${no_index_opt:+$no_index_opt }$verbose_opt${non_matching_opt:+ $non_matching_opt}"
test_expect_success $prereq "$testname${opts:+ with $opts}" "$test_code"
done
done
verbose_opt=
non_matching_opt=
no_index_opt=
}
test_expect_success_multi () {
test_expect_success_multiple "$@" "--index"
}
test_expect_success_no_index_multi () {
test_expect_success_multiple "$@" "--no-index"
}
test_expect_success 'setup' '
@ -288,7 +308,7 @@ test_expect_success_multi 'needs work tree' '' '
# 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.
# index does unless the --no-index option is used.
for subdir in '' 'a/'
do
@ -303,27 +323,61 @@ do
":: ${subdir}non-existent" \
"test_check_ignore '${subdir}non-existent' 1"
test_expect_success_no_index_multi "non-existent file $where not ignored" \
":: ${subdir}non-existent" \
"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_no_index_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" \
":: ${subdir}not-ignored" \
"test_check_ignore '${subdir}not-ignored' 1"
test_expect_success_no_index_multi "existing untracked file $where not ignored" \
":: ${subdir}not-ignored" \
"test_check_ignore '${subdir}not-ignored' 1"
test_expect_success_multi "existing tracked file $where not ignored" \
":: ${subdir}ignored-but-in-index" \
"test_check_ignore '${subdir}ignored-but-in-index' 1"
test_expect_success_no_index_multi "existing tracked file $where shown as ignored" \
".gitignore:2:ignored-* ${subdir}ignored-but-in-index" \
"test_check_ignore '${subdir}ignored-but-in-index'"
test_expect_success_multi "existing untracked file $where ignored" \
".gitignore:2:ignored-* ${subdir}ignored-and-untracked" \
"test_check_ignore '${subdir}ignored-and-untracked'"
test_expect_success_no_index_multi "existing untracked file $where ignored" \
".gitignore:2:ignored-* ${subdir}ignored-and-untracked" \
"test_check_ignore '${subdir}ignored-and-untracked'"
test_expect_success_multi "mix of file types $where" \
":: ${subdir}non-existent
.gitignore:1:one ${subdir}one
:: ${subdir}not-ignored
:: ${subdir}ignored-but-in-index
.gitignore:2:ignored-* ${subdir}ignored-and-untracked" \
"test_check_ignore '
${subdir}non-existent
${subdir}one
${subdir}not-ignored
${subdir}ignored-but-in-index
${subdir}ignored-and-untracked'
"
test_expect_success_no_index_multi "mix of file types $where" \
":: ${subdir}non-existent
.gitignore:1:one ${subdir}one
:: ${subdir}not-ignored
.gitignore:2:ignored-* ${subdir}ignored-but-in-index
.gitignore:2:ignored-* ${subdir}ignored-and-untracked" \
"test_check_ignore '
${subdir}non-existent