From 00f01ddd3c94aee816ef287d3228d531a64a768b Mon Sep 17 00:00:00 2001 From: Derrick Stolee Date: Fri, 3 Sep 2021 09:55:13 -0400 Subject: [PATCH] dir: add path_matches_cone_mode_pattern_list() When matching against a generic pattern list, the 'basename' is important for some patterns. However, it and the 'dtype' parameter are irrelevant for cone mode sparse-checkout patterns. If we know that we are working with cone mode patterns from the start, then we can speed up the pattern check slightly by not computing the 'basename'. In many existing consumers, the 'basename' is already known from context, but some new consumers we compute this on-demand. A future change will add more calls that do not have the 'basename' from context and would need to compute it for many cache entries in a tight loop. Avoid this problem by creating the new path_matches_cone_mode_pattern_list() method. Signed-off-by: Derrick Stolee --- dir.c | 78 +++++++++++++++++++++++++++++++++-------------------------- dir.h | 9 +++++++ 2 files changed, 53 insertions(+), 34 deletions(-) diff --git a/dir.c b/dir.c index 4339715ae5ad7c..28da33f875838f 100644 --- a/dir.c +++ b/dir.c @@ -1400,46 +1400,16 @@ static struct path_pattern *last_matching_pattern_from_list(const char *pathname return res; } -/* - * Scan the list of patterns to determine if the ordered list - * of patterns matches on 'pathname'. - * - * Return 1 for a match, 0 for not matched and -1 for undecided. - */ -enum pattern_match_result path_matches_pattern_list( +enum pattern_match_result path_matches_cone_mode_pattern_list( const char *pathname, int pathlen, - const char *basename, int *dtype, - struct pattern_list *pl, - struct index_state *istate) + struct pattern_list *pl) { - struct path_pattern *pattern; struct strbuf parent_pathname = STRBUF_INIT; int result = NOT_MATCHED; size_t slash_pos; - /* - * The virtual file system data is used to prevent git from traversing - * any part of the tree that is not in the virtual file system. Return - * 1 to exclude the entry if it is not found in the virtual file system, - * else fall through to the regular excludes logic as it may further exclude. - */ - if (*dtype == DT_UNKNOWN) - *dtype = resolve_dtype(DT_UNKNOWN, istate, pathname, pathlen); - if (is_excluded_from_virtualfilesystem(pathname, pathlen, *dtype) > 0) - return 1; - - if (!pl->use_cone_patterns) { - pattern = last_matching_pattern_from_list(pathname, pathlen, basename, - dtype, pl, istate); - if (pattern) { - if (pattern->flags & PATTERN_FLAG_NEGATIVE) - return NOT_MATCHED; - else - return MATCHED; - } - - return UNDECIDED; - } + if (!pl->use_cone_patterns) + BUG("path_matches_cone_mode_pattern_list requires cone mode patterns"); if (pl->full_cone) return MATCHED; @@ -1492,6 +1462,46 @@ enum pattern_match_result path_matches_pattern_list( return result; } +/* + * Scan the list of patterns to determine if the ordered list + * of patterns matches on 'pathname'. + * + * Return 1 for a match, 0 for not matched and -1 for undecided. + */ +enum pattern_match_result path_matches_pattern_list( + const char *pathname, int pathlen, + const char *basename, int *dtype, + struct pattern_list *pl, + struct index_state *istate) +{ + /* + * The virtual file system data is used to prevent git from traversing + * any part of the tree that is not in the virtual file system. Return + * 1 to exclude the entry if it is not found in the virtual file system, + * else fall through to the regular excludes logic as it may further exclude. + */ + if (*dtype == DT_UNKNOWN) + *dtype = resolve_dtype(DT_UNKNOWN, istate, pathname, pathlen); + if (is_excluded_from_virtualfilesystem(pathname, pathlen, *dtype) > 0) + return 1; + + if (!pl->use_cone_patterns) { + struct path_pattern *pattern = last_matching_pattern_from_list( + pathname, pathlen, basename, + dtype, pl, istate); + if (pattern) { + if (pattern->flags & PATTERN_FLAG_NEGATIVE) + return NOT_MATCHED; + else + return MATCHED; + } + + return UNDECIDED; + } + + return path_matches_cone_mode_pattern_list(pathname, pathlen, pl); +} + int init_sparse_checkout_patterns(struct index_state *istate) { if (!core_apply_sparse_checkout) diff --git a/dir.h b/dir.h index 7bc862030cfb3b..3e73d11f31f0d0 100644 --- a/dir.h +++ b/dir.h @@ -383,6 +383,15 @@ enum pattern_match_result { MATCHED_RECURSIVE = 2, }; +/* + * Test if a given path is contained in the given pattern list. + * + * The given pattern list _must_ use cone mode patterns. + */ +enum pattern_match_result path_matches_cone_mode_pattern_list( + const char *pathname, int pathlen, + struct pattern_list *pl); + /* * Scan the list of patterns to determine if the ordered list * of patterns matches on 'pathname'.