Merge branch 'nd/exclusion-regression-fix'
authorJunio C Hamano <gitster@pobox.com>
Wed, 24 Feb 2016 21:25:59 +0000 (13:25 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 24 Feb 2016 21:25:59 +0000 (13:25 -0800)
Another try to add support to the ignore mechanism that lets you
say "this is excluded" and then later say "oh, no, this part (that
is a subset of the previous part) is not excluded".

* nd/exclusion-regression-fix:
dir.c: don't exclude whole dir prematurely
dir.c: support marking some patterns already matched
dir.c: support tracing exclude
dir.c: fix match_pathname()

102 files changed:
.gitignore
Documentation/RelNotes/2.7.2.txt [new file with mode: 0644]
Documentation/RelNotes/2.8.0.txt
Documentation/config.txt
Documentation/fetch-options.txt
Documentation/git-bundle.txt
Documentation/git-clean.txt
Documentation/git-clone.txt
Documentation/git-config.txt
Documentation/git-push.txt
Documentation/git-repack.txt
Documentation/git.txt
Documentation/gitcore-tutorial.txt
Documentation/gittutorial.txt
Documentation/revisions.txt
Documentation/urls.txt
Makefile
builtin/apply.c
builtin/check-attr.c
builtin/check-ignore.c
builtin/checkout-index.c
builtin/checkout.c
builtin/clone.c
builtin/fetch.c
builtin/hash-object.c
builtin/ls-files.c
builtin/pack-objects.c
builtin/push.c
builtin/rev-list.c
builtin/rev-parse.c
builtin/stripspace.c
builtin/update-index.c
compat/mingw.c
config.mak.uname
connect.c
connect.h
contrib/completion/git-completion.bash
convert.c
git-cvsserver.perl
git.c
http-push.c
http.c
http.h
ident.c
list-objects.c
list-objects.h
mergetools/vimdiff
pack-bitmap-write.c
pack-bitmap.c
perl/Git.pm
perl/Git/SVN/Editor.pm
reachable.c
remote-curl.c
remote.c
rerere.c
revision.c
revision.h
setup.c
sha1_name.c
t/Makefile
t/lib-git-daemon.sh
t/lib-git-svn.sh
t/t0008-ignores.sh
t/t0021-conversion.sh
t/t0060-path-utils.sh
t/t1508-at-combinations.sh
t/t1511-rev-parse-caret.sh
t/t2019-checkout-ambiguous-ref.sh
t/t2027-worktree-list.sh
t/t3300-funny-names.sh
t/t3600-rm.sh
t/t3703-add-magic-pathspec.sh
t/t3902-quoted.sh
t/t4016-diff-quote.sh
t/t4135-apply-weird-filenames.sh
t/t5505-remote.sh
t/t5510-fetch.sh
t/t5533-push-cas.sh
t/t5570-git-daemon.sh
t/t5601-clone.sh
t/t6133-pathspec-rev-dwim.sh [new file with mode: 0755]
t/t7517-per-repo-email.sh [new file with mode: 0755]
t/t7800-difftool.sh
t/t9003-help-autocorrect.sh [new file with mode: 0755]
t/t9100-git-svn-basic.sh
t/t9115-git-svn-dcommit-funky-renames.sh
t/t9118-git-svn-funky-branch-names.sh
t/t9124-git-svn-dcommit-auto-props.sh
t/t9129-git-svn-i18n-commitencoding.sh
t/t9130-git-svn-authors-file.sh
t/t9200-git-cvsexportcommit.sh
t/t9400-git-cvsserver-server.sh
t/t9401-git-cvsserver-crlf.sh
t/t9402-git-cvsserver-refs.sh
t/t9700/test.pl
t/t9903-bash-prompt.sh
t/test-lib.sh
test-fake-ssh.c [new file with mode: 0644]
test-path-utils.c
transport-helper.c
transport.c
transport.h
index 1c2f8321386f89ef8c03d11159c97a0f194c4423..5087ce1eb7e2210e7fc25a9a14ac3f499ad5ac2f 100644 (file)
 /test-dump-cache-tree
 /test-dump-split-index
 /test-dump-untracked-cache
+/test-fake-ssh
 /test-scrap-cache-tree
 /test-genrandom
 /test-hashmap
