From e814bc4d159f62941fafe135c3008b3ff103444d Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 19 Nov 2005 03:48:56 -0800 Subject: git-proxy updates. This builds on top of the git-proxy mechanism Paul Collins did, and updates its configuration mechanism. * GIT_PROXY_COMMAND environment variable is used as the catch-all fallback, as in the original. This has not changed. * Renames proxy configuration variables to core.gitproxy; this has become a multi-value variable per list discussion, most notably from suggestion by Linus. [core] ;# matches www.kernel.org as well gitproxy = netcatter for kernel.org gitproxy = netscatter for sample.xz gitproxy = none for mydomain.xz gitproxy = netcatter-default The values are command names, followed by an optional " for " and domainname; the first tail-match of the domainname determines which proxy command is used. An entry without " for " matches any domain and can be used as the default. The command name "none" is special -- it tells the mechanism not to use any proxy command and use the native git:// connection. Signed-off-by: Junio C Hamano --- connect.c | 52 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/connect.c b/connect.c index be88ef038..a4d6d356f 100644 --- a/connect.c +++ b/connect.c @@ -449,25 +449,63 @@ 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 const char *rhost_name = NULL; +static int rhost_len; 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); + if (!strcmp(var, "core.gitproxy")) { + if (git_proxy_command) return 0; + /* [core] + * ;# matches www.kernel.org as well + * gitproxy = netcatter-1 for kernel.org + * gitproxy = netcatter-2 for sample.xz + * gitproxy = netcatter-default + */ + const char *for_pos = strstr(value, " for "); + int matchlen = -1; + int hostlen; + + if (!for_pos) + /* matches everybody */ + matchlen = strlen(value); + else { + hostlen = strlen(for_pos + 5); + if (rhost_len < hostlen) + matchlen = -1; + else if (!strncmp(for_pos + 5, + rhost_name + rhost_len - hostlen, + hostlen) && + ((rhost_len == hostlen) || + rhost_name[rhost_len - hostlen -1] == '.')) + matchlen = for_pos - value; + else + matchlen = -1; } + if (0 <= matchlen) { + /* core.gitproxy = none for kernel.org */ + if (matchlen == 4 && + !memcmp(value, "none", 4)) + matchlen = 0; + git_proxy_command = xmalloc(matchlen + 1); + memcpy(git_proxy_command, value, matchlen); + git_proxy_command[matchlen] = 0; + } + return 0; } return git_default_config(var, value); } -static int git_use_proxy(void) +static int git_use_proxy(const char *host) { + rhost_name = host; + rhost_len = strlen(host); git_proxy_command = getenv("GIT_PROXY_COMMAND"); git_config(git_proxy_command_options); - return git_proxy_command != NULL; + rhost_name = NULL; + return (git_proxy_command && *git_proxy_command); } static int git_proxy_connect(int fd[2], const char *prog, char *host, char *path) @@ -561,7 +599,7 @@ int git_connect(int fd[2], char *url, const char *prog) } if (protocol == PROTO_GIT) { - if (git_use_proxy()) + if (git_use_proxy(host)) return git_proxy_connect(fd, prog, host, path); return git_tcp_connect(fd, prog, host, path); } -- cgit v1.2.1