[PATCH] clean: confirm before cleaning files and directories

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxx>
---
 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

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]