From f801477645146fd7eff018b4997b86dfa1a0767d Mon Sep 17 00:00:00 2001 From: Paul Collins Date: Fri, 4 Nov 2005 14:57:16 +0000 Subject: [PATCH] proxy-command support for git:// Here is an updated patch that first looks for GIT_PROXY_COMMAND in the environment and then git.proxycommand in the repository's configuration file. I have left the calling convention the same argv[1] is the host and argv[2] is the port. I've taken the hostname parsing verbatim from git_tcp_connect(), so it should now support an explicit port number and whatever that business with the square brackets is. (Should I move this to a helper function?) Regarding internal vs. external hosts, the proxy command can simply run netcat locally to internal hosts, so perhaps that is sufficient. Signed-off-by: Junio C Hamano --- connect.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/connect.c b/connect.c index 73187a1e93..be88ef0388 100644 --- a/connect.c +++ b/connect.c @@ -448,6 +448,73 @@ static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path) #endif /* NO_IPV6 */ +static char *git_proxy_command = NULL; + +static int git_proxy_command_options(const char *var, const char *value) +{ + if (git_proxy_command == NULL) { + if (!strcmp(var, "git.proxycommand")) { + git_proxy_command = xmalloc(strlen(value) + 1); + strcpy(git_proxy_command, value); + return 0; + } + } + + return git_default_config(var, value); +} + +static int git_use_proxy(void) +{ + git_proxy_command = getenv("GIT_PROXY_COMMAND"); + git_config(git_proxy_command_options); + return git_proxy_command != NULL; +} + +static int git_proxy_connect(int fd[2], const char *prog, char *host, char *path) +{ + char *port = STR(DEFAULT_GIT_PORT); + char *colon, *end; + int pipefd[2][2]; + pid_t pid; + + if (host[0] == '[') { + end = strchr(host + 1, ']'); + if (end) { + *end = 0; + end++; + host++; + } else + end = host; + } else + end = host; + colon = strchr(end, ':'); + + if (colon) { + *colon = 0; + port = colon + 1; + } + + if (pipe(pipefd[0]) < 0 || pipe(pipefd[1]) < 0) + die("unable to create pipe pair for communication"); + pid = fork(); + if (!pid) { + 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]); + execlp(git_proxy_command, git_proxy_command, host, port, NULL); + die("exec failed"); + } + fd[0] = pipefd[0][0]; + fd[1] = pipefd[1][1]; + close(pipefd[0][1]); + close(pipefd[1][0]); + packet_write(fd[1], "%s %s\n", prog, path); + return pid; +} + /* * Yeah, yeah, fixme. Need to pass in the heads etc. */ @@ -493,8 +560,11 @@ int git_connect(int fd[2], char *url, const char *prog) *ptr = '\0'; } - if (protocol == PROTO_GIT) + if (protocol == PROTO_GIT) { + if (git_use_proxy()) + return git_proxy_connect(fd, prog, host, path); return git_tcp_connect(fd, prog, host, path); + } if (pipe(pipefd[0]) < 0 || pipe(pipefd[1]) < 0) die("unable to create pipe pair for communication");