From: Junio C Hamano Date: Tue, 29 Jan 2019 20:47:55 +0000 (-0800) Subject: Merge branch 'ms/http-no-more-failonerror' X-Git-Tag: v2.21.0-rc0~63 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/99c0bdd09de2b04b7a4464e14fe9b65e2152b3d1?ds=inline;hp=-c 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 --- 99c0bdd09de2b04b7a4464e14fe9b65e2152b3d1 diff --combined http.c index 0b6807cef9,b39921636a..954bebf684 --- a/http.c +++ b/http.c @@@ -48,7 -48,6 +48,7 @@@ char curl_errorstr[CURL_ERROR_SIZE] static int curl_ssl_verify = -1; static int curl_ssl_try; +static const char *curl_http_version = NULL; static const char *ssl_cert; static const char *ssl_cipherlist; static const char *ssl_version; @@@ -285,9 -284,6 +285,9 @@@ static void process_curl_messages(void static int http_options(const char *var, const char *value, void *cb) { + if (!strcmp("http.version", var)) { + return git_config_string(&curl_http_version, var, value); + } if (!strcmp("http.sslverify", var)) { curl_ssl_verify = git_config_bool(var, value); return 0; @@@ -793,31 -789,6 +793,31 @@@ static long get_curl_allowed_protocols( } #endif +#if LIBCURL_VERSION_NUM >=0x072f00 +static int get_curl_http_version_opt(const char *version_string, long *opt) +{ + int i; + static struct { + const char *name; + long opt_token; + } choice[] = { + { "HTTP/1.1", CURL_HTTP_VERSION_1_1 }, + { "HTTP/2", CURL_HTTP_VERSION_2 } + }; + + for (i = 0; i < ARRAY_SIZE(choice); i++) { + if (!strcmp(version_string, choice[i].name)) { + *opt = choice[i].opt_token; + return 0; + } + } + + warning("unknown value given to http.version: '%s'", version_string); + return -1; /* not found */ +} + +#endif + static CURL *get_curl_handle(void) { CURL *result = curl_easy_init(); @@@ -835,16 -806,6 +835,16 @@@ curl_easy_setopt(result, CURLOPT_SSL_VERIFYHOST, 2); } +#if LIBCURL_VERSION_NUM >= 0x072f00 // 7.47.0 + if (curl_http_version) { + long opt; + if (!get_curl_http_version_opt(curl_http_version, &opt)) { + /* Set request use http version */ + curl_easy_setopt(result, CURLOPT_HTTP_VERSION, opt); + } + } +#endif + #if LIBCURL_VERSION_NUM >= 0x070907 curl_easy_setopt(result, CURLOPT_NETRC, CURL_NETRC_OPTIONAL); #endif @@@ -1876,8 -1837,6 +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 -1854,7 +1893,7 @@@ 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 -1949,26 +1988,26 @@@ static int http_request_reauth(const ch 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); @@@ -2353,7 -2320,7 +2359,7 @@@ struct http_object_request *new_http_ob hashcpy(freq->sha1, sha1); freq->localfile = -1; - sha1_file_name(the_repository, &filename, sha1); + loose_object_path(the_repository, &filename, sha1); strbuf_addf(&freq->tmpfile, "%s.temp", filename.buf); strbuf_addf(&prevfile, "%s.prev", filename.buf); @@@ -2504,7 -2471,7 +2510,7 @@@ int finish_http_object_request(struct h unlink_or_warn(freq->tmpfile.buf); return -1; } - sha1_file_name(the_repository, &filename, freq->sha1); + loose_object_path(the_repository, &filename, freq->sha1); freq->rename = finalize_object_file(freq->tmpfile.buf, filename.buf); strbuf_release(&filename); diff --combined remote-curl.c index 90d565c8c5,91b39ca098..6ff9c66b90 --- a/remote-curl.c +++ b/remote-curl.c @@@ -380,7 -380,6 +380,6 @@@ static struct discovery *discover_refs( 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 +545,30 @@@ static curlioerr rpc_ioctl(CURL *handle } #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; } @@@ -617,8 -632,7 +632,8 @@@ static int probe_rpc(struct rpc_state * return err; } -static curl_off_t xcurl_off_t(size_t len) { +static curl_off_t xcurl_off_t(size_t len) +{ uintmax_t size = len; if (size > maximum_signed_value_of_type(curl_off_t)) die("cannot handle pushes this big"); @@@ -634,6 -648,7 +649,7 @@@ static int post_rpc(struct rpc_state *r 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 -781,10 +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;