Re: [PATCH v2 2/2] clean: new option --exclude-from

2015-12-07 Thread Eric Sunshine
In addition to Peff's and Junio's review comments...

On Sun, Dec 6, 2015 at 9:58 AM, James  wrote:
> From: James Rouzier 
>
> Specify a file to read for exclude patterns.

Missing Signed-off-by:.

> ---
> diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh
> @@ -628,6 +628,66 @@ test_expect_success 'git clean -e' '
> +test_expect_success 'git clean --exclude-from' '
> +   rm -fr repo &&
> +   mkdir repo &&
> +   cd repo &&

See my review comments for patch 1/2 as to why you want to wrap 'cd'
and remaining statements in a subshell.

> +   git init &&
> +   touch known 1 2 3 &&

Likewise, use '>' rather than 'touch' to create empty files when the
timestamp isn't significant.

   >1 &&
   >2 &&
   >3 &&

> +   git add known &&
> +   cat >.git/clean-exclude <<-\EOF &&
> +   1
> +   2
> +   EOF
> +   git clean -f --exclude-from=.git/clean-exclude &&
> +   test_path_is_file 1 &&
> +   test_path_is_file 2 &&
> +   test_path_is_missing 3 &&
> +   test_path_is_file known
> +'
> +
> +test_expect_success 'git clean -e --exclude-from' '
> +   rm -fr repo &&
> +   mkdir repo &&
> +   cd repo &&
> +   git init &&
> +   touch known 1 2 3 &&
> +   git add known &&
> +   echo 1 >> .git/clean-exclude &&
> +   git clean -f -e 2 --exclude-from=.git/clean-exclude &&
> +   test_path_is_file 1 &&
> +   test_path_is_file 2 &&
> +   test_path_is_missing 3 &&
> +   test_path_is_file known
> +'
> +
> +test_expect_success 'git clean --exclude-from --exclude-from' '
> +   rm -fr repo &&
> +   mkdir repo &&
> +   git init &&
> +   touch known 1 2 3 &&
> +   git add known &&
> +   cat >.git/clean-exclude1 <<-\EOF &&
> +   1
> +   EOF
> +   cat >.git/clean-exclude2 <<-\EOF &&
> +   2
> +   EOF

Creation of these single-line files probably would be more readable
using 'echo', as you do in the test just above (for
.git/clean-exclude):

echo 1 >.git/clean-exclude1 &&
echo 2 >.git/clean-exclude2 &&

> +   git clean -f --exclude-from=.git/clean-exclude1 
> --exclude-from=.git/clean-exclude2 &&
> +   test_path_is_file 1 &&
> +   test_path_is_file 2 &&
> +   test_path_is_missing 3 &&
> +   test_path_is_file known
> +'
> +
> +test_expect_success 'git clean --exclude-from=BADFILE' '
> +   rm -fr repo &&
> +   mkdir repo &&
> +   cd repo &&
> +   git init &&
> +   test_expect_code 128 git clean -f 
> --exclude-from=.git/clean-exclude-not-there
> +'
> +
>  test_expect_success SANITY 'git clean -d with an unreadable empty directory' 
> '
> mkdir foo &&
> chmod a= foo &&
> --
> 2.3.6
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 2/2] clean: new option --exclude-from

2015-12-07 Thread Junio C Hamano
James  writes:

> +static int exclude_from_cb(const struct option *opt,
> +  const char *arg, int unset)
> +{
> + struct dir_struct *dir = opt->value;
> + add_excludes_from_file(dir, arg);

I suspect this is wrong.  add_excludes_from_file() creates a
new excludes_list that is separate from the command line level and
pushes that down to the exclude stack.  You'd instead need to add
each line of the input at the same EXC_CMDL level like -e 
option does from the command line, I would think.

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 2/2] clean: new option --exclude-from

2015-12-07 Thread Jeff King
On Sun, Dec 06, 2015 at 09:58:26AM -0500, James wrote:

> +test_expect_success 'git clean -e --exclude-from' '
> + rm -fr repo &&
> + mkdir repo &&
> + cd repo &&
> + git init &&
> + touch known 1 2 3 &&
> + git add known &&
> + echo 1 >> .git/clean-exclude &&
> + git clean -f -e 2 --exclude-from=.git/clean-exclude &&
> + test_path_is_file 1 &&
> + test_path_is_file 2 &&
> + test_path_is_missing 3 &&
> + test_path_is_file known
> +'

This checks that we exclude the union of the "-e" and "--exclude-from"
parameters. What happens if one excludes a path and the other negates
the exclusion? How is the precedence handled? Is it based on order on
the command-line, or something else?

I do not have much of a preference myself, but it probably makes sense
to document and test it.

> +test_expect_success 'git clean --exclude-from --exclude-from' '
> + rm -fr repo &&
> + mkdir repo &&
> + git init &&
> + touch known 1 2 3 &&
> + git add known &&
> + cat >.git/clean-exclude1 <<-\EOF &&
> + 1
> + EOF
> + cat >.git/clean-exclude2 <<-\EOF &&
> + 2
> + EOF
> + git clean -f --exclude-from=.git/clean-exclude1 
> --exclude-from=.git/clean-exclude2 &&
> + test_path_is_file 1 &&
> + test_path_is_file 2 &&
> + test_path_is_missing 3 &&
> + test_path_is_file known
> +'

Ditto here (as the same "type", the only precedence that would make any
sense is command-line order here).

> +test_expect_success 'git clean --exclude-from=BADFILE' '
> + rm -fr repo &&
> + mkdir repo &&
> + cd repo &&
> + git init &&
> + test_expect_code 128 git clean -f 
> --exclude-from=.git/clean-exclude-not-there
> +'

Do you actually care about the 128 here, or is just "it should exit with
failure"? If the latter, we usually use test_must_fail.

