From 61221472a5f8591f2d06d5e5c5aafb03271b8066 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 29 Jun 2005 19:09:05 -0700 Subject: [PATCH] Start of "git-send-pack", the local part of sending off a pack Like git-receive-pack, this is only partway done. --- Makefile | 3 +- send-pack.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 send-pack.c diff --git a/Makefile b/Makefile index c21a1a0d2..792b01445 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,7 @@ PROG= git-update-cache git-diff-files git-init-db git-write-tree \ git-get-tar-commit-id git-apply git-stripspace \ git-cvs2git git-diff-stages git-rev-parse git-patch-id \ git-pack-objects git-unpack-objects git-verify-pack \ - git-receive-pack + git-receive-pack git-send-pack all: $(PROG) @@ -127,6 +127,7 @@ git-pack-objects: pack-objects.c git-unpack-objects: unpack-objects.c git-verify-pack: verify-pack.c git-receive-pack: receive-pack.c +git-send-pack: send-pack.c git-http-pull: LIBS += -lcurl git-rev-list: LIBS += -lssl diff --git a/send-pack.c b/send-pack.c new file mode 100644 index 000000000..af57d4028 --- /dev/null +++ b/send-pack.c @@ -0,0 +1,118 @@ +#include "cache.h" + +static const char send_pack_usage[] = "git-send-pack [--exec=other] destination [heads]*"; + +static const char *exec = "git-receive-pack"; + +static int send_pack(int in, int out) +{ + for (;;) { + static char buffer[1000]; + int ret = read(in, buffer, sizeof(buffer)); + if (ret > 0) { + write(1, buffer, ret); + continue; + } + break; + } + close(out); + return 0; +} + +/* + * First, make it shell-safe. We do this by just disallowing any + * special characters. Somebody who cares can do escaping and let + * through the rest. But since we're doing to feed this to ssh as + * a command line, we're going to be pretty damn anal for now. + */ +static char *shell_safe(char *url) +{ + char *n = url; + unsigned char c; + static const char flags[256] = { + ['0'...'9'] = 1, + ['a'...'z'] = 1, + ['A'...'Z'] = 1, + ['.'] = 1, ['/'] = 1, + ['-'] = 1, ['+'] = 1, + [':'] = 1 + }; + + while ((c = *n++) != 0) { + if (flags[c] != 1) + die("I don't like '%c'. Sue me.", c); + } + return url; +} + +/* + * Yeah, yeah, fixme. Need to pass in the heads etc. + */ +static int setup_connection(int fd[2], char *url, char **heads) +{ + char command[1024]; + const char *host, *path; + char *colon; + int pipefd[2][2]; + + url = shell_safe(url); + host = NULL; + path = url; + colon = strchr(url, ':'); + if (colon) { + *colon = 0; + host = url; + path = colon+1; + } + snprintf(command, sizeof(command), "%s %s", exec, path); + if (pipe(pipefd[0]) < 0 || pipe(pipefd[1]) < 0) + die("unable to create pipe pair for communication"); + if (!fork()) { + dup2(pipefd[1][0], 0); + dup2(pipefd[0][1], 1); + close(pipefd[0][0]); + close(pipefd[0][1]); + close(pipefd[1][0]); + close(pipefd[1][1]); + if (host) + execlp("ssh", "ssh", host, command, NULL); + else + execlp(host, command, NULL); + die("exec failed"); + } + fd[0] = pipefd[0][0]; + fd[1] = pipefd[1][1]; + close(pipefd[0][1]); + close(pipefd[1][0]); + return 0; +} + +int main(int argc, char **argv) +{ + int i, nr_heads = 0; + char *dest = NULL; + char **heads = NULL; + int fd[2]; + + argv++; + for (i = 1; i < argc; i++) { + char *arg = *argv++; + + if (*arg == '-') { + if (!strncmp(arg, "--exec=", 7)) { + exec = arg + 7; + continue; + } + usage(send_pack_usage); + } + dest = arg; + heads = argv; + nr_heads = argc - i -1; + break; + } + if (!dest) + usage(send_pack_usage); + if (setup_connection(fd, dest, heads)) + return 1; + return send_pack(fd[0], fd[1]); +} -- 2.26.2