summaryrefslogtreecommitdiff
path: root/upload-pack.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2005-07-04 16:35:13 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2005-07-04 16:35:13 -0700
commit75bfc6c232689ae06aba6a7d4aa15ac2791d9a11 (patch)
tree5cbe1763905b2fa0ec6281c8b1003149a1eb72c0 /upload-pack.c
parentfb9040cc83540fff9d05c8056433a4aa05b8a7c2 (diff)
downloadgit-75bfc6c232689ae06aba6a7d4aa15ac2791d9a11.tar.gz
Make git-fetch-pack actually do all the unpacking etc.
It returns the result SHA1 on stdout, so you can do remote=$(git-fetch-pack host:dir branchname) and it will unpack the objects and "remote" will be the SHA1 name of the branch on the other side. You can then save that off, or merge it, or whatever.
Diffstat (limited to 'upload-pack.c')
-rw-r--r--upload-pack.c63
1 files changed, 52 insertions, 11 deletions
diff --git a/upload-pack.c b/upload-pack.c
index b454c9e11d..d35c0685ce 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -10,16 +10,57 @@ 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;