threads / patch / 24433

patchAdd --exclude to git-clean.j

Subject: [PATCH] Add --exclude to git-clean.j

## tl;dr

16 messages between Jul 19, 2010 and Sep 23, 2010. Diffs are folded; open one to read it.

replies: 15people: 5as markdown or json

Jared Hance· Jul 19, 2010, 15:50 UTC · lore

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 |    6 +++++-
 builtin/clean.c             |   21 +++++++++++++++++++++
 2 files changed, 26 insertions(+), 1 deletions(-)
Show changes to 2 files +26 −1

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

diff --git a/Documentation/git-clean.txt b/Documentation/git-clean.txt
index a81cb6c..2bf9cf2 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] [-x | -X] [--] <path>...
 
 DESCRIPTION
 -----------
@@ -45,6 +45,10 @@ OPTIONS
 	Be quiet, only report errors, but not the files that are
 	successfully removed.
 
+-e::
+--exclude::
+	Specify special exceptions to not be cleaned. Separate with colon.
+
 -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..aa3eed8 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -13,6 +13,7 @@
 #include "quote.h"
 
 static int force = -1; /* unset */
+static char *excludes;
 
 static const char *const builtin_clean_usage[] = {
 	"git clean [-d] [-f] [-n] [-q] [-x | -X] [--] <paths>...",
@@ -36,6 +37,8 @@ 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 strbuf excludes_buf = STRBUF_INIT;
+	struct strbuf **excludes_split;
 	const char *qname;
 	char *seen = NULL;
 	struct option options[] = {
@@ -44,6 +47,7 @@ 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"),
+		OPT_STRING('e', "exclude", &excludes, "EXCLUDES", "specify files not to clean"),
 		OPT_BOOLEAN('x', NULL, &ignored, "remove ignored files, too"),
 		OPT_BOOLEAN('X', NULL, &ignored_only,
 				"remove only ignored files"),
@@ -81,6 +85,17 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 	if (!ignored)
 		setup_standard_excludes(&dir);
 
+	if (excludes) {
+		strbuf_addstr(&excludes_buf, excludes);
+		excludes_split = strbuf_split(&excludes_buf, ':');
+		for (i = 0; excludes_split[i]; i++) {
+			if (excludes_split[i]->buf[excludes_split[i]->len - 1] == ':') {
+				strbuf_remove(excludes_split[i], excludes_split[i]->len - 1, 1);
+			}
+			add_exclude(excludes_split[i]->buf, "", 0, dir.exclude_list);
+		}
+	}
+
 	pathspec = get_pathspec(prefix, argv);
 
 	fill_directory(&dir, pathspec);
@@ -167,5 +182,11 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 	free(seen);
 
 	strbuf_release(&directory);
+	if (excludes) {
+		strbuf_release(&excludes_buf);
+		for (i = 0; excludes_split[i]; i++) {
+			strbuf_release(excludes_split[i]);
+		}
+	}
 	return (errors != 0);
 }
-- 
1.7.1.1
Jonathan Nieder· Jul 19, 2010, 16:14 UTC · re: Jared Hance · lore

Re: [PATCH] Add --exclude to git-clean.j

Jared Hance wrote:
> 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.
No thoughts on your patch, but have you looked into “git add -N”?
Jonathan
Jared Hance· Jul 19, 2010, 16:21 UTC · re: Jonathan Nieder · lore

Re: [PATCH] Add --exclude to git-clean.j

On Mon, Jul 19, 2010 at 11:14:14AM -0500, Jonathan Nieder wrote: Johnathon wrote:

> No thoughts on your patch, but have you looked into “git add -N”?

That is interesting. However, it doesn't really help for files that you don't intend to add to the index later. "git clean -e" is nice for when you have a file you are using for some temporary purpose.

On another note, I failed getting my title correct, so I sent another patch with the correct title (I think it affects the description of the commit).

Jared Hance· Jul 19, 2010, 16:18 UTC · re: Jared Hance · lore

[PATCH v2] Add --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 |    6 +++++-
 builtin/clean.c             |   21 +++++++++++++++++++++
 2 files changed, 26 insertions(+), 1 deletions(-)
Show changes to 2 files +26 −1

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

diff --git a/Documentation/git-clean.txt b/Documentation/git-clean.txt
index a81cb6c..2bf9cf2 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] [-x | -X] [--] <path>...
 
 DESCRIPTION
 -----------
