Skip to content

Commit

Permalink
git-clean: add support for -i/--interactive
Browse files Browse the repository at this point in the history
Show what would be done and the user must confirm before actually
cleaning.

    Would remove ...
    Would remove ...
    Would remove ...

    Remove [y/n]?

Press "y" to start cleaning, and press "n" if you want to abort.

Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Jiang Xin authored and Junio C Hamano committed Jun 26, 2013
1 parent 396049e commit 1769600
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 7 deletions.
10 changes: 8 additions & 2 deletions Documentation/git-clean.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ git-clean - Remove untracked files from the working tree
SYNOPSIS
--------
[verse]
'git clean' [-d] [-f] [-n] [-q] [-e <pattern>] [-x | -X] [--] <path>...
'git clean' [-d] [-f] [-i] [-n] [-q] [-e <pattern>] [-x | -X] [--] <path>...

DESCRIPTION
-----------
Expand All @@ -34,7 +34,13 @@ OPTIONS
-f::
--force::
If the Git configuration variable clean.requireForce is not set
to false, 'git clean' will refuse to run unless given -f or -n.
to false, 'git clean' will refuse to run unless given -f, -n or
-i.

-i::
--interactive::
Show what would be done and the user must confirm before actually
cleaning.

-n::
--dry-run::
Expand Down
57 changes: 52 additions & 5 deletions builtin/clean.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
};

Expand Down Expand Up @@ -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;
Expand All @@ -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"),
Expand All @@ -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"));
}

Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 1769600

Please sign in to comment.