> > + ce = cache_name_exists(path, len, 0); > > + if (ce) { > > + if (ce_uptodate(ce)) > > + return ce->ce_mode; > > You return ce->ce_mode for up-to-date entries. I do not remember what > ce_uptodate(ce) says for gitlinks, but ce->ce_mode for them would be > 160000 that is not very kosher to give to S_ISDIR(). I realize that this > worry actually applies to your patch from yesterday, the one Dmitry > already tested. Yeah. I guess we don't have a lot of coverage for subprojects. Here's an alternative version that just makes the thing return the DT_xyz flag rather than the mode (and it returns DT_REG for symlinks too, because it knows nobody cares - we only really care about "directory or not") Linus --- dir.c | 47 ++++++++++++++++++++++++++++++++++++++++++----- 1 files changed, 42 insertions(+), 5 deletions(-) diff --git a/dir.c b/dir.c index 8a9e7d8..e05b850 100644 --- a/dir.c +++ b/dir.c @@ -566,18 +566,55 @@ static int in_pathspec(const char *path, int len, const struct path_simplify *si return 0; } +static int get_index_dtype(const char *path, int len) +{ + int pos; + struct cache_entry *ce; + + ce = cache_name_exists(path, len, 0); + if (ce) { + if (!ce_uptodate(ce)) + return DT_UNKNOWN; + if (S_ISGITLINK(ce->ce_mode)) + return DT_DIR; + /* + * Nobody actually cares about the + * difference between DT_LNK and DT_REG + */ + return DT_REG; + } + + /* Try to look it up as a directory */ + pos = cache_name_pos(path, len); + if (pos >= 0) + return DT_UNKNOWN; + pos = -pos-1; + while (pos < active_nr) { + ce = active_cache[pos++]; + if (strncmp(ce->name, path, len)) + break; + if (ce->name[len] > '/') + break; + if (ce->name[len] < '/') + continue; + if (!ce_uptodate(ce)) + break; /* continue? */ + return DT_DIR; + } + return DT_UNKNOWN; +} + static int get_dtype(struct dirent *de, const char *path, int len) { int dtype = de ? DTYPE(de) : DT_UNKNOWN; - struct cache_entry *ce; struct stat st; if (dtype != DT_UNKNOWN) return dtype; - ce = cache_name_exists(path, len, 0); - if (ce && ce_uptodate(ce)) - st.st_mode = ce->ce_mode; - else if (lstat(path, &st)) + dtype = get_index_dtype(path, len); + if (dtype != DT_UNKNOWN) + return dtype; + if (lstat(path, &st)) return dtype; if (S_ISREG(st.st_mode)) return DT_REG; -- 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