Change the loop body into the more straightforward * remove item from the front of the old list * if necessary, add it to the tail of the new list and return a pointer to the new list (even though it is currently always the same as the input argument, because the first element in the list is currently never deleted). Signed-off-by: Michael Haggerty <mhagger@xxxxxxxxxxxx> --- builtin/fetch.c | 4 +--- remote.c | 52 +++++++++++++++++++++++++++++++--------------------- remote.h | 8 ++++++-- 3 files changed, 38 insertions(+), 26 deletions(-) diff --git a/builtin/fetch.c b/builtin/fetch.c index 5ddb9af..3d978eb 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -360,9 +360,7 @@ static struct ref *get_ref_map(struct transport *transport, tail = &rm->next; } - ref_remove_duplicates(ref_map); - - return ref_map; + return ref_remove_duplicates(ref_map); } #define STORE_REF_ERROR_OTHER 1 diff --git a/remote.c b/remote.c index 15f3dc5..c90a2bf 100644 --- a/remote.c +++ b/remote.c @@ -745,35 +745,45 @@ int for_each_remote(each_remote_fn fn, void *priv) return result; } -void ref_remove_duplicates(struct ref *ref_map) +struct ref *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; + struct ref *retval = NULL; + struct ref **p = &retval; - for (; ref_map; prev = ref_map, ref_map = next) { - next = ref_map->next; - if (!ref_map->peer_ref) - continue; + while (ref_map) { + struct ref *ref = ref_map; + + ref_map = ref_map->next; + ref->next = NULL; - 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", - ref_map->peer_ref->name, - ((struct ref *)item->util)->name, - ref_map->name); - prev->next = ref_map->next; - free(ref_map->peer_ref); - free(ref_map); - ref_map = prev; /* skip this; we freed it */ + if (!ref->peer_ref) { + *p = ref; + p = &ref->next; } else { - item->util = ref_map; + struct string_list_item *item = + string_list_insert(&refs, ref->peer_ref->name); + + if (item->util) { + /* Entry already existed */ + if (strcmp(((struct ref *)item->util)->name, + ref->name)) + die("%s tracks both %s and %s", + ref->peer_ref->name, + ((struct ref *)item->util)->name, + ref->name); + free(ref->peer_ref); + free(ref); + } else { + *p = ref; + p = &ref->next; + item->util = ref; + } } } + string_list_clear(&refs, 0); + return retval; } int remote_has_url(struct remote *remote, const char *url) diff --git a/remote.h b/remote.h index 131130a..c07eb99 100644 --- a/remote.h +++ b/remote.h @@ -149,9 +149,13 @@ int resolve_remote_symref(struct ref *ref, struct ref *list); int ref_newer(const unsigned char *new_sha1, const unsigned char *old_sha1); /* - * Removes and frees any duplicate refs in the map. + * Remove and free all but the first of any entries in the input list + * that map the same remote reference to the same local reference. If + * there are two entries that map different remote references to the + * same local reference, emit an error message and die. Return a + * pointer to the head of the resulting list. */ -void ref_remove_duplicates(struct ref *ref_map); +struct ref *ref_remove_duplicates(struct ref *ref_map); int valid_fetch_refspec(const char *refspec); struct refspec *parse_fetch_refspec(int nr_refspec, const char **refspec); -- 1.8.4.1 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html