Re: [PATCH v14 06/16] git-clean: refactor git-clean into two phases

2013-06-24 Thread Junio C Hamano
Jiang Xin  writes:

> 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 
> Signed-off-by: Junio C Hamano 
> ---

Looks sensible.
--
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 v14 06/16] git-clean: refactor git-clean into two phases

2013-06-24 Thread Jiang Xin
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 
Signed-off-by: Junio C Hamano 
---
 builtin/clean.c | 64 -
 1 file changed, 45 insertions(+), 19 deletions(-)

diff --git a/builtin/clean.c b/builtin/clean.c
index f77f95..77ec1 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 ] [-x | -X] [--] 
..."),
@@ -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);