From 7fe1ffdafa56b8453a47a40b866d029f24a56d76 Mon Sep 17 00:00:00 2001 From: Elijah Newren Date: Wed, 12 May 2021 17:28:15 +0000 Subject: dir: report number of visited directories and paths with trace2 Provide more statistics in trace2 output that include the number of directories and total paths visited by the directory traversal logic. Subsequent patches will take advantage of this to ensure we do not unnecessarily traverse into ignored directories. Signed-off-by: Elijah Newren Signed-off-by: Junio C Hamano --- dir.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'dir.h') diff --git a/dir.h b/dir.h index facfae4740..70c750e305 100644 --- a/dir.h +++ b/dir.h @@ -336,6 +336,10 @@ struct dir_struct { struct oid_stat ss_info_exclude; struct oid_stat ss_excludes_file; unsigned unmanaged_exclude_files; + + /* Stats about the traversal */ + unsigned visited_paths; + unsigned visited_directories; }; /*Count the number of slashes for string s*/ -- cgit v1.3 From b548f0f1568f6b01e55ca69c24d3cb19489f92aa Mon Sep 17 00:00:00 2001 From: Elijah Newren Date: Wed, 12 May 2021 17:28:22 +0000 Subject: dir: introduce readdir_skip_dot_and_dotdot() helper Many places in the code were doing while ((d = readdir(dir)) != NULL) { if (is_dot_or_dotdot(d->d_name)) continue; ...process d... } Introduce a readdir_skip_dot_and_dotdot() helper to make that a one-liner: while ((d = readdir_skip_dot_and_dotdot(dir)) != NULL) { ...process d... } This helper particularly simplifies checks for empty directories. Also use this helper in read_cached_dir() so that our statistics are consistent across platforms. (In other words, read_cached_dir() should have been using is_dot_or_dotdot() and skipping such entries, but did not and left it to treat_path() to detect and mark such entries as path_none.) Signed-off-by: Elijah Newren Signed-off-by: Junio C Hamano --- builtin/clean.c | 4 +--- builtin/worktree.c | 4 +--- diff-no-index.c | 5 ++--- dir.c | 26 +++++++++++++++++--------- dir.h | 2 ++ entry.c | 5 +---- notes-merge.c | 5 +---- object-file.c | 4 +--- packfile.c | 5 +---- rerere.c | 4 +--- worktree.c | 12 +++--------- 11 files changed, 31 insertions(+), 45 deletions(-) (limited to 'dir.h') diff --git a/builtin/clean.c b/builtin/clean.c index 995053b791..a1a5747615 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -189,10 +189,8 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag, strbuf_complete(path, '/'); len = path->len; - while ((e = readdir(dir)) != NULL) { + while ((e = readdir_skip_dot_and_dotdot(dir)) != NULL) { struct stat st; - if (is_dot_or_dotdot(e->d_name)) - continue; strbuf_setlen(path, len); strbuf_addstr(path, e->d_name); diff --git a/builtin/worktree.c b/builtin/worktree.c index 1cd5c2016e..e081ca9bef 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -118,10 +118,8 @@ static void prune_worktrees(void) struct dirent *d; if (!dir) return; - while ((d = readdir(dir)) != NULL) { + while ((d = readdir_skip_dot_and_dotdot(dir)) != NULL) { char *path; - if (is_dot_or_dotdot(d->d_name)) - continue; strbuf_reset(&reason); if (should_prune_worktree(d->d_name, &reason, &path, expire)) prune_worktree(d->d_name, reason.buf); diff --git a/diff-no-index.c b/diff-no-index.c index 7814eabfe0..e5cc878371 100644 --- a/diff-no-index.c +++ b/diff-no-index.c @@ -26,9 +26,8 @@ static int read_directory_contents(const char *path, struct string_list *list) if (!(dir = opendir(path))) return error("Could not open directory %s", path); - while ((e = readdir(dir))) - if (!is_dot_or_dotdot(e->d_name)) - string_list_insert(list, e->d_name); + while ((e = readdir_skip_dot_and_dotdot(dir))) + string_list_insert(list, e->d_name); closedir(dir); return 0; diff --git a/dir.c b/dir.c index ff004b298b..e47b4c507f 100644 --- a/dir.c +++ b/dir.c @@ -59,6 +59,18 @@ void dir_init(struct dir_struct *dir) memset(dir, 0, sizeof(*dir)); } +struct dirent * +readdir_skip_dot_and_dotdot(DIR *dirp) +{ + struct dirent *e; + + while ((e = readdir(dirp)) != NULL) { + if (!is_dot_or_dotdot(e->d_name)) + break; + } + return e; +} + int count_slashes(const char *s) { int cnt = 0; @@ -2332,7 +2344,7 @@ static int read_cached_dir(struct cached_dir *cdir) struct dirent *de; if (cdir->fdir) { - de = readdir(cdir->fdir); + de = readdir_skip_dot_and_dotdot(cdir->fdir); if (!de) { cdir->d_name = NULL; cdir->d_type = DT_UNKNOWN; @@ -2931,11 +2943,9 @@ int is_empty_dir(const char *path) if (!dir) return 0; - while ((e = readdir(dir)) != NULL) - if (!is_dot_or_dotdot(e->d_name)) { - ret = 0; - break; - } + e = readdir_skip_dot_and_dotdot(dir); + if (e) + ret = 0; closedir(dir); return ret; @@ -2975,10 +2985,8 @@ static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up) strbuf_complete(path, '/'); len = path->len; - while ((e = readdir(dir)) != NULL) { + while ((e = readdir_skip_dot_and_dotdot(dir)) != NULL) { struct stat st; - if (is_dot_or_dotdot(e->d_name)) - continue; strbuf_setlen(path, len); strbuf_addstr(path, e->d_name); diff --git a/dir.h b/dir.h index 70c750e305..6b3fac0829 100644 --- a/dir.h +++ b/dir.h @@ -342,6 +342,8 @@ struct dir_struct { unsigned visited_directories; }; +struct dirent *readdir_skip_dot_and_dotdot(DIR *dirp); + /*Count the number of slashes for string s*/ int count_slashes(const char *s); diff --git a/entry.c b/entry.c index 7b9f43716f..e3d3add300 100644 --- a/entry.c +++ b/entry.c @@ -56,12 +56,9 @@ static void remove_subtree(struct strbuf *path) if (!dir) die_errno("cannot opendir '%s'", path->buf); - while ((de = readdir(dir)) != NULL) { + while ((de = readdir_skip_dot_and_dotdot(dir)) != NULL) { struct stat st; - if (is_dot_or_dotdot(de->d_name)) - continue; - strbuf_addch(path, '/'); strbuf_addstr(path, de->d_name); if (lstat(path->buf, &st)) diff --git a/notes-merge.c b/notes-merge.c index d2771fa3d4..e9d6f86d34 100644 --- a/notes-merge.c +++ b/notes-merge.c @@ -695,13 +695,10 @@ int notes_merge_commit(struct notes_merge_options *o, strbuf_addch(&path, '/'); baselen = path.len; - while ((e = readdir(dir)) != NULL) { + while ((e = readdir_skip_dot_and_dotdot(dir)) != NULL) { struct stat st; struct object_id obj_oid, blob_oid; - if (is_dot_or_dotdot(e->d_name)) - continue; - if (get_oid_hex(e->d_name, &obj_oid)) { if (o->verbosity >= 3) printf("Skipping non-SHA1 entry '%s%s'\n", diff --git a/object-file.c b/object-file.c index 624af408cd..77bdcfd21b 100644 --- a/object-file.c +++ b/object-file.c @@ -2304,10 +2304,8 @@ int for_each_file_in_obj_subdir(unsigned int subdir_nr, strbuf_addch(path, '/'); baselen = path->len; - while ((de = readdir(dir))) { + while ((de = readdir_skip_dot_and_dotdot(dir))) { size_t namelen; - if (is_dot_or_dotdot(de->d_name)) - continue; namelen = strlen(de->d_name); strbuf_setlen(path, baselen); diff --git a/packfile.c b/packfile.c index ea29f4ba77..463d61c877 100644 --- a/packfile.c +++ b/packfile.c @@ -813,10 +813,7 @@ void for_each_file_in_pack_dir(const char *objdir, } strbuf_addch(&path, '/'); dirnamelen = path.len; - while ((de = readdir(dir)) != NULL) { - if (is_dot_or_dotdot(de->d_name)) - continue; - + while ((de = readdir_skip_dot_and_dotdot(dir)) != NULL) { strbuf_setlen(&path, dirnamelen); strbuf_addstr(&path, de->d_name); diff --git a/rerere.c b/rerere.c index dee60dc6df..d83d58df4f 100644 --- a/rerere.c +++ b/rerere.c @@ -1190,13 +1190,11 @@ void rerere_gc(struct repository *r, struct string_list *rr) if (!dir) die_errno(_("unable to open rr-cache directory")); /* Collect stale conflict IDs ... */ - while ((e = readdir(dir))) { + while ((e = readdir_skip_dot_and_dotdot(dir))) { struct rerere_dir *rr_dir; struct rerere_id id; int now_empty; - if (is_dot_or_dotdot(e->d_name)) - continue; if (!is_rr_cache_dirname(e->d_name)) continue; /* or should we remove e->d_name? */ diff --git a/worktree.c b/worktree.c index f35ac40a84..237517baee 100644 --- a/worktree.c +++ b/worktree.c @@ -128,10 +128,8 @@ struct worktree **get_worktrees(void) dir = opendir(path.buf); strbuf_release(&path); if (dir) { - while ((d = readdir(dir)) != NULL) { + while ((d = readdir_skip_dot_and_dotdot(dir)) != NULL) { struct worktree *linked = NULL; - if (is_dot_or_dotdot(d->d_name)) - continue; if ((linked = get_linked_worktree(d->d_name))) { ALLOC_GROW(list, counter + 1, alloc); @@ -486,13 +484,9 @@ int submodule_uses_worktrees(const char *path) if (!dir) return 0; - while ((d = readdir(dir)) != NULL) { - if (is_dot_or_dotdot(d->d_name)) - continue; - + d = readdir_skip_dot_and_dotdot(dir); + if (d != NULL) ret = 1; - break; - } closedir(dir); return ret; } -- cgit v1.3