From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jiang Xin Subject: [PATCH v13 07/15] git-clean: add support for -i/--interactive Date: Wed, 22 May 2013 09:40:28 +0800 Message-ID: References: Cc: Git List , Jiang Xin To: Junio C Hamano X-From: git-owner@vger.kernel.org Wed May 22 03:41:27 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 1Uey3O-0001VA-Di for gcvg-git-2@plane.gmane.org; Wed, 22 May 2013 03:41:22 +0200 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754617Ab3EVBlK (ORCPT ); Tue, 21 May 2013 21:41:10 -0400 Received: from mail-pa0-f51.google.com ([209.85.220.51]:56803 "EHLO mail-pa0-f51.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754554Ab3EVBlH (ORCPT ); Tue, 21 May 2013 21:41:07 -0400 Received: by mail-pa0-f51.google.com with SMTP id lf10so269668pab.24 for ; Tue, 21 May 2013 18:41:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references :in-reply-to:references; bh=c/sod0nNv1uN9h2AnUICueTg6fJvtEWZ7ednsaVd5SY=; b=IIH+GJYXjSx6dG+qnT56Bv0wMmmFfy6jvf2Iw5JxkxJYarAXDf9GijpYopufI6fnDx 3jmWoxtotTN1/aAXBgLwIU3hHF1NyItFQ+PRKC5ggZpkc1WED8UJ13SNIeF7P2zIvBj3 AwCTjVc6CwiDPPY9YidYuaV2psmM2PCK9LnqPEcbEln8xxm2XAGEjZoyh2R/dWJAEG9S 0UAogsXTFAEacM/H6V+1tjtPRdknGj8bU502ME+o2hQ4r8eGX7ReASJjIZE0l4+J2dsk kh1PVm8HlId8i8Xd0r4z6NWBimIztQaeN9RiCtfM+Jqa+oOupoaZlShDFAWKzvJ/wZTN sWvA== X-Received: by 10.66.255.99 with SMTP id ap3mr6010026pad.102.1369186867228; Tue, 21 May 2013 18:41:07 -0700 (PDT) Received: from localhost.localdomain ([114.248.150.82]) by mx.google.com with ESMTPSA id at1sm4939345pbc.10.2013.05.21.18.41.04 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Tue, 21 May 2013 18:41:06 -0700 (PDT) X-Mailer: git-send-email 1.8.3.rc3.368.g7c798dd In-Reply-To: In-Reply-To: References: <7vhahwm5n6.fsf@alter.siamese.dyndns.org> 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 Signed-off-by: Junio C Hamano --- 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 77ec1..698fb 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.rc3.368.g7c798dd