From: Junio C Hamano Date: Tue, 31 May 2016 21:08:28 +0000 (-0700) Subject: Merge branch 'bn/http-cookiefile-config' into maint X-Git-Tag: v2.9.0-rc1~1^2~2 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/e646a82ce2828d6e8e3a18fe02dd9b3d31478f00?hp=-c Merge branch 'bn/http-cookiefile-config' into maint "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 --- e646a82ce2828d6e8e3a18fe02dd9b3d31478f00 diff --combined Documentation/config.txt index d3a6de81d3,3c0c48478e..b945d67bc0 --- a/Documentation/config.txt +++ b/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 ~~~~~~~ @@@ -117,7 -114,7 +117,7 @@@ [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 is logged to the file - "$GIT_DIR/logs/", by appending the new and old + "`$GIT_DIR/logs/`", 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/" + variable is set to true, missing "`$GIT_DIR/logs/`" 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..*: 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..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..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..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..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..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..proxy: the proxy to use for that remote. Set to the empty string to disable proxying for that remote. +remote..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..proxy`). See `http.proxyAuthMethod`. + remote..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..path:: submodule..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 index 4304b80ad3,1b4520c626..1044f9ba0e --- a/http.c +++ b/http.c @@@ -11,11 -11,6 +11,11 @@@ #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; @@@ -309,31 -274,14 +309,31 @@@ 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); @@@ -357,64 -305,6 +357,64 @@@ #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); @@@ -577,38 -463,10 +577,38 @@@ 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")) @@@ -618,23 -476,10 +618,23 @@@ 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; @@@ -1137,8 -960,6 +1137,8 @@@ 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]; @@@ -1733,9 -1553,9 +1733,9 @@@ 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"; @@@ -1771,7 -1591,8 +1771,7 @@@ 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; @@@ -1803,13 -1624,16 +1803,13 @@@ * 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)); @@@ -1962,9 -1788,12 +1962,9 @@@ 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;