]> git.ipfire.org Git - thirdparty/git.git/commitdiff
sparse-checkout: warn on globs in cone patterns
authorDerrick Stolee <dstolee@microsoft.com>
Fri, 31 Jan 2020 20:16:08 +0000 (20:16 +0000)
committerJunio C Hamano <gitster@pobox.com>
Fri, 31 Jan 2020 21:05:29 +0000 (13:05 -0800)
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>
dir.c
t/t1091-sparse-checkout-builtin.sh

diff --git a/dir.c b/dir.c
index c2e585607e1962d084271f608938efc8f4b7206b..71d28331f35c1a2f27e42f7123a86fc2bd5ebdef 100644 (file)
--- 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)) {
index 2e575347995b1518f4ebfbc02be8c667d62d2d67..c732abeacde4d0a0f2fc5e918305773754c93bfa 100755 (executable)
@@ -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