From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jiang Xin Subject: [PATCH v11 07/15] git-clean: add support for -i/--interactive Date: Fri, 17 May 2013 17:20:11 +0800 Message-ID: References: Cc: Jiang Xin To: Junio C Hamano , Eric Sunshine , Matthieu Moy , Git List X-From: git-owner@vger.kernel.org Fri May 17 11:21:06 2013 Return-path: Envelope-to: gcvg-git-2@plane.gmane.org Received: from vger.kernel.org ([209.132.180.67]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1UdGqS-0006KJ-CY for gcvg-git-2@plane.gmane.org; Fri, 17 May 2013 11:21:00 +0200 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754290Ab3EQJUw (ORCPT ); Fri, 17 May 2013 05:20:52 -0400 Received: from mail-pa0-f52.google.com ([209.85.220.52]:50199 "EHLO mail-pa0-f52.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753156Ab3EQJUt (ORCPT ); Fri, 17 May 2013 05:20:49 -0400 Received: by mail-pa0-f52.google.com with SMTP id bg2so3377625pad.11 for ; Fri, 17 May 2013 02:20:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references:in-reply-to:references; bh=62EQZmv3ScPZcOc47tb6mU6GguEaX7g5ppJX4tGvCEw=; b=Tnzcly7xnVv/lvBU04xHG8fEvFhfr7qFU8wcI1Jqfety2M/odN94BZZh5WLTwgXUGp RQGXEwZtlJK/4VcljaUjmCXTw55sZG2VjAgYO8XWaqUzEs34fhUwafUi7J8Qwk2l8HyW hyltRquR2k5e7MMFMLd4gfyc8XtOXy3abymjyIb9AHXWWGq3tVex1/474MiPijCc2/MT f4xOEs98QArBtpyhIlqfKoZ62F4I5Vwnd1MiW4Htoy/stUKOjysNFqJph2tXzbCcq6ki HIdnFzeGu91r4sP6O2gATp++q8KwNkQEPrFoRRxXKgGdUuOBOofljie7uBHyUwhWbzxL jsbg== X-Received: by 10.66.8.69 with SMTP id p5mr47992671paa.57.1368782448871; Fri, 17 May 2013 02:20:48 -0700 (PDT) Received: from localhost.localdomain ([114.248.153.37]) by mx.google.com with ESMTPSA id 10sm10531002pbm.0.2013.05.17.02.20.46 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Fri, 17 May 2013 02:20:48 -0700 (PDT) X-Mailer: git-send-email 1.8.3.rc2.380.g956c2b2 In-Reply-To: In-Reply-To: References: Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org Archived-At: 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 --- Documentation/git-clean.txt | 10 ++++++-- builtin/clean.c | 57 +++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 60 insertions(+), 7 deletions(-) diff --git a/Documentation/git-clean.txt b/Documentation/git-clean.txt index bdc3a..186e34 100644 --- a/Documentation/git-clean.txt +++ b/Documentation/git-clean.txt @@ -8,7 +8,7 @@ git-clean - Remove untracked files from the working tree SYNOPSIS -------- [verse] -'git clean' [-d] [-f] [-n] [-q] [-e ] [-x | -X] [--] ... +'git clean' [-d] [-f] [-i] [-n] [-q] [-e ] [-x | -X] [--] ... DESCRIPTION ----------- @@ -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:: diff --git a/builtin/clean.c b/builtin/clean.c index 23e1f..f28d6 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -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 ] [-x | -X] [--] ..."), + N_("git clean [-d] [-f] [-i] [-n] [-q] [-e ] [-x | -X] [--] ..."), NULL }; @@ -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) 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) 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) } } - /* 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; -- 1.8.3.rc2.380.g956c2b2