git-upload-pack: More efficient usage of the has_sha1 array
[git.git] / fetch-pack.c
index 9dfd072..8566ab1 100644 (file)
@@ -28,22 +28,39 @@ static int find_common(int fd[2], unsigned char *result_sha1,
        fetching = 0;
        for ( ; refs ; refs = refs->next) {
                unsigned char *remote = refs->old_sha1;
+               struct object *o;
 
                /*
-                  If that object is complete (i.e. it is a descendant of a
-                  local ref), we don't want it, nor its descendants.
-               */
-               if (has_sha1_file(remote)
-                               && parse_object(remote)->flags & COMPLETE) {
-                       if (rev_command_len + 44 < sizeof(rev_command)) {
+                * If that object is complete (i.e. it is an ancestor of a
+                * local ref), we tell them we have it but do not have to
+                * tell them about its ancestors, which they already know
+                * about.
+                *
+                * We use lookup_object here because we are only
+                * interested in the case we *know* the object is
+                * reachable and we have already scanned it.
+                */
+               if (((o = lookup_object(remote)) != NULL) &&
+                   (o->flags & COMPLETE)) {
+                       struct commit_list *p;
+                       struct commit *commit =
+                               (struct commit *) (o = deref_tag(o));
+                       if (!o)
+                               goto repair;
+                       if (o->type != commit_type)
+                               continue;
+                       p = commit->parents;
+                       while (p &&
+                              rev_command_len + 44 < sizeof(rev_command)) {
                                snprintf(rev_command + rev_command_len, 44,
-                                       " ^%s^", sha1_to_hex(remote));
+                                        " ^%s",
+                                        sha1_to_hex(p->item->object.sha1));
                                rev_command_len += 43;
+                               p = p->next;
                        }
-
                        continue;
                }
-
+       repair:
                packet_write(fd[1], "want %s\n", sha1_to_hex(remote));
                fetching++;
        }
@@ -106,10 +123,13 @@ static int mark_complete(const char *path, const unsigned char *sha1)
        struct object *o = parse_object(sha1);
 
        while (o && o->type == tag_type) {
+               struct tag *t = (struct tag *) o;
+               if (!t->tagged)
+                       break; /* broken repository */
                o->flags |= COMPLETE;
-               o = parse_object(((struct tag *)o)->tagged->sha1);
+               o = parse_object(t->tagged->sha1);
        }
-       if (o->type == commit_type) {
+       if (o && o->type == commit_type) {
                struct commit *commit = (struct commit *)o;
                commit->object.flags |= COMPLETE;
                insert_by_date(commit, &complete);