66#include "repository.h"
77#include "run-command.h"
88#include "strbuf.h"
9+ #include "string-list.h"
910
1011static char const * const builtin_sparse_checkout_usage [] = {
1112 N_ ("git sparse-checkout [init|add|list|disable]" ),
1213 NULL
1314};
1415
16+ static const char * const builtin_sparse_checkout_init_usage [] = {
17+ N_ ("git sparse-checkout init [--cone]" ),
18+ NULL
19+ };
20+
1521struct opts_sparse_checkout {
1622 const char * subcommand ;
1723 int read_stdin ;
24+ int cone ;
1825} opts ;
1926
2027static char * get_sparse_checkout_filename (void )
@@ -41,6 +48,60 @@ static void write_excludes_to_file(FILE *fp, struct exclude_list *el)
4148 }
4249}
4350
51+ static void write_cone_to_file (FILE * fp , struct exclude_list * el )
52+ {
53+ int i ;
54+ struct exclude_entry * entry ;
55+ struct hashmap_iter iter ;
56+ struct string_list sl = STRING_LIST_INIT_DUP ;
57+
58+ hashmap_iter_init (& el -> parent_hashmap , & iter );
59+ while ((entry = hashmap_iter_next (& iter ))) {
60+ char * pattern = xstrdup (entry -> pattern );
61+ char * converted = pattern ;
62+ if (pattern [0 ] == '/' )
63+ converted ++ ;
64+ if (pattern [entry -> patternlen - 1 ] == '/' )
65+ pattern [entry -> patternlen - 1 ] = 0 ;
66+ string_list_insert (& sl , converted );
67+ free (pattern );
68+ }
69+
70+ string_list_sort (& sl );
71+ string_list_remove_duplicates (& sl , 0 );
72+
73+ for (i = 0 ; i < sl .nr ; i ++ ) {
74+ char * pattern = sl .items [i ].string ;
75+
76+ if (!strcmp (pattern , "" ))
77+ fprintf (fp , "/*\n!/*/*\n" );
78+ else
79+ fprintf (fp , "/%s/*\n!/%s/*/*\n" , pattern , pattern );
80+ }
81+
82+ string_list_clear (& sl , 0 );
83+
84+ hashmap_iter_init (& el -> recursive_hashmap , & iter );
85+ while ((entry = hashmap_iter_next (& iter ))) {
86+ char * pattern = xstrdup (entry -> pattern );
87+ char * converted = pattern ;
88+ if (pattern [0 ] == '/' )
89+ converted ++ ;
90+ if (pattern [entry -> patternlen - 1 ] == '/' )
91+ pattern [entry -> patternlen - 1 ] = 0 ;
92+ string_list_insert (& sl , converted );
93+ free (pattern );
94+ }
95+
96+ string_list_sort (& sl );
97+ string_list_remove_duplicates (& sl , 0 );
98+
99+ for (i = 0 ; i < sl .nr ; i ++ ) {
100+ char * pattern = sl .items [i ].string ;
101+ fprintf (fp , "/%s/*\n" , pattern );
102+ }
103+ }
104+
44105static int sparse_checkout_list (int argc , const char * * argv )
45106{
46107 struct exclude_list el ;
@@ -141,8 +202,21 @@ static int sparse_checkout_init(int argc, const char **argv)
141202 char * sparse_filename ;
142203 FILE * fp ;
143204 int res ;
205+ enum sparse_checkout_mode mode ;
144206
145- if (sc_set_config (SPARSE_CHECKOUT_FULL ))
207+ static struct option builtin_sparse_checkout_init_options [] = {
208+ OPT_BOOL (0 , "cone" , & opts .cone ,
209+ N_ ("initialize the sparse-checkout in cone mode" )),
210+ OPT_END (),
211+ };
212+
213+ argc = parse_options (argc , argv , NULL ,
214+ builtin_sparse_checkout_init_options ,
215+ builtin_sparse_checkout_init_usage , 0 );
216+
217+ mode = opts .cone ? SPARSE_CHECKOUT_CONE : SPARSE_CHECKOUT_FULL ;
218+
219+ if (sc_set_config (mode ))
146220 return 1 ;
147221
148222 memset (& el , 0 , sizeof (el ));
@@ -183,6 +257,34 @@ static int sparse_checkout_init(int argc, const char **argv)
183257 return sc_read_tree ();
184258}
185259
260+ static void insert_recursive_pattern (struct exclude_list * el , struct strbuf * path )
261+ {
262+ struct exclude_entry * e = xmalloc (sizeof (struct exclude_entry ));
263+ e -> patternlen = path -> len ;
264+ e -> pattern = strbuf_detach (path , NULL );
265+ hashmap_entry_init (e , memhash (e -> pattern , e -> patternlen ));
266+
267+ hashmap_add (& el -> recursive_hashmap , e );
268+
269+ while (e -> patternlen ) {
270+ char * slash = strrchr (e -> pattern , '/' );
271+ char * oldpattern = e -> pattern ;
272+ size_t newlen ;
273+
274+ if (!slash )
275+ break ;
276+
277+ newlen = slash - e -> pattern ;
278+ e = xmalloc (sizeof (struct exclude_entry ));
279+ e -> patternlen = newlen ;
280+ e -> pattern = xstrndup (oldpattern , newlen );
281+ hashmap_entry_init (e , memhash (e -> pattern , e -> patternlen ));
282+
283+ if (!hashmap_get (& el -> parent_hashmap , e , NULL ))
284+ hashmap_add (& el -> parent_hashmap , e );
285+ }
286+ }
287+
186288static int sparse_checkout_add (int argc , const char * * argv )
187289{
188290 struct exclude_list el ;
@@ -196,11 +298,33 @@ static int sparse_checkout_add(int argc, const char **argv)
196298 add_excludes_from_file_to_list (sparse_filename , "" , 0 , & el , NULL );
197299
198300 fp = fopen (sparse_filename , "w" );
199- write_excludes_to_file (fp , & el );
200301
201- while (!strbuf_getline (& line , stdin )) {
202- strbuf_trim (& line );
203- fprintf (fp , "%s\n" , line .buf );
302+ if (core_sparse_checkout == SPARSE_CHECKOUT_FULL ) {
303+ write_excludes_to_file (fp , & el );
304+
305+ while (!strbuf_getline (& line , stdin )) {
306+ strbuf_trim (& line );
307+ fprintf (fp , "%s\n" , line .buf );
308+ }
309+ } else if (core_sparse_checkout == SPARSE_CHECKOUT_CONE ) {
310+ while (!strbuf_getline (& line , stdin )) {
311+ strbuf_trim (& line );
312+
313+ strbuf_trim_trailing_dir_sep (& line );
314+
315+ if (!line .len )
316+ continue ;
317+
318+ if (line .buf [0 ] == '/' )
319+ strbuf_remove (& line , 0 , 1 );
320+
321+ if (!line .len )
322+ continue ;
323+
324+ insert_recursive_pattern (& el , & line );
325+ }
326+
327+ write_cone_to_file (fp , & el );
204328 }
205329
206330 fclose (fp );
0 commit comments