diff --git a/Documentation/RelNotes/2.7.2.txt b/Documentation/RelNotes/2.7.2.txt
new file mode 100644 (file)
index 0000000..4feef76
--- /dev/null
@@ -0,0 +1,41 @@
+Git v2.7.2 Release Notes
+========================
+
+Fixes since v2.7.1
+------------------
+
+ * The low-level merge machinery has been taught to use CRLF line
+   termination when inserting conflict markers to merged contents that
+   are themselves CRLF line-terminated.
+
+ * "git worktree" had a broken code that attempted to auto-fix
+   possible inconsistency that results from end-users moving a
+   worktree to different places without telling Git (the original
+   repository needs to maintain backpointers to its worktrees, but
+   "mv" run by end-users who are not familiar with that fact will
+   obviously not adjust them), which actually made things worse
+   when triggered.
+
+ * "git push --force-with-lease" has been taught to report if the push
+   needed to force (or fast-forwarded).
+
+ * The emulated "yes" command used in our test scripts has been
+   tweaked not to spend too much time generating unnecessary output
+   that is not used, to help those who test on Windows where it would
+   not stop until it fills the pipe buffer due to lack of SIGPIPE.
+
+ * The vimdiff backend for "git mergetool" has been tweaked to arrange
+   and number buffers in the order that would match the expectation of
+   majority of people who read left to right, then top down and assign
+   buffers 1 2 3 4 "mentally" to local base remote merge windows based
+   on that order.
+
+ * The documentation for "git clean" has been corrected; it mentioned
+   that .git/modules/* are removed by giving two "-f", which has never
+   been the case.
+
+ * Paths that have been told the index about with "add -N" are not
+   quite yet in the index, but a few commands behaved as if they
+   already are in a harmful way.
+
+Also includes tiny documentation and test updates.
index 166e06ccd47fdee71f8dadf7a717e61212393950..dd540d032738eb372ef4c774b4e767f2c09da6ad 100644 (file)
@@ -1,11 +1,21 @@
 Git 2.8 Release Notes
 =====================
 
+Backward compatibility note
+---------------------------
+
+The rsync:// transport has been removed.
+
+
 Updates since v2.7
 ------------------
 
 UI, Workflows & Features
 
+ * It turns out "git clone" over rsync transport has been broken when
+   the source repository has packed references for a long time, and
+   nobody noticed nor complained about it.
+
  * "branch --delete" has "branch -d" but "push --delete" does not.
 
  * "git blame" learned to produce the progress eye-candy when it takes
@@ -67,6 +77,27 @@ UI, Workflows & Features
    has been taught to use credential API to store the authentication
    material in user's keyrings.
 
+ * Update the untracked cache subsystem and change its primary UI from
+   "git update-index" to "git config".
+
+ * There were a few "now I am doing this thing" progress messages in
+   the TCP connection code that can be triggered by setting a verbose
+   option internally in the code, but "git fetch -v" and friends never
+   passed the verbose option down to that codepath.
+
+ * Clean/smudge filters defined in a configuration file of lower
+   precedence can now be overridden to be a pass-through no-op by
+   setting the variable to an empty string.
+
+ * A new "<branch>^{/!-<pattern>}" notation can be used to name a
+   commit that is reachable from <branch> that does not match the
+   given <pattern>.
+
+ * The "user.useConfigOnly" configuration variable can be used to
+   force the user to always set user.email & user.name configuration
+   variables, serving as a reminder for those who work on multiple
+   projects and do not want to put these in their $HOME/.gitconfig.
+
 
 Performance, Internal Implementation, Development Support etc.
 
@@ -110,6 +141,21 @@ Performance, Internal Implementation, Development Support etc.
    tests that take longer before other ones; this reduces the total
    wallclock time.
 
+ * Test scripts have been updated to remove assumptions that are not
+   portable between Git for POSIX and Git for Windows, or to skip ones
+   with expectations that are not satisfiable on Git for Windows.
+
+ * Some calls to strcpy(3) triggers a false warning from static
+   analysers that are less intelligent than humans, and reducing the
+   number of these false hits helps us notice real issues.  A few
+   calls to strcpy(3) in test-path-utils that are already safe has
+   been rewritten to avoid false wanings.
+
+ * Some calls to strcpy(3) triggers a false warning from static
+   analysers that are less intelligent than humans, and reducing the
+   number of these false hits helps us notice real issues.  A few
+   calls to strcpy(3) in "git rerere" that are already safe has been
+   rewritten to avoid false wanings.
 
 Also contains various documentation updates and code clean-ups.
 
@@ -227,9 +273,46 @@ notes for details).
    CPU cycles.
    (merge a2d5156 jk/ref-cache-non-repository-optim later to maint).
 
+ * "git worktree" had a broken code that attempted to auto-fix
+   possible inconsistency that results from end-users moving a
+   worktree to different places without telling Git (the original
+   repository needs to maintain backpointers to its worktrees, but
+   "mv" run by end-users who are not familiar with that fact will
+   obviously not adjust them), which actually made things worse
+   when triggered.
+   (merge 618244e nd/do-not-move-worktree-manually later to maint).
+
+ * The low-level merge machinery has been taught to use CRLF line
+   termination when inserting conflict markers to merged contents that
+   are themselves CRLF line-terminated.
+   (merge 15980de js/xmerge-marker-eol later to maint).
+
+ * "git push --force-with-lease" has been taught to report if the push
+   needed to force (or fast-forwarded).
+   (merge b2e93f8 aw/push-force-with-lease-reporting later to maint).
+
+ * The emulated "yes" command used in our test scripts has been
+   tweaked not to spend too much time generating unnecessary output
+   that is not used, to help those who test on Windows where it would
+   not stop until it fills the pipe buffer due to lack of SIGPIPE.
+   (merge 6129c93 js/test-lib-windows-emulated-yes later to maint).
+
+ * The documentation for "git clean" has been corrected; it mentioned
+   that .git/modules/* are removed by giving two "-f", which has never
+   been the case.
+   (merge 31e3c2d mm/clean-doc-fix later to maint).
+
+ * The vimdiff backend for "git mergetool" has been tweaked to arrange
+   and number buffers in the order that would match the expectation of
+   majority of people who read left to right, then top down and assign
+   buffers 1 2 3 4 "mentally" to local base remote merge windows based
+   on that order.
+   (merge 2300328 dw/mergetool-vim-window-shuffle later to maint).
+
  * Other minor clean-ups and documentation updates
    (merge 99487cf ss/user-manual later to maint).
    (merge e914ef0 ew/for-each-ref-doc later to maint).
    (merge 36fc7d8 sg/t6050-failing-editor-test-fix later to maint).
    (merge 60253a6 ss/clone-depth-single-doc later to maint).
    (merge bd02e97 lv/add-doc-working-tree later to maint).
+   (merge f562d7d ah/stripspace-optstring later to maint).
index 27f02be35ed2aebedab93281814b1f4e0fea4f35..2cd6bdd7d2bc2816c1a9aed1c6a26bbd3285777c 100644 (file)
@@ -1648,6 +1648,12 @@ http.proxyAuthMethod::
 * `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
        in the Git http session, if they match the server. The file format
@@ -1727,6 +1733,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
@@ -2122,7 +2136,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,
@@ -2830,6 +2844,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
index 952dfdfef098ca00b7976ef9d549401f171514f6..036edfb099c367262f34d2c1275ac5079a1e0914 100644 (file)
@@ -158,3 +158,11 @@ endif::git-pull[]
        by default when it is attached to a terminal, unless -q
        is specified. This flag forces progress status even if the
        standard error stream is not directed to a terminal.
+
+-4::
+--ipv4::
+       Use IPv4 addresses only, ignoring IPv6 addresses.
+
+-6::
+--ipv6::
+       Use IPv6 addresses only, ignoring IPv4 addresses.
index 0417562eb736f8a3b919bfa4deeb372164451bab..3a8120c3b3795784cb05211bcde959a224f0a867 100644 (file)
@@ -20,7 +20,7 @@ DESCRIPTION
 Some workflows require that one or more branches of development on one
 machine be replicated on another machine, but the two machines cannot
 be directly connected, and therefore the interactive Git protocols (git,
-ssh, rsync, http) cannot be used.  This command provides support for
+ssh, http) cannot be used.  This command provides support for
 'git fetch' and 'git pull' to operate by packaging objects and references
 in an archive at the originating machine, then importing those into
 another repository using 'git fetch' and 'git pull'
index 641681f61ad360fcfd5aa98f81a9e3d49c44c8a7..51a7e26a8ec178e7e9fd0b78c00bb7ce518cd049 100644 (file)
@@ -37,9 +37,7 @@ OPTIONS
        to false, 'git clean' will refuse to delete files or directories
        unless given -f, -n or -i. Git will refuse to delete directories
        with .git sub directory or file unless a second -f
-       is given. This affects also git submodules where the storage area
-       of the removed submodule under .git/modules/ is not removed until
-       -f is given twice.
+       is given.
 
 -i::
 --interactive::
index 789b668f7732957d71f42f98d361abd0b34305a7..b7c467a001ad47de0bebd8c985df769fe4e63adc 100644 (file)
@@ -115,8 +115,7 @@ objects from the source repository into a pack in the cloned repository.
 --quiet::
 -q::
        Operate quietly.  Progress is not reported to the standard
-       error stream. This flag is also passed to the `rsync'
-       command when given.
+       error stream.
 
 --verbose::
 -v::
index 2608ca74ac82f7e18531dc0d49a81c84e3155a5c..242fa5d1bb2b7eff9645e140613640d94d28852f 100644 (file)
@@ -219,7 +219,9 @@ See also <<FILES>>.
 
 --[no-]includes::
        Respect `include.*` directives in config files when looking up
-       values. Defaults to on.
+       values. Defaults to `off` when a specific file is given (e.g.,
+       using `--file`, `--global`, etc) and `on` when searching all
+       config files.
 
 [[FILES]]
 FILES
index 32482cec42d3ea5661813097919ff38657c2e01c..669a357c81fbba17c245adc3660cdd07479e564e 100644 (file)
@@ -277,6 +277,13 @@ origin +master` to force a push to the `master` branch). See the
        default is --verify, giving the hook a chance to prevent the
        push.  With --no-verify, the hook is bypassed completely.
 
+-4::
+--ipv4::
+       Use IPv4 addresses only, ignoring IPv6 addresses.
+
+-6::
+--ipv6::
+       Use IPv6 addresses only, ignoring IPv4 addresses.
 
 include::urls-remotes.txt[]
 
index 0e0bd363d6773bd2652287e12aff62bcf6ea09f4..af230d06475eedf99ee4a27eab5f1cc204f71aa1 100644 (file)
@@ -133,7 +133,7 @@ By default, the command passes `--delta-base-offset` option to
 'git pack-objects'; this typically results in slightly smaller packs,
 but the generated packs are incompatible with versions of Git older than
 version 1.4.4. If you need to share your repository with such ancient Git
-versions, either directly or via the dumb http or rsync protocol, then you
+versions, either directly or via the dumb http protocol, then you
 need to set the configuration variable `repack.UseDeltaBaseOffset` to
 "false" and repack. Access from old Git versions over the native protocol
 is unaffected by this option as the conversion is performed on the fly
index 2c4f0f247065966e26bd1971db66ed74aacfa54b..2754af8f7782d4a13fce4f5752737e3106491f22 100644 (file)
@@ -43,9 +43,10 @@ unreleased) version of Git, that is available from the 'master'
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
-* link:v2.7.1/git.html[documentation for release 2.7.1]
+* link:v2.7.2/git.html[documentation for release 2.7.2]
 
 * release notes for
+  link:RelNotes/2.7.2.txt[2.7.2],
   link:RelNotes/2.7.1.txt[2.7.1],
   link:RelNotes/2.7.0.txt[2.7].
 
@@ -1129,8 +1130,6 @@ of clones and fetches.
          - `ssh`: git over ssh (including `host:path` syntax,
            `git+ssh://`, etc).
 
-         - `rsync`: git over rsync
-
          - `http`: git over http, both "smart http" and "dumb http".
            Note that this does _not_ include `https`; if you want both,
            you should specify both as `http:https`.
index 36e9ab3e16860be21e6bcdc6e2f7c6ff44aa4757..15b3bfa8db143948629405a2ea9a72b7a83b31d5 100644 (file)
@@ -710,7 +710,7 @@ files).
 Again, this can all be simplified with
 
 ----------------
-$ git clone rsync://rsync.kernel.org/pub/scm/git/git.git/ my-git
+$ git clone git://git.kernel.org/pub/scm/git/git.git/ my-git
 $ cd my-git
 $ git checkout
 ----------------
@@ -1011,20 +1011,6 @@ $ git fetch <remote-repository>
 One of the following transports can be used to name the
 repository to download from:
 
-Rsync::
-       `rsync://remote.machine/path/to/repo.git/`
-+
-Rsync transport is usable for both uploading and downloading,
-but is completely unaware of what git does, and can produce
-unexpected results when you download from the public repository
-while the repository owner is uploading into it via `rsync`
-transport.  Most notably, it could update the files under
-`refs/` which holds the object name of the topmost commits
-before uploading the files in `objects/` -- the downloader would
-obtain head commit object name while that object itself is still
-not available in the repository.  For this reason, it is
-considered deprecated.
-
 SSH::
        `remote.machine:/path/to/repo.git/` or
 +
@@ -1430,7 +1416,7 @@ while, depending on how active your project is.
 
 When a repository is synchronized via `git push` and `git pull`
 objects packed in the source repository are usually stored
-unpacked in the destination, unless rsync transport is used.
+unpacked in the destination.
 While this allows you to use different packing strategies on
 both ends, it also means you may need to repack both
 repositories every once in a while.
index b00c67df46dad4efe93dddc7ead0a7422aa47c32..b3b58d324e4b7c254c54531bbab979064f3ced4a 100644 (file)
@@ -451,7 +451,7 @@ perform clones and pulls using the ssh protocol:
 bob$ git clone alice.org:/home/alice/project myrepo
 -------------------------------------
 
-Alternatively, Git has a native protocol, or can use rsync or http;
+Alternatively, Git has a native protocol, or can use http;
 see linkgit:git-pull[1] for details.
 
 Git can also be used in a CVS-like mode, with a central repository
index fa4bdb208cd86c603e1d7e430e753d5fe4768a13..19314e3b7f3eb7616be5ab88580020206285f880 100644 (file)
@@ -176,11 +176,12 @@ existing tag object.
   A colon, followed by a slash, followed by a text, names
   a commit whose commit message matches the specified regular expression.
   This name returns the youngest matching commit which is
-  reachable from any ref.  If the commit message starts with a
-  '!' you have to repeat that;  the special sequence ':/!',
-  followed by something else than '!', is reserved for now.
-  The regular expression can match any part of the commit message. To
-  match messages starting with a string, one can use e.g. ':/^foo'.
+  reachable from any ref. The regular expression can match any part of the
+  commit message. To match messages starting with a string, one can use
+  e.g. ':/^foo'. The special sequence ':/!' is reserved for modifiers to what
+  is matched. ':/!-foo' performs a negative match, while ':/!!foo' matches a
+  literal '!' character, followed by 'foo'. Any other sequence beginning with
+  ':/!' is reserved for now.
 
 '<rev>:<path>', e.g. 'HEAD:README', ':README', 'master:./README'::
   A suffix ':' followed by a path names the blob or tree
index 9ccb24677e95b8aff605c9020bc7a0537e23f751..b05da95788f7b1294be6b2733ca55b58111b7607 100644 (file)
@@ -7,9 +7,8 @@ Depending on the transport protocol, some of this information may be
 absent.
 
 Git supports ssh, git, http, and https protocols (in addition, ftp,
-and ftps can be used for fetching and rsync can be used for fetching
-and pushing, but these are inefficient and deprecated; do not use
-them).
+and ftps can be used for fetching, but this is inefficient and
+deprecated; do not use it).
 
 The native transport (i.e. git:// URL) does no authentication and
 should be used with caution on unsecured networks.
@@ -20,7 +19,6 @@ The following syntaxes may be used with them:
 - git://host.xz{startsb}:port{endsb}/path/to/repo.git/
 - http{startsb}s{endsb}://host.xz{startsb}:port{endsb}/path/to/repo.git/
 - ftp{startsb}s{endsb}://host.xz{startsb}:port{endsb}/path/to/repo.git/
-- rsync://host.xz/path/to/repo.git/
 
 An alternative scp-like syntax may also be used with the ssh protocol:
 
index fc2f1ab2c31820513758514cd445fc63521b1d19..10566d648175fc561fde6a1498996e2bb43b880d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -583,6 +583,7 @@ TEST_PROGRAMS_NEED_X += test-delta
 TEST_PROGRAMS_NEED_X += test-dump-cache-tree
 TEST_PROGRAMS_NEED_X += test-dump-split-index
 TEST_PROGRAMS_NEED_X += test-dump-untracked-cache
+TEST_PROGRAMS_NEED_X += test-fake-ssh
 TEST_PROGRAMS_NEED_X += test-genrandom
 TEST_PROGRAMS_NEED_X += test-hashmap
 TEST_PROGRAMS_NEED_X += test-index-version
index deb1364fa81452d236a224109a99b28a034f9a9a..d61ac65dab28a766a13782bdef572431e20e80ff 100644 (file)
@@ -4464,16 +4464,6 @@ static int option_parse_p(const struct option *opt,
        return 0;
 }
 
-static int option_parse_z(const struct option *opt,
-                         const char *arg, int unset)
-{
-       if (unset)
-               line_termination = '\n';
-       else
-               line_termination = 0;
-       return 0;
-}
-
 static int option_parse_space_change(const struct option *opt,
                          const char *arg, int unset)
 {
@@ -4546,9 +4536,9 @@ int cmd_apply(int argc, const char **argv, const char *prefix_)
                         N_( "attempt three-way merge if a patch does not apply")),
                OPT_FILENAME(0, "build-fake-ancestor", &fake_ancestor,
                        N_("build a temporary index based on embedded index information")),
-               { OPTION_CALLBACK, 'z', NULL, NULL, NULL,
-                       N_("paths are separated with NUL character"),
-                       PARSE_OPT_NOARG, option_parse_z },
+               /* Think twice before adding "--nul" synonym to this */
+               OPT_SET_INT('z', NULL, &line_termination,
+                       N_("paths are separated with NUL character"), '\0'),
                OPT_INTEGER('C', NULL, &p_context,
                                N_("ensure at least <n> lines of context match")),
                { OPTION_CALLBACK, 0, "whitespace", &whitespace_option, N_("action"),
index 087325ef6954e4a2364d194f8d7ac27fedb7fc67..53a5a18c1681f5f13f6ddd4fd4d7d30c0ea14ce6 100644 (file)
@@ -72,24 +72,23 @@ static void check_attr(const char *prefix, int cnt,
 static void check_attr_stdin_paths(const char *prefix, int cnt,
        struct git_attr_check *check)
 {
-       struct strbuf buf, nbuf;
+       struct strbuf buf = STRBUF_INIT;
+       struct strbuf unquoted = STRBUF_INIT;
        strbuf_getline_fn getline_fn;
 
        getline_fn = nul_term_line ? strbuf_getline_nul : strbuf_getline_lf;
-       strbuf_init(&buf, 0);
-       strbuf_init(&nbuf, 0);
        while (getline_fn(&buf, stdin) != EOF) {
                if (!nul_term_line && buf.buf[0] == '"') {
-                       strbuf_reset(&nbuf);
-                       if (unquote_c_style(&nbuf, buf.buf, NULL))
+                       strbuf_reset(&unquoted);
+                       if (unquote_c_style(&unquoted, buf.buf, NULL))
                                die("line is badly quoted");
-                       strbuf_swap(&buf, &nbuf);
+                       strbuf_swap(&buf, &unquoted);
                }
                check_attr(prefix, cnt, check, buf.buf);
                maybe_flush_or_die(stdout, "attribute to stdout");
        }
        strbuf_release(&buf);
-       strbuf_release(&nbuf);
+       strbuf_release(&unquoted);
 }
 
 static NORETURN void error_with_usage(const char *msg)
index 4f0b09e2db5c0e0bc4665b06dc543b7f8ea1d467..1d73d3ca3d0509d71b927d685f3239cdab3cc885 100644 (file)
@@ -115,20 +115,19 @@ static int check_ignore(struct dir_struct *dir,
 
 static int check_ignore_stdin_paths(struct dir_struct *dir, const char *prefix)
 {
-       struct strbuf buf, nbuf;
+       struct strbuf buf = STRBUF_INIT;
+       struct strbuf unquoted = STRBUF_INIT;
        char *pathspec[2] = { NULL, NULL };
        strbuf_getline_fn getline_fn;
        int num_ignored = 0;
 
        getline_fn = nul_term_line ? strbuf_getline_nul : strbuf_getline_lf;
-       strbuf_init(&buf, 0);
-       strbuf_init(&nbuf, 0);
        while (getline_fn(&buf, stdin) != EOF) {
                if (!nul_term_line && buf.buf[0] == '"') {
-                       strbuf_reset(&nbuf);
-                       if (unquote_c_style(&nbuf, buf.buf, NULL))
+                       strbuf_reset(&unquoted);
+                       if (unquote_c_style(&unquoted, buf.buf, NULL))
                                die("line is badly quoted");
-                       strbuf_swap(&buf, &nbuf);
+                       strbuf_swap(&buf, &unquoted);
                }
                pathspec[0] = buf.buf;
                num_ignored += check_ignore(dir, prefix,
@@ -136,7 +135,7 @@ static int check_ignore_stdin_paths(struct dir_struct *dir, const char *prefix)
                maybe_flush_or_die(stdout, "check-ignore to stdout");
        }
        strbuf_release(&buf);
-       strbuf_release(&nbuf);
+       strbuf_release(&unquoted);
        return num_ignored;
 }
 
index ed888a5b9e8a2978369c404ab050b237ab5c7b4d..92c69672e96f6e7fc6bbe7b783c551474224f18b 100644 (file)
@@ -130,33 +130,6 @@ static const char * const builtin_checkout_index_usage[] = {
 
 static struct lock_file lock_file;
 
-static int option_parse_u(const struct option *opt,
-                             const char *arg, int unset)
-{
-       int *newfd = opt->value;
-
-       state.refresh_cache = 1;
-       state.istate = &the_index;
-       if (*newfd < 0)
-               *newfd = hold_locked_index(&lock_file, 1);
-       return 0;
-}
-
-static int option_parse_z(const struct option *opt,
-                         const char *arg, int unset)
-{
-       nul_term_line = !unset;
-       return 0;
-}
-
-static int option_parse_prefix(const struct option *opt,
-                              const char *arg, int unset)
-{
-       state.base_dir = arg;
-       state.base_dir_len = strlen(arg);
-       return 0;
-}
-
 static int option_parse_stage(const struct option *opt,
                              const char *arg, int unset)
 {
@@ -168,7 +141,7 @@ static int option_parse_stage(const struct option *opt,
                if ('1' <= ch && ch <= '3')
                        checkout_stage = arg[0] - '0';
                else
-                       die("stage should be between 1 and 3 or all");
+                       die(_("stage should be between 1 and 3 or all"));
        }
        return 0;
 }
@@ -181,6 +154,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
        int read_from_stdin = 0;
        int prefix_length;
        int force = 0, quiet = 0, not_new = 0;
+       int index_opt = 0;
        struct option builtin_checkout_index_options[] = {
                OPT_BOOL('a', "all", &all,
                        N_("check out all files in the index")),
@@ -189,22 +163,19 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
                        N_("no warning for existing files and files not in index")),
                OPT_BOOL('n', "no-create", &not_new,
                        N_("don't checkout new files")),
-               { OPTION_CALLBACK, 'u', "index", &newfd, NULL,
-                       N_("update stat information in the index file"),
-                       PARSE_OPT_NOARG, option_parse_u },
-               { OPTION_CALLBACK, 'z', NULL, NULL, NULL,
-                       N_("paths are separated with NUL character"),
-                       PARSE_OPT_NOARG, option_parse_z },
+               OPT_BOOL('u', "index", &index_opt,
+                        N_("update stat information in the index file")),
+               OPT_BOOL('z', NULL, &nul_term_line,
+                       N_("paths are separated with NUL character")),
                OPT_BOOL(0, "stdin", &read_from_stdin,
                        N_("read list of paths from the standard input")),
                OPT_BOOL(0, "temp", &to_tempfile,
                        N_("write the content to temporary files")),
-               OPT_CALLBACK(0, "prefix", NULL, N_("string"),
-                       N_("when creating files, prepend <string>"),
-                       option_parse_prefix),
-               OPT_CALLBACK(0, "stage", NULL, NULL,
+               OPT_STRING(0, "prefix", &state.base_dir, N_("string"),
+                       N_("when creating files, prepend <string>")),
+               { OPTION_CALLBACK, 0, "stage", NULL, "1-3|all",
                        N_("copy out the files from named stage"),
-                       option_parse_stage),
+                       PARSE_OPT_NONEG, option_parse_stage },
                OPT_END()
        };
 
@@ -212,7 +183,6 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
                usage_with_options(builtin_checkout_index_usage,
                                   builtin_checkout_index_options);
        git_config(git_default_config, NULL);
-       state.base_dir = "";
        prefix_length = prefix ? strlen(prefix) : 0;
 
        if (read_cache() < 0) {
@@ -225,15 +195,17 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
        state.quiet = quiet;
        state.not_new = not_new;
 
-       if (state.base_dir_len || to_tempfile) {
-               /* when --prefix is specified we do not
-                * want to update cache.
-                */
-               if (state.refresh_cache) {
-                       rollback_lock_file(&lock_file);
-                       newfd = -1;
-               }
-               state.refresh_cache = 0;
+       if (!state.base_dir)
+               state.base_dir = "";
+       state.base_dir_len = strlen(state.base_dir);
+
+       /*
+        * when --prefix is specified we do not want to update cache.
+        */
+       if (index_opt && !state.base_dir_len && !to_tempfile) {
+               state.refresh_cache = 1;
+               state.istate = &the_index;
+               newfd = hold_locked_index(&lock_file, 1);
        }
 
        /* Check out named files first */
@@ -251,7 +223,8 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
        }
 
        if (read_from_stdin) {
-               struct strbuf buf = STRBUF_INIT, nbuf = STRBUF_INIT;
+               struct strbuf buf = STRBUF_INIT;
+               struct strbuf unquoted = STRBUF_INIT;
                strbuf_getline_fn getline_fn;
 
                if (all)
@@ -261,16 +234,16 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
                while (getline_fn(&buf, stdin) != EOF) {
                        char *p;
                        if (!nul_term_line && buf.buf[0] == '"') {
-                               strbuf_reset(&nbuf);
-                               if (unquote_c_style(&nbuf, buf.buf, NULL))
+                               strbuf_reset(&unquoted);
+                               if (unquote_c_style(&unquoted, buf.buf, NULL))
                                        die("line is badly quoted");
-                               strbuf_swap(&buf, &nbuf);
+                               strbuf_swap(&buf, &unquoted);
                        }
                        p = prefix_path(prefix, prefix_length, buf.buf);
                        checkout_file(p, prefix);
                        free(p);
                }
-               strbuf_release(&nbuf);
+               strbuf_release(&unquoted);
                strbuf_release(&buf);
        }
 
index 5af84a3118d20da437d3e08c1667f76dc2f57845..cfa66e25eb0838ba70d87d3008c6d3c57e363bd1 100644 (file)
@@ -982,7 +982,8 @@ static int parse_branchname_arg(int argc, const char **argv,
                 */
                int recover_with_dwim = dwim_new_local_branch_ok;
 
-               if (check_filename(NULL, arg) && !has_dash_dash)
+               if (!has_dash_dash &&
+                   (check_filename(NULL, arg) || !no_wildcard(arg)))
                        recover_with_dwim = 0;
                /*
                 * Accept "git checkout foo" and "git checkout foo --"
index bcba0805e1c9c5691c2e876f9748a2cf492b1c70..b8c39aa701d6fd53f5bbb121ef9b9f0e77ca9d6d 100644 (file)
@@ -47,6 +47,7 @@ static const char *real_git_dir;
 static char *option_upload_pack = "git-upload-pack";
 static int option_verbosity;
 static int option_progress = -1;
+static enum transport_family family;
 static struct string_list option_config;
 static struct string_list option_reference;
 static int option_dissociate;
@@ -92,6 +93,10 @@ static struct option builtin_clone_options[] = {
                   N_("separate git dir from working tree")),
        OPT_STRING_LIST('c', "config", &option_config, N_("key=value"),
                        N_("set config inside the new repository")),
+       OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"),
+                       TRANSPORT_FAMILY_IPV4),
+       OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"),
+                       TRANSPORT_FAMILY_IPV6),
        OPT_END()
 };
 
@@ -970,6 +975,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
        remote = remote_get(option_origin);
        transport = transport_get(remote, remote->url[0]);
        transport_set_verbosity(transport, option_verbosity, option_progress);
+       transport->family = family;
 
        path = get_repo_path(remote->url[0], &is_bundle);
        is_local = option_local != 0 && path && !is_bundle;
index 8e742135f049c2792bfc5a20299dac88518929cc..55919a9e4fb8e2fd538b6c111bfdacf83acf62ed 100644 (file)
@@ -38,6 +38,7 @@ static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosit
 static int progress = -1, recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
 static int tags = TAGS_DEFAULT, unshallow, update_shallow;
 static int max_children = 1;
+static enum transport_family family;
 static const char *depth;
 static const char *upload_pack;
 static struct strbuf default_rla = STRBUF_INIT;
@@ -127,6 +128,10 @@ static struct option builtin_fetch_options[] = {
                 N_("accept refs that update .git/shallow")),
        { OPTION_CALLBACK, 0, "refmap", NULL, N_("refmap"),
          N_("specify fetch refmap"), PARSE_OPT_NONEG, parse_refmap_arg },
+       OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"),
+                       TRANSPORT_FAMILY_IPV4),
+       OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"),
+                       TRANSPORT_FAMILY_IPV6),
        OPT_END()
 };
 
@@ -864,6 +869,7 @@ static struct transport *prepare_transport(struct remote *remote)
        struct transport *transport;
        transport = transport_get(remote, NULL);
        transport_set_verbosity(transport, verbosity, progress);
+       transport->family = family;
        if (upload_pack)
                set_option(transport, TRANS_OPT_UPLOADPACK, upload_pack);
        if (keep)
index ff20395c69780cb5869300af83084d6cac1bbd4d..f7d3567dd0ce2d75778d6cf011961c0f203432b4 100644 (file)
@@ -58,20 +58,21 @@ static void hash_object(const char *path, const char *type, const char *vpath,
 static void hash_stdin_paths(const char *type, int no_filters, unsigned flags,
                             int literally)
 {
-       struct strbuf buf = STRBUF_INIT, nbuf = STRBUF_INIT;
+       struct strbuf buf = STRBUF_INIT;
+       struct strbuf unquoted = STRBUF_INIT;
 
        while (strbuf_getline(&buf, stdin) != EOF) {
                if (buf.buf[0] == '"') {
-                       strbuf_reset(&nbuf);
-                       if (unquote_c_style(&nbuf, buf.buf, NULL))
+                       strbuf_reset(&unquoted);
+                       if (unquote_c_style(&unquoted, buf.buf, NULL))
                                die("line is badly quoted");
-                       strbuf_swap(&buf, &nbuf);
+                       strbuf_swap(&buf, &unquoted);
                }
                hash_object(buf.buf, type, no_filters ? NULL : buf.buf, flags,
                            literally);
        }
        strbuf_release(&buf);
-       strbuf_release(&nbuf);
+       strbuf_release(&unquoted);
 }
 
 int cmd_hash_object(int argc, const char **argv, const char *prefix)
index dedf02dc702d1cc94399f45869e5d01d2f0eecb9..f02e3d23bb71a39dfd9f6eddf40aa84da896b650 100644 (file)
@@ -379,14 +379,6 @@ static const char * const ls_files_usage[] = {
        NULL
 };
 
-static int option_parse_z(const struct option *opt,
-                         const char *arg, int unset)
-{
-       line_terminator = unset ? '\n' : '\0';
-
-       return 0;
-}
-
 static int option_parse_exclude(const struct option *opt,
                                const char *arg, int unset)
 {
@@ -428,9 +420,9 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
        struct exclude_list *el;
        struct string_list exclude_list = STRING_LIST_INIT_NODUP;
        struct option builtin_ls_files_options[] = {
-               { OPTION_CALLBACK, 'z', NULL, NULL, NULL,
-                       N_("paths are separated with NUL character"),
-                       PARSE_OPT_NOARG, option_parse_z },
+               /* Think twice before adding "--nul" synonym to this */
+               OPT_SET_INT('z', NULL, &line_terminator,
+                       N_("paths are separated with NUL character"), '\0'),
                OPT_BOOL('t', NULL, &show_tag,
                        N_("identify the file status with tags")),
                OPT_BOOL('v', NULL, &show_valid_bit,
index 4dae5b11c28deb3c296cbd89753cafe3ca7a1e90..a6609f19ffa2c5320eee3e2994eda1d13e922729 100644 (file)
@@ -2284,21 +2284,11 @@ static void show_commit(struct commit *commit, void *data)
                index_commit_for_bitmap(commit);
 }
 
-static void show_object(struct object *obj,
-                       const struct name_path *path, const char *last,
-                       void *data)
+static void show_object(struct object *obj, const char *name, void *data)
 {
-       char *name = path_name(path, last);
-
        add_preferred_base_object(name);
        add_object_entry(obj->oid.hash, obj->type, name, 0);
        obj->flags |= OBJECT_ADDED;
-
-       /*
-        * We will have generated the hash from the name,
-        * but not saved a pointer to it - we can free it
-        */
-       free((char *)name);
 }
 
 static void show_edge(struct commit *commit)
@@ -2480,8 +2470,7 @@ static int get_object_list_from_bitmap(struct rev_info *revs)
 }
 
 static void record_recent_object(struct object *obj,
-                                const struct name_path *path,
-                                const char *last,
+                                const char *name,
                                 void *data)
 {
        sha1_array_append(&recent_objects, obj->oid.hash);
index 960ffc31e1537441a1120dceb120ce584b7edccf..6e13b3c90a08ade04aa7f84b2f3a3c869c0288bd 100644 (file)
@@ -23,6 +23,7 @@ static const char *receivepack;
 static int verbosity;
 static int progress = -1;
 static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
+static enum transport_family family;
 
 static struct push_cas_option cas;
 
@@ -346,6 +347,7 @@ static int push_with_options(struct transport *transport, int flags)
        unsigned int reject_reasons;
 
        transport_set_verbosity(transport, verbosity, progress);
+       transport->family = family;
 
        if (receivepack)
                transport_set_option(transport,
@@ -565,6 +567,10 @@ int cmd_push(int argc, const char **argv, const char *prefix)
                  0, "signed", &push_cert, "yes|no|if-asked", N_("GPG sign the push"),
                  PARSE_OPT_OPTARG, option_parse_push_signed },
                OPT_BIT(0, "atomic", &flags, N_("request atomic transaction on remote side"), TRANSPORT_PUSH_ATOMIC),
+               OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"),
+                               TRANSPORT_FAMILY_IPV4),
+               OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"),
+                               TRANSPORT_FAMILY_IPV6),
                OPT_END()
        };
 
index 3aa89a1a3cd951afdb97cf1fe371404fc96bca8d..275da0d647ebe147386c69683cc75f2d06105d23 100644 (file)
@@ -177,9 +177,7 @@ static void finish_commit(struct commit *commit, void *data)
        free_commit_buffer(commit);
 }
 
-static void finish_object(struct object *obj,
-                         const struct name_path *path, const char *name,
-                         void *cb_data)
+static void finish_object(struct object *obj, const char *name, void *cb_data)
 {
        struct rev_list_info *info = cb_data;
        if (obj->type == OBJ_BLOB && !has_object_file(&obj->oid))
@@ -188,15 +186,13 @@ static void finish_object(struct object *obj,
                parse_object(obj->oid.hash);
 }
 
-static void show_object(struct object *obj,
-                       const struct name_path *path, const char *component,
-                       void *cb_data)
+static void show_object(struct object *obj, const char *name, void *cb_data)
 {
        struct rev_list_info *info = cb_data;
-       finish_object(obj, path, component, cb_data);
+       finish_object(obj, name, cb_data);
        if (info->flags & REV_LIST_QUIET)
                return;
-       show_object_with_name(stdout, obj, path, component);
+       show_object_with_name(stdout, obj, name);
 }
 
 static void show_edge(struct commit *commit)
index bd16876df5ff7bce4fbf348d84a0ebc4ea53e7d7..cf8487b3b95fcca9a8a96a1562646ee8ddd5b354 100644 (file)
@@ -763,7 +763,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
                                continue;
                        }
                        if (!strcmp(arg, "--git-common-dir")) {
-                               puts(get_git_common_dir());
+                               const char *pfx = prefix ? prefix : "";
+                               puts(prefix_filename(pfx, strlen(pfx), get_git_common_dir()));
                                continue;
                        }
                        if (!strcmp(arg, "--resolve-git-dir")) {
index 7ff8434f7c3cf71dbd77cbf868d5dc56dd943fdb..15e716ef4322bb53428685c349aa489ed84a6dda 100644 (file)
@@ -35,7 +35,7 @@ int cmd_stripspace(int argc, const char **argv, const char *prefix)
                            N_("skip and remove all lines starting with comment character"),
                            STRIP_COMMENTS),
                OPT_CMDMODE('c', "comment-lines", &mode,
-                           N_("prepend comment character and blank to each line"),
+                           N_("prepend comment character and space to each line"),
                            COMMENT_LINES),
                OPT_END()
        };
index dbc23a46b13bee7ff532232c0e1d821c565fd2fb..1c94ca59bfcd756c94d86ef46592528e8fbfdcb1 100644 (file)
@@ -1086,16 +1086,17 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
        }
 
        if (read_from_stdin) {
-               struct strbuf buf = STRBUF_INIT, nbuf = STRBUF_INIT;
+               struct strbuf buf = STRBUF_INIT;
+               struct strbuf unquoted = STRBUF_INIT;
 
                setup_work_tree();
                while (getline_fn(&buf, stdin) != EOF) {
                        char *p;
                        if (!nul_term_line && buf.buf[0] == '"') {
-                               strbuf_reset(&nbuf);
-                               if (unquote_c_style(&nbuf, buf.buf, NULL))
+                               strbuf_reset(&unquoted);
+                               if (unquote_c_style(&unquoted, buf.buf, NULL))
                                        die("line is badly quoted");
-                               strbuf_swap(&buf, &nbuf);
+                               strbuf_swap(&buf, &unquoted);
                        }
                        p = prefix_path(prefix, prefix_length, buf.buf);
                        update_one(p);
@@ -1103,7 +1104,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
                                chmod_path(set_executable_bit, p);
                        free(p);
                }
-               strbuf_release(&nbuf);
+               strbuf_release(&unquoted);
                strbuf_release(&buf);
        }
 
