Merge with git://repo.or.cz/git.git#next.

This commit is contained in:
Johannes Sixt
2007-01-25 11:50:13 +01:00
68 changed files with 1302 additions and 336 deletions

View File

@@ -30,7 +30,9 @@ Robert Fitzsimons <robfitz@273k.net>
Santi Béjar <sbejar@gmail.com>
Sean Estabrooks <seanlkml@sympatico.ca>
Shawn O. Pearce <spearce@spearce.org>
Theodore Ts'o <tytso@mit.edu>
Tony Luck <tony.luck@intel.com>
Uwe Kleine-König <zeisberg@informatik.uni-freiburg.de>
Ville Skyttä <scop@xemacs.org>
YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
anonymous <linux@horizon.com>

View File

@@ -4,5 +4,4 @@
*.7
howto-index.txt
doc.dep
README
cmds-*.txt

View File

@@ -76,9 +76,12 @@ cmds_txt = cmds-ancillaryinterrogators.txt \
cmds-mainporcelain.txt \
cmds-plumbinginterrogators.txt \
cmds-plumbingmanipulators.txt \
cmds-synchingrepositories.txt
cmds-synchingrepositories.txt \
cmds-synchelpers.txt \
cmds-purehelpers.txt \
cmds-foreignscminterface.txt
$(cmds_txt): cmd-list.perl $(MAN1_TXT) $(MAN7_TXT)
$(cmds_txt): cmd-list.perl $(MAN1_TXT)
perl ./cmd-list.perl
git.7 git.html: git.txt core-intro.txt

View File

@@ -45,7 +45,10 @@ for my $cat (qw(ancillaryinterrogators
mainporcelain
plumbinginterrogators
plumbingmanipulators
synchingrepositories)) {
synchingrepositories
foreignscminterface
purehelpers
synchelpers)) {
my $out = "cmds-$cat.txt";
open O, '>', "$out+" or die "Cannot open output file $out+";
for (@{$cmds{$cat}}) {
@@ -59,10 +62,10 @@ __DATA__
git-add mainporcelain
git-am mainporcelain
git-annotate ancillaryinterrogators
git-applymbox mainporcelain
git-applypatch ancillarymanipulators
git-applymbox ancillaryinterrogators
git-applypatch purehelpers
git-apply plumbingmanipulators
git-archimport ancillarymanipulators
git-archimport foreignscminterface
git-archive mainporcelain
git-bisect mainporcelain
git-blame ancillaryinterrogators
@@ -70,7 +73,7 @@ git-branch mainporcelain
git-cat-file plumbinginterrogators
git-checkout-index plumbingmanipulators
git-checkout mainporcelain
git-check-ref-format ancillaryinterrogators
git-check-ref-format purehelpers
git-cherry ancillaryinterrogators
git-cherry-pick mainporcelain
git-clean mainporcelain
@@ -79,11 +82,11 @@ git-commit mainporcelain
git-commit-tree plumbingmanipulators
git-convert-objects ancillarymanipulators
git-count-objects ancillaryinterrogators
git-cvsexportcommit ancillarymanipulators
git-cvsimport ancillarymanipulators
git-cvsserver ancillarymanipulators
git-daemon ancillaryinterrogators
git-describe plumbinginterrogators
git-cvsexportcommit foreignscminterface
git-cvsimport foreignscminterface
git-cvsserver foreignscminterface
git-daemon synchingrepositories
git-describe mainporcelain
git-diff-files plumbinginterrogators
git-diff-index plumbinginterrogators
git-diff mainporcelain
@@ -91,34 +94,34 @@ git-diff-stages plumbinginterrogators
git-diff-tree plumbinginterrogators
git-fetch mainporcelain
git-fetch-pack synchingrepositories
git-fmt-merge-msg ancillaryinterrogators
git-fmt-merge-msg purehelpers
git-for-each-ref plumbinginterrogators
git-format-patch mainporcelain
git-fsck-objects plumbinginterrogators
git-gc ancillarymanipulators
git-fsck-objects ancillaryinterrogators
git-gc mainporcelain
git-get-tar-commit-id ancillaryinterrogators
git-grep mainporcelain
git-hash-object plumbingmanipulators
git-http-fetch synchingrepositories
git-http-push synchingrepositories
git-imap-send ancillaryinterrogators
git-http-fetch synchelpers
git-http-push synchelpers
git-imap-send foreignscminterface
git-index-pack plumbingmanipulators
git-init plumbingmanipulators
git-init mainporcelain
git-instaweb ancillaryinterrogators
gitk mainporcelain
git-local-fetch synchingrepositories
git-log mainporcelain
git-lost-found ancillarymanipulators
git-ls-files plumbinginterrogators
git-ls-remote mainporcelain
git-ls-remote plumbinginterrogators
git-ls-tree plumbinginterrogators
git-mailinfo ancillaryinterrogators
git-mailsplit ancillaryinterrogators
git-mailinfo purehelpers
git-mailsplit purehelpers
git-merge-base plumbinginterrogators
git-merge-file plumbingmanipulators
git-merge-index plumbingmanipulators
git-merge mainporcelain
git-merge-one-file ancillarymanipulators
git-merge-one-file purehelpers
git-merge-tree ancillaryinterrogators
git-mktag plumbingmanipulators
git-mktree plumbingmanipulators
@@ -126,24 +129,24 @@ git-mv mainporcelain
git-name-rev plumbinginterrogators
git-pack-objects plumbingmanipulators
git-pack-redundant plumbinginterrogators
git-pack-refs mainporcelain
git-parse-remote ancillaryinterrogators
git-patch-id ancillaryinterrogators
git-peek-remote synchingrepositories
git-pack-refs ancillarymanipulators
git-parse-remote synchelpers
git-patch-id purehelpers
git-peek-remote purehelpers
git-prune ancillarymanipulators
git-prune-packed plumbingmanipulators
git-pull mainporcelain
git-push mainporcelain
git-quiltimport ancillarymanipulators
git-quiltimport foreignscminterface
git-read-tree plumbingmanipulators
git-rebase mainporcelain
git-receive-pack synchingrepositories
git-receive-pack synchelpers
git-reflog ancillarymanipulators
git-relink ancillarymanipulators
git-repack mainporcelain
git-repo-config plumbingmanipulators
git-request-pull ancillaryinterrogators
git-rerere mainporcelain
git-repack ancillarymanipulators
git-repo-config ancillarymanipulators
git-request-pull foreignscminterface
git-rerere ancillaryinterrogators
git-reset mainporcelain
git-resolve mainporcelain
git-revert mainporcelain
@@ -151,34 +154,33 @@ git-rev-list plumbinginterrogators
git-rev-parse ancillaryinterrogators
git-rm mainporcelain
git-runstatus ancillaryinterrogators
git-send-email ancillaryinterrogators
git-send-email foreignscminterface
git-send-pack synchingrepositories
git-shell synchingrepositories
git-shell synchelpers
git-shortlog mainporcelain
git-show mainporcelain
git-show-branch mainporcelain
git-show-branch ancillaryinterrogators
git-show-index plumbinginterrogators
git-show-ref plumbinginterrogators
git-sh-setup ancillarymanipulators
git-sh-setup purehelpers
git-ssh-fetch synchingrepositories
git-ssh-upload synchingrepositories
git-status mainporcelain
git-stripspace ancillaryinterrogators
git-svn ancillarymanipulators
git-svnimport ancillarymanipulators
git-symbolic-ref ancillaryinterrogators
git-symbolic-ref ancillarymanipulators
git-tag ancillarymanipulators
git-stripspace purehelpers
git-svn foreignscminterface
git-svnimport foreignscminterface
git-symbolic-ref plumbingmanipulators
git-tag mainporcelain
git-tar-tree plumbinginterrogators
git-unpack-file plumbinginterrogators
git-unpack-objects plumbingmanipulators
git-update-index plumbingmanipulators
git-update-ref ancillarymanipulators
git-update-ref plumbingmanipulators
git-update-server-info synchingrepositories
git-upload-archive synchingrepositories
git-upload-pack synchingrepositories
git-upload-archive synchelpers
git-upload-pack synchelpers
git-var plumbinginterrogators
git-verify-pack plumbinginterrogators
git-verify-tag mainporcelain
git-whatchanged mainporcelain
git-verify-tag ancillaryinterrogators
git-whatchanged ancillaryinterrogators
git-write-tree plumbingmanipulators

View File

@@ -14,14 +14,72 @@ dot-separated segment and the section name is everything before the last
dot. The variable names are case-insensitive and only alphanumeric
characters are allowed. Some variables may appear multiple times.
Syntax
~~~~~~
The syntax is fairly flexible and permissive; whitespaces are mostly
ignored. The '#' and ';' characters begin comments to the end of line,
blank lines are ignored, lines containing strings enclosed in square
brackets start sections and all the other lines are recognized
as setting variables, in the form 'name = value'. If there is no equal
sign on the line, the entire line is taken as 'name' and the variable
is recognized as boolean "true". String values may be entirely or partially
enclosed in double quotes; some variables may require special value format.
ignored. The '#' and ';' characters begin comments to the end of line,
blank lines are ignored.
The file consists of sections and variables. A section begins with
the name of the section in square brackets and continues until the next
section begins. Section names are not case sensitive. Only alphanumeric
characters, '`-`' and '`.`' are allowed in section names. Each variable
must belong to some section, which means that there must be section
header before first setting of a variable.
Sections can be further divided into subsections. To begin a subsection
put its name in double quotes, separated by space from the section name,
in the section header, like in example below:
--------
[section "subsection"]
--------
Subsection names can contain any characters except newline (doublequote
'`"`' and backslash have to be escaped as '`\"`' and '`\\`',
respecitvely) and are case sensitive. Section header cannot span multiple
lines. Variables may belong directly to a section or to a given subsection.
You can have `[section]` if you have `[section "subsection"]`, but you
don't need to.
There is also (case insensitive) alternative `[section.subsection]` syntax.
In this syntax subsection names follow the same restrictions as for section
name.
All the other lines are recognized as setting variables, in the form
'name = value'. If there is no equal sign on the line, the entire line
is taken as 'name' and the variable is recognized as boolean "true".
The variable names are case-insensitive and only alphanumeric
characters and '`-`' are allowed. There can be more than one value
for a given variable; we say then that variable is multivalued.
Leading and trailing whitespace in a variable value is discarded.
Internal whitespace within a variable value is retained verbatim.
The values following the equals sign in variable assign are all either
a string, an integer, or a boolean. Boolean values may be given as yes/no,
0/1 or true/false. Case is not significant in boolean values, when
converting value to the canonical form using '--bool' type specifier;
`git-repo-config` will ensure that the output is "true" or "false".
String values may be entirely or partially enclosed in double quotes.
You need to enclose variable value in double quotes if you want to
preserve leading or trailing whitespace, or if variable value contains
beginning of comment characters (if it contains '#' or ';').
Double quote '`"`' and backslash '`\`' characters in variable value must
be escaped: use '`\"`' for '`"`' and '`\\`' for '`\`'.
The following escape sequences (beside '`\"`' and '`\\`') are recognized:
'`\n`' for newline character (NL), '`\t`' for horizontal tabulation (HT, TAB)
and '`\b`' for backspace (BS). No other char escape sequence, nor octal
char sequences are valid.
Variable value ending in a '`\`' is continued on the next line in the
customary UNIX fashion.
Some variables may require special value format.
Example
~~~~~~~
@@ -40,6 +98,10 @@ Example
remote = origin
merge = refs/heads/devel
# Proxy settings
[core]
gitProxy="ssh" for "ssh://kernel.org/"
gitProxy=default-proxy ; for the rest
Variables
~~~~~~~~~
@@ -233,6 +295,16 @@ diff.renames::
will enable basic rename detection. If set to "copies" or
"copy", it will detect copies, as well.
fetch.unpackLimit::
If the number of objects fetched over the git native
transfer is below this
limit, then the objects will be unpacked into loose object
files. However if the number of received objects equals or
exceeds this limit then the received pack will be stored as
a pack, after adding any missing delta bases. Storing the
pack from a push can make the push operation complete faster,
especially on slow filesystems.
format.headers::
Additional email headers to include in a patch to be submitted
by mail. See gitlink:git-format-patch[1].
@@ -356,6 +428,10 @@ remote.<name>.push::
The default set of "refspec" for gitlink:git-push[1]. See
gitlink:git-push[1].
remote.<name>.receivepack::
The default program to execute on the remote side when pulling. See
option \--exec of gitlink:git-push[1].
repack.usedeltabaseoffset::
Allow gitlink:git-repack[1] to create packs that uses
delta-base offset. Defaults to false.
@@ -412,3 +488,8 @@ receive.denyNonFastForwards::
even if that push is forced. This configuration variable is
set when initializing a shared repository.
transfer.unpackLimit::
When `fetch.unpackLimit` or `receive.unpackLimit` are
not set, the value of this variable is used instead.

View File

@@ -8,8 +8,8 @@ git-commit - Record changes to the repository
SYNOPSIS
--------
[verse]
'git-commit' [-a] [-s] [-v] [(-c | -C) <commit> | -F <file> | -m <msg>]
[--no-verify] [--amend] [-e] [--author <author>]
'git-commit' [-a] [-s] [-v] [(-c | -C) <commit> | -F <file> | -m <msg> |
--amend] [--no-verify] [-e] [--author <author>]
[--] [[-i | -o ]<file>...]
DESCRIPTION

View File

@@ -131,14 +131,14 @@ Giving these options is an error when used with `--inetd`; use
the facility of inet daemon to achieve the same before spawning
`git-daemon` if needed.
--enable-service, --disable-service::
--enable=service, --disable=service::
Enable/disable the service site-wide per default. Note
that a service disabled site-wide can still be enabled
per repository if it is marked overridable and the
repository enables the service with an configuration
item.
--allow-override, --forbid-override::
--allow-override=service, --forbid-override=service::
Allow/forbid overriding the site-wide default with per
repository configuration. By default, all the services
are overridable.

View File

@@ -8,7 +8,7 @@ git-fetch-pack - Receive missing objects from another repository
SYNOPSIS
--------
'git-fetch-pack' [-q] [-k] [--exec=<git-upload-pack>] [<host>:]<directory> [<refs>...]
'git-fetch-pack' [--all] [--quiet|-q] [--keep|-k] [--thin] [--upload-pack=<git-upload-pack>] [--depth=<n>] [-v] [<host>:]<directory> [<refs>...]
DESCRIPTION
-----------
@@ -28,17 +28,24 @@ have a common ancestor commit.
OPTIONS
-------
-q::
\--all::
Fetch all remote refs.
\--quiet, \-q::
Pass '-q' flag to 'git-unpack-objects'; this makes the
cloning process less verbose.
-k::
\--keep, \-k::
Do not invoke 'git-unpack-objects' on received data, but
create a single packfile out of it instead, and store it
in the object database. If provided twice then the pack is
locked against repacking.
--exec=<git-upload-pack>::
\--thin::
Spend extra cycles to minimize the number of objects to be sent.
Use it on slower connection.
\--upload-pack=<git-upload-pack>::
Use this to specify the path to 'git-upload-pack' on the
remote side, if is not found on your $PATH.
Installations of sshd ignores the user's environment
@@ -50,6 +57,15 @@ OPTIONS
shells by having a lean .bashrc file (they set most of
the things up in .bash_profile).
\--exec=<git-upload-pack>::
Same as \--upload-pack=<git-upload-pack>.
\--depth=<n>::
Limit fetching to ancestor-chains not longer than n.
\-v::
Run verbosely.
<host>::
A remote host that houses the repository. When this
part is specified, 'git-upload-pack' is invoked via

View File

@@ -8,7 +8,7 @@ git-gc - Cleanup unnecessary files and optimize the local repository
SYNOPSIS
--------
'git-gc'
'git-gc' [--prune]
DESCRIPTION
-----------
@@ -21,6 +21,21 @@ Users are encouraged to run this task on a regular basis within
each repository to maintain good disk space utilization and good
operating performance.
OPTIONS
-------
--prune::
Usually `git-gc` packs refs, expires old reflog entries,
packs loose objects,
and removes old 'rerere' records. Removal
of unreferenced loose objects is an unsafe operation
while other git operations are in progress, so it is not
done by default. Pass this option if you want it, and only
when you know nobody else is creating new objects in the
repository at the same time (e.g. never use this option
in a cron script).
Configuration
-------------

View File

@@ -8,7 +8,7 @@ git-peek-remote - List the references in a remote repository
SYNOPSIS
--------
'git-peek-remote' [--exec=<git-upload-pack>] [<host>:]<directory>
'git-peek-remote' [--upload-pack=<git-upload-pack>] [<host>:]<directory>
DESCRIPTION
-----------
@@ -17,7 +17,7 @@ stores them in the local repository under the same name.
OPTIONS
-------
--exec=<git-upload-pack>::
\--upload-pack=<git-upload-pack>::
Use this to specify the path to 'git-upload-pack' on the
remote side, if it is not found on your $PATH. Some
installations of sshd ignores the user's environment
@@ -29,6 +29,9 @@ OPTIONS
shells, but prefer having a lean .bashrc file (they set most of
the things up in .bash_profile).
\--exec=<git-upload-pack>::
Same \--upload-pack=<git-upload-pack>.
<host>::
A remote host that houses the repository. When this
part is specified, 'git-upload-pack' is invoked via

View File

@@ -8,7 +8,7 @@ git-push - Update remote refs along with associated objects
SYNOPSIS
--------
'git-push' [--all] [--tags] [--exec=<receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]
'git-push' [--all] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]
DESCRIPTION
-----------
@@ -67,12 +67,15 @@ the remote repository.
addition to refspecs explicitly listed on the command
line.
\--exec::
\--receive-pack=<git-receive-pack>::
Path to the 'git-receive-pack' program on the remote
end. Sometimes useful when pushing to a remote
repository over ssh, and you do not have the program in
a directory on the default $PATH.
\--exec=<git-receive-pack>::
Same as \--receive-pack=<git-receive-pack>.
-f, \--force::
Usually, the command refuses to update a remote ref that is
not a descendant of the local ref used to overwrite it.

View File

@@ -27,6 +27,8 @@ SYNOPSIS
[ \--pretty | \--header ]
[ \--bisect ]
[ \--merge ]
[ \--reverse ]
[ \--walk-reflogs ]
<commit>... [ \-- <paths>... ]
DESCRIPTION
@@ -190,6 +192,22 @@ limiting may be applied.
In addition to the '<commit>' listed on the command
line, read them from the standard input.
-g, --walk-reflogs::
Instead of walking the commit ancestry chain, walk
reflog entries from the most recent one to older ones.
When this option is used you cannot specify commits to
exclude (that is, '{caret}commit', 'commit1..commit2',
nor 'commit1...commit2' notations cannot be used).
+
With '\--pretty' format other than oneline (for obvious reasons),
this causes the output to have two extra lines of information
taken from the reflog. By default, 'commit@{Nth}' notation is
used in the output. When the starting commit is specified as
'commit@{now}', output also uses 'commit@{timestamp}' notation
instead. Under '\--pretty=oneline', the commit message is
prefixed with this information on the same line.
--merge::
After a failed merge, show refs that touch files having a
@@ -249,6 +267,10 @@ By default, the commits are shown in reverse chronological order.
parent comes before all of its children, but otherwise things
are still ordered in the commit timestamp order.
--reverse::
Output the commits in reverse order.
Object Traversal
~~~~~~~~~~~~~~~~

View File

@@ -8,7 +8,7 @@ git-send-pack - Push objects over git protocol to another reposiotory
SYNOPSIS
--------
'git-send-pack' [--all] [--force] [--exec=<git-receive-pack>] [<host>:]<directory> [<ref>...]
'git-send-pack' [--all] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]
DESCRIPTION
-----------
@@ -21,23 +21,33 @@ updates it from the current repository, sending named refs.
OPTIONS
-------
--exec=<git-receive-pack>::
\--receive-pack=<git-receive-pack>::
Path to the 'git-receive-pack' program on the remote
end. Sometimes useful when pushing to a remote
repository over ssh, and you do not have the program in
a directory on the default $PATH.
--all::
\--exec=<git-receive-pack>::
Same as \--receive-pack=<git-receive-pack>.
\--all::
Instead of explicitly specifying which refs to update,
update all refs that locally exist.
--force::
\--force::
Usually, the command refuses to update a remote ref that
is not an ancestor of the local ref used to overwrite it.
This flag disables the check. What this means is that
the remote repository can lose commits; use it with
care.
\--verbose::
Run verbosely.
\--thin::
Spend extra cycles to minimize the number of objects to be sent.
Use it on slower connection.
<host>::
A remote host to house the repository. When this
part is specified, 'git-receive-pack' is invoked via

