sparse-checkout: optimize string_list construction and add tests to verify deduplication.
Improve O(n^2) complexity to O(n log n) while building a sorted 'string_list' by constructing it unsorted then sorting it followed by removing duplicates. sparse-checkout deduplicates repeated cone-mode patterns, but this behaviour was previously untested, add tests that verify that sparse-checkout file contain each cone pattern only once and sparse-checkout list reports each pattern only once. Signed-off-by: Amisha Chhajed <amishhhaaaa@gmail.com> Acked-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Amisha Chhajed committed
Jan 21, 2026 at 18:30 UTC
49223593fd743998d13fcd27fceaf1e0095bb08e
2 files changed
+52
-3
builtin/sparse-checkout.c
+4
-3
@@ -91,10 +91,11 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix,
91
92
hashmap_for_each_entry(&pl.recursive_hashmap, &iter, pe, ent) {
93
/* pe->pattern starts with "/", skip it */
94
- string_list_insert(&sl, pe->pattern + 1);
94
+ string_list_append(&sl, pe->pattern + 1);
95
}
96
97
string_list_sort(&sl);
98
+ string_list_remove_duplicates(&sl, 0);
99
100
for (i = 0; i < sl.nr; i++) {
101
quote_c_style(sl.items[i].string, NULL, stdout, 0);
@@ -289,7 +290,7 @@ static void write_cone_to_file(FILE *fp, struct pattern_list *pl)
290
if (!hashmap_contains_parent(&pl->recursive_hashmap,
291
pe->pattern,
292
&parent_pattern))
292
- string_list_insert(&sl, pe->pattern);
293
+ string_list_append(&sl, pe->pattern);
294
}
295
296
string_list_sort(&sl);
@@ -311,7 +312,7 @@ static void write_cone_to_file(FILE *fp, struct pattern_list *pl)
312
if (!hashmap_contains_parent(&pl->recursive_hashmap,
313
pe->pattern,
314
&parent_pattern))
314
- string_list_insert(&sl, pe->pattern);
315
+ string_list_append(&sl, pe->pattern);
316
}
317
318
strbuf_release(&parent_pattern);
t/t1091-sparse-checkout-builtin.sh
+48
@@ -817,6 +817,54 @@ test_expect_success 'cone mode clears ignored subdirectories' '
817
test_cmp expect out
818
'
819
820
+test_expect_success 'sparse-checkout deduplicates repeated cone patterns' '
821
+ rm -f repo/.git/info/sparse-checkout &&
822
+ git -C repo sparse-checkout init --cone &&
823
+ git -C repo sparse-checkout add --stdin <<-\EOF &&
824
+ foo/bar/baz
825
+ a/b/c
826
+ foo/bar/baz
827
+ a/b
828
+ EOF
829
+ cat >expect <<-\EOF &&
830
+ /*
831
+ !/*/
832
+ /a/
833
+ !/a/*/
834
+ /foo/
835
+ !/foo/*/
836
+ /foo/bar/
837
+ !/foo/bar/*/
838
+ /a/b/
839
+ /foo/bar/baz/
840
+ EOF
841
+ test_cmp expect repo/.git/info/sparse-checkout
842
+'
843
+
844
+test_expect_success 'sparse-checkout list deduplicates repeated cone patterns' '
845
+ rm -f repo/.git/info/sparse-checkout &&
846
+ git -C repo sparse-checkout init --cone &&
847
+ cat <<-\EOF >repo/.git/info/sparse-checkout &&
848
+ /*
849
+ !/*/
850
+ /a/
851
+ !/a/*/
852
+ /foo/
853
+ !/foo/*/
854
+ /foo/bar/
855
+ !/foo/bar/*/
856
+ /a/b/
857
+ /foo/bar/baz/
858
+ /foo/bar/baz/
859
+ EOF
860
+ git -C repo sparse-checkout list >actual &&
861
+ cat <<-\EOF >expect &&
862
+ a/b
863
+ foo/bar/baz
864
+ EOF
865
+ test_cmp expect actual
866
+'
867
+
868
test_expect_success 'malformed cone-mode patterns' '
869
git -C repo sparse-checkout init --cone &&
870
mkdir -p repo/foo/bar &&