Merge branch 'jt/http-base-url-update-upon-redirect'
authorJunio C Hamano <gitster@pobox.com>
Fri, 10 Mar 2017 21:24:23 +0000 (13:24 -0800)
committerJunio C Hamano <gitster@pobox.com>
Fri, 10 Mar 2017 21:24:23 +0000 (13:24 -0800)
When a redirected http transport gets an error during the
redirected request, we ignored the error we got from the server,
and ended up giving a not-so-useful error message.

* jt/http-base-url-update-upon-redirect:
http: attempt updating base URL only if no error

1  2 
http.c
t/t5550-http-fetch-dumb.sh
diff --combined http.c
index d2d6899b99bdf7c1ba3bae79d3ff53d09e7a1bd6,1df186894d2a8b1ae17792cac72c524aa823443a..96d84bbed3f66153cc3d817f2b342dc5d1600574
--- 1/http.c
--- 2/http.c
+++ b/http.c
@@@ -109,7 -109,7 +109,7 @@@ static int curl_save_cookies
  struct credential http_auth = CREDENTIAL_INIT;
  static int http_proactive_auth;
  static const char *user_agent;
 -static int curl_empty_auth;
 +static int curl_empty_auth = -1;
  
  enum http_follow_config http_follow_config = HTTP_FOLLOW_INITIAL;
  
@@@ -125,14 -125,6 +125,14 @@@ static struct credential cert_auth = CR
  static int ssl_cert_password_required;
  #ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
  static unsigned long http_auth_methods = CURLAUTH_ANY;
 +static int http_auth_methods_restricted;
 +/* Modes for which empty_auth cannot actually help us. */
 +static unsigned long empty_auth_useless =
 +      CURLAUTH_BASIC
 +#ifdef CURLAUTH_DIGEST_IE
 +      | CURLAUTH_DIGEST_IE
 +#endif
 +      | CURLAUTH_DIGEST;
  #endif
  
  static struct curl_slist *pragma_header;
@@@ -341,10 -333,7 +341,10 @@@ static int http_options(const char *var
                return git_config_string(&user_agent, var, value);
  
        if (!strcmp("http.emptyauth", var)) {
 -              curl_empty_auth = git_config_bool(var, value);
 +              if (value && !strcmp("auto", value))
 +                      curl_empty_auth = -1;
 +              else
 +                      curl_empty_auth = git_config_bool(var, value);
                return 0;
        }
  
        return git_default_config(var, value, cb);
  }
  
 +static int curl_empty_auth_enabled(void)
 +{
 +      if (curl_empty_auth >= 0)
 +              return curl_empty_auth;
 +
 +#ifndef LIBCURL_CAN_HANDLE_AUTH_ANY
 +      /*
 +       * Our libcurl is too old to do AUTH_ANY in the first place;
 +       * just default to turning the feature off.
 +       */
 +#else
 +      /*
 +       * In the automatic case, kick in the empty-auth
 +       * hack as long as we would potentially try some
 +       * method more exotic than "Basic" or "Digest".
 +       *
 +       * But only do this when this is our second or
 +       * subsequent request, as by then we know what
 +       * methods are available.
 +       */
 +      if (http_auth_methods_restricted &&
 +          (http_auth_methods & ~empty_auth_useless))
 +              return 1;
 +#endif
 +      return 0;
 +}
 +
  static void init_curl_http_auth(CURL *result)
  {
        if (!http_auth.username || !*http_auth.username) {
 -              if (curl_empty_auth)
 +              if (curl_empty_auth_enabled())
                        curl_easy_setopt(result, CURLOPT_USERPWD, ":");
                return;
        }
@@@ -1117,7 -1079,7 +1117,7 @@@ struct active_request_slot *get_active_
  #ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
        curl_easy_setopt(slot->curl, CURLOPT_HTTPAUTH, http_auth_methods);
  #endif
 -      if (http_auth.password || curl_empty_auth)
 +      if (http_auth.password || curl_empty_auth_enabled())
                init_curl_http_auth(slot->curl);
  
        return slot;
@@@ -1385,10 -1347,6 +1385,10 @@@ static int handle_curl_result(struct sl
                } else {
  #ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
                        http_auth_methods &= ~CURLAUTH_GSSNEGOTIATE;
 +                      if (results->auth_avail) {
 +                              http_auth_methods &= results->auth_avail;
 +                              http_auth_methods_restricted = 1;
 +                      }
  #endif
                        return HTTP_REAUTH;
                }
@@@ -1769,6 -1727,9 +1769,9 @@@ static int http_request_reauth(const ch
  {
        int ret = http_request(url, result, target, options);
  
+       if (ret != HTTP_OK && ret != HTTP_REAUTH)
+               return ret;
        if (options && options->effective_url && options->base_url) {
                if (update_url_from_redirect(options->base_url,
                                             url, options->effective_url)) {
index b69ece1d66f2b076ff94904dc7fddb7c7c1c88c5,2d3b1e9f937219b84069d9d0b1ce17129e87d110..87308cdced9af11365d5eb0644b9ac86fac21177
@@@ -34,15 -34,6 +34,15 @@@ test_expect_success 'clone http reposit
        test_cmp file clone/file
  '
  
 +test_expect_success 'list refs from outside any repository' '
 +      cat >expect <<-EOF &&
 +      $(git rev-parse master) HEAD
 +      $(git rev-parse master) refs/heads/master
 +      EOF
 +      nongit git ls-remote "$HTTPD_URL/dumb/repo.git" >actual &&
 +      test_cmp expect actual
 +'
 +
  test_expect_success 'create password-protected repository' '
        mkdir -p "$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/" &&
        cp -Rf "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \
@@@ -387,5 -378,14 +387,14 @@@ test_expect_success 'http-alternates tr
                clone $HTTPD_URL/dumb/evil.git evil-user
  '
  
+ test_expect_success 'can redirect through non-"info/refs?service=git-upload-pack" URL' '
+       git clone "$HTTPD_URL/redir-to/dumb/repo.git"
+ '
+ test_expect_success 'print HTTP error when any intermediate redirect throws error' '
+       test_must_fail git clone "$HTTPD_URL/redir-to/502" 2> stderr &&
+       test_i18ngrep "unable to access.*/redir-to/502" stderr
+ '
  stop_httpd
  test_done