git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jiang Xin <worldhello.net@gmail.com>
To: Junio C Hamano <gitster@pobox.com>,
	Eric Sunshine <sunshine@sunshineco.com>,
	Matthieu Moy <Matthieu.Moy@imag.fr>,
	Thomas Rast <trast@inf.ethz.ch>
Cc: Git List <git@vger.kernel.org>, Jiang Xin <worldhello.net@gmail.com>
Subject: [PATCH v8 10/12] git-clean refactor: add wrapper scan_clean_candidates
Date: Fri, 10 May 2013 01:14:14 +0800	[thread overview]
Message-ID: <d09dbbd3fc3e9f46bcd9f0444fbdc78e8cd0cb96.1368118918.git.worldhello.net@gmail.com> (raw)
In-Reply-To: <cover.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

  parent reply	other threads:[~2013-05-09 17:15 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-05-08 11:38 [PATCH v7 00/10] interactive git clean Jiang Xin
2013-05-08 11:38 ` [PATCH v7 01/10] Add support for -i/--interactive to git-clean Jiang Xin
2013-05-08 11:38   ` [PATCH v7 02/10] Show items of interactive git-clean in columns Jiang Xin
2013-05-08 11:38     ` [PATCH v7 03/10] Add colors to interactive git-clean Jiang Xin
2013-05-08 11:38       ` [PATCH v7 04/10] git-clean: use a git-add-interactive compatible UI Jiang Xin
2013-05-08 11:38         ` [PATCH v7 05/10] git-clean: interactive cleaning by select numbers Jiang Xin
2013-05-08 11:38           ` [PATCH v7 06/10] git-clean: rm -i style interactive cleaning Jiang Xin
2013-05-08 11:38             ` [PATCH v7 07/10] git-clean: update document for interactive git-clean Jiang Xin
2013-05-08 11:38               ` [PATCH v7 08/10] git-clean refactor: save some options in clean_flags Jiang Xin
2013-05-08 11:38                 ` [PATCH v7 09/10] git-clean refactor: wrap in scan_clean_candidates Jiang Xin
2013-05-08 11:38                   ` [PATCH v7 10/10] git-clean: change clean flags in interactive mode Jiang Xin
2013-05-08 17:02         ` [PATCH v7 04/10] git-clean: use a git-add-interactive compatible UI Junio C Hamano
2013-05-12 17:15       ` [PATCH v7 03/10] Add colors to interactive git-clean Matthieu Moy
2013-05-13  2:47         ` Jiang Xin
2013-05-13  5:28           ` Junio C Hamano
2013-05-13  6:57           ` Matthieu Moy
2013-05-08 17:02     ` [PATCH v7 02/10] Show items of interactive git-clean in columns Junio C Hamano
2013-05-12 17:09     ` Matthieu Moy
2013-05-08 16:57   ` [PATCH v7 01/10] Add support for -i/--interactive to git-clean Junio C Hamano
2013-05-09 16:35     ` Jiang Xin
2013-05-09 17:14       ` [PATCH v8 00/12] Interactive git clean Jiang Xin
2013-05-09 17:14       ` [PATCH v8 01/12] git-clean refactor: hold cleaning items in del_list Jiang Xin
2013-05-09 17:14       ` [PATCH v8 02/12] git-clean: add support for -i/--interactive Jiang Xin
2013-05-09 17:14       ` [PATCH v8 03/12] git-clean: show items of del_list in columns Jiang Xin
2013-05-09 17:14       ` [PATCH v8 04/12] git-clean: add colors to interactive git-clean Jiang Xin
2013-05-09 17:14       ` [PATCH v8 05/12] git-clean: use a git-add-interactive compatible UI Jiang Xin
2013-05-09 17:14       ` [PATCH v8 06/12] git-clean: add filter by pattern interactive action Jiang Xin
2013-05-09 17:14       ` [PATCH v8 07/12] git-clean: add select by numbers " Jiang Xin
2013-05-09 17:14       ` [PATCH v8 08/12] git-clean: add ask each " Jiang Xin
2013-05-09 17:14       ` [PATCH v8 09/12] git-clean refactor: save some options in clean_flags Jiang Xin
2013-05-09 17:14       ` Jiang Xin [this message]
2013-05-09 17:14       ` [PATCH v8 11/12] git-clean: add toggle flags interactive action Jiang Xin
2013-05-09 17:14       ` [PATCH v8 12/12] git-clean: update document for interactive git-clean Jiang Xin
2013-05-12 16:54   ` [PATCH v7 01/10] Add support for -i/--interactive to git-clean Matthieu Moy
2013-05-13 14:46     ` Jiang Xin
2013-05-08 15:15 ` [PATCH v7 00/10] interactive git clean Eric Sunshine
2013-05-08 15:18   ` Eric Sunshine
2013-05-08 16:08   ` Junio C Hamano
2013-05-12 17:28     ` Matthieu Moy
2013-05-13  2:34       ` Jiang Xin
2013-05-13  6:55         ` Matthieu Moy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=d09dbbd3fc3e9f46bcd9f0444fbdc78e8cd0cb96.1368118918.git.worldhello.net@gmail.com \
    --to=worldhello.net@gmail.com \
    --cc=Matthieu.Moy@imag.fr \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=sunshine@sunshineco.com \
    --cc=trast@inf.ethz.ch \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).