Merge branch 'bn/http-cookiefile-config'
authorJunio C Hamano <gitster@pobox.com>
Tue, 17 May 2016 21:38:18 +0000 (14:38 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 17 May 2016 21:38:18 +0000 (14:38 -0700)
"http.cookieFile" configuration variable clearly wants a pathname,
but we forgot to treat it as such by e.g. applying tilde expansion.

* bn/http-cookiefile-config:
http: expand http.cookieFile as a path
Documentation: config: improve word ordering for http.cookieFile

1  2 
Documentation/config.txt
http.c
diff --combined Documentation/config.txt
index 6e97e1e05e4912b5d0b80dc64f3fd683c41e7614,3c0c48478e0efce977197e0cf19fa9dfef487ea9..536b6e624a14ca275a702ca1f3f598fcdc9e6675
@@@ -308,15 -308,6 +308,15 @@@ core.trustctime:
        crawlers and some backup systems).
        See linkgit:git-update-index[1]. True by default.
  
 +core.untrackedCache::
 +      Determines what to do about the untracked cache feature of the
 +      index. It will be kept, if this variable is unset or set to
 +      `keep`. It will automatically be added if set to `true`. And
 +      it will automatically be removed, if set to `false`. Before
 +      setting it to `true`, you should check that mtime is working
 +      properly on your system.
 +      See linkgit:git-update-index[1]. `keep` by default.
 +
  core.checkStat::
        Determines which stat fields to match between the index
        and work tree. The user can set this to 'default' or
@@@ -618,23 -609,6 +618,23 @@@ core.attributesFile:
        $XDG_CONFIG_HOME/git/attributes. If $XDG_CONFIG_HOME is either not
        set or empty, $HOME/.config/git/attributes is used instead.
  
 +core.hooksPath::
 +      By default Git will look for your hooks in the
 +      '$GIT_DIR/hooks' directory. Set this to different path,
 +      e.g. '/etc/git/hooks', and Git will try to find your hooks in
 +      that directory, e.g. '/etc/git/hooks/pre-receive' instead of
 +      in '$GIT_DIR/hooks/pre-receive'.
 ++
 +The path can be either absolute or relative. A relative path is
 +taken as relative to the directory where the hooks are run (see
 +the "DESCRIPTION" section of linkgit:githooks[5]).
 ++
 +This configuration variable is useful in cases where you'd like to
 +centrally configure your Git hooks instead of configuring them on a
 +per-repository basis, or as a more flexible and centralized
 +alternative to having an `init.templateDir` where you've changed
 +default hooks.
 +
  core.editor::
        Commands such as `commit` and `tag` that lets you edit
        messages by launching an editor uses the value of this
