test prerequisites: enumerate with commas
[gitweb.git] / builtin / fetch.c
index 09825c84d731014e075a6f77791f0681b7c4efb0..e8d0cca3e4110e1ae6db82f21c899c44460cb849 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 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;
@@ -45,6 +45,8 @@ static struct transport *gsecondary;
 static const char *submodule_prefix = "";
 static const char *recurse_submodules_default;
 static int shown_url = 0;
+static int refmap_alloc, refmap_nr;
+static const char **refmap_array;
 
 static int option_parse_recurse_submodules(const struct option *opt,
                                   const char *arg, int unset)
@@ -69,6 +71,19 @@ static int git_fetch_config(const char *k, const char *v, void *cb)
        return 0;
 }
 
+static int parse_refmap_arg(const struct option *opt, const char *arg, int unset)
+{
+       ALLOC_GROW(refmap_array, refmap_nr + 1, refmap_alloc);
+
+       /*
+        * "git fetch --refmap='' origin foo"
+        * can be used to tell the command not to store anywhere
+        */
+       if (*arg)
+               refmap_array[refmap_nr++] = arg;
+       return 0;
+}
+
 static struct option builtin_fetch_options[] = {
        OPT__VERBOSITY(&verbosity),
        OPT_BOOL(0, "all", &all,
@@ -105,6 +120,10 @@ static struct option builtin_fetch_options[] = {
        { 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")),
+       { OPTION_CALLBACK, 0, "refmap", NULL, N_("refmap"),
+         N_("specify fetch refmap"), PARSE_OPT_NONEG, parse_refmap_arg },
        OPT_END()
 };
 
@@ -276,6 +295,9 @@ static struct ref *get_ref_map(struct transport *transport,
        const struct ref *remote_refs = transport_get_remote_refs(transport);
 
        if (refspec_count) {
+               struct refspec *fetch_refspec;
+               int fetch_refspec_nr;
+
                for (i = 0; i < refspec_count; i++) {
                        get_fetch_map(remote_refs, &refspecs[i], &tail, 0);
                        if (refspecs[i].dst && refspecs[i].dst[0])
@@ -305,12 +327,21 @@ static struct ref *get_ref_map(struct transport *transport,
                 * by ref_remove_duplicates() in favor of one of these
                 * opportunistic entries with FETCH_HEAD_IGNORE.
                 */
-               for (i = 0; i < transport->remote->fetch_refspec_nr; i++)
-                       get_fetch_map(ref_map, &transport->remote->fetch[i],
-                                     &oref_tail, 1);
+               if (refmap_array) {
+                       fetch_refspec = parse_fetch_refspec(refmap_nr, refmap_array);
+                       fetch_refspec_nr = refmap_nr;
+               } else {
+                       fetch_refspec = transport->remote->fetch;
+                       fetch_refspec_nr = transport->remote->fetch_refspec_nr;
+               }
+
+               for (i = 0; i < fetch_refspec_nr; i++)
+                       get_fetch_map(ref_map, &fetch_refspec[i], &oref_tail, 1);
 
                if (tags == TAGS_SET)
                        get_fetch_map(remote_refs, tag_refspec, &tail, 0);
+       } else if (refmap_array) {
+               die("--refmap option is only meaningful with command-line refspec(s).");
        } else {
                /* Use the defaults */
                struct remote *remote = transport->remote;
@@ -524,6 +555,8 @@ static int iterate_ref_map(void *cb_data, unsigned char sha1[20])
        struct ref **rm = cb_data;
        struct ref *ref = *rm;
 
+       while (ref && ref->status == REF_STATUS_REJECT_SHALLOW)
+               ref = ref->next;
        if (!ref)
                return -1; /* end of the list */
        *rm = ref->next;
@@ -570,6 +603,13 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
                        struct ref *ref = NULL;
                        const char *merge_status_marker = "";
 
+                       if (rm->status == REF_STATUS_REJECT_SHALLOW) {
+                               if (want_status == FETCH_HEAD_MERGE)
+                                       warning(_("reject %s because shallow roots are not allowed to be updated"),
+                                               rm->peer_ref ? rm->peer_ref->name : rm->name);
+                               continue;
+                       }
+
                        commit = lookup_commit_reference_gently(rm->old_sha1, 1);
                        if (!commit)
                                rm->fetch_head_status = FETCH_HEAD_NOT_FOR_MERGE;
@@ -798,6 +838,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);
+       if (update_shallow)
+               set_option(transport, TRANS_OPT_UPDATE_SHALLOW, "yes");
        return transport;
 }
 
@@ -1013,7 +1055,6 @@ static int fetch_multiple(struct string_list *list)
 
 static int fetch_one(struct remote *remote, int argc, const char **argv)
 {
-       int i;
        static const char **refs = NULL;
        struct refspec *refspec;
        int ref_nr = 0;
@@ -1037,19 +1078,15 @@ static int fetch_one(struct remote *remote, int argc, const char **argv)
 
        if (argc > 0) {
                int j = 0;
+               int i;
                refs = xcalloc(argc + 1, sizeof(const char *));
                for (i = 0; i < argc; i++) {
                        if (!strcmp(argv[i], "tag")) {
-                               char *ref;
                                i++;
                                if (i >= argc)
                                        die(_("You need to specify a tag name."));
-                               ref = xmalloc(strlen(argv[i]) * 2 + 22);
-                               strcpy(ref, "refs/tags/");
-                               strcat(ref, argv[i]);
-                               strcat(ref, ":refs/tags/");
-                               strcat(ref, argv[i]);
-                               refs[j++] = ref;
+                               refs[j++] = xstrfmt("refs/tags/%s:refs/tags/%s",
+                                                   argv[i], argv[i]);
                        } else
                                refs[j++] = argv[i];
                }