View File

@@ -11,7 +11,7 @@ SYNOPSIS
'git-show-branch' [--all] [--remotes] [--topo-order] [--current]
[--more=<n> | --list | --independent | --merge-base]
[--no-name | --sha1-name] [--topics] [<rev> | <glob>]...
'git-show-branch' --reflog[=<n>] <ref>
'git-show-branch' (-g|--reflog)[=<n>[,<base>]] [--list] <ref>
DESCRIPTION
-----------
@@ -97,9 +97,11 @@ OPTIONS
will show the revisions given by "git rev-list {caret}master
topic1 topic2"
--reflog[=<n>] <ref>::
Shows <n> most recent ref-log entries for the given ref.
--reflog[=<n>[,<base>]] <ref>::
Shows <n> most recent ref-log entries for the given
ref. If <base> is given, <n> entries going back from
that entry. <base> can be specified as count or date.
`-g` can be used as a short-hand for this option.
Note that --more, --list, --independent and --merge-base options
are mutually exclusive.
@@ -165,6 +167,13 @@ With this, `git show-branch` without extra parameters would show
only the primary branches. In addition, if you happen to be on
your topic branch, it is shown as well.
------------
$ git show-branch --reflog='10,1 hour ago' --list master
------------
shows 10 reflog entries going back from the tip as of 1 hour ago.
Without `--list`, the output also shows how these tips are
topologically related with each other.
Author

View File

@@ -3,14 +3,14 @@ git-tag(1)
NAME
----
git-tag - Create or verify a tag object signed with GPG
git-tag - Create, list, delete or verify a tag object signed with GPG
SYNOPSIS
--------
[verse]
'git-tag' [-a | -s | -u <key-id>] [-f | -d | -v] [-m <msg> | -F <file>]
<name> [<head>]
'git-tag' [-a | -s | -u <key-id>] [-f | -v] [-m <msg> | -F <file>] <name> [<head>]
'git-tag' -d <name>...
'git-tag' -l [<pattern>]
DESCRIPTION
@@ -55,7 +55,7 @@ OPTIONS
Replace an existing tag with the given name (instead of failing)
-d::
Delete an existing tag with the given name
Delete existing tags with the given names.
-v::
Verify the gpg signature of given the tag

View File

