summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/config.txt15
-rw-r--r--Documentation/git-cvsimport.txt2
-rw-r--r--Documentation/git-grep.txt20
-rw-r--r--Documentation/git-init-db.txt51
-rw-r--r--Documentation/git-push.txt2
-rw-r--r--Documentation/git-rev-list.txt5
-rw-r--r--Documentation/git-status.txt6
-rw-r--r--Documentation/git.txt6
-rw-r--r--Documentation/howto/setup-git-server-over-http.txt256
-rw-r--r--Documentation/tutorial-2.txt1
-rwxr-xr-xGIT-VERSION-GEN12
-rw-r--r--Makefile11
-rw-r--r--blame.c2
-rw-r--r--builtin-add.c2
-rw-r--r--builtin-apply.c9
-rw-r--r--builtin-check-ref-format.c2
-rw-r--r--builtin-diff.c13
-rw-r--r--builtin-fmt-merge-msg.c3
-rw-r--r--builtin-grep.c35
-rw-r--r--builtin-help.c2
-rw-r--r--builtin-init-db.c2
-rw-r--r--builtin-log.c2
-rw-r--r--builtin-mv.c5
-rw-r--r--builtin-prune-packed.c (renamed from prune-packed.c)5
-rw-r--r--builtin-prune.c2
-rw-r--r--builtin-push.c4
-rw-r--r--builtin-read-tree.c2
-rw-r--r--builtin-repo-config.c (renamed from repo-config.c)3
-rw-r--r--builtin-rm.c6
-rw-r--r--builtin-tar-tree.c6
-rw-r--r--builtin-write-tree.c2
-rw-r--r--builtin.h2
-rw-r--r--combine-diff.c50
-rw-r--r--diff.c12
-rw-r--r--diffcore-rename.c1
-rw-r--r--diffcore.h3
-rw-r--r--fetch-clone.c4
-rwxr-xr-xgit-annotate.perl129
-rwxr-xr-xgit-clone.sh2
-rw-r--r--git-compat-util.h10
-rwxr-xr-xgit-push.sh87
-rwxr-xr-xgit-sh-setup.sh11
-rwxr-xr-xgit-svn.perl75
-rw-r--r--git.c4
-rwxr-xr-xgitk2
-rw-r--r--hash-object.c6
-rw-r--r--http-fetch.c3
-rw-r--r--http-push.c2
-rw-r--r--index-pack.c2
-rw-r--r--local-fetch.c5
-rw-r--r--log-tree.c2
-rw-r--r--mktag.c2
-rw-r--r--mktree.c2
-rw-r--r--refs.c2
-rw-r--r--revision.c3
-rw-r--r--setup.c2
-rw-r--r--sha1_file.c2
-rw-r--r--sha1_name.c2
-rw-r--r--ssh-fetch.c1
-rwxr-xr-xt/t1003-read-tree-prefix.sh27
-rwxr-xr-xt/t1020-subdirectory.sh109
-rwxr-xr-xt/t4115-apply-symlink.sh49
-rwxr-xr-xt/t7002-grep.sh85
-rw-r--r--verify-pack.c75
64 files changed, 961 insertions, 306 deletions
diff --git a/Documentation/config.txt b/Documentation/config.txt
index e669003f72..ce722a2db0 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -83,9 +83,12 @@ core.repositoryFormatVersion::
version.
core.sharedRepository::
- If true, the repository is made shareable between several users
- in a group (making sure all the files and objects are group-writable).
- See gitlink:git-init-db[1]. False by default.
+ When 'group' (or 'true'), the repository is made shareable between
+ several users in a group (making sure all the files and objects are
+ group-writable). When 'all' (or 'world' or 'everybody'), the
+ repository will be readable by all users, additionally to being
+ group-shareable. When 'umask' (or 'false'), git will use permissions
+ reported by umask(2). See gitlink:git-init-db[1]. False by default.
core.warnAmbiguousRefs::
If true, git will warn you if the ref name you passed it is ambiguous
@@ -223,14 +226,14 @@ showbranch.default::
See gitlink:git-show-branch[1].
tar.umask::
- By default, git-link:git-tar-tree[1] sets file and directories modes
+ By default, gitlink:git-tar-tree[1] sets file and directories modes
to 0666 or 0777. While this is both useful and acceptable for projects
such as the Linux Kernel, it might be excessive for other projects.
With this variable, it becomes possible to tell
- git-link:git-tar-tree[1] to apply a specific umask to the modes above.
+ gitlink:git-tar-tree[1] to apply a specific umask to the modes above.
The special value "user" indicates that the user's current umask will
be used. This should be enough for most projects, as it will lead to
- the same permissions as git-link:git-checkout[1] would use. The default
+ the same permissions as gitlink:git-checkout[1] would use. The default
value remains 0, which means world read-write.
user.email::
diff --git a/Documentation/git-cvsimport.txt b/Documentation/git-cvsimport.txt
index b0c6d7c303..d21d66bfeb 100644
--- a/Documentation/git-cvsimport.txt
+++ b/Documentation/git-cvsimport.txt
@@ -116,7 +116,7 @@ file each time git-cvsimport is run.
+
It is not recommended to use this feature if you intend to
export changes back to CVS again later with
-git-link[1]::git-cvsexportcommit.
+gitlink:git-cvsexportcommit[1].
OUTPUT
------
diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt
index 62a8e7f222..dc7683383c 100644
--- a/Documentation/git-grep.txt
+++ b/Documentation/git-grep.txt
@@ -16,7 +16,7 @@ SYNOPSIS
[-n] [-l | --files-with-matches] [-L | --files-without-match]
[-c | --count]
[-A <post-context>] [-B <pre-context>] [-C <context>]
- [-f <file>] [-e] <pattern>
+ [-f <file>] [-e] <pattern> [--and|--or|--not|(|)|-e <pattern>...]
[<tree>...]
[--] [<path>...]
@@ -74,16 +74,30 @@ OPTIONS
-e::
The next parameter is the pattern. This option has to be
used for patterns starting with - and should be used in
- scripts passing user input to grep.
+ scripts passing user input to grep. Multiple patterns are
+ combined by 'or'.
+
+--and | --or | --not | ( | )::
+ Specify how multiple patterns are combined using boolean
+ expressions. `--or` is the default operator. `--and` has
+ higher precedence than `--or`. `-e` has to be used for all
+ patterns.
`<tree>...`::
Search blobs in the trees for specified patterns.
-`--`::
+\--::
Signals the end of options; the rest of the parameters
are <path> limiters.
+Example
+-------
+
+git grep -e \'#define\' --and \( -e MAX_PATH -e PATH_MAX \)::
+ Looks for a line that has `#define` and either `MAX_PATH` or
+ `PATH_MAX`.
+
Author
------
Originally written by Linus Torvalds <torvalds@osdl.org>, later
diff --git a/Documentation/git-init-db.txt b/Documentation/git-init-db.txt
index 0a4fc14b97..63cd5dab3f 100644
--- a/Documentation/git-init-db.txt
+++ b/Documentation/git-init-db.txt
@@ -8,17 +8,47 @@ git-init-db - Creates an empty git repository
SYNOPSIS
--------
-'git-init-db' [--template=<template_directory>] [--shared]
+'git-init-db' [--template=<template_directory>] [--shared[=<permissions>]]
OPTIONS
-------
+
+--
+
--template=<template_directory>::
- Provide the directory from which templates will be used.
- The default template directory is `/usr/share/git-core/templates`.
---shared::
- Specify that the git repository is to be shared amongst several users.
+Provide the directory from which templates will be used. The default template
+directory is `/usr/share/git-core/templates`.
+
+When specified, `<template_directory>` is used as the source of the template
+files rather than the default. The template files include some directory
+structure, some suggested "exclude patterns", and copies of non-executing
+"hook" files. The suggested patterns and hook files are all modifiable and
+extensible.
+
+--shared[={false|true|umask|group|all|world|everybody}]::
+
+Specify that the git repository is to be shared amongst several users. This
+allows users belonging to the same group to push into that
+repository. When specified, the config variable "core.sharedRepository" is
+set so that files and directories under `$GIT_DIR` are created with the
+requested permissions. When not specified, git will use permissions reported
+by umask(2).
+
+The option can have the following values, defaulting to 'group' if no value
+is given:
+
+ - 'umask' (or 'false'): Use permissions reported by umask(2). The default,
+ when `--shared` is not specified.
+
+ - 'group' (or 'true'): Make the repository group-writable, (and g+sx, since
+ the git group may be not the primary group of all users).
+
+ - 'all' (or 'world' or 'everybody'): Same as 'group', but make the repository
+ readable by all users.
+
+--
DESCRIPTION
@@ -29,12 +59,6 @@ template files.
An initial `HEAD` file that references the HEAD of the master branch
is also created.
-If `--template=<template_directory>` is specified, `<template_directory>`
-is used as the source of the template files rather than the default.
-The template files include some directory structure, some suggested
-"exclude patterns", and copies of non-executing "hook" files. The
-suggested patterns and hook files are all modifiable and extensible.
-
If the `$GIT_DIR` environment variable is set then it specifies a path
to use instead of `./.git` for the base of the repository.
@@ -42,11 +66,6 @@ If the object storage directory is specified via the `$GIT_OBJECT_DIRECTORY`
environment variable then the sha1 directories are created underneath -
otherwise the default `$GIT_DIR/objects` directory is used.
-A shared repository allows users belonging to the same group to push into that
-repository. When specifying `--shared` the config variable "core.sharedRepository"
-is set to 'true' so that directories under `$GIT_DIR` are made group writable
-(and g+sx, since the git group may be not the primary group of all users).
-
Running `git-init-db` in an existing repository is safe. It will not overwrite
things that are already there. The primary reason for rerunning `git-init-db`
is to pick up newly added templates.
diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index 56afd64f42..d4ae99fa53 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -8,7 +8,7 @@ git-push - Update remote refs along with associated objects
SYNOPSIS
--------
-'git-push' [--all] [--tags] [--force] <repository> <refspec>...
+'git-push' [--all] [--tags] [-f | --force] <repository> <refspec>...
DESCRIPTION
-----------
diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt
index f60eacd93e..dd9fff16d3 100644
--- a/Documentation/git-rev-list.txt
+++ b/Documentation/git-rev-list.txt
@@ -22,6 +22,7 @@ SYNOPSIS
[ [\--objects | \--objects-edge] [ \--unpacked ] ]
[ \--pretty | \--header ]
[ \--bisect ]
+ [ \--merge ]
<commit>... [ \-- <paths>... ]
DESCRIPTION
@@ -123,6 +124,10 @@ OPTIONS
topological order (i.e. descendant commits are shown
before their parents).
+--merge::
+ After a failed merge, show refs that touch files having a
+ conflict and don't exist on all heads to merge.
+
Author
------
Written by Linus Torvalds <torvalds@osdl.org>
diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt
index e446f4812e..ce7857e5a9 100644
--- a/Documentation/git-status.txt
+++ b/Documentation/git-status.txt
@@ -8,7 +8,7 @@ git-status - Show working tree status
SYNOPSIS
--------
-'git-status'
+'git-status' <options>...
DESCRIPTION
-----------
@@ -23,6 +23,10 @@ If there is no path that is different between the index file and
the current HEAD commit, the command exits with non-zero
status.
+The command takes the same set of options as `git-commit`; it
+shows what would be committed if the same options are given to
+`git-commit`.
+
OUTPUT
------
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 7310a2b8b8..bcf187a11c 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -397,6 +397,9 @@ gitlink:git-quiltimport[1]::
gitlink:git-relink[1]::
Hardlink common objects in local repositories.
+gitlink:git-svn[1]::
+ Bidirectional operation between a single Subversion branch and git.
+
gitlink:git-svnimport[1]::
Import a SVN repository into git.
@@ -442,6 +445,9 @@ gitlink:git-get-tar-commit-id[1]::
gitlink:git-imap-send[1]::
Dump a mailbox from stdin into an imap folder.
+gitlink:git-instaweb[1]::
+ Instantly browse your working repository in gitweb.
+
gitlink:git-mailinfo[1]::
Extracts patch and authorship information from a single
e-mail message, optionally transliterating the commit
diff --git a/Documentation/howto/setup-git-server-over-http.txt b/Documentation/howto/setup-git-server-over-http.txt
new file mode 100644
index 0000000000..ba191569af
--- /dev/null
+++ b/Documentation/howto/setup-git-server-over-http.txt
@@ -0,0 +1,256 @@
+From: Rutger Nijlunsing <rutger@nospam.com>
+Subject: Setting up a git repository which can be pushed into and pulled from over HTTP.
+Date: Thu, 10 Aug 2006 22:00:26 +0200
+
+Since Apache is one of those packages people like to compile
+themselves while others prefer the bureaucrat's dream Debian, it is
+impossible to give guidelines which will work for everyone. Just send
+some feedback to the mailing list at git@vger.kernel.org to get this
+document tailored to your favorite distro.
+
+
+What's needed:
+
+- Have an Apache web-server
+
+ On Debian:
+ $ apt-get install apache2
+ To get apache2 by default started,
+ edit /etc/default/apache2 and set NO_START=0
+
+- can edit the configuration of it.
+
+ This could be found under /etc/httpd, or refer to your Apache documentation.
+
+ On Debian: this means being able to edit files under /etc/apache2
+
+- can restart it.
+
+ 'apachectl --graceful' might do. If it doesn't, just stop and
+ restart apache. Be warning that active connections to your server
+ might be aborted by this.
+
+ On Debian:
+ $ /etc/init.d/apache2 restart
+ or
+ $ /etc/init.d/apache2 force-reload
+ (which seems to do the same)
+ This adds symlinks from the /etc/apache2/mods-enabled to
+ /etc/apache2/mods-available.
+
+- have permissions to chown a directory
+
+- have git installed at the server _and_ client
+
+In effect, this probably means you're going to be root.
+
+
+Step 1: setup a bare GIT repository
+-----------------------------------
+
+At the time of writing, git-http-push cannot remotely create a GIT
+repository. So we have to do that at the server side with git. Another
+option would be to generate an empty repository at the client and copy
+it to the server with WebDAV. But then you're probably the first to
+try that out :)
+
+Create the directory under the DocumentRoot of the directories served
+by Apache. As an example we take /usr/local/apache2, but try "grep
+DocumentRoot /where/ever/httpd.conf" to find your root:
+
+ $ cd /usr/local/apache/htdocs
+ $ mkdir my-new-repo.git
+
+ On Debian:
+
+ $ cd /var/www
+ $ mkdir my-new-repo.git
+
+
+Initialize a bare repository
+
+ $ cd my-new-repo.git
+ $ git --bare init-db
+
+
+Change the ownership to your web-server's credentials. Use "grep ^User
+httpd.conf" and "grep ^Group httpd.conf" to find out:
+
+ $ chown -R www.www .
+
+ On Debian:
+
+ $ chown -R www-data.www-data .
+
+
+If you do not know which user Apache runs as, you can alternatively do
+a "chmod -R a+w .", inspect the files which are created later on, and
+set the permissions appropriately.
+
+Restart apache2, and check whether http://server/my-new-repo.git gives
+a directory listing. If not, check whether apache started up
+successfully.
+
+
+Step 2: enable DAV on this repository
+-------------------------------------
+
+First make sure the dav_module is loaded. For this, insert in httpd.conf:
+
+ LoadModule dav_module libexec/httpd/libdav.so
+ AddModule mod_dav.c
+
+Also make sure that this line exists which is the file used for
+locking DAV operations:
+
+ DAVLockDB "/usr/local/apache2/temp/DAV.lock"
+
+ On Debian these steps can be performed with:
+
+ Enable the dav and dav_fs modules of apache:
+ $ a2enmod dav_fs
+ (just to be sure. dav_fs might be unneeded, I don't know)
+ $ a2enmod dav
+ The DAV lock is located in /etc/apache2/mods-available/dav_fs.conf:
+ DAVLockDB /var/lock/apache2/DAVLock
+
+Of course, it can point somewhere else, but the string is actually just a
+prefix in some Apache configurations, and therefore the _directory_ has to
+be writable by the user Apache runs as.
+
+Then, add something like this to your httpd.conf
+
+ <Location /my-new-repo.git>
+ DAV on
+ AuthType Basic
+ AuthName "Git"
+ AuthUserFile /usr/local/apache2/conf/passwd.git
+ Require valid-user
+ </Location>
+
+ On Debian:
+ Create (or add to) /etc/apache2/conf.d/git.conf :
+
+ <Location /my-new-repo.git>
+ DAV on
+ AuthType Basic
+ AuthName "Git"
+ AuthUserFile /etc/apache2/passwd.git
+ Require valid-user
+ </Location>
+
+ Debian automatically reads all files under /etc/apach2/conf.d.
+
+The password file can be somewhere else, but it has to be readable by
+Apache and preferably not readable by the world.
+
+Create this file by
+ $ htpasswd -c /usr/local/apache2/conf/passwd.git <user>
+
+ On Debian:
+ $ htpasswd -c /etc/apache2/passwd.git <user>
+
+You will be asked a password, and the file is created. Subsequent calls
+to htpasswd should omit the '-c' option, since you want to append to the
+existing file.
+
+You need to restart Apache.
+
+Now go to http://<username>@<servername>/my-new-repo.git in your
+browser to check whether it asks for a password and accepts the right
+password.
+
+On Debian:
+
+ To test the WebDAV part, do:
+
+ $ apt-get install litmus
+ $ litmus http://<servername>/my-new-repo.git <username> <password>
+
+ Most tests should pass.
+
+A command line tool to test WebDAV is cadaver.
+
+If you're into Windows, from XP onwards Internet Explorer supports
+WebDAV. For this, do Internet Explorer -> Open Location ->
+http://<servername>/my-new-repo.git [x] Open as webfolder -> login .
+
+
+Step 3: setup the client
+------------------------
+
+Make sure that you have HTTP support, i.e. your git was built with curl.
+The easiest way to check is to look for the executable 'git-http-push'.
+
+Then, add the following to your $HOME/.netrc (you can do without, but will be
+asked to input your password a _lot_ of times):
+
+ machine <servername>
+ login <username>
+ password <password>
+
+...and set permissions:
+ chmod 600 ~/.netrc
+
+If you want to access the web-server by its IP, you have to type that in,
+instead of the server name.
+
+To check whether all is OK, do:
+
+ curl --netrc --location -v http://<username>@<servername>/my-new-repo.git/
+
+...this should give a directory listing in HTML of /var/www/my-new-repo.git .
+
+
+Now, add the remote in your existing repository which contains the project
+you want to export:
+
+ $ git-repo-config remote.upload.url \
+ http://<username>@<servername>/my-new-repo.git/
+
+It is important to put the last '/'; Without it, the server will send
+a redirect which git-http-push does not (yet) understand, and git-http-push
+will repeat the request infinitely.
+
+
+Step 4: make the initial push
+-----------------------------
+
+From your client repository, do
+
+ $ git push upload master
+
+This pushes branch 'master' (which is assumed to be the branch you
+want to export) to repository called 'upload', which we previously
+defined with git-repo-config.
+
+
+Troubleshooting:
+----------------
+
+If git-http-push says
+
+ Error: no DAV locking support on remote repo http://...
+
+then it means the web-server did not accept your authentication. Make sure
+that the user name and password matches in httpd.conf, .netrc and the URL
+you are uploading to.
+
+If git-http-push shows you an error (22/502) when trying to MOVE a blob,
+it means that your web-server somehow does not recognize its name in the
+request; This can happen when you start Apache, but then disable the
+network interface. A simple restart of Apache helps.
+
+Errors like (22/502) are of format (curl error code/http error
+code). So (22/404) means something like 'not found' at the server.
+
+Reading /usr/local/apache2/logs/error_log is often helpful.
+
+ On Debian: Read /var/log/apache2/error.log instead.
+
+
+Debian References: http://www.debian-administration.org/articles/285
+
+Authors
+ Johannes Schindelin <Johannes.Schindelin@gmx.de>
+ Rutger Nijlunsing <git@wingding.demon.nl>
diff --git a/Documentation/tutorial-2.txt b/Documentation/tutorial-2.txt
index 894ca5e06f..2f4fe1217a 100644
--- a/Documentation/tutorial-2.txt
+++ b/Documentation/tutorial-2.txt
@@ -244,6 +244,7 @@ $ git ls-files --stage
$ git cat-file -t 513feba2
blob
$ git cat-file blob 513feba2
+hello world!
hello world, again
------------------------------------------------
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index 5d25b7e12b..14923c973b 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,11 +1,19 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v1.4.GIT
+DEF_VER=v1.4.2.GIT
+
+LF='
+'
# First try git-describe, then see if there is a version file
# (included in release tarballs), then default
-if VN=$(git describe --abbrev=4 HEAD 2>/dev/null); then
+if VN=$(git describe --abbrev=4 HEAD 2>/dev/null) &&
+ case "$VN" in
+ *$LF*) (exit 1) ;;
+ v[0-9]*) : happy ;;
+ esac
+then
VN=$(echo "$VN" | sed -e 's/-/./g');
elif test -f version
then
diff --git a/Makefile b/Makefile
index e66e9b16a5..0761d6c6ed 100644
--- a/Makefile
+++ b/Makefile
@@ -178,14 +178,14 @@ PROGRAMS = \
git-hash-object$X git-index-pack$X git-local-fetch$X \
git-merge-base$X \
git-merge-index$X git-mktag$X git-mktree$X git-pack-objects$X git-patch-id$X \
- git-peek-remote$X git-prune-packed$X git-receive-pack$X \
+ git-peek-remote$X git-receive-pack$X \
git-send-pack$X git-shell$X \
git-show-index$X git-ssh-fetch$X \
git-ssh-upload$X git-unpack-file$X \
git-unpack-objects$X git-update-server-info$X \
git-upload-pack$X git-verify-pack$X \
git-symbolic-ref$X \
- git-name-rev$X git-pack-redundant$X git-repo-config$X git-var$X \
+ git-name-rev$X git-pack-redundant$X git-var$X \
git-describe$X git-merge-tree$X git-blame$X git-imap-send$X
BUILT_INS = git-log$X git-whatchanged$X git-show$X git-update-ref$X \
@@ -197,7 +197,8 @@ BUILT_INS = git-log$X git-whatchanged$X git-show$X git-update-ref$X \
git-read-tree$X git-commit-tree$X git-write-tree$X \
git-apply$X git-show-branch$X git-diff-files$X git-update-index$X \
git-diff-index$X git-diff-stages$X git-diff-tree$X git-cat-file$X \
- git-fmt-merge-msg$X git-prune$X git-mv$X
+ git-fmt-merge-msg$X git-prune$X git-mv$X git-prune-packed$X \
+ git-repo-config$X
# what 'all' will build and 'install' will install, in gitexecdir
ALL_PROGRAMS = $(PROGRAMS) $(SIMPLE_PROGRAMS) $(SCRIPTS)
@@ -254,7 +255,7 @@ BUILTIN_OBJS = \
builtin-diff-index.o builtin-diff-stages.o builtin-diff-tree.o \
builtin-cat-file.o builtin-mailsplit.o builtin-stripspace.o \
builtin-update-ref.o builtin-fmt-merge-msg.o builtin-prune.o \
- builtin-mv.o
+ builtin-mv.o builtin-prune-packed.o builtin-repo-config.o
GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
LIBS = $(GITLIBS) -lz
@@ -313,9 +314,9 @@ ifeq ($(uname_O),Cygwin)
NO_D_TYPE_IN_DIRENT = YesPlease
NO_D_INO_IN_DIRENT = YesPlease
NO_STRCASESTR = YesPlease
- NO_STRLCPY = YesPlease
NO_SYMLINK_HEAD = YesPlease
NEEDS_LIBICONV = YesPlease
+ NO_C99_FORMAT = YesPlease
# There are conflicting reports about this.
# On some boxes NO_MMAP is needed, and not so elsewhere.
# Try uncommenting this if you see things break -- YMMV.
diff --git a/blame.c b/blame.c
index 76712b5962..7099b53c72 100644
--- a/blame.c
+++ b/blame.c
@@ -20,7 +20,7 @@
#define DEBUG 0
-static const char blame_usage[] = "[-c] [-l] [-t] [-S <revs-file>] [--] file [commit]\n"
+static const char blame_usage[] = "git-blame [-c] [-l] [-t] [-S <revs-file>] [--] file [commit]\n"
" -c, --compatibility Use the same output mode as git-annotate (Default: off)\n"
" -l, --long Show long commit SHA1 (Default: off)\n"
" -t, --time Show raw timestamp (Default: off)\n"
diff --git a/builtin-add.c b/builtin-add.c
index f548b8007d..096b611b5b 100644
--- a/builtin-add.c
+++ b/builtin-add.c
@@ -117,7 +117,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
verbose = 1;
continue;
}
- die(builtin_add_usage);
+ usage(builtin_add_usage);
}
pathspec = get_pathspec(prefix, argv + i);
diff --git a/builtin-apply.c b/builtin-apply.c
index f8c6763c74..be2c7152cd 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -1698,6 +1698,12 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *
desc.buffer = buf;
if (apply_fragments(&desc, patch) < 0)
return -1;
+
+ /* NUL terminate the result */
+ if (desc.alloc <= desc.size)
+ desc.buffer = xrealloc(desc.buffer, desc.size + 1);
+ desc.buffer[desc.size] = 0;
+
patch->result = desc.buffer;
patch->resultsize = desc.size;
@@ -2040,6 +2046,9 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf,
int fd;
if (S_ISLNK(mode))
+ /* Although buf:size is counted string, it also is NUL
+ * terminated.
+ */
return symlink(buf, path);
fd = open(path, O_CREAT | O_EXCL | O_WRONLY, (mode & 0100) ? 0777 : 0666);
if (fd < 0)
diff --git a/builtin-check-ref-format.c b/builtin-check-ref-format.c
index 701de439ae..fe04be77a9 100644
--- a/builtin-check-ref-format.c
+++ b/builtin-check-ref-format.c
@@ -9,6 +9,6 @@
int cmd_check_ref_format(int argc, const char **argv, const char *prefix)
{
if (argc != 2)
- usage("git check-ref-format refname");
+ usage("git-check-ref-format refname");
return !!check_ref_format(argv[1]);
}
diff --git a/builtin-diff.c b/builtin-diff.c
index 48d2fd03b7..a090e298a5 100644
--- a/builtin-diff.c
+++ b/builtin-diff.c
@@ -23,7 +23,7 @@ struct blobinfo {
};
static const char builtin_diff_usage[] =
-"diff <options> <rev>{0,2} -- <path>*";
+"git-diff <options> <rev>{0,2} -- <path>*";
static int builtin_diff_files(struct rev_info *revs,
int argc, const char **argv)
@@ -125,9 +125,6 @@ static int builtin_diff_blobs(struct rev_info *revs,
int argc, const char **argv,
struct blobinfo *blob)
{
- /* Blobs: the arguments are reversed when setup_revisions()
- * picked them up.
- */
unsigned mode = canon_mode(S_IFREG | 0644);
if (argc > 1)
@@ -135,8 +132,8 @@ static int builtin_diff_blobs(struct rev_info *revs,
stuff_change(&revs->diffopt,
mode, mode,
- blob[1].sha1, blob[0].sha1,
- blob[0].name, blob[0].name);
+ blob[0].sha1, blob[1].sha1,
+ blob[0].name, blob[1].name);
diffcore_std(&revs->diffopt);
diff_flush(&revs->diffopt);
return 0;
@@ -256,7 +253,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
argc = setup_revisions(argc, argv, &rev, NULL);
if (!rev.diffopt.output_format) {
rev.diffopt.output_format = DIFF_FORMAT_PATCH;
- diff_setup_done(&rev.diffopt);
+ if (diff_setup_done(&rev.diffopt) < 0)
+ die("diff_setup_done failed");
}
/* Do we have --cached and not have a pending object, then
@@ -351,6 +349,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
* A and B. We have ent[0] == merge-base, ent[1] == A,
* and ent[2] == B. Show diff between the base and B.
*/
+ ent[1] = ent[2];
return builtin_diff_tree(&rev, argc, argv, ent);
}
else
diff --git a/builtin-fmt-merge-msg.c b/builtin-fmt-merge-msg.c
index c84224ee84..485ede7cad 100644
--- a/builtin-fmt-merge-msg.c
+++ b/builtin-fmt-merge-msg.c
@@ -1,3 +1,4 @@
+#include "builtin.h"
#include "cache.h"
#include "commit.h"
#include "diff.h"
@@ -242,7 +243,7 @@ static void shortlog(const char *name, unsigned char *sha1,
free_list(&subjects);
}
-int cmd_fmt_merge_msg(int argc, char **argv, const char *prefix)
+int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
{
int limit = 20, i = 0;
char line[1024];
diff --git a/builtin-grep.c b/builtin-grep.c
index 69b7c4862a..93b7e07b30 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -410,8 +410,10 @@ static int fixmatch(const char *pattern, char *line, regmatch_t *match)
static int match_one_pattern(struct grep_opt *opt, struct grep_pat *p, char *bol, char *eol)
{
int hit = 0;
+ int at_true_bol = 1;
regmatch_t pmatch[10];
+ again:
if (!opt->fixed) {
regex_t *exp = &p->regexp;
hit = !regexec(exp, bol, ARRAY_SIZE(pmatch),
@@ -422,22 +424,35 @@ static int match_one_pattern(struct grep_opt *opt, struct grep_pat *p, char *bol
}
if (hit && opt->word_regexp) {
- /* Match beginning must be either
- * beginning of the line, or at word
- * boundary (i.e. the last char must
- * not be alnum or underscore).
- */
if ((pmatch[0].rm_so < 0) ||
(eol - bol) <= pmatch[0].rm_so ||
(pmatch[0].rm_eo < 0) ||
(eol - bol) < pmatch[0].rm_eo)
die("regexp returned nonsense");
- if (pmatch[0].rm_so != 0 &&
- word_char(bol[pmatch[0].rm_so-1]))
- hit = 0;
- if (pmatch[0].rm_eo != (eol-bol) &&
- word_char(bol[pmatch[0].rm_eo]))
+
+ /* Match beginning must be either beginning of the
+ * line, or at word boundary (i.e. the last char must
+ * not be a word char). Similarly, match end must be
+ * either end of the line, or at word boundary
+ * (i.e. the next char must not be a word char).
+ */
+ if ( ((pmatch[0].rm_so == 0 && at_true_bol) ||
+ !word_char(bol[pmatch[0].rm_so-1])) &&
+ ((pmatch[0].rm_eo == (eol-bol)) ||
+ !word_char(bol[pmatch[0].rm_eo])) )
+ ;
+ else
hit = 0;
+
+ if (!hit && pmatch[0].rm_so + bol + 1 < eol) {
+ /* There could be more than one match on the
+ * line, and the first match might not be
+ * strict word match. But later ones could be!
+ */
+ bol = pmatch[0].rm_so + bol + 1;
+ at_true_bol = 0;
+ goto again;
+ }
}
return hit;
}
diff --git a/builtin-help.c b/builtin-help.c
index fb731cc934..6484cb9df2 100644
--- a/builtin-help.c
+++ b/builtin-help.c
@@ -140,7 +140,7 @@ static void list_commands(const char *exec_path, const char *pattern)
continue;
entlen = strlen(de->d_name);
- if (4 < entlen && !strcmp(de->d_name + entlen - 4, ".exe"))
+ if (has_extension(de->d_name, ".exe"))
entlen -= 4;
if (longest < entlen)
diff --git a/builtin-init-db.c b/builtin-init-db.c
index 52473edf56..5085018e46 100644
--- a/builtin-init-db.c
+++ b/builtin-init-db.c
@@ -267,7 +267,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
else if (!strncmp(arg, "--shared=", 9))
shared_repository = git_config_perm("arg", arg+9);
else
- die(init_db_usage);
+ usage(init_db_usage);
}
/*
diff --git a/builtin-log.c b/builtin-log.c
index bba1496bf2..691cf3aef7 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -257,6 +257,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
char message_id[1024];
char ref_message_id[1024];
+ setup_ident();
git_config(git_format_config);
init_revisions(&rev, prefix);
rev.commit_format = CMIT_FMT_EMAIL;
@@ -306,7 +307,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
!strcmp(argv[i], "-s")) {
const char *committer;
const char *endpos;
- setup_ident();
committer = git_committer_info(1);
endpos = strchr(committer, '>');
if (!endpos)
diff --git a/builtin-mv.c b/builtin-mv.c
index 62ae937cb1..ce8187c1e9 100644
--- a/builtin-mv.c
+++ b/builtin-mv.c
@@ -48,7 +48,8 @@ static const char *add_slash(const char *path)
if (path[len - 1] != '/') {
char *with_slash = xmalloc(len + 2);
memcpy(with_slash, path, len);
- strcat(with_slash + len, "/");
+ with_slash[len++] = '/';
+ with_slash[len] = 0;
return with_slash;
}
return path;
@@ -99,7 +100,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
ignore_errors = 1;
continue;
}
- die(builtin_mv_usage);
+ usage(builtin_mv_usage);
}
count = argc - i - 1;
if (count < 1)
diff --git a/prune-packed.c b/builtin-prune-packed.c
index d24b097114..d3dd94d9ef 100644
--- a/prune-packed.c
+++ b/builtin-prune-packed.c
@@ -1,3 +1,4 @@
+#include "builtin.h"
#include "cache.h"
static const char prune_packed_usage[] =
@@ -54,12 +55,10 @@ static void prune_packed_objects(void)
}
}
-int main(int argc, char **argv)
+int cmd_prune_packed(int argc, const char **argv, const char *prefix)
{
int i;
- setup_git_directory();
-
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
diff --git a/builtin-prune.c b/builtin-prune.c
index 6a86eb52ae..89ec7f1426 100644
--- a/builtin-prune.c
+++ b/builtin-prune.c
@@ -10,7 +10,7 @@
#include "builtin.h"
#include "cache-tree.h"
-static const char prune_usage[] = "git prune [-n]";
+static const char prune_usage[] = "git-prune [-n]";
static int show_only = 0;
static struct rev_info revs;
diff --git a/builtin-push.c b/builtin-push.c
index a824171066..53bc378f73 100644
--- a/builtin-push.c
+++ b/builtin-push.c
@@ -8,7 +8,7 @@
#define MAX_URI (16)
-static const char push_usage[] = "git push [--all] [--tags] [--force] <repository> [<refspec>...]";
+static const char push_usage[] = "git-push [--all] [--tags] [-f | --force] <repository> [<refspec>...]";
static int all = 0, tags = 0, force = 0, thin = 1;
static const char *execute = NULL;
@@ -291,7 +291,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
tags = 1;
continue;
}
- if (!strcmp(arg, "--force")) {
+ if (!strcmp(arg, "--force") || !strcmp(arg, "-f")) {
force = 1;
continue;
}
diff --git a/builtin-read-tree.c b/builtin-read-tree.c
index 49c10bf221..b30160a5b3 100644
--- a/builtin-read-tree.c
+++ b/builtin-read-tree.c
@@ -870,7 +870,7 @@ static const char read_tree_usage[] = "git-read-tree (<sha> | [[-m [--aggressive
static struct lock_file lock_file;
-int cmd_read_tree(int argc, const char **argv, const char *prefix)
+int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
{
int i, newfd, stage = 0;
unsigned char sha1[20];
diff --git a/repo-config.c b/builtin-repo-config.c
index 743f02b7de..c821e22717 100644
--- a/repo-config.c
+++ b/builtin-repo-config.c
@@ -1,3 +1,4 @@
+#include "builtin.h"
#include "cache.h"
#include <regex.h>
@@ -128,7 +129,7 @@ free_strings:
return ret;
}
-int main(int argc, const char **argv)
+int cmd_repo_config(int argc, const char **argv, const char *prefix)
{
int nongit = 0;
setup_git_directory_gently(&nongit);
diff --git a/builtin-rm.c b/builtin-rm.c
index 92d205a715..8af3d7eb48 100644
--- a/builtin-rm.c
+++ b/builtin-rm.c
@@ -80,7 +80,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
force = 1;
continue;
}
- die(builtin_rm_usage);
+ usage(builtin_rm_usage);
}
if (argc <= i)
usage(builtin_rm_usage);
@@ -115,7 +115,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
printf("rm '%s'\n", path);
if (remove_file_from_cache(path))
- die("git rm: unable to remove %s", path);
+ die("git-rm: unable to remove %s", path);
cache_tree_invalidate_path(active_cache_tree, path);
}
@@ -139,7 +139,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
continue;
}
if (!removed)
- die("git rm: %s: %s", path, strerror(errno));
+ die("git-rm: %s: %s", path, strerror(errno));
}
}
diff --git a/builtin-tar-tree.c b/builtin-tar-tree.c
index 7c48db9ec8..215892b696 100644
--- a/builtin-tar-tree.c
+++ b/builtin-tar-tree.c
@@ -314,6 +314,7 @@ static int generate_tar(int argc, const char **argv, const char *prefix)
struct commit *commit;
struct tree_desc tree;
struct strbuf current_path;
+ void *buffer;
current_path.buf = xmalloc(PATH_MAX);
current_path.alloc = PATH_MAX;
@@ -341,8 +342,8 @@ static int generate_tar(int argc, const char **argv, const char *prefix)
} else
archive_time = time(NULL);
- tree.buf = read_object_with_reference(sha1, tree_type, &tree.size,
- tree_sha1);
+ tree.buf = buffer = read_object_with_reference(sha1, tree_type,
+ &tree.size, tree_sha1);
if (!tree.buf)
die("not a reference to a tag, commit or tree object: %s",
sha1_to_hex(sha1));
@@ -351,6 +352,7 @@ static int generate_tar(int argc, const char **argv, const char *prefix)
write_entry(tree_sha1, &current_path, 040777, NULL, 0);
traverse_tree(&tree, &current_path);
write_trailer();
+ free(buffer);
free(current_path.buf);
return 0;
}
diff --git a/builtin-write-tree.c b/builtin-write-tree.c
index 0289f59936..6b62d7dc8c 100644
--- a/builtin-write-tree.c
+++ b/builtin-write-tree.c
@@ -73,7 +73,7 @@ int cmd_write_tree(int argc, const char **argv, const char *unused_prefix)
else if (!strncmp(arg, "--prefix=", 9))
prefix = arg + 9;
else
- die(write_tree_usage);
+ usage(write_tree_usage);
argc--; argv++;
}
diff --git a/builtin.h b/builtin.h
index f10d3b77c8..26ebcaf213 100644
--- a/builtin.h
+++ b/builtin.h
@@ -20,6 +20,7 @@ extern int cmd_format_patch(int argc, const char **argv, const char *prefix);
extern int cmd_count_objects(int argc, const char **argv, const char *prefix);
extern int cmd_prune(int argc, const char **argv, const char *prefix);
+extern int cmd_prune_packed(int argc, const char **argv, const char *prefix);
extern int cmd_push(int argc, const char **argv, const char *prefix);
extern int cmd_grep(int argc, const char **argv, const char *prefix);
@@ -47,6 +48,7 @@ extern int cmd_update_index(int argc, const char **argv, const char *prefix);
extern int cmd_update_ref(int argc, const char **argv, const char *prefix);
extern int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix);
extern int cmd_mv(int argc, const char **argv, const char *prefix);
+extern int cmd_repo_config(int argc, const char **argv, const char *prefix);
extern int cmd_write_tree(int argc, const char **argv, const char *prefix);
extern int write_tree(unsigned char *sha1, int missing_ok, const char *prefix);
diff --git a/combine-diff.c b/combine-diff.c
index 919112bba9..ba8baca0ab 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -497,11 +497,17 @@ static void show_parent_lno(struct sline *sline, unsigned long l0, unsigned long
printf(" -%lu,%lu", l0, l1-l0);
}
-static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent)
+static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent,
+ int use_color)
{
unsigned long mark = (1UL<<num_parent);
int i;
unsigned long lno = 0;
+ const char *c_frag = diff_get_color(use_color, DIFF_FRAGINFO);
+ const char *c_new = diff_get_color(use_color, DIFF_FILE_NEW);
+ const char *c_old = diff_get_color(use_color, DIFF_FILE_OLD);
+ const char *c_plain = diff_get_color(use_color, DIFF_PLAIN);
+ const char *c_reset = diff_get_color(use_color, DIFF_RESET);
if (!cnt)
return; /* result deleted */
@@ -522,12 +528,13 @@ static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent)
rlines = hunk_end - lno;
if (cnt < hunk_end)
rlines--; /* pointing at the last delete hunk */
+ fputs(c_frag, stdout);
for (i = 0; i <= num_parent; i++) putchar(combine_marker);
for (i = 0; i < num_parent; i++)
show_parent_lno(sline, lno, hunk_end, i);
printf(" +%lu,%lu ", lno+1, rlines);
for (i = 0; i <= num_parent; i++) putchar(combine_marker);
- putchar('\n');
+ printf("%s\n", c_reset);
while (lno < hunk_end) {
struct lline *ll;
int j;
@@ -535,18 +542,23 @@ static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent)
sl = &sline[lno++];
ll = sl->lost_head;
while (ll) {
+ fputs(c_old, stdout);
for (j = 0; j < num_parent; j++) {
if (ll->parent_map & (1UL<<j))
putchar('-');
else
putchar(' ');
}
- puts(ll->line);
+ printf("%s%s\n", ll->line, c_reset);
ll = ll->next;
}
if (cnt < lno)
break;
p_mask = 1;
+ if (!(sl->flag & (mark-1)))
+ fputs(c_plain, stdout);
+ else
+ fputs(c_new, stdout);
for (j = 0; j < num_parent; j++) {
if (p_mask & sl->flag)
putchar('+');
@@ -554,7 +566,7 @@ static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent)
putchar(' ');
p_mask <<= 1;
}
- printf("%.*s\n", sl->len, sl->bol);
+ printf("%.*s%s\n", sl->len, sl->bol, c_reset);
}
}
}
@@ -586,14 +598,15 @@ static void reuse_combine_diff(struct sline *sline, unsigned long cnt,
sline->p_lno[i] = sline->p_lno[j];
}
-static void dump_quoted_path(const char *prefix, const char *path)
+static void dump_quoted_path(const char *prefix, const char *path,
+ const char *c_meta, const char *c_reset)
{
- fputs(prefix, stdout);
+ printf("%s%s", c_meta, prefix);
if (quote_c_style(path, NULL, NULL, 0))
quote_c_style(path, NULL, stdout, 0);
else
printf("%s", path);
- putchar('\n');
+ printf("%s\n", c_reset);
}
static int show_patch_diff(struct combine_diff_path *elem, int num_parent,
@@ -699,18 +712,22 @@ static int show_patch_diff(struct combine_diff_path *elem, int num_parent,
if (show_hunks || mode_differs || working_tree_file) {
const char *abb;
+ int use_color = opt->color_diff;
+ const char *c_meta = diff_get_color(use_color, DIFF_METAINFO);
+ const char *c_reset = diff_get_color(use_color, DIFF_RESET);
if (rev->loginfo)
show_log(rev, opt->msg_sep);
- dump_quoted_path(dense ? "diff --cc " : "diff --combined ", elem->path);
- printf("index ");
+ dump_quoted_path(dense ? "diff --cc " : "diff --combined ",
+ elem->path, c_meta, c_reset);
+ printf("%sindex ", c_meta);
for (i = 0; i < num_parent; i++) {
abb = find_unique_abbrev(elem->parent[i].sha1,
abbrev);
printf("%s%s", i ? "," : "", abb);
}
abb = find_unique_abbrev(elem->sha1, abbrev);
- printf("..%s\n", abb);
+ printf("..%s%s\n", abb, c_reset);
if (mode_differs) {
int added = !!elem->mode;
@@ -719,10 +736,11 @@ static int show_patch_diff(struct combine_diff_path *elem, int num_parent,
DIFF_STATUS_ADDED)
added = 0;
if (added)
- printf("new file mode %06o", elem->mode);
+ printf("%snew file mode %06o",
+ c_meta, elem->mode);
else {
if (!elem->mode)
- printf("deleted file ");
+ printf("%sdeleted file ", c_meta);
printf("mode ");
for (i = 0; i < num_parent; i++) {
printf("%s%06o", i ? "," : "",
@@ -731,11 +749,11 @@ static int show_patch_diff(struct combine_diff_path *elem, int num_parent,
if (elem->mode)
printf("..%06o", elem->mode);
}
- putchar('\n');
+ printf("%s\n", c_reset);
}
- dump_quoted_path("--- a/", elem->path);
- dump_quoted_path("+++ b/", elem->path);
- dump_sline(sline, cnt, num_parent);
+ dump_quoted_path("--- a/", elem->path, c_meta, c_reset);
+ dump_quoted_path("+++ b/", elem->path, c_meta, c_reset);
+ dump_sline(sline, cnt, num_parent, opt->color_diff);
}
free(result);
diff --git a/diff.c b/diff.c
index 607c357f5a..b3b1781a9c 100644
--- a/diff.c
+++ b/diff.c
@@ -1515,10 +1515,8 @@ void diff_setup(struct diff_options *options)
int diff_setup_done(struct diff_options *options)
{
- if ((options->find_copies_harder &&
- options->detect_rename != DIFF_DETECT_COPY) ||
- (0 <= options->rename_limit && !options->detect_rename))
- return -1;
+ if (options->find_copies_harder)
+ options->detect_rename = DIFF_DETECT_COPY;
if (options->output_format & (DIFF_FORMAT_NAME |
DIFF_FORMAT_NAME_STATUS |
@@ -1786,13 +1784,9 @@ struct diff_filepair *diff_queue(struct diff_queue_struct *queue,
struct diff_filespec *one,
struct diff_filespec *two)
{
- struct diff_filepair *dp = xmalloc(sizeof(*dp));
+ struct diff_filepair *dp = xcalloc(1, sizeof(*dp));
dp->one = one;
dp->two = two;
- dp->score = 0;
- dp->status = 0;
- dp->source_stays = 0;
- dp->broken_pair = 0;
if (queue)
diff_q(queue, dp);
return dp;
diff --git a/diffcore-rename.c b/diffcore-rename.c
index 1de8d32502..0ec488a903 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -205,6 +205,7 @@ static void record_rename_pair(int dst_index, int src_index, int score)
fill_filespec(two, dst->sha1, dst->mode);
dp = diff_queue(NULL, one, two);
+ dp->renamed_pair = 1;
if (!strcmp(src->path, dst->path))
dp->score = rename_src[src_index].score;
else
diff --git a/diffcore.h b/diffcore.h
index 73c7842cc7..2249bc2c05 100644
--- a/diffcore.h
+++ b/diffcore.h
@@ -53,11 +53,12 @@ struct diff_filepair {
char status; /* M C R N D U (see Documentation/diff-format.txt) */
unsigned source_stays : 1; /* all of R/C are copies */
unsigned broken_pair : 1;
+ unsigned renamed_pair : 1;
};
#define DIFF_PAIR_UNMERGED(p) \
(!DIFF_FILE_VALID((p)->one) && !DIFF_FILE_VALID((p)->two))
-#define DIFF_PAIR_RENAME(p) (strcmp((p)->one->path, (p)->two->path))
+#define DIFF_PAIR_RENAME(p) ((p)->renamed_pair)
#define DIFF_PAIR_BROKEN(p) \
( (!DIFF_FILE_VALID((p)->one) != !DIFF_FILE_VALID((p)->two)) && \
diff --git a/fetch-clone.c b/fetch-clone.c
index 81d1371296..5e84c4620f 100644
--- a/fetch-clone.c
+++ b/fetch-clone.c
@@ -129,10 +129,12 @@ static pid_t setup_sideband(int sideband, const char *me, int fd[2], int xd[2])
len--;
switch (buf[0] & 0xFF) {
case 3:
+ safe_write(2, "remote: ", 8);
safe_write(2, buf+1, len);
- fprintf(stderr, "\n");
+ safe_write(2, "\n", 1);
exit(1);
case 2:
+ safe_write(2, "remote: ", 8);
safe_write(2, buf+1, len);
continue;
case 1:
diff --git a/git-annotate.perl b/git-annotate.perl
index 6db2f48241..215ed26f3a 100755
--- a/git-annotate.perl
+++ b/git-annotate.perl
@@ -147,7 +147,7 @@ sub init_claim {
sub handle_rev {
- my $i = 0;
+ my $revseen = 0;
my %seen;
while (my $rev = shift @revqueue) {
next if $seen{$rev}++;
@@ -247,22 +247,129 @@ sub git_find_parent {
return $parent;
}
+sub git_find_all_parents {
+ my ($rev) = @_;
+
+ my $revparent = open_pipe("git-rev-list","--remove-empty", "--parents","--max-count=1","$rev")
+ or die "Failed to open git-rev-list to find a single parent: $!";
+
+ my $parentline = <$revparent>;
+ chomp $parentline;
+ my ($origrev, @parents) = split m/\s+/, $parentline;
+
+ close($revparent);
+
+ return @parents;
+}
+
+sub git_merge_base {
+ my ($rev1, $rev2) = @_;
+
+ my $mb = open_pipe("git-merge-base", $rev1, $rev2)
+ or die "Failed to open git-merge-base: $!";
+
+ my $base = <$mb>;
+ chomp $base;
+
+ close($mb);
+
+ return $base;
+}
+
+# Construct a set of pseudo parents that are in the same order,
+# and the same quantity as the real parents,
+# but whose SHA1s are as similar to the logical parents
+# as possible.
+sub get_pseudo_parents {
+ my ($all, $fake) = @_;
+
+ my @all = @$all;
+ my @fake = @$fake;
+
+ my @pseudo;
+
+ my %fake = map {$_ => 1} @fake;
+ my %seenfake;
+
+ my $fakeidx = 0;
+ foreach my $p (@all) {
+ if (exists $fake{$p}) {
+ if ($fake[$fakeidx] ne $p) {
+ die sprintf("parent mismatch: %s != %s\nall:%s\nfake:%s\n",
+ $fake[$fakeidx], $p,
+ join(", ", @all),
+ join(", ", @fake),
+ );
+ }
+
+ push @pseudo, $p;
+ $fakeidx++;
+ $seenfake{$p}++;
+
+ } else {
+ my $base = git_merge_base($fake[$fakeidx], $p);
+ if ($base ne $fake[$fakeidx]) {
+ die sprintf("Result of merge-base doesn't match fake: %s,%s != %s\n",
+ $fake[$fakeidx], $p, $base);
+ }
+
+ # The details of how we parse the diffs
+ # mean that we cannot have a duplicate
+ # revision in the list, so if we've already
+ # seen the revision we would normally add, just use
+ # the actual revision.
+ if ($seenfake{$base}) {
+ push @pseudo, $p;
+ } else {
+ push @pseudo, $base;
+ $seenfake{$base}++;
+ }
+ }
+ }
+
+ return @pseudo;
+}
+
# Get a diff between the current revision and a parent.
# Record the commit information that results.
sub git_diff_parse {
my ($parents, $rev, %revinfo) = @_;
+ my @pseudo_parents;
+ my @command = ("git-diff-tree");
+ my $revision_spec;
+
+ if (scalar @$parents == 1) {
+
+ $revision_spec = join("..", $parents->[0], $rev);
+ @pseudo_parents = @$parents;
+ } else {
+ my @all_parents = git_find_all_parents($rev);
+
+ if (@all_parents != @$parents) {
+ @pseudo_parents = get_pseudo_parents(\@all_parents, $parents);
+ } else {
+ @pseudo_parents = @$parents;
+ }
+
+ $revision_spec = $rev;
+ push @command, "-c";
+ }
+
my @filenames = ( $revs{$rev}{'filename'} );
+
foreach my $parent (@$parents) {
push @filenames, $revs{$parent}{'filename'};
}
- my $diff = open_pipe("git-diff-tree","-M","-p","-c",$rev,"--",
- @filenames )
+ push @command, "-p", "-M", $revision_spec, "--", @filenames;
+
+
+ my $diff = open_pipe( @command )
or die "Failed to call git-diff for annotation: $!";
- _git_diff_parse($diff, $parents, $rev, %revinfo);
+ _git_diff_parse($diff, \@pseudo_parents, $rev, %revinfo);
close($diff);
}
@@ -283,6 +390,7 @@ sub _git_diff_parse {
$diff_header_regexp .= "@" x @$parents;
$diff_header_regexp .= ' -\d+,\d+' x @$parents;
$diff_header_regexp .= ' \+(\d+),\d+';
+ $diff_header_regexp .= " " . ("@" x @$parents);
my %claim_regexps;
my $allparentplus = '^' . '\\+' x @$parents . '(.*)$';
@@ -311,13 +419,13 @@ sub _git_diff_parse {
DIFF:
while(<$diff>) {
chomp;
+ #printf("%d:%s:\n", $gotheader, $_);
if (m/$diff_header_regexp/) {
$remstart = $1 - 1;
# (0-based arrays)
$gotheader = 1;
- printf("Copying from %d to %d\n", $ri, $remstart);
foreach my $parent (@$parents) {
for (my $i = $ri; $i < $remstart; $i++) {
$plines{$parent}[$pi{$parent}++] = $slines->[$i];
@@ -392,10 +500,17 @@ sub _git_diff_parse {
printf("parent %s is on line %d\n", $parent, $pi{$parent});
}
+ my @context;
+ for (my $i = -2; $i < 2; $i++) {
+ push @context, get_line($slines, $ri + $i);
+ }
+ my $context = join("\n", @context);
+
+ my $justline = substr($_, scalar @$parents);
die sprintf("Line %d, does not match:\n|%s|\n|%s|\n%s\n",
$ri,
- substr($_,scalar @$parents),
- get_line($slines,$ri), $rev);
+ $justline,
+ $context);
}
foreach my $parent (@$parents) {
$plines{$parent}[$pi{$parent}++] = $slines->[$ri];
diff --git a/git-clone.sh b/git-clone.sh
index acc7a51b97..7060bdab01 100755
--- a/git-clone.sh
+++ b/git-clone.sh
@@ -298,7 +298,7 @@ yes,yes)
fi
git-ls-remote "$repo" >"$GIT_DIR/CLONE_HEAD" || exit 1
;;
- http://*)
+ https://*|http://*)
if test -z "@@NO_CURL@@"
then
clone_dumb_http "$repo" "$D"
diff --git a/git-compat-util.h b/git-compat-util.h
index 93f558056d..b2e18954c0 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -91,6 +91,9 @@ static inline void *xmalloc(size_t size)
ret = malloc(1);
if (!ret)
die("Out of memory, malloc failed");
+#ifdef XMALLOC_POISON
+ memset(ret, 0xA5, size);
+#endif
return ret;
}
@@ -136,6 +139,13 @@ static inline ssize_t xwrite(int fd, const void *buf, size_t len)
}
}
+static inline int has_extension(const char *filename, const char *ext)
+{
+ size_t len = strlen(filename);
+ size_t extlen = strlen(ext);
+ return len > extlen && !memcmp(filename + len - extlen, ext, extlen);
+}
+
/* Sane ctype - no locale, and works with signed chars */
#undef isspace
#undef isdigit
diff --git a/git-push.sh b/git-push.sh
deleted file mode 100755
index 21775fc21a..0000000000
--- a/git-push.sh
+++ /dev/null
@@ -1,87 +0,0 @@
-#!/bin/sh
-
-USAGE='[--all] [--tags] [--force] <repository> [<refspec>...]'
-. git-sh-setup
-
-# Parse out parameters and then stop at remote, so that we can
-# translate it using .git/branches information
-has_all=
-has_force=
-has_exec=
-has_thin=--thin
-remote=
-do_tags=
-
-while case "$#" in 0) break ;; esac
-do
- case "$1" in
- --all)
- has_all=--all ;;
- --tags)
- do_tags=yes ;;
- --force)
- has_force=--force ;;
- --exec=*)
- has_exec="$1" ;;
- --thin)
- ;; # noop
- --no-thin)
- has_thin= ;;
- -*)
- usage ;;
- *)
- set x "$@"
- shift
- break ;;
- esac
- shift
-done
-case "$#" in
-0)
- echo "Where would you want to push today?"
- usage ;;
-esac
-
-. git-parse-remote
-remote=$(get_remote_url "$@")
-
-case "$has_all" in
---all)
- set x ;;
-'')
- case "$do_tags,$#" in
- yes,1)
- set x $(cd "$GIT_DIR/refs" && find tags -type f -print) ;;
- yes,*)
- set x $(cd "$GIT_DIR/refs" && find tags -type f -print) \
- $(get_remote_refs_for_push "$@") ;;
- ,*)
- set x $(get_remote_refs_for_push "$@") ;;
- esac
-esac
-
-shift ;# away the initial 'x'
-
-# $# is now 0 if there was no explicit refspec on the command line
-# and there was no default refspec to push from remotes/ file.
-# we will let git-send-pack to do its "matching refs" thing.
-
-case "$remote" in
-git://*)
- die "Cannot use READ-ONLY transport to push to $remote" ;;
-rsync://*)
- die "Pushing with rsync transport is deprecated" ;;
-esac
-
-set x "$remote" "$@"; shift
-test "$has_all" && set x "$has_all" "$@" && shift
-test "$has_force" && set x "$has_force" "$@" && shift
-test "$has_exec" && set x "$has_exec" "$@" && shift
-test "$has_thin" && set x "$has_thin" "$@" && shift
-
-case "$remote" in
-http://* | https://*)
- exec git-http-push "$@";;
-*)
- exec git-send-pack "$@";;
-esac
diff --git a/git-sh-setup.sh b/git-sh-setup.sh
index d15747f1ed..42f9b1c125 100755
--- a/git-sh-setup.sh
+++ b/git-sh-setup.sh
@@ -35,17 +35,12 @@ case "$1" in
exit
esac
+# Make sure we are in a valid repository of a vintage we understand.
if [ -z "$SUBDIRECTORY_OK" ]
then
: ${GIT_DIR=.git}
- : ${GIT_OBJECT_DIRECTORY="$GIT_DIR/objects"}
-
- # Make sure we are in a valid repository of a vintage we understand.
- GIT_DIR="$GIT_DIR" git repo-config --get core.nosuch >/dev/null
- if test $? = 128
- then
- exit
- fi
+ GIT_DIR=$(GIT_DIR="$GIT_DIR" git-rev-parse --git-dir) || exit
else
GIT_DIR=$(git-rev-parse --git-dir) || exit
fi
+: ${GIT_OBJECT_DIRECTORY="$GIT_DIR/objects"}
diff --git a/git-svn.perl b/git-svn.perl
index 6453771f9c..0d58bb9b37 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -31,6 +31,7 @@ use File::Basename qw/dirname basename/;
use File::Path qw/mkpath/;
use Getopt::Long qw/:config gnu_getopt no_ignore_case auto_abbrev pass_through/;
use File::Spec qw//;
+use File::Copy qw/copy/;
use POSIX qw/strftime/;
use IPC::Open3;
use Memoize;
@@ -77,9 +78,6 @@ my %cmt_opts = ( 'edit|e' => \$_edit,
'copy-similarity|C=i'=> \$_cp_similarity
);
-# yes, 'native' sets "\n". Patches to fix this for non-*nix systems welcome:
-my %EOL = ( CR => "\015", LF => "\012", CRLF => "\015\012", native => "\012" );
-
my %cmd = (
fetch => [ \&fetch, "Download new revisions from SVN",
{ 'revision|r=s' => \$_revision, %fc_opts } ],
@@ -1160,27 +1158,24 @@ sub repo_path_split {
}
}
- my ($url, $path) = ($full_url =~ m!^([a-z\+]+://[^/]*)(.*)$!i);
- $path =~ s#^/+##;
- my @paths = split(m#/+#, $path);
-
if ($_use_lib) {
- while (1) {
- $SVN = libsvn_connect($url);
- last if (defined $SVN &&
- defined eval { $SVN->get_latest_revnum });
- my $n = shift @paths || last;
- $url .= "/$n";
- }
+ my $tmp = libsvn_connect($full_url);
+ my $url = $tmp->get_repos_root;
+ $full_url =~ s#^\Q$url\E/*##;
+ push @repo_path_split_cache, qr/^(\Q$url\E)/;
+ return ($url, $full_url);
} else {
+ my ($url, $path) = ($full_url =~ m!^([a-z\+]+://[^/]*)(.*)$!i);
+ $path =~ s#^/+##;
+ my @paths = split(m#/+#, $path);
while (quiet_run(qw/svn ls --non-interactive/, $url)) {
my $n = shift @paths || last;
$url .= "/$n";
}
+ push @repo_path_split_cache, qr/^(\Q$url\E)/;
+ $path = join('/',@paths);
+ return ($url, $path);
}
- push @repo_path_split_cache, qr/^(\Q$url\E)/;
- $path = join('/',@paths);
- return ($url, $path);
}
sub setup_git_svn {
@@ -1760,43 +1755,6 @@ sub svn_info {
sub sys { system(@_) == 0 or croak $? }
-sub eol_cp {
- my ($from, $to) = @_;
- my $es = svn_propget_base('svn:eol-style', $to);
- open my $rfd, '<', $from or croak $!;
- binmode $rfd or croak $!;
- open my $wfd, '>', $to or croak $!;
- binmode $wfd or croak $!;
- eol_cp_fd($rfd, $wfd, $es);
- close $rfd or croak $!;
- close $wfd or croak $!;
-}
-
-sub eol_cp_fd {
- my ($rfd, $wfd, $es) = @_;
- my $eol = defined $es ? $EOL{$es} : undef;
- my $buf;
- use bytes;
- while (1) {
- my ($r, $w, $t);
- defined($r = sysread($rfd, $buf, 4096)) or croak $!;
- return unless $r;
- if ($eol) {
- if ($buf =~ /\015$/) {
- my $c;
- defined($r = sysread($rfd,$c,1)) or croak $!;
- $buf .= $c if $r > 0;
- }
- $buf =~ s/(?:\015\012|\015|\012)/$eol/gs;
- $r = length($buf);
- }
- for ($w = 0; $w < $r; $w += $t) {
- $t = syswrite($wfd, $buf, $r - $w, $w) or croak $!;
- }
- }
- no bytes;
-}
-
sub do_update_index {
my ($z_cmd, $cmd, $no_text_base) = @_;
@@ -1824,9 +1782,11 @@ sub do_update_index {
'text-base',"$f.svn-base");
$tb =~ s#^/##;
}
+ my @s = stat($x);
unlink $x or croak $!;
- eol_cp($tb, $x);
+ copy($tb, $x);
chmod(($mode &~ umask), $x) or croak $!;
+ utime $s[8], $s[9], $x;
}
print $ui $x,"\0";
}
@@ -2617,7 +2577,9 @@ sub libsvn_connect {
sub libsvn_get_file {
my ($gui, $f, $rev) = @_;
my $p = $f;
- return unless ($p =~ s#^\Q$SVN_PATH\E/##);
+ if (length $SVN_PATH > 0) {
+ return unless ($p =~ s#^\Q$SVN_PATH\E/##);
+ }
my ($hash, $pid, $in, $out);
my $pool = SVN::Pool->new;
@@ -2664,6 +2626,7 @@ sub libsvn_log_entry {
if (defined $_authors && ! defined $users{$author}) {
die "Author: $author not defined in $_authors file\n";
}
+ $msg = '' if ($rev == 0 && !defined $msg);
return { revision => $rev, date => "+0000 $Y-$m-$d $H:$M:$S",
author => $author, msg => $msg."\n", parents => $parents || [] }
}
diff --git a/git.c b/git.c
index 110e82e9ac..18ba14ade1 100644
--- a/git.c
+++ b/git.c
@@ -229,7 +229,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
{ "log", cmd_log, NEEDS_PREFIX | USE_PAGER },
{ "whatchanged", cmd_whatchanged, NEEDS_PREFIX | USE_PAGER },
{ "show", cmd_show, NEEDS_PREFIX | USE_PAGER },
- { "push", cmd_push },
+ { "push", cmd_push, NEEDS_PREFIX },
{ "format-patch", cmd_format_patch, NEEDS_PREFIX },
{ "count-objects", cmd_count_objects },
{ "diff", cmd_diff, NEEDS_PREFIX },
@@ -263,6 +263,8 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
{ "fmt-merge-msg", cmd_fmt_merge_msg, NEEDS_PREFIX },
{ "prune", cmd_prune, NEEDS_PREFIX },
{ "mv", cmd_mv, NEEDS_PREFIX },
+ { "prune-packed", cmd_prune_packed, NEEDS_PREFIX },
+ { "repo-config", cmd_repo_config },
};
int i;
diff --git a/gitk b/gitk
index ba4644f450..5acaadf495 100755
--- a/gitk
+++ b/gitk
@@ -4901,7 +4901,7 @@ proc domktag {} {
proc redrawtags {id} {
global canv linehtag commitrow idpos selectedline curview
- global mainfont
+ global mainfont canvxmax
if {![info exists commitrow($curview,$id)]} return
drawcmitrow $commitrow($curview,$id)
diff --git a/hash-object.c b/hash-object.c
index 43bd93bffb..5f89e64c13 100644
--- a/hash-object.c
+++ b/hash-object.c
@@ -46,7 +46,7 @@ int main(int argc, char **argv)
if (!no_more_flags && argv[i][0] == '-') {
if (!strcmp(argv[i], "-t")) {
if (argc <= ++i)
- die(hash_object_usage);
+ usage(hash_object_usage);
type = argv[i];
}
else if (!strcmp(argv[i], "-w")) {
@@ -66,8 +66,8 @@ int main(int argc, char **argv)
hash_stdin(type, write_object);
}
else
- die(hash_object_usage);
- }
+ usage(hash_object_usage);
+ }
else {
const char *arg = argv[i];
if (0 <= prefix_length)
diff --git a/http-fetch.c b/http-fetch.c
index 1aad39b4d8..de5fc44e66 100644
--- a/http-fetch.c
+++ b/http-fetch.c
@@ -870,7 +870,7 @@ static void process_ls_pack(struct remote_ls_ctx *ls)
if (strlen(ls->dentry_name) == 63 &&
!strncmp(ls->dentry_name, "objects/pack/pack-", 18) &&
- !strncmp(ls->dentry_name+58, ".pack", 5)) {
+ has_extension(ls->dentry_name, ".pack")) {
get_sha1_hex(ls->dentry_name + 18, sha1);
setup_index(ls->repo, sha1);
}
@@ -1226,6 +1226,7 @@ int main(int argc, const char **argv)
int arg = 1;
int rc = 0;
+ setup_ident();
setup_git_directory();
git_config(git_default_config);
diff --git a/http-push.c b/http-push.c
index 4021e7d927..d45733ef64 100644
--- a/http-push.c
+++ b/http-push.c
@@ -530,7 +530,7 @@ static void start_put(struct transfer_request *request)
request->dest = xmalloc(strlen(request->url) + 14);
sprintf(request->dest, "Destination: %s", request->url);
posn += 38;
- *(posn++) = '.';
+ *(posn++) = '_';
strcpy(posn, request->lock->token);
slot = get_active_slot();
diff --git a/index-pack.c b/index-pack.c
index b39953dc69..b20659c259 100644
--- a/index-pack.c
+++ b/index-pack.c
@@ -447,7 +447,7 @@ int main(int argc, char **argv)
usage(index_pack_usage);
if (!index_name) {
int len = strlen(pack_name);
- if (len < 5 || strcmp(pack_name + len - 5, ".pack"))
+ if (!has_extension(pack_name, ".pack"))
die("packfile name '%s' does not end with '.pack'",
pack_name);
index_name_buf = xmalloc(len);
diff --git a/local-fetch.c b/local-fetch.c
index b216bdd557..7d01845d39 100644
--- a/local-fetch.c
+++ b/local-fetch.c
@@ -43,8 +43,8 @@ static int setup_indices(void)
return -1;
while ((de = readdir(dir)) != NULL) {
int namelen = strlen(de->d_name);
- if (namelen != 50 ||
- strcmp(de->d_name + namelen - 5, ".pack"))
+ if (namelen != 50 ||
+ !has_extension(de->d_name, ".pack"))
continue;
get_sha1_hex(de->d_name + 5, sha1);
setup_index(sha1);
@@ -210,6 +210,7 @@ int main(int argc, const char **argv)
char **commit_id;
int arg = 1;
+ setup_ident();
setup_git_directory();
git_config(git_default_config);
diff --git a/log-tree.c b/log-tree.c
index b67b8dd17a..05ede0c175 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -59,7 +59,7 @@ void show_log(struct rev_info *opt, const char *sep)
fputs(diff_unique_abbrev(commit->object.sha1, abbrev_commit), stdout);
if (opt->parents)
show_parents(commit, abbrev_commit);
- putchar('\n');
+ putchar(opt->diffopt.line_termination);
return;
}
diff --git a/mktag.c b/mktag.c
index 09b6e437d4..be23e589fb 100644
--- a/mktag.c
+++ b/mktag.c
@@ -123,7 +123,7 @@ int main(int argc, char **argv)
unsigned char result_sha1[20];
if (argc != 1)
- usage("cat <signaturefile> | git-mktag");
+ usage("git-mktag < signaturefile");
setup_git_directory();
diff --git a/mktree.c b/mktree.c
index ab63cd99d4..9a6f0d2f6b 100644
--- a/mktree.c
+++ b/mktree.c
@@ -71,7 +71,7 @@ static void write_tree(unsigned char *sha1)
write_sha1_file(buffer, offset, tree_type, sha1);
}
-static const char mktree_usage[] = "mktree [-z]";
+static const char mktree_usage[] = "git-mktree [-z]";
int main(int ac, char **av)
{
diff --git a/refs.c b/refs.c
index 02850b6908..28a9394605 100644
--- a/refs.c
+++ b/refs.c
@@ -147,7 +147,7 @@ static int do_for_each_ref(const char *base, int (*fn)(const char *path, const u
namelen = strlen(de->d_name);
if (namelen > 255)
continue;
- if (namelen>5 && !strcmp(de->d_name+namelen-5,".lock"))
+ if (has_extension(de->d_name, ".lock"))
continue;
memcpy(path + baselen, de->d_name, namelen+1);
if (stat(git_path("%s", path), &st) < 0)
diff --git a/revision.c b/revision.c
index a58257ad80..5a91d06b98 100644
--- a/revision.c
+++ b/revision.c
@@ -936,7 +936,8 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
revs->diffopt.output_format = DIFF_FORMAT_PATCH;
}
revs->diffopt.abbrev = revs->abbrev;
- diff_setup_done(&revs->diffopt);
+ if (diff_setup_done(&revs->diffopt) < 0)
+ die("diff_setup_done failed");
return left;
}
diff --git a/setup.c b/setup.c
index 358e139d84..2afdba414a 100644
--- a/setup.c
+++ b/setup.c
@@ -184,7 +184,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
}
return NULL;
bad_dir_environ:
- if (!nongit_ok) {
+ if (nongit_ok) {
*nongit_ok = 1;
return NULL;
}
diff --git a/sha1_file.c b/sha1_file.c
index 43bc2ea0cf..3db956dd5c 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -590,7 +590,7 @@ static void prepare_packed_git_one(char *objdir, int local)
int namelen = strlen(de->d_name);
struct packed_git *p;
- if (strcmp(de->d_name + namelen - 4, ".idx"))
+ if (!has_extension(de->d_name, ".idx"))
continue;
/* we have .idx. Is it a file we can map? */
diff --git a/sha1_name.c b/sha1_name.c
index 5fe8e5d4bf..c5a05faeb6 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -193,7 +193,7 @@ const char *find_unique_abbrev(const unsigned char *sha1, int len)
is_null = !memcmp(sha1, null_sha1, 20);
memcpy(hex, sha1_to_hex(sha1), 40);
- if (len == 40)
+ if (len == 40 || !len)
return hex;
while (len < 40) {
unsigned char sha1_ret[20];
diff --git a/ssh-fetch.c b/ssh-fetch.c
index 6e16568f88..c7d8fa80e4 100644
--- a/ssh-fetch.c
+++ b/ssh-fetch.c
@@ -132,6 +132,7 @@ int main(int argc, char **argv)
prog = getenv("GIT_SSH_PUSH");
if (!prog) prog = "git-ssh-upload";
+ setup_ident();
setup_git_directory();
git_config(git_default_config);
diff --git a/t/t1003-read-tree-prefix.sh b/t/t1003-read-tree-prefix.sh
new file mode 100755
index 0000000000..48ab117d75
--- /dev/null
+++ b/t/t1003-read-tree-prefix.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 Junio C Hamano
+#
+
+test_description='git-read-tree --prefix test.
+'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ echo hello >one &&
+ git-update-index --add one &&
+ tree=`git-write-tree` &&
+ echo tree is $tree
+'
+
+echo 'one
+two/one' >expect
+
+test_expect_success 'read-tree --prefix' '
+ git-read-tree --prefix=two/ $tree &&
+ git-ls-files >actual &&
+ cmp expect actual
+'
+
+test_done
diff --git a/t/t1020-subdirectory.sh b/t/t1020-subdirectory.sh
new file mode 100755
index 0000000000..4409b87f8d
--- /dev/null
+++ b/t/t1020-subdirectory.sh
@@ -0,0 +1,109 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 Junio C Hamano
+#
+
+test_description='Try various core-level commands in subdirectory.
+'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ long="a b c d e f g h i j k l m n o p q r s t u v w x y z" &&
+ for c in $long; do echo $c; done >one &&
+ mkdir dir &&
+ for c in x y z $long a b c; do echo $c; done >dir/two &&
+ cp one original.one &&
+ cp dir/two original.two
+'
+HERE=`pwd`
+LF='
+'
+
+test_expect_success 'update-index and ls-files' '
+ cd $HERE &&
+ git-update-index --add one &&
+ case "`git-ls-files`" in
+ one) echo ok one ;;
+ *) echo bad one; exit 1 ;;
+ esac &&
+ cd dir &&
+ git-update-index --add two &&
+ case "`git-ls-files`" in
+ two) echo ok two ;;
+ *) echo bad two; exit 1 ;;
+ esac &&
+ cd .. &&
+ case "`git-ls-files`" in
+ dir/two"$LF"one) echo ok both ;;
+ *) echo bad; exit 1 ;;
+ esac
+'
+
+test_expect_success 'cat-file' '
+ cd $HERE &&
+ two=`git-ls-files -s dir/two` &&
+ two=`expr "$two" : "[0-7]* \\([0-9a-f]*\\)"` &&
+ echo "$two" &&
+ git-cat-file -p "$two" >actual &&
+ cmp dir/two actual &&
+ cd dir &&
+ git-cat-file -p "$two" >actual &&
+ cmp two actual
+'
+rm -f actual dir/actual
+
+test_expect_success 'diff-files' '
+ cd $HERE &&
+ echo a >>one &&
+ echo d >>dir/two &&
+ case "`git-diff-files --name-only`" in
+ dir/two"$LF"one) echo ok top ;;
+ *) echo bad top; exit 1 ;;
+ esac &&
+ # diff should not omit leading paths
+ cd dir &&
+ case "`git-diff-files --name-only`" in
+ dir/two"$LF"one) echo ok subdir ;;
+ *) echo bad subdir; exit 1 ;;
+ esac &&
+ case "`git-diff-files --name-only .`" in
+ dir/two) echo ok subdir limited ;;
+ *) echo bad subdir limited; exit 1 ;;
+ esac
+'
+
+test_expect_success 'write-tree' '
+ cd $HERE &&
+ top=`git-write-tree` &&
+ echo $top &&
+ cd dir &&
+ sub=`git-write-tree` &&
+ echo $sub &&
+ test "z$top" = "z$sub"
+'
+
+test_expect_success 'checkout-index' '
+ cd $HERE &&
+ git-checkout-index -f -u one &&
+ cmp one original.one &&
+ cd dir &&
+ git-checkout-index -f -u two &&
+ cmp two ../original.two
+'
+
+test_expect_success 'read-tree' '
+ cd $HERE &&
+ rm -f one dir/two &&
+ tree=`git-write-tree` &&
+ git-read-tree --reset -u "$tree" &&
+ cmp one original.one &&
+ cmp dir/two original.two &&
+ cd dir &&
+ rm -f two &&
+ git-read-tree --reset -u "$tree" &&
+ cmp two ../original.two &&
+ cmp ../one ../original.one
+'
+
+test_done
diff --git a/t/t4115-apply-symlink.sh b/t/t4115-apply-symlink.sh
new file mode 100755
index 0000000000..d5f2cfb186
--- /dev/null
+++ b/t/t4115-apply-symlink.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+#
+# Copyright (c) 2005 Junio C Hamano
+#
+
+test_description='git-apply symlinks and partial files
+
+'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+
+ ln -s path1/path2/path3/path4/path5 link1 &&
+ git add link? &&
+ git commit -m initial &&
+
+ git branch side &&
+
+ rm -f link? &&
+
+ ln -s htap6 link1 &&
+ git update-index link? &&
+ git commit -m second &&
+
+ git diff-tree -p HEAD^ HEAD >patch &&
+ git apply --stat --summary patch
+
+'
+
+test_expect_success 'apply symlink patch' '
+
+ git checkout side &&
+ git apply patch &&
+ git diff-files -p >patched &&
+ diff -u patch patched
+
+'
+
+test_expect_success 'apply --index symlink patch' '
+
+ git checkout -f side &&
+ git apply --index patch &&
+ git diff-index --cached -p HEAD >patched &&
+ diff -u patch patched
+
+'
+
+test_done
diff --git a/t/t7002-grep.sh b/t/t7002-grep.sh
new file mode 100755
index 0000000000..00a7d762ce
--- /dev/null
+++ b/t/t7002-grep.sh
@@ -0,0 +1,85 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 Junio C Hamano
+#
+
+test_description='git grep -w
+'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ {
+ echo foo mmap bar
+ echo foo_mmap bar
+ echo foo_mmap bar mmap
+ echo foo mmap bar_mmap
+ echo foo_mmap bar mmap baz
+ } >file &&
+ echo x x xx x >x &&
+ echo y yy >y &&
+ echo zzz > z &&
+ git add file x y z &&
+ git commit -m initial
+'
+
+for H in HEAD ''
+do
+ case "$H" in
+ HEAD) HC='HEAD:' L='HEAD' ;;
+ '') HC= L='in working tree' ;;
+ esac
+
+ test_expect_success "grep -w $L" '
+ {
+ echo ${HC}file:1:foo mmap bar
+ echo ${HC}file:3:foo_mmap bar mmap
+ echo ${HC}file:4:foo mmap bar_mmap
+ echo ${HC}file:5:foo_mmap bar mmap baz
+ } >expected &&
+ git grep -n -w -e mmap $H >actual &&
+ diff expected actual
+ '
+
+ test_expect_success "grep -w $L (x)" '
+ {
+ echo ${HC}x:1:x x xx x
+ } >expected &&
+ git grep -n -w -e "x xx* x" $H >actual &&
+ diff expected actual
+ '
+
+ test_expect_success "grep -w $L (y-1)" '
+ {
+ echo ${HC}y:1:y yy
+ } >expected &&
+ git grep -n -w -e "^y" $H >actual &&
+ diff expected actual
+ '
+
+ test_expect_success "grep -w $L (y-2)" '
+ : >expected &&
+ if git grep -n -w -e "^y y" $H >actual
+ then
+ echo should not have matched
+ cat actual
+ false
+ else
+ diff expected actual
+ fi
+ '
+
+ test_expect_success "grep -w $L (z)" '
+ : >expected &&
+ if git grep -n -w -e "^z" $H >actual
+ then
+ echo should not have matched
+ cat actual
+ false
+ else
+ diff expected actual
+ fi
+ '
+done
+
+test_done
diff --git a/verify-pack.c b/verify-pack.c
index c99db9dd79..357970da39 100644
--- a/verify-pack.c
+++ b/verify-pack.c
@@ -1,43 +1,60 @@
#include "cache.h"
#include "pack.h"
-static int verify_one_pack(char *arg, int verbose)
+static int verify_one_pack(const char *path, int verbose)
{
- int len = strlen(arg);
- struct packed_git *g;
-
- while (1) {
- /* Should name foo.idx, but foo.pack may be named;
- * convert it to foo.idx
- */
- if (!strcmp(arg + len - 5, ".pack")) {
- strcpy(arg + len - 5, ".idx");
- len--;
- }
- /* Should name foo.idx now */
- if ((g = add_packed_git(arg, len, 1)))
- break;
- /* No? did you name just foo? */
+ char arg[PATH_MAX];
+ int len;
+ struct packed_git *pack;
+ int err;
+
+ len = strlcpy(arg, path, PATH_MAX);
+ if (len >= PATH_MAX)
+ return error("name too long: %s", path);
+
+ /*
+ * In addition to "foo.idx" we accept "foo.pack" and "foo";
+ * normalize these forms to "foo.idx" for add_packed_git().
+ */
+ if (has_extension(arg, ".pack")) {
+ strcpy(arg + len - 5, ".idx");
+ len--;
+ } else if (!has_extension(arg, ".idx")) {
+ if (len + 4 >= PATH_MAX)
+ return error("name too long: %s.idx", arg);
strcpy(arg + len, ".idx");
len += 4;
- if ((g = add_packed_git(arg, len, 1)))
- break;
- return error("packfile %s not found.", arg);
}
- return verify_pack(g, verbose);
+
+ /*
+ * add_packed_git() uses our buffer (containing "foo.idx") to
+ * build the pack filename ("foo.pack"). Make sure it fits.
+ */
+ if (len + 1 >= PATH_MAX) {
+ arg[len - 4] = '\0';
+ return error("name too long: %s.pack", arg);
+ }
+
+ pack = add_packed_git(arg, len, 1);
+ if (!pack)
+ return error("packfile %s not found.", arg);
+
+ err = verify_pack(pack, verbose);
+ free(pack);
+
+ return err;
}
static const char verify_pack_usage[] = "git-verify-pack [-v] <pack>...";
int main(int ac, char **av)
{
- int errs = 0;
+ int err = 0;
int verbose = 0;
int no_more_options = 0;
+ int nothing_done = 1;
while (1 < ac) {
- char path[PATH_MAX];
-
if (!no_more_options && av[1][0] == '-') {
if (!strcmp("-v", av[1]))
verbose = 1;
@@ -47,11 +64,15 @@ int main(int ac, char **av)
usage(verify_pack_usage);
}
else {
- strcpy(path, av[1]);
- if (verify_one_pack(path, verbose))
- errs++;
+ if (verify_one_pack(av[1], verbose))
+ err = 1;
+ nothing_done = 0;
}
ac--; av++;
}
- return !!errs;
+
+ if (nothing_done)
+ usage(verify_pack_usage);
+
+ return err;
}