From: Junio C Hamano <gitster@pobox.com>
To: git@vger.kernel.org
Subject: [PATCH 1/6] ls-files -i: pay attention to exclusion of leading paths
Date: Tue, 5 Jun 2012 22:45:14 -0700 [thread overview]
Message-ID: <1338961519-30970-2-git-send-email-gitster@pobox.com> (raw)
In-Reply-To: <1338961519-30970-1-git-send-email-gitster@pobox.com>
"git ls-files --exclude=t/ -i" does not show paths in directory t/
that have been added to the index, but it should.
The excluded() API was designed for callers who walk the tree from
the top, checking each level of the directory hierarchy as it
descends if it is excluded, and not even bothering to recurse into
an excluded directory. This would allow us optimize for a common
case by not having to check if the exclude pattern "foo/" matches
when looking at "foo/bar", because the caller should have noticed
that "foo" is excluded and did not even bother to read "foo/bar"
out of opendir()/readdir() to call it.
The code for "ls-files -i" however walks the index linearly, feeding
paths without checking if the leading directory is already excluded.
Introduce a helper function path_excluded() to let this caller
properly call excluded() check for higher hierarchies as necessary.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
builtin/ls-files.c | 17 +++++++++++------
dir.c | 32 ++++++++++++++++++++++++++++++++
dir.h | 16 ++++++++++++++++
3 files changed, 59 insertions(+), 6 deletions(-)
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 7cff175..90dc360 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -203,6 +203,10 @@ static void show_ru_info(void)
static void show_files(struct dir_struct *dir)
{
int i;
+ struct path_exclude_check check;
+
+ if ((dir->flags & DIR_SHOW_IGNORED))
+ path_exclude_check_init(&check, dir);
/* For cached/deleted files we don't need to even do the readdir */
if (show_others || show_killed) {
@@ -215,9 +219,8 @@ static void show_files(struct dir_struct *dir)
if (show_cached | show_stage) {
for (i = 0; i < active_nr; i++) {
struct cache_entry *ce = active_cache[i];
- int dtype = ce_to_dtype(ce);
- if (dir->flags & DIR_SHOW_IGNORED &&
- !excluded(dir, ce->name, &dtype))
+ if ((dir->flags & DIR_SHOW_IGNORED) &&
+ !path_excluded(&check, ce))
continue;
if (show_unmerged && !ce_stage(ce))
continue;
@@ -232,9 +235,8 @@ static void show_files(struct dir_struct *dir)
struct cache_entry *ce = active_cache[i];
struct stat st;
int err;
- int dtype = ce_to_dtype(ce);
- if (dir->flags & DIR_SHOW_IGNORED &&
- !excluded(dir, ce->name, &dtype))
+ if ((dir->flags & DIR_SHOW_IGNORED) &&
+ !path_excluded(&check, ce))
continue;
if (ce->ce_flags & CE_UPDATE)
continue;
@@ -247,6 +249,9 @@ static void show_files(struct dir_struct *dir)
show_ce_entry(tag_modified, ce);
}
}
+
+ if ((dir->flags & DIR_SHOW_IGNORED))
+ path_exclude_check_clear(&check);
}
/*
diff --git a/dir.c b/dir.c
index 0a78d00..c3f0884 100644
--- a/dir.c
+++ b/dir.c
@@ -580,6 +580,38 @@ int excluded(struct dir_struct *dir, const char *pathname, int *dtype_p)
return 0;
}
+void path_exclude_check_init(struct path_exclude_check *check,
+ struct dir_struct *dir)
+{
+ check->dir = dir;
+ strbuf_init(&check->path, 256);
+}
+
+void path_exclude_check_clear(struct path_exclude_check *check)
+{
+ strbuf_release(&check->path);
+}
+
+int path_excluded(struct path_exclude_check *check, struct cache_entry *ce)
+{
+ int i, dtype;
+ struct strbuf *path = &check->path;
+
+ strbuf_setlen(path, 0);
+ for (i = 0; ce->name[i]; i++) {
+ int ch = ce->name[i];
+
+ if (ch == '/') {
+ dtype = DT_DIR;
+ if (excluded(check->dir, path->buf, &dtype))
+ return 1;
+ }
+ strbuf_addch(path, ch);
+ }
+ dtype = ce_to_dtype(ce);
+ return excluded(check->dir, ce->name, &dtype);
+}
+
static struct dir_entry *dir_entry_new(const char *pathname, int len)
{
struct dir_entry *ent;
diff --git a/dir.h b/dir.h
index dd6947e..7378e69 100644
--- a/dir.h
+++ b/dir.h
@@ -1,6 +1,8 @@
#ifndef DIR_H
#define DIR_H
+#include "strbuf.h"
+
struct dir_entry {
unsigned int len;
char name[FLEX_ARRAY]; /* more */
@@ -78,6 +80,20 @@ extern int excluded_from_list(const char *pathname, int pathlen, const char *bas
int *dtype, struct exclude_list *el);
extern int excluded(struct dir_struct *, const char *, int *);
struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname, int len);
+
+/*
+ * The excluded() API is meant for callers that check each level of leading
+ * directory hierarchies with excluded() to avoid recursing into excluded
+ * directories. Callers that do not do so should use this API instead.
+ */
+struct path_exclude_check {
+ struct dir_struct *dir;
+ struct strbuf path;
+};
+extern void path_exclude_check_init(struct path_exclude_check *, struct dir_struct *);
+extern void path_exclude_check_clear(struct path_exclude_check *);
+extern int path_excluded(struct path_exclude_check *, struct cache_entry *);
+
extern int add_excludes_from_file_to_list(const char *fname, const char *base, int baselen,
char **buf_p, struct exclude_list *which, int check_index);
extern void add_excludes_from_file(struct dir_struct *, const char *fname);
--
1.7.11.rc1.37.g09843ac
next prev parent reply other threads:[~2012-06-06 5:46 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-06-06 5:45 [PATCH 0/6] "ls-files -i" not honoring directory wide ignore Junio C Hamano
2012-06-06 5:45 ` Junio C Hamano [this message]
2012-06-06 5:45 ` [PATCH 2/6] ls-files -i: micro-optimize path_excluded() Junio C Hamano
2012-06-06 5:45 ` [PATCH 3/6] path_excluded(): update API to less cache-entry centric Junio C Hamano
2012-06-06 5:45 ` [PATCH 4/6] builtin/add.c: use path_excluded() Junio C Hamano
2012-06-06 5:45 ` [PATCH 5/6] unpack-trees.c: use path_excluded() in check_ok_to_remove() Junio C Hamano
2012-06-06 5:45 ` [PATCH 6/6] dir.c: make excluded() file scope static Junio C Hamano
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=1338961519-30970-2-git-send-email-gitster@pobox.com \
--to=gitster@pobox.com \
--cc=git@vger.kernel.org \
/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).