{"thread":{"id":"24448","subject":"[PATCH 0/2] Add -e/--exclude to git-clean.","startedAt":"2010-07-20T19:35:37Z","lastAt":"2010-07-20T23:35:54Z","messageCount":7,"participants":["Jared Hance","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"145892","messageId":"cover.1279654370.git.jaredhance@gmail.com","threadId":"24448","inReplyTo":null,"subject":"[PATCH 0/2] Add -e/--exclude to git-clean.","fromName":"Jared Hance","fromEmail":"jaredhance@gmail.com","sentAt":"2010-07-20T19:35:37Z","receivedAt":"2010-07-20T19:35:37Z","isPatch":true,"sender":{"key":"jaredhance@gmail.com","avatar":"https://avatars.githubusercontent.com/u/170192?v=4"},"body":"Changes:\n    - Use -e multiple times instead of using a separator\n\nI'm starting a new thread since the code change is rather major. I've\nincorporated Julio's changes, touched up on them a bit, and updated\nthe test suite so that it uses multiple instances of -e rather than \nusing a separator in them.\n\nThanks to Julio and all that helped.\n\nJared Hance (2):\n  Add -e/--exclude to git-clean.\n  Add test for git clean -e.\n\n Documentation/git-clean.txt |    8 +++++++-\n builtin/clean.c             |   17 ++++++++++++++++-\n t/t7300-clean.sh            |   16 ++++++++++++++++\n 3 files changed, 39 insertions(+), 2 deletions(-)\n"},{"id":"145893","messageId":"8f454efeb3aa4acd0e0c420b197d0269dc53db34.1279654370.git.jaredhance@gmail.com","threadId":"24448","inReplyTo":"cover.1279654370.git.jaredhance@gmail.com","subject":"[PATCH 1/2] Add -e/--exclude to git-clean.","fromName":"Jared Hance","fromEmail":"jaredhance@gmail.com","sentAt":"2010-07-20T19:35:56Z","receivedAt":"2010-07-20T19:35:56Z","isPatch":true,"sender":{"key":"jaredhance@gmail.com","avatar":"https://avatars.githubusercontent.com/u/170192?v=4"},"body":"With the -e/--exclude option for git-clean, a user can specify files\nthat they haven't yet told git about, but either need for a short amount\nof time or plan to tell git about them later. This allows one to still\nuse git-clean while these files are around without losing data.\n\nSigned-off-by: Jared Hance <jaredhance@gmail.com>\n---\n Documentation/git-clean.txt |    8 +++++++-\n builtin/clean.c             |   17 ++++++++++++++++-\n 2 files changed, 23 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-clean.txt b/Documentation/git-clean.txt\nindex a81cb6c..60e38e6 100644\n--- a/Documentation/git-clean.txt\n+++ b/Documentation/git-clean.txt\n@@ -8,7 +8,7 @@ git-clean - Remove untracked files from the working tree\n SYNOPSIS\n --------\n [verse]\n-'git clean' [-d] [-f] [-n] [-q] [-x | -X] [--] <path>...\n+'git clean' [-d] [-f] [-n] [-q] [-e <pattern>] [-x | -X] [--] <path>...\n \n DESCRIPTION\n -----------\n@@ -45,6 +45,12 @@ OPTIONS\n \tBe quiet, only report errors, but not the files that are\n \tsuccessfully removed.\n \n+-e <pattern>::\n+--exclude=<pattern>::\n+\tSpecify special exceptions to not be cleaned.  Each <pattern> is\n+\tthe same form as in $GIT_DIR/info/excludes and this option can be\n+\tgiven multiple times.\n+\n -x::\n \tDon't use the ignore rules.  This allows removing all untracked\n \tfiles, including build products.  This can be used (possibly in\ndiff --git a/builtin/clean.c b/builtin/clean.c\nindex fac64e6..841ac26 100644\n--- a/builtin/clean.c\n+++ b/builtin/clean.c\n@@ -10,12 +10,13 @@\n #include \"cache.h\"\n #include \"dir.h\"\n #include \"parse-options.h\"\n+#include \"string-list.h\"\n #include \"quote.h\"\n \n static int force = -1; /* unset */\n \n static const char *const builtin_clean_usage[] = {\n-\t\"git clean [-d] [-f] [-n] [-q] [-x | -X] [--] <paths>...\",\n+\t\"git clean [-d] [-f] [-n] [-q] [-e <pattern>] [-x | -X] [--] <paths>...\",\n \tNULL\n };\n \n@@ -26,6 +27,13 @@ static int git_clean_config(const char *var, const char *value, void *cb)\n \treturn git_default_config(var, value, cb);\n }\n \n+static int exclude_cb(const struct option *opt, const char *arg, int unset)\n+{\n+\tstruct string_list *exclude_list = (struct string_list *)opt->value;\n+\tstring_list_append(exclude_list, arg);\n+\treturn 0;\n+}\n+\n int cmd_clean(int argc, const char **argv, const char *prefix)\n {\n \tint i;\n@@ -36,6 +44,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)\n \tstruct dir_struct dir;\n \tstatic const char **pathspec;\n \tstruct strbuf buf = STRBUF_INIT;\n+\tstruct string_list exclude_list = { NULL, 0, 0, 0 };\n \tconst char *qname;\n \tchar *seen = NULL;\n \tstruct option options[] = {\n@@ -44,6 +53,8 @@ int cmd_clean(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOLEAN('f', \"force\", &force, \"force\"),\n \t\tOPT_BOOLEAN('d', NULL, &remove_directories,\n \t\t\t\t\"remove whole directories\"),\n+\t\t{ OPTION_CALLBACK, 'e', \"exclude\", &exclude_list, \"pattern\",\n+\t\t  \"exclude <pattern>\", PARSE_OPT_NONEG, exclude_cb },\n \t\tOPT_BOOLEAN('x', NULL, &ignored, \"remove ignored files, too\"),\n \t\tOPT_BOOLEAN('X', NULL, &ignored_only,\n \t\t\t\t\"remove only ignored files\"),\n@@ -81,6 +92,9 @@ int cmd_clean(int argc, const char **argv, const char *prefix)\n \tif (!ignored)\n \t\tsetup_standard_excludes(&dir);\n \n+\tfor (i = 0; i < exclude_list.nr; i++)\n+\t\tadd_exclude(exclude_list.items[i].string, \"\", 0, dir.exclude_list);\n+\n \tpathspec = get_pathspec(prefix, argv);\n \n \tfill_directory(&dir, pathspec);\n@@ -167,5 +181,6 @@ int cmd_clean(int argc, const char **argv, const char *prefix)\n \tfree(seen);\n \n \tstrbuf_release(&directory);\n+\tstring_list_clear(&exclude_list, 0);\n \treturn (errors != 0);\n }\n-- \n1.7.1.1\n"},{"id":"145894","messageId":"b8f95cd841124e24b9774c301ac63e803da325de.1279654370.git.jaredhance@gmail.com","threadId":"24448","inReplyTo":"cover.1279654370.git.jaredhance@gmail.com","subject":"[PATCH 2/2] Add test for git clean -e.","fromName":"Jared Hance","fromEmail":"jaredhance@gmail.com","sentAt":"2010-07-20T19:36:21Z","receivedAt":"2010-07-20T19:36:21Z","isPatch":true,"sender":{"key":"jaredhance@gmail.com","avatar":"https://avatars.githubusercontent.com/u/170192?v=4"},"body":"\nSigned-off-by: Jared Hance <jaredhance@gmail.com>\n---\n t/t7300-clean.sh |   16 ++++++++++++++++\n 1 files changed, 16 insertions(+), 0 deletions(-)\n\ndiff --git a/t/t7300-clean.sh b/t/t7300-clean.sh\nindex 7d8ed68..3a43571 100755\n--- a/t/t7300-clean.sh\n+++ b/t/t7300-clean.sh\n@@ -438,4 +438,20 @@ test_expect_success 'force removal of nested git work tree' '\n \t! test -d bar\n '\n \n+test_expect_success 'git clean -e' '\n+\trm -fr repo &&\n+\tmkdir repo &&\n+\t(\n+\t\tcd repo &&\n+\t\tgit init &&\n+\t\ttouch 1 2 3 known &&\n+\t\tgit add known &&\n+\t\tgit clean -f -e 1 -e 2 &&\n+\t\ttest -e 1 &&\n+\t\ttest -e 2 &&\n+\t\t! (test -e 3) &&\n+\t\ttest -e known\n+\t)\n+'\n+\n test_done\n-- \n1.7.1.1\n"},{"id":"145896","messageId":"20100720194353.GA5772@localhost.localdomain","threadId":"24448","inReplyTo":"cover.1279654370.git.jaredhance@gmail.com","subject":"Re: [PATCH 0/2] Add -e/--exclude to git-clean.","fromName":"Jared Hance","fromEmail":"jaredhance@gmail.com","sentAt":"2010-07-20T19:43:54Z","receivedAt":"2010-07-20T19:43:54Z","isPatch":true,"sender":{"key":"jaredhance@gmail.com","avatar":"https://avatars.githubusercontent.com/u/170192?v=4"},"body":"My apologies, please:\n    %s/Julio/Junio/g\n"},{"id":"145900","messageId":"7vr5ixlx0k.fsf@alter.siamese.dyndns.org","threadId":"24448","inReplyTo":"8f454efeb3aa4acd0e0c420b197d0269dc53db34.1279654370.git.jaredhance@gmail.com","subject":"Re: [PATCH 1/2] Add -e/--exclude to git-clean.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-07-20T20:27:07Z","receivedAt":"2010-07-20T20:27:07Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jared Hance <jaredhance@gmail.com> writes:\n\n> With the -e/--exclude option for git-clean, a user can specify files\n> that they haven't yet told git about, but either need for a short amount\n> of time or plan to tell git about them later. This allows one to still\n> use git-clean while these files are around without losing data.\n>\n> Signed-off-by: Jared Hance <jaredhance@gmail.com>\n\nThanks.\n\n> +static int exclude_cb(const struct option *opt, const char *arg, int unset)\n> +{\n> +\tstruct string_list *exclude_list = (struct string_list *)opt->value;\n\nUnnecessary cast, as opt->value is of type (void *).\n\n> @@ -36,6 +44,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)\n>  \tstruct dir_struct dir;\n>  \tstatic const char **pathspec;\n>  \tstruct strbuf buf = STRBUF_INIT;\n> +\tstruct string_list exclude_list = { NULL, 0, 0, 0 };\n\nMental note to myself.  We should convert this to use STRING_LIST_INIT\nafter the next release when Thiago's patch graduates to 'master'.\n"},{"id":"145901","messageId":"7vmxtllwoi.fsf@alter.siamese.dyndns.org","threadId":"24448","inReplyTo":"b8f95cd841124e24b9774c301ac63e803da325de.1279654370.git.jaredhance@gmail.com","subject":"Re: [PATCH 2/2] Add test for git clean -e.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-07-20T20:34:21Z","receivedAt":"2010-07-20T20:34:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jared Hance <jaredhance@gmail.com> writes:\n\n> Signed-off-by: Jared Hance <jaredhance@gmail.com>\n> ---\n>  t/t7300-clean.sh |   16 ++++++++++++++++\n>  1 files changed, 16 insertions(+), 0 deletions(-)\n>\n> diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh\n> index 7d8ed68..3a43571 100755\n> --- a/t/t7300-clean.sh\n> +++ b/t/t7300-clean.sh\n> @@ -438,4 +438,20 @@ test_expect_success 'force removal of nested git work tree' '\n>  \t! test -d bar\n>  '\n>  \n> +test_expect_success 'git clean -e' '\n> +\trm -fr repo &&\n> +\tmkdir repo &&\n> +\t(\n> +\t\tcd repo &&\n> +\t\tgit init &&\n> +\t\ttouch 1 2 3 known &&\n> +\t\tgit add known &&\n> +\t\tgit clean -f -e 1 -e 2 &&\n> +\t\ttest -e 1 &&\n> +\t\ttest -e 2 &&\n> +\t\t! (test -e 3) &&\n> +\t\ttest -e known\n> +\t)\n> +'\n\nThis is a good start but it doesn't seem to test possible interactions\nwith entries in .gitignore file(s) in the working tree.  Do we care?\n\nWhat should happen when a path \"path\":\n\n (1) is marked to be ignored in .gitignore and -e \"path\" is also given;\n\n (2) is marked not to be ignored (i.e. \"!path\") in .gitignore but -e\n    \"path\" is given;\n\n (3) is marked to be ignored in .gitignore but -e \"!path\" is given;\n\n (4) is marked not to be ignored in .gitignore and -e \"!path\" is also\n     given;\n\n (5) perhaps other combinations like \"!path\" in a/.gitignore, and -e \"a/path\"\n     from the command line.\n\nWhat does the code actually do?\n"},{"id":"145913","messageId":"20100720233554.GA2141@localhost.localdomain","threadId":"24448","inReplyTo":"7vmxtllwoi.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 2/2] Add test for git clean -e.","fromName":"Jared Hance","fromEmail":"jaredhance@gmail.com","sentAt":"2010-07-20T23:35:54Z","receivedAt":"2010-07-20T23:35:54Z","isPatch":true,"sender":{"key":"jaredhance@gmail.com","avatar":"https://avatars.githubusercontent.com/u/170192?v=4"},"body":"On Tue, Jul 20, 2010 at 01:34:21PM -0700, Junio C Hamano wrote:\n> This is a good start but it doesn't seem to test possible interactions\n> with entries in .gitignore file(s) in the working tree.  Do we care?\n\nHonestly, I'm not sure that we do care.\n\n> \n> What should happen when a path \"path\":\n> \n>  (1) is marked to be ignored in .gitignore and -e \"path\" is also given;\n\nIt is excluded.\n\n>  (2) is marked not to be ignored (i.e. \"!path\") in .gitignore but -e\n>     \"path\" is given;\n\nI think it would be good for \"!path\" to cause -e path to have no\neffect because of globbing issues.\n\nCurrently, -e works as normal.\n\n>  (3) is marked to be ignored in .gitignore but -e \"!path\" is given;\n\nAgain, I'm not sure and am definately open to debate here. Personally,\nI think that -e \"!path\" is completely abusing the use of -e, because\nit is using -e to NOT exclude something.\n\nCurrently, -e has no effect.\n\n>  (4) is marked not to be ignored in .gitignore and -e \"!path\" is also\n>      given;\n\nNo effect happens. Again, this is abuse of -e in my opinion, as its\ngoal to allow one to do a clean and save one or two files.\n\n>  (5) perhaps other combinations like \"!path\" in a/.gitignore, and -e \"a/path\"\n>      from the command line.\n\nJudging by (2), -e will work as normal.\n"}]}