On Tue, Mar 09, 2010 at 05:37:30PM -0500, Jeff King wrote: > No, we would still be correct if we recurse into the ignored directory > _only_ to collect the ignored bits (so we don't even bother if > COLLECT_IGNORED isn't set). But what I don't like is that you take a > performance hit, because in most cases you won't ever care what's inside > those directories. You need to recurse only when: > > - you actually care about all files. git-add does. git-status does not > (unless you explicitly told it to show directories). So that would > probably need a flag passed to fill_directory. > > - you have a pathspec that means the contents of the directory might > be interesting. Right now we check in_pathspec in treat_one_path. > But I think we would need to recognize that "subdir/file" is > means "subdir" is in our pathspec (and that "sub*" means the same > thing). Actually, if we accept that the message simply mentions the excluded path, i.e.: $ git add subdir/file The following paths are ignored by one of your .gitignore files: subdir Use -f if you really want to add them. then we don't really need to recurse. We just need to fix in_pathspec to flag files that are _relevant_ to a pathspec. And something like this seems to fix the OP's problem: diff --git a/dir.c b/dir.c index 00d698d..5091bfd 100644 --- a/dir.c +++ b/dir.c @@ -554,13 +554,17 @@ static int simplify_away(const char *path, int pathlen, const struct path_simpli return 0; } -static int in_pathspec(const char *path, int len, const struct path_simplify *simplify) +static int relevant_pathspec(const char *path, int len, const struct path_simplify *simplify) { if (simplify) { for (; simplify->path; simplify++) { if (len == simplify->len && !memcmp(path, simplify->path, len)) return 1; + if (len < simplify->len + && simplify->path[len] == '/' + && !memcmp(path, simplify->path, len)) + return 1; } } return 0; @@ -638,7 +642,7 @@ static enum path_treatment treat_one_path(struct dir_struct *dir, { int exclude = excluded(dir, path, &dtype); if (exclude && (dir->flags & DIR_COLLECT_IGNORED) - && in_pathspec(path, *len, simplify)) + && relevant_pathspec(path, *len, simplify)) dir_add_ignored(dir, path, *len); /* Which is similar to your fix, but hoisted into the ignore-collection phase. Like the original code and your patch, it suffers from using a straight memcmp. I think it should actually be checking the pathspec expansion to catch things like 'sub*/file' being relevant to 'subdir'. -Peff -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html