aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtin-fetch.c1
-rw-r--r--remote.c27
-rw-r--r--remote.h5
3 files changed, 33 insertions, 0 deletions
diff --git a/builtin-fetch.c b/builtin-fetch.c
index cf7498b15..caaca6364 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -112,6 +112,7 @@ static struct ref *get_ref_map(struct transport *transport,
ref_map->merge = 1;
}
}
+ ref_remove_duplicates(ref_map);
return ref_map;
}
diff --git a/remote.c b/remote.c
index e7d735b98..e2ca4d32b 100644
--- a/remote.c
+++ b/remote.c
@@ -380,6 +380,33 @@ int for_each_remote(each_remote_fn fn, void *priv)
return result;
}
+void ref_remove_duplicates(struct ref *ref_map)
+{
+ struct ref **posn;
+ struct ref *next;
+ for (; ref_map; ref_map = ref_map->next) {
+ if (!ref_map->peer_ref)
+ continue;
+ posn = &ref_map->next;
+ while (*posn) {
+ if ((*posn)->peer_ref &&
+ !strcmp((*posn)->peer_ref->name,
+ ref_map->peer_ref->name)) {
+ if (strcmp((*posn)->name, ref_map->name))
+ die("%s tracks both %s and %s",
+ ref_map->peer_ref->name,
+ (*posn)->name, ref_map->name);
+ next = (*posn)->next;
+ free((*posn)->peer_ref);
+ free(*posn);
+ *posn = next;
+ } else {
+ posn = &(*posn)->next;
+ }
+ }
+ }
+}
+
int remote_has_url(struct remote *remote, const char *url)
{
int i;
diff --git a/remote.h b/remote.h
index 05add06e4..c62636d78 100644
--- a/remote.h
+++ b/remote.h
@@ -49,6 +49,11 @@ struct ref *alloc_ref(unsigned namelen);
*/
void free_refs(struct ref *ref);
+/*
+ * Removes and frees any duplicate refs in the map.
+ */
+void ref_remove_duplicates(struct ref *ref_map);
+
struct refspec *parse_ref_spec(int nr_refspec, const char **refspec);
int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,