All of lore.kernel.org
 help / color / mirror / Atom feed
From: Karsten Blees <karsten.blees@gmail.com>
To: Git List <git@vger.kernel.org>
Cc: Karsten Blees <karsten.blees@gmail.com>,
	Junio C Hamano <gitster@pobox.com>,
	Erik Faye-Lund <kusmabite@gmail.com>,
	Ramkumar Ramachandra <artagnon@gmail.com>,
	Robert Zeh <robert.allan.zeh@gmail.com>,
	Duy Nguyen <pclouds@gmail.com>,
	Antoine Pelisse <apelisse@gmail.com>,
	Adam Spiers <git@adamspiers.org>
Subject: [PATCH v2 14/14] dir.c: git-status --ignored: don't scan the work tree twice
Date: Mon, 15 Apr 2013 21:15:03 +0200	[thread overview]
Message-ID: <516C51B7.7080305@gmail.com> (raw)
In-Reply-To: <516C4F27.30203@gmail.com>

'git-status --ignored' still scans the work tree twice to collect
untracked and ignored files, respectively.

fill_directory / read_directory already supports collecting untracked and
ignored files in a single directory scan. However, the DIR_COLLECT_IGNORED
flag to enable this has some git-add specific side-effects (e.g. it
doesn't recurse into ignored directories, so listing ignored files with
--untracked=all doesn't work).

The DIR_SHOW_IGNORED flag doesn't list untracked files and returns ignored
files in dir_struct.entries[] (instead of dir_struct.ignored[] as
DIR_COLLECT_IGNORED). DIR_SHOW_IGNORED is used all throughout git.

We don't want to break the existing API, so lets introduce a new flag
DIR_SHOW_IGNORED_TOO that lists untracked as well as ignored files similar
to DIR_COLLECT_FILES, but will recurse into sub-directories based on the
other flags as DIR_SHOW_IGNORED does.

In dir.c::read_directory_recursive, add ignored files to either
dir_struct.entries[] or dir_struct.ignored[] based on the flags. Also move
the DIR_COLLECT_IGNORED case here so that filling result lists is in a
common place.

In wt-status.c::wt_status_collect_untracked, use the new flag and read
results from dir_struct.ignored[]. Remove the extra fill_directory call.

builtin/check-ignore.c doesn't call fill_directory, setting the git-add
specific DIR_COLLECT_IGNORED flag has no effect here. Remove for clarity.

Update API documentation to reflect the changes.

Performance: with this patch, 'git-status --ignored' is typically as fast
as 'git-status'.

Signed-off-by: Karsten Blees <blees@dcon.de>
---
 Documentation/technical/api-directory-listing.txt | 25 ++++++++++++++++++++---
 builtin/check-ignore.c                            |  1 -
 dir.c                                             | 10 +++++----
 dir.h                                             |  3 ++-
 wt-status.c                                       | 24 ++++++++++------------
 5 files changed, 41 insertions(+), 22 deletions(-)

diff --git a/Documentation/technical/api-directory-listing.txt b/Documentation/technical/api-directory-listing.txt
index 1f349b2..7f8e78d 100644
--- a/Documentation/technical/api-directory-listing.txt
+++ b/Documentation/technical/api-directory-listing.txt
@@ -22,12 +22,23 @@ The notable options are:
 
 `flags`::
 
-	A bit-field of options:
+	A bit-field of options (the `*IGNORED*` flags are mutually exclusive):
 
 `DIR_SHOW_IGNORED`:::
 
-	The traversal is for finding just ignored files, not unignored
-	files.
+	Return just ignored files in `entries[]`, not untracked files.
+
+`DIR_SHOW_IGNORED_TOO`:::
+
+	Similar to `DIR_SHOW_IGNORED`, but return ignored files in `ignored[]`
+	in addition to untracked files in `entries[]`.
+
+`DIR_COLLECT_IGNORED`:::
+
+	Special mode for git-add. Return ignored files in `ignored[]` and
+	untracked files in `entries[]`. Only returns ignored files that match
+	pathspec exactly (no wildcards). Does not recurse into ignored
+	directories.
 
 `DIR_SHOW_OTHER_DIRECTORIES`:::
 
@@ -57,6 +68,14 @@ The result of the enumeration is left in these fields:
 
 	Internal use; keeps track of allocation of `entries[]` array.
 
+`ignored[]`::
+
+	An array of `struct dir_entry`, used for ignored paths with the
+	`DIR_SHOW_IGNORED_TOO` and `DIR_COLLECT_IGNORED` flags.
+
+`ignored_nr`::
+
+	The number of members in `ignored[]` array.
 
 Calling sequence
 ----------------
diff --git a/builtin/check-ignore.c b/builtin/check-ignore.c
index 7388346..854a88a 100644
--- a/builtin/check-ignore.c
+++ b/builtin/check-ignore.c
@@ -66,7 +66,6 @@ static int check_ignore(const char *prefix, const char **pathspec)
 		die(_("index file corrupt"));
 
 	memset(&dir, 0, sizeof(dir));
-	dir.flags |= DIR_COLLECT_IGNORED;
 	setup_standard_excludes(&dir);
 
 	if (!pathspec || !*pathspec) {
diff --git a/dir.c b/dir.c
index 5770ed4..847e2f2 100644
--- a/dir.c
+++ b/dir.c
@@ -1139,15 +1139,12 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
 		return path_none;
 
 	exclude = is_excluded(dir, path->buf, &dtype);
-	if (exclude && (dir->flags & DIR_COLLECT_IGNORED)
-	    && exclude_matches_pathspec(path->buf, path->len, simplify))
-		dir_add_ignored(dir, path->buf, path->len);
 
 	/*
 	 * Excluded? If we don't explicitly want to show
 	 * ignored files, ignore it
 	 */
-	if (exclude && !(dir->flags & DIR_SHOW_IGNORED))
+	if (exclude && !(dir->flags & (DIR_SHOW_IGNORED|DIR_SHOW_IGNORED_TOO)))
 		return path_excluded;
 
 	switch (dtype) {
@@ -1236,6 +1233,11 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
 		case path_excluded:
 			if (dir->flags & DIR_SHOW_IGNORED)
 				dir_add_name(dir, path.buf, path.len);
+			else if ((dir->flags & DIR_SHOW_IGNORED_TOO) ||
+				((dir->flags & DIR_COLLECT_IGNORED) &&
+				exclude_matches_pathspec(path.buf, path.len,
+					simplify)))
+				dir_add_ignored(dir, path.buf, path.len);
 			break;
 
 		case path_untracked:
diff --git a/dir.h b/dir.h
index bfe726e..3d6b80c 100644
--- a/dir.h
+++ b/dir.h
@@ -79,7 +79,8 @@ struct dir_struct {
 		DIR_SHOW_OTHER_DIRECTORIES = 1<<1,
 		DIR_HIDE_EMPTY_DIRECTORIES = 1<<2,
 		DIR_NO_GITLINKS = 1<<3,
-		DIR_COLLECT_IGNORED = 1<<4
+		DIR_COLLECT_IGNORED = 1<<4,
+		DIR_SHOW_IGNORED_TOO = 1<<5
 	} flags;
 	struct dir_entry **entries;
 	struct dir_entry **ignored;
diff --git a/wt-status.c b/wt-status.c
index 79eb124..7b3cc8e 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -503,9 +503,12 @@ static void wt_status_collect_untracked(struct wt_status *s)
 	if (s->show_untracked_files != SHOW_ALL_UNTRACKED_FILES)
 		dir.flags |=
 			DIR_SHOW_OTHER_DIRECTORIES | DIR_HIDE_EMPTY_DIRECTORIES;
+	if (s->show_ignored_files)
+		dir.flags |= DIR_SHOW_IGNORED_TOO;
 	setup_standard_excludes(&dir);
 
 	fill_directory(&dir, s->pathspec);
+
 	for (i = 0; i < dir.nr; i++) {
 		struct dir_entry *ent = dir.entries[i];
 		if (cache_name_is_other(ent->name, ent->len) &&
@@ -514,22 +517,17 @@ static void wt_status_collect_untracked(struct wt_status *s)
 		free(ent);
 	}
 
-	if (s->show_ignored_files) {
-		dir.nr = 0;
-		dir.flags = DIR_SHOW_IGNORED;
-		if (s->show_untracked_files != SHOW_ALL_UNTRACKED_FILES)
-			dir.flags |= DIR_SHOW_OTHER_DIRECTORIES | DIR_HIDE_EMPTY_DIRECTORIES;
-		fill_directory(&dir, s->pathspec);
-		for (i = 0; i < dir.nr; i++) {
-			struct dir_entry *ent = dir.entries[i];
-			if (cache_name_is_other(ent->name, ent->len) &&
-			    match_pathspec(s->pathspec, ent->name, ent->len, 0, NULL))
-				string_list_insert(&s->ignored, ent->name);
-			free(ent);
-		}
+	for (i = 0; i < dir.ignored_nr; i++) {
+		struct dir_entry *ent = dir.ignored[i];
+		if (cache_name_is_other(ent->name, ent->len) &&
+		    match_pathspec(s->pathspec, ent->name, ent->len, 0, NULL))
+			string_list_insert(&s->ignored, ent->name);
+		free(ent);
 	}
 
 	free(dir.entries);
+	free(dir.ignored);
+	clear_directory(&dir);
 }
 
 void wt_status_collect(struct wt_status *s)
-- 
1.8.1.2.8026.g2b66448.dirty

  parent reply	other threads:[~2013-04-15 19:15 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-03-18 20:28 [PATCH 0/8] Improve git-status --ignored Karsten Blees
2013-03-19  4:08 ` Junio C Hamano
2013-03-19  5:20   ` Duy Nguyen
2013-03-19 10:48     ` Karsten Blees
2013-03-19 14:48     ` Junio C Hamano
2013-03-19 15:58       ` Duy Nguyen
2013-04-15 19:04 ` [PATCH v2 00/14] " Karsten Blees
2013-04-15 19:05   ` [PATCH v2 01/14] dir.c: git-status --ignored: don't drop ignored directories Karsten Blees
2013-04-16 17:33     ` Ramkumar Ramachandra
2013-04-17  0:31       ` Karsten Blees
2013-04-15 19:06   ` [PATCH v2 02/14] dir.c: git-status --ignored: don't list files in " Karsten Blees
2013-04-16  9:57     ` [PATCH] read_revisions_from_stdin: make copies for handle_revision_arg Thomas Rast
2013-04-16 18:17       ` Junio C Hamano
2013-04-15 19:07   ` [PATCH v2 03/14] dir.c: git-status --ignored: don't list empty ignored directories Karsten Blees
2013-04-16 17:48     ` Ramkumar Ramachandra
2013-04-17  0:31       ` Karsten Blees
2013-04-15 19:08   ` [PATCH v2 04/14] dir.c: git-ls-files --directories: don't hide empty directories Karsten Blees
2013-04-15 19:08   ` [PATCH v2 05/14] dir.c: git-status --ignored: don't list empty directories as ignored Karsten Blees
2013-04-15 19:09   ` [PATCH v2 06/14] dir.c: make 'git-status --ignored' work within leading directories Karsten Blees
2013-04-15 19:10   ` [PATCH v2 07/14] dir.c: git-clean -d -X: don't delete tracked directories Karsten Blees
2013-04-15 19:11   ` [PATCH v2 08/14] dir.c: factor out parts of last_exclude_matching for later reuse Karsten Blees
2013-04-15 19:11   ` [PATCH v2 09/14] dir.c: move prep_exclude Karsten Blees
2013-04-15 19:12   ` [PATCH v2 10/14] dir.c: unify is_excluded and is_path_excluded APIs Karsten Blees
2013-04-15 21:35     ` Junio C Hamano
2013-04-15 19:12   ` [PATCH v2 11/14] dir.c: replace is_path_excluded with now equivalent is_excluded API Karsten Blees
2013-04-15 19:13   ` [PATCH v2 12/14] dir.c: git-status: avoid is_excluded checks for tracked files Karsten Blees
2013-04-15 19:14   ` [PATCH v2 13/14] dir.c: git-status --ignored: don't scan the work tree three times Karsten Blees
2013-04-15 19:15   ` Karsten Blees [this message]
2013-04-15 19:23   ` [PATCH v2 00/14] Improve git-status --ignored Junio C Hamano
2013-04-15 19:33     ` Junio C Hamano
2013-04-15 20:06       ` Karsten Blees
2013-04-15 20:25         ` Junio C Hamano
2013-04-17 19:50           ` Karsten Blees
2013-04-17 22:03             ` Junio C Hamano
2013-04-17 19:50           ` [PATCH v2-pu 11/14] dir.c: replace is_path_excluded with now equivalent is_excluded API Karsten Blees
2013-04-17 19:51           ` [PATCH v2-pu 14/14] dir.c: git-status --ignored: don't scan the work tree twice Karsten Blees

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=516C51B7.7080305@gmail.com \
    --to=karsten.blees@gmail.com \
    --cc=apelisse@gmail.com \
    --cc=artagnon@gmail.com \
    --cc=git@adamspiers.org \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=kusmabite@gmail.com \
    --cc=pclouds@gmail.com \
    --cc=robert.allan.zeh@gmail.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.