@@ -93,6 +93,16 @@ Interrogators:
include::cmds-ancillaryinterrogators.txt[]
Interacting with Others
~~~~~~~~~~~~~~~~~~~~~~~
These commands are to interact with foreign SCM and with other
people via patch over e-mail.
include::cmds-foreignscminterface.txt[]
Low-level commands (plumbing)
-----------------------------
@@ -102,11 +112,20 @@ development of alternative porcelains. Developers of such porcelains
might start by reading about gitlink:git-update-index[1] and
gitlink:git-read-tree[1].
We divide the low-level commands into commands that manipulate objects (in
The interface (input, output, set of options and the semantics)
to these low-level commands are meant to be a lot more stable
than Porcelain level commands, because these commands are
primarily for scripted use. The interface to Porcelain commands
on the other hand are subject to change in order to improve the
end user experience.
The following description divides
the low-level commands into commands that manipulate objects (in
the repository, index, and working tree), commands that interrogate and
compare objects, and commands that move objects and references between
repositories.
Manipulation commands
~~~~~~~~~~~~~~~~~~~~~
@@ -127,6 +146,20 @@ Synching repositories
include::cmds-synchingrepositories.txt[]
The following are helper programs used by the above; end users
typically do not use them directly.
include::cmds-synchelpers.txt[]
Internal helper commands
~~~~~~~~~~~~~~~~~~~~~~~~
These are internal helper commands used by other commands; end
users typically do not use them directly.
include::cmds-purehelpers.txt[]
Configuration Mechanism
-----------------------

View File

@@ -343,8 +343,8 @@ And, as you can see with cat-file, this new entry refers to the
current contents of the file:
------------------------------------------------
$ git cat-file blob a6b11f7a
goodbye, word
$ git cat-file blob 8b9743b2
goodbye, world
------------------------------------------------
The "status" command is a useful way to get a quick summary of the

View File

@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
DEF_VER=v1.5.0-rc1.GIT
DEF_VER=v1.5.0-rc2.GIT
LF='
'

View File

@@ -240,7 +240,7 @@ LIB_H = \
diff.h object.h pack.h pkt-line.h quote.h refs.h list-objects.h sideband.h \
run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \
tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h \
spawn-pipe.h utf8.h
spawn-pipe.h utf8.h reflog-walk.h
DIFF_OBJS = \
diff.o diff-lib.o diffcore-break.o diffcore-order.o \
@@ -254,7 +254,7 @@ LIB_OBJS = \
lockfile.o \
spawn-pipe.o \
object.o pack-check.o patch-delta.o path.o pkt-line.o sideband.o \
reachable.o \
reachable.o reflog-walk.o \
quote.o read-cache.o refs.o run-command.o dir.o object-refs.o \
server-info.o setup.o sha1_file.o sha1_name.o strbuf.o \
tag.o tree.o usage.o config.o environment.o ctype.o copy.o \

View File

@@ -2589,7 +2589,7 @@ static int git_apply_config(const char *var, const char *value)
}
int cmd_apply(int argc, const char **argv, const char *prefix)
int cmd_apply(int argc, const char **argv, const char *unused_prefix)
{
int i;
int read_stdin = 1;

View File

@@ -74,6 +74,7 @@ static int run_remote_archiver(const char *remote, int argc,
/* Now, start reading from fd[0] and spit it out to stdout */
rv = recv_sideband("archive", fd[0], 1, 2);
close(fd[0]);
close(fd[1]);
rv |= finish_connect(pid);
return !!rv;

View File

@@ -324,7 +324,7 @@ static void create_branch(const char *name, const char *start_name,
if (resolve_ref(ref, sha1, 1, NULL)) {
if (!force)
die("A branch named '%s' already exists.", name);
else if (!strcmp(head, name))
else if (!is_bare_repository() && !strcmp(head, name))
die("Cannot force update the current branch.");
}

View File

@@ -257,7 +257,9 @@ static int create_default_files(const char *git_dir, const char *template_path)
}
else {
git_config_set("core.bare", "false");
git_config_set("core.logallrefupdates", "true");
/* allow template config file to override the default */
if (log_all_ref_updates == -1)
git_config_set("core.logallrefupdates", "true");
}
return reinit;
}

View File

@@ -50,8 +50,11 @@ static int cmd_log_walk(struct rev_info *rev)
prepare_revision_walk(rev);
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
if (!rev->reflog_info) {
/* we allow cycles in reflog ancestry */
free(commit->buffer);
commit->buffer = NULL;
}
free_commit_list(commit->parents);
commit->parents = NULL;
}
@@ -473,7 +476,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
if (!rev.diffopt.text)
rev.diffopt.binary = 1;
if (!output_directory)
if (!output_directory && !use_stdout)
output_directory = prefix;
if (output_directory) {

View File

@@ -8,10 +8,10 @@
#define MAX_URI (16)
static const char push_usage[] = "git-push [--all] [--tags] [-f | --force] <repository> [<refspec>...]";
static const char push_usage[] = "git-push [--all] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]";
static int all, tags, force, thin = 1, verbose;
static const char *execute;
static const char *receivepack;
#define BUF_SIZE (2084)
static char buffer[BUF_SIZE];
@@ -143,6 +143,7 @@ static const char *config_repo;
static int config_repo_len;
static int config_current_uri;
static int config_get_refspecs;
static int config_get_receivepack;
static int get_remote_config(const char* key, const char* value)
{
@@ -157,6 +158,15 @@ static int get_remote_config(const char* key, const char* value)
else if (config_get_refspecs &&
!strcmp(key + 7 + config_repo_len, ".push"))
add_refspec(xstrdup(value));
else if (config_get_receivepack &&
!strcmp(key + 7 + config_repo_len, ".receivepack")) {
if (!receivepack) {
char *rp = xmalloc(strlen(value) + 16);
sprintf(rp, "--receive-pack=%s", value);
receivepack = rp;
} else
error("more than one receivepack given, using the first");
}
}
return 0;
}
@@ -168,6 +178,7 @@ static int get_config_remotes_uri(const char *repo, const char *uri[MAX_URI])
config_current_uri = 0;
config_uri = uri;
config_get_refspecs = !(refspec_nr || all || tags);
config_get_receivepack = (receivepack == NULL);
git_config(get_remote_config);
return config_current_uri;
@@ -252,8 +263,8 @@ static int do_push(const char *repo)
argv[argc++] = "--all";
if (force)
argv[argc++] = "--force";
if (execute)
argv[argc++] = execute;
if (receivepack)
argv[argc++] = receivepack;
common_argc = argc;
for (i = 0; i < n; i++) {
@@ -336,8 +347,12 @@ int cmd_push(int argc, const char **argv, const char *prefix)
thin = 0;
continue;
}
if (!strncmp(arg, "--receive-pack=", 15)) {
receivepack = arg;
continue;
}
if (!strncmp(arg, "--exec=", 7)) {
execute = arg;
receivepack = arg;
continue;
}
usage(push_usage);

View File

@@ -263,9 +263,6 @@ static int expire_reflog(const char *ref, const unsigned char *sha1, int unused,
}
cb.ref_commit = lookup_commit_reference_gently(sha1, 1);
if (!cb.ref_commit)
fprintf(stderr,
"warning: ref '%s' does not point at a commit\n", ref);
cb.ref = ref;
cb.cmd = cmd;
for_each_reflog_ent(ref, expire_reflog_ent, &cb);

View File

