Merge branch 'jp/fetch-cull-many-refs'
authorJunio C Hamano <gitster@pobox.com>
Sat, 21 Nov 2009 07:44:35 +0000 (23:44 -0800)
committerJunio C Hamano <gitster@pobox.com>
Sat, 21 Nov 2009 07:44:35 +0000 (23:44 -0800)
* jp/fetch-cull-many-refs:
remote: fix use-after-free error detected by glibc in ref_remove_duplicates
fetch: Speed up fetch of large numbers of refs
remote: Make ref_remove_duplicates faster for large numbers of refs

1  2 
builtin-fetch.c
diff --combined builtin-fetch.c
index f871f2bfe8b81a508c8850c607a88249a63933f6,5c7465cfeb5c1bb0649fed6475618ba975955e99..2728860399460243cdd57ebca995f418b4c19848
@@@ -269,7 -269,7 +269,7 @@@ static int update_local_ref(struct ref 
                strcpy(quickref, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV));
                strcat(quickref, "..");
                strcat(quickref, find_unique_abbrev(ref->new_sha1, DEFAULT_ABBREV));
 -              r = s_update_ref("fast forward", ref, 1);
 +              r = s_update_ref("fast-forward", ref, 1);
                sprintf(display, "%c %-*s %-*s -> %s%s", r ? '!' : ' ',
                        SUMMARY_WIDTH, quickref, REFCOL_WIDTH, remote,
                        pretty_ref, r ? "  (unable to update local ref)" : "");
                        r ? "unable to update local ref" : "forced update");
                return r;
        } else {
 -              sprintf(display, "! %-*s %-*s -> %s  (non fast forward)",
 +              sprintf(display, "! %-*s %-*s -> %s  (non-fast-forward)",
                        SUMMARY_WIDTH, "[rejected]", REFCOL_WIDTH, remote,
                        pretty_ref);
                return 1;
@@@ -489,7 -489,8 +489,8 @@@ static int add_existing(const char *ref
                        int flag, void *cbdata)
  {
        struct string_list *list = (struct string_list *)cbdata;
-       string_list_insert(refname, list);
+       struct string_list_item *item = string_list_insert(refname, list);
+       item->util = (void *)sha1;
        return 0;
  }
  
@@@ -615,9 -616,14 +616,14 @@@ static void check_not_current_branch(st
  static int do_fetch(struct transport *transport,
                    struct refspec *refs, int ref_count)
  {
+       struct string_list existing_refs = { NULL, 0, 0, 0 };
+       struct string_list_item *peer_item = NULL;
        struct ref *ref_map;
        struct ref *rm;
        int autotags = (transport->remote->fetch_tags == 1);
+       for_each_ref(add_existing, &existing_refs);
        if (transport->remote->fetch_tags == 2 && tags != TAGS_UNSET)
                tags = TAGS_SET;
        if (transport->remote->fetch_tags == -1)
                check_not_current_branch(ref_map);
  
        for (rm = ref_map; rm; rm = rm->next) {
-               if (rm->peer_ref)
-                       read_ref(rm->peer_ref->name, rm->peer_ref->old_sha1);
+               if (rm->peer_ref) {
+                       peer_item = string_list_lookup(rm->peer_ref->name,
+                                                      &existing_refs);
+                       if (peer_item)
+                               hashcpy(rm->peer_ref->old_sha1,
+                                       peer_item->util);
+               }
        }
  
        if (tags == TAGS_DEFAULT && autotags)