aboutsummaryrefslogtreecommitdiffstats
path: root/dir.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dir.c59
1 files changed, 52 insertions, 7 deletions
diff --git a/dir.c b/dir.c
index 0a67a99cb3..2d145a9f61 100644
--- a/dir.c
+++ b/dir.c
@@ -30,6 +30,7 @@
#include "read-cache-ll.h"
#include "setup.h"
#include "sparse-index.h"
+#include "strbuf.h"
#include "submodule-config.h"
#include "symlinks.h"
#include "trace2.h"
@@ -87,6 +88,33 @@ struct dirent *readdir_skip_dot_and_dotdot(DIR *dirp)
return e;
}
+int for_each_file_in_dir(struct strbuf *path, file_iterator fn, const void *data)
+{
+ struct dirent *e;
+ int res = 0;
+ size_t baselen = path->len;
+ DIR *dir = opendir(path->buf);
+
+ if (!dir)
+ return 0;
+
+ while (!res && (e = readdir_skip_dot_and_dotdot(dir)) != NULL) {
+ unsigned char dtype = get_dtype(e, path, 0);
+ strbuf_setlen(path, baselen);
+ strbuf_addstr(path, e->d_name);
+
+ if (dtype == DT_REG) {
+ res = fn(path->buf, data);
+ } else if (dtype == DT_DIR) {
+ strbuf_addch(path, '/');
+ res = for_each_file_in_dir(path, fn, data);
+ }
+ }
+
+ closedir(dir);
+ return res;
+}
+
int count_slashes(const char *s)
{
int cnt = 0;
@@ -1360,18 +1388,25 @@ int match_pathname(const char *pathname, int pathlen,
if (fspathncmp(pattern, name, prefix))
return 0;
- pattern += prefix;
- patternlen -= prefix;
- name += prefix;
- namelen -= prefix;
/*
* If the whole pattern did not have a wildcard,
* then our prefix match is all we need; we
* do not need to call fnmatch at all.
*/
- if (!patternlen && !namelen)
+ if (patternlen == prefix && namelen == prefix)
return 1;
+
+ /*
+ * Retain one character of the prefix to
+ * pass to fnmatch, which lets it distinguish
+ * the start of a directory component correctly.
+ */
+ prefix--;
+ pattern += prefix;
+ patternlen -= prefix;
+ name += prefix;
+ namelen -= prefix;
}
return fnmatch_icase_mem(pattern, patternlen,
@@ -2228,6 +2263,8 @@ static int exclude_matches_pathspec(const char *path, int pathlen,
const struct pathspec *pathspec)
{
int i;
+ int matches_exclude_magic = 0;
+ int matches_pathspec_elem = 0;
if (!pathspec || !pathspec->nr)
return 0;
@@ -2244,15 +2281,23 @@ static int exclude_matches_pathspec(const char *path, int pathlen,
for (i = 0; i < pathspec->nr; i++) {
const struct pathspec_item *item = &pathspec->items[i];
int len = item->nowildcard_len;
+ int *matches;
+
+ if (item->magic & PATHSPEC_EXCLUDE)
+ matches = &matches_exclude_magic;
+ else
+ matches = &matches_pathspec_elem;
if (len == pathlen &&
!ps_strncmp(item, item->match, path, pathlen))
- return 1;
+ *matches = 1;
if (len > pathlen &&
item->match[pathlen] == '/' &&
!ps_strncmp(item, item->match, path, pathlen))
- return 1;
+ *matches = 1;
}
+ if (matches_pathspec_elem && !matches_exclude_magic)
+ return 1;
return 0;
}