X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=fetch-pack.c;h=8566ab1744b029e9696976e78bac4d48d2324129;hb=794f9fe7db30e2aff8f8f0543c6d18bf579cdbc2;hp=9dfd072db786a62d7d971a1b98f539e68ec364fc;hpb=0a8944dd48b97d258240af967dfdfcea4f203b85;p=git.git diff --git a/fetch-pack.c b/fetch-pack.c index 9dfd072d..8566ab17 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -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);