@matheusbsbs / matheus-bagliano / commits / 6831a88ac0
Fork 0

gitignore: lazily find dtype

When we process "foo/" entries in gitignore files on a system that does not have d_type member in "struct dirent", the earlier implementation ran lstat(2) separately when matching with entries that came from the command line, in-tree .gitignore files, and $GIT_DIR/info/excludes file. This optimizes it by delaying the lstat(2) call until it becomes absolutely necessary. The initial idea for this change was by Jeff King, but I optimized it further to pass pointers to around. Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Jan 31, 2008 at 20:23 UTC 6831a88ac03759a8133f10ffd52ad235a081a8a3
4 files changed +23 -15
builtin-ls-files.c
+4 -4
@@ -238,8 +238,8 @@ static void show_files(struct dir_struct *dir, const char *prefix)
238 if (show_cached | show_stage) {
239 for (i = 0; i < active_nr; i++) {
240 struct cache_entry *ce = active_cache[i];
241 - if (excluded(dir, ce->name, ce_to_dtype(ce)) !=
242 - dir->show_ignored)
241 + int dtype = ce_to_dtype(ce);
242 + if (excluded(dir, ce->name, &dtype) != dir->show_ignored)
243 continue;
244 if (show_unmerged && !ce_stage(ce))
245 continue;
@@ -253,8 +253,8 @@ static void show_files(struct dir_struct *dir, const char *prefix)
253 struct cache_entry *ce = active_cache[i];
254 struct stat st;
255 int err;
256 - if (excluded(dir, ce->name, ce_to_dtype(ce)) !=
257 - dir->show_ignored)
256 + int dtype = ce_to_dtype(ce);
257 + if (excluded(dir, ce->name, &dtype) != dir->show_ignored)
258 continue;
259 err = lstat(ce->name, &st);
260 if (show_deleted && err)
dir.c
+16 -9
@@ -17,6 +17,7 @@ struct path_simplify {
17 static int read_directory_recursive(struct dir_struct *dir,
18 const char *path, const char *base, int baselen,
19 int check_only, const struct path_simplify *simplify);
20 +static int get_dtype(struct dirent *de, const char *path);
21
22 int common_prefix(const char **pathspec)
23 {
@@ -277,7 +278,7 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
278 * Return 1 for exclude, 0 for include and -1 for undecided.
279 */
280 static int excluded_1(const char *pathname,
280 - int pathlen, const char *basename, int dtype,
281 + int pathlen, const char *basename, int *dtype,
282 struct exclude_list *el)
283 {
284 int i;
@@ -288,9 +289,12 @@ static int excluded_1(const char *pathname,
289 const char *exclude = x->pattern;
290 int to_exclude = x->to_exclude;
291
291 - if ((x->flags & EXC_FLAG_MUSTBEDIR) &&
292 - (dtype != DT_DIR))
293 - continue;
292 + if (x->flags & EXC_FLAG_MUSTBEDIR) {
293 + if (*dtype == DT_UNKNOWN)
294 + *dtype = get_dtype(NULL, pathname);
295 + if (*dtype != DT_DIR)
296 + continue;
297 + }
298
299 if (x->flags & EXC_FLAG_NODIR) {
300 /* match basename */
@@ -334,7 +338,7 @@ static int excluded_1(const char *pathname,
338 return -1; /* undecided */
339 }
340
337 -int excluded(struct dir_struct *dir, const char *pathname, int dtype)
341 +int excluded(struct dir_struct *dir, const char *pathname, int *dtype_p)
342 {
343 int pathlen = strlen(pathname);
344 int st;
@@ -344,7 +348,7 @@ int excluded(struct dir_struct *dir, const char *pathname, int dtype)
348 prep_exclude(dir, pathname, basename-pathname);
349 for (st = EXC_CMDL; st <= EXC_FILE; st++) {
350 switch (excluded_1(pathname, pathlen, basename,
347 - dtype, &dir->exclude_list[st])) {
351 + dtype_p, &dir->exclude_list[st])) {
352 case 0:
353 return 0;
354 case 1:
@@ -529,7 +533,7 @@ static int in_pathspec(const char *path, int len, const struct path_simplify *si
533
534 static int get_dtype(struct dirent *de, const char *path)
535 {
532 - int dtype = DTYPE(de);
536 + int dtype = de ? DTYPE(de) : DT_UNKNOWN;
537 struct stat st;
538
539 if (dtype != DT_UNKNOWN)
@@ -581,8 +585,8 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co
585 if (simplify_away(fullname, baselen + len, simplify))
586 continue;
587
584 - dtype = get_dtype(de, fullname);
585 - exclude = excluded(dir, fullname, dtype);
588 + dtype = DTYPE(de);
589 + exclude = excluded(dir, fullname, &dtype);
590 if (exclude && dir->collect_ignored
591 && in_pathspec(fullname, baselen + len, simplify))
592 dir_add_ignored(dir, fullname, baselen + len);
@@ -594,6 +598,9 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co
598 if (exclude && !dir->show_ignored)
599 continue;
600
601 + if (dtype == DT_UNKNOWN)
602 + dtype = get_dtype(de, fullname);
603 +
604 /*
605 * Do we want to see just the ignored files?
606 * We still need to recurse into directories,
dir.h
+1 -1
@@ -68,7 +68,7 @@ extern int match_pathspec(const char **pathspec, const char *name, int namelen,
68
69 extern int read_directory(struct dir_struct *, const char *path, const char *base, int baselen, const char **pathspec);
70
71 -extern int excluded(struct dir_struct *, const char *, int);
71 +extern int excluded(struct dir_struct *, const char *, int *);
72 extern void add_excludes_from_file(struct dir_struct *, const char *fname);
73 extern void add_exclude(const char *string, const char *base,
74 int baselen, struct exclude_list *which);
unpack-trees.c
+2 -1
@@ -522,8 +522,9 @@ static void verify_absent(struct cache_entry *ce, const char *action,
522
523 if (!lstat(ce->name, &st)) {
524 int cnt;
525 + int dtype = ce_to_dtype(ce);
526
526 - if (o->dir && excluded(o->dir, ce->name, ce_to_dtype(ce)))
527 + if (o->dir && excluded(o->dir, ce->name, &dtype))
528 /*
529 * ce->name is explicitly excluded, so it is Ok to
530 * overwrite it.