@@ -4,7 +4,9 @@
#include "builtin.h"
static const char show_branch_usage[] =
"git-show-branch [--sparse] [--current] [--all] [--remotes] [--topo-order] [--more=count | --list | --independent | --merge-base ] [--topics] [<refs>...] | --reflog[=n] <branch>";
"git-show-branch [--sparse] [--current] [--all] [--remotes] [--topo-order] [--more=count | --list | --independent | --merge-base ] [--topics] [<refs>...] | --reflog[=n[,b]] <branch>";
static const char show_branch_usage_reflog[] =
"--reflog is incompatible with --all, --remotes, --independent or --merge-base";
static int default_num;
static int default_alloc;
@@ -346,18 +348,21 @@ static void sort_ref_range(int bottom, int top)
compare_ref_name);
}
static int append_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
static int append_ref(const char *refname, const unsigned char *sha1,
int allow_dups)
{
struct commit *commit = lookup_commit_reference_gently(sha1, 1);
int i;
if (!commit)
return 0;
/* Avoid adding the same thing twice */
for (i = 0; i < ref_name_cnt; i++)
if (!strcmp(refname, ref_name[i]))
return 0;
if (!allow_dups) {
/* Avoid adding the same thing twice */
for (i = 0; i < ref_name_cnt; i++)
if (!strcmp(refname, ref_name[i]))
return 0;
}
if (MAX_REVS <= ref_name_cnt) {
fprintf(stderr, "warning: ignoring %s; "
"cannot handle more than %d refs\n",
@@ -380,7 +385,7 @@ static int append_head_ref(const char *refname, const unsigned char *sha1, int f
*/
if (get_sha1(refname + ofs, tmp) || hashcmp(tmp, sha1))
ofs = 5;
return append_ref(refname + ofs, sha1, flag, cb_data);
return append_ref(refname + ofs, sha1, 0);
}
static int append_remote_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
@@ -394,14 +399,14 @@ static int append_remote_ref(const char *refname, const unsigned char *sha1, int
*/
if (get_sha1(refname + ofs, tmp) || hashcmp(tmp, sha1))
ofs = 5;
return append_ref(refname + ofs, sha1, flag, cb_data);
return append_ref(refname + ofs, sha1, 0);
}
static int append_tag_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
{
if (strncmp(refname, "refs/tags/", 10))
return 0;
return append_ref(refname + 5, sha1, flag, cb_data);
return append_ref(refname + 5, sha1, 0);
}
static const char *match_ref_pattern = NULL;
@@ -434,7 +439,7 @@ static int append_matching_ref(const char *refname, const unsigned char *sha1, i
return append_head_ref(refname, sha1, flag, cb_data);
if (!strncmp("refs/tags/", refname, 10))
return append_tag_ref(refname, sha1, flag, cb_data);
return append_ref(refname, sha1, flag, cb_data);
return append_ref(refname, sha1, 0);
}
static void snarf_refs(int head, int remotes)
@@ -507,7 +512,7 @@ static void append_one_rev(const char *av)
{
unsigned char revkey[20];
if (!get_sha1(av, revkey)) {
append_ref(av, revkey, 0, NULL);
append_ref(av, revkey, 0);
return;
}
if (strchr(av, '*') || strchr(av, '?') || strchr(av, '[')) {
@@ -562,9 +567,24 @@ static int omit_in_dense(struct commit *commit, struct commit **rev, int n)
return 0;
}
static void parse_reflog_param(const char *arg, int *cnt, const char **base)
{
char *ep;
*cnt = strtoul(arg, &ep, 10);
if (*ep == ',')
*base = ep + 1;
else if (*ep)
die("unrecognized reflog param '%s'", arg + 9);
else
*base = NULL;
if (*cnt <= 0)
*cnt = DEFAULT_REFLOG;
}
int cmd_show_branch(int ac, const char **av, const char *prefix)
{
struct commit *rev[MAX_REVS], *commit;
char *reflog_msg[MAX_REVS];
struct commit_list *list = NULL, *seen = NULL;
unsigned int rev_mask[MAX_REVS];
int num_rev, i, extra = 0;
@@ -585,6 +605,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
int topics = 0;
int dense = 1;
int reflog = 0;
const char *reflog_base = NULL;
git_config(git_show_branch_config);
@@ -628,24 +649,34 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
dense = 0;
else if (!strcmp(arg, "--date-order"))
lifo = 0;
else if (!strcmp(arg, "--reflog")) {
else if (!strcmp(arg, "--reflog") || !strcmp(arg, "-g")) {
reflog = DEFAULT_REFLOG;
}
else if (!strncmp(arg, "--reflog=", 9)) {
char *end;
reflog = strtoul(arg + 9, &end, 10);
if (*end != '\0')
die("unrecognized reflog count '%s'", arg + 9);
}
else if (!strncmp(arg, "--reflog=", 9))
parse_reflog_param(arg + 9, &reflog, &reflog_base);
else if (!strncmp(arg, "-g=", 3))
parse_reflog_param(arg + 3, &reflog, &reflog_base);
else
usage(show_branch_usage);
ac--; av++;
}
ac--; av++;
/* Only one of these is allowed */
if (1 < independent + merge_base + (extra != 0) + (!!reflog))
usage(show_branch_usage);
if (!!extra || !!reflog) {
/* "listing" mode is incompatible with
* independent nor merge-base modes.
*/
if (independent || merge_base)
usage(show_branch_usage);
if (!!reflog && ((0 < extra) || all_heads || all_remotes))
/*
* Asking for --more in reflog mode does not
* make sense. --list is Ok.
*
* Also --all and --remotes do not make sense either.
*/
usage(show_branch_usage_reflog);
}
/* If nothing is specified, show all branches by default */
if (ac + all_heads + all_remotes == 0)
@@ -654,14 +685,54 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
if (all_heads + all_remotes)
snarf_refs(all_heads, all_remotes);
if (reflog) {
int reflen;
if (!ac)
unsigned char sha1[20];
char nth_desc[256];
char *ref;
int base = 0;
if (ac != 1)
die("--reflog option needs one branch name");
reflen = strlen(*av);
if (MAX_REVS < reflog)
die("Only %d entries can be shown at one time.",
MAX_REVS);
if (!dwim_ref(*av, strlen(*av), sha1, &ref))
die("No such ref %s", *av);
/* Has the base been specified? */
if (reflog_base) {
char *ep;
base = strtoul(reflog_base, &ep, 10);
if (*ep) {
/* Ah, that is a date spec... */
unsigned long at;
at = approxidate(reflog_base);
read_ref_at(ref, at, -1, sha1, NULL,
NULL, NULL, &base);
}
}
for (i = 0; i < reflog; i++) {
char *name = xmalloc(reflen + 20);
sprintf(name, "%s@{%d}", *av, i);
append_one_rev(name);
char *logmsg, *msg, *m;
unsigned long timestamp;
int tz;
if (read_ref_at(ref, 0, base+i, sha1, &logmsg,
&timestamp, &tz, NULL)) {
reflog = i;
break;
}
msg = strchr(logmsg, '\t');
if (!msg)
msg = "(none)";
else
msg++;
m = xmalloc(strlen(msg) + 200);
sprintf(m, "(%s) %s",
show_date(timestamp, tz, 1),
msg);
reflog_msg[i] = m;
free(logmsg);
sprintf(nth_desc, "%s@{%d}", *av, base+i);
append_ref(nth_desc, sha1, 1);
}
}
else {
@@ -760,8 +831,14 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
printf("%c [%s] ",
is_head ? '*' : '!', ref_name[i]);
}
/* header lines never need name */
show_one_commit(rev[i], 1);
if (!reflog) {
/* header lines never need name */
show_one_commit(rev[i], 1);
}
else
puts(reflog_msg[i]);
if (is_head)
head_at = i;
}

View File

@@ -129,6 +129,7 @@ extern int cache_errno;
extern int is_bare_repository_cfg;
extern int is_bare_repository(void);
extern int is_inside_git_dir(void);
extern const char *get_git_dir(void);
extern char *get_object_directory(void);
extern char *get_refs_directory(void);
@@ -300,6 +301,8 @@ extern int get_sha1_hex(const char *hex, unsigned char *sha1);
extern char *sha1_to_hex(const unsigned char *sha1); /* static buffer result! */
extern int read_ref(const char *filename, unsigned char *sha1);
extern const char *resolve_ref(const char *path, unsigned char *sha1, int, int *);
extern int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref);
extern int create_symref(const char *ref, const char *refs_heads_master);
extern int validate_headref(const char *ref);

View File

@@ -110,7 +110,7 @@ extern struct commit_list *get_merge_bases(struct commit *rev1, struct commit *r
extern int register_shallow(const unsigned char *sha1);
extern int unregister_shallow(const unsigned char *sha1);
extern int write_shallow_commits(int fd, int use_pack_protocol);
extern int is_repository_shallow();
extern int is_repository_shallow(void);
extern struct commit_list *get_shallow_commits(struct object_array *heads,
int depth, int shallow_flag, int not_shallow_flag);

View File

@@ -661,6 +661,11 @@ int git_config_set_multivar(const char* key, const char* value,
goto out_free;
}
c = tolower(c);
} else if (c == '\n') {
fprintf(stderr, "invalid key (newline): %s\n", key);
free(store.key);
ret = 1;
goto out_free;
}
store.key[i] = c;
}

View File

@@ -530,7 +530,7 @@ static void git_tcp_connect(int fd[2], char *host)
int sockfd = git_tcp_connect_sock(host);
fd[0] = sockfd;
fd[1] = sockfd;
fd[1] = dup(sockfd);
}

View File

@@ -1,7 +1,7 @@
syn region gitLine start=/^#/ end=/$/
syn region gitCommit start=/^# Added but not yet committed:$/ end=/^#$/ contains=gitHead,gitCommitFile
syn region gitCommit start=/^# Changes to be committed:$/ end=/^#$/ contains=gitHead,gitCommitFile
syn region gitHead contained start=/^# (.*)/ end=/^#$/
syn region gitChanged start=/^# Changed but not added:/ end=/^#$/ contains=gitHead,gitChangedFile
syn region gitChanged start=/^# Changed but not updated:/ end=/^#$/ contains=gitHead,gitChangedFile
syn region gitUntracked start=/^# Untracked files:/ end=/^#$/ contains=gitHead,gitUntrackedFile
syn match gitCommitFile contained /^#\t.*/hs=s+2

5
date.c
View File

@@ -62,12 +62,11 @@ const char *show_date(unsigned long time, int tz, int relative)
if (relative) {
unsigned long diff;
time_t t = gm_time_t(time, tz);
struct timeval now;
gettimeofday(&now, NULL);
if (now.tv_sec < t)
if (now.tv_sec < time)
return "in the future";
diff = now.tv_sec - t;
diff = now.tv_sec - time;
if (diff < 90) {
snprintf(timebuf, sizeof(timebuf), "%lu seconds ago", diff);
return timebuf;

View File

@@ -4,16 +4,20 @@
#include "commit.h"
#include "tag.h"
#include "exec_cmd.h"
#include "pack.h"
#include "sideband.h"
static int keep_pack;
static int transfer_unpack_limit = -1;
static int fetch_unpack_limit = -1;
static int unpack_limit = 100;
static int quiet;
static int verbose;
static int fetch_all;
static int depth;
static const char fetch_pack_usage[] =
"git-fetch-pack [--all] [-q] [-v] [-k] [--thin] [--exec=upload-pack] [--depth=<n>] [host:]directory <refs>...";
static const char *exec = "git-upload-pack";
"git-fetch-pack [--all] [--quiet|-q] [--keep|-k] [--thin] [--upload-pack=<git-upload-pack>] [--depth=<n>] [-v] [<host>:]<directory> [<refs>...]";
static const char *uploadpack = "git-upload-pack";
#define COMPLETE (1U << 0)
#define COMMON (1U << 1)
@@ -486,13 +490,58 @@ static pid_t setup_sideband(int fd[2], int xd[2])
return side_pid;
}
static int get_pack(int xd[2], const char **argv)
static int get_pack(int xd[2])
{
int status;
pid_t pid, side_pid;
int fd[2];
const char *argv[20];
char keep_arg[256];
char hdr_arg[256];
const char **av;
int do_keep = keep_pack;
side_pid = setup_sideband(fd, xd);
av = argv;
*hdr_arg = 0;
if (unpack_limit) {
struct pack_header header;
if (read_pack_header(fd[0], &header))
die("protocol error: bad pack header");
snprintf(hdr_arg, sizeof(hdr_arg), "--pack_header=%u,%u",
ntohl(header.hdr_version), ntohl(header.hdr_entries));
if (ntohl(header.hdr_entries) < unpack_limit)
do_keep = 0;
else
do_keep = 1;
}
if (do_keep) {
*av++ = "index-pack";
*av++ = "--stdin";
if (!quiet)
*av++ = "-v";
if (use_thin_pack)
*av++ = "--fix-thin";
if (keep_pack > 1 || unpack_limit) {
int s = sprintf(keep_arg,
"--keep=fetch-pack %d on ", getpid());
if (gethostname(keep_arg + s, sizeof(keep_arg) - s))
strcpy(keep_arg + s, "localhost");
*av++ = keep_arg;
}
}
else {
*av++ = "unpack-objects";
if (quiet)
*av++ = "-q";
}
if (*hdr_arg)
*av++ = hdr_arg;
*av++ = NULL;
pid = spawnv_git_cmd(argv, fd, NULL);
if (pid < 0)
die("fetch-pack: unable to fork off %s", argv[0]);
@@ -514,39 +563,10 @@ static int get_pack(int xd[2], const char **argv)
die("%s died of unnatural causes %d", argv[0], status);
}
static int explode_rx_pack(int xd[2])
{
const char *argv[3] = { "unpack-objects", quiet ? "-q" : NULL, NULL };
return get_pack(xd, argv);
}
static int keep_rx_pack(int xd[2])
{
const char *argv[6];
char keep_arg[256];
int n = 0;
argv[n++] = "index-pack";
argv[n++] = "--stdin";
if (!quiet)
argv[n++] = "-v";
if (use_thin_pack)
argv[n++] = "--fix-thin";
if (keep_pack > 1) {
int s = sprintf(keep_arg, "--keep=fetch-pack %i on ", getpid());
if (gethostname(keep_arg + s, sizeof(keep_arg) - s))
strcpy(keep_arg + s, "localhost");
argv[n++] = keep_arg;
}
argv[n] = NULL;
return get_pack(xd, argv);
}
static int fetch_pack(int fd[2], int nr_match, char **match)
{
struct ref *ref;
unsigned char sha1[20];
int status;
get_remote_heads(fd[0], &ref, 0, NULL, 0);
if (is_repository_shallow() && !server_supports("shallow"))
@@ -583,8 +603,7 @@ static int fetch_pack(int fd[2], int nr_match, char **match)
*/
fprintf(stderr, "warning: no common commits\n");
status = (keep_pack) ? keep_rx_pack(fd) : explode_rx_pack(fd);
if (status)
if (get_pack(fd))
die("git-fetch-pack: fetch failed.");
all_done:
@@ -619,6 +638,21 @@ static int remove_duplicates(int nr_heads, char **heads)
return dst;
}
static int fetch_pack_config(const char *var, const char *value)
{
if (strcmp(var, "fetch.unpacklimit") == 0) {
fetch_unpack_limit = git_config_int(var, value);
return 0;
}
if (strcmp(var, "transfer.unpacklimit") == 0) {
transfer_unpack_limit = git_config_int(var, value);
return 0;
}
return git_default_config(var, value);
}
static struct lock_file lock;
int main(int argc, char **argv)
@@ -630,6 +664,13 @@ int main(int argc, char **argv)
struct stat st;
setup_git_directory();
setup_ident();
git_config(fetch_pack_config);
if (0 <= transfer_unpack_limit)
unpack_limit = transfer_unpack_limit;
else if (0 <= fetch_unpack_limit)
unpack_limit = fetch_unpack_limit;
nr_heads = 0;
heads = NULL;
@@ -637,8 +678,12 @@ int main(int argc, char **argv)
char *arg = argv[i];
if (*arg == '-') {
if (!strncmp("--upload-pack=", arg, 14)) {
uploadpack = arg + 14;
continue;
}
if (!strncmp("--exec=", arg, 7)) {
exec = arg + 7;
uploadpack = arg + 7;
continue;
}
if (!strcmp("--quiet", arg) || !strcmp("-q", arg)) {
@@ -647,6 +692,7 @@ int main(int argc, char **argv)
}
if (!strcmp("--keep", arg) || !strcmp("-k", arg)) {
keep_pack++;
unpack_limit = 0;
continue;
}
if (!strcmp("--thin", arg)) {
@@ -676,7 +722,7 @@ int main(int argc, char **argv)
}
if (!dest)
usage(fetch_pack_usage);
pid = git_connect(fd, dest, exec);
pid = git_connect(fd, dest, uploadpack);
if (pid < 0)
return 1;
if (heads && nr_heads)

View File

@@ -54,6 +54,99 @@ static int objwarning(struct object *obj, const char *err, ...)
return -1;
}
/*
* Check a single reachable object
*/
static void check_reachable_object(struct object *obj)
{
const struct object_refs *refs;
/*
* We obviously want the object to be parsed,
* except if it was in a pack-file and we didn't
* do a full fsck
*/
if (!obj->parsed) {
if (has_sha1_file(obj->sha1))
return; /* it is in pack - forget about it */
printf("missing %s %s\n", typename(obj->type), sha1_to_hex(obj->sha1));
return;
}
/*
* Check that everything that we try to reference is also good.
*/
refs = lookup_object_refs(obj);
if (refs) {
unsigned j;
for (j = 0; j < refs->count; j++) {
struct object *ref = refs->ref[j];
if (ref->parsed ||
(has_sha1_file(ref->sha1)))
continue;
printf("broken link from %7s %s\n",
typename(obj->type), sha1_to_hex(obj->sha1));
printf(" to %7s %s\n",
typename(ref->type), sha1_to_hex(ref->sha1));
}
}
}
/*
* Check a single unreachable object
*/
static void check_unreachable_object(struct object *obj)
{
/*
* Missing unreachable object? Ignore it. It's not like
* we miss it (since it can't be reached), nor do we want
* to complain about it being unreachable (since it does
* not exist).
*/
if (!obj->parsed)
return;
/*
* Unreachable object that exists? Show it if asked to,
* since this is something that is prunable.
*/
if (show_unreachable) {
printf("unreachable %s %s\n", typename(obj->type), sha1_to_hex(obj->sha1));
return;
}
/*
* "!used" means that nothing at all points to it, including
* other unreacahble objects. In other words, it's the "tip"
* of some set of unreachable objects, usually a commit that
* got dropped.
*
* Such starting points are more interesting than some random
* set of unreachable objects, so we show them even if the user
* hasn't asked for _all_ unreachable objects. If you have
* deleted a branch by mistake, this is a prime candidate to
* start looking at, for example.
*/
if (!obj->used) {
printf("dangling %s %s\n", typename(obj->type),
sha1_to_hex(obj->sha1));
return;
}
/*
* Otherwise? It's there, it's unreachable, and some other unreachable
* object points to it. Ignore it - it's not interesting, and we showed
* all the interesting cases above.
*/
}
static void check_object(struct object *obj)
{
if (obj->flags & REACHABLE)
check_reachable_object(obj);
else
check_unreachable_object(obj);
}
static void check_connectivity(void)
{
@@ -62,46 +155,10 @@ static void check_connectivity(void)
/* Look up all the requirements, warn about missing objects.. */
max = get_max_object_index();
for (i = 0; i < max; i++) {
const struct object_refs *refs;
struct object *obj = get_indexed_object(i);
if (!obj)
continue;
if (!obj->parsed) {
if (has_sha1_file(obj->sha1))
; /* it is in pack */
else
printf("missing %s %s\n",
typename(obj->type), sha1_to_hex(obj->sha1));
continue;
}
refs = lookup_object_refs(obj);
if (refs) {
unsigned j;
for (j = 0; j < refs->count; j++) {
struct object *ref = refs->ref[j];
if (ref->parsed ||
(has_sha1_file(ref->sha1)))
continue;
printf("broken link from %7s %s\n",
typename(obj->type), sha1_to_hex(obj->sha1));
printf(" to %7s %s\n",
typename(ref->type), sha1_to_hex(ref->sha1));
}
}
if (show_unreachable && !(obj->flags & REACHABLE)) {
printf("unreachable %s %s\n",
typename(obj->type), sha1_to_hex(obj->sha1));
continue;
}
if (!obj->used) {
printf("dangling %s %s\n", typename(obj->type),
sha1_to_hex(obj->sha1));
}
if (obj)
check_object(obj);
}
}

View File

@@ -203,17 +203,12 @@ else
# Match the index to the working tree, and do a three-way.
git diff-files --name-only | git update-index --remove --stdin &&
work=`git write-tree` &&
git read-tree --reset -u $new &&
eval GITHEAD_$new=${new_name:-${branch:-$new}} GITHEAD_$work=local &&
export GITHEAD_$new GITHEAD_$work &&
git merge-recursive $old -- $new $work || exit
git read-tree --reset -u $new || exit
if result=`git write-tree 2>/dev/null`
then
echo >&2 "Trivially automerged."
else
git merge-index -o git-merge-one-file -a
fi
eval GITHEAD_$new=${new_name:-${branch:-$new}} &&
eval GITHEAD_$work=local &&
export GITHEAD_$new GITHEAD_$work &&
git merge-recursive $old -- $new $work
# Do not register the cleanly merged paths in the index yet.
# this is not a real merge before committing, but just carrying

View File

@@ -163,7 +163,9 @@ while
1,-u|1,--upload-pack) usage ;;
*,-u|*,--upload-pack)
shift
upload_pack="--exec=$1" ;;
upload_pack="--upload-pack=$1" ;;
*,--upload-pack=*)
upload_pack=--upload-pack=$(expr "$1" : '-[^=]*=\(.*\)') ;;
1,--depth) usage;;
*,--depth)
shift

