Merge branch 'bn/http-cookiefile-config' into maint
authorJunio C Hamano <gitster@pobox.com>
Tue, 31 May 2016 21:08:28 +0000 (14:08 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 31 May 2016 21:08:28 +0000 (14:08 -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
@@@ -81,16 -81,13 +81,16 @@@ Include
  
  You can include one config file from another by setting the special
  `include.path` variable to the name of the file to be included. The
 +variable takes a pathname as its value, and is subject to tilde
 +expansion.
 +
 +The
  included file is expanded immediately, as if its contents had been
  found at the location of the include directive. If the value of the
  `include.path` variable is a relative path, the path is considered to be
  relative to the configuration file in which the include directive was
 -found. The value of `include.path` is subject to tilde expansion: `~/`
 -is expanded to the value of `$HOME`, and `~user/` to the specified
 -user's home directory. See below for examples.
 +found.  See below for examples.
 +
  
  Example
  ~~~~~~~
        [include]
                path = /path/to/foo.inc ; include by absolute path
                path = foo ; expand "foo" relative to the current file
 -              path = ~/foo ; expand "foo" in your $HOME directory
 +              path = ~/foo ; expand "foo" in your `$HOME` directory
  
  
  Values
@@@ -172,13 -169,6 +172,13 @@@ thing on the same output line (e.g. ope
  list of branch names in `log --decorate` output) is set to be
  painted with `bold` or some other attribute.
  
 +pathname::
 +      A variable that takes a pathname value can be given a
 +      string that begins with "`~/`" or "`~user/`", and the usual
 +      tilde expansion happens to such a string: `~/`
 +      is expanded to the value of `$HOME`, and `~user/` to the
 +      specified user's home directory.
 +
  
  Variables
  ~~~~~~~~~
@@@ -279,12 -269,6 +279,12 @@@ See linkgit:git-update-index[1]
  +
  The default is true (when core.filemode is not specified in the config file).
  
 +core.hideDotFiles::
 +      (Windows-only) If true, mark newly-created directories and files whose
 +      name starts with a dot as hidden.  If 'dotGitOnly', only the `.git/`
 +      directory is hidden, but no other files starting with a dot.  The
 +      default mode is 'dotGitOnly'.
 +
  core.ignoreCase::
        If true, this option enables various workarounds to enable
        Git to work better on filesystems that are not case sensitive,
@@@ -324,15 -308,6 +324,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
@@@ -502,10 -477,10 +502,10 @@@ repository's usual working tree)
  
  core.logAllRefUpdates::
        Enable the reflog. Updates to a ref <ref> is logged to the file
 -      "$GIT_DIR/logs/<ref>", by appending the new and old
 +      "`$GIT_DIR/logs/<ref>`", by appending the new and old
        SHA-1, the date/time and the reason of the update, but
        only when the file exists.  If this configuration
 -      variable is set to true, missing "$GIT_DIR/logs/<ref>"
 +      variable is set to true, missing "`$GIT_DIR/logs/<ref>`"
        file is automatically created for branch heads (i.e. under
        refs/heads/), remote refs (i.e. under refs/remotes/),
        note refs (i.e. under refs/notes/), and the symbolic ref HEAD.
@@@ -609,11 -584,12 +609,11 @@@ be delta compressed, but larger binary 
  Common unit suffixes of 'k', 'm', or 'g' are supported.
  
  core.excludesFile::
 -      In addition to '.gitignore' (per-directory) and
 -      '.git/info/exclude', Git looks into this file for patterns
 -      of files which are not meant to be tracked.  "`~/`" is expanded
 -      to the value of `$HOME` and "`~user/`" to the specified user's
 -      home directory. Its default value is $XDG_CONFIG_HOME/git/ignore.
 -      If $XDG_CONFIG_HOME is either not set or empty, $HOME/.config/git/ignore
 +      Specifies the pathname to the file that contains patterns to
 +      describe paths that are not meant to be tracked, in addition
 +      to '.gitignore' (per-directory) and '.git/info/exclude'.
 +      Defaults to `$XDG_CONFIG_HOME/git/ignore`.
 +      If `$XDG_CONFIG_HOME` is either not set or empty, `$HOME/.config/git/ignore`
        is used instead. See linkgit:gitignore[5].
  
  core.askPass::
@@@ -630,8 -606,8 +630,8 @@@ core.attributesFile:
        '.git/info/attributes', Git looks into this file for attributes
        (see linkgit:gitattributes[5]). Path expansions are made the same
        way as for `core.excludesFile`. Its default value is
 -      $XDG_CONFIG_HOME/git/attributes. If $XDG_CONFIG_HOME is either not
 -      set or empty, $HOME/.config/git/attributes is used instead.
 +      `$XDG_CONFIG_HOME/git/attributes`. If `$XDG_CONFIG_HOME` is either not
 +      set or empty, `$HOME/.config/git/attributes` is used instead.
  
  core.editor::
        Commands such as `commit` and `tag` that lets you edit
@@@ -894,8 -870,6 +894,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).
@@@ -1121,8 -1095,9 +1121,8 @@@ commit.status:
        message.  Defaults to true.
  
  commit.template::
 -      Specify a file to use as the template for new commit messages.
 -      "`~/`" is expanded to the value of `$HOME` and "`~user/`" to the
 -      specified user's home directory.
 +      Specify the pathname of a file to use as the template for
 +      new commit messages.
  
  credential.helper::
        Specify an external helper to be called when a username or
@@@ -1147,9 -1122,6 +1147,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::
@@@ -1268,10 -1240,6 +1268,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
@@@ -1348,7 -1316,7 +1348,7 @@@ gc.worktreePruneExpire:
        'git worktree prune --expire 3.months.ago'.
        This config variable can be used to set a different grace
        period. The value "now" may be used to disable the grace
 -      period and prune $GIT_DIR/worktrees immediately, or "never"
 +      period and prune `$GIT_DIR/worktrees` immediately, or "never"
        may be used to suppress pruning.
  
  gc.reflogExpire::
@@@ -1479,22 -1447,14 +1479,22 @@@ 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
 +      Use this custom program instead of "`gpg`" found on `$PATH` when
        making or verifying a PGP signature. The program must support the
        same command-line interface as GPG, namely, to verify a detached
 -      signature, "gpg --verify $file - <$signature" is run, and the
 +      signature, "`gpg --verify $file - <$signature`" is run, and the
        program is expected to signal a good signature by exiting with
        code 0, and to generate an ASCII-armored detached signature, the
 -      standard input of "gpg -bsau $key" is fed with the contents to be
 +      standard input of "`gpg -bsau $key`" is fed with the contents to be
        signed, and the program is expected to send the result to its
        standard output.
  
@@@ -1507,7 -1467,7 +1507,7 @@@ gui.diffContext:
        made by the linkgit:git-gui[1]. The default is "5".
  
  gui.displayUntracked::
 -      Determines if linkgit::git-gui[1] shows untracked files
 +      Determines if linkgit:git-gui[1] shows untracked files
        in the file list. The default is "true".
  
  gui.encoding::
@@@ -1633,47 -1593,17 +1633,48 @@@ 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.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]).
 +      the Netscape/Mozilla cookie file format (see `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::
@@@ -1747,14 -1677,6 +1748,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
@@@ -1908,7 -1830,9 +1909,7 @@@ log.abbrevCommit:
  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
@@@ -2150,7 -2074,7 +2151,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,
@@@ -2161,11 -2085,8 +2162,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.
  
@@@ -2228,8 -2149,6 +2229,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).
@@@ -2310,20 -2229,6 +2311,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.
@@@ -2488,11 -2393,6 +2489,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].
@@@ -2565,9 -2465,8 +2566,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
@@@ -2695,16 -2594,6 +2696,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
@@@ -2777,15 -2666,6 +2778,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
@@@ -2862,16 -2742,6 +2863,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
--- 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 */
@@@ -189,9 -160,6 +189,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 */
@@@ -289,11 -257,8 +289,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
 +      }
 +
        /* 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)
@@@ -525,10 -415,6 +525,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);
  
@@@ -675,9 -520,6 +675,9 @@@ void http_init(struct remote *remote, c
        if (remote && remote->http_proxy)
                curl_http_proxy = xstrdup(remote->http_proxy);
  
 +      if (remote)
 +              var_override(&http_proxy_authmethod, remote->http_proxy_authmethod);
 +
        pragma_header = curl_slist_append(pragma_header, "Pragma: no-cache");
        no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
  
@@@ -776,18 -618,6 +776,18 @@@ void http_cleanup(void
                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);
@@@ -862,15 -692,10 +862,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;
@@@ -1121,8 -946,6 +1121,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,
@@@ -1312,7 -1133,7 +1312,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: ");
  
@@@ -1363,13 -1184,6 +1363,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
@@@ -1395,11 -1209,14 +1395,11 @@@ static int http_request(const char *url
                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);
@@@ -1581,7 -1398,7 +1581,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;
@@@ -1709,6 -1526,10 +1709,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);
@@@ -1719,7 -1540,6 +1719,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;
@@@ -1858,7 -1682,9 +1858,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;