Skip to content

Commit a63d67b

Browse files
vdyeldennington
authored andcommitted
sparse-checkout: require starting '/' in cone mode patterns
Add check for missing initial '/' when verifying cone patterns in `add_pattern_to_hashsets(...)`, disabling cone patterns if not found. Update tests in `t1091-sparse-checkout-builtin.sh` to ensure the starting '/' is present unless the test verifies behavior when it is missing. The implicit assumption of a starting '/' in cone mode patterns exists throughout the code paths of `git sparse-checkout`, including in the construction of the sparse pattern hashmaps. However, without enforcement of that assumption, the presence of a directory pattern missing the starting '/' would cause any subsequent cone mode `git sparse-checkout add` to enter an infinite recursive loop in `insert_recursive_pattern(...)` (`sparse-checkout.c`). By adding the starting '/' requirement to `add_pattern_to_hashsets(...)` (`dir.c`), cone mode is disabled on the pattern list, forcing `git sparse-checkout add` to exit early. Signed-off-by: Victoria Dye <[email protected]>
1 parent 0a30e28 commit a63d67b

File tree

2 files changed

+47
-3
lines changed

2 files changed

+47
-3
lines changed

dir.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,11 @@ static void add_pattern_to_hashsets(struct pattern_list *pl, struct path_pattern
715715
if (!pl->use_cone_patterns)
716716
return;
717717

718+
if (*given->pattern != '/') {
719+
warning(_("unrecognized pattern: '%s'"), given->pattern);
720+
goto clear_hashmaps;
721+
}
722+
718723
if (given->flags & PATTERN_FLAG_NEGATIVE &&
719724
given->flags & PATTERN_FLAG_MUSTBEDIR &&
720725
!strcmp(given->pattern, "/*")) {

t/t1091-sparse-checkout-builtin.sh

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ test_expect_success 'cone mode: match patterns' '
216216
test_expect_success 'cone mode: warn on bad pattern' '
217217
test_when_finished mv sparse-checkout repo/.git/info/ &&
218218
cp repo/.git/info/sparse-checkout . &&
219-
echo "!/deep/deeper/*" >>repo/.git/info/sparse-checkout &&
219+
echo "!/deep/deeper/*" >repo/.git/info/sparse-checkout &&
220220
git -C repo read-tree -mu HEAD 2>err &&
221221
test_i18ngrep "unrecognized negative pattern" err
222222
'
@@ -608,7 +608,7 @@ test_expect_success 'pattern-checks: starting "*"' '
608608
cat >repo/.git/info/sparse-checkout <<-\EOF &&
609609
/*
610610
!/*/
611-
*eep/
611+
/*eep/
612612
EOF
613613
check_read_tree_errors repo "a deep" "disabling cone pattern matching"
614614
'
@@ -619,12 +619,21 @@ test_expect_success 'pattern-checks: contained glob characters' '
619619
cat >repo/.git/info/sparse-checkout <<-EOF &&
620620
/*
621621
!/*/
622-
something$c-else/
622+
/something$c-else/
623623
EOF
624624
check_read_tree_errors repo "a" "disabling cone pattern matching" || return 1
625625
done
626626
'
627627

628+
test_expect_success 'pattern-checks: starting "/"' '
629+
cat >repo/.git/info/sparse-checkout <<-\EOF &&
630+
/*
631+
!/*/
632+
deep/
633+
EOF
634+
check_read_tree_errors repo "a deep" "disabling cone pattern matching"
635+
'
636+
628637
test_expect_success BSLASHPSPEC 'pattern-checks: escaped characters' '
629638
git clone repo escaped &&
630639
TREEOID=$(git -C escaped rev-parse HEAD:folder1) &&
@@ -777,4 +786,34 @@ test_expect_success 'init with cone mode verifies existing cone patterns' '
777786
test_must_fail git -C repo config core.sparsecheckoutcone
778787
'
779788

789+
# NEEDSWORK: in the case of directory patterns like `deep/`, it might be worth trying
790+
# to "correct" the patterns to match a cone mode style. However, that may be more difficult
791+
# for nested directories (like `deep/deeper1/`) in which multiple individual patterns
792+
# would be mapped from the original (`/deep/`, `!/deep/*/`, `/deep/deeper1/`).
793+
test_expect_success 'add cone pattern disallowed with existing non-cone directory pattern' '
794+
rm -f repo/.git/info/sparse-checkout &&
795+
796+
git -C repo sparse-checkout init --cone &&
797+
798+
# Manually set the sparse checkout pattern to a directory pattern
799+
# without preceding slash
800+
cat >repo/.git/info/sparse-checkout <<-\EOF &&
801+
deep/
802+
EOF
803+
804+
# `add` fails because `deep/` is not a valid cone pattern.
805+
test_must_fail git -C repo sparse-checkout add folder1/ 2>err &&
806+
test_i18ngrep "existing sparse-checkout patterns do not use cone mode" err &&
807+
808+
# `set` succeeds with same patterns set properly for cone mode.
809+
git -C repo sparse-checkout set deep/ folder1/ &&
810+
cat >expect <<-\EOF &&
811+
/*
812+
!/*/
813+
/deep/
814+
/folder1/
815+
EOF
816+
test_cmp expect repo/.git/info/sparse-checkout
817+
'
818+
780819
test_done

0 commit comments

Comments
 (0)