-Peff
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 2/2] clean: new option --exclude-from

2015-12-06 Thread James
From: James Rouzier 

Specify a file to read for exclude patterns.
---
 Documentation/git-clean.txt |  5 +++-
 builtin/clean.c | 15 ++--
 t/t7300-clean.sh| 60 +
 3 files changed, 77 insertions(+), 3 deletions(-)

diff --git a/Documentation/git-clean.txt b/Documentation/git-clean.txt
index 641681f..ef5dc41 100644
--- a/Documentation/git-clean.txt
+++ b/Documentation/git-clean.txt
@@ -8,7 +8,7 @@ git-clean - Remove untracked files from the working tree
 SYNOPSIS
 
 [verse]
-'git clean' [-d] [-f] [-i] [-n] [-q] [-e ] [-x | -X] [--] ...
+'git clean' [-d] [-f] [-i] [-n] [-q] [-e ] [--exclude-from=] 
[-x | -X] [--] ...
 
 DESCRIPTION
 ---
@@ -61,6 +61,9 @@ OPTIONS
$GIT_DIR/info/exclude, also consider these patterns to be in the
set of the ignore rules in effect.
 
+--exclude-from=::
+   Read exclude patterns from ; 1 per line.
+
 -x::
Don't use the standard ignore rules read from .gitignore (per
directory) and $GIT_DIR/info/exclude, but do still use the ignore
diff --git a/builtin/clean.c b/builtin/clean.c
index d7acb94..8e652f8 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -22,7 +22,7 @@ static struct string_list del_list = STRING_LIST_INIT_DUP;
 static unsigned int colopts;
 
 static const char *const builtin_clean_usage[] = {
-   N_("git clean [-d] [-f] [-i] [-n] [-q] [-e ] [-x | -X] [--] 
..."),
+   N_("git clean [-d] [-f] [-i] [-n] [-q] [-e ] 
[--exclude-from=] [-x | -X] [--] ..."),
NULL
 };
 
@@ -875,6 +875,14 @@ static void interactive_main_loop(void)
}
 }
 
+static int exclude_from_cb(const struct option *opt,
+const char *arg, int unset)
+{
+   struct dir_struct *dir = opt->value;
+   add_excludes_from_file(dir, arg);
+   return 0;
+}
+
 int cmd_clean(int argc, const char **argv, const char *prefix)
 {
int i, res;
@@ -898,12 +906,16 @@ int cmd_clean(int argc, const char **argv, const char 
*prefix)
N_("remove whole directories")),
{ OPTION_CALLBACK, 'e', "exclude", &exclude_list, N_("pattern"),
  N_("add  to ignore rules"), PARSE_OPT_NONEG, 
exclude_cb },
+   { OPTION_CALLBACK, 0, "exclude-from", &dir, N_("file"),
+   N_("read exclude patterns from "),
+   0, exclude_from_cb },
OPT_BOOL('x', NULL, &ignored, N_("remove ignored files, too")),
OPT_BOOL('X', NULL, &ignored_only,
N_("remove only ignored files")),
OPT_END()
};
 
+   memset(&dir, 0, sizeof(dir));
git_config(git_clean_config, NULL);
if (force < 0)
force = 0;
@@ -913,7 +925,6 @@ int cmd_clean(int argc, const char **argv, const char 
*prefix)
argc = parse_options(argc, argv, prefix, options, builtin_clean_usage,
 0);
 
-   memset(&dir, 0, sizeof(dir));
if (ignored_only)
dir.flags |= DIR_SHOW_IGNORED;
 
diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh
index d555bb6..c6bfdda 100755
--- a/t/t7300-clean.sh
+++ b/t/t7300-clean.sh
@@ -628,6 +628,66 @@ test_expect_success 'git clean -e' '
test_path_is_file known
 '
 
+test_expect_success 'git clean --exclude-from' '
+   rm -fr repo &&
+   mkdir repo &&
+   cd repo &&
+   git init &&
+   touch known 1 2 3 &&
+   git add known &&
+   cat >.git/clean-exclude <<-\EOF &&
+   1
+   2
+   EOF
+   git clean -f --exclude-from=.git/clean-exclude &&
+   test_path_is_file 1 &&
+   test_path_is_file 2 &&
+   test_path_is_missing 3 &&
+   test_path_is_file known
+'
+
+test_expect_success 'git clean -e --exclude-from' '
+   rm -fr repo &&
+   mkdir repo &&
+   cd repo &&
+   git init &&
+   touch known 1 2 3 &&
+   git add known &&
+   echo 1 >> .git/clean-exclude &&
+   git clean -f -e 2 --exclude-from=.git/clean-exclude &&
+   test_path_is_file 1 &&
+   test_path_is_file 2 &&
+   test_path_is_missing 3 &&
+   test_path_is_file known
+'
+
+test_expect_success 'git clean --exclude-from --exclude-from' '
+   rm -fr repo &&
+   mkdir repo &&
+   git init &&
+   touch known 1 2 3 &&
+   git add known &&
+   cat >.git/clean-exclude1 <<-\EOF &&
+   1
+   EOF
+   cat >.git/clean-exclude2 <<-\EOF &&
+   2
+   EOF
+   git clean -f --exclude-from=.git/clean-exclude1 
--exclude-from=.git/clean-exclude2 &&
+   test_path_is_file 1 &&
+   test_path_is_file 2 &&
+   test_path_is_missing 3 &&
+   test_path_is_file known
+'
+
+test_expect_success 'git clean --exclude-from=BADFILE' '
+   rm -fr repo &&
+   mkdir repo &&
+   cd repo &&
+   git init &&
+   test_expect_code 128 git clean -f 
--exclude-from=.git/clean-exclude-not-th