summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/Makefile2
-rw-r--r--Documentation/RelNotes-1.7.1.1.txt28
-rw-r--r--Documentation/RelNotes-1.7.1.2.txt19
-rw-r--r--Documentation/RelNotes-1.7.2.txt53
-rw-r--r--Documentation/config.txt20
-rw-r--r--Documentation/diff-options.txt10
-rw-r--r--Documentation/fetch-options.txt1
-rw-r--r--Documentation/git-cat-file.txt2
-rw-r--r--Documentation/git-check-ref-format.txt2
-rw-r--r--Documentation/git-checkout.txt2
-rw-r--r--Documentation/git-cherry-pick.txt11
-rw-r--r--Documentation/git-diff.txt4
-rw-r--r--Documentation/git-fast-import.txt2
-rw-r--r--Documentation/git-format-patch.txt2
-rw-r--r--Documentation/git-gc.txt7
-rw-r--r--Documentation/git-grep.txt8
-rw-r--r--Documentation/git-log.txt18
-rw-r--r--Documentation/git-push.txt2
-rw-r--r--Documentation/git-reflog.txt2
-rw-r--r--Documentation/git-rerere.txt7
-rw-r--r--Documentation/git-rev-parse.txt197
-rw-r--r--Documentation/git-revert.txt2
-rw-r--r--Documentation/git-show-branch.txt2
-rw-r--r--Documentation/git-show.txt2
-rw-r--r--Documentation/git-status.txt11
-rw-r--r--Documentation/git-submodule.txt4
-rw-r--r--Documentation/git.txt5
-rw-r--r--Documentation/gitcore-tutorial.txt2
-rw-r--r--Documentation/gitk.txt2
-rw-r--r--Documentation/gitmodules.txt3
-rw-r--r--Documentation/gitrevisions.txt35
-rw-r--r--Documentation/rev-list-options.txt9
-rw-r--r--Documentation/revisions.txt199
-rw-r--r--Documentation/technical/api-string-list.txt4
-rw-r--r--Documentation/technical/protocol-capabilities.txt2
-rw-r--r--Documentation/user-manual.txt8
-rw-r--r--Makefile10
-rw-r--r--block-sha1/sha1.c1
-rw-r--r--builtin/apply.c10
-rw-r--r--builtin/commit.c25
-rw-r--r--builtin/diff.c31
-rw-r--r--builtin/fast-export.c4
-rw-r--r--builtin/fetch.c18
-rw-r--r--builtin/fmt-merge-msg.c18
-rw-r--r--builtin/grep.c122
-rw-r--r--builtin/log.c23
-rw-r--r--builtin/ls-files.c2
-rw-r--r--builtin/mailsplit.c2
-rw-r--r--builtin/merge-tree.c3
-rw-r--r--builtin/mv.c2
-rw-r--r--builtin/notes.c4
-rw-r--r--builtin/read-tree.c5
-rw-r--r--builtin/receive-pack.c4
-rw-r--r--builtin/remote.c68
-rw-r--r--builtin/rerere.c4
-rw-r--r--builtin/rev-list.c16
-rw-r--r--builtin/rev-parse.c4
-rw-r--r--builtin/revert.c35
-rw-r--r--builtin/shortlog.c4
-rw-r--r--builtin/show-ref.c2
-rw-r--r--commit.h1
-rwxr-xr-xcontrib/completion/git-completion.bash158
-rw-r--r--date.c2
-rw-r--r--diff-lib.c1
-rw-r--r--diff-no-index.c2
-rw-r--r--diff.c7
-rwxr-xr-xgit-rebase--interactive.sh19
-rwxr-xr-xgit-submodule.sh10
-rw-r--r--git.c2
-rw-r--r--git.spec.in15
-rwxr-xr-xgitweb/gitweb.perl20
-rw-r--r--http-backend.c6
-rw-r--r--log-tree.c108
-rw-r--r--log-tree.h1
-rw-r--r--mailmap.c8
-rw-r--r--merge-recursive.c26
-rw-r--r--notes.c14
-rw-r--r--reflog-walk.c4
-rw-r--r--refs.c21
-rw-r--r--remote.c6
-rw-r--r--rerere.c10
-rw-r--r--resolve-undo.c8
-rw-r--r--revision.c6
-rw-r--r--revision.h5
-rw-r--r--setup.c3
-rw-r--r--string-list.c18
-rw-r--r--string-list.h16
-rw-r--r--submodule.c13
-rw-r--r--submodule.h3
-rw-r--r--t/README253
-rw-r--r--t/gitweb-lib.sh4
-rw-r--r--t/lib-cvs.sh6
-rw-r--r--t/lib-git-svn.sh15
-rw-r--r--t/lib-httpd.sh11
-rw-r--r--t/lib-pager.sh15
-rw-r--r--t/lib-patch-mode.sh2
-rwxr-xr-xt/t0005-signals.sh1
-rwxr-xr-xt/t0006-date.sh6
-rwxr-xr-xt/t1001-read-tree-m-2way.sh16
-rwxr-xr-xt/t1020-subdirectory.sh12
-rwxr-xr-xt/t1304-default-acl.sh9
-rwxr-xr-xt/t1502-rev-parse-parseopt.sh18
-rwxr-xr-xt/t1509-root-worktree.sh6
-rwxr-xr-xt/t2007-checkout-symlink.sh2
-rwxr-xr-xt/t2102-update-index-symlinks.sh2
-rwxr-xr-xt/t3000-ls-files-others.sh89
-rwxr-xr-xt/t3300-funny-names.sh2
-rwxr-xr-xt/t3301-notes.sh6
-rwxr-xr-xt/t3302-notes-index-expensive.sh2
-rwxr-xr-xt/t3404-rebase-interactive.sh18
-rwxr-xr-xt/t3501-revert-cherry-pick.sh18
-rwxr-xr-xt/t3508-cherry-pick-many-commits.sh26
-rwxr-xr-xt/t3600-rm.sh2
-rwxr-xr-xt/t3700-add.sh12
-rwxr-xr-xt/t3701-add-interactive.sh4
-rwxr-xr-xt/t3902-quoted.sh2
-rwxr-xr-xt/t4004-diff-rename-symlink.sh2
-rwxr-xr-xt/t4011-diff-symlink.sh2
-rwxr-xr-xt/t4016-diff-quote.sh2
-rwxr-xr-xt/t4023-diff-rename-typechange.sh2
-rwxr-xr-xt/t4027-diff-submodule.sh18
-rwxr-xr-xt/t4041-diff-submodule-option.sh (renamed from t/t4041-diff-submodule.sh)81
-rwxr-xr-xt/t4114-apply-typechange.sh2
-rwxr-xr-xt/t4115-apply-symlink.sh2
-rwxr-xr-xt/t4122-apply-symlink-inside.sh2
-rwxr-xr-xt/t4151-am-abort.sh4
-rwxr-xr-xt/t4207-log-decoration-colors.sh66
-rwxr-xr-xt/t4300-merge-tree.sh257
-rwxr-xr-xt/t5302-pack-index.sh2
-rwxr-xr-xt/t5503-tagfollow.sh2
-rwxr-xr-xt/t5522-pull-symlink.sh2
-rwxr-xr-xt/t5540-http-push.sh2
-rwxr-xr-xt/t5541-http-push.sh2
-rwxr-xr-xt/t5550-http-fetch.sh2
-rwxr-xr-xt/t5551-http-fetch.sh2
-rwxr-xr-xt/t5561-http-backend.sh2
-rwxr-xr-xt/t5705-clone-2gb.sh2
-rwxr-xr-xt/t5800-remote-helpers.sh2
-rwxr-xr-xt/t6007-rev-list-cherry-pick-file.sh29
-rwxr-xr-xt/t6018-rev-list-glob.sh17
-rwxr-xr-xt/t6035-merge-dir-to-symlink.sh2
-rwxr-xr-xt/t7004-tag.sh2
-rwxr-xr-xt/t7005-editor.sh2
-rwxr-xr-xt/t7006-pager.sh18
-rwxr-xr-xt/t7400-submodule-basic.sh24
-rwxr-xr-xt/t7405-submodule-merge.sh2
-rwxr-xr-xt/t7508-status.sh127
-rwxr-xr-xt/t7800-difftool.sh2
-rwxr-xr-xt/t7810-grep.sh (renamed from t/t7002-grep.sh)0
-rwxr-xr-xt/t7811-grep-open.sh168
-rwxr-xr-xt/t9001-send-email.sh10
-rwxr-xr-xt/t9100-git-svn-basic.sh2
-rwxr-xr-xt/t9118-git-svn-funky-branch-names.sh48
-rwxr-xr-xt/t9119-git-svn-info.sh2
-rwxr-xr-xt/t9129-git-svn-i18n-commitencoding.sh2
-rwxr-xr-xt/t9143-git-svn-gc.sh2
-rwxr-xr-xt/t9200-git-cvsexportcommit.sh4
-rwxr-xr-xt/t9400-git-cvsserver-server.sh6
-rwxr-xr-xt/t9401-git-cvsserver-crlf.sh6
-rwxr-xr-xt/t9600-cvsimport.sh2
-rwxr-xr-xt/t9700-perl-git.sh7
-rwxr-xr-xt/t9700/test.pl12
-rw-r--r--t/test-lib.sh91
-rw-r--r--test-date.c11
-rw-r--r--transport-helper.c4
-rw-r--r--url.c8
-rw-r--r--wt-status.c20
-rw-r--r--wt-status.h1
-rw-r--r--xdiff/xutils.c4
169 files changed, 2483 insertions, 790 deletions
diff --git a/Documentation/Makefile b/Documentation/Makefile
index 04f69cf64e..a4c4063e50 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -6,7 +6,7 @@ MAN5_TXT=gitattributes.txt gitignore.txt gitmodules.txt githooks.txt \
gitrepository-layout.txt
MAN7_TXT=gitcli.txt gittutorial.txt gittutorial-2.txt \
gitcvs-migration.txt gitcore-tutorial.txt gitglossary.txt \
- gitdiffcore.txt gitworkflows.txt
+ gitdiffcore.txt gitrevisions.txt gitworkflows.txt
MAN_TXT = $(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT)
MAN_XML=$(patsubst %.txt,%.xml,$(MAN_TXT))
diff --git a/Documentation/RelNotes-1.7.1.1.txt b/Documentation/RelNotes-1.7.1.1.txt
index bfdb5ba064..3f6b3148a3 100644
--- a/Documentation/RelNotes-1.7.1.1.txt
+++ b/Documentation/RelNotes-1.7.1.1.txt
@@ -1,5 +1,5 @@
-Git v1.7.1.1 Release Notes (draft)
-==================================
+Git v1.7.1.1 Release Notes
+==========================
Fixes since v1.7.1
------------------
@@ -17,11 +17,18 @@ Fixes since v1.7.1
* We didn't recognize timezone "Z" as a synonym for "UTC" (75b37e70).
+ * In 1.7.0, read-tree and user commands that use the mechanism such as
+ checkout and merge were fixed to handle switching between branches one
+ of which has a file while the other has a directory at the same path
+ correctly even when there are some "confusing" pathnames in them. But
+ the algorithm used for this fix was suboptimal and had a terrible
+ performance degradation especially in larger trees.
+
* "git am -3" did not show diagnosis when the patch in the message was corrupt.
* After "git apply --whitespace=fix" removed trailing blank lines in an
patch in a patch series, it failed to apply later patches that depend
- on the presense of such blank lines.
+ on the presence of such blank lines.
* "git bundle --stdin" segfaulted.
@@ -57,10 +64,15 @@ Fixes since v1.7.1
* "git merge --log" used to replace the custom message given by "-m" with
the shortlog, instead of appending to it.
+ * "git notes copy" without any other argument segfaulted.
+
* "git pull" accepted "--dry-run", gave it to underlying "git fetch" but
ignored the option itself, resulting in a bogus attempt to merge
unrelated commit.
+ * "git rebase" did not faithfully reproduce a malformed author ident, that
+ is often seen in a repository converted from foreign SCMs.
+
* "git reset --hard" started from a wrong directory and a working tree in
a nonstandard location is in use got confused.
@@ -68,6 +80,9 @@ Fixes since v1.7.1
EHLO/HELO exchange, causing rejected connection from picky servers.
It learned --smtp-domain option to solve this issue.
+ * "git send-email" did not declare a content-transfer-encoding and
+ content-type even when its payload needs to be sent in 8-bit.
+
* "git show -C -C" and other corner cases lost diff metainfo output
in 1.7.0.
@@ -79,10 +94,3 @@ Fixes since v1.7.1
* "git status" showed excess "hints" even when advice.statusHints is set to false.
And other minor fixes and documentation updates.
-
-
---
-exec >/var/tmp/1
-O=v1.7.1-195-gb2ebbd8
-echo O=$(git describe HEAD)
-git shortlog --no-merges HEAD ^$O
diff --git a/Documentation/RelNotes-1.7.1.2.txt b/Documentation/RelNotes-1.7.1.2.txt
new file mode 100644
index 0000000000..46b6a960c7
--- /dev/null
+++ b/Documentation/RelNotes-1.7.1.2.txt
@@ -0,0 +1,19 @@
+Git v1.7.1.2 Release Notes
+==========================
+
+Fixes since v1.7.1.1
+--------------------
+
+ * "git commit" did not honor GIT_REFLOG_ACTION environment variable, resulting
+ reflog messages for cherry-pick and revert actions to be recorded as "commit".
+
+ * "git clone/fetch/pull" issued an incorrect error message when a ref and
+ a symref that points to the ref were updated at the same time. This
+ obviously would update them to the same value, and should not result in
+ an error condition.
+
+ * "git diff" inside a tree with many pathnames that have certain
+ characters has become very slow in 1.7.0 by mistake.
+
+ * "git rev-parse --parseopt --stop-at-non-option" did not stop at non option
+ when --keep-dashdash was in effect.
diff --git a/Documentation/RelNotes-1.7.2.txt b/Documentation/RelNotes-1.7.2.txt
index 8ed7406266..f24b3876af 100644
--- a/Documentation/RelNotes-1.7.2.txt
+++ b/Documentation/RelNotes-1.7.2.txt
@@ -4,10 +4,13 @@ Git v1.7.2 Release Notes (draft)
Updates since v1.7.1
--------------------
- * core.eol configuration and eol attribute are the new way to control
- the end of line conventions for files in the working tree;
- core.autocrlf overrides it, keeping the traditional behaviour by
- default.
+ * core.eol configuration and text/eol attributes are the new way to control
+ the end of line conventions for files in the working tree.
+
+ * core.autocrlf has been made safer - it will now only handle line
+ endings for new files and files that are LF-only in the
+ repository. To normalize content that has been checked in with
+ CRLF, use the new eol/text attributes.
* The whitespace rules used in "git apply --whitespace" and "git diff"
gained a new member in the family (tab-in-indent) to help projects with
@@ -44,9 +47,13 @@ Updates since v1.7.1
prepares to create a root commit that is not connected to any existing
commit.
- * "git cherry-pick" learned to pick a range of commits (e.g. "cherry-pick
- A..B"); this does not have nicer sequencing control "rebase [-i]" has,
- though.
+ * "git cherry-pick" learned to pick a range of commits
+ (e.g. "cherry-pick A..B" and "cherry-pick --stdin"), so did "git
+ revert"; these do not support the nicer sequencing control "rebase
+ [-i]" has, though.
+
+ * "git cherry-pick" and "git revert" learned --strategy option to specify
+ the merge strategy to be used when performing three-way merges.
* "git cvsserver" can be told to use pserver; its password file can be
stored outside the repository.
@@ -74,8 +81,12 @@ Updates since v1.7.1
* Various options to "git grep" (e.g. --count, --name-only) work better
with binary files.
+ * "git grep" learned "-Ovi" to open the files with hits in your editor.
+
* "git help -w" learned "chrome" and "chromium" browsers.
+ * "git log --decorate" shows commit decorations in various colours.
+
* "git log --follow <path>" follows across copies (it used to only follow
renames). This may make the processing more expensive.
@@ -92,8 +103,6 @@ Updates since v1.7.1
* "git remote" learned "set-branches" subcommand.
- * "git revert" learned --strategy option to specify the merge strategy.
-
* "git rev-list A..B" learned --ancestry-path option to further limit
the result to the commits that are on the ancestry chain between A and
B (i.e. commits that are not descendants of A are excluded).
@@ -106,10 +115,14 @@ Updates since v1.7.1
* "git status -s -b" shows the current branch in the output.
+ * "git status" learned "--ignore-submodules" option.
+
* Various "gitweb" enhancements and clean-ups, including syntax
highlighting, "plackup" support for instaweb, .fcgi suffix to run
it as FastCGI script, etc.
+ * The test harness has been updated to produce TAP-friendly output.
+
Fixes since v1.7.1
------------------
@@ -118,37 +131,25 @@ All of the fixes in v1.7.1.X maintenance series are included in this
release, unless otherwise noted.
* We didn't URL decode "file:///path/to/repo" correctly when path/to/repo
- had percent-encoded characters (638794c, 9d2e942).
-
- * "git commit" did not honor GIT_REFLOG_ACTION environment variable, resulting
- reflog messages for cherry-pick and revert actions to be recorded as "commit".
-
- * "git clone/fetch/pull" issued an incorrect error message when a ref and
- a symref that points to the ref were updated at the same time. This
- obviously would update them to the same value, and should not result in
- an error condition (0e71bc3).
+ had percent-encoded characters (638794c, 9d2e942, ce83eda, 3c73a1d).
* "git clone" did not configure remote.origin.url correctly for bare
clones (df61c889).
- * "git diff" inside a tree with many pathnames that have certain
- characters has become very slow in 1.7.0 by mistake (will merge
- e53e6b443 to 'maint').
-
* "git diff --graph" works better with "--color-words" and other options
(81fa024..4297c0a).
* "git diff" could show ambiguous abbreviation of blob object names on
its "index" line (3e5a188).
- * "git rebase" did not faithfully reproduce a malformed author ident, that
- is often seen in a repository converted from foreign SCMs (43c23251).
-
* "git reset --hard" started from a wrong directory and a working tree in
a nonstandard location is in use got confused (560fb6a1).
+ * "git read-tree -m A B" used to switch to branch B while retaining
+ local changes added an incorrect cache-tree information (b1f47514).
+
--
exec >/var/tmp/1
-O=v1.7.1-592-gcf4403a
+O=v1.7.2-rc2-17-gc9a9766
echo O=$(git describe HEAD)
git shortlog --no-merges HEAD ^maint ^$O
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 4c491045c9..e75434b3ef 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -690,6 +690,11 @@ color.diff.<slot>::
(highlighting whitespace errors). The values of these variables may be
specified as in color.branch.<slot>.
+color.decorate.<slot>::
+ Use customized color for 'git log --decorate' output. `<slot>` is one
+ of `branch`, `remoteBranch`, `tag`, `stash` or `HEAD` for local
+ branches, remote tracking branches, tags, stash and HEAD, respectively.
+
color.grep::
When set to `always`, always highlight matches. When `false` (or
`never`), never. When set to `true` or `auto`, use color only
@@ -881,9 +886,11 @@ format.headers::
Additional email headers to include in a patch to be submitted
by mail. See linkgit:git-format-patch[1].
+format.to::
format.cc::
- Additional "Cc:" headers to include in a patch to be submitted
- by mail. See the --cc option in linkgit:git-format-patch[1].
+ Additional recipients to include in a patch to be submitted
+ by mail. See the --to and --cc options in
+ linkgit:git-format-patch[1].
format.subjectprefix::
The default for format-patch is to output files with the '[PATCH]'
@@ -1727,6 +1734,15 @@ status.submodulesummary::
summary of commits for modified submodules will be shown (see
--summary-limit option of linkgit:git-submodule[1]).
+submodule.<name>.path::
+submodule.<name>.url::
+submodule.<name>.update::
+ The path within this project, URL, and the updating strategy
+ for a submodule. These variables are initially populated
+ by 'git submodule init'; edit them to override the
+ URL and other values found in the `.gitmodules` file. See
+ linkgit:git-submodule[1] and linkgit:gitmodules[5] for details.
+
tar.umask::
This variable can be used to restrict the permission bits of
tar archive entries. The default is 0002, which turns off the
diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
index e745a3ccdc..2371262b10 100644
--- a/Documentation/diff-options.txt
+++ b/Documentation/diff-options.txt
@@ -328,8 +328,14 @@ endif::git-format-patch[]
--no-ext-diff::
Disallow external diff drivers.
---ignore-submodules::
- Ignore changes to submodules in the diff generation.
+--ignore-submodules[=<when>]::
+ Ignore changes to submodules in the diff generation. <when> can be
+ either "untracked", "dirty" or "all", which is the default. When
+ "untracked" is used submodules are not considered dirty when they only
+ contain untracked content (but they are still scanned for modified
+ content). Using "dirty" ignores all changes to the work tree of submodules,
+ only changes to the commits stored in the superproject are shown (this was
+ the behavior until 1.7.0). Using "all" hides all changes to submodules.
--src-prefix=<prefix>::
Show the given source prefix instead of "a/".
diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index 044ec882cc..9333c42c55 100644
--- a/Documentation/fetch-options.txt
+++ b/Documentation/fetch-options.txt
@@ -34,6 +34,7 @@ ifndef::git-pull[]
Allow several <repository> and <group> arguments to be
specified. No <refspec>s may be specified.
+-p::
--prune::
After fetching, remove any remote tracking branches which
no longer exist on the remote.
diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt
index 9ebbe9402b..a3f56b07fd 100644
--- a/Documentation/git-cat-file.txt
+++ b/Documentation/git-cat-file.txt
@@ -27,7 +27,7 @@ OPTIONS
<object>::
The name of the object to show.
For a more complete list of ways to spell object names, see
- the "SPECIFYING REVISIONS" section in linkgit:git-rev-parse[1].
+ the "SPECIFYING REVISIONS" section in linkgit:gitrevisions[1].
-t::
Instead of the content, show the object type identified by
diff --git a/Documentation/git-check-ref-format.txt b/Documentation/git-check-ref-format.txt
index 379eee6734..f5c2e0601d 100644
--- a/Documentation/git-check-ref-format.txt
+++ b/Documentation/git-check-ref-format.txt
@@ -49,7 +49,7 @@ git imposes the following rules on how references are named:
These rules make it easy for shell script based tools to parse
reference names, pathname expansion by the shell when a reference name is used
unquoted (by mistake), and also avoids ambiguities in certain
-reference name expressions (see linkgit:git-rev-parse[1]):
+reference name expressions (see linkgit:gitrevisions[1]):
. A double-dot `..` is often used as in `ref1..ref2`, and in some
contexts this notation means `{caret}ref1 ref2` (i.e. not in
diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index 261dd90c38..1bacd2e104 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -263,7 +263,7 @@ the above checkout would fail like this:
+
------------
$ git checkout mytopic
-fatal: Entry 'frotz' not uptodate. Cannot merge.
+error: You have local changes to 'frotz'; not switching branches.
------------
+
You can give the `-m` flag to the command, which would try a
diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt
index bcb4c758b7..2cef579316 100644
--- a/Documentation/git-cherry-pick.txt
+++ b/Documentation/git-cherry-pick.txt
@@ -20,8 +20,8 @@ OPTIONS
-------
<commit>...::
Commits to cherry-pick.
- For a more complete list of ways to spell commits, see the
- "SPECIFYING REVISIONS" section in linkgit:git-rev-parse[1].
+ For a more complete list of ways to spell commits, see
+ linkgit:gitrevisions[1].
Sets of commits can be passed but no traversal is done by
default, as if the '--no-walk' option was specified, see
linkgit:git-rev-list[1].
@@ -113,6 +113,13 @@ git cherry-pick --ff ..next::
are in next but not HEAD to the current branch, creating a new
commit for each new change.
+git rev-list --reverse master \-- README | git cherry-pick -n --stdin::
+
+ Apply the changes introduced by all commits on the master
+ branch that touched README to the working tree and index,
+ so the result can be inspected and made into a single new
+ commit if suitable.
+
Author
------
Written by Junio C Hamano <gitster@pobox.com>
diff --git a/Documentation/git-diff.txt b/Documentation/git-diff.txt
index 723a64872f..08fd4099ad 100644
--- a/Documentation/git-diff.txt
+++ b/Documentation/git-diff.txt
@@ -68,11 +68,11 @@ for the last two forms that use ".." notations, can be any
<tree-ish>.
For a more complete list of ways to spell <commit>, see
-"SPECIFYING REVISIONS" section in linkgit:git-rev-parse[1].
+"SPECIFYING REVISIONS" section in linkgit:gitrevisions[1].
However, "diff" is about comparing two _endpoints_, not ranges,
and the range notations ("<commit>..<commit>" and
"<commit>\...<commit>") do not mean a range as defined in the
-"SPECIFYING RANGES" section in linkgit:git-rev-parse[1].
+"SPECIFYING RANGES" section in linkgit:gitrevisions[1].
OPTIONS
-------
diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt
index 19082b04eb..77a0a2481a 100644
--- a/Documentation/git-fast-import.txt
+++ b/Documentation/git-fast-import.txt
@@ -439,7 +439,7 @@ Marks must be declared (via `mark`) before they can be used.
* A complete 40 byte or abbreviated commit SHA-1 in hex.
* Any valid Git SHA-1 expression that resolves to a commit. See
- ``SPECIFYING REVISIONS'' in linkgit:git-rev-parse[1] for details.
+ ``SPECIFYING REVISIONS'' in linkgit:gitrevisions[1] for details.
The special case of restarting an incremental import from the
current branch value should be written as:
diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt
index c8c81e8437..4b3f5ba535 100644
--- a/Documentation/git-format-patch.txt
+++ b/Documentation/git-format-patch.txt
@@ -39,7 +39,7 @@ There are two ways to specify which commits to operate on.
that leads to the <since> to be output.
2. Generic <revision range> expression (see "SPECIFYING
- REVISIONS" section in linkgit:git-rev-parse[1]) means the
+ REVISIONS" section in linkgit:gitrevisions[1]) means the
commits in the specified range.
The first rule takes precedence in the case of a single <commit>. To
diff --git a/Documentation/git-gc.txt b/Documentation/git-gc.txt
index a9e0882e9b..315f07ef1c 100644
--- a/Documentation/git-gc.txt
+++ b/Documentation/git-gc.txt
@@ -137,6 +137,13 @@ If you are expecting some objects to be collected and they aren't, check
all of those locations and decide whether it makes sense in your case to
remove those references.
+HOOKS
+-----
+
+The 'git gc --auto' command will run the 'pre-auto-gc' hook. See
+linkgit:githooks[5] for more information.
+
+
SEE ALSO
--------
linkgit:git-prune[1]
diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt
index 912bddd7b6..5474dd7f94 100644
--- a/Documentation/git-grep.txt
+++ b/Documentation/git-grep.txt
@@ -14,6 +14,7 @@ SYNOPSIS
[-E | --extended-regexp] [-G | --basic-regexp]
[-F | --fixed-strings] [-n]
[-l | --files-with-matches] [-L | --files-without-match]
+ [(-O | --open-files-in-pager) [<pager>]]
[-z | --null]
[-c | --count] [--all-match] [-q | --quiet]
[--max-depth <depth>]
@@ -104,6 +105,13 @@ OPTIONS
For better compatibility with 'git diff', `--name-only` is a
synonym for `--files-with-matches`.
+-O [<pager>]::
+--open-files-in-pager [<pager>]::
+ Open the matching files in the pager (not the output of 'grep').
+ If the pager happens to be "less" or "vi", and the user
+ specified only one pattern, the first file is positioned at
+ the first match automatically.
+
-z::
--null::
Output \0 instead of the character that normally follows a
diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt
index 0e6ff31823..e970664fe1 100644
--- a/Documentation/git-log.txt
+++ b/Documentation/git-log.txt
@@ -23,9 +23,6 @@ each commit introduces are shown.
OPTIONS
-------
-:git-log: 1
-include::diff-options.txt[]
-
-<n>::
Limits the number of commits to show.
@@ -34,8 +31,11 @@ include::diff-options.txt[]
either <since> or <until> is omitted, it defaults to
`HEAD`, i.e. the tip of the current branch.
For a more complete list of ways to spell <since>
- and <until>, see "SPECIFYING REVISIONS" section in
- linkgit:git-rev-parse[1].
+ and <until>, see linkgit:gitrevisions[1].
+
+--follow::
+ Continue listing the history of a file beyond renames
+ (works only for a single file).
--no-decorate::
--decorate[=short|full|no]::
@@ -56,9 +56,6 @@ include::diff-options.txt[]
the specified paths; this means that "<path>..." limits only
commits, and doesn't limit diff for those commits.
---follow::
- Continue listing the history of a file beyond renames/copies.
-
--log-size::
Before the log message print out its size in bytes. Intended
mainly for porcelain tools consumption. If git is unable to
@@ -72,6 +69,11 @@ include::diff-options.txt[]
to be prefixed with "\-- " to separate them from options or
refnames.
+Common diff options
+~~~~~~~~~~~~~~~~~~~
+
+:git-log: 1
+include::diff-options.txt[]
include::rev-list-options.txt[]
diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index 48570242fb..b68abff28a 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -41,7 +41,7 @@ OPTIONS[[OPTIONS]]
+
The <src> is often the name of the branch you would want to push, but
it can be any arbitrary "SHA-1 expression", such as `master~4` or
-`HEAD` (see linkgit:git-rev-parse[1]).
+`HEAD` (see linkgit:gitrevisions[1]).
+
The <dst> tells which ref on the remote side is updated with this
push. Arbitrary expressions cannot be used here, an actual ref must
diff --git a/Documentation/git-reflog.txt b/Documentation/git-reflog.txt
index 4eaa62b691..5a0451aaf3 100644
--- a/Documentation/git-reflog.txt
+++ b/Documentation/git-reflog.txt
@@ -40,7 +40,7 @@ see linkgit:git-log[1].
The reflog is useful in various git commands, to specify the old value
of a reference. For example, `HEAD@\{2\}` means "where HEAD used to be
two moves ago", `master@\{one.week.ago\}` means "where master used to
-point to one week ago", and so on. See linkgit:git-rev-parse[1] for
+point to one week ago", and so on. See linkgit:gitrevisions[1] for
more details.
To delete single entries from the reflog, use the subcommand "delete"
diff --git a/Documentation/git-rerere.txt b/Documentation/git-rerere.txt
index acc220a00f..db99d4786e 100644
--- a/Documentation/git-rerere.txt
+++ b/Documentation/git-rerere.txt
@@ -7,7 +7,7 @@ git-rerere - Reuse recorded resolution of conflicted merges
SYNOPSIS
--------
-'git rerere' ['clear'|'diff'|'status'|'gc']
+'git rerere' ['clear'|'forget' [<pathspec>]|'diff'|'status'|'gc']
DESCRIPTION
-----------
@@ -40,6 +40,11 @@ This resets the metadata used by rerere if a merge resolution is to be
aborted. Calling 'git am [--skip|--abort]' or 'git rebase [--skip|--abort]'
will automatically invoke this command.
+'forget' <pathspec>::
+
+This resets the conflict resolutions which rerere has recorded for the current
+conflict in <pathspec>. The <pathspec> is optional.
+
'diff'::
This displays diffs for the current state of the resolution. It is
diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt
index 8db600f6ba..0727f431c6 100644
--- a/Documentation/git-rev-parse.txt
+++ b/Documentation/git-rev-parse.txt
@@ -174,202 +174,7 @@ shown. If the pattern does not contain a globbing character (`?`,
Flags and parameters to be parsed.
-SPECIFYING REVISIONS
---------------------
-
-A revision parameter typically, but not necessarily, names a
-commit object. They use what is called an 'extended SHA1'
-syntax. Here are various ways to spell object names. The
-ones listed near the end of this list are to name trees and
-blobs contained in a commit.
-
-* The full SHA1 object name (40-byte hexadecimal string), or
- a substring of such that is unique within the repository.
- E.g. dae86e1950b1277e545cee180551750029cfe735 and dae86e both
- name the same commit object if there are no other object in
- your repository whose object name starts with dae86e.
-
-* An output from 'git describe'; i.e. a closest tag, optionally
- followed by a dash and a number of commits, followed by a dash, a
- `g`, and an abbreviated object name.
-
-* A symbolic ref name. E.g. 'master' typically means the commit
- object referenced by refs/heads/master. If you
- happen to have both heads/master and tags/master, you can
- explicitly say 'heads/master' to tell git which one you mean.
- When ambiguous, a `<name>` is disambiguated by taking the
- first match in the following rules:
-
- . if `$GIT_DIR/<name>` exists, that is what you mean (this is usually
- useful only for `HEAD`, `FETCH_HEAD`, `ORIG_HEAD` and `MERGE_HEAD`);
-
- . otherwise, `refs/<name>` if exists;
-
- . otherwise, `refs/tags/<name>` if exists;
-
- . otherwise, `refs/heads/<name>` if exists;
-
- . otherwise, `refs/remotes/<name>` if exists;
-
- . otherwise, `refs/remotes/<name>/HEAD` if exists.
-+
-HEAD names the commit your changes in the working tree is based on.
-FETCH_HEAD records the branch you fetched from a remote repository
-with your last 'git fetch' invocation.
-ORIG_HEAD is created by commands that moves your HEAD in a drastic
-way, to record the position of the HEAD before their operation, so that
-you can change the tip of the branch back to the state before you ran
-them easily.
-MERGE_HEAD records the commit(s) you are merging into your branch
-when you run 'git merge'.
-+
-Note that any of the `refs/*` cases above may come either from
-the `$GIT_DIR/refs` directory or from the `$GIT_DIR/packed-refs` file.
-
-* A ref followed by the suffix '@' with a date specification
- enclosed in a brace
- pair (e.g. '\{yesterday\}', '\{1 month 2 weeks 3 days 1 hour 1
- second ago\}' or '\{1979-02-26 18:30:00\}') to specify the value
- of the ref at a prior point in time. This suffix may only be
- used immediately following a ref name and the ref must have an
- existing log ($GIT_DIR/logs/<ref>). Note that this looks up the state
- of your *local* ref at a given time; e.g., what was in your local
- `master` branch last week. If you want to look at commits made during
- certain times, see `--since` and `--until`.
-
-* A ref followed by the suffix '@' with an ordinal specification
- enclosed in a brace pair (e.g. '\{1\}', '\{15\}') to specify
- the n-th prior value of that ref. For example 'master@\{1\}'
- is the immediate prior value of 'master' while 'master@\{5\}'
- is the 5th prior value of 'master'. This suffix may only be used
- immediately following a ref name and the ref must have an existing
- log ($GIT_DIR/logs/<ref>).
-
-* You can use the '@' construct with an empty ref part to get at a
- reflog of the current branch. For example, if you are on the
- branch 'blabla', then '@\{1\}' means the same as 'blabla@\{1\}'.
-
-* The special construct '@\{-<n>\}' means the <n>th branch checked out
- before the current one.
-
-* The suffix '@\{upstream\}' to a ref (short form 'ref@\{u\}') refers to
- the branch the ref is set to build on top of. Missing ref defaults
- to the current branch.
-
-* A suffix '{caret}' to a revision parameter means the first parent of
- that commit object. '{caret}<n>' means the <n>th parent (i.e.
- 'rev{caret}'
- is equivalent to 'rev{caret}1'). As a special rule,
- 'rev{caret}0' means the commit itself and is used when 'rev' is the
- object name of a tag object that refers to a commit object.
-
-* A suffix '{tilde}<n>' to a revision parameter means the commit
- object that is the <n>th generation grand-parent of the named
- commit object, following only the first parent. I.e. rev~3 is
- equivalent to rev{caret}{caret}{caret} which is equivalent to
- rev{caret}1{caret}1{caret}1. See below for a illustration of
- the usage of this form.
-
-* A suffix '{caret}' followed by an object type name enclosed in
- brace pair (e.g. `v0.99.8{caret}\{commit\}`) means the object
- could be a tag, and dereference the tag recursively until an
- object of that type is found or the object cannot be
- dereferenced anymore (in which case, barf). `rev{caret}0`
- introduced earlier is a short-hand for `rev{caret}\{commit\}`.
-
-* A suffix '{caret}' followed by an empty brace pair
- (e.g. `v0.99.8{caret}\{\}`) means the object could be a tag,
- and dereference the tag recursively until a non-tag object is
- found.
-
-* A colon, followed by a slash, followed by a text: this names
- a commit whose commit message starts with the specified text.
- This name returns the youngest matching commit which is
- reachable from any ref. If the commit message starts with a
- '!', you have to repeat that; the special sequence ':/!',
- followed by something else than '!' is reserved for now.
-
-* A suffix ':' followed by a path; this names the blob or tree
- at the given path in the tree-ish object named by the part
- before the colon.
-
-* A colon, optionally followed by a stage number (0 to 3) and a
- colon, followed by a path; this names a blob object in the
- index at the given path. Missing stage number (and the colon
- that follows it) names a stage 0 entry. During a merge, stage
- 1 is the common ancestor, stage 2 is the target branch's version
- (typically the current branch), and stage 3 is the version from
- the branch being merged.
-
-Here is an illustration, by Jon Loeliger. Both commit nodes B
-and C are parents of commit node A. Parent commits are ordered
-left-to-right.
-
-........................................
-G H I J
- \ / \ /
- D E F
- \ | / \
- \ | / |
- \|/ |
- B C
- \ /
- \ /
- A
-........................................
-
- A = = A^0
- B = A^ = A^1 = A~1
- C = A^2 = A^2
- D = A^^ = A^1^1 = A~2
- E = B^2 = A^^2
- F = B^3 = A^^3
- G = A^^^ = A^1^1^1 = A~3
- H = D^2 = B^^2 = A^^^2 = A~2^2
- I = F^ = B^3^ = A^^3^
- J = F^2 = B^3^2 = A^^3^2
-
-
-SPECIFYING RANGES
------------------
-
-History traversing commands such as 'git log' operate on a set
-of commits, not just a single commit. To these commands,
-specifying a single revision with the notation described in the
-previous section means the set of commits reachable from that
-commit, following the commit ancestry chain.
-
-To exclude commits reachable from a commit, a prefix `{caret}`
-notation is used. E.g. `{caret}r1 r2` means commits reachable
-from `r2` but exclude the ones reachable from `r1`.
-
-This set operation appears so often that there is a shorthand
-for it. When you have two commits `r1` and `r2` (named according
-to the syntax explained in SPECIFYING REVISIONS above), you can ask
-for commits that are reachable from r2 excluding those that are reachable
-from r1 by `{caret}r1 r2` and it can be written as `r1..r2`.
-
-A similar notation `r1\...r2` is called symmetric difference
-of `r1` and `r2` and is defined as
-`r1 r2 --not $(git merge-base --all r1 r2)`.
-It is the set of commits that are reachable from either one of
-`r1` or `r2` but not from both.
-
-Two other shorthands for naming a set that is formed by a commit
-and its parent commits exist. The `r1{caret}@` notation means all
-parents of `r1`. `r1{caret}!` includes commit `r1` but excludes
-all of its parents.
-
-Here are a handful of examples:
-
- D G H D
- D F G H I J D F
- ^G D H D
- ^D B E I J F B
- B...C G H D E B C
- ^D B C E I J F B C
- C^@ I J F
- F^! D G H D F
+include::revisions.txt[]
PARSEOPT
--------
diff --git a/Documentation/git-revert.txt b/Documentation/git-revert.txt
index dea4f53522..b7d9ef7e47 100644
--- a/Documentation/git-revert.txt
+++ b/Documentation/git-revert.txt
@@ -31,7 +31,7 @@ OPTIONS
<commit>...::
Commits to revert.
For a more complete list of ways to spell commit names, see
- "SPECIFYING REVISIONS" section in linkgit:git-rev-parse[1].
+ linkgit:gitrevisions[1].
Sets of commits can also be given but no traversal is done by
default, see linkgit:git-rev-list[1] and its '--no-walk'
option.
diff --git a/Documentation/git-show-branch.txt b/Documentation/git-show-branch.txt
index f1499bba88..81ba29669c 100644
--- a/Documentation/git-show-branch.txt
+++ b/Documentation/git-show-branch.txt
@@ -32,7 +32,7 @@ no <rev> nor <glob> is given on the command line.
OPTIONS
-------
<rev>::
- Arbitrary extended SHA1 expression (see linkgit:git-rev-parse[1])
+ Arbitrary extended SHA1 expression (see linkgit:gitrevisions[1])
that typically names a branch head or a tag.
<glob>::
diff --git a/Documentation/git-show.txt b/Documentation/git-show.txt
index 55e687a7c7..0002bfb045 100644
--- a/Documentation/git-show.txt
+++ b/Documentation/git-show.txt
@@ -36,7 +36,7 @@ OPTIONS
<object>...::
The names of objects to show.
For a more complete list of ways to spell object names, see
- "SPECIFYING REVISIONS" section in linkgit:git-rev-parse[1].
+ "SPECIFYING REVISIONS" section in linkgit:gitrevisions[1].
include::pretty-options.txt[]
diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt
index fd0fe7cb56..2fd054c104 100644
--- a/Documentation/git-status.txt
+++ b/Documentation/git-status.txt
@@ -53,6 +53,17 @@ See linkgit:git-config[1] for configuration variable
used to change the default for when the option is not
specified.
+--ignore-submodules[=<when>]::
+ Ignore changes to submodules when looking for changes. <when> can be
+ either "untracked", "dirty" or "all", which is the default. When
+ "untracked" is used submodules are not considered dirty when they only
+ contain untracked content (but they are still scanned for modified
+ content). Using "dirty" ignores all changes to the work tree of submodules,
+ only changes to the commits stored in the superproject are shown (this was
+ the behavior before 1.7.0). Using "all" hides all changes to submodules
+ (and suppresses the output of submodule summaries when the config option
+ `status.submodulesummary` is set).
+
-z::
Terminate entries with NUL, instead of LF. This implies
the `--porcelain` output format if no other format is given.
diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index cdabfd29ad..76a832a3ac 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -95,6 +95,10 @@ is the superproject and submodule repositories will be kept
together in the same relative location, and only the
superproject's URL needs to be provided: git-submodule will correctly
locate the submodule using the relative URL in .gitmodules.
++
+The submodule will be added with "git add --force <path>". I.e. git
+doesn't care if the new path is in a `gitignore`. Your invocation of
+"git submodule add" is considered enough to override it.
status::
Show the status of the submodules. This will print the SHA-1 of the
diff --git a/Documentation/git.txt b/Documentation/git.txt
index bec6348dab..12066ab3fc 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -44,9 +44,10 @@ unreleased) version of git, that is available from 'master'
branch of the `git.git` repository.
Documentation for older releases are available here:
-* link:v1.7.1/git.html[documentation for release 1.7.1]
+* link:v1.7.1.1/git.html[documentation for release 1.7.1.1]
* release notes for
+ link:RelNotes-1.7.1.1.txt[1.7.1.1],
link:RelNotes-1.7.1.txt[1.7.1].
* link:v1.7.0.6/git.html[documentation for release 1.7.0.6]
@@ -478,7 +479,7 @@ HEAD::
(i.e. the contents of `$GIT_DIR/refs/heads/<head>`).
For a more complete list of ways to spell object names, see
-"SPECIFYING REVISIONS" section in linkgit:git-rev-parse[1].
+"SPECIFYING REVISIONS" section in linkgit:gitrevisions[1].
File/Directory Structure
diff --git a/Documentation/gitcore-tutorial.txt b/Documentation/gitcore-tutorial.txt
index f7815e96a2..ed3ddc92cb 100644
--- a/Documentation/gitcore-tutorial.txt
+++ b/Documentation/gitcore-tutorial.txt
@@ -971,7 +971,7 @@ commits from the master branch. The string inside brackets
before the commit log message is a short name you can use to
name the commit. In the above example, 'master' and 'mybranch'
are branch heads. 'master^' is the first parent of 'master'
-branch head. Please see linkgit:git-rev-parse[1] if you want to
+branch head. Please see linkgit:gitrevisions[1] if you want to
see more complex cases.
[NOTE]
diff --git a/Documentation/gitk.txt b/Documentation/gitk.txt
index 99baa24a2d..05ac1c79f7 100644
--- a/Documentation/gitk.txt
+++ b/Documentation/gitk.txt
@@ -69,7 +69,7 @@ frequently used options.
the form "'<from>'..'<to>'" to show all revisions between '<from>' and
back to '<to>'. Note, more advanced revision selection can be applied.
For a more complete list of ways to spell object names, see
- "SPECIFYING REVISIONS" section in linkgit:git-rev-parse[1].
+ linkgit:gitrevisions[1].
<path>...::
diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt
index 5daf750d19..72a13d18e0 100644
--- a/Documentation/gitmodules.txt
+++ b/Documentation/gitmodules.txt
@@ -29,6 +29,9 @@ submodule.<name>.path::
submodule.<name>.url::
Defines an url from where the submodule repository can be cloned.
+ This may be either an absolute URL ready to be passed to
+ linkgit:git-clone[1] or (if it begins with ./ or ../) a location
+ relative to the superproject's origin repository.
submodule.<name>.update::
Defines what to do when the submodule is updated by the superproject.
diff --git a/Documentation/gitrevisions.txt b/Documentation/gitrevisions.txt
new file mode 100644
index 0000000000..fc4789f98e
--- /dev/null
+++ b/Documentation/gitrevisions.txt
@@ -0,0 +1,35 @@
+gitrevisions(7)
+================
+
+NAME
+----
+gitrevisions - specifying revisions and ranges for git
+
+SYNOPSIS
+--------
+gitrevisions
+
+
+DESCRIPTION
+-----------
+
+Many Git commands take revision parameters as arguments. Depending on
+the command, they denote a specific commit or, for commands which
+walk the revision graph (such as linkgit:git-log[1]), all commits which can
+be reached from that commit. In the latter case one can also specify a
+range of revisions explicitly.
+
+In addition, some Git commands (such as linkgit:git-show[1]) also take
+revision parameters which denote other objects than commits, e.g. blobs
+("files") or trees ("directories of files").
+
+include::revisions.txt[]
+
+
+SEE ALSO
+--------
+linkgit:git-rev-parse[1]
+
+GIT
+---
+Part of the linkgit:git[1] suite
diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt
index 73569c073e..cc562a057a 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -98,6 +98,15 @@ you would get an output like this:
This implies the '--topo-order' option by default, but the
'--date-order' option may also be specified.
+ifdef::git-rev-list[]
+--count::
+ Print a number stating how many commits would have been
+ listed, and suppress all other output. When used together
+ with '--left-right', instead print the counts for left and
+ right commits, separated by a tab.
+endif::git-rev-list[]
+
+
ifndef::git-rev-list[]
Diff Formatting
~~~~~~~~~~~~~~~
diff --git a/Documentation/revisions.txt b/Documentation/revisions.txt
new file mode 100644
index 0000000000..fe846f043c
--- /dev/null
+++ b/Documentation/revisions.txt
@@ -0,0 +1,199 @@
+SPECIFYING REVISIONS
+--------------------
+
+A revision parameter typically, but not necessarily, names a
+commit object. They use what is called an 'extended SHA1'
+syntax. Here are various ways to spell object names. The
+ones listed near the end of this list are to name trees and
+blobs contained in a commit.
+
+* The full SHA1 object name (40-byte hexadecimal string), or
+ a substring of such that is unique within the repository.
+ E.g. dae86e1950b1277e545cee180551750029cfe735 and dae86e both
+ name the same commit object if there are no other object in
+ your repository whose object name starts with dae86e.
+
+* An output from 'git describe'; i.e. a closest tag, optionally
+ followed by a dash and a number of commits, followed by a dash, a
+ `g`, and an abbreviated object name.
+
+* A symbolic ref name. E.g. 'master' typically means the commit
+ object referenced by refs/heads/master. If you
+ happen to have both heads/master and tags/master, you can
+ explicitly say 'heads/master' to tell git which one you mean.
+ When ambiguous, a `<name>` is disambiguated by taking the
+ first match in the following rules:
+
+ . if `$GIT_DIR/<name>` exists, that is what you mean (this is usually
+ useful only for `HEAD`, `FETCH_HEAD`, `ORIG_HEAD` and `MERGE_HEAD`);
+
+ . otherwise, `refs/<name>` if exists;
+
+ . otherwise, `refs/tags/<name>` if exists;
+
+ . otherwise, `refs/heads/<name>` if exists;
+
+ . otherwise, `refs/remotes/<name>` if exists;
+
+ . otherwise, `refs/remotes/<name>/HEAD` if exists.
++
+HEAD names the commit your changes in the working tree is based on.
+FETCH_HEAD records the branch you fetched from a remote repository
+with your last 'git fetch' invocation.
+ORIG_HEAD is created by commands that moves your HEAD in a drastic
+way, to record the position of the HEAD before their operation, so that
+you can change the tip of the branch back to the state before you ran
+them easily.
+MERGE_HEAD records the commit(s) you are merging into your branch
+when you run 'git merge'.
++
+Note that any of the `refs/*` cases above may come either from
+the `$GIT_DIR/refs` directory or from the `$GIT_DIR/packed-refs` file.
+
+* A ref followed by the suffix '@' with a date specification
+ enclosed in a brace
+ pair (e.g. '\{yesterday\}', '\{1 month 2 weeks 3 days 1 hour 1
+ second ago\}' or '\{1979-02-26 18:30:00\}') to specify the value
+ of the ref at a prior point in time. This suffix may only be
+ used immediately following a ref name and the ref must have an
+ existing log ($GIT_DIR/logs/<ref>). Note that this looks up the state
+ of your *local* ref at a given time; e.g., what was in your local
+ `master` branch last week. If you want to look at commits made during
+ certain times, see `--since` and `--until`.
+
+* A ref followed by the suffix '@' with an ordinal specification
+ enclosed in a brace pair (e.g. '\{1\}', '\{15\}') to specify
+ the n-th prior value of that ref. For example 'master@\{1\}'
+ is the immediate prior value of 'master' while 'master@\{5\}'
+ is the 5th prior value of 'master'. This suffix may only be used
+ immediately following a ref name and the ref must have an existing
+ log ($GIT_DIR/logs/<ref>).
+
+* You can use the '@' construct with an empty ref part to get at a
+ reflog of the current branch. For example, if you are on the
+ branch 'blabla', then '@\{1\}' means the same as 'blabla@\{1\}'.
+
+* The special construct '@\{-<n>\}' means the <n>th branch checked out
+ before the current one.
+
+* The suffix '@\{upstream\}' to a ref (short form 'ref@\{u\}') refers to
+ the branch the ref is set to build on top of. Missing ref defaults
+ to the current branch.
+
+* A suffix '{caret}' to a revision parameter (e.g. 'HEAD{caret}') means the first parent of
+ that commit object. '{caret}<n>' means the <n>th parent (i.e.
+ 'rev{caret}'
+ is equivalent to 'rev{caret}1'). As a special rule,
+ 'rev{caret}0' means the commit itself and is used when 'rev' is the
+ object name of a tag object that refers to a commit object.
+
+* A suffix '{tilde}<n>' to a revision parameter means the commit
+ object that is the <n>th generation grand-parent of the named
+ commit object, following only the first parent. I.e. rev~3 is
+ equivalent to rev{caret}{caret}{caret} which is equivalent to
+ rev{caret}1{caret}1{caret}1. See below for a illustration of
+ the usage of this form.
+
+* A suffix '{caret}' followed by an object type name enclosed in
+ brace pair (e.g. `v0.99.8{caret}\{commit\}`) means the object
+ could be a tag, and dereference the tag recursively until an
+ object of that type is found or the object cannot be
+ dereferenced anymore (in which case, barf). `rev{caret}0`
+ introduced earlier is a short-hand for `rev{caret}\{commit\}`.
+
+* A suffix '{caret}' followed by an empty brace pair
+ (e.g. `v0.99.8{caret}\{\}`) means the object could be a tag,
+ and dereference the tag recursively until a non-tag object is
+ found.
+
+* A colon, followed by a slash, followed by a text (e.g. `:/fix nasty bug`): this names
+ a commit whose commit message starts with the specified text.
+ This name returns the youngest matching commit which is
+ reachable from any ref. If the commit message starts with a
+ '!', you have to repeat that; the special sequence ':/!',
+ followed by something else than '!' is reserved for now.
+
+* A suffix ':' followed by a path (e.g. `HEAD:README`); this names the blob or tree
+ at the given path in the tree-ish object named by the part
+ before the colon.
+ ':path' (with an empty part before the colon, e.g. `:README`)
+ is a special case of the syntax described next: content
+ recorded in the index at the given path.
+
+* A colon, optionally followed by a stage number (0 to 3) and a
+ colon, followed by a path (e.g. `:0:README`); this names a blob object in the
+ index at the given path. Missing stage number (and the colon
+ that follows it, e.g. `:README`) names a stage 0 entry. During a merge, stage
+ 1 is the common ancestor, stage 2 is the target branch's version
+ (typically the current branch), and stage 3 is the version from
+ the branch being merged.
+
+Here is an illustration, by Jon Loeliger. Both commit nodes B
+and C are parents of commit node A. Parent commits are ordered
+left-to-right.
+
+........................................
+G H I J
+ \ / \ /
+ D E F
+ \ | / \
+ \ | / |
+ \|/ |
+ B C
+ \ /
+ \ /
+ A
+........................................
+
+ A = = A^0
+ B = A^ = A^1 = A~1
+ C = A^2 = A^2
+ D = A^^ = A^1^1 = A~2
+ E = B^2 = A^^2
+ F = B^3 = A^^3
+ G = A^^^ = A^1^1^1 = A~3
+ H = D^2 = B^^2 = A^^^2 = A~2^2
+ I = F^ = B^3^ = A^^3^
+ J = F^2 = B^3^2 = A^^3^2
+
+
+SPECIFYING RANGES
+-----------------
+
+History traversing commands such as 'git log' operate on a set
+of commits, not just a single commit. To these commands,
+specifying a single revision with the notation described in the
+previous section means the set of commits reachable from that
+commit, following the commit ancestry chain.
+
+To exclude commits reachable from a commit, a prefix `{caret}`
+notation is used. E.g. `{caret}r1 r2` means commits reachable
+from `r2` but exclude the ones reachable from `r1`.
+
+This set operation appears so often that there is a shorthand
+for it. When you have two commits `r1` and `r2` (named according
+to the syntax explained in SPECIFYING REVISIONS above), you can ask
+for commits that are reachable from r2 excluding those that are reachable
+from r1 by `{caret}r1 r2` and it can be written as `r1..r2`.
+
+A similar notation `r1\...r2` is called symmetric difference
+of `r1` and `r2` and is defined as
+`r1 r2 --not $(git merge-base --all r1 r2)`.
+It is the set of commits that are reachable from either one of
+`r1` or `r2` but not from both.
+
+Two other shorthands for naming a set that is formed by a commit
+and its parent commits exist. The `r1{caret}@` notation means all
+parents of `r1`. `r1{caret}!` includes commit `r1` but excludes
+all of its parents.
+
+Here are a handful of examples:
+
+ D G H D
+ D F G H I J D F
+ ^G D H D
+ ^D B E I J F B
+ B...C G H D E B C
+ ^D B C E I J F B C
+ C^@ I J F
+ F^! D G H D F
diff --git a/Documentation/technical/api-string-list.txt b/Documentation/technical/api-string-list.txt
index 6d8c24bb1e..3f575bdcff 100644
--- a/Documentation/technical/api-string-list.txt
+++ b/Documentation/technical/api-string-list.txt
@@ -38,8 +38,8 @@ struct string_list list;
int i;
memset(&list, 0, sizeof(struct string_list));
-string_list_append("foo", &list);
-string_list_append("bar", &list);
+string_list_append(&list, "foo");
+string_list_append(&list, "bar");
for (i = 0; i < list.nr; i++)
printf("%s\n", list.items[i].string)
----
diff --git a/Documentation/technical/protocol-capabilities.txt b/Documentation/technical/protocol-capabilities.txt
index fd1a593149..b15517fa06 100644
--- a/Documentation/technical/protocol-capabilities.txt
+++ b/Documentation/technical/protocol-capabilities.txt
@@ -119,7 +119,7 @@ both.
ofs-delta
---------
-Server can send, and client understand PACKv2 with delta refering to
+Server can send, and client understand PACKv2 with delta referring to
its base by position in pack rather than by an obj-id. That is, they can
send/read OBJ_OFS_DELTA (aka type 6) in a packfile.
diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt
index fe6fb722da..22aee34d4a 100644
--- a/Documentation/user-manual.txt
+++ b/Documentation/user-manual.txt
@@ -397,7 +397,7 @@ is usually a shortcut for the HEAD branch in the repository "origin".
For the complete list of paths which git checks for references, and
the order it uses to decide which to choose when there are multiple
references with the same shorthand name, see the "SPECIFYING
-REVISIONS" section of linkgit:git-rev-parse[1].
+REVISIONS" section of linkgit:gitrevisions[1].
[[Updating-a-repository-With-git-fetch]]
Updating a repository with git fetch
@@ -568,7 +568,7 @@ We have seen several ways of naming commits already:
- HEAD: refers to the head of the current branch
There are many more; see the "SPECIFYING REVISIONS" section of the
-linkgit:git-rev-parse[1] man page for the complete list of ways to
+linkgit:gitrevisions[1] man page for the complete list of ways to
name revisions. Some examples:
-------------------------------------------------
@@ -909,7 +909,7 @@ commits reachable from some head but not from any tag in the repository:
$ gitk $( git show-ref --heads ) --not $( git show-ref --tags )
-------------------------------------------------
-(See linkgit:git-rev-parse[1] for explanations of commit-selecting
+(See linkgit:gitrevisions[1] for explanations of commit-selecting
syntax such as `--not`.)
[[making-a-release]]
@@ -1635,7 +1635,7 @@ you've checked out.
The reflogs are kept by default for 30 days, after which they may be
pruned. See linkgit:git-reflog[1] and linkgit:git-gc[1] to learn
how to control this pruning, and see the "SPECIFYING REVISIONS"
-section of linkgit:git-rev-parse[1] for details.
+section of linkgit:gitrevisions[1] for details.
Note that the reflog history is very different from normal git history.
While normal history is shared by every repository that works on the
diff --git a/Makefile b/Makefile
index 9aca8a16d9..bc3c57058f 100644
--- a/Makefile
+++ b/Makefile
@@ -2079,19 +2079,19 @@ endif
test -z "$(NO_CROSS_DIRECTORY_HARDLINKS)" && \
ln "$$bindir/git$X" "$$execdir/git$X" 2>/dev/null || \
cp "$$bindir/git$X" "$$execdir/git$X"; } ; } && \
- { for p in $(BUILT_INS); do \
+ for p in $(BUILT_INS); do \
$(RM) "$$execdir/$$p" && \
ln "$$execdir/git$X" "$$execdir/$$p" 2>/dev/null || \
ln -s "git$X" "$$execdir/$$p" 2>/dev/null || \
cp "$$execdir/git$X" "$$execdir/$$p" || exit; \
- done; } && \
- { test x"$(REMOTE_CURL_ALIASES)" = x || \
- { for p in $(REMOTE_CURL_ALIASES); do \
+ done && \
+ remote_curl_aliases="$(REMOTE_CURL_ALIASES)" && \
+ for p in $$remote_curl_aliases; do \
$(RM) "$$execdir/$$p" && \
ln "$$execdir/git-remote-http$X" "$$execdir/$$p" 2>/dev/null || \
ln -s "git-remote-http$X" "$$execdir/$$p" 2>/dev/null || \
cp "$$execdir/git-remote-http$X" "$$execdir/$$p" || exit; \
- done; } ; } && \
+ done && \
./check_bindir "z$$bindir" "z$$execdir" "$$bindir/git-add$X"
install-gitweb:
diff --git a/block-sha1/sha1.c b/block-sha1/sha1.c
index d880a5336e..c0054a0b0a 100644
--- a/block-sha1/sha1.c
+++ b/block-sha1/sha1.c
@@ -70,6 +70,7 @@
*/
#if defined(__i386__) || defined(__x86_64__) || \
+ defined(_M_IX86) || defined(_M_X64) || \
defined(__ppc__) || defined(__ppc64__) || \
defined(__powerpc__) || defined(__powerpc64__) || \
defined(__s390__) || defined(__s390x__)
diff --git a/builtin/apply.c b/builtin/apply.c
index 562e5345fc..12ef9ea8af 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -2628,7 +2628,7 @@ static struct patch *in_fn_table(const char *name)
if (name == NULL)
return NULL;
- item = string_list_lookup(name, &fn_table);
+ item = string_list_lookup(&fn_table, name);
if (item != NULL)
return (struct patch *)item->util;
@@ -2664,7 +2664,7 @@ static void add_to_fn_table(struct patch *patch)
* file creations and copies
*/
if (patch->new_name != NULL) {
- item = string_list_insert(patch->new_name, &fn_table);
+ item = string_list_insert(&fn_table, patch->new_name);
item->util = patch;
}
@@ -2673,7 +2673,7 @@ static void add_to_fn_table(struct patch *patch)
* later chunks shouldn't patch old names
*/
if ((patch->new_name == NULL) || (patch->is_rename)) {
- item = string_list_insert(patch->old_name, &fn_table);
+ item = string_list_insert(&fn_table, patch->old_name);
item->util = PATH_WAS_DELETED;
}
}
@@ -2686,7 +2686,7 @@ static void prepare_fn_table(struct patch *patch)
while (patch) {
if ((patch->new_name == NULL) || (patch->is_rename)) {
struct string_list_item *item;
- item = string_list_insert(patch->old_name, &fn_table);
+ item = string_list_insert(&fn_table, patch->old_name);
item->util = PATH_TO_BE_DELETED;
}
patch = patch->next;
@@ -3394,7 +3394,7 @@ static void add_name_limit(const char *name, int exclude)
{
struct string_list_item *it;
- it = string_list_append(name, &limit_by_name);
+ it = string_list_append(&limit_by_name, name);
it->util = exclude ? NULL : (void *) 1;
}
diff --git a/builtin/commit.c b/builtin/commit.c
index 3d99cf9158..a78dbd83bf 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -72,7 +72,7 @@ static char *author_name, *author_email, *author_date;
static int all, edit_flag, also, interactive, only, amend, signoff;
static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;
static int no_post_rewrite, allow_empty_message;
-static char *untracked_files_arg, *force_date;
+static char *untracked_files_arg, *force_date, *ignore_submodule_arg;
/*
* The default commit message cleanup mode will remove the lines
* beginning with # (shell comments) and leading and trailing
@@ -219,7 +219,7 @@ static int list_paths(struct string_list *list, const char *with_tree,
continue;
if (!match_pathspec(pattern, ce->name, ce_namelen(ce), 0, m))
continue;
- item = string_list_insert(ce->name, list);
+ item = string_list_insert(list, ce->name);
if (ce_skip_worktree(ce))
item->util = item; /* better a valid pointer than a fake one */
}
@@ -343,9 +343,13 @@ static char *prepare_index(int argc, const char **argv, const char *prefix, int
if (!pathspec || !*pathspec) {
fd = hold_locked_index(&index_lock, 1);
refresh_cache_or_die(refresh_flags);
- if (write_cache(fd, active_cache, active_nr) ||
- commit_locked_index(&index_lock))
- die("unable to write new_index file");
+ if (active_cache_changed) {
+ if (write_cache(fd, active_cache, active_nr) ||
+ commit_locked_index(&index_lock))
+ die("unable to write new_index file");
+ } else {
+ rollback_lock_file(&index_lock);
+ }
commit_style = COMMIT_AS_IS;
return get_index_file();
}
@@ -1059,6 +1063,9 @@ int cmd_status(int argc, const char **argv, const char *prefix)
PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
OPT_BOOLEAN(0, "ignored", &show_ignored_in_status,
"show ignored files"),
+ { OPTION_STRING, 0, "ignore-submodules", &ignore_submodule_arg, "when",
+ "ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)",
+ PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
OPT_END(),
};
@@ -1082,13 +1089,16 @@ int cmd_status(int argc, const char **argv, const char *prefix)
fd = hold_locked_index(&index_lock, 0);
if (0 <= fd) {
- if (!write_cache(fd, active_cache, active_nr))
+ if (active_cache_changed &&
+ !write_cache(fd, active_cache, active_nr))
commit_locked_index(&index_lock);
- rollback_lock_file(&index_lock);
+ else
+ rollback_lock_file(&index_lock);
}
s.is_initial = get_sha1(s.reference, sha1) ? 1 : 0;
s.in_merge = in_merge;
+ s.ignore_submodule_arg = ignore_submodule_arg;
wt_status_collect(&s);
if (s.relative_paths)
@@ -1107,6 +1117,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
break;
case STATUS_FORMAT_LONG:
s.verbose = verbose;
+ s.ignore_submodule_arg = ignore_submodule_arg;
wt_status_print(&s);
break;
}
diff --git a/builtin/diff.c b/builtin/diff.c
index ffcdd055ca..bb128631a9 100644
--- a/builtin/diff.c
+++ b/builtin/diff.c
@@ -407,17 +407,32 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
result = builtin_diff_index(&rev, argc, argv);
else if (ents == 2)
result = builtin_diff_tree(&rev, argc, argv, ent);
- else if ((ents == 3) && (ent[0].item->flags & UNINTERESTING)) {
- /* diff A...B where there is one sane merge base between
- * A and B. We have ent[0] == merge-base, ent[1] == A,
- * and ent[2] == B. Show diff between the base and B.
+ else if (ent[0].item->flags & UNINTERESTING) {
+ /*
+ * Perhaps the user gave us A...B, which expands
+ * to a list of negative merge bases followed by
+ * A (symmetric-left) and B? Let's make sure...
*/
- ent[1] = ent[2];
+ for (i = 1; i < ents; i++)
+ if (!(ent[i].item->flags & UNINTERESTING))
+ break;
+ if (ents != i + 2 ||
+ (ent[i+1].item->flags & UNINTERESTING) ||
+ (!(ent[i].item->flags & SYMMETRIC_LEFT)) ||
+ (ent[i+1].item->flags & SYMMETRIC_LEFT))
+ die("what do you mean by that?");
+ /*
+ * diff A...B where there is at least one merge base
+ * between A and B. We have ent[0] == merge-base,
+ * ent[ents-2] == A, and ent[ents-1] == B. Show diff
+ * between the base and B. Note that we pick one
+ * merge base at random if there are more than one.
+ */
+ ent[1] = ent[ents-1];
result = builtin_diff_tree(&rev, argc, argv, ent);
- }
- else
+ } else
result = builtin_diff_combined(&rev, argc, argv,
- ent, ents);
+ ent, ents);
result = diff_result_code(&rev.diffopt, result);
if (1 < rev.diffopt.skip_stat_unmatch)
refresh_index_quietly();
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index c6dd71a7bc..9fe25ff0b3 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -438,7 +438,7 @@ static void get_tags_and_duplicates(struct object_array *pending,
/* handle nested tags */
while (tag && tag->object.type == OBJ_TAG) {
parse_object(tag->object.sha1);
- string_list_append(full_name, extra_refs)->util = tag;
+ string_list_append(extra_refs, full_name)->util = tag;
tag = (struct tag *)tag->tagged;
}
if (!tag)
@@ -464,7 +464,7 @@ static void get_tags_and_duplicates(struct object_array *pending,
}
if (commit->util)
/* more than one name for the same object */
- string_list_append(full_name, extra_refs)->util = commit;
+ string_list_append(extra_refs, full_name)->util = commit;
else
commit->util = full_name;
}
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 5cb369cfd1..6eb1dfea09 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -528,7 +528,7 @@ static int add_existing(const char *refname, const unsigned char *sha1,
int flag, void *cbdata)
{
struct string_list *list = (struct string_list *)cbdata;
- struct string_list_item *item = string_list_insert(refname, list);
+ struct string_list_item *item = string_list_insert(list, refname);
item->util = (void *)sha1;
return 0;
}
@@ -617,7 +617,7 @@ static void find_non_local_tags(struct transport *transport,
string_list_has_string(&existing_refs, ref->name))
continue;
- item = string_list_insert(ref->name, &remote_refs);
+ item = string_list_insert(&remote_refs, ref->name);
item->util = (void *)ref->old_sha1;
}
string_list_clear(&existing_refs, 0);
@@ -634,7 +634,7 @@ static void find_non_local_tags(struct transport *transport,
* For all the tags in the remote_refs string list, call
* add_to_tail to add them to the list of refs to be fetched
*/
- for_each_string_list(add_to_tail, &remote_refs, &data);
+ for_each_string_list(&remote_refs, add_to_tail, &data);
string_list_clear(&remote_refs, 0);
}
@@ -696,8 +696,8 @@ static int do_fetch(struct transport *transport,
for (rm = ref_map; rm; rm = rm->next) {
if (rm->peer_ref) {
- peer_item = string_list_lookup(rm->peer_ref->name,
- &existing_refs);
+ peer_item = string_list_lookup(&existing_refs,
+ rm->peer_ref->name);
if (peer_item)
hashcpy(rm->peer_ref->old_sha1,
peer_item->util);
@@ -746,7 +746,7 @@ static int get_one_remote_for_fetch(struct remote *remote, void *priv)
{
struct string_list *list = priv;
if (!remote->skip_default_update)
- string_list_append(remote->name, list);
+ string_list_append(list, remote->name);
return 0;
}
@@ -765,8 +765,8 @@ static int get_remote_group(const char *key, const char *value, void *priv)
int space = strcspn(value, " \t\n");
while (*value) {
if (space > 1) {
- string_list_append(xstrndup(value, space),
- g->list);
+ string_list_append(g->list,
+ xstrndup(value, space));
}
value += space + (value[space] != '\0');
space = strcspn(value, " \t\n");
@@ -788,7 +788,7 @@ static int add_remote_or_group(const char *name, struct string_list *list)
if (!remote_is_configured(name))
return 0;
remote = remote_get(name);
- string_list_append(remote->name, list);
+ string_list_append(list, remote->name);
}
return 1;
}
diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
index 44204257c7..bc3c5e6d3e 100644
--- a/builtin/fmt-merge-msg.c
+++ b/builtin/fmt-merge-msg.c
@@ -82,7 +82,7 @@ static int handle_line(char *line)
item = unsorted_string_list_lookup(&srcs, src);
if (!item) {
- item = string_list_append(src, &srcs);
+ item = string_list_append(&srcs, src);
item->util = xcalloc(1, sizeof(struct src_data));
init_src_data(item->util);
}
@@ -93,19 +93,19 @@ static int handle_line(char *line)
src_data->head_status |= 1;
} else if (!prefixcmp(line, "branch ")) {
origin = line + 7;
- string_list_append(origin, &src_data->branch);
+ string_list_append(&src_data->branch, origin);
src_data->head_status |= 2;
} else if (!prefixcmp(line, "tag ")) {
origin = line;
- string_list_append(origin + 4, &src_data->tag);
+ string_list_append(&src_data->tag, origin + 4);
src_data->head_status |= 2;
} else if (!prefixcmp(line, "remote branch ")) {
origin = line + 14;
- string_list_append(origin, &src_data->r_branch);
+ string_list_append(&src_data->r_branch, origin);
src_data->head_status |= 2;
} else {
origin = src;
- string_list_append(line, &src_data->generic);
+ string_list_append(&src_data->generic, line);
src_data->head_status |= 2;
}
@@ -118,7 +118,7 @@ static int handle_line(char *line)
sprintf(new_origin, "%s of %s", origin, src);
origin = new_origin;
}
- string_list_append(origin, &origins)->util = sha1;
+ string_list_append(&origins, origin)->util = sha1;
return 0;
}
@@ -176,10 +176,10 @@ static void shortlog(const char *name, unsigned char *sha1,
strbuf_ltrim(&sb);
if (!sb.len)
- string_list_append(sha1_to_hex(commit->object.sha1),
- &subjects);
+ string_list_append(&subjects,
+ sha1_to_hex(commit->object.sha1));
else
- string_list_append(strbuf_detach(&sb, NULL), &subjects);
+ string_list_append(&subjects, strbuf_detach(&sb, NULL));
}
if (count > limit)
diff --git a/builtin/grep.c b/builtin/grep.c
index d0a73da07a..597f76bc42 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -11,6 +11,8 @@
#include "tree-walk.h"
#include "builtin.h"
#include "parse-options.h"
+#include "string-list.h"
+#include "run-command.h"
#include "userdiff.h"
#include "grep.h"
#include "quote.h"
@@ -556,6 +558,33 @@ static int grep_file(struct grep_opt *opt, const char *filename)
}
}
+static void append_path(struct grep_opt *opt, const void *data, size_t len)
+{
+ struct string_list *path_list = opt->output_priv;
+
+ if (len == 1 && *(const char *)data == '\0')
+ return;
+ string_list_append(path_list, xstrndup(data, len));
+}
+
+static void run_pager(struct grep_opt *opt, const char *prefix)
+{
+ struct string_list *path_list = opt->output_priv;
+ const char **argv = xmalloc(sizeof(const char *) * (path_list->nr + 1));
+ int i, status;
+
+ for (i = 0; i < path_list->nr; i++)
+ argv[i] = path_list->items[i].string;
+ argv[path_list->nr] = NULL;
+
+ if (prefix && chdir(prefix))
+ die("Failed to chdir: %s", prefix);
+ status = run_command_v_opt(argv, RUN_USING_SHELL);
+ if (status)
+ exit(status);
+ free(argv);
+}
+
static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
{
int hit = 0;
@@ -590,7 +619,6 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
if (hit && opt->status_only)
break;
}
- free_grep_patterns(opt);
return hit;
}
@@ -675,6 +703,25 @@ static int grep_object(struct grep_opt *opt, const char **paths,
die("unable to grep from object of type %s", typename(obj->type));
}
+static int grep_objects(struct grep_opt *opt, const char **paths,
+ const struct object_array *list)
+{
+ unsigned int i;
+ int hit = 0;
+ const unsigned int nr = list->nr;
+
+ for (i = 0; i < nr; i++) {
+ struct object *real_obj;
+ real_obj = deref_tag(list->objects[i].item, NULL, 0);
+ if (grep_object(opt, paths, real_obj, list->objects[i].name)) {
+ hit = 1;
+ if (opt->status_only)
+ break;
+ }
+ }
+ return hit;
+}
+
static int grep_directory(struct grep_opt *opt, const char **paths)
{
struct dir_struct dir;
@@ -689,7 +736,6 @@ static int grep_directory(struct grep_opt *opt, const char **paths)
if (hit && opt->status_only)
break;
}
- free_grep_patterns(opt);
return hit;
}
@@ -786,9 +832,11 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
int cached = 0;
int seen_dashdash = 0;
int external_grep_allowed__ignored;
+ const char *show_in_pager = NULL, *default_pager = "dummy";
struct grep_opt opt;
struct object_array list = { 0, 0, NULL };
const char **paths = NULL;
+ struct string_list path_list = { NULL, 0, 0, 0 };
int i;
int dummy;
int nongit = 0, use_index = 1;
@@ -872,6 +920,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
OPT_BOOLEAN(0, "all-match", &opt.all_match,
"show only matches from files that match all patterns"),
OPT_GROUP(""),
+ { OPTION_STRING, 'O', "open-files-in-pager", &show_in_pager,
+ "pager", "show matching files in the pager",
+ PARSE_OPT_OPTARG, NULL, (intptr_t)default_pager },
OPT_BOOLEAN(0, "ext-grep", &external_grep_allowed__ignored,
"allow calling of grep(1) (ignored by this build)"),
{ OPTION_CALLBACK, 0, "help-all", &options, NULL, "show usage",
@@ -947,6 +998,18 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
argc--;
}
+ if (show_in_pager == default_pager)
+ show_in_pager = git_pager(1);
+ if (show_in_pager) {
+ opt.color = 0;
+ opt.name_only = 1;
+ opt.null_following_name = 1;
+ opt.output_priv = &path_list;
+ opt.output = append_path;
+ string_list_append(&path_list, show_in_pager);
+ use_threads = 0;
+ }
+
if (!opt.pattern_list)
die("no pattern given.");
if (!opt.fixed && opt.ignore_case)
@@ -1003,44 +1066,51 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
paths[1] = NULL;
}
+ if (show_in_pager && (cached || list.nr))
+ die("--open-files-in-pager only works on the worktree");
+
+ if (show_in_pager && opt.pattern_list && !opt.pattern_list->next) {
+ const char *pager = path_list.items[0].string;
+ int len = strlen(pager);
+
+ if (len > 4 && is_dir_sep(pager[len - 5]))
+ pager += len - 4;
+
+ if (!strcmp("less", pager) || !strcmp("vi", pager)) {
+ struct strbuf buf = STRBUF_INIT;
+ strbuf_addf(&buf, "+/%s%s",
+ strcmp("less", pager) ? "" : "*",
+ opt.pattern_list->pattern);
+ string_list_append(&path_list, buf.buf);
+ strbuf_detach(&buf, NULL);
+ }
+ }
+
+ if (!show_in_pager)
+ setup_pager();
+
+
if (!use_index) {
- int hit;
if (cached)
die("--cached cannot be used with --no-index.");
if (list.nr)
die("--no-index cannot be used with revs.");
hit = grep_directory(&opt, paths);
- if (use_threads)
- hit |= wait_all();
- return !hit;
- }
-
- if (!list.nr) {
- int hit;
+ } else if (!list.nr) {
if (!cached)
setup_work_tree();
hit = grep_cache(&opt, paths, cached);
- if (use_threads)
- hit |= wait_all();
- return !hit;
- }
-
- if (cached)
- die("both --cached and trees are given.");
-
- for (i = 0; i < list.nr; i++) {
- struct object *real_obj;
- real_obj = deref_tag(list.objects[i].item, NULL, 0);
- if (grep_object(&opt, paths, real_obj, list.objects[i].name)) {
- hit = 1;
- if (opt.status_only)
- break;
- }
+ } else {
+ if (cached)
+ die("both --cached and trees are given.");
+ hit = grep_objects(&opt, paths, &list);
}
if (use_threads)
hit |= wait_all();
+ if (hit && show_in_pager)
+ run_pager(&opt, prefix);
free_grep_patterns(&opt);
return !hit;
}
diff --git a/builtin/log.c b/builtin/log.c
index f068583618..08b872263c 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -296,6 +296,9 @@ static int git_log_config(const char *var, const char *value, void *cb)
default_show_root = git_config_bool(var, value);
return 0;
}
+ if (!prefixcmp(var, "color.decorate."))
+ return parse_decorate_color_config(var, 15, value);
+
return git_diff_ui_config(var, value, cb);
}
@@ -535,13 +538,13 @@ static void add_header(const char *value)
len--;
if (!strncasecmp(value, "to: ", 4)) {
- item = string_list_append(value + 4, &extra_to);
+ item = string_list_append(&extra_to, value + 4);
len -= 4;
} else if (!strncasecmp(value, "cc: ", 4)) {
- item = string_list_append(value + 4, &extra_cc);
+ item = string_list_append(&extra_cc, value + 4);
len -= 4;
} else {
- item = string_list_append(value, &extra_hdr);
+ item = string_list_append(&extra_hdr, value);
}
item->string[len] = '\0';
@@ -566,13 +569,13 @@ static int git_format_config(const char *var, const char *value, void *cb)
if (!strcmp(var, "format.to")) {
if (!value)
return config_error_nonbool(var);
- string_list_append(value, &extra_to);
+ string_list_append(&extra_to, value);
return 0;
}
if (!strcmp(var, "format.cc")) {
if (!value)
return config_error_nonbool(var);
- string_list_append(value, &extra_cc);
+ string_list_append(&extra_cc, value);
return 0;
}
if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff")) {
@@ -959,7 +962,7 @@ static int to_callback(const struct option *opt, const char *arg, int unset)
if (unset)
string_list_clear(&extra_to, 0);
else
- string_list_append(arg, &extra_to);
+ string_list_append(&extra_to, arg);
return 0;
}
@@ -968,7 +971,7 @@ static int cc_callback(const struct option *opt, const char *arg, int unset)
if (unset)
string_list_clear(&extra_cc, 0);
else
- string_list_append(arg, &extra_cc);
+ string_list_append(&extra_cc, arg);
return 0;
}
@@ -1251,7 +1254,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
rev.ref_message_ids = xcalloc(1, sizeof(struct string_list));
if (in_reply_to) {
const char *msgid = clean_message_id(in_reply_to);
- string_list_append(msgid, rev.ref_message_ids);
+ string_list_append(rev.ref_message_ids, msgid);
}
rev.numbered_files = numbered_files;
rev.patch_suffix = fmt_patch_suffix;
@@ -1298,8 +1301,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
&& (!cover_letter || rev.nr > 1))
free(rev.message_id);
else
- string_list_append(rev.message_id,
- rev.ref_message_ids);
+ string_list_append(rev.ref_message_ids,
+ rev.message_id);
}
gen_message_id(&rev, sha1_to_hex(commit->object.sha1));
}
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 0804047693..1b9b8a8b4a 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -190,7 +190,7 @@ static void show_ru_info(void)
{
if (!the_index.resolve_undo)
return;
- for_each_string_list(show_one_ru, the_index.resolve_undo, NULL);
+ for_each_string_list(the_index.resolve_undo, show_one_ru, NULL);
}
static void show_files(struct dir_struct *dir)
diff --git a/builtin/mailsplit.c b/builtin/mailsplit.c
index cdfc1b7042..e4560da191 100644
--- a/builtin/mailsplit.c
+++ b/builtin/mailsplit.c
@@ -121,7 +121,7 @@ static int populate_maildir_list(struct string_list *list, const char *path)
if (dent->d_name[0] == '.')
continue;
snprintf(name, sizeof(name), "%s/%s", *sub, dent->d_name);
- string_list_insert(name, list);
+ string_list_insert(list, name);
}
closedir(dir);
diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c
index fc00d794d6..9b25ddc979 100644
--- a/builtin/merge-tree.c
+++ b/builtin/merge-tree.c
@@ -60,6 +60,7 @@ static void *result(struct merge_list *entry, unsigned long *size)
{
enum object_type type;
struct blob *base, *our, *their;
+ const char *path = entry->path;
if (!entry->stage)
return read_sha1_file(entry->blob->object.sha1, &type, size);
@@ -76,7 +77,7 @@ static void *result(struct merge_list *entry, unsigned long *size)
their = NULL;
if (entry)
their = entry->blob;
- return merge_file(entry->path, base, our, their, size);
+ return merge_file(path, base, our, their, size);
}
static void *origin(struct merge_list *entry, unsigned long *size)
diff --git a/builtin/mv.c b/builtin/mv.c
index c07f53b343..38574b89f7 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -180,7 +180,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
} else if (string_list_has_string(&src_for_dst, dst))
bad = "multiple sources for the same target";
else
- string_list_insert(dst, &src_for_dst);
+ string_list_insert(&src_for_dst, dst);
if (bad) {
if (ignore_errors) {
diff --git a/builtin/notes.c b/builtin/notes.c
index f1f53a80e1..190005f3cd 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -614,6 +614,10 @@ static int copy(int argc, const char **argv, const char *prefix)
}
}
+ if (argc < 2) {
+ error("too few parameters");
+ usage_with_options(git_notes_copy_usage, options);
+ }
if (2 < argc) {
error("too many parameters");
usage_with_options(git_notes_copy_usage, options);
diff --git a/builtin/read-tree.c b/builtin/read-tree.c
index 8bdcab1138..9ad1e66916 100644
--- a/builtin/read-tree.c
+++ b/builtin/read-tree.c
@@ -219,14 +219,9 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
* "-m ent" or "--reset ent" form), we can obtain a fully
* valid cache-tree because the index must match exactly
* what came from the tree.
- *
- * The same holds true if we are switching between two trees
- * using read-tree -m A B. The index must match B after that.
*/
if (nr_trees == 1 && !opts.prefix)
prime_cache_tree(&active_cache_tree, trees[0]);
- else if (nr_trees == 2 && opts.merge)
- prime_cache_tree(&active_cache_tree, trees[1]);
if (write_cache(newfd, active_cache, active_nr) ||
commit_locked_index(&lock_file))
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 29bc8d50bb..d634b5a3d5 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -501,7 +501,7 @@ static void check_aliased_update(struct command *cmd, struct string_list *list)
if (!(flag & REF_ISSYMREF))
return;
- if ((item = string_list_lookup(dst_name, list)) == NULL)
+ if ((item = string_list_lookup(list, dst_name)) == NULL)
return;
cmd->skip_update = 1;
@@ -534,7 +534,7 @@ static void check_aliased_updates(struct command *commands)
for (cmd = commands; cmd; cmd = cmd->next) {
struct string_list_item *item =
- string_list_append(cmd->ref_name, &ref_list);
+ string_list_append(&ref_list, cmd->ref_name);
item->util = (void *)cmd;
}
sort_string_list(&ref_list);
diff --git a/builtin/remote.c b/builtin/remote.c
index 0a52667e0f..6699bc5712 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -94,7 +94,7 @@ static int opt_parse_track(const struct option *opt, const char *arg, int not)
if (not)
string_list_clear(list, 0);
else
- string_list_append(arg, list);
+ string_list_append(list, arg);
return 0;
}
@@ -181,7 +181,7 @@ static int add(int argc, const char **argv)
strbuf_addf(&buf, "remote.%s.fetch", name);
if (track.nr == 0)
- string_list_append("*", &track);
+ string_list_append(&track, "*");
for (i = 0; i < track.nr; i++) {
if (add_branch(buf.buf, track.items[i].string,
name, mirror, &buf2))
@@ -263,7 +263,7 @@ static int config_read_branches(const char *key, const char *value, void *cb)
} else
return 0;
- item = string_list_insert(name, &branch_list);
+ item = string_list_insert(&branch_list, name);
if (!item->util)
item->util = xcalloc(sizeof(struct branch_info), 1);
@@ -278,11 +278,11 @@ static int config_read_branches(const char *key, const char *value, void *cb)
while (space) {
char *merge;
merge = xstrndup(value, space - value);
- string_list_append(merge, &info->merge);
+ string_list_append(&info->merge, merge);
value = abbrev_branch(space + 1);
space = strchr(value, ' ');
}
- string_list_append(xstrdup(value), &info->merge);
+ string_list_append(&info->merge, xstrdup(value));
} else
info->rebase = git_config_bool(orig_key, value);
}
@@ -319,14 +319,14 @@ static int get_ref_states(const struct ref *remote_refs, struct ref_states *stat
for (ref = fetch_map; ref; ref = ref->next) {
unsigned char sha1[20];
if (!ref->peer_ref || read_ref(ref->peer_ref->name, sha1))
- string_list_append(abbrev_branch(ref->name), &states->new);
+ string_list_append(&states->new, abbrev_branch(ref->name));
else
- string_list_append(abbrev_branch(ref->name), &states->tracked);
+ string_list_append(&states->tracked, abbrev_branch(ref->name));
}
stale_refs = get_stale_heads(states->remote, fetch_map);
for (ref = stale_refs; ref; ref = ref->next) {
struct string_list_item *item =
- string_list_append(abbrev_branch(ref->name), &states->stale);
+ string_list_append(&states->stale, abbrev_branch(ref->name));
item->util = xstrdup(ref->name);
}
free_refs(stale_refs);
@@ -375,8 +375,8 @@ static int get_push_ref_states(const struct ref *remote_refs,
continue;
hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
- item = string_list_append(abbrev_branch(ref->peer_ref->name),
- &states->push);
+ item = string_list_append(&states->push,
+ abbrev_branch(ref->peer_ref->name));
item->util = xcalloc(sizeof(struct push_info), 1);
info = item->util;
info->forced = ref->force;
@@ -411,7 +411,7 @@ static int get_push_ref_states_noquery(struct ref_states *states)
states->push.strdup_strings = 1;
if (!remote->push_refspec_nr) {
- item = string_list_append("(matching)", &states->push);
+ item = string_list_append(&states->push, "(matching)");
info = item->util = xcalloc(sizeof(struct push_info), 1);
info->status = PUSH_STATUS_NOTQUERIED;
info->dest = xstrdup(item->string);
@@ -419,11 +419,11 @@ static int get_push_ref_states_noquery(struct ref_states *states)
for (i = 0; i < remote->push_refspec_nr; i++) {
struct refspec *spec = remote->push + i;
if (spec->matching)
- item = string_list_append("(matching)", &states->push);
+ item = string_list_append(&states->push, "(matching)");
else if (strlen(spec->src))
- item = string_list_append(spec->src, &states->push);
+ item = string_list_append(&states->push, spec->src);
else
- item = string_list_append("(delete)", &states->push);
+ item = string_list_append(&states->push, "(delete)");
info = item->util = xcalloc(sizeof(struct push_info), 1);
info->forced = spec->force;
@@ -447,7 +447,7 @@ static int get_head_names(const struct ref *remote_refs, struct ref_states *stat
matches = guess_remote_head(find_ref_by_name(remote_refs, "HEAD"),
fetch_map, 1);
for (ref = matches; ref; ref = ref->next)
- string_list_append(abbrev_branch(ref->name), &states->heads);
+ string_list_append(&states->heads, abbrev_branch(ref->name));
free_refs(fetch_map);
free_refs(matches);
@@ -511,8 +511,8 @@ static int add_branch_for_removal(const char *refname,
if (prefixcmp(refname, "refs/remotes")) {
/* advise user how to delete local branches */
if (!prefixcmp(refname, "refs/heads/"))
- string_list_append(abbrev_branch(refname),
- branches->skipped);
+ string_list_append(branches->skipped,
+ abbrev_branch(refname));
/* silently skip over other non-remote refs */
return 0;
}
@@ -521,7 +521,7 @@ static int add_branch_for_removal(const char *refname,
if (flags & REF_ISSYMREF)
return unlink(git_path("%s", refname));
- item = string_list_append(refname, branches->branches);
+ item = string_list_append(branches->branches, refname);
item->util = xmalloc(20);
hashcpy(item->util, sha1);
@@ -546,7 +546,7 @@ static int read_remote_branches(const char *refname,
strbuf_addf(&buf, "refs/remotes/%s", rename->old);
if (!prefixcmp(refname, buf.buf)) {
- item = string_list_append(xstrdup(refname), rename->remote_branches);
+ item = string_list_append(rename->remote_branches, xstrdup(refname));
symref = resolve_ref(refname, orig_sha1, 1, &flag);
if (flag & REF_ISSYMREF)
item->util = xstrdup(symref);
@@ -832,7 +832,7 @@ static int append_ref_to_tracked_list(const char *refname,
memset(&refspec, 0, sizeof(refspec));
refspec.dst = (char *)refname;
if (!remote_find_tracking(states->remote, &refspec))
- string_list_append(abbrev_branch(refspec.src), &states->tracked);
+ string_list_append(&states->tracked, abbrev_branch(refspec.src));
return 0;
}
@@ -885,7 +885,7 @@ static int add_remote_to_show_info(struct string_list_item *item, void *cb_data)
int n = strlen(item->string);
if (n > info->width)
info->width = n;
- string_list_insert(item->string, info->list);
+ string_list_insert(info->list, item->string);
return 0;
}
@@ -932,7 +932,7 @@ static int add_local_to_show_info(struct string_list_item *branch_item, void *cb
if (branch_info->rebase)
show_info->any_rebase = 1;
- item = string_list_insert(branch_item->string, show_info->list);
+ item = string_list_insert(show_info->list, branch_item->string);
item->util = branch_info;
return 0;
@@ -980,7 +980,7 @@ static int add_push_to_show_info(struct string_list_item *push_item, void *cb_da
show_info->width = n;
if ((n = strlen(push_info->dest)) > show_info->width2)
show_info->width2 = n;
- item = string_list_append(push_item->string, show_info->list);
+ item = string_list_append(show_info->list, push_item->string);
item->util = push_item->util;
return 0;
}
@@ -1096,24 +1096,24 @@ static int show(int argc, const char **argv)
/* remote branch info */
info.width = 0;
- for_each_string_list(add_remote_to_show_info, &states.new, &info);
- for_each_string_list(add_remote_to_show_info, &states.tracked, &info);
- for_each_string_list(add_remote_to_show_info, &states.stale, &info);
+ for_each_string_list(&states.new, add_remote_to_show_info, &info);
+ for_each_string_list(&states.tracked, add_remote_to_show_info, &info);
+ for_each_string_list(&states.stale, add_remote_to_show_info, &info);
if (info.list->nr)
printf(" Remote branch%s:%s\n",
info.list->nr > 1 ? "es" : "",
no_query ? " (status not queried)" : "");
- for_each_string_list(show_remote_info_item, info.list, &info);
+ for_each_string_list(info.list, show_remote_info_item, &info);
string_list_clear(info.list, 0);
/* git pull info */
info.width = 0;
info.any_rebase = 0;
- for_each_string_list(add_local_to_show_info, &branch_list, &info);
+ for_each_string_list(&branch_list, add_local_to_show_info, &info);
if (info.list->nr)
printf(" Local branch%s configured for 'git pull':\n",
info.list->nr > 1 ? "es" : "");
- for_each_string_list(show_local_info_item, info.list, &info);
+ for_each_string_list(info.list, show_local_info_item, &info);
string_list_clear(info.list, 0);
/* git push info */
@@ -1121,14 +1121,14 @@ static int show(int argc, const char **argv)
printf(" Local refs will be mirrored by 'git push'\n");
info.width = info.width2 = 0;
- for_each_string_list(add_push_to_show_info, &states.push, &info);
+ for_each_string_list(&states.push, add_push_to_show_info, &info);
qsort(info.list->items, info.list->nr,
sizeof(*info.list->items), cmp_string_with_push);
if (info.list->nr)
printf(" Local ref%s configured for 'git push'%s:\n",
info.list->nr > 1 ? "s" : "",
no_query ? " (status not queried)" : "");
- for_each_string_list(show_push_info_item, info.list, &info);
+ for_each_string_list(info.list, show_push_info_item, &info);
string_list_clear(info.list, 0);
free_remote_ref_states(&states);
@@ -1460,10 +1460,10 @@ static int get_one_entry(struct remote *remote, void *priv)
if (remote->url_nr > 0) {
strbuf_addf(&url_buf, "%s (fetch)", remote->url[0]);
- string_list_append(remote->name, list)->util =
+ string_list_append(list, remote->name)->util =
strbuf_detach(&url_buf, NULL);
} else
- string_list_append(remote->name, list)->util = NULL;
+ string_list_append(list, remote->name)->util = NULL;
if (remote->pushurl_nr) {
url = remote->pushurl;
url_nr = remote->pushurl_nr;
@@ -1474,7 +1474,7 @@ static int get_one_entry(struct remote *remote, void *priv)
for (i = 0; i < url_nr; i++)
{
strbuf_addf(&url_buf, "%s (push)", url[i]);
- string_list_append(remote->name, list)->util =
+ string_list_append(list, remote->name)->util =
strbuf_detach(&url_buf, NULL);
}
diff --git a/builtin/rerere.c b/builtin/rerere.c
index 0048f9ef7f..39ad60169d 100644
--- a/builtin/rerere.c
+++ b/builtin/rerere.c
@@ -59,7 +59,7 @@ static void garbage_collect(struct string_list *rr)
cutoff = (has_rerere_resolution(e->d_name)
? cutoff_resolve : cutoff_noresolve);
if (then < now - cutoff * 86400)
- string_list_append(e->d_name, &to_remove);
+ string_list_append(&to_remove, e->d_name);
}
for (i = 0; i < to_remove.nr; i++)
unlink_rr_item(to_remove.items[i].string);
@@ -135,7 +135,7 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)
if (!has_rerere_resolution(name))
unlink_rr_item(name);
}
- unlink_or_warn(git_path("rr-cache/MERGE_RR"));
+ unlink_or_warn(git_path("MERGE_RR"));
} else if (!strcmp(argv[1], "gc"))
garbage_collect(&merge_rr);
else if (!strcmp(argv[1], "status"))
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index 51ceb19d88..efe9360e2f 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -50,6 +50,15 @@ static void show_commit(struct commit *commit, void *data)
graph_show_commit(revs->graph);
+ if (revs->count) {
+ if (commit->object.flags & SYMMETRIC_LEFT)
+ revs->count_left++;
+ else
+ revs->count_right++;
+ finish_commit(commit, data);
+ return;
+ }
+
if (info->show_timestamp)
printf("%lu ", commit->date);
if (info->header_prefix)
@@ -400,5 +409,12 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
quiet ? finish_object : show_object,
&info);
+ if (revs.count) {
+ if (revs.left_right)
+ printf("%d\t%d\n", revs.count_left, revs.count_right);
+ else
+ printf("%d\n", revs.count_left + revs.count_right);
+ }
+
return 0;
}
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index b676e29635..a5a1c86e92 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -407,8 +407,8 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
ALLOC_GROW(opts, onb + 1, osz);
memset(opts + onb, 0, sizeof(opts[onb]));
argc = parse_options(argc, argv, prefix, opts, usage,
- keep_dashdash ? PARSE_OPT_KEEP_DASHDASH : 0 |
- stop_at_non_option ? PARSE_OPT_STOP_AT_NON_OPTION : 0 |
+ (keep_dashdash ? PARSE_OPT_KEEP_DASHDASH : 0) |
+ (stop_at_non_option ? PARSE_OPT_STOP_AT_NON_OPTION : 0) |
PARSE_OPT_SHELL_EVAL);
strbuf_addf(&parsed, " --");
diff --git a/builtin/revert.c b/builtin/revert.c
index 853e9e406c..8b9d829a73 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -50,10 +50,14 @@ static const char *strategy;
static char *get_encoding(const char *message);
+static const char * const *revert_or_cherry_pick_usage(void)
+{
+ return action == REVERT ? revert_usage : cherry_pick_usage;
+}
+
static void parse_args(int argc, const char **argv)
{
- const char * const * usage_str =
- action == REVERT ? revert_usage : cherry_pick_usage;
+ const char * const * usage_str = revert_or_cherry_pick_usage();
int noop;
struct option options[] = {
OPT_BOOLEAN('n', "no-commit", &no_commit, "don't automatically commit"),
@@ -78,8 +82,10 @@ static void parse_args(int argc, const char **argv)
die("program error");
}
- commit_argc = parse_options(argc, argv, NULL, options, usage_str, 0);
- if (commit_argc < 1)
+ commit_argc = parse_options(argc, argv, NULL, options, usage_str,
+ PARSE_OPT_KEEP_ARGV0 |
+ PARSE_OPT_KEEP_UNKNOWN);
+ if (commit_argc < 2)
usage_with_options(usage_str, options);
commit_argv = argv;
@@ -525,27 +531,22 @@ static int do_pick_commit(void)
static void prepare_revs(struct rev_info *revs)
{
- int argc = 0;
- int i;
- const char **argv = xmalloc((commit_argc + 4) * sizeof(*argv));
+ int argc;
- argv[argc++] = NULL;
- argv[argc++] = "--no-walk";
+ init_revisions(revs, NULL);
+ revs->no_walk = 1;
if (action != REVERT)
- argv[argc++] = "--reverse";
- for (i = 0; i < commit_argc; i++)
- argv[argc++] = commit_argv[i];
- argv[argc++] = NULL;
+ revs->reverse = 1;
+
+ argc = setup_revisions(commit_argc, commit_argv, revs, NULL);
+ if (argc > 1)
+ usage(*revert_or_cherry_pick_usage());
- init_revisions(revs, NULL);
- setup_revisions(argc - 1, argv, revs, NULL);
if (prepare_revision_walk(revs))
die("revision walk setup failed");
if (!revs->commits)
die("empty commit set passed");
-
- free(argv);
}
static int revert_or_cherry_pick(int argc, const char **argv)
diff --git a/builtin/shortlog.c b/builtin/shortlog.c
index 5089502800..0a9681ba7e 100644
--- a/builtin/shortlog.c
+++ b/builtin/shortlog.c
@@ -84,7 +84,7 @@ static void insert_one_record(struct shortlog *log,
snprintf(namebuf + len, room, " <%.*s>", maillen, emailbuf);
}
- item = string_list_insert(namebuf, &log->list);
+ item = string_list_insert(&log->list, namebuf);
if (item->util == NULL)
item->util = xcalloc(1, sizeof(struct string_list));
@@ -115,7 +115,7 @@ static void insert_one_record(struct shortlog *log,
}
}
- string_list_append(buffer, item->util);
+ string_list_append(item->util, buffer);
}
static void read_from_stdin(struct shortlog *log)
diff --git a/builtin/show-ref.c b/builtin/show-ref.c
index 17ada88dfb..0b2a9ad1a9 100644
--- a/builtin/show-ref.c
+++ b/builtin/show-ref.c
@@ -105,7 +105,7 @@ match:
static int add_existing(const char *refname, const unsigned char *sha1, int flag, void *cbdata)
{
struct string_list *list = (struct string_list *)cbdata;
- string_list_insert(refname, list);
+ string_list_insert(list, refname);
return 0;
}
diff --git a/commit.h b/commit.h
index e958a7c3df..eb2b8ac3cd 100644
--- a/commit.h
+++ b/commit.h
@@ -28,6 +28,7 @@ extern const char *commit_type;
extern struct decoration name_decoration;
struct name_decoration {
struct name_decoration *next;
+ int type;
char name[1];
};
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 14874377af..67569901e7 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -42,6 +42,24 @@
# set GIT_PS1_SHOWUNTRACKEDFILES to a nonempty value. If there're
# untracked files, then a '%' will be shown next to the branch name.
#
+# If you would like to see the difference between HEAD and its
+# upstream, set GIT_PS1_SHOWUPSTREAM="auto". A "<" indicates
+# you are behind, ">" indicates you are ahead, and "<>"
+# indicates you have diverged. You can further control
+# behaviour by setting GIT_PS1_SHOWUPSTREAM to a space-separated
+# list of values:
+# verbose show number of commits ahead/behind (+/-) upstream
+# legacy don't use the '--count' option available in recent
+# versions of git-rev-list
+# git always compare HEAD to @{upstream}
+# svn always compare HEAD to your SVN upstream
+# By default, __git_ps1 will compare HEAD to your SVN upstream
+# if it can find one, or @{upstream} otherwise. Once you have
+# set GIT_PS1_SHOWUPSTREAM, you can override it on a
+# per-repository basis by setting the bash.showUpstream config
+# variable.
+#
+#
# To submit patches:
#
# *) Read Documentation/SubmittingPatches
@@ -78,14 +96,133 @@ __gitdir ()
fi
}
+# stores the divergence from upstream in $p
+# used by GIT_PS1_SHOWUPSTREAM
+__git_ps1_show_upstream ()
+{
+ local key value
+ local svn_remote=() svn_url_pattern count n
+ local upstream=git legacy="" verbose=""
+
+ # get some config options from git-config
+ while read key value; do
+ case "$key" in
+ bash.showupstream)
+ GIT_PS1_SHOWUPSTREAM="$value"
+ if [[ -z "${GIT_PS1_SHOWUPSTREAM}" ]]; then
+ p=""
+ return
+ fi
+ ;;
+ svn-remote.*.url)
+ svn_remote[ $((${#svn_remote[@]} + 1)) ]="$value"
+ svn_url_pattern+="\\|$value"
+ upstream=svn+git # default upstream is SVN if available, else git
+ ;;
+ esac
+ done < <(git config -z --get-regexp '^(svn-remote\..*\.url|bash\.showupstream)$' 2>/dev/null | tr '\0\n' '\n ')
+
+ # parse configuration values
+ for option in ${GIT_PS1_SHOWUPSTREAM}; do
+ case "$option" in
+ git|svn) upstream="$option" ;;
+ verbose) verbose=1 ;;
+ legacy) legacy=1 ;;
+ esac
+ done
+
+ # Find our upstream
+ case "$upstream" in
+ git) upstream="@{upstream}" ;;
+ svn*)
+ # get the upstream from the "git-svn-id: ..." in a commit message
+ # (git-svn uses essentially the same procedure internally)
+ local svn_upstream=($(git log --first-parent -1 \
+ --grep="^git-svn-id: \(${svn_url_pattern:2}\)" 2>/dev/null))
+ if [[ 0 -ne ${#svn_upstream[@]} ]]; then
+ svn_upstream=${svn_upstream[ ${#svn_upstream[@]} - 2 ]}
+ svn_upstream=${svn_upstream%@*}
+ for ((n=1; "$n" <= "${#svn_remote[@]}"; ++n)); do
+ svn_upstream=${svn_upstream#${svn_remote[$n]}}
+ done
+
+ if [[ -z "$svn_upstream" ]]; then
+ # default branch name for checkouts with no layout:
+ upstream=${GIT_SVN_ID:-git-svn}
+ else
+ upstream=${svn_upstream#/}
+ fi
+ elif [[ "svn+git" = "$upstream" ]]; then
+ upstream="@{upstream}"
+ fi
+ ;;
+ esac
+
+ # Find how many commits we are ahead/behind our upstream
+ if [[ -z "$legacy" ]]; then
+ count="$(git rev-list --count --left-right \
+ "$upstream"...HEAD 2>/dev/null)"
+ else
+ # produce equivalent output to --count for older versions of git
+ local commits
+ if commits="$(git rev-list --left-right "$upstream"...HEAD 2>/dev/null)"
+ then
+ local commit behind=0 ahead=0
+ for commit in $commits
+ do
+ case "$commit" in
+ "<"*) let ++behind
+ ;;
+ *) let ++ahead
+ ;;
+ esac
+ done
+ count="$behind $ahead"
+ else
+ count=""
+ fi
+ fi
+
+ # calculate the result
+ if [[ -z "$verbose" ]]; then
+ case "$count" in
+ "") # no upstream
+ p="" ;;
+ "0 0") # equal to upstream
+ p="=" ;;
+ "0 "*) # ahead of upstream
+ p=">" ;;
+ *" 0") # behind upstream
+ p="<" ;;
+ *) # diverged from upstream
+ p="<>" ;;
+ esac
+ else
+ case "$count" in
+ "") # no upstream
+ p="" ;;
+ "0 0") # equal to upstream
+ p=" u=" ;;
+ "0 "*) # ahead of upstream
+ p=" u+${count#0 }" ;;
+ *" 0") # behind upstream
+ p=" u-${count% 0}" ;;
+ *) # diverged from upstream
+ p=" u+${count#* }-${count% *}" ;;
+ esac
+ fi
+
+}
+
+
# __git_ps1 accepts 0 or 1 arguments (i.e., format string)
# returns text to add to bash PS1 prompt (includes branch name)
__git_ps1 ()
{
local g="$(__gitdir)"
if [ -n "$g" ]; then
- local r
- local b
+ local r=""
+ local b=""
if [ -f "$g/rebase-merge/interactive" ]; then
r="|REBASE-i"
b="$(cat "$g/rebase-merge/head-name")"
@@ -127,11 +264,12 @@ __git_ps1 ()
}
fi
- local w
- local i
- local s
- local u
- local c
+ 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
@@ -159,10 +297,14 @@ __git_ps1 ()
u="%"
fi
fi
+
+ if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
+ __git_ps1_show_upstream
+ fi
fi
local f="$w$i$s$u"
- printf "${1:- (%s)}" "$c${b##refs/heads/}${f:+ $f}$r"
+ printf "${1:- (%s)}" "$c${b##refs/heads/}${f:+ $f}$r$p"
fi
}
diff --git a/date.c b/date.c
index 68cdcaa3f6..3c981f7eb5 100644
--- a/date.c
+++ b/date.c
@@ -635,7 +635,7 @@ int parse_date_toffset(const char *date, unsigned long *timestamp, int *offset)
/* mktime uses local timezone */
*timestamp = tm_to_time_t(&tm);
if (*offset == -1)
- *offset = (*timestamp - mktime(&tm)) / 60;
+ *offset = ((time_t)*timestamp - mktime(&tm)) / 60;
if (*timestamp == -1)
return -1;
diff --git a/diff-lib.c b/diff-lib.c
index c9f6e05bad..8b8978ae6d 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -70,6 +70,7 @@ static int match_stat_with_submodule(struct diff_options *diffopt,
int changed = ce_match_stat(ce, st, ce_option);
if (S_ISGITLINK(ce->ce_mode)
&& !DIFF_OPT_TST(diffopt, IGNORE_SUBMODULES)
+ && !DIFF_OPT_TST(diffopt, IGNORE_DIRTY_SUBMODULES)
&& (!changed || DIFF_OPT_TST(diffopt, DIRTY_SUBMODULES))) {
*dirty_submodule = is_submodule_modified(ce->name, DIFF_OPT_TST(diffopt, IGNORE_UNTRACKED_IN_SUBMODULES));
}
diff --git a/diff-no-index.c b/diff-no-index.c
index 4cd9dacbe8..43aeeba2e0 100644
--- a/diff-no-index.c
+++ b/diff-no-index.c
@@ -26,7 +26,7 @@ static int read_directory(const char *path, struct string_list *list)
while ((e = readdir(dir)))
if (strcmp(".", e->d_name) && strcmp("..", e->d_name))
- string_list_insert(e->d_name, list);
+ string_list_insert(list, e->d_name);
closedir(dir);
return 0;
diff --git a/diff.c b/diff.c
index 2332fa6798..17873f3d9e 100644
--- a/diff.c
+++ b/diff.c
@@ -2627,8 +2627,7 @@ static void fill_metainfo(struct strbuf *msg,
(!fill_mmfile(&mf, two) && diff_filespec_is_binary(two)))
abbrev = 40;
}
- strbuf_addf(msg, "%s%sindex %s..", set,
- line_prefix,
+ strbuf_addf(msg, "%s%sindex %s..", line_prefix, set,
find_unique_abbrev(one->sha1, abbrev));
strbuf_addstr(msg, find_unique_abbrev(two->sha1, abbrev));
if (one->mode == two->mode)
@@ -3168,7 +3167,9 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
else if (!strcmp(arg, "--no-textconv"))
DIFF_OPT_CLR(options, ALLOW_TEXTCONV);
else if (!strcmp(arg, "--ignore-submodules"))
- DIFF_OPT_SET(options, IGNORE_SUBMODULES);
+ handle_ignore_submodules_arg(options, "all");
+ else if (!prefixcmp(arg, "--ignore-submodules="))
+ handle_ignore_submodules_arg(options, arg + 20);
else if (!strcmp(arg, "--submodule"))
DIFF_OPT_SET(options, SUBMODULE_LOG);
else if (!prefixcmp(arg, "--submodule=")) {
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 6b86abc64b..31e68603f4 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -263,10 +263,10 @@ pick_one_preserving_merges () {
then
if test "$fast_forward" = t
then
- cat "$DOTEST"/current-commit | while read current_commit
+ while read current_commit
do
git rev-parse HEAD > "$REWRITTEN"/$current_commit
- done
+ done <"$DOTEST"/current-commit
rm "$DOTEST"/current-commit ||
die "Cannot write current commit's replacement sha1"
fi
@@ -440,9 +440,9 @@ record_in_rewritten() {
echo "$oldsha1" >> "$REWRITTEN_PENDING"
case "$(peek_next_command)" in
- squash|s|fixup|f)
+ squash|s|fixup|f)
;;
- *)
+ *)
flush_rewritten_pending
;;
esac
@@ -450,7 +450,7 @@ record_in_rewritten() {
do_next () {
rm -f "$MSG" "$AUTHOR_SCRIPT" "$AMEND" || exit
- read command sha1 rest < "$TODO"
+ read -r command sha1 rest < "$TODO"
case "$command" in
'#'*|''|noop)
mark_action_done
@@ -591,7 +591,7 @@ do_rest () {
# skip picking commits whose parents are unchanged
skip_unnecessary_picks () {
fd=3
- while read command sha1 rest
+ while read -r command sha1 rest
do
# fd=3 means we skip the command
case "$fd,$command,$(git rev-parse --verify --quiet $sha1^)" in
@@ -644,13 +644,13 @@ rearrange_squash () {
test -s "$1.sq" || return
used=
- while read pick sha1 message
+ while read -r pick sha1 message
do
case " $used" in
*" $sha1 "*) continue ;;
esac
echo "$pick $sha1 $message"
- while read squash action msg
+ while read -r squash action msg
do
case "$message" in
"$msg"*)
@@ -890,7 +890,8 @@ first and then run 'git rebase --continue' again."
git rev-list $MERGES_OPTION --pretty=oneline --abbrev-commit \
--abbrev=7 --reverse --left-right --topo-order \
$REVISIONS | \
- sed -n "s/^>//p" | while read shortsha1 rest
+ sed -n "s/^>//p" |
+ while read -r shortsha1 rest
do
if test t != "$PRESERVE_MERGES"
then
diff --git a/git-submodule.sh b/git-submodule.sh
index 8c562a72e6..ad2417d1b0 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -234,12 +234,12 @@ cmd_add()
) || die "Unable to checkout submodule '$path'"
fi
- git add "$path" ||
+ git add --force "$path" ||
die "Failed to add submodule '$path'"
git config -f .gitmodules submodule."$path".path "$path" &&
git config -f .gitmodules submodule."$path".url "$repo" &&
- git add .gitmodules ||
+ git add --force .gitmodules ||
die "Failed to register submodule '$path'"
}
@@ -580,7 +580,7 @@ cmd_summary() {
cd_to_toplevel
# Get modified modules cared by user
- modules=$(git $diff_cmd $cached --raw $head -- "$@" |
+ modules=$(git $diff_cmd $cached --ignore-submodules=dirty --raw $head -- "$@" |
sane_egrep '^:([0-7]* )?160000' |
while read mod_src mod_dst sha1_src sha1_dst status name
do
@@ -594,7 +594,7 @@ cmd_summary() {
test -z "$modules" && return
- git $diff_cmd $cached --raw $head -- $modules |
+ git $diff_cmd $cached --ignore-submodules=dirty --raw $head -- $modules |
sane_egrep '^:([0-7]* )?160000' |
cut -c2- |
while read mod_src mod_dst sha1_src sha1_dst status name
@@ -760,7 +760,7 @@ cmd_status()
continue;
fi
set_name_rev "$path" "$sha1"
- if git diff-files --quiet -- "$path"
+ if git diff-files --ignore-submodules=dirty --quiet -- "$path"
then
say " $sha1 $displaypath$revname"
else
diff --git a/git.c b/git.c
index 99517dd83a..17538117a5 100644
--- a/git.c
+++ b/git.c
@@ -330,7 +330,7 @@ static void handle_internal_command(int argc, const char **argv)
{ "fsck-objects", cmd_fsck, RUN_SETUP },
{ "gc", cmd_gc, RUN_SETUP },
{ "get-tar-commit-id", cmd_get_tar_commit_id },
- { "grep", cmd_grep, USE_PAGER },
+ { "grep", cmd_grep },
{ "hash-object", cmd_hash_object },
{ "help", cmd_help },
{ "index-pack", cmd_index_pack },
diff --git a/git.spec.in b/git.spec.in
index 9533147ff2..91c8462b7d 100644
--- a/git.spec.in
+++ b/git.spec.in
@@ -35,6 +35,7 @@ Requires: git-cvs = %{version}-%{release}
Requires: git-arch = %{version}-%{release}
Requires: git-email = %{version}-%{release}
Requires: gitk = %{version}-%{release}
+Requires: gitweb = %{version}-%{release}
Requires: git-gui = %{version}-%{release}
Obsoletes: git <= 1.5.4.2
@@ -87,6 +88,13 @@ Requires: git = %{version}-%{release}, tk >= 8.4
%description -n gitk
Git revision tree visualiser ('gitk')
+%package -n gitweb
+Summary: Git web interface
+Group: Development/Tools
+Requires: git = %{version}-%{release}
+%description -n gitweb
+Browsing git repository on the web
+
%package -n perl-Git
Summary: Perl interface to Git
Group: Development/Libraries
@@ -189,6 +197,10 @@ rm -rf $RPM_BUILD_ROOT
%{!?_without_docs: %{_mandir}/man1/*gitk*.1*}
%{!?_without_docs: %doc Documentation/*gitk*.html }
+%files -n gitweb
+%defattr(-,root,root)
+%{_datadir}/gitweb
+
%files -n perl-Git -f perl-files
%defattr(-,root,root)
@@ -196,6 +208,9 @@ rm -rf $RPM_BUILD_ROOT
# No files for you!
%changelog
+* Wed Jun 30 2010 Junio C Hamano <gitster@pobox.com>
+- Add 'gitweb' subpackage.
+
* Fri Mar 26 2010 Ian Ward Comfort <icomfort@stanford.edu>
- Ship bash completion support from contrib/ in the core package.
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 9446376535..cedc357313 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -1027,18 +1027,18 @@ sub dispatch {
$actions{$action}->();
}
-sub run_request {
+sub reset_timer {
our $t0 = [Time::HiRes::gettimeofday()]
if defined $t0;
+ our $number_of_git_cmds = 0;
+}
+
+sub run_request {
+ reset_timer();
evaluate_uri();
- evaluate_gitweb_config();
- evaluate_git_version();
check_loadavg();
- # $projectroot and $projects_list might be set in gitweb config file
- $projects_list ||= $projectroot;
-
evaluate_query_params();
evaluate_path_info();
evaluate_and_validate_params();
@@ -1086,6 +1086,11 @@ sub evaluate_argv {
sub run {
evaluate_argv();
+ evaluate_gitweb_config();
+ evaluate_git_version();
+
+ # $projectroot and $projects_list might be set in gitweb config file
+ $projects_list ||= $projectroot;
$pre_listen_hook->()
if $pre_listen_hook;
@@ -1322,8 +1327,7 @@ sub esc_param {
sub esc_url {
my $str = shift;
return undef unless defined $str;
- $str =~ s/([^A-Za-z0-9\-_.~();\/;?:@&=])/sprintf("%%%02X", ord($1))/eg;
- $str =~ s/\+/%2B/g;
+ $str =~ s/([^A-Za-z0-9\-_.~();\/;?:@&= ]+)/CGI::escape($1)/eg;
$str =~ s/ /\+/g;
return $str;
}
diff --git a/http-backend.c b/http-backend.c
index 44ce6bb32b..14c90c2e84 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -37,9 +37,9 @@ static struct string_list *get_parameters(void)
char *value = url_decode_parameter_value(&query);
struct string_list_item *i;
- i = string_list_lookup(name, query_params);
+ i = string_list_lookup(query_params, name);
if (!i)
- i = string_list_insert(name, query_params);
+ i = string_list_insert(query_params, name);
else
free(i->util);
i->util = value;
@@ -51,7 +51,7 @@ static struct string_list *get_parameters(void)
static const char *get_parameter(const char *name)
{
struct string_list_item *i;
- i = string_list_lookup(name, get_parameters());
+ i = string_list_lookup(get_parameters(), name);
return i ? i->util : NULL;
}
diff --git a/log-tree.c b/log-tree.c
index 2e2be7c40f..b46ed3baef 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -7,32 +7,113 @@
#include "reflog-walk.h"
#include "refs.h"
#include "string-list.h"
+#include "color.h"
struct decoration name_decoration = { "object names" };
-static void add_name_decoration(const char *prefix, const char *name, struct object *obj)
+enum decoration_type {
+ DECORATION_NONE = 0,
+ DECORATION_REF_LOCAL,
+ DECORATION_REF_REMOTE,
+ DECORATION_REF_TAG,
+ DECORATION_REF_STASH,
+ DECORATION_REF_HEAD,
+};
+
+static char decoration_colors[][COLOR_MAXLEN] = {
+ GIT_COLOR_RESET,
+ GIT_COLOR_BOLD_GREEN, /* REF_LOCAL */
+ GIT_COLOR_BOLD_RED, /* REF_REMOTE */
+ GIT_COLOR_BOLD_YELLOW, /* REF_TAG */
+ GIT_COLOR_BOLD_MAGENTA, /* REF_STASH */
+ GIT_COLOR_BOLD_CYAN, /* REF_HEAD */
+};
+
+static const char *decorate_get_color(int decorate_use_color, enum decoration_type ix)
+{
+ if (decorate_use_color)
+ return decoration_colors[ix];
+ return "";
+}
+
+static int parse_decorate_color_slot(const char *slot)
+{
+ /*
+ * We're comparing with 'ignore-case' on
+ * (because config.c sets them all tolower),
+ * but let's match the letters in the literal
+ * string values here with how they are
+ * documented in Documentation/config.txt, for
+ * consistency.
+ *
+ * We love being consistent, don't we?
+ */
+ if (!strcasecmp(slot, "branch"))
+ return DECORATION_REF_LOCAL;
+ if (!strcasecmp(slot, "remoteBranch"))
+ return DECORATION_REF_REMOTE;
+ if (!strcasecmp(slot, "tag"))
+ return DECORATION_REF_TAG;
+ if (!strcasecmp(slot, "stash"))
+ return DECORATION_REF_STASH;
+ if (!strcasecmp(slot, "HEAD"))
+ return DECORATION_REF_HEAD;
+ return -1;
+}
+
+int parse_decorate_color_config(const char *var, const int ofs, const char *value)
+{
+ int slot = parse_decorate_color_slot(var + ofs);
+ if (slot < 0)
+ return 0;
+ if (!value)
+ return config_error_nonbool(var);
+ color_parse(value, var, decoration_colors[slot]);
+ return 0;
+}
+
+/*
+ * log-tree.c uses DIFF_OPT_TST for determining whether to use color
+ * for showing the commit sha1, use the same check for --decorate
+ */
+#define decorate_get_color_opt(o, ix) \
+ decorate_get_color(DIFF_OPT_TST((o), COLOR_DIFF), ix)
+
+static void add_name_decoration(enum decoration_type type, const char *name, struct object *obj)
{
- int plen = strlen(prefix);
int nlen = strlen(name);
- struct name_decoration *res = xmalloc(sizeof(struct name_decoration) + plen + nlen);
- memcpy(res->name, prefix, plen);
- memcpy(res->name + plen, name, nlen + 1);
+ struct name_decoration *res = xmalloc(sizeof(struct name_decoration) + nlen);
+ memcpy(res->name, name, nlen + 1);
+ res->type = type;
res->next = add_decoration(&name_decoration, obj, res);
}
static int add_ref_decoration(const char *refname, const unsigned char *sha1, int flags, void *cb_data)
{
struct object *obj = parse_object(sha1);
+ enum decoration_type type = DECORATION_NONE;
if (!obj)
return 0;
+
+ if (!prefixcmp(refname, "refs/heads"))
+ type = DECORATION_REF_LOCAL;
+ else if (!prefixcmp(refname, "refs/remotes"))
+ type = DECORATION_REF_REMOTE;
+ else if (!prefixcmp(refname, "refs/tags"))
+ type = DECORATION_REF_TAG;
+ else if (!prefixcmp(refname, "refs/stash"))
+ type = DECORATION_REF_STASH;
+ else if (!prefixcmp(refname, "HEAD"))
+ type = DECORATION_REF_HEAD;
+
if (!cb_data || *(int *)cb_data == DECORATE_SHORT_REFS)
refname = prettify_refname(refname);
- add_name_decoration("", refname, obj);
+ add_name_decoration(type, refname, obj);
while (obj->type == OBJ_TAG) {
obj = ((struct tag *)obj)->tagged;
if (!obj)
break;
- add_name_decoration("tag: ", refname, obj);
+ add_name_decoration(DECORATION_REF_TAG, refname, obj);
}
return 0;
}
@@ -60,6 +141,10 @@ void show_decorations(struct rev_info *opt, struct commit *commit)
{
const char *prefix;
struct name_decoration *decoration;
+ const char *color_commit =
+ diff_get_color_opt(&opt->diffopt, DIFF_COMMIT);
+ const char *color_reset =
+ decorate_get_color_opt(&opt->diffopt, DECORATION_NONE);
if (opt->show_source && commit->util)
printf("\t%s", (char *) commit->util);
@@ -70,7 +155,14 @@ void show_decorations(struct rev_info *opt, struct commit *commit)
return;
prefix = " (";
while (decoration) {
- printf("%s%s", prefix, decoration->name);
+ printf("%s", prefix);
+ fputs(decorate_get_color_opt(&opt->diffopt, decoration->type),
+ stdout);
+ if (decoration->type == DECORATION_REF_TAG)
+ fputs("tag: ", stdout);
+ printf("%s", decoration->name);
+ fputs(color_reset, stdout);
+ fputs(color_commit, stdout);
prefix = ", ";
decoration = decoration->next;
}
diff --git a/log-tree.h b/log-tree.h
index 3f7b40027b..5c4cf7cac3 100644
--- a/log-tree.h
+++ b/log-tree.h
@@ -7,6 +7,7 @@ struct log_info {
struct commit *commit, *parent;
};
+int parse_decorate_color_config(const char *var, const int ofs, const char *value);
void init_log_tree_opt(struct rev_info *);
int log_tree_diff_flush(struct rev_info *);
int log_tree_commit(struct rev_info *, struct commit *);
diff --git a/mailmap.c b/mailmap.c
index b68c1fec9c..f80b701292 100644
--- a/mailmap.c
+++ b/mailmap.c
@@ -69,7 +69,7 @@ static void add_mapping(struct string_list *map,
index = -1 - index;
} else {
/* create mailmap entry */
- struct string_list_item *item = string_list_insert_at_index(index, old_email, map);
+ struct string_list_item *item = string_list_insert_at_index(map, index, old_email);
item->util = xmalloc(sizeof(struct mailmap_entry));
memset(item->util, 0, sizeof(struct mailmap_entry));
((struct mailmap_entry *)item->util)->namemap.strdup_strings = 1;
@@ -92,7 +92,7 @@ static void add_mapping(struct string_list *map,
mi->name = xstrdup(new_name);
if (new_email)
mi->email = xstrdup(new_email);
- string_list_insert(old_name, &me->namemap)->util = mi;
+ string_list_insert(&me->namemap, old_name)->util = mi;
}
debug_mm("mailmap: '%s' <%s> -> '%s' <%s>\n",
@@ -214,13 +214,13 @@ int map_user(struct string_list *map,
mailbuf[i] = 0;
debug_mm("map_user: map '%s' <%s>\n", name, mailbuf);
- item = string_list_lookup(mailbuf, map);
+ item = string_list_lookup(map, mailbuf);
if (item != NULL) {
me = (struct mailmap_entry *)item->util;
if (me->namemap.nr) {
/* The item has multiple items, so we'll look up on name too */
/* If the name is not found, we choose the simple entry */
- struct string_list_item *subitem = string_list_lookup(name, &me->namemap);
+ struct string_list_item *subitem = string_list_lookup(&me->namemap, name);
if (subitem)
item = subitem;
}
diff --git a/merge-recursive.c b/merge-recursive.c
index 206c103635..fb6aa4a551 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -238,9 +238,9 @@ static int save_files_dirs(const unsigned char *sha1,
newpath[baselen + len] = '\0';
if (S_ISDIR(mode))
- string_list_insert(newpath, &o->current_directory_set);
+ string_list_insert(&o->current_directory_set, newpath);
else
- string_list_insert(newpath, &o->current_file_set);
+ string_list_insert(&o->current_file_set, newpath);
free(newpath);
return (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0);
@@ -271,7 +271,7 @@ static struct stage_data *insert_stage_data(const char *path,
e->stages[2].sha, &e->stages[2].mode);
get_tree_entry(b->object.sha1, path,
e->stages[3].sha, &e->stages[3].mode);
- item = string_list_insert(path, entries);
+ item = string_list_insert(entries, path);
item->util = e;
return e;
}
@@ -294,9 +294,9 @@ static struct string_list *get_unmerged(void)
if (!ce_stage(ce))
continue;
- item = string_list_lookup(ce->name, unmerged);
+ item = string_list_lookup(unmerged, ce->name);
if (!item) {
- item = string_list_insert(ce->name, unmerged);
+ item = string_list_insert(unmerged, ce->name);
item->util = xcalloc(1, sizeof(struct stage_data));
}
e = item->util;
@@ -356,20 +356,20 @@ static struct string_list *get_renames(struct merge_options *o,
re = xmalloc(sizeof(*re));
re->processed = 0;
re->pair = pair;
- item = string_list_lookup(re->pair->one->path, entries);
+ item = string_list_lookup(entries, re->pair->one->path);
if (!item)
re->src_entry = insert_stage_data(re->pair->one->path,
o_tree, a_tree, b_tree, entries);
else
re->src_entry = item->util;
- item = string_list_lookup(re->pair->two->path, entries);
+ item = string_list_lookup(entries, re->pair->two->path);
if (!item)
re->dst_entry = insert_stage_data(re->pair->two->path,
o_tree, a_tree, b_tree, entries);
else
re->dst_entry = item->util;
- item = string_list_insert(pair->one->path, renames);
+ item = string_list_insert(renames, pair->one->path);
item->util = re;
}
opts.output_format = DIFF_FORMAT_NO_OUTPUT;
@@ -432,7 +432,7 @@ static char *unique_path(struct merge_options *o, const char *path, const char *
lstat(newpath, &st) == 0)
sprintf(p, "_%d", suffix++);
- string_list_insert(newpath, &o->current_file_set);
+ string_list_insert(&o->current_file_set, newpath);
return newpath;
}
@@ -811,12 +811,12 @@ static int process_renames(struct merge_options *o,
for (i = 0; i < a_renames->nr; i++) {
sre = a_renames->items[i].util;
- string_list_insert(sre->pair->two->path, &a_by_dst)->util
+ string_list_insert(&a_by_dst, sre->pair->two->path)->util
= sre->dst_entry;
}
for (i = 0; i < b_renames->nr; i++) {
sre = b_renames->items[i].util;
- string_list_insert(sre->pair->two->path, &b_by_dst)->util
+ string_list_insert(&b_by_dst, sre->pair->two->path)->util
= sre->dst_entry;
}
@@ -988,7 +988,7 @@ static int process_renames(struct merge_options *o,
output(o, 1, "Adding as %s instead", new_path);
update_file(o, 0, dst_other.sha1, dst_other.mode, new_path);
}
- } else if ((item = string_list_lookup(ren1_dst, renames2Dst))) {
+ } else if ((item = string_list_lookup(renames2Dst, ren1_dst))) {
ren2 = item->util;
clean_merge = 0;
ren2->processed = 1;
@@ -1214,7 +1214,7 @@ int merge_trees(struct merge_options *o,
}
if (sha_eq(common->object.sha1, merge->object.sha1)) {
- output(o, 0, "Already uptodate!");
+ output(o, 0, "Already up-to-date!");
*result = head;
return 1;
}
diff --git a/notes.c b/notes.c
index 6ee04e79e9..1978244398 100644
--- a/notes.c
+++ b/notes.c
@@ -716,7 +716,7 @@ static int write_each_non_note_until(const char *note_path,
struct write_each_note_data *d)
{
struct non_note *n = d->next_non_note;
- int cmp, ret;
+ int cmp = 0, ret;
while (n && (!note_path || (cmp = strcmp(n->path, note_path)) <= 0)) {
if (note_path && cmp == 0)
; /* do nothing, prefer note to non-note */
@@ -838,7 +838,7 @@ static int string_list_add_one_ref(const char *path, const unsigned char *sha1,
{
struct string_list *refs = cb;
if (!unsorted_string_list_has_string(refs, path))
- string_list_append(path, refs);
+ string_list_append(refs, path);
return 0;
}
@@ -851,7 +851,7 @@ void string_list_add_refs_by_glob(struct string_list *list, const char *glob)
if (get_sha1(glob, sha1))
warning("notes ref %s is invalid", glob);
if (!unsorted_string_list_has_string(list, glob))
- string_list_append(glob, list);
+ string_list_append(list, glob);
}
}
@@ -969,7 +969,7 @@ struct notes_tree **load_notes_trees(struct string_list *refs)
trees = xmalloc((refs->nr+1) * sizeof(struct notes_tree *));
cb_data.counter = 0;
cb_data.trees = trees;
- for_each_string_list(load_one_display_note_ref, refs, &cb_data);
+ for_each_string_list(refs, load_one_display_note_ref, &cb_data);
trees[cb_data.counter] = NULL;
return trees;
}
@@ -983,7 +983,7 @@ void init_display_notes(struct display_notes_opt *opt)
assert(!display_notes_trees);
if (!opt || !opt->suppress_default_notes) {
- string_list_append(default_notes_ref(), &display_notes_refs);
+ string_list_append(&display_notes_refs, default_notes_ref());
display_ref_env = getenv(GIT_NOTES_DISPLAY_REF_ENVIRONMENT);
if (display_ref_env) {
string_list_add_refs_from_colon_sep(&display_notes_refs,
@@ -996,8 +996,8 @@ void init_display_notes(struct display_notes_opt *opt)
git_config(notes_display_config, &load_config_refs);
if (opt && opt->extra_notes_refs)
- for_each_string_list(string_list_add_refs_from_list,
- opt->extra_notes_refs,
+ for_each_string_list(opt->extra_notes_refs,
+ string_list_add_refs_from_list,
&display_notes_refs);
display_notes_trees = load_notes_trees(&display_notes_refs);
diff --git a/reflog-walk.c b/reflog-walk.c
index caba4f743f..4879615cad 100644
--- a/reflog-walk.c
+++ b/reflog-walk.c
@@ -162,7 +162,7 @@ int add_reflog_for_walk(struct reflog_walk_info *info,
} else
recno = 0;
- item = string_list_lookup(branch, &info->complete_reflogs);
+ item = string_list_lookup(&info->complete_reflogs, branch);
if (item)
reflogs = item->util;
else {
@@ -190,7 +190,7 @@ int add_reflog_for_walk(struct reflog_walk_info *info,
}
if (!reflogs || reflogs->nr == 0)
return -1;
- string_list_insert(branch, &info->complete_reflogs)->util
+ string_list_insert(&info->complete_reflogs, branch)->util
= reflogs;
}
diff --git a/refs.c b/refs.c
index 6f486ae62d..b5400674d7 100644
--- a/refs.c
+++ b/refs.c
@@ -1090,6 +1090,15 @@ int delete_ref(const char *refname, const unsigned char *sha1, int delopt)
return ret;
}
+/*
+ * People using contrib's git-new-workdir have .git/logs/refs ->
+ * /some/other/path/.git/logs/refs, and that may live on another device.
+ *
+ * IOW, to avoid cross device rename errors, the temporary renamed log must
+ * live into logs/refs.
+ */
+#define TMP_RENAMED_LOG "logs/refs/.tmp-renamed-log"
+
int rename_ref(const char *oldref, const char *newref, const char *logmsg)
{
static const char renamed_ref[] = "RENAMED-REF";
@@ -1123,8 +1132,8 @@ int rename_ref(const char *oldref, const char *newref, const char *logmsg)
if (write_ref_sha1(lock, orig_sha1, logmsg))
return error("unable to save current sha1 in %s", renamed_ref);
- if (log && rename(git_path("logs/%s", oldref), git_path("tmp-renamed-log")))
- return error("unable to move logfile logs/%s to tmp-renamed-log: %s",
+ if (log && rename(git_path("logs/%s", oldref), git_path(TMP_RENAMED_LOG)))
+ return error("unable to move logfile logs/%s to "TMP_RENAMED_LOG": %s",
oldref, strerror(errno));
if (delete_ref(oldref, orig_sha1, REF_NODEREF)) {
@@ -1150,7 +1159,7 @@ int rename_ref(const char *oldref, const char *newref, const char *logmsg)
}
retry:
- if (log && rename(git_path("tmp-renamed-log"), git_path("logs/%s", newref))) {
+ if (log && rename(git_path(TMP_RENAMED_LOG), git_path("logs/%s", newref))) {
if (errno==EISDIR || errno==ENOTDIR) {
/*
* rename(a, b) when b is an existing
@@ -1163,7 +1172,7 @@ int rename_ref(const char *oldref, const char *newref, const char *logmsg)
}
goto retry;
} else {
- error("unable to move logfile tmp-renamed-log to logs/%s: %s",
+ error("unable to move logfile "TMP_RENAMED_LOG" to logs/%s: %s",
newref, strerror(errno));
goto rollback;
}
@@ -1203,8 +1212,8 @@ int rename_ref(const char *oldref, const char *newref, const char *logmsg)
error("unable to restore logfile %s from %s: %s",
oldref, newref, strerror(errno));
if (!logmoved && log &&
- rename(git_path("tmp-renamed-log"), git_path("logs/%s", oldref)))
- error("unable to restore logfile %s from tmp-renamed-log: %s",
+ rename(git_path(TMP_RENAMED_LOG), git_path("logs/%s", oldref)))
+ error("unable to restore logfile %s from "TMP_RENAMED_LOG": %s",
oldref, strerror(errno));
return 1;
diff --git a/remote.c b/remote.c
index e51cd22d6b..afbba47460 100644
--- a/remote.c
+++ b/remote.c
@@ -762,7 +762,7 @@ void ref_remove_duplicates(struct ref *ref_map)
if (!ref_map->peer_ref)
continue;
- item = string_list_lookup(ref_map->peer_ref->name, &refs);
+ item = string_list_lookup(&refs, ref_map->peer_ref->name);
if (item) {
if (strcmp(((struct ref *)item->util)->name,
ref_map->name))
@@ -777,7 +777,7 @@ void ref_remove_duplicates(struct ref *ref_map)
continue;
}
- item = string_list_insert(ref_map->peer_ref->name, &refs);
+ item = string_list_insert(&refs, ref_map->peer_ref->name);
item->util = ref_map;
}
string_list_clear(&refs, 0);
@@ -1710,7 +1710,7 @@ struct ref *get_stale_heads(struct remote *remote, struct ref *fetch_map)
info.ref_names = &ref_names;
info.stale_refs_tail = &stale_refs;
for (ref = fetch_map; ref; ref = ref->next)
- string_list_append(ref->name, &ref_names);
+ string_list_append(&ref_names, ref->name);
sort_string_list(&ref_names);
for_each_ref(get_stale_heads_cb, &info);
string_list_clear(&ref_names, 0);
diff --git a/rerere.c b/rerere.c
index 2197890982..d03a69634b 100644
--- a/rerere.c
+++ b/rerere.c
@@ -46,7 +46,7 @@ static void read_rr(struct string_list *rr)
; /* do nothing */
if (i == sizeof(buf))
die("filename too long");
- string_list_insert(buf, rr)->util = name;
+ string_list_insert(rr, buf)->util = name;
}
fclose(in);
}
@@ -354,7 +354,7 @@ static int find_conflict(struct string_list *conflict)
ce_same_name(e2, e3) &&
S_ISREG(e2->ce_mode) &&
S_ISREG(e3->ce_mode)) {
- string_list_insert((const char *)e2->name, conflict);
+ string_list_insert(conflict, (const char *)e2->name);
i++; /* skip over both #2 and #3 */
}
}
@@ -449,7 +449,7 @@ static int do_plain_rerere(struct string_list *rr, int fd)
if (ret < 1)
continue;
hex = xstrdup(sha1_to_hex(sha1));
- string_list_insert(path, rr)->util = hex;
+ string_list_insert(rr, path)->util = hex;
if (mkdir(git_path("rr-cache/%s", hex), 0755))
continue;
handle_file(path, NULL, rerere_path(hex, "preimage"));
@@ -471,7 +471,7 @@ static int do_plain_rerere(struct string_list *rr, int fd)
if (has_rerere_resolution(name)) {
if (!merge(name, path)) {
if (rerere_autoupdate)
- string_list_insert(path, &update);
+ string_list_insert(&update, path);
fprintf(stderr,
"%s '%s' using previous resolution.\n",
rerere_autoupdate
@@ -577,7 +577,7 @@ static int rerere_forget_one_path(const char *path, struct string_list *rr)
fprintf(stderr, "Updated preimage for '%s'\n", path);
- string_list_insert(path, rr)->util = hex;
+ string_list_insert(rr, path)->util = hex;
fprintf(stderr, "Forgot resolution for %s\n", path);
return 0;
}
diff --git a/resolve-undo.c b/resolve-undo.c
index 0f50ee0484..174ebec9e5 100644
--- a/resolve-undo.c
+++ b/resolve-undo.c
@@ -20,7 +20,7 @@ void record_resolve_undo(struct index_state *istate, struct cache_entry *ce)
istate->resolve_undo = resolve_undo;
}
resolve_undo = istate->resolve_undo;
- lost = string_list_insert(ce->name, resolve_undo);
+ lost = string_list_insert(resolve_undo, ce->name);
if (!lost->util)
lost->util = xcalloc(1, sizeof(*ui));
ui = lost->util;
@@ -50,7 +50,7 @@ static int write_one(struct string_list_item *item, void *cbdata)
void resolve_undo_write(struct strbuf *sb, struct string_list *resolve_undo)
{
- for_each_string_list(write_one, resolve_undo, sb);
+ for_each_string_list(resolve_undo, write_one, sb);
}
struct string_list *resolve_undo_read(const char *data, unsigned long size)
@@ -70,7 +70,7 @@ struct string_list *resolve_undo_read(const char *data, unsigned long size)
len = strlen(data) + 1;
if (size <= len)
goto error;
- lost = string_list_insert(data, resolve_undo);
+ lost = string_list_insert(resolve_undo, data);
if (!lost->util)
lost->util = xcalloc(1, sizeof(*ui));
ui = lost->util;
@@ -135,7 +135,7 @@ int unmerge_index_entry_at(struct index_state *istate, int pos)
pos++;
return pos - 1; /* return the last entry processed */
}
- item = string_list_lookup(ce->name, istate->resolve_undo);
+ item = string_list_lookup(istate->resolve_undo, ce->name);
if (!item)
return pos;
ru = item->util;
diff --git a/revision.c b/revision.c
index 540358184d..7e82efd932 100644
--- a/revision.c
+++ b/revision.c
@@ -1253,6 +1253,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
revs->boundary = 1;
} else if (!strcmp(arg, "--left-right")) {
revs->left_right = 1;
+ } else if (!strcmp(arg, "--count")) {
+ revs->count = 1;
} else if (!strcmp(arg, "--cherry-pick")) {
revs->cherry_pick = 1;
revs->limited = 1;
@@ -1312,8 +1314,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
else
strbuf_addstr(&buf, "refs/notes/");
strbuf_addstr(&buf, arg+13);
- string_list_append(strbuf_detach(&buf, NULL),
- revs->notes_opt.extra_notes_refs);
+ string_list_append(revs->notes_opt.extra_notes_refs,
+ strbuf_detach(&buf, NULL));
} else if (!strcmp(arg, "--no-notes")) {
revs->show_notes = 0;
revs->show_notes_given = 1;
diff --git a/revision.h b/revision.h
index 855464f144..36fdf22b29 100644
--- a/revision.h
+++ b/revision.h
@@ -57,6 +57,7 @@ struct rev_info {
limited:1,
unpacked:1,
boundary:2,
+ count:1,
left_right:1,
rewrite_parents:1,
print_parents:1,
@@ -132,6 +133,10 @@ struct rev_info {
/* notes-specific options: which refs to show */
struct display_notes_opt notes_opt;
+
+ /* commit counts */
+ int count_left;
+ int count_right;
};
#define REV_TREE_SAME 0
diff --git a/setup.c b/setup.c
index 7e0460205d..87c21f02e0 100644
--- a/setup.c
+++ b/setup.c
@@ -323,7 +323,8 @@ const char *setup_git_directory_gently(int *nongit_ok)
const char *gitdirenv;
const char *gitfile_dir;
int len, offset, ceil_offset, root_len;
- int current_device = 0, one_filesystem = 1;
+ dev_t current_device = 0;
+ int one_filesystem = 1;
struct stat buf;
/*
diff --git a/string-list.c b/string-list.c
index c9ad7fcd49..9b023a2584 100644
--- a/string-list.c
+++ b/string-list.c
@@ -51,13 +51,13 @@ static int add_entry(int insert_at, struct string_list *list, const char *string
return index;
}
-struct string_list_item *string_list_insert(const char *string, struct string_list *list)
+struct string_list_item *string_list_insert(struct string_list *list, const char *string)
{
- return string_list_insert_at_index(-1, string, list);
+ return string_list_insert_at_index(list, -1, string);
}
-struct string_list_item *string_list_insert_at_index(int insert_at,
- const char *string, struct string_list *list)
+struct string_list_item *string_list_insert_at_index(struct string_list *list,
+ int insert_at, const char *string)
{
int index = add_entry(insert_at, list, string);
@@ -84,7 +84,7 @@ int string_list_find_insert_index(const struct string_list *list, const char *st
return index;
}
-struct string_list_item *string_list_lookup(const char *string, struct string_list *list)
+struct string_list_item *string_list_lookup(struct string_list *list, const char *string)
{
int exact_match, i = get_entry_index(list, string, &exact_match);
if (!exact_match)
@@ -92,8 +92,8 @@ struct string_list_item *string_list_lookup(const char *string, struct string_li
return list->items + i;
}
-int for_each_string_list(string_list_each_func_t fn,
- struct string_list *list, void *cb_data)
+int for_each_string_list(struct string_list *list,
+ string_list_each_func_t fn, void *cb_data)
{
int i, ret = 0;
for (i = 0; i < list->nr; i++)
@@ -139,7 +139,7 @@ void string_list_clear_func(struct string_list *list, string_list_clear_func_t c
}
-void print_string_list(const char *text, const struct string_list *p)
+void print_string_list(const struct string_list *p, const char *text)
{
int i;
if ( text )
@@ -148,7 +148,7 @@ void print_string_list(const char *text, const struct string_list *p)
printf("%s:%p\n", p->items[i].string, p->items[i].util);
}
-struct string_list_item *string_list_append(const char *string, struct string_list *list)
+struct string_list_item *string_list_append(struct string_list *list, const char *string)
{
ALLOC_GROW(list->items, list->nr + 1, list->alloc);
list->items[list->nr].string =
diff --git a/string-list.h b/string-list.h
index 63b69c8d75..680d600d16 100644
--- a/string-list.h
+++ b/string-list.h
@@ -12,7 +12,7 @@ struct string_list
unsigned int strdup_strings:1;
};
-void print_string_list(const char *text, const struct string_list *p);
+void print_string_list(const struct string_list *p, const char *text);
void string_list_clear(struct string_list *list, int free_util);
/* Use this function to call a custom clear function on each util pointer */
@@ -22,20 +22,20 @@ void string_list_clear_func(struct string_list *list, string_list_clear_func_t c
/* Use this function to iterate over each item */
typedef int (*string_list_each_func_t)(struct string_list_item *, void *);
-int for_each_string_list(string_list_each_func_t,
- struct string_list *list, void *cb_data);
+int for_each_string_list(struct string_list *list,
+ string_list_each_func_t, void *cb_data);
/* Use these functions only on sorted lists: */
int string_list_has_string(const struct string_list *list, const char *string);
int string_list_find_insert_index(const struct string_list *list, const char *string,
int negative_existing_index);
-struct string_list_item *string_list_insert(const char *string, struct string_list *list);
-struct string_list_item *string_list_insert_at_index(int insert_at,
- const char *string, struct string_list *list);
-struct string_list_item *string_list_lookup(const char *string, struct string_list *list);
+struct string_list_item *string_list_insert(struct string_list *list, const char *string);
+struct string_list_item *string_list_insert_at_index(struct string_list *list,
+ int insert_at, const char *string);
+struct string_list_item *string_list_lookup(struct string_list *list, const char *string);
/* Use these functions only on unsorted lists: */
-struct string_list_item *string_list_append(const char *string, struct string_list *list);
+struct string_list_item *string_list_append(struct string_list *list, const char *string);
void sort_string_list(struct string_list *list);
int unsorted_string_list_has_string(struct string_list *list, const char *string);
struct string_list_item *unsorted_string_list_lookup(struct string_list *list,
diff --git a/submodule.c b/submodule.c
index 676d48fb33..61cb6e21dd 100644
--- a/submodule.c
+++ b/submodule.c
@@ -46,6 +46,19 @@ done:
return ret;
}
+void handle_ignore_submodules_arg(struct diff_options *diffopt,
+ const char *arg)
+{
+ if (!strcmp(arg, "all"))
+ DIFF_OPT_SET(diffopt, IGNORE_SUBMODULES);
+ else if (!strcmp(arg, "untracked"))
+ DIFF_OPT_SET(diffopt, IGNORE_UNTRACKED_IN_SUBMODULES);
+ else if (!strcmp(arg, "dirty"))
+ DIFF_OPT_SET(diffopt, IGNORE_DIRTY_SUBMODULES);
+ else
+ die("bad --ignore-submodules argument: %s", arg);
+}
+
void show_submodule_summary(FILE *f, const char *path,
unsigned char one[20], unsigned char two[20],
unsigned dirty_submodule,
diff --git a/submodule.h b/submodule.h
index dbda270873..6fd3bb4070 100644
--- a/submodule.h
+++ b/submodule.h
@@ -1,6 +1,9 @@
#ifndef SUBMODULE_H
#define SUBMODULE_H
+struct diff_options;
+
+void handle_ignore_submodules_arg(struct diff_options *diffopt, const char *);
void show_submodule_summary(FILE *f, const char *path,
unsigned char one[20], unsigned char two[20],
unsigned dirty_submodule,
diff --git a/t/README b/t/README
index 0e4e8d8862..b906ceb476 100644
--- a/t/README
+++ b/t/README
@@ -18,25 +18,48 @@ The easiest way to run tests is to say "make". This runs all
the tests.
*** t0000-basic.sh ***
- * ok 1: .git/objects should be empty after git-init in an empty repo.
- * ok 2: .git/objects should have 256 subdirectories.
- * ok 3: git-update-index without --add should fail adding.
+ ok 1 - .git/objects should be empty after git init in an empty repo.
+ ok 2 - .git/objects should have 3 subdirectories.
+ ok 3 - success is reported like this
...
- * ok 23: no diff after checkout and git-update-index --refresh.
- * passed all 23 test(s)
- *** t0100-environment-names.sh ***
- * ok 1: using old names should issue warnings.
- * ok 2: using old names but having new names should not issue warnings.
- ...
-
-Or you can run each test individually from command line, like
-this:
-
- $ sh ./t3001-ls-files-killed.sh
- * ok 1: git-update-index --add to add various paths.
- * ok 2: git-ls-files -k to show killed files.
- * ok 3: validate git-ls-files -k output.
- * passed all 3 test(s)
+ ok 43 - very long name in the index handled sanely
+ # fixed 1 known breakage(s)
+ # still have 1 known breakage(s)
+ # passed all remaining 42 test(s)
+ 1..43
+ *** t0001-init.sh ***
+ ok 1 - plain
+ ok 2 - plain with GIT_WORK_TREE
+ ok 3 - plain bare
+
+Since the tests all output TAP (see http://testanything.org) they can
+be run with any TAP harness. Here's an example of parallel testing
+powered by a recent version of prove(1):
+
+ $ prove --timer --jobs 15 ./t[0-9]*.sh
+ [19:17:33] ./t0005-signals.sh ................................... ok 36 ms
+ [19:17:33] ./t0022-crlf-rename.sh ............................... ok 69 ms
+ [19:17:33] ./t0024-crlf-archive.sh .............................. ok 154 ms
+ [19:17:33] ./t0004-unwritable.sh ................................ ok 289 ms
+ [19:17:33] ./t0002-gitfile.sh ................................... ok 480 ms
+ ===( 102;0 25/? 6/? 5/? 16/? 1/? 4/? 2/? 1/? 3/? 1... )===
+
+prove and other harnesses come with a lot of useful options. The
+--state option in particular is very useful:
+
+ # Repeat until no more failures
+ $ prove -j 15 --state=failed,save ./t[0-9]*.sh
+
+You can also run each test individually from command line, like this:
+
+ $ sh ./t3010-ls-files-killed-modified.sh
+ ok 1 - git update-index --add to add various paths.
+ ok 2 - git ls-files -k to show killed files.
+ ok 3 - validate git ls-files -k output.
+ ok 4 - git ls-files -m to show modified files.
+ ok 5 - validate git ls-files -m output.
+ # passed all 5 test(s)
+ 1..5
You can pass --verbose (or -v), --debug (or -d), and --immediate
(or -i) command line argument to the test, or by setting GIT_TEST_OPTS
@@ -198,15 +221,101 @@ This test harness library does the following things:
- If the script is invoked with command line argument --help
(or -h), it shows the test_description and exits.
- - Creates an empty test directory with an empty .git/objects
- database and chdir(2) into it. This directory is 't/trash directory'
- if you must know, but I do not think you care.
+ - Creates an empty test directory with an empty .git/objects database
+ and chdir(2) into it. This directory is 't/trash
+ directory.$test_name_without_dotsh', with t/ subject to change by
+ the --root option documented above.
- Defines standard test helper functions for your scripts to
use. These functions are designed to make all scripts behave
consistently when command line arguments --verbose (or -v),
--debug (or -d), and --immediate (or -i) is given.
+Do's, don'ts & things to keep in mind
+-------------------------------------
+
+Here are a few examples of things you probably should and shouldn't do
+when writing tests.
+
+Do:
+
+ - Put all code inside test_expect_success and other assertions.
+
+ Even code that isn't a test per se, but merely some setup code
+ should be inside a test assertion.
+
+ - Chain your test assertions
+
+ Write test code like this:
+
+ git merge foo &&
+ git push bar &&
+ test ...
+
+ Instead of:
+
+ git merge hla
+ git push gh
+ test ...
+
+ That way all of the commands in your tests will succeed or fail. If
+ you must ignore the return value of something (e.g. the return
+ value of export is unportable) it's best to indicate so explicitly
+ with a semicolon:
+
+ export HLAGH;
+ git merge hla &&
+ git push gh &&
+ test ...
+
+Don't:
+
+ - exit() within a <script> part.
+
+ The harness will catch this as a programming error of the test.
+ Use test_done instead if you need to stop the tests early (see
+ "Skipping tests" below).
+
+ - Break the TAP output
+
+ The raw output from your test may be interpreted by a TAP harness. TAP
+ harnesses will ignore everything they don't know about, but don't step
+ on their toes in these areas:
+
+ - Don't print lines like "$x..$y" where $x and $y are integers.
+
+ - Don't print lines that begin with "ok" or "not ok".
+
+ TAP harnesses expect a line that begins with either "ok" and "not
+ ok" to signal a test passed or failed (and our harness already
+ produces such lines), so your script shouldn't emit such lines to
+ their output.
+
+ You can glean some further possible issues from the TAP grammar
+ (see http://search.cpan.org/perldoc?TAP::Parser::Grammar#TAP_Grammar)
+ but the best indication is to just run the tests with prove(1),
+ it'll complain if anything is amiss.
+
+Keep in mind:
+
+ - Inside <script> part, the standard output and standard error
+ streams are discarded, and the test harness only reports "ok" or
+ "not ok" to the end user running the tests. Under --verbose, they
+ are shown to help debugging the tests.
+
+
+Skipping tests
+--------------
+
+If you need to skip all the remaining tests you should set skip_all
+and immediately call test_done. The string you give to skip_all will
+be used as an explanation for why the test was skipped. for instance:
+
+ if ! test_have_prereq PERL
+ then
+ skip_all='skipping perl interface tests, perl not available'
+ test_done
+ fi
End with test_done
------------------
@@ -222,9 +331,9 @@ Test harness library
There are a handful helper functions defined in the test harness
library for your script to use.
- - test_expect_success <message> <script>
+ - test_expect_success [<prereq>] <message> <script>
- This takes two strings as parameter, and evaluates the
+ Usually takes two strings as parameter, and evaluates the
<script>. If it yields success, test is considered
successful. <message> should state what it is testing.
@@ -234,7 +343,14 @@ library for your script to use.
'git-write-tree should be able to write an empty tree.' \
'tree=$(git-write-tree)'
- - test_expect_failure <message> <script>
+ If you supply three parameters the first will be taken to be a
+ prerequisite, see the test_set_prereq and test_have_prereq
+ documentation below:
+
+ test_expect_success TTY 'git --paginate rev-list uses a pager' \
+ ' ... '
+
+ - test_expect_failure [<prereq>] <message> <script>
This is NOT the opposite of test_expect_success, but is used
to mark a test that demonstrates a known breakage. Unlike
@@ -243,6 +359,16 @@ library for your script to use.
success and "still broken" on failure. Failures from these
tests won't cause -i (immediate) to stop.
+ Like test_expect_success this function can optionally use a three
+ argument invocation with a prerequisite as the first argument.
+
+ - test_expect_code [<prereq>] <code> <message> <script>
+
+ Analogous to test_expect_success, but pass the test if it exits
+ with a given exit <code>
+
+ test_expect_code 1 'Merge with d/f conflicts' 'git merge "merge msg" B master'
+
- test_debug <script>
This takes a single argument, <script>, and evaluates it only
@@ -275,6 +401,85 @@ library for your script to use.
Merges the given rev using the given message. Like test_commit,
creates a tag and calls test_tick before committing.
+ - test_set_prereq SOME_PREREQ
+
+ Set a test prerequisite to be used later with test_have_prereq. The
+ test-lib will set some prerequisites for you, e.g. PERL and PYTHON
+ which are derived from ./GIT-BUILD-OPTIONS (grep test_set_prereq
+ test-lib.sh for more). Others you can set yourself and use later
+ with either test_have_prereq directly, or the three argument
+ invocation of test_expect_success and test_expect_failure.
+
+ - test_have_prereq SOME PREREQ
+
+ Check if we have a prerequisite previously set with
+ test_set_prereq. The most common use of this directly is to skip
+ all the tests if we don't have some essential prerequisite:
+
+ if ! test_have_prereq PERL
+ then
+ skip_all='skipping perl interface tests, perl not available'
+ test_done
+ fi
+
+ - test_external [<prereq>] <message> <external> <script>
+
+ Execute a <script> with an <external> interpreter (like perl). This
+ was added for tests like t9700-perl-git.sh which do most of their
+ work in an external test script.
+
+ test_external \
+ 'GitwebCache::*FileCache*' \
+ "$PERL_PATH" "$TEST_DIRECTORY"/t9503/test_cache_interface.pl
+
+ If the test is outputting its own TAP you should set the
+ test_external_has_tap variable somewhere before calling the first
+ test_external* function. See t9700-perl-git.sh for an example.
+
+ # The external test will outputs its own plan
+ test_external_has_tap=1
+
+ - test_external_without_stderr [<prereq>] <message> <external> <script>
+
+ Like test_external but fail if there's any output on stderr,
+ instead of checking the exit code.
+
+ test_external_without_stderr \
+ 'Perl API' \
+ "$PERL_PATH" "$TEST_DIRECTORY"/t9700/test.pl
+
+ - test_must_fail <git-command>
+
+ Run a git command and ensure it fails in a controlled way. Use
+ this instead of "! <git-command>" to fail when git commands
+ segfault.
+
+ - test_might_fail <git-command>
+
+ Similar to test_must_fail, but tolerate success, too. Use this
+ instead of "<git-command> || :" to catch failures due to segv.
+
+ - test_cmp <expected> <actual>
+
+ Check whether the content of the <actual> file matches the
+ <expected> file. This behaves like "cmp" but produces more
+ helpful output when the test is run with "-v" option.
+
+ - test_when_finished <script>
+
+ Prepend <script> to a list of commands to run to clean up
+ at the end of the current test. If some clean-up command
+ fails, the test will not pass.
+
+ Example:
+
+ test_expect_success 'branch pointing to non-commit' '
+ git rev-parse HEAD^{tree} >.git/refs/heads/invalid &&
+ test_when_finished "git update-ref -d refs/heads/invalid" &&
+ ...
+ '
+
+
Tips for Writing Tests
----------------------
diff --git a/t/gitweb-lib.sh b/t/gitweb-lib.sh
index b70b891b62..81ef2a0969 100644
--- a/t/gitweb-lib.sh
+++ b/t/gitweb-lib.sh
@@ -76,12 +76,12 @@ gitweb_run () {
. ./test-lib.sh
if ! test_have_prereq PERL; then
- say 'skipping gitweb tests, perl not available'
+ skip_all='skipping gitweb tests, perl not available'
test_done
fi
perl -MEncode -e 'decode_utf8("", Encode::FB_CROAK)' >/dev/null 2>&1 || {
- say 'skipping gitweb tests, perl version is too old'
+ skip_all='skipping gitweb tests, perl version is too old'
test_done
}
diff --git a/t/lib-cvs.sh b/t/lib-cvs.sh
index 4b3b793730..648d1619c8 100644
--- a/t/lib-cvs.sh
+++ b/t/lib-cvs.sh
@@ -9,7 +9,7 @@ export HOME
if ! type cvs >/dev/null 2>&1
then
- say 'skipping cvsimport tests, cvs not found'
+ skip_all='skipping cvsimport tests, cvs not found'
test_done
fi
@@ -21,11 +21,11 @@ case "$cvsps_version" in
2.1 | 2.2*)
;;
'')
- say 'skipping cvsimport tests, cvsps not found'
+ skip_all='skipping cvsimport tests, cvsps not found'
test_done
;;
*)
- say 'skipping cvsimport tests, unsupported cvsps version'
+ skip_all='skipping cvsimport tests, unsupported cvsps version'
test_done
;;
esac
diff --git a/t/lib-git-svn.sh b/t/lib-git-svn.sh
index 0f7f35ccc9..c3f6676ca2 100644
--- a/t/lib-git-svn.sh
+++ b/t/lib-git-svn.sh
@@ -5,11 +5,11 @@ git_svn_id=git""-svn-id
if test -n "$NO_SVN_TESTS"
then
- say 'skipping git svn tests, NO_SVN_TESTS defined'
+ skip_all='skipping git svn tests, NO_SVN_TESTS defined'
test_done
fi
if ! test_have_prereq PERL; then
- say 'skipping git svn tests, perl not available'
+ skip_all='skipping git svn tests, perl not available'
test_done
fi
@@ -21,7 +21,7 @@ PERL=${PERL:-perl}
svn >/dev/null 2>&1
if test $? -ne 1
then
- say 'skipping git svn tests, svn not found'
+ skip_all='skipping git svn tests, svn not found'
test_done
fi
@@ -40,13 +40,12 @@ x=$?
if test $x -ne 0
then
if test $x -eq 42; then
- err='Perl SVN libraries must be >= 1.1.0'
+ skip_all='Perl SVN libraries must be >= 1.1.0'
elif test $x -eq 41; then
- err='svnadmin failed to create fsfs repository'
+ skip_all='svnadmin failed to create fsfs repository'
else
- err='Perl SVN libraries not found or unusable, skipping test'
+ skip_all='Perl SVN libraries not found or unusable'
fi
- say "$err"
test_done
fi
@@ -159,7 +158,7 @@ EOF
require_svnserve () {
if test -z "$SVNSERVE_PORT"
then
- say 'skipping svnserve test. (set $SVNSERVE_PORT to enable)'
+ skip_all='skipping svnserve test. (set $SVNSERVE_PORT to enable)'
test_done
fi
}
diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh
index da4b8d5a6f..71effc5bec 100644
--- a/t/lib-httpd.sh
+++ b/t/lib-httpd.sh
@@ -5,8 +5,7 @@
if test -z "$GIT_TEST_HTTPD"
then
- say "skipping test, network testing disabled by default"
- say "(define GIT_TEST_HTTPD to enable)"
+ skip_all="Network testing disabled (define GIT_TEST_HTTPD to enable)"
test_done
fi
@@ -46,7 +45,7 @@ HTTPD_DOCUMENT_ROOT_PATH=$HTTPD_ROOT_PATH/www
if ! test -x "$LIB_HTTPD_PATH"
then
- say "skipping test, no web server found at '$LIB_HTTPD_PATH'"
+ skip_all="skipping test, no web server found at '$LIB_HTTPD_PATH'"
test_done
fi
@@ -59,12 +58,12 @@ then
then
if ! test $HTTPD_VERSION -ge 2
then
- say "skipping test, at least Apache version 2 is required"
+ skip_all="skipping test, at least Apache version 2 is required"
test_done
fi
if ! test -d "$DEFAULT_HTTPD_MODULE_PATH"
then
- say "Apache module directory not found. Skipping tests."
+ skip_all="Apache module directory not found. Skipping tests."
test_done
fi
@@ -119,7 +118,7 @@ start_httpd() {
>&3 2>&4
if test $? -ne 0
then
- say "skipping test, web server setup failed"
+ skip_all="skipping test, web server setup failed"
trap 'die' EXIT
test_done
fi
diff --git a/t/lib-pager.sh b/t/lib-pager.sh
new file mode 100644
index 0000000000..ba03eab14f
--- /dev/null
+++ b/t/lib-pager.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+test_expect_success 'determine default pager' '
+ test_might_fail git config --unset core.pager &&
+ less=$(
+ unset PAGER GIT_PAGER;
+ git var GIT_PAGER
+ ) &&
+ test -n "$less"
+'
+
+if expr "$less" : '[a-z][a-z]*$' >/dev/null
+then
+ test_set_prereq SIMPLEPAGER
+fi
diff --git a/t/lib-patch-mode.sh b/t/lib-patch-mode.sh
index ce36f34d03..375e248651 100644
--- a/t/lib-patch-mode.sh
+++ b/t/lib-patch-mode.sh
@@ -3,7 +3,7 @@
. ./test-lib.sh
if ! test_have_prereq PERL; then
- say 'skipping --patch tests, perl not available'
+ skip_all='skipping --patch tests, perl not available'
test_done
fi
diff --git a/t/t0005-signals.sh b/t/t0005-signals.sh
index 09f855af3e..93e58c00e8 100755
--- a/t/t0005-signals.sh
+++ b/t/t0005-signals.sh
@@ -13,6 +13,7 @@ test_expect_success 'sigchain works' '
test-sigchain >actual
case "$?" in
143) true ;; # POSIX w/ SIGTERM=15
+ 271) true ;; # ksh w/ SIGTERM=15
3) true ;; # Windows
*) false ;;
esac &&
diff --git a/t/t0006-date.sh b/t/t0006-date.sh
index 75b02af86d..1d4d0a5c7d 100755
--- a/t/t0006-date.sh
+++ b/t/t0006-date.sh
@@ -28,8 +28,8 @@ check_show 31449600 '12 months ago'
check_parse() {
echo "$1 -> $2" >expect
- test_expect_${3:-success} "parse date ($1)" "
- test-date parse '$1' >actual &&
+ test_expect_${4:-success} "parse date ($1${3:+ TZ=$3})" "
+ TZ=${3:-$TZ} test-date parse '$1' >actual &&
test_cmp expect actual
"
}
@@ -38,6 +38,8 @@ check_parse 2008 bad
check_parse 2008-02 bad
check_parse 2008-02-14 bad
check_parse '2008-02-14 20:30:45' '2008-02-14 20:30:45 +0000'
+check_parse '2008-02-14 20:30:45 -0500' '2008-02-14 20:30:45 -0500'
+check_parse '2008-02-14 20:30:45' '2008-02-14 20:30:45 -0500' EST5
check_approxidate() {
echo "$1 -> $2 +0000" >expect
diff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh
index 6327d205cb..0c562bb820 100755
--- a/t/t1001-read-tree-m-2way.sh
+++ b/t/t1001-read-tree-m-2way.sh
@@ -390,4 +390,20 @@ test_expect_success \
git ls-files --stage | tee >treeMcheck.out &&
test_cmp treeM.out treeMcheck.out'
+test_expect_success '-m references the correct modified tree' '
+ echo >file-a &&
+ echo >file-b &&
+ git add file-a file-b &&
+ git commit -a -m "test for correct modified tree"
+ git branch initial-mod &&
+ echo b >file-b &&
+ git commit -a -m "B" &&
+ echo a >file-a &&
+ git add file-a &&
+ git ls-tree $(git write-tree) file-a >expect &&
+ git read-tree -m HEAD initial-mod &&
+ git ls-tree $(git write-tree) file-a >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t1020-subdirectory.sh b/t/t1020-subdirectory.sh
index 210e594f6f..56874996a6 100755
--- a/t/t1020-subdirectory.sh
+++ b/t/t1020-subdirectory.sh
@@ -24,18 +24,18 @@ test_expect_success 'update-index and ls-files' '
cd "$HERE" &&
git update-index --add one &&
case "`git ls-files`" in
- one) echo ok one ;;
+ one) echo pass one ;;
*) echo bad one; exit 1 ;;
esac &&
cd dir &&
git update-index --add two &&
case "`git ls-files`" in
- two) echo ok two ;;
+ two) echo pass two ;;
*) echo bad two; exit 1 ;;
esac &&
cd .. &&
case "`git ls-files`" in
- dir/two"$LF"one) echo ok both ;;
+ dir/two"$LF"one) echo pass both ;;
*) echo bad; exit 1 ;;
esac
'
@@ -58,17 +58,17 @@ test_expect_success 'diff-files' '
echo a >>one &&
echo d >>dir/two &&
case "`git diff-files --name-only`" in
- dir/two"$LF"one) echo ok top ;;
+ dir/two"$LF"one) echo pass top ;;
*) echo bad top; exit 1 ;;
esac &&
# diff should not omit leading paths
cd dir &&
case "`git diff-files --name-only`" in
- dir/two"$LF"one) echo ok subdir ;;
+ dir/two"$LF"one) echo pass subdir ;;
*) echo bad subdir; exit 1 ;;
esac &&
case "`git diff-files --name-only .`" in
- dir/two) echo ok subdir limited ;;
+ dir/two) echo pass subdir limited ;;
*) echo bad subdir limited; exit 1 ;;
esac
'
diff --git a/t/t1304-default-acl.sh b/t/t1304-default-acl.sh
index 055ad00f77..97ab02aceb 100755
--- a/t/t1304-default-acl.sh
+++ b/t/t1304-default-acl.sh
@@ -15,9 +15,12 @@ umask 077
# is a good candidate: exists on all unices, and it has permission
# anyway, so we don't create a security hole running the testsuite.
-if ! setfacl -m u:root:rwx .; then
- say "Skipping ACL tests: unable to use setfacl"
- test_done
+setfacl_out="$(setfacl -m u:root:rwx . 2>&1)"
+setfacl_ret=$?
+
+if [ $setfacl_ret != 0 ]; then
+ skip_all="Skipping ACL tests: unable to use setfacl (output: '$setfacl_out'; return code: '$setfacl_ret')"
+ test_done
fi
check_perms_and_acl () {
diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh
index 4346795855..b3195c4707 100755
--- a/t/t1502-rev-parse-parseopt.sh
+++ b/t/t1502-rev-parse-parseopt.sh
@@ -81,4 +81,22 @@ test_expect_success 'test --parseopt --keep-dashdash' '
test_cmp expect output
'
+cat >expect <<EOF
+set -- --foo -- '--' 'arg' '--spam=ham'
+EOF
+
+test_expect_success 'test --parseopt --keep-dashdash --stop-at-non-option with --' '
+ git rev-parse --parseopt --keep-dashdash --stop-at-non-option -- --foo -- arg --spam=ham <optionspec >output &&
+ test_cmp expect output
+'
+
+cat > expect <<EOF
+set -- --foo -- 'arg' '--spam=ham'
+EOF
+
+test_expect_success 'test --parseopt --keep-dashdash --stop-at-non-option without --' '
+ git rev-parse --parseopt --keep-dashdash --stop-at-non-option -- --foo arg --spam=ham <optionspec >output &&
+ test_cmp expect output
+'
+
test_done
diff --git a/t/t1509-root-worktree.sh b/t/t1509-root-worktree.sh
index 5322a3bf97..7f60fd0b2e 100755
--- a/t/t1509-root-worktree.sh
+++ b/t/t1509-root-worktree.sh
@@ -99,17 +99,17 @@ test_foobar_foobar() {
}
if ! test_have_prereq POSIXPERM || ! [ -w / ]; then
- say "Dangerous test skipped. Read this test if you want to execute it"
+ skip_all="Dangerous test skipped. Read this test if you want to execute it"
test_done
fi
if [ "$IKNOWWHATIAMDOING" != "YES" ]; then
- say "You must set env var IKNOWWHATIAMDOING=YES in order to run this test"
+ skip_all="You must set env var IKNOWWHATIAMDOING=YES in order to run this test"
test_done
fi
if [ "$UID" = 0 ]; then
- say "No you can't run this with root"
+ skip_all="No you can't run this with root"
test_done
fi
diff --git a/t/t2007-checkout-symlink.sh b/t/t2007-checkout-symlink.sh
index 27e2127afe..05cc8fdd01 100755
--- a/t/t2007-checkout-symlink.sh
+++ b/t/t2007-checkout-symlink.sh
@@ -8,7 +8,7 @@ test_description='git checkout to switch between branches with symlink<->dir'
if ! test_have_prereq SYMLINKS
then
- say "symbolic links not supported - skipping tests"
+ skip_all="symbolic links not supported - skipping tests"
test_done
fi
diff --git a/t/t2102-update-index-symlinks.sh b/t/t2102-update-index-symlinks.sh
index 1ed44ee503..4d0d0a3515 100755
--- a/t/t2102-update-index-symlinks.sh
+++ b/t/t2102-update-index-symlinks.sh
@@ -24,7 +24,7 @@ git update-index symlink'
test_expect_success \
'the index entry must still be a symbolic link' '
case "`git ls-files --stage --cached symlink`" in
-120000" "*symlink) echo ok;;
+120000" "*symlink) echo pass;;
*) echo fail; git ls-files --stage --cached symlink; (exit 1);;
esac'
diff --git a/t/t3000-ls-files-others.sh b/t/t3000-ls-files-others.sh
index 86291e8399..2eec0118c4 100755
--- a/t/t3000-ls-files-others.sh
+++ b/t/t3000-ls-files-others.sh
@@ -17,57 +17,52 @@ filesystem.
'
. ./test-lib.sh
-date >path0
-if test_have_prereq SYMLINKS
-then
- ln -s xyzzy path1
-else
- date > path1
-fi
-mkdir path2 path3 path4
-date >path2/file2
-date >path2-junk
-date >path3/file3
-date >path3-junk
-git update-index --add path3-junk path3/file3
-
-cat >expected1 <<EOF
-expected1
-expected2
-expected3
-output
-path0
-path1
-path2-junk
-path2/file2
-EOF
-sed -e 's|path2/file2|path2/|' <expected1 >expected2
-cat <expected2 >expected3
-echo path4/ >>expected2
-
-test_expect_success \
- 'git ls-files --others to show output.' \
- 'git ls-files --others >output'
-
-test_expect_success \
- 'git ls-files --others should pick up symlinks.' \
- 'test_cmp expected1 output'
+test_expect_success 'setup ' '
+ date >path0 &&
+ if test_have_prereq SYMLINKS
+ then
+ ln -s xyzzy path1
+ else
+ date >path1
+ fi &&
+ mkdir path2 path3 path4 &&
+ date >path2/file2 &&
+ date >path2-junk &&
+ date >path3/file3 &&
+ date >path3-junk &&
+ git update-index --add path3-junk path3/file3
+'
-test_expect_success \
- 'git ls-files --others --directory to show output.' \
- 'git ls-files --others --directory >output'
+test_expect_success 'setup: expected output' '
+ cat >expected1 <<-\EOF &&
+ expected1
+ expected2
+ expected3
+ output
+ path0
+ path1
+ path2-junk
+ path2/file2
+ EOF
+ sed -e "s|path2/file2|path2/|" <expected1 >expected2 &&
+ cp expected2 expected3 &&
+ echo path4/ >>expected2
+'
-test_expect_success \
- 'git ls-files --others --directory should not get confused.' \
- 'test_cmp expected2 output'
+test_expect_success 'ls-files --others' '
+ git ls-files --others >output &&
+ test_cmp expected1 output
+'
-test_expect_success \
- 'git ls-files --others --directory --no-empty-directory to show output.' \
- 'git ls-files --others --directory --no-empty-directory >output'
+test_expect_success 'ls-files --others --directory' '
+ git ls-files --others --directory >output &&
+ test_cmp expected2 output
+'
-test_expect_success \
- '--no-empty-directory hides empty directory' \
- 'test_cmp expected3 output'
+test_expect_success '--no-empty-directory hides empty directory' '
+ git ls-files --others --directory --no-empty-directory >output &&
+ test_cmp expected3 output
+'
test_done
diff --git a/t/t3300-funny-names.sh b/t/t3300-funny-names.sh
index db46d53e82..a99e4d8b92 100755
--- a/t/t3300-funny-names.sh
+++ b/t/t3300-funny-names.sh
@@ -26,7 +26,7 @@ echo 'Foo Bar Baz' >"$p2"
test -f "$p1" && cmp "$p0" "$p1" || {
# since FAT/NTFS does not allow tabs in filenames, skip this test
- say 'Your filesystem does not allow tabs in filenames, test skipped.'
+ skip_all='Your filesystem does not allow tabs in filenames, test skipped.'
test_done
}
diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh
index 64f32ad94d..2d67a40fc1 100755
--- a/t/t3301-notes.sh
+++ b/t/t3301-notes.sh
@@ -1044,4 +1044,10 @@ test_expect_success 'GIT_NOTES_REWRITE_REF overrides config' '
git log -1 > output &&
test_cmp expect output
'
+
+test_expect_success 'git notes copy diagnoses too many or too few parameters' '
+ test_must_fail git notes copy &&
+ test_must_fail git notes copy one two three
+'
+
test_done
diff --git a/t/t3302-notes-index-expensive.sh b/t/t3302-notes-index-expensive.sh
index ee84fc4884..361a10aeb1 100755
--- a/t/t3302-notes-index-expensive.sh
+++ b/t/t3302-notes-index-expensive.sh
@@ -8,7 +8,7 @@ test_description='Test commit notes index (expensive!)'
. ./test-lib.sh
test -z "$GIT_NOTES_TIMING_TESTS" && {
- say Skipping timing tests
+ skip_all="Skipping timing tests"
test_done
exit
}
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index ee9a1b25e6..47ca88fc52 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -630,4 +630,22 @@ test_expect_success 'always cherry-pick with --no-ff' '
test_cmp empty out
'
+test_expect_success 'set up commits with funny messages' '
+ git checkout -b funny A &&
+ echo >>file1 &&
+ test_tick &&
+ git commit -a -m "end with slash\\" &&
+ echo >>file1 &&
+ test_tick &&
+ git commit -a -m "another commit"
+'
+
+test_expect_success 'rebase-i history with funny messages' '
+ git rev-list A..funny >expect &&
+ test_tick &&
+ FAKE_LINES="1 2" git rebase -i A &&
+ git rev-list A.. >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t3501-revert-cherry-pick.sh b/t/t3501-revert-cherry-pick.sh
index e4fbf7a210..bc7aedd048 100755
--- a/t/t3501-revert-cherry-pick.sh
+++ b/t/t3501-revert-cherry-pick.sh
@@ -41,6 +41,24 @@ test_expect_success setup '
git tag rename2
'
+test_expect_success 'cherry-pick --nonsense' '
+
+ pos=$(git rev-parse HEAD) &&
+ git diff --exit-code HEAD &&
+ test_must_fail git cherry-pick --nonsense 2>msg &&
+ git diff --exit-code HEAD "$pos" &&
+ grep '[Uu]sage:' msg
+'
+
+test_expect_success 'revert --nonsense' '
+
+ pos=$(git rev-parse HEAD) &&
+ git diff --exit-code HEAD &&
+ test_must_fail git revert --nonsense 2>msg &&
+ git diff --exit-code HEAD "$pos" &&
+ grep '[Uu]sage:' msg
+'
+
test_expect_success 'cherry-pick after renaming branch' '
git checkout rename2 &&
diff --git a/t/t3508-cherry-pick-many-commits.sh b/t/t3508-cherry-pick-many-commits.sh
index 3b87efe3ad..f90ed3da3e 100755
--- a/t/t3508-cherry-pick-many-commits.sh
+++ b/t/t3508-cherry-pick-many-commits.sh
@@ -23,7 +23,7 @@ test_expect_success setup '
'
test_expect_success 'cherry-pick first..fourth works' '
- git checkout master &&
+ git checkout -f master &&
git reset --hard first &&
test_tick &&
git cherry-pick first..fourth &&
@@ -33,7 +33,7 @@ test_expect_success 'cherry-pick first..fourth works' '
'
test_expect_success 'cherry-pick --ff first..fourth works' '
- git checkout master &&
+ git checkout -f master &&
git reset --hard first &&
test_tick &&
git cherry-pick --ff first..fourth &&
@@ -43,7 +43,7 @@ test_expect_success 'cherry-pick --ff first..fourth works' '
'
test_expect_success 'cherry-pick -n first..fourth works' '
- git checkout master &&
+ git checkout -f master &&
git reset --hard first &&
test_tick &&
git cherry-pick -n first..fourth &&
@@ -53,7 +53,7 @@ test_expect_success 'cherry-pick -n first..fourth works' '
'
test_expect_success 'revert first..fourth works' '
- git checkout master &&
+ git checkout -f master &&
git reset --hard fourth &&
test_tick &&
git revert first..fourth &&
@@ -63,7 +63,7 @@ test_expect_success 'revert first..fourth works' '
'
test_expect_success 'revert ^first fourth works' '
- git checkout master &&
+ git checkout -f master &&
git reset --hard fourth &&
test_tick &&
git revert ^first fourth &&
@@ -73,7 +73,7 @@ test_expect_success 'revert ^first fourth works' '
'
test_expect_success 'revert fourth fourth~1 fourth~2 works' '
- git checkout master &&
+ git checkout -f master &&
git reset --hard fourth &&
test_tick &&
git revert fourth fourth~1 fourth~2 &&
@@ -82,8 +82,8 @@ test_expect_success 'revert fourth fourth~1 fourth~2 works' '
git diff --quiet HEAD first
'
-test_expect_failure 'cherry-pick -3 fourth works' '
- git checkout master &&
+test_expect_success 'cherry-pick -3 fourth works' '
+ git checkout -f master &&
git reset --hard first &&
test_tick &&
git cherry-pick -3 fourth &&
@@ -92,4 +92,14 @@ test_expect_failure 'cherry-pick -3 fourth works' '
test "$(git rev-parse --verify HEAD)" != "$(git rev-parse --verify fourth)"
'
+test_expect_success 'cherry-pick --stdin works' '
+ git checkout -f master &&
+ git reset --hard first &&
+ test_tick &&
+ git rev-list --reverse first..fourth | git cherry-pick --stdin &&
+ git diff --quiet other &&
+ git diff --quiet HEAD other &&
+ test "$(git rev-parse --verify HEAD)" != "$(git rev-parse --verify fourth)"
+'
+
test_done
diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh
index 0aaf0ad84b..b514cbb606 100755
--- a/t/t3600-rm.sh
+++ b/t/t3600-rm.sh
@@ -39,7 +39,7 @@ if test -f test-file
then
test_set_prereq RO_DIR
else
- say 'skipping removal failure test (perhaps running as root?)'
+ skip_all='skipping removal failure test (perhaps running as root?)'
fi
chmod 775 .
rm -f test-file
diff --git a/t/t3700-add.sh b/t/t3700-add.sh
index 525c9a8fdf..6f031af9f3 100755
--- a/t/t3700-add.sh
+++ b/t/t3700-add.sh
@@ -26,7 +26,7 @@ test_expect_success \
chmod 755 xfoo1 &&
git add xfoo1 &&
case "`git ls-files --stage xfoo1`" in
- 100644" "*xfoo1) echo ok;;
+ 100644" "*xfoo1) echo pass;;
*) echo fail; git ls-files --stage xfoo1; (exit 1);;
esac'
@@ -35,7 +35,7 @@ test_expect_success SYMLINKS 'git add: filemode=0 should not get confused by sym
ln -s foo xfoo1 &&
git add xfoo1 &&
case "`git ls-files --stage xfoo1`" in
- 120000" "*xfoo1) echo ok;;
+ 120000" "*xfoo1) echo pass;;
*) echo fail; git ls-files --stage xfoo1; (exit 1);;
esac
'
@@ -47,7 +47,7 @@ test_expect_success \
chmod 755 xfoo2 &&
git update-index --add xfoo2 &&
case "`git ls-files --stage xfoo2`" in
- 100644" "*xfoo2) echo ok;;
+ 100644" "*xfoo2) echo pass;;
*) echo fail; git ls-files --stage xfoo2; (exit 1);;
esac'
@@ -56,7 +56,7 @@ test_expect_success SYMLINKS 'git add: filemode=0 should not get confused by sym
ln -s foo xfoo2 &&
git update-index --add xfoo2 &&
case "`git ls-files --stage xfoo2`" in
- 120000" "*xfoo2) echo ok;;
+ 120000" "*xfoo2) echo pass;;
*) echo fail; git ls-files --stage xfoo2; (exit 1);;
esac
'
@@ -67,7 +67,7 @@ test_expect_success SYMLINKS \
ln -s xfoo2 xfoo3 &&
git update-index --add xfoo3 &&
case "`git ls-files --stage xfoo3`" in
- 120000" "*xfoo3) echo ok;;
+ 120000" "*xfoo3) echo pass;;
*) echo fail; git ls-files --stage xfoo3; (exit 1);;
esac'
@@ -172,7 +172,7 @@ test_expect_success 'git add --refresh' '
test -z "`git diff-index HEAD -- foo`" &&
git read-tree HEAD &&
case "`git diff-index HEAD -- foo`" in
- :100644" "*"M foo") echo ok;;
+ :100644" "*"M foo") echo pass;;
*) echo fail; (exit 1);;
esac &&
git add --refresh -- foo &&
diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh
index b6eba6a839..7ad8465f8f 100755
--- a/t/t3701-add-interactive.sh
+++ b/t/t3701-add-interactive.sh
@@ -4,7 +4,7 @@ test_description='add -i basic tests'
. ./test-lib.sh
if ! test_have_prereq PERL; then
- say 'skipping git add -i tests, perl not available'
+ skip_all='skipping git add -i tests, perl not available'
test_done
fi
@@ -154,7 +154,7 @@ rm -f .gitignore
if test "$(git config --bool core.filemode)" = false
then
- say 'skipping filemode tests (filesystem does not properly support modes)'
+ say '# skipping filemode tests (filesystem does not properly support modes)'
else
test_set_prereq FILEMODE
fi
diff --git a/t/t3902-quoted.sh b/t/t3902-quoted.sh
index 29103f65dc..147e634cd6 100755
--- a/t/t3902-quoted.sh
+++ b/t/t3902-quoted.sh
@@ -17,7 +17,7 @@ DQ='"'
echo foo 2>/dev/null > "Name and an${HT}HT"
test -f "Name and an${HT}HT" || {
# since FAT/NTFS does not allow tabs in filenames, skip this test
- say 'Your filesystem does not allow tabs in filenames, test skipped.'
+ skip_all='Your filesystem does not allow tabs in filenames, test skipped.'
test_done
}
diff --git a/t/t4004-diff-rename-symlink.sh b/t/t4004-diff-rename-symlink.sh
index a4da1196a9..1a09e8db40 100755
--- a/t/t4004-diff-rename-symlink.sh
+++ b/t/t4004-diff-rename-symlink.sh
@@ -14,7 +14,7 @@ by an edit for them.
if ! test_have_prereq SYMLINKS
then
- say 'Symbolic links not supported, skipping tests.'
+ skip_all='Symbolic links not supported, skipping tests.'
test_done
fi
diff --git a/t/t4011-diff-symlink.sh b/t/t4011-diff-symlink.sh
index e12fbea1b5..918a21a2f4 100755
--- a/t/t4011-diff-symlink.sh
+++ b/t/t4011-diff-symlink.sh
@@ -11,7 +11,7 @@ test_description='Test diff of symlinks.
if ! test_have_prereq SYMLINKS
then
- say 'Symbolic links not supported, skipping tests.'
+ skip_all='Symbolic links not supported, skipping tests.'
test_done
fi
diff --git a/t/t4016-diff-quote.sh b/t/t4016-diff-quote.sh
index 55eb5f83f1..34e5144eed 100755
--- a/t/t4016-diff-quote.sh
+++ b/t/t4016-diff-quote.sh
@@ -14,7 +14,7 @@ P2='pathname with SP'
P3='pathname
with LF'
: 2>/dev/null >"$P1" && test -f "$P1" && rm -f "$P1" || {
- say 'Your filesystem does not allow tabs in filenames, test skipped.'
+ skip_all='Your filesystem does not allow tabs in filenames, test skipped.'
test_done
}
diff --git a/t/t4023-diff-rename-typechange.sh b/t/t4023-diff-rename-typechange.sh
index 9bdf6596d8..40a95a149e 100755
--- a/t/t4023-diff-rename-typechange.sh
+++ b/t/t4023-diff-rename-typechange.sh
@@ -6,7 +6,7 @@ test_description='typechange rename detection'
if ! test_have_prereq SYMLINKS
then
- say 'Symbolic links not supported, skipping tests.'
+ skip_all='Symbolic links not supported, skipping tests.'
test_done
fi
diff --git a/t/t4027-diff-submodule.sh b/t/t4027-diff-submodule.sh
index 83c1914771..1bd8e5ee3a 100755
--- a/t/t4027-diff-submodule.sh
+++ b/t/t4027-diff-submodule.sh
@@ -103,7 +103,15 @@ test_expect_success 'git diff HEAD with dirty submodule (work tree, refs match)'
git diff HEAD >actual &&
sed -e "1,/^@@/d" actual >actual.body &&
expect_from_to >expect.body $subprev $subprev-dirty &&
- test_cmp expect.body actual.body
+ test_cmp expect.body actual.body &&
+ git diff --ignore-submodules HEAD >actual2 &&
+ ! test -s actual2 &&
+ git diff --ignore-submodules=untracked HEAD >actual3 &&
+ sed -e "1,/^@@/d" actual3 >actual3.body &&
+ expect_from_to >expect.body $subprev $subprev-dirty &&
+ test_cmp expect.body actual3.body &&
+ git diff --ignore-submodules=dirty HEAD >actual4 &&
+ ! test -s actual4
'
test_expect_success 'git diff HEAD with dirty submodule (index, refs match)' '
@@ -129,7 +137,13 @@ test_expect_success 'git diff HEAD with dirty submodule (untracked, refs match)'
git diff HEAD >actual &&
sed -e "1,/^@@/d" actual >actual.body &&
expect_from_to >expect.body $subprev $subprev-dirty &&
- test_cmp expect.body actual.body
+ test_cmp expect.body actual.body &&
+ git diff --ignore-submodules=all HEAD >actual2 &&
+ ! test -s actual2 &&
+ git diff --ignore-submodules=untracked HEAD >actual3 &&
+ ! test -s actual3 &&
+ git diff --ignore-submodules=dirty HEAD >actual4 &&
+ ! test -s actual4
'
test_expect_success 'git diff (empty submodule dir)' '
diff --git a/t/t4041-diff-submodule.sh b/t/t4041-diff-submodule-option.sh
index 019acb926d..8e391cf9a7 100755
--- a/t/t4041-diff-submodule.sh
+++ b/t/t4041-diff-submodule-option.sh
@@ -205,6 +205,21 @@ Submodule sm1 contains untracked content
EOF
"
+test_expect_success 'submodule contains untracked content (untracked ignored)' "
+ git diff-index -p --ignore-submodules=untracked --submodule=log HEAD >actual &&
+ ! test -s actual
+"
+
+test_expect_success 'submodule contains untracked content (dirty ignored)' "
+ git diff-index -p --ignore-submodules=dirty --submodule=log HEAD >actual &&
+ ! test -s actual
+"
+
+test_expect_success 'submodule contains untracked content (all ignored)' "
+ git diff-index -p --ignore-submodules=all --submodule=log HEAD >actual &&
+ ! test -s actual
+"
+
test_expect_success 'submodule contains untracked and modifed content' "
echo new > sm1/foo6 &&
git diff-index -p --submodule=log HEAD >actual &&
@@ -214,6 +229,26 @@ Submodule sm1 contains modified content
EOF
"
+test_expect_success 'submodule contains untracked and modifed content (untracked ignored)' "
+ echo new > sm1/foo6 &&
+ git diff-index -p --ignore-submodules=untracked --submodule=log HEAD >actual &&
+ diff actual - <<-EOF
+Submodule sm1 contains modified content
+EOF
+"
+
+test_expect_success 'submodule contains untracked and modifed content (dirty ignored)' "
+ echo new > sm1/foo6 &&
+ git diff-index -p --ignore-submodules=dirty --submodule=log HEAD >actual &&
+ ! test -s actual
+"
+
+test_expect_success 'submodule contains untracked and modifed content (all ignored)' "
+ echo new > sm1/foo6 &&
+ git diff-index -p --ignore-submodules --submodule=log HEAD >actual &&
+ ! test -s actual
+"
+
test_expect_success 'submodule contains modifed content' "
rm -f sm1/new-file &&
git diff-index -p --submodule=log HEAD >actual &&
@@ -242,6 +277,27 @@ Submodule sm1 $head6..$head8:
EOF
"
+test_expect_success 'modified submodule contains untracked content (untracked ignored)' "
+ git diff-index -p --ignore-submodules=untracked --submodule=log HEAD >actual &&
+ diff actual - <<-EOF
+Submodule sm1 $head6..$head8:
+ > change
+EOF
+"
+
+test_expect_success 'modified submodule contains untracked content (dirty ignored)' "
+ git diff-index -p --ignore-submodules=dirty --submodule=log HEAD >actual &&
+ diff actual - <<-EOF
+Submodule sm1 $head6..$head8:
+ > change
+EOF
+"
+
+test_expect_success 'modified submodule contains untracked content (all ignored)' "
+ git diff-index -p --ignore-submodules=all --submodule=log HEAD >actual &&
+ ! test -s actual
+"
+
test_expect_success 'modified submodule contains untracked and modifed content' "
echo modification >> sm1/foo6 &&
git diff-index -p --submodule=log HEAD >actual &&
@@ -253,6 +309,31 @@ Submodule sm1 $head6..$head8:
EOF
"
+test_expect_success 'modified submodule contains untracked and modifed content (untracked ignored)' "
+ echo modification >> sm1/foo6 &&
+ git diff-index -p --ignore-submodules=untracked --submodule=log HEAD >actual &&
+ diff actual - <<-EOF
+Submodule sm1 contains modified content
+Submodule sm1 $head6..$head8:
+ > change
+EOF
+"
+
+test_expect_success 'modified submodule contains untracked and modifed content (dirty ignored)' "
+ echo modification >> sm1/foo6 &&
+ git diff-index -p --ignore-submodules=dirty --submodule=log HEAD >actual &&
+ diff actual - <<-EOF
+Submodule sm1 $head6..$head8:
+ > change
+EOF
+"
+
+test_expect_success 'modified submodule contains untracked and modifed content (all ignored)' "
+ echo modification >> sm1/foo6 &&
+ git diff-index -p --ignore-submodules --submodule=log HEAD >actual &&
+ ! test -s actual
+"
+
test_expect_success 'modified submodule contains modifed content' "
rm -f sm1/new-file &&
git diff-index -p --submodule=log HEAD >actual &&
diff --git a/t/t4114-apply-typechange.sh b/t/t4114-apply-typechange.sh
index 99ec13dd53..164d58c222 100755
--- a/t/t4114-apply-typechange.sh
+++ b/t/t4114-apply-typechange.sh
@@ -11,7 +11,7 @@ test_description='git apply should not get confused with type changes.
if ! test_have_prereq SYMLINKS
then
- say 'Symbolic links not supported, skipping tests.'
+ skip_all='Symbolic links not supported, skipping tests.'
test_done
fi
diff --git a/t/t4115-apply-symlink.sh b/t/t4115-apply-symlink.sh
index b852e58980..aff4348034 100755
--- a/t/t4115-apply-symlink.sh
+++ b/t/t4115-apply-symlink.sh
@@ -11,7 +11,7 @@ test_description='git apply symlinks and partial files
if ! test_have_prereq SYMLINKS
then
- say 'Symbolic links not supported, skipping tests.'
+ skip_all='Symbolic links not supported, skipping tests.'
test_done
fi
diff --git a/t/t4122-apply-symlink-inside.sh b/t/t4122-apply-symlink-inside.sh
index 0d3c1d5dd5..923fcab7f9 100755
--- a/t/t4122-apply-symlink-inside.sh
+++ b/t/t4122-apply-symlink-inside.sh
@@ -5,7 +5,7 @@ test_description='apply to deeper directory without getting fooled with symlink'
if ! test_have_prereq SYMLINKS
then
- say 'Symbolic links not supported, skipping tests.'
+ skip_all='Symbolic links not supported, skipping tests.'
test_done
fi
diff --git a/t/t4151-am-abort.sh b/t/t4151-am-abort.sh
index 2b912d7728..b55c411788 100755
--- a/t/t4151-am-abort.sh
+++ b/t/t4151-am-abort.sh
@@ -47,7 +47,7 @@ do
test_must_fail git am$with3 --skip >output &&
test "$(grep "^Applying" output)" = "Applying: 6" &&
test_cmp file-2-expect file-2 &&
- test ! -f .git/rr-cache/MERGE_RR
+ test ! -f .git/MERGE_RR
'
test_expect_success "am --abort goes back after failed am$with3" '
@@ -57,7 +57,7 @@ do
test_cmp expect actual &&
test_cmp file-2-expect file-2 &&
git diff-index --exit-code --cached HEAD &&
- test ! -f .git/rr-cache/MERGE_RR
+ test ! -f .git/MERGE_RR
'
done
diff --git a/t/t4207-log-decoration-colors.sh b/t/t4207-log-decoration-colors.sh
new file mode 100755
index 0000000000..bbde31b019
--- /dev/null
+++ b/t/t4207-log-decoration-colors.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Nazri Ramliy
+#
+
+test_description='Test for "git log --decorate" colors'
+
+. ./test-lib.sh
+
+get_color ()
+{
+ git config --get-color no.such.slot "$1"
+}
+
+test_expect_success setup '
+ git config diff.color.commit yellow &&
+ git config color.decorate.branch green &&
+ git config color.decorate.remoteBranch red &&
+ git config color.decorate.tag "reverse bold yellow" &&
+ git config color.decorate.stash magenta &&
+ git config color.decorate.HEAD cyan &&
+
+ c_reset=$(get_color reset) &&
+
+ c_commit=$(get_color yellow) &&
+ c_branch=$(get_color green) &&
+ c_remoteBranch=$(get_color red) &&
+ c_tag=$(get_color "reverse bold yellow") &&
+ c_stash=$(get_color magenta) &&
+ c_HEAD=$(get_color cyan) &&
+
+ test_commit A &&
+ git clone . other &&
+ (
+ cd other &&
+ test_commit A1
+ ) &&
+
+ git remote add -f other ./other &&
+ test_commit B &&
+ git tag v1.0 &&
+ echo >>A.t &&
+ git stash save Changes to A.t
+'
+
+cat >expected <<EOF
+${c_commit}COMMIT_ID (${c_HEAD}HEAD${c_reset}${c_commit},\
+ ${c_tag}tag: v1.0${c_reset}${c_commit},\
+ ${c_tag}tag: B${c_reset}${c_commit},\
+ ${c_branch}master${c_reset}${c_commit})${c_reset} B
+${c_commit}COMMIT_ID (${c_tag}tag: A1${c_reset}${c_commit},\
+ ${c_remoteBranch}other/master${c_reset}${c_commit})${c_reset} A1
+${c_commit}COMMIT_ID (${c_stash}refs/stash${c_reset}${c_commit})${c_reset}\
+ On master: Changes to A.t
+${c_commit}COMMIT_ID (${c_tag}tag: A${c_reset}${c_commit})${c_reset} A
+EOF
+
+# We want log to show all, but the second parent to refs/stash is irrelevant
+# to this test since it does not contain any decoration, hence --first-parent
+test_expect_success 'Commit Decorations Colored Correctly' '
+ git log --first-parent --abbrev=10 --all --decorate --oneline --color=always |
+ sed "s/[0-9a-f]\{10,10\}/COMMIT_ID/" >out &&
+ test_cmp expected out
+'
+
+test_done
diff --git a/t/t4300-merge-tree.sh b/t/t4300-merge-tree.sh
new file mode 100755
index 0000000000..46c3fe76d3
--- /dev/null
+++ b/t/t4300-merge-tree.sh
@@ -0,0 +1,257 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Will Palmer
+#
+
+test_description='git merge-tree'
+. ./test-lib.sh
+
+test_expect_success setup '
+ test_commit "initial" "initial-file" "initial"
+'
+
+test_expect_success 'file add A, !B' '
+ cat >expected <<\EXPECTED &&
+added in remote
+ their 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE
+@@ -0,0 +1 @@
++AAA
+EXPECTED
+
+ git reset --hard initial &&
+ test_commit "add-a-not-b" "ONE" "AAA" &&
+ git merge-tree initial initial add-a-not-b >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'file add !A, B' '
+ cat >expected <<\EXPECTED &&
+added in local
+ our 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE
+EXPECTED
+
+ git reset --hard initial &&
+ test_commit "add-not-a-b" "ONE" "AAA" &&
+ git merge-tree initial add-not-a-b initial >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'file add A, B (same)' '
+ cat >expected <<\EXPECTED &&
+added in both
+ our 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE
+ their 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE
+EXPECTED
+
+ git reset --hard initial &&
+ test_commit "add-a-b-same-A" "ONE" "AAA" &&
+ git reset --hard initial &&
+ test_commit "add-a-b-same-B" "ONE" "AAA" &&
+ git merge-tree initial add-a-b-same-A add-a-b-same-B >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'file add A, B (different)' '
+ cat >expected <<\EXPECTED &&
+added in both
+ our 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE
+ their 100644 ba629238ca89489f2b350e196ca445e09d8bb834 ONE
+@@ -1 +1,5 @@
++<<<<<<< .our
+ AAA
++=======
++BBB
++>>>>>>> .their
+EXPECTED
+
+ git reset --hard initial &&
+ test_commit "add-a-b-diff-A" "ONE" "AAA" &&
+ git reset --hard initial &&
+ test_commit "add-a-b-diff-B" "ONE" "BBB" &&
+ git merge-tree initial add-a-b-diff-A add-a-b-diff-B >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'file change A, !B' '
+ cat >expected <<\EXPECTED &&
+EXPECTED
+
+ git reset --hard initial &&
+ test_commit "change-a-not-b" "initial-file" "BBB" &&
+ git merge-tree initial change-a-not-b initial >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'file change !A, B' '
+ cat >expected <<\EXPECTED &&
+merged
+ result 100644 ba629238ca89489f2b350e196ca445e09d8bb834 initial-file
+ our 100644 e79c5e8f964493290a409888d5413a737e8e5dd5 initial-file
+@@ -1 +1 @@
+-initial
++BBB
+EXPECTED
+
+ git reset --hard initial &&
+ test_commit "change-not-a-b" "initial-file" "BBB" &&
+ git merge-tree initial initial change-not-a-b >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'file change A, B (same)' '
+ cat >expected <<\EXPECTED &&
+EXPECTED
+
+ git reset --hard initial &&
+ test_commit "change-a-b-same-A" "initial-file" "AAA" &&
+ git reset --hard initial &&
+ test_commit "change-a-b-same-B" "initial-file" "AAA" &&
+ git merge-tree initial change-a-b-same-A change-a-b-same-B >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'file change A, B (different)' '
+ cat >expected <<\EXPECTED &&
+changed in both
+ base 100644 e79c5e8f964493290a409888d5413a737e8e5dd5 initial-file
+ our 100644 43d5a8ed6ef6c00ff775008633f95787d088285d initial-file
+ their 100644 ba629238ca89489f2b350e196ca445e09d8bb834 initial-file
+@@ -1 +1,5 @@
++<<<<<<< .our
+ AAA
++=======
++BBB
++>>>>>>> .their
+EXPECTED
+
+ git reset --hard initial &&
+ test_commit "change-a-b-diff-A" "initial-file" "AAA" &&
+ git reset --hard initial &&
+ test_commit "change-a-b-diff-B" "initial-file" "BBB" &&
+ git merge-tree initial change-a-b-diff-A change-a-b-diff-B >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'file change A, B (mixed)' '
+ cat >expected <<\EXPECTED &&
+changed in both
+ base 100644 f4f1f998c7776568c4ff38f516d77fef9399b5a7 ONE
+ our 100644 af14c2c3475337c73759d561ef70b59e5c731176 ONE
+ their 100644 372d761493f524d44d59bd24700c3bdf914c973c ONE
+@@ -7,7 +7,11 @@
+ AAA
+ AAA
+ AAA
++<<<<<<< .our
+ BBB
++=======
++CCC
++>>>>>>> .their
+ AAA
+ AAA
+ AAA
+EXPECTED
+
+ git reset --hard initial &&
+ test_commit "change-a-b-mix-base" "ONE" "
+AAA
+AAA
+AAA
+AAA
+AAA
+AAA
+AAA
+AAA
+AAA
+AAA
+AAA
+AAA
+AAA
+AAA
+AAA" &&
+ test_commit "change-a-b-mix-A" "ONE" \
+ "$(sed -e "1{s/AAA/BBB/;}" -e "10{s/AAA/BBB/;}" <ONE)" &&
+ git reset --hard change-a-b-mix-base &&
+ test_commit "change-a-b-mix-B" "ONE" \
+ "$(sed -e "1{s/AAA/BBB/;}" -e "10{s/AAA/CCC/;}" <ONE)" &&
+ git merge-tree change-a-b-mix-base change-a-b-mix-A change-a-b-mix-B \
+ >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'file remove A, !B' '
+ cat >expected <<\EXPECTED &&
+removed in local
+ base 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE
+ their 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE
+EXPECTED
+
+ git reset --hard initial &&
+ test_commit "rm-a-not-b-base" "ONE" "AAA" &&
+ git rm ONE &&
+ git commit -m "rm-a-not-b" &&
+ git tag "rm-a-not-b" &&
+ git merge-tree rm-a-not-b-base rm-a-not-b rm-a-not-b-base >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'file remove !A, B' '
+ cat >expected <<\EXPECTED &&
+removed in remote
+ base 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE
+ our 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE
+@@ -1 +0,0 @@
+-AAA
+EXPECTED
+
+ git reset --hard initial &&
+ test_commit "rm-not-a-b-base" "ONE" "AAA" &&
+ git rm ONE &&
+ git commit -m "rm-not-a-b" &&
+ git tag "rm-not-a-b" &&
+ git merge-tree rm-a-not-b-base rm-a-not-b-base rm-a-not-b >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'file change A, remove B' '
+ cat >expected <<\EXPECTED &&
+removed in remote
+ base 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE
+ our 100644 ba629238ca89489f2b350e196ca445e09d8bb834 ONE
+@@ -1 +0,0 @@
+-BBB
+EXPECTED
+
+ git reset --hard initial &&
+ test_commit "change-a-rm-b-base" "ONE" "AAA" &&
+ test_commit "change-a-rm-b-A" "ONE" "BBB" &&
+ git reset --hard change-a-rm-b-base &&
+ git rm ONE &&
+ git commit -m "change-a-rm-b-B" &&
+ git tag "change-a-rm-b-B" &&
+ git merge-tree change-a-rm-b-base change-a-rm-b-A change-a-rm-b-B \
+ >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'file remove A, change B' '
+ cat >expected <<\EXPECTED &&
+removed in local
+ base 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE
+ their 100644 ba629238ca89489f2b350e196ca445e09d8bb834 ONE
+EXPECTED
+
+ git reset --hard initial &&
+ test_commit "rm-a-change-b-base" "ONE" "AAA" &&
+
+ git rm ONE &&
+ git commit -m "rm-a-change-b-A" &&
+ git tag "rm-a-change-b-A" &&
+ git reset --hard rm-a-change-b-base &&
+ test_commit "rm-a-change-b-B" "ONE" "BBB" &&
+ git merge-tree rm-a-change-b-base rm-a-change-b-A rm-a-change-b-B \
+ >actual &&
+ test_cmp expected actual
+'
+
+test_done
diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh
index 4360e77d31..fb3a270822 100755
--- a/t/t5302-pack-index.sh
+++ b/t/t5302-pack-index.sh
@@ -74,7 +74,7 @@ if msg=$(git verify-pack -v "test-3-${pack3}.pack" 2>&1) ||
then
test_set_prereq OFF64_T
else
- say "skipping tests concerning 64-bit offsets"
+ say "# skipping tests concerning 64-bit offsets"
fi
test_expect_success OFF64_T \
diff --git a/t/t5503-tagfollow.sh b/t/t5503-tagfollow.sh
index d5db75d826..bab1a536f5 100755
--- a/t/t5503-tagfollow.sh
+++ b/t/t5503-tagfollow.sh
@@ -6,7 +6,7 @@ test_description='test automatic tag following'
case $(uname -s) in
*MINGW*)
- say "GIT_DEBUG_SEND_PACK not supported - skipping tests"
+ skip_all="GIT_DEBUG_SEND_PACK not supported - skipping tests"
test_done
esac
diff --git a/t/t5522-pull-symlink.sh b/t/t5522-pull-symlink.sh
index 7206817ca1..298200fa4c 100755
--- a/t/t5522-pull-symlink.sh
+++ b/t/t5522-pull-symlink.sh
@@ -6,7 +6,7 @@ test_description='pulling from symlinked subdir'
if ! test_have_prereq SYMLINKS
then
- say 'Symbolic links not supported, skipping tests.'
+ skip_all='Symbolic links not supported, skipping tests.'
test_done
fi
diff --git a/t/t5540-http-push.sh b/t/t5540-http-push.sh
index 37fe875411..a266ca5636 100755
--- a/t/t5540-http-push.sh
+++ b/t/t5540-http-push.sh
@@ -11,7 +11,7 @@ This test runs various sanity checks on http-push.'
if git http-push > /dev/null 2>&1 || [ $? -eq 128 ]
then
- say "skipping test, USE_CURL_MULTI is not defined"
+ skip_all="skipping test, USE_CURL_MULTI is not defined"
test_done
fi
diff --git a/t/t5541-http-push.sh b/t/t5541-http-push.sh
index 17e1bdc5a8..504884b9f8 100755
--- a/t/t5541-http-push.sh
+++ b/t/t5541-http-push.sh
@@ -7,7 +7,7 @@ test_description='test smart pushing over http via http-backend'
. ./test-lib.sh
if test -n "$NO_CURL"; then
- say 'skipping test, git built without http support'
+ skip_all='skipping test, git built without http support'
test_done
fi
diff --git a/t/t5550-http-fetch.sh b/t/t5550-http-fetch.sh
index fc675b50ad..2fb48d09ed 100755
--- a/t/t5550-http-fetch.sh
+++ b/t/t5550-http-fetch.sh
@@ -4,7 +4,7 @@ test_description='test dumb fetching over http via static file'
. ./test-lib.sh
if test -n "$NO_CURL"; then
- say 'skipping test, git built without http support'
+ skip_all='skipping test, git built without http support'
test_done
fi
diff --git a/t/t5551-http-fetch.sh b/t/t5551-http-fetch.sh
index 7faa31a299..fd19121372 100755
--- a/t/t5551-http-fetch.sh
+++ b/t/t5551-http-fetch.sh
@@ -4,7 +4,7 @@ test_description='test smart fetching over http via http-backend'
. ./test-lib.sh
if test -n "$NO_CURL"; then
- say 'skipping test, git built without http support'
+ skip_all='skipping test, git built without http support'
test_done
fi
diff --git a/t/t5561-http-backend.sh b/t/t5561-http-backend.sh
index 8c6d0b2f20..b5d7fbc381 100755
--- a/t/t5561-http-backend.sh
+++ b/t/t5561-http-backend.sh
@@ -4,7 +4,7 @@ test_description='test git-http-backend'
. ./test-lib.sh
if test -n "$NO_CURL"; then
- say 'skipping test, git built without http support'
+ skip_all='skipping test, git built without http support'
test_done
fi
diff --git a/t/t5705-clone-2gb.sh b/t/t5705-clone-2gb.sh
index 8afbdd4de2..e4d1b6a0fa 100755
--- a/t/t5705-clone-2gb.sh
+++ b/t/t5705-clone-2gb.sh
@@ -4,7 +4,7 @@ test_description='Test cloning a repository larger than 2 gigabyte'
. ./test-lib.sh
test -z "$GIT_TEST_CLONE_2GB" &&
-say "Skipping expensive 2GB clone test; enable it with GIT_TEST_CLONE_2GB=t" &&
+skip_all="Skipping expensive 2GB clone test; enable it with GIT_TEST_CLONE_2GB=t" &&
test_done &&
exit
diff --git a/t/t5800-remote-helpers.sh b/t/t5800-remote-helpers.sh
index 4ee7b65ce6..637d8e97ac 100755
--- a/t/t5800-remote-helpers.sh
+++ b/t/t5800-remote-helpers.sh
@@ -15,7 +15,7 @@ if sys.hexversion < 0x02040000:
then
:
else
- say 'skipping git remote-testgit tests: requires Python 2.4 or newer'
+ skip_all='skipping git remote-testgit tests: requires Python 2.4 or newer'
test_done
fi
diff --git a/t/t6007-rev-list-cherry-pick-file.sh b/t/t6007-rev-list-cherry-pick-file.sh
index 4b8611ce20..b565638e92 100755
--- a/t/t6007-rev-list-cherry-pick-file.sh
+++ b/t/t6007-rev-list-cherry-pick-file.sh
@@ -32,6 +32,23 @@ test_expect_success setup '
git tag B
'
+cat >expect <<EOF
+<tags/B
+>tags/C
+EOF
+
+test_expect_success '--left-right' '
+ git rev-list --left-right B...C > actual &&
+ git name-rev --stdin --name-only --refs="*tags/*" \
+ < actual > actual.named &&
+ test_cmp actual.named expect
+'
+
+test_expect_success '--count' '
+ git rev-list --count B...C > actual &&
+ test "$(cat actual)" = 2
+'
+
test_expect_success '--cherry-pick foo comes up empty' '
test -z "$(git rev-list --left-right --cherry-pick B...C -- foo)"
'
@@ -54,4 +71,16 @@ test_expect_success '--cherry-pick with independent, but identical branches' '
HEAD...master -- foo)"
'
+cat >expect <<EOF
+1 2
+EOF
+
+# Insert an extra commit to break the symmetry
+test_expect_success '--count --left-right' '
+ git checkout branch &&
+ test_commit D &&
+ git rev-list --count --left-right B...D > actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t6018-rev-list-glob.sh b/t/t6018-rev-list-glob.sh
index 8d3fa7d014..58428d9f5c 100755
--- a/t/t6018-rev-list-glob.sh
+++ b/t/t6018-rev-list-glob.sh
@@ -34,7 +34,9 @@ test_expect_success 'setup' '
git checkout master &&
commit master2 &&
git tag foo/bar master &&
- git update-ref refs/remotes/foo/baz master
+ commit master3 &&
+ git update-ref refs/remotes/foo/baz master &&
+ commit master4
'
test_expect_success 'rev-parse --glob=refs/heads/subspace/*' '
@@ -162,6 +164,13 @@ test_expect_success 'rev-list --branches=subspace' '
compare rev-list "subspace/one subspace/two" "--branches=subspace"
'
+
+test_expect_success 'rev-list --branches' '
+
+ compare rev-list "master subspace-x someref other/three subspace/one subspace/two" "--branches"
+
+'
+
test_expect_success 'rev-list --glob=heads/someref/* master' '
compare rev-list "master" "--glob=heads/someref/* master"
@@ -186,6 +195,12 @@ test_expect_success 'rev-list --tags=foo' '
'
+test_expect_success 'rev-list --tags' '
+
+ compare rev-list "foo/bar" "--tags"
+
+'
+
test_expect_success 'rev-list --remotes=foo' '
compare rev-list "foo/baz" "--remotes=foo"
diff --git a/t/t6035-merge-dir-to-symlink.sh b/t/t6035-merge-dir-to-symlink.sh
index 3202e1de6d..cd3190c4a6 100755
--- a/t/t6035-merge-dir-to-symlink.sh
+++ b/t/t6035-merge-dir-to-symlink.sh
@@ -5,7 +5,7 @@ test_description='merging when a directory was replaced with a symlink'
if ! test_have_prereq SYMLINKS
then
- say 'Symbolic links not supported, skipping tests.'
+ skip_all='Symbolic links not supported, skipping tests.'
test_done
fi
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index 73dbc4360b..ac943f5eee 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -583,7 +583,7 @@ test_expect_success \
# subsequent tests require gpg; check if it is available
gpg --version >/dev/null 2>/dev/null
if [ $? -eq 127 ]; then
- say "gpg not found - skipping tag signing and verification tests"
+ say "# gpg not found - skipping tag signing and verification tests"
else
# As said here: http://www.gnupg.org/documentation/faqs.html#q6.19
# the gpg version 1.0.6 didn't parse trust packets correctly, so for
diff --git a/t/t7005-editor.sh b/t/t7005-editor.sh
index fe60d699a3..26ddf9d496 100755
--- a/t/t7005-editor.sh
+++ b/t/t7005-editor.sh
@@ -113,7 +113,7 @@ done
if ! echo 'echo space > "$1"' > "e space.sh"
then
- say "Skipping; FS does not support spaces in filenames"
+ skip_all="Skipping; FS does not support spaces in filenames"
test_done
fi
diff --git a/t/t7006-pager.sh b/t/t7006-pager.sh
index 9215c2ff56..71d3ceff8f 100755
--- a/t/t7006-pager.sh
+++ b/t/t7006-pager.sh
@@ -3,6 +3,7 @@
test_description='Test automatic use of a pager.'
. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-pager.sh
cleanup_fail() {
echo >&2 cleanup failed
@@ -36,7 +37,7 @@ then
}
test_set_prereq TTY
else
- say no usable terminal, so skipping some tests
+ say "# no usable terminal, so skipping some tests"
fi
test_expect_success 'setup' '
@@ -158,18 +159,9 @@ test_expect_success 'color when writing to a file intended for a pager' '
colorful colorful.log
'
-test_expect_success 'determine default pager' '
- unset PAGER GIT_PAGER;
- test_might_fail git config --unset core.pager ||
- cleanup_fail &&
-
- less=$(git var GIT_PAGER) &&
- test -n "$less"
-'
-
-if expr "$less" : '[a-z][a-z]*$' >/dev/null && test_have_prereq TTY
+if test_have_prereq SIMPLEPAGER && test_have_prereq TTY
then
- test_set_prereq SIMPLEPAGER
+ test_set_prereq SIMPLEPAGERTTY
fi
# Use this helper to make it easy for the caller of your
@@ -207,7 +199,7 @@ parse_args() {
test_default_pager() {
parse_args "$@"
- $test_expectation SIMPLEPAGER "$cmd - default pager is used by default" "
+ $test_expectation SIMPLEPAGERTTY "$cmd - default pager is used by default" "
unset PAGER GIT_PAGER;
test_might_fail git config --unset core.pager &&
rm -f default_pager_used ||
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index 97ff074da7..d9f2785993 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -42,7 +42,8 @@ test_expect_success 'setup - hide init subdirectory' '
'
test_expect_success 'setup - repository to add submodules to' '
- git init addtest
+ git init addtest &&
+ git init addtest-ignore
'
# The 'submodule add' tests need some repository to add as a submodule.
@@ -85,6 +86,27 @@ test_expect_success 'submodule add' '
test_cmp empty untracked
'
+test_expect_success 'submodule add to .gitignored path' '
+ echo "refs/heads/master" >expect &&
+ >empty &&
+
+ (
+ cd addtest-ignore &&
+ # Does not use test_commit due to the ignore
+ echo "*" > .gitignore &&
+ git add --force .gitignore &&
+ git commit -m"Ignore everything" &&
+ git submodule add "$submodurl" submod &&
+ git submodule init
+ ) &&
+
+ rm -f heads head untracked &&
+ inspect addtest/submod ../.. &&
+ test_cmp expect heads &&
+ test_cmp expect head &&
+ test_cmp empty untracked
+'
+
test_expect_success 'submodule add --branch' '
echo "refs/heads/initial" >expect-head &&
cat <<-\EOF >expect-heads &&
diff --git a/t/t7405-submodule-merge.sh b/t/t7405-submodule-merge.sh
index 9a21f783d3..4a7b8933f4 100755
--- a/t/t7405-submodule-merge.sh
+++ b/t/t7405-submodule-merge.sh
@@ -45,7 +45,7 @@ test_expect_success setup '
git commit -m sub-b) &&
git add sub &&
test_tick &&
- git commit -m b
+ git commit -m b &&
git checkout -b c a &&
git merge -s ours b &&
diff --git a/t/t7508-status.sh b/t/t7508-status.sh
index 9e081073fb..a72fe3ae64 100755
--- a/t/t7508-status.sh
+++ b/t/t7508-status.sh
@@ -808,4 +808,131 @@ test_expect_success POSIXPERM 'status succeeds in a read-only repository' '
(exit $status)
'
+cat > expect << EOF
+# On branch master
+# Changed but not updated:
+# (use "git add <file>..." to update what will be committed)
+# (use "git checkout -- <file>..." to discard changes in working directory)
+#
+# modified: dir1/modified
+#
+# Untracked files:
+# (use "git add <file>..." to include in what will be committed)
+#
+# dir1/untracked
+# dir2/modified
+# dir2/untracked
+# expect
+# output
+# untracked
+no changes added to commit (use "git add" and/or "git commit -a")
+EOF
+
+test_expect_success '--ignore-submodules=untracked suppresses submodules with untracked content' '
+ echo modified > sm/untracked &&
+ git status --ignore-submodules=untracked > output &&
+ test_cmp expect output
+'
+
+test_expect_success '--ignore-submodules=dirty suppresses submodules with untracked content' '
+ git status --ignore-submodules=dirty > output &&
+ test_cmp expect output
+'
+
+test_expect_success '--ignore-submodules=dirty suppresses submodules with modified content' '
+ echo modified > sm/foo &&
+ git status --ignore-submodules=dirty > output &&
+ test_cmp expect output
+'
+
+cat > expect << EOF
+# On branch master
+# Changed but not updated:
+# (use "git add <file>..." to update what will be committed)
+# (use "git checkout -- <file>..." to discard changes in working directory)
+# (commit or discard the untracked or modified content in submodules)
+#
+# modified: dir1/modified
+# modified: sm (modified content)
+#
+# Untracked files:
+# (use "git add <file>..." to include in what will be committed)
+#
+# dir1/untracked
+# dir2/modified
+# dir2/untracked
+# expect
+# output
+# untracked
+no changes added to commit (use "git add" and/or "git commit -a")
+EOF
+
+test_expect_success "--ignore-submodules=untracked doesn't suppress submodules with modified content" '
+ git status --ignore-submodules=untracked > output &&
+ test_cmp expect output
+'
+
+head2=$(cd sm && git commit -q -m "2nd commit" foo && git rev-parse --short=7 --verify HEAD)
+
+cat > expect << EOF
+# On branch master
+# Changed but not updated:
+# (use "git add <file>..." to update what will be committed)
+# (use "git checkout -- <file>..." to discard changes in working directory)
+#
+# modified: dir1/modified
+# modified: sm (new commits)
+#
+# Submodules changed but not updated:
+#
+# * sm $head...$head2 (1):
+# > 2nd commit
+#
+# Untracked files:
+# (use "git add <file>..." to include in what will be committed)
+#
+# dir1/untracked
+# dir2/modified
+# dir2/untracked
+# expect
+# output
+# untracked
+no changes added to commit (use "git add" and/or "git commit -a")
+EOF
+
+test_expect_success "--ignore-submodules=untracked doesn't suppress submodule summary" '
+ git status --ignore-submodules=untracked > output &&
+ test_cmp expect output
+'
+
+test_expect_success "--ignore-submodules=dirty doesn't suppress submodule summary" '
+ git status --ignore-submodules=dirty > output &&
+ test_cmp expect output
+'
+
+cat > expect << EOF
+# On branch master
+# Changed but not updated:
+# (use "git add <file>..." to update what will be committed)
+# (use "git checkout -- <file>..." to discard changes in working directory)
+#
+# modified: dir1/modified
+#
+# Untracked files:
+# (use "git add <file>..." to include in what will be committed)
+#
+# dir1/untracked
+# dir2/modified
+# dir2/untracked
+# expect
+# output
+# untracked
+no changes added to commit (use "git add" and/or "git commit -a")
+EOF
+
+test_expect_success "--ignore-submodules=all suppresses submodule summary" '
+ git status --ignore-submodules=all > output &&
+ test_cmp expect output
+'
+
test_done
diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh
index 1de83ef98f..196827e7ea 100755
--- a/t/t7800-difftool.sh
+++ b/t/t7800-difftool.sh
@@ -11,7 +11,7 @@ Testing basic diff tool invocation
. ./test-lib.sh
if ! test_have_prereq PERL; then
- say 'skipping difftool tests, perl not available'
+ skip_all='skipping difftool tests, perl not available'
test_done
fi
diff --git a/t/t7002-grep.sh b/t/t7810-grep.sh
index 8a6322765c..8a6322765c 100755
--- a/t/t7002-grep.sh
+++ b/t/t7810-grep.sh
diff --git a/t/t7811-grep-open.sh b/t/t7811-grep-open.sh
new file mode 100755
index 0000000000..568a6f2b69
--- /dev/null
+++ b/t/t7811-grep-open.sh
@@ -0,0 +1,168 @@
+#!/bin/sh
+
+test_description='git grep --open-files-in-pager
+'
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-pager.sh
+unset PAGER GIT_PAGER
+
+test_expect_success 'setup' '
+ test_commit initial grep.h "
+enum grep_pat_token {
+ GREP_PATTERN,
+ GREP_PATTERN_HEAD,
+ GREP_PATTERN_BODY,
+ GREP_AND,
+ GREP_OPEN_PAREN,
+ GREP_CLOSE_PAREN,
+ GREP_NOT,
+ GREP_OR,
+};" &&
+
+ test_commit add-user revision.c "
+ }
+ if (seen_dashdash)
+ read_pathspec_from_stdin(revs, &sb, prune);
+ strbuf_release(&sb);
+}
+
+static void add_grep(struct rev_info *revs, const char *ptn, enum grep_pat_token what)
+{
+ append_grep_pattern(&revs->grep_filter, ptn, \"command line\", 0, what);
+" &&
+
+ mkdir subdir &&
+ test_commit subdir subdir/grep.c "enum grep_pat_token" &&
+
+ test_commit uninteresting unrelated "hello, world" &&
+
+ echo GREP_PATTERN >untracked
+'
+
+test_expect_success SIMPLEPAGER 'git grep -O' '
+ cat >$less <<-\EOF &&
+ #!/bin/sh
+ printf "%s\n" "$@" >pager-args
+ EOF
+ chmod +x $less &&
+ cat >expect.less <<-\EOF &&
+ +/*GREP_PATTERN
+ grep.h
+ EOF
+ echo grep.h >expect.notless &&
+ >empty &&
+
+ PATH=.:$PATH git grep -O GREP_PATTERN >out &&
+ {
+ test_cmp expect.less pager-args ||
+ test_cmp expect.notless pager-args
+ } &&
+ test_cmp empty out
+'
+
+test_expect_success 'git grep -O --cached' '
+ test_must_fail git grep --cached -O GREP_PATTERN >out 2>msg &&
+ grep open-files-in-pager msg
+'
+
+test_expect_success 'git grep -O --no-index' '
+ rm -f expect.less pager-args out &&
+ cat >expect <<-\EOF &&
+ grep.h
+ untracked
+ EOF
+ >empty &&
+
+ (
+ GIT_PAGER='\''printf "%s\n" >pager-args'\'' &&
+ export GIT_PAGER &&
+ git grep --no-index -O GREP_PATTERN >out
+ ) &&
+ test_cmp expect pager-args &&
+ test_cmp empty out
+'
+
+test_expect_success 'setup: fake "less"' '
+ cat >less <<-\EOF &&
+ #!/bin/sh
+ printf "%s\n" "$@" >actual
+ EOF
+ chmod +x less
+'
+
+test_expect_success 'git grep -O jumps to line in less' '
+ cat >expect <<-\EOF &&
+ +/*GREP_PATTERN
+ grep.h
+ EOF
+ >empty &&
+
+ GIT_PAGER=./less git grep -O GREP_PATTERN >out &&
+ test_cmp expect actual &&
+ test_cmp empty out &&
+
+ git grep -O./less GREP_PATTERN >out2 &&
+ test_cmp expect actual &&
+ test_cmp empty out2
+'
+
+test_expect_success 'modified file' '
+ rm -f actual &&
+ cat >expect <<-\EOF &&
+ +/*enum grep_pat_token
+ grep.h
+ revision.c
+ subdir/grep.c
+ unrelated
+ EOF
+ >empty &&
+
+ echo "enum grep_pat_token" >unrelated &&
+ test_when_finished "git checkout HEAD unrelated" &&
+ GIT_PAGER=./less git grep -F -O "enum grep_pat_token" >out &&
+ test_cmp expect actual &&
+ test_cmp empty out
+'
+
+test_config() {
+ git config "$1" "$2" &&
+ test_when_finished "git config --unset $1"
+}
+
+test_expect_success 'copes with color settings' '
+ rm -f actual &&
+ echo grep.h >expect &&
+ test_config color.grep always &&
+ test_config color.grep.filename yellow &&
+ test_config color.grep.separator green &&
+ git grep -O'\''printf "%s\n" >actual'\'' GREP_AND &&
+ test_cmp expect actual
+'
+
+test_expect_success 'run from subdir' '
+ rm -f actual &&
+ echo grep.c >expect &&
+ >empty &&
+
+ (
+ cd subdir &&
+ export GIT_PAGER &&
+ GIT_PAGER='\''printf "%s\n" >../args'\'' &&
+ git grep -O "enum grep_pat_token" >../out &&
+ git grep -O"pwd >../dir; :" "enum grep_pat_token" >../out2
+ ) &&
+ case $(cat dir) in
+ *subdir)
+ : good
+ ;;
+ *)
+ false
+ ;;
+ esac &&
+ test_cmp expect args &&
+ test_cmp empty out &&
+ test_cmp empty out2
+'
+
+test_done
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index 0b8a591507..23597cc407 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -4,7 +4,7 @@ test_description='git send-email'
. ./test-lib.sh
if ! test_have_prereq PERL; then
- say 'skipping git send-email tests, perl not available'
+ skip_all='skipping git send-email tests, perl not available'
test_done
fi
@@ -58,7 +58,7 @@ test_no_confirm () {
# Exit immediately to prevent hang if a no-confirm test fails
check_no_confirm () {
test -f no_confirm_okay || {
- say 'No confirm test failed; skipping remaining tests to prevent hanging'
+ skip_all='confirm test failed; skipping remaining tests to prevent hanging'
test_done
}
}
@@ -943,7 +943,7 @@ test_expect_success 'asks about and fixes 8bit encodings' '
grep "do not declare a Content-Transfer-Encoding" stdout &&
grep email-using-8bit stdout &&
grep "Which 8bit encoding" stdout &&
- grep "Content\\|MIME" msgtxt1 >actual &&
+ egrep "Content|MIME" msgtxt1 >actual &&
test_cmp actual content-type-decl
'
@@ -954,7 +954,7 @@ test_expect_success 'sendemail.8bitEncoding works' '
git send-email --from=author@example.com --to=nobody@example.com \
--smtp-server="$(pwd)/fake.sendmail" \
email-using-8bit >stdout &&
- grep "Content\\|MIME" msgtxt1 >actual &&
+ egrep "Content|MIME" msgtxt1 >actual &&
test_cmp actual content-type-decl
'
@@ -966,7 +966,7 @@ test_expect_success '--8bit-encoding overrides sendemail.8bitEncoding' '
--smtp-server="$(pwd)/fake.sendmail" \
--8bit-encoding=UTF-8 \
email-using-8bit >stdout &&
- grep "Content\\|MIME" msgtxt1 >actual &&
+ egrep "Content|MIME" msgtxt1 >actual &&
test_cmp actual content-type-decl
'
diff --git a/t/t9100-git-svn-basic.sh b/t/t9100-git-svn-basic.sh
index 570e0359e4..13766ab160 100755
--- a/t/t9100-git-svn-basic.sh
+++ b/t/t9100-git-svn-basic.sh
@@ -15,7 +15,7 @@ case "$GIT_SVN_LC_ALL" in
test_set_prereq UTF8
;;
*)
- say "UTF-8 locale not set, some tests skipped ($GIT_SVN_LC_ALL)"
+ say "# UTF-8 locale not set, some tests skipped ($GIT_SVN_LC_ALL)"
;;
esac
diff --git a/t/t9118-git-svn-funky-branch-names.sh b/t/t9118-git-svn-funky-branch-names.sh
index 7d7acc30b4..63fc982c8c 100755
--- a/t/t9118-git-svn-funky-branch-names.sh
+++ b/t/t9118-git-svn-funky-branch-names.sh
@@ -28,48 +28,52 @@ test_expect_success 'setup svnrepo' '
svn_cmd cp -m "trailing .lock" "$svnrepo/pr ject/trunk" \
"$svnrepo/pr ject/branches/trailing_dotlock.lock" &&
svn_cmd cp -m "reflog" "$svnrepo/pr ject/trunk" \
- "$svnrepo/pr ject/branches/not-a@{0}reflog" &&
+ "$svnrepo/pr ject/branches/not-a%40{0}reflog" &&
start_httpd
'
test_expect_success 'test clone with funky branch names' '
git svn clone -s "$svnrepo/pr ject" project &&
- cd project &&
+ (
+ cd project &&
git rev-parse "refs/remotes/fun%20plugin" &&
git rev-parse "refs/remotes/more%20fun%20plugin!" &&
git rev-parse "refs/remotes/$scary_ref" &&
git rev-parse "refs/remotes/%2Eleading_dot" &&
git rev-parse "refs/remotes/trailing_dot%2E" &&
git rev-parse "refs/remotes/trailing_dotlock%2Elock" &&
- git rev-parse "refs/remotes/not-a%40{0}reflog" &&
- cd ..
+ git rev-parse "refs/remotes/not-a%40{0}reflog"
+ )
'
test_expect_success 'test dcommit to funky branch' "
- cd project &&
- git reset --hard 'refs/remotes/more%20fun%20plugin!' &&
- echo hello >> foo &&
- git commit -m 'hello' -- foo &&
- git svn dcommit &&
- cd ..
+ (
+ cd project &&
+ git reset --hard 'refs/remotes/more%20fun%20plugin!' &&
+ echo hello >> foo &&
+ git commit -m 'hello' -- foo &&
+ git svn dcommit
+ )
"
test_expect_success 'test dcommit to scary branch' '
- cd project &&
- git reset --hard "refs/remotes/$scary_ref" &&
- echo urls are scary >> foo &&
- git commit -m "eep" -- foo &&
- git svn dcommit &&
- cd ..
+ (
+ cd project &&
+ git reset --hard "refs/remotes/$scary_ref" &&
+ echo urls are scary >> foo &&
+ git commit -m "eep" -- foo &&
+ git svn dcommit
+ )
'
test_expect_success 'test dcommit to trailing_dotlock branch' '
- cd project &&
- git reset --hard "refs/remotes/trailing_dotlock%2Elock" &&
- echo who names branches like this anyway? >> foo &&
- git commit -m "bar" -- foo &&
- git svn dcommit &&
- cd ..
+ (
+ cd project &&
+ git reset --hard "refs/remotes/trailing_dotlock%2Elock" &&
+ echo who names branches like this anyway? >> foo &&
+ git commit -m "bar" -- foo &&
+ git svn dcommit
+ )
'
stop_httpd
diff --git a/t/t9119-git-svn-info.sh b/t/t9119-git-svn-info.sh
index a9a558d292..5fb94fb3d6 100755
--- a/t/t9119-git-svn-info.sh
+++ b/t/t9119-git-svn-info.sh
@@ -13,7 +13,7 @@ case $v in
1.[456].*)
;;
*)
- say "skipping svn-info test (SVN version: $v not supported)"
+ skip_all="skipping svn-info test (SVN version: $v not supported)"
test_done
;;
esac
diff --git a/t/t9129-git-svn-i18n-commitencoding.sh b/t/t9129-git-svn-i18n-commitencoding.sh
index 1e9a2eb12b..8cfdfe790f 100755
--- a/t/t9129-git-svn-i18n-commitencoding.sh
+++ b/t/t9129-git-svn-i18n-commitencoding.sh
@@ -23,7 +23,7 @@ if test -n "$a_utf8_locale"
then
test_set_prereq UTF8
else
- say "UTF-8 locale not available, some tests are skipped"
+ say "# UTF-8 locale not available, some tests are skipped"
fi
compare_svn_head_with () {
diff --git a/t/t9143-git-svn-gc.sh b/t/t9143-git-svn-gc.sh
index 99f69c6a0b..337ea59711 100755
--- a/t/t9143-git-svn-gc.sh
+++ b/t/t9143-git-svn-gc.sh
@@ -43,7 +43,7 @@ then
gunzip .git/svn/refs/remotes/git-svn/unhandled.log.gz
'
else
- say "Perl Compress::Zlib unavailable, skipping gunzip test"
+ say "# Perl Compress::Zlib unavailable, skipping gunzip test"
fi
test_expect_success 'git svn gc does not change unhandled.log files' '
diff --git a/t/t9200-git-cvsexportcommit.sh b/t/t9200-git-cvsexportcommit.sh
index 61bcb8fc86..ee39b36d78 100755
--- a/t/t9200-git-cvsexportcommit.sh
+++ b/t/t9200-git-cvsexportcommit.sh
@@ -7,14 +7,14 @@ test_description='Test export of commits to CVS'
. ./test-lib.sh
if ! test_have_prereq PERL; then
- say 'skipping git cvsexportcommit tests, perl not available'
+ skip_all='skipping git cvsexportcommit tests, perl not available'
test_done
fi
cvs >/dev/null 2>&1
if test $? -ne 1
then
- say 'skipping git cvsexportcommit tests, cvs not found'
+ skip_all='skipping git cvsexportcommit tests, cvs not found'
test_done
fi
diff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh
index 86395065cf..36c457e7f2 100755
--- a/t/t9400-git-cvsserver-server.sh
+++ b/t/t9400-git-cvsserver-server.sh
@@ -11,17 +11,17 @@ cvs CLI client via git-cvsserver server'
. ./test-lib.sh
if ! test_have_prereq PERL; then
- say 'skipping git cvsserver tests, perl not available'
+ skip_all='skipping git cvsserver tests, perl not available'
test_done
fi
cvs >/dev/null 2>&1
if test $? -ne 1
then
- say 'skipping git-cvsserver tests, cvs not found'
+ skip_all='skipping git-cvsserver tests, cvs not found'
test_done
fi
"$PERL_PATH" -e 'use DBI; use DBD::SQLite' >/dev/null 2>&1 || {
- say 'skipping git-cvsserver tests, Perl SQLite interface unavailable'
+ skip_all='skipping git-cvsserver tests, Perl SQLite interface unavailable'
test_done
}
diff --git a/t/t9401-git-cvsserver-crlf.sh b/t/t9401-git-cvsserver-crlf.sh
index ed7b513f3e..925bd0fbed 100755
--- a/t/t9401-git-cvsserver-crlf.sh
+++ b/t/t9401-git-cvsserver-crlf.sh
@@ -41,16 +41,16 @@ not_present() {
cvs >/dev/null 2>&1
if test $? -ne 1
then
- say 'skipping git-cvsserver tests, cvs not found'
+ skip_all='skipping git-cvsserver tests, cvs not found'
test_done
fi
if ! test_have_prereq PERL
then
- say 'skipping git-cvsserver tests, perl not available'
+ skip_all='skipping git-cvsserver tests, perl not available'
test_done
fi
"$PERL_PATH" -e 'use DBI; use DBD::SQLite' >/dev/null 2>&1 || {
- say 'skipping git-cvsserver tests, Perl SQLite interface unavailable'
+ skip_all='skipping git-cvsserver tests, Perl SQLite interface unavailable'
test_done
}
diff --git a/t/t9600-cvsimport.sh b/t/t9600-cvsimport.sh
index b572ce3ab7..2eff9cd68c 100755
--- a/t/t9600-cvsimport.sh
+++ b/t/t9600-cvsimport.sh
@@ -4,7 +4,7 @@ test_description='git cvsimport basic tests'
. ./lib-cvs.sh
if ! test_have_prereq PERL; then
- say 'skipping git cvsimport tests, perl not available'
+ skip_all='skipping git cvsimport tests, perl not available'
test_done
fi
diff --git a/t/t9700-perl-git.sh b/t/t9700-perl-git.sh
index 8686086dde..3787186703 100755
--- a/t/t9700-perl-git.sh
+++ b/t/t9700-perl-git.sh
@@ -7,12 +7,12 @@ test_description='perl interface (Git.pm)'
. ./test-lib.sh
if ! test_have_prereq PERL; then
- say 'skipping perl interface tests, perl not available'
+ skip_all='skipping perl interface tests, perl not available'
test_done
fi
"$PERL_PATH" -MTest::More -e 0 2>/dev/null || {
- say "Perl Test::More unavailable, skipping test"
+ skip_all="Perl Test::More unavailable, skipping test"
test_done
}
@@ -46,6 +46,9 @@ test_expect_success \
git config --add test.int 2k
'
+# The external test will outputs its own plan
+test_external_has_tap=1
+
test_external_without_stderr \
'Perl API' \
"$PERL_PATH" "$TEST_DIRECTORY"/t9700/test.pl
diff --git a/t/t9700/test.pl b/t/t9700/test.pl
index 666722d9bf..671f38db2b 100755
--- a/t/t9700/test.pl
+++ b/t/t9700/test.pl
@@ -7,6 +7,13 @@ use strict;
use Test::More qw(no_plan);
+BEGIN {
+ # t9700-perl-git.sh kicks off our testing, so we have to go from
+ # there.
+ Test::More->builder->current_test(1);
+ Test::More->builder->no_ending(1);
+}
+
use Cwd;
use File::Basename;
@@ -105,3 +112,8 @@ my $last_commit = $r2->command_oneline(qw(rev-parse --verify HEAD));
like($last_commit, qr/^[0-9a-fA-F]{40}$/, 'rev-parse returned hash');
my $dir_commit = $r2->command_oneline('log', '-n1', '--pretty=format:%H', '.');
isnt($last_commit, $dir_commit, 'log . does not show last commit');
+
+printf "1..%d\n", Test::More->builder->current_test;
+
+my $is_passing = eval { Test::More->is_passing };
+exit($is_passing ? 0 : 1) unless $@ =~ /Can't locate object method/;
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 367f0537cd..db8371cb17 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -160,7 +160,7 @@ if test -n "$color"; then
*) test -n "$quiet" && return;;
esac
shift
- printf "* %s" "$*"
+ printf "%s" "$*"
tput sgr0
echo
)
@@ -169,7 +169,7 @@ else
say_color() {
test -z "$1" && test -n "$quiet" && return
shift
- echo "* $*"
+ echo "$*"
}
fi
@@ -206,6 +206,8 @@ test_fixed=0
test_broken=0
test_success=0
+test_external_has_tap=0
+
die () {
code=$?
if test -n "$GIT_EXIT_OK"
@@ -339,25 +341,25 @@ test_have_prereq () {
test_ok_ () {
test_success=$(($test_success + 1))
- say_color "" " ok $test_count: $@"
+ say_color "" "ok $test_count - $@"
}
test_failure_ () {
test_failure=$(($test_failure + 1))
- say_color error "FAIL $test_count: $1"
+ say_color error "not ok - $test_count $1"
shift
- echo "$@" | sed -e 's/^/ /'
+ echo "$@" | sed -e 's/^/# /'
test "$immediate" = "" || { GIT_EXIT_OK=t; exit 1; }
}
test_known_broken_ok_ () {
test_fixed=$(($test_fixed+1))
- say_color "" " FIXED $test_count: $@"
+ say_color "" "ok $test_count - $@ # TODO known breakage"
}
test_known_broken_failure_ () {
test_broken=$(($test_broken+1))
- say_color skip " still broken $test_count: $@"
+ say_color skip "not ok $test_count - $@ # TODO known breakage"
}
test_debug () {
@@ -369,6 +371,9 @@ test_run_ () {
eval >&3 2>&4 "$1"
eval_ret=$?
eval >&3 2>&4 "$test_cleanup"
+ if test "$verbose" = "t" && test -n "$HARNESS_ACTIVE"; then
+ echo ""
+ fi
return 0
}
@@ -380,6 +385,7 @@ test_skip () {
case $this_test.$test_count in
$skp)
to_skip=t
+ break
esac
done
if test -z "$to_skip" && test -n "$prereq" &&
@@ -390,7 +396,7 @@ test_skip () {
case "$to_skip" in
t)
say_color skip >&3 "skipping test: $@"
- say_color skip "skip $test_count: $1"
+ say_color skip "ok $test_count # skip $1"
: true
;;
*)
@@ -456,7 +462,7 @@ test_expect_code () {
# test_external runs external test scripts that provide continuous
# test output about their progress, and succeeds/fails on
# zero/non-zero exit code. It outputs the test output on stdout even
-# in non-verbose mode, and announces the external script with "* run
+# in non-verbose mode, and announces the external script with "# run
# <n>: ..." before running it. When providing relative paths, keep in
# mind that all scripts run in "trash directory".
# Usage: test_external description command arguments...
@@ -471,7 +477,7 @@ test_external () {
then
# Announce the script to reduce confusion about the
# test output that follows.
- say_color "" " run $test_count: $descr ($*)"
+ say_color "" "# run $test_count: $descr ($*)"
# Export TEST_DIRECTORY, TRASH_DIRECTORY and GIT_TEST_LONG
# to be able to use them in script
export TEST_DIRECTORY TRASH_DIRECTORY GIT_TEST_LONG
@@ -481,9 +487,19 @@ test_external () {
"$@" 2>&4
if [ "$?" = 0 ]
then
- test_ok_ "$descr"
+ if test $test_external_has_tap -eq 0; then
+ test_ok_ "$descr"
+ else
+ say_color "" "# test_external test $descr was ok"
+ test_success=$(($test_success + 1))
+ fi
else
- test_failure_ "$descr" "$@"
+ if test $test_external_has_tap -eq 0; then
+ test_failure_ "$descr" "$@"
+ else
+ say_color error "# test_external test $descr failed: $@"
+ test_failure=$(($test_failure + 1))
+ fi
fi
fi
}
@@ -499,19 +515,30 @@ test_external_without_stderr () {
[ -f "$stderr" ] || error "Internal error: $stderr disappeared."
descr="no stderr: $1"
shift
- say >&3 "expecting no stderr from previous command"
+ say >&3 "# expecting no stderr from previous command"
if [ ! -s "$stderr" ]; then
rm "$stderr"
- test_ok_ "$descr"
+
+ if test $test_external_has_tap -eq 0; then
+ test_ok_ "$descr"
+ else
+ say_color "" "# test_external_without_stderr test $descr was ok"
+ test_success=$(($test_success + 1))
+ fi
else
if [ "$verbose" = t ]; then
- output=`echo; echo Stderr is:; cat "$stderr"`
+ output=`echo; echo "# Stderr is:"; cat "$stderr"`
else
output=
fi
# rm first in case test_failure exits.
rm "$stderr"
- test_failure_ "$descr" "$@" "$output"
+ if test $test_external_has_tap -eq 0; then
+ test_failure_ "$descr" "$@" "$output"
+ else
+ say_color error "# test_external_without_stderr test $descr failed: $@: $output"
+ test_failure=$(($test_failure + 1))
+ fi
fi
}
@@ -620,18 +647,24 @@ test_done () {
if test "$test_fixed" != 0
then
- say_color pass "fixed $test_fixed known breakage(s)"
+ say_color pass "# fixed $test_fixed known breakage(s)"
fi
if test "$test_broken" != 0
then
- say_color error "still have $test_broken known breakage(s)"
+ say_color error "# still have $test_broken known breakage(s)"
msg="remaining $(($test_count-$test_broken)) test(s)"
else
msg="$test_count test(s)"
fi
case "$test_failure" in
0)
- say_color pass "passed all $msg"
+ # Maybe print SKIP message
+ [ -z "$skip_all" ] || skip_all=" # SKIP $skip_all"
+
+ if test $test_external_has_tap -eq 0; then
+ say_color pass "# passed all $msg"
+ say "1..$test_count$skip_all"
+ fi
test -d "$remove_trash" &&
cd "$(dirname "$remove_trash")" &&
@@ -640,7 +673,11 @@ test_done () {
exit 0 ;;
*)
- say_color error "failed $test_failure among $msg"
+ if test $test_external_has_tap -eq 0; then
+ say_color error "# failed $test_failure among $msg"
+ say "1..$test_count"
+ fi
+
exit 1 ;;
esac
@@ -793,18 +830,10 @@ this_test=${0##*/}
this_test=${this_test%%-*}
for skp in $GIT_SKIP_TESTS
do
- to_skip=
- for skp in $GIT_SKIP_TESTS
- do
- case "$this_test" in
- $skp)
- to_skip=t
- esac
- done
- case "$to_skip" in
- t)
+ case "$this_test" in
+ $skp)
say_color skip >&3 "skipping test $this_test altogether"
- say_color skip "skip all tests in $this_test"
+ skip_all="skip all tests in $this_test"
test_done
esac
done
diff --git a/test-date.c b/test-date.c
index a9e705f79a..6bcd5b03c0 100644
--- a/test-date.c
+++ b/test-date.c
@@ -20,13 +20,16 @@ static void parse_dates(char **argv, struct timeval *now)
{
for (; *argv; argv++) {
char result[100];
- time_t t;
+ unsigned long t;
+ int tz;
result[0] = 0;
parse_date(*argv, result, sizeof(result));
- t = strtoul(result, NULL, 0);
- printf("%s -> %s\n", *argv,
- t ? show_date(t, 0, DATE_ISO8601) : "bad");
+ if (sscanf(result, "%lu %d", &t, &tz) == 2)
+ printf("%s -> %s\n",
+ *argv, show_date(t, tz, DATE_ISO8601));
+ else
+ printf("%s -> bad\n", *argv);
}
}
diff --git a/transport-helper.c b/transport-helper.c
index 0381de5368..191fbf798a 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -727,10 +727,10 @@ static int push_refs_with_export(struct transport *transport,
private = apply_refspecs(data->refspecs, data->refspec_nr, ref->name);
if (private && !get_sha1(private, sha1)) {
strbuf_addf(&buf, "^%s", private);
- string_list_append(strbuf_detach(&buf, NULL), &revlist_args);
+ string_list_append(&revlist_args, strbuf_detach(&buf, NULL));
}
- string_list_append(ref->name, &revlist_args);
+ string_list_append(&revlist_args, ref->name);
}
diff --git a/url.c b/url.c
index bf5bb9c88f..230623657a 100644
--- a/url.c
+++ b/url.c
@@ -103,12 +103,12 @@ static char *url_decode_internal(const char **query, const char *stop_at, struct
char *url_decode(const char *url)
{
struct strbuf out = STRBUF_INIT;
- const char *slash = strchr(url, '/');
+ const char *colon = strchr(url, ':');
/* Skip protocol part if present */
- if (slash && url < slash) {
- strbuf_add(&out, url, slash - url);
- url = slash;
+ if (colon && url < colon) {
+ strbuf_add(&out, url, colon - url);
+ url = colon;
}
return url_decode_internal(&url, NULL, &out);
}
diff --git a/wt-status.c b/wt-status.c
index 9d9cb95562..2f9e33c8fa 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -10,6 +10,7 @@
#include "run-command.h"
#include "remote.h"
#include "refs.h"
+#include "submodule.h"
static char default_wt_status_colors[][COLOR_MAXLEN] = {
GIT_COLOR_NORMAL, /* WT_STATUS_HEADER */
@@ -235,7 +236,7 @@ static void wt_status_collect_changed_cb(struct diff_queue_struct *q,
struct wt_status_change_data *d;
p = q->queue[i];
- it = string_list_insert(p->one->path, &s->change);
+ it = string_list_insert(&s->change, p->one->path);
d = it->util;
if (!d) {
d = xcalloc(1, sizeof(*d));
@@ -282,7 +283,7 @@ static void wt_status_collect_updated_cb(struct diff_queue_struct *q,
struct wt_status_change_data *d;
p = q->queue[i];
- it = string_list_insert(p->two->path, &s->change);
+ it = string_list_insert(&s->change, p->two->path);
d = it->util;
if (!d) {
d = xcalloc(1, sizeof(*d));
@@ -312,6 +313,8 @@ static void wt_status_collect_changes_worktree(struct wt_status *s)
DIFF_OPT_SET(&rev.diffopt, DIRTY_SUBMODULES);
if (!s->show_untracked_files)
DIFF_OPT_SET(&rev.diffopt, IGNORE_UNTRACKED_IN_SUBMODULES);
+ if (s->ignore_submodule_arg)
+ handle_ignore_submodules_arg(&rev.diffopt, s->ignore_submodule_arg);
rev.diffopt.format_callback = wt_status_collect_changed_cb;
rev.diffopt.format_callback_data = s;
rev.prune_data = s->pathspec;
@@ -328,6 +331,9 @@ static void wt_status_collect_changes_index(struct wt_status *s)
opt.def = s->is_initial ? EMPTY_TREE_SHA1_HEX : s->reference;
setup_revisions(0, NULL, &rev, &opt);
+ if (s->ignore_submodule_arg)
+ handle_ignore_submodules_arg(&rev.diffopt, s->ignore_submodule_arg);
+
rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;
rev.diffopt.format_callback = wt_status_collect_updated_cb;
rev.diffopt.format_callback_data = s;
@@ -349,7 +355,7 @@ static void wt_status_collect_changes_initial(struct wt_status *s)
if (!ce_path_match(ce, s->pathspec))
continue;
- it = string_list_insert(ce->name, &s->change);
+ it = string_list_insert(&s->change, ce->name);
d = it->util;
if (!d) {
d = xcalloc(1, sizeof(*d));
@@ -384,7 +390,7 @@ static void wt_status_collect_untracked(struct wt_status *s)
continue;
if (!match_pathspec(s->pathspec, ent->name, ent->len, 0, NULL))
continue;
- string_list_insert(ent->name, &s->untracked);
+ string_list_insert(&s->untracked, ent->name);
free(ent);
}
@@ -398,7 +404,7 @@ static void wt_status_collect_untracked(struct wt_status *s)
continue;
if (!match_pathspec(s->pathspec, ent->name, ent->len, 0, NULL))
continue;
- string_list_insert(ent->name, &s->ignored);
+ string_list_insert(&s->ignored, ent->name);
free(ent);
}
}
@@ -646,7 +652,9 @@ void wt_status_print(struct wt_status *s)
wt_status_print_updated(s);
wt_status_print_unmerged(s);
wt_status_print_changed(s);
- if (s->submodule_summary) {
+ if (s->submodule_summary &&
+ (!s->ignore_submodule_arg ||
+ strcmp(s->ignore_submodule_arg, "all"))) {
wt_status_print_submodule_summary(s, 0); /* staged */
wt_status_print_submodule_summary(s, 1); /* unstaged */
}
diff --git a/wt-status.h b/wt-status.h
index 4cd74c4b32..9df9c9fad2 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -45,6 +45,7 @@ struct wt_status {
int submodule_summary;
int show_ignored_files;
enum untracked_status_type show_untracked_files;
+ const char *ignore_submodule_arg;
char color_palette[WT_STATUS_REMOTE_BRANCH+1][COLOR_MAXLEN];
/* These are computed during processing of the individual sections */
diff --git a/xdiff/xutils.c b/xdiff/xutils.c
index bc12f29895..22f9bd692c 100644
--- a/xdiff/xutils.c
+++ b/xdiff/xutils.c
@@ -190,8 +190,10 @@ int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)
{
int i1, i2;
+ if (s1 == s2 && !memcmp(l1, l2, s1))
+ return 1;
if (!(flags & XDF_WHITESPACE_FLAGS))
- return s1 == s2 && !memcmp(l1, l2, s1);
+ return 0;
i1 = 0;
i2 = 0;