Git fork

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

authored by

Derrick Stolee and committed by
Junio C Hamano
1588e836 a8077c19

+42
+28
dir.c
··· 30 30 #include "read-cache-ll.h" 31 31 #include "setup.h" 32 32 #include "sparse-index.h" 33 + #include "strbuf.h" 33 34 #include "submodule-config.h" 34 35 #include "symlinks.h" 35 36 #include "trace2.h" ··· 85 86 break; 86 87 } 87 88 return e; 89 + } 90 + 91 + int for_each_file_in_dir(struct strbuf *path, file_iterator fn, const void *data) 92 + { 93 + struct dirent *e; 94 + int res = 0; 95 + size_t baselen = path->len; 96 + DIR *dir = opendir(path->buf); 97 + 98 + if (!dir) 99 + return 0; 100 + 101 + while (!res && (e = readdir_skip_dot_and_dotdot(dir)) != NULL) { 102 + unsigned char dtype = get_dtype(e, path, 0); 103 + strbuf_setlen(path, baselen); 104 + strbuf_addstr(path, e->d_name); 105 + 106 + if (dtype == DT_REG) { 107 + res = fn(path->buf, data); 108 + } else if (dtype == DT_DIR) { 109 + strbuf_addch(path, '/'); 110 + res = for_each_file_in_dir(path, fn, data); 111 + } 112 + } 113 + 114 + closedir(dir); 115 + return res; 88 116 } 89 117 90 118 int count_slashes(const char *s)
+14
dir.h
··· 537 537 int remove_dir_recursively(struct strbuf *path, int flag); 538 538 539 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 + 553 + /* 540 554 * Tries to remove the path, along with leading empty directories so long as 541 555 * those empty directories are not startup_info->original_cwd. Ignores 542 556 * ENOENT.