From 5f4888567c49aee9c387edc0ec3ca54c3556a7fd Mon Sep 17 00:00:00 2001 From: Christoph Bartschat Date: Mon, 5 Feb 2024 15:55:28 -0800 Subject: [PATCH] Fix toplevel wildcard matching --- src/libgit2/sparse.c | 6 +++++- tests/libgit2/sparse/paths.c | 28 +++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/libgit2/sparse.c b/src/libgit2/sparse.c index 070e230cdb5..83d0af8ff7d 100644 --- a/src/libgit2/sparse.c +++ b/src/libgit2/sparse.c @@ -65,6 +65,10 @@ static bool pattern_matches_path(git_attr_fnmatch *match, git_attr_path *path, s if (HAS_FLAG(match, GIT_ATTR_FNMATCH_HASWILD)) { expected_extra_nesting = true; + if (match->length <= 1) { + // Top level wildcard always matches + return true; + } exact_match_length = match->length - 2; // Cut off the trailing "/*" } @@ -183,7 +187,7 @@ static int parse_sparse_file( bool matched = false; size_t k; git_attr_fnmatch *parent_match; - git_vector_foreach(&attrs->rules, k, parent_match) { + git_vector_rforeach(&attrs->rules, k, parent_match) { if (pattern_matches_path(parent_match, &parent_path, parent_length)) { matched = !HAS_FLAG(parent_match, GIT_ATTR_FNMATCH_NEGATIVE); break; diff --git a/tests/libgit2/sparse/paths.c b/tests/libgit2/sparse/paths.c index 769c40fb06c..33902a4c521 100644 --- a/tests/libgit2/sparse/paths.c +++ b/tests/libgit2/sparse/paths.c @@ -129,6 +129,31 @@ void test_sparse_paths__check_toplevel(void) } } +void test_sparse_paths__check_toplevelwildcard(void) +{ + git_sparse_checkout_init_options scopts = GIT_SPARSE_CHECKOUT_INIT_OPTIONS_INIT; + g_repo = cl_git_sandbox_init("sparse"); + + cl_git_pass(git_sparse_checkout_init(g_repo, &scopts)); + { + char *pattern_strings[] = {"/*"}; + git_strarray patterns = { pattern_strings, ARRAY_SIZE(pattern_strings) }; + cl_git_pass(git_sparse_checkout_add(g_repo, &patterns)); + } + + char *matches[] = { + "_", // Even with no include patterns, toplevel files are included. + "A/", + "A/_", + }; + + size_t j; + for ( j = 0; j < ARRAY_SIZE(matches); j++) { + assert_is_checkout(matches[j]); + } + +} + void test_sparse_paths__validate_cone(void) { size_t i; @@ -160,7 +185,8 @@ void test_sparse_paths__validate_cone(void) char *missing_parent_patterns[] = { "/A/B/", "/A/B/C/", - "/*\n!/A/B/*/\n/A/B/C/D/" + "/*\n!/A/B/*/\n/A/B/C/D/", + "/A/\n!/A/B/*/\n/A/B/C/D/" }; for (i = 0; i < ARRAY_SIZE(good_patterns); i++) {