From: Junio C Hamano Date: Fri, 21 Oct 2005 17:11:00 GMT Subject: Re: [PATCH] Do not call git-rev-list from git-fetch-pack Message-ID: <7vwtk6vlqz.fsf@assigned-by-dhcp.cox.net> In-Reply-To: Johannes Schindelin writes: > Note that the best thing would probably be to add a binary search to that, > and *not* stop at the first ack'ed rev, but rather count them, and stop at > MAX_HAS. Another alternative. We send "haves" in order, without 2^n skipping nor binary search backtrack. Instead, add a logic in upload-pack to see if a newly arrived "have" is a direct child of anything that we have already heard about, and mark to ignore them. We need to add that MAX_HAS counting to fetch-pack side for this to work. This is not even compile tested, but just to outline the idea. (... now off to day-job ...) --- diff --git a/upload-pack.c b/upload-pack.c index 8a41caf..d98a28e 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -3,9 +3,11 @@ #include "pkt-line.h" #include "tag.h" #include "object.h" +#include "commit.h" static const char upload_pack_usage[] = "git-upload-pack [--strict] [--timeout=nn] "; +#define THEY_HAVE (1U << 0) #define MAX_HAS (16) #define MAX_NEEDS (256) static int nr_has = 0, nr_needs = 0; @@ -92,6 +94,20 @@ static int got_sha1(char *hex, unsigned return 0; nr = nr_has; if (nr < MAX_HAS) { + struct object *o = lookup_object(sha1); + if (!o || (o->parsed || !parse_object(sha1))) + die("oops"); + if (o->type == commit_type) { + struct commit_list *parents; + if (o->flags & THEY_HAVE) + return 0; + o->flags |= THEY_HAVE; + for (parents = ((struct commit*)o)->parents; + parents; + parents = parents->next) { + parents->item->object.flags |= THEY_HAVE; + } + } memcpy(has_sha1[nr], sha1, 20); nr_has = nr+1; } @@ -104,6 +120,9 @@ static int get_common_commits(void) unsigned char sha1[20]; int len; + track_object_refs = 0; + save_commit_buffer = 0; + for(;;) { len = packet_read_line(0, line, sizeof(line)); reset_timeout();