{"thread":{"id":"34835","subject":"[PATCH V2] check-ignore: Add option to ignore index contents","startedAt":"2013-09-02T21:20:54Z","lastAt":"2013-09-02T22:15:31Z","messageCount":2,"participants":["Dave Williams","Eric Sunshine"],"isPatch":true,"patchVersion":2,"patchTotal":null},"messages":[{"id":"226556","messageId":"20130902212054.GA7012@opensourcesolutions.co.uk","threadId":"34835","inReplyTo":null,"subject":"[PATCH V2] check-ignore: Add option to ignore index contents","fromName":"Dave Williams","fromEmail":"dave@opensourcesolutions.co.uk","sentAt":"2013-09-02T21:20:54Z","receivedAt":"2013-09-02T21:20:54Z","isPatch":true,"sender":{"key":"dave@opensourcesolutions.co.uk","avatar":"https://avatars.githubusercontent.com/u/2284929?v=4"},"body":"I have updated the original version of this patch to encompass the\nfeedback comments obtained. Updates include:\n1) Rename option to --no-index for consistency with other commands\n2) Improved Documentation text\n3) Extension to test scripts to include this option\n\nRegarding test scripts I have scoped coverage to ensure correct\nbehaviour with the new option in all standard cases but without\nduplicating every single corner case.\n\nThe original patch is at $gmane/233381.\n\n\n\ncheck-ignore currently shows how .gitignore rules would treat untracked\npaths. Tracked paths do not generate useful output.  This prevents\ndebugging of why a path became tracked unexpectedly unless that path is\nfirst removed from the index with `git rm --cached <path>`.\n\nThis option (-i, --no-index) simply by-passes the check for the path\nbeing in the index and hence allows tracked paths to be checked too.\n\nWhilst this behaviour deviates from the characteristics of `git add` and\n`git status` its use case is unlikely to cause any user confusion.\n\nTest scripts are augmented to check this option against the standard\nignores to ensure correct behaviour.\n\nSigned-off-by: Dave Williams <dave@opensourcesolutions.co.uk>\n---\n Documentation/git-check-ignore.txt |  7 ++++\n builtin/check-ignore.c             | 14 ++++---\n t/t0008-ignores.sh                 | 77 +++++++++++++++++++++++++++++++++-----\n 3 files changed, 83 insertions(+), 15 deletions(-)\n\ndiff --git a/Documentation/git-check-ignore.txt b/Documentation/git-check-ignore.txt\nindex d2df487..96c591f 100644\n--- a/Documentation/git-check-ignore.txt\n+++ b/Documentation/git-check-ignore.txt\n@@ -45,6 +45,13 @@ OPTIONS\n \tnot be possible to distinguish between paths which match a\n \tpattern and those which don't.\n \n+-i, --no-index::\n+\tDon't look in the index when undertaking the checks. This can\n+\tbe used to debug why a path became tracked by e.g. `git add .`\n+\tand was not ignored by the rules as expected by the user or when\n+\tdeveloping patterns including negation to match a path previously\n+\tadded with `git add -f`.\n+\n OUTPUT\n ------\n \ndiff --git a/builtin/check-ignore.c b/builtin/check-ignore.c\nindex 4a8fc70..2b0c8a6 100644\n--- a/builtin/check-ignore.c\n+++ b/builtin/check-ignore.c\n@@ -5,7 +5,7 @@\n #include \"pathspec.h\"\n #include \"parse-options.h\"\n \n-static int quiet, verbose, stdin_paths, show_non_matching;\n+static int quiet, verbose, stdin_paths, show_non_matching, no_index;\n static const char * const check_ignore_usage[] = {\n \"git check-ignore [options] pathname...\",\n \"git check-ignore [options] --stdin < <list-of-paths>\",\n@@ -24,6 +24,8 @@ static const struct option check_ignore_options[] = {\n \t\t    N_(\"input paths are terminated by a null character\")),\n \tOPT_BOOLEAN('n', \"non-matching\", &show_non_matching,\n \t\t    N_(\"show non-matching input paths\")),\n+\tOPT_BOOLEAN('i', \"no-index\", &no_index,\n+\t\t    N_(\"ignore index when checking\")),\n \tOPT_END()\n };\n \n@@ -67,7 +69,7 @@ static int check_ignore(struct dir_struct *dir,\n \t\t\tconst char *prefix, const char **pathspec)\n {\n \tconst char *path, *full_path;\n-\tchar *seen;\n+\tchar *seen = NULL;\n \tint num_ignored = 0, dtype = DT_UNKNOWN, i;\n \tstruct exclude *exclude;\n \n@@ -82,7 +84,9 @@ static int check_ignore(struct dir_struct *dir,\n \t * should not be ignored, in order to be consistent with\n \t * 'git status', 'git add' etc.\n \t */\n-\tseen = find_pathspecs_matching_against_index(pathspec);\n+\tif (!no_index) {\n+\t\tseen = find_pathspecs_matching_against_index(pathspec);\n+\t}\n \tfor (i = 0; pathspec[i]; i++) {\n \t\tpath = pathspec[i];\n \t\tfull_path = prefix_path(prefix, prefix\n@@ -90,7 +94,7 @@ static int check_ignore(struct dir_struct *dir,\n \t\tfull_path = check_path_for_gitlink(full_path);\n \t\tdie_if_path_beyond_symlink(full_path, prefix);\n \t\texclude = NULL;\n-\t\tif (!seen[i]) {\n+\t\tif (no_index || !seen[i]) {\n \t\t\texclude = last_exclude_matching(dir, full_path, &dtype);\n \t\t}\n \t\tif (!quiet && (exclude || show_non_matching))\n@@ -157,7 +161,7 @@ int cmd_check_ignore(int argc, const char **argv, const char *prefix)\n \t\tdie(_(\"--non-matching is only valid with --verbose\"));\n \n \t/* read_cache() is only necessary so we can watch out for submodules. */\n-\tif (read_cache() < 0)\n+\tif (!no_index && read_cache() < 0)\n \t\tdie(_(\"index file corrupt\"));\n \n \tmemset(&dir, 0, sizeof(dir));\ndiff --git a/t/t0008-ignores.sh b/t/t0008-ignores.sh\nindex c29342d..0ad0534 100755\n--- a/t/t0008-ignores.sh\n+++ b/t/t0008-ignores.sh\n@@ -66,11 +66,11 @@ test_check_ignore () {\n \n \tinit_vars &&\n \trm -f \"$HOME/stdout\" \"$HOME/stderr\" \"$HOME/cmd\" &&\n-\techo git $global_args check-ignore $quiet_opt $verbose_opt $non_matching_opt $args \\\n+\techo git $global_args check-ignore $quiet_opt $verbose_opt $non_matching_opt $no_index_opt $args \\\n \t\t>\"$HOME/cmd\" &&\n \techo \"$expect_code\" >\"$HOME/expected-exit-code\" &&\n \ttest_expect_code \"$expect_code\" \\\n-\t\tgit $global_args check-ignore $quiet_opt $verbose_opt $non_matching_opt $args \\\n+\t\tgit $global_args check-ignore $quiet_opt $verbose_opt $non_matching_opt $no_index_opt $args \\\n \t\t>\"$HOME/stdout\" 2>\"$HOME/stderr\" &&\n \ttest_cmp \"$HOME/expected-stdout\" \"$HOME/stdout\" &&\n \tstderr_empty_on_success \"$expect_code\"\n@@ -87,6 +87,9 @@ test_check_ignore () {\n # check-ignore --verbose output is the same as normal output except\n # for the extra first column.\n #\n+# A parameter is used to determine if the tests are run with the\n+# normal case (using the index), or with the -i or --no_index option.\n+#\n # Arguments:\n #   - (optional) prereqs for this test, e.g. 'SYMLINKS'\n #   - test name\n@@ -94,19 +97,26 @@ test_check_ignore () {\n #     from the other verbosity modes is automatically inferred\n #     from this value)\n #   - code to run (should invoke test_check_ignore)\n-test_expect_success_multi () {\n+#   - index option: --index, -i or --no-index\n+test_expect_success_multitude () {\n \tprereq=\n-\tif test $# -eq 4\n+\tif test $# -eq 5\n \tthen\n \t\tprereq=$1\n \t\tshift\n \tfi\n+\tif test \"$4\" = \"--index\"\n+\tthen\n+\t\tno_index_opt=\n+\telse\n+\t\tno_index_opt=$4\n+\tfi\n \ttestname=\"$1\" expect_all=\"$2\" code=\"$3\"\n \n \texpect_verbose=$( echo \"$expect_all\" | grep -v '^::\t' )\n \texpect=$( echo \"$expect_verbose\" | sed -e 's/.*\t//' )\n \n-\ttest_expect_success $prereq \"$testname\" '\n+\ttest_expect_success $prereq \"$testname${no_index_opt:+ with $no_index_opt}\" '\n \t\texpect \"$expect\" &&\n \t\teval \"$code\"\n \t'\n@@ -114,9 +124,10 @@ test_expect_success_multi () {\n \t# --quiet is only valid when a single pattern is passed\n \tif test $( echo \"$expect_all\" | wc -l ) = 1\n \tthen\n-\t\tfor quiet_opt in '-q' '--quiet'\n+\t\tfor quiet_opt in ' -q' ' --quiet'\n \t\tdo\n-\t\t\ttest_expect_success $prereq \"$testname${quiet_opt:+ with $quiet_opt}\" \"\n+\t\t\topts=\"$no_index_opt$quiet_opt\"\n+\t\t\ttest_expect_success $prereq \"$testname${opts:+ with $opts}\" \"\n \t\t\texpect '' &&\n \t\t\t$code\n \t\t\"\n@@ -124,7 +135,7 @@ test_expect_success_multi () {\n \t\tquiet_opt=\n \tfi\n \n-\tfor verbose_opt in '-v' '--verbose'\n+\tfor verbose_opt in ' -v' ' --verbose'\n \tdo\n \t\tfor non_matching_opt in '' ' -n' ' --non-matching'\n \t\tdo\n@@ -139,12 +150,24 @@ test_expect_success_multi () {\n \t\t\t\texpect '$my_expect' &&\n \t\t\t\t$code\n \t\t\t\"\n-\t\t\topts=\"$verbose_opt$non_matching_opt\"\n+\t\t\topts=\"$no_index_opt$verbose_opt$non_matching_opt\"\n \t\t\ttest_expect_success $prereq \"$testname${opts:+ with $opts}\" \"$test_code\"\n \t\tdone\n \tdone\n \tverbose_opt=\n \tnon_matching_opt=\n+\tno_index_opt=\n+}\n+\n+test_expect_success_multi () {\n+\ttest_expect_success_multitude \"$@\" \"--index\"\n+}\n+\n+test_expect_success_no_index_multi () {\n+\tfor ni in '-i' '--no-index'\n+\tdo\n+\t\ttest_expect_success_multitude \"$@\" \"$ni\"\n+\tdone\n }\n \n test_expect_success 'setup' '\n@@ -288,7 +311,7 @@ test_expect_success_multi 'needs work tree' '' '\n \n # First make sure that the presence of a file in the working tree\n # does not impact results, but that the presence of a file in the\n-# index does.\n+# index does unless the --no-index option is used.\n \n for subdir in '' 'a/'\n do\n@@ -303,22 +326,42 @@ do\n \t\t\"::\t${subdir}non-existent\" \\\n \t\t\"test_check_ignore '${subdir}non-existent' 1\"\n \n+\ttest_expect_success_no_index_multi \"non-existent file $where not ignored\" \\\n+\t\t\"::\t${subdir}non-existent\" \\\n+\t\t\"test_check_ignore '${subdir}non-existent' 1\"\n+\n \ttest_expect_success_multi \"non-existent file $where ignored\" \\\n \t\t\".gitignore:1:one\t${subdir}one\" \\\n \t\t\"test_check_ignore '${subdir}one'\"\n \n+\ttest_expect_success_no_index_multi \"non-existent file $where ignored\" \\\n+\t\t\".gitignore:1:one\t${subdir}one\" \\\n+\t\t\"test_check_ignore '${subdir}one'\"\n+\n \ttest_expect_success_multi \"existing untracked file $where not ignored\" \\\n \t\t\"::\t${subdir}not-ignored\" \\\n \t\t\"test_check_ignore '${subdir}not-ignored' 1\"\n \n+\ttest_expect_success_no_index_multi \"existing untracked file $where not ignored\" \\\n+\t\t\"::\t${subdir}not-ignored\" \\\n+\t\t\"test_check_ignore '${subdir}not-ignored' 1\"\n+\n \ttest_expect_success_multi \"existing tracked file $where not ignored\" \\\n \t\t\"::\t${subdir}ignored-but-in-index\" \\\n \t\t\"test_check_ignore '${subdir}ignored-but-in-index' 1\"\n \n+\ttest_expect_success_no_index_multi \"existing tracked file $where shown as ignored\" \\\n+\t\t\".gitignore:2:ignored-*\t${subdir}ignored-but-in-index\" \\\n+\t\t\"test_check_ignore '${subdir}ignored-but-in-index'\"\n+\n \ttest_expect_success_multi \"existing untracked file $where ignored\" \\\n \t\t\".gitignore:2:ignored-*\t${subdir}ignored-and-untracked\" \\\n \t\t\"test_check_ignore '${subdir}ignored-and-untracked'\"\n \n+\ttest_expect_success_no_index_multi \"existing untracked file $where ignored\" \\\n+\t\t\".gitignore:2:ignored-*\t${subdir}ignored-and-untracked\" \\\n+\t\t\"test_check_ignore '${subdir}ignored-and-untracked'\"\n+\n \ttest_expect_success_multi \"mix of file types $where\" \\\n \"::\t${subdir}non-existent\n .gitignore:1:one\t${subdir}one\n@@ -332,6 +375,20 @@ do\n \t\t\t${subdir}ignored-but-in-index\n \t\t\t${subdir}ignored-and-untracked'\n \t\t\"\n+\n+\ttest_expect_success_no_index_multi \"mix of file types $where\" \\\n+\"::\t${subdir}non-existent\n+.gitignore:1:one\t${subdir}one\n+::\t${subdir}not-ignored\n+.gitignore:2:ignored-*\t${subdir}ignored-but-in-index\n+.gitignore:2:ignored-*\t${subdir}ignored-and-untracked\" \\\n+\t\t\"test_check_ignore '\n+\t\t\t${subdir}non-existent\n+\t\t\t${subdir}one\n+\t\t\t${subdir}not-ignored\n+\t\t\t${subdir}ignored-but-in-index\n+\t\t\t${subdir}ignored-and-untracked'\n+\t\t\"\n done\n \n # Having established the above, from now on we mostly test against\n-- \n1.8.4.rc3\n"},{"id":"226560","messageId":"CAPig+cRPmFViknOkq3OnK3wjTtdd+7ywrCJUHd_85=4xyzHH_g@mail.gmail.com","threadId":"34835","inReplyTo":"20130902212054.GA7012@opensourcesolutions.co.uk","subject":"Re: [PATCH V2] check-ignore: Add option to ignore index contents","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2013-09-02T22:15:31Z","receivedAt":"2013-09-02T22:15:31Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Mon, Sep 2, 2013 at 5:20 PM, Dave Williams\n<dave@opensourcesolutions.co.uk> wrote:\n> I have updated the original version of this patch to encompass the\n> feedback comments obtained. Updates include:\n> 1) Rename option to --no-index for consistency with other commands\n> 2) Improved Documentation text\n> 3) Extension to test scripts to include this option\n>\n> Regarding test scripts I have scoped coverage to ensure correct\n> behaviour with the new option in all standard cases but without\n> duplicating every single corner case.\n>\n> The original patch is at $gmane/233381.\n\nThis commentary, which is not intended as part of the commit message,\nnormally goes below the '---' line after your sign-off just before the\ndiffstat. When the project maintainer applies a patch with git-am,\nsuch commentary is stripped out automatically, otherwise he has to\nstrip it manually. (Alternately, you could use a -->8-- line to\nseparate the above commentary from the commit message.)\n\nOne more minor issue below...\n\n> check-ignore currently shows how .gitignore rules would treat untracked\n> paths. Tracked paths do not generate useful output.  This prevents\n> debugging of why a path became tracked unexpectedly unless that path is\n> first removed from the index with `git rm --cached <path>`.\n>\n> This option (-i, --no-index) simply by-passes the check for the path\n> being in the index and hence allows tracked paths to be checked too.\n>\n> Whilst this behaviour deviates from the characteristics of `git add` and\n> `git status` its use case is unlikely to cause any user confusion.\n>\n> Test scripts are augmented to check this option against the standard\n> ignores to ensure correct behaviour.\n>\n> Signed-off-by: Dave Williams <dave@opensourcesolutions.co.uk>\n> ---\n> diff --git a/t/t0008-ignores.sh b/t/t0008-ignores.sh\n> index c29342d..0ad0534 100755\n> --- a/t/t0008-ignores.sh\n> +++ b/t/t0008-ignores.sh\n> @@ -87,6 +87,9 @@ test_check_ignore () {\n>  # check-ignore --verbose output is the same as normal output except\n>  # for the extra first column.\n>  #\n> +# A parameter is used to determine if the tests are run with the\n> +# normal case (using the index), or with the -i or --no_index option.\n\ns/--no_index/--no-index/\n\n> +#\n>  # Arguments:\n>  #   - (optional) prereqs for this test, e.g. 'SYMLINKS'\n>  #   - test name\n"}]}