t3600: Use test prerequisite tags
[gitweb.git] / remote.c
index aed760ee3aca4df344646db698b5bec5ec83ef8b..baa50aab6573738059a9a71a224acb6877257255 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -39,6 +39,7 @@ static int branches_nr;
 
 static struct branch *current_branch;
 static const char *default_remote_name;
+static int explicit_default_remote_name;
 
 static struct rewrite **rewrite;
 static int rewrite_alloc;
@@ -331,8 +332,10 @@ static int handle_config(const char *key, const char *value, void *cb)
                        if (!value)
                                return config_error_nonbool(key);
                        branch->remote_name = xstrdup(value);
-                       if (branch == current_branch)
+                       if (branch == current_branch) {
                                default_remote_name = branch->remote_name;
+                               explicit_default_remote_name = 1;
+                       }
                } else if (!strcmp(subkey, ".merge")) {
                        if (!value)
                                return config_error_nonbool(key);
@@ -496,7 +499,7 @@ static struct refspec *parse_refspec_internal(int nr_refspec, const char **refsp
                int is_glob;
                const char *lhs, *rhs;
 
-               llen = is_glob = 0;
+               is_glob = 0;
 
                lhs = refspec[i];
                if (*lhs == '+') {
@@ -644,10 +647,16 @@ static int valid_remote_nick(const char *name)
 struct remote *remote_get(const char *name)
 {
        struct remote *ret;
+       int name_given = 0;
 
        read_config();
-       if (!name)
+       if (name)
+               name_given = 1;
+       else {
                name = default_remote_name;
+               name_given = explicit_default_remote_name;
+       }
+
        ret = make_remote(name, 0);
        if (valid_remote_nick(name)) {
                if (!ret->url)
@@ -655,7 +664,7 @@ struct remote *remote_get(const char *name)
                if (!ret->url)
                        read_branches_file(ret);
        }
-       if (!ret->url)
+       if (name_given && !ret->url)
                add_url_alias(ret, name);
        if (!ret->url)
                return NULL;
@@ -779,10 +788,18 @@ struct ref *alloc_ref(const char *name)
 
 static struct ref *copy_ref(const struct ref *ref)
 {
-       struct ref *ret = xmalloc(sizeof(struct ref) + strlen(ref->name) + 1);
-       memcpy(ret, ref, sizeof(struct ref) + strlen(ref->name) + 1);
-       ret->next = NULL;
-       return ret;
+       struct ref *cpy;
+       size_t len;
+       if (!ref)
+               return NULL;
+       len = strlen(ref->name);
+       cpy = xmalloc(sizeof(struct ref) + len + 1);
+       memcpy(cpy, ref, sizeof(struct ref) + len + 1);
+       cpy->next = NULL;
+       cpy->symref = ref->symref ? xstrdup(ref->symref) : NULL;
+       cpy->remote_status = ref->remote_status ? xstrdup(ref->remote_status) : NULL;
+       cpy->peer_ref = copy_ref(ref->peer_ref);
+       return cpy;
 }
 
 struct ref *copy_ref_list(const struct ref *ref)
@@ -801,6 +818,7 @@ static void free_ref(struct ref *ref)
 {
        if (!ref)
                return;
+       free_ref(ref->peer_ref);
        free(ref->remote_status);
        free(ref->symref);
        free(ref);
@@ -811,7 +829,6 @@ void free_refs(struct ref *ref)
        struct ref *next;
        while (ref) {
                next = ref->next;
-               free(ref->peer_ref);
                free_ref(ref);
                ref = next;
        }
@@ -928,6 +945,7 @@ static int match_explicit(struct ref *src, struct ref *dst,
                          struct refspec *rs)
 {
        struct ref *matched_src, *matched_dst;
+       int copy_src;
 
        const char *dst_value = rs->dst;
        char *dst_guess;
@@ -938,6 +956,7 @@ static int match_explicit(struct ref *src, struct ref *dst,
        matched_src = matched_dst = NULL;
        switch (count_refspec_match(rs->src, src, &matched_src)) {
        case 1:
+               copy_src = 1;
                break;
        case 0:
                /* The source could be in the get_sha1() format
@@ -947,6 +966,7 @@ static int match_explicit(struct ref *src, struct ref *dst,
                matched_src = try_explicit_object_name(rs->src);
                if (!matched_src)
                        return error("src refspec %s does not match any.", rs->src);
+               copy_src = 0;
                break;
        default:
                return error("src refspec %s matches more than one.", rs->src);
@@ -992,7 +1012,7 @@ static int match_explicit(struct ref *src, struct ref *dst,
                return error("dst ref %s receives from more than one src.",
                      matched_dst->name);
        else {
-               matched_dst->peer_ref = matched_src;
+               matched_dst->peer_ref = copy_src ? copy_ref(matched_src) : matched_src;
                matched_dst->force = rs->force;
        }
        return 0;
@@ -1041,6 +1061,7 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
        struct refspec *rs;
        int send_all = flags & MATCH_REFS_ALL;
        int send_mirror = flags & MATCH_REFS_MIRROR;
+       int errs;
        static const char *default_refspec[] = { ":", 0 };
 
        if (!nr_refspec) {
@@ -1048,8 +1069,7 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
                refspec = default_refspec;
        }
        rs = parse_push_refspec(nr_refspec, (const char **) refspec);
-       if (match_explicit_refs(src, dst, dst_tail, rs, nr_refspec))
-               return -1;
+       errs = match_explicit_refs(src, dst, dst_tail, rs, nr_refspec);
 
        /* pick the remainder */
        for ( ; src; src = src->next) {
@@ -1100,11 +1120,13 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
                        dst_peer = make_linked_ref(dst_name, dst_tail);
                        hashcpy(dst_peer->new_sha1, src->new_sha1);
                }
-               dst_peer->peer_ref = src;
+               dst_peer->peer_ref = copy_ref(src);
                dst_peer->force = pat->force;
        free_name:
                free(dst_name);
        }
+       if (errs)
+               return -1;
        return 0;
 }
 
@@ -1452,24 +1474,41 @@ struct ref *get_local_heads(void)
        return local_refs;
 }
 
-const struct ref *guess_remote_head(const struct ref *head,
-                                   const struct ref *refs)
+struct ref *guess_remote_head(const struct ref *head,
+                             const struct ref *refs,
+                             int all)
 {
        const struct ref *r;
+       struct ref *list = NULL;
+       struct ref **tail = &list;
 
        if (!head)
                return NULL;
 
+       /*
+        * Some transports support directly peeking at
+        * where HEAD points; if that is the case, then
+        * we don't have to guess.
+        */
+       if (head->symref)
+               return copy_ref(find_ref_by_name(refs, head->symref));
+
        /* If refs/heads/master could be right, it is. */
-       r = find_ref_by_name(refs, "refs/heads/master");
-       if (r && !hashcmp(r->old_sha1, head->old_sha1))
-               return r;
+       if (!all) {
+               r = find_ref_by_name(refs, "refs/heads/master");
+               if (r && !hashcmp(r->old_sha1, head->old_sha1))
+                       return copy_ref(r);
+       }
 
        /* Look for another ref that points there */
-       for (r = refs; r; r = r->next)
-               if (r != head && !hashcmp(r->old_sha1, head->old_sha1))
-                       return r;
+       for (r = refs; r; r = r->next) {
+               if (r != head && !hashcmp(r->old_sha1, head->old_sha1)) {
+                       *tail = copy_ref(r);
+                       tail = &((*tail)->next);
+                       if (!all)
+                               break;
+               }
+       }
 
-       /* Nothing is the same */
-       return NULL;
+       return list;
 }