@matheusbsbs / matheus-bagliano / commits / 416adc8711
Fork 0

sparse-checkout: update working directory in-process for 'init'

The 'git sparse-checkout init' subcommand previously wrote directly to the sparse-checkout file and then updated the working directory. This may fail if there are modified files not included in the initial pattern set. However, that left a populated sparse-checkout file. Use the in-process working directory update to guarantee that the init subcommand only changes the sparse-checkout file if the working directory update succeeds. Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Derrick Stolee committed Nov 21, 2019 at 22:04 UTC 416adc8711d16c5231693f19ca483dd3d59bef5d
1 file changed +20 -16
builtin/sparse-checkout.c
+20 -16
@@ -13,6 +13,8 @@
13 #include "resolve-undo.h"
14 #include "unpack-trees.h"
15
16 +static const char *empty_base = "";
17 +
18 static char const * const builtin_sparse_checkout_usage[] = {
19 N_("git sparse-checkout (init|list|set|disable) <options>"),
20 NULL
@@ -243,10 +245,10 @@ static int sparse_checkout_init(int argc, const char **argv)
245 {
246 struct pattern_list pl;
247 char *sparse_filename;
246 - FILE *fp;
248 int res;
249 struct object_id oid;
250 int mode;
251 + struct strbuf pattern = STRBUF_INIT;
252
253 static struct option builtin_sparse_checkout_init_options[] = {
254 OPT_BOOL(0, "cone", &init_opts.cone_mode,
@@ -275,26 +277,30 @@ static int sparse_checkout_init(int argc, const char **argv)
277 /* If we already have a sparse-checkout file, use it. */
278 if (res >= 0) {
279 free(sparse_filename);
278 - goto reset_dir;
280 + core_apply_sparse_checkout = 1;
281 + return update_working_directory(NULL);
282 }
283
281 - /* initial mode: all blobs at root */
282 - fp = xfopen(sparse_filename, "w");
283 - if (!fp)
284 - die(_("failed to open '%s'"), sparse_filename);
284 + if (get_oid("HEAD", &oid)) {
285 + FILE *fp;
286
286 - free(sparse_filename);
287 - fprintf(fp, "/*\n!/*/\n");
288 - fclose(fp);
287 + /* assume we are in a fresh repo, but update the sparse-checkout file */
288 + fp = xfopen(sparse_filename, "w");
289 + if (!fp)
290 + die(_("failed to open '%s'"), sparse_filename);
291
290 - if (get_oid("HEAD", &oid)) {
291 - /* assume we are in a fresh repo */
292 + free(sparse_filename);
293 + fprintf(fp, "/*\n!/*/\n");
294 + fclose(fp);
295 return 0;
296 }
297
295 -reset_dir:
296 - core_apply_sparse_checkout = 1;
297 - return update_working_directory(NULL);
298 + strbuf_addstr(&pattern, "/*");
299 + add_pattern(strbuf_detach(&pattern, NULL), empty_base, 0, &pl, 0);
300 + strbuf_addstr(&pattern, "!/*/");
301 + add_pattern(strbuf_detach(&pattern, NULL), empty_base, 0, &pl, 0);
302 +
303 + return write_patterns_and_update(&pl);
304 }
305
306 static void insert_recursive_pattern(struct pattern_list *pl, struct strbuf *path)
@@ -351,7 +357,6 @@ static struct sparse_checkout_set_opts {
357
358 static int sparse_checkout_set(int argc, const char **argv, const char *prefix)
359 {
354 - static const char *empty_base = "";
360 int i;
361 struct pattern_list pl;
362 int result;
@@ -419,7 +424,6 @@ static int sparse_checkout_set(int argc, const char **argv, const char *prefix)
424
425 static int sparse_checkout_disable(int argc, const char **argv)
426 {
422 - static const char *empty_base = "";
427 struct pattern_list pl;
428 struct strbuf match_all = STRBUF_INIT;
429