fetch/push: readd rsync support
[gitweb.git] / builtin-fetch.c
index 8b0fdbe90502e16117d0bf4ea2193e830fa7857f..ac68ff592eb10652fccdcf74f27763b1e2254f5e 100644 (file)
@@ -28,20 +28,37 @@ static void unlock_pack_on_signal(int signo)
        raise(signo);
 }
 
-static void find_merge_config(struct ref *ref_map, struct remote *remote)
+static void add_merge_config(struct ref **head,
+                          struct ref *remote_refs,
+                          struct branch *branch,
+                          struct ref ***tail)
 {
-       struct ref *rm = ref_map;
-       struct branch *branch = branch_get(NULL);
+       int i;
 
-       for (rm = ref_map; rm; rm = rm->next) {
-               if (!branch_has_merge_config(branch)) {
-                       if (remote && remote->fetch &&
-                           !strcmp(remote->fetch[0].src, rm->name))
-                               rm->merge = 1;
-               } else {
-                       if (branch_merges(branch, rm->name))
+       for (i = 0; i < branch->merge_nr; i++) {
+               struct ref *rm, **old_tail = *tail;
+               struct refspec refspec;
+
+               for (rm = *head; rm; rm = rm->next) {
+                       if (branch_merge_matches(branch, i, rm->name)) {
                                rm->merge = 1;
+                               break;
+                       }
                }
+               if (rm)
+                       continue;
+
+               /* Not fetched to a tracking branch?  We need to fetch
+                * it anyway to allow this branch's "branch.$name.merge"
+                * to be honored by git-pull.
+                */
+               refspec.src = branch->merge[i]->src;
+               refspec.dst = NULL;
+               refspec.pattern = 0;
+               refspec.force = 0;
+               get_fetch_map(remote_refs, &refspec, tail);
+               for (rm = *old_tail; rm; rm = rm->next)
+                       rm->merge = 1;
        }
 }
 
@@ -76,17 +93,22 @@ static struct ref *get_ref_map(struct transport *transport,
        } else {
                /* Use the defaults */
                struct remote *remote = transport->remote;
-               if (remote->fetch_refspec_nr) {
+               struct branch *branch = branch_get(NULL);
+               int has_merge = branch_has_merge_config(branch);
+               if (remote && (remote->fetch_refspec_nr || has_merge)) {
                        for (i = 0; i < remote->fetch_refspec_nr; i++) {
                                get_fetch_map(remote_refs, &remote->fetch[i], &tail);
                                if (remote->fetch[i].dst &&
                                    remote->fetch[i].dst[0])
                                        *autotags = 1;
+                               if (!i && !has_merge && ref_map &&
+                                   !remote->fetch[0].pattern)
+                                       ref_map->merge = 1;
                        }
-                       find_merge_config(ref_map, remote);
+                       if (has_merge)
+                               add_merge_config(&ref_map, remote_refs, branch, &tail);
                } else {
                        ref_map = get_remote_ref(remote_refs, "HEAD");
-
                        ref_map->merge = 1;
                }
        }
@@ -151,7 +173,8 @@ static int update_local_ref(struct ref *ref,
                return 0;
        }
 
-       if (!strcmp(ref->name, current_branch->name) &&
+       if (current_branch &&
+           !strcmp(ref->name, current_branch->name) &&
            !(update_head_ok || is_bare_repository()) &&
            !is_null_sha1(ref->old_sha1)) {
                /*
@@ -369,8 +392,7 @@ static int do_fetch(struct transport *transport,
        if (transport->remote->fetch_tags == -1)
                no_tags = 1;
 
-       if (!transport->ops || !transport->ops->get_refs_list ||
-           !transport->ops->fetch)
+       if (!transport->get_refs_list || !transport->fetch)
                die("Don't know how to fetch from %s", transport->url);
 
        /* if not appending, truncate FETCH_HEAD */
@@ -407,6 +429,17 @@ static int do_fetch(struct transport *transport,
        return 0;
 }
 
+static void set_option(const char *name, const char *value)
+{
+       int r = transport_set_option(transport, name, value);
+       if (r < 0)
+               die("Option \"%s\" value \"%s\" is not valid for %s\n",
+                       name, value, transport->url);
+       if (r > 0)
+               warning("Option \"%s\" is ignored for %s\n",
+                       name, transport->url);
+}
+
 int cmd_fetch(int argc, const char **argv, const char *prefix)
 {
        struct remote *remote;
@@ -496,16 +529,17 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
        else
                remote = remote_get(argv[i++]);
 
-       transport = transport_get(remote, remote->uri[0], 1);
+       transport = transport_get(remote, remote->url[0]);
        if (verbose >= 2)
                transport->verbose = 1;
        if (quiet)
                transport->verbose = 0;
        if (upload_pack)
-               transport_set_option(transport, TRANS_OPT_UPLOADPACK, upload_pack);
+               set_option(TRANS_OPT_UPLOADPACK, upload_pack);
        if (keep)
-               transport_set_option(transport, TRANS_OPT_KEEP, "yes");
-       transport_set_option(transport, TRANS_OPT_DEPTH, depth);
+               set_option(TRANS_OPT_KEEP, "yes");
+       if (depth)
+               set_option(TRANS_OPT_DEPTH, depth);
 
        if (!transport->url)
                die("Where do you want to fetch from today?");
@@ -529,8 +563,6 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
                }
                refs[j] = NULL;
                ref_nr = j;
-               for (j = 0; refs[j]; j++)
-                       printf("ref: %s\n", refs[j]);
        }
 
        signal(SIGINT, unlock_pack_on_signal);