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 <torvalds@linux-foundation.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Linus Torvalds committed
Jul 9, 2009 at 13:14 UTC
443e061a41bee30de34793648793ed70477ac575
1 file changed
+42
-5
dir.c
+42
-5
@@ -566,18 +566,55 @@ static int in_pathspec(const char *path, int len, const struct path_simplify *si
566
return 0;
567
}
568
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
+
607
static int get_dtype(struct dirent *de, const char *path, int len)
608
{
609
int dtype = de ? DTYPE(de) : DT_UNKNOWN;
572
- struct cache_entry *ce;
610
struct stat st;
611
612
if (dtype != DT_UNKNOWN)
613
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))
618
return dtype;
619
if (S_ISREG(st.st_mode))
620
return DT_REG;