fetch: add --update-shallow to accept refs that update .git/shallow
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>
Thu, 5 Dec 2013 13:02:42 +0000 (20:02 +0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 11 Dec 2013 00:14:17 +0000 (16:14 -0800)
The same steps are done as in when --update-shallow is not given. The
only difference is we now add all shallow commits in "ours" and
"theirs" to .git/shallow (aka "step 8").

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/fetch-options.txt
builtin/fetch.c
fetch-pack.c
fetch-pack.h
t/t5537-fetch-shallow.sh
transport.c
transport.h
index a83d2b4778a016e8d8f6ead29d9122a7eff49fdb..54043e3633af37585e87e80077d4f31a27731d60 100644 (file)
 If the source repository is shallow, fetch as much as possible so that
 the current repository has the same history as the source repository.
 
 If the source repository is shallow, fetch as much as possible so that
 the current repository has the same history as the source repository.
 
+--update-shallow::
+       By default when fetching from a shallow repository,
+       `git fetch` refuses refs that require updating
+       .git/shallow. This option updates .git/shallow and accept such
+       refs.
+
 ifndef::git-pull[]
 --dry-run::
        Show what would be done, without making any changes.
 ifndef::git-pull[]
 --dry-run::
        Show what would be done, without making any changes.
index 7b41a7e388791466cc6c15e55be1bcebb5b3e69f..d2e4fc03d857b8b29bc871c5f983dddb93498ed3 100644 (file)
@@ -36,7 +36,7 @@ static int prune = -1; /* unspecified */
 
 static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosity;
 static int progress = -1, recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
 
 static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosity;
 static int progress = -1, recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
-static int tags = TAGS_DEFAULT, unshallow;
+static int tags = TAGS_DEFAULT, unshallow, update_shallow;
 static const char *depth;
 static const char *upload_pack;
 static struct strbuf default_rla = STRBUF_INIT;
 static const char *depth;
 static const char *upload_pack;
 static struct strbuf default_rla = STRBUF_INIT;
@@ -104,6 +104,8 @@ static struct option builtin_fetch_options[] = {
        { OPTION_STRING, 0, "recurse-submodules-default",
                   &recurse_submodules_default, NULL,
                   N_("default mode for recursion"), PARSE_OPT_HIDDEN },
        { OPTION_STRING, 0, "recurse-submodules-default",
                   &recurse_submodules_default, NULL,
                   N_("default mode for recursion"), PARSE_OPT_HIDDEN },
+       OPT_BOOL(0, "update-shallow", &update_shallow,
+                N_("accept refs that update .git/shallow")),
        OPT_END()
 };
 
        OPT_END()
 };
 
@@ -768,6 +770,8 @@ static struct transport *prepare_transport(struct remote *remote)
                set_option(transport, TRANS_OPT_KEEP, "yes");
        if (depth)
                set_option(transport, TRANS_OPT_DEPTH, depth);
                set_option(transport, TRANS_OPT_KEEP, "yes");
        if (depth)
                set_option(transport, TRANS_OPT_DEPTH, depth);
+       if (update_shallow)
+               set_option(transport, TRANS_OPT_UPDATE_SHALLOW, "yes");
        return transport;
 }
 
        return transport;
 }
 
