mirror of
https://github.com/git/git.git
synced 2026-04-02 04:50:12 +02:00
Merge commit '0a17b2cd7ebc0beeab6121d96ce812f22994cc39' into msysgit/devel
Conflicts: Makefile compat/mingw.c
This commit is contained in:
93
Documentation/RelNotes-1.6.4.txt
Normal file
93
Documentation/RelNotes-1.6.4.txt
Normal file
@@ -0,0 +1,93 @@
|
||||
GIT v1.6.4 Release Notes
|
||||
========================
|
||||
|
||||
With the next major release, "git push" into a branch that is
|
||||
currently checked out will be refused by default. You can choose
|
||||
what should happen upon such a push by setting the configuration
|
||||
variable receive.denyCurrentBranch in the receiving repository.
|
||||
|
||||
To ease the transition plan, the receiving repository of such a
|
||||
push running this release will issue a big warning when the
|
||||
configuration variable is missing. Please refer to:
|
||||
|
||||
http://git.or.cz/gitwiki/GitFaq#non-bare
|
||||
http://thread.gmane.org/gmane.comp.version-control.git/107758/focus=108007
|
||||
|
||||
for more details on the reason why this change is needed and the
|
||||
transition plan.
|
||||
|
||||
For a similar reason, "git push $there :$killed" to delete the branch
|
||||
$killed in a remote repository $there, if $killed branch is the current
|
||||
branch pointed at by its HEAD, gets a large warning. You can choose what
|
||||
should happen upon such a push by setting the configuration variable
|
||||
receive.denyDeleteCurrent in the receiving repository.
|
||||
|
||||
When the user does not tell "git push" what to push, it has always
|
||||
pushed matching refs. For some people it is unexpected, and a new
|
||||
configuration variable push.default has been introduced to allow
|
||||
changing a different default behaviour. To advertise the new feature,
|
||||
a big warning is issued if this is not configured and a git push without
|
||||
arguments is attempted.
|
||||
|
||||
|
||||
Updates since v1.6.3
|
||||
--------------------
|
||||
|
||||
(subsystems)
|
||||
|
||||
* gitweb Perl style clean-up.
|
||||
|
||||
* git-svn updates, including a new --authors-prog option to map author
|
||||
names by invoking an external program.
|
||||
|
||||
(portability)
|
||||
|
||||
* We feed iconv with "UTF-8" instead of "utf8"; the former is
|
||||
understood more widely.
|
||||
|
||||
(performance)
|
||||
|
||||
(usability, bells and whistles)
|
||||
|
||||
* "git add --edit" lets users edit the whole patch text to fine-tune what
|
||||
is added to the index.
|
||||
|
||||
* "git log --graph" draws graphs more compactly by using horizonal lines
|
||||
when able.
|
||||
|
||||
* "git log --decorate" shows shorter refnames by stripping well-known
|
||||
refs/* prefix.
|
||||
|
||||
* "git send-email" understands quoted aliases in .mailrc files (might
|
||||
have to be backported to 1.6.3.X).
|
||||
|
||||
* "git send-email" can fetch the sender address from the configuration
|
||||
variable "sendmail.from" (and "sendmail.<identity>.from").
|
||||
|
||||
* "git show-branch" can color its output.
|
||||
|
||||
* "add" and "update" subcommands to "git submodule" learned --reference
|
||||
option to use local clone with references.
|
||||
|
||||
(developers)
|
||||
|
||||
* A major part of the "git bisect" wrapper has moved to C.
|
||||
|
||||
Fixes since v1.6.3
|
||||
------------------
|
||||
|
||||
All of the fixes in v1.6.3.X maintenance series are included in this
|
||||
release, unless otherwise noted.
|
||||
|
||||
Here are fixes that this release has, but have not been backported to
|
||||
v1.6.3.X series.
|
||||
|
||||
* The way Git.pm sets up a Repository object was not friendly to callers
|
||||
that chdir around. It now internally records the repository location
|
||||
as an absolute path when autodetected.
|
||||
|
||||
---
|
||||
exec >/var/tmp/1
|
||||
echo O=$(git describe master)
|
||||
O=v1.6.3.1-168-g23807fa
|
||||
git shortlog --no-merges $O..master ^maint
|
||||
@@ -438,6 +438,11 @@ On some file system/operating system combinations, this is unreliable.
|
||||
Set this config setting to 'rename' there; However, This will remove the
|
||||
check that makes sure that existing object files will not get overwritten.
|
||||
|
||||
add.ignore-errors::
|
||||
Tells 'git-add' to continue adding files when some files cannot be
|
||||
added due to indexing errors. Equivalent to the '--ignore-errors'
|
||||
option of linkgit:git-add[1].
|
||||
|
||||
alias.*::
|
||||
Command aliases for the linkgit:git[1] command wrapper - e.g.
|
||||
after defining "alias.last = cat-file commit HEAD", the invocation
|
||||
@@ -604,6 +609,12 @@ color.pager::
|
||||
A boolean to enable/disable colored output when the pager is in
|
||||
use (default is true).
|
||||
|
||||
color.showbranch::
|
||||
A boolean to enable/disable color in the output of
|
||||
linkgit:git-show-branch[1]. May be set to `always`,
|
||||
`false` (or `never`) or `auto` (or `true`), in which case colors are used
|
||||
only when the output is to a terminal. Defaults to false.
|
||||
|
||||
color.status::
|
||||
A boolean to enable/disable color in the output of
|
||||
linkgit:git-status[1]. May be set to `always`,
|
||||
|
||||
@@ -9,7 +9,7 @@ SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git add' [-n] [-v] [--force | -f] [--interactive | -i] [--patch | -p]
|
||||
[--all | [--update | -u]] [--intent-to-add | -N]
|
||||
[--edit | -e] [--all | [--update | -u]] [--intent-to-add | -N]
|
||||
[--refresh] [--ignore-errors] [--] <filepattern>...
|
||||
|
||||
DESCRIPTION
|
||||
@@ -76,6 +76,15 @@ OPTIONS
|
||||
bypassed and the 'patch' subcommand is invoked using each of
|
||||
the specified filepatterns before exiting.
|
||||
|
||||
-e, \--edit::
|
||||
Open the diff vs. the index in an editor and let the user
|
||||
edit it. After the editor was closed, adjust the hunk headers
|
||||
and apply the patch to the index.
|
||||
+
|
||||
*NOTE*: Obviously, if you change anything else than the first character
|
||||
on lines beginning with a space or a minus, the patch will no longer
|
||||
apply.
|
||||
|
||||
-u::
|
||||
--update::
|
||||
Update only files that git already knows about, staging modified
|
||||
|
||||
@@ -3,7 +3,7 @@ git-apply(1)
|
||||
|
||||
NAME
|
||||
----
|
||||
git-apply - Apply a patch on a git index file and a working tree
|
||||
git-apply - Apply a patch on a git index file and/or a working tree
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
@@ -111,6 +111,7 @@ OPTIONS
|
||||
--no-abbrev::
|
||||
Display the full sha1s in the output listing rather than abbreviating them.
|
||||
|
||||
-t::
|
||||
--track::
|
||||
When creating a new branch, set up configuration to mark the
|
||||
start-point branch as "upstream" from the new branch. This
|
||||
|
||||
@@ -25,6 +25,10 @@ imposes the following rules on how references are named:
|
||||
grouping, but no slash-separated component can begin with a
|
||||
dot `.`.
|
||||
|
||||
. They must contain at least one `/`. This enforces the presence of a
|
||||
category like `heads/`, `tags/` etc. but the actual names are not
|
||||
restricted.
|
||||
|
||||
. They cannot have two consecutive dots `..` anywhere.
|
||||
|
||||
. They cannot have ASCII control characters (i.e. bytes whose
|
||||
@@ -38,6 +42,8 @@ imposes the following rules on how references are named:
|
||||
|
||||
. They cannot contain a sequence `@{`.
|
||||
|
||||
- They cannot contain a `\\`.
|
||||
|
||||
These rules make it easy for shell script based tools to parse
|
||||
reference names, pathname expansion by the shell when a reference name is used
|
||||
unquoted (by mistake), and also avoids ambiguities in certain
|
||||
|
||||
@@ -31,7 +31,7 @@ OPTIONS
|
||||
Use the diff tool specified by <tool>.
|
||||
Valid merge tools are:
|
||||
kdiff3, kompare, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff,
|
||||
ecmerge, diffuse and opendiff
|
||||
ecmerge, diffuse, opendiff and araxis.
|
||||
+
|
||||
If a diff tool is not specified, 'git-difftool'
|
||||
will use the configuration variable `diff.tool`. If the
|
||||
|
||||
@@ -27,7 +27,7 @@ OPTIONS
|
||||
Use the merge resolution program specified by <tool>.
|
||||
Valid merge tools are:
|
||||
kdiff3, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff, ecmerge,
|
||||
diffuse, tortoisemerge and opendiff
|
||||
diffuse, tortoisemerge, opendiff and araxis.
|
||||
+
|
||||
If a merge resolution program is not specified, 'git-mergetool'
|
||||
will use the configuration variable `merge.tool`. If the
|
||||
|
||||
@@ -8,12 +8,13 @@ git-mktree - Build a tree-object from ls-tree formatted text
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git mktree' [-z]
|
||||
'git mktree' [-z] [--missing] [--batch]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Reads standard input in non-recursive `ls-tree` output format,
|
||||
and creates a tree object. The object name of the tree object
|
||||
Reads standard input in non-recursive `ls-tree` output format, and creates
|
||||
a tree object. The order of the tree entries is normalised by mktree so
|
||||
pre-sorting the input is not required. The object name of the tree object
|
||||
built is written to the standard output.
|
||||
|
||||
OPTIONS
|
||||
@@ -21,6 +22,18 @@ OPTIONS
|
||||
-z::
|
||||
Read the NUL-terminated `ls-tree -z` output instead.
|
||||
|
||||
--missing::
|
||||
Allow missing objects. The default behaviour (without this option)
|
||||
is to verify that each tree entry's sha1 identifies an existing
|
||||
object. This option has no effect on the treatment of gitlink entries
|
||||
(aka "submodules") which are always allowed to be missing.
|
||||
|
||||
--batch::
|
||||
Allow building of more than one tree object before exiting. Each
|
||||
tree is separated by as single blank line. The final new-line is
|
||||
optional. Note - if the '-z' option is used, lines are terminated
|
||||
with NUL.
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Junio C Hamano <gitster@pobox.com>
|
||||
|
||||
@@ -231,8 +231,7 @@ OPTIONS
|
||||
|
||||
-s <strategy>::
|
||||
--strategy=<strategy>::
|
||||
Use the given merge strategy; can be supplied more than
|
||||
once to specify them in the order they should be tried.
|
||||
Use the given merge strategy.
|
||||
If there is no `-s` option, a built-in list of strategies
|
||||
is used instead ('git-merge-recursive' when merging a single
|
||||
head, 'git-merge-octopus' otherwise). This implies --merge.
|
||||
|
||||
@@ -31,11 +31,14 @@ OPTIONS
|
||||
Instead of incrementally packing the unpacked objects,
|
||||
pack everything referenced into a single pack.
|
||||
Especially useful when packing a repository that is used
|
||||
for private development and there is no need to worry
|
||||
about people fetching via dumb protocols from it. Use
|
||||
for private development. Use
|
||||
with '-d'. This will clean up the objects that `git prune`
|
||||
leaves behind, but `git fsck --full` shows as
|
||||
dangling.
|
||||
+
|
||||
Note that users fetching over dumb protocols will have to fetch the
|
||||
whole new pack in order to get any contained object, no matter how many
|
||||
other objects in that pack they already have locally.
|
||||
|
||||
-A::
|
||||
Same as `-a`, unless '-d' is used. Then any unreachable
|
||||
|
||||
@@ -30,6 +30,11 @@ OPTIONS
|
||||
Only meaningful in `--parseopt` mode. Tells the option parser to echo
|
||||
out the first `--` met instead of skipping it.
|
||||
|
||||
--sq-quote::
|
||||
Use 'git-rev-parse' in shell quoting mode (see SQ-QUOTE
|
||||
section below). In contrast to the `--sq` option below, this
|
||||
mode does only quoting. Nothing else is done to command input.
|
||||
|
||||
--revs-only::
|
||||
Do not output flags and parameters not meant for
|
||||
'git-rev-list' command.
|
||||
@@ -64,7 +69,8 @@ OPTIONS
|
||||
properly quoted for consumption by shell. Useful when
|
||||
you expect your parameter to contain whitespaces and
|
||||
newlines (e.g. when using pickaxe `-S` with
|
||||
'git-diff-\*').
|
||||
'git-diff-\*'). In contrast to the `--sq-quote` option,
|
||||
the command input is still interpreted as usual.
|
||||
|
||||
--not::
|
||||
When showing object names, prefix them with '{caret}' and
|
||||
@@ -406,6 +412,33 @@ C? option C with an optional argument"
|
||||
eval `echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?`
|
||||
------------
|
||||
|
||||
SQ-QUOTE
|
||||
--------
|
||||
|
||||
In `--sq-quote` mode, 'git-rev-parse' echoes on the standard output a
|
||||
single line suitable for `sh(1)` `eval`. This line is made by
|
||||
normalizing the arguments following `--sq-quote`. Nothing other than
|
||||
quoting the arguments is done.
|
||||
|
||||
If you want command input to still be interpreted as usual by
|
||||
'git-rev-parse' before the output is shell quoted, see the `--sq`
|
||||
option.
|
||||
|
||||
Example
|
||||
~~~~~~~
|
||||
|
||||
------------
|
||||
$ cat >your-git-script.sh <<\EOF
|
||||
#!/bin/sh
|
||||
args=$(git rev-parse --sq-quote "$@") # quote user-supplied arguments
|
||||
command="git frotz -n24 $args" # and use it inside a handcrafted
|
||||
# command line
|
||||
eval "$command"
|
||||
EOF
|
||||
|
||||
$ sh your-git-script.sh "a b'c"
|
||||
------------
|
||||
|
||||
EXAMPLES
|
||||
--------
|
||||
|
||||
|
||||
@@ -14,6 +14,10 @@ SYNOPSIS
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Takes the patches given on the command line and emails them out.
|
||||
Patches can be specified as files, directories (which will send all
|
||||
files in the directory), or directly as a revision list. In the
|
||||
last case, any format accepted by linkgit:git-format-patch[1] can
|
||||
be passed to git send-email.
|
||||
|
||||
The header of the email is configurable by command line options. If not
|
||||
specified on the command line, the user will be prompted with a ReadLine
|
||||
@@ -39,6 +43,10 @@ OPTIONS
|
||||
Composing
|
||||
~~~~~~~~~
|
||||
|
||||
--annotate::
|
||||
Review and edit each patch you're about to send. See the
|
||||
CONFIGURATION section for 'sendemail.multiedit'.
|
||||
|
||||
--bcc=<address>::
|
||||
Specify a "Bcc:" value for each email. Default is the value of
|
||||
'sendemail.bcc'.
|
||||
@@ -51,11 +59,6 @@ The --bcc option must be repeated for each user you want on the bcc list.
|
||||
+
|
||||
The --cc option must be repeated for each user you want on the cc list.
|
||||
|
||||
--annotate::
|
||||
Review each patch you're about to send in an editor. The setting
|
||||
'sendemail.multiedit' defines if this will spawn one editor per patch
|
||||
or one for all of them at once.
|
||||
|
||||
--compose::
|
||||
Use $GIT_EDITOR, core.editor, $VISUAL, or $EDITOR to edit an
|
||||
introductory message for the patch series.
|
||||
@@ -67,11 +70,16 @@ In-Reply-To headers specified in the message. If the body of the message
|
||||
and In-Reply-To headers will be used unless they are removed.
|
||||
+
|
||||
Missing From or In-Reply-To headers will be prompted for.
|
||||
+
|
||||
See the CONFIGURATION section for 'sendemail.multiedit'.
|
||||
|
||||
--from=<address>::
|
||||
Specify the sender of the emails. This will default to
|
||||
the value GIT_COMMITTER_IDENT, as returned by "git var -l".
|
||||
The user will still be prompted to confirm this entry.
|
||||
Specify the sender of the emails. If not specified on the command line,
|
||||
the value of the 'sendemail.from' configuration option is used. If
|
||||
neither the command line option nor 'sendemail.from' are set, then the
|
||||
user will be prompted for the value. The default for the prompt will be
|
||||
the value of GIT_AUTHOR_IDENT, or GIT_COMMITTER_IDENT if that is not
|
||||
set, as returned by "git var -l".
|
||||
|
||||
--in-reply-to=<identifier>::
|
||||
Specify the contents of the first In-Reply-To header.
|
||||
@@ -135,7 +143,9 @@ user is prompted for a password while the input is masked for privacy.
|
||||
--smtp-server-port=<port>::
|
||||
Specifies a port different from the default port (SMTP
|
||||
servers typically listen to smtp port 25 and ssmtp port
|
||||
465). This can be set with 'sendemail.smtpserverport'.
|
||||
465); symbolic port names (e.g. "submission" instead of 465)
|
||||
are also accepted. The port can also be set with the
|
||||
'sendemail.smtpserverport' configuration variable.
|
||||
|
||||
--smtp-ssl::
|
||||
Legacy alias for '--smtp-encryption ssl'.
|
||||
@@ -230,6 +240,12 @@ have been specified, in which case default to 'compose'.
|
||||
--dry-run::
|
||||
Do everything except actually send the emails.
|
||||
|
||||
--[no-]format-patch::
|
||||
When an argument may be understood either as a reference or as a file name,
|
||||
choose to understand it as a format-patch argument ('--format-patch')
|
||||
or as a file name ('--no-format-patch'). By default, when such a conflict
|
||||
occurs, git send-email will fail.
|
||||
|
||||
--quiet::
|
||||
Make git-send-email less verbose. One line per email should be
|
||||
all that is output.
|
||||
@@ -246,12 +262,6 @@ have been specified, in which case default to 'compose'.
|
||||
Default is the value of 'sendemail.validate'; if this is not set,
|
||||
default to '--validate'.
|
||||
|
||||
--[no-]format-patch::
|
||||
When an argument may be understood either as a reference or as a file name,
|
||||
choose to understand it as a format-patch argument ('--format-patch')
|
||||
or as a file name ('--no-format-patch'). By default, when such a conflict
|
||||
occurs, git send-email will fail.
|
||||
|
||||
|
||||
CONFIGURATION
|
||||
-------------
|
||||
|
||||
@@ -8,9 +8,11 @@ git-show-branch - Show branches and their commits
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git show-branch' [--all] [--remotes] [--topo-order] [--current]
|
||||
'git show-branch' [--all] [--remotes] [--topo-order | --date-order]
|
||||
[--current] [--color | --no-color]
|
||||
[--more=<n> | --list | --independent | --merge-base]
|
||||
[--no-name | --sha1-name] [--topics] [<rev> | <glob>]...
|
||||
[--no-name | --sha1-name] [--topics]
|
||||
[<rev> | <glob>]...
|
||||
'git show-branch' (-g|--reflog)[=<n>[,<base>]] [--list] [<ref>]
|
||||
|
||||
DESCRIPTION
|
||||
@@ -57,6 +59,11 @@ OPTIONS
|
||||
appear in topological order (i.e., descendant commits
|
||||
are shown before their parents).
|
||||
|
||||
--date-order::
|
||||
This option is similar to '--topo-order' in the sense that no
|
||||
parent comes before all of its children, but otherwise commits
|
||||
are ordered according to their commit date.
|
||||
|
||||
--sparse::
|
||||
By default, the output omits merges that are reachable
|
||||
from only one tip being shown. This option makes them
|
||||
@@ -107,6 +114,14 @@ OPTIONS
|
||||
When no explicit <ref> parameter is given, it defaults to the
|
||||
current branch (or `HEAD` if it is detached).
|
||||
|
||||
--color::
|
||||
Color the status sign (one of these: `*` `!` `+` `-`) of each commit
|
||||
corresponding to the branch it's in.
|
||||
|
||||
--no-color::
|
||||
Turn off colored output, even when the configuration file gives the
|
||||
default to color output.
|
||||
|
||||
Note that --more, --list, --independent and --merge-base options
|
||||
are mutually exclusive.
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git stash' list [<options>]
|
||||
'git stash' (show | drop | pop ) [<stash>]
|
||||
'git stash' apply [--index] [<stash>]
|
||||
'git stash' ( show | drop ) [<stash>]
|
||||
'git stash' ( pop | apply ) [--index] [<stash>]
|
||||
'git stash' branch <branchname> [<stash>]
|
||||
'git stash' [save [--keep-index] [<message>]]
|
||||
'git stash' clear
|
||||
@@ -86,16 +86,16 @@ Applying the state can fail with conflicts; in this case, it is not
|
||||
removed from the stash list. You need to resolve the conflicts by hand
|
||||
and call `git stash drop` manually afterwards.
|
||||
+
|
||||
When no `<stash>` is given, `stash@\{0}` is assumed. See also `apply`.
|
||||
|
||||
apply [--index] [<stash>]::
|
||||
|
||||
Like `pop`, but do not remove the state from the stash list.
|
||||
+
|
||||
If the `--index` option is used, then tries to reinstate not only the working
|
||||
tree's changes, but also the index's ones. However, this can fail, when you
|
||||
have conflicts (which are stored in the index, where you therefore can no
|
||||
longer apply the changes as they were originally).
|
||||
+
|
||||
When no `<stash>` is given, `stash@\{0}` is assumed.
|
||||
|
||||
apply [--index] [<stash>]::
|
||||
|
||||
Like `pop`, but do not remove the state from the stash list.
|
||||
|
||||
branch <branchname> [<stash>]::
|
||||
|
||||
|
||||
@@ -9,10 +9,12 @@ git-submodule - Initialize, update or inspect submodules
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git submodule' [--quiet] add [-b branch] [--] <repository> <path>
|
||||
'git submodule' [--quiet] add [-b branch]
|
||||
[--reference <repository>] [--] <repository> <path>
|
||||
'git submodule' [--quiet] status [--cached] [--] [<path>...]
|
||||
'git submodule' [--quiet] init [--] [<path>...]
|
||||
'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--] [<path>...]
|
||||
'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--rebase]
|
||||
[--reference <repository>] [--] [<path>...]
|
||||
'git submodule' [--quiet] summary [--summary-limit <n>] [commit] [--] [<path>...]
|
||||
'git submodule' [--quiet] foreach <command>
|
||||
'git submodule' [--quiet] sync [--] [<path>...]
|
||||
@@ -113,7 +115,8 @@ init::
|
||||
update::
|
||||
Update the registered submodules, i.e. clone missing submodules and
|
||||
checkout the commit specified in the index of the containing repository.
|
||||
This will make the submodules HEAD be detached.
|
||||
This will make the submodules HEAD be detached unless '--rebase' is
|
||||
specified or the key `submodule.$name.update` is set to `rebase`.
|
||||
+
|
||||
If the submodule is not yet initialized, and you just want to use the
|
||||
setting as stored in .gitmodules, you can automatically initialize the
|
||||
@@ -177,6 +180,23 @@ OPTIONS
|
||||
This option is only valid for the update command.
|
||||
Don't fetch new objects from the remote site.
|
||||
|
||||
--rebase::
|
||||
This option is only valid for the update command.
|
||||
Rebase the current branch onto the commit recorded in the
|
||||
superproject. If this option is given, the submodule's HEAD will not
|
||||
be detached. If a a merge failure prevents this process, you will have
|
||||
to resolve these failures with linkgit:git-rebase[1].
|
||||
If the key `submodule.$name.update` is set to `rebase`, this option is
|
||||
implicit.
|
||||
|
||||
--reference <repository>::
|
||||
This option is only valid for add and update commands. These
|
||||
commands sometimes need to clone a remote repository. In this case,
|
||||
this option will be passed to the linkgit:git-clone[1] command.
|
||||
+
|
||||
*NOTE*: Do *not* use this option unless you have read the note
|
||||
for linkgit:git-clone[1]'s --reference and --shared options carefully.
|
||||
|
||||
<path>...::
|
||||
Paths to submodule(s). When specified this will restrict the command
|
||||
to only operate on the submodules found at the specified paths.
|
||||
|
||||
@@ -398,6 +398,14 @@ after the authors-file is modified should continue operation.
|
||||
|
||||
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.
|
||||
|
||||
-q::
|
||||
--quiet::
|
||||
Make 'git-svn' less verbose. Specify a second time to make it
|
||||
|
||||
@@ -43,7 +43,12 @@ unreleased) version of git, that is available from 'master'
|
||||
branch of the `git.git` repository.
|
||||
Documentation for older releases are available here:
|
||||
|
||||
* link:v1.6.3/git.html[documentation for release 1.6.3]
|
||||
* link:v1.6.3.2/git.html[documentation for release 1.6.3.2]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes-1.6.3.2.txt[1.6.3.2],
|
||||
link:RelNotes-1.6.3.1.txt[1.6.3.1],
|
||||
link:RelNotes-1.6.3.txt[1.6.3].
|
||||
|
||||
* release notes for
|
||||
link:RelNotes-1.6.2.5.txt[1.6.2.5],
|
||||
@@ -227,6 +232,8 @@ The link:user-manual.html#git-concepts[git concepts chapter of the
|
||||
user-manual] and linkgit:gitcore-tutorial[7] both provide
|
||||
introductions to the underlying git architecture.
|
||||
|
||||
See linkgit:gitworkflows[7] for an overview of recommended workflows.
|
||||
|
||||
See also the link:howto-index.html[howto] documents for some useful
|
||||
examples.
|
||||
|
||||
@@ -644,7 +651,8 @@ SEE ALSO
|
||||
linkgit:gittutorial[7], linkgit:gittutorial-2[7],
|
||||
link:everyday.html[Everyday Git], linkgit:gitcvs-migration[7],
|
||||
linkgit:gitglossary[7], linkgit:gitcore-tutorial[7],
|
||||
linkgit:gitcli[7], link:user-manual.html[The Git User's Manual]
|
||||
linkgit:gitcli[7], link:user-manual.html[The Git User's Manual],
|
||||
linkgit:gitworkflows[7]
|
||||
|
||||
GIT
|
||||
---
|
||||
|
||||
@@ -30,6 +30,15 @@ submodule.<name>.path::
|
||||
submodule.<name>.url::
|
||||
Defines an url from where the submodule repository can be cloned.
|
||||
|
||||
submodule.<name>.update::
|
||||
Defines what to do when the submodule is updated by the superproject.
|
||||
If 'checkout' (the default), the new commit specified in the
|
||||
superproject will be checked out in the submodule on a detached HEAD.
|
||||
If 'rebase', the current branch of the submodule will be rebased onto
|
||||
the commit specified in the superproject.
|
||||
This config option is overridden if 'git submodule update' is given
|
||||
the '--rebase' option.
|
||||
|
||||
|
||||
EXAMPLES
|
||||
--------
|
||||
|
||||
@@ -650,6 +650,9 @@ digressions that may be interesting at this point are:
|
||||
smart enough to perform a close-to-optimal search even in the
|
||||
case of complex non-linear history with lots of merged branches.
|
||||
|
||||
* linkgit:gitworkflows[7]: Gives an overview of recommended
|
||||
workflows.
|
||||
|
||||
* link:everyday.html[Everyday GIT with 20 Commands Or So]
|
||||
|
||||
* linkgit:gitcvs-migration[7]: Git for CVS users.
|
||||
@@ -661,6 +664,7 @@ linkgit:gitcvs-migration[7],
|
||||
linkgit:gitcore-tutorial[7],
|
||||
linkgit:gitglossary[7],
|
||||
linkgit:git-help[1],
|
||||
linkgit:gitworkflows[7],
|
||||
link:everyday.html[Everyday git],
|
||||
link:user-manual.html[The Git User's Manual]
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ merge.tool::
|
||||
Controls which merge resolution program is used by
|
||||
linkgit:git-mergetool[1]. Valid built-in values are: "kdiff3",
|
||||
"tkdiff", "meld", "xxdiff", "emerge", "vimdiff", "gvimdiff",
|
||||
"diffuse", "ecmerge", "tortoisemerge", and
|
||||
"diffuse", "ecmerge", "tortoisemerge", "araxis", and
|
||||
"opendiff". Any other value is treated is custom merge tool
|
||||
and there must be a corresponding mergetool.<tool>.cmd option.
|
||||
|
||||
|
||||
@@ -60,13 +60,13 @@ Steps to parse options
|
||||
. in `cmd_foo(int argc, const char **argv, const char *prefix)`
|
||||
call
|
||||
|
||||
argc = parse_options(argc, argv, builtin_foo_options, builtin_foo_usage, flags);
|
||||
argc = parse_options(argc, argv, prefix, builtin_foo_options, builtin_foo_usage, flags);
|
||||
+
|
||||
`parse_options()` will filter out the processed options of `argv[]` and leave the
|
||||
non-option arguments in `argv[]`.
|
||||
`argc` is updated appropriately because of the assignment.
|
||||
+
|
||||
You can also pass NULL instead of a usage array as fourth parameter of
|
||||
You can also pass NULL instead of a usage array as the fifth parameter of
|
||||
parse_options(), to avoid displaying a help screen with usage info and
|
||||
option list. This should only be done if necessary, e.g. to implement
|
||||
a limited parser for only a subset of the options that needs to be run
|
||||
@@ -137,6 +137,10 @@ There are some macros to easily define options:
|
||||
Introduce a boolean option.
|
||||
If used, `int_var` is bitwise-ored with `mask`.
|
||||
|
||||
`OPT_NEGBIT(short, long, &int_var, description, mask)`::
|
||||
Introduce a boolean option.
|
||||
If used, `int_var` is bitwise-anded with the inverted `mask`.
|
||||
|
||||
`OPT_SET_INT(short, long, &int_var, description, integer)`::
|
||||
Introduce a boolean option.
|
||||
If used, set `int_var` to `integer`.
|
||||
@@ -163,9 +167,22 @@ There are some macros to easily define options:
|
||||
and the result will be put into `var`.
|
||||
See 'Option Callbacks' below for a more elaborate description.
|
||||
|
||||
`OPT_FILENAME(short, long, &var, description)`::
|
||||
Introduce an option with a filename argument.
|
||||
The filename will be prefixed by passing the filename along with
|
||||
the prefix argument of `parse_options()` to `prefix_filename()`.
|
||||
|
||||
`OPT_ARGUMENT(long, description)`::
|
||||
Introduce a long-option argument that will be kept in `argv[]`.
|
||||
|
||||
`OPT_NUMBER_CALLBACK(&var, description, func_ptr)`::
|
||||
Recognize numerical options like -123 and feed the integer as
|
||||
if it was an argument to the function given by `func_ptr`.
|
||||
The result will be put into `var`. There can be only one such
|
||||
option definition. It cannot be negated and it takes no
|
||||
arguments. Short options that happen to be digits take
|
||||
precedence over it.
|
||||
|
||||
|
||||
The last element of the array must be `OPT_END()`.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
GVF=GIT-VERSION-FILE
|
||||
DEF_VER=v1.6.3.2
|
||||
DEF_VER=v1.6.3.GIT
|
||||
|
||||
LF='
|
||||
'
|
||||
|
||||
73
Makefile
73
Makefile
@@ -3,6 +3,11 @@ all::
|
||||
|
||||
# Define V=1 to have a more verbose compile.
|
||||
#
|
||||
# Define SHELL_PATH to a POSIX shell if your /bin/sh is broken.
|
||||
#
|
||||
# Define SANE_TOOL_PATH to a colon-separated list of paths to prepend
|
||||
# to PATH if your tools in /usr/bin are broken.
|
||||
#
|
||||
# Define SNPRINTF_RETURNS_BOGUS if your are on a system which snprintf()
|
||||
# or vsnprintf() return -1 instead of number of characters which would
|
||||
# have been written to the final string if enough space had been available.
|
||||
@@ -52,6 +57,10 @@ all::
|
||||
#
|
||||
# Define NO_MKDTEMP if you don't have mkdtemp in the C library.
|
||||
#
|
||||
# Define NO_MKSTEMPS if you don't have mkstemps in the C library.
|
||||
#
|
||||
# Define NO_LIBGEN_H if you don't have libgen.h.
|
||||
#
|
||||
# Define NO_SYS_SELECT_H if you don't have sys/select.h.
|
||||
#
|
||||
# Define NO_SYMLINK_HEAD if you never want .git/HEAD to be a symbolic link.
|
||||
@@ -91,6 +100,10 @@ all::
|
||||
# Define NEEDS_SOCKET if linking with libc is not enough (SunOS,
|
||||
# Patrick Mauritz).
|
||||
#
|
||||
# Define NEEDS_RESOLV if linking with -lnsl and/or -lsocket is not enough.
|
||||
# Notably on Solaris hstrerror resides in libresolv and on Solaris 7
|
||||
# inet_ntop and inet_pton additionally reside there.
|
||||
#
|
||||
# Define NO_MMAP if you want to avoid mmap.
|
||||
#
|
||||
# Define NO_PTHREADS if you do not have or do not want to use Pthreads.
|
||||
@@ -339,7 +352,6 @@ PROGRAMS += git-index-pack$X
|
||||
PROGRAMS += git-merge-index$X
|
||||
PROGRAMS += git-merge-tree$X
|
||||
PROGRAMS += git-mktag$X
|
||||
PROGRAMS += git-mktree$X
|
||||
PROGRAMS += git-pack-redundant$X
|
||||
PROGRAMS += git-patch-id$X
|
||||
PROGRAMS += git-shell$X
|
||||
@@ -593,6 +605,7 @@ BUILTIN_OBJS += builtin-merge-base.o
|
||||
BUILTIN_OBJS += builtin-merge-file.o
|
||||
BUILTIN_OBJS += builtin-merge-ours.o
|
||||
BUILTIN_OBJS += builtin-merge-recursive.o
|
||||
BUILTIN_OBJS += builtin-mktree.o
|
||||
BUILTIN_OBJS += builtin-mv.o
|
||||
BUILTIN_OBJS += builtin-name-rev.o
|
||||
BUILTIN_OBJS += builtin-pack-objects.o
|
||||
@@ -639,10 +652,12 @@ EXTLIBS =
|
||||
|
||||
ifeq ($(uname_S),Linux)
|
||||
NO_STRLCPY = YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
THREADED_DELTA_SEARCH = YesPlease
|
||||
endif
|
||||
ifeq ($(uname_S),GNU/kFreeBSD)
|
||||
NO_STRLCPY = YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
THREADED_DELTA_SEARCH = YesPlease
|
||||
endif
|
||||
ifeq ($(uname_S),UnixWare)
|
||||
@@ -654,6 +669,7 @@ ifeq ($(uname_S),UnixWare)
|
||||
SHELL_PATH = /usr/local/bin/bash
|
||||
NO_IPV6 = YesPlease
|
||||
NO_HSTRERROR = YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
BASIC_CFLAGS += -Kthread
|
||||
BASIC_CFLAGS += -I/usr/local/include
|
||||
BASIC_LDFLAGS += -L/usr/local/lib
|
||||
@@ -677,6 +693,7 @@ ifeq ($(uname_S),SCO_SV)
|
||||
SHELL_PATH = /usr/bin/bash
|
||||
NO_IPV6 = YesPlease
|
||||
NO_HSTRERROR = YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
BASIC_CFLAGS += -I/usr/local/include
|
||||
BASIC_LDFLAGS += -L/usr/local/lib
|
||||
NO_STRCASESTR = YesPlease
|
||||
@@ -701,11 +718,21 @@ ifeq ($(uname_S),SunOS)
|
||||
NEEDS_SOCKET = YesPlease
|
||||
NEEDS_NSL = YesPlease
|
||||
SHELL_PATH = /bin/bash
|
||||
SANE_TOOL_PATH = /usr/xpg6/bin:/usr/xpg4/bin
|
||||
NO_STRCASESTR = YesPlease
|
||||
NO_MEMMEM = YesPlease
|
||||
NO_HSTRERROR = YesPlease
|
||||
NO_MKDTEMP = YesPlease
|
||||
OLD_ICONV = UnfortunatelyYes
|
||||
NO_MKSTEMPS = YesPlease
|
||||
ifeq ($(uname_R),5.7)
|
||||
NEEDS_RESOLV = YesPlease
|
||||
NO_IPV6 = YesPlease
|
||||
NO_SOCKADDR_STORAGE = YesPlease
|
||||
NO_UNSETENV = YesPlease
|
||||
NO_SETENV = YesPlease
|
||||
NO_STRLCPY = YesPlease
|
||||
NO_C99_FORMAT = YesPlease
|
||||
NO_STRTOUMAX = YesPlease
|
||||
endif
|
||||
ifeq ($(uname_R),5.8)
|
||||
NO_UNSETENV = YesPlease
|
||||
NO_SETENV = YesPlease
|
||||
@@ -718,15 +745,19 @@ ifeq ($(uname_S),SunOS)
|
||||
NO_C99_FORMAT = YesPlease
|
||||
NO_STRTOUMAX = YesPlease
|
||||
endif
|
||||
INSTALL = ginstall
|
||||
ifdef NO_IPV6
|
||||
NEEDS_RESOLV = YesPlease
|
||||
endif
|
||||
INSTALL = /usr/ucb/install
|
||||
TAR = gtar
|
||||
BASIC_CFLAGS += -D__EXTENSIONS__
|
||||
BASIC_CFLAGS += -D__EXTENSIONS__ -D__sun__
|
||||
endif
|
||||
ifeq ($(uname_O),Cygwin)
|
||||
NO_D_TYPE_IN_DIRENT = YesPlease
|
||||
NO_D_INO_IN_DIRENT = YesPlease
|
||||
NO_STRCASESTR = YesPlease
|
||||
NO_MEMMEM = YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
NO_SYMLINK_HEAD = YesPlease
|
||||
NEEDS_LIBICONV = YesPlease
|
||||
NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes
|
||||
@@ -770,11 +801,13 @@ ifeq ($(uname_S),NetBSD)
|
||||
BASIC_LDFLAGS += -L/usr/pkg/lib $(CC_LD_DYNPATH)/usr/pkg/lib
|
||||
THREADED_DELTA_SEARCH = YesPlease
|
||||
USE_ST_TIMESPEC = YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
endif
|
||||
ifeq ($(uname_S),AIX)
|
||||
NO_STRCASESTR=YesPlease
|
||||
NO_MEMMEM = YesPlease
|
||||
NO_MKDTEMP = YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
NO_STRLCPY = YesPlease
|
||||
NO_NSEC = YesPlease
|
||||
FREAD_READS_DIRECTORIES = UnfortunatelyYes
|
||||
@@ -790,12 +823,14 @@ endif
|
||||
ifeq ($(uname_S),GNU)
|
||||
# GNU/Hurd
|
||||
NO_STRLCPY=YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
endif
|
||||
ifeq ($(uname_S),IRIX64)
|
||||
NO_IPV6=YesPlease
|
||||
NO_SETENV=YesPlease
|
||||
NO_STRCASESTR=YesPlease
|
||||
NO_MEMMEM = YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
NO_STRLCPY = YesPlease
|
||||
NO_SOCKADDR_STORAGE=YesPlease
|
||||
SHELL_PATH=/usr/gnu/bin/bash
|
||||
@@ -808,6 +843,7 @@ ifeq ($(uname_S),HP-UX)
|
||||
NO_SETENV=YesPlease
|
||||
NO_STRCASESTR=YesPlease
|
||||
NO_MEMMEM = YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
NO_STRLCPY = YesPlease
|
||||
NO_MKDTEMP = YesPlease
|
||||
NO_UNSETENV = YesPlease
|
||||
@@ -823,6 +859,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
|
||||
pathsep = ;
|
||||
NO_PREAD = YesPlease
|
||||
NO_OPENSSL = YesPlease
|
||||
NO_LIBGEN_H = YesPlease
|
||||
NO_SYMLINK_HEAD = YesPlease
|
||||
NO_SETENV = YesPlease
|
||||
NO_UNSETENV = YesPlease
|
||||
@@ -834,6 +871,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
|
||||
NO_C99_FORMAT = YesPlease
|
||||
NO_STRTOUMAX = YesPlease
|
||||
NO_MKDTEMP = YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
SNPRINTF_RETURNS_BOGUS = YesPlease
|
||||
NO_SVN_TESTS = YesPlease
|
||||
NO_PERL_MAKEMAKER = YesPlease
|
||||
@@ -865,11 +903,20 @@ endif
|
||||
endif
|
||||
ifneq (,$(findstring arm,$(uname_M)))
|
||||
ARM_SHA1 = YesPlease
|
||||
NO_MKSTEMPS = YesPlease
|
||||
endif
|
||||
|
||||
-include config.mak.autogen
|
||||
-include config.mak
|
||||
|
||||
ifdef SANE_TOOL_PATH
|
||||
SANE_TOOL_PATH_SQ = $(subst ','\'',$(SANE_TOOL_PATH))
|
||||
BROKEN_PATH_FIX = 's|^\# @@BROKEN_PATH_FIX@@$$|git_broken_path_fix $(SANE_TOOL_PATH_SQ)|'
|
||||
PATH := $(SANE_TOOL_PATH):${PATH}
|
||||
else
|
||||
BROKEN_PATH_FIX = '/^\# @@BROKEN_PATH_FIX@@$$/d'
|
||||
endif
|
||||
|
||||
ifeq ($(uname_S),Darwin)
|
||||
ifndef NO_FINK
|
||||
ifeq ($(shell test -d /sw/lib && echo y),y)
|
||||
@@ -896,6 +943,11 @@ ifndef CC_LD_DYNPATH
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef NO_LIBGEN_H
|
||||
COMPAT_CFLAGS += -DNO_LIBGEN_H
|
||||
COMPAT_OBJS += compat/basename.o
|
||||
endif
|
||||
|
||||
ifdef NO_CURL
|
||||
BASIC_CFLAGS += -DNO_CURL
|
||||
else
|
||||
@@ -968,6 +1020,9 @@ endif
|
||||
ifdef NEEDS_NSL
|
||||
EXTLIBS += -lnsl
|
||||
endif
|
||||
ifdef NEEDS_RESOLV
|
||||
EXTLIBS += -lresolv
|
||||
endif
|
||||
ifdef NO_D_TYPE_IN_DIRENT
|
||||
BASIC_CFLAGS += -DNO_D_TYPE_IN_DIRENT
|
||||
endif
|
||||
@@ -1023,6 +1078,10 @@ ifdef NO_MKDTEMP
|
||||
COMPAT_CFLAGS += -DNO_MKDTEMP
|
||||
COMPAT_OBJS += compat/mkdtemp.o
|
||||
endif
|
||||
ifdef NO_MKSTEMPS
|
||||
COMPAT_CFLAGS += -DNO_MKSTEMPS
|
||||
COMPAT_OBJS += compat/mkstemps.o
|
||||
endif
|
||||
ifdef NO_UNSETENV
|
||||
COMPAT_CFLAGS += -DNO_UNSETENV
|
||||
COMPAT_OBJS += compat/unsetenv.o
|
||||
@@ -1271,9 +1330,9 @@ $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
|
||||
$(QUIET_GEN)$(RM) $@ $@+ && \
|
||||
sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
|
||||
-e 's|@SHELL_PATH@|$(SHELL_PATH_SQ)|' \
|
||||
-e 's|@@PERL@@|$(PERL_PATH_SQ)|g' \
|
||||
-e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
|
||||
-e 's/@@NO_CURL@@/$(NO_CURL)/g' \
|
||||
-e $(BROKEN_PATH_FIX) \
|
||||
$@.sh >$@+ && \
|
||||
chmod +x $@+ && \
|
||||
mv $@+ $@
|
||||
@@ -1513,6 +1572,8 @@ test-delta$X: diff-delta.o patch-delta.o
|
||||
|
||||
test-parse-options$X: parse-options.o
|
||||
|
||||
test-parse-options.o: parse-options.h
|
||||
|
||||
.PRECIOUS: $(patsubst test-%$X,test-%.o,$(TEST_PROGRAMS))
|
||||
|
||||
test-%$X: test-%.o $(GITLIBS)
|
||||
|
||||
2
RelNotes
2
RelNotes
@@ -1 +1 @@
|
||||
Documentation/RelNotes-1.6.3.2.txt
|
||||
Documentation/RelNotes-1.6.4.txt
|
||||
@@ -309,7 +309,7 @@ static int parse_archive_args(int argc, const char **argv,
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
argc = parse_options(argc, argv, opts, archive_usage, 0);
|
||||
argc = parse_options(argc, argv, NULL, opts, archive_usage, 0);
|
||||
|
||||
if (remote)
|
||||
die("Unexpected option --remote");
|
||||
|
||||
451
bisect.c
451
bisect.c
@@ -6,15 +6,30 @@
|
||||
#include "list-objects.h"
|
||||
#include "quote.h"
|
||||
#include "sha1-lookup.h"
|
||||
#include "run-command.h"
|
||||
#include "bisect.h"
|
||||
|
||||
static unsigned char (*skipped_sha1)[20];
|
||||
static int skipped_sha1_nr;
|
||||
static int skipped_sha1_alloc;
|
||||
struct sha1_array {
|
||||
unsigned char (*sha1)[20];
|
||||
int sha1_nr;
|
||||
int sha1_alloc;
|
||||
int sorted;
|
||||
};
|
||||
|
||||
static const char **rev_argv;
|
||||
static int rev_argv_nr;
|
||||
static int rev_argv_alloc;
|
||||
static struct sha1_array good_revs;
|
||||
static struct sha1_array skipped_revs;
|
||||
|
||||
static const unsigned char *current_bad_sha1;
|
||||
|
||||
struct argv_array {
|
||||
const char **argv;
|
||||
int argv_nr;
|
||||
int argv_alloc;
|
||||
};
|
||||
|
||||
static const char *argv_diff_tree[] = {"diff-tree", "--pretty", NULL, NULL};
|
||||
static const char *argv_checkout[] = {"checkout", "-q", NULL, "--", NULL};
|
||||
static const char *argv_show_branch[] = {"show-branch", NULL, NULL};
|
||||
|
||||
/* bits #0-15 in revision.h */
|
||||
|
||||
@@ -398,23 +413,37 @@ struct commit_list *find_bisection(struct commit_list *list,
|
||||
return best;
|
||||
}
|
||||
|
||||
static void argv_array_push(struct argv_array *array, const char *string)
|
||||
{
|
||||
ALLOC_GROW(array->argv, array->argv_nr + 1, array->argv_alloc);
|
||||
array->argv[array->argv_nr++] = string;
|
||||
}
|
||||
|
||||
static void argv_array_push_sha1(struct argv_array *array,
|
||||
const unsigned char *sha1,
|
||||
const char *format)
|
||||
{
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
strbuf_addf(&buf, format, sha1_to_hex(sha1));
|
||||
argv_array_push(array, strbuf_detach(&buf, NULL));
|
||||
}
|
||||
|
||||
static void sha1_array_push(struct sha1_array *array,
|
||||
const unsigned char *sha1)
|
||||
{
|
||||
ALLOC_GROW(array->sha1, array->sha1_nr + 1, array->sha1_alloc);
|
||||
hashcpy(array->sha1[array->sha1_nr++], sha1);
|
||||
}
|
||||
|
||||
static int register_ref(const char *refname, const unsigned char *sha1,
|
||||
int flags, void *cb_data)
|
||||
{
|
||||
if (!strcmp(refname, "bad")) {
|
||||
ALLOC_GROW(rev_argv, rev_argv_nr + 1, rev_argv_alloc);
|
||||
rev_argv[rev_argv_nr++] = xstrdup(sha1_to_hex(sha1));
|
||||
current_bad_sha1 = sha1;
|
||||
} else if (!prefixcmp(refname, "good-")) {
|
||||
const char *hex = sha1_to_hex(sha1);
|
||||
char *good = xmalloc(strlen(hex) + 2);
|
||||
*good = '^';
|
||||
memcpy(good + 1, hex, strlen(hex) + 1);
|
||||
ALLOC_GROW(rev_argv, rev_argv_nr + 1, rev_argv_alloc);
|
||||
rev_argv[rev_argv_nr++] = good;
|
||||
sha1_array_push(&good_revs, sha1);
|
||||
} else if (!prefixcmp(refname, "skip-")) {
|
||||
ALLOC_GROW(skipped_sha1, skipped_sha1_nr + 1,
|
||||
skipped_sha1_alloc);
|
||||
hashcpy(skipped_sha1[skipped_sha1_nr++], sha1);
|
||||
sha1_array_push(&skipped_revs, sha1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -425,7 +454,7 @@ static int read_bisect_refs(void)
|
||||
return for_each_ref_in("refs/bisect/", register_ref, NULL);
|
||||
}
|
||||
|
||||
void read_bisect_paths(void)
|
||||
void read_bisect_paths(struct argv_array *array)
|
||||
{
|
||||
struct strbuf str = STRBUF_INIT;
|
||||
const char *filename = git_path("BISECT_NAMES");
|
||||
@@ -440,8 +469,8 @@ void read_bisect_paths(void)
|
||||
|
||||
strbuf_trim(&str);
|
||||
quoted = strbuf_detach(&str, NULL);
|
||||
res = sq_dequote_to_argv(quoted, &rev_argv,
|
||||
&rev_argv_nr, &rev_argv_alloc);
|
||||
res = sq_dequote_to_argv(quoted, &array->argv,
|
||||
&array->argv_nr, &array->argv_alloc);
|
||||
if (res)
|
||||
die("Badly quoted content in file '%s': %s",
|
||||
filename, quoted);
|
||||
@@ -451,26 +480,45 @@ void read_bisect_paths(void)
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
static int skipcmp(const void *a, const void *b)
|
||||
static int array_cmp(const void *a, const void *b)
|
||||
{
|
||||
return hashcmp(a, b);
|
||||
}
|
||||
|
||||
static void prepare_skipped(void)
|
||||
static void sort_sha1_array(struct sha1_array *array)
|
||||
{
|
||||
qsort(skipped_sha1, skipped_sha1_nr, sizeof(*skipped_sha1), skipcmp);
|
||||
qsort(array->sha1, array->sha1_nr, sizeof(*array->sha1), array_cmp);
|
||||
|
||||
array->sorted = 1;
|
||||
}
|
||||
|
||||
static const unsigned char *skipped_sha1_access(size_t index, void *table)
|
||||
static const unsigned char *sha1_access(size_t index, void *table)
|
||||
{
|
||||
unsigned char (*skipped)[20] = table;
|
||||
return skipped[index];
|
||||
unsigned char (*array)[20] = table;
|
||||
return array[index];
|
||||
}
|
||||
|
||||
static int lookup_skipped(unsigned char *sha1)
|
||||
static int lookup_sha1_array(struct sha1_array *array,
|
||||
const unsigned char *sha1)
|
||||
{
|
||||
return sha1_pos(sha1, skipped_sha1, skipped_sha1_nr,
|
||||
skipped_sha1_access);
|
||||
if (!array->sorted)
|
||||
sort_sha1_array(array);
|
||||
|
||||
return sha1_pos(sha1, array->sha1, array->sha1_nr, sha1_access);
|
||||
}
|
||||
|
||||
static char *join_sha1_array_hex(struct sha1_array *array, char delim)
|
||||
{
|
||||
struct strbuf joined_hexs = STRBUF_INIT;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < array->sha1_nr; i++) {
|
||||
strbuf_addstr(&joined_hexs, sha1_to_hex(array->sha1[i]));
|
||||
if (i + 1 < array->sha1_nr)
|
||||
strbuf_addch(&joined_hexs, delim);
|
||||
}
|
||||
|
||||
return strbuf_detach(&joined_hexs, NULL);
|
||||
}
|
||||
|
||||
struct commit_list *filter_skipped(struct commit_list *list,
|
||||
@@ -481,15 +529,14 @@ struct commit_list *filter_skipped(struct commit_list *list,
|
||||
|
||||
*tried = NULL;
|
||||
|
||||
if (!skipped_sha1_nr)
|
||||
if (!skipped_revs.sha1_nr)
|
||||
return list;
|
||||
|
||||
prepare_skipped();
|
||||
|
||||
while (list) {
|
||||
struct commit_list *next = list->next;
|
||||
list->next = NULL;
|
||||
if (0 <= lookup_skipped(list->item->object.sha1)) {
|
||||
if (0 <= lookup_sha1_array(&skipped_revs,
|
||||
list->item->object.sha1)) {
|
||||
/* Move current to tried list */
|
||||
*tried = list;
|
||||
tried = &list->next;
|
||||
@@ -506,51 +553,323 @@ struct commit_list *filter_skipped(struct commit_list *list,
|
||||
return filtered;
|
||||
}
|
||||
|
||||
static void bisect_rev_setup(struct rev_info *revs, const char *prefix)
|
||||
static void bisect_rev_setup(struct rev_info *revs, const char *prefix,
|
||||
const char *bad_format, const char *good_format,
|
||||
int read_paths)
|
||||
{
|
||||
struct argv_array rev_argv = { NULL, 0, 0 };
|
||||
int i;
|
||||
|
||||
init_revisions(revs, prefix);
|
||||
revs->abbrev = 0;
|
||||
revs->commit_format = CMIT_FMT_UNSPECIFIED;
|
||||
|
||||
/* argv[0] will be ignored by setup_revisions */
|
||||
ALLOC_GROW(rev_argv, rev_argv_nr + 1, rev_argv_alloc);
|
||||
rev_argv[rev_argv_nr++] = xstrdup("bisect_rev_setup");
|
||||
/* rev_argv.argv[0] will be ignored by setup_revisions */
|
||||
argv_array_push(&rev_argv, xstrdup("bisect_rev_setup"));
|
||||
argv_array_push_sha1(&rev_argv, current_bad_sha1, bad_format);
|
||||
for (i = 0; i < good_revs.sha1_nr; i++)
|
||||
argv_array_push_sha1(&rev_argv, good_revs.sha1[i],
|
||||
good_format);
|
||||
argv_array_push(&rev_argv, xstrdup("--"));
|
||||
if (read_paths)
|
||||
read_bisect_paths(&rev_argv);
|
||||
argv_array_push(&rev_argv, NULL);
|
||||
|
||||
setup_revisions(rev_argv.argv_nr, rev_argv.argv, revs, NULL);
|
||||
}
|
||||
|
||||
static void bisect_common(struct rev_info *revs)
|
||||
{
|
||||
if (prepare_revision_walk(revs))
|
||||
die("revision walk setup failed");
|
||||
if (revs->tree_objects)
|
||||
mark_edges_uninteresting(revs->commits, revs, NULL);
|
||||
}
|
||||
|
||||
static void exit_if_skipped_commits(struct commit_list *tried,
|
||||
const unsigned char *bad)
|
||||
{
|
||||
if (!tried)
|
||||
return;
|
||||
|
||||
printf("There are only 'skip'ped commits left to test.\n"
|
||||
"The first bad commit could be any of:\n");
|
||||
print_commit_list(tried, "%s\n", "%s\n");
|
||||
if (bad)
|
||||
printf("%s\n", sha1_to_hex(bad));
|
||||
printf("We cannot bisect more!\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
static int is_expected_rev(const unsigned char *sha1)
|
||||
{
|
||||
const char *filename = git_path("BISECT_EXPECTED_REV");
|
||||
struct stat st;
|
||||
struct strbuf str = STRBUF_INIT;
|
||||
FILE *fp;
|
||||
int res = 0;
|
||||
|
||||
if (stat(filename, &st) || !S_ISREG(st.st_mode))
|
||||
return 0;
|
||||
|
||||
fp = fopen(filename, "r");
|
||||
if (!fp)
|
||||
return 0;
|
||||
|
||||
if (strbuf_getline(&str, fp, '\n') != EOF)
|
||||
res = !strcmp(str.buf, sha1_to_hex(sha1));
|
||||
|
||||
strbuf_release(&str);
|
||||
fclose(fp);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void mark_expected_rev(char *bisect_rev_hex)
|
||||
{
|
||||
int len = strlen(bisect_rev_hex);
|
||||
const char *filename = git_path("BISECT_EXPECTED_REV");
|
||||
int fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0600);
|
||||
|
||||
if (fd < 0)
|
||||
die("could not create file '%s': %s",
|
||||
filename, strerror(errno));
|
||||
|
||||
bisect_rev_hex[len] = '\n';
|
||||
write_or_die(fd, bisect_rev_hex, len + 1);
|
||||
bisect_rev_hex[len] = '\0';
|
||||
|
||||
if (close(fd) < 0)
|
||||
die("closing file %s: %s", filename, strerror(errno));
|
||||
}
|
||||
|
||||
static int bisect_checkout(char *bisect_rev_hex)
|
||||
{
|
||||
int res;
|
||||
|
||||
mark_expected_rev(bisect_rev_hex);
|
||||
|
||||
argv_checkout[2] = bisect_rev_hex;
|
||||
res = run_command_v_opt(argv_checkout, RUN_GIT_CMD);
|
||||
if (res)
|
||||
exit(res);
|
||||
|
||||
argv_show_branch[1] = bisect_rev_hex;
|
||||
return run_command_v_opt(argv_show_branch, RUN_GIT_CMD);
|
||||
}
|
||||
|
||||
static struct commit *get_commit_reference(const unsigned char *sha1)
|
||||
{
|
||||
struct commit *r = lookup_commit_reference(sha1);
|
||||
if (!r)
|
||||
die("Not a valid commit name %s", sha1_to_hex(sha1));
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct commit **get_bad_and_good_commits(int *rev_nr)
|
||||
{
|
||||
int len = 1 + good_revs.sha1_nr;
|
||||
struct commit **rev = xmalloc(len * sizeof(*rev));
|
||||
int i, n = 0;
|
||||
|
||||
rev[n++] = get_commit_reference(current_bad_sha1);
|
||||
for (i = 0; i < good_revs.sha1_nr; i++)
|
||||
rev[n++] = get_commit_reference(good_revs.sha1[i]);
|
||||
*rev_nr = n;
|
||||
|
||||
return rev;
|
||||
}
|
||||
|
||||
static void handle_bad_merge_base(void)
|
||||
{
|
||||
if (is_expected_rev(current_bad_sha1)) {
|
||||
char *bad_hex = sha1_to_hex(current_bad_sha1);
|
||||
char *good_hex = join_sha1_array_hex(&good_revs, ' ');
|
||||
|
||||
fprintf(stderr, "The merge base %s is bad.\n"
|
||||
"This means the bug has been fixed "
|
||||
"between %s and [%s].\n",
|
||||
bad_hex, bad_hex, good_hex);
|
||||
|
||||
exit(3);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Some good revs are not ancestor of the bad rev.\n"
|
||||
"git bisect cannot work properly in this case.\n"
|
||||
"Maybe you mistake good and bad revs?\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void handle_skipped_merge_base(const unsigned char *mb)
|
||||
{
|
||||
char *mb_hex = sha1_to_hex(mb);
|
||||
char *bad_hex = sha1_to_hex(current_bad_sha1);
|
||||
char *good_hex = join_sha1_array_hex(&good_revs, ' ');
|
||||
|
||||
fprintf(stderr, "Warning: the merge base between %s and [%s] "
|
||||
"must be skipped.\n"
|
||||
"So we cannot be sure the first bad commit is "
|
||||
"between %s and %s.\n"
|
||||
"We continue anyway.\n",
|
||||
bad_hex, good_hex, mb_hex, bad_hex);
|
||||
free(good_hex);
|
||||
}
|
||||
|
||||
/*
|
||||
* "check_merge_bases" checks that merge bases are not "bad".
|
||||
*
|
||||
* - If one is "bad", it means the user assumed something wrong
|
||||
* and we must exit with a non 0 error code.
|
||||
* - If one is "good", that's good, we have nothing to do.
|
||||
* - If one is "skipped", we can't know but we should warn.
|
||||
* - If we don't know, we should check it out and ask the user to test.
|
||||
*/
|
||||
static void check_merge_bases(void)
|
||||
{
|
||||
struct commit_list *result;
|
||||
int rev_nr;
|
||||
struct commit **rev = get_bad_and_good_commits(&rev_nr);
|
||||
|
||||
result = get_merge_bases_many(rev[0], rev_nr - 1, rev + 1, 0);
|
||||
|
||||
for (; result; result = result->next) {
|
||||
const unsigned char *mb = result->item->object.sha1;
|
||||
if (!hashcmp(mb, current_bad_sha1)) {
|
||||
handle_bad_merge_base();
|
||||
} else if (0 <= lookup_sha1_array(&good_revs, mb)) {
|
||||
continue;
|
||||
} else if (0 <= lookup_sha1_array(&skipped_revs, mb)) {
|
||||
handle_skipped_merge_base(mb);
|
||||
} else {
|
||||
printf("Bisecting: a merge base must be tested\n");
|
||||
exit(bisect_checkout(sha1_to_hex(mb)));
|
||||
}
|
||||
}
|
||||
|
||||
free(rev);
|
||||
free_commit_list(result);
|
||||
}
|
||||
|
||||
static int check_ancestors(const char *prefix)
|
||||
{
|
||||
struct rev_info revs;
|
||||
struct object_array pending_copy;
|
||||
int i, res;
|
||||
|
||||
bisect_rev_setup(&revs, prefix, "^%s", "%s", 0);
|
||||
|
||||
/* Save pending objects, so they can be cleaned up later. */
|
||||
memset(&pending_copy, 0, sizeof(pending_copy));
|
||||
for (i = 0; i < revs.pending.nr; i++)
|
||||
add_object_array(revs.pending.objects[i].item,
|
||||
revs.pending.objects[i].name,
|
||||
&pending_copy);
|
||||
|
||||
bisect_common(&revs);
|
||||
res = (revs.commits != NULL);
|
||||
|
||||
/* Clean up objects used, as they will be reused. */
|
||||
for (i = 0; i < pending_copy.nr; i++) {
|
||||
struct object *o = pending_copy.objects[i].item;
|
||||
unparse_commit((struct commit *)o);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* "check_good_are_ancestors_of_bad" checks that all "good" revs are
|
||||
* ancestor of the "bad" rev.
|
||||
*
|
||||
* If that's not the case, we need to check the merge bases.
|
||||
* If a merge base must be tested by the user, its source code will be
|
||||
* checked out to be tested by the user and we will exit.
|
||||
*/
|
||||
static void check_good_are_ancestors_of_bad(const char *prefix)
|
||||
{
|
||||
const char *filename = git_path("BISECT_ANCESTORS_OK");
|
||||
struct stat st;
|
||||
int fd;
|
||||
|
||||
if (!current_bad_sha1)
|
||||
die("a bad revision is needed");
|
||||
|
||||
/* Check if file BISECT_ANCESTORS_OK exists. */
|
||||
if (!stat(filename, &st) && S_ISREG(st.st_mode))
|
||||
return;
|
||||
|
||||
/* Bisecting with no good rev is ok. */
|
||||
if (good_revs.sha1_nr == 0)
|
||||
return;
|
||||
|
||||
/* Check if all good revs are ancestor of the bad rev. */
|
||||
if (check_ancestors(prefix))
|
||||
check_merge_bases();
|
||||
|
||||
/* Create file BISECT_ANCESTORS_OK. */
|
||||
fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0600);
|
||||
if (fd < 0)
|
||||
warning("could not create file '%s': %s",
|
||||
filename, strerror(errno));
|
||||
else
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/*
|
||||
* We use the convention that exiting with an exit code 10 means that
|
||||
* the bisection process finished successfully.
|
||||
* In this case the calling shell script should exit 0.
|
||||
*/
|
||||
int bisect_next_all(const char *prefix)
|
||||
{
|
||||
struct rev_info revs;
|
||||
struct commit_list *tried;
|
||||
int reaches = 0, all = 0, nr;
|
||||
const unsigned char *bisect_rev;
|
||||
char bisect_rev_hex[41];
|
||||
|
||||
if (read_bisect_refs())
|
||||
die("reading bisect refs failed");
|
||||
|
||||
ALLOC_GROW(rev_argv, rev_argv_nr + 1, rev_argv_alloc);
|
||||
rev_argv[rev_argv_nr++] = xstrdup("--");
|
||||
check_good_are_ancestors_of_bad(prefix);
|
||||
|
||||
read_bisect_paths();
|
||||
bisect_rev_setup(&revs, prefix, "%s", "^%s", 1);
|
||||
revs.limited = 1;
|
||||
|
||||
ALLOC_GROW(rev_argv, rev_argv_nr + 1, rev_argv_alloc);
|
||||
rev_argv[rev_argv_nr++] = NULL;
|
||||
|
||||
setup_revisions(rev_argv_nr, rev_argv, revs, NULL);
|
||||
|
||||
revs->limited = 1;
|
||||
}
|
||||
|
||||
int bisect_next_vars(const char *prefix)
|
||||
{
|
||||
struct rev_info revs;
|
||||
struct rev_list_info info;
|
||||
int reaches = 0, all = 0;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.revs = &revs;
|
||||
info.bisect_show_flags = BISECT_SHOW_TRIED | BISECT_SHOW_STRINGED;
|
||||
|
||||
bisect_rev_setup(&revs, prefix);
|
||||
|
||||
if (prepare_revision_walk(&revs))
|
||||
die("revision walk setup failed");
|
||||
if (revs.tree_objects)
|
||||
mark_edges_uninteresting(revs.commits, &revs, NULL);
|
||||
bisect_common(&revs);
|
||||
|
||||
revs.commits = find_bisection(revs.commits, &reaches, &all,
|
||||
!!skipped_sha1_nr);
|
||||
!!skipped_revs.sha1_nr);
|
||||
revs.commits = filter_skipped(revs.commits, &tried, 0);
|
||||
|
||||
return show_bisect_vars(&info, reaches, all);
|
||||
if (!revs.commits) {
|
||||
/*
|
||||
* We should exit here only if the "bad"
|
||||
* commit is also a "skip" commit.
|
||||
*/
|
||||
exit_if_skipped_commits(tried, NULL);
|
||||
|
||||
printf("%s was both good and bad\n",
|
||||
sha1_to_hex(current_bad_sha1));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
bisect_rev = revs.commits->item->object.sha1;
|
||||
memcpy(bisect_rev_hex, sha1_to_hex(bisect_rev), 41);
|
||||
|
||||
if (!hashcmp(bisect_rev, current_bad_sha1)) {
|
||||
exit_if_skipped_commits(tried, current_bad_sha1);
|
||||
printf("%s is first bad commit\n", bisect_rev_hex);
|
||||
argv_diff_tree[2] = bisect_rev_hex;
|
||||
run_command_v_opt(argv_diff_tree, RUN_GIT_CMD);
|
||||
/* This means the bisection process succeeded. */
|
||||
exit(10);
|
||||
}
|
||||
|
||||
nr = all - reaches - 1;
|
||||
printf("Bisecting: %d revisions left to test after this "
|
||||
"(roughly %d steps)\n", nr, estimate_bisect_steps(all));
|
||||
|
||||
return bisect_checkout(bisect_rev_hex);
|
||||
}
|
||||
|
||||
|
||||
9
bisect.h
9
bisect.h
@@ -9,10 +9,13 @@ extern struct commit_list *filter_skipped(struct commit_list *list,
|
||||
struct commit_list **tried,
|
||||
int show_all);
|
||||
|
||||
extern void print_commit_list(struct commit_list *list,
|
||||
const char *format_cur,
|
||||
const char *format_last);
|
||||
|
||||
/* bisect_show_flags flags in struct rev_list_info */
|
||||
#define BISECT_SHOW_ALL (1<<0)
|
||||
#define BISECT_SHOW_TRIED (1<<1)
|
||||
#define BISECT_SHOW_STRINGED (1<<2)
|
||||
|
||||
struct rev_list_info {
|
||||
struct rev_info *revs;
|
||||
@@ -24,6 +27,8 @@ struct rev_list_info {
|
||||
|
||||
extern int show_bisect_vars(struct rev_list_info *info, int reaches, int all);
|
||||
|
||||
extern int bisect_next_vars(const char *prefix);
|
||||
extern int bisect_next_all(const char *prefix);
|
||||
|
||||
extern int estimate_bisect_steps(int all);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -10,12 +10,14 @@
|
||||
#include "cache-tree.h"
|
||||
#include "run-command.h"
|
||||
#include "parse-options.h"
|
||||
#include "diff.h"
|
||||
#include "revision.h"
|
||||
|
||||
static const char * const builtin_add_usage[] = {
|
||||
"git add [options] [--] <filepattern>...",
|
||||
NULL
|
||||
};
|
||||
static int patch_interactive, add_interactive;
|
||||
static int patch_interactive, add_interactive, edit_interactive;
|
||||
static int take_worktree_changes;
|
||||
|
||||
static void fill_pathspec_matches(const char **pathspec, char *seen, int specs)
|
||||
@@ -187,6 +189,51 @@ int interactive_add(int argc, const char **argv, const char *prefix)
|
||||
return status;
|
||||
}
|
||||
|
||||
int edit_patch(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
char *file = xstrdup(git_path("ADD_EDIT.patch"));
|
||||
const char *apply_argv[] = { "apply", "--recount", "--cached",
|
||||
file, NULL };
|
||||
struct child_process child;
|
||||
struct rev_info rev;
|
||||
int out;
|
||||
struct stat st;
|
||||
|
||||
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
|
||||
|
||||
if (read_cache() < 0)
|
||||
die ("Could not read the index");
|
||||
|
||||
init_revisions(&rev, prefix);
|
||||
rev.diffopt.context = 7;
|
||||
|
||||
argc = setup_revisions(argc, argv, &rev, NULL);
|
||||
rev.diffopt.output_format = DIFF_FORMAT_PATCH;
|
||||
out = open(file, O_CREAT | O_WRONLY, 0644);
|
||||
if (out < 0)
|
||||
die ("Could not open '%s' for writing.", file);
|
||||
rev.diffopt.file = fdopen(out, "w");
|
||||
rev.diffopt.close_file = 1;
|
||||
if (run_diff_files(&rev, 0))
|
||||
die ("Could not write patch");
|
||||
|
||||
launch_editor(file, NULL, NULL);
|
||||
|
||||
if (stat(file, &st))
|
||||
die("Could not stat '%s'", file);
|
||||
if (!st.st_size)
|
||||
die("Empty patch. Aborted.");
|
||||
|
||||
memset(&child, 0, sizeof(child));
|
||||
child.git_cmd = 1;
|
||||
child.argv = apply_argv;
|
||||
if (run_command(&child))
|
||||
die ("Could not apply '%s'", file);
|
||||
|
||||
unlink(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct lock_file lock_file;
|
||||
|
||||
static const char ignore_error[] =
|
||||
@@ -201,6 +248,7 @@ static struct option builtin_add_options[] = {
|
||||
OPT_GROUP(""),
|
||||
OPT_BOOLEAN('i', "interactive", &add_interactive, "interactive picking"),
|
||||
OPT_BOOLEAN('p', "patch", &patch_interactive, "interactive patching"),
|
||||
OPT_BOOLEAN('e', "edit", &edit_interactive, "edit current diff and apply"),
|
||||
OPT_BOOLEAN('f', "force", &ignored_too, "allow adding otherwise ignored files"),
|
||||
OPT_BOOLEAN('u', "update", &take_worktree_changes, "update tracked files"),
|
||||
OPT_BOOLEAN('N', "intent-to-add", &intent_to_add, "record only the fact that the path will be added later"),
|
||||
@@ -250,15 +298,20 @@ int cmd_add(int argc, const char **argv, const char *prefix)
|
||||
int add_new_files;
|
||||
int require_pathspec;
|
||||
|
||||
argc = parse_options(argc, argv, builtin_add_options,
|
||||
builtin_add_usage, 0);
|
||||
argc = parse_options(argc, argv, prefix, builtin_add_options,
|
||||
builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
|
||||
if (patch_interactive)
|
||||
add_interactive = 1;
|
||||
if (add_interactive)
|
||||
exit(interactive_add(argc, argv, prefix));
|
||||
exit(interactive_add(argc - 1, argv + 1, prefix));
|
||||
|
||||
git_config(add_config, NULL);
|
||||
|
||||
if (edit_interactive)
|
||||
return(edit_patch(argc, argv, prefix));
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
if (addremove && take_worktree_changes)
|
||||
die("-A and -u are mutually incompatible");
|
||||
if ((addremove || take_worktree_changes) && !argc) {
|
||||
|
||||
@@ -320,6 +320,20 @@ static int name_terminate(const char *name, int namelen, int c, int terminate)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* remove double slashes to make --index work with such filenames */
|
||||
static char *squash_slash(char *name)
|
||||
{
|
||||
int i = 0, j = 0;
|
||||
|
||||
while (name[i]) {
|
||||
if ((name[j++] = name[i++]) == '/')
|
||||
while (name[i] == '/')
|
||||
i++;
|
||||
}
|
||||
name[j] = '\0';
|
||||
return name;
|
||||
}
|
||||
|
||||
static char *find_name(const char *line, char *def, int p_value, int terminate)
|
||||
{
|
||||
int len;
|
||||
@@ -349,7 +363,7 @@ static char *find_name(const char *line, char *def, int p_value, int terminate)
|
||||
free(def);
|
||||
if (root)
|
||||
strbuf_insert(&name, 0, root, root_len);
|
||||
return strbuf_detach(&name, NULL);
|
||||
return squash_slash(strbuf_detach(&name, NULL));
|
||||
}
|
||||
}
|
||||
strbuf_release(&name);
|
||||
@@ -369,10 +383,10 @@ static char *find_name(const char *line, char *def, int p_value, int terminate)
|
||||
start = line;
|
||||
}
|
||||
if (!start)
|
||||
return def;
|
||||
return squash_slash(def);
|
||||
len = line - start;
|
||||
if (!len)
|
||||
return def;
|
||||
return squash_slash(def);
|
||||
|
||||
/*
|
||||
* Generally we prefer the shorter name, especially
|
||||
@@ -383,7 +397,7 @@ static char *find_name(const char *line, char *def, int p_value, int terminate)
|
||||
if (def) {
|
||||
int deflen = strlen(def);
|
||||
if (deflen < len && !strncmp(start, def, deflen))
|
||||
return def;
|
||||
return squash_slash(def);
|
||||
free(def);
|
||||
}
|
||||
|
||||
@@ -392,10 +406,10 @@ static char *find_name(const char *line, char *def, int p_value, int terminate)
|
||||
strcpy(ret, root);
|
||||
memcpy(ret + root_len, start, len);
|
||||
ret[root_len + len] = '\0';
|
||||
return ret;
|
||||
return squash_slash(ret);
|
||||
}
|
||||
|
||||
return xmemdupz(start, len);
|
||||
return squash_slash(xmemdupz(start, len));
|
||||
}
|
||||
|
||||
static int count_slashes(const char *cp)
|
||||
@@ -3278,7 +3292,7 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
|
||||
"apply a patch without touching the working tree"),
|
||||
OPT_BOOLEAN(0, "apply", &force_apply,
|
||||
"also apply the patch (use with --stat/--summary/--check)"),
|
||||
OPT_STRING(0, "build-fake-ancestor", &fake_ancestor, "file",
|
||||
OPT_FILENAME(0, "build-fake-ancestor", &fake_ancestor,
|
||||
"build a temporary index based on embedded index information"),
|
||||
{ OPTION_CALLBACK, 'z', NULL, NULL, NULL,
|
||||
"paths are separated with NUL character",
|
||||
@@ -3313,11 +3327,8 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
|
||||
if (apply_default_whitespace)
|
||||
parse_whitespace_option(apply_default_whitespace);
|
||||
|
||||
argc = parse_options(argc, argv, builtin_apply_options,
|
||||
argc = parse_options(argc, argv, prefix, builtin_apply_options,
|
||||
apply_usage, 0);
|
||||
fake_ancestor = parse_options_fix_filename(prefix, fake_ancestor);
|
||||
if (fake_ancestor)
|
||||
fake_ancestor = xstrdup(fake_ancestor);
|
||||
|
||||
if (apply_with_reject)
|
||||
apply = apply_verbosely = 1;
|
||||
|
||||
@@ -80,7 +80,8 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
argc = parse_options(argc, argv, local_opts, NULL, PARSE_OPT_KEEP_ALL);
|
||||
argc = parse_options(argc, argv, prefix, local_opts, NULL,
|
||||
PARSE_OPT_KEEP_ALL);
|
||||
|
||||
if (output)
|
||||
create_output_file(output);
|
||||
|
||||
@@ -4,24 +4,25 @@
|
||||
#include "bisect.h"
|
||||
|
||||
static const char * const git_bisect_helper_usage[] = {
|
||||
"git bisect--helper --next-vars",
|
||||
"git bisect--helper --next-all",
|
||||
NULL
|
||||
};
|
||||
|
||||
int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int next_vars = 0;
|
||||
int next_all = 0;
|
||||
struct option options[] = {
|
||||
OPT_BOOLEAN(0, "next-vars", &next_vars,
|
||||
"output next bisect step variables"),
|
||||
OPT_BOOLEAN(0, "next-all", &next_all,
|
||||
"perform 'git bisect next'"),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
argc = parse_options(argc, argv, options, git_bisect_helper_usage, 0);
|
||||
argc = parse_options(argc, argv, prefix, options,
|
||||
git_bisect_helper_usage, 0);
|
||||
|
||||
if (!next_vars)
|
||||
if (!next_all)
|
||||
usage_with_options(git_bisect_helper_usage, options);
|
||||
|
||||
/* next-vars */
|
||||
return bisect_next_vars(prefix);
|
||||
/* next-all */
|
||||
return bisect_next_all(prefix);
|
||||
}
|
||||
|
||||
@@ -2239,7 +2239,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
|
||||
save_commit_buffer = 0;
|
||||
dashdash_pos = 0;
|
||||
|
||||
parse_options_start(&ctx, argc, argv, PARSE_OPT_KEEP_DASHDASH |
|
||||
parse_options_start(&ctx, argc, argv, prefix, PARSE_OPT_KEEP_DASHDASH |
|
||||
PARSE_OPT_KEEP_ARGV0);
|
||||
for (;;) {
|
||||
switch (parse_options_step(&ctx, options, blame_opt_usage)) {
|
||||
|
||||
@@ -547,7 +547,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
|
||||
struct option options[] = {
|
||||
OPT_GROUP("Generic options"),
|
||||
OPT__VERBOSE(&verbose),
|
||||
OPT_SET_INT( 0 , "track", &track, "set up tracking mode (see git-pull(1))",
|
||||
OPT_SET_INT('t', "track", &track, "set up tracking mode (see git-pull(1))",
|
||||
BRANCH_TRACK_EXPLICIT),
|
||||
OPT_BOOLEAN( 0 , "color", &branch_use_color, "use colored output"),
|
||||
OPT_SET_INT('r', NULL, &kinds, "act on remote-tracking branches",
|
||||
@@ -610,7 +610,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
|
||||
}
|
||||
hashcpy(merge_filter_ref, head_sha1);
|
||||
|
||||
argc = parse_options(argc, argv, options, builtin_branch_usage, 0);
|
||||
argc = parse_options(argc, argv, prefix, options, builtin_branch_usage,
|
||||
0);
|
||||
if (!!delete + !!rename + !!force_create > 1)
|
||||
usage_with_options(builtin_branch_usage, options);
|
||||
|
||||
|
||||
@@ -231,7 +231,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
|
||||
if (argc != 3 && argc != 2)
|
||||
usage_with_options(cat_file_usage, options);
|
||||
|
||||
argc = parse_options(argc, argv, options, cat_file_usage, 0);
|
||||
argc = parse_options(argc, argv, prefix, options, cat_file_usage, 0);
|
||||
|
||||
if (opt) {
|
||||
if (argc == 1)
|
||||
|
||||
@@ -69,8 +69,8 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)
|
||||
int cnt, i, doubledash;
|
||||
const char *errstr = NULL;
|
||||
|
||||
argc = parse_options(argc, argv, check_attr_options, check_attr_usage,
|
||||
PARSE_OPT_KEEP_DASHDASH);
|
||||
argc = parse_options(argc, argv, prefix, check_attr_options,
|
||||
check_attr_usage, PARSE_OPT_KEEP_DASHDASH);
|
||||
if (!argc)
|
||||
usage_with_options(check_attr_usage, check_attr_options);
|
||||
|
||||
|
||||
@@ -249,7 +249,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
|
||||
die("invalid cache");
|
||||
}
|
||||
|
||||
argc = parse_options(argc, argv, builtin_checkout_index_options,
|
||||
argc = parse_options(argc, argv, prefix, builtin_checkout_index_options,
|
||||
builtin_checkout_index_usage, 0);
|
||||
state.force = force;
|
||||
state.quiet = quiet;
|
||||
|
||||
@@ -605,7 +605,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
|
||||
|
||||
opts.track = BRANCH_TRACK_UNSPECIFIED;
|
||||
|
||||
argc = parse_options(argc, argv, options, checkout_usage,
|
||||
argc = parse_options(argc, argv, prefix, options, checkout_usage,
|
||||
PARSE_OPT_KEEP_DASHDASH);
|
||||
|
||||
/* --track without -b should DWIM */
|
||||
|
||||
@@ -56,7 +56,8 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
|
||||
else
|
||||
config_set = 1;
|
||||
|
||||
argc = parse_options(argc, argv, options, builtin_clean_usage, 0);
|
||||
argc = parse_options(argc, argv, prefix, options, builtin_clean_usage,
|
||||
0);
|
||||
|
||||
memset(&dir, 0, sizeof(dir));
|
||||
if (ignored_only)
|
||||
|
||||
@@ -104,11 +104,12 @@ static char *get_repo_path(const char *repo, int *is_bundle)
|
||||
static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)
|
||||
{
|
||||
const char *end = repo + strlen(repo), *start;
|
||||
char *dir;
|
||||
|
||||
/*
|
||||
* Strip trailing slashes and /.git
|
||||
* Strip trailing spaces, slashes and /.git
|
||||
*/
|
||||
while (repo < end && is_dir_sep(end[-1]))
|
||||
while (repo < end && (is_dir_sep(end[-1]) || isspace(end[-1])))
|
||||
end--;
|
||||
if (end - repo > 5 && is_dir_sep(end[-5]) &&
|
||||
!strncmp(end - 4, ".git", 4)) {
|
||||
@@ -140,10 +141,33 @@ static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)
|
||||
if (is_bare) {
|
||||
struct strbuf result = STRBUF_INIT;
|
||||
strbuf_addf(&result, "%.*s.git", (int)(end - start), start);
|
||||
return strbuf_detach(&result, 0);
|
||||
dir = strbuf_detach(&result, 0);
|
||||
} else
|
||||
dir = xstrndup(start, end - start);
|
||||
/*
|
||||
* Replace sequences of 'control' characters and whitespace
|
||||
* with one ascii space, remove leading and trailing spaces.
|
||||
*/
|
||||
if (*dir) {
|
||||
char *out = dir;
|
||||
int prev_space = 1 /* strip leading whitespace */;
|
||||
for (end = dir; *end; ++end) {
|
||||
char ch = *end;
|
||||
if ((unsigned char)ch < '\x20')
|
||||
ch = '\x20';
|
||||
if (isspace(ch)) {
|
||||
if (prev_space)
|
||||
continue;
|
||||
prev_space = 1;
|
||||
} else
|
||||
prev_space = 0;
|
||||
*out++ = ch;
|
||||
}
|
||||
*out = '\0';
|
||||
if (out > dir && prev_space)
|
||||
out[-1] = '\0';
|
||||
}
|
||||
|
||||
return xstrndup(start, end - start);
|
||||
return dir;
|
||||
}
|
||||
|
||||
static void strip_trailing_slashes(char *dir)
|
||||
@@ -336,7 +360,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
|
||||
junk_pid = getpid();
|
||||
|
||||
argc = parse_options(argc, argv, builtin_clone_options,
|
||||
argc = parse_options(argc, argv, prefix, builtin_clone_options,
|
||||
builtin_clone_usage, 0);
|
||||
|
||||
if (argc == 0)
|
||||
|
||||
@@ -88,13 +88,13 @@ static struct option builtin_commit_options[] = {
|
||||
OPT__VERBOSE(&verbose),
|
||||
OPT_GROUP("Commit message options"),
|
||||
|
||||
OPT_STRING('F', "file", &logfile, "FILE", "read log from file"),
|
||||
OPT_FILENAME('F', "file", &logfile, "read log from file"),
|
||||
OPT_STRING(0, "author", &force_author, "AUTHOR", "override author for commit"),
|
||||
OPT_CALLBACK('m', "message", &message, "MESSAGE", "specify commit message", opt_parse_m),
|
||||
OPT_STRING('c', "reedit-message", &edit_message, "COMMIT", "reuse and edit message from specified commit "),
|
||||
OPT_STRING('C', "reuse-message", &use_message, "COMMIT", "reuse message from specified commit"),
|
||||
OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
|
||||
OPT_STRING('t', "template", &template_file, "FILE", "use specified template file"),
|
||||
OPT_FILENAME('t', "template", &template_file, "use specified template file"),
|
||||
OPT_BOOLEAN('e', "edit", &edit_flag, "force edit of commit"),
|
||||
|
||||
OPT_GROUP("Commit contents options"),
|
||||
@@ -697,13 +697,8 @@ static int parse_and_validate_options(int argc, const char *argv[],
|
||||
{
|
||||
int f = 0;
|
||||
|
||||
argc = parse_options(argc, argv, builtin_commit_options, usage, 0);
|
||||
logfile = parse_options_fix_filename(prefix, logfile);
|
||||
if (logfile)
|
||||
logfile = xstrdup(logfile);
|
||||
template_file = parse_options_fix_filename(prefix, template_file);
|
||||
if (template_file)
|
||||
template_file = xstrdup(template_file);
|
||||
argc = parse_options(argc, argv, prefix, builtin_commit_options, usage,
|
||||
0);
|
||||
|
||||
if (force_author && !strchr(force_author, '>'))
|
||||
force_author = find_author_by_nickname(force_author);
|
||||
|
||||
@@ -316,7 +316,8 @@ int cmd_config(int argc, const char **argv, const char *unused_prefix)
|
||||
|
||||
config_exclusive_filename = getenv(CONFIG_ENVIRONMENT);
|
||||
|
||||
argc = parse_options(argc, argv, builtin_config_options, builtin_config_usage,
|
||||
argc = parse_options(argc, argv, prefix, builtin_config_options,
|
||||
builtin_config_usage,
|
||||
PARSE_OPT_STOP_AT_NON_OPTION);
|
||||
|
||||
if (use_global_config + use_system_config + !!given_config_file > 1) {
|
||||
|
||||
@@ -83,7 +83,7 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)
|
||||
OPT_END(),
|
||||
};
|
||||
|
||||
argc = parse_options(argc, argv, opts, count_objects_usage, 0);
|
||||
argc = parse_options(argc, argv, prefix, opts, count_objects_usage, 0);
|
||||
/* we do not take arguments other than flags for now */
|
||||
if (argc)
|
||||
usage_with_options(count_objects_usage, opts);
|
||||
|
||||
@@ -322,7 +322,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
|
||||
OPT_END(),
|
||||
};
|
||||
|
||||
argc = parse_options(argc, argv, options, describe_usage, 0);
|
||||
argc = parse_options(argc, argv, prefix, options, describe_usage, 0);
|
||||
if (max_candidates < 0)
|
||||
max_candidates = 0;
|
||||
else if (max_candidates > MAX_TAGS)
|
||||
|
||||
@@ -515,7 +515,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
|
||||
|
||||
init_revisions(&revs, prefix);
|
||||
argc = setup_revisions(argc, argv, &revs, NULL);
|
||||
argc = parse_options(argc, argv, options, fast_export_usage, 0);
|
||||
argc = parse_options(argc, argv, prefix, options, fast_export_usage, 0);
|
||||
if (argc > 1)
|
||||
usage_with_options (fast_export_usage, options);
|
||||
|
||||
|
||||
@@ -483,7 +483,9 @@ static int sideband_demux(int fd, void *data)
|
||||
{
|
||||
int *xd = data;
|
||||
|
||||
return recv_sideband("fetch-pack", xd[0], fd);
|
||||
int ret = recv_sideband("fetch-pack", xd[0], fd);
|
||||
close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int get_pack(int xd[2], char **pack_lockfile)
|
||||
|
||||
@@ -202,7 +202,7 @@ static int update_local_ref(struct ref *ref,
|
||||
struct commit *current = NULL, *updated;
|
||||
enum object_type type;
|
||||
struct branch *current_branch = branch_get(NULL);
|
||||
const char *pretty_ref = prettify_ref(ref);
|
||||
const char *pretty_ref = prettify_refname(ref->name);
|
||||
|
||||
*display = 0;
|
||||
type = sha1_object_info(ref->new_sha1, NULL);
|
||||
@@ -294,7 +294,7 @@ static int update_local_ref(struct ref *ref,
|
||||
}
|
||||
}
|
||||
|
||||
static int store_updated_refs(const char *url, const char *remote_name,
|
||||
static int store_updated_refs(const char *raw_url, const char *remote_name,
|
||||
struct ref *ref_map)
|
||||
{
|
||||
FILE *fp;
|
||||
@@ -303,11 +303,13 @@ static int store_updated_refs(const char *url, const char *remote_name,
|
||||
char note[1024];
|
||||
const char *what, *kind;
|
||||
struct ref *rm;
|
||||
char *filename = git_path("FETCH_HEAD");
|
||||
char *url, *filename = git_path("FETCH_HEAD");
|
||||
|
||||
fp = fopen(filename, "a");
|
||||
if (!fp)
|
||||
return error("cannot open %s: %s\n", filename, strerror(errno));
|
||||
|
||||
url = transport_anonymize_url(raw_url);
|
||||
for (rm = ref_map; rm; rm = rm->next) {
|
||||
struct ref *ref = NULL;
|
||||
|
||||
@@ -358,12 +360,18 @@ static int store_updated_refs(const char *url, const char *remote_name,
|
||||
kind);
|
||||
note_len += sprintf(note + note_len, "'%s' of ", what);
|
||||
}
|
||||
note_len += sprintf(note + note_len, "%.*s", url_len, url);
|
||||
fprintf(fp, "%s\t%s\t%s\n",
|
||||
note[note_len] = '\0';
|
||||
fprintf(fp, "%s\t%s\t%s",
|
||||
sha1_to_hex(commit ? commit->object.sha1 :
|
||||
rm->old_sha1),
|
||||
rm->merge ? "" : "not-for-merge",
|
||||
note);
|
||||
for (i = 0; i < url_len; ++i)
|
||||
if ('\n' == url[i])
|
||||
fputs("\\n", fp);
|
||||
else
|
||||
fputc(url[i], fp);
|
||||
fputc('\n', fp);
|
||||
|
||||
if (ref)
|
||||
rc |= update_local_ref(ref, what, note);
|
||||
@@ -381,6 +389,7 @@ static int store_updated_refs(const char *url, const char *remote_name,
|
||||
fprintf(stderr, " %s\n", note);
|
||||
}
|
||||
}
|
||||
free(url);
|
||||
fclose(fp);
|
||||
if (rc & STORE_REF_ERROR_DF_CONFLICT)
|
||||
error("some local refs could not be updated; try running\n"
|
||||
@@ -630,7 +639,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
|
||||
for (i = 1; i < argc; i++)
|
||||
strbuf_addf(&default_rla, " %s", argv[i]);
|
||||
|
||||
argc = parse_options(argc, argv,
|
||||
argc = parse_options(argc, argv, prefix,
|
||||
builtin_fetch_options, builtin_fetch_usage, 0);
|
||||
|
||||
if (argc == 0)
|
||||
|
||||
@@ -351,7 +351,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
|
||||
struct option options[] = {
|
||||
OPT_BOOLEAN(0, "log", &merge_summary, "populate log with the shortlog"),
|
||||
OPT_BOOLEAN(0, "summary", &merge_summary, "alias for --log"),
|
||||
OPT_STRING('F', "file", &inpath, "file", "file to read from"),
|
||||
OPT_FILENAME('F', "file", &inpath, "file to read from"),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
@@ -360,10 +360,10 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
|
||||
int ret;
|
||||
|
||||
git_config(fmt_merge_msg_config, NULL);
|
||||
argc = parse_options(argc, argv, options, fmt_merge_msg_usage, 0);
|
||||
argc = parse_options(argc, argv, prefix, options, fmt_merge_msg_usage,
|
||||
0);
|
||||
if (argc > 0)
|
||||
usage_with_options(fmt_merge_msg_usage, options);
|
||||
inpath = parse_options_fix_filename(prefix, inpath);
|
||||
|
||||
if (inpath && strcmp(inpath, "-")) {
|
||||
in = fopen(inpath, "r");
|
||||
|
||||
@@ -905,7 +905,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
|
||||
OPT_END(),
|
||||
};
|
||||
|
||||
parse_options(argc, argv, opts, for_each_ref_usage, 0);
|
||||
parse_options(argc, argv, prefix, opts, for_each_ref_usage, 0);
|
||||
if (maxcount < 0) {
|
||||
error("invalid --count argument: `%d'", maxcount);
|
||||
usage_with_options(for_each_ref_usage, opts);
|
||||
|
||||
@@ -590,7 +590,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
|
||||
|
||||
errors_found = 0;
|
||||
|
||||
argc = parse_options(argc, argv, fsck_opts, fsck_usage, 0);
|
||||
argc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0);
|
||||
if (write_lost_and_found) {
|
||||
check_full = 1;
|
||||
include_reflogs = 0;
|
||||
|
||||
@@ -194,7 +194,8 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
|
||||
if (pack_refs < 0)
|
||||
pack_refs = !is_bare_repository();
|
||||
|
||||
argc = parse_options(argc, argv, builtin_gc_options, builtin_gc_usage, 0);
|
||||
argc = parse_options(argc, argv, prefix, builtin_gc_options,
|
||||
builtin_gc_usage, 0);
|
||||
if (argc > 0)
|
||||
usage_with_options(builtin_gc_usage, builtin_gc_options);
|
||||
|
||||
|
||||
416
builtin-grep.c
416
builtin-grep.c
@@ -10,6 +10,7 @@
|
||||
#include "tag.h"
|
||||
#include "tree-walk.h"
|
||||
#include "builtin.h"
|
||||
#include "parse-options.h"
|
||||
#include "grep.h"
|
||||
|
||||
#ifndef NO_EXTERNAL_GREP
|
||||
@@ -20,7 +21,10 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static int builtin_grep;
|
||||
static char const * const grep_usage[] = {
|
||||
"git grep [options] [-e] <pattern> [<rev>...] [[--] path...]",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int grep_config(const char *var, const char *value, void *cb)
|
||||
{
|
||||
@@ -432,7 +436,8 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
|
||||
static int grep_cache(struct grep_opt *opt, const char **paths, int cached,
|
||||
int external_grep_allowed)
|
||||
{
|
||||
int hit = 0;
|
||||
int nr;
|
||||
@@ -444,7 +449,7 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
|
||||
* we grep through the checked-out files. It tends to
|
||||
* be a lot more optimized
|
||||
*/
|
||||
if (!cached && !builtin_grep) {
|
||||
if (!cached && external_grep_allowed) {
|
||||
hit = external_grep(opt, paths, cached);
|
||||
if (hit >= 0)
|
||||
return hit;
|
||||
@@ -560,25 +565,182 @@ static int grep_object(struct grep_opt *opt, const char **paths,
|
||||
die("unable to grep from object of type %s", typename(obj->type));
|
||||
}
|
||||
|
||||
static const char builtin_grep_usage[] =
|
||||
"git grep <option>* [-e] <pattern> <rev>* [[--] <path>...]";
|
||||
static int context_callback(const struct option *opt, const char *arg,
|
||||
int unset)
|
||||
{
|
||||
struct grep_opt *grep_opt = opt->value;
|
||||
int value;
|
||||
const char *endp;
|
||||
|
||||
static const char emsg_invalid_context_len[] =
|
||||
"%s: invalid context length argument";
|
||||
static const char emsg_missing_context_len[] =
|
||||
"missing context length argument";
|
||||
static const char emsg_missing_argument[] =
|
||||
"option requires an argument -%s";
|
||||
if (unset) {
|
||||
grep_opt->pre_context = grep_opt->post_context = 0;
|
||||
return 0;
|
||||
}
|
||||
value = strtol(arg, (char **)&endp, 10);
|
||||
if (*endp) {
|
||||
return error("switch `%c' expects a numerical value",
|
||||
opt->short_name);
|
||||
}
|
||||
grep_opt->pre_context = grep_opt->post_context = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int file_callback(const struct option *opt, const char *arg, int unset)
|
||||
{
|
||||
struct grep_opt *grep_opt = opt->value;
|
||||
FILE *patterns;
|
||||
int lno = 0;
|
||||
struct strbuf sb;
|
||||
|
||||
patterns = fopen(arg, "r");
|
||||
if (!patterns)
|
||||
die("'%s': %s", arg, strerror(errno));
|
||||
while (strbuf_getline(&sb, patterns, '\n') == 0) {
|
||||
/* ignore empty line like grep does */
|
||||
if (sb.len == 0)
|
||||
continue;
|
||||
append_grep_pattern(grep_opt, strbuf_detach(&sb, NULL), arg,
|
||||
++lno, GREP_PATTERN);
|
||||
}
|
||||
fclose(patterns);
|
||||
strbuf_release(&sb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int not_callback(const struct option *opt, const char *arg, int unset)
|
||||
{
|
||||
struct grep_opt *grep_opt = opt->value;
|
||||
append_grep_pattern(grep_opt, "--not", "command line", 0, GREP_NOT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int and_callback(const struct option *opt, const char *arg, int unset)
|
||||
{
|
||||
struct grep_opt *grep_opt = opt->value;
|
||||
append_grep_pattern(grep_opt, "--and", "command line", 0, GREP_AND);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int open_callback(const struct option *opt, const char *arg, int unset)
|
||||
{
|
||||
struct grep_opt *grep_opt = opt->value;
|
||||
append_grep_pattern(grep_opt, "(", "command line", 0, GREP_OPEN_PAREN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int close_callback(const struct option *opt, const char *arg, int unset)
|
||||
{
|
||||
struct grep_opt *grep_opt = opt->value;
|
||||
append_grep_pattern(grep_opt, ")", "command line", 0, GREP_CLOSE_PAREN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pattern_callback(const struct option *opt, const char *arg,
|
||||
int unset)
|
||||
{
|
||||
struct grep_opt *grep_opt = opt->value;
|
||||
append_grep_pattern(grep_opt, arg, "-e option", 0, GREP_PATTERN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int help_callback(const struct option *opt, const char *arg, int unset)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cmd_grep(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int hit = 0;
|
||||
int cached = 0;
|
||||
int external_grep_allowed = 1;
|
||||
int seen_dashdash = 0;
|
||||
struct grep_opt opt;
|
||||
struct object_array list = { 0, 0, NULL };
|
||||
const char **paths = NULL;
|
||||
int i;
|
||||
int dummy;
|
||||
struct option options[] = {
|
||||
OPT_BOOLEAN(0, "cached", &cached,
|
||||
"search in index instead of in the work tree"),
|
||||
OPT_GROUP(""),
|
||||
OPT_BOOLEAN('v', "invert-match", &opt.invert,
|
||||
"show non-matching lines"),
|
||||
OPT_BIT('i', "ignore-case", &opt.regflags,
|
||||
"case insensitive matching", REG_ICASE),
|
||||
OPT_BOOLEAN('w', "word-regexp", &opt.word_regexp,
|
||||
"match patterns only at word boundaries"),
|
||||
OPT_SET_INT('a', "text", &opt.binary,
|
||||
"process binary files as text", GREP_BINARY_TEXT),
|
||||
OPT_SET_INT('I', NULL, &opt.binary,
|
||||
"don't match patterns in binary files",
|
||||
GREP_BINARY_NOMATCH),
|
||||
OPT_GROUP(""),
|
||||
OPT_BIT('E', "extended-regexp", &opt.regflags,
|
||||
"use extended POSIX regular expressions", REG_EXTENDED),
|
||||
OPT_NEGBIT('G', "basic-regexp", &opt.regflags,
|
||||
"use basic POSIX regular expressions (default)",
|
||||
REG_EXTENDED),
|
||||
OPT_BOOLEAN('F', "fixed-strings", &opt.fixed,
|
||||
"interpret patterns as fixed strings"),
|
||||
OPT_GROUP(""),
|
||||
OPT_BOOLEAN('n', NULL, &opt.linenum, "show line numbers"),
|
||||
OPT_NEGBIT('h', NULL, &opt.pathname, "don't show filenames", 1),
|
||||
OPT_BIT('H', NULL, &opt.pathname, "show filenames", 1),
|
||||
OPT_NEGBIT(0, "full-name", &opt.relative,
|
||||
"show filenames relative to top directory", 1),
|
||||
OPT_BOOLEAN('l', "files-with-matches", &opt.name_only,
|
||||
"show only filenames instead of matching lines"),
|
||||
OPT_BOOLEAN(0, "name-only", &opt.name_only,
|
||||
"synonym for --files-with-matches"),
|
||||
OPT_BOOLEAN('L', "files-without-match",
|
||||
&opt.unmatch_name_only,
|
||||
"show only the names of files without match"),
|
||||
OPT_BOOLEAN('z', "null", &opt.null_following_name,
|
||||
"print NUL after filenames"),
|
||||
OPT_BOOLEAN('c', "count", &opt.count,
|
||||
"show the number of matches instead of matching lines"),
|
||||
OPT_SET_INT(0, "color", &opt.color, "highlight matches", 1),
|
||||
OPT_GROUP(""),
|
||||
OPT_CALLBACK('C', NULL, &opt, "n",
|
||||
"show <n> context lines before and after matches",
|
||||
context_callback),
|
||||
OPT_INTEGER('B', NULL, &opt.pre_context,
|
||||
"show <n> context lines before matches"),
|
||||
OPT_INTEGER('A', NULL, &opt.post_context,
|
||||
"show <n> context lines after matches"),
|
||||
OPT_NUMBER_CALLBACK(&opt, "shortcut for -C NUM",
|
||||
context_callback),
|
||||
OPT_GROUP(""),
|
||||
OPT_CALLBACK('f', NULL, &opt, "file",
|
||||
"read patterns from file", file_callback),
|
||||
{ OPTION_CALLBACK, 'e', NULL, &opt, "pattern",
|
||||
"match <pattern>", PARSE_OPT_NONEG, pattern_callback },
|
||||
{ OPTION_CALLBACK, 0, "and", &opt, NULL,
|
||||
"combine patterns specified with -e",
|
||||
PARSE_OPT_NOARG | PARSE_OPT_NONEG, and_callback },
|
||||
OPT_BOOLEAN(0, "or", &dummy, ""),
|
||||
{ OPTION_CALLBACK, 0, "not", &opt, NULL, "",
|
||||
PARSE_OPT_NOARG | PARSE_OPT_NONEG, not_callback },
|
||||
{ OPTION_CALLBACK, '(', NULL, &opt, NULL, "",
|
||||
PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
|
||||
open_callback },
|
||||
{ OPTION_CALLBACK, ')', NULL, &opt, NULL, "",
|
||||
PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
|
||||
close_callback },
|
||||
OPT_BOOLEAN(0, "all-match", &opt.all_match,
|
||||
"show only matches from files that match all patterns"),
|
||||
OPT_GROUP(""),
|
||||
#if NO_EXTERNAL_GREP
|
||||
OPT_BOOLEAN(0, "ext-grep", &external_grep_allowed,
|
||||
"allow calling of grep(1) (ignored by this build)"),
|
||||
#else
|
||||
OPT_BOOLEAN(0, "ext-grep", &external_grep_allowed,
|
||||
"allow calling of grep(1) (default)"),
|
||||
#endif
|
||||
{ OPTION_CALLBACK, 0, "help-all", &options, NULL, "show usage",
|
||||
PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, help_callback },
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
memset(&opt, 0, sizeof(opt));
|
||||
opt.prefix_length = (prefix && *prefix) ? strlen(prefix) : 0;
|
||||
@@ -603,227 +765,21 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
||||
* unrecognized non option is the beginning of the refs list
|
||||
* that continues up to the -- (if exists), and then paths.
|
||||
*/
|
||||
argc = parse_options(argc, argv, prefix, options, grep_usage,
|
||||
PARSE_OPT_KEEP_DASHDASH |
|
||||
PARSE_OPT_STOP_AT_NON_OPTION |
|
||||
PARSE_OPT_NO_INTERNAL_HELP);
|
||||
|
||||
while (1 < argc) {
|
||||
const char *arg = argv[1];
|
||||
argc--; argv++;
|
||||
if (!strcmp("--cached", arg)) {
|
||||
cached = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("--no-ext-grep", arg)) {
|
||||
builtin_grep = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("-a", arg) ||
|
||||
!strcmp("--text", arg)) {
|
||||
opt.binary = GREP_BINARY_TEXT;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("-i", arg) ||
|
||||
!strcmp("--ignore-case", arg)) {
|
||||
opt.regflags |= REG_ICASE;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("-I", arg)) {
|
||||
opt.binary = GREP_BINARY_NOMATCH;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("-v", arg) ||
|
||||
!strcmp("--invert-match", arg)) {
|
||||
opt.invert = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("-E", arg) ||
|
||||
!strcmp("--extended-regexp", arg)) {
|
||||
opt.regflags |= REG_EXTENDED;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("-F", arg) ||
|
||||
!strcmp("--fixed-strings", arg)) {
|
||||
opt.fixed = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("-G", arg) ||
|
||||
!strcmp("--basic-regexp", arg)) {
|
||||
opt.regflags &= ~REG_EXTENDED;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("-n", arg)) {
|
||||
opt.linenum = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("-h", arg)) {
|
||||
opt.pathname = 0;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("-H", arg)) {
|
||||
opt.pathname = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("-l", arg) ||
|
||||
!strcmp("--name-only", arg) ||
|
||||
!strcmp("--files-with-matches", arg)) {
|
||||
opt.name_only = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("-L", arg) ||
|
||||
!strcmp("--files-without-match", arg)) {
|
||||
opt.unmatch_name_only = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("-z", arg) ||
|
||||
!strcmp("--null", arg)) {
|
||||
opt.null_following_name = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("-c", arg) ||
|
||||
!strcmp("--count", arg)) {
|
||||
opt.count = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("-w", arg) ||
|
||||
!strcmp("--word-regexp", arg)) {
|
||||
opt.word_regexp = 1;
|
||||
continue;
|
||||
}
|
||||
if (!prefixcmp(arg, "-A") ||
|
||||
!prefixcmp(arg, "-B") ||
|
||||
!prefixcmp(arg, "-C") ||
|
||||
(arg[0] == '-' && '1' <= arg[1] && arg[1] <= '9')) {
|
||||
unsigned num;
|
||||
const char *scan;
|
||||
switch (arg[1]) {
|
||||
case 'A': case 'B': case 'C':
|
||||
if (!arg[2]) {
|
||||
if (argc <= 1)
|
||||
die(emsg_missing_context_len);
|
||||
scan = *++argv;
|
||||
argc--;
|
||||
}
|
||||
else
|
||||
scan = arg + 2;
|
||||
break;
|
||||
default:
|
||||
scan = arg + 1;
|
||||
break;
|
||||
}
|
||||
if (strtoul_ui(scan, 10, &num))
|
||||
die(emsg_invalid_context_len, scan);
|
||||
switch (arg[1]) {
|
||||
case 'A':
|
||||
opt.post_context = num;
|
||||
break;
|
||||
default:
|
||||
case 'C':
|
||||
opt.post_context = num;
|
||||
case 'B':
|
||||
opt.pre_context = num;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("-f", arg)) {
|
||||
FILE *patterns;
|
||||
int lno = 0;
|
||||
char buf[1024];
|
||||
if (argc <= 1)
|
||||
die(emsg_missing_argument, arg);
|
||||
patterns = fopen(argv[1], "r");
|
||||
if (!patterns)
|
||||
die("'%s': %s", argv[1], strerror(errno));
|
||||
while (fgets(buf, sizeof(buf), patterns)) {
|
||||
int len = strlen(buf);
|
||||
if (len && buf[len-1] == '\n')
|
||||
buf[len-1] = 0;
|
||||
/* ignore empty line like grep does */
|
||||
if (!buf[0])
|
||||
continue;
|
||||
append_grep_pattern(&opt, xstrdup(buf),
|
||||
argv[1], ++lno,
|
||||
GREP_PATTERN);
|
||||
}
|
||||
fclose(patterns);
|
||||
argv++;
|
||||
argc--;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("--not", arg)) {
|
||||
append_grep_pattern(&opt, arg, "command line", 0,
|
||||
GREP_NOT);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("--and", arg)) {
|
||||
append_grep_pattern(&opt, arg, "command line", 0,
|
||||
GREP_AND);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("--or", arg))
|
||||
continue; /* no-op */
|
||||
if (!strcmp("(", arg)) {
|
||||
append_grep_pattern(&opt, arg, "command line", 0,
|
||||
GREP_OPEN_PAREN);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(")", arg)) {
|
||||
append_grep_pattern(&opt, arg, "command line", 0,
|
||||
GREP_CLOSE_PAREN);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("--all-match", arg)) {
|
||||
opt.all_match = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("-e", arg)) {
|
||||
if (1 < argc) {
|
||||
append_grep_pattern(&opt, argv[1],
|
||||
"-e option", 0,
|
||||
GREP_PATTERN);
|
||||
argv++;
|
||||
argc--;
|
||||
continue;
|
||||
}
|
||||
die(emsg_missing_argument, arg);
|
||||
}
|
||||
if (!strcmp("--full-name", arg)) {
|
||||
opt.relative = 0;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("--color", arg)) {
|
||||
opt.color = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("--no-color", arg)) {
|
||||
opt.color = 0;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("--", arg)) {
|
||||
/* later processing wants to have this at argv[1] */
|
||||
argv--;
|
||||
argc++;
|
||||
break;
|
||||
}
|
||||
if (*arg == '-')
|
||||
usage(builtin_grep_usage);
|
||||
|
||||
/* First unrecognized non-option token */
|
||||
if (!opt.pattern_list) {
|
||||
append_grep_pattern(&opt, arg, "command line", 0,
|
||||
GREP_PATTERN);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
/* We are looking at the first path or rev;
|
||||
* it is found at argv[1] after leaving the
|
||||
* loop.
|
||||
*/
|
||||
argc++; argv--;
|
||||
break;
|
||||
}
|
||||
/* First unrecognized non-option token */
|
||||
if (argc > 0 && !opt.pattern_list) {
|
||||
append_grep_pattern(&opt, argv[0], "command line", 0,
|
||||
GREP_PATTERN);
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
|
||||
if (opt.color && !opt.color_external)
|
||||
builtin_grep = 1;
|
||||
external_grep_allowed = 0;
|
||||
if (!opt.pattern_list)
|
||||
die("no pattern given.");
|
||||
if ((opt.regflags != REG_NEWLINE) && opt.fixed)
|
||||
@@ -831,7 +787,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
||||
compile_grep_patterns(&opt);
|
||||
|
||||
/* Check revs and then paths */
|
||||
for (i = 1; i < argc; i++) {
|
||||
for (i = 0; i < argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
unsigned char sha1[20];
|
||||
/* Is it a rev? */
|
||||
@@ -874,7 +830,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
|
||||
if (!list.nr) {
|
||||
if (!cached)
|
||||
setup_work_tree();
|
||||
return !grep_cache(&opt, paths, cached);
|
||||
return !grep_cache(&opt, paths, cached, external_grep_allowed);
|
||||
}
|
||||
|
||||
if (cached)
|
||||
|
||||
@@ -80,10 +80,9 @@ static int check_emacsclient_version(void)
|
||||
ec_process.argv = argv_ec;
|
||||
ec_process.err = -1;
|
||||
ec_process.stdout_to_stderr = 1;
|
||||
if (start_command(&ec_process)) {
|
||||
fprintf(stderr, "Failed to start emacsclient.\n");
|
||||
return -1;
|
||||
}
|
||||
if (start_command(&ec_process))
|
||||
return error("Failed to start emacsclient.");
|
||||
|
||||
strbuf_read(&buffer, ec_process.err, 20);
|
||||
close(ec_process.err);
|
||||
|
||||
@@ -94,20 +93,17 @@ static int check_emacsclient_version(void)
|
||||
finish_command(&ec_process);
|
||||
|
||||
if (prefixcmp(buffer.buf, "emacsclient")) {
|
||||
fprintf(stderr, "Failed to parse emacsclient version.\n");
|
||||
strbuf_release(&buffer);
|
||||
return -1;
|
||||
return error("Failed to parse emacsclient version.");
|
||||
}
|
||||
|
||||
strbuf_remove(&buffer, 0, strlen("emacsclient"));
|
||||
version = atoi(buffer.buf);
|
||||
|
||||
if (version < 22) {
|
||||
fprintf(stderr,
|
||||
"emacsclient version '%d' too old (< 22).\n",
|
||||
version);
|
||||
strbuf_release(&buffer);
|
||||
return -1;
|
||||
return error("emacsclient version '%d' too old (< 22).",
|
||||
version);
|
||||
}
|
||||
|
||||
strbuf_release(&buffer);
|
||||
@@ -423,7 +419,7 @@ int cmd_help(int argc, const char **argv, const char *prefix)
|
||||
setup_git_directory_gently(&nongit);
|
||||
git_config(git_help_config, NULL);
|
||||
|
||||
argc = parse_options(argc, argv, builtin_help_options,
|
||||
argc = parse_options(argc, argv, prefix, builtin_help_options,
|
||||
builtin_help_usage, 0);
|
||||
|
||||
if (show_all) {
|
||||
|
||||
262
builtin-log.c
262
builtin-log.c
@@ -18,6 +18,7 @@
|
||||
#include "shortlog.h"
|
||||
#include "remote.h"
|
||||
#include "string-list.h"
|
||||
#include "parse-options.h"
|
||||
|
||||
/* Set a default date-time format for git log ("log.date" config variable) */
|
||||
static const char *default_date_mode = NULL;
|
||||
@@ -619,7 +620,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
|
||||
struct shortlog log;
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
int i;
|
||||
const char *encoding = "utf-8";
|
||||
const char *encoding = "UTF-8";
|
||||
struct diff_options opts;
|
||||
int need_8bit_cte = 0;
|
||||
struct commit *commit = NULL;
|
||||
@@ -740,27 +741,179 @@ static const char *set_outdir(const char *prefix, const char *output_directory)
|
||||
output_directory));
|
||||
}
|
||||
|
||||
static const char * const builtin_format_patch_usage[] = {
|
||||
"git format-patch [options] [<since> | <revision range>]",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int keep_subject = 0;
|
||||
|
||||
static int keep_callback(const struct option *opt, const char *arg, int unset)
|
||||
{
|
||||
((struct rev_info *)opt->value)->total = -1;
|
||||
keep_subject = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int subject_prefix = 0;
|
||||
|
||||
static int subject_prefix_callback(const struct option *opt, const char *arg,
|
||||
int unset)
|
||||
{
|
||||
subject_prefix = 1;
|
||||
((struct rev_info *)opt->value)->subject_prefix = arg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int numbered_cmdline_opt = 0;
|
||||
|
||||
static int numbered_callback(const struct option *opt, const char *arg,
|
||||
int unset)
|
||||
{
|
||||
*(int *)opt->value = numbered_cmdline_opt = unset ? 0 : 1;
|
||||
if (unset)
|
||||
auto_number = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int no_numbered_callback(const struct option *opt, const char *arg,
|
||||
int unset)
|
||||
{
|
||||
return numbered_callback(opt, arg, 1);
|
||||
}
|
||||
|
||||
static int output_directory_callback(const struct option *opt, const char *arg,
|
||||
int unset)
|
||||
{
|
||||
const char **dir = (const char **)opt->value;
|
||||
if (*dir)
|
||||
die("Two output directories?");
|
||||
*dir = arg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int thread_callback(const struct option *opt, const char *arg, int unset)
|
||||
{
|
||||
int *thread = (int *)opt->value;
|
||||
if (unset)
|
||||
*thread = 0;
|
||||
else if (!arg || !strcmp(arg, "shallow"))
|
||||
*thread = THREAD_SHALLOW;
|
||||
else if (!strcmp(arg, "deep"))
|
||||
*thread = THREAD_DEEP;
|
||||
else
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int attach_callback(const struct option *opt, const char *arg, int unset)
|
||||
{
|
||||
struct rev_info *rev = (struct rev_info *)opt->value;
|
||||
if (unset)
|
||||
rev->mime_boundary = NULL;
|
||||
else if (arg)
|
||||
rev->mime_boundary = arg;
|
||||
else
|
||||
rev->mime_boundary = git_version_string;
|
||||
rev->no_inline = unset ? 0 : 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int inline_callback(const struct option *opt, const char *arg, int unset)
|
||||
{
|
||||
struct rev_info *rev = (struct rev_info *)opt->value;
|
||||
if (unset)
|
||||
rev->mime_boundary = NULL;
|
||||
else if (arg)
|
||||
rev->mime_boundary = arg;
|
||||
else
|
||||
rev->mime_boundary = git_version_string;
|
||||
rev->no_inline = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int header_callback(const struct option *opt, const char *arg, int unset)
|
||||
{
|
||||
add_header(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cc_callback(const struct option *opt, const char *arg, int unset)
|
||||
{
|
||||
ALLOC_GROW(extra_cc, extra_cc_nr + 1, extra_cc_alloc);
|
||||
extra_cc[extra_cc_nr++] = xstrdup(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
struct commit *commit;
|
||||
struct commit **list = NULL;
|
||||
struct rev_info rev;
|
||||
int nr = 0, total, i, j;
|
||||
int nr = 0, total, i;
|
||||
int use_stdout = 0;
|
||||
int start_number = -1;
|
||||
int keep_subject = 0;
|
||||
int numbered_files = 0; /* _just_ numbers */
|
||||
int subject_prefix = 0;
|
||||
int ignore_if_in_upstream = 0;
|
||||
int cover_letter = 0;
|
||||
int boundary_count = 0;
|
||||
int no_binary_diff = 0;
|
||||
int numbered_cmdline_opt = 0;
|
||||
struct commit *origin = NULL, *head = NULL;
|
||||
const char *in_reply_to = NULL;
|
||||
struct patch_ids ids;
|
||||
char *add_signoff = NULL;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
const struct option builtin_format_patch_options[] = {
|
||||
{ OPTION_CALLBACK, 'n', "numbered", &numbered, NULL,
|
||||
"use [PATCH n/m] even with a single patch",
|
||||
PARSE_OPT_NOARG, numbered_callback },
|
||||
{ OPTION_CALLBACK, 'N', "no-numbered", &numbered, NULL,
|
||||
"use [PATCH] even with multiple patches",
|
||||
PARSE_OPT_NOARG, no_numbered_callback },
|
||||
OPT_BOOLEAN('s', "signoff", &do_signoff, "add Signed-off-by:"),
|
||||
OPT_BOOLEAN(0, "stdout", &use_stdout,
|
||||
"print patches to standard out"),
|
||||
OPT_BOOLEAN(0, "cover-letter", &cover_letter,
|
||||
"generate a cover letter"),
|
||||
OPT_BOOLEAN(0, "numbered-files", &numbered_files,
|
||||
"use simple number sequence for output file names"),
|
||||
OPT_STRING(0, "suffix", &fmt_patch_suffix, "sfx",
|
||||
"use <sfx> instead of '.patch'"),
|
||||
OPT_INTEGER(0, "start-number", &start_number,
|
||||
"start numbering patches at <n> instead of 1"),
|
||||
{ OPTION_CALLBACK, 0, "subject-prefix", &rev, "prefix",
|
||||
"Use [<prefix>] instead of [PATCH]",
|
||||
PARSE_OPT_NONEG, subject_prefix_callback },
|
||||
{ OPTION_CALLBACK, 'o', "output-directory", &output_directory,
|
||||
"dir", "store resulting files in <dir>",
|
||||
PARSE_OPT_NONEG, output_directory_callback },
|
||||
{ OPTION_CALLBACK, 'k', "keep-subject", &rev, NULL,
|
||||
"don't strip/add [PATCH]",
|
||||
PARSE_OPT_NOARG | PARSE_OPT_NONEG, keep_callback },
|
||||
OPT_BOOLEAN(0, "no-binary", &no_binary_diff,
|
||||
"don't output binary diffs"),
|
||||
OPT_BOOLEAN(0, "ignore-if-in-upstream", &ignore_if_in_upstream,
|
||||
"don't include a patch matching a commit upstream"),
|
||||
OPT_GROUP("Messaging"),
|
||||
{ OPTION_CALLBACK, 0, "add-header", NULL, "header",
|
||||
"add email header", PARSE_OPT_NONEG,
|
||||
header_callback },
|
||||
{ OPTION_CALLBACK, 0, "cc", NULL, "email", "add Cc: header",
|
||||
PARSE_OPT_NONEG, cc_callback },
|
||||
OPT_STRING(0, "in-reply-to", &in_reply_to, "message-id",
|
||||
"make first mail a reply to <message-id>"),
|
||||
{ OPTION_CALLBACK, 0, "attach", &rev, "boundary",
|
||||
"attach the patch", PARSE_OPT_OPTARG,
|
||||
attach_callback },
|
||||
{ OPTION_CALLBACK, 0, "inline", &rev, "boundary",
|
||||
"inline the patch",
|
||||
PARSE_OPT_OPTARG | PARSE_OPT_NONEG,
|
||||
inline_callback },
|
||||
{ OPTION_CALLBACK, 0, "thread", &thread, "style",
|
||||
"enable message threading, styles: shallow, deep",
|
||||
PARSE_OPT_OPTARG, thread_callback },
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
git_config(git_format_config, NULL);
|
||||
init_revisions(&rev, prefix);
|
||||
@@ -783,102 +936,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
* like "git format-patch -o a123 HEAD^.." may fail; a123 is
|
||||
* possibly a valid SHA1.
|
||||
*/
|
||||
for (i = 1, j = 1; i < argc; i++) {
|
||||
if (!strcmp(argv[i], "--stdout"))
|
||||
use_stdout = 1;
|
||||
else if (!strcmp(argv[i], "-n") ||
|
||||
!strcmp(argv[i], "--numbered")) {
|
||||
numbered = 1;
|
||||
numbered_cmdline_opt = 1;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-N") ||
|
||||
!strcmp(argv[i], "--no-numbered")) {
|
||||
numbered = 0;
|
||||
auto_number = 0;
|
||||
}
|
||||
else if (!prefixcmp(argv[i], "--start-number="))
|
||||
start_number = strtol(argv[i] + 15, NULL, 10);
|
||||
else if (!strcmp(argv[i], "--numbered-files"))
|
||||
numbered_files = 1;
|
||||
else if (!strcmp(argv[i], "--start-number")) {
|
||||
i++;
|
||||
if (i == argc)
|
||||
die("Need a number for --start-number");
|
||||
start_number = strtol(argv[i], NULL, 10);
|
||||
}
|
||||
else if (!prefixcmp(argv[i], "--cc=")) {
|
||||
ALLOC_GROW(extra_cc, extra_cc_nr + 1, extra_cc_alloc);
|
||||
extra_cc[extra_cc_nr++] = xstrdup(argv[i] + 5);
|
||||
}
|
||||
else if (!strcmp(argv[i], "-k") ||
|
||||
!strcmp(argv[i], "--keep-subject")) {
|
||||
keep_subject = 1;
|
||||
rev.total = -1;
|
||||
}
|
||||
else if (!strcmp(argv[i], "--output-directory") ||
|
||||
!strcmp(argv[i], "-o")) {
|
||||
i++;
|
||||
if (argc <= i)
|
||||
die("Which directory?");
|
||||
if (output_directory)
|
||||
die("Two output directories?");
|
||||
output_directory = argv[i];
|
||||
}
|
||||
else if (!strcmp(argv[i], "--signoff") ||
|
||||
!strcmp(argv[i], "-s")) {
|
||||
do_signoff = 1;
|
||||
}
|
||||
else if (!strcmp(argv[i], "--attach")) {
|
||||
rev.mime_boundary = git_version_string;
|
||||
rev.no_inline = 1;
|
||||
}
|
||||
else if (!prefixcmp(argv[i], "--attach=")) {
|
||||
rev.mime_boundary = argv[i] + 9;
|
||||
rev.no_inline = 1;
|
||||
}
|
||||
else if (!strcmp(argv[i], "--no-attach")) {
|
||||
rev.mime_boundary = NULL;
|
||||
rev.no_inline = 0;
|
||||
}
|
||||
else if (!strcmp(argv[i], "--inline")) {
|
||||
rev.mime_boundary = git_version_string;
|
||||
rev.no_inline = 0;
|
||||
}
|
||||
else if (!prefixcmp(argv[i], "--inline=")) {
|
||||
rev.mime_boundary = argv[i] + 9;
|
||||
rev.no_inline = 0;
|
||||
}
|
||||
else if (!strcmp(argv[i], "--ignore-if-in-upstream"))
|
||||
ignore_if_in_upstream = 1;
|
||||
else if (!strcmp(argv[i], "--thread")
|
||||
|| !strcmp(argv[i], "--thread=shallow"))
|
||||
thread = THREAD_SHALLOW;
|
||||
else if (!strcmp(argv[i], "--thread=deep"))
|
||||
thread = THREAD_DEEP;
|
||||
else if (!strcmp(argv[i], "--no-thread"))
|
||||
thread = 0;
|
||||
else if (!prefixcmp(argv[i], "--in-reply-to="))
|
||||
in_reply_to = argv[i] + 14;
|
||||
else if (!strcmp(argv[i], "--in-reply-to")) {
|
||||
i++;
|
||||
if (i == argc)
|
||||
die("Need a Message-Id for --in-reply-to");
|
||||
in_reply_to = argv[i];
|
||||
} else if (!prefixcmp(argv[i], "--subject-prefix=")) {
|
||||
subject_prefix = 1;
|
||||
rev.subject_prefix = argv[i] + 17;
|
||||
} else if (!prefixcmp(argv[i], "--suffix="))
|
||||
fmt_patch_suffix = argv[i] + 9;
|
||||
else if (!strcmp(argv[i], "--cover-letter"))
|
||||
cover_letter = 1;
|
||||
else if (!strcmp(argv[i], "--no-binary"))
|
||||
no_binary_diff = 1;
|
||||
else if (!prefixcmp(argv[i], "--add-header="))
|
||||
add_header(argv[i] + 13);
|
||||
else
|
||||
argv[j++] = argv[i];
|
||||
}
|
||||
argc = j;
|
||||
argc = parse_options(argc, argv, prefix, builtin_format_patch_options,
|
||||
builtin_format_patch_usage,
|
||||
PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN);
|
||||
|
||||
if (do_signoff) {
|
||||
const char *committer;
|
||||
|
||||
@@ -454,7 +454,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
|
||||
OPT_BIT(0, "directory", &dir.flags,
|
||||
"show 'other' directories' name only",
|
||||
DIR_SHOW_OTHER_DIRECTORIES),
|
||||
OPT_BIT(0, "no-empty-directory", &dir.flags,
|
||||
OPT_NEGBIT(0, "empty-directory", &dir.flags,
|
||||
"don't show empty directories",
|
||||
DIR_HIDE_EMPTY_DIRECTORIES),
|
||||
OPT_BOOLEAN('u', "unmerged", &show_unmerged,
|
||||
@@ -486,7 +486,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
|
||||
prefix_offset = strlen(prefix);
|
||||
git_config(git_default_config, NULL);
|
||||
|
||||
argc = parse_options(argc, argv, builtin_ls_files_options,
|
||||
argc = parse_options(argc, argv, prefix, builtin_ls_files_options,
|
||||
ls_files_usage, 0);
|
||||
if (show_tag || show_valid_bit) {
|
||||
tag_cached = "H ";
|
||||
|
||||
@@ -193,8 +193,7 @@ static void handle_content_type(struct strbuf *line)
|
||||
*content_top = boundary;
|
||||
boundary = NULL;
|
||||
}
|
||||
if (slurp_attr(line->buf, "charset=", &charset))
|
||||
strbuf_tolower(&charset);
|
||||
slurp_attr(line->buf, "charset=", &charset);
|
||||
|
||||
if (boundary) {
|
||||
strbuf_release(boundary);
|
||||
@@ -481,7 +480,7 @@ static const char *guess_charset(const struct strbuf *line, const char *target_c
|
||||
if (is_utf8(line->buf))
|
||||
return NULL;
|
||||
}
|
||||
return "latin1";
|
||||
return "ISO8859-1";
|
||||
}
|
||||
|
||||
static void convert_to_utf8(struct strbuf *line, const char *charset)
|
||||
@@ -494,7 +493,7 @@ static void convert_to_utf8(struct strbuf *line, const char *charset)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcmp(metainfo_charset, charset))
|
||||
if (!strcasecmp(metainfo_charset, charset))
|
||||
return;
|
||||
out = reencode_string(line->buf, metainfo_charset, charset);
|
||||
if (!out)
|
||||
@@ -550,7 +549,6 @@ static int decode_header_bq(struct strbuf *it)
|
||||
if (cp + 3 - it->buf > it->len)
|
||||
goto decode_header_bq_out;
|
||||
strbuf_add(&charset_q, ep, cp - ep);
|
||||
strbuf_tolower(&charset_q);
|
||||
|
||||
encoding = cp[1];
|
||||
if (!encoding || cp[2] != '?')
|
||||
@@ -944,7 +942,7 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix)
|
||||
*/
|
||||
git_config(git_default_config, NULL);
|
||||
|
||||
def_charset = (git_commit_encoding ? git_commit_encoding : "utf-8");
|
||||
def_charset = (git_commit_encoding ? git_commit_encoding : "UTF-8");
|
||||
metainfo_charset = def_charset;
|
||||
|
||||
while (1 < argc && argv[1][0] == '-') {
|
||||
|
||||
@@ -53,7 +53,7 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix)
|
||||
};
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
argc = parse_options(argc, argv, options, merge_base_usage, 0);
|
||||
argc = parse_options(argc, argv, prefix, options, merge_base_usage, 0);
|
||||
if (argc < 2)
|
||||
usage_with_options(merge_base_usage, options);
|
||||
rev = xmalloc(argc * sizeof(*rev));
|
||||
|
||||
@@ -48,7 +48,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
|
||||
merge_style = git_xmerge_style;
|
||||
}
|
||||
|
||||
argc = parse_options(argc, argv, options, merge_file_usage, 0);
|
||||
argc = parse_options(argc, argv, prefix, options, merge_file_usage, 0);
|
||||
if (argc != 3)
|
||||
usage_with_options(merge_file_usage, options);
|
||||
if (quiet) {
|
||||
|
||||
@@ -462,7 +462,7 @@ static int git_merge_config(const char *k, const char *v, void *cb)
|
||||
argv = xrealloc(argv, sizeof(*argv) * (argc + 2));
|
||||
memmove(argv + 1, argv, sizeof(*argv) * (argc + 1));
|
||||
argc++;
|
||||
parse_options(argc, argv, builtin_merge_options,
|
||||
parse_options(argc, argv, NULL, builtin_merge_options,
|
||||
builtin_merge_usage, 0);
|
||||
free(buf);
|
||||
}
|
||||
@@ -836,8 +836,11 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
||||
struct commit_list **remotes = &remoteheads;
|
||||
|
||||
setup_work_tree();
|
||||
if (file_exists(git_path("MERGE_HEAD")))
|
||||
die("You have not concluded your merge. (MERGE_HEAD exists)");
|
||||
if (read_cache_unmerged())
|
||||
die("You are in the middle of a conflicted merge.");
|
||||
die("You are in the middle of a conflicted merge."
|
||||
" (index unmerged)");
|
||||
|
||||
/*
|
||||
* Check if we are _not_ on a detached HEAD, i.e. if there is a
|
||||
@@ -855,7 +858,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
|
||||
if (diff_use_color_default == -1)
|
||||
diff_use_color_default = git_use_color_default;
|
||||
|
||||
argc = parse_options(argc, argv, builtin_merge_options,
|
||||
argc = parse_options(argc, argv, prefix, builtin_merge_options,
|
||||
builtin_merge_usage, 0);
|
||||
if (verbosity < 0)
|
||||
show_diffstat = 0;
|
||||
|
||||
190
builtin-mktree.c
Normal file
190
builtin-mktree.c
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* GIT - the stupid content tracker
|
||||
*
|
||||
* Copyright (c) Junio C Hamano, 2006, 2009
|
||||
*/
|
||||
#include "builtin.h"
|
||||
#include "quote.h"
|
||||
#include "tree.h"
|
||||
#include "parse-options.h"
|
||||
|
||||
static struct treeent {
|
||||
unsigned mode;
|
||||
unsigned char sha1[20];
|
||||
int len;
|
||||
char name[FLEX_ARRAY];
|
||||
} **entries;
|
||||
static int alloc, used;
|
||||
|
||||
static void append_to_tree(unsigned mode, unsigned char *sha1, char *path)
|
||||
{
|
||||
struct treeent *ent;
|
||||
int len = strlen(path);
|
||||
if (strchr(path, '/'))
|
||||
die("path %s contains slash", path);
|
||||
|
||||
if (alloc <= used) {
|
||||
alloc = alloc_nr(used);
|
||||
entries = xrealloc(entries, sizeof(*entries) * alloc);
|
||||
}
|
||||
ent = entries[used++] = xmalloc(sizeof(**entries) + len + 1);
|
||||
ent->mode = mode;
|
||||
ent->len = len;
|
||||
hashcpy(ent->sha1, sha1);
|
||||
memcpy(ent->name, path, len+1);
|
||||
}
|
||||
|
||||
static int ent_compare(const void *a_, const void *b_)
|
||||
{
|
||||
struct treeent *a = *(struct treeent **)a_;
|
||||
struct treeent *b = *(struct treeent **)b_;
|
||||
return base_name_compare(a->name, a->len, a->mode,
|
||||
b->name, b->len, b->mode);
|
||||
}
|
||||
|
||||
static void write_tree(unsigned char *sha1)
|
||||
{
|
||||
struct strbuf buf;
|
||||
size_t size;
|
||||
int i;
|
||||
|
||||
qsort(entries, used, sizeof(*entries), ent_compare);
|
||||
for (size = i = 0; i < used; i++)
|
||||
size += 32 + entries[i]->len;
|
||||
|
||||
strbuf_init(&buf, size);
|
||||
for (i = 0; i < used; i++) {
|
||||
struct treeent *ent = entries[i];
|
||||
strbuf_addf(&buf, "%o %s%c", ent->mode, ent->name, '\0');
|
||||
strbuf_add(&buf, ent->sha1, 20);
|
||||
}
|
||||
|
||||
write_sha1_file(buf.buf, buf.len, tree_type, sha1);
|
||||
}
|
||||
|
||||
static const char *mktree_usage[] = {
|
||||
"git mktree [-z] [--missing] [--batch]",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void mktree_line(char *buf, size_t len, int line_termination, int allow_missing)
|
||||
{
|
||||
char *ptr, *ntr;
|
||||
unsigned mode;
|
||||
enum object_type mode_type; /* object type derived from mode */
|
||||
enum object_type obj_type; /* object type derived from sha */
|
||||
char *path;
|
||||
unsigned char sha1[20];
|
||||
|
||||
ptr = buf;
|
||||
/*
|
||||
* Read non-recursive ls-tree output format:
|
||||
* mode SP type SP sha1 TAB name
|
||||
*/
|
||||
mode = strtoul(ptr, &ntr, 8);
|
||||
if (ptr == ntr || !ntr || *ntr != ' ')
|
||||
die("input format error: %s", buf);
|
||||
ptr = ntr + 1; /* type */
|
||||
ntr = strchr(ptr, ' ');
|
||||
if (!ntr || buf + len <= ntr + 40 ||
|
||||
ntr[41] != '\t' ||
|
||||
get_sha1_hex(ntr + 1, sha1))
|
||||
die("input format error: %s", buf);
|
||||
|
||||
/* It is perfectly normal if we do not have a commit from a submodule */
|
||||
if (S_ISGITLINK(mode))
|
||||
allow_missing = 1;
|
||||
|
||||
|
||||
*ntr++ = 0; /* now at the beginning of SHA1 */
|
||||
|
||||
path = ntr + 41; /* at the beginning of name */
|
||||
if (line_termination && path[0] == '"') {
|
||||
struct strbuf p_uq = STRBUF_INIT;
|
||||
if (unquote_c_style(&p_uq, path, NULL))
|
||||
die("invalid quoting");
|
||||
path = strbuf_detach(&p_uq, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Object type is redundantly derivable three ways.
|
||||
* These should all agree.
|
||||
*/
|
||||
mode_type = object_type(mode);
|
||||
if (mode_type != type_from_string(ptr)) {
|
||||
die("entry '%s' object type (%s) doesn't match mode type (%s)",
|
||||
path, ptr, typename(mode_type));
|
||||
}
|
||||
|
||||
/* Check the type of object identified by sha1 */
|
||||
obj_type = sha1_object_info(sha1, NULL);
|
||||
if (obj_type < 0) {
|
||||
if (allow_missing) {
|
||||
; /* no problem - missing objects are presumed to be of the right type */
|
||||
} else {
|
||||
die("entry '%s' object %s is unavailable", path, sha1_to_hex(sha1));
|
||||
}
|
||||
} else {
|
||||
if (obj_type != mode_type) {
|
||||
/*
|
||||
* The object exists but is of the wrong type.
|
||||
* This is a problem regardless of allow_missing
|
||||
* because the new tree entry will never be correct.
|
||||
*/
|
||||
die("entry '%s' object %s is a %s but specified type was (%s)",
|
||||
path, sha1_to_hex(sha1), typename(obj_type), typename(mode_type));
|
||||
}
|
||||
}
|
||||
|
||||
append_to_tree(mode, sha1, path);
|
||||
}
|
||||
|
||||
int cmd_mktree(int ac, const char **av, const char *prefix)
|
||||
{
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
unsigned char sha1[20];
|
||||
int line_termination = '\n';
|
||||
int allow_missing = 0;
|
||||
int is_batch_mode = 0;
|
||||
int got_eof = 0;
|
||||
|
||||
const struct option option[] = {
|
||||
OPT_SET_INT('z', NULL, &line_termination, "input is NUL terminated", '\0'),
|
||||
OPT_SET_INT( 0 , "missing", &allow_missing, "allow missing objects", 1),
|
||||
OPT_SET_INT( 0 , "batch", &is_batch_mode, "allow creation of more than one tree", 1),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
ac = parse_options(ac, av, prefix, option, mktree_usage, 0);
|
||||
|
||||
while (!got_eof) {
|
||||
while (1) {
|
||||
if (strbuf_getline(&sb, stdin, line_termination) == EOF) {
|
||||
got_eof = 1;
|
||||
break;
|
||||
}
|
||||
if (sb.buf[0] == '\0') {
|
||||
/* empty lines denote tree boundaries in batch mode */
|
||||
if (is_batch_mode)
|
||||
break;
|
||||
die("input format error: (blank line only valid in batch mode)");
|
||||
}
|
||||
mktree_line(sb.buf, sb.len, line_termination, allow_missing);
|
||||
}
|
||||
if (is_batch_mode && got_eof && used < 1) {
|
||||
/*
|
||||
* Execution gets here if the last tree entry is terminated with a
|
||||
* new-line. The final new-line has been made optional to be
|
||||
* consistent with the original non-batch behaviour of mktree.
|
||||
*/
|
||||
; /* skip creating an empty tree */
|
||||
} else {
|
||||
write_tree(sha1);
|
||||
puts(sha1_to_hex(sha1));
|
||||
fflush(stdout);
|
||||
}
|
||||
used=0; /* reset tree entry buffer for re-use in batch mode */
|
||||
}
|
||||
strbuf_release(&sb);
|
||||
exit(0);
|
||||
}
|
||||
@@ -72,7 +72,8 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
|
||||
if (read_cache() < 0)
|
||||
die("index file corrupt");
|
||||
|
||||
argc = parse_options(argc, argv, builtin_mv_options, builtin_mv_usage, 0);
|
||||
argc = parse_options(argc, argv, prefix, builtin_mv_options,
|
||||
builtin_mv_usage, 0);
|
||||
if (--argc < 1)
|
||||
usage_with_options(builtin_mv_usage, builtin_mv_options);
|
||||
|
||||
|
||||
@@ -238,7 +238,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
|
||||
};
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
argc = parse_options(argc, argv, opts, name_rev_usage, 0);
|
||||
argc = parse_options(argc, argv, prefix, opts, name_rev_usage, 0);
|
||||
if (!!all + !!transform_stdin + !!argc > 1) {
|
||||
error("Specify either a list, or --all, not both!");
|
||||
usage_with_options(name_rev_usage, opts);
|
||||
|
||||
@@ -15,7 +15,7 @@ int cmd_pack_refs(int argc, const char **argv, const char *prefix)
|
||||
OPT_BIT(0, "prune", &flags, "prune loose refs (default)", PACK_REFS_PRUNE),
|
||||
OPT_END(),
|
||||
};
|
||||
if (parse_options(argc, argv, opts, pack_refs_usage, 0))
|
||||
if (parse_options(argc, argv, prefix, opts, pack_refs_usage, 0))
|
||||
usage_with_options(pack_refs_usage, opts);
|
||||
return pack_refs(flags);
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
|
||||
save_commit_buffer = 0;
|
||||
init_revisions(&revs, prefix);
|
||||
|
||||
argc = parse_options(argc, argv, options, prune_usage, 0);
|
||||
argc = parse_options(argc, argv, prefix, options, prune_usage, 0);
|
||||
while (argc--) {
|
||||
unsigned char sha1[20];
|
||||
const char *name = *argv++;
|
||||
|
||||
@@ -198,7 +198,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
argc = parse_options(argc, argv, options, push_usage, 0);
|
||||
argc = parse_options(argc, argv, prefix, options, push_usage, 0);
|
||||
|
||||
if (tags)
|
||||
add_refspec("refs/tags/*");
|
||||
|
||||
@@ -192,7 +192,6 @@ static int run_receive_hook(const char *hook_name)
|
||||
static int run_update_hook(struct command *cmd)
|
||||
{
|
||||
static const char update_hook[] = "hooks/update";
|
||||
struct child_process proc;
|
||||
const char *argv[5];
|
||||
|
||||
if (access(update_hook, X_OK) < 0)
|
||||
@@ -204,12 +203,9 @@ static int run_update_hook(struct command *cmd)
|
||||
argv[3] = sha1_to_hex(cmd->new_sha1);
|
||||
argv[4] = NULL;
|
||||
|
||||
memset(&proc, 0, sizeof(proc));
|
||||
proc.argv = argv;
|
||||
proc.no_stdin = 1;
|
||||
proc.stdout_to_stderr = 1;
|
||||
|
||||
return hook_status(run_command(&proc), update_hook);
|
||||
return hook_status(run_command_v_opt(argv, RUN_COMMAND_NO_STDIN |
|
||||
RUN_COMMAND_STDOUT_TO_STDERR),
|
||||
update_hook);
|
||||
}
|
||||
|
||||
static int is_ref_checked_out(const char *ref)
|
||||
|
||||
@@ -79,7 +79,8 @@ static int add(int argc, const char **argv)
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
argc = parse_options(argc, argv, options, builtin_remote_usage, 0);
|
||||
argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
|
||||
0);
|
||||
|
||||
if (argc < 2)
|
||||
usage_with_options(builtin_remote_usage, options);
|
||||
@@ -294,17 +295,14 @@ static int get_push_ref_states(const struct ref *remote_refs,
|
||||
struct ref_states *states)
|
||||
{
|
||||
struct remote *remote = states->remote;
|
||||
struct ref *ref, *local_refs, *push_map, **push_tail;
|
||||
struct ref *ref, *local_refs, *push_map;
|
||||
if (remote->mirror)
|
||||
return 0;
|
||||
|
||||
local_refs = get_local_heads();
|
||||
push_map = copy_ref_list(remote_refs);
|
||||
|
||||
push_tail = &push_map;
|
||||
while (*push_tail)
|
||||
push_tail = &((*push_tail)->next);
|
||||
match_refs(local_refs, push_map, &push_tail, remote->push_refspec_nr,
|
||||
match_refs(local_refs, &push_map, remote->push_refspec_nr,
|
||||
remote->push_refspec, MATCH_REFS_NONE);
|
||||
|
||||
states->push.strdup_strings = 1;
|
||||
@@ -986,7 +984,8 @@ static int show(int argc, const char **argv)
|
||||
struct string_list info_list = { NULL, 0, 0, 0 };
|
||||
struct show_info info;
|
||||
|
||||
argc = parse_options(argc, argv, options, builtin_remote_usage, 0);
|
||||
argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
|
||||
0);
|
||||
|
||||
if (argc < 1)
|
||||
return show_all();
|
||||
@@ -1003,9 +1002,12 @@ static int show(int argc, const char **argv)
|
||||
|
||||
get_remote_ref_states(*argv, &states, query_flag);
|
||||
|
||||
printf("* remote %s\n URL: %s\n", *argv,
|
||||
states.remote->url_nr > 0 ?
|
||||
states.remote->url[0] : "(no URL)");
|
||||
printf("* remote %s\n", *argv);
|
||||
if (states.remote->url_nr) {
|
||||
for (i=0; i < states.remote->url_nr; i++)
|
||||
printf(" URL: %s\n", states.remote->url[i]);
|
||||
} else
|
||||
printf(" URL: %s\n", "(no URL)");
|
||||
if (no_query)
|
||||
printf(" HEAD branch: (not queried)\n");
|
||||
else if (!states.heads.nr)
|
||||
@@ -1076,7 +1078,8 @@ static int set_head(int argc, const char **argv)
|
||||
"delete refs/remotes/<name>/HEAD"),
|
||||
OPT_END()
|
||||
};
|
||||
argc = parse_options(argc, argv, options, builtin_remote_usage, 0);
|
||||
argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
|
||||
0);
|
||||
if (argc)
|
||||
strbuf_addf(&buf, "refs/remotes/%s/HEAD", argv[0]);
|
||||
|
||||
@@ -1130,7 +1133,8 @@ static int prune(int argc, const char **argv)
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
argc = parse_options(argc, argv, options, builtin_remote_usage, 0);
|
||||
argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
|
||||
0);
|
||||
|
||||
if (argc < 1)
|
||||
usage_with_options(builtin_remote_usage, options);
|
||||
@@ -1220,7 +1224,7 @@ static int update(int argc, const char **argv)
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
argc = parse_options(argc, argv, options, builtin_remote_usage,
|
||||
argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
|
||||
PARSE_OPT_KEEP_ARGV0);
|
||||
if (argc < 2) {
|
||||
argc = 2;
|
||||
@@ -1306,7 +1310,7 @@ int cmd_remote(int argc, const char **argv, const char *prefix)
|
||||
};
|
||||
int result;
|
||||
|
||||
argc = parse_options(argc, argv, options, builtin_remote_usage,
|
||||
argc = parse_options(argc, argv, prefix, options, builtin_remote_usage,
|
||||
PARSE_OPT_STOP_AT_NON_OPTION);
|
||||
|
||||
if (argc < 1)
|
||||
|
||||
@@ -203,7 +203,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
|
||||
argc = parse_options(argc, argv, options, git_reset_usage,
|
||||
argc = parse_options(argc, argv, prefix, options, git_reset_usage,
|
||||
PARSE_OPT_KEEP_DASHDASH);
|
||||
reflog_action = args_to_str(argv);
|
||||
setenv("GIT_REFLOG_ACTION", reflog_action, 0);
|
||||
|
||||
@@ -211,7 +211,7 @@ static inline int exp2i(int n)
|
||||
*
|
||||
* and P(2^n + x) < 0.5 means 2^n < 3x
|
||||
*/
|
||||
static int estimate_bisect_steps(int all)
|
||||
int estimate_bisect_steps(int all)
|
||||
{
|
||||
int n, x, e;
|
||||
|
||||
@@ -225,20 +225,37 @@ static int estimate_bisect_steps(int all)
|
||||
return (e < 3 * x) ? n : n - 1;
|
||||
}
|
||||
|
||||
static void show_tried_revs(struct commit_list *tried, int stringed)
|
||||
void print_commit_list(struct commit_list *list,
|
||||
const char *format_cur,
|
||||
const char *format_last)
|
||||
{
|
||||
for ( ; list; list = list->next) {
|
||||
const char *format = list->next ? format_cur : format_last;
|
||||
printf(format, sha1_to_hex(list->item->object.sha1));
|
||||
}
|
||||
}
|
||||
|
||||
static void show_tried_revs(struct commit_list *tried)
|
||||
{
|
||||
printf("bisect_tried='");
|
||||
for (;tried; tried = tried->next) {
|
||||
char *format = tried->next ? "%s|" : "%s";
|
||||
printf(format, sha1_to_hex(tried->item->object.sha1));
|
||||
}
|
||||
printf(stringed ? "' &&\n" : "'\n");
|
||||
print_commit_list(tried, "%s|", "%s");
|
||||
printf("'\n");
|
||||
}
|
||||
|
||||
static void print_var_str(const char *var, const char *val)
|
||||
{
|
||||
printf("%s='%s'\n", var, val);
|
||||
}
|
||||
|
||||
static void print_var_int(const char *var, int val)
|
||||
{
|
||||
printf("%s=%d\n", var, val);
|
||||
}
|
||||
|
||||
int show_bisect_vars(struct rev_list_info *info, int reaches, int all)
|
||||
{
|
||||
int cnt, flags = info->bisect_show_flags;
|
||||
char hex[41] = "", *format;
|
||||
char hex[41] = "";
|
||||
struct commit_list *tried;
|
||||
struct rev_info *revs = info->revs;
|
||||
|
||||
@@ -269,28 +286,14 @@ int show_bisect_vars(struct rev_list_info *info, int reaches, int all)
|
||||
}
|
||||
|
||||
if (flags & BISECT_SHOW_TRIED)
|
||||
show_tried_revs(tried, flags & BISECT_SHOW_STRINGED);
|
||||
format = (flags & BISECT_SHOW_STRINGED) ?
|
||||
"bisect_rev=%s &&\n"
|
||||
"bisect_nr=%d &&\n"
|
||||
"bisect_good=%d &&\n"
|
||||
"bisect_bad=%d &&\n"
|
||||
"bisect_all=%d &&\n"
|
||||
"bisect_steps=%d\n"
|
||||
:
|
||||
"bisect_rev=%s\n"
|
||||
"bisect_nr=%d\n"
|
||||
"bisect_good=%d\n"
|
||||
"bisect_bad=%d\n"
|
||||
"bisect_all=%d\n"
|
||||
"bisect_steps=%d\n";
|
||||
printf(format,
|
||||
hex,
|
||||
cnt - 1,
|
||||
all - reaches - 1,
|
||||
reaches - 1,
|
||||
all,
|
||||
estimate_bisect_steps(all));
|
||||
show_tried_revs(tried);
|
||||
|
||||
print_var_str("bisect_rev", hex);
|
||||
print_var_int("bisect_nr", cnt - 1);
|
||||
print_var_int("bisect_good", all - reaches - 1);
|
||||
print_var_int("bisect_bad", reaches - 1);
|
||||
print_var_int("bisect_all", all);
|
||||
print_var_int("bisect_steps", estimate_bisect_steps(all));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -318,7 +318,7 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
|
||||
int onb = 0, osz = 0, unb = 0, usz = 0;
|
||||
|
||||
strbuf_addstr(&parsed, "set --");
|
||||
argc = parse_options(argc, argv, parseopt_opts, parseopt_usage,
|
||||
argc = parse_options(argc, argv, prefix, parseopt_opts, parseopt_usage,
|
||||
PARSE_OPT_KEEP_DASHDASH);
|
||||
if (argc < 1 || strcmp(argv[0], "--"))
|
||||
usage_with_options(parseopt_usage, parseopt_opts);
|
||||
@@ -393,7 +393,7 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
|
||||
/* put an OPT_END() */
|
||||
ALLOC_GROW(opts, onb + 1, osz);
|
||||
memset(opts + onb, 0, sizeof(opts[onb]));
|
||||
argc = parse_options(argc, argv, opts, usage,
|
||||
argc = parse_options(argc, argv, prefix, opts, usage,
|
||||
keep_dashdash ? PARSE_OPT_KEEP_DASHDASH : 0);
|
||||
|
||||
strbuf_addf(&parsed, " --");
|
||||
@@ -402,6 +402,18 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_sq_quote(int argc, const char **argv)
|
||||
{
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
|
||||
if (argc)
|
||||
sq_quote_argv(&buf, argv, 0);
|
||||
printf("%s\n", buf.buf);
|
||||
strbuf_release(&buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void die_no_single_rev(int quiet)
|
||||
{
|
||||
if (quiet)
|
||||
@@ -419,6 +431,9 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
|
||||
if (argc > 1 && !strcmp("--parseopt", argv[1]))
|
||||
return cmd_parseopt(argc - 1, argv + 1, prefix);
|
||||
|
||||
if (argc > 1 && !strcmp("--sq-quote", argv[1]))
|
||||
return cmd_sq_quote(argc - 2, argv + 2);
|
||||
|
||||
prefix = setup_git_directory();
|
||||
git_config(git_default_config, NULL);
|
||||
for (i = 1; i < argc; i++) {
|
||||
|
||||
@@ -60,7 +60,7 @@ static void parse_args(int argc, const char **argv)
|
||||
OPT_END(),
|
||||
};
|
||||
|
||||
if (parse_options(argc, argv, options, usage_str, 0) != 1)
|
||||
if (parse_options(argc, argv, NULL, options, usage_str, 0) != 1)
|
||||
usage_with_options(usage_str, options);
|
||||
arg = argv[0];
|
||||
|
||||
@@ -323,9 +323,9 @@ static int revert_or_cherry_pick(int argc, const char **argv)
|
||||
|
||||
encoding = get_encoding(message);
|
||||
if (!encoding)
|
||||
encoding = "utf-8";
|
||||
encoding = "UTF-8";
|
||||
if (!git_commit_encoding)
|
||||
git_commit_encoding = "utf-8";
|
||||
git_commit_encoding = "UTF-8";
|
||||
if ((reencoded_message = reencode_string(message,
|
||||
git_commit_encoding, encoding)))
|
||||
message = reencoded_message;
|
||||
|
||||
@@ -157,7 +157,8 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
|
||||
argc = parse_options(argc, argv, builtin_rm_options, builtin_rm_usage, 0);
|
||||
argc = parse_options(argc, argv, prefix, builtin_rm_options,
|
||||
builtin_rm_usage, 0);
|
||||
if (!argc)
|
||||
usage_with_options(builtin_rm_usage, builtin_rm_options);
|
||||
|
||||
|
||||
@@ -178,9 +178,9 @@ static void print_ref_status(char flag, const char *summary, struct ref *to, str
|
||||
{
|
||||
fprintf(stderr, " %c %-*s ", flag, SUMMARY_WIDTH, summary);
|
||||
if (from)
|
||||
fprintf(stderr, "%s -> %s", prettify_ref(from), prettify_ref(to));
|
||||
fprintf(stderr, "%s -> %s", prettify_refname(from->name), prettify_refname(to->name));
|
||||
else
|
||||
fputs(prettify_ref(to), stderr);
|
||||
fputs(prettify_refname(to->name), stderr);
|
||||
if (msg) {
|
||||
fputs(" (", stderr);
|
||||
fputs(msg, stderr);
|
||||
@@ -473,7 +473,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
|
||||
int fd[2];
|
||||
struct child_process *conn;
|
||||
struct extra_have_objects extra_have;
|
||||
struct ref *remote_refs, **remote_tail, *local_refs;
|
||||
struct ref *remote_refs, *local_refs;
|
||||
int ret;
|
||||
int send_all = 0;
|
||||
const char *receivepack = "git-receive-pack";
|
||||
@@ -567,13 +567,8 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
|
||||
flags |= MATCH_REFS_MIRROR;
|
||||
|
||||
/* match them up */
|
||||
remote_tail = &remote_refs;
|
||||
while (*remote_tail)
|
||||
remote_tail = &((*remote_tail)->next);
|
||||
if (match_refs(local_refs, remote_refs, &remote_tail,
|
||||
nr_refspecs, refspecs, flags)) {
|
||||
if (match_refs(local_refs, &remote_refs, nr_refspecs, refspecs, flags))
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = send_pack(&args, fd, conn, remote_refs, &extra_have);
|
||||
|
||||
|
||||
@@ -263,7 +263,7 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix)
|
||||
git_config(git_default_config, NULL);
|
||||
shortlog_init(&log);
|
||||
init_revisions(&rev, prefix);
|
||||
parse_options_start(&ctx, argc, argv, PARSE_OPT_KEEP_DASHDASH |
|
||||
parse_options_start(&ctx, argc, argv, prefix, PARSE_OPT_KEEP_DASHDASH |
|
||||
PARSE_OPT_KEEP_ARGV0);
|
||||
|
||||
for (;;) {
|
||||
|
||||
@@ -2,11 +2,26 @@
|
||||
#include "commit.h"
|
||||
#include "refs.h"
|
||||
#include "builtin.h"
|
||||
#include "color.h"
|
||||
#include "parse-options.h"
|
||||
|
||||
static const char show_branch_usage[] =
|
||||
"git show-branch [--sparse] [--current] [--all] [--remotes] [--topo-order] [--more=count | --list | --independent | --merge-base ] [--topics] [<refs>...] | --reflog[=n[,b]] <branch>";
|
||||
static const char show_branch_usage_reflog[] =
|
||||
"--reflog is incompatible with --all, --remotes, --independent or --merge-base";
|
||||
static const char* show_branch_usage[] = {
|
||||
"git show-branch [--sparse] [--current] [--all] [--remotes] [--topo-order] [--more=count | --list | --independent | --merge-base] [--topics] [--color] [<refs>...]",
|
||||
"--reflog[=n[,b]] [--list] [--color] <branch>",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int showbranch_use_color = -1;
|
||||
static char column_colors[][COLOR_MAXLEN] = {
|
||||
GIT_COLOR_RED,
|
||||
GIT_COLOR_GREEN,
|
||||
GIT_COLOR_YELLOW,
|
||||
GIT_COLOR_BLUE,
|
||||
GIT_COLOR_MAGENTA,
|
||||
GIT_COLOR_CYAN,
|
||||
};
|
||||
|
||||
#define COLUMN_COLORS_MAX (ARRAY_SIZE(column_colors))
|
||||
|
||||
static int default_num;
|
||||
static int default_alloc;
|
||||
@@ -19,6 +34,20 @@ static const char **default_arg;
|
||||
|
||||
#define DEFAULT_REFLOG 4
|
||||
|
||||
static const char *get_color_code(int idx)
|
||||
{
|
||||
if (showbranch_use_color)
|
||||
return column_colors[idx];
|
||||
return "";
|
||||
}
|
||||
|
||||
static const char *get_color_reset_code(void)
|
||||
{
|
||||
if (showbranch_use_color)
|
||||
return GIT_COLOR_RESET;
|
||||
return "";
|
||||
}
|
||||
|
||||
static struct commit *interesting(struct commit_list *list)
|
||||
{
|
||||
while (list) {
|
||||
@@ -545,7 +574,12 @@ static int git_show_branch_config(const char *var, const char *value, void *cb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return git_default_config(var, value, cb);
|
||||
if (!strcmp(var, "color.showbranch")) {
|
||||
showbranch_use_color = git_config_colorbool(var, value, -1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return git_color_default_config(var, value, cb);
|
||||
}
|
||||
|
||||
static int omit_in_dense(struct commit *commit, struct commit **rev, int n)
|
||||
@@ -569,18 +603,25 @@ static int omit_in_dense(struct commit *commit, struct commit **rev, int n)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void parse_reflog_param(const char *arg, int *cnt, const char **base)
|
||||
static int reflog = 0;
|
||||
|
||||
static int parse_reflog_param(const struct option *opt, const char *arg,
|
||||
int unset)
|
||||
{
|
||||
char *ep;
|
||||
*cnt = strtoul(arg, &ep, 10);
|
||||
const char **base = (const char **)opt->value;
|
||||
if (!arg)
|
||||
arg = "";
|
||||
reflog = strtoul(arg, &ep, 10);
|
||||
if (*ep == ',')
|
||||
*base = ep + 1;
|
||||
else if (*ep)
|
||||
die("unrecognized reflog param '%s'", arg);
|
||||
return error("unrecognized reflog param '%s'", arg);
|
||||
else
|
||||
*base = NULL;
|
||||
if (*cnt <= 0)
|
||||
*cnt = DEFAULT_REFLOG;
|
||||
if (reflog <= 0)
|
||||
reflog = DEFAULT_REFLOG;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cmd_show_branch(int ac, const char **av, const char *prefix)
|
||||
@@ -606,70 +647,67 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
|
||||
int head_at = -1;
|
||||
int topics = 0;
|
||||
int dense = 1;
|
||||
int reflog = 0;
|
||||
const char *reflog_base = NULL;
|
||||
struct option builtin_show_branch_options[] = {
|
||||
OPT_BOOLEAN('a', "all", &all_heads,
|
||||
"show remote-tracking and local branches"),
|
||||
OPT_BOOLEAN('r', "remotes", &all_remotes,
|
||||
"show remote-tracking branches"),
|
||||
OPT_BOOLEAN(0, "color", &showbranch_use_color,
|
||||
"color '*!+-' corresponding to the branch"),
|
||||
{ OPTION_INTEGER, 0, "more", &extra, "n",
|
||||
"show <n> more commits after the common ancestor",
|
||||
PARSE_OPT_OPTARG, NULL, (intptr_t)1 },
|
||||
OPT_SET_INT(0, "list", &extra, "synonym to more=-1", -1),
|
||||
OPT_BOOLEAN(0, "no-name", &no_name, "suppress naming strings"),
|
||||
OPT_BOOLEAN(0, "current", &with_current_branch,
|
||||
"include the current branch"),
|
||||
OPT_BOOLEAN(0, "sha1-name", &sha1_name,
|
||||
"name commits with their object names"),
|
||||
OPT_BOOLEAN(0, "merge-base", &merge_base,
|
||||
"act like git merge-base -a"),
|
||||
OPT_BOOLEAN(0, "independent", &independent,
|
||||
"show refs unreachable from any other ref"),
|
||||
OPT_BOOLEAN(0, "topo-order", &lifo,
|
||||
"show commits in topological order"),
|
||||
OPT_BOOLEAN(0, "topics", &topics,
|
||||
"show only commits not on the first branch"),
|
||||
OPT_SET_INT(0, "sparse", &dense,
|
||||
"show merges reachable from only one tip", 0),
|
||||
OPT_SET_INT(0, "date-order", &lifo,
|
||||
"show commits where no parent comes before its "
|
||||
"children", 0),
|
||||
{ OPTION_CALLBACK, 'g', "reflog", &reflog_base, "<n>[,<base>]",
|
||||
"show <n> most recent ref-log entries starting at "
|
||||
"base",
|
||||
PARSE_OPT_OPTARG | PARSE_OPT_LITERAL_ARGHELP,
|
||||
parse_reflog_param },
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
git_config(git_show_branch_config, NULL);
|
||||
|
||||
if (showbranch_use_color == -1)
|
||||
showbranch_use_color = git_use_color_default;
|
||||
|
||||
/* If nothing is specified, try the default first */
|
||||
if (ac == 1 && default_num) {
|
||||
ac = default_num + 1;
|
||||
av = default_arg - 1; /* ick; we would not address av[0] */
|
||||
}
|
||||
|
||||
while (1 < ac && av[1][0] == '-') {
|
||||
const char *arg = av[1];
|
||||
if (!strcmp(arg, "--")) {
|
||||
ac--; av++;
|
||||
break;
|
||||
}
|
||||
else if (!strcmp(arg, "--all") || !strcmp(arg, "-a"))
|
||||
all_heads = all_remotes = 1;
|
||||
else if (!strcmp(arg, "--remotes") || !strcmp(arg, "-r"))
|
||||
all_remotes = 1;
|
||||
else if (!strcmp(arg, "--more"))
|
||||
extra = 1;
|
||||
else if (!strcmp(arg, "--list"))
|
||||
extra = -1;
|
||||
else if (!strcmp(arg, "--no-name"))
|
||||
no_name = 1;
|
||||
else if (!strcmp(arg, "--current"))
|
||||
with_current_branch = 1;
|
||||
else if (!strcmp(arg, "--sha1-name"))
|
||||
sha1_name = 1;
|
||||
else if (!prefixcmp(arg, "--more="))
|
||||
extra = atoi(arg + 7);
|
||||
else if (!strcmp(arg, "--merge-base"))
|
||||
merge_base = 1;
|
||||
else if (!strcmp(arg, "--independent"))
|
||||
independent = 1;
|
||||
else if (!strcmp(arg, "--topo-order"))
|
||||
lifo = 1;
|
||||
else if (!strcmp(arg, "--topics"))
|
||||
topics = 1;
|
||||
else if (!strcmp(arg, "--sparse"))
|
||||
dense = 0;
|
||||
else if (!strcmp(arg, "--date-order"))
|
||||
lifo = 0;
|
||||
else if (!strcmp(arg, "--reflog") || !strcmp(arg, "-g")) {
|
||||
reflog = DEFAULT_REFLOG;
|
||||
}
|
||||
else if (!prefixcmp(arg, "--reflog="))
|
||||
parse_reflog_param(arg + 9, &reflog, &reflog_base);
|
||||
else if (!prefixcmp(arg, "-g="))
|
||||
parse_reflog_param(arg + 3, &reflog, &reflog_base);
|
||||
else
|
||||
usage(show_branch_usage);
|
||||
ac--; av++;
|
||||
}
|
||||
ac--; av++;
|
||||
ac = parse_options(ac, av, prefix, builtin_show_branch_options,
|
||||
show_branch_usage, PARSE_OPT_STOP_AT_NON_OPTION);
|
||||
if (all_heads)
|
||||
all_remotes = 1;
|
||||
|
||||
if (extra || reflog) {
|
||||
/* "listing" mode is incompatible with
|
||||
* independent nor merge-base modes.
|
||||
*/
|
||||
if (independent || merge_base)
|
||||
usage(show_branch_usage);
|
||||
usage_with_options(show_branch_usage,
|
||||
builtin_show_branch_options);
|
||||
if (reflog && ((0 < extra) || all_heads || all_remotes))
|
||||
/*
|
||||
* Asking for --more in reflog mode does not
|
||||
@@ -677,7 +715,8 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
|
||||
*
|
||||
* Also --all and --remotes do not make sense either.
|
||||
*/
|
||||
usage(show_branch_usage_reflog);
|
||||
die("--reflog is incompatible with --all, --remotes, "
|
||||
"--independent or --merge-base");
|
||||
}
|
||||
|
||||
/* If nothing is specified, show all branches by default */
|
||||
@@ -843,8 +882,10 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
|
||||
else {
|
||||
for (j = 0; j < i; j++)
|
||||
putchar(' ');
|
||||
printf("%c [%s] ",
|
||||
is_head ? '*' : '!', ref_name[i]);
|
||||
printf("%s%c%s [%s] ",
|
||||
get_color_code(i % COLUMN_COLORS_MAX),
|
||||
is_head ? '*' : '!',
|
||||
get_color_reset_code(), ref_name[i]);
|
||||
}
|
||||
|
||||
if (!reflog) {
|
||||
@@ -903,7 +944,9 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
|
||||
mark = '*';
|
||||
else
|
||||
mark = '+';
|
||||
putchar(mark);
|
||||
printf("%s%c%s",
|
||||
get_color_code(i % COLUMN_COLORS_MAX),
|
||||
mark, get_color_reset_code());
|
||||
}
|
||||
putchar(' ');
|
||||
}
|
||||
|
||||
@@ -36,7 +36,8 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
|
||||
};
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
argc = parse_options(argc, argv, options, git_symbolic_ref_usage, 0);
|
||||
argc = parse_options(argc, argv, prefix, options,
|
||||
git_symbolic_ref_usage, 0);
|
||||
if (msg &&!*msg)
|
||||
die("Refusing to perform update with empty message");
|
||||
switch (argc) {
|
||||
|
||||
@@ -387,7 +387,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
|
||||
"annotated tag, needs a message"),
|
||||
OPT_CALLBACK('m', NULL, &msg, "msg",
|
||||
"message for the tag", parse_msg_arg),
|
||||
OPT_STRING('F', NULL, &msgfile, "file", "message in a file"),
|
||||
OPT_FILENAME('F', NULL, &msgfile, "message in a file"),
|
||||
OPT_BOOLEAN('s', NULL, &sign, "annotated and GPG-signed tag"),
|
||||
OPT_STRING('u', NULL, &keyid, "key-id",
|
||||
"use another key to sign the tag"),
|
||||
@@ -405,8 +405,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
|
||||
|
||||
git_config(git_tag_config, NULL);
|
||||
|
||||
argc = parse_options(argc, argv, options, git_tag_usage, 0);
|
||||
msgfile = parse_options_fix_filename(prefix, msgfile);
|
||||
argc = parse_options(argc, argv, prefix, options, git_tag_usage, 0);
|
||||
|
||||
if (keyid) {
|
||||
sign = 1;
|
||||
|
||||
@@ -23,7 +23,8 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
|
||||
};
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
argc = parse_options(argc, argv, options, git_update_ref_usage, 0);
|
||||
argc = parse_options(argc, argv, prefix, options, git_update_ref_usage,
|
||||
0);
|
||||
if (msg && !*msg)
|
||||
die("Refusing to perform update with empty message.");
|
||||
|
||||
|
||||
@@ -72,6 +72,7 @@ extern int cmd_merge_base(int argc, const char **argv, const char *prefix);
|
||||
extern int cmd_merge_ours(int argc, const char **argv, const char *prefix);
|
||||
extern int cmd_merge_file(int argc, const char **argv, const char *prefix);
|
||||
extern int cmd_merge_recursive(int argc, const char **argv, const char *prefix);
|
||||
extern int cmd_mktree(int argc, const char **argv, const char *prefix);
|
||||
extern int cmd_mv(int argc, const char **argv, const char *prefix);
|
||||
extern int cmd_name_rev(int argc, const char **argv, const char *prefix);
|
||||
extern int cmd_pack_objects(int argc, const char **argv, const char *prefix);
|
||||
|
||||
2
bundle.c
2
bundle.c
@@ -98,7 +98,7 @@ int verify_bundle(struct bundle_header *header, int verbose)
|
||||
*/
|
||||
struct ref_list *p = &header->prerequisites;
|
||||
struct rev_info revs;
|
||||
const char *argv[] = {NULL, "--all"};
|
||||
const char *argv[] = {NULL, "--all", NULL};
|
||||
struct object_array refs;
|
||||
struct commit *commit;
|
||||
int i, ret = 0, req_nr;
|
||||
|
||||
2
cache.h
2
cache.h
@@ -614,6 +614,8 @@ extern int is_empty_blob_sha1(const unsigned char *sha1);
|
||||
|
||||
int git_mkstemp(char *path, size_t n, const char *template);
|
||||
|
||||
int git_mkstemps(char *path, size_t n, const char *template, int suffix_len);
|
||||
|
||||
/*
|
||||
* NOTE NOTE NOTE!!
|
||||
*
|
||||
|
||||
20
commit.c
20
commit.c
@@ -316,6 +316,26 @@ int parse_commit(struct commit *item)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void unparse_commit_list(struct commit_list *list)
|
||||
{
|
||||
for (; list; list = list->next)
|
||||
unparse_commit(list->item);
|
||||
}
|
||||
|
||||
void unparse_commit(struct commit *item)
|
||||
{
|
||||
item->object.flags = 0;
|
||||
item->object.used = 0;
|
||||
if (item->object.parsed) {
|
||||
item->object.parsed = 0;
|
||||
if (item->parents) {
|
||||
unparse_commit_list(item->parents);
|
||||
free_commit_list(item->parents);
|
||||
item->parents = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct commit_list *commit_list_insert(struct commit *item, struct commit_list **list_p)
|
||||
{
|
||||
struct commit_list *new_list = xmalloc(sizeof(struct commit_list));
|
||||
|
||||
2
commit.h
2
commit.h
@@ -40,6 +40,8 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size);
|
||||
|
||||
int parse_commit(struct commit *item);
|
||||
|
||||
void unparse_commit(struct commit *item);
|
||||
|
||||
struct commit_list * commit_list_insert(struct commit *item, struct commit_list **list_p);
|
||||
unsigned commit_list_count(const struct commit_list *l);
|
||||
struct commit_list * insert_by_date(struct commit *item, struct commit_list **list);
|
||||
|
||||
15
compat/basename.c
Normal file
15
compat/basename.c
Normal file
@@ -0,0 +1,15 @@
|
||||
#include "../git-compat-util.h"
|
||||
|
||||
/* Adapted from libiberty's basename.c. */
|
||||
char *gitbasename (char *path)
|
||||
{
|
||||
const char *base;
|
||||
/* Skip over the disk name in MSDOS pathnames. */
|
||||
if (has_dos_drive_prefix(path))
|
||||
path += 2;
|
||||
for (base = path; *path; path++) {
|
||||
if (is_dir_sep(*path))
|
||||
base = path + 1;
|
||||
}
|
||||
return (char *)base;
|
||||
}
|
||||
70
compat/mkstemps.c
Normal file
70
compat/mkstemps.c
Normal file
@@ -0,0 +1,70 @@
|
||||
#include "../git-compat-util.h"
|
||||
|
||||
/* Adapted from libiberty's mkstemp.c. */
|
||||
|
||||
#undef TMP_MAX
|
||||
#define TMP_MAX 16384
|
||||
|
||||
int gitmkstemps(char *pattern, int suffix_len)
|
||||
{
|
||||
static const char letters[] =
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789";
|
||||
static const int num_letters = 62;
|
||||
uint64_t value;
|
||||
struct timeval tv;
|
||||
char *template;
|
||||
size_t len;
|
||||
int fd, count;
|
||||
|
||||
len = strlen(pattern);
|
||||
|
||||
if (len < 6 + suffix_len) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strncmp(&pattern[len - 6 - suffix_len], "XXXXXX", 6)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Replace pattern's XXXXXX characters with randomness.
|
||||
* Try TMP_MAX different filenames.
|
||||
*/
|
||||
gettimeofday(&tv, NULL);
|
||||
value = ((size_t)(tv.tv_usec << 16)) ^ tv.tv_sec ^ getpid();
|
||||
template = &pattern[len - 6 - suffix_len];
|
||||
for (count = 0; count < TMP_MAX; ++count) {
|
||||
uint64_t v = value;
|
||||
/* Fill in the random bits. */
|
||||
template[0] = letters[v % num_letters]; v /= num_letters;
|
||||
template[1] = letters[v % num_letters]; v /= num_letters;
|
||||
template[2] = letters[v % num_letters]; v /= num_letters;
|
||||
template[3] = letters[v % num_letters]; v /= num_letters;
|
||||
template[4] = letters[v % num_letters]; v /= num_letters;
|
||||
template[5] = letters[v % num_letters]; v /= num_letters;
|
||||
|
||||
fd = open(pattern, O_CREAT | O_EXCL | O_RDWR, 0600);
|
||||
if (fd > 0)
|
||||
return fd;
|
||||
/*
|
||||
* Fatal error (EPERM, ENOSPC etc).
|
||||
* It doesn't make sense to loop.
|
||||
*/
|
||||
if (errno != EEXIST)
|
||||
break;
|
||||
/*
|
||||
* This is a random value. It is only necessary that
|
||||
* the next TMP_MAX values generated by adding 7777 to
|
||||
* VALUE are different with (module 2^32).
|
||||
*/
|
||||
value += 7777;
|
||||
}
|
||||
/* We return the null string if we can't find a unique file name. */
|
||||
pattern[0] = '\0';
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
@@ -30,8 +30,10 @@ NEEDS_SSL_WITH_CRYPTO=@NEEDS_SSL_WITH_CRYPTO@
|
||||
NO_OPENSSL=@NO_OPENSSL@
|
||||
NO_CURL=@NO_CURL@
|
||||
NO_EXPAT=@NO_EXPAT@
|
||||
NO_LIBGEN_H=@NO_LIBGEN_H@
|
||||
NEEDS_LIBICONV=@NEEDS_LIBICONV@
|
||||
NEEDS_SOCKET=@NEEDS_SOCKET@
|
||||
NEEDS_RESOLV=@NEEDS_RESOLV@
|
||||
NO_SYS_SELECT_H=@NO_SYS_SELECT_H@
|
||||
NO_D_INO_IN_DIRENT=@NO_D_INO_IN_DIRENT@
|
||||
NO_D_TYPE_IN_DIRENT=@NO_D_TYPE_IN_DIRENT@
|
||||
@@ -46,6 +48,7 @@ NO_STRTOUMAX=@NO_STRTOUMAX@
|
||||
NO_SETENV=@NO_SETENV@
|
||||
NO_UNSETENV=@NO_UNSETENV@
|
||||
NO_MKDTEMP=@NO_MKDTEMP@
|
||||
NO_MKSTEMPS=@NO_MKSTEMPS@
|
||||
NO_ICONV=@NO_ICONV@
|
||||
OLD_ICONV=@OLD_ICONV@
|
||||
NO_DEFLATE_BOUND=@NO_DEFLATE_BOUND@
|
||||
|
||||
22
configure.ac
22
configure.ac
@@ -467,6 +467,15 @@ AC_CHECK_LIB([c], [socket],
|
||||
AC_SUBST(NEEDS_SOCKET)
|
||||
test -n "$NEEDS_SOCKET" && LIBS="$LIBS -lsocket"
|
||||
|
||||
#
|
||||
# Define NEEDS_RESOLV if linking with -lnsl and/or -lsocket is not enough.
|
||||
# Notably on Solaris hstrerror resides in libresolv and on Solaris 7
|
||||
# inet_ntop and inet_pton additionally reside there.
|
||||
AC_CHECK_LIB([resolv], [hstrerror],
|
||||
[NEEDS_RESOLV=],
|
||||
[NEEDS_RESOLV=YesPlease])
|
||||
AC_SUBST(NEEDS_RESOLV)
|
||||
test -n "$NEEDS_RESOLV" && LIBS="$LIBS -lresolv"
|
||||
|
||||
## Checks for header files.
|
||||
AC_MSG_NOTICE([CHECKS for header files])
|
||||
@@ -627,6 +636,12 @@ AC_SUBST(SNPRINTF_RETURNS_BOGUS)
|
||||
## (in default C library and libraries checked by AC_CHECK_LIB)
|
||||
AC_MSG_NOTICE([CHECKS for library functions])
|
||||
#
|
||||
# Define NO_LIBGEN_H if you don't have libgen.h.
|
||||
AC_CHECK_HEADER([libgen.h],
|
||||
[NO_LIBGEN_H=],
|
||||
[NO_LIBGEN_H=YesPlease])
|
||||
AC_SUBST(NO_LIBGEN_H)
|
||||
#
|
||||
# Define NO_STRCASESTR if you don't have strcasestr.
|
||||
GIT_CHECK_FUNC(strcasestr,
|
||||
[NO_STRCASESTR=],
|
||||
@@ -677,6 +692,13 @@ GIT_CHECK_FUNC(mkdtemp,
|
||||
[NO_MKDTEMP=YesPlease])
|
||||
AC_SUBST(NO_MKDTEMP)
|
||||
#
|
||||
# Define NO_MKSTEMPS if you don't have mkstemps in the C library.
|
||||
GIT_CHECK_FUNC(mkstemps,
|
||||
[NO_MKSTEMPS=],
|
||||
[NO_MKSTEMPS=YesPlease])
|
||||
AC_SUBST(NO_MKSTEMPS)
|
||||
#
|
||||
#
|
||||
# Define NO_MMAP if you want to avoid mmap.
|
||||
#
|
||||
# Define NO_ICONV if your libc does not properly support iconv.
|
||||
|
||||
@@ -579,7 +579,10 @@ struct child_process *git_connect(int fd[2], const char *url_orig,
|
||||
git_tcp_connect(fd, host, flags);
|
||||
/*
|
||||
* Separate original protocol components prog and path
|
||||
* from extended components with a NUL byte.
|
||||
* from extended host header with a NUL byte.
|
||||
*
|
||||
* Note: Do not add any other headers here! Doing so
|
||||
* will cause older git-daemon servers to crash.
|
||||
*/
|
||||
packet_write(fd[1],
|
||||
"%s %s%chost=%s%c",
|
||||
|
||||
@@ -40,6 +40,10 @@
|
||||
# with the bash.showDirtyState variable, which defaults to true
|
||||
# once GIT_PS1_SHOWDIRTYSTATE is enabled.
|
||||
#
|
||||
# You can also see if currently something is stashed, by setting
|
||||
# GIT_PS1_SHOWSTASHSTATE to a nonempty value. If something is stashed,
|
||||
# then a '$' will be shown next to the branch name.
|
||||
#
|
||||
# To submit patches:
|
||||
#
|
||||
# *) Read Documentation/SubmittingPatches
|
||||
@@ -84,26 +88,24 @@ __git_ps1 ()
|
||||
if [ -n "$g" ]; then
|
||||
local r
|
||||
local b
|
||||
if [ -d "$g/rebase-apply" ]; then
|
||||
if [ -f "$g/rebase-apply/rebasing" ]; then
|
||||
r="|REBASE"
|
||||
elif [ -f "$g/rebase-apply/applying" ]; then
|
||||
r="|AM"
|
||||
else
|
||||
r="|AM/REBASE"
|
||||
fi
|
||||
b="$(git symbolic-ref HEAD 2>/dev/null)"
|
||||
elif [ -f "$g/rebase-merge/interactive" ]; then
|
||||
if [ -f "$g/rebase-merge/interactive" ]; then
|
||||
r="|REBASE-i"
|
||||
b="$(cat "$g/rebase-merge/head-name")"
|
||||
elif [ -d "$g/rebase-merge" ]; then
|
||||
r="|REBASE-m"
|
||||
b="$(cat "$g/rebase-merge/head-name")"
|
||||
else
|
||||
if [ -f "$g/MERGE_HEAD" ]; then
|
||||
if [ -d "$g/rebase-apply" ]; then
|
||||
if [ -f "$g/rebase-apply/rebasing" ]; then
|
||||
r="|REBASE"
|
||||
elif [ -f "$g/rebase-apply/applying" ]; then
|
||||
r="|AM"
|
||||
else
|
||||
r="|AM/REBASE"
|
||||
fi
|
||||
elif [ -f "$g/MERGE_HEAD" ]; then
|
||||
r="|MERGING"
|
||||
fi
|
||||
if [ -f "$g/BISECT_LOG" ]; then
|
||||
elif [ -f "$g/BISECT_LOG" ]; then
|
||||
r="|BISECTING"
|
||||
fi
|
||||
|
||||
@@ -129,6 +131,7 @@ __git_ps1 ()
|
||||
|
||||
local w
|
||||
local i
|
||||
local s
|
||||
local c
|
||||
|
||||
if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then
|
||||
@@ -150,14 +153,15 @@ __git_ps1 ()
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ]; then
|
||||
git rev-parse --verify refs/stash >/dev/null 2>&1 && s="$"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$b" ]; then
|
||||
if [ -n "${1-}" ]; then
|
||||
printf "$1" "$c${b##refs/heads/}$w$i$r"
|
||||
else
|
||||
printf " (%s)" "$c${b##refs/heads/}$w$i$r"
|
||||
fi
|
||||
if [ -n "${1-}" ]; then
|
||||
printf "$1" "$c${b##refs/heads/}$w$i$s$r"
|
||||
else
|
||||
printf " (%s)" "$c${b##refs/heads/}$w$i$s$r"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
@@ -923,7 +927,7 @@ _git_diff ()
|
||||
}
|
||||
|
||||
__git_mergetools_common="diffuse ecmerge emerge kdiff3 meld opendiff
|
||||
tkdiff vimdiff gvimdiff xxdiff
|
||||
tkdiff vimdiff gvimdiff xxdiff araxis
|
||||
"
|
||||
|
||||
_git_difftool ()
|
||||
@@ -1334,6 +1338,35 @@ _git_send_email ()
|
||||
COMPREPLY=()
|
||||
}
|
||||
|
||||
__git_config_get_set_variables ()
|
||||
{
|
||||
local prevword word config_file= c=$COMP_CWORD
|
||||
while [ $c -gt 1 ]; do
|
||||
word="${COMP_WORDS[c]}"
|
||||
case "$word" in
|
||||
--global|--system|--file=*)
|
||||
config_file="$word"
|
||||
break
|
||||
;;
|
||||
-f|--file)
|
||||
config_file="$word $prevword"
|
||||
break
|
||||
;;
|
||||
esac
|
||||
prevword=$word
|
||||
c=$((--c))
|
||||
done
|
||||
|
||||
for i in $(git --git-dir="$(__gitdir)" config $config_file --list \
|
||||
2>/dev/null); do
|
||||
case "$i" in
|
||||
*.*)
|
||||
echo "${i/=*/}"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
_git_config ()
|
||||
{
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
@@ -1365,7 +1398,8 @@ _git_config ()
|
||||
__gitcomp "$(__git_merge_strategies)"
|
||||
return
|
||||
;;
|
||||
color.branch|color.diff|color.interactive|color.status|color.ui)
|
||||
color.branch|color.diff|color.interactive|\
|
||||
color.showbranch|color.status|color.ui)
|
||||
__gitcomp "always never auto"
|
||||
return
|
||||
;;
|
||||
@@ -1400,6 +1434,10 @@ _git_config ()
|
||||
__gitcomp "$__git_send_email_suppresscc_options"
|
||||
return
|
||||
;;
|
||||
--get|--get-all|--unset|--unset-all)
|
||||
__gitcomp "$(__git_config_get_set_variables)"
|
||||
return
|
||||
;;
|
||||
*.*)
|
||||
COMPREPLY=()
|
||||
return
|
||||
@@ -1510,6 +1548,7 @@ _git_config ()
|
||||
color.interactive.help
|
||||
color.interactive.prompt
|
||||
color.pager
|
||||
color.showbranch
|
||||
color.status
|
||||
color.status.added
|
||||
color.status.changed
|
||||
@@ -1821,6 +1860,7 @@ _git_show_branch ()
|
||||
__gitcomp "
|
||||
--all --remotes --topo-order --current --more=
|
||||
--list --independent --merge-base --no-name
|
||||
--color --no-color
|
||||
--sha1-name --sparse --topics --reflog
|
||||
"
|
||||
return
|
||||
@@ -1841,10 +1881,10 @@ _git_stash ()
|
||||
save,--*)
|
||||
__gitcomp "--keep-index"
|
||||
;;
|
||||
apply,--*)
|
||||
apply,--*|pop,--*)
|
||||
__gitcomp "--index"
|
||||
;;
|
||||
show,--*|drop,--*|pop,--*|branch,--*)
|
||||
show,--*|drop,--*|branch,--*)
|
||||
COMPREPLY=()
|
||||
;;
|
||||
show,*|apply,*|drop,*|pop,*|branch,*)
|
||||
|
||||
4
contrib/hooks/post-receive-email
Normal file → Executable file
4
contrib/hooks/post-receive-email
Normal file → Executable file
@@ -44,6 +44,10 @@
|
||||
# --pretty %s", displaying the commit id, author, date and log
|
||||
# message. To list full patches separated by a blank line, you
|
||||
# could set this to "git show -C %s; echo".
|
||||
# To list a gitweb/cgit URL *and* a full patch for each change set, use this:
|
||||
# "t=%s; printf 'http://.../?id=%%s' \$t; echo;echo; git show -C \$t; echo"
|
||||
# Be careful if "..." contains things that will be expanded by shell "eval"
|
||||
# or printf.
|
||||
#
|
||||
# Notes
|
||||
# -----
|
||||
|
||||
10
daemon.c
10
daemon.c
@@ -406,15 +406,15 @@ static char *xstrdup_tolower(const char *str)
|
||||
}
|
||||
|
||||
/*
|
||||
* Separate the "extra args" information as supplied by the client connection.
|
||||
* Read the host as supplied by the client connection.
|
||||
*/
|
||||
static void parse_extra_args(char *extra_args, int buflen)
|
||||
static void parse_host_arg(char *extra_args, int buflen)
|
||||
{
|
||||
char *val;
|
||||
int vallen;
|
||||
char *end = extra_args + buflen;
|
||||
|
||||
while (extra_args < end && *extra_args) {
|
||||
if (extra_args < end && *extra_args) {
|
||||
saw_extended_args = 1;
|
||||
if (strncasecmp("host=", extra_args, 5) == 0) {
|
||||
val = extra_args + 5;
|
||||
@@ -436,6 +436,8 @@ static void parse_extra_args(char *extra_args, int buflen)
|
||||
/* On to the next one */
|
||||
extra_args = val + vallen;
|
||||
}
|
||||
if (extra_args < end && *extra_args)
|
||||
die("Invalid request");
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -545,7 +547,7 @@ static int execute(struct sockaddr *addr)
|
||||
hostname = canon_hostname = ip_address = tcp_port = NULL;
|
||||
|
||||
if (len != pktlen)
|
||||
parse_extra_args(line + len + 1, pktlen - len - 1);
|
||||
parse_host_arg(line + len + 1, pktlen - len - 1);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
|
||||
struct daemon_service *s = &(daemon_service[i]);
|
||||
|
||||
@@ -18,7 +18,7 @@ static void *insert_decoration(struct decoration *n, const struct object *base,
|
||||
{
|
||||
int size = n->size;
|
||||
struct object_decoration *hash = n->hash;
|
||||
int j = hash_obj(base, size);
|
||||
unsigned int j = hash_obj(base, size);
|
||||
|
||||
while (hash[j].base) {
|
||||
if (hash[j].base == base) {
|
||||
@@ -70,7 +70,7 @@ void *add_decoration(struct decoration *n, const struct object *obj,
|
||||
/* Lookup a decoration pointer */
|
||||
void *lookup_decoration(struct decoration *n, const struct object *obj)
|
||||
{
|
||||
int j;
|
||||
unsigned int j;
|
||||
|
||||
/* nothing to lookup */
|
||||
if (!n->size)
|
||||
|
||||
39
diff.c
39
diff.c
@@ -839,10 +839,9 @@ static int scale_linear(int it, int width, int max_change)
|
||||
}
|
||||
|
||||
static void show_name(FILE *file,
|
||||
const char *prefix, const char *name, int len,
|
||||
const char *reset, const char *set)
|
||||
const char *prefix, const char *name, int len)
|
||||
{
|
||||
fprintf(file, " %s%s%-*s%s |", set, prefix, len, name, reset);
|
||||
fprintf(file, " %s%-*s |", prefix, len, name);
|
||||
}
|
||||
|
||||
static void show_graph(FILE *file, char ch, int cnt, const char *set, const char *reset)
|
||||
@@ -956,7 +955,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
|
||||
}
|
||||
|
||||
if (data->files[i]->is_binary) {
|
||||
show_name(options->file, prefix, name, len, reset, set);
|
||||
show_name(options->file, prefix, name, len);
|
||||
fprintf(options->file, " Bin ");
|
||||
fprintf(options->file, "%s%d%s", del_c, deleted, reset);
|
||||
fprintf(options->file, " -> ");
|
||||
@@ -966,7 +965,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
|
||||
continue;
|
||||
}
|
||||
else if (data->files[i]->is_unmerged) {
|
||||
show_name(options->file, prefix, name, len, reset, set);
|
||||
show_name(options->file, prefix, name, len);
|
||||
fprintf(options->file, " Unmerged\n");
|
||||
continue;
|
||||
}
|
||||
@@ -988,7 +987,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
|
||||
add = scale_linear(add, width, max_change);
|
||||
del = scale_linear(del, width, max_change);
|
||||
}
|
||||
show_name(options->file, prefix, name, len, reset, set);
|
||||
show_name(options->file, prefix, name, len);
|
||||
fprintf(options->file, "%5d%s", added + deleted,
|
||||
added + deleted ? " " : "");
|
||||
show_graph(options->file, '+', add, add_c, reset);
|
||||
@@ -996,8 +995,8 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
|
||||
fprintf(options->file, "\n");
|
||||
}
|
||||
fprintf(options->file,
|
||||
"%s %d files changed, %d insertions(+), %d deletions(-)%s\n",
|
||||
set, total_files, adds, dels, reset);
|
||||
" %d files changed, %d insertions(+), %d deletions(-)\n",
|
||||
total_files, adds, dels);
|
||||
}
|
||||
|
||||
static void show_shortstats(struct diffstat_t* data, struct diff_options *options)
|
||||
@@ -1965,8 +1964,16 @@ static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
|
||||
{
|
||||
int fd;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
struct strbuf template = STRBUF_INIT;
|
||||
char *path_dup = xstrdup(path);
|
||||
const char *base = basename(path_dup);
|
||||
|
||||
fd = git_mkstemp(temp->tmp_path, PATH_MAX, ".diff_XXXXXX");
|
||||
/* Generate "XXXXXX_basename.ext" */
|
||||
strbuf_addstr(&template, "XXXXXX_");
|
||||
strbuf_addstr(&template, base);
|
||||
|
||||
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));
|
||||
if (convert_to_working_tree(path,
|
||||
@@ -1982,6 +1989,8 @@ static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
|
||||
temp->hex[40] = 0;
|
||||
sprintf(temp->mode, "%06o", mode);
|
||||
strbuf_release(&buf);
|
||||
strbuf_release(&template);
|
||||
free(path_dup);
|
||||
}
|
||||
|
||||
static struct diff_tempfile *prepare_temp_file(const char *name,
|
||||
@@ -2015,18 +2024,15 @@ static struct diff_tempfile *prepare_temp_file(const char *name,
|
||||
die("stat(%s): %s", name, strerror(errno));
|
||||
}
|
||||
if (S_ISLNK(st.st_mode)) {
|
||||
int ret;
|
||||
char buf[PATH_MAX + 1]; /* ought to be SYMLINK_MAX */
|
||||
ret = readlink(name, buf, sizeof(buf));
|
||||
if (ret < 0)
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
if (strbuf_readlink(&sb, name, st.st_size) < 0)
|
||||
die("readlink(%s)", name);
|
||||
if (ret == sizeof(buf))
|
||||
die("symlink too long: %s", name);
|
||||
prep_temp_blob(name, temp, buf, ret,
|
||||
prep_temp_blob(name, temp, sb.buf, sb.len,
|
||||
(one->sha1_valid ?
|
||||
one->sha1 : null_sha1),
|
||||
(one->sha1_valid ?
|
||||
one->mode : S_IFLNK));
|
||||
strbuf_release(&sb);
|
||||
}
|
||||
else {
|
||||
/* we can borrow from the file in the work tree */
|
||||
@@ -3590,6 +3596,7 @@ static char *run_textconv(const char *pgm, struct diff_filespec *spec,
|
||||
if (start_command(&child) != 0 ||
|
||||
strbuf_read(&buf, child.out, 0) < 0 ||
|
||||
finish_command(&child) != 0) {
|
||||
strbuf_release(&buf);
|
||||
remove_tempfile();
|
||||
error("error running textconv command '%s'", pgm);
|
||||
return NULL;
|
||||
|
||||
2
dir.c
2
dir.c
@@ -396,7 +396,7 @@ static struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathna
|
||||
|
||||
static struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname, int len)
|
||||
{
|
||||
if (cache_name_pos(pathname, len) >= 0)
|
||||
if (!cache_name_is_other(pathname, len))
|
||||
return NULL;
|
||||
|
||||
ALLOC_GROW(dir->ignored, dir->ignored_nr+1, dir->ignored_alloc);
|
||||
|
||||
@@ -44,11 +44,7 @@ else
|
||||
fi
|
||||
|
||||
sq () {
|
||||
for sqarg
|
||||
do
|
||||
printf "%s" "$sqarg" |
|
||||
sed -e 's/'\''/'\''\\'\'''\''/g' -e 's/.*/ '\''&'\''/'
|
||||
done
|
||||
git rev-parse --sq-quote "$@"
|
||||
}
|
||||
|
||||
stop_here () {
|
||||
|
||||
176
git-bisect.sh
176
git-bisect.sh
@@ -33,16 +33,6 @@ require_work_tree
|
||||
_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
|
||||
_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
|
||||
|
||||
sq() {
|
||||
@@PERL@@ -e '
|
||||
for (@ARGV) {
|
||||
s/'\''/'\'\\\\\'\''/g;
|
||||
print " '\''$_'\''";
|
||||
}
|
||||
print "\n";
|
||||
' "$@"
|
||||
}
|
||||
|
||||
bisect_autostart() {
|
||||
test -s "$GIT_DIR/BISECT_START" || {
|
||||
echo >&2 'You need to start by "git bisect start"'
|
||||
@@ -107,7 +97,7 @@ bisect_start() {
|
||||
for arg; do
|
||||
case "$arg" in --) has_double_dash=1; break ;; esac
|
||||
done
|
||||
orig_args=$(sq "$@")
|
||||
orig_args=$(git rev-parse --sq-quote "$@")
|
||||
bad_seen=0
|
||||
eval=''
|
||||
while [ $# -gt 0 ]; do
|
||||
@@ -147,7 +137,7 @@ bisect_start() {
|
||||
# Write new start state.
|
||||
#
|
||||
echo "$start_head" >"$GIT_DIR/BISECT_START" &&
|
||||
sq "$@" >"$GIT_DIR/BISECT_NAMES" &&
|
||||
git rev-parse --sq-quote "$@" >"$GIT_DIR/BISECT_NAMES" &&
|
||||
eval "$eval" &&
|
||||
echo "git bisect start$orig_args" >>"$GIT_DIR/BISECT_LOG" || exit
|
||||
#
|
||||
@@ -177,10 +167,6 @@ is_expected_rev() {
|
||||
test "$1" = $(cat "$GIT_DIR/BISECT_EXPECTED_REV")
|
||||
}
|
||||
|
||||
mark_expected_rev() {
|
||||
echo "$1" > "$GIT_DIR/BISECT_EXPECTED_REV"
|
||||
}
|
||||
|
||||
check_expected_revs() {
|
||||
for _rev in "$@"; do
|
||||
if ! is_expected_rev "$_rev"; then
|
||||
@@ -199,7 +185,7 @@ bisect_skip() {
|
||||
*..*)
|
||||
revs=$(git rev-list "$arg") || die "Bad rev input: $arg" ;;
|
||||
*)
|
||||
revs=$(sq "$arg") ;;
|
||||
revs=$(git rev-parse --sq-quote "$arg") ;;
|
||||
esac
|
||||
all="$all $revs"
|
||||
done
|
||||
@@ -279,162 +265,22 @@ bisect_auto_next() {
|
||||
bisect_next_check && bisect_next || :
|
||||
}
|
||||
|
||||
exit_if_skipped_commits () {
|
||||
_tried=$1
|
||||
_bad=$2
|
||||
if test -n "$_tried" ; then
|
||||
echo "There are only 'skip'ped commit left to test."
|
||||
echo "The first bad commit could be any of:"
|
||||
echo "$_tried" | tr '[|]' '[\012]'
|
||||
test -n "$_bad" && echo "$_bad"
|
||||
echo "We cannot bisect more!"
|
||||
exit 2
|
||||
fi
|
||||
}
|
||||
|
||||
bisect_checkout() {
|
||||
_rev="$1"
|
||||
_msg="$2"
|
||||
echo "Bisecting: $_msg"
|
||||
mark_expected_rev "$_rev"
|
||||
git checkout -q "$_rev" -- || exit
|
||||
git show-branch "$_rev"
|
||||
}
|
||||
|
||||
is_among() {
|
||||
_rev="$1"
|
||||
_list="$2"
|
||||
case "$_list" in *$_rev*) return 0 ;; esac
|
||||
return 1
|
||||
}
|
||||
|
||||
handle_bad_merge_base() {
|
||||
_badmb="$1"
|
||||
_good="$2"
|
||||
if is_expected_rev "$_badmb"; then
|
||||
cat >&2 <<EOF
|
||||
The merge base $_badmb is bad.
|
||||
This means the bug has been fixed between $_badmb and [$_good].
|
||||
EOF
|
||||
exit 3
|
||||
else
|
||||
cat >&2 <<EOF
|
||||
Some good revs are not ancestor of the bad rev.
|
||||
git bisect cannot work properly in this case.
|
||||
Maybe you mistake good and bad revs?
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
handle_skipped_merge_base() {
|
||||
_mb="$1"
|
||||
_bad="$2"
|
||||
_good="$3"
|
||||
cat >&2 <<EOF
|
||||
Warning: the merge base between $_bad and [$_good] must be skipped.
|
||||
So we cannot be sure the first bad commit is between $_mb and $_bad.
|
||||
We continue anyway.
|
||||
EOF
|
||||
}
|
||||
|
||||
#
|
||||
# "check_merge_bases" checks that merge bases are not "bad".
|
||||
#
|
||||
# - If one is "good", that's good, we have nothing to do.
|
||||
# - If one is "bad", it means the user assumed something wrong
|
||||
# and we must exit.
|
||||
# - If one is "skipped", we can't know but we should warn.
|
||||
# - If we don't know, we should check it out and ask the user to test.
|
||||
#
|
||||
# In the last case we will return 1, and otherwise 0.
|
||||
#
|
||||
check_merge_bases() {
|
||||
_bad="$1"
|
||||
_good="$2"
|
||||
_skip="$3"
|
||||
for _mb in $(git merge-base --all $_bad $_good)
|
||||
do
|
||||
if is_among "$_mb" "$_good"; then
|
||||
continue
|
||||
elif test "$_mb" = "$_bad"; then
|
||||
handle_bad_merge_base "$_bad" "$_good"
|
||||
elif is_among "$_mb" "$_skip"; then
|
||||
handle_skipped_merge_base "$_mb" "$_bad" "$_good"
|
||||
else
|
||||
bisect_checkout "$_mb" "a merge base must be tested"
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
#
|
||||
# "check_good_are_ancestors_of_bad" checks that all "good" revs are
|
||||
# ancestor of the "bad" rev.
|
||||
#
|
||||
# If that's not the case, we need to check the merge bases.
|
||||
# If a merge base must be tested by the user we return 1 and
|
||||
# otherwise 0.
|
||||
#
|
||||
check_good_are_ancestors_of_bad() {
|
||||
test -f "$GIT_DIR/BISECT_ANCESTORS_OK" &&
|
||||
return
|
||||
|
||||
_bad="$1"
|
||||
_good=$(echo $2 | sed -e 's/\^//g')
|
||||
_skip="$3"
|
||||
|
||||
# Bisecting with no good rev is ok
|
||||
test -z "$_good" && return
|
||||
|
||||
_side=$(git rev-list $_good ^$_bad)
|
||||
if test -n "$_side"; then
|
||||
# Return if a checkout was done
|
||||
check_merge_bases "$_bad" "$_good" "$_skip" || return
|
||||
fi
|
||||
|
||||
: > "$GIT_DIR/BISECT_ANCESTORS_OK"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
bisect_next() {
|
||||
case "$#" in 0) ;; *) usage ;; esac
|
||||
bisect_autostart
|
||||
bisect_next_check good
|
||||
|
||||
# Get bad, good and skipped revs
|
||||
bad=$(git rev-parse --verify refs/bisect/bad) &&
|
||||
good=$(git for-each-ref --format='^%(objectname)' \
|
||||
"refs/bisect/good-*" | tr '\012' ' ') &&
|
||||
skip=$(git for-each-ref --format='%(objectname)' \
|
||||
"refs/bisect/skip-*" | tr '\012' ' ') || exit
|
||||
# Perform all bisection computation, display and checkout
|
||||
git bisect--helper --next-all
|
||||
res=$?
|
||||
|
||||
# Maybe some merge bases must be tested first
|
||||
check_good_are_ancestors_of_bad "$bad" "$good" "$skip"
|
||||
# Return now if a checkout has already been done
|
||||
test "$?" -eq "1" && return
|
||||
# Check if we should exit because bisection is finished
|
||||
test $res -eq 10 && exit 0
|
||||
|
||||
# Get bisection information
|
||||
eval=$(eval "git bisect--helper --next-vars") &&
|
||||
eval "$eval" || exit
|
||||
# Check for an error in the bisection process
|
||||
test $res -ne 0 && exit $res
|
||||
|
||||
if [ -z "$bisect_rev" ]; then
|
||||
# We should exit here only if the "bad"
|
||||
# commit is also a "skip" commit (see above).
|
||||
exit_if_skipped_commits "$bisect_tried"
|
||||
echo "$bad was both good and bad"
|
||||
exit 1
|
||||
fi
|
||||
if [ "$bisect_rev" = "$bad" ]; then
|
||||
exit_if_skipped_commits "$bisect_tried" "$bad"
|
||||
echo "$bisect_rev is first bad commit"
|
||||
git diff-tree --pretty $bisect_rev
|
||||
exit 0
|
||||
fi
|
||||
|
||||
bisect_checkout "$bisect_rev" "$bisect_nr revisions left to test after this (roughly $bisect_steps steps)"
|
||||
return 0
|
||||
}
|
||||
|
||||
bisect_visualize() {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
/*
|
||||
* See if our compiler is known to support flexible array members.
|
||||
*/
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && (!defined(__SUNPRO_C) || (__SUNPRO_C > 0x580))
|
||||
# define FLEX_ARRAY /* empty */
|
||||
#elif defined(__GNUC__)
|
||||
# if (__GNUC__ >= 3)
|
||||
@@ -39,10 +39,25 @@
|
||||
/* Approximation of the length of the decimal representation of this type. */
|
||||
#define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1)
|
||||
|
||||
#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__USLC__) && !defined(_M_UNIX)
|
||||
#if defined(__sun__)
|
||||
/*
|
||||
* On Solaris, when _XOPEN_EXTENDED is set, its header file
|
||||
* forces the programs to be XPG4v2, defeating any _XOPEN_SOURCE
|
||||
* setting to say we are XPG5 or XPG6. Also on Solaris,
|
||||
* XPG6 programs must be compiled with a c99 compiler, while
|
||||
* non XPG6 programs must be compiled with a pre-c99 compiler.
|
||||
*/
|
||||
# if __STDC_VERSION__ - 0 >= 199901L
|
||||
# define _XOPEN_SOURCE 600
|
||||
# else
|
||||
# define _XOPEN_SOURCE 500
|
||||
# endif
|
||||
#elif !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__USLC__) && !defined(_M_UNIX)
|
||||
#define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */
|
||||
#ifndef __sun__
|
||||
#define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */
|
||||
#endif
|
||||
#endif
|
||||
#define _ALL_SOURCE 1
|
||||
#define _GNU_SOURCE 1
|
||||
#define _BSD_SOURCE 1
|
||||
@@ -97,6 +112,13 @@
|
||||
#include "compat/mingw.h"
|
||||
#endif /* __MINGW32__ */
|
||||
|
||||
#ifndef NO_LIBGEN_H
|
||||
#include <libgen.h>
|
||||
#else
|
||||
#define basename gitbasename
|
||||
extern char *gitbasename(char *);
|
||||
#endif
|
||||
|
||||
#ifndef NO_ICONV
|
||||
#include <iconv.h>
|
||||
#endif
|
||||
@@ -232,6 +254,11 @@ extern int gitsetenv(const char *, const char *, int);
|
||||
extern char *gitmkdtemp(char *);
|
||||
#endif
|
||||
|
||||
#ifdef NO_MKSTEMPS
|
||||
#define mkstemps gitmkstemps
|
||||
extern int gitmkstemps(char *, int);
|
||||
#endif
|
||||
|
||||
#ifdef NO_UNSETENV
|
||||
#define unsetenv gitunsetenv
|
||||
extern void gitunsetenv(const char *);
|
||||
|
||||
@@ -225,7 +225,14 @@ if (@canstatusfiles) {
|
||||
foreach my $name (keys %todo) {
|
||||
my $basename = basename($name);
|
||||
|
||||
$basename = "no file " . $basename if (exists($added{$basename}));
|
||||
# CVS reports files that don't exist in the current revision as
|
||||
# "no file $basename" in its "status" output, so we should
|
||||
# anticipate that. Totally unknown files will have a status
|
||||
# "Unknown". However, if they exist in the Attic, their status
|
||||
# will be "Up-to-date" (this means they were added once but have
|
||||
# been removed).
|
||||
$basename = "no file $basename" if $added{$basename};
|
||||
|
||||
$basename =~ s/^\s+//;
|
||||
$basename =~ s/\s+$//;
|
||||
|
||||
@@ -233,31 +240,45 @@ if (@canstatusfiles) {
|
||||
$fullname{$basename} = $name;
|
||||
push (@canstatusfiles2, $name);
|
||||
delete($todo{$name});
|
||||
}
|
||||
}
|
||||
}
|
||||
my @cvsoutput;
|
||||
@cvsoutput = xargs_safe_pipe_capture([@cvs, 'status'], @canstatusfiles2);
|
||||
foreach my $l (@cvsoutput) {
|
||||
chomp $l;
|
||||
if ($l =~ /^File:\s+(.*\S)\s+Status: (.*)$/) {
|
||||
if (!exists($fullname{$1})) {
|
||||
print STDERR "Huh? Status reported for unexpected file '$1'\n";
|
||||
} else {
|
||||
$cvsstat{$fullname{$1}} = $2;
|
||||
}
|
||||
}
|
||||
chomp $l;
|
||||
next unless
|
||||
my ($file, $status) = $l =~ /^File:\s+(.*\S)\s+Status: (.*)$/;
|
||||
|
||||
my $fullname = $fullname{$file};
|
||||
print STDERR "Huh? Status '$status' reported for unexpected file '$file'\n"
|
||||
unless defined $fullname;
|
||||
|
||||
# This response means the file does not exist except in
|
||||
# CVS's attic, so set the status accordingly
|
||||
$status = "In-attic"
|
||||
if $file =~ /^no file /
|
||||
&& $status eq 'Up-to-date';
|
||||
|
||||
$cvsstat{$fullname{$file}} = $status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ... validate new files,
|
||||
# ... Validate that new files have the correct status
|
||||
foreach my $f (@afiles) {
|
||||
if (defined ($cvsstat{$f}) and $cvsstat{$f} ne "Unknown") {
|
||||
$dirty = 1;
|
||||
next unless defined(my $stat = $cvsstat{$f});
|
||||
|
||||
# This means the file has never been seen before
|
||||
next if $stat eq 'Unknown';
|
||||
|
||||
# This means the file has been seen before but was removed
|
||||
next if $stat eq 'In-attic';
|
||||
|
||||
$dirty = 1;
|
||||
warn "File $f is already known in your CVS checkout -- perhaps it has been added by another user. Or this may indicate that it exists on a different branch. If this is the case, use -f to force the merge.\n";
|
||||
warn "Status was: $cvsstat{$f}\n";
|
||||
}
|
||||
}
|
||||
|
||||
# ... validate known files.
|
||||
foreach my $f (@files) {
|
||||
next if grep { $_ eq $f } @afiles;
|
||||
|
||||
@@ -18,6 +18,9 @@ translate_merge_tool_path () {
|
||||
emerge)
|
||||
echo emacs
|
||||
;;
|
||||
araxis)
|
||||
echo compare
|
||||
;;
|
||||
*)
|
||||
echo "$1"
|
||||
;;
|
||||
@@ -43,7 +46,7 @@ check_unchanged () {
|
||||
valid_tool () {
|
||||
case "$1" in
|
||||
kdiff3 | tkdiff | xxdiff | meld | opendiff | \
|
||||
emerge | vimdiff | gvimdiff | ecmerge | diffuse)
|
||||
emerge | vimdiff | gvimdiff | ecmerge | diffuse | araxis)
|
||||
;; # happy
|
||||
tortoisemerge)
|
||||
if ! merge_mode; then
|
||||
@@ -228,8 +231,8 @@ run_merge_tool () {
|
||||
fi
|
||||
check_unchanged
|
||||
else
|
||||
"$merge_tool_path" "$LOCAL" "$REMOTE" \
|
||||
--default --mode=merge2 --to="$MERGED"
|
||||
"$merge_tool_path" --default --mode=diff2 \
|
||||
"$LOCAL" "$REMOTE"
|
||||
fi
|
||||
;;
|
||||
emerge)
|
||||
@@ -248,7 +251,7 @@ run_merge_tool () {
|
||||
status=$?
|
||||
else
|
||||
"$merge_tool_path" -f emerge-files-command \
|
||||
"$LOCAL" "$REMOTE" "$(basename "$MERGED")"
|
||||
"$LOCAL" "$REMOTE"
|
||||
fi
|
||||
;;
|
||||
tortoisemerge)
|
||||
@@ -263,6 +266,24 @@ run_merge_tool () {
|
||||
status=1
|
||||
fi
|
||||
;;
|
||||
araxis)
|
||||
if merge_mode; then
|
||||
touch "$BACKUP"
|
||||
if $base_present; then
|
||||
"$merge_tool_path" -wait -merge -3 -a1 \
|
||||
"$BASE" "$LOCAL" "$REMOTE" "$MERGED" \
|
||||
>/dev/null 2>&1
|
||||
else
|
||||
"$merge_tool_path" -wait -2 \
|
||||
"$LOCAL" "$REMOTE" "$MERGED" \
|
||||
>/dev/null 2>&1
|
||||
fi
|
||||
check_unchanged
|
||||
else
|
||||
"$merge_tool_path" -wait -2 "$LOCAL" "$REMOTE" \
|
||||
>/dev/null 2>&1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
merge_tool_cmd="$(get_merge_tool_cmd "$1")"
|
||||
if test -z "$merge_tool_cmd"; then
|
||||
@@ -302,7 +323,7 @@ guess_merge_tool () {
|
||||
else
|
||||
tools="opendiff kdiff3 tkdiff xxdiff meld $tools"
|
||||
fi
|
||||
tools="$tools gvimdiff diffuse ecmerge"
|
||||
tools="$tools gvimdiff diffuse ecmerge araxis"
|
||||
fi
|
||||
if echo "${VISUAL:-$EDITOR}" | grep emacs > /dev/null 2>&1; then
|
||||
# $EDITOR is emacs so add emerge as a candidate
|
||||
|
||||
@@ -420,7 +420,7 @@ do_next () {
|
||||
NEWHEAD=$(git rev-parse HEAD) &&
|
||||
case $HEADNAME in
|
||||
refs/*)
|
||||
message="$GIT_REFLOG_ACTION: $HEADNAME onto $SHORTONTO)" &&
|
||||
message="$GIT_REFLOG_ACTION: $HEADNAME onto $SHORTONTO" &&
|
||||
git update-ref -m "$message" $HEADNAME $NEWHEAD $OLDHEAD &&
|
||||
git symbolic-ref HEAD $HEADNAME
|
||||
;;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user