X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=upload-pack.c;h=da10742c44201cfb6f86eb8d80f3be27940335ff;hb=4fa2197e614950279527b14825d1e9572454a48c;hp=b454c9e11dbea4d023ec724252e14b4984bfba9b;hpb=fb9040cc83540fff9d05c8056433a4aa05b8a7c2;p=git.git diff --git a/upload-pack.c b/upload-pack.c index b454c9e1..da10742c 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -5,21 +5,62 @@ static const char upload_pack_usage[] = "git-upload-pack "; #define MAX_HAS (16) -#define MAX_NEEDS (16) +#define MAX_NEEDS (256) 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 int strip(char *line, int len) +{ + if (len && line[len-1] == '\n') + line[--len] = 0; + return len; +} + static void create_pack_file(void) { - /* - * Here, we should do - * - * git-rev-list --objects needs_sha1 --not has_sha1 | - * git-pack-objects --stdout - * - * but we don't. - */ + int fd[2]; + pid_t pid; + + if (pipe(fd) < 0) + die("git-upload-pack: unable to create pipe"); + pid = fork(); + if (pid < 0) + die("git-upload-pack: unable to fork git-rev-list"); + + if (!pid) { + int i; + int args = nr_has + nr_needs + 5; + char **argv = xmalloc(args * sizeof(char *)); + char *buf = xmalloc(args * 45); + char **p = argv; + + dup2(fd[1], 1); + close(0); + close(fd[0]); + close(fd[1]); + *p++ = "git-rev-list"; + *p++ = "--objects"; + for (i = 0; i < nr_needs; i++) { + *p++ = buf; + memcpy(buf, sha1_to_hex(needs_sha1[i]), 41); + buf += 41; + } + for (i = 0; i < nr_has; i++) { + *p++ = buf; + *buf++ = '^'; + memcpy(buf, sha1_to_hex(has_sha1[i]), 41); + buf += 41; + } + *p++ = NULL; + execvp("git-rev-list", argv); + die("git-upload-pack: unable to exec git-rev-list"); + } + dup2(fd[0], 0); + close(fd[0]); + close(fd[1]); + execlp("git-pack-objects", "git-pack-objects", "--stdout", NULL); + die("git-upload-pack: unable to exec git-pack-objects"); } static int got_sha1(char *hex, unsigned char *sha1) @@ -50,8 +91,7 @@ static int get_common_commits(void) packet_write(1, "NAK\n"); continue; } - if (line[len-1] == '\n') - line[--len] = 0; + len = strip(line, len); if (!strncmp(line, "have ", 5)) { if (got_sha1(line+5, sha1)) { packet_write(1, "ACK %s\n", sha1_to_hex(sha1)); @@ -69,7 +109,8 @@ static int get_common_commits(void) for (;;) { len = packet_read_line(0, line, sizeof(line)); if (!len) - break; + continue; + len = strip(line, len); if (!strncmp(line, "have ", 5)) { got_sha1(line+5, sha1); continue; @@ -112,6 +153,7 @@ static int send_ref(const char *refname, const unsigned char *sha1) static int upload_pack(void) { + head_ref(send_ref); for_each_ref(send_ref); packet_flush(1); nr_needs = receive_needs(); @@ -128,12 +170,16 @@ int main(int argc, char **argv) if (argc != 2) usage(upload_pack_usage); dir = argv[1]; - if (chdir(dir)) - die("git-upload-pack unable to chdir to %s", dir); + + /* chdir to the directory. If that fails, try appending ".git" */ + if (chdir(dir) < 0) { + if (chdir(mkpath("%s.git", dir)) < 0) + die("git-upload-pack unable to chdir to %s", dir); + } chdir(".git"); if (access("objects", X_OK) || access("refs", X_OK)) die("git-upload-pack: %s doesn't seem to be a git archive", dir); - setenv("GIT_DIR", ".", 1); + putenv("GIT_DIR=."); upload_pack(); return 0; }