]> git.ipfire.org Git - thirdparty/git.git/blobdiff - remote.c
t5536: new test of refspec conflicts when fetching
[thirdparty/git.git] / remote.c
index e9fedfa918d6806532184b8735d2761951fd4a2e..1fb87de01c6a3e7cede213b64a99408060eef33a 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -750,13 +750,15 @@ void ref_remove_duplicates(struct ref *ref_map)
        struct string_list refs = STRING_LIST_INIT_NODUP;
        struct string_list_item *item = NULL;
        struct ref *prev = NULL, *next = NULL;
+
        for (; ref_map; prev = ref_map, ref_map = next) {
                next = ref_map->next;
                if (!ref_map->peer_ref)
                        continue;
 
-               item = string_list_lookup(&refs, ref_map->peer_ref->name);
-               if (item) {
+               item = string_list_insert(&refs, ref_map->peer_ref->name);
+               if (item->util) {
+                       /* Entry already existed */
                        if (strcmp(((struct ref *)item->util)->name,
                                   ref_map->name))
                                die("%s tracks both %s and %s",
@@ -767,11 +769,9 @@ void ref_remove_duplicates(struct ref *ref_map)
                        free(ref_map->peer_ref);
                        free(ref_map);
                        ref_map = prev; /* skip this; we freed it */
-                       continue;
+               } else {
+                       item->util = ref_map;
                }
-
-               item = string_list_insert(&refs, ref_map->peer_ref->name);
-               item->util = ref_map;
        }
        string_list_clear(&refs, 0);
 }
@@ -825,6 +825,8 @@ static int query_refspecs(struct refspec *refs, int ref_count, struct refspec *q
 {
        int i;
        int find_src = !query->src;
+       const char *needle = find_src ? query->dst : query->src;
+       char **result = find_src ? &query->src : &query->dst;
 
        if (find_src && !query->dst)
                return error("query_refspecs: need either src or dst");
@@ -833,8 +835,6 @@ static int query_refspecs(struct refspec *refs, int ref_count, struct refspec *q
                struct refspec *refspec = &refs[i];
                const char *key = find_src ? refspec->dst : refspec->src;
                const char *value = find_src ? refspec->src : refspec->dst;
-               const char *needle = find_src ? query->dst : query->src;
-               char **result = find_src ? &query->src : &query->dst;
 
                if (!refspec->dst)
                        continue;
@@ -1553,6 +1553,13 @@ static int ignore_symref_update(const char *refname)
        return (flag & REF_ISSYMREF);
 }
 
+/*
+ * Create and return a list of (struct ref) consisting of copies of
+ * each remote_ref that matches refspec.  refspec must be a pattern.
+ * Fill in the copies' peer_ref to describe the local tracking refs to
+ * which they map.  Omit any references that would map to an existing
+ * local symbolic ref.
+ */
 static struct ref *get_expanded_map(const struct ref *remote_refs,
                                    const struct refspec *refspec)
 {
@@ -1560,9 +1567,9 @@ static struct ref *get_expanded_map(const struct ref *remote_refs,
        struct ref *ret = NULL;
        struct ref **tail = &ret;
 
-       char *expn_name;
-
        for (ref = remote_refs; ref; ref = ref->next) {
+               char *expn_name = NULL;
+
                if (strchr(ref->name, '^'))
                        continue; /* a dereference item */
                if (match_name_with_pattern(refspec->src, ref->name,
@@ -1571,12 +1578,12 @@ static struct ref *get_expanded_map(const struct ref *remote_refs,
                        struct ref *cpy = copy_ref(ref);
 
                        cpy->peer_ref = alloc_ref(expn_name);
-                       free(expn_name);
                        if (refspec->force)
                                cpy->peer_ref->force = 1;
                        *tail = cpy;
                        tail = &cpy->next;
                }
+               free(expn_name);
        }
 
        return ret;