fetch/pull: recurse into submodules when necessary
[gitweb.git] / builtin / fetch.c
index cbbde2d0ee15623299ded2c74d06a4be5bdcf548..23c249dbfb2b7b7e9a1423d22af4979170750dc4 100644 (file)
@@ -17,7 +17,7 @@
 static const char * const builtin_fetch_usage[] = {
        "git fetch [<options>] [<repository> [<refspec>...]]",
        "git fetch [<options>] <group>",
-       "git fetch --multiple [<options>] [<repository> | <group>]...",
+       "git fetch --multiple [<options>] [(<repository> | <group>)...]",
        "git fetch --all [<options>]",
        NULL
 };
@@ -29,13 +29,14 @@ enum {
 };
 
 static int all, append, dry_run, force, keep, multiple, prune, update_head_ok, verbosity;
-static int progress, recurse_submodules;
+static int progress, recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
 static int tags = TAGS_DEFAULT;
 static const char *depth;
 static const char *upload_pack;
 static struct strbuf default_rla = STRBUF_INIT;
 static struct transport *transport;
 static const char *submodule_prefix = "";
+static const char *recurse_submodules_default;
 
 static struct option builtin_fetch_options[] = {
        OPT__VERBOSITY(&verbosity),
@@ -45,8 +46,7 @@ static struct option builtin_fetch_options[] = {
                    "append to .git/FETCH_HEAD instead of overwriting"),
        OPT_STRING(0, "upload-pack", &upload_pack, "PATH",
                   "path to upload pack on remote end"),
-       OPT_BOOLEAN('f', "force", &force,
-                   "force overwrite of local branch"),
+       OPT__FORCE(&force, "force overwrite of local branch"),
        OPT_BOOLEAN('m', "multiple", &multiple,
                    "fetch from multiple remotes"),
        OPT_SET_INT('t', "tags", &tags,
@@ -54,9 +54,10 @@ static struct option builtin_fetch_options[] = {
        OPT_SET_INT('n', NULL, &tags,
                    "do not fetch all tags (--no-tags)", TAGS_UNSET),
        OPT_BOOLEAN('p', "prune", &prune,
-                   "prune tracking branches no longer on remote"),
-       OPT_BOOLEAN(0, "recurse-submodules", &recurse_submodules,
-                   "control recursive fetching of submodules"),
+                   "prune remote-tracking branches no longer on remote"),
+       OPT_SET_INT(0, "recurse-submodules", &recurse_submodules,
+                   "control recursive fetching of submodules",
+                   RECURSE_SUBMODULES_ON),
        OPT_BOOLEAN(0, "dry-run", &dry_run,
                    "dry run"),
        OPT_BOOLEAN('k', "keep", &keep, "keep downloaded pack"),
@@ -67,6 +68,9 @@ static struct option builtin_fetch_options[] = {
                   "deepen history of shallow clone"),
        { OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, "DIR",
                   "prepend this to submodule path output", PARSE_OPT_HIDDEN },
+       { OPTION_STRING, 0, "recurse-submodules-default",
+                  &recurse_submodules_default, NULL,
+                  "default mode for recursion", PARSE_OPT_HIDDEN },
        OPT_END()
 };
 
@@ -104,7 +108,7 @@ static void add_merge_config(struct ref **head,
                        continue;
 
                /*
-                * Not fetched to a tracking branch?  We need to fetch
+                * Not fetched to a remote-tracking branch?  We need to fetch
                 * it anyway to allow this branch's "branch.$name.merge"
                 * to be honored by 'git pull', but we do not have to
                 * fail if branch.$name.merge is misconfigured to point
@@ -152,7 +156,10 @@ static struct ref *get_ref_map(struct transport *transport,
                struct remote *remote = transport->remote;
                struct branch *branch = branch_get(NULL);
                int has_merge = branch_has_merge_config(branch);
-               if (remote && (remote->fetch_refspec_nr || has_merge)) {
+               if (remote &&
+                   (remote->fetch_refspec_nr ||
+                    /* Note: has_merge implies non-NULL branch->remote_name */
+                    (has_merge && !strcmp(branch->remote_name, remote->name)))) {
                        for (i = 0; i < remote->fetch_refspec_nr; i++) {
                                get_fetch_map(remote_refs, &remote->fetch[i], &tail, 0);
                                if (remote->fetch[i].dst &&
@@ -166,6 +173,8 @@ static struct ref *get_ref_map(struct transport *transport,
                         * if the remote we're fetching from is the same
                         * as given in branch.<name>.remote, we add the
                         * ref given in branch.<name>.merge, too.
+                        *
+                        * Note: has_merge implies non-NULL branch->remote_name
                         */
                        if (has_merge &&
                            !strcmp(branch->remote_name, remote->name))
@@ -273,6 +282,9 @@ static int update_local_ref(struct ref *ref,
                else {
                        msg = "storing head";
                        what = "[new branch]";
+                       if ((recurse_submodules != RECURSE_SUBMODULES_OFF) &&
+                           (recurse_submodules != RECURSE_SUBMODULES_ON))
+                               check_for_new_submodule_commits(ref->new_sha1);
                }
 
                r = s_update_ref(msg, ref, 0);
@@ -288,6 +300,9 @@ static int update_local_ref(struct ref *ref,
                strcpy(quickref, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV));
                strcat(quickref, "..");
                strcat(quickref, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV));
+               if ((recurse_submodules != RECURSE_SUBMODULES_OFF) &&
+                   (recurse_submodules != RECURSE_SUBMODULES_ON))
+                       check_for_new_submodule_commits(ref->new_sha1);
                r = s_update_ref("fast-forward", ref, 1);
                sprintf(display, "%c %-*s %-*s -> %s%s", r ? '!' : ' ',
                        TRANSPORT_SUMMARY_WIDTH, quickref, REFCOL_WIDTH, remote,
@@ -299,6 +314,9 @@ static int update_local_ref(struct ref *ref,
                strcpy(quickref, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV));
                strcat(quickref, "...");
                strcat(quickref, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV));
+               if ((recurse_submodules != RECURSE_SUBMODULES_OFF) &&
+                   (recurse_submodules != RECURSE_SUBMODULES_ON))
+                       check_for_new_submodule_commits(ref->new_sha1);
                r = s_update_ref("forced-update", ref, 1);
                sprintf(display, "%c %-*s %-*s -> %s  (%s)", r ? '!' : '+',
                        TRANSPORT_SUMMARY_WIDTH, quickref, REFCOL_WIDTH, remote,
@@ -360,7 +378,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
                        what = rm->name + 10;
                }
                else if (!prefixcmp(rm->name, "refs/remotes/")) {
-                       kind = "remote branch";
+                       kind = "remote-tracking branch";
                        what = rm->name + 13;
                }
                else {
@@ -665,10 +683,12 @@ static int do_fetch(struct transport *transport,
 
        for_each_ref(add_existing, &existing_refs);
 
-       if (transport->remote->fetch_tags == 2 && tags != TAGS_UNSET)
-               tags = TAGS_SET;
-       if (transport->remote->fetch_tags == -1)
-               tags = TAGS_UNSET;
+       if (tags == TAGS_DEFAULT) {
+               if (transport->remote->fetch_tags == 2)
+                       tags = TAGS_SET;
+               if (transport->remote->fetch_tags == -1)
+                       tags = TAGS_UNSET;
+       }
 
        if (!transport->get_refs_list || !transport->fetch)
                die("Don't know how to fetch from %s", transport->url);
@@ -795,7 +815,7 @@ static void add_options_to_argv(int *argc, const char **argv)
                argv[(*argc)++] = "--force";
        if (keep)
                argv[(*argc)++] = "--keep";
-       if (recurse_submodules)
+       if (recurse_submodules == RECURSE_SUBMODULES_ON)
                argv[(*argc)++] = "--recurse-submodules";
        if (verbosity >= 2)
                argv[(*argc)++] = "-v";
@@ -933,14 +953,19 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
                }
        }
 
-       if (!result && recurse_submodules) {
+       if (!result && (recurse_submodules != RECURSE_SUBMODULES_OFF)) {
                const char *options[10];
                int num_options = 0;
+               if (recurse_submodules_default) {
+                       int arg = parse_fetch_recurse_submodules_arg("--recurse-submodules-default", recurse_submodules_default);
+                       set_config_fetch_recurse_submodules(arg);
+               }
                gitmodules_config();
                git_config(submodule_config, NULL);
                add_options_to_argv(&num_options, options);
                result = fetch_populated_submodules(num_options, options,
                                                    submodule_prefix,
+                                                   recurse_submodules == RECURSE_SUBMODULES_ON,
                                                    verbosity < 0);
        }