diff options
-rw-r--r-- | connect.c | 5 | ||||
-rw-r--r-- | fetch-pack.c | 199 | ||||
-rw-r--r-- | upload-pack.c | 64 |
3 files changed, 72 insertions, 196 deletions
@@ -59,11 +59,8 @@ int get_ack(int fd, unsigned char *result_sha1) if (!strcmp(line, "NAK")) return 0; if (!strncmp(line, "ACK ", 3)) { - if (!get_sha1_hex(line+4, result_sha1)) { - if (strstr(line+45, "continue")) - return 2; + if (!get_sha1_hex(line+4, result_sha1)) return 1; - } } die("git-fetch_pack: expected ACK/NAK, got '%s'", line); } diff --git a/fetch-pack.c b/fetch-pack.c index 57602b956..8566ab174 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -13,123 +13,18 @@ static const char fetch_pack_usage[] = static const char *exec = "git-upload-pack"; #define COMPLETE (1U << 0) -#define COMMON (1U << 1) -#define COMMON_REF (1U << 2 | COMMON) -#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 void rev_list_append(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.flags & COMMON)) - non_common_revs++; - } -} - -static int rev_list_append_sha1(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); - - return 0; -} - -static void mark_common(struct commit *commit) -{ - if (commit != NULL && !(commit->object.flags & COMMON)) { - struct object *o = (struct object *)commit; - o->flags |= COMMON; - if (!(o->flags & SEEN)) - rev_list_append(commit, SEEN); - else { - struct commit_list *parents; - - if (!(o->flags & POPPED)) - non_common_revs--; - if (!o->parsed) - parse_commit(commit); - for (parents = commit->parents; - parents; - parents = parents->next) - mark_common(parents->item); - } - } -} - -/* - Get the next rev to send, ignoring the common. -*/ - -static const unsigned char* get_rev() -{ - struct commit *commit = NULL; - - while (commit == NULL) { - unsigned int mark; - struct commit_list* parents; - - if (rev_list == NULL || non_common_revs == 0) - return NULL; - - commit = rev_list->item; - if (!(commit->object.parsed)) - parse_commit(commit); - commit->object.flags |= POPPED; - if (!(commit->object.flags & COMMON)) - non_common_revs--; - - parents = commit->parents; - - if (commit->object.flags & COMMON) { - /* do not send "have", and ignore ancestors */ - commit = NULL; - mark = COMMON | SEEN; - } else if (commit->object.flags & COMMON_REF) - /* send "have", and ignore ancestors */ - mark = COMMON | SEEN; - else - /* send "have", also for its ancestors */ - mark = SEEN; - - while (parents) { - if (mark & COMMON) - mark_common(parents->item); - else - rev_list_append(parents->item, mark); - parents = parents->next; - } - - rev_list = rev_list->next; - } - - return commit->object.sha1; -} 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; - const unsigned char *sha1; - - for_each_ref(rev_list_append_sha1); + static char line[1000]; + static char rev_command[1024]; + int count = 0, flushes = 0, retval, rev_command_len; + FILE *revs; + strcpy(rev_command, "git-rev-list $(git-rev-parse --all)"); + rev_command_len = strlen(rev_command); fetching = 0; for ( ; refs ; refs = refs->next) { unsigned char *remote = refs->old_sha1; @@ -147,31 +42,46 @@ static int find_common(int fd[2], unsigned char *result_sha1, */ if (((o = lookup_object(remote)) != NULL) && (o->flags & COMPLETE)) { - o = deref_tag(o); - - if (o->type == commit_type) - rev_list_append((struct commit *)o, - COMMON_REF | SEEN); - + 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(p->item->object.sha1)); + rev_command_len += 43; + p = p->next; + } continue; } - - packet_write(fd[1], "want %s multi_ack\n", sha1_to_hex(remote)); + repair: + packet_write(fd[1], "want %s\n", sha1_to_hex(remote)); fetching++; } packet_flush(fd[1]); if (!fetching) return 1; - flushes = 0; + revs = popen(rev_command, "r"); + if (!revs) + die("unable to run 'git-rev-list'"); + + flushes = 1; retval = -1; - while ((sha1 = get_rev())) { + while (fgets(line, sizeof(line), revs) != NULL) { + unsigned char sha1[20]; + if (get_sha1_hex(line, sha1)) + die("git-fetch-pack: expected object name, got crud"); packet_write(fd[1], "have %s\n", sha1_to_hex(sha1)); if (verbose) fprintf(stderr, "have %s\n", sha1_to_hex(sha1)); if (!(31 & ++count)) { - int ack; - packet_flush(fd[1]); flushes++; @@ -181,48 +91,27 @@ 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++; - } + pclose(revs); 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; } diff --git a/upload-pack.c b/upload-pack.c index 25a343ecc..accdba669 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -3,14 +3,12 @@ #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] <dir>"; -#define THEY_HAVE (1U << 0) #define MAX_HAS 256 #define MAX_NEEDS 256 -static int nr_has = 0, nr_needs = 0, multi_ack = 0; +static int nr_has = 0, nr_needs = 0; static unsigned char has_sha1[MAX_HAS][20]; static unsigned char needs_sha1[MAX_NEEDS][20]; static unsigned int timeout = 0; @@ -87,27 +85,15 @@ static void create_pack_file(void) static int got_sha1(char *hex, unsigned char *sha1) { + int nr; if (get_sha1_hex(hex, sha1)) die("git-upload-pack: expected SHA1 object, got '%s'", hex); if (!has_sha1_file(sha1)) return 0; - if (nr_has < MAX_HAS) { - struct object *o = lookup_object(sha1); - if (!(o && o->parsed)) - o = parse_object(sha1); - if (!o) - die("oops (%s)", sha1_to_hex(sha1)); - 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_has++], sha1, 20); + nr = nr_has; + if (nr < MAX_HAS) { + memcpy(has_sha1[nr], sha1, 20); + nr_has = nr+1; } return 1; } @@ -118,36 +104,44 @@ 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(); if (!len) { - if (multi_ack || nr_has == 0) - packet_write(1, "NAK\n"); + packet_write(1, "NAK\n"); continue; } len = strip(line, len); if (!strncmp(line, "have ", 5)) { - if (got_sha1(line+5, sha1) && - (multi_ack || nr_has == 1)) - packet_write(1, "ACK %s%s\n", - sha1_to_hex(sha1), - multi_ack && nr_has < MAX_HAS ? - " continue" : ""); + if (got_sha1(line+5, sha1)) { + packet_write(1, "ACK %s\n", sha1_to_hex(sha1)); + break; + } continue; } if (!strcmp(line, "done")) { - if (nr_has > 0) - return 0; packet_write(1, "NAK\n"); return -1; } die("git-upload-pack: expected SHA1 list, got '%s'", line); } + + for (;;) { + len = packet_read_line(0, line, sizeof(line)); + reset_timeout(); + if (!len) + continue; + len = strip(line, len); + if (!strncmp(line, "have ", 5)) { + got_sha1(line+5, sha1); + continue; + } + if (!strcmp(line, "done")) + break; + die("git-upload-pack: expected SHA1 list, got '%s'", line); + } + return 0; } static int receive_needs(void) @@ -176,10 +170,6 @@ static int receive_needs(void) if (strncmp("want ", line, 5) || get_sha1_hex(line+5, sha1_buf)) die("git-upload-pack: protocol error, " "expected to get sha, not '%s'", line); - - if (strstr(line+45, "multi_ack")) - multi_ack = 1; - needs++; } } |