This cuts down a signficant number of open(.gitignore) because most
directories usually don't have .gitignore files.
---
 dir.c | 26 +++++++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/dir.c b/dir.c
index 63fa960..b5bfda8 100644
--- a/dir.c
+++ b/dir.c
@@ -1021,7 +1021,21 @@ static void prep_exclude(struct dir_struct *dir, const 
char *base, int baselen)
 
                /* Try to read per-directory file */
                hashclr(sha1);
-               if (dir->exclude_per_dir) {
+               if (dir->exclude_per_dir &&
+                   /*
+                    * If we know that no files have been added in
+                    * this directory (i.e. valid_cached_dir() has
+                    * been executed and set untracked->valid) ..
+                    */
+                   (!untracked || !untracked->valid ||
+                    /*
+                     * .. and .gitignore does not exist before
+                     * (i.e. null exclude_sha1 and skip_worktree is
+                     * not set). Then we can skip loading .gitignore,
+                     * which would result in ENOENT anyway.
+                     * skip_worktree is taken care in read_directory()
+                     */
+                    !is_null_sha1(untracked->exclude_sha1))) {
                        /*
                         * dir->basebuf gets reused by the traversal, but we
                         * need fname to remain unchanged to ensure the src
@@ -1788,6 +1802,7 @@ static struct untracked_cache_dir 
*validate_untracked_cache(struct dir_struct *d
                                                      const struct pathspec 
*pathspec)
 {
        struct untracked_cache_dir *root;
+       int i;
 
        if (!dir->untracked)
                return NULL;
@@ -1839,6 +1854,15 @@ static struct untracked_cache_dir 
*validate_untracked_cache(struct dir_struct *d
        if (dir->exclude_list_group[EXC_CMDL].nr)
                return NULL;
 
+       /*
+        * An optimization in prep_exclude() does not play well with
+        * CE_SKIP_WORKTREE. It's a rare case anyway, if a single
+        * entry has that bit set, disable the whole untracked cache.
+        */
+       for (i = 0; i < active_nr; i++)
+               if (ce_skip_worktree(active_cache[i]))
+                       return NULL;
+
        if (!dir->untracked->root) {
                const int len = sizeof(*dir->untracked->root);
                dir->untracked->root = xmalloc(len);
-- 
1.9.1.346.ga2b5940

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to