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

Re: [PATCH] gitignore(5): Allow "foo/" in ignore list to match directory "foo"

From
Jeff King <peff@peff.net>
Date
Jan 31, 2008, 09:41 UTC
Message-ID
<20080131094124.GA25546@coredump.intra.peff.net>
In-Reply-To
<7v63xae4lf.fsf_-_@gitster.siamese.dyndns.org>
On Thu, Jan 31, 2008 at 01:17:48AM -0800, Junio C Hamano wrote:
Show 5 quoted lines
> A downside is that the recursive directory walk may need to run
> lstat(2) more often on systems whose "struct dirent" do not give
> the type of the entry; earlier it did not have to do so for an
> excluded path, but we now need to figure out if a path is a
> directory before deciding to exclude it.  This is especially bad

You can at least lazily do the stat so that only users of foo/ need to pay the penalty. Something like this (completely untested):

diff --git a/dir.c b/dir.c
index a4f8c25..9487908 100644
--- a/dir.c
+++ b/dir.c
@@ -17,6 +17,7 @@ struct path_simplify {
 static int read_directory_recursive(struct dir_struct *dir,
 	const char *path, const char *base, int baselen,
 	int check_only, const struct path_simplify *simplify);
+static int get_dtype(struct dirent *de, const char *path, int try_stat);
 
 int common_prefix(const char **pathspec)
 {
@@ -288,9 +289,12 @@ static int excluded_1(const char *pathname,
 			const char *exclude = x->pattern;
 			int to_exclude = x->to_exclude;
 
-			if ((x->flags & EXC_FLAG_MUSTBEDIR) &&
-			    (dtype != DT_DIR))
-				continue;
+			if (x->flags & EXC_FLAG_MUSTBEDIR) {
+				if (dtype == DT_UNKNOWN)
+					dtype = get_dtype(NULL, pathname, 1);
+				if (dtype != DT_DIR)
+					continue;
+			}
 
 			if (x->flags & EXC_FLAG_NODIR) {
 				/* match basename */
@@ -527,13 +531,15 @@ static int in_pathspec(const char *path, int len, const struct path_simplify *si
 	return 0;
 }
 
-static int get_dtype(struct dirent *de, const char *path)
+static int get_dtype(struct dirent *de, const char *path, int try_stat)
 {
-	int dtype = DTYPE(de);
+	int dtype = de ? DTYPE(de) : DT_UNKNOWN;
 	struct stat st;
 
 	if (dtype != DT_UNKNOWN)
 		return dtype;
+	if (!try_stat)
+		return DT_UNKNOWN;
 	if (lstat(path, &st))
 		return dtype;
 	if (S_ISREG(st.st_mode))
@@ -581,7 +587,7 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co
 			if (simplify_away(fullname, baselen + len, simplify))
 				continue;
 
-			dtype = get_dtype(de, fullname);
+			dtype = get_dtype(de, fullname, 0);
 			exclude = excluded(dir, fullname, dtype);
 			if (exclude && dir->collect_ignored
 			    && in_pathspec(fullname, baselen + len, simplify))
Previous: Junio C HamanoNext: Junio C Hamano
Message 11 of 20 in “Why does git track directory listed in .gitignore/".git/info/exclude"?”
  1. pradeep singh rautelaJan 23, 2008
  2. pradeep singh rautelaJan 23, 2008
  3. Linus TorvaldsJan 23, 2008
  4. pradeep singh rautelaJan 24, 2008
  5. Adam PiatyszekJan 30, 2008
  6. Junio C HamanoJan 30, 2008
  7. Junio C HamanoJan 30, 2008
  8. Adam PiatyszekJan 31, 2008
  9. *Re: Why does git track directory listed in .gitignore/".git/info/exclude"?Junio C Hamano, Jan 31, 2008
  10. gitignore(5): Allow "foo/" in ignore list to match directory "foo"Junio C Hamano, Jan 31, 2008
  11. Jeff KingJan 31, 2008
  12. Junio C HamanoJan 31, 2008
  13. Jeff KingJan 31, 2008
  14. Johannes SchindelinJan 31, 2008
  15. pradeep singh rautelaJan 31, 2008
  16. Junio C HamanoJan 31, 2008
  17. Adam PiatyszekJan 31, 2008
  18. Andreas EricssonFeb 1, 2008
  19. Adam PiatyszekJan 31, 2008
  20. Wayne DavisonJan 23, 2008

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.