Skip to content

Commit 2e07ab3

Browse files
authored
Fix toplevel wildcard matching
1 parent db3b60a commit 2e07ab3

File tree

2 files changed

+32
-2
lines changed

2 files changed

+32
-2
lines changed

src/libgit2/sparse.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ static bool pattern_matches_path(git_attr_fnmatch *match, git_attr_path *path, s
6565

6666
if (HAS_FLAG(match, GIT_ATTR_FNMATCH_HASWILD)) {
6767
expected_extra_nesting = true;
68+
if (match->length <= 1) {
69+
// Top level wildcard always matches
70+
return true;
71+
}
6872
exact_match_length = match->length - 2; // Cut off the trailing "/*"
6973
}
7074

@@ -183,7 +187,7 @@ static int parse_sparse_file(
183187
bool matched = false;
184188
size_t k;
185189
git_attr_fnmatch *parent_match;
186-
git_vector_foreach(&attrs->rules, k, parent_match) {
190+
git_vector_rforeach(&attrs->rules, k, parent_match) {
187191
if (pattern_matches_path(parent_match, &parent_path, parent_length)) {
188192
matched = !HAS_FLAG(parent_match, GIT_ATTR_FNMATCH_NEGATIVE);
189193
break;

tests/libgit2/sparse/paths.c

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,31 @@ void test_sparse_paths__check_toplevel(void)
129129
}
130130
}
131131

132+
void test_sparse_paths__check_toplevelwildcard(void)
133+
{
134+
git_sparse_checkout_init_options scopts = GIT_SPARSE_CHECKOUT_INIT_OPTIONS_INIT;
135+
g_repo = cl_git_sandbox_init("sparse");
136+
137+
cl_git_pass(git_sparse_checkout_init(g_repo, &scopts));
138+
{
139+
char *pattern_strings[] = {"/*"};
140+
git_strarray patterns = { pattern_strings, ARRAY_SIZE(pattern_strings) };
141+
cl_git_pass(git_sparse_checkout_add(g_repo, &patterns));
142+
}
143+
144+
char *matches[] = {
145+
"_", // Even with no include patterns, toplevel files are included.
146+
"A/",
147+
"A/_",
148+
};
149+
150+
size_t j;
151+
for ( j = 0; j < ARRAY_SIZE(matches); j++) {
152+
assert_is_checkout(matches[j]);
153+
}
154+
155+
}
156+
132157
void test_sparse_paths__validate_cone(void)
133158
{
134159
size_t i;
@@ -160,7 +185,8 @@ void test_sparse_paths__validate_cone(void)
160185
char *missing_parent_patterns[] = {
161186
"/A/B/",
162187
"/A/B/C/",
163-
"/*\n!/A/B/*/\n/A/B/C/D/"
188+
"/*\n!/A/B/*/\n/A/B/C/D/",
189+
"/A/\n!/A/B/*/\n/A/B/C/D/"
164190
};
165191

166192
for (i = 0; i < ARRAY_SIZE(good_patterns); i++) {

0 commit comments

Comments
 (0)