diff options
Diffstat (limited to 'builtin/clean.c')
-rw-r--r-- | builtin/clean.c | 85 |
1 files changed, 41 insertions, 44 deletions
diff --git a/builtin/clean.c b/builtin/clean.c index fad533a0a7..4ca12bc0c0 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -6,6 +6,7 @@ * Based on git-clean.sh by Pavel Roskin */ +#define USE_THE_INDEX_COMPATIBILITY_MACROS #include "builtin.h" #include "cache.h" #include "config.h" @@ -16,6 +17,8 @@ #include "column.h" #include "color.h" #include "pathspec.h" +#include "help.h" +#include "prompt.h" static int force = -1; /* unset */ static int interactive; @@ -32,6 +35,7 @@ static const char *msg_would_remove = N_("Would remove %s\n"); static const char *msg_skip_git_dir = N_("Skipping repository %s\n"); static const char *msg_would_skip_git_dir = N_("Would skip repository %s\n"); static const char *msg_warn_remove_failed = N_("failed to remove %s"); +static const char *msg_warn_lstat_failed = N_("could not lstat %s\n"); enum color_clean { CLEAN_COLOR_RESET = 0, @@ -42,6 +46,15 @@ enum color_clean { CLEAN_COLOR_ERROR = 5 }; +static const char *color_interactive_slots[] = { + [CLEAN_COLOR_ERROR] = "error", + [CLEAN_COLOR_HEADER] = "header", + [CLEAN_COLOR_HELP] = "help", + [CLEAN_COLOR_PLAIN] = "plain", + [CLEAN_COLOR_PROMPT] = "prompt", + [CLEAN_COLOR_RESET] = "reset", +}; + static int clean_use_color = -1; static char clean_colors[][COLOR_MAXLEN] = { [CLEAN_COLOR_ERROR] = GIT_COLOR_BOLD_RED, @@ -82,22 +95,7 @@ struct menu_stuff { void *stuff; }; -static int parse_clean_color_slot(const char *var) -{ - if (!strcasecmp(var, "reset")) - return CLEAN_COLOR_RESET; - if (!strcasecmp(var, "plain")) - return CLEAN_COLOR_PLAIN; - if (!strcasecmp(var, "prompt")) - return CLEAN_COLOR_PROMPT; - if (!strcasecmp(var, "header")) - return CLEAN_COLOR_HEADER; - if (!strcasecmp(var, "help")) - return CLEAN_COLOR_HELP; - if (!strcasecmp(var, "error")) - return CLEAN_COLOR_ERROR; - return -1; -} +define_list_config_array(color_interactive_slots); static int git_clean_config(const char *var, const char *value, void *cb) { @@ -113,7 +111,7 @@ static int git_clean_config(const char *var, const char *value, void *cb) return 0; } if (skip_prefix(var, "color.interactive.", &slot_name)) { - int slot = parse_clean_color_slot(slot_name); + int slot = LOOKUP_CONFIG(color_interactive_slots, slot_name); if (slot < 0) return 0; if (!value) @@ -145,6 +143,7 @@ static void clean_print_color(enum color_clean ix) static int exclude_cb(const struct option *opt, const char *arg, int unset) { struct string_list *exclude_list = opt->value; + BUG_ON_OPT_NEG(unset); string_list_append(exclude_list, arg); return 0; } @@ -160,7 +159,8 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag, *dir_gone = 1; - if ((force_flag & REMOVE_DIR_KEEP_NESTED_GIT) && is_nonbare_repository_dir(path)) { + if ((force_flag & REMOVE_DIR_KEEP_NESTED_GIT) && + is_nonbare_repository_dir(path)) { if (!quiet) { quote_path_relative(path->buf, prefix, "ed); printf(dry_run ? _(msg_would_skip_git_dir) : _(msg_skip_git_dir), @@ -197,7 +197,7 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag, strbuf_setlen(path, len); strbuf_addstr(path, e->d_name); if (lstat(path->buf, &st)) - ; /* fall thru */ + warning_errno(_(msg_warn_lstat_failed), path->buf); else if (S_ISDIR(st.st_mode)) { if (remove_dirs(path, prefix, force_flag, dry_run, quiet, &gone)) ret = 1; @@ -421,7 +421,6 @@ static int find_unique(const char *choice, struct menu_stuff *menu_stuff) return found; } - /* * Parse user input, and return choice(s) for menu (menu_stuff). * @@ -581,9 +580,7 @@ static int *list_and_choose(struct menu_opts *opts, struct menu_stuff *stuff) clean_get_color(CLEAN_COLOR_RESET)); } - if (strbuf_getline_lf(&choice, stdin) != EOF) { - strbuf_trim(&choice); - } else { + if (git_read_line_interactively(&choice) == EOF) { eof = 1; break; } @@ -650,7 +647,7 @@ static int filter_by_patterns_cmd(void) struct strbuf confirm = STRBUF_INIT; struct strbuf **ignore_list; struct string_list_item *item; - struct exclude_list *el; + struct pattern_list *pl; int changed = -1, i; for (;;) { @@ -663,9 +660,7 @@ static int filter_by_patterns_cmd(void) clean_print_color(CLEAN_COLOR_PROMPT); printf(_("Input ignore patterns>> ")); clean_print_color(CLEAN_COLOR_RESET); - if (strbuf_getline_lf(&confirm, stdin) != EOF) - strbuf_trim(&confirm); - else + if (git_read_line_interactively(&confirm) == EOF) putchar('\n'); /* quit filter_by_pattern mode if press ENTER or Ctrl-D */ @@ -673,7 +668,7 @@ static int filter_by_patterns_cmd(void) break; memset(&dir, 0, sizeof(dir)); - el = add_exclude_list(&dir, EXC_CMDL, "manual exclude"); + pl = add_pattern_list(&dir, EXC_CMDL, "manual exclude"); ignore_list = strbuf_split_max(&confirm, ' ', 0); for (i = 0; ignore_list[i]; i++) { @@ -681,7 +676,7 @@ static int filter_by_patterns_cmd(void) if (!ignore_list[i]->len) continue; - add_exclude(ignore_list[i]->buf, "", 0, el, -(i+1)); + add_pattern(ignore_list[i]->buf, "", 0, pl, -(i+1)); } changed = 0; @@ -761,9 +756,7 @@ static int ask_each_cmd(void) qname = quote_path_relative(item->string, NULL, &buf); /* TRANSLATORS: Make sure to keep [y/N] as is */ printf(_("Remove %s [y/N]? "), qname); - if (strbuf_getline_lf(&confirm, stdin) != EOF) { - strbuf_trim(&confirm); - } else { + if (git_read_line_interactively(&confirm) == EOF) { putchar('\n'); eof = 1; } @@ -903,7 +896,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix) struct pathspec pathspec; struct strbuf buf = STRBUF_INIT; struct string_list exclude_list = STRING_LIST_INIT_NODUP; - struct exclude_list *el; + struct pattern_list *pl; struct string_list_item *item; const char *qname; struct option options[] = { @@ -913,8 +906,8 @@ int cmd_clean(int argc, const char **argv, const char *prefix) OPT_BOOL('i', "interactive", &interactive, N_("interactive cleaning")), OPT_BOOL('d', NULL, &remove_directories, N_("remove whole directories")), - { OPTION_CALLBACK, 'e', "exclude", &exclude_list, N_("pattern"), - N_("add <pattern> to ignore rules"), PARSE_OPT_NONEG, exclude_cb }, + OPT_CALLBACK_F('e', "exclude", &exclude_list, N_("pattern"), + N_("add <pattern> to ignore rules"), PARSE_OPT_NONEG, exclude_cb), OPT_BOOL('x', NULL, &ignored, N_("remove ignored files, too")), OPT_BOOL('X', NULL, &ignored_only, N_("remove only ignored files")), @@ -948,9 +941,19 @@ int cmd_clean(int argc, const char **argv, const char *prefix) if (force > 1) rm_flags = 0; + else + dir.flags |= DIR_SKIP_NESTED_GIT; dir.flags |= DIR_SHOW_OTHER_DIRECTORIES; + if (argc) { + /* + * Remaining args implies pathspecs specified, and we should + * recurse within those. + */ + remove_directories = 1; + } + if (remove_directories) dir.flags |= DIR_SHOW_IGNORED_TOO | DIR_KEEP_UNTRACKED_CONTENTS; @@ -960,9 +963,9 @@ int cmd_clean(int argc, const char **argv, const char *prefix) if (!ignored) setup_standard_excludes(&dir); - el = add_exclude_list(&dir, EXC_CMDL, "--exclude option"); + pl = add_pattern_list(&dir, EXC_CMDL, "--exclude option"); for (i = 0; i < exclude_list.nr; i++) - add_exclude(exclude_list.items[i].string, "", 0, el, -(i+1)); + add_pattern(exclude_list.items[i].string, "", 0, pl, -(i+1)); parse_pathspec(&pathspec, 0, PATHSPEC_PREFER_CWD, @@ -980,12 +983,6 @@ int cmd_clean(int argc, const char **argv, const char *prefix) if (!cache_name_is_other(ent->name, ent->len)) continue; - if (pathspec.nr) - matches = dir_path_match(ent, &pathspec, 0, NULL); - - if (pathspec.nr && !matches) - continue; - if (lstat(ent->name, &st)) die_errno("Cannot lstat '%s'", ent->name); @@ -1009,6 +1006,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix) for_each_string_list_item(item, &del_list) { struct stat st; + strbuf_reset(&abs_path); if (prefix) strbuf_addstr(&abs_path, prefix); @@ -1042,7 +1040,6 @@ int cmd_clean(int argc, const char **argv, const char *prefix) printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname); } } - strbuf_reset(&abs_path); } strbuf_release(&abs_path); |