Skip to content

Commit 443e061

Browse files
torvaldsgitster
authored andcommitted
Avoid using 'lstat()' to figure out directories
If we have an up-to-date index entry for a file in that directory, we can know that the directories leading up to that file must be directories. No need to do an lstat() on the directory. Signed-off-by: Linus Torvalds <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent caa6b78 commit 443e061

File tree

1 file changed

+42
-5
lines changed

1 file changed

+42
-5
lines changed

dir.c

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -566,18 +566,55 @@ static int in_pathspec(const char *path, int len, const struct path_simplify *si
566566
return 0;
567567
}
568568

569+
static int get_index_dtype(const char *path, int len)
570+
{
571+
int pos;
572+
struct cache_entry *ce;
573+
574+
ce = cache_name_exists(path, len, 0);
575+
if (ce) {
576+
if (!ce_uptodate(ce))
577+
return DT_UNKNOWN;
578+
if (S_ISGITLINK(ce->ce_mode))
579+
return DT_DIR;
580+
/*
581+
* Nobody actually cares about the
582+
* difference between DT_LNK and DT_REG
583+
*/
584+
return DT_REG;
585+
}
586+
587+
/* Try to look it up as a directory */
588+
pos = cache_name_pos(path, len);
589+
if (pos >= 0)
590+
return DT_UNKNOWN;
591+
pos = -pos-1;
592+
while (pos < active_nr) {
593+
ce = active_cache[pos++];
594+
if (strncmp(ce->name, path, len))
595+
break;
596+
if (ce->name[len] > '/')
597+
break;
598+
if (ce->name[len] < '/')
599+
continue;
600+
if (!ce_uptodate(ce))
601+
break; /* continue? */
602+
return DT_DIR;
603+
}
604+
return DT_UNKNOWN;
605+
}
606+
569607
static int get_dtype(struct dirent *de, const char *path, int len)
570608
{
571609
int dtype = de ? DTYPE(de) : DT_UNKNOWN;
572-
struct cache_entry *ce;
573610
struct stat st;
574611

575612
if (dtype != DT_UNKNOWN)
576613
return dtype;
577-
ce = cache_name_exists(path, len, 0);
578-
if (ce && ce_uptodate(ce))
579-
st.st_mode = ce->ce_mode;
580-
else if (lstat(path, &st))
614+
dtype = get_index_dtype(path, len);
615+
if (dtype != DT_UNKNOWN)
616+
return dtype;
617+
if (lstat(path, &st))
581618
return dtype;
582619
if (S_ISREG(st.st_mode))
583620
return DT_REG;

0 commit comments

Comments
 (0)