Merge branch 'dw/check-ignore-sans-index'

"git check-ignore" follows the same rule as "git add" and "git
status" in that the ignore/exclude mechanism does not take effect
on paths that are already tracked.  With "--no-index" option, it
can be used to diagnose which paths that should have been ignored
have been mistakenly added to the index.

* dw/check-ignore-sans-index:
  check-ignore: Add option to ignore index contents
This commit is contained in:
Junio C Hamano 2013-09-20 12:37:32 -07:00
commit 005a1de380
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 not be possible to distinguish between paths which match a
pattern and those which don't. 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 OUTPUT
------ ------

View file

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

View file

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