X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=fetch-pack.c;h=3be77c3a8e76c6bc08414e9467c1dc1d0d91c6d1;hb=23d61f8343282643c830e1c446962b213dbcc09a;hp=57602b9561160a3ff14b893a92d69b46c1ffa9df;hpb=40a10462498bdd23d4e49f02867b8be50eb78704;p=git.git diff --git a/fetch-pack.c b/fetch-pack.c index 57602b95..3be77c3a 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -14,60 +14,67 @@ static const char *exec = "git-upload-pack"; #define COMPLETE (1U << 0) #define COMMON (1U << 1) -#define COMMON_REF (1U << 2 | COMMON) +#define COMMON_REF (1U << 2) #define SEEN (1U << 3) #define POPPED (1U << 4) static struct commit_list *rev_list = NULL; -static struct commit_list *rev_list_end = NULL; -static unsigned long non_common_revs = 0; +static int non_common_revs = 0; -static void rev_list_append(struct commit *commit, int mark) +static void rev_list_push(struct commit *commit, int mark) { if (!(commit->object.flags & mark)) { commit->object.flags |= mark; - if (rev_list == NULL) { - commit_list_insert(commit, &rev_list); - rev_list_end = rev_list; - } else { - commit_list_insert(commit, &(rev_list_end->next)); - rev_list_end = rev_list_end->next; - } + if (!(commit->object.parsed)) + parse_commit(commit); + + insert_by_date(commit, &rev_list); if (!(commit->object.flags & COMMON)) non_common_revs++; } } -static int rev_list_append_sha1(const char *path, const unsigned char *sha1) +static int rev_list_insert_ref(const char *path, const unsigned char *sha1) { struct object *o = deref_tag(parse_object(sha1)); if (o->type == commit_type) - rev_list_append((struct commit *)o, SEEN); + rev_list_push((struct commit *)o, SEEN); return 0; } -static void mark_common(struct commit *commit) +/* + This function marks a rev and its ancestors as common. + In some cases, it is desirable to mark only the ancestors (for example + when only the server does not yet know that they are common). +*/ + +static void mark_common(struct commit *commit, + int ancestors_only, int dont_parse) { if (commit != NULL && !(commit->object.flags & COMMON)) { struct object *o = (struct object *)commit; - o->flags |= COMMON; + + if (!ancestors_only) + o->flags |= COMMON; + if (!(o->flags & SEEN)) - rev_list_append(commit, SEEN); + rev_list_push(commit, SEEN); else { struct commit_list *parents; - if (!(o->flags & POPPED)) + if (!ancestors_only && !(o->flags & POPPED)) non_common_revs--; - if (!o->parsed) + if (!o->parsed && !dont_parse) parse_commit(commit); + for (parents = commit->parents; parents; parents = parents->next) - mark_common(parents->item); + mark_common(parents->item, 0, dont_parse); } } } @@ -108,10 +115,10 @@ static const unsigned char* get_rev() mark = SEEN; while (parents) { + if (!(parents->item->object.flags & SEEN)) + rev_list_push(parents->item, mark); if (mark & COMMON) - mark_common(parents->item); - else - rev_list_append(parents->item, mark); + mark_common(parents->item, 1, 0); parents = parents->next; } @@ -125,10 +132,10 @@ static int find_common(int fd[2], unsigned char *result_sha1, struct ref *refs) { int fetching; - int count = 0, flushes = 0, multi_ack = 0, retval; + int count = 0, flushes = 0, retval; const unsigned char *sha1; - for_each_ref(rev_list_append_sha1); + for_each_ref(rev_list_insert_ref); fetching = 0; for ( ; refs ; refs = refs->next) { @@ -149,14 +156,17 @@ static int find_common(int fd[2], unsigned char *result_sha1, (o->flags & COMPLETE)) { o = deref_tag(o); - if (o->type == commit_type) - rev_list_append((struct commit *)o, - COMMON_REF | SEEN); + if (o->type == commit_type) { + struct commit *commit = (struct commit *)o; + + rev_list_push(commit, COMMON_REF | SEEN); + mark_common(commit, 1, 1); + } continue; } - packet_write(fd[1], "want %s multi_ack\n", sha1_to_hex(remote)); + packet_write(fd[1], "want %s\n", sha1_to_hex(remote)); fetching++; } packet_flush(fd[1]); @@ -170,8 +180,6 @@ static int find_common(int fd[2], unsigned char *result_sha1, if (verbose) fprintf(stderr, "have %s\n", sha1_to_hex(sha1)); if (!(31 & ++count)) { - int ack; - packet_flush(fd[1]); flushes++; @@ -181,48 +189,29 @@ static int find_common(int fd[2], unsigned char *result_sha1, */ if (count == 32) continue; - - do { - ack = get_ack(fd[0], result_sha1); - if (verbose && ack) - fprintf(stderr, "got ack %d %s\n", ack, - sha1_to_hex(result_sha1)); - if (ack == 1) { - if (!multi_ack) - flushes = 0; - retval = 0; - goto done; - } else if (ack == 2) { - multi_ack = 1; - mark_common((struct commit *) - lookup_object(result_sha1)); - retval = 0; - } - } while(ack); + if (get_ack(fd[0], result_sha1)) { + flushes = 0; + retval = 0; + if (verbose) + fprintf(stderr, "got ack\n"); + break; + } flushes--; } } -done: - if (multi_ack) { - packet_flush(fd[1]); - flushes++; - } + packet_write(fd[1], "done\n"); if (verbose) fprintf(stderr, "done\n"); if (retval != 0) flushes++; while (flushes) { + flushes--; if (get_ack(fd[0], result_sha1)) { if (verbose) - fprintf(stderr, "got ack %s\n", - sha1_to_hex(result_sha1)); - if (!multi_ack) - return 0; - retval = 0; - continue; + fprintf(stderr, "got ack\n"); + return 0; } - flushes--; } return retval; }