Merge branch 'mv/merge-ff-tristate'
authorJunio C Hamano <gitster@pobox.com>
Mon, 15 Jul 2013 17:28:34 +0000 (10:28 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 15 Jul 2013 17:28:34 +0000 (10:28 -0700)
The configuration variable "merge.ff" was cleary a tri-state to
choose one from "favor fast-forward when possible", "always create
a merge even when the history could fast-forward" and "do not
create any merge, only update when the history fast-forwards", but
the command line parser did not implement the usual convention of
"last one wins, and command line overrides the configuration"
correctly.

* mv/merge-ff-tristate:
merge: handle --ff/--no-ff/--ff-only as a tri-state option

94 files changed:
.gitignore
.mailmap
Documentation/RelNotes/1.8.3.3.txt
Documentation/RelNotes/1.8.4.txt
Documentation/config.txt
Documentation/diff-options.txt
Documentation/git-am.txt
Documentation/git-clone.txt
Documentation/git-config.txt
Documentation/git-fast-export.txt
Documentation/git-ls-remote.txt
Documentation/git-name-rev.txt
Documentation/git-p4.txt
Documentation/git-pull.txt
Documentation/git-rebase.txt
Documentation/git-remote.txt
Documentation/git-stash.txt
Documentation/git-submodule.txt
Documentation/gitweb.conf.txt
Documentation/glossary-content.txt
Documentation/rev-list-options.txt
Documentation/technical/racy-git.txt
Documentation/urls.txt
Documentation/user-manual.txt
Makefile
builtin/checkout.c
builtin/clone.c
builtin/commit.c
builtin/log.c
builtin/merge.c
builtin/push.c
builtin/reset.c
builtin/rev-list.c
builtin/shortlog.c
builtin/show-branch.c
commit-slab.h [new file with mode: 0644]
commit.c
commit.h
contrib/completion/git-completion.bash
contrib/completion/git-prompt.sh
contrib/mw-to-git/git-remote-mediawiki.perl
diff.c
diffcore-pickaxe.c
dir.c
fetch-pack.c
fixup-builtins [deleted file]
git-am.sh
git-pull.sh
git-rebase--interactive.sh
git-stash.sh
gitweb/gitweb.perl
lockfile.c
log-tree.c
prio-queue.c [new file with mode: 0644]
prio-queue.h [new file with mode: 0644]
remote-curl.c
remote.c
revision.c
revision.h
sha1_name.c
submodule.c
t/README
t/check-non-portable-shell.pl
t/lib-rebase.sh
t/lib-t6000.sh
t/perf/README
t/perf/perf-lib.sh
t/t0000-basic.sh
t/t0009-prio-queue.sh [new file with mode: 0755]
t/t0020-crlf.sh
t/t1512-rev-parse-disambiguation.sh
t/t2012-checkout-last.sh
t/t3010-ls-files-killed-modified.sh
t/t3404-rebase-interactive.sh
t/t3415-rebase-autosquash.sh
t/t3903-stash.sh
t/t4041-diff-submodule-option.sh
t/t4205-log-pretty-formats.sh
t/t5505-remote.sh
t/t5528-push-default.sh
t/t6002-rev-list-bisect.sh
t/t6003-rev-list-topo-order.sh
t/t6006-rev-list-format.sh
t/t7102-reset.sh
t/t7500-commit.sh
t/t7508-status.sh
t/t7512-status-help.sh
t/t9902-completion.sh
t/t9903-bash-prompt.sh
t/test-lib-functions.sh
t/test-lib.sh
t/valgrind/valgrind.sh
test-prio-queue.c [new file with mode: 0644]
wt-status.c
index c0e00eb37bb370ce9deee72468fb419bc25cfd62..efa8db00358772852e637af8758f8f76719dec01 100644 (file)
 /test-mktemp
 /test-parse-options
 /test-path-utils
+/test-prio-queue
 /test-read-cache
 /test-regex
 /test-revision-walking
index 48d7acf013c611d4885cddffdf516bb5d0ea5a86..345cce698a3bfe1575db0f439d2879d3bf9c05b2 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -24,6 +24,7 @@ Eric S. Raymond <esr@thyrsus.com>
 Erik Faye-Lund <kusmabite@gmail.com> <kusmabite@googlemail.com>
 Fredrik Kuivinen <freku045@student.liu.se>
 Frédéric Heitzmann <frederic.heitzmann@gmail.com>
+H. Merijn Brand <h.m.brand@xs4all.nl> H.Merijn Brand <h.m.brand@xs4all.nl>
 H. Peter Anvin <hpa@bonde.sc.orionmulti.com>
 H. Peter Anvin <hpa@tazenda.sc.orionmulti.com>
 H. Peter Anvin <hpa@trantor.hos.anvin.org>
index 58a570ef3dadd5c512bb6b82e805fd531f9ee4c7..04289e793cdee716dfb12cb9115ebb19cb6bbb9c 100644 (file)
@@ -4,8 +4,23 @@ Git v1.8.3.3 Release Notes
 Fixes since v1.8.3.2
 --------------------
 
+ * "gitweb" forgot to clear a global variable $search_regexp upon each
+   request, mistakenly carrying over the previous search to a new one
+   when used as a persistent CGI.
+
+ * The wildmatch engine did not honor WM_CASEFOLD option correctly.
+
+ * "git log -c --follow $path" segfaulted upon hitting the commit that
+   renamed the $path being followed.
+
+ * When a reflog notation is used for implicit "current branch",
+   e.g. "git log @{u}", we did not say which branch and worse said
+   "branch ''" in the error messages.
+
  * Mac OS X does not like to write(2) more than INT_MAX number of
    bytes; work it around by chopping write(2) into smaller pieces.
 
  * Newer MacOS X encourages the programs to compile and link with
    their CommonCrypto, not with OpenSSL.
+
+Also contains various minor documentation updates.
index 5f440b8a6b1ce0d7b0808bffcdc46d3fc9298fac..4250e5a3a90e39cad45d90c9ef836ce2ba04cce8 100644 (file)
@@ -1,11 +1,55 @@
 Git v1.8.4 Release Notes
 ========================
 
+Backward compatibility notes (for Git 2.0)
+------------------------------------------
+
+When "git push [$there]" does not say what to push, we have used the
+traditional "matching" semantics so far (all your branches were sent
+to the remote as long as there already are branches of the same name
+over there).  In Git 2.0, the default will change to the "simple"
+semantics that pushes:
+
+ - only the current branch to the branch with the same name, and only
+   when the current branch is set to integrate with that remote
+   branch, if you are pushing to the same remote as you fetch from; or
+
+ - only the current branch to the branch with the same name, if you
+   are pushing to a remote that is not where you usually fetch from.
+
+Use the user preference configuration variable "push.default" to
+change this.  If you are an old-timer who is used to the "matching"
+semantics, you can set the variable to "matching" to keep the
+traditional behaviour.  If you want to live in the future early, you
+can set it to "simple" today without waiting for Git 2.0.
+
+When "git add -u" (and "git add -A") is run inside a subdirectory and
+does not specify which paths to add on the command line, it
+will operate on the entire tree in Git 2.0 for consistency
+with "git commit -a" and other commands.  There will be no
+mechanism to make plain "git add -u" behave like "git add -u .".
+Current users of "git add -u" (without a pathspec) should start
+training their fingers to explicitly say "git add -u ."
+before Git 2.0 comes.  A warning is issued when these commands are
+run without a pathspec and when you have local changes outside the
+current directory, because the behaviour in Git 2.0 will be different
+from today's version in such a situation.
+
+In Git 2.0, "git add <path>" will behave as "git add -A <path>", so
+that "git add dir/" will notice paths you removed from the directory
+and record the removal.  Versions before Git 2.0, including this
+release, will keep ignoring removals, but the users who rely on this
+behaviour are encouraged to start using "git add --ignore-removal <path>"
+now before 2.0 is released.
+
+
 Updates since v1.8.3
 --------------------
 
 Foreign interfaces, subsystems and ports.
 
+ * "git rebase -i" now honors --strategy and -X options.
+
  * Git-gui has been updated to its 0.18.0 version.
 
  * MediaWiki remote helper (in contrib/) has been updated to use the
@@ -35,6 +79,25 @@ Foreign interfaces, subsystems and ports.
 
 UI, Workflows & Features
 
+ * "gitweb" learned to optionally place extra links that point at the
+   levels higher than the Gitweb pages themselves in the breadcrumbs,
+   so that it can be used as part of a larger installation.
+
+ * "git log --format=" now honors i18n.logoutputencoding configuration
+   variable.
+
+ * The "push.default=simple" mode of "git push" has been updated to
+   behave like "current" without requiring a remote tracking
+   information, when you push to a remote that is different from where
+   you fetch from (i.e. a triangular workflow).
+
+ * Having multiple "fixup!" on a line in the rebase instruction sheet
+   did not work very well with "git rebase -i --autosquash".
+
+ * "git log" learned the "--author-date-order" option, with which the
+   output is topologically sorted and commits in parallel histories
+   are shown intermixed together based on the author timestamp.
+
  * Various subcommands of "git submodule" refused to run from anywhere
    other than the top of the working tree of the superproject, but
    they have been taught to let you run from a subdirectory.
@@ -56,9 +119,9 @@ UI, Workflows & Features
  * On Cygwin, "cygstart" is now recognised as a possible way to start
    a web browser (used in "help -w" and "instaweb" among others).
 
-### * "git status" learned status.branch and status.short configuration
-###   variables to use --branch and --short options by default (override
-###   with --no-branch and --no-short options from the command line).
+ * "git status" learned status.branch and status.short configuration
+   variables to use --branch and --short options by default (override
+   with --no-branch and --no-short options from the command line).
 
  * "git cmd <name>", when <name> happens to be a 40-hex string,
    directly uses the 40-hex string as an object name, even if a ref
@@ -116,6 +179,12 @@ UI, Workflows & Features
 
 Performance, Internal Implementation, etc.
 
+ * The original way to specify remote repository using .git/branches/
+   used to have a nifty feature.  The code to support the feature was
+   still in a function but the caller was changed not to call it 5
+   years ago, breaking that feature and leaving the supporting code
+   unreachable.  The dead code has been removed.
+
  * "git pack-refs" that races with new ref creation or deletion have
    been susceptible to lossage of refs under right conditions, which
    has been tightened up.
@@ -175,6 +244,33 @@ Unless otherwise noted, all the fixes since v1.8.3 in the maintenance
 track are contained in this release (see release notes to them for
 details).
 
+ * "git diff" refused to even show difference when core.safecrlf is
+   set to true (i.e. error out) and there are offending lines in the
+   working tree files.
+   (merge 5430bb2 jc/maint-diff-core-safecrlf later to maint).
+
+ * A test that should have failed but didn't revealed a bug that needs
+   to be corrected.
+   (merge 94d75d1 jc/t1512-fix later to maint).
+
+ * An overlong path to a .git directory may have overflown the
+   temporary path buffer used to create a name for lockfiles.
+   (merge 2fbd4f9 mh/maint-lockfile-overflow later to maint).
+
+ * Invocations of "git checkout" used internally by "git rebase" were
+   counted as "checkout", and affected later "git checkout -" to the
+   the user to an unexpected place.
+   (merge 3bed291 rr/rebase-checkout-reflog later to maint).
+
+ * "git stash save", when your local change turns a tracked file into
+   a directory, has to remove files in that directory in order to
+   revert your working tree to a pristine state.  This will lose
+   untracked files in such a directory, and the command now requires
+   you to "--force" it.
+
+ * The configuration variable column.ui was poorly documented.
+   (merge 5e62cc1 rr/column-doc later to maint).
+
  * "git name-rev --refs=tags/v*" were forbidden, which was a bit
    inconvenient (you had to give a pattern to match refs fully, like
    --refs=refs/tags/v*).
index 1153585aa2e2d19dd41f8cf81465e8b6d858a028..81856dd5a2559149b9dcdf263ed5c3212a07d480 100644 (file)
@@ -934,6 +934,9 @@ column.ui::
        This variable consists of a list of tokens separated by spaces
        or commas:
 +
+These options control when the feature should be enabled
+(defaults to 'never'):
++
 --
 `always`;;
        always show in columns
@@ -941,19 +944,30 @@ column.ui::
        never show in columns
 `auto`;;
        show in columns if the output is to the terminal
+--
++
+These options control layout (defaults to 'column').  Setting any
+of these implies 'always' if none of 'always', 'never', or 'auto' are
+specified.
++
+--
 `column`;;
-       fill columns before rows (default)
+       fill columns before rows
 `row`;;
        fill rows before columns
 `plain`;;
        show in one column
+--
++
+Finally, these options can be combined with a layout option (defaults
+to 'nodense'):
++
+--
 `dense`;;
        make unequal size columns to utilize more space
 `nodense`;;
        make equal size columns
 --
-+
-This option defaults to 'never'.
 
 column.branch::
        Specify whether to output branch listing in `git branch` in columns.
@@ -1830,39 +1844,59 @@ pull.twohead::
        The default merge strategy to use when pulling a single branch.
 
 push.default::
-       Defines the action `git push` should take if no refspec is given
-       on the command line, no refspec is configured in the remote, and
-       no refspec is implied by any of the options given on the command
-       line. Possible values are:
+       Defines the action `git push` should take if no refspec is
+       explicitly given.  Different values are well-suited for
+       specific workflows; for instance, in a purely central workflow
+       (i.e. the fetch source is equal to the push destination),
+       `upstream` is probably what you want.  Possible values are:
 +
 --
-* `nothing` - do not push anything.
-* `matching` - push all branches having the same name in both ends.
-  This is for those who prepare all the branches into a publishable
-  shape and then push them out with a single command.  It is not
-  appropriate for pushing into a repository shared by multiple users,
-  since locally stalled branches will attempt a non-fast forward push
-  if other users updated the branch.
-  +
-  This is currently the default, but Git 2.0 will change the default
-  to `simple`.
-* `upstream` - push the current branch to its upstream branch
-  (`tracking` is a deprecated synonym for this).
-  With this, `git push` will update the same remote ref as the one which
-  is merged by `git pull`, making `push` and `pull` symmetrical.
-  See "branch.<name>.merge" for how to configure the upstream branch.
-* `simple` - like `upstream`, but refuses to push if the upstream
-  branch's name is different from the local one. This is the safest
-  option and is well-suited for beginners. It will become the default
-  in Git 2.0.
-* `current` - push the current branch to a branch of the same name.
---
+
+* `nothing` - do not push anything (error out) unless a refspec is
+  explicitly given. This is primarily meant for people who want to
+  avoid mistakes by always being explicit.
+
+* `current` - push the current branch to update a branch with the same
+  name on the receiving end.  Works in both central and non-central
+  workflows.
+
+* `upstream` - push the current branch back to the branch whose
+  changes are usually integrated into the current branch (which is
+  called `@{upstream}`).  This mode only makes sense if you are
+  pushing to the same repository you would normally pull from
+  (i.e. central workflow).
+
+* `simple` - in centralized workflow, work like `upstream` with an
+  added safety to refuse to push if the upstream branch's name is
+  different from the local one.
++
+When pushing to a remote that is different from the remote you normally
+pull from, work as `current`.  This is the safest option and is suited
+for beginners.
++
+This mode will become the default in Git 2.0.
+
+* `matching` - push all branches having the same name on both ends.
+  This makes the repository you are pushing to remember the set of
+  branches that will be pushed out (e.g. if you always push 'maint'
+  and 'master' there and no other branches, the repository you push
+  to will have these two branches, and your local 'maint' and
+  'master' will be pushed there).
 +
-The `simple`, `current` and `upstream` modes are for those who want to
-push out a single branch after finishing work, even when the other
-branches are not yet ready to be pushed out. If you are working with
-other people to push into the same shared repository, you would want
-to use one of these.
+To use this mode effectively, you have to make sure _all_ the
+branches you would push out are ready to be pushed out before
+running 'git push', as the whole point of this mode is to allow you
+to push all of the branches in one go.  If you usually finish work
+on only one branch and push out the result, while other branches are
+unfinished, this mode is not for you.  Also this mode is not
+suitable for pushing into a shared central repository, as other
+people may add new branches there, or update the tip of existing
+branches outside your control.
++
+This is currently the default, but Git 2.0 will change the default
+to `simple`.
+
+--
 
 rebase.stat::
        Whether to show a diffstat of what changed upstream since the last
@@ -2078,6 +2112,14 @@ status.relativePaths::
        relative to the repository root (this was the default for Git
        prior to v1.5.4).
 
+status.short::
+       Set to true to enable --short by default in linkgit:git-status[1].
+       The option --no-short takes precedence over this variable.
+
+status.branch::
+       Set to true to enable --branch by default in linkgit:git-status[1].
+       The option --no-branch takes precedence over this variable.
+
 status.showUntrackedFiles::
        By default, linkgit:git-status[1] and linkgit:git-commit[1] show
        files which are not currently tracked by Git. Directories which
index 19f78a7d5cca0c4a08681605d31a57158a869298..87e92d6537a097a172d37b5893dd4c8c092a2368 100644 (file)
@@ -333,7 +333,7 @@ endif::git-log[]
        a fraction, with a decimal point before it.  I.e., `-M5` becomes
        0.5, and is thus the same as `-M50%`.  Similarly, `-M05` is
        the same as `-M5%`.  To limit detection to exact renames, use
-       `-M100%`.
+       `-M100%`.  The default similarity index is 50%.
 
 -C[<n>]::
 --find-copies[=<n>]::
index 5bbe7b6d10de652658871048329c5dd60f1e12e0..54d8461d61b2f2ad5dbf5ce8c9106534d1a74289 100644 (file)
@@ -132,7 +132,7 @@ default.   You can use `--no-utf8` to override this.
 --resolvemsg=<msg>::
        When a patch failure occurs, <msg> will be printed
        to the screen before exiting.  This overrides the
-       standard message informing you to use `--resolved`
+       standard message informing you to use `--continue`
        or `--skip` to handle the failure.  This is solely
        for internal use between 'git rebase' and 'git am'.
 
@@ -176,7 +176,7 @@ aborts in the middle.  You can recover from this in one of two ways:
 
 . hand resolve the conflict in the working directory, and update
   the index file to bring it into a state that the patch should
-  have produced.  Then run the command with the '--resolved' option.
+  have produced.  Then run the command with the '--continue' option.
 
 The command refuses to process new mailboxes until the current
 operation is finished, so if you decide to start over from scratch,
index a0727d7759aefef4dede0fb40008b7b1ee957b2d..85769b884e0f018c68fc0393d77b167a09d3ef44 100644 (file)
@@ -182,11 +182,13 @@ objects from the source repository into a pack in the cloned repository.
 --depth <depth>::
        Create a 'shallow' clone with a history truncated to the
        specified number of revisions.  A shallow repository has a
-       number of limitations (you cannot clone or fetch from
-       it, nor push from nor into it), but is adequate if you
-       are only interested in the recent history of a large project
-       with a long history, and would want to send in fixes
-       as patches.
+       number of limitations (you cannot clone or fetch from it, nor
+       push into it), but is adequate if you are only interested in
+       the recent history of a large project with a long history.
++
+Pushing from a shallow clone should be avoided if the git version on
+the receiver end is older than v1.7.10, or any other git
+implementation that does not perform connectivity check.
 
 --[no-]single-branch::
        Clone only the history leading to the tip of a single branch,
@@ -239,8 +241,8 @@ Examples
 * Clone from upstream:
 +
 ------------
-$ git clone git://git.kernel.org/pub/scm/.../linux-2.6 my2.6
-$ cd my2.6
+$ git clone git://git.kernel.org/pub/scm/.../linux.git my-linux
+$ cd my-linux
 $ make
 ------------
 
@@ -257,10 +259,10 @@ $ git show-branch
 * Clone from upstream while borrowing from an existing local directory:
 +
 ------------
-$ git clone --reference my2.6 \
-       git://git.kernel.org/pub/scm/.../linux-2.7 \
-       my2.7
-$ cd my2.7
+$ git clone --reference /git/linux.git \
+       git://git.kernel.org/pub/scm/.../linux.git \
+       my-linux
+$ cd my-linux
 ------------
 
 
@@ -271,13 +273,6 @@ $ git clone --bare -l /home/proj/.git /pub/scm/proj.git
 ------------
 
 
-* Create a repository on the kernel.org machine that borrows from Linus:
-+
-------------
-$ git clone --bare -l -s /pub/scm/.../torvalds/linux-2.6.git \
-    /pub/scm/.../me/subsys-2.6.git
-------------
-
 GIT
 ---
 Part of the linkgit:git[1] suite
index 19a7be085693f7f9386fd3856fa38ebeed364f99..99dc497b6f25243dbe01ce47d6e53ec6952d1737 100644 (file)
@@ -82,7 +82,7 @@ OPTIONS
 --get::
        Get the value for a given key (optionally filtered by a regex
        matching the value). Returns error code 1 if the key was not
-       found and error code 2 if multiple key values were found.
+       found and the last value if multiple key values were found.
 
 --get-all::
        Like get, but does not fail if the number of values for the key
@@ -206,12 +206,8 @@ FILES
 If not set explicitly with '--file', there are four files where
 'git config' will search for configuration options:
 
-$GIT_DIR/config::
-       Repository specific configuration file.
-
-~/.gitconfig::
-       User-specific configuration file. Also called "global"
-       configuration file.
+$(prefix)/etc/gitconfig::
+       System-wide configuration file.
 
 $XDG_CONFIG_HOME/git/config::
        Second user-specific configuration file. If $XDG_CONFIG_HOME is not set
@@ -221,8 +217,12 @@ $XDG_CONFIG_HOME/git/config::
        you sometimes use older versions of Git, as support for this
        file was added fairly recently.
 
-$(prefix)/etc/gitconfig::
-       System-wide configuration file.
+~/.gitconfig::
+       User-specific configuration file. Also called "global"
+       configuration file.
+
+$GIT_DIR/config::
+       Repository specific configuration file.
 
 If no further options are given, all reading options will read all of these
 files that are available. If the global or the system-wide configuration
@@ -230,6 +230,10 @@ file are not available they will be ignored. If the repository configuration
 file is not available or readable, 'git config' will exit with a non-zero
 error code. However, in neither case will an error message be issued.
 
+The files are read in the order given above, with last value found taking
+precedence over values read earlier.  When multiple values are taken then all
+values of a key from all files will be used.
+
 All writing options will per default write to the repository specific
 configuration file. Note that this also affects options like '--replace-all'
 and '--unset'. *'git config' will only ever change one file at a time*.
index efb03806f507789877219f87217841d6deb5cd26..85f1f30fdf5c0a741c3c575bfa393fc7d88d308f 100644 (file)
@@ -141,7 +141,7 @@ Limitations
 -----------
 
 Since 'git fast-import' cannot tag trees, you will not be
-able to export the linux-2.6.git repository completely, as it contains
+able to export the linux.git repository completely, as it contains
 a tag referencing a tree instead of a commit.
 
 GIT
index 774de5e9d9fc2d4d88e4f820be177ea6c0a09360..2e22915eb857bd960f09afc725107198642bfd22 100644 (file)
@@ -48,9 +48,9 @@ OPTIONS
        exit without talking to the remote.
 
 <repository>::
-       Location of the repository.  The shorthand defined in
-       $GIT_DIR/branches/ can be used. Use "." (dot) to list references in
-       the local repository.
+       The "remote" repository to query.  This parameter can be
+       either a URL or the name of a remote (see the GIT URLS and
+       REMOTES sections of linkgit:git-fetch[1]).
 
 <refs>...::
        When unspecified, all references, after filtering done
@@ -70,9 +70,8 @@ EXAMPLES
        $ git ls-remote http://www.kernel.org/pub/scm/git/git.git master pu rc
        5fe978a5381f1fbad26a80e682ddd2a401966740        refs/heads/master
        c781a84b5204fb294c9ccc79f8b3baceeb32c061        refs/heads/pu
-       b1d096f2926c4e37c9c0b6a7bf2119bedaa277cb        refs/heads/rc
-       $ echo http://www.kernel.org/pub/scm/git/git.git >.git/branches/public
-       $ git ls-remote --tags public v\*
+       $ git remote add korg http://www.kernel.org/pub/scm/git/git.git
+       $ git ls-remote --tags korg v\*
        d6602ec5194c87b0fc87103ca4d67251c76f233a        refs/tags/v0.99
        f25a265a342aed6041ab0cc484224d9ca54b6f41        refs/tags/v0.99.1
        c5db5456ae3b0873fc659c19fafdde22313cc441        refs/tags/v0.99.2
index 6b0f1ba75fc98dedf7b940355274ad25d3b458c5..15b00e09916fff47a8244432ce396c9b6f7fbec1 100644 (file)
@@ -32,8 +32,10 @@ OPTIONS
        List all commits reachable from all refs
 
 --stdin::
-       Read from stdin, append "(<rev_name>)" to all sha1's of nameable
-       commits, and pass to stdout
+       Transform stdin by substituting all the 40-character SHA-1
+       hexes (say $hex) with "$hex ($rev_name)".  When used with
+       --name-only, substitute with "$rev_name", omitting $hex
+       altogether.  Intended for the scripter's use.
 
 --name-only::
        Instead of printing both the SHA-1 and the name, print only
index c579fbc2b858d0a6fb5cd8dcbcaa25d3b3fca2a5..8cba16d67f29ec48738b00a607add4a20bc7d4b2 100644 (file)
@@ -176,13 +176,16 @@ Sync options
 These options can be used in the initial 'clone' as well as in
 subsequent 'sync' operations.
 
---branch <branch>::
-       Import changes into given branch.  If the branch starts with
-       'refs/', it will be used as is.  Otherwise if it does not start
-       with 'p4/', that prefix is added.  The branch is assumed to
-       name a remote tracking, but this can be modified using
-       '--import-local', or by giving a full ref name.  The default
-       branch is 'master'.
+--branch <ref>::
+       Import changes into <ref> instead of refs/remotes/p4/master.
+       If <ref> starts with refs/, it is used as is.  Otherwise, if
+       it does not start with p4/, that prefix is added.
++
+By default a <ref> not starting with refs/ is treated as the
+name of a remote-tracking branch (under refs/remotes/).  This
+behavior can be modified using the --import-local option.
++
+The default <ref> is "master".
 +
 This example imports a new remote "p4/proj2" into an existing
 Git repository:
index 24ab07a3f8f80c56cbbd7feffc1b5bf65e137968..6ef8d599d31ac20982fa74f213b81494ceae162a 100644 (file)
@@ -3,7 +3,7 @@ git-pull(1)
 
 NAME
 ----
-git-pull - Fetch from and merge with another repository or a local branch
+git-pull - Fetch from and integrate with another repository or a local branch
 
 
 SYNOPSIS
index c84854ae87df094683600c559e88c13a8b770e01..6b2e1c86ab6c1084421e06b5f677264dc4099b6a 100644 (file)
@@ -389,7 +389,9 @@ squash/fixup series.
        the same ..., automatically modify the todo list of rebase -i
        so that the commit marked for squashing comes right after the
        commit to be modified, and change the action of the moved
-       commit from `pick` to `squash` (or `fixup`).
+       commit from `pick` to `squash` (or `fixup`).  Ignores subsequent
+       "fixup! " or "squash! " after the first, in case you referred to an
+       earlier fixup/squash with `git commit --fixup/--squash`.
 +
 This option is only valid when the '--interactive' option is used.
 +
index 581bb4c413fb70956430bb7359bbee3bbc1a24e6..9c3e3bf83a2721678a2c7a430ec88bee0d39dd0a 100644 (file)
@@ -187,18 +187,25 @@ Examples
 $ git remote
 origin
 $ git branch -r
-origin/master
-$ git remote add linux-nfs git://linux-nfs.org/pub/linux/nfs-2.6.git
+  origin/HEAD -> origin/master
+  origin/master
+$ git remote add staging git://git.kernel.org/.../gregkh/staging.git
 $ git remote
-linux-nfs
 origin
-$ git fetch
-* refs/remotes/linux-nfs/master: storing branch 'master' ...
-  commit: bf81b46
+staging
+$ git fetch staging
+...
+From git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging
+ * [new branch]      master     -> staging/master
+ * [new branch]      staging-linus -> staging/staging-linus
+ * [new branch]      staging-next -> staging/staging-next
 $ git branch -r
-origin/master
-linux-nfs/master
-$ git checkout -b nfs linux-nfs/master
+  origin/HEAD -> origin/master
+  origin/master
+  staging/master
+  staging/staging-linus
+  staging/staging-next
+$ git checkout -b staging staging/master
 ...
 ------------
 
index db7e803038090510609a6534ab7d086245c15270..7c8b648fbe8f76d523f781699447586c838b12fc 100644 (file)
@@ -14,7 +14,8 @@ SYNOPSIS
 'git stash' ( pop | apply ) [--index] [-q|--quiet] [<stash>]
 'git stash' branch <branchname> [<stash>]
 'git stash' [save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
-            [-u|--include-untracked] [-a|--all] [<message>]]
+            [-u|--include-untracked] [-a|--all] [-f|--force]
+            [<message>]]
 'git stash' clear
 'git stash' create [<message>]
 'git stash' store [-m|--message <message>] [-q|--quiet] <commit>
@@ -44,7 +45,7 @@ is also possible).
 OPTIONS
 -------
 
