]> git.ipfire.org Git - thirdparty/git.git/commitdiff
sparse-checkout: cone mode does not recognize "**"
authorDerrick Stolee <dstolee@microsoft.com>
Fri, 24 Jan 2020 21:19:36 +0000 (21:19 +0000)
committerJunio C Hamano <gitster@pobox.com>
Fri, 24 Jan 2020 21:26:54 +0000 (13:26 -0800)
When core.sparseCheckoutCone is enabled, the 'git sparse-checkout set'
command creates a restricted set of possible patterns that are used
by a custom algorithm to quickly match those patterns.

If a user manually edits the sparse-checkout file, then they could
create patterns that do not match these expectations. The cone-mode
matching algorithm can return incorrect results. The solution is to
detect these incorrect patterns, warn that we do not recognize them,
and revert to the standard algorithm.

Check each pattern for the "**" substring, and revert to the old
logic if seen. While technically a "/<dir>/**" pattern matches
the meaning of "/<dir>/", it is not one that would be written by
the sparse-checkout builtin in cone mode. Attempting to accept that
pattern change complicates the logic and instead we punt and do
not accept any instance of "**".

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 22d08e61c296a0ca2676c705422b9b50c292650c..40fed73a947bad3837839af8195cfd06442b7324 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -651,11 +651,16 @@ static void add_pattern_to_hashsets(struct pattern_list *pl, struct path_pattern
                return;
        }
 
+       if (strstr(given->pattern, "**")) {
+               /* Not a cone pattern. */
+               warning(_("unrecognized pattern: '%s'"), given->pattern);
+               goto clear_hashmaps;
+       }
+
        if (given->patternlen > 2 &&
            !strcmp(given->pattern + given->patternlen - 2, "/*")) {
                if (!(given->flags & PATTERN_FLAG_NEGATIVE)) {
                        /* Not a cone pattern. */
-                       pl->use_cone_patterns = 0;
                        warning(_("unrecognized pattern: '%s'"), given->pattern);
                        goto clear_hashmaps;
                }
index cf4a595c868d8ed429dc557e851a5a95692d999d..e2e45dc7fd6351ef574ee6fb52027b726e50d6a6 100755 (executable)
@@ -305,4 +305,38 @@ test_expect_success 'different sparse-checkouts with worktrees' '
        check_files worktree a deep
 '
 
+check_read_tree_errors () {
+       REPO=$1
+       FILES=$2
+       ERRORS=$3
+       git -C $REPO read-tree -mu HEAD 2>err &&
+       if test -z "$ERRORS"
+       then
+               test_must_be_empty err
+       else
+               test_i18ngrep "$ERRORS" err
+       fi &&
+       check_files $REPO $FILES
+}
+
+test_expect_success 'pattern-checks: /A/**' '
+       cat >repo/.git/info/sparse-checkout <<-\EOF &&
+       /*
+       !/*/
+       /folder1/**
+       EOF
+       check_read_tree_errors repo "a folder1" "disabling cone pattern matching"
+'
+
+test_expect_success 'pattern-checks: /A/**/B/' '
+       cat >repo/.git/info/sparse-checkout <<-\EOF &&
+       /*
+       !/*/
+       /deep/**/deepest
+       EOF
+       check_read_tree_errors repo "a deep" "disabling cone pattern matching" &&
+       check_files repo/deep "deeper1" &&
+       check_files repo/deep/deeper1 "deepest"
+'
+
 test_done