Skip to content

Commit 99c0bdd

Browse files
committed
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
2 parents d94ade7 + e4871cd commit 99c0bdd

File tree

5 files changed

+72
-19
lines changed

5 files changed

+72
-19
lines changed

http.c

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,8 +1876,6 @@ static int http_request(const char *url,
18761876
strbuf_addstr(&buf, "Pragma:");
18771877
if (options && options->no_cache)
18781878
strbuf_addstr(&buf, " no-cache");
1879-
if (options && options->keep_error)
1880-
curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 0);
18811879
if (options && options->initial_request &&
18821880
http_follow_config == HTTP_FOLLOW_INITIAL)
18831881
curl_easy_setopt(slot->curl, CURLOPT_FOLLOWLOCATION, 1);
@@ -1895,6 +1893,7 @@ static int http_request(const char *url,
18951893
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
18961894
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers);
18971895
curl_easy_setopt(slot->curl, CURLOPT_ENCODING, "");
1896+
curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 0);
18981897

18991898
ret = run_one_slot(slot, &results);
19001899

@@ -1989,19 +1988,26 @@ static int http_request_reauth(const char *url,
19891988
return ret;
19901989

19911990
/*
1992-
* If we are using KEEP_ERROR, the previous request may have
1993-
* put cruft into our output stream; we should clear it out before
1994-
* making our next request. We only know how to do this for
1995-
* the strbuf case, but that is enough to satisfy current callers.
1991+
* The previous request may have put cruft into our output stream; we
1992+
* should clear it out before making our next request.
19961993
*/
1997-
if (options && options->keep_error) {
1998-
switch (target) {
1999-
case HTTP_REQUEST_STRBUF:
2000-
strbuf_reset(result);
2001-
break;
2002-
default:
2003-
BUG("HTTP_KEEP_ERROR is only supported with strbufs");
1994+
switch (target) {
1995+
case HTTP_REQUEST_STRBUF:
1996+
strbuf_reset(result);
1997+
break;
1998+
case HTTP_REQUEST_FILE:
1999+
if (fflush(result)) {
2000+
error_errno("unable to flush a file");
2001+
return HTTP_START_FAILED;
20042002
}
2003+
rewind(result);
2004+
if (ftruncate(fileno(result), 0) < 0) {
2005+
error_errno("unable to truncate a file");
2006+
return HTTP_START_FAILED;
2007+
}
2008+
break;
2009+
default:
2010+
BUG("Unknown http_request target");
20052011
}
20062012

20072013
credential_fill(&http_auth);

http.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,6 @@ extern char *get_remote_object_url(const char *url, const char *hex,
146146
/* Options for http_get_*() */
147147
struct http_get_options {
148148
unsigned no_cache:1,
149-
keep_error:1,
150149
initial_request:1;
151150

152151
/* If non-NULL, returns the content-type of the response. */

remote-curl.c

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,6 @@ static struct discovery *discover_refs(const char *service, int for_push)
380380
http_options.extra_headers = &extra_headers;
381381
http_options.initial_request = 1;
382382
http_options.no_cache = 1;
383-
http_options.keep_error = 1;
384383

385384
http_ret = http_get_strbuf(refs_url.buf, &buffer, &http_options);
386385
switch (http_ret) {
@@ -546,14 +545,30 @@ static curlioerr rpc_ioctl(CURL *handle, int cmd, void *clientp)
546545
}
547546
#endif
548547

548+
struct rpc_in_data {
549+
struct rpc_state *rpc;
550+
struct active_request_slot *slot;
551+
};
552+
553+
/*
554+
* A callback for CURLOPT_WRITEFUNCTION. The return value is the bytes consumed
555+
* from ptr.
556+
*/
549557
static size_t rpc_in(char *ptr, size_t eltsize,
550558
size_t nmemb, void *buffer_)
551559
{
552560
size_t size = eltsize * nmemb;
553-
struct rpc_state *rpc = buffer_;
561+
struct rpc_in_data *data = buffer_;
562+
long response_code;
563+
564+
if (curl_easy_getinfo(data->slot->curl, CURLINFO_RESPONSE_CODE,
565+
&response_code) != CURLE_OK)
566+
return size;
567+
if (response_code >= 300)
568+
return size;
554569
if (size)
555-
rpc->any_written = 1;
556-
write_or_die(rpc->in, ptr, size);
570+
data->rpc->any_written = 1;
571+
write_or_die(data->rpc->in, ptr, size);
557572
return size;
558573
}
559574

@@ -634,6 +649,7 @@ static int post_rpc(struct rpc_state *rpc)
634649
size_t gzip_size = 0;
635650
int err, large_request = 0;
636651
int needs_100_continue = 0;
652+
struct rpc_in_data rpc_in_data;
637653

638654
/* Try to load the entire request, if we can fit it into the
639655
* allocated buffer space we can use HTTP/1.0 and avoid the
@@ -766,7 +782,10 @@ static int post_rpc(struct rpc_state *rpc)
766782

767783
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers);
768784
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, rpc_in);
769-
curl_easy_setopt(slot->curl, CURLOPT_FILE, rpc);
785+
rpc_in_data.rpc = rpc;
786+
rpc_in_data.slot = slot;
787+
curl_easy_setopt(slot->curl, CURLOPT_FILE, &rpc_in_data);
788+
curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 0);
770789

771790

772791
rpc->any_written = 0;

t/lib-httpd/apache.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ Alias /auth/dumb/ www/auth/dumb/
115115
SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
116116
SetEnv GIT_HTTP_EXPORT_ALL
117117
</LocationMatch>
118+
ScriptAliasMatch /error_git_upload_pack/(.*)/git-upload-pack error.sh/
118119
ScriptAliasMatch /smart_*[^/]*/(.*) ${GIT_EXEC_PATH}/git-http-backend/$1
119120
ScriptAlias /broken_smart/ broken-smart-http.sh/
120121
ScriptAlias /error/ error.sh/

t/t5581-http-curl-verbose.sh

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/bin/sh
2+
3+
test_description='test GIT_CURL_VERBOSE'
4+
. ./test-lib.sh
5+
. "$TEST_DIRECTORY"/lib-httpd.sh
6+
start_httpd
7+
8+
test_expect_success 'setup repository' '
9+
mkdir "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
10+
git -C "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" --bare init &&
11+
git config push.default matching &&
12+
echo content >file &&
13+
git add file &&
14+
git commit -m one &&
15+
git remote add public "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
16+
git push public master:master
17+
'
18+
19+
test_expect_success 'failure in git-upload-pack is shown' '
20+
test_might_fail env GIT_CURL_VERBOSE=1 \
21+
git clone "$HTTPD_URL/error_git_upload_pack/smart/repo.git" \
22+
2>curl_log &&
23+
grep "< HTTP/1.1 500 Intentional Breakage" curl_log
24+
'
25+
26+
stop_httpd
27+
28+
test_done

0 commit comments

Comments
 (0)