summaryrefslogtreecommitdiff
path: root/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'dir.c')
-rw-r--r--dir.c85
1 files changed, 29 insertions, 56 deletions
diff --git a/dir.c b/dir.c
index a4306ab874..5aa6fbad0b 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 || (flags & PATTERN_FLAG_MUSTBEDIR)))
+ if (!patternlen && !namelen)
return 1;
}
@@ -1303,44 +1303,6 @@ 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
@@ -1356,7 +1318,6 @@ 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 */
@@ -1366,10 +1327,11 @@ 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 &&
- !path_matches_dir_pattern(pathname, pathlen, &path_parent,
- dtype, pattern, istate))
- continue;
+ if (pattern->flags & PATTERN_FLAG_MUSTBEDIR) {
+ *dtype = resolve_dtype(*dtype, istate, pathname, pathlen);
+ if (*dtype != DT_DIR)
+ continue;
+ }
if (pattern->flags & PATTERN_FLAG_NODIR) {
if (match_basename(basename,
@@ -1393,12 +1355,6 @@ 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;
}
@@ -1504,8 +1460,9 @@ static int path_in_sparse_checkout_1(const char *path,
struct index_state *istate,
int require_cone_mode)
{
- const char *base;
int dtype = DT_REG;
+ enum pattern_match_result match = UNDECIDED;
+ const char *end, *slash;
/*
* We default to accepting a path if there are no patterns or
@@ -1516,11 +1473,27 @@ static int path_in_sparse_checkout_1(const char *path,
!istate->sparse_checkout_patterns->use_cone_patterns))
return 1;
- base = strrchr(path, '/');
- return path_matches_pattern_list(path, strlen(path), base ? base + 1 : path,
- &dtype,
- istate->sparse_checkout_patterns,
- istate) > 0;
+ /*
+ * If UNDECIDED, use the match from the parent dir (recursively), or
+ * fall back to NOT_MATCHED at the topmost level. Note that cone mode
+ * never returns UNDECIDED, so we will execute only one iteration in
+ * this case.
+ */
+ for (end = path + strlen(path);
+ end > path && match == UNDECIDED;
+ end = slash) {
+
+ for (slash = end - 1; slash > path && *slash != '/'; slash--)
+ ; /* do nothing */
+
+ match = path_matches_pattern_list(path, end - path,
+ slash > path ? slash + 1 : path, &dtype,
+ istate->sparse_checkout_patterns, istate);
+
+ /* We are going to match the parent dir now */
+ dtype = DT_DIR;
+ }
+ return match > 0;
}
int path_in_sparse_checkout(const char *path,