View File

@@ -3,7 +3,7 @@
# Copyright (c) 2005 Linus Torvalds
# Copyright (c) 2006 Junio C Hamano
USAGE='[-a] [-s] [-v] [--no-verify] [-m <message> | -F <logfile> | (-C|-c) <commit>] [-u] [--amend] [-e] [--author <author>] [[-i | -o] <path>...]'
USAGE='[-a] [-s] [-v] [--no-verify] [-m <message> | -F <logfile> | (-C|-c) <commit> | --amend] [-u] [-e] [--author <author>] [[-i | -o] <path>...]'
SUBDIRECTORY_OK=Yes
. git-sh-setup
require_work_tree
@@ -284,9 +284,9 @@ esac
case "$log_given" in
tt*)
die "Only one of -c/-C/-F can be used." ;;
die "Only one of -c/-C/-F/--amend can be used." ;;
*tm*|*mt*)
die "Option -m cannot be combined with -c/-C/-F." ;;
die "Option -m cannot be combined with -c/-C/-F/--amend." ;;
esac
case "$#,$also,$only,$amend" in
@@ -462,15 +462,7 @@ if test -f "$GIT_DIR/MERGE_HEAD" && test -z "$no_edit"; then
fi >>"$GIT_DIR"/COMMIT_EDITMSG
# Author
if test '' != "$force_author"
then
GIT_AUTHOR_NAME=`expr "z$force_author" : 'z\(.*[^ ]\) *<.*'` &&
GIT_AUTHOR_EMAIL=`expr "z$force_author" : '.*\(<.*\)'` &&
test '' != "$GIT_AUTHOR_NAME" &&
test '' != "$GIT_AUTHOR_EMAIL" ||
die "malformed --author parameter"
export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL
elif test '' != "$use_commit"
if test '' != "$use_commit"
then
pick_author_script='
/^author /{
@@ -501,6 +493,15 @@ then
export GIT_AUTHOR_EMAIL
export GIT_AUTHOR_DATE
fi
if test '' != "$force_author"
then
GIT_AUTHOR_NAME=`expr "z$force_author" : 'z\(.*[^ ]\) *<.*'` &&
GIT_AUTHOR_EMAIL=`expr "z$force_author" : '.*\(<.*\)'` &&
test '' != "$GIT_AUTHOR_NAME" &&
test '' != "$GIT_AUTHOR_EMAIL" ||
die "malformed --author parameter"
export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL
fi
PARENTS="-p HEAD"
if test -z "$initial_commit"

View File

@@ -85,7 +85,7 @@ sub write_author_info($) {
close ($f);
}
getopts("hivmkuo:d:p:C:z:s:M:P:A:S:L:") or usage();
getopts("haivmkuo:d:p:C:z:s:M:P:A:S:L:") or usage();
usage if $opt_h;
@ARGV <= 1 or usage();

View File

@@ -22,7 +22,6 @@ force=
verbose=
update_head_ok=
exec=
upload_pack=
keep=
shallow_depth=
while case "$#" in 0) break ;; esac
@@ -34,8 +33,12 @@ do
--upl|--uplo|--uploa|--upload|--upload-|--upload-p|\
--upload-pa|--upload-pac|--upload-pack)
shift
exec="--exec=$1"
upload_pack="-u $1"
exec="--upload-pack=$1"
;;
--upl=*|--uplo=*|--uploa=*|--upload=*|\
--upload-=*|--upload-p=*|--upload-pa=*|--upload-pac=*|--upload-pack=*)
exec=--upload-pack=$(expr "$1" : '-[^=]*=\(.*\)')
shift
;;
-f|--f|--fo|--for|--forc|--force)
force=t
@@ -94,7 +97,7 @@ then
fi
# Global that is reused later
ls_remote_result=$(git ls-remote $upload_pack "$remote") ||
ls_remote_result=$(git ls-remote $exec "$remote") ||
die "Cannot get the repository state from $remote"
append_fetch_head () {

View File

@@ -4,12 +4,26 @@
#
# Cleanup unreachable files and optimize the repository.
USAGE=''
USAGE='git-gc [--prune]'
SUBDIRECTORY_OK=Yes
. git-sh-setup
no_prune=:
while case $# in 0) break ;; esac
do
case "$1" in
--prune)
no_prune=
;;
--)
usage
;;
esac
shift
done
git-pack-refs --prune &&
git-reflog expire --all &&
git-repack -a -d -l &&
git-prune &&
$no_prune git-prune &&
git-rerere gc || exit

View File

@@ -23,7 +23,11 @@ do
-u|--u|--up|--upl|--uploa|--upload|--upload-|--upload-p|--upload-pa|\
--upload-pac|--upload-pack)
shift
exec="--exec=$1"
exec="--upload-pack=$1"
shift;;
-u=*|--u=*|--up=*|--upl=*|--uplo=*|--uploa=*|--upload=*|\
--upload-=*|--upload-p=*|--upload-pa=*|--upload-pac=*|--upload-pack=*)
exec=--upload-pack=$(expr "$1" : '-[^=]*=\(.*\)')
shift;;
--)
shift; break ;;

View File

@@ -275,8 +275,12 @@ case "$#" in
git-checkout "$2" || usage
;;
*)
branch_name=`git symbolic-ref HEAD` || die "No current branch"
branch_name=`expr "z$branch_name" : 'zrefs/heads/\(.*\)'`
if branch_name=`git symbolic-ref -q HEAD`
then
branch_name=`expr "z$branch_name" : 'zrefs/heads/\(.*\)'`
else
branch_name=HEAD ;# detached
fi
;;
esac
branch=$(git-rev-parse --verify "${branch_name}^0") || exit

View File

