]> git.ipfire.org Git - thirdparty/git.git/commitdiff
sparse-checkout: update working directory in-process for 'init'
authorDerrick Stolee <dstolee@microsoft.com>
Thu, 21 Nov 2019 22:04:50 +0000 (22:04 +0000)
committerJunio C Hamano <gitster@pobox.com>
Fri, 22 Nov 2019 07:11:45 +0000 (16:11 +0900)
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>
builtin/sparse-checkout.c

index 9a620ff014e739319beeb998a8e4acca310440a8..5dbfb2a7e0c6f81fd4cf190aec297424046cfe0d 100644 (file)
@@ -13,6 +13,8 @@
 #include "resolve-undo.h"
 #include "unpack-trees.h"
 
+static const char *empty_base = "";
+
 static char const * const builtin_sparse_checkout_usage[] = {
        N_("git sparse-checkout (init|list|set|disable) <options>"),
        NULL
@@ -243,10 +245,10 @@ static int sparse_checkout_init(int argc, const char **argv)
 {
        struct pattern_list pl;
        char *sparse_filename;
-       FILE *fp;
        int res;
        struct object_id oid;
        int mode;
+       struct strbuf pattern = STRBUF_INIT;
 
        static struct option builtin_sparse_checkout_init_options[] = {
                OPT_BOOL(0, "cone", &init_opts.cone_mode,
@@ -275,26 +277,30 @@ static int sparse_checkout_init(int argc, const char **argv)
        /* If we already have a sparse-checkout file, use it. */
        if (res >= 0) {
                free(sparse_filename);
-               goto reset_dir;
+               core_apply_sparse_checkout = 1;
+               return update_working_directory(NULL);
        }
 
-       /* initial mode: all blobs at root */
-       fp = xfopen(sparse_filename, "w");
-       if (!fp)
-               die(_("failed to open '%s'"), sparse_filename);
+       if (get_oid("HEAD", &oid)) {
+               FILE *fp;
 
-       free(sparse_filename);
-       fprintf(fp, "/*\n!/*/\n");
-       fclose(fp);
+               /* assume we are in a fresh repo, but update the sparse-checkout file */
+               fp = xfopen(sparse_filename, "w");
+               if (!fp)
+                       die(_("failed to open '%s'"), sparse_filename);
 
-       if (get_oid("HEAD", &oid)) {
-               /* assume we are in a fresh repo */
+               free(sparse_filename);
+               fprintf(fp, "/*\n!/*/\n");
+               fclose(fp);
                return 0;
        }
 
-reset_dir:
-       core_apply_sparse_checkout = 1;
-       return update_working_directory(NULL);
+       strbuf_addstr(&pattern, "/*");
+       add_pattern(strbuf_detach(&pattern, NULL), empty_base, 0, &pl, 0);
+       strbuf_addstr(&pattern, "!/*/");
+       add_pattern(strbuf_detach(&pattern, NULL), empty_base, 0, &pl, 0);
+
+       return write_patterns_and_update(&pl);
 }
 
 static void insert_recursive_pattern(struct pattern_list *pl, struct strbuf *path)
@@ -351,7 +357,6 @@ static struct sparse_checkout_set_opts {
 
 static int sparse_checkout_set(int argc, const char **argv, const char *prefix)
 {
-       static const char *empty_base = "";
        int i;
        struct pattern_list pl;
        int result;
@@ -419,7 +424,6 @@ static int sparse_checkout_set(int argc, const char **argv, const char *prefix)
 
 static int sparse_checkout_disable(int argc, const char **argv)
 {
-       static const char *empty_base = "";
        struct pattern_list pl;
        struct strbuf match_all = STRBUF_INIT;