summaryrefslogtreecommitdiff
path: root/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'dir.c')
-rw-r--r--dir.c56
1 files changed, 50 insertions, 6 deletions
diff --git a/dir.c b/dir.c
index 39fce3bcba..a4306ab874 100644
--- a/dir.c
+++ b/dir.c
@@ -1294,7 +1294,7 @@ int match_pathname(const char *pathname, int pathlen,
* then our prefix match is all we need; we
* do not need to call fnmatch at all.
*/
- if (!patternlen && !namelen)
+ if (!patternlen && (!namelen || (flags & PATTERN_FLAG_MUSTBEDIR)))
return 1;
}
@@ -1303,6 +1303,44 @@ int match_pathname(const char *pathname, int pathlen,
WM_PATHNAME) == 0;
}
+static int path_matches_dir_pattern(const char *pathname,
+ int pathlen,
+ struct strbuf **path_parent,
+ int *dtype,
+ struct path_pattern *pattern,
+ struct index_state *istate)
+{
+ if (!*path_parent) {
+ char *slash;
+ CALLOC_ARRAY(*path_parent, 1);
+ strbuf_add(*path_parent, pathname, pathlen);
+ slash = find_last_dir_sep((*path_parent)->buf);
+
+ if (slash)
+ strbuf_setlen(*path_parent, slash - (*path_parent)->buf);
+ else
+ strbuf_setlen(*path_parent, 0);
+ }
+
+ /*
+ * If the parent directory matches the pattern, then we do not
+ * need to check for dtype.
+ */
+ if ((*path_parent)->len &&
+ match_pathname((*path_parent)->buf, (*path_parent)->len,
+ pattern->base,
+ pattern->baselen ? pattern->baselen - 1 : 0,
+ pattern->pattern, pattern->nowildcardlen,
+ pattern->patternlen, pattern->flags))
+ return 1;
+
+ *dtype = resolve_dtype(*dtype, istate, pathname, pathlen);
+ if (*dtype != DT_DIR)
+ return 0;
+
+ return 1;
+}
+
/*
* Scan the given exclude list in reverse to see whether pathname
* should be ignored. The first match (i.e. the last on the list), if
@@ -1318,6 +1356,7 @@ static struct path_pattern *last_matching_pattern_from_list(const char *pathname
{
struct path_pattern *res = NULL; /* undecided */
int i;
+ struct strbuf *path_parent = NULL;
if (!pl->nr)
return NULL; /* undefined */
@@ -1327,11 +1366,10 @@ static struct path_pattern *last_matching_pattern_from_list(const char *pathname
const char *exclude = pattern->pattern;
int prefix = pattern->nowildcardlen;
- if (pattern->flags & PATTERN_FLAG_MUSTBEDIR) {
- *dtype = resolve_dtype(*dtype, istate, pathname, pathlen);
- if (*dtype != DT_DIR)
- continue;
- }
+ if (pattern->flags & PATTERN_FLAG_MUSTBEDIR &&
+ !path_matches_dir_pattern(pathname, pathlen, &path_parent,
+ dtype, pattern, istate))
+ continue;
if (pattern->flags & PATTERN_FLAG_NODIR) {
if (match_basename(basename,
@@ -1355,6 +1393,12 @@ static struct path_pattern *last_matching_pattern_from_list(const char *pathname
break;
}
}
+
+ if (path_parent) {
+ strbuf_release(path_parent);
+ free(path_parent);
+ }
+
return res;
}