@@@ -896,8 -870,6 +896,8 @@@ When preserve, also pass `--preserve-me
  so that locally committed merge commits will not be flattened
  by running 'git pull'.
  +
 +When the value is `interactive`, the rebase is run in interactive mode.
 ++
  *NOTE*: this is a possibly dangerous operation; do *not* use
  it unless you understand the implications (see linkgit:git-rebase[1]
  for details).
@@@ -1130,9 -1102,8 +1130,9 @@@ commit.template:
  credential.helper::
        Specify an external helper to be called when a username or
        password credential is needed; the helper may consult external
 -      storage to avoid prompting the user for the credentials. See
 -      linkgit:gitcredentials[7] for details.
 +      storage to avoid prompting the user for the credentials. Note
 +      that multiple helpers may be defined. See linkgit:gitcredentials[7]
 +      for details.
  
  credential.useHttpPath::
        When acquiring credentials, consider the "path" component of an http
@@@ -1151,9 -1122,6 +1151,9 @@@ credential.<url>.*:
        example.com. See linkgit:gitcredentials[7] for details on how URLs are
        matched.
  
 +credentialCache.ignoreSIGHUP::
 +      Tell git-credential-cache--daemon to ignore SIGHUP, instead of quitting.
 +
  include::diff-config.txt[]
  
  difftool.<tool>.path::
@@@ -1272,10 -1240,6 +1272,10 @@@ format.coverLetter:
        format-patch is invoked, but in addition can be set to "auto", to
        generate a cover-letter only when there's more than one patch.
  
 +format.outputDirectory::
 +      Set a custom directory to store the resulting files instead of the
 +      current working directory.
 +
  filter.<driver>.clean::
        The command which is used to convert the content of a worktree
        file to a blob upon checkin.  See linkgit:gitattributes[5] for
@@@ -1483,14 -1447,6 +1483,14 @@@ grep.extendedRegexp:
        option is ignored when the 'grep.patternType' option is set to a value
        other than 'default'.
  
 +grep.threads::
 +      Number of grep worker threads to use.
 +      See `grep.threads` in linkgit:git-grep[1] for more information.
 +
 +grep.fallbackToNoIndex::
 +      If set to true, fall back to git grep --no-index if git grep
 +      is executed outside of a git repository.  Defaults to false.
 +
  gpg.program::
        Use this custom program instead of "gpg" found on $PATH when
        making or verifying a PGP signature. The program must support the
@@@ -1637,53 -1593,17 +1637,54 @@@ help.htmlPath:
  
  http.proxy::
        Override the HTTP proxy, normally configured using the 'http_proxy',
 -      'https_proxy', and 'all_proxy' environment variables (see
 -      `curl(1)`).  This can be overridden on a per-remote basis; see
 -      remote.<name>.proxy
 +      'https_proxy', and 'all_proxy' environment variables (see `curl(1)`). In
 +      addition to the syntax understood by curl, it is possible to specify a
 +      proxy string with a user name but no password, in which case git will
 +      attempt to acquire one in the same way it does for other credentials. See
 +      linkgit:gitcredentials[7] for more information. The syntax thus is
 +      '[protocol://][user[:password]@]proxyhost[:port]'. This can be overridden
 +      on a per-remote basis; see remote.<name>.proxy
 +
 +http.proxyAuthMethod::
 +      Set the method with which to authenticate against the HTTP proxy. This
 +      only takes effect if the configured proxy string contains a user name part
 +      (i.e. is of the form 'user@host' or 'user@host:port'). This can be
 +      overridden on a per-remote basis; see `remote.<name>.proxyAuthMethod`.
 +      Both can be overridden by the 'GIT_HTTP_PROXY_AUTHMETHOD' environment
 +      variable.  Possible values are:
 ++
 +--
 +* `anyauth` - Automatically pick a suitable authentication method. It is
 +  assumed that the proxy answers an unauthenticated request with a 407
 +  status code and one or more Proxy-authenticate headers with supported
 +  authentication methods. This is the default.
 +* `basic` - HTTP Basic authentication
 +* `digest` - HTTP Digest authentication; this prevents the password from being
 +  transmitted to the proxy in clear text
 +* `negotiate` - GSS-Negotiate authentication (compare the --negotiate option
 +  of `curl(1)`)
 +* `ntlm` - NTLM authentication (compare the --ntlm option of `curl(1)`)
 +--
 +
 +http.emptyAuth::
 +      Attempt authentication without seeking a username or password.  This
 +      can be used to attempt GSS-Negotiate authentication without specifying
 +      a username in the URL, as libcurl normally requires a username for
 +      authentication.
 +
 +http.extraHeader::
 +      Pass an additional HTTP header when communicating with a server.  If
 +      more than one such entry exists, all of them are added as extra
 +      headers.  To allow overriding the settings inherited from the system
 +      config, an empty value will reset the extra headers to the empty list.
  
  http.cookieFile::
-       File containing previously stored cookie lines which should be used
+       The pathname of a file containing previously stored cookie lines,
+       which should be used
        in the Git http session, if they match the server. The file format
        of the file to read cookies from should be plain HTTP headers or
        the Netscape/Mozilla cookie file format (see linkgit:curl[1]).
-       NOTE that the file specified with http.cookieFile is only used as
+       NOTE that the file specified with http.cookieFile is used only as
        input unless http.saveCookies is set.
  
  http.saveCookies::
@@@ -1757,14 -1677,6 +1758,14 @@@ http.sslCAPath:
        with when fetching or pushing over HTTPS. Can be overridden
        by the 'GIT_SSL_CAPATH' environment variable.
  
 +http.pinnedpubkey::
 +      Public key of the https service. It may either be the filename of
 +      a PEM or DER encoded public key file or a string starting with
 +      'sha256//' followed by the base64 encoded sha256 hash of the
 +      public key. See also libcurl 'CURLOPT_PINNEDPUBLICKEY'. git will
 +      exit with an error if this option is set but not supported by
 +      cURL.
 +
  http.sslTry::
        Attempt to use AUTH SSL/TLS and encrypted data transfers
        when connecting via regular FTP protocol. This might be needed
@@@ -1910,14 -1822,6 +1911,14 @@@ interactive.singleKey:
        setting is silently ignored if portable keystroke input
        is not available; requires the Perl module Term::ReadKey.
  
 +interactive.diffFilter::
 +      When an interactive command (such as `git add --patch`) shows
 +      a colorized diff, git will pipe the diff through the shell
 +      command defined by this configuration variable. The command may
 +      mark up the diff further for human consumption, provided that it
 +      retains a one-to-one correspondence with the lines in the
 +      original diff. Defaults to disabled (no filtering).
 +
  log.abbrevCommit::
        If true, makes linkgit:git-log[1], linkgit:git-show[1], and
        linkgit:git-whatchanged[1] assume `--abbrev-commit`. You may
  log.date::
        Set the default date-time mode for the 'log' command.
        Setting a value for log.date is similar to using 'git log''s
 -      `--date` option.  Possible values are `relative`, `local`,
 -      `default`, `iso`, `rfc`, and `short`; see linkgit:git-log[1]
 -      for details.
 +      `--date` option.  See linkgit:git-log[1] for details.
  
  log.decorate::
        Print out the ref names of any commits that are shown by the log
@@@ -2168,7 -2074,7 +2169,7 @@@ pack.indexVersion:
        larger than 2 GB.
  +
  If you have an old Git that does not understand the version 2 `*.idx` file,
 -cloning or fetching over a non native protocol (e.g. "http" and "rsync")
 +cloning or fetching over a non native protocol (e.g. "http")
  that will copy both `*.pack` file and corresponding `*.idx` file from the
  other side may give you a repository that cannot be accessed with your
  older version of Git. If the `*.pack` file is smaller than 2 GB, however,
@@@ -2179,11 -2085,8 +2180,11 @@@ pack.packSizeLimit:
        The maximum size of a pack.  This setting only affects
        packing to a file when repacking, i.e. the git:// protocol
        is unaffected.  It can be overridden by the `--max-pack-size`
 -      option of linkgit:git-repack[1]. The minimum size allowed is
 -      limited to 1 MiB. The default is unlimited.
 +      option of linkgit:git-repack[1].  Reaching this limit results
 +      in the creation of multiple packfiles; which in turn prevents
 +      bitmaps from being created.
 +      The minimum size allowed is limited to 1 MiB.
 +      The default is unlimited.
        Common unit suffixes of 'k', 'm', or 'g' are
        supported.
  
@@@ -2246,8 -2149,6 +2247,8 @@@ When preserve, also pass `--preserve-me
  so that locally committed merge commits will not be flattened
  by running 'git pull'.
  +
 +When the value is `interactive`, the rebase is run in interactive mode.
 ++
  *NOTE*: this is a possibly dangerous operation; do *not* use
  it unless you understand the implications (see linkgit:git-rebase[1]
  for details).
