summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/RelNotes-1.6.0.1.txt17
-rw-r--r--Documentation/RelNotes-1.6.1.txt58
-rw-r--r--Documentation/SubmittingPatches2
-rw-r--r--Documentation/config.txt21
-rw-r--r--Documentation/diff-options.txt6
-rw-r--r--Documentation/git-checkout.txt17
-rw-r--r--Documentation/git-count-objects.txt5
-rw-r--r--Documentation/git-diff-tree.txt19
-rw-r--r--Documentation/git-hash-object.txt20
-rw-r--r--Documentation/git-imap-send.txt78
-rw-r--r--Documentation/git-merge-base.txt77
-rw-r--r--Documentation/git-merge.txt24
-rw-r--r--Documentation/git-submodule.txt26
-rw-r--r--Documentation/git.txt6
-rw-r--r--Documentation/gitattributes.txt4
-rw-r--r--Makefile50
l---------RelNotes2
-rw-r--r--builtin-add.c12
-rw-r--r--builtin-blame.c6
-rw-r--r--builtin-checkout.c23
-rw-r--r--builtin-commit-tree.c5
-rw-r--r--builtin-count-objects.c7
-rw-r--r--builtin-diff-tree.c56
-rw-r--r--builtin-fast-export.c3
-rw-r--r--builtin-log.c14
-rw-r--r--builtin-merge-base.c24
-rw-r--r--builtin-merge-recursive.c36
-rw-r--r--builtin-merge.c21
-rw-r--r--builtin-pack-objects.c1
-rw-r--r--builtin-push.c13
-rw-r--r--builtin-reflog.c8
-rw-r--r--builtin-rev-list.c3
-rw-r--r--builtin-update-index.c5
-rw-r--r--cache.h6
-rw-r--r--combine-diff.c20
-rw-r--r--commit.h1
-rw-r--r--compat/mingw.c36
-rw-r--r--compat/mingw.h16
-rw-r--r--config.mak.in1
-rwxr-xr-xcontrib/completion/git-completion.bash2
-rwxr-xr-xcontrib/fast-import/git-p433
-rw-r--r--contrib/fast-import/git-p4.txt69
-rw-r--r--ctype.c5
-rw-r--r--diff.c56
-rw-r--r--dir.c6
-rw-r--r--git-compat-util.h11
-rwxr-xr-xgit-filter-branch.sh12
-rwxr-xr-xgit-merge-octopus.sh11
-rwxr-xr-xgit-submodule.sh88
-rw-r--r--hash-object.c159
-rw-r--r--help.c3
-rw-r--r--imap-send.c922
-rw-r--r--index-pack.c2
-rw-r--r--log-tree.c2
-rw-r--r--pack-write.c1
-rw-r--r--pager.c55
-rw-r--r--read-cache.c8
-rw-r--r--remote.c29
-rw-r--r--remote.h1
-rw-r--r--revision.c34
-rw-r--r--revision.h3
-rw-r--r--run-command.c2
-rw-r--r--run-command.h1
-rw-r--r--sha1_file.c64
-rw-r--r--sha1_name.c5
-rw-r--r--shell.c8
-rw-r--r--t/.gitignore2
-rw-r--r--t/Makefile8
-rw-r--r--t/lib-httpd.sh2
-rwxr-xr-xt/t0022-crlf-rename.sh4
-rwxr-xr-xt/t0055-beyond-symlinks.sh25
-rwxr-xr-xt/t1000-read-tree-m-3way.sh2
-rwxr-xr-xt/t1007-hash-object.sh56
-rwxr-xr-xt/t3030-merge-recursive.sh11
-rwxr-xr-xt/t3300-funny-names.sh2
-rwxr-xr-xt/t3900-i18n-commit.sh18
-rwxr-xr-xt/t3901-i18n-patch.sh28
-rwxr-xr-xt/t3902-quoted.sh8
-rwxr-xr-xt/t4000-diff-format.sh2
-rwxr-xr-xt/t4001-diff-rename.sh2
-rwxr-xr-xt/t4002-diff-basic.sh16
-rwxr-xr-xt/t4003-diff-rename-1.sh6
-rwxr-xr-xt/t4004-diff-rename-symlink.sh2
-rwxr-xr-xt/t4005-diff-rename-2.sh6
-rwxr-xr-xt/t4007-rename-3.sh4
-rwxr-xr-xt/t4008-diff-break-rewrite.sh6
-rwxr-xr-xt/t4009-diff-rename-4.sh6
-rwxr-xr-xt/t4010-diff-pathspec.sh2
-rwxr-xr-xt/t4011-diff-symlink.sh2
-rwxr-xr-xt/t4012-diff-binary.sh2
-rwxr-xr-xt/t4013-diff-various.sh2
-rwxr-xr-xt/t4014-format-patch.sh25
-rwxr-xr-xt/t4015-diff-whitespace.sh18
-rwxr-xr-xt/t4016-diff-quote.sh4
-rwxr-xr-xt/t4020-diff-external.sh2
-rwxr-xr-xt/t4022-diff-rewrite.sh4
-rwxr-xr-xt/t4023-diff-rename-typechange.sh14
-rwxr-xr-xt/t4027-diff-submodule.sh2
-rwxr-xr-xt/t4029-diff-trailing-space.sh39
-rwxr-xr-xt/t4100-apply-stat.sh4
-rwxr-xr-xt/t4101-apply-nonl.sh7
-rwxr-xr-xt/t4202-log.sh22
-rwxr-xr-xt/t5100-mailinfo.sh23
-rwxr-xr-xt/t5500-fetch-pack.sh2
-rwxr-xr-xt/t5515-fetch-merge-logic.sh4
-rwxr-xr-xt/t5540-http-push.sh2
-rwxr-xr-xt/t6002-rev-list-bisect.sh2
-rwxr-xr-xt/t6003-rev-list-topo-order.sh2
-rwxr-xr-xt/t6010-merge-base.sh48
-rwxr-xr-xt/t6023-merge-file.sh2
-rwxr-xr-xt/t6027-merge-binary.sh2
-rwxr-xr-xt/t6101-rev-parse-parents.sh2
-rwxr-xr-xt/t6200-fmt-merge-msg.sh4
-rwxr-xr-xt/t7001-mv.sh4
-rwxr-xr-xt/t7003-filter-branch.sh8
-rwxr-xr-xt/t7004-tag.sh2
-rwxr-xr-xt/t7101-reset.sh10
-rwxr-xr-xt/t7201-co.sh32
-rwxr-xr-xt/t7500-commit.sh41
-rwxr-xr-xt/t7600-merge.sh9
-rwxr-xr-xt/t7605-merge-resolve.sh4
-rwxr-xr-xt/t8001-annotate.sh2
-rwxr-xr-xt/t8002-blame.sh2
-rwxr-xr-xt/t9110-git-svn-use-svm-props.sh2
-rwxr-xr-xt/t9111-git-svn-use-svnsync-props.sh2
-rwxr-xr-xt/t9115-git-svn-dcommit-funky-renames.sh2
-rwxr-xr-xt/t9121-git-svn-fetch-renamed-dir.sh2
-rwxr-xr-xt/t9200-git-cvsexportcommit.sh14
-rwxr-xr-xt/t9300-fast-import.sh2
-rwxr-xr-xt/t9301-fast-export.sh2
-rwxr-xr-xt/t9500-gitweb-standalone-no-errors.sh16
-rwxr-xr-xt/t9700-perl-git.sh2
-rwxr-xr-xt/t9700/test.pl3
-rw-r--r--t/test-lib.sh10
-rw-r--r--templates/Makefile4
-rw-r--r--unpack-trees.c1
-rw-r--r--xdiff-interface.c60
-rw-r--r--xdiff-interface.h13
138 files changed, 1963 insertions, 1085 deletions
diff --git a/Documentation/RelNotes-1.6.0.1.txt b/Documentation/RelNotes-1.6.0.1.txt
index bac117e89d..49d7a1cafa 100644
--- a/Documentation/RelNotes-1.6.0.1.txt
+++ b/Documentation/RelNotes-1.6.0.1.txt
@@ -4,6 +4,9 @@ GIT v1.6.0.1 Release Notes
Fixes since v1.6.0
------------------
+* "git diff --cc" did not honor content mangling specified by
+ gitattributes and core.autocrlf when reading from the work tree.
+
* "git diff --check" incorrectly detected new trailing blank lines when
whitespace check was in effect.
@@ -13,6 +16,8 @@ Fixes since v1.6.0
* "git format-patch" peeked before the beginning of a string when
"format.headers" variable is empty (a misconfiguration).
+* "git help help" did not work correctly.
+
* "git mailinfo" (hence "git am") was unhappy when MIME multipart message
contained garbage after the finishing boundary.
@@ -22,10 +27,10 @@ Fixes since v1.6.0
* "git merge" did not refresh the index correctly when a merge resulted in
a fast-forward.
-Contains other various documentation fixes.
+* "git merge" did not resolve a truly trivial merges that can be done
+ without content level merges.
---
-exec >/var/tmp/1
-O=v1.6.0-14-g3a634dc
-echo O=$(git describe maint)
-git shortlog --no-merges $O..maint
+* "git svn dcommit" to a repository with URL that has embedded usernames
+ did not work correctly.
+
+Contains other various documentation fixes.
diff --git a/Documentation/RelNotes-1.6.1.txt b/Documentation/RelNotes-1.6.1.txt
new file mode 100644
index 0000000000..d37da039f6
--- /dev/null
+++ b/Documentation/RelNotes-1.6.1.txt
@@ -0,0 +1,58 @@
+GIT v1.6.1 Release Notes
+========================
+
+Updates since v1.6.0
+--------------------
+
+When some commands (e.g. "git log", "git diff") spawn pager internally, we
+used to make the pager the parent process of the git command that produces
+output. This meant that the exit status of the whole thing comes from the
+pager, not the underlying git command. We swapped the order of the
+processes around and you will see the exit code from the command from now
+on.
+
+(subsystems)
+
+* ...
+
+(portability)
+
+* ...
+
+(documentation)
+
+* ...
+
+(performance)
+
+* The underlying diff machinery to produce textual output has been
+ optimized, which would result in faster "git blame" processing.
+
+(usability, bells and whistles)
+
+* "git checkout --track origin/hack" used to be a syntax error. It now
+ DWIMs to create a corresponding local branch "hack", i.e. acts as if you
+ said "git checkout --track -b hack origin/hack".
+
+* "git diff" learned to mimick --suppress-blank-empty from GNU diff via a
+ configuration option.
+
+* "git imap-send" can optionally talk SSL.
+
+(internal)
+
+* "git hash-object" learned to lie about the path being hashed, so that
+ correct gitattributes processing can be done while hashing contents
+ stored in a temporary file.
+
+Fixes since v1.6.0
+------------------
+
+All of the fixes in v1.6.0.X maintenance series are included in this
+release, unless otherwise noted.
+
+--
+exec >/var/tmp/1
+O=v1.6.0-48-ge28a867
+echo O=$(git describe master)
+git shortlog --no-merges $O..master ^maint
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 841bead9db..a1e9100f9e 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -71,7 +71,7 @@ run git diff --check on your changes before you commit.
(1a) Try to be nice to older C compilers
-We try to support wide range of C compilers to compile
+We try to support a wide range of C compilers to compile
git with. That means that you should not use C99 initializers, even
if a lot of compilers grok it.
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 676c39bb84..af57d94304 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -358,8 +358,13 @@ core.editor::
`EDITOR` environment variables and then finally `vi`.
core.pager::
- The command that git will use to paginate output. Can be overridden
- with the `GIT_PAGER` environment variable.
+ The command that git will use to paginate output. Can
+ be overridden with the `GIT_PAGER` environment
+ variable. Note that git sets the `LESS` environment
+ variable to `FRSX` if it is unset when it runs the
+ pager. One can change these settings by setting the
+ `LESS` variable to some other value or by giving the
+ `core.pager` option a value such as "`less -+FRSX`".
core.whitespace::
A comma separated list of common whitespace problems to
@@ -567,6 +572,10 @@ diff.autorefreshindex::
affects only 'git-diff' Porcelain, and not lower level
'diff' commands, such as 'git-diff-files'.
+diff.suppress-blank-empty::
+ A boolean to inhibit the standard behavior of printing a space
+ before each empty output line. Defaults to false.
+
diff.external::
If this config variable is set, diff generation is not
performed using the internal diff machinery, but using the
@@ -979,9 +988,11 @@ pack.packSizeLimit::
linkgit:git-repack[1].
pager.<cmd>::
- Allows to set your own pager preferences for each command, overriding
- the default. If `\--pager` or `\--no-pager` is specified on the command
- line, it takes precedence over this option.
+ Allows turning on or off pagination of the output of a
+ particular git subcommand when writing to a tty. If
+ `\--paginate` or `\--no-pager` is specified on the command line,
+ it takes precedence over this option. To disable pagination for
+ all commands, set `core.pager` or 'GIT_PAGER' to "`cat`".
pull.octopus::
The default merge strategy to use when pulling multiple branches
diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
index cba90fd27c..1759386404 100644
--- a/Documentation/diff-options.txt
+++ b/Documentation/diff-options.txt
@@ -107,9 +107,9 @@ endif::git-format-patch[]
--exit-code.
--full-index::
- Instead of the first handful characters, show full
- object name of pre- and post-image blob on the "index"
- line when generating a patch format output.
+ Instead of the first handful of characters, show the full
+ pre- and post-image blob object names on the "index"
+ line when generating patch format output.
--binary::
In addition to --full-index, output "binary diff" that
diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index 5aa69c0e12..be54a0299f 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -8,7 +8,7 @@ git-checkout - Checkout a branch or paths to the working tree
SYNOPSIS
--------
[verse]
-'git checkout' [-q] [-f] [[--track | --no-track] -b <new_branch> [-l]] [-m] [<branch>]
+'git checkout' [-q] [-f] [--track | --no-track] [-b <new_branch> [-l]] [-m] [<branch>]
'git checkout' [<tree-ish>] [--] <paths>...
DESCRIPTION
@@ -21,6 +21,10 @@ specified, <new_branch>. Using -b will cause <new_branch> to
be created; in this case you can use the --track or --no-track
options, which will be passed to `git branch`.
+As a convenience, --track will default to create a branch whose
+name is constructed from the specified branch name by stripping
+the first namespace level.
+
When <paths> are given, this command does *not* switch
branches. It updates the named paths in the working tree from
the index file (i.e. it runs `git checkout-index -f -u`), or
@@ -59,6 +63,17 @@ OPTIONS
'git-checkout' and 'git-branch' to always behave as if '--no-track' were
given. Set it to `always` if you want this behavior when the
start-point is either a local or remote branch.
++
+If no '-b' option was given, the name of the new branch will be
+derived from the remote branch, by attempting to guess the name
+of the branch on remote system. If "remotes/" or "refs/remotes/"
+are prefixed, it is stripped away, and then the part up to the
+next slash (which would be the nickname of the remote) is removed.
+This would tell us to use "hack" as the local branch when branching
+off of "origin/hack" (or "remotes/origin/hack", or even
+"refs/remotes/origin/hack"). If the given name has no slash, or the above
+guessing results in an empty name, the guessing is aborted. You can
+exlicitly give a name with '-b' in such a case.
--no-track::
Ignore the branch.autosetupmerge configuration variable.
diff --git a/Documentation/git-count-objects.txt b/Documentation/git-count-objects.txt
index 75a8da1ca9..6bc1c21e62 100644
--- a/Documentation/git-count-objects.txt
+++ b/Documentation/git-count-objects.txt
@@ -21,8 +21,9 @@ OPTIONS
--verbose::
In addition to the number of loose objects and disk
space consumed, it reports the number of in-pack
- objects, number of packs, and number of objects that can be
- removed by running `git prune-packed`.
+ objects, number of packs, disk space consumed by those packs,
+ and number of objects that can be removed by running
+ `git prune-packed`.
Author
diff --git a/Documentation/git-diff-tree.txt b/Documentation/git-diff-tree.txt
index 1fdf20dcc9..5d48664e62 100644
--- a/Documentation/git-diff-tree.txt
+++ b/Documentation/git-diff-tree.txt
@@ -49,13 +49,22 @@ include::diff-options.txt[]
--stdin::
When '--stdin' is specified, the command does not take
<tree-ish> arguments from the command line. Instead, it
- reads either one <commit> or a list of <commit>
- separated with a single space from its standard input.
+ reads lines containing either two <tree>, one <commit>, or a
+ list of <commit> from its standard input. (Use a single space
+ as separator.)
+
-When a single commit is given on one line of such input, it compares
-the commit with its parents. The following flags further affects its
-behavior. The remaining commits, when given, are used as if they are
+When two trees are given, it compares the first tree with the second.
+When a single commit is given, it compares the commit with its
+parents. The remaining commits, when given, are used as if they are
parents of the first commit.
++
+When comparing two trees, the ID of both trees (separated by a space
+and terminated by a newline) is printed before the difference. When
+comparing commits, the ID of the first (or only) commit, followed by a
+newline, is printed.
++
+The following flags further affects the behavior when comparing
+commits (but not trees).
-m::
By default, 'git-diff-tree --stdin' does not show
diff --git a/Documentation/git-hash-object.txt b/Documentation/git-hash-object.txt
index ac928e198e..0af40cfb85 100644
--- a/Documentation/git-hash-object.txt
+++ b/Documentation/git-hash-object.txt
@@ -8,7 +8,9 @@ git-hash-object - Compute object ID and optionally creates a blob from a file
SYNOPSIS
--------
-'git hash-object' [-t <type>] [-w] [--stdin | --stdin-paths] [--] <file>...
+[verse]
+'git hash-object' [-t <type>] [-w] [--path=<file>|--no-filters] [--stdin] [--] <file>...
+'git hash-object' [-t <type>] [-w] --stdin-paths < <list-of-paths>
DESCRIPTION
-----------
@@ -35,6 +37,22 @@ OPTIONS
--stdin-paths::
Read file names from stdin instead of from the command-line.
+--path::
+ Hash object as it were located at the given path. The location of
+ file does not directly influence on the hash value, but path is
+ used to determine what git filters should be applied to the object
+ before it can be placed to the object database, and, as result of
+ applying filters, the actual blob put into the object database may
+ differ from the given file. This option is mainly useful for hashing
+ temporary files located outside of the working directory or files
+ read from stdin.
+
+--no-filters::
+ Hash the contents as is, ignoring any input filter that would
+ have been chosen by the attributes mechanism, including crlf
+ conversion. If the file is read from standard input then this
+ is always implied, unless the --path option is given.
+
Author
------
Written by Junio C Hamano <gitster@pobox.com>
diff --git a/Documentation/git-imap-send.txt b/Documentation/git-imap-send.txt
index b3d8da33ee..bd49a0aee8 100644
--- a/Documentation/git-imap-send.txt
+++ b/Documentation/git-imap-send.txt
@@ -3,7 +3,7 @@ git-imap-send(1)
NAME
----
-git-imap-send - Dump a mailbox from stdin into an imap folder
+git-imap-send - Send a collection of patches from stdin to an IMAP folder
SYNOPSIS
@@ -13,9 +13,9 @@ SYNOPSIS
DESCRIPTION
-----------
-This command uploads a mailbox generated with git-format-patch
-into an imap drafts folder. This allows patches to be sent as
-other email is sent with mail clients that cannot read mailbox
+This command uploads a mailbox generated with 'git-format-patch'
+into an IMAP drafts folder. This allows patches to be sent as
+other email is when using mail clients that cannot read mailbox
files directly.
Typical usage is something like:
@@ -26,21 +26,75 @@ git format-patch --signoff --stdout --attach origin | git imap-send
CONFIGURATION
-------------
-'git-imap-send' requires the following values in the repository
-configuration file (shown with examples):
+To use the tool, imap.folder and either imap.tunnel or imap.host must be set
+to appropriate values.
+
+Variables
+~~~~~~~~~
+
+imap.folder::
+ The folder to drop the mails into, which is typically the Drafts
+ folder. For example: "INBOX.Drafts", "INBOX/Drafts" or
+ "[Gmail]/Drafts". Required to use imap-send.
+
+imap.tunnel::
+ Command used to setup a tunnel to the IMAP server through which
+ commands will be piped instead of using a direct network connection
+ to the server. Required when imap.host is not set to use imap-send.
+
+imap.host::
+ A URL identifying the server. Use a `imap://` prefix for non-secure
+ connections and a `imaps://` prefix for secure connections.
+ Ignored when imap.tunnel is set, but required to use imap-send
+ otherwise.
+
+imap.user::
+ The username to use when logging in to the server.
+
+imap.password::
+ The password to use when logging in to the server.
+
+imap.port::
+ An integer port number to connect to on the server.
+ Defaults to 143 for imap:// hosts and 993 for imaps:// hosts.
+ Ignored when imap.tunnel is set.
+
+imap.sslverify::
+ A boolean to enable/disable verification of the server certificate
+ used by the SSL/TLS connection. Default is `true`. Ignored when
+ imap.tunnel is set.
+
+Examples
+~~~~~~~~
+
+Using tunnel mode:
..........................
[imap]
- Folder = "INBOX.Drafts"
+ folder = "INBOX.Drafts"
+ tunnel = "ssh -q -C user@example.com /usr/bin/imapd ./Maildir 2> /dev/null"
+..........................
+Using direct mode:
+
+.........................
[imap]
- Tunnel = "ssh -q user@server.com /usr/bin/imapd ./Maildir 2> /dev/null"
+ folder = "INBOX.Drafts"
+ host = imap://imap.example.com
+ user = bob
+ pass = p4ssw0rd
+..........................
+
+Using direct mode with SSL:
+.........................
[imap]
- Host = imap.server.com
- User = bob
- Pass = pwd
- Port = 143
+ folder = "INBOX.Drafts"
+ host = imaps://imap.example.com
+ user = bob
+ pass = p4ssw0rd
+ port = 123
+ sslverify = false
..........................
diff --git a/Documentation/git-merge-base.txt b/Documentation/git-merge-base.txt
index 1a7ecbf8f3..2f0c5259e0 100644
--- a/Documentation/git-merge-base.txt
+++ b/Documentation/git-merge-base.txt
@@ -8,26 +8,81 @@ git-merge-base - Find as good common ancestors as possible for a merge
SYNOPSIS
--------
-'git merge-base' [--all] <commit> <commit>
+'git merge-base' [--all] <commit> <commit>...
DESCRIPTION
-----------
-'git-merge-base' finds as good a common ancestor as possible between
-the two commits. That is, given two commits A and B, `git merge-base A
-B` will output a commit which is reachable from both A and B through
-the parent relationship.
+'git-merge-base' finds best common ancestor(s) between two commits to use
+in a three-way merge. One common ancestor is 'better' than another common
+ancestor if the latter is an ancestor of the former. A common ancestor
+that does not have any better common ancestor than it is a 'best common
+ancestor', i.e. a 'merge base'. Note that there can be more than one
+merge bases between two commits.
-Given a selection of equally good common ancestors it should not be
-relied on to decide in any particular way.
-
-The 'git-merge-base' algorithm is still in flux - use the source...
+Among the two commits to compute their merge bases, one is specified by
+the first commit argument on the command line; the other commit is a
+(possibly hypothetical) commit that is a merge across all the remaining
+commits on the command line. As the most common special case, giving only
+two commits from the command line means computing the merge base between
+the given two commits.
OPTIONS
-------
--all::
- Output all common ancestors for the two commits instead of
- just one.
+ Output all merge bases for the commits, instead of just one.
+
+DISCUSSION
+----------
+
+Given two commits 'A' and 'B', `git merge-base A B` will output a commit
+which is reachable from both 'A' and 'B' through the parent relationship.
+
+For example, with this topology:
+
+ o---o---o---B
+ /
+ ---o---1---o---o---o---A
+
+the merge base between 'A' and 'B' is '1'.
+
+Given three commits 'A', 'B' and 'C', `git merge-base A B C` will compute the
+merge base between 'A' and an hypothetical commit 'M', which is a merge
+between 'B' and 'C'. For example, with this topology:
+
+ o---o---o---o---C
+ /
+ / o---o---o---B
+ / /
+ ---2---1---o---o---o---A
+
+the result of `git merge-base A B C` is '1'. This is because the
+equivalent topology with a merge commit 'M' between 'B' and 'C' is:
+
+
+ o---o---o---o---o
+ / \
+ / o---o---o---o---M
+ / /
+ ---2---1---o---o---o---A
+
+and the result of `git merge-base A M` is '1'. Commit '2' is also a
+common ancestor between 'A' and 'M', but '1' is a better common ancestor,
+because '2' is an ancestor of '1'. Hence, '2' is not a merge base.
+
+When the history involves criss-cross merges, there can be more than one
+'best' common ancestors between two commits. For example, with this
+topology:
+
+ ---1---o---A
+ \ /
+ X
+ / \
+ ---2---o---o---B
+
+both '1' and '2' are merge-base of A and B. Neither one is better than
+the other (both are 'best' merge base). When `--all` option is not given,
+it is unspecified which best one is output.
Author
------
diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt
index 17a15acb07..685e1fed58 100644
--- a/Documentation/git-merge.txt
+++ b/Documentation/git-merge.txt
@@ -126,13 +126,25 @@ After seeing a conflict, you can do two things:
up working tree changes made by 2. and 3.; 'git-reset --hard' can
be used for this.
- * Resolve the conflicts. `git diff` would report only the
- conflicting paths because of the above 2. and 3.
- Edit the working tree files into a desirable shape
- ('git mergetool' can ease this task), 'git-add' or 'git-rm'
- them, to make the index file contain what the merge result
- should be, and run 'git-commit' to commit the result.
+ * Resolve the conflicts. Git will mark the conflicts in
+ the working tree. Edit the files into shape and
+ 'git-add' to the index. 'git-commit' to seal the deal.
+You can work through the conflict with a number of tools:
+
+ * Use a mergetool. 'git mergetool' to launch a graphical
+ mergetool which will work you through the merge.
+
+ * Look at the diffs. 'git diff' will show a three-way diff,
+ highlighting changes from both the HEAD and remote versions.
+
+ * Look at the diffs on their own. 'git log --merge -p <path>'
+ will show diffs first for the HEAD version and then the
+ remote version.
+
+ * Look at the originals. 'git show :1:filename' shows the
+ common ancestor, 'git show :2:filename' shows the HEAD
+ version and 'git show :3:filename' shows the remote version.
SEE ALSO
--------
diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index bf33b0cba0..babaa9bc46 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -14,6 +14,8 @@ SYNOPSIS
'git submodule' [--quiet] init [--] [<path>...]
'git submodule' [--quiet] update [--init] [--] [<path>...]
'git submodule' [--quiet] summary [--summary-limit <n>] [commit] [--] [<path>...]
+'git submodule' [--quiet] foreach <command>
+'git submodule' [--quiet] sync [--] [<path>...]
DESCRIPTION
@@ -123,6 +125,30 @@ summary::
in the submodule between the given super project commit and the
index or working tree (switched by --cached) are shown.
+foreach::
+ Evaluates an arbitrary shell command in each checked out submodule.
+ The command has access to the variables $path and $sha1:
+ $path is the name of the submodule directory relative to the
+ superproject, and $sha1 is the commit as recorded in the superproject.
+ Any submodules defined in the superproject but not checked out are
+ ignored by this command. Unless given --quiet, foreach prints the name
+ of each submodule before evaluating the command.
+ A non-zero return from the command in any submodule causes
+ the processing to terminate. This can be overridden by adding '|| :'
+ to the end of the command.
++
+As an example, "git submodule foreach 'echo $path `git rev-parse HEAD`' will
+show the path and currently checked out commit for each submodule.
+
+sync::
+ Synchronizes submodules' remote URL configuration setting
+ to the value specified in .gitmodules. This is useful when
+ submodule URLs change upstream and you need to update your local
+ repositories accordingly.
++
+"git submodule sync" synchronizes all submodules while
+"git submodule sync -- A" synchronizes submodule "A" only.
+
OPTIONS
-------
-q::
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 1bc295dd54..e178fb5813 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -43,9 +43,10 @@ unreleased) version of git, that is available from 'master'
branch of the `git.git` repository.
Documentation for older releases are available here:
-* link:v1.6.0/git.html[documentation for release 1.6.0]
+* link:v1.6.1/git.html[documentation for release 1.6.1]
* release notes for
+ link:RelNotes-1.6.1.txt[1.6.1],
link:RelNotes-1.6.0.txt[1.6.0].
* link:v1.5.6.5/git.html[documentation for release 1.5.6.5]
@@ -497,7 +498,8 @@ other
'GIT_PAGER'::
This environment variable overrides `$PAGER`. If it is set
to an empty string or to the value "cat", git will not launch
- a pager.
+ a pager. See also the `core.pager` option in
+ linkgit:git-config[1].
'GIT_SSH'::
If this environment variable is set then 'git-fetch'
diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt
index db16b0ca5b..5495d695c6 100644
--- a/Documentation/gitattributes.txt
+++ b/Documentation/gitattributes.txt
@@ -316,10 +316,14 @@ patterns are available:
- `pascal` suitable for source code in the Pascal/Delphi language.
+- `python` suitable for source code in the Python language.
+
- `ruby` suitable for source code in the Ruby language.
- `tex` suitable for source code for LaTeX documents.
+- `html` suitable for HTML/XHTML documents.
+
Performing a three-way merge
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/Makefile b/Makefile
index 53ab4b5536..4119fb3003 100644
--- a/Makefile
+++ b/Makefile
@@ -124,6 +124,9 @@ all::
# Define USE_STDEV below if you want git to care about the underlying device
# change being considered an inode change from the update-index perspective.
#
+# Define NO_ST_BLOCKS_IN_STRUCT_STAT if your platform does not have st_blocks
+# field that counts the on-disk footprint in 512-byte blocks.
+#
# Define ASCIIDOC8 if you want to format documentation with AsciiDoc 8
#
# Define DOCBOOK_XSL_172 if you want to format man pages with DocBook XSL v1.72.
@@ -333,7 +336,6 @@ endif
export PERL_PATH
LIB_FILE=libgit.a
-COMPAT_LIB = compat/lib.a
XDIFF_LIB=xdiff/lib.a
LIB_H += archive.h
@@ -575,9 +577,11 @@ EXTLIBS =
ifeq ($(uname_S),Linux)
NO_STRLCPY = YesPlease
+ THREADED_DELTA_SEARCH = YesPlease
endif
ifeq ($(uname_S),GNU/kFreeBSD)
NO_STRLCPY = YesPlease
+ THREADED_DELTA_SEARCH = YesPlease
endif
ifeq ($(uname_S),UnixWare)
CC = cc
@@ -675,6 +679,7 @@ ifeq ($(uname_S),FreeBSD)
BASIC_CFLAGS += -I/usr/local/include
BASIC_LDFLAGS += -L/usr/local/lib
DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease
+ THREADED_DELTA_SEARCH = YesPlease
endif
ifeq ($(uname_S),OpenBSD)
NO_STRCASESTR = YesPlease
@@ -682,6 +687,7 @@ ifeq ($(uname_S),OpenBSD)
NEEDS_LIBICONV = YesPlease
BASIC_CFLAGS += -I/usr/local/include
BASIC_LDFLAGS += -L/usr/local/lib
+ THREADED_DELTA_SEARCH = YesPlease
endif
ifeq ($(uname_S),NetBSD)
ifeq ($(shell expr "$(uname_R)" : '[01]\.'),2)
@@ -690,6 +696,7 @@ ifeq ($(uname_S),NetBSD)
BASIC_CFLAGS += -I/usr/pkg/include
BASIC_LDFLAGS += -L/usr/pkg/lib
ALL_LDFLAGS += -Wl,-rpath,/usr/pkg/lib
+ THREADED_DELTA_SEARCH = YesPlease
endif
ifeq ($(uname_S),AIX)
NO_STRCASESTR=YesPlease
@@ -727,6 +734,7 @@ ifeq ($(uname_S),HP-UX)
NO_UNSETENV = YesPlease
NO_HSTRERROR = YesPlease
NO_SYS_SELECT_H = YesPlease
+ SNPRINTF_RETURNS_BOGUS = YesPlease
endif
ifneq (,$(findstring MINGW,$(uname_S)))
NO_MMAP = YesPlease
@@ -749,6 +757,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
NO_SVN_TESTS = YesPlease
NO_PERL_MAKEMAKER = YesPlease
NO_POSIX_ONLY_PROGRAMS = YesPlease
+ NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat
COMPAT_CFLAGS += -DSNPRINTF_SIZE_CORR=1
COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
@@ -863,6 +872,9 @@ endif
ifdef NO_D_INO_IN_DIRENT
BASIC_CFLAGS += -DNO_D_INO_IN_DIRENT
endif
+ifdef NO_ST_BLOCKS_IN_STRUCT_STAT
+ BASIC_CFLAGS += -DNO_ST_BLOCKS_IN_STRUCT_STAT
+endif
ifdef NO_C99_FORMAT
BASIC_CFLAGS += -DNO_C99_FORMAT
endif
@@ -1098,7 +1110,10 @@ help.o: help.c common-cmds.h GIT-CFLAGS
'-DGIT_INFO_PATH="$(infodir_SQ)"' $<
$(BUILT_INS): git$X
- $(QUIET_BUILT_IN)$(RM) $@ && ln git$X $@
+ $(QUIET_BUILT_IN)$(RM) $@ && \
+ ln git$X $@ 2>/dev/null || \
+ ln -s git$X $@ 2>/dev/null || \
+ cp git$X $@
common-cmds.h: ./generate-cmdlist.sh command-list.txt
@@ -1215,7 +1230,9 @@ endif
git-%$X: %.o $(GITLIBS)
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
-git-imap-send$X: imap-send.o $(LIB_FILE)
+git-imap-send$X: imap-send.o $(GITLIBS)
+ $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
+ $(LIBS) $(OPENSSL_LINK) $(OPENSSL_LIBSSL)
http.o http-walker.o http-push.o transport.o: http.h
@@ -1223,12 +1240,6 @@ git-http-push$X: revision.o http.o http-push.o $(GITLIBS)
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
-$(COMPAT_LIB): $(COMPAT_OBJS)
- $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(COMPAT_OBJS)
-
-git-shell$X: abspath.o ctype.o exec_cmd.o quote.o strbuf.o usage.o wrapper.o shell.o $(COMPAT_LIB)
- $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(COMPAT_LIB)
-
$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
$(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
builtin-revert.o wt-status.o: wt-status.h
@@ -1351,7 +1362,7 @@ install: all
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
$(INSTALL) $(ALL_PROGRAMS) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
- $(INSTALL) git$X git-upload-pack$X git-receive-pack$X git-upload-archive$X '$(DESTDIR_SQ)$(bindir_SQ)'
+ $(INSTALL) git$X git-upload-pack$X git-receive-pack$X git-upload-archive$X git-shell$X '$(DESTDIR_SQ)$(bindir_SQ)'
$(MAKE) -C templates DESTDIR='$(DESTDIR_SQ)' install
$(MAKE) -C perl prefix='$(prefix_SQ)' DESTDIR='$(DESTDIR_SQ)' install
ifndef NO_TCLTK
@@ -1363,16 +1374,13 @@ ifneq (,$X)
endif
bindir=$$(cd '$(DESTDIR_SQ)$(bindir_SQ)' && pwd) && \
execdir=$$(cd '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' && pwd) && \
- if test "z$$bindir" != "z$$execdir"; \
- then \
- ln -f "$$bindir/git$X" "$$execdir/git$X" || \
- cp "$$bindir/git$X" "$$execdir/git$X"; \
- fi && \
- { $(foreach p,$(BUILT_INS), $(RM) "$$execdir/$p" && ln "$$execdir/git$X" "$$execdir/$p" ;) } && \
- if test "z$$bindir" != "z$$execdir"; \
- then \
- $(RM) "$$execdir/git$X"; \
- fi && \
+ { $(RM) "$$execdir/git-add$X" && \
+ ln git-add$X "$$execdir/git-add$X" 2>/dev/null || \
+ cp git-add$X "$$execdir/git-add$X"; } && \
+ { $(foreach p,$(filter-out git-add,$(BUILT_INS)), $(RM) "$$execdir/$p" && \
+ ln "$$execdir/git-add$X" "$$execdir/$p" 2>/dev/null || \
+ ln -s "git-add$X" "$$execdir/$p" 2>/dev/null || \
+ cp "$$execdir/git-add$X" "$$execdir/$p" || exit;) } && \
./check_bindir "z$$bindir" "z$$execdir" "$$bindir/git-add$X"
install-doc:
@@ -1441,7 +1449,7 @@ distclean: clean
clean:
$(RM) *.o mozilla-sha1/*.o arm/*.o ppc/*.o compat/*.o xdiff/*.o \
- $(LIB_FILE) $(XDIFF_LIB) $(COMPAT_LIB)
+ $(LIB_FILE) $(XDIFF_LIB)
$(RM) $(ALL_PROGRAMS) $(BUILT_INS) git$X
$(RM) $(TEST_PROGRAMS)
$(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo common-cmds.h TAGS tags cscope*
diff --git a/RelNotes b/RelNotes
index 8f32997335..3d420845b1 120000
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes-1.6.0.1.txt \ No newline at end of file
+Documentation/RelNotes-1.6.1.txt \ No newline at end of file
diff --git a/builtin-add.c b/builtin-add.c
index fc3f96eaef..81b64d7b9d 100644
--- a/builtin-add.c
+++ b/builtin-add.c
@@ -153,6 +153,16 @@ static const char **validate_pathspec(int argc, const char **argv, const char *p
{
const char **pathspec = get_pathspec(prefix, argv);
+ if (pathspec) {
+ const char **p;
+ for (p = pathspec; *p; p++) {
+ if (has_symlink_leading_path(strlen(*p), *p)) {
+ int len = prefix ? strlen(prefix) : 0;
+ die("'%s' is beyond a symbolic link", *p + len);
+ }
+ }
+ }
+
return pathspec;
}
@@ -278,7 +288,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
fprintf(stderr, "Maybe you wanted to say 'git add .'?\n");
return 0;
}
- pathspec = get_pathspec(prefix, argv);
+ pathspec = validate_pathspec(argc, argv, prefix);
/*
* If we are adding new files, we need to scan the working
diff --git a/builtin-blame.c b/builtin-blame.c
index 4ea343189f..e4d12de8a9 100644
--- a/builtin-blame.c
+++ b/builtin-blame.c
@@ -465,7 +465,6 @@ struct patch {
};
struct blame_diff_state {
- struct xdiff_emit_state xm;
struct patch *ret;
unsigned hunk_post_context;
unsigned hunk_in_pre_context : 1;
@@ -528,15 +527,12 @@ static struct patch *compare_buffer(mmfile_t *file_p, mmfile_t *file_o,
xpp.flags = xdl_opts;
memset(&xecfg, 0, sizeof(xecfg));
xecfg.ctxlen = context;
- ecb.outf = xdiff_outf;
- ecb.priv = &state;
memset(&state, 0, sizeof(state));
- state.xm.consume = process_u_diff;
state.ret = xmalloc(sizeof(struct patch));
state.ret->chunks = NULL;
state.ret->num = 0;
- xdi_diff(file_p, file_o, &xpp, &xecfg, &ecb);
+ xdi_diff_outf(file_p, file_o, process_u_diff, &state, &xpp, &xecfg, &ecb);
if (state.ret->num) {
struct chunk *chunk;
diff --git a/builtin-checkout.c b/builtin-checkout.c
index 411cc513c6..b380ad6e80 100644
--- a/builtin-checkout.c
+++ b/builtin-checkout.c
@@ -157,7 +157,7 @@ struct checkout_opts {
int force;
int writeout_error;
- char *new_branch;
+ const char *new_branch;
int new_branch_log;
enum branch_track track;
};
@@ -437,13 +437,28 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
git_config(git_default_config, NULL);
- opts.track = git_branch_track;
+ opts.track = BRANCH_TRACK_UNSPECIFIED;
argc = parse_options(argc, argv, options, checkout_usage,
PARSE_OPT_KEEP_DASHDASH);
- if (!opts.new_branch && (opts.track != git_branch_track))
- die("git checkout: --track and --no-track require -b");
+ /* --track without -b should DWIM */
+ if (0 < opts.track && !opts.new_branch) {
+ const char *argv0 = argv[0];
+ if (!argc || !strcmp(argv0, "--"))
+ die ("--track needs a branch name");
+ if (!prefixcmp(argv0, "refs/"))
+ argv0 += 5;
+ if (!prefixcmp(argv0, "remotes/"))
+ argv0 += 8;
+ argv0 = strchr(argv0, '/');
+ if (!argv0 || !argv0[1])
+ die ("Missing branch name; try -b");
+ opts.new_branch = argv0 + 1;
+ }
+
+ if (opts.track == BRANCH_TRACK_UNSPECIFIED)
+ opts.track = git_branch_track;
if (opts.force && opts.merge)
die("git checkout: -f and -m are incompatible");
diff --git a/builtin-commit-tree.c b/builtin-commit-tree.c
index 7a9a309be0..f773db596c 100644
--- a/builtin-commit-tree.c
+++ b/builtin-commit-tree.c
@@ -48,6 +48,7 @@ static const char commit_utf8_warn[] =
int commit_tree(const char *msg, unsigned char *tree,
struct commit_list *parents, unsigned char *ret)
{
+ int result;
int encoding_is_utf8;
struct strbuf buffer;
@@ -86,7 +87,9 @@ int commit_tree(const char *msg, unsigned char *tree,
if (encoding_is_utf8 && !is_utf8(buffer.buf))
fprintf(stderr, commit_utf8_warn);
- return write_sha1_file(buffer.buf, buffer.len, commit_type, ret);
+ result = write_sha1_file(buffer.buf, buffer.len, commit_type, ret);
+ strbuf_release(&buffer);
+ return result;
}
int cmd_commit_tree(int argc, const char **argv, const char *prefix)
diff --git a/builtin-count-objects.c b/builtin-count-objects.c
index 91b5487478..6e80fe7c01 100644
--- a/builtin-count-objects.c
+++ b/builtin-count-objects.c
@@ -43,7 +43,7 @@ static void count_objects(DIR *d, char *path, int len, int verbose,
if (lstat(path, &st) || !S_ISREG(st.st_mode))
bad = 1;
else
- (*loose_size) += xsize_t(st.st_blocks);
+ (*loose_size) += xsize_t(on_disk_bytes(st));
}
if (bad) {
if (verbose) {
@@ -104,6 +104,7 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)
if (verbose) {
struct packed_git *p;
unsigned long num_pack = 0;
+ unsigned long size_pack = 0;
if (!packed_git)
prepare_packed_git();
for (p = packed_git; p; p = p->next) {
@@ -112,12 +113,14 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)
if (open_pack_index(p))
continue;
packed += p->num_objects;
+ size_pack += p->pack_size + p->index_size;
num_pack++;
}
printf("count: %lu\n", loose);
- printf("size: %lu\n", loose_size / 2);
+ printf("size: %lu\n", loose_size / 1024);
printf("in-pack: %lu\n", packed);
printf("packs: %lu\n", num_pack);
+ printf("size-pack: %lu\n", size_pack / 1024);
printf("prune-packable: %lu\n", packed_loose);
printf("garbage: %lu\n", garbage);
}
diff --git a/builtin-diff-tree.c b/builtin-diff-tree.c
index 415cb1612f..1138c2da73 100644
--- a/builtin-diff-tree.c
+++ b/builtin-diff-tree.c
@@ -14,20 +14,10 @@ static int diff_tree_commit_sha1(const unsigned char *sha1)
return log_tree_commit(&log_tree_opt, commit);
}
-static int diff_tree_stdin(char *line)
+/* Diff one or more commits. */
+static int stdin_diff_commit(struct commit *commit, char *line, int len)
{
- int len = strlen(line);
unsigned char sha1[20];
- struct commit *commit;
-
- if (!len || line[len-1] != '\n')
- return -1;
- line[len-1] = 0;
- if (get_sha1_hex(line, sha1))
- return -1;
- commit = lookup_commit(sha1);
- if (!commit || parse_commit(commit))
- return -1;
if (isspace(line[40]) && !get_sha1_hex(line+41, sha1)) {
/* Graft the fake parents locally to the commit */
int pos = 41;
@@ -52,6 +42,48 @@ static int diff_tree_stdin(char *line)
return log_tree_commit(&log_tree_opt, commit);
}
+/* Diff two trees. */
+static int stdin_diff_trees(struct tree *tree1, char *line, int len)
+{
+ unsigned char sha1[20];
+ struct tree *tree2;
+ if (len != 82 || !isspace(line[40]) || get_sha1_hex(line + 41, sha1))
+ return error("Need exactly two trees, separated by a space");
+ tree2 = lookup_tree(sha1);
+ if (!tree2 || parse_tree(tree2))
+ return -1;
+ printf("%s %s\n", sha1_to_hex(tree1->object.sha1),
+ sha1_to_hex(tree2->object.sha1));
+ diff_tree_sha1(tree1->object.sha1, tree2->object.sha1,
+ "", &log_tree_opt.diffopt);
+ log_tree_diff_flush(&log_tree_opt);
+ return 0;
+}
+
+static int diff_tree_stdin(char *line)
+{
+ int len = strlen(line);
+ unsigned char sha1[20];
+ struct object *obj;
+
+ if (!len || line[len-1] != '\n')
+ return -1;
+ line[len-1] = 0;
+ if (get_sha1_hex(line, sha1))
+ return -1;
+ obj = lookup_object(sha1);
+ obj = obj ? obj : parse_object(sha1);
+ if (!obj)
+ return -1;
+ if (obj->type == OBJ_COMMIT)
+ return stdin_diff_commit((struct commit *)obj, line, len);
+ if (obj->type == OBJ_TREE)
+ return stdin_diff_trees((struct tree *)obj, line, len);
+ error("Object %s is a %s, not a commit or tree",
+ sha1_to_hex(sha1), typename(obj->type));
+ return -1;
+}
+
static const char diff_tree_usage[] =
"git diff-tree [--stdin] [-m] [-c] [--cc] [-s] [-v] [--pretty] [-t] [-r] [--root] "
"[<common diff options>] <tree-ish> [<tree-ish>] [<path>...]\n"
diff --git a/builtin-fast-export.c b/builtin-fast-export.c
index 070971616d..7c93eb878d 100644
--- a/builtin-fast-export.c
+++ b/builtin-fast-export.c
@@ -417,7 +417,8 @@ static void export_marks(char *file)
for (i = 0; i < idnums.size; i++) {
if (deco->base && deco->base->type == 1) {
mark = ptr_to_mark(deco->decoration);
- fprintf(f, ":%u %s\n", mark, sha1_to_hex(deco->base->sha1));
+ fprintf(f, ":%"PRIu32" %s\n", mark,
+ sha1_to_hex(deco->base->sha1));
}
deco++;
}
diff --git a/builtin-log.c b/builtin-log.c
index 911fd65990..1d3c5cbf58 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -217,6 +217,11 @@ static int cmd_log_walk(struct rev_info *rev)
if (rev->early_output)
finish_early_output(rev);
+ /*
+ * For --check and --exit-code, the exit code is based on CHECK_FAILED
+ * and HAS_CHANGES being accumulated in rev->diffopt, so be careful to
+ * retain that state information if replacing rev->diffopt in this loop
+ */
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
if (!rev->reflog_info) {
@@ -227,7 +232,11 @@ static int cmd_log_walk(struct rev_info *rev)
free_commit_list(commit->parents);
commit->parents = NULL;
}
- return 0;
+ if (rev->diffopt.output_format & DIFF_FORMAT_CHECKDIFF &&
+ DIFF_OPT_TST(&rev->diffopt, CHECK_FAILED)) {
+ return 02;
+ }
+ return diff_result_code(&rev->diffopt, 0);
}
static int git_log_config(const char *var, const char *value, void *cb)
@@ -923,7 +932,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
if (argc > 1)
die ("unrecognized argument: %s", argv[1]);
- if (!rev.diffopt.output_format)
+ if (!rev.diffopt.output_format
+ || rev.diffopt.output_format == DIFF_FORMAT_PATCH)
rev.diffopt.output_format = DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_SUMMARY | DIFF_FORMAT_PATCH;
if (!DIFF_OPT_TST(&rev.diffopt, TEXT) && !no_binary_diff)
diff --git a/builtin-merge-base.c b/builtin-merge-base.c
index 3382b1382a..b08da516e4 100644
--- a/builtin-merge-base.c
+++ b/builtin-merge-base.c
@@ -2,9 +2,11 @@
#include "cache.h"
#include "commit.h"
-static int show_merge_base(struct commit *rev1, struct commit *rev2, int show_all)
+static int show_merge_base(struct commit **rev, int rev_nr, int show_all)
{
- struct commit_list *result = get_merge_bases(rev1, rev2, 0);
+ struct commit_list *result;
+
+ result = get_merge_bases_many(rev[0], rev_nr - 1, rev + 1, 0);
if (!result)
return 1;
@@ -20,7 +22,7 @@ static int show_merge_base(struct commit *rev1, struct commit *rev2, int show_al
}
static const char merge_base_usage[] =
-"git merge-base [--all] <commit-id> <commit-id>";
+"git merge-base [--all] <commit-id> <commit-id>...";
static struct commit *get_commit_reference(const char *arg)
{
@@ -38,7 +40,8 @@ static struct commit *get_commit_reference(const char *arg)
int cmd_merge_base(int argc, const char **argv, const char *prefix)
{
- struct commit *rev1, *rev2;
+ struct commit **rev;
+ int rev_nr = 0;
int show_all = 0;
git_config(git_default_config, NULL);
@@ -51,10 +54,15 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix)
usage(merge_base_usage);
argc--; argv++;
}
- if (argc != 3)
+ if (argc < 3)
usage(merge_base_usage);
- rev1 = get_commit_reference(argv[1]);
- rev2 = get_commit_reference(argv[2]);
- return show_merge_base(rev1, rev2, show_all);
+ rev = xmalloc((argc - 1) * sizeof(*rev));
+
+ do {
+ rev[rev_nr++] = get_commit_reference(argv[1]);
+ argc--; argv++;
+ } while (argc > 1);
+
+ return show_merge_base(rev, rev_nr, show_all);
}
diff --git a/builtin-merge-recursive.c b/builtin-merge-recursive.c
index 43e55bf901..dfb363ee2f 100644
--- a/builtin-merge-recursive.c
+++ b/builtin-merge-recursive.c
@@ -729,13 +729,13 @@ static void conflict_rename_rename(struct rename *ren1,
const char *dst_name2 = ren2_dst;
if (string_list_has_string(&current_directory_set, ren1_dst)) {
dst_name1 = del[delp++] = unique_path(ren1_dst, branch1);
- output(1, "%s is a directory in %s added as %s instead",
+ output(1, "%s is a directory in %s adding as %s instead",
ren1_dst, branch2, dst_name1);
remove_file(0, ren1_dst, 0);
}
if (string_list_has_string(&current_directory_set, ren2_dst)) {
dst_name2 = del[delp++] = unique_path(ren2_dst, branch2);
- output(1, "%s is a directory in %s added as %s instead",
+ output(1, "%s is a directory in %s adding as %s instead",
ren2_dst, branch1, dst_name2);
remove_file(0, ren2_dst, 0);
}
@@ -760,7 +760,7 @@ static void conflict_rename_dir(struct rename *ren1,
const char *branch1)
{
char *new_path = unique_path(ren1->pair->two->path, branch1);
- output(1, "Renamed %s to %s instead", ren1->pair->one->path, new_path);
+ output(1, "Renaming %s to %s instead", ren1->pair->one->path, new_path);
remove_file(0, ren1->pair->two->path, 0);
update_file(0, ren1->pair->two->sha1, ren1->pair->two->mode, new_path);
free(new_path);
@@ -773,7 +773,7 @@ static void conflict_rename_rename_2(struct rename *ren1,
{
char *new_path1 = unique_path(ren1->pair->two->path, branch1);
char *new_path2 = unique_path(ren2->pair->two->path, branch2);
- output(1, "Renamed %s to %s and %s to %s instead",
+ output(1, "Renaming %s to %s and %s to %s instead",
ren1->pair->one->path, new_path1,
ren2->pair->one->path, new_path2);
remove_file(0, ren1->pair->two->path, 0);
@@ -887,10 +887,10 @@ static int process_renames(struct string_list *a_renames,
branch1,
branch2);
if (mfi.merge || !mfi.clean)
- output(1, "Renamed %s->%s", src, ren1_dst);
+ output(1, "Renaming %s->%s", src, ren1_dst);
if (mfi.merge)
- output(2, "Auto-merged %s", ren1_dst);
+ output(2, "Auto-merging %s", ren1_dst);
if (!mfi.clean) {
output(1, "CONFLICT (content): merge conflict in %s",
@@ -924,14 +924,14 @@ static int process_renames(struct string_list *a_renames,
if (string_list_has_string(&current_directory_set, ren1_dst)) {
clean_merge = 0;
- output(1, "CONFLICT (rename/directory): Renamed %s->%s in %s "
+ output(1, "CONFLICT (rename/directory): Rename %s->%s in %s "
" directory %s added in %s",
ren1_src, ren1_dst, branch1,
ren1_dst, branch2);
conflict_rename_dir(ren1, branch1);
} else if (sha_eq(src_other.sha1, null_sha1)) {
clean_merge = 0;
- output(1, "CONFLICT (rename/delete): Renamed %s->%s in %s "
+ output(1, "CONFLICT (rename/delete): Rename %s->%s in %s "
"and deleted in %s",
ren1_src, ren1_dst, branch1,
branch2);
@@ -940,19 +940,19 @@ static int process_renames(struct string_list *a_renames,
const char *new_path;
clean_merge = 0;
try_merge = 1;
- output(1, "CONFLICT (rename/add): Renamed %s->%s in %s. "
+ output(1, "CONFLICT (rename/add): Rename %s->%s in %s. "
"%s added in %s",
ren1_src, ren1_dst, branch1,
ren1_dst, branch2);
new_path = unique_path(ren1_dst, branch2);
- output(1, "Added as %s instead", new_path);
+ output(1, "Adding as %s instead", new_path);
update_file(0, dst_other.sha1, dst_other.mode, new_path);
} else if ((item = string_list_lookup(ren1_dst, renames2Dst))) {
ren2 = item->util;
clean_merge = 0;
ren2->processed = 1;
- output(1, "CONFLICT (rename/rename): Renamed %s->%s in %s. "
- "Renamed %s->%s in %s",
+ output(1, "CONFLICT (rename/rename): Rename %s->%s in %s. "
+ "Rename %s->%s in %s",
ren1_src, ren1_dst, branch1,
ren2->pair->one->path, ren2->pair->two->path, branch2);
conflict_rename_rename_2(ren1, branch1, ren2, branch2);
@@ -986,9 +986,9 @@ static int process_renames(struct string_list *a_renames,
output(3, "Skipped %s (merged same as existing)", ren1_dst);
else {
if (mfi.merge || !mfi.clean)
- output(1, "Renamed %s => %s", ren1_src, ren1_dst);
+ output(1, "Renaming %s => %s", ren1_src, ren1_dst);
if (mfi.merge)
- output(2, "Auto-merged %s", ren1_dst);
+ output(2, "Auto-merging %s", ren1_dst);
if (!mfi.clean) {
output(1, "CONFLICT (rename/modify): Merge conflict in %s",
ren1_dst);
@@ -1039,7 +1039,7 @@ static int process_entry(const char *path, struct stage_data *entry,
/* Deleted in both or deleted in one and
* unchanged in the other */
if (a_sha)
- output(2, "Removed %s", path);
+ output(2, "Removing %s", path);
/* do not touch working file if it did not exist */
remove_file(1, path, !a_sha);
} else {
@@ -1086,12 +1086,12 @@ static int process_entry(const char *path, struct stage_data *entry,
const char *new_path = unique_path(path, add_branch);
clean_merge = 0;
output(1, "CONFLICT (%s): There is a directory with name %s in %s. "
- "Added %s as %s",
+ "Adding %s as %s",
conf, path, other_branch, path, new_path);
remove_file(0, path, 0);
update_file(0, sha, mode, new_path);
} else {
- output(2, "Added %s", path);
+ output(2, "Adding %s", path);
update_file(1, sha, mode, path);
}
} else if (a_sha && b_sha) {
@@ -1105,7 +1105,7 @@ static int process_entry(const char *path, struct stage_data *entry,
reason = "add/add";
o_sha = (unsigned char *)null_sha1;
}
- output(2, "Auto-merged %s", path);
+ output(2, "Auto-merging %s", path);
o.path = a.path = b.path = (char *)path;
hashcpy(o.sha1, o_sha);
o.mode = o_mode;
diff --git a/builtin-merge.c b/builtin-merge.c
index a201c6628d..0bff26e833 100644
--- a/builtin-merge.c
+++ b/builtin-merge.c
@@ -564,8 +564,6 @@ static int checkout_fast_forward(unsigned char *head, unsigned char *remote)
struct dir_struct dir;
struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file));
- if (read_cache_unmerged())
- die("you need to resolve your current index first");
refresh_cache(REFRESH_QUIET);
fd = hold_locked_index(lock_file, 1);
@@ -651,13 +649,15 @@ static void add_strategies(const char *string, unsigned attr)
static int merge_trivial(void)
{
unsigned char result_tree[20], result_commit[20];
- struct commit_list parent;
+ struct commit_list *parent = xmalloc(sizeof(struct commit_list *));
write_tree_trivial(result_tree);
printf("Wonderful.\n");
- parent.item = remoteheads->item;
- parent.next = NULL;
- commit_tree(merge_msg.buf, result_tree, &parent, result_commit);
+ parent->item = lookup_commit(head);
+ parent->next = xmalloc(sizeof(struct commit_list *));
+ parent->next->item = remoteheads->item;
+ parent->next->next = NULL;
+ commit_tree(merge_msg.buf, result_tree, parent, result_commit);
finish(result_commit, "In-index merge");
drop_save();
return 0;
@@ -743,6 +743,7 @@ static int evaluate_result(void)
int cnt = 0;
struct rev_info rev;
+ discard_cache();
if (read_cache() < 0)
die("failed to read the cache");
@@ -776,7 +777,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
struct commit_list **remotes = &remoteheads;
setup_work_tree();
- if (unmerged_cache())
+ if (read_cache_unmerged())
die("You are in the middle of a conflicted merge.");
/*
@@ -833,6 +834,11 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
if (argc != 1)
die("Can merge only exactly one commit into "
"empty head");
+ if (squash)
+ die("Squash commit into empty head not supported yet");
+ if (!allow_fast_forward)
+ die("Non-fast-forward commit does not make sense into "
+ "an empty head");
remote_head = peel_to_type(argv[0], 0, NULL, OBJ_COMMIT);
if (!remote_head)
die("%s - not something we can merge", argv[0]);
@@ -1073,6 +1079,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
}
/* Automerge succeeded. */
+ discard_cache();
write_tree_trivial(result_tree);
automerge_was_ok = 1;
break;
diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
index 2dadec1630..d394c494a5 100644
--- a/builtin-pack-objects.c
+++ b/builtin-pack-objects.c
@@ -499,7 +499,6 @@ static void write_pack_file(void)
} else {
int fd = sha1close(f, NULL, 0);
fixup_pack_header_footer(fd, sha1, pack_tmp_name, nr_written);
- fsync_or_die(fd, pack_tmp_name);
close(fd);
}
diff --git a/builtin-push.c b/builtin-push.c
index c1ed68d938..cc6666f75e 100644
--- a/builtin-push.c
+++ b/builtin-push.c
@@ -59,8 +59,17 @@ static int do_push(const char *repo, int flags)
if (remote->mirror)
flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
- if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) && refspec)
- return -1;
+ if ((flags & TRANSPORT_PUSH_ALL) && refspec) {
+ if (!strcmp(*refspec, "refs/tags/*"))
+ return error("--all and --tags are incompatible");
+ return error("--all can't be combined with refspecs");
+ }
+
+ if ((flags & TRANSPORT_PUSH_MIRROR) && refspec) {
+ if (!strcmp(*refspec, "refs/tags/*"))
+ return error("--mirror and --tags are incompatible");
+ return error("--mirror can't be combined with refspecs");
+ }
if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) ==
(TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) {
diff --git a/builtin-reflog.c b/builtin-reflog.c
index 196fa03b7f..6b3667ef0e 100644
--- a/builtin-reflog.c
+++ b/builtin-reflog.c
@@ -540,11 +540,11 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
free(collected.e);
}
- while (i < argc) {
- const char *ref = argv[i++];
+ for (; i < argc; i++) {
+ char *ref;
unsigned char sha1[20];
- if (!resolve_ref(ref, sha1, 1, NULL)) {
- status |= error("%s points nowhere!", ref);
+ if (!dwim_log(argv[i], strlen(argv[i]), sha1, &ref)) {
+ status |= error("%s points nowhere!", argv[i]);
continue;
}
set_reflog_expiry_param(&cb, explicit_expiry, ref);
diff --git a/builtin-rev-list.c b/builtin-rev-list.c
index 893762c80f..c023003b2b 100644
--- a/builtin-rev-list.c
+++ b/builtin-rev-list.c
@@ -645,7 +645,8 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
revs.diff)
usage(rev_list_usage);
- save_commit_buffer = revs.verbose_header || revs.grep_filter;
+ save_commit_buffer = revs.verbose_header ||
+ revs.grep_filter.pattern_list;
if (bisect_list)
revs.limited = 1;
diff --git a/builtin-update-index.c b/builtin-update-index.c
index 38eb53ccba..434cb8e4a0 100644
--- a/builtin-update-index.c
+++ b/builtin-update-index.c
@@ -194,6 +194,10 @@ static int process_path(const char *path)
int len;
struct stat st;
+ len = strlen(path);
+ if (has_symlink_leading_path(len, path))
+ return error("'%s' is beyond a symbolic link", path);
+
/*
* First things first: get the stat information, to decide
* what to do about the pathname!
@@ -201,7 +205,6 @@ static int process_path(const char *path)
if (lstat(path, &st) < 0)
return process_lstat_error(path, errno);
- len = strlen(path);
if (S_ISDIR(st.st_mode))
return process_directory(path, len, &st);
diff --git a/cache.h b/cache.h
index 2475de9fa8..ab9f97efc6 100644
--- a/cache.h
+++ b/cache.h
@@ -126,6 +126,7 @@ struct cache_entry {
#define CE_NAMEMASK (0x0fff)
#define CE_STAGEMASK (0x3000)
+#define CE_EXTENDED (0x4000)
#define CE_VALID (0x8000)
#define CE_STAGESHIFT 12
@@ -222,7 +223,8 @@ struct index_state {
struct cache_tree *cache_tree;
time_t timestamp;
void *alloc;
- unsigned name_hash_initialized : 1;
+ unsigned name_hash_initialized : 1,
+ initialized : 1;
struct hash_table name_hash;
};
@@ -391,7 +393,6 @@ extern int ie_modified(const struct index_state *, struct cache_entry *, struct
extern int ce_path_match(const struct cache_entry *ce, const char **pathspec);
extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, enum object_type type, const char *path);
-extern int index_pipe(unsigned char *sha1, int fd, const char *type, int write_object);
extern int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object);
extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);
@@ -451,6 +452,7 @@ enum safe_crlf {
extern enum safe_crlf safe_crlf;
enum branch_track {
+ BRANCH_TRACK_UNSPECIFIED = -1,
BRANCH_TRACK_NEVER = 0,
BRANCH_TRACK_REMOTE,
BRANCH_TRACK_ALWAYS,
diff --git a/combine-diff.c b/combine-diff.c
index 9f80a1c5e3..0cf2a830b5 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -143,8 +143,6 @@ static void append_lost(struct sline *sline, int n, const char *line, int len)
}
struct combine_diff_state {
- struct xdiff_emit_state xm;
-
unsigned int lno;
int ob, on, nb, nn;
unsigned long nmask;
@@ -217,17 +215,15 @@ static void combine_diff(const unsigned char *parent, mmfile_t *result_file,
parent_file.size = sz;
xpp.flags = XDF_NEED_MINIMAL;
memset(&xecfg, 0, sizeof(xecfg));
- ecb.outf = xdiff_outf;
- ecb.priv = &state;
memset(&state, 0, sizeof(state));
- state.xm.consume = consume_line;
state.nmask = nmask;
state.sline = sline;
state.lno = 1;
state.num_parent = num_parent;
state.n = n;
- xdi_diff(&parent_file, result_file, &xpp, &xecfg, &ecb);
+ xdi_diff_outf(&parent_file, result_file, consume_line, &state,
+ &xpp, &xecfg, &ecb);
free(parent_file.ptr);
/* Assign line numbers for this parent.
@@ -727,6 +723,18 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
die("early EOF '%s'", elem->path);
result[len] = 0;
+
+ /* If not a fake symlink, apply filters, e.g. autocrlf */
+ if (is_file) {
+ struct strbuf buf;
+
+ strbuf_init(&buf, 0);
+ if (convert_to_git(elem->path, result, len, &buf, safe_crlf)) {
+ free(result);
+ result = strbuf_detach(&buf, &len);
+ result_size = len;
+ }
+ }
}
else {
deleted_file:
diff --git a/commit.h b/commit.h
index 77de9621d9..d163c7487b 100644
--- a/commit.h
+++ b/commit.h
@@ -121,6 +121,7 @@ int read_graft_file(const char *graft_file);
struct commit_graft *lookup_commit_graft(const unsigned char *sha1);
extern struct commit_list *get_merge_bases(struct commit *rev1, struct commit *rev2, int cleanup);
+extern struct commit_list *get_merge_bases_many(struct commit *one, int n, struct commit **twos, int cleanup);
extern struct commit_list *get_octopus_merge_bases(struct commit_list *in);
extern int register_shallow(const unsigned char *sha1);
diff --git a/compat/mingw.c b/compat/mingw.c
index 772cad510d..ccfa2a0a3d 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -31,11 +31,6 @@ static inline time_t filetime_to_time_t(const FILETIME *ft)
return (time_t)winTime;
}
-static inline size_t size_to_blocks(size_t s)
-{
- return (s+511)/512;
-}
-
extern int _getdrive( void );
/* We keep the do_lstat code in a separate function to avoid recursion.
* When a path ends with a slash, the stat will fail with ENOENT. In
@@ -57,10 +52,10 @@ static int do_lstat(const char *file_name, struct stat *buf)
buf->st_ino = 0;
buf->st_gid = 0;
buf->st_uid = 0;
+ buf->st_nlink = 1;
buf->st_mode = fMode;
buf->st_size = fdata.nFileSizeLow; /* Can't use nFileSizeHigh, since it's not a stat64 */
- buf->st_blocks = size_to_blocks(buf->st_size);
- buf->st_dev = _getdrive() - 1;
+ buf->st_dev = buf->st_rdev = (_getdrive() - 1);
buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
@@ -94,7 +89,7 @@ static int do_lstat(const char *file_name, struct stat *buf)
* complete. Note that Git stat()s are redirected to mingw_lstat()
* too, since Windows doesn't really handle symlinks that well.
*/
-int mingw_lstat(const char *file_name, struct mingw_stat *buf)
+int mingw_lstat(const char *file_name, struct stat *buf)
{
int namelen;
static char alt_name[PATH_MAX];
@@ -122,8 +117,7 @@ int mingw_lstat(const char *file_name, struct mingw_stat *buf)
}
#undef fstat
-#undef stat
-int mingw_fstat(int fd, struct mingw_stat *buf)
+int mingw_fstat(int fd, struct stat *buf)
{
HANDLE fh = (HANDLE)_get_osfhandle(fd);
BY_HANDLE_FILE_INFORMATION fdata;
@@ -133,22 +127,8 @@ int mingw_fstat(int fd, struct mingw_stat *buf)
return -1;
}
/* direct non-file handles to MS's fstat() */
- if (GetFileType(fh) != FILE_TYPE_DISK) {
- struct stat st;
- if (fstat(fd, &st))
- return -1;
- buf->st_ino = st.st_ino;
- buf->st_gid = st.st_gid;
- buf->st_uid = st.st_uid;
- buf->st_mode = st.st_mode;
- buf->st_size = st.st_size;
- buf->st_blocks = size_to_blocks(buf->st_size);
- buf->st_dev = st.st_dev;
- buf->st_atime = st.st_atime;
- buf->st_mtime = st.st_mtime;
- buf->st_ctime = st.st_ctime;
- return 0;
- }
+ if (GetFileType(fh) != FILE_TYPE_DISK)
+ return fstat(fd, buf);
if (GetFileInformationByHandle(fh, &fdata)) {
int fMode = S_IREAD;
@@ -162,10 +142,10 @@ int mingw_fstat(int fd, struct mingw_stat *buf)
buf->st_ino = 0;
buf->st_gid = 0;
buf->st_uid = 0;
+ buf->st_nlink = 1;
buf->st_mode = fMode;
buf->st_size = fdata.nFileSizeLow; /* Can't use nFileSizeHigh, since it's not a stat64 */
- buf->st_blocks = size_to_blocks(buf->st_size);
- buf->st_dev = _getdrive() - 1;
+ buf->st_dev = buf->st_rdev = (_getdrive() - 1);
buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
diff --git a/compat/mingw.h b/compat/mingw.h
index a52e657c51..4f275cb8e6 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -162,22 +162,12 @@ int mingw_rename(const char*, const char*);
/* Use mingw_lstat() instead of lstat()/stat() and
* mingw_fstat() instead of fstat() on Windows.
- * struct stat is redefined because it lacks the st_blocks member.
*/
-struct mingw_stat {
- unsigned st_mode;
- time_t st_mtime, st_atime, st_ctime;
- unsigned st_dev, st_ino, st_uid, st_gid;
- size_t st_size;
- size_t st_blocks;
-};
-int mingw_lstat(const char *file_name, struct mingw_stat *buf);
-int mingw_fstat(int fd, struct mingw_stat *buf);
+int mingw_lstat(const char *file_name, struct stat *buf);
+int mingw_fstat(int fd, struct stat *buf);
#define fstat mingw_fstat
#define lstat mingw_lstat
-#define stat mingw_stat
-static inline int mingw_stat(const char *file_name, struct mingw_stat *buf)
-{ return mingw_lstat(file_name, buf); }
+#define stat(x,y) mingw_lstat(x,y)
int mingw_utime(const char *file_name, const struct utimbuf *times);
#define utime mingw_utime
diff --git a/config.mak.in b/config.mak.in
index b776149531..f67d673d01 100644
--- a/config.mak.in
+++ b/config.mak.in
@@ -3,6 +3,7 @@
CC = @CC@
CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
AR = @AR@
TAR = @TAR@
#INSTALL = @INSTALL@ # needs install-sh or install.sh in sources
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index a31004088a..89858c237e 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -771,7 +771,7 @@ _git_diff ()
__gitcomp "--cached --stat --numstat --shortstat --summary
--patch-with-stat --name-only --name-status --color
--no-color --color-words --no-renames --check
- --full-index --binary --abbrev --diff-filter
+ --full-index --binary --abbrev --diff-filter=
--find-copies-harder --pickaxe-all --pickaxe-regex
--text --ignore-space-at-eol --ignore-space-change
--ignore-all-space --exit-code --quiet --ext-diff
diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4
index f9865b444f..c1d24b38f3 100755
--- a/contrib/fast-import/git-p4
+++ b/contrib/fast-import/git-p4
@@ -76,7 +76,7 @@ def write_pipe(c, str):
def p4_write_pipe(c, str):
real_cmd = p4_build_cmd(c)
- return write_pipe(c, str)
+ return write_pipe(real_cmd, str)
def read_pipe(c, ignore_error=False):
if verbose:
@@ -708,6 +708,7 @@ class P4Submit(Command):
newdiff = newdiff.replace("\n", "\r\n")
tmpFile.write(submitTemplate + separatorLine + diff + newdiff)
tmpFile.close()
+ mtime = os.stat(fileName).st_mtime
defaultEditor = "vi"
if platform.system() == "Windows":
defaultEditor = "notepad"
@@ -716,15 +717,29 @@ class P4Submit(Command):
else:
editor = os.environ.get("EDITOR", defaultEditor);
system(editor + " " + fileName)
- tmpFile = open(fileName, "rb")
- message = tmpFile.read()
- tmpFile.close()
- os.remove(fileName)
- submitTemplate = message[:message.index(separatorLine)]
- if self.isWindows:
- submitTemplate = submitTemplate.replace("\r\n", "\n")
- p4_write_pipe("submit -i", submitTemplate)
+ response = "y"
+ if os.stat(fileName).st_mtime <= mtime:
+ response = "x"
+ while response != "y" and response != "n":
+ response = raw_input("Submit template unchanged. Submit anyway? [y]es, [n]o (skip this patch) ")
+
+ if response == "y":
+ tmpFile = open(fileName, "rb")
+ message = tmpFile.read()
+ tmpFile.close()
+ submitTemplate = message[:message.index(separatorLine)]
+ if self.isWindows:
+ submitTemplate = submitTemplate.replace("\r\n", "\n")
+ p4_write_pipe("submit -i", submitTemplate)
+ else:
+ for f in editedFiles:
+ p4_system("revert \"%s\"" % f);
+ for f in filesToAdd:
+ p4_system("revert \"%s\"" % f);
+ system("rm %s" %f)
+
+ os.remove(fileName)
else:
fileName = "submit.txt"
file = open(fileName, "w+")
diff --git a/contrib/fast-import/git-p4.txt b/contrib/fast-import/git-p4.txt
index ac551d45f1..49b335921a 100644
--- a/contrib/fast-import/git-p4.txt
+++ b/contrib/fast-import/git-p4.txt
@@ -3,14 +3,16 @@ git-p4 - Perforce <-> Git converter using git-fast-import
Usage
=====
-git-p4 supports two main modes: Importing from Perforce to a Git repository is
-done using "git-p4 sync" or "git-p4 rebase". Submitting changes from Git back
-to Perforce is done using "git-p4 submit".
+git-p4 can be used in two different ways:
+
+1) To import changes from Perforce to a Git repository, using "git-p4 sync".
+
+2) To submit changes from Git back to Perforce, using "git-p4 submit".
Importing
=========
-You can simply start with
+Simply start with
git-p4 clone //depot/path/project
@@ -18,11 +20,18 @@ or
git-p4 clone //depot/path/project myproject
-This will create an empty git repository in a subdirectory called "project" (or
-"myproject" with the second command), import the head revision from the
-specified perforce path into a git "p4" branch (remotes/p4 actually), create a
-master branch off it and check it out. If you want the entire history (not just
-the head revision) then you can simply append a "@all" to the depot path:
+This will:
+
+1) Create an empty git repository in a subdirectory called "project" (or
+"myproject" with the second command)
+
+2) Import the head revision from the given Perforce path into a git branch
+called "p4" (remotes/p4 actually)
+
+3) Create a master branch based on it and check it out.
+
+If you want the entire history (not just the head revision) then you can simply
+append a "@all" to the depot path:
git-p4 clone //depot/project/main@all myproject
@@ -37,31 +46,40 @@ If you want more control you can also use the git-p4 sync command directly:
This will import the current head revision of the specified depot path into a
"remotes/p4/master" branch of your git repository. You can use the
---branch=mybranch option to use a different branch.
+--branch=mybranch option to import into a different branch.
-If you want to import the entire history of a given depot path just use
+If you want to import the entire history of a given depot path simply use:
git-p4 sync //path/in/depot@all
+
+Note:
+
To achieve optimal compression you may want to run 'git repack -a -d -f' after
a big import. This may take a while.
-Support for Perforce integrations is still work in progress. Don't bother
-trying it unless you want to hack on it :)
-
Incremental Imports
===================
-After an initial import you can easily synchronize your git repository with
-newer changes from the Perforce depot by just calling
+After an initial import you can continue to synchronize your git repository
+with newer changes from the Perforce depot by just calling
git-p4 sync
in your git repository. By default the "remotes/p4/master" branch is updated.
-It is recommended to run 'git repack -a -d -f' from time to time when using
-incremental imports to optimally combine the individual git packs that each
-incremental import creates through the use of git-fast-import.
+Advanced Setup
+==============
+
+Suppose you have a periodically updated git repository somewhere, containing a
+complete import of a Perforce project. This repository can be cloned and used
+with git-p4. When updating the cloned repository with the "sync" command,
+git-p4 will try to fetch changes from the original repository first. The git
+protocol used with this is usually faster than importing from Perforce
+directly.
+
+This behaviour can be disabled by setting the "git-p4.syncFromOrigin" git
+configuration variable to "false".
Updating
========
@@ -79,7 +97,7 @@ Submitting
==========
git-p4 has support for submitting changes from a git repository back to the
-Perforce depot. This requires a Perforce checkout separate to your git
+Perforce depot. This requires a Perforce checkout separate from your git
repository. To submit all changes that are in the current git branch but not in
the "p4" branch (or "origin" if "p4" doesn't exist) simply call
@@ -97,17 +115,6 @@ continue importing the remaining changes with
git-p4 submit --continue
-After submitting you should sync your perforce import branch ("p4" or "origin")
-from Perforce using git-p4's sync command.
-
-If you have changes in your working directory that you haven't committed into
-git yet but that you want to commit to Perforce directly ("quick fixes") then
-you do not have to go through the intermediate step of creating a git commit
-first but you can just call
-
- git-p4 submit --direct
-
-
Example
=======
diff --git a/ctype.c b/ctype.c
index ee06eb7f48..d2bd38e901 100644
--- a/ctype.c
+++ b/ctype.c
@@ -5,6 +5,11 @@
*/
#include "cache.h"
+/* Just so that no insane platform contaminate namespace with these symbols */
+#undef SS
+#undef AA
+#undef DD
+
#define SS GIT_SPACE
#define AA GIT_ALPHA
#define DD GIT_DIGIT
diff --git a/diff.c b/diff.c
index f70e6b4912..18fa7a712c 100644
--- a/diff.c
+++ b/diff.c
@@ -20,6 +20,7 @@
static int diff_detect_rename_default;
static int diff_rename_limit_default = 200;
+static int diff_suppress_blank_empty;
int diff_use_color_default = -1;
static const char *external_diff_cmd_cfg;
int diff_auto_refresh_index = 1;
@@ -176,6 +177,12 @@ int git_diff_basic_config(const char *var, const char *value, void *cb)
return 0;
}
+ /* like GNU diff's --suppress-blank-empty option */
+ if (!strcmp(var, "diff.suppress-blank-empty")) {
+ diff_suppress_blank_empty = git_config_bool(var, value);
+ return 0;
+ }
+
if (!prefixcmp(var, "diff.")) {
const char *ep = strrchr(var, '.');
if (ep != var + 4) {
@@ -369,7 +376,6 @@ static void diff_words_append(char *line, unsigned long len,
}
struct diff_words_data {
- struct xdiff_emit_state xm;
struct diff_words_buffer minus, plus;
FILE *file;
};
@@ -459,11 +465,8 @@ static void diff_words_show(struct diff_words_data *diff_words)
xpp.flags = XDF_NEED_MINIMAL;
xecfg.ctxlen = diff_words->minus.alloc + diff_words->plus.alloc;
- ecb.outf = xdiff_outf;
- ecb.priv = diff_words;
- diff_words->xm.consume = fn_out_diff_words_aux;
- xdi_diff(&minus, &plus, &xpp, &xecfg, &ecb);
-
+ xdi_diff_outf(&minus, &plus, fn_out_diff_words_aux, diff_words,
+ &xpp, &xecfg, &ecb);
free(minus.ptr);
free(plus.ptr);
diff_words->minus.text.size = diff_words->plus.text.size = 0;
@@ -477,7 +480,6 @@ static void diff_words_show(struct diff_words_data *diff_words)
typedef unsigned long (*sane_truncate_fn)(char *line, unsigned long len);
struct emit_callback {
- struct xdiff_emit_state xm;
int nparents, color_diff;
unsigned ws_rule;
sane_truncate_fn truncate;
@@ -580,6 +582,12 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
ecbdata->label_path[0] = ecbdata->label_path[1] = NULL;
}
+ if (diff_suppress_blank_empty
+ && len == 2 && line[0] == ' ' && line[1] == '\n') {
+ line[0] = '\n';
+ len = 1;
+ }
+
/* This is not really necessary for now because
* this codepath only deals with two-way diffs.
*/
@@ -708,8 +716,6 @@ static char *pprint_rename(const char *a, const char *b)
}
struct diffstat_t {
- struct xdiff_emit_state xm;
-
int nr;
int alloc;
struct diffstat_file {
@@ -1131,7 +1137,6 @@ static void free_diffstat_info(struct diffstat_t *diffstat)
}
struct checkdiff_t {
- struct xdiff_emit_state xm;
const char *filename;
int lineno;
struct diff_options *o;
@@ -1376,6 +1381,8 @@ static struct builtin_funcname_pattern {
const char *name;
const char *pattern;
} builtin_funcname_pattern[] = {
+ { "bibtex", "\\(@[a-zA-Z]\\{1,\\}[ \t]*{\\{0,1\\}[ \t]*[^ \t\"@',\\#}{~%]*\\).*$" },
+ { "html", "^\\s*\\(<[Hh][1-6]\\s.*>.*\\)$" },
{ "java", "!^[ ]*\\(catch\\|do\\|for\\|if\\|instanceof\\|"
"new\\|return\\|switch\\|throw\\|while\\)\n"
"^[ ]*\\(\\([ ]*"
@@ -1387,9 +1394,9 @@ static struct builtin_funcname_pattern {
"\\|"
"^\\(.*=[ \t]*\\(class\\|record\\).*\\)$"
},
- { "bibtex", "\\(@[a-zA-Z]\\{1,\\}[ \t]*{\\{0,1\\}[ \t]*[^ \t\"@',\\#}{~%]*\\).*$" },
- { "tex", "^\\(\\\\\\(\\(sub\\)*section\\|chapter\\|part\\)\\*\\{0,1\\}{.*\\)$" },
+ { "python", "^\\s*\\(\\(class\\|def\\)\\s.*\\)$" },
{ "ruby", "^\\s*\\(\\(class\\|module\\|def\\)\\s.*\\)$" },
+ { "tex", "^\\(\\\\\\(\\(sub\\)*section\\|chapter\\|part\\)\\*\\{0,1\\}{.*\\)$" },
};
static const char *diff_funcname_pattern(struct diff_filespec *one)
@@ -1521,15 +1528,13 @@ static void builtin_diff(const char *name_a,
xecfg.ctxlen = strtoul(diffopts + 10, NULL, 10);
else if (!prefixcmp(diffopts, "-u"))
xecfg.ctxlen = strtoul(diffopts + 2, NULL, 10);
- ecb.outf = xdiff_outf;
- ecb.priv = &ecbdata;
- ecbdata.xm.consume = fn_out_consume;
if (DIFF_OPT_TST(o, COLOR_DIFF_WORDS)) {
ecbdata.diff_words =
xcalloc(1, sizeof(struct diff_words_data));
ecbdata.diff_words->file = o->file;
}
- xdi_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
+ xdi_diff_outf(&mf1, &mf2, fn_out_consume, &ecbdata,
+ &xpp, &xecfg, &ecb);
if (DIFF_OPT_TST(o, COLOR_DIFF_WORDS))
free_diff_words_data(&ecbdata);
}
@@ -1580,9 +1585,8 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
memset(&xecfg, 0, sizeof(xecfg));
xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
- ecb.outf = xdiff_outf;
- ecb.priv = diffstat;
- xdi_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
+ xdi_diff_outf(&mf1, &mf2, diffstat_consume, diffstat,
+ &xpp, &xecfg, &ecb);
}
free_and_return:
@@ -1603,7 +1607,6 @@ static void builtin_checkdiff(const char *name_a, const char *name_b,
return;
memset(&data, 0, sizeof(data));
- data.xm.consume = checkdiff_consume;
data.filename = name_b ? name_b : name_a;
data.lineno = 0;
data.o = o;
@@ -1629,9 +1632,8 @@ static void builtin_checkdiff(const char *name_a, const char *name_b,
memset(&xecfg, 0, sizeof(xecfg));
xecfg.ctxlen = 1; /* at least one context line */
xpp.flags = XDF_NEED_MINIMAL;
- ecb.outf = xdiff_outf;
- ecb.priv = &data;
- xdi_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
+ xdi_diff_outf(&mf1, &mf2, checkdiff_consume, &data,
+ &xpp, &xecfg, &ecb);
if ((data.ws_rule & WS_TRAILING_SPACE) &&
data.trailing_blanks_start) {
@@ -3019,7 +3021,6 @@ static void diff_summary(FILE *file, struct diff_filepair *p)
}
struct patch_id_t {
- struct xdiff_emit_state xm;
SHA_CTX *ctx;
int patchlen;
};
@@ -3064,7 +3065,6 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1)
SHA1_Init(&ctx);
memset(&data, 0, sizeof(struct patch_id_t));
data.ctx = &ctx;
- data.xm.consume = patch_id_consume;
for (i = 0; i < q->nr; i++) {
xpparam_t xpp;
@@ -3129,9 +3129,8 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1)
xpp.flags = XDF_NEED_MINIMAL;
xecfg.ctxlen = 3;
xecfg.flags = XDL_EMIT_FUNCNAMES;
- ecb.outf = xdiff_outf;
- ecb.priv = &data;
- xdi_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
+ xdi_diff_outf(&mf1, &mf2, patch_id_consume, &data,
+ &xpp, &xecfg, &ecb);
}
SHA1_Final(sha1, &ctx);
@@ -3208,7 +3207,6 @@ void diff_flush(struct diff_options *options)
struct diffstat_t diffstat;
memset(&diffstat, 0, sizeof(struct diffstat_t));
- diffstat.xm.consume = diffstat_consume;
for (i = 0; i < q->nr; i++) {
struct diff_filepair *p = q->queue[i];
if (check_pair_status(p))
diff --git a/dir.c b/dir.c
index 109e05b013..92452eb5ef 100644
--- a/dir.c
+++ b/dir.c
@@ -727,8 +727,12 @@ static void free_simplify(struct path_simplify *simplify)
int read_directory(struct dir_struct *dir, const char *path, const char *base, int baselen, const char **pathspec)
{
- struct path_simplify *simplify = create_simplify(pathspec);
+ struct path_simplify *simplify;
+ if (has_symlink_leading_path(strlen(path), path))
+ return dir->nr;
+
+ simplify = create_simplify(pathspec);
read_directory_recursive(dir, path, base, baselen, 0, simplify);
free_simplify(simplify);
qsort(dir->entries, dir->nr, sizeof(struct dir_entry *), cmp_name);
diff --git a/git-compat-util.h b/git-compat-util.h
index cf89cdf459..6ee325546e 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -99,6 +99,11 @@
#include <iconv.h>
#endif
+#ifndef NO_OPENSSL
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#endif
+
/* On most systems <limits.h> would have given us this, but
* not on some systems (e.g. GNU/Hurd).
*/
@@ -192,6 +197,12 @@ extern int git_munmap(void *start, size_t length);
#endif /* NO_MMAP */
+#ifdef NO_ST_BLOCKS_IN_STRUCT_STAT
+#define on_disk_bytes(st) ((st).st_size)
+#else
+#define on_disk_bytes(st) ((st).st_blocks * 512)
+#endif
+
#define DEFAULT_PACKED_GIT_LIMIT \
((1024L * 1024L) * (sizeof(void*) >= 8 ? 8192 : 256))
diff --git a/git-filter-branch.sh b/git-filter-branch.sh
index a324cf0596..2871a59e32 100755
--- a/git-filter-branch.sh
+++ b/git-filter-branch.sh
@@ -416,15 +416,17 @@ if [ "$filter_tag_name" ]; then
echo "$ref -> $new_ref ($sha1 -> $new_sha1)"
if [ "$type" = "tag" ]; then
- new_sha1=$(git cat-file tag "$ref" |
+ new_sha1=$( ( printf 'object %s\ntype commit\ntag %s\n' \
+ "$new_sha1" "$new_ref"
+ git cat-file tag "$ref" |
sed -n \
-e "1,/^$/{
- s/^object .*/object $new_sha1/
- s/^type .*/type commit/
- s/^tag .*/tag $new_ref/
+ /^object /d
+ /^type /d
+ /^tag /d
}" \
-e '/^-----BEGIN PGP SIGNATURE-----/q' \
- -e 'p' |
+ -e 'p' ) |
git mktag) ||
die "Could not create new tag object for $ref"
if git cat-file tag "$ref" | \
diff --git a/git-merge-octopus.sh b/git-merge-octopus.sh
index 645e1147dc..1dadbb4966 100755
--- a/git-merge-octopus.sh
+++ b/git-merge-octopus.sh
@@ -61,7 +61,7 @@ do
exit 2
esac
- common=$(git merge-base --all $MRC $SHA1) ||
+ common=$(git merge-base --all $SHA1 $MRC) ||
die "Unable to find common commit with $SHA1"
case "$LF$common$LF" in
@@ -100,14 +100,7 @@ do
next=$(git write-tree 2>/dev/null)
fi
- # We have merged the other branch successfully. Ideally
- # we could implement OR'ed heads in merge-base, and keep
- # a list of commits we have merged so far in MRC to feed
- # them to merge-base, but we approximate it by keep using
- # the current MRC. We used to update it to $common, which
- # was incorrectly doing AND'ed merge-base here, which was
- # unneeded.
-
+ MRC="$MRC $SHA1"
MRT=$next
done
diff --git a/git-submodule.sh b/git-submodule.sh
index b40f876a2c..4a95035d85 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -6,9 +6,10 @@
USAGE="[--quiet] [--cached] \
[add <repo> [-b branch] <path>]|[status|init|update [-i|--init]|summary [-n|--summary-limit <n>] [<commit>]] \
-[--] [<path>...]"
+[--] [<path>...]|[foreach <command>]|[sync [--] [<path>...]]"
OPTIONS_SPEC=
. git-sh-setup
+. git-parse-remote
require_work_tree
command=
@@ -30,9 +31,7 @@ say()
# Resolve relative url by appending to parent's url
resolve_relative_url ()
{
- branch="$(git symbolic-ref HEAD 2>/dev/null)"
- remote="$(git config branch.${branch#refs/heads/}.remote)"
- remote="${remote:-origin}"
+ remote=$(get_default_remote)
remoteurl=$(git config "remote.$remote.url") ||
die "remote ($remote) does not have a url defined in .git/config"
url="$1"
@@ -54,6 +53,15 @@ resolve_relative_url ()
}
#
+# Get submodule info for registered submodules
+# $@ = path to limit submodule list
+#
+module_list()
+{
+ git ls-files --stage -- "$@" | grep '^160000 '
+}
+
+#
# Map submodule path to submodule name
#
# $1 = path
@@ -199,6 +207,26 @@ cmd_add()
}
#
+# Execute an arbitrary command sequence in each checked out
+# submodule
+#
+# $@ = command to execute
+#
+cmd_foreach()
+{
+ module_list |
+ while read mode sha1 stage path
+ do
+ if test -e "$path"/.git
+ then
+ say "Entering '$path'"
+ (cd "$path" && eval "$@") ||
+ die "Stopping at '$path'; script returned non-zero status."
+ fi
+ done
+}
+
+#
# Register submodules in .git/config
#
# $@ = requested paths (default to all)
@@ -226,7 +254,7 @@ cmd_init()
shift
done
- git ls-files --stage -- "$@" | grep '^160000 ' |
+ module_list "$@" |
while read mode sha1 stage path
do
# Skip already registered paths
@@ -284,7 +312,7 @@ cmd_update()
esac
done
- git ls-files --stage -- "$@" | grep '^160000 ' |
+ module_list "$@" |
while read mode sha1 stage path
do
name=$(module_name "$path") || exit
@@ -549,7 +577,7 @@ cmd_status()
shift
done
- git ls-files --stage -- "$@" | grep '^160000 ' |
+ module_list "$@" |
while read mode sha1 stage path
do
name=$(module_name "$path") || exit
@@ -573,6 +601,50 @@ cmd_status()
fi
done
}
+#
+# Sync remote urls for submodules
+# This makes the value for remote.$remote.url match the value
+# specified in .gitmodules.
+#
+cmd_sync()
+{
+ while test $# -ne 0
+ do
+ case "$1" in
+ -q|--quiet)
+ quiet=1
+ shift
+ ;;
+ --)
+ shift
+ break
+ ;;
+ -*)
+ usage
+ ;;
+ *)
+ break
+ ;;
+ esac
+ done
+ cd_to_toplevel
+ module_list "$@" |
+ while read mode sha1 stage path
+ do
+ name=$(module_name "$path")
+ url=$(git config -f .gitmodules --get submodule."$name".url)
+ if test -e "$path"/.git
+ then
+ (
+ unset GIT_DIR
+ cd "$path"
+ remote=$(get_default_remote)
+ say "Synchronizing submodule url for '$name'"
+ git config remote."$remote".url "$url"
+ )
+ fi
+ done
+}
# This loop parses the command line arguments to find the
# subcommand name to dispatch. Parsing of the subcommand specific
@@ -583,7 +655,7 @@ cmd_status()
while test $# != 0 && test -z "$command"
do
case "$1" in
- add | init | update | status | summary)
+ add | foreach | init | update | status | summary | sync)
command=$1
;;
-q|--quiet)
diff --git a/hash-object.c b/hash-object.c
index 46c06a9552..a4d127cf78 100644
--- a/hash-object.c
+++ b/hash-object.c
@@ -7,16 +7,14 @@
#include "cache.h"
#include "blob.h"
#include "quote.h"
+#include "parse-options.h"
-static void hash_object(const char *path, enum object_type type, int write_object)
+static void hash_fd(int fd, const char *type, int write_object, const char *path)
{
- int fd;
struct stat st;
unsigned char sha1[20];
- fd = open(path, O_RDONLY);
- if (fd < 0 ||
- fstat(fd, &st) < 0 ||
- index_fd(sha1, fd, &st, write_object, type, path))
+ if (fstat(fd, &st) < 0 ||
+ index_fd(sha1, fd, &st, write_object, type_from_string(type), path))
die(write_object
? "Unable to add %s to database"
: "Unable to hash %s", path);
@@ -24,12 +22,14 @@ static void hash_object(const char *path, enum object_type type, int write_objec
maybe_flush_or_die(stdout, "hash to stdout");
}
-static void hash_stdin(const char *type, int write_object)
+static void hash_object(const char *path, const char *type, int write_object,
+ const char *vpath)
{
- unsigned char sha1[20];
- if (index_pipe(sha1, 0, type, write_object))
- die("Unable to add stdin to database");
- printf("%s\n", sha1_to_hex(sha1));
+ int fd;
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ die("Cannot open %s", path);
+ hash_fd(fd, type, write_object, vpath);
}
static void hash_stdin_paths(const char *type, int write_objects)
@@ -45,92 +45,91 @@ static void hash_stdin_paths(const char *type, int write_objects)
die("line is badly quoted");
strbuf_swap(&buf, &nbuf);
}
- hash_object(buf.buf, type_from_string(type), write_objects);
+ hash_object(buf.buf, type, write_objects, buf.buf);
}
strbuf_release(&buf);
strbuf_release(&nbuf);
}
-static const char hash_object_usage[] =
-"git hash-object [ [-t <type>] [-w] [--stdin] <file>... | --stdin-paths < <list-of-paths> ]";
+static const char * const hash_object_usage[] = {
+ "git hash-object [-t <type>] [-w] [--path=<file>|--no-filters] [--stdin] [--] <file>...",
+ "git hash-object --stdin-paths < <list-of-paths>",
+ NULL
+};
-int main(int argc, char **argv)
+static const char *type;
+static int write_object;
+static int hashstdin;
+static int stdin_paths;
+static int no_filters;
+static const char *vpath;
+
+static const struct option hash_object_options[] = {
+ OPT_STRING('t', NULL, &type, "type", "object type"),
+ OPT_BOOLEAN('w', NULL, &write_object, "write the object into the object database"),
+ OPT_BOOLEAN( 0 , "stdin", &hashstdin, "read the object from stdin"),
+ OPT_BOOLEAN( 0 , "stdin-paths", &stdin_paths, "read file names from stdin"),
+ OPT_BOOLEAN( 0 , "no-filters", &no_filters, "store file as is without filters"),
+ OPT_STRING( 0 , "path", &vpath, "file", "process file as it were from this path"),
+ OPT_END()
+};
+
+int main(int argc, const char **argv)
{
int i;
- const char *type = blob_type;
- int write_object = 0;
const char *prefix = NULL;
int prefix_length = -1;
- int no_more_flags = 0;
- int hashstdin = 0;
- int stdin_paths = 0;
+ const char *errstr = NULL;
+
+ type = blob_type;
git_config(git_default_config, NULL);
- for (i = 1 ; i < argc; i++) {
- if (!no_more_flags && argv[i][0] == '-') {
- if (!strcmp(argv[i], "-t")) {
- if (argc <= ++i)
- usage(hash_object_usage);
- type = argv[i];
- }
- else if (!strcmp(argv[i], "-w")) {
- if (prefix_length < 0) {
- prefix = setup_git_directory();
- prefix_length =
- prefix ? strlen(prefix) : 0;
- }
- write_object = 1;
- }
- else if (!strcmp(argv[i], "--")) {
- no_more_flags = 1;
- }
- else if (!strcmp(argv[i], "--help"))
- usage(hash_object_usage);
- else if (!strcmp(argv[i], "--stdin-paths")) {
- if (hashstdin) {
- error("Can't use --stdin-paths with --stdin");
- usage(hash_object_usage);
- }
- stdin_paths = 1;
-
- }
- else if (!strcmp(argv[i], "--stdin")) {
- if (stdin_paths) {
- error("Can't use %s with --stdin-paths", argv[i]);
- usage(hash_object_usage);
- }
- if (hashstdin)
- die("Multiple --stdin arguments are not supported");
- hashstdin = 1;
- }
- else
- usage(hash_object_usage);
- }
- else {
- const char *arg = argv[i];
-
- if (stdin_paths) {
- error("Can't specify files (such as \"%s\") with --stdin-paths", arg);
- usage(hash_object_usage);
- }
-
- if (hashstdin) {
- hash_stdin(type, write_object);
- hashstdin = 0;
- }
- if (0 <= prefix_length)
- arg = prefix_filename(prefix, prefix_length,
- arg);
- hash_object(arg, type_from_string(type), write_object);
- no_more_flags = 1;
- }
+ argc = parse_options(argc, argv, hash_object_options, hash_object_usage, 0);
+
+ if (write_object) {
+ prefix = setup_git_directory();
+ prefix_length = prefix ? strlen(prefix) : 0;
+ if (vpath && prefix)
+ vpath = prefix_filename(prefix, prefix_length, vpath);
+ }
+
+ if (stdin_paths) {
+ if (hashstdin)
+ errstr = "Can't use --stdin-paths with --stdin";
+ else if (argc)
+ errstr = "Can't specify files with --stdin-paths";
+ else if (vpath)
+ errstr = "Can't use --stdin-paths with --path";
+ else if (no_filters)
+ errstr = "Can't use --stdin-paths with --no-filters";
+ }
+ else {
+ if (hashstdin > 1)
+ errstr = "Multiple --stdin arguments are not supported";
+ if (vpath && no_filters)
+ errstr = "Can't use --path with --no-filters";
+ }
+
+ if (errstr) {
+ error (errstr);
+ usage_with_options(hash_object_usage, hash_object_options);
+ }
+
+ if (hashstdin)
+ hash_fd(0, type, write_object, vpath);
+
+ for (i = 0 ; i < argc; i++) {
+ const char *arg = argv[i];
+
+ if (0 <= prefix_length)
+ arg = prefix_filename(prefix, prefix_length, arg);
+ hash_object(arg, type, write_object,
+ no_filters ? NULL : vpath ? vpath : arg);
}
if (stdin_paths)
hash_stdin_paths(type, write_object);
- if (hashstdin)
- hash_stdin(type, write_object);
return 0;
}
diff --git a/help.c b/help.c
index 3cb1962896..dc0786d800 100644
--- a/help.c
+++ b/help.c
@@ -555,7 +555,8 @@ static int is_git_command(const char *s)
{
load_command_list();
return is_in_cmdlist(&main_cmds, s) ||
- is_in_cmdlist(&other_cmds, s);
+ is_in_cmdlist(&other_cmds, s) ||
+ !strcmp(s, "help");
}
static const char *prepend(const char *prefix, const char *cmd)
diff --git a/imap-send.c b/imap-send.c
index 1ec1310921..af7e08c094 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -23,71 +23,74 @@
*/
#include "cache.h"
+#ifdef NO_OPENSSL
+typedef void *SSL;
+#endif
-typedef struct store_conf {
+struct store_conf {
char *name;
const char *path; /* should this be here? its interpretation is driver-specific */
char *map_inbox;
char *trash;
unsigned max_size; /* off_t is overkill */
unsigned trash_remote_new:1, trash_only_new:1;
-} store_conf_t;
+};
-typedef struct string_list {
+struct string_list {
struct string_list *next;
char string[1];
-} string_list_t;
+};
-typedef struct channel_conf {
+struct channel_conf {
struct channel_conf *next;
char *name;
- store_conf_t *master, *slave;
+ struct store_conf *master, *slave;
char *master_name, *slave_name;
char *sync_state;
- string_list_t *patterns;
+ struct string_list *patterns;
int mops, sops;
unsigned max_messages; /* for slave only */
-} channel_conf_t;
+};
-typedef struct group_conf {
+struct group_conf {
struct group_conf *next;
char *name;
- string_list_t *channels;
-} group_conf_t;
+ struct string_list *channels;
+};
/* For message->status */
#define M_RECENT (1<<0) /* unsyncable flag; maildir_* depend on this being 1<<0 */
#define M_DEAD (1<<1) /* expunged */
#define M_FLAGS (1<<2) /* flags fetched */
-typedef struct message {
+struct message {
struct message *next;
- /* string_list_t *keywords; */
+ /* struct string_list *keywords; */
size_t size; /* zero implies "not fetched" */
int uid;
unsigned char flags, status;
-} message_t;
+};
-typedef struct store {
- store_conf_t *conf; /* foreign */
+struct store {
+ struct store_conf *conf; /* foreign */
/* currently open mailbox */
const char *name; /* foreign! maybe preset? */
char *path; /* own */
- message_t *msgs; /* own */
+ struct message *msgs; /* own */
int uidvalidity;
unsigned char opts; /* maybe preset? */
/* note that the following do _not_ reflect stats from msgs, but mailbox totals */
int count; /* # of messages */
int recent; /* # of recent messages - don't trust this beyond the initial read */
-} store_t;
+};
-typedef struct {
+struct msg_data {
char *data;
int len;
unsigned char flags;
unsigned int crlf:1;
-} msg_data_t;
+};
#define DRV_OK 0
#define DRV_MSG_BAD -1
@@ -96,14 +99,14 @@ typedef struct {
static int Verbose, Quiet;
-static void imap_info( const char *, ... );
-static void imap_warn( const char *, ... );
+static void imap_info(const char *, ...);
+static void imap_warn(const char *, ...);
-static char *next_arg( char ** );
+static char *next_arg(char **);
-static void free_generic_messages( message_t * );
+static void free_generic_messages(struct message *);
-static int nfsnprintf( char *buf, int blen, const char *fmt, ... );
+static int nfsnprintf(char *buf, int blen, const char *fmt, ...);
static int nfvasprintf(char **strp, const char *fmt, va_list ap)
{
@@ -119,67 +122,70 @@ static int nfvasprintf(char **strp, const char *fmt, va_list ap)
return len;
}
-static void arc4_init( void );
-static unsigned char arc4_getbyte( void );
+static void arc4_init(void);
+static unsigned char arc4_getbyte(void);
-typedef struct imap_server_conf {
+struct imap_server_conf {
char *name;
char *tunnel;
char *host;
int port;
char *user;
char *pass;
-} imap_server_conf_t;
+ int use_ssl;
+ int ssl_verify;
+};
-typedef struct imap_store_conf {
- store_conf_t gen;
- imap_server_conf_t *server;
+struct imap_store_conf {
+ struct store_conf gen;
+ struct imap_server_conf *server;
unsigned use_namespace:1;
-} imap_store_conf_t;
+};
-#define NIL (void*)0x1
-#define LIST (void*)0x2
+#define NIL (void *)0x1
+#define LIST (void *)0x2
-typedef struct _list {
- struct _list *next, *child;
+struct imap_list {
+ struct imap_list *next, *child;
char *val;
int len;
-} list_t;
+};
-typedef struct {
+struct imap_socket {
int fd;
-} Socket_t;
+ SSL *ssl;
+};
-typedef struct {
- Socket_t sock;
+struct imap_buffer {
+ struct imap_socket sock;
int bytes;
int offset;
char buf[1024];
-} buffer_t;
+};
struct imap_cmd;
-typedef struct imap {
+struct imap {
int uidnext; /* from SELECT responses */
- list_t *ns_personal, *ns_other, *ns_shared; /* NAMESPACE info */
+ struct imap_list *ns_personal, *ns_other, *ns_shared; /* NAMESPACE info */
unsigned caps, rcaps; /* CAPABILITY results */
/* command queue */
int nexttag, num_in_progress, literal_pending;
struct imap_cmd *in_progress, **in_progress_append;
- buffer_t buf; /* this is BIG, so put it last */
-} imap_t;
+ struct imap_buffer buf; /* this is BIG, so put it last */
+};
-typedef struct imap_store {
- store_t gen;
+struct imap_store {
+ struct store gen;
int uidvalidity;
- imap_t *imap;
+ struct imap *imap;
const char *prefix;
unsigned /*currentnc:1,*/ trashnc:1;
-} imap_store_t;
+};
struct imap_cmd_cb {
- int (*cont)( imap_store_t *ctx, struct imap_cmd *cmd, const char *prompt );
- void (*done)( imap_store_t *ctx, struct imap_cmd *cmd, int response);
+ int (*cont)(struct imap_store *ctx, struct imap_cmd *cmd, const char *prompt);
+ void (*done)(struct imap_store *ctx, struct imap_cmd *cmd, int response);
void *ctx;
char *data;
int dlen;
@@ -201,6 +207,7 @@ enum CAPABILITY {
UIDPLUS,
LITERALPLUS,
NAMESPACE,
+ STARTTLS,
};
static const char *cap_list[] = {
@@ -208,13 +215,14 @@ static const char *cap_list[] = {
"UIDPLUS",
"LITERAL+",
"NAMESPACE",
+ "STARTTLS",
};
#define RESP_OK 0
#define RESP_NO 1
#define RESP_BAD 2
-static int get_cmd_result( imap_store_t *ctx, struct imap_cmd *tcmd );
+static int get_cmd_result(struct imap_store *ctx, struct imap_cmd *tcmd);
static const char *Flags[] = {
@@ -225,42 +233,137 @@ static const char *Flags[] = {
"Deleted",
};
-static void
-socket_perror( const char *func, Socket_t *sock, int ret )
+#ifndef NO_OPENSSL
+static void ssl_socket_perror(const char *func)
+{
+ fprintf(stderr, "%s: %s\n", func, ERR_error_string(ERR_get_error(), 0));
+}
+#endif
+
+static void socket_perror(const char *func, struct imap_socket *sock, int ret)
+{
+#ifndef NO_OPENSSL
+ if (sock->ssl) {
+ int sslerr = SSL_get_error(sock->ssl, ret);
+ switch (sslerr) {
+ case SSL_ERROR_NONE:
+ break;
+ case SSL_ERROR_SYSCALL:
+ perror("SSL_connect");
+ break;
+ default:
+ ssl_socket_perror("SSL_connect");
+ break;
+ }
+ } else
+#endif
+ {
+ if (ret < 0)
+ perror(func);
+ else
+ fprintf(stderr, "%s: unexpected EOF\n", func);
+ }
+}
+
+static int ssl_socket_connect(struct imap_socket *sock, int use_tls_only, int verify)
{
- if (ret < 0)
- perror( func );
+#ifdef NO_OPENSSL
+ fprintf(stderr, "SSL requested but SSL support not compiled in\n");
+ return -1;
+#else
+ SSL_METHOD *meth;
+ SSL_CTX *ctx;
+ int ret;
+
+ SSL_library_init();
+ SSL_load_error_strings();
+
+ if (use_tls_only)
+ meth = TLSv1_method();
else
- fprintf( stderr, "%s: unexpected EOF\n", func );
+ meth = SSLv23_method();
+
+ if (!meth) {
+ ssl_socket_perror("SSLv23_method");
+ return -1;
+ }
+
+ ctx = SSL_CTX_new(meth);
+
+ if (verify)
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
+
+ if (!SSL_CTX_set_default_verify_paths(ctx)) {
+ ssl_socket_perror("SSL_CTX_set_default_verify_paths");
+ return -1;
+ }
+ sock->ssl = SSL_new(ctx);
+ if (!sock->ssl) {
+ ssl_socket_perror("SSL_new");
+ return -1;
+ }
+ if (!SSL_set_fd(sock->ssl, sock->fd)) {
+ ssl_socket_perror("SSL_set_fd");
+ return -1;
+ }
+
+ ret = SSL_connect(sock->ssl);
+ if (ret <= 0) {
+ socket_perror("SSL_connect", sock, ret);
+ return -1;
+ }
+
+ return 0;
+#endif
}
-static int
-socket_read( Socket_t *sock, char *buf, int len )
+static int socket_read(struct imap_socket *sock, char *buf, int len)
{
- ssize_t n = xread( sock->fd, buf, len );
+ ssize_t n;
+#ifndef NO_OPENSSL
+ if (sock->ssl)
+ n = SSL_read(sock->ssl, buf, len);
+ else
+#endif
+ n = xread(sock->fd, buf, len);
if (n <= 0) {
- socket_perror( "read", sock, n );
- close( sock->fd );
+ socket_perror("read", sock, n);
+ close(sock->fd);
sock->fd = -1;
}
return n;
}
-static int
-socket_write( Socket_t *sock, const char *buf, int len )
+static int socket_write(struct imap_socket *sock, const char *buf, int len)
{
- int n = write_in_full( sock->fd, buf, len );
+ int n;
+#ifndef NO_OPENSSL
+ if (sock->ssl)
+ n = SSL_write(sock->ssl, buf, len);
+ else
+#endif
+ n = write_in_full(sock->fd, buf, len);
if (n != len) {
- socket_perror( "write", sock, n );
- close( sock->fd );
+ socket_perror("write", sock, n);
+ close(sock->fd);
sock->fd = -1;
}
return n;
}
+static void socket_shutdown(struct imap_socket *sock)
+{
+#ifndef NO_OPENSSL
+ if (sock->ssl) {
+ SSL_shutdown(sock->ssl);
+ SSL_free(sock->ssl);
+ }
+#endif
+ close(sock->fd);
+}
+
/* simple line buffering */
-static int
-buffer_gets( buffer_t * b, char **s )
+static int buffer_gets(struct imap_buffer *b, char **s)
{
int n;
int start = b->offset;
@@ -274,7 +377,7 @@ buffer_gets( buffer_t * b, char **s )
/* shift down used bytes */
*s = b->buf;
- assert( start <= b->bytes );
+ assert(start <= b->bytes);
n = b->bytes - start;
if (n)
@@ -284,8 +387,8 @@ buffer_gets( buffer_t * b, char **s )
start = 0;
}
- n = socket_read( &b->sock, b->buf + b->bytes,
- sizeof(b->buf) - b->bytes );
+ n = socket_read(&b->sock, b->buf + b->bytes,
+ sizeof(b->buf) - b->bytes);
if (n <= 0)
return -1;
@@ -294,12 +397,12 @@ buffer_gets( buffer_t * b, char **s )
}
if (b->buf[b->offset] == '\r') {
- assert( b->offset + 1 < b->bytes );
+ assert(b->offset + 1 < b->bytes);
if (b->buf[b->offset + 1] == '\n') {
b->buf[b->offset] = 0; /* terminate the string */
b->offset += 2; /* next line */
if (Verbose)
- puts( *s );
+ puts(*s);
return 0;
}
}
@@ -309,39 +412,36 @@ buffer_gets( buffer_t * b, char **s )
/* not reached */
}
-static void
-imap_info( const char *msg, ... )
+static void imap_info(const char *msg, ...)
{
va_list va;
if (!Quiet) {
- va_start( va, msg );
- vprintf( msg, va );
- va_end( va );
- fflush( stdout );
+ va_start(va, msg);
+ vprintf(msg, va);
+ va_end(va);
+ fflush(stdout);
}
}
-static void
-imap_warn( const char *msg, ... )
+static void imap_warn(const char *msg, ...)
{
va_list va;
if (Quiet < 2) {
- va_start( va, msg );
- vfprintf( stderr, msg, va );
- va_end( va );
+ va_start(va, msg);
+ vfprintf(stderr, msg, va);
+ va_end(va);
}
}
-static char *
-next_arg( char **s )
+static char *next_arg(char **s)
{
char *ret;
if (!s || !*s)
return NULL;
- while (isspace( (unsigned char) **s ))
+ while (isspace((unsigned char) **s))
(*s)++;
if (!**s) {
*s = NULL;
@@ -350,10 +450,10 @@ next_arg( char **s )
if (**s == '"') {
++*s;
ret = *s;
- *s = strchr( *s, '"' );
+ *s = strchr(*s, '"');
} else {
ret = *s;
- while (**s && !isspace( (unsigned char) **s ))
+ while (**s && !isspace((unsigned char) **s))
(*s)++;
}
if (*s) {
@@ -365,27 +465,25 @@ next_arg( char **s )
return ret;
}
-static void
-free_generic_messages( message_t *msgs )
+static void free_generic_messages(struct message *msgs)
{
- message_t *tmsg;
+ struct message *tmsg;
for (; msgs; msgs = tmsg) {
tmsg = msgs->next;
- free( msgs );
+ free(msgs);
}
}
-static int
-nfsnprintf( char *buf, int blen, const char *fmt, ... )
+static int nfsnprintf(char *buf, int blen, const char *fmt, ...)
{
int ret;
va_list va;
- va_start( va, fmt );
- if (blen <= 0 || (unsigned)(ret = vsnprintf( buf, blen, fmt, va )) >= (unsigned)blen)
- die( "Fatal: buffer too small. Please report a bug.\n");
- va_end( va );
+ va_start(va, fmt);
+ if (blen <= 0 || (unsigned)(ret = vsnprintf(buf, blen, fmt, va)) >= (unsigned)blen)
+ die("Fatal: buffer too small. Please report a bug.\n");
+ va_end(va);
return ret;
}
@@ -393,21 +491,20 @@ static struct {
unsigned char i, j, s[256];
} rs;
-static void
-arc4_init( void )
+static void arc4_init(void)
{
int i, fd;
unsigned char j, si, dat[128];
- if ((fd = open( "/dev/urandom", O_RDONLY )) < 0 && (fd = open( "/dev/random", O_RDONLY )) < 0) {
- fprintf( stderr, "Fatal: no random number source available.\n" );
- exit( 3 );
+ if ((fd = open("/dev/urandom", O_RDONLY)) < 0 && (fd = open("/dev/random", O_RDONLY)) < 0) {
+ fprintf(stderr, "Fatal: no random number source available.\n");
+ exit(3);
}
- if (read_in_full( fd, dat, 128 ) != 128) {
- fprintf( stderr, "Fatal: cannot read random number source.\n" );
- exit( 3 );
+ if (read_in_full(fd, dat, 128) != 128) {
+ fprintf(stderr, "Fatal: cannot read random number source.\n");
+ exit(3);
}
- close( fd );
+ close(fd);
for (i = 0; i < 256; i++)
rs.s[i] = i;
@@ -423,8 +520,7 @@ arc4_init( void )
arc4_getbyte();
}
-static unsigned char
-arc4_getbyte( void )
+static unsigned char arc4_getbyte(void)
{
unsigned char si, sj;
@@ -437,54 +533,53 @@ arc4_getbyte( void )
return rs.s[(si + sj) & 0xff];
}
-static struct imap_cmd *
-v_issue_imap_cmd( imap_store_t *ctx, struct imap_cmd_cb *cb,
- const char *fmt, va_list ap )
+static struct imap_cmd *v_issue_imap_cmd(struct imap_store *ctx,
+ struct imap_cmd_cb *cb,
+ const char *fmt, va_list ap)
{
- imap_t *imap = ctx->imap;
+ struct imap *imap = ctx->imap;
struct imap_cmd *cmd;
int n, bufl;
char buf[1024];
- cmd = xmalloc( sizeof(struct imap_cmd) );
- nfvasprintf( &cmd->cmd, fmt, ap );
+ cmd = xmalloc(sizeof(struct imap_cmd));
+ nfvasprintf(&cmd->cmd, fmt, ap);
cmd->tag = ++imap->nexttag;
if (cb)
cmd->cb = *cb;
else
- memset( &cmd->cb, 0, sizeof(cmd->cb) );
+ memset(&cmd->cb, 0, sizeof(cmd->cb));
while (imap->literal_pending)
- get_cmd_result( ctx, NULL );
+ get_cmd_result(ctx, NULL);
- bufl = nfsnprintf( buf, sizeof(buf), cmd->cb.data ? CAP(LITERALPLUS) ?
+ bufl = nfsnprintf(buf, sizeof(buf), cmd->cb.data ? CAP(LITERALPLUS) ?
"%d %s{%d+}\r\n" : "%d %s{%d}\r\n" : "%d %s\r\n",
- cmd->tag, cmd->cmd, cmd->cb.dlen );
+ cmd->tag, cmd->cmd, cmd->cb.dlen);
if (Verbose) {
if (imap->num_in_progress)
- printf( "(%d in progress) ", imap->num_in_progress );
- if (memcmp( cmd->cmd, "LOGIN", 5 ))
- printf( ">>> %s", buf );
+ printf("(%d in progress) ", imap->num_in_progress);
+ if (memcmp(cmd->cmd, "LOGIN", 5))
+ printf(">>> %s", buf);
else
- printf( ">>> %d LOGIN <user> <pass>\n", cmd->tag );
+ printf(">>> %d LOGIN <user> <pass>\n", cmd->tag);
}
- if (socket_write( &imap->buf.sock, buf, bufl ) != bufl) {
- free( cmd->cmd );
- free( cmd );
+ if (socket_write(&imap->buf.sock, buf, bufl) != bufl) {
+ free(cmd->cmd);
+ free(cmd);
if (cb)
- free( cb->data );
+ free(cb->data);
return NULL;
}
if (cmd->cb.data) {
if (CAP(LITERALPLUS)) {
- n = socket_write( &imap->buf.sock, cmd->cb.data, cmd->cb.dlen );
- free( cmd->cb.data );
+ n = socket_write(&imap->buf.sock, cmd->cb.data, cmd->cb.dlen);
+ free(cmd->cb.data);
if (n != cmd->cb.dlen ||
- (n = socket_write( &imap->buf.sock, "\r\n", 2 )) != 2)
- {
- free( cmd->cmd );
- free( cmd );
+ (n = socket_write(&imap->buf.sock, "\r\n", 2)) != 2) {
+ free(cmd->cmd);
+ free(cmd);
return NULL;
}
cmd->cb.data = NULL;
@@ -499,109 +594,106 @@ v_issue_imap_cmd( imap_store_t *ctx, struct imap_cmd_cb *cb,
return cmd;
}
-static struct imap_cmd *
-issue_imap_cmd( imap_store_t *ctx, struct imap_cmd_cb *cb, const char *fmt, ... )
+static struct imap_cmd *issue_imap_cmd(struct imap_store *ctx,
+ struct imap_cmd_cb *cb,
+ const char *fmt, ...)
{
struct imap_cmd *ret;
va_list ap;
- va_start( ap, fmt );
- ret = v_issue_imap_cmd( ctx, cb, fmt, ap );
- va_end( ap );
+ va_start(ap, fmt);
+ ret = v_issue_imap_cmd(ctx, cb, fmt, ap);
+ va_end(ap);
return ret;
}
-static int
-imap_exec( imap_store_t *ctx, struct imap_cmd_cb *cb, const char *fmt, ... )
+static int imap_exec(struct imap_store *ctx, struct imap_cmd_cb *cb,
+ const char *fmt, ...)
{
va_list ap;
struct imap_cmd *cmdp;
- va_start( ap, fmt );
- cmdp = v_issue_imap_cmd( ctx, cb, fmt, ap );
- va_end( ap );
+ va_start(ap, fmt);
+ cmdp = v_issue_imap_cmd(ctx, cb, fmt, ap);
+ va_end(ap);
if (!cmdp)
return RESP_BAD;
- return get_cmd_result( ctx, cmdp );
+ return get_cmd_result(ctx, cmdp);
}
-static int
-imap_exec_m( imap_store_t *ctx, struct imap_cmd_cb *cb, const char *fmt, ... )
+static int imap_exec_m(struct imap_store *ctx, struct imap_cmd_cb *cb,
+ const char *fmt, ...)
{
va_list ap;
struct imap_cmd *cmdp;
- va_start( ap, fmt );
- cmdp = v_issue_imap_cmd( ctx, cb, fmt, ap );
- va_end( ap );
+ va_start(ap, fmt);
+ cmdp = v_issue_imap_cmd(ctx, cb, fmt, ap);
+ va_end(ap);
if (!cmdp)
return DRV_STORE_BAD;
- switch (get_cmd_result( ctx, cmdp )) {
+ switch (get_cmd_result(ctx, cmdp)) {
case RESP_BAD: return DRV_STORE_BAD;
case RESP_NO: return DRV_MSG_BAD;
default: return DRV_OK;
}
}
-static int
-is_atom( list_t *list )
+static int is_atom(struct imap_list *list)
{
return list && list->val && list->val != NIL && list->val != LIST;
}
-static int
-is_list( list_t *list )
+static int is_list(struct imap_list *list)
{
return list && list->val == LIST;
}
-static void
-free_list( list_t *list )
+static void free_list(struct imap_list *list)
{
- list_t *tmp;
+ struct imap_list *tmp;
for (; list; list = tmp) {
tmp = list->next;
- if (is_list( list ))
- free_list( list->child );
- else if (is_atom( list ))
- free( list->val );
- free( list );
+ if (is_list(list))
+ free_list(list->child);
+ else if (is_atom(list))
+ free(list->val);
+ free(list);
}
}
-static int
-parse_imap_list_l( imap_t *imap, char **sp, list_t **curp, int level )
+static int parse_imap_list_l(struct imap *imap, char **sp, struct imap_list **curp, int level)
{
- list_t *cur;
+ struct imap_list *cur;
char *s = *sp, *p;
int n, bytes;
for (;;) {
- while (isspace( (unsigned char)*s ))
+ while (isspace((unsigned char)*s))
s++;
if (level && *s == ')') {
s++;
break;
}
- *curp = cur = xmalloc( sizeof(*cur) );
+ *curp = cur = xmalloc(sizeof(*cur));
curp = &cur->next;
cur->val = NULL; /* for clean bail */
if (*s == '(') {
/* sublist */
s++;
cur->val = LIST;
- if (parse_imap_list_l( imap, &s, &cur->child, level + 1 ))
+ if (parse_imap_list_l(imap, &s, &cur->child, level + 1))
goto bail;
} else if (imap && *s == '{') {
/* literal */
- bytes = cur->len = strtol( s + 1, &s, 10 );
+ bytes = cur->len = strtol(s + 1, &s, 10);
if (*s != '}')
goto bail;
- s = cur->val = xmalloc( cur->len );
+ s = cur->val = xmalloc(cur->len);
/* dump whats left over in the input buffer */
n = imap->buf.bytes - imap->buf.offset;
@@ -610,7 +702,7 @@ parse_imap_list_l( imap_t *imap, char **sp, list_t **curp, int level )
/* the entire message fit in the buffer */
n = bytes;
- memcpy( s, imap->buf.buf + imap->buf.offset, n );
+ memcpy(s, imap->buf.buf + imap->buf.offset, n);
s += n;
bytes -= n;
@@ -619,13 +711,13 @@ parse_imap_list_l( imap_t *imap, char **sp, list_t **curp, int level )
/* now read the rest of the message */
while (bytes > 0) {
- if ((n = socket_read (&imap->buf.sock, s, bytes)) <= 0)
+ if ((n = socket_read(&imap->buf.sock, s, bytes)) <= 0)
goto bail;
s += n;
bytes -= n;
}
- if (buffer_gets( &imap->buf, &s ))
+ if (buffer_gets(&imap->buf, &s))
goto bail;
} else if (*s == '"') {
/* quoted string */
@@ -640,15 +732,14 @@ parse_imap_list_l( imap_t *imap, char **sp, list_t **curp, int level )
} else {
/* atom */
p = s;
- for (; *s && !isspace( (unsigned char)*s ); s++)
+ for (; *s && !isspace((unsigned char)*s); s++)
if (level && *s == ')')
break;
cur->len = s - p;
- if (cur->len == 3 && !memcmp ("NIL", p, 3)) {
+ if (cur->len == 3 && !memcmp("NIL", p, 3))
cur->val = NIL;
- } else {
+ else
cur->val = xmemdupz(p, cur->len);
- }
}
if (!level)
@@ -660,127 +751,122 @@ parse_imap_list_l( imap_t *imap, char **sp, list_t **curp, int level )
*curp = NULL;
return 0;
- bail:
+bail:
*curp = NULL;
return -1;
}
-static list_t *
-parse_imap_list( imap_t *imap, char **sp )
+static struct imap_list *parse_imap_list(struct imap *imap, char **sp)
{
- list_t *head;
+ struct imap_list *head;
- if (!parse_imap_list_l( imap, sp, &head, 0 ))
+ if (!parse_imap_list_l(imap, sp, &head, 0))
return head;
- free_list( head );
+ free_list(head);
return NULL;
}
-static list_t *
-parse_list( char **sp )
+static struct imap_list *parse_list(char **sp)
{
- return parse_imap_list( NULL, sp );
+ return parse_imap_list(NULL, sp);
}
-static void
-parse_capability( imap_t *imap, char *cmd )
+static void parse_capability(struct imap *imap, char *cmd)
{
char *arg;
unsigned i;
imap->caps = 0x80000000;
- while ((arg = next_arg( &cmd )))
+ while ((arg = next_arg(&cmd)))
for (i = 0; i < ARRAY_SIZE(cap_list); i++)
- if (!strcmp( cap_list[i], arg ))
+ if (!strcmp(cap_list[i], arg))
imap->caps |= 1 << i;
imap->rcaps = imap->caps;
}
-static int
-parse_response_code( imap_store_t *ctx, struct imap_cmd_cb *cb, char *s )
+static int parse_response_code(struct imap_store *ctx, struct imap_cmd_cb *cb,
+ char *s)
{
- imap_t *imap = ctx->imap;
+ struct imap *imap = ctx->imap;
char *arg, *p;
if (*s != '[')
return RESP_OK; /* no response code */
s++;
- if (!(p = strchr( s, ']' ))) {
- fprintf( stderr, "IMAP error: malformed response code\n" );
+ if (!(p = strchr(s, ']'))) {
+ fprintf(stderr, "IMAP error: malformed response code\n");
return RESP_BAD;
}
*p++ = 0;
- arg = next_arg( &s );
- if (!strcmp( "UIDVALIDITY", arg )) {
- if (!(arg = next_arg( &s )) || !(ctx->gen.uidvalidity = atoi( arg ))) {
- fprintf( stderr, "IMAP error: malformed UIDVALIDITY status\n" );
+ arg = next_arg(&s);
+ if (!strcmp("UIDVALIDITY", arg)) {
+ if (!(arg = next_arg(&s)) || !(ctx->gen.uidvalidity = atoi(arg))) {
+ fprintf(stderr, "IMAP error: malformed UIDVALIDITY status\n");
return RESP_BAD;
}
- } else if (!strcmp( "UIDNEXT", arg )) {
- if (!(arg = next_arg( &s )) || !(imap->uidnext = atoi( arg ))) {
- fprintf( stderr, "IMAP error: malformed NEXTUID status\n" );
+ } else if (!strcmp("UIDNEXT", arg)) {
+ if (!(arg = next_arg(&s)) || !(imap->uidnext = atoi(arg))) {
+ fprintf(stderr, "IMAP error: malformed NEXTUID status\n");
return RESP_BAD;
}
- } else if (!strcmp( "CAPABILITY", arg )) {
- parse_capability( imap, s );
- } else if (!strcmp( "ALERT", arg )) {
+ } else if (!strcmp("CAPABILITY", arg)) {
+ parse_capability(imap, s);
+ } else if (!strcmp("ALERT", arg)) {
/* RFC2060 says that these messages MUST be displayed
* to the user
*/
- for (; isspace( (unsigned char)*p ); p++);
- fprintf( stderr, "*** IMAP ALERT *** %s\n", p );
- } else if (cb && cb->ctx && !strcmp( "APPENDUID", arg )) {
- if (!(arg = next_arg( &s )) || !(ctx->gen.uidvalidity = atoi( arg )) ||
- !(arg = next_arg( &s )) || !(*(int *)cb->ctx = atoi( arg )))
- {
- fprintf( stderr, "IMAP error: malformed APPENDUID status\n" );
+ for (; isspace((unsigned char)*p); p++);
+ fprintf(stderr, "*** IMAP ALERT *** %s\n", p);
+ } else if (cb && cb->ctx && !strcmp("APPENDUID", arg)) {
+ if (!(arg = next_arg(&s)) || !(ctx->gen.uidvalidity = atoi(arg)) ||
+ !(arg = next_arg(&s)) || !(*(int *)cb->ctx = atoi(arg))) {
+ fprintf(stderr, "IMAP error: malformed APPENDUID status\n");
return RESP_BAD;
}
}
return RESP_OK;
}
-static int
-get_cmd_result( imap_store_t *ctx, struct imap_cmd *tcmd )
+static int get_cmd_result(struct imap_store *ctx, struct imap_cmd *tcmd)
{
- imap_t *imap = ctx->imap;
+ struct imap *imap = ctx->imap;
struct imap_cmd *cmdp, **pcmdp, *ncmdp;
char *cmd, *arg, *arg1, *p;
int n, resp, resp2, tag;
for (;;) {
- if (buffer_gets( &imap->buf, &cmd ))
+ if (buffer_gets(&imap->buf, &cmd))
return RESP_BAD;
- arg = next_arg( &cmd );
+ arg = next_arg(&cmd);
if (*arg == '*') {
- arg = next_arg( &cmd );
+ arg = next_arg(&cmd);
if (!arg) {
- fprintf( stderr, "IMAP error: unable to parse untagged response\n" );
+ fprintf(stderr, "IMAP error: unable to parse untagged response\n");
return RESP_BAD;
}
- if (!strcmp( "NAMESPACE", arg )) {
- imap->ns_personal = parse_list( &cmd );
- imap->ns_other = parse_list( &cmd );
- imap->ns_shared = parse_list( &cmd );
- } else if (!strcmp( "OK", arg ) || !strcmp( "BAD", arg ) ||
- !strcmp( "NO", arg ) || !strcmp( "BYE", arg )) {
- if ((resp = parse_response_code( ctx, NULL, cmd )) != RESP_OK)
+ if (!strcmp("NAMESPACE", arg)) {
+ imap->ns_personal = parse_list(&cmd);
+ imap->ns_other = parse_list(&cmd);
+ imap->ns_shared = parse_list(&cmd);
+ } else if (!strcmp("OK", arg) || !strcmp("BAD", arg) ||
+ !strcmp("NO", arg) || !strcmp("BYE", arg)) {
+ if ((resp = parse_response_code(ctx, NULL, cmd)) != RESP_OK)
return resp;
- } else if (!strcmp( "CAPABILITY", arg ))
- parse_capability( imap, cmd );
- else if ((arg1 = next_arg( &cmd ))) {
- if (!strcmp( "EXISTS", arg1 ))
- ctx->gen.count = atoi( arg );
- else if (!strcmp( "RECENT", arg1 ))
- ctx->gen.recent = atoi( arg );
+ } else if (!strcmp("CAPABILITY", arg))
+ parse_capability(imap, cmd);
+ else if ((arg1 = next_arg(&cmd))) {
+ if (!strcmp("EXISTS", arg1))
+ ctx->gen.count = atoi(arg);
+ else if (!strcmp("RECENT", arg1))
+ ctx->gen.recent = atoi(arg);
} else {
- fprintf( stderr, "IMAP error: unable to parse untagged response\n" );
+ fprintf(stderr, "IMAP error: unable to parse untagged response\n");
return RESP_BAD;
}
} else if (!imap->in_progress) {
- fprintf( stderr, "IMAP error: unexpected reply: %s %s\n", arg, cmd ? cmd : "" );
+ fprintf(stderr, "IMAP error: unexpected reply: %s %s\n", arg, cmd ? cmd : "");
return RESP_BAD;
} else if (*arg == '+') {
/* This can happen only with the last command underway, as
@@ -788,57 +874,57 @@ get_cmd_result( imap_store_t *ctx, struct imap_cmd *tcmd )
cmdp = (struct imap_cmd *)((char *)imap->in_progress_append -
offsetof(struct imap_cmd, next));
if (cmdp->cb.data) {
- n = socket_write( &imap->buf.sock, cmdp->cb.data, cmdp->cb.dlen );
- free( cmdp->cb.data );
+ n = socket_write(&imap->buf.sock, cmdp->cb.data, cmdp->cb.dlen);
+ free(cmdp->cb.data);
cmdp->cb.data = NULL;
if (n != (int)cmdp->cb.dlen)
return RESP_BAD;
} else if (cmdp->cb.cont) {
- if (cmdp->cb.cont( ctx, cmdp, cmd ))
+ if (cmdp->cb.cont(ctx, cmdp, cmd))
return RESP_BAD;
} else {
- fprintf( stderr, "IMAP error: unexpected command continuation request\n" );
+ fprintf(stderr, "IMAP error: unexpected command continuation request\n");
return RESP_BAD;
}
- if (socket_write( &imap->buf.sock, "\r\n", 2 ) != 2)
+ if (socket_write(&imap->buf.sock, "\r\n", 2) != 2)
return RESP_BAD;
if (!cmdp->cb.cont)
imap->literal_pending = 0;
if (!tcmd)
return DRV_OK;
} else {
- tag = atoi( arg );
+ tag = atoi(arg);
for (pcmdp = &imap->in_progress; (cmdp = *pcmdp); pcmdp = &cmdp->next)
if (cmdp->tag == tag)
goto gottag;
- fprintf( stderr, "IMAP error: unexpected tag %s\n", arg );
+ fprintf(stderr, "IMAP error: unexpected tag %s\n", arg);
return RESP_BAD;
- gottag:
+ gottag:
if (!(*pcmdp = cmdp->next))
imap->in_progress_append = pcmdp;
imap->num_in_progress--;
if (cmdp->cb.cont || cmdp->cb.data)
imap->literal_pending = 0;
- arg = next_arg( &cmd );
- if (!strcmp( "OK", arg ))
+ arg = next_arg(&cmd);
+ if (!strcmp("OK", arg))
resp = DRV_OK;
else {
- if (!strcmp( "NO", arg )) {
- if (cmdp->cb.create && cmd && (cmdp->cb.trycreate || !memcmp( cmd, "[TRYCREATE]", 11 ))) { /* SELECT, APPEND or UID COPY */
- p = strchr( cmdp->cmd, '"' );
- if (!issue_imap_cmd( ctx, NULL, "CREATE \"%.*s\"", strchr( p + 1, '"' ) - p + 1, p )) {
+ if (!strcmp("NO", arg)) {
+ if (cmdp->cb.create && cmd && (cmdp->cb.trycreate || !memcmp(cmd, "[TRYCREATE]", 11))) { /* SELECT, APPEND or UID COPY */
+ p = strchr(cmdp->cmd, '"');
+ if (!issue_imap_cmd(ctx, NULL, "CREATE \"%.*s\"", strchr(p + 1, '"') - p + 1, p)) {
resp = RESP_BAD;
goto normal;
}
/* not waiting here violates the spec, but a server that does not
grok this nonetheless violates it too. */
cmdp->cb.create = 0;
- if (!(ncmdp = issue_imap_cmd( ctx, &cmdp->cb, "%s", cmdp->cmd ))) {
+ if (!(ncmdp = issue_imap_cmd(ctx, &cmdp->cb, "%s", cmdp->cmd))) {
resp = RESP_BAD;
goto normal;
}
- free( cmdp->cmd );
- free( cmdp );
+ free(cmdp->cmd);
+ free(cmdp);
if (!tcmd)
return 0; /* ignored */
if (cmdp == tcmd)
@@ -846,21 +932,21 @@ get_cmd_result( imap_store_t *ctx, struct imap_cmd *tcmd )
continue;
}
resp = RESP_NO;
- } else /*if (!strcmp( "BAD", arg ))*/
+ } else /*if (!strcmp("BAD", arg))*/
resp = RESP_BAD;
- fprintf( stderr, "IMAP command '%s' returned response (%s) - %s\n",
- memcmp (cmdp->cmd, "LOGIN", 5) ?
+ fprintf(stderr, "IMAP command '%s' returned response (%s) - %s\n",
+ memcmp(cmdp->cmd, "LOGIN", 5) ?
cmdp->cmd : "LOGIN <user> <pass>",
arg, cmd ? cmd : "");
}
- if ((resp2 = parse_response_code( ctx, &cmdp->cb, cmd )) > resp)
+ if ((resp2 = parse_response_code(ctx, &cmdp->cb, cmd)) > resp)
resp = resp2;
- normal:
+ normal:
if (cmdp->cb.done)
- cmdp->cb.done( ctx, cmdp, resp );
- free( cmdp->cb.data );
- free( cmdp->cmd );
- free( cmdp );
+ cmdp->cb.done(ctx, cmdp, resp);
+ free(cmdp->cb.data);
+ free(cmdp->cmd);
+ free(cmdp);
if (!tcmd || tcmd == cmdp)
return resp;
}
@@ -868,170 +954,184 @@ get_cmd_result( imap_store_t *ctx, struct imap_cmd *tcmd )
/* not reached */
}
-static void
-imap_close_server( imap_store_t *ictx )
+static void imap_close_server(struct imap_store *ictx)
{
- imap_t *imap = ictx->imap;
+ struct imap *imap = ictx->imap;
if (imap->buf.sock.fd != -1) {
- imap_exec( ictx, NULL, "LOGOUT" );
- close( imap->buf.sock.fd );
+ imap_exec(ictx, NULL, "LOGOUT");
+ socket_shutdown(&imap->buf.sock);
}
- free_list( imap->ns_personal );
- free_list( imap->ns_other );
- free_list( imap->ns_shared );
- free( imap );
+ free_list(imap->ns_personal);
+ free_list(imap->ns_other);
+ free_list(imap->ns_shared);
+ free(imap);
}
-static void
-imap_close_store( store_t *ctx )
+static void imap_close_store(struct store *ctx)
{
- imap_close_server( (imap_store_t *)ctx );
- free_generic_messages( ctx->msgs );
- free( ctx );
+ imap_close_server((struct imap_store *)ctx);
+ free_generic_messages(ctx->msgs);
+ free(ctx);
}
-static store_t *
-imap_open_store( imap_server_conf_t *srvc )
+static struct store *imap_open_store(struct imap_server_conf *srvc)
{
- imap_store_t *ctx;
- imap_t *imap;
+ struct imap_store *ctx;
+ struct imap *imap;
char *arg, *rsp;
struct hostent *he;
struct sockaddr_in addr;
int s, a[2], preauth;
pid_t pid;
- ctx = xcalloc( sizeof(*ctx), 1 );
+ ctx = xcalloc(sizeof(*ctx), 1);
- ctx->imap = imap = xcalloc( sizeof(*imap), 1 );
+ ctx->imap = imap = xcalloc(sizeof(*imap), 1);
imap->buf.sock.fd = -1;
imap->in_progress_append = &imap->in_progress;
/* open connection to IMAP server */
if (srvc->tunnel) {
- imap_info( "Starting tunnel '%s'... ", srvc->tunnel );
+ imap_info("Starting tunnel '%s'... ", srvc->tunnel);
- if (socketpair( PF_UNIX, SOCK_STREAM, 0, a )) {
- perror( "socketpair" );
- exit( 1 );
+ if (socketpair(PF_UNIX, SOCK_STREAM, 0, a)) {
+ perror("socketpair");
+ exit(1);
}
pid = fork();
if (pid < 0)
- _exit( 127 );
+ _exit(127);
if (!pid) {
- if (dup2( a[0], 0 ) == -1 || dup2( a[0], 1 ) == -1)
- _exit( 127 );
- close( a[0] );
- close( a[1] );
- execl( "/bin/sh", "sh", "-c", srvc->tunnel, NULL );
- _exit( 127 );
+ if (dup2(a[0], 0) == -1 || dup2(a[0], 1) == -1)
+ _exit(127);
+ close(a[0]);
+ close(a[1]);
+ execl("/bin/sh", "sh", "-c", srvc->tunnel, NULL);
+ _exit(127);
}
- close (a[0]);
+ close(a[0]);
imap->buf.sock.fd = a[1];
- imap_info( "ok\n" );
+ imap_info("ok\n");
} else {
- memset( &addr, 0, sizeof(addr) );
- addr.sin_port = htons( srvc->port );
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_port = htons(srvc->port);
addr.sin_family = AF_INET;
- imap_info( "Resolving %s... ", srvc->host );
- he = gethostbyname( srvc->host );
+ imap_info("Resolving %s... ", srvc->host);
+ he = gethostbyname(srvc->host);
if (!he) {
- perror( "gethostbyname" );
+ perror("gethostbyname");
goto bail;
}
- imap_info( "ok\n" );
+ imap_info("ok\n");
addr.sin_addr.s_addr = *((int *) he->h_addr_list[0]);
- s = socket( PF_INET, SOCK_STREAM, 0 );
+ s = socket(PF_INET, SOCK_STREAM, 0);
- imap_info( "Connecting to %s:%hu... ", inet_ntoa( addr.sin_addr ), ntohs( addr.sin_port ) );
- if (connect( s, (struct sockaddr *)&addr, sizeof(addr) )) {
- close( s );
- perror( "connect" );
+ imap_info("Connecting to %s:%hu... ", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
+ if (connect(s, (struct sockaddr *)&addr, sizeof(addr))) {
+ close(s);
+ perror("connect");
goto bail;
}
- imap_info( "ok\n" );
imap->buf.sock.fd = s;
+ if (srvc->use_ssl &&
+ ssl_socket_connect(&imap->buf.sock, 0, srvc->ssl_verify)) {
+ close(s);
+ goto bail;
+ }
+ imap_info("ok\n");
}
/* read the greeting string */
- if (buffer_gets( &imap->buf, &rsp )) {
- fprintf( stderr, "IMAP error: no greeting response\n" );
+ if (buffer_gets(&imap->buf, &rsp)) {
+ fprintf(stderr, "IMAP error: no greeting response\n");
goto bail;
}
- arg = next_arg( &rsp );
- if (!arg || *arg != '*' || (arg = next_arg( &rsp )) == NULL) {
- fprintf( stderr, "IMAP error: invalid greeting response\n" );
+ arg = next_arg(&rsp);
+ if (!arg || *arg != '*' || (arg = next_arg(&rsp)) == NULL) {
+ fprintf(stderr, "IMAP error: invalid greeting response\n");
goto bail;
}
preauth = 0;
- if (!strcmp( "PREAUTH", arg ))
+ if (!strcmp("PREAUTH", arg))
preauth = 1;
- else if (strcmp( "OK", arg ) != 0) {
- fprintf( stderr, "IMAP error: unknown greeting response\n" );
+ else if (strcmp("OK", arg) != 0) {
+ fprintf(stderr, "IMAP error: unknown greeting response\n");
goto bail;
}
- parse_response_code( ctx, NULL, rsp );
- if (!imap->caps && imap_exec( ctx, NULL, "CAPABILITY" ) != RESP_OK)
+ parse_response_code(ctx, NULL, rsp);
+ if (!imap->caps && imap_exec(ctx, NULL, "CAPABILITY") != RESP_OK)
goto bail;
if (!preauth) {
-
- imap_info ("Logging in...\n");
+#ifndef NO_OPENSSL
+ if (!srvc->use_ssl && CAP(STARTTLS)) {
+ if (imap_exec(ctx, 0, "STARTTLS") != RESP_OK)
+ goto bail;
+ if (ssl_socket_connect(&imap->buf.sock, 1,
+ srvc->ssl_verify))
+ goto bail;
+ /* capabilities may have changed, so get the new capabilities */
+ if (imap_exec(ctx, 0, "CAPABILITY") != RESP_OK)
+ goto bail;
+ }
+#endif
+ imap_info("Logging in...\n");
if (!srvc->user) {
- fprintf( stderr, "Skipping server %s, no user\n", srvc->host );
+ fprintf(stderr, "Skipping server %s, no user\n", srvc->host);
goto bail;
}
if (!srvc->pass) {
char prompt[80];
- sprintf( prompt, "Password (%s@%s): ", srvc->user, srvc->host );
- arg = getpass( prompt );
+ sprintf(prompt, "Password (%s@%s): ", srvc->user, srvc->host);
+ arg = getpass(prompt);
if (!arg) {
- perror( "getpass" );
- exit( 1 );
+ perror("getpass");
+ exit(1);
}
if (!*arg) {
- fprintf( stderr, "Skipping account %s@%s, no password\n", srvc->user, srvc->host );
+ fprintf(stderr, "Skipping account %s@%s, no password\n", srvc->user, srvc->host);
goto bail;
}
/*
* getpass() returns a pointer to a static buffer. make a copy
* for long term storage.
*/
- srvc->pass = xstrdup( arg );
+ srvc->pass = xstrdup(arg);
}
if (CAP(NOLOGIN)) {
- fprintf( stderr, "Skipping account %s@%s, server forbids LOGIN\n", srvc->user, srvc->host );
+ fprintf(stderr, "Skipping account %s@%s, server forbids LOGIN\n", srvc->user, srvc->host);
goto bail;
}
- imap_warn( "*** IMAP Warning *** Password is being sent in the clear\n" );
- if (imap_exec( ctx, NULL, "LOGIN \"%s\" \"%s\"", srvc->user, srvc->pass ) != RESP_OK) {
- fprintf( stderr, "IMAP error: LOGIN failed\n" );
+ if (!imap->buf.sock.ssl)
+ imap_warn("*** IMAP Warning *** Password is being "
+ "sent in the clear\n");
+ if (imap_exec(ctx, NULL, "LOGIN \"%s\" \"%s\"", srvc->user, srvc->pass) != RESP_OK) {
+ fprintf(stderr, "IMAP error: LOGIN failed\n");
goto bail;
}
} /* !preauth */
ctx->prefix = "";
ctx->trashnc = 1;
- return (store_t *)ctx;
+ return (struct store *)ctx;
- bail:
- imap_close_store( &ctx->gen );
+bail:
+ imap_close_store(&ctx->gen);
return NULL;
}
-static int
-imap_make_flags( int flags, char *buf )
+static int imap_make_flags(int flags, char *buf)
{
const char *s;
unsigned i, d;
@@ -1050,11 +1150,10 @@ imap_make_flags( int flags, char *buf )
#define TUIDL 8
-static int
-imap_store_msg( store_t *gctx, msg_data_t *data, int *uid )
+static int imap_store_msg(struct store *gctx, struct msg_data *data, int *uid)
{
- imap_store_t *ctx = (imap_store_t *)gctx;
- imap_t *imap = ctx->imap;
+ struct imap_store *ctx = (struct imap_store *)gctx;
+ struct imap *imap = ctx->imap;
struct imap_cmd_cb cb;
char *fmap, *buf;
const char *prefix, *box;
@@ -1062,14 +1161,14 @@ imap_store_msg( store_t *gctx, msg_data_t *data, int *uid )
int start, sbreak = 0, ebreak = 0;
char flagstr[128], tuid[TUIDL * 2 + 1];
- memset( &cb, 0, sizeof(cb) );
+ memset(&cb, 0, sizeof(cb));
fmap = data->data;
len = data->len;
nocr = !data->crlf;
extra = 0, i = 0;
if (!CAP(UIDPLUS) && uid) {
- nloop:
+ nloop:
start = i;
while (i < len)
if (fmap[i++] == '\n') {
@@ -1078,18 +1177,18 @@ imap_store_msg( store_t *gctx, msg_data_t *data, int *uid )
sbreak = ebreak = i - 2 + nocr;
goto mktid;
}
- if (!memcmp( fmap + start, "X-TUID: ", 8 )) {
+ if (!memcmp(fmap + start, "X-TUID: ", 8)) {
extra -= (ebreak = i) - (sbreak = start) + nocr;
goto mktid;
}
goto nloop;
}
/* invalid message */
- free( fmap );
+ free(fmap);
return DRV_MSG_BAD;
- mktid:
+ mktid:
for (j = 0; j < TUIDL; j++)
- sprintf( tuid + j * 2, "%02x", arc4_getbyte() );
+ sprintf(tuid + j * 2, "%02x", arc4_getbyte());
extra += 8 + TUIDL * 2 + 2;
}
if (nocr)
@@ -1098,7 +1197,7 @@ imap_store_msg( store_t *gctx, msg_data_t *data, int *uid )
extra++;
cb.dlen = len + extra;
- buf = cb.data = xmalloc( cb.dlen );
+ buf = cb.data = xmalloc(cb.dlen);
i = 0;
if (!CAP(UIDPLUS) && uid) {
if (nocr) {
@@ -1109,12 +1208,12 @@ imap_store_msg( store_t *gctx, msg_data_t *data, int *uid )
} else
*buf++ = fmap[i];
} else {
- memcpy( buf, fmap, sbreak );
+ memcpy(buf, fmap, sbreak);
buf += sbreak;
}
- memcpy( buf, "X-TUID: ", 8 );
+ memcpy(buf, "X-TUID: ", 8);
buf += 8;
- memcpy( buf, tuid, TUIDL * 2 );
+ memcpy(buf, tuid, TUIDL * 2);
buf += TUIDL * 2;
*buf++ = '\r';
*buf++ = '\n';
@@ -1128,13 +1227,13 @@ imap_store_msg( store_t *gctx, msg_data_t *data, int *uid )
} else
*buf++ = fmap[i];
} else
- memcpy( buf, fmap + i, len - i );
+ memcpy(buf, fmap + i, len - i);
- free( fmap );
+ free(fmap);
d = 0;
if (data->flags) {
- d = imap_make_flags( data->flags, flagstr );
+ d = imap_make_flags(data->flags, flagstr);
flagstr[d++] = ' ';
}
flagstr[d] = 0;
@@ -1147,11 +1246,11 @@ imap_store_msg( store_t *gctx, msg_data_t *data, int *uid )
imap->caps = imap->rcaps & ~(1 << LITERALPLUS);
} else {
box = gctx->name;
- prefix = !strcmp( box, "INBOX" ) ? "" : ctx->prefix;
+ prefix = !strcmp(box, "INBOX") ? "" : ctx->prefix;
cb.create = 0;
}
cb.ctx = uid;
- ret = imap_exec_m( ctx, &cb, "APPEND \"%s%s\" %s", prefix, box, flagstr );
+ ret = imap_exec_m(ctx, &cb, "APPEND \"%s%s\" %s", prefix, box, flagstr);
imap->caps = imap->rcaps;
if (ret != DRV_OK)
return ret;
@@ -1165,8 +1264,7 @@ imap_store_msg( store_t *gctx, msg_data_t *data, int *uid )
#define CHUNKSIZE 0x1000
-static int
-read_message( FILE *f, msg_data_t *msg )
+static int read_message(FILE *f, struct msg_data *msg)
{
struct strbuf buf;
@@ -1183,8 +1281,7 @@ read_message( FILE *f, msg_data_t *msg )
return msg->len;
}
-static int
-count_messages( msg_data_t *msg )
+static int count_messages(struct msg_data *msg)
{
int count = 0;
char *p = msg->data;
@@ -1194,7 +1291,7 @@ count_messages( msg_data_t *msg )
count++;
p += 5;
}
- p = strstr( p+5, "\nFrom ");
+ p = strstr(p+5, "\nFrom ");
if (!p)
break;
p++;
@@ -1202,22 +1299,21 @@ count_messages( msg_data_t *msg )
return count;
}
-static int
-split_msg( msg_data_t *all_msgs, msg_data_t *msg, int *ofs )
+static int split_msg(struct msg_data *all_msgs, struct msg_data *msg, int *ofs)
{
char *p, *data;
- memset( msg, 0, sizeof *msg );
+ memset(msg, 0, sizeof *msg);
if (*ofs >= all_msgs->len)
return 0;
- data = &all_msgs->data[ *ofs ];
+ data = &all_msgs->data[*ofs];
msg->len = all_msgs->len - *ofs;
if (msg->len < 5 || prefixcmp(data, "From "))
return 0;
- p = strchr( data, '\n' );
+ p = strchr(data, '\n');
if (p) {
p = &p[1];
msg->len -= p-data;
@@ -1225,7 +1321,7 @@ split_msg( msg_data_t *all_msgs, msg_data_t *msg, int *ofs )
data = p;
}
- p = strstr( data, "\nFrom " );
+ p = strstr(data, "\nFrom ");
if (p)
msg->len = &p[1] - data;
@@ -1234,24 +1330,24 @@ split_msg( msg_data_t *all_msgs, msg_data_t *msg, int *ofs )
return 1;
}
-static imap_server_conf_t server =
-{
+static struct imap_server_conf server = {
NULL, /* name */
NULL, /* tunnel */
NULL, /* host */
0, /* port */
NULL, /* user */
NULL, /* pass */
+ 0, /* use_ssl */
+ 1, /* ssl_verify */
};
static char *imap_folder;
-static int
-git_imap_config(const char *key, const char *val, void *cb)
+static int git_imap_config(const char *key, const char *val, void *cb)
{
char imap_key[] = "imap.";
- if (strncmp( key, imap_key, sizeof imap_key - 1 ))
+ if (strncmp(key, imap_key, sizeof imap_key - 1))
return 0;
if (!val)
@@ -1259,90 +1355,96 @@ git_imap_config(const char *key, const char *val, void *cb)
key += sizeof imap_key - 1;
- if (!strcmp( "folder", key )) {
- imap_folder = xstrdup( val );
- } else if (!strcmp( "host", key )) {
- {
- if (!prefixcmp(val, "imap:"))
- val += 5;
- if (!server.port)
- server.port = 143;
+ if (!strcmp("folder", key)) {
+ imap_folder = xstrdup(val);
+ } else if (!strcmp("host", key)) {
+ if (!prefixcmp(val, "imap:"))
+ val += 5;
+ else if (!prefixcmp(val, "imaps:")) {
+ val += 6;
+ server.use_ssl = 1;
}
if (!prefixcmp(val, "//"))
val += 2;
- server.host = xstrdup( val );
- }
- else if (!strcmp( "user", key ))
- server.user = xstrdup( val );
- else if (!strcmp( "pass", key ))
- server.pass = xstrdup( val );
- else if (!strcmp( "port", key ))
- server.port = git_config_int( key, val );
- else if (!strcmp( "tunnel", key ))
- server.tunnel = xstrdup( val );
+ server.host = xstrdup(val);
+ } else if (!strcmp("user", key))
+ server.user = xstrdup(val);
+ else if (!strcmp("pass", key))
+ server.pass = xstrdup(val);
+ else if (!strcmp("port", key))
+ server.port = git_config_int(key, val);
+ else if (!strcmp("tunnel", key))
+ server.tunnel = xstrdup(val);
+ else if (!strcmp("sslverify", key))
+ server.ssl_verify = git_config_bool(key, val);
return 0;
}
-int
-main(int argc, char **argv)
+int main(int argc, char **argv)
{
- msg_data_t all_msgs, msg;
- store_t *ctx = NULL;
+ struct msg_data all_msgs, msg;
+ struct store *ctx = NULL;
int uid = 0;
int ofs = 0;
int r;
int total, n = 0;
+ int nongit_ok;
/* init the random number generator */
arc4_init();
+ setup_git_directory_gently(&nongit_ok);
git_config(git_imap_config, NULL);
+ if (!server.port)
+ server.port = server.use_ssl ? 993 : 143;
+
if (!imap_folder) {
- fprintf( stderr, "no imap store specified\n" );
+ fprintf(stderr, "no imap store specified\n");
return 1;
}
if (!server.host) {
if (!server.tunnel) {
- fprintf( stderr, "no imap host specified\n" );
+ fprintf(stderr, "no imap host specified\n");
return 1;
}
server.host = "tunnel";
}
/* read the messages */
- if (!read_message( stdin, &all_msgs )) {
- fprintf(stderr,"nothing to send\n");
+ if (!read_message(stdin, &all_msgs)) {
+ fprintf(stderr, "nothing to send\n");
return 1;
}
- total = count_messages( &all_msgs );
+ total = count_messages(&all_msgs);
if (!total) {
- fprintf(stderr,"no messages to send\n");
+ fprintf(stderr, "no messages to send\n");
return 1;
}
/* write it to the imap server */
- ctx = imap_open_store( &server );
+ ctx = imap_open_store(&server);
if (!ctx) {
- fprintf( stderr,"failed to open store\n");
+ fprintf(stderr, "failed to open store\n");
return 1;
}
- fprintf( stderr, "sending %d message%s\n", total, (total!=1)?"s":"" );
+ fprintf(stderr, "sending %d message%s\n", total, (total != 1) ? "s" : "");
ctx->name = imap_folder;
while (1) {
unsigned percent = n * 100 / total;
- fprintf( stderr, "%4u%% (%d/%d) done\r", percent, n, total );
- if (!split_msg( &all_msgs, &msg, &ofs ))
+ fprintf(stderr, "%4u%% (%d/%d) done\r", percent, n, total);
+ if (!split_msg(&all_msgs, &msg, &ofs))
+ break;
+ r = imap_store_msg(ctx, &msg, &uid);
+ if (r != DRV_OK)
break;
- r = imap_store_msg( ctx, &msg, &uid );
- if (r != DRV_OK) break;
n++;
}
- fprintf( stderr,"\n" );
+ fprintf(stderr, "\n");
- imap_close_store( ctx );
+ imap_close_store(ctx);
return 0;
}
diff --git a/index-pack.c b/index-pack.c
index 52064befdb..728af7da9c 100644
--- a/index-pack.c
+++ b/index-pack.c
@@ -876,7 +876,9 @@ int main(int argc, char **argv)
char *index_name_buf = NULL, *keep_name_buf = NULL;
struct pack_idx_entry **idx_objects;
unsigned char sha1[20];
+ int nongit = 0;
+ setup_git_directory_gently(&nongit);
git_config(git_index_pack_config, NULL);
for (i = 1; i < argc; i++) {
diff --git a/log-tree.c b/log-tree.c
index bd8b9e45ab..30cd5bb228 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -432,7 +432,7 @@ static int log_tree_diff(struct rev_info *opt, struct commit *commit, struct log
struct commit_list *parents;
unsigned const char *sha1 = commit->object.sha1;
- if (!opt->diff)
+ if (!opt->diff && !DIFF_OPT_TST(&opt->diffopt, EXIT_WITH_STATUS))
return 0;
/* Root commit? */
diff --git a/pack-write.c b/pack-write.c
index a8f0269936..ddcfd37af2 100644
--- a/pack-write.c
+++ b/pack-write.c
@@ -179,6 +179,7 @@ void fixup_pack_header_footer(int pack_fd,
SHA1_Final(pack_file_sha1, &c);
write_or_die(pack_fd, pack_file_sha1, 20);
+ fsync_or_die(pack_fd, pack_name);
}
char *index_pack_lockfile(int ip_out)
diff --git a/pager.c b/pager.c
index 6b5c9e44b4..aa0966c9c5 100644
--- a/pager.c
+++ b/pager.c
@@ -1,4 +1,5 @@
#include "cache.h"
+#include "run-command.h"
/*
* This is split up from the rest of git so that we can do
@@ -8,7 +9,7 @@
static int spawned_pager;
#ifndef __MINGW32__
-static void run_pager(const char *pager)
+static void pager_preexec(void)
{
/*
* Work around bug in "less" by not starting it until we
@@ -20,17 +21,13 @@ static void run_pager(const char *pager)
FD_SET(0, &in);
select(1, &in, NULL, &in, NULL);
- execlp(pager, pager, NULL);
- execl("/bin/sh", "sh", "-c", pager, NULL);
+ setenv("LESS", "FRSX", 0);
}
-#else
-#include "run-command.h"
+#endif
static const char *pager_argv[] = { "sh", "-c", NULL, NULL };
-static struct child_process pager_process = {
- .argv = pager_argv,
- .in = -1
-};
+static struct child_process pager_process;
+
static void wait_for_pager(void)
{
fflush(stdout);
@@ -40,14 +37,9 @@ static void wait_for_pager(void)
close(2);
finish_command(&pager_process);
}
-#endif
void setup_pager(void)
{
-#ifndef __MINGW32__
- pid_t pid;
- int fd[2];
-#endif
const char *pager = getenv("GIT_PAGER");
if (!isatty(1))
@@ -66,37 +58,13 @@ void setup_pager(void)
spawned_pager = 1; /* means we are emitting to terminal */
-#ifndef __MINGW32__
- if (pipe(fd) < 0)
- return;
- pid = fork();
- if (pid < 0) {
- close(fd[0]);
- close(fd[1]);
- return;
- }
-
- /* return in the child */
- if (!pid) {
- dup2(fd[1], 1);
- dup2(fd[1], 2);
- close(fd[0]);
- close(fd[1]);
- return;
- }
-
- /* The original process turns into the PAGER */
- dup2(fd[0], 0);
- close(fd[0]);
- close(fd[1]);
-
- setenv("LESS", "FRSX", 0);
- run_pager(pager);
- die("unable to execute pager '%s'", pager);
- exit(255);
-#else
/* spawn the pager */
pager_argv[2] = pager;
+ pager_process.argv = pager_argv;
+ pager_process.in = -1;
+#ifndef __MINGW32__
+ pager_process.preexec_cb = pager_preexec;
+#endif
if (start_command(&pager_process))
return;
@@ -107,7 +75,6 @@ void setup_pager(void)
/* this makes sure that the parent terminates after the pager */
atexit(wait_for_pager);
-#endif
}
int pager_in_use(void)
diff --git a/read-cache.c b/read-cache.c
index 2c03ec3069..a857c8e12f 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -1118,6 +1118,10 @@ static void convert_from_disk(struct ondisk_cache_entry *ondisk, struct cache_en
ce->ce_size = ntohl(ondisk->size);
/* On-disk flags are just 16 bits */
ce->ce_flags = ntohs(ondisk->flags);
+
+ /* For future extension: we do not understand this entry yet */
+ if (ce->ce_flags & CE_EXTENDED)
+ die("Unknown index entry format");
hashcpy(ce->sha1, ondisk->sha1);
len = ce->ce_flags & CE_NAMEMASK;
@@ -1155,7 +1159,7 @@ int read_index_from(struct index_state *istate, const char *path)
size_t mmap_size;
errno = EBUSY;
- if (istate->alloc)
+ if (istate->initialized)
return istate->cache_nr;
errno = ENOENT;
@@ -1195,6 +1199,7 @@ int read_index_from(struct index_state *istate, const char *path)
* index size
*/
istate->alloc = xmalloc(estimate_cache_size(mmap_size, istate->cache_nr));
+ istate->initialized = 1;
src_offset = sizeof(*hdr);
dst_offset = 0;
@@ -1247,6 +1252,7 @@ int discard_index(struct index_state *istate)
cache_tree_free(&(istate->cache_tree));
free(istate->alloc);
istate->alloc = NULL;
+ istate->initialized = 0;
/* no need to throw away allocated active_cache */
return 0;
diff --git a/remote.c b/remote.c
index 105668f8a3..3ef09a44a1 100644
--- a/remote.c
+++ b/remote.c
@@ -449,6 +449,26 @@ static int verify_refname(char *name, int is_glob)
return result;
}
+/*
+ * This function frees a refspec array.
+ * Warning: code paths should be checked to ensure that the src
+ * and dst pointers are always freeable pointers as well
+ * as the refspec pointer itself.
+ */
+void free_refspecs(struct refspec *refspec, int nr_refspec)
+{
+ int i;
+
+ if (!refspec)
+ return;
+
+ for (i = 0; i < nr_refspec; i++) {
+ free(refspec[i].src);
+ free(refspec[i].dst);
+ }
+ free(refspec);
+}
+
static struct refspec *parse_refspec_internal(int nr_refspec, const char **refspec, int fetch, int verify)
{
int i;
@@ -567,7 +587,12 @@ static struct refspec *parse_refspec_internal(int nr_refspec, const char **refsp
invalid:
if (verify) {
- free(rs);
+ /*
+ * nr_refspec must be greater than zero and i must be valid
+ * since it is only possible to reach this point from within
+ * the for loop above.
+ */
+ free_refspecs(rs, i+1);
return NULL;
}
die("Invalid refspec '%s'", refspec[i]);
@@ -579,7 +604,7 @@ int valid_fetch_refspec(const char *fetch_refspec_str)
struct refspec *refspec;
refspec = parse_refspec_internal(1, fetch_refspec, 1, 1);
- free(refspec);
+ free_refspecs(refspec, 1);
return !!refspec;
}
diff --git a/remote.h b/remote.h
index 091b1d041f..2601f6e76d 100644
--- a/remote.h
+++ b/remote.h
@@ -78,6 +78,7 @@ void ref_remove_duplicates(struct ref *ref_map);
int valid_fetch_refspec(const char *refspec);
struct refspec *parse_fetch_refspec(int nr_refspec, const char **refspec);
struct refspec *parse_push_refspec(int nr_refspec, const char **refspec);
+void free_refspecs(struct refspec *refspec, int nr_refspec);
int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
int nr_refspec, const char **refspec, int all);
diff --git a/revision.c b/revision.c
index e75079a6e1..36291b6b86 100644
--- a/revision.c
+++ b/revision.c
@@ -782,6 +782,10 @@ void init_revisions(struct rev_info *revs, const char *prefix)
revs->commit_format = CMIT_FMT_DEFAULT;
+ revs->grep_filter.status_only = 1;
+ revs->grep_filter.pattern_tail = &(revs->grep_filter.pattern_list);
+ revs->grep_filter.regflags = REG_NEWLINE;
+
diff_setup(&revs->diffopt);
if (prefix && !revs->diffopt.prefix) {
revs->diffopt.prefix = prefix;
@@ -946,15 +950,7 @@ void read_revisions_from_stdin(struct rev_info *revs)
static void add_grep(struct rev_info *revs, const char *ptn, enum grep_pat_token what)
{
- if (!revs->grep_filter) {
- struct grep_opt *opt = xcalloc(1, sizeof(*opt));
- opt->status_only = 1;
- opt->pattern_tail = &(opt->pattern_list);
- opt->regflags = REG_NEWLINE;
- revs->grep_filter = opt;
- }
- append_grep_pattern(revs->grep_filter, ptn,
- "command line", 0, what);
+ append_grep_pattern(&revs->grep_filter, ptn, "command line", 0, what);
}
static void add_header_grep(struct rev_info *revs, const char *field, const char *pattern)
@@ -1164,17 +1160,13 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
} else if (!prefixcmp(arg, "--grep=")) {
add_message_grep(revs, arg+7);
} else if (!strcmp(arg, "--extended-regexp") || !strcmp(arg, "-E")) {
- if (revs->grep_filter)
- revs->grep_filter->regflags |= REG_EXTENDED;
+ revs->grep_filter.regflags |= REG_EXTENDED;
} else if (!strcmp(arg, "--regexp-ignore-case") || !strcmp(arg, "-i")) {
- if (revs->grep_filter)
- revs->grep_filter->regflags |= REG_ICASE;
+ revs->grep_filter.regflags |= REG_ICASE;
} else if (!strcmp(arg, "--fixed-strings") || !strcmp(arg, "-F")) {
- if (revs->grep_filter)
- revs->grep_filter->fixed = 1;
+ revs->grep_filter.fixed = 1;
} else if (!strcmp(arg, "--all-match")) {
- if (revs->grep_filter)
- revs->grep_filter->all_match = 1;
+ revs->grep_filter.all_match = 1;
} else if (!prefixcmp(arg, "--encoding=")) {
arg += 11;
if (strcmp(arg, "none"))
@@ -1349,9 +1341,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
if (diff_setup_done(&revs->diffopt) < 0)
die("diff_setup_done failed");
- if (revs->grep_filter) {
- compile_grep_patterns(revs->grep_filter);
- }
+ compile_grep_patterns(&revs->grep_filter);
if (revs->reverse && revs->reflog_info)
die("cannot combine --reverse with --walk-reflogs");
@@ -1492,9 +1482,9 @@ static int rewrite_parents(struct rev_info *revs, struct commit *commit)
static int commit_match(struct commit *commit, struct rev_info *opt)
{
- if (!opt->grep_filter)
+ if (!opt->grep_filter.pattern_list)
return 1;
- return grep_buffer(opt->grep_filter,
+ return grep_buffer(&opt->grep_filter,
NULL, /* we say nothing, not even filename */
commit->buffer, strlen(commit->buffer));
}
diff --git a/revision.h b/revision.h
index 1b045669ae..91f194478b 100644
--- a/revision.h
+++ b/revision.h
@@ -2,6 +2,7 @@
#define REVISION_H
#include "parse-options.h"
+#include "grep.h"
#define SEEN (1u<<0)
#define UNINTERESTING (1u<<1)
@@ -92,7 +93,7 @@ struct rev_info {
int show_log_size;
/* Filter by commit log message */
- struct grep_opt *grep_filter;
+ struct grep_opt grep_filter;
/* Display history graph */
struct git_graph *graph;
diff --git a/run-command.c b/run-command.c
index bbb9c777e5..caab374577 100644
--- a/run-command.c
+++ b/run-command.c
@@ -111,6 +111,8 @@ int start_command(struct child_process *cmd)
unsetenv(*cmd->env);
}
}
+ if (cmd->preexec_cb)
+ cmd->preexec_cb();
if (cmd->git_cmd) {
execv_git_cmd(cmd->argv);
} else {
diff --git a/run-command.h b/run-command.h
index 5203a9ebb1..4f2b7d7d40 100644
--- a/run-command.h
+++ b/run-command.h
@@ -42,6 +42,7 @@ struct child_process {
unsigned no_stderr:1;
unsigned git_cmd:1; /* if this is to be git sub-command */
unsigned stdout_to_stderr:1;
+ void (*preexec_cb)(void);
};
int start_command(struct child_process *);
diff --git a/sha1_file.c b/sha1_file.c
index 477d3fb4b0..9ee1ed16ad 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -2361,51 +2361,22 @@ int has_sha1_file(const unsigned char *sha1)
return has_loose_object(sha1);
}
-int index_pipe(unsigned char *sha1, int fd, const char *type, int write_object)
+static int index_mem(unsigned char *sha1, void *buf, size_t size,
+ int write_object, enum object_type type, const char *path)
{
- struct strbuf buf;
- int ret;
-
- strbuf_init(&buf, 0);
- if (strbuf_read(&buf, fd, 4096) < 0) {
- strbuf_release(&buf);
- return -1;
- }
-
- if (!type)
- type = blob_type;
- if (write_object)
- ret = write_sha1_file(buf.buf, buf.len, type, sha1);
- else
- ret = hash_sha1_file(buf.buf, buf.len, type, sha1);
- strbuf_release(&buf);
-
- return ret;
-}
-
-int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object,
- enum object_type type, const char *path)
-{
- size_t size = xsize_t(st->st_size);
- void *buf = NULL;
int ret, re_allocated = 0;
- if (size)
- buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
- close(fd);
-
if (!type)
type = OBJ_BLOB;
/*
* Convert blobs to git internal format
*/
- if ((type == OBJ_BLOB) && S_ISREG(st->st_mode)) {
+ if ((type == OBJ_BLOB) && path) {
struct strbuf nbuf;
strbuf_init(&nbuf, 0);
if (convert_to_git(path, buf, size, &nbuf,
write_object ? safe_crlf : 0)) {
- munmap(buf, size);
buf = strbuf_detach(&nbuf, &size);
re_allocated = 1;
}
@@ -2415,12 +2386,33 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object,
ret = write_sha1_file(buf, size, typename(type), sha1);
else
ret = hash_sha1_file(buf, size, typename(type), sha1);
- if (re_allocated) {
+ if (re_allocated)
free(buf);
- return ret;
- }
- if (size)
+ return ret;
+}
+
+int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object,
+ enum object_type type, const char *path)
+{
+ int ret;
+ size_t size = xsize_t(st->st_size);
+
+ if (!S_ISREG(st->st_mode)) {
+ struct strbuf sbuf;
+ strbuf_init(&sbuf, 0);
+ if (strbuf_read(&sbuf, fd, 4096) >= 0)
+ ret = index_mem(sha1, sbuf.buf, sbuf.len, write_object,
+ type, path);
+ else
+ ret = -1;
+ strbuf_release(&sbuf);
+ } else if (size) {
+ void *buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
+ ret = index_mem(sha1, buf, size, write_object, type, path);
munmap(buf, size);
+ } else
+ ret = index_mem(sha1, NULL, size, write_object, type, path);
+ close(fd);
return ret;
}
diff --git a/sha1_name.c b/sha1_name.c
index 4fb77f8863..41b680915d 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -349,7 +349,10 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
else
nth = -1;
}
- if (0 <= nth)
+ if (100000000 <= nth) {
+ at_time = nth;
+ nth = -1;
+ } else if (0 <= nth)
at_time = 0;
else {
char *tmp = xstrndup(str + at + 2, reflog_len);
diff --git a/shell.c b/shell.c
index 6a48de05ff..0f6a727a8c 100644
--- a/shell.c
+++ b/shell.c
@@ -3,14 +3,6 @@
#include "exec_cmd.h"
#include "strbuf.h"
-/* Stubs for functions that make no sense for git-shell. These stubs
- * are provided here to avoid linking in external redundant modules.
- */
-void release_pack_memory(size_t need, int fd){}
-void trace_argv_printf(const char **argv, const char *fmt, ...){}
-void trace_printf(const char *fmt, ...){}
-
-
static int do_generic_cmd(const char *me, char *arg)
{
const char *my_argv[4];
diff --git a/t/.gitignore b/t/.gitignore
index b27e280083..7dcbb232cd 100644
--- a/t/.gitignore
+++ b/t/.gitignore
@@ -1,2 +1,2 @@
-/trash directory
+/trash directory*
/test-results
diff --git a/t/Makefile b/t/Makefile
index 0d65cedaa6..ed49c20b16 100644
--- a/t/Makefile
+++ b/t/Makefile
@@ -14,7 +14,8 @@ SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
T = $(wildcard t[0-9][0-9][0-9][0-9]-*.sh)
TSVN = $(wildcard t91[0-9][0-9]-*.sh)
-all: pre-clean $(T) aggregate-results clean
+all: pre-clean
+ $(MAKE) aggregate-results-and-cleanup
$(T):
@echo "*** $@ ***"; GIT_CONFIG=.git/config '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS)
@@ -25,6 +26,10 @@ pre-clean:
clean:
$(RM) -r 'trash directory' test-results
+aggregate-results-and-cleanup: $(T)
+ $(MAKE) aggregate-results
+ $(MAKE) clean
+
aggregate-results:
'$(SHELL_PATH_SQ)' ./aggregate-results.sh test-results/t*-*
@@ -34,4 +39,3 @@ full-svn-test:
$(MAKE) $(TSVN) GIT_SVN_NO_OPTIMIZE_COMMITS=0 LC_ALL=en_US.UTF-8
.PHONY: pre-clean $(T) aggregate-results clean
-.NOTPARALLEL:
diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh
index dc473dfb53..6ac312b905 100644
--- a/t/lib-httpd.sh
+++ b/t/lib-httpd.sh
@@ -14,7 +14,7 @@ fi
LIB_HTTPD_PATH=${LIB_HTTPD_PATH-'/usr/sbin/apache2'}
LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'8111'}
-TEST_PATH="$PWD"/../lib-httpd
+TEST_PATH="$TEST_DIRECTORY"/lib-httpd
HTTPD_ROOT_PATH="$PWD"/httpd
HTTPD_DOCUMENT_ROOT_PATH=$HTTPD_ROOT_PATH/www
diff --git a/t/t0022-crlf-rename.sh b/t/t0022-crlf-rename.sh
index 7d1ce2d056..f1e1d48869 100755
--- a/t/t0022-crlf-rename.sh
+++ b/t/t0022-crlf-rename.sh
@@ -6,13 +6,13 @@ test_description='ignore CR in CRLF sequence while computing similiarity'
test_expect_success setup '
- cat ../t0022-crlf-rename.sh >sample &&
+ cat "$TEST_DIRECTORY"/t0022-crlf-rename.sh >sample &&
git add sample &&
test_tick &&
git commit -m Initial &&
- sed -e "s/\$/ /" ../t0022-crlf-rename.sh >elpmas &&
+ sed -e "s/\$/ /" "$TEST_DIRECTORY"/t0022-crlf-rename.sh >elpmas &&
git add elpmas &&
rm -f sample &&
diff --git a/t/t0055-beyond-symlinks.sh b/t/t0055-beyond-symlinks.sh
new file mode 100755
index 0000000000..b29c37a5a4
--- /dev/null
+++ b/t/t0055-beyond-symlinks.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+test_description='update-index and add refuse to add beyond symlinks'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ >a &&
+ mkdir b &&
+ ln -s b c &&
+ >c/d &&
+ git update-index --add a b/d
+'
+
+test_expect_success 'update-index --add beyond symlinks' '
+ test_must_fail git update-index --add c/d &&
+ ! ( git ls-files | grep c/d )
+'
+
+test_expect_success 'add beyond symlinks' '
+ test_must_fail git add c/d &&
+ ! ( git ls-files | grep c/d )
+'
+
+test_done
diff --git a/t/t1000-read-tree-m-3way.sh b/t/t1000-read-tree-m-3way.sh
index 807fb83af8..22ba7a5442 100755
--- a/t/t1000-read-tree-m-3way.sh
+++ b/t/t1000-read-tree-m-3way.sh
@@ -72,7 +72,7 @@ In addition:
'
. ./test-lib.sh
-. ../lib-read-tree-m-3way.sh
+. "$TEST_DIRECTORY"/lib-read-tree-m-3way.sh
################################################################
# Trivial "majority when 3 stages exist" merge plus #2ALT, #3ALT
diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh
index 1ec0535138..fcdd15a358 100755
--- a/t/t1007-hash-object.sh
+++ b/t/t1007-hash-object.sh
@@ -49,16 +49,28 @@ setup_repo
# Argument checking
test_expect_success "multiple '--stdin's are rejected" '
- test_must_fail git hash-object --stdin --stdin < example
+ echo example | test_must_fail git hash-object --stdin --stdin
'
test_expect_success "Can't use --stdin and --stdin-paths together" '
- test_must_fail git hash-object --stdin --stdin-paths &&
- test_must_fail git hash-object --stdin-paths --stdin
+ echo example | test_must_fail git hash-object --stdin --stdin-paths &&
+ echo example | test_must_fail git hash-object --stdin-paths --stdin
'
test_expect_success "Can't pass filenames as arguments with --stdin-paths" '
- test_must_fail git hash-object --stdin-paths hello < example
+ echo example | test_must_fail git hash-object --stdin-paths hello
+'
+
+test_expect_success "Can't use --path with --stdin-paths" '
+ echo example | test_must_fail git hash-object --stdin-paths --path=foo
+'
+
+test_expect_success "Can't use --stdin-paths with --no-filters" '
+ echo example | test_must_fail git hash-object --stdin-paths --no-filters
+'
+
+test_expect_success "Can't use --path with --no-filters" '
+ test_must_fail git hash-object --no-filters --path=foo
'
# Behavior
@@ -93,6 +105,42 @@ test_expect_success 'git hash-object --stdin file1 <file0 first operates on file
test "$obname1" = "$obname1new"
'
+test_expect_success 'check that appropriate filter is invoke when --path is used' '
+ echo fooQ | tr Q "\\015" >file0 &&
+ cp file0 file1 &&
+ echo "file0 -crlf" >.gitattributes &&
+ echo "file1 crlf" >>.gitattributes &&
+ git config core.autocrlf true &&
+ file0_sha=$(git hash-object file0) &&
+ file1_sha=$(git hash-object file1) &&
+ test "$file0_sha" != "$file1_sha" &&
+ path1_sha=$(git hash-object --path=file1 file0) &&
+ path0_sha=$(git hash-object --path=file0 file1) &&
+ test "$file0_sha" = "$path0_sha" &&
+ test "$file1_sha" = "$path1_sha" &&
+ path1_sha=$(cat file0 | git hash-object --path=file1 --stdin) &&
+ path0_sha=$(cat file1 | git hash-object --path=file0 --stdin) &&
+ test "$file0_sha" = "$path0_sha" &&
+ test "$file1_sha" = "$path1_sha" &&
+ git config --unset core.autocrlf
+'
+
+test_expect_success 'check that --no-filters option works' '
+ echo fooQ | tr Q "\\015" >file0 &&
+ cp file0 file1 &&
+ echo "file0 -crlf" >.gitattributes &&
+ echo "file1 crlf" >>.gitattributes &&
+ git config core.autocrlf true &&
+ file0_sha=$(git hash-object file0) &&
+ file1_sha=$(git hash-object file1) &&
+ test "$file0_sha" != "$file1_sha" &&
+ nofilters_file1=$(git hash-object --no-filters file1) &&
+ test "$file0_sha" = "$nofilters_file1" &&
+ nofilters_file1=$(cat file1 | git hash-object --stdin) &&
+ test "$file0_sha" = "$nofilters_file1" &&
+ git config --unset core.autocrlf
+'
+
pop_repo
for args in "-w --stdin" "--stdin -w"; do
diff --git a/t/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh
index aff360303a..f2880152b0 100755
--- a/t/t3030-merge-recursive.sh
+++ b/t/t3030-merge-recursive.sh
@@ -269,6 +269,17 @@ test_expect_success 'merge-recursive result' '
'
+test_expect_success 'fail if the index has unresolved entries' '
+
+ rm -fr [abcd] &&
+ git checkout -f "$c1" &&
+
+ test_must_fail git merge "$c5" &&
+ test_must_fail git merge "$c5" 2> out &&
+ grep "You are in the middle of a conflicted merge" out
+
+'
+
test_expect_success 'merge-recursive remove conflict' '
rm -fr [abcd] &&
diff --git a/t/t3300-funny-names.sh b/t/t3300-funny-names.sh
index 0574ef1f10..db46d53e82 100755
--- a/t/t3300-funny-names.sh
+++ b/t/t3300-funny-names.sh
@@ -21,7 +21,7 @@ cat >"$p0" <<\EOF
3. A quick brown fox jumps over the lazy cat, oops dog.
EOF
-cat >"$p1" "$p0"
+cat 2>/dev/null >"$p1" "$p0"
echo 'Foo Bar Baz' >"$p2"
test -f "$p1" && cmp "$p0" "$p1" || {
diff --git a/t/t3900-i18n-commit.sh b/t/t3900-i18n-commit.sh
index 883281dbd6..f4f41847f3 100755
--- a/t/t3900-i18n-commit.sh
+++ b/t/t3900-i18n-commit.sh
@@ -16,7 +16,7 @@ test_expect_success setup '
: >F &&
git add F &&
T=$(git write-tree) &&
- C=$(git commit-tree $T <../t3900/1-UTF-8.txt) &&
+ C=$(git commit-tree $T <"$TEST_DIRECTORY"/t3900/1-UTF-8.txt) &&
git update-ref HEAD $C &&
git-tag C0
'
@@ -32,7 +32,7 @@ do
git config i18n.commitencoding $H &&
git-checkout -b $H C0 &&
echo $H >F &&
- git-commit -a -F ../t3900/$H.txt
+ git-commit -a -F "$TEST_DIRECTORY"/t3900/$H.txt
'
done
@@ -57,13 +57,13 @@ test_expect_success 'config to remove customization' '
'
test_expect_success 'ISO-8859-1 should be shown in UTF-8 now' '
- compare_with ISO-8859-1 ../t3900/1-UTF-8.txt
+ compare_with ISO-8859-1 "$TEST_DIRECTORY"/t3900/1-UTF-8.txt
'
for H in EUCJP ISO-2022-JP
do
test_expect_success "$H should be shown in UTF-8 now" '
- compare_with '$H' ../t3900/2-UTF-8.txt
+ compare_with '$H' "$TEST_DIRECTORY"/t3900/2-UTF-8.txt
'
done
@@ -82,7 +82,7 @@ for H in ISO-8859-1 EUCJP ISO-2022-JP
do
test_expect_success "$H should be shown in itself now" '
git config i18n.commitencoding '$H' &&
- compare_with '$H' ../t3900/'$H'.txt
+ compare_with '$H' "$TEST_DIRECTORY"/t3900/'$H'.txt
'
done
@@ -91,13 +91,13 @@ test_expect_success 'config to tweak customization' '
'
test_expect_success 'ISO-8859-1 should be shown in UTF-8 now' '
- compare_with ISO-8859-1 ../t3900/1-UTF-8.txt
+ compare_with ISO-8859-1 "$TEST_DIRECTORY"/t3900/1-UTF-8.txt
'
for H in EUCJP ISO-2022-JP
do
test_expect_success "$H should be shown in UTF-8 now" '
- compare_with '$H' ../t3900/2-UTF-8.txt
+ compare_with '$H' "$TEST_DIRECTORY"/t3900/2-UTF-8.txt
'
done
@@ -107,7 +107,7 @@ do
for H in EUCJP ISO-2022-JP
do
test_expect_success "$H should be shown in $J now" '
- compare_with '$H' ../t3900/'$J'.txt
+ compare_with '$H' "$TEST_DIRECTORY"/t3900/'$J'.txt
'
done
done
@@ -115,7 +115,7 @@ done
for H in ISO-8859-1 EUCJP ISO-2022-JP
do
test_expect_success "No conversion with $H" '
- compare_with "--encoding=none '$H'" ../t3900/'$H'.txt
+ compare_with "--encoding=none '$H'" "$TEST_DIRECTORY"/t3900/'$H'.txt
'
done
diff --git a/t/t3901-i18n-patch.sh b/t/t3901-i18n-patch.sh
index 235f372832..f68ff53051 100755
--- a/t/t3901-i18n-patch.sh
+++ b/t/t3901-i18n-patch.sh
@@ -35,7 +35,7 @@ test_expect_success setup '
# use UTF-8 in author and committer name to match the
# i18n.commitencoding settings
- . ../t3901-utf8.txt &&
+ . "$TEST_DIRECTORY"/t3901-utf8.txt &&
test_tick &&
echo "$GIT_AUTHOR_NAME" >mine &&
@@ -57,7 +57,7 @@ test_expect_success setup '
# the second one on the side branch is ISO-8859-1
git config i18n.commitencoding ISO-8859-1 &&
# use author and committer name in ISO-8859-1 to match it.
- . ../t3901-8859-1.txt &&
+ . "$TEST_DIRECTORY"/t3901-8859-1.txt &&
test_tick &&
echo Yet another >theirs &&
git add theirs &&
@@ -101,7 +101,7 @@ test_expect_success 'rebase (U/U)' '
# The result will be committed by GIT_COMMITTER_NAME --
# we want UTF-8 encoded name.
- . ../t3901-utf8.txt &&
+ . "$TEST_DIRECTORY"/t3901-utf8.txt &&
git checkout -b test &&
git-rebase master &&
@@ -111,7 +111,7 @@ test_expect_success 'rebase (U/U)' '
test_expect_success 'rebase (U/L)' '
git config i18n.commitencoding UTF-8 &&
git config i18n.logoutputencoding ISO-8859-1 &&
- . ../t3901-utf8.txt &&
+ . "$TEST_DIRECTORY"/t3901-utf8.txt &&
git reset --hard side &&
git-rebase master &&
@@ -123,7 +123,7 @@ test_expect_success 'rebase (L/L)' '
# In this test we want ISO-8859-1 encoded commits as the result
git config i18n.commitencoding ISO-8859-1 &&
git config i18n.logoutputencoding ISO-8859-1 &&
- . ../t3901-8859-1.txt &&
+ . "$TEST_DIRECTORY"/t3901-8859-1.txt &&
git reset --hard side &&
git-rebase master &&
@@ -136,7 +136,7 @@ test_expect_success 'rebase (L/U)' '
# to get ISO-8859-1 results.
git config i18n.commitencoding ISO-8859-1 &&
git config i18n.logoutputencoding UTF-8 &&
- . ../t3901-8859-1.txt &&
+ . "$TEST_DIRECTORY"/t3901-8859-1.txt &&
git reset --hard side &&
git-rebase master &&
@@ -149,7 +149,7 @@ test_expect_success 'cherry-pick(U/U)' '
git config i18n.commitencoding UTF-8 &&
git config i18n.logoutputencoding UTF-8 &&
- . ../t3901-utf8.txt &&
+ . "$TEST_DIRECTORY"/t3901-utf8.txt &&
git reset --hard master &&
git cherry-pick side^ &&
@@ -164,7 +164,7 @@ test_expect_success 'cherry-pick(L/L)' '
git config i18n.commitencoding ISO-8859-1 &&
git config i18n.logoutputencoding ISO-8859-1 &&
- . ../t3901-8859-1.txt &&
+ . "$TEST_DIRECTORY"/t3901-8859-1.txt &&
git reset --hard master &&
git cherry-pick side^ &&
@@ -179,7 +179,7 @@ test_expect_success 'cherry-pick(U/L)' '
git config i18n.commitencoding UTF-8 &&
git config i18n.logoutputencoding ISO-8859-1 &&
- . ../t3901-utf8.txt &&
+ . "$TEST_DIRECTORY"/t3901-utf8.txt &&
git reset --hard master &&
git cherry-pick side^ &&
@@ -195,7 +195,7 @@ test_expect_success 'cherry-pick(L/U)' '
git config i18n.commitencoding ISO-8859-1 &&
git config i18n.logoutputencoding UTF-8 &&
- . ../t3901-8859-1.txt &&
+ . "$TEST_DIRECTORY"/t3901-8859-1.txt &&
git reset --hard master &&
git cherry-pick side^ &&
@@ -208,7 +208,7 @@ test_expect_success 'cherry-pick(L/U)' '
test_expect_success 'rebase --merge (U/U)' '
git config i18n.commitencoding UTF-8 &&
git config i18n.logoutputencoding UTF-8 &&
- . ../t3901-utf8.txt &&
+ . "$TEST_DIRECTORY"/t3901-utf8.txt &&
git reset --hard side &&
git-rebase --merge master &&
@@ -219,7 +219,7 @@ test_expect_success 'rebase --merge (U/U)' '
test_expect_success 'rebase --merge (U/L)' '
git config i18n.commitencoding UTF-8 &&
git config i18n.logoutputencoding ISO-8859-1 &&
- . ../t3901-utf8.txt &&
+ . "$TEST_DIRECTORY"/t3901-utf8.txt &&
git reset --hard side &&
git-rebase --merge master &&
@@ -231,7 +231,7 @@ test_expect_success 'rebase --merge (L/L)' '
# In this test we want ISO-8859-1 encoded commits as the result
git config i18n.commitencoding ISO-8859-1 &&
git config i18n.logoutputencoding ISO-8859-1 &&
- . ../t3901-8859-1.txt &&
+ . "$TEST_DIRECTORY"/t3901-8859-1.txt &&
git reset --hard side &&
git-rebase --merge master &&
@@ -244,7 +244,7 @@ test_expect_success 'rebase --merge (L/U)' '
# to get ISO-8859-1 results.
git config i18n.commitencoding ISO-8859-1 &&
git config i18n.logoutputencoding UTF-8 &&
- . ../t3901-8859-1.txt &&
+ . "$TEST_DIRECTORY"/t3901-8859-1.txt &&
git reset --hard side &&
git-rebase --merge master &&
diff --git a/t/t3902-quoted.sh b/t/t3902-quoted.sh
index fe4fb5116a..5868052425 100755
--- a/t/t3902-quoted.sh
+++ b/t/t3902-quoted.sh
@@ -7,12 +7,6 @@ test_description='quoted output'
. ./test-lib.sh
-P1='pathname with HT'
-: >"$P1" 2>&1 && test -f "$P1" && rm -f "$P1" || {
- echo >&2 'Filesystem does not support HT in names'
- test_done
-}
-
FN='濱野'
GN='純'
HT=' '
@@ -20,7 +14,7 @@ LF='
'
DQ='"'
-echo foo > "Name and an${HT}HT"
+echo foo 2>/dev/null > "Name and an${HT}HT"
test -f "Name and an${HT}HT" || {
# since FAT/NTFS does not allow tabs in filenames, skip this test
say 'Your filesystem does not allow tabs in filenames, test skipped.'
diff --git a/t/t4000-diff-format.sh b/t/t4000-diff-format.sh
index c44b27aeb2..6ddd46915d 100755
--- a/t/t4000-diff-format.sh
+++ b/t/t4000-diff-format.sh
@@ -7,7 +7,7 @@ test_description='Test built-in diff output engine.
'
. ./test-lib.sh
-. ../diff-lib.sh
+. "$TEST_DIRECTORY"/diff-lib.sh
echo >path0 'Line 1
Line 2
diff --git a/t/t4001-diff-rename.sh b/t/t4001-diff-rename.sh
index a32692417d..71bac83dd5 100755
--- a/t/t4001-diff-rename.sh
+++ b/t/t4001-diff-rename.sh
@@ -7,7 +7,7 @@ test_description='Test rename detection in diff engine.
'
. ./test-lib.sh
-. ../diff-lib.sh
+. "$TEST_DIRECTORY"/diff-lib.sh
echo >path0 'Line 1
Line 2
diff --git a/t/t4002-diff-basic.sh b/t/t4002-diff-basic.sh
index a4cfde6b29..cc3681f161 100755
--- a/t/t4002-diff-basic.sh
+++ b/t/t4002-diff-basic.sh
@@ -7,7 +7,7 @@ test_description='Test diff raw-output.
'
. ./test-lib.sh
-. ../lib-read-tree-m-3way.sh
+. "$TEST_DIRECTORY"/lib-read-tree-m-3way.sh
cat >.test-plain-OA <<\EOF
:000000 100644 0000000000000000000000000000000000000000 ccba72ad3888a3520b39efcf780b9ee64167535d A AA
@@ -169,6 +169,20 @@ test_expect_success \
cmp -s .test-a .test-recursive-AB'
test_expect_success \
+ 'diff-tree --stdin of known trees.' \
+ 'echo $tree_A $tree_B | git diff-tree --stdin > .test-a &&
+ echo $tree_A $tree_B > .test-plain-ABx &&
+ cat .test-plain-AB >> .test-plain-ABx &&
+ cmp -s .test-a .test-plain-ABx'
+
+test_expect_success \
+ 'diff-tree --stdin of known trees.' \
+ 'echo $tree_A $tree_B | git diff-tree -r --stdin > .test-a &&
+ echo $tree_A $tree_B > .test-recursive-ABx &&
+ cat .test-recursive-AB >> .test-recursive-ABx &&
+ cmp -s .test-a .test-recursive-ABx'
+
+test_expect_success \
'diff-cache O with A in cache' \
'git read-tree $tree_A &&
git diff-index --cached $tree_O >.test-a &&
diff --git a/t/t4003-diff-rename-1.sh b/t/t4003-diff-rename-1.sh
index 8b1f875286..c6130c4019 100755
--- a/t/t4003-diff-rename-1.sh
+++ b/t/t4003-diff-rename-1.sh
@@ -7,11 +7,11 @@ test_description='More rename detection
'
. ./test-lib.sh
-. ../diff-lib.sh ;# test-lib chdir's into trash
+. "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash
test_expect_success \
'prepare reference tree' \
- 'cat ../../COPYING >COPYING &&
+ 'cat "$TEST_DIRECTORY"/../COPYING >COPYING &&
echo frotz >rezrov &&
git update-index --add COPYING rezrov &&
tree=$(git write-tree) &&
@@ -99,7 +99,7 @@ test_expect_success \
test_expect_success \
'prepare work tree once again' \
- 'cat ../../COPYING >COPYING &&
+ 'cat "$TEST_DIRECTORY"/../COPYING >COPYING &&
git update-index --add --remove COPYING COPYING.1'
# tree has COPYING and rezrov. work tree has COPYING and COPYING.1,
diff --git a/t/t4004-diff-rename-symlink.sh b/t/t4004-diff-rename-symlink.sh
index 3d25be7a67..b35af9b42d 100755
--- a/t/t4004-diff-rename-symlink.sh
+++ b/t/t4004-diff-rename-symlink.sh
@@ -10,7 +10,7 @@ copy of symbolic links, but should not produce rename/copy followed
by an edit for them.
'
. ./test-lib.sh
-. ../diff-lib.sh
+. "$TEST_DIRECTORY"/diff-lib.sh
test_expect_success \
'prepare reference tree' \
diff --git a/t/t4005-diff-rename-2.sh b/t/t4005-diff-rename-2.sh
index 6630017312..1ba359d478 100755
--- a/t/t4005-diff-rename-2.sh
+++ b/t/t4005-diff-rename-2.sh
@@ -7,11 +7,11 @@ test_description='Same rename detection as t4003 but testing diff-raw.
'
. ./test-lib.sh
-. ../diff-lib.sh ;# test-lib chdir's into trash
+. "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash
test_expect_success \
'prepare reference tree' \
- 'cat ../../COPYING >COPYING &&
+ 'cat "$TEST_DIRECTORY"/../COPYING >COPYING &&
echo frotz >rezrov &&
git update-index --add COPYING rezrov &&
tree=$(git write-tree) &&
@@ -71,7 +71,7 @@ test_expect_success \
test_expect_success \
'prepare work tree once again' \
- 'cat ../../COPYING >COPYING &&
+ 'cat "$TEST_DIRECTORY"/../COPYING >COPYING &&
git update-index --add --remove COPYING COPYING.1'
git diff-index -C --find-copies-harder $tree >current
diff --git a/t/t4007-rename-3.sh b/t/t4007-rename-3.sh
index 104a4e1492..42072d724e 100755
--- a/t/t4007-rename-3.sh
+++ b/t/t4007-rename-3.sh
@@ -7,12 +7,12 @@ test_description='Rename interaction with pathspec.
'
. ./test-lib.sh
-. ../diff-lib.sh ;# test-lib chdir's into trash
+. "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash
test_expect_success \
'prepare reference tree' \
'mkdir path0 path1 &&
- cp ../../COPYING path0/COPYING &&
+ cp "$TEST_DIRECTORY"/../COPYING path0/COPYING &&
git update-index --add path0/COPYING &&
tree=$(git write-tree) &&
echo $tree'
diff --git a/t/t4008-diff-break-rewrite.sh b/t/t4008-diff-break-rewrite.sh
index 26c2e4aa65..7e343a9cd1 100755
--- a/t/t4008-diff-break-rewrite.sh
+++ b/t/t4008-diff-break-rewrite.sh
@@ -22,12 +22,12 @@ four changes in total.
Further, with -B and -M together, these should turn into two renames.
'
. ./test-lib.sh
-. ../diff-lib.sh ;# test-lib chdir's into trash
+. "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash
test_expect_success \
setup \
- 'cat ../../README >file0 &&
- cat ../../COPYING >file1 &&
+ 'cat "$TEST_DIRECTORY"/../README >file0 &&
+ cat "$TEST_DIRECTORY"/../COPYING >file1 &&
git update-index --add file0 file1 &&
tree=$(git write-tree) &&
echo "$tree"'
diff --git a/t/t4009-diff-rename-4.sh b/t/t4009-diff-rename-4.sh
index d2b45e7b8f..de3f17478e 100755
--- a/t/t4009-diff-rename-4.sh
+++ b/t/t4009-diff-rename-4.sh
@@ -7,11 +7,11 @@ test_description='Same rename detection as t4003 but testing diff-raw -z.
'
. ./test-lib.sh
-. ../diff-lib.sh ;# test-lib chdir's into trash
+. "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash
test_expect_success \
'prepare reference tree' \
- 'cat ../../COPYING >COPYING &&
+ 'cat "$TEST_DIRECTORY"/../COPYING >COPYING &&
echo frotz >rezrov &&
git update-index --add COPYING rezrov &&
tree=$(git write-tree) &&
@@ -78,7 +78,7 @@ test_expect_success \
test_expect_success \
'prepare work tree once again' \
- 'cat ../../COPYING >COPYING &&
+ 'cat "$TEST_DIRECTORY"/../COPYING >COPYING &&
git update-index --add --remove COPYING COPYING.1'
git diff-index -z -C --find-copies-harder $tree >current
diff --git a/t/t4010-diff-pathspec.sh b/t/t4010-diff-pathspec.sh
index ad3d9e4845..9322298ecc 100755
--- a/t/t4010-diff-pathspec.sh
+++ b/t/t4010-diff-pathspec.sh
@@ -10,7 +10,7 @@ Prepare:
path1/file1
'
. ./test-lib.sh
-. ../diff-lib.sh ;# test-lib chdir's into trash
+. "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash
test_expect_success \
setup \
diff --git a/t/t4011-diff-symlink.sh b/t/t4011-diff-symlink.sh
index c6d13693ba..02efecae3a 100755
--- a/t/t4011-diff-symlink.sh
+++ b/t/t4011-diff-symlink.sh
@@ -7,7 +7,7 @@ test_description='Test diff of symlinks.
'
. ./test-lib.sh
-. ../diff-lib.sh
+. "$TEST_DIRECTORY"/diff-lib.sh
cat > expected << EOF
diff --git a/frotz b/frotz
diff --git a/t/t4012-diff-binary.sh b/t/t4012-diff-binary.sh
index eced1f30fb..69934991cb 100755
--- a/t/t4012-diff-binary.sh
+++ b/t/t4012-diff-binary.sh
@@ -12,7 +12,7 @@ test_expect_success 'prepare repository' \
'echo AIT >a && echo BIT >b && echo CIT >c && echo DIT >d &&
git update-index --add a b c d &&
echo git >a &&
- cat ../test4012.png >b &&
+ cat "$TEST_DIRECTORY"/test4012.png >b &&
echo git >c &&
cat b b >d'
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index 9337b81064..1a6b52234d 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -99,7 +99,7 @@ do
test=`echo "$cmd" | sed -e 's|[/ ][/ ]*|_|g'`
cnt=`expr $test_count + 1`
pfx=`printf "%04d" $cnt`
- expect="../t4013/diff.$test"
+ expect="$TEST_DIRECTORY/t4013/diff.$test"
actual="$pfx-diff.$test"
test_expect_success "git $cmd" '
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index 7fe853c20d..9d99dc2887 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -230,4 +230,29 @@ test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
'
+cat > expect << EOF
+---
+ file | 16 ++++++++++++++++
+ 1 files changed, 16 insertions(+), 0 deletions(-)
+
+diff --git a/file b/file
+index 40f36c6..2dc5c23 100644
+--- a/file
++++ b/file
+@@ -13,4 +13,20 @@ C
+ 10
+ D
+ E
+ F
++5
+EOF
+
+test_expect_success 'format-patch respects -U' '
+
+ git format-patch -U4 -2 &&
+ sed -e "1,/^$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
+ test_cmp expect output
+
+'
+
test_done
diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh
index ec98509fd2..fc2307eaa3 100755
--- a/t/t4015-diff-whitespace.sh
+++ b/t/t4015-diff-whitespace.sh
@@ -7,7 +7,7 @@ test_description='Test special whitespace in diff engine.
'
. ./test-lib.sh
-. ../diff-lib.sh
+. "$TEST_DIRECTORY"/diff-lib.sh
# Ray Lehtiniemi's example
@@ -352,4 +352,20 @@ test_expect_success 'checkdiff allows new blank lines' '
git diff --check
'
+test_expect_success 'combined diff with autocrlf conversion' '
+
+ git reset --hard &&
+ echo >x hello &&
+ git commit -m "one side" x &&
+ git checkout HEAD^ &&
+ echo >x goodbye &&
+ git commit -m "the other side" x &&
+ git config core.autocrlf true &&
+ test_must_fail git merge master &&
+
+ git diff | sed -e "1,/^@@@/d" >actual &&
+ ! grep "^-" actual
+
+'
+
test_done
diff --git a/t/t4016-diff-quote.sh b/t/t4016-diff-quote.sh
index f07035ab7e..55eb5f83f1 100755
--- a/t/t4016-diff-quote.sh
+++ b/t/t4016-diff-quote.sh
@@ -13,8 +13,8 @@ P1='pathname with HT'
P2='pathname with SP'
P3='pathname
with LF'
-: >"$P1" 2>&1 && test -f "$P1" && rm -f "$P1" || {
- echo >&2 'Filesystem does not support tabs in names'
+: 2>/dev/null >"$P1" && test -f "$P1" && rm -f "$P1" || {
+ say 'Your filesystem does not allow tabs in filenames, test skipped.'
test_done
}
diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh
index 637b4e19d5..dfe3fbc74b 100755
--- a/t/t4020-diff-external.sh
+++ b/t/t4020-diff-external.sh
@@ -104,7 +104,7 @@ echo NULZbetweenZwords | perl -pe 'y/Z/\000/' > file
test_expect_success 'force diff with "diff"' '
echo >.gitattributes "file diff" &&
git diff >actual &&
- test_cmp ../t4020/diff.NUL actual
+ test_cmp "$TEST_DIRECTORY"/t4020/diff.NUL actual
'
test_done
diff --git a/t/t4022-diff-rewrite.sh b/t/t4022-diff-rewrite.sh
index bf996fc414..2a537a21e8 100755
--- a/t/t4022-diff-rewrite.sh
+++ b/t/t4022-diff-rewrite.sh
@@ -6,12 +6,12 @@ test_description='rewrite diff'
test_expect_success setup '
- cat ../../COPYING >test &&
+ cat "$TEST_DIRECTORY"/../COPYING >test &&
git add test &&
tr \
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" \
"nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM" \
- <../../COPYING >test
+ <"$TEST_DIRECTORY"/../COPYING >test
'
diff --git a/t/t4023-diff-rename-typechange.sh b/t/t4023-diff-rename-typechange.sh
index 4dbfc6e8b7..297ddb5a25 100755
--- a/t/t4023-diff-rename-typechange.sh
+++ b/t/t4023-diff-rename-typechange.sh
@@ -7,21 +7,21 @@ test_description='typechange rename detection'
test_expect_success setup '
rm -f foo bar &&
- cat ../../COPYING >foo &&
+ cat "$TEST_DIRECTORY"/../COPYING >foo &&
ln -s linklink bar &&
git add foo bar &&
git commit -a -m Initial &&
git tag one &&
rm -f foo bar &&
- cat ../../COPYING >bar &&
+ cat "$TEST_DIRECTORY"/../COPYING >bar &&
ln -s linklink foo &&
git add foo bar &&
git commit -a -m Second &&
git tag two &&
rm -f foo bar &&
- cat ../../COPYING >foo &&
+ cat "$TEST_DIRECTORY"/../COPYING >foo &&
git add foo &&
git commit -a -m Third &&
git tag three &&
@@ -35,15 +35,15 @@ test_expect_success setup '
# This is purely for sanity check
rm -f foo bar &&
- cat ../../COPYING >foo &&
- cat ../../Makefile >bar &&
+ cat "$TEST_DIRECTORY"/../COPYING >foo &&
+ cat "$TEST_DIRECTORY"/../Makefile >bar &&
git add foo bar &&
git commit -a -m Fifth &&
git tag five &&
rm -f foo bar &&
- cat ../../Makefile >foo &&
- cat ../../COPYING >bar &&
+ cat "$TEST_DIRECTORY"/../Makefile >foo &&
+ cat "$TEST_DIRECTORY"/../COPYING >bar &&
git add foo bar &&
git commit -a -m Sixth &&
git tag six
diff --git a/t/t4027-diff-submodule.sh b/t/t4027-diff-submodule.sh
index ba6679c6e4..1c2edebb09 100755
--- a/t/t4027-diff-submodule.sh
+++ b/t/t4027-diff-submodule.sh
@@ -3,7 +3,7 @@
test_description='difference in submodules'
. ./test-lib.sh
-. ../diff-lib.sh
+. "$TEST_DIRECTORY"/diff-lib.sh
_z40=0000000000000000000000000000000000000000
test_expect_success setup '
diff --git a/t/t4029-diff-trailing-space.sh b/t/t4029-diff-trailing-space.sh
new file mode 100755
index 0000000000..4ca65e0332
--- /dev/null
+++ b/t/t4029-diff-trailing-space.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+#
+# Copyright (c) Jim Meyering
+#
+test_description='diff honors config option, diff.suppress-blank-empty'
+
+. ./test-lib.sh
+
+cat <<\EOF > exp ||
+diff --git a/f b/f
+index 5f6a263..8cb8bae 100644
+--- a/f
++++ b/f
+@@ -1,2 +1,2 @@
+
+-x
++y
+EOF
+exit 1
+
+test_expect_success \
+ "$test_description" \
+ 'printf "\nx\n" > f &&
+ git add f &&
+ git commit -q -m. f &&
+ printf "\ny\n" > f &&
+ git config --bool diff.suppress-blank-empty true &&
+ git diff f > actual &&
+ test_cmp exp actual &&
+ perl -i.bak -p -e "s/^\$/ /" exp &&
+ git config --bool diff.suppress-blank-empty false &&
+ git diff f > actual &&
+ test_cmp exp actual &&
+ git config --bool --unset diff.suppress-blank-empty &&
+ git diff f > actual &&
+ test_cmp exp actual
+ '
+
+test_done
diff --git a/t/t4100-apply-stat.sh b/t/t4100-apply-stat.sh
index e0c67740a5..9b433de836 100755
--- a/t/t4100-apply-stat.sh
+++ b/t/t4100-apply-stat.sh
@@ -17,13 +17,13 @@ do
test_expect_success "$title" '
git apply --stat --summary \
<"$TEST_DIRECTORY/t4100/t-apply-$num.patch" >current &&
- test_cmp ../t4100/t-apply-$num.expect current
+ test_cmp "$TEST_DIRECTORY"/t4100/t-apply-$num.expect current
'
test_expect_success "$title with recount" '
sed -e "$UNC" <"$TEST_DIRECTORY/t4100/t-apply-$num.patch" |
git apply --recount --stat --summary >current &&
- test_cmp ../t4100/t-apply-$num.expect current
+ test_cmp "$TEST_DIRECTORY"/t4100/t-apply-$num.expect current
'
done <<\EOF
rename
diff --git a/t/t4101-apply-nonl.sh b/t/t4101-apply-nonl.sh
index da8abcf364..e3443d004d 100755
--- a/t/t4101-apply-nonl.sh
+++ b/t/t4101-apply-nonl.sh
@@ -21,9 +21,10 @@ do
do
test $i -eq $j && continue
cat frotz.$i >frotz
- test_expect_success \
- "apply diff between $i and $j" \
- "git apply <../t4101/diff.$i-$j && diff frotz.$j frotz"
+ test_expect_success "apply diff between $i and $j" '
+ git apply <"$TEST_DIRECTORY"/t4101/diff.$i-$j &&
+ test_cmp frotz.$j frotz
+ '
done
done
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index 4c8af45f83..0ab925c4e4 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -69,7 +69,29 @@ test_expect_success 'diff-filter=D' '
'
+test_expect_success 'setup case sensitivity tests' '
+ echo case >one &&
+ test_tick &&
+ git commit -a -m Second
+'
+
+test_expect_success 'log --grep' '
+ echo second >expect &&
+ git log -1 --pretty="tformat:%s" --grep=sec >actual &&
+ test_cmp expect actual
+'
+test_expect_success 'log -i --grep' '
+ echo Second >expect &&
+ git log -1 --pretty="tformat:%s" -i --grep=sec >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'log --grep -i' '
+ echo Second >expect &&
+ git log -1 --pretty="tformat:%s" --grep=sec -i >actual &&
+ test_cmp expect actual
+'
test_done
diff --git a/t/t5100-mailinfo.sh b/t/t5100-mailinfo.sh
index 198e3503d5..fe14589427 100755
--- a/t/t5100-mailinfo.sh
+++ b/t/t5100-mailinfo.sh
@@ -8,27 +8,28 @@ test_description='git mailinfo and git mailsplit test'
. ./test-lib.sh
test_expect_success 'split sample box' \
- 'git mailsplit -o. ../t5100/sample.mbox >last &&
+ 'git mailsplit -o. "$TEST_DIRECTORY"/t5100/sample.mbox >last &&
last=`cat last` &&
echo total is $last &&
test `cat last` = 11'
for mail in `echo 00*`
do
- test_expect_success "mailinfo $mail" \
- "git mailinfo -u msg$mail patch$mail <$mail >info$mail &&
+ test_expect_success "mailinfo $mail" '
+ git mailinfo -u msg$mail patch$mail <$mail >info$mail &&
echo msg &&
- diff ../t5100/msg$mail msg$mail &&
+ test_cmp "$TEST_DIRECTORY"/t5100/msg$mail msg$mail &&
echo patch &&
- diff ../t5100/patch$mail patch$mail &&
+ test_cmp "$TEST_DIRECTORY"/t5100/patch$mail patch$mail &&
echo info &&
- diff ../t5100/info$mail info$mail"
+ test_cmp "$TEST_DIRECTORY"/t5100/info$mail info$mail
+ '
done
test_expect_success 'respect NULs' '
- git mailsplit -d3 -o. ../t5100/nul-plain &&
- cmp ../t5100/nul-plain 001 &&
+ git mailsplit -d3 -o. "$TEST_DIRECTORY"/t5100/nul-plain &&
+ test_cmp "$TEST_DIRECTORY"/t5100/nul-plain 001 &&
(cat 001 | git mailinfo msg patch) &&
test 4 = $(wc -l < patch)
@@ -36,10 +37,10 @@ test_expect_success 'respect NULs' '
test_expect_success 'Preserve NULs out of MIME encoded message' '
- git mailsplit -d5 -o. ../t5100/nul-b64.in &&
- cmp ../t5100/nul-b64.in 00001 &&
+ git mailsplit -d5 -o. "$TEST_DIRECTORY"/t5100/nul-b64.in &&
+ test_cmp "$TEST_DIRECTORY"/t5100/nul-b64.in 00001 &&
git mailinfo msg patch <00001 &&
- cmp ../t5100/nul-b64.expect patch
+ test_cmp "$TEST_DIRECTORY"/t5100/nul-b64.expect patch
'
diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh
index 362cf7e928..7125baebb8 100755
--- a/t/t5500-fetch-pack.sh
+++ b/t/t5500-fetch-pack.sh
@@ -137,7 +137,7 @@ test_expect_success "clone shallow object count" \
"test \"in-pack: 18\" = \"$(grep in-pack count.shallow)\""
count_output () {
- sed -e '/^in-pack:/d' -e '/^packs:/d' -e '/: 0$/d' "$1"
+ sed -e '/^in-pack:/d' -e '/^packs:/d' -e '/^size-pack:/d' -e '/: 0$/d' "$1"
}
test_expect_success "clone shallow object count (part 2)" '
diff --git a/t/t5515-fetch-merge-logic.sh b/t/t5515-fetch-merge-logic.sh
index 8becbc3f38..1f4608d8ba 100755
--- a/t/t5515-fetch-merge-logic.sh
+++ b/t/t5515-fetch-merge-logic.sh
@@ -131,9 +131,9 @@ do
test=`echo "$cmd" | sed -e 's|[/ ][/ ]*|_|g'`
cnt=`expr $test_count + 1`
pfx=`printf "%04d" $cnt`
- expect_f="../../t5515/fetch.$test"
+ expect_f="$TEST_DIRECTORY/t5515/fetch.$test"
actual_f="$pfx-fetch.$test"
- expect_r="../../t5515/refs.$test"
+ expect_r="$TEST_DIRECTORY/t5515/refs.$test"
actual_r="$pfx-refs.$test"
test_expect_success "$cmd" '
diff --git a/t/t5540-http-push.sh b/t/t5540-http-push.sh
index b0d242e3ed..da9588645c 100755
--- a/t/t5540-http-push.sh
+++ b/t/t5540-http-push.sh
@@ -19,7 +19,7 @@ then
exit
fi
-. ../lib-httpd.sh
+. "$TEST_DIRECTORY"/lib-httpd.sh
if ! start_httpd >&3 2>&4
then
diff --git a/t/t6002-rev-list-bisect.sh b/t/t6002-rev-list-bisect.sh
index 8f5de097ec..b4e8fbaa5e 100755
--- a/t/t6002-rev-list-bisect.sh
+++ b/t/t6002-rev-list-bisect.sh
@@ -5,7 +5,7 @@
test_description='Tests git rev-list --bisect functionality'
. ./test-lib.sh
-. ../t6000lib.sh # t6xxx specific functions
+. "$TEST_DIRECTORY"/t6000lib.sh # t6xxx specific functions
# usage: test_bisection max-diff bisect-option head ^prune...
#
diff --git a/t/t6003-rev-list-topo-order.sh b/t/t6003-rev-list-topo-order.sh
index 5daa0be8cc..2c73f2da7b 100755
--- a/t/t6003-rev-list-topo-order.sh
+++ b/t/t6003-rev-list-topo-order.sh
@@ -6,7 +6,7 @@
test_description='Tests git rev-list --topo-order functionality'
. ./test-lib.sh
-. ../t6000lib.sh # t6xxx specific functions
+. "$TEST_DIRECTORY"/t6000lib.sh # t6xxx specific functions
list_duplicates()
{
diff --git a/t/t6010-merge-base.sh b/t/t6010-merge-base.sh
index b6e57b2426..04e4b7c5c2 100755
--- a/t/t6010-merge-base.sh
+++ b/t/t6010-merge-base.sh
@@ -108,4 +108,52 @@ test_expect_success 'compute merge-base (all)' \
'MB=$(git merge-base --all PL PR) &&
expr "$(git name-rev "$MB")" : "[0-9a-f]* tags/C2"'
+# Another set to demonstrate base between one commit and a merge
+# in the documentation.
+
+test_expect_success 'merge-base for octopus-step (setup)' '
+ test_tick && git commit --allow-empty -m root && git tag MMR &&
+ test_tick && git commit --allow-empty -m 1 && git tag MM1 &&
+ test_tick && git commit --allow-empty -m o &&
+ test_tick && git commit --allow-empty -m o &&
+ test_tick && git commit --allow-empty -m o &&
+ test_tick && git commit --allow-empty -m A && git tag MMA &&
+ git checkout MM1 &&
+ test_tick && git commit --allow-empty -m o &&
+ test_tick && git commit --allow-empty -m o &&
+ test_tick && git commit --allow-empty -m o &&
+ test_tick && git commit --allow-empty -m B && git tag MMB &&
+ git checkout MMR &&
+ test_tick && git commit --allow-empty -m o &&
+ test_tick && git commit --allow-empty -m o &&
+ test_tick && git commit --allow-empty -m o &&
+ test_tick && git commit --allow-empty -m o &&
+ test_tick && git commit --allow-empty -m C && git tag MMC
+'
+
+test_expect_success 'merge-base A B C' '
+ MB=$(git merge-base --all MMA MMB MMC) &&
+ MM1=$(git rev-parse --verify MM1) &&
+ test "$MM1" = "$MB"
+'
+
+test_expect_success 'criss-cross merge-base for octopus-step (setup)' '
+ git reset --hard MMR &&
+ test_tick && git commit --allow-empty -m 1 && git tag CC1 &&
+ git reset --hard E &&
+ test_tick && git commit --allow-empty -m 2 && git tag CC2 &&
+ test_tick && git merge -s ours CC1 &&
+ test_tick && git commit --allow-empty -m o &&
+ test_tick && git commit --allow-empty -m B && git tag CCB &&
+ git reset --hard CC1 &&
+ test_tick && git merge -s ours CC2 &&
+ test_tick && git commit --allow-empty -m A && git tag CCA
+'
+
+test_expect_success 'merge-base B A^^ A^^2' '
+ MB0=$(git merge-base --all CCB CCA^^ CCA^^2 | sort) &&
+ MB1=$(git rev-parse CC1 CC2 | sort) &&
+ test "$MB0" = "$MB1"
+'
+
test_done
diff --git a/t/t6023-merge-file.sh b/t/t6023-merge-file.sh
index f674c48cab..42620e0732 100755
--- a/t/t6023-merge-file.sh
+++ b/t/t6023-merge-file.sh
@@ -136,7 +136,7 @@ test_expect_success "expected conflict markers" "test_cmp expect out"
test_expect_success 'binary files cannot be merged' '
test_must_fail git merge-file -p \
- orig.txt ../test4012.png new1.txt 2> merge.err &&
+ orig.txt "$TEST_DIRECTORY"/test4012.png new1.txt 2> merge.err &&
grep "Cannot merge binary files" merge.err
'
diff --git a/t/t6027-merge-binary.sh b/t/t6027-merge-binary.sh
index 92ca1f0f8c..b519626ca0 100755
--- a/t/t6027-merge-binary.sh
+++ b/t/t6027-merge-binary.sh
@@ -6,7 +6,7 @@ test_description='ask merge-recursive to merge binary files'
test_expect_success setup '
- cat ../test4012.png >m &&
+ cat "$TEST_DIRECTORY"/test4012.png >m &&
git add m &&
git ls-files -s | sed -e "s/ 0 / 1 /" >E1 &&
test_tick &&
diff --git a/t/t6101-rev-parse-parents.sh b/t/t6101-rev-parse-parents.sh
index 919552a2fc..f105fab98e 100755
--- a/t/t6101-rev-parse-parents.sh
+++ b/t/t6101-rev-parse-parents.sh
@@ -6,7 +6,7 @@
test_description='Test git rev-parse with different parent options'
. ./test-lib.sh
-. ../t6000lib.sh # t6xxx specific functions
+. "$TEST_DIRECTORY"/t6000lib.sh # t6xxx specific functions
date >path0
git update-index --add path0
diff --git a/t/t6200-fmt-merge-msg.sh b/t/t6200-fmt-merge-msg.sh
index bc74349416..8f5a06f7dd 100755
--- a/t/t6200-fmt-merge-msg.sh
+++ b/t/t6200-fmt-merge-msg.sh
@@ -83,13 +83,13 @@ test_expect_success 'merge-msg test #1' '
'
cat >expected <<EOF
-Merge branch 'left' of ../$test
+Merge branch 'left' of $TEST_DIRECTORY/$test
EOF
test_expect_success 'merge-msg test #2' '
git checkout master &&
- git fetch ../"$test" left &&
+ git fetch "$TEST_DIRECTORY/$test" left &&
git fmt-merge-msg <.git/FETCH_HEAD >actual &&
test_cmp expected actual
diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh
index 910a28c7e2..78167980b3 100755
--- a/t/t7001-mv.sh
+++ b/t/t7001-mv.sh
@@ -6,7 +6,7 @@ test_description='git mv in subdirs'
test_expect_success \
'prepare reference tree' \
'mkdir path0 path1 &&
- cp ../../COPYING path0/COPYING &&
+ cp "$TEST_DIRECTORY"/../COPYING path0/COPYING &&
git add path0/COPYING &&
git-commit -m add -a'
@@ -40,7 +40,7 @@ test_expect_success \
test_expect_success \
'adding another file' \
- 'cp ../../README path0/README &&
+ 'cp "$TEST_DIRECTORY"/../README path0/README &&
git add path0/README &&
git-commit -m add2 -a'
diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh
index a0ab096c8f..f92d414e63 100755
--- a/t/t7003-filter-branch.sh
+++ b/t/t7003-filter-branch.sh
@@ -250,4 +250,12 @@ test_expect_success 'Tag name filtering strips gpg signature' '
test_cmp expect actual
'
+test_expect_success 'Tag name filtering allows slashes in tag names' '
+ git tag -m tag-with-slash X/1 &&
+ git cat-file tag X/1 | sed -e s,X/1,X/2, > expect &&
+ git filter-branch -f --tag-name-filter "echo X/2" &&
+ git cat-file tag X/2 > actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index 8d44c2ed1f..198244c57d 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -625,7 +625,7 @@ esac
# Name and email: C O Mitter <committer@example.com>
# No password given, to enable non-interactive operation.
-cp -R ../t7004 ./gpghome
+cp -R "$TEST_DIRECTORY"/t7004 ./gpghome
chmod 0700 gpghome
GNUPGHOME="$(pwd)/gpghome"
export GNUPGHOME
diff --git a/t/t7101-reset.sh b/t/t7101-reset.sh
index 0d9874bfd7..ffaeb3983a 100755
--- a/t/t7101-reset.sh
+++ b/t/t7101-reset.sh
@@ -9,7 +9,7 @@ test_description='git-reset should cull empty subdirs'
test_expect_success \
'creating initial files' \
'mkdir path0 &&
- cp ../../COPYING path0/COPYING &&
+ cp "$TEST_DIRECTORY"/../COPYING path0/COPYING &&
git add path0/COPYING &&
git-commit -m add -a'
@@ -17,10 +17,10 @@ test_expect_success \
'creating second files' \
'mkdir path1 &&
mkdir path1/path2 &&
- cp ../../COPYING path1/path2/COPYING &&
- cp ../../COPYING path1/COPYING &&
- cp ../../COPYING COPYING &&
- cp ../../COPYING path0/COPYING-TOO &&
+ cp "$TEST_DIRECTORY"/../COPYING path1/path2/COPYING &&
+ cp "$TEST_DIRECTORY"/../COPYING path1/COPYING &&
+ cp "$TEST_DIRECTORY"/../COPYING COPYING &&
+ cp "$TEST_DIRECTORY"/../COPYING path0/COPYING-TOO &&
git add path1/path2/COPYING &&
git add path1/COPYING &&
git add COPYING &&
diff --git a/t/t7201-co.sh b/t/t7201-co.sh
index 9ad5d635a2..1dff84d2fd 100755
--- a/t/t7201-co.sh
+++ b/t/t7201-co.sh
@@ -337,4 +337,36 @@ test_expect_success \
test refs/heads/delete-me = "$(git symbolic-ref HEAD)" &&
test_must_fail git checkout --track -b track'
+test_expect_success \
+ 'checkout with --track fakes a sensible -b <name>' '
+ git update-ref refs/remotes/origin/koala/bear renamer &&
+ git update-ref refs/new/koala/bear renamer &&
+
+ git checkout --track origin/koala/bear &&
+ test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
+
+ git checkout master && git branch -D koala/bear &&
+
+ git checkout --track refs/remotes/origin/koala/bear &&
+ test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
+
+ git checkout master && git branch -D koala/bear &&
+
+ git checkout --track remotes/origin/koala/bear &&
+ test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
+
+ git checkout master && git branch -D koala/bear &&
+
+ git checkout --track refs/new/koala/bear &&
+ test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)"
+'
+
+test_expect_success \
+ 'checkout with --track, but without -b, fails with too short tracked name' '
+ test_must_fail git checkout --track renamer'
+
test_done
diff --git a/t/t7500-commit.sh b/t/t7500-commit.sh
index 809bdba630..7ae0bd0e31 100755
--- a/t/t7500-commit.sh
+++ b/t/t7500-commit.sh
@@ -46,15 +46,24 @@ test_expect_success 'unedited template with comments should not commit' '
'
test_expect_success 'a Signed-off-by line by itself should not commit' '
- ! GIT_EDITOR=../t7500/add-signed-off git commit --template "$TEMPLATE"
+ (
+ test_set_editor "$TEST_DIRECTORY"/t7500/add-signed-off &&
+ test_must_fail git commit --template "$TEMPLATE"
+ )
'
test_expect_success 'adding comments to a template should not commit' '
- ! GIT_EDITOR=../t7500/add-comments git commit --template "$TEMPLATE"
+ (
+ test_set_editor "$TEST_DIRECTORY"/t7500/add-comments &&
+ test_must_fail git commit --template "$TEMPLATE"
+ )
'
test_expect_success 'adding real content to a template should commit' '
- GIT_EDITOR=../t7500/add-content git commit --template "$TEMPLATE" &&
+ (
+ test_set_editor "$TEST_DIRECTORY"/t7500/add-content &&
+ git commit --template "$TEMPLATE"
+ ) &&
commit_msg_is "template linecommit message"
'
@@ -62,7 +71,10 @@ test_expect_success '-t option should be short for --template' '
echo "short template" > "$TEMPLATE" &&
echo "new content" >> foo &&
git add foo &&
- GIT_EDITOR=../t7500/add-content git commit -t "$TEMPLATE" &&
+ (
+ test_set_editor "$TEST_DIRECTORY"/t7500/add-content &&
+ git commit -t "$TEMPLATE"
+ ) &&
commit_msg_is "short templatecommit message"
'
@@ -71,7 +83,10 @@ test_expect_success 'config-specified template should commit' '
git config commit.template "$TEMPLATE" &&
echo "more content" >> foo &&
git add foo &&
- GIT_EDITOR=../t7500/add-content git commit &&
+ (
+ test_set_editor "$TEST_DIRECTORY"/t7500/add-content &&
+ git commit
+ ) &&
git config --unset commit.template &&
commit_msg_is "new templatecommit message"
'
@@ -79,7 +94,7 @@ test_expect_success 'config-specified template should commit' '
test_expect_success 'explicit commit message should override template' '
echo "still more content" >> foo &&
git add foo &&
- GIT_EDITOR=../t7500/add-content git commit --template "$TEMPLATE" \
+ GIT_EDITOR="$TEST_DIRECTORY"/t7500/add-content git commit --template "$TEMPLATE" \
-m "command line msg" &&
commit_msg_is "command line msg"
'
@@ -88,8 +103,10 @@ test_expect_success 'commit message from file should override template' '
echo "content galore" >> foo &&
git add foo &&
echo "standard input msg" |
- GIT_EDITOR=../t7500/add-content git commit \
- --template "$TEMPLATE" --file - &&
+ (
+ test_set_editor "$TEST_DIRECTORY"/t7500/add-content &&
+ git commit --template "$TEMPLATE" --file -
+ ) &&
commit_msg_is "standard input msg"
'
@@ -132,10 +149,12 @@ EOF
test_expect_success '--signoff' '
echo "yet another content *narf*" >> foo &&
- echo "zort" |
- GIT_EDITOR=../t7500/add-content git commit -s -F - foo &&
+ echo "zort" | (
+ test_set_editor "$TEST_DIRECTORY"/t7500/add-content &&
+ git commit -s -F - foo
+ ) &&
git cat-file commit HEAD | sed "1,/^$/d" > output &&
- diff expect output
+ test_cmp expect output
'
test_expect_success 'commit message from file (1)' '
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index fee8fb77d4..dbc90bc416 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -498,4 +498,13 @@ test_expect_success 'merge fast-forward in a dirty tree' '
test_debug 'gitk --all'
+test_expect_success 'in-index merge' '
+ git reset --hard c0 &&
+ git merge --no-ff -s resolve c1 > out &&
+ grep "Wonderful." out &&
+ verify_parents $c0 $c1
+'
+
+test_debug 'gitk --all'
+
test_done
diff --git a/t/t7605-merge-resolve.sh b/t/t7605-merge-resolve.sh
index ee21a107fd..f1f86ddb23 100755
--- a/t/t7605-merge-resolve.sh
+++ b/t/t7605-merge-resolve.sh
@@ -36,7 +36,9 @@ test_expect_success 'merge c1 to c2' '
git diff --exit-code &&
test -f c0.c &&
test -f c1.c &&
- test -f c2.c
+ test -f c2.c &&
+ test 3 = $(git ls-tree -r HEAD | wc -l) &&
+ test 3 = $(git ls-files | wc -l)
'
test_expect_success 'merge c2 to c3 (fails)' '
diff --git a/t/t8001-annotate.sh b/t/t8001-annotate.sh
index eabec2e06e..45cb60ea4b 100755
--- a/t/t8001-annotate.sh
+++ b/t/t8001-annotate.sh
@@ -4,7 +4,7 @@ test_description='git annotate'
. ./test-lib.sh
PROG='git annotate'
-. ../annotate-tests.sh
+. "$TEST_DIRECTORY"/annotate-tests.sh
test_expect_success \
'Annotating an old revision works' \
diff --git a/t/t8002-blame.sh b/t/t8002-blame.sh
index 92ece30fa9..597cf0486f 100755
--- a/t/t8002-blame.sh
+++ b/t/t8002-blame.sh
@@ -4,6 +4,6 @@ test_description='git blame'
. ./test-lib.sh
PROG='git blame -c'
-. ../annotate-tests.sh
+. "$TEST_DIRECTORY"/annotate-tests.sh
test_done
diff --git a/t/t9110-git-svn-use-svm-props.sh b/t/t9110-git-svn-use-svm-props.sh
index 04d2a65c08..83bd1cf17a 100755
--- a/t/t9110-git-svn-use-svm-props.sh
+++ b/t/t9110-git-svn-use-svm-props.sh
@@ -8,7 +8,7 @@ test_description='git-svn useSvmProps test'
. ./lib-git-svn.sh
test_expect_success 'load svm repo' '
- svnadmin load -q "$rawsvnrepo" < ../t9110/svm.dump &&
+ svnadmin load -q "$rawsvnrepo" < "$TEST_DIRECTORY"/t9110/svm.dump &&
git-svn init --minimize-url -R arr -i bar "$svnrepo"/mirror/arr &&
git-svn init --minimize-url -R argh -i dir "$svnrepo"/mirror/argh &&
git-svn init --minimize-url -R argh -i e \
diff --git a/t/t9111-git-svn-use-svnsync-props.sh b/t/t9111-git-svn-use-svnsync-props.sh
index a8d74dcd3a..c5dfd61e41 100755
--- a/t/t9111-git-svn-use-svnsync-props.sh
+++ b/t/t9111-git-svn-use-svnsync-props.sh
@@ -8,7 +8,7 @@ test_description='git-svn useSvnsyncProps test'
. ./lib-git-svn.sh
test_expect_success 'load svnsync repo' '
- svnadmin load -q "$rawsvnrepo" < ../t9111/svnsync.dump &&
+ svnadmin load -q "$rawsvnrepo" < "$TEST_DIRECTORY"/t9111/svnsync.dump &&
git-svn init --minimize-url -R arr -i bar "$svnrepo"/bar &&
git-svn init --minimize-url -R argh -i dir "$svnrepo"/dir &&
git-svn init --minimize-url -R argh -i e "$svnrepo"/dir/a/b/c/d/e &&
diff --git a/t/t9115-git-svn-dcommit-funky-renames.sh b/t/t9115-git-svn-dcommit-funky-renames.sh
index f0fbd3aff7..b0ba1f0200 100755
--- a/t/t9115-git-svn-dcommit-funky-renames.sh
+++ b/t/t9115-git-svn-dcommit-funky-renames.sh
@@ -8,7 +8,7 @@ test_description='git-svn dcommit can commit renames of files with ugly names'
. ./lib-git-svn.sh
test_expect_success 'load repository with strange names' '
- svnadmin load -q "$rawsvnrepo" < ../t9115/funky-names.dump &&
+ svnadmin load -q "$rawsvnrepo" < "$TEST_DIRECTORY"/t9115/funky-names.dump &&
start_httpd gtk+
'
diff --git a/t/t9121-git-svn-fetch-renamed-dir.sh b/t/t9121-git-svn-fetch-renamed-dir.sh
index 99230b0810..92e69a2a75 100755
--- a/t/t9121-git-svn-fetch-renamed-dir.sh
+++ b/t/t9121-git-svn-fetch-renamed-dir.sh
@@ -8,7 +8,7 @@ test_description='git-svn can fetch renamed directories'
. ./lib-git-svn.sh
test_expect_success 'load repository with renamed directory' '
- svnadmin load -q "$rawsvnrepo" < ../t9121/renamed-dir.dump
+ svnadmin load -q "$rawsvnrepo" < "$TEST_DIRECTORY"/t9121/renamed-dir.dump
'
test_expect_success 'init and fetch repository' '
diff --git a/t/t9200-git-cvsexportcommit.sh b/t/t9200-git-cvsexportcommit.sh
index 3e32e84e6c..988c3ac754 100755
--- a/t/t9200-git-cvsexportcommit.sh
+++ b/t/t9200-git-cvsexportcommit.sh
@@ -45,8 +45,8 @@ test_expect_success \
'mkdir A B C D E F &&
echo hello1 >A/newfile1.txt &&
echo hello2 >B/newfile2.txt &&
- cp ../test9200a.png C/newfile3.png &&
- cp ../test9200a.png D/newfile4.png &&
+ cp "$TEST_DIRECTORY"/test9200a.png C/newfile3.png &&
+ cp "$TEST_DIRECTORY"/test9200a.png D/newfile4.png &&
git add A/newfile1.txt &&
git add B/newfile2.txt &&
git add C/newfile3.png &&
@@ -71,8 +71,8 @@ test_expect_success \
rm -f B/newfile2.txt &&
rm -f C/newfile3.png &&
echo Hello5 >E/newfile5.txt &&
- cp ../test9200b.png D/newfile4.png &&
- cp ../test9200a.png F/newfile6.png &&
+ cp "$TEST_DIRECTORY"/test9200b.png D/newfile4.png &&
+ cp "$TEST_DIRECTORY"/test9200a.png F/newfile6.png &&
git add E/newfile5.txt &&
git add F/newfile6.png &&
git commit -a -m "Test: Remove, add and update" &&
@@ -160,7 +160,7 @@ test_expect_success \
'mkdir "G g" &&
echo ok then >"G g/with spaces.txt" &&
git add "G g/with spaces.txt" && \
- cp ../test9200a.png "G g/with spaces.png" && \
+ cp "$TEST_DIRECTORY"/test9200a.png "G g/with spaces.png" && \
git add "G g/with spaces.png" &&
git commit -a -m "With spaces" &&
id=$(git rev-list --max-count=1 HEAD) &&
@@ -172,7 +172,7 @@ test_expect_success \
test_expect_success \
'Update file with spaces in file name' \
'echo Ok then >>"G g/with spaces.txt" &&
- cat ../test9200a.png >>"G g/with spaces.png" && \
+ cat "$TEST_DIRECTORY"/test9200a.png >>"G g/with spaces.png" && \
git add "G g/with spaces.png" &&
git commit -a -m "Update with spaces" &&
id=$(git rev-list --max-count=1 HEAD) &&
@@ -197,7 +197,7 @@ test_expect_success \
'mkdir -p Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö &&
echo Foo >Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.txt &&
git add Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.txt &&
- cp ../test9200a.png Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.png &&
+ cp "$TEST_DIRECTORY"/test9200a.png Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.png &&
git add Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.png &&
git commit -a -m "Går det så går det" && \
id=$(git rev-list --max-count=1 HEAD) &&
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index c6bc0a607f..bd5d5af661 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -5,7 +5,7 @@
test_description='test git-fast-import utility'
. ./test-lib.sh
-. ../diff-lib.sh ;# test-lib chdir's into trash
+. "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash
file2_data='file2
second line of EOF'
diff --git a/t/t9301-fast-export.sh b/t/t9301-fast-export.sh
index c19b4a2bab..3cb9f80708 100755
--- a/t/t9301-fast-export.sh
+++ b/t/t9301-fast-export.sh
@@ -67,7 +67,7 @@ test_expect_success 'iso-8859-1' '
git config i18n.commitencoding ISO-8859-1 &&
# use author and committer name in ISO-8859-1 to match it.
- . ../t3901-8859-1.txt &&
+ . "$TEST_DIRECTORY"/t3901-8859-1.txt &&
test_tick &&
echo rosten >file &&
git commit -s -m den file &&
diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh
index ae7082be1d..46ba19be7d 100755
--- a/t/t9500-gitweb-standalone-no-errors.sh
+++ b/t/t9500-gitweb-standalone-no-errors.sh
@@ -25,9 +25,9 @@ our \$site_name = "[localhost]";
our \$site_header = "";
our \$site_footer = "";
our \$home_text = "indextext.html";
-our @stylesheets = ("file:///$safe_pwd/../../gitweb/gitweb.css");
-our \$logo = "file:///$safe_pwd/../../gitweb/git-logo.png";
-our \$favicon = "file:///$safe_pwd/../../gitweb/git-favicon.png";
+our @stylesheets = ("file:///$TEST_DIRECTORY/../gitweb/gitweb.css");
+our \$logo = "file:///$TEST_DIRECTORY/../gitweb/git-logo.png";
+our \$favicon = "file:///$TEST_DIRECTORY/../gitweb/git-favicon.png";
our \$projects_list = "";
our \$export_ok = "";
our \$strict_export = "";
@@ -54,7 +54,7 @@ gitweb_run () {
# written to web server logs, so we are not interested in that:
# we are interested only in properly formatted errors/warnings
rm -f gitweb.log &&
- perl -- "$(pwd)/../../gitweb/gitweb.perl" \
+ perl -- "$TEST_DIRECTORY/../gitweb/gitweb.perl" \
>/dev/null 2>gitweb.log &&
if grep -q -s "^[[]" gitweb.log >/dev/null; then false; else true; fi
@@ -525,20 +525,20 @@ test_debug 'cat gitweb.log'
test_expect_success \
'encode(commit): utf8' \
- '. ../t3901-utf8.txt &&
+ '. "$TEST_DIRECTORY"/t3901-utf8.txt &&
echo "UTF-8" >> file &&
git add file &&
- git commit -F ../t3900/1-UTF-8.txt &&
+ git commit -F "$TEST_DIRECTORY"/t3900/1-UTF-8.txt &&
gitweb_run "p=.git;a=commit"'
test_debug 'cat gitweb.log'
test_expect_success \
'encode(commit): iso-8859-1' \
- '. ../t3901-8859-1.txt &&
+ '. "$TEST_DIRECTORY"/t3901-8859-1.txt &&
echo "ISO-8859-1" >> file &&
git add file &&
git config i18n.commitencoding ISO-8859-1 &&
- git commit -F ../t3900/ISO-8859-1.txt &&
+ git commit -F "$TEST_DIRECTORY"/t3900/ISO-8859-1.txt &&
git config --unset i18n.commitencoding &&
gitweb_run "p=.git;a=commit"'
test_debug 'cat gitweb.log'
diff --git a/t/t9700-perl-git.sh b/t/t9700-perl-git.sh
index 9706ee5773..0f04ba094b 100755
--- a/t/t9700-perl-git.sh
+++ b/t/t9700-perl-git.sh
@@ -39,6 +39,6 @@ test_expect_success \
test_external_without_stderr \
'Perl API' \
- perl ../t9700/test.pl
+ perl "$TEST_DIRECTORY"/t9700/test.pl
test_done
diff --git a/t/t9700/test.pl b/t/t9700/test.pl
index 4d2312548a..851cea4a4b 100755
--- a/t/t9700/test.pl
+++ b/t/t9700/test.pl
@@ -14,10 +14,7 @@ use File::Temp;
BEGIN { use_ok('Git') }
# set up
-our $repo_dir = "trash directory";
our $abs_repo_dir = Cwd->cwd;
-die "this must be run by calling the t/t97* shell script(s)\n"
- if basename(Cwd->cwd) ne $repo_dir;
ok(our $r = Git->repository(Directory => "."), "open repository");
# config
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 11c027571b..e2b106cb6a 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -406,7 +406,7 @@ test_create_repo () {
error "bug in the test script: not 1 parameter to test-create-repo"
owd=`pwd`
repo="$1"
- mkdir "$repo"
+ mkdir -p "$repo"
cd "$repo" || error "Cannot setup test environment"
"$GIT_EXEC_PATH/git" init "--template=$GIT_EXEC_PATH/templates/blt/" >&3 2>&4 ||
error "cannot run git init -- have you built things yet?"
@@ -449,6 +449,11 @@ test_done () {
# we will leave things as they are.
say_color pass "passed all $msg"
+
+ test -d "$remove_trash" &&
+ cd "$(dirname "$remove_trash")" &&
+ rm -rf "$(basename "$remove_trash")"
+
exit 0 ;;
*)
@@ -485,7 +490,8 @@ fi
. ../GIT-BUILD-OPTIONS
# Test repository
-test="trash directory"
+test="trash directory.$(basename "$0" .sh)"
+test ! -z "$debug" || remove_trash="$TEST_DIRECTORY/$test"
rm -fr "$test" || {
trap - exit
echo >&5 "FATAL: Cannot prepare test area"
diff --git a/templates/Makefile b/templates/Makefile
index cc3fc3094c..0722a926f7 100644
--- a/templates/Makefile
+++ b/templates/Makefile
@@ -23,13 +23,13 @@ all: boilerplates.made custom
bpsrc = $(filter-out %~,$(wildcard *--*))
boilerplates.made : $(bpsrc)
- $(QUIET)ls *--* 2>/dev/null | \
+ $(QUIET)umask 022 && ls *--* 2>/dev/null | \
while read boilerplate; \
do \
case "$$boilerplate" in *~) continue ;; esac && \
dst=`echo "$$boilerplate" | sed -e 's|^this|.|;s|--|/|g'` && \
dir=`expr "$$dst" : '\(.*\)/'` && \
- $(INSTALL) -d -m 755 blt/$$dir && \
+ mkdir -p blt/$$dir && \
case "$$boilerplate" in \
*--) ;; \
*) cp -p $$boilerplate blt/$$dst ;; \
diff --git a/unpack-trees.c b/unpack-trees.c
index cba0aca062..ef21c62195 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -376,6 +376,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
state.refresh_cache = 1;
memset(&o->result, 0, sizeof(o->result));
+ o->result.initialized = 1;
if (o->src_index)
o->result.timestamp = o->src_index->timestamp;
o->merge_size = len;
diff --git a/xdiff-interface.c b/xdiff-interface.c
index 61dc5c5470..944ad9887f 100644
--- a/xdiff-interface.c
+++ b/xdiff-interface.c
@@ -1,5 +1,12 @@
#include "cache.h"
#include "xdiff-interface.h"
+#include "strbuf.h"
+
+struct xdiff_emit_state {
+ xdiff_emit_consume_fn consume;
+ void *consume_callback_data;
+ struct strbuf remainder;
+};
static int parse_num(char **cp_p, int *num_p)
{
@@ -55,13 +62,13 @@ static void consume_one(void *priv_, char *s, unsigned long size)
unsigned long this_size;
ep = memchr(s, '\n', size);
this_size = (ep == NULL) ? size : (ep - s + 1);
- priv->consume(priv, s, this_size);
+ priv->consume(priv->consume_callback_data, s, this_size);
size -= this_size;
s += this_size;
}
}
-int xdiff_outf(void *priv_, mmbuffer_t *mb, int nbuf)
+static int xdiff_outf(void *priv_, mmbuffer_t *mb, int nbuf)
{
struct xdiff_emit_state *priv = priv_;
int i;
@@ -69,36 +76,22 @@ int xdiff_outf(void *priv_, mmbuffer_t *mb, int nbuf)
for (i = 0; i < nbuf; i++) {
if (mb[i].ptr[mb[i].size-1] != '\n') {
/* Incomplete line */
- priv->remainder = xrealloc(priv->remainder,
- priv->remainder_size +
- mb[i].size);
- memcpy(priv->remainder + priv->remainder_size,
- mb[i].ptr, mb[i].size);
- priv->remainder_size += mb[i].size;
+ strbuf_add(&priv->remainder, mb[i].ptr, mb[i].size);
continue;
}
/* we have a complete line */
- if (!priv->remainder) {
+ if (!priv->remainder.len) {
consume_one(priv, mb[i].ptr, mb[i].size);
continue;
}
- priv->remainder = xrealloc(priv->remainder,
- priv->remainder_size +
- mb[i].size);
- memcpy(priv->remainder + priv->remainder_size,
- mb[i].ptr, mb[i].size);
- consume_one(priv, priv->remainder,
- priv->remainder_size + mb[i].size);
- free(priv->remainder);
- priv->remainder = NULL;
- priv->remainder_size = 0;
+ strbuf_add(&priv->remainder, mb[i].ptr, mb[i].size);
+ consume_one(priv, priv->remainder.buf, priv->remainder.len);
+ strbuf_reset(&priv->remainder);
}
- if (priv->remainder) {
- consume_one(priv, priv->remainder, priv->remainder_size);
- free(priv->remainder);
- priv->remainder = NULL;
- priv->remainder_size = 0;
+ if (priv->remainder.len) {
+ consume_one(priv, priv->remainder.buf, priv->remainder.len);
+ strbuf_reset(&priv->remainder);
}
return 0;
}
@@ -141,6 +134,25 @@ int xdi_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdemitconf_t co
return xdl_diff(&a, &b, xpp, xecfg, xecb);
}
+int xdi_diff_outf(mmfile_t *mf1, mmfile_t *mf2,
+ xdiff_emit_consume_fn fn, void *consume_callback_data,
+ xpparam_t const *xpp,
+ xdemitconf_t const *xecfg, xdemitcb_t *xecb)
+{
+ int ret;
+ struct xdiff_emit_state state;
+
+ memset(&state, 0, sizeof(state));
+ state.consume = fn;
+ state.consume_callback_data = consume_callback_data;
+ xecb->outf = xdiff_outf;
+ xecb->priv = &state;
+ strbuf_init(&state.remainder, 0);
+ ret = xdi_diff(mf1, mf2, xpp, xecfg, xecb);
+ strbuf_release(&state.remainder);
+ return ret;
+}
+
int read_mmfile(mmfile_t *ptr, const char *filename)
{
struct stat st;
diff --git a/xdiff-interface.h b/xdiff-interface.h
index f7f791d96b..558492ba38 100644
--- a/xdiff-interface.h
+++ b/xdiff-interface.h
@@ -3,18 +3,13 @@
#include "xdiff/xdiff.h"
-struct xdiff_emit_state;
-
typedef void (*xdiff_emit_consume_fn)(void *, char *, unsigned long);
-struct xdiff_emit_state {
- xdiff_emit_consume_fn consume;
- char *remainder;
- unsigned long remainder_size;
-};
-
int xdi_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdemitconf_t const *xecfg, xdemitcb_t *ecb);
-int xdiff_outf(void *priv_, mmbuffer_t *mb, int nbuf);
+int xdi_diff_outf(mmfile_t *mf1, mmfile_t *mf2,
+ xdiff_emit_consume_fn fn, void *consume_callback_data,
+ xpparam_t const *xpp,
+ xdemitconf_t const *xecfg, xdemitcb_t *xecb);
int parse_hunk_header(char *line, int len,
int *ob, int *on,
int *nb, int *nn);