author | Junio C Hamano <gitster@pobox.com> | |
Thu, 9 Jul 2009 08:07:54 +0000 (01:07 -0700) | ||
committer | Junio C Hamano <gitster@pobox.com> | |
Thu, 9 Jul 2009 08:07:54 +0000 (01:07 -0700) |
* ld/push-porcelain-output-format:
add --porcelain option to git-push
add --porcelain option to git-push
113 files changed:
index dc76e7f073f23cd911da0b0d0d49b72726576f1a..87a90f2c3fd48bbb593a2cef135310f88d87e4b4 100644 (file)
startsb=[
endsb=]
tilde=~
+backtick=`
ifdef::backend-docbook[]
[linkgit-inlinemacro]
index 2fecbe32a68bd981959735dd14e6e311d16b233a..cb6832b4e80efc7dc34690f92c63ba4ee12529c7 100644 (file)
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
it will be treated as a shell command. For example, defining
"alias.new = !gitk --all --not ORIG_HEAD", the invocation
"git new" is equivalent to running the shell command
-"gitk --all --not ORIG_HEAD".
+"gitk --all --not ORIG_HEAD". Note that shell commands will be
+executed from the top-level directory of a repository, which may
+not necessarily be the current directory.
apply.whitespace::
Tells 'git-apply' how to handle whitespaces, in the same way
over HTTPS. Can be overridden by the 'GIT_SSL_KEY' environment
variable.
+http.sslCertPasswordProtected::
+ Enable git's password prompt for the SSL certificate. Otherwise
+ OpenSSL will prompt the user, possibly many times, if the
+ certificate or private key is encrypted. Can be overridden by the
+ 'GIT_SSL_CERT_PASSWORD_PROTECTED' environment variable.
+
http.sslCAInfo::
File containing the certificates to verify the peer with when
fetching or pushing over HTTPS. Can be overridden by the
index 6d92cbee6475e29660d91a97683bf5843aacab38..32e689b2bf184464b0923c3bb88a209b9b28a022 100644 (file)
--- a/Documentation/git-am.txt
+++ b/Documentation/git-am.txt
[--3way] [--interactive] [--committer-date-is-author-date]
[--ignore-date]
[--whitespace=<option>] [-C<n>] [-p<n>] [--directory=<dir>]
- [--reject]
+ [--reject] [-q | --quiet]
[<mbox> | <Maildir>...]
'git am' (--skip | --resolved | --abort)
--keep::
Pass `-k` flag to 'git-mailinfo' (see linkgit:git-mailinfo[1]).
+-q::
+--quiet::
+ Be quiet. Only print error messages.
+
-u::
--utf8::
Pass `-u` flag to 'git-mailinfo' (see linkgit:git-mailinfo[1]).
index ffc02c737cf0a8d2bdb3cd812e0a23d43ee27fd7..63e7a42cb353e2cd0c8bbb6e83927bd1863a32cb 100644 (file)
$ git bisect skip # Current version cannot be tested
------------
-But computing the commit to test may be slower afterwards and git may
-eventually not be able to tell the first bad commit among a bad commit
-and one or more skipped commits.
+But git may eventually be unable to tell the first bad commit among
+a bad commit and one or more skipped commits.
You can even skip a range of commits, instead of just one commit,
using the "'<commit1>'..'<commit2>'" notation. For example:
index fccb82deb48ec75d25f948e7caa69a44e09f5832..b753c9d76fde51198eb7ef34b9ff298095fb1f72 100644 (file)
-<num>::
A shortcut for specifying -C<num>.
+-p::
+--show-function::
+ Show the preceding line that contains the function name of
+ the match, unless the matching line is a function name itself.
+ The name is determined in the same way as 'git diff' works out
+ patch hunk headers (see 'Defining a custom hunk-header' in
+ linkgit:gitattributes[5]).
+
-f <file>::
Read patterns from <file>, one per line.
index 26f3b7b2b0daad0affb36e6514156520a693b164..db1b71d24846e4561d99bed095345eb9580b0632 100644 (file)
is used instead ('git-merge-recursive' when merging a single
head, 'git-merge-octopus' otherwise). This implies --merge.
+-q::
+--quiet::
+ Be quiet. Implies --no-stat.
+
-v::
--verbose::
Be verbose. Implies --stat.
index 4bbdd056da4ca5a3032b53afac820b86c74a54e4..82045a2522799ccf3a03479bf4f4cd1fa1809879 100644 (file)
Only meaningful in `--parseopt` mode. Tells the option parser to echo
out the first `--` met instead of skipping it.
+--stop-at-non-option::
+ Only meaningful in `--parseopt` mode. Lets the option parser stop at
+ the first non-option argument. This can be used to parse sub-commands
+ that take options themself.
+
--sq-quote::
Use 'git-rev-parse' in shell quoting mode (see SQ-QUOTE
section below). In contrast to the `--sq` option below, this
index 98e294aa869d39575ab32d859ca9fcc3bfcaf789..f4429bdc6863ce1d115b47282f2c04a4d9093d29 100644 (file)
--------
[verse]
'git show-ref' [-q|--quiet] [--verify] [-h|--head] [-d|--dereference]
- [-s|--hash] [--abbrev] [--tags] [--heads] [--] <pattern>...
-'git show-ref' --exclude-existing[=pattern]
+ [-s|--hash[=<n>]] [--abbrev[=<n>]] [--tags]
+ [--heads] [--] <pattern>...
+'git show-ref' --exclude-existing[=<pattern>] < ref-list
DESCRIPTION
-----------
appended.
-s::
---hash::
+--hash[=<n>]::
Only show the SHA1 hash, not the reference name. When combined with
--dereference the dereferenced tag will still be shown after the SHA1.
Aside from returning an error code of 1, it will also print an error
message if '--quiet' was not specified.
---abbrev::
---abbrev=len::
+--abbrev[=<n>]::
Abbreviate the object name. When using `--hash`, you do
- not have to say `--hash --abbrev`; `--hash=len` would do.
+ not have to say `--hash --abbrev`; `--hash=n` would do.
-q::
--quiet::
Do not print any results to stdout. When combined with '--verify' this
can be used to silently check if a reference exists.
---exclude-existing::
---exclude-existing=pattern::
+--exclude-existing[=<pattern>]::
Make 'git-show-ref' act as a filter that reads refs from stdin of the
form "^(?:<anything>\s)?<refname>(?:\^\{\})?$" and performs the
index a42d4c85bddd539d46aaaafea6bf6412cd7c3436..1c64a02fe576a6bdad2afcbc96391ce0c2d541c4 100644 (file)
--------
[verse]
'git stash' list [<options>]
-'git stash' ( show | drop ) [<stash>]
-'git stash' ( pop | apply ) [--index] [<stash>]
+'git stash' show [<stash>]
+'git stash' drop [-q|--quiet] [<stash>]
+'git stash' ( pop | apply ) [--index] [-q|--quiet] [<stash>]
'git stash' branch <branchname> [<stash>]
-'git stash' [save [--keep-index] [<message>]]
+'git stash' [save [--keep-index] [-q|--quiet] [<message>]]
'git stash' clear
'git stash' create
OPTIONS
-------
-save [--keep-index] [<message>]::
+save [--keep-index] [-q|--quiet] [<message>]::
Save your local modifications to a new 'stash', and run `git reset
--hard` to revert them. This is the default action when no
it will accept any format known to 'git-diff' (e.g., `git stash show
-p stash@\{1}` to view the second most recent stash in patch form).
-pop [<stash>]::
+pop [--index] [-q|--quiet] [<stash>]::
Remove a single stashed state from the stash list and apply it
on top of the current working tree state, i.e., do the inverse
+
When no `<stash>` is given, `stash@\{0}` is assumed.
-apply [--index] [<stash>]::
+apply [--index] [-q|--quiet] [<stash>]::
Like `pop`, but do not remove the state from the stash list.
Remove all the stashed states. Note that those states will then
be subject to pruning, and may be difficult or impossible to recover.
-drop [<stash>]::
+drop [-q|--quiet] [<stash>]::
Remove a single stashed state from the stash list. When no `<stash>`
is given, it removes the latest one. i.e. `stash@\{0}`
index 470bd75ad9ca7760bef33c1c4a326c79da92eb2b..683ba1a1ebe080e6e093d27686068823448e459c 100644 (file)
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.
+As an example, +git submodule foreach \'echo $path {backtick}git
+rev-parse HEAD{backtick}'+ will show the path and currently checked out
+commit for each submodule.
sync::
Synchronizes submodules' remote URL configuration setting
index 7e9b9a042347bf286c6ea523bef1952f0c72dec9..10af599b44a38981126af62652815b5d184e6774 100644 (file)
DESCRIPTION
-----------
-'git-svn' is a simple conduit for changesets between Subversion and git.
+'git svn' is a simple conduit for changesets between Subversion and git.
It provides a bidirectional flow of changes between a Subversion and a git
repository.
-'git-svn' can track a standard Subversion repository,
+'git svn' can track a standard Subversion repository,
following the common "trunk/branches/tags" layout, with the --stdlayout option.
It can also follow branches and tags in any layout with the -T/-t/-b options
(see options to 'init' below, and also the 'clone' command).
COMMANDS
--------
---
'init'::
Initializes an empty git repository with additional
- metadata directories for 'git-svn'. The Subversion URL
+ metadata directories for 'git svn'. The Subversion URL
may be specified as a command-line argument, or as full
URL arguments to -T/-t/-b. Optionally, the target
directory to operate on can be specified as a second
Set the 'useSvnsyncProps' option in the [svn-remote] config.
--rewrite-root=<URL>;;
Set the 'rewriteRoot' option in the [svn-remote] config.
---use-log-author;;
- When retrieving svn commits into git (as part of fetch, rebase, or
- dcommit operations), look for the first From: or Signed-off-by: line
- in the log message and use that as the author string.
---add-author-from;;
- When committing to svn from git (as part of commit or dcommit
- operations), if the existing log message doesn't already have a
- From: or Signed-off-by: line, append a From: line based on the
- git commit's author string. If you use this, then --use-log-author
- will retrieve a valid author string for all commits.
--username=<USER>;;
For transports that SVN handles authentication for (http,
https, and plain svn), specify the username. For other
--localtime;;
Store Git commit times in the local timezone instead of UTC. This
- makes 'git-log' (even without --date=local) show the same times
+ makes 'git log' (even without --date=local) show the same times
that `svn log` would in the local timezone.
--parent;;
Fetch only from the SVN parent of the current HEAD.
-
++
This doesn't interfere with interoperating with the Subversion
repository you cloned from, but if you wish for your local Git
repository to be able to interoperate with someone else's local Git
The '--ignore-paths' option should match for every 'fetch'
(including automatic fetches due to 'clone', 'dcommit',
'rebase', etc) on a given repository.
-
++
+[verse]
config key: svn-remote.<name>.ignore-paths
-
- If the ignore-paths config key is set and the command
- line option is also given, both regular expressions
- will be used.
-
++
+If the ignore-paths config key is set and the command line option is
+also given, both regular expressions will be used.
++
Examples:
++
+--
+Skip "doc*" directory for every fetch;;
++
+------------------------------------------------------------------------
+--ignore-paths="^doc"
+------------------------------------------------------------------------
- --ignore-paths="^doc" - skip "doc*" directory for every
- fetch.
+Skip "branches" and "tags" of first level directories;;
++
+------------------------------------------------------------------------
+--ignore-paths="^[^/]+/(?:branches|tags)"
+------------------------------------------------------------------------
+--
- --ignore-paths="^[^/]+/(?:branches|tags)" - skip
- "branches" and "tags" of first level directories.
+--use-log-author;;
+ When retrieving svn commits into git (as part of fetch, rebase, or
+ dcommit operations), look for the first From: or Signed-off-by: line
+ in the log message and use that as the author string.
+--add-author-from;;
+ When committing to svn from git (as part of commit or dcommit
+ operations), if the existing log message doesn't already have a
+ From: or Signed-off-by: line, append a From: line based on the
+ git commit's author string. If you use this, then --use-log-author
+ will retrieve a valid author string for all commits.
'clone'::
Runs 'init' and 'fetch'. It will automatically create a
or if a second argument is passed; it will create a directory
and work within that. It accepts all arguments that the
'init' and 'fetch' commands accept; with the exception of
- '--fetch-all'. After a repository is cloned, the 'fetch'
- command will be able to update revisions without affecting
- the working tree; and the 'rebase' command will be able
- to update the working tree with the latest changes.
+ '--fetch-all' and '--parent'. After a repository is cloned,
+ the 'fetch' command will be able to update revisions without
+ affecting the working tree; and the 'rebase' command will be
+ able to update the working tree with the latest changes.
'rebase'::
This fetches revisions from the SVN parent of the current HEAD
and rebases the current (uncommitted to SVN) work against it.
-
-This works similarly to `svn update` or 'git-pull' except that
-it preserves linear history with 'git-rebase' instead of
-'git-merge' for ease of dcommitting with 'git-svn'.
-
-This accepts all options that 'git-svn fetch' and 'git-rebase'
++
+This works similarly to `svn update` or 'git pull' except that
+it preserves linear history with 'git rebase' instead of
+'git merge' for ease of dcommitting with 'git svn'.
++
+This accepts all options that 'git svn fetch' and 'git rebase'
accept. However, '--fetch-all' only fetches from the current
[svn-remote], and not all [svn-remote] definitions.
-
-Like 'git-rebase'; this requires that the working tree be clean
++
+Like 'git rebase'; this requires that the working tree be clean
and have no uncommitted changes.
-l;;
--local;;
- Do not fetch remotely; only run 'git-rebase' against the
+ Do not fetch remotely; only run 'git rebase' against the
last fetched commit from the upstream SVN.
'dcommit'::
repository, and then rebase or reset (depending on whether or
not there is a diff between SVN and head). This will create
a revision in SVN for each commit in git.
- It is recommended that you run 'git-svn' fetch and rebase (not
+ It is recommended that you run 'git svn' fetch and rebase (not
pull or merge) your commits against the latest changes in the
SVN repository.
An optional revision or branch argument may be specified, and
- causes 'git-svn' to do all work on that revision/branch
+ causes 'git svn' to do all work on that revision/branch
instead of HEAD.
This is advantageous over 'set-tree' (below) because it produces
cleaner, more linear history.
After committing, do not rebase or reset.
--commit-url <URL>;;
Commit to this SVN URL (the full path). This is intended to
- allow existing git-svn repositories created with one transport
+ allow existing 'git svn' repositories created with one transport
method (e.g. `svn://` or `http://` for anonymous read) to be
reused if a user is later given access to an alternate transport
method (e.g. `svn+ssh://` or `https://`) for commit.
-
++
+[verse]
config key: svn-remote.<name>.commiturl
-
config key: svn.commiturl (overwrites all svn-remote.<name>.commiturl options)
-
- Using this option for any other purpose (don't ask)
- is very strongly discouraged.
---
++
+Using this option for any other purpose (don't ask) is very strongly
+discouraged.
'branch'::
Create a branch in the SVN repository.
@@ -232,10 +239,12 @@ where <name> is the name of the SVN repository as specified by the -R option to
The following features from `svn log' are supported:
+
--
--r/--revision=<n>[:<n>];;
+-r <n>[:<n>];;
+--revision=<n>[:<n>];;
is supported, non-numeric args are not:
HEAD, NEXT, BASE, PREV, etc ...
--v/--verbose;;
+-v;;
+--verbose;;
it's not completely compatible with the --verbose
output in svn log, but reasonably close.
--limit=<n>;;
client converts the UTC time to the local time (or based on the TZ=
environment). This command has the same behaviour.
+
-Any other arguments are passed directly to 'git-log'
+Any other arguments are passed directly to 'git log'
'blame'::
Show what revision and author last modified each line of a file. The
`svn blame' by default. Like the SVN blame command,
local uncommitted changes in the working copy are ignored;
the version of the file in the HEAD revision is annotated. Unknown
- arguments are passed directly to 'git-blame'.
+ arguments are passed directly to 'git blame'.
+
--git-format;;
- Produce output in the same format as 'git-blame', but with
+ Produce output in the same format as 'git blame', but with
SVN revision numbers instead of git commit hashes. In this mode,
changes that haven't been committed to SVN (including local
working-copy edits) are shown as revision 0.
---
'find-rev'::
When given an SVN revision number of the form 'rN', returns the
corresponding git commit hash (this can optionally be followed by a
absolutely no attempts to do patching when committing to SVN, it
simply overwrites files with those specified in the tree or
commit. All merging is assumed to have taken place
- independently of 'git-svn' functions.
+ independently of 'git svn' functions.
'create-ignore'::
Recursively finds the svn:ignore property on directories and
'commit-diff'::
Commits the diff of two tree-ish arguments from the
- command-line. This command does not rely on being inside an `git-svn
+ command-line. This command does not rely on being inside an `git svn
init`-ed repository. This command takes three arguments, (a) the
original tree to diff against, (b) the new tree result, (c) the
URL of the target Subversion repository. The final argument
- (URL) may be omitted if you are working from a 'git-svn'-aware
- repository (that has been `init`-ed with 'git-svn').
+ (URL) may be omitted if you are working from a 'git svn'-aware
+ repository (that has been `init`-ed with 'git svn').
The -r<revision> option is required for this.
'info'::
"checksum mismatch" (missed a modification). If the problem
file cannot be ignored forever (with --ignore-paths) the only
way to repair the repo is to use 'reset'.
-
++
Only the rev_map and refs/remotes/git-svn are changed. Follow 'reset'
-with a 'fetch' and then 'git-reset' or 'git-rebase' to move local
+with a 'fetch' and then 'git reset' or 'git rebase' to move local
branches onto the new tree.
--r/--revision=<n>;;
+-r <n>;;
+--revision=<n>;;
Specify the most recent revision to keep. All later revisions
are discarded.
--p/--parent;;
+-p;;
+--parent;;
Discard the specified revision as well, keeping the nearest
parent instead.
Example:;;
Assume you have local changes in "master", but you need to refetch "r2".
-
++
------------
r1---r2---r3 remotes/git-svn
\
A---B master
------------
-
++
Fix the ignore-paths or SVN permissions problem that caused "r2" to
be incomplete in the first place. Then:
-
++
[verse]
git svn reset -r2 -p
git svn fetch
-
++
------------
r1---r2'--r3' remotes/git-svn
\
r2---r3---A---B master
------------
-
-Then fixup "master" with 'git-rebase'.
-Do NOT use 'git-merge' or your history will not be compatible with a
++
+Then fixup "master" with 'git rebase'.
+Do NOT use 'git merge' or your history will not be compatible with a
future 'dcommit'!
-
++
[verse]
git rebase --onto remotes/git-svn A^ master
-
++
------------
r1---r2'--r3' remotes/git-svn
\
A'--B' master
------------
-
---
-
OPTIONS
-------
---
--shared[={false|true|umask|group|all|world|everybody}]::
--template=<template_directory>::
Only used with the 'init' command.
- These are passed directly to 'git-init'.
+ These are passed directly to 'git init'.
-r <ARG>::
--revision <ARG>::
-
-Used with the 'fetch' command.
-
+ Used with the 'fetch' command.
++
This allows revision ranges for partial/cauterized history
to be supported. $NUMBER, $NUMBER1:$NUMBER2 (numeric ranges),
$NUMBER:HEAD, and BASE:$NUMBER are all supported.
-
++
This can allow you to make partial mirrors when running fetch;
but is generally not recommended because history will be skipped
and lost.
-::
--stdin::
-
-Only used with the 'set-tree' command.
-
+ Only used with the 'set-tree' command.
++
Read a list of commits from stdin and commit them in reverse
order. Only the leading sha1 is read from each line, so
-'git-rev-list --pretty=oneline' output can be used.
+'git rev-list --pretty=oneline' output can be used.
--rmdir::
-
-Only used with the 'dcommit', 'set-tree' and 'commit-diff' commands.
-
+ Only used with the 'dcommit', 'set-tree' and 'commit-diff' commands.
++
Remove directories from the SVN tree if there are no files left
behind. SVN can version empty directories, and they are not
removed by default if there are no files left in them. git
cannot version empty directories. Enabling this flag will make
the commit to SVN act like git.
-
++
+[verse]
config key: svn.rmdir
-e::
--edit::
-
-Only used with the 'dcommit', 'set-tree' and 'commit-diff' commands.
-
+ Only used with the 'dcommit', 'set-tree' and 'commit-diff' commands.
++
Edit the commit message before committing to SVN. This is off by
default for objects that are commits, and forced on when committing
tree objects.
-
++
+[verse]
config key: svn.edit
-l<num>::
--find-copies-harder::
-
-Only used with the 'dcommit', 'set-tree' and 'commit-diff' commands.
-
-They are both passed directly to 'git-diff-tree'; see
+ Only used with the 'dcommit', 'set-tree' and 'commit-diff' commands.
++
+They are both passed directly to 'git diff-tree'; see
linkgit:git-diff-tree[1] for more information.
-
++
[verse]
config key: svn.l
config key: svn.findcopiesharder
-A<filename>::
--authors-file=<filename>::
-
-Syntax is compatible with the file used by 'git-cvsimport':
-
+ Syntax is compatible with the file used by 'git cvsimport':
++
------------------------------------------------------------------------
loginname = Joe User <user@example.com>
------------------------------------------------------------------------
-
-If this option is specified and 'git-svn' encounters an SVN
-committer name that does not exist in the authors-file, 'git-svn'
++
+If this option is specified and 'git svn' encounters an SVN
+committer name that does not exist in the authors-file, 'git svn'
will abort operation. The user will then have to add the
-appropriate entry. Re-running the previous 'git-svn' command
+appropriate entry. Re-running the previous 'git svn' command
after the authors-file is modified should continue operation.
-
++
+[verse]
config key: svn.authorsfile
--authors-prog=<filename>::
-
-If this option is specified, for each SVN committer name that does not
-exist in the authors file, the given file is executed with the committer
-name as the first argument. The program is expected to return a single
-line of the form "Name <email>", which will be treated as if included in
-the authors file.
+ If this option is specified, for each SVN committer name that
+ does not exist in the authors file, the given file is executed
+ with the committer name as the first argument. The program is
+ expected to return a single line of the form "Name <email>",
+ which will be treated as if included in the authors file.
-q::
--quiet::
- Make 'git-svn' less verbose. Specify a second time to make it
+ Make 'git svn' less verbose. Specify a second time to make it
even less verbose.
--repack[=<n>]::
--repack-flags=<flags>::
-
-These should help keep disk usage sane for large fetches
-with many revisions.
-
+ These should help keep disk usage sane for large fetches with
+ many revisions.
++
--repack takes an optional argument for the number of revisions
to fetch before repacking. This defaults to repacking every
1000 commits fetched if no argument is specified.
-
---repack-flags are passed directly to 'git-repack'.
-
++
+--repack-flags are passed directly to 'git repack'.
++
[verse]
config key: svn.repack
config key: svn.repackflags
--merge::
-s<strategy>::
--strategy=<strategy>::
-
-These are only used with the 'dcommit' and 'rebase' commands.
-
-Passed directly to 'git-rebase' when using 'dcommit' if a
-'git-reset' cannot be used (see 'dcommit').
+ These are only used with the 'dcommit' and 'rebase' commands.
++
+Passed directly to 'git rebase' when using 'dcommit' if a
+'git reset' cannot be used (see 'dcommit').
-n::
--dry-run::
-
-This can be used with the 'dcommit', 'rebase', 'branch' and 'tag'
-commands.
-
+ This can be used with the 'dcommit', 'rebase', 'branch' and
+ 'tag' commands.
++
For 'dcommit', print out the series of git arguments that would show
which diffs would be committed to SVN.
-
++
For 'rebase', display the local branch associated with the upstream svn
repository associated with the current branch and the URL of svn
repository that will be fetched from.
-
++
For 'branch' and 'tag', display the urls that will be used for copying when
creating the branch or tag.
---
ADVANCED OPTIONS
----------------
---
-i<GIT_SVN_ID>::
--id <GIT_SVN_ID>::
-
-This sets GIT_SVN_ID (instead of using the environment). This
-allows the user to override the default refname to fetch from
-when tracking a single URL. The 'log' and 'dcommit' commands
-no longer require this switch as an argument.
+ This sets GIT_SVN_ID (instead of using the environment). This
+ allows the user to override the default refname to fetch from
+ when tracking a single URL. The 'log' and 'dcommit' commands
+ no longer require this switch as an argument.
-R<remote name>::
--svn-remote <remote name>::
started tracking a branch and never tracked the trunk it was
descended from. This feature is enabled by default, use
--no-follow-parent to disable it.
-
++
+[verse]
config key: svn.followparent
---
CONFIG FILE-ONLY OPTIONS
------------------------
---
svn.noMetadata::
svn-remote.<name>.noMetadata::
-
-This gets rid of the 'git-svn-id:' lines at the end of every commit.
-
-If you lose your .git/svn/git-svn/.rev_db file, 'git-svn' will not
+ This gets rid of the 'git-svn-id:' lines at the end of every commit.
++
+If you lose your .git/svn/git-svn/.rev_db file, 'git svn' will not
be able to rebuild it and you won't be able to fetch again,
either. This is fine for one-shot imports.
-
-The 'git-svn log' command will not work on repositories using
++
+The 'git svn log' command will not work on repositories using
this, either. Using this conflicts with the 'useSvmProps'
option for (hopefully) obvious reasons.
svn.useSvmProps::
svn-remote.<name>.useSvmProps::
-
-This allows 'git-svn' to re-map repository URLs and UUIDs from
-mirrors created using SVN::Mirror (or svk) for metadata.
-
+ This allows 'git svn' to re-map repository URLs and UUIDs from
+ mirrors created using SVN::Mirror (or svk) for metadata.
++
If an SVN revision has a property, "svm:headrev", it is likely
that the revision was created by SVN::Mirror (also used by SVK).
The property contains a repository UUID and a revision. We want
svn-remote.<name>.rewriteRoot::
This allows users to create repositories from alternate
- URLs. For example, an administrator could run 'git-svn' on the
+ URLs. For example, an administrator could run 'git svn' on the
server locally (accessing via file://) but wish to distribute
the repository with a public http:// or svn:// URL in the
metadata so users of it will see the public URL.
svn.brokenSymlinkWorkaround::
-This disables potentially expensive checks to workaround broken symlinks
-checked into SVN by broken clients. Set this option to "false" if you
-track a SVN repository with many empty blobs that are not symlinks.
-This option may be changed while "git-svn" is running and take effect on
-the next revision fetched. If unset, git-svn assumes this option to be
-"true".
-
---
+ This disables potentially expensive checks to workaround
+ broken symlinks checked into SVN by broken clients. Set this
+ option to "false" if you track a SVN repository with many
+ empty blobs that are not symlinks. This option may be changed
+ while 'git svn' is running and take effect on the next
+ revision fetched. If unset, 'git svn' assumes this option to
+ be "true".
Since the noMetadata, rewriteRoot, useSvnsyncProps and useSvmProps
-options all affect the metadata generated and used by 'git-svn'; they
+options all affect the metadata generated and used by 'git svn'; they
*must* be set in the configuration file before any history is imported
and these settings should never be changed once they are set.
git svn clone http://svn.example.com/project/trunk
# Enter the newly cloned directory:
cd trunk
-# You should be on master branch, double-check with git-branch
+# You should be on master branch, double-check with 'git branch'
git branch
# Do some work and commit locally to git:
git commit ...
# of dcommit/rebase/show-ignore should be the same as above.
------------------------------------------------------------------------
-The initial 'git-svn clone' can be quite time-consuming
+The initial 'git svn clone' can be quite time-consuming
(especially for large Subversion repositories). If multiple
people (or one person with multiple machines) want to use
-'git-svn' to interact with the same Subversion repository, you can
-do the initial 'git-svn clone' to a repository on a server and
-have each person clone that repository with 'git-clone':
+'git svn' to interact with the same Subversion repository, you can
+do the initial 'git svn clone' to a repository on a server and
+have each person clone that repository with 'git clone':
------------------------------------------------------------------------
# Do the initial import on a server
git fetch
# Create a local branch from one of the branches just fetched
git checkout -b master FETCH_HEAD
-# Initialize git-svn locally (be sure to use the same URL and -T/-b/-t options as were used on server)
+# Initialize 'git svn' locally (be sure to use the same URL and -T/-b/-t options as were used on server)
git svn init http://svn.example.com/project
# Pull the latest changes from Subversion
git svn rebase
REBASE VS. PULL/MERGE
---------------------
-Originally, 'git-svn' recommended that the 'remotes/git-svn' branch be
+Originally, 'git svn' recommended that the 'remotes/git-svn' branch be
pulled or merged from. This is because the author favored
`git svn set-tree B` to commit a single head rather than the
`git svn set-tree A..B` notation to commit multiple commits.
DESIGN PHILOSOPHY
-----------------
Merge tracking in Subversion is lacking and doing branched development
-with Subversion can be cumbersome as a result. While 'git-svn' can track
+with Subversion can be cumbersome as a result. While 'git svn' can track
copy history (including branches and tags) for repositories adopting a
standard layout, it cannot yet represent merge history that happened
inside git back upstream to SVN users. Therefore it is advised that
-------
For the sake of simplicity and interoperating with a less-capable system
-(SVN), it is recommended that all 'git-svn' users clone, fetch and dcommit
-directly from the SVN server, and avoid all 'git-clone'/'pull'/'merge'/'push'
+(SVN), it is recommended that all 'git svn' users clone, fetch and dcommit
+directly from the SVN server, and avoid all 'git clone'/'pull'/'merge'/'push'
operations between git repositories and branches. The recommended
method of exchanging code between git branches and users is
-'git-format-patch' and 'git-am', or just 'dcommit'ing to the SVN repository.
+'git format-patch' and 'git am', or just 'dcommit'ing to the SVN repository.
-Running 'git-merge' or 'git-pull' is NOT recommended on a branch you
+Running 'git merge' or 'git pull' is NOT recommended on a branch you
plan to 'dcommit' from. Subversion does not represent merges in any
reasonable or useful fashion; so users using Subversion cannot see any
merges you've made. Furthermore, if you merge or pull from a git branch
that is a mirror of an SVN branch, 'dcommit' may commit to the wrong
branch.
-'git-clone' does not clone branches under the refs/remotes/ hierarchy or
-any 'git-svn' metadata, or config. So repositories created and managed with
-using 'git-svn' should use 'rsync' for cloning, if cloning is to be done
+'git clone' does not clone branches under the refs/remotes/ hierarchy or
+any 'git svn' metadata, or config. So repositories created and managed with
+using 'git svn' should use 'rsync' for cloning, if cloning is to be done
at all.
-Since 'dcommit' uses rebase internally, any git branches you 'git-push' to
+Since 'dcommit' uses rebase internally, any git branches you 'git push' to
before 'dcommit' on will require forcing an overwrite of the existing ref
on the remote repository. This is generally considered bad practice,
see the linkgit:git-push[1] documentation for details.
you've already pushed to a remote repository for other users, and
dcommit with SVN is analogous to that.
-When using multiple --branches or --tags, 'git-svn' does not automatically
+When using multiple --branches or --tags, 'git svn' does not automatically
handle name collisions (for example, if two branches from different paths have
the same name, or if a branch and a tag have the same name). In these cases,
use 'init' to set up your git repository then, before your first 'fetch', edit
CONFIGURATION
-------------
-'git-svn' stores [svn-remote] configuration information in the
+'git svn' stores [svn-remote] configuration information in the
repository .git/config file. It is similar the core git
[remote] sections except 'fetch' keys do not accept glob
arguments; but they are instead handled by the 'branches'
however the remote wildcard may be anywhere as long as it's an
independent path component (surrounded by '/' or EOL). This
type of configuration is not automatically created by 'init' and
-should be manually entered with a text-editor or using 'git-config'.
+should be manually entered with a text-editor or using 'git config'.
SEE ALSO
--------
index c7fa949c287f76c5ab8173d975f6da3dd92e6802..cf0689cfeb8b5122f8fa20345d9f5307fee1cd6c 100644 (file)
------------------------------------------------
This operation is safe even if Alice has uncommitted local changes.
-The range notation HEAD..FETCH_HEAD" means "show everything that is reachable
-from the FETCH_HEAD but exclude anything that is reachable from HEAD.
+The range notation "HEAD..FETCH_HEAD" means "show everything that is reachable
+from the FETCH_HEAD but exclude anything that is reachable from HEAD".
Alice already knows everything that leads to her current state (HEAD),
-and reviewing what Bob has in his state (FETCH_HEAD) that she has not
-seen with this command
+and reviews what Bob has in his state (FETCH_HEAD) that she has not
+seen with this command.
If Alice wants to visualize what Bob did since their histories forked
she can issue the following command:
alice$ git remote add bob /home/bob/myrepo
------------------------------------------------
-With this, Alice can perform the first part of the "pull" operation alone using the
-'git-fetch' command without merging them with her own branch,
-using:
+With this, Alice can perform the first part of the "pull" operation
+alone using the 'git-fetch' command without merging them with her own
+branch, using:
-------------------------------------
alice$ git fetch bob
You can also give 'git-log' a "range" of commits where the first is not
necessarily an ancestor of the second; for example, if the tips of
-the branches "stable-release" and "master" diverged from a common
+the branches "stable" and "master" diverged from a common
commit some time ago, then
-------------------------------------
-$ git log stable..experimental
+$ git log stable..master
-------------------------------------
-will list commits made in the experimental branch but not in the
+will list commits made in the master branch but not in the
stable branch, while
-------------------------------------
-$ git log experimental..stable
+$ git log master..stable
-------------------------------------
will show the list of commits made on the stable branch but not
-the experimental branch.
+the master branch.
The 'git-log' command has a weakness: it must present commits in a
list. When the history has lines of development that diverged and
diff --git a/Makefile b/Makefile
index 41ab8e9e0db59647b2e872757ec05e86f615ea1c..78cc11382a1e5f5d4d5b403015b8071c785a8501 100644 (file)
--- a/Makefile
+++ b/Makefile
#
# Define USE_NED_ALLOCATOR if you want to replace the platforms default
# memory allocators with the nedmalloc allocator written by Niall Douglas.
+#
+# Define NO_REGEX if you have no or inferior regex support in your C library.
GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
@$(SHELL_PATH) ./GIT-VERSION-GEN
NO_MEMMEM = YesPlease
NO_MKDTEMP = YesPlease
NO_MKSTEMPS = YesPlease
+ NO_REGEX = YesPlease
ifeq ($(uname_R),5.7)
NEEDS_RESOLV = YesPlease
NO_IPV6 = YesPlease
endif
INSTALL = /usr/ucb/install
TAR = gtar
- BASIC_CFLAGS += -D__EXTENSIONS__ -D__sun__
+ BASIC_CFLAGS += -D__EXTENSIONS__ -D__sun__ -DHAVE_ALLOCA_H
endif
ifeq ($(uname_O),Cygwin)
NO_D_TYPE_IN_DIRENT = YesPlease
USE_NED_ALLOCATOR = YesPlease
UNRELIABLE_FSTAT = UnfortunatelyYes
OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo
- COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/regex -Icompat/fnmatch
+ NO_REGEX = YesPlease
+ COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/fnmatch
COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
- COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/regex/regex.o compat/winansi.o
+ COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o
EXTLIBS += -lws2_32
X = .exe
ifneq (,$(wildcard ../THIS_IS_MSYSGIT))
ifdef UNRELIABLE_FSTAT
BASIC_CFLAGS += -DUNRELIABLE_FSTAT
endif
+ifdef NO_REGEX
+ COMPAT_CFLAGS += -Icompat/regex
+ COMPAT_OBJS += compat/regex/regex.o
+endif
ifdef USE_NED_ALLOCATOR
COMPAT_CFLAGS += -DUSE_NED_ALLOCATOR -DOVERRIDE_STRDUP -DNDEBUG -DREPLACE_SYSTEM_ALLOCATOR -Icompat/nedmalloc
$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
-$(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
+$(patsubst git-%$X,%.o,$(PROGRAMS)) git.o: $(LIB_H) $(wildcard */*.h)
builtin-revert.o wt-status.o: wt-status.h
$(LIB_FILE): $(LIB_OBJS)
diff --git a/abspath.c b/abspath.c
index 649f34f83365db3513c5166b897c4f033831444d..4bee0ba1ec6fcf49e88b874f0a415f4220117c0a 100644 (file)
--- a/abspath.c
+++ b/abspath.c
if (*buf) {
if (!*cwd && !getcwd(cwd, sizeof(cwd)))
- die ("Could not get current working directory");
+ die_errno ("Could not get current working directory");
if (chdir(buf))
- die ("Could not switch to '%s'", buf);
+ die_errno ("Could not switch to '%s'", buf);
}
if (!getcwd(buf, PATH_MAX))
- die ("Could not get current working directory");
+ die_errno ("Could not get current working directory");
if (last_elem) {
int len = strlen(buf);
if (!lstat(buf, &st) && S_ISLNK(st.st_mode)) {
len = readlink(buf, next_buf, PATH_MAX);
if (len < 0)
- die ("Invalid symlink: %s", buf);
+ die_errno ("Invalid symlink '%s'", buf);
if (PATH_MAX <= len)
die("symbolic link too long: %s", buf);
next_buf[len] = '\0';
}
if (*cwd && chdir(cwd))
- die ("Could not change back to '%s'", cwd);
+ die_errno ("Could not change back to '%s'", cwd);
return buf;
}
} else {
const char *cwd = get_pwd_cwd();
if (!cwd)
- die("Cannot determine the current working directory");
+ die_errno("Cannot determine the current working directory");
if (snprintf(buf, PATH_MAX, "%s/%s", cwd, path) >= PATH_MAX)
die("Too long path: %.*s", 60, path);
}
index f8f6faa94fd7eb4e260a75b82ef372e632f5eb9a..55bdb7cdebea7f7ea551231fe7801f272d128d69 100644 (file)
--- a/attr.c
+++ b/attr.c
}
}
+ strbuf_release(&pathbuf);
+
/*
* Finally push the "info" one at the top of the stack.
*/
diff --git a/bisect.c b/bisect.c
index dbeb28752adce639d8729fa7cbb003fc31bd240f..7f20acb4b9e391bd383597ec554ec58b70979fe5 100644 (file)
--- a/bisect.c
+++ b/bisect.c
FILE *fp = fopen(filename, "r");
if (!fp)
- die("Could not open file '%s': %s", filename, strerror(errno));
+ die_errno("Could not open file '%s'", filename);
while (strbuf_getline(&str, fp, '\n') != EOF) {
char *quoted;
return filtered;
}
-static struct commit_list *apply_skip_ratio(struct commit_list *list,
- int count,
- int skip_num, int skip_denom)
+#define PRN_MODULO 32768
+
+/*
+ * This is a pseudo random number generator based on "man 3 rand".
+ * It is not used properly because the seed is the argument and it
+ * is increased by one between each call, but that should not matter
+ * for this application.
+ */
+int get_prn(int count) {
+ count = count * 1103515245 + 12345;
+ return ((unsigned)(count/65536) % PRN_MODULO);
+}
+
+/*
+ * Custom integer square root from
+ * http://en.wikipedia.org/wiki/Integer_square_root
+ */
+static int sqrti(int val)
+{
+ float d, x = val;
+
+ if (val == 0)
+ return 0;
+
+ do {
+ float y = (x + (float)val / x) / 2;
+ d = (y > x) ? y - x : x - y;
+ x = y;
+ } while (d >= 0.5);
+
+ return (int)x;
+}
+
+static struct commit_list *skip_away(struct commit_list *list, int count)
{
- int index, i;
struct commit_list *cur, *previous;
+ int prn, index, i;
+
+ prn = get_prn(count);
+ index = (count * prn / PRN_MODULO) * sqrti(prn) / sqrti(PRN_MODULO);
cur = list;
previous = NULL;
- index = count * skip_num / skip_denom;
for (i = 0; cur; cur = cur->next, i++) {
if (i == index) {
struct commit_list **tried)
{
int count, skipped_first;
- int skip_num, skip_denom;
*tried = NULL;
if (!skipped_first)
return list;
- /* Use alternatively 1/5, 2/5 and 3/5 as skip ratio. */
- skip_num = count % 3 + 1;
- skip_denom = 5;
-
- return apply_skip_ratio(list, count, skip_num, skip_denom);
+ return skip_away(list, count);
}
static void bisect_rev_setup(struct rev_info *revs, const char *prefix,
int fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0600);
if (fd < 0)
- die("could not create file '%s': %s",
- filename, strerror(errno));
+ die_errno("could not create file '%s'", filename);
bisect_rev_hex[len] = '\n';
write_or_die(fd, bisect_rev_hex, len + 1);
diff --git a/branch.c b/branch.c
index 62030af4b51abbfb9c488dbf018770f3b3606789..05ef3f5c9ce6e1b55a7eb483a197fe9fd6e5437d 100644 (file)
--- a/branch.c
+++ b/branch.c
lock = lock_any_ref_for_update(ref.buf, NULL, 0);
if (!lock)
- die("Failed to lock ref for update: %s.", strerror(errno));
+ die_errno("Failed to lock ref for update");
if (reflog)
log_all_ref_updates = 1;
setup_tracking(name, real_ref, track);
if (write_ref_sha1(lock, sha1, msg) < 0)
- die("Failed to write ref: %s.", strerror(errno));
+ die_errno("Failed to write ref");
strbuf_release(&ref);
free(real_ref);
diff --git a/builtin-add.c b/builtin-add.c
index 4e44148e05843e03befc167f6bdf3a1567d3f8ad..78989dad8cb07dee00054c3ea98d16eb493a05c9 100644 (file)
--- a/builtin-add.c
+++ b/builtin-add.c
launch_editor(file, NULL, NULL);
if (stat(file, &st))
- die("Could not stat '%s'", file);
+ die_errno("Could not stat '%s'", file);
if (!st.st_size)
die("Empty patch. Aborted.");
diff --git a/builtin-apply.c b/builtin-apply.c
index 4cf819c7905d5997a6ce2a89b4ecce1176a4b045..dc0ff5e08ae73f2832fd4451cce2e849c88be5a8 100644 (file)
--- a/builtin-apply.c
+++ b/builtin-apply.c
static void read_patch_file(struct strbuf *sb, int fd)
{
if (strbuf_read(sb, fd, 0) < 0)
- die("git apply: read returned %s", strerror(errno));
+ die_errno("git apply: failed to read");
/*
* Make sure that we have some slop in the buffer
@@ -2823,8 +2823,8 @@ static void add_index_file(const char *path, unsigned mode, void *buf, unsigned
} else {
if (!cached) {
if (lstat(path, &st) < 0)
- die("unable to stat newly created file %s",
- path);
+ die_errno("unable to stat newly created file '%s'",
+ path);
fill_stat_cache_info(ce, &st);
}
if (write_sha1_file(buf, size, blob_type, ce->sha1) < 0)
@@ -2864,7 +2864,7 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf,
strbuf_release(&nbuf);
if (close(fd) < 0)
- die("closing file %s: %s", path, strerror(errno));
+ die_errno("closing file '%s'", path);
return 0;
}
@@ -2913,7 +2913,7 @@ static void create_one_file(char *path, unsigned mode, const char *buf, unsigned
++nr;
}
}
- die("unable to write file %s mode %o", path, mode);
+ die_errno("unable to write file '%s' mode %o", path, mode);
}
static void create_file(struct patch *patch)
fd = open(arg, O_RDONLY);
if (fd < 0)
- die("can't open patch '%s': %s", arg, strerror(errno));
+ die_errno("can't open patch '%s'", arg);
read_stdin = 0;
set_default_whitespace_mode(whitespace_option);
errs |= apply_patch(fd, arg, options);
diff --git a/builtin-archive.c b/builtin-archive.c
index 3c5a5a7822afebf87ef6eb1f89c7c54d76844161..f9a4bea41e95b9a34f190fc2b696c7394d0e0971 100644 (file)
--- a/builtin-archive.c
+++ b/builtin-archive.c
{
int output_fd = open(output_file, O_CREAT | O_WRONLY | O_TRUNC, 0666);
if (output_fd < 0)
- die("could not create archive file: %s ", output_file);
+ die_errno("could not create archive file '%s'", output_file);
if (output_fd != 1) {
if (dup2(output_fd, 1) < 0)
- die("could not redirect output");
+ die_errno("could not redirect output");
else
close(output_fd);
}
diff --git a/builtin-blame.c b/builtin-blame.c
index 0c2d29a43005e0afe7c0b0754499a37156e235ef..fd6ca51eebb2234be429b47b572ae2f30592ff4e 100644 (file)
--- a/builtin-blame.c
+++ b/builtin-blame.c
@@ -2008,23 +2008,23 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
if (contents_from) {
if (stat(contents_from, &st) < 0)
- die("Cannot stat %s", contents_from);
+ die_errno("Cannot stat '%s'", contents_from);
read_from = contents_from;
}
else {
if (lstat(path, &st) < 0)
- die("Cannot lstat %s", path);
+ die_errno("Cannot lstat '%s'", path);
read_from = path;
}
mode = canon_mode(st.st_mode);
switch (st.st_mode & S_IFMT) {
case S_IFREG:
if (strbuf_read_file(&buf, read_from, st.st_size) != st.st_size)
- die("cannot open or read %s", read_from);
+ die_errno("cannot open or read '%s'", read_from);
break;
case S_IFLNK:
if (strbuf_readlink(&buf, read_from, st.st_size) < 0)
- die("cannot readlink %s", read_from);
+ die_errno("cannot readlink '%s'", read_from);
break;
default:
die("unsupported file type %s", read_from);
@@ -2035,7 +2035,7 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
contents_from = "standard input";
mode = 0;
if (strbuf_read(&buf, 0, 0) < 0)
- die("read error %s from stdin", strerror(errno));
+ die_errno("failed to read from stdin");
}
convert_to_git(path, buf.buf, buf.len, &buf, 0);
origin->file.ptr = buf.buf;
argc = parse_options_end(&ctx);
if (revs_file && read_ancestry(revs_file))
- die("reading graft file %s failed: %s",
- revs_file, strerror(errno));
+ die_errno("reading graft file '%s' failed", revs_file);
if (cmd_is_annotate) {
output_option |= OUTPUT_ANNOTATE_COMPAT;
setup_work_tree();
if (!has_string_in_work_tree(path))
- die("cannot stat path %s: %s", path, strerror(errno));
+ die_errno("cannot stat path '%s'", path);
}
setup_revisions(argc, argv, &revs, NULL);
diff --git a/builtin-clone.c b/builtin-clone.c
index 2ceacb7b3f34c78e64ed047833d8af5a061f065f..32dea74d78381ca1dffdac7f88e45a89a9825104 100644 (file)
--- a/builtin-clone.c
+++ b/builtin-clone.c
dir = opendir(src->buf);
if (!dir)
- die("failed to open %s", src->buf);
+ die_errno("failed to open '%s'", src->buf);
if (mkdir(dest->buf, 0777)) {
if (errno != EEXIST)
- die("failed to create directory %s", dest->buf);
+ die_errno("failed to create directory '%s'", dest->buf);
else if (stat(dest->buf, &buf))
- die("failed to stat %s", dest->buf);
+ die_errno("failed to stat '%s'", dest->buf);
else if (!S_ISDIR(buf.st_mode))
die("%s exists and is not a directory", dest->buf);
}
}
if (unlink(dest->buf) && errno != ENOENT)
- die("failed to unlink %s: %s",
- dest->buf, strerror(errno));
+ die_errno("failed to unlink '%s'", dest->buf);
if (!option_no_hardlinks) {
if (!link(src->buf, dest->buf))
continue;
if (option_local)
- die("failed to create link %s", dest->buf);
+ die_errno("failed to create link '%s'", dest->buf);
option_no_hardlinks = 1;
}
if (copy_file(dest->buf, src->buf, 0666))
- die("failed to copy file to %s", dest->buf);
+ die_errno("failed to copy file to '%s'", dest->buf);
}
closedir(dir);
}
if (!option_bare) {
junk_work_tree = work_tree;
if (safe_create_leading_directories_const(work_tree) < 0)
- die("could not create leading directories of '%s': %s",
- work_tree, strerror(errno));
+ die_errno("could not create leading directories of '%s'",
+ work_tree);
if (!dest_exists && mkdir(work_tree, 0755))
- die("could not create work tree dir '%s': %s.",
- work_tree, strerror(errno));
+ die_errno("could not create work tree dir '%s'.",
+ work_tree);
set_git_work_tree(work_tree);
}
junk_git_dir = git_dir;
diff --git a/builtin-commit-tree.c b/builtin-commit-tree.c
index 0453425c471f1d6793bc7f5f59d17e9d285ddfc6..64670777312c71d45b10f72a1efe9fceae3e3b89 100644 (file)
--- a/builtin-commit-tree.c
+++ b/builtin-commit-tree.c
}
if (strbuf_read(&buffer, 0, 0) < 0)
- die("git commit-tree: read returned %s", strerror(errno));
+ die_errno("git commit-tree: failed to read");
if (!commit_tree(buffer.buf, tree_sha1, parents, commit_sha1, NULL)) {
printf("%s\n", sha1_to_hex(commit_sha1));
diff --git a/builtin-commit.c b/builtin-commit.c
index 41e222d267ca952c3bc0c8d6b1e19c0171df0c62..4bcce06fbffdf10ec701dfbc0b6b90a11513f89e 100644 (file)
--- a/builtin-commit.c
+++ b/builtin-commit.c
if (isatty(0))
fprintf(stderr, "(reading log message from standard input)\n");
if (strbuf_read(&sb, 0, 0) < 0)
- die("could not read log from standard input");
+ die_errno("could not read log from standard input");
hook_arg1 = "message";
} else if (logfile) {
if (strbuf_read_file(&sb, logfile, 0) < 0)
- die("could not read log file '%s': %s",
- logfile, strerror(errno));
+ die_errno("could not read log file '%s'",
+ logfile);
hook_arg1 = "message";
} else if (use_message) {
buffer = strstr(use_message_buffer, "\n\n");
hook_arg2 = use_message;
} else if (!stat(git_path("MERGE_MSG"), &statbuf)) {
if (strbuf_read_file(&sb, git_path("MERGE_MSG"), 0) < 0)
- die("could not read MERGE_MSG: %s", strerror(errno));
+ die_errno("could not read MERGE_MSG");
hook_arg1 = "merge";
} else if (!stat(git_path("SQUASH_MSG"), &statbuf)) {
if (strbuf_read_file(&sb, git_path("SQUASH_MSG"), 0) < 0)
- die("could not read SQUASH_MSG: %s", strerror(errno));
+ die_errno("could not read SQUASH_MSG");
hook_arg1 = "squash";
} else if (template_file && !stat(template_file, &statbuf)) {
if (strbuf_read_file(&sb, template_file, 0) < 0)
- die("could not read %s: %s",
- template_file, strerror(errno));
+ die_errno("could not read '%s'", template_file);
hook_arg1 = "template";
}
fp = fopen(git_path(commit_editmsg), "w");
if (fp == NULL)
- die("could not open %s: %s",
- git_path(commit_editmsg), strerror(errno));
+ die_errno("could not open '%s'", git_path(commit_editmsg));
if (cleanup_mode != CLEANUP_NONE)
stripspace(&sb, 0);
}
if (fwrite(sb.buf, 1, sb.len, fp) < sb.len)
- die("could not write commit template: %s", strerror(errno));
+ die_errno("could not write commit template");
strbuf_release(&sb);
pptr = &commit_list_insert(lookup_commit(head_sha1), pptr)->next;
fp = fopen(git_path("MERGE_HEAD"), "r");
if (fp == NULL)
- die("could not open %s for reading: %s",
- git_path("MERGE_HEAD"), strerror(errno));
+ die_errno("could not open '%s' for reading",
+ git_path("MERGE_HEAD"));
while (strbuf_getline(&m, fp, '\n') != EOF) {
unsigned char sha1[20];
if (get_sha1_hex(m.buf, sha1) < 0)
strbuf_release(&m);
if (!stat(git_path("MERGE_MODE"), &statbuf)) {
if (strbuf_read_file(&sb, git_path("MERGE_MODE"), 0) < 0)
- die("could not read MERGE_MODE: %s",
- strerror(errno));
+ die_errno("could not read MERGE_MODE");
if (!strcmp(sb.buf, "no-ff"))
allow_fast_forward = 0;
}
/* Finally, get the commit message */
strbuf_reset(&sb);
if (strbuf_read_file(&sb, git_path(commit_editmsg), 0) < 0) {
+ int saved_errno = errno;
rollback_index_files();
- die("could not read commit message");
+ die("could not read commit message: %s", strerror(saved_errno));
}
/* Truncate the message just before the diff, if any. */
diff --git a/builtin-config.c b/builtin-config.c
index 60915f91caff02997222d18bc625d242d95c6bb1..a2d656edb383da47fb3622f1f7c2d1524285ac00 100644 (file)
--- a/builtin-config.c
+++ b/builtin-config.c
check_argc(argc, 0, 0);
if (git_config(show_all_config, NULL) < 0) {
if (config_exclusive_filename)
- die("unable to read config file %s: %s",
- config_exclusive_filename, strerror(errno));
+ die_errno("unable to read config file '%s'",
+ config_exclusive_filename);
else
die("error processing config file(s)");
}
diff --git a/builtin-diff.c b/builtin-diff.c
index d75d69bf5774ffd402bbeec47b9a0e0800554d63..2e51f408f9f3399195604fd23d430c180a7f20a4 100644 (file)
--- a/builtin-diff.c
+++ b/builtin-diff.c
usage(builtin_diff_usage);
if (lstat(path, &st))
- die("'%s': %s", path, strerror(errno));
+ die_errno("failed to stat '%s'", path);
if (!(S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)))
die("'%s': not a regular file or symlink", path);
diff --git a/builtin-fast-export.c b/builtin-fast-export.c
index 6cef8103127a8748acb64ca7ec7a7a95fb639cd3..9a8a6fc6b1e98162a1548b40bd4281172e18d7b2 100644 (file)
--- a/builtin-fast-export.c
+++ b/builtin-fast-export.c
printf("blob\nmark :%"PRIu32"\ndata %lu\n", last_idnum, size);
if (size && fwrite(buf, size, 1, stdout) != 1)
- die ("Could not write blob %s", sha1_to_hex(sha1));
+ die_errno ("Could not write blob '%s'", sha1_to_hex(sha1));
printf("\n");
show_progress();
char line[512];
FILE *f = fopen(input_file, "r");
if (!f)
- die("cannot read %s: %s", input_file, strerror(errno));
+ die_errno("cannot read '%s'", input_file);
while (fgets(line, sizeof(line), f)) {
uint32_t mark;
diff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c
index 29356d25db910c6d90df46da87aa374467611350..3dbdf7a2887002f0d7a67a1db35bd3c72d7a9d30 100644 (file)
--- a/builtin-fetch--tool.c
+++ b/builtin-fetch--tool.c
{
struct strbuf buf = STRBUF_INIT;
if (strbuf_read(&buf, 0, 1024) < 0) {
- die("error reading standard input: %s", strerror(errno));
+ die_errno("error reading standard input");
}
return strbuf_detach(&buf, NULL);
}
index fbf9582e667dfd1e69027b35c3f307f3c7a08a99..9d524000b5ba4d9c7566edd5756b68d728ec362b 100644 (file)
--- a/builtin-fmt-merge-msg.c
+++ b/builtin-fmt-merge-msg.c
if (inpath && strcmp(inpath, "-")) {
in = fopen(inpath, "r");
if (!in)
- die("cannot open %s", inpath);
+ die_errno("cannot open '%s'", inpath);
}
if (strbuf_read(&input, fileno(in), 0) < 0)
- die("could not read input file %s", strerror(errno));
-
+ die_errno("could not read input file");
ret = fmt_merge_msg(merge_summary, &input, &output);
if (ret)
return ret;
diff --git a/builtin-fsck.c b/builtin-fsck.c
index e077e72dea94892e2f74ddd6be528b02bc6ccea4..b3d38fa277b3d0024b9c46a62cf15bc2448cc1e7 100644 (file)
--- a/builtin-fsck.c
+++ b/builtin-fsck.c
return;
}
if (!(f = fopen(filename, "w")))
- die("Could not open %s", filename);
+ die_errno("Could not open '%s'", filename);
if (obj->type == OBJ_BLOB) {
enum object_type type;
unsigned long size;
&type, &size);
if (buf) {
if (fwrite(buf, size, 1, f) != 1)
- die("Could not write %s: %s",
- filename, strerror(errno));
+ die_errno("Could not write '%s'",
+ filename);
free(buf);
}
} else
fprintf(f, "%s\n", sha1_to_hex(obj->sha1));
if (fclose(f))
- die("Could not finish %s: %s",
- filename, strerror(errno));
+ die_errno("Could not finish '%s'",
+ filename);
}
return;
}
diff --git a/builtin-grep.c b/builtin-grep.c
index 73fc922c4995369c0ca86c01200e2a0ea39161ab..f477659100fdc63bff5938b4c96f28eaefc07460 100644 (file)
--- a/builtin-grep.c
+++ b/builtin-grep.c
#include "tree-walk.h"
#include "builtin.h"
#include "parse-options.h"
+#include "userdiff.h"
#include "grep.h"
#ifndef NO_EXTERNAL_GREP
{
struct grep_opt *opt = cb;
+ switch (userdiff_config(var, value)) {
+ case 0: break;
+ case -1: return -1;
+ default: return 0;
+ }
+
if (!strcmp(var, "color.grep")) {
opt->color = git_config_colorbool(var, value, -1);
return 0;
argc -= 2;
}
+ if (opt->pre_context || opt->post_context) {
+ /*
+ * grep handles hunk marks between files, but we need to
+ * do that ourselves between multiple calls.
+ */
+ if (opt->show_hunk_mark)
+ write_or_die(1, "--\n", 3);
+ else
+ opt->show_hunk_mark = 1;
+ }
+
status = exec_grep(argc, argv);
if (kept_0) {
patterns = fopen(arg, "r");
if (!patterns)
- die("'%s': %s", arg, strerror(errno));
+ die_errno("cannot open '%s'", arg);
while (strbuf_getline(&sb, patterns, '\n') == 0) {
/* ignore empty line like grep does */
if (sb.len == 0)
"show <n> context lines after matches"),
OPT_NUMBER_CALLBACK(&opt, "shortcut for -C NUM",
context_callback),
+ OPT_BOOLEAN('p', "show-function", &opt.funcname,
+ "show a line with the function name before matches"),
OPT_GROUP(""),
OPT_CALLBACK('f', NULL, &opt, "file",
"read patterns from file", file_callback),
argc--;
}
- if (opt.color && !opt.color_external)
+ if ((opt.color && !opt.color_external) || opt.funcname)
external_grep_allowed = 0;
if (!opt.pattern_list)
die("no pattern given.");
diff --git a/builtin-init-db.c b/builtin-init-db.c
index d1fa12a59efb34256b2cc80b03c637cc844d84ff..4a5600631c5800d7f9d844118f37c0672b89b581 100644 (file)
--- a/builtin-init-db.c
+++ b/builtin-init-db.c
memcpy(template + template_baselen, de->d_name, namelen+1);
if (lstat(path, &st_git)) {
if (errno != ENOENT)
- die("cannot stat %s", path);
+ die_errno("cannot stat '%s'", path);
}
else
exists = 1;
if (lstat(template, &st_template))
- die("cannot stat template %s", template);
+ die_errno("cannot stat template '%s'", template);
if (S_ISDIR(st_template.st_mode)) {
DIR *subdir = opendir(template);
int baselen_sub = baselen + namelen;
int template_baselen_sub = template_baselen + namelen;
if (!subdir)
- die("cannot opendir %s", template);
+ die_errno("cannot opendir '%s'", template);
path[baselen_sub++] =
template[template_baselen_sub++] = '/';
path[baselen_sub] =
int len;
len = readlink(template, lnk, sizeof(lnk));
if (len < 0)
- die("cannot readlink %s", template);
+ die_errno("cannot readlink '%s'", template);
if (sizeof(lnk) <= len)
die("insanely long symlink %s", template);
lnk[len] = 0;
if (symlink(lnk, path))
- die("cannot symlink %s %s", lnk, path);
+ die_errno("cannot symlink '%s' '%s'", lnk, path);
}
else if (S_ISREG(st_template.st_mode)) {
if (copy_file(path, template, st_template.st_mode))
- die("cannot copy %s to %s", template, path);
+ die_errno("cannot copy '%s' to '%s'", template,
+ path);
}
else
error("ignoring template %s", template);
if (!strcmp(".", git_dir))
return 1;
if (!getcwd(cwd, sizeof(cwd)))
- die("cannot tell cwd");
+ die_errno("cannot tell cwd");
if (!strcmp(git_dir, cwd))
return 1;
/*
if (!git_work_tree_cfg) {
git_work_tree_cfg = xcalloc(PATH_MAX, 1);
if (!getcwd(git_work_tree_cfg, PATH_MAX))
- die ("Cannot access current working directory.");
+ die_errno ("Cannot access current working directory");
}
if (access(get_git_work_tree(), X_OK))
- die ("Cannot access work tree '%s'",
- get_git_work_tree());
+ die_errno ("Cannot access work tree '%s'",
+ get_git_work_tree());
}
set_git_dir(make_absolute_path(git_dir));
diff --git a/builtin-log.c b/builtin-log.c
index 44f9a27daec612db6d0f0e502c99d5e5ecaaf842..0c2fa0ae2dc3f23cd52d2e8d765805b07262a7d6 100644 (file)
--- a/builtin-log.c
+++ b/builtin-log.c
if (use_stdout)
die("standard output, or directory, which one?");
if (mkdir(output_directory, 0777) < 0 && errno != EEXIST)
- die("Could not create directory %s",
- output_directory);
+ die_errno("Could not create directory '%s'",
+ output_directory);
}
if (rev.pending.nr == 1) {
diff --git a/builtin-mailsplit.c b/builtin-mailsplit.c
index 71f3b3b8741e505fc652e6c74c75972f19211f71..ad5f6b593df45f01360f3daa8b37d024ee793e9e 100644 (file)
--- a/builtin-mailsplit.c
+++ b/builtin-mailsplit.c
fd = open(name, O_WRONLY | O_CREAT | O_EXCL, 0666);
if (fd < 0)
- die("cannot open output file %s", name);
+ die_errno("cannot open output file '%s'", name);
output = fdopen(fd, "w");
/* Copy it out, while searching for a line that begins with
int is_partial = len && buf[len-1] != '\n';
if (fwrite(buf, 1, len, output) != len)
- die("cannot write output");
+ die_errno("cannot write output");
len = read_line_with_nul(buf, sizeof(buf), mbox);
if (len == 0) {
status = 1;
break;
}
- die("cannot read mbox");
+ die_errno("cannot read mbox");
}
if (!is_partial && !is_bare && is_from_line(buf, len))
break; /* done with one message */
diff --git a/builtin-merge.c b/builtin-merge.c
index af9adab300de98026b23a58b1d8b40f9395ff11a..82b546689c500649285ea2c7825171f572c3758e 100644 (file)
--- a/builtin-merge.c
+++ b/builtin-merge.c
printf("Squash commit -- not updating HEAD\n");
fd = open(git_path("SQUASH_MSG"), O_WRONLY | O_CREAT, 0666);
if (fd < 0)
- die("Could not write to %s", git_path("SQUASH_MSG"));
+ die_errno("Could not write to '%s'", git_path("SQUASH_MSG"));
init_revisions(&rev, NULL);
rev.ignore_merges = 1;
NULL, NULL, rev.date_mode, 0);
}
if (write(fd, out.buf, out.len) < 0)
- die("Writing SQUASH_MSG: %s", strerror(errno));
+ die_errno("Writing SQUASH_MSG");
if (close(fd))
- die("Finishing SQUASH_MSG: %s", strerror(errno));
+ die_errno("Finishing SQUASH_MSG");
strbuf_release(&out);
}
fp = fopen(git_path("FETCH_HEAD"), "r");
if (!fp)
- die("could not open %s for reading: %s",
- git_path("FETCH_HEAD"), strerror(errno));
+ die_errno("could not open '%s' for reading",
+ git_path("FETCH_HEAD"));
strbuf_getline(&line, fp, '\n');
fclose(fp);
ptr = strstr(line.buf, "\tnot-for-merge\t");
fp = fopen(git_path("MERGE_MSG"), "a");
if (!fp)
- die("Could not open %s for writing", git_path("MERGE_MSG"));
+ die_errno("Could not open '%s' for writing",
+ git_path("MERGE_MSG"));
fprintf(fp, "\nConflicts:\n");
for (pos = 0; pos < active_nr; pos++) {
struct cache_entry *ce = active_cache[pos];
sha1_to_hex(j->item->object.sha1));
fd = open(git_path("MERGE_HEAD"), O_WRONLY | O_CREAT, 0666);
if (fd < 0)
- die("Could open %s for writing",
- git_path("MERGE_HEAD"));
+ die_errno("Could not open '%s' for writing",
+ git_path("MERGE_HEAD"));
if (write_in_full(fd, buf.buf, buf.len) != buf.len)
- die("Could not write to %s", git_path("MERGE_HEAD"));
+ die_errno("Could not write to '%s'", git_path("MERGE_HEAD"));
close(fd);
strbuf_addch(&merge_msg, '\n');
fd = open(git_path("MERGE_MSG"), O_WRONLY | O_CREAT, 0666);
if (fd < 0)
- die("Could open %s for writing", git_path("MERGE_MSG"));
+ die_errno("Could not open '%s' for writing",
+ git_path("MERGE_MSG"));
if (write_in_full(fd, merge_msg.buf, merge_msg.len) !=
merge_msg.len)
- die("Could not write to %s", git_path("MERGE_MSG"));
+ die_errno("Could not write to '%s'", git_path("MERGE_MSG"));
close(fd);
fd = open(git_path("MERGE_MODE"), O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (fd < 0)
- die("Could open %s for writing", git_path("MERGE_MODE"));
+ die_errno("Could not open '%s' for writing",
+ git_path("MERGE_MODE"));
strbuf_reset(&buf);
if (!allow_fast_forward)
strbuf_addf(&buf, "no-ff");
if (write_in_full(fd, buf.buf, buf.len) != buf.len)
- die("Could not write to %s", git_path("MERGE_MODE"));
+ die_errno("Could not write to '%s'", git_path("MERGE_MODE"));
close(fd);
}
diff --git a/builtin-mv.c b/builtin-mv.c
index 8b81d4b51d78bb2aa49430102ab585afce9cccdf..b592c367b2cc016a50db6d49948e9efbbf0e8f2f 100644 (file)
--- a/builtin-mv.c
+++ b/builtin-mv.c
result[count] = NULL;
for (i = 0; i < count; i++) {
int length = strlen(result[i]);
- if (length > 0 && result[i][length - 1] == '/') {
+ if (length > 0 && is_dir_sep(result[i][length - 1]))
result[i] = xmemdupz(result[i], length - 1);
- }
- if (base_name) {
- const char *last_slash = strrchr(result[i], '/');
- if (last_slash)
- result[i] = last_slash + 1;
- }
+ if (base_name)
+ result[i] = basename((char *)result[i]);
}
return get_pathspec(prefix, result);
}
printf("Renaming %s to %s\n", src, dst);
if (!show_only && mode != INDEX &&
rename(src, dst) < 0 && !ignore_errors)
- die ("renaming %s failed: %s", src, strerror(errno));
+ die_errno ("renaming '%s' failed", src);
if (mode == WORKING_DIRECTORY)
continue;
diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
index 941cc2d73cf5ee6791a0cee8c409dcdb9756b448..a27c2f6277cd55951cec5d9b5b207df426ed9ff0 100644 (file)
--- a/builtin-pack-objects.c
+++ b/builtin-pack-objects.c
base_name, sha1_to_hex(sha1));
free_pack_by_name(tmpname);
if (adjust_perm(pack_tmp_name, mode))
- die("unable to make temporary pack file readable: %s",
- strerror(errno));
+ die_errno("unable to make temporary pack file readable");
if (rename(pack_tmp_name, tmpname))
- die("unable to rename temporary pack file: %s",
- strerror(errno));
+ die_errno("unable to rename temporary pack file");
/*
* Packs are runtime accessed in their mtime
snprintf(tmpname, sizeof(tmpname), "%s-%s.idx",
base_name, sha1_to_hex(sha1));
if (adjust_perm(idx_tmp_name, mode))
- die("unable to make temporary index file readable: %s",
- strerror(errno));
+ die_errno("unable to make temporary index file readable");
if (rename(idx_tmp_name, tmpname))
- die("unable to rename temporary index file: %s",
- strerror(errno));
+ die_errno("unable to rename temporary index file");
free(idx_tmp_name);
free(pack_tmp_name);
if (!ferror(stdin))
die("fgets returned NULL, not EOF, not error!");
if (errno != EINTR)
- die("fgets: %s", strerror(errno));
+ die_errno("fgets");
clearerr(stdin);
continue;
}
diff --git a/builtin-receive-pack.c b/builtin-receive-pack.c
index 33d345dc3993d01d3cd5ae1cc0aa5ae8eda83edb..6ec1d056e6fa24bf6008d9114df5d5cdacd837af 100644 (file)
--- a/builtin-receive-pack.c
+++ b/builtin-receive-pack.c
static const char pre_receive_hook[] = "hooks/pre-receive";
static const char post_receive_hook[] = "hooks/post-receive";
-static int hook_status(int code, const char *hook_name)
+static int run_status(int code, const char *cmd_name)
{
switch (code) {
case 0:
return 0;
case -ERR_RUN_COMMAND_FORK:
- return error("hook fork failed");
+ return error("fork of %s failed", cmd_name);
case -ERR_RUN_COMMAND_EXEC:
- return error("hook execute failed");
+ return error("execute of %s failed", cmd_name);
case -ERR_RUN_COMMAND_PIPE:
- return error("hook pipe failed");
+ return error("pipe failed");
case -ERR_RUN_COMMAND_WAITPID:
return error("waitpid failed");
case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
return error("waitpid is confused");
case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
- return error("%s died of signal", hook_name);
+ return error("%s died of signal", cmd_name);
case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
- return error("%s died strangely", hook_name);
+ return error("%s died strangely", cmd_name);
default:
- error("%s exited with error code %d", hook_name, -code);
+ error("%s exited with error code %d", cmd_name, -code);
return -code;
}
}
code = start_command(&proc);
if (code)
- return hook_status(code, hook_name);
+ return run_status(code, hook_name);
for (cmd = commands; cmd; cmd = cmd->next) {
if (!cmd->error_string) {
size_t n = snprintf(buf, sizeof(buf), "%s %s %s\n",
}
}
close(proc.in);
- return hook_status(finish_command(&proc), hook_name);
+ return run_status(finish_command(&proc), hook_name);
}
static int run_update_hook(struct command *cmd)
argv[3] = sha1_to_hex(cmd->new_sha1);
argv[4] = NULL;
- return hook_status(run_command_v_opt(argv, RUN_COMMAND_NO_STDIN |
+ return run_status(run_command_v_opt(argv, RUN_COMMAND_NO_STDIN |
RUN_COMMAND_STDOUT_TO_STDERR),
update_hook);
}
static void run_update_post_hook(struct command *cmd)
{
struct command *cmd_p;
- int argc;
+ int argc, status;
const char **argv;
for (argc = 0, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
argc++;
}
argv[argc] = NULL;
- run_command_v_opt(argv, RUN_COMMAND_NO_STDIN
- | RUN_COMMAND_STDOUT_TO_STDERR);
+ status = run_command_v_opt(argv, RUN_COMMAND_NO_STDIN
+ | RUN_COMMAND_STDOUT_TO_STDERR);
+ run_status(status, update_post_hook);
}
static void execute_commands(const char *unpacker_error)
unpacker[i++] = hdr_arg;
unpacker[i++] = NULL;
code = run_command_v_opt(unpacker, RUN_GIT_CMD);
- switch (code) {
- case 0:
+ if (!code)
return NULL;
- case -ERR_RUN_COMMAND_FORK:
- return "unpack fork failed";
- case -ERR_RUN_COMMAND_EXEC:
- return "unpack execute failed";
- case -ERR_RUN_COMMAND_WAITPID:
- return "waitpid failed";
- case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
- return "waitpid is confused";
- case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
- return "unpacker died of signal";
- case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
- return "unpacker died strangely";
- default:
- return "unpacker exited with error code";
- }
+ run_status(code, unpacker[0]);
+ return "unpack-objects abnormal exit";
} else {
const char *keeper[7];
int s, status, i = 0;
ip.argv = keeper;
ip.out = -1;
ip.git_cmd = 1;
- if (start_command(&ip))
+ status = start_command(&ip);
+ if (status) {
+ run_status(status, keeper[0]);
return "index-pack fork failed";
+ }
pack_lockfile = index_pack_lockfile(ip.out);
close(ip.out);
status = finish_command(&ip);
reprepare_packed_git();
return NULL;
}
+ run_status(status, keeper[0]);
return "index-pack abnormal exit";
}
}
diff --git a/builtin-remote.c b/builtin-remote.c
index 2fb76d32f86cb4e699036b40eac9bd9a747fb77f..008abfe0922f6d1662aebcfbf63ba9f47de4ae65 100644 (file)
--- a/builtin-remote.c
+++ b/builtin-remote.c
read_branches();
if (query) {
- transport = transport_get(NULL, states->remote->url_nr > 0 ?
+ transport = transport_get(states->remote, states->remote->url_nr > 0 ?
states->remote->url[0] : NULL);
remote_refs = transport_get_remote_refs(transport);
transport_disconnect(transport);
diff --git a/builtin-rev-parse.c b/builtin-rev-parse.c
index 112d622cda6f74f9752627d9adf3a1cdb04851c3..45bead65451e87a4b564e59fed3518a4de9198e9 100644 (file)
--- a/builtin-rev-parse.c
+++ b/builtin-rev-parse.c
static int cmd_parseopt(int argc, const char **argv, const char *prefix)
{
- static int keep_dashdash = 0;
+ static int keep_dashdash = 0, stop_at_non_option = 0;
static char const * const parseopt_usage[] = {
"git rev-parse --parseopt [options] -- [<args>...]",
NULL
static struct option parseopt_opts[] = {
OPT_BOOLEAN(0, "keep-dashdash", &keep_dashdash,
"keep the `--` passed as an arg"),
+ OPT_BOOLEAN(0, "stop-at-non-option", &stop_at_non_option,
+ "stop parsing after the "
+ "first non-option argument"),
OPT_END(),
};
ALLOC_GROW(opts, onb + 1, osz);
memset(opts + onb, 0, sizeof(opts[onb]));
argc = parse_options(argc, argv, prefix, opts, usage,
- keep_dashdash ? PARSE_OPT_KEEP_DASHDASH : 0);
+ keep_dashdash ? PARSE_OPT_KEEP_DASHDASH : 0 |
+ stop_at_non_option ? PARSE_OPT_STOP_AT_NON_OPTION : 0);
strbuf_addf(&parsed, " --");
sq_quote_argv(&parsed, argv, 0);
continue;
}
if (!getcwd(cwd, PATH_MAX))
- die("unable to get current working directory");
+ die_errno("unable to get current working directory");
printf("%s/.git\n", cwd);
continue;
}
diff --git a/builtin-revert.c b/builtin-revert.c
index c87115af30abd9515599586af860ccd07b96b264..151aa6a981832954120359f7c953015525b530d8 100644 (file)
--- a/builtin-revert.c
+++ b/builtin-revert.c
{
int len = strlen(string);
if (write_in_full(msg_fd, string, len) < 0)
- die ("Could not write to MERGE_MSG");
+ die_errno ("Could not write to MERGE_MSG");
}
static void add_message_to_msg(const char *message)
diff --git a/builtin-rm.c b/builtin-rm.c
index 0cc491271846214d73d55a4f528c8854e0460c8f..57975dbcfd7c0dbcba03b88a1bf403f1ec5f528c 100644 (file)
--- a/builtin-rm.c
+++ b/builtin-rm.c
continue;
}
if (!removed)
- die("git rm: %s: %s", path, strerror(errno));
+ die_errno("git rm: '%s'", path);
}
}
diff --git a/builtin-send-pack.c b/builtin-send-pack.c
index c375a3dbde0a75af592c8881965f255f66b599d1..47fb9f7baa9ad9c070e1a6d9c245300ba2402ce5 100644 (file)
--- a/builtin-send-pack.c
+++ b/builtin-send-pack.c
po.out = fd;
po.git_cmd = 1;
if (start_command(&po))
- die("git pack-objects failed (%s)", strerror(errno));
+ die_errno("git pack-objects failed");
/*
* We feed the pack-objects we just spawned with revision
diff --git a/builtin-show-ref.c b/builtin-show-ref.c
index dc76c5090f2367426201b37c5b13c2a5cbf00de2..c46550c9c01da8fe74145e16656a5163a7e4f07b 100644 (file)
--- a/builtin-show-ref.c
+++ b/builtin-show-ref.c
#include "object.h"
#include "tag.h"
#include "string-list.h"
+#include "parse-options.h"
-static const char show_ref_usage[] = "git show-ref [-q|--quiet] [--verify] [-h|--head] [-d|--dereference] [-s|--hash[=<length>]] [--abbrev[=<length>]] [--tags] [--heads] [--] [pattern*] < ref-list";
+static const char * const show_ref_usage[] = {
+ "git show-ref [-q|--quiet] [--verify] [-h|--head] [-d|--dereference] [-s|--hash[=<n>]] [--abbrev[=<n>]] [--tags] [--heads] [--] [pattern*] ",
+ "git show-ref --exclude-existing[=pattern] < ref-list",
+ NULL
+};
-static int deref_tags = 0, show_head = 0, tags_only = 0, heads_only = 0,
- found_match = 0, verify = 0, quiet = 0, hash_only = 0, abbrev = 0;
+static int deref_tags, show_head, tags_only, heads_only, found_match, verify,
+ quiet, hash_only, abbrev, exclude_arg;
static const char **pattern;
+static const char *exclude_existing_arg;
static void show_one(const char *refname, const unsigned char *sha1)
{
return 0;
}
+static int hash_callback(const struct option *opt, const char *arg, int unset)
+{
+ hash_only = 1;
+ /* Use full length SHA1 if no argument */
+ if (!arg)
+ return 0;
+ return parse_opt_abbrev_cb(opt, arg, unset);
+}
+
+static int exclude_existing_callback(const struct option *opt, const char *arg,
+ int unset)
+{
+ exclude_arg = 1;
+ *(const char **)opt->value = arg;
+ return 0;
+}
+
+static int help_callback(const struct option *opt, const char *arg, int unset)
+{
+ return -1;
+}
+
+static const struct option show_ref_options[] = {
+ OPT_BOOLEAN(0, "tags", &tags_only, "only show tags (can be combined with heads)"),
+ OPT_BOOLEAN(0, "heads", &heads_only, "only show heads (can be combined with tags)"),
+ OPT_BOOLEAN(0, "verify", &verify, "stricter reference checking, "
+ "requires exact ref path"),
+ OPT_BOOLEAN('h', "head", &show_head, "show the HEAD reference"),
+ OPT_BOOLEAN('d', "dereference", &deref_tags,
+ "dereference tags into object IDs"),
+ { OPTION_CALLBACK, 's', "hash", &abbrev, "n",
+ "only show SHA1 hash using <n> digits",
+ PARSE_OPT_OPTARG, &hash_callback },
+ OPT__ABBREV(&abbrev),
+ OPT__QUIET(&quiet),
+ { OPTION_CALLBACK, 0, "exclude-existing", &exclude_existing_arg,
+ "pattern", "show refs from stdin that aren't in local repository",
+ PARSE_OPT_OPTARG | PARSE_OPT_NONEG, exclude_existing_callback },
+ { OPTION_CALLBACK, 0, "help-all", NULL, NULL, "show usage",
+ PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, help_callback },
+ OPT_END()
+};
+
int cmd_show_ref(int argc, const char **argv, const char *prefix)
{
- int i;
+ argc = parse_options(argc, argv, prefix, show_ref_options,
+ show_ref_usage, PARSE_OPT_NO_INTERNAL_HELP);
- for (i = 1; i < argc; i++) {
- const char *arg = argv[i];
- if (*arg != '-') {
- pattern = argv + i;
- break;
- }
- if (!strcmp(arg, "--")) {
- pattern = argv + i + 1;
- if (!*pattern)
- pattern = NULL;
- break;
- }
- if (!strcmp(arg, "-q") || !strcmp(arg, "--quiet")) {
- quiet = 1;
- continue;
- }
- if (!strcmp(arg, "-h") || !strcmp(arg, "--head")) {
- show_head = 1;
- continue;
- }
- if (!strcmp(arg, "-d") || !strcmp(arg, "--dereference")) {
- deref_tags = 1;
- continue;
- }
- if (!strcmp(arg, "-s") || !strcmp(arg, "--hash")) {
- hash_only = 1;
- continue;
- }
- if (!prefixcmp(arg, "--hash=") ||
- (!prefixcmp(arg, "--abbrev") &&
- (arg[8] == '=' || arg[8] == '\0'))) {
- if (arg[2] != 'h' && !arg[8])
- /* --abbrev only */
- abbrev = DEFAULT_ABBREV;
- else {
- /* --hash= or --abbrev= */
- char *end;
- if (arg[2] == 'h') {
- hash_only = 1;
- arg += 7;
- }
- else
- arg += 9;
- abbrev = strtoul(arg, &end, 10);
- if (*end || abbrev > 40)
- usage(show_ref_usage);
- if (abbrev < MINIMUM_ABBREV)
- abbrev = MINIMUM_ABBREV;
- }
- continue;
- }
- if (!strcmp(arg, "--verify")) {
- verify = 1;
- continue;
- }
- if (!strcmp(arg, "--tags")) {
- tags_only = 1;
- continue;
- }
- if (!strcmp(arg, "--heads")) {
- heads_only = 1;
- continue;
- }
- if (!strcmp(arg, "--exclude-existing"))
- return exclude_existing(NULL);
- if (!prefixcmp(arg, "--exclude-existing="))
- return exclude_existing(arg + 19);
- usage(show_ref_usage);
- }
+ if (exclude_arg)
+ return exclude_existing(exclude_existing_arg);
+
+ pattern = argv;
+ if (!*pattern)
+ pattern = NULL;
if (verify) {
if (!pattern)
diff --git a/builtin-stripspace.c b/builtin-stripspace.c
index d6e3896c006796ccca12c00de45e36583387f05b..1fd2205d530ad510a18ff5a441ca7b5cb1cc34a6 100644 (file)
--- a/builtin-stripspace.c
+++ b/builtin-stripspace.c
strip_comments = 1;
if (strbuf_read(&buf, 0, 1024) < 0)
- die("could not read the input");
+ die_errno("could not read the input");
stripspace(&buf, strip_comments);
diff --git a/builtin-tag.c b/builtin-tag.c
index 080e04a8fc6fc1fc3f10f59a4c1f1aa067b81aa1..a51a6d1ea21412f151238e48984bc13110fcbc6c 100644 (file)
--- a/builtin-tag.c
+++ b/builtin-tag.c
path = git_pathdup("TAG_EDITMSG");
fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
if (fd < 0)
- die("could not create file '%s': %s",
- path, strerror(errno));
+ die_errno("could not create file '%s'", path);
if (!is_null_sha1(prev))
write_tag_body(fd, prev);
else {
if (!strcmp(msgfile, "-")) {
if (strbuf_read(&buf, 0, 1024) < 0)
- die("cannot read %s", msgfile);
+ die_errno("cannot read '%s'", msgfile);
} else {
if (strbuf_read_file(&buf, msgfile, 1024) < 0)
- die("could not open or read '%s': %s",
- msgfile, strerror(errno));
+ die_errno("could not open or read '%s'",
+ msgfile);
}
}
}
diff --git a/builtin-tar-tree.c b/builtin-tar-tree.c
index f88e7219367c309dbc3d3e7ce2db32666703a91d..8b3a35e12da2cca8b632d4139bc2c5ba2409d322 100644 (file)
--- a/builtin-tar-tree.c
+++ b/builtin-tar-tree.c
n = write_in_full(1, content + 11, 41);
if (n < 41)
- die("git get-tar-commit-id: write error");
+ die_errno("git get-tar-commit-id: write error");
return 0;
}
index 7e3ea73006ecdc74c03580ac7297be4ebee174b3..557148a693c058f51222cb3d996c309791d43d8b 100644 (file)
--- a/builtin-unpack-objects.c
+++ b/builtin-unpack-objects.c
if (ret <= 0) {
if (!ret)
die("early EOF");
- die("read error on input: %s", strerror(errno));
+ die_errno("read error on input");
}
len += ret;
} while (len < min);
diff --git a/combine-diff.c b/combine-diff.c
index 60d03676bbd0dba7be79c7098d7cae553962ca98..bbf74fc42e4e72eb3df99272fb75a03bbeaf726a 100644 (file)
--- a/combine-diff.c
+++ b/combine-diff.c
done = read_in_full(fd, result, len);
if (done < 0)
- die("read error '%s'", elem->path);
+ die_errno("read error '%s'", elem->path);
else if (done < len)
die("early EOF '%s'", elem->path);
diff --git a/commit.c b/commit.c
index aa3b35b6a86891ac9d0628e20a6a46d506bf7700..a47fb4da271beaf5595b6bbbe41f94bad08f404d 100644 (file)
--- a/commit.c
+++ b/commit.c
static unsigned long parse_commit_date(const char *buf, const char *tail)
{
- unsigned long date;
const char *dateptr;
if (buf + 6 >= tail)
if (buf >= tail)
return 0;
/* dateptr < buf && buf[-1] == '\n', so strtoul will stop at buf-1 */
- date = strtoul(dateptr, NULL, 10);
- if (date == ULONG_MAX)
- date = 0;
- return date;
+ return strtoul(dateptr, NULL, 10);
}
static struct commit_graft **commit_graft;
diff --git a/compat/mingw.h b/compat/mingw.h
index 4f7ba4c13f9d0086acf9d1cfadf6912b1d641033..c1859c5480f67dbe9640975d68407f2c1efd15f5 100644 (file)
--- a/compat/mingw.h
+++ b/compat/mingw.h
errno = EINVAL;
return -1;
}
+/* bash cannot reliably detect negative return codes as failure */
+#define exit(code) exit((code) & 0xff)
/*
* simple adaptors
index b60cb68a8bd19ddfdce06f136121189b2bad0185..9c488646d04f9fa08d9b2f2445b2a83d9bc4de40 100755 (executable)
$__git_log_shortlog_options
$__git_log_gitk_options
--root --topo-order --date-order --reverse
- --follow
+ --follow --full-diff
--abbrev-commit --abbrev=
--relative-date --date=
--pretty= --format= --oneline
c=$((--c))
done
- for i in $(git --git-dir="$(__gitdir)" config $config_file --list \
- 2>/dev/null); do
- case "$i" in
- *.*)
- echo "${i/=*/}"
+ git --git-dir="$(__gitdir)" config $config_file --list 2>/dev/null |
+ while read line
+ do
+ case "$line" in
+ *.*=*)
+ echo "${line/=*/}"
;;
esac
done
branch.*.*)
local pfx="${cur%.*}."
cur="${cur##*.}"
- __gitcomp "remote merge mergeoptions" "$pfx" "$cur"
+ __gitcomp "remote merge mergeoptions rebase" "$pfx" "$cur"
return
;;
branch.*)
cur="${cur##*.}"
__gitcomp "
url proxy fetch push mirror skipDefaultUpdate
- receivepack uploadpack tagopt
+ receivepack uploadpack tagopt pushurl
" "$pfx" "$cur"
return
;;
;;
esac
__gitcomp "
+ add.ignore-errors
alias.
apply.whitespace
branch.autosetupmerge
diff --git a/csum-file.c b/csum-file.c
index 2ddb12a0b70da87afe6fa8a33dce08c6c8ae7f71..4d50cc5ce18c24a1dc853d3050062b864fe0b943 100644 (file)
--- a/csum-file.c
+++ b/csum-file.c
}
if (!ret)
die("sha1 file '%s' write error. Out of diskspace", f->name);
- die("sha1 file '%s' write error (%s)", f->name, strerror(errno));
+ die_errno("sha1 file '%s' write error", f->name);
}
}
if (flags & CSUM_FSYNC)
fsync_or_die(f->fd, f->name);
if (close(f->fd))
- die("%s: sha1 file error on close (%s)",
- f->name, strerror(errno));
+ die_errno("%s: sha1 file error on close", f->name);
fd = 0;
} else
fd = f->fd;
diff --git a/daemon.c b/daemon.c
index 366db37b39f7dcfb29dbb4e79ad5bcc985b75bc6..1b5ada6648da66d14dec6c399898916920582852 100644 (file)
--- a/daemon.c
+++ b/daemon.c
#include "cache.h"
#include "pkt-line.h"
#include "exec_cmd.h"
+#include "run-command.h"
+#include "strbuf.h"
#include <syslog.h>
return service->fn();
}
+static void copy_to_log(int fd)
+{
+ struct strbuf line = STRBUF_INIT;
+ FILE *fp;
+
+ fp = fdopen(fd, "r");
+ if (fp == NULL) {
+ logerror("fdopen of error channel failed");
+ close(fd);
+ return;
+ }
+
+ while (strbuf_getline(&line, fp, '\n') != EOF) {
+ logerror("%s", line.buf);
+ strbuf_setlen(&line, 0);
+ }
+
+ strbuf_release(&line);
+ fclose(fp);
+}
+
+static int run_service_command(const char **argv)
+{
+ struct child_process cld;
+
+ memset(&cld, 0, sizeof(cld));
+ cld.argv = argv;
+ cld.git_cmd = 1;
+ cld.err = -1;
+ if (start_command(&cld))
+ return -1;
+
+ close(0);
+ close(1);
+
+ copy_to_log(cld.err);
+
+ return finish_command(&cld);
+}
+
static int upload_pack(void)
{
/* Timeout as string */
char timeout_buf[64];
+ const char *argv[] = { "upload-pack", "--strict", timeout_buf, ".", NULL };
snprintf(timeout_buf, sizeof timeout_buf, "--timeout=%u", timeout);
-
- /* git-upload-pack only ever reads stuff, so this is safe */
- execl_git_cmd("upload-pack", "--strict", timeout_buf, ".", NULL);
- return -1;
+ return run_service_command(argv);
}
static int upload_archive(void)
{
- execl_git_cmd("upload-archive", ".", NULL);
- return -1;
+ static const char *argv[] = { "upload-archive", ".", NULL };
+ return run_service_command(argv);
}
static int receive_pack(void)
{
- execl_git_cmd("receive-pack", ".", NULL);
- return -1;
+ static const char *argv[] = { "receive-pack", ".", NULL };
+ return run_service_command(argv);
}
static struct daemon_service daemon_service[] = {
case ECONNABORTED:
continue;
default:
- die("accept returned %s", strerror(errno));
+ die_errno("accept returned");
}
}
handle(incoming, (struct sockaddr *)&ss, sslen);
while (fd != -1 && fd < 2)
fd = dup(fd);
if (fd == -1)
- die("open /dev/null or dup failed: %s", strerror(errno));
+ die_errno("open /dev/null or dup failed");
if (fd > 2)
close(fd);
}
case 0:
break;
case -1:
- die("fork failed: %s", strerror(errno));
+ die_errno("fork failed");
default:
exit(0);
}
if (setsid() == -1)
- die("setsid failed: %s", strerror(errno));
+ die_errno("setsid failed");
close(0);
close(1);
close(2);
{
FILE *f = fopen(path, "w");
if (!f)
- die("cannot open pid file %s: %s", path, strerror(errno));
+ die_errno("cannot open pid file '%s'", path);
if (fprintf(f, "%"PRIuMAX"\n", (uintmax_t) getpid()) < 0 || fclose(f) != 0)
- die("failed to write pid file %s: %s", path, strerror(errno));
+ die_errno("failed to write pid file '%s'", path);
}
static int serve(char *listen_addr, int listen_port, struct passwd *pass, gid_t gid)
socklen_t slen = sizeof(ss);
if (!freopen("/dev/null", "w", stderr))
- die("failed to redirect stderr to /dev/null: %s",
- strerror(errno));
+ die_errno("failed to redirect stderr to /dev/null");
if (getpeername(0, peer, &slen))
peer = NULL;
index 43835d756c2c2c7ec579e1c38804fe33a706944f..cd35e0c2d7e29012e24cc8f5f49d9d351420b56e 100644 (file)
--- a/diff.c
+++ b/diff.c
free(mf1.ptr);
if (textconv_two)
free(mf2.ptr);
+ xdiff_clear_find_func(&xecfg);
}
free_ab_and_return:
fd = git_mkstemps(temp->tmp_path, PATH_MAX, template.buf,
strlen(base) + 1);
if (fd < 0)
- die("unable to create temp-file: %s", strerror(errno));
+ die_errno("unable to create temp-file");
if (convert_to_working_tree(path,
(const char *)blob, (size_t)size, &buf)) {
blob = buf.buf;
size = buf.len;
}
if (write_in_full(fd, blob, size) != size)
- die("unable to write temp-file");
+ die_errno("unable to write temp-file");
close(fd);
temp->name = temp->tmp_path;
strcpy(temp->hex, sha1_to_hex(sha1));
if (lstat(name, &st) < 0) {
if (errno == ENOENT)
goto not_a_valid_file;
- die("stat(%s): %s", name, strerror(errno));
+ die_errno("stat(%s)", name);
}
if (S_ISLNK(st.st_mode)) {
struct strbuf sb = STRBUF_INIT;
if (strbuf_readlink(&sb, name, st.st_size) < 0)
- die("readlink(%s)", name);
+ die_errno("readlink(%s)", name);
prep_temp_blob(name, temp, sb.buf, sb.len,
(one->sha1_valid ?
one->sha1 : null_sha1),
return;
}
if (lstat(one->path, &st) < 0)
- die("stat %s", one->path);
+ die_errno("stat '%s'", one->path);
if (index_path(one->sha1, one->path, &st, 0))
die("cannot hash %s", one->path);
}
index bbfcb566e63310d38848b0b76076fb051a7446c8..74b3bbf6fd557943e0e7b9027556312203e58d7a 100644 (file)
--- a/dir.c
+++ b/dir.c
if (!dir)
return NULL;
if (!getcwd(buffer, size))
- die("can't find the current directory: %s", strerror(errno));
+ die_errno("can't find the current directory");
if (!is_absolute_path(dir))
dir = make_absolute_path(dir);
index cc841edf9051460b3a382ea25c0097f245ec8884..d3e86c722a6663a65f69b73621f57aa6331a5e5b 100644 (file)
--- a/entry.c
+++ b/entry.c
if (errno == EEXIST && state->force &&
!unlink_or_warn(buf) && !mkdir(buf, 0777))
continue;
- die("cannot create directory at %s", buf);
+ die_errno("cannot create directory at '%s'", buf);
}
}
free(buf);
char *name;
if (!dir)
- die("cannot opendir %s (%s)", path, strerror(errno));
+ die_errno("cannot opendir '%s'", path);
strcpy(pathbuf, path);
name = pathbuf + strlen(path);
*name++ = '/';
continue;
strcpy(name, de->d_name);
if (lstat(pathbuf, &st))
- die("cannot lstat %s (%s)", pathbuf, strerror(errno));
+ die_errno("cannot lstat '%s'", pathbuf);
if (S_ISDIR(st.st_mode))
remove_subtree(pathbuf);
else if (unlink(pathbuf))
- die("cannot unlink %s (%s)", pathbuf, strerror(errno));
+ die_errno("cannot unlink '%s'", pathbuf);
}
closedir(dir);
if (rmdir(path))
- die("cannot rmdir %s (%s)", path, strerror(errno));
+ die_errno("cannot rmdir '%s'", path);
}
static int create_file(const char *path, unsigned int mode)
diff --git a/fast-import.c b/fast-import.c
index a2a24588a99957d5af759ca6d8858366430ab3a3..7ef9865aa6da794ab52cfc50f21f9f41f861fc4f 100644 (file)
--- a/fast-import.c
+++ b/fast-import.c
keep_fd = odb_pack_keep(name, sizeof(name), pack_data->sha1);
if (keep_fd < 0)
- die("cannot create keep file");
+ die_errno("cannot create keep file");
write_or_die(keep_fd, keep_msg, strlen(keep_msg));
if (close(keep_fd))
- die("failed to write keep file");
+ die_errno("failed to write keep file");
snprintf(name, sizeof(name), "%s/pack/pack-%s.pack",
get_object_directory(), sha1_to_hex(pack_data->sha1));
char line[512];
FILE *f = fopen(input_file, "r");
if (!f)
- die("cannot read %s: %s", input_file, strerror(errno));
+ die_errno("cannot read '%s'", input_file);
while (fgets(line, sizeof(line), f)) {
uintmax_t mark;
char *end;
fclose(pack_edges);
pack_edges = fopen(a + 20, "a");
if (!pack_edges)
- die("Cannot open %s: %s", a + 20, strerror(errno));
+ die_errno("Cannot open '%s'", a + 20);
} else if (!strcmp(a, "--force"))
force_update = 1;
else if (!strcmp(a, "--quiet"))
index 511b82cba9977c14d6dcba5efbd6d38591d3aacc..89278c1459d36a3e2b718661ca71483522f587fd 100644 (file)
--- a/fsck.c
+++ b/fsck.c
struct commit_graft *graft;
int parents = 0;
- if (!commit->date)
+ if (commit->date == ULONG_MAX)
return error_func(&commit->object, FSCK_ERROR, "invalid author/committer line");
if (memcmp(buffer, "tree ", 5))
diff --git a/git-am.sh b/git-am.sh
index 578780be138b216dc89333e1fde87ddcb91e5e54..d64d9975358a6b9a18596c45b13434463903a344 100755 (executable)
--- a/git-am.sh
+++ b/git-am.sh
i,interactive run interactively
b,binary* (historical option -- no-op)
3,3way allow fall back on 3way merging if needed
+q,quiet be quiet
s,signoff add a Signed-off-by line to the commit message
u,utf8 recode into utf8 (default)
k,keep pass -k flag to git-mailinfo
directory= pass it through git-apply
C= pass it through git-apply
p= pass it through git-apply
+patch-format= format the patch(es) are in
reject pass it through git-apply
resolvemsg= override error message when patch failure occurs
r,resolved to be used after a patch failure
git write-tree >"$dotest/patch-merge-base+" ||
cannot_fallback "Repository lacks necessary blobs to fall back on 3-way merge."
- echo Using index info to reconstruct a base tree...
+ say Using index info to reconstruct a base tree...
if GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \
git apply --cached <"$dotest/patch"
then
orig_tree=$(cat "$dotest/patch-merge-base") &&
rm -fr "$dotest"/patch-merge-* || exit 1
- echo Falling back to patching base and 3-way merge...
+ say Falling back to patching base and 3-way merge...
# This is not so wrong. Depending on which base we picked,
# orig_tree may be wildly different from ours, but his_tree
eval GITHEAD_$his_tree='"$FIRSTLINE"'
export GITHEAD_$his_tree
+ if test -n "$GIT_QUIET"
+ then
+ export GIT_MERGE_VERBOSITY=0
+ fi
git-merge-recursive $orig_tree -- HEAD $his_tree || {
git rerere
echo Failed to merge in the changes.
unset GITHEAD_$his_tree
}
+clean_abort () {
+ test $# = 0 || echo >&2 "$@"
+ rm -fr "$dotest"
+ exit 1
+}
+
+patch_format=
+
+check_patch_format () {
+ # early return if patch_format was set from the command line
+ if test -n "$patch_format"
+ then
+ return 0
+ fi
+
+ # we default to mbox format if input is from stdin and for
+ # directories
+ if test $# = 0 || test "x$1" = "x-" || test -d "$1"
+ then
+ patch_format=mbox
+ return 0
+ fi
+
+ # otherwise, check the first few lines of the first patch to try
+ # to detect its format
+ {
+ read l1
+ read l2
+ read l3
+ case "$l1" in
+ "From "* | "From: "*)
+ patch_format=mbox
+ ;;
+ '# This series applies on GIT commit'*)
+ patch_format=stgit-series
+ ;;
+ "# HG changeset patch")
+ patch_format=hg
+ ;;
+ *)
+ # if the second line is empty and the third is
+ # a From, Author or Date entry, this is very
+ # likely an StGIT patch
+ case "$l2,$l3" in
+ ,"From: "* | ,"Author: "* | ,"Date: "*)
+ patch_format=stgit
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ esac
+ } < "$1" || clean_abort
+}
+
+split_patches () {
+ case "$patch_format" in
+ mbox)
+ git mailsplit -d"$prec" -o"$dotest" -b -- "$@" > "$dotest/last" ||
+ clean_abort
+ ;;
+ stgit-series)
+ if test $# -ne 1
+ then
+ clean_abort "Only one StGIT patch series can be applied at once"
+ fi
+ series_dir=`dirname "$1"`
+ series_file="$1"
+ shift
+ {
+ set x
+ while read filename
+ do
+ set "$@" "$series_dir/$filename"
+ done
+ # remove the safety x
+ shift
+ # remove the arg coming from the first-line comment
+ shift
+ } < "$series_file" || clean_abort
+ # set the patch format appropriately
+ patch_format=stgit
+ # now handle the actual StGIT patches
+ split_patches "$@"
+ ;;
+ stgit)
+ this=0
+ for stgit in "$@"
+ do
+ this=`expr "$this" + 1`
+ msgnum=`printf "%0${prec}d" $this`
+ # Perl version of StGIT parse_patch. The first nonemptyline
+ # not starting with Author, From or Date is the
+ # subject, and the body starts with the next nonempty
+ # line not starting with Author, From or Date
+ perl -ne 'BEGIN { $subject = 0 }
+ if ($subject > 1) { print ; }
+ elsif (/^\s+$/) { next ; }
+ elsif (/^Author:/) { print s/Author/From/ ; }
+ elsif (/^(From|Date)/) { print ; }
+ elsif ($subject) {
+ $subject = 2 ;
+ print "\n" ;
+ print ;
+ } else {
+ print "Subject: ", $_ ;
+ $subject = 1;
+ }
+ ' < "$stgit" > "$dotest/$msgnum" || clean_abort
+ done
+ echo "$this" > "$dotest/last"
+ this=
+ msgnum=
+ ;;
+ *)
+ clean_abort "Patch format $patch_format is not supported."
+ ;;
+ esac
+}
+
prec=4
dotest="$GIT_DIR/rebase-apply"
sign= utf8=t keep= skip= interactive= resolved= rebasing= abort=
git_apply_opt="$git_apply_opt $(sq "$1=$2")"; shift ;;
-C|-p)
git_apply_opt="$git_apply_opt $(sq "$1$2")"; shift ;;
+ --patch-format)
+ shift ; patch_format="$1" ;;
--reject)
git_apply_opt="$git_apply_opt $1" ;;
--committer-date-is-author-date)
committer_date_is_author_date=t ;;
--ignore-date)
ignore_date=t ;;
+ -q|--quiet)
+ GIT_QUIET=t ;;
--)
shift; break ;;
*)
done
shift
fi
- git mailsplit -d"$prec" -o"$dotest" -b -- "$@" > "$dotest/last" || {
- rm -fr "$dotest"
- exit 1
- }
- # -s, -u, -k, --whitespace, -3, -C and -p flags are kept
+ check_patch_format "$@"
+
+ split_patches "$@"
+
+ # -s, -u, -k, --whitespace, -3, -C, -q and -p flags are kept
# for the resuming session after a patch failure.
# -i can and must be given when resuming.
echo " $git_apply_opt" >"$dotest/apply-opt"
echo "$sign" >"$dotest/sign"
echo "$utf8" >"$dotest/utf8"
echo "$keep" >"$dotest/keep"
+ echo "$GIT_QUIET" >"$dotest/quiet"
echo 1 >"$dotest/next"
if test -n "$rebasing"
then
then
keep=-k
fi
+if test "$(cat "$dotest/quiet")" = t
+then
+ GIT_QUIET=t
+fi
if test "$(cat "$dotest/threeway")" = t
then
threeway=t
if test "$this" -gt "$last"
then
- echo Nothing to do.
+ say Nothing to do.
rm -fr "$dotest"
exit
fi
stop_here $this
fi
- printf 'Applying: %s\n' "$FIRSTLINE"
+ say "Applying: $FIRSTLINE"
case "$resolved" in
'')
- eval 'git apply '"$git_apply_opt"' --index "$dotest/patch"'
+ # When we are allowed to fall back to 3-way later, don't give
+ # false errors during the initial attempt.
+ squelch=
+ if test "$threeway" = t
+ then
+ squelch='>/dev/null 2>&1 '
+ fi
+ eval "git apply $squelch$git_apply_opt"' --index "$dotest/patch"'
apply_status=$?
;;
t)
# Applying the patch to an earlier tree and merging the
# result may have produced the same tree as ours.
git diff-index --quiet --cached HEAD -- && {
- echo No changes -- Patch already applied.
+ say No changes -- Patch already applied.
go_next
continue
}
GIT_AUTHOR_DATE=
fi
parent=$(git rev-parse --verify -q HEAD) ||
- echo >&2 "applying to an empty history"
+ say >&2 "applying to an empty history"
if test -n "$committer_date_is_author_date"
then
diff --git a/git-compat-util.h b/git-compat-util.h
index 919b7f1ade9cab3c4ba907f9506e3cb518fb9e7f..9609eaa77f1dad589700bda222e0a81ad4f4d1ee 100644 (file)
--- a/git-compat-util.h
+++ b/git-compat-util.h
/* General helper functions */
extern void usage(const char *err) NORETURN;
extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
+extern void die_errno(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
extern int error(const char *err, ...) __attribute__((format (printf, 1, 2)));
extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2)));
index a36df3392652b8a854ca48bdf71977dcf12b244b..59b672213bfc36f95db089f0e13bafc1c2f2ed71 100755 (executable)
--- a/git-cvsexportcommit.perl
+++ b/git-cvsexportcommit.perl
if $file =~ /^no file /
&& $status eq 'Up-to-date';
- $cvsstat{$fullname{$file}} = $status;
+ $cvsstat{$fullname{$file}} = $status
+ if defined $fullname{$file};
}
}
}
while (<FILTER_IN>)
{
my $line = $_;
- $line =~ s/\$([A-Z][a-z]+):[^\$]+\$/\$\1\$/g;
+ $line =~ s/\$([A-Z][a-z]+):[^\$]+\$/\$$1\$/g;
print FILTER_OUT $line;
}
close FILTER_IN;
diff --git a/git-rebase.sh b/git-rebase.sh
index 334629fc97c0d06e9c9cfda058bdd999810f9d55..18bc6946cfa592c11cf7499b1c1ff9a6cb378b26 100755 (executable)
--- a/git-rebase.sh
+++ b/git-rebase.sh
# Copyright (c) 2005 Junio C Hamano.
#
-USAGE='[--interactive | -i] [-v] [--force-rebase | -f] [--onto <newbase>] [<upstream>|--root] [<branch>]'
+USAGE='[--interactive | -i] [-v] [--force-rebase | -f] [--onto <newbase>] [<upstream>|--root] [<branch>] [--quiet | -q]'
LONG_USAGE='git-rebase replaces <branch> with a new branch of the
same name. When the --onto option is provided the new branch starts
out with a HEAD equal to <newbase>, otherwise it is equal to <upstream>
echo "directly, but instead do one of the following: "
die "$RESOLVEMSG"
fi
- printf "Committed: %0${prec}d " $msgnum
+ if test -z "$GIT_QUIET"
+ then
+ printf "Committed: %0${prec}d " $msgnum
+ fi
else
- printf "Already applied: %0${prec}d " $msgnum
+ if test -z "$GIT_QUIET"
+ then
+ printf "Already applied: %0${prec}d " $msgnum
+ fi
+ fi
+ if test -z "$GIT_QUIET"
+ then
+ git rev-list --pretty=oneline -1 "$cmt" | sed -e 's/^[^ ]* //'
fi
- git rev-list --pretty=oneline -1 "$cmt" | sed -e 's/^[^ ]* //'
prev_head=`git rev-parse HEAD^0`
# save the resulting commit so we can read-tree on it later
eval GITHEAD_$cmt='"${cmt_name##refs/heads/}~$(($end - $msgnum))"'
eval GITHEAD_$hd='$(cat "$dotest/onto_name")'
export GITHEAD_$cmt GITHEAD_$hd
+ if test -n "$GIT_QUIET"
+ then
+ export GIT_MERGE_VERBOSITY=1
+ fi
git-merge-$strategy "$cmt^" -- "$hd" "$cmt"
rv=$?
case "$rv" in
finish_rb_merge () {
move_to_original_branch
rm -r "$dotest"
- echo "All done."
+ say All done.
}
is_interactive () {
end=$(cat "$dotest/end")
msgnum=$(cat "$dotest/msgnum")
onto=$(cat "$dotest/onto")
+ GIT_QUIET=$(cat "$dotest/quiet")
continue_merge
while test "$msgnum" -le "$end"
do
head_name=$(cat "$GIT_DIR"/rebase-apply/head-name) &&
onto=$(cat "$GIT_DIR"/rebase-apply/onto) &&
orig_head=$(cat "$GIT_DIR"/rebase-apply/orig-head) &&
+ GIT_QUIET=$(cat "$GIT_DIR"/rebase-apply/quiet)
git am --resolved --3way --resolvemsg="$RESOLVEMSG" &&
move_to_original_branch
exit
msgnum=$(cat "$dotest/msgnum")
msgnum=$(($msgnum + 1))
onto=$(cat "$dotest/onto")
+ GIT_QUIET=$(cat "$dotest/quiet")
while test "$msgnum" -le "$end"
do
call_merge "$msgnum"
head_name=$(cat "$GIT_DIR"/rebase-apply/head-name) &&
onto=$(cat "$GIT_DIR"/rebase-apply/onto) &&
orig_head=$(cat "$GIT_DIR"/rebase-apply/orig-head) &&
+ GIT_QUIET=$(cat "$GIT_DIR"/rebase-apply/quiet)
git am -3 --skip --resolvemsg="$RESOLVEMSG" &&
move_to_original_branch
exit
git rerere clear
if test -d "$dotest"
then
+ GIT_QUIET=$(cat "$dotest/quiet")
move_to_original_branch
else
dotest="$GIT_DIR"/rebase-apply
+ GIT_QUIET=$(cat "$dotest/quiet")
move_to_original_branch
fi
git reset --hard $(cat "$dotest/orig-head")
-v|--verbose)
verbose=t
diffstat=t
+ GIT_QUIET=
+ ;;
+ -q|--quiet)
+ GIT_QUIET=t
+ git_am_opt="$git_am_opt -q"
+ verbose=
+ diffstat=
;;
--whitespace=*)
git_am_opt="$git_am_opt $1"
then
# Lazily switch to the target branch if needed...
test -z "$switch_to" || git checkout "$switch_to"
- echo >&2 "Current branch $branch_name is up to date."
+ say "Current branch $branch_name is up to date."
exit 0
else
- echo "Current branch $branch_name is up to date, rebase forced."
+ say "Current branch $branch_name is up to date, rebase forced."
fi
fi
# Detach HEAD and reset the tree
-echo "First, rewinding head to replay your work on top of it..."
+say "First, rewinding head to replay your work on top of it..."
git checkout -q "$onto^0" || die "could not detach HEAD"
git update-ref ORIG_HEAD $branch
# we just fast forwarded.
if test "$mb" = "$branch"
then
- echo >&2 "Fast-forwarded $branch_name to $onto_name."
+ say "Fast-forwarded $branch_name to $onto_name."
move_to_original_branch
exit 0
fi
test 0 != $ret -a -d "$GIT_DIR"/rebase-apply &&
echo $head_name > "$GIT_DIR"/rebase-apply/head-name &&
echo $onto > "$GIT_DIR"/rebase-apply/onto &&
- echo $orig_head > "$GIT_DIR"/rebase-apply/orig-head
+ echo $orig_head > "$GIT_DIR"/rebase-apply/orig-head &&
+ echo "$GIT_QUIET" > "$GIT_DIR"/rebase-apply/quiet
exit $ret
fi
echo "$prev_head" > "$dotest/prev_head"
echo "$orig_head" > "$dotest/orig-head"
echo "$head_name" > "$dotest/head-name"
+echo "$GIT_QUIET" > "$dotest/quiet"
msgnum=0
for cmt in `git rev-list --reverse --no-merges "$revisions"`
diff --git a/git-repack.sh b/git-repack.sh
index 0868734723b3c96144bfa9360a9e19ebae1995f7..1bf239499c7bdb04622ea6fa239bd7c0ace42065 100755 (executable)
--- a/git-repack.sh
+++ b/git-repack.sh
. git-sh-setup
no_update_info= all_into_one= remove_redundant= unpack_unreachable=
-local= quiet= no_reuse= extra=
+local= no_reuse= extra=
while test $# != 0
do
case "$1" in
-A) all_into_one=t
unpack_unreachable=--unpack-unreachable ;;
-d) remove_redundant=t ;;
- -q) quiet=-q ;;
+ -q) GIT_QUIET=t ;;
-f) no_reuse=--no-reuse-object ;;
-l) local=--local ;;
--max-pack-size|--window|--window-memory|--depth)
;;
esac
-args="$args $local $quiet $no_reuse$extra"
+args="$args $local ${GIT_QUIET:+-q} $no_reuse$extra"
names=$(git pack-objects --honor-pack-keep --non-empty --all --reflog $args </dev/null "$PACKTMP") ||
exit 1
if [ -z "$names" ]; then
- if test -z "$quiet"; then
- echo Nothing new to pack.
- fi
+ say Nothing new to pack.
fi
# Ok we have prepared all new packfiles.
done
)
fi
- git prune-packed $quiet
+ git prune-packed ${GIT_QUIET:+-q}
fi
case "$no_update_info" in
diff --git a/git-request-pull.sh b/git-request-pull.sh
index a2cf5b82150a77fd9ddb775fea1bc8d5e8ee7392..5917773240dfb2e8b5f078afee22a3d9bf607ce3 100755 (executable)
--- a/git-request-pull.sh
+++ b/git-request-pull.sh
. git-sh-setup
. git-parse-remote
+GIT_PAGER=
+export GIT_PAGER
+
base=$1
url=$2
head=${3-HEAD}
}")
if [ -z "$branch" ]; then
echo "warn: No branch of $url is at:" >&2
- git log --max-count=1 --pretty='format:warn: %h: %s' $headrev >&2
+ git log --max-count=1 --pretty='tformat:warn: %h: %s' $headrev >&2
echo "warn: Are you sure you pushed $head there?" >&2
echo >&2
echo >&2
status=1
fi
-PAGER=
-export PAGER
echo "The following changes since commit $baserev:"
git shortlog --max-count=1 $baserev | sed -e 's/^\(.\)/ \1/'
diff --git a/git-sh-setup.sh b/git-sh-setup.sh
index 80acb7de729f2f824043b592ce110479d4334a06..c41c2f7439724adc3dd13b92c86b25d254fc23b8 100755 (executable)
--- a/git-sh-setup.sh
+++ b/git-sh-setup.sh
exit 1
}
+GIT_QUIET=
+
+say () {
+ if test -z "$GIT_QUIET"
+ then
+ printf '%s\n' "$*"
+ fi
+}
+
if test -n "$OPTIONS_SPEC"; then
usage() {
"$0" -h
diff --git a/git-stash.sh b/git-stash.sh
index e6a586720978ec516d243590b0e403ed7ecfe36c..531c7c31aca87db77e54c46ffb89899652a79fcd 100755 (executable)
--- a/git-stash.sh
+++ b/git-stash.sh
dashless=$(basename "$0" | sed -e 's/-/ /')
USAGE="list [<options>]
- or: $dashless ( show | drop ) [<stash>]
- or: $dashless ( pop | apply ) [--index] [<stash>]
+ or: $dashless show [<stash>]
+ or: $dashless drop [-q|--quiet] [<stash>]
+ or: $dashless ( pop | apply ) [--index] [-q|--quiet] [<stash>]
or: $dashless branch <branchname> [<stash>]
- or: $dashless [save [--keep-index] [<message>]]
+ or: $dashless [save [--keep-index] [-q|--quiet] [<message>]]
or: $dashless clear"
SUBDIRECTORY_OK=Yes
save_stash () {
keep_index=
- case "$1" in
- --keep-index)
- keep_index=t
+ while test $# != 0
+ do
+ case "$1" in
+ --keep-index)
+ keep_index=t
+ ;;
+ -q|--quiet)
+ GIT_QUIET=t
+ ;;
+ *)
+ break
+ ;;
+ esac
shift
- esac
+ done
stash_msg="$*"
git update-index -q --refresh
if no_changes
then
- echo 'No local changes to save'
+ say 'No local changes to save'
exit 0
fi
test -f "$GIT_DIR/logs/$ref_stash" ||
git update-ref -m "$stash_msg" $ref_stash $w_commit ||
die "Cannot save the current status"
- printf 'Saved working directory and index state "%s"\n' "$stash_msg"
+ say Saved working directory and index state "$stash_msg"
- git reset --hard
+ git reset --hard ${GIT_QUIET:+-q}
if test -n "$keep_index" && test -n $i_tree
then
die 'Cannot apply to a dirty working tree, please stage your changes'
unstash_index=
- case "$1" in
- --index)
- unstash_index=t
+
+ while test $# != 0
+ do
+ case "$1" in
+ --index)
+ unstash_index=t
+ ;;
+ -q|--quiet)
+ GIT_QUIET=t
+ ;;
+ *)
+ break
+ ;;
+ esac
shift
- esac
+ done
# current index state
c_tree=$(git write-tree) ||
export GITHEAD_$w_tree GITHEAD_$c_tree GITHEAD_$b_tree
"
+ if test -n "$GIT_QUIET"
+ then
+ export GIT_MERGE_VERBOSITY=0
+ fi
if git-merge-recursive $b_tree -- $c_tree $w_tree
then
# No conflict
die "Cannot unstage modified files"
rm -f "$a"
fi
- git status || :
+ squelch=
+ if test -n "$GIT_QUIET"
+ then
+ squelch='>/dev/null 2>&1'
+ fi
+ eval "git status $squelch" || :
else
# Merge conflict; keep the exit status from merge-recursive
status=$?
drop_stash () {
have_stash || die 'No stash entries to drop'
+ while test $# != 0
+ do
+ case "$1" in
+ -q|--quiet)
+ GIT_QUIET=t
+ ;;
+ *)
+ break
+ ;;
+ esac
+ shift
+ done
+
if test $# = 0
then
set x "$ref_stash@{0}"
die "$*: not a valid stashed state"
git reflog delete --updateref --rewrite "$@" &&
- echo "Dropped $* ($s)" || die "$*: Could not drop stash entry"
+ say "Dropped $* ($s)" || die "$*: Could not drop stash entry"
# clear_stash if we just dropped the last stash entry
git rev-parse --verify "$ref_stash@{0}" > /dev/null 2>&1 || clear_stash
if test $# -eq 0
then
save_stash &&
- echo '(To restore them type "git stash apply")'
+ say '(To restore them type "git stash apply")'
else
usage
fi
diff --git a/git-submodule.sh b/git-submodule.sh
index f4f35626713bd8ec238262731b0fd2ab59d6f07f..ebed711da41a7ac3c4caa7ae9b7f73e0c75f4fe7 100755 (executable)
--- a/git-submodule.sh
+++ b/git-submodule.sh
command=
branch=
-quiet=
reference=
cached=
nofetch=
update=
-#
-# print stuff on stdout unless -q was specified
-#
-say()
-{
- if test -z "$quiet"
- then
- echo "$@"
- fi
-}
-
# Resolve relative url by appending to parent's url
resolve_relative_url ()
{
shift
;;
-q|--quiet)
- quiet=1
+ GIT_QUIET=1
;;
--reference)
case "$2" in '') usage ;; esac
do
case "$1" in
-q|--quiet)
- quiet=1
+ GIT_QUIET=1
;;
--)
shift
case "$1" in
-q|--quiet)
shift
- quiet=1
+ GIT_QUIET=1
;;
-i|--init)
init=1
do
case "$1" in
-q|--quiet)
- quiet=1
+ GIT_QUIET=1
;;
--cached)
cached=1
do
case "$1" in
-q|--quiet)
- quiet=1
+ GIT_QUIET=1
shift
;;
--)
command=$1
;;
-q|--quiet)
- quiet=1
+ GIT_QUIET=1
;;
-b|--branch)
case "$2" in
index 7d7f949f0da85ea124f67ead6f68fdd0ddc75d20..807d875ae06ce7bbf61bb846c5b4cb5a51855eba 100644 (file)
--- a/git.c
+++ b/git.c
alias_command);
new_argv = xrealloc(new_argv, sizeof(char *) *
- (count + *argcp + 1));
+ (count + *argcp));
/* insert after command name */
memcpy(new_argv + count, *argv + 1, sizeof(char *) * *argcp);
- new_argv[count+*argcp] = NULL;
*argv = new_argv;
*argcp += count - 1;
}
if (subdir && chdir(subdir))
- die("Cannot change to %s: %s", subdir, strerror(errno));
+ die_errno("Cannot change to '%s'", subdir);
errno = saved_errno;
status = p->fn(argc, argv, prefix);
if (status)
- return status & 0xff;
+ return status;
/* Somebody closed stdout? */
if (fstat(fileno(stdout), &st))
/* Check for ENOSPC and EIO errors.. */
if (fflush(stdout))
- die("write failure on standard output: %s", strerror(errno));
+ die_errno("write failure on standard output");
if (ferror(stdout))
die("unknown write failure on standard output");
if (fclose(stdout))
- die("close failed on standard output: %s", strerror(errno));
+ die_errno("close failed on standard output");
return 0;
}
diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css
index a01eac814e51edd2115474f4d48a8d7fafa8c0e6..d05bc376463c3412f50f299949fb836aee5c12da 100644 (file)
--- a/gitweb/gitweb.css
+++ b/gitweb/gitweb.css
border-width: 0px;
}
+img.avatar {
+ vertical-align: middle;
+}
+
div.page_header {
height: 25px;
padding: 8px;
font-style: italic;
}
+.author_date, .author {
+ font-style: italic;
+}
+
div.author_date {
padding: 8px;
border: solid #d9d8d1;
border-width: 0px 0px 1px 0px;
- font-style: italic;
}
a.list {
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 1e7e2d8387efb810afb3b9c9d279cc59f52d932e..6a1b5b5b49611e158e5cd74b50685c9022b17adc 100755 (executable)
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
'x-zip' => undef, '' => undef,
);
+# Pixel sizes for icons and avatars. If the default font sizes or lineheights
+# are changed, it may be appropriate to change these values too via
+# $GITWEB_CONFIG.
+our %avatar_size = (
+ 'default' => 16,
+ 'double' => 32
+);
+
# You define site-wide feature defaults here; override them with
# $GITWEB_CONFIG as necessary.
our %feature = (
'sub' => \&feature_patches,
'override' => 0,
'default' => [16]},
+
+ # Avatar support. When this feature is enabled, views such as
+ # shortlog or commit will display an avatar associated with
+ # the email of the committer(s) and/or author(s).
+
+ # Currently available providers are gravatar and picon.
+ # If an unknown provider is specified, the feature is disabled.
+
+ # Gravatar depends on Digest::MD5.
+ # Picon currently relies on the indiana.edu database.
+
+ # To enable system wide have in $GITWEB_CONFIG
+ # $feature{'avatar'}{'default'} = ['<provider>'];
+ # where <provider> is either gravatar or picon.
+ # To have project specific config enable override in $GITWEB_CONFIG
+ # $feature{'avatar'}{'override'} = 1;
+ # and in project config gitweb.avatar = <provider>;
+ 'avatar' => {
+ 'sub' => \&feature_avatar,
+ 'override' => 0,
+ 'default' => ['']},
);
sub gitweb_get_feature {
return ($_[0]);
}
+sub feature_avatar {
+ my @val = (git_get_project_config('avatar'));
+
+ return @val ? @val : @_;
+}
+
# checking HEAD file with -e is fragile if the repository was
# initialized long time ago (i.e. symlink HEAD) and was pack-ref'ed
# and then pruned.
our @snapshot_fmts = gitweb_get_feature('snapshot');
@snapshot_fmts = filter_snapshot_fmts(@snapshot_fmts);
+# check that the avatar feature is set to a known provider name,
+# and for each provider check if the dependencies are satisfied.
+# if the provider name is invalid or the dependencies are not met,
+# reset $git_avatar to the empty string.
+our ($git_avatar) = gitweb_get_feature('avatar');
+if ($git_avatar eq 'gravatar') {
+ $git_avatar = '' unless (eval { require Digest::MD5; 1; });
+} elsif ($git_avatar eq 'picon') {
+ # no dependencies
+} else {
+ $git_avatar = '';
+}
+
# dispatch
if (!defined $action) {
if (defined $hash) {
}
}
+# Rather than recomputing the url for an email multiple times, we cache it
+# after the first hit. This gives a visible benefit in views where the avatar
+# for the same email is used repeatedly (e.g. shortlog).
+# The cache is shared by all avatar engines (currently gravatar only), which
+# are free to use it as preferred. Since only one avatar engine is used for any
+# given page, there's no risk for cache conflicts.
+our %avatar_cache = ();
+
+# Compute the picon url for a given email, by using the picon search service over at
+# http://www.cs.indiana.edu/picons/search.html
+sub picon_url {
+ my $email = lc shift;
+ if (!$avatar_cache{$email}) {
+ my ($user, $domain) = split('@', $email);
+ $avatar_cache{$email} =
+ "http://www.cs.indiana.edu/cgi-pub/kinzler/piconsearch.cgi/" .
+ "$domain/$user/" .
+ "users+domains+unknown/up/single";
+ }
+ return $avatar_cache{$email};
+}
+
+# Compute the gravatar url for a given email, if it's not in the cache already.
+# Gravatar stores only the part of the URL before the size, since that's the
+# one computationally more expensive. This also allows reuse of the cache for
+# different sizes (for this particular engine).
+sub gravatar_url {
+ my $email = lc shift;
+ my $size = shift;
+ $avatar_cache{$email} ||=
+ "http://www.gravatar.com/avatar/" .
+ Digest::MD5::md5_hex($email) . "?s=";
+ return $avatar_cache{$email} . $size;
+}
+
+# Insert an avatar for the given $email at the given $size if the feature
+# is enabled.
+sub git_get_avatar {
+ my ($email, %opts) = @_;
+ my $pre_white = ($opts{-pad_before} ? " " : "");
+ my $post_white = ($opts{-pad_after} ? " " : "");
+ $opts{-size} ||= 'default';
+ my $size = $avatar_size{$opts{-size}} || $avatar_size{'default'};
+ my $url = "";
+ if ($git_avatar eq 'gravatar') {
+ $url = gravatar_url($email, $size);
+ } elsif ($git_avatar eq 'picon') {
+ $url = picon_url($email);
+ }
+ # Other providers can be added by extending the if chain, defining $url
+ # as needed. If no variant puts something in $url, we assume avatars
+ # are completely disabled/unavailable.
+ if ($url) {
+ return $pre_white .
+ "<img width=\"$size\" " .
+ "class=\"avatar\" " .
+ "src=\"$url\" " .
+ "alt=\"\" " .
+ "/>" . $post_white;
+ } else {
+ return "";
+ }
+}
+
+# format the author name of the given commit with the given tag
+# the author name is chopped and escaped according to the other
+# optional parameters (see chop_str).
+sub format_author_html {
+ my $tag = shift;
+ my $co = shift;
+ my $author = chop_and_escape_str($co->{'author_name'}, @_);
+ return "<$tag class=\"author\">" .
+ git_get_avatar($co->{'author_email'}, -pad_after => 1) .
+ $author . "</$tag>";
+}
+
# format git diff header line, i.e. "diff --(git|combined|cc) ..."
sub format_git_diff_header_line {
my $line = shift;
$tag{'name'} = $1;
} elsif ($line =~ m/^tagger (.*) ([0-9]+) (.*)$/) {
$tag{'author'} = $1;
- $tag{'epoch'} = $2;
- $tag{'tz'} = $3;
+ $tag{'author_epoch'} = $2;
+ $tag{'author_tz'} = $3;
+ if ($tag{'author'} =~ m/^([^<]+) <([^>]*)>/) {
+ $tag{'author_name'} = $1;
+ $tag{'author_email'} = $2;
+ } else {
+ $tag{'author_name'} = $tag{'author'};
+ }
} elsif ($line =~ m/--BEGIN/) {
push @comment, $line;
last;
"\n</div>\n";
}
+sub print_local_time {
+ my %date = @_;
+ if ($date{'hour_local'} < 6) {
+ printf(" (<span class=\"atnight\">%02d:%02d</span> %s)",
+ $date{'hour_local'}, $date{'minute_local'}, $date{'tz_local'});
+ } else {
+ printf(" (%02d:%02d %s)",
+ $date{'hour_local'}, $date{'minute_local'}, $date{'tz_local'});
+ }
+}
+
+# Outputs the author name and date in long form
sub git_print_authorship {
my $co = shift;
+ my %opts = @_;
+ my $tag = $opts{-tag} || 'div';
my %ad = parse_date($co->{'author_epoch'}, $co->{'author_tz'});
- print "<div class=\"author_date\">" .
+ print "<$tag class=\"author_date\">" .
esc_html($co->{'author_name'}) .
" [$ad{'rfc2822'}";
- if ($ad{'hour_local'} < 6) {
- printf(" (<span class=\"atnight\">%02d:%02d</span> %s)",
- $ad{'hour_local'}, $ad{'minute_local'}, $ad{'tz_local'});
- } else {
- printf(" (%02d:%02d %s)",
- $ad{'hour_local'}, $ad{'minute_local'}, $ad{'tz_local'});
+ print_local_time(%ad) if ($opts{-localtime});
+ print "]" . git_get_avatar($co->{'author_email'}, -pad_before => 1)
+ . "</$tag>\n";
+}
+
+# Outputs table rows containing the full author or committer information,
+# in the format expected for 'commit' view (& similia).
+# Parameters are a commit hash reference, followed by the list of people
+# to output information for. If the list is empty it defalts to both
+# author and committer.
+sub git_print_authorship_rows {
+ my $co = shift;
+ # too bad we can't use @people = @_ || ('author', 'committer')
+ my @people = @_;
+ @people = ('author', 'committer') unless @people;
+ foreach my $who (@people) {
+ my %wd = parse_date($co->{"${who}_epoch"}, $co->{"${who}_tz"});
+ print "<tr><td>$who</td><td>" . esc_html($co->{$who}) . "</td>" .
+ "<td rowspan=\"2\">" .
+ git_get_avatar($co->{"${who}_email"}, -size => 'double') .
+ "</td></tr>\n" .
+ "<tr>" .
+ "<td></td><td> $wd{'rfc2822'}";
+ print_local_time(%wd);
+ print "</td>" .
+ "</tr>\n";
}
- print "]</div>\n";
}
sub git_print_page_path {
print "<tr class=\"light\">\n";
}
$alternate ^= 1;
- my $author = chop_and_escape_str($co{'author_name'}, 10);
# git_summary() used print "<td><i>$co{'age_string'}</i></td>\n" .
print "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
- "<td><i>" . $author . "</i></td>\n" .
- "<td>";
+ format_author_html('td', \%co, 10) . "<td>";
print format_subject_html($co{'title'}, $co{'title_short'},
href(action=>"commit", hash=>$commit), $ref);
print "</td>\n" .
print "<tr class=\"light\">\n";
}
$alternate ^= 1;
- # shortlog uses chop_str($co{'author_name'}, 10)
- my $author = chop_and_escape_str($co{'author_name'}, 15, 3);
print "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
- "<td><i>" . $author . "</i></td>\n" .
- "<td>";
+ # shortlog: format_author_html('td', \%co, 10)
+ format_author_html('td', \%co, 15, 3) . "<td>";
# originally git_history used chop_str($co{'title'}, 50)
print format_subject_html($co{'title'}, $co{'title_short'},
href(action=>"commit", hash=>$commit), $ref);
print "<tr class=\"light\">\n";
}
$alternate ^= 1;
- my $author = chop_and_escape_str($co{'author_name'}, 15, 5);
print "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
- "<td><i>" . $author . "</i></td>\n" .
+ format_author_html('td', \%co, 15, 5) .
"<td>" .
$cgi->a({-href => href(action=>"commit", hash=>$co{'id'}),
-class => "list subject"},
$tag{'type'}) . "</td>\n" .
"</tr>\n";
if (defined($tag{'author'})) {
- my %ad = parse_date($tag{'epoch'}, $tag{'tz'});
- print "<tr><td>author</td><td>" . esc_html($tag{'author'}) . "</td></tr>\n";
- print "<tr><td></td><td>" . $ad{'rfc2822'} .
- sprintf(" (%02d:%02d %s)", $ad{'hour_local'}, $ad{'minute_local'}, $ad{'tz_local'}) .
- "</td></tr>\n";
+ git_print_authorship_rows(\%tag, 'author');
}
print "</table>\n\n" .
"</div>\n";
" | " .
$cgi->a({-href => href(action=>"tree", hash=>$commit, hash_base=>$commit)}, "tree") .
"<br/>\n" .
- "</div>\n" .
- "<i>" . esc_html($co{'author_name'}) . " [$ad{'rfc2822'}]</i><br/>\n" .
"</div>\n";
+ git_print_authorship(\%co, -tag => 'span');
+ print "<br/>\n</div>\n";
print "<div class=\"log_body\">\n";
git_print_log($co{'comment'}, -final_empty_line=> 1);
$hash ||= $hash_base || "HEAD";
my %co = parse_commit($hash)
or die_error(404, "Unknown commit object");
- my %ad = parse_date($co{'author_epoch'}, $co{'author_tz'});
- my %cd = parse_date($co{'committer_epoch'}, $co{'committer_tz'});
my $parent = $co{'parent'};
my $parents = $co{'parents'}; # listref
}
print "<div class=\"title_text\">\n" .
"<table class=\"object_header\">\n";
- print "<tr><td>author</td><td>" . esc_html($co{'author'}) . "</td></tr>\n".
- "<tr>" .
- "<td></td><td> $ad{'rfc2822'}";
- if ($ad{'hour_local'} < 6) {
- printf(" (<span class=\"atnight\">%02d:%02d</span> %s)",
- $ad{'hour_local'}, $ad{'minute_local'}, $ad{'tz_local'});
- } else {
- printf(" (%02d:%02d %s)",
- $ad{'hour_local'}, $ad{'minute_local'}, $ad{'tz_local'});
- }
- print "</td>" .
- "</tr>\n";
- print "<tr><td>committer</td><td>" . esc_html($co{'committer'}) . "</td></tr>\n";
- print "<tr><td></td><td> $cd{'rfc2822'}" .
- sprintf(" (%02d:%02d %s)", $cd{'hour_local'}, $cd{'minute_local'}, $cd{'tz_local'}) .
- "</td></tr>\n";
+ git_print_authorship_rows(\%co);
print "<tr><td>commit</td><td class=\"sha1\">$co{'id'}</td></tr>\n";
print "<tr>" .
"<td>tree</td>" .
git_header_html(undef, $expires);
git_print_page_nav('commitdiff','', $hash,$co{'tree'},$hash, $formats_nav);
git_print_header_div('commit', esc_html($co{'title'}) . $ref, $hash);
- git_print_authorship(\%co);
+ print "<div class=\"title_text\">\n" .
+ "<table class=\"object_header\">\n";
+ git_print_authorship_rows(\%co);
+ print "</table>".
+ "</div>\n";
print "<div class=\"page_body\">\n";
if (@{$co{'comment'}} > 1) {
print "<div class=\"log\">\n";
index 92a47c71e7d93eef7dc8d6967cd071aa061218ce..5d162dae6e43cdfcf6b20627df088a73cbfa98dc 100644 (file)
--- a/grep.c
+++ b/grep.c
#include "cache.h"
#include "grep.h"
+#include "userdiff.h"
#include "xdiff-interface.h"
void append_header_grep_pattern(struct grep_opt *opt, enum grep_header_field field, const char *pat)
{
int rest = eol - bol;
+ if (opt->pre_context || opt->post_context) {
+ if (opt->last_shown == 0) {
+ if (opt->show_hunk_mark)
+ fputs("--\n", stdout);
+ else
+ opt->show_hunk_mark = 1;
+ } else if (lno > opt->last_shown + 1)
+ fputs("--\n", stdout);
+ }
+ opt->last_shown = lno;
+
if (opt->null_following_name)
sign = '\0';
if (opt->pathname)
printf("%.*s\n", rest, bol);
}
+static int match_funcname(struct grep_opt *opt, char *bol, char *eol)
+{
+ xdemitconf_t *xecfg = opt->priv;
+ if (xecfg && xecfg->find_func) {
+ char buf[1];
+ return xecfg->find_func(bol, eol - bol, buf, 1,
+ xecfg->find_func_priv) >= 0;
+ }
+
+ if (bol == eol)
+ return 0;
+ if (isalpha(*bol) || *bol == '_' || *bol == '$')
+ return 1;
+ return 0;
+}
+
+static void show_funcname_line(struct grep_opt *opt, const char *name,
+ char *buf, char *bol, unsigned lno)
+{
+ while (bol > buf) {
+ char *eol = --bol;
+
+ while (bol > buf && bol[-1] != '\n')
+ bol--;
+ lno--;
+
+ if (lno <= opt->last_shown)
+ break;
+
+ if (match_funcname(opt, bol, eol)) {
+ show_line(opt, bol, eol, name, lno, '=');
+ break;
+ }
+ }
+}
+
+static void show_pre_context(struct grep_opt *opt, const char *name, char *buf,
+ char *bol, unsigned lno)
+{
+ unsigned cur = lno, from = 1, funcname_lno = 0;
+ int funcname_needed = opt->funcname;
+
+ if (opt->pre_context < lno)
+ from = lno - opt->pre_context;
+ if (from <= opt->last_shown)
+ from = opt->last_shown + 1;
+
+ /* Rewind. */
+ while (bol > buf && cur > from) {
+ char *eol = --bol;
+
+ while (bol > buf && bol[-1] != '\n')
+ bol--;
+ cur--;
+ if (funcname_needed && match_funcname(opt, bol, eol)) {
+ funcname_lno = cur;
+ funcname_needed = 0;
+ }
+ }
+
+ /* We need to look even further back to find a function signature. */
+ if (opt->funcname && funcname_needed)
+ show_funcname_line(opt, name, buf, bol, cur);
+
+ /* Back forward. */
+ while (cur < lno) {
+ char *eol = bol, sign = (cur == funcname_lno) ? '=' : '-';
+
+ while (*eol != '\n')
+ eol++;
+ show_line(opt, bol, eol, name, cur, sign);
+ bol = eol + 1;
+ cur++;
+ }
+}
+
static int grep_buffer_1(struct grep_opt *opt, const char *name,
char *buf, unsigned long size, int collect_hits)
{
char *bol = buf;
unsigned long left = size;
unsigned lno = 1;
- struct pre_context_line {
- char *bol;
- char *eol;
- } *prev = NULL, *pcl;
unsigned last_hit = 0;
- unsigned last_shown = 0;
int binary_match_only = 0;
- const char *hunk_mark = "";
unsigned count = 0;
enum grep_context ctx = GREP_CONTEXT_HEAD;
+ xdemitconf_t xecfg;
+
+ opt->last_shown = 0;
if (buffer_is_binary(buf, size)) {
switch (opt->binary) {
}
}
- if (opt->pre_context)
- prev = xcalloc(opt->pre_context, sizeof(*prev));
- if (opt->pre_context || opt->post_context)
- hunk_mark = "--\n";
+ memset(&xecfg, 0, sizeof(xecfg));
+ if (opt->funcname && !opt->unmatch_name_only && !opt->status_only &&
+ !opt->name_only && !binary_match_only && !collect_hits) {
+ struct userdiff_driver *drv = userdiff_find_by_path(name);
+ if (drv && drv->funcname.pattern) {
+ const struct userdiff_funcname *pe = &drv->funcname;
+ xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags);
+ opt->priv = &xecfg;
+ }
+ }
while (left) {
char *eol, ch;
* the context which is nonsense, but the user
* deserves to get that ;-).
*/
- if (opt->pre_context) {
- unsigned from;
- if (opt->pre_context < lno)
- from = lno - opt->pre_context;
- else
- from = 1;
- if (from <= last_shown)
- from = last_shown + 1;
- if (last_shown && from != last_shown + 1)
- fputs(hunk_mark, stdout);
- while (from < lno) {
- pcl = &prev[lno-from-1];
- show_line(opt, pcl->bol, pcl->eol,
- name, from, '-');
- from++;
- }
- last_shown = lno-1;
- }
- if (last_shown && lno != last_shown + 1)
- fputs(hunk_mark, stdout);
+ if (opt->pre_context)
+ show_pre_context(opt, name, buf, bol, lno);
+ else if (opt->funcname)
+ show_funcname_line(opt, name, buf, bol, lno);
if (!opt->count)
show_line(opt, bol, eol, name, lno, ':');
- last_shown = last_hit = lno;
+ last_hit = lno;
}
else if (last_hit &&
lno <= last_hit + opt->post_context) {
/* If the last hit is within the post context,
* we need to show this line.
*/
- if (last_shown && lno != last_shown + 1)
- fputs(hunk_mark, stdout);
show_line(opt, bol, eol, name, lno, '-');
- last_shown = lno;
- }
- if (opt->pre_context) {
- memmove(prev+1, prev,
- (opt->pre_context-1) * sizeof(*prev));
- prev->bol = bol;
- prev->eol = eol;
}
next_line:
lno++;
}
- free(prev);
if (collect_hits)
return 0;
return 1;
}
+ xdiff_clear_find_func(&xecfg);
+ opt->priv = NULL;
+
/* NEEDSWORK:
* The real "grep -c foo *.c" gives many "bar.c:0" lines,
* which feels mostly useless but sometimes useful. Maybe
index 464e272edf4594539915a89d68628fd3959b8ee3..f00db0e40273c7cca1695ddc6be00921f9da8ef4 100644 (file)
--- a/grep.h
+++ b/grep.h
int pathname;
int null_following_name;
int color;
+ int funcname;
char color_match[COLOR_MAXLEN];
const char *color_external;
int regflags;
unsigned pre_context;
unsigned post_context;
+ unsigned last_shown;
+ int show_hunk_mark;
+ void *priv;
};
extern void append_grep_pattern(struct grep_opt *opt, const char *pat, const char *origin, int no, enum grep_pat_token t);
diff --git a/hash-object.c b/hash-object.c
index 47cf43c3cdd2bcd7638360a130fc8ef04ce132e9..9455dd0709aeb81436ef2e3e36422578d66ce8e7 100644 (file)
--- a/hash-object.c
+++ b/hash-object.c
int fd;
fd = open(path, O_RDONLY);
if (fd < 0)
- die("Cannot open %s", path);
+ die_errno("Cannot open '%s'", path);
hash_fd(fd, type, write_object, vpath);
}
diff --git a/http-push.c b/http-push.c
index 8cc8ee0dfd5c047b2523f63346bf9b30094c1386..00e83dcec1d973b069d4c75105aed96634b00994 100644 (file)
--- a/http-push.c
+++ b/http-push.c
case '&':
strbuf_addstr(&buf, "&");
break;
+ case 0:
+ return strbuf_detach(&buf, NULL);
}
s++;
}
index b0499482455e256a3c2c9b6498b21c32d328c5c9..a2720d576d72e456b038444050f5b8de9d25d792 100644 (file)
--- a/http.c
+++ b/http.c
static const char *curl_http_proxy;
static char *user_name, *user_pass;
+#if LIBCURL_VERSION_NUM >= 0x071700
+/* Use CURLOPT_KEYPASSWD as is */
+#elif LIBCURL_VERSION_NUM >= 0x070903
+#define CURLOPT_KEYPASSWD CURLOPT_SSLKEYPASSWD
+#else
+#define CURLOPT_KEYPASSWD CURLOPT_SSLCERTPASSWD
+#endif
+
+static char *ssl_cert_password;
+static int ssl_cert_password_required;
+
static struct curl_slist *pragma_header;
static struct curl_slist *no_pragma_header;
#endif
if (!strcmp("http.sslcainfo", var))
return git_config_string(&ssl_cainfo, var, value);
+ if (!strcmp("http.sslcertpasswordprotected", var)) {
+ if (git_config_bool(var, value))
+ ssl_cert_password_required = 1;
+ return 0;
+ }
#ifdef USE_CURL_MULTI
if (!strcmp("http.maxrequests", var)) {
max_requests = git_config_int(var, value);
}
}
+static int has_cert_password(void)
+{
+ if (ssl_cert_password != NULL)
+ return 1;
+ if (ssl_cert == NULL || ssl_cert_password_required != 1)
+ return 0;
+ /* Only prompt the user once. */
+ ssl_cert_password_required = -1;
+ ssl_cert_password = getpass("Certificate Password: ");
+ if (ssl_cert_password != NULL) {
+ ssl_cert_password = xstrdup(ssl_cert_password);
+ return 1;
+ } else
+ return 0;
+}
+
static CURL *get_curl_handle(void)
{
CURL *result = curl_easy_init();
if (ssl_cert != NULL)
curl_easy_setopt(result, CURLOPT_SSLCERT, ssl_cert);
+ if (has_cert_password())
+ curl_easy_setopt(result, CURLOPT_KEYPASSWD, ssl_cert_password);
#if LIBCURL_VERSION_NUM >= 0x070903
if (ssl_key != NULL)
curl_easy_setopt(result, CURLOPT_SSLKEY, ssl_key);
if (getenv("GIT_CURL_FTP_NO_EPSV"))
curl_ftp_no_epsv = 1;
- if (remote && remote->url && remote->url[0])
+ if (remote && remote->url && remote->url[0]) {
http_auth_init(remote->url[0]);
+ if (!ssl_cert_password_required &&
+ getenv("GIT_SSL_CERT_PASSWORD_PROTECTED") &&
+ !prefixcmp(remote->url[0], "https://"))
+ ssl_cert_password_required = 1;
+ }
#ifndef NO_CURL_EASY_DUPHANDLE
curl_default = get_curl_handle();
free((void *)curl_http_proxy);
curl_http_proxy = NULL;
}
+
+ if (ssl_cert_password != NULL) {
+ memset(ssl_cert_password, 0, strlen(ssl_cert_password));
+ free(ssl_cert_password);
+ ssl_cert_password = NULL;
+ }
+ ssl_cert_password_required = 0;
}
struct active_request_slot *get_active_slot(void)
diff --git a/index-pack.c b/index-pack.c
index c72cbd406a7880361f262f43daff62a9f453628d..340074fc793e8e7534bb168784a7051af6d81b34 100644 (file)
--- a/index-pack.c
+++ b/index-pack.c
if (ret <= 0) {
if (!ret)
die("early EOF");
- die("read error on input: %s", strerror(errno));
+ die_errno("read error on input");
}
input_len += ret;
if (from_stdin)
} else
output_fd = open(pack_name, O_CREAT|O_EXCL|O_RDWR, 0600);
if (output_fd < 0)
- die("unable to create %s: %s", pack_name, strerror(errno));
+ die_errno("unable to create '%s'", pack_name);
pack_fd = output_fd;
} else {
input_fd = open(pack_name, O_RDONLY);
if (input_fd < 0)
- die("cannot open packfile '%s': %s",
- pack_name, strerror(errno));
+ die_errno("cannot open packfile '%s'", pack_name);
output_fd = -1;
pack_fd = input_fd;
}
do {
ssize_t n = pread(pack_fd, data + rdy, len - rdy, from + rdy);
if (n < 0)
- die("cannot pread pack file: %s", strerror(errno));
+ die_errno("cannot pread pack file");
if (!n)
die("premature end of pack file, %lu bytes missing",
len - rdy);
/* If input_fd is a file, we should have reached its end now. */
if (fstat(input_fd, &st))
- die("cannot fstat packfile: %s", strerror(errno));
+ die_errno("cannot fstat packfile");
if (S_ISREG(st.st_mode) &&
lseek(input_fd, 0, SEEK_CUR) - input_len != st.st_size)
die("pack has junk at the end");
fsync_or_die(output_fd, curr_pack_name);
err = close(output_fd);
if (err)
- die("error while closing pack file: %s", strerror(errno));
+ die_errno("error while closing pack file");
}
if (keep_msg) {
if (keep_fd < 0) {
if (errno != EEXIST)
- die("cannot write keep file '%s' (%s)",
- keep_name, strerror(errno));
+ die_errno("cannot write keep file '%s'",
+ keep_name);
} else {
if (keep_msg_len > 0) {
write_or_die(keep_fd, keep_msg, keep_msg_len);
write_or_die(keep_fd, "\n", 1);
}
if (close(keep_fd) != 0)
- die("cannot close written keep file '%s' (%s)",
- keep_name, strerror(errno));
+ die_errno("cannot close written keep file '%s'",
+ keep_name);
report = "keep";
}
}
diff --git a/ll-merge.c b/ll-merge.c
index 9168958e863e50f0d1bd1446b3314cb3dd2e772f..0571564ddfb336247c8268fbdecd8674d8bacd3e 100644 (file)
--- a/ll-merge.c
+++ b/ll-merge.c
static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
mmbuffer_t *result,
- const char *path_unused,
+ const char *path,
mmfile_t *orig,
mmfile_t *src1, const char *name1,
mmfile_t *src2, const char *name2,
if (buffer_is_binary(orig->ptr, orig->size) ||
buffer_is_binary(src1->ptr, src1->size) ||
buffer_is_binary(src2->ptr, src2->size)) {
- warning("Cannot merge binary files: %s vs. %s\n",
- name1, name2);
+ warning("Cannot merge binary files: %s (%s vs. %s)\n",
+ path, name1, name2);
return ll_binary_merge(drv_unused, result,
- path_unused,
+ path,
orig, src1, name1,
src2, name2,
virtual_ancestor);
strcpy(path, ".merge_file_XXXXXX");
fd = xmkstemp(path);
if (write_in_full(fd, src->ptr, src->size) != src->size)
- die("unable to write temp-file");
+ die_errno("unable to write temp-file");
close(fd);
}
diff --git a/log-tree.c b/log-tree.c
index 59d63eb67e57ab55bdca6493fa8b28b0c870ff21..6f73c17d74bee326a40505b29bba762bade2451e 100644 (file)
--- a/log-tree.c
+++ b/log-tree.c
}
/*
- * If use_terminator is set, add a newline at the end of the entry.
+ * If use_terminator is set, we already handled any record termination
+ * at the end of the last record.
* Otherwise, add a diffopt.line_termination character before all
* entries but the first. (IOW, as a separator between entries)
*/
diff --git a/merge-recursive.c b/merge-recursive.c
index c703445a9cdf66f2933c1ffce636bfe3c11a048c..d415c4188d181fbdc765fff90fbbc4897ced53ad 100644 (file)
--- a/merge-recursive.c
+++ b/merge-recursive.c
/* Ignore epipe */
if (errno == EPIPE)
break;
- die("merge-recursive: %s", strerror(errno));
+ die_errno("merge-recursive");
} else if (!ret) {
die("merge-recursive: disk full?");
}
mode = 0666;
fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, mode);
if (fd < 0)
- die("failed to open %s: %s", path, strerror(errno));
+ die_errno("failed to open '%s'", path);
flush_buffer(fd, buf, size);
close(fd);
} else if (S_ISLNK(mode)) {
safe_create_leading_directories_const(path);
unlink(path);
if (symlink(lnk, path))
- die("failed to symlink %s: %s", path, strerror(errno));
+ die_errno("failed to symlink '%s'", path);
free(lnk);
} else
die("do not know what to do with %06o %s '%s'",
char *name1, *name2;
int merge_status;
- name1 = xstrdup(mkpath("%s:%s", branch1, a->path));
- name2 = xstrdup(mkpath("%s:%s", branch2, b->path));
+ if (strcmp(a->path, b->path)) {
+ name1 = xstrdup(mkpath("%s:%s", branch1, a->path));
+ name2 = xstrdup(mkpath("%s:%s", branch2, b->path));
+ } else {
+ name1 = xstrdup(mkpath("%s", branch1));
+ name2 = xstrdup(mkpath("%s", branch2));
+ }
fill_mm(one->sha1, &orig);
fill_mm(a->sha1, &src1);
index 99a356e9ee75cb247d80ed6dc0b251ceb0bd9e46..a609e3ebd106ed985fa2065dc4af6565e5a379a6 100644 (file)
--- a/mktag.c
+++ b/mktag.c
setup_git_directory();
if (strbuf_read(&buf, 0, 4096) < 0) {
- die("could not read from stdin");
+ die_errno("could not read from stdin");
}
/* Verify it for some basic sanity: it needs to start with
diff --git a/pack-refs.c b/pack-refs.c
index 301fc60eae1ad53721851a272a0fbd0192881801..7f43f8ac3398fb2dbe393f08811989b0a8d4e2dd 100644 (file)
--- a/pack-refs.c
+++ b/pack-refs.c
LOCK_DIE_ON_ERROR);
cbdata.refs_file = fdopen(fd, "w");
if (!cbdata.refs_file)
- die("unable to create ref-pack file structure (%s)",
- strerror(errno));
+ die_errno("unable to create ref-pack file structure");
/* perhaps other traits later as well */
fprintf(cbdata.refs_file, "# pack-refs with: peeled \n");
if (ferror(cbdata.refs_file))
die("failed to write ref-pack file");
if (fflush(cbdata.refs_file) || fsync(fd) || fclose(cbdata.refs_file))
- die("failed to write ref-pack file (%s)", strerror(errno));
+ die_errno("failed to write ref-pack file");
/*
* Since the lock file was fdopen()'ed and then fclose()'ed above,
* assign -1 to the lock file descriptor so that commit_lock_file()
*/
packed.fd = -1;
if (commit_lock_file(&packed) < 0)
- die("unable to overwrite old ref-pack file (%s)", strerror(errno));
+ die_errno("unable to overwrite old ref-pack file");
if (cbdata.flags & PACK_REFS_PRUNE)
prune_refs(cbdata.ref_to_prune);
return 0;
diff --git a/pack-write.c b/pack-write.c
index 7053538f4cf44e15a788ab46dfb680ee85ce4fc2..741efcd93bd2a2c105bfe2d771d32857ce2ae816 100644 (file)
--- a/pack-write.c
+++ b/pack-write.c
fd = open(index_name, O_CREAT|O_EXCL|O_WRONLY, 0600);
}
if (fd < 0)
- die("unable to create %s: %s", index_name, strerror(errno));
+ die_errno("unable to create '%s'", index_name);
f = sha1fd(fd, index_name);
/* if last object's offset is >= 2^31 we should use index V2 */
git_SHA1_Init(&new_sha1_ctx);
if (lseek(pack_fd, 0, SEEK_SET) != 0)
- die("Failed seeking to start of %s: %s", pack_name, strerror(errno));
+ die_errno("Failed seeking to start of '%s'", pack_name);
if (read_in_full(pack_fd, &hdr, sizeof(hdr)) != sizeof(hdr))
- die("Unable to reread header of %s: %s", pack_name, strerror(errno));
+ die_errno("Unable to reread header of '%s'", pack_name);
if (lseek(pack_fd, 0, SEEK_SET) != 0)
- die("Failed seeking to start of %s: %s", pack_name, strerror(errno));
+ die_errno("Failed seeking to start of '%s'", pack_name);
git_SHA1_Update(&old_sha1_ctx, &hdr, sizeof(hdr));
hdr.hdr_entries = htonl(object_count);
git_SHA1_Update(&new_sha1_ctx, &hdr, sizeof(hdr));
if (!n)
break;
if (n < 0)
- die("Failed to checksum %s: %s", pack_name, strerror(errno));
+ die_errno("Failed to checksum '%s'", pack_name);
git_SHA1_Update(&new_sha1_ctx, buf, n);
aligned_sz -= n;
diff --git a/pkt-line.c b/pkt-line.c
index f5d00863a6234c16db33637d19fefd2014780e87..b691abebd79b40f096b28b5dbcb433f01bc0e949 100644 (file)
--- a/pkt-line.c
+++ b/pkt-line.c
}
if (!ret)
die("write error (disk full?)");
- die("write error (%s)", strerror(errno));
+ die_errno("write error");
}
return nn;
}
{
ssize_t ret = read_in_full(fd, buffer, size);
if (ret < 0)
- die("read error (%s)", strerror(errno));
+ die_errno("read error");
else if (ret < size)
die("The remote end hung up unexpectedly");
}
diff --git a/read-cache.c b/read-cache.c
index 3f587110cb9d7be1890b7db68a0bdac35d48cd35..4e3e272ee409de66de2059a8be475fddcaa4dc28 100644 (file)
--- a/read-cache.c
+++ b/read-cache.c
{
struct stat st;
if (lstat(path, &st))
- die("%s: unable to stat (%s)", path, strerror(errno));
+ die_errno("unable to stat '%s'", path);
return add_to_index(istate, path, &st, flags);
}
if (fd < 0) {
if (errno == ENOENT)
return 0;
- die("index file open failed (%s)", strerror(errno));
+ die_errno("index file open failed");
}
if (fstat(fd, &st))
- die("cannot stat the open index (%s)", strerror(errno));
+ die_errno("cannot stat the open index");
errno = EINVAL;
mmap_size = xsize_t(st.st_size);
mmap = xmmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
close(fd);
if (mmap == MAP_FAILED)
- die("unable to map index file");
+ die_errno("unable to map index file");
hdr = mmap;
if (verify_hdr(hdr, mmap_size) < 0)
index 24438c652fe4e09aaa1ba6dab283b8e59c24c1a7..dffe395a97a12f2489dc5bbec1f822e3b8f08de5 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -1418,7 +1418,7 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *
logfile = git_path("logs/%s", ref);
logfd = open(logfile, O_RDONLY, 0);
if (logfd < 0)
- die("Unable to read log %s: %s", logfile, strerror(errno));
+ die_errno("Unable to read log '%s'", logfile);
fstat(logfd, &st);
if (!st.st_size)
die("Log %s is empty.", logfile);
diff --git a/remote.c b/remote.c
index 733ba57494715e00427350af4175fe67c390ec34..c3ada2d72b9b3f7411ffe420030768e73a003923 100644 (file)
--- a/remote.c
+++ b/remote.c
static struct ref *get_local_ref(const char *name)
{
- if (!name)
+ if (!name || name[0] == '\0')
return NULL;
if (!prefixcmp(name, "refs/"))
diff --git a/revision.c b/revision.c
index bf584483675ef55b2ed9b8d8586b92d5432759a5..a31434bdc8ed19674d3c4863e009af0c40d75e73 100644 (file)
--- a/revision.c
+++ b/revision.c
@@ -1077,6 +1077,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
revs->show_all = 1;
} else if (!strcmp(arg, "--remove-empty")) {
revs->remove_empty_trees = 1;
+ } else if (!strcmp(arg, "--merges")) {
+ revs->merges_only = 1;
} else if (!strcmp(arg, "--no-merges")) {
revs->no_merges = 1;
} else if (!strcmp(arg, "--boundary")) {
@@ -1676,6 +1678,8 @@ enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit)
return commit_ignore;
if (revs->no_merges && commit->parents && commit->parents->next)
return commit_ignore;
+ if (revs->merges_only && !(commit->parents && commit->parents->next))
+ return commit_ignore;
if (!commit_match(commit, revs))
return commit_ignore;
if (revs->prune && revs->dense) {
diff --git a/revision.h b/revision.h
index 227164cf7096d3b0642714b18ee345738684da79..fb74492714b9276d02992dbe1101efff2cbdb5e6 100644 (file)
--- a/revision.h
+++ b/revision.h
unsigned int dense:1,
prune:1,
no_merges:1,
+ merges_only:1,
no_walk:1,
show_all:1,
remove_empty_trees:1,
diff --git a/run-command.c b/run-command.c
index eb2efc33073512efd14b65e67db8cf814ca3fa33..ff3d8e2d8bf3208b7ad0f29d7cf76cc84a4ad0e6 100644 (file)
--- a/run-command.c
+++ b/run-command.c
}
if (cmd->dir && chdir(cmd->dir))
- die("exec %s: cd to %s failed (%s)", cmd->argv[0],
- cmd->dir, strerror(errno));
+ die_errno("exec '%s': cd to '%s' failed", cmd->argv[0],
+ cmd->dir);
if (cmd->env) {
for (; *cmd->env; cmd->env++) {
if (strchr(*cmd->env, '='))
index ebd60de9ce5b52f348819a6a390c15b8dc08d2ff..e3781b656d77be94e04c5229e6a190c5fc496490 100644 (file)
--- a/setup.c
+++ b/setup.c
if (errno == ENOENT)
die("ambiguous argument '%s': unknown revision or path not in the working tree.\n"
"Use '--' to separate paths from revisions", arg);
- die("'%s': %s", arg, strerror(errno));
+ die_errno("failed to stat '%s'", arg);
}
/*
die("ambiguous argument '%s': both revision and filename\n"
"Use '--' to separate filenames from revisions", arg);
if (errno != ENOENT && errno != ENOTDIR)
- die("'%s': %s", arg, strerror(errno));
+ die_errno("failed to stat '%s'", arg);
}
const char **get_pathspec(const char *prefix, const char **pathspec)
return NULL;
fd = open(path, O_RDONLY);
if (fd < 0)
- die("Error opening %s: %s", path, strerror(errno));
+ die_errno("Error opening '%s'", path);
buf = xmalloc(st.st_size + 1);
len = read_in_full(fd, buf, st.st_size);
close(fd);
return NULL;
set_git_dir(make_absolute_path(gitdirenv));
if (chdir(work_tree_env) < 0)
- die ("Could not chdir to %s", work_tree_env);
+ die_errno ("Could not chdir to '%s'", work_tree_env);
strcat(buffer, "/");
return retval;
}
}
if (!getcwd(cwd, sizeof(cwd)-1))
- die("Unable to read current working directory");
+ die_errno("Unable to read current working directory");
ceil_offset = longest_ancestor_length(cwd, env_ceiling_dirs);
if (ceil_offset < 0 && has_dos_drive_prefix(cwd))
if (offset <= ceil_offset) {
if (nongit_ok) {
if (chdir(cwd))
- die("Cannot come back to cwd");
+ die_errno("Cannot come back to cwd");
*nongit_ok = 1;
return NULL;
}
die("Not a git repository (or any of the parent directories): %s", DEFAULT_GIT_DIR_ENVIRONMENT);
}
if (chdir(".."))
- die("Cannot change to %s/..: %s", cwd, strerror(errno));
+ die_errno("Cannot change to '%s/..'", cwd);
}
inside_git_dir = 0;
static char buffer[PATH_MAX + 1];
char *rel;
if (retval && chdir(retval))
- die ("Could not jump back into original cwd");
+ die_errno ("Could not jump back into original cwd");
rel = get_relative_cwd(buffer, PATH_MAX, get_git_work_tree());
if (rel && *rel && chdir(get_git_work_tree()))
- die ("Could not jump to working directory");
+ die_errno ("Could not jump to working directory");
return rel && *rel ? strcat(rel, "/") : NULL;
}
diff --git a/sha1_file.c b/sha1_file.c
index 8f5fe62d545ace21c338cd554c76bac5d5acb431..4576ff77f3ceec7231b14261f7386abb2289cd5c 100644 (file)
--- a/sha1_file.c
+++ b/sha1_file.c
if (fsync_object_files)
fsync_or_die(fd, "sha1 file");
if (close(fd) != 0)
- die("error when closing sha1 file (%s)", strerror(errno));
+ die_errno("error when closing sha1 file");
}
/* Size of directory component, including the ending '/' */
index b968be79f487f8d93e205fd0a844a206e24f21f8..e4864e04da3b0e237342c2ca0548c0ec0082c171 100644 (file)
--- a/shell.c
+++ b/shell.c
while (devnull_fd >= 0 && devnull_fd <= 2)
devnull_fd = dup(devnull_fd);
if (devnull_fd == -1)
- die("opening /dev/null failed (%s)", strerror(errno));
+ die_errno("opening /dev/null failed");
close (devnull_fd);
/*
index 997002d4c40dd8e66e3be5a701e3d99bab1c57c4..e5040580626f4df6159c929c1ad54f085f03d830 100755 (executable)
EOF
-test_expect_success 'test --parseopt help output' '
- git rev-parse --parseopt -- -h 2> output.err <<EOF
+cat > optionspec << EOF
some-command [options] <args>...
some-command does foo and bar!
Extras
extra1 line above used to cause a segfault but no longer does
EOF
+
+test_expect_success 'test --parseopt help output' '
+ git rev-parse --parseopt -- -h 2> output.err < optionspec
test_cmp expect.err output.err
'
+cat > expect <<EOF
+set -- --foo --bar 'ham' -- 'arg'
+EOF
+
+test_expect_success 'test --parseopt' '
+ git rev-parse --parseopt -- --foo --bar=ham arg < optionspec > output &&
+ test_cmp expect output
+'
+
+test_expect_success 'test --parseopt with mixed options and arguments' '
+ git rev-parse --parseopt -- --foo arg --bar=ham < optionspec > output &&
+ test_cmp expect output
+'
+
+cat > expect <<EOF
+set -- --foo -- 'arg' '--bar=ham'
+EOF
+
+test_expect_success 'test --parseopt with --' '
+ git rev-parse --parseopt -- --foo -- arg --bar=ham < optionspec > output &&
+ test_cmp expect output
+'
+
+test_expect_success 'test --parseopt --stop-at-non-option' '
+ git rev-parse --parseopt --stop-at-non-option -- --foo arg --bar=ham < optionspec > output &&
+ test_cmp expect output
+'
+
+cat > expect <<EOF
+set -- --foo -- '--' 'arg' '--bar=ham'
+EOF
+
+test_expect_success 'test --parseopt --keep-dashdash' '
+ git rev-parse --parseopt --keep-dashdash -- --foo -- arg --bar=ham < optionspec > output &&
+ test_cmp expect output
+'
+
test_done
diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh
index 7f62bfb9ddbc4b28017be529d73c7ece29424fec..c5c29ccc4f372723fc77c1af0d7cb7879b92729f 100755 (executable)
--- a/t/t3400-rebase.sh
+++ b/t/t3400-rebase.sh
git rebase master'
test_expect_success 'rebase against master twice' '
- git rebase master 2>err &&
- grep "Current branch my-topic-branch is up to date" err
+ git rebase master >out &&
+ grep "Current branch my-topic-branch is up to date" out
'
test_expect_success 'rebase against master twice with --force' '
test_expect_success 'rebase against master twice from another branch' '
git checkout my-topic-branch^ &&
- git rebase master my-topic-branch 2>err &&
- grep "Current branch my-topic-branch is up to date" err
+ git rebase master my-topic-branch >out &&
+ grep "Current branch my-topic-branch is up to date" out
'
test_expect_success 'rebase fast-forward to master' '
git checkout my-topic-branch^ &&
- git rebase my-topic-branch 2>err &&
- grep "Fast-forwarded HEAD to my-topic-branch" err
+ git rebase my-topic-branch >out &&
+ grep "Fast-forwarded HEAD to my-topic-branch" out
'
test_expect_success \
grep "Untracked working tree file .B. would be overwritten" output.err
'
+test_expect_success 'rebase -q is quiet' '
+ rm B &&
+ git checkout -b quiet topic &&
+ git rebase -q master > output.out 2>&1 &&
+ test ! -s output.out
+'
+
test_done
index c32ff6682b932b3d9b270de7260a2671d8d07403..a973628e8e3767ae017a6b18742bf4b66a68cdaa 100755 (executable)
EOF
cat > expect2 << EOF
-<<<<<<< HEAD:file1
+<<<<<<< HEAD
2
=======
3
->>>>>>> b7ca976... G:file1
+>>>>>>> b7ca976... G
EOF
test_expect_success 'stop on conflicting pick' '
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index 7484cbede6ccd3ecb56a3ebff734740cb543c0a4..7a3fb679571a9fc79135f8b9495462f723b663af 100755 (executable)
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
test 0 = $(git stash list | wc -l)
'
+test_expect_success 'apply -q is quiet' '
+ echo foo > file &&
+ git stash &&
+ git stash apply -q > output.out 2>&1 &&
+ test ! -s output.out
+'
+
+test_expect_success 'save -q is quiet' '
+ git stash save --quiet > output.out 2>&1 &&
+ test ! -s output.out
+'
+
+test_expect_success 'pop -q is quiet' '
+ git stash pop -q > output.out 2>&1 &&
+ test ! -s output.out
+'
+
+test_expect_success 'drop -q is quiet' '
+ git stash &&
+ git stash drop -q > output.out 2>&1 &&
+ test ! -s output.out
+'
+
test_done
diff --git a/t/t4037-diff-r-t-dirs.sh b/t/t4037-diff-r-t-dirs.sh
--- /dev/null
+++ b/t/t4037-diff-r-t-dirs.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+test_description='diff -r -t shows directory additions and deletions'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ mkdir dc dr dt &&
+ >dc/1 &&
+ >dr/2 &&
+ >dt/3 &&
+ >fc &&
+ >fr &&
+ >ft &&
+ git add . &&
+ test_tick &&
+ git commit -m initial &&
+
+ rm -fr dt dr ft fr &&
+ mkdir da ft &&
+ for p in dc/1 da/4 dt ft/5 fc
+ do
+ echo hello >$p || exit
+ done &&
+ git add -u &&
+ git add . &&
+ test_tick &&
+ git commit -m second
+'
+
+cat >expect <<\EOF
+A da
+A da/4
+M dc
+M dc/1
+D dr
+D dr/2
+A dt
+D dt
+D dt/3
+M fc
+D fr
+D ft
+A ft
+A ft/5
+EOF
+
+test_expect_success verify '
+ git diff-tree -r -t --name-status HEAD^ HEAD >actual &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t4150-am.sh b/t/t4150-am.sh
index d6ebbaebe2c258a4694cfb709809e13d24084231..a12bf846231d18b2a815151d1a0e1ab3d5f491d1 100755 (executable)
--- a/t/t4150-am.sh
+++ b/t/t4150-am.sh
test -z "$(git diff lorem)"
'
+test_expect_success 'am -3 -q is quiet' '
+ git reset master2 --hard &&
+ sed -n -e "3,\$p" msg >file &&
+ head -n 9 msg >>file &&
+ git add file &&
+ test_tick &&
+ git commit -m "copied stuff" &&
+ git am -3 -q lorem-move.patch > output.out 2>&1 &&
+ ! test -s output.out
+'
+
test_expect_success 'am pauses on conflict' '
git checkout lorem2^^ &&
test_must_fail git am lorem-move.patch &&
test "z$result" = "z$(git rev-parse first^{tree})"
'
+test_expect_success 'am newline in subject' '
+ git checkout first &&
+ test_tick &&
+ sed -e "s/second/second \\\n foo/" patch1 > patchnl &&
+ git am < patchnl > output.out 2>&1 &&
+ grep "^Applying: second \\\n foo$" output.out
+'
+
+test_expect_success 'am -q is quiet' '
+ git checkout first &&
+ test_tick &&
+ git am -q < patch1 > output.out 2>&1 &&
+ ! test -s output.out
+'
+
test_done
index 129fa3000c9543804b43e74e27eec523e328bb5c..b3fbf659c003acbed785558c21950046b8caced8 100755 (executable)
"
cat > expect << EOF
-<<<<<<< HEAD:a1
+<<<<<<< HEAD
F
=======
G
->>>>>>> G:a1
+>>>>>>> G
EOF
test_expect_success "result contains a conflict" "test_cmp expect a1"
git ls-files --stage > out
cat > expect << EOF
-100644 da056ce14a2241509897fa68bb2b3b6e6194ef9e 1 a1
+100644 439cc46de773d8a83c77799b7cc9191c128bfcff 1 a1
100644 cf84443e49e1b366fac938711ddf4be2d4d1d9e9 2 a1
100644 fd7923529855d0b274795ae3349c5e0438333979 3 a1
EOF
git add binary-file &&
git commit -m binary2 &&
test_must_fail git merge F > merge.out 2> merge.err &&
- grep "Cannot merge binary files: HEAD:binary-file vs. F:binary-file" \
- merge.err
+ grep "Cannot merge binary files: binary-file (HEAD vs. F)" merge.err
'
test_expect_success 'mark rename/delete as unmerged' '
index 4556cdd8d2ac5d0b5c0e49d232de9923695ee540..1315bab595c03f16b89060434588b505faf1c46b 100755 (executable)
hash7=$(git rev-parse --verify HEAD) &&
test "$hash7" = "$HASH7" &&
git bisect skip &&
- hash3=$(git rev-parse --verify HEAD) &&
- test "$hash3" = "$HASH3"
+ para3=$(git rev-parse --verify HEAD) &&
+ test "$para3" = "$PARA_HASH3"
'
#
diff --git a/t/t7002-grep.sh b/t/t7002-grep.sh
index 7868af8f1896e621b98a2ae9b71492a68a96e584..b13aa7e89ad51566979ab674baa2ac36c7e33da6 100755 (executable)
--- a/t/t7002-grep.sh
+++ b/t/t7002-grep.sh
. ./test-lib.sh
+cat >hello.c <<EOF
+#include <stdio.h>
+int main(int argc, const char **argv)
+{
+ printf("Hello world.\n");
+ return 0;
+}
+EOF
+
test_expect_success setup '
{
echo foo mmap bar
echo zzz > z &&
mkdir t &&
echo test >t/t &&
- git add file w x y z t/t &&
+ git add file w x y z t/t hello.c &&
test_tick &&
git commit -m initial
'
test_cmp expected actual
'
+cat >expected <<EOF
+y:y yy
+--
+z:zzz
+EOF
+
+# Create 1024 file names that sort between "y" and "z" to make sure
+# the two files are handled by different calls to an external grep.
+# This depends on MAXARGS in builtin-grep.c being 1024 or less.
+c32="0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v"
+test_expect_success 'grep -C1, hunk mark between files' '
+ for a in $c32; do for b in $c32; do : >y-$a$b; done; done &&
+ git add y-?? &&
+ git grep -C1 "^[yz]" >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'grep -C1 --no-ext-grep, hunk mark between files' '
+ git grep -C1 --no-ext-grep "^[yz]" >actual &&
+ test_cmp expected actual
+'
+
test_expect_success 'log grep setup' '
echo a >>file &&
test_tick &&
test_expect_success 'grep with CE_VALID file' '
git update-index --assume-unchanged t/t &&
rm t/t &&
- test "$(git grep --no-ext-grep t)" = "t/t:test" &&
+ test "$(git grep --no-ext-grep test)" = "t/t:test" &&
git update-index --no-assume-unchanged t/t &&
git checkout t/t
'
+cat >expected <<EOF
+hello.c=#include <stdio.h>
+hello.c: return 0;
+EOF
+
+test_expect_success 'grep -p with userdiff' '
+ git config diff.custom.funcname "^#" &&
+ echo "hello.c diff=custom" >.gitattributes &&
+ git grep -p return >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+hello.c=int main(int argc, const char **argv)
+hello.c: return 0;
+EOF
+
+test_expect_success 'grep -p' '
+ rm -f .gitattributes &&
+ git grep -p return >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<EOF
+hello.c-#include <stdio.h>
+hello.c=int main(int argc, const char **argv)
+hello.c-{
+hello.c- printf("Hello world.\n");
+hello.c: return 0;
+EOF
+
+test_expect_success 'grep -p -B5' '
+ git grep -p -B5 return >actual &&
+ test_cmp expected actual
+'
+
test_done
index d539619e89c5263e3b8339c408f1c0dcd867457b..627518108acfbab990fc259412e395150c1fb5b1 100755 (executable)
\$feature{'blame'}{'override'} = 1;
\$feature{'snapshot'}{'override'} = 1;
+\$feature{'avatar'}{'override'} = 1;
EOF
test_expect_success \
'config override: tree view, features disabled in repo config' \
'git config gitweb.blame no &&
git config gitweb.snapshot none &&
+ git config gitweb.avatar gravatar &&
gitweb_run "p=.git;a=tree"'
test_debug 'cat gitweb.log'
diff --git a/test-sha1.c b/test-sha1.c
index 9b98d07c786b36f005f4b3ffd51926f3c1a343dd..80daba980ecd85852ee3a23c155602e4cd1ba07a 100644 (file)
--- a/test-sha1.c
+++ b/test-sha1.c
if (sz == 0)
break;
if (sz < 0)
- die("test-sha1: %s", strerror(errno));
+ die_errno("test-sha1");
this_sz += sz;
cp += sz;
room -= sz;
diff --git a/transport.c b/transport.c
index b07406745ebb303b17baae6ba673897359ed7d87..de0d5874a3d867d71eaec3cd1dde1bf2f09cfe4d 100644 (file)
--- a/transport.c
+++ b/transport.c
@@ -158,7 +158,7 @@ static struct ref *get_refs_via_rsync(struct transport *transport, int for_push)
strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX"));
if (!mkdtemp(temp_dir.buf))
- die ("Could not make temporary directory");
+ die_errno ("Could not make temporary directory");
temp_dir_len = temp_dir.len;
strbuf_addstr(&buf, rsync_url(transport->url));
strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX"));
if (!mkdtemp(temp_dir.buf))
- die ("Could not make temporary directory");
+ die_errno ("Could not make temporary directory");
strbuf_addch(&temp_dir, '/');
if (flags & TRANSPORT_PUSH_ALL) {
diff --git a/tree-diff.c b/tree-diff.c
index edd83949bf0896bedff4cab8e2b037eba574a45e..0459e54d3d89a413330f52ab34662f51924b04ea 100644 (file)
--- a/tree-diff.c
+++ b/tree-diff.c
@@ -239,6 +239,12 @@ static void show_entry(struct diff_options *opt, const char *prefix, struct tree
if (!tree || type != OBJ_TREE)
die("corrupt tree sha %s", sha1_to_hex(sha1));
+ if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE)) {
+ newbase[baselen + pathlen] = 0;
+ opt->add_remove(opt, *prefix, mode, sha1, newbase);
+ newbase[baselen + pathlen] = '/';
+ }
+
init_tree_desc(&inner, tree, size);
show_tree(opt, prefix, &inner, newbase, baselen + 1 + pathlen);
diff --git a/unpack-file.c b/unpack-file.c
index 75cd2f1a6adf3ea773a6acc3f1e7f122e30676e5..ac9cbf7cd8ed1367151de0e8b96668f498b7f1a1 100644 (file)
--- a/unpack-file.c
+++ b/unpack-file.c
strcpy(path, ".merge_file_XXXXXX");
fd = xmkstemp(path);
if (write_in_full(fd, buf, size) != size)
- die("unable to write temp-file");
+ die_errno("unable to write temp-file");
close(fd);
return path;
}
diff --git a/upload-pack.c b/upload-pack.c
index edc78612289c5bd774e18fe5f8e1b9ea80378a5f..841ebb534ac3393f5ee80692f1402c82a1b4a5f6 100644 (file)
--- a/upload-pack.c
+++ b/upload-pack.c
static int multi_ack, nr_our_refs;
static int use_thin_pack, use_ofs_delta, use_include_tag;
-static int no_progress;
+static int no_progress, daemon_mode;
static struct object_array have_obj;
static struct object_array want_obj;
static unsigned int timeout;
}
if (debug_fd)
write_in_full(debug_fd, "#E\n", 3);
+
+ if (!use_sideband && daemon_mode)
+ no_progress = 1;
+
if (depth == 0 && shallows.nr == 0)
return;
if (depth > 0) {
}
if (!prefixcmp(arg, "--timeout=")) {
timeout = atoi(arg+10);
+ daemon_mode = 1;
continue;
}
if (!strcmp(arg, "--")) {
index 820d09f92b03b6cc96fbe9a954c37fd2d5e5a417..b6aea45280bf2aa4c06a0130f912a61377165016 100644 (file)
--- a/usage.c
+++ b/usage.c
va_end(params);
}
+void die_errno(const char *fmt, ...)
+{
+ va_list params;
+ char fmt_with_err[1024];
+ char str_error[256], *err;
+ int i, j;
+
+ err = strerror(errno);
+ for (i = j = 0; err[i] && j < sizeof(str_error) - 1; ) {
+ if ((str_error[j++] = err[i++]) != '%')
+ continue;
+ if (j < sizeof(str_error) - 1) {
+ str_error[j++] = '%';
+ } else {
+ /* No room to double the '%', so we overwrite it with
+ * '\0' below */
+ j--;
+ break;
+ }
+ }
+ str_error[j] = 0;
+ snprintf(fmt_with_err, sizeof(fmt_with_err), "%s: %s", fmt, str_error);
+
+ va_start(params, fmt);
+ die_routine(fmt_with_err, params);
+ va_end(params);
+}
+
int error(const char *err, ...)
{
va_list params;
diff --git a/wrapper.c b/wrapper.c
index 7eb3218ee995991881252e4bb599452d7214ae4f..c9be1400c005e25b003acecc0cb037dd2f07e56f 100644 (file)
--- a/wrapper.c
+++ b/wrapper.c
release_pack_memory(length, fd);
ret = mmap(start, length, prot, flags, fd, offset);
if (ret == MAP_FAILED)
- die("Out of memory? mmap failed: %s", strerror(errno));
+ die_errno("Out of memory? mmap failed");
}
return ret;
}
{
int ret = dup(fd);
if (ret < 0)
- die("dup failed: %s", strerror(errno));
+ die_errno("dup failed");
return ret;
}
{
FILE *stream = fdopen(fd, mode);
if (stream == NULL)
- die("Out of memory? fdopen failed: %s", strerror(errno));
+ die_errno("Out of memory? fdopen failed");
return stream;
}
fd = mkstemp(template);
if (fd < 0)
- die("Unable to create temporary file: %s", strerror(errno));
+ die_errno("Unable to create temporary file");
return fd;
}
diff --git a/write_or_die.c b/write_or_die.c
index 4c29255df1b637f93ab3d59e0dcab1fa3b40e10b..d45b536021e15c5a674f7969be39f238194bef99 100644 (file)
--- a/write_or_die.c
+++ b/write_or_die.c
*/
if (errno == EPIPE || errno == EINVAL)
exit(0);
- die("write failure on %s: %s", desc, strerror(errno));
+ die_errno("write failure on '%s'", desc);
}
}
void fsync_or_die(int fd, const char *msg)
{
if (fsync(fd) < 0) {
- die("%s: fsync error (%s)", msg, strerror(errno));
+ die_errno("fsync error on '%s'", msg);
}
}
if (write_in_full(fd, buf, count) < 0) {
if (errno == EPIPE)
exit(0);
- die("write error (%s)", strerror(errno));
+ die_errno("write error");
}
}
diff --git a/xdiff-interface.c b/xdiff-interface.c
index b9b0db8d86615d6ca1046b932772f3d9750a8062..01f14fb50f7cf1387898a0c8db44f966ce07b720 100644 (file)
--- a/xdiff-interface.c
+++ b/xdiff-interface.c
}
}
+void xdiff_clear_find_func(xdemitconf_t *xecfg)
+{
+ if (xecfg->find_func) {
+ int i;
+ struct ff_regs *regs = xecfg->find_func_priv;
+
+ for (i = 0; i < regs->nr; i++)
+ regfree(®s->array[i].re);
+ free(regs->array);
+ free(regs);
+ xecfg->find_func = NULL;
+ xecfg->find_func_priv = NULL;
+ }
+}
+
int git_xmerge_style = -1;
int git_xmerge_config(const char *var, const char *value, void *cb)
diff --git a/xdiff-interface.h b/xdiff-interface.h
index 7352b9a9c204c2b1d4ca9df5ce040fe22d6f521c..55572c39a10dee336355f816b324946fc087d6e7 100644 (file)
--- a/xdiff-interface.h
+++ b/xdiff-interface.h
int buffer_is_binary(const char *ptr, unsigned long size);
extern void xdiff_set_find_func(xdemitconf_t *xecfg, const char *line, int cflags);
+extern void xdiff_clear_find_func(xdemitconf_t *xecfg);
extern int git_xmerge_config(const char *var, const char *value, void *cb);
extern int git_xmerge_style;