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/mingw into devel
Conflicts: t/t5505-remote.sh test-path-utils.c Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -82,7 +82,6 @@ git-mktag
|
||||
git-mktree
|
||||
git-name-rev
|
||||
git-mv
|
||||
git-notes
|
||||
git-pack-redundant
|
||||
git-pack-objects
|
||||
git-pack-refs
|
||||
|
||||
@@ -45,7 +45,7 @@ Fixes since v1.5.2.1
|
||||
correctly when the branch name had slash in it.
|
||||
|
||||
- The email address of the user specified with user.email
|
||||
configuration was overriden by EMAIL environment variable.
|
||||
configuration was overridden by EMAIL environment variable.
|
||||
|
||||
- The tree parser did not warn about tree entries with
|
||||
nonsense file modes, and assumed they must be blobs.
|
||||
|
||||
@@ -7,7 +7,7 @@ Fixes since v1.6.0.1
|
||||
* Installation on platforms that needs .exe suffix to git-* programs were
|
||||
broken in 1.6.0.1.
|
||||
|
||||
* Installation on filesystems without symbolic links support did nto
|
||||
* Installation on filesystems without symbolic links support did not
|
||||
work well.
|
||||
|
||||
* In-tree documentations and test scripts now use "git foo" form to set a
|
||||
|
||||
@@ -41,11 +41,11 @@ Fixes since v1.6.1
|
||||
work tree upon delete/modify conflict.
|
||||
|
||||
* "git merge -s recursive" didn't leave the index unmerged for entries with
|
||||
rename/delete conflictd.
|
||||
rename/delete conflicts.
|
||||
|
||||
* "git merge -s recursive" clobbered untracked files in the work tree.
|
||||
|
||||
* "git mv -k" with more than one errorneous paths misbehaved.
|
||||
* "git mv -k" with more than one erroneous paths misbehaved.
|
||||
|
||||
* "git read-tree -m -u" hence branch switching incorrectly lost a
|
||||
subdirectory in rare cases.
|
||||
|
||||
@@ -4,8 +4,8 @@ GIT v1.6.1.2 Release Notes
|
||||
Fixes since v1.6.1.1
|
||||
--------------------
|
||||
|
||||
* The logic for rename detectin in internal diff used by commands like
|
||||
"git diff" and "git blame" have been optimized to avoid loading the same
|
||||
* The logic for rename detection in internal diff used by commands like
|
||||
"git diff" and "git blame" has been optimized to avoid loading the same
|
||||
blob repeatedly.
|
||||
|
||||
* We did not allow writing out a blob that is larger than 2GB for no good
|
||||
|
||||
32
Documentation/RelNotes-1.6.1.3.txt
Normal file
32
Documentation/RelNotes-1.6.1.3.txt
Normal file
@@ -0,0 +1,32 @@
|
||||
GIT v1.6.1.3 Release Notes
|
||||
==========================
|
||||
|
||||
Fixes since v1.6.1.2
|
||||
--------------------
|
||||
|
||||
* "git diff --binary | git apply" pipeline did not work well when
|
||||
a binary blob is changed to a symbolic link.
|
||||
|
||||
* Some combinations of -b/-w/--ignore-space-at-eol to "git diff" did
|
||||
not work as expected.
|
||||
|
||||
* "git grep" did not pass the -I (ignore binary) option when
|
||||
calling out an external grep program.
|
||||
|
||||
* "git log" and friends include HEAD to the set of starting points
|
||||
when --all is given. This makes a difference when you are not
|
||||
on any branch.
|
||||
|
||||
* "git mv" to move an untracked file to overwrite a tracked
|
||||
contents misbehaved.
|
||||
|
||||
* "git merge -s octopus" with many potential merge bases did not
|
||||
work correctly.
|
||||
|
||||
* RPM binary package installed the html manpages in a wrong place.
|
||||
|
||||
Also includes minor documentation fixes and updates.
|
||||
|
||||
|
||||
--
|
||||
git shortlog --no-merges v1.6.1.2-33-gc789350..
|
||||
19
Documentation/RelNotes-1.6.1.4.txt
Normal file
19
Documentation/RelNotes-1.6.1.4.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
GIT v1.6.1.4 Release Notes
|
||||
==========================
|
||||
|
||||
Fixes since v1.6.1.3
|
||||
--------------------
|
||||
|
||||
* "git fast-export" produced wrong output with some parents missing from
|
||||
commits, when the history is clock-skewed.
|
||||
|
||||
* "git fast-import" sometimes failed to read back objects it just wrote
|
||||
out and aborted, because it failed to flush stale cached data.
|
||||
|
||||
* "git repack" did not error out when necessary object was missing in the
|
||||
repository.
|
||||
|
||||
Also includes minor documentation fixes and updates.
|
||||
|
||||
--
|
||||
git shortlog --no-merges v1.6.1.3..
|
||||
@@ -1,6 +1,28 @@
|
||||
GIT v1.6.2 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.1
|
||||
--------------------
|
||||
|
||||
@@ -11,7 +33,9 @@ Updates since v1.6.1
|
||||
* gitweb updates, including a new patch view and RSS/Atom feed
|
||||
improvements.
|
||||
|
||||
(portability)
|
||||
* (contrib/emacs) git.el now has commands for checking out a branch,
|
||||
creating a branch, cherry-picking and reverting commits; vc-git.el
|
||||
is not shipped with git anymore (it is part of official Emacs).
|
||||
|
||||
(performance)
|
||||
|
||||
@@ -24,17 +48,36 @@ Updates since v1.6.1
|
||||
|
||||
* @{-1} is a way to refer to the last branch you were on. This is
|
||||
accepted not only where an object name is expected, but anywhere
|
||||
a branch name is expected. E.g. "git branch --track mybranch @{-1}"
|
||||
"git rev-parse --symbolic-full-name @{-1}".
|
||||
a branch name is expected and acts as if you typed the branch name.
|
||||
E.g. "git branch --track mybranch @{-1}", "git merge @{-1}", and
|
||||
"git rev-parse --symbolic-full-name @{-1}" would work as expected.
|
||||
|
||||
* When refs/remotes/origin/HEAD points at a remote tracking branch that
|
||||
has been pruned away, many git operations issued warning when they
|
||||
internally enumerated the refs. We now warn only when you say "origin"
|
||||
to refer to that pruned branch.
|
||||
|
||||
* The location of .mailmap file can be configured, and its file format was
|
||||
enhanced to allow mapping an incorrect e-mail field as well.
|
||||
|
||||
* "git add -p" learned 'g'oto action to jump directly to a hunk.
|
||||
|
||||
* "git add -p" learned to find a hunk with given text with '/'.
|
||||
|
||||
* "git add -p" optionally can be told to work with just the command letter
|
||||
without Enter.
|
||||
|
||||
* when "git am" stops upon a patch that does not apply, it shows the
|
||||
title of the offending patch.
|
||||
|
||||
* "git am --directory=<dir>" and "git am --reject" passes these options
|
||||
to underlying "git apply".
|
||||
|
||||
* "git am" learned --ignore-date option.
|
||||
|
||||
* "git blame" aligns author names better when they are spelled in
|
||||
non US-ASCII encoding.
|
||||
|
||||
* "git clone" now makes its best effort when cloning from an empty
|
||||
repository to set up configuration variables to refer to the remote
|
||||
repository.
|
||||
@@ -48,6 +91,9 @@ Updates since v1.6.1
|
||||
the commit log message it serves via gitcvs.commitmsgannotation
|
||||
configuration.
|
||||
|
||||
* "git cvsserver" learned to handle 'noop' command some CVS clients seem
|
||||
to expect to work.
|
||||
|
||||
* "git diff" learned a new option --inter-hunk-context to coalesce close
|
||||
hunks together and show context between them.
|
||||
|
||||
@@ -56,21 +102,17 @@ Updates since v1.6.1
|
||||
|
||||
* "git diff" learned --patience to run "patience diff" algorithm.
|
||||
|
||||
* Some combinations of -b/-w/--ignore-space-at-eol to "git diff" did
|
||||
not work as expected.
|
||||
|
||||
* "git filter-branch" learned --prune-empty option that discards commits
|
||||
that do not change the contents.
|
||||
|
||||
* "git fsck" now checks loose objects in alternate object stores, instead
|
||||
of misreporting them as missing.
|
||||
|
||||
* "git gc --prune" was resurrected to allow "git gc --no-prune" and
|
||||
giving non-default expiration period e.g. "git gc --prune=now".
|
||||
|
||||
* "git grep -w" and "git grep" for fixed strings have been optimized.
|
||||
|
||||
* "git log" and friends include HEAD to the set of starting points
|
||||
when --all is given. This makes a difference when you are not on
|
||||
any branch.
|
||||
|
||||
* "git ls-tree" learned --full-tree option that shows the path in full
|
||||
regardless of where in the work tree hierarchy the command was started.
|
||||
|
||||
* "git mergetool" learned -y(--no-prompt) option to disable prompting.
|
||||
|
||||
* "git rebase -i" can transplant a history down to root to elsewhere
|
||||
@@ -80,7 +122,10 @@ Updates since v1.6.1
|
||||
"git checkout" switches branches, taking the local changes while
|
||||
switching to another commit.
|
||||
|
||||
(internal)
|
||||
* "git submodule update" learned --no-fetch option.
|
||||
|
||||
* "git tag" learned --contains that works the same way as the same option
|
||||
from "git branch".
|
||||
|
||||
|
||||
Fixes since v1.6.1
|
||||
@@ -89,18 +134,31 @@ Fixes since v1.6.1
|
||||
All of the fixes in v1.6.1.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.1.X series.
|
||||
|
||||
* "git-add sub/file" when sub is a submodule incorrectly added the path to
|
||||
the superproject.
|
||||
|
||||
* git-bundle did not exclude annotated tags even when a range given from the
|
||||
command line wanted to.
|
||||
* "git bundle" did not exclude annotated tags even when a range given
|
||||
from the command line wanted to.
|
||||
|
||||
* "git filter-branch" unnecessarily refused to work when you had
|
||||
checked out a different commit from what is recorded in the superproject
|
||||
index in a submodule.
|
||||
|
||||
* "git filter-branch" incorrectly tried to update a nonexistent work tree
|
||||
at the end when it is run in a bare repository.
|
||||
|
||||
* "git gc" did not work if your repository was created with an ancient git
|
||||
and never had any pack files in it before.
|
||||
|
||||
* "git mergetool" used to ignore autocrlf and other attributes
|
||||
based content rewriting.
|
||||
|
||||
* branch switching and merges had a silly bug that did not validate
|
||||
the correct directory when making sure an existing subdirectory is
|
||||
clean.
|
||||
|
||||
--
|
||||
exec >/var/tmp/1
|
||||
O=v1.6.1.2-252-g8c95d3c
|
||||
echo O=$(git describe master)
|
||||
git shortlog --no-merges $O..master ^maint
|
||||
* "git -p cmd" when cmd is not a built-in one left the display in funny state
|
||||
when killed in the middle.
|
||||
|
||||
@@ -376,9 +376,36 @@ Thunderbird
|
||||
|
||||
(A Large Angry SCM)
|
||||
|
||||
By default, Thunderbird will both wrap emails as well as flag them as
|
||||
being 'format=flowed', both of which will make the resulting email unusable
|
||||
by git.
|
||||
|
||||
Here are some hints on how to successfully submit patches inline using
|
||||
Thunderbird.
|
||||
|
||||
There are two different approaches. One approach is to configure
|
||||
Thunderbird to not mangle patches. The second approach is to use
|
||||
an external editor to keep Thunderbird from mangling the patches.
|
||||
|
||||
Approach #1 (configuration):
|
||||
|
||||
This recipe is current as of Thunderbird 2.0.0.19. Three steps:
|
||||
1. Configure your mail server composition as plain text
|
||||
Edit...Account Settings...Composition & Addressing,
|
||||
uncheck 'Compose Messages in HTML'.
|
||||
2. Configure your general composition window to not wrap
|
||||
Edit..Preferences..Composition, wrap plain text messages at 0
|
||||
3. Disable the use of format=flowed
|
||||
Edit..Preferences..Advanced..Config Editor. Search for:
|
||||
mailnews.send_plaintext_flowed
|
||||
toggle it to make sure it is set to 'false'.
|
||||
|
||||
After that is done, you should be able to compose email as you
|
||||
otherwise would (cut + paste, git-format-patch | git-imap-send, etc),
|
||||
and the patches should not be mangled.
|
||||
|
||||
Approach #2 (external editor):
|
||||
|
||||
This recipe appears to work with the current [*1*] Thunderbird from Suse.
|
||||
|
||||
The following Thunderbird extensions are needed:
|
||||
|
||||
@@ -41,6 +41,13 @@ of lines before or after the line given by <start>.
|
||||
-S <revs-file>::
|
||||
Use revs from revs-file instead of calling linkgit:git-rev-list[1].
|
||||
|
||||
--reverse::
|
||||
Walk history forward instead of backward. Instead of showing
|
||||
the revision in which a line appeared, this shows the last
|
||||
revision in which a line has existed. This requires a range of
|
||||
revision like START..END where the path to blame exists in
|
||||
START.
|
||||
|
||||
-p::
|
||||
--porcelain::
|
||||
Show in a format designed for machine consumption.
|
||||
@@ -67,7 +74,7 @@ of lines before or after the line given by <start>.
|
||||
Detect moving lines in the file as well. When a commit
|
||||
moves a block of lines in a file (e.g. the original file
|
||||
has A and then B, and the commit changes it to B and
|
||||
then A), traditional 'blame' algorithm typically blames
|
||||
then A), the traditional 'blame' algorithm typically blames
|
||||
the lines that were moved up (i.e. B) to the parent and
|
||||
assigns blame to the lines that were moved down (i.e. A)
|
||||
to the child commit. With this option, both groups of lines
|
||||
@@ -83,8 +90,8 @@ commit.
|
||||
files that were modified in the same commit. This is
|
||||
useful when you reorganize your program and move code
|
||||
around across files. When this option is given twice,
|
||||
the command looks for copies from all other files in the
|
||||
parent for the commit that creates the file in addition.
|
||||
the command additionally looks for copies from all other
|
||||
files in the parent for the commit that creates the file.
|
||||
+
|
||||
<num> is optional but it is the lower bound on the number of
|
||||
alphanumeric characters that git must detect as moving
|
||||
|
||||
@@ -422,19 +422,6 @@ relatively high IO latencies. With this set to 'true', git will do the
|
||||
index comparison to the filesystem data in parallel, allowing
|
||||
overlapping IO's.
|
||||
|
||||
core.notesRef::
|
||||
When showing commit messages, also show notes which are stored in
|
||||
the given ref. This ref is expected to contain files named
|
||||
after the full SHA-1 of the commit they annotate.
|
||||
+
|
||||
If such a file exists in the given ref, the referenced blob is read, and
|
||||
appended to the commit message, separated by a "Notes:" line. If the
|
||||
given ref itself does not exist, it is not an error, but means that no
|
||||
notes should be printed.
|
||||
+
|
||||
This setting defaults to "refs/notes/commits", and can be overridden by
|
||||
the `GIT_NOTES_REF` environment variable.
|
||||
|
||||
alias.*::
|
||||
Command aliases for the linkgit:git[1] command wrapper - e.g.
|
||||
after defining "alias.last = cat-file commit HEAD", the invocation
|
||||
@@ -569,8 +556,8 @@ color.interactive::
|
||||
|
||||
color.interactive.<slot>::
|
||||
Use customized color for 'git-add --interactive'
|
||||
output. `<slot>` may be `prompt`, `header`, or `help`, for
|
||||
three distinct types of normal output from interactive
|
||||
output. `<slot>` may be `prompt`, `header`, `help` or `error`, for
|
||||
four distinct types of normal output from interactive
|
||||
programs. The values of these variables may be specified as
|
||||
in color.branch.<slot>.
|
||||
|
||||
@@ -1013,6 +1000,13 @@ instaweb.port::
|
||||
The port number to bind the gitweb httpd to. See
|
||||
linkgit:git-instaweb[1].
|
||||
|
||||
interactive.singlekey::
|
||||
In interactive programs, allow the user to provide one-letter
|
||||
input with a single key (i.e., without hitting enter).
|
||||
Currently this is used only by the `\--patch` mode of
|
||||
linkgit:git-add[1]. Note that this setting is silently
|
||||
ignored if portable keystroke input is not available.
|
||||
|
||||
log.date::
|
||||
Set default date-time mode for the log command. Setting log.date
|
||||
value is similar to using 'git-log'\'s --date option. The value is one of the
|
||||
@@ -1025,6 +1019,14 @@ log.showroot::
|
||||
Tools like linkgit:git-log[1] or linkgit:git-whatchanged[1], which
|
||||
normally hide the root commit will now show it. True by default.
|
||||
|
||||
mailmap.file::
|
||||
The location of an augmenting mailmap file. The default
|
||||
mailmap, located in the root of the repository, is loaded
|
||||
first, then the mailmap file pointed to by this variable.
|
||||
The location of the mailmap file may be in a repository
|
||||
subdirectory, or somewhere outside of the repository itself.
|
||||
See linkgit:git-shortlog[1] and linkgit:git-blame[1].
|
||||
|
||||
man.viewer::
|
||||
Specify the programs that may be used to display help in the
|
||||
'man' format. See linkgit:git-help[1].
|
||||
|
||||
@@ -136,7 +136,7 @@ $ git add Documentation/\\*.txt
|
||||
------------
|
||||
+
|
||||
Note that the asterisk `\*` is quoted from the shell in this
|
||||
example; this lets the command to include the files from
|
||||
example; this lets the command include the files from
|
||||
subdirectories of `Documentation/` directory.
|
||||
|
||||
* Considers adding content from all git-*.sh scripts:
|
||||
@@ -145,7 +145,7 @@ subdirectories of `Documentation/` directory.
|
||||
$ git add git-*.sh
|
||||
------------
|
||||
+
|
||||
Because this example lets shell expand the asterisk (i.e. you are
|
||||
Because this example lets the shell expand the asterisk (i.e. you are
|
||||
listing the files explicitly), it does not consider
|
||||
`subdir/git-foo.sh`.
|
||||
|
||||
@@ -198,8 +198,8 @@ one deletion).
|
||||
|
||||
update::
|
||||
|
||||
This shows the status information and gives prompt
|
||||
"Update>>". When the prompt ends with double '>>', you can
|
||||
This shows the status information and issues an "Update>>"
|
||||
prompt. When the prompt ends with double '>>', you can
|
||||
make more than one selection, concatenated with whitespace or
|
||||
comma. Also you can say ranges. E.g. "2-5 7,9" to choose
|
||||
2,3,4,5,7,9 from the list. If the second number in a range is
|
||||
@@ -238,8 +238,8 @@ add untracked::
|
||||
|
||||
patch::
|
||||
|
||||
This lets you choose one path out of 'status' like selection.
|
||||
After choosing the path, it presents diff between the index
|
||||
This lets you choose one path out of a 'status' like selection.
|
||||
After choosing the path, it presents the diff between the index
|
||||
and the working tree file and asks you if you want to stage
|
||||
the change of each hunk. You can say:
|
||||
|
||||
|
||||
@@ -27,8 +27,8 @@ OPTIONS
|
||||
-------
|
||||
<mbox>|<Maildir>...::
|
||||
The list of mailbox files to read patches from. If you do not
|
||||
supply this argument, reads from the standard input. If you supply
|
||||
directories, they'll be treated as Maildirs.
|
||||
supply this argument, the command reads from the standard input.
|
||||
If you supply directories, they will be treated as Maildirs.
|
||||
|
||||
-s::
|
||||
--signoff::
|
||||
@@ -48,7 +48,7 @@ OPTIONS
|
||||
preferred encoding if it is not UTF-8).
|
||||
+
|
||||
This was optional in prior versions of git, but now it is the
|
||||
default. You could use `--no-utf8` to override this.
|
||||
default. You can use `--no-utf8` to override this.
|
||||
|
||||
--no-utf8::
|
||||
Pass `-n` flag to 'git-mailinfo' (see
|
||||
@@ -57,8 +57,8 @@ default. You could use `--no-utf8` to override this.
|
||||
-3::
|
||||
--3way::
|
||||
When the patch does not apply cleanly, fall back on
|
||||
3-way merge, if the patch records the identity of blobs
|
||||
it is supposed to apply to, and we have those blobs
|
||||
3-way merge if the patch records the identity of blobs
|
||||
it is supposed to apply to and we have those blobs
|
||||
available locally.
|
||||
|
||||
--whitespace=<option>::
|
||||
@@ -121,18 +121,18 @@ the commit, after stripping common prefix "[PATCH <anything>]".
|
||||
It is supposed to describe what the commit is about concisely as
|
||||
a one line text.
|
||||
|
||||
The body of the message (iow, after a blank line that terminates
|
||||
RFC2822 headers) can begin with "Subject: " and "From: " lines
|
||||
that are different from those of the mail header, to override
|
||||
the values of these fields.
|
||||
The body of the message (the rest of the message after the blank line
|
||||
that terminates the RFC2822 headers) can begin with "Subject: " and
|
||||
"From: " lines that are different from those of the mail header,
|
||||
to override the values of these fields.
|
||||
|
||||
The commit message is formed by the title taken from the
|
||||
"Subject: ", a blank line and the body of the message up to
|
||||
where the patch begins. Excess whitespaces at the end of the
|
||||
where the patch begins. Excess whitespace characters at the end of the
|
||||
lines are automatically stripped.
|
||||
|
||||
The patch is expected to be inline, directly following the
|
||||
message. Any line that is of form:
|
||||
message. Any line that is of the form:
|
||||
|
||||
* three-dashes and end-of-line, or
|
||||
* a line that begins with "diff -", or
|
||||
@@ -141,18 +141,18 @@ message. Any line that is of form:
|
||||
is taken as the beginning of a patch, and the commit log message
|
||||
is terminated before the first occurrence of such a line.
|
||||
|
||||
When initially invoking it, you give it names of the mailboxes
|
||||
to crunch. Upon seeing the first patch that does not apply, it
|
||||
aborts in the middle,. You can recover from this in one of two ways:
|
||||
When initially invoking it, you give it the names of the mailboxes
|
||||
to process. Upon seeing the first patch that does not apply, it
|
||||
aborts in the middle. You can recover from this in one of two ways:
|
||||
|
||||
. skip the current patch by re-running the command with '--skip'
|
||||
. skip the current patch by re-running the command with the '--skip'
|
||||
option.
|
||||
|
||||
. hand resolve the conflict in the working directory, and update
|
||||
the index file to bring it in a state that the patch should
|
||||
have produced. Then run the command with '--resolved' option.
|
||||
the index file to bring it into a state that the patch should
|
||||
have produced. Then run the command with the '--resolved' option.
|
||||
|
||||
The command refuses to process new mailboxes while `.git/rebase-apply`
|
||||
The command refuses to process new mailboxes while the `.git/rebase-apply`
|
||||
directory exists, so if you decide to start over from scratch,
|
||||
run `rm -f -r .git/rebase-apply` before running the command with mailbox
|
||||
names.
|
||||
|
||||
@@ -3,7 +3,7 @@ git-annotate(1)
|
||||
|
||||
NAME
|
||||
----
|
||||
git-annotate - Annotate file lines with commit info
|
||||
git-annotate - Annotate file lines with commit information
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
@@ -12,11 +12,11 @@ SYNOPSIS
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Annotates each line in the given file with information from the commit
|
||||
which introduced the line. Optionally annotate from a given revision.
|
||||
which introduced the line. Optionally annotates from a given revision.
|
||||
|
||||
The only difference between this command and linkgit:git-blame[1] is that
|
||||
they use slightly different output formats, and this command exists only
|
||||
for backward compatibility to support existing scripts, and provide more
|
||||
for backward compatibility to support existing scripts, and provide a more
|
||||
familiar command name for people coming from other SCM systems.
|
||||
|
||||
OPTIONS
|
||||
|
||||
@@ -25,7 +25,7 @@ and a work tree.
|
||||
OPTIONS
|
||||
-------
|
||||
<patch>...::
|
||||
The files to read patch from. '-' can be used to read
|
||||
The files to read the patch from. '-' can be used to read
|
||||
from the standard input.
|
||||
|
||||
--stat::
|
||||
@@ -33,8 +33,8 @@ OPTIONS
|
||||
input. Turns off "apply".
|
||||
|
||||
--numstat::
|
||||
Similar to \--stat, but shows number of added and
|
||||
deleted lines in decimal notation and pathname without
|
||||
Similar to \--stat, but shows the number of added and
|
||||
deleted lines in decimal notation and the pathname without
|
||||
abbreviation, to make it more machine friendly. For
|
||||
binary files, outputs two `-` instead of saying
|
||||
`0 0`. Turns off "apply".
|
||||
@@ -60,15 +60,15 @@ OPTIONS
|
||||
causes the index file to be updated.
|
||||
|
||||
--cached::
|
||||
Apply a patch without touching the working tree. Instead, take the
|
||||
cached data, apply the patch, and store the result in the index,
|
||||
Apply a patch without touching the working tree. Instead take the
|
||||
cached data, apply the patch, and store the result in the index
|
||||
without using the working tree. This implies '--index'.
|
||||
|
||||
--build-fake-ancestor=<file>::
|
||||
Newer 'git-diff' output has embedded 'index information'
|
||||
for each blob to help identify the original version that
|
||||
the patch applies to. When this flag is given, and if
|
||||
the original versions of the blobs is available locally,
|
||||
the original versions of the blobs are available locally,
|
||||
builds a temporary index containing those blobs.
|
||||
+
|
||||
When a pure mode change is encountered (which has no index information),
|
||||
@@ -109,13 +109,13 @@ the information is read from the current index instead.
|
||||
applying a diff generated with --unified=0. To bypass these
|
||||
checks use '--unidiff-zero'.
|
||||
+
|
||||
Note, for the reasons stated above usage of context-free patches are
|
||||
Note, for the reasons stated above usage of context-free patches is
|
||||
discouraged.
|
||||
|
||||
--apply::
|
||||
If you use any of the options marked "Turns off
|
||||
'apply'" above, 'git-apply' reads and outputs the
|
||||
information you asked without actually applying the
|
||||
requested information without actually applying the
|
||||
patch. Give this flag after those flags to also apply
|
||||
the patch.
|
||||
|
||||
@@ -124,7 +124,7 @@ discouraged.
|
||||
patch. This can be used to extract the common part between
|
||||
two files by first running 'diff' on them and applying
|
||||
the result with this option, which would apply the
|
||||
deletion part but not addition part.
|
||||
deletion part but not the addition part.
|
||||
|
||||
--allow-binary-replacement::
|
||||
--binary::
|
||||
@@ -159,10 +159,10 @@ on the command line, and ignored if there is any include pattern.
|
||||
considered whitespace errors.
|
||||
+
|
||||
By default, the command outputs warning messages but applies the patch.
|
||||
When `git-apply is used for statistics and not applying a
|
||||
When `git-apply` is used for statistics and not applying a
|
||||
patch, it defaults to `nowarn`.
|
||||
+
|
||||
You can use different `<action>` to control this
|
||||
You can use different `<action>` values to control this
|
||||
behavior:
|
||||
+
|
||||
* `nowarn` turns off the trailing whitespace warning.
|
||||
@@ -170,7 +170,7 @@ behavior:
|
||||
patch as-is (default).
|
||||
* `fix` outputs warnings for a few such errors, and applies the
|
||||
patch after fixing them (`strip` is a synonym --- the tool
|
||||
used to consider only trailing whitespaces as errors, and the
|
||||
used to consider only trailing whitespace characters as errors, and the
|
||||
fix involved 'stripping' them, but modern gits do more).
|
||||
* `error` outputs warnings for a few such errors, and refuses
|
||||
to apply the patch.
|
||||
@@ -195,7 +195,7 @@ behavior:
|
||||
adjusting the hunk headers appropriately).
|
||||
|
||||
--directory=<root>::
|
||||
Prepend <root> to all filenames. If a "-p" argument was passed, too,
|
||||
Prepend <root> to all filenames. If a "-p" argument was also passed,
|
||||
it is applied before prepending the new root.
|
||||
+
|
||||
For example, a patch that talks about updating `a/git-gui.sh` to `b/git-gui.sh`
|
||||
@@ -221,7 +221,7 @@ ignored, i.e., they are not required to be up-to-date or clean and they
|
||||
are not updated.
|
||||
|
||||
If --index is not specified, then the submodule commits in the patch
|
||||
are ignored and only the absence of presence of the corresponding
|
||||
are ignored and only the absence or presence of the corresponding
|
||||
subdirectory is checked and (if possible) updated.
|
||||
|
||||
Author
|
||||
|
||||
@@ -88,6 +88,18 @@ tar.umask::
|
||||
archiving user's umask will be used instead. See umask(2) for
|
||||
details.
|
||||
|
||||
ATTRIBUTES
|
||||
----------
|
||||
|
||||
export-ignore::
|
||||
Files and directories with the attribute export-ignore won't be
|
||||
added to archive files. See linkgit:gitattributes[5] for details.
|
||||
|
||||
export-subst::
|
||||
If the attribute export-subst is set for a file then git will
|
||||
expand several placeholders when adding this file to an archive.
|
||||
See linkgit:gitattributes[5] for details.
|
||||
|
||||
EXAMPLES
|
||||
--------
|
||||
git archive --format=tar --prefix=junk/ HEAD | (cd /var/tmp/ && tar xf -)::
|
||||
@@ -110,6 +122,11 @@ git archive --format=zip --prefix=git-docs/ HEAD:Documentation/ > git-1.4.0-docs
|
||||
Put everything in the current head's Documentation/ directory
|
||||
into 'git-1.4.0-docs.zip', with the prefix 'git-docs/'.
|
||||
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
linkgit:gitattributes[5]
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Franck Bui-Huu and Rene Scharfe.
|
||||
|
||||
@@ -10,7 +10,7 @@ SYNOPSIS
|
||||
[verse]
|
||||
'git blame' [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-p] [-w] [--incremental] [-L n,m]
|
||||
[-S <revs-file>] [-M] [-C] [-C] [--since=<date>]
|
||||
[<rev> | --contents <file>] [--] <file>
|
||||
[<rev> | --contents <file> | --reverse <rev>] [--] <file>
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@@ -184,6 +184,12 @@ there is ever added information (like the commit encoding or extended
|
||||
commit commentary), a blame viewer won't ever care.
|
||||
|
||||
|
||||
MAPPING AUTHORS
|
||||
---------------
|
||||
|
||||
include::mailmap.txt[]
|
||||
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
linkgit:git-annotate[1]
|
||||
|
||||
@@ -107,17 +107,17 @@ incremental bundle,
|
||||
|
||||
----------------
|
||||
machineA$ cd R1
|
||||
machineA$ git bundle create file.bdl master
|
||||
machineA$ git bundle create file.bundle master
|
||||
machineA$ git tag -f lastR2bundle master
|
||||
----------------
|
||||
|
||||
Then you sneakernet file.bdl to the target machine B. Because you don't
|
||||
Then you sneakernet file.bundle to the target machine B. Because you don't
|
||||
have to have any object to extract objects from such a bundle, not only
|
||||
you can fetch/pull from a bundle, you can clone from it as if it was a
|
||||
remote repository.
|
||||
|
||||
----------------
|
||||
machineB$ git clone /home/me/tmp/file.bdl R2
|
||||
machineB$ git clone /home/me/tmp/file.bundle R2
|
||||
----------------
|
||||
|
||||
This will define a remote called "origin" in the resulting repository that
|
||||
@@ -126,12 +126,12 @@ have an entry like this:
|
||||
|
||||
------------------------
|
||||
[remote "origin"]
|
||||
url = /home/me/tmp/file.bdl
|
||||
url = /home/me/tmp/file.bundle
|
||||
fetch = refs/heads/*:refs/remotes/origin/*
|
||||
------------------------
|
||||
|
||||
You can fetch/pull to update the resulting mine.git repository after
|
||||
replacing the bundle you store at /home/me/tmp/file.bdl with incremental
|
||||
replacing the bundle you store at /home/me/tmp/file.bundle with incremental
|
||||
updates from here on.
|
||||
|
||||
After working more in the original repository, you can create an
|
||||
@@ -139,11 +139,11 @@ incremental bundle to update the other:
|
||||
|
||||
----------------
|
||||
machineA$ cd R1
|
||||
machineA$ git bundle create file.bdl lastR2bundle..master
|
||||
machineA$ git bundle create file.bundle lastR2bundle..master
|
||||
machineA$ git tag -f lastR2bundle master
|
||||
----------------
|
||||
|
||||
and sneakernet it to the other machine to replace /home/me/tmp/file.bdl,
|
||||
and sneakernet it to the other machine to replace /home/me/tmp/file.bundle,
|
||||
and pull from it.
|
||||
|
||||
----------------
|
||||
|
||||
@@ -212,6 +212,11 @@ git filter-branch --index-filter 'git rm --cached 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:
|
||||
|
||||
@@ -334,6 +339,47 @@ git filter-branch --index-filter \
|
||||
---------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
Checklist for Shrinking a Repository
|
||||
------------------------------------
|
||||
|
||||
git-filter-branch is often used to get rid of a subset of files,
|
||||
usually with some combination of `\--index-filter` and
|
||||
`\--subdirectory-filter`. People expect the resulting repository to
|
||||
be smaller than the original, but you need a few more steps to
|
||||
actually make it smaller, because git tries hard not to lose your
|
||||
objects until you tell it to. First make sure that:
|
||||
|
||||
* You really removed all variants of a filename, if a blob was moved
|
||||
over its lifetime. `git log \--name-only \--follow \--all \--
|
||||
filename` can help you find renames.
|
||||
|
||||
* You really filtered all refs: use `\--tag-name-filter cat \--
|
||||
\--all` when calling git-filter-branch.
|
||||
|
||||
Then there are two ways to get a smaller repository. A safer way is
|
||||
to clone, that keeps your original intact.
|
||||
|
||||
* Clone it with `git clone +++file:///path/to/repo+++`. The clone
|
||||
will not have the removed objects. See linkgit:git-clone[1]. (Note
|
||||
that cloning with a plain path just hardlinks everything!)
|
||||
|
||||
If you really don't want to clone it, for whatever reasons, check the
|
||||
following points instead (in this order). This is a very destructive
|
||||
approach, so *make a backup* or go back to cloning it. You have been
|
||||
warned.
|
||||
|
||||
* Remove the original refs backed up by git-filter-branch: say `git
|
||||
for-each-ref \--format="%(refname)" refs/original/ | xargs -n 1 git
|
||||
update-ref -d`.
|
||||
|
||||
* Expire all reflogs with `git reflog expire \--expire=now \--all`.
|
||||
|
||||
* Garbage collect all unreferenced objects with `git gc \--prune=now`
|
||||
(or if your git-gc is not new enough to support arguments to
|
||||
`\--prune`, use `git repack -ad; git prune` instead).
|
||||
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Petr "Pasky" Baudis <pasky@suse.cz>,
|
||||
|
||||
@@ -8,7 +8,7 @@ git-gc - Cleanup unnecessary files and optimize the local repository
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git gc' [--aggressive] [--auto] [--quiet]
|
||||
'git gc' [--aggressive] [--auto] [--quiet] [--prune=<date> | --no-prune]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@@ -59,6 +59,14 @@ are consolidated into a single pack by using the `-A` option of
|
||||
'git-repack'. Setting `gc.autopacklimit` to 0 disables
|
||||
automatic consolidation of packs.
|
||||
|
||||
--prune=<date>::
|
||||
Prune loose objects older than date (default is 2 weeks ago,
|
||||
overrideable by the config variable `gc.pruneExpire`). This
|
||||
option is on by default.
|
||||
|
||||
--no-prune::
|
||||
Do not prune any loose objects.
|
||||
|
||||
--quiet::
|
||||
Suppress all progress reports.
|
||||
|
||||
|
||||
@@ -98,6 +98,20 @@ Using direct mode with SSL:
|
||||
..........................
|
||||
|
||||
|
||||
CAUTION
|
||||
-------
|
||||
It is still your responsibility to make sure that the email message
|
||||
sent by your email program meets the standards of your project.
|
||||
Many projects do not like patches to be attached. Some mail
|
||||
agents will transform patches (e.g. wrap lines, send them as
|
||||
format=flowed) in ways that make them fail. You will get angry
|
||||
flames ridiculing you if you don't check this.
|
||||
|
||||
Thunderbird in particular is known to be problematic. Thunderbird
|
||||
users may wish to visit this web page for more information:
|
||||
http://kb.mozillazine.org/Plain_text_e-mail_-_Thunderbird#Completely_plain_email
|
||||
|
||||
|
||||
BUGS
|
||||
----
|
||||
Doesn't handle lines starting with "From " in the message body.
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
git-notes(1)
|
||||
============
|
||||
|
||||
NAME
|
||||
----
|
||||
git-notes - Add/inspect commit notes
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git-notes' (edit | show) [commit]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
This command allows you to add notes to commit messages, without
|
||||
changing the commit. To discern these notes from the message stored
|
||||
in the commit object, the notes are indented like the message, after
|
||||
an unindented line saying "Notes:".
|
||||
|
||||
To disable commit notes, you have to set the config variable
|
||||
core.notesRef to the empty string. Alternatively, you can set it
|
||||
to a different ref, something like "refs/notes/bugzilla". This setting
|
||||
can be overridden by the environment variable "GIT_NOTES_REF".
|
||||
|
||||
|
||||
SUBCOMMANDS
|
||||
-----------
|
||||
|
||||
edit::
|
||||
Edit the notes for a given commit (defaults to HEAD).
|
||||
|
||||
show::
|
||||
Show the notes for a given commit (defaults to HEAD).
|
||||
|
||||
|
||||
Author
|
||||
------
|
||||
Written by Johannes Schindelin <johannes.schindelin@gmx.de>
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
Documentation by Johannes Schindelin
|
||||
|
||||
GIT
|
||||
---
|
||||
Part of the gitlink:git[7] suite
|
||||
@@ -9,7 +9,7 @@ git-push - Update remote refs along with associated objects
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git push' [--all | --mirror] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>]
|
||||
'git push' [--all | --mirror | --tags] [--dry-run] [--receive-pack=<git-receive-pack>]
|
||||
[--repo=<repository>] [-f | --force] [-v | --verbose]
|
||||
[<repository> <refspec>...]
|
||||
|
||||
@@ -48,17 +48,19 @@ push. Arbitrary expressions cannot be used here, an actual ref must
|
||||
be named. If `:`<dst> is omitted, the same ref as <src> will be
|
||||
updated.
|
||||
+
|
||||
The object referenced by <src> is used to fast forward the ref <dst>
|
||||
on the remote side. If the optional leading plus `{plus}` is used, the
|
||||
remote ref is updated even if it does not result in a fast forward
|
||||
update.
|
||||
The object referenced by <src> is used to update the <dst> reference
|
||||
on the remote side, but by default this is only allowed if the
|
||||
update can fast forward <dst>. By having the optional leading `{plus}`,
|
||||
you can tell git to update the <dst> ref even when the update is not a
|
||||
fast forward. This does *not* attempt to merge <src> into <dst>. See
|
||||
EXAMPLES below for details.
|
||||
+
|
||||
`tag <tag>` means the same as `refs/tags/<tag>:refs/tags/<tag>`.
|
||||
+
|
||||
Pushing an empty <src> allows you to delete the <dst> ref from
|
||||
the remote repository.
|
||||
+
|
||||
The special refspec `:` (or `+:` to allow non-fast forward updates)
|
||||
The special refspec `:` (or `{plus}:` to allow non-fast forward updates)
|
||||
directs git to push "matching" branches: for every branch that exists on
|
||||
the local side, the remote side is updated if a branch of the same name
|
||||
already exists on the remote side. This is the default operation mode
|
||||
@@ -218,6 +220,30 @@ git push origin :experimental::
|
||||
Find a ref that matches `experimental` in the `origin` repository
|
||||
(e.g. `refs/heads/experimental`), and delete it.
|
||||
|
||||
git push origin {plus}dev:master::
|
||||
Update the origin repository's master branch with the dev branch,
|
||||
allowing non-fast forward updates. *This can leave unreferenced
|
||||
commits dangling in the origin repository.* Consider the
|
||||
following situation, where a fast forward is not possible:
|
||||
+
|
||||
----
|
||||
o---o---o---A---B origin/master
|
||||
\
|
||||
X---Y---Z dev
|
||||
----
|
||||
+
|
||||
The above command would change the origin repository to
|
||||
+
|
||||
----
|
||||
A---B (unnamed branch)
|
||||
/
|
||||
o---o---o---X---Y---Z master
|
||||
----
|
||||
+
|
||||
Commits A and B would no longer belong to a branch with a symbolic name,
|
||||
and so would be unreachable. As such, these commits would be removed by
|
||||
a `git gc` command on the origin repository.
|
||||
|
||||
|
||||
Author
|
||||
------
|
||||
|
||||
@@ -243,9 +243,10 @@ OPTIONS
|
||||
context exist they all must match. By default no context is
|
||||
ever ignored.
|
||||
|
||||
--whitespace=<nowarn|warn|error|error-all|strip>::
|
||||
--whitespace=<option>::
|
||||
This flag is passed to the 'git-apply' program
|
||||
(see linkgit:git-apply[1]) that applies the patch.
|
||||
Incompatible with the --interactive option.
|
||||
|
||||
-i::
|
||||
--interactive::
|
||||
|
||||
@@ -19,6 +19,19 @@ The header of the email is configurable by command line options. If not
|
||||
specified on the command line, the user will be prompted with a ReadLine
|
||||
enabled interface to provide the necessary information.
|
||||
|
||||
There are two formats accepted for patch files:
|
||||
|
||||
1. mbox format files
|
||||
+
|
||||
This is what linkgit:git-format-patch[1] generates. Most headers and MIME
|
||||
formatting are ignored.
|
||||
|
||||
2. The original format used by Greg Kroah-Hartman's 'send_lots_of_email.pl'
|
||||
script
|
||||
+
|
||||
This format expects the first line of the file to contain the "Cc:" value
|
||||
and the "Subject:" of the message as the second line.
|
||||
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
|
||||
@@ -45,45 +45,16 @@ OPTIONS
|
||||
and subsequent lines are indented by `indent2` spaces. `width`,
|
||||
`indent1`, and `indent2` default to 76, 6 and 9 respectively.
|
||||
|
||||
FILES
|
||||
-----
|
||||
|
||||
If a file `.mailmap` exists at the toplevel of the repository,
|
||||
it is used to map an author email address to a canonical real name. This
|
||||
can be used to coalesce together commits by the same person where their
|
||||
name was spelled differently (whether with the same email address or
|
||||
not).
|
||||
MAPPING AUTHORS
|
||||
---------------
|
||||
|
||||
Each line in the file consists, in this order, of the canonical real name
|
||||
of an author, whitespace, and an email address (enclosed by '<' and '>')
|
||||
to map to the name. Use hash '#' for comments, either on their own line,
|
||||
or after the email address.
|
||||
The `.mailmap` feature is used to coalesce together commits by the same
|
||||
person in the shortlog, where their name and/or email address was
|
||||
spelled differently.
|
||||
|
||||
A canonical name may appear in more than one line, associated with
|
||||
different email addresses, but it doesn't make sense for a given address
|
||||
to appear more than once (if that happens, a later line overrides the
|
||||
earlier ones).
|
||||
include::mailmap.txt[]
|
||||
|
||||
So, for example, if your history contains commits by two authors, Jane
|
||||
and Joe, whose names appear in the repository under several forms:
|
||||
|
||||
------------
|
||||
Joe Developer <joe@example.com>
|
||||
Joe R. Developer <joe@example.com>
|
||||
Jane Doe <jane@example.com>
|
||||
Jane Doe <jane@laptop.(none)>
|
||||
Jane D. <jane@desktop.(none)>
|
||||
------------
|
||||
|
||||
Then, supposing Joe wants his middle name initial used, and Jane prefers
|
||||
her family name fully spelled out, a proper `.mailmap` file would look like:
|
||||
|
||||
------------
|
||||
# Note how we don't need an entry for <jane@laptop.(none)>, because the
|
||||
# real name of that author is correct already, and coalesced directly.
|
||||
Jane Doe <jane@desktop.(none)>
|
||||
Joe R. Developer <joe@example.com>
|
||||
------------
|
||||
|
||||
Author
|
||||
------
|
||||
|
||||
@@ -12,7 +12,7 @@ SYNOPSIS
|
||||
'git submodule' [--quiet] add [-b branch] [--] <repository> <path>
|
||||
'git submodule' [--quiet] status [--cached] [--] [<path>...]
|
||||
'git submodule' [--quiet] init [--] [<path>...]
|
||||
'git submodule' [--quiet] update [--init] [--] [<path>...]
|
||||
'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--] [<path>...]
|
||||
'git submodule' [--quiet] summary [--summary-limit <n>] [commit] [--] [<path>...]
|
||||
'git submodule' [--quiet] foreach <command>
|
||||
'git submodule' [--quiet] sync [--] [<path>...]
|
||||
@@ -172,6 +172,11 @@ OPTIONS
|
||||
(the default). This limit only applies to modified submodules. The
|
||||
size is always limited to 1 for added/deleted/typechanged submodules.
|
||||
|
||||
-N::
|
||||
--no-fetch::
|
||||
This option is only valid for the update command.
|
||||
Don't fetch new objects from the remote site.
|
||||
|
||||
<path>...::
|
||||
Paths to submodule(s). When specified this will restrict the command
|
||||
to only operate on the submodules found at the specified paths.
|
||||
|
||||
@@ -169,6 +169,10 @@ and have no uncommitted changes.
|
||||
reused if a user is later given access to an alternate transport
|
||||
method (e.g. `svn+ssh://` or `https://`) for commit.
|
||||
|
||||
config key: svn-remote.<name>.commiturl
|
||||
|
||||
config key: svn.commiturl (overwrites all svn-remote.<name>.commiturl options)
|
||||
|
||||
Using this option for any other purpose (don't ask)
|
||||
is very strongly discouraged.
|
||||
--
|
||||
@@ -499,6 +503,14 @@ svn-remote.<name>.rewriteRoot::
|
||||
the repository with a public http:// or svn:// URL in the
|
||||
metadata so users of it will see the public URL.
|
||||
|
||||
svn.brokenSymlinkWorkaround::
|
||||
This disables potentially expensive checks to workaround broken symlinks
|
||||
checked into SVN by broken clients. Set this option to "false" if you
|
||||
track a SVN repository with many empty blobs that are not symlinks.
|
||||
This option may be changed while "git-svn" is running and take effect on
|
||||
the next revision fetched. If unset, git-svn assumes this option to be
|
||||
"true".
|
||||
|
||||
--
|
||||
|
||||
Since the noMetadata, rewriteRoot, useSvnsyncProps and useSvmProps
|
||||
|
||||
@@ -43,9 +43,16 @@ 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.1.1/git.html[documentation for release 1.6.1.1]
|
||||
* link:v1.6.2/git.html[documentation for release 1.6.2]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes-1.6.2.txt[1.6.2].
|
||||
|
||||
* link:v1.6.1.3/git.html[documentation for release 1.6.1.3]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes-1.6.1.3.txt[1.6.1.3],
|
||||
link:RelNotes-1.6.1.2.txt[1.6.1.2],
|
||||
link:RelNotes-1.6.1.1.txt[1.6.1.1],
|
||||
link:RelNotes-1.6.1.txt[1.6.1].
|
||||
|
||||
|
||||
@@ -18,10 +18,10 @@ A `gitattributes` file is a simple text file that gives
|
||||
|
||||
Each line in `gitattributes` file is of form:
|
||||
|
||||
glob attr1 attr2 ...
|
||||
pattern attr1 attr2 ...
|
||||
|
||||
That is, a glob pattern followed by an attributes list,
|
||||
separated by whitespaces. When the glob pattern matches the
|
||||
That is, a pattern followed by an attributes list,
|
||||
separated by whitespaces. When the pattern matches the
|
||||
path in question, the attributes listed on the line are given to
|
||||
the path.
|
||||
|
||||
@@ -48,13 +48,14 @@ Set to a value::
|
||||
|
||||
Unspecified::
|
||||
|
||||
No glob pattern matches the path, and nothing says if
|
||||
No pattern matches the path, and nothing says if
|
||||
the path has or does not have the attribute, the
|
||||
attribute for the path is said to be Unspecified.
|
||||
|
||||
When more than one glob pattern matches the path, a later line
|
||||
When more than one pattern matches the path, a later line
|
||||
overrides an earlier line. This overriding is done per
|
||||
attribute.
|
||||
attribute. The rules how the pattern matches paths are the
|
||||
same as in `.gitignore` files; see linkgit:gitignore[5].
|
||||
|
||||
When deciding what attributes are assigned to a path, git
|
||||
consults `$GIT_DIR/info/attributes` file (which has the highest
|
||||
|
||||
@@ -47,7 +47,8 @@ frequently used options.
|
||||
|
||||
After an attempt to merge stops with conflicts, show the commits on
|
||||
the history between two branches (i.e. the HEAD and the MERGE_HEAD)
|
||||
that modify the conflicted files.
|
||||
that modify the conflicted files and do not exist on all the heads
|
||||
being merged.
|
||||
|
||||
--argscmd=<command>::
|
||||
Command to be run each time gitk has to determine the list of
|
||||
@@ -73,7 +74,7 @@ frequently used options.
|
||||
<path>...::
|
||||
|
||||
Limit commits to the ones touching files in the given paths. Note, to
|
||||
avoid ambiguity wrt. revision names use "--" to separate the paths
|
||||
avoid ambiguity with respect to revision names use "--" to separate the paths
|
||||
from any preceding options.
|
||||
|
||||
Examples
|
||||
|
||||
@@ -39,7 +39,7 @@ Such a "revert" of a merge can be made with:
|
||||
|
||||
$ git revert -m 1 M
|
||||
|
||||
After the develpers of the side branch fixes their mistakes, the history
|
||||
After the developers of the side branch fix their mistakes, the history
|
||||
may look like this:
|
||||
|
||||
---o---o---o---M---x---x---W---x
|
||||
@@ -116,7 +116,7 @@ If you reverted the revert in such a case as in the previous example:
|
||||
/ \ /
|
||||
---A---B A'--B'--C'
|
||||
|
||||
where Y is the revert of W, A' and B'are rerolled A and B, and there may
|
||||
where Y is the revert of W, A' and B' are rerolled A and B, and there may
|
||||
also be a further fix-up C' on the side branch. "diff Y^..Y" is similar
|
||||
to "diff -R W^..W" (which in turn means it is similar to "diff M^..M"),
|
||||
and "diff A'^..C'" by definition would be similar but different from that,
|
||||
|
||||
@@ -143,7 +143,7 @@ Then, add something like this to your httpd.conf
|
||||
Require valid-user
|
||||
</Location>
|
||||
|
||||
Debian automatically reads all files under /etc/apach2/conf.d.
|
||||
Debian automatically reads all files under /etc/apache2/conf.d.
|
||||
|
||||
The password file can be somewhere else, but it has to be readable by
|
||||
Apache and preferably not readable by the world.
|
||||
|
||||
75
Documentation/mailmap.txt
Normal file
75
Documentation/mailmap.txt
Normal file
@@ -0,0 +1,75 @@
|
||||
If the file `.mailmap` exists at the toplevel of the repository, or at
|
||||
the location pointed to by the mailmap.file configuration option, it
|
||||
is used to map author and committer names and email addresses to
|
||||
canonical real names and email addresses.
|
||||
|
||||
In the simple form, each line in the file consists of the canonical
|
||||
real name of an author, whitespace, and an email address used in the
|
||||
commit (enclosed by '<' and '>') to map to the name. Thus, looks like
|
||||
this
|
||||
--
|
||||
Proper Name <commit@email.xx>
|
||||
--
|
||||
|
||||
The more complex forms are
|
||||
--
|
||||
<proper@email.xx> <commit@email.xx>
|
||||
--
|
||||
which allows mailmap to replace only the email part of a commit, and
|
||||
--
|
||||
Proper Name <proper@email.xx> <commit@email.xx>
|
||||
--
|
||||
which allows mailmap to replace both the name and the email of a
|
||||
commit matching the specified commit email address, and
|
||||
--
|
||||
Proper Name <proper@email.xx> Commit Name <commit@email.xx>
|
||||
--
|
||||
which allows mailmap to replace both the name and the email of a
|
||||
commit matching both the specified commit name and email address.
|
||||
|
||||
Example 1: Your history contains commits by two authors, Jane
|
||||
and Joe, whose names appear in the repository under several forms:
|
||||
|
||||
------------
|
||||
Joe Developer <joe@example.com>
|
||||
Joe R. Developer <joe@example.com>
|
||||
Jane Doe <jane@example.com>
|
||||
Jane Doe <jane@laptop.(none)>
|
||||
Jane D. <jane@desktop.(none)>
|
||||
------------
|
||||
|
||||
Now suppose that Joe wants his middle name initial used, and Jane
|
||||
prefers her family name fully spelled out. A proper `.mailmap` file
|
||||
would look like:
|
||||
|
||||
------------
|
||||
Jane Doe <jane@desktop.(none)>
|
||||
Joe R. Developer <joe@example.com>
|
||||
------------
|
||||
|
||||
Note how we don't need an entry for <jane@laptop.(none)>, because the
|
||||
real name of that author is correct already.
|
||||
|
||||
Example 2: Your repository contains commits from the following
|
||||
authors:
|
||||
|
||||
------------
|
||||
nick1 <bugs@company.xx>
|
||||
nick2 <bugs@company.xx>
|
||||
nick2 <nick2@company.xx>
|
||||
santa <me@company.xx>
|
||||
claus <me@company.xx>
|
||||
CTO <cto@coompany.xx>
|
||||
------------
|
||||
|
||||
Then, you might want a `.mailmap` file looking like:
|
||||
------------
|
||||
<cto@company.xx> <cto@coompany.xx>
|
||||
Some Dude <some@dude.xx> nick1 <bugs@company.xx>
|
||||
Other Author <other@author.xx> nick2 <bugs@company.xx>
|
||||
Other Author <other@author.xx> <nick2@company.xx>
|
||||
Santa Claus <santa.claus@northpole.xx> <me@company.xx>
|
||||
------------
|
||||
|
||||
Use hash '#' for comments that are either on their own line, or after
|
||||
the email address.
|
||||
@@ -101,16 +101,18 @@ The placeholders are:
|
||||
- '%P': parent hashes
|
||||
- '%p': abbreviated parent hashes
|
||||
- '%an': author name
|
||||
- '%aN': author name (respecting .mailmap)
|
||||
- '%aN': author name (respecting .mailmap, see linkgit:git-shortlog[1] or linkgit:git-blame[1])
|
||||
- '%ae': author email
|
||||
- '%aE': author email (respecting .mailmap, see linkgit:git-shortlog[1] or linkgit:git-blame[1])
|
||||
- '%ad': author date (format respects --date= option)
|
||||
- '%aD': author date, RFC2822 style
|
||||
- '%ar': author date, relative
|
||||
- '%at': author date, UNIX timestamp
|
||||
- '%ai': author date, ISO 8601 format
|
||||
- '%cn': committer name
|
||||
- '%cN': committer name (respecting .mailmap)
|
||||
- '%cN': committer name (respecting .mailmap, see linkgit:git-shortlog[1] or linkgit:git-blame[1])
|
||||
- '%ce': committer email
|
||||
- '%cE': committer email (respecting .mailmap, see linkgit:git-shortlog[1] or linkgit:git-blame[1])
|
||||
- '%cd': committer date
|
||||
- '%cD': committer date, RFC2822 style
|
||||
- '%cr': committer date, relative
|
||||
|
||||
@@ -13,7 +13,7 @@ include::pretty-options.txt[]
|
||||
|
||||
Synonym for `--date=relative`.
|
||||
|
||||
--date={relative,local,default,iso,rfc,short}::
|
||||
--date={relative,local,default,iso,rfc,short,raw}::
|
||||
|
||||
Only takes effect for dates shown in human-readable format, such
|
||||
as when using "--pretty". `log.date` config variable sets a default
|
||||
@@ -31,6 +31,8 @@ format, often found in E-mail messages.
|
||||
+
|
||||
`--date=short` shows only date but not time, in `YYYY-MM-DD` format.
|
||||
+
|
||||
`--date=raw` shows the date in the internal raw git format `%s %z` format.
|
||||
+
|
||||
`--date=default` shows timestamps in the original timezone
|
||||
(either committer's or author's).
|
||||
|
||||
|
||||
@@ -222,7 +222,7 @@ which can be used by the programmer of the callback as she sees fit.
|
||||
|
||||
Read a given size of data from a FILE* pointer to the buffer.
|
||||
+
|
||||
NOTE: The buffer is rewinded if the read fails. If -1 is returned,
|
||||
NOTE: The buffer is rewound if the read fails. If -1 is returned,
|
||||
`errno` must be consulted, like you would do for `read(3)`.
|
||||
`strbuf_read()`, `strbuf_read_file()` and `strbuf_getline()` has the
|
||||
same behaviour as well.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
GVF=GIT-VERSION-FILE
|
||||
DEF_VER=v1.6.1.GIT
|
||||
DEF_VER=v1.6.2.GIT
|
||||
|
||||
LF='
|
||||
'
|
||||
|
||||
25
Makefile
25
Makefile
@@ -228,7 +228,7 @@ GITWEB_FAVICON = git-favicon.png
|
||||
GITWEB_SITE_HEADER =
|
||||
GITWEB_SITE_FOOTER =
|
||||
|
||||
export prefix bindir sharedir htmldir sysconfdir
|
||||
export prefix bindir sharedir sysconfdir
|
||||
|
||||
CC = gcc
|
||||
AR = ar
|
||||
@@ -265,7 +265,6 @@ SCRIPT_SH += git-merge-octopus.sh
|
||||
SCRIPT_SH += git-merge-one-file.sh
|
||||
SCRIPT_SH += git-merge-resolve.sh
|
||||
SCRIPT_SH += git-mergetool.sh
|
||||
SCRIPT_SH += git-notes.sh
|
||||
SCRIPT_SH += git-parse-remote.sh
|
||||
SCRIPT_SH += git-pull.sh
|
||||
SCRIPT_SH += git-quiltimport.sh
|
||||
@@ -318,8 +317,8 @@ PROGRAMS += git-var$X
|
||||
# builtin-$C.o but is linked in as part of some other command.
|
||||
BUILT_INS += $(patsubst builtin-%.o,git-%$X,$(BUILTIN_OBJS))
|
||||
|
||||
BUILT_INS += git-cherry-pick$X
|
||||
BUILT_INS += git-cherry$X
|
||||
BUILT_INS += git-cherry-pick$X
|
||||
BUILT_INS += git-format-patch$X
|
||||
BUILT_INS += git-fsck-objects$X
|
||||
BUILT_INS += git-get-tar-commit-id$X
|
||||
@@ -358,8 +357,8 @@ LIB_H += builtin.h
|
||||
LIB_H += cache.h
|
||||
LIB_H += cache-tree.h
|
||||
LIB_H += commit.h
|
||||
LIB_H += compat/mingw.h
|
||||
LIB_H += compat/cygwin.h
|
||||
LIB_H += compat/mingw.h
|
||||
LIB_H += csum-file.h
|
||||
LIB_H += decorate.h
|
||||
LIB_H += delta.h
|
||||
@@ -378,14 +377,12 @@ LIB_H += ll-merge.h
|
||||
LIB_H += log-tree.h
|
||||
LIB_H += mailmap.h
|
||||
LIB_H += merge-recursive.h
|
||||
LIB_H += notes.h
|
||||
LIB_H += object.h
|
||||
LIB_H += pack.h
|
||||
LIB_H += pack-refs.h
|
||||
LIB_H += pack-revindex.h
|
||||
LIB_H += parse-options.h
|
||||
LIB_H += patch-ids.h
|
||||
LIB_H += string-list.h
|
||||
LIB_H += pkt-line.h
|
||||
LIB_H += progress.h
|
||||
LIB_H += quote.h
|
||||
@@ -399,6 +396,7 @@ LIB_H += sha1-lookup.h
|
||||
LIB_H += sideband.h
|
||||
LIB_H += sigchain.h
|
||||
LIB_H += strbuf.h
|
||||
LIB_H += string-list.h
|
||||
LIB_H += tag.h
|
||||
LIB_H += transport.h
|
||||
LIB_H += tree.h
|
||||
@@ -437,8 +435,8 @@ LIB_OBJS += diffcore-order.o
|
||||
LIB_OBJS += diffcore-pickaxe.o
|
||||
LIB_OBJS += diffcore-rename.o
|
||||
LIB_OBJS += diff-delta.o
|
||||
LIB_OBJS += diff-no-index.o
|
||||
LIB_OBJS += diff-lib.o
|
||||
LIB_OBJS += diff-no-index.o
|
||||
LIB_OBJS += diff.o
|
||||
LIB_OBJS += dir.o
|
||||
LIB_OBJS += editor.o
|
||||
@@ -461,7 +459,6 @@ LIB_OBJS += match-trees.o
|
||||
LIB_OBJS += merge-file.o
|
||||
LIB_OBJS += merge-recursive.o
|
||||
LIB_OBJS += name-hash.o
|
||||
LIB_OBJS += notes.o
|
||||
LIB_OBJS += object.o
|
||||
LIB_OBJS += pack-check.o
|
||||
LIB_OBJS += pack-refs.o
|
||||
@@ -471,9 +468,9 @@ LIB_OBJS += pager.o
|
||||
LIB_OBJS += parse-options.o
|
||||
LIB_OBJS += patch-delta.o
|
||||
LIB_OBJS += patch-ids.o
|
||||
LIB_OBJS += string-list.o
|
||||
LIB_OBJS += path.o
|
||||
LIB_OBJS += pkt-line.o
|
||||
LIB_OBJS += preload-index.o
|
||||
LIB_OBJS += pretty.o
|
||||
LIB_OBJS += progress.o
|
||||
LIB_OBJS += quote.o
|
||||
@@ -487,13 +484,14 @@ LIB_OBJS += revision.o
|
||||
LIB_OBJS += run-command.o
|
||||
LIB_OBJS += server-info.o
|
||||
LIB_OBJS += setup.o
|
||||
LIB_OBJS += sha1_file.o
|
||||
LIB_OBJS += sha1-lookup.o
|
||||
LIB_OBJS += sha1_file.o
|
||||
LIB_OBJS += sha1_name.o
|
||||
LIB_OBJS += shallow.o
|
||||
LIB_OBJS += sideband.o
|
||||
LIB_OBJS += sigchain.o
|
||||
LIB_OBJS += strbuf.o
|
||||
LIB_OBJS += string-list.o
|
||||
LIB_OBJS += symlinks.o
|
||||
LIB_OBJS += tag.o
|
||||
LIB_OBJS += trace.o
|
||||
@@ -502,8 +500,8 @@ LIB_OBJS += tree-diff.o
|
||||
LIB_OBJS += tree.o
|
||||
LIB_OBJS += tree-walk.o
|
||||
LIB_OBJS += unpack-trees.o
|
||||
LIB_OBJS += userdiff.o
|
||||
LIB_OBJS += usage.o
|
||||
LIB_OBJS += userdiff.o
|
||||
LIB_OBJS += utf8.o
|
||||
LIB_OBJS += walker.o
|
||||
LIB_OBJS += wrapper.o
|
||||
@@ -511,7 +509,6 @@ LIB_OBJS += write_or_die.o
|
||||
LIB_OBJS += ws.o
|
||||
LIB_OBJS += wt-status.o
|
||||
LIB_OBJS += xdiff-interface.o
|
||||
LIB_OBJS += preload-index.o
|
||||
|
||||
BUILTIN_OBJS += builtin-add.o
|
||||
BUILTIN_OBJS += builtin-annotate.o
|
||||
@@ -1476,8 +1473,8 @@ endif
|
||||
bindir=$$(cd '$(DESTDIR_SQ)$(bindir_SQ)' && pwd) && \
|
||||
execdir=$$(cd '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' && pwd) && \
|
||||
{ $(RM) "$$execdir/git-add$X" && \
|
||||
ln git-add$X "$$execdir/git-add$X" 2>/dev/null || \
|
||||
cp git-add$X "$$execdir/git-add$X"; } && \
|
||||
ln "$$bindir/git$X" "$$execdir/git-add$X" 2>/dev/null || \
|
||||
cp "$$bindir/git$X" "$$execdir/git-add$X"; } && \
|
||||
{ for p in $(filter-out git-add$X,$(BUILT_INS)); do \
|
||||
$(RM) "$$execdir/$$p" && \
|
||||
ln "$$execdir/git-add$X" "$$execdir/$$p" 2>/dev/null || \
|
||||
|
||||
14
README
14
README
@@ -24,10 +24,18 @@ It was originally written by Linus Torvalds with help of a group of
|
||||
hackers around the net. It is currently maintained by Junio C Hamano.
|
||||
|
||||
Please read the file INSTALL for installation instructions.
|
||||
|
||||
See Documentation/gittutorial.txt to get started, then see
|
||||
Documentation/everyday.txt for a useful minimum set of commands,
|
||||
and "man git-commandname" for documentation of each command.
|
||||
CVS users may also want to read Documentation/cvs-migration.txt.
|
||||
Documentation/everyday.txt for a useful minimum set of commands, and
|
||||
Documentation/git-commandname.txt for documentation of each command.
|
||||
If git has been correctly installed, then the tutorial can also be
|
||||
read with "man gittutorial" or "git help tutorial", and the
|
||||
documentation of each command with "man git-commandname" or "git help
|
||||
commandname".
|
||||
|
||||
CVS users may also want to read Documentation/gitcvs-migration.txt
|
||||
("man gitcvs-migration" or "git help cvs-migration" if git is
|
||||
installed).
|
||||
|
||||
Many Git online resources are accessible from http://git.or.cz/
|
||||
including full documentation and Git related tools.
|
||||
|
||||
@@ -132,7 +132,7 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
|
||||
err = write_entry(args, sha1, path.buf, path.len, mode, NULL, 0);
|
||||
if (err)
|
||||
return err;
|
||||
return READ_TREE_RECURSIVE;
|
||||
return (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0);
|
||||
}
|
||||
|
||||
buffer = sha1_file_to_archive(path_without_prefix, sha1, mode,
|
||||
|
||||
19
branch.c
19
branch.c
@@ -103,14 +103,22 @@ void create_branch(const char *head,
|
||||
struct ref_lock *lock;
|
||||
struct commit *commit;
|
||||
unsigned char sha1[20];
|
||||
char *real_ref, ref[PATH_MAX], msg[PATH_MAX + 20];
|
||||
char *real_ref, msg[PATH_MAX + 20];
|
||||
struct strbuf ref = STRBUF_INIT;
|
||||
int forcing = 0;
|
||||
int len;
|
||||
|
||||
snprintf(ref, sizeof ref, "refs/heads/%s", name);
|
||||
if (check_ref_format(ref))
|
||||
len = strlen(name);
|
||||
if (interpret_nth_last_branch(name, &ref) != len) {
|
||||
strbuf_reset(&ref);
|
||||
strbuf_add(&ref, name, len);
|
||||
}
|
||||
strbuf_splice(&ref, 0, 0, "refs/heads/", 11);
|
||||
|
||||
if (check_ref_format(ref.buf))
|
||||
die("'%s' is not a valid branch name.", name);
|
||||
|
||||
if (resolve_ref(ref, sha1, 1, NULL)) {
|
||||
if (resolve_ref(ref.buf, sha1, 1, NULL)) {
|
||||
if (!force)
|
||||
die("A branch named '%s' already exists.", name);
|
||||
else if (!is_bare_repository() && !strcmp(head, name))
|
||||
@@ -142,7 +150,7 @@ void create_branch(const char *head,
|
||||
die("Not a valid branch point: '%s'.", start_name);
|
||||
hashcpy(sha1, commit->object.sha1);
|
||||
|
||||
lock = lock_any_ref_for_update(ref, NULL, 0);
|
||||
lock = lock_any_ref_for_update(ref.buf, NULL, 0);
|
||||
if (!lock)
|
||||
die("Failed to lock ref for update: %s.", strerror(errno));
|
||||
|
||||
@@ -162,6 +170,7 @@ void create_branch(const char *head,
|
||||
if (write_ref_sha1(lock, sha1, msg) < 0)
|
||||
die("Failed to write ref: %s.", strerror(errno));
|
||||
|
||||
strbuf_release(&ref);
|
||||
free(real_ref);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ static const char * const builtin_add_usage[] = {
|
||||
"git add [options] [--] <filepattern>...",
|
||||
NULL
|
||||
};
|
||||
static int patch_interactive = 0, add_interactive = 0;
|
||||
static int patch_interactive, add_interactive;
|
||||
static int take_worktree_changes;
|
||||
|
||||
static void fill_pathspec_matches(const char **pathspec, char *seen, int specs)
|
||||
|
||||
@@ -1264,11 +1264,12 @@ struct commit_info
|
||||
* Parse author/committer line in the commit object buffer
|
||||
*/
|
||||
static void get_ac_line(const char *inbuf, const char *what,
|
||||
int bufsz, char *person, const char **mail,
|
||||
int person_len, char *person,
|
||||
int mail_len, char *mail,
|
||||
unsigned long *time, const char **tz)
|
||||
{
|
||||
int len, tzlen, maillen;
|
||||
char *tmp, *endp, *timepos;
|
||||
char *tmp, *endp, *timepos, *mailpos;
|
||||
|
||||
tmp = strstr(inbuf, what);
|
||||
if (!tmp)
|
||||
@@ -1279,10 +1280,11 @@ static void get_ac_line(const char *inbuf, const char *what,
|
||||
len = strlen(tmp);
|
||||
else
|
||||
len = endp - tmp;
|
||||
if (bufsz <= len) {
|
||||
if (person_len <= len) {
|
||||
error_out:
|
||||
/* Ugh */
|
||||
*mail = *tz = "(unknown)";
|
||||
*tz = "(unknown)";
|
||||
strcpy(mail, *tz);
|
||||
*time = 0;
|
||||
return;
|
||||
}
|
||||
@@ -1305,9 +1307,10 @@ static void get_ac_line(const char *inbuf, const char *what,
|
||||
*tmp = 0;
|
||||
while (*tmp != ' ')
|
||||
tmp--;
|
||||
*mail = tmp + 1;
|
||||
mailpos = tmp + 1;
|
||||
*tmp = 0;
|
||||
maillen = timepos - tmp;
|
||||
memcpy(mail, mailpos, maillen);
|
||||
|
||||
if (!mailmap.nr)
|
||||
return;
|
||||
@@ -1316,20 +1319,23 @@ static void get_ac_line(const char *inbuf, const char *what,
|
||||
* mailmap expansion may make the name longer.
|
||||
* make room by pushing stuff down.
|
||||
*/
|
||||
tmp = person + bufsz - (tzlen + 1);
|
||||
tmp = person + person_len - (tzlen + 1);
|
||||
memmove(tmp, *tz, tzlen);
|
||||
tmp[tzlen] = 0;
|
||||
*tz = tmp;
|
||||
|
||||
tmp = tmp - (maillen + 1);
|
||||
memmove(tmp, *mail, maillen);
|
||||
tmp[maillen] = 0;
|
||||
*mail = tmp;
|
||||
|
||||
/*
|
||||
* Now, convert e-mail using mailmap
|
||||
* Now, convert both name and e-mail using mailmap
|
||||
*/
|
||||
map_email(&mailmap, tmp + 1, person, tmp-person-1);
|
||||
if(map_user(&mailmap, mail+1, mail_len-1, person, tmp-person-1)) {
|
||||
/* Add a trailing '>' to email, since map_user returns plain emails
|
||||
Note: It already has '<', since we replace from mail+1 */
|
||||
mailpos = memchr(mail, '\0', mail_len);
|
||||
if (mailpos && mailpos-mail < mail_len - 1) {
|
||||
*mailpos = '>';
|
||||
*(mailpos+1) = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void get_commit_info(struct commit *commit,
|
||||
@@ -1338,8 +1344,10 @@ static void get_commit_info(struct commit *commit,
|
||||
{
|
||||
int len;
|
||||
char *tmp, *endp, *reencoded, *message;
|
||||
static char author_buf[1024];
|
||||
static char committer_buf[1024];
|
||||
static char author_name[1024];
|
||||
static char author_mail[1024];
|
||||
static char committer_name[1024];
|
||||
static char committer_mail[1024];
|
||||
static char summary_buf[1024];
|
||||
|
||||
/*
|
||||
@@ -1357,9 +1365,11 @@ static void get_commit_info(struct commit *commit,
|
||||
}
|
||||
reencoded = reencode_commit_message(commit, NULL);
|
||||
message = reencoded ? reencoded : commit->buffer;
|
||||
ret->author = author_buf;
|
||||
ret->author = author_name;
|
||||
ret->author_mail = author_mail;
|
||||
get_ac_line(message, "\nauthor ",
|
||||
sizeof(author_buf), author_buf, &ret->author_mail,
|
||||
sizeof(author_name), author_name,
|
||||
sizeof(author_mail), author_mail,
|
||||
&ret->author_time, &ret->author_tz);
|
||||
|
||||
if (!detailed) {
|
||||
@@ -1367,9 +1377,11 @@ static void get_commit_info(struct commit *commit,
|
||||
return;
|
||||
}
|
||||
|
||||
ret->committer = committer_buf;
|
||||
ret->committer = committer_name;
|
||||
ret->committer_mail = committer_mail;
|
||||
get_ac_line(message, "\ncommitter ",
|
||||
sizeof(committer_buf), committer_buf, &ret->committer_mail,
|
||||
sizeof(committer_name), committer_name,
|
||||
sizeof(committer_mail), committer_mail,
|
||||
&ret->committer_time, &ret->committer_tz);
|
||||
|
||||
ret->summary = summary_buf;
|
||||
@@ -2396,7 +2408,7 @@ parse_done:
|
||||
die("reading graft file %s failed: %s",
|
||||
revs_file, strerror(errno));
|
||||
|
||||
read_mailmap(&mailmap, ".mailmap", NULL);
|
||||
read_mailmap(&mailmap, NULL);
|
||||
|
||||
if (!incremental)
|
||||
setup_pager();
|
||||
|
||||
@@ -99,6 +99,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)
|
||||
const char *fmt, *remote;
|
||||
int i;
|
||||
int ret = 0;
|
||||
struct strbuf bname = STRBUF_INIT;
|
||||
|
||||
switch (kinds) {
|
||||
case REF_REMOTE_BRANCH:
|
||||
@@ -119,20 +120,25 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)
|
||||
if (!head_rev)
|
||||
die("Couldn't look up commit object for HEAD");
|
||||
}
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (kinds == REF_LOCAL_BRANCH && !strcmp(head, argv[i])) {
|
||||
for (i = 0; i < argc; i++, strbuf_release(&bname)) {
|
||||
int len = strlen(argv[i]);
|
||||
|
||||
if (interpret_nth_last_branch(argv[i], &bname) != len)
|
||||
strbuf_add(&bname, argv[i], len);
|
||||
|
||||
if (kinds == REF_LOCAL_BRANCH && !strcmp(head, bname.buf)) {
|
||||
error("Cannot delete the branch '%s' "
|
||||
"which you are currently on.", argv[i]);
|
||||
"which you are currently on.", bname.buf);
|
||||
ret = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
free(name);
|
||||
|
||||
name = xstrdup(mkpath(fmt, argv[i]));
|
||||
name = xstrdup(mkpath(fmt, bname.buf));
|
||||
if (!resolve_ref(name, sha1, 1, NULL)) {
|
||||
error("%sbranch '%s' not found.",
|
||||
remote, argv[i]);
|
||||
remote, bname.buf);
|
||||
ret = 1;
|
||||
continue;
|
||||
}
|
||||
@@ -152,22 +158,23 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)
|
||||
if (!force &&
|
||||
!in_merge_bases(rev, &head_rev, 1)) {
|
||||
error("The branch '%s' is not an ancestor of "
|
||||
"your current HEAD.\n"
|
||||
"If you are sure you want to delete it, "
|
||||
"run 'git branch -D %s'.", argv[i], argv[i]);
|
||||
"your current HEAD.\n"
|
||||
"If you are sure you want to delete it, "
|
||||
"run 'git branch -D %s'.", bname.buf, bname.buf);
|
||||
ret = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (delete_ref(name, sha1, 0)) {
|
||||
error("Error deleting %sbranch '%s'", remote,
|
||||
argv[i]);
|
||||
bname.buf);
|
||||
ret = 1;
|
||||
} else {
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
printf("Deleted %sbranch %s (%s).\n", remote, argv[i],
|
||||
find_unique_abbrev(sha1, DEFAULT_ABBREV));
|
||||
strbuf_addf(&buf, "branch.%s", argv[i]);
|
||||
printf("Deleted %sbranch %s (%s).\n", remote,
|
||||
bname.buf,
|
||||
find_unique_abbrev(sha1, DEFAULT_ABBREV));
|
||||
strbuf_addf(&buf, "branch.%s", bname.buf);
|
||||
if (git_config_rename_section(buf.buf, NULL) < 0)
|
||||
warning("Update of config-file failed");
|
||||
strbuf_release(&buf);
|
||||
|
||||
@@ -350,6 +350,19 @@ static struct ref *write_remote_refs(const struct ref *refs,
|
||||
return local_refs;
|
||||
}
|
||||
|
||||
static void install_branch_config(const char *local,
|
||||
const char *origin,
|
||||
const char *remote)
|
||||
{
|
||||
struct strbuf key = STRBUF_INIT;
|
||||
strbuf_addf(&key, "branch.%s.remote", local);
|
||||
git_config_set(key.buf, origin);
|
||||
strbuf_reset(&key);
|
||||
strbuf_addf(&key, "branch.%s.merge", local);
|
||||
git_config_set(key.buf, remote);
|
||||
strbuf_release(&key);
|
||||
}
|
||||
|
||||
int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int use_local_hardlinks = 1;
|
||||
@@ -539,6 +552,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
head_points_at = NULL;
|
||||
remote_head = NULL;
|
||||
option_no_checkout = 1;
|
||||
if (!option_bare)
|
||||
install_branch_config("master", option_origin,
|
||||
"refs/heads/master");
|
||||
}
|
||||
|
||||
if (head_points_at) {
|
||||
@@ -567,11 +583,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
head_points_at->peer_ref->name,
|
||||
reflog_msg.buf);
|
||||
|
||||
strbuf_addf(&key, "branch.%s.remote", head);
|
||||
git_config_set(key.buf, option_origin);
|
||||
strbuf_reset(&key);
|
||||
strbuf_addf(&key, "branch.%s.merge", head);
|
||||
git_config_set(key.buf, head_points_at->name);
|
||||
install_branch_config(head, option_origin,
|
||||
head_points_at->name);
|
||||
}
|
||||
} else if (remote_head) {
|
||||
/* Source had detached HEAD pointing somewhere. */
|
||||
|
||||
@@ -561,7 +561,6 @@ static int prepare_to_commit(const char *index_file, const char *prefix)
|
||||
commitable = run_status(fp, index_file, prefix, 1);
|
||||
wt_status_use_color = saved_color_setting;
|
||||
} else {
|
||||
struct rev_info rev;
|
||||
unsigned char sha1[20];
|
||||
const char *parent = "HEAD";
|
||||
|
||||
@@ -573,16 +572,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix)
|
||||
|
||||
if (get_sha1(parent, sha1))
|
||||
commitable = !!active_nr;
|
||||
else {
|
||||
init_revisions(&rev, "");
|
||||
rev.abbrev = 0;
|
||||
setup_revisions(0, NULL, &rev, parent);
|
||||
DIFF_OPT_SET(&rev.diffopt, QUIET);
|
||||
DIFF_OPT_SET(&rev.diffopt, EXIT_WITH_STATUS);
|
||||
run_diff_index(&rev, 1 /* cached */);
|
||||
|
||||
commitable = !!DIFF_OPT_TST(&rev.diffopt, HAS_CHANGES);
|
||||
}
|
||||
else
|
||||
commitable = index_differs_from(parent, 0);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
@@ -514,6 +514,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
|
||||
|
||||
get_tags_and_duplicates(&revs.pending, &extra_refs);
|
||||
|
||||
revs.topo_order = 1;
|
||||
if (prepare_revision_walk(&revs))
|
||||
die("revision walk setup failed");
|
||||
revs.diffopt.format_callback = show_filemodify;
|
||||
|
||||
19
builtin-gc.c
19
builtin-gc.c
@@ -161,7 +161,8 @@ static int need_to_gc(void)
|
||||
*/
|
||||
if (too_many_packs())
|
||||
append_option(argv_repack,
|
||||
!strcmp(prune_expire, "now") ? "-a" : "-A",
|
||||
prune_expire && !strcmp(prune_expire, "now") ?
|
||||
"-a" : "-A",
|
||||
MAX_ADD);
|
||||
else if (!too_many_loose_objects())
|
||||
return 0;
|
||||
@@ -173,14 +174,15 @@ static int need_to_gc(void)
|
||||
|
||||
int cmd_gc(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int prune = 0;
|
||||
int aggressive = 0;
|
||||
int auto_gc = 0;
|
||||
int quiet = 0;
|
||||
char buf[80];
|
||||
|
||||
struct option builtin_gc_options[] = {
|
||||
OPT_BOOLEAN(0, "prune", &prune, "prune unreferenced objects (deprecated)"),
|
||||
{ OPTION_STRING, 0, "prune", &prune_expire, "date",
|
||||
"prune unreferenced objects",
|
||||
PARSE_OPT_OPTARG, NULL, (intptr_t)prune_expire },
|
||||
OPT_BOOLEAN(0, "aggressive", &aggressive, "be more thorough (increased runtime)"),
|
||||
OPT_BOOLEAN(0, "auto", &auto_gc, "enable auto-gc mode"),
|
||||
OPT_BOOLEAN('q', "quiet", &quiet, "suppress progress reports"),
|
||||
@@ -218,7 +220,8 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
|
||||
"\"git help gc\" for more information.\n");
|
||||
} else
|
||||
append_option(argv_repack,
|
||||
!strcmp(prune_expire, "now") ? "-a" : "-A",
|
||||
prune_expire && !strcmp(prune_expire, "now")
|
||||
? "-a" : "-A",
|
||||
MAX_ADD);
|
||||
|
||||
if (pack_refs && run_command_v_opt(argv_pack_refs, RUN_GIT_CMD))
|
||||
@@ -230,9 +233,11 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
|
||||
if (run_command_v_opt(argv_repack, RUN_GIT_CMD))
|
||||
return error(FAILED_RUN, argv_repack[0]);
|
||||
|
||||
argv_prune[2] = prune_expire;
|
||||
if (run_command_v_opt(argv_prune, RUN_GIT_CMD))
|
||||
return error(FAILED_RUN, argv_prune[0]);
|
||||
if (prune_expire) {
|
||||
argv_prune[2] = prune_expire;
|
||||
if (run_command_v_opt(argv_prune, RUN_GIT_CMD))
|
||||
return error(FAILED_RUN, argv_prune[0]);
|
||||
}
|
||||
|
||||
if (run_command_v_opt(argv_rerere, RUN_GIT_CMD))
|
||||
return error(FAILED_RUN, argv_rerere[0]);
|
||||
|
||||
@@ -262,6 +262,21 @@ static const char *verify_pathspec(const char *prefix)
|
||||
return max ? xmemdupz(prev, max) : NULL;
|
||||
}
|
||||
|
||||
static void strip_trailing_slash_from_submodules(void)
|
||||
{
|
||||
const char **p;
|
||||
|
||||
for (p = pathspec; *p != NULL; p++) {
|
||||
int len = strlen(*p), pos;
|
||||
|
||||
if (len < 1 || (*p)[len - 1] != '/')
|
||||
continue;
|
||||
pos = cache_name_pos(*p, len - 1);
|
||||
if (pos >= 0 && S_ISGITLINK(active_cache[pos]->ce_mode))
|
||||
*p = xstrndup(*p, len - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the tree specified with --with-tree option
|
||||
* (typically, HEAD) into stage #1 and then
|
||||
@@ -510,6 +525,11 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
|
||||
|
||||
pathspec = get_pathspec(prefix, argv + i);
|
||||
|
||||
/* be nice with submodule patsh ending in a slash */
|
||||
read_cache();
|
||||
if (pathspec)
|
||||
strip_trailing_slash_from_submodules();
|
||||
|
||||
/* Verify that the pathspec matches the prefix */
|
||||
if (pathspec)
|
||||
prefix = verify_pathspec(prefix);
|
||||
@@ -533,7 +553,6 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
|
||||
show_killed | show_modified))
|
||||
show_cached = 1;
|
||||
|
||||
read_cache();
|
||||
if (prefix)
|
||||
prune_cache(prefix);
|
||||
if (with_tree) {
|
||||
|
||||
@@ -68,13 +68,8 @@ static int show_tree(const unsigned char *sha1, const char *base, int baselen,
|
||||
*
|
||||
* Something similar to this incomplete example:
|
||||
*
|
||||
if (show_subprojects(base, baselen, pathname)) {
|
||||
struct child_process ls_tree;
|
||||
|
||||
ls_tree.dir = base;
|
||||
ls_tree.argv = ls-tree;
|
||||
start_command(&ls_tree);
|
||||
}
|
||||
if (show_subprojects(base, baselen, pathname))
|
||||
retval = READ_TREE_RECURSIVE;
|
||||
*
|
||||
*/
|
||||
type = commit_type;
|
||||
|
||||
@@ -356,9 +356,14 @@ static void merge_name(const char *remote, struct strbuf *msg)
|
||||
struct object *remote_head;
|
||||
unsigned char branch_head[20], buf_sha[20];
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
struct strbuf bname = STRBUF_INIT;
|
||||
const char *ptr;
|
||||
int len, early;
|
||||
|
||||
len = strlen(remote);
|
||||
if (interpret_nth_last_branch(remote, &bname) == len)
|
||||
remote = bname.buf;
|
||||
|
||||
memset(branch_head, 0, sizeof(branch_head));
|
||||
remote_head = peel_to_type(remote, 0, NULL, OBJ_COMMIT);
|
||||
if (!remote_head)
|
||||
@@ -371,7 +376,7 @@ static void merge_name(const char *remote, struct strbuf *msg)
|
||||
if (!hashcmp(remote_head->sha1, branch_head)) {
|
||||
strbuf_addf(msg, "%s\t\tbranch '%s' of .\n",
|
||||
sha1_to_hex(branch_head), remote);
|
||||
return;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* See if remote matches <name>^^^.. or <name>~<number> */
|
||||
@@ -411,7 +416,8 @@ static void merge_name(const char *remote, struct strbuf *msg)
|
||||
sha1_to_hex(remote_head->sha1),
|
||||
truname.buf + 11,
|
||||
(early ? " (early part)" : ""));
|
||||
return;
|
||||
strbuf_release(&truname);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -432,10 +438,13 @@ static void merge_name(const char *remote, struct strbuf *msg)
|
||||
strbuf_remove(&line, ptr-line.buf+1, 13);
|
||||
strbuf_addbuf(msg, &line);
|
||||
strbuf_release(&line);
|
||||
return;
|
||||
goto cleanup;
|
||||
}
|
||||
strbuf_addf(msg, "%s\t\tcommit '%s'\n",
|
||||
sha1_to_hex(remote_head->sha1), remote);
|
||||
cleanup:
|
||||
strbuf_release(&buf);
|
||||
strbuf_release(&bname);
|
||||
}
|
||||
|
||||
static int git_merge_config(const char *k, const char *v, void *cb)
|
||||
|
||||
@@ -488,9 +488,8 @@ static void write_pack_file(void)
|
||||
} else {
|
||||
char tmpname[PATH_MAX];
|
||||
int fd;
|
||||
snprintf(tmpname, sizeof(tmpname),
|
||||
"%s/pack/tmp_pack_XXXXXX", get_object_directory());
|
||||
fd = xmkstemp(tmpname);
|
||||
fd = odb_mkstemp(tmpname, sizeof(tmpname),
|
||||
"pack/tmp_pack_XXXXXX");
|
||||
pack_tmp_name = xstrdup(tmpname);
|
||||
f = sha1fd(fd, pack_tmp_name);
|
||||
}
|
||||
|
||||
@@ -18,14 +18,16 @@ enum deny_action {
|
||||
DENY_REFUSE,
|
||||
};
|
||||
|
||||
static int deny_deletes = 0;
|
||||
static int deny_non_fast_forwards = 0;
|
||||
static int deny_deletes;
|
||||
static int deny_non_fast_forwards;
|
||||
static enum deny_action deny_current_branch = DENY_UNCONFIGURED;
|
||||
static enum deny_action deny_delete_current = DENY_UNCONFIGURED;
|
||||
static int receive_fsck_objects;
|
||||
static int receive_unpack_limit = -1;
|
||||
static int transfer_unpack_limit = -1;
|
||||
static int unpack_limit = 100;
|
||||
static int report_status;
|
||||
static const char *head_name;
|
||||
|
||||
static char capabilities[] = " report-status delete-refs ";
|
||||
static int capabilities_sent;
|
||||
@@ -77,6 +79,11 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(var, "receive.denydeletecurrent") == 0) {
|
||||
deny_delete_current = parse_deny_action(var, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return git_default_config(var, value, cb);
|
||||
}
|
||||
|
||||
@@ -203,16 +210,12 @@ static int run_update_hook(struct command *cmd)
|
||||
|
||||
static int is_ref_checked_out(const char *ref)
|
||||
{
|
||||
unsigned char sha1[20];
|
||||
const char *head;
|
||||
|
||||
if (is_bare_repository())
|
||||
return 0;
|
||||
|
||||
head = resolve_ref("HEAD", sha1, 0, NULL);
|
||||
if (!head)
|
||||
if (!head_name)
|
||||
return 0;
|
||||
return !strcmp(head, ref);
|
||||
return !strcmp(head_name, ref);
|
||||
}
|
||||
|
||||
static char *warn_unconfigured_deny_msg[] = {
|
||||
@@ -241,7 +244,33 @@ static void warn_unconfigured_deny(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(warn_unconfigured_deny_msg); i++)
|
||||
warning(warn_unconfigured_deny_msg[i]);
|
||||
warning("%s", warn_unconfigured_deny_msg[i]);
|
||||
}
|
||||
|
||||
static char *warn_unconfigured_deny_delete_current_msg[] = {
|
||||
"Deleting the current branch can cause confusion by making the next",
|
||||
"'git clone' not check out any file.",
|
||||
"",
|
||||
"You can set 'receive.denyDeleteCurrent' configuration variable to",
|
||||
"'refuse' in the remote repository to disallow deleting the current",
|
||||
"branch.",
|
||||
"",
|
||||
"You can set it to 'ignore' to allow such a delete without a warning.",
|
||||
"",
|
||||
"To make this warning message less loud, you can set it to 'warn'.",
|
||||
"",
|
||||
"Note that the default will change in a future version of git",
|
||||
"to refuse deleting the current branch unless you have the",
|
||||
"configuration variable set to either 'ignore' or 'warn'."
|
||||
};
|
||||
|
||||
static void warn_unconfigured_deny_delete_current(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0;
|
||||
i < ARRAY_SIZE(warn_unconfigured_deny_delete_current_msg);
|
||||
i++)
|
||||
warning("%s", warn_unconfigured_deny_delete_current_msg[i]);
|
||||
}
|
||||
|
||||
static const char *update(struct command *cmd)
|
||||
@@ -278,12 +307,30 @@ static const char *update(struct command *cmd)
|
||||
"but I can't find it!", sha1_to_hex(new_sha1));
|
||||
return "bad pack";
|
||||
}
|
||||
if (deny_deletes && is_null_sha1(new_sha1) &&
|
||||
!is_null_sha1(old_sha1) &&
|
||||
!prefixcmp(name, "refs/heads/")) {
|
||||
error("denying ref deletion for %s", name);
|
||||
return "deletion prohibited";
|
||||
|
||||
if (!is_null_sha1(old_sha1) && is_null_sha1(new_sha1)) {
|
||||
if (deny_deletes && !prefixcmp(name, "refs/heads/")) {
|
||||
error("denying ref deletion for %s", name);
|
||||
return "deletion prohibited";
|
||||
}
|
||||
|
||||
if (!strcmp(name, head_name)) {
|
||||
switch (deny_delete_current) {
|
||||
case DENY_IGNORE:
|
||||
break;
|
||||
case DENY_WARN:
|
||||
case DENY_UNCONFIGURED:
|
||||
if (deny_delete_current == DENY_UNCONFIGURED)
|
||||
warn_unconfigured_deny_delete_current();
|
||||
warning("deleting the current branch");
|
||||
break;
|
||||
case DENY_REFUSE:
|
||||
error("refusing to delete the current branch: %s", name);
|
||||
return "deletion of the current branch prohibited";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (deny_non_fast_forwards && !is_null_sha1(new_sha1) &&
|
||||
!is_null_sha1(old_sha1) &&
|
||||
!prefixcmp(name, "refs/heads/")) {
|
||||
@@ -377,6 +424,7 @@ static void run_update_post_hook(struct command *cmd)
|
||||
static void execute_commands(const char *unpacker_error)
|
||||
{
|
||||
struct command *cmd = commands;
|
||||
unsigned char sha1[20];
|
||||
|
||||
if (unpacker_error) {
|
||||
while (cmd) {
|
||||
@@ -394,6 +442,8 @@ static void execute_commands(const char *unpacker_error)
|
||||
return;
|
||||
}
|
||||
|
||||
head_name = resolve_ref("HEAD", sha1, 0, NULL);
|
||||
|
||||
while (cmd) {
|
||||
cmd->error_string = update(cmd);
|
||||
cmd = cmd->next;
|
||||
|
||||
@@ -756,12 +756,17 @@ static int prune(int argc, const char **argv)
|
||||
OPT_END()
|
||||
};
|
||||
struct ref_states states;
|
||||
const char *dangling_msg;
|
||||
|
||||
argc = parse_options(argc, argv, options, builtin_remote_usage, 0);
|
||||
|
||||
if (argc < 1)
|
||||
usage_with_options(builtin_remote_usage, options);
|
||||
|
||||
dangling_msg = (dry_run
|
||||
? " %s will become dangling!\n"
|
||||
: " %s has become dangling!\n");
|
||||
|
||||
memset(&states, 0, sizeof(states));
|
||||
for (; argc; argc--, argv++) {
|
||||
int i;
|
||||
@@ -784,6 +789,7 @@ static int prune(int argc, const char **argv)
|
||||
|
||||
printf(" * [%s] %s\n", dry_run ? "would prune" : "pruned",
|
||||
abbrev_ref(refname, "refs/remotes/"));
|
||||
warn_dangling_symref(dangling_msg, refname);
|
||||
}
|
||||
|
||||
/* NEEDSWORK: free remote */
|
||||
|
||||
@@ -608,6 +608,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
|
||||
if (!strcmp(arg, "--bisect-all")) {
|
||||
bisect_list = 1;
|
||||
bisect_find_all = 1;
|
||||
revs.show_decorations = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--bisect-vars")) {
|
||||
|
||||
@@ -223,17 +223,6 @@ static char *help_msg(const unsigned char *sha1)
|
||||
return helpbuf;
|
||||
}
|
||||
|
||||
static int index_is_dirty(void)
|
||||
{
|
||||
struct rev_info rev;
|
||||
init_revisions(&rev, NULL);
|
||||
setup_revisions(0, NULL, &rev, "HEAD");
|
||||
DIFF_OPT_SET(&rev.diffopt, QUIET);
|
||||
DIFF_OPT_SET(&rev.diffopt, EXIT_WITH_STATUS);
|
||||
run_diff_index(&rev, 1);
|
||||
return !!DIFF_OPT_TST(&rev.diffopt, HAS_CHANGES);
|
||||
}
|
||||
|
||||
static struct tree *empty_tree(void)
|
||||
{
|
||||
struct tree *tree = xcalloc(1, sizeof(struct tree));
|
||||
@@ -279,7 +268,7 @@ static int revert_or_cherry_pick(int argc, const char **argv)
|
||||
} else {
|
||||
if (get_sha1("HEAD", head))
|
||||
die ("You do not have a valid HEAD");
|
||||
if (index_is_dirty())
|
||||
if (index_differs_from("HEAD", 0))
|
||||
die ("Dirty index: cannot %s", me);
|
||||
}
|
||||
discard_cache();
|
||||
|
||||
@@ -40,6 +40,7 @@ static void insert_one_record(struct shortlog *log,
|
||||
char *buffer, *p;
|
||||
struct string_list_item *item;
|
||||
char namebuf[1024];
|
||||
char emailbuf[1024];
|
||||
size_t len;
|
||||
const char *eol;
|
||||
const char *boemail, *eoemail;
|
||||
@@ -51,7 +52,19 @@ static void insert_one_record(struct shortlog *log,
|
||||
eoemail = strchr(boemail, '>');
|
||||
if (!eoemail)
|
||||
return;
|
||||
if (!map_email(&log->mailmap, boemail+1, namebuf, sizeof(namebuf))) {
|
||||
|
||||
/* copy author name to namebuf, to support matching on both name and email */
|
||||
memcpy(namebuf, author, boemail - author);
|
||||
len = boemail - author;
|
||||
while(len > 0 && isspace(namebuf[len-1]))
|
||||
len--;
|
||||
namebuf[len] = 0;
|
||||
|
||||
/* copy email name to emailbuf, to allow email replacement as well */
|
||||
memcpy(emailbuf, boemail+1, eoemail - boemail);
|
||||
emailbuf[eoemail - boemail - 1] = 0;
|
||||
|
||||
if (!map_user(&log->mailmap, emailbuf, sizeof(emailbuf), namebuf, sizeof(namebuf))) {
|
||||
while (author < boemail && isspace(*author))
|
||||
author++;
|
||||
for (len = 0;
|
||||
@@ -67,8 +80,8 @@ static void insert_one_record(struct shortlog *log,
|
||||
|
||||
if (log->email) {
|
||||
size_t room = sizeof(namebuf) - len - 1;
|
||||
int maillen = eoemail - boemail + 1;
|
||||
snprintf(namebuf + len, room, " %.*s", maillen, boemail);
|
||||
int maillen = strlen(emailbuf);
|
||||
snprintf(namebuf + len, room, " <%.*s>", maillen, emailbuf);
|
||||
}
|
||||
|
||||
item = string_list_insert(namebuf, &log->list);
|
||||
@@ -219,7 +232,7 @@ void shortlog_init(struct shortlog *log)
|
||||
{
|
||||
memset(log, 0, sizeof(*log));
|
||||
|
||||
read_mailmap(&log->mailmap, ".mailmap", &log->common_repo_prefix);
|
||||
read_mailmap(&log->mailmap, &log->common_repo_prefix);
|
||||
|
||||
log->list.strdup_strings = 1;
|
||||
log->wrap = DEFAULT_WRAPLEN;
|
||||
@@ -248,6 +261,7 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix)
|
||||
struct parse_opt_ctx_t ctx;
|
||||
|
||||
prefix = setup_git_directory_gently(&nongit);
|
||||
git_config(git_default_config, NULL);
|
||||
shortlog_init(&log);
|
||||
init_revisions(&rev, prefix);
|
||||
parse_options_start(&ctx, argc, argv, PARSE_OPT_KEEP_DASHDASH |
|
||||
@@ -320,6 +334,5 @@ void shortlog_output(struct shortlog *log)
|
||||
|
||||
log->list.strdup_strings = 1;
|
||||
string_list_clear(&log->list, 1);
|
||||
log->mailmap.strdup_strings = 1;
|
||||
string_list_clear(&log->mailmap, 1);
|
||||
clear_mailmap(&log->mailmap);
|
||||
}
|
||||
|
||||
@@ -45,8 +45,8 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
|
||||
break;
|
||||
case 2:
|
||||
if (!strcmp(argv[0], "HEAD") &&
|
||||
prefixcmp(argv[1], "refs/heads/"))
|
||||
die("Refusing to point HEAD outside of refs/heads/");
|
||||
prefixcmp(argv[1], "refs/"))
|
||||
die("Refusing to point HEAD outside of refs/");
|
||||
create_symref(argv[0], argv[1], msg);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -742,8 +742,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
|
||||
if (newfd < 0) {
|
||||
if (refresh_flags & REFRESH_QUIET)
|
||||
exit(128);
|
||||
die("unable to create '%s.lock': %s",
|
||||
get_index_file(), strerror(lock_error));
|
||||
unable_to_lock_index_die(get_index_file(), lock_error);
|
||||
}
|
||||
if (write_cache(newfd, active_cache, active_nr) ||
|
||||
commit_locked_index(lock_file))
|
||||
|
||||
11
cache.h
11
cache.h
@@ -371,8 +371,6 @@ static inline enum object_type object_type(unsigned int mode)
|
||||
#define GITATTRIBUTES_FILE ".gitattributes"
|
||||
#define INFOATTRIBUTES_FILE "info/attributes"
|
||||
#define ATTRIBUTE_MACRO_PREFIX "[attr]"
|
||||
#define GIT_NOTES_REF_ENVIRONMENT "GIT_NOTES_REF"
|
||||
#define GIT_NOTES_DEFAULT_REF "refs/notes/commits"
|
||||
|
||||
extern int is_bare_repository_cfg;
|
||||
extern int is_bare_repository(void);
|
||||
@@ -486,6 +484,7 @@ struct lock_file {
|
||||
};
|
||||
#define LOCK_DIE_ON_ERROR 1
|
||||
#define LOCK_NODEREF 2
|
||||
extern NORETURN void unable_to_lock_index_die(const char *path, int err);
|
||||
extern int hold_lock_file_for_update(struct lock_file *, const char *path, int);
|
||||
extern int hold_lock_file_for_append(struct lock_file *, const char *path, int);
|
||||
extern int commit_lock_file(struct lock_file *);
|
||||
@@ -544,7 +543,6 @@ enum rebase_setup_type {
|
||||
|
||||
extern enum branch_track git_branch_track;
|
||||
extern enum rebase_setup_type autorebase;
|
||||
extern char *notes_ref_name;
|
||||
|
||||
#define GIT_REPO_VERSION 0
|
||||
extern int repository_format_version;
|
||||
@@ -627,7 +625,7 @@ int is_directory(const char *);
|
||||
const char *make_absolute_path(const char *path);
|
||||
const char *make_nonrelative_path(const char *path);
|
||||
const char *make_relative_path(const char *abs, const char *base);
|
||||
int normalize_absolute_path(char *buf, const char *path);
|
||||
int normalize_path_copy(char *dst, const char *src);
|
||||
int longest_ancestor_length(const char *path, const char *prefix_list);
|
||||
char *strip_path_suffix(const char *path, const char *suffix);
|
||||
|
||||
@@ -698,7 +696,8 @@ enum date_mode {
|
||||
DATE_SHORT,
|
||||
DATE_LOCAL,
|
||||
DATE_ISO8601,
|
||||
DATE_RFC2822
|
||||
DATE_RFC2822,
|
||||
DATE_RAW
|
||||
};
|
||||
|
||||
const char *show_date(unsigned long time, int timezone, enum date_mode mode);
|
||||
@@ -831,6 +830,7 @@ extern unsigned char* use_pack(struct packed_git *, struct pack_window **, off_t
|
||||
extern void close_pack_windows(struct packed_git *);
|
||||
extern void unuse_pack(struct pack_window **);
|
||||
extern void free_pack_by_name(const char *);
|
||||
extern void clear_delta_base_cache(void);
|
||||
extern struct packed_git *add_packed_git(const char *, int, int);
|
||||
extern const unsigned char *nth_packed_object_sha1(struct packed_git *, uint32_t);
|
||||
extern off_t nth_packed_object_offset(const struct packed_git *, uint32_t);
|
||||
@@ -871,6 +871,7 @@ extern int user_ident_explicitly_given;
|
||||
|
||||
extern const char *git_commit_encoding;
|
||||
extern const char *git_log_output_encoding;
|
||||
extern const char *git_mailmap_file;
|
||||
|
||||
/* IO helper functions */
|
||||
extern void maybe_flush_or_die(FILE *, const char *);
|
||||
|
||||
@@ -73,7 +73,6 @@ git-mktag plumbingmanipulators
|
||||
git-mktree plumbingmanipulators
|
||||
git-mv mainporcelain common
|
||||
git-name-rev plumbinginterrogators
|
||||
git-notes mainporcelain
|
||||
git-pack-objects plumbingmanipulators
|
||||
git-pack-redundant plumbinginterrogators
|
||||
git-pack-refs ancillarymanipulators
|
||||
|
||||
1
commit.c
1
commit.c
@@ -5,7 +5,6 @@
|
||||
#include "utf8.h"
|
||||
#include "diff.h"
|
||||
#include "revision.h"
|
||||
#include "notes.h"
|
||||
|
||||
int save_commit_buffer = 1;
|
||||
|
||||
|
||||
17
config.c
17
config.c
@@ -469,11 +469,6 @@ static int git_default_core_config(const char *var, const char *value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(var, "core.notesref")) {
|
||||
notes_ref_name = xstrdup(value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(var, "core.pager"))
|
||||
return git_config_string(&pager_program, var, value);
|
||||
|
||||
@@ -570,6 +565,15 @@ static int git_default_branch_config(const char *var, const char *value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int git_default_mailmap_config(const char *var, const char *value)
|
||||
{
|
||||
if (!strcmp(var, "mailmap.file"))
|
||||
return git_config_string(&git_mailmap_file, var, value);
|
||||
|
||||
/* Add other config variables here and to Documentation/config.txt. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_default_config(const char *var, const char *value, void *dummy)
|
||||
{
|
||||
if (!prefixcmp(var, "core."))
|
||||
@@ -584,6 +588,9 @@ int git_default_config(const char *var, const char *value, void *dummy)
|
||||
if (!prefixcmp(var, "branch."))
|
||||
return git_default_branch_config(var, value);
|
||||
|
||||
if (!prefixcmp(var, "mailmap."))
|
||||
return git_default_mailmap_config(var, value);
|
||||
|
||||
if (!strcmp(var, "pager.color") || !strcmp(var, "color.pager")) {
|
||||
pager_use_color = git_config_bool(var,value);
|
||||
return 0;
|
||||
|
||||
@@ -34,11 +34,11 @@
|
||||
# are currently in a git repository. The %s token will be
|
||||
# the name of the current branch.
|
||||
#
|
||||
# In addition, if you set GIT_PS1_SHOWDIRTYSTATE to a nonempty
|
||||
# value, unstaged (*) and staged (+) changes will be shown next
|
||||
# to the branch name. You can configure this per-repository
|
||||
# with the bash.showDirtyState variable, which defaults to true
|
||||
# once GIT_PS1_SHOWDIRTYSTATE is enabled.
|
||||
# In addition, if you set GIT_PS1_SHOWDIRTYSTATE to a nonempty
|
||||
# value, unstaged (*) and staged (+) changes will be shown next
|
||||
# to the branch name. You can configure this per-repository
|
||||
# with the bash.showDirtyState variable, which defaults to true
|
||||
# once GIT_PS1_SHOWDIRTYSTATE is enabled.
|
||||
#
|
||||
# To submit patches:
|
||||
#
|
||||
@@ -125,7 +125,7 @@ __git_ps1 ()
|
||||
local w
|
||||
local i
|
||||
|
||||
if test -n "$GIT_PS1_SHOWDIRTYSTATE"; then
|
||||
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="*"
|
||||
@@ -975,6 +975,27 @@ _git_ls_tree ()
|
||||
__git_complete_file
|
||||
}
|
||||
|
||||
# Options that go well for log, shortlog and gitk
|
||||
__git_log_common_options="
|
||||
--not --all
|
||||
--branches --tags --remotes
|
||||
--first-parent --no-merges
|
||||
--max-count=
|
||||
--max-age= --since= --after=
|
||||
--min-age= --until= --before=
|
||||
"
|
||||
# Options that go well for log and gitk (not shortlog)
|
||||
__git_log_gitk_options="
|
||||
--dense --sparse --full-history
|
||||
--simplify-merges --simplify-by-decoration
|
||||
--left-right
|
||||
"
|
||||
# Options that go well for log and shortlog (not gitk)
|
||||
__git_log_shortlog_options="
|
||||
--author= --committer= --grep=
|
||||
--all-match
|
||||
"
|
||||
|
||||
__git_log_pretty_formats="oneline short medium full fuller email raw format:"
|
||||
|
||||
_git_log ()
|
||||
@@ -982,6 +1003,11 @@ _git_log ()
|
||||
__git_has_doubledash && return
|
||||
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
local g="$(git rev-parse --git-dir 2>/dev/null)"
|
||||
local merge=""
|
||||
if [ -f $g/MERGE_HEAD ]; then
|
||||
merge="--merge"
|
||||
fi
|
||||
case "$cur" in
|
||||
--pretty=*)
|
||||
__gitcomp "$__git_log_pretty_formats
|
||||
@@ -996,22 +1022,20 @@ _git_log ()
|
||||
;;
|
||||
--*)
|
||||
__gitcomp "
|
||||
--max-count= --max-age= --since= --after=
|
||||
--min-age= --before= --until=
|
||||
$__git_log_common_options
|
||||
$__git_log_shortlog_options
|
||||
$__git_log_gitk_options
|
||||
--root --topo-order --date-order --reverse
|
||||
--no-merges --follow
|
||||
--follow
|
||||
--abbrev-commit --abbrev=
|
||||
--relative-date --date=
|
||||
--author= --committer= --grep=
|
||||
--all-match
|
||||
--pretty=
|
||||
--not --all
|
||||
--left-right --cherry-pick
|
||||
--cherry-pick
|
||||
--graph
|
||||
--decorate
|
||||
--walk-reflogs
|
||||
--parents --children --full-history
|
||||
--merge
|
||||
--parents --children
|
||||
$merge
|
||||
$__git_diff_common_options
|
||||
--pickaxe-all --pickaxe-regex
|
||||
"
|
||||
@@ -1037,6 +1061,7 @@ _git_merge ()
|
||||
--*)
|
||||
__gitcomp "
|
||||
--no-commit --no-stat --log --no-log --squash --strategy
|
||||
--commit --stat --no-squash --ff --no-ff
|
||||
"
|
||||
return
|
||||
esac
|
||||
@@ -1196,10 +1221,14 @@ _git_config ()
|
||||
__gitcomp "$(__git_merge_strategies)"
|
||||
return
|
||||
;;
|
||||
color.branch|color.diff|color.status)
|
||||
color.branch|color.diff|color.interactive|color.status|color.ui)
|
||||
__gitcomp "always never auto"
|
||||
return
|
||||
;;
|
||||
color.pager)
|
||||
__gitcomp "false true"
|
||||
return
|
||||
;;
|
||||
color.*.*)
|
||||
__gitcomp "
|
||||
normal black red green yellow blue magenta cyan white
|
||||
@@ -1491,12 +1520,8 @@ _git_shortlog ()
|
||||
case "$cur" in
|
||||
--*)
|
||||
__gitcomp "
|
||||
--max-count= --max-age= --since= --after=
|
||||
--min-age= --before= --until=
|
||||
--no-merges
|
||||
--author= --committer= --grep=
|
||||
--all-match
|
||||
--not --all
|
||||
$__git_log_common_options
|
||||
$__git_log_shortlog_options
|
||||
--numbered --summary
|
||||
"
|
||||
return
|
||||
@@ -1595,7 +1620,8 @@ _git_svn ()
|
||||
local subcommands="
|
||||
init fetch clone rebase dcommit log find-rev
|
||||
set-tree commit-diff info create-ignore propget
|
||||
proplist show-ignore show-externals
|
||||
proplist show-ignore show-externals branch tag blame
|
||||
migrate
|
||||
"
|
||||
local subcommand="$(__git_find_subcommand "$subcommands")"
|
||||
if [ -z "$subcommand" ]; then
|
||||
@@ -1606,13 +1632,15 @@ _git_svn ()
|
||||
--follow-parent --authors-file= --repack=
|
||||
--no-metadata --use-svm-props --use-svnsync-props
|
||||
--log-window-size= --no-checkout --quiet
|
||||
--repack-flags --user-log-author --localtime $remote_opts
|
||||
--repack-flags --use-log-author --localtime
|
||||
--ignore-paths= $remote_opts
|
||||
"
|
||||
local init_opts="
|
||||
--template= --shared= --trunk= --tags=
|
||||
--branches= --stdlayout --minimize-url
|
||||
--no-metadata --use-svm-props --use-svnsync-props
|
||||
--rewrite-root= $remote_opts
|
||||
--rewrite-root= --prefix= --use-log-author
|
||||
--add-author-from $remote_opts
|
||||
"
|
||||
local cmt_opts="
|
||||
--edit --rmdir --find-copies-harder --copy-similarity=
|
||||
@@ -1632,7 +1660,8 @@ _git_svn ()
|
||||
dcommit,--*)
|
||||
__gitcomp "
|
||||
--merge --strategy= --verbose --dry-run
|
||||
--fetch-all --no-rebase $cmt_opts $fc_opts
|
||||
--fetch-all --no-rebase --commit-url
|
||||
--revision $cmt_opts $fc_opts
|
||||
"
|
||||
;;
|
||||
set-tree,--*)
|
||||
@@ -1646,13 +1675,13 @@ _git_svn ()
|
||||
__gitcomp "
|
||||
--limit= --revision= --verbose --incremental
|
||||
--oneline --show-commit --non-recursive
|
||||
--authors-file=
|
||||
--authors-file= --color
|
||||
"
|
||||
;;
|
||||
rebase,--*)
|
||||
__gitcomp "
|
||||
--merge --verbose --strategy= --local
|
||||
--fetch-all $fc_opts
|
||||
--fetch-all --dry-run $fc_opts
|
||||
"
|
||||
;;
|
||||
commit-diff,--*)
|
||||
@@ -1661,6 +1690,21 @@ _git_svn ()
|
||||
info,--*)
|
||||
__gitcomp "--url"
|
||||
;;
|
||||
branch,--*)
|
||||
__gitcomp "--dry-run --message --tag"
|
||||
;;
|
||||
tag,--*)
|
||||
__gitcomp "--dry-run --message"
|
||||
;;
|
||||
blame,--*)
|
||||
__gitcomp "--git-format"
|
||||
;;
|
||||
migrate,--*)
|
||||
__gitcomp "
|
||||
--config-dir= --ignore-paths= --minimize
|
||||
--no-auth-cache --username=
|
||||
"
|
||||
;;
|
||||
*)
|
||||
COMPREPLY=()
|
||||
;;
|
||||
@@ -1804,7 +1848,11 @@ _gitk ()
|
||||
fi
|
||||
case "$cur" in
|
||||
--*)
|
||||
__gitcomp "--not --all $merge"
|
||||
__gitcomp "
|
||||
$__git_log_common_options
|
||||
$__git_log_gitk_options
|
||||
$merge
|
||||
"
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
EMACS = emacs
|
||||
|
||||
ELC = git.elc vc-git.elc git-blame.elc
|
||||
ELC = git.elc git-blame.elc
|
||||
INSTALL ?= install
|
||||
INSTALL_ELC = $(INSTALL) -m 644
|
||||
prefix ?= $(HOME)
|
||||
|
||||
39
contrib/emacs/README
Normal file
39
contrib/emacs/README
Normal file
@@ -0,0 +1,39 @@
|
||||
This directory contains various modules for Emacs support.
|
||||
|
||||
To make the modules available to Emacs, you should add this directory
|
||||
to your load-path, and then require the modules you want. This can be
|
||||
done by adding to your .emacs something like this:
|
||||
|
||||
(add-to-list 'load-path ".../git/contrib/emacs")
|
||||
(require 'git)
|
||||
(require 'git-blame)
|
||||
|
||||
|
||||
The following modules are available:
|
||||
|
||||
* git.el:
|
||||
|
||||
Status manager that displays the state of all the files of the
|
||||
project, and provides easy access to the most frequently used git
|
||||
commands. The user interface is as far as possible compatible with
|
||||
the pcl-cvs mode. It can be started with `M-x git-status'.
|
||||
|
||||
* git-blame.el:
|
||||
|
||||
Emacs implementation of incremental git-blame. When you turn it on
|
||||
while viewing a file, the editor buffer will be updated by setting
|
||||
the background of individual lines to a color that reflects which
|
||||
commit it comes from. And when you move around the buffer, a
|
||||
one-line summary will be shown in the echo area.
|
||||
|
||||
* vc-git.el:
|
||||
|
||||
This file used to contain the VC-mode backend for git, but it is no
|
||||
longer distributed with git. It is now maintained as part of Emacs
|
||||
and included in standard Emacs distributions starting from version
|
||||
22.2.
|
||||
|
||||
If you have an earlier Emacs version, upgrading to Emacs 22 is
|
||||
recommended, since the VC mode in older Emacs is not generic enough
|
||||
to be able to support git in a reasonable manner, and no attempt has
|
||||
been made to backport vc-git.el.
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; git.el --- A user interface for git
|
||||
|
||||
;; Copyright (C) 2005, 2006, 2007 Alexandre Julliard <julliard@winehq.org>
|
||||
;; Copyright (C) 2005, 2006, 2007, 2008, 2009 Alexandre Julliard <julliard@winehq.org>
|
||||
|
||||
;; Version: 1.0
|
||||
|
||||
@@ -34,15 +34,21 @@
|
||||
;; To start: `M-x git-status'
|
||||
;;
|
||||
;; TODO
|
||||
;; - portability to XEmacs
|
||||
;; - diff against other branch
|
||||
;; - renaming files from the status buffer
|
||||
;; - creating tags
|
||||
;; - fetch/pull
|
||||
;; - switching branches
|
||||
;; - revlist browser
|
||||
;; - git-show-branch browser
|
||||
;; - menus
|
||||
;;
|
||||
|
||||
;;; Compatibility:
|
||||
;;
|
||||
;; This file works on GNU Emacs 21 or later. It may work on older
|
||||
;; versions but this is not guaranteed.
|
||||
;;
|
||||
;; It may work on XEmacs 21, provided that you first install the ewoc
|
||||
;; and log-edit packages.
|
||||
;;
|
||||
|
||||
(eval-when-compile (require 'cl))
|
||||
@@ -222,7 +228,7 @@ the process output as a string, or nil if the git command failed."
|
||||
(with-current-buffer buffer
|
||||
(cd dir)
|
||||
(apply #'call-process-region start end program
|
||||
nil (list output-buffer nil) nil args))))
|
||||
nil (list output-buffer t) nil args))))
|
||||
|
||||
(defun git-run-command-buffer (buffer-name &rest args)
|
||||
"Run a git command, sending the output to a buffer named BUFFER-NAME."
|
||||
@@ -239,13 +245,15 @@ the process output as a string, or nil if the git command failed."
|
||||
|
||||
(defun git-run-command-region (buffer start end env &rest args)
|
||||
"Run a git command with specified buffer region as input."
|
||||
(unless (eq 0 (if env
|
||||
(git-run-process-region
|
||||
buffer start end "env"
|
||||
(append (git-get-env-strings env) (list "git") args))
|
||||
(with-temp-buffer
|
||||
(if (eq 0 (if env
|
||||
(git-run-process-region
|
||||
buffer start end "git" args)))
|
||||
(error "Failed to run \"git %s\":\n%s" (mapconcat (lambda (x) x) args " ") (buffer-string))))
|
||||
buffer start end "env"
|
||||
(append (git-get-env-strings env) (list "git") args))
|
||||
(git-run-process-region buffer start end "git" args)))
|
||||
(buffer-string)
|
||||
(display-message-or-buffer (current-buffer))
|
||||
nil)))
|
||||
|
||||
(defun git-run-hook (hook env &rest args)
|
||||
"Run a git hook and display its output if any."
|
||||
@@ -397,6 +405,17 @@ the process output as a string, or nil if the git command failed."
|
||||
(unless newval (push "-d" args))
|
||||
(apply 'git-call-process-display-error "update-ref" args)))
|
||||
|
||||
(defun git-for-each-ref (&rest specs)
|
||||
"Return a list of refs using git-for-each-ref.
|
||||
Each entry is a cons of (SHORT-NAME . FULL-NAME)."
|
||||
(let (refs)
|
||||
(with-temp-buffer
|
||||
(apply #'git-call-process t "for-each-ref" "--format=%(refname)" specs)
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "^[^/\n]+/[^/\n]+/\\(.+\\)$" nil t)
|
||||
(push (cons (match-string 1) (match-string 0)) refs)))
|
||||
(nreverse refs)))
|
||||
|
||||
(defun git-read-tree (tree &optional index-file)
|
||||
"Read a tree into the index file."
|
||||
(let ((process-environment
|
||||
@@ -447,18 +466,16 @@ the process output as a string, or nil if the git command failed."
|
||||
(setq coding-system-for-write buffer-file-coding-system))
|
||||
(let ((commit
|
||||
(git-get-string-sha1
|
||||
(with-output-to-string
|
||||
(with-current-buffer standard-output
|
||||
(let ((env `(("GIT_AUTHOR_NAME" . ,author-name)
|
||||
("GIT_AUTHOR_EMAIL" . ,author-email)
|
||||
("GIT_COMMITTER_NAME" . ,(git-get-committer-name))
|
||||
("GIT_COMMITTER_EMAIL" . ,(git-get-committer-email)))))
|
||||
(when author-date (push `("GIT_AUTHOR_DATE" . ,author-date) env))
|
||||
(apply #'git-run-command-region
|
||||
buffer log-start log-end env
|
||||
"commit-tree" tree (nreverse args))))))))
|
||||
(and (git-update-ref "HEAD" commit head subject)
|
||||
commit))))
|
||||
(let ((env `(("GIT_AUTHOR_NAME" . ,author-name)
|
||||
("GIT_AUTHOR_EMAIL" . ,author-email)
|
||||
("GIT_COMMITTER_NAME" . ,(git-get-committer-name))
|
||||
("GIT_COMMITTER_EMAIL" . ,(git-get-committer-email)))))
|
||||
(when author-date (push `("GIT_AUTHOR_DATE" . ,author-date) env))
|
||||
(apply #'git-run-command-region
|
||||
buffer log-start log-end env
|
||||
"commit-tree" tree (nreverse args))))))
|
||||
(when commit (git-update-ref "HEAD" commit head subject))
|
||||
commit)))
|
||||
|
||||
(defun git-empty-db-p ()
|
||||
"Check if the git db is empty (no commit done yet)."
|
||||
@@ -513,9 +530,9 @@ the process output as a string, or nil if the git command failed."
|
||||
(git-fileinfo->needs-refresh info) t)))
|
||||
|
||||
(defun git-status-filenames-map (status func files &rest args)
|
||||
"Apply FUNC to the status files names in the FILES list."
|
||||
"Apply FUNC to the status files names in the FILES list.
|
||||
The list must be sorted."
|
||||
(when files
|
||||
(setq files (sort files #'string-lessp))
|
||||
(let ((file (pop files))
|
||||
(node (ewoc-nth status 0)))
|
||||
(while (and file node)
|
||||
@@ -528,7 +545,7 @@ the process output as a string, or nil if the git command failed."
|
||||
(setq file (pop files))))))))
|
||||
|
||||
(defun git-set-filenames-state (status files state)
|
||||
"Set the state of a list of named files."
|
||||
"Set the state of a list of named files. The list must be sorted"
|
||||
(when files
|
||||
(git-status-filenames-map status #'git-set-fileinfo-state files state)
|
||||
(unless state ;; delete files whose state has been set to nil
|
||||
@@ -562,29 +579,29 @@ the process output as a string, or nil if the git command failed."
|
||||
(let* ((old-type (lsh (or old-perm 0) -9))
|
||||
(new-type (lsh (or new-perm 0) -9))
|
||||
(str (case new-type
|
||||
(?\100 ;; file
|
||||
(64 ;; file
|
||||
(case old-type
|
||||
(?\100 nil)
|
||||
(?\120 " (type change symlink -> file)")
|
||||
(?\160 " (type change subproject -> file)")))
|
||||
(?\120 ;; symlink
|
||||
(64 nil)
|
||||
(80 " (type change symlink -> file)")
|
||||
(112 " (type change subproject -> file)")))
|
||||
(80 ;; symlink
|
||||
(case old-type
|
||||
(?\100 " (type change file -> symlink)")
|
||||
(?\160 " (type change subproject -> symlink)")
|
||||
(64 " (type change file -> symlink)")
|
||||
(112 " (type change subproject -> symlink)")
|
||||
(t " (symlink)")))
|
||||
(?\160 ;; subproject
|
||||
(112 ;; subproject
|
||||
(case old-type
|
||||
(?\100 " (type change file -> subproject)")
|
||||
(?\120 " (type change symlink -> subproject)")
|
||||
(64 " (type change file -> subproject)")
|
||||
(80 " (type change symlink -> subproject)")
|
||||
(t " (subproject)")))
|
||||
(?\110 nil) ;; directory (internal, not a real git state)
|
||||
(?\000 ;; deleted or unknown
|
||||
(72 nil) ;; directory (internal, not a real git state)
|
||||
(0 ;; deleted or unknown
|
||||
(case old-type
|
||||
(?\120 " (symlink)")
|
||||
(?\160 " (subproject)")))
|
||||
(80 " (symlink)")
|
||||
(112 " (subproject)")))
|
||||
(t (format " (unknown type %o)" new-type)))))
|
||||
(cond (str (propertize str 'face 'git-status-face))
|
||||
((eq new-type ?\110) "/")
|
||||
((eq new-type 72) "/")
|
||||
(t ""))))
|
||||
|
||||
(defun git-rename-as-string (info)
|
||||
@@ -733,6 +750,7 @@ Return the list of files that haven't been handled."
|
||||
(let (unmerged-files)
|
||||
(while (re-search-forward "[0-7]\\{6\\} [0-9a-f]\\{40\\} [123]\t\\([^\0]+\\)\0" nil t)
|
||||
(push (match-string 1) unmerged-files))
|
||||
(setq unmerged-files (nreverse unmerged-files)) ;; assume it is sorted already
|
||||
(git-set-filenames-state status unmerged-files 'unmerged))))
|
||||
|
||||
(defun git-get-exclude-files ()
|
||||
@@ -753,17 +771,18 @@ Return the list of files that haven't been handled."
|
||||
(append options (mapcar (lambda (f) (concat "--exclude-from=" f)) exclude-files)))))
|
||||
|
||||
(defun git-update-status-files (&optional files mark-files)
|
||||
"Update the status of FILES from the index."
|
||||
"Update the status of FILES from the index.
|
||||
The FILES list must be sorted."
|
||||
(unless git-status (error "Not in git-status buffer."))
|
||||
;; set the needs-update flag on existing files
|
||||
(if (setq files (sort files #'string-lessp))
|
||||
(if files
|
||||
(git-status-filenames-map
|
||||
git-status (lambda (info) (setf (git-fileinfo->needs-update info) t)) files)
|
||||
(ewoc-map (lambda (info) (setf (git-fileinfo->needs-update info) t) nil) git-status)
|
||||
(git-call-process nil "update-index" "--refresh")
|
||||
(when git-show-uptodate
|
||||
(git-run-ls-files-cached git-status nil 'uptodate)))
|
||||
(let* ((remaining-files
|
||||
(let ((remaining-files
|
||||
(if (git-empty-db-p) ; we need some special handling for an empty db
|
||||
(git-run-ls-files-cached git-status files 'added)
|
||||
(git-run-diff-index git-status files))))
|
||||
@@ -808,13 +827,13 @@ Return the list of files that haven't been handled."
|
||||
(list (ewoc-data (ewoc-locate git-status)))))
|
||||
|
||||
(defun git-marked-files-state (&rest states)
|
||||
"Return marked files that are in the specified states."
|
||||
"Return a sorted list of marked files that are in the specified states."
|
||||
(let ((files (git-marked-files))
|
||||
result)
|
||||
(dolist (info files)
|
||||
(when (memq (git-fileinfo->state info) states)
|
||||
(push info result)))
|
||||
result))
|
||||
(nreverse result)))
|
||||
|
||||
(defun git-refresh-files ()
|
||||
"Refresh all files that need it and clear the needs-refresh flag."
|
||||
@@ -1049,7 +1068,9 @@ Return the list of files that haven't been handled."
|
||||
(unless files
|
||||
(push (file-relative-name (read-file-name "File to remove: " nil nil t)) files))
|
||||
(if (yes-or-no-p
|
||||
(format "Remove %d file%s? " (length files) (if (> (length files) 1) "s" "")))
|
||||
(if (cdr files)
|
||||
(format "Remove %d files? " (length files))
|
||||
(format "Remove %s? " (car files))))
|
||||
(progn
|
||||
(dolist (name files)
|
||||
(ignore-errors
|
||||
@@ -1068,7 +1089,9 @@ Return the list of files that haven't been handled."
|
||||
added modified)
|
||||
(when (and files
|
||||
(yes-or-no-p
|
||||
(format "Revert %d file%s? " (length files) (if (> (length files) 1) "s" ""))))
|
||||
(if (cdr files)
|
||||
(format "Revert %d files? " (length files))
|
||||
(format "Revert %s? " (git-fileinfo->name (car files))))))
|
||||
(dolist (info files)
|
||||
(case (git-fileinfo->state info)
|
||||
('added (push (git-fileinfo->name info) added))
|
||||
@@ -1084,13 +1107,14 @@ Return the list of files that haven't been handled."
|
||||
(or (not added)
|
||||
(apply 'git-call-process-display-error "update-index" "--force-remove" "--" added))
|
||||
(or (not modified)
|
||||
(apply 'git-call-process-display-error "checkout" "HEAD" modified)))))
|
||||
(git-update-status-files (append added modified))
|
||||
(apply 'git-call-process-display-error "checkout" "HEAD" modified))))
|
||||
(names (git-get-filenames files)))
|
||||
(git-update-status-files names)
|
||||
(when ok
|
||||
(dolist (file modified)
|
||||
(let ((buffer (get-file-buffer file)))
|
||||
(when buffer (with-current-buffer buffer (revert-buffer t t t)))))
|
||||
(git-success-message "Reverted" (git-get-filenames files)))))))
|
||||
(git-success-message "Reverted" names))))))
|
||||
|
||||
(defun git-resolve-file ()
|
||||
"Resolve conflicts in marked file(s)."
|
||||
@@ -1320,6 +1344,7 @@ Return the list of files that haven't been handled."
|
||||
(log-edit-diff-function . git-log-edit-diff)) buffer)
|
||||
(log-edit 'git-do-commit nil 'git-log-edit-files buffer))
|
||||
(setq font-lock-keywords (font-lock-compile-keywords git-log-edit-font-lock-keywords))
|
||||
(setq paragraph-separate (concat (regexp-quote git-log-msg-separator) "$\\|Author: \\|Date: \\|Merge: \\|Signed-off-by: \\|\f\\|[ ]*$"))
|
||||
(setq buffer-file-coding-system coding-system)
|
||||
(re-search-forward (regexp-quote (concat git-log-msg-separator "\n")) nil t))))
|
||||
|
||||
@@ -1347,14 +1372,44 @@ Return the list of files that haven't been handled."
|
||||
(mapconcat #'identity msg "\n"))))
|
||||
|
||||
(defun git-get-commit-files (commit)
|
||||
"Retrieve the list of files modified by COMMIT."
|
||||
"Retrieve a sorted list of files modified by COMMIT."
|
||||
(let (files)
|
||||
(with-temp-buffer
|
||||
(git-call-process t "diff-tree" "-m" "-r" "-z" "--name-only" "--no-commit-id" "--root" commit)
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "\\([^\0]*\\)\0" nil t 1)
|
||||
(push (match-string 1) files)))
|
||||
files))
|
||||
(sort files #'string-lessp)))
|
||||
|
||||
(defun git-read-commit-name (prompt &optional default)
|
||||
"Ask for a commit name, with completion for local branch, remote branch and tag."
|
||||
(completing-read prompt
|
||||
(list* "HEAD" "ORIG_HEAD" "FETCH_HEAD" (mapcar #'car (git-for-each-ref)))
|
||||
nil nil nil nil default))
|
||||
|
||||
(defun git-checkout (branch &optional merge)
|
||||
"Checkout a branch, tag, or any commit.
|
||||
Use a prefix arg if git should merge while checking out."
|
||||
(interactive
|
||||
(list (git-read-commit-name "Checkout: ")
|
||||
current-prefix-arg))
|
||||
(unless git-status (error "Not in git-status buffer."))
|
||||
(let ((args (list branch "--")))
|
||||
(when merge (push "-m" args))
|
||||
(when (apply #'git-call-process-display-error "checkout" args)
|
||||
(git-update-status-files))))
|
||||
|
||||
(defun git-branch (branch)
|
||||
"Create a branch from the current HEAD and switch to it."
|
||||
(interactive (list (git-read-commit-name "Branch: ")))
|
||||
(unless git-status (error "Not in git-status buffer."))
|
||||
(if (git-rev-parse (concat "refs/heads/" branch))
|
||||
(if (yes-or-no-p (format "Branch %s already exists, replace it? " branch))
|
||||
(and (git-call-process-display-error "branch" "-f" branch)
|
||||
(git-call-process-display-error "checkout" branch))
|
||||
(message "Canceled."))
|
||||
(git-call-process-display-error "checkout" "-b" branch))
|
||||
(git-refresh-ewoc-hf git-status))
|
||||
|
||||
(defun git-amend-commit ()
|
||||
"Undo the last commit on HEAD, and set things up to commit an
|
||||
@@ -1372,6 +1427,44 @@ amended version of it."
|
||||
(git-setup-commit-buffer commit)
|
||||
(git-commit-file))))
|
||||
|
||||
(defun git-cherry-pick-commit (arg)
|
||||
"Cherry-pick a commit."
|
||||
(interactive (list (git-read-commit-name "Cherry-pick commit: ")))
|
||||
(unless git-status (error "Not in git-status buffer."))
|
||||
(let ((commit (git-rev-parse (concat arg "^0"))))
|
||||
(unless commit (error "Not a valid commit '%s'." arg))
|
||||
(when (git-rev-parse (concat commit "^2"))
|
||||
(error "Cannot cherry-pick a merge commit."))
|
||||
(let ((files (git-get-commit-files commit))
|
||||
(ok (git-call-process-display-error "cherry-pick" "-n" commit)))
|
||||
(git-update-status-files files ok)
|
||||
(with-current-buffer (git-setup-commit-buffer commit)
|
||||
(goto-char (point-min))
|
||||
(if (re-search-forward "^\n*Signed-off-by:" nil t 1)
|
||||
(goto-char (match-beginning 0))
|
||||
(goto-char (point-max)))
|
||||
(insert "(cherry picked from commit " commit ")\n"))
|
||||
(when ok (git-commit-file)))))
|
||||
|
||||
(defun git-revert-commit (arg)
|
||||
"Revert a commit."
|
||||
(interactive (list (git-read-commit-name "Revert commit: ")))
|
||||
(unless git-status (error "Not in git-status buffer."))
|
||||
(let ((commit (git-rev-parse (concat arg "^0"))))
|
||||
(unless commit (error "Not a valid commit '%s'." arg))
|
||||
(when (git-rev-parse (concat commit "^2"))
|
||||
(error "Cannot revert a merge commit."))
|
||||
(let ((files (git-get-commit-files commit))
|
||||
(subject (git-get-commit-description commit))
|
||||
(ok (git-call-process-display-error "revert" "-n" commit)))
|
||||
(git-update-status-files files ok)
|
||||
(when (string-match "^[0-9a-f]+ - \\(.*\\)$" subject)
|
||||
(setq subject (match-string 1 subject)))
|
||||
(git-setup-log-buffer (get-buffer-create "*git-commit*")
|
||||
(git-get-merge-heads) nil nil (format "Revert \"%s\"" subject) nil
|
||||
(format "This reverts commit %s.\n" commit))
|
||||
(when ok (git-commit-file)))))
|
||||
|
||||
(defun git-find-file ()
|
||||
"Visit the current file in its own buffer."
|
||||
(interactive)
|
||||
@@ -1471,6 +1564,10 @@ amended version of it."
|
||||
(define-key map "\M-\C-?" 'git-unmark-all)
|
||||
; the commit submap
|
||||
(define-key commit-map "\C-a" 'git-amend-commit)
|
||||
(define-key commit-map "\C-b" 'git-branch)
|
||||
(define-key commit-map "\C-o" 'git-checkout)
|
||||
(define-key commit-map "\C-p" 'git-cherry-pick-commit)
|
||||
(define-key commit-map "\C-v" 'git-revert-commit)
|
||||
; the diff submap
|
||||
(define-key diff-map "b" 'git-diff-file-base)
|
||||
(define-key diff-map "c" 'git-diff-file-combined)
|
||||
@@ -1491,6 +1588,10 @@ amended version of it."
|
||||
`("Git"
|
||||
["Refresh" git-refresh-status t]
|
||||
["Commit" git-commit-file t]
|
||||
["Checkout..." git-checkout t]
|
||||
["New Branch..." git-branch t]
|
||||
["Cherry-pick Commit..." git-cherry-pick-commit t]
|
||||
["Revert Commit..." git-revert-commit t]
|
||||
("Merge"
|
||||
["Next Unmerged File" git-next-unmerged-file t]
|
||||
["Prev Unmerged File" git-prev-unmerged-file t]
|
||||
|
||||
@@ -1,216 +0,0 @@
|
||||
;;; vc-git.el --- VC backend for the git version control system
|
||||
|
||||
;; Copyright (C) 2006 Alexandre Julliard
|
||||
|
||||
;; This program is free software; you can redistribute it and/or
|
||||
;; modify it under the terms of the GNU General Public License as
|
||||
;; published by the Free Software Foundation; either version 2 of
|
||||
;; the License, or (at your option) any later version.
|
||||
;;
|
||||
;; This program is distributed in the hope that it will be
|
||||
;; useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
;; PURPOSE. See the GNU General Public License for more details.
|
||||
;;
|
||||
;; You should have received a copy of the GNU General Public
|
||||
;; License along with this program; if not, write to the Free
|
||||
;; Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
;; MA 02111-1307 USA
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file contains a VC backend for the git version control
|
||||
;; system.
|
||||
;;
|
||||
;; To install: put this file on the load-path and add GIT to the list
|
||||
;; of supported backends in `vc-handled-backends'; the following line,
|
||||
;; placed in your ~/.emacs, will accomplish this:
|
||||
;;
|
||||
;; (add-to-list 'vc-handled-backends 'GIT)
|
||||
;;
|
||||
;; TODO
|
||||
;; - changelog generation
|
||||
;; - working with revisions other than HEAD
|
||||
;;
|
||||
|
||||
(eval-when-compile (require 'cl))
|
||||
|
||||
(defvar git-commits-coding-system 'utf-8
|
||||
"Default coding system for git commits.")
|
||||
|
||||
(defun vc-git--run-command-string (file &rest args)
|
||||
"Run a git command on FILE and return its output as string."
|
||||
(let* ((ok t)
|
||||
(str (with-output-to-string
|
||||
(with-current-buffer standard-output
|
||||
(unless (eq 0 (apply #'call-process "git" nil '(t nil) nil
|
||||
(append args (list (file-relative-name file)))))
|
||||
(setq ok nil))))))
|
||||
(and ok str)))
|
||||
|
||||
(defun vc-git--run-command (file &rest args)
|
||||
"Run a git command on FILE, discarding any output."
|
||||
(let ((name (file-relative-name file)))
|
||||
(eq 0 (apply #'call-process "git" nil (get-buffer "*Messages") nil (append args (list name))))))
|
||||
|
||||
(defun vc-git-registered (file)
|
||||
"Check whether FILE is registered with git."
|
||||
(with-temp-buffer
|
||||
(let* ((dir (file-name-directory file))
|
||||
(name (file-relative-name file dir)))
|
||||
(and (ignore-errors
|
||||
(when dir (cd dir))
|
||||
(eq 0 (call-process "git" nil '(t nil) nil "ls-files" "-c" "-z" "--" name)))
|
||||
(let ((str (buffer-string)))
|
||||
(and (> (length str) (length name))
|
||||
(string= (substring str 0 (1+ (length name))) (concat name "\0"))))))))
|
||||
|
||||
(defun vc-git-state (file)
|
||||
"git-specific version of `vc-state'."
|
||||
(let ((diff (vc-git--run-command-string file "diff-index" "-z" "HEAD" "--")))
|
||||
(if (and diff (string-match ":[0-7]\\{6\\} [0-7]\\{6\\} [0-9a-f]\\{40\\} [0-9a-f]\\{40\\} [ADMU]\0[^\0]+\0" diff))
|
||||
'edited
|
||||
'up-to-date)))
|
||||
|
||||
(defun vc-git-workfile-version (file)
|
||||
"git-specific version of `vc-workfile-version'."
|
||||
(let ((str (with-output-to-string
|
||||
(with-current-buffer standard-output
|
||||
(call-process "git" nil '(t nil) nil "symbolic-ref" "HEAD")))))
|
||||
(if (string-match "^\\(refs/heads/\\)?\\(.+\\)$" str)
|
||||
(match-string 2 str)
|
||||
str)))
|
||||
|
||||
(defun vc-git-symbolic-commit (commit)
|
||||
"Translate COMMIT string into symbolic form.
|
||||
Returns nil if not possible."
|
||||
(and commit
|
||||
(with-temp-buffer
|
||||
(and
|
||||
(zerop
|
||||
(call-process "git" nil '(t nil) nil "name-rev"
|
||||
"--name-only" "--tags"
|
||||
commit))
|
||||
(goto-char (point-min))
|
||||
(= (forward-line 2) 1)
|
||||
(bolp)
|
||||
(buffer-substring-no-properties (point-min) (1- (point-max)))))))
|
||||
|
||||
(defun vc-git-previous-version (file rev)
|
||||
"git-specific version of `vc-previous-version'."
|
||||
(let ((default-directory (file-name-directory (expand-file-name file)))
|
||||
(file (file-name-nondirectory file)))
|
||||
(vc-git-symbolic-commit
|
||||
(with-temp-buffer
|
||||
(and
|
||||
(zerop
|
||||
(call-process "git" nil '(t nil) nil "rev-list"
|
||||
"-2" rev "--" file))
|
||||
(goto-char (point-max))
|
||||
(bolp)
|
||||
(zerop (forward-line -1))
|
||||
(not (bobp))
|
||||
(buffer-substring-no-properties
|
||||
(point)
|
||||
(1- (point-max))))))))
|
||||
|
||||
(defun vc-git-next-version (file rev)
|
||||
"git-specific version of `vc-next-version'."
|
||||
(let* ((default-directory (file-name-directory
|
||||
(expand-file-name file)))
|
||||
(file (file-name-nondirectory file))
|
||||
(current-rev
|
||||
(with-temp-buffer
|
||||
(and
|
||||
(zerop
|
||||
(call-process "git" nil '(t nil) nil "rev-list"
|
||||
"-1" rev "--" file))
|
||||
(goto-char (point-max))
|
||||
(bolp)
|
||||
(zerop (forward-line -1))
|
||||
(bobp)
|
||||
(buffer-substring-no-properties
|
||||
(point)
|
||||
(1- (point-max)))))))
|
||||
(and current-rev
|
||||
(vc-git-symbolic-commit
|
||||
(with-temp-buffer
|
||||
(and
|
||||
(zerop
|
||||
(call-process "git" nil '(t nil) nil "rev-list"
|
||||
"HEAD" "--" file))
|
||||
(goto-char (point-min))
|
||||
(search-forward current-rev nil t)
|
||||
(zerop (forward-line -1))
|
||||
(buffer-substring-no-properties
|
||||
(point)
|
||||
(progn (forward-line 1) (1- (point))))))))))
|
||||
|
||||
(defun vc-git-revert (file &optional contents-done)
|
||||
"Revert FILE to the version stored in the git repository."
|
||||
(if contents-done
|
||||
(vc-git--run-command file "update-index" "--")
|
||||
(vc-git--run-command file "checkout" "HEAD")))
|
||||
|
||||
(defun vc-git-checkout-model (file)
|
||||
'implicit)
|
||||
|
||||
(defun vc-git-workfile-unchanged-p (file)
|
||||
(let ((sha1 (vc-git--run-command-string file "hash-object" "--"))
|
||||
(head (vc-git--run-command-string file "ls-tree" "-z" "HEAD" "--")))
|
||||
(and head
|
||||
(string-match "[0-7]\\{6\\} blob \\([0-9a-f]\\{40\\}\\)\t[^\0]+\0" head)
|
||||
(string= (car (split-string sha1 "\n")) (match-string 1 head)))))
|
||||
|
||||
(defun vc-git-register (file &optional rev comment)
|
||||
"Register FILE into the git version-control system."
|
||||
(vc-git--run-command file "update-index" "--add" "--"))
|
||||
|
||||
(defun vc-git-print-log (file &optional buffer)
|
||||
(let ((name (file-relative-name file))
|
||||
(coding-system-for-read git-commits-coding-system))
|
||||
(vc-do-command buffer 'async "git" name "rev-list" "--pretty" "HEAD" "--")))
|
||||
|
||||
(defun vc-git-diff (file &optional rev1 rev2 buffer)
|
||||
(let ((name (file-relative-name file))
|
||||
(buf (or buffer "*vc-diff*")))
|
||||
(if (and rev1 rev2)
|
||||
(vc-do-command buf 0 "git" name "diff-tree" "-p" rev1 rev2 "--")
|
||||
(vc-do-command buf 0 "git" name "diff-index" "-p" (or rev1 "HEAD") "--"))
|
||||
; git-diff-index doesn't set exit status like diff does
|
||||
(if (vc-git-workfile-unchanged-p file) 0 1)))
|
||||
|
||||
(defun vc-git-checkin (file rev comment)
|
||||
(let ((coding-system-for-write git-commits-coding-system))
|
||||
(vc-git--run-command file "commit" "-m" comment "--only" "--")))
|
||||
|
||||
(defun vc-git-checkout (file &optional editable rev destfile)
|
||||
(if destfile
|
||||
(let ((fullname (substring
|
||||
(vc-git--run-command-string file "ls-files" "-z" "--full-name" "--")
|
||||
0 -1))
|
||||
(coding-system-for-read 'no-conversion)
|
||||
(coding-system-for-write 'no-conversion))
|
||||
(with-temp-file destfile
|
||||
(eq 0 (call-process "git" nil t nil "cat-file" "blob"
|
||||
(concat (or rev "HEAD") ":" fullname)))))
|
||||
(vc-git--run-command file "checkout" (or rev "HEAD"))))
|
||||
|
||||
(defun vc-git-annotate-command (file buf &optional rev)
|
||||
; FIXME: rev is ignored
|
||||
(let ((name (file-relative-name file)))
|
||||
(call-process "git" nil buf nil "blame" name)))
|
||||
|
||||
(defun vc-git-annotate-time ()
|
||||
(and (re-search-forward "[0-9a-f]+ (.* \\([0-9]+\\)-\\([0-9]+\\)-\\([0-9]+\\) \\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\) \\([-+0-9]+\\) +[0-9]+)" nil t)
|
||||
(vc-annotate-convert-time
|
||||
(apply #'encode-time (mapcar (lambda (match) (string-to-number (match-string match))) '(6 5 4 3 2 1 7))))))
|
||||
|
||||
;; Not really useful since we can't do anything with the revision yet
|
||||
;;(defun vc-annotate-extract-revision-at-line ()
|
||||
;; (save-excursion
|
||||
;; (move-beginning-of-line 1)
|
||||
;; (and (looking-at "[0-9a-f]+")
|
||||
;; (buffer-substring (match-beginning 0) (match-end 0)))))
|
||||
|
||||
(provide 'vc-git)
|
||||
@@ -287,9 +287,9 @@ my $last_rev = "";
|
||||
my $last_branch;
|
||||
my $current_rev = $opt_s || 1;
|
||||
unless(-d $git_dir) {
|
||||
system("git-init");
|
||||
system("git init");
|
||||
die "Cannot init the GIT db at $git_tree: $?\n" if $?;
|
||||
system("git-read-tree");
|
||||
system("git read-tree");
|
||||
die "Cannot init an empty tree: $?\n" if $?;
|
||||
|
||||
$last_branch = $opt_o;
|
||||
@@ -303,7 +303,7 @@ unless(-d $git_dir) {
|
||||
-f "$git_dir/svn2git"
|
||||
or die "'$git_dir/svn2git' does not exist.\n".
|
||||
"You need that file for incremental imports.\n";
|
||||
open(F, "git-symbolic-ref HEAD |") or
|
||||
open(F, "git symbolic-ref HEAD |") or
|
||||
die "Cannot run git-symbolic-ref: $!\n";
|
||||
chomp ($last_branch = <F>);
|
||||
$last_branch = basename($last_branch);
|
||||
@@ -331,7 +331,7 @@ EOM
|
||||
"$git_dir/refs/heads/$opt_o") == 0;
|
||||
|
||||
# populate index
|
||||
system('git-read-tree', $last_rev);
|
||||
system('git', 'read-tree', $last_rev);
|
||||
die "read-tree failed: $?\n" if $?;
|
||||
|
||||
# Get the last import timestamps
|
||||
@@ -399,7 +399,7 @@ sub get_file($$$) {
|
||||
my $pid = open(my $F, '-|');
|
||||
die $! unless defined $pid;
|
||||
if (!$pid) {
|
||||
exec("git-hash-object", "-w", $name)
|
||||
exec("git", "hash-object", "-w", $name)
|
||||
or die "Cannot create object: $!\n";
|
||||
}
|
||||
my $sha = <$F>;
|
||||
@@ -423,7 +423,7 @@ sub get_ignore($$$$$) {
|
||||
my $pid = open(my $F, '-|');
|
||||
die $! unless defined $pid;
|
||||
if (!$pid) {
|
||||
exec("git-hash-object", "-w", $name)
|
||||
exec("git", "hash-object", "-w", $name)
|
||||
or die "Cannot create object: $!\n";
|
||||
}
|
||||
my $sha = <$F>;
|
||||
@@ -547,7 +547,7 @@ sub copy_path($$$$$$$$) {
|
||||
my $pid = open my $f,'-|';
|
||||
die $! unless defined $pid;
|
||||
if (!$pid) {
|
||||
exec("git-ls-tree","-r","-z",$gitrev,$srcpath)
|
||||
exec("git","ls-tree","-r","-z",$gitrev,$srcpath)
|
||||
or die $!;
|
||||
}
|
||||
local $/ = "\0";
|
||||
@@ -634,7 +634,7 @@ sub commit {
|
||||
|
||||
my $rev;
|
||||
if($revision > $opt_s and defined $parent) {
|
||||
open(H,'-|',"git-rev-parse","--verify",$parent);
|
||||
open(H,'-|',"git","rev-parse","--verify",$parent);
|
||||
$rev = <H>;
|
||||
close(H) or do {
|
||||
print STDERR "$revision: cannot find commit '$parent'!\n";
|
||||
@@ -671,7 +671,7 @@ sub commit {
|
||||
unlink($git_index);
|
||||
} elsif ($rev ne $last_rev) {
|
||||
print "Switching from $last_rev to $rev ($branch)\n" if $opt_v;
|
||||
system("git-read-tree", $rev);
|
||||
system("git", "read-tree", $rev);
|
||||
die "read-tree failed for $rev: $?\n" if $?;
|
||||
$last_rev = $rev;
|
||||
}
|
||||
@@ -740,7 +740,7 @@ sub commit {
|
||||
my $pid = open my $F, "-|";
|
||||
die "$!" unless defined $pid;
|
||||
if (!$pid) {
|
||||
exec("git-ls-files", "-z", @o1) or die $!;
|
||||
exec("git", "ls-files", "-z", @o1) or die $!;
|
||||
}
|
||||
@o1 = ();
|
||||
local $/ = "\0";
|
||||
@@ -758,7 +758,7 @@ sub commit {
|
||||
@o2 = @o1;
|
||||
@o1 = ();
|
||||
}
|
||||
system("git-update-index","--force-remove","--",@o2);
|
||||
system("git","update-index","--force-remove","--",@o2);
|
||||
die "Cannot remove files: $?\n" if $?;
|
||||
}
|
||||
}
|
||||
@@ -770,7 +770,7 @@ sub commit {
|
||||
@n2 = @new;
|
||||
@new = ();
|
||||
}
|
||||
system("git-update-index","--add",
|
||||
system("git","update-index","--add",
|
||||
(map { ('--cacheinfo', @$_) } @n2));
|
||||
die "Cannot add files: $?\n" if $?;
|
||||
}
|
||||
@@ -778,7 +778,7 @@ sub commit {
|
||||
my $pid = open(C,"-|");
|
||||
die "Cannot fork: $!" unless defined $pid;
|
||||
unless($pid) {
|
||||
exec("git-write-tree");
|
||||
exec("git","write-tree");
|
||||
die "Cannot exec git-write-tree: $!\n";
|
||||
}
|
||||
chomp(my $tree = <C>);
|
||||
@@ -830,7 +830,7 @@ sub commit {
|
||||
"GIT_COMMITTER_NAME=$committer_name",
|
||||
"GIT_COMMITTER_EMAIL=$committer_email",
|
||||
"GIT_COMMITTER_DATE=".strftime("+0000 %Y-%m-%d %H:%M:%S",gmtime($date)),
|
||||
"git-commit-tree", $tree,@par);
|
||||
"git", "commit-tree", $tree,@par);
|
||||
die "Cannot exec git-commit-tree: $!\n";
|
||||
}
|
||||
$pw->writer();
|
||||
@@ -874,7 +874,7 @@ sub commit {
|
||||
|
||||
$dest =~ tr/_/\./ if $opt_u;
|
||||
|
||||
system('git-tag', '-f', $dest, $cid) == 0
|
||||
system('git', 'tag', '-f', $dest, $cid) == 0
|
||||
or die "Cannot create tag $dest: $!\n";
|
||||
|
||||
print "Created tag '$dest' on '$branch'\n" if $opt_v;
|
||||
@@ -937,7 +937,7 @@ while ($to_rev < $opt_l) {
|
||||
my $pid = fork();
|
||||
die "Fork: $!\n" unless defined $pid;
|
||||
unless($pid) {
|
||||
exec("git-repack", "-d")
|
||||
exec("git", "repack", "-d")
|
||||
or die "Cannot repack: $!\n";
|
||||
}
|
||||
waitpid($pid, 0);
|
||||
@@ -958,7 +958,7 @@ if($orig_branch) {
|
||||
system("cp","$git_dir/refs/heads/$opt_o","$git_dir/refs/heads/master")
|
||||
if $forward_master;
|
||||
unless ($opt_i) {
|
||||
system('git-read-tree', '-m', '-u', 'SVN2GIT_HEAD', 'HEAD');
|
||||
system('git', 'read-tree', '-m', '-u', 'SVN2GIT_HEAD', 'HEAD');
|
||||
die "read-tree failed: $?\n" if $?;
|
||||
}
|
||||
} else {
|
||||
@@ -966,7 +966,7 @@ if($orig_branch) {
|
||||
print "DONE; creating $orig_branch branch\n" if $opt_v and (not defined $opt_l or $opt_l > 0);
|
||||
system("cp","$git_dir/refs/heads/$opt_o","$git_dir/refs/heads/master")
|
||||
unless -f "$git_dir/refs/heads/master";
|
||||
system('git-update-ref', 'HEAD', "$orig_branch");
|
||||
system('git', 'update-ref', 'HEAD', "$orig_branch");
|
||||
unless ($opt_i) {
|
||||
system('git checkout');
|
||||
die "checkout failed: $?\n" if $?;
|
||||
|
||||
@@ -114,9 +114,9 @@ due to SVN memory leaks. (These have been worked around.)
|
||||
-R <repack_each_revs>::
|
||||
Specify how often git repository should be repacked.
|
||||
+
|
||||
The default value is 1000. git-svnimport will do import in chunks of 1000
|
||||
revisions, after each chunk git repository will be repacked. To disable
|
||||
this behavior specify some big value here which is mote than number of
|
||||
The default value is 1000. git-svnimport will do imports in chunks of 1000
|
||||
revisions, after each chunk the git repository will be repacked. To disable
|
||||
this behavior specify some large value here which is greater than the number of
|
||||
revisions to import.
|
||||
|
||||
-P <path_from_trunk>::
|
||||
|
||||
@@ -442,13 +442,14 @@ def p4ChangesForPaths(depotPaths, changeRange):
|
||||
output = p4_read_pipe_lines("changes " + ' '.join (["%s...%s" % (p, changeRange)
|
||||
for p in depotPaths]))
|
||||
|
||||
changes = []
|
||||
changes = {}
|
||||
for line in output:
|
||||
changeNum = line.split(" ")[1]
|
||||
changes.append(int(changeNum))
|
||||
changeNum = int(line.split(" ")[1])
|
||||
changes[changeNum] = True
|
||||
|
||||
changes.sort()
|
||||
return changes
|
||||
changelist = changes.keys()
|
||||
changelist.sort()
|
||||
return changelist
|
||||
|
||||
class Command:
|
||||
def __init__(self):
|
||||
|
||||
@@ -615,7 +615,9 @@ show_new_revisions()
|
||||
revspec=$oldrev..$newrev
|
||||
fi
|
||||
|
||||
git rev-parse --not --branches | grep -v $(git rev-parse $refname) |
|
||||
other_branches=$(git for-each-ref --format='%(refname)' refs/heads/ |
|
||||
grep -F -v $refname)
|
||||
git rev-parse --not $other_branches |
|
||||
if [ -z "$custom_showrev" ]
|
||||
then
|
||||
git rev-list --pretty --stdin $revspec
|
||||
|
||||
7
date.c
7
date.c
@@ -89,6 +89,11 @@ const char *show_date(unsigned long time, int tz, enum date_mode mode)
|
||||
struct tm *tm;
|
||||
static char timebuf[200];
|
||||
|
||||
if (mode == DATE_RAW) {
|
||||
snprintf(timebuf, sizeof(timebuf), "%lu %+05d", time, tz);
|
||||
return timebuf;
|
||||
}
|
||||
|
||||
if (mode == DATE_RELATIVE) {
|
||||
unsigned long diff;
|
||||
struct timeval now;
|
||||
@@ -615,6 +620,8 @@ enum date_mode parse_date_format(const char *format)
|
||||
return DATE_LOCAL;
|
||||
else if (!strcmp(format, "default"))
|
||||
return DATE_NORMAL;
|
||||
else if (!strcmp(format, "raw"))
|
||||
return DATE_RAW;
|
||||
else
|
||||
die("unknown date format %s", format);
|
||||
}
|
||||
|
||||
15
diff-lib.c
15
diff-lib.c
@@ -513,3 +513,18 @@ int do_diff_cache(const unsigned char *tree_sha1, struct diff_options *opt)
|
||||
exit(128);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int index_differs_from(const char *def, int diff_flags)
|
||||
{
|
||||
struct rev_info rev;
|
||||
|
||||
init_revisions(&rev, NULL);
|
||||
setup_revisions(0, NULL, &rev, def);
|
||||
DIFF_OPT_SET(&rev.diffopt, QUIET);
|
||||
DIFF_OPT_SET(&rev.diffopt, EXIT_WITH_STATUS);
|
||||
rev.diffopt.flags |= diff_flags;
|
||||
run_diff_index(&rev, 1);
|
||||
if (rev.pending.alloc)
|
||||
free(rev.pending.objects);
|
||||
return (DIFF_OPT_TST(&rev.diffopt, HAS_CHANGES) != 0);
|
||||
}
|
||||
|
||||
@@ -247,6 +247,7 @@ void diff_no_index(struct rev_info *revs,
|
||||
else
|
||||
revs->diffopt.paths = argv + argc - 2;
|
||||
revs->diffopt.nr_paths = 2;
|
||||
revs->diffopt.skip_stat_unmatch = 1;
|
||||
|
||||
DIFF_OPT_SET(&revs->diffopt, EXIT_WITH_STATUS);
|
||||
DIFF_OPT_SET(&revs->diffopt, NO_INDEX);
|
||||
|
||||
11
diff.c
11
diff.c
@@ -184,11 +184,11 @@ static int remove_tempfile_installed;
|
||||
static void remove_tempfile(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(diff_temp); i++)
|
||||
if (diff_temp[i].name == diff_temp[i].tmp_path) {
|
||||
for (i = 0; i < ARRAY_SIZE(diff_temp); i++) {
|
||||
if (diff_temp[i].name == diff_temp[i].tmp_path)
|
||||
unlink(diff_temp[i].name);
|
||||
diff_temp[i].name = NULL;
|
||||
}
|
||||
diff_temp[i].name = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void remove_tempfile_on_signal(int signo)
|
||||
@@ -2326,15 +2326,12 @@ void diff_setup(struct diff_options *options)
|
||||
options->break_opt = -1;
|
||||
options->rename_limit = -1;
|
||||
options->dirstat_percent = 3;
|
||||
DIFF_OPT_CLR(options, DIRSTAT_CUMULATIVE);
|
||||
options->context = 3;
|
||||
|
||||
options->change = diff_change;
|
||||
options->add_remove = diff_addremove;
|
||||
if (diff_use_color_default > 0)
|
||||
DIFF_OPT_SET(options, COLOR_DIFF);
|
||||
else
|
||||
DIFF_OPT_CLR(options, COLOR_DIFF);
|
||||
options->detect_rename = diff_detect_rename_default;
|
||||
|
||||
if (!diff_mnemonic_prefix) {
|
||||
|
||||
2
diff.h
2
diff.h
@@ -265,4 +265,6 @@ extern int diff_result_code(struct diff_options *, int);
|
||||
|
||||
extern void diff_no_index(struct rev_info *, int, const char **, int, const char *);
|
||||
|
||||
extern int index_differs_from(const char *def, int diff_flags);
|
||||
|
||||
#endif /* DIFF_H */
|
||||
|
||||
@@ -45,7 +45,6 @@ enum rebase_setup_type autorebase = AUTOREBASE_NEVER;
|
||||
|
||||
/* Parallel index stat data preload? */
|
||||
int core_preload_index = 0;
|
||||
char *notes_ref_name;
|
||||
|
||||
/* This is set by setup_git_dir_gently() and/or git_default_config() */
|
||||
char *git_work_tree_cfg;
|
||||
|
||||
@@ -817,9 +817,8 @@ static void start_packfile(void)
|
||||
struct pack_header hdr;
|
||||
int pack_fd;
|
||||
|
||||
snprintf(tmpfile, sizeof(tmpfile),
|
||||
"%s/pack/tmp_pack_XXXXXX", get_object_directory());
|
||||
pack_fd = xmkstemp(tmpfile);
|
||||
pack_fd = odb_mkstemp(tmpfile, sizeof(tmpfile),
|
||||
"pack/tmp_pack_XXXXXX");
|
||||
p = xcalloc(1, sizeof(*p) + strlen(tmpfile) + 2);
|
||||
strcpy(p->pack_name, tmpfile);
|
||||
p->pack_fd = pack_fd;
|
||||
@@ -869,7 +868,7 @@ static char *create_index(void)
|
||||
/* Generate the fan-out array. */
|
||||
c = idx;
|
||||
for (i = 0; i < 256; i++) {
|
||||
struct object_entry **next = c;;
|
||||
struct object_entry **next = c;
|
||||
while (next < last) {
|
||||
if ((*next)->sha1[0] != i)
|
||||
break;
|
||||
@@ -879,9 +878,8 @@ static char *create_index(void)
|
||||
c = next;
|
||||
}
|
||||
|
||||
snprintf(tmpfile, sizeof(tmpfile),
|
||||
"%s/pack/tmp_idx_XXXXXX", get_object_directory());
|
||||
idx_fd = xmkstemp(tmpfile);
|
||||
idx_fd = odb_mkstemp(tmpfile, sizeof(tmpfile),
|
||||
"pack/tmp_idx_XXXXXX");
|
||||
f = sha1fd(idx_fd, tmpfile);
|
||||
sha1write(f, array, 256 * sizeof(int));
|
||||
git_SHA1_Init(&ctx);
|
||||
@@ -907,9 +905,7 @@ static char *keep_pack(char *curr_index_name)
|
||||
chmod(pack_data->pack_name, 0444);
|
||||
chmod(curr_index_name, 0444);
|
||||
|
||||
snprintf(name, sizeof(name), "%s/pack/pack-%s.keep",
|
||||
get_object_directory(), sha1_to_hex(pack_data->sha1));
|
||||
keep_fd = open(name, O_RDWR|O_CREAT|O_EXCL, 0600);
|
||||
keep_fd = odb_pack_keep(name, sizeof(name), pack_data->sha1);
|
||||
if (keep_fd < 0)
|
||||
die("cannot create keep file");
|
||||
write_or_die(keep_fd, keep_msg, strlen(keep_msg));
|
||||
@@ -945,6 +941,7 @@ static void end_packfile(void)
|
||||
{
|
||||
struct packed_git *old_p = pack_data, *new_p;
|
||||
|
||||
clear_delta_base_cache();
|
||||
if (object_count) {
|
||||
char *idx_name;
|
||||
int i;
|
||||
|
||||
@@ -12,6 +12,13 @@ my ($prompt_color, $header_color, $help_color) =
|
||||
$repo->get_color('color.interactive.header', 'bold'),
|
||||
$repo->get_color('color.interactive.help', 'red bold'),
|
||||
) : ();
|
||||
my $error_color = ();
|
||||
if ($menu_use_color) {
|
||||
my $help_color_spec = ($repo->config('color.interactive.help') or
|
||||
'red bold');
|
||||
$error_color = $repo->get_color('color.interactive.error',
|
||||
$help_color_spec);
|
||||
}
|
||||
|
||||
my $diff_use_color = $repo->get_colorbool('color.diff');
|
||||
my ($fraginfo_color) =
|
||||
@@ -33,6 +40,17 @@ my ($diff_new_color) =
|
||||
|
||||
my $normal_color = $repo->get_color("", "reset");
|
||||
|
||||
my $use_readkey = 0;
|
||||
sub ReadMode;
|
||||
sub ReadKey;
|
||||
if ($repo->config_bool("interactive.singlekey")) {
|
||||
eval {
|
||||
require Term::ReadKey;
|
||||
Term::ReadKey->import;
|
||||
$use_readkey = 1;
|
||||
};
|
||||
}
|
||||
|
||||
sub colored {
|
||||
my $color = shift;
|
||||
my $string = join("", @_);
|
||||
@@ -325,6 +343,10 @@ sub highlight_prefix {
|
||||
return "$prompt_color$prefix$normal_color$remainder";
|
||||
}
|
||||
|
||||
sub error_msg {
|
||||
print STDERR colored $error_color, @_;
|
||||
}
|
||||
|
||||
sub list_and_choose {
|
||||
my ($opts, @stuff) = @_;
|
||||
my (@chosen, @return);
|
||||
@@ -420,12 +442,12 @@ sub list_and_choose {
|
||||
else {
|
||||
$bottom = $top = find_unique($choice, @stuff);
|
||||
if (!defined $bottom) {
|
||||
print "Huh ($choice)?\n";
|
||||
error_msg "Huh ($choice)?\n";
|
||||
next TOPLOOP;
|
||||
}
|
||||
}
|
||||
if ($opts->{SINGLETON} && $bottom != $top) {
|
||||
print "Huh ($choice)?\n";
|
||||
error_msg "Huh ($choice)?\n";
|
||||
next TOPLOOP;
|
||||
}
|
||||
for ($i = $bottom-1; $i <= $top-1; $i++) {
|
||||
@@ -758,11 +780,32 @@ sub diff_applies {
|
||||
return close $fh;
|
||||
}
|
||||
|
||||
sub _restore_terminal_and_die {
|
||||
ReadMode 'restore';
|
||||
print "\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
sub prompt_single_character {
|
||||
if ($use_readkey) {
|
||||
local $SIG{TERM} = \&_restore_terminal_and_die;
|
||||
local $SIG{INT} = \&_restore_terminal_and_die;
|
||||
ReadMode 'cbreak';
|
||||
my $key = ReadKey 0;
|
||||
ReadMode 'restore';
|
||||
print "$key" if defined $key;
|
||||
print "\n";
|
||||
return $key;
|
||||
} else {
|
||||
return <STDIN>;
|
||||
}
|
||||
}
|
||||
|
||||
sub prompt_yesno {
|
||||
my ($prompt) = @_;
|
||||
while (1) {
|
||||
print colored $prompt_color, $prompt;
|
||||
my $line = <STDIN>;
|
||||
my $line = prompt_single_character;
|
||||
return 0 if $line =~ /^n/i;
|
||||
return 1 if $line =~ /^y/i;
|
||||
}
|
||||
@@ -893,7 +936,7 @@ sub patch_update_file {
|
||||
print @{$mode->{DISPLAY}};
|
||||
print colored $prompt_color,
|
||||
"Stage mode change [y/n/a/d/?]? ";
|
||||
my $line = <STDIN>;
|
||||
my $line = prompt_single_character;
|
||||
if ($line =~ /^y/i) {
|
||||
$mode->{USE} = 1;
|
||||
last;
|
||||
@@ -966,7 +1009,7 @@ sub patch_update_file {
|
||||
print;
|
||||
}
|
||||
print colored $prompt_color, "Stage this hunk [y,n,a,d,/$other,?]? ";
|
||||
my $line = <STDIN>;
|
||||
my $line = prompt_single_character;
|
||||
if ($line) {
|
||||
if ($line =~ /^y/i) {
|
||||
$hunk[$ix]{USE} = 1;
|
||||
@@ -1000,11 +1043,11 @@ sub patch_update_file {
|
||||
chomp $response;
|
||||
}
|
||||
if ($response !~ /^\s*\d+\s*$/) {
|
||||
print STDERR "Invalid number: '$response'\n";
|
||||
error_msg "Invalid number: '$response'\n";
|
||||
} elsif (0 < $response && $response <= $num) {
|
||||
$ix = $response - 1;
|
||||
} else {
|
||||
print STDERR "Sorry, only $num hunks available.\n";
|
||||
error_msg "Sorry, only $num hunks available.\n";
|
||||
}
|
||||
next;
|
||||
}
|
||||
@@ -1018,14 +1061,22 @@ sub patch_update_file {
|
||||
next;
|
||||
}
|
||||
elsif ($line =~ m|^/(.*)|) {
|
||||
my $regex = $1;
|
||||
if ($1 eq "") {
|
||||
print colored $prompt_color, "search for regex? ";
|
||||
$regex = <STDIN>;
|
||||
if (defined $regex) {
|
||||
chomp $regex;
|
||||
}
|
||||
}
|
||||
my $search_string;
|
||||
eval {
|
||||
$search_string = qr{$1}m;
|
||||
$search_string = qr{$regex}m;
|
||||
};
|
||||
if ($@) {
|
||||
my ($err,$exp) = ($@, $1);
|
||||
$err =~ s/ at .*git-add--interactive line \d+, <STDIN> line \d+.*$//;
|
||||
print STDERR "Malformed search regexp $exp: $err\n";
|
||||
error_msg "Malformed search regexp $exp: $err\n";
|
||||
next;
|
||||
}
|
||||
my $iy = $ix;
|
||||
@@ -1035,7 +1086,7 @@ sub patch_update_file {
|
||||
$iy++;
|
||||
$iy = 0 if ($iy >= $num);
|
||||
if ($ix == $iy) {
|
||||
print STDERR "No hunk matches the given pattern\n";
|
||||
error_msg "No hunk matches the given pattern\n";
|
||||
last;
|
||||
}
|
||||
}
|
||||
@@ -1047,7 +1098,7 @@ sub patch_update_file {
|
||||
$ix--;
|
||||
}
|
||||
else {
|
||||
print STDERR "No previous hunk\n";
|
||||
error_msg "No previous hunk\n";
|
||||
}
|
||||
next;
|
||||
}
|
||||
@@ -1056,7 +1107,7 @@ sub patch_update_file {
|
||||
$ix++;
|
||||
}
|
||||
else {
|
||||
print STDERR "No next hunk\n";
|
||||
error_msg "No next hunk\n";
|
||||
}
|
||||
next;
|
||||
}
|
||||
@@ -1069,13 +1120,13 @@ sub patch_update_file {
|
||||
}
|
||||
}
|
||||
else {
|
||||
print STDERR "No previous hunk\n";
|
||||
error_msg "No previous hunk\n";
|
||||
}
|
||||
next;
|
||||
}
|
||||
elsif ($line =~ /^j/) {
|
||||
if ($other !~ /j/) {
|
||||
print STDERR "No next hunk\n";
|
||||
error_msg "No next hunk\n";
|
||||
next;
|
||||
}
|
||||
}
|
||||
|
||||
20
git-am.sh
20
git-am.sh
@@ -221,6 +221,9 @@ then
|
||||
resume=yes
|
||||
|
||||
case "$skip,$abort" in
|
||||
t,t)
|
||||
die "Please make up your mind. --skip or --abort?"
|
||||
;;
|
||||
t,)
|
||||
git rerere clear
|
||||
git read-tree --reset -u HEAD HEAD
|
||||
@@ -229,12 +232,19 @@ then
|
||||
git update-ref ORIG_HEAD $orig_head
|
||||
;;
|
||||
,t)
|
||||
if test -f "$dotest/rebasing"
|
||||
then
|
||||
exec git rebase --abort
|
||||
fi
|
||||
git rerere clear
|
||||
git read-tree --reset -u HEAD ORIG_HEAD
|
||||
git reset ORIG_HEAD
|
||||
test -f "$dotest/dirtyindex" || {
|
||||
git read-tree --reset -u HEAD ORIG_HEAD
|
||||
git reset ORIG_HEAD
|
||||
}
|
||||
rm -fr "$dotest"
|
||||
exit ;;
|
||||
esac
|
||||
rm -f "$dotest/dirtyindex"
|
||||
else
|
||||
# Make sure we are not given --skip, --resolved, nor --abort
|
||||
test "$skip$resolved$abort" = "" ||
|
||||
@@ -287,7 +297,11 @@ fi
|
||||
case "$resolved" in
|
||||
'')
|
||||
files=$(git diff-index --cached --name-only HEAD --) || exit
|
||||
test "$files" && die "Dirty index: cannot apply patches (dirty: $files)"
|
||||
if test "$files"
|
||||
then
|
||||
: >"$dotest/dirtyindex"
|
||||
die "Dirty index: cannot apply patches (dirty: $files)"
|
||||
fi
|
||||
esac
|
||||
|
||||
if test "$(cat "$dotest/utf8")" = t
|
||||
|
||||
@@ -284,62 +284,74 @@ filter_skipped() {
|
||||
_skip="$2"
|
||||
|
||||
if [ -z "$_skip" ]; then
|
||||
eval "$_eval"
|
||||
eval "$_eval" | {
|
||||
while read line
|
||||
do
|
||||
echo "$line &&"
|
||||
done
|
||||
echo ':'
|
||||
}
|
||||
return
|
||||
fi
|
||||
|
||||
# Let's parse the output of:
|
||||
# "git rev-list --bisect-vars --bisect-all ..."
|
||||
eval "$_eval" | while read hash line
|
||||
do
|
||||
case "$VARS,$FOUND,$TRIED,$hash" in
|
||||
# We display some vars.
|
||||
1,*,*,*) echo "$hash $line" ;;
|
||||
|
||||
# Split line.
|
||||
,*,*,---*) ;;
|
||||
|
||||
# We had nothing to search.
|
||||
eval "$_eval" | {
|
||||
VARS= FOUND= TRIED=
|
||||
while read hash line
|
||||
do
|
||||
case "$VARS,$FOUND,$TRIED,$hash" in
|
||||
1,*,*,*)
|
||||
# "bisect_foo=bar" read from rev-list output.
|
||||
echo "$hash &&"
|
||||
;;
|
||||
,*,*,---*)
|
||||
# Separator
|
||||
;;
|
||||
,,,bisect_rev*)
|
||||
echo "bisect_rev="
|
||||
# We had nothing to search.
|
||||
echo "bisect_rev= &&"
|
||||
VARS=1
|
||||
;;
|
||||
|
||||
# We did not find a good bisect rev.
|
||||
# This should happen only if the "bad"
|
||||
# commit is also a "skip" commit.
|
||||
,,*,bisect_rev*)
|
||||
echo "bisect_rev=$TRIED"
|
||||
# We did not find a good bisect rev.
|
||||
# This should happen only if the "bad"
|
||||
# commit is also a "skip" commit.
|
||||
echo "bisect_rev='$TRIED' &&"
|
||||
VARS=1
|
||||
;;
|
||||
|
||||
# We are searching.
|
||||
,,*,*)
|
||||
# We are searching.
|
||||
TRIED="${TRIED:+$TRIED|}$hash"
|
||||
case "$_skip" in
|
||||
*$hash*) ;;
|
||||
*)
|
||||
echo "bisect_rev=$hash"
|
||||
echo "bisect_tried=\"$TRIED\""
|
||||
echo "bisect_rev=$hash &&"
|
||||
echo "bisect_tried='$TRIED' &&"
|
||||
FOUND=1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
# We have already found a rev to be tested.
|
||||
,1,*,bisect_rev*) VARS=1 ;;
|
||||
,1,*,*) ;;
|
||||
|
||||
# ???
|
||||
*) die "filter_skipped error " \
|
||||
"VARS: '$VARS' " \
|
||||
"FOUND: '$FOUND' " \
|
||||
"TRIED: '$TRIED' " \
|
||||
"hash: '$hash' " \
|
||||
"line: '$line'"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
,1,*,bisect_rev*)
|
||||
# We have already found a rev to be tested.
|
||||
VARS=1
|
||||
;;
|
||||
,1,*,*)
|
||||
;;
|
||||
*)
|
||||
# Unexpected input
|
||||
echo "die 'filter_skipped error'"
|
||||
die "filter_skipped error " \
|
||||
"VARS: '$VARS' " \
|
||||
"FOUND: '$FOUND' " \
|
||||
"TRIED: '$TRIED' " \
|
||||
"hash: '$hash' " \
|
||||
"line: '$line'"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
echo ':'
|
||||
}
|
||||
}
|
||||
|
||||
exit_if_skipped_commits () {
|
||||
|
||||
@@ -303,6 +303,8 @@ extern ssize_t xwrite(int fd, const void *buf, size_t len);
|
||||
extern int xdup(int fd);
|
||||
extern FILE *xfdopen(int fd, const char *mode);
|
||||
extern int xmkstemp(char *template);
|
||||
extern int odb_mkstemp(char *template, size_t limit, const char *pattern);
|
||||
extern int odb_pack_keep(char *name, size_t namesz, unsigned char *sha1);
|
||||
|
||||
static inline size_t xsize_t(off_t len)
|
||||
{
|
||||
|
||||
@@ -108,7 +108,7 @@ OPTIONS_SPEC=
|
||||
. git-sh-setup
|
||||
|
||||
if [ "$(is_bare_repository)" = false ]; then
|
||||
git diff-files --quiet &&
|
||||
git diff-files --ignore-submodules --quiet &&
|
||||
git diff-index --cached --quiet HEAD -- ||
|
||||
die "Cannot rewrite branch(es) with a dirty working directory."
|
||||
fi
|
||||
@@ -220,8 +220,14 @@ die ""
|
||||
# Remove tempdir on exit
|
||||
trap 'cd ../..; rm -rf "$tempdir"' 0
|
||||
|
||||
ORIG_GIT_DIR="$GIT_DIR"
|
||||
ORIG_GIT_WORK_TREE="$GIT_WORK_TREE"
|
||||
ORIG_GIT_INDEX_FILE="$GIT_INDEX_FILE"
|
||||
GIT_WORK_TREE=.
|
||||
export GIT_DIR GIT_WORK_TREE
|
||||
|
||||
# Make sure refs/original is empty
|
||||
git for-each-ref > "$tempdir"/backup-refs
|
||||
git for-each-ref > "$tempdir"/backup-refs || exit
|
||||
while read sha1 type name
|
||||
do
|
||||
case "$force,$name" in
|
||||
@@ -234,15 +240,10 @@ do
|
||||
esac
|
||||
done < "$tempdir"/backup-refs
|
||||
|
||||
ORIG_GIT_DIR="$GIT_DIR"
|
||||
ORIG_GIT_WORK_TREE="$GIT_WORK_TREE"
|
||||
ORIG_GIT_INDEX_FILE="$GIT_INDEX_FILE"
|
||||
GIT_WORK_TREE=.
|
||||
export GIT_DIR GIT_WORK_TREE
|
||||
|
||||
# The refs should be updated if their heads were rewritten
|
||||
git rev-parse --no-flags --revs-only --symbolic-full-name --default HEAD "$@" |
|
||||
sed -e '/^^/d' >"$tempdir"/heads
|
||||
git rev-parse --no-flags --revs-only --symbolic-full-name \
|
||||
--default HEAD "$@" > "$tempdir"/raw-heads || exit
|
||||
sed -e '/^^/d' "$tempdir"/raw-heads >"$tempdir"/heads
|
||||
|
||||
test -s "$tempdir"/heads ||
|
||||
die "Which ref do you want to rewrite?"
|
||||
@@ -251,8 +252,6 @@ GIT_INDEX_FILE="$(pwd)/../index"
|
||||
export GIT_INDEX_FILE
|
||||
git read-tree || die "Could not seed the index"
|
||||
|
||||
ret=0
|
||||
|
||||
# map old->new commit ids for rewriting parents
|
||||
mkdir ../map || die "Could not create map/ directory"
|
||||
|
||||
@@ -315,10 +314,11 @@ while read commit parents; do
|
||||
die "tree filter failed: $filter_tree"
|
||||
|
||||
(
|
||||
git diff-index -r --name-only $commit
|
||||
git diff-index -r --name-only $commit &&
|
||||
git ls-files --others
|
||||
) |
|
||||
git update-index --add --replace --remove --stdin
|
||||
) > "$tempdir"/tree-state || exit
|
||||
git update-index --add --replace --remove --stdin \
|
||||
< "$tempdir"/tree-state || exit
|
||||
fi
|
||||
|
||||
eval "$filter_index" < /dev/null ||
|
||||
@@ -339,7 +339,8 @@ while read commit parents; do
|
||||
eval "$filter_msg" > ../message ||
|
||||
die "msg filter failed: $filter_msg"
|
||||
@SHELL_PATH@ -c "$filter_commit" "git commit-tree" \
|
||||
$(git write-tree) $parentstr < ../message > ../map/$commit
|
||||
$(git write-tree) $parentstr < ../message > ../map/$commit ||
|
||||
die "could not write rewritten commit"
|
||||
done <../revs
|
||||
|
||||
# In case of a subdirectory filter, it is possible that a specified head
|
||||
@@ -407,7 +408,8 @@ do
|
||||
die "Could not rewrite $ref"
|
||||
;;
|
||||
esac
|
||||
git update-ref -m "filter-branch: backup" "$orig_namespace$ref" $sha1
|
||||
git update-ref -m "filter-branch: backup" "$orig_namespace$ref" $sha1 ||
|
||||
exit
|
||||
done < "$tempdir"/heads
|
||||
|
||||
# TODO: This should possibly go, with the semantics that all positive given
|
||||
@@ -469,20 +471,21 @@ rm -rf "$tempdir"
|
||||
|
||||
trap - 0
|
||||
|
||||
unset GIT_DIR GIT_WORK_TREE GIT_INDEX_FILE
|
||||
test -z "$ORIG_GIT_DIR" || {
|
||||
GIT_DIR="$ORIG_GIT_DIR" && export GIT_DIR
|
||||
}
|
||||
test -z "$ORIG_GIT_WORK_TREE" || {
|
||||
GIT_WORK_TREE="$ORIG_GIT_WORK_TREE" &&
|
||||
export GIT_WORK_TREE
|
||||
}
|
||||
test -z "$ORIG_GIT_INDEX_FILE" || {
|
||||
GIT_INDEX_FILE="$ORIG_GIT_INDEX_FILE" &&
|
||||
export GIT_INDEX_FILE
|
||||
}
|
||||
|
||||
if [ "$(is_bare_repository)" = false ]; then
|
||||
unset GIT_DIR GIT_WORK_TREE GIT_INDEX_FILE
|
||||
test -z "$ORIG_GIT_DIR" || {
|
||||
GIT_DIR="$ORIG_GIT_DIR" && export GIT_DIR
|
||||
}
|
||||
test -z "$ORIG_GIT_WORK_TREE" || {
|
||||
GIT_WORK_TREE="$ORIG_GIT_WORK_TREE" &&
|
||||
export GIT_WORK_TREE
|
||||
}
|
||||
test -z "$ORIG_GIT_INDEX_FILE" || {
|
||||
GIT_INDEX_FILE="$ORIG_GIT_INDEX_FILE" &&
|
||||
export GIT_INDEX_FILE
|
||||
}
|
||||
git read-tree -u -m HEAD
|
||||
git read-tree -u -m HEAD || exit
|
||||
fi
|
||||
|
||||
exit $ret
|
||||
exit 0
|
||||
|
||||
65
git-notes.sh
65
git-notes.sh
@@ -1,65 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
USAGE="(edit | show) [commit]"
|
||||
. git-sh-setup
|
||||
|
||||
test -n "$3" && usage
|
||||
|
||||
test -z "$1" && usage
|
||||
ACTION="$1"; shift
|
||||
|
||||
test -z "$GIT_NOTES_REF" && GIT_NOTES_REF="$(git config core.notesref)"
|
||||
test -z "$GIT_NOTES_REF" && GIT_NOTES_REF="refs/notes/commits"
|
||||
|
||||
COMMIT=$(git rev-parse --verify --default HEAD "$@") ||
|
||||
die "Invalid commit: $@"
|
||||
|
||||
MESSAGE="$GIT_DIR"/new-notes-$COMMIT
|
||||
trap '
|
||||
test -f "$MESSAGE" && rm "$MESSAGE"
|
||||
' 0
|
||||
|
||||
case "$ACTION" in
|
||||
edit)
|
||||
GIT_NOTES_REF= git log -1 $COMMIT | sed "s/^/#/" > "$MESSAGE"
|
||||
|
||||
GIT_INDEX_FILE="$MESSAGE".idx
|
||||
export GIT_INDEX_FILE
|
||||
|
||||
CURRENT_HEAD=$(git show-ref "$GIT_NOTES_REF" | cut -f 1 -d ' ')
|
||||
if [ -z "$CURRENT_HEAD" ]; then
|
||||
PARENT=
|
||||
else
|
||||
PARENT="-p $CURRENT_HEAD"
|
||||
git read-tree "$GIT_NOTES_REF" || die "Could not read index"
|
||||
git cat-file blob :$COMMIT >> "$MESSAGE" 2> /dev/null
|
||||
fi
|
||||
|
||||
${VISUAL:-${EDITOR:-vi}} "$MESSAGE"
|
||||
|
||||
grep -v ^# < "$MESSAGE" | git stripspace > "$MESSAGE".processed
|
||||
mv "$MESSAGE".processed "$MESSAGE"
|
||||
if [ -s "$MESSAGE" ]; then
|
||||
BLOB=$(git hash-object -w "$MESSAGE") ||
|
||||
die "Could not write into object database"
|
||||
git update-index --add --cacheinfo 0644 $BLOB $COMMIT ||
|
||||
die "Could not write index"
|
||||
else
|
||||
test -z "$CURRENT_HEAD" &&
|
||||
die "Will not initialise with empty tree"
|
||||
git update-index --force-remove $COMMIT ||
|
||||
die "Could not update index"
|
||||
fi
|
||||
|
||||
TREE=$(git write-tree) || die "Could not write tree"
|
||||
NEW_HEAD=$(echo Annotate $COMMIT | git commit-tree $TREE $PARENT) ||
|
||||
die "Could not annotate"
|
||||
git update-ref -m "Annotate $COMMIT" \
|
||||
"$GIT_NOTES_REF" $NEW_HEAD $CURRENT_HEAD
|
||||
;;
|
||||
show)
|
||||
git show "$GIT_NOTES_REF":$COMMIT
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
esac
|
||||
@@ -171,6 +171,11 @@ case "$merge_head" in
|
||||
echo >&2 "Cannot merge multiple branches into empty head"
|
||||
exit 1
|
||||
fi
|
||||
if test true = "$rebase"
|
||||
then
|
||||
echo >&2 "Cannot rebase onto multiple branches"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ tmp_info="$tmp_dir/info"
|
||||
commit=$(git rev-parse HEAD)
|
||||
|
||||
mkdir $tmp_dir || exit 2
|
||||
while read patch_name level garbage
|
||||
while read patch_name level garbage <&3
|
||||
do
|
||||
case "$patch_name" in ''|'#'*) continue;; esac
|
||||
case "$level" in
|
||||
@@ -134,5 +134,5 @@ do
|
||||
commit=$( (echo "$SUBJECT"; echo; cat "$tmp_msg") | git commit-tree $tree -p $commit) &&
|
||||
git update-ref -m "quiltimport: $patch_name" HEAD $commit || exit 4
|
||||
fi
|
||||
done <"$QUILT_PATCHES/series"
|
||||
done 3<"$QUILT_PATCHES/series"
|
||||
rm -rf $tmp_dir || exit 5
|
||||
|
||||
@@ -310,6 +310,7 @@ do
|
||||
esac
|
||||
shift
|
||||
done
|
||||
test $# -gt 2 && usage
|
||||
|
||||
# Make sure we do not have $GIT_DIR/rebase-apply
|
||||
if test -z "$do_merge"
|
||||
|
||||
@@ -88,32 +88,79 @@ if [ -z "$names" ]; then
|
||||
echo Nothing new to pack.
|
||||
fi
|
||||
fi
|
||||
for name in $names ; do
|
||||
|
||||
# Ok we have prepared all new packfiles.
|
||||
mkdir -p "$PACKDIR" || exit
|
||||
|
||||
# First see if there are packs of the same name and if so
|
||||
# if we can move them out of the way (this can happen if we
|
||||
# repacked immediately after packing fully.
|
||||
rollback=
|
||||
failed=
|
||||
for name in $names
|
||||
do
|
||||
for sfx in pack idx
|
||||
do
|
||||
file=pack-$name.$sfx
|
||||
test -f "$PACKDIR/$file" || continue
|
||||
rm -f "$PACKDIR/old-$file" &&
|
||||
mv "$PACKDIR/$file" "$PACKDIR/old-$file" || {
|
||||
failed=t
|
||||
break
|
||||
}
|
||||
rollback="$rollback $file"
|
||||
done
|
||||
test -z "$failed" || break
|
||||
done
|
||||
|
||||
# If renaming failed for any of them, roll the ones we have
|
||||
# already renamed back to their original names.
|
||||
if test -n "$failed"
|
||||
then
|
||||
rollback_failure=
|
||||
for file in $rollback
|
||||
do
|
||||
mv "$PACKDIR/old-$file" "$PACKDIR/$file" ||
|
||||
rollback_failure="$rollback_failure $file"
|
||||
done
|
||||
if test -n "$rollback_failure"
|
||||
then
|
||||
echo >&2 "WARNING: Some packs in use have been renamed by"
|
||||
echo >&2 "WARNING: prefixing old- to their name, in order to"
|
||||
echo >&2 "WARNING: replace them with the new version of the"
|
||||
echo >&2 "WARNING: file. But the operation failed, and"
|
||||
echo >&2 "WARNING: attempt to rename them back to their"
|
||||
echo >&2 "WARNING: original names also failed."
|
||||
echo >&2 "WARNING: Please rename them in $PACKDIR manually:"
|
||||
for file in $rollback_failure
|
||||
do
|
||||
echo >&2 "WARNING: old-$file -> $file"
|
||||
done
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Now the ones with the same name are out of the way...
|
||||
fullbases=
|
||||
for name in $names
|
||||
do
|
||||
fullbases="$fullbases pack-$name"
|
||||
chmod a-w "$PACKTMP-$name.pack"
|
||||
chmod a-w "$PACKTMP-$name.idx"
|
||||
mkdir -p "$PACKDIR" || exit
|
||||
|
||||
for sfx in pack idx
|
||||
do
|
||||
if test -f "$PACKDIR/pack-$name.$sfx"
|
||||
then
|
||||
mv -f "$PACKDIR/pack-$name.$sfx" \
|
||||
"$PACKDIR/old-pack-$name.$sfx"
|
||||
fi
|
||||
done &&
|
||||
mv -f "$PACKTMP-$name.pack" "$PACKDIR/pack-$name.pack" &&
|
||||
mv -f "$PACKTMP-$name.idx" "$PACKDIR/pack-$name.idx" &&
|
||||
test -f "$PACKDIR/pack-$name.pack" &&
|
||||
test -f "$PACKDIR/pack-$name.idx" || {
|
||||
echo >&2 "Couldn't replace the existing pack with updated one."
|
||||
echo >&2 "The original set of packs have been saved as"
|
||||
echo >&2 "old-pack-$name.{pack,idx} in $PACKDIR."
|
||||
exit 1
|
||||
}
|
||||
rm -f "$PACKDIR/old-pack-$name.pack" "$PACKDIR/old-pack-$name.idx"
|
||||
mv -f "$PACKTMP-$name.idx" "$PACKDIR/pack-$name.idx" ||
|
||||
exit
|
||||
done
|
||||
|
||||
# Remove the "old-" files
|
||||
for name in $names
|
||||
do
|
||||
rm -f "$PACKDIR/old-pack-$name.idx"
|
||||
rm -f "$PACKDIR/old-pack-$name.pack"
|
||||
done
|
||||
|
||||
# End of pack replacement.
|
||||
|
||||
if test "$remove_redundant" = t
|
||||
then
|
||||
# We know $existing are all redundant.
|
||||
|
||||
@@ -85,27 +85,14 @@ cd_to_toplevel () {
|
||||
cdup=$(git rev-parse --show-cdup)
|
||||
if test ! -z "$cdup"
|
||||
then
|
||||
case "$cdup" in
|
||||
/*)
|
||||
# Not quite the same as if we did "cd -P '$cdup'" when
|
||||
# $cdup contains ".." after symlink path components.
|
||||
# Don't fix that case at least until Git switches to
|
||||
# "cd -P" across the board.
|
||||
phys="$cdup"
|
||||
;;
|
||||
..|../*|*/..|*/../*)
|
||||
# Interpret $cdup relative to the physical, not logical, cwd.
|
||||
# Probably /bin/pwd is more portable than passing -P to cd or pwd.
|
||||
phys="$(unset PWD; /bin/pwd)/$cdup"
|
||||
;;
|
||||
*)
|
||||
# There's no "..", so no need to make things absolute.
|
||||
phys="$cdup"
|
||||
;;
|
||||
esac
|
||||
|
||||
cd "$phys" || {
|
||||
echo >&2 "Cannot chdir to $phys, the toplevel of the working tree"
|
||||
# The "-P" option says to follow "physical" directory
|
||||
# structure instead of following symbolic links. When cdup is
|
||||
# "../", this means following the ".." entry in the current
|
||||
# directory instead textually removing a symlink path element
|
||||
# from the PWD shell variable. The "-P" behavior is more
|
||||
# consistent with the C-style chdir used by most of Git.
|
||||
cd -P "$cdup" || {
|
||||
echo >&2 "Cannot chdir to $cdup, the toplevel of the working tree"
|
||||
exit 1
|
||||
}
|
||||
fi
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
# Copyright (c) 2007 Lars Hjemli
|
||||
|
||||
USAGE="[--quiet] [--cached] \
|
||||
[add <repo> [-b branch] <path>]|[status|init|update [-i|--init]|summary [-n|--summary-limit <n>] [<commit>]] \
|
||||
[add <repo> [-b branch] <path>]|[status|init|update [-i|--init] [-N|--no-fetch]|summary [-n|--summary-limit <n>] [<commit>]] \
|
||||
[--] [<path>...]|[foreach <command>]|[sync [--] [<path>...]]"
|
||||
OPTIONS_SPEC=
|
||||
. git-sh-setup
|
||||
@@ -16,6 +16,7 @@ command=
|
||||
branch=
|
||||
quiet=
|
||||
cached=
|
||||
nofetch=
|
||||
|
||||
#
|
||||
# print stuff on stdout unless -q was specified
|
||||
@@ -59,7 +60,7 @@ resolve_relative_url ()
|
||||
#
|
||||
module_list()
|
||||
{
|
||||
git ls-files --stage -- "$@" | grep '^160000 '
|
||||
git ls-files --error-unmatch --stage -- "$@" | grep '^160000 '
|
||||
}
|
||||
|
||||
#
|
||||
@@ -300,6 +301,10 @@ cmd_update()
|
||||
shift
|
||||
cmd_init "$@" || return
|
||||
;;
|
||||
-N|--no-fetch)
|
||||
shift
|
||||
nofetch=1
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
@@ -345,8 +350,16 @@ cmd_update()
|
||||
then
|
||||
force="-f"
|
||||
fi
|
||||
(unset GIT_DIR; cd "$path" && git-fetch &&
|
||||
git-checkout $force -q "$sha1") ||
|
||||
|
||||
if test -z "$nofetch"
|
||||
then
|
||||
(unset GIT_DIR; cd "$path" &&
|
||||
git-fetch) ||
|
||||
die "Unable to fetch in submodule path '$path'"
|
||||
fi
|
||||
|
||||
(unset GIT_DIR; cd "$path" &&
|
||||
git-checkout $force -q "$sha1") ||
|
||||
die "Unable to checkout '$sha1' in submodule path '$path'"
|
||||
|
||||
say "Submodule path '$path': checked out '$sha1'"
|
||||
|
||||
104
git-svn.perl
104
git-svn.perl
@@ -438,7 +438,17 @@ sub cmd_dcommit {
|
||||
die "Unable to determine upstream SVN information from ",
|
||||
"$head history.\nPerhaps the repository is empty.";
|
||||
}
|
||||
$url = defined $_commit_url ? $_commit_url : $gs->full_url;
|
||||
|
||||
if (defined $_commit_url) {
|
||||
$url = $_commit_url;
|
||||
} else {
|
||||
$url = eval { command_oneline('config', '--get',
|
||||
"svn-remote.$gs->{repo_id}.commiturl") };
|
||||
if (!$url) {
|
||||
$url = $gs->full_url
|
||||
}
|
||||
}
|
||||
|
||||
my $last_rev = $_revision if defined $_revision;
|
||||
if ($url) {
|
||||
print "Committing to $url ...\n";
|
||||
@@ -670,7 +680,11 @@ sub cmd_create_ignore {
|
||||
$gs->prop_walk($gs->{path}, $r, sub {
|
||||
my ($gs, $path, $props) = @_;
|
||||
# $path is of the form /path/to/dir/
|
||||
my $ignore = '.' . $path . '.gitignore';
|
||||
$path = '.' . $path;
|
||||
# SVN can have attributes on empty directories,
|
||||
# which git won't track
|
||||
mkpath([$path]) unless -d $path;
|
||||
my $ignore = $path . '.gitignore';
|
||||
my $s = $props->{'svn:ignore'} or return;
|
||||
open(GITIGNORE, '>', $ignore)
|
||||
or fatal("Failed to open `$ignore' for writing: $!");
|
||||
@@ -1693,6 +1707,7 @@ sub find_by_url { # repos_root and, path are optional
|
||||
my $prefix = '';
|
||||
if ($rwr) {
|
||||
$z = $rwr;
|
||||
remove_username($z);
|
||||
} elsif (defined $svm) {
|
||||
$z = $svm->{source};
|
||||
$prefix = $svm->{replace};
|
||||
@@ -2389,22 +2404,8 @@ sub find_parent_branch {
|
||||
print STDERR "Found possible branch point: ",
|
||||
"$new_url => ", $self->full_url, ", $r\n";
|
||||
$branch_from =~ s#^/##;
|
||||
my $gs = Git::SVN->find_by_url($new_url, $repos_root, $branch_from);
|
||||
unless ($gs) {
|
||||
my $ref_id = $self->{ref_id};
|
||||
$ref_id =~ s/\@\d+$//;
|
||||
$ref_id .= "\@$r";
|
||||
# just grow a tail if we're not unique enough :x
|
||||
$ref_id .= '-' while find_ref($ref_id);
|
||||
print STDERR "Initializing parent: $ref_id\n";
|
||||
my ($u, $p, $repo_id) = ($new_url, '', $ref_id);
|
||||
if ($u =~ s#^\Q$url\E(/|$)##) {
|
||||
$p = $u;
|
||||
$u = $url;
|
||||
$repo_id = $self->{repo_id};
|
||||
}
|
||||
$gs = Git::SVN->init($u, $p, $repo_id, $ref_id, 1);
|
||||
}
|
||||
my $gs = $self->other_gs($new_url, $url, $repos_root,
|
||||
$branch_from, $r, $self->{ref_id});
|
||||
my ($r0, $parent) = $gs->find_rev_before($r, 1);
|
||||
{
|
||||
my ($base, $head);
|
||||
@@ -2430,8 +2431,9 @@ sub find_parent_branch {
|
||||
# do_switch works with svn/trunk >= r22312, but that
|
||||
# is not included with SVN 1.4.3 (the latest version
|
||||
# at the moment), so we can't rely on it
|
||||
$self->{last_rev} = $r0;
|
||||
$self->{last_commit} = $parent;
|
||||
$ed = SVN::Git::Fetcher->new($self);
|
||||
$ed = SVN::Git::Fetcher->new($self, $gs->{path});
|
||||
$gs->ra->gs_do_switch($r0, $rev, $gs,
|
||||
$self->full_url, $ed)
|
||||
or die "SVN connection failed somewhere...\n";
|
||||
@@ -2539,7 +2541,7 @@ sub get_untracked {
|
||||
sub parse_svn_date {
|
||||
my $date = shift || return '+0000 1970-01-01 00:00:00';
|
||||
my ($Y,$m,$d,$H,$M,$S) = ($date =~ /^(\d{4})\-(\d\d)\-(\d\d)T
|
||||
(\d\d)\:(\d\d)\:(\d\d).\d+Z$/x) or
|
||||
(\d\d)\:(\d\d)\:(\d\d)\.\d*Z$/x) or
|
||||
croak "Unable to parse date: $date\n";
|
||||
my $parsed_date; # Set next.
|
||||
|
||||
@@ -2586,6 +2588,28 @@ sub parse_svn_date {
|
||||
return $parsed_date;
|
||||
}
|
||||
|
||||
sub other_gs {
|
||||
my ($self, $new_url, $url, $repos_root,
|
||||
$branch_from, $r, $old_ref_id) = @_;
|
||||
my $gs = Git::SVN->find_by_url($new_url, $repos_root, $branch_from);
|
||||
unless ($gs) {
|
||||
my $ref_id = $old_ref_id;
|
||||
$ref_id =~ s/\@\d+$//;
|
||||
$ref_id .= "\@$r";
|
||||
# just grow a tail if we're not unique enough :x
|
||||
$ref_id .= '-' while find_ref($ref_id);
|
||||
print STDERR "Initializing parent: $ref_id\n";
|
||||
my ($u, $p, $repo_id) = ($new_url, '', $ref_id);
|
||||
if ($u =~ s#^\Q$url\E(/|$)##) {
|
||||
$p = $u;
|
||||
$u = $url;
|
||||
$repo_id = $self->{repo_id};
|
||||
}
|
||||
$gs = Git::SVN->init($u, $p, $repo_id, $ref_id, 1);
|
||||
}
|
||||
$gs
|
||||
}
|
||||
|
||||
sub check_author {
|
||||
my ($author) = @_;
|
||||
if (!defined $author || length $author == 0) {
|
||||
@@ -3250,12 +3274,13 @@ use vars qw/$_ignore_regex/;
|
||||
|
||||
# file baton members: path, mode_a, mode_b, pool, fh, blob, base
|
||||
sub new {
|
||||
my ($class, $git_svn) = @_;
|
||||
my ($class, $git_svn, $switch_path) = @_;
|
||||
my $self = SVN::Delta::Editor->new;
|
||||
bless $self, $class;
|
||||
if (exists $git_svn->{last_commit}) {
|
||||
$self->{c} = $git_svn->{last_commit};
|
||||
$self->{empty_symlinks} = _mark_empty_symlinks($git_svn);
|
||||
$self->{empty_symlinks} =
|
||||
_mark_empty_symlinks($git_svn, $switch_path);
|
||||
}
|
||||
$self->{empty} = {};
|
||||
$self->{dir_prop} = {};
|
||||
@@ -3270,19 +3295,39 @@ sub new {
|
||||
# not inside them (when the Git::SVN::Fetcher object is passed) to
|
||||
# do_{switch,update}
|
||||
sub _mark_empty_symlinks {
|
||||
my ($git_svn) = @_;
|
||||
my ($git_svn, $switch_path) = @_;
|
||||
my $bool = Git::config_bool('svn.brokenSymlinkWorkaround');
|
||||
return {} if (!defined($bool)) || (defined($bool) && ! $bool);
|
||||
|
||||
my %ret;
|
||||
my ($rev, $cmt) = $git_svn->last_rev_commit;
|
||||
return {} unless ($rev && $cmt);
|
||||
|
||||
# allow the warning to be printed for each revision we fetch to
|
||||
# ensure the user sees it. The user can also disable the workaround
|
||||
# on the repository even while git svn is running and the next
|
||||
# revision fetched will skip this expensive function.
|
||||
my $printed_warning;
|
||||
chomp(my $empty_blob = `git hash-object -t blob --stdin < /dev/null`);
|
||||
my ($ls, $ctx) = command_output_pipe(qw/ls-tree -r -z/, $cmt);
|
||||
local $/ = "\0";
|
||||
my $pfx = $git_svn->{path};
|
||||
my $pfx = defined($switch_path) ? $switch_path : $git_svn->{path};
|
||||
$pfx .= '/' if length($pfx);
|
||||
while (<$ls>) {
|
||||
chomp;
|
||||
s/\A100644 blob $empty_blob\t//o or next;
|
||||
unless ($printed_warning) {
|
||||
print STDERR "Scanning for empty symlinks, ",
|
||||
"this may take a while if you have ",
|
||||
"many empty files\n",
|
||||
"You may disable this with `",
|
||||
"git config svn.brokenSymlinkWorkaround ",
|
||||
"false'.\n",
|
||||
"This may be done in a different ",
|
||||
"terminal without restarting ",
|
||||
"git svn\n";
|
||||
$printed_warning = 1;
|
||||
}
|
||||
my $path = $_;
|
||||
my (undef, $props) =
|
||||
$git_svn->ra->get_file($pfx.$path, $rev, undef);
|
||||
@@ -4348,6 +4393,9 @@ sub gs_fetch_loop_common {
|
||||
}
|
||||
$self->get_log([$longest_path], $min, $max, 0, 1, 1,
|
||||
sub { $revs{$_[1]} = _cb(@_) });
|
||||
if ($err) {
|
||||
print "Checked through r$max\r";
|
||||
}
|
||||
if ($err && $max >= $head) {
|
||||
print STDERR "Path '$longest_path' ",
|
||||
"was probably deleted:\n",
|
||||
@@ -4582,6 +4630,7 @@ package Git::SVN::Log;
|
||||
use strict;
|
||||
use warnings;
|
||||
use POSIX qw/strftime/;
|
||||
use Time::Local;
|
||||
use constant commit_log_separator => ('-' x 72) . "\n";
|
||||
use vars qw/$TZ $limit $color $pager $non_recursive $verbose $oneline
|
||||
%rusers $show_commit $incremental/;
|
||||
@@ -4688,7 +4737,12 @@ sub run_pager {
|
||||
}
|
||||
|
||||
sub format_svn_date {
|
||||
return strftime("%Y-%m-%d %H:%M:%S %z (%a, %d %b %Y)", localtime(shift));
|
||||
# some systmes don't handle or mishandle %z, so be creative.
|
||||
my $t = shift || time;
|
||||
my $gm = timelocal(gmtime($t));
|
||||
my $sign = qw( + + - )[ $t <=> $gm ];
|
||||
my $gmoff = sprintf("%s%02d%02d", $sign, (gmtime(abs($t - $gm)))[2,1]);
|
||||
return strftime("%Y-%m-%d %H:%M:%S $gmoff (%a, %d %b %Y)", localtime($t));
|
||||
}
|
||||
|
||||
sub parse_git_date {
|
||||
|
||||
@@ -115,7 +115,7 @@ if test -z "$browser" ; then
|
||||
browser_candidates="open $browser_candidates"
|
||||
fi
|
||||
# /bin/start indicates MinGW
|
||||
if test -n /bin/start; then
|
||||
if test -x /bin/start; then
|
||||
browser_candidates="start $browser_candidates"
|
||||
fi
|
||||
|
||||
|
||||
@@ -701,16 +701,17 @@ proc newvarc {view id} {
|
||||
}
|
||||
|
||||
proc splitvarc {p v} {
|
||||
global varcid varcstart varccommits varctok
|
||||
global varcid varcstart varccommits varctok vtokmod
|
||||
global vupptr vdownptr vleftptr vbackptr varcix varcrow vlastins
|
||||
|
||||
set oa $varcid($v,$p)
|
||||
set otok [lindex $varctok($v) $oa]
|
||||
set ac $varccommits($v,$oa)
|
||||
set i [lsearch -exact $varccommits($v,$oa) $p]
|
||||
if {$i <= 0} return
|
||||
set na [llength $varctok($v)]
|
||||
# "%" sorts before "0"...
|
||||
set tok "[lindex $varctok($v) $oa]%[strrep $i]"
|
||||
set tok "$otok%[strrep $i]"
|
||||
lappend varctok($v) $tok
|
||||
lappend varcrow($v) {}
|
||||
lappend varcix($v) {}
|
||||
@@ -730,6 +731,9 @@ proc splitvarc {p v} {
|
||||
for {set b [lindex $vdownptr($v) $na]} {$b != 0} {set b [lindex $vleftptr($v) $b]} {
|
||||
lset vupptr($v) $b $na
|
||||
}
|
||||
if {[string compare $otok $vtokmod($v)] <= 0} {
|
||||
modify_arc $v $oa
|
||||
}
|
||||
}
|
||||
|
||||
proc renumbervarc {a v} {
|
||||
@@ -3364,7 +3368,6 @@ proc external_blame {parent_idx {line {}}} {
|
||||
# being given an absolute path...
|
||||
set f [make_relative $f]
|
||||
lappend cmdline $base_commit $f
|
||||
puts "cmdline={$cmdline}"
|
||||
if {[catch {eval exec $cmdline &} err]} {
|
||||
error_popup "[mc "git gui blame: command failed:"] $err"
|
||||
}
|
||||
@@ -5732,7 +5735,6 @@ proc drawcommits {row {endrow {}}} {
|
||||
optimize_rows $ro1 0 $r2
|
||||
if {$need_redisplay || $nrows_drawn > 2000} {
|
||||
clear_display
|
||||
drawvisible
|
||||
}
|
||||
|
||||
# make the lines join to already-drawn rows either side
|
||||
|
||||
@@ -212,6 +212,11 @@ not include variables usually directly set during build):
|
||||
Rename detection options for git-diff and git-diff-tree. By default
|
||||
('-M'); set it to ('-C') or ('-C', '-C') to also detect copies, or
|
||||
set it to () if you don't want to have renames detection.
|
||||
* $prevent_xss
|
||||
If true, some gitweb features are disabled to prevent content in
|
||||
repositories from launching cross-site scripting (XSS) attacks. Set this
|
||||
to true if you don't trust the content of your repositories. The default
|
||||
is false.
|
||||
|
||||
|
||||
Projects list file format
|
||||
@@ -258,7 +263,9 @@ You can use the following files in repository:
|
||||
A .html file (HTML fragment) which is included on the gitweb project
|
||||
summary page inside <div> block element. You can use it for longer
|
||||
description of a project, to provide links (for example to project's
|
||||
homepage), etc.
|
||||
homepage), etc. This is recognized only if XSS prevention is off
|
||||
($prevent_xss is false); a way to include a readme safely when XSS
|
||||
prevention is on may be worked out in the future.
|
||||
* description (or gitweb.description)
|
||||
Short (shortened by default to 25 characters in the projects list page)
|
||||
single line description of a project (of a repository). Plain text file;
|
||||
|
||||
@@ -27,13 +27,29 @@ our $version = "++GIT_VERSION++";
|
||||
our $my_url = $cgi->url();
|
||||
our $my_uri = $cgi->url(-absolute => 1);
|
||||
|
||||
# if we're called with PATH_INFO, we have to strip that
|
||||
# from the URL to find our real URL
|
||||
# we make $path_info global because it's also used later on
|
||||
# Base URL for relative URLs in gitweb ($logo, $favicon, ...),
|
||||
# needed and used only for URLs with nonempty PATH_INFO
|
||||
our $base_url = $my_url;
|
||||
|
||||
# When the script is used as DirectoryIndex, the URL does not contain the name
|
||||
# of the script file itself, and $cgi->url() fails to strip PATH_INFO, so we
|
||||
# have to do it ourselves. We make $path_info global because it's also used
|
||||
# later on.
|
||||
#
|
||||
# Another issue with the script being the DirectoryIndex is that the resulting
|
||||
# $my_url data is not the full script URL: this is good, because we want
|
||||
# generated links to keep implying the script name if it wasn't explicitly
|
||||
# indicated in the URL we're handling, but it means that $my_url cannot be used
|
||||
# as base URL.
|
||||
# Therefore, if we needed to strip PATH_INFO, then we know that we have
|
||||
# to build the base URL ourselves:
|
||||
our $path_info = $ENV{"PATH_INFO"};
|
||||
if ($path_info) {
|
||||
$my_url =~ s,\Q$path_info\E$,,;
|
||||
$my_uri =~ s,\Q$path_info\E$,,;
|
||||
if ($my_url =~ s,\Q$path_info\E$,, &&
|
||||
$my_uri =~ s,\Q$path_info\E$,, &&
|
||||
defined $ENV{'SCRIPT_NAME'}) {
|
||||
$base_url = $cgi->url(-base => 1) . $ENV{'SCRIPT_NAME'};
|
||||
}
|
||||
}
|
||||
|
||||
# core git executable to use
|
||||
@@ -132,6 +148,10 @@ our $fallback_encoding = 'latin1';
|
||||
# - one might want to include '-B' option, e.g. '-B', '-M'
|
||||
our @diff_opts = ('-M'); # taken from git_commit
|
||||
|
||||
# Disables features that would allow repository owners to inject script into
|
||||
# the gitweb domain.
|
||||
our $prevent_xss = 0;
|
||||
|
||||
# information about snapshot formats that gitweb is capable of serving
|
||||
our %known_snapshot_formats = (
|
||||
# name => {
|
||||
@@ -382,13 +402,13 @@ sub feature_bool {
|
||||
my $key = shift;
|
||||
my ($val) = git_get_project_config($key, '--bool');
|
||||
|
||||
if ($val eq 'true') {
|
||||
if (!defined $val) {
|
||||
return ($_[0]);
|
||||
} elsif ($val eq 'true') {
|
||||
return (1);
|
||||
} elsif ($val eq 'false') {
|
||||
return (0);
|
||||
}
|
||||
|
||||
return ($_[0]);
|
||||
}
|
||||
|
||||
sub feature_snapshot {
|
||||
@@ -1364,13 +1384,11 @@ sub format_log_line_html {
|
||||
my $line = shift;
|
||||
|
||||
$line = esc_html($line, -nbsp=>1);
|
||||
if ($line =~ m/([0-9a-fA-F]{8,40})/) {
|
||||
my $hash_text = $1;
|
||||
my $link =
|
||||
$cgi->a({-href => href(action=>"object", hash=>$hash_text),
|
||||
-class => "text"}, $hash_text);
|
||||
$line =~ s/$hash_text/$link/;
|
||||
}
|
||||
$line =~ s{\b([0-9a-fA-F]{8,40})\b}{
|
||||
$cgi->a({-href => href(action=>"object", hash=>$1),
|
||||
-class => "text"}, $1);
|
||||
}eg;
|
||||
|
||||
return $line;
|
||||
}
|
||||
|
||||
@@ -1894,18 +1912,19 @@ sub git_parse_project_config {
|
||||
return %config;
|
||||
}
|
||||
|
||||
# convert config value to boolean, 'true' or 'false'
|
||||
# convert config value to boolean: 'true' or 'false'
|
||||
# no value, number > 0, 'true' and 'yes' values are true
|
||||
# rest of values are treated as false (never as error)
|
||||
sub config_to_bool {
|
||||
my $val = shift;
|
||||
|
||||
return 1 if !defined $val; # section.key
|
||||
|
||||
# strip leading and trailing whitespace
|
||||
$val =~ s/^\s+//;
|
||||
$val =~ s/\s+$//;
|
||||
|
||||
return (!defined $val || # section.key
|
||||
($val =~ /^\d+$/ && $val) || # section.key = 1
|
||||
return (($val =~ /^\d+$/ && $val) || # section.key = 1
|
||||
($val =~ /^(?:true|yes)$/i)); # section.key = true
|
||||
}
|
||||
|
||||
@@ -1958,6 +1977,9 @@ sub git_get_project_config {
|
||||
$config_file = "$git_dir/config";
|
||||
}
|
||||
|
||||
# check if config variable (key) exists
|
||||
return unless exists $config{"gitweb.$key"};
|
||||
|
||||
# ensure given type
|
||||
if (!defined $type) {
|
||||
return $config{"gitweb.$key"};
|
||||
@@ -2904,7 +2926,7 @@ EOF
|
||||
# the stylesheet, favicon etc urls won't work correctly with path_info
|
||||
# unless we set the appropriate base URL
|
||||
if ($ENV{'PATH_INFO'}) {
|
||||
print '<base href="'.esc_url($my_url).'" />\n';
|
||||
print "<base href=\"".esc_url($base_url)."\" />\n";
|
||||
}
|
||||
# print out each stylesheet that exist, providing backwards capability
|
||||
# for those people who defined $stylesheet in a config file
|
||||
@@ -4503,7 +4525,9 @@ sub git_summary {
|
||||
|
||||
print "</table>\n";
|
||||
|
||||
if (-s "$projectroot/$project/README.html") {
|
||||
# If XSS prevention is on, we don't include README.html.
|
||||
# TODO: Allow a readme in some safe format.
|
||||
if (!$prevent_xss && -s "$projectroot/$project/README.html") {
|
||||
print "<div class=\"title\">readme</div>\n" .
|
||||
"<div class=\"readme\">\n";
|
||||
insert_file("$projectroot/$project/README.html");
|
||||
@@ -4764,10 +4788,21 @@ sub git_blob_plain {
|
||||
$save_as .= '.txt';
|
||||
}
|
||||
|
||||
# With XSS prevention on, blobs of all types except a few known safe
|
||||
# ones are served with "Content-Disposition: attachment" to make sure
|
||||
# they don't run in our security domain. For certain image types,
|
||||
# blob view writes an <img> tag referring to blob_plain view, and we
|
||||
# want to be sure not to break that by serving the image as an
|
||||
# attachment (though Firefox 3 doesn't seem to care).
|
||||
my $sandbox = $prevent_xss &&
|
||||
$type !~ m!^(?:text/plain|image/(?:gif|png|jpeg))$!;
|
||||
|
||||
print $cgi->header(
|
||||
-type => $type,
|
||||
-expires => $expires,
|
||||
-content_disposition => 'inline; filename="' . $save_as . '"');
|
||||
-content_disposition =>
|
||||
($sandbox ? 'attachment' : 'inline')
|
||||
. '; filename="' . $save_as . '"');
|
||||
undef $/;
|
||||
binmode STDOUT, ':raw';
|
||||
print <$fd>;
|
||||
|
||||
13
http-push.c
13
http-push.c
@@ -153,6 +153,7 @@ struct remote_lock
|
||||
char *url;
|
||||
char *owner;
|
||||
char *token;
|
||||
char tmpfile_suffix[41];
|
||||
time_t start_time;
|
||||
long timeout;
|
||||
int refreshing;
|
||||
@@ -557,8 +558,7 @@ static void start_put(struct transfer_request *request)
|
||||
request->dest = strbuf_detach(&buf, NULL);
|
||||
|
||||
append_remote_object_url(&buf, remote->url, hex, 0);
|
||||
strbuf_addstr(&buf, "_");
|
||||
strbuf_addstr(&buf, request->lock->token);
|
||||
strbuf_add(&buf, request->lock->tmpfile_suffix, 41);
|
||||
request->url = strbuf_detach(&buf, NULL);
|
||||
|
||||
slot = get_active_slot();
|
||||
@@ -1130,6 +1130,8 @@ static void handle_lockprop_ctx(struct xml_ctx *ctx, int tag_closed)
|
||||
static void handle_new_lock_ctx(struct xml_ctx *ctx, int tag_closed)
|
||||
{
|
||||
struct remote_lock *lock = (struct remote_lock *)ctx->userData;
|
||||
git_SHA_CTX sha_ctx;
|
||||
unsigned char lock_token_sha1[20];
|
||||
|
||||
if (tag_closed && ctx->cdata) {
|
||||
if (!strcmp(ctx->name, DAV_ACTIVELOCK_OWNER)) {
|
||||
@@ -1142,6 +1144,13 @@ static void handle_new_lock_ctx(struct xml_ctx *ctx, int tag_closed)
|
||||
} else if (!strcmp(ctx->name, DAV_ACTIVELOCK_TOKEN)) {
|
||||
lock->token = xmalloc(strlen(ctx->cdata) + 1);
|
||||
strcpy(lock->token, ctx->cdata);
|
||||
|
||||
git_SHA1_Init(&sha_ctx);
|
||||
git_SHA1_Update(&sha_ctx, lock->token, strlen(lock->token));
|
||||
git_SHA1_Final(lock_token_sha1, &sha_ctx);
|
||||
|
||||
lock->tmpfile_suffix[0] = '_';
|
||||
memcpy(lock->tmpfile_suffix + 1, sha1_to_hex(lock_token_sha1), 40);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
23
index-pack.c
23
index-pack.c
@@ -172,9 +172,8 @@ static char *open_pack_file(char *pack_name)
|
||||
input_fd = 0;
|
||||
if (!pack_name) {
|
||||
static char tmpfile[PATH_MAX];
|
||||
snprintf(tmpfile, sizeof(tmpfile),
|
||||
"%s/pack/tmp_pack_XXXXXX", get_object_directory());
|
||||
output_fd = xmkstemp(tmpfile);
|
||||
output_fd = odb_mkstemp(tmpfile, sizeof(tmpfile),
|
||||
"pack/tmp_pack_XXXXXX");
|
||||
pack_name = xstrdup(tmpfile);
|
||||
} else
|
||||
output_fd = open(pack_name, O_CREAT|O_EXCL|O_RDWR, 0600);
|
||||
@@ -794,22 +793,24 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
|
||||
|
||||
if (keep_msg) {
|
||||
int keep_fd, keep_msg_len = strlen(keep_msg);
|
||||
if (!keep_name) {
|
||||
snprintf(name, sizeof(name), "%s/pack/pack-%s.keep",
|
||||
get_object_directory(), sha1_to_hex(sha1));
|
||||
keep_name = name;
|
||||
}
|
||||
keep_fd = open(keep_name, O_RDWR|O_CREAT|O_EXCL, 0600);
|
||||
|
||||
if (!keep_name)
|
||||
keep_fd = odb_pack_keep(name, sizeof(name), sha1);
|
||||
else
|
||||
keep_fd = open(keep_name, O_RDWR|O_CREAT|O_EXCL, 0600);
|
||||
|
||||
if (keep_fd < 0) {
|
||||
if (errno != EEXIST)
|
||||
die("cannot write keep file");
|
||||
die("cannot write keep file '%s' (%s)",
|
||||
keep_name, strerror(errno));
|
||||
} else {
|
||||
if (keep_msg_len > 0) {
|
||||
write_or_die(keep_fd, keep_msg, keep_msg_len);
|
||||
write_or_die(keep_fd, "\n", 1);
|
||||
}
|
||||
if (close(keep_fd) != 0)
|
||||
die("cannot write keep file");
|
||||
die("cannot close written keep file '%s' (%s)",
|
||||
keep_name, strerror(errno));
|
||||
report = "keep";
|
||||
}
|
||||
}
|
||||
|
||||
16
lockfile.c
16
lockfile.c
@@ -155,11 +155,25 @@ static int lock_file(struct lock_file *lk, const char *path, int flags)
|
||||
return lk->fd;
|
||||
}
|
||||
|
||||
|
||||
NORETURN void unable_to_lock_index_die(const char *path, int err)
|
||||
{
|
||||
if (errno == 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"
|
||||
"process is running and remove the file manually to continue.",
|
||||
path, strerror(err));
|
||||
} else {
|
||||
die("Unable to create '%s.lock': %s", path, strerror(err));
|
||||
}
|
||||
}
|
||||
|
||||
int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags)
|
||||
{
|
||||
int fd = lock_file(lk, path, flags);
|
||||
if (fd < 0 && (flags & LOCK_DIE_ON_ERROR))
|
||||
die("unable to create '%s.lock': %s", path, strerror(errno));
|
||||
unable_to_lock_index_die(path, errno);
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user