aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDerrick Stolee <dstolee@microsoft.com>2020-01-31 20:16:08 +0000
committerJunio C Hamano <gitster@pobox.com>2020-01-31 13:05:29 -0800
commit9abc60f8015d060d3f3433b105648a4725c97bd1 (patch)
tree367534ff77b191bf1edbfa24ef61496733332b40
parent9e6d3e64175713bc0007f3012ea288f4dfc0a399 (diff)
downloadgit-9abc60f8015d060d3f3433b105648a4725c97bd1.tar.gz
sparse-checkout: warn on globs in cone patterns
In cone mode, the sparse-checkout commmand will write patterns that allow faster pattern matching. This matching only works if the patterns in the sparse-checkout file are those written by that command. Users can edit the sparse-checkout file and create patterns that cause the cone mode matching to fail. The cone mode patterns may end in "/*" but otherwise an un-escaped asterisk or other glob character is invalid. Add checks to disable cone mode when seeing these values. A later change will properly handle escaped globs. Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--dir.c36
-rwxr-xr-xt/t1091-sparse-checkout-builtin.sh39
2 files changed, 75 insertions, 0 deletions
diff --git a/dir.c b/dir.c
index c2e585607e..71d28331f3 100644
--- a/dir.c
+++ b/dir.c
@@ -635,6 +635,7 @@ static void add_pattern_to_hashsets(struct pattern_list *pl, struct path_pattern
struct pattern_entry *translated;
char *truncated;
char *data = NULL;
+ const char *prev, *cur, *next;
if (!pl->use_cone_patterns)
return;
@@ -652,12 +653,47 @@ static void add_pattern_to_hashsets(struct pattern_list *pl, struct path_pattern
}
if (given->patternlen <= 2 ||
+ *given->pattern == '*' ||
strstr(given->pattern, "**")) {
/* Not a cone pattern. */
warning(_("unrecognized pattern: '%s'"), given->pattern);
goto clear_hashmaps;
}
+ prev = given->pattern;
+ cur = given->pattern + 1;
+ next = given->pattern + 2;
+
+ while (*cur) {
+ /* Watch for glob characters '*', '\', '[', '?' */
+ if (!is_glob_special(*cur))
+ goto increment;
+
+ /* But only if *prev != '\\' */
+ if (*prev == '\\')
+ goto increment;
+
+ /* But allow the initial '\' */
+ if (*cur == '\\' &&
+ is_glob_special(*next))
+ goto increment;
+
+ /* But a trailing '/' then '*' is fine */
+ if (*prev == '/' &&
+ *cur == '*' &&
+ *next == 0)
+ goto increment;
+
+ /* Not a cone pattern. */
+ warning(_("unrecognized pattern: '%s'"), given->pattern);
+ goto clear_hashmaps;
+
+ increment:
+ prev++;
+ cur++;
+ next++;
+ }
+
if (given->patternlen > 2 &&
!strcmp(given->pattern + given->patternlen - 2, "/*")) {
if (!(given->flags & PATTERN_FLAG_NEGATIVE)) {
diff --git a/t/t1091-sparse-checkout-builtin.sh b/t/t1091-sparse-checkout-builtin.sh
index 2e57534799..c732abeacd 100755
--- a/t/t1091-sparse-checkout-builtin.sh
+++ b/t/t1091-sparse-checkout-builtin.sh
@@ -348,4 +348,43 @@ test_expect_success 'pattern-checks: too short' '
check_read_tree_errors repo "a" "disabling cone pattern matching"
'
+test_expect_success 'pattern-checks: trailing "*"' '
+ cat >repo/.git/info/sparse-checkout <<-\EOF &&
+ /*
+ !/*/
+ /a*
+ EOF
+ check_read_tree_errors repo "a" "disabling cone pattern matching"
+'
+
+test_expect_success 'pattern-checks: starting "*"' '
+ cat >repo/.git/info/sparse-checkout <<-\EOF &&
+ /*
+ !/*/
+ *eep/
+ EOF
+ check_read_tree_errors repo "a deep" "disabling cone pattern matching"
+'
+
+test_expect_success 'pattern-checks: contained glob characters' '
+ for c in "[a]" "\\" "?" "*"
+ do
+ cat >repo/.git/info/sparse-checkout <<-EOF &&
+ /*
+ !/*/
+ something$c-else/
+ EOF
+ check_read_tree_errors repo "a" "disabling cone pattern matching"
+ done
+'
+
+test_expect_success 'pattern-checks: escaped "*"' '
+ cat >repo/.git/info/sparse-checkout <<-\EOF &&
+ /*
+ !/*/
+ /does\*not\*exist/
+ EOF
+ check_read_tree_errors repo "a" ""
+'
+
test_done