@@ -2856,7 +2856,7 @@ sub rmdirs {
foreach my $d (sort { $b =~ tr#/#/# <=> $a =~ tr#/#/# } keys %$rm) {
$self->close_directory($bat->{$d}, $p);
my ($dn) = ($d =~ m#^(.*?)/?(?:[^/]+)$#);
print "\tD+\t/$d/\n" unless $q;
print "\tD+\t$d/\n" unless $q;
$self->SUPER::delete_entry($d, $r, $bat->{$dn}, $p);
delete $bat->{$d};
}

View File

@@ -63,12 +63,21 @@ do
;;
-d)
shift
tag_name="$1"
tag=$(git-show-ref --verify --hash -- "refs/tags/$tag_name") ||
die "Seriously, what tag are you talking about?"
git-update-ref -m 'tag: delete' -d "refs/tags/$tag_name" "$tag" &&
echo "Deleted tag $tag_name."
exit $?
had_error=0
for tag
do
cur=$(git-show-ref --verify --hash -- "refs/tags/$tag") || {
echo >&2 "Seriously, what tag are you talking about?"
had_error=1
continue
}
git-update-ref -m 'tag: delete' -d "refs/tags/$tag" "$cur" || {
had_error=1
continue
}
echo "Deleted tag $tag."
done
exit $had_error
;;
-v)
shift

2
git.c
View File

@@ -218,7 +218,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
int option;
} commands[] = {
{ "add", cmd_add, RUN_SETUP | NOT_BARE },
{ "annotate", cmd_annotate, },
{ "annotate", cmd_annotate, USE_PAGER },
{ "apply", cmd_apply },
{ "archive", cmd_archive },
{ "blame", cmd_blame, RUN_SETUP | USE_PAGER },

View File

@@ -2,6 +2,7 @@
#include "diff.h"
#include "commit.h"
#include "log-tree.h"
#include "reflog-walk.h"
static void show_parents(struct commit *commit, int abbrev)
{
@@ -223,6 +224,9 @@ void show_log(struct rev_info *opt, const char *sep)
printf("%s",
diff_get_color(opt->diffopt.color_diff, DIFF_RESET));
putchar(opt->commit_format == CMIT_FMT_ONELINE ? ' ' : '\n');
if (opt->reflog_info)
show_reflog_message(opt->reflog_info,
opt->commit_format == CMIT_FMT_ONELINE);;
}
/*

5
pack.h
View File

@@ -44,4 +44,9 @@ struct pack_header {
#define PACK_IDX_SIGNATURE 0xff744f63 /* "\377tOc" */
extern int verify_pack(struct packed_git *, int);
#define PH_ERROR_EOF (-1)
#define PH_ERROR_PACK_SIGNATURE (-2)
#define PH_ERROR_PROTOCOL (-3)
extern int read_pack_header(int fd, struct pack_header *);
#endif

View File

@@ -3,8 +3,8 @@
#include "pkt-line.h"
static const char peek_remote_usage[] =
"git-peek-remote [--exec=upload-pack] [host:]directory";
static const char *exec = "git-upload-pack";
"git-peek-remote [--upload-pack=<git-upload-pack>] [<host>:]<directory>";
static const char *uploadpack = "git-upload-pack";
static int peek_remote(int fd[2], unsigned flags)
{
@@ -35,8 +35,12 @@ int main(int argc, char **argv)
char *arg = argv[i];
if (*arg == '-') {
if (!strncmp("--upload-pack=", arg, 14)) {
uploadpack = arg + 14;
continue;
}
if (!strncmp("--exec=", arg, 7)) {
exec = arg + 7;
uploadpack = arg + 7;
continue;
}
if (!strcmp("--tags", arg)) {
@@ -60,7 +64,7 @@ int main(int argc, char **argv)
if (!dest || i != argc - 1)
usage(peek_remote_usage);
pid = git_connect(fd, dest, exec);
pid = git_connect(fd, dest, uploadpack);
if (pid < 0)
return 1;
ret = peek_remote(fd, flags);

View File

@@ -275,7 +275,7 @@ sub command {
} else {
my @lines = <$fh>;
chomp @lines;
defined and chomp for @lines;
try {
_cmd_close($fh, $ctx);
} catch Git::Error::Command with {
@@ -736,13 +736,19 @@ sub _command_common_pipe {
_check_valid_cmd($cmd);
my $fh;
if ($^O eq '##INSERT_ACTIVESTATE_STRING_HERE##') {
if ($^O eq 'MSWin32') {
# ActiveState Perl
#defined $opts{STDERR} and
# warn 'ignoring STDERR option - running w/ ActiveState';
$direction eq '-|' or
die 'input pipe for ActiveState not implemented';
tie ($fh, 'Git::activestate_pipe', $cmd, @args);
# the strange construction with *ACPIPE is just to
# explain the tie below that we want to bind to
# a handle class, not scalar. It is not known if
# it is something specific to ActiveState Perl or
# just a Perl quirk.
tie (*ACPIPE, 'Git::activestate_pipe', $cmd, @args);
$fh = *ACPIPE;
} else {
my $pid = open($fh, $direction);
@@ -809,8 +815,9 @@ sub TIEHANDLE {
# FIXME: This is probably horrible idea and the thing will explode
# at the moment you give it arguments that require some quoting,
# but I have no ActiveState clue... --pasky
my $cmdline = join " ", @params;
my @data = qx{$cmdline};
# Let's just hope ActiveState Perl does at least the quoting
# correctly.
my @data = qx{git @params};
bless { i => 0, data => \@data }, $class;
}

View File

@@ -10,6 +10,8 @@
static const char receive_pack_usage[] = "git-receive-pack <git-dir>";
static int deny_non_fast_forwards = 0;
static int receive_unpack_limit = -1;
static int transfer_unpack_limit = -1;
static int unpack_limit = 100;
static int report_status;
@@ -18,21 +20,22 @@ static int capabilities_sent;
static int receive_pack_config(const char *var, const char *value)
{
git_default_config(var, value);
if (strcmp(var, "receive.denynonfastforwards") == 0)
{
if (strcmp(var, "receive.denynonfastforwards") == 0) {
deny_non_fast_forwards = git_config_bool(var, value);
return 0;
}
if (strcmp(var, "receive.unpacklimit") == 0)
{
unpack_limit = git_config_int(var, value);
if (strcmp(var, "receive.unpacklimit") == 0) {
receive_unpack_limit = git_config_int(var, value);
return 0;
}
return 0;
if (strcmp(var, "transfer.unpacklimit") == 0) {
transfer_unpack_limit = git_config_int(var, value);
return 0;
}
return git_default_config(var, value);
}
static int show_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
@@ -250,20 +253,22 @@ static void read_head_info(void)
static const char *parse_pack_header(struct pack_header *hdr)
{
char *c = (char*)hdr;
ssize_t remaining = sizeof(struct pack_header);
do {
ssize_t r = xread(0, c, remaining);
if (r <= 0)
return "eof before pack header was fully read";
remaining -= r;
c += r;
} while (remaining > 0);
if (hdr->hdr_signature != htonl(PACK_SIGNATURE))
switch (read_pack_header(0, hdr)) {
case PH_ERROR_EOF:
return "eof before pack header was fully read";
case PH_ERROR_PACK_SIGNATURE:
return "protocol error (pack signature mismatch detected)";
if (!pack_version_ok(hdr->hdr_version))
case PH_ERROR_PROTOCOL:
return "protocol error (pack version unsupported)";
return NULL;
default:
return "unknown error in parse_pack_header";
case 0:
return NULL;
}
}
static const char *pack_lockfile;
@@ -413,11 +418,19 @@ int main(int argc, char **argv)
if(!enter_repo(dir, 0))
die("'%s': unable to chdir or not a git archive", dir);
if (is_repository_shallow())
die("attempt to push into a shallow repository");
setup_ident();
/* don't die if gecos is empty */
ignore_missing_committer_name();
git_config(receive_pack_config);
if (0 <= transfer_unpack_limit)
unpack_limit = transfer_unpack_limit;
else if (0 <= receive_unpack_limit)
unpack_limit = receive_unpack_limit;
write_head_info();
/* EOF */

250
reflog-walk.c Normal file
View File

@@ -0,0 +1,250 @@
#include "cache.h"
#include "commit.h"
#include "refs.h"
#include "diff.h"
#include "revision.h"
#include "path-list.h"
#include "reflog-walk.h"
struct complete_reflogs {
char *ref;
struct reflog_info {
unsigned char osha1[20], nsha1[20];
char *email;
unsigned long timestamp;
int tz;
char *message;
} *items;
int nr, alloc;
};
static int read_one_reflog(unsigned char *osha1, unsigned char *nsha1,
const char *email, unsigned long timestamp, int tz,
const char *message, void *cb_data)
{
struct complete_reflogs *array = cb_data;
struct reflog_info *item;
if (array->nr >= array->alloc) {
array->alloc = alloc_nr(array->nr + 1);
array->items = xrealloc(array->items, array->alloc *
sizeof(struct reflog_info));
}
item = array->items + array->nr;
memcpy(item->osha1, osha1, 20);
memcpy(item->nsha1, nsha1, 20);
item->email = xstrdup(email);
item->timestamp = timestamp;
item->tz = tz;
item->message = xstrdup(message);
array->nr++;
return 0;
}
static struct complete_reflogs *read_complete_reflog(const char *ref)
{
struct complete_reflogs *reflogs =
xcalloc(sizeof(struct complete_reflogs), 1);
reflogs->ref = xstrdup(ref);
for_each_reflog_ent(ref, read_one_reflog, reflogs);
if (reflogs->nr == 0) {
unsigned char sha1[20];
const char *name = resolve_ref(ref, sha1, 1, NULL);
if (name)
for_each_reflog_ent(name, read_one_reflog, reflogs);
}
if (reflogs->nr == 0) {
int len = strlen(ref);
char *refname = xmalloc(len + 12);
sprintf(refname, "refs/%s", ref);
for_each_reflog_ent(refname, read_one_reflog, reflogs);
if (reflogs->nr == 0) {
sprintf(refname, "refs/heads/%s", ref);
for_each_reflog_ent(refname, read_one_reflog, reflogs);
}
free(refname);
}
return reflogs;
}
static int get_reflog_recno_by_time(struct complete_reflogs *array,
unsigned long timestamp)
{
int i;
for (i = array->nr - 1; i >= 0; i--)
if (timestamp >= array->items[i].timestamp)
return i;
return -1;
}
struct commit_info_lifo {
struct commit_info {
struct commit *commit;
void *util;
} *items;
int nr, alloc;
};
static struct commit_info *get_commit_info(struct commit *commit,
struct commit_info_lifo *lifo, int pop)
{
int i;
for (i = 0; i < lifo->nr; i++)
if (lifo->items[i].commit == commit) {
struct commit_info *result = &lifo->items[i];
if (pop) {
if (i + 1 < lifo->nr)
memmove(lifo->items + i,
lifo->items + i + 1,
(lifo->nr - i) *
sizeof(struct commit_info));
lifo->nr--;
}
return result;
}
return NULL;
}
static void add_commit_info(struct commit *commit, void *util,
struct commit_info_lifo *lifo)
{
struct commit_info *info;
if (lifo->nr >= lifo->alloc) {
lifo->alloc = alloc_nr(lifo->nr + 1);
lifo->items = xrealloc(lifo->items,
lifo->alloc * sizeof(struct commit_info));
}
info = lifo->items + lifo->nr;
info->commit = commit;
info->util = util;
lifo->nr++;
}
struct commit_reflog {
int flag, recno;
struct complete_reflogs *reflogs;
};
struct reflog_walk_info {
struct commit_info_lifo reflogs;
struct path_list complete_reflogs;
struct commit_reflog *last_commit_reflog;
};
void init_reflog_walk(struct reflog_walk_info** info)
{
*info = xcalloc(sizeof(struct reflog_walk_info), 1);
}
void add_reflog_for_walk(struct reflog_walk_info *info,
struct commit *commit, const char *name)
{
unsigned long timestamp = 0;
int recno = -1;
struct path_list_item *item;
struct complete_reflogs *reflogs;
char *branch, *at = strchr(name, '@');
struct commit_reflog *commit_reflog;
if (commit->object.flags & UNINTERESTING)
die ("Cannot walk reflogs for %s", name);
branch = xstrdup(name);
if (at && at[1] == '{') {
char *ep;
branch[at - name] = '\0';
recno = strtoul(at + 2, &ep, 10);
if (*ep != '}') {
recno = -1;
timestamp = approxidate(at + 2);
}
} else
recno = 0;
item = path_list_lookup(branch, &info->complete_reflogs);
if (item)
reflogs = item->util;
else {
reflogs = read_complete_reflog(branch);
if (!reflogs || reflogs->nr == 0)
die("No reflogs found for '%s'", branch);
path_list_insert(branch, &info->complete_reflogs)->util
= reflogs;
}
commit_reflog = xcalloc(sizeof(struct commit_reflog), 1);
if (recno < 0) {
commit_reflog->flag = 1;
commit_reflog->recno = get_reflog_recno_by_time(reflogs, timestamp);
if (commit_reflog->recno < 0) {
free(branch);
free(commit_reflog);
return;
}
} else
commit_reflog->recno = reflogs->nr - recno - 1;
commit_reflog->reflogs = reflogs;
add_commit_info(commit, commit_reflog, &info->reflogs);
}
void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit)
{
struct commit_info *commit_info =
get_commit_info(commit, &info->reflogs, 0);
struct commit_reflog *commit_reflog;
struct reflog_info *reflog;
info->last_commit_reflog = NULL;
if (!commit_info)
return;
commit_reflog = commit_info->util;
if (commit_reflog->recno < 0) {
commit->parents = NULL;
return;
}
reflog = &commit_reflog->reflogs->items[commit_reflog->recno];
info->last_commit_reflog = commit_reflog;
commit_reflog->recno--;
commit_info->commit = (struct commit *)parse_object(reflog->osha1);
if (!commit_info->commit) {
commit->parents = NULL;
return;
}
commit->parents = xcalloc(sizeof(struct commit_list), 1);
commit->parents->item = commit_info->commit;
commit->object.flags &= ~(ADDED | SEEN | SHOWN);
}
void show_reflog_message(struct reflog_walk_info* info, int oneline)
{
if (info && info->last_commit_reflog) {
struct commit_reflog *commit_reflog = info->last_commit_reflog;
struct reflog_info *info;
info = &commit_reflog->reflogs->items[commit_reflog->recno+1];
if (oneline) {
printf("%s@{", commit_reflog->reflogs->ref);
if (commit_reflog->flag)
printf("%s", show_date(info->timestamp, 0, 1));
else
printf("%d", commit_reflog->reflogs->nr
- 2 - commit_reflog->recno);
printf("}: ");
}
else {
printf("Reflog: %s@{", commit_reflog->reflogs->ref);
if (commit_reflog->flag)
printf("%s", show_rfc2822_date(info->timestamp,
info->tz));
else
printf("%d", commit_reflog->reflogs->nr
- 2 - commit_reflog->recno);
printf("} (%s)\nReflog message: %s",
info->email, info->message);
}
}
}

11
reflog-walk.h Normal file
View File

@@ -0,0 +1,11 @@
#ifndef REFLOG_WALK_H
#define REFLOG_WALK_H
extern void init_reflog_walk(struct reflog_walk_info** info);
extern void add_reflog_for_walk(struct reflog_walk_info *info,
struct commit *commit, const char *name);
extern void fake_reflog_parent(struct reflog_walk_info *info,
struct commit *commit);
extern void show_reflog_message(struct reflog_walk_info *info, int);
#endif

59
refs.c
View File

@@ -1036,7 +1036,21 @@ int write_ref_sha1(struct ref_lock *lock,
return 0;
}
int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *sha1)
static char *ref_msg(const char *line, const char *endp)
{
const char *ep;
char *msg;
line += 82;
for (ep = line; ep < endp && *ep != '\n'; ep++)
;
msg = xmalloc(ep - line + 1);
memcpy(msg, line, ep - line);
msg[ep - line] = 0;
return msg;
}
int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *sha1, char **msg, unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt)
{
const char *logfile, *logdata, *logend, *rec, *lastgt, *lastrec;
char *tz_c;
@@ -1044,6 +1058,7 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *
struct stat st;
unsigned long date;
unsigned char logged_sha1[20];
void *log_mapped;
logfile = git_path("logs/%s", ref);
logfd = open(logfile, O_RDONLY, 0);
@@ -1052,7 +1067,8 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *
fstat(logfd, &st);
if (!st.st_size)
die("Log %s is empty.", logfile);
logdata = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, logfd, 0);
log_mapped = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, logfd, 0);
logdata = log_mapped;
close(logfd);
lastrec = NULL;
@@ -1071,13 +1087,21 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *
die("Log %s is corrupt.", logfile);
date = strtoul(lastgt + 1, &tz_c, 10);
if (date <= at_time || cnt == 0) {
tz = strtoul(tz_c, NULL, 10);
if (msg)
*msg = ref_msg(rec, logend);
if (cutoff_time)
*cutoff_time = date;
if (cutoff_tz)
*cutoff_tz = tz;
if (cutoff_cnt)
*cutoff_cnt = reccnt - 1;
if (lastrec) {
if (get_sha1_hex(lastrec, logged_sha1))
die("Log %s is corrupt.", logfile);
if (get_sha1_hex(rec + 41, sha1))
die("Log %s is corrupt.", logfile);
if (hashcmp(logged_sha1, sha1)) {
tz = strtoul(tz_c, NULL, 10);
fprintf(stderr,
"warning: Log %s has gap after %s.\n",
logfile, show_rfc2822_date(date, tz));
@@ -1091,13 +1115,12 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *
if (get_sha1_hex(rec + 41, logged_sha1))
die("Log %s is corrupt.", logfile);
if (hashcmp(logged_sha1, sha1)) {
tz = strtoul(tz_c, NULL, 10);
fprintf(stderr,
"warning: Log %s unexpectedly ended on %s.\n",
logfile, show_rfc2822_date(date, tz));
}
}
munmap((void*)logdata, st.st_size);
munmap(log_mapped, st.st_size);
return 0;
}
lastrec = rec;
@@ -1114,14 +1137,17 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *
tz = strtoul(tz_c, NULL, 10);
if (get_sha1_hex(logdata, sha1))
die("Log %s is corrupt.", logfile);
munmap((void*)logdata, st.st_size);
if (at_time)
fprintf(stderr, "warning: Log %s only goes back to %s.\n",
logfile, show_rfc2822_date(date, tz));
else
fprintf(stderr, "warning: Log %s only has %d entries.\n",
logfile, reccnt);
return 0;
if (msg)
*msg = ref_msg(logdata, logend);
munmap(log_mapped, st.st_size);
if (cutoff_time)
*cutoff_time = date;
if (cutoff_tz)
*cutoff_tz = tz;
if (cutoff_cnt)
*cutoff_cnt = reccnt;
return 1;
}
int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data)
@@ -1129,6 +1155,7 @@ int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data)
const char *logfile;
FILE *logfp;
char buf[1024];
int ret = 0;
logfile = git_path("logs/%s", ref);
logfp = fopen(logfile, "r");
@@ -1138,7 +1165,7 @@ int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data)
unsigned char osha1[20], nsha1[20];
char *email_end, *message;
unsigned long timestamp;
int len, ret, tz;
int len, tz;
/* old SP new SP name <email> SP time TAB msg LF */
len = strlen(buf);
@@ -1159,9 +1186,9 @@ int for_each_reflog_ent(const char *ref, each_reflog_ent_fn fn, void *cb_data)
message += 7;
ret = fn(osha1, nsha1, buf+82, timestamp, tz, message, cb_data);
if (ret)
return ret;
break;
}
fclose(logfp);
return 0;
return ret;
}

2
refs.h
View File

@@ -42,7 +42,7 @@ extern void unlock_ref(struct ref_lock *lock);
extern int write_ref_sha1(struct ref_lock *lock, const unsigned char *sha1, const char *msg);
/** Reads log for the value of ref during at_time. **/
extern int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *sha1);
extern int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *sha1, char **msg, unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt);
/* iterate over reflog entries */
typedef int each_reflog_ent_fn(unsigned char *osha1, unsigned char *nsha1, const char *, unsigned long, int, const char *, void *);

