Skip to content

Commit 1a74f67

Browse files
derrickstoleedscho
authored andcommitted
dir: add generic "walk all files" helper
There is sometimes a need to visit every file within a directory, recursively. The main example is remove_dir_recursively(), though it has some extra flags that make it want to iterate over paths in a custom way. There is also the fill_directory() approach but that involves an index and a pathspec. This change adds a new for_each_file_in_dir() method that will be helpful in the next change. Signed-off-by: Derrick Stolee <[email protected]>
1 parent f0d5222 commit 1a74f67

File tree

2 files changed

+42
-0
lines changed

2 files changed

+42
-0
lines changed

dir.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "read-cache-ll.h"
3232
#include "setup.h"
3333
#include "sparse-index.h"
34+
#include "strbuf.h"
3435
#include "submodule-config.h"
3536
#include "symlinks.h"
3637
#include "trace2.h"
@@ -88,6 +89,33 @@ struct dirent *readdir_skip_dot_and_dotdot(DIR *dirp)
8889
return e;
8990
}
9091

92+
int for_each_file_in_dir(struct strbuf *path, file_iterator fn, const void *data)
93+
{
94+
struct dirent *e;
95+
int res = 0;
96+
size_t baselen = path->len;
97+
DIR *dir = opendir(path->buf);
98+
99+
if (!dir)
100+
return 0;
101+
102+
while (!res && (e = readdir_skip_dot_and_dotdot(dir)) != NULL) {
103+
unsigned char dtype = get_dtype(e, path, 0);
104+
strbuf_setlen(path, baselen);
105+
strbuf_addstr(path, e->d_name);
106+
107+
if (dtype == DT_REG) {
108+
res = fn(path->buf, data);
109+
} else if (dtype == DT_DIR) {
110+
strbuf_addch(path, '/');
111+
res = for_each_file_in_dir(path, fn, data);
112+
}
113+
}
114+
115+
closedir(dir);
116+
return res;
117+
}
118+
91119
int count_slashes(const char *s)
92120
{
93121
int cnt = 0;

dir.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,20 @@ int get_sparse_checkout_patterns(struct pattern_list *pl);
536536
*/
537537
int remove_dir_recursively(struct strbuf *path, int flag);
538538

539+
/*
540+
* This function pointer type is called on each file discovered in
541+
* for_each_file_in_dir. The iteration stops if this method returns
542+
* non-zero.
543+
*/
544+
typedef int (*file_iterator)(const char *path, const void *data);
545+
546+
struct strbuf;
547+
/*
548+
* Given a directory path, recursively visit each file within, including
549+
* within subdirectories.
550+
*/
551+
int for_each_file_in_dir(struct strbuf *path, file_iterator fn, const void *data);
552+
539553
/*
540554
* Tries to remove the path, along with leading empty directories so long as
541555
* those empty directories are not startup_info->original_cwd. Ignores

0 commit comments

Comments
 (0)