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

[PATCH v8 10/12] git-clean refactor: add wrapper scan_clean_candidates

From
Jiang Xin <worldhello.net@gmail.com>
Date
May 9, 2013, 17:14 UTC
Message-ID
<d09dbbd3fc3e9f46bcd9f0444fbdc78e8cd0cb96.1368118918.git.worldhello.net@gmail.com>
In-Reply-To
<cover.1368118918.git.worldhello.net@gmail.com>

Add new wrapper `scan_clean_candidates`, which determines the del_list (i.e. the cleaning candidates). This function will be reused later in the interactive git-clean, so we can change flags of git-clean and refresh the del_list.

Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
---
 builtin/clean.c | 169 +++++++++++++++++++++++++++++++-------------------------
 1 file changed, 93 insertions(+), 76 deletions(-)
diff --git a/builtin/clean.c b/builtin/clean.c
index 26d00..232d48 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -295,6 +295,96 @@ static const char *path_relative(const char *in, const char *prefix)
 	return buf;
 }
 
+static void scan_clean_candidates(const char **pathspec,
+				  struct string_list exclude_list,
+				  const char *prefix)
+{
+	struct dir_struct dir;
+	struct exclude_list *el;
+	char *seen = NULL;
+	const char **pathspec_p = pathspec;
+	const char *rel;
+	int pathspec_nr = 0;
+	int i;
+
+	while (pathspec_p && *(pathspec_p++))
+		pathspec_nr++;
+
+	memset(&dir, 0, sizeof(dir));
+	if (clean_flags & CLEAN_OPTS_IGNORED_ONLY)
+		dir.flags |= DIR_SHOW_IGNORED;
+
+	if (clean_flags & CLEAN_OPTS_IGNORED_ONLY &&
+	    clean_flags & CLEAN_OPTS_SHOW_IGNORED)
+		die(_("-x and -X cannot be used together"));
+
+	dir.flags |= DIR_SHOW_OTHER_DIRECTORIES;
+
+	if (!(clean_flags & CLEAN_OPTS_SHOW_IGNORED))
+		setup_standard_excludes(&dir);
+
+	el = add_exclude_list(&dir, EXC_CMDL, "--exclude option");
+	for (i = 0; i < exclude_list.nr; i++)
+		add_exclude(exclude_list.items[i].string, "", 0, el, -(i+1));
+
+	fill_directory(&dir, pathspec);
+
+	if (pathspec)
+		seen = xmalloc(pathspec_nr > 0 ? pathspec_nr : 1);
+
+	string_list_clear(&del_list, 0);
+
+	for (i = 0; i < dir.nr; i++) {
+		struct dir_entry *ent = dir.entries[i];
+		int len, pos;
+		int matches = 0;
+		struct cache_entry *ce;
+		struct stat st;
+
+		/*
+		 * Remove the '/' at the end that directory
+		 * walking adds for directory entries.
+		 */
+		len = ent->len;
+		if (len && ent->name[len-1] == '/')
+			len--;
+		pos = cache_name_pos(ent->name, len);
+		if (0 <= pos)
+			continue;	/* exact match */
+		pos = -pos - 1;
+		if (pos < active_nr) {
+			ce = active_cache[pos];
+			if (ce_namelen(ce) == len &&
+			    !memcmp(ce->name, ent->name, len))
+				continue; /* Yup, this one exists unmerged */
+		}
+
+		if (lstat(ent->name, &st))
+			continue;
+
+		if (pathspec) {
+			memset(seen, 0, pathspec_nr > 0 ? pathspec_nr : 1);
+			matches = match_pathspec(pathspec, ent->name, len,
+						 0, seen);
+		}
+
+		if (S_ISDIR(st.st_mode)) {
+			if ((clean_flags & CLEAN_OPTS_REMOVE_DIRECTORIES) ||
+			    (matches == MATCHED_EXACTLY)) {
+				rel = path_relative(ent->name, prefix);
+				string_list_append(&del_list, rel);
+			}
+		} else {
+			if (pathspec && !matches)
+				continue;
+			rel = path_relative(ent->name, prefix);
+			string_list_append(&del_list, rel);
+		}
+	}
+
+	free(seen);
+}
+
 static void pretty_print_dels(void)
 {
 	struct string_list list = STRING_LIST_INIT_DUP;
@@ -871,18 +961,15 @@ static void interactive_main_loop(void)
 
 int cmd_clean(int argc, const char **argv, const char *prefix)
 {
-	int i, res;
+	int res;
 	int dry_run = 0, remove_directories = 0, quiet = 0, ignored = 0;
 	int ignored_only = 0, config_set = 0, errors = 0, gone = 1;
 	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;
+	struct string_list exclude_list = STRING_LIST_INIT_NODUP;
 	const char *qname;
-	char *seen = NULL;
 	struct option options[] = {
 		OPT__QUIET(&quiet, N_("do not print names of files removed")),
 		OPT__DRY_RUN(&dry_run, N_("dry run")),
@@ -932,78 +1019,9 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 	if (remove_directories)
 		clean_flags |= CLEAN_OPTS_REMOVE_DIRECTORIES;
 
-	memset(&dir, 0, sizeof(dir));
-	if (clean_flags & CLEAN_OPTS_IGNORED_ONLY)
-		dir.flags |= DIR_SHOW_IGNORED;
-
-	if (clean_flags & CLEAN_OPTS_IGNORED_ONLY &&
-	    clean_flags & CLEAN_OPTS_SHOW_IGNORED)
-		die(_("-x and -X cannot be used together"));
-
-	dir.flags |= DIR_SHOW_OTHER_DIRECTORIES;
-
-	if (!(clean_flags & CLEAN_OPTS_SHOW_IGNORED))
-		setup_standard_excludes(&dir);
-
-	el = add_exclude_list(&dir, EXC_CMDL, "--exclude option");
-	for (i = 0; i < exclude_list.nr; i++)
-		add_exclude(exclude_list.items[i].string, "", 0, el, -(i+1));
-
 	pathspec = get_pathspec(prefix, argv);
 
-	fill_directory(&dir, pathspec);
-
-	if (pathspec)
-		seen = xmalloc(argc > 0 ? argc : 1);
-
-	for (i = 0; i < dir.nr; i++) {
-		struct dir_entry *ent = dir.entries[i];
-		int len, pos;
-		int matches = 0;
-		struct cache_entry *ce;
-		struct stat st;
-		const char *rel;
-
-		/*
-		 * Remove the '/' at the end that directory
-		 * walking adds for directory entries.
-		 */
-		len = ent->len;
-		if (len && ent->name[len-1] == '/')
-			len--;
-		pos = cache_name_pos(ent->name, len);
-		if (0 <= pos)
-			continue;	/* exact match */
-		pos = -pos - 1;
-		if (pos < active_nr) {
-			ce = active_cache[pos];
-			if (ce_namelen(ce) == len &&
-			    !memcmp(ce->name, ent->name, len))
-				continue; /* Yup, this one exists unmerged */
-		}
-
-		if (lstat(ent->name, &st))
-			continue;
-
-		if (pathspec) {
-			memset(seen, 0, argc > 0 ? argc : 1);
-			matches = match_pathspec(pathspec, ent->name, len,
-						 0, seen);
-		}
-
-		if (S_ISDIR(st.st_mode)) {
-			if ((clean_flags & CLEAN_OPTS_REMOVE_DIRECTORIES) ||
-			    (matches == MATCHED_EXACTLY)) {
-				rel = path_relative(ent->name, prefix);
-				string_list_append(&del_list, rel);
-			}
-		} else {
-			if (pathspec && !matches)
-				continue;
-			rel = path_relative(ent->name, prefix);
-			string_list_append(&del_list, rel);
-		}
-	}
+	scan_clean_candidates(pathspec, exclude_list, prefix);
 
 	if (interactive && !dry_run && del_list.nr > 0)
 		interactive_main_loop();
@@ -1047,7 +1065,6 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 		}
 		strbuf_reset(&abs_path);
 	}
-	free(seen);
 
 	strbuf_release(&abs_path);
 	string_list_clear(&del_list, 0);
-- 
1.8.3.rc1.341.g24a8a0f
Previous: Jiang XinNext: Jiang Xin
Message 31 of 41 in “interactive git clean”
  1. 00/10 interactive git cleanJiang Xin, May 8, 2013
  2. 01/10 Add support for -i/--interactive to git-cleanJiang Xin, May 8, 2013
  3. 02/10 Show items of interactive git-clean in columnsJiang Xin, May 8, 2013
  4. 03/10 Add colors to interactive git-cleanJiang Xin, May 8, 2013
  5. 04/10 git-clean: use a git-add-interactive compatible UIJiang Xin, May 8, 2013
  6. 05/10 git-clean: interactive cleaning by select numbersJiang Xin, May 8, 2013
  7. 06/10 git-clean: rm -i style interactive cleaningJiang Xin, May 8, 2013
  8. 07/10 git-clean: update document for interactive git-cleanJiang Xin, May 8, 2013
  9. 08/10 git-clean refactor: save some options in clean_flagsJiang Xin, May 8, 2013
  10. 09/10 git-clean refactor: wrap in scan_clean_candidatesJiang Xin, May 8, 2013
  11. 10/10 git-clean: change clean flags in interactive modeJiang Xin, May 8, 2013
  12. Junio C HamanoMay 8, 2013
  13. Matthieu MoyMay 12, 2013
  14. Jiang XinMay 13, 2013
  15. Junio C HamanoMay 13, 2013
  16. Matthieu MoyMay 13, 2013
  17. Junio C HamanoMay 8, 2013
  18. Matthieu MoyMay 12, 2013
  19. Junio C HamanoMay 8, 2013
  20. Jiang XinMay 9, 2013
  21. 00/12 Interactive git cleanJiang Xin, May 9, 2013
  22. 01/12 git-clean refactor: hold cleaning items in del_listJiang Xin, May 9, 2013
  23. 02/12 git-clean: add support for -i/--interactiveJiang Xin, May 9, 2013
  24. 03/12 git-clean: show items of del_list in columnsJiang Xin, May 9, 2013
  25. 04/12 git-clean: add colors to interactive git-cleanJiang Xin, May 9, 2013
  26. 05/12 git-clean: use a git-add-interactive compatible UIJiang Xin, May 9, 2013
  27. 06/12 git-clean: add filter by pattern interactive actionJiang Xin, May 9, 2013
  28. 07/12 git-clean: add select by numbers interactive actionJiang Xin, May 9, 2013
  29. 08/12 git-clean: add ask each interactive actionJiang Xin, May 9, 2013
  30. 09/12 git-clean refactor: save some options in clean_flagsJiang Xin, May 9, 2013
  31. 10/12 git-clean refactor: add wrapper scan_clean_candidatesJiang Xin, May 9, 2013
  32. 11/12 git-clean: add toggle flags interactive actionJiang Xin, May 9, 2013
  33. 12/12 git-clean: update document for interactive git-cleanJiang Xin, May 9, 2013
  34. Matthieu MoyMay 12, 2013
  35. Jiang XinMay 13, 2013
  36. Eric SunshineMay 8, 2013
  37. Eric SunshineMay 8, 2013
  38. Junio C HamanoMay 8, 2013
  39. Matthieu MoyMay 12, 2013
  40. Jiang XinMay 13, 2013
  41. Matthieu MoyMay 13, 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.