Merge branch 'bc/http-keep-memory-given-to-curl'
authorJunio C Hamano <gitster@pobox.com>
Thu, 27 Jun 2013 21:29:49 +0000 (14:29 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 27 Jun 2013 21:29:49 +0000 (14:29 -0700)
Older cURL wanted piece of memory we call it with to be stable, but
we updated the auth material after handing it to a call.

* bc/http-keep-memory-given-to-curl:
http.c: don't rewrite the user:passwd string multiple times

1  2 
http.c
diff --combined http.c
index 92aba59082a4ed9aa0c92d8522793abcd332e279,c02246a78b954569e9c6d5757f7ffe7464e97424..2d086aedfac9a8ea384c53f3b1963149b880ed31
--- 1/http.c
--- 2/http.c
+++ b/http.c
@@@ -5,7 -5,6 +5,7 @@@
  #include "url.h"
  #include "credential.h"
  #include "version.h"
 +#include "pkt-line.h"
  
  int active_requests;
  int http_is_verbose;
@@@ -31,7 -30,6 +31,7 @@@ static CURL *curl_default
  char curl_errorstr[CURL_ERROR_SIZE];
  
  static int curl_ssl_verify = -1;
 +static int curl_ssl_try;
  static const char *ssl_cert;
  #if LIBCURL_VERSION_NUM >= 0x070903
  static const char *ssl_key;
@@@ -164,10 -162,6 +164,10 @@@ static int http_options(const char *var
                        ssl_cert_password_required = 1;
                return 0;
        }
 +      if (!strcmp("http.ssltry", var)) {
 +              curl_ssl_try = git_config_bool(var, value);
 +              return 0;
 +      }
        if (!strcmp("http.minsessions", var)) {
                min_curl_sessions = git_config_int(var, value);
  #ifndef USE_CURL_MULTI
@@@ -228,9 -222,15 +228,15 @@@ static void init_curl_http_auth(CURL *r
  #else
        {
                static struct strbuf up = STRBUF_INIT;
-               strbuf_reset(&up);
-               strbuf_addf(&up, "%s:%s",
-                           http_auth.username, http_auth.password);
+               /*
+                * Note that we assume we only ever have a single set of
+                * credentials in a given program run, so we do not have
+                * to worry about updating this buffer, only setting its
+                * initial value.
+                */
+               if (!up.len)
+                       strbuf_addf(&up, "%s:%s",
+                               http_auth.username, http_auth.password);
                curl_easy_setopt(result, CURLOPT_USERPWD, up.buf);
        }
  #endif
@@@ -287,6 -287,7 +293,6 @@@ static CURL *get_curl_handle(void
  #endif
        if (ssl_cainfo != NULL)
                curl_easy_setopt(result, CURLOPT_CAINFO, ssl_cainfo);
 -      curl_easy_setopt(result, CURLOPT_FAILONERROR, 1);
  
        if (curl_low_speed_limit > 0 && curl_low_speed_time > 0) {
                curl_easy_setopt(result, CURLOPT_LOW_SPEED_LIMIT,
        if (curl_ftp_no_epsv)
                curl_easy_setopt(result, CURLOPT_FTP_USE_EPSV, 0);
  
 +#ifdef CURLOPT_USE_SSL
 +      if (curl_ssl_try)
 +              curl_easy_setopt(result, CURLOPT_USE_SSL, CURLUSESSL_TRY);
 +#endif
 +
        if (curl_http_proxy) {
                curl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);
                curl_easy_setopt(result, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
@@@ -515,7 -511,6 +521,7 @@@ struct active_request_slot *get_active_
        curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, NULL);
        curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 0);
        curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
 +      curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 1);
        if (http_auth.password)
                init_curl_http_auth(slot->curl);
  
@@@ -771,25 -766,6 +777,25 @@@ char *get_remote_object_url(const char 
  
  int handle_curl_result(struct slot_results *results)
  {
 +      /*
 +       * If we see a failing http code with CURLE_OK, we have turned off
 +       * FAILONERROR (to keep the server's custom error response), and should
 +       * translate the code into failure here.
 +       */
 +      if (results->curl_result == CURLE_OK &&
 +          results->http_code >= 400) {
 +              results->curl_result = CURLE_HTTP_RETURNED_ERROR;
 +              /*
 +               * Normally curl will already have put the "reason phrase"
 +               * from the server into curl_errorstr; unfortunately without
 +               * FAILONERROR it is lost, so we can give only the numeric
 +               * status code.
 +               */
 +              snprintf(curl_errorstr, sizeof(curl_errorstr),
 +                       "The requested URL returned error: %ld",
 +                       results->http_code);
 +      }
 +
        if (results->curl_result == CURLE_OK) {
                credential_approve(&http_auth);
                return HTTP_OK;
@@@ -854,8 -830,6 +860,8 @@@ static int http_request(const char *url
        strbuf_addstr(&buf, "Pragma:");
        if (options & HTTP_NO_CACHE)
                strbuf_addstr(&buf, " no-cache");
 +      if (options & HTTP_KEEP_ERROR)
 +              curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 0);
  
        headers = curl_slist_append(headers, buf.buf);
  
                run_active_slot(slot);
                ret = handle_curl_result(&results);
        } else {
 -              error("Unable to start HTTP request for %s", url);
 +              snprintf(curl_errorstr, sizeof(curl_errorstr),
 +                       "failed to start HTTP request");
                ret = HTTP_START_FAILED;
        }
  
@@@ -894,22 -867,6 +900,22 @@@ static int http_request_reauth(const ch
        int ret = http_request(url, type, result, target, options);
        if (ret != HTTP_REAUTH)
                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.
 +       */
 +      if (options & HTTP_KEEP_ERROR) {
 +              switch (target) {
 +              case HTTP_REQUEST_STRBUF:
 +                      strbuf_reset(result);
 +                      break;
 +              default:
 +                      die("BUG: HTTP_KEEP_ERROR is only supported with strbufs");
 +              }
 +      }
        return http_request(url, type, result, target, options);
  }
  
@@@ -951,6 -908,15 +957,6 @@@ cleanup
        return ret;
  }
  
 -int http_error(const char *url, int ret)
 -{
 -      /* http_request has already handled HTTP_START_FAILED. */
 -      if (ret != HTTP_START_FAILED)
 -              error("%s while accessing %s", curl_errorstr, url);
 -
 -      return ret;
 -}
 -
  int http_fetch_ref(const char *base, struct ref *ref)
  {
        char *url;