git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v12 06/15] git-clean: refactor git-clean into two phases

From
Jiang Xin <worldhello.net@gmail.com>
Date
May 18, 2013, 03:18 UTC
Message-ID
<271643036271eeaadb6b65c223905771be4bef71.1368846844.git.worldhello.net@gmail.com>
In-Reply-To
<cover.1368846844.git.worldhello.net@gmail.com>

Before introducing interactive git-clean, refactor git-clean operations into two phases:

 * hold cleaning items in del_list,
 * and remove them in a separate loop at the end.

We will introduce interactive git-clean between the two phases. The interactive git-clean will show what would be done and must confirm before do real cleaning.

Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
---
 builtin/clean.c | 64 ++++++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 45 insertions(+), 19 deletions(-)
diff --git a/builtin/clean.c b/builtin/clean.c
index f77f95..23e1f 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -15,6 +15,7 @@
 #include "quote.h"
 
 static int force = -1; /* unset */
+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>..."),
@@ -148,12 +149,13 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 	int dry_run = 0, remove_directories = 0, quiet = 0, ignored = 0;
 	int ignored_only = 0, config_set = 0, errors = 0, gone = 1;
 	int rm_flags = REMOVE_DIR_KEEP_NESTED_GIT;
-	struct strbuf directory = STRBUF_INIT;
+	struct strbuf abs_path = STRBUF_INIT;
 	struct dir_struct dir;
 	static const char **pathspec;
 	struct strbuf buf = STRBUF_INIT;
 	struct string_list exclude_list = STRING_LIST_INIT_NODUP;
 	struct exclude_list *el;
+	struct string_list_item *item;
 	const char *qname;
 	char *seen = NULL;
 	struct option options[] = {
@@ -223,6 +225,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 		int matches = 0;
 		struct cache_entry *ce;
 		struct stat st;
+		const char *rel;
 
 		/*
 		 * Remove the '/' at the end that directory
@@ -242,13 +245,8 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 				continue; /* Yup, this one exists unmerged */
 		}
 
-		/*
-		 * we might have removed this as part of earlier
-		 * recursive directory removal, so lstat() here could
-		 * fail with ENOENT.
-		 */
 		if (lstat(ent->name, &st))
-			continue;
+			die_errno("Cannot lstat '%s'", ent->name);
 
 		if (pathspec) {
 			memset(seen, 0, argc > 0 ? argc : 1);
@@ -257,33 +255,61 @@ 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)) {
-				if (remove_dirs(&directory, prefix, rm_flags, dry_run, quiet, &gone))
-					errors++;
-				if (gone && !quiet) {
-					qname = quote_path_relative(directory.buf, prefix, &buf);
-					printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname);
-				}
+				rel = relative_path(ent->name, prefix, &buf);
+				string_list_append(&del_list, rel);
 			}
-			strbuf_reset(&directory);
 		} else {
 			if (pathspec && !matches)
 				continue;
-			res = dry_run ? 0 : unlink(ent->name);
+			rel = relative_path(ent->name, prefix, &buf);
+			string_list_append(&del_list, rel);
+		}
+	}
+
+	/* TODO: do interactive git-clean here, which will modify del_list */
+
+	for_each_string_list_item(item, &del_list) {
+		struct stat st;
+
+		if (prefix) {
+			strbuf_addstr(&abs_path, prefix);
+		}
+		strbuf_addstr(&abs_path, item->string);
+
+		/*
+		 * we might have removed this as part of earlier
+		 * recursive directory removal, so lstat() here could
+		 * fail with ENOENT.
+		 */
+		if (lstat(abs_path.buf, &st))
+			continue;
+
+		if (S_ISDIR(st.st_mode)) {
+			if (remove_dirs(&abs_path, prefix, rm_flags, dry_run, quiet, &gone))
+				errors++;
+			if (gone && !quiet) {
+				qname = quote_path_relative(item->string, NULL, &buf);
+				printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname);
+			}
+		} else {
+			res = dry_run ? 0 : unlink(abs_path.buf);
 			if (res) {
-				qname = quote_path_relative(ent->name, prefix, &buf);
+				qname = quote_path_relative(item->string, NULL, &buf);
 				warning(_(msg_warn_remove_failed), qname);
 				errors++;
 			} else if (!quiet) {
-				qname = quote_path_relative(ent->name, prefix, &buf);
+				qname = quote_path_relative(item->string, NULL, &buf);
 				printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname);
 			}
 		}
+		strbuf_reset(&abs_path);
 	}
 	free(seen);
 
-	strbuf_release(&directory);
+	strbuf_release(&abs_path);
+	strbuf_release(&buf);
+	string_list_clear(&del_list, 0);
 	string_list_clear(&exclude_list, 0);
 	return (errors != 0);
 }
-- 
1.8.3.rc2.26.g7472058
Previous: Jiang XinNext: Jiang Xin
Message 28 of 38 in “Interactive git-clean”
  1. 00/15 Interactive git-cleanJiang Xin, May 18, 2013
  2. 01/15 test: add test cases for relative_pathJiang Xin, May 18, 2013
  3. Junio C HamanoMay 21, 2013
  4. 00/15 interactive git-cleanJiang Xin, May 22, 2013
  5. 01/15 test: add test cases for relative_pathJiang Xin, May 22, 2013
  6. 02/15 path.c: refactor relative_path(), not only strip prefixJiang Xin, May 22, 2013
  7. Michael HaggertyMay 22, 2013
  8. Junio C HamanoMay 22, 2013
  9. Jiang XinMay 26, 2013
  10. Jiang XinMay 30, 2013
  11. 03/15 quote.c: remove path_relative, use relative_path insteadJiang Xin, May 22, 2013
  12. 04/15 Refactor quote_path_relative, remove unused paramsJiang Xin, May 22, 2013
  13. 05/15 Refactor write_name_quoted_relative, remove unused paramsJiang Xin, May 22, 2013
  14. 06/15 git-clean: refactor git-clean into two phasesJiang Xin, May 22, 2013
  15. 07/15 git-clean: add support for -i/--interactiveJiang Xin, May 22, 2013
  16. 08/15 git-clean: show items of del_list in columnsJiang Xin, May 22, 2013
  17. 09/15 git-clean: add colors to interactive git-cleanJiang Xin, May 22, 2013
  18. 10/15 git-clean: use a git-add-interactive compatible UIJiang Xin, May 22, 2013
  19. 11/15 git-clean: add filter by pattern interactive actionJiang Xin, May 22, 2013
  20. 12/15 git-clean: add select by numbers interactive actionJiang Xin, May 22, 2013
  21. 13/15 git-clean: add ask each interactive actionJiang Xin, May 22, 2013
  22. 14/15 git-clean: add documentation for interactive git-cleanJiang Xin, May 22, 2013
  23. 15/15 test: add t7301 for git-clean--interactiveJiang Xin, May 22, 2013
  24. 02/15 path.c: refactor relative_path(), not only strip prefixJiang Xin, May 18, 2013
  25. 03/15 quote.c: remove path_relative, use relative_path insteadJiang Xin, May 18, 2013
  26. 04/15 Refactor quote_path_relative, remove unused paramsJiang Xin, May 18, 2013
  27. 05/15 Refactor write_name_quoted_relative, remove unused paramsJiang Xin, May 18, 2013
  28. 06/15 git-clean: refactor git-clean into two phasesJiang Xin, May 18, 2013
  29. 07/15 git-clean: add support for -i/--interactiveJiang Xin, May 18, 2013
  30. 08/15 git-clean: show items of del_list in columnsJiang Xin, May 18, 2013
  31. 09/15 git-clean: add colors to interactive git-cleanJiang Xin, May 18, 2013
  32. 10/15 git-clean: use a git-add-interactive compatible UIJiang Xin, May 18, 2013
  33. 11/15 git-clean: add filter by pattern interactive actionJiang Xin, May 18, 2013
  34. 12/15 git-clean: add select by numbers interactive actionJiang Xin, May 18, 2013
  35. 13/15 git-clean: add ask each interactive actionJiang Xin, May 18, 2013
  36. 14/15 git-clean: add documentation for interactive git-cleanJiang Xin, May 18, 2013
  37. 15/15 test: add t7301 for git-clean--interactiveJiang Xin, May 18, 2013
  38. Junio C HamanoMay 20, 2013

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.