зеркало из https://github.com/microsoft/git.git
GIT 1.0.0
Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
Коммит
c2f3bf071e
|
@ -60,7 +60,6 @@ git-merge-stupid
|
|||
git-mktag
|
||||
git-name-rev
|
||||
git-mv
|
||||
git-octopus
|
||||
git-pack-redundant
|
||||
git-pack-objects
|
||||
git-parse-remote
|
||||
|
|
|
@ -18,6 +18,14 @@
|
|||
object name of pre- and post-image blob on the "index"
|
||||
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::
|
||||
Break complete rewrite changes into pairs of delete and create.
|
||||
|
||||
|
|
|
@ -211,10 +211,12 @@ $ git fetch --tags <8>
|
|||
|
||||
<1> repeat as needed.
|
||||
<2> extract patches from your branch for e-mail submission.
|
||||
<3> "pull" fetches from "origin" by default and merges.
|
||||
<4> look at the changes since last time we checked, only in the
|
||||
<3> "pull" fetches from "origin" by default and merges into 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.
|
||||
<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.
|
||||
<7> garbage collect leftover objects from reverted pull.
|
||||
<8> from time to time, obtain official tags from the "origin"
|
||||
|
@ -330,16 +332,18 @@ master, nor exposed as a part of a stable branch.
|
|||
<8> and bundle topic branches still cooking.
|
||||
<9> backport a critical fix.
|
||||
<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
|
||||
at kernel.org, and looks like this:
|
||||
$ cat .git/remotes/ko
|
||||
URL: kernel.org:/pub/scm/git/git.git
|
||||
Pull: master:refs/tags/ko-master
|
||||
Pull: maint:refs/tags/ko-maint
|
||||
Push: master
|
||||
Push: +pu
|
||||
Push: maint
|
||||
$ cat .git/remotes/ko
|
||||
URL: kernel.org:/pub/scm/git/git.git
|
||||
Pull: master:refs/tags/ko-master
|
||||
Pull: maint:refs/tags/ko-maint
|
||||
Push: master
|
||||
Push: +pu
|
||||
Push: maint
|
||||
In the output from "git show-branch", "master" should have
|
||||
everything "ko-master" has.
|
||||
<12> push out the bleeding edge.
|
||||
<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'
|
||||
for shared central repository users.
|
||||
|
||||
* link:howto/update-hook-example.txt[update hook howto] has a
|
||||
good example of managing a shared central repository.
|
||||
link:howto/update-hook-example.txt[update hook howto] has a good
|
||||
example of managing a shared central repository.
|
||||
|
||||
|
||||
Examples
|
||||
|
@ -424,3 +428,14 @@ for branch policy control.
|
|||
david is the release manager and is the only person who can
|
||||
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
|
||||
--------
|
||||
`git-archimport` [ -h ] [ -v ] [ -T ] [ -t tempdir ]
|
||||
`git-archimport` [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ]
|
||||
[ -D depth ] [ -t tempdir ]
|
||||
<archive/branch> [ <archive/branch> ]
|
||||
|
||||
DESCRIPTION
|
||||
|
@ -63,6 +64,26 @@ OPTIONS
|
|||
Many tags. Will create a tag for every commit, reflecting the commit
|
||||
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>::
|
||||
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
|
||||
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 `/`.
|
||||
|
||||
These rules makes it easy for shell script based tools to parse
|
||||
refnames, and also avoids ambiguities in certain refname
|
||||
expressions (see gitlink:git-rev-parse[1]). Namely:
|
||||
refnames, pathname expansion by the shell when a refname is used
|
||||
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
|
||||
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
|
||||
(e.g. "HEAD", "refs/heads/master"). When unspecified,
|
||||
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
|
||||
------
|
||||
|
|
|
@ -66,6 +66,10 @@ OPTIONS
|
|||
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
|
||||
------
|
||||
Written by Linus Torvalds <torvalds@osdl.org> and
|
||||
|
|
|
@ -8,7 +8,7 @@ git-fetch-pack - Receive missing objects from another repository.
|
|||
|
||||
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
|
||||
-----------
|
||||
|
@ -29,6 +29,11 @@ OPTIONS
|
|||
Pass '-q' flag to 'git-unpack-objects'; this makes the
|
||||
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>::
|
||||
Use this to specify the path to 'git-upload-pack' on the
|
||||
remote side, if is not found on your $PATH.
|
||||
|
|
|
@ -37,6 +37,11 @@ include::merge-options.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
|
||||
---------------
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
||||
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
|
||||
--------
|
||||
gitlink:git-fetch[1], gitlink:git-merge[1]
|
||||
|
|
|
@ -111,6 +111,39 @@ remain there.
|
|||
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
|
||||
------
|
||||
|
|
|
@ -12,11 +12,11 @@ SYNOPSIS
|
|||
|
||||
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
|
||||
$GIT_OBJECT_DIRECTORY/info directories to help clients discover
|
||||
what references and packs the server has and make optimized
|
||||
pull decisions. This command generates such auxiliary files.
|
||||
what references and packs the server has. This command
|
||||
generates such auxiliary files.
|
||||
|
||||
|
||||
OPTIONS
|
||||
|
|
|
@ -297,9 +297,6 @@ gitlink:git-merge[1]::
|
|||
gitlink:git-mv[1]::
|
||||
Move or rename a file, a directory, or a symlink.
|
||||
|
||||
gitlink:git-octopus[1]::
|
||||
Merge more than two commits.
|
||||
|
||||
gitlink:git-pull[1]::
|
||||
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
|
||||
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
|
||||
-----------
|
||||
|
||||
|
@ -125,3 +129,7 @@ the outcome of `git-receive-pack`.
|
|||
The default post-update hook, when enabled, runs
|
||||
`git-update-server-info` to keep the information used by dumb
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
The directories relevant to this how-to are these two:
|
||||
|
@ -63,7 +63,7 @@ like this:
|
|||
EOF
|
||||
$ 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
|
||||
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
|
||||
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
|
||||
make invocations stomping on each other. I would need to add
|
||||
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:
|
||||
|
||||
$ git clone \
|
||||
master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6.git work
|
||||
$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git work
|
||||
|
||||
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":
|
||||
|
||||
$ 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
|
||||
^D
|
||||
|
||||
|
|
|
@ -27,6 +27,12 @@ SCM, you can skip them during your first pass.
|
|||
[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
|
||||
-------------------------
|
||||
|
@ -1085,9 +1091,10 @@ lacks and transfers (close to) minimum set of objects.
|
|||
HTTP(S)::
|
||||
`http://remote.machine/path/to/repo.git/`
|
||||
+
|
||||
HTTP and HTTPS transport are used only for downloading. They
|
||||
first obtain the topmost commit object name from the remote site
|
||||
by looking at `repo.git/info/refs` file, tries to obtain the
|
||||
Downloader from http and https URL
|
||||
first obtains the topmost commit object name from the remote site
|
||||
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\...`
|
||||
using the object name of that commit object. Then it reads the
|
||||
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
|
||||
transports', because they do not require any git aware smart
|
||||
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`
|
||||
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.
|
||||
+
|
||||
If other people are pulling from your repository over dumb
|
||||
transport protocols, you need to keep this repository 'dumb
|
||||
transport friendly'. After `git init-db`,
|
||||
transport protocols (HTTP), you need to keep this repository
|
||||
'dumb transport friendly'. After `git init-db`,
|
||||
`$GIT_DIR/hooks/post-update` copied from the standard templates
|
||||
would contain a call to `git-update-server-info` but the
|
||||
`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
|
||||
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
|
||||
reachable via SSH by people with "commit privileges". Put the
|
||||
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:
|
||||
|
||||
|
|
8
Makefile
8
Makefile
|
@ -55,7 +55,7 @@ all:
|
|||
# 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.
|
||||
|
||||
GIT_VERSION = 0.99.9n
|
||||
GIT_VERSION = 1.0.0
|
||||
|
||||
# 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-count-objects.sh git-diff.sh git-fetch.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-repack.sh git-request-pull.sh git-reset.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 \
|
||||
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 \
|
||||
fetch-clone.o \
|
||||
$(DIFF_OBJS)
|
||||
|
||||
LIBS = $(LIB_FILE)
|
||||
|
@ -497,7 +498,7 @@ clean:
|
|||
rm -f *.o mozilla-sha1/*.o arm/*.o ppc/*.o compat/*.o $(LIB_FILE)
|
||||
rm -f $(PROGRAMS) $(SIMPLE_PROGRAMS) git$X
|
||||
rm -f $(filter-out gitk,$(SCRIPTS))
|
||||
rm -f *.spec *.pyc *.pyo
|
||||
rm -f *.spec *.pyc *.pyo */*.pyc */*.pyo
|
||||
rm -rf $(GIT_TARNAME)
|
||||
rm -f $(GIT_TARNAME).tar.gz git-core_$(GIT_VERSION)-*.tar.gz
|
||||
rm -f git-core_$(GIT_VERSION)-*.dsc
|
||||
|
@ -505,3 +506,4 @@ clean:
|
|||
$(MAKE) -C Documentation/ clean
|
||||
$(MAKE) -C templates 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);
|
||||
nr = alloc - size;
|
||||
}
|
||||
nr = read(fd, buffer + size, nr);
|
||||
nr = xread(fd, buffer + size, nr);
|
||||
if (!nr)
|
||||
break;
|
||||
if (nr < 0) {
|
||||
if (errno == EAGAIN)
|
||||
continue;
|
||||
if (nr < 0)
|
||||
die("git-apply: read returned %s", strerror(errno));
|
||||
}
|
||||
size += nr;
|
||||
}
|
||||
*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);
|
||||
got = 0;
|
||||
for (;;) {
|
||||
int ret = read(fd, buf + got, size - got);
|
||||
if (ret < 0) {
|
||||
if (errno == EAGAIN)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if (!ret)
|
||||
int ret = xread(fd, buf + got, size - got);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
got += ret;
|
||||
}
|
||||
|
@ -1600,12 +1592,9 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf,
|
|||
if (fd < 0)
|
||||
return -1;
|
||||
while (size) {
|
||||
int written = write(fd, buf, size);
|
||||
if (written < 0) {
|
||||
if (errno == EINTR || errno == EAGAIN)
|
||||
continue;
|
||||
int written = xwrite(fd, buf, size);
|
||||
if (written < 0)
|
||||
die("writing file %s: %s", path, strerror(errno));
|
||||
}
|
||||
if (!written)
|
||||
die("out of space writing file %s", path);
|
||||
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 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 */
|
||||
|
|
|
@ -55,10 +55,8 @@ int main(int argc, char **argv)
|
|||
die("git-cat-file %s: bad file", argv[2]);
|
||||
|
||||
while (size > 0) {
|
||||
long ret = write(1, buf, size);
|
||||
long ret = xwrite(1, buf, size);
|
||||
if (ret < 0) {
|
||||
if (errno == EAGAIN)
|
||||
continue;
|
||||
/* Ignore epipe */
|
||||
if (errno == EPIPE)
|
||||
break;
|
||||
|
|
151
clone-pack.c
151
clone-pack.c
|
@ -1,7 +1,6 @@
|
|||
#include "cache.h"
|
||||
#include "refs.h"
|
||||
#include "pkt-line.h"
|
||||
#include <sys/wait.h>
|
||||
|
||||
static const char clone_pack_usage[] =
|
||||
"git-clone-pack [--exec=<git-upload-pack>] [<host>:]<directory> [<heads>]*";
|
||||
|
@ -112,139 +111,6 @@ static void write_refs(struct ref *ref)
|
|||
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)
|
||||
{
|
||||
struct ref *refs;
|
||||
|
@ -257,10 +123,19 @@ static int clone_pack(int fd[2], int nr_match, char **match)
|
|||
}
|
||||
clone_handshake(fd, refs);
|
||||
|
||||
status = clone_without_unpack(fd);
|
||||
status = receive_keep_pack(fd, "git-clone-pack");
|
||||
|
||||
if (!status)
|
||||
write_refs(refs);
|
||||
if (!status) {
|
||||
if (nr_match == 0)
|
||||
write_refs(refs);
|
||||
else
|
||||
while (refs) {
|
||||
printf("%s %s\n",
|
||||
sha1_to_hex(refs->old_sha1),
|
||||
refs->name);
|
||||
refs = refs->next;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -285,8 +160,6 @@ int main(int argc, char **argv)
|
|||
exec = arg + 7;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("--keep", arg))
|
||||
continue;
|
||||
usage(clone_pack_usage);
|
||||
}
|
||||
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
|
19
copy.c
19
copy.c
|
@ -6,32 +6,27 @@ int copy_fd(int ifd, int ofd)
|
|||
int len;
|
||||
char buffer[8192];
|
||||
char *buf = buffer;
|
||||
len = read(ifd, buffer, sizeof(buffer));
|
||||
len = xread(ifd, buffer, sizeof(buffer));
|
||||
if (!len)
|
||||
break;
|
||||
if (len < 0) {
|
||||
int read_error;
|
||||
if (errno == EAGAIN)
|
||||
continue;
|
||||
read_error = errno;
|
||||
close(ifd);
|
||||
return error("copy-fd: read returned %s",
|
||||
strerror(read_error));
|
||||
}
|
||||
while (1) {
|
||||
int written = write(ofd, buf, len);
|
||||
while (len) {
|
||||
int written = xwrite(ofd, buf, len);
|
||||
if (written > 0) {
|
||||
buf += written;
|
||||
len -= written;
|
||||
if (!len)
|
||||
break;
|
||||
}
|
||||
if (!written)
|
||||
else if (!written)
|
||||
return error("copy-fd: write returned 0");
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
continue;
|
||||
return error("copy-fd: write returned %s",
|
||||
strerror(errno));
|
||||
else
|
||||
return error("copy-fd: write returned %s",
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
close(ifd);
|
||||
|
|
|
@ -15,7 +15,7 @@ static int sha1flush(struct sha1file *f, unsigned int count)
|
|||
void *buf = f->buffer;
|
||||
|
||||
for (;;) {
|
||||
int ret = write(f->fd, buf, count);
|
||||
int ret = xwrite(f->fd, buf, count);
|
||||
if (ret > 0) {
|
||||
buf += ret;
|
||||
count -= ret;
|
||||
|
@ -25,8 +25,6 @@ static int sha1flush(struct sha1file *f, unsigned int count)
|
|||
}
|
||||
if (!ret)
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 0.99.9n aka 1.0rc6
|
||||
|
|
34
diff-delta.c
34
diff-delta.c
|
@ -84,20 +84,15 @@ typedef struct s_chanode {
|
|||
} chanode_t;
|
||||
|
||||
typedef struct s_chastore {
|
||||
chanode_t *head, *tail;
|
||||
int isize, nsize;
|
||||
chanode_t *ancur;
|
||||
chanode_t *sncur;
|
||||
int scurr;
|
||||
} chastore_t;
|
||||
|
||||
static void cha_init(chastore_t *cha, int isize, int icount)
|
||||
{
|
||||
cha->head = cha->tail = NULL;
|
||||
cha->isize = isize;
|
||||
cha->nsize = icount * isize;
|
||||
cha->ancur = cha->sncur = NULL;
|
||||
cha->scurr = 0;
|
||||
cha->ancur = NULL;
|
||||
}
|
||||
|
||||
static void *cha_alloc(chastore_t *cha)
|
||||
|
@ -111,12 +106,7 @@ static void *cha_alloc(chastore_t *cha)
|
|||
if (!ancur)
|
||||
return NULL;
|
||||
ancur->icurr = 0;
|
||||
ancur->next = NULL;
|
||||
if (cha->tail)
|
||||
cha->tail->next = ancur;
|
||||
if (!cha->head)
|
||||
cha->head = ancur;
|
||||
cha->tail = ancur;
|
||||
ancur->next = cha->ancur;
|
||||
cha->ancur = ancur;
|
||||
}
|
||||
|
||||
|
@ -127,7 +117,7 @@ static void *cha_alloc(chastore_t *cha)
|
|||
|
||||
static void cha_free(chastore_t *cha)
|
||||
{
|
||||
chanode_t *cur = cha->head;
|
||||
chanode_t *cur = cha->ancur;
|
||||
while (cur) {
|
||||
chanode_t *tmp = cur;
|
||||
cur = cur->next;
|
||||
|
@ -142,7 +132,6 @@ typedef struct s_bdrecord {
|
|||
} bdrecord_t;
|
||||
|
||||
typedef struct s_bdfile {
|
||||
const unsigned char *data, *top;
|
||||
chastore_t cha;
|
||||
unsigned int fphbits;
|
||||
bdrecord_t **fphash;
|
||||
|
@ -152,7 +141,7 @@ static int delta_prepare(const unsigned char *buf, int bufsize, bdfile_t *bdf)
|
|||
{
|
||||
unsigned int fphbits;
|
||||
int i, hsize;
|
||||
const unsigned char *base, *data, *top;
|
||||
const unsigned char *data, *top;
|
||||
bdrecord_t *brec;
|
||||
bdrecord_t **fphash;
|
||||
|
||||
|
@ -165,13 +154,12 @@ static int delta_prepare(const unsigned char *buf, int bufsize, bdfile_t *bdf)
|
|||
fphash[i] = NULL;
|
||||
cha_init(&bdf->cha, sizeof(bdrecord_t), hsize / 4 + 1);
|
||||
|
||||
bdf->data = data = base = buf;
|
||||
bdf->top = top = buf + bufsize;
|
||||
data += (bufsize / BLK_SIZE) * BLK_SIZE;
|
||||
top = buf + bufsize;
|
||||
data = buf + (bufsize / BLK_SIZE) * BLK_SIZE;
|
||||
if (data == top)
|
||||
data -= BLK_SIZE;
|
||||
|
||||
for ( ; data >= base; data -= BLK_SIZE) {
|
||||
for ( ; data >= buf; data -= BLK_SIZE) {
|
||||
brec = cha_alloc(&bdf->cha);
|
||||
if (!brec) {
|
||||
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;
|
||||
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;
|
||||
bdrecord_t *brec;
|
||||
bdfile_t bdf;
|
||||
|
@ -224,6 +212,8 @@ void *diff_delta(void *from_buf, unsigned long from_size,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ref_data = from_buf;
|
||||
ref_top = from_buf + from_size;
|
||||
data = to_buf;
|
||||
top = to_buf + to_size;
|
||||
|
||||
|
@ -253,7 +243,7 @@ void *diff_delta(void *from_buf, unsigned long from_size,
|
|||
i = HASH(fp, bdf.fphbits);
|
||||
for (brec = bdf.fphash[i]; brec; brec = brec->next) {
|
||||
if (brec->fp == fp) {
|
||||
csize = bdf.top - brec->ptr;
|
||||
csize = ref_top - brec->ptr;
|
||||
if (csize > top - data)
|
||||
csize = top - 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;
|
||||
if (csize > msize) {
|
||||
moff = brec->ptr - bdf.data;
|
||||
moff = brec->ptr - ref_data;
|
||||
msize = csize;
|
||||
if (msize >= 0x10000) {
|
||||
msize = 0x10000;
|
||||
|
|
40
diff-tree.c
40
diff-tree.c
|
@ -14,11 +14,6 @@ static enum cmit_fmt commit_format = CMIT_FMT_RAW;
|
|||
|
||||
static struct diff_options diff_options;
|
||||
|
||||
static void call_diff_setup_done(void)
|
||||
{
|
||||
diff_setup_done(&diff_options);
|
||||
}
|
||||
|
||||
static int call_diff_flush(void)
|
||||
{
|
||||
diffcore_std(&diff_options);
|
||||
|
@ -43,7 +38,6 @@ static int diff_tree_sha1_top(const unsigned char *old,
|
|||
{
|
||||
int ret;
|
||||
|
||||
call_diff_setup_done();
|
||||
ret = diff_tree_sha1(old, new, base, &diff_options);
|
||||
call_diff_flush();
|
||||
return ret;
|
||||
|
@ -55,7 +49,6 @@ static int diff_root_tree(const unsigned char *new, const char *base)
|
|||
void *tree;
|
||||
struct tree_desc empty, real;
|
||||
|
||||
call_diff_setup_done();
|
||||
tree = read_object_with_reference(new, "tree", &real.size, NULL);
|
||||
if (!tree)
|
||||
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;
|
||||
}
|
||||
|
||||
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];
|
||||
int offset;
|
||||
unsigned long len;
|
||||
int abbrev = diff_options.abbrev;
|
||||
|
||||
if (!verbose_header)
|
||||
return commit;
|
||||
return sha1_to_hex(commit_sha1);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -99,18 +103,18 @@ static int diff_tree_commit(const unsigned char *commit_sha1)
|
|||
|
||||
/* Root commit? */
|
||||
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, "");
|
||||
}
|
||||
|
||||
/* More than one parent? */
|
||||
if (ignore_merges && commit->parents && commit->parents->next)
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
for (parents = commit->parents; parents; parents = parents->next) {
|
||||
struct commit *parent = parents->item;
|
||||
header = generate_header(name,
|
||||
sha1_to_hex(parent->object.sha1),
|
||||
header = generate_header(sha1,
|
||||
parent->object.sha1,
|
||||
commit->buffer);
|
||||
diff_tree_sha1_top(parent->object.sha1, commit_sha1, "");
|
||||
if (!header && verbose_header) {
|
||||
|
@ -129,6 +133,7 @@ static int diff_tree_stdin(char *line)
|
|||
int len = strlen(line);
|
||||
unsigned char commit[20], parent[20];
|
||||
static char this_header[1000];
|
||||
int abbrev = diff_options.abbrev;
|
||||
|
||||
if (!len || line[len-1] != '\n')
|
||||
return -1;
|
||||
|
@ -138,7 +143,9 @@ static int diff_tree_stdin(char *line)
|
|||
if (isspace(line[40]) && !get_sha1_hex(line+41, parent)) {
|
||||
line[40] = 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;
|
||||
return diff_tree_sha1_top(parent, commit, "");
|
||||
}
|
||||
|
@ -239,6 +246,7 @@ int main(int argc, const char **argv)
|
|||
diff_options.recursive = 1;
|
||||
|
||||
diff_tree_setup_paths(get_pathspec(prefix, argv));
|
||||
diff_setup_done(&diff_options);
|
||||
|
||||
switch (nr_sha1) {
|
||||
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)) {
|
||||
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);
|
||||
|
||||
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)
|
||||
len += snprintf(msg + len, sizeof(msg) - len,
|
||||
" %06o", one->mode);
|
||||
|
@ -791,6 +793,8 @@ int diff_setup_done(struct diff_options *options)
|
|||
}
|
||||
if (options->setup & DIFF_SETUP_USE_SIZE_CACHE)
|
||||
use_size_cache = 1;
|
||||
if (options->abbrev <= 0 || 40 < options->abbrev)
|
||||
options->abbrev = 40; /* full */
|
||||
|
||||
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"))
|
||||
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
|
||||
return 0;
|
||||
return 1;
|
||||
|
@ -947,14 +955,49 @@ void diff_free_filepair(struct diff_filepair *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,
|
||||
int line_termination,
|
||||
int inter_name_termination,
|
||||
int output_format)
|
||||
struct diff_options *options)
|
||||
{
|
||||
int two_paths;
|
||||
char status[10];
|
||||
int abbrev = options->abbrev;
|
||||
const char *path_one, *path_two;
|
||||
int output_format = options->output_format;
|
||||
|
||||
path_one = p->one->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) {
|
||||
printf(":%06o %06o %s ",
|
||||
p->one->mode, p->two->mode, sha1_to_hex(p->one->sha1));
|
||||
printf("%s ", sha1_to_hex(p->two->sha1));
|
||||
p->one->mode, p->two->mode,
|
||||
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);
|
||||
if (two_paths)
|
||||
|
@ -1194,7 +1239,7 @@ void diff_flush(struct diff_options *options)
|
|||
case DIFF_FORMAT_NAME_STATUS:
|
||||
diff_flush_raw(p, line_termination,
|
||||
inter_name_termination,
|
||||
diff_output_format);
|
||||
options);
|
||||
break;
|
||||
case DIFF_FORMAT_NAME:
|
||||
diff_flush_name(p,
|
||||
|
|
9
diff.h
9
diff.h
|
@ -44,6 +44,7 @@ struct diff_options {
|
|||
int reverse_diff;
|
||||
int rename_limit;
|
||||
int setup;
|
||||
int abbrev;
|
||||
|
||||
change_fn_t change;
|
||||
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_DEFAULT_INDEX_ABBREV 7 /* hex digits */
|
||||
#define DIFF_DEFAULT_ABBREV 7 /* hex digits */
|
||||
|
||||
extern void diffcore_std(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" \
|
||||
" --name-only show only names 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" \
|
||||
" -B detect complete rewrites.\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_BROKEN 'B'
|
||||
|
||||
extern const char *diff_unique_abbrev(const unsigned char *, int);
|
||||
|
||||
#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);
|
||||
}
|
60
fetch-pack.c
60
fetch-pack.c
|
@ -3,13 +3,12 @@
|
|||
#include "pkt-line.h"
|
||||
#include "commit.h"
|
||||
#include "tag.h"
|
||||
#include <time.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
static int keep_pack;
|
||||
static int quiet;
|
||||
static int verbose;
|
||||
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";
|
||||
|
||||
#define COMPLETE (1U << 0)
|
||||
|
@ -363,7 +362,6 @@ static int fetch_pack(int fd[2], int nr_match, char **match)
|
|||
struct ref *ref;
|
||||
unsigned char sha1[20];
|
||||
int status;
|
||||
pid_t pid;
|
||||
|
||||
get_remote_heads(fd[0], &ref, 0, NULL, 0);
|
||||
if (server_supports("multi_ack")) {
|
||||
|
@ -381,40 +379,22 @@ static int fetch_pack(int fd[2], int nr_match, char **match)
|
|||
}
|
||||
if (find_common(fd, sha1, ref) < 0)
|
||||
fprintf(stderr, "warning: no common commits\n");
|
||||
pid = fork();
|
||||
if (pid < 0)
|
||||
die("git-fetch-pack: unable to fork off git-unpack-objects");
|
||||
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");
|
||||
|
||||
if (keep_pack)
|
||||
status = receive_keep_pack(fd, "git-fetch-pack");
|
||||
else
|
||||
status = receive_unpack_pack(fd, "git-fetch-pack", quiet);
|
||||
|
||||
if (status)
|
||||
die("git-fetch-pack: fetch failed.");
|
||||
|
||||
all_done:
|
||||
while (ref) {
|
||||
printf("%s %s\n",
|
||||
sha1_to_hex(ref->old_sha1), ref->name);
|
||||
ref = ref->next;
|
||||
}
|
||||
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:
|
||||
while (ref) {
|
||||
printf("%s %s\n",
|
||||
sha1_to_hex(ref->old_sha1), ref->name);
|
||||
ref = ref->next;
|
||||
}
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
|
@ -436,10 +416,14 @@ int main(int argc, char **argv)
|
|||
exec = arg + 7;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("-q", arg)) {
|
||||
if (!strcmp("--quiet", arg) || !strcmp("-q", arg)) {
|
||||
quiet = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("--keep", arg) || !strcmp("-k", arg)) {
|
||||
keep_pack = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp("-v", arg)) {
|
||||
verbose = 1;
|
||||
continue;
|
||||
|
|
|
@ -211,6 +211,7 @@ this=`cat "$dotest/next"`
|
|||
if test "$skip" = t
|
||||
then
|
||||
this=`expr "$this" + 1`
|
||||
resume=
|
||||
fi
|
||||
|
||||
if test "$this" -gt "$last"
|
||||
|
@ -225,6 +226,7 @@ do
|
|||
msgnum=`printf "%0${prec}d" $this`
|
||||
next=`expr "$this" + 1`
|
||||
test -f "$dotest/$msgnum" || {
|
||||
resume=
|
||||
go_next
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
USAGE='<msg> <patch> <info> [<signoff>]'
|
||||
. git-sh-setup
|
||||
|
||||
case "$#" in 3|4) usage ;; esac
|
||||
case "$#" in 3|4) ;; *) usage ;; esac
|
||||
|
||||
final=.dotest/final-commit
|
||||
##
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
|
||||
=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
|
||||
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() {
|
||||
print STDERR <<END;
|
||||
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] ...
|
||||
END
|
||||
exit(1);
|
||||
|
|
|
@ -32,11 +32,11 @@ delete_branch () {
|
|||
case " $mbs " in
|
||||
*' '$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.
|
||||
If you are sure you want to delete it, run 'git branch -D $branch_name'."
|
||||
If you are sure you want to delete it, run 'git branch -D $branch_name'."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
|
|
@ -116,7 +116,7 @@ else
|
|||
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
|
||||
# old MERGE_HEAD's (subsequent commits will clearly not
|
||||
# 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;
|
||||
}
|
||||
|
||||
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 */
|
||||
#undef isspace
|
||||
#undef isdigit
|
||||
|
|
14
git-diff.sh
14
git-diff.sh
|
@ -3,15 +3,14 @@
|
|||
# Copyright (c) 2005 Linus Torvalds
|
||||
# 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
|
||||
flags=$(git-rev-parse --no-revs --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
|
||||
# obviously I mean 'git diff --cached -p HEAD' in that case.
|
||||
case "$rev" in
|
||||
|
@ -40,8 +39,7 @@ esac
|
|||
|
||||
case "$rev" in
|
||||
?*' '?*' '?*)
|
||||
echo >&2 "I don't understand"
|
||||
exit 1
|
||||
usage
|
||||
;;
|
||||
?*' '^?*)
|
||||
begin=$(expr "$rev" : '.*^.\([0-9a-f]*\).*') &&
|
||||
|
@ -58,7 +56,7 @@ case "$rev" in
|
|||
cmd="git-diff-files $flags -- $files"
|
||||
;;
|
||||
*)
|
||||
die "I don't understand $*"
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
|
||||
|
|
|
@ -210,6 +210,8 @@ Date: '"$ad"
|
|||
}
|
||||
|
||||
mailScript="$mailScript"'
|
||||
a\
|
||||
|
||||
: body
|
||||
p
|
||||
n
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
# Copyright (c) 2005 Linus Torvalds
|
||||
#
|
||||
|
||||
# This one uses only subdirectory-aware commands, so no need to
|
||||
# include sh-setup-script.
|
||||
USAGE='[--max-count=<n>] [<since>..<limit>] [--pretty=<format>] [git-rev-list options]'
|
||||
SUBDIRECTORY_OK='Yes'
|
||||
. git-sh-setup
|
||||
|
||||
revs=$(git-rev-parse --revs-only --no-flags --default HEAD "$@") || exit
|
||||
[ "$revs" ] || {
|
||||
echo >&2 "No HEAD ref"
|
||||
exit 1
|
||||
die "No HEAD ref"
|
||||
}
|
||||
git-rev-list --pretty $(git-rev-parse --default HEAD "$@") |
|
||||
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'};
|
||||
|
||||
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;
|
||||
|
||||
my $pool=SVN::Pool->new;
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
#!/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 "$@") &&
|
||||
diff_tree_args=$(git-rev-parse --sq --no-revs "$@") &&
|
||||
|
||||
|
|
32
git.c
32
git.c
|
@ -8,6 +8,7 @@
|
|||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include "git-compat-util.h"
|
||||
|
||||
#ifndef PATH_MAX
|
||||
|
@ -26,6 +27,16 @@ static int term_columns(void)
|
|||
if (col_string && (n_cols = atoi(col_string)) > 0)
|
||||
return n_cols;
|
||||
|
||||
#ifdef TIOCGWINSZ
|
||||
{
|
||||
struct winsize ws;
|
||||
if (!ioctl(1, TIOCGWINSZ, &ws)) {
|
||||
if (ws.ws_col)
|
||||
return ws.ws_col;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
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)
|
||||
{
|
||||
int cols = 1;
|
||||
int cols = 1, rows;
|
||||
int space = longest + 1; /* min 1 SP between words */
|
||||
int max_cols = term_columns() - 1; /* don't print *on* the edge */
|
||||
int i;
|
||||
int i, j;
|
||||
|
||||
if (space < max_cols)
|
||||
cols = max_cols / space;
|
||||
rows = (cmdname_cnt + cols - 1) / cols;
|
||||
|
||||
qsort(cmdname, cmdname_cnt, sizeof(*cmdname), cmdname_compare);
|
||||
|
||||
for (i = 0; i < cmdname_cnt; ) {
|
||||
int c;
|
||||
for (i = 0; i < rows; i++) {
|
||||
printf(" ");
|
||||
|
||||
for (c = cols; c && i < cmdname_cnt; i++) {
|
||||
printf("%s", cmdname[i]->name);
|
||||
|
||||
if (--c)
|
||||
mput_char(' ', space - cmdname[i]->len);
|
||||
for (j = 0; j < cols; j++) {
|
||||
int n = j * rows + i;
|
||||
int size = space;
|
||||
if (n >= cmdname_cnt)
|
||||
break;
|
||||
if (j == cols-1 || n + rows >= cmdname_cnt)
|
||||
size = 1;
|
||||
printf("%-*s", size, cmdname[n]->name);
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
|
|
9
mktag.c
9
mktag.c
|
@ -116,14 +116,9 @@ int main(int argc, char **argv)
|
|||
// Read the signature
|
||||
size = 0;
|
||||
for (;;) {
|
||||
int ret = read(0, buffer + size, MAXSIZE - size);
|
||||
if (!ret)
|
||||
int ret = xread(0, buffer + size, MAXSIZE - size);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
if (ret < 0) {
|
||||
if (errno == EAGAIN)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
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)
|
||||
{
|
||||
while (n) {
|
||||
int ret = write(fd, buf, n);
|
||||
int ret = xwrite(fd, buf, n);
|
||||
if (ret > 0) {
|
||||
buf += ret;
|
||||
n -= ret;
|
||||
|
@ -27,8 +27,6 @@ static void safe_write(int fd, const void *buf, unsigned n)
|
|||
}
|
||||
if (!ret)
|
||||
die("write error (disk full?)");
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
continue;
|
||||
die("write error (%s)", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
@ -68,12 +66,9 @@ static void safe_read(int fd, void *buffer, unsigned size)
|
|||
int n = 0;
|
||||
|
||||
while (n < size) {
|
||||
int ret = read(fd, buffer + n, size - n);
|
||||
if (ret < 0) {
|
||||
if (errno == EINTR || errno == EAGAIN)
|
||||
continue;
|
||||
int ret = xread(fd, buffer + n, size - n);
|
||||
if (ret < 0)
|
||||
die("read error (%s)", strerror(errno));
|
||||
}
|
||||
if (!ret)
|
||||
die("unexpected EOF");
|
||||
n += ret;
|
||||
|
|
188
read-cache.c
188
read-cache.c
|
@ -6,6 +6,7 @@
|
|||
#include "cache.h"
|
||||
|
||||
struct cache_entry **active_cache = NULL;
|
||||
static time_t index_file_timestamp;
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
@ -83,57 +142,44 @@ int ce_match_stat(struct cache_entry *ce, struct stat *st)
|
|||
|
||||
if (ce->ce_size != htonl(st->st_size))
|
||||
changed |= DATA_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;
|
||||
int fd = open(ce->name, O_RDONLY);
|
||||
unsigned int changed = ce_match_stat_basic(ce, st);
|
||||
|
||||
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;
|
||||
}
|
||||
/*
|
||||
* Within 1 second of this sequence:
|
||||
* echo xyzzy >file && git-update-index --add file
|
||||
* running this command:
|
||||
* echo frotz >file
|
||||
* would give a falsely clean cache entry. The mtime and
|
||||
* 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)
|
||||
{
|
||||
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;
|
||||
return changed;
|
||||
}
|
||||
|
||||
int ce_modified(struct cache_entry *ce, struct stat *st)
|
||||
{
|
||||
int changed;
|
||||
int changed, changed_fs;
|
||||
changed = ce_match_stat(ce, st);
|
||||
if (!changed)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If the mode or type has changed, there's no point in trying
|
||||
* 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))
|
||||
return changed;
|
||||
|
||||
switch (st->st_mode & S_IFMT) {
|
||||
case S_IFREG:
|
||||
if (ce_compare_data(ce, st))
|
||||
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;
|
||||
}
|
||||
changed_fs = ce_modified_check_fs(ce, st);
|
||||
if (changed_fs)
|
||||
return changed | changed_fs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -471,6 +508,7 @@ int read_cache(void)
|
|||
return active_nr;
|
||||
|
||||
errno = ENOENT;
|
||||
index_file_timestamp = 0;
|
||||
fd = open(get_index_file(), O_RDONLY);
|
||||
if (fd < 0) {
|
||||
if (errno == ENOENT)
|
||||
|
@ -504,6 +542,7 @@ int read_cache(void)
|
|||
offset = offset + ce_size(ce);
|
||||
active_cache[i] = ce;
|
||||
}
|
||||
index_file_timestamp = st.st_mtime;
|
||||
return active_nr;
|
||||
|
||||
unmap:
|
||||
|
@ -562,6 +601,50 @@ static int ce_flush(SHA_CTX *context, int fd)
|
|||
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)
|
||||
{
|
||||
SHA_CTX c;
|
||||
|
@ -584,6 +667,9 @@ int write_cache(int newfd, struct cache_entry **cache, int entries)
|
|||
struct cache_entry *ce = cache[i];
|
||||
if (!ce->ce_mode)
|
||||
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)
|
||||
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)
|
||||
{
|
||||
return (((unsigned) ch) <= ' ' ||
|
||||
ch == '~' || ch == '^' || ch == ':');
|
||||
ch == '~' || ch == '^' || ch == ':' ||
|
||||
/* 2.13 Pattern Matching Notation */
|
||||
ch == '?' || ch == '*' || ch == '[');
|
||||
}
|
||||
|
||||
int check_ref_format(const char *ref)
|
||||
|
|
|
@ -850,7 +850,8 @@ int main(int argc, const char **argv)
|
|||
handle_one_commit(commit, &list);
|
||||
}
|
||||
|
||||
if (!list)
|
||||
if (!list &&
|
||||
(!(tag_objects||tree_objects||blob_objects) && !pending_objects))
|
||||
usage(rev_list_usage);
|
||||
|
||||
paths = get_pathspec(prefix, argv + i);
|
||||
|
|
10
send-pack.c
10
send-pack.c
|
@ -8,6 +8,7 @@ static const char send_pack_usage[] =
|
|||
"git-send-pack [--all] [--exec=git-receive-pack] <remote> [<head>...]\n"
|
||||
" --all and explicit <head> specification are mutually exclusive.";
|
||||
static const char *exec = "git-receive-pack";
|
||||
static int verbose = 0;
|
||||
static int send_all = 0;
|
||||
static int force_update = 0;
|
||||
|
||||
|
@ -206,7 +207,8 @@ static int send_pack(int in, int out, int nr_refspec, char **refspec)
|
|||
if (!ref->peer_ref)
|
||||
continue;
|
||||
if (!memcmp(ref->old_sha1, ref->peer_ref->new_sha1, 20)) {
|
||||
fprintf(stderr, "'%s': up-to-date\n", ref->name);
|
||||
if (verbose)
|
||||
fprintf(stderr, "'%s': up-to-date\n", ref->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -270,6 +272,8 @@ static int send_pack(int in, int out, int nr_refspec, char **refspec)
|
|||
packet_flush(out);
|
||||
if (new_refs)
|
||||
pack_objects(out, remote_refs);
|
||||
else
|
||||
fprintf(stderr, "Everything up-to-date\n");
|
||||
close(out);
|
||||
return ret;
|
||||
}
|
||||
|
@ -301,6 +305,10 @@ int main(int argc, char **argv)
|
|||
force_update = 1;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(arg, "--verbose")) {
|
||||
verbose = 1;
|
||||
continue;
|
||||
}
|
||||
usage(send_pack_usage);
|
||||
}
|
||||
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;
|
||||
static char hex[41];
|
||||
|
||||
memcpy(hex, sha1_to_hex(sha1), 40);
|
||||
if (len == 40)
|
||||
return hex;
|
||||
while (len < 40) {
|
||||
unsigned char sha1_ret[20];
|
||||
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;
|
||||
}
|
||||
|
||||
static int ambiguous_path(const char *path)
|
||||
static int ambiguous_path(const char *path, int len)
|
||||
{
|
||||
int slash = 1;
|
||||
int cnt;
|
||||
|
||||
for (;;) {
|
||||
for (cnt = 0; cnt < len; cnt++) {
|
||||
switch (*path++) {
|
||||
case '\0':
|
||||
break;
|
||||
|
@ -222,8 +226,9 @@ static int ambiguous_path(const char *path)
|
|||
slash = 0;
|
||||
continue;
|
||||
}
|
||||
return slash;
|
||||
break;
|
||||
}
|
||||
return slash;
|
||||
}
|
||||
|
||||
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
|
||||
};
|
||||
const char **p;
|
||||
int found = 0;
|
||||
|
||||
if (len == 40 && !get_sha1_hex(str, sha1))
|
||||
return 0;
|
||||
|
||||
/* Accept only unambiguous ref paths. */
|
||||
if (ambiguous_path(str))
|
||||
if (ambiguous_path(str, len))
|
||||
return -1;
|
||||
|
||||
for (p = prefix; *p; p++) {
|
||||
char *pathname = git_path("%s/%.*s", *p, len, str);
|
||||
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 (!read_ref(pathname, sha1))
|
||||
return 0;
|
||||
}
|
||||
if (found == 1)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -450,6 +450,8 @@ static void append_one_rev(const char *av)
|
|||
if (saved_matches == ref_name_cnt &&
|
||||
ref_name_cnt < MAX_REVS)
|
||||
error("no matching refs with %s", av);
|
||||
if (saved_matches + 1 < ref_name_cnt)
|
||||
sort_ref_range(saved_matches, ref_name_cnt);
|
||||
return;
|
||||
}
|
||||
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_EMAIL
|
||||
unset GIT_AUTHOR_NAME
|
||||
unset GIT_COMMITTER_DATE
|
||||
unset GIT_COMMITTER_EMAIL
|
||||
unset GIT_COMMITTER_NAME
|
||||
unset GIT_DIFF_OPTS
|
||||
|
|
|
@ -34,10 +34,8 @@ struct path_prefix {
|
|||
static void reliable_write(void *buf, unsigned long size)
|
||||
{
|
||||
while (size > 0) {
|
||||
long ret = write(1, buf, size);
|
||||
long ret = xwrite(1, buf, size);
|
||||
if (ret < 0) {
|
||||
if (errno == EAGAIN)
|
||||
continue;
|
||||
if (errno == EPIPE)
|
||||
exit(0);
|
||||
die("git-tar-tree: %s", strerror(errno));
|
||||
|
|
|
@ -31,12 +31,10 @@ static void * fill(int min)
|
|||
offset = 0;
|
||||
}
|
||||
do {
|
||||
int ret = read(0, buffer + len, sizeof(buffer) - len);
|
||||
int ret = xread(0, buffer + len, sizeof(buffer) - len);
|
||||
if (ret <= 0) {
|
||||
if (!ret)
|
||||
die("early EOF");
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
continue;
|
||||
die("read error on input: %s", strerror(errno));
|
||||
}
|
||||
len += ret;
|
||||
|
@ -299,14 +297,9 @@ int main(int argc, char **argv)
|
|||
|
||||
/* Write the last part of the buffer to stdout */
|
||||
while (len) {
|
||||
int ret = write(1, buffer + offset, len);
|
||||
if (!ret)
|
||||
int ret = xwrite(1, buffer + offset, len);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
if (ret < 0) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
len -= ret;
|
||||
offset += ret;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче