git-clean: refactor git-clean into two phases
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.net@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
e9a820cefd
commit
396049e5fb
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user