git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] clean: confirm before cleaning files and directories
@ 2013-04-26  8:07 Jiang Xin
  2013-04-26  8:21 ` Matthieu Moy
  0 siblings, 1 reply; 30+ messages in thread
From: Jiang Xin @ 2013-04-26  8:07 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git List, Jiang Xin

When running `git clean`, it will be convenient and safe to show a
confirm dialog and only delete files and directories when confirmed.
The confirm dialog will popup when:

 * run `git clean` in interactive sessions,
 * not a dry run,
 * and not quiet.

There may be existing scripts that call `git clean -f` while leave the
standard input and the standard output of the `git clean` connected to
whatever environment the scripts were started, and such invocation might
trigger the confirm dialog. In this case, add a `-q` option, such as
`git clean -q -f`, then the confirm dialog won't popup.

Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
---
 builtin/clean.c | 66 +++++++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 52 insertions(+), 14 deletions(-)

diff --git a/builtin/clean.c b/builtin/clean.c
index 04e39..e31a1 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -169,6 +169,10 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 				N_("remove only ignored files")),
 		OPT_END()
 	};
+	struct string_list dels = STRING_LIST_INIT_DUP;
+	struct string_list_item *item;
+	struct strbuf confirm = STRBUF_INIT;
+	int confirmed = 0;
 
 	git_config(git_clean_config, NULL);
 	if (force < 0)
@@ -257,33 +261,67 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 		}
 
 		if (S_ISDIR(st.st_mode)) {
-			strbuf_addstr(&directory, ent->name);
 			if (remove_directories || (matches == MATCHED_EXACTLY)) {
+				string_list_append(&dels, ent->name);
+			}
+		} else {
+			if (pathspec && !matches)
+				continue;
+			string_list_append(&dels, ent->name);
+		}
+	}
+
+	if (!isatty(0) || !isatty(1) || quiet || dry_run) {
+		confirmed = 1;
+	}
+
+	if (!confirmed && dels.nr > 0) {
+		for_each_string_list_item(item, &dels) {
+			qname = quote_path_relative(item->string, -1, &buf, prefix);
+			printf(_(msg_would_remove), qname);
+		}
+		printf(_("Are you sure [y/N]? "));
+		strbuf_getline(&confirm, stdin, '\n');
+		strbuf_trim(&confirm);
+		if (!strcasecmp(confirm.buf, "y")) {
+			confirmed = 1;
+		}
+	}
+
+	if (confirmed) {
+		for_each_string_list_item(item, &dels) {
+			struct stat st;
+
+			if (lstat(item->string, &st))
+				continue;
+
+			if (S_ISDIR(st.st_mode)) {
+				strbuf_addstr(&directory, item->string);
 				if (remove_dirs(&directory, prefix, rm_flags, dry_run, quiet, &gone))
 					errors++;
 				if (gone && !quiet) {
 					qname = quote_path_relative(directory.buf, directory.len, &buf, prefix);
 					printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname);
 				}
-			}
-			strbuf_reset(&directory);
-		} else {
-			if (pathspec && !matches)
-				continue;
-			res = dry_run ? 0 : unlink(ent->name);
-			if (res) {
-				qname = quote_path_relative(ent->name, -1, &buf, prefix);
-				warning(_(msg_warn_remove_failed), qname);
-				errors++;
-			} else if (!quiet) {
-				qname = quote_path_relative(ent->name, -1, &buf, prefix);
-				printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname);
+				strbuf_reset(&directory);
+			} else {
+				res = dry_run ? 0 : unlink(item->string);
+				if (res) {
+					qname = quote_path_relative(item->string, -1, &buf, prefix);
+					warning(_(msg_warn_remove_failed), qname);
+					errors++;
+				} else if (!quiet) {
+					qname = quote_path_relative(item->string, -1, &buf, prefix);
+					printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname);
+				}
 			}
 		}
 	}
 	free(seen);
 
 	strbuf_release(&directory);
+	strbuf_release(&confirm);
 	string_list_clear(&exclude_list, 0);
+	string_list_clear(&dels, 0);
 	return (errors != 0);
 }
-- 
1.8.2.1.628.gcd33b41

^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2013-05-03 12:55 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-04-26  8:07 [PATCH] clean: confirm before cleaning files and directories Jiang Xin
2013-04-26  8:21 ` Matthieu Moy
2013-04-26  8:41   ` Jiang Xin
2013-04-26  8:51     ` Matthieu Moy
2013-04-26 10:00       ` Jiang Xin
2013-04-26  8:53     ` Thomas Rast
2013-04-26 16:10     ` Junio C Hamano
2013-04-26 16:19       ` Matthieu Moy
2013-04-26 17:07         ` Junio C Hamano
2013-04-26 19:06           ` Junio C Hamano
2013-04-27  2:09             ` Jiang Xin
2013-04-27 16:13             ` [PATCH v2] Add support for -i/--interactive to git-clean Jiang Xin
2013-04-27 21:41               ` Matthieu Moy
2013-04-27 23:11                 ` Junio C Hamano
2013-04-28  2:03               ` Eric Sunshine
2013-04-29  8:03               ` Matthieu Moy
2013-04-29 14:30                 ` [PATCH] clean: Introduce -z for machine readable output Michael J Gruber
2013-04-29 14:45                   ` Matthieu Moy
2013-04-29 16:15                 ` [PATCH v2] Add support for -i/--interactive to git-clean Jiang Xin
2013-04-30 19:25                   ` [PATCH v3] " Jiang Xin
2013-05-01 15:12                     ` Matthieu Moy
2013-05-02 13:15                       ` [PATCH v4 1/3] " Jiang Xin
2013-05-02 13:15                       ` [PATCH v4 2/3] Show items of interactive git-clean in columns Jiang Xin
2013-05-02 15:03                         ` Matthieu Moy
2013-05-03  1:26                           ` Jiang Xin
2013-05-03 12:54                             ` Matthieu Moy
2013-05-02 13:15                       ` [PATCH v4 3/3] Add colors to interactive git-clean Jiang Xin
2013-05-02 15:07                         ` Matthieu Moy
2013-05-03  2:53                           ` Jiang Xin
2013-05-02 13:43                       ` [PATCH v3] Add support for -i/--interactive to git-clean Jiang Xin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).