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 <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Elijah Newren committed May 27, 2021 at 04:53 UTC 906fc557b70b2b2995785c9b37e212d2f86b469e
11 files changed +30 -45
builtin/clean.c
+1 -3
@@ -189,10 +189,8 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
189 strbuf_complete(path, '/');
190
191 len = path->len;
192 - while ((e = readdir(dir)) != NULL) {
192 + while ((e = readdir_skip_dot_and_dotdot(dir)) != NULL) {
193 struct stat st;
194 - if (is_dot_or_dotdot(e->d_name))
195 - continue;
194
195 strbuf_setlen(path, len);
196 strbuf_addstr(path, e->d_name);
builtin/worktree.c
+1 -3
@@ -118,10 +118,8 @@ static void prune_worktrees(void)
118 struct dirent *d;
119 if (!dir)
120 return;
121 - while ((d = readdir(dir)) != NULL) {
121 + while ((d = readdir_skip_dot_and_dotdot(dir)) != NULL) {
122 char *path;
123 - if (is_dot_or_dotdot(d->d_name))
124 - continue;
123 strbuf_reset(&reason);
124 if (should_prune_worktree(d->d_name, &reason, &path, expire))
125 prune_worktree(d->d_name, reason.buf);
diff-no-index.c
+2 -3
@@ -26,9 +26,8 @@ static int read_directory_contents(const char *path, struct string_list *list)
26 if (!(dir = opendir(path)))
27 return error("Could not open directory %s", path);
28
29 - while ((e = readdir(dir)))
30 - if (!is_dot_or_dotdot(e->d_name))
31 - string_list_insert(list, e->d_name);
29 + while ((e = readdir_skip_dot_and_dotdot(dir)))
30 + string_list_insert(list, e->d_name);
31
32 closedir(dir);
33 return 0;
dir.c
+16 -9
@@ -59,6 +59,17 @@ void dir_init(struct dir_struct *dir)
59 memset(dir, 0, sizeof(*dir));
60 }
61
62 +struct dirent *readdir_skip_dot_and_dotdot(DIR *dirp)
63 +{
64 + struct dirent *e;
65 +
66 + while ((e = readdir(dirp)) != NULL) {
67 + if (!is_dot_or_dotdot(e->d_name))
68 + break;
69 + }
70 + return e;
71 +}
72 +
73 int count_slashes(const char *s)
74 {
75 int cnt = 0;
@@ -2332,7 +2343,7 @@ static int read_cached_dir(struct cached_dir *cdir)
2343 struct dirent *de;
2344
2345 if (cdir->fdir) {
2335 - de = readdir(cdir->fdir);
2346 + de = readdir_skip_dot_and_dotdot(cdir->fdir);
2347 if (!de) {
2348 cdir->d_name = NULL;
2349 cdir->d_type = DT_UNKNOWN;
@@ -2931,11 +2942,9 @@ int is_empty_dir(const char *path)
2942 if (!dir)
2943 return 0;
2944
2934 - while ((e = readdir(dir)) != NULL)
2935 - if (!is_dot_or_dotdot(e->d_name)) {
2936 - ret = 0;
2937 - break;
2938 - }
2945 + e = readdir_skip_dot_and_dotdot(dir);
2946 + if (e)
2947 + ret = 0;
2948
2949 closedir(dir);
2950 return ret;
@@ -2975,10 +2984,8 @@ static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up)
2984 strbuf_complete(path, '/');
2985
2986 len = path->len;
2978 - while ((e = readdir(dir)) != NULL) {
2987 + while ((e = readdir_skip_dot_and_dotdot(dir)) != NULL) {
2988 struct stat st;
2980 - if (is_dot_or_dotdot(e->d_name))
2981 - continue;
2989
2990 strbuf_setlen(path, len);
2991 strbuf_addstr(path, e->d_name);
dir.h
+2
@@ -342,6 +342,8 @@ struct dir_struct {
342 unsigned visited_directories;
343 };
344
345 +struct dirent *readdir_skip_dot_and_dotdot(DIR *dirp);
346 +
347 /*Count the number of slashes for string s*/
348 int count_slashes(const char *s);
349
entry.c
+1 -4
@@ -56,12 +56,9 @@ static void remove_subtree(struct strbuf *path)
56
57 if (!dir)
58 die_errno("cannot opendir '%s'", path->buf);
59 - while ((de = readdir(dir)) != NULL) {
59 + while ((de = readdir_skip_dot_and_dotdot(dir)) != NULL) {
60 struct stat st;
61
62 - if (is_dot_or_dotdot(de->d_name))
63 - continue;
64 -
62 strbuf_addch(path, '/');
63 strbuf_addstr(path, de->d_name);
64 if (lstat(path->buf, &st))
notes-merge.c
+1 -4
@@ -695,13 +695,10 @@ int notes_merge_commit(struct notes_merge_options *o,
695
696 strbuf_addch(&path, '/');
697 baselen = path.len;
698 - while ((e = readdir(dir)) != NULL) {
698 + while ((e = readdir_skip_dot_and_dotdot(dir)) != NULL) {
699 struct stat st;
700 struct object_id obj_oid, blob_oid;
701
702 - if (is_dot_or_dotdot(e->d_name))
703 - continue;
704 -
702 if (get_oid_hex(e->d_name, &obj_oid)) {
703 if (o->verbosity >= 3)
704 printf("Skipping non-SHA1 entry '%s%s'\n",
object-file.c
+1 -3
@@ -2304,10 +2304,8 @@ int for_each_file_in_obj_subdir(unsigned int subdir_nr,
2304 strbuf_addch(path, '/');
2305 baselen = path->len;
2306
2307 - while ((de = readdir(dir))) {
2307 + while ((de = readdir_skip_dot_and_dotdot(dir))) {
2308 size_t namelen;
2309 - if (is_dot_or_dotdot(de->d_name))
2310 - continue;
2309
2310 namelen = strlen(de->d_name);
2311 strbuf_setlen(path, baselen);
packfile.c
+1 -4
@@ -813,10 +813,7 @@ void for_each_file_in_pack_dir(const char *objdir,
813 }
814 strbuf_addch(&path, '/');
815 dirnamelen = path.len;
816 - while ((de = readdir(dir)) != NULL) {
817 - if (is_dot_or_dotdot(de->d_name))
818 - continue;
819 -
816 + while ((de = readdir_skip_dot_and_dotdot(dir)) != NULL) {
817 strbuf_setlen(&path, dirnamelen);
818 strbuf_addstr(&path, de->d_name);
819
rerere.c
+1 -3
@@ -1190,13 +1190,11 @@ void rerere_gc(struct repository *r, struct string_list *rr)
1190 if (!dir)
1191 die_errno(_("unable to open rr-cache directory"));
1192 /* Collect stale conflict IDs ... */
1193 - while ((e = readdir(dir))) {
1193 + while ((e = readdir_skip_dot_and_dotdot(dir))) {
1194 struct rerere_dir *rr_dir;
1195 struct rerere_id id;
1196 int now_empty;
1197
1198 - if (is_dot_or_dotdot(e->d_name))
1199 - continue;
1198 if (!is_rr_cache_dirname(e->d_name))
1199 continue; /* or should we remove e->d_name? */
1200
worktree.c
+3 -9
@@ -128,10 +128,8 @@ struct worktree **get_worktrees(void)
128 dir = opendir(path.buf);
129 strbuf_release(&path);
130 if (dir) {
131 - while ((d = readdir(dir)) != NULL) {
131 + while ((d = readdir_skip_dot_and_dotdot(dir)) != NULL) {
132 struct worktree *linked = NULL;
133 - if (is_dot_or_dotdot(d->d_name))
134 - continue;
133
134 if ((linked = get_linked_worktree(d->d_name))) {
135 ALLOC_GROW(list, counter + 1, alloc);
@@ -486,13 +484,9 @@ int submodule_uses_worktrees(const char *path)
484 if (!dir)
485 return 0;
486
489 - while ((d = readdir(dir)) != NULL) {
490 - if (is_dot_or_dotdot(d->d_name))
491 - continue;
492 -
487 + d = readdir_skip_dot_and_dotdot(dir);
488 + if (d != NULL)
489 ret = 1;
494 - break;
495 - }
490 closedir(dir);
491 return ret;
492 }