Skip to content

Commit 6831a88

Browse files
committed
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>
1 parent d6b8fc3 commit 6831a88

File tree

4 files changed

+23
-15
lines changed

4 files changed

+23
-15
lines changed

builtin-ls-files.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,8 @@ static void show_files(struct dir_struct *dir, const char *prefix)
238238
if (show_cached | show_stage) {
239239
for (i = 0; i < active_nr; i++) {
240240
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)
243243
continue;
244244
if (show_unmerged && !ce_stage(ce))
245245
continue;
@@ -253,8 +253,8 @@ static void show_files(struct dir_struct *dir, const char *prefix)
253253
struct cache_entry *ce = active_cache[i];
254254
struct stat st;
255255
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)
258258
continue;
259259
err = lstat(ce->name, &st);
260260
if (show_deleted && err)

dir.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ struct path_simplify {
1717
static int read_directory_recursive(struct dir_struct *dir,
1818
const char *path, const char *base, int baselen,
1919
int check_only, const struct path_simplify *simplify);
20+
static int get_dtype(struct dirent *de, const char *path);
2021

2122
int common_prefix(const char **pathspec)
2223
{
@@ -277,7 +278,7 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
277278
* Return 1 for exclude, 0 for include and -1 for undecided.
278279
*/
279280
static int excluded_1(const char *pathname,
280-
int pathlen, const char *basename, int dtype,
281+
int pathlen, const char *basename, int *dtype,
281282
struct exclude_list *el)
282283
{
283284
int i;
@@ -288,9 +289,12 @@ static int excluded_1(const char *pathname,
288289
const char *exclude = x->pattern;
289290
int to_exclude = x->to_exclude;
290291

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+
}
294298

295299
if (x->flags & EXC_FLAG_NODIR) {
296300
/* match basename */
@@ -334,7 +338,7 @@ static int excluded_1(const char *pathname,
334338
return -1; /* undecided */
335339
}
336340

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)
338342
{
339343
int pathlen = strlen(pathname);
340344
int st;
@@ -344,7 +348,7 @@ int excluded(struct dir_struct *dir, const char *pathname, int dtype)
344348
prep_exclude(dir, pathname, basename-pathname);
345349
for (st = EXC_CMDL; st <= EXC_FILE; st++) {
346350
switch (excluded_1(pathname, pathlen, basename,
347-
dtype, &dir->exclude_list[st])) {
351+
dtype_p, &dir->exclude_list[st])) {
348352
case 0:
349353
return 0;
350354
case 1:
@@ -529,7 +533,7 @@ static int in_pathspec(const char *path, int len, const struct path_simplify *si
529533

530534
static int get_dtype(struct dirent *de, const char *path)
531535
{
532-
int dtype = DTYPE(de);
536+
int dtype = de ? DTYPE(de) : DT_UNKNOWN;
533537
struct stat st;
534538

535539
if (dtype != DT_UNKNOWN)
@@ -581,8 +585,8 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co
581585
if (simplify_away(fullname, baselen + len, simplify))
582586
continue;
583587

584-
dtype = get_dtype(de, fullname);
585-
exclude = excluded(dir, fullname, dtype);
588+
dtype = DTYPE(de);
589+
exclude = excluded(dir, fullname, &dtype);
586590
if (exclude && dir->collect_ignored
587591
&& in_pathspec(fullname, baselen + len, simplify))
588592
dir_add_ignored(dir, fullname, baselen + len);
@@ -594,6 +598,9 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co
594598
if (exclude && !dir->show_ignored)
595599
continue;
596600

601+
if (dtype == DT_UNKNOWN)
602+
dtype = get_dtype(de, fullname);
603+
597604
/*
598605
* Do we want to see just the ignored files?
599606
* We still need to recurse into directories,

dir.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ extern int match_pathspec(const char **pathspec, const char *name, int namelen,
6868

6969
extern int read_directory(struct dir_struct *, const char *path, const char *base, int baselen, const char **pathspec);
7070

71-
extern int excluded(struct dir_struct *, const char *, int);
71+
extern int excluded(struct dir_struct *, const char *, int *);
7272
extern void add_excludes_from_file(struct dir_struct *, const char *fname);
7373
extern void add_exclude(const char *string, const char *base,
7474
int baselen, struct exclude_list *which);

unpack-trees.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -522,8 +522,9 @@ static void verify_absent(struct cache_entry *ce, const char *action,
522522

523523
if (!lstat(ce->name, &st)) {
524524
int cnt;
525+
int dtype = ce_to_dtype(ce);
525526

526-
if (o->dir && excluded(o->dir, ce->name, ce_to_dtype(ce)))
527+
if (o->dir && excluded(o->dir, ce->name, &dtype))
527528
/*
528529
* ce->name is explicitly excluded, so it is Ok to
529530
* overwrite it.

0 commit comments

Comments
 (0)