index 77a51d3f72ebf8a3fa53b72e93b26f4e60c710b8..fbe69b874b06259e1d699572ace7dd8d2c4667c6 100644 (file)
@@ -454,6 +454,39 @@ static inline time_t filetime_to_time_t(const FILETIME *ft)
        return (time_t)(filetime_to_hnsec(ft) / 10000000);
 }
 
+/**
+ * Verifies that safe_create_leading_directories() would succeed.
+ */
+static int has_valid_directory_prefix(wchar_t *wfilename)
+{
+       int n = wcslen(wfilename);
+
+       while (n > 0) {
+               wchar_t c = wfilename[--n];
+               DWORD attributes;
+
+               if (!is_dir_sep(c))
+                       continue;
+
+               wfilename[n] = L'\0';
+               attributes = GetFileAttributesW(wfilename);
+               wfilename[n] = c;
+               if (attributes == FILE_ATTRIBUTE_DIRECTORY ||
+                               attributes == FILE_ATTRIBUTE_DEVICE)
+                       return 1;
+               if (attributes == INVALID_FILE_ATTRIBUTES)
+                       switch (GetLastError()) {
+                       case ERROR_PATH_NOT_FOUND:
+                               continue;
+                       case ERROR_FILE_NOT_FOUND:
+                               /* This implies parent directory exists. */
+                               return 1;
+                       }
+               return 0;
+       }
+       return 1;
+}
+
 /* We keep the do_lstat code in a separate function to avoid recursion.
  * When a path ends with a slash, the stat will fail with ENOENT. In
  * this case, we strip the trailing slashes and stat again.
@@ -514,6 +547,12 @@ static int do_lstat(int follow, const char *file_name, struct stat *buf)
        case ERROR_NOT_ENOUGH_MEMORY:
                errno = ENOMEM;
                break;
+       case ERROR_PATH_NOT_FOUND:
+               if (!has_valid_directory_prefix(wfilename)) {
+                       errno = ENOTDIR;
+                       break;
+               }
+               /* fallthru */
        default:
                errno = ENOENT;
                break;
@@ -1603,7 +1642,12 @@ int mingw_rename(const char *pold, const char *pnew)
        if (gle == ERROR_ACCESS_DENIED &&
            (attrs = GetFileAttributesW(wpnew)) != INVALID_FILE_ATTRIBUTES) {
                if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
-                       errno = EISDIR;
+                       DWORD attrsold = GetFileAttributesW(wpold);
+                       if (attrsold == INVALID_FILE_ATTRIBUTES ||
+                           !(attrsold & FILE_ATTRIBUTE_DIRECTORY))
+                               errno = EISDIR;
+                       else if (!_wrmdir(wpnew))
+                               goto repeat;
                        return -1;
                }
                if ((attrs & FILE_ATTRIBUTE_READONLY) &&
@@ -2047,6 +2091,37 @@ int xwcstoutf(char *utf, const wchar_t *wcs, size_t utflen)
        return -1;
 }
 
+static void setup_windows_environment()
+{
+       char *tmp = getenv("TMPDIR");
+
+       /* on Windows it is TMP and TEMP */
+       if (!tmp) {
+               if (!(tmp = getenv("TMP")))
+                       tmp = getenv("TEMP");
+               if (tmp) {
+                       setenv("TMPDIR", tmp, 1);
+                       tmp = getenv("TMPDIR");
+               }
+       }
+
+       if (tmp) {
+               /*
+                * Convert all dir separators to forward slashes,
+                * to help shell commands called from the Git
+                * executable (by not mistaking the dir separators
+                * for escape characters).
+                */
+               for (; *tmp; tmp++)
+                       if (*tmp == '\\')
+                               *tmp = '/';
+       }
+
+       /* simulate TERM to enable auto-color (see color.c) */
+       if (!getenv("TERM"))
+               setenv("TERM", "cygwin", 1);
+}
+
 /*
  * Disable MSVCRT command line wildcard expansion (__getmainargs called from
  * mingw startup code, see init.c in mingw runtime).
@@ -2125,19 +2200,7 @@ void mingw_startup()
        qsort(environ, i, sizeof(char*), compareenv);
 
        /* fix Windows specific environment settings */
-
-       /* on Windows it is TMP and TEMP */
-       if (!mingw_getenv("TMPDIR")) {
-               const char *tmp = mingw_getenv("TMP");
-               if (!tmp)
-                       tmp = mingw_getenv("TEMP");
-               if (tmp)
-                       setenv("TMPDIR", tmp, 1);
-       }
-
-       /* simulate TERM to enable auto-color (see color.c) */
-       if (!getenv("TERM"))
-               setenv("TERM", "cygwin", 1);
+       setup_windows_environment();
 
        /* initialize critical section for waitpid pinfo_t list */
        InitializeCriticalSection(&pinfo_cs);
index 4b2e1b807fc4e6f4467f0da891afe9aa8dad6310..d6f7980bb91ab7d1e4a02a91407bd8e38461671b 100644 (file)
@@ -560,7 +560,8 @@ else
                NO_R_TO_GCC_LINKER = YesPlease
                INTERNAL_QSORT = YesPlease
                HAVE_LIBCHARSET_H = YesPlease
-               NO_GETTEXT = YesPlease
+               NO_GETTEXT =
+               USE_GETTEXT_SCHEME = fallthrough
                USE_LIBPCRE= YesPlease
                NO_CURL =
                USE_NED_ALLOCATOR = YesPlease
index fd7ffe1840e64417cf94d208840cf97c91e962b7..047863144f3f22fe36d178a00b116ee45c2e9e11 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -357,6 +357,10 @@ static int git_tcp_connect_sock(char *host, int flags)
                port = "<none>";
 
        memset(&hints, 0, sizeof(hints));
+       if (flags & CONNECT_IPV4)
+               hints.ai_family = AF_INET;
+       else if (flags & CONNECT_IPV6)
+               hints.ai_family = AF_INET6;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_protocol = IPPROTO_TCP;
 
@@ -783,6 +787,10 @@ struct child_process *git_connect(int fd[2], const char *url,
                        }
 
                        argv_array_push(&conn->args, ssh);
+                       if (flags & CONNECT_IPV4)
+                               argv_array_push(&conn->args, "-4");
+                       else if (flags & CONNECT_IPV6)
+                               argv_array_push(&conn->args, "-6");
                        if (tortoiseplink)
                                argv_array_push(&conn->args, "-batch");
                        if (port) {
index c41a6850f1302e4d27af1066b53b20dd303f0d13..01f14cdf3fa4e6b6c8cd3b4c9ec3c3d55e7fc04f 100644 (file)
--- a/connect.h
+++ b/connect.h
@@ -3,6 +3,8 @@
 
 #define CONNECT_VERBOSE       (1u << 0)
 #define CONNECT_DIAG_URL      (1u << 1)
+#define CONNECT_IPV4          (1u << 2)
+#define CONNECT_IPV6          (1u << 3)
 extern struct child_process *git_connect(int fd[2], const char *url, const char *prog, int flags);
 extern int finish_connect(struct child_process *conn);
 extern int git_connection_is_socket(struct child_process *conn);
index 45ec47f2b1b45e346290e7bbad143519b1ad91a6..e3918c87e3adf32a9d7a4f0320c92c497376b9b5 100644 (file)
@@ -2415,8 +2415,8 @@ _git_stash ()
                show,--*|branch,--*)
                        ;;
                branch,*)
-                 if [ $cword -eq 3 ]; then
-                       __gitcomp_nl "$(__git_refs)";
+                       if [ $cword -eq 3 ]; then
+                               __gitcomp_nl "$(__git_refs)";
                        else
                                __gitcomp_nl "$(git --git-dir="$(__gitdir)" stash list \
                                                | sed -n -e 's/:.*//p')"
index 4bb4ec1d836e695a86f309b276fd07e300885c57..8cd6222a263ac99a63335bf7080a3fb4dd797ff7 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -434,7 +434,7 @@ static int apply_filter(const char *path, const char *src, size_t len, int fd,
        struct async async;
        struct filter_params params;
 
-       if (!cmd)
+       if (!cmd || !*cmd)
                return 0;
 
        if (!dst)
index 95e69b19a70ba63f2055d6a2ec3f9af0092a0832..02c0445be1057619e01e56bd6792f78fc011dc42 100755 (executable)
@@ -2664,7 +2664,7 @@ sub argsfromdir
     #   co  # Obtain list directly.
     #   remove # HERE: TEST: MAYBE client does the recursion for us,
     #          # since it only makes sense to remove stuff already in
-    #          # the sandobx?
+    #          # the sandbox?
     #   ci # HERE: Similar to remove...
     #      # Don't try to implement the confusing/weird
     #      # ci -r bug er.."feature".
diff --git a/git.c b/git.c
index da278c3d41ed308581ffec46e3487e7670898d41..6c64c9430e8e5ae3130b0c97e90bcbad29625b1e 100644 (file)
--- a/git.c
+++ b/git.c
@@ -25,14 +25,14 @@ static const char *env_names[] = {
        GIT_PREFIX_ENVIRONMENT
 };
 static char *orig_env[4];
-static int saved_env_before_alias;
+static int save_restore_env_balance;
 
 static void save_env_before_alias(void)
 {
        int i;
-       if (saved_env_before_alias)
-               return;
-       saved_env_before_alias = 1;
+
+       assert(save_restore_env_balance == 0);
+       save_restore_env_balance = 1;
        orig_cwd = xgetcwd();
        for (i = 0; i < ARRAY_SIZE(env_names); i++) {
                orig_env[i] = getenv(env_names[i]);
@@ -44,6 +44,9 @@ static void save_env_before_alias(void)
 static void restore_env(int external_alias)
 {
        int i;
+
+       assert(save_restore_env_balance == 1);
+       save_restore_env_balance = 0;
        if (!external_alias && orig_cwd && chdir(orig_cwd))
                die_errno("could not move to %s", orig_cwd);
        free(orig_cwd);
@@ -51,10 +54,12 @@ static void restore_env(int external_alias)
                if (external_alias &&
                    !strcmp(env_names[i], GIT_PREFIX_ENVIRONMENT))
                        continue;
-               if (orig_env[i])
+               if (orig_env[i]) {
                        setenv(env_names[i], orig_env[i], 1);
-               else
+                       free(orig_env[i]);
+               } else {
                        unsetenv(env_names[i]);
+               }
        }
 }
 
@@ -531,16 +536,8 @@ static void handle_builtin(int argc, const char **argv)
        }
 
        builtin = get_builtin(cmd);
-       if (builtin) {
-               /*
-                * XXX: if we can figure out cases where it is _safe_
-                * to do, we can avoid spawning a new process when
-                * saved_env_before_alias is true
-                * (i.e. setup_git_dir* has been run once)
-                */
-               if (!saved_env_before_alias)
-                       exit(run_builtin(builtin, argc, argv));
-       }
+       if (builtin)
+               exit(run_builtin(builtin, argc, argv));
 }
 
 static void execv_dashed_external(const char **argv)
@@ -584,8 +581,17 @@ static int run_argv(int *argcp, const char ***argv)
        int done_alias = 0;
 
        while (1) {
-               /* See if it's a builtin */
-               handle_builtin(*argcp, *argv);
+               /*
+                * If we tried alias and futzed with our environment,
+                * it no longer is safe to invoke builtins directly in
+                * general.  We have to spawn them as dashed externals.
+                *
+                * NEEDSWORK: if we can figure out cases
+                * where it is safe to do, we can avoid spawning a new
+                * process.
+                */
+               if (!done_alias)
+                       handle_builtin(*argcp, *argv);
 
                /* .. then try the external ones */
                execv_dashed_external(*argv);
index d857b131a8f7b02e3120900c5a4e525d9f8de591..bd60668707b956160edd9fb22767758023571ebb 100644 (file)
@@ -1277,9 +1277,7 @@ static struct object_list **add_one_object(struct object *obj, struct object_lis
 }
 
 static struct object_list **process_blob(struct blob *blob,
-                                        struct object_list **p,
-                                        struct name_path *path,
-                                        const char *name)
+                                        struct object_list **p)
 {
        struct object *obj = &blob->object;
 
@@ -1293,14 +1291,11 @@ static struct object_list **process_blob(struct blob *blob,
 }
 
 static struct object_list **process_tree(struct tree *tree,
-                                        struct object_list **p,
-                                        struct name_path *path,
-                                        const char *name)
+                                        struct object_list **p)
 {
        struct object *obj = &tree->object;
        struct tree_desc desc;
        struct name_entry entry;
-       struct name_path me;
 
        obj->flags |= LOCAL;
 
@@ -1310,21 +1305,17 @@ static struct object_list **process_tree(struct tree *tree,
                die("bad tree object %s", oid_to_hex(&obj->oid));
 
        obj->flags |= SEEN;
-       name = xstrdup(name);
        p = add_one_object(obj, p);
-       me.up = path;
-       me.elem = name;
-       me.elem_len = strlen(name);
 
        init_tree_desc(&desc, tree->buffer, tree->size);
 
        while (tree_entry(&desc, &entry))
                switch (object_type(entry.mode)) {
                case OBJ_TREE:
-                       p = process_tree(lookup_tree(entry.sha1), p, &me, name);
+                       p = process_tree(lookup_tree(entry.sha1), p);
                        break;
                case OBJ_BLOB:
-                       p = process_blob(lookup_blob(entry.sha1), p, &me, name);
+                       p = process_blob(lookup_blob(entry.sha1), p);
                        break;
                default:
                        /* Subproject commit - not in this repository */
@@ -1343,7 +1334,7 @@ static int get_delta(struct rev_info *revs, struct remote_lock *lock)
        int count = 0;
 
        while ((commit = get_revision(revs)) != NULL) {
-               p = process_tree(commit->tree, p, NULL, "");
+               p = process_tree(commit->tree, p);
                commit->object.flags |= LOCAL;
                if (!(commit->object.flags & UNINTERESTING))
                        count += add_send_request(&commit->object, lock);
@@ -1362,11 +1353,11 @@ static int get_delta(struct rev_info *revs, struct remote_lock *lock)
                        continue;
                }
                if (obj->type == OBJ_TREE) {
-                       p = process_tree((struct tree *)obj, p, NULL, name);
+                       p = process_tree((struct tree *)obj, p);
                        continue;
                }
                if (obj->type == OBJ_BLOB) {
-                       p = process_blob((struct blob *)obj, p, NULL, name);
+                       p = process_blob((struct blob *)obj, p);
                        continue;
                }
                die("unknown pending object %s (%s)", oid_to_hex(&obj->oid), name);
diff --git a/http.c b/http.c
index dfc53c1e2554e76126459d6cb1f098facac28593..1d5e3bbd11ae0e7dc0e682d3914e07cc13a0ce14 100644 (file)
--- a/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;
@@ -57,6 +62,9 @@ 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;
@@ -87,6 +95,7 @@ static int curl_save_cookies;
 struct credential http_auth = CREDENTIAL_INIT;
 static int http_proactive_auth;
 static const char *user_agent;
+static int curl_empty_auth;
 
 #if LIBCURL_VERSION_NUM >= 0x071700
 /* Use CURLOPT_KEYPASSWD as is */
@@ -299,14 +308,31 @@ static int http_options(const char *var, const char *value, void *cb)
        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);
 
@@ -498,6 +524,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);
@@ -824,10 +854,14 @@ struct active_request_slot *get_active_slot(void)
        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;
diff --git a/http.h b/http.h
index f83cfa686823728587b2a803c3e84a8cd4669220..4ef4bbda7d86d8ca5238d45897b277709b30414a 100644 (file)
--- a/http.h
+++ b/http.h
@@ -107,6 +107,7 @@ extern void http_init(struct remote *remote, const char *url,
                      int proactive_auth);
 extern void http_cleanup(void);
 
+extern long int git_curl_ipresolve;
 extern int active_requests;
 extern int http_is_verbose;
 extern size_t http_post_buffer;
diff --git a/ident.c b/ident.c
index 3da555634290f1812702e2d6da15e5a6806fe635..6e125821f0563c46eaf8253f31e19d9d97a94e7e 100644 (file)
--- a/ident.c
+++ b/ident.c
@@ -13,11 +13,14 @@ static struct strbuf git_default_date = STRBUF_INIT;
 static int default_email_is_bogus;
 static int default_name_is_bogus;
 
+static int ident_use_config_only;
+
 #define IDENT_NAME_GIVEN 01
 #define IDENT_MAIL_GIVEN 02
 #define IDENT_ALL_GIVEN (IDENT_NAME_GIVEN|IDENT_MAIL_GIVEN)
 static int committer_ident_explicitly_given;
 static int author_ident_explicitly_given;
+static int ident_config_given;
 
 #ifdef NO_GECOS_IN_PWENT
 #define get_gecos(ignored) "&"
@@ -345,32 +348,40 @@ const char *fmt_ident(const char *name, const char *email,
        int want_date = !(flag & IDENT_NO_DATE);
        int want_name = !(flag & IDENT_NO_NAME);
 
-       if (want_name && !name)
-               name = ident_default_name();
-       if (!email)
-               email = ident_default_email();
-
-       if (want_name && !*name) {
-               struct passwd *pw;
-
-               if (strict) {
-                       if (name == git_default_name.buf)
+       if (want_name) {
+               int using_default = 0;
+               if (!name) {
+                       name = ident_default_name();
+                       using_default = 1;
+                       if (strict && default_name_is_bogus) {
                                fputs(env_hint, stderr);
-                       die("empty ident name (for <%s>) not allowed", email);
+                               die("unable to auto-detect name (got '%s')", name);
+                       }
+                       if (strict && ident_use_config_only
+                           && !(ident_config_given & IDENT_NAME_GIVEN))
+                               die("user.useConfigOnly set but no name given");
+               }
+               if (!*name) {
+                       struct passwd *pw;
+                       if (strict) {
+                               if (using_default)
+                                       fputs(env_hint, stderr);
+                               die("empty ident name (for <%s>) not allowed", email);
+                       }
+                       pw = xgetpwuid_self(NULL);
+                       name = pw->pw_name;
                }
-               pw = xgetpwuid_self(NULL);
-               name = pw->pw_name;
-       }
-
-       if (want_name && strict &&
-           name == git_default_name.buf && default_name_is_bogus) {
-               fputs(env_hint, stderr);
-               die("unable to auto-detect name (got '%s')", name);
        }
 
-       if (strict && email == git_default_email.buf && default_email_is_bogus) {
-               fputs(env_hint, stderr);
-               die("unable to auto-detect email address (got '%s')", email);
+       if (!email) {
+               email = ident_default_email();
+               if (strict && default_email_is_bogus) {
+                       fputs(env_hint, stderr);
+                       die("unable to auto-detect email address (got '%s')", email);
+               }
+               if (strict && ident_use_config_only
+                   && !(ident_config_given & IDENT_MAIL_GIVEN))
+                       die("user.useConfigOnly set but no mail given");
        }
 
        strbuf_reset(&ident);
@@ -444,6 +455,11 @@ int author_ident_sufficiently_given(void)
 
 int git_ident_config(const char *var, const char *value, void *data)
 {
+       if (!strcmp(var, "user.useconfigonly")) {
+               ident_use_config_only = git_config_bool(var, value);
+               return 0;
+       }
+
        if (!strcmp(var, "user.name")) {
                if (!value)
                        return config_error_nonbool(var);
@@ -451,6 +467,7 @@ int git_ident_config(const char *var, const char *value, void *data)
                strbuf_addstr(&git_default_name, value);
                committer_ident_explicitly_given |= IDENT_NAME_GIVEN;
                author_ident_explicitly_given |= IDENT_NAME_GIVEN;
+               ident_config_given |= IDENT_NAME_GIVEN;
                return 0;
        }
 
@@ -461,6 +478,7 @@ int git_ident_config(const char *var, const char *value, void *data)
                strbuf_addstr(&git_default_email, value);
                committer_ident_explicitly_given |= IDENT_MAIL_GIVEN;
                author_ident_explicitly_given |= IDENT_MAIL_GIVEN;
+               ident_config_given |= IDENT_MAIL_GIVEN;
                return 0;
        }
 
index 11732d93883ee6af8990ad311d07f28028af9876..917cc5d7c9ee04d07199f18b78342b84c0375fcd 100644 (file)
 static void process_blob(struct rev_info *revs,
                         struct blob *blob,
                         show_object_fn show,
-                        struct name_path *path,
+                        struct strbuf *path,
                         const char *name,
                         void *cb_data)
 {
        struct object *obj = &blob->object;
+       size_t pathlen;
 
        if (!revs->blob_objects)
                return;
@@ -24,7 +25,11 @@ static void process_blob(struct rev_info *revs,
        if (obj->flags & (UNINTERESTING | SEEN))
                return;
        obj->flags |= SEEN;
-       show(obj, path, name, cb_data);
+
+       pathlen = path->len;
+       strbuf_addstr(path, name);
+       show(obj, path->buf, cb_data);
+       strbuf_setlen(path, pathlen);
 }
 
 /*
@@ -52,7 +57,7 @@ static void process_blob(struct rev_info *revs,
 static void process_gitlink(struct rev_info *revs,
                            const unsigned char *sha1,
                            show_object_fn show,
-                           struct name_path *path,
+                           struct strbuf *path,
                            const char *name,
                            void *cb_data)
 {
@@ -62,7 +67,6 @@ static void process_gitlink(struct rev_info *revs,
 static void process_tree(struct rev_info *revs,
                         struct tree *tree,
                         show_object_fn show,
-                        struct name_path *path,
                         struct strbuf *base,
                         const char *name,
                         void *cb_data)
@@ -70,7 +74,6 @@ static void process_tree(struct rev_info *revs,
        struct object *obj = &tree->object;
        struct tree_desc desc;
        struct name_entry entry;
-       struct name_path me;
        enum interesting match = revs->diffopt.pathspec.nr == 0 ?
                all_entries_interesting: entry_not_interesting;
        int baselen = base->len;
@@ -86,17 +89,12 @@ static void process_tree(struct rev_info *revs,
                        return;
                die("bad tree object %s", oid_to_hex(&obj->oid));
        }
+
        obj->flags |= SEEN;
-       show(obj, path, name, cb_data);
-       me.up = path;
-       me.elem = name;
-       me.elem_len = strlen(name);
-
-       if (!match) {
-               strbuf_addstr(base, name);
-               if (base->len)
-                       strbuf_addch(base, '/');
-       }
+       strbuf_addstr(base, name);
+       show(obj, base->buf, cb_data);
+       if (base->len)
+               strbuf_addch(base, '/');
 
        init_tree_desc(&desc, tree->buffer, tree->size);
 
@@ -113,16 +111,16 @@ static void process_tree(struct rev_info *revs,
                if (S_ISDIR(entry.mode))
                        process_tree(revs,
                                     lookup_tree(entry.sha1),
-                                    show, &me, base, entry.path,
+                                    show, base, entry.path,
                                     cb_data);
                else if (S_ISGITLINK(entry.mode))
                        process_gitlink(revs, entry.sha1,
-                                       show, &me, entry.path,
+                                       show, base, entry.path,
                                        cb_data);
                else
                        process_blob(revs,
                                     lookup_blob(entry.sha1),
-                                    show, &me, entry.path,
+                                    show, base, entry.path,
                                     cb_data);
        }
        strbuf_setlen(base, baselen);
@@ -213,19 +211,19 @@ void traverse_commit_list(struct rev_info *revs,
                        continue;
                if (obj->type == OBJ_TAG) {
                        obj->flags |= SEEN;
-                       show_object(obj, NULL, name, data);
+                       show_object(obj, name, data);
                        continue;
                }
                if (!path)
                        path = "";
                if (obj->type == OBJ_TREE) {
                        process_tree(revs, (struct tree *)obj, show_object,
-                                    NULL, &base, path, data);
+                                    &base, path, data);
                        continue;
                }
                if (obj->type == OBJ_BLOB) {
                        process_blob(revs, (struct blob *)obj, show_object,
-                                    NULL, path, data);
+                                    &base, path, data);
                        continue;
                }
                die("unknown pending object %s (%s)",
index 136a1da5a6f048c0f4645112cdbf29c7b0982526..0cebf8585cb179ae46fd8238eaf2b2162739bbaa 100644 (file)
@@ -2,7 +2,7 @@
 #define LIST_OBJECTS_H
 
 typedef void (*show_commit_fn)(struct commit *, void *);
-typedef void (*show_object_fn)(struct object *, const struct name_path *, const char *, void *);
+typedef void (*show_object_fn)(struct object *, const char *, void *);
 void traverse_commit_list(struct rev_info *, show_commit_fn, show_object_fn, void *);
 
 typedef void (*show_edge_fn)(struct commit *);
index 1ddfbfcd782d3b8d0e479cb0c5e29abce86e63c9..74ea6d54793f62188cd88e93f1adfe74c5957dda 100644 (file)
@@ -9,8 +9,8 @@ merge_cmd () {
        gvimdiff|vimdiff)
                if $base_present
                then
-                       "$merge_tool_path" -f -d -c 'wincmd J' \
-                               "$MERGED" "$LOCAL" "$BASE" "$REMOTE"
+                       "$merge_tool_path" -f -d -c '4wincmd w | wincmd J' \
+                               "$LOCAL" "$BASE" "$REMOTE" "$MERGED"
                else
                        "$merge_tool_path" -f -d -c 'wincmd l' \
                                "$LOCAL" "$MERGED" "$REMOTE"
index 6bff970c905b6a9c8a04773d64afb164dd124cbe..c30bcd06cbd516eb04e9b55b27b5f091ede61439 100644 (file)
@@ -148,8 +148,7 @@ static uint32_t find_object_pos(const unsigned char *sha1)
        return entry->in_pack_pos;
 }
 
-static void show_object(struct object *object, const struct name_path *path,
-                       const char *last, void *data)
+static void show_object(struct object *object, const char *name, void *data)
 {
        struct bitmap *base = data;
        bitmap_set(base, find_object_pos(object->oid.hash));
index dd8dc16e676fb3e928560002c0cb7e1f36910e1a..b949e517167dbac6c4c347e0a2cbdf8ca2dabbcf 100644 (file)
@@ -414,19 +414,15 @@ static int ext_index_add_object(struct object *object, const char *name)
        return bitmap_pos + bitmap_git.pack->num_objects;
 }
 
-static void show_object(struct object *object, const struct name_path *path,
-                       const char *last, void *data)
+static void show_object(struct object *object, const char *name, void *data)
 {
        struct bitmap *base = data;
        int bitmap_pos;
 
        bitmap_pos = bitmap_position(object->oid.hash);
 
-       if (bitmap_pos < 0) {
-               char *name = path_name(path, last);
+       if (bitmap_pos < 0)
                bitmap_pos = ext_index_add_object(object, name);
-               free(name);
-       }
 
        bitmap_set(base, bitmap_pos);
 }
@@ -894,9 +890,8 @@ struct bitmap_test_data {
        size_t seen;
 };
 
-static void test_show_object(struct object *object,
-                            const struct name_path *path,
-                            const char *last, void *data)
+static void test_show_object(struct object *object, const char *name,
+                            void *data)
 {
        struct bitmap_test_data *tdata = data;
        int bitmap_pos;
index 19ef081103a56e3c723749dc172ccc356a9b795c..49eb88af8d052e2bd71b83576034f8d338290013 100644 (file)
@@ -188,7 +188,8 @@ sub repository {
                };
 
                if ($dir) {
-                       $dir =~ m#^/# or $dir = $opts{Directory} . '/' . $dir;
+                       _verify_require();
+                       File::Spec->file_name_is_absolute($dir) or $dir = $opts{Directory} . '/' . $dir;
                        $opts{Repository} = abs_path($dir);
 
                        # If --git-dir went ok, this shouldn't die either.
index c50176eec9418c50e5c63921c24e76a87b6123ab..4c4199afecac2c5fc6d918cf0d3b75449504b808 100644 (file)
@@ -41,6 +41,7 @@ sub new {
                               "$self->{svn_path}/" : '';
        $self->{config} = $opts->{config};
        $self->{mergeinfo} = $opts->{mergeinfo};
+       $self->{pathnameencoding} = Git::config('svn.pathnameencoding');
        return $self;
 }
 
@@ -143,11 +144,12 @@ sub repo_path {
 
 sub url_path {
        my ($self, $path) = @_;
+       $path = $self->repo_path($path);
        if ($self->{url} =~ m#^https?://#) {
                # characters are taken from subversion/libsvn_subr/path.c
                $path =~ s#([^~a-zA-Z0-9_./!$&'()*+,-])#sprintf("%%%02X",ord($1))#eg;
        }
-       $self->{url} . '/' . $self->repo_path($path);
+       $self->{url} . '/' . $path;
 }
 
 sub rmdirs {
index 43616d49c7f88166d2fa2f009ca5b926d751ab0b..ed352018964ef2260f5da51239800bbcc816ad1b 100644 (file)
@@ -43,15 +43,14 @@ static int add_one_ref(const char *path, const struct object_id *oid,
  * The traversal will have already marked us as SEEN, so we
  * only need to handle any progress reporting here.
  */
-static void mark_object(struct object *obj, const struct name_path *path,
-                       const char *name, void *data)
+static void mark_object(struct object *obj, const char *name, void *data)
 {
        update_progress(data);
 }
 
 static void mark_commit(struct commit *c, void *data)
 {
-       mark_object(&c->object, NULL, NULL, data);
+       mark_object(&c->object, NULL, data);
 }
 
 struct recent_data {
index c7048575fbdca1bd8dc57c114d0cfdc031e63039..2e2266b856afa920d798f9ae9ee3238c681f9380 100644 (file)
@@ -119,6 +119,19 @@ static int set_option(const char *name, const char *value)
                else
                        return -1;
                return 0;
+
+#if LIBCURL_VERSION_NUM >= 0x070a08
+       } else if (!strcmp(name, "family")) {
+               if (!strcmp(value, "ipv4"))
+                       git_curl_ipresolve = CURL_IPRESOLVE_V4;
+               else if (!strcmp(value, "ipv6"))
+                       git_curl_ipresolve = CURL_IPRESOLVE_V6;
+               else if (!strcmp(value, "all"))
+                       git_curl_ipresolve = CURL_IPRESOLVE_WHATEVER;
+               else
+                       return -1;
+               return 0;
+#endif /* LIBCURL_VERSION_NUM >= 0x070a08 */
        } else {
                return 1 /* unsupported */;
        }
@@ -439,8 +452,20 @@ static int run_slot(struct active_request_slot *slot,
        err = run_one_slot(slot, results);
 
        if (err != HTTP_OK && err != HTTP_REAUTH) {
-               error("RPC failed; result=%d, HTTP code = %ld",
-                     results->curl_result, results->http_code);
+               struct strbuf msg = STRBUF_INIT;
+               if (results->http_code && results->http_code != 200)
+                       strbuf_addf(&msg, "HTTP %ld", results->http_code);
+               if (results->curl_result != CURLE_OK) {
+                       if (msg.len)
+                               strbuf_addch(&msg, ' ');
+                       strbuf_addf(&msg, "curl %d", results->curl_result);
+                       if (curl_errorstr[0]) {
+                               strbuf_addch(&msg, ' ');
+                               strbuf_addstr(&msg, curl_errorstr);
+                       }
+               }
+               error("RPC failed; %s", msg.buf);
+               strbuf_release(&msg);
        }
 
        return err;
index 35940a5602807542eeae12a45bb845e73a99339c..02e698a5e05a02f8905ec511851eea15e86d746f 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -1548,11 +1548,8 @@ void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
                }
 
                /*
-                * Bypass the usual "must fast-forward" check but
-                * replace it with a weaker "the old value must be
-                * this value we observed".  If the remote ref has
-                * moved and is now different from what we expect,
-                * reject any push.
+                * If the remote ref has moved and is now different
+                * from what we expect, reject any push.
                 *
                 * It also is an error if the user told us to check
                 * with the remote-tracking branch to find the value
@@ -1563,10 +1560,14 @@ void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
                        if (ref->expect_old_no_trackback ||
                            oidcmp(&ref->old_oid, &ref->old_oid_expect))
                                reject_reason = REF_STATUS_REJECT_STALE;
+                       else
+                               /* If the ref isn't stale then force the update. */
+                               force_ref_update = 1;
                }
 
                /*
-                * The usual "must fast-forward" rules.
+                * If the update isn't already rejected then check
+                * the usual "must fast-forward" rules.
                 *
                 * Decide whether an individual refspec A:B can be
                 * pushed.  The push will succeed if any of the
@@ -1585,7 +1586,7 @@ void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
                 *     passing the --force argument
                 */
 
-               else if (!ref->deletion && !is_null_oid(&ref->old_oid)) {
+               if (!reject_reason && !ref->deletion && !is_null_oid(&ref->old_oid)) {
                        if (starts_with(ref->name, "refs/tags/"))
                                reject_reason = REF_STATUS_REJECT_ALREADY_EXISTS;
                        else if (!has_object_file(&ref->old_oid))
index 403c700c326e4551aea183523af6ed46e1476432..587b7e2717b14748b92a5960f79947b5fba088f0 100644 (file)
--- a/rerere.c
+++ b/rerere.c
@@ -48,7 +48,7 @@ static int has_rerere_resolution(const struct rerere_id *id)
 static struct rerere_id *new_rerere_id_hex(char *hex)
 {
        struct rerere_id *id = xmalloc(sizeof(*id));
-       strcpy(id->hex, hex);
+       xsnprintf(id->hex, sizeof(id->hex), "%s", hex);
        return id;
 }
 
@@ -904,7 +904,7 @@ int rerere_forget(struct pathspec *pathspec)
 static struct rerere_id *dirname_to_id(const char *name)
 {
        static struct rerere_id id;
-       strcpy(id.hex, name);
+       xsnprintf(id.hex, sizeof(id.hex), "%s", name);
        return &id;
 }
 
index f24ead53d537b05d7819ce53b45b05a15ec60a96..82f3ca44b3e3dba8bdd487be04bd66b862fefa4c 100644 (file)
@@ -25,69 +25,13 @@ volatile show_early_output_fn_t show_early_output;
 static const char *term_bad;
 static const char *term_good;
 
-char *path_name(const struct name_path *path, const char *name)
-{
-       const struct name_path *p;
-       char *n, *m;
-       int nlen = strlen(name);
-       int len = nlen + 1;
-
-       for (p = path; p; p = p->up) {
-               if (p->elem_len)
-                       len += p->elem_len + 1;
-       }
-       n = xmalloc(len);
-       m = n + len - (nlen + 1);
-       memcpy(m, name, nlen + 1);
-       for (p = path; p; p = p->up) {
-               if (p->elem_len) {
-                       m -= p->elem_len + 1;
-                       memcpy(m, p->elem, p->elem_len);
-                       m[p->elem_len] = '/';
-               }
-       }
-       return n;
-}
-
-static int show_path_component_truncated(FILE *out, const char *name, int len)
-{
-       int cnt;
-       for (cnt = 0; cnt < len; cnt++) {
-               int ch = name[cnt];
-               if (!ch || ch == '\n')
-                       return -1;
-               fputc(ch, out);
-       }
-       return len;
-}
-
-static int show_path_truncated(FILE *out, const struct name_path *path)
-{
-       int emitted, ours;
-
-       if (!path)
-               return 0;
-       emitted = show_path_truncated(out, path->up);
-       if (emitted < 0)
-               return emitted;
-       if (emitted)
-               fputc('/', out);
-       ours = show_path_component_truncated(out, path->elem, path->elem_len);
-       if (ours < 0)
-               return ours;
-       return ours || emitted;
-}
-
-void show_object_with_name(FILE *out, struct object *obj,
-                          const struct name_path *path, const char *component)
+void show_object_with_name(FILE *out, struct object *obj, const char *name)
 {
-       struct name_path leaf;
-       leaf.up = (struct name_path *)path;
-       leaf.elem = component;
-       leaf.elem_len = strlen(component);
+       const char *p;
 
        fprintf(out, "%s ", oid_to_hex(&obj->oid));
-       show_path_truncated(out, &leaf);
+       for (p = name; *p && *p != '\n'; p++)
+               fputc(*p, out);
        fputc('\n', out);
 }
 
index 23857c0ed1d7a304c848842711a920e678fd506d..dca0d381715cf5bc6888587feaec989012f51252 100644 (file)
@@ -257,16 +257,9 @@ extern void put_revision_mark(const struct rev_info *revs,
 extern void mark_parents_uninteresting(struct commit *commit);
 extern void mark_tree_uninteresting(struct tree *tree);
 
-struct name_path {
-       struct name_path *up;
-       int elem_len;
-       const char *elem;
-};
-
-char *path_name(const struct name_path *path, const char *name);
+char *path_name(struct strbuf *path, const char *name);
 
-extern void show_object_with_name(FILE *, struct object *,
-                                 const struct name_path *, const char *);
+extern void show_object_with_name(FILE *, struct object *, const char *);
 
 extern void add_pending_object(struct rev_info *revs,
                               struct object *obj, const char *name);
diff --git a/setup.c b/setup.c
index 0deb02238ba426144e0b7b077c9f2ad5c7993d23..59ec6587aa7e54b72d7a2f9fe0af51d66b2c8901 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -139,9 +139,7 @@ int check_filename(const char *prefix, const char *arg)
                if (arg[2] == '\0') /* ":/" is root dir, always exists */
                        return 1;
                name = arg + 2;
-       } else if (!no_wildcard(arg))
-               return 1;
-       else if (prefix)
+       } else if (prefix)
                name = prefix_filename(prefix, strlen(prefix), arg);
        else
                name = arg;
@@ -202,7 +200,7 @@ void verify_filename(const char *prefix,
 {
        if (*arg == '-')
                die("bad flag '%s' used after filename", arg);
-       if (check_filename(prefix, arg))
+       if (check_filename(prefix, arg) || !no_wildcard(arg))
                return;
        die_verify_filename(prefix, arg, diagnose_misspelt_rev);
 }
index 892db21813bc484628e940274e742d103629b0ed..d0f844db897751adca937578185c7421095bbc1e 100644 (file)
@@ -848,8 +848,12 @@ static int get_sha1_1(const char *name, int len, unsigned char *sha1, unsigned l
  * through history and returning the first commit whose message starts
  * the given regular expression.
  *
- * For future extension, ':/!' is reserved. If you want to match a message
- * beginning with a '!', you have to repeat the exclamation mark.
+ * For negative-matching, prefix the pattern-part with '!-', like: ':/!-WIP'.
+ *
+ * For a literal '!' character at the beginning of a pattern, you have to repeat
+ * that, like: ':/!!foo'
+ *
+ * For future extension, all other sequences beginning with ':/!' are reserved.
  */
 
 /* Remember to update object flag allocation in object.h */
@@ -878,16 +882,22 @@ static int get_sha1_oneline(const char *prefix, unsigned char *sha1,
 {
        struct commit_list *backup = NULL, *l;
        int found = 0;
+       int negative = 0;
        regex_t regex;
 
        if (prefix[0] == '!') {
-               if (prefix[1] != '!')
-                       die ("Invalid search pattern: %s", prefix);
                prefix++;
+
+               if (prefix[0] == '-') {
+                       prefix++;
+                       negative = 1;
+               } else if (prefix[0] != '!') {
+                       return -1;
+               }
        }
 
        if (regcomp(&regex, prefix, REG_EXTENDED))
-               die("Invalid search pattern: %s", prefix);
+               return -1;
 
        for (l = list; l; l = l->next) {
                l->item->object.flags |= ONELINE_SEEN;
@@ -903,7 +913,7 @@ static int get_sha1_oneline(const char *prefix, unsigned char *sha1,
                        continue;
                buf = get_commit_buffer(commit, NULL);
                p = strstr(buf, "\n\n");
-               matches = p && !regexec(&regex, p + 2, 0, NULL, 0);
+               matches = negative ^ (p && !regexec(&regex, p + 2, 0, NULL, 0));
                unuse_commit_buffer(commit, buf);
 
                if (matches) {
index 43b15e36aeeba4ddc48073f8463592efc5216e3c..18e2b28b263682a9eb6902b62535c228be1f36af 100644 (file)
@@ -27,7 +27,6 @@ PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
 TEST_RESULTS_DIRECTORY_SQ = $(subst ','\'',$(TEST_RESULTS_DIRECTORY))
 
 T = $(sort $(wildcard t[0-9][0-9][0-9][0-9]-*.sh))
-TSVN = $(sort $(wildcard t91[0-9][0-9]-*.sh))
 TGITWEB = $(sort $(wildcard t95[0-9][0-9]-*.sh))
 THELPERS = $(sort $(filter-out $(T),$(wildcard *.sh)))
 
@@ -77,11 +76,6 @@ aggregate-results:
                echo "$$f"; \
        done | '$(SHELL_PATH_SQ)' ./aggregate-results.sh
 
-# we can test NO_OPTIMIZE_COMMITS independently of LC_ALL
-full-svn-test:
-       $(MAKE) $(TSVN) GIT_SVN_NO_OPTIMIZE_COMMITS=1 LC_ALL=C
-       $(MAKE) $(TSVN) GIT_SVN_NO_OPTIMIZE_COMMITS=0 LC_ALL=en_US.UTF-8
-
 gitweb-test:
        $(MAKE) $(TGITWEB)
 
index bc4b3412fbca1f545ebdcaf23d3ef83d124ddc71..340534c0644eb46782c0a95103bd2a3ef60da9f7 100644 (file)
@@ -23,6 +23,11 @@ then
        test_done
 fi
 
+if test_have_prereq !PIPE
+then
+       test_skip_or_die $GIT_TEST_GIT_DAEMON "file system does not support FIFOs"
+fi
+
 LIB_GIT_DAEMON_PORT=${LIB_GIT_DAEMON_PORT-${this_test#t}}
 
 GIT_DAEMON_PID=
index b0ec12ff6cbcdd7352b764db32bc34340b37fc8a..6a50b8793e4ff840e67d20c169159f474cb9d297 100644 (file)
@@ -186,3 +186,15 @@ start_svnserve () {
              --listen-host 127.0.0.1 &
 }
 
+prepare_a_utf8_locale () {
+       a_utf8_locale=$(locale -a | sed -n '/\.[uU][tT][fF]-*8$/{
+       p
+       q
+}')
+       if test -n "$a_utf8_locale"
+       then
+               test_set_prereq UTF8
+       else
+               say "# UTF-8 locale not available, some tests are skipped"
+       fi
+}
index 4ef5ed484c12a4509b9bc66f2cc41118f7254431..89544dd8332793af7c792a45e6566f207ef57e38 100755 (executable)
@@ -5,7 +5,7 @@ test_description=check-ignore
 . ./test-lib.sh
 
 init_vars () {
-       global_excludes="$(pwd)/global-excludes"
+       global_excludes="global-excludes"
 }
 
 enable_global_excludes () {
index 718efa04d34df1f867a37d7b3073f1463457455b..7bac2bcf260794bbfeb795b210ed0c9eceb45937 100755 (executable)
@@ -252,4 +252,20 @@ test_expect_success "filter: smudge empty file" '
        test_cmp expected filtered-empty-in-repo
 '
 
+test_expect_success 'disable filter with empty override' '
+       test_config_global filter.disable.smudge false &&
+       test_config_global filter.disable.clean false &&
+       test_config filter.disable.smudge false &&
+       test_config filter.disable.clean false &&
+
+       echo "*.disable filter=disable" >.gitattributes &&
+
+       echo test >test.disable &&
+       git -c filter.disable.clean= add test.disable 2>err &&
+       test_must_be_empty err &&
+       rm -f test.disable &&
+       git -c filter.disable.smudge= checkout -- test.disable 2>err &&
+       test_must_be_empty err
+'
+
 test_done
index f0152a7ab4aabd4f47f546c038efcd8503adc9a4..8532a028e7c814057fe0bb7fd87addbd5dc90392 100755 (executable)
@@ -36,12 +36,21 @@ if test $rootoff = 2; then
        rootoff=        # we are on Unix
 else
        rootoff=$(($rootoff-1))
+       # In MSYS2, the root directory "/" is translated into a Windows
+       # directory *with* trailing slash. Let's test for that and adjust
+       # our expected longest ancestor length accordingly.
+       case "$(test-path-utils print_path /)" in
+       */) rootslash=1;;
+       *) rootslash=0;;
+       esac
 fi
 
 ancestor() {
        # We do some math with the expected ancestor length.
        expected=$3
        if test -n "$rootoff" && test "x$expected" != x-1; then
+               expected=$(($expected-$rootslash))
+               test $expected -lt 0 ||
                expected=$(($expected+$rootoff))
        fi
        test_expect_success "longest ancestor: $1 $2 => $expected" \
index 078e1195dfa1625796fdbbf1b054ebf8a1ba2621..4a9964e9dc4e0437b703a35a727e7e1971cf06fd 100755 (executable)
@@ -35,7 +35,10 @@ test_expect_success 'setup' '
        git checkout -b upstream-branch &&
        test_commit upstream-one &&
        test_commit upstream-two &&
-       git checkout -b @/at-test &&
+       if test_have_prereq !MINGW
+       then
+               git checkout -b @/at-test
+       fi &&
        git checkout -b @@/at-test &&
        git checkout -b @at-test &&
        git checkout -b old-branch &&
@@ -64,6 +67,7 @@ check "@{-1}@{u}@{1}" commit master-one
 check "@" commit new-two
 check "@@{u}" ref refs/heads/upstream-branch
 check "@@/at-test" ref refs/heads/@@/at-test
+test_have_prereq MINGW ||
 check "@/at-test" ref refs/heads/@/at-test
 check "@at-test" ref refs/heads/@at-test
 nonsense "@{u}@{-1}"
index 7043ba7947933644f15d086d8bdd95d377c4d265..e0a49a651fdd3b3f7d9e0f24e00439c9642f896c 100755 (executable)
@@ -18,7 +18,18 @@ test_expect_success 'setup' '
        git checkout master &&
        echo modified >>a-blob &&
        git add -u &&
-       git commit -m Modified
+       git commit -m Modified &&
+       git branch modref &&
+       echo changed! >>a-blob &&
+       git add -u &&
+       git commit -m !Exp &&
+       git branch expref &&
+       echo changed >>a-blob &&
+       git add -u &&
+       git commit -m Changed &&
+       echo changed-again >>a-blob &&
+       git add -u &&
+       git commit -m Changed-again
 '
 
 test_expect_success 'ref^{non-existent}' '
@@ -77,4 +88,44 @@ test_expect_success 'ref^{/Initial}' '
        test_cmp expected actual
 '
 
+test_expect_success 'ref^{/!Exp}' '
+       test_must_fail git rev-parse master^{/!Exp}
+'
+
+test_expect_success 'ref^{/!}' '
+       test_must_fail git rev-parse master^{/!}
+'
+
+test_expect_success 'ref^{/!!Exp}' '
+       git rev-parse expref >expected &&
+       git rev-parse master^{/!!Exp} >actual &&
+       test_cmp expected actual
+'
+
+test_expect_success 'ref^{/!-}' '
+       test_must_fail git rev-parse master^{/!-}
+'
+
+test_expect_success 'ref^{/!-.}' '
+       test_must_fail git rev-parse master^{/!-.}
+'
+
+test_expect_success 'ref^{/!-non-existent}' '
+       git rev-parse master >expected &&
+       git rev-parse master^{/!-non-existent} >actual &&
+       test_cmp expected actual
+'
+
+test_expect_success 'ref^{/!-Changed}' '
+       git rev-parse expref >expected &&
+       git rev-parse master^{/!-Changed} >actual &&
+       test_cmp expected actual
+'
+
+test_expect_success 'ref^{/!-!Exp}' '
+       git rev-parse modref >expected &&
+       git rev-parse expref^{/!-!Exp} >actual &&
+       test_cmp expected actual
+'
+
 test_done
index 199b22d85e92535f148eaaca4d3856dbdfb6bcec..b99d5192a96ec77ef6a99cb86518375c447b48a9 100755 (executable)
@@ -56,30 +56,4 @@ test_expect_success VAGUENESS_SUCCESS 'checkout reports switch to branch' '
        test_i18ngrep ! "^HEAD is now at" stderr
 '
 
-test_expect_success 'wildcard ambiguation, paths win' '
-       git init ambi &&
-       (
-               cd ambi &&
-               echo a >a.c &&
-               git add a.c &&
-               echo b >a.c &&
-               git checkout "*.c" &&
-               echo a >expect &&
-               test_cmp expect a.c
-       )
-'
-
-test_expect_success !MINGW 'wildcard ambiguation, refs lose' '
-       git init ambi2 &&
-       (
-               cd ambi2 &&
-               echo a >"*.c" &&
-               git add . &&
-               test_must_fail git show :"*.c" &&
-               git show :"*.c" -- >actual &&
-               echo a >expect &&
-               test_cmp expect actual
-       )
-'
-
 test_done
index 75ebb1b4a0f79faa6f92cc9575eeef6b10ae27d3..1b1b65a6b0fc7ace4e18e8642a6c47631d7e6a43 100755 (executable)
@@ -8,6 +8,16 @@ test_expect_success 'setup' '
        test_commit init
 '
 
+test_expect_success 'rev-parse --git-common-dir on main worktree' '
+       git rev-parse --git-common-dir >actual &&
+       echo .git >expected &&
+       test_cmp expected actual &&
+       mkdir sub &&
+       git -C sub rev-parse --git-common-dir >actual2 &&
+       echo sub/.git >expected2 &&
+       test_cmp expected2 actual2
+'
+
 test_expect_success '"list" all worktrees from main' '
        echo "$(git rev-parse --show-toplevel) $(git rev-parse --short HEAD) [$(git symbolic-ref --short HEAD)]" >expect &&
        test_when_finished "rm -rf here && git worktree prune" &&
index 9a146f133539387a8cbc70fb4f5095eca5cd288e..04de03cad0a7466106a125205742b5feea1b1e2f 100755 (executable)
@@ -13,6 +13,7 @@ tree, index, and tree objects.
 
 HT='   '
 
+test_have_prereq MINGW ||
 echo 2>/dev/null > "Name with an${HT}HT"
 if ! test -f "Name with an${HT}HT"
 then
index 2e47a2bfd8c99988d536483a0c01d8b81396c5b5..d046d98aec61748ad936515807f28f77600f630e 100755 (executable)
@@ -14,7 +14,7 @@ test_expect_success \
      git add -- foo bar baz 'space embedded' -q &&
      git commit -m 'add normal files'"
 
-if touch -- 'tab       embedded' 'newline
+if test_have_prereq !MINGW && touch -- 'tab    embedded' 'newline
 embedded' 2>/dev/null
 then
        test_set_prereq FUNNYNAMES
index 5115de7036c38a9464dfdab0e13519a872902991..3ef525a559d91b115a3dbe4a1373c8c51fb1fc98 100755 (executable)
@@ -38,7 +38,7 @@ cat >expected <<EOF
 add 'sub/foo'
 EOF
 
-if mkdir ":" 2>/dev/null
+if test_have_prereq !MINGW && mkdir ":" 2>/dev/null
 then
        test_set_prereq COLON_DIR
 fi
index 892f5678441b3c9065f743d9fe9f071334420831..f528008c363c68f40da3b88a34ae8ec931d0c1ac 100755 (executable)
@@ -12,6 +12,7 @@ GN='純'
 HT='   '
 DQ='"'
 
+test_have_prereq MINGW ||
 echo foo 2>/dev/null > "Name and an${HT}HT"
 if ! test -f "Name and an${HT}HT"
 then
index cd543ecc5429dc175750971f4b593e327ab3fcee..9c48e5c2c99ad1eafc343a2cf6b9eeda54f644d4 100755 (executable)
@@ -13,6 +13,7 @@ P1='pathname  with HT'
 P2='pathname with SP'
 P3='pathname
 with LF'
+test_have_prereq !MINGW &&
 echo 2>/dev/null >"$P1" && test -f "$P1" && rm -f "$P1" || {
        skip_all='Your filesystem does not allow tabs in filenames'
        test_done
index bf5dc57286493b0b94caf927304e92db11e54f2c..27cb0009fb1ed52b749785c31081b3097fef0022 100755 (executable)
@@ -19,7 +19,8 @@ test_expect_success 'setup' '
 
        test_when_finished "rm -f \"tab embedded.txt\"" &&
        test_when_finished "rm -f '\''\"quoteembedded\".txt'\''" &&
-       if touch -- "tab        embedded.txt" '\''"quoteembedded".txt'\''
+       if test_have_prereq !MINGW &&
+               touch -- "tab   embedded.txt" '\''"quoteembedded".txt'\''
        then
                test_set_prereq FUNNYNAMES
        fi
index 1a8e3b81c815cfb92b7025a12d8c703f2ffc54e9..0dcc752076a9e42b0cff982d7b0f42c63f85dee2 100755 (executable)
@@ -51,6 +51,11 @@ test_expect_success setup '
        git clone one test
 '
 
+test_expect_success 'add remote whose URL agrees with url.<...>.insteadOf' '
+       test_config url.git@host.com:team/repo.git.insteadOf myremote &&
+       git remote add myremote git@host.com:team/repo.git
+'
+
 test_expect_success C_LOCALE_OUTPUT 'remote information for the origin' '
        (
                cd test &&
index 9203a6507fa8df75ef187c129f750921caf19951..0c10c856a96072a1b0c37530a9f5c8605d8833b5 100755 (executable)
@@ -314,42 +314,6 @@ test_expect_success 'bundle should be able to create a full history' '
 
 '
 
-! rsync --help > /dev/null 2> /dev/null &&
-say 'Skipping rsync tests because rsync was not found' || {
-test_expect_success 'fetch via rsync' '
-       git pack-refs &&
-       mkdir rsynced &&
-       (cd rsynced &&
-        git init --bare &&
-        git fetch "rsync:../.git" master:refs/heads/master &&
-        git gc --prune &&
-        test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
-        git fsck --full)
-'
-
-test_expect_success 'push via rsync' '
-       mkdir rsynced2 &&
-       (cd rsynced2 &&
-        git init) &&
-       (cd rsynced &&
-        git push "rsync:../rsynced2/.git" master) &&
-       (cd rsynced2 &&
-        git gc --prune &&
-        test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
-        git fsck --full)
-'
-
-test_expect_success 'push via rsync' '
-       mkdir rsynced3 &&
-       (cd rsynced3 &&
-        git init) &&
-       git push --all "rsync:rsynced3/.git" &&
-       (cd rsynced3 &&
-        test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
-        git fsck --full)
-'
-}
-
 test_expect_success 'fetch with a non-applying branch.<name>.merge' '
        git config branch.master.remote yeti &&
        git config branch.master.merge refs/heads/bigfoot &&
index c402d8d3d7c7e053373ffd98491ae0160481f3ba..c7320121ecfa74dce8389d3790364501c8bb12b8 100755 (executable)
@@ -25,7 +25,8 @@ test_expect_success 'push to update (protected)' '
        (
                cd dst &&
                test_commit D &&
-               test_must_fail git push --force-with-lease=master:master origin master
+               test_must_fail git push --force-with-lease=master:master origin master 2>err &&
+               grep "stale info" err
        ) &&
        git ls-remote . refs/heads/master >expect &&
        git ls-remote src refs/heads/master >actual &&
@@ -37,7 +38,8 @@ test_expect_success 'push to update (protected, forced)' '
        (
                cd dst &&
                test_commit D &&
-               git push --force --force-with-lease=master:master origin master
+               git push --force --force-with-lease=master:master origin master 2>err &&
+               grep "forced update" err
        ) &&
        git ls-remote dst refs/heads/master >expect &&
        git ls-remote src refs/heads/master >actual &&
@@ -101,7 +103,8 @@ test_expect_success 'push to update (allowed, tracking)' '
        (
                cd dst &&
                test_commit D &&
-               git push --force-with-lease=master origin master
+               git push --force-with-lease=master origin master 2>err &&
+               ! grep "forced update" err
        ) &&
        git ls-remote dst refs/heads/master >expect &&
        git ls-remote src refs/heads/master >actual &&
@@ -114,7 +117,8 @@ test_expect_success 'push to update (allowed even though no-ff)' '
                cd dst &&
                git reset --hard HEAD^ &&
                test_commit D &&
-               git push --force-with-lease=master origin master
+               git push --force-with-lease=master origin master 2>err &&
+               grep "forced update" err
        ) &&
        git ls-remote dst refs/heads/master >expect &&
        git ls-remote src refs/heads/master >actual &&
@@ -147,7 +151,8 @@ test_expect_success 'push to delete (allowed)' '
        setup_srcdst_basic &&
        (
                cd dst &&
-               git push --force-with-lease=master origin :master
+               git push --force-with-lease=master origin :master 2>err &&
+               grep deleted err
        ) &&
        >expect &&
        git ls-remote src refs/heads/master >actual &&
index d76269a8fc96a874042cd2e070794e2c56577468..225a022e8a8fe063bc9cb8b8b282323f95bb18e3 100755 (executable)
@@ -6,6 +6,12 @@ test_description='test fetching over git protocol'
 . "$TEST_DIRECTORY"/lib-git-daemon.sh
 start_git_daemon
 
+check_verbose_connect () {
+       grep -F "Looking up 127.0.0.1 ..." stderr &&
+       grep -F "Connecting to 127.0.0.1 (port " stderr &&
+       grep -F "done." stderr
+}
+
 test_expect_success 'setup repository' '
        git config push.default matching &&
        echo content >file &&
@@ -24,7 +30,8 @@ test_expect_success 'create git-accessible bare repository' '
 '
 
 test_expect_success 'clone git repository' '
-       git clone "$GIT_DAEMON_URL/repo.git" clone &&
+       git clone -v "$GIT_DAEMON_URL/repo.git" clone 2>stderr &&
+       check_verbose_connect &&
        test_cmp file clone/file
 '
 
@@ -32,10 +39,21 @@ test_expect_success 'fetch changes via git protocol' '
        echo content >>file &&
        git commit -a -m two &&
        git push public &&
-       (cd clone && git pull) &&
+       (cd clone && git pull -v) 2>stderr &&
+       check_verbose_connect &&
        test_cmp file clone/file
 '
 
+test_expect_success 'no-op fetch -v stderr is as expected' '
+       (cd clone && git fetch -v) 2>stderr &&
+       check_verbose_connect
+'
+
+test_expect_success 'no-op fetch without "-v" is quiet' '
+       (cd clone && git fetch) 2>stderr &&
+       ! test -s stderr
+'
+
 test_expect_success 'remote detects correct HEAD' '
        git push public master:other &&
        (cd clone &&
index 669ec9ba811fedeca820c4454b490e975b03bfca..c1efb8e445402cccdddda987e1eafad4d4bb75f9 100755 (executable)
@@ -4,6 +4,9 @@ test_description=clone
 
 . ./test-lib.sh
 
+X=
+test_have_prereq !MINGW || X=.exe
+
 test_expect_success setup '
 
        rm -fr .git &&
@@ -305,14 +308,9 @@ test_expect_success 'clone checking out a tag' '
 
 setup_ssh_wrapper () {
        test_expect_success 'setup ssh wrapper' '
-               write_script "$TRASH_DIRECTORY/ssh-wrapper" <<-\EOF &&
-               echo >>"$TRASH_DIRECTORY/ssh-output" "ssh: $*" &&
-               # throw away all but the last argument, which should be the
-               # command
-               while test $# -gt 1; do shift; done
-               eval "$1"
-               EOF
-               GIT_SSH="$TRASH_DIRECTORY/ssh-wrapper" &&
+               cp "$GIT_BUILD_DIR/test-fake-ssh$X" \
+                       "$TRASH_DIRECTORY/ssh-wrapper$X" &&
+               GIT_SSH="$TRASH_DIRECTORY/ssh-wrapper$X" &&
                export GIT_SSH &&
                export TRASH_DIRECTORY &&
                >"$TRASH_DIRECTORY"/ssh-output
@@ -320,8 +318,8 @@ setup_ssh_wrapper () {
 }
 
 copy_ssh_wrapper_as () {
-       cp "$TRASH_DIRECTORY/ssh-wrapper" "$1" &&
-       GIT_SSH="$1" &&
+       cp "$TRASH_DIRECTORY/ssh-wrapper$X" "${1%$X}$X" &&
+       GIT_SSH="${1%$X}$X" &&
        export GIT_SSH
 }
 
diff --git a/t/t6133-pathspec-rev-dwim.sh b/t/t6133-pathspec-rev-dwim.sh
new file mode 100755 (executable)
index 0000000..a290ffc
--- /dev/null
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+test_description='test dwim of revs versus pathspecs in revision parser'
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+       test_commit base &&
+       echo content >"br[ack]ets" &&
+       git add . &&
+       test_tick &&
+       git commit -m brackets
+'
+
+test_expect_success 'non-rev wildcard dwims to pathspec' '
+       git log -- "*.t" >expect &&
+       git log    "*.t" >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'tree:path with metacharacters dwims to rev' '
+       git show "HEAD:br[ack]ets" -- >expect &&
+       git show "HEAD:br[ack]ets"    >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success '^{foo} with metacharacters dwims to rev' '
+       git log "HEAD^{/b.*}" -- >expect &&
+       git log "HEAD^{/b.*}"    >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success '@{foo} with metacharacters dwims to rev' '
+       git log "HEAD@{now [or thereabouts]}" -- >expect &&
+       git log "HEAD@{now [or thereabouts]}"    >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success ':/*.t from a subdir dwims to a pathspec' '
+       mkdir subdir &&
+       (
+               cd subdir &&
+               git log -- ":/*.t" >expect &&
+               git log    ":/*.t" >actual &&
+               test_cmp expect actual
+       )
+'
+
+test_done
diff --git a/t/t7517-per-repo-email.sh b/t/t7517-per-repo-email.sh
new file mode 100755 (executable)
index 0000000..337e6e3
--- /dev/null
@@ -0,0 +1,39 @@
+#!/bin/sh
+#
+# Copyright (c) 2016 Dan Aloni
+# Copyright (c) 2016 Jeff King
+#
+
+test_description='per-repo forced setting of email address'
+
+. ./test-lib.sh
+
+test_expect_success 'setup a likely user.useConfigOnly use case' '
+       # we want to make sure a reflog is written, since that needs
+       # a non-strict ident. So be sure we have an actual commit.
+       test_commit foo &&
+
+       sane_unset GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL &&
+       sane_unset GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL &&
+       git config user.name "test" &&
+       git config --global user.useConfigOnly true
+'
+
+test_expect_success 'fails committing if clone email is not set' '
+       test_must_fail git commit --allow-empty -m msg
+'
+
+test_expect_success 'fails committing if clone email is not set, but EMAIL set' '
+       test_must_fail env EMAIL=test@fail.com git commit --allow-empty -m msg
+'
+
+test_expect_success 'succeeds committing if clone email is set' '
+       test_config user.email "test@ok.com" &&
+       git commit --allow-empty -m msg
+'
+
+test_expect_success 'succeeds cloning if global email is not set' '
+       git clone . clone
+'
+
+test_done
index ec8bc8c7656fd7f0fd03226b5491f5bc9d532dd7..4e713f7aa54d4713cfd74978460ec9aa144fc773 100755 (executable)
@@ -430,11 +430,11 @@ EOF
 test_expect_success PERL,SYMLINKS 'difftool --dir-diff --symlink without unstaged changes' '
        cat >expect <<-EOF &&
        file
-       $(pwd)/file
+       $PWD/file
        file2
-       $(pwd)/file2
+       $PWD/file2
        sub/sub
-       $(pwd)/sub/sub
+       $PWD/sub/sub
        EOF
        git difftool --dir-diff --symlink \
                --extcmd "./.git/CHECK_SYMLINKS" branch HEAD &&
@@ -448,14 +448,14 @@ EOF
 run_dir_diff_test 'difftool --dir-diff syncs worktree with unstaged change' '
        test_when_finished git reset --hard &&
        echo "orig content" >file &&
-       git difftool -d $symlinks --extcmd "$(pwd)/modify-right-file" branch &&
+       git difftool -d $symlinks --extcmd "$PWD/modify-right-file" branch &&
        echo "new content" >expect &&
        test_cmp expect file
 '
 
 run_dir_diff_test 'difftool --dir-diff syncs worktree without unstaged change' '
        test_when_finished git reset --hard &&
-       git difftool -d $symlinks --extcmd "$(pwd)/modify-right-file" branch &&
+       git difftool -d $symlinks --extcmd "$PWD/modify-right-file" branch &&
        echo "new content" >expect &&
        test_cmp expect file
 '
@@ -466,7 +466,7 @@ EOF
 
 test_expect_success PERL 'difftool --no-symlinks does not overwrite working tree file ' '
        echo "orig content" >file &&
-       git difftool --dir-diff --no-symlinks --extcmd "$(pwd)/modify-file" branch &&
+       git difftool --dir-diff --no-symlinks --extcmd "$PWD/modify-file" branch &&
        echo "new content" >expect &&
        test_cmp expect file
 '
@@ -482,7 +482,7 @@ test_expect_success PERL 'difftool --no-symlinks detects conflict ' '
                TMPDIR=$TRASH_DIRECTORY &&
                export TMPDIR &&
                echo "orig content" >file &&
-               test_must_fail git difftool --dir-diff --no-symlinks --extcmd "$(pwd)/modify-both-files" branch &&
+               test_must_fail git difftool --dir-diff --no-symlinks --extcmd "$PWD/modify-both-files" branch &&
                echo "wt content" >expect &&
                test_cmp expect file &&
                echo "tmp content" >expect &&
diff --git a/t/t9003-help-autocorrect.sh b/t/t9003-help-autocorrect.sh
new file mode 100755 (executable)
index 0000000..dfe95c9
--- /dev/null
@@ -0,0 +1,52 @@
+#!/bin/sh
+
+test_description='help.autocorrect finding a match'
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+       # An alias
+       git config alias.lgf "log --format=%s --first-parent" &&
+
+       # A random user-defined command
+       write_script git-distimdistim <<-EOF &&
+               echo distimdistim was called
+       EOF
+
+       PATH="$PATH:." &&
+       export PATH &&
+
+       git commit --allow-empty -m "a single log entry" &&
+
+       # Sanity check
+       git lgf >actual &&
+       echo "a single log entry" >expect &&
+       test_cmp expect actual &&
+
+       git distimdistim >actual &&
+       echo "distimdistim was called" >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success 'autocorrect showing candidates' '
+       git config help.autocorrect 0 &&
+
+       test_must_fail git lfg 2>actual &&
+       sed -e "1,/^Did you mean this/d" actual | grep lgf &&
+
+       test_must_fail git distimdist 2>actual &&
+       sed -e "1,/^Did you mean this/d" actual | grep distimdistim
+'
+
+test_expect_success 'autocorrect running commands' '
+       git config help.autocorrect -1 &&
+
+       git lfg >actual &&
+       echo "a single log entry" >expect &&
+       test_cmp expect actual &&
+
+       git distimdist >actual &&
+       echo "distimdistim was called" >expect &&
+       test_cmp expect actual
+'
+
+test_done
index 258d9b8cefb6bbf81a64098d57db03f7c1da90c6..22d8367ff397fc68683ff1084ce4914cfbfa9d89 100755 (executable)
@@ -117,7 +117,7 @@ test_expect_success "$name" '
 
 
 name='remove executable bit from a file'
-test_expect_success "$name" '
+test_expect_success POSIXPERM "$name" '
        rm -f "$GIT_DIR"/index &&
        git checkout -f -b mybranch5 ${remotes_git_svn} &&
        chmod -x exec.sh &&
@@ -130,7 +130,7 @@ test_expect_success "$name" '
 
 
 name='add executable bit back file'
-test_expect_success "$name" '
+test_expect_success POSIXPERM "$name" '
        chmod +x exec.sh &&
        git update-index exec.sh &&
        git commit -m "$name" &&
@@ -141,7 +141,7 @@ test_expect_success "$name" '
 
 
 name='executable file becomes a symlink to file'
-test_expect_success "$name" '
+test_expect_success SYMLINKS "$name" '
        rm exec.sh &&
        ln -s file exec.sh &&
        git update-index exec.sh &&
@@ -153,7 +153,7 @@ test_expect_success "$name" '
 
 name='new symlink is added to a file that was also just made executable'
 
-test_expect_success "$name" '
+test_expect_success POSIXPERM,SYMLINKS "$name" '
        chmod +x file &&
        ln -s file exec-2.sh &&
        git update-index --add file exec-2.sh &&
@@ -165,7 +165,7 @@ test_expect_success "$name" '
        test -h "$SVN_TREE"/exec-2.sh'
 
 name='modify a symlink to become a file'
-test_expect_success "$name" '
+test_expect_success POSIXPERM,SYMLINKS "$name" '
        echo git help >help &&
        rm exec-2.sh &&
        cp help exec-2.sh &&
@@ -181,7 +181,8 @@ test_expect_success "$name" '
 name="commit with UTF-8 message: locale: $GIT_SVN_LC_ALL"
 LC_ALL="$GIT_SVN_LC_ALL"
 export LC_ALL
-test_expect_success UTF8 "$name" "
+# This test relies on the previous test, hence requires POSIXPERM,SYMLINKS
+test_expect_success UTF8,POSIXPERM,SYMLINKS "$name" "
        echo '# hello' >> exec-2.sh &&
        git update-index exec-2.sh &&
        git commit -m 'éï∏' &&
@@ -214,7 +215,7 @@ tree d667270a1f7b109f5eb3aaea21ede14b56bfdd6e
 tree 8f51f74cf0163afc9ad68a4b1537288c4558b5a4
 EOF
 
-test_expect_success "$name" "test_cmp a expected"
+test_expect_success POSIXPERM,SYMLINKS "$name" "test_cmp a expected"
 
 test_expect_success 'exit if remote refs are ambigious' "
         git config --add svn-remote.svn.fetch \
index 6a48e4042996549e40843186783e2215beee9cca..0990f8d23571878fccb6e3607caa938590e3f683 100755 (executable)
@@ -77,11 +77,47 @@ test_expect_success 'make a commit to test rebase' '
        '
 
 test_expect_success 'git svn rebase works inside a fresh-cloned repository' '
-       cd test-rebase &&
+       (
+               cd test-rebase &&
                git svn rebase &&
                test -e test-rebase-main &&
                test -e test-rebase
-       '
+       )'
+
+# Without this, LC_ALL=C as set in test-lib.sh, and Cygwin converts
+# non-ASCII characters in filenames unexpectedly, and causes errors.
+# https://cygwin.com/cygwin-ug-net/using-specialnames.html#pathnames-specialchars
+# > Some characters are disallowed in filenames on Windows filesystems. ...
+# ...
+# > ... All of the above characters, except for the backslash, are converted
+# > to special UNICODE characters in the range 0xf000 to 0xf0ff (the
+# > "Private use area") when creating or accessing files.
+prepare_a_utf8_locale
+test_expect_success UTF8 'svn.pathnameencoding=cp932 new file on dcommit' '
+       LC_ALL=$a_utf8_locale &&
+       export LC_ALL &&
+       neq=$(printf "\201\202") &&
+       git config svn.pathnameencoding cp932 &&
+       echo neq >"$neq" &&
+       git add "$neq" &&
+       git commit -m "neq" &&
+       git svn dcommit
+'
+
+# See the comment on the above test for setting of LC_ALL.
+test_expect_success 'svn.pathnameencoding=cp932 rename on dcommit' '
+       LC_ALL=$a_utf8_locale &&
+       export LC_ALL &&
+       inf=$(printf "\201\207") &&
+       git config svn.pathnameencoding cp932 &&
+       echo inf >"$inf" &&
+       git add "$inf" &&
+       git commit -m "inf" &&
+       git svn dcommit &&
+       git mv "$inf" inf &&
+       git commit -m "inf rename" &&
+       git svn dcommit
+'
 
 stop_httpd
 
index a2219154b89393effa51f87b3be56706728b6572..ecb1fed147d206c7d1a3ac43f9d82110e9514e66 100755 (executable)
@@ -23,8 +23,11 @@ test_expect_success 'setup svnrepo' '
                      "$svnrepo/pr ject/branches/$scary_uri" &&
        svn_cmd cp -m "leading dot" "$svnrepo/pr ject/trunk" \
                        "$svnrepo/pr ject/branches/.leading_dot" &&
-       svn_cmd cp -m "trailing dot" "$svnrepo/pr ject/trunk" \
-                       "$svnrepo/pr ject/branches/trailing_dot." &&
+       if test_have_prereq !MINGW
+       then
+               svn_cmd cp -m "trailing dot" "$svnrepo/pr ject/trunk" \
+                       "$svnrepo/pr ject/branches/trailing_dot."
+       fi &&
        svn_cmd cp -m "trailing .lock" "$svnrepo/pr ject/trunk" \
                        "$svnrepo/pr ject/branches/trailing_dotlock.lock" &&
        svn_cmd cp -m "reflog" "$svnrepo/pr ject/trunk" \
@@ -45,7 +48,10 @@ test_expect_success 'test clone with funky branch names' '
                git rev-parse "refs/remotes/origin/more%20fun%20plugin!" &&
                git rev-parse "refs/remotes/origin/$scary_ref" &&
                git rev-parse "refs/remotes/origin/%2Eleading_dot" &&
-               git rev-parse "refs/remotes/origin/trailing_dot%2E" &&
+               if test_have_prereq !MINGW
+               then
+                       git rev-parse "refs/remotes/origin/trailing_dot%2E"
+               fi &&
                git rev-parse "refs/remotes/origin/trailing_dotlock%2Elock" &&
                git rev-parse "refs/remotes/origin/$non_reflog"
        )
index aa841e12996aad8cd7284eea56c47f0d89c79c56..9f7231d5b7dae28b55316e9e24968f4e5fe06664 100755 (executable)
@@ -34,8 +34,7 @@ test_expect_success 'enable auto-props config' '
 '
 
 test_expect_success 'add files matching auto-props' '
-       echo "#!$SHELL_PATH" >exec1.sh &&
-       chmod +x exec1.sh &&
+       write_script exec1.sh </dev/null &&
        echo "hello" >hello.txt &&
        echo bar >bar &&
        git add exec1.sh hello.txt bar &&
@@ -48,8 +47,7 @@ test_expect_success 'disable auto-props config' '
 '
 
 test_expect_success 'add files matching disabled auto-props' '
-       echo "#$SHELL_PATH" >exec2.sh &&
-       chmod +x exec2.sh &&
+       write_script exec2.sh </dev/null &&
        echo "world" >world.txt &&
        echo zot >zot &&
        git add exec2.sh world.txt zot &&
@@ -65,7 +63,10 @@ test_expect_success 'check resulting svn repository' '
        cd svnrepo &&
 
        # Check properties from first commit.
-       test "x$(svn_cmd propget svn:executable exec1.sh)" = "x*" &&
+       if test_have_prereq POSIXPERM
+       then
+               test "x$(svn_cmd propget svn:executable exec1.sh)" = "x*"
+       fi &&
        test "x$(svn_cmd propget svn:mime-type exec1.sh)" = \
             "xapplication/x-shellscript" &&
        test "x$(svn_cmd propget svn:mime-type hello.txt)" = "xtext/plain" &&
@@ -73,7 +74,10 @@ test_expect_success 'check resulting svn repository' '
        test "x$(svn_cmd propget svn:mime-type bar)" = "x" &&
 
        # Check properties from second commit.
-       test "x$(svn_cmd propget svn:executable exec2.sh)" = "x*" &&
+       if test_have_prereq POSIXPERM
+       then
+               test "x$(svn_cmd propget svn:executable exec2.sh)" = "x*"
+       fi &&
        test "x$(svn_cmd propget svn:mime-type exec2.sh)" = "x" &&
        test "x$(svn_cmd propget svn:mime-type world.txt)" = "x" &&
        test "x$(svn_cmd propget svn:eol-style world.txt)" = "x" &&
index 39b6bcb398fff970184e242bdd51500b84f7d382..8dbd6476fa181dc7a2b3f0b6a9dfff57155c9eea 100755 (executable)
@@ -14,17 +14,7 @@ compare_git_head_with () {
        test_cmp current "$1"
 }
 
-a_utf8_locale=$(locale -a | sed -n '/\.[uU][tT][fF]-*8$/{
-       p
-       q
-}')
-
-if test -n "$a_utf8_locale"
-then
-       test_set_prereq UTF8
-else
-       say "# UTF-8 locale not available, some tests are skipped"
-fi
+prepare_a_utf8_locale
 
 compare_svn_head_with () {
        # extract just the log message and strip out committer info.
index d306b77c31e6a73cc777b71eba1f69090093c0dc..41264818ccdd85abb4b0a17c8a508d4bcbfe57f5 100755 (executable)
@@ -91,7 +91,7 @@ test_expect_success 'fetch continues after authors-file is fixed' '
        )
        '
 
-test_expect_success 'fresh clone with svn.authors-file in config' '
+test_expect_success !MINGW 'fresh clone with svn.authors-file in config' '
        (
                rm -r "$GIT_DIR" &&
                test x = x"$(git config svn.authorsfile)" &&
index 812c9cd462f58f6fd76e3d339e95137aee598801..5cfb9cfc52e715c916f3ebe922e57263d7c4d7da 100755 (executable)
@@ -197,7 +197,7 @@ if p="Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö" &&
 then
 
 # This test contains UTF-8 characters
-test_expect_success \
+test_expect_success !MINGW \
      'File with non-ascii file name' \
      'mkdir -p Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö &&
       echo Foo >Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.txt &&
index 6146c3fec293915b4599748e7a787539a7715e1a..d708cbf0320abe502d875ae3333eda2501208ca2 100755 (executable)
@@ -25,11 +25,11 @@ perl -e 'use DBI; use DBD::SQLite' >/dev/null 2>&1 || {
     test_done
 }
 
-WORKDIR=$(pwd)
-SERVERDIR=$(pwd)/gitcvs.git
+WORKDIR=$PWD
+SERVERDIR=$PWD/gitcvs.git
 git_config="$SERVERDIR/config"
 CVSROOT=":fork:$SERVERDIR"
-CVSWORK="$(pwd)/cvswork"
+CVSWORK="$PWD/cvswork"
 CVS_SERVER=git-cvsserver
 export CVSROOT CVS_SERVER
 
index 5a4ed28e4980ea080fc018043527d9c62dd9b5d7..f324b9f010506d5f79388ef454df74156860ec13 100755 (executable)
@@ -74,11 +74,11 @@ perl -e 'use DBI; use DBD::SQLite' >/dev/null 2>&1 || {
 }
 
 unset GIT_DIR GIT_CONFIG
-WORKDIR=$(pwd)
-SERVERDIR=$(pwd)/gitcvs.git
+WORKDIR=$PWD
+SERVERDIR=$PWD/gitcvs.git
 git_config="$SERVERDIR/config"
 CVSROOT=":fork:$SERVERDIR"
-CVSWORK="$(pwd)/cvswork"
+CVSWORK="$PWD/cvswork"
 CVS_SERVER=git-cvsserver
 export CVSROOT CVS_SERVER
 
index d00df0873135a8efcf0edb92cd397b92ab7d06f0..6d2d3c8739cbd6978d823e7947d9f95c758ff241 100755 (executable)
@@ -82,11 +82,11 @@ perl -e 'use DBI; use DBD::SQLite' >/dev/null 2>&1 || {
 }
 
 unset GIT_DIR GIT_CONFIG
-WORKDIR=$(pwd)
-SERVERDIR=$(pwd)/gitcvs.git
+WORKDIR=$PWD
+SERVERDIR=$PWD/gitcvs.git
 git_config="$SERVERDIR/config"
 CVSROOT=":fork:$SERVERDIR"
-CVSWORK="$(pwd)/cvswork"
+CVSWORK="$PWD/cvswork"
 CVS_SERVER=git-cvsserver
 export CVSROOT CVS_SERVER
 
index 1140767b50706f03b0da5b2c8befdae6898e4136..7e8c40b97b4eecc2347ab2986a97b62148fe5f88 100755 (executable)
@@ -33,7 +33,7 @@ BEGIN
 is($r->config_int("test.nonexistent"), undef, "config_int: nonexistent");
 ok($r->config_bool("test.booltrue"), "config_bool: true");
 ok(!$r->config_bool("test.boolfalse"), "config_bool: false");
-is($r->config_path("test.path"), $r->config("test.pathexpanded"),
+is($r->config_path("test.path") =~ s/\\/\//gr, $r->config("test.pathexpanded"),
    "config_path: ~/foo expansion");
 is_deeply([$r->config_path("test.pathmulti")], ["foo", "bar"],
    "config_path: multiple values");
index af82049f82e89c3275c0f1e6c5da9d7f9c7041f5..ffbfa0efb8712f06cb14adc986ae29c4d1c23bf1 100755 (executable)
@@ -67,7 +67,7 @@ repo_with_newline='repo
 with
 newline'
 
-if mkdir "$repo_with_newline" 2>/dev/null
+if test_have_prereq !MINGW && mkdir "$repo_with_newline" 2>/dev/null
 then
        test_set_prereq FUNNYNAMES
 else
index bd4b02e9dbf9560cf1285bb6607be83964ecc40a..0b47eb6bb299492d31111c94557c216bb3f32c7f 100644 (file)
@@ -907,9 +907,11 @@ yes () {
                y="$*"
        fi
 
-       while echo "$y"
+       i=0
+       while test $i -lt 99
        do
-               :
+               echo "$y"
+               i=$(($i+1))
        done
 }
 
@@ -998,7 +1000,7 @@ test_i18ngrep () {
 test_lazy_prereq PIPE '
        # test whether the filesystem supports FIFOs
        case $(uname -s) in
-       CYGWIN*)
+       CYGWIN*|MINGW*)
                false
                ;;
        *)
diff --git a/test-fake-ssh.c b/test-fake-ssh.c
new file mode 100644 (file)
index 0000000..980de21
--- /dev/null
@@ -0,0 +1,30 @@
+#include "git-compat-util.h"
+#include "run-command.h"
+#include "strbuf.h"
+
+int main(int argc, char **argv)
+{
+       const char *trash_directory = getenv("TRASH_DIRECTORY");
+       struct strbuf buf = STRBUF_INIT;
+       FILE *f;
+       int i;
+       const char *child_argv[] = { NULL, NULL };
+
+       /* First, print all parameters into $TRASH_DIRECTORY/ssh-output */
+       if (!trash_directory)
+               die("Need a TRASH_DIRECTORY!");
+       strbuf_addf(&buf, "%s/ssh-output", trash_directory);
+       f = fopen(buf.buf, "w");
+       if (!f)
+               die("Could not write to %s", buf.buf);
+       for (i = 0; i < argc; i++)
+               fprintf(f, "%s%s", i > 0 ? " " : "", i > 0 ? argv[i] : "ssh:");
+       fprintf(f, "\n");
+       fclose(f);
+
+       /* Now, evaluate the *last* parameter */
+       if (argc < 2)
+               return 0;
+       child_argv[0] = argv[argc - 1];
+       return run_command_v_opt(child_argv, RUN_USING_SHELL);
+}
index c3adcd87b8caa2028785483bbc01d85fd0f7a9d6..6232dfe661a53d1eaf17ead5133da5792ae2413f 100644 (file)
@@ -56,7 +56,7 @@ static int test_function(struct test_data *data, char *(*func)(char *input),
                if (!data[i].from)
                        to = func(NULL);
                else {
-                       strcpy(buffer, data[i].from);
+                       xsnprintf(buffer, sizeof(buffer), "%s", data[i].from);
                        to = func(buffer);
                }
                if (!strcmp(to, data[i].to))
index a6bff8b30811c649c82afcdc9e018af1a34ce13c..b934183236ca571093f55818f5018c278150e274 100644 (file)
@@ -321,6 +321,21 @@ static void standard_options(struct transport *t)
        if (n >= sizeof(buf))
                die("impossibly large verbosity value");
        set_helper_option(t, "verbosity", buf);
+
+       switch (t->family) {
+       case TRANSPORT_FAMILY_ALL:
+               /*
+                * this is already the default,
+                * do not break old remote helpers by setting "all" here
+                */
+               break;
+       case TRANSPORT_FAMILY_IPV4:
+               set_helper_option(t, "family", "ipv4");
+               break;
+       case TRANSPORT_FAMILY_IPV6:
+               set_helper_option(t, "family", "ipv6");
+               break;
+       }
 }
 
 static int release_helper(struct transport *transport)
index 67f366687c7abf2f6bd9cf31faa6f4ed9e6dc69e..e20bb771faaa56aa876f14f73123e14a71731a1b 100644 (file)
 #include "sha1-array.h"
 #include "sigchain.h"
 
-/* rsync support */
-
-/*
- * We copy packed-refs and refs/ into a temporary file, then read the
- * loose refs recursively (sorting whenever possible), and then inserting
- * those packed refs that are not yet in the list (not validating, but
- * assuming that the file is sorted).
- *
- * Appears refactoring this from refs.c is too cumbersome.
- */
-
-static int str_cmp(const void *a, const void *b)
-{
-       const char *s1 = a;
-       const char *s2 = b;
-
-       return strcmp(s1, s2);
-}
-
-/* path->buf + name_offset is expected to point to "refs/" */
-
-static int read_loose_refs(struct strbuf *path, int name_offset,
-               struct ref **tail)
-{
-       DIR *dir = opendir(path->buf);
-       struct dirent *de;
-       struct {
-               char **entries;
-               int nr, alloc;
-       } list;
-       int i, pathlen;
-
-       if (!dir)
-               return -1;
-
-       memset (&list, 0, sizeof(list));
-
-       while ((de = readdir(dir))) {
-               if (is_dot_or_dotdot(de->d_name))
-                       continue;
-               ALLOC_GROW(list.entries, list.nr + 1, list.alloc);
-               list.entries[list.nr++] = xstrdup(de->d_name);
-       }
-       closedir(dir);
-
-       /* sort the list */
-
-       qsort(list.entries, list.nr, sizeof(char *), str_cmp);
-
-       pathlen = path->len;
-       strbuf_addch(path, '/');
-
-       for (i = 0; i < list.nr; i++, strbuf_setlen(path, pathlen + 1)) {
-               strbuf_addstr(path, list.entries[i]);
-               if (read_loose_refs(path, name_offset, tail)) {
-                       int fd = open(path->buf, O_RDONLY);
-                       char buffer[40];
-                       struct ref *next;
-
-                       if (fd < 0)
-                               continue;
-                       next = alloc_ref(path->buf + name_offset);
-                       if (read_in_full(fd, buffer, 40) != 40 ||
-                                       get_oid_hex(buffer, &next->old_oid)) {
-                               close(fd);
-                               free(next);
-                               continue;
-                       }
-                       close(fd);
-                       (*tail)->next = next;
-                       *tail = next;
-               }
-       }
-       strbuf_setlen(path, pathlen);
-
-       for (i = 0; i < list.nr; i++)
-               free(list.entries[i]);
-       free(list.entries);
-
-       return 0;
-}
-
-/* insert the packed refs for which no loose refs were found */
-
-static void insert_packed_refs(const char *packed_refs, struct ref **list)
-{
-       FILE *f = fopen(packed_refs, "r");
-       static char buffer[PATH_MAX];
-
-       if (!f)
-               return;
-
-       for (;;) {
-               int cmp = 0; /* assigned before used */
-               int len;
-
-               if (!fgets(buffer, sizeof(buffer), f)) {
-                       fclose(f);
-                       return;
-               }
-
-               if (!isxdigit(buffer[0]))
-                       continue;
-               len = strlen(buffer);
-               if (len && buffer[len - 1] == '\n')
-                       buffer[--len] = '\0';
-               if (len < 41)
-                       continue;
-               while ((*list)->next &&
-                               (cmp = strcmp(buffer + 41,
-                                     (*list)->next->name)) > 0)
-                       list = &(*list)->next;
-               if (!(*list)->next || cmp < 0) {
-                       struct ref *next = alloc_ref(buffer + 41);
-                       buffer[40] = '\0';
-                       if (get_oid_hex(buffer, &next->old_oid)) {
-                               warning ("invalid SHA-1: %s", buffer);
-                               free(next);
-                               continue;
-                       }
-                       next->next = (*list)->next;
-                       (*list)->next = next;
-                       list = &(*list)->next;
-               }
-       }
-}
-
 static void set_upstreams(struct transport *transport, struct ref *refs,
        int pretend)
 {
@@ -192,205 +65,6 @@ static void set_upstreams(struct transport *transport, struct ref *refs,
        }
 }
 
-static const char *rsync_url(const char *url)
-{
-       if (!starts_with(url, "rsync://"))
-               skip_prefix(url, "rsync:", &url);
-       return url;
-}
-
-static struct ref *get_refs_via_rsync(struct transport *transport, int for_push)
-{
-       struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT;
-       struct ref dummy = {NULL}, *tail = &dummy;
-       struct child_process rsync = CHILD_PROCESS_INIT;
-       const char *args[5];
-       int temp_dir_len;
-
-       if (for_push)
-               return NULL;
-
-       /* copy the refs to the temporary directory */
-
-       strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX"));
-       if (!mkdtemp(temp_dir.buf))
-               die_errno ("Could not make temporary directory");
-       temp_dir_len = temp_dir.len;
-
-       strbuf_addstr(&buf, rsync_url(transport->url));
-       strbuf_addstr(&buf, "/refs");
-
-       rsync.argv = args;
-       rsync.stdout_to_stderr = 1;
-       args[0] = "rsync";
-       args[1] = (transport->verbose > 1) ? "-rv" : "-r";
-       args[2] = buf.buf;
-       args[3] = temp_dir.buf;
-       args[4] = NULL;
-
-       if (run_command(&rsync))
-               die ("Could not run rsync to get refs");
-
-       strbuf_reset(&buf);
-       strbuf_addstr(&buf, rsync_url(transport->url));
-       strbuf_addstr(&buf, "/packed-refs");
-
-       args[2] = buf.buf;
-
-       if (run_command(&rsync))
-               die ("Could not run rsync to get refs");
-
-       /* read the copied refs */
-
-       strbuf_addstr(&temp_dir, "/refs");
-       read_loose_refs(&temp_dir, temp_dir_len + 1, &tail);
-       strbuf_setlen(&temp_dir, temp_dir_len);
-
-       tail = &dummy;
-       strbuf_addstr(&temp_dir, "/packed-refs");
-       insert_packed_refs(temp_dir.buf, &tail);
-       strbuf_setlen(&temp_dir, temp_dir_len);
-
-       if (remove_dir_recursively(&temp_dir, 0))
-               warning ("Error removing temporary directory %s.",
-                               temp_dir.buf);
-
-       strbuf_release(&buf);
-       strbuf_release(&temp_dir);
-
-       return dummy.next;
-}
-
-static int fetch_objs_via_rsync(struct transport *transport,
-                               int nr_objs, struct ref **to_fetch)
-{
-       struct child_process rsync = CHILD_PROCESS_INIT;
-
-       rsync.stdout_to_stderr = 1;
-       argv_array_push(&rsync.args, "rsync");
-       argv_array_push(&rsync.args, (transport->verbose > 1) ? "-rv" : "-r");
-       argv_array_push(&rsync.args, "--ignore-existing");
-       argv_array_push(&rsync.args, "--exclude");
-       argv_array_push(&rsync.args, "info");
-       argv_array_pushf(&rsync.args, "%s/objects/", rsync_url(transport->url));
-       argv_array_push(&rsync.args, get_object_directory());
-
-       /* NEEDSWORK: handle one level of alternates */
-       return run_command(&rsync);
-}
-
-static int write_one_ref(const char *name, const struct object_id *oid,
-                        int flags, void *data)
-{
-       struct strbuf *buf = data;
-       int len = buf->len;
-
-       /* when called via for_each_ref(), flags is non-zero */
-       if (flags && !starts_with(name, "refs/heads/") &&
-                       !starts_with(name, "refs/tags/"))
-               return 0;
-
-       strbuf_addstr(buf, name);
-       if (safe_create_leading_directories(buf->buf) ||
-           write_file_gently(buf->buf, "%s", oid_to_hex(oid)))
-               return error("problems writing temporary file %s: %s",
-                            buf->buf, strerror(errno));
-       strbuf_setlen(buf, len);
-       return 0;
-}
-
-static int write_refs_to_temp_dir(struct strbuf *temp_dir,
-                                 int refspec_nr, const char **refspec)
-{
-       int i;
-
-       for (i = 0; i < refspec_nr; i++) {
-               struct object_id oid;
-               char *ref;
-
-               if (dwim_ref(refspec[i], strlen(refspec[i]), oid.hash, &ref) != 1)
-                       return error("Could not get ref %s", refspec[i]);
-
-               if (write_one_ref(ref, &oid, 0, temp_dir)) {
-                       free(ref);
-                       return -1;
-               }
-               free(ref);
-       }
-       return 0;
-}
-
-static int rsync_transport_push(struct transport *transport,
-               int refspec_nr, const char **refspec, int flags)
-{
-       struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT;
-       int result = 0, i;
-       struct child_process rsync = CHILD_PROCESS_INIT;
-       const char *args[10];
-
-       if (flags & TRANSPORT_PUSH_MIRROR)
-               return error("rsync transport does not support mirror mode");
-
-       /* first push the objects */
-
-       strbuf_addstr(&buf, rsync_url(transport->url));
-       strbuf_addch(&buf, '/');
-
-       rsync.argv = args;
-       rsync.stdout_to_stderr = 1;
-       i = 0;
-       args[i++] = "rsync";
-       args[i++] = "-a";
-       if (flags & TRANSPORT_PUSH_DRY_RUN)
-               args[i++] = "--dry-run";
-       if (transport->verbose > 1)
-               args[i++] = "-v";
-       args[i++] = "--ignore-existing";
-       args[i++] = "--exclude";
-       args[i++] = "info";
-       args[i++] = get_object_directory();
-       args[i++] = buf.buf;
-       args[i++] = NULL;
-
-       if (run_command(&rsync))
-               return error("Could not push objects to %s",
-                               rsync_url(transport->url));
-
-       /* copy the refs to the temporary directory; they could be packed. */
-
-       strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX"));
-       if (!mkdtemp(temp_dir.buf))
-               die_errno ("Could not make temporary directory");
-       strbuf_addch(&temp_dir, '/');
-
-       if (flags & TRANSPORT_PUSH_ALL) {
-               if (for_each_ref(write_one_ref, &temp_dir))
-                       return -1;
-       } else if (write_refs_to_temp_dir(&temp_dir, refspec_nr, refspec))
-               return -1;
-
-       i = 2;
-       if (flags & TRANSPORT_PUSH_DRY_RUN)
-               args[i++] = "--dry-run";
-       if (!(flags & TRANSPORT_PUSH_FORCE))
-               args[i++] = "--ignore-existing";
-       args[i++] = temp_dir.buf;
-       args[i++] = rsync_url(transport->url);
-       args[i++] = NULL;
-       if (run_command(&rsync))
-               result = error("Could not push to %s",
-                               rsync_url(transport->url));
-
-       if (remove_dir_recursively(&temp_dir, 0))
-               warning ("Could not remove temporary directory %s.",
-                               temp_dir.buf);
-
-       strbuf_release(&buf);
-       strbuf_release(&temp_dir);
-
-       return result;
-}
-
 struct bundle_transport_data {
        int fd;
        struct bundle_header header;
@@ -481,17 +155,24 @@ static int set_git_option(struct git_transport_options *opts,
        return 1;
 }
 
-static int connect_setup(struct transport *transport, int for_push, int verbose)
+static int connect_setup(struct transport *transport, int for_push)
 {
        struct git_transport_data *data = transport->data;
+       int flags = transport->verbose > 0 ? CONNECT_VERBOSE : 0;
 
        if (data->conn)
                return 0;
 
+       switch (transport->family) {
+       case TRANSPORT_FAMILY_ALL: break;
+       case TRANSPORT_FAMILY_IPV4: flags |= CONNECT_IPV4; break;
+       case TRANSPORT_FAMILY_IPV6: flags |= CONNECT_IPV6; break;
+       }
+
        data->conn = git_connect(data->fd, transport->url,
                                 for_push ? data->options.receivepack :
                                 data->options.uploadpack,
-                                verbose ? CONNECT_VERBOSE : 0);
+                                flags);
 
        return 0;
 }
@@ -501,7 +182,7 @@ static struct ref *get_refs_via_connect(struct transport *transport, int for_pus
        struct git_transport_data *data = transport->data;
        struct ref *refs;
 
-       connect_setup(transport, for_push, 0);
+       connect_setup(transport, for_push);
        get_remote_heads(data->fd[0], NULL, 0, &refs,
                         for_push ? REF_NORMAL : 0,
                         &data->extra_have,
@@ -536,7 +217,7 @@ static int fetch_refs_via_pack(struct transport *transport,
        args.update_shallow = data->options.update_shallow;
 
        if (!data->got_remote_heads) {
-               connect_setup(transport, 0, 0);
+               connect_setup(transport, 0);
                get_remote_heads(data->fd[0], NULL, 0, &refs_tmp, 0,
                                 NULL, &data->shallow);
                data->got_remote_heads = 1;
@@ -812,7 +493,7 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re
 
        if (!data->got_remote_heads) {
                struct ref *tmp_refs;
-               connect_setup(transport, 1, 0);
+               connect_setup(transport, 1);
 
                get_remote_heads(data->fd[0], NULL, 0, &tmp_refs, REF_NORMAL,
                                 NULL, &data->shallow);
@@ -984,11 +665,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
        if (helper) {
                transport_helper_init(ret, helper);
        } else if (starts_with(url, "rsync:")) {
-               transport_check_allowed("rsync");
-               ret->get_refs_list = get_refs_via_rsync;
-               ret->fetch = fetch_objs_via_rsync;
-               ret->push = rsync_transport_push;
-               ret->smart_options = NULL;
+               die("git-over-rsync is no longer supported");
        } else if (url_is_local_not_ssh(url) && is_file(url) && is_bundle(url, 1)) {
                struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
                transport_check_allowed("file");
index 8ebaaf2cae054bcdfea491fc464f8bf3180b1e03..c68140892c6258925104f7dda385e635fcf95e20 100644 (file)
@@ -18,6 +18,12 @@ struct git_transport_options {
        struct push_cas_option *cas;
 };
 
+enum transport_family {
+       TRANSPORT_FAMILY_ALL = 0,
+       TRANSPORT_FAMILY_IPV4,
+       TRANSPORT_FAMILY_IPV6
+};
+
 struct transport {
        struct remote *remote;
        const char *url;
@@ -110,6 +116,8 @@ struct transport {
         * actually turns out to be smart.
         */
        struct git_transport_options *smart_options;
+
+       enum transport_family family;
 };
 
 #define TRANSPORT_PUSH_ALL 1