@@ -45,6 +45,10 @@ OPTIONS
 	Be quiet, only report errors, but not the files that are
 	successfully removed.
 
+-e::
+--exclude::
+	Specify special exceptions to not be cleaned. Separate with colon.
+
 -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..aa3eed8 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -13,6 +13,7 @@
 #include "quote.h"
 
 static int force = -1; /* unset */
+static char *excludes;
 
 static const char *const builtin_clean_usage[] = {
 	"git clean [-d] [-f] [-n] [-q] [-x | -X] [--] <paths>...",
@@ -36,6 +37,8 @@ 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 strbuf excludes_buf = STRBUF_INIT;
+	struct strbuf **excludes_split;
 	const char *qname;
 	char *seen = NULL;
 	struct option options[] = {
@@ -44,6 +47,7 @@ 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"),
+		OPT_STRING('e', "exclude", &excludes, "EXCLUDES", "specify files not to clean"),
 		OPT_BOOLEAN('x', NULL, &ignored, "remove ignored files, too"),
 		OPT_BOOLEAN('X', NULL, &ignored_only,
 				"remove only ignored files"),
@@ -81,6 +85,17 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 	if (!ignored)
 		setup_standard_excludes(&dir);
 
+	if (excludes) {
+		strbuf_addstr(&excludes_buf, excludes);
+		excludes_split = strbuf_split(&excludes_buf, ':');
+		for (i = 0; excludes_split[i]; i++) {
+			if (excludes_split[i]->buf[excludes_split[i]->len - 1] == ':') {
+				strbuf_remove(excludes_split[i], excludes_split[i]->len - 1, 1);
+			}
+			add_exclude(excludes_split[i]->buf, "", 0, dir.exclude_list);
+		}
+	}
+
 	pathspec = get_pathspec(prefix, argv);
 
 	fill_directory(&dir, pathspec);
@@ -167,5 +182,11 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 	free(seen);
 
 	strbuf_release(&directory);
+	if (excludes) {
+		strbuf_release(&excludes_buf);
+		for (i = 0; excludes_split[i]; i++) {
+			strbuf_release(excludes_split[i]);
+		}
+	}
 	return (errors != 0);
 }
-- 
1.7.1.1
Junio C Hamano· Jul 19, 2010, 17:43 UTC · re: Jared Hance · lore

Re: [PATCH v2] Add --exclude to git-clean.

Jared Hance <jaredhance@gmail.com> writes:
Show 10 quoted lines
> diff --git a/Documentation/git-clean.txt b/Documentation/git-clean.txt
> index a81cb6c..2bf9cf2 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] [-x | -X] [--] <path>...
This and ...
Show 8 quoted lines
>  DESCRIPTION
>  -----------
> @@ -45,6 +45,10 @@ OPTIONS
>  	Be quiet, only report errors, but not the files that are
>  	successfully removed.
>  
> +-e::
> +--exclude::

this both look wrong. They do not tell the readers that the option takes a mandatory argument that specifies the "exceptions". Worse yet,

> +	Specify special exceptions to not be cleaned. Separate with colon.
this does not tell _how_ exceptions are specified.
What should each element on the list look like?

Is it a dot-suffix without dot (e.g. "html") or with dot (e.g. ".html")? Or is it a glob (e.g. "*.html")? Or is it a full path relative to the worktree root (e.g. "Documentation/index.html")?

Using colon as an inter-element separator makes sense only if last one is true (i.e. "concrete path, not glob nor suffix"), so an intelligent reader could probably guess what you meant, but you shouldn't make readers guess in the first place.

If on the other hand you wanted to allow specifying the same kind of patterns used in the gitignore files from the command line:

 (1) A list separated with whitespace would be more natural, not a colon;
     and
 (2) I have to wonder why do we give such a command line exclude override
     to begin with.
     (2-a) wouldn't it be easier for the user to add such a local
           configuration to $GIT_DIR/info/exclude once and be done with
           it?
     (2-b) if command-line override has benefit, why is it limited to only
           _exclude_ and not include (iow, additional ignore patterns)?
Jared Hance· Jul 19, 2010, 18:22 UTC · re: Junio C Hamano · lore

Re: [PATCH v2] Add --exclude to git-clean.

On Mon, Jul 19, 2010 at 10:43:43AM -0700, Junio C Hamano wrote:
> this both look wrong.  They do not tell the readers that the option takes
> a mandatory argument that specifies the "exceptions".  Worse yet,
Sorry about that. I will get that fixed.
Show 20 quoted lines
> > +	Specify special exceptions to not be cleaned. Separate with colon.
> 
> this does not tell _how_ exceptions are specified.
> 
> What should each element on the list look like?
> 
> Is it a dot-suffix without dot (e.g. "html") or with dot (e.g. ".html")?
> Or is it a glob (e.g. "*.html")?  Or is it a full path relative to the
> worktree root (e.g. "Documentation/index.html")?
> 
> Using colon as an inter-element separator makes sense only if last one is
> true (i.e. "concrete path, not glob nor suffix"), so an intelligent reader
> could probably guess what you meant, but you shouldn't make readers guess
> in the first place.
> 
> If on the other hand you wanted to allow specifying the same kind of
> patterns used in the gitignore files from the command line:
> 
>  (1) A list separated with whitespace would be more natural, not a colon;
>      and

It is a global (like in the .gitignore file). I will change it to whitespace. At first, I was worried about files with whitespace, and a colon seemed to fit it better (since files don't have colons).

On the other hand, can you think of any character that would fit both a glob and a strict filename (as it allows both)? I had trouble figuring out what to use here.

Show 6 quoted lines
>  (2) I have to wonder why do we give such a command line exclude override
>      to begin with.
> 
>      (2-a) wouldn't it be easier for the user to add such a local
>            configuration to $GIT_DIR/info/exclude once and be done with
>            it?

As I said earlier, its generally useful for files you are only going to have for a few minutes and you don't want to have the clutter up $GIT_DIR/info/exclude with them (since they probably won't ever return).

>      (2-b) if command-line override has benefit, why is it limited to only
>            _exclude_ and not include (iow, additional ignore patterns)?

"git clean && git rm <INCLUDES>" has the same effect as including in the clean.

Jared Hance· Jul 19, 2010, 18:39 UTC · re: Jared Hance · lore

[PATCH v3] Add --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 |    7 ++++++-
 builtin/clean.c             |   21 +++++++++++++++++++++
 2 files changed, 27 insertions(+), 1 deletions(-)
Show changes to 2 files +27 −1

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

diff --git a/Documentation/git-clean.txt b/Documentation/git-clean.txt
index a81cb6c..488e103 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] [-x | -X] [--] <path>...
 
 DESCRIPTION
 -----------
@@ -45,6 +45,11 @@ OPTIONS
 	Be quiet, only report errors, but not the files that are
 	successfully removed.
 
+-e <files>::
+--exclude=<files>::
+	Specify special exceptions to not be cleaned. Separate with a space.
+	Globs, like that in $GIT_DIR/info/excludes, should be used.
+
 -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..b1da923 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -13,6 +13,7 @@
 #include "quote.h"
 
 static int force = -1; /* unset */
+static const char *excludes;
 
 static const char *const builtin_clean_usage[] = {
 	"git clean [-d] [-f] [-n] [-q] [-x | -X] [--] <paths>...",
@@ -36,6 +37,8 @@ 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 strbuf excludes_buf = STRBUF_INIT;
+	struct strbuf **excludes_split = NULL;
 	const char *qname;
 	char *seen = NULL;
 	struct option options[] = {
@@ -44,6 +47,7 @@ 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"),
+		OPT_STRING('e', "exclude", &excludes, "EXCLUDES", "specify files not to clean"),
 		OPT_BOOLEAN('x', NULL, &ignored, "remove ignored files, too"),
 		OPT_BOOLEAN('X', NULL, &ignored_only,
 				"remove only ignored files"),
@@ -81,6 +85,17 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 	if (!ignored)
 		setup_standard_excludes(&dir);
 
+	if (excludes) {
+		strbuf_addstr(&excludes_buf, excludes);
+		excludes_split = strbuf_split(&excludes_buf, ' ');
+		for (i = 0; excludes_split[i]; i++) {
+			if (excludes_split[i]->buf[excludes_split[i]->len - 1] == ' ') {
+				strbuf_remove(excludes_split[i], excludes_split[i]->len - 1, 1);
+			}
+			add_exclude(excludes_split[i]->buf, "", 0, dir.exclude_list);
+		}
+	}
+
 	pathspec = get_pathspec(prefix, argv);
 
 	fill_directory(&dir, pathspec);
@@ -167,5 +182,11 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 	free(seen);
 
 	strbuf_release(&directory);
+	if (excludes) {
+		strbuf_release(&excludes_buf);
+		for (i = 0; excludes_split[i]; i++) {
+			strbuf_release(excludes_split[i]);
+		}
+	}
 	return (errors != 0);
 }
-- 
1.7.1.1
Jared Hance· Jul 20, 2010, 16:28 UTC · re: Jared Hance · lore

[PATCH/RFC v4 0/2] Add -e/--exclude to git clean.

This is the fourth round of patches for git clean -e.
This round introduces a test in t/t7300-clean.sh.

No other changes were added to builtin/clean.c or Documentation/git-clean.txt.

Since this patch seems to be somewhat controversial, I've marked it as PATCH/RFC. I would like some ideas on what to use for separators as well as constructive critism on the Documentation and test.

Jared Hance (2):
  Add --exclude to git-clean.
  Add test for git clean -e.
 Documentation/git-clean.txt |    7 ++++++-
 builtin/clean.c             |   21 +++++++++++++++++++++
 t/t7300-clean.sh            |   16 ++++++++++++++++
 3 files changed, 43 insertions(+), 1 deletions(-)
Jared Hance· Jul 20, 2010, 16:29 UTC · re: Jared Hance · lore

[PATCH/RFC v4 1/2] Add --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 |    7 ++++++-
 builtin/clean.c             |   21 +++++++++++++++++++++
 2 files changed, 27 insertions(+), 1 deletions(-)
Show changes to 2 files +27 −1

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

diff --git a/Documentation/git-clean.txt b/Documentation/git-clean.txt
index a81cb6c..488e103 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] [-x | -X] [--] <path>...
 
 DESCRIPTION
 -----------
@@ -45,6 +45,11 @@ OPTIONS
 	Be quiet, only report errors, but not the files that are
 	successfully removed.
 
+-e <files>::
+--exclude=<files>::
+	Specify special exceptions to not be cleaned. Separate with a space.
+	Globs, like that in $GIT_DIR/info/excludes, should be used.
+
 -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..b1da923 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -13,6 +13,7 @@
 #include "quote.h"
 
 static int force = -1; /* unset */
+static const char *excludes;
 
 static const char *const builtin_clean_usage[] = {
 	"git clean [-d] [-f] [-n] [-q] [-x | -X] [--] <paths>...",
@@ -36,6 +37,8 @@ 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 strbuf excludes_buf = STRBUF_INIT;
+	struct strbuf **excludes_split = NULL;
 	const char *qname;
 	char *seen = NULL;
 	struct option options[] = {
@@ -44,6 +47,7 @@ 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"),
+		OPT_STRING('e', "exclude", &excludes, "EXCLUDES", "specify files not to clean"),
 		OPT_BOOLEAN('x', NULL, &ignored, "remove ignored files, too"),
 		OPT_BOOLEAN('X', NULL, &ignored_only,
 				"remove only ignored files"),
@@ -81,6 +85,17 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 	if (!ignored)
 		setup_standard_excludes(&dir);
 
+	if (excludes) {
+		strbuf_addstr(&excludes_buf, excludes);
+		excludes_split = strbuf_split(&excludes_buf, ' ');
+		for (i = 0; excludes_split[i]; i++) {
+			if (excludes_split[i]->buf[excludes_split[i]->len - 1] == ' ') {
+				strbuf_remove(excludes_split[i], excludes_split[i]->len - 1, 1);
+			}
+			add_exclude(excludes_split[i]->buf, "", 0, dir.exclude_list);
+		}
+	}
+
 	pathspec = get_pathspec(prefix, argv);
 
 	fill_directory(&dir, pathspec);
@@ -167,5 +182,11 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 	free(seen);
 
 	strbuf_release(&directory);
+	if (excludes) {
+		strbuf_release(&excludes_buf);
+		for (i = 0; excludes_split[i]; i++) {
+			strbuf_release(excludes_split[i]);
+		}
+	}
 	return (errors != 0);
 }
-- 
1.7.1.1
Jared Hance· Jul 20, 2010, 16:30 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..c6df26d 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 2" &&
+		test -e 1 &&
+		test -e 2 &&
+		! (test -e 3) &&
+		test -e known
+	)
+'
+
 test_done
-- 
1.7.1.1
Aaron Crane· Jul 20, 2010, 17:03 UTC · re: Jared Hance · lore

Re: [PATCH/RFC v4 0/2] Add -e/--exclude to git clean.

Jared Hance <jaredhance@gmail.com> wrote:
> This is the fourth round of patches for git clean -e.
> Since this patch seems to be somewhat controversial, I've marked it as
> PATCH/RFC. I would like some ideas on what to use for separators

Rather than stuffing multiple exclusions into a single option, how about requiring one -e option per exclusion?

git clean -e foo -e bar
-- 
Aaron Crane ** http://aaroncrane.co.uk/
Jared Hance· Jul 20, 2010, 17:13 UTC · re: Aaron Crane · lore

Re: [PATCH/RFC v4 0/2] Add -e/--exclude to git clean.

On Tue, Jul 20, 2010 at 06:03:36PM +0100, Aaron Crane wrote:
> Rather than stuffing multiple exclusions into a single option, how
> about requiring one -e option per exclusion?
> 
> git clean -e foo -e bar

I actually considered that - However, Documentation/technical/api-parse-options.txt does not document how to do this type of thing with the the parse options api. I will look into the code for some examples to see if I can figure it out.

Junio C Hamano· Jul 20, 2010, 18:02 UTC · re: Aaron Crane · lore

Re: [PATCH/RFC v4 0/2] Add -e/--exclude to git clean.

Aaron Crane <git@aaroncrane.co.uk> writes:
Show 9 quoted lines
> Jared Hance <jaredhance@gmail.com> wrote:
>> This is the fourth round of patches for git clean -e.
>> Since this patch seems to be somewhat controversial, I've marked it as
>> PATCH/RFC. I would like some ideas on what to use for separators
>
> Rather than stuffing multiple exclusions into a single option, how
> about requiring one -e option per exclusion?
>
> git clean -e foo -e bar
I find it a lot saner.

Sorry, Jared, I should have thought of it and suggested it during the first review round.

Junio C Hamano· Jul 20, 2010, 18:23 UTC · re: Junio C Hamano · lore

Re: [PATCH/RFC v4 0/2] Add -e/--exclude to git clean.

Junio C Hamano <gitster@pobox.com> writes:
Show 16 quoted lines
> Aaron Crane <git@aaroncrane.co.uk> writes:
>
>> Jared Hance <jaredhance@gmail.com> wrote:
>>> This is the fourth round of patches for git clean -e.
>>> Since this patch seems to be somewhat controversial, I've marked it as
>>> PATCH/RFC. I would like some ideas on what to use for separators
>>
>> Rather than stuffing multiple exclusions into a single option, how
>> about requiring one -e option per exclusion?
>>
>> git clean -e foo -e bar
>
> I find it a lot saner.
>
> Sorry, Jared, I should have thought of it and suggested it during the
> first review round.
The fix-up should look something like this, on top of your patch.

Note that I did this on top of applying your patch to 'maint', and you may need to adjust the parameter order of string-list functions if you want to forward port it to 'master'.

Untested, of course ;-)
 Documentation/git-clean.txt |   11 ++++++-----
 builtin/clean.c             |   36 +++++++++++++++---------------------
 2 files changed, 21 insertions(+), 26 deletions(-)
Show changes to 2 files +21 −25

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

diff --git a/Documentation/git-clean.txt b/Documentation/git-clean.txt
index 488e103..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] [-e] [-x | -X] [--] <path>...
+'git clean' [-d] [-f] [-n] [-q] [-e <pattern>] [-x | -X] [--] <path>...
 
 DESCRIPTION
 -----------