@@@ -2328,20 -2229,6 +2329,20 @@@ push.gpgSign:
        override a value from a lower-priority config file. An explicit
        command-line flag always overrides this config option.
  
 +push.recurseSubmodules::
 +      Make sure all submodule commits used by the revisions to be pushed
 +      are available on a remote-tracking branch. If the value is 'check'
 +      then Git will verify that all submodule commits that changed in the
 +      revisions to be pushed are available on at least one remote of the
 +      submodule. If any commits are missing, the push will be aborted and
 +      exit with non-zero status. If the value is 'on-demand' then all
 +      submodules that changed in the revisions to be pushed will be
 +      pushed. If on-demand was not able to push all necessary revisions
 +      it will also be aborted and exit with non-zero status. If the value
 +      is 'no' then default behavior of ignoring submodules when pushing
 +      is retained. You may override this configuration at time of push by
 +      specifying '--recurse-submodules=check|on-demand|no'.
 +
  rebase.stat::
        Whether to show a diffstat of what changed upstream since the last
        rebase. False by default.
@@@ -2506,11 -2393,6 +2507,11 @@@ remote.<name>.proxy:
        the proxy to use for that remote.  Set to the empty string to
        disable proxying for that remote.
  
 +remote.<name>.proxyAuthMethod::
 +      For remotes that require curl (http, https and ftp), the method to use for
 +      authenticating against the proxy in use (probably set in
 +      `remote.<name>.proxy`). See `http.proxyAuthMethod`.
 +
  remote.<name>.fetch::
        The default set of "refspec" for linkgit:git-fetch[1]. See
        linkgit:git-fetch[1].
@@@ -2583,9 -2465,8 +2584,9 @@@ repack.writeBitmaps:
        objects to disk (e.g., when `git repack -a` is run).  This
        index can speed up the "counting objects" phase of subsequent
        packs created for clones and fetches, at the cost of some disk
 -      space and extra time spent on the initial repack.  Defaults to
 -      false.
 +      space and extra time spent on the initial repack.  This has
 +      no effect if multiple packfiles are created.
 +      Defaults to false.
  
  rerere.autoUpdate::
        When set to true, `git-rerere` updates the index with the
@@@ -2713,16 -2594,6 +2714,16 @@@ status.submoduleSummary:
        submodule summary' command, which shows a similar output but does
        not honor these settings.
  
 +stash.showPatch::
 +      If this is set to true, the `git stash show` command without an
 +      option will show the stash in patch form.  Defaults to false.
 +      See description of 'show' command in linkgit:git-stash[1].
 +
 +stash.showStat::
 +      If this is set to true, the `git stash show` command without an
 +      option will show diffstat of the stash.  Defaults to true.
 +      See description of 'show' command in linkgit:git-stash[1].
 +
  submodule.<name>.path::
  submodule.<name>.url::
        The path within this project and URL for a submodule. These
