summaryrefslogtreecommitdiff
path: root/src/remote.c
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2021-09-01 21:57:16 -0400
committerGitHub <noreply@github.com>2021-09-01 21:57:16 -0400
commit002b2ffe69d9d17e5b5570c5cd3cc13bac4b004c (patch)
tree1ae5a9dd0aab3ffec9d7433efff5b97696db9b9d /src/remote.c
parentd56b4079e0474b2f96abe0487a44359970e43c2a (diff)
parent3c0f14cc95debb426bd53150aac0eef1a7f625d8 (diff)
downloadlibgit2-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.c149
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;
}