threads / patch / 24448

patch, 2 partsAdd -e/--exclude to git-clean.

Subject: [PATCH 0/2] Add -e/--exclude to git-clean.

## tl;dr

7 messages between Jul 20, 2010 and Jul 20, 2010. Diffs are folded; open one to read it.

replies: 6people: 2as markdown or json

Jared Hance· Jul 20, 2010, 19:35 UTC · lore
Changes:
    - Use -e multiple times instead of using a separator

I'm starting a new thread since the code change is rather major. I've incorporated Julio's changes, touched up on them a bit, and updated the test suite so that it uses multiple instances of -e rather than using a separator in them.

Thanks to Julio and all that helped.
Jared Hance (2):
  Add -e/--exclude to git-clean.
  Add test for git clean -e.
 Documentation/git-clean.txt |    8 +++++++-
 builtin/clean.c             |   17 ++++++++++++++++-
 t/t7300-clean.sh            |   16 ++++++++++++++++
 3 files changed, 39 insertions(+), 2 deletions(-)
Jared Hance· Jul 20, 2010, 19:35 UTC · re: Jared Hance · lore

[PATCH 1/2] Add -e/--exclude to git-clean.

With the -e/--exclude option for git-clean, a user can specify files that they haven't yet told git about, but either need for a short amount of time or plan to tell git about them later. This allows one to still use git-clean while these files are around without losing data.

Signed-off-by: Jared Hance <jaredhance@gmail.com>
---
 Documentation/git-clean.txt |    8 +++++++-
 builtin/clean.c             |   17 ++++++++++++++++-
 2 files changed, 23 insertions(+), 2 deletions(-)
Show changes to 2 files +23 −2

Documentation/git-clean.txt, builtin/clean.c

diff --git a/Documentation/git-clean.txt b/Documentation/git-clean.txt
index a81cb6c..60e38e6 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] [-n] [-q] [-x | -X] [--] <path>...
+'git clean' [-d] [-f] [-n] [-q] [-e <pattern>] [-x | -X] [--] <path>...
 
 DESCRIPTION
 -----------
@@ -45,6 +45,12 @@ OPTIONS
 	Be quiet, only report errors, but not the files that are
 	successfully removed.
 
+-e <pattern>::
+--exclude=<pattern>::
+	Specify special exceptions to not be cleaned.  Each <pattern> is
+	the same form as in $GIT_DIR/info/excludes and this option can be
+	given multiple times.
+
 -x::
 	Don't use the ignore rules.  This allows removing all untracked
 	files, including build products.  This can be used (possibly in
diff --git a/builtin/clean.c b/builtin/clean.c
index fac64e6..841ac26 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -10,12 +10,13 @@
 #include "cache.h"
 #include "dir.h"
 #include "parse-options.h"
+#include "string-list.h"
 #include "quote.h"
 
 static int force = -1; /* unset */
 
 static const char *const builtin_clean_usage[] = {
-	"git clean [-d] [-f] [-n] [-q] [-x | -X] [--] <paths>...",
+	"git clean [-d] [-f] [-n] [-q] [-e <pattern>] [-x | -X] [--] <paths>...",
 	NULL
 };
 
@@ -26,6 +27,13 @@ static int git_clean_config(const char *var, const char *value, void *cb)
 	return git_default_config(var, value, cb);
 }
 