@@@ -2765,17 -2636,6 +2766,17 @@@ submodule.<name>.ignore:
        "--ignore-submodules" option. The 'git submodule' commands are not
        affected by this setting.
  
 +submodule.fetchJobs::
 +      Specifies how many submodules are fetched/cloned at the same time.
 +      A positive integer allows up to that number of submodules fetched
 +      in parallel. A value of 0 will give some reasonable default.
 +      If unset, it defaults to 1.
 +
 +tag.forceSignAnnotated::
 +      A boolean to specify whether annotated tags created should be GPG signed.
 +      If `--annotate` is specified on the command line, it takes
 +      precedence over this option.
 +
  tag.sort::
        This variable controls the sort ordering of tags when displayed by
        linkgit:git-tag[1]. Without the "--sort=<value>" option provided, the
@@@ -2806,15 -2666,6 +2807,15 @@@ You may also include a `!` in front of 
  explicitly exposing it, even if an earlier entry marked it as hidden.
  If you have multiple hideRefs values, later entries override earlier ones
  (and entries in more-specific config files override less-specific ones).
 ++
 +If a namespace is in use, the namespace prefix is stripped from each
 +reference before it is matched against `transfer.hiderefs` patterns.
 +For example, if `refs/heads/master` is specified in `transfer.hideRefs` and
 +the current namespace is `foo`, then `refs/namespaces/foo/refs/heads/master`
 +is omitted from the advertisements but `refs/heads/master` and
 +`refs/namespaces/bar/refs/heads/master` are still advertised as so-called
 +"have" lines. In order to match refs before stripping, add a `^` in front of
 +the ref name. If you combine `!` and `^`, `!` must be specified first.
  
  transfer.unpackLimit::
        When `fetch.unpackLimit` or `receive.unpackLimit` are
@@@ -2891,16 -2742,6 +2892,16 @@@ user.name:
        Can be overridden by the 'GIT_AUTHOR_NAME' and 'GIT_COMMITTER_NAME'
        environment variables.  See linkgit:git-commit-tree[1].
  
 +user.useConfigOnly::
 +      Instruct Git to avoid trying to guess defaults for 'user.email'
 +      and 'user.name', and instead retrieve the values only from the
 +      configuration. For example, if you have multiple email addresses
 +      and would like to use a different one for each repository, then
 +      with this configuration option set to `true` in the global config
 +      along with a name, Git will prompt you to set up an email before
 +      making new commits in a newly cloned repository.
 +      Defaults to `false`.
 +
  user.signingKey::
        If linkgit:git-tag[1] or linkgit:git-commit[1] is not selecting the
        key you want it to automatically when creating a signed tag or
diff --combined http.c
index 985b995c1d05b9a1ae461d6056e14e66b39d563c,1b4520c626d1ecf6794ac19663da2d31f0f3172e..6fe74d5eeafa0566cc7f19c8024ed0c82b55db77
--- 1/http.c
--- 2/http.c
+++ b/http.c
  #include "gettext.h"
  #include "transport.h"
  
 +#if LIBCURL_VERSION_NUM >= 0x070a08
 +long int git_curl_ipresolve = CURL_IPRESOLVE_WHATEVER;
 +#else
 +long int git_curl_ipresolve;
 +#endif
  int active_requests;
  int http_is_verbose;
  size_t http_post_buffer = 16 * LARGE_PACKET_MAX;
@@@ -35,6 -30,7 +35,6 @@@ static CURL *curl_default
  #endif
  
  #define PREV_BUF_SIZE 4096
 -#define RANGE_HEADER_SIZE 30
  
  char curl_errorstr[CURL_ERROR_SIZE];
  
@@@ -62,41 -58,16 +62,41 @@@ static const char *ssl_key
  #if LIBCURL_VERSION_NUM >= 0x070908
  static const char *ssl_capath;
  #endif
 +#if LIBCURL_VERSION_NUM >= 0x072c00
 +static const char *ssl_pinnedkey;
 +#endif
  static const char *ssl_cainfo;
  static long curl_low_speed_limit = -1;
  static long curl_low_speed_time = -1;
  static int curl_ftp_no_epsv;
  static const char *curl_http_proxy;
 +static const char *curl_no_proxy;
 +static const char *http_proxy_authmethod;
 +static struct {
 +      const char *name;
 +      long curlauth_param;
 +} proxy_authmethods[] = {
 +      { "basic", CURLAUTH_BASIC },
 +      { "digest", CURLAUTH_DIGEST },
 +      { "negotiate", CURLAUTH_GSSNEGOTIATE },
 +      { "ntlm", CURLAUTH_NTLM },
 +#ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
 +      { "anyauth", CURLAUTH_ANY },
 +#endif
 +      /*
 +       * CURLAUTH_DIGEST_IE has no corresponding command-line option in
 +       * curl(1) and is not included in CURLAUTH_ANY, so we leave it out
 +       * here, too
 +       */
 +};
 +static struct credential proxy_auth = CREDENTIAL_INIT;
 +static const char *curl_proxyuserpwd;
  static const char *curl_cookie_file;
  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;
  
  #if LIBCURL_VERSION_NUM >= 0x071700
  /* Use CURLOPT_KEYPASSWD as is */
