summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDerrick Stolee <dstolee@microsoft.com>2019-11-21 22:04:45 (GMT)
committerJunio C Hamano <gitster@pobox.com>2019-11-22 07:11:44 (GMT)
commite9de487aa36aa75b5c9068c6bd07cfb8bf2ee955 (patch)
tree7547885c82f1eb655d8cf51a33e57beea1e63464
parent4dcd4def3ca46fc0e8cb28cbfc815a35dd2c3f1d (diff)
downloadgit-e9de487aa36aa75b5c9068c6bd07cfb8bf2ee955.zip
git-e9de487aa36aa75b5c9068c6bd07cfb8bf2ee955.tar.gz
git-e9de487aa36aa75b5c9068c6bd07cfb8bf2ee955.tar.bz2
sparse-checkout: sanitize for nested folders
If a user provides folders A/ and A/B/ for inclusion in a cone-mode sparse-checkout file, the parsing logic will notice that A/ appears both as a "parent" type pattern and as a "recursive" type pattern. This is unexpected and hence will complain via a warning and revert to the old logic for checking sparse-checkout patterns. Prevent this from happening accidentally by sanitizing the folders for this type of inclusion in the 'git sparse-checkout' builtin. This happens in two ways: 1. Do not include any parent patterns that also appear as recursive patterns. 2. Do not include any recursive patterns deeper than other recursive patterns. In order to minimize duplicate code for scanning parents, create hashmap_contains_parent() method. It takes a strbuf buffer to avoid reallocating a buffer when calling in a tight loop. Helped-by: Eric Wong <e@80x24.org> Helped-by: Johannes Schindelin <Johannes.Schindelin@gmx.de> Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--builtin/sparse-checkout.c22
-rwxr-xr-xt/t1091-sparse-checkout-builtin.sh11
2 files changed, 29 insertions, 4 deletions
diff --git a/builtin/sparse-checkout.c b/builtin/sparse-checkout.c
index 85cc801..55b337a 100644
--- a/builtin/sparse-checkout.c
+++ b/builtin/sparse-checkout.c
@@ -81,9 +81,17 @@ static void write_cone_to_file(FILE *fp, struct pattern_list *pl)
struct pattern_entry *pe;
struct hashmap_iter iter;
struct string_list sl = STRING_LIST_INIT_DUP;
+ struct strbuf parent_pattern = STRBUF_INIT;
- hashmap_for_each_entry(&pl->parent_hashmap, &iter, pe, ent)
- string_list_insert(&sl, pe->pattern);
+ hashmap_for_each_entry(&pl->parent_hashmap, &iter, pe, ent) {
+ if (hashmap_get_entry(&pl->recursive_hashmap, pe, ent, NULL))
+ continue;
+
+ if (!hashmap_contains_parent(&pl->recursive_hashmap,
+ pe->pattern,
+ &parent_pattern))
+ string_list_insert(&sl, pe->pattern);
+ }
string_list_sort(&sl);
string_list_remove_duplicates(&sl, 0);
@@ -99,8 +107,14 @@ static void write_cone_to_file(FILE *fp, struct pattern_list *pl)
string_list_clear(&sl, 0);
- hashmap_for_each_entry(&pl->recursive_hashmap, &iter, pe, ent)
- string_list_insert(&sl, pe->pattern);
+ hashmap_for_each_entry(&pl->recursive_hashmap, &iter, pe, ent) {
+ if (!hashmap_contains_parent(&pl->recursive_hashmap,
+ pe->pattern,
+ &parent_pattern))
+ string_list_insert(&sl, pe->pattern);
+ }
+
+ strbuf_release(&parent_pattern);
string_list_sort(&sl);
string_list_remove_duplicates(&sl, 0);
diff --git a/t/t1091-sparse-checkout-builtin.sh b/t/t1091-sparse-checkout-builtin.sh
index fbd46c3..b88d08d 100755
--- a/t/t1091-sparse-checkout-builtin.sh
+++ b/t/t1091-sparse-checkout-builtin.sh
@@ -237,4 +237,15 @@ test_expect_success 'cone mode: init and set' '
test_cmp expect dir
'
+test_expect_success 'cone mode: set with nested folders' '
+ git -C repo sparse-checkout set deep deep/deeper1/deepest 2>err &&
+ test_line_count = 0 err &&
+ cat >expect <<-EOF &&
+ /*
+ !/*/
+ /deep/
+ EOF
+ test_cmp repo/.git/info/sparse-checkout expect
+'
+
test_done