7
7
#include "run-command.h"
8
8
#include "strbuf.h"
9
9
#include "string-list.h"
10
+ #include "cache.h"
11
+ #include "cache-tree.h"
12
+ #include "lockfile.h"
13
+ #include "resolve-undo.h"
14
+ #include "unpack-trees.h"
10
15
11
16
static char const * const builtin_sparse_checkout_usage [] = {
12
17
N_ ("git sparse-checkout [init|list|set|disable] <options>" ),
@@ -60,18 +65,82 @@ static int sparse_checkout_list(int argc, const char **argv)
60
65
return 0 ;
61
66
}
62
67
63
- static int update_working_directory (void )
68
+ struct update_data {
69
+ struct unpack_trees_options o ;
70
+ struct lock_file lock_file ;
71
+ struct object_id oid ;
72
+ struct tree * tree ;
73
+ struct tree_desc t ;
74
+ struct pattern_list * pl ;
75
+ };
76
+
77
+ static struct update_data * initialize_update_data (struct pattern_list * pl )
64
78
{
65
- struct argv_array argv = ARGV_ARRAY_INIT ;
66
- int result = 0 ;
67
- argv_array_pushl (& argv , "read-tree" , "-m" , "-u" , "HEAD" , NULL );
79
+ struct repository * r = the_repository ;
80
+ struct update_data * ud = xcalloc (1 , sizeof (* ud ));
68
81
69
- if (run_command_v_opt ( argv . argv , RUN_GIT_CMD )) {
70
- error ( _ ( "failed to update index with new sparse-checkout paths" ) );
71
- result = 1 ;
82
+ if (get_oid ( "HEAD" , & ud -> oid )) {
83
+ free ( ud );
84
+ return NULL ;
72
85
}
73
86
74
- argv_array_clear (& argv );
87
+ ud -> tree = parse_tree_indirect (& ud -> oid );
88
+ parse_tree (ud -> tree );
89
+ init_tree_desc (& ud -> t , ud -> tree -> buffer , ud -> tree -> size );
90
+
91
+ memset (& ud -> o , 0 , sizeof (ud -> o ));
92
+ ud -> o .verbose_update = isatty (2 );
93
+ ud -> o .merge = 1 ;
94
+ ud -> o .update = 1 ;
95
+ ud -> o .fn = oneway_merge ;
96
+ ud -> o .head_idx = -1 ;
97
+ ud -> o .src_index = r -> index ;
98
+ ud -> o .dst_index = r -> index ;
99
+ ud -> o .skip_sparse_checkout = 0 ;
100
+ ud -> o .pl = pl ;
101
+ ud -> o .keep_pattern_list = !!pl ;
102
+
103
+ resolve_undo_clear_index (r -> index );
104
+ setup_work_tree ();
105
+
106
+ cache_tree_free (& r -> index -> cache_tree );
107
+
108
+ repo_hold_locked_index (r , & ud -> lock_file , LOCK_DIE_ON_ERROR );
109
+
110
+ return ud ;
111
+ }
112
+
113
+ static void finish_update_data (struct update_data * ud )
114
+ {
115
+ struct repository * r = the_repository ;
116
+ prime_cache_tree (r , r -> index , ud -> tree );
117
+ write_locked_index (r -> index , & ud -> lock_file , COMMIT_LOCK );
118
+ }
119
+
120
+ static int update_working_directory (struct update_data * ud )
121
+ {
122
+ struct repository * r = the_repository ;
123
+ int complete = !ud ;
124
+ int result ;
125
+
126
+ if (repo_read_index_unmerged (r ))
127
+ die (_ ("You need to resolve your current index first" ));
128
+
129
+ if (!ud )
130
+ ud = initialize_update_data (NULL );
131
+
132
+ /* If we have no HEAD, then ud will be NULL. */
133
+ if (!ud )
134
+ return 0 ;
135
+
136
+ core_apply_sparse_checkout = 1 ;
137
+ result = unpack_trees (1 , & ud -> t , & ud -> o );
138
+
139
+ if (!result && complete ) {
140
+ finish_update_data (ud );
141
+ free (ud );
142
+ }
143
+
75
144
return result ;
76
145
}
77
146
@@ -145,7 +214,11 @@ static int sparse_checkout_init(int argc, const char **argv)
145
214
builtin_sparse_checkout_init_options ,
146
215
builtin_sparse_checkout_init_usage , 0 );
147
216
148
- mode = init_opts .cone_mode ? SPARSE_CHECKOUT_CONE : SPARSE_CHECKOUT_FULL ;
217
+ if (init_opts .cone_mode ) {
218
+ mode = SPARSE_CHECKOUT_CONE ;
219
+ core_sparse_checkout_cone = 1 ;
220
+ } else
221
+ mode = SPARSE_CHECKOUT_FULL ;
149
222
150
223
if (sc_set_config (mode ))
151
224
return 1 ;
@@ -173,12 +246,14 @@ static int sparse_checkout_init(int argc, const char **argv)
173
246
}
174
247
175
248
reset_dir :
176
- return update_working_directory ();
249
+ core_apply_sparse_checkout = 1 ;
250
+ return update_working_directory (NULL );
177
251
}
178
252
179
253
static void insert_recursive_pattern (struct pattern_list * pl , struct strbuf * path )
180
254
{
181
- struct pattern_entry * e = xmalloc (sizeof (struct pattern_entry ));
255
+ struct pattern_entry * e = xmalloc (sizeof (* e ));
256
+
182
257
e -> patternlen = path -> len ;
183
258
e -> pattern = strbuf_detach (path , NULL );
184
259
hashmap_entry_init (e , memhash (e -> pattern , e -> patternlen ));
@@ -190,7 +265,7 @@ static void insert_recursive_pattern(struct pattern_list *pl, struct strbuf *pat
190
265
char * oldpattern = e -> pattern ;
191
266
size_t newlen ;
192
267
193
- if (! slash )
268
+ if (slash == e -> pattern )
194
269
break ;
195
270
196
271
newlen = slash - e -> pattern ;
@@ -232,7 +307,7 @@ static void write_cone_to_file(FILE *fp, struct pattern_list *pl)
232
307
char * pattern = sl .items [i ].string ;
233
308
234
309
if (strlen (pattern ))
235
- fprintf (fp , "/ %s/\n!/ %s/*/\n" , pattern , pattern );
310
+ fprintf (fp , "%s/\n!%s/*/\n" , pattern , pattern );
236
311
}
237
312
238
313
string_list_clear (& sl , 0 );
@@ -252,28 +327,58 @@ static void write_cone_to_file(FILE *fp, struct pattern_list *pl)
252
327
253
328
for (i = 0 ; i < sl .nr ; i ++ ) {
254
329
char * pattern = sl .items [i ].string ;
255
- fprintf (fp , "/ %s/\n" , pattern );
330
+ fprintf (fp , "%s/\n" , pattern );
256
331
}
257
332
}
258
333
259
334
static int write_patterns_and_update (struct pattern_list * pl )
260
335
{
261
336
char * sparse_filename ;
262
337
FILE * fp ;
338
+ int fd ;
339
+ struct lock_file lk = LOCK_INIT ;
340
+ int result ;
341
+ struct update_data * ud ;
342
+
343
+ /* take index.lock */
344
+ ud = initialize_update_data (pl );
263
345
264
346
sparse_filename = get_sparse_checkout_filename ();
265
- fp = fopen (sparse_filename , "w" );
347
+
348
+ /* take sparse-checkout.lock */
349
+ fd = hold_lock_file_for_update (& lk , sparse_filename ,
350
+ LOCK_DIE_ON_ERROR );
351
+
352
+ result = update_working_directory (ud );
353
+ if (result ) {
354
+ rollback_lock_file (& lk );
355
+ free (sparse_filename );
356
+ clear_pattern_list (pl );
357
+ free (ud );
358
+ update_working_directory (NULL );
359
+ return result ;
360
+ }
361
+
362
+ fp = fdopen (fd , "w" );
266
363
267
364
if (core_sparse_checkout_cone )
268
365
write_cone_to_file (fp , pl );
269
366
else
270
367
write_patterns_to_file (fp , pl );
271
368
272
- fclose (fp );
273
- free (sparse_filename );
369
+ fflush (fp );
370
+
371
+ /* commit sparse-checkout.lock file */
372
+ commit_lock_file (& lk );
274
373
374
+ /* commit index.lock file */
375
+ finish_update_data (ud );
376
+ free (ud );
377
+
378
+ free (sparse_filename );
275
379
clear_pattern_list (pl );
276
- return update_working_directory ();
380
+
381
+ return 0 ;
277
382
}
278
383
279
384
static void strbuf_to_cone_pattern (struct strbuf * line , struct pattern_list * pl )
@@ -285,11 +390,8 @@ static void strbuf_to_cone_pattern(struct strbuf *line, struct pattern_list *pl)
285
390
if (!line -> len )
286
391
return ;
287
392
288
- if (line -> buf [0 ] == '/' )
289
- strbuf_remove (line , 0 , 1 );
290
-
291
- if (!line -> len )
292
- return ;
393
+ if (line -> buf [0 ] != '/' )
394
+ strbuf_insert (line , 0 , "/" , 1 );
293
395
294
396
insert_recursive_pattern (pl , line );
295
397
}
@@ -307,6 +409,7 @@ static int sparse_checkout_set(int argc, const char **argv, const char *prefix)
307
409
{
308
410
int i ;
309
411
struct pattern_list pl ;
412
+ static const char * empty_base = "" ;
310
413
311
414
static struct option builtin_sparse_checkout_set_options [] = {
312
415
OPT_BOOL (0 , "stdin" , & set_opts .use_stdin ,
@@ -325,6 +428,7 @@ static int sparse_checkout_set(int argc, const char **argv, const char *prefix)
325
428
struct strbuf line = STRBUF_INIT ;
326
429
hashmap_init (& pl .recursive_hashmap , pl_hashmap_cmp , NULL , 0 );
327
430
hashmap_init (& pl .parent_hashmap , pl_hashmap_cmp , NULL , 0 );
431
+ pl .use_cone_patterns = 1 ;
328
432
329
433
if (set_opts .use_stdin ) {
330
434
while (!strbuf_getline (& line , stdin ))
@@ -343,11 +447,11 @@ static int sparse_checkout_set(int argc, const char **argv, const char *prefix)
343
447
while (!strbuf_getline (& line , stdin )) {
344
448
size_t len ;
345
449
char * buf = strbuf_detach (& line , & len );
346
- add_pattern (buf , buf , len , & pl , 0 );
450
+ add_pattern (buf , empty_base , 0 , & pl , 0 );
347
451
}
348
452
} else {
349
453
for (i = 0 ; i < argc ; i ++ )
350
- add_pattern (argv [i ], argv [ i ], strlen ( argv [ i ]) , & pl , 0 );
454
+ add_pattern (argv [i ], empty_base , 0 , & pl , 0 );
351
455
}
352
456
}
353
457
@@ -367,7 +471,9 @@ static int sparse_checkout_disable(int argc, const char **argv)
367
471
fprintf (fp , "/*\n" );
368
472
fclose (fp );
369
473
370
- if (update_working_directory ())
474
+ core_apply_sparse_checkout = 1 ;
475
+ core_sparse_checkout_cone = 0 ;
476
+ if (update_working_directory (NULL ))
371
477
die (_ ("error while refreshing working directory" ));
372
478
373
479
unlink (sparse_filename );
0 commit comments