Skip to content

Commit 9abc60f

Browse files
derrickstoleegitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 9e6d3e6 commit 9abc60f

File tree

2 files changed

+75
-0
lines changed

2 files changed

+75
-0
lines changed

dir.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,7 @@ static void add_pattern_to_hashsets(struct pattern_list *pl, struct path_pattern
635635
struct pattern_entry *translated;
636636
char *truncated;
637637
char *data = NULL;
638+
const char *prev, *cur, *next;
638639

639640
if (!pl->use_cone_patterns)
640641
return;
@@ -652,12 +653,47 @@ static void add_pattern_to_hashsets(struct pattern_list *pl, struct path_pattern
652653
}
653654

654655
if (given->patternlen <= 2 ||
656+
*given->pattern == '*' ||
655657
strstr(given->pattern, "**")) {
656658
/* Not a cone pattern. */
657659
warning(_("unrecognized pattern: '%s'"), given->pattern);
658660
goto clear_hashmaps;
659661
}
660662

663+
prev = given->pattern;
664+
cur = given->pattern + 1;
665+
next = given->pattern + 2;
666+
667+
while (*cur) {
668+
/* Watch for glob characters '*', '\', '[', '?' */
669+
if (!is_glob_special(*cur))
670+
goto increment;
671+
672+
/* But only if *prev != '\\' */
673+
if (*prev == '\\')
674+
goto increment;
675+
676+
/* But allow the initial '\' */
677+
if (*cur == '\\' &&
678+
is_glob_special(*next))
679+
goto increment;
680+
681+
/* But a trailing '/' then '*' is fine */
682+
if (*prev == '/' &&
683+
*cur == '*' &&
684+
*next == 0)
685+
goto increment;
686+
687+
/* Not a cone pattern. */
688+
warning(_("unrecognized pattern: '%s'"), given->pattern);
689+
goto clear_hashmaps;
690+
691+
increment:
692+
prev++;
693+
cur++;
694+
next++;
695+
}
696+
661697
if (given->patternlen > 2 &&
662698
!strcmp(given->pattern + given->patternlen - 2, "/*")) {
663699
if (!(given->flags & PATTERN_FLAG_NEGATIVE)) {

t/t1091-sparse-checkout-builtin.sh

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,4 +348,43 @@ test_expect_success 'pattern-checks: too short' '
348348
check_read_tree_errors repo "a" "disabling cone pattern matching"
349349
'
350350

351+
test_expect_success 'pattern-checks: trailing "*"' '
352+
cat >repo/.git/info/sparse-checkout <<-\EOF &&
353+
/*
354+
!/*/
355+
/a*
356+
EOF
357+
check_read_tree_errors repo "a" "disabling cone pattern matching"
358+
'
359+
360+
test_expect_success 'pattern-checks: starting "*"' '
361+
cat >repo/.git/info/sparse-checkout <<-\EOF &&
362+
/*
363+
!/*/
364+
*eep/
365+
EOF
366+
check_read_tree_errors repo "a deep" "disabling cone pattern matching"
367+
'
368+
369+
test_expect_success 'pattern-checks: contained glob characters' '
370+
for c in "[a]" "\\" "?" "*"
371+
do
372+
cat >repo/.git/info/sparse-checkout <<-EOF &&
373+
/*
374+
!/*/
375+
something$c-else/
376+
EOF
377+
check_read_tree_errors repo "a" "disabling cone pattern matching"
378+
done
379+
'
380+
381+
test_expect_success 'pattern-checks: escaped "*"' '
382+
cat >repo/.git/info/sparse-checkout <<-\EOF &&
383+
/*
384+
!/*/
385+
/does\*not\*exist/
386+
EOF
387+
check_read_tree_errors repo "a" ""
388+
'
389+
351390
test_done

0 commit comments

Comments
 (0)