@ -15,10 +15,11 @@
@@ -15,10 +15,11 @@
#include "quote.h"
static int force = -1; /* unset */
static int interactive;
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>..."),
N_("git clean [-d] [-f] [-i] [-n] [-q] [-e <pattern>] [-x | -X] [--] <paths>..."),
NULL
};
@ -143,6 +144,50 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
@@ -143,6 +144,50 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
return ret;
}
static void interactive_main_loop(void)
{
struct strbuf confirm = STRBUF_INIT;
struct strbuf buf = STRBUF_INIT;
struct string_list_item *item;
const char *qname;
while (del_list.nr) {
putchar('\n');
for_each_string_list_item(item, &del_list) {
qname = quote_path_relative(item->string, NULL, &buf);
printf(_(msg_would_remove), qname);
}
putchar('\n');
printf(_("Remove [y/n]? "));
if (strbuf_getline(&confirm, stdin, '\n') != EOF) {
strbuf_trim(&confirm);
} else {
/* Ctrl-D is the same as "quit" */
string_list_clear(&del_list, 0);
putchar('\n');
printf_ln("Bye.");
break;
}
if (confirm.len) {
if (!strncasecmp(confirm.buf, "yes", confirm.len)) {
break;
} else if (!strncasecmp(confirm.buf, "no", confirm.len) ||
!strncasecmp(confirm.buf, "quit", confirm.len)) {
string_list_clear(&del_list, 0);
printf_ln("Bye.");
break;
} else {
continue;
}
}
}
strbuf_release(&buf);
strbuf_release(&confirm);
}
int cmd_clean(int argc, const char **argv, const char *prefix)
{
int i, res;
@ -162,6 +207,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
@@ -162,6 +207,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
OPT__QUIET(&quiet, N_("do not print names of files removed")),
OPT__DRY_RUN(&dry_run, N_("dry run")),
OPT__FORCE(&force, N_("force")),
OPT_BOOL('i', "interactive", &interactive, N_("interactive cleaning")),
OPT_BOOLEAN('d', NULL, &remove_directories,
N_("remove whole directories")),
{ OPTION_CALLBACK, 'e', "exclude", &exclude_list, N_("pattern"),
@ -188,12 +234,12 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
@@ -188,12 +234,12 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
if (ignored && ignored_only)
die(_("-x and -X cannot be used together"));
if (!dry_run && !force) {
if (!interactive && !dry_run && !force) {
if (config_set)
die(_("clean.requireForce set to true and neither -n nor -f given; "
die(_("clean.requireForce set to true and neither -i, -n nor -f given; "
"refusing to clean"));
else
die(_("clean.requireForce defaults to true and neither -n nor -f given; "
die(_("clean.requireForce defaults to true and neither -i, -n nor -f given; "
"refusing to clean"));
}
@ -267,7 +313,8 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
@@ -267,7 +313,8 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
}
}
/* TODO: do interactive git-clean here, which will modify del_list */
if (interactive && del_list.nr > 0)
interactive_main_loop();
for_each_string_list_item(item, &del_list) {
struct stat st;