View File

@@ -7,6 +7,7 @@
#include "refs.h"
#include "revision.h"
#include "grep.h"
#include "reflog-walk.h"
static char *path_name(struct name_path *path, const char *name)
{
@@ -116,6 +117,9 @@ void mark_parents_uninteresting(struct commit *commit)
void add_pending_object(struct rev_info *revs, struct object *obj, const char *name)
{
add_object_array(obj, name, &revs->pending);
if (revs->reflog_info && obj->type == OBJ_COMMIT)
add_reflog_for_walk(revs->reflog_info,
(struct commit *)obj, name);
}
static struct object *get_reference(struct rev_info *revs, const char *name, const unsigned char *sha1, unsigned int flags)
@@ -864,6 +868,11 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
handle_reflog(revs, flags);
continue;
}
if (!strcmp(arg, "-g") ||
!strcmp(arg, "--walk-reflogs")) {
init_reflog_walk(&revs->reflog_info);
continue;
}
if (!strcmp(arg, "--not")) {
flags ^= UNINTERESTING;
continue;
@@ -1049,6 +1058,10 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
git_log_output_encoding = "";
continue;
}
if (!strcmp(arg, "--reverse")) {
revs->reverse ^= 1;
continue;
}
opts = diff_opt_parse(&revs->diffopt, argv+i, argc-i);
if (opts > 0) {
@@ -1210,6 +1223,9 @@ static struct commit *get_revision_1(struct rev_info *revs)
revs->commits = entry->next;
free(entry);
if (revs->reflog_info)
fake_reflog_parent(revs->reflog_info, commit);
/*
* If we haven't done the list limiting, we need to look at
* the parents here. We also need to do the date-based limiting
@@ -1274,6 +1290,40 @@ struct commit *get_revision(struct rev_info *revs)
{
struct commit *c = NULL;
if (revs->reverse) {
struct commit_list *list;
/*
* rev_info.reverse is used to note the fact that we
* want to output the list of revisions in reverse
* order. To accomplish this goal, reverse can have
* different values:
*
* 0 do nothing
* 1 reverse the list
* 2 internal use: we have already obtained and
* reversed the list, now we only need to yield
* its items.
*/
if (revs->reverse == 1) {
revs->reverse = 0;
list = NULL;
while ((c = get_revision(revs)))
commit_list_insert(c, &list);
revs->commits = list;
revs->reverse = 2;
}
if (!revs->commits)
return NULL;
c = revs->commits->item;
list = revs->commits->next;
free(revs->commits);
revs->commits = list;
return c;
}
if (0 < revs->skip_count) {
while ((c = get_revision_1(revs)) != NULL) {
if (revs->skip_count-- <= 0)

View File

@@ -42,7 +42,8 @@ struct rev_info {
unpacked:1, /* see also ignore_packed below */
boundary:1,
left_right:1,
parents:1;
parents:1,
reverse:2;
/* Diff flags */
unsigned int diff:1,
@@ -89,6 +90,8 @@ struct rev_info {
topo_sort_set_fn_t topo_setter;
topo_sort_get_fn_t topo_getter;
struct reflog_walk_info *reflog_info;
};
#define REV_TREE_SAME 0

View File

@@ -6,9 +6,9 @@
#include "exec_cmd.h"
static const char send_pack_usage[] =
"git-send-pack [--all] [--exec=git-receive-pack] <remote> [<head>...]\n"
" --all and explicit <head> specification are mutually exclusive.";
static const char *exec = "git-receive-pack";
"git-send-pack [--all] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\n"
" --all and explicit <ref> specification are mutually exclusive.";
static const char *receivepack = "git-receive-pack";
static int verbose;
static int send_all;
static int force_update;
@@ -370,8 +370,12 @@ int main(int argc, char **argv)
char *arg = *argv;
if (*arg == '-') {
if (!strncmp(arg, "--receive-pack=", 15)) {
receivepack = arg + 15;
continue;
}
if (!strncmp(arg, "--exec=", 7)) {
exec = arg + 7;
receivepack = arg + 7;
continue;
}
if (!strcmp(arg, "--all")) {
@@ -406,7 +410,7 @@ int main(int argc, char **argv)
usage(send_pack_usage);
verify_remote_names(nr_heads, heads);
pid = git_connect(fd, dest, exec);
pid = git_connect(fd, dest, receivepack);
if (pid < 0)
return 1;
ret = send_pack(fd[0], fd[1], nr_heads, heads);

26
setup.c
View File

@@ -95,6 +95,8 @@ void verify_non_filename(const char *prefix, const char *arg)
const char *name;
struct stat st;
if (is_inside_git_dir())
return;
if (*arg == '-')
return; /* flag */
name = prefix ? prefix_filename(prefix, strlen(prefix), arg) : arg;
@@ -168,6 +170,28 @@ static int is_git_directory(const char *suspect)
return 1;
}
static int inside_git_dir = -1;
int is_inside_git_dir(void)
{
if (inside_git_dir < 0) {
char buffer[1024];
if (is_bare_repository())
return (inside_git_dir = 1);
if (getcwd(buffer, sizeof(buffer))) {
const char *git_dir = get_git_dir(), *cwd = buffer;
while (*git_dir && *git_dir == *cwd) {
git_dir++;
cwd++;
}
inside_git_dir = !*git_dir;
} else
inside_git_dir = 0;
}
return inside_git_dir;
}
const char *setup_git_directory_gently(int *nongit_ok)
{
static char cwd[PATH_MAX+1];
@@ -214,6 +238,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
if (chdir(cwd))
die("Cannot come back to cwd");
setenv(GIT_DIR_ENVIRONMENT, cwd, 1);
inside_git_dir = 1;
return NULL;
}
if (nongit_ok) {
@@ -234,6 +259,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
offset++;
cwd[len++] = '/';
cwd[len] = 0;
inside_git_dir = !strncmp(cwd + offset, ".git/", 5);
return cwd + offset;
}

View File

@@ -1479,21 +1479,20 @@ static void *read_packed_sha1(const unsigned char *sha1, char *type, unsigned lo
{
struct pack_entry e;
if (!find_pack_entry(sha1, &e, NULL)) {
error("cannot read sha1_file for %s", sha1_to_hex(sha1));
if (!find_pack_entry(sha1, &e, NULL))
return NULL;
}
return unpack_entry(e.p, e.offset, type, size);
else
return unpack_entry(e.p, e.offset, type, size);
}
void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size)
{
unsigned long mapsize;
void *map, *buf;
struct pack_entry e;
if (find_pack_entry(sha1, &e, NULL))
return read_packed_sha1(sha1, type, size);
buf = read_packed_sha1(sha1, type, size);
if (buf)
return buf;
map = map_sha1_file(sha1, &mapsize);
if (map) {
buf = unpack_sha1_file(map, mapsize, type, size);
@@ -1501,9 +1500,7 @@ void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size
return buf;
}
reprepare_packed_git();
if (find_pack_entry(sha1, &e, NULL))
return read_packed_sha1(sha1, type, size);
return NULL;
return read_packed_sha1(sha1, type, size);
}
void *read_object_with_reference(const unsigned char *sha1,
@@ -1791,6 +1788,8 @@ static void *repack_object(const unsigned char *sha1, unsigned long *objsize)
/* need to unpack and recompress it by itself */
unpacked = read_packed_sha1(sha1, type, &len);
if (!unpacked)
error("cannot read sha1_file for %s", sha1_to_hex(sha1));
hdrlen = sprintf(hdr, "%s %lu", type, len) + 1;
@@ -2059,3 +2058,24 @@ int index_path(unsigned char *sha1, const char *path, struct stat *st, int write
}
return 0;
}
int read_pack_header(int fd, struct pack_header *header)
{
char *c = (char*)header;
ssize_t remaining = sizeof(struct pack_header);
do {
ssize_t r = xread(fd, c, remaining);
if (r <= 0)
/* "eof before pack header was fully read" */
return PH_ERROR_EOF;
remaining -= r;
c += r;
} while (remaining > 0);
if (header->hdr_signature != htonl(PACK_SIGNATURE))
/* "protocol error (pack signature mismatch detected)" */
return PH_ERROR_PACK_SIGNATURE;
if (!pack_version_ok(header->hdr_version))
/* "protocol error (pack version unsupported)" */
return PH_ERROR_PROTOCOL;
return 0;
}

View File

@@ -235,7 +235,7 @@ static int ambiguous_path(const char *path, int len)
return slash;
}
static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
{
static const char *fmt[] = {
"%.*s",
@@ -246,13 +246,32 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
"refs/remotes/%.*s/HEAD",
NULL
};
const char **p, *r;
int refs_found = 0;
*ref = NULL;
for (p = fmt; *p; p++) {
unsigned char sha1_from_ref[20];
unsigned char *this_result;
this_result = refs_found ? sha1_from_ref : sha1;
r = resolve_ref(mkpath(*p, len, str), this_result, 1, NULL);
if (r) {
if (!refs_found++)
*ref = xstrdup(r);
if (!warn_ambiguous_refs)
break;
}
}
return refs_found;
}
static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
{
static const char *warning = "warning: refname '%.*s' is ambiguous.\n";
const char **p, *ref;
char *real_ref = NULL;
int refs_found = 0;
int at, reflog_len;
unsigned char *this_result;
unsigned char sha1_from_ref[20];
if (len == 40 && !get_sha1_hex(str, sha1))
return 0;
@@ -273,16 +292,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
if (ambiguous_path(str, len))
return -1;
for (p = fmt; *p; p++) {
this_result = refs_found ? sha1_from_ref : sha1;
ref = resolve_ref(mkpath(*p, len, str), this_result, 1, NULL);
if (ref) {
if (!refs_found++)
real_ref = xstrdup(ref);
if (!warn_ambiguous_refs)
break;
}
}
refs_found = dwim_ref(str, len, sha1, &real_ref);
if (!refs_found)
return -1;
@@ -294,6 +304,9 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
/* Is it asking for N-th entry, or approxidate? */
int nth, i;
unsigned long at_time;
unsigned long co_time;
int co_tz, co_cnt;
for (i = nth = 0; 0 <= nth && i < reflog_len; i++) {
char ch = str[at+2+i];
if ('0' <= ch && ch <= '9')
@@ -305,7 +318,18 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
at_time = 0;
else
at_time = approxidate(str + at + 2);
read_ref_at(real_ref, at_time, nth, sha1);
if (read_ref_at(real_ref, at_time, nth, sha1, NULL,
&co_time, &co_tz, &co_cnt)) {
if (at_time)
fprintf(stderr,
"warning: Log for '%.*s' only goes "
"back to %s.\n", len, str,
show_rfc2822_date(co_time, co_tz));
else
fprintf(stderr,
"warning: Log for '%.*s' only has "
"%d entries.\n", len, str, co_cnt);
}
}
free(real_ref);

View File

@@ -17,7 +17,7 @@ int register_shallow(const unsigned char *sha1)
return register_commit_graft(graft, 0);
}
int is_repository_shallow()
int is_repository_shallow(void)
{
FILE *fp;
char buf[1024];

View File

@@ -106,4 +106,33 @@ test_expect_success 'read-tree' '
cmp ../one ../original.one
'
test_expect_success 'no file/rev ambuguity check inside .git' '
cd $HERE &&
git commit -a -m 1 &&
cd $HERE/.git &&
git show -s HEAD
'
test_expect_success 'no file/rev ambuguity check inside a bare repo' '
cd $HERE &&
git clone -s --bare .git foo.git &&
cd foo.git && GIT_DIR=. git show -s HEAD
'
# This still does not work as it should...
: test_expect_success 'no file/rev ambuguity check inside a bare repo' '
cd $HERE &&
git clone -s --bare .git foo.git &&
cd foo.git && git show -s HEAD
'
test_expect_success 'detection should not be fooled by a symlink' '
cd $HERE &&
rm -fr foo.git &&
git clone -s .git another &&
ln -s another yetanother &&
cd yetanother/.git &&
git show -s HEAD
'
test_done

View File

@@ -418,5 +418,31 @@ EOF
test_expect_success 'quoting' 'cmp .git/config expect'
test_expect_failure 'key with newline' 'git repo-config key.with\\\
newline 123'
test_expect_success 'value with newline' 'git repo-config key.sub value.with\\\
newline'
cat > .git/config <<\EOF
[section]
; comment \
continued = cont\
inued
noncont = not continued ; \
quotecont = "cont;\
inued"
EOF
cat > expect <<\EOF
section.continued=continued
section.noncont=not continued
section.quotecont=cont;inued
EOF
git repo-config --list > result
test_expect_success 'value continued on next line' 'cmp result expect'
test_done

View File

@@ -138,19 +138,19 @@ test_expect_success \
'rm -f o e
git-rev-parse --verify "master@{May 25 2005}" >o 2>e &&
test '"$C"' = $(cat o) &&
test "warning: Log .git/logs/'"$m only goes back to $ed"'." = "$(cat e)"'
test "warning: Log for '\'master\'' only goes back to $ed." = "$(cat e)"'
test_expect_success \
"Query master@{2005-05-25} (before history)" \
'rm -f o e
git-rev-parse --verify master@{2005-05-25} >o 2>e &&
test '"$C"' = $(cat o) &&
echo test "warning: Log .git/logs/'"$m only goes back to $ed"'." = "$(cat e)"'
echo test "warning: Log for '\'master\'' only goes back to $ed." = "$(cat e)"'
test_expect_success \
'Query "master@{May 26 2005 23:31:59}" (1 second before history)' \
'rm -f o e
git-rev-parse --verify "master@{May 26 2005 23:31:59}" >o 2>e &&
test '"$C"' = $(cat o) &&
test "warning: Log .git/logs/'"$m only goes back to $ed"'." = "$(cat e)"'
test "warning: Log for '\''master'\'' only goes back to $ed." = "$(cat e)"'
test_expect_success \
'Query "master@{May 26 2005 23:32:00}" (exactly history start)' \
'rm -f o e

View File

@@ -97,7 +97,8 @@ pull_to_client () {
(
mkdir client &&
cd client &&
git-init 2>> log2.txt
git-init 2>> log2.txt &&
git repo-config transfer.unpacklimit 0
)
add A1

View File

@@ -100,7 +100,33 @@ test_expect_success "checkout -m with dirty tree, renamed" '
git checkout -m renamer &&
fill 1 3 4 5 7 8 >expect &&
diff expect uno &&
! test -f one
! test -f one &&
git diff --cached >current &&
! test -s current
'
test_expect_success 'checkout -m with merge conflict' '
git checkout -f master && git clean &&
fill 1 T 3 4 5 6 S 8 >one &&
if git checkout renamer
then
echo Not happy
false
else
echo "happy - failed correctly"
fi &&
git checkout -m renamer &&
git diff master:one :3:uno |
sed -e "1,/^@@/d" -e "/^ /d" -e "s/^-/d/" -e "s/^+/a/" >current &&
fill d2 aT d7 aS >expect &&
diff current expect &&
git diff --cached two >current &&
! test -s current
'
test_done

View File

@@ -761,7 +761,8 @@ int main(int argc, char **argv)
if (!enter_repo(dir, strict))
die("'%s': unable to chdir or not a git archive", dir);
if (is_repository_shallow())
die("attempt to fetch/clone from a shallow repository");
upload_pack();
return 0;
}