remote: honor `http.followRedirects` configuration option
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
diff --git a/src/remote.c b/src/remote.c
index 2e818cd..f101041 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -858,25 +858,70 @@ static int validate_custom_headers(const git_strarray *custom_headers)
return 0;
}
+static int lookup_redirect_config(
+ git_remote_redirect_t *out,
+ git_repository *repo)
+{
+ git_config *config;
+ const char *value;
+ int bool_value, error = 0;
+
+ if (!repo) {
+ *out = GIT_REMOTE_REDIRECT_INITIAL;
+ return 0;
+ }
+
+ if ((error = git_repository_config_snapshot(&config, repo)) < 0)
+ goto done;
+
+ if ((error = git_config_get_string(&value, config, "http.followRedirects")) < 0) {
+ if (error == GIT_ENOTFOUND) {
+ *out = GIT_REMOTE_REDIRECT_INITIAL;
+ error = 0;
+ }
+
+ goto done;
+ }
+
+ if (git_config_parse_bool(&bool_value, value) == 0) {
+ *out = bool_value ? GIT_REMOTE_REDIRECT_ALL :
+ GIT_REMOTE_REDIRECT_NONE;
+ } else if (strcasecmp(value, "initial") == 0) {
+ *out = GIT_REMOTE_REDIRECT_INITIAL;
+ } else {
+ git_error_set(GIT_ERROR_CONFIG, "invalid configuration setting '%s' for 'http.followRedirects'", value);
+ error = -1;
+ }
+
+done:
+ git_config_free(config);
+ return error;
+}
+
int git_remote_connect_options_normalize(
git_remote_connect_options *dst,
+ git_repository *repo,
const git_remote_connect_options *src)
{
git_remote_connect_options_dispose(dst);
+ git_remote_connect_options_init(dst, GIT_REMOTE_CONNECT_OPTIONS_VERSION);
- if (!src) {
- git_remote_connect_options_init(dst, GIT_REMOTE_CONNECT_OPTIONS_VERSION);
- return 0;
- }
+ if (src) {
+ GIT_ERROR_CHECK_VERSION(src, GIT_REMOTE_CONNECT_OPTIONS_VERSION, "git_remote_connect_options");
+ GIT_ERROR_CHECK_VERSION(&src->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
+ GIT_ERROR_CHECK_VERSION(&src->proxy_opts, GIT_PROXY_OPTIONS_VERSION, "git_proxy_options");
- GIT_ERROR_CHECK_VERSION(src, GIT_REMOTE_CONNECT_OPTIONS_VERSION, "git_remote_connect_options");
- GIT_ERROR_CHECK_VERSION(&src->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
- GIT_ERROR_CHECK_VERSION(&src->proxy_opts, GIT_PROXY_OPTIONS_VERSION, "git_proxy_options");
+ if (validate_custom_headers(&src->custom_headers) < 0 ||
+ git_remote_connect_options_dup(dst, src) < 0)
+ return -1;
+ }
- if (validate_custom_headers(&src->custom_headers))
- return -1;
+ if (dst->follow_redirects == 0) {
+ if (lookup_redirect_config(&dst->follow_redirects, repo) < 0)
+ return -1;
+ }
- return git_remote_connect_options_dup(dst, src);
+ return 0;
}
int git_remote_connect_ext(
@@ -1176,11 +1221,12 @@ static int ls_to_vector(git_vector *out, git_remote *remote)
GIT_INLINE(int) connect_opts_from_fetch_opts(
git_remote_connect_options *out,
+ git_remote *remote,
const git_fetch_options *fetch_opts)
{
git_remote_connect_options tmp = GIT_REMOTE_CONNECT_OPTIONS_INIT;
copy_opts(&tmp, fetch_opts);
- return git_remote_connect_options_normalize(out, &tmp);
+ return git_remote_connect_options_normalize(out, remote->repo, &tmp);
}
static int connect_or_reset_options(
@@ -1270,7 +1316,7 @@ int git_remote_download(
return -1;
}
- if (connect_opts_from_fetch_opts(&connect_opts, opts) < 0)
+ if (connect_opts_from_fetch_opts(&connect_opts, remote, opts) < 0)
return -1;
if ((error = connect_or_reset_options(remote, GIT_DIRECTION_FETCH, &connect_opts)) < 0)
@@ -1298,7 +1344,7 @@ int git_remote_fetch(
return -1;
}
- if (connect_opts_from_fetch_opts(&connect_opts, opts) < 0)
+ if (connect_opts_from_fetch_opts(&connect_opts, remote, opts) < 0)
return -1;
if ((error = connect_or_reset_options(remote, GIT_DIRECTION_FETCH, &connect_opts)) < 0)
@@ -2771,11 +2817,12 @@ done:
GIT_INLINE(int) connect_opts_from_push_opts(
git_remote_connect_options *out,
+ git_remote *remote,
const git_push_options *push_opts)
{
git_remote_connect_options tmp = GIT_REMOTE_CONNECT_OPTIONS_INIT;
copy_opts(&tmp, push_opts);
- return git_remote_connect_options_normalize(out, &tmp);
+ return git_remote_connect_options_normalize(out, remote->repo, &tmp);
}
int git_remote_upload(
@@ -2796,7 +2843,7 @@ int git_remote_upload(
return -1;
}
- if ((error = connect_opts_from_push_opts(&connect_opts, opts)) < 0)
+ if ((error = connect_opts_from_push_opts(&connect_opts, remote, opts)) < 0)
goto cleanup;
if ((error = connect_or_reset_options(remote, GIT_DIRECTION_PUSH, &connect_opts)) < 0)
@@ -2857,7 +2904,7 @@ int git_remote_push(
return -1;
}
- if (connect_opts_from_push_opts(&connect_opts, opts) < 0)
+ if (connect_opts_from_push_opts(&connect_opts, remote, opts) < 0)
return -1;
if ((error = git_remote_upload(remote, refspecs, opts)) < 0)
diff --git a/src/remote.h b/src/remote.h
index 1655e15..3cf0fd9 100644
--- a/src/remote.h
+++ b/src/remote.h
@@ -50,6 +50,7 @@ int git_remote_connect_options_dup(
const git_remote_connect_options *src);
int git_remote_connect_options_normalize(
git_remote_connect_options *dst,
+ git_repository *repo,
const git_remote_connect_options *src);
void git_remote_connect_options_dispose(git_remote_connect_options *opts);
diff --git a/src/transports/local.c b/src/transports/local.c
index 6065d40..86524ed 100644
--- a/src/transports/local.c
+++ b/src/transports/local.c
@@ -209,7 +209,7 @@ static int local_connect(
if (t->connected)
return 0;
- if (git_remote_connect_options_normalize(&t->connect_opts, connect_opts) < 0)
+ if (git_remote_connect_options_normalize(&t->connect_opts, t->owner->repo, connect_opts) < 0)
return -1;
free_heads(&t->refs);
@@ -253,7 +253,7 @@ static int local_set_connect_opts(
return -1;
}
- return git_remote_connect_options_normalize(&t->connect_opts, connect_opts);
+ return git_remote_connect_options_normalize(&t->connect_opts, t->owner->repo, connect_opts);
}
static int local_ls(const git_remote_head ***out, size_t *size, git_transport *transport)
diff --git a/src/transports/smart.c b/src/transports/smart.c
index 4267e88..e76c18f 100644
--- a/src/transports/smart.c
+++ b/src/transports/smart.c
@@ -125,7 +125,7 @@ static int git_smart__connect(
if (git_smart__reset_stream(t, true) < 0)
return -1;
- if (git_remote_connect_options_normalize(&t->connect_opts, connect_opts) < 0)
+ if (git_remote_connect_options_normalize(&t->connect_opts, t->owner->repo, connect_opts) < 0)
return -1;
t->url = git__strdup(url);
@@ -223,7 +223,7 @@ static int git_smart__set_connect_opts(
return -1;
}
- return git_remote_connect_options_normalize(&t->connect_opts, opts);
+ return git_remote_connect_options_normalize(&t->connect_opts, t->owner->repo, opts);
}
static int git_smart__ls(const git_remote_head ***out, size_t *size, git_transport *transport)