aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rwxr-xr-xDocumentation/cmd-list.perl1
-rw-r--r--Documentation/config.txt5
-rw-r--r--Documentation/git-branch.txt9
-rw-r--r--Documentation/git-checkout.txt15
-rw-r--r--Documentation/git-commit.txt9
-rw-r--r--Documentation/git-cvsserver.txt19
-rw-r--r--Documentation/git-fast-import.txt6
-rw-r--r--Documentation/git-format-patch.txt16
-rw-r--r--Documentation/git-mergetool.txt46
-rw-r--r--Documentation/git-receive-pack.txt32
-rw-r--r--Documentation/git-send-email.txt23
-rw-r--r--Documentation/git-svn.txt8
-rwxr-xr-xDocumentation/install-webdoc.sh2
-rw-r--r--Documentation/sort_glossary.pl2
-rw-r--r--Documentation/user-manual.txt45
-rw-r--r--Makefile113
-rw-r--r--builtin-branch.c153
-rw-r--r--builtin-bundle.c185
-rw-r--r--builtin-fsck.c28
-rw-r--r--builtin-grep.c15
-rw-r--r--builtin-log.c16
-rw-r--r--builtin-push.c2
-rw-r--r--builtin-revert.c404
-rw-r--r--builtin-shortlog.c5
-rw-r--r--builtin.h2
-rw-r--r--cache.h2
-rw-r--r--contrib/emacs/git.el89
-rw-r--r--diff-lib.c42
-rw-r--r--diff.c33
-rw-r--r--fast-import.c8
-rwxr-xr-xgit-checkout.sh17
-rwxr-xr-xgit-commit.sh21
-rwxr-xr-xgit-cvsserver.perl6
-rw-r--r--git-gui/.gitignore1
-rwxr-xr-xgit-gui/CREDITS-GEN71
-rw-r--r--git-gui/Makefile28
-rwxr-xr-xgit-gui/git-gui.sh76
-rwxr-xr-xgit-merge.sh7
-rwxr-xr-xgit-mergetool.sh352
-rwxr-xr-xgit-revert.sh197
-rwxr-xr-xgit-send-email.perl10
-rwxr-xr-xgit-svn.perl7
-rw-r--r--git.c2
-rw-r--r--log-tree.c10
-rw-r--r--perl/Makefile8
-rw-r--r--receive-pack.c109
-rw-r--r--refs.c2
-rw-r--r--revision.c219
-rw-r--r--revision.h10
-rw-r--r--run-command.c116
-rw-r--r--run-command.h19
-rw-r--r--setup.c2
-rw-r--r--sha1_file.c27
-rw-r--r--sha1_name.c12
-rwxr-xr-xt/diff-lib.sh6
-rwxr-xr-xt/t1000-read-tree-m-3way.sh2
-rwxr-xr-xt/t1001-read-tree-m-2way.sh26
-rwxr-xr-xt/t1002-read-tree-m-u-2way.sh2
-rwxr-xr-xt/t1300-repo-config.sh8
-rwxr-xr-xt/t3001-ls-files-others-exclude.sh4
-rwxr-xr-xt/t3002-ls-files-dashpath.sh10
-rwxr-xr-xt/t3100-ls-tree-restrict.sh2
-rwxr-xr-xt/t3101-ls-tree-dirname.sh2
-rwxr-xr-xt/t3200-branch.sh65
-rwxr-xr-xt/t3300-funny-names.sh30
-rwxr-xr-xt/t3900-i18n-commit.sh2
-rwxr-xr-xt/t4006-diff-mode.sh2
-rwxr-xr-xt/t4013-diff-various.sh7
-rw-r--r--t/t4013/diff.format-patch_--attach_--stdout_initial..master27
-rw-r--r--t/t4013/diff.format-patch_--attach_--stdout_initial..master^18
-rw-r--r--t/t4013/diff.format-patch_--attach_--stdout_initial..side9
-rw-r--r--t/t4013/diff.format-patch_--inline_--stdout_initial..master164
-rw-r--r--t/t4013/diff.format-patch_--inline_--stdout_initial..master^106
-rw-r--r--t/t4013/diff.format-patch_--inline_--stdout_initial..side59
-rwxr-xr-xt/t4015-diff-whitespace.sh12
-rwxr-xr-xt/t4016-diff-quote.sh4
-rwxr-xr-xt/t4100-apply-stat.sh14
-rwxr-xr-xt/t4104-apply-boundary.sh4
-rwxr-xr-xt/t4115-apply-symlink.sh4
-rwxr-xr-xt/t4116-apply-reverse.sh2
-rwxr-xr-xt/t4117-apply-reject.sh12
-rwxr-xr-xt/t4118-apply-empty-context.sh6
-rwxr-xr-xt/t4200-rerere.sh6
-rwxr-xr-xt/t5400-send-pack.sh2
-rwxr-xr-xt/t5401-update-hooks.sh36
-rwxr-xr-xt/t5510-fetch.sh38
-rwxr-xr-xt/t5515-fetch-merge-logic.sh2
-rw-r--r--t/t6023-merge-file.sh8
-rw-r--r--t/t6024-recursive-merge.sh4
-rwxr-xr-xt/t6200-fmt-merge-msg.sh10
-rwxr-xr-xt/t9100-git-svn-basic.sh6
-rwxr-xr-xt/t9300-fast-import.sh78
-rw-r--r--templates/Makefile10
-rw-r--r--trace.c18
95 files changed, 2453 insertions, 1039 deletions
diff --git a/.gitignore b/.gitignore
index 0eaba0a27..27797d149 100644
--- a/.gitignore
+++ b/.gitignore
@@ -75,6 +75,7 @@ git-merge-ours
git-merge-recursive
git-merge-resolve
git-merge-stupid
+git-mergetool
git-mktag
git-mktree
git-name-rev
diff --git a/Documentation/cmd-list.perl b/Documentation/cmd-list.perl
index f61c77aa7..b54382b2b 100755
--- a/Documentation/cmd-list.perl
+++ b/Documentation/cmd-list.perl
@@ -124,6 +124,7 @@ git-merge-index plumbingmanipulators
git-merge mainporcelain
git-merge-one-file purehelpers
git-merge-tree ancillaryinterrogators
+git-mergetool ancillarymanipulators
git-mktag plumbingmanipulators
git-mktree plumbingmanipulators
git-mv mainporcelain
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 5408dd67d..aaae9ac30 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -453,6 +453,11 @@ merge.summary::
Whether to include summaries of merged commits in newly created
merge commit messages. False by default.
+merge.tool::
+ Controls which merge resolution program is used by
+ gitlink:git-mergetool[l]. Valid values are: "kdiff3", "tkdiff",
+ "meld", "xxdiff", "emerge"
+
merge.verbosity::
Controls the amount of output shown by the recursive merge
strategy. Level 0 outputs nothing except a final error
diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index 3ea3b8063..603f87f3b 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -10,7 +10,7 @@ SYNOPSIS
[verse]
'git-branch' [--color | --no-color] [-r | -a]
[-v [--abbrev=<length> | --no-abbrev]]
-'git-branch' [-l] [-f] <branchname> [<start-point>]
+'git-branch' [--track | --no-track] [-l] [-f] <branchname> [<start-point>]
'git-branch' (-m | -M) [<oldbranch>] <newbranch>
'git-branch' (-d | -D) [-r] <branchname>...
@@ -26,6 +26,13 @@ It will start out with a head equal to the one given as <start-point>.
If no <start-point> is given, the branch will be created with a head
equal to that of the currently checked out branch.
+When a local branch is started off a remote branch, git can setup the
+branch so that gitlink:git-pull[1] will appropriately merge from that
+remote branch. If this behavior is desired, it is possible to make it
+the default using the global `branch.autosetupmerge` configuration
+flag. Otherwise, it can be chosen per-branch using the `--track`
+and `--no-track` options.
+
With a '-m' or '-M' option, <oldbranch> will be renamed to <newbranch>.
If <oldbranch> had a corresponding reflog, it is renamed to match
<newbranch>, and a reflog entry is created to remember the branch
diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index 1ae77be45..f5b2d5017 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -8,7 +8,7 @@ git-checkout - Checkout and switch to a branch
SYNOPSIS
--------
[verse]
-'git-checkout' [-q] [-f] [-b <new_branch> [-l]] [-m] [<branch>]
+'git-checkout' [-q] [-f] [-b [--track | --no-track] <new_branch> [-l]] [-m] [<branch>]
'git-checkout' [<tree-ish>] <paths>...
DESCRIPTION
@@ -18,7 +18,8 @@ When <paths> are not given, this command switches branches by
updating the index and working tree to reflect the specified
branch, <branch>, and updating HEAD to be <branch> or, if
specified, <new_branch>. Using -b will cause <new_branch> to
-be created.
+be created; in this case you can use the --track or --no-track
+options, which will be passed to `git branch`.
When <paths> are given, this command does *not* switch
branches. It updates the named paths in the working tree from
@@ -45,6 +46,16 @@ OPTIONS
by gitlink:git-check-ref-format[1]. Some of these checks
may restrict the characters allowed in a branch name.
+--track::
+ When -b is given and a branch is created off a remote branch,
+ setup so that git-pull will automatically retrieve data from
+ the remote branch.
+
+--no-track::
+ When -b is given and a branch is created off a remote branch,
+ force that git-pull will automatically retrieve data from
+ the remote branch independent of the configuration settings.
+
-l::
Create the new branch's ref log. This activates recording of
all changes to made the branch ref, enabling use of date
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index 2187eee41..53a7bb089 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -8,8 +8,9 @@ git-commit - Record changes to the repository
SYNOPSIS
--------
[verse]
-'git-commit' [-a] [-s] [-v] [(-c | -C) <commit> | -F <file> | -m <msg> |
- --amend] [--no-verify] [-e] [--author <author>]
+'git-commit' [-a | --interactive] [-s] [-v]
+ [(-c | -C) <commit> | -F <file> | -m <msg> | --amend]
+ [--no-verify] [-e] [--author <author>]
[--] [[-i | -o ]<file>...]
DESCRIPTION
@@ -35,6 +36,10 @@ methods:
before, and to automatically "rm" files that have been
removed from the working tree, and perform the actual commit.
+5. by using the --interactive switch with the 'commit' command to decide one
+ by one which files should be part of the commit, before finalizing the
+ operation. Currently, this is done by invoking `git-add --interactive`.
+
The gitlink:git-status[1] command can be used to obtain a
summary of what is included by any of the above for the next
commit by giving the same set of parameters you would give to
diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt
index e328db379..1c6f6a7e2 100644
--- a/Documentation/git-cvsserver.txt
+++ b/Documentation/git-cvsserver.txt
@@ -121,10 +121,10 @@ so that calling 'cvs' effectively calls git-cvsserver.
Clients known to work
---------------------
-CVS 1.12.9 on Debian
-CVS 1.11.17 on MacOSX (from Fink package)
-Eclipse 3.0, 3.1.2 on MacOSX (see Eclipse CVS Client Notes)
-TortoiseCVS
+- CVS 1.12.9 on Debian
+- CVS 1.11.17 on MacOSX (from Fink package)
+- Eclipse 3.0, 3.1.2 on MacOSX (see Eclipse CVS Client Notes)
+- TortoiseCVS
Operations supported
--------------------
@@ -148,13 +148,16 @@ Copyright and Authors
This program is copyright The Open University UK - 2006.
-Authors: Martyn Smith <martyn@catalyst.net.nz>
- Martin Langhoff <martin@catalyst.net.nz>
- with ideas and patches from participants of the git-list <git@vger.kernel.org>.
+Authors:
+
+- Martyn Smith <martyn@catalyst.net.nz>
+- Martin Langhoff <martin@catalyst.net.nz>
+
+with ideas and patches from participants of the git-list <git@vger.kernel.org>.
Documentation
--------------
-Documentation by Martyn Smith <martyn@catalyst.net.nz> and Martin Langhoff <martin@catalyst.net.nz> Matthias Urlichs <smurf@smurf.noris.de>.
+Documentation by Martyn Smith <martyn@catalyst.net.nz>, Martin Langhoff <martin@catalyst.net.nz>, and Matthias Urlichs <smurf@smurf.noris.de>.
GIT
---
diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt
index 7e3d2b1a9..eaba6fd4c 100644
--- a/Documentation/git-fast-import.txt
+++ b/Documentation/git-fast-import.txt
@@ -462,7 +462,7 @@ in octal. Git only supports the following modes:
In both formats `<path>` is the complete path of the file to be added
(if not already existing) or modified (if already existing).
-A `<path>` string must use UNIX-style directory seperators (forward
+A `<path>` string must use UNIX-style directory separators (forward
slash `/`), may contain any byte other than `LF`, and must not
start with double quote (`"`).
@@ -472,8 +472,8 @@ quoting should be used, e.g. `"path/with\n and \" in it"`.
The value of `<path>` must be in canoncial form. That is it must not:
* contain an empty directory component (e.g. `foo//bar` is invalid),
-* end with a directory seperator (e.g. `foo/` is invalid),
-* start with a directory seperator (e.g. `/foo` is invalid),
+* end with a directory separator (e.g. `foo/` is invalid),
+* start with a directory separator (e.g. `/foo` is invalid),
* contain the special component `.` or `..` (e.g. `foo/./bar` and
`foo/../bar` are invalid).
diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt
index 84eabebe0..111d7c60b 100644
--- a/Documentation/git-format-patch.txt
+++ b/Documentation/git-format-patch.txt
@@ -9,8 +9,9 @@ git-format-patch - Prepare patches for e-mail submission
SYNOPSIS
--------
[verse]
-'git-format-patch' [<common diff options>] [-n | -k] [-o <dir> | --stdout]
- [--attach] [--thread] [-s | --signoff] [--start-number <n>]
+'git-format-patch' [-n | -k] [-o <dir> | --stdout] [--thread]
+ [--attach[=<boundary>] | --inline[=<boundary>]]
+ [-s | --signoff] [<common diff options>] [--start-number <n>]
[--in-reply-to=Message-Id] [--suffix=.<sfx>]
[--ignore-if-in-upstream]
<since>[..<until>]
@@ -70,8 +71,15 @@ include::diff-options.txt[]
Print all commits to the standard output in mbox format,
instead of creating a file for each one.
---attach::
- Create attachments instead of inlining patches.
+--attach[=<boundary>]::
+ Create multipart/mixed attachment, the first part of
+ which is the commit message and the patch itself in the
+ second part, with "Content-Disposition: attachment".
+
+--inline[=<boundary>]::
+ Create multipart/mixed attachment, the first part of
+ which is the commit message and the patch itself in the
+ second part, with "Content-Disposition: inline".
--thread::
Add In-Reply-To and References headers to make the second and
diff --git a/Documentation/git-mergetool.txt b/Documentation/git-mergetool.txt
new file mode 100644
index 000000000..ae69a0eb8
--- /dev/null
+++ b/Documentation/git-mergetool.txt
@@ -0,0 +1,46 @@
+git-mergetool(1)
+================
+
+NAME
+----
+git-mergetool - Run merge conflict resolution tools to resolve merge conflicts
+
+SYNOPSIS
+--------
+'git-mergetool' [--tool=<tool>] [<file>]...
+
+DESCRIPTION
+-----------
+
+Use 'git mergetool' to run one of several merge utilities to resolve
+merge conflicts. It is typically run after gitlink:git-merge[1].
+
+If one or more <file> parameters are given, the merge tool program will
+be run to resolve differences on each file. If no <file> names are
+specified, 'git mergetool' will run the merge tool program on every file
+with merge conflicts.
+
+OPTIONS
+-------
+-t or --tool=<tool>::
+ Use the merge resolution program specified by <tool>.
+ Valid merge tools are:
+ kdiff3, tkdiff, meld, xxdiff, and emerge.
+
+ If a merge resolution program is not specified, 'git mergetool'
+ will use the configuration variable merge.tool. If the
+ configuration variable merge.tool is not set, 'git mergetool'
+ will pick a suitable default.
+
+Author
+------
+Written by Theodore Y Ts'o <tytso@mit.edu>
+
+Documentation
+--------------
+Documentation by Theodore Y Ts'o.
+
+GIT
+---
+Part of the gitlink:git[7] suite
+
diff --git a/Documentation/git-receive-pack.txt b/Documentation/git-receive-pack.txt
index 3cf55111c..6914aa59c 100644
--- a/Documentation/git-receive-pack.txt
+++ b/Documentation/git-receive-pack.txt
@@ -40,13 +40,13 @@ OPTIONS
pre-receive Hook
----------------
Before any ref is updated, if $GIT_DIR/hooks/pre-receive file exists
-and is executable, it will be invoked once, with three parameters
-per ref to be updated:
+and is executable, it will be invoked once with no parameters. The
+standard input of the hook will be one line per ref to be updated:
- $GIT_DIR/hooks/pre-receive (refname sha1-old sha1-new)+
+ sha1-old SP sha1-new SP refname LF
-The refname parameter is relative to $GIT_DIR; e.g. for the master
-head this is "refs/heads/master". The two sha1 arguments after
+The refname value is relative to $GIT_DIR; e.g. for the master
+head this is "refs/heads/master". The two sha1 values before
each refname are the object names for the refname before and after
the update. Refs to be created will have sha1-old equal to 0{40},
while refs to be deleted will have sha1-new equal to 0{40}, otherwise
@@ -86,13 +86,14 @@ post-receive Hook
-----------------
After all refs were updated (or attempted to be updated), if any
ref update was successful, and if $GIT_DIR/hooks/post-receive
-file exists and is executable, it will be invoke once with three
-parameters for each successfully updated ref:
+file exists and is executable, it will be invoke once with no
+parameters. The standard input of the hook will be one line
+for each successfully updated ref:
- $GIT_DIR/hooks/post-receive (refname sha1-old sha1-new)+
+ sha1-old SP sha1-new SP refname LF
-The refname parameter is relative to $GIT_DIR; e.g. for the master
-head this is "refs/heads/master". The two sha1 arguments after
+The refname value is relative to $GIT_DIR; e.g. for the master
+head this is "refs/heads/master". The two sha1 values before
each refname are the object names for the refname before and after
the update. Refs that were created will have sha1-old equal to
0{40}, while refs that were deleted will have sha1-new equal to
@@ -105,18 +106,17 @@ ref listing the commits pushed to the repository:
#!/bin/sh
# mail out commit update information.
- while test $# -gt 0
+ while read oval nval ref
do
- if expr "$2" : '0*$' >/dev/null
+ if expr "$oval" : '0*$' >/dev/null
then
echo "Created a new ref, with the following commits:"
- git-rev-list --pretty "$2"
+ git-rev-list --pretty "$nval"
else
echo "New commits:"
- git-rev-list --pretty "$3" "^$2"
+ git-rev-list --pretty "$nval" "^$oval"
fi |
- mail -s "Changes to ref $1" commit-list@mydomain
- shift; shift; shift; # discard this ref's args
+ mail -s "Changes to ref $ref" commit-list@mydomain
done
exit 0
diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt
index 35b0104e4..9b3aabb6f 100644
--- a/Documentation/git-send-email.txt
+++ b/Documentation/git-send-email.txt
@@ -40,7 +40,8 @@ The --cc option must be repeated for each user you want on the cc list.
the first will be sent as replies to the first email sent. When using
this, it is recommended that the first file given be an overview of the
entire patch series.
- Default is --chain-reply-to
+ Default is the value of the 'sendemail.chainreplyto' configuration
+ value; if that is unspecified, default to --chain-reply-to.
--compose::
Use $EDITOR to edit an introductory message for the
@@ -91,6 +92,26 @@ The --cc option must be repeated for each user you want on the cc list.
The --to option must be repeated for each user you want on the to list.
+CONFIGURATION
+-------------
+sendemail.aliasesfile::
+ To avoid typing long email addresses, point this to one or more
+ email aliases files. You must also supply 'sendemail.aliasfiletype'.
+
+sendemail.aliasfiletype::
+ Format of the file(s) specified in sendemail.aliasesfile. Must be
+ one of 'mutt', 'mailrc', 'pine', or 'gnus'.
+
+sendemail.bcc::
+ Email address (or alias) to always bcc.
+
+sendemail.chainreplyto::
+ Boolean value specifying the default to the '--chain_reply_to'
+ parameter.
+
+sendemail.smtpserver::
+ Default smtp server to use.
+
Author
------
Written by Ryan Anderson <ryan@michonline.com>
diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index 9b5a3d619..a0d34e005 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -104,6 +104,14 @@ accepts. However '--fetch-all' only fetches from the current
Like 'git-rebase'; this requires that the working tree be clean
and have no uncommitted changes.
++
+--
+-l;;
+--local;;
+ Do not fetch remotely; only run 'git-rebase' against the
+ last fetched commit from the upstream SVN.
+--
++
'dcommit'::
Commit each diff from a specified head directly to the SVN
diff --git a/Documentation/install-webdoc.sh b/Documentation/install-webdoc.sh
index b3981936e..cd3a18eb7 100755
--- a/Documentation/install-webdoc.sh
+++ b/Documentation/install-webdoc.sh
@@ -2,7 +2,7 @@
T="$1"
-for h in *.html *.txt howto/*.txt howto/*.html RelNotes-*.txt
+for h in *.html *.txt howto/*.txt howto/*.html RelNotes-*.txt *.css
do
if test -f "$T/$h" &&
diff -u -I'Last updated [0-9][0-9]-[A-Z][a-z][a-z]-' "$T/$h" "$h"
diff --git a/Documentation/sort_glossary.pl b/Documentation/sort_glossary.pl
index e0bc552a6..05dc7b2c7 100644
--- a/Documentation/sort_glossary.pl
+++ b/Documentation/sort_glossary.pl
@@ -48,7 +48,7 @@ This list is sorted alphabetically:
';
@keys=sort {uc($a) cmp uc($b)} keys %terms;
-$pattern='(\b(?<!link:git-)'.join('\b|\b(?<!link:git-)',reverse @keys).'\b)';
+$pattern='(\b(?<!link:git-)'.join('\b|\b(?<!-)',reverse @keys).'\b)';
foreach $key (@keys) {
$terms{$key}=~s/$pattern/sprintf "<<ref_".no_spaces($1).",$1>>";/eg;
print '[[ref_'.no_spaces($key).']]'.$key."::\n"
diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt
index ffd673ec3..d7b227e64 100644
--- a/Documentation/user-manual.txt
+++ b/Documentation/user-manual.txt
@@ -437,11 +437,14 @@ We will sometimes represent git history using diagrams like the one
below. Commits are shown as "o", and the links between them with
lines drawn with - / and \. Time goes left to right:
+
+................................................
o--o--o <-- Branch A
/
o--o--o <-- master
\
o--o--o <-- Branch B
+................................................
If we need to talk about a particular commit, the character "o" may
be replaced with another letter or number.
@@ -601,8 +604,8 @@ a new stanza:
$ cat .git/config
...
[remote "linux-nfs"]
- url = git://linux-nfs.org/~bfields/git.git
- fetch = +refs/heads/*:refs/remotes/linux-nfs-read/*
+ url = git://linux-nfs.org/pub/nfs-2.6.git
+ fetch = +refs/heads/*:refs/remotes/linux-nfs/*
...
-------------------------------------------------
@@ -1133,17 +1136,9 @@ modified in two different ways in the remote branch and the local
branch--then you are warned; the output may look something like this:
-------------------------------------------------
-$ git pull . next
-Trying really trivial in-index merge...
-fatal: Merge requires file-level merging
-Nope.
-Merging HEAD with 77976da35a11db4580b80ae27e8d65caf5208086
-Merging:
-15e2162 world
-77976da goodbye
-found 1 common ancestor(s):
-d122ed4 initial
-Auto-merging file.txt
+$ git merge next
+ 100% (4/4) done
+Auto-merged file.txt
CONFLICT (content): Merge conflict in file.txt
Automatic merge failed; fix conflicts and then commit the result.
-------------------------------------------------
@@ -1439,7 +1434,7 @@ modifying the working directory, you can do that with
gitlink:git-show[1]:
-------------------------------------------------
-$ git show HEAD^ path/to/file
+$ git show HEAD^:path/to/file
-------------------------------------------------
which will display the given version of the file.
@@ -1936,25 +1931,29 @@ $ git commit
You have performed no merges into mywork, so it is just a simple linear
sequence of patches on top of "origin":
-
+................................................
o--o--o <-- origin
\
o--o--o <-- mywork
+................................................
Some more interesting work has been done in the upstream project, and
"origin" has advanced:
+................................................
o--o--O--o--o--o <-- origin
\
a--b--c <-- mywork
+................................................
At this point, you could use "pull" to merge your changes back in;
the result would create a new merge commit, like this:
-
+................................................
o--o--O--o--o--o <-- origin
\ \
a--b--c--m <-- mywork
+................................................
However, if you prefer to keep the history in mywork a simple series of
commits without any merges, you may instead choose to use
@@ -1971,9 +1970,11 @@ point at the latest version of origin, then apply each of the saved
patches to the new mywork. The result will look like:
+................................................
o--o--O--o--o--o <-- origin
\
a'--b'--c' <-- mywork
+................................................
In the process, it may discover conflicts. In that case it will stop
and allow you to fix the conflicts; after fixing conflicts, use "git
@@ -2081,24 +2082,30 @@ The primary problem with rewriting the history of a branch has to do
with merging. Suppose somebody fetches your branch and merges it into
their branch, with a result something like this:
+................................................
o--o--O--o--o--o <-- origin
\ \
t--t--t--m <-- their branch:
+................................................
Then suppose you modify the last three commits:
+................................................
o--o--o <-- new head of origin
/
o--o--O--o--o--o <-- old head of origin
+................................................
If we examined all this history together in one repository, it will
look like:
+................................................
o--o--o <-- new head of origin
/
o--o--O--o--o--o <-- old head of origin
\ \
t--t--t--m <-- their branch:
+................................................
Git has no way of knowing that the new head is an updated version of
the old head; it treats this situation exactly the same as it would if
@@ -2159,9 +2166,11 @@ commit. Git calls this process a "fast forward".
A fast forward looks something like this:
+................................................
o--o--o--o <-- old head of the branch
\
o--o--o <-- new head of the branch
+................................................
In some cases it is possible that the new head will *not* actually be
@@ -2169,11 +2178,11 @@ a descendant of the old head. For example, the developer may have
realized she made a serious mistake, and decided to backtrack,
resulting in a situation like:
+................................................
o--o--o--o--a--b <-- old head of the branch
\
o--o--o <-- new head of the branch
-
-
+................................................
In this case, "git fetch" will fail, and print out a warning.
diff --git a/Makefile b/Makefile
index a221bdc02..45fe3663a 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,8 @@
# The default target of this Makefile is...
all::
+# Define V=1 to have a more verbose compile.
+#
# Define NO_OPENSSL environment variable if you do not have OpenSSL.
# This also implies MOZILLA_SHA1.
#
@@ -177,10 +179,10 @@ SCRIPT_SH = \
git-clean.sh git-clone.sh git-commit.sh \
git-fetch.sh git-gc.sh \
git-ls-remote.sh \
- git-merge-one-file.sh git-parse-remote.sh \
+ git-merge-one-file.sh git-mergetool.sh git-parse-remote.sh \
git-pull.sh git-rebase.sh \
git-repack.sh git-request-pull.sh git-reset.sh \
- git-revert.sh git-sh-setup.sh \
+ git-sh-setup.sh \
git-tag.sh git-verify-tag.sh \
git-applymbox.sh git-applypatch.sh git-am.sh \
git-merge.sh git-merge-stupid.sh git-merge-octopus.sh \
@@ -196,7 +198,7 @@ SCRIPT_PERL = \
SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
$(patsubst %.perl,%,$(SCRIPT_PERL)) \
- git-cherry-pick git-status git-instaweb
+ git-status git-instaweb
# ... and all the rest that could be moved out of bindir to gitexecdir
PROGRAMS = \
@@ -223,7 +225,7 @@ EXTRA_PROGRAMS =
BUILT_INS = \
git-format-patch$X git-show$X git-whatchanged$X git-cherry$X \
git-get-tar-commit-id$X git-init$X git-repo-config$X \
- git-fsck-objects$X \
+ git-fsck-objects$X git-cherry-pick$X \
$(patsubst builtin-%.o,git-%$X,$(BUILTIN_OBJS))
# what 'all' will build and 'install' will install, in gitexecdir
@@ -315,6 +317,7 @@ BUILTIN_OBJS = \
builtin-rerere.o \
builtin-rev-list.o \
builtin-rev-parse.o \
+ builtin-revert.o \
builtin-rm.o \
builtin-runstatus.o \
builtin-shortlog.o \
@@ -603,6 +606,31 @@ ifdef NO_PERL_MAKEMAKER
export NO_PERL_MAKEMAKER
endif
+QUIET_SUBDIR0 = $(MAKE) -C # space to separate -C and subdir
+QUIET_SUBDIR1 =
+
+ifneq ($(findstring $(MAKEFLAGS),w),w)
+PRINT_DIR = --no-print-directory
+else # "make -w"
+NO_SUBDIR = :
+endif
+
+ifneq ($(findstring $(MAKEFLAGS),s),s)
+ifndef V
+ QUIET_CC = @echo ' ' CC $@;
+ QUIET_AR = @echo ' ' AR $@;
+ QUIET_LINK = @echo ' ' LINK $@;
+ QUIET_BUILT_IN = @echo ' ' BUILTIN $@;
+ QUIET_GEN = @echo ' ' GEN $@;
+ QUIET_SUBDIR0 = @subdir=
+ QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \
+ $(MAKE) $(PRINT_DIR) -C $$subdir
+ export V
+ export QUIET_GEN
+ export QUIET_BUILT_IN
+endif
+endif
+
# Shell quote (do not use $(call) to accommodate ancient setups);
SHA1_HEADER_SQ = $(subst ','\'',$(SHA1_HEADER))
@@ -637,44 +665,43 @@ ifneq (,$X)
endif
all::
- $(MAKE) -C git-gui all
- $(MAKE) -C perl PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' all
- $(MAKE) -C templates
+ $(QUIET_SUBDIR0)git-gui $(QUIET_SUBDIR1) all
+ $(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' all
+ $(QUIET_SUBDIR0)templates $(QUIET_SUBDIR1)
strip: $(PROGRAMS) git$X
$(STRIP) $(STRIP_OPTS) $(PROGRAMS) git$X
git$X: git.c common-cmds.h $(BUILTIN_OBJS) $(GITLIBS) GIT-CFLAGS
- $(CC) -DGIT_VERSION='"$(GIT_VERSION)"' \
+ $(QUIET_LINK)$(CC) -DGIT_VERSION='"$(GIT_VERSION)"' \
$(ALL_CFLAGS) -o $@ $(filter %.c,$^) \
$(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS)
help.o: common-cmds.h
$(BUILT_INS): git$X
- rm -f $@ && ln git$X $@
+ $(QUIET_BUILT_IN)rm -f $@ && ln git$X $@
common-cmds.h: Documentation/git-*.txt
- ./generate-cmdlist.sh > $@+
- mv $@+ $@
+ $(QUIET_GEN)./generate-cmdlist.sh > $@+ && mv $@+ $@
$(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
- rm -f $@ $@+
+ $(QUIET_GEN)rm -f $@ $@+ && \
sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
-e 's|@@PERL@@|$(PERL_PATH_SQ)|g' \
-e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
-e 's/@@NO_CURL@@/$(NO_CURL)/g' \
- $@.sh >$@+
- chmod +x $@+
+ $@.sh >$@+ && \
+ chmod +x $@+ && \
mv $@+ $@
$(patsubst %.perl,%,$(SCRIPT_PERL)): perl/perl.mak
perl/perl.mak: GIT-CFLAGS
- $(MAKE) -C perl PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' $(@F)
+ $(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' $(@F)
$(patsubst %.perl,%,$(SCRIPT_PERL)): % : %.perl
- rm -f $@ $@+
+ $(QUIET_GEN)rm -f $@ $@+ && \
INSTLIBDIR=`$(MAKE) -C perl -s --no-print-directory instlibdir` && \
sed -e '1{' \
-e ' s|#!.*perl|#!$(PERL_PATH_SQ)|' \
@@ -685,20 +712,15 @@ $(patsubst %.perl,%,$(SCRIPT_PERL)): % : %.perl
-e '}' \
-e 's|@@INSTLIBDIR@@|'"$$INSTLIBDIR"'|g' \
-e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
- $@.perl >$@+
- chmod +x $@+
- mv $@+ $@
-
-git-cherry-pick: git-revert
- cp $< $@+
+ $@.perl >$@+ && \
+ chmod +x $@+ && \
mv $@+ $@
git-status: git-commit
- cp $< $@+
- mv $@+ $@
+ $(QUIET_GEN)cp $< $@+ && mv $@+ $@
gitweb/gitweb.cgi: gitweb/gitweb.perl
- rm -f $@ $@+
+ $(QUIET_GEN)rm -f $@ $@+ && \
sed -e '1s|#!.*perl|#!$(PERL_PATH_SQ)|' \
-e 's|++GIT_VERSION++|$(GIT_VERSION)|g' \
-e 's|++GIT_BINDIR++|$(bindir)|g' \
@@ -716,12 +738,12 @@ gitweb/gitweb.cgi: gitweb/gitweb.perl
-e 's|++GITWEB_FAVICON++|$(GITWEB_FAVICON)|g' \
-e 's|++GITWEB_SITE_HEADER++|$(GITWEB_SITE_HEADER)|g' \
-e 's|++GITWEB_SITE_FOOTER++|$(GITWEB_SITE_FOOTER)|g' \
- $< >$@+
- chmod +x $@+
+ $< >$@+ && \
+ chmod +x $@+ && \
mv $@+ $@
git-instaweb: git-instaweb.sh gitweb/gitweb.cgi gitweb/gitweb.css
- rm -f $@ $@+
+ $(QUIET_GEN)rm -f $@ $@+ && \
sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
-e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
-e 's/@@NO_CURL@@/$(NO_CURL)/g' \
@@ -729,15 +751,15 @@ git-instaweb: git-instaweb.sh gitweb/gitweb.cgi gitweb/gitweb.css
-e '/@@GITWEB_CGI@@/d' \
-e '/@@GITWEB_CSS@@/r gitweb/gitweb.css' \
-e '/@@GITWEB_CSS@@/d' \
- $@.sh > $@+
- chmod +x $@+
+ $@.sh > $@+ && \
+ chmod +x $@+ && \
mv $@+ $@
configure: configure.ac
- rm -f $@ $<+
+ $(QUIET_GEN)rm -f $@ $<+ && \
sed -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
- $< > $<+
- autoconf -o $@ $<+
+ $< > $<+ && \
+ autoconf -o $@ $<+ && \
rm -f $<+
# These can record GIT_VERSION
@@ -747,25 +769,25 @@ git$X git.spec \
: GIT-VERSION-FILE
%.o: %.c GIT-CFLAGS
- $(CC) -o $*.o -c $(ALL_CFLAGS) $<
+ $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) $<
%.o: %.S
- $(CC) -o $*.o -c $(ALL_CFLAGS) $<
+ $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) $<
exec_cmd.o: exec_cmd.c GIT-CFLAGS
- $(CC) -o $*.o -c $(ALL_CFLAGS) '-DGIT_EXEC_PATH="$(gitexecdir_SQ)"' $<
+ $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) '-DGIT_EXEC_PATH="$(gitexecdir_SQ)"' $<
builtin-init-db.o: builtin-init-db.c GIT-CFLAGS
- $(CC) -o $*.o -c $(ALL_CFLAGS) -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $<
+ $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $<
http.o: http.c GIT-CFLAGS
- $(CC) -o $*.o -c $(ALL_CFLAGS) -DGIT_USER_AGENT='"git/$(GIT_VERSION)"' $<
+ $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DGIT_USER_AGENT='"git/$(GIT_VERSION)"' $<
ifdef NO_EXPAT
http-fetch.o: http-fetch.c http.h GIT-CFLAGS
- $(CC) -o $*.o -c $(ALL_CFLAGS) -DNO_EXPAT $<
+ $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DNO_EXPAT $<
endif
git-%$X: %.o $(GITLIBS)
- $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
+ $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
ssh-pull.o: ssh-fetch.c
ssh-push.o: ssh-upload.c
@@ -779,11 +801,11 @@ git-imap-send$X: imap-send.o $(LIB_FILE)
http.o http-fetch.o http-push.o: http.h
git-http-fetch$X: fetch.o http.o http-fetch.o $(GITLIBS)
- $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
+ $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
git-http-push$X: revision.o http.o http-push.o $(GITLIBS)
- $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
+ $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
$(LIB_OBJS) $(BUILTIN_OBJS) fetch.o: $(LIB_H)
@@ -791,7 +813,7 @@ $(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
$(DIFF_OBJS): diffcore.h
$(LIB_FILE): $(LIB_OBJS)
- rm -f $@ && $(AR) rcs $@ $(LIB_OBJS)
+ $(QUIET_AR)rm -f $@ && $(AR) rcs $@ $(LIB_OBJS)
XDIFF_OBJS=xdiff/xdiffi.o xdiff/xprepare.o xdiff/xutils.o xdiff/xemit.o \
xdiff/xmerge.o
@@ -799,7 +821,7 @@ $(XDIFF_OBJS): xdiff/xinclude.h xdiff/xmacros.h xdiff/xdiff.h xdiff/xtypes.h \
xdiff/xutils.h xdiff/xprepare.h xdiff/xdiffi.h xdiff/xemit.h
$(XDIFF_LIB): $(XDIFF_OBJS)
- rm -f $@ && $(AR) rcs $@ $(XDIFF_OBJS)
+ $(QUIET_AR)rm -f $@ && $(AR) rcs $@ $(XDIFF_OBJS)
perl/Makefile: perl/Git.pm perl/Makefile.PL GIT-CFLAGS
@@ -909,8 +931,7 @@ dist: git.spec git-archive
$(TAR) rf $(GIT_TARNAME).tar \
$(GIT_TARNAME)/git.spec \
$(GIT_TARNAME)/version \
- $(GIT_TARNAME)/git-gui/version \
- $(GIT_TARNAME)/git-gui/credits
+ $(GIT_TARNAME)/git-gui/version
@rm -rf $(GIT_TARNAME)
gzip -f -9 $(GIT_TARNAME).tar
diff --git a/builtin-branch.c b/builtin-branch.c
index 06d8a8ce0..42b1ff129 100644
--- a/builtin-branch.c
+++ b/builtin-branch.c
@@ -12,7 +12,7 @@
#include "builtin.h"
static const char builtin_branch_usage[] =
- "git-branch [-r] (-d | -D) <branchname> | [-l] [-f] <branchname> [<start-point>] | (-m | -M) [<oldbranch>] <newbranch> | [--color | --no-color] [-r | -a] [-v [--abbrev=<length> | --no-abbrev]]";
+ "git-branch [-r] (-d | -D) <branchname> | [--track | --no-track] [-l] [-f] <branchname> [<start-point>] | (-m | -M) [<oldbranch>] <newbranch> | [--color | --no-color] [-r | -a] [-v [--abbrev=<length> | --no-abbrev]]";
#define REF_UNKNOWN_TYPE 0x00
#define REF_LOCAL_BRANCH 0x01
@@ -22,6 +22,8 @@ static const char builtin_branch_usage[] =
static const char *head;
static unsigned char head_sha1[20];
+static int branch_track_remotes;
+
static int branch_use_color;
static char branch_colors[][COLOR_MAXLEN] = {
"\033[m", /* reset */
@@ -64,6 +66,9 @@ int git_branch_config(const char *var, const char *value)
color_parse(value, var, branch_colors[slot]);
return 0;
}
+ if (!strcmp(var, "branch.autosetupmerge"))
+ branch_track_remotes = git_config_bool(var, value);
+
return git_default_config(var, value);
}
@@ -309,14 +314,108 @@ static void print_ref_list(int kinds, int detached, int verbose, int abbrev)
free_ref_list(&ref_list);
}
+static char *config_repo;
+static char *config_remote;
+static const char *start_ref;
+static int start_len;
+static int base_len;
+
+static int get_remote_branch_name(const char *value)
+{
+ const char *colon;
+ const char *end;
+
+ if (*value == '+')
+ value++;
+
+ colon = strchr(value, ':');
+ if (!colon)
+ return 0;
+
+ end = value + strlen(value);
+
+ /* Try an exact match first. */
+ if (!strcmp(colon + 1, start_ref)) {
+ /* Truncate the value before the colon. */
+ nfasprintf(&config_repo, "%.*s", colon - value, value);
+ return 1;
+ }
+
+ /* Try with a wildcard match now. */
+ if (end - value > 2 && end[-2] == '/' && end[-1] == '*' &&
+ colon - value > 2 && colon[-2] == '/' && colon[-1] == '*' &&
+ (end - 2) - (colon + 1) == base_len &&
+ !strncmp(colon + 1, start_ref, base_len)) {
+ /* Replace the star with the remote branch name. */
+ nfasprintf(&config_repo, "%.*s%s",
+ (colon - 2) - value, value,
+ start_ref + base_len);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int get_remote_config(const char *key, const char *value)
+{
+ const char *var;
+ if (prefixcmp(key, "remote."))
+ return 0;
+
+ var = strrchr(key, '.');
+ if (var == key + 6)
+ return 0;
+
+ if (!strcmp(var, ".fetch") && get_remote_branch_name(value))
+ nfasprintf(&config_remote, "%.*s", var - (key + 7), key + 7);
+
+ return 0;
+}
+
+static void set_branch_defaults(const char *name, const char *real_ref)
+{
+ char key[1024];
+ const char *slash = strrchr(real_ref, '/');
+
+ if (!slash)
+ return;
+
+ start_ref = real_ref;
+ start_len = strlen(real_ref);
+ base_len = slash - real_ref;
+ git_config(get_remote_config);
+
+ if (config_repo && config_remote) {
+ if (sizeof(key) <=
+ snprintf(key, sizeof(key), "branch.%s.remote", name))
+ die("what a long branch name you have!");
+ git_config_set(key, config_remote);
+
+ /*
+ * We do not have to check if we have enough space for
+ * the 'merge' key, since it's shorter than the
+ * previous 'remote' key, which we already checked.
+ */
+ snprintf(key, sizeof(key), "branch.%s.merge", name);
+ git_config_set(key, config_repo);
+
+ printf("Branch %s set up to track remote branch %s.\n",
+ name, real_ref);
+ }
+
+ if (config_repo)
+ free(config_repo);
+ if (config_remote)
+ free(config_remote);
+}
+
static void create_branch(const char *name, const char *start_name,
- unsigned char *start_sha1,
- int force, int reflog)
+ int force, int reflog, int track)
{
struct ref_lock *lock;
struct commit *commit;
unsigned char sha1[20];
- char ref[PATH_MAX], msg[PATH_MAX + 20];
+ char *real_ref, ref[PATH_MAX], msg[PATH_MAX + 20];
int forcing = 0;
snprintf(ref, sizeof ref, "refs/heads/%s", name);
@@ -331,12 +430,23 @@ static void create_branch(const char *name, const char *start_name,
forcing = 1;
}
- if (start_sha1)
- /* detached HEAD */
- hashcpy(sha1, start_sha1);
- else if (get_sha1(start_name, sha1))
+ real_ref = NULL;
+ if (get_sha1(start_name, sha1))
die("Not a valid object name: '%s'.", start_name);
+ switch (dwim_ref(start_name, strlen(start_name), sha1, &real_ref)) {
+ case 0:
+ /* Not branching from any existing branch */
+ real_ref = NULL;
+ break;
+ case 1:
+ /* Unique completion -- good */
+ break;
+ default:
+ die("Ambiguous object name: '%s'.", start_name);
+ break;
+ }
+
if ((commit = lookup_commit_reference(sha1)) == NULL)
die("Not a valid branch point: '%s'.", start_name);
hashcpy(sha1, commit->object.sha1);
@@ -355,8 +465,17 @@ static void create_branch(const char *name, const char *start_name,
snprintf(msg, sizeof msg, "branch: Created from %s",
start_name);
+ /* When branching off a remote branch, set up so that git-pull
+ automatically merges from there. So far, this is only done for
+ remotes registered via .git/config. */
+ if (real_ref && track)
+ set_branch_defaults(name, real_ref);
+
if (write_ref_sha1(lock, sha1, msg) < 0)
die("Failed to write ref: %s.", strerror(errno));
+
+ if (real_ref)
+ free(real_ref);
}
static void rename_branch(const char *oldname, const char *newname, int force)
@@ -398,11 +517,12 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
int delete = 0, force_delete = 0, force_create = 0;
int rename = 0, force_rename = 0;
int verbose = 0, abbrev = DEFAULT_ABBREV, detached = 0;
- int reflog = 0;
+ int reflog = 0, track;
int kinds = REF_LOCAL_BRANCH;
int i;
git_config(git_branch_config);
+ track = branch_track_remotes;
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
@@ -413,6 +533,14 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
i++;
break;
}
+ if (!strcmp(arg, "--track")) {
+ track = 1;
+ continue;
+ }
+ if (!strcmp(arg, "--no-track")) {
+ track = 0;
+ continue;
+ }
if (!strcmp(arg, "-d")) {
delete = 1;
continue;
@@ -498,10 +626,9 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
rename_branch(head, argv[i], force_rename);
else if (rename && (i == argc - 2))
rename_branch(argv[i], argv[i + 1], force_rename);
- else if (i == argc - 1)
- create_branch(argv[i], head, head_sha1, force_create, reflog);
- else if (i == argc - 2)
- create_branch(argv[i], argv[i+1], NULL, force_create, reflog);
+ else if (i == argc - 1 || i == argc - 2)
+ create_branch(argv[i], (i == argc - 2) ? argv[i+1] : head,
+ force_create, reflog, track);
else
usage(builtin_branch_usage);
diff --git a/builtin-bundle.c b/builtin-bundle.c
index 279b8f8e5..786808081 100644
--- a/builtin-bundle.c
+++ b/builtin-bundle.c
@@ -160,7 +160,28 @@ static int fork_with_pipe(const char **argv, int *in, int *out)
return pid;
}
-static int verify_bundle(struct bundle_header *header)
+static int list_refs(struct ref_list *r, int argc, const char **argv)
+{
+ int i;
+
+ for (i = 0; i < r->nr; i++) {
+ if (argc > 1) {
+ int j;
+ for (j = 1; j < argc; j++)
+ if (!strcmp(r->list[i].name, argv[j]))
+ break;
+ if (j == argc)
+ continue;
+ }
+ printf("%s %s\n", sha1_to_hex(r->list[i].sha1),
+ r->list[i].name);
+ }
+ return 0;
+}
+
+#define PREREQ_MARK (1u<<16)
+
+static int verify_bundle(struct bundle_header *header, int verbose)
{
/*
* Do fast check, then if any prereqs are missing then go line by line
@@ -179,7 +200,7 @@ static int verify_bundle(struct bundle_header *header)
struct ref_list_entry *e = p->list + i;
struct object *o = parse_object(e->sha1);
if (o) {
- o->flags |= BOUNDARY_SHOW;
+ o->flags |= PREREQ_MARK;
add_pending_object(&revs, o, e->name);
continue;
}
@@ -187,7 +208,7 @@ static int verify_bundle(struct bundle_header *header)
error(message);
error("%s %s", sha1_to_hex(e->sha1), e->name);
}
- if (revs.pending.nr == 0)
+ if (revs.pending.nr != p->nr)
return ret;
req_nr = revs.pending.nr;
setup_revisions(2, argv, &revs, NULL);
@@ -202,7 +223,7 @@ static int verify_bundle(struct bundle_header *header)
i = req_nr;
while (i && (commit = get_revision(&revs)))
- if (commit->object.flags & BOUNDARY_SHOW)
+ if (commit->object.flags & PREREQ_MARK)
i--;
for (i = 0; i < req_nr; i++)
@@ -216,56 +237,24 @@ static int verify_bundle(struct bundle_header *header)
for (i = 0; i < refs.nr; i++)
clear_commit_marks((struct commit *)refs.objects[i].item, -1);
+ if (verbose) {
+ struct ref_list *r;
+
+ r = &header->references;
+ printf("The bundle contains %d ref%s\n",
+ r->nr, (1 < r->nr) ? "s" : "");
+ list_refs(r, 0, NULL);
+ r = &header->prerequisites;
+ printf("The bundle requires these %d ref%s\n",
+ r->nr, (1 < r->nr) ? "s" : "");
+ list_refs(r, 0, NULL);
+ }
return ret;
}
static int list_heads(struct bundle_header *header, int argc, const char **argv)
{
- int i;
- struct ref_list *r = &header->references;
-
- for (i = 0; i < r->nr; i++) {
- if (argc > 1) {
- int j;
- for (j = 1; j < argc; j++)
- if (!strcmp(r->list[i].name, argv[j]))
- break;
- if (j == argc)
- continue;
- }
- printf("%s %s\n", sha1_to_hex(r->list[i].sha1),
- r->list[i].name);
- }
- return 0;
-}
-
-static void show_commit(struct commit *commit)
-{
- write_or_die(1, sha1_to_hex(commit->object.sha1), 40);
- write_or_die(1, "\n", 1);
- if (commit->parents) {
- free_commit_list(commit->parents);
- commit->parents = NULL;
- }
-}
-
-static void show_object(struct object_array_entry *p)
-{
- /* An object with name "foo\n0000000..." can be used to
- * confuse downstream git-pack-objects very badly.
- */
- const char *ep = strchr(p->name, '\n');
- int len = ep ? ep - p->name : strlen(p->name);
- write_or_die(1, sha1_to_hex(p->item->sha1), 40);
- write_or_die(1, " ", 1);
- if (len)
- write_or_die(1, p->name, len);
- write_or_die(1, "\n", 1);
-}
-
-static void show_edge(struct commit *commit)
-{
- ; /* nothing to do */
+ return list_refs(&header->references, argc, argv);
}
static int create_bundle(struct bundle_header *header, const char *path,
@@ -273,19 +262,23 @@ static int create_bundle(struct bundle_header *header, const char *path,
{
int bundle_fd = -1;
const char **argv_boundary = xmalloc((argc + 4) * sizeof(const char *));
- const char **argv_pack = xmalloc(4 * sizeof(const char *));
- int pid, in, out, i, status;
+ const char **argv_pack = xmalloc(5 * sizeof(const char *));
+ int pid, in, out, i, status, ref_count = 0;
char buffer[1024];
struct rev_info revs;
bundle_fd = (!strcmp(path, "-") ? 1 :
- open(path, O_CREAT | O_WRONLY, 0666));
+ open(path, O_CREAT | O_EXCL | O_WRONLY, 0666));
if (bundle_fd < 0)
- return error("Could not write to '%s'", path);
+ return error("Could not create '%s': %s", path, strerror(errno));
/* write signature */
write_or_die(bundle_fd, bundle_signature, strlen(bundle_signature));
+ /* init revs to list objects for pack-objects later */
+ save_commit_buffer = 0;
+ init_revisions(&revs, NULL);
+
/* write prerequisites */
memcpy(argv_boundary + 3, argv + 1, argc * sizeof(const char *));
argv_boundary[0] = "rev-list";
@@ -296,9 +289,20 @@ static int create_bundle(struct bundle_header *header, const char *path,
pid = fork_with_pipe(argv_boundary, NULL, &out);
if (pid < 0)
return -1;
- while ((i = read_string(out, buffer, sizeof(buffer))) > 0)
- if (buffer[0] == '-')
+ while ((i = read_string(out, buffer, sizeof(buffer))) > 0) {
+ unsigned char sha1[20];
+ if (buffer[0] == '-') {
write_or_die(bundle_fd, buffer, i);
+ if (!get_sha1_hex(buffer + 1, sha1)) {
+ struct object *object = parse_object(sha1);
+ object->flags |= UNINTERESTING;
+ add_pending_object(&revs, object, buffer);
+ }
+ } else if (!get_sha1_hex(buffer, sha1)) {
+ struct object *object = parse_object(sha1);
+ object->flags |= SHOWN;
+ }
+ }
while ((i = waitpid(pid, &status, 0)) < 0)
if (errno != EINTR)
return error("rev-list died");
@@ -306,28 +310,38 @@ static int create_bundle(struct bundle_header *header, const char *path,
return error("rev-list died %d", WEXITSTATUS(status));
/* write references */
- save_commit_buffer = 0;
- init_revisions(&revs, NULL);
- revs.tag_objects = 1;
- revs.tree_objects = 1;
- revs.blob_objects = 1;
argc = setup_revisions(argc, argv, &revs, NULL);
if (argc > 1)
return error("unrecognized argument: %s'", argv[1]);
+
for (i = 0; i < revs.pending.nr; i++) {
struct object_array_entry *e = revs.pending.objects + i;
- if (!(e->item->flags & UNINTERESTING)) {
- unsigned char sha1[20];
- char *ref;
- if (dwim_ref(e->name, strlen(e->name), sha1, &ref) != 1)
- continue;
- write_or_die(bundle_fd, sha1_to_hex(e->item->sha1), 40);
- write_or_die(bundle_fd, " ", 1);
- write_or_die(bundle_fd, ref, strlen(ref));
- write_or_die(bundle_fd, "\n", 1);
- free(ref);
+ unsigned char sha1[20];
+ char *ref;
+
+ if (e->item->flags & UNINTERESTING)
+ continue;
+ if (dwim_ref(e->name, strlen(e->name), sha1, &ref) != 1)
+ continue;
+ /*
+ * Make sure the refs we wrote out is correct; --max-count and
+ * other limiting options could have prevented all the tips
+ * from getting output.
+ */
+ if (!(e->item->flags & SHOWN)) {
+ warn("ref '%s' is excluded by the rev-list options",
+ e->name);
+ continue;
}
+ ref_count++;
+ write_or_die(bundle_fd, sha1_to_hex(e->item->sha1), 40);
+ write_or_die(bundle_fd, " ", 1);
+ write_or_die(bundle_fd, ref, strlen(ref));
+ write_or_die(bundle_fd, "\n", 1);
+ free(ref);
}
+ if (!ref_count)
+ die ("Refusing to create empty bundle.");
/* end header */
write_or_die(bundle_fd, "\n", 1);
@@ -336,36 +350,42 @@ static int create_bundle(struct bundle_header *header, const char *path,
argv_pack[0] = "pack-objects";
argv_pack[1] = "--all-progress";
argv_pack[2] = "--stdout";
- argv_pack[3] = NULL;
+ argv_pack[3] = "--thin";
+ argv_pack[4] = NULL;
in = -1;
out = bundle_fd;
pid = fork_with_pipe(argv_pack, &in, &out);
if (pid < 0)
return error("Could not spawn pack-objects");
- close(1);
- dup2(in, 1);
+ for (i = 0; i < revs.pending.nr; i++) {
+ struct object *object = revs.pending.objects[i].item;
+ if (object->flags & UNINTERESTING)
+ write(in, "^", 1);
+ write(in, sha1_to_hex(object->sha1), 40);
+ write(in, "\n", 1);
+ }
close(in);
- prepare_revision_walk(&revs);
- mark_edges_uninteresting(revs.commits, &revs, show_edge);
- traverse_commit_list(&revs, show_commit, show_object);
- close(1);
while (waitpid(pid, &status, 0) < 0)
if (errno != EINTR)
return -1;
if (!WIFEXITED(status) || WEXITSTATUS(status))
return error ("pack-objects died");
- return 0;
+
+ return status;
}
static int unbundle(struct bundle_header *header, int bundle_fd,
int argc, const char **argv)
{
- const char *argv_index_pack[] = {"index-pack", "--stdin", NULL};
+ const char *argv_index_pack[] = {"index-pack",
+ "--fix-thin", "--stdin", NULL};
int pid, status, dev_null;
- if (verify_bundle(header))
+ if (verify_bundle(header, 0))
return -1;
dev_null = open("/dev/null", O_WRONLY);
+ if (dev_null < 0)
+ return error("Could not open /dev/null");
pid = fork_with_pipe(argv_index_pack, &bundle_fd, &dev_null);
if (pid < 0)
return error("Could not spawn index-pack");
@@ -402,12 +422,12 @@ int cmd_bundle(int argc, const char **argv, const char *prefix)
memset(&header, 0, sizeof(header));
if (strcmp(cmd, "create") &&
- !(bundle_fd = read_header(bundle_file, &header)))
+ (bundle_fd = read_header(bundle_file, &header)) < 0)
return 1;
if (!strcmp(cmd, "verify")) {
close(bundle_fd);
- if (verify_bundle(&header))
+ if (verify_bundle(&header, 1))
return 1;
fprintf(stderr, "%s is okay\n", bundle_file);
return 0;
@@ -427,4 +447,3 @@ int cmd_bundle(int argc, const char **argv, const char *prefix)
} else
usage(bundle_usage);
}
-
diff --git a/builtin-fsck.c b/builtin-fsck.c
index 39cfc3281..b8e71b640 100644
--- a/builtin-fsck.c
+++ b/builtin-fsck.c
@@ -18,6 +18,9 @@ static int check_full;
static int check_strict;
static int keep_cache_objects;
static unsigned char head_sha1[20];
+static int errors_found;
+#define ERROR_OBJECT 01
+#define ERROR_REACHABLE 02
#ifdef NO_D_INO_IN_DIRENT
#define SORT_DIRENT 0
@@ -40,6 +43,7 @@ static int objerror(struct object *obj, const char *err, ...)
{
va_list params;
va_start(params, err);
+ errors_found |= ERROR_OBJECT;
objreport(obj, "error", err, params);
va_end(params);
return -1;
@@ -67,9 +71,10 @@ static void check_reachable_object(struct object *obj)
* do a full fsck
*/
if (!obj->parsed) {
- if (has_sha1_file(obj->sha1))
+ if (has_sha1_pack(obj->sha1, NULL))
return; /* it is in pack - forget about it */
printf("missing %s %s\n", typename(obj->type), sha1_to_hex(obj->sha1));
+ errors_found |= ERROR_REACHABLE;
return;
}
@@ -88,6 +93,7 @@ static void check_reachable_object(struct object *obj)
typename(obj->type), sha1_to_hex(obj->sha1));
printf(" to %7s %s\n",
typename(ref->type), sha1_to_hex(ref->sha1));
+ errors_found |= ERROR_REACHABLE;
}
}
}
@@ -346,8 +352,11 @@ static int fsck_tag(struct tag *tag)
static int fsck_sha1(unsigned char *sha1)
{
struct object *obj = parse_object(sha1);
- if (!obj)
- return error("%s: object corrupt or missing", sha1_to_hex(sha1));
+ if (!obj) {
+ errors_found |= ERROR_OBJECT;
+ return error("%s: object corrupt or missing",
+ sha1_to_hex(sha1));
+ }
if (obj->flags & SEEN)
return 0;
obj->flags |= SEEN;
@@ -359,8 +368,10 @@ static int fsck_sha1(unsigned char *sha1)
return fsck_commit((struct commit *) obj);
if (obj->type == OBJ_TAG)
return fsck_tag((struct tag *) obj);
+
/* By now, parse_object() would've returned NULL instead. */
- return objerror(obj, "unknown type '%d' (internal fsck error)", obj->type);
+ return objerror(obj, "unknown type '%d' (internal fsck error)",
+ obj->type);
}
/*
@@ -576,11 +587,16 @@ static int fsck_cache_tree(struct cache_tree *it)
return err;
}
+static const char fsck_usage[] =
+"git-fsck [--tags] [--root] [[--unreachable] [--cache] [--full] "
+"[--strict] <head-sha1>*]";
+
int cmd_fsck(int argc, char **argv, const char *prefix)
{
int i, heads;
track_object_refs = 1;
+ errors_found = 0;
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
@@ -610,7 +626,7 @@ int cmd_fsck(int argc, char **argv, const char *prefix)
continue;
}
if (*arg == '-')
- usage("git-fsck [--tags] [--root] [[--unreachable] [--cache] [--full] [--strict] <head-sha1>*]");
+ usage(fsck_usage);
}
fsck_head_link();
@@ -690,5 +706,5 @@ int cmd_fsck(int argc, char **argv, const char *prefix)
}
check_connectivity();
- return 0;
+ return errors_found;
}
diff --git a/builtin-grep.c b/builtin-grep.c
index 694da5ba0..4510d3532 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -431,6 +431,19 @@ static const char emsg_missing_context_len[] =
static const char emsg_missing_argument[] =
"option requires an argument -%s";
+static int strtoul_ui(char const *s, unsigned int *result)
+{
+ unsigned long ul;
+ char *p;
+
+ errno = 0;
+ ul = strtoul(s, &p, 10);
+ if (errno || *p || p == s || (unsigned int) ul != ul)
+ return -1;
+ *result = ul;
+ return 0;
+}
+
int cmd_grep(int argc, const char **argv, const char *prefix)
{
int hit = 0;
@@ -553,7 +566,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
scan = arg + 1;
break;
}
- if (sscanf(scan, "%u", &num) != 1)
+ if (strtoul_ui(scan, &num))
die(emsg_invalid_context_len, scan);
switch (arg[1]) {
case 'A':
diff --git a/builtin-log.c b/builtin-log.c
index 1c9f7d02a..865832c85 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -482,10 +482,22 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
memcpy(add_signoff, committer, endpos - committer + 1);
add_signoff[endpos - committer + 1] = 0;
}
- else if (!strcmp(argv[i], "--attach"))
+ else if (!strcmp(argv[i], "--attach")) {
rev.mime_boundary = git_version_string;
- else if (!prefixcmp(argv[i], "--attach="))
+ rev.no_inline = 1;
+ }
+ else if (!prefixcmp(argv[i], "--attach=")) {
+ rev.mime_boundary = argv[i] + 9;
+ rev.no_inline = 1;
+ }
+ else if (!strcmp(argv[i], "--inline")) {
+ rev.mime_boundary = git_version_string;
+ rev.no_inline = 0;
+ }
+ else if (!prefixcmp(argv[i], "--inline=")) {
rev.mime_boundary = argv[i] + 9;
+ rev.no_inline = 0;
+ }
else if (!strcmp(argv[i], "--ignore-if-in-upstream"))
ignore_if_in_upstream = 1;
else if (!strcmp(argv[i], "--thread"))
diff --git a/builtin-push.c b/builtin-push.c
index 979efcc45..6ab9a28e8 100644
--- a/builtin-push.c
+++ b/builtin-push.c
@@ -336,7 +336,7 @@ static int do_push(const char *repo)
argv[dest_argc] = NULL;
if (verbose)
fprintf(stderr, "Pushing to %s\n", dest);
- err = run_command_v(argv);
+ err = run_command_v_opt(argv, 0);
if (!err)
continue;
switch (err) {
diff --git a/builtin-revert.c b/builtin-revert.c
new file mode 100644
index 000000000..652eece5a
--- /dev/null
+++ b/builtin-revert.c
@@ -0,0 +1,404 @@
+#include "cache.h"
+#include "builtin.h"
+#include "object.h"
+#include "commit.h"
+#include "tag.h"
+#include "wt-status.h"
+#include "run-command.h"
+#include "exec_cmd.h"
+#include "utf8.h"
+
+/*
+ * This implements the builtins revert and cherry-pick.
+ *
+ * Copyright (c) 2007 Johannes E. Schindelin
+ *
+ * Based on git-revert.sh, which is
+ *
+ * Copyright (c) 2005 Linus Torvalds
+ * Copyright (c) 2005 Junio C Hamano
+ */
+
+static const char *revert_usage = "git-revert [--edit | --no-edit] [-n] <commit-ish>";
+
+static const char *cherry_pick_usage = "git-cherry-pick [--edit] [-n] [-r] [-x] <commit-ish>";
+
+static int edit;
+static int replay;
+enum { REVERT, CHERRY_PICK } action;
+static int no_commit;
+static struct commit *commit;
+static int needed_deref;
+
+static const char *me;
+
+#define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
+
+static void parse_options(int argc, const char **argv)
+{
+ const char *usage_str = action == REVERT ?
+ revert_usage : cherry_pick_usage;
+ unsigned char sha1[20];
+ const char *arg;
+ int i;
+
+ if (argc < 2)
+ usage(usage_str);
+
+ for (i = 1; i < argc - 1; i++) {
+ arg = argv[i];
+ if (!strcmp(arg, "-n") || !strcmp(arg, "--no-commit"))
+ no_commit = 1;
+ else if (!strcmp(arg, "-e") || !strcmp(arg, "--edit"))
+ edit = 1;
+ else if (!strcmp(arg, "--no-edit"))
+ edit = 0;
+ else if (!strcmp(arg, "-x") || !strcmp(arg, "--i-really-want-"
+ "to-expose-my-private-commit-object-name"))
+ replay = 0;
+ else if (strcmp(arg, "-r"))
+ usage(usage_str);
+ }
+
+ arg = argv[argc - 1];
+ if (get_sha1(arg, sha1))
+ die ("Cannot find '%s'", arg);
+ commit = (struct commit *)parse_object(sha1);
+ if (!commit)
+ die ("Could not find %s", sha1_to_hex(sha1));
+ if (commit->object.type == OBJ_TAG) {
+ commit = (struct commit *)
+ deref_tag((struct object *)commit, arg, strlen(arg));
+ needed_deref = 1;
+ }
+ if (commit->object.type != OBJ_COMMIT)
+ die ("'%s' does not point to a commit", arg);
+}
+
+static char *get_oneline(const char *message)
+{
+ char *result;
+ const char *p = message, *abbrev, *eol;
+ int abbrev_len, oneline_len;
+
+ if (!p)
+ die ("Could not read commit message of %s",
+ sha1_to_hex(commit->object.sha1));
+ while (*p && (*p != '\n' || p[1] != '\n'))
+ p++;
+
+ if (*p) {
+ p += 2;
+ for (eol = p + 1; *eol && *eol != '\n'; eol++)
+ ; /* do nothing */
+ } else
+ eol = p;
+ abbrev = find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV);
+ abbrev_len = strlen(abbrev);
+ oneline_len = eol - p;
+ result = xmalloc(abbrev_len + 5 + oneline_len);
+ memcpy(result, abbrev, abbrev_len);
+ memcpy(result + abbrev_len, "... ", 4);
+ memcpy(result + abbrev_len + 4, p, oneline_len);
+ result[abbrev_len + 4 + oneline_len] = '\0';
+ return result;
+}
+
+char *get_encoding(const char *message)
+{
+ const char *p = message, *eol;
+
+ if (!p)
+ die ("Could not read commit message of %s",
+ sha1_to_hex(commit->object.sha1));
+ while (*p && *p != '\n') {
+ for (eol = p + 1; *eol && *eol != '\n'; eol++)
+ ; /* do nothing */
+ if (!prefixcmp(p, "encoding ")) {
+ char *result = xmalloc(eol - 8 - p);
+ strlcpy(result, p + 9, eol - 8 - p);
+ return result;
+ }
+ p = eol;
+ if (*p == '\n')
+ p++;
+ }
+ return NULL;
+}
+
+struct lock_file msg_file;
+static int msg_fd;
+
+static void add_to_msg(const char *string)
+{
+ int len = strlen(string);
+ if (write_in_full(msg_fd, string, len) < 0)
+ die ("Could not write to .msg");
+}
+
+static void add_message_to_msg(const char *message)
+{
+ const char *p = message;
+ while (*p && (*p != '\n' || p[1] != '\n'))
+ p++;
+
+ if (!*p)
+ add_to_msg(sha1_to_hex(commit->object.sha1));
+
+ p += 2;
+ add_to_msg(p);
+ return;
+}
+
+static void set_author_ident_env(const char *message)
+{
+ const char *p = message;
+ if (!p)
+ die ("Could not read commit message of %s",
+ sha1_to_hex(commit->object.sha1));
+ while (*p && *p != '\n') {
+ const char *eol;
+
+ for (eol = p; *eol && *eol != '\n'; eol++)
+ ; /* do nothing */
+ if (!prefixcmp(p, "author ")) {
+ char *line, *pend, *email, *timestamp;
+
+ p += 7;
+ line = xmalloc(eol + 1 - p);
+ memcpy(line, p, eol - p);
+ line[eol - p] = '\0';
+ email = strchr(line, '<');
+ if (!email)
+ die ("Could not extract author email from %s",
+ sha1_to_hex(commit->object.sha1));
+ if (email == line)
+ pend = line;
+ else
+ for (pend = email; pend != line + 1 &&
+ isspace(pend[-1]); pend--);
+ ; /* do nothing */
+ *pend = '\0';
+ email++;
+ timestamp = strchr(email, '>');
+ if (!timestamp)
+ die ("Could not extract author email from %s",
+ sha1_to_hex(commit->object.sha1));
+ *timestamp = '\0';
+ for (timestamp++; *timestamp && isspace(*timestamp);
+ timestamp++)
+ ; /* do nothing */
+ setenv("GIT_AUTHOR_NAME", line, 1);
+ setenv("GIT_AUTHOR_EMAIL", email, 1);
+ setenv("GIT_AUTHOR_DATE", timestamp, 1);
+ free(line);
+ return;
+ }
+ p = eol;
+ if (*p == '\n')
+ p++;
+ }
+ die ("No author information found in %s",
+ sha1_to_hex(commit->object.sha1));
+}
+
+static int merge_recursive(const char *base_sha1,
+ const char *head_sha1, const char *head_name,
+ const char *next_sha1, const char *next_name)
+{
+ char buffer[256];
+ const char *argv[6];
+
+ sprintf(buffer, "GITHEAD_%s", head_sha1);
+ setenv(buffer, head_name, 1);
+ sprintf(buffer, "GITHEAD_%s", next_sha1);
+ setenv(buffer, next_name, 1);
+
+ /*
+ * This three way merge is an interesting one. We are at
+ * $head, and would want to apply the change between $commit
+ * and $prev on top of us (when reverting), or the change between
+ * $prev and $commit on top of us (when cherry-picking or replaying).
+ */
+ argv[0] = "merge-recursive";
+ argv[1] = base_sha1;
+ argv[2] = "--";
+ argv[3] = head_sha1;
+ argv[4] = next_sha1;
+ argv[5] = NULL;
+
+ return run_command_v_opt(argv, RUN_COMMAND_NO_STDIN | RUN_GIT_CMD);
+}
+
+static int revert_or_cherry_pick(int argc, const char **argv)
+{
+ unsigned char head[20];
+ struct commit *base, *next;
+ int i;
+ char *oneline, *encoding, *reencoded_message = NULL;
+ const char *message;
+
+ git_config(git_default_config);
+ me = action == REVERT ? "revert" : "cherry-pick";
+ setenv(GIT_REFLOG_ACTION, me, 0);
+ parse_options(argc, argv);
+
+ /* this is copied from the shell script, but it's never triggered... */
+ if (action == REVERT && replay)
+ die("revert is incompatible with replay");
+
+ if (no_commit) {
+ /*
+ * We do not intend to commit immediately. We just want to
+ * merge the differences in.
+ */
+ if (write_tree(head, 0, NULL))
+ die ("Your index file is unmerged.");
+ } else {
+ struct wt_status s;
+
+ if (get_sha1("HEAD", head))
+ die ("You do not have a valid HEAD");
+ wt_status_prepare(&s);
+ if (s.commitable || s.workdir_dirty)
+ die ("Dirty index: cannot %s", me);
+ discard_cache();
+ }
+
+ if (!commit->parents)
+ die ("Cannot %s a root commit", me);
+ if (commit->parents->next)
+ die ("Cannot %s a multi-parent commit.", me);
+ if (!(message = commit->buffer))
+ die ("Cannot get commit message for %s",
+ sha1_to_hex(commit->object.sha1));
+
+ /*
+ * "commit" is an existing commit. We would want to apply
+ * the difference it introduces since its first parent "prev"
+ * on top of the current HEAD if we are cherry-pick. Or the
+ * reverse of it if we are revert.
+ */
+
+ msg_fd = hold_lock_file_for_update(&msg_file, ".msg", 1);
+
+ encoding = get_encoding(message);
+ if (!encoding)
+ encoding = "utf-8";
+ if (!git_commit_encoding)
+ git_commit_encoding = "utf-8";
+ if ((reencoded_message = reencode_string(message,
+ git_commit_encoding, encoding)))
+ message = reencoded_message;
+
+ oneline = get_oneline(message);
+
+ if (action == REVERT) {
+ base = commit;
+ next = commit->parents->item;
+ add_to_msg("Revert ");
+ add_to_msg(find_unique_abbrev(commit->object.sha1,
+ DEFAULT_ABBREV));
+ add_to_msg(oneline);
+ add_to_msg("\nThis reverts commit ");
+ add_to_msg(sha1_to_hex(commit->object.sha1));
+ add_to_msg(".\n");
+ } else {
+ base = commit->parents->item;
+ next = commit;
+ set_author_ident_env(message);
+ add_message_to_msg(message);
+ if (!replay) {
+ add_to_msg("(cherry picked from commit ");
+ add_to_msg(sha1_to_hex(commit->object.sha1));
+ add_to_msg(")\n");
+ }
+ }
+ if (needed_deref) {
+ add_to_msg("(original 'git ");
+ add_to_msg(me);
+ add_to_msg("' arguments: ");
+ for (i = 0; i < argc; i++) {
+ if (i)
+ add_to_msg(" ");
+ add_to_msg(argv[i]);
+ }
+ add_to_msg(")\n");
+ }
+
+ if (merge_recursive(sha1_to_hex(base->object.sha1),
+ sha1_to_hex(head), "HEAD",
+ sha1_to_hex(next->object.sha1), oneline) ||
+ write_tree(head, 0, NULL)) {
+ const char *target = git_path("MERGE_MSG");
+ add_to_msg("\nConflicts:\n\n");
+ read_cache();
+ for (i = 0; i < active_nr;) {
+ struct cache_entry *ce = active_cache[i++];
+ if (ce_stage(ce)) {
+ add_to_msg("\t");
+ add_to_msg(ce->name);
+ add_to_msg("\n");
+ while (i < active_nr && !strcmp(ce->name,
+ active_cache[i]->name))
+ i++;
+ }
+ }
+ if (close(msg_fd) || commit_lock_file(&msg_file) < 0)
+ die ("Error wrapping up .msg");
+ unlink(target);
+ if (rename(".msg", target))
+ die ("Could not move .msg to %s", target);
+ fprintf(stderr, "Automatic %s failed. "
+ "After resolving the conflicts,\n"
+ "mark the corrected paths with 'git-add <paths>'\n"
+ "and commit the result.\n", me);
+ if (action == CHERRY_PICK) {
+ fprintf(stderr, "When commiting, use the option "
+ "'-c %s' to retain authorship and message.\n",
+ find_unique_abbrev(commit->object.sha1,
+ DEFAULT_ABBREV));
+ }
+ exit(1);
+ }
+ if (close(msg_fd) || commit_lock_file(&msg_file) < 0)
+ die ("Error wrapping up .msg");
+ fprintf(stderr, "Finished one %s.\n", me);
+
+ /*
+ *
+ * If we are cherry-pick, and if the merge did not result in
+ * hand-editing, we will hit this commit and inherit the original
+ * author date and name.
+ * If we are revert, or if our cherry-pick results in a hand merge,
+ * we had better say that the current user is responsible for that.
+ */
+
+ if (!no_commit) {
+ if (edit)
+ return execl_git_cmd("commit", "-n", "-F", ".msg",
+ "-e", NULL);
+ else
+ return execl_git_cmd("commit", "-n", "-F", ".msg",
+ NULL);
+ }
+ if (reencoded_message)
+ free(reencoded_message);
+
+ return 0;
+}
+
+int cmd_revert(int argc, const char **argv, const char *prefix)
+{
+ if (isatty(0))
+ edit = 1;
+ action = REVERT;
+ return revert_or_cherry_pick(argc, argv);
+}
+
+int cmd_cherry_pick(int argc, const char **argv, const char *prefix)
+{
+ replay = 1;
+ action = CHERRY_PICK;
+ return revert_or_cherry_pick(argc, argv);
+}
diff --git a/builtin-shortlog.c b/builtin-shortlog.c
index 2d7726e8b..29343aefc 100644
--- a/builtin-shortlog.c
+++ b/builtin-shortlog.c
@@ -304,8 +304,11 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix)
if (!access(".mailmap", R_OK))
read_mailmap(".mailmap");
- if (rev.pending.nr == 0)
+ if (rev.pending.nr == 0) {
+ if (isatty(0))
+ fprintf(stderr, "(reading log to summarize from standard input)\n");
read_from_stdin(&list);
+ }
else
get_from_rev(&rev, &list);
diff --git a/builtin.h b/builtin.h
index 528074b61..c58d3e344 100644
--- a/builtin.h
+++ b/builtin.h
@@ -24,6 +24,7 @@ extern int cmd_cat_file(int argc, const char **argv, const char *prefix);
extern int cmd_checkout_index(int argc, const char **argv, const char *prefix);
extern int cmd_check_ref_format(int argc, const char **argv, const char *prefix);
extern int cmd_cherry(int argc, const char **argv, const char *prefix);
+extern int cmd_cherry_pick(int argc, const char **argv, const char *prefix);
extern int cmd_commit_tree(int argc, const char **argv, const char *prefix);
extern int cmd_count_objects(int argc, const char **argv, const char *prefix);
extern int cmd_describe(int argc, const char **argv, const char *prefix);
@@ -60,6 +61,7 @@ extern int cmd_config(int argc, const char **argv, const char *prefix);
extern int cmd_rerere(int argc, const char **argv, const char *prefix);
extern int cmd_rev_list(int argc, const char **argv, const char *prefix);
extern int cmd_rev_parse(int argc, const char **argv, const char *prefix);
+extern int cmd_revert(int argc, const char **argv, const char *prefix);
extern int cmd_rm(int argc, const char **argv, const char *prefix);
extern int cmd_runstatus(int argc, const char **argv, const char *prefix);
extern int cmd_shortlog(int argc, const char **argv, const char *prefix);
diff --git a/cache.h b/cache.h
index ae25759c4..faed2a899 100644
--- a/cache.h
+++ b/cache.h
@@ -281,7 +281,6 @@ char *enter_repo(char *path, int strict);
/* Read and unpack a sha1 file into memory, write memory to a sha1 file */
extern int sha1_object_info(const unsigned char *, unsigned long *);
-extern void * unpack_sha1_file(void *map, unsigned long mapsize, enum object_type *type, unsigned long *size);
extern void * read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size);
extern int hash_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *sha1);
extern int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *return_sha1);
@@ -481,6 +480,7 @@ extern struct tag *alloc_tag_node(void);
extern void alloc_report(void);
/* trace.c */
+extern int nfasprintf(char **str, const char *fmt, ...);
extern int nfvasprintf(char **str, const char *fmt, va_list va);
extern void trace_printf(const char *format, ...);
extern void trace_argv_printf(const char **argv, int count, const char *format, ...);
diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el
index 13d198229..db87a3789 100644
--- a/contrib/emacs/git.el
+++ b/contrib/emacs/git.el
@@ -891,36 +891,77 @@ and returns the process output as a string."
(with-current-buffer log-edit-parent-buffer
(git-get-filenames (git-marked-files-state 'added 'deleted 'modified))))
+(defun git-append-sign-off (name email)
+ "Append a Signed-off-by entry to the current buffer, avoiding duplicates."
+ (let ((sign-off (format "Signed-off-by: %s <%s>" name email))
+ (case-fold-search t))
+ (goto-char (point-min))
+ (unless (re-search-forward (concat "^" (regexp-quote sign-off)) nil t)
+ (goto-char (point-min))
+ (unless (re-search-forward "^Signed-off-by: " nil t)
+ (setq sign-off (concat "\n" sign-off)))
+ (goto-char (point-max))
+ (insert sign-off "\n"))))
+
+(defun git-setup-log-buffer (buffer &optional author-name author-email subject date msg)
+ "Setup the log buffer for a commit."
+ (unless git-status (error "Not in git-status buffer."))
+ (let ((merge-heads (git-get-merge-heads))
+ (dir default-directory)
+ (committer-name (git-get-committer-name))
+ (committer-email (git-get-committer-email))
+ (sign-off git-append-signed-off-by))
+ (with-current-buffer buffer
+ (cd dir)
+ (erase-buffer)
+ (insert
+ (propertize
+ (format "Author: %s <%s>\n%s%s"
+ (or author-name committer-name)
+ (or author-email committer-email)
+ (if date (format "Date: %s\n" date) "")
+ (if merge-heads
+ (format "Parent: %s\n%s\n"
+ (git-rev-parse "HEAD")
+ (mapconcat (lambda (str) (concat "Parent: " str)) merge-heads "\n"))
+ ""))
+ 'face 'git-header-face)
+ (propertize git-log-msg-separator 'face 'git-separator-face)
+ "\n")
+ (when subject (insert subject "\n\n"))
+ (cond (msg (insert msg "\n"))
+ ((file-readable-p ".dotest/msg")
+ (insert-file-contents ".dotest/msg"))
+ ((file-readable-p ".git/MERGE_MSG")
+ (insert-file-contents ".git/MERGE_MSG")))
+ ; delete empty lines at end
+ (goto-char (point-min))
+ (when (re-search-forward "\n+\\'" nil t)
+ (replace-match "\n" t t))
+ (when sign-off (git-append-sign-off committer-name committer-email)))))
+
(defun git-commit-file ()
"Commit the marked file(s), asking for a commit message."
(interactive)
(unless git-status (error "Not in git-status buffer."))
(let ((buffer (get-buffer-create "*git-commit*"))
- (merge-heads (git-get-merge-heads))
- (dir default-directory)
(coding-system (git-get-commits-coding-system))
- (sign-off git-append-signed-off-by))
- (with-current-buffer buffer
- (when (eq 0 (buffer-size))
- (cd dir)
- (erase-buffer)
- (insert
- (propertize
- (format "Author: %s <%s>\n%s"
- (git-get-committer-name) (git-get-committer-email)
- (if merge-heads
- (format "Parent: %s\n%s\n"
- (git-rev-parse "HEAD")
- (mapconcat (lambda (str) (concat "Parent: " str)) merge-heads "\n"))
- ""))
- 'face 'git-header-face)
- (propertize git-log-msg-separator 'face 'git-separator-face)
- "\n")
- (cond ((file-readable-p ".git/MERGE_MSG")
- (insert-file-contents ".git/MERGE_MSG"))
- (sign-off
- (insert (format "\n\nSigned-off-by: %s <%s>\n"
- (git-get-committer-name) (git-get-committer-email)))))))
+ author-name author-email subject date)
+ (when (eq 0 (buffer-size buffer))
+ (when (file-readable-p ".dotest/info")
+ (with-temp-buffer
+ (insert-file-contents ".dotest/info")
+ (goto-char (point-min))
+ (when (re-search-forward "^Author: \\(.*\\)\nEmail: \\(.*\\)$" nil t)
+ (setq author-name (match-string 1))
+ (setq author-email (match-string 2)))
+ (goto-char (point-min))
+ (when (re-search-forward "^Subject: \\(.*\\)$" nil t)
+ (setq subject (match-string 1)))
+ (goto-char (point-min))
+ (when (re-search-forward "^Date: \\(.*\\)$" nil t)
+ (setq date (match-string 1)))))
+ (git-setup-log-buffer buffer author-name author-email subject date))
(log-edit #'git-do-commit nil #'git-log-edit-files buffer)
(setq font-lock-keywords (font-lock-compile-keywords git-log-edit-font-lock-keywords))
(setq buffer-file-coding-system coding-system)
diff --git a/diff-lib.c b/diff-lib.c
index 778cf5824..6abb98153 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -30,22 +30,28 @@ static int read_directory(const char *path, struct path_list *list)
return 0;
}
+static int get_mode(const char *path, int *mode)
+{
+ struct stat st;
+
+ if (!path || !strcmp(path, "/dev/null"))
+ *mode = 0;
+ else if (!strcmp(path, "-"))
+ *mode = ntohl(create_ce_mode(0666));
+ else if (stat(path, &st))
+ return error("Could not access '%s'", path);
+ else
+ *mode = st.st_mode;
+ return 0;
+}
+
static int queue_diff(struct diff_options *o,
const char *name1, const char *name2)
{
- struct stat st;
int mode1 = 0, mode2 = 0;
- if (name1) {
- if (stat(name1, &st))
- return error("Could not access '%s'", name1);
- mode1 = st.st_mode;
- }
- if (name2) {
- if (stat(name2, &st))
- return error("Could not access '%s'", name2);
- mode2 = st.st_mode;
- }
+ if (get_mode(name1, &mode1) || get_mode(name2, &mode2))
+ return -1;
if (mode1 && mode2 && S_ISDIR(mode1) != S_ISDIR(mode2))
return error("file/directory conflict: %s, %s", name1, name2);
@@ -224,7 +230,7 @@ int setup_diff_no_index(struct rev_info *revs,
{
int i;
for (i = 1; i < argc; i++)
- if (argv[i][0] != '-')
+ if (argv[i][0] != '-' || argv[i][1] == '\0')
break;
else if (!strcmp(argv[i], "--")) {
i++;
@@ -254,9 +260,15 @@ int setup_diff_no_index(struct rev_info *revs,
revs->diffopt.paths = xcalloc(2, sizeof(char*));
for (i = 0; i < 2; i++) {
- const char *p;
- p = prefix_filename(prefix, len, argv[argc - 2 + i]);
- revs->diffopt.paths[i] = xstrdup(p);
+ const char *p = argv[argc - 2 + i];
+ /*
+ * stdin should be spelled as '-'; if you have
+ * path that is '-', spell it as ./-.
+ */
+ p = (strcmp(p, "-")
+ ? xstrdup(prefix_filename(prefix, len, p))
+ : p);
+ revs->diffopt.paths[i] = p;
}
}
else
diff --git a/diff.c b/diff.c
index 8f7a7d110..954ca83e0 100644
--- a/diff.c
+++ b/diff.c
@@ -1364,6 +1364,32 @@ static struct sha1_size_cache *locate_size_cache(unsigned char *sha1,
return e;
}
+static int populate_from_stdin(struct diff_filespec *s)
+{
+#define INCREMENT 1024
+ char *buf;
+ unsigned long size;
+ int got;
+
+ size = 0;
+ buf = NULL;
+ while (1) {
+ buf = xrealloc(buf, size + INCREMENT);
+ got = xread(0, buf + size, INCREMENT);
+ if (!got)
+ break; /* EOF */
+ if (got < 0)
+ return error("error while reading from stdin %s",
+ strerror(errno));
+ size += got;
+ }
+ s->should_munmap = 0;
+ s->data = buf;
+ s->size = size;
+ s->should_free = 1;
+ return 0;
+}
+
/*
* While doing rename detection and pickaxe operation, we may need to
* grab the data for the blob (or file) for our own in-core comparison.
@@ -1389,6 +1415,9 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)
char *buf;
unsigned long size;
+ if (!strcmp(s->path, "-"))
+ return populate_from_stdin(s);
+
if (lstat(s->path, &st) < 0) {
if (errno == ENOENT) {
err_empty:
@@ -1690,6 +1719,10 @@ static void diff_fill_sha1_info(struct diff_filespec *one)
if (DIFF_FILE_VALID(one)) {
if (!one->sha1_valid) {
struct stat st;
+ if (!strcmp(one->path, "-")) {
+ hashcpy(one->sha1, null_sha1);
+ return;
+ }
if (lstat(one->path, &st) < 0)
die("stat %s", one->path);
if (index_path(one->sha1, one->path, &st, 0))
diff --git a/fast-import.c b/fast-import.c
index 726f5ba7d..55ffae4fa 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -1058,7 +1058,7 @@ static void load_tree(struct tree_entry *root)
struct tree_entry *e = new_tree_entry();
if (t->entry_count == t->entry_capacity)
- root->tree = t = grow_tree_content(t, 8);
+ root->tree = t = grow_tree_content(t, t->entry_count);
t->entries[t->entry_count++] = e;
e->tree = NULL;
@@ -1066,7 +1066,7 @@ static void load_tree(struct tree_entry *root)
if (!c)
die("Corrupt mode in %s", sha1_to_hex(sha1));
e->versions[0].mode = e->versions[1].mode;
- e->name = to_atom(c, (unsigned short)strlen(c));
+ e->name = to_atom(c, strlen(c));
c += e->name->str_len + 1;
hashcpy(e->versions[0].sha1, (unsigned char*)c);
hashcpy(e->versions[1].sha1, (unsigned char*)c);
@@ -1225,9 +1225,9 @@ static int tree_content_set(
}
if (t->entry_count == t->entry_capacity)
- root->tree = t = grow_tree_content(t, 8);
+ root->tree = t = grow_tree_content(t, t->entry_count);
e = new_tree_entry();
- e->name = to_atom(p, (unsigned short)n);
+ e->name = to_atom(p, n);
e->versions[0].mode = 0;
hashclr(e->versions[0].sha1);
t->entries[t->entry_count++] = e;
diff --git a/git-checkout.sh b/git-checkout.sh
index 14835a4aa..6caa9fdcc 100755
--- a/git-checkout.sh
+++ b/git-checkout.sh
@@ -12,6 +12,7 @@ new=
new_name=
force=
branch=
+track=
newbranch=
newbranch_log=
merge=
@@ -33,7 +34,10 @@ while [ "$#" != "0" ]; do
die "git checkout: we do not like '$newbranch' as a branch name."
;;
"-l")
- newbranch_log=1
+ newbranch_log=-l
+ ;;
+ "--track"|"--no-track")
+ track="$arg"
;;
"-f")
force=1
@@ -85,6 +89,11 @@ while [ "$#" != "0" ]; do
esac
done
+case "$new_branch,$track" in
+,--*)
+ die "git checkout: --track and --no-track require -b"
+esac
+
case "$force$merge" in
11)
die "git checkout: -f and -m are incompatible"
@@ -235,11 +244,7 @@ fi
#
if [ "$?" -eq 0 ]; then
if [ "$newbranch" ]; then
- if [ "$newbranch_log" ]; then
- mkdir -p $(dirname "$GIT_DIR/logs/refs/heads/$newbranch")
- touch "$GIT_DIR/logs/refs/heads/$newbranch"
- fi
- git-update-ref -m "checkout: Created from $new_name" "refs/heads/$newbranch" $new || exit
+ git-branch $track $newbranch_log "$newbranch" "$new_name" || exit
branch="$newbranch"
fi
if test -n "$branch"
diff --git a/git-commit.sh b/git-commit.sh
index b8c00b823..3656d607d 100755
--- a/git-commit.sh
+++ b/git-commit.sh
@@ -3,7 +3,7 @@
# Copyright (c) 2005 Linus Torvalds
# Copyright (c) 2006 Junio C Hamano
-USAGE='[-a] [-s] [-v] [--no-verify] [-m <message> | -F <logfile> | (-C|-c) <commit> | --amend] [-u] [-e] [--author <author>] [[-i | -o] <path>...]'
+USAGE='[-a | --interactive] [-s] [-v] [--no-verify] [-m <message> | -F <logfile> | (-C|-c) <commit> | --amend] [-u] [-e] [--author <author>] [[-i | -o] <path>...]'
SUBDIRECTORY_OK=Yes
. git-sh-setup
require_work_tree
@@ -71,6 +71,7 @@ trap '
all=
also=
+interactive=
only=
logfile=
use_commit=
@@ -131,6 +132,11 @@ do
also=t
shift
;;
+ --int|--inte|--inter|--intera|--interac|--interact|--interacti|\
+ --interactiv|--interactive)
+ interactive=t
+ shift
+ ;;
-o|--o|--on|--onl|--only)
only=t
shift
@@ -304,12 +310,14 @@ case "$#,$also,$only,$amend" in
;;
esac
unset only
-case "$all,$also,$#" in
-t,t,*)
- die "Cannot use -a and -i at the same time." ;;
+case "$all,$interactive,$also,$#" in
+*t,*t,*)
+ die "Cannot use -a, --interactive or -i at the same time." ;;
t,,[1-9]*)
die "Paths with -a does not make sense." ;;
-,t,0)
+,t,[1-9]*)
+ die "Paths with --interactive does not make sense." ;;
+,,t,0)
die "No paths with -i does not make sense." ;;
esac
@@ -344,6 +352,9 @@ t,)
) || exit
;;
,)
+ if test "$interactive" = t; then
+ git add --interactive || exit
+ fi
case "$#" in
0)
;; # commit as-is
diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index 1bf892e4c..65fcc8404 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -957,12 +957,12 @@ sub req_update
{
$log->info("Merged successfully");
print "M M $filename\n";
- $log->debug("Update-existing $dirpart");
+ $log->debug("Merged $dirpart");
# Don't want to actually _DO_ the update if -n specified
unless ( $state->{globaloptions}{-n} )
{
- print "Update-existing $dirpart\n";
+ print "Merged $dirpart\n";
$log->debug($state->{CVSROOT} . "/$state->{module}/$filename");
print $state->{CVSROOT} . "/$state->{module}/$filename\n";
my $kopts = kopts_from_path($filepart);
@@ -978,7 +978,7 @@ sub req_update
# Don't want to actually _DO_ the update if -n specified
unless ( $state->{globaloptions}{-n} )
{
- print "Update-existing $dirpart\n";
+ print "Merged $dirpart\n";
print $state->{CVSROOT} . "/$state->{module}/$filename\n";
my $kopts = kopts_from_path($filepart);
print "/$filepart/1.$meta->{revision}/+/$kopts/\n";
diff --git a/git-gui/.gitignore b/git-gui/.gitignore
index 805ca2e1c..c714d382e 100644
--- a/git-gui/.gitignore
+++ b/git-gui/.gitignore
@@ -1,4 +1,3 @@
-CREDITS-FILE
GIT-VERSION-FILE
git-citool
git-gui
diff --git a/git-gui/CREDITS-GEN b/git-gui/CREDITS-GEN
deleted file mode 100755
index d1b0f8635..000000000
--- a/git-gui/CREDITS-GEN
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/bin/sh
-
-CF=CREDITS-FILE
-tip=
-
-tree_search ()
-{
- head=$1
- tree=$2
- for p in $(git rev-list --parents --max-count=1 $head 2>/dev/null)
- do
- test $tree = $(git rev-parse $p^{tree} 2>/dev/null) &&
- vn=$(git describe --abbrev=4 $p 2>/dev/null) &&
- case "$vn" in
- gitgui-[0-9]*) echo $p; break;;
- esac
- done
-}
-
-generate_credits ()
-{
- tip=$1 &&
- rm -f "$2" &&
- git shortlog -n -s $tip | sed 's/: .*$//' >"$2" || exit
-}
-
-# Always use the tarball credits file if found, just
-# in case we are somehow contained in a larger git
-# repository that doesn't actually track our state.
-# (At least one package manager is doing this.)
-#
-# We may be a subproject, so try looking for the merge
-# commit that supplied this directory content if we are
-# not at the toplevel. We probably will always be the
-# second parent in the commit, but we shouldn't rely on
-# that fact.
-#
-
-credits_tmp=/var/tmp/gitgui-credits-$$
-trap 'rm -f "$credits_tmp"' 0
-
-orig="$credits_tmp"
-
-if test -f credits
-then
- orig=credits
-elif prefix="$(git rev-parse --show-prefix 2>/dev/null)" &&
- test -n "$prefix" &&
- head=$(git rev-list --max-count=1 HEAD -- . 2>/dev/null) &&
- tree=$(git rev-parse --verify "HEAD:$prefix" 2>/dev/null) &&
- tip=$(tree_search $head $tree) &&
- test -n "$tip"
-then
- generate_credits $tip "$orig" || exit
-elif tip="$(git rev-parse --verify HEAD 2>/dev/null)" &&
- test -n "$tip"
-then
- generate_credits $tip "$orig" || exit
-else
- echo "error: Cannot locate authorship information." >&2
- exit 1
-fi
-
-if test -f "$orig" && cmp -s "$orig" "$CF"
-then
- : noop
-else
- rm -f "$CF" &&
- cat "$orig" >"$CF"
-fi
-
diff --git a/git-gui/Makefile b/git-gui/Makefile
index e486e8f98..b82789ead 100644
--- a/git-gui/Makefile
+++ b/git-gui/Makefile
@@ -7,8 +7,9 @@ GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
@$(SHELL_PATH) ./GIT-VERSION-GEN
-include GIT-VERSION-FILE
+SCRIPT_SH = git-gui.sh
GITGUI_BUILT_INS = git-citool
-ALL_PROGRAMS = git-gui $(GITGUI_BUILT_INS)
+ALL_PROGRAMS = $(GITGUI_BUILT_INS) $(patsubst %.sh,%,$(SCRIPT_SH))
ifndef SHELL_PATH
SHELL_PATH = /bin/sh
@@ -27,28 +28,29 @@ ifndef V
QUIET_BUILT_IN = @echo ' ' BUILTIN $@;
endif
+ifeq ($(findstring $(MAKEFLAGS),s),s)
+QUIET_GEN =
+QUIET_BUILT_IN =
+endif
+
DESTDIR_SQ = $(subst ','\'',$(DESTDIR))
gitexecdir_SQ = $(subst ','\'',$(gitexecdir))
SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
-git-gui: git-gui.sh GIT-VERSION-FILE CREDITS-FILE
+$(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
$(QUIET_GEN)rm -f $@ $@+ && \
- sed -n \
- -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
+ sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
-e 's/@@GITGUI_VERSION@@/$(GITGUI_VERSION)/g' \
- -e '1,/^set gitgui_credits /p' \
$@.sh >$@+ && \
- cat CREDITS-FILE >>$@+ && \
- sed -e '1,/^set gitgui_credits /d' $@.sh >>$@+ && \
chmod +x $@+ && \
mv $@+ $@
-CREDITS-FILE: CREDITS-GEN .FORCE-CREDITS-FILE
- $(QUIET_GEN)$(SHELL_PATH) ./CREDITS-GEN
-
$(GITGUI_BUILT_INS): git-gui
$(QUIET_BUILT_IN)rm -f $@ && ln git-gui $@
+# These can record GITGUI_VERSION
+$(patsubst %.sh,%,$(SCRIPT_SH)): GIT-VERSION-FILE
+
all:: $(ALL_PROGRAMS)
install: all
@@ -56,14 +58,12 @@ install: all
$(INSTALL) git-gui '$(DESTDIR_SQ)$(gitexecdir_SQ)'
$(foreach p,$(GITGUI_BUILT_INS), rm -f '$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' && ln '$(DESTDIR_SQ)$(gitexecdir_SQ)/git-gui' '$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' ;)
-dist-version: CREDITS-FILE
+dist-version:
@mkdir -p $(TARDIR)
@echo $(GITGUI_VERSION) > $(TARDIR)/version
- @cat CREDITS-FILE > $(TARDIR)/credits
clean::
- rm -f $(ALL_PROGRAMS) GIT-VERSION-FILE CREDITS-FILE
+ rm -f $(ALL_PROGRAMS) GIT-VERSION-FILE
.PHONY: all install dist-version clean
.PHONY: .FORCE-GIT-VERSION-FILE
-.PHONY: .FORCE-CREDITS-FILE
diff --git a/git-gui/git-gui.sh b/git-gui/git-gui.sh
index 1981827a8..60e79ca1b 100755
--- a/git-gui/git-gui.sh
+++ b/git-gui/git-gui.sh
@@ -19,9 +19,6 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA}
-set gitgui_credits {
-Paul Mackerras
-}
######################################################################
##
@@ -302,6 +299,11 @@ proc ask_popup {msg} {
##
## version check
+if {{--version} eq $argv || {version} eq $argv} {
+ puts "git-gui version $appvers"
+ exit
+}
+
set req_maj 1
set req_min 5
@@ -1171,7 +1173,7 @@ File [short_path $path] cannot be committed by this program.
}
}
}
- if {!$files_ready} {
+ if {!$files_ready && ![string match *merge $curType]} {
info_popup {No changes to commit.
You must add at least 1 file before you can commit.
@@ -4492,61 +4494,6 @@ proc do_commit {} {
commit_tree
}
-proc do_credits {} {
- global gitgui_credits
-
- set w .credits_dialog
-
- toplevel $w
- wm geometry $w "+[winfo rootx .]+[winfo rooty .]"
-
- label $w.header -text {git-gui Contributors} -font font_uibold
- pack $w.header -side top -fill x
-
- frame $w.buttons
- button $w.buttons.close -text {Close} \
- -font font_ui \
- -command [list destroy $w]
- pack $w.buttons.close -side right
- pack $w.buttons -side bottom -fill x -pady 10 -padx 10
-
- frame $w.credits
- text $w.credits.t \
- -background [$w.header cget -background] \
- -yscrollcommand [list $w.credits.sby set] \
- -width 20 \
- -height 10 \
- -wrap none \
- -borderwidth 1 \
- -relief solid \
- -padx 5 -pady 5 \
- -font font_ui
- scrollbar $w.credits.sby -command [list $w.credits.t yview]
- pack $w.credits.sby -side right -fill y
- pack $w.credits.t -fill both -expand 1
- pack $w.credits -side top -fill both -expand 1 -padx 5 -pady 5
-
- label $w.desc \
- -text "All portions are copyrighted by their respective authors
-and are distributed under the GNU General Public License." \
- -padx 5 -pady 5 \
- -justify left \
- -anchor w \
- -borderwidth 1 \
- -relief solid \
- -font font_ui
- pack $w.desc -side top -fill x -padx 5 -pady 5
-
- $w.credits.t insert end "[string trim $gitgui_credits]\n"
- $w.credits.t conf -state disabled
- $w.credits.t see 1.0
-
- bind $w <Visibility> "grab $w; focus $w"
- bind $w <Key-Escape> [list destroy $w]
- wm title $w [$w.header cget -text]
- tkwait window $w
-}
-
proc do_about {} {
global appvers copyright
global tcl_patchLevel tk_patchLevel
@@ -4563,10 +4510,6 @@ proc do_about {} {
button $w.buttons.close -text {Close} \
-font font_ui \
-command [list destroy $w]
- button $w.buttons.credits -text {Contributors} \
- -font font_ui \
- -command do_credits
- pack $w.buttons.credits -side left
pack $w.buttons.close -side right
pack $w.buttons -side bottom -fill x -pady 10 -padx 10
@@ -5116,8 +5059,6 @@ enable_option branch
enable_option transport
switch -- $subcommand {
---version -
-version -
browser -
blame {
disable_option multicommit
@@ -5488,11 +5429,6 @@ bind all <$M1B-Key-W> {destroy [winfo toplevel %W]}
# -- Not a normal commit type invocation? Do that instead!
#
switch -- $subcommand {
---version -
-version {
- puts "git-gui version $appvers"
- exit
-}
browser {
if {[llength $argv] != 1} {
puts stderr "usage: $argv0 browser commit"
diff --git a/git-merge.sh b/git-merge.sh
index 4afcd9531..6ce62c860 100755
--- a/git-merge.sh
+++ b/git-merge.sh
@@ -294,7 +294,12 @@ f,*)
git-update-index --refresh 2>/dev/null
new_head=$(git-rev-parse --verify "$1^0") &&
git-read-tree -v -m -u --exclude-per-directory=.gitignore $head "$new_head" &&
- finish "$new_head" "Fast forward" || exit
+ msg="Fast forward"
+ if test -n "$have_message"
+ then
+ msg="$msg (no commit created; -m option ignored)"
+ fi
+ finish "$new_head" "$msg" || exit
dropsave
exit 0
;;
diff --git a/git-mergetool.sh b/git-mergetool.sh
new file mode 100755
index 000000000..52386a544
--- /dev/null
+++ b/git-mergetool.sh
@@ -0,0 +1,352 @@
+#!/bin/sh
+#
+# This program resolves merge conflicts in git
+#
+# Copyright (c) 2006 Theodore Y. Ts'o
+#
+# This file is licensed under the GPL v2, or a later version
+# at the discretion of Junio C Hammano.
+#
+
+USAGE='[--tool=tool] [file to merge] ...'
+SUBDIRECTORY_OK=Yes
+. git-sh-setup
+require_work_tree
+
+# Returns true if the mode reflects a symlink
+function is_symlink () {
+ test "$1" = 120000
+}
+
+function local_present () {
+ test -n "$local_mode"
+}
+
+function remote_present () {
+ test -n "$remote_mode"
+}
+
+function base_present () {
+ test -n "$base_mode"
+}
+
+cleanup_temp_files () {
+ if test "$1" = --save-backup ; then
+ mv -- "$BACKUP" "$path.orig"
+ rm -f -- "$LOCAL" "$REMOTE" "$BASE"
+ else
+ rm -f -- "$LOCAL" "$REMOTE" "$BASE" "$BACKUP"
+ fi
+}
+
+function describe_file () {
+ mode="$1"
+ branch="$2"
+ file="$3"
+
+ echo -n " "
+ if test -z "$mode"; then
+ echo -n "'$path' was deleted"
+ elif is_symlink "$mode" ; then
+ echo -n "'$path' is a symlink containing '"
+ cat "$file"
+ echo -n "'"
+ else
+ if base_present; then
+ echo -n "'$path' was created"
+ else
+ echo -n "'$path' was modified"
+ fi
+ fi
+ echo " in the $branch branch"
+}
+
+
+resolve_symlink_merge () {
+ while /bin/true; do
+ echo -n "Use (r)emote or (l)ocal, or (a)bort? "
+ read ans
+ case "$ans" in
+ [lL]*)
+ git-checkout-index -f --stage=2 -- "$path"
+ git-add -- "$path"
+ cleanup_temp_files --save-backup
+ return
+ ;;
+ [rR]*)
+ git-checkout-index -f --stage=3 -- "$path"
+ git-add -- "$path"
+ cleanup_temp_files --save-backup
+ return
+ ;;
+ [qQ]*)
+ exit 1
+ ;;
+ esac
+ done
+}
+
+resolve_deleted_merge () {
+ while /bin/true; do
+ echo -n "Use (m)odified or (d)eleted file, or (a)bort? "
+ read ans
+ case "$ans" in
+ [mM]*)
+ git-add -- "$path"
+ cleanup_temp_files --save-backup
+ return
+ ;;
+ [dD]*)
+ git-rm -- "$path"
+ cleanup_temp_files
+ return
+ ;;
+ [qQ]*)
+ exit 1
+ ;;
+ esac
+ done
+}
+
+merge_file () {
+ path="$1"
+
+ if test ! -f "$path" ; then
+ echo "$path: file not found"
+ exit 1
+ fi
+
+ f=`git-ls-files -u -- "$path"`
+ if test -z "$f" ; then
+ echo "$path: file does not need merging"
+ exit 1
+ fi
+
+ BACKUP="$path.BACKUP.$$"
+ LOCAL="$path.LOCAL.$$"
+ REMOTE="$path.REMOTE.$$"
+ BASE="$path.BASE.$$"
+
+ mv -- "$path" "$BACKUP"
+ cp -- "$BACKUP" "$path"
+
+ base_mode=`git ls-files -u -- "$path" | awk '{if ($3==1) print $1;}'`
+ local_mode=`git ls-files -u -- "$path" | awk '{if ($3==2) print $1;}'`
+ remote_mode=`git ls-files -u -- "$path" | awk '{if ($3==3) print $1;}'`
+
+ base_present && git cat-file blob ":1:$path" > "$BASE" 2>/dev/null
+ local_present && git cat-file blob ":2:$path" > "$LOCAL" 2>/dev/null
+ remote_present && git cat-file blob ":3:$path" > "$REMOTE" 2>/dev/null
+
+ if test -z "$local_mode" -o -z "$remote_mode"; then
+ echo "Deleted merge conflict for $path:"
+ describe_file "$local_mode" "local" "$LOCAL"
+ describe_file "$remote_mode" "remote" "$REMOTE"
+ resolve_deleted_merge
+ return
+ fi
+
+ if is_symlink "$local_mode" || is_symlink "$remote_mode"; then
+ echo "Symlink merge conflict for $path:"
+ describe_file "$local_mode" "local" "$LOCAL"
+ describe_file "$remote_mode" "remote" "$REMOTE"
+ resolve_symlink_merge
+ return
+ fi
+
+ echo "Normal merge conflict for $path:"
+ describe_file "$local_mode" "local" "$LOCAL"
+ describe_file "$remote_mode" "remote" "$REMOTE"
+ echo -n "Hit return to start merge resolution tool ($merge_tool): "
+ read ans
+
+ case "$merge_tool" in
+ kdiff3)
+ if base_present ; then
+ (kdiff3 --auto --L1 "$path (Base)" -L2 "$path (Local)" --L3 "$path (Remote)" \
+ -o "$path" -- "$BASE" "$LOCAL" "$REMOTE" > /dev/null 2>&1)
+ else
+ (kdiff3 --auto -L1 "$path (Local)" --L2 "$path (Remote)" \
+ -o "$path" -- "$LOCAL" "$REMOTE" > /dev/null 2>&1)
+ fi
+ status=$?
+ if test "$status" -eq 0; then
+ rm "$BACKUP"
+ fi
+ ;;
+ tkdiff)
+ if base_present ; then
+ tkdiff -a "$BASE" -o "$path" -- "$LOCAL" "$REMOTE"
+ else
+ tkdiff -o "$path" -- "$LOCAL" "$REMOTE"
+ fi
+ status=$?
+ if test "$status" -eq 0; then
+ mv -- "$BACKUP" "$path.orig"
+ fi
+ ;;
+ meld)
+ touch "$BACKUP"
+ meld -- "$LOCAL" "$path" "$REMOTE"
+ if test "$path" -nt "$BACKUP" ; then
+ status=0;
+ else
+ while true; do
+ echo "$path seems unchanged."
+ echo -n "Was the merge successful? [y/n] "
+ read answer < /dev/tty
+ case "$answer" in
+ y*|Y*) status=0; break ;;
+ n*|N*) status=1; break ;;
+ esac
+ done
+ fi
+ if test "$status" -eq 0; then
+ mv -- "$BACKUP" "$path.orig"
+ fi
+ ;;
+ xxdiff)
+ touch "$BACKUP"
+ if base_present ; then
+ xxdiff -X --show-merged-pane \
+ -R 'Accel.SaveAsMerged: "Ctrl-S"' \
+ -R 'Accel.Search: "Ctrl+F"' \
+ -R 'Accel.SearchForward: "Ctrl-G"' \
+ --merged-file "$path" -- "$LOCAL" "$BASE" "$REMOTE"
+ else
+ xxdiff -X --show-merged-pane \
+ -R 'Accel.SaveAsMerged: "Ctrl-S"' \
+ -R 'Accel.Search: "Ctrl+F"' \
+ -R 'Accel.SearchForward: "Ctrl-G"' \
+ --merged-file "$path" -- "$LOCAL" "$REMOTE"
+ fi
+ if test "$path" -nt "$BACKUP" ; then
+ status=0;
+ else
+ while true; do
+ echo "$path seems unchanged."
+ echo -n "Was the merge successful? [y/n] "
+ read answer < /dev/tty
+ case "$answer" in
+ y*|Y*) status=0; break ;;
+ n*|N*) status=1; break ;;
+ esac
+ done
+ fi
+ if test "$status" -eq 0; then
+ mv -- "$BACKUP" "$path.orig"
+ fi
+ ;;
+ emerge)
+ if base_present ; then
+ emacs -f emerge-files-with-ancestor-command "$LOCAL" "$REMOTE" "$BASE" "$path"
+ else
+ emacs -f emerge-files-command "$LOCAL" "$REMOTE" "$path"
+ fi
+ status=$?
+ if test "$status" -eq 0; then
+ mv -- "$BACKUP" "$path.orig"
+ fi
+ ;;
+ esac
+ if test "$status" -ne 0; then
+ echo "merge of $path failed" 1>&2
+ mv -- "$BACKUP" "$path"
+ exit 1
+ fi
+ git add -- "$path"
+ cleanup_temp_files
+}
+
+while case $# in 0) break ;; esac
+do
+ case "$1" in
+ -t|--tool*)
+ case "$#,$1" in
+ *,*=*)
+ merge_tool=`expr "z$1" : 'z-[^=]*=\(.*\)'`
+ ;;
+ 1,*)
+ usage ;;
+ *)
+ merge_tool="$2"
+ shift ;;
+ esac
+ ;;
+ --)
+ break
+ ;;
+ -*)
+ usage
+ ;;
+ *)
+ break
+ ;;
+ esac
+ shift
+done
+
+if test -z "$merge_tool"; then
+ merge_tool=`git-config merge.tool`
+ if test $merge_tool = kdiff3 -o $merge_tool = tkdiff -o \
+ $merge_tool = xxdiff -o $merge_tool = meld ; then
+ unset merge_tool
+ fi
+fi
+
+if test -z "$merge_tool" ; then
+ if type kdiff3 >/dev/null 2>&1 && test -n "$DISPLAY"; then
+ merge_tool="kdiff3";
+ elif type tkdiff >/dev/null 2>&1 && test -n "$DISPLAY"; then
+ merge_tool=tkdiff
+ elif type xxdiff >/dev/null 2>&1 && test -n "$DISPLAY"; then
+ merge_tool=xxdiff
+ elif type meld >/dev/null 2>&1 && test -n "$DISPLAY"; then
+ merge_tool=meld
+ elif type emacs >/dev/null 2>&1; then
+ merge_tool=emerge
+ else
+ echo "No available merge resolution programs available."
+ exit 1
+ fi
+fi
+
+case "$merge_tool" in
+ kdiff3|tkdiff|meld|xxdiff)
+ if ! type "$merge_tool" > /dev/null 2>&1; then
+ echo "The merge tool $merge_tool is not available"
+ exit 1
+ fi
+ ;;
+ emerge)
+ if ! type "emacs" > /dev/null 2>&1; then
+ echo "Emacs is not available"
+ exit 1
+ fi
+ ;;
+ *)
+ echo "Unknown merge tool: $merge_tool"
+ exit 1
+ ;;
+esac
+
+if test $# -eq 0 ; then
+ files=`git ls-files -u | sed -e 's/^[^ ]* //' | sort -u`
+ if test -z "$files" ; then
+ echo "No files need merging"
+ exit 0
+ fi
+ echo Merging the files: $files
+ git ls-files -u | sed -e 's/^[^ ]* //' | sort -u | while read i
+ do
+ echo ""
+ merge_file "$i" < /dev/tty > /dev/tty
+ done
+else
+ while test $# -gt 0; do
+ echo ""
+ merge_file "$1"
+ shift
+ done
+fi
+exit 0
diff --git a/git-revert.sh b/git-revert.sh
deleted file mode 100755
index 49f00321b..000000000
--- a/git-revert.sh
+++ /dev/null
@@ -1,197 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2005 Linus Torvalds
-# Copyright (c) 2005 Junio C Hamano
-#
-
-case "$0" in
-*-revert* )
- test -t 0 && edit=-e
- replay=
- me=revert
- USAGE='[--edit | --no-edit] [-n] <commit-ish>' ;;
-*-cherry-pick* )
- replay=t
- edit=
- me=cherry-pick
- USAGE='[--edit] [-n] [-r] [-x] <commit-ish>' ;;
-* )
- echo >&2 "What are you talking about?"
- exit 1 ;;
-esac
-
-SUBDIRECTORY_OK=Yes ;# we will cd up
-. git-sh-setup
-require_work_tree
-cd_to_toplevel
-
-no_commit=
-while case "$#" in 0) break ;; esac
-do
- case "$1" in
- -n|--n|--no|--no-|--no-c|--no-co|--no-com|--no-comm|\
- --no-commi|--no-commit)
- no_commit=t
- ;;
- -e|--e|--ed|--edi|--edit)
- edit=-e
- ;;
- --n|--no|--no-|--no-e|--no-ed|--no-edi|--no-edit)
- edit=
- ;;
- -r)
- : no-op ;;
- -x|--i-really-want-to-expose-my-private-commit-object-name)
- replay=
- ;;
- -*)
- usage
- ;;
- *)
- break
- ;;
- esac
- shift
-done
-
-set_reflog_action "$me"
-
-test "$me,$replay" = "revert,t" && usage
-
-case "$no_commit" in
-t)
- # We do not intend to commit immediately. We just want to
- # merge the differences in.
- head=$(git-write-tree) ||
- die "Your index file is unmerged."
- ;;
-*)
- head=$(git-rev-parse --verify HEAD) ||
- die "You do not have a valid HEAD"
- files=$(git-diff-index --cached --name-only $head) || exit
- if [ "$files" ]; then
- die "Dirty index: cannot $me (dirty: $files)"
- fi
- ;;
-esac
-
-rev=$(git-rev-parse --verify "$@") &&
-commit=$(git-rev-parse --verify "$rev^0") ||
- die "Not a single commit $@"
-prev=$(git-rev-parse --verify "$commit^1" 2>/dev/null) ||
- die "Cannot run $me a root commit"
-git-rev-parse --verify "$commit^2" >/dev/null 2>&1 &&
- die "Cannot run $me a multi-parent commit."
-
-encoding=$(git config i18n.commitencoding || echo UTF-8)
-
-# "commit" is an existing commit. We would want to apply
-# the difference it introduces since its first parent "prev"
-# on top of the current HEAD if we are cherry-pick. Or the
-# reverse of it if we are revert.
-
-case "$me" in
-revert)
- git show -s --pretty=oneline --encoding="$encoding" $commit |
- sed -e '
- s/^[^ ]* /Revert "/
- s/$/"/
- '
- echo
- echo "This reverts commit $commit."
- test "$rev" = "$commit" ||
- echo "(original 'git revert' arguments: $@)"
- base=$commit next=$prev
- ;;
-
-cherry-pick)
- pick_author_script='
- /^author /{
- s/'\''/'\''\\'\'\''/g
- h
- s/^author \([^<]*\) <[^>]*> .*$/\1/
- s/'\''/'\''\'\'\''/g
- s/.*/GIT_AUTHOR_NAME='\''&'\''/p
-
- g
- s/^author [^<]* <\([^>]*\)> .*$/\1/
- s/'\''/'\''\'\'\''/g
- s/.*/GIT_AUTHOR_EMAIL='\''&'\''/p
-
- g
- s/^author [^<]* <[^>]*> \(.*\)$/\1/
- s/'\''/'\''\'\'\''/g
- s/.*/GIT_AUTHOR_DATE='\''&'\''/p
-
- q
- }'
-
- logmsg=`git show -s --pretty=raw --encoding="$encoding" "$commit"`
- set_author_env=`echo "$logmsg" |
- LANG=C LC_ALL=C sed -ne "$pick_author_script"`
- eval "$set_author_env"
- export GIT_AUTHOR_NAME
- export GIT_AUTHOR_EMAIL
- export GIT_AUTHOR_DATE
-
- echo "$logmsg" |
- sed -e '1,/^$/d' -e 's/^ //'
- case "$replay" in
- '')
- echo "(cherry picked from commit $commit)"
- test "$rev" = "$commit" ||
- echo "(original 'git cherry-pick' arguments: $@)"
- ;;
- esac
- base=$prev next=$commit
- ;;
-
-esac >.msg
-
-eval GITHEAD_$head=HEAD
-eval GITHEAD_$next='`git show -s \
- --pretty=oneline --encoding="$encoding" "$commit" |
- sed -e "s/^[^ ]* //"`'
-export GITHEAD_$head GITHEAD_$next
-
-# This three way merge is an interesting one. We are at
-# $head, and would want to apply the change between $commit
-# and $prev on top of us (when reverting), or the change between
-# $prev and $commit on top of us (when cherry-picking or replaying).
-
-git-merge-recursive $base -- $head $next &&
-result=$(git-write-tree 2>/dev/null) || {
- mv -f .msg "$GIT_DIR/MERGE_MSG"
- {
- echo '
-Conflicts:
-'
- git ls-files --unmerged |
- sed -e 's/^[^ ]* / /' |
- uniq
- } >>"$GIT_DIR/MERGE_MSG"
- echo >&2 "Automatic $me failed. After resolving the conflicts,"
- echo >&2 "mark the corrected paths with 'git-add <paths>'"
- echo >&2 "and commit the result."
- case "$me" in
- cherry-pick)
- echo >&2 "You may choose to use the following when making"
- echo >&2 "the commit:"
- echo >&2 "$set_author_env"
- esac
- exit 1
-}
-echo >&2 "Finished one $me."
-
-# If we are cherry-pick, and if the merge did not result in
-# hand-editing, we will hit this commit and inherit the original
-# author date and name.
-# If we are revert, or if our cherry-pick results in a hand merge,
-# we had better say that the current user is responsible for that.
-
-case "$no_commit" in
-'')
- git-commit -n -F .msg $edit
- rm -f .msg
- ;;
-esac
diff --git a/git-send-email.perl b/git-send-email.perl
index a71a192e4..6989c0260 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -149,6 +149,16 @@ if ($@) {
$term = new FakeTerm "$@: going non-interactive";
}
+my $def_chain = $repo->config_boolean('sendemail.chainreplyto');
+if ($def_chain and $def_chain eq 'false') {
+ $chain_reply_to = 0;
+}
+
+@bcclist = $repo->config('sendemail.bcc');
+if (!@bcclist or !$bcclist[0]) {
+ @bcclist = ();
+}
+
# Begin by accumulating all the variables (defined above), that we will end up
# needing, first, from the command line:
diff --git a/git-svn.perl b/git-svn.perl
index 326e89fe0..e8457893d 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -56,7 +56,7 @@ my ($_stdin, $_help, $_edit,
$_message, $_file,
$_template, $_shared,
$_version, $_fetch_all,
- $_merge, $_strategy, $_dry_run,
+ $_merge, $_strategy, $_dry_run, $_local,
$_prefix, $_no_checkout, $_verbose);
$Git::SVN::_follow_parent = 1;
my %remote_opts = ( 'username=s' => \$Git::SVN::Prompt::_username,
@@ -145,6 +145,7 @@ my %cmd = (
{ 'merge|m|M' => \$_merge,
'verbose|v' => \$_verbose,
'strategy|s=s' => \$_strategy,
+ 'local|l' => \$_local,
'fetch-all|all' => \$_fetch_all,
%fc_opts } ],
'commit-diff' => [ \&cmd_commit_diff,
@@ -439,7 +440,9 @@ sub cmd_rebase {
command_noisy('status');
exit 1;
}
- $_fetch_all ? $gs->fetch_all : $gs->fetch;
+ unless ($_local) {
+ $_fetch_all ? $gs->fetch_all : $gs->fetch;
+ }
command_noisy(rebase_cmd(), $gs->refname);
}
diff --git a/git.c b/git.c
index 04fc99a3d..fe2b74ab7 100644
--- a/git.c
+++ b/git.c
@@ -234,6 +234,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
{ "checkout-index", cmd_checkout_index, RUN_SETUP },
{ "check-ref-format", cmd_check_ref_format },
{ "cherry", cmd_cherry, RUN_SETUP },
+ { "cherry-pick", cmd_cherry_pick, RUN_SETUP | NOT_BARE },
{ "commit-tree", cmd_commit_tree, RUN_SETUP },
{ "config", cmd_config },
{ "count-objects", cmd_count_objects, RUN_SETUP },
@@ -272,6 +273,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
{ "rerere", cmd_rerere, RUN_SETUP },
{ "rev-list", cmd_rev_list, RUN_SETUP },
{ "rev-parse", cmd_rev_parse, RUN_SETUP },
+ { "revert", cmd_revert, RUN_SETUP | NOT_BARE },
{ "rm", cmd_rm, RUN_SETUP | NOT_BARE },
{ "runstatus", cmd_runstatus, RUN_SETUP | NOT_BARE },
{ "shortlog", cmd_shortlog, RUN_SETUP | USE_PAGER },
diff --git a/log-tree.c b/log-tree.c
index 6ce239d8f..8797aa14c 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -186,7 +186,7 @@ void show_log(struct rev_info *opt, const char *sep)
snprintf(subject_buffer, sizeof(subject_buffer) - 1,
"%s"
"MIME-Version: 1.0\n"
- "Content-Type: multipart/mixed;\n"
+ "Content-Type: multipart/mixed;"
" boundary=\"%s%s\"\n"
"\n"
"This is a multi-part message in MIME "
@@ -202,13 +202,15 @@ void show_log(struct rev_info *opt, const char *sep)
snprintf(buffer, sizeof(buffer) - 1,
"--%s%s\n"
- "Content-Type: text/x-patch;\n"
+ "Content-Type: text/x-patch;"
" name=\"%s.diff\"\n"
"Content-Transfer-Encoding: 8bit\n"
- "Content-Disposition: inline;\n"
+ "Content-Disposition: %s;"
" filename=\"%s.diff\"\n\n",
mime_boundary_leader, opt->mime_boundary,
- sha1, sha1);
+ sha1,
+ opt->no_inline ? "attachment" : "inline",
+ sha1);
opt->diffopt.stat_sep = buffer;
}
} else if (opt->commit_format != CMIT_FMT_USERFORMAT) {
diff --git a/perl/Makefile b/perl/Makefile
index 099beda87..17d004e5a 100644
--- a/perl/Makefile
+++ b/perl/Makefile
@@ -6,11 +6,15 @@ makfile:=perl.mak
PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
prefix_SQ = $(subst ','\'',$(prefix))
+ifndef V
+ QUIET = @
+endif
+
all install instlibdir: $(makfile)
- $(MAKE) -f $(makfile) $@
+ $(QUIET)$(MAKE) -f $(makfile) $@
clean:
- test -f $(makfile) && $(MAKE) -f $(makfile) $@ || exit 0
+ $(QUIET)test -f $(makfile) && $(MAKE) -f $(makfile) $@ || exit 0
$(RM) ppport.h
$(RM) $(makfile)
$(RM) $(makfile).old
diff --git a/receive-pack.c b/receive-pack.c
index 675c88f49..7cf58782e 100644
--- a/receive-pack.c
+++ b/receive-pack.c
@@ -67,47 +67,11 @@ struct command {
static struct command *commands;
-static const char update_hook[] = "hooks/update";
static const char pre_receive_hook[] = "hooks/pre-receive";
static const char post_receive_hook[] = "hooks/post-receive";
-static int run_hook(const char *hook_name,
- struct command *first_cmd,
- int single)
+static int hook_status(int code, const char *hook_name)
{
- struct command *cmd;
- int argc, code;
- const char **argv;
-
- for (argc = 0, cmd = first_cmd; cmd; cmd = cmd->next) {
- if (!cmd->error_string)
- argc += 3;
- if (single)
- break;
- }
-
- if (!argc || access(hook_name, X_OK) < 0)
- return 0;
-
- argv = xmalloc(sizeof(*argv) * (2 + argc));
- argv[0] = hook_name;
- for (argc = 1, cmd = first_cmd; cmd; cmd = cmd->next) {
- if (!cmd->error_string) {
- argv[argc++] = xstrdup(cmd->ref_name);
- argv[argc++] = xstrdup(sha1_to_hex(cmd->old_sha1));
- argv[argc++] = xstrdup(sha1_to_hex(cmd->new_sha1));
- }
- if (single)
- break;
- }
- argv[argc] = NULL;
-
- code = run_command_v_opt(argv,
- RUN_COMMAND_NO_STDIN | RUN_COMMAND_STDOUT_TO_STDERR);
- while (--argc > 0)
- free((char*)argv[argc]);
- free(argv);
-
switch (code) {
case 0:
return 0;
@@ -115,6 +79,8 @@ static int run_hook(const char *hook_name,
return error("hook fork failed");
case -ERR_RUN_COMMAND_EXEC:
return error("hook execute failed");
+ case -ERR_RUN_COMMAND_PIPE:
+ return error("hook pipe failed");
case -ERR_RUN_COMMAND_WAITPID:
return error("waitpid failed");
case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
@@ -129,6 +95,69 @@ static int run_hook(const char *hook_name,
}
}
+static int run_hook(const char *hook_name)
+{
+ static char buf[sizeof(commands->old_sha1) * 2 + PATH_MAX + 4];
+ struct command *cmd;
+ struct child_process proc;
+ const char *argv[2];
+ int have_input = 0, code;
+
+ for (cmd = commands; !have_input && cmd; cmd = cmd->next) {
+ if (!cmd->error_string)
+ have_input = 1;
+ }
+
+ if (!have_input || access(hook_name, X_OK) < 0)
+ return 0;
+
+ argv[0] = hook_name;
+ argv[1] = NULL;
+
+ memset(&proc, 0, sizeof(proc));
+ proc.argv = argv;
+ proc.in = -1;
+ proc.stdout_to_stderr = 1;
+
+ code = start_command(&proc);
+ if (code)
+ return hook_status(code, hook_name);
+ for (cmd = commands; cmd; cmd = cmd->next) {
+ if (!cmd->error_string) {
+ size_t n = snprintf(buf, sizeof(buf), "%s %s %s\n",
+ sha1_to_hex(cmd->old_sha1),
+ sha1_to_hex(cmd->new_sha1),
+ cmd->ref_name);
+ if (write_in_full(proc.in, buf, n) != n)
+ break;
+ }
+ }
+ return hook_status(finish_command(&proc), hook_name);
+}
+
+static int run_update_hook(struct command *cmd)
+{
+ static const char update_hook[] = "hooks/update";
+ struct child_process proc;
+ const char *argv[5];
+
+ if (access(update_hook, X_OK) < 0)
+ return 0;
+
+ argv[0] = update_hook;
+ argv[1] = cmd->ref_name;
+ argv[2] = sha1_to_hex(cmd->old_sha1);
+ argv[3] = sha1_to_hex(cmd->new_sha1);
+ argv[4] = NULL;
+
+ memset(&proc, 0, sizeof(proc));
+ proc.argv = argv;
+ proc.no_stdin = 1;
+ proc.stdout_to_stderr = 1;
+
+ return hook_status(run_command(&proc), update_hook);
+}
+
static const char *update(struct command *cmd)
{
const char *name = cmd->ref_name;
@@ -165,7 +194,7 @@ static const char *update(struct command *cmd)
return "non-fast forward";
}
}
- if (run_hook(update_hook, cmd, 1)) {
+ if (run_update_hook(cmd)) {
error("hook declined to update %s", name);
return "hook declined";
}
@@ -238,7 +267,7 @@ static void execute_commands(const char *unpacker_error)
return;
}
- if (run_hook(pre_receive_hook, commands, 0)) {
+ if (run_hook(pre_receive_hook)) {
while (cmd) {
cmd->error_string = "pre-receive hook declined";
cmd = cmd->next;
@@ -493,7 +522,7 @@ int main(int argc, char **argv)
unlink(pack_lockfile);
if (report_status)
report(unpack_status);
- run_hook(post_receive_hook, commands, 0);
+ run_hook(post_receive_hook);
run_update_post_hook(commands);
}
return 0;
diff --git a/refs.c b/refs.c
index 76c08d036..9f1fb68d0 100644
--- a/refs.c
+++ b/refs.c
@@ -921,6 +921,8 @@ static int log_ref_write(const char *ref_name, const unsigned char *old_sha1,
log_file, strerror(errno));
}
+ adjust_shared_perm(log_file);
+
msglen = 0;
if (msg) {
/* clean up the message and make sure it is a single line */
diff --git a/revision.c b/revision.c
index f5b8ae4f0..3c2eb125e 100644
--- a/revision.c
+++ b/revision.c
@@ -437,36 +437,6 @@ static void limit_list(struct rev_info *revs)
continue;
p = &commit_list_insert(commit, p)->next;
}
- if (revs->boundary) {
- /* mark the ones that are on the result list first */
- for (list = newlist; list; list = list->next) {
- struct commit *commit = list->item;
- commit->object.flags |= TMP_MARK;
- }
- for (list = newlist; list; list = list->next) {
- struct commit *commit = list->item;
- struct object *obj = &commit->object;
- struct commit_list *parent;
- if (obj->flags & UNINTERESTING)
- continue;
- for (parent = commit->parents;
- parent;
- parent = parent->next) {
- struct commit *pcommit = parent->item;
- if (!(pcommit->object.flags & UNINTERESTING))
- continue;
- pcommit->object.flags |= BOUNDARY;
- if (pcommit->object.flags & TMP_MARK)
- continue;
- pcommit->object.flags |= TMP_MARK;
- p = &commit_list_insert(pcommit, p)->next;
- }
- }
- for (list = newlist; list; list = list->next) {
- struct commit *commit = list->item;
- commit->object.flags &= ~TMP_MARK;
- }
- }
revs->commits = newlist;
}
@@ -1193,17 +1163,6 @@ static void rewrite_parents(struct rev_info *revs, struct commit *commit)
}
}
-static void mark_boundary_to_show(struct commit *commit)
-{
- struct commit_list *p = commit->parents;
- while (p) {
- commit = p->item;
- p = p->next;
- if (commit->object.flags & BOUNDARY)
- commit->object.flags |= BOUNDARY_SHOW;
- }
-}
-
static int commit_match(struct commit *commit, struct rev_info *opt)
{
if (!opt->grep_filter)
@@ -1235,15 +1194,9 @@ static struct commit *get_revision_1(struct rev_info *revs)
*/
if (!revs->limited) {
if (revs->max_age != -1 &&
- (commit->date < revs->max_age)) {
- if (revs->boundary)
- commit->object.flags |=
- BOUNDARY_SHOW | BOUNDARY;
- else
- continue;
- } else
- add_parents_to_list(revs, commit,
- &revs->commits);
+ (commit->date < revs->max_age))
+ continue;
+ add_parents_to_list(revs, commit, &revs->commits);
}
if (commit->object.flags & SHOWN)
continue;
@@ -1252,18 +1205,6 @@ static struct commit *get_revision_1(struct rev_info *revs)
revs->ignore_packed))
continue;
- /* We want to show boundary commits only when their
- * children are shown. When path-limiter is in effect,
- * rewrite_parents() drops some commits from getting shown,
- * and there is no point showing boundary parents that
- * are not shown. After rewrite_parents() rewrites the
- * parents of a commit that is shown, we mark the boundary
- * parents with BOUNDARY_SHOW.
- */
- if (commit->object.flags & BOUNDARY_SHOW) {
- commit->object.flags |= SHOWN;
- return commit;
- }
if (commit->object.flags & UNINTERESTING)
continue;
if (revs->min_age != -1 && (commit->date > revs->min_age))
@@ -1286,80 +1227,136 @@ static struct commit *get_revision_1(struct rev_info *revs)
if (revs->parents)
rewrite_parents(revs, commit);
}
- if (revs->boundary)
- mark_boundary_to_show(commit);
- commit->object.flags |= SHOWN;
return commit;
} while (revs->commits);
return NULL;
}
+static void gc_boundary(struct object_array *array)
+{
+ unsigned nr = array->nr;
+ unsigned alloc = array->alloc;
+ struct object_array_entry *objects = array->objects;
+
+ if (alloc <= nr) {
+ unsigned i, j;
+ for (i = j = 0; i < nr; i++) {
+ if (objects[i].item->flags & SHOWN)
+ continue;
+ if (i != j)
+ objects[j] = objects[i];
+ j++;
+ }
+ for (i = j; i < nr; i++)
+ objects[i].item = NULL;
+ array->nr = j;
+ }
+}
+
struct commit *get_revision(struct rev_info *revs)
{
struct commit *c = NULL;
+ struct commit_list *l;
+
+ if (revs->boundary == 2) {
+ unsigned i;
+ struct object_array *array = &revs->boundary_commits;
+ struct object_array_entry *objects = array->objects;
+ for (i = 0; i < array->nr; i++) {
+ c = (struct commit *)(objects[i].item);
+ if (!c)
+ continue;
+ if (!(c->object.flags & CHILD_SHOWN))
+ continue;
+ if (!(c->object.flags & SHOWN))
+ break;
+ }
+ if (array->nr <= i)
+ return NULL;
- if (revs->reverse) {
- struct commit_list *list;
+ c->object.flags |= SHOWN | BOUNDARY;
+ return c;
+ }
- /*
- * rev_info.reverse is used to note the fact that we
- * want to output the list of revisions in reverse
- * order. To accomplish this goal, reverse can have
- * different values:
- *
- * 0 do nothing
- * 1 reverse the list
- * 2 internal use: we have already obtained and
- * reversed the list, now we only need to yield
- * its items.
- */
+ if (revs->reverse) {
+ int limit = -1;
- if (revs->reverse == 1) {
- revs->reverse = 0;
- list = NULL;
- while ((c = get_revision(revs)))
- commit_list_insert(c, &list);
- revs->commits = list;
- revs->reverse = 2;
+ if (0 <= revs->max_count) {
+ limit = revs->max_count;
+ if (0 < revs->skip_count)
+ limit += revs->skip_count;
}
-
- if (!revs->commits)
- return NULL;
- c = revs->commits->item;
- list = revs->commits->next;
- free(revs->commits);
- revs->commits = list;
- return c;
+ l = NULL;
+ while ((c = get_revision_1(revs))) {
+ commit_list_insert(c, &l);
+ if ((0 < limit) && !--limit)
+ break;
+ }
+ revs->commits = l;
+ revs->reverse = 0;
+ revs->max_count = -1;
+ c = NULL;
}
- if (0 < revs->skip_count) {
- while ((c = get_revision_1(revs)) != NULL) {
- if (revs->skip_count-- <= 0)
+ /*
+ * Now pick up what they want to give us
+ */
+ c = get_revision_1(revs);
+ if (c) {
+ while (0 < revs->skip_count) {
+ revs->skip_count--;
+ c = get_revision_1(revs);
+ if (!c)
break;
}
}
- /* Check the max_count ... */
+ /*
+ * Check the max_count.
+ */
switch (revs->max_count) {
case -1:
break;
case 0:
- if (revs->boundary) {
- struct commit_list *list = revs->commits;
- while (list) {
- list->item->object.flags |=
- BOUNDARY_SHOW | BOUNDARY;
- list = list->next;
- }
- /* all remaining commits are boundary commits */
- revs->max_count = -1;
- revs->limited = 1;
- } else
- return NULL;
+ c = NULL;
+ break;
default:
revs->max_count--;
}
+
if (c)
+ c->object.flags |= SHOWN;
+
+ if (!revs->boundary) {
return c;
- return get_revision_1(revs);
+ }
+
+ if (!c) {
+ /*
+ * get_revision_1() runs out the commits, and
+ * we are done computing the boundaries.
+ * switch to boundary commits output mode.
+ */
+ revs->boundary = 2;
+ return get_revision(revs);
+ }
+
+ /*
+ * boundary commits are the commits that are parents of the
+ * ones we got from get_revision_1() but they themselves are
+ * not returned from get_revision_1(). Before returning
+ * 'c', we need to mark its parents that they could be boundaries.
+ */
+
+ for (l = c->parents; l; l = l->next) {
+ struct object *p;
+ p = &(l->item->object);
+ if (p->flags & (CHILD_SHOWN | SHOWN))
+ continue;
+ p->flags |= CHILD_SHOWN;
+ gc_boundary(&revs->boundary_commits);
+ add_object_array(p, NULL, &revs->boundary_commits);
+ }
+
+ return c;
}
diff --git a/revision.h b/revision.h
index 5fec1846f..6ae39e6be 100644
--- a/revision.h
+++ b/revision.h
@@ -7,7 +7,7 @@
#define SHOWN (1u<<3)
#define TMP_MARK (1u<<4) /* for isolated cases; clean after use */
#define BOUNDARY (1u<<5)
-#define BOUNDARY_SHOW (1u<<6)
+#define CHILD_SHOWN (1u<<6)
#define ADDED (1u<<7) /* Parents already parsed and added? */
#define SYMMETRIC_LEFT (1u<<8)
@@ -21,6 +21,9 @@ struct rev_info {
struct commit_list *commits;
struct object_array pending;
+ /* Parents of shown commits */
+ struct object_array boundary_commits;
+
/* Basic information */
const char *prefix;
void *prune_data;
@@ -40,10 +43,10 @@ struct rev_info {
edge_hint:1,
limited:1,
unpacked:1, /* see also ignore_packed below */
- boundary:1,
+ boundary:2,
left_right:1,
parents:1,
- reverse:2;
+ reverse:1;
/* Diff flags */
unsigned int diff:1,
@@ -74,6 +77,7 @@ struct rev_info {
const char *add_signoff;
const char *extra_headers;
const char *log_reencode;
+ int no_inline;
/* Filter by commit log message */
struct grep_opt *grep_filter;
diff --git a/run-command.c b/run-command.c
index cfbad74d1..bef9775e0 100644
--- a/run-command.c
+++ b/run-command.c
@@ -2,30 +2,70 @@
#include "run-command.h"
#include "exec_cmd.h"
-int run_command_v_opt(const char **argv, int flags)
+static inline void close_pair(int fd[2])
{
- pid_t pid = fork();
+ close(fd[0]);
+ close(fd[1]);
+}
+
+int start_command(struct child_process *cmd)
+{
+ int need_in = !cmd->no_stdin && cmd->in < 0;
+ int fdin[2];
- if (pid < 0)
+ if (need_in) {
+ if (pipe(fdin) < 0)
+ return -ERR_RUN_COMMAND_PIPE;
+ cmd->in = fdin[1];
+ cmd->close_in = 1;
+ }
+
+ cmd->pid = fork();
+ if (cmd->pid < 0) {
+ if (need_in)
+ close_pair(fdin);
return -ERR_RUN_COMMAND_FORK;
- if (!pid) {
- if (flags & RUN_COMMAND_NO_STDIN) {
+ }
+
+ if (!cmd->pid) {
+ if (cmd->no_stdin) {
int fd = open("/dev/null", O_RDWR);
dup2(fd, 0);
close(fd);
+ } else if (need_in) {
+ dup2(fdin[0], 0);
+ close_pair(fdin);
+ } else if (cmd->in) {
+ dup2(cmd->in, 0);
+ close(cmd->in);
}
- if (flags & RUN_COMMAND_STDOUT_TO_STDERR)
+
+ if (cmd->stdout_to_stderr)
dup2(2, 1);
- if (flags & RUN_GIT_CMD) {
- execv_git_cmd(argv);
+ if (cmd->git_cmd) {
+ execv_git_cmd(cmd->argv);
} else {
- execvp(argv[0], (char *const*) argv);
+ execvp(cmd->argv[0], (char *const*) cmd->argv);
}
- die("exec %s failed.", argv[0]);
+ die("exec %s failed.", cmd->argv[0]);
}
+
+ if (need_in)
+ close(fdin[0]);
+ else if (cmd->in)
+ close(cmd->in);
+
+ return 0;
+}
+
+int finish_command(struct child_process *cmd)
+{
+ if (cmd->close_in)
+ close(cmd->in);
+
for (;;) {
int status, code;
- pid_t waiting = waitpid(pid, &status, 0);
+ pid_t waiting = waitpid(cmd->pid, &status, 0);
if (waiting < 0) {
if (errno == EINTR)
@@ -33,7 +73,7 @@ int run_command_v_opt(const char **argv, int flags)
error("waitpid failed (%s)", strerror(errno));
return -ERR_RUN_COMMAND_WAITPID;
}
- if (waiting != pid)
+ if (waiting != cmd->pid)
return -ERR_RUN_COMMAND_WAITPID_WRONG_PID;
if (WIFSIGNALED(status))
return -ERR_RUN_COMMAND_WAITPID_SIGNAL;
@@ -47,47 +87,21 @@ int run_command_v_opt(const char **argv, int flags)
}
}
-int run_command_v(const char **argv)
-{
- return run_command_v_opt(argv, 0);
-}
-
-static int run_command_va_opt(int opt, const char *cmd, va_list param)
-{
- int argc;
- const char *argv[MAX_RUN_COMMAND_ARGS];
- const char *arg;
-
- argv[0] = (char*) cmd;
- argc = 1;
- while (argc < MAX_RUN_COMMAND_ARGS) {
- arg = argv[argc++] = va_arg(param, char *);
- if (!arg)
- break;
- }
- if (MAX_RUN_COMMAND_ARGS <= argc)
- return error("too many args to run %s", cmd);
- return run_command_v_opt(argv, opt);
-}
-
-int run_command_opt(int opt, const char *cmd, ...)
+int run_command(struct child_process *cmd)
{
- va_list params;
- int r;
-
- va_start(params, cmd);
- r = run_command_va_opt(opt, cmd, params);
- va_end(params);
- return r;
+ int code = start_command(cmd);
+ if (code)
+ return code;
+ return finish_command(cmd);
}
-int run_command(const char *cmd, ...)
+int run_command_v_opt(const char **argv, int opt)
{
- va_list params;
- int r;
-
- va_start(params, cmd);
- r = run_command_va_opt(0, cmd, params);
- va_end(params);
- return r;
+ struct child_process cmd;
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.argv = argv;
+ cmd.no_stdin = opt & RUN_COMMAND_NO_STDIN ? 1 : 0;
+ cmd.git_cmd = opt & RUN_GIT_CMD ? 1 : 0;
+ cmd.stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0;
+ return run_command(&cmd);
}
diff --git a/run-command.h b/run-command.h
index 59c4476ce..ff090679a 100644
--- a/run-command.h
+++ b/run-command.h
@@ -1,22 +1,33 @@
#ifndef RUN_COMMAND_H
#define RUN_COMMAND_H
-#define MAX_RUN_COMMAND_ARGS 256
enum {
ERR_RUN_COMMAND_FORK = 10000,
ERR_RUN_COMMAND_EXEC,
+ ERR_RUN_COMMAND_PIPE,
ERR_RUN_COMMAND_WAITPID,
ERR_RUN_COMMAND_WAITPID_WRONG_PID,
ERR_RUN_COMMAND_WAITPID_SIGNAL,
ERR_RUN_COMMAND_WAITPID_NOEXIT,
};
+struct child_process {
+ const char **argv;
+ pid_t pid;
+ int in;
+ unsigned close_in:1;
+ unsigned no_stdin:1;
+ unsigned git_cmd:1; /* if this is to be git sub-command */
+ unsigned stdout_to_stderr:1;
+};
+
+int start_command(struct child_process *);
+int finish_command(struct child_process *);
+int run_command(struct child_process *);
+
#define RUN_COMMAND_NO_STDIN 1
#define RUN_GIT_CMD 2 /*If this is to be git sub-command */
#define RUN_COMMAND_STDOUT_TO_STDERR 4
int run_command_v_opt(const char **argv, int opt);
-int run_command_v(const char **argv);
-int run_command_opt(int opt, const char *cmd, ...);
-int run_command(const char *cmd, ...);
#endif
diff --git a/setup.c b/setup.c
index dda67d268..a45ea8309 100644
--- a/setup.c
+++ b/setup.c
@@ -216,7 +216,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
die("Not a git repository: '%s'", gitdirenv);
}
- if (!getcwd(cwd, sizeof(cwd)) || cwd[0] != '/')
+ if (!getcwd(cwd, sizeof(cwd)-1) || cwd[0] != '/')
die("Unable to read current working directory");
offset = len = strlen(cwd);
diff --git a/sha1_file.c b/sha1_file.c
index 219a10f40..7faa8bcd5 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -967,11 +967,12 @@ static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned lon
return 0;
}
-static void *unpack_sha1_rest(z_stream *stream, void *buffer, unsigned long size)
+static void *unpack_sha1_rest(z_stream *stream, void *buffer, unsigned long size, const unsigned char *sha1)
{
int bytes = strlen(buffer) + 1;
unsigned char *buf = xmalloc(1+size);
unsigned long n;
+ int status = Z_OK;
n = stream->total_out - bytes;
if (n > size)
@@ -981,12 +982,22 @@ static void *unpack_sha1_rest(z_stream *stream, void *buffer, unsigned long size
if (bytes < size) {
stream->next_out = buf + bytes;
stream->avail_out = size - bytes;
- while (inflate(stream, Z_FINISH) == Z_OK)
- /* nothing */;
+ while (status == Z_OK)
+ status = inflate(stream, Z_FINISH);
}
buf[size] = 0;
- inflateEnd(stream);
- return buf;
+ if ((status == Z_OK || status == Z_STREAM_END) && !stream->avail_in) {
+ inflateEnd(stream);
+ return buf;
+ }
+
+ if (status < 0)
+ error("corrupt loose object '%s'", sha1_to_hex(sha1));
+ else if (stream->avail_in)
+ error("garbage at end of loose object '%s'",
+ sha1_to_hex(sha1));
+ free(buf);
+ return NULL;
}
/*
@@ -1040,7 +1051,7 @@ static int parse_sha1_header(const char *hdr, unsigned long *sizep)
return *hdr ? -1 : type_from_string(type);
}
-void * unpack_sha1_file(void *map, unsigned long mapsize, enum object_type *type, unsigned long *size)
+static void *unpack_sha1_file(void *map, unsigned long mapsize, enum object_type *type, unsigned long *size, const unsigned char *sha1)
{
int ret;
z_stream stream;
@@ -1050,7 +1061,7 @@ void * unpack_sha1_file(void *map, unsigned long mapsize, enum object_type *type
if (ret < Z_OK || (*type = parse_sha1_header(hdr, size)) < 0)
return NULL;
- return unpack_sha1_rest(&stream, hdr, *size);
+ return unpack_sha1_rest(&stream, hdr, *size, sha1);
}
static off_t get_delta_base(struct packed_git *p,
@@ -1571,7 +1582,7 @@ void *read_sha1_file(const unsigned char *sha1, enum object_type *type,
return buf;
map = map_sha1_file(sha1, &mapsize);
if (map) {
- buf = unpack_sha1_file(map, mapsize, type, size);
+ buf = unpack_sha1_file(map, mapsize, type, size, sha1);
munmap(map, mapsize);
return buf;
}
diff --git a/sha1_name.c b/sha1_name.c
index 31812d3d2..bede0e5b0 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -602,10 +602,10 @@ static int handle_one_ref(const char *path,
*/
#define ONELINE_SEEN (1u<<20)
-int get_sha1_oneline(const char *prefix, unsigned char *sha1)
+static int get_sha1_oneline(const char *prefix, unsigned char *sha1)
{
struct commit_list *list = NULL, *backup = NULL, *l;
- struct commit *commit;
+ int retval = -1;
if (prefix[0] == '!') {
if (prefix[1] != '!')
@@ -617,20 +617,24 @@ int get_sha1_oneline(const char *prefix, unsigned char *sha1)
for_each_ref(handle_one_ref, &list);
for (l = list; l; l = l->next)
commit_list_insert(l->item, &backup);
- while ((commit = pop_most_recent_commit(&list, ONELINE_SEEN))) {
+ while (list) {
char *p;
+ struct commit *commit;
+
+ commit = pop_most_recent_commit(&list, ONELINE_SEEN);
parse_object(commit->object.sha1);
if (!commit->buffer || !(p = strstr(commit->buffer, "\n\n")))
continue;
if (!prefixcmp(p + 2, prefix)) {
hashcpy(sha1, commit->object.sha1);
+ retval = 0;
break;
}
}
free_commit_list(list);
for (l = backup; l; l = l->next)
clear_commit_marks(l->item, ONELINE_SEEN);
- return commit == NULL;
+ return retval;
}
/*
diff --git a/t/diff-lib.sh b/t/diff-lib.sh
index 745a1b031..4624fe654 100755
--- a/t/diff-lib.sh
+++ b/t/diff-lib.sh
@@ -11,7 +11,7 @@ compare_diff_raw () {
sed -e "$sanitize_diff_raw" <"$1" >.tmp-1
sed -e "$sanitize_diff_raw" <"$2" >.tmp-2
- diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2
+ git diff .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2
}
sanitize_diff_raw_z='/^:/s/ '"$_x40"' '"$_x40"' \([A-Z]\)[0-9]*$/ X X \1#/'
@@ -23,7 +23,7 @@ compare_diff_raw_z () {
tr '\0' '\012' <"$1" | sed -e "$sanitize_diff_raw_z" >.tmp-1
tr '\0' '\012' <"$2" | sed -e "$sanitize_diff_raw_z" >.tmp-2
- diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2
+ git diff .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2
}
compare_diff_patch () {
@@ -37,5 +37,5 @@ compare_diff_patch () {
/^[dis]*imilarity index [0-9]*%$/d
/^index [0-9a-f]*\.\.[0-9a-f]/d
' <"$2" >.tmp-2
- diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2
+ git diff .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2
}
diff --git a/t/t1000-read-tree-m-3way.sh b/t/t1000-read-tree-m-3way.sh
index d0af8c3d5..e26a36cf0 100755
--- a/t/t1000-read-tree-m-3way.sh
+++ b/t/t1000-read-tree-m-3way.sh
@@ -131,7 +131,7 @@ _x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
check_result () {
git-ls-files --stage | sed -e 's/ '"$_x40"' / X /' >current &&
- diff -u expected current
+ git diff expected current
}
# This is done on an empty work directory, which is the normal
diff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh
index 75e4c9a88..030226bbf 100755
--- a/t/t1001-read-tree-m-2way.sh
+++ b/t/t1001-read-tree-m-2way.sh
@@ -33,7 +33,7 @@ compare_change () {
-e '/^--- /d; /^+++ /d; /^@@ /d;' \
-e 's/^\([-+][0-7][0-7][0-7][0-7][0-7][0-7]\) '"$_x40"' /\1 X /p' \
"$1"
- diff -u expected current
+ git diff expected current
}
check_cache_at () {
@@ -86,7 +86,7 @@ test_expect_success \
'rm -f .git/index &&
read_tree_twoway $treeH $treeM &&
git-ls-files --stage >1-3.out &&
- diff -u M.out 1-3.out &&
+ git diff M.out 1-3.out &&
check_cache_at bozbar dirty &&
check_cache_at frotz dirty &&
check_cache_at nitfol dirty'
@@ -101,7 +101,7 @@ test_expect_success \
git-update-index --add yomin &&
read_tree_twoway $treeH $treeM &&
git-ls-files --stage >4.out || return 1
- diff -u M.out 4.out >4diff.out
+ git diff M.out 4.out >4diff.out
compare_change 4diff.out expected &&
check_cache_at yomin clean'
@@ -115,7 +115,7 @@ test_expect_success \
echo yomin yomin >yomin &&
read_tree_twoway $treeH $treeM &&
git-ls-files --stage >5.out || return 1
- diff -u M.out 5.out >5diff.out
+ git diff M.out 5.out >5diff.out
compare_change 5diff.out expected &&
check_cache_at yomin dirty'
@@ -127,7 +127,7 @@ test_expect_success \
git-update-index --add frotz &&
read_tree_twoway $treeH $treeM &&
git-ls-files --stage >6.out &&
- diff -u M.out 6.out &&
+ git diff M.out 6.out &&
check_cache_at frotz clean'
test_expect_success \
@@ -140,7 +140,7 @@ test_expect_success \
echo frotz frotz >frotz &&
read_tree_twoway $treeH $treeM &&
git-ls-files --stage >7.out &&
- diff -u M.out 7.out &&
+ git diff M.out 7.out &&
check_cache_at frotz dirty'
test_expect_success \
@@ -171,7 +171,7 @@ test_expect_success \
git-update-index --add rezrov &&
read_tree_twoway $treeH $treeM &&
git-ls-files --stage >10.out &&
- diff -u M.out 10.out'
+ git diff M.out 10.out'
test_expect_success \
'11 - dirty path removed.' \
@@ -216,7 +216,7 @@ test_expect_success \
git-update-index --add nitfol &&
read_tree_twoway $treeH $treeM &&
git-ls-files --stage >14.out || return 1
- diff -u M.out 14.out >14diff.out
+ git diff M.out 14.out >14diff.out
compare_change 14diff.out expected &&
check_cache_at nitfol clean'
@@ -230,7 +230,7 @@ test_expect_success \
echo nitfol nitfol nitfol >nitfol &&
read_tree_twoway $treeH $treeM &&
git-ls-files --stage >15.out || return 1
- diff -u M.out 15.out >15diff.out
+ git diff M.out 15.out >15diff.out
compare_change 15diff.out expected &&
check_cache_at nitfol dirty'
@@ -262,7 +262,7 @@ test_expect_success \
git-update-index --add bozbar &&
read_tree_twoway $treeH $treeM &&
git-ls-files --stage >18.out &&
- diff -u M.out 18.out &&
+ git diff M.out 18.out &&
check_cache_at bozbar clean'
test_expect_success \
@@ -275,7 +275,7 @@ test_expect_success \
echo gnusto gnusto >bozbar &&
read_tree_twoway $treeH $treeM &&
git-ls-files --stage >19.out &&
- diff -u M.out 19.out &&
+ git diff M.out 19.out &&
check_cache_at bozbar dirty'
test_expect_success \
@@ -287,7 +287,7 @@ test_expect_success \
git-update-index --add bozbar &&
read_tree_twoway $treeH $treeM &&
git-ls-files --stage >20.out &&
- diff -u M.out 20.out &&
+ git diff M.out 20.out &&
check_cache_at bozbar dirty'
test_expect_success \
@@ -337,7 +337,7 @@ test_expect_success \
git-update-index --add DF &&
read_tree_twoway $treeDF $treeDFDF &&
git-ls-files --stage >DFDFcheck.out &&
- diff -u DFDF.out DFDFcheck.out &&
+ git diff DFDF.out DFDFcheck.out &&
check_cache_at DF/DF dirty &&
:'
diff --git a/t/t1002-read-tree-m-u-2way.sh b/t/t1002-read-tree-m-u-2way.sh
index da3c81357..87fe993f5 100755
--- a/t/t1002-read-tree-m-u-2way.sh
+++ b/t/t1002-read-tree-m-u-2way.sh
@@ -16,7 +16,7 @@ compare_change () {
sed >current \
-e '/^--- /d; /^+++ /d; /^@@ /d;' \
-e 's/^\(.[0-7][0-7][0-7][0-7][0-7][0-7]\) '"$_x40"' /\1 X /' "$1"
- diff -u expected current
+ git diff expected current
}
check_cache_at () {
diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index ee386cfbf..78c2e0864 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -368,12 +368,12 @@ cat > expect << EOF
weird
EOF
-test_expect_success "rename succeeded" "diff -u expect .git/config"
+test_expect_success "rename succeeded" "git diff expect .git/config"
test_expect_failure "rename non-existing section" \
'git-config --rename-section branch."world domination" branch.drei'
-test_expect_success "rename succeeded" "diff -u expect .git/config"
+test_expect_success "rename succeeded" "git diff expect .git/config"
test_expect_success "rename another section" \
'git-config --rename-section branch."1 234 blabl/a" branch.drei'
@@ -389,7 +389,7 @@ cat > expect << EOF
weird
EOF
-test_expect_success "rename succeeded" "diff -u expect .git/config"
+test_expect_success "rename succeeded" "git diff expect .git/config"
cat >> .git/config << EOF
[branch "zwei"] a = 1 [branch "vier"]
@@ -405,7 +405,7 @@ weird
EOF
test_expect_success "section was removed properly" \
- "diff -u expect .git/config"
+ "git diff -u expect .git/config"
test_expect_success numbers '
diff --git a/t/t3001-ls-files-others-exclude.sh b/t/t3001-ls-files-others-exclude.sh
index 6979b7c1c..db7a847a5 100755
--- a/t/t3001-ls-files-others-exclude.sh
+++ b/t/t3001-ls-files-others-exclude.sh
@@ -65,7 +65,7 @@ test_expect_success \
--exclude-per-directory=.gitignore \
--exclude-from=.git/ignore \
>output &&
- diff -u expect output'
+ git diff expect output'
# Test \r\n (MSDOS-like systems)
printf '*.1\r\n/*.3\r\n!*.6\r\n' >.gitignore
@@ -77,6 +77,6 @@ test_expect_success \
--exclude-per-directory=.gitignore \
--exclude-from=.git/ignore \
>output &&
- diff -u expect output'
+ git diff expect output'
test_done
diff --git a/t/t3002-ls-files-dashpath.sh b/t/t3002-ls-files-dashpath.sh
index b42f1382b..cc8967d76 100755
--- a/t/t3002-ls-files-dashpath.sh
+++ b/t/t3002-ls-files-dashpath.sh
@@ -23,7 +23,7 @@ test_expect_success \
test_expect_success \
'git-ls-files without path restriction.' \
'git-ls-files --others >output &&
- diff -u output - <<EOF
+ git diff output - <<EOF
--
-foo
output
@@ -34,7 +34,7 @@ EOF
test_expect_success \
'git-ls-files with path restriction.' \
'git-ls-files --others path0 >output &&
- diff -u output - <<EOF
+ git diff output - <<EOF
path0
EOF
'
@@ -42,7 +42,7 @@ EOF
test_expect_success \
'git-ls-files with path restriction with --.' \
'git-ls-files --others -- path0 >output &&
- diff -u output - <<EOF
+ git diff output - <<EOF
path0
EOF
'
@@ -50,7 +50,7 @@ EOF
test_expect_success \
'git-ls-files with path restriction with -- --.' \
'git-ls-files --others -- -- >output &&
- diff -u output - <<EOF
+ git diff output - <<EOF
--
EOF
'
@@ -58,7 +58,7 @@ EOF
test_expect_success \
'git-ls-files with no path restriction.' \
'git-ls-files --others -- >output &&
- diff -u output - <<EOF
+ git diff output - <<EOF
--
-foo
output
diff --git a/t/t3100-ls-tree-restrict.sh b/t/t3100-ls-tree-restrict.sh
index 2ec06d3d3..e10749245 100755
--- a/t/t3100-ls-tree-restrict.sh
+++ b/t/t3100-ls-tree-restrict.sh
@@ -35,7 +35,7 @@ _x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
test_output () {
sed -e "s/ $_x40 / X /" <current >check
- diff -u expected check
+ git diff expected check
}
test_expect_success \
diff --git a/t/t3101-ls-tree-dirname.sh b/t/t3101-ls-tree-dirname.sh
index d78deb1e7..087929a4b 100755
--- a/t/t3101-ls-tree-dirname.sh
+++ b/t/t3101-ls-tree-dirname.sh
@@ -43,7 +43,7 @@ _x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
test_output () {
sed -e "s/ $_x40 / X /" <current >check
- diff -u expected check
+ git diff expected check
}
test_expect_success \
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 5565c2703..75c000a96 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -47,17 +47,6 @@ test_expect_success \
test ! -f .git/refs/heads/d/e/f &&
test ! -f .git/logs/refs/heads/d/e/f'
-cat >expect <<EOF
-0000000000000000000000000000000000000000 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000 checkout: Created from master
-EOF
-test_expect_success \
- 'git checkout -b g/h/i -l should create a branch and a log' \
- 'GIT_COMMITTER_DATE="2005-05-26 23:30" \
- git-checkout -b g/h/i -l master &&
- test -f .git/refs/heads/g/h/i &&
- test -f .git/logs/refs/heads/g/h/i &&
- diff expect .git/logs/refs/heads/g/h/i'
-
test_expect_success \
'git branch j/k should work after branch j has been deleted' \
'git-branch j &&
@@ -117,4 +106,58 @@ test_expect_failure \
ln -s real-u .git/logs/refs/heads/u &&
git-branch -m u v'
+test_expect_success 'test tracking setup via --track' \
+ 'git-config remote.local.url . &&
+ git-config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+ (git-show-ref -q refs/remotes/local/master || git-fetch local) &&
+ git-branch --track my1 local/master &&
+ test $(git-config branch.my1.remote) = local &&
+ test $(git-config branch.my1.merge) = refs/heads/master'
+
+test_expect_success 'test tracking setup (non-wildcard, matching)' \
+ 'git-config remote.local.url . &&
+ git-config remote.local.fetch refs/heads/master:refs/remotes/local/master &&
+ (git-show-ref -q refs/remotes/local/master || git-fetch local) &&
+ git-branch --track my4 local/master &&
+ test $(git-config branch.my4.remote) = local &&
+ test $(git-config branch.my4.merge) = refs/heads/master'
+
+test_expect_success 'test tracking setup (non-wildcard, not matching)' \
+ 'git-config remote.local.url . &&
+ git-config remote.local.fetch refs/heads/s:refs/remotes/local/s &&
+ (git-show-ref -q refs/remotes/local/master || git-fetch local) &&
+ git-branch --track my5 local/master &&
+ ! test $(git-config branch.my5.remote) = local &&
+ ! test $(git-config branch.my5.merge) = refs/heads/master'
+
+test_expect_success 'test tracking setup via config' \
+ 'git-config branch.autosetupmerge true &&
+ git-config remote.local.url . &&
+ git-config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+ (git-show-ref -q refs/remotes/local/master || git-fetch local) &&
+ git-branch my3 local/master &&
+ test $(git-config branch.my3.remote) = local &&
+ test $(git-config branch.my3.merge) = refs/heads/master'
+
+test_expect_success 'test overriding tracking setup via --no-track' \
+ 'git-config branch.autosetupmerge true &&
+ git-config remote.local.url . &&
+ git-config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
+ (git-show-ref -q refs/remotes/local/master || git-fetch local) &&
+ git-branch --no-track my2 local/master &&
+ ! test $(git-config branch.my2.remote) = local &&
+ ! test $(git-config branch.my2.merge) = refs/heads/master'
+
+# Keep this test last, as it changes the current branch
+cat >expect <<EOF
+0000000000000000000000000000000000000000 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000 branch: Created from master
+EOF
+test_expect_success \
+ 'git checkout -b g/h/i -l should create a branch and a log' \
+ 'GIT_COMMITTER_DATE="2005-05-26 23:30" \
+ git-checkout -b g/h/i -l master &&
+ test -f .git/refs/heads/g/h/i &&
+ test -f .git/logs/refs/heads/g/h/i &&
+ diff expect .git/logs/refs/heads/g/h/i'
+
test_done
diff --git a/t/t3300-funny-names.sh b/t/t3300-funny-names.sh
index c12270efa..b5a1400e1 100755
--- a/t/t3300-funny-names.sh
+++ b/t/t3300-funny-names.sh
@@ -35,7 +35,7 @@ no-funny' >expected
test_expect_success 'git-ls-files no-funny' \
'git-update-index --add "$p0" "$p2" &&
git-ls-files >current &&
- diff -u expected current'
+ git diff expected current'
t0=`git-write-tree`
echo "$t0" >t0
@@ -48,14 +48,14 @@ EOF
test_expect_success 'git-ls-files with-funny' \
'git-update-index --add "$p1" &&
git-ls-files >current &&
- diff -u expected current'
+ git diff expected current'
echo 'just space
no-funny
tabs ," (dq) and spaces' >expected
test_expect_success 'git-ls-files -z with-funny' \
'git-ls-files -z | tr \\0 \\012 >current &&
- diff -u expected current'
+ git diff expected current'
t1=`git-write-tree`
echo "$t1" >t1
@@ -67,28 +67,28 @@ no-funny
EOF
test_expect_success 'git-ls-tree with funny' \
'git-ls-tree -r $t1 | sed -e "s/^[^ ]* //" >current &&
- diff -u expected current'
+ git diff expected current'
cat > expected <<\EOF
A "tabs\t,\" (dq) and spaces"
EOF
test_expect_success 'git-diff-index with-funny' \
'git-diff-index --name-status $t0 >current &&
- diff -u expected current'
+ git diff expected current'
test_expect_success 'git-diff-tree with-funny' \
'git-diff-tree --name-status $t0 $t1 >current &&
- diff -u expected current'
+ git diff expected current'
echo 'A
tabs ," (dq) and spaces' >expected
test_expect_success 'git-diff-index -z with-funny' \
'git-diff-index -z --name-status $t0 | tr \\0 \\012 >current &&
- diff -u expected current'
+ git diff expected current'
test_expect_success 'git-diff-tree -z with-funny' \
'git-diff-tree -z --name-status $t0 $t1 | tr \\0 \\012 >current &&
- diff -u expected current'
+ git diff expected current'
cat > expected <<\EOF
CNUM no-funny "tabs\t,\" (dq) and spaces"
@@ -96,7 +96,7 @@ EOF
test_expect_success 'git-diff-tree -C with-funny' \
'git-diff-tree -C --find-copies-harder --name-status \
$t0 $t1 | sed -e 's/^C[0-9]*/CNUM/' >current &&
- diff -u expected current'
+ git diff expected current'
cat > expected <<\EOF
RNUM no-funny "tabs\t,\" (dq) and spaces"
@@ -105,7 +105,7 @@ test_expect_success 'git-diff-tree delete with-funny' \
'git-update-index --force-remove "$p0" &&
git-diff-index -M --name-status \
$t0 | sed -e 's/^R[0-9]*/RNUM/' >current &&
- diff -u expected current'
+ git diff expected current'
cat > expected <<\EOF
diff --git a/no-funny "b/tabs\t,\" (dq) and spaces"
@@ -116,7 +116,7 @@ EOF
test_expect_success 'git-diff-tree delete with-funny' \
'git-diff-index -M -p $t0 |
sed -e "s/index [0-9]*%/index NUM%/" >current &&
- diff -u expected current'
+ git diff expected current'
chmod +x "$p1"
cat > expected <<\EOF
@@ -130,7 +130,7 @@ EOF
test_expect_success 'git-diff-tree delete with-funny' \
'git-diff-index -M -p $t0 |
sed -e "s/index [0-9]*%/index NUM%/" >current &&
- diff -u expected current'
+ git diff expected current'
cat >expected <<\EOF
"tabs\t,\" (dq) and spaces"
@@ -139,7 +139,7 @@ EOF
test_expect_success 'git-diff-tree rename with-funny applied' \
'git-diff-index -M -p $t0 |
git-apply --stat | sed -e "s/|.*//" -e "s/ *\$//" >current &&
- diff -u expected current'
+ git diff expected current'
cat > expected <<\EOF
no-funny
@@ -149,12 +149,12 @@ EOF
test_expect_success 'git-diff-tree delete with-funny applied' \
'git-diff-index -p $t0 |
git-apply --stat | sed -e "s/|.*//" -e "s/ *\$//" >current &&
- diff -u expected current'
+ git diff expected current'
test_expect_success 'git-apply non-git diff' \
'git-diff-index -p $t0 |
sed -ne "/^[-+@]/p" |
git-apply --stat | sed -e "s/|.*//" -e "s/ *\$//" >current &&
- diff -u expected current'
+ git diff expected current'
test_done
diff --git a/t/t3900-i18n-commit.sh b/t/t3900-i18n-commit.sh
index e54fe0f40..ffddb68db 100755
--- a/t/t3900-i18n-commit.sh
+++ b/t/t3900-i18n-commit.sh
@@ -9,7 +9,7 @@ test_description='commit and log output encodings'
compare_with () {
git-show -s $1 | sed -e '1,/^$/d' -e 's/^ //' -e '$d' >current &&
- diff -u current "$2"
+ git diff current "$2"
}
test_expect_success setup '
diff --git a/t/t4006-diff-mode.sh b/t/t4006-diff-mode.sh
index ca342f48a..e72c6fd1b 100755
--- a/t/t4006-diff-mode.sh
+++ b/t/t4006-diff-mode.sh
@@ -38,7 +38,7 @@ echo ":100644 100755 X X M rezrov" >expected
test_expect_success \
'verify' \
- 'diff -u expected check'
+ 'git diff expected check'
test_done
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index 3d85ceaae..488e075c1 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -106,12 +106,12 @@ do
echo "\$ git $cmd"
git $cmd |
sed -e "s/^\\(-*\\)$V\\(-*\\)\$/\\1g-i-t--v-e-r-s-i-o-n\2/" \
- -e "s/^\\( *boundary=\"-*\\)$V\\(-*\\)\"\$/\\1g-i-t--v-e-r-s-i-o-n\2\"/"
+ -e "s/^\\(.*mixed; boundary=\"-*\\)$V\\(-*\\)\"\$/\\1g-i-t--v-e-r-s-i-o-n\2\"/"
echo "\$"
} >"$actual" &&
if test -f "$expect"
then
- diff -u "$expect" "$actual" &&
+ git diff "$expect" "$actual" &&
rm -f "$actual"
else
# this is to help developing new tests.
@@ -238,6 +238,9 @@ format-patch --stdout initial..master
format-patch --attach --stdout initial..side
format-patch --attach --stdout initial..master^
format-patch --attach --stdout initial..master
+format-patch --inline --stdout initial..side
+format-patch --inline --stdout initial..master^
+format-patch --inline --stdout initial..master
diff --abbrev initial..side
diff -r initial..side
diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master b/t/t4013/diff.format-patch_--attach_--stdout_initial..master
index e5ddd6fcb..cf6891f74 100644
--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master
+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master
@@ -4,8 +4,7 @@ From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:01:00 +0000
Subject: [PATCH] Second
MIME-Version: 1.0
-Content-Type: multipart/mixed;
- boundary="------------g-i-t--v-e-r-s-i-o-n"
+Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
This is a multi-part message in MIME format.
--------------g-i-t--v-e-r-s-i-o-n
@@ -21,11 +20,9 @@ This is the second commit.
3 files changed, 5 insertions(+), 3 deletions(-)
delete mode 100644 file2
--------------g-i-t--v-e-r-s-i-o-n
-Content-Type: text/x-patch;
- name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
+Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
Content-Transfer-Encoding: 8bit
-Content-Disposition: inline;
- filename="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
+Content-Disposition: attachment; filename="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
diff --git a/dir/sub b/dir/sub
index 35d242b..8422d40 100644
@@ -66,8 +63,7 @@ From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:02:00 +0000
Subject: [PATCH] Third
MIME-Version: 1.0
-Content-Type: multipart/mixed;
- boundary="------------g-i-t--v-e-r-s-i-o-n"
+Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
This is a multi-part message in MIME format.
--------------g-i-t--v-e-r-s-i-o-n
@@ -80,11 +76,9 @@ Content-Transfer-Encoding: 8bit
2 files changed, 5 insertions(+), 0 deletions(-)
create mode 100644 file1
--------------g-i-t--v-e-r-s-i-o-n
-Content-Type: text/x-patch;
- name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
+Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
Content-Transfer-Encoding: 8bit
-Content-Disposition: inline;
- filename="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
+Content-Disposition: attachment; filename="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
diff --git a/dir/sub b/dir/sub
index 8422d40..cead32e 100644
@@ -115,8 +109,7 @@ From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:03:00 +0000
Subject: [PATCH] Side
MIME-Version: 1.0
-Content-Type: multipart/mixed;
- boundary="------------g-i-t--v-e-r-s-i-o-n"
+Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
This is a multi-part message in MIME format.
--------------g-i-t--v-e-r-s-i-o-n
@@ -130,11 +123,9 @@ Content-Transfer-Encoding: 8bit
3 files changed, 9 insertions(+), 0 deletions(-)
create mode 100644 file3
--------------g-i-t--v-e-r-s-i-o-n
-Content-Type: text/x-patch;
- name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
+Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
Content-Transfer-Encoding: 8bit
-Content-Disposition: inline;
- filename="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
+Content-Disposition: attachment; filename="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
diff --git a/dir/sub b/dir/sub
index 35d242b..7289e35 100644
diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master^
index d0dd19b62..fe0258720 100644
--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^
+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master^
@@ -4,8 +4,7 @@ From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:01:00 +0000
Subject: [PATCH] Second
MIME-Version: 1.0
-Content-Type: multipart/mixed;
- boundary="------------g-i-t--v-e-r-s-i-o-n"
+Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
This is a multi-part message in MIME format.
--------------g-i-t--v-e-r-s-i-o-n
@@ -21,11 +20,9 @@ This is the second commit.
3 files changed, 5 insertions(+), 3 deletions(-)
delete mode 100644 file2
--------------g-i-t--v-e-r-s-i-o-n
-Content-Type: text/x-patch;
- name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
+Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
Content-Transfer-Encoding: 8bit
-Content-Disposition: inline;
- filename="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
+Content-Disposition: attachment; filename="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
diff --git a/dir/sub b/dir/sub
index 35d242b..8422d40 100644
@@ -66,8 +63,7 @@ From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:02:00 +0000
Subject: [PATCH] Third
MIME-Version: 1.0
-Content-Type: multipart/mixed;
- boundary="------------g-i-t--v-e-r-s-i-o-n"
+Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
This is a multi-part message in MIME format.
--------------g-i-t--v-e-r-s-i-o-n
@@ -80,11 +76,9 @@ Content-Transfer-Encoding: 8bit
2 files changed, 5 insertions(+), 0 deletions(-)
create mode 100644 file1
--------------g-i-t--v-e-r-s-i-o-n
-Content-Type: text/x-patch;
- name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
+Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
Content-Transfer-Encoding: 8bit
-Content-Disposition: inline;
- filename="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
+Content-Disposition: attachment; filename="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
diff --git a/dir/sub b/dir/sub
index 8422d40..cead32e 100644
diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..side b/t/t4013/diff.format-patch_--attach_--stdout_initial..side
index 67a95c5cb..9ff828ee9 100644
--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..side
+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..side
@@ -4,8 +4,7 @@ From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:03:00 +0000
Subject: [PATCH] Side
MIME-Version: 1.0
-Content-Type: multipart/mixed;
- boundary="------------g-i-t--v-e-r-s-i-o-n"
+Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
This is a multi-part message in MIME format.
--------------g-i-t--v-e-r-s-i-o-n
@@ -19,11 +18,9 @@ Content-Transfer-Encoding: 8bit
3 files changed, 9 insertions(+), 0 deletions(-)
create mode 100644 file3
--------------g-i-t--v-e-r-s-i-o-n
-Content-Type: text/x-patch;
- name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
+Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
Content-Transfer-Encoding: 8bit
-Content-Disposition: inline;
- filename="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
+Content-Disposition: attachment; filename="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
diff --git a/dir/sub b/dir/sub
index 35d242b..7289e35 100644
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_initial..master
new file mode 100644
index 000000000..aa110c0e7
--- /dev/null
+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master
@@ -0,0 +1,164 @@
+$ git format-patch --inline --stdout initial..master
+From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
+From: A U Thor <author@example.com>
+Date: Mon, 26 Jun 2006 00:01:00 +0000
+Subject: [PATCH] Second
+MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
+
+This is a multi-part message in MIME format.
+--------------g-i-t--v-e-r-s-i-o-n
+Content-Type: text/plain; charset=UTF-8; format=fixed
+Content-Transfer-Encoding: 8bit
+
+
+This is the second commit.
+---
+ dir/sub | 2 ++
+ file0 | 3 +++
+ file2 | 3 ---
+ 3 files changed, 5 insertions(+), 3 deletions(-)
+ delete mode 100644 file2
+--------------g-i-t--v-e-r-s-i-o-n
+Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
+Content-Transfer-Encoding: 8bit
+Content-Disposition: inline; filename="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
+
+diff --git a/dir/sub b/dir/sub
+index 35d242b..8422d40 100644
+--- a/dir/sub
++++ b/dir/sub
+@@ -1,2 +1,4 @@
+ A
+ B
++C
++D
+diff --git a/file0 b/file0
+index 01e79c3..b414108 100644
+--- a/file0
++++ b/file0
+@@ -1,3 +1,6 @@
+ 1
+ 2
+ 3
++4
++5
++6
+diff --git a/file2 b/file2
+deleted file mode 100644
+index 01e79c3..0000000
+--- a/file2
++++ /dev/null
+@@ -1,3 +0,0 @@
+-1
+-2
+-3
+
+--------------g-i-t--v-e-r-s-i-o-n--
+
+
+
+From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001
+From: A U Thor <author@example.com>
+Date: Mon, 26 Jun 2006 00:02:00 +0000
+Subject: [PATCH] Third
+MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
+
+This is a multi-part message in MIME format.
+--------------g-i-t--v-e-r-s-i-o-n
+Content-Type: text/plain; charset=UTF-8; format=fixed
+Content-Transfer-Encoding: 8bit
+
+---
+ dir/sub | 2 ++
+ file1 | 3 +++
+ 2 files changed, 5 insertions(+), 0 deletions(-)
+ create mode 100644 file1
+--------------g-i-t--v-e-r-s-i-o-n
+Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
+Content-Transfer-Encoding: 8bit
+Content-Disposition: inline; filename="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
+
+diff --git a/dir/sub b/dir/sub
+index 8422d40..cead32e 100644
+--- a/dir/sub
++++ b/dir/sub
+@@ -2,3 +2,5 @@ A
+ B
+ C
+ D
++E
++F
+diff --git a/file1 b/file1
+new file mode 100644
+index 0000000..b1e6722
+--- /dev/null
++++ b/file1
+@@ -0,0 +1,3 @@
++A
++B
++C
+
+--------------g-i-t--v-e-r-s-i-o-n--
+
+
+
+From c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a Mon Sep 17 00:00:00 2001
+From: A U Thor <author@example.com>
+Date: Mon, 26 Jun 2006 00:03:00 +0000
+Subject: [PATCH] Side
+MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
+
+This is a multi-part message in MIME format.
+--------------g-i-t--v-e-r-s-i-o-n
+Content-Type: text/plain; charset=UTF-8; format=fixed
+Content-Transfer-Encoding: 8bit
+
+---
+ dir/sub | 2 ++
+ file0 | 3 +++
+ file3 | 4 ++++
+ 3 files changed, 9 insertions(+), 0 deletions(-)
+ create mode 100644 file3
+--------------g-i-t--v-e-r-s-i-o-n
+Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
+Content-Transfer-Encoding: 8bit
+Content-Disposition: inline; filename="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
+
+diff --git a/dir/sub b/dir/sub
+index 35d242b..7289e35 100644
+--- a/dir/sub
++++ b/dir/sub
+@@ -1,2 +1,4 @@
+ A
+ B
++1
++2
+diff --git a/file0 b/file0
+index 01e79c3..f4615da 100644
+--- a/file0
++++ b/file0
+@@ -1,3 +1,6 @@
+ 1
+ 2
+ 3
++A
++B
++C
+diff --git a/file3 b/file3
+new file mode 100644
+index 0000000..7289e35
+--- /dev/null
++++ b/file3
+@@ -0,0 +1,4 @@
++A
++B
++1
++2
+
+--------------g-i-t--v-e-r-s-i-o-n--
+
+
+$
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^
new file mode 100644
index 000000000..95e9ea4c5
--- /dev/null
+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^
@@ -0,0 +1,106 @@
+$ git format-patch --inline --stdout initial..master^
+From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
+From: A U Thor <author@example.com>
+Date: Mon, 26 Jun 2006 00:01:00 +0000
+Subject: [PATCH] Second
+MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
+
+This is a multi-part message in MIME format.
+--------------g-i-t--v-e-r-s-i-o-n
+Content-Type: text/plain; charset=UTF-8; format=fixed
+Content-Transfer-Encoding: 8bit
+
+
+This is the second commit.
+---
+ dir/sub | 2 ++
+ file0 | 3 +++
+ file2 | 3 ---
+ 3 files changed, 5 insertions(+), 3 deletions(-)
+ delete mode 100644 file2
+--------------g-i-t--v-e-r-s-i-o-n
+Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
+Content-Transfer-Encoding: 8bit
+Content-Disposition: inline; filename="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
+
+diff --git a/dir/sub b/dir/sub
+index 35d242b..8422d40 100644
+--- a/dir/sub
++++ b/dir/sub
+@@ -1,2 +1,4 @@
+ A
+ B
++C
++D
+diff --git a/file0 b/file0
+index 01e79c3..b414108 100644
+--- a/file0
++++ b/file0
+@@ -1,3 +1,6 @@
+ 1
+ 2
+ 3
++4
++5
++6
+diff --git a/file2 b/file2
+deleted file mode 100644
+index 01e79c3..0000000
+--- a/file2
++++ /dev/null
+@@ -1,3 +0,0 @@
+-1
+-2
+-3
+
+--------------g-i-t--v-e-r-s-i-o-n--
+
+
+
+From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001
+From: A U Thor <author@example.com>
+Date: Mon, 26 Jun 2006 00:02:00 +0000
+Subject: [PATCH] Third
+MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
+
+This is a multi-part message in MIME format.
+--------------g-i-t--v-e-r-s-i-o-n
+Content-Type: text/plain; charset=UTF-8; format=fixed
+Content-Transfer-Encoding: 8bit
+
+---
+ dir/sub | 2 ++
+ file1 | 3 +++
+ 2 files changed, 5 insertions(+), 0 deletions(-)
+ create mode 100644 file1
+--------------g-i-t--v-e-r-s-i-o-n
+Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
+Content-Transfer-Encoding: 8bit
+Content-Disposition: inline; filename="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
+
+diff --git a/dir/sub b/dir/sub
+index 8422d40..cead32e 100644
+--- a/dir/sub
++++ b/dir/sub
+@@ -2,3 +2,5 @@ A
+ B
+ C
+ D
++E
++F
+diff --git a/file1 b/file1
+new file mode 100644
+index 0000000..b1e6722
+--- /dev/null
++++ b/file1
+@@ -0,0 +1,3 @@
++A
++B
++C
+
+--------------g-i-t--v-e-r-s-i-o-n--
+
+
+$
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..side b/t/t4013/diff.format-patch_--inline_--stdout_initial..side
new file mode 100644
index 000000000..86ae923d7
--- /dev/null
+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..side
@@ -0,0 +1,59 @@
+$ git format-patch --inline --stdout initial..side
+From c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a Mon Sep 17 00:00:00 2001
+From: A U Thor <author@example.com>
+Date: Mon, 26 Jun 2006 00:03:00 +0000
+Subject: [PATCH] Side
+MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
+
+This is a multi-part message in MIME format.
+--------------g-i-t--v-e-r-s-i-o-n
+Content-Type: text/plain; charset=UTF-8; format=fixed
+Content-Transfer-Encoding: 8bit
+
+---
+ dir/sub | 2 ++
+ file0 | 3 +++
+ file3 | 4 ++++
+ 3 files changed, 9 insertions(+), 0 deletions(-)
+ create mode 100644 file3
+--------------g-i-t--v-e-r-s-i-o-n
+Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
+Content-Transfer-Encoding: 8bit
+Content-Disposition: inline; filename="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
+
+diff --git a/dir/sub b/dir/sub
+index 35d242b..7289e35 100644
+--- a/dir/sub
++++ b/dir/sub
+@@ -1,2 +1,4 @@
+ A
+ B
++1
++2
+diff --git a/file0 b/file0
+index 01e79c3..f4615da 100644
+--- a/file0
++++ b/file0
+@@ -1,3 +1,6 @@
+ 1
+ 2
+ 3
++A
++B
++C
+diff --git a/file3 b/file3
+new file mode 100644
+index 0000000..7289e35
+--- /dev/null
++++ b/file3
+@@ -0,0 +1,4 @@
++A
++B
++1
++2
+
+--------------g-i-t--v-e-r-s-i-o-n--
+
+
+$
diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh
index adf4993ba..930e209d3 100755
--- a/t/t4015-diff-whitespace.sh
+++ b/t/t4015-diff-whitespace.sh
@@ -43,13 +43,13 @@ index adf3937..6edc172 100644
EOF
git-diff > out
-test_expect_success "Ray's example without options" 'diff -u expect out'
+test_expect_success "Ray's example without options" 'git diff expect out'
git-diff -w > out
-test_expect_success "Ray's example with -w" 'diff -u expect out'
+test_expect_success "Ray's example with -w" 'git diff expect out'
git-diff -b > out
-test_expect_success "Ray's example with -b" 'diff -u expect out'
+test_expect_success "Ray's example with -b" 'git diff expect out'
tr 'Q' '\015' << EOF > x
whitespace at beginning
@@ -90,14 +90,14 @@ index d99af23..8b32fb5 100644
+CR at end
EOF
git-diff > out
-test_expect_success 'another test, without options' 'diff -u expect out'
+test_expect_success 'another test, without options' 'git diff expect out'
cat << EOF > expect
diff --git a/x b/x
index d99af23..8b32fb5 100644
EOF
git-diff -w > out
-test_expect_success 'another test, with -w' 'diff -u expect out'
+test_expect_success 'another test, with -w' 'git diff expect out'
tr 'Q' '\015' << EOF > expect
diff --git a/x b/x
@@ -115,6 +115,6 @@ index d99af23..8b32fb5 100644
CR at endQ
EOF
git-diff -b > out
-test_expect_success 'another test, with -b' 'diff -u expect out'
+test_expect_success 'another test, with -b' 'git diff expect out'
test_done
diff --git a/t/t4016-diff-quote.sh b/t/t4016-diff-quote.sh
index 2e7cd5f25..5dbdc0c9f 100755
--- a/t/t4016-diff-quote.sh
+++ b/t/t4016-diff-quote.sh
@@ -49,7 +49,7 @@ cat >expect <<\EOF
EOF
test_expect_success 'git diff --summary -M HEAD' '
git diff --summary -M HEAD >actual &&
- diff -u expect actual
+ git diff expect actual
'
cat >expect <<\EOF
@@ -64,7 +64,7 @@ cat >expect <<\EOF
EOF
test_expect_success 'git diff --stat -M HEAD' '
git diff --stat -M HEAD >actual &&
- diff -u expect actual
+ git diff expect actual
'
test_done
diff --git a/t/t4100-apply-stat.sh b/t/t4100-apply-stat.sh
index 6579f06b0..7b81c32e5 100755
--- a/t/t4100-apply-stat.sh
+++ b/t/t4100-apply-stat.sh
@@ -11,37 +11,37 @@ test_description='git-apply --stat --summary test.
test_expect_success \
'rename' \
'git-apply --stat --summary <../t4100/t-apply-1.patch >current &&
- diff -u ../t4100/t-apply-1.expect current'
+ git diff ../t4100/t-apply-1.expect current'
test_expect_success \
'copy' \
'git-apply --stat --summary <../t4100/t-apply-2.patch >current &&
- diff -u ../t4100/t-apply-2.expect current'
+ git diff ../t4100/t-apply-2.expect current'
test_expect_success \
'rewrite' \
'git-apply --stat --summary <../t4100/t-apply-3.patch >current &&
- diff -u ../t4100/t-apply-3.expect current'
+ git diff ../t4100/t-apply-3.expect current'
test_expect_success \
'mode' \
'git-apply --stat --summary <../t4100/t-apply-4.patch >current &&
- diff -u ../t4100/t-apply-4.expect current'
+ git diff ../t4100/t-apply-4.expect current'
test_expect_success \
'non git' \
'git-apply --stat --summary <../t4100/t-apply-5.patch >current &&
- diff -u ../t4100/t-apply-5.expect current'
+ git diff ../t4100/t-apply-5.expect current'
test_expect_success \
'non git' \
'git-apply --stat --summary <../t4100/t-apply-6.patch >current &&
- diff -u ../t4100/t-apply-6.expect current'
+ git diff ../t4100/t-apply-6.expect current'
test_expect_success \
'non git' \
'git-apply --stat --summary <../t4100/t-apply-7.patch >current &&
- diff -u ../t4100/t-apply-7.expect current'
+ git diff ../t4100/t-apply-7.expect current'
test_done
diff --git a/t/t4104-apply-boundary.sh b/t/t4104-apply-boundary.sh
index 2ff800c23..a5fb3ea40 100755
--- a/t/t4104-apply-boundary.sh
+++ b/t/t4104-apply-boundary.sh
@@ -90,7 +90,7 @@ do
cat '"$kind-patch.$with"'
(exit 1)
} &&
- diff -u '"$kind"'-expect victim
+ git diff '"$kind"'-expect victim
'
done
done
@@ -108,7 +108,7 @@ do
cat '"$kind-ng.without"'
(exit 1)
} &&
- diff -u '"$kind"'-expect victim
+ git diff '"$kind"'-expect victim
'
done
diff --git a/t/t4115-apply-symlink.sh b/t/t4115-apply-symlink.sh
index d5f2cfb18..b947ed83b 100755
--- a/t/t4115-apply-symlink.sh
+++ b/t/t4115-apply-symlink.sh
@@ -33,7 +33,7 @@ test_expect_success 'apply symlink patch' '
git checkout side &&
git apply patch &&
git diff-files -p >patched &&
- diff -u patch patched
+ git diff patch patched
'
@@ -42,7 +42,7 @@ test_expect_success 'apply --index symlink patch' '
git checkout -f side &&
git apply --index patch &&
git diff-index --cached -p HEAD >patched &&
- diff -u patch patched
+ git diff patch patched
'
diff --git a/t/t4116-apply-reverse.sh b/t/t4116-apply-reverse.sh
index aa2c869e0..2685b2263 100755
--- a/t/t4116-apply-reverse.sh
+++ b/t/t4116-apply-reverse.sh
@@ -42,7 +42,7 @@ test_expect_success 'apply in reverse' '
git reset --hard second &&
git apply --reverse --binary --index patch &&
git diff >diff &&
- diff -u /dev/null diff
+ git diff /dev/null diff
'
diff --git a/t/t4117-apply-reject.sh b/t/t4117-apply-reject.sh
index b4de075a3..91931f0e3 100755
--- a/t/t4117-apply-reject.sh
+++ b/t/t4117-apply-reject.sh
@@ -54,7 +54,7 @@ test_expect_success 'apply without --reject should fail' '
exit 1
fi
- diff -u file1 saved.file1
+ git diff file1 saved.file1
'
test_expect_success 'apply without --reject should fail' '
@@ -65,7 +65,7 @@ test_expect_success 'apply without --reject should fail' '
exit 1
fi
- diff -u file1 saved.file1
+ git diff file1 saved.file1
'
test_expect_success 'apply with --reject should fail but update the file' '
@@ -79,7 +79,7 @@ test_expect_success 'apply with --reject should fail but update the file' '
exit 1
fi
- diff -u file1 expected &&
+ git diff file1 expected &&
cat file1.rej &&
@@ -105,7 +105,7 @@ test_expect_success 'apply with --reject should fail but update the file' '
echo "file1 still exists?"
exit 1
}
- diff -u file2 expected &&
+ git diff file2 expected &&
cat file2.rej &&
@@ -132,7 +132,7 @@ test_expect_success 'the same test with --verbose' '
echo "file1 still exists?"
exit 1
}
- diff -u file2 expected &&
+ git diff file2 expected &&
cat file2.rej &&
@@ -151,7 +151,7 @@ test_expect_success 'apply cleanly with --verbose' '
git apply --verbose patch.1 &&
- diff -u file1 clean
+ git diff file1 clean
'
test_done
diff --git a/t/t4118-apply-empty-context.sh b/t/t4118-apply-empty-context.sh
index 7309422fe..690a18200 100755
--- a/t/t4118-apply-empty-context.sh
+++ b/t/t4118-apply-empty-context.sh
@@ -37,7 +37,7 @@ test_expect_success 'apply --numstat' '
echo "0 1 file1" &&
echo "0 1 file2"
} >expect &&
- diff -u expect actual
+ git diff expect actual
'
@@ -47,8 +47,8 @@ test_expect_success 'apply --apply' '
cat file2.orig >file2 &&
git update-index file1 file2 &&
git apply --index diff.output &&
- diff -u file1.mods file1 &&
- diff -u file2.mods file2
+ git diff file1.mods file1 &&
+ git diff file2.mods file2
'
test_done
diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh
index 639d45fce..e081b32af 100755
--- a/t/t4200-rerere.sh
+++ b/t/t4200-rerere.sh
@@ -70,7 +70,7 @@ EOF
git rerere diff > out
-test_expect_success 'rerere diff' 'diff -u expect out'
+test_expect_success 'rerere diff' 'git diff expect out'
cat > expect << EOF
a1
@@ -78,7 +78,7 @@ EOF
git rerere status > out
-test_expect_success 'rerere status' 'diff -u expect out'
+test_expect_success 'rerere status' 'git diff expect out'
test_expect_success 'commit succeeds' \
"git commit -q -a -m 'prefer first over second'"
@@ -94,7 +94,7 @@ test_expect_failure 'another conflicting merge' 'git pull . first'
git show first:a1 | sed 's/To die: t/To die! T/' > expect
test_expect_success 'rerere kicked in' "! grep ======= a1"
-test_expect_success 'rerere prefers first change' 'diff -u a1 expect'
+test_expect_success 'rerere prefers first change' 'git diff a1 expect'
rm $rr/postimage
echo "$sha1 a1" | tr '\012' '\0' > .git/rr-cache/MERGE_RR
diff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh
index b1c97b0df..477b26759 100755
--- a/t/t5400-send-pack.sh
+++ b/t/t5400-send-pack.sh
@@ -110,7 +110,7 @@ test_expect_success \
cd .. &&
git-update-ref refs/heads/master master^ || return 1
git-send-pack --force ./victim/.git/ master && return 1
- ! diff .git/refs/heads/master victim/.git/refs/heads/master
+ ! git diff .git/refs/heads/master victim/.git/refs/heads/master
'
test_done
diff --git a/t/t5401-update-hooks.sh b/t/t5401-update-hooks.sh
index 0c0034e34..f1c7ff0c0 100755
--- a/t/t5401-update-hooks.sh
+++ b/t/t5401-update-hooks.sh
@@ -25,8 +25,8 @@ test_expect_success setup '
cat >victim/.git/hooks/pre-receive <<'EOF'
#!/bin/sh
-echo "$@" >>$GIT_DIR/pre-receive.args
-read x; printf "$x" >$GIT_DIR/pre-receive.stdin
+printf "$@" >>$GIT_DIR/pre-receive.args
+cat - >$GIT_DIR/pre-receive.stdin
echo STDOUT pre-receive
echo STDERR pre-receive >&2
EOF
@@ -44,8 +44,8 @@ chmod u+x victim/.git/hooks/update
cat >victim/.git/hooks/post-receive <<'EOF'
#!/bin/sh
-echo "$@" >>$GIT_DIR/post-receive.args
-read x; printf "$x" >$GIT_DIR/post-receive.stdin
+printf "$@" >>$GIT_DIR/post-receive.args
+cat - >$GIT_DIR/post-receive.stdin
echo STDOUT post-receive
echo STDERR post-receive >&2
EOF
@@ -80,36 +80,38 @@ test_expect_success 'hooks ran' '
test -f victim/.git/post-update.stdin
'
-test_expect_success 'pre-receive hook arguments' '
- echo \
- refs/heads/master $commit0 $commit1 \
- refs/heads/tofail $commit1 $commit0 \
- | diff - victim/.git/pre-receive.args
+test_expect_success 'pre-receive hook input' '
+ (echo $commit0 $commit1 refs/heads/master;
+ echo $commit1 $commit0 refs/heads/tofail
+ ) | git diff - victim/.git/pre-receive.stdin
'
test_expect_success 'update hook arguments' '
(echo refs/heads/master $commit0 $commit1;
echo refs/heads/tofail $commit1 $commit0
- ) | diff - victim/.git/update.args
+ ) | git diff - victim/.git/update.args
'
-test_expect_success 'post-receive hook arguments' '
- echo refs/heads/master $commit0 $commit1 |
- diff - victim/.git/post-receive.args
+test_expect_success 'post-receive hook input' '
+ echo $commit0 $commit1 refs/heads/master |
+ git diff - victim/.git/post-receive.stdin
'
test_expect_success 'post-update hook arguments' '
echo refs/heads/master |
- diff -u - victim/.git/post-update.args
+ git diff - victim/.git/post-update.args
'
test_expect_success 'all hook stdin is /dev/null' '
- ! test -s victim/.git/pre-receive.stdin &&
! test -s victim/.git/update.stdin &&
- ! test -s victim/.git/post-receive.stdin &&
! test -s victim/.git/post-update.stdin
'
+test_expect_success 'all *-receive hook args are empty' '
+ ! test -s victim/.git/pre-receive.args &&
+ ! test -s victim/.git/post-receive.args
+'
+
test_expect_failure 'send-pack produced no output' '
test -s send.out
'
@@ -128,7 +130,7 @@ STDERR post-update
EOF
test_expect_success 'send-pack stderr contains hook messages' '
egrep ^STD send.err >actual &&
- diff - actual <expect
+ git diff - actual <expect
'
test_done
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index fa76662dc..426017e1d 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -90,6 +90,13 @@ test_expect_success 'create bundle 1' '
git bundle create bundle1 master^..master
'
+test_expect_success 'header of bundle looks right' '
+ head -n 1 "$D"/bundle1 | grep "^#" &&
+ head -n 2 "$D"/bundle1 | grep "^-[0-9a-f]\{40\} " &&
+ head -n 3 "$D"/bundle1 | grep "^[0-9a-f]\{40\} " &&
+ head -n 4 "$D"/bundle1 | grep "^$"
+'
+
test_expect_success 'create bundle 2' '
cd "$D" &&
git bundle create bundle2 master~2..master
@@ -101,10 +108,41 @@ test_expect_failure 'unbundle 1' '
git fetch "$D/bundle1" master:master
'
+test_expect_success 'bundle 1 has only 3 files ' '
+ cd "$D" &&
+ (
+ while read x && test -n "$x"
+ do
+ :;
+ done
+ cat
+ ) <bundle1 >bundle.pack &&
+ git index-pack bundle.pack &&
+ verify=$(git verify-pack -v bundle.pack) &&
+ test 4 = $(echo "$verify" | wc -l)
+'
+
test_expect_success 'unbundle 2' '
cd "$D/bundle" &&
git fetch ../bundle2 master:master &&
test "tip" = "$(git log -1 --pretty=oneline master | cut -b42-)"
'
+test_expect_success 'bundle does not prerequisite objects' '
+ cd "$D" &&
+ touch file2 &&
+ git add file2 &&
+ git commit -m add.file2 file2 &&
+ git bundle create bundle3 -1 HEAD &&
+ (
+ while read x && test -n "$x"
+ do
+ :;
+ done
+ cat
+ ) <bundle3 >bundle.pack &&
+ git index-pack bundle.pack &&
+ test 4 = $(git verify-pack -v bundle.pack | wc -l)
+'
+
test_done
diff --git a/t/t5515-fetch-merge-logic.sh b/t/t5515-fetch-merge-logic.sh
index 0b600bb42..6c9cc6750 100755
--- a/t/t5515-fetch-merge-logic.sh
+++ b/t/t5515-fetch-merge-logic.sh
@@ -149,7 +149,7 @@ do
} >"$actual" &&
if test -f "$expect"
then
- diff -u "$expect" "$actual" &&
+ git diff -u "$expect" "$actual" &&
rm -f "$actual"
else
# this is to help developing new tests.
diff --git a/t/t6023-merge-file.sh b/t/t6023-merge-file.sh
index f3cd3dba4..c76fccfb5 100644
--- a/t/t6023-merge-file.sh
+++ b/t/t6023-merge-file.sh
@@ -63,7 +63,7 @@ test_expect_success "merge without conflict (missing LF at EOF)" \
"git-merge-file test2.txt orig.txt new2.txt"
test_expect_success "merge result added missing LF" \
- "diff -u test.txt test2.txt"
+ "git diff test.txt test2.txt"
cp test.txt backup.txt
test_expect_failure "merge with conflicts" \
@@ -86,7 +86,7 @@ non timebo mala, quoniam tu mecum es:
virga tua et baculus tuus ipsa me consolata sunt.
EOF
-test_expect_success "expected conflict markers" "diff -u test.txt expect.txt"
+test_expect_success "expected conflict markers" "git diff test.txt expect.txt"
cp backup.txt test.txt
test_expect_failure "merge with conflicts, using -L" \
@@ -110,7 +110,7 @@ virga tua et baculus tuus ipsa me consolata sunt.
EOF
test_expect_success "expected conflict markers, with -L" \
- "diff -u test.txt expect.txt"
+ "git diff test.txt expect.txt"
sed "s/ tu / TU /" < new1.txt > new5.txt
test_expect_failure "conflict in removed tail" \
@@ -132,7 +132,7 @@ virga tua et baculus tuus ipsa me consolata sunt.
>>>>>>> new5.txt
EOF
-test_expect_success "expected conflict markers" "diff -u expect out"
+test_expect_success "expected conflict markers" "git diff expect out"
test_done
diff --git a/t/t6024-recursive-merge.sh b/t/t6024-recursive-merge.sh
index 31b96257b..a39855613 100644
--- a/t/t6024-recursive-merge.sh
+++ b/t/t6024-recursive-merge.sh
@@ -70,7 +70,7 @@ G
>>>>>>> G:a1
EOF
-test_expect_success "result contains a conflict" "diff -u expect a1"
+test_expect_success "result contains a conflict" "git diff expect a1"
git ls-files --stage > out
cat > expect << EOF
@@ -79,6 +79,6 @@ cat > expect << EOF
100644 fd7923529855d0b274795ae3349c5e0438333979 3 a1
EOF
-test_expect_success "virtual trees were processed" "diff -u expect out"
+test_expect_success "virtual trees were processed" "git diff expect out"
test_done
diff --git a/t/t6200-fmt-merge-msg.sh b/t/t6200-fmt-merge-msg.sh
index ea1402361..526d7d1c4 100755
--- a/t/t6200-fmt-merge-msg.sh
+++ b/t/t6200-fmt-merge-msg.sh
@@ -79,7 +79,7 @@ test_expect_success 'merge-msg test #1' '
git fetch . left &&
git fmt-merge-msg <.git/FETCH_HEAD >actual &&
- diff -u actual expected
+ git diff actual expected
'
cat >expected <<\EOF
@@ -92,7 +92,7 @@ test_expect_success 'merge-msg test #2' '
git fetch ../trash left &&
git fmt-merge-msg <.git/FETCH_HEAD >actual &&
- diff -u actual expected
+ git diff actual expected
'
cat >expected <<\EOF
@@ -115,7 +115,7 @@ test_expect_success 'merge-msg test #3' '
git fetch . left &&
git fmt-merge-msg <.git/FETCH_HEAD >actual &&
- diff -u actual expected
+ git diff actual expected
'
cat >expected <<\EOF
@@ -145,7 +145,7 @@ test_expect_success 'merge-msg test #4' '
git fetch . left right &&
git fmt-merge-msg <.git/FETCH_HEAD >actual &&
- diff -u actual expected
+ git diff actual expected
'
test_expect_success 'merge-msg test #5' '
@@ -157,7 +157,7 @@ test_expect_success 'merge-msg test #5' '
git fetch . left right &&
git fmt-merge-msg <.git/FETCH_HEAD >actual &&
- diff -u actual expected
+ git diff actual expected
'
test_done
diff --git a/t/t9100-git-svn-basic.sh b/t/t9100-git-svn-basic.sh
index 7dcfc7e7d..eb628fe07 100755
--- a/t/t9100-git-svn-basic.sh
+++ b/t/t9100-git-svn-basic.sh
@@ -169,7 +169,7 @@ test_expect_success "$name" "
svn up '$SVN_TREE' &&
test -f '$SVN_TREE'/exec-2.sh &&
test ! -L '$SVN_TREE'/exec-2.sh &&
- diff -u help $SVN_TREE/exec-2.sh"
+ git diff help $SVN_TREE/exec-2.sh"
if test "$have_utf8" = t
then
@@ -193,7 +193,7 @@ test_expect_success "$name" \
"git-svn init $svnrepo && git-svn fetch &&
git-rev-list --pretty=raw remotes/git-svn | grep ^tree | uniq > a &&
git-rev-list --pretty=raw remotes/alt | grep ^tree | uniq > b &&
- diff -u a b"
+ git diff a b"
name='check imported tree checksums expected tree checksums'
rm -f expected
@@ -211,7 +211,7 @@ tree d667270a1f7b109f5eb3aaea21ede14b56bfdd6e
tree 8f51f74cf0163afc9ad68a4b1537288c4558b5a4
EOF
-test_expect_success "$name" "diff -u a expected"
+test_expect_success "$name" "git diff a expected"
test_expect_failure 'exit if remote refs are ambigious' "
git-config --add svn-remote.svn.fetch \
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index 2e1a09ff2..8e958da53 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -74,7 +74,7 @@ EOF
test_expect_success \
'A: verify commit' \
'git-cat-file commit master | sed 1d >actual &&
- diff -u expect actual'
+ git diff expect actual'
cat >expect <<EOF
100644 blob file2
@@ -84,22 +84,22 @@ EOF
test_expect_success \
'A: verify tree' \
'git-cat-file -p master^{tree} | sed "s/ [0-9a-f]* / /" >actual &&
- diff -u expect actual'
+ git diff expect actual'
echo "$file2_data" >expect
test_expect_success \
'A: verify file2' \
- 'git-cat-file blob master:file2 >actual && diff -u expect actual'
+ 'git-cat-file blob master:file2 >actual && git diff expect actual'
echo "$file3_data" >expect
test_expect_success \
'A: verify file3' \
- 'git-cat-file blob master:file3 >actual && diff -u expect actual'
+ 'git-cat-file blob master:file3 >actual && git diff expect actual'
printf "$file4_data" >expect
test_expect_success \
'A: verify file4' \
- 'git-cat-file blob master:file4 >actual && diff -u expect actual'
+ 'git-cat-file blob master:file4 >actual && git diff expect actual'
cat >expect <<EOF
:2 `git-rev-parse --verify master:file2`
@@ -109,7 +109,7 @@ cat >expect <<EOF
EOF
test_expect_success \
'A: verify marks output' \
- 'diff -u expect marks.out'
+ 'git diff expect marks.out'
test_expect_success \
'A: verify marks import' \
@@ -117,7 +117,7 @@ test_expect_success \
--import-marks=marks.out \
--export-marks=marks.new \
</dev/null &&
- diff -u expect marks.new'
+ git diff -u expect marks.new'
###
### series B
@@ -183,7 +183,7 @@ EOF
test_expect_success \
'C: verify commit' \
'git-cat-file commit branch | sed 1d >actual &&
- diff -u expect actual'
+ git diff expect actual'
cat >expect <<EOF
:000000 100755 0000000000000000000000000000000000000000 f1fb5da718392694d0076d677d6d0e364c79b0bc A file2/newf
@@ -240,13 +240,13 @@ echo "$file5_data" >expect
test_expect_success \
'D: verify file5' \
'git-cat-file blob branch:newdir/interesting >actual &&
- diff -u expect actual'
+ git diff expect actual'
echo "$file6_data" >expect
test_expect_success \
'D: verify file6' \
'git-cat-file blob branch:newdir/exec.sh >actual &&
- diff -u expect actual'
+ git diff expect actual'
###
### series E
@@ -282,7 +282,7 @@ EOF
test_expect_success \
'E: verify commit' \
'git-cat-file commit branch | sed 1,2d >actual &&
- diff -u expect actual'
+ git diff expect actual'
###
### series F
@@ -335,7 +335,7 @@ EOF
test_expect_success \
'F: verify other commit' \
'git-cat-file commit other >actual &&
- diff -u expect actual'
+ git diff expect actual'
###
### series G
@@ -413,7 +413,7 @@ echo "$file5_data" >expect
test_expect_success \
'H: verify file' \
'git-cat-file blob H:h/e/l/lo >actual &&
- diff -u expect actual'
+ git diff expect actual'
###
### series I
@@ -439,7 +439,7 @@ EOF
test_expect_success \
'I: verify edge list' \
'sed -e s/pack-.*pack/pack-.pack/ edges.list >actual &&
- diff -u expect actual'
+ git diff expect actual'
###
### series J
@@ -501,4 +501,54 @@ test_expect_success \
'test `git-rev-parse --verify branch^1` \
= `git-rev-parse --verify K^1`'
+###
+### series L
+###
+
+cat >input <<INPUT_END
+blob
+mark :1
+data <<EOF
+some data
+EOF
+
+blob
+mark :2
+data <<EOF
+other data
+EOF
+
+commit refs/heads/L
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+create L
+COMMIT
+
+M 644 :1 b.
+M 644 :1 b/other
+M 644 :1 ba
+
+commit refs/heads/L
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+update L
+COMMIT
+
+M 644 :2 b.
+M 644 :2 b/other
+M 644 :2 ba
+INPUT_END
+
+cat >expect <<EXPECT_END
+:100644 100644 4268632... 55d3a52... M b.
+:040000 040000 0ae5cac... 443c768... M b
+:100644 100644 4268632... 55d3a52... M ba
+EXPECT_END
+
+test_expect_success \
+ 'L: verify internal tree sorting' \
+ 'git-fast-import <input &&
+ git-diff --raw L^ L >output &&
+ git diff expect output'
+
test_done
diff --git a/templates/Makefile b/templates/Makefile
index 0eeee43fe..b8352e731 100644
--- a/templates/Makefile
+++ b/templates/Makefile
@@ -1,5 +1,9 @@
# make and install sample templates
+ifndef V
+ QUIET = @
+endif
+
INSTALL ?= install
TAR ?= tar
prefix ?= $(HOME)
@@ -18,7 +22,7 @@ all: boilerplates.made custom
bpsrc = $(filter-out %~,$(wildcard *--*))
boilerplates.made : $(bpsrc)
- ls *--* 2>/dev/null | \
+ $(QUIET)ls *--* 2>/dev/null | \
while read boilerplate; \
do \
case "$$boilerplate" in *~) continue ;; esac && \
@@ -29,13 +33,13 @@ boilerplates.made : $(bpsrc)
*--) ;; \
*) cp $$boilerplate blt/$$dst ;; \
esac || exit; \
- done || exit
+ done && \
date >$@
# If you need build-tailored templates, build them into blt/
# directory yourself here.
custom:
- : no custom templates yet
+ $(QUIET): no custom templates yet
clean:
rm -rf blt boilerplates.made
diff --git a/trace.c b/trace.c
index 27fef868c..7961a27a2 100644
--- a/trace.c
+++ b/trace.c
@@ -26,14 +26,14 @@
#include "quote.h"
/* Stolen from "imap-send.c". */
-static int git_vasprintf(char **strp, const char *fmt, va_list ap)
+int nfvasprintf(char **strp, const char *fmt, va_list ap)
{
int len;
char tmp[1024];
if ((len = vsnprintf(tmp, sizeof(tmp), fmt, ap)) < 0 ||
!(*strp = xmalloc(len + 1)))
- return -1;
+ die("Fatal: Out of memory\n");
if (len >= (int)sizeof(tmp))
vsprintf(*strp, fmt, ap);
else
@@ -41,13 +41,15 @@ static int git_vasprintf(char **strp, const char *fmt, va_list ap)
return len;
}
-/* Stolen from "imap-send.c". */
-int nfvasprintf(char **str, const char *fmt, va_list va)
+int nfasprintf(char **str, const char *fmt, ...)
{
- int ret = git_vasprintf(str, fmt, va);
- if (ret < 0)
- die("Fatal: Out of memory\n");
- return ret;
+ int rc;
+ va_list args;
+
+ va_start(args, fmt);
+ rc = nfvasprintf(str, fmt, args);
+ va_end(args);
+ return rc;
}
/* Get a trace file descriptor from GIT_TRACE env variable. */