GIT 0.99.9j aka 1.0rc3
Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
parent
60d64db461
commit
27dedf0c3b
@ -81,7 +81,7 @@ The "diff" formatting options can be customized via the
|
|||||||
environment variable 'GIT_DIFF_OPTS'. For example, if you
|
environment variable 'GIT_DIFF_OPTS'. For example, if you
|
||||||
prefer context diff:
|
prefer context diff:
|
||||||
|
|
||||||
GIT_DIFF_OPTS=-c git-diff-index -p $(cat .git/HEAD)
|
GIT_DIFF_OPTS=-c git-diff-index -p HEAD
|
||||||
|
|
||||||
|
|
||||||
2. When the environment variable 'GIT_EXTERNAL_DIFF' is set, the
|
2. When the environment variable 'GIT_EXTERNAL_DIFF' is set, the
|
||||||
|
@ -13,6 +13,11 @@
|
|||||||
--name-status::
|
--name-status::
|
||||||
Show only names and status of changed files.
|
Show only names and status of changed files.
|
||||||
|
|
||||||
|
--full-index::
|
||||||
|
Instead of the first handful characters, show full
|
||||||
|
object name of pre- and post-image blob on the "index"
|
||||||
|
line when generating a patch format output.
|
||||||
|
|
||||||
-B::
|
-B::
|
||||||
Break complete rewrite changes into pairs of delete and create.
|
Break complete rewrite changes into pairs of delete and create.
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ git-apply - Apply patch on a git index file and a work tree
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-apply' [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--index-info] [-z] [<patch>...]
|
'git-apply' [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [-z] [<patch>...]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -79,6 +79,17 @@ OPTIONS
|
|||||||
the result with this option, which would apply the
|
the result with this option, which would apply the
|
||||||
deletion part but not addition part.
|
deletion part but not addition part.
|
||||||
|
|
||||||
|
--allow-binary-replacement::
|
||||||
|
When applying a patch, which is a git-enhanced patch
|
||||||
|
that was prepared to record the pre- and post-image object
|
||||||
|
name in full, and the path being patched exactly matches
|
||||||
|
the object the patch applies to (i.e. "index" line's
|
||||||
|
pre-image object name is what is in the working tree),
|
||||||
|
and the post-image object is available in the object
|
||||||
|
database, use the post-image object as the patch
|
||||||
|
result. This allows binary files to be patched in a
|
||||||
|
very limited way.
|
||||||
|
|
||||||
Author
|
Author
|
||||||
------
|
------
|
||||||
Written by Linus Torvalds <torvalds@osdl.org>
|
Written by Linus Torvalds <torvalds@osdl.org>
|
||||||
|
@ -26,8 +26,9 @@ to get there.
|
|||||||
|
|
||||||
Normally a commit would identify a new "HEAD" state, and while git
|
Normally a commit would identify a new "HEAD" state, and while git
|
||||||
doesn't care where you save the note about that state, in practice we
|
doesn't care where you save the note about that state, in practice we
|
||||||
tend to just write the result to the file `.git/HEAD`, so that we can
|
tend to just write the result to the file that is pointed at by
|
||||||
always see what the last committed state was.
|
`.git/HEAD`, so that we can always see what the last committed
|
||||||
|
state was.
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
|
@ -35,7 +35,7 @@ OPTIONS
|
|||||||
do not have the 'git-daemon-export-ok' file.
|
do not have the 'git-daemon-export-ok' file.
|
||||||
|
|
||||||
--inetd::
|
--inetd::
|
||||||
Have the server run as an inetd service.
|
Have the server run as an inetd service. Implies --syslog.
|
||||||
|
|
||||||
--port::
|
--port::
|
||||||
Listen on an alternative port.
|
Listen on an alternative port.
|
||||||
|
@ -57,14 +57,14 @@ some files in the index and are ready to commit. You want to see eactly
|
|||||||
*what* you are going to commit is without having to write a new tree
|
*what* you are going to commit is without having to write a new tree
|
||||||
object and compare it that way, and to do that, you just do
|
object and compare it that way, and to do that, you just do
|
||||||
|
|
||||||
git-diff-index --cached $(cat .git/HEAD)
|
git-diff-index --cached HEAD
|
||||||
|
|
||||||
Example: let's say I had renamed `commit.c` to `git-commit.c`, and I had
|
Example: let's say I had renamed `commit.c` to `git-commit.c`, and I had
|
||||||
done an "git-update-index" to make that effective in the index file.
|
done an "git-update-index" to make that effective in the index file.
|
||||||
"git-diff-files" wouldn't show anything at all, since the index file
|
"git-diff-files" wouldn't show anything at all, since the index file
|
||||||
matches my working directory. But doing a "git-diff-index" does:
|
matches my working directory. But doing a "git-diff-index" does:
|
||||||
|
|
||||||
torvalds@ppc970:~/git> git-diff-index --cached $(cat .git/HEAD)
|
torvalds@ppc970:~/git> git-diff-index --cached HEAD
|
||||||
-100644 blob 4161aecc6700a2eb579e842af0b7f22b98443f74 commit.c
|
-100644 blob 4161aecc6700a2eb579e842af0b7f22b98443f74 commit.c
|
||||||
+100644 blob 4161aecc6700a2eb579e842af0b7f22b98443f74 git-commit.c
|
+100644 blob 4161aecc6700a2eb579e842af0b7f22b98443f74 git-commit.c
|
||||||
|
|
||||||
@ -98,7 +98,7 @@ show that. So let's say that you have edited `kernel/sched.c`, but
|
|||||||
have not actually done a "git-update-index" on it yet - there is no
|
have not actually done a "git-update-index" on it yet - there is no
|
||||||
"object" associated with the new state, and you get:
|
"object" associated with the new state, and you get:
|
||||||
|
|
||||||
torvalds@ppc970:~/v2.6/linux> git-diff-index $(cat .git/HEAD )
|
torvalds@ppc970:~/v2.6/linux> git-diff-index HEAD
|
||||||
*100644->100664 blob 7476bb......->000000...... kernel/sched.c
|
*100644->100664 blob 7476bb......->000000...... kernel/sched.c
|
||||||
|
|
||||||
ie it shows that the tree has changed, and that `kernel/sched.c` has is
|
ie it shows that the tree has changed, and that `kernel/sched.c` has is
|
||||||
|
@ -68,7 +68,7 @@ that aren't readable from any of the specified head nodes.
|
|||||||
|
|
||||||
So for example
|
So for example
|
||||||
|
|
||||||
git-fsck-objects --unreachable $(cat .git/HEAD .git/refs/heads/*)
|
git-fsck-objects --unreachable HEAD $(cat .git/refs/heads/*)
|
||||||
|
|
||||||
will do quite a _lot_ of verification on the tree. There are a few
|
will do quite a _lot_ of verification on the tree. There are a few
|
||||||
extra validity tests to be added (make sure that tree objects are
|
extra validity tests to be added (make sure that tree objects are
|
||||||
|
@ -20,7 +20,7 @@ This manual page describes only the most frequently used options.
|
|||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
--pretty=<format>:
|
--pretty=<format>::
|
||||||
Controls the way the commit log is formatted.
|
Controls the way the commit log is formatted.
|
||||||
|
|
||||||
--max-count=<n>::
|
--max-count=<n>::
|
||||||
|
@ -237,7 +237,7 @@ This is done to prevent you from losing your work-in-progress
|
|||||||
changes. To illustrate, suppose you start from what has been
|
changes. To illustrate, suppose you start from what has been
|
||||||
commited last to your repository:
|
commited last to your repository:
|
||||||
|
|
||||||
$ JC=`cat .git/HEAD`
|
$ JC=`git-rev-parse --verify "HEAD^0"`
|
||||||
$ git-checkout-index -f -u -a $JC
|
$ git-checkout-index -f -u -a $JC
|
||||||
|
|
||||||
You do random edits, without running git-update-index. And then
|
You do random edits, without running git-update-index. And then
|
||||||
|
@ -24,8 +24,8 @@ Traditionally, `.git/HEAD` is a symlink pointing at
|
|||||||
we did `ln -sf refs/heads/newbranch .git/HEAD`, and when we want
|
we did `ln -sf refs/heads/newbranch .git/HEAD`, and when we want
|
||||||
to find out which branch we are on, we did `readlink .git/HEAD`.
|
to find out which branch we are on, we did `readlink .git/HEAD`.
|
||||||
This was fine, and internally that is what still happens by
|
This was fine, and internally that is what still happens by
|
||||||
default, but on platforms that does not have working symlinks,
|
default, but on platforms that do not have working symlinks,
|
||||||
or that does not have the `readlink(1)` command, this was a bit
|
or that do not have the `readlink(1)` command, this was a bit
|
||||||
cumbersome. On some platforms, `ln -sf` does not even work as
|
cumbersome. On some platforms, `ln -sf` does not even work as
|
||||||
advertised (horrors).
|
advertised (horrors).
|
||||||
|
|
||||||
|
@ -8,13 +8,33 @@ git - the stupid content tracker
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
'git-<command>' <args>
|
'git' [--version] [--exec-path[=GIT_EXEC_PATH]] [--help] COMMAND [ARGS]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
|
'git' is both a program and a directory content tracker system.
|
||||||
|
The program 'git' is just a wrapper to reach the core git programs
|
||||||
|
(or a potty if you like, as it's not exactly porcelain but still
|
||||||
|
brings your stuff to the plumbing).
|
||||||
|
|
||||||
This is reference information for the core git commands.
|
OPTIONS
|
||||||
|
-------
|
||||||
|
--version::
|
||||||
|
prints the git suite version that the 'git' program came from.
|
||||||
|
|
||||||
|
--help::
|
||||||
|
prints the synopsis and a list of available commands.
|
||||||
|
If a git command is named this option will bring up the
|
||||||
|
man-page for that command.
|
||||||
|
|
||||||
|
--exec-path::
|
||||||
|
path to wherever your core git programs are installed.
|
||||||
|
This can also be controlled by setting the GIT_EXEC_PATH
|
||||||
|
environment variable. If no path is given 'git' will print
|
||||||
|
the current setting and then exit.
|
||||||
|
|
||||||
|
CORE GIT COMMANDS
|
||||||
|
-----------------
|
||||||
Before reading this cover to cover, you may want to take a look
|
Before reading this cover to cover, you may want to take a look
|
||||||
at the link:tutorial.html[tutorial] document.
|
at the link:tutorial.html[tutorial] document.
|
||||||
|
|
||||||
@ -67,7 +87,7 @@ gitlink:git-commit-tree[1]::
|
|||||||
gitlink:git-hash-object[1]::
|
gitlink:git-hash-object[1]::
|
||||||
Computes the object ID from a file.
|
Computes the object ID from a file.
|
||||||
|
|
||||||
gitlink:git-index-pack.html[1]::
|
gitlink:git-index-pack[1]::
|
||||||
Build pack index file for an existing packed archive.
|
Build pack index file for an existing packed archive.
|
||||||
|
|
||||||
gitlink:git-init-db[1]::
|
gitlink:git-init-db[1]::
|
||||||
@ -533,9 +553,12 @@ Discussion[[Discussion]]
|
|||||||
------------------------
|
------------------------
|
||||||
include::../README[]
|
include::../README[]
|
||||||
|
|
||||||
Author
|
Authors
|
||||||
------
|
-------
|
||||||
Written by Linus Torvalds <torvalds@osdl.org> and the git-list <git@vger.kernel.org>.
|
git's founding father is Linus Torvalds <torvalds@osdl.org>.
|
||||||
|
The current git nurse is Junio C. Hamano <junkio@cox.net>.
|
||||||
|
The git potty was written by Andres Ericsson <ae@op5.se>.
|
||||||
|
General upbringing is handled by the git-list <git@vger.kernel.org>.
|
||||||
|
|
||||||
Documentation
|
Documentation
|
||||||
--------------
|
--------------
|
||||||
|
40
Makefile
40
Makefile
@ -50,7 +50,7 @@
|
|||||||
# 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.9i
|
GIT_VERSION = 0.99.9j
|
||||||
|
|
||||||
# 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.
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ SCRIPT_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 \
|
||||||
git-tag.sh git-verify-tag.sh git-whatchanged.sh git.sh \
|
git-tag.sh git-verify-tag.sh git-whatchanged.sh \
|
||||||
git-applymbox.sh git-applypatch.sh git-am.sh \
|
git-applymbox.sh git-applypatch.sh git-am.sh \
|
||||||
git-merge.sh git-merge-stupid.sh git-merge-octopus.sh \
|
git-merge.sh git-merge-stupid.sh git-merge-octopus.sh \
|
||||||
git-merge-resolve.sh git-merge-ours.sh git-grep.sh \
|
git-merge-resolve.sh git-merge-ours.sh git-grep.sh \
|
||||||
@ -105,7 +105,7 @@ SCRIPT_PYTHON = \
|
|||||||
# The ones that do not have to link with lcrypto nor lz.
|
# The ones that do not have to link with lcrypto nor lz.
|
||||||
SIMPLE_PROGRAMS = \
|
SIMPLE_PROGRAMS = \
|
||||||
git-get-tar-commit-id$X git-mailinfo$X git-mailsplit$X \
|
git-get-tar-commit-id$X git-mailinfo$X git-mailsplit$X \
|
||||||
git-stripspace$X git-var$X git-daemon$X
|
git-stripspace$X git-daemon$X
|
||||||
|
|
||||||
# ... and all the rest
|
# ... and all the rest
|
||||||
PROGRAMS = \
|
PROGRAMS = \
|
||||||
@ -125,7 +125,7 @@ PROGRAMS = \
|
|||||||
git-unpack-objects$X git-update-index$X git-update-server-info$X \
|
git-unpack-objects$X git-update-index$X git-update-server-info$X \
|
||||||
git-upload-pack$X git-verify-pack$X git-write-tree$X \
|
git-upload-pack$X git-verify-pack$X git-write-tree$X \
|
||||||
git-update-ref$X git-symbolic-ref$X git-check-ref-format$X \
|
git-update-ref$X git-symbolic-ref$X git-check-ref-format$X \
|
||||||
git-name-rev$X git-pack-redundant$X $(SIMPLE_PROGRAMS)
|
git-name-rev$X git-pack-redundant$X git-var$X $(SIMPLE_PROGRAMS)
|
||||||
|
|
||||||
# Backward compatibility -- to be removed after 1.0
|
# Backward compatibility -- to be removed after 1.0
|
||||||
PROGRAMS += git-ssh-pull$X git-ssh-push$X
|
PROGRAMS += git-ssh-pull$X git-ssh-push$X
|
||||||
@ -334,19 +334,15 @@ SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
|
|||||||
export prefix TAR INSTALL DESTDIR SHELL_PATH template_dir
|
export prefix TAR INSTALL DESTDIR SHELL_PATH template_dir
|
||||||
### Build rules
|
### Build rules
|
||||||
|
|
||||||
all: $(PROGRAMS) $(SCRIPTS)
|
all: $(PROGRAMS) $(SCRIPTS) git
|
||||||
|
|
||||||
all:
|
all:
|
||||||
$(MAKE) -C templates
|
$(MAKE) -C templates
|
||||||
|
|
||||||
git: git.sh Makefile
|
# Only use $(CFLAGS). We don't need anything else.
|
||||||
rm -f $@+ $@
|
git: git.c Makefile
|
||||||
sed -e '1s|#!.*/sh|#!$(call shq,$(SHELL_PATH))|' \
|
$(CC) -DGIT_EXEC_PATH='"$(bindir)"' -DGIT_VERSION='"$(GIT_VERSION)"' \
|
||||||
-e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
|
$(CFLAGS) $@.c -o $@
|
||||||
-e 's/@@X@@/$(X)/g' \
|
|
||||||
$(GIT_LIST_TWEAK) <$@.sh >$@+
|
|
||||||
chmod +x $@+
|
|
||||||
mv $@+ $@
|
|
||||||
|
|
||||||
$(filter-out git,$(patsubst %.sh,%,$(SCRIPT_SH))) : % : %.sh
|
$(filter-out git,$(patsubst %.sh,%,$(SCRIPT_SH))) : % : %.sh
|
||||||
rm -f $@
|
rm -f $@
|
||||||
@ -431,9 +427,9 @@ check:
|
|||||||
|
|
||||||
### Installation rules
|
### Installation rules
|
||||||
|
|
||||||
install: $(PROGRAMS) $(SCRIPTS)
|
install: $(PROGRAMS) $(SCRIPTS) git
|
||||||
$(INSTALL) -d -m755 $(call shellquote,$(DESTDIR)$(bindir))
|
$(INSTALL) -d -m755 $(call shellquote,$(DESTDIR)$(bindir))
|
||||||
$(INSTALL) $(PROGRAMS) $(SCRIPTS) $(call shellquote,$(DESTDIR)$(bindir))
|
$(INSTALL) git $(PROGRAMS) $(SCRIPTS) $(call shellquote,$(DESTDIR)$(bindir))
|
||||||
$(MAKE) -C templates install
|
$(MAKE) -C templates install
|
||||||
$(INSTALL) -d -m755 $(call shellquote,$(DESTDIR)$(GIT_PYTHON_DIR))
|
$(INSTALL) -d -m755 $(call shellquote,$(DESTDIR)$(GIT_PYTHON_DIR))
|
||||||
$(INSTALL) $(PYMODULES) $(call shellquote,$(DESTDIR)$(GIT_PYTHON_DIR))
|
$(INSTALL) $(PYMODULES) $(call shellquote,$(DESTDIR)$(GIT_PYTHON_DIR))
|
||||||
@ -446,20 +442,20 @@ install-doc:
|
|||||||
|
|
||||||
### Maintainer's dist rules
|
### Maintainer's dist rules
|
||||||
|
|
||||||
git-core.spec: git-core.spec.in Makefile
|
git.spec: git.spec.in Makefile
|
||||||
sed -e 's/@@VERSION@@/$(GIT_VERSION)/g' < $< > $@
|
sed -e 's/@@VERSION@@/$(GIT_VERSION)/g' < $< > $@
|
||||||
|
|
||||||
GIT_TARNAME=git-core-$(GIT_VERSION)
|
GIT_TARNAME=git-$(GIT_VERSION)
|
||||||
dist: git-core.spec git-tar-tree
|
dist: git.spec git-tar-tree
|
||||||
./git-tar-tree HEAD $(GIT_TARNAME) > $(GIT_TARNAME).tar
|
./git-tar-tree HEAD $(GIT_TARNAME) > $(GIT_TARNAME).tar
|
||||||
@mkdir -p $(GIT_TARNAME)
|
@mkdir -p $(GIT_TARNAME)
|
||||||
@cp git-core.spec $(GIT_TARNAME)
|
@cp git.spec $(GIT_TARNAME)
|
||||||
$(TAR) rf $(GIT_TARNAME).tar $(GIT_TARNAME)/git-core.spec
|
$(TAR) rf $(GIT_TARNAME).tar $(GIT_TARNAME)/git.spec
|
||||||
@rm -rf $(GIT_TARNAME)
|
@rm -rf $(GIT_TARNAME)
|
||||||
gzip -f -9 $(GIT_TARNAME).tar
|
gzip -f -9 $(GIT_TARNAME).tar
|
||||||
|
|
||||||
rpm: dist
|
rpm: dist
|
||||||
$(RPMBUILD) -ta git-core-$(GIT_VERSION).tar.gz
|
$(RPMBUILD) -ta $(GIT_TARNAME).tar.gz
|
||||||
|
|
||||||
deb: dist
|
deb: dist
|
||||||
rm -rf $(GIT_TARNAME)
|
rm -rf $(GIT_TARNAME)
|
||||||
@ -472,7 +468,7 @@ deb: dist
|
|||||||
clean:
|
clean:
|
||||||
rm -f *.o mozilla-sha1/*.o ppc/*.o compat/*.o $(PROGRAMS) $(LIB_FILE)
|
rm -f *.o mozilla-sha1/*.o ppc/*.o compat/*.o $(PROGRAMS) $(LIB_FILE)
|
||||||
rm -f $(filter-out gitk,$(SCRIPTS))
|
rm -f $(filter-out gitk,$(SCRIPTS))
|
||||||
rm -f git-core.spec *.pyc *.pyo
|
rm -f *.spec *.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
|
||||||
|
6
README
6
README
@ -396,8 +396,8 @@ git-commit-tree will return the name of the object that represents
|
|||||||
that commit, and you should save it away for later use. Normally,
|
that commit, and you should save it away for later use. Normally,
|
||||||
you'd commit a new `HEAD` state, and while git doesn't care where you
|
you'd commit a new `HEAD` state, and while git doesn't care where you
|
||||||
save the note about that state, in practice we tend to just write the
|
save the note about that state, in practice we tend to just write the
|
||||||
result to the file `.git/HEAD`, so that we can always see what the
|
result to the file pointed at by `.git/HEAD`, so that we can always see
|
||||||
last committed state was.
|
what the last committed state was.
|
||||||
|
|
||||||
Here is an ASCII art by Jon Loeliger that illustrates how
|
Here is an ASCII art by Jon Loeliger that illustrates how
|
||||||
various pieces fit together.
|
various pieces fit together.
|
||||||
@ -464,7 +464,7 @@ tend to be small and fairly self-explanatory. In particular, if you
|
|||||||
follow the convention of having the top commit name in `.git/HEAD`,
|
follow the convention of having the top commit name in `.git/HEAD`,
|
||||||
you can do
|
you can do
|
||||||
|
|
||||||
git-cat-file commit $(cat .git/HEAD)
|
git-cat-file commit HEAD
|
||||||
|
|
||||||
to see what the top commit was.
|
to see what the top commit was.
|
||||||
|
|
||||||
|
92
apply.c
92
apply.c
@ -16,6 +16,7 @@
|
|||||||
// --numstat does numeric diffstat, and doesn't actually apply
|
// --numstat does numeric diffstat, and doesn't actually apply
|
||||||
// --index-info shows the old and new index info for paths if available.
|
// --index-info shows the old and new index info for paths if available.
|
||||||
//
|
//
|
||||||
|
static int allow_binary_replacement = 0;
|
||||||
static int check_index = 0;
|
static int check_index = 0;
|
||||||
static int write_index = 0;
|
static int write_index = 0;
|
||||||
static int diffstat = 0;
|
static int diffstat = 0;
|
||||||
@ -27,7 +28,7 @@ static int no_add = 0;
|
|||||||
static int show_index_info = 0;
|
static int show_index_info = 0;
|
||||||
static int line_termination = '\n';
|
static int line_termination = '\n';
|
||||||
static const char apply_usage[] =
|
static const char apply_usage[] =
|
||||||
"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--index-info] [-z] <patch>...";
|
"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [-z] <patch>...";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For "diff-stat" like behaviour, we keep track of the biggest change
|
* For "diff-stat" like behaviour, we keep track of the biggest change
|
||||||
@ -891,7 +892,7 @@ static int parse_chunk(char *buffer, unsigned long size, struct patch *patch)
|
|||||||
|
|
||||||
patchsize = parse_single_patch(buffer + offset + hdrsize, size - offset - hdrsize, patch);
|
patchsize = parse_single_patch(buffer + offset + hdrsize, size - offset - hdrsize, patch);
|
||||||
|
|
||||||
if (!patchsize && !metadata_changes(patch)) {
|
if (!patchsize) {
|
||||||
static const char binhdr[] = "Binary files ";
|
static const char binhdr[] = "Binary files ";
|
||||||
|
|
||||||
if (sizeof(binhdr) - 1 < size - offset - hdrsize &&
|
if (sizeof(binhdr) - 1 < size - offset - hdrsize &&
|
||||||
@ -899,9 +900,14 @@ static int parse_chunk(char *buffer, unsigned long size, struct patch *patch)
|
|||||||
sizeof(binhdr)-1))
|
sizeof(binhdr)-1))
|
||||||
patch->is_binary = 1;
|
patch->is_binary = 1;
|
||||||
|
|
||||||
if (patch->is_binary && !apply && !check)
|
/* Empty patch cannot be applied if:
|
||||||
;
|
* - it is a binary patch and we do not do binary_replace, or
|
||||||
else
|
* - text patch without metadata change
|
||||||
|
*/
|
||||||
|
if ((apply || check) &&
|
||||||
|
(patch->is_binary
|
||||||
|
? !allow_binary_replacement
|
||||||
|
: !metadata_changes(patch)))
|
||||||
die("patch with only garbage at line %d", linenr);
|
die("patch with only garbage at line %d", linenr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1155,10 +1161,77 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag)
|
|||||||
static int apply_fragments(struct buffer_desc *desc, struct patch *patch)
|
static int apply_fragments(struct buffer_desc *desc, struct patch *patch)
|
||||||
{
|
{
|
||||||
struct fragment *frag = patch->fragments;
|
struct fragment *frag = patch->fragments;
|
||||||
|
const char *name = patch->old_name ? patch->old_name : patch->new_name;
|
||||||
|
|
||||||
|
if (patch->is_binary) {
|
||||||
|
unsigned char sha1[20];
|
||||||
|
|
||||||
|
if (!allow_binary_replacement)
|
||||||
|
return error("cannot apply binary patch to '%s' "
|
||||||
|
"without --allow-binary-replacement",
|
||||||
|
name);
|
||||||
|
|
||||||
|
/* For safety, we require patch index line to contain
|
||||||
|
* full 40-byte textual SHA1 for old and new, at least for now.
|
||||||
|
*/
|
||||||
|
if (strlen(patch->old_sha1_prefix) != 40 ||
|
||||||
|
strlen(patch->new_sha1_prefix) != 40 ||
|
||||||
|
get_sha1_hex(patch->old_sha1_prefix, sha1) ||
|
||||||
|
get_sha1_hex(patch->new_sha1_prefix, sha1))
|
||||||
|
return error("cannot apply binary patch to '%s' "
|
||||||
|
"without full index line", name);
|
||||||
|
|
||||||
|
if (patch->old_name) {
|
||||||
|
unsigned char hdr[50];
|
||||||
|
int hdrlen;
|
||||||
|
|
||||||
|
/* See if the old one matches what the patch
|
||||||
|
* applies to.
|
||||||
|
*/
|
||||||
|
write_sha1_file_prepare(desc->buffer, desc->size,
|
||||||
|
"blob", sha1, hdr, &hdrlen);
|
||||||
|
if (strcmp(sha1_to_hex(sha1), patch->old_sha1_prefix))
|
||||||
|
return error("the patch applies to '%s' (%s), "
|
||||||
|
"which does not match the "
|
||||||
|
"current contents.",
|
||||||
|
name, sha1_to_hex(sha1));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Otherwise, the old one must be empty. */
|
||||||
|
if (desc->size)
|
||||||
|
return error("the patch applies to an empty "
|
||||||
|
"'%s' but it is not empty", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For now, we do not record post-image data in the patch,
|
||||||
|
* and require the object already present in the recipient's
|
||||||
|
* object database.
|
||||||
|
*/
|
||||||
|
if (desc->buffer) {
|
||||||
|
free(desc->buffer);
|
||||||
|
desc->alloc = desc->size = 0;
|
||||||
|
}
|
||||||
|
get_sha1_hex(patch->new_sha1_prefix, sha1);
|
||||||
|
|
||||||
|
if (memcmp(sha1, null_sha1, 20)) {
|
||||||
|
char type[10];
|
||||||
|
unsigned long size;
|
||||||
|
|
||||||
|
desc->buffer = read_sha1_file(sha1, type, &size);
|
||||||
|
if (!desc->buffer)
|
||||||
|
return error("the necessary postimage %s for "
|
||||||
|
"'%s' does not exist",
|
||||||
|
patch->new_sha1_prefix, name);
|
||||||
|
desc->alloc = desc->size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
while (frag) {
|
while (frag) {
|
||||||
if (apply_one_fragment(desc, frag) < 0)
|
if (apply_one_fragment(desc, frag) < 0)
|
||||||
return error("patch failed: %s:%ld", patch->old_name, frag->oldpos);
|
return error("patch failed: %s:%ld",
|
||||||
|
name, frag->oldpos);
|
||||||
frag = frag->next;
|
frag = frag->next;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -1200,6 +1273,7 @@ static int check_patch(struct patch *patch)
|
|||||||
struct stat st;
|
struct stat st;
|
||||||
const char *old_name = patch->old_name;
|
const char *old_name = patch->old_name;
|
||||||
const char *new_name = patch->new_name;
|
const char *new_name = patch->new_name;
|
||||||
|
const char *name = old_name ? old_name : new_name;
|
||||||
|
|
||||||
if (old_name) {
|
if (old_name) {
|
||||||
int changed;
|
int changed;
|
||||||
@ -1274,7 +1348,7 @@ static int check_patch(struct patch *patch)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (apply_data(patch, &st) < 0)
|
if (apply_data(patch, &st) < 0)
|
||||||
return error("%s: patch does not apply", old_name);
|
return error("%s: patch does not apply", name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1723,6 +1797,10 @@ int main(int argc, char **argv)
|
|||||||
diffstat = 1;
|
diffstat = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!strcmp(arg, "--allow-binary-replacement")) {
|
||||||
|
allow_binary_replacement = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!strcmp(arg, "--numstat")) {
|
if (!strcmp(arg, "--numstat")) {
|
||||||
apply = 0;
|
apply = 0;
|
||||||
numstat = 1;
|
numstat = 1;
|
||||||
|
2
cache.h
2
cache.h
@ -179,6 +179,8 @@ extern int commit_index_file(struct cache_file *);
|
|||||||
extern void rollback_index_file(struct cache_file *);
|
extern void rollback_index_file(struct cache_file *);
|
||||||
|
|
||||||
extern int trust_executable_bit;
|
extern int trust_executable_bit;
|
||||||
|
extern int only_use_symrefs;
|
||||||
|
extern int diff_rename_limit_default;
|
||||||
|
|
||||||
#define MTIME_CHANGED 0x0001
|
#define MTIME_CHANGED 0x0001
|
||||||
#define CTIME_CHANGED 0x0002
|
#define CTIME_CHANGED 0x0002
|
||||||
|
19
commit.c
19
commit.c
@ -204,6 +204,7 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)
|
|||||||
unsigned char parent[20];
|
unsigned char parent[20];
|
||||||
struct commit_list **pptr;
|
struct commit_list **pptr;
|
||||||
struct commit_graft *graft;
|
struct commit_graft *graft;
|
||||||
|
unsigned n_refs = 0;
|
||||||
|
|
||||||
if (item->object.parsed)
|
if (item->object.parsed)
|
||||||
return 0;
|
return 0;
|
||||||
@ -214,7 +215,7 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)
|
|||||||
return error("bad tree pointer in commit %s\n", sha1_to_hex(item->object.sha1));
|
return error("bad tree pointer in commit %s\n", sha1_to_hex(item->object.sha1));
|
||||||
item->tree = lookup_tree(parent);
|
item->tree = lookup_tree(parent);
|
||||||
if (item->tree)
|
if (item->tree)
|
||||||
add_ref(&item->object, &item->tree->object);
|
n_refs++;
|
||||||
bufptr += 46; /* "tree " + "hex sha1" + "\n" */
|
bufptr += 46; /* "tree " + "hex sha1" + "\n" */
|
||||||
pptr = &item->parents;
|
pptr = &item->parents;
|
||||||
|
|
||||||
@ -230,7 +231,7 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)
|
|||||||
new_parent = lookup_commit(parent);
|
new_parent = lookup_commit(parent);
|
||||||
if (new_parent) {
|
if (new_parent) {
|
||||||
pptr = &commit_list_insert(new_parent, pptr)->next;
|
pptr = &commit_list_insert(new_parent, pptr)->next;
|
||||||
add_ref(&item->object, &new_parent->object);
|
n_refs++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (graft) {
|
if (graft) {
|
||||||
@ -241,10 +242,22 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)
|
|||||||
if (!new_parent)
|
if (!new_parent)
|
||||||
continue;
|
continue;
|
||||||
pptr = &commit_list_insert(new_parent, pptr)->next;
|
pptr = &commit_list_insert(new_parent, pptr)->next;
|
||||||
add_ref(&item->object, &new_parent->object);
|
n_refs++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
item->date = parse_commit_date(bufptr);
|
item->date = parse_commit_date(bufptr);
|
||||||
|
|
||||||
|
if (track_object_refs) {
|
||||||
|
unsigned i = 0;
|
||||||
|
struct commit_list *p;
|
||||||
|
struct object_refs *refs = alloc_object_refs(n_refs);
|
||||||
|
if (item->tree)
|
||||||
|
refs->ref[i++] = &item->tree->object;
|
||||||
|
for (p = item->parents; p; p = p->next)
|
||||||
|
refs->ref[i++] = &p->item->object;
|
||||||
|
set_object_refs(&item->object, refs);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
config.c
10
config.c
@ -214,6 +214,11 @@ int git_default_config(const char *var, const char *value)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!strcmp(var, "core.symrefsonly")) {
|
||||||
|
only_use_symrefs = git_config_bool(var, value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!strcmp(var, "user.name")) {
|
if (!strcmp(var, "user.name")) {
|
||||||
strncpy(git_default_name, value, sizeof(git_default_name));
|
strncpy(git_default_name, value, sizeof(git_default_name));
|
||||||
return 0;
|
return 0;
|
||||||
@ -224,6 +229,11 @@ int git_default_config(const char *var, const char *value)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!strcmp(var, "diff.renamelimit")) {
|
||||||
|
diff_rename_limit_default = git_config_int(var, value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Add other config variables here.. */
|
/* Add other config variables here.. */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
11
daemon.c
11
daemon.c
@ -594,6 +594,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
if (!strcmp(arg, "--inetd")) {
|
if (!strcmp(arg, "--inetd")) {
|
||||||
inetd_mode = 1;
|
inetd_mode = 1;
|
||||||
|
log_syslog = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp(arg, "--verbose")) {
|
if (!strcmp(arg, "--verbose")) {
|
||||||
@ -602,7 +603,6 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
if (!strcmp(arg, "--syslog")) {
|
if (!strcmp(arg, "--syslog")) {
|
||||||
log_syslog = 1;
|
log_syslog = 1;
|
||||||
openlog("git-daemon", 0, LOG_DAEMON);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp(arg, "--export-all")) {
|
if (!strcmp(arg, "--export-all")) {
|
||||||
@ -611,9 +611,11 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
if (!strncmp(arg, "--timeout=", 10)) {
|
if (!strncmp(arg, "--timeout=", 10)) {
|
||||||
timeout = atoi(arg+10);
|
timeout = atoi(arg+10);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
if (!strncmp(arg, "--init-timeout=", 15)) {
|
if (!strncmp(arg, "--init-timeout=", 15)) {
|
||||||
init_timeout = atoi(arg+15);
|
init_timeout = atoi(arg+15);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp(arg, "--")) {
|
if (!strcmp(arg, "--")) {
|
||||||
ok_paths = &argv[i+1];
|
ok_paths = &argv[i+1];
|
||||||
@ -626,10 +628,13 @@ int main(int argc, char **argv)
|
|||||||
usage(daemon_usage);
|
usage(daemon_usage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (log_syslog)
|
||||||
|
openlog("git-daemon", 0, LOG_DAEMON);
|
||||||
|
|
||||||
if (inetd_mode) {
|
if (inetd_mode) {
|
||||||
fclose(stderr); //FIXME: workaround
|
fclose(stderr); //FIXME: workaround
|
||||||
return execute();
|
return execute();
|
||||||
} else {
|
|
||||||
return serve(port);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return serve(port);
|
||||||
}
|
}
|
||||||
|
6
debian/changelog
vendored
6
debian/changelog
vendored
@ -1,3 +1,9 @@
|
|||||||
|
git-core (0.99.9j-0) unstable; urgency=low
|
||||||
|
|
||||||
|
* GIT 0.99.9j aka 1.0rc3
|
||||||
|
|
||||||
|
-- Junio C Hamano <junkio@cox.net> Wed, 16 Nov 2005 20:39:55 -0800
|
||||||
|
|
||||||
git-core (0.99.9i-0) unstable; urgency=low
|
git-core (0.99.9i-0) unstable; urgency=low
|
||||||
|
|
||||||
* GIT 0.99.9i aka 1.0rc2
|
* GIT 0.99.9i aka 1.0rc2
|
||||||
|
23
diff.c
23
diff.c
@ -13,6 +13,8 @@ static const char *diff_opts = "-pu";
|
|||||||
|
|
||||||
static int use_size_cache;
|
static int use_size_cache;
|
||||||
|
|
||||||
|
int diff_rename_limit_default = -1;
|
||||||
|
|
||||||
static char *quote_one(const char *str)
|
static char *quote_one(const char *str)
|
||||||
{
|
{
|
||||||
int needlen;
|
int needlen;
|
||||||
@ -648,7 +650,7 @@ static void diff_fill_sha1_info(struct diff_filespec *one)
|
|||||||
memset(one->sha1, 0, 20);
|
memset(one->sha1, 0, 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void run_diff(struct diff_filepair *p)
|
static void run_diff(struct diff_filepair *p, struct diff_options *o)
|
||||||
{
|
{
|
||||||
const char *pgm = external_diff();
|
const char *pgm = external_diff();
|
||||||
char msg[PATH_MAX*2+300], *xfrm_msg;
|
char msg[PATH_MAX*2+300], *xfrm_msg;
|
||||||
@ -711,11 +713,11 @@ static void run_diff(struct diff_filepair *p)
|
|||||||
|
|
||||||
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";
|
||||||
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 %.7s..%.7s", one_sha1,
|
index_fmt, one_sha1, sha1_to_hex(two->sha1));
|
||||||
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);
|
||||||
@ -761,9 +763,12 @@ void diff_setup(struct diff_options *options)
|
|||||||
|
|
||||||
int diff_setup_done(struct diff_options *options)
|
int diff_setup_done(struct diff_options *options)
|
||||||
{
|
{
|
||||||
if ((options->find_copies_harder || 0 <= options->rename_limit) &&
|
if ((options->find_copies_harder &&
|
||||||
options->detect_rename != DIFF_DETECT_COPY)
|
options->detect_rename != DIFF_DETECT_COPY) ||
|
||||||
|
(0 <= options->rename_limit && !options->detect_rename))
|
||||||
return -1;
|
return -1;
|
||||||
|
if (options->detect_rename && options->rename_limit < 0)
|
||||||
|
options->rename_limit = diff_rename_limit_default;
|
||||||
if (options->setup & DIFF_SETUP_USE_CACHE) {
|
if (options->setup & DIFF_SETUP_USE_CACHE) {
|
||||||
if (!active_cache)
|
if (!active_cache)
|
||||||
/* read-cache does not die even when it fails
|
/* read-cache does not die even when it fails
|
||||||
@ -789,6 +794,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
|
|||||||
options->line_termination = 0;
|
options->line_termination = 0;
|
||||||
else if (!strncmp(arg, "-l", 2))
|
else if (!strncmp(arg, "-l", 2))
|
||||||
options->rename_limit = strtoul(arg+2, NULL, 10);
|
options->rename_limit = strtoul(arg+2, NULL, 10);
|
||||||
|
else if (!strcmp(arg, "--full-index"))
|
||||||
|
options->full_index = 1;
|
||||||
else if (!strcmp(arg, "--name-only"))
|
else if (!strcmp(arg, "--name-only"))
|
||||||
options->output_format = DIFF_FORMAT_NAME;
|
options->output_format = DIFF_FORMAT_NAME;
|
||||||
else if (!strcmp(arg, "--name-status"))
|
else if (!strcmp(arg, "--name-status"))
|
||||||
@ -1017,7 +1024,7 @@ int diff_unmodified_pair(struct diff_filepair *p)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void diff_flush_patch(struct diff_filepair *p)
|
static void diff_flush_patch(struct diff_filepair *p, struct diff_options *o)
|
||||||
{
|
{
|
||||||
if (diff_unmodified_pair(p))
|
if (diff_unmodified_pair(p))
|
||||||
return;
|
return;
|
||||||
@ -1026,7 +1033,7 @@ static void diff_flush_patch(struct diff_filepair *p)
|
|||||||
(DIFF_FILE_VALID(p->two) && S_ISDIR(p->two->mode)))
|
(DIFF_FILE_VALID(p->two) && S_ISDIR(p->two->mode)))
|
||||||
return; /* no tree diffs in patch format */
|
return; /* no tree diffs in patch format */
|
||||||
|
|
||||||
run_diff(p);
|
run_diff(p, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
int diff_queue_is_empty(void)
|
int diff_queue_is_empty(void)
|
||||||
@ -1158,7 +1165,7 @@ void diff_flush(struct diff_options *options)
|
|||||||
die("internal error in diff-resolve-rename-copy");
|
die("internal error in diff-resolve-rename-copy");
|
||||||
switch (diff_output_format) {
|
switch (diff_output_format) {
|
||||||
case DIFF_FORMAT_PATCH:
|
case DIFF_FORMAT_PATCH:
|
||||||
diff_flush_patch(p);
|
diff_flush_patch(p, options);
|
||||||
break;
|
break;
|
||||||
case DIFF_FORMAT_RAW:
|
case DIFF_FORMAT_RAW:
|
||||||
case DIFF_FORMAT_NAME_STATUS:
|
case DIFF_FORMAT_NAME_STATUS:
|
||||||
|
4
diff.h
4
diff.h
@ -32,7 +32,8 @@ struct diff_options {
|
|||||||
const char *orderfile;
|
const char *orderfile;
|
||||||
const char *pickaxe;
|
const char *pickaxe;
|
||||||
unsigned recursive:1,
|
unsigned recursive:1,
|
||||||
tree_in_recursive:1;
|
tree_in_recursive:1,
|
||||||
|
full_index:1;
|
||||||
int break_opt;
|
int break_opt;
|
||||||
int detect_rename;
|
int detect_rename;
|
||||||
int find_copies_harder;
|
int find_copies_harder;
|
||||||
@ -96,6 +97,7 @@ 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" \
|
||||||
" -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" \
|
||||||
|
@ -283,7 +283,7 @@ void diffcore_rename(struct diff_options *options)
|
|||||||
register_rename_src(p->one, 1);
|
register_rename_src(p->one, 1);
|
||||||
}
|
}
|
||||||
if (rename_dst_nr == 0 ||
|
if (rename_dst_nr == 0 ||
|
||||||
(0 <= rename_limit && rename_limit < rename_dst_nr))
|
(0 < rename_limit && rename_limit < rename_dst_nr))
|
||||||
goto cleanup; /* nothing to do */
|
goto cleanup; /* nothing to do */
|
||||||
|
|
||||||
/* We really want to cull the candidates list early
|
/* We really want to cull the candidates list early
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
char git_default_email[MAX_GITNAME];
|
char git_default_email[MAX_GITNAME];
|
||||||
char git_default_name[MAX_GITNAME];
|
char git_default_name[MAX_GITNAME];
|
||||||
int trust_executable_bit = 1;
|
int trust_executable_bit = 1;
|
||||||
|
int only_use_symrefs = 0;
|
||||||
|
|
||||||
static char *git_dir, *git_object_dir, *git_index_file, *git_refs_dir,
|
static char *git_dir, *git_object_dir, *git_index_file, *git_refs_dir,
|
||||||
*git_graft_file;
|
*git_graft_file;
|
||||||
|
@ -56,7 +56,6 @@ static void check_connectivity(void)
|
|||||||
/* Look up all the requirements, warn about missing objects.. */
|
/* Look up all the requirements, warn about missing objects.. */
|
||||||
for (i = 0; i < nr_objs; i++) {
|
for (i = 0; i < nr_objs; i++) {
|
||||||
struct object *obj = objs[i];
|
struct object *obj = objs[i];
|
||||||
struct object_list *refs;
|
|
||||||
|
|
||||||
if (!obj->parsed) {
|
if (!obj->parsed) {
|
||||||
if (!standalone && has_sha1_file(obj->sha1))
|
if (!standalone && has_sha1_file(obj->sha1))
|
||||||
@ -67,14 +66,19 @@ static void check_connectivity(void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (refs = obj->refs; refs; refs = refs->next) {
|
if (obj->refs) {
|
||||||
if (refs->item->parsed ||
|
const struct object_refs *refs = obj->refs;
|
||||||
(!standalone && has_sha1_file(refs->item->sha1)))
|
unsigned j;
|
||||||
|
for (j = 0; j < refs->count; j++) {
|
||||||
|
struct object *ref = refs->ref[j];
|
||||||
|
if (ref->parsed ||
|
||||||
|
(!standalone && has_sha1_file(ref->sha1)))
|
||||||
continue;
|
continue;
|
||||||
printf("broken link from %7s %s\n",
|
printf("broken link from %7s %s\n",
|
||||||
obj->type, sha1_to_hex(obj->sha1));
|
obj->type, sha1_to_hex(obj->sha1));
|
||||||
printf(" to %7s %s\n",
|
printf(" to %7s %s\n",
|
||||||
refs->item->type, sha1_to_hex(refs->item->sha1));
|
ref->type, sha1_to_hex(ref->sha1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (show_unreachable && !(obj->flags & REACHABLE)) {
|
if (show_unreachable && !(obj->flags & REACHABLE)) {
|
||||||
@ -184,10 +188,17 @@ static int fsck_tree(struct tree *item)
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
free(last->name);
|
||||||
|
free(last);
|
||||||
}
|
}
|
||||||
|
|
||||||
last = entry;
|
last = entry;
|
||||||
}
|
}
|
||||||
|
if (last) {
|
||||||
|
free(last->name);
|
||||||
|
free(last);
|
||||||
|
}
|
||||||
|
item->entries = NULL;
|
||||||
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
if (has_full_path) {
|
if (has_full_path) {
|
||||||
|
63
git-am.sh
63
git-am.sh
@ -3,16 +3,10 @@
|
|||||||
#
|
#
|
||||||
. git-sh-setup || die "Not a git archive"
|
. git-sh-setup || die "Not a git archive"
|
||||||
|
|
||||||
files=$(git-diff-index --cached --name-only HEAD) || exit
|
|
||||||
if [ "$files" ]; then
|
|
||||||
echo "Dirty index: cannot apply patches (dirty: $files)" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
usage () {
|
usage () {
|
||||||
echo >&2 "usage: $0 [--signoff] [--dotest=<dir>] [--utf8] [--3way] <mbox>"
|
echo >&2 "usage: $0 [--signoff] [--dotest=<dir>] [--utf8] [--3way] <mbox>"
|
||||||
echo >&2 " or, when resuming"
|
echo >&2 " or, when resuming"
|
||||||
echo >&2 " $0 [--skip]"
|
echo >&2 " $0 [--skip | --resolved]"
|
||||||
exit 1;
|
exit 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +98,7 @@ fall_back_3way () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
prec=4
|
prec=4
|
||||||
dotest=.dotest sign= utf8= keep= skip= interactive=
|
dotest=.dotest sign= utf8= keep= skip= interactive= resolved=
|
||||||
|
|
||||||
while case "$#" in 0) break;; esac
|
while case "$#" in 0) break;; esac
|
||||||
do
|
do
|
||||||
@ -128,6 +122,9 @@ do
|
|||||||
-k|--k|--ke|--kee|--keep)
|
-k|--k|--ke|--kee|--keep)
|
||||||
keep=t; shift ;;
|
keep=t; shift ;;
|
||||||
|
|
||||||
|
-r|--r|--re|--res|--reso|--resol|--resolv|--resolve|--resolved)
|
||||||
|
resolved=t; shift ;;
|
||||||
|
|
||||||
--sk|--ski|--skip)
|
--sk|--ski|--skip)
|
||||||
skip=t; shift ;;
|
skip=t; shift ;;
|
||||||
|
|
||||||
@ -140,6 +137,8 @@ do
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# If the dotest directory exists, but we have finished applying all the
|
||||||
|
# patches in them, clear it out.
|
||||||
if test -d "$dotest" &&
|
if test -d "$dotest" &&
|
||||||
last=$(cat "$dotest/last") &&
|
last=$(cat "$dotest/last") &&
|
||||||
next=$(cat "$dotest/next") &&
|
next=$(cat "$dotest/next") &&
|
||||||
@ -155,8 +154,8 @@ then
|
|||||||
die "previous dotest directory $dotest still exists but mbox given."
|
die "previous dotest directory $dotest still exists but mbox given."
|
||||||
resume=yes
|
resume=yes
|
||||||
else
|
else
|
||||||
# Make sure we are not given --skip
|
# Make sure we are not given --skip nor --resolved
|
||||||
test ",$skip," = ,, ||
|
test ",$skip,$resolved," = ,,, ||
|
||||||
die "we are not resuming."
|
die "we are not resuming."
|
||||||
|
|
||||||
# Start afresh.
|
# Start afresh.
|
||||||
@ -170,12 +169,24 @@ else
|
|||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# -s, -u and -k flags are kept for the resuming session after
|
||||||
|
# a patch failure.
|
||||||
|
# -3 and -i can and must be given when resuming.
|
||||||
echo "$sign" >"$dotest/sign"
|
echo "$sign" >"$dotest/sign"
|
||||||
echo "$utf8" >"$dotest/utf8"
|
echo "$utf8" >"$dotest/utf8"
|
||||||
echo "$keep" >"$dotest/keep"
|
echo "$keep" >"$dotest/keep"
|
||||||
echo 1 >"$dotest/next"
|
echo 1 >"$dotest/next"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
case "$resolved" in
|
||||||
|
'')
|
||||||
|
files=$(git-diff-index --cached --name-only HEAD) || exit
|
||||||
|
if [ "$files" ]; then
|
||||||
|
echo "Dirty index: cannot apply patches (dirty: $files)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
esac
|
||||||
|
|
||||||
if test "$(cat "$dotest/utf8")" = t
|
if test "$(cat "$dotest/utf8")" = t
|
||||||
then
|
then
|
||||||
utf8=-u
|
utf8=-u
|
||||||
@ -216,6 +227,15 @@ do
|
|||||||
go_next
|
go_next
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# If we are not resuming, parse and extract the patch information
|
||||||
|
# into separate files:
|
||||||
|
# - info records the authorship and title
|
||||||
|
# - msg is the rest of commit log message
|
||||||
|
# - patch is the patch body.
|
||||||
|
#
|
||||||
|
# When we are resuming, these files are either already prepared
|
||||||
|
# by the user, or the user can tell us to do so by --resolved flag.
|
||||||
case "$resume" in
|
case "$resume" in
|
||||||
'')
|
'')
|
||||||
git-mailinfo $keep $utf8 "$dotest/msg" "$dotest/patch" \
|
git-mailinfo $keep $utf8 "$dotest/msg" "$dotest/patch" \
|
||||||
@ -263,6 +283,13 @@ do
|
|||||||
fi
|
fi
|
||||||
} >"$dotest/final-commit"
|
} >"$dotest/final-commit"
|
||||||
;;
|
;;
|
||||||
|
*)
|
||||||
|
case "$resolved,$interactive" in
|
||||||
|
tt)
|
||||||
|
# This is used only for interactive view option.
|
||||||
|
git-diff-index -p --cached HEAD >"$dotest/patch"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
esac
|
esac
|
||||||
|
|
||||||
resume=
|
resume=
|
||||||
@ -310,7 +337,21 @@ do
|
|||||||
echo "Applying '$SUBJECT'"
|
echo "Applying '$SUBJECT'"
|
||||||
echo
|
echo
|
||||||
|
|
||||||
git-apply --index "$dotest/patch"; apply_status=$?
|
case "$resolved" in
|
||||||
|
'')
|
||||||
|
git-apply --index "$dotest/patch"
|
||||||
|
apply_status=$?
|
||||||
|
;;
|
||||||
|
t)
|
||||||
|
# Resolved means the user did all the hard work, and
|
||||||
|
# we do not have to do any patch application. Just
|
||||||
|
# trust what the user has in the index file and the
|
||||||
|
# working tree.
|
||||||
|
resolved=
|
||||||
|
apply_status=0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
if test $apply_status = 1 && test "$threeway" = t
|
if test $apply_status = 1 && test "$threeway" = t
|
||||||
then
|
then
|
||||||
if (fall_back_3way)
|
if (fall_back_3way)
|
||||||
|
@ -410,8 +410,7 @@ foreach my $ps (@psets) {
|
|||||||
open HEAD, ">$git_dir/refs/heads/$ps->{branch}";
|
open HEAD, ">$git_dir/refs/heads/$ps->{branch}";
|
||||||
print HEAD $commitid;
|
print HEAD $commitid;
|
||||||
close HEAD;
|
close HEAD;
|
||||||
unlink ("$git_dir/HEAD");
|
system('git-update-ref', 'HEAD', "$ps->{branch}");
|
||||||
symlink("refs/heads/$ps->{branch}","$git_dir/HEAD");
|
|
||||||
|
|
||||||
# tag accordingly
|
# tag accordingly
|
||||||
ptag($ps->{id}, $commitid); # private tag
|
ptag($ps->{id}, $commitid); # private tag
|
||||||
|
@ -4,6 +4,7 @@ use strict;
|
|||||||
use Getopt::Std;
|
use Getopt::Std;
|
||||||
use File::Temp qw(tempdir);
|
use File::Temp qw(tempdir);
|
||||||
use Data::Dumper;
|
use Data::Dumper;
|
||||||
|
use File::Basename qw(basename);
|
||||||
|
|
||||||
unless ($ENV{GIT_DIR} && -r $ENV{GIT_DIR}){
|
unless ($ENV{GIT_DIR} && -r $ENV{GIT_DIR}){
|
||||||
die "GIT_DIR is not defined or is unreadable";
|
die "GIT_DIR is not defined or is unreadable";
|
||||||
@ -11,7 +12,7 @@ unless ($ENV{GIT_DIR} && -r $ENV{GIT_DIR}){
|
|||||||
|
|
||||||
our ($opt_h, $opt_p, $opt_v, $opt_c );
|
our ($opt_h, $opt_p, $opt_v, $opt_c );
|
||||||
|
|
||||||
getopt('hpvc');
|
getopts('hpvc');
|
||||||
|
|
||||||
$opt_h && usage();
|
$opt_h && usage();
|
||||||
|
|
||||||
@ -77,7 +78,7 @@ $opt_v && print "Applying to CVS commit $commit from parent $parent\n";
|
|||||||
|
|
||||||
# grab the commit message
|
# grab the commit message
|
||||||
`git-cat-file commit $commit | sed -e '1,/^\$/d' > .msg`;
|
`git-cat-file commit $commit | sed -e '1,/^\$/d' > .msg`;
|
||||||
$? && die "Error extraction the commit message";
|
$? && die "Error extracting the commit message";
|
||||||
|
|
||||||
my (@afiles, @dfiles, @mfiles);
|
my (@afiles, @dfiles, @mfiles);
|
||||||
my @files = `git-diff-tree -r $parent $commit`;
|
my @files = `git-diff-tree -r $parent $commit`;
|
||||||
@ -187,9 +188,9 @@ my $cmd = "cvs commit -F .msg $commitfiles";
|
|||||||
|
|
||||||
if ($dirtypatch) {
|
if ($dirtypatch) {
|
||||||
print "NOTE: One or more hunks failed to apply cleanly.\n";
|
print "NOTE: One or more hunks failed to apply cleanly.\n";
|
||||||
print "Resolve the conflicts and then commit using:n";
|
print "Resolve the conflicts and then commit using:\n";
|
||||||
print "\n $cmd\n\n";
|
print "\n $cmd\n\n";
|
||||||
exit;
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -206,8 +207,7 @@ if ($opt_c) {
|
|||||||
}
|
}
|
||||||
sub usage {
|
sub usage {
|
||||||
print STDERR <<END;
|
print STDERR <<END;
|
||||||
Usage: GIT_DIR=/path/to/.gi ${\basename $0} # fetch/update GIT from CVS
|
Usage: GIT_DIR=/path/to/.git ${\basename $0} [-h] [-p] [-v] [-c] [ parent ] commit
|
||||||
[-h] [-p] [ parent ] commit
|
|
||||||
END
|
END
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -437,7 +437,11 @@ unless(-d $git_dir) {
|
|||||||
"Either use the correct '-o branch' option,\n".
|
"Either use the correct '-o branch' option,\n".
|
||||||
"or import to a new repository.\n";
|
"or import to a new repository.\n";
|
||||||
|
|
||||||
$last_branch = basename(readlink("$git_dir/HEAD"));
|
open(F, "git-symbolic-ref HEAD |") or
|
||||||
|
die "Cannot run git-symbolic-ref: $!\n";
|
||||||
|
chomp ($last_branch = <F>);
|
||||||
|
$last_branch = basename($last_branch);
|
||||||
|
close(F);
|
||||||
unless($last_branch) {
|
unless($last_branch) {
|
||||||
warn "Cannot read the last branch name: $! -- assuming 'master'\n";
|
warn "Cannot read the last branch name: $! -- assuming 'master'\n";
|
||||||
$last_branch = "master";
|
$last_branch = "master";
|
||||||
@ -829,8 +833,7 @@ if($orig_branch) {
|
|||||||
print "DONE; creating $orig_branch branch\n" if $opt_v;
|
print "DONE; creating $orig_branch branch\n" if $opt_v;
|
||||||
system("cp","$git_dir/refs/heads/$opt_o","$git_dir/refs/heads/master")
|
system("cp","$git_dir/refs/heads/$opt_o","$git_dir/refs/heads/master")
|
||||||
unless -f "$git_dir/refs/heads/master";
|
unless -f "$git_dir/refs/heads/master";
|
||||||
unlink("$git_dir/HEAD");
|
system('git-update-ref', 'HEAD', "$orig_branch");
|
||||||
symlink("refs/heads/$orig_branch","$git_dir/HEAD");
|
|
||||||
unless ($opt_i) {
|
unless ($opt_i) {
|
||||||
system('git checkout');
|
system('git checkout');
|
||||||
die "checkout failed: $?\n" if $?;
|
die "checkout failed: $?\n" if $?;
|
||||||
|
@ -39,5 +39,9 @@ while : ; do
|
|||||||
esac
|
esac
|
||||||
shift
|
shift
|
||||||
done
|
done
|
||||||
|
[ "$pattern" ] || {
|
||||||
|
echo >&2 "usage: 'git grep <pattern> [pathspec*]'"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
git-ls-files -z "${git_flags[@]}" "$@" |
|
git-ls-files -z "${git_flags[@]}" "$@" |
|
||||||
xargs -0 grep "${flags[@]}" -e "$pattern"
|
xargs -0 grep "${flags[@]}" -e "$pattern"
|
||||||
|
@ -3,11 +3,13 @@
|
|||||||
# Copyright (C) 2005 Fredrik Kuivinen
|
# Copyright (C) 2005 Fredrik Kuivinen
|
||||||
#
|
#
|
||||||
|
|
||||||
import sys, math, random, os, re, signal, tempfile, stat, errno, traceback
|
import sys
|
||||||
|
sys.path.append('''@@GIT_PYTHON_PATH@@''')
|
||||||
|
|
||||||
|
import math, random, os, re, signal, tempfile, stat, errno, traceback
|
||||||
from heapq import heappush, heappop
|
from heapq import heappush, heappop
|
||||||
from sets import Set
|
from sets import Set
|
||||||
|
|
||||||
sys.path.append('''@@GIT_PYTHON_PATH@@''')
|
|
||||||
from gitMergeCommon import *
|
from gitMergeCommon import *
|
||||||
|
|
||||||
outputIndent = 0
|
outputIndent = 0
|
||||||
|
@ -216,7 +216,11 @@ unless(-d $git_dir) {
|
|||||||
-f "$git_dir/svn2git"
|
-f "$git_dir/svn2git"
|
||||||
or die "'$git_dir/svn2git' does not exist.\n".
|
or die "'$git_dir/svn2git' does not exist.\n".
|
||||||
"You need that file for incremental imports.\n";
|
"You need that file for incremental imports.\n";
|
||||||
$last_branch = basename(readlink("$git_dir/HEAD"));
|
open(F, "git-symbolic-ref HEAD |") or
|
||||||
|
die "Cannot run git-symbolic-ref: $!\n";
|
||||||
|
chomp ($last_branch = <F>);
|
||||||
|
$last_branch = basename($last_branch);
|
||||||
|
close(F);
|
||||||
unless($last_branch) {
|
unless($last_branch) {
|
||||||
warn "Cannot read the last branch name: $! -- assuming 'master'\n";
|
warn "Cannot read the last branch name: $! -- assuming 'master'\n";
|
||||||
$last_branch = "master";
|
$last_branch = "master";
|
||||||
@ -766,8 +770,7 @@ if($orig_branch) {
|
|||||||
print "DONE; creating $orig_branch branch\n" if $opt_v and (not defined $opt_l or $opt_l > 0);
|
print "DONE; creating $orig_branch branch\n" if $opt_v and (not defined $opt_l or $opt_l > 0);
|
||||||
system("cp","$git_dir/refs/heads/$opt_o","$git_dir/refs/heads/master")
|
system("cp","$git_dir/refs/heads/$opt_o","$git_dir/refs/heads/master")
|
||||||
unless -f "$git_dir/refs/heads/master";
|
unless -f "$git_dir/refs/heads/master";
|
||||||
unlink("$git_dir/HEAD");
|
system('git-update-ref', 'HEAD', "$orig_branch");
|
||||||
symlink("refs/heads/$orig_branch","$git_dir/HEAD");
|
|
||||||
unless ($opt_i) {
|
unless ($opt_i) {
|
||||||
system('git checkout');
|
system('git checkout');
|
||||||
die "checkout failed: $?\n" if $?;
|
die "checkout failed: $?\n" if $?;
|
||||||
|
295
git.c
Normal file
295
git.c
Normal file
@ -0,0 +1,295 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#ifndef PATH_MAX
|
||||||
|
# define PATH_MAX 4096
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const char git_usage[] =
|
||||||
|
"Usage: git [--version] [--exec-path[=GIT_EXEC_PATH]] [--help] COMMAND [ ARGS ]";
|
||||||
|
|
||||||
|
/* most gui terms set COLUMNS (although some don't export it) */
|
||||||
|
static int term_columns(void)
|
||||||
|
{
|
||||||
|
char *col_string = getenv("COLUMNS");
|
||||||
|
int n_cols = 0;
|
||||||
|
|
||||||
|
if (col_string && (n_cols = atoi(col_string)) > 0)
|
||||||
|
return n_cols;
|
||||||
|
|
||||||
|
return 80;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void oom(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "git: out of memory\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void mput_char(char c, unsigned int num)
|
||||||
|
{
|
||||||
|
while(num--)
|
||||||
|
putchar(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct cmdname {
|
||||||
|
size_t len;
|
||||||
|
char name[1];
|
||||||
|
} **cmdname;
|
||||||
|
static int cmdname_alloc, cmdname_cnt;
|
||||||
|
|
||||||
|
static void add_cmdname(const char *name, int len)
|
||||||
|
{
|
||||||
|
struct cmdname *ent;
|
||||||
|
if (cmdname_alloc <= cmdname_cnt) {
|
||||||
|
cmdname_alloc = cmdname_alloc + 200;
|
||||||
|
cmdname = realloc(cmdname, cmdname_alloc * sizeof(*cmdname));
|
||||||
|
if (!cmdname)
|
||||||
|
oom();
|
||||||
|
}
|
||||||
|
ent = malloc(sizeof(*ent) + len);
|
||||||
|
if (!ent)
|
||||||
|
oom();
|
||||||
|
ent->len = len;
|
||||||
|
memcpy(ent->name, name, len+1);
|
||||||
|
cmdname[cmdname_cnt++] = ent;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmdname_compare(const void *a_, const void *b_)
|
||||||
|
{
|
||||||
|
struct cmdname *a = *(struct cmdname **)a_;
|
||||||
|
struct cmdname *b = *(struct cmdname **)b_;
|
||||||
|
return strcmp(a->name, b->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pretty_print_string_list(struct cmdname **cmdname, int longest)
|
||||||
|
{
|
||||||
|
int cols = 1;
|
||||||
|
int space = longest + 1; /* min 1 SP between words */
|
||||||
|
int max_cols = term_columns() - 1; /* don't print *on* the edge */
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (space < max_cols)
|
||||||
|
cols = max_cols / space;
|
||||||
|
|
||||||
|
qsort(cmdname, cmdname_cnt, sizeof(*cmdname), cmdname_compare);
|
||||||
|
|
||||||
|
for (i = 0; i < cmdname_cnt; ) {
|
||||||
|
int c;
|
||||||
|
printf(" ");
|
||||||
|
|
||||||
|
for (c = cols; c && i < cmdname_cnt; i++) {
|
||||||
|
printf("%s", cmdname[i]->name);
|
||||||
|
|
||||||
|
if (--c)
|
||||||
|
mput_char(' ', space - cmdname[i]->len);
|
||||||
|
}
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void list_commands(const char *exec_path, const char *pattern)
|
||||||
|
{
|
||||||
|
unsigned int longest = 0;
|
||||||
|
char path[PATH_MAX];
|
||||||
|
int dirlen;
|
||||||
|
DIR *dir = opendir(exec_path);
|
||||||
|
struct dirent *de;
|
||||||
|
|
||||||
|
if (!dir) {
|
||||||
|
fprintf(stderr, "git: '%s': %s\n", exec_path, strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
dirlen = strlen(exec_path);
|
||||||
|
if (PATH_MAX - 20 < dirlen) {
|
||||||
|
fprintf(stderr, "git: insanely long exec-path '%s'\n",
|
||||||
|
exec_path);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(path, exec_path, dirlen);
|
||||||
|
path[dirlen++] = '/';
|
||||||
|
|
||||||
|
while ((de = readdir(dir)) != NULL) {
|
||||||
|
struct stat st;
|
||||||
|
int entlen;
|
||||||
|
|
||||||
|
if (strncmp(de->d_name, "git-", 4))
|
||||||
|
continue;
|
||||||
|
strcpy(path+dirlen, de->d_name);
|
||||||
|
if (stat(path, &st) || /* stat, not lstat */
|
||||||
|
!S_ISREG(st.st_mode) ||
|
||||||
|
!(st.st_mode & S_IXUSR))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
entlen = strlen(de->d_name);
|
||||||
|
|
||||||
|
if (longest < entlen)
|
||||||
|
longest = entlen;
|
||||||
|
|
||||||
|
add_cmdname(de->d_name + 4, entlen-4);
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
|
||||||
|
printf("git commands available in '%s'\n", exec_path);
|
||||||
|
printf("----------------------------");
|
||||||
|
mput_char('-', strlen(exec_path));
|
||||||
|
putchar('\n');
|
||||||
|
pretty_print_string_list(cmdname, longest - 4);
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
static void usage(const char *exec_path, const char *fmt, ...)
|
||||||
|
__attribute__((__format__(__printf__, 2, 3), __noreturn__));
|
||||||
|
#endif
|
||||||
|
static void usage(const char *exec_path, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
if (fmt) {
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
printf("git: ");
|
||||||
|
vprintf(fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
puts(git_usage);
|
||||||
|
|
||||||
|
putchar('\n');
|
||||||
|
|
||||||
|
if(exec_path)
|
||||||
|
list_commands(exec_path, "git-*");
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void prepend_to_path(const char *dir, int len)
|
||||||
|
{
|
||||||
|
char *path, *old_path = getenv("PATH");
|
||||||
|
int path_len = len;
|
||||||
|
|
||||||
|
if (!old_path)
|
||||||
|
old_path = "/usr/local/bin:/usr/bin:/bin";
|
||||||
|
|
||||||
|
path_len = len + strlen(old_path) + 1;
|
||||||
|
|
||||||
|
path = malloc(path_len + 1);
|
||||||
|
path[path_len + 1] = '\0';
|
||||||
|
|
||||||
|
memcpy(path, dir, len);
|
||||||
|
path[len] = ':';
|
||||||
|
memcpy(path + len + 1, old_path, path_len - len);
|
||||||
|
|
||||||
|
setenv("PATH", path, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void show_man_page(char *git_cmd)
|
||||||
|
{
|
||||||
|
char *page;
|
||||||
|
|
||||||
|
if (!strncmp(git_cmd, "git", 3))
|
||||||
|
page = git_cmd;
|
||||||
|
else {
|
||||||
|
int page_len = strlen(git_cmd) + 4;
|
||||||
|
|
||||||
|
page = malloc(page_len + 1);
|
||||||
|
strcpy(page, "git-");
|
||||||
|
strcpy(page + 4, git_cmd);
|
||||||
|
page[page_len] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
execlp("man", "man", page, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv, char **envp)
|
||||||
|
{
|
||||||
|
char git_command[PATH_MAX + 1];
|
||||||
|
char wd[PATH_MAX + 1];
|
||||||
|
int i, len, show_help = 0;
|
||||||
|
char *exec_path = getenv("GIT_EXEC_PATH");
|
||||||
|
|
||||||
|
getcwd(wd, PATH_MAX);
|
||||||
|
|
||||||
|
if (!exec_path)
|
||||||
|
exec_path = GIT_EXEC_PATH;
|
||||||
|
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
char *arg = argv[i];
|
||||||
|
|
||||||
|
if (strncmp(arg, "--", 2))
|
||||||
|
break;
|
||||||
|
|
||||||
|
arg += 2;
|
||||||
|
|
||||||
|
if (!strncmp(arg, "exec-path", 9)) {
|
||||||
|
arg += 9;
|
||||||
|
if (*arg == '=')
|
||||||
|
exec_path = arg + 1;
|
||||||
|
else {
|
||||||
|
puts(exec_path);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!strcmp(arg, "version")) {
|
||||||
|
printf("git version %s\n", GIT_VERSION);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
else if (!strcmp(arg, "help"))
|
||||||
|
show_help = 1;
|
||||||
|
else if (!show_help)
|
||||||
|
usage(NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i >= argc || show_help) {
|
||||||
|
if (i >= argc)
|
||||||
|
usage(exec_path, NULL);
|
||||||
|
|
||||||
|
show_man_page(argv[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*exec_path != '/') {
|
||||||
|
if (!getcwd(git_command, sizeof(git_command))) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"git: cannot determine current directory");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
len = strlen(git_command);
|
||||||
|
|
||||||
|
/* Trivial cleanup */
|
||||||
|
while (!strncmp(exec_path, "./", 2)) {
|
||||||
|
exec_path += 2;
|
||||||
|
while (*exec_path == '/')
|
||||||
|
*exec_path++;
|
||||||
|
}
|
||||||
|
snprintf(git_command + len, sizeof(git_command) - len,
|
||||||
|
"/%s", exec_path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
strcpy(git_command, exec_path);
|
||||||
|
len = strlen(git_command);
|
||||||
|
prepend_to_path(git_command, len);
|
||||||
|
|
||||||
|
strncat(&git_command[len], "/git-", sizeof(git_command) - len);
|
||||||
|
len += 5;
|
||||||
|
strncat(&git_command[len], argv[i], sizeof(git_command) - len);
|
||||||
|
|
||||||
|
if (access(git_command, X_OK))
|
||||||
|
usage(exec_path, "'%s' is not a git-command", argv[i]);
|
||||||
|
|
||||||
|
/* execve() can only ever return if it fails */
|
||||||
|
execve(git_command, &argv[i], envp);
|
||||||
|
printf("Failed to run command '%s': %s\n", git_command, strerror(errno));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
76
git.sh
76
git.sh
@ -1,76 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
cmd=
|
|
||||||
path=$(dirname "$0")
|
|
||||||
case "$#" in
|
|
||||||
0) ;;
|
|
||||||
*) cmd="$1"
|
|
||||||
shift
|
|
||||||
case "$cmd" in
|
|
||||||
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
|
||||||
echo "git version @@GIT_VERSION@@"
|
|
||||||
exit 0 ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
test -x "$path/git-$cmd" && exec "$path/git-$cmd" "$@"
|
|
||||||
|
|
||||||
case '@@X@@' in
|
|
||||||
'')
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
test -x "$path/git-$cmd@@X@@" &&
|
|
||||||
exec "$path/git-$cmd@@X@@" "$@"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
echo "Usage: git COMMAND [OPTIONS] [TARGET]"
|
|
||||||
if [ -n "$cmd" ]; then
|
|
||||||
echo "git command '$cmd' not found."
|
|
||||||
fi
|
|
||||||
echo "git commands are:"
|
|
||||||
|
|
||||||
fmt <<\EOF | sed -e 's/^/ /'
|
|
||||||
add
|
|
||||||
apply
|
|
||||||
archimport
|
|
||||||
bisect
|
|
||||||
branch
|
|
||||||
checkout
|
|
||||||
cherry
|
|
||||||
clone
|
|
||||||
commit
|
|
||||||
count-objects
|
|
||||||
cvsimport
|
|
||||||
diff
|
|
||||||
fetch
|
|
||||||
format-patch
|
|
||||||
fsck-objects
|
|
||||||
get-tar-commit-id
|
|
||||||
init-db
|
|
||||||
log
|
|
||||||
ls-remote
|
|
||||||
octopus
|
|
||||||
pack-objects
|
|
||||||
parse-remote
|
|
||||||
patch-id
|
|
||||||
prune
|
|
||||||
pull
|
|
||||||
push
|
|
||||||
rebase
|
|
||||||
relink
|
|
||||||
rename
|
|
||||||
repack
|
|
||||||
request-pull
|
|
||||||
reset
|
|
||||||
resolve
|
|
||||||
revert
|
|
||||||
send-email
|
|
||||||
shortlog
|
|
||||||
show-branch
|
|
||||||
status
|
|
||||||
tag
|
|
||||||
verify-tag
|
|
||||||
whatchanged
|
|
||||||
EOF
|
|
@ -1,5 +1,5 @@
|
|||||||
# Pass --without docs to rpmbuild if you don't want the documentation
|
# Pass --without docs to rpmbuild if you don't want the documentation
|
||||||
Name: git-core
|
Name: git
|
||||||
Version: @@VERSION@@
|
Version: @@VERSION@@
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: Git core and tools
|
Summary: Git core and tools
|
||||||
@ -9,7 +9,7 @@ URL: http://kernel.org/pub/software/scm/git/
|
|||||||
Source: http://kernel.org/pub/software/scm/git/%{name}-%{version}.tar.gz
|
Source: http://kernel.org/pub/software/scm/git/%{name}-%{version}.tar.gz
|
||||||
BuildRequires: zlib-devel >= 1.2, openssl-devel, curl-devel, expat-devel %{!?_without_docs:, xmlto, asciidoc > 6.0.3}
|
BuildRequires: zlib-devel >= 1.2, openssl-devel, curl-devel, expat-devel %{!?_without_docs:, xmlto, asciidoc > 6.0.3}
|
||||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||||
Requires: zlib >= 1.2, rsync, rcs, curl, less, openssh-clients, python >= 2.3, expat
|
Requires: git-core, git-svn, git-cvs, git-arch, git-email, gitk
|
||||||
|
|
||||||
%description
|
%description
|
||||||
This is a stupid (but extremely fast) directory content manager. It
|
This is a stupid (but extremely fast) directory content manager. It
|
||||||
@ -19,6 +19,22 @@ distributed source code management system. This package includes
|
|||||||
rudimentary tools that can be used as a SCM, but you should look
|
rudimentary tools that can be used as a SCM, but you should look
|
||||||
elsewhere for tools for ordinary humans layered on top of this.
|
elsewhere for tools for ordinary humans layered on top of this.
|
||||||
|
|
||||||
|
This is a dummy package which brings in all subpackages.
|
||||||
|
|
||||||
|
%package core
|
||||||
|
Summary: Core git tools
|
||||||
|
Group: Development/Tools
|
||||||
|
Requires: zlib >= 1.2, rsync, rcs, curl, less, openssh-clients, python >= 2.3, expat
|
||||||
|
%description core
|
||||||
|
This is a stupid (but extremely fast) directory content manager. It
|
||||||
|
doesn't do a whole lot, but what it _does_ do is track directory
|
||||||
|
contents efficiently. It is intended to be the base of an efficient,
|
||||||
|
distributed source code management system. This package includes
|
||||||
|
rudimentary tools that can be used as a SCM, but you should look
|
||||||
|
elsewhere for tools for ordinary humans layered on top of this.
|
||||||
|
|
||||||
|
These are the core tools with minimal dependencies.
|
||||||
|
|
||||||
%package svn
|
%package svn
|
||||||
Summary: Git tools for importing Subversion repositories
|
Summary: Git tools for importing Subversion repositories
|
||||||
Group: Development/Tools
|
Group: Development/Tools
|
||||||
@ -47,11 +63,11 @@ Requires: git-core = %{version}-%{release}
|
|||||||
%description email
|
%description email
|
||||||
Git tools for sending email.
|
Git tools for sending email.
|
||||||
|
|
||||||
%package tk
|
%package -n gitk
|
||||||
Summary: Git revision tree visualiser ('gitk')
|
Summary: Git revision tree visualiser ('gitk')
|
||||||
Group: Development/Tools
|
Group: Development/Tools
|
||||||
Requires: git-core = %{version}-%{release}, tk >= 8.4
|
Requires: git-core = %{version}-%{release}, tk >= 8.4
|
||||||
%description tk
|
%description -n gitk
|
||||||
Git revision tree visualiser ('gitk')
|
Git revision tree visualiser ('gitk')
|
||||||
|
|
||||||
%prep
|
%prep
|
||||||
@ -75,6 +91,9 @@ make %{_smp_mflags} DESTDIR=$RPM_BUILD_ROOT WITH_OWN_SUBPROCESS_PY=YesPlease WIT
|
|||||||
%clean
|
%clean
|
||||||
rm -rf $RPM_BUILD_ROOT
|
rm -rf $RPM_BUILD_ROOT
|
||||||
|
|
||||||
|
%files
|
||||||
|
# These are no files in the root package
|
||||||
|
|
||||||
%files svn
|
%files svn
|
||||||
%defattr(-,root,root)
|
%defattr(-,root,root)
|
||||||
%{_bindir}/*svn*
|
%{_bindir}/*svn*
|
||||||
@ -103,20 +122,25 @@ rm -rf $RPM_BUILD_ROOT
|
|||||||
%{!?_without_docs: %{_mandir}/man1/*email*.1*}
|
%{!?_without_docs: %{_mandir}/man1/*email*.1*}
|
||||||
%{!?_without_docs: %doc Documentation/*email*.html }
|
%{!?_without_docs: %doc Documentation/*email*.html }
|
||||||
|
|
||||||
%files tk
|
%files -n gitk
|
||||||
%defattr(-,root,root)
|
%defattr(-,root,root)
|
||||||
%doc Documentation/*gitk*.txt
|
%doc Documentation/*gitk*.txt
|
||||||
%{_bindir}/*gitk*
|
%{_bindir}/*gitk*
|
||||||
%{!?_without_docs: %{_mandir}/man1/*gitk*.1*}
|
%{!?_without_docs: %{_mandir}/man1/*gitk*.1*}
|
||||||
%{!?_without_docs: %doc Documentation/*gitk*.html }
|
%{!?_without_docs: %doc Documentation/*gitk*.html }
|
||||||
|
|
||||||
%files -f bin-man-doc-files
|
%files core -f bin-man-doc-files
|
||||||
%defattr(-,root,root)
|
%defattr(-,root,root)
|
||||||
%{_datadir}/git-core/
|
%{_datadir}/git-core/
|
||||||
%doc README COPYING Documentation/*.txt
|
%doc README COPYING Documentation/*.txt
|
||||||
%{!?_without_docs: %doc Documentation/*.html }
|
%{!?_without_docs: %doc Documentation/*.html }
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Mon Nov 14 2005 H. Peter Anvin <hpa@zytor.com> 0.99.9j-1
|
||||||
|
- Change subpackage names to git-<name> instead of git-core-<name>
|
||||||
|
- Create empty root package which brings in all subpackages
|
||||||
|
- Rename git-tk -> gitk
|
||||||
|
|
||||||
* Thu Nov 10 2005 Chris Wright <chrisw@osdl.org> 0.99.9g-1
|
* Thu Nov 10 2005 Chris Wright <chrisw@osdl.org> 0.99.9g-1
|
||||||
- zlib dependency fix
|
- zlib dependency fix
|
||||||
- Minor cleanups from split
|
- Minor cleanups from split
|
16
http-fetch.c
16
http-fetch.c
@ -425,6 +425,8 @@ static void start_request(struct transfer_request *request)
|
|||||||
rename(request->tmpfile, prevfile);
|
rename(request->tmpfile, prevfile);
|
||||||
unlink(request->tmpfile);
|
unlink(request->tmpfile);
|
||||||
|
|
||||||
|
if (request->local != -1)
|
||||||
|
error("fd leakage in start: %d", request->local);
|
||||||
request->local = open(request->tmpfile,
|
request->local = open(request->tmpfile,
|
||||||
O_WRONLY | O_CREAT | O_EXCL, 0666);
|
O_WRONLY | O_CREAT | O_EXCL, 0666);
|
||||||
/* This could have failed due to the "lazy directory creation";
|
/* This could have failed due to the "lazy directory creation";
|
||||||
@ -523,7 +525,7 @@ static void start_request(struct transfer_request *request)
|
|||||||
/* Try to get the request started, abort the request on error */
|
/* Try to get the request started, abort the request on error */
|
||||||
if (!start_active_slot(slot)) {
|
if (!start_active_slot(slot)) {
|
||||||
request->state = ABORTED;
|
request->state = ABORTED;
|
||||||
close(request->local);
|
close(request->local); request->local = -1;
|
||||||
free(request->url);
|
free(request->url);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -537,7 +539,7 @@ static void finish_request(struct transfer_request *request)
|
|||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
fchmod(request->local, 0444);
|
fchmod(request->local, 0444);
|
||||||
close(request->local);
|
close(request->local); request->local = -1;
|
||||||
|
|
||||||
if (request->http_code == 416) {
|
if (request->http_code == 416) {
|
||||||
fprintf(stderr, "Warning: requested range invalid; we may already have all the data.\n");
|
fprintf(stderr, "Warning: requested range invalid; we may already have all the data.\n");
|
||||||
@ -569,6 +571,8 @@ static void release_request(struct transfer_request *request)
|
|||||||
{
|
{
|
||||||
struct transfer_request *entry = request_queue_head;
|
struct transfer_request *entry = request_queue_head;
|
||||||
|
|
||||||
|
if (request->local != -1)
|
||||||
|
error("fd leakage in release: %d", request->local);
|
||||||
if (request == request_queue_head) {
|
if (request == request_queue_head) {
|
||||||
request_queue_head = request->next;
|
request_queue_head = request->next;
|
||||||
} else {
|
} else {
|
||||||
@ -631,6 +635,8 @@ static void process_curl_messages(void)
|
|||||||
if (request->repo->next != NULL) {
|
if (request->repo->next != NULL) {
|
||||||
request->repo =
|
request->repo =
|
||||||
request->repo->next;
|
request->repo->next;
|
||||||
|
close(request->local);
|
||||||
|
request->local = -1;
|
||||||
start_request(request);
|
start_request(request);
|
||||||
} else {
|
} else {
|
||||||
finish_request(request);
|
finish_request(request);
|
||||||
@ -763,6 +769,7 @@ static int fetch_index(struct alt_base *repo, unsigned char *sha1)
|
|||||||
curl_errorstr);
|
curl_errorstr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
fclose(indexfile);
|
||||||
return error("Unable to start request");
|
return error("Unable to start request");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1083,6 +1090,7 @@ static int fetch_pack(struct alt_base *repo, unsigned char *sha1)
|
|||||||
curl_errorstr);
|
curl_errorstr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
fclose(packfile);
|
||||||
return error("Unable to start request");
|
return error("Unable to start request");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1145,6 +1153,7 @@ static int fetch_object(struct alt_base *repo, unsigned char *sha1)
|
|||||||
fetch_alternates(alt->base);
|
fetch_alternates(alt->base);
|
||||||
if (request->repo->next != NULL) {
|
if (request->repo->next != NULL) {
|
||||||
request->repo = request->repo->next;
|
request->repo = request->repo->next;
|
||||||
|
close(request->local); request->local = -1;
|
||||||
start_request(request);
|
start_request(request);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1153,6 +1162,9 @@ static int fetch_object(struct alt_base *repo, unsigned char *sha1)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
if (request->local != -1) {
|
||||||
|
close(request->local); request->local = -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (request->state == ABORTED) {
|
if (request->state == ABORTED) {
|
||||||
release_request(request);
|
release_request(request);
|
||||||
|
62
object.c
62
object.c
@ -67,40 +67,66 @@ void created_object(const unsigned char *sha1, struct object *obj)
|
|||||||
nr_objs++;
|
nr_objs++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_ref(struct object *refer, struct object *target)
|
struct object_refs *alloc_object_refs(unsigned count)
|
||||||
{
|
{
|
||||||
struct object_list **pp, *p;
|
struct object_refs *refs;
|
||||||
|
size_t size = sizeof(*refs) + count*sizeof(struct object *);
|
||||||
|
|
||||||
if (!track_object_refs)
|
refs = xmalloc(size);
|
||||||
return;
|
memset(refs, 0, size);
|
||||||
|
refs->count = count;
|
||||||
|
return refs;
|
||||||
|
}
|
||||||
|
|
||||||
pp = &refer->refs;
|
static int compare_object_pointers(const void *a, const void *b)
|
||||||
while ((p = *pp) != NULL) {
|
{
|
||||||
if (p->item == target)
|
const struct object * const *pa = a;
|
||||||
|
const struct object * const *pb = b;
|
||||||
|
return *pa - *pb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_object_refs(struct object *obj, struct object_refs *refs)
|
||||||
|
{
|
||||||
|
unsigned int i, j;
|
||||||
|
|
||||||
|
/* Do not install empty list of references */
|
||||||
|
if (refs->count < 1) {
|
||||||
|
free(refs);
|
||||||
return;
|
return;
|
||||||
pp = &p->next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
target->used = 1;
|
/* Sort the list and filter out duplicates */
|
||||||
p = xmalloc(sizeof(*p));
|
qsort(refs->ref, refs->count, sizeof(refs->ref[0]),
|
||||||
p->item = target;
|
compare_object_pointers);
|
||||||
p->next = NULL;
|
for (i = j = 1; i < refs->count; i++) {
|
||||||
*pp = p;
|
if (refs->ref[i] != refs->ref[i - 1])
|
||||||
|
refs->ref[j++] = refs->ref[i];
|
||||||
|
}
|
||||||
|
if (j < refs->count) {
|
||||||
|
/* Duplicates were found - reallocate list */
|
||||||
|
size_t size = sizeof(*refs) + j*sizeof(struct object *);
|
||||||
|
refs->count = j;
|
||||||
|
refs = xrealloc(refs, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < refs->count; i++)
|
||||||
|
refs->ref[i]->used = 1;
|
||||||
|
obj->refs = refs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mark_reachable(struct object *obj, unsigned int mask)
|
void mark_reachable(struct object *obj, unsigned int mask)
|
||||||
{
|
{
|
||||||
struct object_list *p = obj->refs;
|
|
||||||
|
|
||||||
if (!track_object_refs)
|
if (!track_object_refs)
|
||||||
die("cannot do reachability with object refs turned off");
|
die("cannot do reachability with object refs turned off");
|
||||||
/* If we've been here already, don't bother */
|
/* If we've been here already, don't bother */
|
||||||
if (obj->flags & mask)
|
if (obj->flags & mask)
|
||||||
return;
|
return;
|
||||||
obj->flags |= mask;
|
obj->flags |= mask;
|
||||||
while (p) {
|
if (obj->refs) {
|
||||||
mark_reachable(p->item, mask);
|
const struct object_refs *refs = obj->refs;
|
||||||
p = p->next;
|
unsigned i;
|
||||||
|
for (i = 0; i < refs->count; i++)
|
||||||
|
mark_reachable(refs->ref[i], mask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
object.h
10
object.h
@ -7,13 +7,18 @@ struct object_list {
|
|||||||
const char *name;
|
const char *name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct object_refs {
|
||||||
|
unsigned count;
|
||||||
|
struct object *ref[0];
|
||||||
|
};
|
||||||
|
|
||||||
struct object {
|
struct object {
|
||||||
unsigned parsed : 1;
|
unsigned parsed : 1;
|
||||||
unsigned used : 1;
|
unsigned used : 1;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
const char *type;
|
const char *type;
|
||||||
struct object_list *refs;
|
struct object_refs *refs;
|
||||||
void *util;
|
void *util;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -35,7 +40,8 @@ struct object *parse_object(const unsigned char *sha1);
|
|||||||
/** Returns the object, with potentially excess memory allocated. **/
|
/** Returns the object, with potentially excess memory allocated. **/
|
||||||
struct object *lookup_unknown_object(const unsigned char *sha1);
|
struct object *lookup_unknown_object(const unsigned char *sha1);
|
||||||
|
|
||||||
void add_ref(struct object *refer, struct object *target);
|
struct object_refs *alloc_object_refs(unsigned count);
|
||||||
|
void set_object_refs(struct object *obj, struct object_refs *refs);
|
||||||
|
|
||||||
void mark_reachable(struct object *obj, unsigned int mask);
|
void mark_reachable(struct object *obj, unsigned int mask);
|
||||||
|
|
||||||
|
@ -127,38 +127,6 @@ inline struct llist_item * llist_insert_sorted_unique(struct llist *list,
|
|||||||
return llist_insert_back(list, sha1);
|
return llist_insert_back(list, sha1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* computes A\B */
|
|
||||||
void llist_sorted_difference_inplace(struct llist *A,
|
|
||||||
struct llist *B)
|
|
||||||
{
|
|
||||||
struct llist_item *prev, *a, *b, *x;
|
|
||||||
|
|
||||||
prev = a = A->front;
|
|
||||||
b = B->front;
|
|
||||||
|
|
||||||
while (a != NULL && b != NULL) {
|
|
||||||
int cmp = memcmp(a->sha1, b->sha1, 20);
|
|
||||||
if (!cmp) {
|
|
||||||
x = a;
|
|
||||||
if (a == A->front)
|
|
||||||
A->front = a->next;
|
|
||||||
a = prev->next = a->next;
|
|
||||||
|
|
||||||
if (a == NULL) /* end of list */
|
|
||||||
A->back = prev;
|
|
||||||
A->size--;
|
|
||||||
free(x);
|
|
||||||
b = b->next;
|
|
||||||
} else
|
|
||||||
if (cmp > 0)
|
|
||||||
b = b->next;
|
|
||||||
else {
|
|
||||||
prev = a;
|
|
||||||
a = a->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* returns a pointer to an item in front of sha1 */
|
/* returns a pointer to an item in front of sha1 */
|
||||||
inline struct llist_item * llist_sorted_remove(struct llist *list, char *sha1,
|
inline struct llist_item * llist_sorted_remove(struct llist *list, char *sha1,
|
||||||
struct llist_item *hint)
|
struct llist_item *hint)
|
||||||
@ -194,6 +162,21 @@ redo_from_start:
|
|||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* computes A\B */
|
||||||
|
void llist_sorted_difference_inplace(struct llist *A,
|
||||||
|
struct llist *B)
|
||||||
|
{
|
||||||
|
struct llist_item *hint, *b;
|
||||||
|
|
||||||
|
hint = NULL;
|
||||||
|
b = B->front;
|
||||||
|
|
||||||
|
while (b) {
|
||||||
|
hint = llist_sorted_remove(A, b->sha1, hint);
|
||||||
|
b = b->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline struct pack_list * pack_list_insert(struct pack_list **pl,
|
inline struct pack_list * pack_list_insert(struct pack_list **pl,
|
||||||
struct pack_list *entry)
|
struct pack_list *entry)
|
||||||
{
|
{
|
||||||
|
2
refs.c
2
refs.c
@ -121,10 +121,12 @@ int create_symref(const char *git_HEAD, const char *refs_heads_master)
|
|||||||
int fd, len, written;
|
int fd, len, written;
|
||||||
|
|
||||||
#if USE_SYMLINK_HEAD
|
#if USE_SYMLINK_HEAD
|
||||||
|
if (!only_use_symrefs) {
|
||||||
unlink(git_HEAD);
|
unlink(git_HEAD);
|
||||||
if (!symlink(refs_heads_master, git_HEAD))
|
if (!symlink(refs_heads_master, git_HEAD))
|
||||||
return 0;
|
return 0;
|
||||||
fprintf(stderr, "no symlink - falling back to symbolic ref\n");
|
fprintf(stderr, "no symlink - falling back to symbolic ref\n");
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
len = snprintf(ref, sizeof(ref), "ref: %s\n", refs_heads_master);
|
len = snprintf(ref, sizeof(ref), "ref: %s\n", refs_heads_master);
|
||||||
|
@ -424,7 +424,6 @@ static void find_pack_info_one(int pack_ix)
|
|||||||
{
|
{
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
struct object *o;
|
struct object *o;
|
||||||
struct object_list *ref;
|
|
||||||
int i;
|
int i;
|
||||||
struct packed_git *p = info[pack_ix]->p;
|
struct packed_git *p = info[pack_ix]->p;
|
||||||
int num = num_packed_objects(p);
|
int num = num_packed_objects(p);
|
||||||
@ -437,8 +436,12 @@ static void find_pack_info_one(int pack_ix)
|
|||||||
die("corrupt pack file %s?", p->pack_name);
|
die("corrupt pack file %s?", p->pack_name);
|
||||||
if ((o = lookup_object(sha1)) == NULL)
|
if ((o = lookup_object(sha1)) == NULL)
|
||||||
die("cannot parse %s", sha1_to_hex(sha1));
|
die("cannot parse %s", sha1_to_hex(sha1));
|
||||||
for (ref = o->refs; ref; ref = ref->next)
|
if (o->refs) {
|
||||||
ref->item->flags = 0;
|
struct object_refs *refs = o->refs;
|
||||||
|
int j;
|
||||||
|
for (j = 0; j < refs->count; j++)
|
||||||
|
refs->ref[j]->flags = 0;
|
||||||
|
}
|
||||||
o->flags = 0;
|
o->flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -448,8 +451,12 @@ static void find_pack_info_one(int pack_ix)
|
|||||||
die("corrupt pack file %s?", p->pack_name);
|
die("corrupt pack file %s?", p->pack_name);
|
||||||
if ((o = lookup_object(sha1)) == NULL)
|
if ((o = lookup_object(sha1)) == NULL)
|
||||||
die("cannot find %s", sha1_to_hex(sha1));
|
die("cannot find %s", sha1_to_hex(sha1));
|
||||||
for (ref = o->refs; ref; ref = ref->next)
|
if (o->refs) {
|
||||||
ref->item->flags |= REFERENCED;
|
struct object_refs *refs = o->refs;
|
||||||
|
int j;
|
||||||
|
for (j = 0; j < refs->count; j++)
|
||||||
|
refs->ref[j]->flags |= REFERENCED;
|
||||||
|
}
|
||||||
o->flags |= INTERNAL;
|
o->flags |= INTERNAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -460,8 +467,12 @@ static void find_pack_info_one(int pack_ix)
|
|||||||
die("cannot find %s", sha1_to_hex(sha1));
|
die("cannot find %s", sha1_to_hex(sha1));
|
||||||
|
|
||||||
show(o, pack_ix);
|
show(o, pack_ix);
|
||||||
for (ref = o->refs; ref; ref = ref->next)
|
if (o->refs) {
|
||||||
show(ref->item, pack_ix);
|
struct object_refs *refs = o->refs;
|
||||||
|
int j;
|
||||||
|
for (j = 0; j < refs->count; j++)
|
||||||
|
show(refs->ref[j], pack_ix);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -424,7 +424,7 @@ struct packed_git *add_packed_git(char *path, int path_len, int local)
|
|||||||
struct packed_git *p;
|
struct packed_git *p;
|
||||||
unsigned long idx_size;
|
unsigned long idx_size;
|
||||||
void *idx_map;
|
void *idx_map;
|
||||||
char sha1[20];
|
unsigned char sha1[20];
|
||||||
|
|
||||||
if (check_packed_git_idx(path, &idx_size, &idx_map))
|
if (check_packed_git_idx(path, &idx_size, &idx_map))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -20,6 +20,7 @@ static void check_symref(const char *HEAD)
|
|||||||
int main(int argc, const char **argv)
|
int main(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
setup_git_directory();
|
setup_git_directory();
|
||||||
|
git_config(git_default_config);
|
||||||
switch (argc) {
|
switch (argc) {
|
||||||
case 2:
|
case 2:
|
||||||
check_symref(argv[1]);
|
check_symref(argv[1]);
|
||||||
|
115
t/t4103-apply-binary.sh
Normal file
115
t/t4103-apply-binary.sh
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Copyright (c) 2005 Junio C Hamano
|
||||||
|
#
|
||||||
|
|
||||||
|
test_description='git-apply handling binary patches
|
||||||
|
|
||||||
|
'
|
||||||
|
. ./test-lib.sh
|
||||||
|
|
||||||
|
# setup
|
||||||
|
|
||||||
|
cat >file1 <<EOF
|
||||||
|
A quick brown fox jumps over the lazy dog.
|
||||||
|
A tiny little penguin runs around in circles.
|
||||||
|
There is a flag with Linux written on it.
|
||||||
|
A slow black-and-white panda just sits there,
|
||||||
|
munching on his bamboo.
|
||||||
|
EOF
|
||||||
|
cat file1 >file2
|
||||||
|
cat file1 >file4
|
||||||
|
|
||||||
|
git-update-index --add --remove file1 file2 file4
|
||||||
|
git-commit -m 'Initial Version' 2>/dev/null
|
||||||
|
|
||||||
|
git-checkout -b binary
|
||||||
|
tr 'x' '\0' <file1 >file3
|
||||||
|
cat file3 >file4
|
||||||
|
git-add file2
|
||||||
|
tr '\0' 'v' <file3 >file1
|
||||||
|
rm -f file2
|
||||||
|
git-update-index --add --remove file1 file2 file3 file4
|
||||||
|
git-commit -m 'Second Version'
|
||||||
|
|
||||||
|
git-diff-tree -p master binary >B.diff
|
||||||
|
git-diff-tree -p -C master binary >C.diff
|
||||||
|
|
||||||
|
git-diff-tree -p --full-index master binary >BF.diff
|
||||||
|
git-diff-tree -p --full-index -C master binary >CF.diff
|
||||||
|
|
||||||
|
test_expect_success 'stat binary diff -- should not fail.' \
|
||||||
|
'git-checkout master
|
||||||
|
git-apply --stat --summary B.diff'
|
||||||
|
|
||||||
|
test_expect_success 'stat binary diff (copy) -- should not fail.' \
|
||||||
|
'git-checkout master
|
||||||
|
git-apply --stat --summary C.diff'
|
||||||
|
|
||||||
|
test_expect_failure 'check binary diff -- should fail.' \
|
||||||
|
'git-checkout master
|
||||||
|
git-apply --check B.diff'
|
||||||
|
|
||||||
|
test_expect_failure 'check binary diff (copy) -- should fail.' \
|
||||||
|
'git-checkout master
|
||||||
|
git-apply --check C.diff'
|
||||||
|
|
||||||
|
test_expect_failure 'check incomplete binary diff with replacement -- should fail.' \
|
||||||
|
'git-checkout master
|
||||||
|
git-apply --check --allow-binary-replacement B.diff'
|
||||||
|
|
||||||
|
test_expect_failure 'check incomplete binary diff with replacement (copy) -- should fail.' \
|
||||||
|
'git-checkout master
|
||||||
|
git-apply --check --allow-binary-replacement C.diff'
|
||||||
|
|
||||||
|
test_expect_success 'check binary diff with replacement.' \
|
||||||
|
'git-checkout master
|
||||||
|
git-apply --check --allow-binary-replacement BF.diff'
|
||||||
|
|
||||||
|
test_expect_success 'check binary diff with replacement (copy).' \
|
||||||
|
'git-checkout master
|
||||||
|
git-apply --check --allow-binary-replacement CF.diff'
|
||||||
|
|
||||||
|
# Now we start applying them.
|
||||||
|
|
||||||
|
do_reset () {
|
||||||
|
rm -f file?
|
||||||
|
git-reset --hard
|
||||||
|
git-checkout -f master
|
||||||
|
}
|
||||||
|
|
||||||
|
test_expect_failure 'apply binary diff -- should fail.' \
|
||||||
|
'do_reset
|
||||||
|
git-apply B.diff'
|
||||||
|
|
||||||
|
test_expect_failure 'apply binary diff -- should fail.' \
|
||||||
|
'do_reset
|
||||||
|
git-apply --index B.diff'
|
||||||
|
|
||||||
|
test_expect_failure 'apply binary diff (copy) -- should fail.' \
|
||||||
|
'do_reset
|
||||||
|
git-apply C.diff'
|
||||||
|
|
||||||
|
test_expect_failure 'apply binary diff (copy) -- should fail.' \
|
||||||
|
'do_reset
|
||||||
|
git-apply --index C.diff'
|
||||||
|
|
||||||
|
test_expect_failure 'apply binary diff without replacement -- should fail.' \
|
||||||
|
'do_reset
|
||||||
|
git-apply BF.diff'
|
||||||
|
|
||||||
|
test_expect_failure 'apply binary diff without replacement (copy) -- should fail.' \
|
||||||
|
'do_reset
|
||||||
|
git-apply CF.diff'
|
||||||
|
|
||||||
|
test_expect_success 'apply binary diff.' \
|
||||||
|
'do_reset
|
||||||
|
git-apply --allow-binary-replacement --index BF.diff &&
|
||||||
|
test -z "$(git-diff --name-status binary)"'
|
||||||
|
|
||||||
|
test_expect_success 'apply binary diff (copy).' \
|
||||||
|
'do_reset
|
||||||
|
git-apply --allow-binary-replacement --index CF.diff &&
|
||||||
|
test -z "$(git-diff --name-status binary)"'
|
||||||
|
|
||||||
|
test_done
|
@ -158,6 +158,8 @@ test_done () {
|
|||||||
# Test the binaries we have just built. The tests are kept in
|
# Test the binaries we have just built. The tests are kept in
|
||||||
# t/ subdirectory and are run in trash subdirectory.
|
# t/ subdirectory and are run in trash subdirectory.
|
||||||
PATH=$(pwd)/..:$PATH
|
PATH=$(pwd)/..:$PATH
|
||||||
|
GIT_EXEC_PATH=$(pwd)/..
|
||||||
|
export GIT_EXEC_PATH
|
||||||
|
|
||||||
# Test repository
|
# Test repository
|
||||||
test=trash
|
test=trash
|
||||||
|
7
tag.c
7
tag.c
@ -75,8 +75,11 @@ int parse_tag_buffer(struct tag *item, void *data, unsigned long size)
|
|||||||
item->tag[taglen] = '\0';
|
item->tag[taglen] = '\0';
|
||||||
|
|
||||||
item->tagged = lookup_object_type(object, type);
|
item->tagged = lookup_object_type(object, type);
|
||||||
if (item->tagged)
|
if (item->tagged && track_object_refs) {
|
||||||
add_ref(&item->object, item->tagged);
|
struct object_refs *refs = alloc_object_refs(1);
|
||||||
|
refs->ref[0] = item->tagged;
|
||||||
|
set_object_refs(&item->object, refs);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
13
tree.c
13
tree.c
@ -148,6 +148,7 @@ int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size)
|
|||||||
{
|
{
|
||||||
void *bufptr = buffer;
|
void *bufptr = buffer;
|
||||||
struct tree_entry_list **list_p;
|
struct tree_entry_list **list_p;
|
||||||
|
int n_refs = 0;
|
||||||
|
|
||||||
if (item->object.parsed)
|
if (item->object.parsed)
|
||||||
return 0;
|
return 0;
|
||||||
@ -184,11 +185,21 @@ int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size)
|
|||||||
obj = &entry->item.blob->object;
|
obj = &entry->item.blob->object;
|
||||||
}
|
}
|
||||||
if (obj)
|
if (obj)
|
||||||
add_ref(&item->object, obj);
|
n_refs++;
|
||||||
entry->parent = NULL; /* needs to be filled by the user */
|
entry->parent = NULL; /* needs to be filled by the user */
|
||||||
*list_p = entry;
|
*list_p = entry;
|
||||||
list_p = &entry->next;
|
list_p = &entry->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (track_object_refs) {
|
||||||
|
struct tree_entry_list *entry;
|
||||||
|
unsigned i = 0;
|
||||||
|
struct object_refs *refs = alloc_object_refs(n_refs);
|
||||||
|
for (entry = item->entries; entry; entry = entry->next)
|
||||||
|
refs->ref[i++] = entry->item.any;
|
||||||
|
set_object_refs(&item->object, refs);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user