Merge branch 'ms/http-no-more-failonerror'

Debugging help for http transport.

* ms/http-no-more-failonerror:
  test: test GIT_CURL_VERBOSE=1 shows an error
  remote-curl: unset CURLOPT_FAILONERROR
  remote-curl: define struct for CURLOPT_WRITEFUNCTION
  http: enable keep_error for HTTP requests
  http: support file handles for HTTP_KEEP_ERROR
This commit is contained in:
Junio C Hamano 2019-01-29 12:47:55 -08:00
Родитель d94ade7f1f e4871cd50c
Коммит 99c0bdd09d
5 изменённых файлов: 72 добавлений и 19 удалений

32
http.c
Просмотреть файл

@ -1876,8 +1876,6 @@ static int http_request(const char *url,
strbuf_addstr(&buf, "Pragma:");
if (options && options->no_cache)
strbuf_addstr(&buf, " no-cache");
if (options && options->keep_error)
curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 0);
if (options && options->initial_request &&
http_follow_config == HTTP_FOLLOW_INITIAL)
curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 1);
@ -1895,6 +1893,7 @@ static int http_request(const char *url,
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(slot->curl, CURLOPT_ENCODING, "");
curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 0);
ret = run_one_slot(slot, &results);
@ -1989,19 +1988,26 @@ static int http_request_reauth(const char *url,
return ret;
/*
* If we are using KEEP_ERROR, the previous request may have
* put cruft into our output stream; we should clear it out before
* making our next request. We only know how to do this for
* the strbuf case, but that is enough to satisfy current callers.
* The previous request may have put cruft into our output stream; we
* should clear it out before making our next request.
*/
if (options && options->keep_error) {
switch (target) {
case HTTP_REQUEST_STRBUF:
strbuf_reset(result);
break;
default:
BUG("HTTP_KEEP_ERROR is only supported with strbufs");
switch (target) {
case HTTP_REQUEST_STRBUF:
strbuf_reset(result);
break;
case HTTP_REQUEST_FILE:
if (fflush(result)) {
error_errno("unable to flush a file");
return HTTP_START_FAILED;
}
rewind(result);
if (ftruncate(fileno(result), 0) < 0) {
error_errno("unable to truncate a file");
return HTTP_START_FAILED;
}
break;
default:
BUG("Unknown http_request target");
}
credential_fill(&http_auth);

1
http.h
Просмотреть файл

@ -146,7 +146,6 @@ extern char *get_remote_object_url(const char *url, const char *hex,
/* Options for http_get_*() */
struct http_get_options {
unsigned no_cache:1,
keep_error:1,
initial_request:1;
/* If non-NULL, returns the content-type of the response. */

Просмотреть файл

@ -380,7 +380,6 @@ static struct discovery *discover_refs(const char *service, int for_push)
http_options.extra_headers = &extra_headers;
http_options.initial_request = 1;
http_options.no_cache = 1;
http_options.keep_error = 1;
http_ret = http_get_strbuf(refs_url.buf, &buffer, &http_options);
switch (http_ret) {
@ -546,14 +545,30 @@ static curlioerr rpc_ioctl(CURL *handle, int cmd, void *clientp)
}
#endif
struct rpc_in_data {
struct rpc_state *rpc;
struct active_request_slot *slot;
};
/*
* A callback for CURLOPT_WRITEFUNCTION. The return value is the bytes consumed
* from ptr.
*/
static size_t rpc_in(char *ptr, size_t eltsize,
size_t nmemb, void *buffer_)
{
size_t size = eltsize * nmemb;
struct rpc_state *rpc = buffer_;
struct rpc_in_data *data = buffer_;
long response_code;
if (curl_easy_getinfo(data->slot->curl, CURLINFO_RESPONSE_CODE,
&response_code) != CURLE_OK)
return size;
if (response_code >= 300)
return size;
if (size)
rpc->any_written = 1;
write_or_die(rpc->in, ptr, size);
data->rpc->any_written = 1;
write_or_die(data->rpc->in, ptr, size);
return size;
}
@ -634,6 +649,7 @@ static int post_rpc(struct rpc_state *rpc)
size_t gzip_size = 0;
int err, large_request = 0;
int needs_100_continue = 0;
struct rpc_in_data rpc_in_data;
/* Try to load the entire request, if we can fit it into the
* allocated buffer space we can use HTTP/1.0 and avoid the
@ -766,7 +782,10 @@ retry:
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, rpc_in);
curl_easy_setopt(slot->curl, CURLOPT_FILE, rpc);
rpc_in_data.rpc = rpc;
rpc_in_data.slot = slot;
curl_easy_setopt(slot->curl, CURLOPT_FILE, &rpc_in_data);
curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 0);
rpc->any_written = 0;

Просмотреть файл

@ -115,6 +115,7 @@ Alias /auth/dumb/ www/auth/dumb/
SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
SetEnv GIT_HTTP_EXPORT_ALL
</LocationMatch>
ScriptAliasMatch /error_git_upload_pack/(.*)/git-upload-pack error.sh/
ScriptAliasMatch /smart_*[^/]*/(.*) ${GIT_EXEC_PATH}/git-http-backend/$1
ScriptAlias /broken_smart/ broken-smart-http.sh/
ScriptAlias /error/ error.sh/

28
t/t5581-http-curl-verbose.sh Executable file
Просмотреть файл

@ -0,0 +1,28 @@
#!/bin/sh
test_description='test GIT_CURL_VERBOSE'
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-httpd.sh
start_httpd
test_expect_success 'setup repository' '
mkdir "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
git -C "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" --bare init &&
git config push.default matching &&
echo content >file &&
git add file &&
git commit -m one &&
git remote add public "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
git push public master:master
'
test_expect_success 'failure in git-upload-pack is shown' '
test_might_fail env GIT_CURL_VERBOSE=1 \
git clone "$HTTPD_URL/error_git_upload_pack/smart/repo.git" \
2>curl_log &&
grep "< HTTP/1.1 500 Intentional Breakage" curl_log
'
stop_httpd
test_done