Before introducing interactive git-clean, refactor git-clean operations
into two phases:

 * hold cleaning items in del_list,
 * and remove them in a separate loop at the end.

We will introduce interactive git-clean between the two phases. The
interactive git-clean will show what would be done and must confirm
before do real cleaning.

Signed-off-by: Jiang Xin <worldhello....@gmail.com>
---
 builtin/clean.c | 64 ++++++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 45 insertions(+), 19 deletions(-)

diff --git a/builtin/clean.c b/builtin/clean.c
index f77f95..23e1f 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -15,6 +15,7 @@
 #include "quote.h"
 
 static int force = -1; /* unset */
+static struct string_list del_list = STRING_LIST_INIT_DUP;
 
 static const char *const builtin_clean_usage[] = {
        N_("git clean [-d] [-f] [-n] [-q] [-e <pattern>] [-x | -X] [--] 
<paths>..."),
@@ -148,12 +149,13 @@ int cmd_clean(int argc, const char **argv, const char 
*prefix)
        int dry_run = 0, remove_directories = 0, quiet = 0, ignored = 0;
        int ignored_only = 0, config_set = 0, errors = 0, gone = 1;
        int rm_flags = REMOVE_DIR_KEEP_NESTED_GIT;
-       struct strbuf directory = STRBUF_INIT;
+       struct strbuf abs_path = STRBUF_INIT;
        struct dir_struct dir;
        static const char **pathspec;
        struct strbuf buf = STRBUF_INIT;
        struct string_list exclude_list = STRING_LIST_INIT_NODUP;
        struct exclude_list *el;
+       struct string_list_item *item;
        const char *qname;
        char *seen = NULL;
        struct option options[] = {
@@ -223,6 +225,7 @@ int cmd_clean(int argc, const char **argv, const char 
*prefix)
                int matches = 0;
                struct cache_entry *ce;
                struct stat st;
+               const char *rel;
 
                /*
                 * Remove the '/' at the end that directory
@@ -242,13 +245,8 @@ int cmd_clean(int argc, const char **argv, const char 
*prefix)
                                continue; /* Yup, this one exists unmerged */
                }
 
-               /*
-                * we might have removed this as part of earlier
-                * recursive directory removal, so lstat() here could
-                * fail with ENOENT.
-                */
                if (lstat(ent->name, &st))
-                       continue;
+                       die_errno("Cannot lstat '%s'", ent->name);
 
                if (pathspec) {
                        memset(seen, 0, argc > 0 ? argc : 1);
@@ -257,33 +255,61 @@ int cmd_clean(int argc, const char **argv, const char 
*prefix)
                }
 
                if (S_ISDIR(st.st_mode)) {
-                       strbuf_addstr(&directory, ent->name);
                        if (remove_directories || (matches == MATCHED_EXACTLY)) 
{
-                               if (remove_dirs(&directory, prefix, rm_flags, 
dry_run, quiet, &gone))
-                                       errors++;
-                               if (gone && !quiet) {
-                                       qname = 
quote_path_relative(directory.buf, prefix, &buf);
-                                       printf(dry_run ? _(msg_would_remove) : 
_(msg_remove), qname);
-                               }
+                               rel = relative_path(ent->name, prefix, &buf);
+                               string_list_append(&del_list, rel);
                        }
-                       strbuf_reset(&directory);
                } else {
                        if (pathspec && !matches)
                                continue;
-                       res = dry_run ? 0 : unlink(ent->name);
+                       rel = relative_path(ent->name, prefix, &buf);
+                       string_list_append(&del_list, rel);
+               }
+       }
+
+       /* TODO: do interactive git-clean here, which will modify del_list */
+
+       for_each_string_list_item(item, &del_list) {
+               struct stat st;
+
+               if (prefix) {
+                       strbuf_addstr(&abs_path, prefix);
+               }
+               strbuf_addstr(&abs_path, item->string);
+
+               /*
+                * we might have removed this as part of earlier
+                * recursive directory removal, so lstat() here could
+                * fail with ENOENT.
+                */
+               if (lstat(abs_path.buf, &st))
+                       continue;
+
+               if (S_ISDIR(st.st_mode)) {
+                       if (remove_dirs(&abs_path, prefix, rm_flags, dry_run, 
quiet, &gone))
+                               errors++;
+                       if (gone && !quiet) {
+                               qname = quote_path_relative(item->string, NULL, 
&buf);
+                               printf(dry_run ? _(msg_would_remove) : 
_(msg_remove), qname);
+                       }
+               } else {
+                       res = dry_run ? 0 : unlink(abs_path.buf);
                        if (res) {
-                               qname = quote_path_relative(ent->name, prefix, 
&buf);
+                               qname = quote_path_relative(item->string, NULL, 
&buf);
                                warning(_(msg_warn_remove_failed), qname);
                                errors++;
                        } else if (!quiet) {
-                               qname = quote_path_relative(ent->name, prefix, 
&buf);
+                               qname = quote_path_relative(item->string, NULL, 
&buf);
                                printf(dry_run ? _(msg_would_remove) : 
_(msg_remove), qname);
                        }
                }
+               strbuf_reset(&abs_path);
        }
        free(seen);
 
-       strbuf_release(&directory);
+       strbuf_release(&abs_path);
+       strbuf_release(&buf);
+       string_list_clear(&del_list, 0);
        string_list_clear(&exclude_list, 0);
        return (errors != 0);
 }
-- 
1.8.3.rc2.26.g7472058

--
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

Reply via email to