summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Michael Haggerty <mhagger@alum.mit.edu>2013-10-30 06:33:09 +0100
committerLibravatar Junio C Hamano <gitster@pobox.com>2013-10-30 14:16:41 -0700
commitb9afe6654db2bfb776db933f832e7e03052adf98 (patch)
treeb88e6f7c317f436739cd15d8942bc00518d391c2
parentt5536: new test of refspec conflicts when fetching (diff)
downloadtgif-b9afe6654db2bfb776db933f832e7e03052adf98.tar.xz
ref_remove_duplicates(): simplify loop logic
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@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--builtin/fetch.c4
-rw-r--r--remote.c52
-rw-r--r--remote.h8
3 files changed, 38 insertions, 26 deletions
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 5ddb9af05c..3d978eb58e 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 1fb87de01c..f803990760 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 131130a611..c07eb9950a 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);