index 34c544d0ca9e32dd2f28c572100040f054476db5..a2d1b4ab28aa94b6e685cd7bac1fb18ed1a6d96d 100644 (file)
@@ -993,6 +993,33 @@ static void update_shallow(struct fetch_pack_args *args,
                sha1_array_append(&ref, sought[i]->old_sha1);
        si->ref = &ref;
 
                sha1_array_append(&ref, sought[i]->old_sha1);
        si->ref = &ref;
 
+       if (args->update_shallow) {
+               /*
+                * remote is also shallow, .git/shallow may be updated
+                * so all refs can be accepted. Make sure we only add
+                * shallow roots that are actually reachable from new
+                * refs.
+                */
+               struct sha1_array extra = SHA1_ARRAY_INIT;
+               unsigned char (*sha1)[20] = si->shallow->sha1;
+               assign_shallow_commits_to_refs(si, NULL, NULL);
+               if (!si->nr_ours && !si->nr_theirs) {
+                       sha1_array_clear(&ref);
+                       return;
+               }
+               for (i = 0; i < si->nr_ours; i++)
+                       sha1_array_append(&extra, sha1[si->ours[i]]);
+               for (i = 0; i < si->nr_theirs; i++)
+                       sha1_array_append(&extra, sha1[si->theirs[i]]);
+               setup_alternate_shallow(&shallow_lock,
+                                       &alternate_shallow_file,
+                                       &extra);
+               commit_lock_file(&shallow_lock);
+               sha1_array_clear(&extra);
+               sha1_array_clear(&ref);
+               return;
+       }
+
        /*
         * remote is also shallow, check what ref is safe to update
         * without updating .git/shallow
        /*
         * remote is also shallow, check what ref is safe to update
         * without updating .git/shallow
index ce595376b74645e06e7247ab285d8c38709347c7..ada02f51c162a72d58782f315e648f2de8340d61 100644 (file)
@@ -23,6 +23,7 @@ struct fetch_pack_args {
        unsigned check_self_contained_and_connected:1;
        unsigned self_contained_and_connected:1;
        unsigned cloning:1;
        unsigned check_self_contained_and_connected:1;
        unsigned self_contained_and_connected:1;
        unsigned cloning:1;
+       unsigned update_shallow:1;
 };
 
 /*
 };
 
 /*
index 022cb2c990152c858810d263c64e32f8f75ffb75..3ae9092f5c2511e075c1bf6c215ea773f738f1f9 100755 (executable)
@@ -141,4 +141,36 @@ EOF
        )
 '
 
        )
 '
 
+test_expect_success 'fetch --update-shallow' '
+       (
+       cd shallow &&
+       git checkout master &&
+       commit 7 &&
+       git tag -m foo heavy-tag HEAD^ &&
+       git tag light-tag HEAD^:tracked
+       ) &&
+       (
+       cd notshallow &&
+       git fetch --update-shallow ../shallow/.git refs/heads/*:refs/remotes/shallow/* &&
+       git fsck &&
+       git for-each-ref --sort=refname --format="%(refname)" >actual.refs &&
+       cat <<EOF >expect.refs &&
+refs/remotes/shallow/master
+refs/remotes/shallow/no-shallow
+refs/tags/heavy-tag
+refs/tags/light-tag
+EOF
+       test_cmp expect.refs actual.refs &&
+       git log --format=%s shallow/master >actual &&
+       cat <<EOF >expect &&
+7
+6
+5
+4
+3
+EOF
+       test_cmp expect actual
+       )
+'
+
 test_done
 test_done
index 491360be2c4225cc1208bb75dacd1d09ebe476b5..a09fdb6df2a7a4a9b5ad1b381c8cafb4dfcc9972 100644 (file)
@@ -477,6 +477,9 @@ static int set_git_option(struct git_transport_options *opts,
        } else if (!strcmp(name, TRANS_OPT_KEEP)) {
                opts->keep = !!value;
                return 0;
        } else if (!strcmp(name, TRANS_OPT_KEEP)) {
                opts->keep = !!value;
                return 0;
+       } else if (!strcmp(name, TRANS_OPT_UPDATE_SHALLOW)) {
+               opts->update_shallow = !!value;
+               return 0;
        } else if (!strcmp(name, TRANS_OPT_DEPTH)) {
                if (!value)
                        opts->depth = 0;
        } else if (!strcmp(name, TRANS_OPT_DEPTH)) {
                if (!value)
                        opts->depth = 0;
@@ -543,6 +546,7 @@ static int fetch_refs_via_pack(struct transport *transport,
        args.check_self_contained_and_connected =
                data->options.check_self_contained_and_connected;
        args.cloning = transport->cloning;
        args.check_self_contained_and_connected =
                data->options.check_self_contained_and_connected;
        args.cloning = transport->cloning;
+       args.update_shallow = data->options.update_shallow;
 
        if (!data->got_remote_heads) {
                connect_setup(transport, 0, 0);
 
        if (!data->got_remote_heads) {
                connect_setup(transport, 0, 0);
index 59842d49947b5e6bb502dcd17405c302c61d0c9b..02ea248db18a558674825384a5d2678a45483873 100644 (file)
@@ -11,6 +11,7 @@ struct git_transport_options {
        unsigned followtags : 1;
        unsigned check_self_contained_and_connected : 1;
        unsigned self_contained_and_connected : 1;
        unsigned followtags : 1;
        unsigned check_self_contained_and_connected : 1;
        unsigned self_contained_and_connected : 1;
+       unsigned update_shallow : 1;
        int depth;
        const char *uploadpack;
        const char *receivepack;
        int depth;
        const char *uploadpack;
        const char *receivepack;
@@ -152,6 +153,9 @@ struct transport *transport_get(struct remote *, const char *);
 /* Aggressively fetch annotated tags if possible */
 #define TRANS_OPT_FOLLOWTAGS "followtags"
 
 /* Aggressively fetch annotated tags if possible */
 #define TRANS_OPT_FOLLOWTAGS "followtags"
 
+/* Accept refs that may update .git/shallow without --depth */
+#define TRANS_OPT_UPDATE_SHALLOW "updateshallow"
+
 /**
  * Returns 0 if the option was used, non-zero otherwise. Prints a
  * message to stderr if the option is not used.
 /**
  * Returns 0 if the option was used, non-zero otherwise. Prints a
  * message to stderr if the option is not used.