diff options
Diffstat (limited to 'dir.c')
-rw-r--r-- | dir.c | 85 |
1 files changed, 29 insertions, 56 deletions
@@ -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, |