@@@ -114,7 -85,6 +114,7 @@@ static unsigned long http_auth_methods 
  
  static struct curl_slist *pragma_header;
  static struct curl_slist *no_pragma_header;
 +static struct curl_slist *extra_http_headers;
  
  static struct active_request_slot *active_queue_head;
  
@@@ -190,9 -160,6 +190,9 @@@ static void finish_active_slot(struct a
  #else
                slot->results->auth_avail = 0;
  #endif
 +
 +              curl_easy_getinfo(slot->curl, CURLINFO_HTTP_CONNECTCODE,
 +                      &slot->results->http_connectcode);
        }
  
        /* Run callback if appropriate */
@@@ -290,11 -257,8 +290,11 @@@ static int http_options(const char *var
        if (!strcmp("http.proxy", var))
                return git_config_string(&curl_http_proxy, var, value);
  
 +      if (!strcmp("http.proxyauthmethod", var))
 +              return git_config_string(&http_proxy_authmethod, var, value);
 +
        if (!strcmp("http.cookiefile", var))
-               return git_config_string(&curl_cookie_file, var, value);
+               return git_config_pathname(&curl_cookie_file, var, value);
        if (!strcmp("http.savecookies", var)) {
                curl_save_cookies = git_config_bool(var, value);
                return 0;
        if (!strcmp("http.useragent", var))
                return git_config_string(&user_agent, var, value);
  
 +      if (!strcmp("http.emptyauth", var)) {
 +              curl_empty_auth = git_config_bool(var, value);
 +              return 0;
 +      }
 +
 +      if (!strcmp("http.pinnedpubkey", var)) {
 +#if LIBCURL_VERSION_NUM >= 0x072c00
 +              return git_config_pathname(&ssl_pinnedkey, var, value);
 +#else
 +              warning(_("Public key pinning not supported with cURL < 7.44.0"));
 +              return 0;
 +#endif
 +      }
 +
 +      if (!strcmp("http.extraheader", var)) {
 +              if (!value) {
 +                      return config_error_nonbool(var);
 +              } else if (!*value) {
 +                      curl_slist_free_all(extra_http_headers);
 +                      extra_http_headers = NULL;
 +              } else {
 +                      extra_http_headers =
 +                              curl_slist_append(extra_http_headers, value);
 +              }
 +              return 0;
 +      }
 +
        /* Fall back on the default ones */
        return git_default_config(var, value, cb);
  }
  
  static void init_curl_http_auth(CURL *result)
  {
 -      if (!http_auth.username)
 +      if (!http_auth.username) {
 +              if (curl_empty_auth)
 +                      curl_easy_setopt(result, CURLOPT_USERPWD, ":");
                return;
 +      }
  
        credential_fill(&http_auth);
  
  #endif
  }
  
 +/* *var must be free-able */
 +static void var_override(const char **var, char *value)
 +{
 +      if (value) {
 +              free((void *)*var);
 +              *var = xstrdup(value);
 +      }
 +}
 +
 +static void set_proxyauth_name_password(CURL *result)
 +{
 +#if LIBCURL_VERSION_NUM >= 0x071301
 +              curl_easy_setopt(result, CURLOPT_PROXYUSERNAME,
 +                      proxy_auth.username);
 +              curl_easy_setopt(result, CURLOPT_PROXYPASSWORD,
 +                      proxy_auth.password);
 +#else
 +              struct strbuf s = STRBUF_INIT;
 +
 +              strbuf_addstr_urlencode(&s, proxy_auth.username, 1);
 +              strbuf_addch(&s, ':');
 +              strbuf_addstr_urlencode(&s, proxy_auth.password, 1);
 +              curl_proxyuserpwd = strbuf_detach(&s, NULL);
 +              curl_easy_setopt(result, CURLOPT_PROXYUSERPWD, curl_proxyuserpwd);
 +#endif
 +}
 +
 +static void init_curl_proxy_auth(CURL *result)
 +{
 +      if (proxy_auth.username) {
 +              if (!proxy_auth.password)
 +                      credential_fill(&proxy_auth);
 +              set_proxyauth_name_password(result);
 +      }
 +
 +      var_override(&http_proxy_authmethod, getenv("GIT_HTTP_PROXY_AUTHMETHOD"));
 +
 +#if LIBCURL_VERSION_NUM >= 0x070a07 /* CURLOPT_PROXYAUTH and CURLAUTH_ANY */
 +      if (http_proxy_authmethod) {
 +              int i;
 +              for (i = 0; i < ARRAY_SIZE(proxy_authmethods); i++) {
 +                      if (!strcmp(http_proxy_authmethod, proxy_authmethods[i].name)) {
 +                              curl_easy_setopt(result, CURLOPT_PROXYAUTH,
 +                                              proxy_authmethods[i].curlauth_param);
 +                              break;
 +                      }
 +              }
 +              if (i == ARRAY_SIZE(proxy_authmethods)) {
 +                      warning("unsupported proxy authentication method %s: using anyauth",
 +                                      http_proxy_authmethod);
 +                      curl_easy_setopt(result, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
 +              }
 +      }
 +      else
 +              curl_easy_setopt(result, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
 +#endif
 +}
 +
  static int has_cert_password(void)
  {
        if (ssl_cert == NULL || ssl_cert_password_required != 1)
@@@ -539,10 -415,6 +539,10 @@@ static CURL *get_curl_handle(void
  #if LIBCURL_VERSION_NUM >= 0x070908
        if (ssl_capath != NULL)
                curl_easy_setopt(result, CURLOPT_CAPATH, ssl_capath);
 +#endif
 +#if LIBCURL_VERSION_NUM >= 0x072c00
 +      if (ssl_pinnedkey != NULL)
 +              curl_easy_setopt(result, CURLOPT_PINNEDPUBLICKEY, ssl_pinnedkey);
  #endif
        if (ssl_cainfo != NULL)
                curl_easy_setopt(result, CURLOPT_CAINFO, ssl_cainfo);
                curl_easy_setopt(result, CURLOPT_USE_SSL, CURLUSESSL_TRY);
  #endif
  
 +      /*
 +       * CURL also examines these variables as a fallback; but we need to query
 +       * them here in order to decide whether to prompt for missing password (cf.
 +       * init_curl_proxy_auth()).
 +       *
 +       * Unlike many other common environment variables, these are historically
 +       * lowercase only. It appears that CURL did not know this and implemented
 +       * only uppercase variants, which was later corrected to take both - with
 +       * the exception of http_proxy, which is lowercase only also in CURL. As
 +       * the lowercase versions are the historical quasi-standard, they take
 +       * precedence here, as in CURL.
 +       */
 +      if (!curl_http_proxy) {
 +              if (!strcmp(http_auth.protocol, "https")) {
 +                      var_override(&curl_http_proxy, getenv("HTTPS_PROXY"));
 +                      var_override(&curl_http_proxy, getenv("https_proxy"));
 +              } else {
 +                      var_override(&curl_http_proxy, getenv("http_proxy"));
 +              }
 +              if (!curl_http_proxy) {
 +                      var_override(&curl_http_proxy, getenv("ALL_PROXY"));
 +                      var_override(&curl_http_proxy, getenv("all_proxy"));
 +              }
 +      }
 +
        if (curl_http_proxy) {
                curl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);
  #if LIBCURL_VERSION_NUM >= 0x071800
 -              if (starts_with(curl_http_proxy, "socks5"))
 +              if (starts_with(curl_http_proxy, "socks5h"))
 +                      curl_easy_setopt(result,
 +                              CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5_HOSTNAME);
 +              else if (starts_with(curl_http_proxy, "socks5"))
                        curl_easy_setopt(result,
                                CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
                else if (starts_with(curl_http_proxy, "socks4a"))
                        curl_easy_setopt(result,
                                CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
  #endif
 -      }
 -#if LIBCURL_VERSION_NUM >= 0x070a07
 -      curl_easy_setopt(result, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
 +              if (strstr(curl_http_proxy, "://"))
 +                      credential_from_url(&proxy_auth, curl_http_proxy);
 +              else {
 +                      struct strbuf url = STRBUF_INIT;
 +                      strbuf_addf(&url, "http://%s", curl_http_proxy);
 +                      credential_from_url(&proxy_auth, url.buf);
 +                      strbuf_release(&url);
 +              }
 +
 +              curl_easy_setopt(result, CURLOPT_PROXY, proxy_auth.host);
 +#if LIBCURL_VERSION_NUM >= 0x071304
 +              var_override(&curl_no_proxy, getenv("NO_PROXY"));
 +              var_override(&curl_no_proxy, getenv("no_proxy"));
 +              curl_easy_setopt(result, CURLOPT_NOPROXY, curl_no_proxy);
  #endif
 +      }
 +      init_curl_proxy_auth(result);
  
        set_curl_keepalive(result);
  
@@@ -689,13 -520,8 +689,13 @@@ void http_init(struct remote *remote, c
        if (remote && remote->http_proxy)
                curl_http_proxy = xstrdup(remote->http_proxy);
  
 -      pragma_header = curl_slist_append(pragma_header, "Pragma: no-cache");
 -      no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
 +      if (remote)
 +              var_override(&http_proxy_authmethod, remote->http_proxy_authmethod);
 +
 +      pragma_header = curl_slist_append(http_copy_default_headers(),
 +              "Pragma: no-cache");
 +      no_pragma_header = curl_slist_append(http_copy_default_headers(),
 +              "Pragma:");
  
  #ifdef USE_CURL_MULTI
        {
@@@ -781,9 -607,6 +781,9 @@@ void http_cleanup(void
  #endif
        curl_global_cleanup();
  
 +      curl_slist_free_all(extra_http_headers);
 +      extra_http_headers = NULL;
 +
        curl_slist_free_all(pragma_header);
        pragma_header = NULL;
  
                curl_http_proxy = NULL;
        }
  
 +      if (proxy_auth.password) {
 +              memset(proxy_auth.password, 0, strlen(proxy_auth.password));
 +              free(proxy_auth.password);
 +              proxy_auth.password = NULL;
 +      }
 +
 +      free((void *)curl_proxyuserpwd);
 +      curl_proxyuserpwd = NULL;
 +
 +      free((void *)http_proxy_authmethod);
 +      http_proxy_authmethod = NULL;
 +
        if (cert_auth.password != NULL) {
                memset(cert_auth.password, 0, strlen(cert_auth.password));
                free(cert_auth.password);
@@@ -881,15 -692,10 +881,15 @@@ struct active_request_slot *get_active_
        curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 0);
        curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
        curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 1);
 +      curl_easy_setopt(slot->curl, CURLOPT_RANGE, NULL);
 +
 +#if LIBCURL_VERSION_NUM >= 0x070a08
 +      curl_easy_setopt(slot->curl, CURLOPT_IPRESOLVE, git_curl_ipresolve);
 +#endif
  #ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
        curl_easy_setopt(slot->curl, CURLOPT_HTTPAUTH, http_auth_methods);
  #endif
 -      if (http_auth.password)
 +      if (http_auth.password || curl_empty_auth)
                init_curl_http_auth(slot->curl);
  
        return slot;
@@@ -1140,8 -946,6 +1140,8 @@@ static int handle_curl_result(struct sl
  
        if (results->curl_result == CURLE_OK) {
                credential_approve(&http_auth);
 +              if (proxy_auth.password)
 +                      credential_approve(&proxy_auth);
                return HTTP_OK;
        } else if (missing_target(results))
                return HTTP_MISSING_TARGET;
                        return HTTP_REAUTH;
                }
        } else {
 +              if (results->http_connectcode == 407)
 +                      credential_reject(&proxy_auth);
  #if LIBCURL_VERSION_NUM >= 0x070c00
                if (!curl_errorstr[0])
                        strlcpy(curl_errorstr,
@@@ -1182,16 -984,6 +1182,16 @@@ int run_one_slot(struct active_request_
        return handle_curl_result(results);
  }
  
 +struct curl_slist *http_copy_default_headers(void)
 +{
 +      struct curl_slist *headers = NULL, *h;
 +
 +      for (h = extra_http_headers; h; h = h->next)
 +              headers = curl_slist_append(headers, h->data);
 +
 +      return headers;
 +}
 +
  static CURLcode curlinfo_strbuf(CURL *curl, CURLINFO info, struct strbuf *buf)
  {
        char *ptr;
@@@ -1341,7 -1133,7 +1341,7 @@@ static void write_accept_language(struc
                     decimal_places++, max_q *= 10)
                        ;
  
 -              sprintf(q_format, ";q=0.%%0%dd", decimal_places);
 +              xsnprintf(q_format, sizeof(q_format), ";q=0.%%0%dd", decimal_places);
  
                strbuf_addstr(buf, "Accept-Language: ");
  
@@@ -1392,13 -1184,6 +1392,13 @@@ static const char *get_accept_language(
        return cached_accept_language;
  }
  
 +static void http_opt_request_remainder(CURL *curl, off_t pos)
 +{
 +      char buf[128];
 +      xsnprintf(buf, sizeof(buf), "%"PRIuMAX"-", (uintmax_t)pos);
 +      curl_easy_setopt(curl, CURLOPT_RANGE, buf);
 +}
 +
  /* http_request() targets */
  #define HTTP_REQUEST_STRBUF   0
  #define HTTP_REQUEST_FILE     1
@@@ -1409,7 -1194,7 +1409,7 @@@ static int http_request(const char *url
  {
        struct active_request_slot *slot;
        struct slot_results results;
 -      struct curl_slist *headers = NULL;
 +      struct curl_slist *headers = http_copy_default_headers();
        struct strbuf buf = STRBUF_INIT;
        const char *accept_language;
        int ret;
                curl_easy_setopt(slot->curl, CURLOPT_FILE, result);
  
                if (target == HTTP_REQUEST_FILE) {
 -                      long posn = ftell(result);
 +                      off_t posn = ftello(result);
                        curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION,
                                         fwrite);
 -                      if (posn > 0) {
 -                              strbuf_addf(&buf, "Range: bytes=%ld-", posn);
 -                              headers = curl_slist_append(headers, buf.buf);
 -                              strbuf_reset(&buf);
 -                      }
 +                      if (posn > 0)
 +                              http_opt_request_remainder(slot->curl, posn);
                } else
                        curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION,
                                         fwrite_buffer);
@@@ -1610,7 -1398,7 +1610,7 @@@ int http_fetch_ref(const char *base, st
        if (http_get_strbuf(url, &buffer, &options) == HTTP_OK) {
                strbuf_rtrim(&buffer);
                if (buffer.len == 40)
 -                      ret = get_sha1_hex(buffer.buf, ref->old_sha1);
 +                      ret = get_oid_hex(buffer.buf, &ref->old_oid);
                else if (starts_with(buffer.buf, "ref: ")) {
                        ref->symref = xstrdup(buffer.buf + 5);
                        ret = 0;
@@@ -1738,6 -1526,10 +1738,6 @@@ void release_http_pack_request(struct h
                fclose(preq->packfile);
                preq->packfile = NULL;
        }
 -      if (preq->range_header != NULL) {
 -              curl_slist_free_all(preq->range_header);
 -              preq->range_header = NULL;
 -      }
        preq->slot = NULL;
        free(preq->url);
        free(preq);
@@@ -1748,7 -1540,6 +1748,7 @@@ int finish_http_pack_request(struct htt
        struct packed_git **lst;
        struct packed_git *p = preq->target;
        char *tmp_idx;
 +      size_t len;
        struct child_process ip = CHILD_PROCESS_INIT;
        const char *ip_argv[8];
  
                lst = &((*lst)->next);
        *lst = (*lst)->next;
  
 -      tmp_idx = xstrdup(preq->tmpfile);
 -      strcpy(tmp_idx + strlen(tmp_idx) - strlen(".pack.temp"),
 -             ".idx.temp");
 +      if (!strip_suffix(preq->tmpfile, ".pack.temp", &len))
 +              die("BUG: pack tmpfile does not end in .pack.temp?");
 +      tmp_idx = xstrfmt("%.*s.idx.temp", (int)len, preq->tmpfile);
  
        ip_argv[0] = "index-pack";
        ip_argv[1] = "-o";
  struct http_pack_request *new_http_pack_request(
        struct packed_git *target, const char *base_url)
  {
 -      long prev_posn = 0;
 -      char range[RANGE_HEADER_SIZE];
 +      off_t prev_posn = 0;
        struct strbuf buf = STRBUF_INIT;
        struct http_pack_request *preq;
  
         * If there is data present from a previous transfer attempt,
         * resume where it left off
         */
 -      prev_posn = ftell(preq->packfile);
 +      prev_posn = ftello(preq->packfile);
        if (prev_posn>0) {
                if (http_is_verbose)
                        fprintf(stderr,
 -                              "Resuming fetch of pack %s at byte %ld\n",
 -                              sha1_to_hex(target->sha1), prev_posn);
 -              sprintf(range, "Range: bytes=%ld-", prev_posn);
 -              preq->range_header = curl_slist_append(NULL, range);
 -              curl_easy_setopt(preq->slot->curl, CURLOPT_HTTPHEADER,
 -                      preq->range_header);
 +                              "Resuming fetch of pack %s at byte %"PRIuMAX"\n",
 +                              sha1_to_hex(target->sha1), (uintmax_t)prev_posn);
 +              http_opt_request_remainder(preq->slot->curl, prev_posn);
        }
  
        return preq;
@@@ -1887,7 -1682,9 +1887,7 @@@ struct http_object_request *new_http_ob
        int prevlocal;
        char prev_buf[PREV_BUF_SIZE];
        ssize_t prev_read = 0;
 -      long prev_posn = 0;
 -      char range[RANGE_HEADER_SIZE];
 -      struct curl_slist *range_header = NULL;
 +      off_t prev_posn = 0;
        struct http_object_request *freq;
  
        freq = xcalloc(1, sizeof(*freq));
        if (prev_posn>0) {
                if (http_is_verbose)
                        fprintf(stderr,
 -                              "Resuming fetch of object %s at byte %ld\n",
 -                              hex, prev_posn);
 -              sprintf(range, "Range: bytes=%ld-", prev_posn);
 -              range_header = curl_slist_append(range_header, range);
 -              curl_easy_setopt(freq->slot->curl,
 -                               CURLOPT_HTTPHEADER, range_header);
 +                              "Resuming fetch of object %s at byte %"PRIuMAX"\n",
 +                              hex, (uintmax_t)prev_posn);
 +              http_opt_request_remainder(freq->slot->curl, prev_posn);
        }
  
        return freq;