Skip to content

Commit 161cda9

Browse files
vdyeldennington
authored andcommitted
Merge pull request git-for-windows#465 from vdye/bugfix/sparse-checkout-fixes
sparse-checkout: avoid crash when switching between cone and non-cone
2 parents 2462d79 + 0dbdf16 commit 161cda9

File tree

3 files changed

+83
-3
lines changed

3 files changed

+83
-3
lines changed

builtin/sparse-checkout.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,10 +467,37 @@ static int sparse_checkout_init(int argc, const char **argv)
467467
return 1;
468468

469469
memset(&pl, 0, sizeof(pl));
470+
pl.use_cone_patterns = core_sparse_checkout_cone;
470471

471472
sparse_filename = get_sparse_checkout_filename();
472473
res = add_patterns_from_file_to_list(sparse_filename, "", 0, &pl, NULL, 0);
473474

475+
/*
476+
* If res >= 0, file already exists. If in cone mode init, verify that the
477+
* patterns are cone mode-compatible (if applicable). Otherwise, fall back
478+
* on non-cone mode sparse checkout.
479+
*/
480+
if (res >= 0 && core_sparse_checkout_cone && !pl.use_cone_patterns) {
481+
warning(_("unable to initialize from existing patterns; disabling cone mode"));
482+
core_sparse_checkout_cone = 0;
483+
484+
if (set_config(MODE_ALL_PATTERNS))
485+
return 1;
486+
487+
/* Set sparse-index/non-sparse-index mode if specified */
488+
if (init_opts.sparse_index >= 0) {
489+
if (set_sparse_index_config(the_repository, init_opts.sparse_index) < 0)
490+
die(_("failed to modify sparse-index config"));
491+
492+
/* force an index rewrite */
493+
repo_read_index(the_repository);
494+
the_repository->index->updated_workdir = 1;
495+
496+
if (!init_opts.sparse_index)
497+
ensure_full_index(the_repository->index);
498+
}
499+
}
500+
474501
/* If we already have a sparse-checkout file, use it. */
475502
if (res >= 0) {
476503
free(sparse_filename);

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: 51 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) &&
@@ -768,4 +777,43 @@ test_expect_success 'malformed cone-mode patterns' '
768777
grep "warning: disabling cone pattern matching" err
769778
'
770779

780+
test_expect_success 'init with cone mode verifies existing cone patterns' '
781+
# Set non-cone mode pattern
782+
echo "/deep/deeper*" >repo/.git/info/sparse-checkout &&
783+
784+
git -C repo sparse-checkout init --cone 2>err &&
785+
test_i18ngrep "disabling cone mode" err &&
786+
test_must_fail git -C repo config core.sparsecheckoutcone
787+
'
788+
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+
771819
test_done

0 commit comments

Comments
 (0)