@@ -45,10 +45,11 @@ OPTIONS
 	Be quiet, only report errors, but not the files that are
 	successfully removed.
 
--e <files>::
---exclude=<files>::
-	Specify special exceptions to not be cleaned. Separate with a space.
-	Globs, like that in $GIT_DIR/info/excludes, should be used.
+-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
diff --git a/builtin/clean.c b/builtin/clean.c
index b1da923..58c9c06 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -10,13 +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 *excludes;
 
 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
 };
 
@@ -27,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 = opt->value;
+	string_list_append(arg, exclude_list);
+	return 0;
+}
+
 int cmd_clean(int argc, const char **argv, const char *prefix)
 {
 	int i;
@@ -37,8 +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 strbuf excludes_buf = STRBUF_INIT;
-	struct strbuf **excludes_split = NULL;
+	struct string_list exclude_list = { NULL, 0, 0, 0 };
 	const char *qname;
 	char *seen = NULL;
 	struct option options[] = {
@@ -47,7 +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"),
-		OPT_STRING('e', "exclude", &excludes, "EXCLUDES", "specify files not to clean"),
+		{ 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"),
@@ -85,16 +92,8 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 	if (!ignored)
 		setup_standard_excludes(&dir);
 
-	if (excludes) {
-		strbuf_addstr(&excludes_buf, excludes);
-		excludes_split = strbuf_split(&excludes_buf, ' ');
-		for (i = 0; excludes_split[i]; i++) {
-			if (excludes_split[i]->buf[excludes_split[i]->len - 1] == ' ') {
-				strbuf_remove(excludes_split[i], excludes_split[i]->len - 1, 1);
-			}
-			add_exclude(excludes_split[i]->buf, "", 0, dir.exclude_list);
-		}
-	}
+	for (i = 0; i < exclude_list.nr; i++)
+		add_exclude(exclude_list.items[i].string, "", 0, dir.exclude_list);
 
 	pathspec = get_pathspec(prefix, argv);
 
@@ -182,11 +181,6 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 	free(seen);
 
 	strbuf_release(&directory);
-	if (excludes) {
-		strbuf_release(&excludes_buf);
-		for (i = 0; excludes_split[i]; i++) {
-			strbuf_release(excludes_split[i]);
-		}
-	}
+	string_list_clear(&exclude_list, 0);
 	return (errors != 0);
 }
Jared Hance· Jul 20, 2010, 19:11 UTC · re: Junio C Hamano · lore

Re: [PATCH/RFC v4 0/2] Add -e/--exclude to git clean.

On Tue, Jul 20, 2010 at 11:23:22AM -0700, Junio C Hamano wrote:
Show 7 quoted lines
> The fix-up should look something like this, on top of your patch.
> 
> Note that I did this on top of applying your patch to 'maint', and you may
> need to adjust the parameter order of string-list functions if you want to
> forward port it to 'master'.
> 
> Untested, of course ;-)

Okay. Do you want to me to create a rebased version to combine this and my first patch?

Louis Strous· Sep 23, 2010, 09:05 UTC · re: Jared Hance · lore

Re: [PATCH/RFC v4 0/2] Add -e/--exclude to git clean.

The git clean -e option is more useful than just for stuff that you plan to bring under git control later. It also allows to retain per-user configurations of external tools when using git clean to remove all build results and intermediate files. This leads to the enhancement request described below.

Most IDEs (integrated development environments) allow the user to configure various display and debugger options, and store those options in some configuration file. Such user option files should not be under git control in a multi-user environment, because then all users are forced to use the same options. Yet these user option files should not be deleted when the rest of the untracked files are deleted (through git clean), otherwise the user options are lost.

git clean -x -d -f -e "pattern" removes all untracked files except those matching the pattern. However, it is cumbersome to specify these patterns every time. It would be more convenient if git clean would read such patterns from a file similar to .gitignore (maybe .gitignoreclean?). Then that file itself could be put under git control and shared with the other developers.

I request implementation of this feature.
Best regards,
Louis Strous

← back to recent threads