commit
c2f3bf071e
|
@ -60,7 +60,6 @@ git-merge-stupid
|
||||||
git-mktag
|
git-mktag
|
||||||
git-name-rev
|
git-name-rev
|
||||||
git-mv
|
git-mv
|
||||||
git-octopus
|
|
||||||
git-pack-redundant
|
git-pack-redundant
|
||||||
git-pack-objects
|
git-pack-objects
|
||||||
git-parse-remote
|
git-parse-remote
|
||||||
|
|
|
@ -18,6 +18,14 @@
|
||||||
object name of pre- and post-image blob on the "index"
|
object name of pre- and post-image blob on the "index"
|
||||||
line when generating a patch format output.
|
line when generating a patch format output.
|
||||||
|
|
||||||
|
--abbrev[=<n>]::
|
||||||
|
Instead of showing the full 40-byte hexadecimal object
|
||||||
|
name in diff-raw format output and diff-tree header
|
||||||
|
lines, show only handful dhexigits prefix. This is
|
||||||
|
independent of --full-index option above, which controls
|
||||||
|
the diff-patch output format. Non default number of
|
||||||
|
digits can be specified with --abbrev=<n>.
|
||||||
|
|
||||||
-B::
|
-B::
|
||||||
Break complete rewrite changes into pairs of delete and create.
|
Break complete rewrite changes into pairs of delete and create.
|
||||||
|
|
||||||
|
|
|
@ -211,10 +211,12 @@ $ git fetch --tags <8>
|
||||||
|
|
||||||
<1> repeat as needed.
|
<1> repeat as needed.
|
||||||
<2> extract patches from your branch for e-mail submission.
|
<2> extract patches from your branch for e-mail submission.
|
||||||
<3> "pull" fetches from "origin" by default and merges.
|
<3> "pull" fetches from "origin" by default and merges into the
|
||||||
<4> look at the changes since last time we checked, only in the
|
current branch.
|
||||||
|
<4> immediately after pulling, look at the changes done upstream
|
||||||
|
since last time we checked, only in the
|
||||||
area we are interested in.
|
area we are interested in.
|
||||||
<5> fetch from a specific branch from a specific repository and and merge.
|
<5> fetch from a specific branch from a specific repository and merge.
|
||||||
<6> revert the pull.
|
<6> revert the pull.
|
||||||
<7> garbage collect leftover objects from reverted pull.
|
<7> garbage collect leftover objects from reverted pull.
|
||||||
<8> from time to time, obtain official tags from the "origin"
|
<8> from time to time, obtain official tags from the "origin"
|
||||||
|
@ -330,7 +332,7 @@ master, nor exposed as a part of a stable branch.
|
||||||
<8> and bundle topic branches still cooking.
|
<8> and bundle topic branches still cooking.
|
||||||
<9> backport a critical fix.
|
<9> backport a critical fix.
|
||||||
<10> create a signed tag.
|
<10> create a signed tag.
|
||||||
<11> make sure I did not accidentally rewound master beyond what I
|
<11> make sure I did not accidentally rewind master beyond what I
|
||||||
already pushed out. "ko" shorthand points at the repository I have
|
already pushed out. "ko" shorthand points at the repository I have
|
||||||
at kernel.org, and looks like this:
|
at kernel.org, and looks like this:
|
||||||
$ cat .git/remotes/ko
|
$ cat .git/remotes/ko
|
||||||
|
@ -340,6 +342,8 @@ Pull: maint:refs/tags/ko-maint
|
||||||
Push: master
|
Push: master
|
||||||
Push: +pu
|
Push: +pu
|
||||||
Push: maint
|
Push: maint
|
||||||
|
In the output from "git show-branch", "master" should have
|
||||||
|
everything "ko-master" has.
|
||||||
<12> push out the bleeding edge.
|
<12> push out the bleeding edge.
|
||||||
<13> push the tag out, too.
|
<13> push the tag out, too.
|
||||||
------------
|
------------
|
||||||
|
@ -357,8 +361,8 @@ and maintain access to the repository by developers.
|
||||||
* gitlink:git-shell[1] can be used as a 'restricted login shell'
|
* gitlink:git-shell[1] can be used as a 'restricted login shell'
|
||||||
for shared central repository users.
|
for shared central repository users.
|
||||||
|
|
||||||
* link:howto/update-hook-example.txt[update hook howto] has a
|
link:howto/update-hook-example.txt[update hook howto] has a good
|
||||||
good example of managing a shared central repository.
|
example of managing a shared central repository.
|
||||||
|
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
|
@ -424,3 +428,14 @@ for branch policy control.
|
||||||
david is the release manager and is the only person who can
|
david is the release manager and is the only person who can
|
||||||
create and push version tags.
|
create and push version tags.
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
HTTP server to support dumb protocol transfer.::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
dev$ git update-server-info <1>
|
||||||
|
dev$ ftp user@isp.example.com <2>
|
||||||
|
ftp> cp -r .git /home/user/myproject.git
|
||||||
|
|
||||||
|
<1> make sure your info/refs and objects/info/packs are up-to-date
|
||||||
|
<2> upload to public HTTP server hosted by your ISP.
|
||||||
|
------------
|
||||||
|
|
|
@ -8,7 +8,8 @@ git-archimport - Import an Arch repository into git
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
`git-archimport` [ -h ] [ -v ] [ -T ] [ -t tempdir ]
|
`git-archimport` [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ]
|
||||||
|
[ -D depth ] [ -t tempdir ]
|
||||||
<archive/branch> [ <archive/branch> ]
|
<archive/branch> [ <archive/branch> ]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
|
@ -63,6 +64,26 @@ OPTIONS
|
||||||
Many tags. Will create a tag for every commit, reflecting the commit
|
Many tags. Will create a tag for every commit, reflecting the commit
|
||||||
name in the Arch repository.
|
name in the Arch repository.
|
||||||
|
|
||||||
|
-f::
|
||||||
|
Use the fast patchset import strategy. This can be significantly
|
||||||
|
faster for large trees, but cannot handle directory renames or
|
||||||
|
permissions changes. The default strategy is slow and safe.
|
||||||
|
|
||||||
|
-o::
|
||||||
|
Use this for compatibility with old-style branch names used by
|
||||||
|
earlier versions of git-archimport. Old-style branch names
|
||||||
|
were category--branch, whereas new-style branch names are
|
||||||
|
archive,category--branch--version.
|
||||||
|
|
||||||
|
-D <depth>::
|
||||||
|
Follow merge ancestry and attempt to import trees that have been
|
||||||
|
merged from. Specify a depth greater than 1 if patch logs have been
|
||||||
|
pruned.
|
||||||
|
|
||||||
|
-a::
|
||||||
|
Attempt to auto-register archives at http://mirrors.sourcecontrol.net
|
||||||
|
This is particularly useful with the -D option.
|
||||||
|
|
||||||
-t <tmpdir>::
|
-t <tmpdir>::
|
||||||
Override the default tempdir.
|
Override the default tempdir.
|
||||||
|
|
||||||
|
|
|
@ -26,13 +26,15 @@ imposes the following rules on how refs are named:
|
||||||
|
|
||||||
. It cannot have ASCII control character (i.e. bytes whose
|
. It cannot have ASCII control character (i.e. bytes whose
|
||||||
values are lower than \040, or \177 `DEL`), space, tilde `~`,
|
values are lower than \040, or \177 `DEL`), space, tilde `~`,
|
||||||
caret `{caret}`, or colon `:` anywhere;
|
caret `{caret}`, colon `:`, question-mark `?`, asterisk `*`,
|
||||||
|
or open bracket `[` anywhere;
|
||||||
|
|
||||||
. It cannot end with a slash `/`.
|
. It cannot end with a slash `/`.
|
||||||
|
|
||||||
These rules makes it easy for shell script based tools to parse
|
These rules makes it easy for shell script based tools to parse
|
||||||
refnames, and also avoids ambiguities in certain refname
|
refnames, pathname expansion by the shell when a refname is used
|
||||||
expressions (see gitlink:git-rev-parse[1]). Namely:
|
unquoted (by mistake), and also avoids ambiguities in certain
|
||||||
|
refname expressions (see gitlink:git-rev-parse[1]). Namely:
|
||||||
|
|
||||||
. double-dot `..` are often used as in `ref1..ref2`, and in some
|
. double-dot `..` are often used as in `ref1..ref2`, and in some
|
||||||
context this notation means `{caret}ref1 ref2` (i.e. not in
|
context this notation means `{caret}ref1 ref2` (i.e. not in
|
||||||
|
|
|
@ -43,7 +43,11 @@ OPTIONS
|
||||||
The heads to update. This is relative to $GIT_DIR
|
The heads to update. This is relative to $GIT_DIR
|
||||||
(e.g. "HEAD", "refs/heads/master"). When unspecified,
|
(e.g. "HEAD", "refs/heads/master"). When unspecified,
|
||||||
all heads are updated to match the remote repository.
|
all heads are updated to match the remote repository.
|
||||||
|
+
|
||||||
|
Usually all the refs from existing repository are stored
|
||||||
|
under the same name in the new repository. Giving explicit
|
||||||
|
<head> arguments instead writes the object names and refs to
|
||||||
|
the standard output, just like get-fetch-pack does.
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
|
|
|
@ -66,6 +66,10 @@ OPTIONS
|
||||||
Update specified paths in the index file before committing.
|
Update specified paths in the index file before committing.
|
||||||
|
|
||||||
|
|
||||||
|
If you make a commit and then found a mistake immediately after
|
||||||
|
that, you can recover from it with gitlink:git-reset[1].
|
||||||
|
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
Written by Linus Torvalds <torvalds@osdl.org> and
|
Written by Linus Torvalds <torvalds@osdl.org> and
|
||||||
|
|
|
@ -8,7 +8,7 @@ git-fetch-pack - Receive missing objects from another repository.
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
git-fetch-pack [-q] [--exec=<git-upload-pack>] [<host>:]<directory> [<refs>...]
|
git-fetch-pack [-q] [-k] [--exec=<git-upload-pack>] [<host>:]<directory> [<refs>...]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
|
@ -29,6 +29,11 @@ OPTIONS
|
||||||
Pass '-q' flag to 'git-unpack-objects'; this makes the
|
Pass '-q' flag to 'git-unpack-objects'; this makes the
|
||||||
cloning process less verbose.
|
cloning process less verbose.
|
||||||
|
|
||||||
|
-k::
|
||||||
|
Do not invoke 'git-unpack-objects' on received data, but
|
||||||
|
create a single packfile out of it instead, and store it
|
||||||
|
in the object database.
|
||||||
|
|
||||||
--exec=<git-upload-pack>::
|
--exec=<git-upload-pack>::
|
||||||
Use this to specify the path to 'git-upload-pack' on the
|
Use this to specify the path to 'git-upload-pack' on the
|
||||||
remote side, if is not found on your $PATH.
|
remote side, if is not found on your $PATH.
|
||||||
|
|
|
@ -37,6 +37,11 @@ include::merge-options.txt[]
|
||||||
include::merge-strategies.txt[]
|
include::merge-strategies.txt[]
|
||||||
|
|
||||||
|
|
||||||
|
If you tried a merge which resulted in a complex conflicts and
|
||||||
|
would want to start over, you can recover with
|
||||||
|
gitlink:git-reset[1].
|
||||||
|
|
||||||
|
|
||||||
HOW MERGE WORKS
|
HOW MERGE WORKS
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
git-octopus(1)
|
|
||||||
==============
|
|
||||||
|
|
||||||
NAME
|
|
||||||
----
|
|
||||||
git-octopus - Merge more than two commits.
|
|
||||||
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
--------
|
|
||||||
'git-octopus'
|
|
||||||
|
|
||||||
DESCRIPTION
|
|
||||||
-----------
|
|
||||||
After running 'git fetch', $GIT_DIR/FETCH_HEAD contains the
|
|
||||||
following information, one line per remote ref:
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
<object name> <ref name> from <repository>
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
Using this information, create and commit an Octopus merge on
|
|
||||||
top of the current HEAD.
|
|
||||||
|
|
||||||
|
|
||||||
Author
|
|
||||||
------
|
|
||||||
Written by Junio C Hamano <junkio@cox.net>
|
|
||||||
|
|
||||||
|
|
||||||
Documentation
|
|
||||||
--------------
|
|
||||||
Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
|
|
||||||
|
|
||||||
GIT
|
|
||||||
---
|
|
||||||
Part of the gitlink:git[7] suite
|
|
||||||
|
|
|
@ -104,6 +104,11 @@ merge the remote `origin` head into the current,
|
||||||
local `master` branch.
|
local `master` branch.
|
||||||
|
|
||||||
|
|
||||||
|
If you tried a pull which resulted in a complex conflicts and
|
||||||
|
would want to start over, you can recover with
|
||||||
|
gitlink:git-reset[1].
|
||||||
|
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
--------
|
--------
|
||||||
gitlink:git-fetch[1], gitlink:git-merge[1]
|
gitlink:git-fetch[1], gitlink:git-merge[1]
|
||||||
|
|
|
@ -111,6 +111,39 @@ remain there.
|
||||||
changes still in the working tree.
|
changes still in the working tree.
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
Undo a merge or pull::
|
||||||
|
+
|
||||||
|
------------
|
||||||
|
$ git pull <1>
|
||||||
|
Trying really trivial in-index merge...
|
||||||
|
fatal: Merge requires file-level merging
|
||||||
|
Nope.
|
||||||
|
...
|
||||||
|
Auto-merging nitfol
|
||||||
|
CONFLICT (content): Merge conflict in nitfol
|
||||||
|
Automatic merge failed/prevented; fix up by hand
|
||||||
|
$ git reset --hard <2>
|
||||||
|
|
||||||
|
<1> try to update from the upstream resulted in a lot of
|
||||||
|
conflicts; you were not ready to spend a lot of time merging
|
||||||
|
right now, so you decide to do that later.
|
||||||
|
<2> "pull" has not made merge commit, so "git reset --hard"
|
||||||
|
which is a synonym for "git reset --hard HEAD" clears the mess
|
||||||
|
from the index file and the working tree.
|
||||||
|
|
||||||
|
$ git pull . topic/branch <3>
|
||||||
|
Updating from 41223... to 13134...
|
||||||
|
Fast forward
|
||||||
|
$ git reset --hard ORIG_HEAD <4>
|
||||||
|
|
||||||
|
<3> merge a topic branch into the current branch, which resulted
|
||||||
|
in a fast forward.
|
||||||
|
<4> but you decided that the topic branch is not ready for public
|
||||||
|
consumption yet. "pull" or "merge" always leaves the original
|
||||||
|
tip of the current branch in ORIG_HEAD, so resetting hard to it
|
||||||
|
brings your index file and the working tree back to that state,
|
||||||
|
and resets the tip of the branch to that commit.
|
||||||
|
------------
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
|
|
|
@ -12,11 +12,11 @@ SYNOPSIS
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
A dumb server that does not do on-the-fly pack generations can
|
A dumb server that does not do on-the-fly pack generations must
|
||||||
have some auxiliary information files in $GIT_DIR/info and
|
have some auxiliary information files in $GIT_DIR/info and
|
||||||
$GIT_OBJECT_DIRECTORY/info directories to help clients discover
|
$GIT_OBJECT_DIRECTORY/info directories to help clients discover
|
||||||
what references and packs the server has and make optimized
|
what references and packs the server has. This command
|
||||||
pull decisions. This command generates such auxiliary files.
|
generates such auxiliary files.
|
||||||
|
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
|
|
|
@ -297,9 +297,6 @@ gitlink:git-merge[1]::
|
||||||
gitlink:git-mv[1]::
|
gitlink:git-mv[1]::
|
||||||
Move or rename a file, a directory, or a symlink.
|
Move or rename a file, a directory, or a symlink.
|
||||||
|
|
||||||
gitlink:git-octopus[1]::
|
|
||||||
Merge more than two commits.
|
|
||||||
|
|
||||||
gitlink:git-pull[1]::
|
gitlink:git-pull[1]::
|
||||||
Fetch from and merge with a remote repository.
|
Fetch from and merge with a remote repository.
|
||||||
|
|
||||||
|
|
|
@ -111,6 +111,10 @@ Another use suggested on the mailing list is to use this hook to
|
||||||
implement access control which is finer grained than the one
|
implement access control which is finer grained than the one
|
||||||
based on filesystem group.
|
based on filesystem group.
|
||||||
|
|
||||||
|
The standard output of this hook is sent to /dev/null; if you
|
||||||
|
want to report something to the git-send-pack on the other end,
|
||||||
|
you can redirect your output to your stderr.
|
||||||
|
|
||||||
post-update
|
post-update
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
@ -125,3 +129,7 @@ the outcome of `git-receive-pack`.
|
||||||
The default post-update hook, when enabled, runs
|
The default post-update hook, when enabled, runs
|
||||||
`git-update-server-info` to keep the information used by dumb
|
`git-update-server-info` to keep the information used by dumb
|
||||||
transport up-to-date.
|
transport up-to-date.
|
||||||
|
|
||||||
|
The standard output of this hook is sent to /dev/null; if you
|
||||||
|
want to report something to the git-send-pack on the other end,
|
||||||
|
you can redirect your output to your stderr.
|
||||||
|
|
|
@ -10,7 +10,7 @@ The pages under http://www.kernel.org/pub/software/scm/git/docs/
|
||||||
are built from Documentation/ directory of the git.git project
|
are built from Documentation/ directory of the git.git project
|
||||||
and needed to be kept up-to-date. The www.kernel.org/ servers
|
and needed to be kept up-to-date. The www.kernel.org/ servers
|
||||||
are mirrored and I was told that the origin of the mirror is on
|
are mirrored and I was told that the origin of the mirror is on
|
||||||
the machine master.kernel.org, on which I was given an account
|
the machine $some.kernel.org, on which I was given an account
|
||||||
when I took over git maintainership from Linus.
|
when I took over git maintainership from Linus.
|
||||||
|
|
||||||
The directories relevant to this how-to are these two:
|
The directories relevant to this how-to are these two:
|
||||||
|
@ -63,7 +63,7 @@ like this:
|
||||||
EOF
|
EOF
|
||||||
$ chmod +x /pub/scm/git/git.git/hooks/post-update
|
$ chmod +x /pub/scm/git/git.git/hooks/post-update
|
||||||
|
|
||||||
There are three things worth mentioning:
|
There are four things worth mentioning:
|
||||||
|
|
||||||
- The update-hook is run after the repository accepts a "git
|
- The update-hook is run after the repository accepts a "git
|
||||||
push", under my user privilege. It is given the full names
|
push", under my user privilege. It is given the full names
|
||||||
|
@ -77,6 +77,10 @@ There are three things worth mentioning:
|
||||||
pull" it does into $HOME/doc-git/docgen/ repository would not
|
pull" it does into $HOME/doc-git/docgen/ repository would not
|
||||||
work correctly.
|
work correctly.
|
||||||
|
|
||||||
|
- The stdout of update hook script is not connected to git
|
||||||
|
push; I run the heavy part of the command inside "at", to
|
||||||
|
receive the execution report via e-mail.
|
||||||
|
|
||||||
- This is still crude and does not protect against simultaneous
|
- This is still crude and does not protect against simultaneous
|
||||||
make invocations stomping on each other. I would need to add
|
make invocations stomping on each other. I would need to add
|
||||||
some locking mechanism for this.
|
some locking mechanism for this.
|
||||||
|
|
|
@ -42,8 +42,7 @@ So here is the step-by-step guide how this all works for me.
|
||||||
|
|
||||||
First create your work tree by cloning Linus's public tree:
|
First create your work tree by cloning Linus's public tree:
|
||||||
|
|
||||||
$ git clone \
|
$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git work
|
||||||
master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6.git work
|
|
||||||
|
|
||||||
Change directory into the cloned tree you just created
|
Change directory into the cloned tree you just created
|
||||||
|
|
||||||
|
@ -53,7 +52,7 @@ Set up a remotes file so that you can fetch the latest from Linus' master
|
||||||
branch into a local branch named "linus":
|
branch into a local branch named "linus":
|
||||||
|
|
||||||
$ cat > .git/remotes/linus
|
$ cat > .git/remotes/linus
|
||||||
URL: master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
|
URL: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
|
||||||
Pull: master:linus
|
Pull: master:linus
|
||||||
^D
|
^D
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,12 @@ SCM, you can skip them during your first pass.
|
||||||
[NOTE]
|
[NOTE]
|
||||||
And those "too deep" descriptions are often marked as Note.
|
And those "too deep" descriptions are often marked as Note.
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
If you are already familiar with another version control system,
|
||||||
|
like CVS, you may want to take a look at
|
||||||
|
link:everyday.html[Everyday GIT in 20 commands or so] first
|
||||||
|
before reading this.
|
||||||
|
|
||||||
|
|
||||||
Creating a git repository
|
Creating a git repository
|
||||||
-------------------------
|
-------------------------
|
||||||
|
@ -1085,9 +1091,10 @@ lacks and transfers (close to) minimum set of objects.
|
||||||
HTTP(S)::
|
HTTP(S)::
|
||||||
`http://remote.machine/path/to/repo.git/`
|
`http://remote.machine/path/to/repo.git/`
|
||||||
+
|
+
|
||||||
HTTP and HTTPS transport are used only for downloading. They
|
Downloader from http and https URL
|
||||||
first obtain the topmost commit object name from the remote site
|
first obtains the topmost commit object name from the remote site
|
||||||
by looking at `repo.git/info/refs` file, tries to obtain the
|
by looking at the specified refname under `repo.git/refs/` directory,
|
||||||
|
and then tries to obtain the
|
||||||
commit object by downloading from `repo.git/objects/xx/xxx\...`
|
commit object by downloading from `repo.git/objects/xx/xxx\...`
|
||||||
using the object name of that commit object. Then it reads the
|
using the object name of that commit object. Then it reads the
|
||||||
commit object to find out its parent commits and the associate
|
commit object to find out its parent commits and the associate
|
||||||
|
@ -1098,7 +1105,9 @@ sometimes also called 'commit walkers'.
|
||||||
The 'commit walkers' are sometimes also called 'dumb
|
The 'commit walkers' are sometimes also called 'dumb
|
||||||
transports', because they do not require any git aware smart
|
transports', because they do not require any git aware smart
|
||||||
server like git Native transport does. Any stock HTTP server
|
server like git Native transport does. Any stock HTTP server
|
||||||
would suffice.
|
that does not even support directory index would suffice. But
|
||||||
|
you must prepare your repository with `git-update-server-info`
|
||||||
|
to help dumb transport downloaders.
|
||||||
+
|
+
|
||||||
There are (confusingly enough) `git-ssh-fetch` and `git-ssh-upload`
|
There are (confusingly enough) `git-ssh-fetch` and `git-ssh-upload`
|
||||||
programs, which are 'commit walkers'; they outlived their
|
programs, which are 'commit walkers'; they outlived their
|
||||||
|
@ -1511,12 +1520,13 @@ A recommended workflow for a "project lead" goes like this:
|
||||||
2. Prepare a public repository accessible to others.
|
2. Prepare a public repository accessible to others.
|
||||||
+
|
+
|
||||||
If other people are pulling from your repository over dumb
|
If other people are pulling from your repository over dumb
|
||||||
transport protocols, you need to keep this repository 'dumb
|
transport protocols (HTTP), you need to keep this repository
|
||||||
transport friendly'. After `git init-db`,
|
'dumb transport friendly'. After `git init-db`,
|
||||||
`$GIT_DIR/hooks/post-update` copied from the standard templates
|
`$GIT_DIR/hooks/post-update` copied from the standard templates
|
||||||
would contain a call to `git-update-server-info` but the
|
would contain a call to `git-update-server-info` but the
|
||||||
`post-update` hook itself is disabled by default -- enable it
|
`post-update` hook itself is disabled by default -- enable it
|
||||||
with `chmod +x post-update`.
|
with `chmod +x post-update`. This makes sure `git-update-server-info`
|
||||||
|
keeps the necessary files up-to-date.
|
||||||
|
|
||||||
3. Push into the public repository from your primary
|
3. Push into the public repository from your primary
|
||||||
repository.
|
repository.
|
||||||
|
@ -1615,7 +1625,9 @@ cooperation you are probably more familiar with as well.
|
||||||
For this, set up a public repository on a machine that is
|
For this, set up a public repository on a machine that is
|
||||||
reachable via SSH by people with "commit privileges". Put the
|
reachable via SSH by people with "commit privileges". Put the
|
||||||
committers in the same user group and make the repository
|
committers in the same user group and make the repository
|
||||||
writable by that group.
|
writable by that group. Make sure their umasks are set up to
|
||||||
|
allow group members to write into directories other members
|
||||||
|
have created.
|
||||||
|
|
||||||
You, as an individual committer, then:
|
You, as an individual committer, then:
|
||||||
|
|
||||||
|
|
8
Makefile
8
Makefile
|
@ -55,7 +55,7 @@ all:
|
||||||
# Define USE_STDEV below if you want git to care about the underlying device
|
# Define USE_STDEV below if you want git to care about the underlying device
|
||||||
# change being considered an inode change from the update-cache perspective.
|
# change being considered an inode change from the update-cache perspective.
|
||||||
|
|
||||||
GIT_VERSION = 0.99.9n
|
GIT_VERSION = 1.0.0
|
||||||
|
|
||||||
# CFLAGS and LDFLAGS are for the users to override from the command line.
|
# CFLAGS and LDFLAGS are for the users to override from the command line.
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ SCRIPT_SH = \
|
||||||
git-cherry.sh git-clone.sh git-commit.sh \
|
git-cherry.sh git-clone.sh git-commit.sh \
|
||||||
git-count-objects.sh git-diff.sh git-fetch.sh \
|
git-count-objects.sh git-diff.sh git-fetch.sh \
|
||||||
git-format-patch.sh git-log.sh git-ls-remote.sh \
|
git-format-patch.sh git-log.sh git-ls-remote.sh \
|
||||||
git-merge-one-file.sh git-octopus.sh git-parse-remote.sh \
|
git-merge-one-file.sh git-parse-remote.sh \
|
||||||
git-prune.sh git-pull.sh git-push.sh git-rebase.sh \
|
git-prune.sh git-pull.sh git-push.sh git-rebase.sh \
|
||||||
git-repack.sh git-request-pull.sh git-reset.sh \
|
git-repack.sh git-request-pull.sh git-reset.sh \
|
||||||
git-resolve.sh git-revert.sh git-sh-setup.sh git-status.sh \
|
git-resolve.sh git-revert.sh git-sh-setup.sh git-status.sh \
|
||||||
|
@ -175,6 +175,7 @@ LIB_OBJS = \
|
||||||
quote.o read-cache.o refs.o run-command.o \
|
quote.o read-cache.o refs.o run-command.o \
|
||||||
server-info.o setup.o sha1_file.o sha1_name.o strbuf.o \
|
server-info.o setup.o sha1_file.o sha1_name.o strbuf.o \
|
||||||
tag.o tree.o usage.o config.o environment.o ctype.o copy.o \
|
tag.o tree.o usage.o config.o environment.o ctype.o copy.o \
|
||||||
|
fetch-clone.o \
|
||||||
$(DIFF_OBJS)
|
$(DIFF_OBJS)
|
||||||
|
|
||||||
LIBS = $(LIB_FILE)
|
LIBS = $(LIB_FILE)
|
||||||
|
@ -497,7 +498,7 @@ clean:
|
||||||
rm -f *.o mozilla-sha1/*.o arm/*.o ppc/*.o compat/*.o $(LIB_FILE)
|
rm -f *.o mozilla-sha1/*.o arm/*.o ppc/*.o compat/*.o $(LIB_FILE)
|
||||||
rm -f $(PROGRAMS) $(SIMPLE_PROGRAMS) git$X
|
rm -f $(PROGRAMS) $(SIMPLE_PROGRAMS) git$X
|
||||||
rm -f $(filter-out gitk,$(SCRIPTS))
|
rm -f $(filter-out gitk,$(SCRIPTS))
|
||||||
rm -f *.spec *.pyc *.pyo
|
rm -f *.spec *.pyc *.pyo */*.pyc */*.pyo
|
||||||
rm -rf $(GIT_TARNAME)
|
rm -rf $(GIT_TARNAME)
|
||||||
rm -f $(GIT_TARNAME).tar.gz git-core_$(GIT_VERSION)-*.tar.gz
|
rm -f $(GIT_TARNAME).tar.gz git-core_$(GIT_VERSION)-*.tar.gz
|
||||||
rm -f git-core_$(GIT_VERSION)-*.dsc
|
rm -f git-core_$(GIT_VERSION)-*.dsc
|
||||||
|
@ -505,3 +506,4 @@ clean:
|
||||||
$(MAKE) -C Documentation/ clean
|
$(MAKE) -C Documentation/ clean
|
||||||
$(MAKE) -C templates clean
|
$(MAKE) -C templates clean
|
||||||
$(MAKE) -C t/ clean
|
$(MAKE) -C t/ clean
|
||||||
|
|
||||||
|
|
23
apply.c
23
apply.c
|
@ -84,14 +84,11 @@ static void *read_patch_file(int fd, unsigned long *sizep)
|
||||||
buffer = xrealloc(buffer, alloc);
|
buffer = xrealloc(buffer, alloc);
|
||||||
nr = alloc - size;
|
nr = alloc - size;
|
||||||
}
|
}
|
||||||
nr = read(fd, buffer + size, nr);
|
nr = xread(fd, buffer + size, nr);
|
||||||
if (!nr)
|
if (!nr)
|
||||||
break;
|
break;
|
||||||
if (nr < 0) {
|
if (nr < 0)
|
||||||
if (errno == EAGAIN)
|
|
||||||
continue;
|
|
||||||
die("git-apply: read returned %s", strerror(errno));
|
die("git-apply: read returned %s", strerror(errno));
|
||||||
}
|
|
||||||
size += nr;
|
size += nr;
|
||||||
}
|
}
|
||||||
*sizep = size;
|
*sizep = size;
|
||||||
|
@ -1006,13 +1003,8 @@ static int read_old_data(struct stat *st, const char *path, void *buf, unsigned
|
||||||
return error("unable to open %s", path);
|
return error("unable to open %s", path);
|
||||||
got = 0;
|
got = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int ret = read(fd, buf + got, size - got);
|
int ret = xread(fd, buf + got, size - got);
|
||||||
if (ret < 0) {
|
if (ret <= 0)
|
||||||
if (errno == EAGAIN)
|
|
||||||
continue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!ret)
|
|
||||||
break;
|
break;
|
||||||
got += ret;
|
got += ret;
|
||||||
}
|
}
|
||||||
|
@ -1600,12 +1592,9 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf,
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return -1;
|
return -1;
|
||||||
while (size) {
|
while (size) {
|
||||||
int written = write(fd, buf, size);
|
int written = xwrite(fd, buf, size);
|
||||||
if (written < 0) {
|
if (written < 0)
|
||||||
if (errno == EINTR || errno == EAGAIN)
|
|
||||||
continue;
|
|
||||||
die("writing file %s: %s", path, strerror(errno));
|
die("writing file %s: %s", path, strerror(errno));
|
||||||
}
|
|
||||||
if (!written)
|
if (!written)
|
||||||
die("out of space writing file %s", path);
|
die("out of space writing file %s", path);
|
||||||
buf += written;
|
buf += written;
|
||||||
|
|
5
cache.h
5
cache.h
|
@ -338,4 +338,9 @@ extern char git_default_name[MAX_GITNAME];
|
||||||
extern char git_commit_encoding[MAX_ENCODING_LENGTH];
|
extern char git_commit_encoding[MAX_ENCODING_LENGTH];
|
||||||
|
|
||||||
extern int copy_fd(int ifd, int ofd);
|
extern int copy_fd(int ifd, int ofd);
|
||||||
|
|
||||||
|
/* Finish off pack transfer receiving end */
|
||||||
|
extern int receive_unpack_pack(int fd[2], const char *me, int quiet);
|
||||||
|
extern int receive_keep_pack(int fd[2], const char *me);
|
||||||
|
|
||||||
#endif /* CACHE_H */
|
#endif /* CACHE_H */
|
||||||
|
|
|
@ -55,10 +55,8 @@ int main(int argc, char **argv)
|
||||||
die("git-cat-file %s: bad file", argv[2]);
|
die("git-cat-file %s: bad file", argv[2]);
|
||||||
|
|
||||||
while (size > 0) {
|
while (size > 0) {
|
||||||
long ret = write(1, buf, size);
|
long ret = xwrite(1, buf, size);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (errno == EAGAIN)
|
|
||||||
continue;
|
|
||||||
/* Ignore epipe */
|
/* Ignore epipe */
|
||||||
if (errno == EPIPE)
|
if (errno == EPIPE)
|
||||||
break;
|
break;
|
||||||
|
|
149
clone-pack.c
149
clone-pack.c
|
@ -1,7 +1,6 @@
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
#include "refs.h"
|
#include "refs.h"
|
||||||
#include "pkt-line.h"
|
#include "pkt-line.h"
|
||||||
#include <sys/wait.h>
|
|
||||||
|
|
||||||
static const char clone_pack_usage[] =
|
static const char clone_pack_usage[] =
|
||||||
"git-clone-pack [--exec=<git-upload-pack>] [<host>:]<directory> [<heads>]*";
|
"git-clone-pack [--exec=<git-upload-pack>] [<host>:]<directory> [<heads>]*";
|
||||||
|
@ -112,139 +111,6 @@ static void write_refs(struct ref *ref)
|
||||||
free(head_path);
|
free(head_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int finish_pack(const char *pack_tmp_name)
|
|
||||||
{
|
|
||||||
int pipe_fd[2];
|
|
||||||
pid_t pid;
|
|
||||||
char idx[PATH_MAX];
|
|
||||||
char final[PATH_MAX];
|
|
||||||
char hash[41];
|
|
||||||
unsigned char sha1[20];
|
|
||||||
char *cp;
|
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
if (pipe(pipe_fd) < 0)
|
|
||||||
die("git-clone-pack: unable to set up pipe");
|
|
||||||
|
|
||||||
strcpy(idx, pack_tmp_name); /* ".git/objects/pack-XXXXXX" */
|
|
||||||
cp = strrchr(idx, '/');
|
|
||||||
memcpy(cp, "/pidx", 5);
|
|
||||||
|
|
||||||
pid = fork();
|
|
||||||
if (pid < 0)
|
|
||||||
die("git-clone-pack: unable to fork off git-index-pack");
|
|
||||||
if (!pid) {
|
|
||||||
close(0);
|
|
||||||
dup2(pipe_fd[1], 1);
|
|
||||||
close(pipe_fd[0]);
|
|
||||||
close(pipe_fd[1]);
|
|
||||||
execlp("git-index-pack","git-index-pack",
|
|
||||||
"-o", idx, pack_tmp_name, NULL);
|
|
||||||
error("cannot exec git-index-pack <%s> <%s>",
|
|
||||||
idx, pack_tmp_name);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
close(pipe_fd[1]);
|
|
||||||
if (read(pipe_fd[0], hash, 40) != 40) {
|
|
||||||
error("git-clone-pack: unable to read from git-index-pack");
|
|
||||||
err = 1;
|
|
||||||
}
|
|
||||||
close(pipe_fd[0]);
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
int status, code;
|
|
||||||
int retval = waitpid(pid, &status, 0);
|
|
||||||
|
|
||||||
if (retval < 0) {
|
|
||||||
if (errno == EINTR)
|
|
||||||
continue;
|
|
||||||
error("waitpid failed (%s)", strerror(retval));
|
|
||||||
goto error_die;
|
|
||||||
}
|
|
||||||
if (WIFSIGNALED(status)) {
|
|
||||||
int sig = WTERMSIG(status);
|
|
||||||
error("git-index-pack died of signal %d", sig);
|
|
||||||
goto error_die;
|
|
||||||
}
|
|
||||||
if (!WIFEXITED(status)) {
|
|
||||||
error("git-index-pack died of unnatural causes %d",
|
|
||||||
status);
|
|
||||||
goto error_die;
|
|
||||||
}
|
|
||||||
code = WEXITSTATUS(status);
|
|
||||||
if (code) {
|
|
||||||
error("git-index-pack died with error code %d", code);
|
|
||||||
goto error_die;
|
|
||||||
}
|
|
||||||
if (err)
|
|
||||||
goto error_die;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
hash[40] = 0;
|
|
||||||
if (get_sha1_hex(hash, sha1)) {
|
|
||||||
error("git-index-pack reported nonsense '%s'", hash);
|
|
||||||
goto error_die;
|
|
||||||
}
|
|
||||||
/* Now we have pack in pack_tmp_name[], and
|
|
||||||
* idx in idx[]; rename them to their final names.
|
|
||||||
*/
|
|
||||||
snprintf(final, sizeof(final),
|
|
||||||
"%s/pack/pack-%s.pack", get_object_directory(), hash);
|
|
||||||
move_temp_to_file(pack_tmp_name, final);
|
|
||||||
chmod(final, 0444);
|
|
||||||
snprintf(final, sizeof(final),
|
|
||||||
"%s/pack/pack-%s.idx", get_object_directory(), hash);
|
|
||||||
move_temp_to_file(idx, final);
|
|
||||||
chmod(final, 0444);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
error_die:
|
|
||||||
unlink(idx);
|
|
||||||
unlink(pack_tmp_name);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int clone_without_unpack(int fd[2])
|
|
||||||
{
|
|
||||||
char tmpfile[PATH_MAX];
|
|
||||||
int ofd, ifd;
|
|
||||||
|
|
||||||
ifd = fd[0];
|
|
||||||
snprintf(tmpfile, sizeof(tmpfile),
|
|
||||||
"%s/pack/tmp-XXXXXX", get_object_directory());
|
|
||||||
ofd = mkstemp(tmpfile);
|
|
||||||
if (ofd < 0)
|
|
||||||
return error("unable to create temporary file %s", tmpfile);
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
char buf[8192];
|
|
||||||
ssize_t sz, wsz, pos;
|
|
||||||
sz = read(ifd, buf, sizeof(buf));
|
|
||||||
if (sz == 0)
|
|
||||||
break;
|
|
||||||
if (sz < 0) {
|
|
||||||
error("error reading pack (%s)", strerror(errno));
|
|
||||||
close(ofd);
|
|
||||||
unlink(tmpfile);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
pos = 0;
|
|
||||||
while (pos < sz) {
|
|
||||||
wsz = write(ofd, buf + pos, sz - pos);
|
|
||||||
if (wsz < 0) {
|
|
||||||
error("error writing pack (%s)",
|
|
||||||
strerror(errno));
|
|
||||||
close(ofd);
|
|
||||||
unlink(tmpfile);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
pos += wsz;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close(ofd);
|
|
||||||
return finish_pack(tmpfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int clone_pack(int fd[2], int nr_match, char **match)
|
static int clone_pack(int fd[2], int nr_match, char **match)
|
||||||
{
|
{
|
||||||
struct ref *refs;
|
struct ref *refs;
|
||||||
|
@ -257,10 +123,19 @@ static int clone_pack(int fd[2], int nr_match, char **match)
|
||||||
}
|
}
|
||||||
clone_handshake(fd, refs);
|
clone_handshake(fd, refs);
|
||||||
|
|
||||||
status = clone_without_unpack(fd);
|
status = receive_keep_pack(fd, "git-clone-pack");
|
||||||
|
|
||||||
if (!status)
|
if (!status) {
|
||||||
|
if (nr_match == 0)
|
||||||
write_refs(refs);
|
write_refs(refs);
|
||||||
|
else
|
||||||
|
while (refs) {
|
||||||
|
printf("%s %s\n",
|
||||||
|
sha1_to_hex(refs->old_sha1),
|
||||||
|
refs->name);
|
||||||
|
refs = refs->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,8 +160,6 @@ int main(int argc, char **argv)
|
||||||
exec = arg + 7;
|
exec = arg + 7;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp("--keep", arg))
|
|
||||||
continue;
|
|
||||||
usage(clone_pack_usage);
|
usage(clone_pack_usage);
|
||||||
}
|
}
|
||||||
dest = arg;
|
dest = arg;
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
#
|
|
||||||
# If you installed git by hand previously, you may find this
|
|
||||||
# script useful to remove the symbolic links that we shipped
|
|
||||||
# for backward compatibility.
|
|
||||||
#
|
|
||||||
# Running this script with the previous installation directory
|
|
||||||
# like this:
|
|
||||||
#
|
|
||||||
# $ cmd-rename.sh /usr/local/bin/
|
|
||||||
#
|
|
||||||
# would clean them.
|
|
||||||
|
|
||||||
d="$1"
|
|
||||||
test -d "$d" || exit
|
|
||||||
while read old new
|
|
||||||
do
|
|
||||||
rm -f "$d/$old"
|
|
||||||
done <<\EOF
|
|
||||||
git-add-script git-add
|
|
||||||
git-archimport-script git-archimport
|
|
||||||
git-bisect-script git-bisect
|
|
||||||
git-branch-script git-branch
|
|
||||||
git-checkout-script git-checkout
|
|
||||||
git-cherry-pick-script git-cherry-pick
|
|
||||||
git-clone-script git-clone
|
|
||||||
git-commit-script git-commit
|
|
||||||
git-count-objects-script git-count-objects
|
|
||||||
git-cvsimport-script git-cvsimport
|
|
||||||
git-diff-script git-diff
|
|
||||||
git-send-email-script git-send-email
|
|
||||||
git-fetch-script git-fetch
|
|
||||||
git-format-patch-script git-format-patch
|
|
||||||
git-log-script git-log
|
|
||||||
git-ls-remote-script git-ls-remote
|
|
||||||
git-merge-one-file-script git-merge-one-file
|
|
||||||
git-octopus-script git-octopus
|
|
||||||
git-parse-remote-script git-parse-remote
|
|
||||||
git-prune-script git-prune
|
|
||||||
git-pull-script git-pull
|
|
||||||
git-push-script git-push
|
|
||||||
git-rebase-script git-rebase
|
|
||||||
git-relink-script git-relink
|
|
||||||
git-rename-script git-rename
|
|
||||||
git-repack-script git-repack
|
|
||||||
git-request-pull-script git-request-pull
|
|
||||||
git-reset-script git-reset
|
|
||||||
git-resolve-script git-resolve
|
|
||||||
git-revert-script git-revert
|
|
||||||
git-sh-setup-script git-sh-setup
|
|
||||||
git-status-script git-status
|
|
||||||
git-tag-script git-tag
|
|
||||||
git-verify-tag-script git-verify-tag
|
|
||||||
git-http-pull git-http-fetch
|
|
||||||
git-local-pull git-local-fetch
|
|
||||||
git-checkout-cache git-checkout-index
|
|
||||||
git-diff-cache git-diff-index
|
|
||||||
git-merge-cache git-merge-index
|
|
||||||
git-update-cache git-update-index
|
|
||||||
git-convert-cache git-convert-objects
|
|
||||||
git-fsck-cache git-fsck-objects
|
|
||||||
EOF
|
|
15
copy.c
15
copy.c
|
@ -6,30 +6,25 @@ int copy_fd(int ifd, int ofd)
|
||||||
int len;
|
int len;
|
||||||
char buffer[8192];
|
char buffer[8192];
|
||||||
char *buf = buffer;
|
char *buf = buffer;
|
||||||
len = read(ifd, buffer, sizeof(buffer));
|
len = xread(ifd, buffer, sizeof(buffer));
|
||||||
if (!len)
|
if (!len)
|
||||||
break;
|
break;
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
int read_error;
|
int read_error;
|
||||||
if (errno == EAGAIN)
|
|
||||||
continue;
|
|
||||||
read_error = errno;
|
read_error = errno;
|
||||||
close(ifd);
|
close(ifd);
|
||||||
return error("copy-fd: read returned %s",
|
return error("copy-fd: read returned %s",
|
||||||
strerror(read_error));
|
strerror(read_error));
|
||||||
}
|
}
|
||||||
while (1) {
|
while (len) {
|
||||||
int written = write(ofd, buf, len);
|
int written = xwrite(ofd, buf, len);
|
||||||
if (written > 0) {
|
if (written > 0) {
|
||||||
buf += written;
|
buf += written;
|
||||||
len -= written;
|
len -= written;
|
||||||
if (!len)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (!written)
|
else if (!written)
|
||||||
return error("copy-fd: write returned 0");
|
return error("copy-fd: write returned 0");
|
||||||
if (errno == EAGAIN || errno == EINTR)
|
else
|
||||||
continue;
|
|
||||||
return error("copy-fd: write returned %s",
|
return error("copy-fd: write returned %s",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ static int sha1flush(struct sha1file *f, unsigned int count)
|
||||||
void *buf = f->buffer;
|
void *buf = f->buffer;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int ret = write(f->fd, buf, count);
|
int ret = xwrite(f->fd, buf, count);
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
buf += ret;
|
buf += ret;
|
||||||
count -= ret;
|
count -= ret;
|
||||||
|
@ -25,8 +25,6 @@ static int sha1flush(struct sha1file *f, unsigned int count)
|
||||||
}
|
}
|
||||||
if (!ret)
|
if (!ret)
|
||||||
die("sha1 file '%s' write error. Out of diskspace", f->name);
|
die("sha1 file '%s' write error. Out of diskspace", f->name);
|
||||||
if (errno == EAGAIN || errno == EINTR)
|
|
||||||
continue;
|
|
||||||
die("sha1 file '%s' write error (%s)", f->name, strerror(errno));
|
die("sha1 file '%s' write error (%s)", f->name, strerror(errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
git-core (1.0.0-0) unstable; urgency=low
|
||||||
|
|
||||||
|
* GIT 1.0.0
|
||||||
|
|
||||||
|
-- Junio C Hamano <junkio@cox.net> Wed, 21 Dec 2005 00:01:00 -0800
|
||||||
|
|
||||||
git-core (0.99.9n-0) unstable; urgency=low
|
git-core (0.99.9n-0) unstable; urgency=low
|
||||||
|
|
||||||
* GIT 0.99.9n aka 1.0rc6
|
* GIT 0.99.9n aka 1.0rc6
|
||||||
|
|
34
diff-delta.c
34
diff-delta.c
|
@ -84,20 +84,15 @@ typedef struct s_chanode {
|
||||||
} chanode_t;
|
} chanode_t;
|
||||||
|
|
||||||
typedef struct s_chastore {
|
typedef struct s_chastore {
|
||||||
chanode_t *head, *tail;
|
|
||||||
int isize, nsize;
|
int isize, nsize;
|
||||||
chanode_t *ancur;
|
chanode_t *ancur;
|
||||||
chanode_t *sncur;
|
|
||||||
int scurr;
|
|
||||||
} chastore_t;
|
} chastore_t;
|
||||||
|
|
||||||
static void cha_init(chastore_t *cha, int isize, int icount)
|
static void cha_init(chastore_t *cha, int isize, int icount)
|
||||||
{
|
{
|
||||||
cha->head = cha->tail = NULL;
|
|
||||||
cha->isize = isize;
|
cha->isize = isize;
|
||||||
cha->nsize = icount * isize;
|
cha->nsize = icount * isize;
|
||||||
cha->ancur = cha->sncur = NULL;
|
cha->ancur = NULL;
|
||||||
cha->scurr = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *cha_alloc(chastore_t *cha)
|
static void *cha_alloc(chastore_t *cha)
|
||||||
|
@ -111,12 +106,7 @@ static void *cha_alloc(chastore_t *cha)
|
||||||
if (!ancur)
|
if (!ancur)
|
||||||
return NULL;
|
return NULL;
|
||||||
ancur->icurr = 0;
|
ancur->icurr = 0;
|
||||||
ancur->next = NULL;
|
ancur->next = cha->ancur;
|
||||||
if (cha->tail)
|
|
||||||
cha->tail->next = ancur;
|
|
||||||
if (!cha->head)
|
|
||||||
cha->head = ancur;
|
|
||||||
cha->tail = ancur;
|
|
||||||
cha->ancur = ancur;
|
cha->ancur = ancur;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +117,7 @@ static void *cha_alloc(chastore_t *cha)
|
||||||
|
|
||||||
static void cha_free(chastore_t *cha)
|
static void cha_free(chastore_t *cha)
|
||||||
{
|
{
|
||||||
chanode_t *cur = cha->head;
|
chanode_t *cur = cha->ancur;
|
||||||
while (cur) {
|
while (cur) {
|
||||||
chanode_t *tmp = cur;
|
chanode_t *tmp = cur;
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
|
@ -142,7 +132,6 @@ typedef struct s_bdrecord {
|
||||||
} bdrecord_t;
|
} bdrecord_t;
|
||||||
|
|
||||||
typedef struct s_bdfile {
|
typedef struct s_bdfile {
|
||||||
const unsigned char *data, *top;
|
|
||||||
chastore_t cha;
|
chastore_t cha;
|
||||||
unsigned int fphbits;
|
unsigned int fphbits;
|
||||||
bdrecord_t **fphash;
|
bdrecord_t **fphash;
|
||||||
|
@ -152,7 +141,7 @@ static int delta_prepare(const unsigned char *buf, int bufsize, bdfile_t *bdf)
|
||||||
{
|
{
|
||||||
unsigned int fphbits;
|
unsigned int fphbits;
|
||||||
int i, hsize;
|
int i, hsize;
|
||||||
const unsigned char *base, *data, *top;
|
const unsigned char *data, *top;
|
||||||
bdrecord_t *brec;
|
bdrecord_t *brec;
|
||||||
bdrecord_t **fphash;
|
bdrecord_t **fphash;
|
||||||
|
|
||||||
|
@ -165,13 +154,12 @@ static int delta_prepare(const unsigned char *buf, int bufsize, bdfile_t *bdf)
|
||||||
fphash[i] = NULL;
|
fphash[i] = NULL;
|
||||||
cha_init(&bdf->cha, sizeof(bdrecord_t), hsize / 4 + 1);
|
cha_init(&bdf->cha, sizeof(bdrecord_t), hsize / 4 + 1);
|
||||||
|
|
||||||
bdf->data = data = base = buf;
|
top = buf + bufsize;
|
||||||
bdf->top = top = buf + bufsize;
|
data = buf + (bufsize / BLK_SIZE) * BLK_SIZE;
|
||||||
data += (bufsize / BLK_SIZE) * BLK_SIZE;
|
|
||||||
if (data == top)
|
if (data == top)
|
||||||
data -= BLK_SIZE;
|
data -= BLK_SIZE;
|
||||||
|
|
||||||
for ( ; data >= base; data -= BLK_SIZE) {
|
for ( ; data >= buf; data -= BLK_SIZE) {
|
||||||
brec = cha_alloc(&bdf->cha);
|
brec = cha_alloc(&bdf->cha);
|
||||||
if (!brec) {
|
if (!brec) {
|
||||||
cha_free(&bdf->cha);
|
cha_free(&bdf->cha);
|
||||||
|
@ -208,7 +196,7 @@ void *diff_delta(void *from_buf, unsigned long from_size,
|
||||||
{
|
{
|
||||||
int i, outpos, outsize, inscnt, csize, msize, moff;
|
int i, outpos, outsize, inscnt, csize, msize, moff;
|
||||||
unsigned int fp;
|
unsigned int fp;
|
||||||
const unsigned char *data, *top, *ptr1, *ptr2;
|
const unsigned char *ref_data, *ref_top, *data, *top, *ptr1, *ptr2;
|
||||||
unsigned char *out, *orig;
|
unsigned char *out, *orig;
|
||||||
bdrecord_t *brec;
|
bdrecord_t *brec;
|
||||||
bdfile_t bdf;
|
bdfile_t bdf;
|
||||||
|
@ -224,6 +212,8 @@ void *diff_delta(void *from_buf, unsigned long from_size,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ref_data = from_buf;
|
||||||
|
ref_top = from_buf + from_size;
|
||||||
data = to_buf;
|
data = to_buf;
|
||||||
top = to_buf + to_size;
|
top = to_buf + to_size;
|
||||||
|
|
||||||
|
@ -253,7 +243,7 @@ void *diff_delta(void *from_buf, unsigned long from_size,
|
||||||
i = HASH(fp, bdf.fphbits);
|
i = HASH(fp, bdf.fphbits);
|
||||||
for (brec = bdf.fphash[i]; brec; brec = brec->next) {
|
for (brec = bdf.fphash[i]; brec; brec = brec->next) {
|
||||||
if (brec->fp == fp) {
|
if (brec->fp == fp) {
|
||||||
csize = bdf.top - brec->ptr;
|
csize = ref_top - brec->ptr;
|
||||||
if (csize > top - data)
|
if (csize > top - data)
|
||||||
csize = top - data;
|
csize = top - data;
|
||||||
for (ptr1 = brec->ptr, ptr2 = data;
|
for (ptr1 = brec->ptr, ptr2 = data;
|
||||||
|
@ -262,7 +252,7 @@ void *diff_delta(void *from_buf, unsigned long from_size,
|
||||||
|
|
||||||
csize = ptr1 - brec->ptr;
|
csize = ptr1 - brec->ptr;
|
||||||
if (csize > msize) {
|
if (csize > msize) {
|
||||||
moff = brec->ptr - bdf.data;
|
moff = brec->ptr - ref_data;
|
||||||
msize = csize;
|
msize = csize;
|
||||||
if (msize >= 0x10000) {
|
if (msize >= 0x10000) {
|
||||||
msize = 0x10000;
|
msize = 0x10000;
|
||||||
|
|
38
diff-tree.c
38
diff-tree.c
|
@ -14,11 +14,6 @@ static enum cmit_fmt commit_format = CMIT_FMT_RAW;
|
||||||
|
|
||||||
static struct diff_options diff_options;
|
static struct diff_options diff_options;
|
||||||
|
|
||||||
static void call_diff_setup_done(void)
|
|
||||||
{
|
|
||||||
diff_setup_done(&diff_options);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int call_diff_flush(void)
|
static int call_diff_flush(void)
|
||||||
{
|
{
|
||||||
diffcore_std(&diff_options);
|
diffcore_std(&diff_options);
|
||||||
|
@ -43,7 +38,6 @@ static int diff_tree_sha1_top(const unsigned char *old,
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
call_diff_setup_done();
|
|
||||||
ret = diff_tree_sha1(old, new, base, &diff_options);
|
ret = diff_tree_sha1(old, new, base, &diff_options);
|
||||||
call_diff_flush();
|
call_diff_flush();
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -55,7 +49,6 @@ static int diff_root_tree(const unsigned char *new, const char *base)
|
||||||
void *tree;
|
void *tree;
|
||||||
struct tree_desc empty, real;
|
struct tree_desc empty, real;
|
||||||
|
|
||||||
call_diff_setup_done();
|
|
||||||
tree = read_object_with_reference(new, "tree", &real.size, NULL);
|
tree = read_object_with_reference(new, "tree", &real.size, NULL);
|
||||||
if (!tree)
|
if (!tree)
|
||||||
die("unable to read root tree (%s)", sha1_to_hex(new));
|
die("unable to read root tree (%s)", sha1_to_hex(new));
|
||||||
|
@ -69,18 +62,29 @@ static int diff_root_tree(const unsigned char *new, const char *base)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *generate_header(const char *commit, const char *parent, const char *msg)
|
static const char *generate_header(const unsigned char *commit_sha1,
|
||||||
|
const unsigned char *parent_sha1,
|
||||||
|
const char *msg)
|
||||||
{
|
{
|
||||||
static char this_header[16384];
|
static char this_header[16384];
|
||||||
int offset;
|
int offset;
|
||||||
unsigned long len;
|
unsigned long len;
|
||||||
|
int abbrev = diff_options.abbrev;
|
||||||
|
|
||||||
if (!verbose_header)
|
if (!verbose_header)
|
||||||
return commit;
|
return sha1_to_hex(commit_sha1);
|
||||||
|
|
||||||
len = strlen(msg);
|
len = strlen(msg);
|
||||||
offset = sprintf(this_header, "%s%s (from %s)\n", header_prefix, commit, parent);
|
|
||||||
offset += pretty_print_commit(commit_format, msg, len, this_header + offset, sizeof(this_header) - offset);
|
offset = sprintf(this_header, "%s%s ",
|
||||||
|
header_prefix,
|
||||||
|
diff_unique_abbrev(commit_sha1, abbrev));
|
||||||
|
offset += sprintf(this_header + offset, "(from %s)\n",
|
||||||
|
parent_sha1 ?
|
||||||
|
diff_unique_abbrev(parent_sha1, abbrev) : "root");
|
||||||
|
offset += pretty_print_commit(commit_format, msg, len,
|
||||||
|
this_header + offset,
|
||||||
|
sizeof(this_header) - offset);
|
||||||
return this_header;
|
return this_header;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +103,7 @@ static int diff_tree_commit(const unsigned char *commit_sha1)
|
||||||
|
|
||||||
/* Root commit? */
|
/* Root commit? */
|
||||||
if (show_root_diff && !commit->parents) {
|
if (show_root_diff && !commit->parents) {
|
||||||
header = generate_header(name, "root", commit->buffer);
|
header = generate_header(sha1, NULL, commit->buffer);
|
||||||
diff_root_tree(commit_sha1, "");
|
diff_root_tree(commit_sha1, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,8 +113,8 @@ static int diff_tree_commit(const unsigned char *commit_sha1)
|
||||||
|
|
||||||
for (parents = commit->parents; parents; parents = parents->next) {
|
for (parents = commit->parents; parents; parents = parents->next) {
|
||||||
struct commit *parent = parents->item;
|
struct commit *parent = parents->item;
|
||||||
header = generate_header(name,
|
header = generate_header(sha1,
|
||||||
sha1_to_hex(parent->object.sha1),
|
parent->object.sha1,
|
||||||
commit->buffer);
|
commit->buffer);
|
||||||
diff_tree_sha1_top(parent->object.sha1, commit_sha1, "");
|
diff_tree_sha1_top(parent->object.sha1, commit_sha1, "");
|
||||||
if (!header && verbose_header) {
|
if (!header && verbose_header) {
|
||||||
|
@ -129,6 +133,7 @@ static int diff_tree_stdin(char *line)
|
||||||
int len = strlen(line);
|
int len = strlen(line);
|
||||||
unsigned char commit[20], parent[20];
|
unsigned char commit[20], parent[20];
|
||||||
static char this_header[1000];
|
static char this_header[1000];
|
||||||
|
int abbrev = diff_options.abbrev;
|
||||||
|
|
||||||
if (!len || line[len-1] != '\n')
|
if (!len || line[len-1] != '\n')
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -138,7 +143,9 @@ static int diff_tree_stdin(char *line)
|
||||||
if (isspace(line[40]) && !get_sha1_hex(line+41, parent)) {
|
if (isspace(line[40]) && !get_sha1_hex(line+41, parent)) {
|
||||||
line[40] = 0;
|
line[40] = 0;
|
||||||
line[81] = 0;
|
line[81] = 0;
|
||||||
sprintf(this_header, "%s (from %s)\n", line, line+41);
|
sprintf(this_header, "%s (from %s)\n",
|
||||||
|
diff_unique_abbrev(commit, abbrev),
|
||||||
|
diff_unique_abbrev(parent, abbrev));
|
||||||
header = this_header;
|
header = this_header;
|
||||||
return diff_tree_sha1_top(parent, commit, "");
|
return diff_tree_sha1_top(parent, commit, "");
|
||||||
}
|
}
|
||||||
|
@ -239,6 +246,7 @@ int main(int argc, const char **argv)
|
||||||
diff_options.recursive = 1;
|
diff_options.recursive = 1;
|
||||||
|
|
||||||
diff_tree_setup_paths(get_pathspec(prefix, argv));
|
diff_tree_setup_paths(get_pathspec(prefix, argv));
|
||||||
|
diff_setup_done(&diff_options);
|
||||||
|
|
||||||
switch (nr_sha1) {
|
switch (nr_sha1) {
|
||||||
case 0:
|
case 0:
|
||||||
|
|
57
diff.c
57
diff.c
|
@ -723,11 +723,13 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o)
|
||||||
|
|
||||||
if (memcmp(one->sha1, two->sha1, 20)) {
|
if (memcmp(one->sha1, two->sha1, 20)) {
|
||||||
char one_sha1[41];
|
char one_sha1[41];
|
||||||
const char *index_fmt = o->full_index ? "index %s..%s" : "index %.7s..%.7s";
|
int abbrev = o->full_index ? 40 : DIFF_DEFAULT_INDEX_ABBREV;
|
||||||
memcpy(one_sha1, sha1_to_hex(one->sha1), 41);
|
memcpy(one_sha1, sha1_to_hex(one->sha1), 41);
|
||||||
|
|
||||||
len += snprintf(msg + len, sizeof(msg) - len,
|
len += snprintf(msg + len, sizeof(msg) - len,
|
||||||
index_fmt, one_sha1, sha1_to_hex(two->sha1));
|
"index %.*s..%.*s",
|
||||||
|
abbrev, one_sha1, abbrev,
|
||||||
|
sha1_to_hex(two->sha1));
|
||||||
if (one->mode == two->mode)
|
if (one->mode == two->mode)
|
||||||
len += snprintf(msg + len, sizeof(msg) - len,
|
len += snprintf(msg + len, sizeof(msg) - len,
|
||||||
" %06o", one->mode);
|
" %06o", one->mode);
|
||||||
|
@ -791,6 +793,8 @@ int diff_setup_done(struct diff_options *options)
|
||||||
}
|
}
|
||||||
if (options->setup & DIFF_SETUP_USE_SIZE_CACHE)
|
if (options->setup & DIFF_SETUP_USE_SIZE_CACHE)
|
||||||
use_size_cache = 1;
|
use_size_cache = 1;
|
||||||
|
if (options->abbrev <= 0 || 40 < options->abbrev)
|
||||||
|
options->abbrev = 40; /* full */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -841,6 +845,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
|
||||||
}
|
}
|
||||||
else if (!strcmp(arg, "--find-copies-harder"))
|
else if (!strcmp(arg, "--find-copies-harder"))
|
||||||
options->find_copies_harder = 1;
|
options->find_copies_harder = 1;
|
||||||
|
else if (!strcmp(arg, "--abbrev"))
|
||||||
|
options->abbrev = DIFF_DEFAULT_ABBREV;
|
||||||
|
else if (!strncmp(arg, "--abbrev=", 9))
|
||||||
|
options->abbrev = strtoul(arg + 9, NULL, 10);
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -947,14 +955,49 @@ void diff_free_filepair(struct diff_filepair *p)
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is different from find_unique_abbrev() in that
|
||||||
|
* it needs to deal with 0{40} SHA1.
|
||||||
|
*/
|
||||||
|
const char *diff_unique_abbrev(const unsigned char *sha1, int len)
|
||||||
|
{
|
||||||
|
int abblen;
|
||||||
|
const char *abbrev;
|
||||||
|
if (len == 40)
|
||||||
|
return sha1_to_hex(sha1);
|
||||||
|
|
||||||
|
abbrev = find_unique_abbrev(sha1, len);
|
||||||
|
if (!abbrev) {
|
||||||
|
if (!memcmp(sha1, null_sha1, 20)) {
|
||||||
|
char *buf = sha1_to_hex(null_sha1);
|
||||||
|
if (len < 37)
|
||||||
|
strcpy(buf + len, "...");
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return sha1_to_hex(sha1);
|
||||||
|
}
|
||||||
|
abblen = strlen(abbrev);
|
||||||
|
if (abblen < 37) {
|
||||||
|
static char hex[41];
|
||||||
|
if (len < abblen && abblen <= len + 2)
|
||||||
|
sprintf(hex, "%s%.*s", abbrev, len+3-abblen, "..");
|
||||||
|
else
|
||||||
|
sprintf(hex, "%s...", abbrev);
|
||||||
|
return hex;
|
||||||
|
}
|
||||||
|
return sha1_to_hex(sha1);
|
||||||
|
}
|
||||||
|
|
||||||
static void diff_flush_raw(struct diff_filepair *p,
|
static void diff_flush_raw(struct diff_filepair *p,
|
||||||
int line_termination,
|
int line_termination,
|
||||||
int inter_name_termination,
|
int inter_name_termination,
|
||||||
int output_format)
|
struct diff_options *options)
|
||||||
{
|
{
|
||||||
int two_paths;
|
int two_paths;
|
||||||
char status[10];
|
char status[10];
|
||||||
|
int abbrev = options->abbrev;
|
||||||
const char *path_one, *path_two;
|
const char *path_one, *path_two;
|
||||||
|
int output_format = options->output_format;
|
||||||
|
|
||||||
path_one = p->one->path;
|
path_one = p->one->path;
|
||||||
path_two = p->two->path;
|
path_two = p->two->path;
|
||||||
|
@ -985,8 +1028,10 @@ static void diff_flush_raw(struct diff_filepair *p,
|
||||||
}
|
}
|
||||||
if (output_format != DIFF_FORMAT_NAME_STATUS) {
|
if (output_format != DIFF_FORMAT_NAME_STATUS) {
|
||||||
printf(":%06o %06o %s ",
|
printf(":%06o %06o %s ",
|
||||||
p->one->mode, p->two->mode, sha1_to_hex(p->one->sha1));
|
p->one->mode, p->two->mode,
|
||||||
printf("%s ", sha1_to_hex(p->two->sha1));
|
diff_unique_abbrev(p->one->sha1, abbrev));
|
||||||
|
printf("%s ",
|
||||||
|
diff_unique_abbrev(p->two->sha1, abbrev));
|
||||||
}
|
}
|
||||||
printf("%s%c%s", status, inter_name_termination, path_one);
|
printf("%s%c%s", status, inter_name_termination, path_one);
|
||||||
if (two_paths)
|
if (two_paths)
|
||||||
|
@ -1194,7 +1239,7 @@ void diff_flush(struct diff_options *options)
|
||||||
case DIFF_FORMAT_NAME_STATUS:
|
case DIFF_FORMAT_NAME_STATUS:
|
||||||
diff_flush_raw(p, line_termination,
|
diff_flush_raw(p, line_termination,
|
||||||
inter_name_termination,
|
inter_name_termination,
|
||||||
diff_output_format);
|
options);
|
||||||
break;
|
break;
|
||||||
case DIFF_FORMAT_NAME:
|
case DIFF_FORMAT_NAME:
|
||||||
diff_flush_name(p,
|
diff_flush_name(p,
|
||||||
|
|
9
diff.h
9
diff.h
|
@ -44,6 +44,7 @@ struct diff_options {
|
||||||
int reverse_diff;
|
int reverse_diff;
|
||||||
int rename_limit;
|
int rename_limit;
|
||||||
int setup;
|
int setup;
|
||||||
|
int abbrev;
|
||||||
|
|
||||||
change_fn_t change;
|
change_fn_t change;
|
||||||
add_remove_fn_t add_remove;
|
add_remove_fn_t add_remove;
|
||||||
|
@ -87,6 +88,9 @@ extern int diff_setup_done(struct diff_options *);
|
||||||
|
|
||||||
#define DIFF_PICKAXE_ALL 1
|
#define DIFF_PICKAXE_ALL 1
|
||||||
|
|
||||||
|
#define DIFF_DEFAULT_INDEX_ABBREV 7 /* hex digits */
|
||||||
|
#define DIFF_DEFAULT_ABBREV 7 /* hex digits */
|
||||||
|
|
||||||
extern void diffcore_std(struct diff_options *);
|
extern void diffcore_std(struct diff_options *);
|
||||||
|
|
||||||
extern void diffcore_std_no_resolve(struct diff_options *);
|
extern void diffcore_std_no_resolve(struct diff_options *);
|
||||||
|
@ -98,7 +102,8 @@ extern void diffcore_std_no_resolve(struct diff_options *);
|
||||||
" -u synonym for -p.\n" \
|
" -u synonym for -p.\n" \
|
||||||
" --name-only show only names of changed files.\n" \
|
" --name-only show only names of changed files.\n" \
|
||||||
" --name-status show names and status of changed files.\n" \
|
" --name-status show names and status of changed files.\n" \
|
||||||
" --full-index show full object name on index ines.\n" \
|
" --full-index show full object name on index lines.\n" \
|
||||||
|
" --abbrev=<n> abbreviate object names in diff-tree header and diff-raw.\n" \
|
||||||
" -R swap input file pairs.\n" \
|
" -R swap input file pairs.\n" \
|
||||||
" -B detect complete rewrites.\n" \
|
" -B detect complete rewrites.\n" \
|
||||||
" -M detect renames.\n" \
|
" -M detect renames.\n" \
|
||||||
|
@ -137,4 +142,6 @@ extern void diff_flush(struct diff_options*);
|
||||||
#define DIFF_STATUS_FILTER_AON '*'
|
#define DIFF_STATUS_FILTER_AON '*'
|
||||||
#define DIFF_STATUS_FILTER_BROKEN 'B'
|
#define DIFF_STATUS_FILTER_BROKEN 'B'
|
||||||
|
|
||||||
|
extern const char *diff_unique_abbrev(const unsigned char *, int);
|
||||||
|
|
||||||
#endif /* DIFF_H */
|
#endif /* DIFF_H */
|
||||||
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
#include "cache.h"
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
static int finish_pack(const char *pack_tmp_name, const char *me)
|
||||||
|
{
|
||||||
|
int pipe_fd[2];
|
||||||
|
pid_t pid;
|
||||||
|
char idx[PATH_MAX];
|
||||||
|
char final[PATH_MAX];
|
||||||
|
char hash[41];
|
||||||
|
unsigned char sha1[20];
|
||||||
|
char *cp;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
if (pipe(pipe_fd) < 0)
|
||||||
|
die("%s: unable to set up pipe", me);
|
||||||
|
|
||||||
|
strcpy(idx, pack_tmp_name); /* ".git/objects/pack-XXXXXX" */
|
||||||
|
cp = strrchr(idx, '/');
|
||||||
|
memcpy(cp, "/pidx", 5);
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
if (pid < 0)
|
||||||
|
die("git-clone-pack: unable to fork off git-index-pack");
|
||||||
|
if (!pid) {
|
||||||
|
close(0);
|
||||||
|
dup2(pipe_fd[1], 1);
|
||||||
|
close(pipe_fd[0]);
|
||||||
|
close(pipe_fd[1]);
|
||||||
|
execlp("git-index-pack","git-index-pack",
|
||||||
|
"-o", idx, pack_tmp_name, NULL);
|
||||||
|
error("cannot exec git-index-pack <%s> <%s>",
|
||||||
|
idx, pack_tmp_name);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
close(pipe_fd[1]);
|
||||||
|
if (read(pipe_fd[0], hash, 40) != 40) {
|
||||||
|
error("%s: unable to read from git-index-pack", me);
|
||||||
|
err = 1;
|
||||||
|
}
|
||||||
|
close(pipe_fd[0]);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
int status, code;
|
||||||
|
int retval = waitpid(pid, &status, 0);
|
||||||
|
|
||||||
|
if (retval < 0) {
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
error("waitpid failed (%s)", strerror(retval));
|
||||||
|
goto error_die;
|
||||||
|
}
|
||||||
|
if (WIFSIGNALED(status)) {
|
||||||
|
int sig = WTERMSIG(status);
|
||||||
|
error("git-index-pack died of signal %d", sig);
|
||||||
|
goto error_die;
|
||||||
|
}
|
||||||
|
if (!WIFEXITED(status)) {
|
||||||
|
error("git-index-pack died of unnatural causes %d",
|
||||||
|
status);
|
||||||
|
goto error_die;
|
||||||
|
}
|
||||||
|
code = WEXITSTATUS(status);
|
||||||
|
if (code) {
|
||||||
|
error("git-index-pack died with error code %d", code);
|
||||||
|
goto error_die;
|
||||||
|
}
|
||||||
|
if (err)
|
||||||
|
goto error_die;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
hash[40] = 0;
|
||||||
|
if (get_sha1_hex(hash, sha1)) {
|
||||||
|
error("git-index-pack reported nonsense '%s'", hash);
|
||||||
|
goto error_die;
|
||||||
|
}
|
||||||
|
/* Now we have pack in pack_tmp_name[], and
|
||||||
|
* idx in idx[]; rename them to their final names.
|
||||||
|
*/
|
||||||
|
snprintf(final, sizeof(final),
|
||||||
|
"%s/pack/pack-%s.pack", get_object_directory(), hash);
|
||||||
|
move_temp_to_file(pack_tmp_name, final);
|
||||||
|
chmod(final, 0444);
|
||||||
|
snprintf(final, sizeof(final),
|
||||||
|
"%s/pack/pack-%s.idx", get_object_directory(), hash);
|
||||||
|
move_temp_to_file(idx, final);
|
||||||
|
chmod(final, 0444);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error_die:
|
||||||
|
unlink(idx);
|
||||||
|
unlink(pack_tmp_name);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int receive_unpack_pack(int fd[2], const char *me, int quiet)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
if (pid < 0)
|
||||||
|
die("%s: unable to fork off git-unpack-objects", me);
|
||||||
|
if (!pid) {
|
||||||
|
dup2(fd[0], 0);
|
||||||
|
close(fd[0]);
|
||||||
|
close(fd[1]);
|
||||||
|
execlp("git-unpack-objects", "git-unpack-objects",
|
||||||
|
quiet ? "-q" : NULL, NULL);
|
||||||
|
die("git-unpack-objects exec failed");
|
||||||
|
}
|
||||||
|
close(fd[0]);
|
||||||
|
close(fd[1]);
|
||||||
|
while (waitpid(pid, &status, 0) < 0) {
|
||||||
|
if (errno != EINTR)
|
||||||
|
die("waiting for git-unpack-objects: %s",
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
if (WIFEXITED(status)) {
|
||||||
|
int code = WEXITSTATUS(status);
|
||||||
|
if (code)
|
||||||
|
die("git-unpack-objects died with error code %d",
|
||||||
|
code);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (WIFSIGNALED(status)) {
|
||||||
|
int sig = WTERMSIG(status);
|
||||||
|
die("git-unpack-objects died of signal %d", sig);
|
||||||
|
}
|
||||||
|
die("git-unpack-objects died of unnatural causes %d", status);
|
||||||
|
}
|
||||||
|
|
||||||
|
int receive_keep_pack(int fd[2], const char *me)
|
||||||
|
{
|
||||||
|
char tmpfile[PATH_MAX];
|
||||||
|
int ofd, ifd;
|
||||||
|
|
||||||
|
ifd = fd[0];
|
||||||
|
snprintf(tmpfile, sizeof(tmpfile),
|
||||||
|
"%s/pack/tmp-XXXXXX", get_object_directory());
|
||||||
|
ofd = mkstemp(tmpfile);
|
||||||
|
if (ofd < 0)
|
||||||
|
return error("unable to create temporary file %s", tmpfile);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
char buf[8192];
|
||||||
|
ssize_t sz, wsz, pos;
|
||||||
|
sz = read(ifd, buf, sizeof(buf));
|
||||||
|
if (sz == 0)
|
||||||
|
break;
|
||||||
|
if (sz < 0) {
|
||||||
|
error("error reading pack (%s)", strerror(errno));
|
||||||
|
close(ofd);
|
||||||
|
unlink(tmpfile);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pos = 0;
|
||||||
|
while (pos < sz) {
|
||||||
|
wsz = write(ofd, buf + pos, sz - pos);
|
||||||
|
if (wsz < 0) {
|
||||||
|
error("error writing pack (%s)",
|
||||||
|
strerror(errno));
|
||||||
|
close(ofd);
|
||||||
|
unlink(tmpfile);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pos += wsz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(ofd);
|
||||||
|
return finish_pack(tmpfile, me);
|
||||||
|
}
|
48
fetch-pack.c
48
fetch-pack.c
|
@ -3,13 +3,12 @@
|
||||||
#include "pkt-line.h"
|
#include "pkt-line.h"
|
||||||
#include "commit.h"
|
#include "commit.h"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
#include <time.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
|
|
||||||
|
static int keep_pack;
|
||||||
static int quiet;
|
static int quiet;
|
||||||
static int verbose;
|
static int verbose;
|
||||||
static const char fetch_pack_usage[] =
|
static const char fetch_pack_usage[] =
|
||||||
"git-fetch-pack [-q] [-v] [--exec=upload-pack] [host:]directory <refs>...";
|
"git-fetch-pack [-q] [-v] [-k] [--exec=upload-pack] [host:]directory <refs>...";
|
||||||
static const char *exec = "git-upload-pack";
|
static const char *exec = "git-upload-pack";
|
||||||
|
|
||||||
#define COMPLETE (1U << 0)
|
#define COMPLETE (1U << 0)
|
||||||
|
@ -363,7 +362,6 @@ static int fetch_pack(int fd[2], int nr_match, char **match)
|
||||||
struct ref *ref;
|
struct ref *ref;
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
int status;
|
int status;
|
||||||
pid_t pid;
|
|
||||||
|
|
||||||
get_remote_heads(fd[0], &ref, 0, NULL, 0);
|
get_remote_heads(fd[0], &ref, 0, NULL, 0);
|
||||||
if (server_supports("multi_ack")) {
|
if (server_supports("multi_ack")) {
|
||||||
|
@ -381,27 +379,15 @@ static int fetch_pack(int fd[2], int nr_match, char **match)
|
||||||
}
|
}
|
||||||
if (find_common(fd, sha1, ref) < 0)
|
if (find_common(fd, sha1, ref) < 0)
|
||||||
fprintf(stderr, "warning: no common commits\n");
|
fprintf(stderr, "warning: no common commits\n");
|
||||||
pid = fork();
|
|
||||||
if (pid < 0)
|
if (keep_pack)
|
||||||
die("git-fetch-pack: unable to fork off git-unpack-objects");
|
status = receive_keep_pack(fd, "git-fetch-pack");
|
||||||
if (!pid) {
|
else
|
||||||
dup2(fd[0], 0);
|
status = receive_unpack_pack(fd, "git-fetch-pack", quiet);
|
||||||
close(fd[0]);
|
|
||||||
close(fd[1]);
|
if (status)
|
||||||
execlp("git-unpack-objects", "git-unpack-objects",
|
die("git-fetch-pack: fetch failed.");
|
||||||
quiet ? "-q" : NULL, NULL);
|
|
||||||
die("git-unpack-objects exec failed");
|
|
||||||
}
|
|
||||||
close(fd[0]);
|
|
||||||
close(fd[1]);
|
|
||||||
while (waitpid(pid, &status, 0) < 0) {
|
|
||||||
if (errno != EINTR)
|
|
||||||
die("waiting for git-unpack-objects: %s", strerror(errno));
|
|
||||||
}
|
|
||||||
if (WIFEXITED(status)) {
|
|
||||||
int code = WEXITSTATUS(status);
|
|
||||||
if (code)
|
|
||||||
die("git-unpack-objects died with error code %d", code);
|
|
||||||
all_done:
|
all_done:
|
||||||
while (ref) {
|
while (ref) {
|
||||||
printf("%s %s\n",
|
printf("%s %s\n",
|
||||||
|
@ -410,12 +396,6 @@ all_done:
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (WIFSIGNALED(status)) {
|
|
||||||
int sig = WTERMSIG(status);
|
|
||||||
die("git-unpack-objects died of signal %d", sig);
|
|
||||||
}
|
|
||||||
die("Sherlock Holmes! git-unpack-objects died of unnatural causes %d!", status);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
@ -436,10 +416,14 @@ int main(int argc, char **argv)
|
||||||
exec = arg + 7;
|
exec = arg + 7;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp("-q", arg)) {
|
if (!strcmp("--quiet", arg) || !strcmp("-q", arg)) {
|
||||||
quiet = 1;
|
quiet = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!strcmp("--keep", arg) || !strcmp("-k", arg)) {
|
||||||
|
keep_pack = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!strcmp("-v", arg)) {
|
if (!strcmp("-v", arg)) {
|
||||||
verbose = 1;
|
verbose = 1;
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -211,6 +211,7 @@ this=`cat "$dotest/next"`
|
||||||
if test "$skip" = t
|
if test "$skip" = t
|
||||||
then
|
then
|
||||||
this=`expr "$this" + 1`
|
this=`expr "$this" + 1`
|
||||||
|
resume=
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "$this" -gt "$last"
|
if test "$this" -gt "$last"
|
||||||
|
@ -225,6 +226,7 @@ do
|
||||||
msgnum=`printf "%0${prec}d" $this`
|
msgnum=`printf "%0${prec}d" $this`
|
||||||
next=`expr "$this" + 1`
|
next=`expr "$this" + 1`
|
||||||
test -f "$dotest/$msgnum" || {
|
test -f "$dotest/$msgnum" || {
|
||||||
|
resume=
|
||||||
go_next
|
go_next
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
USAGE='<msg> <patch> <info> [<signoff>]'
|
USAGE='<msg> <patch> <info> [<signoff>]'
|
||||||
. git-sh-setup
|
. git-sh-setup
|
||||||
|
|
||||||
case "$#" in 3|4) usage ;; esac
|
case "$#" in 3|4) ;; *) usage ;; esac
|
||||||
|
|
||||||
final=.dotest/final-commit
|
final=.dotest/final-commit
|
||||||
##
|
##
|
||||||
|
|
|
@ -9,7 +9,8 @@
|
||||||
|
|
||||||
=head1 Invocation
|
=head1 Invocation
|
||||||
|
|
||||||
git-archimport [ -h ] [ -v ] [ -T ] [ -t tempdir ] <archive>/<branch> [ <archive>/<branch> ]
|
git-archimport [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ]
|
||||||
|
[ -D depth] [ -t tempdir ] <archive>/<branch> [ <archive>/<branch> ]
|
||||||
|
|
||||||
Imports a project from one or more Arch repositories. It will follow branches
|
Imports a project from one or more Arch repositories. It will follow branches
|
||||||
and repositories within the namespaces defined by the <archive/branch>
|
and repositories within the namespaces defined by the <archive/branch>
|
||||||
|
@ -74,7 +75,7 @@ our($opt_h,$opt_f,$opt_v,$opt_T,$opt_t,$opt_D,$opt_a,$opt_o);
|
||||||
sub usage() {
|
sub usage() {
|
||||||
print STDERR <<END;
|
print STDERR <<END;
|
||||||
Usage: ${\basename $0} # fetch/update GIT from Arch
|
Usage: ${\basename $0} # fetch/update GIT from Arch
|
||||||
[ -f ] [ -o ] [ -h ] [ -v ] [ -T ] [ -a ] [ -D depth ] [ -t tempdir ]
|
[ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ] [ -D depth ] [ -t tempdir ]
|
||||||
repository/arch-branch [ repository/arch-branch] ...
|
repository/arch-branch [ repository/arch-branch] ...
|
||||||
END
|
END
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
|
@ -32,7 +32,7 @@ delete_branch () {
|
||||||
case " $mbs " in
|
case " $mbs " in
|
||||||
*' '$branch' '*)
|
*' '$branch' '*)
|
||||||
# the merge base of branch and HEAD contains branch --
|
# the merge base of branch and HEAD contains branch --
|
||||||
# which means that the HEAD contains everything in the HEAD.
|
# which means that the HEAD contains everything in both.
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo >&2 "The branch '$branch_name' is not a strict subset of your current HEAD.
|
echo >&2 "The branch '$branch_name' is not a strict subset of your current HEAD.
|
||||||
|
|
|
@ -116,7 +116,7 @@ else
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#
|
#
|
||||||
# Switch the HEAD pointer to the new branch if it we
|
# Switch the HEAD pointer to the new branch if we
|
||||||
# checked out a branch head, and remove any potential
|
# checked out a branch head, and remove any potential
|
||||||
# old MERGE_HEAD's (subsequent commits will clearly not
|
# old MERGE_HEAD's (subsequent commits will clearly not
|
||||||
# be based on them, since we re-set the index)
|
# be based on them, since we re-set the index)
|
||||||
|
|
|
@ -84,6 +84,28 @@ static inline void *xcalloc(size_t nmemb, size_t size)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline ssize_t xread(int fd, void *buf, size_t len)
|
||||||
|
{
|
||||||
|
ssize_t nr;
|
||||||
|
while (1) {
|
||||||
|
nr = read(fd, buf, len);
|
||||||
|
if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
|
||||||
|
continue;
|
||||||
|
return nr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline ssize_t xwrite(int fd, const void *buf, size_t len)
|
||||||
|
{
|
||||||
|
ssize_t nr;
|
||||||
|
while (1) {
|
||||||
|
nr = write(fd, buf, len);
|
||||||
|
if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
|
||||||
|
continue;
|
||||||
|
return nr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Sane ctype - no locale, and works with signed chars */
|
/* Sane ctype - no locale, and works with signed chars */
|
||||||
#undef isspace
|
#undef isspace
|
||||||
#undef isdigit
|
#undef isdigit
|
||||||
|
|
14
git-diff.sh
14
git-diff.sh
|
@ -3,15 +3,14 @@
|
||||||
# Copyright (c) 2005 Linus Torvalds
|
# Copyright (c) 2005 Linus Torvalds
|
||||||
# Copyright (c) 2005 Junio C Hamano
|
# Copyright (c) 2005 Junio C Hamano
|
||||||
|
|
||||||
|
USAGE='[ --diff-options ] <ent>{0,2} [<path>...]'
|
||||||
|
SUBDIRECTORY_OK='Yes'
|
||||||
|
. git-sh-setup
|
||||||
|
|
||||||
rev=$(git-rev-parse --revs-only --no-flags --sq "$@") || exit
|
rev=$(git-rev-parse --revs-only --no-flags --sq "$@") || exit
|
||||||
flags=$(git-rev-parse --no-revs --flags --sq "$@")
|
flags=$(git-rev-parse --no-revs --flags --sq "$@")
|
||||||
files=$(git-rev-parse --no-revs --no-flags --sq "$@")
|
files=$(git-rev-parse --no-revs --no-flags --sq "$@")
|
||||||
|
|
||||||
die () {
|
|
||||||
echo >&2 "$*"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# I often say 'git diff --cached -p' and get scolded by git-diff-files, but
|
# I often say 'git diff --cached -p' and get scolded by git-diff-files, but
|
||||||
# obviously I mean 'git diff --cached -p HEAD' in that case.
|
# obviously I mean 'git diff --cached -p HEAD' in that case.
|
||||||
case "$rev" in
|
case "$rev" in
|
||||||
|
@ -40,8 +39,7 @@ esac
|
||||||
|
|
||||||
case "$rev" in
|
case "$rev" in
|
||||||
?*' '?*' '?*)
|
?*' '?*' '?*)
|
||||||
echo >&2 "I don't understand"
|
usage
|
||||||
exit 1
|
|
||||||
;;
|
;;
|
||||||
?*' '^?*)
|
?*' '^?*)
|
||||||
begin=$(expr "$rev" : '.*^.\([0-9a-f]*\).*') &&
|
begin=$(expr "$rev" : '.*^.\([0-9a-f]*\).*') &&
|
||||||
|
@ -58,7 +56,7 @@ case "$rev" in
|
||||||
cmd="git-diff-files $flags -- $files"
|
cmd="git-diff-files $flags -- $files"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
die "I don't understand $*"
|
usage
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
|
|
@ -210,6 +210,8 @@ Date: '"$ad"
|
||||||
}
|
}
|
||||||
|
|
||||||
mailScript="$mailScript"'
|
mailScript="$mailScript"'
|
||||||
|
a\
|
||||||
|
|
||||||
: body
|
: body
|
||||||
p
|
p
|
||||||
n
|
n
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
# Copyright (c) 2005 Linus Torvalds
|
# Copyright (c) 2005 Linus Torvalds
|
||||||
#
|
#
|
||||||
|
|
||||||
# This one uses only subdirectory-aware commands, so no need to
|
USAGE='[--max-count=<n>] [<since>..<limit>] [--pretty=<format>] [git-rev-list options]'
|
||||||
# include sh-setup-script.
|
SUBDIRECTORY_OK='Yes'
|
||||||
|
. git-sh-setup
|
||||||
|
|
||||||
revs=$(git-rev-parse --revs-only --no-flags --default HEAD "$@") || exit
|
revs=$(git-rev-parse --revs-only --no-flags --default HEAD "$@") || exit
|
||||||
[ "$revs" ] || {
|
[ "$revs" ] || {
|
||||||
echo >&2 "No HEAD ref"
|
die "No HEAD ref"
|
||||||
exit 1
|
|
||||||
}
|
}
|
||||||
git-rev-list --pretty $(git-rev-parse --default HEAD "$@") |
|
git-rev-list --pretty $(git-rev-parse --default HEAD "$@") |
|
||||||
LESS=-S ${PAGER:-less}
|
LESS=-S ${PAGER:-less}
|
||||||
|
|
|
@ -1,90 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
#
|
|
||||||
# Copyright (c) 2005 Junio C Hamano
|
|
||||||
#
|
|
||||||
# Resolve two or more trees recorded in $GIT_DIR/FETCH_HEAD.
|
|
||||||
#
|
|
||||||
. git-sh-setup
|
|
||||||
|
|
||||||
usage () {
|
|
||||||
die "usage: git octopus"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Sanity check the heads early.
|
|
||||||
while read SHA1 REPO
|
|
||||||
do
|
|
||||||
test $(git-cat-file -t $SHA1) = "commit" ||
|
|
||||||
die "$REPO given to octopus is not a commit"
|
|
||||||
done <"$GIT_DIR/FETCH_HEAD"
|
|
||||||
|
|
||||||
head=$(git-rev-parse --verify HEAD) || exit
|
|
||||||
|
|
||||||
git-update-index --refresh ||
|
|
||||||
die "Your working tree is dirty."
|
|
||||||
test "$(git-diff-index --cached "$head")" = "" ||
|
|
||||||
die "Your working tree does not match HEAD."
|
|
||||||
|
|
||||||
# MRC is the current "merge reference commit"
|
|
||||||
# MRT is the current "merge result tree"
|
|
||||||
|
|
||||||
MRC=$head PARENT="-p $head"
|
|
||||||
MRT=$(git-write-tree)
|
|
||||||
CNT=1 ;# counting our head
|
|
||||||
NON_FF_MERGE=0
|
|
||||||
while read SHA1 REPO
|
|
||||||
do
|
|
||||||
common=$(git-merge-base $MRC $SHA1) ||
|
|
||||||
die "Unable to find common commit with $SHA1 from $REPO"
|
|
||||||
|
|
||||||
if test "$common" = $SHA1
|
|
||||||
then
|
|
||||||
echo "Already up-to-date: $REPO"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
CNT=`expr $CNT + 1`
|
|
||||||
PARENT="$PARENT -p $SHA1"
|
|
||||||
|
|
||||||
if test "$common,$NON_FF_MERGE" = "$MRC,0"
|
|
||||||
then
|
|
||||||
# The first head being merged was a fast-forward.
|
|
||||||
# Advance MRC to the head being merged, and use that
|
|
||||||
# tree as the intermediate result of the merge.
|
|
||||||
# We still need to count this as part of the parent set.
|
|
||||||
|
|
||||||
echo "Fast forwarding to: $REPO"
|
|
||||||
git-read-tree -u -m $head $SHA1 || exit
|
|
||||||
MRC=$SHA1 MRT=$(git-write-tree)
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
NON_FF_MERGE=1
|
|
||||||
|
|
||||||
echo "Trying simple merge with $REPO"
|
|
||||||
git-read-tree -u -m $common $MRT $SHA1 || exit
|
|
||||||
next=$(git-write-tree 2>/dev/null)
|
|
||||||
if test $? -ne 0
|
|
||||||
then
|
|
||||||
echo "Simple merge did not work, trying automatic merge."
|
|
||||||
git-merge-index -o git-merge-one-file -a || {
|
|
||||||
git-read-tree --reset "$head"
|
|
||||||
git-checkout-index -f -q -u -a
|
|
||||||
die "Automatic merge failed; should not be doing Octopus"
|
|
||||||
}
|
|
||||||
next=$(git-write-tree 2>/dev/null)
|
|
||||||
fi
|
|
||||||
MRC=$common
|
|
||||||
MRT=$next
|
|
||||||
done <"$GIT_DIR/FETCH_HEAD"
|
|
||||||
|
|
||||||
# Just to be careful in case the user feeds nonsense to us.
|
|
||||||
case "$CNT" in
|
|
||||||
1)
|
|
||||||
echo "No changes."
|
|
||||||
exit 0 ;;
|
|
||||||
esac
|
|
||||||
result_commit=$(git-fmt-merge-msg <"$GIT_DIR/FETCH_HEAD" |
|
|
||||||
git-commit-tree $MRT $PARENT)
|
|
||||||
echo "Committed merge $result_commit"
|
|
||||||
git-update-ref HEAD $result_commit $head
|
|
||||||
git-diff-tree -p $head $result_commit | git-apply --stat
|
|
|
@ -736,6 +736,13 @@ sub commit_all {
|
||||||
}
|
}
|
||||||
|
|
||||||
$opt_l = $svn->{'maxrev'} if not defined $opt_l or $opt_l > $svn->{'maxrev'};
|
$opt_l = $svn->{'maxrev'} if not defined $opt_l or $opt_l > $svn->{'maxrev'};
|
||||||
|
|
||||||
|
if ($svn->{'maxrev'} < $current_rev) {
|
||||||
|
print "Up to date: no new revisions to fetch!\n" if $opt_v;
|
||||||
|
unlink("$git_dir/SVN2GIT_HEAD");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
print "Fetching from $current_rev to $opt_l ...\n" if $opt_v;
|
print "Fetching from $current_rev to $opt_l ...\n" if $opt_v;
|
||||||
|
|
||||||
my $pool=SVN::Pool->new;
|
my $pool=SVN::Pool->new;
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
|
USAGE='[-p] [--max-count=<n>] [<since>..<limit>] [--pretty=<format>] [-m] [git-diff-tree options] [git-rev-list options]'
|
||||||
|
SUBDIRECTORY_OK='Yes'
|
||||||
|
. git-sh-setup
|
||||||
|
|
||||||
rev_list_args=$(git-rev-parse --sq --default HEAD --revs-only "$@") &&
|
rev_list_args=$(git-rev-parse --sq --default HEAD --revs-only "$@") &&
|
||||||
diff_tree_args=$(git-rev-parse --sq --no-revs "$@") &&
|
diff_tree_args=$(git-rev-parse --sq --no-revs "$@") &&
|
||||||
|
|
||||||
|
|
32
git.c
32
git.c
|
@ -8,6 +8,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
#include "git-compat-util.h"
|
#include "git-compat-util.h"
|
||||||
|
|
||||||
#ifndef PATH_MAX
|
#ifndef PATH_MAX
|
||||||
|
@ -26,6 +27,16 @@ static int term_columns(void)
|
||||||
if (col_string && (n_cols = atoi(col_string)) > 0)
|
if (col_string && (n_cols = atoi(col_string)) > 0)
|
||||||
return n_cols;
|
return n_cols;
|
||||||
|
|
||||||
|
#ifdef TIOCGWINSZ
|
||||||
|
{
|
||||||
|
struct winsize ws;
|
||||||
|
if (!ioctl(1, TIOCGWINSZ, &ws)) {
|
||||||
|
if (ws.ws_col)
|
||||||
|
return ws.ws_col;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return 80;
|
return 80;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,25 +85,28 @@ static int cmdname_compare(const void *a_, const void *b_)
|
||||||
|
|
||||||
static void pretty_print_string_list(struct cmdname **cmdname, int longest)
|
static void pretty_print_string_list(struct cmdname **cmdname, int longest)
|
||||||
{
|
{
|
||||||
int cols = 1;
|
int cols = 1, rows;
|
||||||
int space = longest + 1; /* min 1 SP between words */
|
int space = longest + 1; /* min 1 SP between words */
|
||||||
int max_cols = term_columns() - 1; /* don't print *on* the edge */
|
int max_cols = term_columns() - 1; /* don't print *on* the edge */
|
||||||
int i;
|
int i, j;
|
||||||
|
|
||||||
if (space < max_cols)
|
if (space < max_cols)
|
||||||
cols = max_cols / space;
|
cols = max_cols / space;
|
||||||
|
rows = (cmdname_cnt + cols - 1) / cols;
|
||||||
|
|
||||||
qsort(cmdname, cmdname_cnt, sizeof(*cmdname), cmdname_compare);
|
qsort(cmdname, cmdname_cnt, sizeof(*cmdname), cmdname_compare);
|
||||||
|
|
||||||
for (i = 0; i < cmdname_cnt; ) {
|
for (i = 0; i < rows; i++) {
|
||||||
int c;
|
|
||||||
printf(" ");
|
printf(" ");
|
||||||
|
|
||||||
for (c = cols; c && i < cmdname_cnt; i++) {
|
for (j = 0; j < cols; j++) {
|
||||||
printf("%s", cmdname[i]->name);
|
int n = j * rows + i;
|
||||||
|
int size = space;
|
||||||
if (--c)
|
if (n >= cmdname_cnt)
|
||||||
mput_char(' ', space - cmdname[i]->len);
|
break;
|
||||||
|
if (j == cols-1 || n + rows >= cmdname_cnt)
|
||||||
|
size = 1;
|
||||||
|
printf("%-*s", size, cmdname[n]->name);
|
||||||
}
|
}
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
}
|
}
|
||||||
|
|
9
mktag.c
9
mktag.c
|
@ -116,14 +116,9 @@ int main(int argc, char **argv)
|
||||||
// Read the signature
|
// Read the signature
|
||||||
size = 0;
|
size = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int ret = read(0, buffer + size, MAXSIZE - size);
|
int ret = xread(0, buffer + size, MAXSIZE - size);
|
||||||
if (!ret)
|
if (ret <= 0)
|
||||||
break;
|
break;
|
||||||
if (ret < 0) {
|
|
||||||
if (errno == EAGAIN)
|
|
||||||
continue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
size += ret;
|
size += ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
11
pkt-line.c
11
pkt-line.c
|
@ -19,7 +19,7 @@
|
||||||
static void safe_write(int fd, const void *buf, unsigned n)
|
static void safe_write(int fd, const void *buf, unsigned n)
|
||||||
{
|
{
|
||||||
while (n) {
|
while (n) {
|
||||||
int ret = write(fd, buf, n);
|
int ret = xwrite(fd, buf, n);
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
buf += ret;
|
buf += ret;
|
||||||
n -= ret;
|
n -= ret;
|
||||||
|
@ -27,8 +27,6 @@ static void safe_write(int fd, const void *buf, unsigned n)
|
||||||
}
|
}
|
||||||
if (!ret)
|
if (!ret)
|
||||||
die("write error (disk full?)");
|
die("write error (disk full?)");
|
||||||
if (errno == EAGAIN || errno == EINTR)
|
|
||||||
continue;
|
|
||||||
die("write error (%s)", strerror(errno));
|
die("write error (%s)", strerror(errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,12 +66,9 @@ static void safe_read(int fd, void *buffer, unsigned size)
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
while (n < size) {
|
while (n < size) {
|
||||||
int ret = read(fd, buffer + n, size - n);
|
int ret = xread(fd, buffer + n, size - n);
|
||||||
if (ret < 0) {
|
if (ret < 0)
|
||||||
if (errno == EINTR || errno == EAGAIN)
|
|
||||||
continue;
|
|
||||||
die("read error (%s)", strerror(errno));
|
die("read error (%s)", strerror(errno));
|
||||||
}
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
die("unexpected EOF");
|
die("unexpected EOF");
|
||||||
n += ret;
|
n += ret;
|
||||||
|
|
188
read-cache.c
188
read-cache.c
|
@ -6,6 +6,7 @@
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
|
|
||||||
struct cache_entry **active_cache = NULL;
|
struct cache_entry **active_cache = NULL;
|
||||||
|
static time_t index_file_timestamp;
|
||||||
unsigned int active_nr = 0, active_alloc = 0, active_cache_changed = 0;
|
unsigned int active_nr = 0, active_alloc = 0, active_cache_changed = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -28,7 +29,65 @@ void fill_stat_cache_info(struct cache_entry *ce, struct stat *st)
|
||||||
ce->ce_size = htonl(st->st_size);
|
ce->ce_size = htonl(st->st_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ce_match_stat(struct cache_entry *ce, struct stat *st)
|
static int ce_compare_data(struct cache_entry *ce, struct stat *st)
|
||||||
|
{
|
||||||
|
int match = -1;
|
||||||
|
int fd = open(ce->name, O_RDONLY);
|
||||||
|
|
||||||
|
if (fd >= 0) {
|
||||||
|
unsigned char sha1[20];
|
||||||
|
if (!index_fd(sha1, fd, st, 0, NULL))
|
||||||
|
match = memcmp(sha1, ce->sha1, 20);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ce_compare_link(struct cache_entry *ce, unsigned long expected_size)
|
||||||
|
{
|
||||||
|
int match = -1;
|
||||||
|
char *target;
|
||||||
|
void *buffer;
|
||||||
|
unsigned long size;
|
||||||
|
char type[10];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
target = xmalloc(expected_size);
|
||||||
|
len = readlink(ce->name, target, expected_size);
|
||||||
|
if (len != expected_size) {
|
||||||
|
free(target);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
buffer = read_sha1_file(ce->sha1, type, &size);
|
||||||
|
if (!buffer) {
|
||||||
|
free(target);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (size == expected_size)
|
||||||
|
match = memcmp(buffer, target, size);
|
||||||
|
free(buffer);
|
||||||
|
free(target);
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ce_modified_check_fs(struct cache_entry *ce, struct stat *st)
|
||||||
|
{
|
||||||
|
switch (st->st_mode & S_IFMT) {
|
||||||
|
case S_IFREG:
|
||||||
|
if (ce_compare_data(ce, st))
|
||||||
|
return DATA_CHANGED;
|
||||||
|
break;
|
||||||
|
case S_IFLNK:
|
||||||
|
if (ce_compare_link(ce, st->st_size))
|
||||||
|
return DATA_CHANGED;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return TYPE_CHANGED;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st)
|
||||||
{
|
{
|
||||||
unsigned int changed = 0;
|
unsigned int changed = 0;
|
||||||
|
|
||||||
|
@ -83,57 +142,44 @@ int ce_match_stat(struct cache_entry *ce, struct stat *st)
|
||||||
|
|
||||||
if (ce->ce_size != htonl(st->st_size))
|
if (ce->ce_size != htonl(st->st_size))
|
||||||
changed |= DATA_CHANGED;
|
changed |= DATA_CHANGED;
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ce_compare_data(struct cache_entry *ce, struct stat *st)
|
int ce_match_stat(struct cache_entry *ce, struct stat *st)
|
||||||
{
|
{
|
||||||
int match = -1;
|
unsigned int changed = ce_match_stat_basic(ce, st);
|
||||||
int fd = open(ce->name, O_RDONLY);
|
|
||||||
|
|
||||||
if (fd >= 0) {
|
/*
|
||||||
unsigned char sha1[20];
|
* Within 1 second of this sequence:
|
||||||
if (!index_fd(sha1, fd, st, 0, NULL))
|
* echo xyzzy >file && git-update-index --add file
|
||||||
match = memcmp(sha1, ce->sha1, 20);
|
* running this command:
|
||||||
close(fd);
|
* echo frotz >file
|
||||||
}
|
* would give a falsely clean cache entry. The mtime and
|
||||||
return match;
|
* length match the cache, and other stat fields do not change.
|
||||||
}
|
*
|
||||||
|
* We could detect this at update-index time (the cache entry
|
||||||
|
* being registered/updated records the same time as "now")
|
||||||
|
* and delay the return from git-update-index, but that would
|
||||||
|
* effectively mean we can make at most one commit per second,
|
||||||
|
* which is not acceptable. Instead, we check cache entries
|
||||||
|
* whose mtime are the same as the index file timestamp more
|
||||||
|
* careful than others.
|
||||||
|
*/
|
||||||
|
if (!changed &&
|
||||||
|
index_file_timestamp &&
|
||||||
|
index_file_timestamp <= ntohl(ce->ce_mtime.sec))
|
||||||
|
changed |= ce_modified_check_fs(ce, st);
|
||||||
|
|
||||||
static int ce_compare_link(struct cache_entry *ce, unsigned long expected_size)
|
return changed;
|
||||||
{
|
|
||||||
int match = -1;
|
|
||||||
char *target;
|
|
||||||
void *buffer;
|
|
||||||
unsigned long size;
|
|
||||||
char type[10];
|
|
||||||
int len;
|
|
||||||
|
|
||||||
target = xmalloc(expected_size);
|
|
||||||
len = readlink(ce->name, target, expected_size);
|
|
||||||
if (len != expected_size) {
|
|
||||||
free(target);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
buffer = read_sha1_file(ce->sha1, type, &size);
|
|
||||||
if (!buffer) {
|
|
||||||
free(target);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (size == expected_size)
|
|
||||||
match = memcmp(buffer, target, size);
|
|
||||||
free(buffer);
|
|
||||||
free(target);
|
|
||||||
return match;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ce_modified(struct cache_entry *ce, struct stat *st)
|
int ce_modified(struct cache_entry *ce, struct stat *st)
|
||||||
{
|
{
|
||||||
int changed;
|
int changed, changed_fs;
|
||||||
changed = ce_match_stat(ce, st);
|
changed = ce_match_stat(ce, st);
|
||||||
if (!changed)
|
if (!changed)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the mode or type has changed, there's no point in trying
|
* If the mode or type has changed, there's no point in trying
|
||||||
* to refresh the entry - it's not going to match
|
* to refresh the entry - it's not going to match
|
||||||
|
@ -148,18 +194,9 @@ int ce_modified(struct cache_entry *ce, struct stat *st)
|
||||||
if ((changed & DATA_CHANGED) && ce->ce_size != htonl(0))
|
if ((changed & DATA_CHANGED) && ce->ce_size != htonl(0))
|
||||||
return changed;
|
return changed;
|
||||||
|
|
||||||
switch (st->st_mode & S_IFMT) {
|
changed_fs = ce_modified_check_fs(ce, st);
|
||||||
case S_IFREG:
|
if (changed_fs)
|
||||||
if (ce_compare_data(ce, st))
|
return changed | changed_fs;
|
||||||
return changed | DATA_CHANGED;
|
|
||||||
break;
|
|
||||||
case S_IFLNK:
|
|
||||||
if (ce_compare_link(ce, st->st_size))
|
|
||||||
return changed | DATA_CHANGED;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return changed | TYPE_CHANGED;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -471,6 +508,7 @@ int read_cache(void)
|
||||||
return active_nr;
|
return active_nr;
|
||||||
|
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
|
index_file_timestamp = 0;
|
||||||
fd = open(get_index_file(), O_RDONLY);
|
fd = open(get_index_file(), O_RDONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
if (errno == ENOENT)
|
if (errno == ENOENT)
|
||||||
|
@ -504,6 +542,7 @@ int read_cache(void)
|
||||||
offset = offset + ce_size(ce);
|
offset = offset + ce_size(ce);
|
||||||
active_cache[i] = ce;
|
active_cache[i] = ce;
|
||||||
}
|
}
|
||||||
|
index_file_timestamp = st.st_mtime;
|
||||||
return active_nr;
|
return active_nr;
|
||||||
|
|
||||||
unmap:
|
unmap:
|
||||||
|
@ -562,6 +601,50 @@ static int ce_flush(SHA_CTX *context, int fd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ce_smudge_racily_clean_entry(struct cache_entry *ce)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The only thing we care about in this function is to smudge the
|
||||||
|
* falsely clean entry due to touch-update-touch race, so we leave
|
||||||
|
* everything else as they are. We are called for entries whose
|
||||||
|
* ce_mtime match the index file mtime.
|
||||||
|
*/
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
if (lstat(ce->name, &st) < 0)
|
||||||
|
return;
|
||||||
|
if (ce_match_stat_basic(ce, &st))
|
||||||
|
return;
|
||||||
|
if (ce_modified_check_fs(ce, &st)) {
|
||||||
|
/* This is "racily clean"; smudge it. Note that this
|
||||||
|
* is a tricky code. At first glance, it may appear
|
||||||
|
* that it can break with this sequence:
|
||||||
|
*
|
||||||
|
* $ echo xyzzy >frotz
|
||||||
|
* $ git-update-index --add frotz
|
||||||
|
* $ : >frotz
|
||||||
|
* $ sleep 3
|
||||||
|
* $ echo filfre >nitfol
|
||||||
|
* $ git-update-index --add nitfol
|
||||||
|
*
|
||||||
|
* but it does not. Whe the second update-index runs,
|
||||||
|
* it notices that the entry "frotz" has the same timestamp
|
||||||
|
* as index, and if we were to smudge it by resetting its
|
||||||
|
* size to zero here, then the object name recorded
|
||||||
|
* in index is the 6-byte file but the cached stat information
|
||||||
|
* becomes zero --- which would then match what we would
|
||||||
|
* obtain from the filesystem next time we stat("frotz").
|
||||||
|
*
|
||||||
|
* However, the second update-index, before calling
|
||||||
|
* this function, notices that the cached size is 6
|
||||||
|
* bytes and what is on the filesystem is an empty
|
||||||
|
* file, and never calls us, so the cached size information
|
||||||
|
* for "frotz" stays 6 which does not match the filesystem.
|
||||||
|
*/
|
||||||
|
ce->ce_size = htonl(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int write_cache(int newfd, struct cache_entry **cache, int entries)
|
int write_cache(int newfd, struct cache_entry **cache, int entries)
|
||||||
{
|
{
|
||||||
SHA_CTX c;
|
SHA_CTX c;
|
||||||
|
@ -584,6 +667,9 @@ int write_cache(int newfd, struct cache_entry **cache, int entries)
|
||||||
struct cache_entry *ce = cache[i];
|
struct cache_entry *ce = cache[i];
|
||||||
if (!ce->ce_mode)
|
if (!ce->ce_mode)
|
||||||
continue;
|
continue;
|
||||||
|
if (index_file_timestamp &&
|
||||||
|
index_file_timestamp <= ntohl(ce->ce_mtime.sec))
|
||||||
|
ce_smudge_racily_clean_entry(ce);
|
||||||
if (ce_write(&c, newfd, ce, ce_size(ce)) < 0)
|
if (ce_write(&c, newfd, ce, ce_size(ce)) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
4
refs.c
4
refs.c
|
@ -313,7 +313,9 @@ int write_ref_sha1(const char *ref, int fd, const unsigned char *sha1)
|
||||||
static inline int bad_ref_char(int ch)
|
static inline int bad_ref_char(int ch)
|
||||||
{
|
{
|
||||||
return (((unsigned) ch) <= ' ' ||
|
return (((unsigned) ch) <= ' ' ||
|
||||||
ch == '~' || ch == '^' || ch == ':');
|
ch == '~' || ch == '^' || ch == ':' ||
|
||||||
|
/* 2.13 Pattern Matching Notation */
|
||||||
|
ch == '?' || ch == '*' || ch == '[');
|
||||||
}
|
}
|
||||||
|
|
||||||
int check_ref_format(const char *ref)
|
int check_ref_format(const char *ref)
|
||||||
|
|
|
@ -850,7 +850,8 @@ int main(int argc, const char **argv)
|
||||||
handle_one_commit(commit, &list);
|
handle_one_commit(commit, &list);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!list)
|
if (!list &&
|
||||||
|
(!(tag_objects||tree_objects||blob_objects) && !pending_objects))
|
||||||
usage(rev_list_usage);
|
usage(rev_list_usage);
|
||||||
|
|
||||||
paths = get_pathspec(prefix, argv + i);
|
paths = get_pathspec(prefix, argv + i);
|
||||||
|
|
|
@ -8,6 +8,7 @@ static const char send_pack_usage[] =
|
||||||
"git-send-pack [--all] [--exec=git-receive-pack] <remote> [<head>...]\n"
|
"git-send-pack [--all] [--exec=git-receive-pack] <remote> [<head>...]\n"
|
||||||
" --all and explicit <head> specification are mutually exclusive.";
|
" --all and explicit <head> specification are mutually exclusive.";
|
||||||
static const char *exec = "git-receive-pack";
|
static const char *exec = "git-receive-pack";
|
||||||
|
static int verbose = 0;
|
||||||
static int send_all = 0;
|
static int send_all = 0;
|
||||||
static int force_update = 0;
|
static int force_update = 0;
|
||||||
|
|
||||||
|
@ -206,6 +207,7 @@ static int send_pack(int in, int out, int nr_refspec, char **refspec)
|
||||||
if (!ref->peer_ref)
|
if (!ref->peer_ref)
|
||||||
continue;
|
continue;
|
||||||
if (!memcmp(ref->old_sha1, ref->peer_ref->new_sha1, 20)) {
|
if (!memcmp(ref->old_sha1, ref->peer_ref->new_sha1, 20)) {
|
||||||
|
if (verbose)
|
||||||
fprintf(stderr, "'%s': up-to-date\n", ref->name);
|
fprintf(stderr, "'%s': up-to-date\n", ref->name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -270,6 +272,8 @@ static int send_pack(int in, int out, int nr_refspec, char **refspec)
|
||||||
packet_flush(out);
|
packet_flush(out);
|
||||||
if (new_refs)
|
if (new_refs)
|
||||||
pack_objects(out, remote_refs);
|
pack_objects(out, remote_refs);
|
||||||
|
else
|
||||||
|
fprintf(stderr, "Everything up-to-date\n");
|
||||||
close(out);
|
close(out);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -301,6 +305,10 @@ int main(int argc, char **argv)
|
||||||
force_update = 1;
|
force_update = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!strcmp(arg, "--verbose")) {
|
||||||
|
verbose = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
usage(send_pack_usage);
|
usage(send_pack_usage);
|
||||||
}
|
}
|
||||||
if (!dest) {
|
if (!dest) {
|
||||||
|
|
29
sha1_name.c
29
sha1_name.c
|
@ -188,7 +188,10 @@ const char *find_unique_abbrev(const unsigned char *sha1, int len)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
static char hex[41];
|
static char hex[41];
|
||||||
|
|
||||||
memcpy(hex, sha1_to_hex(sha1), 40);
|
memcpy(hex, sha1_to_hex(sha1), 40);
|
||||||
|
if (len == 40)
|
||||||
|
return hex;
|
||||||
while (len < 40) {
|
while (len < 40) {
|
||||||
unsigned char sha1_ret[20];
|
unsigned char sha1_ret[20];
|
||||||
status = get_short_sha1(hex, len, sha1_ret, 1);
|
status = get_short_sha1(hex, len, sha1_ret, 1);
|
||||||
|
@ -203,11 +206,12 @@ const char *find_unique_abbrev(const unsigned char *sha1, int len)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ambiguous_path(const char *path)
|
static int ambiguous_path(const char *path, int len)
|
||||||
{
|
{
|
||||||
int slash = 1;
|
int slash = 1;
|
||||||
|
int cnt;
|
||||||
|
|
||||||
for (;;) {
|
for (cnt = 0; cnt < len; cnt++) {
|
||||||
switch (*path++) {
|
switch (*path++) {
|
||||||
case '\0':
|
case '\0':
|
||||||
break;
|
break;
|
||||||
|
@ -222,8 +226,9 @@ static int ambiguous_path(const char *path)
|
||||||
slash = 0;
|
slash = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
return slash;
|
break;
|
||||||
}
|
}
|
||||||
|
return slash;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
|
static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
|
||||||
|
@ -236,31 +241,19 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
const char **p;
|
const char **p;
|
||||||
int found = 0;
|
|
||||||
|
|
||||||
if (len == 40 && !get_sha1_hex(str, sha1))
|
if (len == 40 && !get_sha1_hex(str, sha1))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Accept only unambiguous ref paths. */
|
/* Accept only unambiguous ref paths. */
|
||||||
if (ambiguous_path(str))
|
if (ambiguous_path(str, len))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
for (p = prefix; *p; p++) {
|
for (p = prefix; *p; p++) {
|
||||||
char *pathname = git_path("%s/%.*s", *p, len, str);
|
char *pathname = git_path("%s/%.*s", *p, len, str);
|
||||||
if (!read_ref(pathname, sha1)) {
|
if (!read_ref(pathname, sha1))
|
||||||
/* Must be unique; i.e. when heads/foo and
|
|
||||||
* tags/foo are both present, reject "foo".
|
|
||||||
* Note that read_ref() eventually calls
|
|
||||||
* get_sha1_hex() which can smudge initial
|
|
||||||
* part of the buffer even if what is read
|
|
||||||
* is found to be invalid halfway.
|
|
||||||
*/
|
|
||||||
if (1 < found++)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (found == 1)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -450,6 +450,8 @@ static void append_one_rev(const char *av)
|
||||||
if (saved_matches == ref_name_cnt &&
|
if (saved_matches == ref_name_cnt &&
|
||||||
ref_name_cnt < MAX_REVS)
|
ref_name_cnt < MAX_REVS)
|
||||||
error("no matching refs with %s", av);
|
error("no matching refs with %s", av);
|
||||||
|
if (saved_matches + 1 < ref_name_cnt)
|
||||||
|
sort_ref_range(saved_matches, ref_name_cnt);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
die("bad sha1 reference %s", av);
|
die("bad sha1 reference %s", av);
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
test_description='racy GIT'
|
||||||
|
|
||||||
|
. ./test-lib.sh
|
||||||
|
|
||||||
|
# This test can give false success if your machine is sufficiently
|
||||||
|
# slow or your trial happened to happen on second boundary.
|
||||||
|
|
||||||
|
for trial in 0 1 2 3 4
|
||||||
|
do
|
||||||
|
rm -f .git/index
|
||||||
|
echo frotz >infocom
|
||||||
|
git update-index --add infocom
|
||||||
|
echo xyzzy >infocom
|
||||||
|
|
||||||
|
files=`git diff-files -p`
|
||||||
|
test_expect_success \
|
||||||
|
"Racy GIT trial #$trial part A" \
|
||||||
|
'test "" != "$files"'
|
||||||
|
|
||||||
|
sleep 1
|
||||||
|
echo xyzzy >cornerstone
|
||||||
|
git update-index --add cornerstone
|
||||||
|
|
||||||
|
files=`git diff-files -p`
|
||||||
|
test_expect_success \
|
||||||
|
"Racy GIT trial #$trial part B" \
|
||||||
|
'test "" != "$files"'
|
||||||
|
|
||||||
|
done
|
||||||
|
|
||||||
|
test_done
|
|
@ -18,6 +18,7 @@ unset GIT_ALTERNATE_OBJECT_DIRECTORIES
|
||||||
unset GIT_AUTHOR_DATE
|
unset GIT_AUTHOR_DATE
|
||||||
unset GIT_AUTHOR_EMAIL
|
unset GIT_AUTHOR_EMAIL
|
||||||
unset GIT_AUTHOR_NAME
|
unset GIT_AUTHOR_NAME
|
||||||
|
unset GIT_COMMITTER_DATE
|
||||||
unset GIT_COMMITTER_EMAIL
|
unset GIT_COMMITTER_EMAIL
|
||||||
unset GIT_COMMITTER_NAME
|
unset GIT_COMMITTER_NAME
|
||||||
unset GIT_DIFF_OPTS
|
unset GIT_DIFF_OPTS
|
||||||
|
|
|
@ -34,10 +34,8 @@ struct path_prefix {
|
||||||
static void reliable_write(void *buf, unsigned long size)
|
static void reliable_write(void *buf, unsigned long size)
|
||||||
{
|
{
|
||||||
while (size > 0) {
|
while (size > 0) {
|
||||||
long ret = write(1, buf, size);
|
long ret = xwrite(1, buf, size);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (errno == EAGAIN)
|
|
||||||
continue;
|
|
||||||
if (errno == EPIPE)
|
if (errno == EPIPE)
|
||||||
exit(0);
|
exit(0);
|
||||||
die("git-tar-tree: %s", strerror(errno));
|
die("git-tar-tree: %s", strerror(errno));
|
||||||
|
|
|
@ -31,12 +31,10 @@ static void * fill(int min)
|
||||||
offset = 0;
|
offset = 0;
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
int ret = read(0, buffer + len, sizeof(buffer) - len);
|
int ret = xread(0, buffer + len, sizeof(buffer) - len);
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
if (!ret)
|
if (!ret)
|
||||||
die("early EOF");
|
die("early EOF");
|
||||||
if (errno == EAGAIN || errno == EINTR)
|
|
||||||
continue;
|
|
||||||
die("read error on input: %s", strerror(errno));
|
die("read error on input: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
len += ret;
|
len += ret;
|
||||||
|
@ -299,14 +297,9 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
/* Write the last part of the buffer to stdout */
|
/* Write the last part of the buffer to stdout */
|
||||||
while (len) {
|
while (len) {
|
||||||
int ret = write(1, buffer + offset, len);
|
int ret = xwrite(1, buffer + offset, len);
|
||||||
if (!ret)
|
if (ret <= 0)
|
||||||
break;
|
break;
|
||||||
if (ret < 0) {
|
|
||||||
if (errno == EAGAIN || errno == EINTR)
|
|
||||||
continue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
len -= ret;
|
len -= ret;
|
||||||
offset += ret;
|
offset += ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue