зеркало из https://github.com/microsoft/git.git
GIT 0.99.9l aka 1.0rc4
This commit is contained in:
Коммит
423325a2d2
|
@ -4,6 +4,11 @@
|
|||
option old data in `.git/FETCH_HEAD` will be overwritten.
|
||||
|
||||
-f, \--force::
|
||||
When `git-fetch` is used with `<rbranch>:<lbranch>`
|
||||
refspec, it refuses to update the local branch
|
||||
`<lbranch>` unless the remote branch `<rbranch>` it
|
||||
fetches is a descendant of `<lbranch>`. This option
|
||||
overrides that check.
|
||||
|
||||
-t, \--tags::
|
||||
By default, the git core utilities will not fetch and store
|
||||
|
|
|
@ -8,13 +8,13 @@ git-bisect - Find the change that introduced a bug
|
|||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git bisect' start
|
||||
'git bisect' bad <rev>
|
||||
'git bisect' good <rev>
|
||||
'git bisect' reset [<branch>]
|
||||
'git bisect' visualize
|
||||
'git bisect' replay <logfile>
|
||||
'git bisect' log
|
||||
'git bisect' start
|
||||
'git bisect' bad <rev>
|
||||
'git bisect' good <rev>
|
||||
'git bisect' reset [<branch>]
|
||||
'git bisect' visualize
|
||||
'git bisect' replay <logfile>
|
||||
'git bisect' log
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
|
|
@ -8,7 +8,7 @@ git-cat-file - Provide content or type information for repository objects
|
|||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git-cat-file' (-t | -s | <type>) <object>
|
||||
'git-cat-file' (-t | -s | -e | <type>) <object>
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
@ -29,6 +29,10 @@ OPTIONS
|
|||
Instead of the content, show the object size identified by
|
||||
<object>.
|
||||
|
||||
-e::
|
||||
Suppress all output; instead exit with zero status if <object>
|
||||
exists and is a valid object.
|
||||
|
||||
<type>::
|
||||
Typically this matches the real type of <object> but asking
|
||||
for a type that can trivially be dereferenced from the given
|
||||
|
@ -39,8 +43,11 @@ OPTIONS
|
|||
|
||||
OUTPUT
|
||||
------
|
||||
If '-t' is specified, one of the <type>. If '-s' is specified,
|
||||
the size of the <object> in bytes.
|
||||
If '-t' is specified, one of the <type>.
|
||||
|
||||
If '-s' is specified, the size of the <object> in bytes.
|
||||
|
||||
If '-e' is specified, no output.
|
||||
|
||||
Otherwise the raw (though uncompressed) contents of the <object> will
|
||||
be returned.
|
||||
|
|
|
@ -21,6 +21,15 @@ OPTIONS
|
|||
-------
|
||||
include::diff-options.txt[]
|
||||
|
||||
-1 -2 -3 or --base --ours --theirs, and -0::
|
||||
Diff against the "base" version, "our branch" or "their
|
||||
branch" respectively. With these options, diffs for
|
||||
merged entries are not shown.
|
||||
+
|
||||
The default is to diff against our branch (-2) and the
|
||||
cleanly resolved paths. The option -0 can be given to
|
||||
omit diff output for unmerged entries and just show "Unmerged".
|
||||
|
||||
-q::
|
||||
Remain silent even on nonexisting files
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ git-mailinfo - Extracts patch from a single e-mail message.
|
|||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git-mailinfo' [-k] [-u] <msg> <patch>
|
||||
'git-mailinfo' [-k] [-u | --encoding=<encoding>] <msg> <patch>
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
|
@ -37,10 +37,17 @@ OPTIONS
|
|||
author email are taken from the e-mail without any
|
||||
charset conversion, after minimally decoding MIME
|
||||
transfer encoding. This flag causes the resulting
|
||||
commit to be encoded in utf-8 by transliterating them.
|
||||
commit to be encoded in the encoding specified by
|
||||
i18n.commitencoding configuration (defaults to utf-8) by
|
||||
transliterating them.
|
||||
Note that the patch is always used as is without charset
|
||||
conversion, even with this flag.
|
||||
|
||||
--encoding=<encoding>::
|
||||
Similar to -u but if the local convention is different
|
||||
from what is specified by i18n.commitencoding, this flag
|
||||
can be used to override it.
|
||||
|
||||
<msg>::
|
||||
The commit log message extracted from e-mail, usually
|
||||
except the title line which comes from e-mail Subject.
|
||||
|
|
|
@ -37,6 +37,103 @@ include::merge-options.txt[]
|
|||
include::merge-strategies.txt[]
|
||||
|
||||
|
||||
HOW MERGE WORKS
|
||||
---------------
|
||||
|
||||
A merge is always between the current `HEAD` and one or more
|
||||
remote branch heads, and the index file must exactly match the
|
||||
tree of `HEAD` commit (i.e. the contents of the last commit) when
|
||||
it happens. In other words, `git-diff --cached HEAD` must
|
||||
report no changes.
|
||||
|
||||
[NOTE]
|
||||
This is a bit of lie. In certain special cases, your index are
|
||||
allowed to be different from the tree of `HEAD` commit. The most
|
||||
notable case is when your `HEAD` commit is already ahead of what
|
||||
is being merged, in which case your index can have arbitrary
|
||||
difference from your `HEAD` commit. Otherwise, your index entries
|
||||
are allowed have differences from your `HEAD` commit that match
|
||||
the result of trivial merge (e.g. you received the same patch
|
||||
from external source to produce the same result as what you are
|
||||
merging). For example, if a path did not exist in the common
|
||||
ancestor and your head commit but exists in the tree you are
|
||||
merging into your repository, and if you already happen to have
|
||||
that path exactly in your index, the merge does not have to
|
||||
fail.
|
||||
|
||||
Otherwise, merge will refuse to do any harm to your repository
|
||||
(that is, it may fetch the objects from remote, and it may even
|
||||
update the local branch used to keep track of the remote branch
|
||||
with `git pull remote rbranch:lbranch`, but your working tree,
|
||||
`.git/HEAD` pointer and index file are left intact).
|
||||
|
||||
You may have local modifications in the working tree files. In
|
||||
other words, `git-diff` is allowed to report changes.
|
||||
However, the merge uses your working tree as the working area,
|
||||
and in order to prevent the merge operation from losing such
|
||||
changes, it makes sure that they do not interfere with the
|
||||
merge. Those complex tables in read-tree documentation define
|
||||
what it means for a path to "interfere with the merge". And if
|
||||
your local modifications interfere with the merge, again, it
|
||||
stops before touching anything.
|
||||
|
||||
So in the above two "failed merge" case, you do not have to
|
||||
worry about lossage of data --- you simply were not ready to do
|
||||
a merge, so no merge happened at all. You may want to finish
|
||||
whatever you were in the middle of doing, and retry the same
|
||||
pull after you are done and ready.
|
||||
|
||||
When things cleanly merge, these things happen:
|
||||
|
||||
1. the results are updated both in the index file and in your
|
||||
working tree,
|
||||
2. index file is written out as a tree,
|
||||
3. the tree gets committed, and
|
||||
4. the `HEAD` pointer gets advanced.
|
||||
|
||||
Because of 2., we require that the original state of the index
|
||||
file to match exactly the current `HEAD` commit; otherwise we
|
||||
will write out your local changes already registered in your
|
||||
index file along with the merge result, which is not good.
|
||||
Because 1. involves only the paths different between your
|
||||
branch and the remote branch you are pulling from during the
|
||||
merge (which is typically a fraction of the whole tree), you can
|
||||
have local modifications in your working tree as long as they do
|
||||
not overlap with what the merge updates.
|
||||
|
||||
When there are conflicts, these things happen:
|
||||
|
||||
1. `HEAD` stays the same.
|
||||
|
||||
2. Cleanly merged paths are updated both in the index file and
|
||||
in your working tree.
|
||||
|
||||
3. For conflicting paths, the index file records up to three
|
||||
versions; stage1 stores the version from the common ancestor,
|
||||
stage2 from `HEAD`, and stage3 from the remote branch (you
|
||||
can inspect the stages with `git-ls-files -u`). The working
|
||||
tree files have the result of "merge" program; i.e. 3-way
|
||||
merge result with familiar conflict markers `<<< === >>>`.
|
||||
|
||||
4. No other changes are done. In particular, the local
|
||||
modifications you had before you started merge will stay the
|
||||
same and the index entries for them stay as they were,
|
||||
i.e. matching `HEAD`.
|
||||
|
||||
After seeing a conflict, you can do two things:
|
||||
|
||||
* Decide not to merge. The only clean-up you need are to reset
|
||||
the index file to the `HEAD` commit to reverse 2. and to clean
|
||||
up working tree changes made by 2. and 3.; `git-reset` can
|
||||
be used for this.
|
||||
|
||||
* Resolve the conflicts. `git-diff` would report only the
|
||||
conflicting paths because of the above 2. and 3.. Edit the
|
||||
working tree files into a desirable shape, `git-update-index`
|
||||
them, to make the index file contain what the merge result
|
||||
should be, and run `git-commit` to commit the result.
|
||||
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
gitlink:git-fmt-merge-msg[1], gitlink:git-pull[1]
|
||||
|
|
|
@ -8,14 +8,14 @@ git-mv - Script used to move or rename a file, directory or symlink.
|
|||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git-mv' [-f] [-n] <source> <destination>
|
||||
'git-mv' [-f] [-k] [-n] <source> ... <destination directory>
|
||||
'git-mv' [-f] [-n] <source> <destination>
|
||||
'git-mv' [-f] [-n] [-k] <source> ... <destination directory>
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
This script is used to move or rename a file, directory or symlink.
|
||||
In the first form, it renames <source>, which must exist and be either
|
||||
a file, symlink or directory, to <destination>, which must not exist.
|
||||
a file, symlink or directory, to <destination>.
|
||||
In the second form, the last argument has to be an existing
|
||||
directory; the given sources will be moved into this directory.
|
||||
|
||||
|
@ -25,7 +25,7 @@ committed.
|
|||
OPTIONS
|
||||
-------
|
||||
-f::
|
||||
Force renaming or moving even targets exist
|
||||
Force renaming or moving of a file even if the target exists
|
||||
-k::
|
||||
Skip move or rename actions which would lead to an error
|
||||
condition. An error happens when a source is neither existing nor
|
||||
|
|
|
@ -28,11 +28,14 @@ will be in unmerged state when "git-read-tree" returns.
|
|||
OPTIONS
|
||||
-------
|
||||
-m::
|
||||
Perform a merge, not just a read.
|
||||
Perform a merge, not just a read. The command will
|
||||
refuse to run if your index file has unmerged entries,
|
||||
indicating that you have not finished previous merge you
|
||||
started.
|
||||
|
||||
--reset::
|
||||
|
||||
Same as -m except that unmerged entries will be silently ignored.
|
||||
Same as -m, except that unmerged entries are discarded
|
||||
instead of failing.
|
||||
|
||||
-u::
|
||||
After a successful merge, update the files in the work
|
||||
|
@ -47,7 +50,6 @@ OPTIONS
|
|||
trees that are not directly related to the current
|
||||
working tree status into a temporary index file.
|
||||
|
||||
|
||||
<tree-ish#>::
|
||||
The id of the tree object(s) to be read/merged.
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ git-svnimport - Import a SVN repository into git
|
|||
SYNOPSIS
|
||||
--------
|
||||
'git-svnimport' [ -o <branch-for-HEAD> ] [ -h ] [ -v ] [ -d | -D ]
|
||||
[ -C <GIT_repository> ] [ -i ] [ -u ] [-l limit_nr_changes]
|
||||
[ -C <GIT_repository> ] [ -i ] [ -u ] [-l limit_rev]
|
||||
[ -b branch_subdir ] [ -t trunk_subdir ] [ -T tag_subdir ]
|
||||
[ -s start_chg ] [ -m ] [ -M regex ]
|
||||
<SVN_repository_URL> [ <path> ]
|
||||
|
@ -71,14 +71,11 @@ When importing incementally, you might need to edit the .git/svn2git file.
|
|||
regex. It can be used with -m to also see the default regexes.
|
||||
You must escape forward slashes.
|
||||
|
||||
-l <max_num_changes>::
|
||||
Limit the number of SVN changesets we pull before quitting.
|
||||
This option is necessary because the SVN library has serious memory
|
||||
leaks; the recommended value for nontrivial imports is 100.
|
||||
-l <max_rev>::
|
||||
Specify a maximum revision number to pull.
|
||||
|
||||
git-svnimport will still exit with a zero exit code. You can check
|
||||
the size of the file ".git/svn2git" to determine whether to call
|
||||
the importer again.
|
||||
Formerly, this option controlled how many revisions to pull, due to
|
||||
SVN memory leaks. (These have been worked around.)
|
||||
|
||||
-v::
|
||||
Verbosity: let 'svnimport' report what it is doing.
|
||||
|
|
|
@ -10,6 +10,26 @@ SYNOPSIS
|
|||
--------
|
||||
'git-tag' [-a | -s | -u <key-id>] [-f | -d] [-m <msg>] <name> [<head>]
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
-a::
|
||||
Make an unsigned, annotated tag object
|
||||
|
||||
-s::
|
||||
Make a GPG-signed tag, using the default e-mail address's key
|
||||
|
||||
-u <key-id>::
|
||||
Make a GPG-signed tag, using the given key
|
||||
|
||||
-f::
|
||||
Replace an existing tag with the given name (instead of failing)
|
||||
|
||||
-d::
|
||||
Delete an existing tag with the given name
|
||||
|
||||
-m <msg>::
|
||||
Use the given tag message (instead of prompting)
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Adds a 'tag' reference in .git/refs/tags/
|
||||
|
@ -23,7 +43,7 @@ creates a 'tag' object, and requires the tag message. Unless
|
|||
in the tag message.
|
||||
|
||||
Otherwise just the SHA1 object name of the commit object is
|
||||
written (i.e. an lightweight tag).
|
||||
written (i.e. a lightweight tag).
|
||||
|
||||
A GnuPG signed tag object will be created when `-s` or `-u
|
||||
<key-id>` is used. When `-u <key-id>` is not used, the
|
||||
|
|
|
@ -15,10 +15,10 @@
|
|||
- ssh://host.xz/~/path/to/repo.git
|
||||
===============================================================
|
||||
+
|
||||
SSH Is the default transport protocol and also supports an
|
||||
scp-like syntax. Both syntaxes support username expansion,
|
||||
as does the native git protocol. The following three are
|
||||
identical to the last three above, respectively:
|
||||
SSH Is the default transport protocol and also supports an
|
||||
scp-like syntax. Both syntaxes support username expansion,
|
||||
as does the native git protocol. The following three are
|
||||
identical to the last three above, respectively:
|
||||
+
|
||||
===============================================================
|
||||
- host.xz:/path/to/repo.git/
|
||||
|
@ -26,8 +26,8 @@
|
|||
- host.xz:path/to/repo.git
|
||||
===============================================================
|
||||
+
|
||||
To sync with a local directory, use:
|
||||
|
||||
To sync with a local directory, use:
|
||||
+
|
||||
===============================================================
|
||||
- /path/to/repo.git/
|
||||
===============================================================
|
||||
|
@ -113,7 +113,7 @@ on the remote branch, merge it into your development branch with
|
|||
`git pull . remote-B`, while you are on `my-B` branch.
|
||||
The common `Pull: master:origin` mapping of a remote `master`
|
||||
branch to a local `origin` branch, which is then merged to a
|
||||
ocal development branch, again typically named `master`, is made
|
||||
local development branch, again typically named `master`, is made
|
||||
when you run `git clone` for you to follow this pattern.
|
||||
+
|
||||
[NOTE]
|
||||
|
|
|
@ -898,9 +898,8 @@ file, which had no differences in the `mybranch` branch), and say:
|
|||
fatal: Merge requires file-level merging
|
||||
Nope.
|
||||
...
|
||||
merge: warning: conflicts during merge
|
||||
ERROR: Merge conflict in hello.
|
||||
fatal: merge program failed
|
||||
Auto-merging hello
|
||||
CONFLICT (content): Merge conflict in hello
|
||||
Automatic merge failed/prevented; fix up by hand
|
||||
----------------
|
||||
|
||||
|
@ -942,10 +941,10 @@ environment, is `git show-branch`.
|
|||
|
||||
------------------------------------------------
|
||||
$ git show-branch master mybranch
|
||||
* [master] Merged "mybranch" changes.
|
||||
* [master] Merge work in mybranch
|
||||
! [mybranch] Some work.
|
||||
--
|
||||
+ [master] Merged "mybranch" changes.
|
||||
+ [master] Merge work in mybranch
|
||||
++ [mybranch] Some work.
|
||||
------------------------------------------------
|
||||
|
||||
|
@ -998,10 +997,10 @@ looks like, or run `show-branch`, which tells you this.
|
|||
|
||||
------------------------------------------------
|
||||
$ git show-branch master mybranch
|
||||
! [master] Merged "mybranch" changes.
|
||||
* [mybranch] Merged "mybranch" changes.
|
||||
! [master] Merge work in mybranch
|
||||
* [mybranch] Merge work in mybranch
|
||||
--
|
||||
++ [master] Merged "mybranch" changes.
|
||||
++ [master] Merge work in mybranch
|
||||
------------------------------------------------
|
||||
|
||||
|
||||
|
|
60
Makefile
60
Makefile
|
@ -1,3 +1,6 @@
|
|||
# The default target of this Makefile is...
|
||||
all:
|
||||
|
||||
# Define MOZILLA_SHA1 environment variable when running make to make use of
|
||||
# a bundled SHA1 routine coming from Mozilla. It is GPL'd and should be fast
|
||||
# on non-x86 architectures (e.g. PowerPC), while the OpenSSL version (default
|
||||
|
@ -18,6 +21,8 @@
|
|||
#
|
||||
# Define NO_STRCASESTR if you don't have strcasestr.
|
||||
#
|
||||
# Define NO_SETENV if you don't have setenv in the C library.
|
||||
#
|
||||
# Define PPC_SHA1 environment variable when running make to make use of
|
||||
# a bundled SHA1 routine optimized for PowerPC.
|
||||
#
|
||||
|
@ -50,7 +55,7 @@
|
|||
# Define USE_STDEV below if you want git to care about the underlying device
|
||||
# change being considered an inode change from the update-cache perspective.
|
||||
|
||||
GIT_VERSION = 0.99.9k
|
||||
GIT_VERSION = 0.99.9l
|
||||
|
||||
# CFLAGS and LDFLAGS are for the users to override from the command line.
|
||||
|
||||
|
@ -138,8 +143,6 @@ ALL_PROGRAMS = $(PROGRAMS) $(SIMPLE_PROGRAMS) $(SCRIPTS) git$X
|
|||
# Backward compatibility -- to be removed after 1.0
|
||||
PROGRAMS += git-ssh-pull$X git-ssh-push$X
|
||||
|
||||
GIT_LIST_TWEAK =
|
||||
|
||||
# Set paths to tools early so that they can be used for version tests.
|
||||
ifndef SHELL_PATH
|
||||
SHELL_PATH = /bin/sh
|
||||
|
@ -154,20 +157,6 @@ endif
|
|||
PYMODULES = \
|
||||
gitMergeCommon.py
|
||||
|
||||
ifdef WITH_OWN_SUBPROCESS_PY
|
||||
PYMODULES += compat/subprocess.py
|
||||
else
|
||||
ifneq ($(shell $(PYTHON_PATH) -c 'import subprocess;print"OK"' 2>/dev/null),OK)
|
||||
PYMODULES += compat/subprocess.py
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef WITH_SEND_EMAIL
|
||||
SCRIPT_PERL += git-send-email.perl
|
||||
else
|
||||
GIT_LIST_TWEAK += -e '/^send-email$$/d'
|
||||
endif
|
||||
|
||||
LIB_FILE=libgit.a
|
||||
|
||||
LIB_H = \
|
||||
|
@ -207,6 +196,7 @@ shellquote = '$(call shq,$(1))'
|
|||
uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
|
||||
uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not')
|
||||
uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not')
|
||||
uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not')
|
||||
|
||||
ifeq ($(uname_S),Darwin)
|
||||
NEEDS_SSL_WITH_CRYPTO = YesPlease
|
||||
|
@ -224,6 +214,9 @@ ifeq ($(uname_S),SunOS)
|
|||
NEEDS_LIBICONV = YesPlease
|
||||
SHELL_PATH = /bin/bash
|
||||
NO_STRCASESTR = YesPlease
|
||||
ifeq ($(uname_R),5.8)
|
||||
NO_SETENV = YesPlease
|
||||
endif
|
||||
INSTALL = ginstall
|
||||
TAR = gtar
|
||||
ALL_CFLAGS += -D__EXTENSIONS__
|
||||
|
@ -256,6 +249,18 @@ endif
|
|||
|
||||
-include config.mak
|
||||
|
||||
ifdef WITH_OWN_SUBPROCESS_PY
|
||||
PYMODULES += compat/subprocess.py
|
||||
else
|
||||
ifneq ($(shell $(PYTHON_PATH) -c 'import subprocess;print"OK"' 2>/dev/null),OK)
|
||||
PYMODULES += compat/subprocess.py
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef WITH_SEND_EMAIL
|
||||
SCRIPT_PERL += git-send-email.perl
|
||||
endif
|
||||
|
||||
ifndef NO_CURL
|
||||
ifdef CURLDIR
|
||||
# This is still problematic -- gcc does not always want -R.
|
||||
|
@ -315,12 +320,16 @@ ifdef NEEDS_NSL
|
|||
SIMPLE_LIB += -lnsl
|
||||
endif
|
||||
ifdef NO_STRCASESTR
|
||||
ALL_CFLAGS += -Dstrcasestr=gitstrcasestr -DNO_STRCASESTR=1
|
||||
LIB_OBJS += compat/strcasestr.o
|
||||
COMPAT_CFLAGS += -Dstrcasestr=gitstrcasestr -DNO_STRCASESTR=1
|
||||
COMPAT_OBJS += compat/strcasestr.o
|
||||
endif
|
||||
ifdef NO_SETENV
|
||||
COMPAT_CFLAGS += -Dsetenv=gitsetenv -DNO_SETENV=1
|
||||
COMPAT_OBJS += compat/setenv.o
|
||||
endif
|
||||
ifdef NO_MMAP
|
||||
ALL_CFLAGS += -Dmmap=gitfakemmap -Dmunmap=gitfakemunmap -DNO_MMAP
|
||||
LIB_OBJS += compat/mmap.o
|
||||
COMPAT_CFLAGS += -Dmmap=gitfakemmap -Dmunmap=gitfakemunmap -DNO_MMAP
|
||||
COMPAT_OBJS += compat/mmap.o
|
||||
endif
|
||||
ifdef NO_IPV6
|
||||
ALL_CFLAGS += -DNO_IPV6 -Dsockaddr_storage=sockaddr_in
|
||||
|
@ -344,8 +353,8 @@ endif
|
|||
endif
|
||||
endif
|
||||
|
||||
ALL_CFLAGS += -DSHA1_HEADER=$(call shellquote,$(SHA1_HEADER))
|
||||
|
||||
ALL_CFLAGS += -DSHA1_HEADER=$(call shellquote,$(SHA1_HEADER)) $(COMPAT_CFLAGS)
|
||||
LIB_OBJS += $(COMPAT_OBJS)
|
||||
export prefix TAR INSTALL DESTDIR SHELL_PATH template_dir
|
||||
### Build rules
|
||||
|
||||
|
@ -354,10 +363,9 @@ all: $(ALL_PROGRAMS)
|
|||
all:
|
||||
$(MAKE) -C templates
|
||||
|
||||
# Only use $(CFLAGS). We don't need anything else.
|
||||
git$(X): git.c Makefile
|
||||
git$(X): git.c $(COMPAT_OBJS) Makefile
|
||||
$(CC) -DGIT_EXEC_PATH='"$(bindir)"' -DGIT_VERSION='"$(GIT_VERSION)"' \
|
||||
$(CFLAGS) $< -o $@
|
||||
$(CFLAGS) $(COMPAT_CFLAGS) -o $@ $(filter %.c,$^) $(filter %.o,$^)
|
||||
|
||||
$(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
|
||||
rm -f $@
|
||||
|
|
18
apply.c
18
apply.c
|
@ -16,6 +16,9 @@
|
|||
// --numstat does numeric diffstat, and doesn't actually apply
|
||||
// --index-info shows the old and new index info for paths if available.
|
||||
//
|
||||
static const char *prefix;
|
||||
static int prefix_length = -1;
|
||||
|
||||
static int allow_binary_replacement = 0;
|
||||
static int check_index = 0;
|
||||
static int write_index = 0;
|
||||
|
@ -1706,6 +1709,12 @@ static int use_patch(struct patch *p)
|
|||
return 0;
|
||||
x = x->next;
|
||||
}
|
||||
if (0 < prefix_length) {
|
||||
int pathlen = strlen(pathname);
|
||||
if (pathlen <= prefix_length ||
|
||||
memcmp(prefix, pathname, prefix_length))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1845,6 +1854,15 @@ int main(int argc, char **argv)
|
|||
line_termination = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (check_index && prefix_length < 0) {
|
||||
prefix = setup_git_directory();
|
||||
prefix_length = prefix ? strlen(prefix) : 0;
|
||||
git_config(git_default_config);
|
||||
}
|
||||
if (0 < prefix_length)
|
||||
arg = prefix_filename(prefix, prefix_length, arg);
|
||||
|
||||
fd = open(arg, O_RDONLY);
|
||||
if (fd < 0)
|
||||
usage(apply_usage);
|
||||
|
|
11
cache.h
11
cache.h
|
@ -147,8 +147,10 @@ extern char *get_graft_file(void);
|
|||
#define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
|
||||
|
||||
extern const char **get_pathspec(const char *prefix, const char **pathspec);
|
||||
extern const char *setup_git_directory_gently(int *);
|
||||
extern const char *setup_git_directory(void);
|
||||
extern const char *prefix_path(const char *prefix, int len, const char *path);
|
||||
extern const char *prefix_filename(const char *prefix, int len, const char *path);
|
||||
|
||||
#define alloc_nr(x) (((x)+16)*3/2)
|
||||
|
||||
|
@ -182,6 +184,10 @@ extern int trust_executable_bit;
|
|||
extern int only_use_symrefs;
|
||||
extern int diff_rename_limit_default;
|
||||
|
||||
#define GIT_REPO_VERSION 0
|
||||
extern int repository_format_version;
|
||||
extern int check_repository_format(void);
|
||||
|
||||
#define MTIME_CHANGED 0x0001
|
||||
#define CTIME_CHANGED 0x0002
|
||||
#define OWNER_CHANGED 0x0004
|
||||
|
@ -383,16 +389,21 @@ extern int gitfakemunmap(void *start, size_t length);
|
|||
|
||||
typedef int (*config_fn_t)(const char *, const char *);
|
||||
extern int git_default_config(const char *, const char *);
|
||||
extern int git_config_from_file(config_fn_t fn, const char *);
|
||||
extern int git_config(config_fn_t fn);
|
||||
extern int git_config_int(const char *, const char *);
|
||||
extern int git_config_bool(const char *, const char *);
|
||||
extern int git_config_set(const char *, const char *);
|
||||
extern int git_config_set_multivar(const char *, const char *, const char *, int);
|
||||
extern int check_repository_format_version(const char *var, const char *value);
|
||||
|
||||
#define MAX_GITNAME (1000)
|
||||
extern char git_default_email[MAX_GITNAME];
|
||||
extern char git_default_name[MAX_GITNAME];
|
||||
|
||||
#define MAX_ENCODING_LENGTH 64
|
||||
extern char git_commit_encoding[MAX_ENCODING_LENGTH];
|
||||
|
||||
/* Sane ctype - no locale, and works with signed chars */
|
||||
#undef isspace
|
||||
#undef isdigit
|
||||
|
|
45
cat-file.c
45
cat-file.c
|
@ -11,27 +11,44 @@ int main(int argc, char **argv)
|
|||
char type[20];
|
||||
void *buf;
|
||||
unsigned long size;
|
||||
int opt;
|
||||
|
||||
setup_git_directory();
|
||||
if (argc != 3 || get_sha1(argv[2], sha1))
|
||||
usage("git-cat-file [-t | -s | <type>] <sha1>");
|
||||
usage("git-cat-file [-t|-s|-e|<type>] <sha1>");
|
||||
|
||||
if (!strcmp("-t", argv[1]) || !strcmp("-s", argv[1])) {
|
||||
if (!sha1_object_info(sha1, type,
|
||||
argv[1][1] == 's' ? &size : NULL)) {
|
||||
switch (argv[1][1]) {
|
||||
case 't':
|
||||
printf("%s\n", type);
|
||||
break;
|
||||
case 's':
|
||||
printf("%lu\n", size);
|
||||
break;
|
||||
}
|
||||
opt = 0;
|
||||
if ( argv[1][0] == '-' ) {
|
||||
opt = argv[1][1];
|
||||
if ( !opt || argv[1][2] )
|
||||
opt = -1; /* Not a single character option */
|
||||
}
|
||||
|
||||
buf = NULL;
|
||||
switch (opt) {
|
||||
case 't':
|
||||
if (!sha1_object_info(sha1, type, NULL)) {
|
||||
printf("%s\n", type);
|
||||
return 0;
|
||||
}
|
||||
buf = NULL;
|
||||
} else {
|
||||
break;
|
||||
|
||||
case 's':
|
||||
if (!sha1_object_info(sha1, type, &size)) {
|
||||
printf("%lu\n", size);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
return !has_sha1_file(sha1);
|
||||
|
||||
case 0:
|
||||
buf = read_object_with_reference(sha1, argv[1], &size, NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
die("git-cat-file: unknown option: %s\n", argv[1]);
|
||||
}
|
||||
|
||||
if (!buf)
|
||||
|
|
|
@ -34,6 +34,9 @@
|
|||
*/
|
||||
#include "cache.h"
|
||||
|
||||
static const char *prefix;
|
||||
static int prefix_length;
|
||||
|
||||
static struct checkout state = {
|
||||
.base_dir = "",
|
||||
.base_dir_len = 0,
|
||||
|
@ -69,6 +72,10 @@ static int checkout_all(void)
|
|||
struct cache_entry *ce = active_cache[i];
|
||||
if (ce_stage(ce))
|
||||
continue;
|
||||
if (prefix && *prefix &&
|
||||
( ce_namelen(ce) <= prefix_length ||
|
||||
memcmp(prefix, ce->name, prefix_length) ))
|
||||
continue;
|
||||
if (checkout_entry(ce, &state) < 0)
|
||||
errs++;
|
||||
}
|
||||
|
@ -91,6 +98,9 @@ int main(int argc, char **argv)
|
|||
int newfd = -1;
|
||||
int all = 0;
|
||||
|
||||
prefix = setup_git_directory();
|
||||
prefix_length = prefix ? strlen(prefix) : 0;
|
||||
|
||||
if (read_cache() < 0) {
|
||||
die("invalid cache");
|
||||
}
|
||||
|
@ -155,7 +165,7 @@ int main(int argc, char **argv)
|
|||
|
||||
if (all)
|
||||
die("git-checkout-index: don't mix '--all' and explicit filenames");
|
||||
checkout_file(arg);
|
||||
checkout_file(prefix_path(prefix, prefix_length, arg));
|
||||
}
|
||||
|
||||
if (all)
|
||||
|
|
|
@ -271,6 +271,8 @@ int main(int argc, char **argv)
|
|||
int fd[2];
|
||||
pid_t pid;
|
||||
|
||||
setup_git_directory();
|
||||
|
||||
nr_heads = 0;
|
||||
heads = NULL;
|
||||
for (i = 1; i < argc; i++) {
|
||||
|
|
|
@ -91,6 +91,8 @@ int main(int argc, char **argv)
|
|||
if (argc < 2 || get_sha1_hex(argv[1], tree_sha1) < 0)
|
||||
usage(commit_tree_usage);
|
||||
|
||||
setup_git_directory();
|
||||
|
||||
check_valid(tree_sha1, "tree");
|
||||
for (i = 2; i < argc; i += 2) {
|
||||
char *a, *b;
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int gitsetenv(const char *name, const char *value, int replace)
|
||||
{
|
||||
int out;
|
||||
size_t namelen, valuelen;
|
||||
char *envstr;
|
||||
|
||||
if (!name || !value) return -1;
|
||||
if (!replace) {
|
||||
char *oldval = NULL;
|
||||
oldval = getenv(name);
|
||||
if (oldval) return 0;
|
||||
}
|
||||
|
||||
namelen = strlen(name);
|
||||
valuelen = strlen(value);
|
||||
envstr = malloc((namelen + valuelen + 2) * sizeof(char));
|
||||
if (!envstr) return -1;
|
||||
|
||||
memcpy(envstr, name, namelen);
|
||||
envstr[namelen] = '=';
|
||||
memcpy(envstr + namelen + 1, value, valuelen);
|
||||
envstr[namelen + valuelen + 1] = 0;
|
||||
|
||||
out = putenv(envstr);
|
||||
|
||||
free(envstr);
|
||||
return out;
|
||||
}
|
21
config.c
21
config.c
|
@ -11,6 +11,7 @@
|
|||
#define MAXNAME (256)
|
||||
|
||||
static FILE *config_file;
|
||||
static const char *config_file_name;
|
||||
static int config_linenr;
|
||||
static int get_next_char(void)
|
||||
{
|
||||
|
@ -186,7 +187,7 @@ static int git_parse_file(config_fn_t fn)
|
|||
if (get_value(fn, var, baselen+1) < 0)
|
||||
break;
|
||||
}
|
||||
die("bad config file line %d", config_linenr);
|
||||
die("bad config file line %d in %s", config_linenr, config_file_name);
|
||||
}
|
||||
|
||||
int git_config_int(const char *name, const char *value)
|
||||
|
@ -197,7 +198,7 @@ int git_config_int(const char *name, const char *value)
|
|||
if (!*end)
|
||||
return val;
|
||||
}
|
||||
die("bad config value for '%s'", name);
|
||||
die("bad config value for '%s' in %s", name, config_file_name);
|
||||
}
|
||||
|
||||
int git_config_bool(const char *name, const char *value)
|
||||
|
@ -236,25 +237,37 @@ int git_default_config(const char *var, const char *value)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(var, "i18n.commitencoding")) {
|
||||
strncpy(git_commit_encoding, value, sizeof(git_commit_encoding));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Add other config variables here.. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_config(config_fn_t fn)
|
||||
int git_config_from_file(config_fn_t fn, const char *filename)
|
||||
{
|
||||
int ret;
|
||||
FILE *f = fopen(git_path("config"), "r");
|
||||
FILE *f = fopen(filename, "r");
|
||||
|
||||
ret = -1;
|
||||
if (f) {
|
||||
config_file = f;
|
||||
config_file_name = filename;
|
||||
config_linenr = 1;
|
||||
ret = git_parse_file(fn);
|
||||
fclose(f);
|
||||
config_file_name = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int git_config(config_fn_t fn)
|
||||
{
|
||||
return git_config_from_file(fn, git_path("config"));
|
||||
}
|
||||
|
||||
/*
|
||||
* Find all the stuff for git_config_set() below.
|
||||
*/
|
||||
|
|
|
@ -316,6 +316,8 @@ int main(int argc, char **argv)
|
|||
unsigned char sha1[20];
|
||||
struct entry *entry;
|
||||
|
||||
setup_git_directory();
|
||||
|
||||
if (argc != 2 || get_sha1(argv[1], sha1))
|
||||
usage("git-convert-objects <sha1>");
|
||||
|
||||
|
|
64
daemon.c
64
daemon.c
|
@ -82,9 +82,63 @@ static void loginfo(const char *err, ...)
|
|||
va_end(params);
|
||||
}
|
||||
|
||||
static int avoid_alias(char *p)
|
||||
{
|
||||
int sl, ndot;
|
||||
|
||||
/*
|
||||
* This resurrects the belts and suspenders paranoia check by HPA
|
||||
* done in <435560F7.4080006@zytor.com> thread, now enter_repo()
|
||||
* does not do getcwd() based path canonicalizations.
|
||||
*
|
||||
* sl becomes true immediately after seeing '/' and continues to
|
||||
* be true as long as dots continue after that without intervening
|
||||
* non-dot character.
|
||||
*/
|
||||
if (!p || (*p != '/' && *p != '~'))
|
||||
return -1;
|
||||
sl = 1; ndot = 0;
|
||||
p++;
|
||||
|
||||
while (1) {
|
||||
char ch = *p++;
|
||||
if (sl) {
|
||||
if (ch == '.')
|
||||
ndot++;
|
||||
else if (ch == '/') {
|
||||
if (ndot < 3)
|
||||
/* reject //, /./ and /../ */
|
||||
return -1;
|
||||
ndot = 0;
|
||||
}
|
||||
else if (ch == 0) {
|
||||
if (0 < ndot && ndot < 3)
|
||||
/* reject /.$ and /..$ */
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
sl = ndot = 0;
|
||||
}
|
||||
else if (ch == 0)
|
||||
return 0;
|
||||
else if (ch == '/') {
|
||||
sl = 1;
|
||||
ndot = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char *path_ok(char *dir)
|
||||
{
|
||||
char *path = enter_repo(dir, strict_paths);
|
||||
char *path;
|
||||
|
||||
if (avoid_alias(dir)) {
|
||||
logerror("'%s': aliased", dir);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
path = enter_repo(dir, strict_paths);
|
||||
|
||||
if (!path) {
|
||||
logerror("'%s': unable to chdir or not a git archive", dir);
|
||||
|
@ -96,9 +150,11 @@ static char *path_ok(char *dir)
|
|||
int pathlen = strlen(path);
|
||||
|
||||
/* The validation is done on the paths after enter_repo
|
||||
* canonicalization, so whitelist should be written in
|
||||
* terms of real pathnames (i.e. after ~user is expanded
|
||||
* and symlinks resolved).
|
||||
* appends optional {.git,.git/.git} and friends, but
|
||||
* it does not use getcwd(). So if your /pub is
|
||||
* a symlink to /mnt/pub, you can whitelist /pub and
|
||||
* do not have to say /mnt/pub.
|
||||
* Do not say /pub/.
|
||||
*/
|
||||
for ( pp = ok_paths ; *pp ; pp++ ) {
|
||||
int len = strlen(*pp);
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
git-core (0.99.9l-0) unstable; urgency=low
|
||||
|
||||
* GIT 0.99.9l aka 1.0rc4
|
||||
|
||||
-- Junio C Hamano <junkio@cox.net> Sat, 3 Dec 2005 23:45:23 -0800
|
||||
|
||||
git-core (0.99.9k-0) unstable; urgency=low
|
||||
|
||||
* GIT 0.99.9k but not 1.0rc yet.
|
||||
|
|
43
diff-files.c
43
diff-files.c
|
@ -7,12 +7,12 @@
|
|||
#include "diff.h"
|
||||
|
||||
static const char diff_files_usage[] =
|
||||
"git-diff-files [-q] "
|
||||
"[<common diff options>] [<path>...]"
|
||||
"git-diff-files [-q] [-0/-1/2/3] [<common diff options>] [<path>...]"
|
||||
COMMON_DIFF_OPTIONS_HELP;
|
||||
|
||||
static struct diff_options diff_options;
|
||||
static int silent = 0;
|
||||
static int diff_unmerged_stage = 2;
|
||||
|
||||
static void show_unmerge(const char *path)
|
||||
{
|
||||
|
@ -46,7 +46,21 @@ int main(int argc, const char **argv)
|
|||
argc--;
|
||||
break;
|
||||
}
|
||||
if (!strcmp(argv[1], "-q"))
|
||||
if (!strcmp(argv[1], "-0"))
|
||||
diff_unmerged_stage = 0;
|
||||
else if (!strcmp(argv[1], "-1"))
|
||||
diff_unmerged_stage = 1;
|
||||
else if (!strcmp(argv[1], "-2"))
|
||||
diff_unmerged_stage = 2;
|
||||
else if (!strcmp(argv[1], "-3"))
|
||||
diff_unmerged_stage = 3;
|
||||
else if (!strcmp(argv[1], "--base"))
|
||||
diff_unmerged_stage = 1;
|
||||
else if (!strcmp(argv[1], "--ours"))
|
||||
diff_unmerged_stage = 2;
|
||||
else if (!strcmp(argv[1], "--theirs"))
|
||||
diff_unmerged_stage = 3;
|
||||
else if (!strcmp(argv[1], "-q"))
|
||||
silent = 1;
|
||||
else if (!strcmp(argv[1], "-r"))
|
||||
; /* no-op */
|
||||
|
@ -95,11 +109,26 @@ int main(int argc, const char **argv)
|
|||
|
||||
if (ce_stage(ce)) {
|
||||
show_unmerge(ce->name);
|
||||
while (i < entries &&
|
||||
!strcmp(ce->name, active_cache[i]->name))
|
||||
while (i < entries) {
|
||||
struct cache_entry *nce = active_cache[i];
|
||||
|
||||
if (strcmp(ce->name, nce->name))
|
||||
break;
|
||||
/* diff against the proper unmerged stage */
|
||||
if (ce_stage(nce) == diff_unmerged_stage)
|
||||
ce = nce;
|
||||
i++;
|
||||
i--; /* compensate for loop control increments */
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* Compensate for loop update
|
||||
*/
|
||||
i--;
|
||||
/*
|
||||
* Show the diff for the 'ce' if we found the one
|
||||
* from the desired stage.
|
||||
*/
|
||||
if (ce_stage(ce) != diff_unmerged_stage)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lstat(ce->name, &st) < 0) {
|
||||
|
|
|
@ -13,6 +13,8 @@ char git_default_email[MAX_GITNAME];
|
|||
char git_default_name[MAX_GITNAME];
|
||||
int trust_executable_bit = 1;
|
||||
int only_use_symrefs = 0;
|
||||
int repository_format_version = 0;
|
||||
char git_commit_encoding[MAX_ENCODING_LENGTH] = "utf-8";
|
||||
|
||||
static char *git_dir, *git_object_dir, *git_index_file, *git_refs_dir,
|
||||
*git_graft_file;
|
||||
|
|
|
@ -424,6 +424,8 @@ int main(int argc, char **argv)
|
|||
int fd[2];
|
||||
pid_t pid;
|
||||
|
||||
setup_git_directory();
|
||||
|
||||
nr_heads = 0;
|
||||
heads = NULL;
|
||||
for (i = 1; i < argc; i++) {
|
||||
|
|
|
@ -431,6 +431,8 @@ int main(int argc, char **argv)
|
|||
{
|
||||
int i, heads;
|
||||
|
||||
setup_git_directory();
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
#!/bin/sh
|
||||
|
||||
die () {
|
||||
echo >&2 "$*"
|
||||
exit 1
|
||||
}
|
||||
|
||||
usage() {
|
||||
die "usage: git add [-n] [-v] <file>..."
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ do
|
|||
-k) keep_subject=-k ;;
|
||||
-q) query_apply=t ;;
|
||||
-c) continue="$2"; resume=f; shift ;;
|
||||
-m) fallback_3way=t ;;
|
||||
-m) fall_back_3way=t ;;
|
||||
-*) usage ;;
|
||||
*) break ;;
|
||||
esac
|
||||
|
|
|
@ -120,26 +120,36 @@ git-apply --index "$PATCHFILE" || {
|
|||
O_OBJECT=`cd "$GIT_OBJECT_DIRECTORY" && pwd`
|
||||
rm -fr .patch-merge-*
|
||||
|
||||
if git-apply -z --index-info "$PATCHFILE" \
|
||||
>.patch-merge-index-info 2>/dev/null &&
|
||||
GIT_INDEX_FILE=.patch-merge-tmp-index \
|
||||
git-update-index -z --index-info <.patch-merge-index-info &&
|
||||
GIT_INDEX_FILE=.patch-merge-tmp-index \
|
||||
git-write-tree >.patch-merge-tmp-base &&
|
||||
(
|
||||
mkdir .patch-merge-tmp-dir &&
|
||||
cd .patch-merge-tmp-dir &&
|
||||
GIT_INDEX_FILE="../.patch-merge-tmp-index" \
|
||||
GIT_OBJECT_DIRECTORY="$O_OBJECT" \
|
||||
git-apply $binary --index
|
||||
) <"$PATCHFILE"
|
||||
then
|
||||
echo Using index info to reconstruct a base tree...
|
||||
mv .patch-merge-tmp-base .patch-merge-base
|
||||
mv .patch-merge-tmp-index .patch-merge-index
|
||||
else
|
||||
(
|
||||
N=10
|
||||
|
||||
# if the patch records the base tree...
|
||||
sed -ne '
|
||||
/^diff /q
|
||||
/^applies-to: \([0-9a-f]*\)$/{
|
||||
s//\1/p
|
||||
q
|
||||
}
|
||||
' "$PATCHFILE"
|
||||
|
||||
# or hoping the patch is against our recent commits...
|
||||
# Otherwise, try nearby trees that can be used to apply the
|
||||
# patch.
|
||||
git-rev-list --max-count=$N HEAD
|
||||
|
||||
# or hoping the patch is against known tags...
|
||||
git-ls-remote --tags .
|
||||
) |
|
||||
while read base junk
|
||||
do
|
||||
while read base junk
|
||||
do
|
||||
# Try it if we have it as a tree.
|
||||
git-cat-file tree "$base" >/dev/null 2>&1 || continue
|
||||
|
||||
|
@ -155,7 +165,8 @@ git-apply --index "$PATCHFILE" || {
|
|||
mv ../.patch-merge-tmp-index ../.patch-merge-index &&
|
||||
echo "$base" >../.patch-merge-base
|
||||
) <"$PATCHFILE" 2>/dev/null && break
|
||||
done
|
||||
done
|
||||
fi
|
||||
|
||||
test -f .patch-merge-index &&
|
||||
his_tree=$(GIT_INDEX_FILE=.patch-merge-index git-write-tree) &&
|
||||
|
|
|
@ -1,9 +1,19 @@
|
|||
#!/bin/sh
|
||||
. git-sh-setup
|
||||
|
||||
sq() {
|
||||
perl -e '
|
||||
for (@ARGV) {
|
||||
s/'\''/'\'\\\\\'\''/g;
|
||||
print " '\''$_'\''";
|
||||
}
|
||||
print "\n";
|
||||
' "$@"
|
||||
}
|
||||
|
||||
usage() {
|
||||
echo >&2 'usage: git bisect [start|bad|good|next|reset|visualize]
|
||||
git bisect start reset bisect state and start bisection.
|
||||
git bisect start [<pathspec>] reset bisect state and start bisection.
|
||||
git bisect bad [<rev>] mark <rev> a known-bad revision.
|
||||
git bisect good [<rev>...] mark <rev>... known-good revisions.
|
||||
git bisect next find next bisection to test and check it out.
|
||||
|
@ -33,7 +43,6 @@ bisect_autostart() {
|
|||
}
|
||||
|
||||
bisect_start() {
|
||||
case "$#" in 0) ;; *) usage ;; esac
|
||||
#
|
||||
# Verify HEAD. If we were bisecting before this, reset to the
|
||||
# top-of-line master first!
|
||||
|
@ -57,7 +66,11 @@ bisect_start() {
|
|||
rm -f "$GIT_DIR/refs/heads/bisect"
|
||||
rm -rf "$GIT_DIR/refs/bisect/"
|
||||
mkdir "$GIT_DIR/refs/bisect"
|
||||
echo "git-bisect start" >"$GIT_DIR/BISECT_LOG"
|
||||
{
|
||||
echo -n "git-bisect start"
|
||||
sq "$@"
|
||||
} >"$GIT_DIR/BISECT_LOG"
|
||||
sq "$@" >"$GIT_DIR/BISECT_NAMES"
|
||||
}
|
||||
|
||||
bisect_bad() {
|
||||
|
@ -121,7 +134,7 @@ bisect_next() {
|
|||
bad=$(git-rev-parse --verify refs/bisect/bad) &&
|
||||
good=$(git-rev-parse --sq --revs-only --not \
|
||||
$(cd "$GIT_DIR" && ls refs/bisect/good-*)) &&
|
||||
rev=$(eval "git-rev-list --bisect $good $bad") || exit
|
||||
rev=$(eval "git-rev-list --bisect $good $bad -- $(cat $GIT_DIR/BISECT_NAMES)") || exit
|
||||
if [ -z "$rev" ]; then
|
||||
echo "$bad was both good and bad"
|
||||
exit 1
|
||||
|
@ -131,7 +144,7 @@ bisect_next() {
|
|||
git-diff-tree --pretty $rev
|
||||
exit 0
|
||||
fi
|
||||
nr=$(eval "git-rev-list $rev $good" | wc -l) || exit
|
||||
nr=$(eval "git-rev-list $rev $good -- $(cat $GIT_DIR/BISECT_NAMES)" | wc -l) || exit
|
||||
echo "Bisecting: $nr revisions left to test after this"
|
||||
echo "$rev" > "$GIT_DIR/refs/heads/new-bisect"
|
||||
git checkout new-bisect || exit
|
||||
|
@ -142,7 +155,8 @@ bisect_next() {
|
|||
|
||||
bisect_visualize() {
|
||||
bisect_next_check fail
|
||||
gitk bisect/bad --not `cd "$GIT_DIR/refs" && echo bisect/good-*`
|
||||
not=`cd "$GIT_DIR/refs" && echo bisect/good-*`
|
||||
eval gitk bisect/bad --not $not -- $(cat "$GIT_DIR/BISECT_NAMES")
|
||||
}
|
||||
|
||||
bisect_reset() {
|
||||
|
@ -173,7 +187,8 @@ bisect_replay () {
|
|||
test "$bisect" = "git-bisect" || continue
|
||||
case "$command" in
|
||||
start)
|
||||
bisect_start
|
||||
cmd="bisect_start $rev"
|
||||
eval "$cmd"
|
||||
;;
|
||||
good)
|
||||
echo "$rev" >"$GIT_DIR/refs/bisect/good-$rev"
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
#!/bin/sh
|
||||
|
||||
. git-sh-setup
|
||||
GIT_DIR=`git-rev-parse --git-dir` || exit $?
|
||||
|
||||
die () {
|
||||
echo >&2 "$*"
|
||||
exit 1
|
||||
}
|
||||
|
||||
usage () {
|
||||
echo >&2 "usage: $(basename $0)"' [-d <branch>] | [[-f] <branch> [start-point]]
|
||||
|
@ -12,8 +17,7 @@ If two arguments, create a new branch <branchname> based off of <start-point>.
|
|||
exit 1
|
||||
}
|
||||
|
||||
headref=$(GIT_DIR="$GIT_DIR" git-symbolic-ref HEAD |
|
||||
sed -e 's|^refs/heads/||')
|
||||
headref=$(git-symbolic-ref HEAD | sed -e 's|^refs/heads/||')
|
||||
|
||||
delete_branch () {
|
||||
option="$1"
|
||||
|
@ -114,4 +118,3 @@ then
|
|||
fi
|
||||
fi
|
||||
git update-ref "refs/heads/$branchname" $rev
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@ while
|
|||
*,-n) no_checkout=yes ;;
|
||||
*,-l|*,--l|*,--lo|*,--loc|*,--loca|*,--local) use_local=yes ;;
|
||||
*,-s|*,--s|*,--sh|*,--sha|*,--shar|*,--share|*,--shared)
|
||||
local_shared=yes ;;
|
||||
local_shared=yes; use_local=yes ;;
|
||||
*,-q|*,--quiet) quiet=-q ;;
|
||||
1,-u|1,--upload-pack) usage ;;
|
||||
*,-u|*,--upload-pack)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# Copyright (c) 2005 Junio C Hamano
|
||||
#
|
||||
|
||||
. git-sh-setup
|
||||
GIT_DIR=`git-rev-parse --git-dir` || exit $?
|
||||
|
||||
dc </dev/null 2>/dev/null || {
|
||||
# This is not a real DC at all -- it just knows how
|
||||
|
|
20
git-diff.sh
20
git-diff.sh
|
@ -7,7 +7,10 @@ rev=$(git-rev-parse --revs-only --no-flags --sq "$@") || exit
|
|||
flags=$(git-rev-parse --no-revs --flags --sq "$@")
|
||||
files=$(git-rev-parse --no-revs --no-flags --sq "$@")
|
||||
|
||||
: ${flags:="'-M' '-p'"}
|
||||
die () {
|
||||
echo >&2 "$*"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# I often say 'git diff --cached -p' and get scolded by git-diff-files, but
|
||||
# obviously I mean 'git diff --cached -p HEAD' in that case.
|
||||
|
@ -20,6 +23,21 @@ case "$rev" in
|
|||
esac
|
||||
esac
|
||||
|
||||
# If we do not have --name-status, --name-only nor -r, default to -p.
|
||||
# If we do not have -B nor -C, default to -M.
|
||||
case " $flags " in
|
||||
*" '--name-status' "* | *" '--name-only' "* | *" '-r' "* )
|
||||
;;
|
||||
*)
|
||||
flags="$flags'-p' " ;;
|
||||
esac
|
||||
case " $flags " in
|
||||
*" '-"[BCM]* | *" '--find-copies-harder' "*)
|
||||
;; # something like -M50.
|
||||
*)
|
||||
flags="$flags'-M' " ;;
|
||||
esac
|
||||
|
||||
case "$rev" in
|
||||
?*' '?*' '?*)
|
||||
echo >&2 "I don't understand"
|
||||
|
|
|
@ -5,6 +5,10 @@
|
|||
|
||||
. git-sh-setup
|
||||
|
||||
# Force diff to run in C locale.
|
||||
LANG=C LC_ALL=C
|
||||
export LANG LC_ALL
|
||||
|
||||
usage () {
|
||||
echo >&2 "usage: $0"' [-n] [-o dir | --stdout] [--keep-subject] [--mbox]
|
||||
[--check] [--signoff] [-<diff options>...]
|
||||
|
@ -202,7 +206,7 @@ process_one () {
|
|||
;;
|
||||
esac
|
||||
|
||||
eval "$(LANG=C LC_ALL=C sed -ne "$whosepatchScript" $commsg)"
|
||||
eval "$(sed -ne "$whosepatchScript" $commsg)"
|
||||
test "$author,$au" = ",$me" || {
|
||||
mailScript="$mailScript"'
|
||||
a\
|
||||
|
@ -238,9 +242,8 @@ Date: '"$ad"
|
|||
echo
|
||||
git-diff-tree -p $diff_opts "$commit" | git-apply --stat --summary
|
||||
echo
|
||||
git-cat-file commit "$commit^" | sed -e 's/^tree /applies-to: /' -e q
|
||||
git-diff-tree -p $diff_opts "$commit"
|
||||
echo "---"
|
||||
echo "-- "
|
||||
echo "@@GIT_VERSION@@"
|
||||
|
||||
case "$mbox" in
|
||||
|
@ -268,7 +271,7 @@ do
|
|||
file=`printf '%04d-%stxt' $i "$title"`
|
||||
if test '' = "$stdout"
|
||||
then
|
||||
echo "* $file"
|
||||
echo "$file"
|
||||
process_one >"$outdir$file"
|
||||
if test t = "$check"
|
||||
then
|
||||
|
@ -279,7 +282,7 @@ do
|
|||
:
|
||||
fi
|
||||
else
|
||||
echo >&2 "* $file"
|
||||
echo >&2 "$file"
|
||||
process_one
|
||||
fi
|
||||
i=`expr "$i" + 1`
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#!/bin/sh
|
||||
|
||||
. git-sh-setup
|
||||
|
||||
GIT_DIR=`git-rev-parse --git-dir` || exit $?
|
||||
laf="$GIT_DIR/lost-found"
|
||||
rm -fr "$laf" && mkdir -p "$laf/commit" "$laf/other" || exit
|
||||
|
||||
|
|
|
@ -6,6 +6,11 @@ usage () {
|
|||
exit 1;
|
||||
}
|
||||
|
||||
die () {
|
||||
echo >&2 "$*"
|
||||
exit 1
|
||||
}
|
||||
|
||||
while case "$#" in 0) break;; esac
|
||||
do
|
||||
case "$1" in
|
||||
|
|
|
@ -8,6 +8,11 @@
|
|||
LF='
|
||||
'
|
||||
|
||||
die () {
|
||||
echo >&2 "$*"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# The first parameters up to -- are merge bases; the rest are heads.
|
||||
bases= head= remotes= sep_seen=
|
||||
for arg
|
||||
|
|
|
@ -26,7 +26,7 @@ case "${1:-.}${2:-.}${3:-.}" in
|
|||
fi
|
||||
if test -f "$4"; then
|
||||
rm -f -- "$4" &&
|
||||
rmdir -p "$(expr "$4" : '\(.*\)/')" 2>/dev/null
|
||||
rmdir -p "$(expr "$4" : '\(.*\)/')" 2>/dev/null || :
|
||||
fi &&
|
||||
exec git-update-index --remove -- "$4"
|
||||
;;
|
||||
|
@ -58,6 +58,14 @@ case "${1:-.}${2:-.}${3:-.}" in
|
|||
# Modified in both, but differently.
|
||||
#
|
||||
"$1$2$3" | ".$2$3")
|
||||
|
||||
case ",$6,$7," in
|
||||
*,120000,*)
|
||||
echo "ERROR: $4: Not merging symbolic link changes."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
src2=`git-unpack-file $3`
|
||||
case "$1" in
|
||||
'')
|
||||
|
@ -79,10 +87,12 @@ case "${1:-.}${2:-.}${3:-.}" in
|
|||
;;
|
||||
esac
|
||||
|
||||
# We reset the index to the first branch, making
|
||||
# git-diff-file useful
|
||||
git-update-index --add --cacheinfo "$6" "$2" "$4"
|
||||
git-checkout-index -u -f -- "$4" &&
|
||||
# Create the working tree file, with the correct permission bits.
|
||||
# we can not rely on the fact that our tree has the path, because
|
||||
# we allow the merge to be done in an unchecked-out working tree.
|
||||
rm -f "$4" &&
|
||||
git-cat-file blob "$2" >"$4" &&
|
||||
case "$6" in *7??) chmod +x "$4" ;; esac &&
|
||||
merge "$4" "$orig" "$src2"
|
||||
ret=$?
|
||||
rm -f -- "$orig" "$src2"
|
||||
|
|
|
@ -98,7 +98,7 @@ getFilesRE = re.compile(r'^([0-7]+) (\S+) ([0-9a-f]{40})\t(.*)$', re.S)
|
|||
def getFilesAndDirs(tree):
|
||||
files = Set()
|
||||
dirs = Set()
|
||||
out = runProgram(['git-ls-tree', '-r', '-z', tree])
|
||||
out = runProgram(['git-ls-tree', '-r', '-z', '-t', tree])
|
||||
for l in out.split('\0'):
|
||||
m = getFilesRE.match(l)
|
||||
if m:
|
||||
|
@ -828,8 +828,6 @@ def processEntry(entry, branch1Name, branch2Name):
|
|||
if cacheOnly:
|
||||
updateFile(False, sha, mode, path)
|
||||
else:
|
||||
updateFileExt(aSha, aMode, path,
|
||||
updateCache=True, updateWd=False)
|
||||
updateFileExt(sha, mode, path, updateCache=False, updateWd=True)
|
||||
else:
|
||||
die("ERROR: Fatal merge failure, shouldn't happen.")
|
||||
|
|
|
@ -273,7 +273,8 @@ fi
|
|||
case "$best_strategy" in
|
||||
'')
|
||||
restorestate
|
||||
die "No merge strategy handled the merge."
|
||||
echo >&2 "No merge strategy handled the merge."
|
||||
exit 2
|
||||
;;
|
||||
"$wt_strategy")
|
||||
# We already have its result in the working tree.
|
||||
|
|
94
git-mv.perl
94
git-mv.perl
|
@ -13,35 +13,15 @@ use Getopt::Std;
|
|||
|
||||
sub usage() {
|
||||
print <<EOT;
|
||||
$0 [-f] [-n] <source> <dest>
|
||||
$0 [-f] [-k] [-n] <source> ... <dest directory>
|
||||
|
||||
In the first form, source must exist and be either a file,
|
||||
symlink or directory, dest must not exist. It renames source to dest.
|
||||
In the second form, the last argument has to be an existing
|
||||
directory; the given sources will be moved into this directory.
|
||||
|
||||
Updates the git cache to reflect the change.
|
||||
Use "git commit" to make the change permanently.
|
||||
|
||||
Options:
|
||||
-f Force renaming/moving, even if target exists
|
||||
-k Continue on error by skipping
|
||||
not-existing or not revision-controlled source
|
||||
-n Do nothing; show what would happen
|
||||
$0 [-f] [-n] <source> <destination>
|
||||
$0 [-f] [-n] [-k] <source> ... <destination directory>
|
||||
EOT
|
||||
exit(1);
|
||||
}
|
||||
|
||||
# Sanity checks:
|
||||
my $GIT_DIR = $ENV{'GIT_DIR'} || ".git";
|
||||
|
||||
unless ( -d $GIT_DIR && -d $GIT_DIR . "/objects" &&
|
||||
-d $GIT_DIR . "/objects/" && -d $GIT_DIR . "/refs") {
|
||||
print "Git repository not found.";
|
||||
usage();
|
||||
}
|
||||
|
||||
my $GIT_DIR = `git rev-parse --git-dir`;
|
||||
exit 1 if $?; # rev-parse would have given "not a git dir" message.
|
||||
chomp($GIT_DIR);
|
||||
|
||||
our ($opt_n, $opt_f, $opt_h, $opt_k, $opt_v);
|
||||
getopts("hnfkv") || usage;
|
||||
|
@ -70,7 +50,7 @@ else {
|
|||
print "Error: moving to directory '"
|
||||
. $ARGV[$argCount-1]
|
||||
. "' not possible; not exisiting\n";
|
||||
usage;
|
||||
exit(1);
|
||||
}
|
||||
@srcArgs = ($ARGV[0]);
|
||||
@dstArgs = ($ARGV[1]);
|
||||
|
@ -122,7 +102,7 @@ while(scalar @srcArgs > 0) {
|
|||
}
|
||||
}
|
||||
|
||||
if (($bad eq "") && ($src eq $dstDir)) {
|
||||
if (($bad eq "") && ($dst =~ /^$safesrc\//)) {
|
||||
$bad = "can not move directory '$src' into itself";
|
||||
}
|
||||
|
||||
|
@ -148,7 +128,7 @@ while(scalar @srcArgs > 0) {
|
|||
next;
|
||||
}
|
||||
print "Error: $bad\n";
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
push @srcs, $src;
|
||||
push @dsts, $dst;
|
||||
|
@ -156,14 +136,22 @@ while(scalar @srcArgs > 0) {
|
|||
|
||||
# Final pass: rename/move
|
||||
my (@deletedfiles,@addedfiles,@changedfiles);
|
||||
$bad = "";
|
||||
while(scalar @srcs > 0) {
|
||||
$src = shift @srcs;
|
||||
$dst = shift @dsts;
|
||||
|
||||
if ($opt_n || $opt_v) { print "Renaming $src to $dst\n"; }
|
||||
if (!$opt_n) {
|
||||
rename($src,$dst)
|
||||
or die "rename failed: $!";
|
||||
if (!rename($src,$dst)) {
|
||||
$bad = "renaming '$src' failed: $!";
|
||||
if ($opt_k) {
|
||||
print "Warning: skipped: $bad\n";
|
||||
$bad = "";
|
||||
next;
|
||||
}
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
$safesrc = quotemeta($src);
|
||||
|
@ -187,20 +175,44 @@ while(scalar @srcs > 0) {
|
|||
}
|
||||
|
||||
if ($opt_n) {
|
||||
if (@changedfiles) {
|
||||
print "Changed : ". join(", ", @changedfiles) ."\n";
|
||||
}
|
||||
if (@addedfiles) {
|
||||
print "Adding : ". join(", ", @addedfiles) ."\n";
|
||||
}
|
||||
if (@deletedfiles) {
|
||||
print "Deleting : ". join(", ", @deletedfiles) ."\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
my $rc;
|
||||
if (scalar @changedfiles >0) {
|
||||
$rc = system("git-update-index","--",@changedfiles);
|
||||
die "git-update-index failed to update changed files with code $?\n" if $rc;
|
||||
else {
|
||||
if (@changedfiles) {
|
||||
open(H, "| git-update-index -z --stdin")
|
||||
or die "git-update-index failed to update changed files with code $!\n";
|
||||
foreach my $fileName (@changedfiles) {
|
||||
print H "$fileName\0";
|
||||
}
|
||||
close(H);
|
||||
}
|
||||
if (@addedfiles) {
|
||||
open(H, "| git-update-index --add -z --stdin")
|
||||
or die "git-update-index failed to add new names with code $!\n";
|
||||
foreach my $fileName (@addedfiles) {
|
||||
print H "$fileName\0";
|
||||
}
|
||||
close(H);
|
||||
}
|
||||
if (@deletedfiles) {
|
||||
open(H, "| git-update-index --remove -z --stdin")
|
||||
or die "git-update-index failed to remove old names with code $!\n";
|
||||
foreach my $fileName (@deletedfiles) {
|
||||
print H "$fileName\0";
|
||||
}
|
||||
close(H);
|
||||
}
|
||||
}
|
||||
if (scalar @addedfiles >0) {
|
||||
$rc = system("git-update-index","--add","--",@addedfiles);
|
||||
die "git-update-index failed to add new names with code $?\n" if $rc;
|
||||
|
||||
if ($bad ne "") {
|
||||
print "Error: $bad\n";
|
||||
exit(1);
|
||||
}
|
||||
$rc = system("git-update-index","--remove","--",@deletedfiles);
|
||||
die "git-update-index failed to remove old names with code $?\n" if $rc;
|
||||
|
|
|
@ -5,9 +5,25 @@
|
|||
|
||||
. git-sh-setup
|
||||
|
||||
# The other head is given
|
||||
# Make sure we do not have .dotest
|
||||
if mkdir .dotest
|
||||
then
|
||||
rmdir .dotest
|
||||
else
|
||||
echo >&2 '
|
||||
It seems that I cannot create a .dotest directory, and I wonder if you
|
||||
are in the middle of patch application or another rebase. If that is not
|
||||
the case, please rm -fr .dotest and run me again. I am stopping in case
|
||||
you still have something valuable there.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# The other head is given. Make sure it is valid.
|
||||
other=$(git-rev-parse --verify "$1^0") || exit
|
||||
|
||||
# Make sure we have HEAD that is valid.
|
||||
head=$(git-rev-parse --verify "HEAD^0") || exit
|
||||
|
||||
# The tree must be really really clean.
|
||||
git-update-index --refresh || exit
|
||||
diff=$(git-diff-index --cached --name-status -r HEAD)
|
||||
|
@ -23,6 +39,16 @@ case "$#" in
|
|||
git-checkout "$2" || exit
|
||||
esac
|
||||
|
||||
# If the HEAD is a proper descendant of $other, we do not even need
|
||||
# to rebase. Make sure we do not do needless rebase. In such a
|
||||
# case, merge-base should be the same as "$other".
|
||||
mb=$(git-merge-base "$other" "$head")
|
||||
if test "$mb" = "$other"
|
||||
then
|
||||
echo >&2 "Current branch `git-symbolic-ref HEAD` is up to date."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Rewind the head to "$other"
|
||||
git-reset --hard "$other"
|
||||
git-format-patch -k --stdout --full-index "$other" ORIG_HEAD |
|
||||
|
|
|
@ -35,7 +35,7 @@ our($opt_h,$opt_o,$opt_v,$opt_u,$opt_C,$opt_i,$opt_m,$opt_M,$opt_t,$opt_T,$opt_b
|
|||
sub usage() {
|
||||
print STDERR <<END;
|
||||
Usage: ${\basename $0} # fetch/update GIT from SVN
|
||||
[-o branch-for-HEAD] [-h] [-v] [-l max_num_changes]
|
||||
[-o branch-for-HEAD] [-h] [-v] [-l max_rev]
|
||||
[-C GIT_repository] [-t tagname] [-T trunkname] [-b branchname]
|
||||
[-d|-D] [-i] [-u] [-s start_chg] [-m] [-M regex] [SVN_URL]
|
||||
END
|
||||
|
@ -126,8 +126,9 @@ sub file {
|
|||
package main;
|
||||
use URI;
|
||||
|
||||
my $svn = $svn_url;
|
||||
our $svn = $svn_url;
|
||||
$svn .= "/$svn_dir" if defined $svn_dir;
|
||||
my $svn2 = SVNconn->new($svn);
|
||||
$svn = SVNconn->new($svn);
|
||||
|
||||
my $lwp_ua;
|
||||
|
@ -198,7 +199,7 @@ $ENV{GIT_INDEX_FILE} = $git_index;
|
|||
my $maxnum = 0;
|
||||
my $last_rev = "";
|
||||
my $last_branch;
|
||||
my $current_rev = $opt_s-1;
|
||||
my $current_rev = $opt_s || 1;
|
||||
unless(-d $git_dir) {
|
||||
system("git-init-db");
|
||||
die "Cannot init the GIT db at $git_tree: $?\n" if $?;
|
||||
|
@ -254,7 +255,7 @@ EOM
|
|||
my($num,$branch,$ref) = split;
|
||||
$branches{$branch}{$num} = $ref;
|
||||
$branches{$branch}{"LAST"} = $ref;
|
||||
$current_rev = $num if $current_rev < $num;
|
||||
$current_rev = $num+1 if $current_rev <= $num;
|
||||
}
|
||||
close($B);
|
||||
}
|
||||
|
@ -708,17 +709,17 @@ sub commit {
|
|||
print "DONE: $revision $dest $cid\n" if $opt_v;
|
||||
}
|
||||
|
||||
my ($changed_paths, $revision, $author, $date, $message, $pool) = @_;
|
||||
sub _commit_all {
|
||||
($changed_paths, $revision, $author, $date, $message, $pool) = @_;
|
||||
sub commit_all {
|
||||
# Recursive use of the SVN connection does not work
|
||||
local $svn = $svn2;
|
||||
|
||||
my ($changed_paths, $revision, $author, $date, $message, $pool) = @_;
|
||||
my %p;
|
||||
while(my($path,$action) = each %$changed_paths) {
|
||||
$p{$path} = [ $action->action,$action->copyfrom_path, $action->copyfrom_rev, $path ];
|
||||
}
|
||||
$changed_paths = \%p;
|
||||
}
|
||||
|
||||
sub commit_all {
|
||||
my %done;
|
||||
my @col;
|
||||
my $pref;
|
||||
|
@ -734,18 +735,12 @@ sub commit_all {
|
|||
}
|
||||
}
|
||||
|
||||
while(++$current_rev <= $svn->{'maxrev'}) {
|
||||
if (defined $opt_l) {
|
||||
$opt_l--;
|
||||
if ($opt_l < 0) {
|
||||
last;
|
||||
}
|
||||
}
|
||||
my $pool=SVN::Pool->new;
|
||||
$svn->{'svn'}->get_log("/",$current_rev,$current_rev,1,1,1,\&_commit_all,$pool);
|
||||
$pool->clear;
|
||||
commit_all();
|
||||
}
|
||||
$opt_l = $svn->{'maxrev'} if not defined $opt_l or $opt_l > $svn->{'maxrev'};
|
||||
print "Fetching from $current_rev to $opt_l ...\n" if $opt_v;
|
||||
|
||||
my $pool=SVN::Pool->new;
|
||||
$svn->{'svn'}->get_log("/",$current_rev,$opt_l,0,1,1,\&commit_all,$pool);
|
||||
$pool->clear;
|
||||
|
||||
|
||||
unlink($git_index);
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
#!/bin/sh
|
||||
# Copyright (c) 2005 Linus Torvalds
|
||||
|
||||
. git-sh-setup
|
||||
GIT_DIR=`git-rev-parse --git-dir` || exit $?
|
||||
|
||||
usage () {
|
||||
echo >&2 "Usage: git-tag [-a | -s | -u <key-id>] [-f | -d] [-m <msg>] <tagname> [<head>]"
|
||||
exit 1
|
||||
}
|
||||
|
||||
die () {
|
||||
echo >&2 "$*"
|
||||
exit 1
|
||||
}
|
||||
|
||||
annotate=
|
||||
signed=
|
||||
force=
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
#!/bin/sh
|
||||
. git-sh-setup
|
||||
|
||||
GIT_DIR=`git-rev-parse --git-dir` || exit $?
|
||||
|
||||
die () {
|
||||
echo >&2 "$*"
|
||||
exit 1
|
||||
}
|
||||
|
||||
type="$(git-cat-file -t "$1" 2>/dev/null)" ||
|
||||
die "$1: no such object."
|
||||
|
@ -7,6 +13,9 @@ type="$(git-cat-file -t "$1" 2>/dev/null)" ||
|
|||
test "$type" = tag ||
|
||||
die "$1: cannot verify a non-tag object of type $type."
|
||||
|
||||
git-cat-file tag "$1" > .tmp-vtag || exit 1
|
||||
cat .tmp-vtag | sed '/-----BEGIN PGP/Q' | gpg --verify .tmp-vtag - || exit 1
|
||||
rm -f .tmp-vtag
|
||||
git-cat-file tag "$1" >"$GIT_DIR/.tmp-vtag" || exit 1
|
||||
cat "$GIT_DIR/.tmp-vtag" |
|
||||
sed '/-----BEGIN PGP/Q' |
|
||||
gpg --verify "$GIT_DIR/.tmp-vtag" - || exit 1
|
||||
rm -f "$GIT_DIR/.tmp-vtag"
|
||||
|
||||
|
|
23
git.c
23
git.c
|
@ -13,6 +13,10 @@
|
|||
# define PATH_MAX 4096
|
||||
#endif
|
||||
|
||||
#ifdef NO_SETENV
|
||||
extern int gitsetenv(char *name, char *value, int overwrite);
|
||||
#endif
|
||||
|
||||
static const char git_usage[] =
|
||||
"Usage: git [--version] [--exec-path[=GIT_EXEC_PATH]] [--help] COMMAND [ ARGS ]";
|
||||
|
||||
|
@ -283,16 +287,21 @@ int main(int argc, char **argv, char **envp)
|
|||
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]);
|
||||
len += snprintf(git_command + len, sizeof(git_command) - len,
|
||||
"/git-%s", argv[i]);
|
||||
if (sizeof(git_command) <= len) {
|
||||
fprintf(stderr, "git: command name given is too long (%d)\n", len);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* 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));
|
||||
|
||||
if (errno == ENOENT)
|
||||
usage(exec_path, "'%s' is not a git-command", argv[i]);
|
||||
|
||||
fprintf(stderr, "Failed to run command '%s': %s\n",
|
||||
git_command, strerror(errno));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
259
gitk
259
gitk
|
@ -19,7 +19,7 @@ proc gitdir {} {
|
|||
proc getcommits {rargs} {
|
||||
global commits commfd phase canv mainfont env
|
||||
global startmsecs nextupdate ncmupdate
|
||||
global ctext maincursor textcursor leftover
|
||||
global ctext maincursor textcursor leftover gitencoding
|
||||
|
||||
# check that we can find a .git directory somewhere...
|
||||
set gitdir [gitdir]
|
||||
|
@ -30,7 +30,7 @@ proc getcommits {rargs} {
|
|||
set commits {}
|
||||
set phase getcommits
|
||||
set startmsecs [clock clicks -milliseconds]
|
||||
set nextupdate [expr $startmsecs + 100]
|
||||
set nextupdate [expr {$startmsecs + 100}]
|
||||
set ncmupdate 1
|
||||
if [catch {
|
||||
set parse_args [concat --default HEAD $rargs]
|
||||
|
@ -49,7 +49,7 @@ proc getcommits {rargs} {
|
|||
exit 1
|
||||
}
|
||||
set leftover {}
|
||||
fconfigure $commfd -blocking 0 -translation lf
|
||||
fconfigure $commfd -blocking 0 -translation lf -encoding $gitencoding
|
||||
fileevent $commfd readable [list getcommitlines $commfd]
|
||||
$canv delete all
|
||||
$canv create text 3 3 -anchor nw -text "Reading commits..." \
|
||||
|
@ -74,9 +74,9 @@ proc getcommitlines {commfd} {
|
|||
}
|
||||
if {[string range $err 0 4] == "usage"} {
|
||||
set err \
|
||||
{Gitk: error reading commits: bad arguments to git-rev-list.
|
||||
(Note: arguments to gitk are passed to git-rev-list
|
||||
to allow selection of commits to be displayed.)}
|
||||
"Gitk: error reading commits: bad arguments to git-rev-list.\
|
||||
(Note: arguments to gitk are passed to git-rev-list\
|
||||
to allow selection of commits to be displayed.)"
|
||||
} else {
|
||||
set err "Error reading commits: $err"
|
||||
}
|
||||
|
@ -297,23 +297,26 @@ proc makewindow {} {
|
|||
global findtype findtypemenu findloc findstring fstring geometry
|
||||
global entries sha1entry sha1string sha1but
|
||||
global maincursor textcursor curtextcursor
|
||||
global rowctxmenu gaudydiff mergemax
|
||||
global rowctxmenu mergemax
|
||||
|
||||
menu .bar
|
||||
.bar add cascade -label "File" -menu .bar.file
|
||||
menu .bar.file
|
||||
.bar.file add command -label "Reread references" -command rereadrefs
|
||||
.bar.file add command -label "Quit" -command doquit
|
||||
menu .bar.edit
|
||||
.bar add cascade -label "Edit" -menu .bar.edit
|
||||
.bar.edit add command -label "Preferences" -command doprefs
|
||||
menu .bar.help
|
||||
.bar add cascade -label "Help" -menu .bar.help
|
||||
.bar.help add command -label "About gitk" -command about
|
||||
. configure -menu .bar
|
||||
|
||||
if {![info exists geometry(canv1)]} {
|
||||
set geometry(canv1) [expr 45 * $charspc]
|
||||
set geometry(canv2) [expr 30 * $charspc]
|
||||
set geometry(canv3) [expr 15 * $charspc]
|
||||
set geometry(canvh) [expr 25 * $linespc + 4]
|
||||
set geometry(canv1) [expr {45 * $charspc}]
|
||||
set geometry(canv2) [expr {30 * $charspc}]
|
||||
set geometry(canv3) [expr {15 * $charspc}]
|
||||
set geometry(canvh) [expr {25 * $linespc + 4}]
|
||||
set geometry(ctextw) 80
|
||||
set geometry(ctexth) 30
|
||||
set geometry(cflistw) 30
|
||||
|
@ -414,25 +417,19 @@ proc makewindow {} {
|
|||
.ctop.cdet add .ctop.cdet.left
|
||||
|
||||
$ctext tag conf filesep -font [concat $textfont bold] -back "#aaaaaa"
|
||||
if {$gaudydiff} {
|
||||
$ctext tag conf hunksep -back blue -fore white
|
||||
$ctext tag conf d0 -back "#ff8080"
|
||||
$ctext tag conf d1 -back green
|
||||
} else {
|
||||
$ctext tag conf hunksep -fore blue
|
||||
$ctext tag conf d0 -fore red
|
||||
$ctext tag conf d1 -fore "#00a000"
|
||||
$ctext tag conf m0 -fore red
|
||||
$ctext tag conf m1 -fore blue
|
||||
$ctext tag conf m2 -fore green
|
||||
$ctext tag conf m3 -fore purple
|
||||
$ctext tag conf m4 -fore brown
|
||||
$ctext tag conf mmax -fore darkgrey
|
||||
set mergemax 5
|
||||
$ctext tag conf mresult -font [concat $textfont bold]
|
||||
$ctext tag conf msep -font [concat $textfont bold]
|
||||
$ctext tag conf found -back yellow
|
||||
}
|
||||
$ctext tag conf hunksep -fore blue
|
||||
$ctext tag conf d0 -fore red
|
||||
$ctext tag conf d1 -fore "#00a000"
|
||||
$ctext tag conf m0 -fore red
|
||||
$ctext tag conf m1 -fore blue
|
||||
$ctext tag conf m2 -fore green
|
||||
$ctext tag conf m3 -fore purple
|
||||
$ctext tag conf m4 -fore brown
|
||||
$ctext tag conf mmax -fore darkgrey
|
||||
set mergemax 5
|
||||
$ctext tag conf mresult -font [concat $textfont bold]
|
||||
$ctext tag conf msep -font [concat $textfont bold]
|
||||
$ctext tag conf found -back yellow
|
||||
|
||||
frame .ctop.cdet.right
|
||||
set cflist .ctop.cdet.right.cfiles
|
||||
|
@ -533,7 +530,7 @@ proc click {w} {
|
|||
|
||||
proc savestuff {w} {
|
||||
global canv canv2 canv3 ctext cflist mainfont textfont
|
||||
global stuffsaved findmergefiles gaudydiff maxgraphpct
|
||||
global stuffsaved findmergefiles maxgraphpct
|
||||
global maxwidth
|
||||
|
||||
if {$stuffsaved} return
|
||||
|
@ -543,15 +540,14 @@ proc savestuff {w} {
|
|||
puts $f [list set mainfont $mainfont]
|
||||
puts $f [list set textfont $textfont]
|
||||
puts $f [list set findmergefiles $findmergefiles]
|
||||
puts $f [list set gaudydiff $gaudydiff]
|
||||
puts $f [list set maxgraphpct $maxgraphpct]
|
||||
puts $f [list set maxwidth $maxwidth]
|
||||
puts $f "set geometry(width) [winfo width .ctop]"
|
||||
puts $f "set geometry(height) [winfo height .ctop]"
|
||||
puts $f "set geometry(canv1) [expr [winfo width $canv]-2]"
|
||||
puts $f "set geometry(canv2) [expr [winfo width $canv2]-2]"
|
||||
puts $f "set geometry(canv3) [expr [winfo width $canv3]-2]"
|
||||
puts $f "set geometry(canvh) [expr [winfo height $canv]-2]"
|
||||
puts $f "set geometry(canv1) [expr {[winfo width $canv]-2}]"
|
||||
puts $f "set geometry(canv2) [expr {[winfo width $canv2]-2}]"
|
||||
puts $f "set geometry(canv3) [expr {[winfo width $canv3]-2}]"
|
||||
puts $f "set geometry(canvh) [expr {[winfo height $canv]-2}]"
|
||||
set wid [expr {([winfo width $ctext] - 8) \
|
||||
/ [font measure $textfont "0"]}]
|
||||
puts $f "set geometry(ctextw) $wid"
|
||||
|
@ -580,12 +576,12 @@ proc resizeclistpanes {win w} {
|
|||
set sash0 30
|
||||
}
|
||||
if {$sash1 < $sash0 + 20} {
|
||||
set sash1 [expr $sash0 + 20]
|
||||
set sash1 [expr {$sash0 + 20}]
|
||||
}
|
||||
if {$sash1 > $w - 10} {
|
||||
set sash1 [expr $w - 10]
|
||||
set sash1 [expr {$w - 10}]
|
||||
if {$sash0 > $sash1 - 20} {
|
||||
set sash0 [expr $sash1 - 20]
|
||||
set sash0 [expr {$sash1 - 20}]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -608,7 +604,7 @@ proc resizecdetpanes {win w} {
|
|||
set sash0 45
|
||||
}
|
||||
if {$sash0 > $w - 15} {
|
||||
set sash0 [expr $w - 15]
|
||||
set sash0 [expr {$w - 15}]
|
||||
}
|
||||
}
|
||||
$win sash place 0 $sash0 [lindex $s0 1]
|
||||
|
@ -819,9 +815,9 @@ proc drawcommitline {level} {
|
|||
}
|
||||
set x [xcoord $level $level $lineno]
|
||||
set y1 $canvy
|
||||
set canvy [expr $canvy + $linespc]
|
||||
set canvy [expr {$canvy + $linespc}]
|
||||
allcanvs conf -scrollregion \
|
||||
[list 0 0 0 [expr $y1 + 0.5 * $linespc + 2]]
|
||||
[list 0 0 0 [expr {$y1 + 0.5 * $linespc + 2}]]
|
||||
if {[info exists mainline($id)]} {
|
||||
lappend mainline($id) $x $y1
|
||||
if {$mainlinearrow($id) ne "none"} {
|
||||
|
@ -830,8 +826,8 @@ proc drawcommitline {level} {
|
|||
}
|
||||
drawlines $id 0 0
|
||||
set orad [expr {$linespc / 3}]
|
||||
set t [$canv create oval [expr $x - $orad] [expr $y1 - $orad] \
|
||||
[expr $x + $orad - 1] [expr $y1 + $orad - 1] \
|
||||
set t [$canv create oval [expr {$x - $orad}] [expr {$y1 - $orad}] \
|
||||
[expr {$x + $orad - 1}] [expr {$y1 + $orad - 1}] \
|
||||
-fill $ofill -outline black -width 1]
|
||||
$canv raise $t
|
||||
$canv bind $t <1> {selcanvline {} %x %y}
|
||||
|
@ -886,8 +882,8 @@ proc drawtags {id x xt y1} {
|
|||
}
|
||||
|
||||
set delta [expr {int(0.5 * ($linespc - $lthickness))}]
|
||||
set yt [expr $y1 - 0.5 * $linespc]
|
||||
set yb [expr $yt + $linespc - 1]
|
||||
set yt [expr {$y1 - 0.5 * $linespc}]
|
||||
set yb [expr {$yt + $linespc - 1}]
|
||||
set xvals {}
|
||||
set wvals {}
|
||||
foreach tag $marks {
|
||||
|
@ -900,12 +896,12 @@ proc drawtags {id x xt y1} {
|
|||
-width $lthickness -fill black -tags tag.$id]
|
||||
$canv lower $t
|
||||
foreach tag $marks x $xvals wid $wvals {
|
||||
set xl [expr $x + $delta]
|
||||
set xr [expr $x + $delta + $wid + $lthickness]
|
||||
set xl [expr {$x + $delta}]
|
||||
set xr [expr {$x + $delta + $wid + $lthickness}]
|
||||
if {[incr ntags -1] >= 0} {
|
||||
# draw a tag
|
||||
set t [$canv create polygon $x [expr $yt + $delta] $xl $yt \
|
||||
$xr $yt $xr $yb $xl $yb $x [expr $yb - $delta] \
|
||||
set t [$canv create polygon $x [expr {$yt + $delta}] $xl $yt \
|
||||
$xr $yt $xr $yb $xl $yb $x [expr {$yb - $delta}] \
|
||||
-width 1 -outline black -fill yellow -tags tag.$id]
|
||||
$canv bind $t <1> [list showtag $tag 1]
|
||||
set rowtextx($idline($id)) [expr {$xr + $linespc}]
|
||||
|
@ -916,7 +912,7 @@ proc drawtags {id x xt y1} {
|
|||
} else {
|
||||
set col "#ddddff"
|
||||
}
|
||||
set xl [expr $xl - $delta/2]
|
||||
set xl [expr {$xl - $delta/2}]
|
||||
$canv create polygon $x $yt $xr $yt $xr $yb $x $yb \
|
||||
-width 1 -outline black -fill $col -tags tag.$id
|
||||
}
|
||||
|
@ -1491,7 +1487,7 @@ proc drawgraph {} {
|
|||
|
||||
if {$displayorder == {}} return
|
||||
set startmsecs [clock clicks -milliseconds]
|
||||
set nextupdate [expr $startmsecs + 100]
|
||||
set nextupdate [expr {$startmsecs + 100}]
|
||||
set ncmupdate 1
|
||||
initgraph
|
||||
foreach id $displayorder {
|
||||
|
@ -1520,7 +1516,7 @@ proc drawrest {} {
|
|||
}
|
||||
drawmore 0
|
||||
set phase {}
|
||||
set drawmsecs [expr [clock clicks -milliseconds] - $startmsecs]
|
||||
set drawmsecs [expr {[clock clicks -milliseconds] - $startmsecs}]
|
||||
#puts "overall $drawmsecs ms for $numcommits commits"
|
||||
if {$redisplaying} {
|
||||
if {$stopped == 0 && [info exists selectedline]} {
|
||||
|
@ -1548,8 +1544,8 @@ proc findmatches {f} {
|
|||
set matches {}
|
||||
set i 0
|
||||
while {[set j [string first $foundstring $str $i]] >= 0} {
|
||||
lappend matches [list $j [expr $j+$foundstrlen-1]]
|
||||
set i [expr $j + $foundstrlen]
|
||||
lappend matches [list $j [expr {$j+$foundstrlen-1}]]
|
||||
set i [expr {$j + $foundstrlen}]
|
||||
}
|
||||
}
|
||||
return $matches
|
||||
|
@ -1630,7 +1626,7 @@ proc findselectline {l} {
|
|||
set matches [findmatches $f]
|
||||
foreach match $matches {
|
||||
set start [lindex $match 0]
|
||||
set end [expr [lindex $match 1] + 1]
|
||||
set end [expr {[lindex $match 1] + 1}]
|
||||
$ctext tag add found "1.0 + $start c" "1.0 + $end c"
|
||||
}
|
||||
}
|
||||
|
@ -1984,9 +1980,10 @@ proc markmatches {canv l str tag matches font} {
|
|||
set start [lindex $match 0]
|
||||
set end [lindex $match 1]
|
||||
if {$start > $end} continue
|
||||
set xoff [font measure $font [string range $str 0 [expr $start-1]]]
|
||||
set xlen [font measure $font [string range $str 0 [expr $end]]]
|
||||
set t [$canv create rect [expr $x0+$xoff] $y0 [expr $x0+$xlen+2] $y1 \
|
||||
set xoff [font measure $font [string range $str 0 [expr {$start-1}]]]
|
||||
set xlen [font measure $font [string range $str 0 [expr {$end}]]]
|
||||
set t [$canv create rect [expr {$x0+$xoff}] $y0 \
|
||||
[expr {$x0+$xlen+2}] $y1 \
|
||||
-outline {} -tags matches -fill yellow]
|
||||
$canv lower $t
|
||||
}
|
||||
|
@ -2078,8 +2075,8 @@ proc selectline {l isnew} {
|
|||
set ytop [expr {$y - $linespc - 1}]
|
||||
set ybot [expr {$y + $linespc + 1}]
|
||||
set wnow [$canv yview]
|
||||
set wtop [expr [lindex $wnow 0] * $ymax]
|
||||
set wbot [expr [lindex $wnow 1] * $ymax]
|
||||
set wtop [expr {[lindex $wnow 0] * $ymax}]
|
||||
set wbot [expr {[lindex $wnow 1] * $ymax}]
|
||||
set wh [expr {$wbot - $wtop}]
|
||||
set newtop $wtop
|
||||
if {$ytop < $wtop} {
|
||||
|
@ -2105,7 +2102,7 @@ proc selectline {l isnew} {
|
|||
if {$newtop < 0} {
|
||||
set newtop 0
|
||||
}
|
||||
allcanvs yview moveto [expr $newtop * 1.0 / $ymax]
|
||||
allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
|
||||
}
|
||||
|
||||
if {$isnew} {
|
||||
|
@ -2164,7 +2161,7 @@ proc selectline {l isnew} {
|
|||
$cflist delete 0 end
|
||||
$cflist insert end "Comments"
|
||||
if {$nparents($id) == 1} {
|
||||
startdiff [concat $id $parents($id)]
|
||||
startdiff $id
|
||||
} elseif {$nparents($id) > 1} {
|
||||
mergediff $id
|
||||
}
|
||||
|
@ -2173,7 +2170,7 @@ proc selectline {l isnew} {
|
|||
proc selnextline {dir} {
|
||||
global selectedline
|
||||
if {![info exists selectedline]} return
|
||||
set l [expr $selectedline + $dir]
|
||||
set l [expr {$selectedline + $dir}]
|
||||
unmarkmatches
|
||||
selectline $l 1
|
||||
}
|
||||
|
@ -2273,12 +2270,12 @@ proc contmergediff {ids} {
|
|||
# diff the child against each of the parents, and diff
|
||||
# each of the parents against the GCA.
|
||||
while 1 {
|
||||
if {[lindex $ids 0] == $diffmergeid && $diffmergegca ne {}} {
|
||||
set ids [list [lindex $ids 1] $diffmergegca]
|
||||
if {[lindex $ids 1] == $diffmergeid && $diffmergegca ne {}} {
|
||||
set ids [list $diffmergegca [lindex $ids 0]]
|
||||
} else {
|
||||
if {[incr diffpindex] >= $nparents($diffmergeid)} break
|
||||
set p [lindex $parents($diffmergeid) $diffpindex]
|
||||
set ids [list $diffmergeid $p]
|
||||
set ids [list $p $diffmergeid]
|
||||
}
|
||||
if {![info exists treediffs($ids)]} {
|
||||
set diffids $ids
|
||||
|
@ -2296,8 +2293,8 @@ proc contmergediff {ids} {
|
|||
if {$diffmergegca ne {}} {
|
||||
set files {}
|
||||
foreach p $parents($diffmergeid) {
|
||||
set gcadiffs $treediffs([list $p $diffmergegca])
|
||||
foreach f $treediffs([list $diffmergeid $p]) {
|
||||
set gcadiffs $treediffs([list $diffmergegca $p])
|
||||
foreach f $treediffs([list $p $diffmergeid]) {
|
||||
if {[lsearch -exact $files $f] < 0
|
||||
&& [lsearch -exact $gcadiffs $f] >= 0} {
|
||||
lappend files $f
|
||||
|
@ -2310,7 +2307,7 @@ proc contmergediff {ids} {
|
|||
set files $treediffs([list $diffmergeid $p])
|
||||
for {set i 1} {$i < $nparents($diffmergeid) && $files ne {}} {incr i} {
|
||||
set p [lindex $parents($diffmergeid) $i]
|
||||
set df $treediffs([list $diffmergeid $p])
|
||||
set df $treediffs([list $p $diffmergeid])
|
||||
set nf {}
|
||||
foreach f $files {
|
||||
if {[lsearch -exact $df $f] >= 0} {
|
||||
|
@ -2787,8 +2784,7 @@ proc gettreediffs {ids} {
|
|||
global treediff parents treepending
|
||||
set treepending $ids
|
||||
set treediff {}
|
||||
set id [lindex $ids 0]
|
||||
if [catch {set gdtf [open "|git-diff-tree --no-commit-id -r $id" r]}] return
|
||||
if [catch {set gdtf [open [concat | git-diff-tree --no-commit-id -r $ids] r]}] return
|
||||
fconfigure $gdtf -blocking 0
|
||||
fileevent $gdtf readable [list gettreediffline $gdtf $ids]
|
||||
}
|
||||
|
@ -2821,9 +2817,8 @@ proc getblobdiffs {ids} {
|
|||
global diffopts blobdifffd diffids env curdifftag curtagstart
|
||||
global difffilestart nextupdate diffinhdr treediffs
|
||||
|
||||
set id [lindex $ids 0]
|
||||
set env(GIT_DIFF_OPTS) $diffopts
|
||||
set cmd [list | git-diff-tree --no-commit-id -r -p -C $id]
|
||||
set cmd [concat | git-diff-tree --no-commit-id -r -p -C $ids]
|
||||
if {[catch {set bdf [open $cmd r]} err]} {
|
||||
puts "error getting diffs: $err"
|
||||
return
|
||||
|
@ -2842,7 +2837,6 @@ proc getblobdiffline {bdf ids} {
|
|||
global diffids blobdifffd ctext curdifftag curtagstart
|
||||
global diffnexthead diffnextnote difffilestart
|
||||
global nextupdate diffinhdr treediffs
|
||||
global gaudydiff
|
||||
|
||||
set n [gets $bdf line]
|
||||
if {$n < 0} {
|
||||
|
@ -2891,26 +2885,14 @@ proc getblobdiffline {bdf ids} {
|
|||
set diffinhdr 0
|
||||
} elseif {[regexp {^@@ -([0-9]+),([0-9]+) \+([0-9]+),([0-9]+) @@(.*)} \
|
||||
$line match f1l f1c f2l f2c rest]} {
|
||||
if {$gaudydiff} {
|
||||
$ctext insert end "\t" hunksep
|
||||
$ctext insert end " $f1l " d0 " $f2l " d1
|
||||
$ctext insert end " $rest \n" hunksep
|
||||
} else {
|
||||
$ctext insert end "$line\n" hunksep
|
||||
}
|
||||
$ctext insert end "$line\n" hunksep
|
||||
set diffinhdr 0
|
||||
} else {
|
||||
set x [string range $line 0 0]
|
||||
if {$x == "-" || $x == "+"} {
|
||||
set tag [expr {$x == "+"}]
|
||||
if {$gaudydiff} {
|
||||
set line [string range $line 1 end]
|
||||
}
|
||||
$ctext insert end "$line\n" d$tag
|
||||
} elseif {$x == " "} {
|
||||
if {$gaudydiff} {
|
||||
set line [string range $line 1 end]
|
||||
}
|
||||
$ctext insert end "$line\n"
|
||||
} elseif {$diffinhdr || $x == "\\"} {
|
||||
# e.g. "\ No newline at end of file"
|
||||
|
@ -2966,8 +2948,8 @@ proc setcoords {} {
|
|||
|
||||
set linespc [font metrics $mainfont -linespace]
|
||||
set charspc [font measure $mainfont "m"]
|
||||
set canvy0 [expr 3 + 0.5 * $linespc]
|
||||
set canvx0 [expr 3 + 0.5 * $linespc]
|
||||
set canvy0 [expr {3 + 0.5 * $linespc}]
|
||||
set canvx0 [expr {3 + 0.5 * $linespc}]
|
||||
set lthickness [expr {int($linespc / 9) + 1}]
|
||||
set xspc1(0) $linespc
|
||||
set xspc2 $linespc
|
||||
|
@ -3340,7 +3322,7 @@ proc doseldiff {oldid newid} {
|
|||
$ctext conf -state disabled
|
||||
$ctext tag delete Comments
|
||||
$ctext tag remove found 1.0 end
|
||||
startdiff [list $newid $oldid]
|
||||
startdiff [list $oldid $newid]
|
||||
}
|
||||
|
||||
proc mkpatch {} {
|
||||
|
@ -3635,33 +3617,94 @@ proc doquit {} {
|
|||
destroy .
|
||||
}
|
||||
|
||||
proc formatdate {d} {
|
||||
global hours nhours tfd fastdate
|
||||
proc doprefs {} {
|
||||
global maxwidth maxgraphpct diffopts findmergefiles
|
||||
global oldprefs prefstop
|
||||
|
||||
if {!$fastdate} {
|
||||
return [clock format $d -format "%Y-%m-%d %H:%M:%S"]
|
||||
set top .gitkprefs
|
||||
set prefstop $top
|
||||
if {[winfo exists $top]} {
|
||||
raise $top
|
||||
return
|
||||
}
|
||||
set hr [expr {$d / 3600}]
|
||||
set ms [expr {$d % 3600}]
|
||||
if {![info exists hours($hr)]} {
|
||||
set hours($hr) [clock format $d -format "%Y-%m-%d %H"]
|
||||
set nhours($hr) 0
|
||||
foreach v {maxwidth maxgraphpct diffopts findmergefiles} {
|
||||
set oldprefs($v) [set $v]
|
||||
}
|
||||
incr nhours($hr)
|
||||
set minsec [format "%.2d:%.2d" [expr {$ms/60}] [expr {$ms%60}]]
|
||||
return "$hours($hr):$minsec"
|
||||
toplevel $top
|
||||
wm title $top "Gitk preferences"
|
||||
label $top.ldisp -text "Commit list display options"
|
||||
grid $top.ldisp - -sticky w -pady 10
|
||||
label $top.spacer -text " "
|
||||
label $top.maxwidthl -text "Maximum graph width (lines)" \
|
||||
-font optionfont
|
||||
spinbox $top.maxwidth -from 0 -to 100 -width 4 -textvariable maxwidth
|
||||
grid $top.spacer $top.maxwidthl $top.maxwidth -sticky w
|
||||
label $top.maxpctl -text "Maximum graph width (% of pane)" \
|
||||
-font optionfont
|
||||
spinbox $top.maxpct -from 1 -to 100 -width 4 -textvariable maxgraphpct
|
||||
grid x $top.maxpctl $top.maxpct -sticky w
|
||||
checkbutton $top.findm -variable findmergefiles
|
||||
label $top.findml -text "Include merges for \"Find\" in \"Files\"" \
|
||||
-font optionfont
|
||||
grid $top.findm $top.findml - -sticky w
|
||||
label $top.ddisp -text "Diff display options"
|
||||
grid $top.ddisp - -sticky w -pady 10
|
||||
label $top.diffoptl -text "Options for diff program" \
|
||||
-font optionfont
|
||||
entry $top.diffopt -width 20 -textvariable diffopts
|
||||
grid x $top.diffoptl $top.diffopt -sticky w
|
||||
frame $top.buts
|
||||
button $top.buts.ok -text "OK" -command prefsok
|
||||
button $top.buts.can -text "Cancel" -command prefscan
|
||||
grid $top.buts.ok $top.buts.can
|
||||
grid columnconfigure $top.buts 0 -weight 1 -uniform a
|
||||
grid columnconfigure $top.buts 1 -weight 1 -uniform a
|
||||
grid $top.buts - - -pady 10 -sticky ew
|
||||
}
|
||||
|
||||
proc prefscan {} {
|
||||
global maxwidth maxgraphpct diffopts findmergefiles
|
||||
global oldprefs prefstop
|
||||
|
||||
foreach v {maxwidth maxgraphpct diffopts findmergefiles} {
|
||||
set $v $oldprefs($v)
|
||||
}
|
||||
catch {destroy $prefstop}
|
||||
unset prefstop
|
||||
}
|
||||
|
||||
proc prefsok {} {
|
||||
global maxwidth maxgraphpct
|
||||
global oldprefs prefstop
|
||||
|
||||
catch {destroy $prefstop}
|
||||
unset prefstop
|
||||
if {$maxwidth != $oldprefs(maxwidth)
|
||||
|| $maxgraphpct != $oldprefs(maxgraphpct)} {
|
||||
redisplay
|
||||
}
|
||||
}
|
||||
|
||||
proc formatdate {d} {
|
||||
return [clock format $d -format "%Y-%m-%d %H:%M:%S"]
|
||||
}
|
||||
|
||||
# defaults...
|
||||
set datemode 0
|
||||
set boldnames 0
|
||||
set diffopts "-U 5 -p"
|
||||
set wrcomcmd "git-diff-tree --stdin -p --pretty"
|
||||
|
||||
set gitencoding ""
|
||||
catch {
|
||||
set gitencoding [exec git-repo-config --get i18n.commitencoding]
|
||||
}
|
||||
if {$gitencoding == ""} {
|
||||
set gitencoding "utf-8"
|
||||
}
|
||||
|
||||
set mainfont {Helvetica 9}
|
||||
set textfont {Courier 9}
|
||||
set findmergefiles 0
|
||||
set gaudydiff 0
|
||||
set maxgraphpct 50
|
||||
set maxwidth 16
|
||||
set revlistorder 0
|
||||
|
@ -3672,15 +3715,13 @@ set colors {green red blue magenta darkgrey brown orange}
|
|||
catch {source ~/.gitk}
|
||||
|
||||
set namefont $mainfont
|
||||
if {$boldnames} {
|
||||
lappend namefont bold
|
||||
}
|
||||
|
||||
font create optionfont -family sans-serif -size -12
|
||||
|
||||
set revtreeargs {}
|
||||
foreach arg $argv {
|
||||
switch -regexp -- $arg {
|
||||
"^$" { }
|
||||
"^-b" { set boldnames 1 }
|
||||
"^-d" { set datemode 1 }
|
||||
"^-r" { set revlistorder 1 }
|
||||
default {
|
||||
|
|
|
@ -29,6 +29,8 @@ int main(int argc, char **argv)
|
|||
int i;
|
||||
const char *type = "blob";
|
||||
int write_object = 0;
|
||||
const char *prefix = NULL;
|
||||
int prefix_length = -1;
|
||||
|
||||
for (i = 1 ; i < argc; i++) {
|
||||
if (!strcmp(argv[i], "-t")) {
|
||||
|
@ -36,10 +38,20 @@ int main(int argc, char **argv)
|
|||
die(hash_object_usage);
|
||||
type = argv[i];
|
||||
}
|
||||
else if (!strcmp(argv[i], "-w"))
|
||||
else if (!strcmp(argv[i], "-w")) {
|
||||
if (prefix_length < 0) {
|
||||
prefix = setup_git_directory();
|
||||
prefix_length = prefix ? strlen(prefix) : 0;
|
||||
}
|
||||
write_object = 1;
|
||||
else
|
||||
hash_object(argv[i], type, write_object);
|
||||
}
|
||||
else {
|
||||
const char *arg = argv[i];
|
||||
if (0 <= prefix_length)
|
||||
arg = prefix_filename(prefix, prefix_length,
|
||||
arg);
|
||||
hash_object(arg, type, write_object);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -922,6 +922,8 @@ int main(int argc, char **argv)
|
|||
int arg = 1;
|
||||
int rc = 0;
|
||||
|
||||
setup_git_directory();
|
||||
|
||||
while (arg < argc && argv[arg][0] == '-') {
|
||||
if (argv[arg][1] == 't') {
|
||||
get_tree = 1;
|
||||
|
|
|
@ -784,7 +784,7 @@ static void handle_new_lock_ctx(struct xml_ctx *ctx, int tag_closed)
|
|||
strtol(ctx->cdata + 7, NULL, 10);
|
||||
} else if (!strcmp(ctx->name, DAV_ACTIVELOCK_TOKEN)) {
|
||||
if (!strncmp(ctx->cdata, "opaquelocktoken:", 16)) {
|
||||
lock->token = xmalloc(strlen(ctx->cdata - 15));
|
||||
lock->token = xmalloc(strlen(ctx->cdata) - 15);
|
||||
strcpy(lock->token, ctx->cdata + 16);
|
||||
}
|
||||
}
|
||||
|
@ -1008,9 +1008,7 @@ static int unlock_remote(struct active_lock *lock)
|
|||
if (lock->owner != NULL)
|
||||
free(lock->owner);
|
||||
free(lock->url);
|
||||
/* Freeing the token causes a segfault...
|
||||
free(lock->token);
|
||||
*/
|
||||
free(lock);
|
||||
|
||||
return rc;
|
||||
|
@ -1239,6 +1237,7 @@ int main(int argc, char **argv)
|
|||
int rc = 0;
|
||||
int i;
|
||||
|
||||
setup_git_directory();
|
||||
setup_ident();
|
||||
|
||||
remote = xmalloc(sizeof(*remote));
|
||||
|
@ -1273,6 +1272,9 @@ int main(int argc, char **argv)
|
|||
break;
|
||||
}
|
||||
|
||||
if (!remote->url)
|
||||
usage(http_push_usage);
|
||||
|
||||
memset(remote_dir_exists, 0, 256);
|
||||
|
||||
http_init();
|
||||
|
|
87
init-db.c
87
init-db.c
|
@ -132,6 +132,23 @@ static void copy_templates(const char *git_dir, int len, char *template_dir)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Make sure that template is from the correct vintage */
|
||||
strcpy(template_path + template_len, "config");
|
||||
repository_format_version = 0;
|
||||
git_config_from_file(check_repository_format_version,
|
||||
template_path);
|
||||
template_path[template_len] = 0;
|
||||
|
||||
if (repository_format_version &&
|
||||
repository_format_version != GIT_REPO_VERSION) {
|
||||
fprintf(stderr, "warning: not copying templates of "
|
||||
"a wrong format version %d from '%s'\n",
|
||||
repository_format_version,
|
||||
template_dir);
|
||||
closedir(dir);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(path, git_dir, len);
|
||||
path[len] = 0;
|
||||
copy_templates_1(path, len,
|
||||
|
@ -140,12 +157,13 @@ static void copy_templates(const char *git_dir, int len, char *template_dir)
|
|||
closedir(dir);
|
||||
}
|
||||
|
||||
static void create_default_files(const char *git_dir,
|
||||
char *template_path)
|
||||
static void create_default_files(const char *git_dir, char *template_path)
|
||||
{
|
||||
unsigned len = strlen(git_dir);
|
||||
static char path[PATH_MAX];
|
||||
unsigned char sha1[20];
|
||||
struct stat st1;
|
||||
char repo_version_string[10];
|
||||
|
||||
if (len > sizeof(path)-50)
|
||||
die("insane git directory %s", git_dir);
|
||||
|
@ -164,6 +182,15 @@ static void create_default_files(const char *git_dir,
|
|||
strcpy(path + len, "refs/tags");
|
||||
safe_create_dir(path);
|
||||
|
||||
/* First copy the templates -- we might have the default
|
||||
* config file there, in which case we would want to read
|
||||
* from it after installing.
|
||||
*/
|
||||
path[len] = 0;
|
||||
copy_templates(path, len, template_path);
|
||||
|
||||
git_config(git_default_config);
|
||||
|
||||
/*
|
||||
* Create the default symlink from ".git/HEAD" to the "master"
|
||||
* branch, if it does not exist yet.
|
||||
|
@ -173,44 +200,22 @@ static void create_default_files(const char *git_dir,
|
|||
if (create_symref(path, "refs/heads/master") < 0)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* This forces creation of new config file */
|
||||
sprintf(repo_version_string, "%d", GIT_REPO_VERSION);
|
||||
git_config_set("core.repositoryformatversion", repo_version_string);
|
||||
|
||||
path[len] = 0;
|
||||
copy_templates(path, len, template_path);
|
||||
|
||||
/*
|
||||
* Find out if we can trust the executable bit.
|
||||
*/
|
||||
safe_create_dir(path);
|
||||
strcpy(path + len, "config");
|
||||
if (access(path, R_OK) < 0) {
|
||||
static const char contents[] =
|
||||
"#\n"
|
||||
"# This is the config file\n"
|
||||
"#\n"
|
||||
"\n"
|
||||
"; core variables\n"
|
||||
"[core]\n"
|
||||
" ; Don't trust file modes\n"
|
||||
" filemode = false\n"
|
||||
"\n";
|
||||
FILE *config = fopen(path, "w");
|
||||
struct stat st;
|
||||
|
||||
if (!config)
|
||||
die("Can not write to %s?", path);
|
||||
|
||||
fwrite(contents, sizeof(contents)-1, 1, config);
|
||||
|
||||
fclose(config);
|
||||
|
||||
if (!lstat(path, &st)) {
|
||||
struct stat st2;
|
||||
if (!chmod(path, st.st_mode ^ S_IXUSR) &&
|
||||
!lstat(path, &st2) &&
|
||||
st.st_mode != st2.st_mode)
|
||||
unlink(path);
|
||||
else
|
||||
fprintf(stderr, "Ignoring file modes\n");
|
||||
}
|
||||
/* Check filemode trustability */
|
||||
if (!lstat(path, &st1)) {
|
||||
struct stat st2;
|
||||
int filemode = (!chmod(path, st1.st_mode ^ S_IXUSR) &&
|
||||
!lstat(path, &st2) &&
|
||||
st1.st_mode != st2.st_mode);
|
||||
git_config_set("core.filemode",
|
||||
filemode ? "true" : "false");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -249,6 +254,14 @@ int main(int argc, char **argv)
|
|||
fprintf(stderr, "defaulting to local storage area\n");
|
||||
}
|
||||
safe_create_dir(git_dir);
|
||||
|
||||
/* Check to see if the repository version is right.
|
||||
* Note that a newly created repository does not have
|
||||
* config file, so this will not fail. What we are catching
|
||||
* is an attempt to reinitialize new repository with an old tool.
|
||||
*/
|
||||
check_repository_format();
|
||||
|
||||
create_default_files(git_dir, template_dir);
|
||||
|
||||
/*
|
||||
|
|
|
@ -207,6 +207,8 @@ int main(int argc, char **argv)
|
|||
char *commit_id;
|
||||
int arg = 1;
|
||||
|
||||
setup_git_directory();
|
||||
|
||||
while (arg < argc && argv[arg][0] == '-') {
|
||||
if (argv[arg][1] == 't')
|
||||
get_tree = 1;
|
||||
|
|
|
@ -344,7 +344,7 @@ static void show_dir_entry(const char *tag, struct nond_on_fs *ent)
|
|||
return;
|
||||
|
||||
fputs(tag, stdout);
|
||||
write_name_quoted("", ent->name + offset, line_terminator, stdout);
|
||||
write_name_quoted("", 0, ent->name + offset, line_terminator, stdout);
|
||||
putchar(line_terminator);
|
||||
}
|
||||
|
||||
|
@ -433,7 +433,8 @@ static void show_ce_entry(const char *tag, struct cache_entry *ce)
|
|||
|
||||
if (!show_stage) {
|
||||
fputs(tag, stdout);
|
||||
write_name_quoted("", ce->name + offset, line_terminator, stdout);
|
||||
write_name_quoted("", 0, ce->name + offset,
|
||||
line_terminator, stdout);
|
||||
putchar(line_terminator);
|
||||
}
|
||||
else {
|
||||
|
@ -442,7 +443,8 @@ static void show_ce_entry(const char *tag, struct cache_entry *ce)
|
|||
ntohl(ce->ce_mode),
|
||||
sha1_to_hex(ce->sha1),
|
||||
ce_stage(ce));
|
||||
write_name_quoted("", ce->name + offset, line_terminator, stdout);
|
||||
write_name_quoted("", 0, ce->name + offset,
|
||||
line_terminator, stdout);
|
||||
putchar(line_terminator);
|
||||
}
|
||||
}
|
||||
|
|
292
ls-tree.c
292
ls-tree.c
|
@ -11,217 +11,75 @@
|
|||
static int line_termination = '\n';
|
||||
#define LS_RECURSIVE 1
|
||||
#define LS_TREE_ONLY 2
|
||||
#define LS_SHOW_TREES 4
|
||||
#define LS_NAME_ONLY 8
|
||||
static int ls_options = 0;
|
||||
|
||||
static struct tree_entry_list root_entry;
|
||||
|
||||
static void prepare_root(unsigned char *sha1)
|
||||
{
|
||||
unsigned char rsha[20];
|
||||
unsigned long size;
|
||||
void *buf;
|
||||
struct tree *root_tree;
|
||||
|
||||
buf = read_object_with_reference(sha1, "tree", &size, rsha);
|
||||
free(buf);
|
||||
if (!buf)
|
||||
die("Could not read %s", sha1_to_hex(sha1));
|
||||
|
||||
root_tree = lookup_tree(rsha);
|
||||
if (!root_tree)
|
||||
die("Could not read %s", sha1_to_hex(sha1));
|
||||
|
||||
/* Prepare a fake entry */
|
||||
root_entry.directory = 1;
|
||||
root_entry.executable = root_entry.symlink = 0;
|
||||
root_entry.mode = S_IFDIR;
|
||||
root_entry.name = "";
|
||||
root_entry.item.tree = root_tree;
|
||||
root_entry.parent = NULL;
|
||||
}
|
||||
|
||||
static int prepare_children(struct tree_entry_list *elem)
|
||||
{
|
||||
if (!elem->directory)
|
||||
return -1;
|
||||
if (!elem->item.tree->object.parsed) {
|
||||
struct tree_entry_list *e;
|
||||
if (parse_tree(elem->item.tree))
|
||||
return -1;
|
||||
/* Set up the parent link */
|
||||
for (e = elem->item.tree->entries; e; e = e->next)
|
||||
e->parent = elem;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct tree_entry_list *find_entry(const char *path, char *pathbuf)
|
||||
{
|
||||
const char *next, *slash;
|
||||
int len;
|
||||
struct tree_entry_list *elem = &root_entry, *oldelem = NULL;
|
||||
|
||||
*(pathbuf) = '\0';
|
||||
|
||||
/* Find tree element, descending from root, that
|
||||
* corresponds to the named path, lazily expanding
|
||||
* the tree if possible.
|
||||
*/
|
||||
|
||||
while (path) {
|
||||
/* The fact we still have path means that the caller
|
||||
* wants us to make sure that elem at this point is a
|
||||
* directory, and possibly descend into it. Even what
|
||||
* is left is just trailing slashes, we loop back to
|
||||
* here, and this call to prepare_children() will
|
||||
* catch elem not being a tree. Nice.
|
||||
*/
|
||||
if (prepare_children(elem))
|
||||
return NULL;
|
||||
|
||||
slash = strchr(path, '/');
|
||||
if (!slash) {
|
||||
len = strlen(path);
|
||||
next = NULL;
|
||||
}
|
||||
else {
|
||||
next = slash + 1;
|
||||
len = slash - path;
|
||||
}
|
||||
if (len) {
|
||||
if (oldelem) {
|
||||
pathbuf += sprintf(pathbuf, "%s/", oldelem->name);
|
||||
}
|
||||
|
||||
/* (len == 0) if the original path was "drivers/char/"
|
||||
* and we have run already two rounds, having elem
|
||||
* pointing at the drivers/char directory.
|
||||
*/
|
||||
elem = elem->item.tree->entries;
|
||||
while (elem) {
|
||||
if ((strlen(elem->name) == len) &&
|
||||
!strncmp(elem->name, path, len)) {
|
||||
/* found */
|
||||
break;
|
||||
}
|
||||
elem = elem->next;
|
||||
}
|
||||
if (!elem)
|
||||
return NULL;
|
||||
|
||||
oldelem = elem;
|
||||
}
|
||||
path = next;
|
||||
}
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
||||
static const char *entry_type(struct tree_entry_list *e)
|
||||
{
|
||||
return (e->directory ? "tree" : "blob");
|
||||
}
|
||||
|
||||
static const char *entry_hex(struct tree_entry_list *e)
|
||||
{
|
||||
return sha1_to_hex(e->directory
|
||||
? e->item.tree->object.sha1
|
||||
: e->item.blob->object.sha1);
|
||||
}
|
||||
|
||||
/* forward declaration for mutually recursive routines */
|
||||
static int show_entry(struct tree_entry_list *, int, char *pathbuf);
|
||||
|
||||
static int show_children(struct tree_entry_list *e, int level, char *pathbuf)
|
||||
{
|
||||
int oldlen = strlen(pathbuf);
|
||||
|
||||
if (e != &root_entry)
|
||||
sprintf(pathbuf + oldlen, "%s/", e->name);
|
||||
|
||||
if (prepare_children(e))
|
||||
die("internal error: ls-tree show_children called with non tree");
|
||||
e = e->item.tree->entries;
|
||||
while (e) {
|
||||
show_entry(e, level, pathbuf);
|
||||
e = e->next;
|
||||
}
|
||||
|
||||
pathbuf[oldlen] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int show_entry(struct tree_entry_list *e, int level, char *pathbuf)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (e != &root_entry) {
|
||||
printf("%06o %s %s ",
|
||||
e->mode, entry_type(e), entry_hex(e));
|
||||
write_name_quoted(pathbuf, e->name, line_termination, stdout);
|
||||
putchar(line_termination);
|
||||
}
|
||||
|
||||
if (e->directory) {
|
||||
/* If this is a directory, we have the following cases:
|
||||
* (1) This is the top-level request (explicit path from the
|
||||
* command line, or "root" if there is no command line).
|
||||
* a. Without any flag. We show direct children. We do not
|
||||
* recurse into them.
|
||||
* b. With -r. We do recurse into children.
|
||||
* c. With -d. We do not recurse into children.
|
||||
* (2) We came here because our caller is either (1-a) or
|
||||
* (1-b).
|
||||
* a. Without any flag. We do not show our children (which
|
||||
* are grandchildren for the original request).
|
||||
* b. With -r. We continue to recurse into our children.
|
||||
* c. With -d. We should not have come here to begin with.
|
||||
*/
|
||||
if (level == 0 && !(ls_options & LS_TREE_ONLY))
|
||||
/* case (1)-a and (1)-b */
|
||||
err = err | show_children(e, level+1, pathbuf);
|
||||
else if (level && ls_options & LS_RECURSIVE)
|
||||
/* case (2)-b */
|
||||
err = err | show_children(e, level+1, pathbuf);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int list_one(const char *path)
|
||||
{
|
||||
int err = 0;
|
||||
char pathbuf[MAXPATHLEN + 1];
|
||||
struct tree_entry_list *e = find_entry(path, pathbuf);
|
||||
if (!e) {
|
||||
/* traditionally ls-tree does not complain about
|
||||
* missing path. We may change this later to match
|
||||
* what "/bin/ls -a" does, which is to complain.
|
||||
*/
|
||||
return err;
|
||||
}
|
||||
err = err | show_entry(e, 0, pathbuf);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int list(char **path)
|
||||
{
|
||||
int i;
|
||||
int err = 0;
|
||||
for (i = 0; path[i]; i++)
|
||||
err = err | list_one(path[i]);
|
||||
return err;
|
||||
}
|
||||
const char **pathspec;
|
||||
|
||||
static const char ls_tree_usage[] =
|
||||
"git-ls-tree [-d] [-r] [-z] <tree-ish> [path...]";
|
||||
"git-ls-tree [-d] [-r] [-t] [-z] [--name-only] [--name-status] <tree-ish> [path...]";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
static int show_recursive(const char *base, int baselen, const char *pathname)
|
||||
{
|
||||
static char *path0[] = { "", NULL };
|
||||
char **path;
|
||||
unsigned char sha1[20];
|
||||
const char **s;
|
||||
|
||||
if (ls_options & LS_RECURSIVE)
|
||||
return 1;
|
||||
|
||||
s = pathspec;
|
||||
if (!s)
|
||||
return 0;
|
||||
|
||||
for (;;) {
|
||||
const char *spec = *s++;
|
||||
int len, speclen;
|
||||
|
||||
if (!spec)
|
||||
return 0;
|
||||
if (strncmp(base, spec, baselen))
|
||||
continue;
|
||||
len = strlen(pathname);
|
||||
spec += baselen;
|
||||
speclen = strlen(spec);
|
||||
if (speclen <= len)
|
||||
continue;
|
||||
if (memcmp(pathname, spec, len))
|
||||
continue;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int show_tree(unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage)
|
||||
{
|
||||
int retval = 0;
|
||||
const char *type = "blob";
|
||||
|
||||
if (S_ISDIR(mode)) {
|
||||
if (show_recursive(base, baselen, pathname)) {
|
||||
retval = READ_TREE_RECURSIVE;
|
||||
if (!(ls_options & LS_SHOW_TREES))
|
||||
return retval;
|
||||
}
|
||||
type = "tree";
|
||||
}
|
||||
else if (ls_options & LS_TREE_ONLY)
|
||||
return 0;
|
||||
|
||||
if (!(ls_options & LS_NAME_ONLY))
|
||||
printf("%06o %s %s\t", mode, type, sha1_to_hex(sha1));
|
||||
write_name_quoted(base, baselen, pathname, line_termination, stdout);
|
||||
putchar(line_termination);
|
||||
return retval;
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
const char *prefix;
|
||||
unsigned char sha1[20];
|
||||
char *buf;
|
||||
unsigned long size;
|
||||
|
||||
prefix = setup_git_directory();
|
||||
while (1 < argc && argv[1][0] == '-') {
|
||||
switch (argv[1][1]) {
|
||||
case 'z':
|
||||
|
@ -233,20 +91,36 @@ int main(int argc, char **argv)
|
|||
case 'd':
|
||||
ls_options |= LS_TREE_ONLY;
|
||||
break;
|
||||
case 't':
|
||||
ls_options |= LS_SHOW_TREES;
|
||||
break;
|
||||
case '-':
|
||||
if (!strcmp(argv[1]+2, "name-only") ||
|
||||
!strcmp(argv[1]+2, "name-status")) {
|
||||
ls_options |= LS_NAME_ONLY;
|
||||
break;
|
||||
}
|
||||
/* otherwise fallthru */
|
||||
default:
|
||||
usage(ls_tree_usage);
|
||||
}
|
||||
argc--; argv++;
|
||||
}
|
||||
/* -d -r should imply -t, but -d by itself should not have to. */
|
||||
if ( (LS_TREE_ONLY|LS_RECURSIVE) ==
|
||||
((LS_TREE_ONLY|LS_RECURSIVE) & ls_options))
|
||||
ls_options |= LS_SHOW_TREES;
|
||||
|
||||
if (argc < 2)
|
||||
usage(ls_tree_usage);
|
||||
if (get_sha1(argv[1], sha1) < 0)
|
||||
usage(ls_tree_usage);
|
||||
|
||||
path = (argc == 2) ? path0 : (argv + 2);
|
||||
prepare_root(sha1);
|
||||
if (list(path) < 0)
|
||||
die("list failed");
|
||||
pathspec = get_pathspec(prefix, argv + 2);
|
||||
buf = read_object_with_reference(sha1, "tree", &size, NULL);
|
||||
if (!buf)
|
||||
die("not a tree object");
|
||||
read_tree_recursive(buf, size, "", 0, 0, pathspec, show_tree);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
74
mailinfo.c
74
mailinfo.c
|
@ -8,6 +8,7 @@
|
|||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <iconv.h>
|
||||
#include "cache.h"
|
||||
|
||||
#ifdef NO_STRCASESTR
|
||||
extern char *gitstrcasestr(const char *haystack, const char *needle);
|
||||
|
@ -16,7 +17,7 @@ extern char *gitstrcasestr(const char *haystack, const char *needle);
|
|||
static FILE *cmitmsg, *patchfile;
|
||||
|
||||
static int keep_subject = 0;
|
||||
static int metainfo_utf8 = 0;
|
||||
static char *metainfo_charset = NULL;
|
||||
static char line[1000];
|
||||
static char date[1000];
|
||||
static char name[1000];
|
||||
|
@ -441,29 +442,38 @@ static int decode_b_segment(char *in, char *ot, char *ep)
|
|||
|
||||
static void convert_to_utf8(char *line, char *charset)
|
||||
{
|
||||
if (*charset) {
|
||||
char *in, *out;
|
||||
size_t insize, outsize, nrc;
|
||||
char outbuf[4096]; /* cheat */
|
||||
iconv_t conv = iconv_open("utf-8", charset);
|
||||
char *in, *out;
|
||||
size_t insize, outsize, nrc;
|
||||
char outbuf[4096]; /* cheat */
|
||||
static char latin_one[] = "latin-1";
|
||||
char *input_charset = *charset ? charset : latin_one;
|
||||
iconv_t conv = iconv_open(metainfo_charset, input_charset);
|
||||
|
||||
if (conv == (iconv_t) -1) {
|
||||
fprintf(stderr, "cannot convert from %s to utf-8\n",
|
||||
charset);
|
||||
if (conv == (iconv_t) -1) {
|
||||
static int warned_latin1_once = 0;
|
||||
if (input_charset != latin_one) {
|
||||
fprintf(stderr, "cannot convert from %s to %s\n",
|
||||
input_charset, metainfo_charset);
|
||||
*charset = 0;
|
||||
return;
|
||||
}
|
||||
in = line;
|
||||
insize = strlen(in);
|
||||
out = outbuf;
|
||||
outsize = sizeof(outbuf);
|
||||
nrc = iconv(conv, &in, &insize, &out, &outsize);
|
||||
iconv_close(conv);
|
||||
if (nrc == (size_t) -1)
|
||||
return;
|
||||
*out = 0;
|
||||
strcpy(line, outbuf);
|
||||
else if (!warned_latin1_once) {
|
||||
warned_latin1_once = 1;
|
||||
fprintf(stderr, "tried to convert from %s to %s, "
|
||||
"but your iconv does not work with it.\n",
|
||||
input_charset, metainfo_charset);
|
||||
}
|
||||
return;
|
||||
}
|
||||
in = line;
|
||||
insize = strlen(in);
|
||||
out = outbuf;
|
||||
outsize = sizeof(outbuf);
|
||||
nrc = iconv(conv, &in, &insize, &out, &outsize);
|
||||
iconv_close(conv);
|
||||
if (nrc == (size_t) -1)
|
||||
return;
|
||||
*out = 0;
|
||||
strcpy(line, outbuf);
|
||||
}
|
||||
|
||||
static void decode_header_bq(char *it)
|
||||
|
@ -511,7 +521,7 @@ static void decode_header_bq(char *it)
|
|||
}
|
||||
if (sz < 0)
|
||||
return;
|
||||
if (metainfo_utf8)
|
||||
if (metainfo_charset)
|
||||
convert_to_utf8(piecebuf, charset_q);
|
||||
strcpy(out, piecebuf);
|
||||
out += strlen(out);
|
||||
|
@ -590,7 +600,7 @@ static int handle_commit_msg(void)
|
|||
* normalize the log message to UTF-8.
|
||||
*/
|
||||
decode_transfer_encoding(line);
|
||||
if (metainfo_utf8)
|
||||
if (metainfo_charset)
|
||||
convert_to_utf8(line, charset);
|
||||
fputs(line, cmitmsg);
|
||||
} while (fgets(line, sizeof(line), stdin) != NULL);
|
||||
|
@ -707,27 +717,29 @@ static void handle_body(void)
|
|||
}
|
||||
|
||||
static const char mailinfo_usage[] =
|
||||
"git-mailinfo [-k] [-u] msg patch <mail >info";
|
||||
|
||||
static void usage(void) {
|
||||
fprintf(stderr, "%s\n", mailinfo_usage);
|
||||
exit(1);
|
||||
}
|
||||
"git-mailinfo [-k] [-u | --encoding=<encoding>] msg patch <mail >info";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
/* NEEDSWORK: might want to do the optional .git/ directory
|
||||
* discovery
|
||||
*/
|
||||
git_config(git_default_config);
|
||||
|
||||
while (1 < argc && argv[1][0] == '-') {
|
||||
if (!strcmp(argv[1], "-k"))
|
||||
keep_subject = 1;
|
||||
else if (!strcmp(argv[1], "-u"))
|
||||
metainfo_utf8 = 1;
|
||||
metainfo_charset = git_commit_encoding;
|
||||
else if (!strncmp(argv[1], "--encoding=", 11))
|
||||
metainfo_charset = argv[1] + 11;
|
||||
else
|
||||
usage();
|
||||
usage(mailinfo_usage);
|
||||
argc--; argv++;
|
||||
}
|
||||
|
||||
if (argc != 3)
|
||||
usage();
|
||||
usage(mailinfo_usage);
|
||||
cmitmsg = fopen(argv[1], "w");
|
||||
if (!cmitmsg) {
|
||||
perror(argv[1]);
|
||||
|
|
|
@ -236,6 +236,8 @@ int main(int argc, char **argv)
|
|||
struct commit *rev1, *rev2;
|
||||
unsigned char rev1key[20], rev2key[20];
|
||||
|
||||
setup_git_directory();
|
||||
|
||||
while (1 < argc && argv[1][0] == '-') {
|
||||
char *arg = argv[1];
|
||||
if (!strcmp(arg, "-a") || !strcmp(arg, "--all"))
|
||||
|
|
|
@ -102,6 +102,7 @@ int main(int argc, char **argv)
|
|||
if (argc < 3)
|
||||
usage("git-merge-index [-o] [-q] <merge-program> (-a | <filename>*)");
|
||||
|
||||
setup_git_directory();
|
||||
read_cache();
|
||||
|
||||
i = 1;
|
||||
|
|
2
mktag.c
2
mktag.c
|
@ -111,6 +111,8 @@ int main(int argc, char **argv)
|
|||
if (argc != 1)
|
||||
usage("cat <signaturefile> | git-mktag");
|
||||
|
||||
setup_git_directory();
|
||||
|
||||
// Read the signature
|
||||
size = 0;
|
||||
for (;;) {
|
||||
|
|
11
name-rev.c
11
name-rev.c
|
@ -21,7 +21,7 @@ static void name_rev(struct commit *commit,
|
|||
{
|
||||
struct rev_name *name = (struct rev_name *)commit->object.util;
|
||||
struct commit_list *parents;
|
||||
int parent_number = 0;
|
||||
int parent_number = 1;
|
||||
|
||||
if (!commit->object.parsed)
|
||||
parse_commit(commit);
|
||||
|
@ -56,7 +56,7 @@ copy_data:
|
|||
for (parents = commit->parents;
|
||||
parents;
|
||||
parents = parents->next, parent_number++) {
|
||||
if (parent_number > 0) {
|
||||
if (parent_number > 1) {
|
||||
char *new_name = xmalloc(strlen(tip_name)+8);
|
||||
|
||||
if (generation > 0)
|
||||
|
@ -217,10 +217,9 @@ int main(int argc, char **argv)
|
|||
if (!strcmp(name, "undefined"))
|
||||
continue;
|
||||
|
||||
fwrite(p_start, p - p_start, 1, stdout);
|
||||
fputc('(', stdout);
|
||||
fputs(name, stdout);
|
||||
fputc(')', stdout);
|
||||
fwrite(p_start, p - p_start + 1, 1,
|
||||
stdout);
|
||||
printf(" (%s)", name);
|
||||
p_start = p + 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -473,6 +473,8 @@ int main(int argc, char **argv)
|
|||
struct object_entry **list;
|
||||
int i;
|
||||
|
||||
setup_git_directory();
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
|
||||
|
|
|
@ -600,6 +600,8 @@ int main(int argc, char **argv)
|
|||
unsigned char *sha1;
|
||||
char buf[42]; /* 40 byte sha1 + \n + \0 */
|
||||
|
||||
setup_git_directory();
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
if(!strcmp(arg, "--")) {
|
||||
|
|
166
path.c
166
path.c
|
@ -131,75 +131,121 @@ int validate_symref(const char *path)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static char *current_dir(void)
|
||||
static char *user_path(char *buf, char *path, int sz)
|
||||
{
|
||||
return getcwd(pathname, sizeof(pathname));
|
||||
}
|
||||
struct passwd *pw;
|
||||
char *slash;
|
||||
int len, baselen;
|
||||
|
||||
static int user_chdir(char *path)
|
||||
{
|
||||
char *dir = path;
|
||||
|
||||
if(*dir == '~') { /* user-relative path */
|
||||
struct passwd *pw;
|
||||
char *slash = strchr(dir, '/');
|
||||
|
||||
dir++;
|
||||
/* '~/' and '~' (no slash) means users own home-dir */
|
||||
if(!*dir || *dir == '/')
|
||||
pw = getpwuid(getuid());
|
||||
else {
|
||||
if (slash) {
|
||||
*slash = '\0';
|
||||
pw = getpwnam(dir);
|
||||
*slash = '/';
|
||||
}
|
||||
else
|
||||
pw = getpwnam(dir);
|
||||
}
|
||||
|
||||
/* make sure we got something back that we can chdir() to */
|
||||
if(!pw || chdir(pw->pw_dir) < 0)
|
||||
return -1;
|
||||
|
||||
if(!slash || !slash[1]) /* no path following username */
|
||||
return 0;
|
||||
|
||||
dir = slash + 1;
|
||||
}
|
||||
|
||||
/* ~foo/path/to/repo is now path/to/repo and we're in foo's homedir */
|
||||
if(chdir(dir) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *enter_repo(char *path, int strict)
|
||||
{
|
||||
if(!path)
|
||||
if (!path || path[0] != '~')
|
||||
return NULL;
|
||||
|
||||
if (strict) {
|
||||
if (chdir(path) < 0)
|
||||
return NULL;
|
||||
path++;
|
||||
slash = strchr(path, '/');
|
||||
if (path[0] == '/' || !path[0]) {
|
||||
pw = getpwuid(getuid());
|
||||
}
|
||||
else {
|
||||
if (!*path)
|
||||
; /* happy -- no chdir */
|
||||
else if (!user_chdir(path))
|
||||
; /* happy -- as given */
|
||||
else if (!user_chdir(mkpath("%s.git", path)))
|
||||
; /* happy -- uemacs --> uemacs.git */
|
||||
if (slash) {
|
||||
*slash = 0;
|
||||
pw = getpwnam(path);
|
||||
*slash = '/';
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
(void)chdir(".git");
|
||||
pw = getpwnam(path);
|
||||
}
|
||||
if (!pw || !pw->pw_dir || sz <= strlen(pw->pw_dir))
|
||||
return NULL;
|
||||
baselen = strlen(pw->pw_dir);
|
||||
memcpy(buf, pw->pw_dir, baselen);
|
||||
while ((1 < baselen) && (buf[baselen-1] == '/')) {
|
||||
buf[baselen-1] = 0;
|
||||
baselen--;
|
||||
}
|
||||
if (slash && slash[1]) {
|
||||
len = strlen(slash);
|
||||
if (sz <= baselen + len)
|
||||
return NULL;
|
||||
memcpy(buf + baselen, slash, len + 1);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
if(access("objects", X_OK) == 0 && access("refs", X_OK) == 0 &&
|
||||
validate_symref("HEAD") == 0) {
|
||||
/*
|
||||
* First, one directory to try is determined by the following algorithm.
|
||||
*
|
||||
* (0) If "strict" is given, the path is used as given and no DWIM is
|
||||
* done. Otherwise:
|
||||
* (1) "~/path" to mean path under the running user's home directory;
|
||||
* (2) "~user/path" to mean path under named user's home directory;
|
||||
* (3) "relative/path" to mean cwd relative directory; or
|
||||
* (4) "/absolute/path" to mean absolute directory.
|
||||
*
|
||||
* Unless "strict" is given, we try access() for existence of "%s.git/.git",
|
||||
* "%s/.git", "%s.git", "%s" in this order. The first one that exists is
|
||||
* what we try.
|
||||
*
|
||||
* Second, we try chdir() to that. Upon failure, we return NULL.
|
||||
*
|
||||
* Then, we try if the current directory is a valid git repository.
|
||||
* Upon failure, we return NULL.
|
||||
*
|
||||
* If all goes well, we return the directory we used to chdir() (but
|
||||
* before ~user is expanded), avoiding getcwd() resolving symbolic
|
||||
* links. User relative paths are also returned as they are given,
|
||||
* except DWIM suffixing.
|
||||
*/
|
||||
char *enter_repo(char *path, int strict)
|
||||
{
|
||||
static char used_path[PATH_MAX];
|
||||
static char validated_path[PATH_MAX];
|
||||
|
||||
if (!path)
|
||||
return NULL;
|
||||
|
||||
if (!strict) {
|
||||
static const char *suffix[] = {
|
||||
".git/.git", "/.git", ".git", "", NULL,
|
||||
};
|
||||
int len = strlen(path);
|
||||
int i;
|
||||
while ((1 < len) && (path[len-1] == '/')) {
|
||||
path[len-1] = 0;
|
||||
len--;
|
||||
}
|
||||
if (PATH_MAX <= len)
|
||||
return NULL;
|
||||
if (path[0] == '~') {
|
||||
if (!user_path(used_path, path, PATH_MAX))
|
||||
return NULL;
|
||||
strcpy(validated_path, path);
|
||||
path = used_path;
|
||||
}
|
||||
else if (PATH_MAX - 10 < len)
|
||||
return NULL;
|
||||
else {
|
||||
path = strcpy(used_path, path);
|
||||
strcpy(validated_path, path);
|
||||
}
|
||||
len = strlen(path);
|
||||
for (i = 0; suffix[i]; i++) {
|
||||
strcpy(path + len, suffix[i]);
|
||||
if (!access(path, F_OK)) {
|
||||
strcat(validated_path, suffix[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!suffix[i] || chdir(path))
|
||||
return NULL;
|
||||
path = validated_path;
|
||||
}
|
||||
else if (chdir(path))
|
||||
return NULL;
|
||||
|
||||
if (access("objects", X_OK) == 0 && access("refs", X_OK) == 0 &&
|
||||
validate_symref("HEAD") == 0) {
|
||||
putenv("GIT_DIR=.");
|
||||
return current_dir();
|
||||
check_repository_format();
|
||||
return path;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
|
|
@ -27,6 +27,9 @@ int main(int argc, char **argv)
|
|||
char *dest = NULL;
|
||||
int fd[2];
|
||||
pid_t pid;
|
||||
int nongit = 0;
|
||||
|
||||
setup_git_directory_gently(&nongit);
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
char *arg = argv[i];
|
||||
|
|
|
@ -58,6 +58,8 @@ int main(int argc, char **argv)
|
|||
{
|
||||
int i;
|
||||
|
||||
setup_git_directory();
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
|
||||
|
|
29
quote.c
29
quote.c
|
@ -112,7 +112,8 @@ char *sq_dequote(char *arg)
|
|||
* but not enclosed in double-quote pair. Return value is undefined.
|
||||
*/
|
||||
|
||||
int quote_c_style(const char *name, char *outbuf, FILE *outfp, int no_dq)
|
||||
static int quote_c_style_counted(const char *name, int namelen,
|
||||
char *outbuf, FILE *outfp, int no_dq)
|
||||
{
|
||||
#undef EMIT
|
||||
#define EMIT(c) \
|
||||
|
@ -125,7 +126,7 @@ int quote_c_style(const char *name, char *outbuf, FILE *outfp, int no_dq)
|
|||
|
||||
if (!no_dq)
|
||||
EMIT('"');
|
||||
for (sp = name; (ch = *sp++); ) {
|
||||
for (sp = name; (ch = *sp++) && (sp - name) <= namelen; ) {
|
||||
|
||||
if ((ch < ' ') || (ch == '"') || (ch == '\\') ||
|
||||
(ch == 0177)) {
|
||||
|
@ -162,6 +163,12 @@ int quote_c_style(const char *name, char *outbuf, FILE *outfp, int no_dq)
|
|||
return needquote ? count : 0;
|
||||
}
|
||||
|
||||
int quote_c_style(const char *name, char *outbuf, FILE *outfp, int no_dq)
|
||||
{
|
||||
int cnt = strlen(name);
|
||||
return quote_c_style_counted(name, cnt, outbuf, outfp, no_dq);
|
||||
}
|
||||
|
||||
/*
|
||||
* C-style name unquoting.
|
||||
*
|
||||
|
@ -227,28 +234,30 @@ char *unquote_c_style(const char *quoted, const char **endp)
|
|||
}
|
||||
}
|
||||
|
||||
void write_name_quoted(const char *prefix, const char *name,
|
||||
int quote, FILE *out)
|
||||
void write_name_quoted(const char *prefix, int prefix_len,
|
||||
const char *name, int quote, FILE *out)
|
||||
{
|
||||
int needquote;
|
||||
|
||||
if (!quote) {
|
||||
no_quote:
|
||||
if (prefix && prefix[0])
|
||||
fputs(prefix, out);
|
||||
if (prefix_len)
|
||||
fprintf(out, "%.*s", prefix_len, prefix);
|
||||
fputs(name, out);
|
||||
return;
|
||||
}
|
||||
|
||||
needquote = 0;
|
||||
if (prefix && prefix[0])
|
||||
needquote = quote_c_style(prefix, NULL, NULL, 0);
|
||||
if (prefix_len)
|
||||
needquote = quote_c_style_counted(prefix, prefix_len,
|
||||
NULL, NULL, 0);
|
||||
if (!needquote)
|
||||
needquote = quote_c_style(name, NULL, NULL, 0);
|
||||
if (needquote) {
|
||||
fputc('"', out);
|
||||
if (prefix && prefix[0])
|
||||
quote_c_style(prefix, NULL, out, 1);
|
||||
if (prefix_len)
|
||||
quote_c_style_counted(prefix, prefix_len,
|
||||
NULL, out, 1);
|
||||
quote_c_style(name, NULL, out, 1);
|
||||
fputc('"', out);
|
||||
}
|
||||
|
|
4
quote.h
4
quote.h
|
@ -41,7 +41,7 @@ extern int quote_c_style(const char *name, char *outbuf, FILE *outfp,
|
|||
int nodq);
|
||||
extern char *unquote_c_style(const char *quoted, const char **endp);
|
||||
|
||||
extern void write_name_quoted(const char *prefix, const char *name,
|
||||
int quote, FILE *out);
|
||||
extern void write_name_quoted(const char *prefix, int prefix_len,
|
||||
const char *name, int quote, FILE *out);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -629,6 +629,8 @@ int main(int argc, char **argv)
|
|||
unsigned char sha1[20];
|
||||
merge_fn_t fn = NULL;
|
||||
|
||||
setup_git_directory();
|
||||
|
||||
newfd = hold_index_file_for_update(&cache_file, get_index_file());
|
||||
if (newfd < 0)
|
||||
die("unable to create new cachefile");
|
||||
|
|
18
rev-list.c
18
rev-list.c
|
@ -350,7 +350,8 @@ static int count_distance(struct commit_list *entry)
|
|||
|
||||
if (commit->object.flags & (UNINTERESTING | COUNTED))
|
||||
break;
|
||||
nr++;
|
||||
if (!paths || (commit->object.flags & TREECHANGE))
|
||||
nr++;
|
||||
commit->object.flags |= COUNTED;
|
||||
p = commit->parents;
|
||||
entry = p;
|
||||
|
@ -362,6 +363,7 @@ static int count_distance(struct commit_list *entry)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nr;
|
||||
}
|
||||
|
||||
|
@ -382,15 +384,20 @@ static struct commit_list *find_bisection(struct commit_list *list)
|
|||
nr = 0;
|
||||
p = list;
|
||||
while (p) {
|
||||
nr++;
|
||||
if (!paths || (p->item->object.flags & TREECHANGE))
|
||||
nr++;
|
||||
p = p->next;
|
||||
}
|
||||
closest = 0;
|
||||
best = list;
|
||||
|
||||
p = list;
|
||||
while (p) {
|
||||
int distance = count_distance(p);
|
||||
for (p = list; p; p = p->next) {
|
||||
int distance;
|
||||
|
||||
if (paths && !(p->item->object.flags & TREECHANGE))
|
||||
continue;
|
||||
|
||||
distance = count_distance(p);
|
||||
clear_distance(list);
|
||||
if (nr - distance < distance)
|
||||
distance = nr - distance;
|
||||
|
@ -398,7 +405,6 @@ static struct commit_list *find_bisection(struct commit_list *list)
|
|||
best = p;
|
||||
closest = distance;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
if (best)
|
||||
best->next = NULL;
|
||||
|
|
|
@ -273,6 +273,7 @@ int main(int argc, char **argv)
|
|||
int fd[2], ret;
|
||||
pid_t pid;
|
||||
|
||||
setup_git_directory();
|
||||
argv++;
|
||||
for (i = 1; i < argc; i++, argv++) {
|
||||
char *arg = *argv;
|
||||
|
|
47
setup.c
47
setup.c
|
@ -47,6 +47,21 @@ const char *prefix_path(const char *prefix, int len, const char *path)
|
|||
return path;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unlike prefix_path, this should be used if the named file does
|
||||
* not have to interact with index entry; i.e. name of a random file
|
||||
* on the filesystem.
|
||||
*/
|
||||
const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
|
||||
{
|
||||
static char path[PATH_MAX];
|
||||
if (!pfx || !*pfx || arg[0] == '/')
|
||||
return arg;
|
||||
memcpy(path, pfx, pfx_len);
|
||||
strcpy(path + pfx_len, arg);
|
||||
return path;
|
||||
}
|
||||
|
||||
const char **get_pathspec(const char *prefix, const char **pathspec)
|
||||
{
|
||||
const char *entry = *pathspec;
|
||||
|
@ -92,7 +107,7 @@ static int is_toplevel_directory(void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static const char *setup_git_directory_1(void)
|
||||
const char *setup_git_directory_gently(int *nongit_ok)
|
||||
{
|
||||
static char cwd[PATH_MAX+1];
|
||||
int len, offset;
|
||||
|
@ -116,7 +131,7 @@ static const char *setup_git_directory_1(void)
|
|||
if (validate_symref(path))
|
||||
goto bad_dir_environ;
|
||||
if (getenv(DB_ENVIRONMENT)) {
|
||||
if (access(DB_ENVIRONMENT, X_OK))
|
||||
if (access(getenv(DB_ENVIRONMENT), X_OK))
|
||||
goto bad_dir_environ;
|
||||
}
|
||||
else {
|
||||
|
@ -139,8 +154,15 @@ static const char *setup_git_directory_1(void)
|
|||
break;
|
||||
chdir("..");
|
||||
do {
|
||||
if (!offset)
|
||||
if (!offset) {
|
||||
if (nongit_ok) {
|
||||
if (chdir(cwd))
|
||||
die("Cannot come back to cwd");
|
||||
*nongit_ok = 1;
|
||||
return NULL;
|
||||
}
|
||||
die("Not a git repository");
|
||||
}
|
||||
} while (cwd[--offset] != '/');
|
||||
}
|
||||
|
||||
|
@ -154,8 +176,25 @@ static const char *setup_git_directory_1(void)
|
|||
return cwd + offset;
|
||||
}
|
||||
|
||||
int check_repository_format_version(const char *var, const char *value)
|
||||
{
|
||||
if (strcmp(var, "core.repositoryformatversion") == 0)
|
||||
repository_format_version = git_config_int(var, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int check_repository_format(void)
|
||||
{
|
||||
git_config(check_repository_format_version);
|
||||
if (GIT_REPO_VERSION < repository_format_version)
|
||||
die ("Expected git repo version <= %d, found %d",
|
||||
GIT_REPO_VERSION, repository_format_version);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *setup_git_directory(void)
|
||||
{
|
||||
const char *retval = setup_git_directory_1();
|
||||
const char *retval = setup_git_directory_gently(NULL);
|
||||
check_repository_format();
|
||||
return retval;
|
||||
}
|
||||
|
|
3
shell.c
3
shell.c
|
@ -5,8 +5,7 @@ static int do_generic_cmd(const char *me, char *arg)
|
|||
{
|
||||
const char *my_argv[4];
|
||||
|
||||
arg = sq_dequote(arg);
|
||||
if (!arg)
|
||||
if (!arg || !(arg = sq_dequote(arg)))
|
||||
die("bad argument");
|
||||
|
||||
my_argv[0] = me;
|
||||
|
|
|
@ -131,6 +131,8 @@ int main(int argc, char **argv)
|
|||
prog = getenv("GIT_SSH_PUSH");
|
||||
if (!prog) prog = "git-ssh-upload";
|
||||
|
||||
setup_git_directory();
|
||||
|
||||
while (arg < argc && argv[arg][0] == '-') {
|
||||
if (argv[arg][1] == 't') {
|
||||
get_tree = 1;
|
||||
|
|
|
@ -121,6 +121,9 @@ int main(int argc, char **argv)
|
|||
|
||||
prog = getenv(COUNTERPART_ENV_NAME);
|
||||
if (!prog) prog = COUNTERPART_PROGRAM_NAME;
|
||||
|
||||
setup_git_directory();
|
||||
|
||||
while (arg < argc && argv[arg][0] == '-') {
|
||||
if (argv[arg][1] == 'w')
|
||||
arg++;
|
||||
|
|
|
@ -126,19 +126,18 @@ test_expect_success \
|
|||
'git-ls-tree output for a known tree.' \
|
||||
'diff current expected'
|
||||
|
||||
# This changed in ls-tree pathspec change -- recursive does
|
||||
# not show tree nodes anymore.
|
||||
test_expect_success \
|
||||
'showing tree with git-ls-tree -r' \
|
||||
'git-ls-tree -r $tree >current'
|
||||
cat >expected <<\EOF
|
||||
100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0
|
||||
120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym
|
||||
040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe path2
|
||||
100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 path2/file2
|
||||
120000 blob d8ce161addc5173867a3c3c730924388daedbc38 path2/file2sym
|
||||
040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3 path3
|
||||
100644 blob 0aa34cae68d0878578ad119c86ca2b5ed5b28376 path3/file3
|
||||
120000 blob 8599103969b43aff7e430efea79ca4636466794f path3/file3sym
|
||||
040000 tree 3c5e5399f3a333eddecce7a9b9465b63f65f51e2 path3/subp3
|
||||
100644 blob 00fb5908cb97c2564a9783c0c64087333b3b464f path3/subp3/file3
|
||||
120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c path3/subp3/file3sym
|
||||
EOF
|
||||
|
|
|
@ -54,6 +54,18 @@ test_expect_success \
|
|||
cat >expected <<\EOF &&
|
||||
100644 blob X path0
|
||||
120000 blob X path1
|
||||
100644 blob X path2/baz/b
|
||||
120000 blob X path2/bazbo
|
||||
100644 blob X path2/foo
|
||||
EOF
|
||||
test_output'
|
||||
|
||||
test_expect_success \
|
||||
'ls-tree recursive with -t' \
|
||||
'git-ls-tree -r -t $tree >current &&
|
||||
cat >expected <<\EOF &&
|
||||
100644 blob X path0
|
||||
120000 blob X path1
|
||||
040000 tree X path2
|
||||
040000 tree X path2/baz
|
||||
100644 blob X path2/baz/b
|
||||
|
@ -62,6 +74,15 @@ test_expect_success \
|
|||
EOF
|
||||
test_output'
|
||||
|
||||
test_expect_success \
|
||||
'ls-tree recursive with -d' \
|
||||
'git-ls-tree -r -d $tree >current &&
|
||||
cat >expected <<\EOF &&
|
||||
040000 tree X path2
|
||||
040000 tree X path2/baz
|
||||
EOF
|
||||
test_output'
|
||||
|
||||
test_expect_success \
|
||||
'ls-tree filtered with path' \
|
||||
'git-ls-tree $tree path >current &&
|
||||
|
@ -70,12 +91,14 @@ EOF
|
|||
test_output'
|
||||
|
||||
|
||||
# it used to be path1 and then path0, but with pathspec semantics
|
||||
# they are shown in canonical order.
|
||||
test_expect_success \
|
||||
'ls-tree filtered with path1 path0' \
|
||||
'git-ls-tree $tree path1 path0 >current &&
|
||||
cat >expected <<\EOF &&
|
||||
120000 blob X path1
|
||||
100644 blob X path0
|
||||
120000 blob X path1
|
||||
EOF
|
||||
test_output'
|
||||
|
||||
|
@ -86,45 +109,49 @@ test_expect_success \
|
|||
EOF
|
||||
test_output'
|
||||
|
||||
# It used to show path2 and its immediate children but
|
||||
# with pathspec semantics it shows only path2
|
||||
test_expect_success \
|
||||
'ls-tree filtered with path2' \
|
||||
'git-ls-tree $tree path2 >current &&
|
||||
cat >expected <<\EOF &&
|
||||
040000 tree X path2
|
||||
EOF
|
||||
test_output'
|
||||
|
||||
# ... and path2/ shows the children.
|
||||
test_expect_success \
|
||||
'ls-tree filtered with path2/' \
|
||||
'git-ls-tree $tree path2/ >current &&
|
||||
cat >expected <<\EOF &&
|
||||
040000 tree X path2/baz
|
||||
120000 blob X path2/bazbo
|
||||
100644 blob X path2/foo
|
||||
EOF
|
||||
test_output'
|
||||
|
||||
# The same change -- exact match does not show children of
|
||||
# path2/baz
|
||||
test_expect_success \
|
||||
'ls-tree filtered with path2/baz' \
|
||||
'git-ls-tree $tree path2/baz >current &&
|
||||
cat >expected <<\EOF &&
|
||||
040000 tree X path2/baz
|
||||
100644 blob X path2/baz/b
|
||||
EOF
|
||||
test_output'
|
||||
|
||||
test_expect_success \
|
||||
'ls-tree filtered with path2' \
|
||||
'git-ls-tree $tree path2 >current &&
|
||||
'ls-tree filtered with path2/bak' \
|
||||
'git-ls-tree $tree path2/bak >current &&
|
||||
cat >expected <<\EOF &&
|
||||
040000 tree X path2
|
||||
040000 tree X path2/baz
|
||||
120000 blob X path2/bazbo
|
||||
100644 blob X path2/foo
|
||||
EOF
|
||||
test_output'
|
||||
|
||||
test_expect_success \
|
||||
'ls-tree filtered with path2/' \
|
||||
'git-ls-tree $tree path2/ >current &&
|
||||
'ls-tree -t filtered with path2/bak' \
|
||||
'git-ls-tree -t $tree path2/bak >current &&
|
||||
cat >expected <<\EOF &&
|
||||
040000 tree X path2
|
||||
040000 tree X path2/baz
|
||||
120000 blob X path2/bazbo
|
||||
100644 blob X path2/foo
|
||||
EOF
|
||||
test_output'
|
||||
|
||||
|
|
|
@ -59,24 +59,16 @@ test_expect_success \
|
|||
EOF
|
||||
test_output'
|
||||
|
||||
# Recursive does not show tree nodes anymore...
|
||||
test_expect_success \
|
||||
'ls-tree recursive' \
|
||||
'git-ls-tree -r $tree >current &&
|
||||
cat >expected <<\EOF &&
|
||||
100644 blob X 1.txt
|
||||
100644 blob X 2.txt
|
||||
040000 tree X path0
|
||||
040000 tree X path0/a
|
||||
040000 tree X path0/a/b
|
||||
040000 tree X path0/a/b/c
|
||||
100644 blob X path0/a/b/c/1.txt
|
||||
040000 tree X path1
|
||||
040000 tree X path1/b
|
||||
040000 tree X path1/b/c
|
||||
100644 blob X path1/b/c/1.txt
|
||||
040000 tree X path2
|
||||
100644 blob X path2/1.txt
|
||||
040000 tree X path3
|
||||
100644 blob X path3/1.txt
|
||||
100644 blob X path3/2.txt
|
||||
EOF
|
||||
|
@ -110,41 +102,27 @@ test_expect_success \
|
|||
EOF
|
||||
test_output'
|
||||
|
||||
# I am not so sure about this one after ls-tree doing pathspec match.
|
||||
# Having both path0/a and path0/a/b/c makes path0/a redundant, and
|
||||
# it behaves as if path0/a/b/c, path1/b/c, path2 and path3 are specified.
|
||||
test_expect_success \
|
||||
'ls-tree filter directories' \
|
||||
'git-ls-tree $tree path3 path2 path0/a/b/c path1/b/c path0/a >current &&
|
||||
cat >expected <<\EOF &&
|
||||
040000 tree X path3
|
||||
100644 blob X path3/1.txt
|
||||
100644 blob X path3/2.txt
|
||||
040000 tree X path2
|
||||
100644 blob X path2/1.txt
|
||||
040000 tree X path0/a/b/c
|
||||
100644 blob X path0/a/b/c/1.txt
|
||||
040000 tree X path1/b/c
|
||||
100644 blob X path1/b/c/1.txt
|
||||
040000 tree X path0/a
|
||||
040000 tree X path0/a/b
|
||||
040000 tree X path2
|
||||
040000 tree X path3
|
||||
EOF
|
||||
test_output'
|
||||
|
||||
# Again, duplicates are filtered away so this is equivalent to
|
||||
# having 1.txt and path3
|
||||
test_expect_success \
|
||||
'ls-tree filter odd names' \
|
||||
'git-ls-tree $tree 1.txt /1.txt //1.txt path3/1.txt /path3/1.txt //path3//1.txt path3 /path3/ path3// >current &&
|
||||
cat >expected <<\EOF &&
|
||||
100644 blob X 1.txt
|
||||
100644 blob X 1.txt
|
||||
100644 blob X 1.txt
|
||||
100644 blob X path3/1.txt
|
||||
100644 blob X path3/1.txt
|
||||
100644 blob X path3/1.txt
|
||||
040000 tree X path3
|
||||
100644 blob X path3/1.txt
|
||||
100644 blob X path3/2.txt
|
||||
040000 tree X path3
|
||||
100644 blob X path3/1.txt
|
||||
100644 blob X path3/2.txt
|
||||
040000 tree X path3
|
||||
100644 blob X path3/1.txt
|
||||
100644 blob X path3/2.txt
|
||||
EOF
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2005 Fredrik Kuivinen
|
||||
#
|
||||
|
||||
test_description='Test merge with directory/file conflicts'
|
||||
. ./test-lib.sh
|
||||
|
||||
test_expect_success 'prepare repository' \
|
||||
'echo "Hello" > init &&
|
||||
git add init &&
|
||||
git commit -m "Initial commit" &&
|
||||
git branch B &&
|
||||
mkdir dir &&
|
||||
echo "foo" > dir/foo &&
|
||||
git add dir/foo &&
|
||||
git commit -m "File: dir/foo" &&
|
||||
git checkout B &&
|
||||
echo "file dir" > dir &&
|
||||
git add dir &&
|
||||
git commit -m "File: dir"'
|
||||
|
||||
test_expect_code 1 'Merge with d/f conflicts' 'git merge "merge msg" B master'
|
||||
|
||||
test_done
|
|
@ -0,0 +1,92 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2005 Fredrik Kuivinen
|
||||
#
|
||||
|
||||
# See http://marc.theaimsgroup.com/?l=git&m=111463358500362&w=2 for a
|
||||
# nice decription of what this is about.
|
||||
|
||||
|
||||
test_description='Test criss-cross merge'
|
||||
. ./test-lib.sh
|
||||
|
||||
test_expect_success 'prepare repository' \
|
||||
'echo "1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9" > file &&
|
||||
git add file &&
|
||||
git commit -m "Initial commit" file &&
|
||||
git branch A &&
|
||||
git branch B &&
|
||||
git checkout A &&
|
||||
echo "1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8 changed in B8, branch A
|
||||
9" > file &&
|
||||
git commit -m "B8" file &&
|
||||
git checkout B &&
|
||||
echo "1
|
||||
2
|
||||
3 changed in C3, branch B
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
" > file &&
|
||||
git commit -m "C3" file &&
|
||||
git branch C3 &&
|
||||
git merge "pre E3 merge" B A &&
|
||||
echo "1
|
||||
2
|
||||
3 changed in E3, branch B. New file size
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8 changed in B8, branch A
|
||||
9
|
||||
" > file &&
|
||||
git commit -m "E3" file &&
|
||||
git checkout A &&
|
||||
git merge "pre D8 merge" A C3 &&
|
||||
echo "1
|
||||
2
|
||||
3 changed in C3, branch B
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8 changed in D8, branch A. New file size 2
|
||||
9" > file &&
|
||||
git commit -m D8 file'
|
||||
|
||||
test_expect_success 'Criss-cross merge' 'git merge "final merge" A B'
|
||||
|
||||
cat > file-expect <<EOF
|
||||
1
|
||||
2
|
||||
3 changed in E3, branch B. New file size
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8 changed in D8, branch A. New file size 2
|
||||
9
|
||||
EOF
|
||||
|
||||
test_expect_success 'Criss-cross merge result' 'cmp file file-expect'
|
||||
|
||||
test_done
|
|
@ -0,0 +1,27 @@
|
|||
#!/bin/sh
|
||||
|
||||
test_description='git-mv in subdirs'
|
||||
. ./test-lib.sh
|
||||
|
||||
test_expect_success \
|
||||
'prepare reference tree' \
|
||||
'mkdir path0 path1 &&
|
||||
cp ../../COPYING path0/COPYING &&
|
||||
git-add path0/COPYING &&
|
||||
git-commit -m add -a'
|
||||
|
||||
test_expect_success \
|
||||
'moving the file' \
|
||||
'cd path0 && git-mv COPYING ../path1/COPYING'
|
||||
|
||||
# in path0 currently
|
||||
test_expect_success \
|
||||
'commiting the change' \
|
||||
'cd .. && git-commit -m move -a'
|
||||
|
||||
test_expect_success \
|
||||
'checking the commit' \
|
||||
'git-diff-tree -r -M --name-status HEAD^ HEAD | \
|
||||
grep -E "^R100.+path0/COPYING.+path1/COPYING"'
|
||||
|
||||
test_done
|
|
@ -133,6 +133,19 @@ test_expect_success () {
|
|||
fi
|
||||
}
|
||||
|
||||
test_expect_code () {
|
||||
test "$#" = 3 ||
|
||||
error "bug in the test script: not 3 parameters to test-expect-code"
|
||||
say >&3 "expecting exit code $1: $3"
|
||||
test_run_ "$3"
|
||||
if [ "$?" = 0 -a "$eval_ret" = "$1" ]
|
||||
then
|
||||
test_ok_ "$2"
|
||||
else
|
||||
test_failure_ "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
test_done () {
|
||||
trap - exit
|
||||
case "$test_failure" in
|
||||
|
|
|
@ -407,6 +407,8 @@ int main(int argc, char **argv)
|
|||
void *buffer;
|
||||
unsigned long size;
|
||||
|
||||
setup_git_directory();
|
||||
|
||||
switch (argc) {
|
||||
case 3:
|
||||
basedir = argv[2];
|
||||
|
|
34
tree.c
34
tree.c
|
@ -9,9 +9,16 @@ const char *tree_type = "tree";
|
|||
|
||||
static int read_one_entry(unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage)
|
||||
{
|
||||
int len = strlen(pathname);
|
||||
unsigned int size = cache_entry_size(baselen + len);
|
||||
struct cache_entry *ce = xmalloc(size);
|
||||
int len;
|
||||
unsigned int size;
|
||||
struct cache_entry *ce;
|
||||
|
||||
if (S_ISDIR(mode))
|
||||
return READ_TREE_RECURSIVE;
|
||||
|
||||
len = strlen(pathname);
|
||||
size = cache_entry_size(baselen + len);
|
||||
ce = xmalloc(size);
|
||||
|
||||
memset(ce, 0, size);
|
||||
|
||||
|
@ -67,9 +74,10 @@ static int match_tree_entry(const char *base, int baselen, const char *path, uns
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int read_tree_recursive(void *buffer, unsigned long size,
|
||||
const char *base, int baselen,
|
||||
int stage, const char **match)
|
||||
int read_tree_recursive(void *buffer, unsigned long size,
|
||||
const char *base, int baselen,
|
||||
int stage, const char **match,
|
||||
read_tree_fn_t fn)
|
||||
{
|
||||
while (size) {
|
||||
int len = strlen(buffer)+1;
|
||||
|
@ -86,6 +94,14 @@ static int read_tree_recursive(void *buffer, unsigned long size,
|
|||
if (!match_tree_entry(base, baselen, path, mode, match))
|
||||
continue;
|
||||
|
||||
switch (fn(sha1, base, baselen, path, mode, stage)) {
|
||||
case 0:
|
||||
continue;
|
||||
case READ_TREE_RECURSIVE:
|
||||
break;;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
if (S_ISDIR(mode)) {
|
||||
int retval;
|
||||
int pathlen = strlen(path);
|
||||
|
@ -106,22 +122,20 @@ static int read_tree_recursive(void *buffer, unsigned long size,
|
|||
retval = read_tree_recursive(eltbuf, eltsize,
|
||||
newbase,
|
||||
baselen + pathlen + 1,
|
||||
stage, match);
|
||||
stage, match, fn);
|
||||
free(eltbuf);
|
||||
free(newbase);
|
||||
if (retval)
|
||||
return -1;
|
||||
continue;
|
||||
}
|
||||
if (read_one_entry(sha1, base, baselen, path, mode, stage) < 0)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_tree(void *buffer, unsigned long size, int stage, const char **match)
|
||||
{
|
||||
return read_tree_recursive(buffer, size, "", 0, stage, match);
|
||||
return read_tree_recursive(buffer, size, "", 0, stage, match, read_one_entry);
|
||||
}
|
||||
|
||||
struct tree *lookup_tree(const unsigned char *sha1)
|
||||
|
|
9
tree.h
9
tree.h
|
@ -35,4 +35,13 @@ int parse_tree(struct tree *tree);
|
|||
/* Parses and returns the tree in the given ent, chasing tags and commits. */
|
||||
struct tree *parse_tree_indirect(const unsigned char *sha1);
|
||||
|
||||
#define READ_TREE_RECURSIVE 1
|
||||
typedef int (*read_tree_fn_t)(unsigned char *, const char *, int, const char *, unsigned int, int);
|
||||
|
||||
extern int read_tree_recursive(void *buffer, unsigned long size,
|
||||
const char *base, int baselen,
|
||||
int stage, const char **match,
|
||||
read_tree_fn_t fn);
|
||||
|
||||
|
||||
#endif /* TREE_H */
|
||||
|
|
|
@ -29,6 +29,8 @@ int main(int argc, char **argv)
|
|||
if (argc != 2 || get_sha1(argv[1], sha1))
|
||||
usage("git-unpack-file <sha1>");
|
||||
|
||||
setup_git_directory();
|
||||
|
||||
puts(create_temp_file(sha1));
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -269,6 +269,8 @@ int main(int argc, char **argv)
|
|||
int i;
|
||||
unsigned char sha1[20];
|
||||
|
||||
setup_git_directory();
|
||||
|
||||
for (i = 1 ; i < argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
|
||||
|
|
|
@ -19,5 +19,7 @@ int main(int ac, char **av)
|
|||
if (i != ac)
|
||||
usage(update_server_info_usage);
|
||||
|
||||
setup_git_directory();
|
||||
|
||||
return !!update_server_info(force);
|
||||
}
|
||||
|
|
|
@ -86,9 +86,12 @@ static int write_tree(struct cache_entry **cachep, int maxentries, const char *b
|
|||
int main(int argc, char **argv)
|
||||
{
|
||||
int i, funny;
|
||||
int entries = read_cache();
|
||||
int entries;
|
||||
unsigned char sha1[20];
|
||||
|
||||
setup_git_directory();
|
||||
|
||||
entries = read_cache();
|
||||
if (argc == 2) {
|
||||
if (!strcmp(argv[1], "--missing-ok"))
|
||||
missing_ok = 1;
|
||||
|
|
Загрузка…
Ссылка в новой задаче