-save [-p|--patch] [--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [<message>]::
+save [-p|--patch] [--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [-f|--force] [<message>]::
 
        Save your local modifications to a new 'stash', and run `git reset
        --hard` to revert them.  The <message> part is optional and gives
@@ -71,6 +72,13 @@ linkgit:git-add[1] to learn how to operate the `--patch` mode.
 +
 The `--patch` option implies `--keep-index`.  You can use
 `--no-keep-index` to override this.
++
+In some cases, saving a stash could mean irretrievably removing some
+data - if a directory with untracked files replaces a tracked file of
+the same name, the new untracked files are not saved (except in case
+of `--include-untracked`) but the original tracked file shall be restored.
+By default, `stash save` will abort in such a case; `--force` will allow
+it to remove the untracked files.
 
 list [<options>]::
 
index e5767134b1a2a84c284e87c900948e4530b25576..bfff09062d028dc038f0926042f651084c1395d6 100644 (file)
@@ -262,7 +262,7 @@ OPTIONS
 --remote::
        This option is only valid for the update command.  Instead of using
        the superproject's recorded SHA-1 to update the submodule, use the
-       status of the submodule's remote tracking branch.  The remote used
+       status of the submodule's remote-tracking branch.  The remote used
        is branch's remote (`branch.<name>.remote`), defaulting to `origin`.
        The remote branch used defaults to `master`, but the branch name may
        be overridden by setting the `submodule.<name>.branch` option in
index ea0526ecc4019802b7088316cba9aed401fa6ee8..305db633ccb1165e819a1061e8ec8b60e33e9eed 100644 (file)
@@ -336,8 +336,26 @@ $home_link_str::
        used as the first component of gitweb's "breadcrumb trail":
        `<home link> / <project> / <action>`.  Can be set at build time using
        the `GITWEB_HOME_LINK_STR` variable.  By default it is set to "projects",
-       as this link leads to the list of projects.  Other popular choice it to
-       set it to the name of site.
+       as this link leads to the list of projects.  Another popular choice is to
+       set it to the name of site.  Note that it is treated as raw HTML so it
+       should not be set from untrusted sources.
+
+@extra_breadcrumbs::
+       Additional links to be added to the start of the breadcrumb trail before
+       the home link, to pages that are logically "above" the gitweb projects
+       list, such as the organization and department which host the gitweb
+       server. Each element of the list is a reference to an array, in which
+       element 0 is the link text (equivalent to `$home_link_str`) and element
+       1 is the target URL (equivalent to `$home_link`).
++
+For example, the following setting produces a breadcrumb trail like
+"home / dev / projects / ..." where "projects" is the home link.
+----------------------------------------------------------------------------
+    our @extra_breadcrumbs = (
+      [ 'home' => 'https://www.example.org/' ],
+      [ 'dev'  => 'https://dev.example.org/' ],
+    );
+----------------------------------------------------------------------------
 
 $logo_url::
 $logo_label::
index db2a74df934f3acd93521e42510b6cd00c9eed6f..dba5062b379cdfcdde31ee0f6809e964f979b5f5 100644 (file)
@@ -113,7 +113,7 @@ Note that commands that operate on the history of the current branch
 while the HEAD is detached. They update the HEAD to point at the tip
 of the updated history without affecting any branch.  Commands that
 update or inquire information _about_ the current branch (e.g. `git
-branch --set-upstream-to` that sets what remote tracking branch the
+branch --set-upstream-to` that sets what remote-tracking branch the
 current branch integrates with) obviously do not work, as there is no
 (real) current branch to ask about in this state.
 
@@ -267,7 +267,7 @@ This commit is referred to as a "merge commit", or sometimes just a
        The default upstream <<def_repository,repository>>. Most projects have
        at least one upstream project which they track. By default
        'origin' is used for that purpose. New upstream updates
-       will be fetched into remote <<def_remote_tracking_branch,remote-tracking branches>> named
+       will be fetched into <<def_remote_tracking_branch,remote-tracking branches>> named
        origin/name-of-upstream-branch, which you can see using
        `git branch -r`.
 
index b462f17f62d4c0066b1178b405b011963643cdd9..e157ec3fe7e6bc72e271337f6cb0b4c1d791a2eb 100644 (file)
@@ -625,6 +625,10 @@ By default, the commits are shown in reverse chronological order.
        Show no parents before all of its children are shown, but
        otherwise show commits in the commit timestamp order.
 
+--author-date-order::
+       Show no parents before all of its children are shown, but
+       otherwise show commits in the author timestamp order.
+
 --topo-order::
        Show no parents before all of its children are shown, and
        avoid showing commits on multiple lines of history
index 6dc82ca5a8a8b744fad1aad6ee7578c3b02495d1..f716d6d97f1cbb66b36a1e06ec2c268abf0a5ed1 100644 (file)
@@ -135,9 +135,9 @@ them, and give the same timestamp to the index file:
   $ git ls-files | git update-index --stdin
   $ touch -r .datestamp .git/index
 
-This will make all index entries racily clean.  The linux-2.6
-project, for example, there are over 20,000 files in the working
-tree.  On my Athlon 64 X2 3800+, after the above:
+This will make all index entries racily clean.  The linux project, for
+example, there are over 20,000 files in the working tree.  On my
+Athlon 64 X2 3800+, after the above:
 
   $ /usr/bin/time git diff-files
   1.68user 0.54system 0:02.22elapsed 100%CPU (0avgtext+0avgdata 0maxresident)k
index 5e185f87c20a2124a7fb9bf2046f6035942b4f92..9ccb24677e95b8aff605c9020bc7a0537e23f751 100644 (file)
@@ -11,6 +11,9 @@ 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).
 
+The native transport (i.e. git:// URL) does no authentication and
+should be used with caution on unsecured networks.
+
 The following syntaxes may be used with them:
 
 - ssh://{startsb}user@{endsb}host.xz{startsb}:port{endsb}/path/to/repo.git/
index 644acce079df81ecd7c2cf8774b3e7fcba9c49d5..e364007d7c2e5f9b1aa5472c7968cb248eb8cf3f 100644 (file)
@@ -66,8 +66,8 @@ $ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
 The initial clone may be time-consuming for a large project, but you
 will only need to clone once.
 
-The clone command creates a new directory named after the project (`git`
-or `linux-2.6` in the examples above).  After you cd into this
+The clone command creates a new directory named after the project
+(`git` or `linux` in the examples above).  After you cd into this
 directory, you will see that it contains a copy of the project files,
 called the <<def_working_tree,working tree>>, together with a special
 top-level directory named `.git`, which contains all the information
@@ -431,19 +431,25 @@ You can also track branches from repositories other than the one you
 cloned from, using linkgit:git-remote[1]:
 
 -------------------------------------------------
-$ git remote add linux-nfs git://linux-nfs.org/pub/nfs-2.6.git
-$ git fetch linux-nfs
-* refs/remotes/linux-nfs/master: storing branch 'master' ...
-  commit: bf81b46
+$ git remote add staging git://git.kernel.org/.../gregkh/staging.git
+$ git fetch staging
+...
+From git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging
+ * [new branch]      master     -> staging/master
+ * [new branch]      staging-linus -> staging/staging-linus
+ * [new branch]      staging-next -> staging/staging-next
 -------------------------------------------------
 
 New remote-tracking branches will be stored under the shorthand name
-that you gave `git remote add`, in this case `linux-nfs`:
+that you gave `git remote add`, in this case `staging`:
 
 -------------------------------------------------
 $ git branch -r
-linux-nfs/master
-origin/master
+  origin/HEAD -> origin/master
+  origin/master
+  staging/master
+  staging/staging-linus
+  staging/staging-next
 -------------------------------------------------
 
 If you run `git fetch <remote>` later, the remote-tracking branches
@@ -455,9 +461,9 @@ a new stanza:
 -------------------------------------------------
 $ cat .git/config
 ...
-[remote "linux-nfs"]
-       url = git://linux-nfs.org/pub/nfs-2.6.git
-       fetch = +refs/heads/*:refs/remotes/linux-nfs/*
+[remote "staging"]
+       url = git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
+       fetch = +refs/heads/*:refs/remotes/staging/*
 ...
 -------------------------------------------------
 
@@ -1835,7 +1841,7 @@ Once the index is updated with the results of the conflict
 resolution, instead of creating a new commit, just run
 
 -------------------------------------------------
-$ git am --resolved
+$ git am --continue
 -------------------------------------------------
 
 and Git will create the commit for you and continue applying the
@@ -2156,7 +2162,7 @@ To set this up, first create your work tree by cloning Linus's public
 tree:
 
 -------------------------------------------------
-$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git work
+$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git work
 $ cd work
 -------------------------------------------------
 
@@ -2198,7 +2204,7 @@ make it easy to push both branches to your public tree.  (See
 -------------------------------------------------
 $ cat >> .git/config <<EOF
 [remote "mytree"]
-       url =  master.kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git
+       url =  master.kernel.org:/pub/scm/linux/kernel/git/aegl/linux.git
        push = release
        push = test
 EOF
index e1583761dfa58c3ede93b2076e4aa0963f2aa379..0600eb46db487c88e24dc3b4089db062ad6350ac 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -569,6 +569,7 @@ TEST_PROGRAMS_NEED_X += test-mergesort
 TEST_PROGRAMS_NEED_X += test-mktemp
 TEST_PROGRAMS_NEED_X += test-parse-options
 TEST_PROGRAMS_NEED_X += test-path-utils
+TEST_PROGRAMS_NEED_X += test-prio-queue
 TEST_PROGRAMS_NEED_X += test-read-cache
 TEST_PROGRAMS_NEED_X += test-regex
 TEST_PROGRAMS_NEED_X += test-revision-walking
@@ -705,6 +706,7 @@ LIB_H += parse-options.h
 LIB_H += patch-ids.h
 LIB_H += pathspec.h
 LIB_H += pkt-line.h
+LIB_H += prio-queue.h
 LIB_H += progress.h
 LIB_H += prompt.h
 LIB_H += quote.h
@@ -846,6 +848,7 @@ LIB_OBJS += pathspec.o
 LIB_OBJS += pkt-line.o
 LIB_OBJS += preload-index.o
 LIB_OBJS += pretty.o
+LIB_OBJS += prio-queue.o
 LIB_OBJS += progress.o
 LIB_OBJS += prompt.o
 LIB_OBJS += quote.o
@@ -2302,9 +2305,6 @@ check: common-cmds.h
                exit 1; \
        fi
 
-remove-dashes:
-       ./fixup-builtins $(BUILT_INS) $(PROGRAMS) $(SCRIPTS)
-
 ### Installation rules
 
 ifneq ($(filter /%,$(firstword $(template_dir))),)
index 3be00188216f503ea1f9269acd312aebdb72a0fa..7fe0bffaf8b875b40b5e4e0e5c207f978c932691 100644 (file)
@@ -587,7 +587,7 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
                                   struct branch_info *new)
 {
        struct strbuf msg = STRBUF_INIT;
-       const char *old_desc;
+       const char *old_desc, *reflog_msg;
        if (opts->new_branch) {
                if (opts->new_orphan_branch) {
                        if (opts->new_branch_log && !log_all_ref_updates) {
@@ -620,8 +620,13 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
        old_desc = old->name;
        if (!old_desc && old->commit)
                old_desc = sha1_to_hex(old->commit->object.sha1);
-       strbuf_addf(&msg, "checkout: moving from %s to %s",
-                   old_desc ? old_desc : "(invalid)", new->name);
+
+       reflog_msg = getenv("GIT_REFLOG_ACTION");
+       if (!reflog_msg)
+               strbuf_addf(&msg, "checkout: moving from %s to %s",
+                       old_desc ? old_desc : "(invalid)", new->name);
+       else
+               strbuf_insert(&msg, 0, reflog_msg, strlen(reflog_msg));
 
        if (!strcmp(new->name, "HEAD") && !new->path && !opts->force_detach) {
                /* Nothing to do. */
index 14b13235682add18daf625295d746ca5dea7ebcc..17f57cdf29a4c74550795ce3f711fbfc57bf38b3 100644 (file)
@@ -701,7 +701,7 @@ static void write_refspec_config(const char* src_ref_prefix,
                        /*
                         * otherwise, the next "git fetch" will
                         * simply fetch from HEAD without updating
-                        * any remote tracking branch, which is what
+                        * any remote-tracking branch, which is what
                         * we want.
                         */
                } else {
index 6b693c16d8842b70b0e1c7bd7df5095947ed0a64..790e5ab5cfee7b0f5760aafed7bf6f3f5927871e 100644 (file)
@@ -112,12 +112,14 @@ static int show_ignored_in_status, have_option_m;
 static const char *only_include_assumed;
 static struct strbuf message = STRBUF_INIT;
 
-static enum {
+static enum status_format {
        STATUS_FORMAT_NONE = 0,
        STATUS_FORMAT_LONG,
        STATUS_FORMAT_SHORT,
-       STATUS_FORMAT_PORCELAIN
-} status_format;
+       STATUS_FORMAT_PORCELAIN,
+
+       STATUS_FORMAT_UNSPECIFIED
+} status_format = STATUS_FORMAT_UNSPECIFIED;
 
 static int opt_parse_m(const struct option *opt, const char *arg, int unset)
 {
@@ -460,6 +462,9 @@ static int run_status(FILE *fp, const char *index_file, const char *prefix, int
        case STATUS_FORMAT_PORCELAIN:
                wt_porcelain_print(s);
                break;
+       case STATUS_FORMAT_UNSPECIFIED:
+               die("BUG: finalize_deferred_config() should have been called");
+               break;
        case STATUS_FORMAT_NONE:
        case STATUS_FORMAT_LONG:
                wt_status_print(s);
@@ -961,6 +966,42 @@ static const char *read_commit_message(const char *name)
        return logmsg_reencode(commit, NULL, out_enc);
 }
 
+/*
+ * Enumerate what needs to be propagated when --porcelain
+ * is not in effect here.
+ */
+static struct status_deferred_config {
+       enum status_format status_format;
+       int show_branch;
+} status_deferred_config = {
+       STATUS_FORMAT_UNSPECIFIED,
+       -1 /* unspecified */
+};
+
+static void finalize_deferred_config(struct wt_status *s)
+{
+       int use_deferred_config = (status_format != STATUS_FORMAT_PORCELAIN &&
+                                  !s->null_termination);
+
+       if (s->null_termination) {
+               if (status_format == STATUS_FORMAT_NONE ||
+                   status_format == STATUS_FORMAT_UNSPECIFIED)
+                       status_format = STATUS_FORMAT_PORCELAIN;
+               else if (status_format == STATUS_FORMAT_LONG)
+                       die(_("--long and -z are incompatible"));
+       }
+
+       if (use_deferred_config && status_format == STATUS_FORMAT_UNSPECIFIED)
+               status_format = status_deferred_config.status_format;
+       if (status_format == STATUS_FORMAT_UNSPECIFIED)
+               status_format = STATUS_FORMAT_NONE;
+
+       if (use_deferred_config && s->show_branch < 0)
+               s->show_branch = status_deferred_config.show_branch;
+       if (s->show_branch < 0)
+               s->show_branch = 0;
+}
+
 static int parse_and_validate_options(int argc, const char *argv[],
                                      const struct option *options,
                                      const char * const usage[],
@@ -971,6 +1012,7 @@ static int parse_and_validate_options(int argc, const char *argv[],
        int f = 0;
 
        argc = parse_options(argc, argv, prefix, options, usage, 0);
+       finalize_deferred_config(s);
 
        if (force_author && !strchr(force_author, '>'))
                force_author = find_author_by_nickname(force_author);
@@ -1055,12 +1097,6 @@ static int parse_and_validate_options(int argc, const char *argv[],
        if (all && argc > 0)
                die(_("Paths with -a does not make sense."));
 
-       if (s->null_termination) {
-               if (status_format == STATUS_FORMAT_NONE)
-                       status_format = STATUS_FORMAT_PORCELAIN;
-               else if (status_format == STATUS_FORMAT_LONG)
-                       die(_("--long and -z are incompatible"));
-       }
        if (status_format != STATUS_FORMAT_NONE)
                dry_run = 1;
 
@@ -1113,6 +1149,17 @@ static int git_status_config(const char *k, const char *v, void *cb)
                        s->submodule_summary = -1;
                return 0;
        }
+       if (!strcmp(k, "status.short")) {
+               if (git_config_bool(k, v))
+                       status_deferred_config.status_format = STATUS_FORMAT_SHORT;
+               else
+                       status_deferred_config.status_format = STATUS_FORMAT_NONE;
+               return 0;
+       }
+       if (!strcmp(k, "status.branch")) {
+               status_deferred_config.show_branch = git_config_bool(k, v);
+               return 0;
+       }
        if (!strcmp(k, "status.color") || !strcmp(k, "color.status")) {
                s->use_color = git_config_colorbool(k, v);
                return 0;
@@ -1155,8 +1202,8 @@ int cmd_status(int argc, const char **argv, const char *prefix)
                OPT__VERBOSE(&verbose, N_("be verbose")),
                OPT_SET_INT('s', "short", &status_format,
                            N_("show status concisely"), STATUS_FORMAT_SHORT),
-               OPT_BOOLEAN('b', "branch", &s.show_branch,
-                           N_("show branch information")),
+               OPT_BOOL('b', "branch", &s.show_branch,
+                        N_("show branch information")),
                OPT_SET_INT(0, "porcelain", &status_format,
                            N_("machine-readable output"),
                            STATUS_FORMAT_PORCELAIN),
@@ -1189,13 +1236,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
                             builtin_status_options,
                             builtin_status_usage, 0);
        finalize_colopts(&s.colopts, -1);
-
-       if (s.null_termination) {
-               if (status_format == STATUS_FORMAT_NONE)
-                       status_format = STATUS_FORMAT_PORCELAIN;
-               else if (status_format == STATUS_FORMAT_LONG)
-                       die(_("--long and -z are incompatible"));
-       }
+       finalize_deferred_config(&s);
 
        handle_untracked_files_arg(&s);
        if (show_ignored_in_status)
@@ -1224,6 +1265,9 @@ int cmd_status(int argc, const char **argv, const char *prefix)
        case STATUS_FORMAT_PORCELAIN:
                wt_porcelain_print(&s);
                break;
+       case STATUS_FORMAT_UNSPECIFIED:
+               die("BUG: finalize_deferred_config() should have been called");
+               break;
        case STATUS_FORMAT_NONE:
        case STATUS_FORMAT_LONG:
                s.verbose = verbose;
@@ -1392,7 +1436,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
                OPT_BOOLEAN(0, "dry-run", &dry_run, N_("show what would be committed")),
                OPT_SET_INT(0, "short", &status_format, N_("show status concisely"),
                            STATUS_FORMAT_SHORT),
-               OPT_BOOLEAN(0, "branch", &s.show_branch, N_("show branch information")),
+               OPT_BOOL(0, "branch", &s.show_branch, N_("show branch information")),
                OPT_SET_INT(0, "porcelain", &status_format,
                            N_("machine-readable output"), STATUS_FORMAT_PORCELAIN),
                OPT_SET_INT(0, "long", &status_format,
@@ -1433,6 +1477,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
        wt_status_prepare(&s);
        gitmodules_config();
        git_config(git_commit_config, &s);
+       status_format = STATUS_FORMAT_NONE; /* Ignore status.short */
        determine_whence(&s);
        s.colopts = 0;
 
index 9e2123295ffa80ecab83977099ed6a43fd4a93f9..e3222ed9f979e3140cbfc88ad2839c573c89bf06 100644 (file)
@@ -237,7 +237,7 @@ static void log_show_early(struct rev_info *revs, struct commit_list *list)
        int i = revs->early_output;
        int show_header = 1;
 
-       sort_in_topological_order(&list, revs->lifo);
+       sort_in_topological_order(&list, revs->sort_order);
        while (list && i) {
                struct commit *commit = list->item;
                switch (simplify_commit(revs, commit)) {
index 149f32afb6eede8b65d1eed9f5def9237e0a908a..9505e7e426d302522f5e065d741fccd37290ea21 100644 (file)
@@ -962,7 +962,7 @@ static int evaluate_result(void)
 }
 
 /*
- * Pretend as if the user told us to merge with the tracking
+ * Pretend as if the user told us to merge with the remote-tracking
  * branch we have for the upstream of the current branch
  */
 static int setup_with_upstream(const char ***argv)
@@ -981,7 +981,7 @@ static int setup_with_upstream(const char ***argv)
        args = xcalloc(branch->merge_nr + 1, sizeof(char *));
        for (i = 0; i < branch->merge_nr; i++) {
                if (!branch->merge[i]->dst)
-                       die(_("No remote tracking branch for %s from %s"),
+                       die(_("No remote-tracking branch for %s from %s"),
                            branch->merge[i]->src, branch->remote_name);
                args[i] = branch->merge[i]->dst;
        }
index 2d84d10720fad88becdfe957f3770a2c44ac0a8f..6d36c24268bea3cb658a1aa94f3a037f403d5895 100644 (file)
@@ -120,10 +120,11 @@ static const char message_detached_head_die[] =
           "\n"
           "    git push %s HEAD:<name-of-remote-branch>\n");
 
-static void setup_push_upstream(struct remote *remote, int simple)
+static void setup_push_upstream(struct remote *remote, struct branch *branch,
+                               int triangular)
 {
        struct strbuf refspec = STRBUF_INIT;
-       struct branch *branch = branch_get(NULL);
+
        if (!branch)
                die(_(message_detached_head_die), remote->name);
        if (!branch->merge_nr || !branch->merge || !branch->remote_name)
@@ -137,18 +138,29 @@ static void setup_push_upstream(struct remote *remote, int simple)
        if (branch->merge_nr != 1)
                die(_("The current branch %s has multiple upstream branches, "
                    "refusing to push."), branch->name);
-       if (strcmp(branch->remote_name, remote->name))
+       if (triangular)
                die(_("You are pushing to remote '%s', which is not the upstream of\n"
                      "your current branch '%s', without telling me what to push\n"
                      "to update which remote branch."),
                    remote->name, branch->name);
-       if (simple && strcmp(branch->refname, branch->merge[0]->src))
-               die_push_simple(branch, remote);
+
+       if (push_default == PUSH_DEFAULT_SIMPLE) {
+               /* Additional safety */
+               if (strcmp(branch->refname, branch->merge[0]->src))
+                       die_push_simple(branch, remote);
+       }
 
        strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src);
        add_refspec(refspec.buf);
 }
 
+static void setup_push_current(struct remote *remote, struct branch *branch)
+{
+       if (!branch)
+               die(_(message_detached_head_die), remote->name);
+       add_refspec(branch->name);
+}
+
 static char warn_unspecified_push_default_msg[] =
 N_("push.default is unset; its implicit value is changing in\n"
    "Git 2.0 from 'matching' to 'simple'. To squelch this message\n"
@@ -173,9 +185,16 @@ static void warn_unspecified_push_default_configuration(void)
        warning("%s\n", _(warn_unspecified_push_default_msg));
 }
 
+static int is_workflow_triangular(struct remote *remote)
+{
+       struct remote *fetch_remote = remote_get(NULL);
+       return (fetch_remote && fetch_remote != remote);
+}
+
 static void setup_default_push_refspecs(struct remote *remote)
 {
-       struct branch *branch;
+       struct branch *branch = branch_get(NULL);
+       int triangular = is_workflow_triangular(remote);
 
        switch (push_default) {
        default:
@@ -188,18 +207,18 @@ static void setup_default_push_refspecs(struct remote *remote)
                break;
 
        case PUSH_DEFAULT_SIMPLE:
-               setup_push_upstream(remote, 1);
+               if (triangular)
+                       setup_push_current(remote, branch);
+               else
+                       setup_push_upstream(remote, branch, triangular);
                break;
 
        case PUSH_DEFAULT_UPSTREAM:
-               setup_push_upstream(remote, 0);
+               setup_push_upstream(remote, branch, triangular);
                break;
 
        case PUSH_DEFAULT_CURRENT:
-               branch = branch_get(NULL);
-               if (!branch)
-                       die(_(message_detached_head_die), remote->name);
-               add_refspec(branch->name);
+               setup_push_current(remote, branch);
                break;
 
        case PUSH_DEFAULT_NOTHING:
@@ -211,8 +230,8 @@ static void setup_default_push_refspecs(struct remote *remote)
 
 static const char message_advice_pull_before_push[] =
        N_("Updates were rejected because the tip of your current branch is behind\n"
-          "its remote counterpart. Merge the remote changes (e.g. 'git pull')\n"
-          "before pushing again.\n"
+          "its remote counterpart. Integrate the remote changes (e.g.\n"
+          "'git pull ...') before pushing again.\n"
           "See the 'Note about fast-forwards' in 'git push --help' for details.");
 
 static const char message_advice_use_upstream[] =
@@ -223,15 +242,15 @@ static const char message_advice_use_upstream[] =
 
 static const char message_advice_checkout_pull_push[] =
        N_("Updates were rejected because a pushed branch tip is behind its remote\n"
-          "counterpart. Check out this branch and merge the remote changes\n"
-          "(e.g. 'git pull') before pushing again.\n"
+          "counterpart. Check out this branch and integrate the remote changes\n"
+          "(e.g. 'git pull ...') before pushing again.\n"
           "See the 'Note about fast-forwards' in 'git push --help' for details.");
 
 static const char message_advice_ref_fetch_first[] =
        N_("Updates were rejected because the remote contains work that you do\n"
           "not have locally. This is usually caused by another repository pushing\n"
-          "to the same ref. You may want to first merge the remote changes (e.g.,\n"
-          "'git pull') before pushing again.\n"
+          "to the same ref. You may want to first integrate the remote changes\n"
+          "(e.g., 'git pull ...') before pushing again.\n"
           "See the 'Note about fast-forwards' in 'git push --help' for details.");
 
 static const char message_advice_ref_already_exists[] =
index 6032131a9087281e97d0abc05365b7485004121b..afa6e020e83ebac739db474c278e44bc22079848 100644 (file)
@@ -93,10 +93,12 @@ static int reset_index(const unsigned char *sha1, int reset_type, int quiet)
 static void print_new_head_line(struct commit *commit)
 {
        const char *hex, *body;
+       char *msg;
 
        hex = find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV);
        printf(_("HEAD is now at %s"), hex);
-       body = strstr(commit->buffer, "\n\n");
+       msg = logmsg_reencode(commit, NULL, get_log_output_encoding());
+       body = strstr(msg, "\n\n");
        if (body) {
                const char *eol;
                size_t len;
@@ -107,6 +109,7 @@ static void print_new_head_line(struct commit *commit)
        }
        else
                printf("\n");
+       logmsg_free(msg, commit);
 }
 
 static void update_index_from_diff(struct diff_queue_struct *q,
index 67701be55193db0fd9733ee7c4962db08072045c..a5ec30d74ee1945ddaf99c89307e59aec714714a 100644 (file)
@@ -111,6 +111,7 @@ static void show_commit(struct commit *commit, void *data)
                ctx.date_mode = revs->date_mode;
                ctx.date_mode_explicit = revs->date_mode_explicit;
                ctx.fmt = revs->commit_format;
+               ctx.output_encoding = get_log_output_encoding();
                pretty_print_commit(&ctx, commit, &buf);
                if (revs->graph) {
                        if (buf.len) {
index 1fd6f8ac5977ee670bf8ba230cec8553393baafd..1434f8fee487751abe069250c611bdaed2fa5857 100644 (file)
@@ -137,6 +137,7 @@ void shortlog_add_commit(struct shortlog *log, struct commit *commit)
                ctx.subject = "";
                ctx.after_subject = "";
                ctx.date_mode = DATE_NORMAL;
+               ctx.output_encoding = get_log_output_encoding();
                pretty_print_commit(&ctx, commit, &ufbuf);
                buffer = ufbuf.buf;
        } else if (*buffer) {
index 90fc6b1b9d2a397ae43dfc4c0aba6bc192c9823c..99ec4af224464f5c6c82599dcc4ca18b6abaa7f7 100644 (file)
@@ -630,7 +630,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
        int num_rev, i, extra = 0;
        int all_heads = 0, all_remotes = 0;
        int all_mask, all_revs;
-       int lifo = 1;
+       enum rev_sort_order sort_order = REV_SORT_IN_GRAPH_ORDER;
        char head[128];
        const char *head_p;
        int head_len;
@@ -665,15 +665,17 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
                            N_("show possible merge bases")),
                OPT_BOOLEAN(0, "independent", &independent,
                            N_("show refs unreachable from any other ref")),
-               OPT_BOOLEAN(0, "topo-order", &lifo,
-                           N_("show commits in topological order")),
+               OPT_SET_INT(0, "topo-order", &sort_order,
+                           N_("show commits in topological order"),
+                           REV_SORT_IN_GRAPH_ORDER),
                OPT_BOOLEAN(0, "topics", &topics,
                            N_("show only commits not on the first branch")),
                OPT_SET_INT(0, "sparse", &dense,
                            N_("show merges reachable from only one tip"), 0),
-               OPT_SET_INT(0, "date-order", &lifo,
+               OPT_SET_INT(0, "date-order", &sort_order,
                            N_("show commits where no parent comes before its "
-                              "children"), 0),
+                              "children"),
+                           REV_SORT_BY_COMMIT_DATE),
                { OPTION_CALLBACK, 'g', "reflog", &reflog_base, N_("<n>[,<base>]"),
                            N_("show <n> most recent ref-log entries starting at "
                               "base"),
@@ -900,7 +902,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
                exit(0);
 
        /* Sort topologically */
-       sort_in_topological_order(&seen, lifo);
+       sort_in_topological_order(&seen, sort_order);
 
        /* Give names to commits */
        if (!sha1_name && !no_name)
diff --git a/commit-slab.h b/commit-slab.h
new file mode 100644 (file)
index 0000000..7d48163
--- /dev/null
@@ -0,0 +1,98 @@
+#ifndef COMMIT_SLAB_H
+#define COMMIT_SLAB_H
+
+/*
+ * define_commit_slab(slabname, elemtype) creates boilerplate code to define
+ * a new struct (struct slabname) that is used to associate a piece of data
+ * of elemtype to commits, and a few functions to use that struct.
+ *
+ * After including this header file, using:
+ *
+ * define_commit_slab(indegee, int);
+ *
+ * will let you call the following functions:
+ *
+ * - int *indegree_at(struct indegree *, struct commit *);
+ *
+ *   This function locates the data associated with the given commit in
+ *   the indegree slab, and returns the pointer to it.
+ *
+ * - void init_indegree(struct indegree *);
+ *   void init_indegree_with_stride(struct indegree *, int);
+ *
+ *   Initializes the indegree slab that associates an array of integers
+ *   to each commit. 'stride' specifies how big each array is.  The slab
+ *   that id initialied by the variant without "_with_stride" associates
+ *   each commit with an array of one integer.
+ */
+
+/* allocate ~512kB at once, allowing for malloc overhead */
+#ifndef COMMIT_SLAB_SIZE
+#define COMMIT_SLAB_SIZE (512*1024-32)
+#endif
+
+#define define_commit_slab(slabname, elemtype)                                 \
+                                                                       \
+struct slabname {                                                      \
+       unsigned slab_size;                                             \
+       unsigned stride;                                                \
+       unsigned slab_count;                                            \
+       elemtype **slab;                                                \
+};                                                                     \
+static int stat_ ##slabname## realloc;                                 \
+                                                                       \
+static void init_ ##slabname## _with_stride(struct slabname *s,                \
+                                           unsigned stride)            \
+{                                                                      \
+       unsigned int elem_size;                                         \
+       if (!stride)                                                    \
+               stride = 1;                                             \
+       s->stride = stride;                                             \
+       elem_size = sizeof(struct slabname) * stride;                   \
+       s->slab_size = COMMIT_SLAB_SIZE / elem_size;                    \
+       s->slab_count = 0;                                              \
+       s->slab = NULL;                                                 \
+}                                                                      \
+                                                                       \
+static void init_ ##slabname(struct slabname *s)                       \
+{                                                                      \
+       init_ ##slabname## _with_stride(s, 1);                          \
+}                                                                      \
+                                                                       \
+static void clear_ ##slabname(struct slabname *s)                      \
+{                                                                      \
+       int i;                                                          \
+       for (i = 0; i < s->slab_count; i++)                             \
+               free(s->slab[i]);                                       \
+       s->slab_count = 0;                                              \
+       free(s->slab);                                                  \
+       s->slab = NULL;                                                 \
+}                                                                      \
+                                                                       \
+static elemtype *slabname## _at(struct slabname *s,                    \
+                               const struct commit *c)                 \
+{                                                                      \
+       int nth_slab, nth_slot, ix;                                     \
+                                                                       \
+       ix = c->index * s->stride;                                      \
+       nth_slab = ix / s->slab_size;                                   \
+       nth_slot = ix % s->slab_size;                                   \
+                                                                       \
+       if (s->slab_count <= nth_slab) {                                \
+               int i;                                                  \
+               s->slab = xrealloc(s->slab,                             \
+                                  (nth_slab + 1) * sizeof(s->slab));   \
+               stat_ ##slabname## realloc++;                           \
+               for (i = s->slab_count; i <= nth_slab; i++)             \
+                       s->slab[i] = NULL;                              \
+               s->slab_count = nth_slab + 1;                           \
+       }                                                               \
+       if (!s->slab[nth_slab])                                         \
+               s->slab[nth_slab] = xcalloc(s->slab_size,               \
+                                           sizeof(**s->slab));         \
+       return &s->slab[nth_slab][nth_slot];                            \
+}                                                                      \
+                                                                       \
+static int stat_ ##slabname## realloc
+
+#endif /* COMMIT_SLAB_H */
index 888e02ae2f65ab566555465e5d88d02bbe52420f..ebc0eeab8f9c1678f3780991a9414f2261215427 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -8,12 +8,15 @@
 #include "notes.h"
 #include "gpg-interface.h"
 #include "mergesort.h"
+#include "commit-slab.h"
+#include "prio-queue.h"
 
 static struct commit_extra_header *read_commit_extra_header_lines(const char *buf, size_t len, const char **);
 
 int save_commit_buffer = 1;
 
 const char *commit_type = "commit";
+static int commit_count;
 
 static struct commit *check_commit(struct object *obj,
                                   const unsigned char *sha1,
@@ -58,8 +61,11 @@ struct commit *lookup_commit_or_die(const unsigned char *sha1, const char *ref_n
 struct commit *lookup_commit(const unsigned char *sha1)
 {
        struct object *obj = lookup_object(sha1);
-       if (!obj)
-               return create_object(sha1, OBJ_COMMIT, alloc_commit_node());
+       if (!obj) {
+               struct commit *c = alloc_commit_node();
+               c->index = commit_count++;
+               return create_object(sha1, OBJ_COMMIT, c);
+       }
        if (!obj->type)
                obj->type = OBJ_COMMIT;
        return check_commit(obj, sha1, 0);
@@ -506,33 +512,137 @@ struct commit *pop_commit(struct commit_list **stack)
        return item;
 }
 
+/*
+ * Topological sort support
+ */
+
+/* count number of children that have not been emitted */
+define_commit_slab(indegree_slab, int);
+
+/* record author-date for each commit object */
+define_commit_slab(author_date_slab, unsigned long);
+
+static void record_author_date(struct author_date_slab *author_date,
+                              struct commit *commit)
+{
+       const char *buf, *line_end;
+       char *buffer = NULL;
+       struct ident_split ident;
+       char *date_end;
+       unsigned long date;
+
+       if (!commit->buffer) {
+               unsigned long size;
+               enum object_type type;
+               buffer = read_sha1_file(commit->object.sha1, &type, &size);
+               if (!buffer)
+                       return;
+       }
+
+       for (buf = commit->buffer ? commit->buffer : buffer;
+            buf;
+            buf = line_end + 1) {
+               line_end = strchrnul(buf, '\n');
+               if (prefixcmp(buf, "author ")) {
+                       if (!line_end[0] || line_end[1] == '\n')
+                               return; /* end of header */
+                       continue;
+               }
+               if (split_ident_line(&ident,
+                                    buf + strlen("author "),
+                                    line_end - (buf + strlen("author "))) ||
+                   !ident.date_begin || !ident.date_end)
+                       goto fail_exit; /* malformed "author" line */
+               break;
+       }
+
+       date = strtoul(ident.date_begin, &date_end, 10);
+       if (date_end != ident.date_end)
+               goto fail_exit; /* malformed date */
+       *(author_date_slab_at(author_date, commit)) = date;
+
+fail_exit:
+       free(buffer);
+}
+
+static int compare_commits_by_author_date(const void *a_, const void *b_,
+                                         void *cb_data)
+{
+       const struct commit *a = a_, *b = b_;
+       struct author_date_slab *author_date = cb_data;
+       unsigned long a_date = *(author_date_slab_at(author_date, a));
+       unsigned long b_date = *(author_date_slab_at(author_date, b));
+
+       /* newer commits with larger date first */
+       if (a_date < b_date)
+               return 1;
+       else if (a_date > b_date)
+               return -1;
+       return 0;
+}
+
+int compare_commits_by_commit_date(const void *a_, const void *b_, void *unused)
+{
+       const struct commit *a = a_, *b = b_;
+       /* newer commits with larger date first */
+       if (a->date < b->date)
+               return 1;
+       else if (a->date > b->date)
+               return -1;
+       return 0;
+}
+
 /*
  * Performs an in-place topological sort on the list supplied.
  */
-void sort_in_topological_order(struct commit_list ** list, int lifo)
+void sort_in_topological_order(struct commit_list **list, enum rev_sort_order sort_order)
 {
        struct commit_list *next, *orig = *list;
-       struct commit_list *work, **insert;
        struct commit_list **pptr;
+       struct indegree_slab indegree;
+       struct prio_queue queue;
+       struct commit *commit;
+       struct author_date_slab author_date;
 
        if (!orig)
                return;
        *list = NULL;
 
+       init_indegree_slab(&indegree);
+       memset(&queue, '\0', sizeof(queue));
+
+       switch (sort_order) {
+       default: /* REV_SORT_IN_GRAPH_ORDER */
+               queue.compare = NULL;
+               break;
+       case REV_SORT_BY_COMMIT_DATE:
+               queue.compare = compare_commits_by_commit_date;
+               break;
+       case REV_SORT_BY_AUTHOR_DATE:
+               init_author_date_slab(&author_date);
+               queue.compare = compare_commits_by_author_date;
+               queue.cb_data = &author_date;
+               break;
+       }
+
        /* Mark them and clear the indegree */
        for (next = orig; next; next = next->next) {
                struct commit *commit = next->item;
-               commit->indegree = 1;
+               *(indegree_slab_at(&indegree, commit)) = 1;
+               /* also record the author dates, if needed */
+               if (sort_order == REV_SORT_BY_AUTHOR_DATE)
+                       record_author_date(&author_date, commit);
        }
 
        /* update the indegree */
        for (next = orig; next; next = next->next) {
-               struct commit_list * parents = next->item->parents;
+               struct commit_list *parents = next->item->parents;
                while (parents) {
                        struct commit *parent = parents->item;
+                       int *pi = indegree_slab_at(&indegree, parent);
 
-                       if (parent->indegree)
-                               parent->indegree++;
+                       if (*pi)
+                               (*pi)++;
                        parents = parents->next;
                }
        }
@@ -544,34 +654,33 @@ void sort_in_topological_order(struct commit_list ** list, int lifo)
         *
         * the tips serve as a starting set for the work queue.
         */
-       work = NULL;
-       insert = &work;
        for (next = orig; next; next = next->next) {
                struct commit *commit = next->item;
 
-               if (commit->indegree == 1)
-                       insert = &commit_list_insert(commit, insert)->next;
+               if (*(indegree_slab_at(&indegree, commit)) == 1)
+                       prio_queue_put(&queue, commit);
        }
 
-       /* process the list in topological order */
-       if (!lifo)
-               commit_list_sort_by_date(&work);
+       /*
+        * This is unfortunate; the initial tips need to be shown
+        * in the order given from the revision traversal machinery.
+        */
+       if (sort_order == REV_SORT_IN_GRAPH_ORDER)
+               prio_queue_reverse(&queue);
+
+       /* We no longer need the commit list */
+       free_commit_list(orig);
 
        pptr = list;
        *list = NULL;
-       while (work) {
-               struct commit *commit;
-               struct commit_list *parents, *work_item;
-
-               work_item = work;
-               work = work_item->next;
-               work_item->next = NULL;
+       while ((commit = prio_queue_get(&queue)) != NULL) {
+               struct commit_list *parents;
 
-               commit = work_item->item;
                for (parents = commit->parents; parents ; parents = parents->next) {
                        struct commit *parent = parents->item;
+                       int *pi = indegree_slab_at(&indegree, parent);
 
-                       if (!parent->indegree)
+                       if (!*pi)
                                continue;
 
                        /*
@@ -579,21 +688,22 @@ void sort_in_topological_order(struct commit_list ** list, int lifo)
                         * when all their children have been emitted thereby
                         * guaranteeing topological order.
                         */
-                       if (--parent->indegree == 1) {
-                               if (!lifo)
-                                       commit_list_insert_by_date(parent, &work);
-                               else
-                                       commit_list_insert(parent, &work);
-                       }
+                       if (--(*pi) == 1)
+                               prio_queue_put(&queue, parent);
                }
                /*
-                * work_item is a commit all of whose children
-                * have already been emitted. we can emit it now.
+                * all children of commit have already been
+                * emitted. we can emit it now.
                 */
-               commit->indegree = 0;
-               *pptr = work_item;
-               pptr = &work_item->next;
+               *(indegree_slab_at(&indegree, commit)) = 0;
+
+               pptr = &commit_list_insert(commit, pptr)->next;
        }
+
+       clear_indegree_slab(&indegree);
+       clear_prio_queue(&queue);
+       if (sort_order == REV_SORT_BY_AUTHOR_DATE)
+               clear_author_date_slab(&author_date);
 }
 
 /* merge-base stuff */
index 6e9c7cd9d5da7d24d4810b36039681f184325932..18a523495eb7be3636f4f1311375fdb35329da9e 100644 (file)
--- a/commit.h
+++ b/commit.h
@@ -15,7 +15,7 @@ struct commit_list {
 struct commit {
        struct object object;
        void *util;
-       unsigned int indegree;
+       unsigned int index;
        unsigned long date;
        struct commit_list *parents;
        struct tree *tree;
@@ -142,15 +142,24 @@ void clear_commit_marks(struct commit *commit, unsigned int mark);
 void clear_commit_marks_many(int nr, struct commit **commit, unsigned int mark);
 void clear_commit_marks_for_object_array(struct object_array *a, unsigned mark);
 
+
+enum rev_sort_order {
+       REV_SORT_IN_GRAPH_ORDER = 0,
+       REV_SORT_BY_COMMIT_DATE,
+       REV_SORT_BY_AUTHOR_DATE
+};
+
 /*
  * Performs an in-place topological sort of list supplied.
  *
  *   invariant of resulting list is:
  *      a reachable from b => ord(b) < ord(a)
- *   in addition, when lifo == 0, commits on parallel tracks are
- *   sorted in the dates order.
+ *   sort_order further specifies:
+ *   REV_SORT_IN_GRAPH_ORDER: try to show a commit on a single-parent
+ *                            chain together.
+ *   REV_SORT_BY_COMMIT_DATE: show eligible commits in committer-date order.
  */
-void sort_in_topological_order(struct commit_list ** list, int lifo);
+void sort_in_topological_order(struct commit_list **, enum rev_sort_order);
 
 struct commit_graft {
        unsigned char sha1[20];
@@ -245,4 +254,6 @@ extern void print_commit_list(struct commit_list *list,
  */
 extern void check_commit_signature(const struct commit* commit, struct signature_check *sigc);
 
+int compare_commits_by_commit_date(const void *a_, const void *b_, void *unused);
+
 #endif /* COMMIT_H */
index 6c3bafeea569601c4b55de165eb7f56ac3be1d31..fa3ae1e8535c786dc724ab7a73cccb6f3bfca8de 100644 (file)
@@ -33,8 +33,6 @@ esac
 # returns location of .git repo
 __gitdir ()
 {
-       # Note: this function is duplicated in git-prompt.sh
-       # When updating it, make sure you update the other one to match.
        if [ -z "${1-}" ]; then
                if [ -n "${__git_dir-}" ]; then
                        echo "$__git_dir"
@@ -2492,9 +2490,10 @@ __git_main ()
                i="${words[c]}"
                case "$i" in
                --git-dir=*) __git_dir="${i#--git-dir=}" ;;
+               --git-dir)   ((c++)) ; __git_dir="${words[c]}" ;;
                --bare)      __git_dir="." ;;
                --help) command="help"; break ;;
-               -c) c=$((++c)) ;;
+               -c|--work-tree|--namespace) ((c++)) ;;
                -*) ;;
                *) command="$i"; break ;;
                esac
@@ -2512,6 +2511,7 @@ __git_main ()
                        --exec-path
                        --exec-path=
                        --html-path
+                       --man-path
                        --info-path
                        --work-tree=
                        --namespace=
index 07a6218d10679f5102c3649794bfd98e1883da75..a81ef5a482d48b114a81e242109e2f0dec0839ed 100644 (file)
@@ -3,7 +3,7 @@
 # Copyright (C) 2006,2007 Shawn O. Pearce <spearce@spearce.org>
 # Distributed under the GNU General Public License, version 2.0.
 #
-# This script allows you to see the current branch in your prompt.
+# This script allows you to see repository status in your prompt.
 #
 # To enable:
 #
 #    3a) Change your PS1 to call __git_ps1 as
 #        command-substitution:
 #        Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
-#        ZSH:  PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ '
+#        ZSH:  setopt PROMPT_SUBST ; PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ '
 #        the optional argument will be used as format string.
-#    3b) Alternatively, if you are using bash, __git_ps1 can be
-#        used for PROMPT_COMMAND with two parameters, <pre> and
-#        <post>, which are strings you would put in $PS1 before
-#        and after the status string generated by the git-prompt
-#        machinery.  e.g.
+#    3b) Alternatively, for a slightly faster prompt, __git_ps1 can
+#        be used for PROMPT_COMMAND in Bash or for precmd() in Zsh
+#        with two parameters, <pre> and <post>, which are strings
+#        you would put in $PS1 before and after the status string
+#        generated by the git-prompt machinery.  e.g.
 #        Bash: PROMPT_COMMAND='__git_ps1 "\u@\h:\w" "\\\$ "'
+#          will show username, at-sign, host, colon, cwd, then
+#          various status string, followed by dollar and SP, as
+#          your prompt.
 #        ZSH:  precmd () { __git_ps1 "%n" ":%~$ " "|%s" }
-#        will show username, at-sign, host, colon, cwd, then
-#        various status string, followed by dollar and SP, as
-#        your prompt.
+#          will show username, pipe, then various status string,
+#          followed by colon, cwd, dollar and SP, as your prompt.
 #        Optionally, you can supply a third argument with a printf
 #        format string to finetune the output of the branch status
 #
-# The argument to __git_ps1 will be displayed only if you are currently
-# in a git repository.  The %s token will be the name of the current
-# branch.
+# The repository status will be displayed only if you are currently in a
+# git repository. The %s token is the placeholder for the shown status.
+#
+# The prompt status always includes the current branch name.
 #
 # In addition, if you set GIT_PS1_SHOWDIRTYSTATE to a nonempty value,
 # unstaged (*) and staged (+) changes will be shown next to the branch
 #
 # If you would like a colored hint about the current dirty state, set
 # GIT_PS1_SHOWCOLORHINTS to a nonempty value. The colors are based on
-# the colored output of "git status -sb".
-
-# __gitdir accepts 0 or 1 arguments (i.e., location)
-# returns location of .git repo
-__gitdir ()
-{
-       # Note: this function is duplicated in git-completion.bash
-       # When updating it, make sure you update the other one to match.
-       if [ -z "${1-}" ]; then
-               if [ -n "${__git_dir-}" ]; then
-                       echo "$__git_dir"
-               elif [ -n "${GIT_DIR-}" ]; then
-                       test -d "${GIT_DIR-}" || return 1
-                       echo "$GIT_DIR"
-               elif [ -d .git ]; then
-                       echo .git
-               else
-                       git rev-parse --git-dir 2>/dev/null
-               fi
-       elif [ -d "$1/.git" ]; then
-               echo "$1/.git"
-       else
-               echo "$1"
-       fi
-}
+# the colored output of "git status -sb" and are available only when
+# using __git_ps1 for PROMPT_COMMAND or precmd.
 
 # stores the divergence from upstream in $p
 # used by GIT_PS1_SHOWUPSTREAM
@@ -225,8 +205,8 @@ __git_ps1_show_upstream ()
 }
 
 # Helper function that is meant to be called from __git_ps1.  It
-# builds up a gitstring injecting color codes into the appropriate
-# places.
+# injects color codes into the appropriate gitstring variables used
+# to build a gitstring.
 __git_ps1_colorize_gitstring ()
 {
        if [[ -n ${ZSH_VERSION-} ]]; then
@@ -234,74 +214,40 @@ __git_ps1_colorize_gitstring ()
                local c_green='%F{green}'
                local c_lblue='%F{blue}'
                local c_clear='%f'
-               local bad_color=$c_red
-               local ok_color=$c_green
-               local branch_color="$c_clear"
-               local flags_color="$c_lblue"
-               local branchstring="$c${b##refs/heads/}"
-
-               if [ $detached = no ]; then
-                       branch_color="$ok_color"
-               else
-                       branch_color="$bad_color"
-               fi
-
-               gitstring="$branch_color$branchstring$c_clear"
-
-               if [ -n "$w$i$s$u$r$p" ]; then
-                       gitstring="$gitstring$z"
-               fi
-               if [ "$w" = "*" ]; then
-                       gitstring="$gitstring$bad_color$w"
-               fi
-               if [ -n "$i" ]; then
-                       gitstring="$gitstring$ok_color$i"
-               fi
-               if [ -n "$s" ]; then
-                       gitstring="$gitstring$flags_color$s"
-               fi
-               if [ -n "$u" ]; then
-                       gitstring="$gitstring$bad_color$u"
-               fi
-               gitstring="$gitstring$c_clear$r$p"
-               return
+       else
+               # Using \[ and \] around colors is necessary to prevent
+               # issues with command line editing/browsing/completion!
+               local c_red='\[\e[31m\]'
+               local c_green='\[\e[32m\]'
+               local c_lblue='\[\e[1;34m\]'
+               local c_clear='\[\e[0m\]'
        fi
-       local c_red='\e[31m'
-       local c_green='\e[32m'
-       local c_lblue='\e[1;34m'
-       local c_clear='\e[0m'
        local bad_color=$c_red
        local ok_color=$c_green
-       local branch_color="$c_clear"
        local flags_color="$c_lblue"
-       local branchstring="$c${b##refs/heads/}"
 
+       local branch_color=""
        if [ $detached = no ]; then
                branch_color="$ok_color"
        else
                branch_color="$bad_color"
        fi
+       c="$branch_color$c"
 
-       # Setting gitstring directly with \[ and \] around colors
-       # is necessary to prevent wrapping issues!
-       gitstring="\[$branch_color\]$branchstring\[$c_clear\]"
-
-       if [ -n "$w$i$s$u$r$p" ]; then
-               gitstring="$gitstring$z"
-       fi
+       z="$c_clear$z"
        if [ "$w" = "*" ]; then
-               gitstring="$gitstring\[$bad_color\]$w"
+               w="$bad_color$w"
        fi
        if [ -n "$i" ]; then
-               gitstring="$gitstring\[$ok_color\]$i"
+               i="$ok_color$i"
        fi
        if [ -n "$s" ]; then
-               gitstring="$gitstring\[$flags_color\]$s"
+               s="$flags_color$s"
        fi
        if [ -n "$u" ]; then
-               gitstring="$gitstring\[$bad_color\]$u"
+               u="$bad_color$u"
        fi
-       gitstring="$gitstring\[$c_clear\]$r$p"
+       r="$c_clear$r"
 }
 
 # __git_ps1 accepts 0 or 1 arguments (i.e., format string)
@@ -335,50 +281,83 @@ __git_ps1 ()
                ;;
        esac
 
-       local g="$(__gitdir)"
-       if [ -z "$g" ]; then
+       local repo_info rev_parse_exit_code
+       repo_info="$(git rev-parse --git-dir --is-inside-git-dir \
+               --is-bare-repository --is-inside-work-tree \
+               --short HEAD 2>/dev/null)"
+       rev_parse_exit_code="$?"
+
+       if [ -z "$repo_info" ]; then
                if [ $pcmode = yes ]; then
                        #In PC mode PS1 always needs to be set
                        PS1="$ps1pc_start$ps1pc_end"
                fi
+               return
+       fi
+
+       local short_sha
+       if [ "$rev_parse_exit_code" = "0" ]; then
+               short_sha="${repo_info##*$'\n'}"
+               repo_info="${repo_info%$'\n'*}"
+       fi
+       local inside_worktree="${repo_info##*$'\n'}"
+       repo_info="${repo_info%$'\n'*}"
+       local bare_repo="${repo_info##*$'\n'}"
+       repo_info="${repo_info%$'\n'*}"
+       local inside_gitdir="${repo_info##*$'\n'}"
+       local g="${repo_info%$'\n'*}"
+
+       local r=""
+       local b=""
+       local step=""
+       local total=""
+       if [ -d "$g/rebase-merge" ]; then
+               read b 2>/dev/null <"$g/rebase-merge/head-name"
+               read step 2>/dev/null <"$g/rebase-merge/msgnum"
+               read total 2>/dev/null <"$g/rebase-merge/end"
+               if [ -f "$g/rebase-merge/interactive" ]; then
+                       r="|REBASE-i"
+               else
+                       r="|REBASE-m"
+               fi
        else
-               local r=""
-               local b=""
-               local step=""
-               local total=""
-               if [ -d "$g/rebase-merge" ]; then
-                       b="$(cat "$g/rebase-merge/head-name" 2>/dev/null)"
-                       step=$(cat "$g/rebase-merge/msgnum" 2>/dev/null)
-                       total=$(cat "$g/rebase-merge/end" 2>/dev/null)
-                       if [ -f "$g/rebase-merge/interactive" ]; then
-                               r="|REBASE-i"
+               if [ -d "$g/rebase-apply" ]; then
+                       read step 2>/dev/null <"$g/rebase-apply/next"
+                       read total 2>/dev/null <"$g/rebase-apply/last"
+                       if [ -f "$g/rebase-apply/rebasing" ]; then
+                               read b 2>/dev/null <"$g/rebase-apply/head-name"
+                               r="|REBASE"
+                       elif [ -f "$g/rebase-apply/applying" ]; then
+                               r="|AM"
                        else
-                               r="|REBASE-m"
+                               r="|AM/REBASE"
                        fi
+               elif [ -f "$g/MERGE_HEAD" ]; then
+                       r="|MERGING"
+               elif [ -f "$g/CHERRY_PICK_HEAD" ]; then
+                       r="|CHERRY-PICKING"
+               elif [ -f "$g/REVERT_HEAD" ]; then
+                       r="|REVERTING"
+               elif [ -f "$g/BISECT_LOG" ]; then
+                       r="|BISECTING"
+               fi
+
+               if [ -n "$b" ]; then
+                       :
+               elif [ -h "$g/HEAD" ]; then
+                       # symlink symbolic ref
+                       b="$(git symbolic-ref HEAD 2>/dev/null)"
                else
-                       if [ -d "$g/rebase-apply" ]; then
-                               step=$(cat "$g/rebase-apply/next" 2>/dev/null)
-                               total=$(cat "$g/rebase-apply/last" 2>/dev/null)
-                               if [ -f "$g/rebase-apply/rebasing" ]; then
-                                       b="$(cat "$g/rebase-apply/head-name" 2>/dev/null)"
-                                       r="|REBASE"
-                               elif [ -f "$g/rebase-apply/applying" ]; then
-                                       r="|AM"
-                               else
-                                       r="|AM/REBASE"
+                       local head=""
+                       if ! read head 2>/dev/null <"$g/HEAD"; then
+                               if [ $pcmode = yes ]; then
+                                       PS1="$ps1pc_start$ps1pc_end"
                                fi
-                       elif [ -f "$g/MERGE_HEAD" ]; then
-                               r="|MERGING"
-                       elif [ -f "$g/CHERRY_PICK_HEAD" ]; then
-                               r="|CHERRY-PICKING"
-                       elif [ -f "$g/REVERT_HEAD" ]; then
-                               r="|REVERTING"
-                       elif [ -f "$g/BISECT_LOG" ]; then
-                               r="|BISECTING"
+                               return
                        fi
-
-                       test -n "$b" ||
-                       b="$(git symbolic-ref HEAD 2>/dev/null)" || {
+                       # is it a symbolic ref?
+                       b="${head#ref: }"
+                       if [ "$head" = "$b" ]; then
                                detached=yes
                                b="$(
                                case "${GIT_PS1_DESCRIBE_STYLE-}" in
@@ -392,70 +371,75 @@ __git_ps1 ()
                                        git describe --tags --exact-match HEAD ;;
                                esac 2>/dev/null)" ||
 
-                               b="$(cut -c1-7 "$g/HEAD" 2>/dev/null)..." ||
-                               b="unknown"
+                               b="$short_sha..."
                                b="($b)"
-                       }
+                       fi
                fi
+       fi
 
-               if [ -n "$step" ] && [ -n "$total" ]; then
-                       r="$r $step/$total"
-               fi
+       if [ -n "$step" ] && [ -n "$total" ]; then
+               r="$r $step/$total"
+       fi
 
-               local w=""
-               local i=""
-               local s=""
-               local u=""
-               local c=""
-               local p=""
+       local w=""
+       local i=""
+       local s=""
+       local u=""
+       local c=""
+       local p=""
 
-               if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then
-                       if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then
-                               c="BARE:"
+       if [ "true" = "$inside_gitdir" ]; then
+               if [ "true" = "$bare_repo" ]; then
+                       c="BARE:"
+               else
+                       b="GIT_DIR!"
+               fi
+       elif [ "true" = "$inside_worktree" ]; then
+               if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ] &&
+                  [ "$(git config --bool bash.showDirtyState)" != "false" ]
+               then
+                       git diff --no-ext-diff --quiet --exit-code || w="*"
+                       if [ -n "$short_sha" ]; then
+                               git diff-index --cached --quiet HEAD -- || i="+"
                        else
-                               b="GIT_DIR!"
-                       fi
-               elif [ "true" = "$(git rev-parse --is-inside-work-tree 2>/dev/null)" ]; then
-                       if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ] &&
-                          [ "$(git config --bool bash.showDirtyState)" != "false" ]
-                       then
-                               git diff --no-ext-diff --quiet --exit-code || w="*"
-                               if git rev-parse --quiet --verify HEAD >/dev/null; then
-                                       git diff-index --cached --quiet HEAD -- || i="+"
-                               else
-                                       i="#"
-                               fi
-                       fi
-                       if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ]; then
-                               git rev-parse --verify refs/stash >/dev/null 2>&1 && s="$"
+                               i="#"
                        fi
+               fi
+               if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ] &&
+                  [ -r "$g/refs/stash" ]; then
+                       s="$"
+               fi
 
-                       if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ] &&
-                          [ "$(git config --bool bash.showUntrackedFiles)" != "false" ] &&
-                          [ -n "$(git ls-files --others --exclude-standard)" ]
-                       then
-                               u="%${ZSH_VERSION+%}"
-                       fi
+               if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ] &&
+                  [ "$(git config --bool bash.showUntrackedFiles)" != "false" ] &&
+                  git ls-files --others --exclude-standard --error-unmatch -- '*' >/dev/null 2>/dev/null
+               then
+                       u="%${ZSH_VERSION+%}"
+               fi
 
-                       if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
-                               __git_ps1_show_upstream
-                       fi
+               if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
+                       __git_ps1_show_upstream
                fi
+       fi
 
-               local z="${GIT_PS1_STATESEPARATOR-" "}"
-               local f="$w$i$s$u"
-               if [ $pcmode = yes ]; then
-                       local gitstring=
-                       if [ -n "${GIT_PS1_SHOWCOLORHINTS-}" ]; then
-                               __git_ps1_colorize_gitstring
-                       else
-                               gitstring="$c${b##refs/heads/}${f:+$z$f}$r$p"
-                       fi
+       local z="${GIT_PS1_STATESEPARATOR-" "}"
+
+       # NO color option unless in PROMPT_COMMAND mode
+       if [ $pcmode = yes ] && [ -n "${GIT_PS1_SHOWCOLORHINTS-}" ]; then
+               __git_ps1_colorize_gitstring
+       fi
+
+       local f="$w$i$s$u"
+       local gitstring="$c${b##refs/heads/}${f:+$z$f}$r$p"
+
+       if [ $pcmode = yes ]; then
+               if [[ -n ${ZSH_VERSION-} ]]; then
                        gitstring=$(printf -- "$printf_format" "$gitstring")
-                       PS1="$ps1pc_start$gitstring$ps1pc_end"
                else
-                       # NO color option unless in PROMPT_COMMAND mode
-                       printf -- "$printf_format" "$c${b##refs/heads/}${f:+$z$f}$r$p"
+                       printf -v gitstring -- "$printf_format" "$gitstring"
                fi
+               PS1="$ps1pc_start$gitstring$ps1pc_end"
+       else
+               printf -- "$printf_format" "$gitstring"
        fi
 }
index 71baf8ace8882e96eddab19e4b11448044b5190e..d09f5da6681fa62dbb87582031c12fe9dceddb69 100755 (executable)
@@ -635,9 +635,9 @@ sub literal_data_raw {
        my ($content) = @_;
        # Avoid confusion between size in bytes and in characters
        utf8::downgrade($content);
-       binmode {*STDOUT}, ':raw';
+       binmode STDOUT, ':raw';
        print {*STDOUT} 'data ', bytes::length($content), "\n", $content;
-       binmode {*STDOUT}, ':encoding(UTF-8)';
+       binmode STDOUT, ':encoding(UTF-8)';
        return;
 }
 
diff --git a/diff.c b/diff.c
index 208094f6b7d8b6e18459fc1cd57ac8554723d8d4..e53ddad7d485c97ca3f0cf0d5784ac712163a857 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -2677,6 +2677,14 @@ static int diff_populate_gitlink(struct diff_filespec *s, int size_only)
 int diff_populate_filespec(struct diff_filespec *s, int size_only)
 {
        int err = 0;
+       /*
+        * demote FAIL to WARN to allow inspecting the situation
+        * instead of refusing.
+        */
+       enum safe_crlf crlf_warn = (safe_crlf == SAFE_CRLF_FAIL
+                                   ? SAFE_CRLF_WARN
+                                   : safe_crlf);
+
        if (!DIFF_FILE_VALID(s))
                die("internal error: asking to populate invalid file.");
        if (S_ISDIR(s->mode))
@@ -2732,7 +2740,7 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)
                /*
                 * Convert from working tree format to canonical git format
                 */
-               if (convert_to_git(s->path, s->data, s->size, &buf, safe_crlf)) {
+               if (convert_to_git(s->path, s->data, s->size, &buf, crlf_warn)) {
                        size_t size = 0;
                        munmap(s->data, s->size);
                        s->should_munmap = 0;
index c97ac9b463fc1248b2dfe70d5fdf1dc1679e2bf8..401eb72c619d432c92fc66b470fae778117bcace 100644 (file)
@@ -131,8 +131,7 @@ static void diffcore_pickaxe_grep(struct diff_options *o)
        return;
 }
 
-static unsigned int contains(mmfile_t *mf, struct diff_options *o,
-                            regex_t *regexp, kwset_t kws)
+static unsigned int contains(mmfile_t *mf, regex_t *regexp, kwset_t kws)
 {
        unsigned int cnt;
        unsigned long sz;
@@ -176,11 +175,9 @@ static int has_changes(mmfile_t *one, mmfile_t *two,
                       struct diff_options *o,
                       regex_t *regexp, kwset_t kws)
 {
-       if (!one)
-               return contains(two, o, regexp, kws) != 0;
-       if (!two)
-               return contains(one, o, regexp, kws) != 0;
-       return contains(one, o, regexp, kws) != contains(two, o, regexp, kws);
+       unsigned int one_contains = one ? contains(one, regexp, kws) : 0;
+       unsigned int two_contains = two ? contains(two, regexp, kws) : 0;
+       return one_contains != two_contains;
 }
 
 static int pickaxe_match(struct diff_filepair *p, struct diff_options *o,
diff --git a/dir.c b/dir.c
index 897c87403e978ab2123ce088cf2d3265e21d7dde..048041954418315d73924b3d73c6f2c794a5edb1 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -1036,9 +1036,7 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
                return path_recurse;
 
        case index_gitdir:
-               if (dir->flags & DIR_SHOW_OTHER_DIRECTORIES)
-                       return path_none;
-               return path_untracked;
+               return path_none;
 
        case index_nonexistent:
                if (dir->flags & DIR_SHOW_OTHER_DIRECTORIES)
index abe5ffbba55037c34b1bf38a86aa0ec8bd7f3447..6684348c0ec9ea742eb98666b56a0bfcef316560 100644 (file)
@@ -11,6 +11,7 @@
 #include "run-command.h"
 #include "transport.h"
 #include "version.h"
+#include "prio-queue.h"
 
 static int transfer_unpack_limit = -1;
 static int fetch_unpack_limit = -1;
@@ -37,7 +38,7 @@ static int marked;
  */
 #define MAX_IN_VAIN 256
 
-static struct commit_list *rev_list;
+static struct prio_queue rev_list = { compare_commits_by_commit_date };
 static int non_common_revs, multi_ack, use_sideband, allow_tip_sha1_in_want;
 
 static void rev_list_push(struct commit *commit, int mark)
@@ -49,7 +50,7 @@ static void rev_list_push(struct commit *commit, int mark)
                        if (parse_commit(commit))
                                return;
 
-               commit_list_insert_by_date(commit, &rev_list);
+               prio_queue_put(&rev_list, commit);
 
                if (!(commit->object.flags & COMMON))
                        non_common_revs++;
@@ -122,10 +123,10 @@ static const unsigned char *get_rev(void)
                unsigned int mark;
                struct commit_list *parents;
 
-               if (rev_list == NULL || non_common_revs == 0)
+               if (rev_list.nr == 0 || non_common_revs == 0)
                        return NULL;
 
-               commit = rev_list->item;
+               commit = prio_queue_get(&rev_list);
                if (!commit->object.parsed)
                        parse_commit(commit);
                parents = commit->parents;
@@ -152,8 +153,6 @@ static const unsigned char *get_rev(void)
                                mark_common(parents->item, 1, 0);
                        parents = parents->next;
                }
-
-               rev_list = rev_list->next;
        }
 
        return commit->object.sha1;
@@ -442,7 +441,7 @@ static int find_common(struct fetch_pack_args *args,
                                        in_vain = 0;
                                        got_continue = 1;
                                        if (ack == ACK_ready) {
-                                               rev_list = NULL;
+                                               clear_prio_queue(&rev_list);
                                                got_ready = 1;
                                        }
                                        break;
@@ -505,7 +504,7 @@ static int mark_complete(const char *refname, const unsigned char *sha1, int fla
                struct commit *commit = (struct commit *)o;
                if (!(commit->object.flags & COMPLETE)) {
                        commit->object.flags |= COMPLETE;
-                       commit_list_insert_by_date(commit, &complete);
+                       commit_list_insert(commit, &complete);
                }
        }
        return 0;
@@ -622,6 +621,7 @@ static int everything_local(struct fetch_pack_args *args,
        if (!args->depth) {
                for_each_ref(mark_complete, NULL);
                for_each_alternate_ref(mark_alternate_complete, NULL);
+               commit_list_sort_by_date(&complete);
                if (cutoff)
                        mark_recent_complete_commits(args, cutoff);
        }
diff --git a/fixup-builtins b/fixup-builtins
deleted file mode 100755 (executable)
index 63dfa4c..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/sh
-while [ "$1" ]
-do
-       if [ "$1" != "git-sh-setup" -a "$1" != "git-parse-remote" -a "$1" != "git-svn" ]; then
-               old="$1"
-               new=$(echo "$1" | sed 's/git-/git /')
-               echo "Converting '$old' to '$new'"
-               sed -i "s/\\<$old\\>/$new/g" $(git ls-files '*.sh')
-       fi
-       shift
-done
-
-sed -i 's/git merge-one-file/git-merge-one-file/g
-s/git rebase-todo/git-rebase-todo/g' $(git ls-files '*.sh')
-git update-index --refresh >& /dev/null
-exit 0
index 9f4450916cd28578002d04a45b4e28e09cca738c..7ea40fe6449b665713a8272f125936edf632189b 100755 (executable)
--- a/git-am.sh
+++ b/git-am.sh
@@ -6,7 +6,7 @@ SUBDIRECTORY_OK=Yes
 OPTIONS_KEEPDASHDASH=
 OPTIONS_SPEC="\
 git am [options] [(<mbox>|<Maildir>)...]
-git am [options] (--resolved | --skip | --abort)
+git am [options] (--continue | --skip | --abort)
 --
 i,interactive   run interactively
 b,binary*       (historical option -- no-op)
@@ -102,7 +102,7 @@ stop_here_user_resolve () {
            printf '%s\n' "$resolvemsg"
            stop_here $1
     fi
-    eval_gettextln "When you have resolved this problem, run \"\$cmdline --resolved\".
+    eval_gettextln "When you have resolved this problem, run \"\$cmdline --continue\".
 If you prefer to skip this patch, run \"\$cmdline --skip\" instead.
 To restore the original branch and stop patching, run \"\$cmdline --abort\"."
 
@@ -523,7 +523,7 @@ Use \"git am --abort\" to remove it.")"
                esac
        fi
 
-       # Make sure we are not given --skip, --resolved, nor --abort
+       # Make sure we are not given --skip, --continue, nor --abort
        test "$skip$resolved$abort" = "" ||
                die "$(gettext "Resolve operation not in progress, we are not resuming.")"
 
@@ -670,7 +670,7 @@ do
        #  - patch is the patch body.
        #
        # When we are resuming, these files are either already prepared
-       # by the user, or the user can tell us to do so by --resolved flag.
+       # by the user, or the user can tell us to do so by --continue flag.
        case "$resume" in
        '')
                if test -f "$dotest/rebasing"
index 6828e2c7157fd80905e864b475c11ccc7a330e03..f0df41c841644208c89230516677db162498be26 100755 (executable)
@@ -5,7 +5,7 @@
 # Fetch one or more remote refs and merge it/them into the current HEAD.
 
 USAGE='[-n | --no-stat] [--[no-]commit] [--[no-]squash] [--[no-]ff] [-s strategy]... [<fetch-options>] <repo> <head>...'
-LONG_USAGE='Fetch one or more remote refs and merge it/them into the current HEAD.'
+LONG_USAGE='Fetch one or more remote refs and integrate it/them with the current HEAD.'
 SUBDIRECTORY_OK=Yes
 OPTIONS_SPEC=
 . git-sh-setup
index f953d8d22499b9e41d3c0ed86183655e39d807af..157690b6858bdd8497be0bcea6f2385d86dc3f33 100644 (file)
@@ -80,6 +80,18 @@ amend="$state_dir"/amend
 rewritten_list="$state_dir"/rewritten-list
 rewritten_pending="$state_dir"/rewritten-pending
 
+strategy_args=
+if test -n "$do_merge"
+then
+       strategy_args=${strategy:+--strategy=$strategy}
+       eval '
+               for strategy_opt in '"$strategy_opts"'
+               do
+                       strategy_args="$strategy_args -X$(git rev-parse --sq-quote "${strategy_opt#--}")"
+               done
+       '
+fi
+
 GIT_CHERRY_PICK_HELP="$resolvemsg"
 export GIT_CHERRY_PICK_HELP
 
@@ -239,7 +251,7 @@ pick_one () {
 
        test -d "$rewritten" &&
                pick_one_preserving_merges "$@" && return
-       output git cherry-pick $empty_args $ff "$@"
+       output eval git cherry-pick "$strategy_args" $empty_args $ff "$@"
 }
 
 pick_one_preserving_merges () {
@@ -340,9 +352,8 @@ pick_one_preserving_merges () {
                        msg_content="$(commit_message $sha1)"
                        # No point in merging the first parent, that's HEAD
                        new_parents=${new_parents# $first_parent}
-                       if ! do_with_author output \
-                               git merge --no-ff ${strategy:+-s $strategy} -m \
-                                       "$msg_content" $new_parents
+                       if ! do_with_author output eval \
+                       'git merge --no-ff $strategy_args -m "$msg_content" $new_parents'
                        then
                                printf "%s\n" "$msg_content" > "$GIT_DIR"/MERGE_MSG
                                die_with_patch $sha1 "Error redoing merge $sha1"
@@ -350,7 +361,7 @@ pick_one_preserving_merges () {
                        echo "$sha1 $(git rev-parse HEAD^0)" >> "$rewritten_list"
                        ;;
                *)
-                       output git cherry-pick "$@" ||
+                       output eval git cherry-pick "$strategy_args" "$@" ||
                                die_with_patch $sha1 "Could not pick $sha1"
                        ;;
                esac
@@ -689,8 +700,22 @@ rearrange_squash () {
                case "$message" in
                "squash! "*|"fixup! "*)
                        action="${message%%!*}"
-                       rest="${message#*! }"
-                       echo "$sha1 $action $rest"
+                       rest=$message
+                       prefix=
+                       # skip all squash! or fixup! (but save for later)
+                       while :
+                       do
+                               case "$rest" in
+                               "squash! "*|"fixup! "*)
+                                       prefix="$prefix${rest%%!*},"
+                                       rest="${rest#*! }"
+                                       ;;
+                               *)
+                                       break
+                                       ;;
+                               esac
+                       done
+                       echo "$sha1 $action $prefix $rest"
                        # if it's a single word, try to resolve to a full sha1 and
                        # emit a second copy. This allows us to match on both message
                        # and on sha1 prefix
@@ -699,7 +724,7 @@ rearrange_squash () {
                                if test -n "$fullsha"; then
                                        # prefix the action to uniquely identify this line as
                                        # intended for full sha1 match
-                                       echo "$sha1 +$action $fullsha"
+                                       echo "$sha1 +$action $prefix $fullsha"
                                fi
                        fi
                esac
@@ -714,7 +739,7 @@ rearrange_squash () {
                esac
                printf '%s\n' "$pick $sha1 $message"
                used="$used$sha1 "
-               while read -r squash action msg_content
+               while read -r squash action msg_prefix msg_content
                do
                        case " $used" in
                        *" $squash "*) continue ;;
@@ -730,7 +755,8 @@ rearrange_squash () {
                                case "$message" in "$msg_content"*) emit=1;; esac ;;
                        esac
                        if test $emit = 1; then
-                               printf '%s\n' "$action $squash $action! $msg_content"
+                               real_prefix=$(echo "$msg_prefix" | sed "s/,/! /g")
+                               printf '%s\n' "$action $squash ${real_prefix}$msg_content"
                                used="$used$squash "
                        fi
                done <"$1.sq"
index 1e541a21257c70fa67c0fee552ccb05fc5b6a280..85c9e2c0817c171d67f7458a0764df8d31fb10ad 100755 (executable)
@@ -195,6 +195,7 @@ save_stash () {
        keep_index=
        patch_mode=
        untracked=
+       force=
        while test $# != 0
        do
                case "$1" in
@@ -215,6 +216,9 @@ save_stash () {
                -u|--include-untracked)
                        untracked=untracked
                        ;;
+               -f|--force)
+                       force=t
+                       ;;
                -a|--all)
                        untracked=all
                        ;;
@@ -258,6 +262,14 @@ save_stash () {
                say "$(gettext "No local changes to save")"
                exit 0
        fi
+       if test -z "$untracked$force" &&
+          test -n "$(git ls-files --killed | head -n 1)"
+       then
+               say "$(gettext "The following untracked files would NOT be saved but need to be removed by stash save:")"
+               test -n "$GIT_QUIET" || git ls-files --killed | sed 's/^/\t/'
+               say "$(gettext "Aborting. Consider using either the --force or --include-untracked option.")" >&2
+               exit 1
+       fi
        test -f "$GIT_DIR/logs/$ref_stash" ||
                clear_stash || die "$(gettext "Cannot initialize stash")"
 
index 8d69ada04291e308e39e999d49278b7af602f28f..f429f75897ed10684d017aeaeb93f1c9d9478e0b 100755 (executable)
@@ -85,6 +85,9 @@ sub evaluate_uri {
 # string of the home link on top of all pages
 our $home_link_str = "++GITWEB_HOME_LINK_STR++";
 
+# extra breadcrumbs preceding the home link
+our @extra_breadcrumbs = ();
+
 # name of your site or organization to appear in page titles
 # replace this with something more descriptive for clearer bookmarks
 our $site_name = "++GITWEB_SITENAME++"
@@ -3982,7 +3985,9 @@ sub print_nav_breadcrumbs_path {
 sub print_nav_breadcrumbs {
        my %opts = @_;
 
-       print $cgi->a({-href => esc_url($home_link)}, $home_link_str) . " / ";
+       for my $crumb (@extra_breadcrumbs, [ $home_link_str => $home_link ]) {
+               print $cgi->a({-href => esc_url($crumb->[1])}, $crumb->[0]) . " / ";
+       }
        if (defined $project) {
                my @dirname = split '/', $project;
                my $projectbasename = pop @dirname;
index c6fb77b26fd88f4edf85a8920a6d72e49551deed..8fbcb6a98aae85b48c6f8de29c6f95af58823411 100644 (file)
@@ -124,15 +124,17 @@ static char *resolve_symlink(char *p, size_t s)
 
 static int lock_file(struct lock_file *lk, const char *path, int flags)
 {
-       if (strlen(path) >= sizeof(lk->filename))
-               return -1;
-       strcpy(lk->filename, path);
        /*
         * subtract 5 from size to make sure there's room for adding
         * ".lock" for the lock file name
         */
+       static const size_t max_path_len = sizeof(lk->filename) - 5;
+
+       if (strlen(path) >= max_path_len)
+               return -1;
+       strcpy(lk->filename, path);
        if (!(flags & LOCK_NODEREF))
-               resolve_symlink(lk->filename, sizeof(lk->filename)-5);
+               resolve_symlink(lk->filename, max_path_len);
        strcat(lk->filename, ".lock");
        lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);
        if (0 <= lk->fd) {
index 2eb69bcfed096d28bff736deca715458605d902a..60f32a3965feeba30bd7ba7ba724c5d7dfd52be8 100644 (file)
@@ -617,6 +617,7 @@ void show_log(struct rev_info *opt)
        ctx.fmt = opt->commit_format;
        ctx.mailmap = opt->mailmap;
        ctx.color = opt->diffopt.use_color;
+       ctx.output_encoding = get_log_output_encoding();
        pretty_print_commit(&ctx, commit, &msgbuf);
 
        if (opt->add_signoff)
diff --git a/prio-queue.c b/prio-queue.c
new file mode 100644 (file)
index 0000000..c9f8c6d
--- /dev/null
@@ -0,0 +1,84 @@
+#include "cache.h"
+#include "commit.h"
+#include "prio-queue.h"
+
+void prio_queue_reverse(struct prio_queue *queue)
+{
+       int i, j;
+
+       if (queue->compare != NULL)
+               die("BUG: prio_queue_reverse() on non-LIFO queue");
+       for (i = 0; i <= (j = (queue->nr - 1) - i); i++) {
+               struct commit *swap = queue->array[i];
+               queue->array[i] = queue->array[j];
+               queue->array[j] = swap;
+       }
+}
+
+void clear_prio_queue(struct prio_queue *queue)
+{
+       free(queue->array);
+       queue->nr = 0;
+       queue->alloc = 0;
+       queue->array = NULL;
+}
+
+void prio_queue_put(struct prio_queue *queue, void *thing)
+{
+       prio_queue_compare_fn compare = queue->compare;
+       int ix, parent;
+
+       /* Append at the end */
+       ALLOC_GROW(queue->array, queue->nr + 1, queue->alloc);
+       queue->array[queue->nr++] = thing;
+       if (!compare)
+               return; /* LIFO */
+
+       /* Bubble up the new one */
+       for (ix = queue->nr - 1; ix; ix = parent) {
+               parent = (ix - 1) / 2;
+               if (compare(queue->array[parent], queue->array[ix],
+                           queue->cb_data) <= 0)
+                       break;
+
+               thing = queue->array[parent];
+               queue->array[parent] = queue->array[ix];
+               queue->array[ix] = thing;
+       }
+}
+
+void *prio_queue_get(struct prio_queue *queue)
+{
+       void *result, *swap;
+       int ix, child;
+       prio_queue_compare_fn compare = queue->compare;
+
+       if (!queue->nr)
+               return NULL;
+       if (!compare)
+               return queue->array[--queue->nr]; /* LIFO */
+
+       result = queue->array[0];
+       if (!--queue->nr)
+               return result;
+
+       queue->array[0] = queue->array[queue->nr];
+
+       /* Push down the one at the root */
+       for (ix = 0; ix * 2 + 1 < queue->nr; ix = child) {
+               child = ix * 2 + 1; /* left */
+               if ((child + 1 < queue->nr) &&
+                   (compare(queue->array[child], queue->array[child + 1],
+                            queue->cb_data) >= 0))
+                       child++; /* use right child */
+
+               if (compare(queue->array[ix], queue->array[child],
+                           queue->cb_data) <= 0)
+                       break;
+
+               swap = queue->array[child];
+               queue->array[child] = queue->array[ix];
+               queue->array[ix] = swap;
+       }
+       return result;
+}
diff --git a/prio-queue.h b/prio-queue.h
new file mode 100644 (file)
index 0000000..9c3cd1f
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef PRIO_QUEUE_H
+#define PRIO_QUEUE_H
+
+/*
+ * A priority queue implementation, primarily for keeping track of
+ * commits in the 'date-order' so that we process them from new to old
+ * as they are discovered, but can be used to hold any pointer to
+ * struct.  The caller is responsible for supplying a function to
+ * compare two "things".
+ *
+ * Alternatively, this data structure can also be used as a LIFO stack
+ * by specifying NULL as the comparison function.
+ */
+
+/*
+ * Compare two "things", one and two; the third parameter is cb_data
+ * in the prio_queue structure.  The result is returned as a sign of
+ * the return value, being the same as the sign of the result of
+ * subtracting "two" from "one" (i.e. negative if "one" sorts earlier
+ * than "two").
+ */
+typedef int (*prio_queue_compare_fn)(const void *one, const void *two, void *cb_data);
+
+struct prio_queue {
+       prio_queue_compare_fn compare;
+       void *cb_data;
+       int alloc, nr;
+       void **array;
+};
+
+/*
+ * Add the "thing" to the queue.
+ */
+extern void prio_queue_put(struct prio_queue *, void *thing);
+
+/*
+ * Extract the "thing" that compares the smallest out of the queue,
+ * or NULL.  If compare function is NULL, the queue acts as a LIFO
+ * stack.
+ */
+extern void *prio_queue_get(struct prio_queue *);
+
+extern void clear_prio_queue(struct prio_queue *);
+
+/* Reverse the LIFO elements */
+extern void prio_queue_reverse(struct prio_queue *);
+
+#endif /* PRIO_QUEUE_H */
index 60eda6308197ad3d0b5957b9ae34e2dc15dfe5cc..5b3ce9eed299e312c132b590ea4926cfb019a271 100644 (file)
@@ -7,6 +7,7 @@
 #include "run-command.h"
 #include "pkt-line.h"
 #include "sideband.h"
+#include "argv-array.h"
 
 static struct remote *remote;
 static const char *url; /* always ends with a trailing slash */
@@ -787,36 +788,35 @@ static int push_dav(int nr_spec, char **specs)
 static int push_git(struct discovery *heads, int nr_spec, char **specs)
 {
        struct rpc_state rpc;
-       const char **argv;
-       int argc = 0, i, err;
+       int i, err;
+       struct argv_array args;
+
+       argv_array_init(&args);
+       argv_array_pushl(&args, "send-pack", "--stateless-rpc", "--helper-status",
+                        NULL);
 
-       argv = xmalloc((10 + nr_spec) * sizeof(char*));
-       argv[argc++] = "send-pack";
-       argv[argc++] = "--stateless-rpc";
-       argv[argc++] = "--helper-status";
        if (options.thin)
-               argv[argc++] = "--thin";
+               argv_array_push(&args, "--thin");
        if (options.dry_run)
-               argv[argc++] = "--dry-run";
+               argv_array_push(&args, "--dry-run");
        if (options.verbosity == 0)
-               argv[argc++] = "--quiet";
+               argv_array_push(&args, "--quiet");
        else if (options.verbosity > 1)
-               argv[argc++] = "--verbose";
-       argv[argc++] = options.progress ? "--progress" : "--no-progress";
-       argv[argc++] = url;
+               argv_array_push(&args, "--verbose");
+       argv_array_push(&args, options.progress ? "--progress" : "--no-progress");
+       argv_array_push(&args, url);
        for (i = 0; i < nr_spec; i++)
-               argv[argc++] = specs[i];
-       argv[argc++] = NULL;
+               argv_array_push(&args, specs[i]);
 
        memset(&rpc, 0, sizeof(rpc));
        rpc.service_name = "git-receive-pack",
-       rpc.argv = argv;
+       rpc.argv = args.argv;
 
        err = rpc_service(&rpc, heads);
        if (rpc.result.len)
                write_or_die(1, rpc.result.buf, rpc.result.len);
        strbuf_release(&rpc.result);
-       free(argv);
+       argv_array_clear(&args);
        return err;
 }
 
index e71f66de25b6031bbe1ee94ab3770aacd15b46e0..6f57830b6401ead50011fda8362a4f85e87fcab4 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -276,10 +276,9 @@ static void read_remotes_file(struct remote *remote)
 
 static void read_branches_file(struct remote *remote)
 {
-       const char *slash = strchr(remote->name, '/');
        char *frag;
        struct strbuf branch = STRBUF_INIT;
-       int n = slash ? slash - remote->name : 1000;
+       int n = 1000;
        FILE *f = fopen(git_path("branches/%.*s", n, remote->name), "r");
        char *s, *p;
        int len;
@@ -299,21 +298,11 @@ static void read_branches_file(struct remote *remote)
        while (isspace(p[-1]))
                *--p = 0;
        len = p - s;
-       if (slash)
-               len += strlen(slash);
        p = xmalloc(len + 1);
        strcpy(p, s);
-       if (slash)
-               strcat(p, slash);
 
        /*
-        * With "slash", e.g. "git fetch jgarzik/netdev-2.6" when
-        * reading from $GIT_DIR/branches/jgarzik fetches "HEAD" from
-        * the partial URL obtained from the branches file plus
-        * "/netdev-2.6" and does not store it in any tracking ref.
-        * #branch specifier in the file is ignored.
-        *
-        * Otherwise, the branches file would have URL and optionally
+        * The branches file would have URL and optionally
         * #branch specified.  The "master" (or specified) branch is
         * fetched and stored in the local branch of the same name.
         */
@@ -323,12 +312,8 @@ static void read_branches_file(struct remote *remote)
                strbuf_addf(&branch, "refs/heads/%s", frag);
        } else
                strbuf_addstr(&branch, "refs/heads/master");
-       if (!slash) {
-               strbuf_addf(&branch, ":refs/heads/%s", remote->name);
-       } else {
-               strbuf_reset(&branch);
-               strbuf_addstr(&branch, "HEAD:");
-       }
+
+       strbuf_addf(&branch, ":refs/heads/%s", remote->name);
        add_url_alias(remote, p);
        add_fetch_refspec(remote, strbuf_detach(&branch, NULL));
        /*
index f1bb731fd71eb874344faa5376e7c375ac2fcf7f..2f0142f22e21d7cfb1c74ca7035ee962e16dbd9e 100644 (file)
@@ -1296,7 +1296,7 @@ void init_revisions(struct rev_info *revs, const char *prefix)
        DIFF_OPT_SET(&revs->pruning, QUICK);
        revs->pruning.add_remove = file_add_remove;
        revs->pruning.change = file_change;
-       revs->lifo = 1;
+       revs->sort_order = REV_SORT_IN_GRAPH_ORDER;
        revs->dense = 1;
        revs->prefix = prefix;
        revs->max_age = -1;
@@ -1638,7 +1638,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
        } else if (!strcmp(arg, "--merge")) {
                revs->show_merge = 1;
        } else if (!strcmp(arg, "--topo-order")) {
-               revs->lifo = 1;
+               revs->sort_order = REV_SORT_IN_GRAPH_ORDER;
                revs->topo_order = 1;
        } else if (!strcmp(arg, "--simplify-merges")) {
                revs->simplify_merges = 1;
@@ -1656,7 +1656,10 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
                revs->prune = 1;
                load_ref_decorations(DECORATE_SHORT_REFS);
        } else if (!strcmp(arg, "--date-order")) {
-               revs->lifo = 0;
+               revs->sort_order = REV_SORT_BY_COMMIT_DATE;
+               revs->topo_order = 1;
+       } else if (!strcmp(arg, "--author-date-order")) {
+               revs->sort_order = REV_SORT_BY_AUTHOR_DATE;
                revs->topo_order = 1;
        } else if (!prefixcmp(arg, "--early-output")) {
                int count = 100;
@@ -2606,7 +2609,7 @@ int prepare_revision_walk(struct rev_info *revs)
                if (limit_list(revs) < 0)
                        return -1;
        if (revs->topo_order)
-               sort_in_topological_order(&revs->commits, revs->lifo);
+               sort_in_topological_order(&revs->commits, revs->sort_order);
        if (revs->line_level_traverse)
                line_log_filter(revs);
        if (revs->simplify_merges)
@@ -2924,7 +2927,7 @@ static void create_boundary_commit_list(struct rev_info *revs)
         * If revs->topo_order is set, sort the boundary commits
         * in topological order
         */
-       sort_in_topological_order(&revs->commits, revs->lifo);
+       sort_in_topological_order(&revs->commits, revs->sort_order);
 }
 
 static struct commit *get_revision_internal(struct rev_info *revs)
index eeea6fba3c5408d5567eec238d0a331bf64ddc04..92d6614af6da62160219b0df40d0caf56335ffce 100644 (file)
@@ -4,6 +4,7 @@
 #include "parse-options.h"
 #include "grep.h"
 #include "notes.h"
+#include "commit.h"
 
 #define SEEN           (1u<<0)
 #define UNINTERESTING   (1u<<1)
@@ -62,6 +63,10 @@ struct rev_info {
        const char *prefix;
        const char *def;
        struct pathspec prune_data;
+
+       /* topo-sort */
+       enum rev_sort_order sort_order;
+
        unsigned int    early_output:1,
                        ignore_missing:1;
 
@@ -72,7 +77,6 @@ struct rev_info {
                        show_all:1,
                        remove_empty_trees:1,
                        simplify_history:1,
-                       lifo:1,
                        topo_order:1,
                        simplify_merges:1,
                        simplify_by_decoration:1,
index 90419efe1052406381af3e35b70dc996fe8533ce..1a75fac05feaefa3cc0c57896aa6ee70813a324a 100644 (file)
@@ -241,7 +241,7 @@ static int disambiguate_committish_only(const unsigned char *sha1, void *cb_data
                return 0;
 
        /* We need to do this the hard way... */
-       obj = deref_tag(lookup_object(sha1), NULL, 0);
+       obj = deref_tag(parse_object(sha1), NULL, 0);
        if (obj && obj->type == OBJ_COMMIT)
                return 1;
        return 0;
index 86854248983be78b3702f5045a659dfe83bf4446..85415d0057402d40c4c9e98e3c94c41eb8dd940f 100644 (file)
@@ -226,6 +226,7 @@ static void print_submodule_summary(struct rev_info *rev, FILE *f,
        while ((commit = get_revision(rev))) {
                struct pretty_print_context ctx = {0};
                ctx.date_mode = rev->date_mode;
+               ctx.output_encoding = get_log_output_encoding();
                strbuf_setlen(&sb, 0);
                strbuf_addstr(&sb, line_prefix);
                if (commit->object.flags & SYMMETRIC_LEFT) {
index ec5246886132f919ec4b6b05bfedd65eb2011690..2167125008db5e3e1c7d13310c8da3a4243e8718 100644 (file)
--- a/t/README
+++ b/t/README
@@ -76,6 +76,11 @@ appropriately before running "make".
        command being run and their output if any are also
        output.
 
+--verbose-only=<pattern>::
+       Like --verbose, but the effect is limited to tests with
+       numbers matching <pattern>.  The number matched against is
+       simply the running count of the test within the file.
+
 --debug::
        This may help the person who is developing a new test.
        It causes the command defined with test_debug to run.
@@ -121,6 +126,11 @@ appropriately before running "make".
        the 't/valgrind/' directory and use the commands under
        't/valgrind/bin/'.
 
+--valgrind-only=<pattern>::
+       Like --valgrind, but the effect is limited to tests with
+       numbers matching <pattern>.  The number matched against is
+       simply the running count of the test within the file.
+
 --tee::
        In addition to printing the test output to the terminal,
        write it to files named 't/test-results/$TEST_NAME.out'.
index 8b5a71dc05216dc0acfb7761a4b9ca789c716ce0..45971f43b77142fe1bb90262974c83c786cfe43d 100755 (executable)
@@ -21,6 +21,7 @@ sub err {
        /^\s*declare\s+/ and err 'arrays/declare not portable';
        /^\s*[^#]\s*which\s/ and err 'which is not portable (please use type)';
        /test\s+[^=]*==/ and err '"test a == b" is not portable (please use =)';
+       /^\s*export\s+[^=]*=/ and err '"export FOO=bar" is not portable (please use FOO=bar && export FOO)';
        # this resets our $. for each file
        close ARGV if eof;
 }
index 4b74ae460b8943c176b6563d374e1663f89a1d7b..8ff87fb3f9bee1c6955f84b66027037100ebbbd3 100644 (file)
 #       ("squash", "fixup", "edit", or "reword") and the SHA1 taken
 #       from the specified line.
 #
+#   "exec_cmd_with_args" -- add an "exec cmd with args" line.
+#
 #   "#" -- Add a comment line.
 #
 #   ">" -- Add a blank line.
 
 set_fake_editor () {
-       echo "#!$SHELL_PATH" >fake-editor.sh
-       cat >> fake-editor.sh <<\EOF
-case "$1" in
-*/COMMIT_EDITMSG)
-       test -z "$EXPECT_HEADER_COUNT" ||
-               test "$EXPECT_HEADER_COUNT" = "$(sed -n '1s/^# This is a combination of \(.*\) commits\./\1/p' < "$1")" ||
+       write_script fake-editor.sh <<-\EOF
+       case "$1" in
+       */COMMIT_EDITMSG)
+               test -z "$EXPECT_HEADER_COUNT" ||
+                       test "$EXPECT_HEADER_COUNT" = "$(sed -n '1s/^# This is a combination of \(.*\) commits\./\1/p' < "$1")" ||
+                       exit
+               test -z "$FAKE_COMMIT_MESSAGE" || echo "$FAKE_COMMIT_MESSAGE" > "$1"
+               test -z "$FAKE_COMMIT_AMEND" || echo "$FAKE_COMMIT_AMEND" >> "$1"
                exit
-       test -z "$FAKE_COMMIT_MESSAGE" || echo "$FAKE_COMMIT_MESSAGE" > "$1"
-       test -z "$FAKE_COMMIT_AMEND" || echo "$FAKE_COMMIT_AMEND" >> "$1"
-       exit
-       ;;
-esac
-test -z "$EXPECT_COUNT" ||
-       test "$EXPECT_COUNT" = $(sed -e '/^#/d' -e '/^$/d' < "$1" | wc -l) ||
-       exit
-test -z "$FAKE_LINES" && exit
-grep -v '^#' < "$1" > "$1".tmp
-rm -f "$1"
-echo 'rebase -i script before editing:'
-cat "$1".tmp
-action=pick
-for line in $FAKE_LINES; do
-       case $line in
-       squash|fixup|edit|reword)
-               action="$line";;
-       exec*)
-               echo "$line" | sed 's/_/ /g' >> "$1";;
-       "#")
-               echo '# comment' >> "$1";;
-       ">")
-               echo >> "$1";;
-       *)
-               sed -n "${line}s/^pick/$action/p" < "$1".tmp >> "$1"
-               action=pick;;
+               ;;
        esac
-done
-echo 'rebase -i script after editing:'
-cat "$1"
-EOF
+       test -z "$EXPECT_COUNT" ||
+               test "$EXPECT_COUNT" = $(sed -e '/^#/d' -e '/^$/d' < "$1" | wc -l) ||
+               exit
+       test -z "$FAKE_LINES" && exit
+       grep -v '^#' < "$1" > "$1".tmp
+       rm -f "$1"
+       echo 'rebase -i script before editing:'
+       cat "$1".tmp
+       action=pick
+       for line in $FAKE_LINES; do
+               case $line in
+               squash|fixup|edit|reword)
+                       action="$line";;
+               exec*)
+                       echo "$line" | sed 's/_/ /g' >> "$1";;
+               "#")
+                       echo '# comment' >> "$1";;
+               ">")
+                       echo >> "$1";;
+               *)
+                       sed -n "${line}s/^pick/$action/p" < "$1".tmp >> "$1"
+                       action=pick;;
+               esac
+       done
+       echo 'rebase -i script after editing:'
+       cat "$1"
+       EOF
+
+       test_set_editor "$(pwd)/fake-editor.sh"
+}
+
+# After set_cat_todo_editor, rebase -i will write the todo list (ignoring
+# blank lines and comments) to stdout, and exit failure (so you should run
+# it with test_must_fail).  This can be used to verify the expected user
+# experience, for todo list changes that do not affect the outcome of
+# rebase; or as an extra check in addition to checking the outcome.
 
+set_cat_todo_editor () {
+       write_script fake-editor.sh <<-\EOF
+       grep "^[^#]" "$1"
+       exit 1
+       EOF
        test_set_editor "$(pwd)/fake-editor.sh"
-       chmod a+x fake-editor.sh
 }
 
 # checks that the revisions in "$2" represent a linear range with the
index ea25dd89e505525507c16c62d91fb07c092b064a..4ffd90127edb360142e492f6562c3c15c002d286 100644 (file)
@@ -1,55 +1,50 @@
 : included from 6002 and others
 
-[ -d .git/refs/tags ] || mkdir -p .git/refs/tags
+mkdir -p .git/refs/tags
 
-:> sed.script
+>sed.script
 
-# Answer the sha1 has associated with the tag. The tag must exist in .git or .git/refs/tags
-tag()
-{
+# Answer the sha1 has associated with the tag. The tag must exist in .git/refs/tags
+tag () {
        _tag=$1
-       [ -f .git/refs/tags/$_tag ] || error "tag: \"$_tag\" does not exist"
-       cat .git/refs/tags/$_tag
+       test -f ".git/refs/tags/$_tag" || error "tag: \"$_tag\" does not exist"
+       cat ".git/refs/tags/$_tag"
 }
 
 # Generate a commit using the text specified to make it unique and the tree
 # named by the tag specified.
-unique_commit()
-{
+unique_commit () {
        _text=$1
-        _tree=$2
+       _tree=$2
        shift 2
-       echo $_text | git commit-tree $(tag $_tree) "$@"
+       echo "$_text" | git commit-tree $(tag "$_tree") "$@"
 }
 
 # Save the output of a command into the tag specified. Prepend
 # a substitution script for the tag onto the front of sed.script
-save_tag()
-{
+save_tag () {
        _tag=$1
-       [ -n "$_tag" ] || error "usage: save_tag tag commit-args ..."
+       test -n "$_tag" || error "usage: save_tag tag commit-args ..."
        shift 1
-       "$@" >.git/refs/tags/$_tag
+       "$@" >".git/refs/tags/$_tag"
 
-        echo "s/$(tag $_tag)/$_tag/g" > sed.script.tmp
-       cat sed.script >> sed.script.tmp
+       echo "s/$(tag $_tag)/$_tag/g" >sed.script.tmp
+       cat sed.script >>sed.script.tmp
        rm sed.script
        mv sed.script.tmp sed.script
 }
 
 # Replace unhelpful sha1 hashses with their symbolic equivalents
-entag()
-{
+entag () {
        sed -f sed.script
 }
 
 # Execute a command after first saving, then setting the GIT_AUTHOR_EMAIL
 # tag to a specified value. Restore the original value on return.
-as_author()
-{
+as_author () {
        _author=$1
        shift 1
-        _save=$GIT_AUTHOR_EMAIL
+       _save=$GIT_AUTHOR_EMAIL
 
        GIT_AUTHOR_EMAIL="$_author"
        export GIT_AUTHOR_EMAIL
@@ -63,45 +58,58 @@ as_author()
        fi
 }
 
-commit_date()
-{
-        _commit=$1
-       git cat-file commit $_commit | sed -n "s/^committer .*> \([0-9]*\) .*/\1/p"
+commit_date () {
+       _commit=$1
+       git cat-file commit $_commit |
+       sed -n "s/^committer .*> \([0-9]*\) .*/\1/p"
 }
 
-on_committer_date()
-{
-    _date=$1
-    shift 1
-    GIT_COMMITTER_DATE="$_date"
-    export GIT_COMMITTER_DATE
-    "$@"
-    unset GIT_COMMITTER_DATE
+# Assign the value of fake date to a variable, but
+# allow fairly common "1971-08-16 00:00" to be omittd
+assign_fake_date () {
+       case "$2" in
+       ??:??:??)       eval "$1='1971-08-16 $2'" ;;
+       ??:??)          eval "$1='1971-08-16 00:$2'" ;;
+       ??)             eval "$1='1971-08-16 00:00:$2'" ;;
+       *)              eval "$1='$2'" ;;
+       esac
+}
+
+on_committer_date () {
+       assign_fake_date GIT_COMMITTER_DATE "$1"
+       export GIT_COMMITTER_DATE
+       shift 1
+       "$@"
+}
+
+on_dates () {
+       assign_fake_date GIT_COMMITTER_DATE "$1"
+       assign_fake_date GIT_AUTHOR_DATE "$2"
+       export GIT_COMMITTER_DATE GIT_AUTHOR_DATE
+       shift 2
+       "$@"
 }
 
 # Execute a command and suppress any error output.
-hide_error()
-{
+hide_error () {
        "$@" 2>/dev/null
 }
 
-check_output()
-{
+check_output () {
        _name=$1
        shift 1
-       if eval "$*" | entag > $_name.actual
+       if eval "$*" | entag >"$_name.actual"
        then
-               test_cmp $_name.expected $_name.actual
+               test_cmp "$_name.expected" "$_name.actual"
        else
-               return 1;
+               return 1
        fi
 }
 
 # Turn a reasonable test description into a reasonable test name.
 # All alphanums translated into -'s which are then compressed and stripped
 # from front and back.
-name_from_description()
-{
+name_from_description () {
        perl -pe '
                s/[^A-Za-z0-9.]/-/g;
                s/-+/-/g;
@@ -119,9 +127,11 @@ name_from_description()
 test_output_expect_success()
 {
        _description=$1
-        _test=$2
-        [ $# -eq 2 ] || error "usage: test_output_expect_success description test <<EOF ... EOF"
-        _name=$(echo $_description | name_from_description)
-       cat > $_name.expected
+       _test=$2
+       test $# -eq 2 ||
+       error "usage: test_output_expect_success description test <<EOF ... EOF"
+
+       _name=$(echo $_description | name_from_description)
+       cat >"$_name.expected"
        test_expect_success "$_description" "check_output $_name \"$_test\""
 }
index c552f561bffd9800d53064772ea640677b20a3ae..8848c1461909199a5c0bd587df8d9ef652c650ac 100644 (file)
@@ -66,7 +66,7 @@ You can set the following variables (also in your config.mak):
     GIT_PERF_LARGE_REPO
        Repositories to copy for the performance tests.  The normal
        repo should be at least git.git size.  The large repo should
-       probably be about linux-2.6.git size for optimal results.
+       probably be about linux.git size for optimal results.
        Both default to the git.git you are running from.
 
 You can also pass the options taken by ordinary git tests; the most
index a816fbcb7618bb8cdbf1f74a4fd2295923c02ea3..c61d5351e1ff0b1b4431eb28553d0d882ebe7451 100644 (file)
@@ -150,6 +150,7 @@ exit $ret' >&3 2>&4
 
 
 test_perf () {
+       test_start_
        test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq=
        test "$#" = 2 ||
        error "bug in the test script: not 2 or 3 parameters to test-expect-success"
@@ -187,7 +188,7 @@ test_perf () {
                base="$perf_results_dir"/"$perf_results_prefix$(basename "$0" .sh)"."$test_count"
                "$TEST_DIRECTORY"/perf/min_time.perl test_time.* >"$base".times
        fi
-       echo >&3 ""
+       test_finish_
 }
 
 # We extend test_done to print timings at the end (./run disables this
index 0f1318056cd06d8bcae615be5e573149ac5971d1..10be52beedb4058318555e096d51517f1c30ad9f 100755 (executable)
@@ -47,8 +47,14 @@ test_expect_failure 'pretend we have a known breakage' '
 
 run_sub_test_lib_test () {
        name="$1" descr="$2" # stdin is the body of the test code
+       shift 2
        mkdir "$name" &&
        (
+               # Pretend we're a test harness.  This prevents
+               # test-lib from writing the counts to a file that will
+               # later be summarized, showing spurious "failed" tests
+               HARNESS_ACTIVE=t &&
+               export HARNESS_ACTIVE &&
                cd "$name" &&
                cat >"$name.sh" <<-EOF &&
                #!$SHELL_PATH
@@ -65,7 +71,7 @@ run_sub_test_lib_test () {
                cat >>"$name.sh" &&
                chmod +x "$name.sh" &&
                export TEST_DIRECTORY &&
-               ./"$name.sh" >out 2>err
+               ./"$name.sh" "$@" >out 2>err
        )
 }
 
@@ -215,6 +221,60 @@ test_expect_success 'pretend we have a mix of all possible results' "
        EOF
 "
 
+test_expect_success 'test --verbose' '
+       test_must_fail run_sub_test_lib_test \
+               test-verbose "test verbose" --verbose <<-\EOF &&
+       test_expect_success "passing test" true
+       test_expect_success "test with output" "echo foo"
+       test_expect_success "failing test" false
+       test_done
+       EOF
+       mv test-verbose/out test-verbose/out+
+       grep -v "^Initialized empty" test-verbose/out+ >test-verbose/out &&
+       check_sub_test_lib_test test-verbose <<-\EOF
+       > expecting success: true
+       > Z
+       > ok 1 - passing test
+       > Z
+       > expecting success: echo foo
+       > foo
+       > Z
+       > ok 2 - test with output
+       > Z
+       > expecting success: false
+       > Z
+       > not ok 3 - failing test
+       > #     false
+       > Z
+       > # failed 1 among 3 test(s)
+       > 1..3
+       EOF
+'
+
+test_expect_success 'test --verbose-only' '
+       test_must_fail run_sub_test_lib_test \
+               test-verbose-only-2 "test verbose-only=2" \
+               --verbose-only=2 <<-\EOF &&
+       test_expect_success "passing test" true
+       test_expect_success "test with output" "echo foo"
+       test_expect_success "failing test" false
+       test_done
+       EOF
+       check_sub_test_lib_test test-verbose-only-2 <<-\EOF
+       > ok 1 - passing test
+       > Z
+       > expecting success: echo foo
+       > foo
+       > Z
+       > ok 2 - test with output
+       > Z
+       > not ok 3 - failing test
+       > #     false
+       > # failed 1 among 3 test(s)
+       > 1..3
+       EOF
+'
+
 test_set_prereq HAVEIT
 haveit=no
 test_expect_success HAVEIT 'test runs if prerequisite is satisfied' '
diff --git a/t/t0009-prio-queue.sh b/t/t0009-prio-queue.sh
new file mode 100755 (executable)
index 0000000..94045c3
--- /dev/null
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+test_description='basic tests for priority queue implementation'
+. ./test-lib.sh
+
+cat >expect <<'EOF'
+1
+2
+3
+4
+5
+5
+6
+7
+8
+9
+10
+EOF
+test_expect_success 'basic ordering' '
+       test-prio-queue 2 6 3 10 9 5 7 4 5 8 1 dump >actual &&
+       test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+2
+3
+4
+1
+5
+6
+EOF
+test_expect_success 'mixed put and get' '
+       test-prio-queue 6 2 4 get 5 3 get get 1 dump >actual &&
+       test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+1
+2
+NULL
+1
+2
+NULL
+EOF
+test_expect_success 'notice empty queue' '
+       test-prio-queue 1 2 get get get 1 2 get get get >actual &&
+       test_cmp expect actual
+'
+
+test_done
index 1a8f44c44ca3cce70990ec56fec61894be9b3086..e526184a0bfa3c8ad2171d0c41a7bee22cf9a04e 100755 (executable)
@@ -81,6 +81,14 @@ test_expect_success 'safecrlf: print warning only once' '
        test $(git add doublewarn 2>&1 | grep "CRLF will be replaced by LF" | wc -l) = 1
 '
 
+
+test_expect_success 'safecrlf: git diff demotes safecrlf=true to warn' '
+       git config core.autocrlf input &&
+       git config core.safecrlf true &&
+       git diff HEAD
+'
+
+
 test_expect_success 'switch off autocrlf, safecrlf, reset HEAD' '
        git config core.autocrlf false &&
        git config core.safecrlf false &&
index db228086d3977d304a3debd7c3ae6dc54c40ad17..4a155c8d095fb8ca2c2f88802d3501e01d07ce28 100755 (executable)
@@ -77,6 +77,7 @@ test_expect_success 'disambiguate blob' '
 
 test_expect_success 'disambiguate tree' '
        commit=$(echo "d7xm" | git commit-tree 000000000) &&
+       # this commit is fffff2e and not ambiguous with the 00000* objects
        test $(git rev-parse $commit^{tree}) = $(git rev-parse 0000000000cdc)
 '
 
@@ -99,10 +100,14 @@ test_expect_success 'disambiguate commit-ish' '
 
 test_expect_success 'disambiguate commit' '
        commit=$(echo "hoaxj" | git commit-tree 0000000000cdc -p 000000000) &&
+       # this commit is ffffffd8 and not ambiguous with the 00000* objects
        test $(git rev-parse $commit^) = $(git rev-parse 0000000000e4f)
 '
 
 test_expect_success 'log name1..name2 takes only commit-ishes on both ends' '
+       # These are underspecified from the prefix-length point of view
+       # to disambiguate the commit with other objects, but there is only
+       # one commit that has 00000* prefix at this point.
        git log 000000000..000000000 &&
        git log ..000000000 &&
        git log 000000000.. &&
@@ -112,16 +117,19 @@ test_expect_success 'log name1..name2 takes only commit-ishes on both ends' '
 '
 
 test_expect_success 'rev-parse name1..name2 takes only commit-ishes on both ends' '
+       # Likewise.
        git rev-parse 000000000..000000000 &&
        git rev-parse ..000000000 &&
        git rev-parse 000000000..
 '
 
 test_expect_success 'git log takes only commit-ish' '
+       # Likewise.
        git log 000000000
 '
 
 test_expect_success 'git reset takes only commit-ish' '
+       # Likewise.
        git reset 000000000
 '
 
@@ -131,26 +139,30 @@ test_expect_success 'first tag' '
 '
 
 test_expect_failure 'two semi-ambiguous commit-ish' '
+       # At this point, we have a tag 0000000000f8f that points
+       # at a commit 0000000000e4f, and a tree and a blob that
+       # share 0000000000 prefix with these tag and commit.
+       #
        # Once the parser becomes ultra-smart, it could notice that
-       # 110282 before ^{commit} name many different objects, but
+       # 0000000000 before ^{commit} name many different objects, but
        # that only two (HEAD and v1.0.0 tag) can be peeled to commit,
        # and that peeling them down to commit yield the same commit
        # without ambiguity.
-       git rev-parse --verify 110282^{commit} &&
+       git rev-parse --verify 0000000000^{commit} &&
 
        # likewise
-       git log 000000000..000000000 &&
-       git log ..000000000 &&
-       git log 000000000.. &&
-       git log 000000000...000000000 &&
-       git log ...000000000 &&
-       git log 000000000...
+       git log 0000000000..0000000000 &&
+       git log ..0000000000 &&
+       git log 0000000000.. &&
+       git log 0000000000...0000000000 &&
+       git log ...0000000000 &&
+       git log 0000000000...
 '
 
 test_expect_failure 'three semi-ambiguous tree-ish' '
        # Likewise for tree-ish.  HEAD, v1.0.0 and HEAD^{tree} share
        # the prefix but peeling them to tree yields the same thing
-       git rev-parse --verify 000000000^{tree}
+       git rev-parse --verify 0000000000^{tree}
 '
 
 test_expect_success 'parse describe name' '
@@ -241,7 +253,7 @@ test_expect_success 'ambiguous commit-ish' '
        # Now there are many commits that begin with the
        # common prefix, none of these should pick one at
        # random.  They all should result in ambiguity errors.
-       test_must_fail git rev-parse --verify 110282^{commit} &&
+       test_must_fail git rev-parse --verify 00000000^{commit} &&
 
        # likewise
        test_must_fail git log 000000000..000000000 &&
index b44de9dc623fc923941b61719f445170602e21be..e7ba8c505f579ab5cd53ee713eaf6ca894e471a1 100755 (executable)
@@ -116,4 +116,38 @@ test_expect_success 'master...' '
        test "z$(git rev-parse --verify HEAD)" = "z$(git rev-parse --verify master^)"
 '
 
+test_expect_success '"checkout -" works after a rebase A' '
+       git checkout master &&
+       git checkout other &&
+       git rebase master &&
+       git checkout - &&
+       test "z$(git symbolic-ref HEAD)" = "zrefs/heads/master"
+'
+
+test_expect_success '"checkout -" works after a rebase A B' '
+       git branch moodle master~1 &&
+       git checkout master &&
+       git checkout other &&
+       git rebase master moodle &&
+       git checkout - &&
+       test "z$(git symbolic-ref HEAD)" = "zrefs/heads/master"
+'
+
+test_expect_success '"checkout -" works after a rebase -i A' '
+       git checkout master &&
+       git checkout other &&
+       git rebase -i master &&
+       git checkout - &&
+       test "z$(git symbolic-ref HEAD)" = "zrefs/heads/master"
+'
+
+test_expect_success '"checkout -" works after a rebase -i A B' '
+       git branch foodle master~1 &&
+       git checkout master &&
+       git checkout other &&
+       git rebase master foodle &&
+       git checkout - &&
+       test "z$(git symbolic-ref HEAD)" = "zrefs/heads/master"
+'
+
 test_done
index 262e61744563b2ce4eb14df0e54f71d56c157007..f611d799b690457e306571adf16813b238a27dc9 100755 (executable)
@@ -11,6 +11,8 @@ This test prepares the following in the cache:
     path1       - a symlink
     path2/file2 - a file in a directory
     path3/file3 - a file in a directory
+    submod1/   - a submodule
+    submod2/   - another submodule
 
 and the following on the filesystem:
 
@@ -21,9 +23,11 @@ and the following on the filesystem:
     path4      - a file
     path5      - a symlink
     path6/file6 - a file in a directory
+    submod1/   - a submodule (modified from the cache)
+    submod2/   - a submodule (matches the cache)
 
-git ls-files -k should report that existing filesystem
-objects except path4, path5 and path6/file6 to be killed.
+git ls-files -k should report that existing filesystem objects
+path0/*, path1/*, path2 and path3 to be killed.
 
 Also for modification test, the cache and working tree have:
 
@@ -33,7 +37,7 @@ Also for modification test, the cache and working tree have:
     path10     - a non-empty file, cache dirtied.
 
 We should report path0, path1, path2/file2, path3/file3, path7 and path8
-modified without reporting path9 and path10.
+modified without reporting path9 and path10.  submod1 is also modified.
 '
 . ./test-lib.sh
 
@@ -48,6 +52,18 @@ test_expect_success 'git update-index --add to add various paths.' '
        : >path9 &&
        date >path10 &&
        git update-index --add -- path0 path?/file? path7 path8 path9 path10 &&
+       for i in 1 2
+       do
+               git init submod$i &&
+               (
+                       cd submod$i && git commit --allow-empty -m "empty $i"
+               ) || break
+       done &&
+       git update-index --add submod[12]
+       (
+               cd submod1 &&
+               git commit --allow-empty -m "empty 1 (updated)"
+       ) &&
        rm -fr path?    # leave path10 alone
 '
 
@@ -94,6 +110,7 @@ test_expect_success 'validate git ls-files -m output.' '
        path3/file3
        path7
        path8
+       submod1
        EOF
        test_cmp .expected .output
 '
index d6b414377306de88e8e294dd5eaadfcb3a234ec2..8a6ec039fe57f6a042fb3fe2e3f4c5807cfe4d68 100755 (executable)
@@ -950,4 +950,15 @@ test_expect_success 'rebase -i, with <onto> and <upstream> specified as :/quuxer
        git checkout branch1
 '
 
+test_expect_success 'rebase -i with --strategy and -X' '
+       git checkout -b conflict-merge-use-theirs conflict-branch &&
+       git reset --hard HEAD^ &&
+       echo five >conflict &&
+       echo Z >file1 &&
+       git commit -a -m "one file conflict" &&
+       EDITOR=true git rebase -i --strategy=recursive -Xours conflict-branch &&
+       test $(git show conflict-branch:conflict) = $(cat conflict) &&
+       test $(cat file1) = Z
+'
+
 test_done
index a1e86c4097ba096245b11a991c39e79886ca2b91..41370ab998c72e14f269a257304b3e0cc4aebc8c 100755 (executable)
@@ -4,6 +4,8 @@ test_description='auto squash'
 
 . ./test-lib.sh
 
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
 test_expect_success setup '
        echo 0 >file0 &&
        git add . &&
@@ -193,4 +195,59 @@ test_expect_success 'use commit --squash' '
        test_auto_commit_flags squash 2
 '
 
+test_auto_fixup_fixup () {
+       git reset --hard base &&
+       echo 1 >file1 &&
+       git add -u &&
+       test_tick &&
+       git commit -m "$1! first" &&
+       echo 2 >file1 &&
+       git add -u &&
+       test_tick &&
+       git commit -m "$1! $2! first" &&
+       git tag "final-$1-$2" &&
+       test_tick &&
+       (
+               set_cat_todo_editor &&
+               test_must_fail git rebase --autosquash -i HEAD^^^^ >actual &&
+               cat >expected <<-EOF &&
+               pick $(git rev-parse --short HEAD^^^) first commit
+               $1 $(git rev-parse --short HEAD^) $1! first
+               $1 $(git rev-parse --short HEAD) $1! $2! first
+               pick $(git rev-parse --short HEAD^^) second commit
+               EOF
+               test_cmp expected actual
+       ) &&
+       git rebase --autosquash -i HEAD^^^^ &&
+       git log --oneline >actual &&
+       test_line_count = 3 actual
+       git diff --exit-code "final-$1-$2" &&
+       test 2 = "$(git cat-file blob HEAD^:file1)" &&
+       if test "$1" = "fixup"
+       then
+               test 1 = $(git cat-file commit HEAD^ | grep first | wc -l)
+       elif test "$1" = "squash"
+       then
+               test 3 = $(git cat-file commit HEAD^ | grep first | wc -l)
+       else
+               false
+       fi
+}
+
+test_expect_success 'fixup! fixup!' '
+       test_auto_fixup_fixup fixup fixup
+'
+
+test_expect_success 'fixup! squash!' '
+       test_auto_fixup_fixup fixup squash
+'
+
+test_expect_success 'squash! squash!' '
+       test_auto_fixup_fixup squash squash
+'
+
+test_expect_success 'squash! fixup!' '
+       test_auto_fixup_fixup squash fixup
+'
+
 test_done
index debda7a678277e1198ba6620210b66984caf03a2..5d22f17ca2d3469c7542805e365246a70a5fba64 100755 (executable)
@@ -673,4 +673,22 @@ test_expect_success 'store updates stash ref and reflog' '
        grep quux bazzy
 '
 
+test_expect_success 'stash a change to turn a non-directory to a directory' '
+       git reset --hard &&
+       >testfile &&
+       git add testfile &&
+       git commit -m "add testfile as a regular file" &&
+       rm testfile &&
+       mkdir testfile &&
+       >testfile/file &&
+       test_must_fail git stash save "recover regular file" &&
+       test -f testfile/file
+'
+
+test_expect_success 'stash a change to turn a non-directory to a directory (forced)' '
+       git stash save --force "recover regular file (forced)" &&
+       ! test -f testfile/file &&
+       test -f testfile
+'
+
 test_done
index 32d4a604250d55e9221a416638c8c8c4fdd6ff87..1751c8330709c56a4b7019513e30434741847b95 100755 (executable)
@@ -1,6 +1,7 @@
 #!/bin/sh
 #
 # Copyright (c) 2009 Jens Lehmann, based on t7401 by Ping Yin
+# Copyright (c) 2011 Alexey Shumkin (+ non-UTF-8 commit encoding tests)
 #
 
 test_description='Support for verbose submodule differences in git diff
@@ -10,6 +11,9 @@ This test tries to verify the sanity of the --submodule option of git diff.
 
 . ./test-lib.sh
 
+# String "added" in German (translated with Google Translate), encoded in UTF-8,
+# used in sample commit log messages in add_file() function below.
+added=$(printf "hinzugef\303\274gt")
 add_file () {
        (
                cd "$1" &&
@@ -19,7 +23,8 @@ add_file () {
                        echo "$name" >"$name" &&
                        git add "$name" &&
                        test_tick &&
-                       git commit -m "Add $name" || exit
+                       msg_added_iso88591=$(echo "Add $name ($added $name)" | iconv -f utf-8 -t iso8859-1) &&
+                       git -c 'i18n.commitEncoding=iso8859-1' commit -m "$msg_added_iso88591"
                done >/dev/null &&
                git rev-parse --short --verify HEAD
        )
@@ -93,7 +98,7 @@ test_expect_success 'modified submodule(forward)' '
        git diff-index -p --submodule=log HEAD >actual &&
        cat >expected <<-EOF &&
        Submodule sm1 $head1..$head2:
-         > Add foo3
+         > Add foo3 ($added foo3)
        EOF
        test_cmp expected actual
 '
@@ -102,7 +107,7 @@ test_expect_success 'modified submodule(forward)' '
        git diff --submodule=log >actual &&
        cat >expected <<-EOF &&
        Submodule sm1 $head1..$head2:
-         > Add foo3
+         > Add foo3 ($added foo3)
        EOF
        test_cmp expected actual
 '
@@ -111,7 +116,7 @@ test_expect_success 'modified submodule(forward) --submodule' '
        git diff --submodule >actual &&
        cat >expected <<-EOF &&
        Submodule sm1 $head1..$head2:
-         > Add foo3
+         > Add foo3 ($added foo3)
        EOF
        test_cmp expected actual
 '
@@ -142,8 +147,8 @@ test_expect_success 'modified submodule(backward)' '
        git diff-index -p --submodule=log HEAD >actual &&
        cat >expected <<-EOF &&
        Submodule sm1 $head2..$head3 (rewind):
-         < Add foo3
-         < Add foo2
+         < Add foo3 ($added foo3)
+         < Add foo2 ($added foo2)
        EOF
        test_cmp expected actual
 '
@@ -153,10 +158,10 @@ test_expect_success 'modified submodule(backward and forward)' '
        git diff-index -p --submodule=log HEAD >actual &&
        cat >expected <<-EOF &&
        Submodule sm1 $head2...$head4:
-         > Add foo5
-         > Add foo4
-         < Add foo3
-         < Add foo2
+         > Add foo5 ($added foo5)
+         > Add foo4 ($added foo4)
+         < Add foo3 ($added foo3)
+         < Add foo2 ($added foo2)
        EOF
        test_cmp expected actual
 '
index 26fbfde4a36689a51c181c13f9d5680fd2780219..fb000411395d50639334c3c0395b2b975aa4bc12 100755 (executable)
@@ -1,20 +1,38 @@
 #!/bin/sh
 #
 # Copyright (c) 2010, Will Palmer
+# Copyright (c) 2011, Alexey Shumkin (+ non-UTF-8 commit encoding tests)
 #
 
 test_description='Test pretty formats'
 . ./test-lib.sh
 
+sample_utf8_part=$(printf "f\303\244ng")
+
+commit_msg () {
+       # String "initial. initial" partly in German
+       # (translated with Google Translate),
+       # encoded in UTF-8, used as a commit log message below.
+       msg="initial. an${sample_utf8_part}lich\n"
+       if test -n "$1"
+       then
+               printf "$msg" | iconv -f utf-8 -t "$1"
+       else
+               printf "$msg"
+       fi
+}
+
 test_expect_success 'set up basic repos' '
        >foo &&
        >bar &&
        git add foo &&
        test_tick &&
-       git commit -m initial &&
+       git config i18n.commitEncoding iso8859-1 &&
+       git commit -m "$(commit_msg iso8859-1)" &&
        git add bar &&
        test_tick &&
-       git commit -m "add bar"
+       git commit -m "add bar" &&
+       git config --unset i18n.commitEncoding
 '
 
 test_expect_success 'alias builtin format' '
@@ -38,6 +56,20 @@ test_expect_success 'alias user-defined format' '
        test_cmp expected actual
 '
 
+test_expect_success 'alias user-defined tformat with %s (iso8859-1 encoding)' '
+       git config i18n.logOutputEncoding iso8859-1 &&
+       git log --oneline >expected-s &&
+       git log --pretty="tformat:%h %s" >actual-s &&
+       git config --unset i18n.logOutputEncoding &&
+       test_cmp expected-s actual-s
+'
+
+test_expect_success 'alias user-defined tformat with %s (utf-8 encoding)' '
+       git log --oneline >expected-s &&
+       git log --pretty="tformat:%h %s" >actual-s &&
+       test_cmp expected-s actual-s
+'
+
 test_expect_success 'alias user-defined tformat' '
        git log --pretty="tformat:%h" >expected &&
        git config pretty.test-alias "tformat:%h" &&
@@ -72,13 +104,13 @@ test_expect_success 'alias loop' '
 '
 
 test_expect_success 'NUL separation' '
-       printf "add bar\0initial" >expected &&
+       printf "add bar\0$(commit_msg)" >expected &&
        git log -z --pretty="format:%s" >actual &&
        test_cmp expected actual
 '
 
 test_expect_success 'NUL termination' '
-       printf "add bar\0initial\0" >expected &&
+       printf "add bar\0$(commit_msg)\0" >expected &&
        git log -z --pretty="tformat:%s" >actual &&
        test_cmp expected actual
 '
@@ -86,7 +118,7 @@ test_expect_success 'NUL termination' '
 test_expect_success 'NUL separation with --stat' '
        stat0_part=$(git diff --stat HEAD^ HEAD) &&
        stat1_part=$(git diff-tree --no-commit-id --stat --root HEAD^) &&
-       printf "add bar\n$stat0_part\n\0initial\n$stat1_part\n" >expected &&
+       printf "add bar\n$stat0_part\n\0$(commit_msg)\n$stat1_part\n" >expected &&
        git log -z --stat --pretty="format:%s" >actual &&
        test_i18ncmp expected actual
 '
@@ -94,25 +126,29 @@ test_expect_success 'NUL separation with --stat' '
 test_expect_failure 'NUL termination with --stat' '
        stat0_part=$(git diff --stat HEAD^ HEAD) &&
        stat1_part=$(git diff-tree --no-commit-id --stat --root HEAD^) &&
-       printf "add bar\n$stat0_part\n\0initial\n$stat1_part\n\0" >expected &&
+       printf "add bar\n$stat0_part\n\0$(commit_msg)\n$stat1_part\n0" >expected &&
        git log -z --stat --pretty="tformat:%s" >actual &&
        test_i18ncmp expected actual
 '
 
 test_expect_success 'setup more commits' '
        test_commit "message one" one one message-one &&
-       test_commit "message two" two two message-two
+       test_commit "message two" two two message-two &&
+       head1=$(git rev-parse --verify --short HEAD~0) &&
+       head2=$(git rev-parse --verify --short HEAD~1) &&
+       head3=$(git rev-parse --verify --short HEAD~2) &&
+       head4=$(git rev-parse --verify --short HEAD~3)
 '
 
 test_expect_success 'left alignment formatting' '
        git log --pretty="format:%<(40)%s" >actual &&
        # complete the incomplete line at the end
        echo >>actual &&
-       qz_to_tab_space <<\EOF >expected &&
+       qz_to_tab_space <<EOF >expected &&
 message two                            Z
 message one                            Z
 add bar                                Z
-initial                                Z
+$(commit_msg)                    Z
 EOF
        test_cmp expected actual
 '
@@ -121,11 +157,11 @@ test_expect_success 'left alignment formatting at the nth column' '
        git log --pretty="format:%h %<|(40)%s" >actual &&
        # complete the incomplete line at the end
        echo >>actual &&
-       qz_to_tab_space <<\EOF >expected &&
-fa33ab1 message two                    Z
-7cd6c63 message one                    Z
-1711bf9 add bar                        Z
-af20c06 initial                        Z
+       qz_to_tab_space <<EOF >expected &&
+$head1 message two                    Z
+$head2 message one                    Z
+$head3 add bar                        Z
+$head4 $(commit_msg)            Z
 EOF
        test_cmp expected actual
 '
@@ -134,11 +170,11 @@ test_expect_success 'left alignment formatting with no padding' '
        git log --pretty="format:%<(1)%s" >actual &&
        # complete the incomplete line at the end
        echo >>actual &&
-       cat <<\EOF >expected &&
+       cat <<EOF >expected &&
 message two
 message one
 add bar
-initial
+$(commit_msg)
 EOF
        test_cmp expected actual
 '
@@ -147,11 +183,11 @@ test_expect_success 'left alignment formatting with trunc' '
        git log --pretty="format:%<(10,trunc)%s" >actual &&
        # complete the incomplete line at the end
        echo >>actual &&
-       qz_to_tab_space <<\EOF >expected &&
+       qz_to_tab_space <<EOF >expected &&
 message ..
 message ..
 add bar  Z
-initial  Z
+initial...
 EOF
        test_cmp expected actual
 '
@@ -160,11 +196,11 @@ test_expect_success 'left alignment formatting with ltrunc' '
        git log --pretty="format:%<(10,ltrunc)%s" >actual &&
        # complete the incomplete line at the end
        echo >>actual &&
-       qz_to_tab_space <<\EOF >expected &&
+       qz_to_tab_space <<EOF >expected &&
 ..sage two
 ..sage one
 add bar  Z
-initial  Z
+..${sample_utf8_part}lich
 EOF
        test_cmp expected actual
 '
@@ -173,11 +209,11 @@ test_expect_success 'left alignment formatting with mtrunc' '
        git log --pretty="format:%<(10,mtrunc)%s" >actual &&
        # complete the incomplete line at the end
        echo >>actual &&
-       qz_to_tab_space <<\EOF >expected &&
+       qz_to_tab_space <<EOF >expected &&
 mess.. two
 mess.. one
 add bar  Z
-initial  Z
+init..lich
 EOF
        test_cmp expected actual
 '
@@ -186,11 +222,11 @@ test_expect_success 'right alignment formatting' '
        git log --pretty="format:%>(40)%s" >actual &&
        # complete the incomplete line at the end
        echo >>actual &&
-       qz_to_tab_space <<\EOF >expected &&
+       qz_to_tab_space <<EOF >expected &&
 Z                            message two
 Z                            message one
 Z                                add bar
-Z                                initial
+Z                    $(commit_msg)
 EOF
        test_cmp expected actual
 '
@@ -199,11 +235,11 @@ test_expect_success 'right alignment formatting at the nth column' '
        git log --pretty="format:%h %>|(40)%s" >actual &&
        # complete the incomplete line at the end
        echo >>actual &&
-       qz_to_tab_space <<\EOF >expected &&
-fa33ab1                      message two
-7cd6c63                      message one
-1711bf9                          add bar
-af20c06                          initial
+       qz_to_tab_space <<EOF >expected &&
+$head1                      message two
+$head2                      message one
+$head3                          add bar
+$head4              $(commit_msg)
 EOF
        test_cmp expected actual
 '
@@ -212,11 +248,11 @@ test_expect_success 'right alignment formatting with no padding' '
        git log --pretty="format:%>(1)%s" >actual &&
        # complete the incomplete line at the end
        echo >>actual &&
-       cat <<\EOF >expected &&
+       cat <<EOF >expected &&
 message two
 message one
 add bar
-initial
+$(commit_msg)
 EOF
        test_cmp expected actual
 '
@@ -225,11 +261,11 @@ test_expect_success 'center alignment formatting' '
        git log --pretty="format:%><(40)%s" >actual &&
        # complete the incomplete line at the end
        echo >>actual &&
-       qz_to_tab_space <<\EOF >expected &&
+       qz_to_tab_space <<EOF >expected &&
 Z             message two              Z
 Z             message one              Z
 Z               add bar                Z
-Z               initial                Z
+Z         $(commit_msg)          Z
 EOF
        test_cmp expected actual
 '
@@ -238,11 +274,11 @@ test_expect_success 'center alignment formatting at the nth column' '
        git log --pretty="format:%h %><|(40)%s" >actual &&
        # complete the incomplete line at the end
        echo >>actual &&
-       qz_to_tab_space <<\EOF >expected &&
-fa33ab1           message two          Z
-7cd6c63           message one          Z
-1711bf9             add bar            Z
-af20c06             initial            Z
+       qz_to_tab_space <<EOF >expected &&
+$head1           message two          Z
+$head2           message one          Z
+$head3             add bar            Z
+$head4       $(commit_msg)      Z
 EOF
        test_cmp expected actual
 '
@@ -251,11 +287,11 @@ test_expect_success 'center alignment formatting with no padding' '
        git log --pretty="format:%><(1)%s" >actual &&
        # complete the incomplete line at the end
        echo >>actual &&
-       cat <<\EOF >expected &&
+       cat <<EOF >expected &&
 message two
 message one
 add bar
-initial
+$(commit_msg)
 EOF
        test_cmp expected actual
 '
@@ -265,11 +301,11 @@ test_expect_success 'left/right alignment formatting with stealing' '
        git log --pretty="format:%<(10,trunc)%s%>>(10,ltrunc)% an" >actual &&
        # complete the incomplete line at the end
        echo >>actual &&
-       cat <<\EOF >expected &&
+       cat <<EOF >expected &&
 short long  long long
 message ..   A U Thor
 add bar      A U Thor
-initial      A U Thor
+initial...   A U Thor
 EOF
        test_cmp expected actual
 '
index dd10ff053ce28ff2ef092e7b0740c809ba64f5b9..8f6e3922dce2b676221610d83a87c5b36d3bc5b6 100755 (executable)
@@ -42,107 +42,104 @@ check_tracking_branch () {
 }
 
 test_expect_success setup '
-
        setup_repository one &&
        setup_repository two &&
        (
-               cd two && git branch another
+               cd two &&
+               git branch another
        ) &&
        git clone one test
-
 '
 
 test_expect_success C_LOCALE_OUTPUT 'remote information for the origin' '
-(
-       cd test &&
-       tokens_match origin "$(git remote)" &&
-       check_remote_track origin master side &&
-       check_tracking_branch origin HEAD master side
-)
+       (
+               cd test &&
+               tokens_match origin "$(git remote)" &&
+               check_remote_track origin master side &&
+               check_tracking_branch origin HEAD master side
+       )
 '
 
 test_expect_success 'add another remote' '
-(
-       cd test &&
-       git remote add -f second ../two &&
-       tokens_match "origin second" "$(git remote)" &&
-       check_tracking_branch second master side another &&
-       git for-each-ref "--format=%(refname)" refs/remotes |
-       sed -e "/^refs\/remotes\/origin\//d" \
-           -e "/^refs\/remotes\/second\//d" >actual &&
-       >expect &&
-       test_cmp expect actual
-)
+       (
+               cd test &&
+               git remote add -f second ../two &&
+               tokens_match "origin second" "$(git remote)" &&
+               check_tracking_branch second master side another &&
+               git for-each-ref "--format=%(refname)" refs/remotes |
+               sed -e "/^refs\/remotes\/origin\//d" \
+                   -e "/^refs\/remotes\/second\//d" >actual &&
+               >expect &&
+               test_cmp expect actual
+       )
 '
 
-test_expect_success C_LOCALE_OUTPUT 'check remote tracking' '
-(
-       cd test &&
-       check_remote_track origin master side &&
-       check_remote_track second master side another
-)
+test_expect_success C_LOCALE_OUTPUT 'check remote-tracking' '
+       (
+               cd test &&
+               check_remote_track origin master side &&
+               check_remote_track second master side another
+       )
 '
 
 test_expect_success 'remote forces tracking branches' '
-(
-       cd test &&
-       case `git config remote.second.fetch` in
-       +*) true ;;
-        *) false ;;
-       esac
-)
+       (
+               cd test &&
+               case `git config remote.second.fetch` in
+               +*) true ;;
+                *) false ;;
+               esac
+       )
 '
 
 test_expect_success 'remove remote' '
-(
-       cd test &&
-       git symbolic-ref refs/remotes/second/HEAD refs/remotes/second/master &&
-       git remote rm second
-)
+       (
+               cd test &&
+               git symbolic-ref refs/remotes/second/HEAD refs/remotes/second/master &&
+               git remote rm second
+       )
 '
 
 test_expect_success C_LOCALE_OUTPUT 'remove remote' '
-(
-       cd test &&
-       tokens_match origin "$(git remote)" &&
-       check_remote_track origin master side &&
-       git for-each-ref "--format=%(refname)" refs/remotes |
-       sed -e "/^refs\/remotes\/origin\//d" >actual &&
-       >expect &&
-       test_cmp expect actual
-)
+       (
+               cd test &&
+               tokens_match origin "$(git remote)" &&
+               check_remote_track origin master side &&
+               git for-each-ref "--format=%(refname)" refs/remotes |
+               sed -e "/^refs\/remotes\/origin\//d" >actual &&
+               >expect &&
+               test_cmp expect actual
+       )
 '
 
 test_expect_success 'remove remote protects local branches' '
-(
-       cd test &&
-       { cat >expect1 <<EOF
-Note: A branch outside the refs/remotes/ hierarchy was not removed;
-to delete it, use:
-  git branch -d master
-EOF
-       } &&
-       { cat >expect2 <<EOF
-Note: Some branches outside the refs/remotes/ hierarchy were not removed;
-to delete them, use:
-  git branch -d foobranch
-  git branch -d master
-EOF
-       } &&
-       git tag footag &&
-       git config --add remote.oops.fetch "+refs/*:refs/*" &&
-       git remote remove oops 2>actual1 &&
-       git branch foobranch &&
-       git config --add remote.oops.fetch "+refs/*:refs/*" &&
-       git remote rm oops 2>actual2 &&
-       git branch -d foobranch &&
-       git tag -d footag &&
-       test_i18ncmp expect1 actual1 &&
-       test_i18ncmp expect2 actual2
-)
-'
-
-cat > test/expect << EOF
+       (
+               cd test &&
+               cat >expect1 <<-\EOF &&
+               Note: A branch outside the refs/remotes/ hierarchy was not removed;
+               to delete it, use:
+                 git branch -d master
+               EOF
+               cat >expect2 <<-\EOF &&
+               Note: Some branches outside the refs/remotes/ hierarchy were not removed;
+               to delete them, use:
+                 git branch -d foobranch
+                 git branch -d master
+               EOF
+               git tag footag &&
+               git config --add remote.oops.fetch "+refs/*:refs/*" &&
+               git remote remove oops 2>actual1 &&
+               git branch foobranch &&
+               git config --add remote.oops.fetch "+refs/*:refs/*" &&
+               git remote rm oops 2>actual2 &&
+               git branch -d foobranch &&
+               git tag -d footag &&
+               test_i18ncmp expect1 actual1 &&
+               test_i18ncmp expect2 actual2
+       )
+'
+
+cat >test/expect <<EOF
 * remote origin
   Fetch URL: $(pwd)/one
   Push  URL: $(pwd)/one
@@ -172,36 +169,40 @@ cat > test/expect << EOF
 EOF
 
 test_expect_success 'show' '
-       (cd test &&
-        git config --add remote.origin.fetch refs/heads/master:refs/heads/upstream &&
-        git fetch &&
-        git checkout -b ahead origin/master &&
-        echo 1 >> file &&
-        test_tick &&
-        git commit -m update file &&
-        git checkout master &&
-        git branch --track octopus origin/master &&
-        git branch --track rebase origin/master &&
-        git branch -d -r origin/master &&
-        git config --add remote.two.url ../two &&
-        git config --add remote.two.pushurl ../three &&
-        git config branch.rebase.rebase true &&
-        git config branch.octopus.merge "topic-a topic-b topic-c" &&
-        (cd ../one &&
-         echo 1 > file &&
-         test_tick &&
-         git commit -m update file) &&
-        git config --add remote.origin.push : &&
-        git config --add remote.origin.push refs/heads/master:refs/heads/upstream &&
-        git config --add remote.origin.push +refs/tags/lastbackup &&
-        git config --add remote.two.push +refs/heads/ahead:refs/heads/master &&
-        git config --add remote.two.push refs/heads/master:refs/heads/another &&
-        git remote show origin two > output &&
-        git branch -d rebase octopus &&
-        test_i18ncmp expect output)
-'
-
-cat > test/expect << EOF
+       (
+               cd test &&
+               git config --add remote.origin.fetch refs/heads/master:refs/heads/upstream &&
+               git fetch &&
+               git checkout -b ahead origin/master &&
+               echo 1 >>file &&
+               test_tick &&
+               git commit -m update file &&
+               git checkout master &&
+               git branch --track octopus origin/master &&
+               git branch --track rebase origin/master &&
+               git branch -d -r origin/master &&
+               git config --add remote.two.url ../two &&
+               git config --add remote.two.pushurl ../three &&
+               git config branch.rebase.rebase true &&
+               git config branch.octopus.merge "topic-a topic-b topic-c" &&
+               (
+                       cd ../one &&
+                       echo 1 >file &&
+                       test_tick &&
+                       git commit -m update file
+               ) &&
+               git config --add remote.origin.push : &&
+               git config --add remote.origin.push refs/heads/master:refs/heads/upstream &&
+               git config --add remote.origin.push +refs/tags/lastbackup &&
+               git config --add remote.two.push +refs/heads/ahead:refs/heads/master &&
+               git config --add remote.two.push refs/heads/master:refs/heads/another &&
+               git remote show origin two >output &&
+               git branch -d rebase octopus &&
+               test_i18ncmp expect output
+       )
+'
+
+cat >test/expect <<EOF
 * remote origin
   Fetch URL: $(pwd)/one
   Push  URL: $(pwd)/one
@@ -219,152 +220,187 @@ cat > test/expect << EOF
 EOF
 
 test_expect_success 'show -n' '
-       (mv one one.unreachable &&
-        cd test &&
-        git remote show -n origin > output &&
-        mv ../one.unreachable ../one &&
-        test_i18ncmp expect output)
+       mv one one.unreachable &&
+       (
+               cd test &&
+               git remote show -n origin >output &&
+               mv ../one.unreachable ../one &&
+               test_i18ncmp expect output
+       )
 '
 
 test_expect_success 'prune' '
-       (cd one &&
-        git branch -m side side2) &&
-       (cd test &&
-        git fetch origin &&
-        git remote prune origin &&
-        git rev-parse refs/remotes/origin/side2 &&
-        test_must_fail git rev-parse refs/remotes/origin/side)
+       (
+               cd one &&
+               git branch -m side side2
+       ) &&
+       (
+               cd test &&
+               git fetch origin &&
+               git remote prune origin &&
+               git rev-parse refs/remotes/origin/side2 &&
+               test_must_fail git rev-parse refs/remotes/origin/side
+       )
 '
 
 test_expect_success 'set-head --delete' '
-       (cd test &&
-        git symbolic-ref refs/remotes/origin/HEAD &&
-        git remote set-head --delete origin &&
-        test_must_fail git symbolic-ref refs/remotes/origin/HEAD)
+       (
+               cd test &&
+               git symbolic-ref refs/remotes/origin/HEAD &&
+               git remote set-head --delete origin &&
+               test_must_fail git symbolic-ref refs/remotes/origin/HEAD
+       )
 '
 
 test_expect_success 'set-head --auto' '
-       (cd test &&
-        git remote set-head --auto origin &&
-        echo refs/remotes/origin/master >expect &&
-        git symbolic-ref refs/remotes/origin/HEAD >output &&
-        test_cmp expect output
+       (
+               cd test &&
+               git remote set-head --auto origin &&
+               echo refs/remotes/origin/master >expect &&
+               git symbolic-ref refs/remotes/origin/HEAD >output &&
+               test_cmp expect output
        )
 '
 
-cat >test/expect <<EOF
+cat >test/expect <<\EOF
 error: Multiple remote HEAD branches. Please choose one explicitly with:
   git remote set-head two another
   git remote set-head two master
 EOF
 
 test_expect_success 'set-head --auto fails w/multiple HEADs' '
-       (cd test &&
-        test_must_fail git remote set-head --auto two >output 2>&1 &&
-       test_i18ncmp expect output)
+       (
+               cd test &&
+               test_must_fail git remote set-head --auto two >output 2>&1 &&
+               test_i18ncmp expect output
+       )
 '
 
-cat >test/expect <<EOF
+cat >test/expect <<\EOF
 refs/remotes/origin/side2
 EOF
 
 test_expect_success 'set-head explicit' '
-       (cd test &&
-        git remote set-head origin side2 &&
-        git symbolic-ref refs/remotes/origin/HEAD >output &&
-        git remote set-head origin master &&
-        test_cmp expect output)
+       (
+               cd test &&
+               git remote set-head origin side2 &&
+               git symbolic-ref refs/remotes/origin/HEAD >output &&
+               git remote set-head origin master &&
+               test_cmp expect output
+       )
 '
 
-cat > test/expect << EOF
+cat >test/expect <<EOF
 Pruning origin
 URL: $(pwd)/one
  * [would prune] origin/side2
 EOF
 
 test_expect_success 'prune --dry-run' '
-       (cd one &&
-        git branch -m side2 side) &&
-       (cd test &&
-        git remote prune --dry-run origin > output &&
-        git rev-parse refs/remotes/origin/side2 &&
-        test_must_fail git rev-parse refs/remotes/origin/side &&
-       (cd ../one &&
-        git branch -m side side2) &&
-        test_i18ncmp expect output)
+       (
+               cd one &&
+               git branch -m side2 side) &&
+       (
+               cd test &&
+               git remote prune --dry-run origin >output &&
+               git rev-parse refs/remotes/origin/side2 &&
+               test_must_fail git rev-parse refs/remotes/origin/side &&
+       (
+               cd ../one &&
+               git branch -m side side2) &&
+               test_i18ncmp expect output
+       )
 '
 
 test_expect_success 'add --mirror && prune' '
-       (mkdir mirror &&
-        cd mirror &&
-        git init --bare &&
-        git remote add --mirror -f origin ../one) &&
-       (cd one &&
-        git branch -m side2 side) &&
-       (cd mirror &&
-        git rev-parse --verify refs/heads/side2 &&
-        test_must_fail git rev-parse --verify refs/heads/side &&
-        git fetch origin &&
-        git remote prune origin &&
-        test_must_fail git rev-parse --verify refs/heads/side2 &&
-        git rev-parse --verify refs/heads/side)
+       mkdir mirror &&
+       (
+               cd mirror &&
+               git init --bare &&
+               git remote add --mirror -f origin ../one
+       ) &&
+       (
+               cd one &&
+               git branch -m side2 side
+       ) &&
+       (
+               cd mirror &&
+               git rev-parse --verify refs/heads/side2 &&
+               test_must_fail git rev-parse --verify refs/heads/side &&
+               git fetch origin &&
+               git remote prune origin &&
+               test_must_fail git rev-parse --verify refs/heads/side2 &&
+               git rev-parse --verify refs/heads/side
+       )
 '
 
 test_expect_success 'add --mirror=fetch' '
        mkdir mirror-fetch &&
        git init mirror-fetch/parent &&
-       (cd mirror-fetch/parent &&
-        test_commit one) &&
+       (
+               cd mirror-fetch/parent &&
+               test_commit one
+       ) &&
        git init --bare mirror-fetch/child &&
-       (cd mirror-fetch/child &&
-        git remote add --mirror=fetch -f parent ../parent)
+       (
+               cd mirror-fetch/child &&
+               git remote add --mirror=fetch -f parent ../parent
+       )
 '
 
 test_expect_success 'fetch mirrors act as mirrors during fetch' '
-       (cd mirror-fetch/parent &&
-        git branch new &&
-        git branch -m master renamed
+       (
+               cd mirror-fetch/parent &&
+               git branch new &&
+               git branch -m master renamed
        ) &&
-       (cd mirror-fetch/child &&
-        git fetch parent &&
-        git rev-parse --verify refs/heads/new &&
-        git rev-parse --verify refs/heads/renamed
+       (
+               cd mirror-fetch/child &&
+               git fetch parent &&
+               git rev-parse --verify refs/heads/new &&
+               git rev-parse --verify refs/heads/renamed
        )
 '
 
 test_expect_success 'fetch mirrors can prune' '
-       (cd mirror-fetch/child &&
-        git remote prune parent &&
-        test_must_fail git rev-parse --verify refs/heads/master
+       (
+               cd mirror-fetch/child &&
+               git remote prune parent &&
+               test_must_fail git rev-parse --verify refs/heads/master
        )
 '
 
 test_expect_success 'fetch mirrors do not act as mirrors during push' '
-       (cd mirror-fetch/parent &&
-        git checkout HEAD^0
+       (
+               cd mirror-fetch/parent &&
+               git checkout HEAD^0
        ) &&
-       (cd mirror-fetch/child &&
-        git branch -m renamed renamed2 &&
-        git push parent :
+       (
+               cd mirror-fetch/child &&
+               git branch -m renamed renamed2 &&
+               git push parent :
        ) &&
-       (cd mirror-fetch/parent &&
-        git rev-parse --verify renamed &&
-        test_must_fail git rev-parse --verify refs/heads/renamed2
+       (
+               cd mirror-fetch/parent &&
+               git rev-parse --verify renamed &&
+               test_must_fail git rev-parse --verify refs/heads/renamed2
        )
 '
 
 test_expect_success 'add fetch mirror with specific branches' '
        git init --bare mirror-fetch/track &&
-       (cd mirror-fetch/track &&
-        git remote add --mirror=fetch -t heads/new parent ../parent
+       (
+               cd mirror-fetch/track &&
+               git remote add --mirror=fetch -t heads/new parent ../parent
        )
 '
 
 test_expect_success 'fetch mirror respects specific branches' '
-       (cd mirror-fetch/track &&
-        git fetch parent &&
-        git rev-parse --verify refs/heads/new &&
-        test_must_fail git rev-parse --verify refs/heads/renamed
+       (
+               cd mirror-fetch/track &&
+               git fetch parent &&
+               git rev-parse --verify refs/heads/new &&
+               test_must_fail git rev-parse --verify refs/heads/renamed
        )
 '
 
@@ -372,60 +408,72 @@ test_expect_success 'add --mirror=push' '
        mkdir mirror-push &&
        git init --bare mirror-push/public &&
        git init mirror-push/private &&
-       (cd mirror-push/private &&
-        test_commit one &&
-        git remote add --mirror=push public ../public
+       (
+               cd mirror-push/private &&
+               test_commit one &&
+               git remote add --mirror=push public ../public
        )
 '
 
 test_expect_success 'push mirrors act as mirrors during push' '
-       (cd mirror-push/private &&
-        git branch new &&
-        git branch -m master renamed &&
-        git push public
+       (
+               cd mirror-push/private &&
+               git branch new &&
+               git branch -m master renamed &&
+               git push public
        ) &&
-       (cd mirror-push/private &&
-        git rev-parse --verify refs/heads/new &&
-        git rev-parse --verify refs/heads/renamed &&
-        test_must_fail git rev-parse --verify refs/heads/master
+       (
+               cd mirror-push/private &&
+               git rev-parse --verify refs/heads/new &&
+               git rev-parse --verify refs/heads/renamed &&
+               test_must_fail git rev-parse --verify refs/heads/master
        )
 '
 
 test_expect_success 'push mirrors do not act as mirrors during fetch' '
-       (cd mirror-push/public &&
-        git branch -m renamed renamed2 &&
-        git symbolic-ref HEAD refs/heads/renamed2
+       (
+               cd mirror-push/public &&
+               git branch -m renamed renamed2 &&
+               git symbolic-ref HEAD refs/heads/renamed2
        ) &&
-       (cd mirror-push/private &&
-        git fetch public &&
-        git rev-parse --verify refs/heads/renamed &&
-        test_must_fail git rev-parse --verify refs/heads/renamed2
+       (
+               cd mirror-push/private &&
+               git fetch public &&
+               git rev-parse --verify refs/heads/renamed &&
+               test_must_fail git rev-parse --verify refs/heads/renamed2
        )
 '
 
 test_expect_success 'push mirrors do not allow you to specify refs' '
        git init mirror-push/track &&
-       (cd mirror-push/track &&
-        test_must_fail git remote add --mirror=push -t new public ../public
+       (
+               cd mirror-push/track &&
+               test_must_fail git remote add --mirror=push -t new public ../public
        )
 '
 
 test_expect_success 'add alt && prune' '
-       (mkdir alttst &&
-        cd alttst &&
-        git init &&
-        git remote add -f origin ../one &&
-        git config remote.alt.url ../one &&
-        git config remote.alt.fetch "+refs/heads/*:refs/remotes/origin/*") &&
-       (cd one &&
-        git branch -m side side2) &&
-       (cd alttst &&
-        git rev-parse --verify refs/remotes/origin/side &&
-        test_must_fail git rev-parse --verify refs/remotes/origin/side2 &&
-        git fetch alt &&
-        git remote prune alt &&
-        test_must_fail git rev-parse --verify refs/remotes/origin/side &&
-        git rev-parse --verify refs/remotes/origin/side2)
+       mkdir alttst &&
+       (
+               cd alttst &&
+               git init &&
+               git remote add -f origin ../one &&
+               git config remote.alt.url ../one &&
+               git config remote.alt.fetch "+refs/heads/*:refs/remotes/origin/*"
+       ) &&
+       (
+               cd one &&
+               git branch -m side side2
+       ) &&
+       (
+               cd alttst &&
+               git rev-parse --verify refs/remotes/origin/side &&
+               test_must_fail git rev-parse --verify refs/remotes/origin/side2 &&
+               git fetch alt &&
+               git remote prune alt &&
+               test_must_fail git rev-parse --verify refs/remotes/origin/side &&
+               git rev-parse --verify refs/remotes/origin/side2
+       )
 '
 
 cat >test/expect <<\EOF
@@ -433,20 +481,24 @@ some-tag
 EOF
 
 test_expect_success 'add with reachable tags (default)' '
-       (cd one &&
-        >foobar &&
-        git add foobar &&
-        git commit -m "Foobar" &&
-        git tag -a -m "Foobar tag" foobar-tag &&
-        git reset --hard HEAD~1 &&
-        git tag -a -m "Some tag" some-tag) &&
-       (mkdir add-tags &&
-        cd add-tags &&
-        git init &&
-        git remote add -f origin ../one &&
-        git tag -l some-tag >../test/output &&
-        git tag -l foobar-tag >>../test/output &&
-        test_must_fail git config remote.origin.tagopt) &&
+       (
+               cd one &&
+               >foobar &&
+               git add foobar &&
+               git commit -m "Foobar" &&
+               git tag -a -m "Foobar tag" foobar-tag &&
+               git reset --hard HEAD~1 &&
+               git tag -a -m "Some tag" some-tag
+       ) &&
+       mkdir add-tags &&
+       (
+               cd add-tags &&
+               git init &&
+               git remote add -f origin ../one &&
+               git tag -l some-tag >../test/output &&
+               git tag -l foobar-tag >>../test/output &&
+               test_must_fail git config remote.origin.tagopt
+       ) &&
        test_cmp test/expect test/output
 '
 
@@ -457,14 +509,16 @@ foobar-tag
 EOF
 
 test_expect_success 'add --tags' '
-       (rm -rf add-tags &&
-        mkdir add-tags &&
-        cd add-tags &&
-        git init &&
-        git remote add -f --tags origin ../one &&
-        git tag -l some-tag >../test/output &&
-        git tag -l foobar-tag >>../test/output &&
-        git config remote.origin.tagopt >>../test/output) &&
+       rm -rf add-tags &&
+       (
+               mkdir add-tags &&
+               cd add-tags &&
+               git init &&
+               git remote add -f --tags origin ../one &&
+               git tag -l some-tag >../test/output &&
+               git tag -l foobar-tag >>../test/output &&
+               git config remote.origin.tagopt >>../test/output
+       ) &&
        test_cmp test/expect test/output
 '
 
@@ -473,25 +527,31 @@ cat >test/expect <<\EOF
 EOF
 
 test_expect_success 'add --no-tags' '
-       (rm -rf add-tags &&
-        mkdir add-no-tags &&
-        cd add-no-tags &&
-        git init &&
-        git remote add -f --no-tags origin ../one &&
-        git tag -l some-tag >../test/output &&
-        git tag -l foobar-tag >../test/output &&
-        git config remote.origin.tagopt >>../test/output) &&
-       (cd one &&
-        git tag -d some-tag foobar-tag) &&
+       rm -rf add-tags &&
+       (
+               mkdir add-no-tags &&
+               cd add-no-tags &&
+               git init &&
+               git remote add -f --no-tags origin ../one &&
+               git tag -l some-tag >../test/output &&
+               git tag -l foobar-tag >../test/output &&
+               git config remote.origin.tagopt >>../test/output
+       ) &&
+       (
+               cd one &&
+               git tag -d some-tag foobar-tag
+       ) &&
        test_cmp test/expect test/output
 '
 
 test_expect_success 'reject --no-no-tags' '
-       (cd add-no-tags &&
-        test_must_fail git remote add -f --no-no-tags neworigin ../one)
+       (
+               cd add-no-tags &&
+               test_must_fail git remote add -f --no-no-tags neworigin ../one
+       )
 '
 
-cat > one/expect << EOF
+cat >one/expect <<\EOF
   apis/master
   apis/side
   drosophila/another
@@ -500,17 +560,17 @@ cat > one/expect << EOF
 EOF
 
 test_expect_success 'update' '
-
-       (cd one &&
-        git remote add drosophila ../two &&
-        git remote add apis ../mirror &&
-        git remote update &&
-        git branch -r > output &&
-        test_cmp expect output)
-
+       (
+               cd one &&
+               git remote add drosophila ../two &&
+               git remote add apis ../mirror &&
+               git remote update &&
+               git branch -r >output &&
+               test_cmp expect output
+       )
 '
 
-cat > one/expect << EOF
+cat >one/expect <<\EOF
   drosophila/another
   drosophila/master
   drosophila/side
@@ -521,34 +581,40 @@ cat > one/expect << EOF
 EOF
 
 test_expect_success 'update with arguments' '
-
-       (cd one &&
-        for b in $(git branch -r)
-        do
+       (
+               cd one &&
+               for b in $(git branch -r)
+               do
                git branch -r -d $b || break
-        done &&
-        git remote add manduca ../mirror &&
-        git remote add megaloprepus ../mirror &&
-        git config remotes.phobaeticus "drosophila megaloprepus" &&
-        git config remotes.titanus manduca &&
-        git remote update phobaeticus titanus &&
-        git branch -r > output &&
-        test_cmp expect output)
-
+               done &&
+               git remote add manduca ../mirror &&
+               git remote add megaloprepus ../mirror &&
+               git config remotes.phobaeticus "drosophila megaloprepus" &&
+               git config remotes.titanus manduca &&
+               git remote update phobaeticus titanus &&
+               git branch -r >output &&
+               test_cmp expect output
+       )
 '
 
 test_expect_success 'update --prune' '
-
-       (cd one &&
-        git branch -m side2 side3) &&
-       (cd test &&
-        git remote update --prune &&
-        (cd ../one && git branch -m side3 side2) &&
-        git rev-parse refs/remotes/origin/side3 &&
-        test_must_fail git rev-parse refs/remotes/origin/side2)
+       (
+               cd one &&
+               git branch -m side2 side3
+       ) &&
+       (
+               cd test &&
+               git remote update --prune &&
+               (
+                       cd ../one &&
+                       git branch -m side3 side2
+               ) &&
+               git rev-parse refs/remotes/origin/side3 &&
+               test_must_fail git rev-parse refs/remotes/origin/side2
+       )
 '
 
-cat > one/expect << EOF
+cat >one/expect <<-\EOF
   apis/master
   apis/side
   manduca/master
@@ -558,176 +624,204 @@ cat > one/expect << EOF
 EOF
 
 test_expect_success 'update default' '
-
-       (cd one &&
-        for b in $(git branch -r)
-        do
+       (
+               cd one &&
+               for b in $(git branch -r)
+               do
                git branch -r -d $b || break
-        done &&
-        git config remote.drosophila.skipDefaultUpdate true &&
-        git remote update default &&
-        git branch -r > output &&
-        test_cmp expect output)
-
+               done &&
+               git config remote.drosophila.skipDefaultUpdate true &&
+               git remote update default &&
+               git branch -r >output &&
+               test_cmp expect output
+       )
 '
 
-cat > one/expect << EOF
+cat >one/expect <<\EOF
   drosophila/another
   drosophila/master
   drosophila/side
 EOF
 
 test_expect_success 'update default (overridden, with funny whitespace)' '
-
-       (cd one &&
-        for b in $(git branch -r)
-        do
+       (
+               cd one &&
+               for b in $(git branch -r)
+               do
                git branch -r -d $b || break
-        done &&
-        git config remotes.default "$(printf "\t drosophila  \n")" &&
-        git remote update default &&
-        git branch -r > output &&
-        test_cmp expect output)
-
+               done &&
+               git config remotes.default "$(printf "\t drosophila  \n")" &&
+               git remote update default &&
+               git branch -r >output &&
+               test_cmp expect output
+       )
 '
 
 test_expect_success 'update (with remotes.default defined)' '
-
-       (cd one &&
-        for b in $(git branch -r)
-        do
+       (
+               cd one &&
+               for b in $(git branch -r)
+               do
                git branch -r -d $b || break
-        done &&
-        git config remotes.default "drosophila" &&
-        git remote update &&
-        git branch -r > output &&
-        test_cmp expect output)
-
+               done &&
+               git config remotes.default "drosophila" &&
+               git remote update &&
+               git branch -r >output &&
+               test_cmp expect output
+       )
 '
 
 test_expect_success '"remote show" does not show symbolic refs' '
-
        git clone one three &&
-       (cd three &&
-        git remote show origin > output &&
-        ! grep "^ *HEAD$" < output &&
-        ! grep -i stale < output)
-
+       (
+               cd three &&
+               git remote show origin >output &&
+               ! grep "^ *HEAD$" < output &&
+               ! grep -i stale < output
+       )
 '
 
 test_expect_success 'reject adding remote with an invalid name' '
-
        test_must_fail git remote add some:url desired-name
-
 '
 
 # The first three test if the tracking branches are properly renamed,
 # the last two ones check if the config is updated.
 
 test_expect_success 'rename a remote' '
-
        git clone one four &&
-       (cd four &&
-        git remote rename origin upstream &&
-        rmdir .git/refs/remotes/origin &&
-        test "$(git symbolic-ref refs/remotes/upstream/HEAD)" = "refs/remotes/upstream/master" &&
-        test "$(git rev-parse upstream/master)" = "$(git rev-parse master)" &&
-        test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/remotes/upstream/*" &&
-        test "$(git config branch.master.remote)" = "upstream")
-
+       (
+               cd four &&
+               git remote rename origin upstream &&
+               rmdir .git/refs/remotes/origin &&
+               test "$(git symbolic-ref refs/remotes/upstream/HEAD)" = "refs/remotes/upstream/master" &&
+               test "$(git rev-parse upstream/master)" = "$(git rev-parse master)" &&
+               test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/remotes/upstream/*" &&
+               test "$(git config branch.master.remote)" = "upstream"
+       )
 '
 
 test_expect_success 'rename does not update a non-default fetch refspec' '
-
        git clone one four.one &&
-       (cd four.one &&
-        git config remote.origin.fetch +refs/heads/*:refs/heads/origin/* &&
-        git remote rename origin upstream &&
-        test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/heads/origin/*" &&
-        git rev-parse -q origin/master)
-
+       (
+               cd four.one &&
+               git config remote.origin.fetch +refs/heads/*:refs/heads/origin/* &&
+               git remote rename origin upstream &&
+               test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/heads/origin/*" &&
+               git rev-parse -q origin/master
+       )
 '
 
 test_expect_success 'rename a remote with name part of fetch spec' '
-
        git clone one four.two &&
-       (cd four.two &&
-        git remote rename origin remote &&
-        git remote rename remote upstream &&
-        test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/remotes/upstream/*")
-
+       (
+               cd four.two &&
+               git remote rename origin remote &&
+               git remote rename remote upstream &&
+               test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/remotes/upstream/*"
+       )
 '
 
 test_expect_success 'rename a remote with name prefix of other remote' '
-
        git clone one four.three &&
-       (cd four.three &&
-        git remote add o git://example.com/repo.git &&
-        git remote rename o upstream &&
-        test "$(git rev-parse origin/master)" = "$(git rev-parse master)")
-
+       (
+               cd four.three &&
+               git remote add o git://example.com/repo.git &&
+               git remote rename o upstream &&
+               test "$(git rev-parse origin/master)" = "$(git rev-parse master)"
+       )
 '
 
-cat > remotes_origin << EOF
+cat >remotes_origin <<EOF
 URL: $(pwd)/one
 Push: refs/heads/master:refs/heads/upstream
+Push: refs/heads/next:refs/heads/upstream2
 Pull: refs/heads/master:refs/heads/origin
+Pull: refs/heads/next:refs/heads/origin2
 EOF
 
 test_expect_success 'migrate a remote from named file in $GIT_DIR/remotes' '
        git clone one five &&
        origin_url=$(pwd)/one &&
-       (cd five &&
-        git remote remove origin &&
-        mkdir -p .git/remotes &&
-        cat ../remotes_origin > .git/remotes/origin &&
-        git remote rename origin origin &&
-        ! test -f .git/remotes/origin &&
-        test "$(git config remote.origin.url)" = "$origin_url" &&
-        test "$(git config remote.origin.push)" = "refs/heads/master:refs/heads/upstream" &&
-        test "$(git config remote.origin.fetch)" = "refs/heads/master:refs/heads/origin")
+       (
+               cd five &&
+               git remote remove origin &&
+               mkdir -p .git/remotes &&
+               cat ../remotes_origin >.git/remotes/origin &&
+               git remote rename origin origin &&
+               test_path_is_missing .git/remotes/origin &&
+               test "$(git config remote.origin.url)" = "$origin_url" &&
+               cat >push_expected <<-\EOF &&
+               refs/heads/master:refs/heads/upstream
+               refs/heads/next:refs/heads/upstream2
+               EOF
+               cat >fetch_expected <<-\EOF &&
+               refs/heads/master:refs/heads/origin
+               refs/heads/next:refs/heads/origin2
+               EOF
+               git config --get-all remote.origin.push >push_actual &&
+               git config --get-all remote.origin.fetch >fetch_actual &&
+               test_cmp push_expected push_actual &&
+               test_cmp fetch_expected fetch_actual
+       )
 '
 
 test_expect_success 'migrate a remote from named file in $GIT_DIR/branches' '
        git clone one six &&
        origin_url=$(pwd)/one &&
-       (cd six &&
-        git remote rm origin &&
-        echo "$origin_url" > .git/branches/origin &&
-        git remote rename origin origin &&
-        ! test -f .git/branches/origin &&
-        test "$(git config remote.origin.url)" = "$origin_url" &&
-        test "$(git config remote.origin.fetch)" = "refs/heads/master:refs/heads/origin")
+       (
+               cd six &&
+               git remote rm origin &&
+               echo "$origin_url" >.git/branches/origin &&
+               git remote rename origin origin &&
+               test_path_is_missing .git/branches/origin &&
+               test "$(git config remote.origin.url)" = "$origin_url" &&
+               test "$(git config remote.origin.fetch)" = "refs/heads/master:refs/heads/origin" &&
+               test "$(git config remote.origin.push)" = "HEAD:refs/heads/master"
+       )
 '
 
-test_expect_success 'remote prune to cause a dangling symref' '
+test_expect_success 'migrate a remote from named file in $GIT_DIR/branches (2)' '
        git clone one seven &&
+       (
+               cd seven &&
+               git remote rm origin &&
+               echo "quux#foom" > .git/branches/origin &&
+               git remote rename origin origin &&
+               test_path_is_missing .git/branches/origin &&
+               test "$(git config remote.origin.url)" = "quux" &&
+               test "$(git config remote.origin.fetch)" = "refs/heads/foom:refs/heads/origin"
+               test "$(git config remote.origin.push)" = "HEAD:refs/heads/foom"
+       )
+'
+
+test_expect_success 'remote prune to cause a dangling symref' '
+       git clone one eight &&
        (
                cd one &&
                git checkout side2 &&
                git branch -D master
        ) &&
        (
-               cd seven &&
+               cd eight &&
                git remote prune origin
        ) >err 2>&1 &&
        test_i18ngrep "has become dangling" err &&
 
        : And the dangling symref will not cause other annoying errors &&
        (
-               cd seven &&
+               cd eight &&
                git branch -a
        ) 2>err &&
        ! grep "points nowhere" err &&
        (
-               cd seven &&
+               cd eight &&
                test_must_fail git branch nomore origin
        ) 2>err &&
        grep "dangling symref" err
 '
 
 test_expect_success 'show empty remote' '
-
        test_create_repo empty &&
        git clone empty empty-clone &&
        (
index 4736da8f36fd4e69fea0008829f4304020ea338d..6a5ac3add47399918737168e60f75d2d7cec1557 100755 (executable)
@@ -15,17 +15,19 @@ test_expect_success 'setup bare remotes' '
 
 # $1 = local revision
 # $2 = remote revision (tested to be equal to the local one)
+# $3 = [optional] repo to check for actual output (repo1 by default)
 check_pushed_commit () {
        git log -1 --format='%h %s' "$1" >expect &&
-       git --git-dir=repo1 log -1 --format='%h %s' "$2" >actual &&
+       git --git-dir="${3:-repo1}" log -1 --format='%h %s' "$2" >actual &&
        test_cmp expect actual
 }
 
 # $1 = push.default value
 # $2 = expected target branch for the push
+# $3 = [optional] repo to check for actual output (repo1 by default)
 test_push_success () {
        git -c push.default="$1" push &&
-       check_pushed_commit HEAD "$2"
+       check_pushed_commit HEAD "$2" "$3"
 }
 
 # $1 = push.default value
@@ -37,6 +39,26 @@ test_push_failure () {
        test_cmp expect actual
 }
 
+# $1 = success or failure
+# $2 = push.default value
+# $3 = branch to check for actual output (master or foo)
+# $4 = [optional] switch to triangular workflow
+test_pushdefault_workflow () {
+       workflow=central
+       pushdefault=parent1
+       if test -n "${4-}"; then
+               workflow=triangular
+               pushdefault=parent2
+       fi
+       test_expect_success "push.default = $2 $1 in $workflow workflows" "
+               test_config branch.master.remote parent1 &&
+               test_config branch.master.merge refs/heads/foo &&
+               test_config remote.pushdefault $pushdefault &&
+               test_commit commit-for-$2${4+-triangular} &&
+               test_push_$1 $2 $3 ${4+repo2}
+       "
+}
+
 test_expect_success '"upstream" pushes to configured upstream' '
        git checkout master &&
        test_config branch.master.remote parent1 &&
@@ -48,7 +70,6 @@ test_expect_success '"upstream" pushes to configured upstream' '
 test_expect_success '"upstream" does not push on unconfigured remote' '
        git checkout master &&
        test_unconfig branch.master.remote &&
-       test_config push.default upstream &&
        test_commit three &&
        test_push_failure upstream
 '
@@ -57,7 +78,6 @@ test_expect_success '"upstream" does not push on unconfigured branch' '
        git checkout master &&
        test_config branch.master.remote parent1 &&
        test_unconfig branch.master.merge &&
-       test_config push.default upstream
        test_commit four &&
        test_push_failure upstream
 '
@@ -115,4 +135,41 @@ test_expect_success 'push to existing branch, upstream configured with different
        test_cmp expect-other-name actual-other-name
 '
 
+# We are on 'master', which integrates with 'foo' from parent1
+# remote (set in test_pushdefault_workflow helper).  Push to
+# parent1 in centralized, and push to parent2 in triangular workflow.
+# The parent1 repository has 'master' and 'foo' branches, while
+# the parent2 repository has only 'master' branch.
+#
+# test_pushdefault_workflow() arguments:
+# $1 = success or failure
+# $2 = push.default value
+# $3 = branch to check for actual output (master or foo)
+# $4 = [optional] switch to triangular workflow
+
+# update parent1's master (which is not our upstream)
+test_pushdefault_workflow success current master
+
+# update parent1's foo (which is our upstream)
+test_pushdefault_workflow success upstream foo
+
+# upsream is foo which is not the name of the current branch
+test_pushdefault_workflow failure simple master
+
+# master and foo are updated
+test_pushdefault_workflow success matching master
+
+# master is updated
+test_pushdefault_workflow success current master triangular
+
+# upstream mode cannot be used in triangular
+test_pushdefault_workflow failure upstream foo triangular
+
+# in triangular, 'simple' works as 'current' and update the branch
+# with the same name.
+test_pushdefault_workflow success simple master triangular
+
+# master is updated (parent2 does not have foo)
+test_pushdefault_workflow success matching master triangular
+
 test_done
index fb07536a0f5b7e1000cf4945f55be3305df88e90..43ad7724845cd0e1523aadd60845f048a6b92ce5 100755 (executable)
@@ -39,25 +39,25 @@ test_bisection_diff()
 date >path0
 git update-index --add path0
 save_tag tree git write-tree
-on_committer_date "1971-08-16 00:00:00" hide_error save_tag root unique_commit root tree
-on_committer_date "1971-08-16 00:00:01" save_tag l0 unique_commit l0 tree -p root
-on_committer_date "1971-08-16 00:00:02" save_tag l1 unique_commit l1 tree -p l0
-on_committer_date "1971-08-16 00:00:03" save_tag l2 unique_commit l2 tree -p l1
-on_committer_date "1971-08-16 00:00:04" save_tag a0 unique_commit a0 tree -p l2
-on_committer_date "1971-08-16 00:00:05" save_tag a1 unique_commit a1 tree -p a0
-on_committer_date "1971-08-16 00:00:06" save_tag b1 unique_commit b1 tree -p a0
-on_committer_date "1971-08-16 00:00:07" save_tag c1 unique_commit c1 tree -p b1
-on_committer_date "1971-08-16 00:00:08" save_tag b2 unique_commit b2 tree -p b1
-on_committer_date "1971-08-16 00:00:09" save_tag b3 unique_commit b2 tree -p b2
-on_committer_date "1971-08-16 00:00:10" save_tag c2 unique_commit c2 tree -p c1 -p b2
-on_committer_date "1971-08-16 00:00:11" save_tag c3 unique_commit c3 tree -p c2
-on_committer_date "1971-08-16 00:00:12" save_tag a2 unique_commit a2 tree -p a1
-on_committer_date "1971-08-16 00:00:13" save_tag a3 unique_commit a3 tree -p a2
-on_committer_date "1971-08-16 00:00:14" save_tag b4 unique_commit b4 tree -p b3 -p a3
-on_committer_date "1971-08-16 00:00:15" save_tag a4 unique_commit a4 tree -p a3 -p b4 -p c3
-on_committer_date "1971-08-16 00:00:16" save_tag l3 unique_commit l3 tree -p a4
-on_committer_date "1971-08-16 00:00:17" save_tag l4 unique_commit l4 tree -p l3
-on_committer_date "1971-08-16 00:00:18" save_tag l5 unique_commit l5 tree -p l4
+on_committer_date "00:00" hide_error save_tag root unique_commit root tree
+on_committer_date "00:01" save_tag l0 unique_commit l0 tree -p root
+on_committer_date "00:02" save_tag l1 unique_commit l1 tree -p l0
+on_committer_date "00:03" save_tag l2 unique_commit l2 tree -p l1
+on_committer_date "00:04" save_tag a0 unique_commit a0 tree -p l2
+on_committer_date "00:05" save_tag a1 unique_commit a1 tree -p a0
+on_committer_date "00:06" save_tag b1 unique_commit b1 tree -p a0
+on_committer_date "00:07" save_tag c1 unique_commit c1 tree -p b1
+on_committer_date "00:08" save_tag b2 unique_commit b2 tree -p b1
+on_committer_date "00:09" save_tag b3 unique_commit b2 tree -p b2
+on_committer_date "00:10" save_tag c2 unique_commit c2 tree -p c1 -p b2
+on_committer_date "00:11" save_tag c3 unique_commit c3 tree -p c2
+on_committer_date "00:12" save_tag a2 unique_commit a2 tree -p a1
+on_committer_date "00:13" save_tag a3 unique_commit a3 tree -p a2
+on_committer_date "00:14" save_tag b4 unique_commit b4 tree -p b3 -p a3
+on_committer_date "00:15" save_tag a4 unique_commit a4 tree -p a3 -p b4 -p c3
+on_committer_date "00:16" save_tag l3 unique_commit l3 tree -p a4
+on_committer_date "00:17" save_tag l4 unique_commit l4 tree -p l3
+on_committer_date "00:18" save_tag l5 unique_commit l5 tree -p l4
 git update-ref HEAD $(tag l5)
 
 
@@ -90,29 +90,29 @@ git update-ref HEAD $(tag l5)
 #     F
 
 
-on_committer_date "1971-08-16 00:00:00" hide_error save_tag F unique_commit F tree
-on_committer_date "1971-08-16 00:00:01" save_tag e8 unique_commit e8 tree -p F
-on_committer_date "1971-08-16 00:00:02" save_tag e7 unique_commit e7 tree -p e8
-on_committer_date "1971-08-16 00:00:03" save_tag e6 unique_commit e6 tree -p e7
-on_committer_date "1971-08-16 00:00:04" save_tag e5 unique_commit e5 tree -p e6
-on_committer_date "1971-08-16 00:00:05" save_tag f4 unique_commit f4 tree -p F
-on_committer_date "1971-08-16 00:00:06" save_tag f3 unique_commit f3 tree -p f4
-on_committer_date "1971-08-16 00:00:07" save_tag f2 unique_commit f2 tree -p f3
-on_committer_date "1971-08-16 00:00:08" save_tag f1 unique_commit f1 tree -p f2
-on_committer_date "1971-08-16 00:00:09" save_tag e4 unique_commit e4 tree -p e5
-on_committer_date "1971-08-16 00:00:10" save_tag e3 unique_commit e3 tree -p e4
-on_committer_date "1971-08-16 00:00:11" save_tag e2 unique_commit e2 tree -p e3
-on_committer_date "1971-08-16 00:00:12" save_tag e1 unique_commit e1 tree -p e2
-on_committer_date "1971-08-16 00:00:13" save_tag E unique_commit E tree -p e1 -p f1
-
-on_committer_date "1971-08-16 00:00:00" hide_error save_tag U unique_commit U tree
-on_committer_date "1971-08-16 00:00:01" save_tag u0 unique_commit u0 tree -p U
-on_committer_date "1971-08-16 00:00:01" save_tag u1 unique_commit u1 tree -p u0
-on_committer_date "1971-08-16 00:00:02" save_tag u2 unique_commit u2 tree -p u0
-on_committer_date "1971-08-16 00:00:03" save_tag u3 unique_commit u3 tree -p u0
-on_committer_date "1971-08-16 00:00:04" save_tag u4 unique_commit u4 tree -p u0
-on_committer_date "1971-08-16 00:00:05" save_tag u5 unique_commit u5 tree -p u0
-on_committer_date "1971-08-16 00:00:06" save_tag V unique_commit V tree -p u1 -p u2 -p u3 -p u4 -p u5
+on_committer_date "00:00" hide_error save_tag F unique_commit F tree
+on_committer_date "00:01" save_tag e8 unique_commit e8 tree -p F
+on_committer_date "00:02" save_tag e7 unique_commit e7 tree -p e8
+on_committer_date "00:03" save_tag e6 unique_commit e6 tree -p e7
+on_committer_date "00:04" save_tag e5 unique_commit e5 tree -p e6
+on_committer_date "00:05" save_tag f4 unique_commit f4 tree -p F
+on_committer_date "00:06" save_tag f3 unique_commit f3 tree -p f4
+on_committer_date "00:07" save_tag f2 unique_commit f2 tree -p f3
+on_committer_date "00:08" save_tag f1 unique_commit f1 tree -p f2
+on_committer_date "00:09" save_tag e4 unique_commit e4 tree -p e5
+on_committer_date "00:10" save_tag e3 unique_commit e3 tree -p e4
+on_committer_date "00:11" save_tag e2 unique_commit e2 tree -p e3
+on_committer_date "00:12" save_tag e1 unique_commit e1 tree -p e2
+on_committer_date "00:13" save_tag E unique_commit E tree -p e1 -p f1
+
+on_committer_date "00:00" hide_error save_tag U unique_commit U tree
+on_committer_date "00:01" save_tag u0 unique_commit u0 tree -p U
+on_committer_date "00:01" save_tag u1 unique_commit u1 tree -p u0
+on_committer_date "00:02" save_tag u2 unique_commit u2 tree -p u0
+on_committer_date "00:03" save_tag u3 unique_commit u3 tree -p u0
+on_committer_date "00:04" save_tag u4 unique_commit u4 tree -p u0
+on_committer_date "00:05" save_tag u5 unique_commit u5 tree -p u0
+on_committer_date "00:06" save_tag V unique_commit V tree -p u1 -p u2 -p u3 -p u4 -p u5
 
 test_sequence()
 {
index e4c52b0214b5028e8c3db035dc96ca3285e61506..24d1836f417d67a224f0d9bef619952a39ed28eb 100755 (executable)
@@ -16,39 +16,34 @@ list_duplicates()
 date >path0
 git update-index --add path0
 save_tag tree git write-tree
-on_committer_date "1971-08-16 00:00:00" hide_error save_tag root unique_commit root tree
-on_committer_date "1971-08-16 00:00:01" save_tag l0 unique_commit l0 tree -p root
-on_committer_date "1971-08-16 00:00:02" save_tag l1 unique_commit l1 tree -p l0
-on_committer_date "1971-08-16 00:00:03" save_tag l2 unique_commit l2 tree -p l1
-on_committer_date "1971-08-16 00:00:04" save_tag a0 unique_commit a0 tree -p l2
-on_committer_date "1971-08-16 00:00:05" save_tag a1 unique_commit a1 tree -p a0
-on_committer_date "1971-08-16 00:00:06" save_tag b1 unique_commit b1 tree -p a0
-on_committer_date "1971-08-16 00:00:07" save_tag c1 unique_commit c1 tree -p b1
-on_committer_date "1971-08-16 00:00:08" as_author foobar@example.com save_tag b2 unique_commit b2 tree -p b1
-on_committer_date "1971-08-16 00:00:09" save_tag b3 unique_commit b3 tree -p b2
-on_committer_date "1971-08-16 00:00:10" save_tag c2 unique_commit c2 tree -p c1 -p b2
-on_committer_date "1971-08-16 00:00:11" save_tag c3 unique_commit c3 tree -p c2
-on_committer_date "1971-08-16 00:00:12" save_tag a2 unique_commit a2 tree -p a1
-on_committer_date "1971-08-16 00:00:13" save_tag a3 unique_commit a3 tree -p a2
-on_committer_date "1971-08-16 00:00:14" save_tag b4 unique_commit b4 tree -p b3 -p a3
-on_committer_date "1971-08-16 00:00:15" save_tag a4 unique_commit a4 tree -p a3 -p b4 -p c3
-on_committer_date "1971-08-16 00:00:16" save_tag l3 unique_commit l3 tree -p a4
-on_committer_date "1971-08-16 00:00:17" save_tag l4 unique_commit l4 tree -p l3
-on_committer_date "1971-08-16 00:00:18" save_tag l5 unique_commit l5 tree -p l4
-on_committer_date "1971-08-16 00:00:19" save_tag m1 unique_commit m1 tree -p a4 -p c3
-on_committer_date "1971-08-16 00:00:20" save_tag m2 unique_commit m2 tree -p c3 -p a4
-on_committer_date "1971-08-16 00:00:21" hide_error save_tag alt_root unique_commit alt_root tree
-on_committer_date "1971-08-16 00:00:22" save_tag r0 unique_commit r0 tree -p alt_root
-on_committer_date "1971-08-16 00:00:23" save_tag r1 unique_commit r1 tree -p r0
-on_committer_date "1971-08-16 00:00:24" save_tag l5r1 unique_commit l5r1 tree -p l5 -p r1
-on_committer_date "1971-08-16 00:00:25" save_tag r1l5 unique_commit r1l5 tree -p r1 -p l5
+on_dates "00:00" "00:00" hide_error save_tag root unique_commit root tree
+on_dates "00:01" "00:01" save_tag l0 unique_commit l0 tree -p root
+on_dates "00:02" "00:02" save_tag l1 unique_commit l1 tree -p l0
+on_dates "00:03" "00:03" save_tag l2 unique_commit l2 tree -p l1
+on_dates "00:04" "00:04" save_tag a0 unique_commit a0 tree -p l2
+on_dates "00:05" "00:05" save_tag a1 unique_commit a1 tree -p a0
+on_dates "00:06" "00:06" save_tag b1 unique_commit b1 tree -p a0
+on_dates "00:07" "00:07" save_tag c1 unique_commit c1 tree -p b1
+on_dates "00:08" "00:08" as_author foobar@example.com save_tag b2 unique_commit b2 tree -p b1
+on_dates "00:09" "00:09" save_tag b3 unique_commit b3 tree -p b2
+on_dates "00:10" "00:10" save_tag c2 unique_commit c2 tree -p c1 -p b2
+on_dates "00:11" "00:11" save_tag c3 unique_commit c3 tree -p c2
+on_dates "00:12" "00:00" save_tag a2 unique_commit a2 tree -p a1
+on_dates "00:13" "00:01" save_tag a3 unique_commit a3 tree -p a2
+on_dates "00:14" "00:14" save_tag b4 unique_commit b4 tree -p b3 -p a3
+on_dates "00:15" "00:15" save_tag a4 unique_commit a4 tree -p a3 -p b4 -p c3
+on_dates "00:16" "00:16" save_tag l3 unique_commit l3 tree -p a4
+on_dates "00:17" "00:17" save_tag l4 unique_commit l4 tree -p l3
+on_dates "00:18" "00:18" save_tag l5 unique_commit l5 tree -p l4
+on_dates "00:19" "00:19" save_tag m1 unique_commit m1 tree -p a4 -p c3
+on_dates "00:20" "00:20" save_tag m2 unique_commit m2 tree -p c3 -p a4
+on_dates "00:21" "00:21" hide_error save_tag alt_root unique_commit alt_root tree
+on_dates "00:22" "00:22" save_tag r0 unique_commit r0 tree -p alt_root
+on_dates "00:23" "00:23" save_tag r1 unique_commit r1 tree -p r0
+on_dates "00:24" "00:24" save_tag l5r1 unique_commit l5r1 tree -p l5 -p r1
+on_dates "00:25" "00:25" save_tag r1l5 unique_commit r1l5 tree -p r1 -p l5
 
 
-#
-# note: as of 20/6, it isn't possible to create duplicate parents, so this
-# can't be tested.
-#
-#on_committer_date "1971-08-16 00:00:20" save_tag m3 unique_commit m3 tree -p c3 -p a4 -p c3
 hide_error save_tag e1 as_author e@example.com unique_commit e1 tree
 save_tag e2 as_author e@example.com unique_commit e2 tree -p e1
 save_tag f1 as_author f@example.com unique_commit f1 tree -p e1
@@ -105,6 +100,50 @@ l0
 root
 EOF
 
+test_output_expect_success 'simple date order' 'git rev-list --date-order  HEAD' <<EOF
+l5
+l4
+l3
+a4
+b4
+a3
+a2
+c3
+c2
+b3
+b2
+c1
+b1
+a1
+a0
+l2
+l1
+l0
+root
+EOF
+
+test_output_expect_success 'simple author-date order' 'git rev-list --author-date-order  HEAD' <<EOF
+l5
+l4
+l3
+a4
+b4
+c3
+c2
+b3
+b2
+c1
+b1
+a3
+a2
+a1
+a0
+l2
+l1
+l0
+root
+EOF
+
 test_output_expect_success 'two diamonds topo order (g6)' 'git rev-list --topo-order  g4' <<EOF
 g4
 h2
index 0393c9fd0b1c155817855857d7476d1638d2296f..98744038eccb396c752e6a4b6ced702733c0d396 100755 (executable)
@@ -1,20 +1,45 @@
 #!/bin/sh
 
+# Copyright (c) 2009 Jens Lehmann
+# Copyright (c) 2011 Alexey Shumkin (+ non-UTF-8 commit encoding tests)
+
 test_description='git rev-list --pretty=format test'
 
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/lib-terminal.sh
 
 test_tick
+# String "added" in German
+# (translated with Google Translate),
+# encoded in UTF-8, used as a commit log message below.
+added=$(printf "added (hinzugef\303\274gt) foo")
+added_iso88591=$(echo "$added" | iconv -f utf-8 -t iso8859-1)
+# same but "changed"
+changed=$(printf "changed (ge\303\244ndert) foo")
+changed_iso88591=$(echo "$changed" | iconv -f utf-8 -t iso8859-1)
+
 test_expect_success 'setup' '
-touch foo && git add foo && git commit -m "added foo" &&
-  echo changed >foo && git commit -a -m "changed foo"
+       : >foo &&
+       git add foo &&
+       git config i18n.commitEncoding iso8859-1 &&
+       git commit -m "$added_iso88591" &&
+       head1=$(git rev-parse --verify HEAD) &&
+       head1_short=$(git rev-parse --verify --short $head1) &&
+       tree1=$(git rev-parse --verify HEAD:) &&
+       tree1_short=$(git rev-parse --verify --short $tree1) &&
+       echo "$changed" > foo &&
+       git commit -a -m "$changed_iso88591" &&
+       head2=$(git rev-parse --verify HEAD) &&
+       head2_short=$(git rev-parse --verify --short $head2) &&
+       tree2=$(git rev-parse --verify HEAD:) &&
+       tree2_short=$(git rev-parse --verify --short $tree2)
+       git config --unset i18n.commitEncoding
 '
 
-# usage: test_format name format_string <expected_output
+# usage: test_format name format_string [failure] <expected_output
 test_format () {
        cat >expect.$1
-       test_expect_success "format $1" "
+       test_expect_${3:-success} "format $1" "
                git rev-list --pretty=format:'$2' master >output.$1 &&
                test_cmp expect.$1 output.$1
        "
@@ -32,49 +57,49 @@ has_no_color () {
        test_cmp expect "$1"
 }
 
-test_format percent %%h <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
+test_format percent %%h <<EOF
+commit $head2
 %h
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+commit $head1
 %h
 EOF
 
-test_format hash %H%n%h <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
-131a310eb913d107dd3c09a65d1651175898735d
-131a310
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
-86c75cfd708a0e5868dc876ed5b8bb66c80b4873
-86c75cf
+test_format hash %H%n%h <<EOF
+commit $head2
+$head2
+$head2_short
+commit $head1
+$head1
+$head1_short
 EOF
 
-test_format tree %T%n%t <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
-fe722612f26da5064c32ca3843aa154bdb0b08a0
-fe72261
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
-4d5fcadc293a348e88f777dc0920f11e7d71441c
-4d5fcad
+test_format tree %T%n%t <<EOF
+commit $head2
+$tree2
+$tree2_short
+commit $head1
+$tree1
+$tree1_short
 EOF
 
-test_format parents %P%n%p <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
-86c75cfd708a0e5868dc876ed5b8bb66c80b4873
-86c75cf
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+test_format parents %P%n%p <<EOF
+commit $head2
+$head1
+$head1_short
+commit $head1
 
 
 EOF
 
 # we don't test relative here
-test_format author %an%n%ae%n%ad%n%aD%n%at <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
+test_format author %an%n%ae%n%ad%n%aD%n%at <<EOF
+commit $head2
 A U Thor
 author@example.com
 Thu Apr 7 15:13:13 2005 -0700
 Thu, 7 Apr 2005 15:13:13 -0700
 1112911993
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+commit $head1
 A U Thor
 author@example.com
 Thu Apr 7 15:13:13 2005 -0700
@@ -82,14 +107,14 @@ Thu, 7 Apr 2005 15:13:13 -0700
 1112911993
 EOF
 
-test_format committer %cn%n%ce%n%cd%n%cD%n%ct <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
+test_format committer %cn%n%ce%n%cd%n%cD%n%ct <<EOF
+commit $head2
 C O Mitter
 committer@example.com
 Thu Apr 7 15:13:13 2005 -0700
 Thu, 7 Apr 2005 15:13:13 -0700
 1112911993
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+commit $head1
 C O Mitter
 committer@example.com
 Thu Apr 7 15:13:13 2005 -0700
@@ -97,43 +122,45 @@ Thu, 7 Apr 2005 15:13:13 -0700
 1112911993
 EOF
 
-test_format encoding %e <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+test_format encoding %e <<EOF
+commit $head2
+iso8859-1
+commit $head1
+iso8859-1
 EOF
 
-test_format subject %s <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
-changed foo
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
-added foo
+test_format subject %s <<EOF
+commit $head2
+$changed
+commit $head1
+$added
 EOF
 
-test_format body %b <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+test_format body %b <<EOF
+commit $head2
+commit $head1
 EOF
 
-test_format raw-body %B <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
-changed foo
+test_format raw-body %B <<EOF
+commit $head2
+$changed
 
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
-added foo
+commit $head1
+$added
 
 EOF
 
-test_format colors %Credfoo%Cgreenbar%Cbluebaz%Cresetxyzzy <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
+test_format colors %Credfoo%Cgreenbar%Cbluebaz%Cresetxyzzy <<EOF
+commit $head2
 \e[31mfoo\e[32mbar\e[34mbaz\e[mxyzzy
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+commit $head1
 \e[31mfoo\e[32mbar\e[34mbaz\e[mxyzzy
 EOF
 
-test_format advanced-colors '%C(red yellow bold)foo%C(reset)' <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
+test_format advanced-colors '%C(red yellow bold)foo%C(reset)' <<EOF
+commit $head2
 \e[1;31;43mfoo\e[m
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+commit $head1
 \e[1;31;43mfoo\e[m
 EOF
 
@@ -179,46 +206,71 @@ test_expect_success '%C(auto) respects --color=auto (stdout not tty)' '
        )
 '
 
-cat >commit-msg <<'EOF'
+iconv -f utf-8 -t iso8859-1 > commit-msg <<EOF
 Test printing of complex bodies
 
 This commit message is much longer than the others,
 and it will be encoded in iso8859-1. We should therefore
-include an iso8859 character: ¡bueno!
+include an iso8859 character: Â¡bueno!
 EOF
+
 test_expect_success 'setup complex body' '
-git config i18n.commitencoding iso8859-1 &&
-  echo change2 >foo && git commit -a -F commit-msg
+       git config i18n.commitencoding iso8859-1 &&
+       echo change2 >foo && git commit -a -F commit-msg &&
+       head3=$(git rev-parse --verify HEAD) &&
+       head3_short=$(git rev-parse --short $head3)
 '
 
-test_format complex-encoding %e <<'EOF'
-commit 1ed88da4a5b5ed8c449114ac131efc62178734c3
+test_format complex-encoding %e <<EOF
+commit $head3
+iso8859-1
+commit $head2
+iso8859-1
+commit $head1
 iso8859-1
-commit 131a310eb913d107dd3c09a65d1651175898735d
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
 EOF
 
-test_format complex-subject %s <<'EOF'
-commit 1ed88da4a5b5ed8c449114ac131efc62178734c3
+test_format complex-subject %s <<EOF
+commit $head3
 Test printing of complex bodies
-commit 131a310eb913d107dd3c09a65d1651175898735d
-changed foo
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
-added foo
+commit $head2
+$changed_iso88591
+commit $head1
+$added_iso88591
 EOF
 
-test_format complex-body %b <<'EOF'
-commit 1ed88da4a5b5ed8c449114ac131efc62178734c3
-This commit message is much longer than the others,
-and it will be encoded in iso8859-1. We should therefore
-include an iso8859 character: ¡bueno!
+test_expect_success 'prepare expected messages (for test %b)' '
+       cat <<-EOF >expected.utf-8 &&
+       commit $head3
+       This commit message is much longer than the others,
+       and it will be encoded in iso8859-1. We should therefore
+       include an iso8859 character: ¡bueno!
+
+       commit $head2
+       commit $head1
+       EOF
+       iconv -f utf-8 -t iso8859-1 expected.utf-8 >expected.iso8859-1
+'
+
+test_format complex-body %b <expected.iso8859-1
 
-commit 131a310eb913d107dd3c09a65d1651175898735d
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+# Git uses i18n.commitEncoding if no i18n.logOutputEncoding set
+# so unset i18n.commitEncoding to test encoding conversion
+git config --unset i18n.commitEncoding
+
+test_format complex-subject-commitencoding-unset %s <<EOF
+commit $head3
+Test printing of complex bodies
+commit $head2
+$changed
+commit $head1
+$added
 EOF
 
+test_format complex-body-commitencoding-unset %b <expected.utf-8
+
 test_expect_success '%x00 shows NUL' '
-       echo  >expect commit 1ed88da4a5b5ed8c449114ac131efc62178734c3 &&
+       echo  >expect commit $head3 &&
        echo >>expect fooQbar &&
        git rev-list -1 --format=foo%x00bar HEAD >actual.nul &&
        nul_to_q <actual.nul >actual &&
@@ -265,12 +317,12 @@ test_expect_success 'add LF before non-empty (2)' '
 
 test_expect_success 'add SP before non-empty (1)' '
        git show -s --pretty=format:"%s% bThanks" HEAD^^ >actual &&
-       test $(wc -w <actual) = 2
+       test $(wc -w <actual) = 3
 '
 
 test_expect_success 'add SP before non-empty (2)' '
        git show -s --pretty=format:"%s% sThanks" HEAD^^ >actual &&
-       test $(wc -w <actual) = 4
+       test $(wc -w <actual) = 6
 '
 
 test_expect_success '--abbrev' '
index 300be86c385a93588e987f591357c57421b9cbae..8d4b50d1b5816d69ab165119773a7ffc0c360c0a 100755 (executable)
@@ -9,6 +9,19 @@ Documented tests for git reset'
 
 . ./test-lib.sh
 
+commit_msg () {
+       # String "modify 2nd file (changed)" partly in German
+       # (translated with Google Translate),
+       # encoded in UTF-8, used as a commit log message below.
+       msg="modify 2nd file (ge\303\244ndert)\n"
+       if test -n "$1"
+       then
+               printf "$msg" | iconv -f utf-8 -t "$1"
+       else
+               printf "$msg"
+       fi
+}
+
 test_expect_success 'creating initial files and commits' '
        test_tick &&
        echo "1st file" >first &&
@@ -28,7 +41,7 @@ test_expect_success 'creating initial files and commits' '
 
        echo "1st line 2nd file" >secondfile &&
        echo "2nd line 2nd file" >>secondfile &&
-       git commit -a -m "modify 2nd file" &&
+       git -c "i18n.commitEncoding=iso8859-1" commit -a -m "$(commit_msg iso8859-1)" &&
        head5=$(git rev-parse --verify HEAD)
 '
 # git log --pretty=oneline # to see those SHA1 involved
@@ -44,6 +57,20 @@ check_changes () {
        done | test_cmp .cat_expect -
 }
 
+test_expect_success 'reset --hard message' '
+       hex=$(git log -1 --format="%h") &&
+       git reset --hard > .actual &&
+       echo HEAD is now at $hex $(commit_msg) > .expected &&
+       test_cmp .expected .actual
+'
+
+test_expect_success 'reset --hard message (iso8859-1 logoutputencoding)' '
+       hex=$(git log -1 --format="%h") &&
+       git -c "i18n.logOutputEncoding=iso8859-1" reset --hard > .actual &&
+       echo HEAD is now at $hex $(commit_msg iso8859-1) > .expected &&
+       test_cmp .expected .actual
+'
+
 >.diff_expect
 >.cached_expect
 cat >.cat_expect <<EOF
@@ -192,7 +219,8 @@ test_expect_success \
        'changing files and redo the last commit should succeed' '
        echo "3rd line 2nd file" >>secondfile &&
        git commit -a -C ORIG_HEAD &&
-       check_changes 3d3b7be011a58ca0c179ae45d94e6c83c0b0cd0d &&
+       head4=$(git rev-parse --verify HEAD) &&
+       check_changes $head4 &&
        test "$(git rev-parse ORIG_HEAD)" = \
                        $head5
 '
@@ -211,7 +239,7 @@ test_expect_success \
        git reset --hard HEAD~2 &&
        check_changes ddaefe00f1da16864591c61fdc7adb5d7cd6b74e &&
        test "$(git rev-parse ORIG_HEAD)" = \
-                       3d3b7be011a58ca0c179ae45d94e6c83c0b0cd0d
+                       $head4
 '
 
 >.diff_expect
@@ -303,7 +331,7 @@ test_expect_success 'redoing the last two commits should succeed' '
 
        echo "1st line 2nd file" >secondfile &&
        echo "2nd line 2nd file" >>secondfile &&
-       git commit -a -m "modify 2nd file" &&
+       git -c "i18n.commitEncoding=iso8859-1" commit -a -m "$(commit_msg iso8859-1)" &&
        check_changes $head5
 '
 
@@ -326,10 +354,11 @@ test_expect_success '--hard reset to HEAD should clear a failed merge' '
        git checkout branch2 &&
        echo "3rd line in branch2" >>secondfile &&
        git commit -a -m "change in branch2" &&
+       head3=$(git rev-parse --verify HEAD) &&
 
        test_must_fail git pull . branch1 &&
        git reset --hard &&
-       check_changes 77abb337073fb4369a7ad69ff6f5ec0e4d6b54bb
+       check_changes $head3
 '
 
 >.diff_expect
index 436b7b606e3eab09a0dd8c1b67ab90e43c24dffc..bdc1f295030b61fd6d4fc0ef672dffa99c027d8b 100755 (executable)
@@ -13,9 +13,9 @@ commit_msg_is () {
        expect=commit_msg_is.expect
        actual=commit_msg_is.actual
 
-       printf "%s" "$(git log --pretty=format:%s%b -1)" >$expect &&
-       printf "%s" "$1" >$actual &&
-       test_i18ncmp $expect $actual
+       printf "%s" "$(git log --pretty=format:%s%b -1)" >"$actual" &&
+       printf "%s" "$1" >"$expect" &&
+       test_i18ncmp "$expect" "$actual"
 }
 
 # A sanity check to see if commit is working at all.
index e2ffdacc267c22e369247791e24338a20badf94d..ac3d0fe44507328f6363edc1d614bc9d8369899b 100755 (executable)
@@ -1335,4 +1335,66 @@ test_expect_failure '.git/config ignore=all suppresses submodule summary' '
        git config -f .gitmodules  --remove-section submodule.subname
 '
 
+test_expect_success 'setup of test environment' '
+       git config status.showUntrackedFiles no &&
+       git status -s >expected_short &&
+       git status --no-short >expected_noshort
+'
+
+test_expect_success '"status.short=true" same as "-s"' '
+       git -c status.short=true status >actual &&
+       test_cmp expected_short actual
+'
+
+test_expect_success '"status.short=true" weaker than "--no-short"' '
+       git -c status.short=true status --no-short >actual &&
+       test_cmp expected_noshort actual
+'
+
+test_expect_success '"status.short=false" same as "--no-short"' '
+       git -c status.short=false status >actual &&
+       test_cmp expected_noshort actual
+'
+
+test_expect_success '"status.short=false" weaker than "-s"' '
+       git -c status.short=false status -s >actual &&
+       test_cmp expected_short actual
+'
+
+test_expect_success '"status.branch=true" same as "-b"' '
+       git status -sb >expected_branch &&
+       git -c status.branch=true status -s >actual &&
+       test_cmp expected_branch actual
+'
+
+test_expect_success '"status.branch=true" different from "--no-branch"' '
+       git status -s --no-branch  >expected_nobranch &&
+       git -c status.branch=true status -s >actual &&
+       test_must_fail test_cmp expected_nobranch actual
+'
+
+test_expect_success '"status.branch=true" weaker than "--no-branch"' '
+       git -c status.branch=true status -s --no-branch >actual &&
+       test_cmp expected_nobranch actual
+'
+
+test_expect_success '"status.branch=true" weaker than "--porcelain"' '
+       git -c status.branch=true status --porcelain >actual &&
+       test_cmp expected_nobranch actual
+'
+
+test_expect_success '"status.branch=false" same as "--no-branch"' '
+       git -c status.branch=false status -s >actual &&
+       test_cmp expected_nobranch actual
+'
+
+test_expect_success '"status.branch=false" weaker than "-b"' '
+       git -c status.branch=false status -sb >actual &&
+       test_cmp expected_branch actual
+'
+
+test_expect_success 'Restore default test environment' '
+       git config --unset status.showUntrackedFiles
+'
+
 test_done
index 4f09beca90ec18c9e541f1f880471f9f2de0de8a..31a798fda21f178cbbedf47ee92dbd997f9c4e42 100755 (executable)
@@ -77,7 +77,7 @@ test_expect_success 'status when rebase in progress before resolving conflicts'
        ONTO=$(git rev-parse --short HEAD^^) &&
        test_must_fail git rebase HEAD^ --onto HEAD^^ &&
        cat >expected <<-EOF &&
-       # HEAD detached at $ONTO
+       # rebase in progress; onto $ONTO
        # You are currently rebasing branch '\''rebase_conflicts'\'' on '\''$ONTO'\''.
        #   (fix conflicts and then run "git rebase --continue")
        #   (use "git rebase --skip" to skip this patch)
@@ -104,7 +104,7 @@ test_expect_success 'status when rebase in progress before rebase --continue' '
        echo three >main.txt &&
        git add main.txt &&
        cat >expected <<-EOF &&
-       # HEAD detached at $ONTO
+       # rebase in progress; onto $ONTO
        # You are currently rebasing branch '\''rebase_conflicts'\'' on '\''$ONTO'\''.
        #   (all conflicts fixed: run "git rebase --continue")
        #
@@ -136,7 +136,7 @@ test_expect_success 'status during rebase -i when conflicts unresolved' '
        ONTO=$(git rev-parse --short rebase_i_conflicts) &&
        test_must_fail git rebase -i rebase_i_conflicts &&
        cat >expected <<-EOF &&
-       # HEAD detached at $ONTO
+       # rebase in progress; onto $ONTO
        # You are currently rebasing branch '\''rebase_i_conflicts_second'\'' on '\''$ONTO'\''.
        #   (fix conflicts and then run "git rebase --continue")
        #   (use "git rebase --skip" to skip this patch)
@@ -162,7 +162,7 @@ test_expect_success 'status during rebase -i after resolving conflicts' '
        test_must_fail git rebase -i rebase_i_conflicts &&
        git add main.txt &&
        cat >expected <<-EOF &&
-       # HEAD detached at $ONTO
+       # rebase in progress; onto $ONTO
        # You are currently rebasing branch '\''rebase_i_conflicts_second'\'' on '\''$ONTO'\''.
        #   (all conflicts fixed: run "git rebase --continue")
        #
@@ -188,10 +188,9 @@ test_expect_success 'status when rebasing -i in edit mode' '
        export FAKE_LINES &&
        test_when_finished "git rebase --abort" &&
        ONTO=$(git rev-parse --short HEAD~2) &&
-       TGT=$(git rev-parse --short two_rebase_i) &&
        git rebase -i HEAD~2 &&
        cat >expected <<-EOF &&
-       # HEAD detached from $TGT
+       # rebase in progress; onto $ONTO
        # You are currently editing a commit while rebasing branch '\''rebase_i_edit'\'' on '\''$ONTO'\''.
        #   (use "git commit --amend" to amend the current commit)
        #   (use "git rebase --continue" once you are satisfied with your changes)
@@ -216,9 +215,8 @@ test_expect_success 'status when splitting a commit' '
        ONTO=$(git rev-parse --short HEAD~3) &&
        git rebase -i HEAD~3 &&
        git reset HEAD^ &&
-       TGT=$(git rev-parse --short HEAD) &&
        cat >expected <<-EOF &&
-       # HEAD detached at $TGT
+       # rebase in progress; onto $ONTO
        # You are currently splitting a commit while rebasing branch '\''split_commit'\'' on '\''$ONTO'\''.
        #   (Once your working directory is clean, run "git rebase --continue")
        #
@@ -246,11 +244,10 @@ test_expect_success 'status after editing the last commit with --amend during a
        export FAKE_LINES &&
        test_when_finished "git rebase --abort" &&
        ONTO=$(git rev-parse --short HEAD~3) &&
-       TGT=$(git rev-parse --short three_amend) &&
        git rebase -i HEAD~3 &&
        git commit --amend -m "foo" &&
        cat >expected <<-EOF &&
-       # HEAD detached from $TGT
+       # rebase in progress; onto $ONTO
        # You are currently editing a commit while rebasing branch '\''amend_last'\'' on '\''$ONTO'\''.
        #   (use "git commit --amend" to amend the current commit)
        #   (use "git rebase --continue" once you are satisfied with your changes)
@@ -280,7 +277,7 @@ test_expect_success 'status: (continue first edit) second edit' '
        git rebase -i HEAD~3 &&
        git rebase --continue &&
        cat >expected <<-EOF &&
-       # HEAD detached from $ONTO
+       # rebase in progress; onto $ONTO
        # You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
        #   (use "git commit --amend" to amend the current commit)
        #   (use "git rebase --continue" once you are satisfied with your changes)
@@ -302,7 +299,7 @@ test_expect_success 'status: (continue first edit) second edit and split' '
        git rebase --continue &&
        git reset HEAD^ &&
        cat >expected <<-EOF &&
-       # HEAD detached from $ONTO
+       # rebase in progress; onto $ONTO
        # You are currently splitting a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
        #   (Once your working directory is clean, run "git rebase --continue")
        #
@@ -329,7 +326,7 @@ test_expect_success 'status: (continue first edit) second edit and amend' '
        git rebase --continue &&
        git commit --amend -m "foo" &&
        cat >expected <<-EOF &&
-       # HEAD detached from $ONTO
+       # rebase in progress; onto $ONTO
        # You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
        #   (use "git commit --amend" to amend the current commit)
        #   (use "git rebase --continue" once you are satisfied with your changes)
@@ -351,7 +348,7 @@ test_expect_success 'status: (amend first edit) second edit' '
        git commit --amend -m "a" &&
        git rebase --continue &&
        cat >expected <<-EOF &&
-       # HEAD detached from $ONTO
+       # rebase in progress; onto $ONTO
        # You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
        #   (use "git commit --amend" to amend the current commit)
        #   (use "git rebase --continue" once you are satisfied with your changes)
@@ -374,7 +371,7 @@ test_expect_success 'status: (amend first edit) second edit and split' '
        git rebase --continue &&
        git reset HEAD^ &&
        cat >expected <<-EOF &&
-       # HEAD detached from $ONTO
+       # rebase in progress; onto $ONTO
        # You are currently splitting a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
        #   (Once your working directory is clean, run "git rebase --continue")
        #
@@ -402,7 +399,7 @@ test_expect_success 'status: (amend first edit) second edit and amend' '
        git rebase --continue &&
        git commit --amend -m "d" &&
        cat >expected <<-EOF &&
-       # HEAD detached from $ONTO
+       # rebase in progress; onto $ONTO
        # You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
        #   (use "git commit --amend" to amend the current commit)
        #   (use "git rebase --continue" once you are satisfied with your changes)
@@ -426,7 +423,7 @@ test_expect_success 'status: (split first edit) second edit' '
        git commit -m "e" &&
        git rebase --continue &&
        cat >expected <<-EOF &&
-       # HEAD detached from $ONTO
+       # rebase in progress; onto $ONTO
        # You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
        #   (use "git commit --amend" to amend the current commit)
        #   (use "git rebase --continue" once you are satisfied with your changes)
@@ -451,7 +448,7 @@ test_expect_success 'status: (split first edit) second edit and split' '
        git rebase --continue &&
        git reset HEAD^ &&
        cat >expected <<-EOF &&
-       # HEAD detached from $ONTO
+       # rebase in progress; onto $ONTO
        # You are currently splitting a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
        #   (Once your working directory is clean, run "git rebase --continue")
        #
@@ -481,7 +478,7 @@ test_expect_success 'status: (split first edit) second edit and amend' '
        git rebase --continue &&
        git commit --amend -m "h" &&
        cat >expected <<-EOF &&
-       # HEAD detached from $ONTO
+       # rebase in progress; onto $ONTO
        # You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
        #   (use "git commit --amend" to amend the current commit)
        #   (use "git rebase --continue" once you are satisfied with your changes)
@@ -510,7 +507,7 @@ test_expect_success 'status in an am session: file already exists' '
        cat >expected <<-\EOF &&
        # On branch am_already_exists
        # You are in the middle of an am session.
-       #   (fix conflicts and then run "git am --resolved")
+       #   (fix conflicts and then run "git am --continue")
        #   (use "git am --skip" to skip this patch)
        #   (use "git am --abort" to restore the original branch)
        #
@@ -532,7 +529,7 @@ test_expect_success 'status in an am session: file does not exist' '
        cat >expected <<-\EOF &&
        # On branch am_not_exists
        # You are in the middle of an am session.
-       #   (fix conflicts and then run "git am --resolved")
+       #   (fix conflicts and then run "git am --continue")
        #   (use "git am --skip" to skip this patch)
        #   (use "git am --abort" to restore the original branch)
        #
@@ -601,7 +598,7 @@ test_expect_success 'status when rebase conflicts with statushints disabled' '
        ONTO=$(git rev-parse --short HEAD^^) &&
        test_must_fail git rebase HEAD^ --onto HEAD^^ &&
        cat >expected <<-EOF &&
-       # HEAD detached at $ONTO
+       # rebase in progress; onto $ONTO
        # You are currently rebasing branch '\''statushints_disabled'\'' on '\''$ONTO'\''.
        #
        # Unmerged paths:
@@ -669,7 +666,7 @@ test_expect_success 'status when cherry-picking after resolving conflicts' '
        test_i18ncmp expected actual
 '
 
-test_expect_success 'status showing detached from a tag' '
+test_expect_success 'status showing detached at and from a tag' '
        test_commit atag tagging &&
        git checkout atag &&
        cat >expected <<-\EOF
@@ -677,6 +674,14 @@ test_expect_success 'status showing detached from a tag' '
        nothing to commit (use -u to show untracked files)
        EOF
        git status --untracked-files=no >actual &&
+       test_i18ncmp expected actual &&
+
+       git reset --hard HEAD^ &&
+       cat >expected <<-\EOF
+       # HEAD detached from atag
+       nothing to commit (use -u to show untracked files)
+       EOF
+       git status --untracked-files=no >actual &&
        test_i18ncmp expected actual
 '
 
index 81a1657efb18e88a448886aed60bb7e5fdb36212..272a071e85b0b7c6b34da06fd7492a257b09fa52 100755 (executable)
@@ -69,7 +69,7 @@ run_completion ()
        local -a COMPREPLY _words
        local _cword
        _words=( $1 )
-       test "${1: -1}" == ' ' && _words+=('')
+       test "${1: -1}" = ' ' && _words+=('')
        (( _cword = ${#_words[@]} - 1 ))
        __git_wrap__git_main && print_comp
 }
@@ -122,6 +122,140 @@ test_gitcomp_nl ()
 
 invalid_variable_name='${foo.bar}'
 
+actual="$TRASH_DIRECTORY/actual"
+
+test_expect_success 'setup for __gitdir tests' '
+       mkdir -p subdir/subsubdir &&
+       git init otherrepo
+'
+
+test_expect_success '__gitdir - from command line (through $__git_dir)' '
+       echo "$TRASH_DIRECTORY/otherrepo/.git" >expected &&
+       (
+               __git_dir="$TRASH_DIRECTORY/otherrepo/.git" &&
+               __gitdir >"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - repo as argument' '
+       echo "otherrepo/.git" >expected &&
+       __gitdir "otherrepo" >"$actual" &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - remote as argument' '
+       echo "remote" >expected &&
+       __gitdir "remote" >"$actual" &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - .git directory in cwd' '
+       echo ".git" >expected &&
+       __gitdir >"$actual" &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - .git directory in parent' '
+       echo "$(pwd -P)/.git" >expected &&
+       (
+               cd subdir/subsubdir &&
+               __gitdir >"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - cwd is a .git directory' '
+       echo "." >expected &&
+       (
+               cd .git &&
+               __gitdir >"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - parent is a .git directory' '
+       echo "$(pwd -P)/.git" >expected &&
+       (
+               cd .git/refs/heads &&
+               __gitdir >"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - $GIT_DIR set while .git directory in cwd' '
+       echo "$TRASH_DIRECTORY/otherrepo/.git" >expected &&
+       (
+               GIT_DIR="$TRASH_DIRECTORY/otherrepo/.git" &&
+               export GIT_DIR &&
+               __gitdir >"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - $GIT_DIR set while .git directory in parent' '
+       echo "$TRASH_DIRECTORY/otherrepo/.git" >expected &&
+       (
+               GIT_DIR="$TRASH_DIRECTORY/otherrepo/.git" &&
+               export GIT_DIR &&
+               cd subdir &&
+               __gitdir >"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - non-existing $GIT_DIR' '
+       (
+               GIT_DIR="$TRASH_DIRECTORY/non-existing" &&
+               export GIT_DIR &&
+               test_must_fail __gitdir
+       )
+'
+
+test_expect_success '__gitdir - gitfile in cwd' '
+       echo "$(pwd -P)/otherrepo/.git" >expected &&
+       echo "gitdir: $TRASH_DIRECTORY/otherrepo/.git" >subdir/.git &&
+       test_when_finished "rm -f subdir/.git" &&
+       (
+               cd subdir &&
+               __gitdir >"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - gitfile in parent' '
+       echo "$(pwd -P)/otherrepo/.git" >expected &&
+       echo "gitdir: $TRASH_DIRECTORY/otherrepo/.git" >subdir/.git &&
+       test_when_finished "rm -f subdir/.git" &&
+       (
+               cd subdir/subsubdir &&
+               __gitdir >"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success SYMLINKS '__gitdir - resulting path avoids symlinks' '
+       echo "$(pwd -P)/otherrepo/.git" >expected &&
+       mkdir otherrepo/dir &&
+       test_when_finished "rm -rf otherrepo/dir" &&
+       ln -s otherrepo/dir link &&
+       test_when_finished "rm -f link" &&
+       (
+               cd link &&
+               __gitdir >"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - not a git repository' '
+       (
+               cd subdir/subsubdir &&
+               GIT_CEILING_DIRECTORIES="$TRASH_DIRECTORY" &&
+               export GIT_CEILING_DIRECTORIES &&
+               test_must_fail __gitdir
+       )
+'
+
 test_expect_success '__gitcomp - trailing space - options' '
        test_gitcomp "--re" "--dry-run --reuse-message= --reedit-message=
                --reset-author" <<-EOF
@@ -231,6 +365,7 @@ test_expect_success 'double dash "git" itself' '
        --exec-path Z
        --exec-path=
        --html-path Z
+       --man-path Z
        --info-path Z
        --work-tree=
        --namespace=
index 15521cc4f9be68ccd105916cee1322041682e8d5..3c3e4e8c38023595978368e0b1665e122e0bdfab 100755 (executable)
@@ -10,528 +10,558 @@ test_description='test git-specific bash prompt functions'
 . "$GIT_BUILD_DIR/contrib/completion/git-prompt.sh"
 
 actual="$TRASH_DIRECTORY/actual"
+c_red='\\[\\e[31m\\]'
+c_green='\\[\\e[32m\\]'
+c_lblue='\\[\\e[1;34m\\]'
+c_clear='\\[\\e[0m\\]'
 
 test_expect_success 'setup for prompt tests' '
-       mkdir -p subdir/subsubdir &&
        git init otherrepo &&
-       echo 1 > file &&
+       echo 1 >file &&
        git add file &&
        test_tick &&
        git commit -m initial &&
        git tag -a -m msg1 t1 &&
        git checkout -b b1 &&
-       echo 2 > file &&
+       echo 2 >file &&
        git commit -m "second b1" file &&
-       echo 3 > file &&
+       echo 3 >file &&
        git commit -m "third b1" file &&
        git tag -a -m msg2 t2 &&
        git checkout -b b2 master &&
-       echo 0 > file &&
+       echo 0 >file &&
        git commit -m "second b2" file &&
-       echo 00 > file &&
+       echo 00 >file &&
        git commit -m "another b2" file &&
-       echo 000 > file &&
+       echo 000 >file &&
        git commit -m "yet another b2" file &&
        git checkout master
 '
 
-test_expect_success 'gitdir - from command line (through $__git_dir)' '
-       echo "$TRASH_DIRECTORY/otherrepo/.git" > expected &&
-       (
-               __git_dir="$TRASH_DIRECTORY/otherrepo/.git" &&
-               __gitdir > "$actual"
-       ) &&
-       test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - repo as argument' '
-       echo "otherrepo/.git" > expected &&
-       __gitdir "otherrepo" > "$actual" &&
-       test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - remote as argument' '
-       echo "remote" > expected &&
-       __gitdir "remote" > "$actual" &&
-       test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - .git directory in cwd' '
-       echo ".git" > expected &&
-       __gitdir > "$actual" &&
-       test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - .git directory in parent' '
-       echo "$(pwd -P)/.git" > expected &&
-       (
-               cd subdir/subsubdir &&
-               __gitdir > "$actual"
-       ) &&
-       test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - cwd is a .git directory' '
-       echo "." > expected &&
-       (
-               cd .git &&
-               __gitdir > "$actual"
-       ) &&
-       test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - parent is a .git directory' '
-       echo "$(pwd -P)/.git" > expected &&
-       (
-               cd .git/refs/heads &&
-               __gitdir > "$actual"
-       ) &&
-       test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - $GIT_DIR set while .git directory in cwd' '
-       echo "$TRASH_DIRECTORY/otherrepo/.git" > expected &&
-       (
-               GIT_DIR="$TRASH_DIRECTORY/otherrepo/.git" &&
-               export GIT_DIR &&
-               __gitdir > "$actual"
-       ) &&
-       test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - $GIT_DIR set while .git directory in parent' '
-       echo "$TRASH_DIRECTORY/otherrepo/.git" > expected &&
-       (
-               GIT_DIR="$TRASH_DIRECTORY/otherrepo/.git" &&
-               export GIT_DIR &&
-               cd subdir &&
-               __gitdir > "$actual"
-       ) &&
-       test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - non-existing $GIT_DIR' '
-       (
-               GIT_DIR="$TRASH_DIRECTORY/non-existing" &&
-               export GIT_DIR &&
-               test_must_fail __gitdir
-       )
-'
-
-test_expect_success 'gitdir - gitfile in cwd' '
-       echo "$(pwd -P)/otherrepo/.git" > expected &&
-       echo "gitdir: $TRASH_DIRECTORY/otherrepo/.git" > subdir/.git &&
-       test_when_finished "rm -f subdir/.git" &&
-       (
-               cd subdir &&
-               __gitdir > "$actual"
-       ) &&
-       test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - gitfile in parent' '
-       echo "$(pwd -P)/otherrepo/.git" > expected &&
-       echo "gitdir: $TRASH_DIRECTORY/otherrepo/.git" > subdir/.git &&
-       test_when_finished "rm -f subdir/.git" &&
-       (
-               cd subdir/subsubdir &&
-               __gitdir > "$actual"
-       ) &&
+test_expect_success 'prompt - branch name' '
+       printf " (master)" >expected &&
+       __git_ps1 >"$actual" &&
        test_cmp expected "$actual"
 '
 
-test_expect_success SYMLINKS 'gitdir - resulting path avoids symlinks' '
-       echo "$(pwd -P)/otherrepo/.git" > expected &&
-       mkdir otherrepo/dir &&
-       test_when_finished "rm -rf otherrepo/dir" &&
-       ln -s otherrepo/dir link &&
-       test_when_finished "rm -f link" &&
-       (
-               cd link &&
-               __gitdir > "$actual"
-       ) &&
+test_expect_success SYMLINKS 'prompt - branch name - symlink symref' '
+       printf " (master)" >expected &&
+       test_when_finished "git checkout master" &&
+       test_config core.preferSymlinkRefs true &&
+       git checkout master &&
+       __git_ps1 >"$actual" &&
        test_cmp expected "$actual"
 '
 
-test_expect_success 'gitdir - not a git repository' '
-       (
-               cd subdir/subsubdir &&
-               GIT_CEILING_DIRECTORIES="$TRASH_DIRECTORY" &&
-               export GIT_CEILING_DIRECTORIES &&
-               test_must_fail __gitdir
-       )
-'
-
-test_expect_success 'prompt - branch name' '
-       printf " (master)" > expected &&
-       __git_ps1 > "$actual" &&
+test_expect_success 'prompt - unborn branch' '
+       printf " (unborn)" >expected &&
+       git checkout --orphan unborn &&
+       test_when_finished "git checkout master" &&
+       __git_ps1 >"$actual" &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - detached head' '
-       printf " ((%s...))" $(git log -1 --format="%h" b1^) > expected &&
+       printf " ((%s...))" $(git log -1 --format="%h" --abbrev=13 b1^) >expected &&
+       test_config core.abbrev 13 &&
        git checkout b1^ &&
        test_when_finished "git checkout master" &&
-       __git_ps1 > "$actual" &&
+       __git_ps1 >"$actual" &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - describe detached head - contains' '
-       printf " ((t2~1))" > expected &&
+       printf " ((t2~1))" >expected &&
        git checkout b1^ &&
        test_when_finished "git checkout master" &&
        (
                GIT_PS1_DESCRIBE_STYLE=contains &&
-               __git_ps1 > "$actual"
+               __git_ps1 >"$actual"
        ) &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - describe detached head - branch' '
-       printf " ((b1~1))" > expected &&
+       printf " ((b1~1))" >expected &&
        git checkout b1^ &&
        test_when_finished "git checkout master" &&
        (
                GIT_PS1_DESCRIBE_STYLE=branch &&
-               __git_ps1 > "$actual"
+               __git_ps1 >"$actual"
        ) &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - describe detached head - describe' '
-       printf " ((t1-1-g%s))" $(git log -1 --format="%h" b1^) > expected &&
+       printf " ((t1-1-g%s))" $(git log -1 --format="%h" b1^) >expected &&
        git checkout b1^ &&
        test_when_finished "git checkout master" &&
        (
                GIT_PS1_DESCRIBE_STYLE=describe &&
-               __git_ps1 > "$actual"
+               __git_ps1 >"$actual"
        ) &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - describe detached head - default' '
-       printf " ((t2))" > expected &&
+       printf " ((t2))" >expected &&
        git checkout --detach b1 &&
        test_when_finished "git checkout master" &&
-       __git_ps1 > "$actual" &&
+       __git_ps1 >"$actual" &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - inside .git directory' '
-       printf " (GIT_DIR!)" > expected &&
+       printf " (GIT_DIR!)" >expected &&
        (
                cd .git &&
-               __git_ps1 > "$actual"
+               __git_ps1 >"$actual"
        ) &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - deep inside .git directory' '
-       printf " (GIT_DIR!)" > expected &&
+       printf " (GIT_DIR!)" >expected &&
        (
                cd .git/refs/heads &&
-               __git_ps1 > "$actual"
+               __git_ps1 >"$actual"
        ) &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - inside bare repository' '
-       printf " (BARE:master)" > expected &&
+       printf " (BARE:master)" >expected &&
        git init --bare bare.git &&
        test_when_finished "rm -rf bare.git" &&
        (
                cd bare.git &&
-               __git_ps1 > "$actual"
+               __git_ps1 >"$actual"
        ) &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - interactive rebase' '
-       printf " (b1|REBASE-i 2/3)" > expected
-       echo "#!$SHELL_PATH" >fake_editor.sh &&
-       cat >>fake_editor.sh <<\EOF &&
-echo "exec echo" > "$1"
-echo "edit $(git log -1 --format="%h")" >> "$1"
-echo "exec echo" >> "$1"
-EOF
+       printf " (b1|REBASE-i 2/3)" >expected
+       write_script fake_editor.sh <<-\EOF &&
+               echo "exec echo" >"$1"
+               echo "edit $(git log -1 --format="%h")" >>"$1"
+               echo "exec echo" >>"$1"
+       EOF
        test_when_finished "rm -f fake_editor.sh" &&
-       chmod a+x fake_editor.sh &&
        test_set_editor "$TRASH_DIRECTORY/fake_editor.sh" &&
        git checkout b1 &&
        test_when_finished "git checkout master" &&
        git rebase -i HEAD^ &&
        test_when_finished "git rebase --abort"
-       __git_ps1 > "$actual" &&
+       __git_ps1 >"$actual" &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - rebase merge' '
-       printf " (b2|REBASE-m 1/3)" > expected &&
+       printf " (b2|REBASE-m 1/3)" >expected &&
        git checkout b2 &&
        test_when_finished "git checkout master" &&
        test_must_fail git rebase --merge b1 b2 &&
        test_when_finished "git rebase --abort" &&
-       __git_ps1 > "$actual" &&
+       __git_ps1 >"$actual" &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - rebase' '
-       printf " (b2|REBASE 1/3)" > expected &&
+       printf " (b2|REBASE 1/3)" >expected &&
        git checkout b2 &&
        test_when_finished "git checkout master" &&
        test_must_fail git rebase b1 b2 &&
        test_when_finished "git rebase --abort" &&
-       __git_ps1 > "$actual" &&
+       __git_ps1 >"$actual" &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - merge' '
-       printf " (b1|MERGING)" > expected &&
+       printf " (b1|MERGING)" >expected &&
        git checkout b1 &&
        test_when_finished "git checkout master" &&
        test_must_fail git merge b2 &&
        test_when_finished "git reset --hard" &&
-       __git_ps1 > "$actual" &&
+       __git_ps1 >"$actual" &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - cherry-pick' '
-       printf " (master|CHERRY-PICKING)" > expected &&
+       printf " (master|CHERRY-PICKING)" >expected &&
        test_must_fail git cherry-pick b1 &&
        test_when_finished "git reset --hard" &&
-       __git_ps1 > "$actual" &&
+       __git_ps1 >"$actual" &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - bisect' '
-       printf " (master|BISECTING)" > expected &&
+       printf " (master|BISECTING)" >expected &&
        git bisect start &&
        test_when_finished "git bisect reset" &&
-       __git_ps1 > "$actual" &&
+       __git_ps1 >"$actual" &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - clean' '
-       printf " (master)" > expected &&
+       printf " (master)" >expected &&
        (
                GIT_PS1_SHOWDIRTYSTATE=y &&
-               __git_ps1 > "$actual"
+               __git_ps1 >"$actual"
        ) &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - dirty worktree' '
-       printf " (master *)" > expected &&
-       echo "dirty" > file &&
+       printf " (master *)" >expected &&
+       echo "dirty" >file &&
        test_when_finished "git reset --hard" &&
        (
                GIT_PS1_SHOWDIRTYSTATE=y &&
-               __git_ps1 > "$actual"
+               __git_ps1 >"$actual"
        ) &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - dirty index' '
-       printf " (master +)" > expected &&
-       echo "dirty" > file &&
+       printf " (master +)" >expected &&
+       echo "dirty" >file &&
        test_when_finished "git reset --hard" &&
        git add -u &&
        (
                GIT_PS1_SHOWDIRTYSTATE=y &&
-               __git_ps1 > "$actual"
+               __git_ps1 >"$actual"
        ) &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - dirty index and worktree' '
-       printf " (master *+)" > expected &&
-       echo "dirty index" > file &&
+       printf " (master *+)" >expected &&
+       echo "dirty index" >file &&
        test_when_finished "git reset --hard" &&
        git add -u &&
-       echo "dirty worktree" > file &&
+       echo "dirty worktree" >file &&
        (
                GIT_PS1_SHOWDIRTYSTATE=y &&
-               __git_ps1 > "$actual"
+               __git_ps1 >"$actual"
        ) &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - before root commit' '
-       printf " (master #)" > expected &&
+       printf " (master #)" >expected &&
        (
                GIT_PS1_SHOWDIRTYSTATE=y &&
                cd otherrepo &&
-               __git_ps1 > "$actual"
+               __git_ps1 >"$actual"
        ) &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - shell variable unset with config disabled' '
-       printf " (master)" > expected &&
-       echo "dirty" > file &&
+       printf " (master)" >expected &&
+       echo "dirty" >file &&
        test_when_finished "git reset --hard" &&
        test_config bash.showDirtyState false &&
        (
                sane_unset GIT_PS1_SHOWDIRTYSTATE &&
-               __git_ps1 > "$actual"
+               __git_ps1 >"$actual"
        ) &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - shell variable unset with config enabled' '
-       printf " (master)" > expected &&
-       echo "dirty" > file &&
+       printf " (master)" >expected &&
+       echo "dirty" >file &&
        test_when_finished "git reset --hard" &&
        test_config bash.showDirtyState true &&
        (
                sane_unset GIT_PS1_SHOWDIRTYSTATE &&
-               __git_ps1 > "$actual"
+               __git_ps1 >"$actual"
        ) &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - shell variable set with config disabled' '
-       printf " (master)" > expected &&
-       echo "dirty" > file &&
+       printf " (master)" >expected &&
+       echo "dirty" >file &&
        test_when_finished "git reset --hard" &&
        test_config bash.showDirtyState false &&
        (
                GIT_PS1_SHOWDIRTYSTATE=y &&
-               __git_ps1 > "$actual"
+               __git_ps1 >"$actual"
        ) &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - shell variable set with config enabled' '
-       printf " (master *)" > expected &&
-       echo "dirty" > file &&
+       printf " (master *)" >expected &&
+       echo "dirty" >file &&
        test_when_finished "git reset --hard" &&
        test_config bash.showDirtyState true &&
        (
                GIT_PS1_SHOWDIRTYSTATE=y &&
-               __git_ps1 > "$actual"
+               __git_ps1 >"$actual"
        ) &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - not shown inside .git directory' '
-       printf " (GIT_DIR!)" > expected &&
-       echo "dirty" > file &&
+       printf " (GIT_DIR!)" >expected &&
+       echo "dirty" >file &&
        test_when_finished "git reset --hard" &&
        (
                GIT_PS1_SHOWDIRTYSTATE=y &&
                cd .git &&
-               __git_ps1 > "$actual"
+               __git_ps1 >"$actual"
        ) &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - stash status indicator - no stash' '
-       printf " (master)" > expected &&
+       printf " (master)" >expected &&
        (
                GIT_PS1_SHOWSTASHSTATE=y &&
-               __git_ps1 > "$actual"
+               __git_ps1 >"$actual"
        ) &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - stash status indicator - stash' '
-       printf " (master $)" > expected &&
+       printf " (master $)" >expected &&
        echo 2 >file &&
        git stash &&
        test_when_finished "git stash drop" &&
+       git pack-refs --all &&
        (
                GIT_PS1_SHOWSTASHSTATE=y &&
-               __git_ps1 > "$actual"
+               __git_ps1 >"$actual"
        ) &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - stash status indicator - not shown inside .git directory' '
-       printf " (GIT_DIR!)" > expected &&
+       printf " (GIT_DIR!)" >expected &&
        echo 2 >file &&
        git stash &&
        test_when_finished "git stash drop" &&
        (
                GIT_PS1_SHOWSTASHSTATE=y &&
                cd .git &&
-               __git_ps1 > "$actual"
+               __git_ps1 >"$actual"
        ) &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - untracked files status indicator - no untracked files' '
-       printf " (master)" > expected &&
+       printf " (master)" >expected &&
        (
                GIT_PS1_SHOWUNTRACKEDFILES=y &&
                cd otherrepo &&
-               __git_ps1 > "$actual"
+               __git_ps1 >"$actual"
        ) &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - untracked files status indicator - untracked files' '
-       printf " (master %%)" > expected &&
+       printf " (master %%)" >expected &&
        (
                GIT_PS1_SHOWUNTRACKEDFILES=y &&
-               __git_ps1 > "$actual"
+               __git_ps1 >"$actual"
        ) &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - untracked files status indicator - shell variable unset with config disabled' '
-       printf " (master)" > expected &&
+       printf " (master)" >expected &&
        test_config bash.showUntrackedFiles false &&
        (
                sane_unset GIT_PS1_SHOWUNTRACKEDFILES &&
-               __git_ps1 > "$actual"
+               __git_ps1 >"$actual"
        ) &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - untracked files status indicator - shell variable unset with config enabled' '
-       printf " (master)" > expected &&
+       printf " (master)" >expected &&
        test_config bash.showUntrackedFiles true &&
        (
                sane_unset GIT_PS1_SHOWUNTRACKEDFILES &&
-               __git_ps1 > "$actual"
+               __git_ps1 >"$actual"
        ) &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - untracked files status indicator - shell variable set with config disabled' '
-       printf " (master)" > expected &&
+       printf " (master)" >expected &&
        test_config bash.showUntrackedFiles false &&
        (
                GIT_PS1_SHOWUNTRACKEDFILES=y &&
-               __git_ps1 > "$actual"
+               __git_ps1 >"$actual"
        ) &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - untracked files status indicator - shell variable set with config enabled' '
-       printf " (master %%)" > expected &&
+       printf " (master %%)" >expected &&
        test_config bash.showUntrackedFiles true &&
        (
                GIT_PS1_SHOWUNTRACKEDFILES=y &&
-               __git_ps1 > "$actual"
+               __git_ps1 >"$actual"
        ) &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - untracked files status indicator - not shown inside .git directory' '
-       printf " (GIT_DIR!)" > expected &&
+       printf " (GIT_DIR!)" >expected &&
        (
                GIT_PS1_SHOWUNTRACKEDFILES=y &&
                cd .git &&
-               __git_ps1 > "$actual"
+               __git_ps1 >"$actual"
        ) &&
        test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - format string starting with dash' '
-       printf -- "-master" > expected &&
-       __git_ps1 "-%s" > "$actual" &&
+       printf -- "-master" >expected &&
+       __git_ps1 "-%s" >"$actual" &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - pc mode' '
+       printf "BEFORE: (master):AFTER" >expected &&
+       printf "" >expected_output &&
+       (
+               __git_ps1 "BEFORE:" ":AFTER" >"$actual" &&
+               test_cmp expected_output "$actual" &&
+               printf "%s" "$PS1" >"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - bash color pc mode - branch name' '
+       printf "BEFORE: (${c_green}master${c_clear}):AFTER" >expected &&
+       (
+               GIT_PS1_SHOWCOLORHINTS=y &&
+               __git_ps1 "BEFORE:" ":AFTER" >"$actual"
+               printf "%s" "$PS1" >"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - bash color pc mode - detached head' '
+       printf "BEFORE: (${c_red}(%s...)${c_clear}):AFTER" $(git log -1 --format="%h" b1^) >expected &&
+       git checkout b1^ &&
+       test_when_finished "git checkout master" &&
+       (
+               GIT_PS1_SHOWCOLORHINTS=y &&
+               __git_ps1 "BEFORE:" ":AFTER" &&
+               printf "%s" "$PS1" >"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - bash color pc mode - dirty status indicator - dirty worktree' '
+       printf "BEFORE: (${c_green}master${c_clear} ${c_red}*${c_clear}):AFTER" >expected &&
+       echo "dirty" >file &&
+       test_when_finished "git reset --hard" &&
+       (
+               GIT_PS1_SHOWDIRTYSTATE=y &&
+               GIT_PS1_SHOWCOLORHINTS=y &&
+               __git_ps1 "BEFORE:" ":AFTER" &&
+               printf "%s" "$PS1" >"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - bash color pc mode - dirty status indicator - dirty index' '
+       printf "BEFORE: (${c_green}master${c_clear} ${c_green}+${c_clear}):AFTER" >expected &&
+       echo "dirty" >file &&
+       test_when_finished "git reset --hard" &&
+       git add -u &&
+       (
+               GIT_PS1_SHOWDIRTYSTATE=y &&
+               GIT_PS1_SHOWCOLORHINTS=y &&
+               __git_ps1 "BEFORE:" ":AFTER" &&
+               printf "%s" "$PS1" >"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - bash color pc mode - dirty status indicator - dirty index and worktree' '
+       printf "BEFORE: (${c_green}master${c_clear} ${c_red}*${c_green}+${c_clear}):AFTER" >expected &&
+       echo "dirty index" >file &&
+       test_when_finished "git reset --hard" &&
+       git add -u &&
+       echo "dirty worktree" >file &&
+       (
+               GIT_PS1_SHOWCOLORHINTS=y &&
+               GIT_PS1_SHOWDIRTYSTATE=y &&
+               __git_ps1 "BEFORE:" ":AFTER" &&
+               printf "%s" "$PS1" >"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - bash color pc mode - dirty status indicator - before root commit' '
+       printf "BEFORE: (${c_green}master${c_clear} ${c_green}#${c_clear}):AFTER" >expected &&
+       (
+               GIT_PS1_SHOWDIRTYSTATE=y &&
+               GIT_PS1_SHOWCOLORHINTS=y &&
+               cd otherrepo &&
+               __git_ps1 "BEFORE:" ":AFTER" &&
+               printf "%s" "$PS1" >"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - bash color pc mode - inside .git directory' '
+       printf "BEFORE: (${c_green}GIT_DIR!${c_clear}):AFTER" >expected &&
+       echo "dirty" >file &&
+       test_when_finished "git reset --hard" &&
+       (
+               GIT_PS1_SHOWDIRTYSTATE=y &&
+               GIT_PS1_SHOWCOLORHINTS=y &&
+               cd .git &&
+               __git_ps1 "BEFORE:" ":AFTER" &&
+               printf "%s" "$PS1" >"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - bash color pc mode - stash status indicator' '
+       printf "BEFORE: (${c_green}master${c_clear} ${c_lblue}\$${c_clear}):AFTER" >expected &&
+       echo 2 >file &&
+       git stash &&
+       test_when_finished "git stash drop" &&
+       (
+               GIT_PS1_SHOWSTASHSTATE=y &&
+               GIT_PS1_SHOWCOLORHINTS=y &&
+               __git_ps1 "BEFORE:" ":AFTER" &&
+               printf "%s" "$PS1" >"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - bash color pc mode - untracked files status indicator' '
+       printf "BEFORE: (${c_green}master${c_clear} ${c_red}%%${c_clear}):AFTER" >expected &&
+       (
+               GIT_PS1_SHOWUNTRACKEDFILES=y &&
+               GIT_PS1_SHOWCOLORHINTS=y &&
+               __git_ps1 "BEFORE:" ":AFTER" &&
+               printf "%s" "$PS1" >"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - zsh color pc mode' '
+       printf "BEFORE: (%%F{green}master%%f):AFTER" >expected &&
+       (
+               ZSH_VERSION=5.0.0 &&
+               GIT_PS1_SHOWCOLORHINTS=y &&
+               __git_ps1 "BEFORE:" ":AFTER" >"$actual"
+               printf "%s" "$PS1" >"$actual"
+       ) &&
        test_cmp expected "$actual"
 '
 
index 8828ff78f184a451fb43709771cc39bf17186cfb..a7e9aacbb2d9b05b0d5083a0fd70cb9287fcf454 100644 (file)
@@ -343,6 +343,7 @@ test_declared_prereq () {
 }
 
 test_expect_failure () {
+       test_start_
        test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq=
        test "$#" = 2 ||
        error "bug in the test script: not 2 or 3 parameters to test-expect-failure"
@@ -357,10 +358,11 @@ test_expect_failure () {
                        test_known_broken_failure_ "$1"
                fi
        fi
-       echo >&3 ""
+       test_finish_
 }
 
 test_expect_success () {
+       test_start_
        test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq=
        test "$#" = 2 ||
        error "bug in the test script: not 2 or 3 parameters to test-expect-success"
@@ -375,7 +377,7 @@ test_expect_success () {
                        test_failure_ "$@"
                fi
        fi
-       echo >&3 ""
+       test_finish_
 }
 
 # test_external runs external test scripts that provide continuous
index eff3a653d14fc27d4e058fb06fa1a5d98c2978ae..2d633073510c1f6a27fc3f7943fed5dafc717dcb 100644 (file)
@@ -184,6 +184,9 @@ do
                help=t; shift ;;
        -v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose)
                verbose=t; shift ;;
+       --verbose-only=*)
+               verbose_only=$(expr "z$1" : 'z[^=]*=\(.*\)')
+               shift ;;
        -q|--q|--qu|--qui|--quie|--quiet)
                # Ignore --quiet under a TAP::Harness. Saying how many tests
                # passed without the ok/not ok details is always an error.
@@ -198,17 +201,39 @@ do
        --valgrind=*)
                valgrind=$(expr "z$1" : 'z[^=]*=\(.*\)')
                shift ;;
+       --valgrind-only=*)
+               valgrind_only=$(expr "z$1" : 'z[^=]*=\(.*\)')
+               shift ;;
+       --valgrind-parallel=*)
+               valgrind_parallel=$(expr "z$1" : 'z[^=]*=\(.*\)')
+               shift ;;
+       --valgrind-only-stride=*)
+               valgrind_only_stride=$(expr "z$1" : 'z[^=]*=\(.*\)')
+               shift ;;
+       --valgrind-only-offset=*)
+               valgrind_only_offset=$(expr "z$1" : 'z[^=]*=\(.*\)')
+               shift ;;
        --tee)
                shift ;; # was handled already
        --root=*)
                root=$(expr "z$1" : 'z[^=]*=\(.*\)')
                shift ;;
+       --statusprefix=*)
+               statusprefix=$(expr "z$1" : 'z[^=]*=\(.*\)')
+               shift ;;
        *)
                echo "error: unknown test option '$1'" >&2; exit 1 ;;
        esac
 done
 
-test -n "$valgrind" && verbose=t
+if test -n "$valgrind_only" || test -n "$valgrind_only_stride"
+then
+       test -z "$valgrind" && valgrind=memcheck
+       test -z "$verbose" && verbose_only="$valgrind_only"
+elif test -n "$valgrind"
+then
+       verbose=t
+fi
 
 if test -n "$color"
 then
@@ -303,12 +328,12 @@ trap 'die' EXIT
 
 test_ok_ () {
        test_success=$(($test_success + 1))
-       say_color "" "ok $test_count - $@"
+       say_color "" "${statusprefix}ok $test_count - $@"
 }
 
 test_failure_ () {
        test_failure=$(($test_failure + 1))
-       say_color error "not ok $test_count - $1"
+       say_color error "${statusprefix}not ok $test_count - $1"
        shift
        echo "$@" | sed -e 's/^/#       /'
        test "$immediate" = "" || { GIT_EXIT_OK=t; exit 1; }
@@ -316,18 +341,83 @@ test_failure_ () {
 
 test_known_broken_ok_ () {
        test_fixed=$(($test_fixed+1))
-       say_color error "ok $test_count - $@ # TODO known breakage vanished"
+       say_color error "${statusprefix}ok $test_count - $@ # TODO known breakage vanished"
 }
 
 test_known_broken_failure_ () {
        test_broken=$(($test_broken+1))
-       say_color warn "not ok $test_count - $@ # TODO known breakage"
+       say_color warn "${statusprefix}not ok $test_count - $@ # TODO known breakage"
 }
 
 test_debug () {
        test "$debug" = "" || eval "$1"
 }
 
+match_pattern_list () {
+       arg="$1"
+       shift
+       test -z "$*" && return 1
+       for pattern_
+       do
+               case "$arg" in
+               $pattern_)
+                       return 0
+               esac
+       done
+       return 1
+}
+
+maybe_teardown_verbose () {
+       test -z "$verbose_only" && return
+       exec 4>/dev/null 3>/dev/null
+       verbose=
+}
+
+last_verbose=t
+maybe_setup_verbose () {
+       test -z "$verbose_only" && return
+       if match_pattern_list $test_count $verbose_only ||
+               { test -n "$valgrind_only_stride" &&
+               expr $test_count "%" $valgrind_only_stride - $valgrind_only_offset = 0 >/dev/null; }
+       then
+               exec 4>&2 3>&1
+               # Emit a delimiting blank line when going from
+               # non-verbose to verbose.  Within verbose mode the
+               # delimiter is printed by test_expect_*.  The choice
+               # of the initial $last_verbose is such that before
+               # test 1, we do not print it.
+               test -z "$last_verbose" && echo >&3 ""
+               verbose=t
+       else
+               exec 4>/dev/null 3>/dev/null
+               verbose=
+       fi
+       last_verbose=$verbose
+}
+
+maybe_teardown_valgrind () {
+       test -z "$GIT_VALGRIND" && return
+       GIT_VALGRIND_ENABLED=
+}
+
+maybe_setup_valgrind () {
+       test -z "$GIT_VALGRIND" && return
+       if test -z "$valgrind_only" && test -z "$valgrind_only_stride"
+       then
+               GIT_VALGRIND_ENABLED=t
+               return
+       fi
+       GIT_VALGRIND_ENABLED=
+       if match_pattern_list $test_count $valgrind_only
+       then
+               GIT_VALGRIND_ENABLED=t
+       elif test -n "$valgrind_only_stride" &&
+               expr $test_count "%" $valgrind_only_stride - $valgrind_only_offset = 0 >/dev/null
+       then
+               GIT_VALGRIND_ENABLED=t
+       fi
+}
+
 test_eval_ () {
        # This is a separate function because some tests use
        # "return" to end a test_expect_success block early.
@@ -337,8 +427,10 @@ test_eval_ () {
 test_run_ () {
        test_cleanup=:
        expecting_failure=$2
+       setup_malloc_check
        test_eval_ "$1"
        eval_ret=$?
+       teardown_malloc_check
 
        if test -z "$immediate" || test $eval_ret = 0 || test -n "$expecting_failure"
        then
@@ -353,17 +445,24 @@ test_run_ () {
        return "$eval_ret"
 }
 
-test_skip () {
+test_start_ () {
        test_count=$(($test_count+1))
+       maybe_setup_verbose
+       maybe_setup_valgrind
+}
+
+test_finish_ () {
+       echo >&3 ""
+       maybe_teardown_valgrind
+       maybe_teardown_verbose
+}
+
+test_skip () {
        to_skip=
-       for skp in $GIT_SKIP_TESTS
-       do
-               case $this_test.$test_count in
-               $skp)
-                       to_skip=t
-                       break
-               esac
-       done
+       if match_pattern_list $this_test.$test_count $GIT_SKIP_TESTS
+       then
+               to_skip=t
+       fi
        if test -z "$to_skip" && test -n "$test_prereq" &&
           ! test_have_prereq "$test_prereq"
        then
@@ -377,8 +476,8 @@ test_skip () {
                        of_prereq=" of $test_prereq"
                fi
 
-               say_color skip >&3 "skipping test: $@"
-               say_color skip "ok $test_count # skip $1 (missing $missing_prereq${of_prereq})"
+               say_color skip >&3 "${statusprefix}skipping test: $@"
+               say_color skip "${statusprefix}ok $test_count # skip $1 (missing $missing_prereq${of_prereq})"
                : true
                ;;
        *)
@@ -395,6 +494,8 @@ test_at_end_hook_ () {
 test_done () {
        GIT_EXIT_OK=t
 
+       # Note: t0000 relies on $HARNESS_ACTIVE disabling the .counts
+       # output file
        if test -z "$HARNESS_ACTIVE"
        then
                test_results_dir="$TEST_OUTPUT_DIRECTORY/test-results"
@@ -414,11 +515,11 @@ test_done () {
 
        if test "$test_fixed" != 0
        then
-               say_color error "# $test_fixed known breakage(s) vanished; please update test(s)"
+               say_color error "${statusprefix}# $test_fixed known breakage(s) vanished; please update test(s)"
        fi
        if test "$test_broken" != 0
        then
-               say_color warn "# still have $test_broken known breakage(s)"
+               say_color warn "${statusprefix}# still have $test_broken known breakage(s)"
        fi
        if test "$test_broken" != 0 || test "$test_fixed" != 0
        then
@@ -441,9 +542,9 @@ test_done () {
                then
                        if test $test_remaining -gt 0
                        then
-                               say_color pass "# passed all $msg"
+                               say_color pass "${statusprefix}# passed all $msg"
                        fi
-                       say "1..$test_count$skip_all"
+                       say "${statusprefix}1..$test_count$skip_all"
                fi
 
                test -d "$remove_trash" &&
@@ -457,8 +558,8 @@ test_done () {
        *)
                if test $test_external_has_tap -eq 0
                then
-                       say_color error "# failed $test_failure among $msg"
-                       say "1..$test_count"
+                       say_color error "${statusprefix}# failed $test_failure among $msg"
+                       say "${statusprefix}1..$test_count"
                fi
 
                exit 1 ;;
@@ -466,6 +567,9 @@ test_done () {
        esac
 }
 
+
+# Set up a directory that we can put in PATH which redirects all git
+# calls to 'valgrind git ...'.
 if test -n "$valgrind"
 then
        make_symlink () {
@@ -513,31 +617,43 @@ then
                make_symlink "$symlink_target" "$GIT_VALGRIND/bin/$base" || exit
        }
 
-       # override all git executables in TEST_DIRECTORY/..
-       GIT_VALGRIND=$TEST_DIRECTORY/valgrind
-       mkdir -p "$GIT_VALGRIND"/bin
-       for file in $GIT_BUILD_DIR/git* $GIT_BUILD_DIR/test-*
-       do
-               make_valgrind_symlink $file
-       done
-       # special-case the mergetools loadables
-       make_symlink "$GIT_BUILD_DIR"/mergetools "$GIT_VALGRIND/bin/mergetools"
-       OLDIFS=$IFS
-       IFS=:
-       for path in $PATH
-       do
-               ls "$path"/git-* 2> /dev/null |
-               while read file
+       # In the case of --valgrind-parallel, we only need to do the
+       # wrapping once, in the main script.  The worker children all
+       # have $valgrind_only_stride set, so we can skip based on that.
+       if test -z "$valgrind_only_stride"
+       then
+               # override all git executables in TEST_DIRECTORY/..
+               GIT_VALGRIND=$TEST_DIRECTORY/valgrind
+               mkdir -p "$GIT_VALGRIND"/bin
+               for file in $GIT_BUILD_DIR/git* $GIT_BUILD_DIR/test-*
                do
-                       make_valgrind_symlink "$file"
+                       make_valgrind_symlink $file
                done
-       done
-       IFS=$OLDIFS
+               # special-case the mergetools loadables
+               make_symlink "$GIT_BUILD_DIR"/mergetools "$GIT_VALGRIND/bin/mergetools"
+               OLDIFS=$IFS
+               IFS=:
+               for path in $PATH
+               do
+                       ls "$path"/git-* 2> /dev/null |
+                       while read file
+                       do
+                               make_valgrind_symlink "$file"
+                       done
+               done
+               IFS=$OLDIFS
+       fi
        PATH=$GIT_VALGRIND/bin:$PATH
        GIT_EXEC_PATH=$GIT_VALGRIND/bin
        export GIT_VALGRIND
        GIT_VALGRIND_MODE="$valgrind"
        export GIT_VALGRIND_MODE
+       GIT_VALGRIND_ENABLED=t
+       if test -n "$valgrind_only" || test -n "$valgrind_only_stride"
+       then
+               GIT_VALGRIND_ENABLED=
+       fi
+       export GIT_VALGRIND_ENABLED
 elif test -n "$GIT_TEST_INSTALLED"
 then
        GIT_EXEC_PATH=$($GIT_TEST_INSTALLED/git --exec-path)  ||
@@ -622,21 +738,53 @@ then
 else
        mkdir -p "$TRASH_DIRECTORY"
 fi
+
+# Gross hack to spawn N sub-instances of the tests in parallel, and
+# summarize the results.  Note that if this is enabled, the script
+# terminates at the end of this 'if' block.
+if test -n "$valgrind_parallel"
+then
+       for i in $(test_seq 1 $valgrind_parallel)
+       do
+               root="$TRASH_DIRECTORY/vgparallel-$i"
+               mkdir "$root"
+               TEST_OUTPUT_DIRECTORY="$root" \
+                       ${SHELL_PATH} "$0" \
+                       --root="$root" --statusprefix="[$i] " \
+                       --valgrind="$valgrind" \
+                       --valgrind-only-stride="$valgrind_parallel" \
+                       --valgrind-only-offset="$i" &
+               pids="$pids $!"
+       done
+       trap "kill $pids" INT TERM HUP
+       wait $pids
+       trap - INT TERM HUP
+       for i in $(test_seq 1 $valgrind_parallel)
+       do
+               root="$TRASH_DIRECTORY/vgparallel-$i"
+               eval "$(cat "$root/test-results/$(basename "$0" .sh)"-*.counts |
+                       sed 's/^\([a-z][a-z]*\) \([0-9][0-9]*\)/inner_\1=\2/')"
+               test_count=$(expr $test_count + $inner_total)
+               test_success=$(expr $test_success + $inner_success)
+               test_fixed=$(expr $test_fixed + $inner_fixed)
+               test_broken=$(expr $test_broken + $inner_broken)
+               test_failure=$(expr $test_failure + $inner_failed)
+       done
+       test_done
+fi
+
 # Use -P to resolve symlinks in our working directory so that the cwd
 # in subprocesses like git equals our $PWD (for pathname comparisons).
 cd -P "$TRASH_DIRECTORY" || exit 1
 
 this_test=${0##*/}
 this_test=${this_test%%-*}
-for skp in $GIT_SKIP_TESTS
-do
-       case "$this_test" in
-       $skp)
-               say_color info >&3 "skipping test $this_test altogether"
-               skip_all="skip all tests in $this_test"
-               test_done
-       esac
-done
+if match_pattern_list "$this_test" $GIT_SKIP_TESTS
+then
+       say_color info >&3 "skipping test $this_test altogether"
+       skip_all="skip all tests in $this_test"
+       test_done
+fi
 
 # Provide an implementation of the 'yes' utility
 yes () {
@@ -737,7 +885,14 @@ test_i18ngrep () {
 
 test_lazy_prereq PIPE '
        # test whether the filesystem supports FIFOs
-       rm -f testfifo && mkfifo testfifo
+       case $(uname -s) in
+       CYGWIN*)
+               false
+               ;;
+       *)
+               rm -f testfifo && mkfifo testfifo
+               ;;
+       esac
 '
 
 test_lazy_prereq SYMLINKS '
index 6b87c91b60cde4b19d6644227548f1ba6b226545..42153036dcfdee66e54fa4bd777ad3c36233d640 100755 (executable)
@@ -4,6 +4,9 @@ base=$(basename "$0")
 
 TOOL_OPTIONS='--leak-check=no'
 
+test -z "$GIT_VALGRIND_ENABLED" &&
+exec "$GIT_VALGRIND"/../../"$base" "$@"
+
 case "$GIT_VALGRIND_MODE" in
 memcheck-fast)
        ;;
diff --git a/test-prio-queue.c b/test-prio-queue.c
new file mode 100644 (file)
index 0000000..7be72f0
--- /dev/null
@@ -0,0 +1,39 @@
+#include "cache.h"
+#include "prio-queue.h"
+
+static int intcmp(const void *va, const void *vb, void *data)
+{
+       const int *a = va, *b = vb;
+       return *a - *b;
+}
+
+static void show(int *v)
+{
+       if (!v)
+               printf("NULL\n");
+       else
+               printf("%d\n", *v);
+       free(v);
+}
+
+int main(int argc, char **argv)
+{
+       struct prio_queue pq = { intcmp };
+
+       while (*++argv) {
+               if (!strcmp(*argv, "get"))
+                       show(prio_queue_get(&pq));
+               else if (!strcmp(*argv, "dump")) {
+                       int *v;
+                       while ((v = prio_queue_get(&pq)))
+                              show(v);
+               }
+               else {
+                       int *v = malloc(sizeof(*v));
+                       *v = atoi(*argv);
+                       prio_queue_put(&pq, v);
+               }
+       }
+
+       return 0;
+}
index 438a40d63739d9397829e83d7af241054f729235..9c4d086b51364ff42a044be95e6ea55dffe7b79e 100644 (file)
@@ -127,6 +127,7 @@ void wt_status_prepare(struct wt_status *s)
        s->change.strdup_strings = 1;
        s->untracked.strdup_strings = 1;
        s->ignored.strdup_strings = 1;
+       s->show_branch = -1;  /* unspecified */
 }
 
 static void wt_status_print_unmerged_header(struct wt_status *s)
@@ -826,7 +827,7 @@ static void show_am_in_progress(struct wt_status *s,
        if (advice_status_hints) {
                if (!state->am_empty_patch)
                        status_printf_ln(s, color,
-                               _("  (fix conflicts and then run \"git am --resolved\")"));
+                               _("  (fix conflicts and then run \"git am --continue\")"));
                status_printf_ln(s, color,
                        _("  (use \"git am --skip\" to skip this patch)"));
                status_printf_ln(s, color,
@@ -1037,7 +1038,6 @@ static char *read_and_strip_branch(const char *path)
 }
 
 struct grab_1st_switch_cbdata {
-       int found;
        struct strbuf buf;
        unsigned char nsha1[20];
 };
@@ -1061,7 +1061,6 @@ static int grab_1st_switch(unsigned char *osha1, unsigned char *nsha1,
        for (end = target; *end && *end != '\n'; end++)
                ;
        strbuf_add(&cb->buf, target, end - target);
-       cb->found = 1;
        return 1;
 }
 
@@ -1178,7 +1177,10 @@ void wt_status_print(struct wt_status *s)
                        branch_name += 11;
                else if (!strcmp(branch_name, "HEAD")) {
                        branch_status_color = color(WT_STATUS_NOBRANCH, s);
-                       if (state.detached_from) {
+                       if (state.rebase_in_progress || state.rebase_interactive_in_progress) {
+                               on_what = _("rebase in progress; onto ");
+                               branch_name = state.onto;
+                       } else if (state.detached_from) {
                                unsigned char sha1[20];
                                branch_name = state.detached_from;
                                if (!get_sha1("HEAD", sha1) &&