diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2021-09-01 21:57:16 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-01 21:57:16 -0400 |
commit | 002b2ffe69d9d17e5b5570c5cd3cc13bac4b004c (patch) | |
tree | 1ae5a9dd0aab3ffec9d7433efff5b97696db9b9d /src/remote.c | |
parent | d56b4079e0474b2f96abe0487a44359970e43c2a (diff) | |
parent | 3c0f14cc95debb426bd53150aac0eef1a7f625d8 (diff) | |
download | libgit2-002b2ffe69d9d17e5b5570c5cd3cc13bac4b004c.tar.gz |
Merge pull request #6026 from libgit2/ethomson/proxy
Update proxy configuration
Diffstat (limited to 'src/remote.c')
-rw-r--r-- | src/remote.c | 149 |
1 files changed, 107 insertions, 42 deletions
diff --git a/src/remote.c b/src/remote.c index 73375b352..7dddea93a 100644 --- a/src/remote.c +++ b/src/remote.c @@ -849,75 +849,140 @@ int git_remote_ls(const git_remote_head ***out, size_t *size, git_remote *remote return remote->transport->ls(out, size, remote->transport); } -int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_url) +static int lookup_config(char **out, git_config *cfg, const char *name) { - git_config *cfg; git_config_entry *ce = NULL; - git_buf val = GIT_BUF_INIT; int error; - GIT_ASSERT_ARG(remote); + if ((error = git_config__lookup_entry(&ce, cfg, name, false)) < 0) + return error; - if (!proxy_url || !remote->repo) - return -1; + if (ce && ce->value) { + *out = git__strdup(ce->value); + GIT_ERROR_CHECK_ALLOC(*out); + } else { + error = GIT_ENOTFOUND; + } + + git_config_entry_free(ce); + return error; +} - *proxy_url = NULL; +static void url_config_trim(git_net_url *url) +{ + size_t len = strlen(url->path); - if ((error = git_repository_config__weakptr(&cfg, remote->repo)) < 0) - return error; + if (url->path[len - 1] == '/') { + len--; + } else { + while (len && url->path[len - 1] != '/') + len--; + } - /* Go through the possible sources for proxy configuration, from most specific - * to least specific. */ + url->path[len] = '\0'; +} + +static int http_proxy_config(char **out, git_remote *remote, git_net_url *url) +{ + git_config *cfg; + git_buf buf = GIT_BUF_INIT; + git_net_url lookup_url = GIT_NET_URL_INIT; + int error; + + if ((error = git_net_url_dup(&lookup_url, url)) < 0 || + (error = git_repository_config__weakptr(&cfg, remote->repo)) < 0) + goto done; /* remote.<name>.proxy config setting */ if (remote->name && remote->name[0]) { - git_buf buf = GIT_BUF_INIT; + git_buf_clear(&buf); - if ((error = git_buf_printf(&buf, "remote.%s.proxy", remote->name)) < 0) - return error; + if ((error = git_buf_printf(&buf, "remote.%s.proxy", remote->name)) < 0 || + (error = lookup_config(out, cfg, buf.ptr)) != GIT_ENOTFOUND) + goto done; + } - error = git_config__lookup_entry(&ce, cfg, git_buf_cstr(&buf), false); - git_buf_dispose(&buf); + while (true) { + git_buf_clear(&buf); - if (error < 0) - return error; + if ((error = git_buf_puts(&buf, "http.")) < 0 || + (error = git_net_url_fmt(&buf, &lookup_url)) < 0 || + (error = git_buf_puts(&buf, ".proxy")) < 0 || + (error = lookup_config(out, cfg, buf.ptr)) != GIT_ENOTFOUND) + goto done; - if (ce && ce->value) { - *proxy_url = git__strdup(ce->value); - goto found; - } + if (! lookup_url.path[0]) + break; + + url_config_trim(&lookup_url); } - /* http.proxy config setting */ - if ((error = git_config__lookup_entry(&ce, cfg, "http.proxy", false)) < 0) - return error; + git_buf_clear(&buf); - if (ce && ce->value) { - *proxy_url = git__strdup(ce->value); - goto found; - } + error = lookup_config(out, cfg, "http.proxy"); + +done: + git_buf_dispose(&buf); + git_net_url_dispose(&lookup_url); + return error; +} + +static int http_proxy_env(char **out, git_remote *remote, git_net_url *url) +{ + git_buf proxy_env = GIT_BUF_INIT, no_proxy_env = GIT_BUF_INIT; + bool use_ssl = (strcmp(url->scheme, "https") == 0); + int error; + + GIT_UNUSED(remote); /* http_proxy / https_proxy environment variables */ - error = git__getenv(&val, use_ssl ? "https_proxy" : "http_proxy"); + error = git__getenv(&proxy_env, use_ssl ? "https_proxy" : "http_proxy"); /* try uppercase environment variables */ if (error == GIT_ENOTFOUND) - error = git__getenv(&val, use_ssl ? "HTTPS_PROXY" : "HTTP_PROXY"); + error = git__getenv(&proxy_env, use_ssl ? "HTTPS_PROXY" : "HTTP_PROXY"); - if (error < 0) { - if (error == GIT_ENOTFOUND) { - git_error_clear(); - error = 0; - } + if (error) + goto done; - return error; - } + /* no_proxy/NO_PROXY environment variables */ + error = git__getenv(&no_proxy_env, "no_proxy"); - *proxy_url = git_buf_detach(&val); + if (error == GIT_ENOTFOUND) + error = git__getenv(&no_proxy_env, "NO_PROXY"); -found: - GIT_ERROR_CHECK_ALLOC(*proxy_url); - git_config_entry_free(ce); + if (error && error != GIT_ENOTFOUND) + goto done; + + if (!git_net_url_matches_pattern_list(url, no_proxy_env.ptr)) + *out = git_buf_detach(&proxy_env); + else + error = GIT_ENOTFOUND; + +done: + git_buf_dispose(&proxy_env); + git_buf_dispose(&no_proxy_env); + return error; +} + +int git_remote__http_proxy(char **out, git_remote *remote, git_net_url *url) +{ + int error; + + GIT_ASSERT_ARG(out); + GIT_ASSERT_ARG(remote); + GIT_ASSERT_ARG(remote->repo); + + *out = NULL; + + /* + * Go through the possible sources for proxy configuration, + * Examine the various git config options first, then + * consult environment variables. + */ + if ((error = http_proxy_config(out, remote, url)) != GIT_ENOTFOUND || + (error = http_proxy_env(out, remote, url)) != GIT_ENOTFOUND) + return error; return 0; } |