+static int exclude_cb(const struct option *opt, const char *arg, int unset)
+{
+	struct string_list *exclude_list = (struct string_list *)opt->value;
+	string_list_append(exclude_list, arg);
+	return 0;
+}
+
 int cmd_clean(int argc, const char **argv, const char *prefix)
 {
 	int i;
@@ -36,6 +44,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 	struct dir_struct dir;
 	static const char **pathspec;
 	struct strbuf buf = STRBUF_INIT;
+	struct string_list exclude_list = { NULL, 0, 0, 0 };
 	const char *qname;
 	char *seen = NULL;
 	struct option options[] = {
@@ -44,6 +53,8 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 		OPT_BOOLEAN('f', "force", &force, "force"),
 		OPT_BOOLEAN('d', NULL, &remove_directories,
 				"remove whole directories"),
+		{ OPTION_CALLBACK, 'e', "exclude", &exclude_list, "pattern",
+		  "exclude <pattern>", PARSE_OPT_NONEG, exclude_cb },
 		OPT_BOOLEAN('x', NULL, &ignored, "remove ignored files, too"),
 		OPT_BOOLEAN('X', NULL, &ignored_only,
 				"remove only ignored files"),
@@ -81,6 +92,9 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 	if (!ignored)
 		setup_standard_excludes(&dir);
 
+	for (i = 0; i < exclude_list.nr; i++)
+		add_exclude(exclude_list.items[i].string, "", 0, dir.exclude_list);
+
 	pathspec = get_pathspec(prefix, argv);
 
 	fill_directory(&dir, pathspec);
@@ -167,5 +181,6 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 	free(seen);
 
 	strbuf_release(&directory);
+	string_list_clear(&exclude_list, 0);
 	return (errors != 0);
 }
-- 
1.7.1.1
Junio C Hamano· Jul 20, 2010, 20:27 UTC · re: Jared Hance · lore

Re: [PATCH 1/2] Add -e/--exclude to git-clean.

Jared Hance <jaredhance@gmail.com> writes:
Show 6 quoted lines
> With the -e/--exclude option for git-clean, a user can specify files
> that they haven't yet told git about, but either need for a short amount
> of time or plan to tell git about them later. This allows one to still
> use git-clean while these files are around without losing data.
>
> Signed-off-by: Jared Hance <jaredhance@gmail.com>
Thanks.
> +static int exclude_cb(const struct option *opt, const char *arg, int unset)
> +{
> +	struct string_list *exclude_list = (struct string_list *)opt->value;
Unnecessary cast, as opt->value is of type (void *).
Show 5 quoted lines
> @@ -36,6 +44,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
>  	struct dir_struct dir;
>  	static const char **pathspec;
>  	struct strbuf buf = STRBUF_INIT;
> +	struct string_list exclude_list = { NULL, 0, 0, 0 };

Mental note to myself. We should convert this to use STRING_LIST_INIT after the next release when Thiago's patch graduates to 'master'.

Jared Hance· Jul 20, 2010, 19:36 UTC · re: Jared Hance · lore

[PATCH 2/2] Add test for git clean -e.

Signed-off-by: Jared Hance <jaredhance@gmail.com>
---
 t/t7300-clean.sh |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)
Show changes to t/t7300-clean.sh +16 −0
diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh
index 7d8ed68..3a43571 100755
--- a/t/t7300-clean.sh
+++ b/t/t7300-clean.sh
@@ -438,4 +438,20 @@ test_expect_success 'force removal of nested git work tree' '
 	! test -d bar
 '
 
+test_expect_success 'git clean -e' '
+	rm -fr repo &&
+	mkdir repo &&
+	(
+		cd repo &&
+		git init &&
+		touch 1 2 3 known &&
+		git add known &&
+		git clean -f -e 1 -e 2 &&
+		test -e 1 &&
+		test -e 2 &&
+		! (test -e 3) &&
+		test -e known
+	)
+'
+
 test_done
-- 
1.7.1.1
Junio C Hamano· Jul 20, 2010, 20:34 UTC · re: Jared Hance · lore

Re: [PATCH 2/2] Add test for git clean -e.

Jared Hance <jaredhance@gmail.com> writes:
Show 28 quoted lines
> Signed-off-by: Jared Hance <jaredhance@gmail.com>
> ---
>  t/t7300-clean.sh |   16 ++++++++++++++++
>  1 files changed, 16 insertions(+), 0 deletions(-)
>
> diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh
> index 7d8ed68..3a43571 100755
> --- a/t/t7300-clean.sh
> +++ b/t/t7300-clean.sh
> @@ -438,4 +438,20 @@ test_expect_success 'force removal of nested git work tree' '
>  	! test -d bar
>  '
>  
> +test_expect_success 'git clean -e' '
> +	rm -fr repo &&
> +	mkdir repo &&
> +	(
> +		cd repo &&
> +		git init &&
> +		touch 1 2 3 known &&
> +		git add known &&
> +		git clean -f -e 1 -e 2 &&
> +		test -e 1 &&
> +		test -e 2 &&
> +		! (test -e 3) &&
> +		test -e known
> +	)
> +'

This is a good start but it doesn't seem to test possible interactions with entries in .gitignore file(s) in the working tree. Do we care?

What should happen when a path "path":
 (1) is marked to be ignored in .gitignore and -e "path" is also given;
 (2) is marked not to be ignored (i.e. "!path") in .gitignore but -e
    "path" is given;
 (3) is marked to be ignored in .gitignore but -e "!path" is given;
 (4) is marked not to be ignored in .gitignore and -e "!path" is also
     given;
 (5) perhaps other combinations like "!path" in a/.gitignore, and -e "a/path"
     from the command line.
What does the code actually do?
Jared Hance· Jul 20, 2010, 23:35 UTC · re: Junio C Hamano · lore

Re: [PATCH 2/2] Add test for git clean -e.

On Tue, Jul 20, 2010 at 01:34:21PM -0700, Junio C Hamano wrote:
> This is a good start but it doesn't seem to test possible interactions
> with entries in .gitignore file(s) in the working tree.  Do we care?
Honestly, I'm not sure that we do care.
> 
> What should happen when a path "path":
> 
>  (1) is marked to be ignored in .gitignore and -e "path" is also given;
It is excluded.
>  (2) is marked not to be ignored (i.e. "!path") in .gitignore but -e
>     "path" is given;

I think it would be good for "!path" to cause -e path to have no effect because of globbing issues.

Currently, -e works as normal.
>  (3) is marked to be ignored in .gitignore but -e "!path" is given;

Again, I'm not sure and am definately open to debate here. Personally, I think that -e "!path" is completely abusing the use of -e, because it is using -e to NOT exclude something.

Currently, -e has no effect.
>  (4) is marked not to be ignored in .gitignore and -e "!path" is also
>      given;

No effect happens. Again, this is abuse of -e in my opinion, as its goal to allow one to do a clean and save one or two files.

>  (5) perhaps other combinations like "!path" in a/.gitignore, and -e "a/path"
>      from the command line.
Judging by (2), -e will work as normal.

← back to recent threads