Merge branch 'jk/http-auth-redirects'

Handle the case where http transport gets redirected during the
authorization request better.

* jk/http-auth-redirects:
  http.c: Spell the null pointer as NULL
  remote-curl: rewrite base url from info/refs redirects
  remote-curl: store url as a strbuf
  remote-curl: make refs_url a strbuf
  http: update base URLs when we see redirects
  http: provide effective url to callers
  http: hoist credential request out of handle_curl_result
  http: refactor options to http_get_*
  http_request: factor out curlinfo_strbuf
  http_get_file: style fixes
This commit is contained in:
Junio C Hamano
2013-10-30 12:09:53 -07:00
7 changed files with 193 additions and 67 deletions

View File

@ -9,9 +9,11 @@
#include "string-list.h"
#include "sideband.h"
#include "argv-array.h"
#include "credential.h"
static struct remote *remote;
static const char *url; /* always ends with a trailing slash */
/* always ends with a trailing slash */
static struct strbuf url = STRBUF_INIT;
struct options {
int verbosity;
@ -130,7 +132,8 @@ static struct ref *parse_info_refs(struct discovery *heads)
mid = &data[i];
if (data[i] == '\n') {
if (mid - start != 40)
die("%sinfo/refs not valid: is this a git repository?", url);
die("%sinfo/refs not valid: is this a git repository?",
url.buf);
data[i] = 0;
ref_name = mid + 1;
ref = xmalloc(sizeof(struct ref) +
@ -149,7 +152,7 @@ static struct ref *parse_info_refs(struct discovery *heads)
}
ref = alloc_ref("HEAD");
if (!http_fetch_ref(url, ref) &&
if (!http_fetch_ref(url.buf, ref) &&
!resolve_remote_symref(ref, refs)) {
ref->next = refs;
refs = ref;
@ -203,40 +206,47 @@ static struct discovery* discover_refs(const char *service, int for_push)
struct strbuf exp = STRBUF_INIT;
struct strbuf type = STRBUF_INIT;
struct strbuf buffer = STRBUF_INIT;
struct strbuf refs_url = STRBUF_INIT;
struct strbuf effective_url = STRBUF_INIT;
struct discovery *last = last_discovery;
char *refs_url;
int http_ret, maybe_smart = 0;
struct http_get_options options;
if (last && !strcmp(service, last->service))
return last;
free_discovery(last);
strbuf_addf(&buffer, "%sinfo/refs", url);
if ((!prefixcmp(url, "http://") || !prefixcmp(url, "https://")) &&
strbuf_addf(&refs_url, "%sinfo/refs", url.buf);
if ((!prefixcmp(url.buf, "http://") || !prefixcmp(url.buf, "https://")) &&
git_env_bool("GIT_SMART_HTTP", 1)) {
maybe_smart = 1;
if (!strchr(url, '?'))
strbuf_addch(&buffer, '?');
if (!strchr(url.buf, '?'))
strbuf_addch(&refs_url, '?');
else
strbuf_addch(&buffer, '&');
strbuf_addf(&buffer, "service=%s", service);
strbuf_addch(&refs_url, '&');
strbuf_addf(&refs_url, "service=%s", service);
}
refs_url = strbuf_detach(&buffer, NULL);
http_ret = http_get_strbuf(refs_url, &type, &buffer,
HTTP_NO_CACHE | HTTP_KEEP_ERROR);
memset(&options, 0, sizeof(options));
options.content_type = &type;
options.effective_url = &effective_url;
options.base_url = &url;
options.no_cache = 1;
options.keep_error = 1;
http_ret = http_get_strbuf(refs_url.buf, &buffer, &options);
switch (http_ret) {
case HTTP_OK:
break;
case HTTP_MISSING_TARGET:
show_http_message(&type, &buffer);
die("repository '%s' not found", url);
die("repository '%s' not found", url.buf);
case HTTP_NOAUTH:
show_http_message(&type, &buffer);
die("Authentication failed for '%s'", url);
die("Authentication failed for '%s'", url.buf);
default:
show_http_message(&type, &buffer);
die("unable to access '%s': %s", url, curl_errorstr);
die("unable to access '%s': %s", url.buf, curl_errorstr);
}
last= xcalloc(1, sizeof(*last_discovery));
@ -277,9 +287,10 @@ static struct discovery* discover_refs(const char *service, int for_push)
else
last->refs = parse_info_refs(last);
free(refs_url);
strbuf_release(&refs_url);
strbuf_release(&exp);
strbuf_release(&type);
strbuf_release(&effective_url);
strbuf_release(&buffer);
last_discovery = last;
return last;
@ -463,6 +474,8 @@ static int post_rpc(struct rpc_state *rpc)
if (large_request) {
do {
err = probe_rpc(rpc);
if (err == HTTP_REAUTH)
credential_fill(&http_auth);
} while (err == HTTP_REAUTH);
if (err != HTTP_OK)
return -1;
@ -562,8 +575,10 @@ retry:
curl_easy_setopt(slot->curl, CURLOPT_FILE, rpc);
err = run_slot(slot);
if (err == HTTP_REAUTH && !large_request)
if (err == HTTP_REAUTH && !large_request) {
credential_fill(&http_auth);
goto retry;
}
if (err != HTTP_OK)
err = -1;
@ -598,7 +613,7 @@ static int rpc_service(struct rpc_state *rpc, struct discovery *heads)
rpc->out = client.out;
strbuf_init(&rpc->result, 0);
strbuf_addf(&buf, "%s%s", url, svc);
strbuf_addf(&buf, "%s%s", url.buf, svc);
rpc->service_url = strbuf_detach(&buf, NULL);
strbuf_addf(&buf, "Content-Type: application/x-%s-request", svc);
@ -650,7 +665,7 @@ static int fetch_dumb(int nr_heads, struct ref **to_fetch)
for (i = 0; i < nr_heads; i++)
targets[i] = xstrdup(sha1_to_hex(to_fetch[i]->old_sha1));
walker = get_http_walker(url);
walker = get_http_walker(url.buf);
walker->get_all = 1;
walker->get_tree = 1;
walker->get_history = 1;
@ -697,7 +712,7 @@ static int fetch_git(struct discovery *heads,
depth_arg = strbuf_detach(&buf, NULL);
argv[argc++] = depth_arg;
}
argv[argc++] = url;
argv[argc++] = url.buf;
argv[argc++] = NULL;
for (i = 0; i < nr_heads; i++) {
@ -795,7 +810,7 @@ static int push_dav(int nr_spec, char **specs)
argv[argc++] = "--dry-run";
if (options.verbosity > 1)
argv[argc++] = "--verbose";
argv[argc++] = url;
argv[argc++] = url.buf;
for (i = 0; i < nr_spec; i++)
argv[argc++] = specs[i];
argv[argc++] = NULL;
@ -828,7 +843,7 @@ static int push_git(struct discovery *heads, int nr_spec, char **specs)
argv_array_push(&args, options.progress ? "--progress" : "--no-progress");
for_each_string_list_item(cas_option, &cas_options)
argv_array_push(&args, cas_option->string);
argv_array_push(&args, url);
argv_array_push(&args, url.buf);
for (i = 0; i < nr_spec; i++)
argv_array_push(&args, specs[i]);
@ -909,14 +924,12 @@ int main(int argc, const char **argv)
remote = remote_get(argv[1]);
if (argc > 2) {
end_url_with_slash(&buf, argv[2]);
end_url_with_slash(&url, argv[2]);
} else {
end_url_with_slash(&buf, remote->url[0]);
end_url_with_slash(&url, remote->url[0]);
}
url = strbuf_detach(&buf, NULL);
http_init(remote, url, 0);
http_init(remote, url.buf, 0);
do {
if (strbuf_getline(&buf, stdin, '\n') == EOF) {