6
6
#include "repository.h"
7
7
#include "run-command.h"
8
8
#include "strbuf.h"
9
+ #include "string-list.h"
9
10
10
11
static char const * const builtin_sparse_checkout_usage [] = {
11
12
N_ ("git sparse-checkout (init|list|set|disable) <options>" ),
@@ -74,9 +75,65 @@ static int update_working_directory(void)
74
75
return result ;
75
76
}
76
77
78
+ static void write_cone_to_file (FILE * fp , struct pattern_list * pl )
79
+ {
80
+ int i ;
81
+ struct pattern_entry * pe ;
82
+ struct hashmap_iter iter ;
83
+ struct string_list sl = STRING_LIST_INIT_DUP ;
84
+
85
+ hashmap_for_each_entry (& pl -> parent_hashmap , & iter , pe , ent )
86
+ string_list_insert (& sl , pe -> pattern );
87
+
88
+ string_list_sort (& sl );
89
+ string_list_remove_duplicates (& sl , 0 );
90
+
91
+ fprintf (fp , "/*\n!/*/\n" );
92
+
93
+ for (i = 0 ; i < sl .nr ; i ++ ) {
94
+ char * pattern = sl .items [i ].string ;
95
+
96
+ if (strlen (pattern ))
97
+ fprintf (fp , "%s/\n!%s/*/\n" , pattern , pattern );
98
+ }
99
+
100
+ string_list_clear (& sl , 0 );
101
+
102
+ hashmap_for_each_entry (& pl -> recursive_hashmap , & iter , pe , ent )
103
+ string_list_insert (& sl , pe -> pattern );
104
+
105
+ string_list_sort (& sl );
106
+ string_list_remove_duplicates (& sl , 0 );
107
+
108
+ for (i = 0 ; i < sl .nr ; i ++ ) {
109
+ char * pattern = sl .items [i ].string ;
110
+ fprintf (fp , "%s/\n" , pattern );
111
+ }
112
+ }
113
+
114
+ static int write_patterns_and_update (struct pattern_list * pl )
115
+ {
116
+ char * sparse_filename ;
117
+ FILE * fp ;
118
+
119
+ sparse_filename = get_sparse_checkout_filename ();
120
+ fp = fopen (sparse_filename , "w" );
121
+
122
+ if (core_sparse_checkout_cone )
123
+ write_cone_to_file (fp , pl );
124
+ else
125
+ write_patterns_to_file (fp , pl );
126
+
127
+ fclose (fp );
128
+ free (sparse_filename );
129
+
130
+ return update_working_directory ();
131
+ }
132
+
77
133
enum sparse_checkout_mode {
78
134
MODE_NO_PATTERNS = 0 ,
79
135
MODE_ALL_PATTERNS = 1 ,
136
+ MODE_CONE_PATTERNS = 2 ,
80
137
};
81
138
82
139
static int set_config (enum sparse_checkout_mode mode )
@@ -93,18 +150,44 @@ static int set_config(enum sparse_checkout_mode mode)
93
150
"core.sparseCheckout" ,
94
151
mode ? "true" : NULL );
95
152
153
+ git_config_set_in_file_gently (config_path ,
154
+ "core.sparseCheckoutCone" ,
155
+ mode == MODE_CONE_PATTERNS ? "true" : NULL );
156
+
96
157
return 0 ;
97
158
}
98
159
160
+ static char const * const builtin_sparse_checkout_init_usage [] = {
161
+ N_ ("git sparse-checkout init [--cone]" ),
162
+ NULL
163
+ };
164
+
165
+ static struct sparse_checkout_init_opts {
166
+ int cone_mode ;
167
+ } init_opts ;
168
+
99
169
static int sparse_checkout_init (int argc , const char * * argv )
100
170
{
101
171
struct pattern_list pl ;
102
172
char * sparse_filename ;
103
173
FILE * fp ;
104
174
int res ;
105
175
struct object_id oid ;
176
+ int mode ;
106
177
107
- if (set_config (MODE_ALL_PATTERNS ))
178
+ static struct option builtin_sparse_checkout_init_options [] = {
179
+ OPT_BOOL (0 , "cone" , & init_opts .cone_mode ,
180
+ N_ ("initialize the sparse-checkout in cone mode" )),
181
+ OPT_END (),
182
+ };
183
+
184
+ argc = parse_options (argc , argv , NULL ,
185
+ builtin_sparse_checkout_init_options ,
186
+ builtin_sparse_checkout_init_usage , 0 );
187
+
188
+ mode = init_opts .cone_mode ? MODE_CONE_PATTERNS : MODE_ALL_PATTERNS ;
189
+
190
+ if (set_config (mode ))
108
191
return 1 ;
109
192
110
193
memset (& pl , 0 , sizeof (pl ));
@@ -136,18 +219,47 @@ static int sparse_checkout_init(int argc, const char **argv)
136
219
return update_working_directory ();
137
220
}
138
221
139
- static int write_patterns_and_update (struct pattern_list * pl )
222
+ static void insert_recursive_pattern (struct pattern_list * pl , struct strbuf * path )
140
223
{
141
- char * sparse_filename ;
142
- FILE * fp ;
224
+ struct pattern_entry * e = xmalloc (sizeof (* e ));
225
+ e -> patternlen = path -> len ;
226
+ e -> pattern = strbuf_detach (path , NULL );
227
+ hashmap_entry_init (& e -> ent , memhash (e -> pattern , e -> patternlen ));
143
228
144
- sparse_filename = get_sparse_checkout_filename ();
145
- fp = fopen (sparse_filename , "w" );
146
- write_patterns_to_file (fp , pl );
147
- fclose (fp );
148
- free (sparse_filename );
229
+ hashmap_add (& pl -> recursive_hashmap , & e -> ent );
149
230
150
- return update_working_directory ();
231
+ while (e -> patternlen ) {
232
+ char * slash = strrchr (e -> pattern , '/' );
233
+ char * oldpattern = e -> pattern ;
234
+ size_t newlen ;
235
+
236
+ if (slash == e -> pattern )
237
+ break ;
238
+
239
+ newlen = slash - e -> pattern ;
240
+ e = xmalloc (sizeof (struct pattern_entry ));
241
+ e -> patternlen = newlen ;
242
+ e -> pattern = xstrndup (oldpattern , newlen );
243
+ hashmap_entry_init (& e -> ent , memhash (e -> pattern , e -> patternlen ));
244
+
245
+ if (!hashmap_get_entry (& pl -> parent_hashmap , e , ent , NULL ))
246
+ hashmap_add (& pl -> parent_hashmap , & e -> ent );
247
+ }
248
+ }
249
+
250
+ static void strbuf_to_cone_pattern (struct strbuf * line , struct pattern_list * pl )
251
+ {
252
+ strbuf_trim (line );
253
+
254
+ strbuf_trim_trailing_dir_sep (line );
255
+
256
+ if (!line -> len )
257
+ return ;
258
+
259
+ if (line -> buf [0 ] != '/' )
260
+ strbuf_insert (line , 0 , "/" , 1 );
261
+
262
+ insert_recursive_pattern (pl , line );
151
263
}
152
264
153
265
static char const * const builtin_sparse_checkout_set_usage [] = {
@@ -180,16 +292,35 @@ static int sparse_checkout_set(int argc, const char **argv, const char *prefix)
180
292
builtin_sparse_checkout_set_usage ,
181
293
PARSE_OPT_KEEP_UNKNOWN );
182
294
183
- if (set_opts . use_stdin ) {
295
+ if (core_sparse_checkout_cone ) {
184
296
struct strbuf line = STRBUF_INIT ;
185
297
186
- while (!strbuf_getline (& line , stdin )) {
187
- char * buf = strbuf_detach (& line , NULL );
188
- add_pattern (buf , empty_base , 0 , & pl , 0 );
298
+ hashmap_init (& pl .recursive_hashmap , pl_hashmap_cmp , NULL , 0 );
299
+ hashmap_init (& pl .parent_hashmap , pl_hashmap_cmp , NULL , 0 );
300
+
301
+ if (set_opts .use_stdin ) {
302
+ while (!strbuf_getline (& line , stdin ))
303
+ strbuf_to_cone_pattern (& line , & pl );
304
+ } else {
305
+ for (i = 0 ; i < argc ; i ++ ) {
306
+ strbuf_setlen (& line , 0 );
307
+ strbuf_addstr (& line , argv [i ]);
308
+ strbuf_to_cone_pattern (& line , & pl );
309
+ }
189
310
}
190
311
} else {
191
- for (i = 0 ; i < argc ; i ++ )
192
- add_pattern (argv [i ], empty_base , 0 , & pl , 0 );
312
+ if (set_opts .use_stdin ) {
313
+ struct strbuf line = STRBUF_INIT ;
314
+
315
+ while (!strbuf_getline (& line , stdin )) {
316
+ size_t len ;
317
+ char * buf = strbuf_detach (& line , & len );
318
+ add_pattern (buf , empty_base , 0 , & pl , 0 );
319
+ }
320
+ } else {
321
+ for (i = 0 ; i < argc ; i ++ )
322
+ add_pattern (argv [i ], empty_base , 0 , & pl , 0 );
323
+ }
193
324
}
194
325
195
326
if (!core_apply_sparse_checkout ) {
0 commit comments