mirror of
https://github.com/git/git.git
synced 2026-03-13 02:13:24 +01:00
Merge branch 'master' of git://repo.or.cz/git into devel
This commit is contained in:
19
Documentation/RelNotes-1.6.2.1.txt
Normal file
19
Documentation/RelNotes-1.6.2.1.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
GIT v1.6.2.1 Release Notes
|
||||
==========================
|
||||
|
||||
Fixes since v1.6.2
|
||||
------------------
|
||||
|
||||
* .gitignore learned to handle backslash as a quoting mechanism for
|
||||
comment introduction character "#".
|
||||
|
||||
* timestamp output in --date=relative mode used to display timestamps that
|
||||
are long time ago in the default mode; it now uses "N years M months
|
||||
ago", and "N years ago".
|
||||
|
||||
* git-add -i/-p now works with non-ASCII pathnames.
|
||||
|
||||
* "git hash-object -w" did not read from the configuration file from the
|
||||
correct .git directory.
|
||||
|
||||
* git-send-email learned to correctly handle multiple Cc: addresses.
|
||||
104
Documentation/RelNotes-1.6.3.txt
Normal file
104
Documentation/RelNotes-1.6.3.txt
Normal file
@@ -0,0 +1,104 @@
|
||||
GIT v1.6.3 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.
|
||||
|
||||
|
||||
Updates since v1.6.2
|
||||
--------------------
|
||||
|
||||
(subsystems)
|
||||
|
||||
(performance)
|
||||
|
||||
(usability, bells and whistles)
|
||||
|
||||
* "--pretty=<style>" option to the log family of commands can now be
|
||||
spelled as "--format=<style>". In addition, --format=%formatstring
|
||||
is a short-hand for --pretty=tformat:%formatstring.
|
||||
|
||||
* "--oneline" is a synonym for "--pretty=oneline --abbrev=commit".
|
||||
|
||||
* If you realize that you botched the patch when you are editing hunks
|
||||
with the 'edit' action in git-add -i/-p, you can abort the editor to
|
||||
tell git not to apply it.
|
||||
|
||||
* git-archive learned --output=<file> option.
|
||||
|
||||
* git-bisect shows not just the number of remaining commits whose goodness
|
||||
is unknown, but also shows the estimated number of remaining rounds.
|
||||
|
||||
* You can give --date=<format> option to git-blame.
|
||||
|
||||
* git-branch -r shows HEAD symref that points at a remote branch in
|
||||
interest of each tracked remote repository.
|
||||
|
||||
* git-config learned -e option to open an editor to edit the config file
|
||||
directly.
|
||||
|
||||
* git-clone runs post-checkout hook when run without --no-checkout.
|
||||
|
||||
* git-format-patch can be told to use attachment with a new configuration,
|
||||
format.attach.
|
||||
|
||||
* git-format-patch can be told to produce deep or shallow message threads.
|
||||
|
||||
* git-imap-send learned to work around Thunderbird's inability to easily
|
||||
disable format=flowed with a new configuration, imap.preformattedHTML.
|
||||
|
||||
* git-rebase can be told to rebase the series even if your branch is a
|
||||
descendant of the commit you are rebasing onto with --force-rebase
|
||||
option.
|
||||
|
||||
* git-rebase can be told to report diffstat with the --stat option.
|
||||
|
||||
* git-send-email learned --confirm option to review the Cc: list before
|
||||
sending the messages out.
|
||||
|
||||
(developers)
|
||||
|
||||
* Test scripts can be run under valgrind.
|
||||
|
||||
* Makefile learned 'coverage' option to run the test suites with
|
||||
coverage tracking enabled.
|
||||
|
||||
Fixes since v1.6.2
|
||||
------------------
|
||||
|
||||
All of the fixes in v1.6.2.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.2.X series.
|
||||
|
||||
* 'git-submodule add' did not tolerate extra slashes and ./ in the
|
||||
path it accepted from the command line; it now is more lenient
|
||||
(if needed, backport by merging db75ada).
|
||||
|
||||
* git-gc spent excessive amount of time to decide if an object appears
|
||||
in a locally existing pack (if needed, backport by merging 69e020a).
|
||||
|
||||
---
|
||||
exec >/var/tmp/1
|
||||
O=v1.6.2.1-135-g7d65c21
|
||||
echo O=$(git describe master)
|
||||
git shortlog --no-merges $O..master ^maint
|
||||
@@ -491,6 +491,12 @@ message, complete the addressing and subject fields, and press send.
|
||||
Gmail
|
||||
-----
|
||||
|
||||
GMail does not appear to have any way to turn off line wrapping in the web
|
||||
interface, so this will mangle any emails that you send. You can however
|
||||
use any IMAP email client to connect to the google imap server, and forward
|
||||
the emails through that. Just make sure to disable line wrapping in that
|
||||
email client. Alternatively, use "git send-email" instead.
|
||||
|
||||
Submitting properly formatted patches via Gmail is simple now that
|
||||
IMAP support is available. First, edit your ~/.gitconfig to specify your
|
||||
account settings:
|
||||
@@ -503,6 +509,9 @@ account settings:
|
||||
port = 993
|
||||
sslverify = false
|
||||
|
||||
You might need to instead use: folder = "[Google Mail]/Drafts" if you get an error
|
||||
that the "Folder doesn't exist".
|
||||
|
||||
Next, ensure that your Gmail settings are correct. In "Settings" the
|
||||
"Use Unicode (UTF-8) encoding for outgoing messages" should be checked.
|
||||
|
||||
@@ -513,3 +522,4 @@ command to send the patch emails to your Gmail Drafts folder.
|
||||
|
||||
Go to your Gmail account, open the Drafts folder, find the patch email, fill
|
||||
in the To: and CC: fields and send away!
|
||||
|
||||
|
||||
@@ -70,6 +70,14 @@ of lines before or after the line given by <start>.
|
||||
tree copy has the contents of the named file (specify
|
||||
`-` to make the command read from the standard input).
|
||||
|
||||
--date <format>::
|
||||
The value is one of the following alternatives:
|
||||
{relative,local,default,iso,rfc,short}. If --date is not
|
||||
provided, the value of the blame.date config variable is
|
||||
used. If the blame.date config variable is also not set, the
|
||||
iso format is used. For more information, See the discussion
|
||||
of the --date option at linkgit:git-log[1].
|
||||
|
||||
-M|<num>|::
|
||||
Detect moving lines in the file as well. When a commit
|
||||
moves a block of lines in a file (e.g. the original file
|
||||
|
||||
@@ -677,6 +677,16 @@ format.pretty::
|
||||
See linkgit:git-log[1], linkgit:git-show[1],
|
||||
linkgit:git-whatchanged[1].
|
||||
|
||||
format.thread::
|
||||
The default threading style for 'git-format-patch'. Can be
|
||||
either a boolean value, `shallow` or `deep`. 'Shallow'
|
||||
threading makes every mail a reply to the head of the series,
|
||||
where the head is chosen from the cover letter, the
|
||||
`\--in-reply-to`, and the first patch mail, in this order.
|
||||
'Deep' threading makes every mail a reply to the previous one.
|
||||
A true boolean value is the same as `shallow`, and a false
|
||||
value disables threading.
|
||||
|
||||
gc.aggressiveWindow::
|
||||
The window size parameter used in the delta compression
|
||||
algorithm used by 'git-gc --aggressive'. This defaults
|
||||
@@ -1160,6 +1170,10 @@ pull.octopus::
|
||||
pull.twohead::
|
||||
The default merge strategy to use when pulling a single branch.
|
||||
|
||||
rebase.stat::
|
||||
Whether to show a diffstat of what changed upstream since the last
|
||||
rebase. False by default.
|
||||
|
||||
receive.fsckObjects::
|
||||
If it is set to true, git-receive-pack will check all received
|
||||
objects. It will abort in the case of a malformed object or a
|
||||
|
||||
@@ -263,13 +263,6 @@ diff::
|
||||
This lets you review what will be committed (i.e. between
|
||||
HEAD and index).
|
||||
|
||||
Bugs
|
||||
----
|
||||
The interactive mode does not work with files whose names contain
|
||||
characters that need C-quoting. `core.quotepath` configuration can be
|
||||
used to work this limitation around to some degree, but backslash,
|
||||
double-quote and control characters will still have problems.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
linkgit:git-status[1]
|
||||
|
||||
@@ -10,6 +10,7 @@ SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git archive' --format=<fmt> [--list] [--prefix=<prefix>/] [<extra>]
|
||||
[--output=<file>]
|
||||
[--remote=<repo> [--exec=<git-upload-archive>]] <tree-ish>
|
||||
[path...]
|
||||
|
||||
@@ -47,6 +48,9 @@ OPTIONS
|
||||
--prefix=<prefix>/::
|
||||
Prepend <prefix>/ to each filename in the archive.
|
||||
|
||||
--output=<file>::
|
||||
Write the archive to <file> instead of stdout.
|
||||
|
||||
<extra>::
|
||||
This can be any options that the archiver backend understand.
|
||||
See next section.
|
||||
|
||||
@@ -212,7 +212,7 @@ If you have a script that can tell if the current source code is good
|
||||
or bad, you can automatically bisect using:
|
||||
|
||||
------------
|
||||
$ git bisect run my_script
|
||||
$ git bisect run my_script arguments
|
||||
------------
|
||||
|
||||
Note that the "run" script (`my_script` in the above example) should
|
||||
@@ -252,6 +252,13 @@ $ git bisect start HEAD v1.2 -- # HEAD is bad, v1.2 is good
|
||||
$ git bisect run make # "make" builds the app
|
||||
------------
|
||||
|
||||
* Automatically bisect a test failure between origin and HEAD:
|
||||
+
|
||||
------------
|
||||
$ git bisect start HEAD origin -- # HEAD is bad, origin is good
|
||||
$ git bisect run make test # "make test" builds and tests
|
||||
------------
|
||||
|
||||
* Automatically bisect a broken test suite:
|
||||
+
|
||||
------------
|
||||
@@ -291,6 +298,15 @@ It's safer if both "test.sh" and "check_test_case.sh" scripts are
|
||||
outside the repo to prevent interactions between the bisect, make and
|
||||
test processes and the scripts.
|
||||
|
||||
* Automatically bisect a broken test suite:
|
||||
+
|
||||
------------
|
||||
$ git bisect start HEAD HEAD~10 -- # culprit is among the last 10
|
||||
$ git bisect run sh -c "make || exit 125; ~/check_test_case.sh"
|
||||
------------
|
||||
+
|
||||
Does the same as the previous example, but on a single line.
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Linus Torvalds <torvalds@osdl.org>
|
||||
|
||||
@@ -8,7 +8,7 @@ git-checkout - Checkout a branch or paths to the working tree
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git checkout' [-q] [-f] [--track | --no-track] [-b <new_branch> [-l]] [-m] [<branch>]
|
||||
'git checkout' [-q] [-f] [-t | --track | --no-track] [-b <new_branch> [-l]] [-m] [<branch>]
|
||||
'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>...
|
||||
|
||||
DESCRIPTION
|
||||
@@ -21,15 +21,15 @@ specified, <new_branch>. Using -b will cause <new_branch> to
|
||||
be created; in this case you can use the --track or --no-track
|
||||
options, which will be passed to `git branch`.
|
||||
|
||||
As a convenience, --track will default to create a branch whose
|
||||
As a convenience, --track will default to creating a branch whose
|
||||
name is constructed from the specified branch name by stripping
|
||||
the first namespace level.
|
||||
|
||||
When <paths> are given, this command does *not* switch
|
||||
branches. It updates the named paths in the working tree from
|
||||
the index file, or from a named <tree-ish> (most often a commit). In
|
||||
this case, the `-b` options is meaningless and giving
|
||||
either of them results in an error. <tree-ish> argument can be
|
||||
this case, the `-b` and `--track` options are meaningless and giving
|
||||
either of them results in an error. The <tree-ish> argument can be
|
||||
used to specify a specific tree-ish (i.e. commit, tag or tree)
|
||||
to update the index for the given paths before updating the
|
||||
working tree.
|
||||
@@ -75,14 +75,13 @@ entries; instead, unmerged entries are ignored.
|
||||
<repository> <refspec>" explicitly. This behavior is the default
|
||||
when the start point is a remote branch. Set the
|
||||
branch.autosetupmerge configuration variable to `false` if you want
|
||||
'git-checkout' and 'git-branch' to always behave as if '--no-track' were
|
||||
'git checkout' and 'git branch' to always behave as if '--no-track' were
|
||||
given. Set it to `always` if you want this behavior when the
|
||||
start-point is either a local or remote branch.
|
||||
start point is either a local or remote branch.
|
||||
+
|
||||
If no '-b' option was given, the name of the new branch will be
|
||||
derived from the remote branch, by attempting to guess the name
|
||||
of the branch on remote system. If "remotes/" or "refs/remotes/"
|
||||
are prefixed, it is stripped away, and then the part up to the
|
||||
If no '-b' option is given, the name of the new branch will be
|
||||
derived from the remote branch. If "remotes/" or "refs/remotes/"
|
||||
is prefixed it is stripped away, and then the part up to the
|
||||
next slash (which would be the nickname of the remote) is removed.
|
||||
This would tell us to use "hack" as the local branch when branching
|
||||
off of "origin/hack" (or "remotes/origin/hack", or even
|
||||
@@ -152,12 +151,12 @@ $ git checkout v2.6.18
|
||||
------------
|
||||
|
||||
Earlier versions of git did not allow this and asked you to
|
||||
create a temporary branch using `-b` option, but starting from
|
||||
create a temporary branch using the `-b` option, but starting from
|
||||
version 1.5.0, the above command 'detaches' your HEAD from the
|
||||
current branch and directly point at the commit named by the tag
|
||||
(`v2.6.18` in the above example).
|
||||
current branch and directly points at the commit named by the tag
|
||||
(`v2.6.18` in the example above).
|
||||
|
||||
You can use usual git commands while in this state. You can use
|
||||
You can use all git commands while in this state. You can use
|
||||
`git reset --hard $othercommit` to further move around, for
|
||||
example. You can make changes and create a new commit on top of
|
||||
a detached HEAD. You can even create a merge by using `git
|
||||
@@ -191,7 +190,7 @@ $ git checkout hello.c <3>
|
||||
------------
|
||||
+
|
||||
<1> switch branch
|
||||
<2> take out a file out of other commit
|
||||
<2> take a file out of another commit
|
||||
<3> restore hello.c from HEAD of current branch
|
||||
+
|
||||
If you have an unfortunate branch that is named `hello.c`, this
|
||||
@@ -202,7 +201,7 @@ You should instead write:
|
||||
$ git checkout -- hello.c
|
||||
------------
|
||||
|
||||
. After working in a wrong branch, switching to the correct
|
||||
. After working in the wrong branch, switching to the correct
|
||||
branch would be done using:
|
||||
+
|
||||
------------
|
||||
@@ -210,7 +209,7 @@ $ git checkout mytopic
|
||||
------------
|
||||
+
|
||||
However, your "wrong" branch and correct "mytopic" branch may
|
||||
differ in files that you have locally modified, in which case,
|
||||
differ in files that you have modified locally, in which case
|
||||
the above checkout would fail like this:
|
||||
+
|
||||
------------
|
||||
|
||||
@@ -22,6 +22,7 @@ SYNOPSIS
|
||||
'git config' [<file-option>] [-z|--null] -l | --list
|
||||
'git config' [<file-option>] --get-color name [default]
|
||||
'git config' [<file-option>] --get-colorbool name [stdout-is-tty]
|
||||
'git config' [<file-option>] -e | --edit
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@@ -130,6 +131,10 @@ See also <<FILES>>.
|
||||
in the config file will cause the value to be multiplied
|
||||
by 1024, 1048576, or 1073741824 prior to output.
|
||||
|
||||
--bool-or-int::
|
||||
'git-config' will ensure that the output matches the format of
|
||||
either --bool or --int, as described above.
|
||||
|
||||
-z::
|
||||
--null::
|
||||
For all options that output values and/or keys, always
|
||||
@@ -157,6 +162,11 @@ See also <<FILES>>.
|
||||
output. The optional `default` parameter is used instead, if
|
||||
there is no color configured for `name`.
|
||||
|
||||
-e::
|
||||
--edit::
|
||||
Opens an editor to modify the specified config file; either
|
||||
'--system', '--global', or repository (default).
|
||||
|
||||
[[FILES]]
|
||||
FILES
|
||||
-----
|
||||
|
||||
@@ -91,7 +91,9 @@ OPTIONS
|
||||
--index-filter <command>::
|
||||
This is the filter for rewriting the index. It is similar to the
|
||||
tree filter but does not check out the tree, which makes it much
|
||||
faster. For hairy cases, see linkgit:git-update-index[1].
|
||||
faster. Frequently used with `git rm \--cached
|
||||
\--ignore-unmatch ...`, see EXAMPLES below. For hairy
|
||||
cases, see linkgit:git-update-index[1].
|
||||
|
||||
--parent-filter <command>::
|
||||
This is the filter for rewriting the commit's parent list.
|
||||
@@ -204,19 +206,18 @@ However, if the file is absent from the tree of some commit,
|
||||
a simple `rm filename` will fail for that tree and commit.
|
||||
Thus you may instead want to use `rm -f filename` as the script.
|
||||
|
||||
A significantly faster version:
|
||||
Using `\--index-filter` with 'git-rm' yields a significantly faster
|
||||
version. Like with using `rm filename`, `git rm --cached filename`
|
||||
will fail if the file is absent from the tree of a commit. If you
|
||||
want to "completely forget" a file, it does not matter when it entered
|
||||
history, so we also add `\--ignore-unmatch`:
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
git filter-branch --index-filter 'git rm --cached filename' HEAD
|
||||
git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' HEAD
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
Now, you will get the rewritten history saved in HEAD.
|
||||
|
||||
As with using `rm filename`, `git rm --cached filename` will fail
|
||||
if the file is absent from the tree of a commit. If it is not important
|
||||
whether the file is already absent from the tree, you can use
|
||||
`git rm --cached --ignore-unmatch filename` instead.
|
||||
|
||||
To rewrite the repository to look as if `foodir/` had been its project
|
||||
root, and discard all other history:
|
||||
|
||||
|
||||
@@ -10,7 +10,8 @@ SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git format-patch' [-k] [-o <dir> | --stdout] [--thread]
|
||||
[--attach[=<boundary>] | --inline[=<boundary>]]
|
||||
[--attach[=<boundary>] | --inline[=<boundary>] |
|
||||
[--no-attach]]
|
||||
[-s | --signoff] [<common diff options>]
|
||||
[-n | --numbered | -N | --no-numbered]
|
||||
[--start-number <n>] [--numbered-files]
|
||||
@@ -117,15 +118,27 @@ include::diff-options.txt[]
|
||||
which is the commit message and the patch itself in the
|
||||
second part, with "Content-Disposition: attachment".
|
||||
|
||||
--no-attach::
|
||||
Disable the creation of an attachment, overriding the
|
||||
configuration setting.
|
||||
|
||||
--inline[=<boundary>]::
|
||||
Create multipart/mixed attachment, the first part of
|
||||
which is the commit message and the patch itself in the
|
||||
second part, with "Content-Disposition: inline".
|
||||
|
||||
--thread::
|
||||
--thread[=<style>]::
|
||||
Add In-Reply-To and References headers to make the second and
|
||||
subsequent mails appear as replies to the first. Also generates
|
||||
the Message-Id header to reference.
|
||||
+
|
||||
The optional <style> argument can be either `shallow` or `deep`.
|
||||
'Shallow' threading makes every mail a reply to the head of the
|
||||
series, where the head is chosen from the cover letter, the
|
||||
`\--in-reply-to`, and the first patch mail, in this order. 'Deep'
|
||||
threading makes every mail a reply to the previous one. If not
|
||||
specified, defaults to the 'format.thread' configuration, or `shallow`
|
||||
if that is not set.
|
||||
|
||||
--in-reply-to=Message-Id::
|
||||
Make the first mail (or all the mails with --no-thread) appear as a
|
||||
@@ -174,7 +187,8 @@ CONFIGURATION
|
||||
-------------
|
||||
You can specify extra mail header lines to be added to each message
|
||||
in the repository configuration, new defaults for the subject prefix
|
||||
and file suffix, and number patches when outputting more than one.
|
||||
and file suffix, control attachements, and number patches when outputting
|
||||
more than one.
|
||||
|
||||
------------
|
||||
[format]
|
||||
@@ -183,6 +197,7 @@ and file suffix, and number patches when outputting more than one.
|
||||
suffix = .txt
|
||||
numbered = auto
|
||||
cc = <email>
|
||||
attach [ = mime-boundary-string ]
|
||||
------------
|
||||
|
||||
|
||||
|
||||
@@ -64,6 +64,13 @@ imap.sslverify::
|
||||
used by the SSL/TLS connection. Default is `true`. Ignored when
|
||||
imap.tunnel is set.
|
||||
|
||||
imap.preformattedHTML::
|
||||
A boolean to enable/disable the use of html encoding when sending
|
||||
a patch. An html encoded patch will be bracketed with <pre>
|
||||
and have a content type of text/html. Ironically, enabling this
|
||||
option causes Thunderbird to send the patch as a plain/text,
|
||||
format=fixed email. Default is `false`.
|
||||
|
||||
Examples
|
||||
~~~~~~~~
|
||||
|
||||
|
||||
@@ -192,6 +192,13 @@ Alternatively, you can undo the 'git-rebase' with
|
||||
|
||||
git rebase --abort
|
||||
|
||||
CONFIGURATION
|
||||
-------------
|
||||
|
||||
rebase.stat::
|
||||
Whether to show a diffstat of what changed upstream since the last
|
||||
rebase. False by default.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
<newbase>::
|
||||
@@ -232,7 +239,15 @@ OPTIONS
|
||||
|
||||
-v::
|
||||
--verbose::
|
||||
Display a diffstat of what changed upstream since the last rebase.
|
||||
Be verbose. Implies --stat.
|
||||
|
||||
--stat::
|
||||
Show a diffstat of what changed upstream since the last rebase. The
|
||||
diffstat is also controlled by the configuration option rebase.stat.
|
||||
|
||||
-n::
|
||||
--no-stat::
|
||||
Do not show a diffstat as part of the rebase process.
|
||||
|
||||
--no-verify::
|
||||
This option bypasses the pre-rebase hook. See also linkgit:githooks[5].
|
||||
|
||||
@@ -177,14 +177,25 @@ Automating
|
||||
|
||||
--suppress-cc::
|
||||
Specify an additional category of recipients to suppress the
|
||||
auto-cc of. 'self' will avoid including the sender, 'author' will
|
||||
avoid including the patch author, 'cc' will avoid including anyone
|
||||
mentioned in Cc lines in the patch, 'sob' will avoid including
|
||||
anyone mentioned in Signed-off-by lines, and 'cccmd' will avoid
|
||||
running the --cc-cmd. 'all' will suppress all auto cc values.
|
||||
Default is the value of 'sendemail.suppresscc' configuration value;
|
||||
if that is unspecified, default to 'self' if --suppress-from is
|
||||
specified, as well as 'sob' if --no-signed-off-cc is specified.
|
||||
auto-cc of:
|
||||
+
|
||||
--
|
||||
- 'author' will avoid including the patch author
|
||||
- 'self' will avoid including the sender
|
||||
- 'cc' will avoid including anyone mentioned in Cc lines in the patch header
|
||||
except for self (use 'self' for that).
|
||||
- 'ccbody' will avoid including anyone mentioned in Cc lines in the
|
||||
patch body (commit message) except for self (use 'self' for that).
|
||||
- 'sob' will avoid including anyone mentioned in Signed-off-by lines except
|
||||
for self (use 'self' for that).
|
||||
- 'cccmd' will avoid running the --cc-cmd.
|
||||
- 'body' is equivalent to 'sob' + 'ccbody'
|
||||
- 'all' will suppress all auto cc values.
|
||||
--
|
||||
+
|
||||
Default is the value of 'sendemail.suppresscc' configuration value; if
|
||||
that is unspecified, default to 'self' if --suppress-from is
|
||||
specified, as well as 'body' if --no-signed-off-cc is specified.
|
||||
|
||||
--[no-]suppress-from::
|
||||
If this is set, do not add the From: address to the cc: list.
|
||||
@@ -201,6 +212,22 @@ Automating
|
||||
Administering
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
--confirm::
|
||||
Confirm just before sending:
|
||||
+
|
||||
--
|
||||
- 'always' will always confirm before sending
|
||||
- 'never' will never confirm before sending
|
||||
- 'cc' will confirm before sending when send-email has automatically
|
||||
added addresses from the patch to the Cc list
|
||||
- 'compose' will confirm before sending the first message when using --compose.
|
||||
- 'auto' is equivalent to 'cc' + 'compose'
|
||||
--
|
||||
+
|
||||
Default is the value of 'sendemail.confirm' configuration value; if that
|
||||
is unspecified, default to 'auto' unless any of the suppress options
|
||||
have been specified, in which case default to 'compose'.
|
||||
|
||||
--dry-run::
|
||||
Do everything except actually send the emails.
|
||||
|
||||
@@ -244,6 +271,11 @@ sendemail.multiedit::
|
||||
summary when '--compose' is used). If false, files will be edited one
|
||||
after the other, spawning a new editor each time.
|
||||
|
||||
sendemail.confirm::
|
||||
Sets the default for whether to confirm before sending. Must be
|
||||
one of 'always', 'never', 'cc', 'compose', or 'auto'. See '--confirm'
|
||||
in the previous section for the meaning of these values.
|
||||
|
||||
|
||||
Author
|
||||
------
|
||||
|
||||
@@ -43,9 +43,10 @@ unreleased) version of git, that is available from 'master'
|
||||
branch of the `git.git` repository.
|
||||
Documentation for older releases are available here:
|
||||
|
||||
* link:v1.6.2/git.html[documentation for release 1.6.2]
|
||||
* link:v1.6.2.1/git.html[documentation for release 1.6.2.1]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes-1.6.2.1.txt[1.6.2.1],
|
||||
link:RelNotes-1.6.2.txt[1.6.2].
|
||||
|
||||
* link:v1.6.1.3/git.html[documentation for release 1.6.1.3]
|
||||
|
||||
@@ -152,3 +152,12 @@ $ git log -2 --pretty=tformat:%h 4da45bef \
|
||||
4da45be
|
||||
7134973
|
||||
---------------------
|
||||
+
|
||||
In addition, any unrecognized string that has a `%` in it is interpreted
|
||||
as if it has `tformat:` in front of it. For example, these two are
|
||||
equivalent:
|
||||
+
|
||||
---------------------
|
||||
$ git log -2 --pretty=tformat:%h 4da45bef
|
||||
$ git log -2 --pretty=%h 4da45bef
|
||||
---------------------
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
--pretty[='<format>']::
|
||||
--format[='<format>']::
|
||||
|
||||
Pretty-print the contents of the commit logs in a given format,
|
||||
where '<format>' can be one of 'oneline', 'short', 'medium',
|
||||
@@ -17,6 +18,10 @@ configuration (see linkgit:git-config[1]).
|
||||
This should make "--pretty=oneline" a whole lot more readable for
|
||||
people using 80-column terminals.
|
||||
|
||||
--oneline::
|
||||
This is a shorthand for "--pretty=oneline --abbrev-commit"
|
||||
used together.
|
||||
|
||||
--encoding[=<encoding>]::
|
||||
The commit objects record the encoding used for the log message
|
||||
in their encoding header; this option can be used to tell the
|
||||
|
||||
@@ -568,11 +568,11 @@ This outputs all the commit objects between the included and excluded
|
||||
commits, ordered by their distance to the included and excluded
|
||||
commits. The farthest from them is displayed first. (This is the only
|
||||
one displayed by `--bisect`.)
|
||||
|
||||
+
|
||||
This is useful because it makes it easy to choose a good commit to
|
||||
test when you want to avoid to test some of them for some reason (they
|
||||
may not compile for example).
|
||||
|
||||
+
|
||||
This option can be used along with `--bisect-vars`, in this case,
|
||||
after all the sorted commit objects, there will be the same text as if
|
||||
`--bisect-vars` had been used alone.
|
||||
|
||||
@@ -66,6 +66,12 @@ Steps to parse options
|
||||
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
|
||||
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
|
||||
before the full parser, which in turn shows the full help message.
|
||||
+
|
||||
Flags are the bitwise-or of:
|
||||
|
||||
`PARSE_OPT_KEEP_DASHDASH`::
|
||||
@@ -77,6 +83,28 @@ Flags are the bitwise-or of:
|
||||
Using this flag, processing is stopped at the first non-option
|
||||
argument.
|
||||
|
||||
`PARSE_OPT_KEEP_ARGV0`::
|
||||
Keep the first argument, which contains the program name. It's
|
||||
removed from argv[] by default.
|
||||
|
||||
`PARSE_OPT_KEEP_UNKNOWN`::
|
||||
Keep unknown arguments instead of erroring out. This doesn't
|
||||
work for all combinations of arguments as users might expect
|
||||
it to do. E.g. if the first argument in `--unknown --known`
|
||||
takes a value (which we can't know), the second one is
|
||||
mistakenly interpreted as a known option. Similarly, if
|
||||
`PARSE_OPT_STOP_AT_NON_OPTION` is set, the second argument in
|
||||
`--unknown value` will be mistakenly interpreted as a
|
||||
non-option, not as a value belonging to the unknown option,
|
||||
the parser early. That's why parse_options() errors out if
|
||||
both options are set.
|
||||
|
||||
`PARSE_OPT_NO_INTERNAL_HELP`::
|
||||
By default, parse_options() handles `-h`, `--help` and
|
||||
`--help-all` internally, by showing a help screen. This option
|
||||
turns it off and allows one to add custom handlers for these
|
||||
options, or to just leave them unknown.
|
||||
|
||||
Data Structure
|
||||
--------------
|
||||
|
||||
|
||||
24
Makefile
24
Makefile
@@ -1646,3 +1646,27 @@ check-docs::
|
||||
check-builtins::
|
||||
./check-builtins.sh
|
||||
|
||||
### Test suite coverage testing
|
||||
#
|
||||
.PHONY: coverage coverage-clean coverage-build coverage-report
|
||||
|
||||
coverage:
|
||||
$(MAKE) coverage-build
|
||||
$(MAKE) coverage-report
|
||||
|
||||
coverage-clean:
|
||||
rm -f *.gcda *.gcno
|
||||
|
||||
COVERAGE_CFLAGS = $(CFLAGS) -O0 -ftest-coverage -fprofile-arcs
|
||||
COVERAGE_LDFLAGS = $(CFLAGS) -O0 -lgcov
|
||||
|
||||
coverage-build: coverage-clean
|
||||
$(MAKE) CFLAGS="$(COVERAGE_CFLAGS)" LDFLAGS="$(COVERAGE_LDFLAGS)" all
|
||||
$(MAKE) CFLAGS="$(COVERAGE_CFLAGS)" LDFLAGS="$(COVERAGE_LDFLAGS)" \
|
||||
-j1 test
|
||||
|
||||
coverage-report:
|
||||
gcov -b *.c
|
||||
grep '^function.*called 0 ' *.c.gcov \
|
||||
| sed -e 's/\([^:]*\)\.gcov: *function \([^ ]*\) called.*/\1: \2/' \
|
||||
| tee coverage-untested-functions
|
||||
|
||||
@@ -253,6 +253,7 @@ static int parse_archive_args(int argc, const char **argv,
|
||||
const char *base = NULL;
|
||||
const char *remote = NULL;
|
||||
const char *exec = NULL;
|
||||
const char *output = NULL;
|
||||
int compression_level = -1;
|
||||
int verbose = 0;
|
||||
int i;
|
||||
@@ -262,6 +263,8 @@ static int parse_archive_args(int argc, const char **argv,
|
||||
OPT_STRING(0, "format", &format, "fmt", "archive format"),
|
||||
OPT_STRING(0, "prefix", &base, "prefix",
|
||||
"prepend prefix to each pathname in the archive"),
|
||||
OPT_STRING(0, "output", &output, "file",
|
||||
"write the archive to this file"),
|
||||
OPT__VERBOSE(&verbose),
|
||||
OPT__COMPR('0', &compression_level, "store only", 0),
|
||||
OPT__COMPR('1', &compression_level, "compress faster", 1),
|
||||
@@ -290,6 +293,8 @@ static int parse_archive_args(int argc, const char **argv,
|
||||
die("Unexpected option --remote");
|
||||
if (exec)
|
||||
die("Option --exec can only be used together with --remote");
|
||||
if (output)
|
||||
die("Unexpected option --output");
|
||||
|
||||
if (!base)
|
||||
base = "";
|
||||
|
||||
@@ -5,44 +5,35 @@
|
||||
#include "cache.h"
|
||||
#include "builtin.h"
|
||||
#include "archive.h"
|
||||
#include "parse-options.h"
|
||||
#include "pkt-line.h"
|
||||
#include "sideband.h"
|
||||
|
||||
static int run_remote_archiver(const char *remote, int argc,
|
||||
const char **argv)
|
||||
static void create_output_file(const char *output_file)
|
||||
{
|
||||
int output_fd = open(output_file, O_CREAT | O_WRONLY | O_TRUNC, 0666);
|
||||
if (output_fd < 0)
|
||||
die("could not create archive file: %s ", output_file);
|
||||
if (output_fd != 1) {
|
||||
if (dup2(output_fd, 1) < 0)
|
||||
die("could not redirect output");
|
||||
else
|
||||
close(output_fd);
|
||||
}
|
||||
}
|
||||
|
||||
static int run_remote_archiver(int argc, const char **argv,
|
||||
const char *remote, const char *exec)
|
||||
{
|
||||
char *url, buf[LARGE_PACKET_MAX];
|
||||
int fd[2], i, len, rv;
|
||||
struct child_process *conn;
|
||||
const char *exec = "git-upload-archive";
|
||||
int exec_at = 0, exec_value_at = 0;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
if (!prefixcmp(arg, "--exec=")) {
|
||||
if (exec_at)
|
||||
die("multiple --exec specified");
|
||||
exec = arg + 7;
|
||||
exec_at = i;
|
||||
} else if (!strcmp(arg, "--exec")) {
|
||||
if (exec_at)
|
||||
die("multiple --exec specified");
|
||||
if (i + 1 >= argc)
|
||||
die("option --exec requires a value");
|
||||
exec = argv[i + 1];
|
||||
exec_at = i;
|
||||
exec_value_at = ++i;
|
||||
}
|
||||
}
|
||||
|
||||
url = xstrdup(remote);
|
||||
conn = git_connect(fd, url, exec, 0);
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (i == exec_at || i == exec_value_at)
|
||||
continue;
|
||||
for (i = 1; i < argc; i++)
|
||||
packet_write(fd[1], "argument %s\n", argv[i]);
|
||||
}
|
||||
packet_flush(fd[1]);
|
||||
|
||||
len = packet_read_line(fd[0], buf, sizeof(buf));
|
||||
@@ -69,51 +60,33 @@ static int run_remote_archiver(const char *remote, int argc,
|
||||
return !!rv;
|
||||
}
|
||||
|
||||
static const char *extract_remote_arg(int *ac, const char **av)
|
||||
{
|
||||
int ix, iy, cnt = *ac;
|
||||
int no_more_options = 0;
|
||||
const char *remote = NULL;
|
||||
|
||||
for (ix = iy = 1; ix < cnt; ix++) {
|
||||
const char *arg = av[ix];
|
||||
if (!strcmp(arg, "--"))
|
||||
no_more_options = 1;
|
||||
if (!no_more_options) {
|
||||
if (!prefixcmp(arg, "--remote=")) {
|
||||
if (remote)
|
||||
die("Multiple --remote specified");
|
||||
remote = arg + 9;
|
||||
continue;
|
||||
} else if (!strcmp(arg, "--remote")) {
|
||||
if (remote)
|
||||
die("Multiple --remote specified");
|
||||
if (++ix >= cnt)
|
||||
die("option --remote requires a value");
|
||||
remote = av[ix];
|
||||
continue;
|
||||
}
|
||||
if (arg[0] != '-')
|
||||
no_more_options = 1;
|
||||
}
|
||||
if (ix != iy)
|
||||
av[iy] = arg;
|
||||
iy++;
|
||||
}
|
||||
if (remote) {
|
||||
av[--cnt] = NULL;
|
||||
*ac = cnt;
|
||||
}
|
||||
return remote;
|
||||
}
|
||||
#define PARSE_OPT_KEEP_ALL ( PARSE_OPT_KEEP_DASHDASH | \
|
||||
PARSE_OPT_KEEP_ARGV0 | \
|
||||
PARSE_OPT_KEEP_UNKNOWN | \
|
||||
PARSE_OPT_NO_INTERNAL_HELP )
|
||||
|
||||
int cmd_archive(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
const char *exec = "git-upload-archive";
|
||||
const char *output = NULL;
|
||||
const char *remote = NULL;
|
||||
struct option local_opts[] = {
|
||||
OPT_STRING(0, "output", &output, "file",
|
||||
"write the archive to this file"),
|
||||
OPT_STRING(0, "remote", &remote, "repo",
|
||||
"retrieve the archive from remote repository <repo>"),
|
||||
OPT_STRING(0, "exec", &exec, "cmd",
|
||||
"path to the remote git-upload-archive command"),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
argc = parse_options(argc, argv, local_opts, NULL, PARSE_OPT_KEEP_ALL);
|
||||
|
||||
if (output)
|
||||
create_output_file(output);
|
||||
|
||||
remote = extract_remote_arg(&argc, argv);
|
||||
if (remote)
|
||||
return run_remote_archiver(remote, argc, argv);
|
||||
return run_remote_archiver(argc, argv, remote, exec);
|
||||
|
||||
setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
|
||||
|
||||
|
||||
174
builtin-blame.c
174
builtin-blame.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Pickaxe
|
||||
* Blame
|
||||
*
|
||||
* Copyright (c) 2006, Junio C Hamano
|
||||
*/
|
||||
@@ -40,6 +40,10 @@ static int reverse;
|
||||
static int blank_boundary;
|
||||
static int incremental;
|
||||
static int xdl_opts = XDF_NEED_MINIMAL;
|
||||
|
||||
static enum date_mode blame_date_mode = DATE_ISO8601;
|
||||
static size_t blame_date_width;
|
||||
|
||||
static struct string_list mailmap;
|
||||
|
||||
#ifndef DEBUG
|
||||
@@ -74,6 +78,7 @@ static unsigned blame_copy_score;
|
||||
*/
|
||||
struct origin {
|
||||
int refcnt;
|
||||
struct origin *previous;
|
||||
struct commit *commit;
|
||||
mmfile_t file;
|
||||
unsigned char blob_sha1[20];
|
||||
@@ -115,6 +120,8 @@ static inline struct origin *origin_incref(struct origin *o)
|
||||
static void origin_decref(struct origin *o)
|
||||
{
|
||||
if (o && --o->refcnt <= 0) {
|
||||
if (o->previous)
|
||||
origin_decref(o->previous);
|
||||
free(o->file.ptr);
|
||||
free(o);
|
||||
}
|
||||
@@ -1198,6 +1205,10 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
|
||||
struct origin *porigin = sg_origin[i];
|
||||
if (!porigin)
|
||||
continue;
|
||||
if (!origin->previous) {
|
||||
origin_incref(porigin);
|
||||
origin->previous = porigin;
|
||||
}
|
||||
if (pass_blame_to_parent(sb, origin, porigin))
|
||||
goto finish;
|
||||
}
|
||||
@@ -1414,6 +1425,39 @@ static void write_filename_info(const char *path)
|
||||
write_name_quoted(path, stdout, '\n');
|
||||
}
|
||||
|
||||
/*
|
||||
* Porcelain/Incremental format wants to show a lot of details per
|
||||
* commit. Instead of repeating this every line, emit it only once,
|
||||
* the first time each commit appears in the output.
|
||||
*/
|
||||
static int emit_one_suspect_detail(struct origin *suspect)
|
||||
{
|
||||
struct commit_info ci;
|
||||
|
||||
if (suspect->commit->object.flags & METAINFO_SHOWN)
|
||||
return 0;
|
||||
|
||||
suspect->commit->object.flags |= METAINFO_SHOWN;
|
||||
get_commit_info(suspect->commit, &ci, 1);
|
||||
printf("author %s\n", ci.author);
|
||||
printf("author-mail %s\n", ci.author_mail);
|
||||
printf("author-time %lu\n", ci.author_time);
|
||||
printf("author-tz %s\n", ci.author_tz);
|
||||
printf("committer %s\n", ci.committer);
|
||||
printf("committer-mail %s\n", ci.committer_mail);
|
||||
printf("committer-time %lu\n", ci.committer_time);
|
||||
printf("committer-tz %s\n", ci.committer_tz);
|
||||
printf("summary %s\n", ci.summary);
|
||||
if (suspect->commit->object.flags & UNINTERESTING)
|
||||
printf("boundary\n");
|
||||
if (suspect->previous) {
|
||||
struct origin *prev = suspect->previous;
|
||||
printf("previous %s ", sha1_to_hex(prev->commit->object.sha1));
|
||||
write_name_quoted(prev->path, stdout, '\n');
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The blame_entry is found to be guilty for the range. Mark it
|
||||
* as such, and show it in incremental output.
|
||||
@@ -1429,22 +1473,7 @@ static void found_guilty_entry(struct blame_entry *ent)
|
||||
printf("%s %d %d %d\n",
|
||||
sha1_to_hex(suspect->commit->object.sha1),
|
||||
ent->s_lno + 1, ent->lno + 1, ent->num_lines);
|
||||
if (!(suspect->commit->object.flags & METAINFO_SHOWN)) {
|
||||
struct commit_info ci;
|
||||
suspect->commit->object.flags |= METAINFO_SHOWN;
|
||||
get_commit_info(suspect->commit, &ci, 1);
|
||||
printf("author %s\n", ci.author);
|
||||
printf("author-mail %s\n", ci.author_mail);
|
||||
printf("author-time %lu\n", ci.author_time);
|
||||
printf("author-tz %s\n", ci.author_tz);
|
||||
printf("committer %s\n", ci.committer);
|
||||
printf("committer-mail %s\n", ci.committer_mail);
|
||||
printf("committer-time %lu\n", ci.committer_time);
|
||||
printf("committer-tz %s\n", ci.committer_tz);
|
||||
printf("summary %s\n", ci.summary);
|
||||
if (suspect->commit->object.flags & UNINTERESTING)
|
||||
printf("boundary\n");
|
||||
}
|
||||
emit_one_suspect_detail(suspect);
|
||||
write_filename_info(suspect->path);
|
||||
maybe_flush_or_die(stdout, "stdout");
|
||||
}
|
||||
@@ -1507,24 +1536,20 @@ static const char *format_time(unsigned long time, const char *tz_str,
|
||||
int show_raw_time)
|
||||
{
|
||||
static char time_buf[128];
|
||||
time_t t = time;
|
||||
int minutes, tz;
|
||||
struct tm *tm;
|
||||
const char *time_str;
|
||||
int time_len;
|
||||
int tz;
|
||||
|
||||
if (show_raw_time) {
|
||||
sprintf(time_buf, "%lu %s", time, tz_str);
|
||||
return time_buf;
|
||||
}
|
||||
|
||||
tz = atoi(tz_str);
|
||||
minutes = tz < 0 ? -tz : tz;
|
||||
minutes = (minutes / 100)*60 + (minutes % 100);
|
||||
minutes = tz < 0 ? -minutes : minutes;
|
||||
t = time + minutes * 60;
|
||||
tm = gmtime(&t);
|
||||
|
||||
strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S ", tm);
|
||||
strcat(time_buf, tz_str);
|
||||
else {
|
||||
tz = atoi(tz_str);
|
||||
time_str = show_date(time, tz, blame_date_mode);
|
||||
time_len = strlen(time_str);
|
||||
memcpy(time_buf, time_str, time_len);
|
||||
memset(time_buf + time_len, ' ', blame_date_width - time_len);
|
||||
}
|
||||
return time_buf;
|
||||
}
|
||||
|
||||
@@ -1551,24 +1576,8 @@ static void emit_porcelain(struct scoreboard *sb, struct blame_entry *ent)
|
||||
ent->s_lno + 1,
|
||||
ent->lno + 1,
|
||||
ent->num_lines);
|
||||
if (!(suspect->commit->object.flags & METAINFO_SHOWN)) {
|
||||
struct commit_info ci;
|
||||
suspect->commit->object.flags |= METAINFO_SHOWN;
|
||||
get_commit_info(suspect->commit, &ci, 1);
|
||||
printf("author %s\n", ci.author);
|
||||
printf("author-mail %s\n", ci.author_mail);
|
||||
printf("author-time %lu\n", ci.author_time);
|
||||
printf("author-tz %s\n", ci.author_tz);
|
||||
printf("committer %s\n", ci.committer);
|
||||
printf("committer-mail %s\n", ci.committer_mail);
|
||||
printf("committer-time %lu\n", ci.committer_time);
|
||||
printf("committer-tz %s\n", ci.committer_tz);
|
||||
write_filename_info(suspect->path);
|
||||
printf("summary %s\n", ci.summary);
|
||||
if (suspect->commit->object.flags & UNINTERESTING)
|
||||
printf("boundary\n");
|
||||
}
|
||||
else if (suspect->commit->object.flags & MORE_THAN_ONE_PATH)
|
||||
if (emit_one_suspect_detail(suspect) ||
|
||||
(suspect->commit->object.flags & MORE_THAN_ONE_PATH))
|
||||
write_filename_info(suspect->path);
|
||||
|
||||
cp = nth_line(sb, ent->lno);
|
||||
@@ -1806,36 +1815,6 @@ static void sanity_check_refcnt(struct scoreboard *sb)
|
||||
baa = 1;
|
||||
}
|
||||
}
|
||||
for (ent = sb->ent; ent; ent = ent->next) {
|
||||
/* Mark the ones that haven't been checked */
|
||||
if (0 < ent->suspect->refcnt)
|
||||
ent->suspect->refcnt = -ent->suspect->refcnt;
|
||||
}
|
||||
for (ent = sb->ent; ent; ent = ent->next) {
|
||||
/*
|
||||
* ... then pick each and see if they have the the
|
||||
* correct refcnt.
|
||||
*/
|
||||
int found;
|
||||
struct blame_entry *e;
|
||||
struct origin *suspect = ent->suspect;
|
||||
|
||||
if (0 < suspect->refcnt)
|
||||
continue;
|
||||
suspect->refcnt = -suspect->refcnt; /* Unmark */
|
||||
for (found = 0, e = sb->ent; e; e = e->next) {
|
||||
if (e->suspect != suspect)
|
||||
continue;
|
||||
found++;
|
||||
}
|
||||
if (suspect->refcnt != found) {
|
||||
fprintf(stderr, "%s in %s has refcnt %d, not %d\n",
|
||||
ent->suspect->path,
|
||||
sha1_to_hex(ent->suspect->commit->object.sha1),
|
||||
ent->suspect->refcnt, found);
|
||||
baa = 2;
|
||||
}
|
||||
}
|
||||
if (baa) {
|
||||
int opt = 0160;
|
||||
find_alignment(sb, &opt);
|
||||
@@ -1975,6 +1954,12 @@ static int git_blame_config(const char *var, const char *value, void *cb)
|
||||
blank_boundary = git_config_bool(var, value);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(var, "blame.date")) {
|
||||
if (!value)
|
||||
return config_error_nonbool(var);
|
||||
blame_date_mode = parse_date_format(value);
|
||||
return 0;
|
||||
}
|
||||
return git_default_config(var, value, cb);
|
||||
}
|
||||
|
||||
@@ -2239,6 +2224,8 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
|
||||
|
||||
git_config(git_blame_config, NULL);
|
||||
init_revisions(&revs, NULL);
|
||||
revs.date_mode = blame_date_mode;
|
||||
|
||||
save_commit_buffer = 0;
|
||||
dashdash_pos = 0;
|
||||
|
||||
@@ -2263,8 +2250,35 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
|
||||
parse_done:
|
||||
argc = parse_options_end(&ctx);
|
||||
|
||||
if (cmd_is_annotate)
|
||||
if (cmd_is_annotate) {
|
||||
output_option |= OUTPUT_ANNOTATE_COMPAT;
|
||||
blame_date_mode = DATE_ISO8601;
|
||||
} else {
|
||||
blame_date_mode = revs.date_mode;
|
||||
}
|
||||
|
||||
/* The maximum width used to show the dates */
|
||||
switch (blame_date_mode) {
|
||||
case DATE_RFC2822:
|
||||
blame_date_width = sizeof("Thu, 19 Oct 2006 16:00:04 -0700");
|
||||
break;
|
||||
case DATE_ISO8601:
|
||||
blame_date_width = sizeof("2006-10-19 16:00:04 -0700");
|
||||
break;
|
||||
case DATE_RAW:
|
||||
blame_date_width = sizeof("1161298804 -0700");
|
||||
break;
|
||||
case DATE_SHORT:
|
||||
blame_date_width = sizeof("2006-10-19");
|
||||
break;
|
||||
case DATE_RELATIVE:
|
||||
/* "normal" is used as the fallback for "relative" */
|
||||
case DATE_LOCAL:
|
||||
case DATE_NORMAL:
|
||||
blame_date_width = sizeof("Thu Oct 19 16:00:04 2006 -0700");
|
||||
break;
|
||||
}
|
||||
blame_date_width -= 1; /* strip the null */
|
||||
|
||||
if (DIFF_OPT_TST(&revs.diffopt, FIND_COPIES_HARDER))
|
||||
opt |= (PICKAXE_BLAME_COPY | PICKAXE_BLAME_MOVE |
|
||||
|
||||
149
builtin-branch.c
149
builtin-branch.c
@@ -32,18 +32,18 @@ static unsigned char head_sha1[20];
|
||||
|
||||
static int branch_use_color = -1;
|
||||
static char branch_colors[][COLOR_MAXLEN] = {
|
||||
"\033[m", /* reset */
|
||||
"", /* PLAIN (normal) */
|
||||
"\033[31m", /* REMOTE (red) */
|
||||
"", /* LOCAL (normal) */
|
||||
"\033[32m", /* CURRENT (green) */
|
||||
GIT_COLOR_RESET,
|
||||
GIT_COLOR_NORMAL, /* PLAIN */
|
||||
GIT_COLOR_RED, /* REMOTE */
|
||||
GIT_COLOR_NORMAL, /* LOCAL */
|
||||
GIT_COLOR_GREEN, /* CURRENT */
|
||||
};
|
||||
enum color_branch {
|
||||
COLOR_BRANCH_RESET = 0,
|
||||
COLOR_BRANCH_PLAIN = 1,
|
||||
COLOR_BRANCH_REMOTE = 2,
|
||||
COLOR_BRANCH_LOCAL = 3,
|
||||
COLOR_BRANCH_CURRENT = 4,
|
||||
BRANCH_COLOR_RESET = 0,
|
||||
BRANCH_COLOR_PLAIN = 1,
|
||||
BRANCH_COLOR_REMOTE = 2,
|
||||
BRANCH_COLOR_LOCAL = 3,
|
||||
BRANCH_COLOR_CURRENT = 4,
|
||||
};
|
||||
|
||||
static enum merge_filter {
|
||||
@@ -56,15 +56,15 @@ static unsigned char merge_filter_ref[20];
|
||||
static int parse_branch_color_slot(const char *var, int ofs)
|
||||
{
|
||||
if (!strcasecmp(var+ofs, "plain"))
|
||||
return COLOR_BRANCH_PLAIN;
|
||||
return BRANCH_COLOR_PLAIN;
|
||||
if (!strcasecmp(var+ofs, "reset"))
|
||||
return COLOR_BRANCH_RESET;
|
||||
return BRANCH_COLOR_RESET;
|
||||
if (!strcasecmp(var+ofs, "remote"))
|
||||
return COLOR_BRANCH_REMOTE;
|
||||
return BRANCH_COLOR_REMOTE;
|
||||
if (!strcasecmp(var+ofs, "local"))
|
||||
return COLOR_BRANCH_LOCAL;
|
||||
return BRANCH_COLOR_LOCAL;
|
||||
if (!strcasecmp(var+ofs, "current"))
|
||||
return COLOR_BRANCH_CURRENT;
|
||||
return BRANCH_COLOR_CURRENT;
|
||||
die("bad config variable '%s'", var);
|
||||
}
|
||||
|
||||
@@ -188,7 +188,8 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)
|
||||
|
||||
struct ref_item {
|
||||
char *name;
|
||||
unsigned int kind;
|
||||
char *dest;
|
||||
unsigned int kind, len;
|
||||
struct commit *commit;
|
||||
};
|
||||
|
||||
@@ -200,22 +201,47 @@ struct ref_list {
|
||||
int kinds;
|
||||
};
|
||||
|
||||
static char *resolve_symref(const char *src, const char *prefix)
|
||||
{
|
||||
unsigned char sha1[20];
|
||||
int flag;
|
||||
const char *dst, *cp;
|
||||
|
||||
dst = resolve_ref(src, sha1, 0, &flag);
|
||||
if (!(dst && (flag & REF_ISSYMREF)))
|
||||
return NULL;
|
||||
if (prefix && (cp = skip_prefix(dst, prefix)))
|
||||
dst = cp;
|
||||
return xstrdup(dst);
|
||||
}
|
||||
|
||||
static int append_ref(const char *refname, const unsigned char *sha1, int flags, void *cb_data)
|
||||
{
|
||||
struct ref_list *ref_list = (struct ref_list*)(cb_data);
|
||||
struct ref_item *newitem;
|
||||
struct commit *commit;
|
||||
int kind;
|
||||
int len;
|
||||
int kind, i;
|
||||
const char *prefix, *orig_refname = refname;
|
||||
|
||||
static struct {
|
||||
int kind;
|
||||
const char *prefix;
|
||||
int pfxlen;
|
||||
} ref_kind[] = {
|
||||
{ REF_LOCAL_BRANCH, "refs/heads/", 11 },
|
||||
{ REF_REMOTE_BRANCH, "refs/remotes/", 13 },
|
||||
};
|
||||
|
||||
/* Detect kind */
|
||||
if (!prefixcmp(refname, "refs/heads/")) {
|
||||
kind = REF_LOCAL_BRANCH;
|
||||
refname += 11;
|
||||
} else if (!prefixcmp(refname, "refs/remotes/")) {
|
||||
kind = REF_REMOTE_BRANCH;
|
||||
refname += 13;
|
||||
} else
|
||||
for (i = 0; i < ARRAY_SIZE(ref_kind); i++) {
|
||||
prefix = ref_kind[i].prefix;
|
||||
if (strncmp(refname, prefix, ref_kind[i].pfxlen))
|
||||
continue;
|
||||
kind = ref_kind[i].kind;
|
||||
refname += ref_kind[i].pfxlen;
|
||||
break;
|
||||
}
|
||||
if (ARRAY_SIZE(ref_kind) <= i)
|
||||
return 0;
|
||||
|
||||
commit = lookup_commit_reference_gently(sha1, 1);
|
||||
@@ -246,9 +272,14 @@ static int append_ref(const char *refname, const unsigned char *sha1, int flags,
|
||||
newitem->name = xstrdup(refname);
|
||||
newitem->kind = kind;
|
||||
newitem->commit = commit;
|
||||
len = strlen(newitem->name);
|
||||
if (len > ref_list->maxwidth)
|
||||
ref_list->maxwidth = len;
|
||||
newitem->len = strlen(refname);
|
||||
newitem->dest = resolve_symref(orig_refname, prefix);
|
||||
/* adjust for "remotes/" */
|
||||
if (newitem->kind == REF_REMOTE_BRANCH &&
|
||||
ref_list->kinds != REF_REMOTE_BRANCH)
|
||||
newitem->len += 8;
|
||||
if (newitem->len > ref_list->maxwidth)
|
||||
ref_list->maxwidth = newitem->len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -257,8 +288,10 @@ static void free_ref_list(struct ref_list *ref_list)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ref_list->index; i++)
|
||||
for (i = 0; i < ref_list->index; i++) {
|
||||
free(ref_list->list[i].name);
|
||||
free(ref_list->list[i].dest);
|
||||
}
|
||||
free(ref_list->list);
|
||||
}
|
||||
|
||||
@@ -299,34 +332,46 @@ static int matches_merge_filter(struct commit *commit)
|
||||
}
|
||||
|
||||
static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
|
||||
int abbrev, int current)
|
||||
int abbrev, int current, char *prefix)
|
||||
{
|
||||
char c;
|
||||
int color;
|
||||
struct commit *commit = item->commit;
|
||||
struct strbuf out = STRBUF_INIT, name = STRBUF_INIT;
|
||||
|
||||
if (!matches_merge_filter(commit))
|
||||
return;
|
||||
|
||||
switch (item->kind) {
|
||||
case REF_LOCAL_BRANCH:
|
||||
color = COLOR_BRANCH_LOCAL;
|
||||
color = BRANCH_COLOR_LOCAL;
|
||||
break;
|
||||
case REF_REMOTE_BRANCH:
|
||||
color = COLOR_BRANCH_REMOTE;
|
||||
color = BRANCH_COLOR_REMOTE;
|
||||
break;
|
||||
default:
|
||||
color = COLOR_BRANCH_PLAIN;
|
||||
color = BRANCH_COLOR_PLAIN;
|
||||
break;
|
||||
}
|
||||
|
||||
c = ' ';
|
||||
if (current) {
|
||||
c = '*';
|
||||
color = COLOR_BRANCH_CURRENT;
|
||||
color = BRANCH_COLOR_CURRENT;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
strbuf_addf(&name, "%s%s", prefix, item->name);
|
||||
if (verbose)
|
||||
strbuf_addf(&out, "%c %s%-*s%s", c, branch_get_color(color),
|
||||
maxwidth, name.buf,
|
||||
branch_get_color(BRANCH_COLOR_RESET));
|
||||
else
|
||||
strbuf_addf(&out, "%c %s%s%s", c, branch_get_color(color),
|
||||
name.buf, branch_get_color(BRANCH_COLOR_RESET));
|
||||
|
||||
if (item->dest)
|
||||
strbuf_addf(&out, " -> %s", item->dest);
|
||||
else if (verbose) {
|
||||
struct strbuf subject = STRBUF_INIT, stat = STRBUF_INIT;
|
||||
const char *sub = " **** invalid ref ****";
|
||||
|
||||
@@ -340,28 +385,25 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
|
||||
if (item->kind == REF_LOCAL_BRANCH)
|
||||
fill_tracking_info(&stat, item->name);
|
||||
|
||||
printf("%c %s%-*s%s %s %s%s\n", c, branch_get_color(color),
|
||||
maxwidth, item->name,
|
||||
branch_get_color(COLOR_BRANCH_RESET),
|
||||
find_unique_abbrev(item->commit->object.sha1, abbrev),
|
||||
stat.buf, sub);
|
||||
strbuf_addf(&out, " %s %s%s",
|
||||
find_unique_abbrev(item->commit->object.sha1, abbrev),
|
||||
stat.buf, sub);
|
||||
strbuf_release(&stat);
|
||||
strbuf_release(&subject);
|
||||
} else {
|
||||
printf("%c %s%s%s\n", c, branch_get_color(color), item->name,
|
||||
branch_get_color(COLOR_BRANCH_RESET));
|
||||
}
|
||||
printf("%s\n", out.buf);
|
||||
strbuf_release(&name);
|
||||
strbuf_release(&out);
|
||||
}
|
||||
|
||||
static int calc_maxwidth(struct ref_list *refs)
|
||||
{
|
||||
int i, l, w = 0;
|
||||
int i, w = 0;
|
||||
for (i = 0; i < refs->index; i++) {
|
||||
if (!matches_merge_filter(refs->list[i].commit))
|
||||
continue;
|
||||
l = strlen(refs->list[i].name);
|
||||
if (l > w)
|
||||
w = l;
|
||||
if (refs->list[i].len > w)
|
||||
w = refs->list[i].len;
|
||||
}
|
||||
return w;
|
||||
}
|
||||
@@ -397,11 +439,13 @@ static void print_ref_list(int kinds, int detached, int verbose, int abbrev, str
|
||||
is_descendant_of(head_commit, with_commit)) {
|
||||
struct ref_item item;
|
||||
item.name = xstrdup("(no branch)");
|
||||
item.len = strlen(item.name);
|
||||
item.kind = REF_LOCAL_BRANCH;
|
||||
item.dest = NULL;
|
||||
item.commit = head_commit;
|
||||
if (strlen(item.name) > ref_list.maxwidth)
|
||||
ref_list.maxwidth = strlen(item.name);
|
||||
print_ref_item(&item, ref_list.maxwidth, verbose, abbrev, 1);
|
||||
if (item.len > ref_list.maxwidth)
|
||||
ref_list.maxwidth = item.len;
|
||||
print_ref_item(&item, ref_list.maxwidth, verbose, abbrev, 1, "");
|
||||
free(item.name);
|
||||
}
|
||||
|
||||
@@ -409,8 +453,11 @@ static void print_ref_list(int kinds, int detached, int verbose, int abbrev, str
|
||||
int current = !detached &&
|
||||
(ref_list.list[i].kind == REF_LOCAL_BRANCH) &&
|
||||
!strcmp(ref_list.list[i].name, head);
|
||||
char *prefix = (kinds != REF_REMOTE_BRANCH &&
|
||||
ref_list.list[i].kind == REF_REMOTE_BRANCH)
|
||||
? "remotes/" : "";
|
||||
print_ref_item(&ref_list.list[i], ref_list.maxwidth, verbose,
|
||||
abbrev, current);
|
||||
abbrev, current, prefix);
|
||||
}
|
||||
|
||||
free_ref_list(&ref_list);
|
||||
|
||||
@@ -295,6 +295,8 @@ static void show_local_changes(struct object *head)
|
||||
init_revisions(&rev, NULL);
|
||||
rev.abbrev = 0;
|
||||
rev.diffopt.output_format |= DIFF_FORMAT_NAME_STATUS;
|
||||
if (diff_setup_done(&rev.diffopt) < 0)
|
||||
die("diff_setup_done failed");
|
||||
add_pending_object(&rev, head, NULL);
|
||||
run_diff_index(&rev, 0);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "dir.h"
|
||||
#include "pack-refs.h"
|
||||
#include "sigchain.h"
|
||||
#include "run-command.h"
|
||||
|
||||
/*
|
||||
* Overall FIXMEs:
|
||||
@@ -365,8 +366,6 @@ static void install_branch_config(const char *local,
|
||||
|
||||
int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int use_local_hardlinks = 1;
|
||||
int use_separate_remote = 1;
|
||||
int is_bundle = 0;
|
||||
struct stat buf;
|
||||
const char *repo_name, *repo, *work_tree, *git_dir;
|
||||
@@ -377,6 +376,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
struct strbuf branch_top = STRBUF_INIT, reflog_msg = STRBUF_INIT;
|
||||
struct transport *transport = NULL;
|
||||
char *src_ref_prefix = "refs/heads/";
|
||||
int err = 0;
|
||||
|
||||
struct refspec refspec;
|
||||
|
||||
@@ -388,9 +388,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
if (argc == 0)
|
||||
die("You must specify a repository to clone.");
|
||||
|
||||
if (option_no_hardlinks)
|
||||
use_local_hardlinks = 0;
|
||||
|
||||
if (option_mirror)
|
||||
option_bare = 1;
|
||||
|
||||
@@ -399,7 +396,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
die("--bare and --origin %s options are incompatible.",
|
||||
option_origin);
|
||||
option_no_checkout = 1;
|
||||
use_separate_remote = 0;
|
||||
}
|
||||
|
||||
if (!option_origin)
|
||||
@@ -631,6 +627,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
if (write_cache(fd, active_cache, active_nr) ||
|
||||
commit_locked_index(lock_file))
|
||||
die("unable to write new index file");
|
||||
|
||||
err |= run_hook(NULL, "post-checkout", sha1_to_hex(null_sha1),
|
||||
sha1_to_hex(remote_head->old_sha1), "1", NULL);
|
||||
}
|
||||
|
||||
strbuf_release(&reflog_msg);
|
||||
@@ -638,5 +637,5 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
strbuf_release(&key);
|
||||
strbuf_release(&value);
|
||||
junk_pid = 0;
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "color.h"
|
||||
|
||||
static const char git_config_set_usage[] =
|
||||
"git config [ --global | --system | [ -f | --file ] config-file ] [ --bool | --int | --bool-or-int ] [ -z | --null ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --remove-section name | --list | --get-color var [default] | --get-colorbool name [stdout-is-tty]";
|
||||
"git config [ --global | --system | [ -f | --file ] config-file ] [ --bool | --int | --bool-or-int ] [ -z | --null ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --remove-section name | --list | --get-color var [default] | --get-colorbool name [stdout-is-tty] | --edit | -e ]";
|
||||
|
||||
static char *key;
|
||||
static regex_t *key_regexp;
|
||||
@@ -27,7 +27,7 @@ static int show_all_config(const char *key_, const char *value_, void *cb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int show_config(const char* key_, const char* value_, void *cb)
|
||||
static int show_config(const char *key_, const char *value_, void *cb)
|
||||
{
|
||||
char value[256];
|
||||
const char *vptr = value;
|
||||
@@ -74,7 +74,7 @@ static int show_config(const char* key_, const char* value_, void *cb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_value(const char* key_, const char* regex_)
|
||||
static int get_value(const char *key_, const char *regex_)
|
||||
{
|
||||
int ret = -1;
|
||||
char *tl;
|
||||
@@ -284,7 +284,7 @@ static int get_colorbool(int argc, const char **argv)
|
||||
int cmd_config(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int nongit;
|
||||
char* value;
|
||||
char *value;
|
||||
const char *file = setup_git_directory_gently(&nongit);
|
||||
|
||||
config_exclusive_filename = getenv(CONFIG_ENVIRONMENT);
|
||||
@@ -362,6 +362,14 @@ int cmd_config(int argc, const char **argv, const char *prefix)
|
||||
return get_color(argc-2, argv+2);
|
||||
} else if (!strcmp(argv[1], "--get-colorbool")) {
|
||||
return get_colorbool(argc-2, argv+2);
|
||||
} else if (!strcmp(argv[1], "--edit") || !strcmp(argv[1], "-e")) {
|
||||
if (argc != 2)
|
||||
usage(git_config_set_usage);
|
||||
git_config(git_default_config, NULL);
|
||||
launch_editor(config_exclusive_filename ?
|
||||
config_exclusive_filename : git_path("config"),
|
||||
NULL, NULL);
|
||||
return 0;
|
||||
} else
|
||||
break;
|
||||
argc--;
|
||||
|
||||
@@ -60,7 +60,7 @@ static void count_objects(DIR *d, char *path, int len, int verbose,
|
||||
hex[40] = 0;
|
||||
if (get_sha1_hex(hex, sha1))
|
||||
die("internal error");
|
||||
if (has_sha1_pack(sha1, NULL))
|
||||
if (has_sha1_pack(sha1))
|
||||
(*packed_loose)++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +102,6 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)
|
||||
|
||||
init_revisions(opt, prefix);
|
||||
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
|
||||
nr_sha1 = 0;
|
||||
opt->abbrev = 0;
|
||||
opt->diff = 1;
|
||||
argc = setup_revisions(argc, argv, opt, NULL);
|
||||
|
||||
@@ -216,9 +216,8 @@ static int find_common(int fd[2], unsigned char *result_sha1,
|
||||
if (args.depth > 0) {
|
||||
char line[1024];
|
||||
unsigned char sha1[20];
|
||||
int len;
|
||||
|
||||
while ((len = packet_read_line(fd[0], line, sizeof(line)))) {
|
||||
while (packet_read_line(fd[0], line, sizeof(line))) {
|
||||
if (!prefixcmp(line, "shallow ")) {
|
||||
if (get_sha1_hex(line + 8, sha1))
|
||||
die("invalid shallow line: %s", line);
|
||||
|
||||
@@ -256,8 +256,7 @@ static void shortlog(const char *name, unsigned char *sha1,
|
||||
|
||||
int fmt_merge_msg(int merge_summary, struct strbuf *in, struct strbuf *out) {
|
||||
int limit = 20, i = 0, pos = 0;
|
||||
char line[1024];
|
||||
char *p = line, *sep = "";
|
||||
char *sep = "";
|
||||
unsigned char head_sha1[20];
|
||||
const char *current_branch;
|
||||
|
||||
@@ -271,9 +270,8 @@ int fmt_merge_msg(int merge_summary, struct strbuf *in, struct strbuf *out) {
|
||||
/* get a line */
|
||||
while (pos < in->len) {
|
||||
int len;
|
||||
char *newline;
|
||||
char *newline, *p = in->buf + pos;
|
||||
|
||||
p = in->buf + pos;
|
||||
newline = strchr(p, '\n');
|
||||
len = newline ? newline - p : strlen(p);
|
||||
pos += len + !!newline;
|
||||
|
||||
@@ -943,7 +943,6 @@ static int opt_parse_sort(const struct option *opt, const char *arg, int unset)
|
||||
return -1;
|
||||
|
||||
*sort_tail = s = xcalloc(1, sizeof(*s));
|
||||
sort_tail = &s->next;
|
||||
|
||||
if (*arg == '-') {
|
||||
s->reverse = 1;
|
||||
|
||||
@@ -160,7 +160,7 @@ static void check_reachable_object(struct object *obj)
|
||||
* do a full fsck
|
||||
*/
|
||||
if (!obj->parsed) {
|
||||
if (has_sha1_pack(obj->sha1, NULL))
|
||||
if (has_sha1_pack(obj->sha1))
|
||||
return; /* it is in pack - forget about it */
|
||||
printf("missing %s %s\n", typename(obj->type), sha1_to_hex(obj->sha1));
|
||||
errors_found |= ERROR_REACHABLE;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "run-command.h"
|
||||
#include "shortlog.h"
|
||||
#include "remote.h"
|
||||
#include "string-list.h"
|
||||
|
||||
/* Set a default date-time format for git log ("log.date" config variable) */
|
||||
static const char *default_date_mode = NULL;
|
||||
@@ -428,6 +429,8 @@ static const char *fmt_patch_suffix = ".patch";
|
||||
static int numbered = 0;
|
||||
static int auto_number = 1;
|
||||
|
||||
static char *default_attach = NULL;
|
||||
|
||||
static char **extra_hdr;
|
||||
static int extra_hdr_nr;
|
||||
static int extra_hdr_alloc;
|
||||
@@ -459,6 +462,10 @@ static void add_header(const char *value)
|
||||
extra_hdr[extra_hdr_nr++] = xstrndup(value, len);
|
||||
}
|
||||
|
||||
#define THREAD_SHALLOW 1
|
||||
#define THREAD_DEEP 2
|
||||
static int thread = 0;
|
||||
|
||||
static int git_format_config(const char *var, const char *value, void *cb)
|
||||
{
|
||||
if (!strcmp(var, "format.headers")) {
|
||||
@@ -488,6 +495,25 @@ static int git_format_config(const char *var, const char *value, void *cb)
|
||||
auto_number = auto_number && numbered;
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(var, "format.attach")) {
|
||||
if (value && *value)
|
||||
default_attach = xstrdup(value);
|
||||
else
|
||||
default_attach = xstrdup(git_version_string);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(var, "format.thread")) {
|
||||
if (value && !strcasecmp(value, "deep")) {
|
||||
thread = THREAD_DEEP;
|
||||
return 0;
|
||||
}
|
||||
if (value && !strcasecmp(value, "shallow")) {
|
||||
thread = THREAD_SHALLOW;
|
||||
return 0;
|
||||
}
|
||||
thread = git_config_bool(var, value) && THREAD_SHALLOW;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return git_log_config(var, value, cb);
|
||||
}
|
||||
@@ -766,7 +792,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
int numbered_files = 0; /* _just_ numbers */
|
||||
int subject_prefix = 0;
|
||||
int ignore_if_in_upstream = 0;
|
||||
int thread = 0;
|
||||
int cover_letter = 0;
|
||||
int boundary_count = 0;
|
||||
int no_binary_diff = 0;
|
||||
@@ -787,6 +812,11 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
|
||||
rev.subject_prefix = fmt_patch_subject_prefix;
|
||||
|
||||
if (default_attach) {
|
||||
rev.mime_boundary = default_attach;
|
||||
rev.no_inline = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the arguments before setup_revisions(), or something
|
||||
* like "git format-patch -o a123 HEAD^.." may fail; a123 is
|
||||
@@ -849,6 +879,10 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
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;
|
||||
@@ -859,8 +893,13 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
}
|
||||
else if (!strcmp(argv[i], "--ignore-if-in-upstream"))
|
||||
ignore_if_in_upstream = 1;
|
||||
else if (!strcmp(argv[i], "--thread"))
|
||||
thread = 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")) {
|
||||
@@ -1011,8 +1050,12 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
numbered = 1;
|
||||
if (numbered)
|
||||
rev.total = total + start_number - 1;
|
||||
if (in_reply_to)
|
||||
rev.ref_message_id = clean_message_id(in_reply_to);
|
||||
if (in_reply_to || thread || cover_letter)
|
||||
rev.ref_message_ids = xcalloc(1, sizeof(struct string_list));
|
||||
if (in_reply_to) {
|
||||
const char *msgid = clean_message_id(in_reply_to);
|
||||
string_list_append(msgid, rev.ref_message_ids);
|
||||
}
|
||||
if (cover_letter) {
|
||||
if (thread)
|
||||
gen_message_id(&rev, "cover");
|
||||
@@ -1031,15 +1074,33 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
||||
/* Have we already had a message ID? */
|
||||
if (rev.message_id) {
|
||||
/*
|
||||
* If we've got the ID to be a reply
|
||||
* to, discard the current ID;
|
||||
* otherwise, make everything a reply
|
||||
* to that.
|
||||
* For deep threading: make every mail
|
||||
* a reply to the previous one, no
|
||||
* matter what other options are set.
|
||||
*
|
||||
* For shallow threading:
|
||||
*
|
||||
* Without --cover-letter and
|
||||
* --in-reply-to, make every mail a
|
||||
* reply to the one before.
|
||||
*
|
||||
* With --in-reply-to but no
|
||||
* --cover-letter, make every mail a
|
||||
* reply to the <reply-to>.
|
||||
*
|
||||
* With --cover-letter, make every
|
||||
* mail but the cover letter a reply
|
||||
* to the cover letter. The cover
|
||||
* letter is a reply to the
|
||||
* --in-reply-to, if specified.
|
||||
*/
|
||||
if (rev.ref_message_id)
|
||||
if (thread == THREAD_SHALLOW
|
||||
&& rev.ref_message_ids->nr > 0
|
||||
&& (!cover_letter || rev.nr > 1))
|
||||
free(rev.message_id);
|
||||
else
|
||||
rev.ref_message_id = rev.message_id;
|
||||
string_list_append(rev.message_id,
|
||||
rev.ref_message_ids);
|
||||
}
|
||||
gen_message_id(&rev, sha1_to_hex(commit->object.sha1));
|
||||
}
|
||||
|
||||
@@ -537,7 +537,6 @@ static int decode_header_bq(struct strbuf *it)
|
||||
*/
|
||||
strbuf_add(&outbuf, in, ep - in);
|
||||
}
|
||||
in = ep;
|
||||
}
|
||||
/* E.g.
|
||||
* ep : "=?iso-2022-jp?B?GyR...?= foo"
|
||||
|
||||
@@ -1966,11 +1966,7 @@ static void add_objects_in_unpacked_packs(struct rev_info *revs)
|
||||
const unsigned char *sha1;
|
||||
struct object *o;
|
||||
|
||||
for (i = 0; i < revs->num_ignore_packed; i++) {
|
||||
if (matches_pack_name(p, revs->ignore_packed[i]))
|
||||
break;
|
||||
}
|
||||
if (revs->num_ignore_packed <= i)
|
||||
if (p->pack_keep)
|
||||
continue;
|
||||
if (open_pack_index(p))
|
||||
die("cannot open pack index");
|
||||
@@ -2006,11 +2002,7 @@ static void loosen_unused_packed_objects(struct rev_info *revs)
|
||||
const unsigned char *sha1;
|
||||
|
||||
for (p = packed_git; p; p = p->next) {
|
||||
for (i = 0; i < revs->num_ignore_packed; i++) {
|
||||
if (matches_pack_name(p, revs->ignore_packed[i]))
|
||||
break;
|
||||
}
|
||||
if (revs->num_ignore_packed <= i)
|
||||
if (p->pack_keep)
|
||||
continue;
|
||||
|
||||
if (open_pack_index(p))
|
||||
@@ -2208,7 +2200,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("--unpacked", arg) ||
|
||||
!prefixcmp(arg, "--unpacked=") ||
|
||||
!strcmp("--kept-pack-only", arg) ||
|
||||
!strcmp("--reflog", arg) ||
|
||||
!strcmp("--all", arg)) {
|
||||
use_internal_rev_list = 1;
|
||||
|
||||
@@ -23,7 +23,7 @@ static void prune_dir(int i, DIR *dir, char *pathname, int len, int opts)
|
||||
memcpy(hex+2, de->d_name, 38);
|
||||
if (get_sha1_hex(hex, sha1))
|
||||
continue;
|
||||
if (!has_sha1_pack(sha1, NULL))
|
||||
if (!has_sha1_pack(sha1))
|
||||
continue;
|
||||
memcpy(pathname + len, de->d_name, 38);
|
||||
if (opts & DRY_RUN)
|
||||
|
||||
@@ -675,7 +675,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
|
||||
setup_path();
|
||||
|
||||
if (!enter_repo(dir, 0))
|
||||
die("'%s': unable to chdir or not a git archive", dir);
|
||||
die("'%s' does not appear to be a git repository", dir);
|
||||
|
||||
if (is_repository_shallow())
|
||||
die("attempt to push into a shallow repository");
|
||||
|
||||
@@ -484,9 +484,8 @@ static int mv(int argc, const char **argv)
|
||||
struct string_list_item *item = remote_branches.items + i;
|
||||
int flag = 0;
|
||||
unsigned char sha1[20];
|
||||
const char *symref;
|
||||
|
||||
symref = resolve_ref(item->string, sha1, 1, &flag);
|
||||
resolve_ref(item->string, sha1, 1, &flag);
|
||||
if (!(flag & REF_ISSYMREF))
|
||||
continue;
|
||||
if (delete_ref(item->string, NULL, REF_NODEREF))
|
||||
|
||||
@@ -13,28 +13,17 @@ static const char git_rerere_usage[] =
|
||||
static int cutoff_noresolve = 15;
|
||||
static int cutoff_resolve = 60;
|
||||
|
||||
static const char *rr_path(const char *name, const char *file)
|
||||
{
|
||||
return git_path("rr-cache/%s/%s", name, file);
|
||||
}
|
||||
|
||||
static time_t rerere_created_at(const char *name)
|
||||
{
|
||||
struct stat st;
|
||||
return stat(rr_path(name, "preimage"), &st) ? (time_t) 0 : st.st_mtime;
|
||||
}
|
||||
|
||||
static int has_resolution(const char *name)
|
||||
{
|
||||
struct stat st;
|
||||
return !stat(rr_path(name, "postimage"), &st);
|
||||
return stat(rerere_path(name, "preimage"), &st) ? (time_t) 0 : st.st_mtime;
|
||||
}
|
||||
|
||||
static void unlink_rr_item(const char *name)
|
||||
{
|
||||
unlink(rr_path(name, "thisimage"));
|
||||
unlink(rr_path(name, "preimage"));
|
||||
unlink(rr_path(name, "postimage"));
|
||||
unlink(rerere_path(name, "thisimage"));
|
||||
unlink(rerere_path(name, "preimage"));
|
||||
unlink(rerere_path(name, "postimage"));
|
||||
rmdir(git_path("rr-cache/%s", name));
|
||||
}
|
||||
|
||||
@@ -65,7 +54,7 @@ static void garbage_collect(struct string_list *rr)
|
||||
then = rerere_created_at(e->d_name);
|
||||
if (!then)
|
||||
continue;
|
||||
cutoff = (has_resolution(e->d_name)
|
||||
cutoff = (has_rerere_resolution(e->d_name)
|
||||
? cutoff_resolve : cutoff_noresolve);
|
||||
if (then < now - cutoff * 86400)
|
||||
string_list_append(e->d_name, &to_remove);
|
||||
@@ -124,7 +113,7 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)
|
||||
if (!strcmp(argv[1], "clear")) {
|
||||
for (i = 0; i < merge_rr.nr; i++) {
|
||||
const char *name = (const char *)merge_rr.items[i].util;
|
||||
if (!has_resolution(name))
|
||||
if (!has_rerere_resolution(name))
|
||||
unlink_rr_item(name);
|
||||
}
|
||||
unlink(git_path("rr-cache/MERGE_RR"));
|
||||
@@ -137,7 +126,7 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)
|
||||
for (i = 0; i < merge_rr.nr; i++) {
|
||||
const char *path = merge_rr.items[i].string;
|
||||
const char *name = (const char *)merge_rr.items[i].util;
|
||||
diff_two(rr_path(name, "preimage"), path, path, path);
|
||||
diff_two(rerere_path(name, "preimage"), path, path, path);
|
||||
}
|
||||
else
|
||||
usage(git_rerere_usage);
|
||||
|
||||
@@ -574,6 +574,45 @@ static struct commit_list *find_bisection(struct commit_list *list,
|
||||
return best;
|
||||
}
|
||||
|
||||
static inline int log2i(int n)
|
||||
{
|
||||
int log2 = 0;
|
||||
|
||||
for (; n > 1; n >>= 1)
|
||||
log2++;
|
||||
|
||||
return log2;
|
||||
}
|
||||
|
||||
static inline int exp2i(int n)
|
||||
{
|
||||
return 1 << n;
|
||||
}
|
||||
|
||||
/*
|
||||
* Estimate the number of bisect steps left (after the current step)
|
||||
*
|
||||
* For any x between 0 included and 2^n excluded, the probability for
|
||||
* n - 1 steps left looks like:
|
||||
*
|
||||
* P(2^n + x) == (2^n - x) / (2^n + x)
|
||||
*
|
||||
* and P(2^n + x) < 0.5 means 2^n < 3x
|
||||
*/
|
||||
static int estimate_bisect_steps(int all)
|
||||
{
|
||||
int n, x, e;
|
||||
|
||||
if (all < 3)
|
||||
return 0;
|
||||
|
||||
n = log2i(all);
|
||||
e = exp2i(n);
|
||||
x = all - e;
|
||||
|
||||
return (e < 3 * x) ? n : n - 1;
|
||||
}
|
||||
|
||||
int cmd_rev_list(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
struct commit_list *list;
|
||||
@@ -688,12 +727,14 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
|
||||
"bisect_nr=%d\n"
|
||||
"bisect_good=%d\n"
|
||||
"bisect_bad=%d\n"
|
||||
"bisect_all=%d\n",
|
||||
"bisect_all=%d\n"
|
||||
"bisect_steps=%d\n",
|
||||
hex,
|
||||
cnt - 1,
|
||||
all - reaches - 1,
|
||||
reaches - 1,
|
||||
all);
|
||||
all,
|
||||
estimate_bisect_steps(all));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -376,6 +376,7 @@ static int revert_or_cherry_pick(int argc, const char **argv)
|
||||
(write_cache(index_fd, active_cache, active_nr) ||
|
||||
commit_locked_index(&index_lock)))
|
||||
die("%s: Unable to write new index file", me);
|
||||
rollback_lock_file(&index_lock);
|
||||
|
||||
if (!clean) {
|
||||
add_to_msg("\nConflicts:\n\n");
|
||||
|
||||
@@ -101,7 +101,6 @@ static void insert_one_record(struct shortlog *log,
|
||||
}
|
||||
while (*oneline && isspace(*oneline) && *oneline != '\n')
|
||||
oneline++;
|
||||
len = eol - oneline;
|
||||
format_subject(&subject, oneline, " ");
|
||||
buffer = strbuf_detach(&subject, NULL);
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ static int run_upload_archive(int argc, const char **argv, const char *prefix)
|
||||
strcpy(buf, argv[1]); /* enter-repo smudges its argument */
|
||||
|
||||
if (!enter_repo(buf, 0))
|
||||
die("not a git archive");
|
||||
die("'%s' does not appear to be a git repository", buf);
|
||||
|
||||
/* put received options in sent_argv[] */
|
||||
sent_argc = 1;
|
||||
|
||||
4
cache.h
4
cache.h
@@ -644,7 +644,8 @@ extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned l
|
||||
|
||||
extern int move_temp_to_file(const char *tmpfile, const char *filename);
|
||||
|
||||
extern int has_sha1_pack(const unsigned char *sha1, const char **ignore);
|
||||
extern int has_sha1_pack(const unsigned char *sha1);
|
||||
extern int has_sha1_kept_pack(const unsigned char *sha1);
|
||||
extern int has_sha1_file(const unsigned char *sha1);
|
||||
extern int has_loose_object_nonlocal(const unsigned char *sha1);
|
||||
|
||||
@@ -839,7 +840,6 @@ extern void *unpack_entry(struct packed_git *, off_t, enum object_type *, unsign
|
||||
extern unsigned long unpack_object_header_buffer(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep);
|
||||
extern unsigned long get_size_from_delta(struct packed_git *, struct pack_window **, off_t);
|
||||
extern const char *packed_object_info_detail(struct packed_git *, off_t, unsigned long *, unsigned long *, unsigned int *, unsigned char *);
|
||||
extern int matches_pack_name(struct packed_git *p, const char *name);
|
||||
|
||||
/* Dumb servers support */
|
||||
extern int update_server_info(int);
|
||||
|
||||
8
color.c
8
color.c
@@ -1,8 +1,6 @@
|
||||
#include "cache.h"
|
||||
#include "color.h"
|
||||
|
||||
#define COLOR_RESET "\033[m"
|
||||
|
||||
int git_use_color_default = 0;
|
||||
|
||||
static int parse_color(const char *name, int len)
|
||||
@@ -54,7 +52,7 @@ void color_parse_mem(const char *value, int value_len, const char *var,
|
||||
int bg = -2;
|
||||
|
||||
if (!strncasecmp(value, "reset", len)) {
|
||||
strcpy(dst, "\033[m");
|
||||
strcpy(dst, GIT_COLOR_RESET);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -175,7 +173,7 @@ static int color_vfprintf(FILE *fp, const char *color, const char *fmt,
|
||||
r += fprintf(fp, "%s", color);
|
||||
r += vfprintf(fp, fmt, args);
|
||||
if (*color)
|
||||
r += fprintf(fp, "%s", COLOR_RESET);
|
||||
r += fprintf(fp, "%s", GIT_COLOR_RESET);
|
||||
if (trail)
|
||||
r += fprintf(fp, "%s", trail);
|
||||
return r;
|
||||
@@ -217,7 +215,7 @@ int color_fwrite_lines(FILE *fp, const char *color,
|
||||
char *p = memchr(buf, '\n', count);
|
||||
if (p != buf && (fputs(color, fp) < 0 ||
|
||||
fwrite(buf, p ? p - buf : count, 1, fp) != 1 ||
|
||||
fputs(COLOR_RESET, fp) < 0))
|
||||
fputs(GIT_COLOR_RESET, fp) < 0))
|
||||
return -1;
|
||||
if (!p)
|
||||
return 0;
|
||||
|
||||
10
color.h
10
color.h
@@ -4,6 +4,16 @@
|
||||
/* "\033[1;38;5;2xx;48;5;2xxm\0" is 23 bytes */
|
||||
#define COLOR_MAXLEN 24
|
||||
|
||||
#define GIT_COLOR_NORMAL ""
|
||||
#define GIT_COLOR_RESET "\033[m"
|
||||
#define GIT_COLOR_BOLD "\033[1m"
|
||||
#define GIT_COLOR_RED "\033[31m"
|
||||
#define GIT_COLOR_GREEN "\033[32m"
|
||||
#define GIT_COLOR_YELLOW "\033[33m"
|
||||
#define GIT_COLOR_BLUE "\033[34m"
|
||||
#define GIT_COLOR_CYAN "\033[36m"
|
||||
#define GIT_COLOR_BG_RED "\033[41m"
|
||||
|
||||
/*
|
||||
* This variable stores the value of color.ui
|
||||
*/
|
||||
|
||||
@@ -526,7 +526,6 @@ static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent,
|
||||
return; /* result deleted */
|
||||
|
||||
while (1) {
|
||||
struct sline *sl = &sline[lno];
|
||||
unsigned long hunk_end;
|
||||
unsigned long rlines;
|
||||
const char *hunk_comment = NULL;
|
||||
@@ -592,7 +591,7 @@ static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent,
|
||||
struct lline *ll;
|
||||
int j;
|
||||
unsigned long p_mask;
|
||||
sl = &sline[lno++];
|
||||
struct sline *sl = &sline[lno++];
|
||||
ll = (sl->flag & no_pre_delete) ? NULL : sl->lost_head;
|
||||
while (ll) {
|
||||
fputs(c_old, stdout);
|
||||
|
||||
@@ -5,6 +5,8 @@ void *gitmemmem(const void *haystack, size_t haystack_len,
|
||||
{
|
||||
const char *begin = haystack;
|
||||
const char *last_possible = begin + haystack_len - needle_len;
|
||||
const char *tail = needle;
|
||||
char point;
|
||||
|
||||
/*
|
||||
* The first occurrence of the empty string is deemed to occur at
|
||||
@@ -20,8 +22,9 @@ void *gitmemmem(const void *haystack, size_t haystack_len,
|
||||
if (haystack_len < needle_len)
|
||||
return NULL;
|
||||
|
||||
point = *tail++;
|
||||
for (; begin <= last_possible; begin++) {
|
||||
if (!memcmp(begin, needle, needle_len))
|
||||
if (*begin == point && !memcmp(begin + 1, tail, needle_len - 1))
|
||||
return (void *)begin;
|
||||
}
|
||||
|
||||
|
||||
11
connect.c
11
connect.c
@@ -373,8 +373,6 @@ static void git_tcp_connect(int fd[2], char *host, int flags)
|
||||
|
||||
|
||||
static char *git_proxy_command;
|
||||
static const char *rhost_name;
|
||||
static int rhost_len;
|
||||
|
||||
static int git_proxy_command_options(const char *var, const char *value,
|
||||
void *cb)
|
||||
@@ -383,6 +381,8 @@ static int git_proxy_command_options(const char *var, const char *value,
|
||||
const char *for_pos;
|
||||
int matchlen = -1;
|
||||
int hostlen;
|
||||
const char *rhost_name = cb;
|
||||
int rhost_len = strlen(rhost_name);
|
||||
|
||||
if (git_proxy_command)
|
||||
return 0;
|
||||
@@ -426,11 +426,8 @@ static int git_proxy_command_options(const char *var, const char *value,
|
||||
|
||||
static int git_use_proxy(const char *host)
|
||||
{
|
||||
rhost_name = host;
|
||||
rhost_len = strlen(host);
|
||||
git_proxy_command = getenv("GIT_PROXY_COMMAND");
|
||||
git_config(git_proxy_command_options, NULL);
|
||||
rhost_name = NULL;
|
||||
git_config(git_proxy_command_options, (void*)host);
|
||||
return (git_proxy_command && *git_proxy_command);
|
||||
}
|
||||
|
||||
@@ -507,7 +504,7 @@ struct child_process *git_connect(int fd[2], const char *url_orig,
|
||||
const char *prog, int flags)
|
||||
{
|
||||
char *url = xstrdup(url_orig);
|
||||
char *host, *path = url;
|
||||
char *host, *path;
|
||||
char *end;
|
||||
int c;
|
||||
struct child_process *conn;
|
||||
|
||||
@@ -62,7 +62,7 @@ esac
|
||||
__gitdir ()
|
||||
{
|
||||
if [ -z "${1-}" ]; then
|
||||
if [ -n "$__git_dir" ]; then
|
||||
if [ -n "${__git_dir-}" ]; then
|
||||
echo "$__git_dir"
|
||||
elif [ -d .git ]; then
|
||||
echo .git
|
||||
@@ -80,68 +80,72 @@ __gitdir ()
|
||||
# returns text to add to bash PS1 prompt (includes branch name)
|
||||
__git_ps1 ()
|
||||
{
|
||||
local g="$(git rev-parse --git-dir 2>/dev/null)"
|
||||
local g="$(__gitdir)"
|
||||
if [ -n "$g" ]; then
|
||||
local r
|
||||
local b
|
||||
if [ -d "$g/rebase-apply" ]
|
||||
then
|
||||
if test -f "$g/rebase-apply/rebasing"
|
||||
then
|
||||
if [ -d "$g/rebase-apply" ]; then
|
||||
if [ -f "$g/rebase-apply/rebasing" ]; then
|
||||
r="|REBASE"
|
||||
elif test -f "$g/rebase-apply/applying"
|
||||
then
|
||||
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
|
||||
elif [ -f "$g/rebase-merge/interactive" ]; then
|
||||
r="|REBASE-i"
|
||||
b="$(cat "$g/rebase-merge/head-name")"
|
||||
elif [ -d "$g/rebase-merge" ]
|
||||
then
|
||||
elif [ -d "$g/rebase-merge" ]; then
|
||||
r="|REBASE-m"
|
||||
b="$(cat "$g/rebase-merge/head-name")"
|
||||
elif [ -f "$g/MERGE_HEAD" ]
|
||||
then
|
||||
elif [ -f "$g/MERGE_HEAD" ]; then
|
||||
r="|MERGING"
|
||||
b="$(git symbolic-ref HEAD 2>/dev/null)"
|
||||
else
|
||||
if [ -f "$g/BISECT_LOG" ]
|
||||
then
|
||||
if [ -f "$g/BISECT_LOG" ]; then
|
||||
r="|BISECTING"
|
||||
fi
|
||||
if ! b="$(git symbolic-ref HEAD 2>/dev/null)"
|
||||
then
|
||||
if ! b="$(git describe --exact-match HEAD 2>/dev/null)"
|
||||
then
|
||||
b="$(cut -c1-7 "$g/HEAD")..."
|
||||
if ! b="$(git symbolic-ref HEAD 2>/dev/null)"; then
|
||||
if ! b="$(git describe --exact-match HEAD 2>/dev/null)"; then
|
||||
if [ -r "$g/HEAD" ]; then
|
||||
b="$(cut -c1-7 "$g/HEAD")..."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
local w
|
||||
local i
|
||||
local c
|
||||
|
||||
if test -n "${GIT_PS1_SHOWDIRTYSTATE-}"; then
|
||||
if test "$(git config --bool bash.showDirtyState)" != "false"; then
|
||||
git diff --no-ext-diff --ignore-submodules \
|
||||
--quiet --exit-code || w="*"
|
||||
if git rev-parse --quiet --verify HEAD >/dev/null; then
|
||||
git diff-index --cached --quiet \
|
||||
--ignore-submodules HEAD -- || i="+"
|
||||
else
|
||||
i="#"
|
||||
if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then
|
||||
if [ "true" = "$(git config --bool core.bare 2>/dev/null)" ]; then
|
||||
c="BARE:"
|
||||
else
|
||||
b="GIT_DIR!"
|
||||
fi
|
||||
elif [ "true" = "$(git rev-parse --is-inside-work-tree 2>/dev/null)" ]; then
|
||||
if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ]; then
|
||||
if [ "$(git config --bool bash.showDirtyState)" != "false" ]; then
|
||||
git diff --no-ext-diff --ignore-submodules \
|
||||
--quiet --exit-code || w="*"
|
||||
if git rev-parse --quiet --verify HEAD >/dev/null; then
|
||||
git diff-index --cached --quiet \
|
||||
--ignore-submodules HEAD -- || i="+"
|
||||
else
|
||||
i="#"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "${1-}" ]; then
|
||||
printf "$1" "${b##refs/heads/}$w$i$r"
|
||||
else
|
||||
printf " (%s)" "${b##refs/heads/}$w$i$r"
|
||||
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
|
||||
fi
|
||||
fi
|
||||
}
|
||||
@@ -299,7 +303,7 @@ __git_remotes ()
|
||||
|
||||
__git_merge_strategies ()
|
||||
{
|
||||
if [ -n "$__git_merge_strategylist" ]; then
|
||||
if [ -n "${__git_merge_strategylist-}" ]; then
|
||||
echo "$__git_merge_strategylist"
|
||||
return
|
||||
fi
|
||||
@@ -383,9 +387,88 @@ __git_complete_revlist ()
|
||||
esac
|
||||
}
|
||||
|
||||
__git_complete_remote_or_refspec ()
|
||||
{
|
||||
local cmd="${COMP_WORDS[1]}"
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
local i c=2 remote="" pfx="" lhs=1 no_complete_refspec=0
|
||||
while [ $c -lt $COMP_CWORD ]; do
|
||||
i="${COMP_WORDS[c]}"
|
||||
case "$i" in
|
||||
--all|--mirror) [ "$cmd" = "push" ] && no_complete_refspec=1 ;;
|
||||
-*) ;;
|
||||
*) remote="$i"; break ;;
|
||||
esac
|
||||
c=$((++c))
|
||||
done
|
||||
if [ -z "$remote" ]; then
|
||||
__gitcomp "$(__git_remotes)"
|
||||
return
|
||||
fi
|
||||
if [ $no_complete_refspec = 1 ]; then
|
||||
COMPREPLY=()
|
||||
return
|
||||
fi
|
||||
[ "$remote" = "." ] && remote=
|
||||
case "$cur" in
|
||||
*:*)
|
||||
case "$COMP_WORDBREAKS" in
|
||||
*:*) : great ;;
|
||||
*) pfx="${cur%%:*}:" ;;
|
||||
esac
|
||||
cur="${cur#*:}"
|
||||
lhs=0
|
||||
;;
|
||||
+*)
|
||||
pfx="+"
|
||||
cur="${cur#+}"
|
||||
;;
|
||||
esac
|
||||
case "$cmd" in
|
||||
fetch)
|
||||
if [ $lhs = 1 ]; then
|
||||
__gitcomp "$(__git_refs2 "$remote")" "$pfx" "$cur"
|
||||
else
|
||||
__gitcomp "$(__git_refs)" "$pfx" "$cur"
|
||||
fi
|
||||
;;
|
||||
pull)
|
||||
if [ $lhs = 1 ]; then
|
||||
__gitcomp "$(__git_refs "$remote")" "$pfx" "$cur"
|
||||
else
|
||||
__gitcomp "$(__git_refs)" "$pfx" "$cur"
|
||||
fi
|
||||
;;
|
||||
push)
|
||||
if [ $lhs = 1 ]; then
|
||||
__gitcomp "$(__git_refs)" "$pfx" "$cur"
|
||||
else
|
||||
__gitcomp "$(__git_refs "$remote")" "$pfx" "$cur"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
__git_complete_strategy ()
|
||||
{
|
||||
case "${COMP_WORDS[COMP_CWORD-1]}" in
|
||||
-s|--strategy)
|
||||
__gitcomp "$(__git_merge_strategies)"
|
||||
return 0
|
||||
esac
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
case "$cur" in
|
||||
--strategy=*)
|
||||
__gitcomp "$(__git_merge_strategies)" "" "${cur##--strategy=}"
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
return 1
|
||||
}
|
||||
|
||||
__git_all_commands ()
|
||||
{
|
||||
if [ -n "$__git_all_commandlist" ]; then
|
||||
if [ -n "${__git_all_commandlist-}" ]; then
|
||||
echo "$__git_all_commandlist"
|
||||
return
|
||||
fi
|
||||
@@ -403,7 +486,7 @@ __git_all_commandlist="$(__git_all_commands 2>/dev/null)"
|
||||
|
||||
__git_porcelain_commands ()
|
||||
{
|
||||
if [ -n "$__git_porcelain_commandlist" ]; then
|
||||
if [ -n "${__git_porcelain_commandlist-}" ]; then
|
||||
echo "$__git_porcelain_commandlist"
|
||||
return
|
||||
fi
|
||||
@@ -826,27 +909,21 @@ _git_diff ()
|
||||
__git_complete_file
|
||||
}
|
||||
|
||||
__git_fetch_options="
|
||||
--quiet --verbose --append --upload-pack --force --keep --depth=
|
||||
--tags --no-tags
|
||||
"
|
||||
|
||||
_git_fetch ()
|
||||
{
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
|
||||
if [ "$COMP_CWORD" = 2 ]; then
|
||||
__gitcomp "$(__git_remotes)"
|
||||
else
|
||||
case "$cur" in
|
||||
*:*)
|
||||
local pfx=""
|
||||
case "$COMP_WORDBREAKS" in
|
||||
*:*) : great ;;
|
||||
*) pfx="${cur%%:*}:" ;;
|
||||
esac
|
||||
__gitcomp "$(__git_refs)" "$pfx" "${cur#*:}"
|
||||
;;
|
||||
*)
|
||||
__gitcomp "$(__git_refs2 "${COMP_WORDS[2]}")"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
case "$cur" in
|
||||
--*)
|
||||
__gitcomp "$__git_fetch_options"
|
||||
return
|
||||
;;
|
||||
esac
|
||||
__git_complete_remote_or_refspec
|
||||
}
|
||||
|
||||
_git_format_patch ()
|
||||
@@ -1014,6 +1091,11 @@ _git_log ()
|
||||
" "" "${cur##--pretty=}"
|
||||
return
|
||||
;;
|
||||
--format=*)
|
||||
__gitcomp "$__git_log_pretty_formats
|
||||
" "" "${cur##--format=}"
|
||||
return
|
||||
;;
|
||||
--date=*)
|
||||
__gitcomp "
|
||||
relative iso8601 rfc2822 short local default
|
||||
@@ -1029,7 +1111,7 @@ _git_log ()
|
||||
--follow
|
||||
--abbrev-commit --abbrev=
|
||||
--relative-date --date=
|
||||
--pretty=
|
||||
--pretty= --format= --oneline
|
||||
--cherry-pick
|
||||
--graph
|
||||
--decorate
|
||||
@@ -1045,24 +1127,19 @@ _git_log ()
|
||||
__git_complete_revlist
|
||||
}
|
||||
|
||||
__git_merge_options="
|
||||
--no-commit --no-stat --log --no-log --squash --strategy
|
||||
--commit --stat --no-squash --ff --no-ff
|
||||
"
|
||||
|
||||
_git_merge ()
|
||||
{
|
||||
__git_complete_strategy && return
|
||||
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
case "${COMP_WORDS[COMP_CWORD-1]}" in
|
||||
-s|--strategy)
|
||||
__gitcomp "$(__git_merge_strategies)"
|
||||
return
|
||||
esac
|
||||
case "$cur" in
|
||||
--strategy=*)
|
||||
__gitcomp "$(__git_merge_strategies)" "" "${cur##--strategy=}"
|
||||
return
|
||||
;;
|
||||
--*)
|
||||
__gitcomp "
|
||||
--no-commit --no-stat --log --no-log --squash --strategy
|
||||
--commit --stat --no-squash --ff --no-ff
|
||||
"
|
||||
__gitcomp "$__git_merge_options"
|
||||
return
|
||||
esac
|
||||
__gitcomp "$(__git_refs)"
|
||||
@@ -1111,40 +1188,44 @@ _git_name_rev ()
|
||||
|
||||
_git_pull ()
|
||||
{
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
__git_complete_strategy && return
|
||||
|
||||
if [ "$COMP_CWORD" = 2 ]; then
|
||||
__gitcomp "$(__git_remotes)"
|
||||
else
|
||||
__gitcomp "$(__git_refs "${COMP_WORDS[2]}")"
|
||||
fi
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
case "$cur" in
|
||||
--*)
|
||||
__gitcomp "
|
||||
--rebase --no-rebase
|
||||
$__git_merge_options
|
||||
$__git_fetch_options
|
||||
"
|
||||
return
|
||||
;;
|
||||
esac
|
||||
__git_complete_remote_or_refspec
|
||||
}
|
||||
|
||||
_git_push ()
|
||||
{
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
|
||||
if [ "$COMP_CWORD" = 2 ]; then
|
||||
case "${COMP_WORDS[COMP_CWORD-1]}" in
|
||||
--repo)
|
||||
__gitcomp "$(__git_remotes)"
|
||||
else
|
||||
case "$cur" in
|
||||
*:*)
|
||||
local pfx=""
|
||||
case "$COMP_WORDBREAKS" in
|
||||
*:*) : great ;;
|
||||
*) pfx="${cur%%:*}:" ;;
|
||||
esac
|
||||
|
||||
__gitcomp "$(__git_refs "${COMP_WORDS[2]}")" "$pfx" "${cur#*:}"
|
||||
;;
|
||||
+*)
|
||||
__gitcomp "$(__git_refs)" + "${cur#+}"
|
||||
;;
|
||||
*)
|
||||
__gitcomp "$(__git_refs)"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
return
|
||||
esac
|
||||
case "$cur" in
|
||||
--repo=*)
|
||||
__gitcomp "$(__git_remotes)" "" "${cur##--repo=}"
|
||||
return
|
||||
;;
|
||||
--*)
|
||||
__gitcomp "
|
||||
--all --mirror --tags --dry-run --force --verbose
|
||||
--receive-pack= --repo=
|
||||
"
|
||||
return
|
||||
;;
|
||||
esac
|
||||
__git_complete_remote_or_refspec
|
||||
}
|
||||
|
||||
_git_rebase ()
|
||||
@@ -1154,16 +1235,8 @@ _git_rebase ()
|
||||
__gitcomp "--continue --skip --abort"
|
||||
return
|
||||
fi
|
||||
case "${COMP_WORDS[COMP_CWORD-1]}" in
|
||||
-s|--strategy)
|
||||
__gitcomp "$(__git_merge_strategies)"
|
||||
return
|
||||
esac
|
||||
__git_complete_strategy && return
|
||||
case "$cur" in
|
||||
--strategy=*)
|
||||
__gitcomp "$(__git_merge_strategies)" "" "${cur##--strategy=}"
|
||||
return
|
||||
;;
|
||||
--*)
|
||||
__gitcomp "--onto --merge --strategy --interactive"
|
||||
return
|
||||
@@ -1541,8 +1614,13 @@ _git_show ()
|
||||
" "" "${cur##--pretty=}"
|
||||
return
|
||||
;;
|
||||
--format=*)
|
||||
__gitcomp "$__git_log_pretty_formats
|
||||
" "" "${cur##--format=}"
|
||||
return
|
||||
;;
|
||||
--*)
|
||||
__gitcomp "--pretty=
|
||||
__gitcomp "--pretty= --format=
|
||||
$__git_diff_common_options
|
||||
"
|
||||
return
|
||||
@@ -1841,7 +1919,7 @@ _gitk ()
|
||||
__git_has_doubledash && return
|
||||
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
local g="$(git rev-parse --git-dir 2>/dev/null)"
|
||||
local g="$(__gitdir)"
|
||||
local merge=""
|
||||
if [ -f $g/MERGE_HEAD ]; then
|
||||
merge="--merge"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# This is a wrapper around the GIT_EXTERNAL_DIFF-compatible
|
||||
# git-difftool-helper script. This script exports
|
||||
# GIT_EXTERNAL_DIFF and GIT_PAGER for use by git, and
|
||||
# GIT_DIFFTOOL_NO_PROMPT and GIT_MERGE_TOOL for use by git-difftool-helper.
|
||||
# GIT_DIFFTOOL_NO_PROMPT and GIT_DIFF_TOOL for use by git-difftool-helper.
|
||||
# Any arguments that are unknown to this script are forwarded to 'git diff'.
|
||||
|
||||
use strict;
|
||||
@@ -49,12 +49,12 @@ sub generate_command
|
||||
}
|
||||
if ($arg eq '-t' or $arg eq '--tool') {
|
||||
usage() if $#ARGV <= $idx;
|
||||
$ENV{GIT_MERGE_TOOL} = $ARGV[$idx + 1];
|
||||
$ENV{GIT_DIFF_TOOL} = $ARGV[$idx + 1];
|
||||
$skip_next = 1;
|
||||
next;
|
||||
}
|
||||
if ($arg =~ /^--tool=/) {
|
||||
$ENV{GIT_MERGE_TOOL} = substr($arg, 7);
|
||||
$ENV{GIT_DIFF_TOOL} = substr($arg, 7);
|
||||
next;
|
||||
}
|
||||
if ($arg eq '--no-prompt') {
|
||||
|
||||
@@ -128,8 +128,10 @@ launch_merge_tool () {
|
||||
cleanup_temp_files
|
||||
}
|
||||
|
||||
# Verifies that mergetool.<tool>.cmd exists
|
||||
# Verifies that (difftool|mergetool).<tool>.cmd exists
|
||||
valid_custom_tool() {
|
||||
merge_tool_cmd="$(git config difftool.$1.cmd)"
|
||||
test -z "$merge_tool_cmd" &&
|
||||
merge_tool_cmd="$(git config mergetool.$1.cmd)"
|
||||
test -n "$merge_tool_cmd"
|
||||
}
|
||||
@@ -150,8 +152,11 @@ valid_tool() {
|
||||
}
|
||||
|
||||
# Sets up the merge_tool_path variable.
|
||||
# This handles the mergetool.<tool>.path configuration.
|
||||
# This handles the difftool.<tool>.path configuration.
|
||||
# This also falls back to mergetool defaults.
|
||||
init_merge_tool_path() {
|
||||
merge_tool_path=$(git config difftool."$1".path)
|
||||
test -z "$merge_tool_path" &&
|
||||
merge_tool_path=$(git config mergetool."$1".path)
|
||||
if test -z "$merge_tool_path"; then
|
||||
case "$1" in
|
||||
@@ -165,15 +170,19 @@ init_merge_tool_path() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Allow the GIT_MERGE_TOOL variable to provide a default value
|
||||
# Allow GIT_DIFF_TOOL and GIT_MERGE_TOOL to provide default values
|
||||
test -n "$GIT_MERGE_TOOL" && merge_tool="$GIT_MERGE_TOOL"
|
||||
test -n "$GIT_DIFF_TOOL" && merge_tool="$GIT_DIFF_TOOL"
|
||||
|
||||
# If not merge tool was specified then use the merge.tool
|
||||
# If merge tool was not specified then use the diff.tool
|
||||
# configuration variable. If that's invalid then reset merge_tool.
|
||||
# Fallback to merge.tool.
|
||||
if test -z "$merge_tool"; then
|
||||
merge_tool=$(git config diff.tool)
|
||||
test -z "$merge_tool" &&
|
||||
merge_tool=$(git config merge.tool)
|
||||
if test -n "$merge_tool" && ! valid_tool "$merge_tool"; then
|
||||
echo >&2 "git config option merge.tool set to unknown tool: $merge_tool"
|
||||
echo >&2 "git config option diff.tool set to unknown tool: $merge_tool"
|
||||
echo >&2 "Resetting to default..."
|
||||
unset merge_tool
|
||||
fi
|
||||
|
||||
@@ -32,23 +32,23 @@ OPTIONS
|
||||
vimdiff, gvimdiff, ecmerge, and opendiff
|
||||
+
|
||||
If a merge resolution program is not specified, 'git-difftool'
|
||||
will use the configuration variable `merge.tool`. If the
|
||||
configuration variable `merge.tool` is not set, 'git difftool'
|
||||
will use the configuration variable `diff.tool`. If the
|
||||
configuration variable `diff.tool` is not set, 'git-difftool'
|
||||
will pick a suitable default.
|
||||
+
|
||||
You can explicitly provide a full path to the tool by setting the
|
||||
configuration variable `mergetool.<tool>.path`. For example, you
|
||||
configuration variable `difftool.<tool>.path`. For example, you
|
||||
can configure the absolute path to kdiff3 by setting
|
||||
`mergetool.kdiff3.path`. Otherwise, 'git-difftool' assumes the
|
||||
`difftool.kdiff3.path`. Otherwise, 'git-difftool' assumes the
|
||||
tool is available in PATH.
|
||||
+
|
||||
Instead of running one of the known merge tool programs,
|
||||
'git-difftool' can be customized to run an alternative program
|
||||
by specifying the command line to invoke in a configuration
|
||||
variable `mergetool.<tool>.cmd`.
|
||||
variable `difftool.<tool>.cmd`.
|
||||
+
|
||||
When 'git-difftool' is invoked with this tool (either through the
|
||||
`-t` or `--tool` option or the `merge.tool` configuration variable)
|
||||
`-t` or `--tool` option or the `diff.tool` configuration variable)
|
||||
the configured command line will be invoked with the following
|
||||
variables available: `$LOCAL` is set to the name of the temporary
|
||||
file containing the contents of the diff pre-image and `$REMOTE`
|
||||
@@ -61,8 +61,18 @@ with custom merge tool commands and has the same value as `$LOCAL`.
|
||||
|
||||
CONFIG VARIABLES
|
||||
----------------
|
||||
merge.tool::
|
||||
'git-difftool' falls back to 'git-mergetool' config variables when the
|
||||
difftool equivalents have not been defined.
|
||||
|
||||
diff.tool::
|
||||
The default merge tool to use.
|
||||
|
||||
difftool.<tool>.path::
|
||||
Override the path for the given tool. This is useful in case
|
||||
your tool is not in the PATH.
|
||||
|
||||
difftool.<tool>.cmd::
|
||||
Specify the command to invoke the specified merge tool.
|
||||
+
|
||||
See the `--tool=<tool>` option above for more details.
|
||||
|
||||
@@ -70,16 +80,6 @@ merge.keepBackup::
|
||||
The original, unedited file content can be saved to a file with
|
||||
a `.orig` extension. Defaults to `true` (i.e. keep the backup files).
|
||||
|
||||
mergetool.<tool>.path::
|
||||
Override the path for the given tool. This is useful in case
|
||||
your tool is not in the PATH.
|
||||
|
||||
mergetool.<tool>.cmd::
|
||||
Specify the command to invoke the specified merge tool.
|
||||
+
|
||||
See the `--tool=<tool>` option above for more details.
|
||||
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
linkgit:git-diff[1]::
|
||||
|
||||
@@ -1142,7 +1142,7 @@ class P4Sync(Command):
|
||||
|
||||
s = ''
|
||||
for (key, val) in self.users.items():
|
||||
s += "%s\t%s\n" % (key, val)
|
||||
s += "%s\t%s\n" % (key.expandtabs(1), val.expandtabs(1))
|
||||
|
||||
open(self.getUserCacheFilename(), "wb").write(s)
|
||||
self.userMapFromPerforceServer = True
|
||||
|
||||
2
daemon.c
2
daemon.c
@@ -229,7 +229,7 @@ static char *path_ok(char *directory)
|
||||
}
|
||||
|
||||
if (!path) {
|
||||
logerror("'%s': unable to chdir or not a git archive", dir);
|
||||
logerror("'%s' does not appear to be a git repository", dir);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
20
date.c
20
date.c
@@ -133,7 +133,25 @@ const char *show_date(unsigned long time, int tz, enum date_mode mode)
|
||||
snprintf(timebuf, sizeof(timebuf), "%lu months ago", (diff + 15) / 30);
|
||||
return timebuf;
|
||||
}
|
||||
/* Else fall back on absolute format.. */
|
||||
/* Give years and months for 5 years or so */
|
||||
if (diff < 1825) {
|
||||
unsigned long years = (diff + 183) / 365;
|
||||
unsigned long months = (diff % 365 + 15) / 30;
|
||||
int n;
|
||||
n = snprintf(timebuf, sizeof(timebuf), "%lu year%s",
|
||||
years, (years > 1 ? "s" : ""));
|
||||
if (months)
|
||||
snprintf(timebuf + n, sizeof(timebuf) - n,
|
||||
", %lu month%s ago",
|
||||
months, (months > 1 ? "s" : ""));
|
||||
else
|
||||
snprintf(timebuf + n, sizeof(timebuf) - n,
|
||||
" ago");
|
||||
return timebuf;
|
||||
}
|
||||
/* Otherwise, just years. Centuries is probably overkill. */
|
||||
snprintf(timebuf, sizeof(timebuf), "%lu years ago", (diff + 183) / 365);
|
||||
return timebuf;
|
||||
}
|
||||
|
||||
if (mode == DATE_LOCAL)
|
||||
|
||||
39
diff.c
39
diff.c
@@ -30,14 +30,14 @@ int diff_auto_refresh_index = 1;
|
||||
static int diff_mnemonic_prefix;
|
||||
|
||||
static char diff_colors[][COLOR_MAXLEN] = {
|
||||
"\033[m", /* reset */
|
||||
"", /* PLAIN (normal) */
|
||||
"\033[1m", /* METAINFO (bold) */
|
||||
"\033[36m", /* FRAGINFO (cyan) */
|
||||
"\033[31m", /* OLD (red) */
|
||||
"\033[32m", /* NEW (green) */
|
||||
"\033[33m", /* COMMIT (yellow) */
|
||||
"\033[41m", /* WHITESPACE (red background) */
|
||||
GIT_COLOR_RESET,
|
||||
GIT_COLOR_NORMAL, /* PLAIN */
|
||||
GIT_COLOR_BOLD, /* METAINFO */
|
||||
GIT_COLOR_CYAN, /* FRAGINFO */
|
||||
GIT_COLOR_RED, /* OLD */
|
||||
GIT_COLOR_GREEN, /* NEW */
|
||||
GIT_COLOR_YELLOW, /* COMMIT */
|
||||
GIT_COLOR_BG_RED, /* WHITESPACE */
|
||||
};
|
||||
|
||||
static void diff_filespec_load_driver(struct diff_filespec *one);
|
||||
@@ -875,7 +875,7 @@ static void fill_print_name(struct diffstat_file *file)
|
||||
|
||||
static void show_stats(struct diffstat_t* data, struct diff_options *options)
|
||||
{
|
||||
int i, len, add, del, total, adds = 0, dels = 0;
|
||||
int i, len, add, del, adds = 0, dels = 0;
|
||||
int max_change = 0, max_len = 0;
|
||||
int total_files = data->nr;
|
||||
int width, name_width;
|
||||
@@ -978,14 +978,12 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options)
|
||||
*/
|
||||
add = added;
|
||||
del = deleted;
|
||||
total = add + del;
|
||||
adds += add;
|
||||
dels += del;
|
||||
|
||||
if (width <= max_change) {
|
||||
add = scale_linear(add, width, max_change);
|
||||
del = scale_linear(del, width, max_change);
|
||||
total = add + del;
|
||||
}
|
||||
show_name(options->file, prefix, name, len, reset, set);
|
||||
fprintf(options->file, "%5d%s", added + deleted,
|
||||
@@ -1783,7 +1781,7 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int
|
||||
* objects however would tend to be slower as they need
|
||||
* to be individually opened and inflated.
|
||||
*/
|
||||
if (!FAST_WORKING_DIRECTORY && !want_file && has_sha1_pack(sha1, NULL))
|
||||
if (!FAST_WORKING_DIRECTORY && !want_file && has_sha1_pack(sha1))
|
||||
return 0;
|
||||
|
||||
len = strlen(name);
|
||||
@@ -2567,13 +2565,13 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
|
||||
|
||||
/* xdiff options */
|
||||
else if (!strcmp(arg, "-w") || !strcmp(arg, "--ignore-all-space"))
|
||||
options->xdl_opts |= XDF_IGNORE_WHITESPACE;
|
||||
DIFF_XDL_SET(options, IGNORE_WHITESPACE);
|
||||
else if (!strcmp(arg, "-b") || !strcmp(arg, "--ignore-space-change"))
|
||||
options->xdl_opts |= XDF_IGNORE_WHITESPACE_CHANGE;
|
||||
DIFF_XDL_SET(options, IGNORE_WHITESPACE_CHANGE);
|
||||
else if (!strcmp(arg, "--ignore-space-at-eol"))
|
||||
options->xdl_opts |= XDF_IGNORE_WHITESPACE_AT_EOL;
|
||||
DIFF_XDL_SET(options, IGNORE_WHITESPACE_AT_EOL);
|
||||
else if (!strcmp(arg, "--patience"))
|
||||
options->xdl_opts |= XDF_PATIENCE_DIFF;
|
||||
DIFF_XDL_SET(options, PATIENCE_DIFF);
|
||||
|
||||
/* flags options */
|
||||
else if (!strcmp(arg, "--binary")) {
|
||||
@@ -2594,10 +2592,13 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
|
||||
DIFF_OPT_SET(options, COLOR_DIFF);
|
||||
else if (!strcmp(arg, "--no-color"))
|
||||
DIFF_OPT_CLR(options, COLOR_DIFF);
|
||||
else if (!strcmp(arg, "--color-words"))
|
||||
options->flags |= DIFF_OPT_COLOR_DIFF | DIFF_OPT_COLOR_DIFF_WORDS;
|
||||
else if (!strcmp(arg, "--color-words")) {
|
||||
DIFF_OPT_SET(options, COLOR_DIFF);
|
||||
DIFF_OPT_SET(options, COLOR_DIFF_WORDS);
|
||||
}
|
||||
else if (!prefixcmp(arg, "--color-words=")) {
|
||||
options->flags |= DIFF_OPT_COLOR_DIFF | DIFF_OPT_COLOR_DIFF_WORDS;
|
||||
DIFF_OPT_SET(options, COLOR_DIFF);
|
||||
DIFF_OPT_SET(options, COLOR_DIFF_WORDS);
|
||||
options->word_regex = arg + 14;
|
||||
}
|
||||
else if (!strcmp(arg, "--exit-code"))
|
||||
|
||||
3
diff.h
3
diff.h
@@ -69,6 +69,9 @@ typedef void (*diff_format_fn_t)(struct diff_queue_struct *q,
|
||||
#define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag)
|
||||
#define DIFF_OPT_SET(opts, flag) ((opts)->flags |= DIFF_OPT_##flag)
|
||||
#define DIFF_OPT_CLR(opts, flag) ((opts)->flags &= ~DIFF_OPT_##flag)
|
||||
#define DIFF_XDL_TST(opts, flag) ((opts)->xdl_opts & XDF_##flag)
|
||||
#define DIFF_XDL_SET(opts, flag) ((opts)->xdl_opts |= XDF_##flag)
|
||||
#define DIFF_XDL_CLR(opts, flag) ((opts)->xdl_opts &= ~XDF_##flag)
|
||||
|
||||
struct diff_options {
|
||||
const char *filter;
|
||||
|
||||
@@ -45,7 +45,7 @@ static int should_break(struct diff_filespec *src,
|
||||
* The value we return is 1 if we want the pair to be broken,
|
||||
* or 0 if we do not.
|
||||
*/
|
||||
unsigned long delta_size, base_size, max_size;
|
||||
unsigned long delta_size, max_size;
|
||||
unsigned long src_copied, literal_added, src_removed;
|
||||
|
||||
*merge_score_p = 0; /* assume no deletion --- "do not break"
|
||||
@@ -64,7 +64,6 @@ static int should_break(struct diff_filespec *src,
|
||||
if (diff_populate_filespec(src, 0) || diff_populate_filespec(dst, 0))
|
||||
return 0; /* error but caught downstream */
|
||||
|
||||
base_size = ((src->size < dst->size) ? src->size : dst->size);
|
||||
max_size = ((src->size > dst->size) ? src->size : dst->size);
|
||||
if (max_size < MINIMUM_BREAK_SIZE)
|
||||
return 0; /* we do not break too small filepair */
|
||||
|
||||
@@ -10,7 +10,7 @@ static unsigned int contains(struct diff_filespec *one,
|
||||
regex_t *regexp)
|
||||
{
|
||||
unsigned int cnt;
|
||||
unsigned long offset, sz;
|
||||
unsigned long sz;
|
||||
const char *data;
|
||||
if (diff_populate_filespec(one, 0))
|
||||
return 0;
|
||||
@@ -33,15 +33,13 @@ static unsigned int contains(struct diff_filespec *one,
|
||||
}
|
||||
|
||||
} else { /* Classic exact string match */
|
||||
/* Yes, I've heard of strstr(), but the thing is *data may
|
||||
* not be NUL terminated. Sue me.
|
||||
*/
|
||||
for (offset = 0; offset + len <= sz; offset++) {
|
||||
/* we count non-overlapping occurrences of needle */
|
||||
if (!memcmp(needle, data + offset, len)) {
|
||||
offset += len - 1;
|
||||
cnt++;
|
||||
}
|
||||
while (sz) {
|
||||
const char *found = memmem(data, sz, needle, len);
|
||||
if (!found)
|
||||
break;
|
||||
sz -= found - data + len;
|
||||
data = found + len;
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
diff_free_filespec_data(one);
|
||||
|
||||
2
dir.c
2
dir.c
@@ -137,7 +137,7 @@ int match_pathspec(const char **pathspec, const char *name, int namelen,
|
||||
|
||||
static int no_wildcard(const char *string)
|
||||
{
|
||||
return string[strcspn(string, "*?[{")] == '\0';
|
||||
return string[strcspn(string, "*?[{\\")] == '\0';
|
||||
}
|
||||
|
||||
void add_exclude(const char *string, const char *base,
|
||||
|
||||
@@ -1745,21 +1745,19 @@ static void parse_data(struct strbuf *sb)
|
||||
static int validate_raw_date(const char *src, char *result, int maxlen)
|
||||
{
|
||||
const char *orig_src = src;
|
||||
char *endp, sign;
|
||||
unsigned long date;
|
||||
char *endp;
|
||||
|
||||
errno = 0;
|
||||
|
||||
date = strtoul(src, &endp, 10);
|
||||
strtoul(src, &endp, 10);
|
||||
if (errno || endp == src || *endp != ' ')
|
||||
return -1;
|
||||
|
||||
src = endp + 1;
|
||||
if (*src != '-' && *src != '+')
|
||||
return -1;
|
||||
sign = *src;
|
||||
|
||||
date = strtoul(src + 1, &endp, 10);
|
||||
strtoul(src + 1, &endp, 10);
|
||||
if (errno || endp == src || *endp || (endp - orig_src) >= maxlen)
|
||||
return -1;
|
||||
|
||||
|
||||
6
fsck.c
6
fsck.c
@@ -148,20 +148,17 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func)
|
||||
struct tree_desc desc;
|
||||
unsigned o_mode;
|
||||
const char *o_name;
|
||||
const unsigned char *o_sha1;
|
||||
|
||||
init_tree_desc(&desc, item->buffer, item->size);
|
||||
|
||||
o_mode = 0;
|
||||
o_name = NULL;
|
||||
o_sha1 = NULL;
|
||||
|
||||
while (desc.size) {
|
||||
unsigned mode;
|
||||
const char *name;
|
||||
const unsigned char *sha1;
|
||||
|
||||
sha1 = tree_entry_extract(&desc, &name, &mode);
|
||||
tree_entry_extract(&desc, &name, &mode);
|
||||
|
||||
if (strchr(name, '/'))
|
||||
has_full_path = 1;
|
||||
@@ -207,7 +204,6 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func)
|
||||
|
||||
o_mode = mode;
|
||||
o_name = name;
|
||||
o_sha1 = sha1;
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
use strict;
|
||||
use Git;
|
||||
|
||||
binmode(STDOUT, ":raw");
|
||||
|
||||
my $repo = Git->repository();
|
||||
|
||||
my $menu_use_color = $repo->get_colorbool('color.interactive');
|
||||
@@ -91,6 +93,47 @@ if (!defined $GIT_DIR) {
|
||||
}
|
||||
chomp($GIT_DIR);
|
||||
|
||||
my %cquote_map = (
|
||||
"b" => chr(8),
|
||||
"t" => chr(9),
|
||||
"n" => chr(10),
|
||||
"v" => chr(11),
|
||||
"f" => chr(12),
|
||||
"r" => chr(13),
|
||||
"\\" => "\\",
|
||||
"\042" => "\042",
|
||||
);
|
||||
|
||||
sub unquote_path {
|
||||
local ($_) = @_;
|
||||
my ($retval, $remainder);
|
||||
if (!/^\042(.*)\042$/) {
|
||||
return $_;
|
||||
}
|
||||
($_, $retval) = ($1, "");
|
||||
while (/^([^\\]*)\\(.*)$/) {
|
||||
$remainder = $2;
|
||||
$retval .= $1;
|
||||
for ($remainder) {
|
||||
if (/^([0-3][0-7][0-7])(.*)$/) {
|
||||
$retval .= chr(oct($1));
|
||||
$_ = $2;
|
||||
last;
|
||||
}
|
||||
if (/^([\\\042btnvfr])(.*)$/) {
|
||||
$retval .= $cquote_map{$1};
|
||||
$_ = $2;
|
||||
last;
|
||||
}
|
||||
# This is malformed -- just return it as-is for now.
|
||||
return $_[0];
|
||||
}
|
||||
$_ = $remainder;
|
||||
}
|
||||
$retval .= $_;
|
||||
return $retval;
|
||||
}
|
||||
|
||||
sub refresh {
|
||||
my $fh;
|
||||
open $fh, 'git update-index --refresh |'
|
||||
@@ -104,7 +147,7 @@ sub refresh {
|
||||
sub list_untracked {
|
||||
map {
|
||||
chomp $_;
|
||||
$_;
|
||||
unquote_path($_);
|
||||
}
|
||||
run_cmd_pipe(qw(git ls-files --others --exclude-standard --), @ARGV);
|
||||
}
|
||||
@@ -141,7 +184,8 @@ sub list_modified {
|
||||
|
||||
if (@ARGV) {
|
||||
@tracked = map {
|
||||
chomp $_; $_;
|
||||
chomp $_;
|
||||
unquote_path($_);
|
||||
} run_cmd_pipe(qw(git ls-files --exclude-standard --), @ARGV);
|
||||
return if (!@tracked);
|
||||
}
|
||||
@@ -153,6 +197,7 @@ sub list_modified {
|
||||
if (($add, $del, $file) =
|
||||
/^([-\d]+) ([-\d]+) (.*)/) {
|
||||
my ($change, $bin);
|
||||
$file = unquote_path($file);
|
||||
if ($add eq '-' && $del eq '-') {
|
||||
$change = 'binary';
|
||||
$bin = 1;
|
||||
@@ -168,6 +213,7 @@ sub list_modified {
|
||||
}
|
||||
elsif (($adddel, $file) =
|
||||
/^ (create|delete) mode [0-7]+ (.*)$/) {
|
||||
$file = unquote_path($file);
|
||||
$data{$file}{INDEX_ADDDEL} = $adddel;
|
||||
}
|
||||
}
|
||||
@@ -175,6 +221,7 @@ sub list_modified {
|
||||
for (run_cmd_pipe(qw(git diff-files --numstat --summary --), @tracked)) {
|
||||
if (($add, $del, $file) =
|
||||
/^([-\d]+) ([-\d]+) (.*)/) {
|
||||
$file = unquote_path($file);
|
||||
if (!exists $data{$file}) {
|
||||
$data{$file} = +{
|
||||
INDEX => 'unchanged',
|
||||
@@ -196,6 +243,7 @@ sub list_modified {
|
||||
}
|
||||
elsif (($adddel, $file) =
|
||||
/^ (create|delete) mode [0-7]+ (.*)$/) {
|
||||
$file = unquote_path($file);
|
||||
$data{$file}{FILE_ADDDEL} = $adddel;
|
||||
}
|
||||
}
|
||||
@@ -302,7 +350,8 @@ sub find_unique_prefixes {
|
||||
}
|
||||
%search = %{$search{$letter}};
|
||||
}
|
||||
if ($soft_limit && $j + 1 > $soft_limit) {
|
||||
if (ord($letters[0]) > 127 ||
|
||||
($soft_limit && $j + 1 > $soft_limit)) {
|
||||
$prefix = undef;
|
||||
$remainder = $ret;
|
||||
}
|
||||
@@ -753,6 +802,10 @@ EOF
|
||||
|| $ENV{VISUAL} || $ENV{EDITOR} || "vi";
|
||||
system('sh', '-c', $editor.' "$@"', $editor, $hunkfile);
|
||||
|
||||
if ($? != 0) {
|
||||
return undef;
|
||||
}
|
||||
|
||||
open $fh, '<', $hunkfile
|
||||
or die "failed to open hunk edit file for reading: " . $!;
|
||||
my @newtext = grep { !/^#/ } <$fh>;
|
||||
|
||||
@@ -512,7 +512,7 @@ bisect_next() {
|
||||
# commit is also a "skip" commit (see above).
|
||||
exit_if_skipped_commits "$bisect_rev"
|
||||
|
||||
bisect_checkout "$bisect_rev" "$bisect_nr revisions left to test after this"
|
||||
bisect_checkout "$bisect_rev" "$bisect_nr revisions left to test after this (roughly $bisect_steps steps)"
|
||||
}
|
||||
|
||||
bisect_visualize() {
|
||||
|
||||
@@ -319,6 +319,7 @@ static inline int has_extension(const char *filename, const char *ext)
|
||||
}
|
||||
|
||||
/* Sane ctype - no locale, and works with signed chars */
|
||||
#undef isascii
|
||||
#undef isspace
|
||||
#undef isdigit
|
||||
#undef isalpha
|
||||
@@ -332,6 +333,7 @@ extern unsigned char sane_ctype[256];
|
||||
#define GIT_GLOB_SPECIAL 0x08
|
||||
#define GIT_REGEX_SPECIAL 0x10
|
||||
#define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0)
|
||||
#define isascii(x) (((x) & ~0x7f) == 0)
|
||||
#define isspace(x) sane_istest(x,GIT_SPACE)
|
||||
#define isdigit(x) sane_istest(x,GIT_DIGIT)
|
||||
#define isalpha(x) sane_istest(x,GIT_ALPHA)
|
||||
|
||||
@@ -232,7 +232,9 @@ while read sha1 type name
|
||||
do
|
||||
case "$force,$name" in
|
||||
,$orig_namespace*)
|
||||
die "Namespace $orig_namespace not empty"
|
||||
die "Cannot create a new backup.
|
||||
A previous backup already exists in $orig_namespace
|
||||
Force overwriting the backup with -f"
|
||||
;;
|
||||
t,$orig_namespace*)
|
||||
git update-ref -d "$name" $sha1
|
||||
|
||||
@@ -49,7 +49,7 @@ resolve_full_httpd () {
|
||||
esac
|
||||
|
||||
httpd_only="$(echo $httpd | cut -f1 -d' ')"
|
||||
if case "$httpd_only" in /*) : ;; *) which $httpd_only >/dev/null;; esac
|
||||
if case "$httpd_only" in /*) : ;; *) which $httpd_only >/dev/null 2>&1;; esac
|
||||
then
|
||||
full_httpd=$httpd
|
||||
else
|
||||
@@ -179,11 +179,74 @@ lighttpd_conf () {
|
||||
cat > "$conf" <<EOF
|
||||
server.document-root = "$fqgitdir/gitweb"
|
||||
server.port = $port
|
||||
server.modules = ( "mod_cgi" )
|
||||
server.modules = ( "mod_setenv", "mod_cgi" )
|
||||
server.indexfiles = ( "gitweb.cgi" )
|
||||
server.pid-file = "$fqgitdir/pid"
|
||||
server.errorlog = "$fqgitdir/gitweb/error.log"
|
||||
|
||||
# to enable, add "mod_access", "mod_accesslog" to server.modules
|
||||
# variable above and uncomment this
|
||||
#accesslog.filename = "$fqgitdir/gitweb/access.log"
|
||||
|
||||
setenv.add-environment = ( "PATH" => "/usr/local/bin:/usr/bin:/bin" )
|
||||
|
||||
cgi.assign = ( ".cgi" => "" )
|
||||
mimetype.assign = ( ".css" => "text/css" )
|
||||
|
||||
# mimetype mapping
|
||||
mimetype.assign = (
|
||||
".pdf" => "application/pdf",
|
||||
".sig" => "application/pgp-signature",
|
||||
".spl" => "application/futuresplash",
|
||||
".class" => "application/octet-stream",
|
||||
".ps" => "application/postscript",
|
||||
".torrent" => "application/x-bittorrent",
|
||||
".dvi" => "application/x-dvi",
|
||||
".gz" => "application/x-gzip",
|
||||
".pac" => "application/x-ns-proxy-autoconfig",
|
||||
".swf" => "application/x-shockwave-flash",
|
||||
".tar.gz" => "application/x-tgz",
|
||||
".tgz" => "application/x-tgz",
|
||||
".tar" => "application/x-tar",
|
||||
".zip" => "application/zip",
|
||||
".mp3" => "audio/mpeg",
|
||||
".m3u" => "audio/x-mpegurl",
|
||||
".wma" => "audio/x-ms-wma",
|
||||
".wax" => "audio/x-ms-wax",
|
||||
".ogg" => "application/ogg",
|
||||
".wav" => "audio/x-wav",
|
||||
".gif" => "image/gif",
|
||||
".jpg" => "image/jpeg",
|
||||
".jpeg" => "image/jpeg",
|
||||
".png" => "image/png",
|
||||
".xbm" => "image/x-xbitmap",
|
||||
".xpm" => "image/x-xpixmap",
|
||||
".xwd" => "image/x-xwindowdump",
|
||||
".css" => "text/css",
|
||||
".html" => "text/html",
|
||||
".htm" => "text/html",
|
||||
".js" => "text/javascript",
|
||||
".asc" => "text/plain",
|
||||
".c" => "text/plain",
|
||||
".cpp" => "text/plain",
|
||||
".log" => "text/plain",
|
||||
".conf" => "text/plain",
|
||||
".text" => "text/plain",
|
||||
".txt" => "text/plain",
|
||||
".dtd" => "text/xml",
|
||||
".xml" => "text/xml",
|
||||
".mpeg" => "video/mpeg",
|
||||
".mpg" => "video/mpeg",
|
||||
".mov" => "video/quicktime",
|
||||
".qt" => "video/quicktime",
|
||||
".avi" => "video/x-msvideo",
|
||||
".asf" => "video/x-ms-asf",
|
||||
".asx" => "video/x-ms-asf",
|
||||
".wmv" => "video/x-ms-wmv",
|
||||
".bz2" => "application/x-bzip",
|
||||
".tbz" => "application/x-bzip-compressed-tar",
|
||||
".tar.bz2" => "application/x-bzip-compressed-tar",
|
||||
"" => "text/plain"
|
||||
)
|
||||
EOF
|
||||
test x"$local" = xtrue && echo 'server.bind = "127.0.0.1"' >> "$conf"
|
||||
}
|
||||
|
||||
10
git-pull.sh
10
git-pull.sh
@@ -16,7 +16,7 @@ cd_to_toplevel
|
||||
test -z "$(git ls-files -u)" ||
|
||||
die "You are in the middle of a conflicted merge."
|
||||
|
||||
strategy_args= no_stat= no_commit= squash= no_ff= log_arg= verbosity=
|
||||
strategy_args= diffstat= no_commit= squash= no_ff= log_arg= verbosity=
|
||||
curr_branch=$(git symbolic-ref -q HEAD)
|
||||
curr_branch_short=$(echo "$curr_branch" | sed "s|refs/heads/||")
|
||||
rebase=$(git config --bool branch.$curr_branch_short.rebase)
|
||||
@@ -28,9 +28,9 @@ do
|
||||
-v|--verbose)
|
||||
verbosity="$verbosity -v" ;;
|
||||
-n|--no-stat|--no-summary)
|
||||
no_stat=-n ;;
|
||||
diffstat=--no-stat ;;
|
||||
--stat|--summary)
|
||||
no_stat=$1 ;;
|
||||
diffstat=--stat ;;
|
||||
--log|--no-log)
|
||||
log_arg=$1 ;;
|
||||
--no-c|--no-co|--no-com|--no-comm|--no-commi|--no-commit)
|
||||
@@ -188,7 +188,7 @@ fi
|
||||
|
||||
merge_name=$(git fmt-merge-msg $log_arg <"$GIT_DIR/FETCH_HEAD") || exit
|
||||
test true = "$rebase" &&
|
||||
exec git-rebase $strategy_args --onto $merge_head \
|
||||
exec git-rebase $diffstat $strategy_args --onto $merge_head \
|
||||
${oldremoteref:-$merge_head}
|
||||
exec git-merge $no_stat $no_commit $squash $no_ff $log_arg $strategy_args \
|
||||
exec git-merge $diffstat $no_commit $squash $no_ff $log_arg $strategy_args \
|
||||
"$merge_name" HEAD $merge_head $verbosity
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# Copyright (c) 2005 Junio C Hamano.
|
||||
#
|
||||
|
||||
USAGE='[--interactive | -i] [-v] [--onto <newbase>] [<upstream>|--root] [<branch>]'
|
||||
USAGE='[--interactive | -i] [-v] [--force-rebase | -f] [--onto <newbase>] [<upstream>|--root] [<branch>]'
|
||||
LONG_USAGE='git-rebase replaces <branch> with a new branch of the
|
||||
same name. When the --onto option is provided the new branch starts
|
||||
out with a HEAD equal to <newbase>, otherwise it is equal to <upstream>
|
||||
@@ -46,8 +46,10 @@ do_merge=
|
||||
dotest="$GIT_DIR"/rebase-merge
|
||||
prec=4
|
||||
verbose=
|
||||
diffstat=$(git config --bool rebase.stat)
|
||||
git_am_opt=
|
||||
rebase_root=
|
||||
force_rebase=
|
||||
|
||||
continue_merge () {
|
||||
test -n "$prev_head" || die "prev_head must be defined"
|
||||
@@ -289,11 +291,23 @@ do
|
||||
esac
|
||||
do_merge=t
|
||||
;;
|
||||
-n|--no-stat)
|
||||
diffstat=
|
||||
;;
|
||||
--stat)
|
||||
diffstat=t
|
||||
;;
|
||||
-v|--verbose)
|
||||
verbose=t
|
||||
diffstat=t
|
||||
;;
|
||||
--whitespace=*)
|
||||
git_am_opt="$git_am_opt $1"
|
||||
case "$1" in
|
||||
--whitespace=fix|--whitespace=strip)
|
||||
force_rebase=t
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
-C*)
|
||||
git_am_opt="$git_am_opt $1"
|
||||
@@ -301,6 +315,9 @@ do
|
||||
--root)
|
||||
rebase_root=t
|
||||
;;
|
||||
-f|--f|--fo|--for|--forc|force|--force-r|--force-re|--force-reb|--force-reba|--force_rebas|--force-rebase)
|
||||
force_rebase=t
|
||||
;;
|
||||
-*)
|
||||
usage
|
||||
;;
|
||||
@@ -420,17 +437,15 @@ if test "$upstream" = "$onto" && test "$mb" = "$onto" &&
|
||||
# linear history?
|
||||
! (git rev-list --parents "$onto".."$branch" | grep " .* ") > /dev/null
|
||||
then
|
||||
# Lazily switch to the target branch if needed...
|
||||
test -z "$switch_to" || git checkout "$switch_to"
|
||||
echo >&2 "Current branch $branch_name is up to date."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test -n "$verbose"
|
||||
then
|
||||
echo "Changes from $mb to $onto:"
|
||||
# We want color (if set), but no pager
|
||||
GIT_PAGER='' git diff --stat --summary "$mb" "$onto"
|
||||
if test -z "$force_rebase"
|
||||
then
|
||||
# Lazily switch to the target branch if needed...
|
||||
test -z "$switch_to" || git checkout "$switch_to"
|
||||
echo >&2 "Current branch $branch_name is up to date."
|
||||
exit 0
|
||||
else
|
||||
echo "Current branch $branch_name is up to date, rebase forced."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Detach HEAD and reset the tree
|
||||
@@ -438,6 +453,16 @@ echo "First, rewinding head to replay your work on top of it..."
|
||||
git checkout -q "$onto^0" || die "could not detach HEAD"
|
||||
git update-ref ORIG_HEAD $branch
|
||||
|
||||
if test -n "$diffstat"
|
||||
then
|
||||
if test -n "$verbose"
|
||||
then
|
||||
echo "Changes from $mb to $onto:"
|
||||
fi
|
||||
# We want color (if set), but no pager
|
||||
GIT_PAGER='' git diff --stat --summary "$mb" "$onto"
|
||||
fi
|
||||
|
||||
# If the $onto is a proper descendant of the tip of the branch, then
|
||||
# we just fast forwarded.
|
||||
if test "$mb" = "$branch"
|
||||
|
||||
@@ -60,6 +60,7 @@ case ",$all_into_one," in
|
||||
args='--unpacked --incremental'
|
||||
;;
|
||||
,t,)
|
||||
args= existing=
|
||||
if [ -d "$PACKDIR" ]; then
|
||||
for e in `cd "$PACKDIR" && find . -type f -name '*.pack' \
|
||||
| sed -e 's/^\.\///' -e 's/\.pack$//'`
|
||||
@@ -67,10 +68,13 @@ case ",$all_into_one," in
|
||||
if [ -e "$PACKDIR/$e.keep" ]; then
|
||||
: keep
|
||||
else
|
||||
args="$args --unpacked=$e.pack"
|
||||
existing="$existing $e"
|
||||
fi
|
||||
done
|
||||
if test -n "$existing"
|
||||
then
|
||||
args="--kept-pack-only"
|
||||
fi
|
||||
if test -n "$args" -a -n "$unpack_unreachable" -a \
|
||||
-n "$remove_redundant"
|
||||
then
|
||||
|
||||
@@ -23,7 +23,7 @@ use Getopt::Long;
|
||||
use Text::ParseWords;
|
||||
use Data::Dumper;
|
||||
use Term::ANSIColor;
|
||||
use File::Temp qw/ tempdir /;
|
||||
use File::Temp qw/ tempdir tempfile /;
|
||||
use Error qw(:try);
|
||||
use Git;
|
||||
|
||||
@@ -68,14 +68,15 @@ git send-email [options] <file | directory | rev-list options >
|
||||
Automating:
|
||||
--identity <str> * Use the sendemail.<id> options.
|
||||
--cc-cmd <str> * Email Cc: via `<str> \$patch_path`
|
||||
--suppress-cc <str> * author, self, sob, cccmd, all.
|
||||
--[no-]signed-off-by-cc * Send to Cc: and Signed-off-by:
|
||||
addresses. Default on.
|
||||
--suppress-cc <str> * author, self, sob, cc, cccmd, body, bodycc, all.
|
||||
--[no-]signed-off-by-cc * Send to Signed-off-by: addresses. Default on.
|
||||
--[no-]suppress-from * Send to self. Default off.
|
||||
--[no-]chain-reply-to * Chain In-Reply-To: fields. Default on.
|
||||
--[no-]thread * Use In-Reply-To: field. Default on.
|
||||
|
||||
Administering:
|
||||
--confirm <str> * Confirm recipients before sending;
|
||||
auto, cc, compose, always, or never.
|
||||
--quiet * Output one line of info per email.
|
||||
--dry-run * Don't actually send the emails.
|
||||
--[no-]validate * Perform patch sanity checks. Default on.
|
||||
@@ -126,6 +127,7 @@ sub format_2822_time {
|
||||
}
|
||||
|
||||
my $have_email_valid = eval { require Email::Valid; 1 };
|
||||
my $have_mail_address = eval { require Mail::Address; 1 };
|
||||
my $smtp;
|
||||
my $auth;
|
||||
|
||||
@@ -156,7 +158,7 @@ if ($@) {
|
||||
# Behavior modification variables
|
||||
my ($quiet, $dry_run) = (0, 0);
|
||||
my $format_patch;
|
||||
my $compose_filename = $repo->repo_path() . "/.gitsendemail.msg.$$";
|
||||
my $compose_filename;
|
||||
|
||||
# Handle interactive edition of files.
|
||||
my $multiedit;
|
||||
@@ -181,7 +183,7 @@ sub do_edit {
|
||||
my ($thread, $chain_reply_to, $suppress_from, $signed_off_by_cc, $cc_cmd);
|
||||
my ($smtp_server, $smtp_server_port, $smtp_authuser, $smtp_encryption);
|
||||
my ($identity, $aliasfiletype, @alias_files, @smtp_host_parts);
|
||||
my ($validate);
|
||||
my ($validate, $confirm);
|
||||
my (@suppress_cc);
|
||||
|
||||
my %config_bool_settings = (
|
||||
@@ -207,6 +209,7 @@ my %config_settings = (
|
||||
"suppresscc" => \@suppress_cc,
|
||||
"envelopesender" => \$envelope_sender,
|
||||
"multiedit" => \$multiedit,
|
||||
"confirm" => \$confirm,
|
||||
);
|
||||
|
||||
# Handle Uncouth Termination
|
||||
@@ -219,11 +222,13 @@ sub signal_handler {
|
||||
system "stty echo";
|
||||
|
||||
# tmp files from --compose
|
||||
if (-e $compose_filename) {
|
||||
print "'$compose_filename' contains an intermediate version of the email you were composing.\n";
|
||||
}
|
||||
if (-e ($compose_filename . ".final")) {
|
||||
print "'$compose_filename.final' contains the composed email.\n"
|
||||
if (defined $compose_filename) {
|
||||
if (-e $compose_filename) {
|
||||
print "'$compose_filename' contains an intermediate version of the email you were composing.\n";
|
||||
}
|
||||
if (-e ($compose_filename . ".final")) {
|
||||
print "'$compose_filename.final' contains the composed email.\n"
|
||||
}
|
||||
}
|
||||
|
||||
exit;
|
||||
@@ -256,6 +261,7 @@ my $rc = GetOptions("sender|from=s" => \$sender,
|
||||
"suppress-from!" => \$suppress_from,
|
||||
"suppress-cc=s" => \@suppress_cc,
|
||||
"signed-off-cc|signed-off-by-cc!" => \$signed_off_by_cc,
|
||||
"confirm=s" => \$confirm,
|
||||
"dry-run" => \$dry_run,
|
||||
"envelope-sender=s" => \$envelope_sender,
|
||||
"thread!" => \$thread,
|
||||
@@ -267,6 +273,9 @@ unless ($rc) {
|
||||
usage();
|
||||
}
|
||||
|
||||
die "Cannot run git format-patch from outside a repository\n"
|
||||
if $format_patch and not $repo;
|
||||
|
||||
# Now, let's fill any that aren't set in with defaults:
|
||||
|
||||
sub read_config {
|
||||
@@ -318,13 +327,13 @@ my(%suppress_cc);
|
||||
if (@suppress_cc) {
|
||||
foreach my $entry (@suppress_cc) {
|
||||
die "Unknown --suppress-cc field: '$entry'\n"
|
||||
unless $entry =~ /^(all|cccmd|cc|author|self|sob)$/;
|
||||
unless $entry =~ /^(all|cccmd|cc|author|self|sob|body|bodycc)$/;
|
||||
$suppress_cc{$entry} = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($suppress_cc{'all'}) {
|
||||
foreach my $entry (qw (ccmd cc author self sob)) {
|
||||
foreach my $entry (qw (ccmd cc author self sob body bodycc)) {
|
||||
$suppress_cc{$entry} = 1;
|
||||
}
|
||||
delete $suppress_cc{'all'};
|
||||
@@ -334,6 +343,21 @@ if ($suppress_cc{'all'}) {
|
||||
$suppress_cc{'self'} = $suppress_from if defined $suppress_from;
|
||||
$suppress_cc{'sob'} = !$signed_off_by_cc if defined $signed_off_by_cc;
|
||||
|
||||
if ($suppress_cc{'body'}) {
|
||||
foreach my $entry (qw (sob bodycc)) {
|
||||
$suppress_cc{$entry} = 1;
|
||||
}
|
||||
delete $suppress_cc{'body'};
|
||||
}
|
||||
|
||||
# Set confirm's default value
|
||||
my $confirm_unconfigured = !defined $confirm;
|
||||
if ($confirm_unconfigured) {
|
||||
$confirm = scalar %suppress_cc ? 'compose' : 'auto';
|
||||
};
|
||||
die "Unknown --confirm setting: '$confirm'\n"
|
||||
unless $confirm =~ /^(?:auto|cc|compose|always|never)/;
|
||||
|
||||
# Debugging, print out the suppressions.
|
||||
if (0) {
|
||||
print "suppressions:\n";
|
||||
@@ -360,6 +384,14 @@ foreach my $entry (@bcclist) {
|
||||
die "Comma in --bcclist entry: $entry'\n" unless $entry !~ m/,/;
|
||||
}
|
||||
|
||||
sub parse_address_line {
|
||||
if ($have_mail_address) {
|
||||
return map { $_->format } Mail::Address->parse($_[0]);
|
||||
} else {
|
||||
return split_addrs($_[0]);
|
||||
}
|
||||
}
|
||||
|
||||
sub split_addrs {
|
||||
return quotewords('\s*,\s*', 1, @_);
|
||||
}
|
||||
@@ -404,6 +436,7 @@ if (@alias_files and $aliasfiletype and defined $parse_alias{$aliasfiletype}) {
|
||||
|
||||
# returns 1 if the conflict must be solved using it as a format-patch argument
|
||||
sub check_file_rev_conflict($) {
|
||||
return unless $repo;
|
||||
my $f = shift;
|
||||
try {
|
||||
$repo->command('rev-parse', '--verify', '--quiet', $f);
|
||||
@@ -445,6 +478,8 @@ while (defined(my $f = shift @ARGV)) {
|
||||
}
|
||||
|
||||
if (@rev_list_opts) {
|
||||
die "Cannot run git format-patch from outside a repository\n"
|
||||
unless $repo;
|
||||
push @files, $repo->command('format-patch', '-o', tempdir(CLEANUP => 1), @rev_list_opts);
|
||||
}
|
||||
|
||||
@@ -481,6 +516,9 @@ sub get_patch_subject($) {
|
||||
if ($compose) {
|
||||
# Note that this does not need to be secure, but we will make a small
|
||||
# effort to have it be unique
|
||||
$compose_filename = ($repo ?
|
||||
tempfile(".gitsendemail.msg.XXXXXX", DIR => $repo->repo_path()) :
|
||||
tempfile(".gitsendemail.msg.XXXXXX", DIR => "."))[1];
|
||||
open(C,">",$compose_filename)
|
||||
or die "Failed to open for writing $compose_filename: $!";
|
||||
|
||||
@@ -593,7 +631,7 @@ if (!@to) {
|
||||
}
|
||||
|
||||
my $to = $_;
|
||||
push @to, split_addrs($to);
|
||||
push @to, parse_address_line($to);
|
||||
$prompting++;
|
||||
}
|
||||
|
||||
@@ -637,25 +675,13 @@ if (!defined $smtp_server) {
|
||||
$smtp_server ||= 'localhost'; # could be 127.0.0.1, too... *shrug*
|
||||
}
|
||||
|
||||
if ($compose) {
|
||||
while (1) {
|
||||
$_ = $term->readline("Send this email? (y|n) ");
|
||||
last if defined $_;
|
||||
print "\n";
|
||||
}
|
||||
|
||||
if (uc substr($_,0,1) ne 'Y') {
|
||||
cleanup_compose_files();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($compose > 0) {
|
||||
@files = ($compose_filename . ".final", @files);
|
||||
}
|
||||
if ($compose && $compose > 0) {
|
||||
@files = ($compose_filename . ".final", @files);
|
||||
}
|
||||
|
||||
# Variables we set as part of the loop over files
|
||||
our ($message_id, %mail, $subject, $reply_to, $references, $message);
|
||||
our ($message_id, %mail, $subject, $reply_to, $references, $message,
|
||||
$needs_confirm, $message_num);
|
||||
|
||||
sub extract_valid_address {
|
||||
my $address = shift;
|
||||
@@ -811,6 +837,37 @@ X-Mailer: git-send-email $gitversion
|
||||
unshift (@sendmail_parameters,
|
||||
'-f', $raw_from) if(defined $envelope_sender);
|
||||
|
||||
if ($needs_confirm && !$dry_run) {
|
||||
print "\n$header\n";
|
||||
if ($needs_confirm eq "inform") {
|
||||
$confirm_unconfigured = 0; # squelch this message for the rest of this run
|
||||
print " The Cc list above has been expanded by additional\n";
|
||||
print " addresses found in the patch commit message. By default\n";
|
||||
print " send-email prompts before sending whenever this occurs.\n";
|
||||
print " This behavior is controlled by the sendemail.confirm\n";
|
||||
print " configuration setting.\n";
|
||||
print "\n";
|
||||
print " For additional information, run 'git send-email --help'.\n";
|
||||
print " To retain the current behavior, but squelch this message,\n";
|
||||
print " run 'git config --global sendemail.confirm auto'.\n\n";
|
||||
}
|
||||
while (1) {
|
||||
chomp ($_ = $term->readline(
|
||||
"Send this email? ([y]es|[n]o|[q]uit|[a]ll): "
|
||||
));
|
||||
last if /^(?:yes|y|no|n|quit|q|all|a)/i;
|
||||
print "\n";
|
||||
}
|
||||
if (/^n/i) {
|
||||
return;
|
||||
} elsif (/^q/i) {
|
||||
cleanup_compose_files();
|
||||
exit(0);
|
||||
} elsif (/^a/i) {
|
||||
$confirm = 'never';
|
||||
}
|
||||
}
|
||||
|
||||
if ($dry_run) {
|
||||
# We don't want to send the email.
|
||||
} elsif ($smtp_server =~ m#^/#) {
|
||||
@@ -909,6 +966,7 @@ X-Mailer: git-send-email $gitversion
|
||||
$reply_to = $initial_reply_to;
|
||||
$references = $initial_reply_to || '';
|
||||
$subject = $initial_subject;
|
||||
$message_num = 0;
|
||||
|
||||
foreach my $t (@files) {
|
||||
open(F,"<",$t) or die "can't open file $t";
|
||||
@@ -917,91 +975,106 @@ foreach my $t (@files) {
|
||||
my $author_encoding;
|
||||
my $has_content_type;
|
||||
my $body_encoding;
|
||||
@cc = @initial_cc;
|
||||
@cc = ();
|
||||
@xh = ();
|
||||
my $input_format = undef;
|
||||
my $header_done = 0;
|
||||
my @header = ();
|
||||
$message = "";
|
||||
$message_num++;
|
||||
# First unfold multiline header fields
|
||||
while(<F>) {
|
||||
if (!$header_done) {
|
||||
if (/^From /) {
|
||||
$input_format = 'mbox';
|
||||
next;
|
||||
}
|
||||
chomp;
|
||||
if (!defined $input_format && /^[-A-Za-z]+:\s/) {
|
||||
$input_format = 'mbox';
|
||||
}
|
||||
last if /^\s*$/;
|
||||
if (/^\s+\S/ and @header) {
|
||||
chomp($header[$#header]);
|
||||
s/^\s+/ /;
|
||||
$header[$#header] .= $_;
|
||||
} else {
|
||||
push(@header, $_);
|
||||
}
|
||||
}
|
||||
# Now parse the header
|
||||
foreach(@header) {
|
||||
if (/^From /) {
|
||||
$input_format = 'mbox';
|
||||
next;
|
||||
}
|
||||
chomp;
|
||||
if (!defined $input_format && /^[-A-Za-z]+:\s/) {
|
||||
$input_format = 'mbox';
|
||||
}
|
||||
|
||||
if (defined $input_format && $input_format eq 'mbox') {
|
||||
if (/^Subject:\s+(.*)$/) {
|
||||
$subject = $1;
|
||||
|
||||
} elsif (/^(Cc|From):\s+(.*)$/) {
|
||||
if (unquote_rfc2047($2) eq $sender) {
|
||||
if (defined $input_format && $input_format eq 'mbox') {
|
||||
if (/^Subject:\s+(.*)$/) {
|
||||
$subject = $1;
|
||||
}
|
||||
elsif (/^From:\s+(.*)$/) {
|
||||
($author, $author_encoding) = unquote_rfc2047($1);
|
||||
next if $suppress_cc{'author'};
|
||||
next if $suppress_cc{'self'} and $author eq $sender;
|
||||
printf("(mbox) Adding cc: %s from line '%s'\n",
|
||||
$1, $_) unless $quiet;
|
||||
push @cc, $1;
|
||||
}
|
||||
elsif (/^Cc:\s+(.*)$/) {
|
||||
foreach my $addr (parse_address_line($1)) {
|
||||
if (unquote_rfc2047($addr) eq $sender) {
|
||||
next if ($suppress_cc{'self'});
|
||||
}
|
||||
elsif ($1 eq 'From') {
|
||||
($author, $author_encoding)
|
||||
= unquote_rfc2047($2);
|
||||
next if ($suppress_cc{'author'});
|
||||
} else {
|
||||
next if ($suppress_cc{'cc'});
|
||||
}
|
||||
printf("(mbox) Adding cc: %s from line '%s'\n",
|
||||
$2, $_) unless $quiet;
|
||||
push @cc, $2;
|
||||
}
|
||||
elsif (/^Content-type:/i) {
|
||||
$has_content_type = 1;
|
||||
if (/charset="?([^ "]+)/) {
|
||||
$body_encoding = $1;
|
||||
}
|
||||
push @xh, $_;
|
||||
}
|
||||
elsif (/^Message-Id: (.*)/i) {
|
||||
$message_id = $1;
|
||||
}
|
||||
elsif (!/^Date:\s/ && /^[-A-Za-z]+:\s+\S/) {
|
||||
push @xh, $_;
|
||||
}
|
||||
|
||||
} else {
|
||||
# In the traditional
|
||||
# "send lots of email" format,
|
||||
# line 1 = cc
|
||||
# line 2 = subject
|
||||
# So let's support that, too.
|
||||
$input_format = 'lots';
|
||||
if (@cc == 0 && !$suppress_cc{'cc'}) {
|
||||
printf("(non-mbox) Adding cc: %s from line '%s'\n",
|
||||
$_, $_) unless $quiet;
|
||||
|
||||
push @cc, $_;
|
||||
|
||||
} elsif (!defined $subject) {
|
||||
$subject = $_;
|
||||
$addr, $_) unless $quiet;
|
||||
push @cc, $addr;
|
||||
}
|
||||
}
|
||||
|
||||
# A whitespace line will terminate the headers
|
||||
if (m/^\s*$/) {
|
||||
$header_done = 1;
|
||||
elsif (/^Content-type:/i) {
|
||||
$has_content_type = 1;
|
||||
if (/charset="?([^ "]+)/) {
|
||||
$body_encoding = $1;
|
||||
}
|
||||
push @xh, $_;
|
||||
}
|
||||
elsif (/^Message-Id: (.*)/i) {
|
||||
$message_id = $1;
|
||||
}
|
||||
elsif (!/^Date:\s/ && /^[-A-Za-z]+:\s+\S/) {
|
||||
push @xh, $_;
|
||||
}
|
||||
|
||||
} else {
|
||||
$message .= $_;
|
||||
if (/^(Signed-off-by|Cc): (.*)$/i) {
|
||||
next if ($suppress_cc{'sob'});
|
||||
chomp;
|
||||
my $c = $2;
|
||||
chomp $c;
|
||||
next if ($c eq $sender and $suppress_cc{'self'});
|
||||
push @cc, $c;
|
||||
printf("(sob) Adding cc: %s from line '%s'\n",
|
||||
$c, $_) unless $quiet;
|
||||
# In the traditional
|
||||
# "send lots of email" format,
|
||||
# line 1 = cc
|
||||
# line 2 = subject
|
||||
# So let's support that, too.
|
||||
$input_format = 'lots';
|
||||
if (@cc == 0 && !$suppress_cc{'cc'}) {
|
||||
printf("(non-mbox) Adding cc: %s from line '%s'\n",
|
||||
$_, $_) unless $quiet;
|
||||
push @cc, $_;
|
||||
} elsif (!defined $subject) {
|
||||
$subject = $_;
|
||||
}
|
||||
}
|
||||
}
|
||||
# Now parse the message body
|
||||
while(<F>) {
|
||||
$message .= $_;
|
||||
if (/^(Signed-off-by|Cc): (.*)$/i) {
|
||||
chomp;
|
||||
my ($what, $c) = ($1, $2);
|
||||
chomp $c;
|
||||
if ($c eq $sender) {
|
||||
next if ($suppress_cc{'self'});
|
||||
} else {
|
||||
next if $suppress_cc{'sob'} and $what =~ /Signed-off-by/i;
|
||||
next if $suppress_cc{'bodycc'} and $what =~ /Cc/i;
|
||||
}
|
||||
push @cc, $c;
|
||||
printf("(body) Adding cc: %s from line '%s'\n",
|
||||
$c, $_) unless $quiet;
|
||||
}
|
||||
}
|
||||
close F;
|
||||
|
||||
if (defined $cc_cmd && !$suppress_cc{'cccmd'}) {
|
||||
@@ -1020,7 +1093,7 @@ foreach my $t (@files) {
|
||||
or die "(cc-cmd) failed to close pipe to '$cc_cmd'";
|
||||
}
|
||||
|
||||
if (defined $author) {
|
||||
if (defined $author and $author ne $sender) {
|
||||
$message = "From: $author\n\n$message";
|
||||
if (defined $author_encoding) {
|
||||
if ($has_content_type) {
|
||||
@@ -1040,6 +1113,14 @@ foreach my $t (@files) {
|
||||
}
|
||||
}
|
||||
|
||||
$needs_confirm = (
|
||||
$confirm eq "always" or
|
||||
($confirm =~ /^(?:auto|cc)$/ && @cc) or
|
||||
($confirm =~ /^(?:auto|compose)$/ && $compose && $message_num == 1));
|
||||
$needs_confirm = "inform" if ($needs_confirm && $confirm_unconfigured && @cc);
|
||||
|
||||
@cc = (@initial_cc, @cc);
|
||||
|
||||
send_message();
|
||||
|
||||
# set up for the next message
|
||||
@@ -1054,13 +1135,10 @@ foreach my $t (@files) {
|
||||
$message_id = undef;
|
||||
}
|
||||
|
||||
if ($compose) {
|
||||
cleanup_compose_files();
|
||||
}
|
||||
cleanup_compose_files();
|
||||
|
||||
sub cleanup_compose_files() {
|
||||
unlink($compose_filename, $compose_filename . ".final");
|
||||
|
||||
unlink($compose_filename, $compose_filename . ".final") if $compose;
|
||||
}
|
||||
|
||||
$smtp->quit if $smtp;
|
||||
|
||||
@@ -167,9 +167,18 @@ cmd_add()
|
||||
;;
|
||||
esac
|
||||
|
||||
# strip trailing slashes from path
|
||||
path=$(echo "$path" | sed -e 's|/*$||')
|
||||
|
||||
# normalize path:
|
||||
# multiple //; leading ./; /./; /../; trailing /
|
||||
path=$(printf '%s/\n' "$path" |
|
||||
sed -e '
|
||||
s|//*|/|g
|
||||
s|^\(\./\)*||
|
||||
s|/\./|/|g
|
||||
:start
|
||||
s|\([^/]*\)/\.\./||
|
||||
tstart
|
||||
s|/*$||
|
||||
')
|
||||
git ls-files --error-unmatch "$path" > /dev/null 2>&1 &&
|
||||
die "'$path' already exists in the index"
|
||||
|
||||
|
||||
@@ -2351,7 +2351,10 @@ sub match_paths {
|
||||
if (my $path = $paths->{"/$self->{path}"}) {
|
||||
return ($path->{action} eq 'D') ? 0 : 1;
|
||||
}
|
||||
$self->{path_regex} ||= qr/^\/\Q$self->{path}\E\//;
|
||||
my $repos_root = $self->ra->{repos_root};
|
||||
my $extended_path = $self->{url} . '/' . $self->{path};
|
||||
$extended_path =~ s#^\Q$repos_root\E(/|$)##;
|
||||
$self->{path_regex} ||= qr/^\/\Q$extended_path\E\//;
|
||||
if (grep /$self->{path_regex}/, keys %$paths) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -84,8 +84,6 @@ int main(int argc, const char **argv)
|
||||
|
||||
git_extract_argv0_path(argv[0]);
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
|
||||
argc = parse_options(argc, argv, hash_object_options, hash_object_usage, 0);
|
||||
|
||||
if (write_object) {
|
||||
@@ -95,6 +93,8 @@ int main(int argc, const char **argv)
|
||||
vpath = prefix_filename(prefix, prefix_length, vpath);
|
||||
}
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
|
||||
if (stdin_paths) {
|
||||
if (hashstdin)
|
||||
errstr = "Can't use --stdin-paths with --stdin";
|
||||
|
||||
@@ -816,7 +816,7 @@ static void finish_request(struct transfer_request *request)
|
||||
#ifdef USE_CURL_MULTI
|
||||
static int fill_active_slot(void *unused)
|
||||
{
|
||||
struct transfer_request *request = request_queue_head;
|
||||
struct transfer_request *request;
|
||||
|
||||
if (aborted)
|
||||
return 0;
|
||||
|
||||
30
http.c
30
http.c
@@ -573,31 +573,21 @@ static inline int hex(int v)
|
||||
|
||||
static char *quote_ref_url(const char *base, const char *ref)
|
||||
{
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
const char *cp;
|
||||
char *dp, *qref;
|
||||
int len, baselen, ch;
|
||||
int ch;
|
||||
|
||||
baselen = strlen(base);
|
||||
len = baselen + 2; /* '/' after base and terminating NUL */
|
||||
for (cp = ref; (ch = *cp) != 0; cp++, len++)
|
||||
strbuf_addstr(&buf, base);
|
||||
if (buf.len && buf.buf[buf.len - 1] != '/' && *ref != '/')
|
||||
strbuf_addstr(&buf, "/");
|
||||
|
||||
for (cp = ref; (ch = *cp) != 0; cp++)
|
||||
if (needs_quote(ch))
|
||||
len += 2; /* extra two hex plus replacement % */
|
||||
qref = xmalloc(len);
|
||||
memcpy(qref, base, baselen);
|
||||
dp = qref + baselen;
|
||||
*(dp++) = '/';
|
||||
for (cp = ref; (ch = *cp) != 0; cp++) {
|
||||
if (needs_quote(ch)) {
|
||||
*dp++ = '%';
|
||||
*dp++ = hex((ch >> 4) & 0xF);
|
||||
*dp++ = hex(ch & 0xF);
|
||||
}
|
||||
strbuf_addf(&buf, "%%%02x", ch);
|
||||
else
|
||||
*dp++ = ch;
|
||||
}
|
||||
*dp = 0;
|
||||
strbuf_addch(&buf, *cp);
|
||||
|
||||
return qref;
|
||||
return strbuf_detach(&buf, NULL);
|
||||
}
|
||||
|
||||
int http_fetch_ref(const char *base, struct ref *ref)
|
||||
|
||||
55
imap-send.c
55
imap-send.c
@@ -135,6 +135,7 @@ struct imap_server_conf {
|
||||
char *pass;
|
||||
int use_ssl;
|
||||
int ssl_verify;
|
||||
int use_html;
|
||||
};
|
||||
|
||||
struct imap_store_conf {
|
||||
@@ -578,7 +579,7 @@ static struct imap_cmd *v_issue_imap_cmd(struct imap_store *ctx,
|
||||
n = socket_write(&imap->buf.sock, cmd->cb.data, cmd->cb.dlen);
|
||||
free(cmd->cb.data);
|
||||
if (n != cmd->cb.dlen ||
|
||||
(n = socket_write(&imap->buf.sock, "\r\n", 2)) != 2) {
|
||||
socket_write(&imap->buf.sock, "\r\n", 2) != 2) {
|
||||
free(cmd->cmd);
|
||||
free(cmd);
|
||||
return NULL;
|
||||
@@ -1263,6 +1264,53 @@ static int imap_store_msg(struct store *gctx, struct msg_data *data, int *uid)
|
||||
return DRV_OK;
|
||||
}
|
||||
|
||||
static void encode_html_chars(struct strbuf *p)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < p->len; i++) {
|
||||
if (p->buf[i] == '&')
|
||||
strbuf_splice(p, i, 1, "&", 5);
|
||||
if (p->buf[i] == '<')
|
||||
strbuf_splice(p, i, 1, "<", 4);
|
||||
if (p->buf[i] == '>')
|
||||
strbuf_splice(p, i, 1, ">", 4);
|
||||
if (p->buf[i] == '"')
|
||||
strbuf_splice(p, i, 1, """, 6);
|
||||
}
|
||||
}
|
||||
static void wrap_in_html(struct msg_data *msg)
|
||||
{
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
struct strbuf **lines;
|
||||
struct strbuf **p;
|
||||
static char *content_type = "Content-Type: text/html;\n";
|
||||
static char *pre_open = "<pre>\n";
|
||||
static char *pre_close = "</pre>\n";
|
||||
int added_header = 0;
|
||||
|
||||
strbuf_attach(&buf, msg->data, msg->len, msg->len);
|
||||
lines = strbuf_split(&buf, '\n');
|
||||
strbuf_release(&buf);
|
||||
for (p = lines; *p; p++) {
|
||||
if (! added_header) {
|
||||
if ((*p)->len == 1 && *((*p)->buf) == '\n') {
|
||||
strbuf_addstr(&buf, content_type);
|
||||
strbuf_addbuf(&buf, *p);
|
||||
strbuf_addstr(&buf, pre_open);
|
||||
added_header = 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
encode_html_chars(*p);
|
||||
strbuf_addbuf(&buf, *p);
|
||||
}
|
||||
strbuf_addstr(&buf, pre_close);
|
||||
strbuf_list_free(lines);
|
||||
msg->len = buf.len;
|
||||
msg->data = strbuf_detach(&buf, NULL);
|
||||
}
|
||||
|
||||
#define CHUNKSIZE 0x1000
|
||||
|
||||
static int read_message(FILE *f, struct msg_data *msg)
|
||||
@@ -1339,6 +1387,7 @@ static struct imap_server_conf server = {
|
||||
NULL, /* pass */
|
||||
0, /* use_ssl */
|
||||
1, /* ssl_verify */
|
||||
0, /* use_html */
|
||||
};
|
||||
|
||||
static char *imap_folder;
|
||||
@@ -1377,6 +1426,8 @@ static int git_imap_config(const char *key, const char *val, void *cb)
|
||||
server.tunnel = xstrdup(val);
|
||||
else if (!strcmp("sslverify", key))
|
||||
server.ssl_verify = git_config_bool(key, val);
|
||||
else if (!strcmp("preformattedHTML", key))
|
||||
server.use_html = git_config_bool(key, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1439,6 +1490,8 @@ int main(int argc, char **argv)
|
||||
fprintf(stderr, "%4u%% (%d/%d) done\r", percent, n, total);
|
||||
if (!split_msg(&all_msgs, &msg, &ofs))
|
||||
break;
|
||||
if (server.use_html)
|
||||
wrap_in_html(&msg);
|
||||
r = imap_store_msg(ctx, &msg, &uid);
|
||||
if (r != DRV_OK)
|
||||
break;
|
||||
|
||||
@@ -232,7 +232,7 @@ static void free_base_data(struct base_data *c)
|
||||
|
||||
static void prune_base_data(struct base_data *retain)
|
||||
{
|
||||
struct base_data *b = base_cache;
|
||||
struct base_data *b;
|
||||
for (b = base_cache;
|
||||
base_cache_used > delta_base_cache_limit && b;
|
||||
b = b->child) {
|
||||
|
||||
@@ -158,7 +158,7 @@ static int lock_file(struct lock_file *lk, const char *path, int flags)
|
||||
|
||||
NORETURN void unable_to_lock_index_die(const char *path, int err)
|
||||
{
|
||||
if (errno == EEXIST) {
|
||||
if (err == EEXIST) {
|
||||
die("Unable to create '%s.lock': %s.\n\n"
|
||||
"If no other git process is currently running, this probably means a\n"
|
||||
"git process crashed in this repository earlier. Make sure no other git\n"
|
||||
@@ -184,7 +184,7 @@ int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
|
||||
fd = lock_file(lk, path, flags);
|
||||
if (fd < 0) {
|
||||
if (flags & LOCK_DIE_ON_ERROR)
|
||||
die("unable to create '%s.lock': %s", path, strerror(errno));
|
||||
unable_to_lock_index_die(path, errno);
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
17
log-tree.c
17
log-tree.c
@@ -6,6 +6,7 @@
|
||||
#include "log-tree.h"
|
||||
#include "reflog-walk.h"
|
||||
#include "refs.h"
|
||||
#include "string-list.h"
|
||||
|
||||
struct decoration name_decoration = { "object names" };
|
||||
|
||||
@@ -79,18 +80,18 @@ void show_decorations(struct rev_info *opt, struct commit *commit)
|
||||
*/
|
||||
static int detect_any_signoff(char *letter, int size)
|
||||
{
|
||||
char ch, *cp;
|
||||
char *cp;
|
||||
int seen_colon = 0;
|
||||
int seen_at = 0;
|
||||
int seen_name = 0;
|
||||
int seen_head = 0;
|
||||
|
||||
cp = letter + size;
|
||||
while (letter <= --cp && (ch = *cp) == '\n')
|
||||
while (letter <= --cp && *cp == '\n')
|
||||
continue;
|
||||
|
||||
while (letter <= cp) {
|
||||
ch = *cp--;
|
||||
char ch = *cp--;
|
||||
if (ch == '\n')
|
||||
break;
|
||||
|
||||
@@ -211,9 +212,13 @@ void log_write_email_headers(struct rev_info *opt, const char *name,
|
||||
printf("Message-Id: <%s>\n", opt->message_id);
|
||||
graph_show_oneline(opt->graph);
|
||||
}
|
||||
if (opt->ref_message_id) {
|
||||
printf("In-Reply-To: <%s>\nReferences: <%s>\n",
|
||||
opt->ref_message_id, opt->ref_message_id);
|
||||
if (opt->ref_message_ids && opt->ref_message_ids->nr > 0) {
|
||||
int i, n;
|
||||
n = opt->ref_message_ids->nr;
|
||||
printf("In-Reply-To: <%s>\n", opt->ref_message_ids->items[n-1].string);
|
||||
for (i = 0; i < n; i++)
|
||||
printf("%s<%s>\n", (i > 0 ? "\t" : "References: "),
|
||||
opt->ref_message_ids->items[i].string);
|
||||
graph_show_oneline(opt->graph);
|
||||
}
|
||||
if (opt->mime_boundary) {
|
||||
|
||||
@@ -801,22 +801,19 @@ static int process_renames(struct merge_options *o,
|
||||
}
|
||||
|
||||
for (i = 0, j = 0; i < a_renames->nr || j < b_renames->nr;) {
|
||||
int compare;
|
||||
char *src;
|
||||
struct string_list *renames1, *renames2, *renames2Dst;
|
||||
struct string_list *renames1, *renames2Dst;
|
||||
struct rename *ren1 = NULL, *ren2 = NULL;
|
||||
const char *branch1, *branch2;
|
||||
const char *ren1_src, *ren1_dst;
|
||||
|
||||
if (i >= a_renames->nr) {
|
||||
compare = 1;
|
||||
ren2 = b_renames->items[j++].util;
|
||||
} else if (j >= b_renames->nr) {
|
||||
compare = -1;
|
||||
ren1 = a_renames->items[i++].util;
|
||||
} else {
|
||||
compare = strcmp(a_renames->items[i].string,
|
||||
b_renames->items[j].string);
|
||||
int compare = strcmp(a_renames->items[i].string,
|
||||
b_renames->items[j].string);
|
||||
if (compare <= 0)
|
||||
ren1 = a_renames->items[i++].util;
|
||||
if (compare >= 0)
|
||||
@@ -826,14 +823,12 @@ static int process_renames(struct merge_options *o,
|
||||
/* TODO: refactor, so that 1/2 are not needed */
|
||||
if (ren1) {
|
||||
renames1 = a_renames;
|
||||
renames2 = b_renames;
|
||||
renames2Dst = &b_by_dst;
|
||||
branch1 = o->branch1;
|
||||
branch2 = o->branch2;
|
||||
} else {
|
||||
struct rename *tmp;
|
||||
renames1 = b_renames;
|
||||
renames2 = a_renames;
|
||||
renames2Dst = &a_by_dst;
|
||||
branch1 = o->branch2;
|
||||
branch2 = o->branch1;
|
||||
|
||||
@@ -244,6 +244,9 @@ void parse_options_start(struct parse_opt_ctx_t *ctx,
|
||||
ctx->out = argv;
|
||||
ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0);
|
||||
ctx->flags = flags;
|
||||
if ((flags & PARSE_OPT_KEEP_UNKNOWN) &&
|
||||
(flags & PARSE_OPT_STOP_AT_NON_OPTION))
|
||||
die("STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together");
|
||||
}
|
||||
|
||||
static int usage_with_options_internal(const char * const *,
|
||||
@@ -253,6 +256,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
|
||||
const struct option *options,
|
||||
const char * const usagestr[])
|
||||
{
|
||||
int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP);
|
||||
|
||||
/* we must reset ->opt, unknown short option leave it dangling */
|
||||
ctx->opt = NULL;
|
||||
|
||||
@@ -268,18 +273,18 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
|
||||
|
||||
if (arg[1] != '-') {
|
||||
ctx->opt = arg + 1;
|
||||
if (*ctx->opt == 'h')
|
||||
if (internal_help && *ctx->opt == 'h')
|
||||
return parse_options_usage(usagestr, options);
|
||||
switch (parse_short_opt(ctx, options)) {
|
||||
case -1:
|
||||
return parse_options_usage(usagestr, options);
|
||||
case -2:
|
||||
return PARSE_OPT_UNKNOWN;
|
||||
goto unknown;
|
||||
}
|
||||
if (ctx->opt)
|
||||
check_typos(arg + 1, options);
|
||||
while (ctx->opt) {
|
||||
if (*ctx->opt == 'h')
|
||||
if (internal_help && *ctx->opt == 'h')
|
||||
return parse_options_usage(usagestr, options);
|
||||
switch (parse_short_opt(ctx, options)) {
|
||||
case -1:
|
||||
@@ -292,7 +297,7 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
|
||||
*/
|
||||
ctx->argv[0] = xstrdup(ctx->opt - 1);
|
||||
*(char *)ctx->argv[0] = '-';
|
||||
return PARSE_OPT_UNKNOWN;
|
||||
goto unknown;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
@@ -306,16 +311,22 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
|
||||
break;
|
||||
}
|
||||
|
||||
if (!strcmp(arg + 2, "help-all"))
|
||||
if (internal_help && !strcmp(arg + 2, "help-all"))
|
||||
return usage_with_options_internal(usagestr, options, 1);
|
||||
if (!strcmp(arg + 2, "help"))
|
||||
if (internal_help && !strcmp(arg + 2, "help"))
|
||||
return parse_options_usage(usagestr, options);
|
||||
switch (parse_long_opt(ctx, arg + 2, options)) {
|
||||
case -1:
|
||||
return parse_options_usage(usagestr, options);
|
||||
case -2:
|
||||
return PARSE_OPT_UNKNOWN;
|
||||
goto unknown;
|
||||
}
|
||||
continue;
|
||||
unknown:
|
||||
if (!(ctx->flags & PARSE_OPT_KEEP_UNKNOWN))
|
||||
return PARSE_OPT_UNKNOWN;
|
||||
ctx->out[ctx->cpidx++] = ctx->argv[0];
|
||||
ctx->opt = NULL;
|
||||
}
|
||||
return PARSE_OPT_DONE;
|
||||
}
|
||||
@@ -356,6 +367,9 @@ int parse_options(int argc, const char **argv, const struct option *options,
|
||||
int usage_with_options_internal(const char * const *usagestr,
|
||||
const struct option *opts, int full)
|
||||
{
|
||||
if (!usagestr)
|
||||
return PARSE_OPT_HELP;
|
||||
|
||||
fprintf(stderr, "usage: %s\n", *usagestr++);
|
||||
while (*usagestr && **usagestr)
|
||||
fprintf(stderr, " or: %s\n", *usagestr++);
|
||||
|
||||
@@ -21,6 +21,8 @@ enum parse_opt_flags {
|
||||
PARSE_OPT_KEEP_DASHDASH = 1,
|
||||
PARSE_OPT_STOP_AT_NON_OPTION = 2,
|
||||
PARSE_OPT_KEEP_ARGV0 = 4,
|
||||
PARSE_OPT_KEEP_UNKNOWN = 8,
|
||||
PARSE_OPT_NO_INTERNAL_HELP = 16,
|
||||
};
|
||||
|
||||
enum parse_opt_option_flags {
|
||||
|
||||
35
pretty.c
35
pretty.c
@@ -10,6 +10,15 @@
|
||||
|
||||
static char *user_format;
|
||||
|
||||
static void save_user_format(struct rev_info *rev, const char *cp, int is_tformat)
|
||||
{
|
||||
free(user_format);
|
||||
user_format = xstrdup(cp);
|
||||
if (is_tformat)
|
||||
rev->use_terminator = 1;
|
||||
rev->commit_format = CMIT_FMT_USERFORMAT;
|
||||
}
|
||||
|
||||
void get_commit_format(const char *arg, struct rev_info *rev)
|
||||
{
|
||||
int i;
|
||||
@@ -33,12 +42,7 @@ void get_commit_format(const char *arg, struct rev_info *rev)
|
||||
return;
|
||||
}
|
||||
if (!prefixcmp(arg, "format:") || !prefixcmp(arg, "tformat:")) {
|
||||
const char *cp = strchr(arg, ':') + 1;
|
||||
free(user_format);
|
||||
user_format = xstrdup(cp);
|
||||
if (arg[0] == 't')
|
||||
rev->use_terminator = 1;
|
||||
rev->commit_format = CMIT_FMT_USERFORMAT;
|
||||
save_user_format(rev, strchr(arg, ':') + 1, arg[0] == 't');
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < ARRAY_SIZE(cmt_fmts); i++) {
|
||||
@@ -50,6 +54,10 @@ void get_commit_format(const char *arg, struct rev_info *rev)
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (strchr(arg, '%')) {
|
||||
save_user_format(rev, arg, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
die("invalid --pretty format: %s", arg);
|
||||
}
|
||||
@@ -75,8 +83,7 @@ static int get_one_line(const char *msg)
|
||||
/* High bit set, or ISO-2022-INT */
|
||||
int non_ascii(int ch)
|
||||
{
|
||||
ch = (ch & 0xff);
|
||||
return ((ch & 0x80) || (ch == 0x1b));
|
||||
return !isascii(ch) || ch == '\033';
|
||||
}
|
||||
|
||||
static int is_rfc2047_special(char ch)
|
||||
@@ -128,7 +135,6 @@ void pp_user_info(const char *what, enum cmit_fmt fmt, struct strbuf *sb,
|
||||
int namelen;
|
||||
unsigned long time;
|
||||
int tz;
|
||||
const char *filler = " ";
|
||||
|
||||
if (fmt == CMIT_FMT_ONELINE)
|
||||
return;
|
||||
@@ -147,7 +153,6 @@ void pp_user_info(const char *what, enum cmit_fmt fmt, struct strbuf *sb,
|
||||
while (line < name_tail && isspace(name_tail[-1]))
|
||||
name_tail--;
|
||||
display_name_length = name_tail - line;
|
||||
filler = "";
|
||||
strbuf_addstr(sb, "From: ");
|
||||
add_rfc2047(sb, line, display_name_length, encoding);
|
||||
strbuf_add(sb, name_tail, namelen - display_name_length);
|
||||
@@ -155,7 +160,7 @@ void pp_user_info(const char *what, enum cmit_fmt fmt, struct strbuf *sb,
|
||||
} else {
|
||||
strbuf_addf(sb, "%s: %.*s%.*s\n", what,
|
||||
(fmt == CMIT_FMT_FULLER) ? 4 : 0,
|
||||
filler, namelen, line);
|
||||
" ", namelen, line);
|
||||
}
|
||||
switch (fmt) {
|
||||
case CMIT_FMT_MEDIUM:
|
||||
@@ -568,16 +573,16 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
|
||||
return end - placeholder + 1;
|
||||
}
|
||||
if (!prefixcmp(placeholder + 1, "red")) {
|
||||
strbuf_addstr(sb, "\033[31m");
|
||||
strbuf_addstr(sb, GIT_COLOR_RED);
|
||||
return 4;
|
||||
} else if (!prefixcmp(placeholder + 1, "green")) {
|
||||
strbuf_addstr(sb, "\033[32m");
|
||||
strbuf_addstr(sb, GIT_COLOR_GREEN);
|
||||
return 6;
|
||||
} else if (!prefixcmp(placeholder + 1, "blue")) {
|
||||
strbuf_addstr(sb, "\033[34m");
|
||||
strbuf_addstr(sb, GIT_COLOR_BLUE);
|
||||
return 5;
|
||||
} else if (!prefixcmp(placeholder + 1, "reset")) {
|
||||
strbuf_addstr(sb, "\033[m");
|
||||
strbuf_addstr(sb, GIT_COLOR_RESET);
|
||||
return 6;
|
||||
} else
|
||||
return 0;
|
||||
|
||||
2
remote.c
2
remote.c
@@ -495,7 +495,7 @@ static struct refspec *parse_refspec_internal(int nr_refspec, const char **refsp
|
||||
int is_glob;
|
||||
const char *lhs, *rhs;
|
||||
|
||||
llen = is_glob = 0;
|
||||
is_glob = 0;
|
||||
|
||||
lhs = refspec[i];
|
||||
if (*lhs == '+') {
|
||||
|
||||
22
rerere.c
22
rerere.c
@@ -12,15 +12,15 @@ static int rerere_autoupdate;
|
||||
|
||||
static char *merge_rr_path;
|
||||
|
||||
static const char *rr_path(const char *name, const char *file)
|
||||
const char *rerere_path(const char *hex, const char *file)
|
||||
{
|
||||
return git_path("rr-cache/%s/%s", name, file);
|
||||
return git_path("rr-cache/%s/%s", hex, file);
|
||||
}
|
||||
|
||||
static int has_resolution(const char *name)
|
||||
int has_rerere_resolution(const char *hex)
|
||||
{
|
||||
struct stat st;
|
||||
return !stat(rr_path(name, "postimage"), &st);
|
||||
return !stat(rerere_path(hex, "postimage"), &st);
|
||||
}
|
||||
|
||||
static void read_rr(struct string_list *rr)
|
||||
@@ -208,12 +208,12 @@ static int merge(const char *name, const char *path)
|
||||
mmbuffer_t result = {NULL, 0};
|
||||
xpparam_t xpp = {XDF_NEED_MINIMAL};
|
||||
|
||||
if (handle_file(path, NULL, rr_path(name, "thisimage")) < 0)
|
||||
if (handle_file(path, NULL, rerere_path(name, "thisimage")) < 0)
|
||||
return 1;
|
||||
|
||||
if (read_mmfile(&cur, rr_path(name, "thisimage")) ||
|
||||
read_mmfile(&base, rr_path(name, "preimage")) ||
|
||||
read_mmfile(&other, rr_path(name, "postimage")))
|
||||
if (read_mmfile(&cur, rerere_path(name, "thisimage")) ||
|
||||
read_mmfile(&base, rerere_path(name, "preimage")) ||
|
||||
read_mmfile(&other, rerere_path(name, "postimage")))
|
||||
return 1;
|
||||
ret = xdl_merge(&base, &cur, "", &other, "",
|
||||
&xpp, XDL_MERGE_ZEALOUS, &result);
|
||||
@@ -291,7 +291,7 @@ static int do_plain_rerere(struct string_list *rr, int fd)
|
||||
string_list_insert(path, rr)->util = hex;
|
||||
if (mkdir(git_path("rr-cache/%s", hex), 0755))
|
||||
continue;
|
||||
handle_file(path, NULL, rr_path(hex, "preimage"));
|
||||
handle_file(path, NULL, rerere_path(hex, "preimage"));
|
||||
fprintf(stderr, "Recorded preimage for '%s'\n", path);
|
||||
}
|
||||
}
|
||||
@@ -307,7 +307,7 @@ static int do_plain_rerere(struct string_list *rr, int fd)
|
||||
const char *path = rr->items[i].string;
|
||||
const char *name = (const char *)rr->items[i].util;
|
||||
|
||||
if (has_resolution(name)) {
|
||||
if (has_rerere_resolution(name)) {
|
||||
if (!merge(name, path)) {
|
||||
if (rerere_autoupdate)
|
||||
string_list_insert(path, &update);
|
||||
@@ -326,7 +326,7 @@ static int do_plain_rerere(struct string_list *rr, int fd)
|
||||
continue;
|
||||
|
||||
fprintf(stderr, "Recorded resolution for '%s'.\n", path);
|
||||
copy_file(rr_path(name, "postimage"), path, 0666);
|
||||
copy_file(rerere_path(name, "postimage"), path, 0666);
|
||||
mark_resolved:
|
||||
rr->items[i].util = NULL;
|
||||
}
|
||||
|
||||
2
rerere.h
2
rerere.h
@@ -5,5 +5,7 @@
|
||||
|
||||
extern int setup_rerere(struct string_list *);
|
||||
extern int rerere(void);
|
||||
extern const char *rerere_path(const char *hex, const char *file);
|
||||
extern int has_rerere_resolution(const char *hex);
|
||||
|
||||
#endif
|
||||
|
||||
31
revision.c
31
revision.c
@@ -994,16 +994,6 @@ static void add_message_grep(struct rev_info *revs, const char *pattern)
|
||||
add_grep(revs, pattern, GREP_PATTERN_BODY);
|
||||
}
|
||||
|
||||
static void add_ignore_packed(struct rev_info *revs, const char *name)
|
||||
{
|
||||
int num = ++revs->num_ignore_packed;
|
||||
|
||||
revs->ignore_packed = xrealloc(revs->ignore_packed,
|
||||
sizeof(const char *) * (num + 1));
|
||||
revs->ignore_packed[num-1] = name;
|
||||
revs->ignore_packed[num] = NULL;
|
||||
}
|
||||
|
||||
static int handle_revision_opt(struct rev_info *revs, int argc, const char **argv,
|
||||
int *unkc, const char **unkv)
|
||||
{
|
||||
@@ -1116,12 +1106,12 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
|
||||
revs->edge_hint = 1;
|
||||
} else if (!strcmp(arg, "--unpacked")) {
|
||||
revs->unpacked = 1;
|
||||
free(revs->ignore_packed);
|
||||
revs->ignore_packed = NULL;
|
||||
revs->num_ignore_packed = 0;
|
||||
} else if (!prefixcmp(arg, "--unpacked=")) {
|
||||
revs->kept_pack_only = 0;
|
||||
} else if (!strcmp(arg, "--kept-pack-only")) {
|
||||
revs->unpacked = 1;
|
||||
add_ignore_packed(revs, arg+11);
|
||||
revs->kept_pack_only = 1;
|
||||
} else if (!prefixcmp(arg, "--unpacked=")) {
|
||||
die("--unpacked=<packfile> no longer supported.");
|
||||
} else if (!strcmp(arg, "-r")) {
|
||||
revs->diff = 1;
|
||||
DIFF_OPT_SET(&revs->diffopt, RECURSIVE);
|
||||
@@ -1144,9 +1134,13 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
|
||||
} else if (!strcmp(arg, "--pretty")) {
|
||||
revs->verbose_header = 1;
|
||||
get_commit_format(arg+8, revs);
|
||||
} else if (!prefixcmp(arg, "--pretty=")) {
|
||||
} else if (!prefixcmp(arg, "--pretty=") || !prefixcmp(arg, "--format=")) {
|
||||
revs->verbose_header = 1;
|
||||
get_commit_format(arg+9, revs);
|
||||
} else if (!strcmp(arg, "--oneline")) {
|
||||
revs->verbose_header = 1;
|
||||
get_commit_format("oneline", revs);
|
||||
revs->abbrev_commit = 1;
|
||||
} else if (!strcmp(arg, "--graph")) {
|
||||
revs->topo_order = 1;
|
||||
revs->rewrite_parents = 1;
|
||||
@@ -1685,7 +1679,10 @@ enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit)
|
||||
{
|
||||
if (commit->object.flags & SHOWN)
|
||||
return commit_ignore;
|
||||
if (revs->unpacked && has_sha1_pack(commit->object.sha1, revs->ignore_packed))
|
||||
if (revs->unpacked &&
|
||||
(revs->kept_pack_only
|
||||
? has_sha1_kept_pack(commit->object.sha1)
|
||||
: has_sha1_pack(commit->object.sha1)))
|
||||
return commit_ignore;
|
||||
if (revs->show_all)
|
||||
return commit_show;
|
||||
|
||||
@@ -49,7 +49,8 @@ struct rev_info {
|
||||
blob_objects:1,
|
||||
edge_hint:1,
|
||||
limited:1,
|
||||
unpacked:1, /* see also ignore_packed below */
|
||||
unpacked:1,
|
||||
kept_pack_only:1,
|
||||
boundary:2,
|
||||
left_right:1,
|
||||
rewrite_parents:1,
|
||||
@@ -80,16 +81,13 @@ struct rev_info {
|
||||
missing_newline:1;
|
||||
enum date_mode date_mode;
|
||||
|
||||
const char **ignore_packed; /* pretend objects in these are unpacked */
|
||||
int num_ignore_packed;
|
||||
|
||||
unsigned int abbrev;
|
||||
enum cmit_fmt commit_format;
|
||||
struct log_info *loginfo;
|
||||
int nr, total;
|
||||
const char *mime_boundary;
|
||||
char *message_id;
|
||||
const char *ref_message_id;
|
||||
struct string_list *ref_message_ids;
|
||||
const char *add_signoff;
|
||||
const char *extra_headers;
|
||||
const char *log_reencode;
|
||||
|
||||
60
sha1_file.c
60
sha1_file.c
@@ -1919,25 +1919,8 @@ off_t find_pack_entry_one(const unsigned char *sha1,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int matches_pack_name(struct packed_git *p, const char *name)
|
||||
{
|
||||
const char *last_c, *c;
|
||||
|
||||
if (!strcmp(p->pack_name, name))
|
||||
return 1;
|
||||
|
||||
for (c = p->pack_name, last_c = c; *c;)
|
||||
if (*c == '/')
|
||||
last_c = ++c;
|
||||
else
|
||||
++c;
|
||||
if (!strcmp(last_c, name))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e, const char **ignore_packed)
|
||||
static int find_pack_ent(const unsigned char *sha1, struct pack_entry *e,
|
||||
int kept_pack_only)
|
||||
{
|
||||
static struct packed_git *last_found = (void *)1;
|
||||
struct packed_git *p;
|
||||
@@ -1949,15 +1932,8 @@ static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e, cons
|
||||
p = (last_found == (void *)1) ? packed_git : last_found;
|
||||
|
||||
do {
|
||||
if (ignore_packed) {
|
||||
const char **ig;
|
||||
for (ig = ignore_packed; *ig; ig++)
|
||||
if (matches_pack_name(p, *ig))
|
||||
break;
|
||||
if (*ig)
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (kept_pack_only && !p->pack_keep)
|
||||
goto next;
|
||||
if (p->num_bad_objects) {
|
||||
unsigned i;
|
||||
for (i = 0; i < p->num_bad_objects; i++)
|
||||
@@ -1997,6 +1973,16 @@ static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e, cons
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
|
||||
{
|
||||
return find_pack_ent(sha1, e, 0);
|
||||
}
|
||||
|
||||
static int find_kept_pack_entry(const unsigned char *sha1, struct pack_entry *e)
|
||||
{
|
||||
return find_pack_ent(sha1, e, 1);
|
||||
}
|
||||
|
||||
struct packed_git *find_sha1_pack(const unsigned char *sha1,
|
||||
struct packed_git *packs)
|
||||
{
|
||||
@@ -2038,7 +2024,7 @@ int sha1_object_info(const unsigned char *sha1, unsigned long *sizep)
|
||||
struct pack_entry e;
|
||||
int status;
|
||||
|
||||
if (!find_pack_entry(sha1, &e, NULL)) {
|
||||
if (!find_pack_entry(sha1, &e)) {
|
||||
/* Most likely it's a loose object. */
|
||||
status = sha1_loose_object_info(sha1, sizep);
|
||||
if (status >= 0)
|
||||
@@ -2046,7 +2032,7 @@ int sha1_object_info(const unsigned char *sha1, unsigned long *sizep)
|
||||
|
||||
/* Not a loose object; someone else may have just packed it. */
|
||||
reprepare_packed_git();
|
||||
if (!find_pack_entry(sha1, &e, NULL))
|
||||
if (!find_pack_entry(sha1, &e))
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -2065,7 +2051,7 @@ static void *read_packed_sha1(const unsigned char *sha1,
|
||||
struct pack_entry e;
|
||||
void *data;
|
||||
|
||||
if (!find_pack_entry(sha1, &e, NULL))
|
||||
if (!find_pack_entry(sha1, &e))
|
||||
return NULL;
|
||||
data = cache_or_unpack_entry(e.p, e.offset, size, type, 1);
|
||||
if (!data) {
|
||||
@@ -2464,17 +2450,23 @@ int has_pack_file(const unsigned char *sha1)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int has_sha1_pack(const unsigned char *sha1, const char **ignore_packed)
|
||||
int has_sha1_pack(const unsigned char *sha1)
|
||||
{
|
||||
struct pack_entry e;
|
||||
return find_pack_entry(sha1, &e, ignore_packed);
|
||||
return find_pack_entry(sha1, &e);
|
||||
}
|
||||
|
||||
int has_sha1_kept_pack(const unsigned char *sha1)
|
||||
{
|
||||
struct pack_entry e;
|
||||
return find_kept_pack_entry(sha1, &e);
|
||||
}
|
||||
|
||||
int has_sha1_file(const unsigned char *sha1)
|
||||
{
|
||||
struct pack_entry e;
|
||||
|
||||
if (find_pack_entry(sha1, &e, NULL))
|
||||
if (find_pack_entry(sha1, &e))
|
||||
return 1;
|
||||
return has_loose_object(sha1);
|
||||
}
|
||||
|
||||
@@ -38,4 +38,7 @@ full-svn-test:
|
||||
$(MAKE) $(TSVN) GIT_SVN_NO_OPTIMIZE_COMMITS=1 LC_ALL=C
|
||||
$(MAKE) $(TSVN) GIT_SVN_NO_OPTIMIZE_COMMITS=0 LC_ALL=en_US.UTF-8
|
||||
|
||||
.PHONY: pre-clean $(T) aggregate-results clean
|
||||
valgrind:
|
||||
GIT_TEST_OPTS=--valgrind $(MAKE)
|
||||
|
||||
.PHONY: pre-clean $(T) aggregate-results clean valgrind
|
||||
|
||||
18
t/README
18
t/README
@@ -39,7 +39,8 @@ this:
|
||||
* passed all 3 test(s)
|
||||
|
||||
You can pass --verbose (or -v), --debug (or -d), and --immediate
|
||||
(or -i) command line argument to the test.
|
||||
(or -i) command line argument to the test, or by setting GIT_TEST_OPTS
|
||||
appropriately before running "make".
|
||||
|
||||
--verbose::
|
||||
This makes the test more verbose. Specifically, the
|
||||
@@ -58,6 +59,21 @@ You can pass --verbose (or -v), --debug (or -d), and --immediate
|
||||
This causes additional long-running tests to be run (where
|
||||
available), for more exhaustive testing.
|
||||
|
||||
--valgrind::
|
||||
Execute all Git binaries with valgrind and exit with status
|
||||
126 on errors (just like regular tests, this will only stop
|
||||
the test script when running under -i). Valgrind errors
|
||||
go to stderr, so you might want to pass the -v option, too.
|
||||
|
||||
Since it makes no sense to run the tests with --valgrind and
|
||||
not see any output, this option implies --verbose. For
|
||||
convenience, it also implies --tee.
|
||||
|
||||
--tee::
|
||||
In addition to printing the test output to the terminal,
|
||||
write it to files named 't/test-results/$TEST_NAME.out'.
|
||||
As the names depend on the tests' file names, it is safe to
|
||||
run the tests with this option in parallel.
|
||||
|
||||
Skipping Tests
|
||||
--------------
|
||||
|
||||
@@ -4,6 +4,9 @@ DocumentRoot www
|
||||
LogFormat "%h %l %u %t \"%r\" %>s %b" common
|
||||
CustomLog access.log common
|
||||
ErrorLog error.log
|
||||
<IfModule !mod_log_config.c>
|
||||
LoadModule log_config_module modules/mod_log_config.so
|
||||
</IfModule>
|
||||
|
||||
<IfDefine Darwin>
|
||||
LoadModule log_config_module modules/mod_log_config.so
|
||||
|
||||
@@ -336,10 +336,10 @@ test_expect_success 'get bool variable with empty value' \
|
||||
'git config --bool emptyvalue.variable > output &&
|
||||
cmp output expect'
|
||||
|
||||
git config > output 2>&1
|
||||
|
||||
test_expect_success 'no arguments, but no crash' \
|
||||
"test $? = 129 && grep usage output"
|
||||
test_expect_success 'no arguments, but no crash' '
|
||||
test_must_fail git config >output 2>&1 &&
|
||||
grep usage output
|
||||
'
|
||||
|
||||
cat > .git/config << EOF
|
||||
[a.b]
|
||||
@@ -373,7 +373,7 @@ EOF
|
||||
test_expect_success 'new variable inserts into proper section' 'cmp .git/config expect'
|
||||
|
||||
test_expect_success 'alternative GIT_CONFIG (non-existing file should fail)' \
|
||||
'git config --file non-existing-config -l; test $? != 0'
|
||||
'test_must_fail git config --file non-existing-config -l'
|
||||
|
||||
cat > other-config << EOF
|
||||
[ein]
|
||||
|
||||
@@ -28,4 +28,71 @@ test_expect_success 'loose objects borrowed from alternate are not missing' '
|
||||
)
|
||||
'
|
||||
|
||||
# Corruption tests follow. Make sure to remove all traces of the
|
||||
# specific corruption you test afterwards, lest a later test trip over
|
||||
# it.
|
||||
|
||||
test_expect_success 'object with bad sha1' '
|
||||
sha=$(echo blob | git hash-object -w --stdin) &&
|
||||
echo $sha &&
|
||||
old=$(echo $sha | sed "s+^..+&/+") &&
|
||||
new=$(dirname $old)/ffffffffffffffffffffffffffffffffffffff &&
|
||||
sha="$(dirname $new)$(basename $new)"
|
||||
mv .git/objects/$old .git/objects/$new &&
|
||||
git update-index --add --cacheinfo 100644 $sha foo &&
|
||||
tree=$(git write-tree) &&
|
||||
cmt=$(echo bogus | git commit-tree $tree) &&
|
||||
git update-ref refs/heads/bogus $cmt &&
|
||||
(git fsck 2>out; true) &&
|
||||
grep "$sha.*corrupt" out &&
|
||||
rm -f .git/objects/$new &&
|
||||
git update-ref -d refs/heads/bogus &&
|
||||
git read-tree -u --reset HEAD
|
||||
'
|
||||
|
||||
test_expect_success 'branch pointing to non-commit' '
|
||||
git rev-parse HEAD^{tree} > .git/refs/heads/invalid &&
|
||||
git fsck 2>out &&
|
||||
grep "not a commit" out &&
|
||||
git update-ref -d refs/heads/invalid
|
||||
'
|
||||
|
||||
cat > invalid-tag <<EOF
|
||||
object ffffffffffffffffffffffffffffffffffffffff
|
||||
type commit
|
||||
tag invalid
|
||||
tagger T A Gger <tagger@example.com> 1234567890 -0000
|
||||
|
||||
This is an invalid tag.
|
||||
EOF
|
||||
|
||||
test_expect_failure 'tag pointing to nonexistent' '
|
||||
tag=$(git hash-object -w --stdin < invalid-tag) &&
|
||||
echo $tag > .git/refs/tags/invalid &&
|
||||
git fsck --tags 2>out &&
|
||||
cat out &&
|
||||
grep "could not load tagged object" out &&
|
||||
rm .git/refs/tags/invalid
|
||||
'
|
||||
|
||||
cat > wrong-tag <<EOF
|
||||
object $(echo blob | git hash-object -w --stdin)
|
||||
type commit
|
||||
tag wrong
|
||||
tagger T A Gger <tagger@example.com> 1234567890 -0000
|
||||
|
||||
This is an invalid tag.
|
||||
EOF
|
||||
|
||||
test_expect_failure 'tag pointing to something else than its type' '
|
||||
tag=$(git hash-object -w --stdin < wrong-tag) &&
|
||||
echo $tag > .git/refs/tags/wrong &&
|
||||
git fsck --tags 2>out &&
|
||||
cat out &&
|
||||
grep "some sane error message" out &&
|
||||
rm .git/refs/tags/wrong
|
||||
'
|
||||
|
||||
|
||||
|
||||
test_done
|
||||
|
||||
@@ -19,6 +19,9 @@ do
|
||||
>$dir/a.$i
|
||||
done
|
||||
done
|
||||
>"#ignore1"
|
||||
>"#ignore2"
|
||||
>"#hidden"
|
||||
|
||||
cat >expect <<EOF
|
||||
a.2
|
||||
@@ -42,6 +45,9 @@ three/a.8
|
||||
EOF
|
||||
|
||||
echo '.gitignore
|
||||
\#ignore1
|
||||
\#ignore2*
|
||||
\#hid*n
|
||||
output
|
||||
expect
|
||||
.gitignore
|
||||
@@ -79,9 +85,10 @@ test_expect_success \
|
||||
>output &&
|
||||
test_cmp expect output'
|
||||
|
||||
cat > excludes-file << EOF
|
||||
cat > excludes-file <<\EOF
|
||||
*.[1-8]
|
||||
e*
|
||||
\#*
|
||||
EOF
|
||||
|
||||
git config core.excludesFile excludes-file
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user