aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Documentation/RelNotes-1.5.0.1.txt42
-rw-r--r--Documentation/RelNotes-1.5.0.txt43
-rw-r--r--Documentation/RelNotes-1.5.1.txt44
-rwxr-xr-xDocumentation/cmd-list.perl3
-rw-r--r--Documentation/config.txt20
-rw-r--r--Documentation/core-intro.txt6
-rw-r--r--Documentation/core-tutorial.txt8
-rw-r--r--Documentation/diff-options.txt3
-rw-r--r--Documentation/diffcore.txt7
-rw-r--r--Documentation/git-checkout.txt7
-rw-r--r--Documentation/git-clone.txt4
-rw-r--r--Documentation/git-cvsexportcommit.txt7
-rw-r--r--Documentation/git-diff-stages.txt42
-rw-r--r--Documentation/git-fast-import.txt2
-rw-r--r--Documentation/git-merge.txt2
-rw-r--r--Documentation/git-name-rev.txt6
-rw-r--r--Documentation/git-rebase.txt24
-rw-r--r--Documentation/git-remote.txt13
-rw-r--r--Documentation/git-rerere.txt3
-rw-r--r--Documentation/git-reset.txt4
-rw-r--r--Documentation/git-resolve.txt38
-rw-r--r--Documentation/git-rev-list.txt5
-rw-r--r--Documentation/git-runstatus.txt2
-rw-r--r--Documentation/git-status.txt2
-rw-r--r--Documentation/git.txt8
-rw-r--r--Documentation/howto/revert-branch-rebase.txt9
-rw-r--r--Documentation/i18n.txt12
-rw-r--r--Documentation/tutorial-2.txt4
-rw-r--r--Documentation/user-manual.txt2
-rwxr-xr-xGIT-VERSION-GEN21
-rw-r--r--Makefile28
l---------RelNotes2
-rw-r--r--builtin-apply.c47
-rw-r--r--builtin-archive.c10
-rw-r--r--builtin-blame.c14
-rw-r--r--builtin-branch.c14
-rw-r--r--builtin-checkout-index.c4
-rw-r--r--builtin-describe.c6
-rw-r--r--builtin-diff-stages.c107
-rw-r--r--builtin-diff.c3
-rw-r--r--builtin-fmt-merge-msg.c10
-rw-r--r--builtin-for-each-ref.c6
-rw-r--r--builtin-fsck.c2
-rw-r--r--builtin-grep.c6
-rw-r--r--builtin-init-db.c4
-rw-r--r--builtin-log.c12
-rw-r--r--builtin-ls-files.c8
-rw-r--r--builtin-ls-tree.c2
-rw-r--r--builtin-mailinfo.c2
-rw-r--r--builtin-merge-base.c (renamed from merge-base.c)12
-rw-r--r--builtin-name-rev.c50
-rw-r--r--builtin-pack-objects.c6
-rw-r--r--builtin-pack-refs.c2
-rw-r--r--builtin-push.c18
-rw-r--r--builtin-read-tree.c4
-rw-r--r--builtin-reflog.c8
-rw-r--r--builtin-rerere.c6
-rw-r--r--builtin-rev-list.c1
-rw-r--r--builtin-rev-parse.c12
-rw-r--r--builtin-shortlog.c6
-rw-r--r--builtin-show-branch.c24
-rw-r--r--builtin-show-ref.c12
-rw-r--r--builtin-tar-tree.c2
-rw-r--r--builtin-unpack-objects.c2
-rw-r--r--builtin-update-index.c13
-rw-r--r--builtin-write-tree.c2
-rw-r--r--builtin.h2
-rw-r--r--cache.h15
-rw-r--r--commit.c9
-rw-r--r--commit.h2
-rw-r--r--compat/strtoumax.c10
-rw-r--r--config.c21
-rw-r--r--configure.ac31
-rw-r--r--connect.c6
-rwxr-xr-xcontrib/completion/git-completion.bash2
-rwxr-xr-xcontrib/examples/git-resolve.sh (renamed from git-resolve.sh)0
-rwxr-xr-xcontrib/fast-import/import-tars.perl9
-rw-r--r--convert.c186
-rw-r--r--daemon.c42
-rw-r--r--diff-lib.c4
-rw-r--r--diff.c159
-rw-r--r--entry.c16
-rw-r--r--environment.c1
-rw-r--r--exec_cmd.c2
-rw-r--r--fast-import.c76
-rw-r--r--fetch-pack.c12
-rwxr-xr-xgit-commit.sh4
-rw-r--r--git-compat-util.h15
-rwxr-xr-xgit-cvsexportcommit.perl27
-rwxr-xr-xgit-cvsserver.perl15
-rwxr-xr-xgit-fetch.sh9
-rw-r--r--git-gui/.gitignore1
-rwxr-xr-xgit-gui/CREDITS-GEN58
-rwxr-xr-xgit-gui/GIT-VERSION-GEN17
-rw-r--r--git-gui/Makefile23
-rw-r--r--git-gui/TODO44
-rwxr-xr-xgit-gui/git-gui.sh285
-rwxr-xr-xgit-merge.sh15
-rwxr-xr-xgit-remote.perl37
-rw-r--r--git.c14
-rw-r--r--help.c4
-rw-r--r--http-fetch.c4
-rw-r--r--http-push.c10
-rw-r--r--imap-send.c8
-rw-r--r--index-pack.c4
-rw-r--r--peek-remote.c4
-rw-r--r--perl/Git.pm30
-rw-r--r--read-cache.c13
-rw-r--r--receive-pack.c4
-rw-r--r--refs.c8
-rw-r--r--revision.c70
-rw-r--r--revision.h3
-rw-r--r--send-pack.c4
-rw-r--r--setup.c2
-rw-r--r--sha1_file.c35
-rw-r--r--shell.c2
-rwxr-xr-xt/t0020-crlf.sh217
-rwxr-xr-xt/t1200-tutorial.sh8
-rwxr-xr-xt/t3700-add.sh20
-rwxr-xr-xt/t4016-diff-quote.sh4
-rw-r--r--templates/hooks--update7
-rw-r--r--upload-pack.c10
-rw-r--r--wt-status.c4
-rw-r--r--xdiff/xdiff.h3
-rw-r--r--xdiff/xutils.c24
126 files changed, 1760 insertions, 773 deletions
diff --git a/.gitignore b/.gitignore
index d99372afc..f15155d1b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -33,7 +33,6 @@ git-daemon
git-diff
git-diff-files
git-diff-index
-git-diff-stages
git-diff-tree
git-describe
git-fast-import
@@ -101,7 +100,6 @@ git-repo-config
git-request-pull
git-rerere
git-reset
-git-resolve
git-rev-list
git-rev-parse
git-revert
diff --git a/Documentation/RelNotes-1.5.0.1.txt b/Documentation/RelNotes-1.5.0.1.txt
new file mode 100644
index 000000000..fea3f9935
--- /dev/null
+++ b/Documentation/RelNotes-1.5.0.1.txt
@@ -0,0 +1,42 @@
+GIT v1.5.0.1 Release Notes
+==========================
+
+Fixes since v1.5.0
+------------------
+
+* Documentation updates
+
+ - Clarifications and corrections to 1.5.0 release notes.
+
+ - The main documentation did not link to git-remote documentation.
+
+ - Clarified introductory text of git-rebase documentation.
+
+ - Converted remaining mentions of update-index on Porcelain
+ documents to git-add/git-rm.
+
+ - Some i18n.* configuration variables were incorrectly
+ described as core.*; fixed.
+
+* Bugfixes
+
+ - git-add and git-update-index on a filesystem on which
+ executable bits are unreliable incorrectly reused st_mode
+ bits even when the path changed between symlink and regular
+ file.
+
+ - git-daemon marks the listening sockets with FD_CLOEXEC so
+ that it won't be leaked into the children.
+
+ - segfault from git-blame when the mandatory pathname
+ parameter was missing was fixed; usage() message is given
+ instead.
+
+ - git-rev-list did not read $GIT_DIR/config file, which means
+ that did not honor i18n.logoutputencoding correctly.
+
+* Tweaks
+
+ - sliding mmap() inefficiently mmaped the same region of a
+ packfile with an access pattern that used objects in the
+ reverse order. This has been made more efficient.
diff --git a/Documentation/RelNotes-1.5.0.txt b/Documentation/RelNotes-1.5.0.txt
index 84e7eaf3c..daf4bdb0d 100644
--- a/Documentation/RelNotes-1.5.0.txt
+++ b/Documentation/RelNotes-1.5.0.txt
@@ -25,12 +25,18 @@ Specifically, the available options are:
older clients over dumb transports (e.g. http) using older
versions of git will also be affected.
+ To let git use the new loose object format, you have to
+ set core.legacyheaders to false.
+
- Since v1.4.3, configuration repack.usedeltabaseoffset allows
packfile to be created in more space efficient format, which
cannot be read by git older than that version.
-The above two are not enabled by default and you explicitly have
-to ask for them, because these two features make repositories
+ To let git use the new format for packfiles, you have to
+ set repack.usedeltabaseoffset to true.
+
+The above two new features are not enabled by default and you
+have to explicitly ask for them, because they make repositories
unreadable by older versions of git, and in v1.5.0 we still do
not enable them by default for the same reason. We will change
this default probably 1 year after 1.4.2's release, when it is
@@ -94,8 +100,8 @@ Updates in v1.5.0 since v1.4.4 series
entries for selected paths.
- git-update-index is much less visible. Many suggestions to
- use the command in git output and documentation have now been
- replaced by simpler commands such as "git add" or "git rm".
+ use the command in git output and documentation have now been
+ replaced by simpler commands such as "git add" or "git rm".
* Repository layout and objects transfer
@@ -217,7 +223,7 @@ Updates in v1.5.0 since v1.4.4 series
"branch@{Nth}" notation.
- "git show-branch" learned showing the reflog data with the
- new -g option. "git log" has -s option to view reflog
+ new -g option. "git log" has -g option to view reflog
entries in a more verbose manner.
- git-branch knows how to rename branches and moves existing
@@ -253,9 +259,6 @@ Updates in v1.5.0 since v1.4.4 series
above sentence, as git-prune does not remove things reachable
from reflog entries.
- - 'git-prune' by default does not remove _everything_
- unreachable, as there is a one-day grace period built-in.
-
- There is a toplevel garbage collector script, 'git-gc', that
runs periodic cleanup functions, including 'git-repack -a -d',
'git-reflog expire', 'git-pack-refs --prune', and 'git-rerere
@@ -291,12 +294,10 @@ Updates in v1.5.0 since v1.4.4 series
reset" to jump to arbitrary commit, while still keeping your
HEAD detached.
- Going back to attached state (i.e. on a particular branch) by
- "git checkout $branch" can lose the current stat you arrived
- in these ways, and "git checkout" refuses when the detached
- HEAD is not pointed by any existing ref (an existing branch,
- a remote tracking branch or a tag). This safety can be
- overridden with "git checkout -f $branch".
+ Remember that a detached state is volatile, i.e. it will be forgotten
+ as soon as you move away from it with the checkout or reset command,
+ unless a branch is created from it as mentioned above. It is also
+ possible to rescue a lost detached state from the HEAD reflog.
* Packed refs
@@ -411,14 +412,14 @@ Updates in v1.5.0 since v1.4.4 series
* Foreign SCM interfaces
- - git-svn now requires the Perl SVN:: libraries, the
- command-line backend was too slow and limited.
+ - git-svn now requires the Perl SVN:: libraries, the
+ command-line backend was too slow and limited.
- - the 'commit' subcommand of git-svn has been renamed to
- 'set-tree', and 'dcommit' is the recommended replacement for
- day-to-day work.
+ - the 'commit' subcommand of git-svn has been renamed to
+ 'set-tree', and 'dcommit' is the recommended replacement for
+ day-to-day work.
- - git fast-import backend.
+ - git fast-import backend.
* User support
@@ -447,7 +448,7 @@ Updates in v1.5.0 since v1.4.4 series
- There is a partial support for 'shallow' repositories that
keeps only recent history. A 'shallow clone' is created by
specifying how deep that truncated history should be
- (e.g. "git clone --depth=5 git://some.where/repo.git").
+ (e.g. "git clone --depth 5 git://some.where/repo.git").
Currently a shallow repository has number of limitations:
diff --git a/Documentation/RelNotes-1.5.1.txt b/Documentation/RelNotes-1.5.1.txt
new file mode 100644
index 000000000..4d371866c
--- /dev/null
+++ b/Documentation/RelNotes-1.5.1.txt
@@ -0,0 +1,44 @@
+GIT v1.5.1 Release Notes
+========================
+
+Updates since v1.5.0
+--------------------
+
+* Deprecated commands and options.
+
+ - git-diff-stages and git-resolve have been removed.
+
+* New commands and options.
+
+ - "git log" and friends take --reverse. This makes output
+ that typically goes reverse order in chronological order.
+ "git shortlog" usually lists commits in chronological order,
+ but with "--reverse", they are shown in reverse
+ chronological order.
+
+ - "git diff" learned --ignore-space-at-eol. This is a weaker
+ form of --ignore-space-change.
+
+ - "git name-rev" learned --refs=<pattern>, to limit the tags
+ used for naming the given revisions only to the ones
+ matching the given pattern.
+
+* Updated behaviour of existing commands.
+
+ - "git diff" outputs a trailing HT when pathnames have embedded
+ SP on +++/--- header lines, in order to help "GNU patch" to
+ parse its output. "git apply" was already updated to accept
+ this modified output format since ce74618d (Sep 22, 2006).
+
+* Hooks
+
+ - The sample update hook to show how to send out notification
+ e-mail was updated to show only new commits that appeared in
+ the repository. Earlier, it showed new commits that appeared
+ on the branch.
+
+--
+exec >/var/tmp/1
+O=v1.5.0-49-g69bc0e2
+echo O=`git describe master`
+git shortlog --no-merges $O..master ^maint
diff --git a/Documentation/cmd-list.perl b/Documentation/cmd-list.perl
index 69003e90a..a2d6268e2 100755
--- a/Documentation/cmd-list.perl
+++ b/Documentation/cmd-list.perl
@@ -90,7 +90,6 @@ git-describe mainporcelain
git-diff-files plumbinginterrogators
git-diff-index plumbinginterrogators
git-diff mainporcelain
-git-diff-stages plumbinginterrogators
git-diff-tree plumbinginterrogators
git-fast-import ancillarymanipulators
git-fetch mainporcelain
@@ -146,10 +145,10 @@ git-reflog ancillarymanipulators
git-relink ancillarymanipulators
git-repack ancillarymanipulators
git-config ancillarymanipulators
+git-remote ancillarymanipulators
git-request-pull foreignscminterface
git-rerere ancillaryinterrogators
git-reset mainporcelain
-git-resolve mainporcelain
git-revert mainporcelain
git-rev-list plumbinginterrogators
git-rev-parse ancillaryinterrogators
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 38655350f..9d045d883 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -142,6 +142,18 @@ core.preferSymlinkRefs::
This is sometimes needed to work with old scripts that
expect HEAD to be a symbolic link.
+core.bare::
+ If true this repository is assumed to be 'bare' and has no
+ working directory associated with it. If this is the case a
+ number of commands that require a working directory will be
+ disabled, such as gitlink:git-add[1] or gitlink:git-merge[1].
++
+This setting is automatically guessed by gitlink:git-clone[1] or
+gitlink:git-init[1] when the repository was created. By default a
+repository that ends in "/.git" is assumed to be not bare (bare =
+false), while all other repositories are assumed to be bare (bare
+= true).
+
core.logAllRefUpdates::
Updates to a ref <ref> is logged to the file
"$GIT_DIR/logs/<ref>", by appending the new and old
@@ -451,6 +463,10 @@ remote.<name>.push::
The default set of "refspec" for gitlink:git-push[1]. See
gitlink:git-push[1].
+remote.<name>.skipDefaultUpdate::
+ If true, this remote will be skipped by default when updating
+ using the remote subcommand of gitlink:git-remote[1].
+
remote.<name>.receivepack::
The default program to execute on the remote side when pushing. See
option \--exec of gitlink:git-push[1].
@@ -459,6 +475,10 @@ remote.<name>.uploadpack::
The default program to execute on the remote side when fetching. See
option \--exec of gitlink:git-fetch-pack[1].
+remotes.<group>::
+ The list of remotes which are fetched by "git remote update
+ <group>". See gitlink:git-remote[1].
+
repack.usedeltabaseoffset::
Allow gitlink:git-repack[1] to create packs that uses
delta-base offset. Defaults to false.
diff --git a/Documentation/core-intro.txt b/Documentation/core-intro.txt
index abafefc71..eea44d9d5 100644
--- a/Documentation/core-intro.txt
+++ b/Documentation/core-intro.txt
@@ -106,7 +106,8 @@ directory tree, and renaming a file does not change the object that
file is associated with in any way.
A blob is typically created when gitlink:git-update-index[1]
-is run, and its data can be accessed by gitlink:git-cat-file[1].
+(or gitlink:git-add[1]) is run, and its data can be accessed by
+gitlink:git-cat-file[1].
Tree Object
~~~~~~~~~~~
@@ -587,4 +588,5 @@ stages to temporary files and calls a "merge" script on it:
git-merge-index git-merge-one-file hello.c
-and that is what higher level `git resolve` is implemented with.
+and that is what higher level `git merge -s resolve` is implemented
+with.
diff --git a/Documentation/core-tutorial.txt b/Documentation/core-tutorial.txt
index 9c28bea62..97cdb90cb 100644
--- a/Documentation/core-tutorial.txt
+++ b/Documentation/core-tutorial.txt
@@ -977,7 +977,7 @@ see more complex cases.
Now, let's pretend you are the one who did all the work in
`mybranch`, and the fruit of your hard work has finally been merged
to the `master` branch. Let's go back to `mybranch`, and run
-resolve to get the "upstream changes" back to your branch.
+`git merge` to get the "upstream changes" back to your branch.
------------
$ git checkout mybranch
@@ -996,7 +996,7 @@ Fast forward
----------------
Because your branch did not contain anything more than what are
-already merged into the `master` branch, the resolve operation did
+already merged into the `master` branch, the merge operation did
not actually do a merge. Instead, it just updated the top of
the tree of your branch to that of the `master` branch. This is
often called 'fast forward' merge.
@@ -1099,11 +1099,11 @@ programs, which are 'commit walkers'; they outlived their
usefulness when git Native and SSH transports were introduced,
and not used by `git pull` or `git push` scripts.
-Once you fetch from the remote repository, you `resolve` that
+Once you fetch from the remote repository, you `merge` that
with your current branch.
However -- it's such a common thing to `fetch` and then
-immediately `resolve`, that it's called `git pull`, and you can
+immediately `merge`, that it's called `git pull`, and you can
simply do
----------------
diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
index 019a39f2b..d8696b7b3 100644
--- a/Documentation/diff-options.txt
+++ b/Documentation/diff-options.txt
@@ -140,6 +140,9 @@
-a::
Shorthand for "--text".
+--ignore-space-at-eol::
+ Ignore changes in white spaces at EOL.
+
--ignore-space-change::
Ignore changes in amount of white space. This ignores white
space at line end, and consider all other sequences of one or
diff --git a/Documentation/diffcore.txt b/Documentation/diffcore.txt
index cb4e56200..34cd306bb 100644
--- a/Documentation/diffcore.txt
+++ b/Documentation/diffcore.txt
@@ -6,8 +6,8 @@ June 2005
Introduction
------------
-The diff commands git-diff-index, git-diff-files, git-diff-tree, and
-git-diff-stages can be told to manipulate differences they find in
+The diff commands git-diff-index, git-diff-files, and git-diff-tree
+can be told to manipulate differences they find in
unconventional ways before showing diff(1) output. The manipulation
is collectively called "diffcore transformation". This short note
describes what they are and how to use them to produce diff outputs
@@ -30,9 +30,6 @@ files:
- git-diff-tree compares contents of two "tree" objects;
- - git-diff-stages compares contents of blobs at two stages in an
- unmerged index file.
-
In all of these cases, the commands themselves compare
corresponding paths in the two sets of files. The result of
comparison is passed from these commands to what is internally
diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index e4ffde4fd..1ae77be45 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -61,7 +61,8 @@ OPTIONS
+
When a merge conflict happens, the index entries for conflicting
paths are left unmerged, and you need to resolve the conflicts
-and mark the resolved paths with `git update-index`.
+and mark the resolved paths with `git add` (or `git rm` if the merge
+should result in deletion of the path).
<new_branch>::
Name for the new branch.
@@ -179,11 +180,11 @@ fatal: merge program failed
At this point, `git diff` shows the changes cleanly merged as in
the previous example, as well as the changes in the conflicted
files. Edit and resolve the conflict and mark it resolved with
-`git update-index` as usual:
+`git add` as usual:
+
------------
$ edit frotz
-$ git update-index frotz
+$ git add frotz
------------
diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index 707376f22..6d32c491a 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -11,7 +11,7 @@ SYNOPSIS
[verse]
'git-clone' [--template=<template_directory>] [-l [-s]] [-q] [-n] [--bare]
[-o <name>] [-u <upload-pack>] [--reference <repository>]
- [--depth=<depth>] <repository> [<directory>]
+ [--depth <depth>] <repository> [<directory>]
DESCRIPTION
-----------
@@ -96,7 +96,7 @@ OPTIONS
if unset the templates are taken from the installation
defined default, typically `/usr/share/git-core/templates`.
---depth=<depth>::
+--depth <depth>::
Create a 'shallow' clone with a history truncated to the
specified number of revs. A shallow repository has
number of limitations (you cannot clone or fetch from
diff --git a/Documentation/git-cvsexportcommit.txt b/Documentation/git-cvsexportcommit.txt
index 27d531b88..555b8234f 100644
--- a/Documentation/git-cvsexportcommit.txt
+++ b/Documentation/git-cvsexportcommit.txt
@@ -8,7 +8,7 @@ git-cvsexportcommit - Export a single commit to a CVS checkout
SYNOPSIS
--------
-'git-cvsexportcommit' [-h] [-v] [-c] [-P] [-p] [-a] [-f] [-m msgprefix] [PARENTCOMMIT] COMMITID
+'git-cvsexportcommit' [-h] [-v] [-c] [-P] [-p] [-a] [-d cvsroot] [-f] [-m msgprefix] [PARENTCOMMIT] COMMITID
DESCRIPTION
@@ -43,6 +43,11 @@ OPTIONS
Add authorship information. Adds Author line, and Committer (if
different from Author) to the message.
+-d::
+ Set an alternative CVSROOT to use. This corresponds to the CVS
+ -d parameter. Usually users will not want to set this, except
+ if using CVS in an asymmetric fashion.
+
-f::
Force the merge even if the files are not up to date.
diff --git a/Documentation/git-diff-stages.txt b/Documentation/git-diff-stages.txt
deleted file mode 100644
index b8f45b8cd..000000000
--- a/Documentation/git-diff-stages.txt
+++ /dev/null
@@ -1,42 +0,0 @@
-git-diff-stages(1)
-==================
-
-NAME
-----
-git-diff-stages - Compares two merge stages in the index
-
-
-SYNOPSIS
---------
-'git-diff-stages' [<common diff options>] <stage1> <stage2> [<path>...]
-
-DESCRIPTION
------------
-DEPRECATED and will be removed in 1.5.1.
-
-Compares the content and mode of the blobs in two stages in an
-unmerged index file.
-
-OPTIONS
--------
-include::diff-options.txt[]
-
-<stage1>,<stage2>::
- The stage number to be compared.
-
-Output format
--------------
-include::diff-format.txt[]
-
-
-Author
-------
-Written by Junio C Hamano <junkio@cox.net>
-
-Documentation
---------------
-Documentation by Junio C Hamano.
-
-GIT
----
-Part of the gitlink:git[7] suite
diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt
index 445f6b854..77a14bb07 100644
--- a/Documentation/git-fast-import.txt
+++ b/Documentation/git-fast-import.txt
@@ -3,7 +3,7 @@ git-fast-import(1)
NAME
----
-git-fast-import - Backend for fast Git data importers.
+git-fast-import - Backend for fast Git data importers
SYNOPSIS
diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt
index e53ff4b4e..9c08efa53 100644
--- a/Documentation/git-merge.txt
+++ b/Documentation/git-merge.txt
@@ -136,7 +136,7 @@ After seeing a conflict, you can do two things:
* Resolve the conflicts. `git-diff` would report only the
conflicting paths because of the above 2. and 3.. Edit the
- working tree files into a desirable shape, `git-update-index`
+ working tree files into a desirable shape, `git-add` or `git-rm`
them, to make the index file contain what the merge result
should be, and run `git-commit` to commit the result.
diff --git a/Documentation/git-name-rev.txt b/Documentation/git-name-rev.txt
index 37fbf66ef..5b5c4c865 100644
--- a/Documentation/git-name-rev.txt
+++ b/Documentation/git-name-rev.txt
@@ -8,7 +8,8 @@ git-name-rev - Find symbolic names for given revs
SYNOPSIS
--------
-'git-name-rev' [--tags] ( --all | --stdin | <committish>... )
+'git-name-rev' [--tags] [--refs=<pattern>]
+ ( --all | --stdin | <committish>... )
DESCRIPTION
-----------
@@ -22,6 +23,9 @@ OPTIONS
--tags::
Do not use branch names, but only tags to name the commits
+--refs=<pattern>::
+ Only use refs whose names match a given shell pattern.
+
--all::
List all commits reachable from all refs
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index f2ef1f7dc..2f417a8f8 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -13,11 +13,20 @@ SYNOPSIS
DESCRIPTION
-----------
-git-rebase replaces <branch> with a new branch of the same name. When
-the --onto option is provided the new branch starts out with a HEAD equal
-to <newbase>, otherwise it is equal to <upstream>. It then attempts to
-create a new commit for each commit from the original <branch> that does
-not exist in the <upstream> branch.
+If <branch> is specified, git-rebase will perform an automatic
+`git checkout <branch>` before doing anything else. Otherwise
+it remains on the current branch.
+
+All changes made by commits in the current branch but that are not
+in <upstream> are saved to a temporary area. This is the same set
+of commits that would be shown by `git log <upstream>..HEAD`.
+
+The current branch is reset to <upstream>, or <newbase> if the
+--onto option was supplied. This has the exact same effect as
+`git reset --hard <upstream>` (or <newbase>).
+
+The commits that were previously saved into the temporary area are
+then reapplied to the current branch, one by one, in order.
It is possible that a merge failure will prevent this process from being
completely automatic. You will have to resolve any such merge failure
@@ -26,9 +35,6 @@ that caused the merge failure with `git rebase --skip`. To restore the
original <branch> and remove the .dotest working files, use the command
`git rebase --abort` instead.
-Note that if <branch> is not specified on the command line, the currently
-checked out branch is used.
-
Assume the following history exists and the current branch is "topic":
------------
@@ -142,7 +148,7 @@ file you edit, you need to tell git that the conflict has been resolved,
typically this would be done with
- git update-index <filename>
+ git add <filename>
After resolving the conflict manually and updating the index with the
diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt
index a60c31a31..250761f97 100644
--- a/Documentation/git-remote.txt
+++ b/Documentation/git-remote.txt
@@ -13,6 +13,7 @@ SYNOPSIS
'git-remote' add <name> <url>
'git-remote' show <name>
'git-remote' prune <name>
+'git-remote' update [group]
DESCRIPTION
-----------
@@ -40,7 +41,17 @@ Gives some information about the remote <name>.
Deletes all stale tracking branches under <name>.
These stale branches have already been removed from the remote repository
-referenced by <name>, but are still locally available in "remotes/<name>".
+referenced by <name>, but are still locally available in
+"remotes/<name>".
+
+'update'::
+
+Fetch updates for a named set of remotes in the repository as defined by
+remotes.<group>. If a named group is not specified on the command line,
+the configuration parameter remotes.default will get used; if
+remotes.default is not defined, all remotes which do not the
+configuration parameter remote.<name>.skipDefaultUpdate set to true will
+be updated. (See gitlink:git-config[1]).
DISCUSSION
diff --git a/Documentation/git-rerere.txt b/Documentation/git-rerere.txt
index 139b6eb77..7ff9b05e6 100644
--- a/Documentation/git-rerere.txt
+++ b/Documentation/git-rerere.txt
@@ -163,8 +163,7 @@ If this three-way merge resolves cleanly, the result is written
out to your working tree file, so you would not have to manually
resolve it. Note that `git-rerere` leaves the index file alone,
so you still need to do the final sanity checks with `git diff`
-(or `git diff -c`) and `git update-index` when you are
-satisfied.
+(or `git diff -c`) and `git add` when you are satisfied.
As a convenience measure, `git-merge` automatically invokes
`git-rerere` when it exits with a failed automerge, which
diff --git a/Documentation/git-reset.txt b/Documentation/git-reset.txt
index 04475a921..5b55cda51 100644
--- a/Documentation/git-reset.txt
+++ b/Documentation/git-reset.txt
@@ -94,11 +94,11 @@ current HEAD.
<2> Rewind the master branch to get rid of those three commits.
<3> Switch to "topic/wip" branch and keep working.
-Undo update-index::
+Undo add::
+
------------
$ edit <1>
-$ git-update-index frotz.c filfre.c
+$ git add frotz.c filfre.c
$ mailx <2>
$ git reset <3>
$ git pull git://info.example.com/ nitfol <4>
diff --git a/Documentation/git-resolve.txt b/Documentation/git-resolve.txt
deleted file mode 100644
index 7fde665fb..000000000
--- a/Documentation/git-resolve.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-git-resolve(1)
-==============
-
-NAME
-----
-git-resolve - Merge two commits
-
-
-SYNOPSIS
---------
-'git-resolve' <current> <merged> <message>
-
-DESCRIPTION
------------
-DEPRECATED and will be removed in 1.5.1. Use `git-merge` instead.
-
-Given two commits and a merge message, merge the <merged> commit
-into <current> commit, with the commit log message <message>.
-
-When <current> is a descendant of <merged>, or <current> is an
-ancestor of <merged>, no new commit is created and the <message>
-is ignored. The former is informally called "already up to
-date", and the latter is often called "fast forward".
-
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org> and
-Dan Holmsand <holmsand@gmail.com>.
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
-GIT
----
-Part of the gitlink:git[7] suite
-
diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt
index c74211759..4f145eaba 100644
--- a/Documentation/git-rev-list.txt
+++ b/Documentation/git-rev-list.txt
@@ -27,6 +27,7 @@ SYNOPSIS
[ \--pretty | \--header ]
[ \--bisect ]
[ \--merge ]
+ [ \--reverse ]
[ \--walk-reflogs ]
<commit>... [ \-- <paths>... ]
@@ -266,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
~~~~~~~~~~~~~~~~
diff --git a/Documentation/git-runstatus.txt b/Documentation/git-runstatus.txt
index 89d7b9273..8bb52f468 100644
--- a/Documentation/git-runstatus.txt
+++ b/Documentation/git-runstatus.txt
@@ -16,7 +16,7 @@ DESCRIPTION
Examines paths in the working tree that has changes unrecorded
to the index file, and changes between the index file and the
current HEAD commit. The former paths are what you _could_
-commit by running 'git-update-index' before running 'git
+commit by running 'git add' (or 'git rm' if you are deleting) before running 'git
commit', and the latter paths are what you _would_ commit by
running 'git commit'.
diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt
index 03871e5d7..e9e193f00 100644
--- a/Documentation/git-status.txt
+++ b/Documentation/git-status.txt
@@ -15,7 +15,7 @@ DESCRIPTION
Examines paths in the working tree that has changes unrecorded
to the index file, and changes between the index file and the
current HEAD commit. The former paths are what you _could_
-commit by running 'git-update-index' before running 'git
+commit by running 'git add' before running 'git
commit', and the latter paths are what you _would_ commit by
running 'git commit'.
diff --git a/Documentation/git.txt b/Documentation/git.txt
index c0fa0d4b1..aa3acc046 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -35,6 +35,14 @@ ifdef::stalenotes[]
You are reading the documentation for the latest version of git.
Documentation for older releases are available here:
+* link:v1.5.0.1/git.html[documentation for release 1.5.0.1]
+
+* link:v1.5.0.1/RelNotes-1.5.0.1.txt[release notes for 1.5.0.1]
+
+* link:v1.5.0/git.html[documentation for release 1.5.0]
+
+* link:v1.5.0/RelNotes-1.5.0.txt[release notes for 1.5.0]
+
* link:v1.4.4.4/git.html[documentation for release 1.4.4.4]
* link:v1.3.3/git.html[documentation for release 1.3.3]
diff --git a/Documentation/howto/revert-branch-rebase.txt b/Documentation/howto/revert-branch-rebase.txt
index d10476b56..d88ec23a9 100644
--- a/Documentation/howto/revert-branch-rebase.txt
+++ b/Documentation/howto/revert-branch-rebase.txt
@@ -85,7 +85,7 @@ Fortunately I did not have to; what I have in the current branch
------------------------------------------------
$ git checkout master
-$ git resolve master revert-c99 fast ;# this should be a fast forward
+$ git merge revert-c99 ;# this should be a fast forward
Updating from 10d781b9caa4f71495c7b34963bef137216f86a8 to e3a693c...
cache.h | 8 ++++----
commit.c | 2 +-
@@ -95,13 +95,6 @@ Updating from 10d781b9caa4f71495c7b34963bef137216f86a8 to e3a693c...
5 files changed, 8 insertions(+), 8 deletions(-)
------------------------------------------------
-The 'fast' in the above 'git resolve' is not a magic. I knew this
-'resolve' would result in a fast forward merge, and if not, there is
-something very wrong (so I would do 'git reset' on the 'master' branch
-and examine the situation). When a fast forward merge is done, the
-message parameter to 'git resolve' is discarded, because no new commit
-is created. You could have said 'junk' or 'nothing' there as well.
-
There is no need to redo the test at this point. We fast forwarded
and we know 'master' matches 'revert-c99' exactly. In fact:
diff --git a/Documentation/i18n.txt b/Documentation/i18n.txt
index b4cbb3830..b95f99be6 100644
--- a/Documentation/i18n.txt
+++ b/Documentation/i18n.txt
@@ -25,15 +25,15 @@ mind.
an warning if the commit log message given to it does not look
like a valid UTF-8 string, unless you explicitly say your
project uses a legacy encoding. The way to say this is to
- have core.commitencoding in `.git/config` file, like this:
+ have i18n.commitencoding in `.git/config` file, like this:
+
------------
-[core]
+[i18n]
commitencoding = ISO-8859-1
------------
+
Commit objects created with the above setting record the value
-of `core.commitencoding` in its `encoding` header. This is to
+of `i18n.commitencoding` in its `encoding` header. This is to
help other people who look at them later. Lack of this header
implies that the commit log message is encoded in UTF-8.
@@ -41,15 +41,15 @@ implies that the commit log message is encoded in UTF-8.
header of a commit object, and tries to re-code the log
message into UTF-8 unless otherwise specified. You can
specify the desired output encoding with
- `core.logoutputencoding` in `.git/config` file, like this:
+ `i18n.logoutputencoding` in `.git/config` file, like this:
+
------------
-[core]
+[i18n]
logoutputencoding = ISO-8859-1
------------
+
If you do not have this configuration variable, the value of
-`core.commitencoding` is used instead.
+`i18n.commitencoding` is used instead.
Note that we deliberately chose not to re-code the commit log
message when a commit is made to force UTF-8 at the commit
diff --git a/Documentation/tutorial-2.txt b/Documentation/tutorial-2.txt
index 8d8999271..af8d43bd1 100644
--- a/Documentation/tutorial-2.txt
+++ b/Documentation/tutorial-2.txt
@@ -227,7 +227,7 @@ $ git diff
@@ -1 +1,2 @@
hello world!
+hello world, again
-$ git update-index file.txt
+$ git add file.txt
$ git diff
------------------------------------------------
@@ -260,7 +260,7 @@ hello world!
hello world, again
------------------------------------------------
-So what our "git update-index" did was store a new blob and then put
+So what our "git add" did was store a new blob and then put
a reference to it in the index file. If we modify the file again,
we'll see that the new modifications are reflected in the "git-diff"
output:
diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt
index c5e9ea8a4..03736bbcd 100644
--- a/Documentation/user-manual.txt
+++ b/Documentation/user-manual.txt
@@ -2755,7 +2755,7 @@ stages to temporary files and calls a "merge" script on it:
$ git-merge-index git-merge-one-file hello.c
-------------------------------------------------
-and that is what higher level `git resolve` is implemented with.
+and that is what higher level `git merge -s resolve` is implemented with.
How git stores objects efficiently: pack files
----------------------------------------------
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index febacd2dc..6abde8d7b 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -6,18 +6,19 @@ DEF_VER=v1.5.0.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) &&
- case "$VN" in
- *$LF*) (exit 1) ;;
- v[0-9]*) : happy ;;
- esac
-then
- VN=$(echo "$VN" | sed -e 's/-/./g');
-elif test -f version
+# First see if there is a version file (included in release tarballs),
+# then try git-describe, then default.
+if test -f version
then
VN=$(cat version) || VN="$DEF_VER"
+elif test -d .git &&
+ 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');
else
VN="$DEF_VER"
fi
diff --git a/Makefile b/Makefile
index 40bdcff69..fbe05f938 100644
--- a/Makefile
+++ b/Makefile
@@ -28,6 +28,10 @@ all::
#
# Define NO_STRLCPY if you don't have strlcpy.
#
+# Define NO_STRTOUMAX if you don't have strtoumax in the C library.
+# If your compiler also does not support long long or does not have
+# strtoull, define NO_STRTOULL.
+#
# Define NO_SETENV if you don't have setenv in the C library.
#
# Define NO_SYMLINK_HEAD if you never want .git/HEAD to be a symbolic link.
@@ -172,7 +176,7 @@ SCRIPT_SH = \
git-merge-one-file.sh git-parse-remote.sh \
git-pull.sh git-rebase.sh \
git-repack.sh git-request-pull.sh git-reset.sh \
- git-resolve.sh git-revert.sh git-sh-setup.sh \
+ git-revert.sh git-sh-setup.sh \
git-tag.sh git-verify-tag.sh \
git-applymbox.sh git-applypatch.sh git-am.sh \
git-merge.sh git-merge-stupid.sh git-merge-octopus.sh \
@@ -262,7 +266,8 @@ LIB_OBJS = \
revision.o pager.o tree-walk.o xdiff-interface.o \
write_or_die.o trace.o list-objects.o grep.o \
alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \
- color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o
+ color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \
+ convert.o
BUILTIN_OBJS = \
builtin-add.o \
@@ -280,7 +285,6 @@ BUILTIN_OBJS = \
builtin-diff.o \
builtin-diff-files.o \
builtin-diff-index.o \
- builtin-diff-stages.o \
builtin-diff-tree.o \
builtin-fmt-merge-msg.o \
builtin-for-each-ref.o \
@@ -292,6 +296,7 @@ BUILTIN_OBJS = \
builtin-ls-tree.o \
builtin-mailinfo.o \
builtin-mailsplit.o \
+ builtin-merge-base.o \
builtin-merge-file.o \
builtin-mv.o \
builtin-name-rev.o \
@@ -353,11 +358,13 @@ ifeq ($(uname_S),SunOS)
NO_UNSETENV = YesPlease
NO_SETENV = YesPlease
NO_C99_FORMAT = YesPlease
+ NO_STRTOUMAX = YesPlease
endif
ifeq ($(uname_R),5.9)
NO_UNSETENV = YesPlease
NO_SETENV = YesPlease
NO_C99_FORMAT = YesPlease
+ NO_STRTOUMAX = YesPlease
endif
INSTALL = ginstall
TAR = gtar
@@ -517,6 +524,13 @@ ifdef NO_STRLCPY
COMPAT_CFLAGS += -DNO_STRLCPY
COMPAT_OBJS += compat/strlcpy.o
endif
+ifdef NO_STRTOUMAX
+ COMPAT_CFLAGS += -DNO_STRTOUMAX
+ COMPAT_OBJS += compat/strtoumax.o
+endif
+ifdef NO_STRTOULL
+ COMPAT_CFLAGS += -DNO_STRTOULL
+endif
ifdef NO_SETENV
COMPAT_CFLAGS += -DNO_SETENV
COMPAT_OBJS += compat/setenv.o
@@ -882,7 +896,8 @@ dist: git.spec git-archive
$(TAR) rf $(GIT_TARNAME).tar \
$(GIT_TARNAME)/git.spec \
$(GIT_TARNAME)/version \
- $(GIT_TARNAME)/git-gui/version
+ $(GIT_TARNAME)/git-gui/version \
+ $(GIT_TARNAME)/git-gui/credits
@rm -rf $(GIT_TARNAME)
gzip -f -9 $(GIT_TARNAME).tar
@@ -939,11 +954,14 @@ check-docs::
case "$$v" in \
git-merge-octopus | git-merge-ours | git-merge-recursive | \
git-merge-resolve | git-merge-stupid | \
+ git-add--interactive | git-fsck-objects | git-init-db | \
+ git-repo-config | \
git-ssh-pull | git-ssh-push ) continue ;; \
esac ; \
test -f "Documentation/$$v.txt" || \
echo "no doc: $$v"; \
- grep -q "^gitlink:$$v\[[0-9]\]::" Documentation/git.txt || \
+ sed -e '1,/^__DATA__/d' Documentation/cmd-list.perl | \
+ grep -q "^$$v[ ]" || \
case "$$v" in \
git) ;; \
*) echo "no link: $$v";; \
diff --git a/RelNotes b/RelNotes
index 4571d0d1c..d5e055de6 120000
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes-1.5.0.txt \ No newline at end of file
+Documentation/RelNotes-1.5.1.txt \ No newline at end of file
diff --git a/builtin-apply.c b/builtin-apply.c
index c7d4bdd47..630d8fd65 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -1186,11 +1186,11 @@ static struct fragment *parse_binary_hunk(char **buf_p,
*status_p = 0;
- if (!strncmp(buffer, "delta ", 6)) {
+ if (!prefixcmp(buffer, "delta ")) {
patch_method = BINARY_DELTA_DEFLATED;
origlen = strtoul(buffer + 6, NULL, 10);
}
- else if (!strncmp(buffer, "literal ", 8)) {
+ else if (!prefixcmp(buffer, "literal ")) {
patch_method = BINARY_LITERAL_DEFLATED;
origlen = strtoul(buffer + 8, NULL, 10);
}
@@ -1450,28 +1450,39 @@ static void show_stats(struct patch *patch)
free(qname);
}
-static int read_old_data(struct stat *st, const char *path, void *buf, unsigned long size)
+static int read_old_data(struct stat *st, const char *path, char **buf_p, unsigned long *alloc_p, unsigned long *size_p)
{
int fd;
unsigned long got;
+ unsigned long nsize;
+ char *nbuf;
+ unsigned long size = *size_p;
+ char *buf = *buf_p;
switch (st->st_mode & S_IFMT) {
case S_IFLNK:
- return readlink(path, buf, size);
+ return readlink(path, buf, size) != size;
case S_IFREG:
fd = open(path, O_RDONLY);
if (fd < 0)
return error("unable to open %s", path);
got = 0;
for (;;) {
- int ret = xread(fd, (char *) buf + got, size - got);
+ int ret = xread(fd, buf + got, size - got);
if (ret <= 0)
break;
got += ret;
}
close(fd);
- return got;
-
+ nsize = got;
+ nbuf = buf;
+ if (convert_to_git(path, &nbuf, &nsize)) {
+ free(buf);
+ *buf_p = nbuf;
+ *alloc_p = nsize;
+ *size_p = nsize;
+ }
+ return got != size;
default:
return -1;
}
@@ -1967,7 +1978,7 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *
size = st->st_size;
alloc = size + 8192;
buf = xmalloc(alloc);
- if (read_old_data(st, patch->old_name, buf, alloc) != size)
+ if (read_old_data(st, patch->old_name, &buf, &alloc, &size))
return error("read of %s failed", patch->old_name);
}
@@ -2045,7 +2056,7 @@ static int check_patch(struct patch *patch, struct patch *prev_patch)
return error("%s: %s", old_name, strerror(errno));
if (!cached)
- st_mode = ntohl(create_ce_mode(st.st_mode));
+ st_mode = ntohl(ce_mode_from_stat(ce, st.st_mode));
if (patch->is_new < 0)
patch->is_new = 0;
@@ -2339,12 +2350,22 @@ static void add_index_file(const char *path, unsigned mode, void *buf, unsigned
static int try_create_file(const char *path, unsigned int mode, const char *buf, unsigned long size)
{
int fd;
+ char *nbuf;
+ unsigned long nsize;
if (S_ISLNK(mode))
/* Although buf:size is counted string, it also is NUL
* terminated.
*/
return symlink(buf, path);
+ nsize = size;
+ nbuf = (char *) buf;
+ if (convert_to_working_tree(path, &nbuf, &nsize)) {
+ free((char *) buf);
+ buf = nbuf;
+ size = nsize;
+ }
+
fd = open(path, O_CREAT | O_EXCL | O_WRONLY, (mode & 0100) ? 0777 : 0666);
if (fd < 0)
return -1;
@@ -2701,14 +2722,14 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
read_stdin = 0;
continue;
}
- if (!strncmp(arg, "--exclude=", 10)) {
+ if (!prefixcmp(arg, "--exclude=")) {
struct excludes *x = xmalloc(sizeof(*x));
x->path = arg + 10;
x->next = excludes;
excludes = x;
continue;
}
- if (!strncmp(arg, "-p", 2)) {
+ if (!prefixcmp(arg, "-p")) {
p_value = atoi(arg + 2);
p_value_known = 1;
continue;
@@ -2767,13 +2788,13 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
line_termination = 0;
continue;
}
- if (!strncmp(arg, "-C", 2)) {
+ if (!prefixcmp(arg, "-C")) {
p_context = strtoul(arg + 2, &end, 0);
if (*end != '\0')
die("unrecognized context count '%s'", arg + 2);
continue;
}
- if (!strncmp(arg, "--whitespace=", 13)) {
+ if (!prefixcmp(arg, "--whitespace=")) {
whitespace_option = arg + 13;
parse_whitespace_option(arg + 13);
continue;
diff --git a/builtin-archive.c b/builtin-archive.c
index f613ac251..8ea6cb1ef 100644
--- a/builtin-archive.c
+++ b/builtin-archive.c
@@ -35,7 +35,7 @@ static int run_remote_archiver(const char *remote, int argc,
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
- if (!strncmp("--exec=", arg, 7)) {
+ if (!prefixcmp(arg, "--exec=")) {
if (exec_at)
die("multiple --exec specified");
exec = arg + 7;
@@ -62,7 +62,7 @@ static int run_remote_archiver(const char *remote, int argc,
if (buf[len-1] == '\n')
buf[--len] = 0;
if (strcmp(buf, "ACK")) {
- if (len > 5 && !strncmp(buf, "NACK ", 5))
+ if (len > 5 && !prefixcmp(buf, "NACK "))
die("git-archive: NACK %s", buf + 5);
die("git-archive: protocol error");
}
@@ -166,11 +166,11 @@ int parse_archive_args(int argc, const char **argv, struct archiver *ar)
verbose = 1;
continue;
}
- if (!strncmp(arg, "--format=", 9)) {
+ if (!prefixcmp(arg, "--format=")) {
format = arg + 9;
continue;
}
- if (!strncmp(arg, "--prefix=", 9)) {
+ if (!prefixcmp(arg, "--prefix=")) {
base = arg + 9;
continue;
}
@@ -218,7 +218,7 @@ static const char *extract_remote_arg(int *ac, const char **av)
if (!strcmp(arg, "--"))
no_more_options = 1;
if (!no_more_options) {
- if (!strncmp(arg, "--remote=", 9)) {
+ if (!prefixcmp(arg, "--remote=")) {
if (remote)
die("Multiple --remote specified");
remote = arg + 9;
diff --git a/builtin-blame.c b/builtin-blame.c
index 69fc145a3..530b97f97 100644
--- a/builtin-blame.c
+++ b/builtin-blame.c
@@ -2065,6 +2065,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
int i, seen_dashdash, unk, opt;
long bottom, top, lno;
int output_option = 0;
+ int show_stats = 0;
const char *revs_file = NULL;
const char *final_commit_name = NULL;
char type[10];
@@ -2086,6 +2087,8 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
blank_boundary = 1;
else if (!strcmp("--root", arg))
show_root = 1;
+ else if (!strcmp(arg, "--show-stats"))
+ show_stats = 1;
else if (!strcmp("-c", arg))
output_option |= OUTPUT_ANNOTATE_COMPAT;
else if (!strcmp("-t", arg))
@@ -2094,17 +2097,17 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
output_option |= OUTPUT_LONG_OBJECT_NAME;
else if (!strcmp("-S", arg) && ++i < argc)
revs_file = argv[i];
- else if (!strncmp("-M", arg, 2)) {
+ else if (!prefixcmp(arg, "-M")) {
opt |= PICKAXE_BLAME_MOVE;
blame_move_score = parse_score(arg+2);
}
- else if (!strncmp("-C", arg, 2)) {
+ else if (!prefixcmp(arg, "-C")) {
if (opt & PICKAXE_BLAME_COPY)
opt |= PICKAXE_BLAME_COPY_HARDER;
opt |= PICKAXE_BLAME_COPY | PICKAXE_BLAME_MOVE;
blame_copy_score = parse_score(arg+2);
}
- else if (!strncmp("-L", arg, 2)) {
+ else if (!prefixcmp(arg, "-L")) {
if (!arg[2]) {
if (++i >= argc)
usage(blame_usage);
@@ -2200,6 +2203,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
if (!strcmp(argv[j], "--"))
seen_dashdash = j;
if (seen_dashdash) {
+ /* (2) */
if (seen_dashdash + 1 != argc - 1)
usage(blame_usage);
path = add_prefix(prefix, argv[seen_dashdash + 1]);
@@ -2208,6 +2212,8 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
}
else {
/* (3) */
+ if (argc <= i)
+ usage(blame_usage);
path = add_prefix(prefix, argv[i]);
if (i + 1 == argc - 1) {
final_commit_name = argv[i + 1];
@@ -2348,7 +2354,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
ent = e;
}
- if (DEBUG) {
+ if (show_stats) {
printf("num read blob: %d\n", num_read_blob);
printf("num get patch: %d\n", num_get_patch);
printf("num commits: %d\n", num_commits);
diff --git a/builtin-branch.c b/builtin-branch.c
index 2d8d61b45..d0179b00a 100644
--- a/builtin-branch.c
+++ b/builtin-branch.c
@@ -59,7 +59,7 @@ int git_branch_config(const char *var, const char *value)
branch_use_color = git_config_colorbool(var, value);
return 0;
}
- if (!strncmp(var, "color.branch.", 13)) {
+ if (!prefixcmp(var, "color.branch.")) {
int slot = parse_branch_color_slot(var, 13);
color_parse(value, var, branch_colors[slot]);
return 0;
@@ -134,7 +134,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)
*/
if (!force &&
- !in_merge_bases(rev, head_rev)) {
+ !in_merge_bases(rev, &head_rev, 1)) {
error("The branch '%s' is not a strict subset of "
"your current HEAD.\n"
"If you are sure you want to delete it, "
@@ -178,13 +178,13 @@ static int append_ref(const char *refname, const unsigned char *sha1, int flags,
int len;
/* Detect kind */
- if (!strncmp(refname, "refs/heads/", 11)) {
+ if (!prefixcmp(refname, "refs/heads/")) {
kind = REF_LOCAL_BRANCH;
refname += 11;
- } else if (!strncmp(refname, "refs/remotes/", 13)) {
+ } else if (!prefixcmp(refname, "refs/remotes/")) {
kind = REF_REMOTE_BRANCH;
refname += 13;
- } else if (!strncmp(refname, "refs/tags/", 10)) {
+ } else if (!prefixcmp(refname, "refs/tags/")) {
kind = REF_TAG;
refname += 10;
}
@@ -446,7 +446,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
reflog = 1;
continue;
}
- if (!strncmp(arg, "--abbrev=", 9)) {
+ if (!prefixcmp(arg, "--abbrev=")) {
abbrev = atoi(arg+9);
continue;
}
@@ -476,7 +476,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
detached = 1;
}
else {
- if (strncmp(head, "refs/heads/", 11))
+ if (prefixcmp(head, "refs/heads/"))
die("HEAD not found below refs/heads!");
head += 11;
}
diff --git a/builtin-checkout-index.c b/builtin-checkout-index.c
index b097c888a..afe4b0e45 100644
--- a/builtin-checkout-index.c
+++ b/builtin-checkout-index.c
@@ -223,12 +223,12 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
to_tempfile = 1;
continue;
}
- if (!strncmp(arg, "--prefix=", 9)) {
+ if (!prefixcmp(arg, "--prefix=")) {
state.base_dir = arg+9;
state.base_dir_len = strlen(state.base_dir);
continue;
}
- if (!strncmp(arg, "--stage=", 8)) {
+ if (!prefixcmp(arg, "--stage=")) {
if (!strcmp(arg + 8, "all")) {
to_tempfile = 1;
checkout_stage = CHECKOUT_ALL;
diff --git a/builtin-describe.c b/builtin-describe.c
index bcc645622..165917e40 100644
--- a/builtin-describe.c
+++ b/builtin-describe.c
@@ -52,7 +52,7 @@ static int get_name(const char *path, const unsigned char *sha1, int flag, void
* If --tags, then any tags are used.
* Otherwise only annotated tags are used.
*/
- if (!strncmp(path, "refs/tags/", 10)) {
+ if (!prefixcmp(path, "refs/tags/")) {
if (object->type == OBJ_TAG)
prio = 2;
else
@@ -254,12 +254,12 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
all = 1;
else if (!strcmp(arg, "--tags"))
tags = 1;
- else if (!strncmp(arg, "--abbrev=", 9)) {
+ else if (!prefixcmp(arg, "--abbrev=")) {
abbrev = strtoul(arg + 9, NULL, 10);
if (abbrev != 0 && (abbrev < MINIMUM_ABBREV || 40 < abbrev))
abbrev = DEFAULT_ABBREV;
}
- else if (!strncmp(arg, "--candidates=", 13)) {
+ else if (!prefixcmp(arg, "--candidates=")) {
max_candidates = strtoul(arg + 13, NULL, 10);
if (max_candidates < 1)
max_candidates = 1;
diff --git a/builtin-diff-stages.c b/builtin-diff-stages.c
deleted file mode 100644
index 70bb89808..000000000
--- a/builtin-diff-stages.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2005 Junio C Hamano
- */
-
-#include "cache.h"
-#include "diff.h"
-#include "builtin.h"
-
-static struct diff_options diff_options;
-
-static const char diff_stages_usage[] =
-"git-diff-stages [<common diff options>] <stage1> <stage2> [<path>...]"
-COMMON_DIFF_OPTIONS_HELP;
-
-static void diff_stages(int stage1, int stage2, const char **pathspec)
-{
- int i = 0;
- while (i < active_nr) {
- struct cache_entry *ce, *stages[4] = { NULL, };
- struct cache_entry *one, *two;
- const char *name;
- int len, skip;
-
- ce = active_cache[i];
- skip = !ce_path_match(ce, pathspec);
- len = ce_namelen(ce);
- name = ce->name;
- for (;;) {
- int stage = ce_stage(ce);
- stages[stage] = ce;
- if (active_nr <= ++i)
- break;
- ce = active_cache[i];
- if (ce_namelen(ce) != len ||
- memcmp(name, ce->name, len))
- break;
- }
- one = stages[stage1];
- two = stages[stage2];
-
- if (skip || (!one && !two))
- continue;
- if (!one)
- diff_addremove(&diff_options, '+', ntohl(two->ce_mode),
- two->sha1, name, NULL);
- else if (!two)
- diff_addremove(&diff_options, '-', ntohl(one->ce_mode),
- one->sha1, name, NULL);
- else if (hashcmp(one->sha1, two->sha1) ||
- (one->ce_mode != two->ce_mode) ||
- diff_options.find_copies_harder)
- diff_change(&diff_options,
- ntohl(one->ce_mode), ntohl(two->ce_mode),
- one->sha1, two->sha1, name, NULL);
- }
-}
-
-int cmd_diff_stages(int ac, const char **av, const char *prefix)
-{
- int stage1, stage2;
- const char **pathspec = NULL;
-
- git_config(git_default_config); /* no "diff" UI options */
- read_cache();
- diff_setup(&diff_options);
- while (1 < ac && av[1][0] == '-') {
- const char *arg = av[1];
- if (!strcmp(arg, "-r"))
- ; /* as usual */
- else {
- int diff_opt_cnt;
- diff_opt_cnt = diff_opt_parse(&diff_options,
- av+1, ac-1);
- if (diff_opt_cnt < 0)
- usage(diff_stages_usage);
- else if (diff_opt_cnt) {
- av += diff_opt_cnt;
- ac -= diff_opt_cnt;
- continue;
- }
- else
- usage(diff_stages_usage);
- }
- ac--; av++;
- }
-
- if (!diff_options.output_format)
- diff_options.output_format = DIFF_FORMAT_RAW;
-
- if (ac < 3 ||
- sscanf(av[1], "%d", &stage1) != 1 ||
- ! (0 <= stage1 && stage1 <= 3) ||
- sscanf(av[2], "%d", &stage2) != 1 ||
- ! (0 <= stage2 && stage2 <= 3))
- usage(diff_stages_usage);
-
- av += 3; /* The rest from av[0] are for paths restriction. */
- pathspec = get_pathspec(prefix, av);
-
- if (diff_setup_done(&diff_options) < 0)
- usage(diff_stages_usage);
-
- diff_stages(stage1, stage2, pathspec);
- diffcore_std(&diff_options);
- diff_flush(&diff_options);
- return 0;
-}
diff --git a/builtin-diff.c b/builtin-diff.c
index a6590205e..c387ebb16 100644
--- a/builtin-diff.c
+++ b/builtin-diff.c
@@ -192,7 +192,8 @@ static int builtin_diff_combined(struct rev_info *revs,
parent = xmalloc(ents * sizeof(*parent));
/* Again, the revs are all reverse */
for (i = 0; i < ents; i++)
- hashcpy((unsigned char*)parent + i, ent[ents - 1 - i].item->sha1);
+ hashcpy((unsigned char *)(parent + i),
+ ent[ents - 1 - i].item->sha1);
diff_tree_combined(parent[0], parent + 1, ents - 1,
revs->dense_combined_merges, revs);
return 0;
diff --git a/builtin-fmt-merge-msg.c b/builtin-fmt-merge-msg.c
index 87d3d63ec..148988356 100644
--- a/builtin-fmt-merge-msg.c
+++ b/builtin-fmt-merge-msg.c
@@ -81,7 +81,7 @@ static int handle_line(char *line)
if (len < 43 || line[40] != '\t')
return 1;
- if (!strncmp(line + 41, "not-for-merge", 13))
+ if (!prefixcmp(line + 41, "not-for-merge"))
return 0;
if (line[41] != '\t')
@@ -119,15 +119,15 @@ static int handle_line(char *line)
if (pulling_head) {
origin = xstrdup(src);
src_data->head_status |= 1;
- } else if (!strncmp(line, "branch ", 7)) {
+ } else if (!prefixcmp(line, "branch ")) {
origin = xstrdup(line + 7);
append_to_list(&src_data->branch, origin, NULL);
src_data->head_status |= 2;
- } else if (!strncmp(line, "tag ", 4)) {
+ } else if (!prefixcmp(line, "tag ")) {
origin = line;
append_to_list(&src_data->tag, xstrdup(origin + 4), NULL);
src_data->head_status |= 2;
- } else if (!strncmp(line, "remote branch ", 14)) {
+ } else if (!prefixcmp(line, "remote branch ")) {
origin = xstrdup(line + 14);
append_to_list(&src_data->r_branch, origin, NULL);
src_data->head_status |= 2;
@@ -280,7 +280,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
current_branch = resolve_ref("HEAD", head_sha1, 1, NULL);
if (!current_branch)
die("No current branch");
- if (!strncmp(current_branch, "refs/heads/", 11))
+ if (!prefixcmp(current_branch, "refs/heads/"))
current_branch += 11;
while (fgets(line, sizeof(line), in)) {
diff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c
index 16c785f04..ac0b9f608 100644
--- a/builtin-for-each-ref.c
+++ b/builtin-for-each-ref.c
@@ -814,7 +814,7 @@ int cmd_for_each_ref(int ac, const char **av, char *prefix)
i++;
break;
}
- if (!strncmp(arg, "--format=", 9)) {
+ if (!prefixcmp(arg, "--format=")) {
if (format)
die("more than one --format?");
format = arg + 9;
@@ -844,7 +844,7 @@ int cmd_for_each_ref(int ac, const char **av, char *prefix)
quote_style = QUOTE_TCL;
continue;
}
- if (!strncmp(arg, "--count=", 8)) {
+ if (!prefixcmp(arg, "--count=")) {
if (maxcount)
die("more than one --count?");
maxcount = atoi(arg + 8);
@@ -852,7 +852,7 @@ int cmd_for_each_ref(int ac, const char **av, char *prefix)
die("The number %s did not parse", arg);
continue;
}
- if (!strncmp(arg, "--sort=", 7)) {
+ if (!prefixcmp(arg, "--sort=")) {
struct ref_sort *s = xcalloc(1, sizeof(*s));
int len;
diff --git a/builtin-fsck.c b/builtin-fsck.c
index 6da3814d5..6abf498d2 100644
--- a/builtin-fsck.c
+++ b/builtin-fsck.c
@@ -546,7 +546,7 @@ static int fsck_head_link(void)
if (!head_points_at || !(flag & REF_ISSYMREF))
return error("HEAD is not a symbolic ref");
- if (strncmp(head_points_at, "refs/heads/", 11))
+ if (prefixcmp(head_points_at, "refs/heads/"))
return error("HEAD points to something strange (%s)",
head_points_at);
if (is_null_sha1(sha1))
diff --git a/builtin-grep.c b/builtin-grep.c
index 2bfbdb714..f35f2d023 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -527,9 +527,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
opt.word_regexp = 1;
continue;
}
- if (!strncmp("-A", arg, 2) ||
- !strncmp("-B", arg, 2) ||
- !strncmp("-C", arg, 2) ||
+ if (!prefixcmp(arg, "-A") ||
+ !prefixcmp(arg, "-B") ||
+ !prefixcmp(arg, "-C") ||
(arg[0] == '-' && '1' <= arg[1] && arg[1] <= '9')) {
unsigned num;
const char *scan;
diff --git a/builtin-init-db.c b/builtin-init-db.c
index 12e43d0db..4df9fd0fa 100644
--- a/builtin-init-db.c
+++ b/builtin-init-db.c
@@ -283,11 +283,11 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
for (i = 1; i < argc; i++, argv++) {
const char *arg = argv[1];
- if (!strncmp(arg, "--template=", 11))
+ if (!prefixcmp(arg, "--template="))
template_dir = arg+11;
else if (!strcmp(arg, "--shared"))
shared_repository = PERM_GROUP;
- else if (!strncmp(arg, "--shared=", 9))
+ else if (!prefixcmp(arg, "--shared="))
shared_repository = git_config_perm("arg", arg+9);
else
usage(init_db_usage);
diff --git a/builtin-log.c b/builtin-log.c
index af2de5437..ad1e8c054 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -32,7 +32,7 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
rev->always_show_header = 0;
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
- if (!strncmp(arg, "--encoding=", 11)) {
+ if (!prefixcmp(arg, "--encoding=")) {
arg += 11;
if (strcmp(arg, "none"))
git_log_output_encoding = strdup(arg);
@@ -287,7 +287,7 @@ static void reopen_stdout(struct commit *commit, int nr, int keep_subject)
sol += 2;
/* strip [PATCH] or [PATCH blabla] */
- if (!keep_subject && !strncmp(sol, "[PATCH", 6)) {
+ if (!keep_subject && !prefixcmp(sol, "[PATCH")) {
char *eos = strchr(sol + 6, ']');
if (eos) {
while (isspace(*eos))
@@ -435,7 +435,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
else if (!strcmp(argv[i], "-n") ||
!strcmp(argv[i], "--numbered"))
numbered = 1;
- else if (!strncmp(argv[i], "--start-number=", 15))
+ else if (!prefixcmp(argv[i], "--start-number="))
start_number = strtol(argv[i] + 15, NULL, 10);
else if (!strcmp(argv[i], "--start-number")) {
i++;
@@ -471,13 +471,13 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
}
else if (!strcmp(argv[i], "--attach"))
rev.mime_boundary = git_version_string;
- else if (!strncmp(argv[i], "--attach=", 9))
+ else if (!prefixcmp(argv[i], "--attach="))
rev.mime_boundary = argv[i] + 9;
else if (!strcmp(argv[i], "--ignore-if-in-upstream"))
ignore_if_in_upstream = 1;
else if (!strcmp(argv[i], "--thread"))
thread = 1;
- else if (!strncmp(argv[i], "--in-reply-to=", 14))
+ else if (!prefixcmp(argv[i], "--in-reply-to="))
in_reply_to = argv[i] + 14;
else if (!strcmp(argv[i], "--in-reply-to")) {
i++;
@@ -485,7 +485,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
die("Need a Message-Id for --in-reply-to");
in_reply_to = argv[i];
}
- else if (!strncmp(argv[i], "--suffix=", 9))
+ else if (!prefixcmp(argv[i], "--suffix="))
fmt_patch_suffix = argv[i] + 9;
else
argv[j++] = argv[i];
diff --git a/builtin-ls-files.c b/builtin-ls-files.c
index ac89eb2f7..4e1d5af63 100644
--- a/builtin-ls-files.c
+++ b/builtin-ls-files.c
@@ -406,7 +406,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
add_exclude(argv[++i], "", 0, &dir.exclude_list[EXC_CMDL]);
continue;
}
- if (!strncmp(arg, "--exclude=", 10)) {
+ if (!prefixcmp(arg, "--exclude=")) {
exc_given = 1;
add_exclude(arg+10, "", 0, &dir.exclude_list[EXC_CMDL]);
continue;
@@ -416,12 +416,12 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
add_excludes_from_file(&dir, argv[++i]);
continue;
}
- if (!strncmp(arg, "--exclude-from=", 15)) {
+ if (!prefixcmp(arg, "--exclude-from=")) {
exc_given = 1;
add_excludes_from_file(&dir, arg+15);
continue;
}
- if (!strncmp(arg, "--exclude-per-directory=", 24)) {
+ if (!prefixcmp(arg, "--exclude-per-directory=")) {
exc_given = 1;
dir.exclude_per_dir = arg + 24;
continue;
@@ -434,7 +434,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
error_unmatch = 1;
continue;
}
- if (!strncmp(arg, "--abbrev=", 9)) {
+ if (!prefixcmp(arg, "--abbrev=")) {
abbrev = strtoul(arg+9, NULL, 10);
if (abbrev && abbrev < MINIMUM_ABBREV)
abbrev = MINIMUM_ABBREV;
diff --git a/builtin-ls-tree.c b/builtin-ls-tree.c
index 201defd93..6472610ac 100644
--- a/builtin-ls-tree.c
+++ b/builtin-ls-tree.c
@@ -118,7 +118,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
chomp_prefix = 0;
break;
}
- if (!strncmp(argv[1]+2, "abbrev=",7)) {
+ if (!prefixcmp(argv[1]+2, "abbrev=")) {
abbrev = strtoul(argv[1]+9, NULL, 10);
if (abbrev && abbrev < MINIMUM_ABBREV)
abbrev = MINIMUM_ABBREV;
diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c
index 583da38b6..6ee6b0b26 100644
--- a/builtin-mailinfo.c
+++ b/builtin-mailinfo.c
@@ -811,7 +811,7 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix)
metainfo_charset = def_charset;
else if (!strcmp(argv[1], "-n"))
metainfo_charset = NULL;
- else if (!strncmp(argv[1], "--encoding=", 11))
+ else if (!prefixcmp(argv[1], "--encoding="))
metainfo_charset = argv[1] + 11;
else
usage(mailinfo_usage);
diff --git a/merge-base.c b/builtin-merge-base.c
index 385f4ba38..e35d362f2 100644
--- a/merge-base.c
+++ b/builtin-merge-base.c
@@ -1,9 +1,7 @@
#include "cache.h"
#include "commit.h"
-static int show_all;
-
-static int merge_base(struct commit *rev1, struct commit *rev2)
+static int show_merge_base(struct commit *rev1, struct commit *rev2, int show_all)
{
struct commit_list *result = get_merge_bases(rev1, rev2, 0);
@@ -23,16 +21,16 @@ static int merge_base(struct commit *rev1, struct commit *rev2)
static const char merge_base_usage[] =
"git-merge-base [--all] <commit-id> <commit-id>";
-int main(int argc, char **argv)
+int cmd_merge_base(int argc, const char **argv, const char *prefix)
{
struct commit *rev1, *rev2;
unsigned char rev1key[20], rev2key[20];
+ int show_all = 0;
- setup_git_directory();
git_config(git_default_config);
while (1 < argc && argv[1][0] == '-') {
- char *arg = argv[1];
+ const char *arg = argv[1];
if (!strcmp(arg, "-a") || !strcmp(arg, "--all"))
show_all = 1;
else
@@ -49,5 +47,5 @@ int main(int argc, char **argv)
rev2 = lookup_commit_reference(rev2key);
if (!rev1 || !rev2)
return 1;
- return merge_base(rev1, rev2);
+ return show_merge_base(rev1, rev2, show_all);
}
diff --git a/builtin-name-rev.c b/builtin-name-rev.c
index b4f15cc38..c02222436 100644
--- a/builtin-name-rev.c
+++ b/builtin-name-rev.c
@@ -5,7 +5,7 @@
#include "refs.h"
static const char name_rev_usage[] =
- "git-name-rev [--tags] ( --all | --stdin | committish [committish...] )\n";
+ "git-name-rev [--tags | --refs=<pattern>] ( --all | --stdin | committish [committish...] )\n";
typedef struct rev_name {
const char *tip_name;
@@ -57,13 +57,17 @@ copy_data:
parents;
parents = parents->next, parent_number++) {
if (parent_number > 1) {
- char *new_name = xmalloc(strlen(tip_name)+8);
+ int len = strlen(tip_name);
+ char *new_name = xmalloc(len + 8);
+ if (len > 2 && !strcmp(tip_name + len - 2, "^0"))
+ len -= 2;
if (generation > 0)
- sprintf(new_name, "%s~%d^%d", tip_name,
+ sprintf(new_name, "%.*s~%d^%d", len, tip_name,
generation, parent_number);
else
- sprintf(new_name, "%s^%d", tip_name, parent_number);
+ sprintf(new_name, "%.*s^%d", len, tip_name,
+ parent_number);
name_rev(parents->item, new_name,
merge_traversals + 1 , 0, 0);
@@ -74,13 +78,21 @@ copy_data:
}
}
+struct name_ref_data {
+ int tags_only;
+ const char *ref_filter;
+};
+
static int name_ref(const char *path, const unsigned char *sha1, int flags, void *cb_data)
{
struct object *o = parse_object(sha1);
- int tags_only = *(int*)cb_data;
+ struct name_ref_data *data = cb_data;
int deref = 0;
- if (tags_only && strncmp(path, "refs/tags/", 10))
+ if (data->tags_only && prefixcmp(path, "refs/tags/"))
+ return 0;
+
+ if (data->ref_filter && fnmatch(data->ref_filter, path, 0))
return 0;
while (o && o->type == OBJ_TAG) {
@@ -93,9 +105,9 @@ static int name_ref(const char *path, const unsigned char *sha1, int flags, void
if (o && o->type == OBJ_COMMIT) {
struct commit *commit = (struct commit *)o;
- if (!strncmp(path, "refs/heads/", 11))
+ if (!prefixcmp(path, "refs/heads/"))
path = path + 11;
- else if (!strncmp(path, "refs/", 5))
+ else if (!prefixcmp(path, "refs/"))
path = path + 5;
name_rev(commit, xstrdup(path), 0, 0, deref);
@@ -119,17 +131,22 @@ static const char* get_rev_name(struct object *o)
if (!n->generation)
return n->tip_name;
-
- snprintf(buffer, sizeof(buffer), "%s~%d", n->tip_name, n->generation);
-
- return buffer;
+ else {
+ int len = strlen(n->tip_name);
+ if (len > 2 && !strcmp(n->tip_name + len - 2, "^0"))
+ len -= 2;
+ snprintf(buffer, sizeof(buffer), "%.*s~%d", len, n->tip_name,
+ n->generation);
+
+ return buffer;
+ }
}
int cmd_name_rev(int argc, const char **argv, const char *prefix)
{
struct object_array revs = { 0, 0, NULL };
int as_is = 0, all = 0, transform_stdin = 0;
- int tags_only = 0;
+ struct name_ref_data data = { 0, NULL };
git_config(git_default_config);
@@ -146,7 +163,10 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
as_is = 1;
continue;
} else if (!strcmp(*argv, "--tags")) {
- tags_only = 1;
+ data.tags_only = 1;
+ continue;
+ } else if (!prefixcmp(*argv, "--refs=")) {
+ data.ref_filter = *argv + 7;
continue;
} else if (!strcmp(*argv, "--all")) {
if (argc > 1)
@@ -185,7 +205,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
add_object_array((struct object *)commit, *argv, &revs);
}
- for_each_ref(name_ref, &tags_only);
+ for_each_ref(name_ref, &data);
if (transform_stdin) {
char buffer[2048];
diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
index 3824ee33a..b5ed9ce2c 100644
--- a/builtin-pack-objects.c
+++ b/builtin-pack-objects.c
@@ -1579,14 +1579,14 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
incremental = 1;
continue;
}
- if (!strncmp("--window=", arg, 9)) {
+ if (!prefixcmp(arg, "--window=")) {
char *end;
window = strtoul(arg+9, &end, 0);
if (!arg[9] || *end)
usage(pack_usage);
continue;
}
- if (!strncmp("--depth=", arg, 8)) {
+ if (!prefixcmp(arg, "--depth=")) {
char *end;
depth = strtoul(arg+8, &end, 0);
if (!arg[8] || *end)
@@ -1622,7 +1622,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
continue;
}
if (!strcmp("--unpacked", arg) ||
- !strncmp("--unpacked=", arg, 11) ||
+ !prefixcmp(arg, "--unpacked=") ||
!strcmp("--reflog", arg) ||
!strcmp("--all", arg)) {
use_internal_rev_list = 1;
diff --git a/builtin-pack-refs.c b/builtin-pack-refs.c
index 3de9b3eef..d080e30d6 100644
--- a/builtin-pack-refs.c
+++ b/builtin-pack-refs.c
@@ -36,7 +36,7 @@ static int handle_one_ref(const char *path, const unsigned char *sha1,
/* Do not pack the symbolic refs */
if ((flags & REF_ISSYMREF))
return 0;
- is_tag_ref = !strncmp(path, "refs/tags/", 10);
+ is_tag_ref = !prefixcmp(path, "refs/tags/");
/* ALWAYS pack refs that were already packed or are tags */
if (!cb->all && !is_tag_ref && !(flags & REF_ISPACKED))
diff --git a/builtin-push.c b/builtin-push.c
index c45649e26..979efcc45 100644
--- a/builtin-push.c
+++ b/builtin-push.c
@@ -32,7 +32,7 @@ static int expand_one_ref(const char *ref, const unsigned char *sha1, int flag,
/* Ignore the "refs/" at the beginning of the refname */
ref += 5;
- if (!strncmp(ref, "tags/", 5))
+ if (!prefixcmp(ref, "tags/"))
add_refspec(xstrdup(ref));
return 0;
}
@@ -149,10 +149,10 @@ static int get_remotes_uri(const char *repo, const char *uri[MAX_URI])
int is_refspec;
char *s, *p;
- if (!strncmp("URL:", buffer, 4)) {
+ if (!prefixcmp(buffer, "URL:")) {
is_refspec = 0;
s = buffer + 4;
- } else if (!strncmp("Push:", buffer, 5)) {
+ } else if (!prefixcmp(buffer, "Push:")) {
is_refspec = 1;
s = buffer + 5;
} else
@@ -195,7 +195,7 @@ static int config_get_receivepack;
static int get_remote_config(const char* key, const char* value)
{
- if (!strncmp(key, "remote.", 7) &&
+ if (!prefixcmp(key, "remote.") &&
!strncmp(key + 7, config_repo, config_repo_len)) {
if (!strcmp(key + 7 + config_repo_len, ".url")) {
if (config_current_uri < MAX_URI)
@@ -324,8 +324,8 @@ static int do_push(const char *repo)
const char **dest_refspec = refspec;
const char *dest = uri[i];
const char *sender = "git-send-pack";
- if (!strncmp(dest, "http://", 7) ||
- !strncmp(dest, "https://", 8))
+ if (!prefixcmp(dest, "http://") ||
+ !prefixcmp(dest, "https://"))
sender = "git-http-push";
else if (thin)
argv[dest_argc++] = "--thin";
@@ -373,7 +373,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
verbose=1;
continue;
}
- if (!strncmp(arg, "--repo=", 7)) {
+ if (!prefixcmp(arg, "--repo=")) {
repo = arg+7;
continue;
}
@@ -397,11 +397,11 @@ int cmd_push(int argc, const char **argv, const char *prefix)
thin = 0;
continue;
}
- if (!strncmp(arg, "--receive-pack=", 15)) {
+ if (!prefixcmp(arg, "--receive-pack=")) {
receivepack = arg;
continue;
}
- if (!strncmp(arg, "--exec=", 7)) {
+ if (!prefixcmp(arg, "--exec=")) {
receivepack = arg;
continue;
}
diff --git a/builtin-read-tree.c b/builtin-read-tree.c
index 8ba436dba..e47715538 100644
--- a/builtin-read-tree.c
+++ b/builtin-read-tree.c
@@ -133,7 +133,7 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
* entries and put the entries from the tree under the
* given subdirectory.
*/
- if (!strncmp(arg, "--prefix=", 9)) {
+ if (!prefixcmp(arg, "--prefix=")) {
if (stage || opts.merge || opts.prefix)
usage(read_tree_usage);
opts.prefix = arg + 9;
@@ -179,7 +179,7 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
continue;
}
- if (!strncmp(arg, "--exclude-per-directory=", 24)) {
+ if (!prefixcmp(arg, "--exclude-per-directory=")) {
struct dir_struct *dir;
if (opts.dir)
diff --git a/builtin-reflog.c b/builtin-reflog.c
index 65b845b44..cefb40da8 100644
--- a/builtin-reflog.c
+++ b/builtin-reflog.c
@@ -215,8 +215,8 @@ static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
old = lookup_commit_reference_gently(osha1, 1);
if (!new && !is_null_sha1(nsha1))
new = lookup_commit_reference_gently(nsha1, 1);
- if ((old && !in_merge_bases(old, cb->ref_commit)) ||
- (new && !in_merge_bases(new, cb->ref_commit)))
+ if ((old && !in_merge_bases(old, &cb->ref_commit, 1)) ||
+ (new && !in_merge_bases(new, &cb->ref_commit, 1)))
goto prune;
}
@@ -321,9 +321,9 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
const char *arg = argv[i];
if (!strcmp(arg, "--dry-run") || !strcmp(arg, "-n"))
cb.dry_run = 1;
- else if (!strncmp(arg, "--expire=", 9))
+ else if (!prefixcmp(arg, "--expire="))
cb.expire_total = approxidate(arg + 9);
- else if (!strncmp(arg, "--expire-unreachable=", 21))
+ else if (!prefixcmp(arg, "--expire-unreachable="))
cb.expire_unreachable = approxidate(arg + 21);
else if (!strcmp(arg, "--stale-fix"))
cb.stalefix = 1;
diff --git a/builtin-rerere.c b/builtin-rerere.c
index 318d959d8..dd1d4c1c1 100644
--- a/builtin-rerere.c
+++ b/builtin-rerere.c
@@ -105,11 +105,11 @@ static int handle_file(const char *path,
SHA1_Init(&ctx);
while (fgets(buf, sizeof(buf), f)) {
- if (!strncmp("<<<<<<< ", buf, 8))
+ if (!prefixcmp(buf, "<<<<<<< "))
hunk = 1;
- else if (!strncmp("=======", buf, 7))
+ else if (!prefixcmp(buf, "======="))
hunk = 2;
- else if (!strncmp(">>>>>>> ", buf, 8)) {
+ else if (!prefixcmp(buf, ">>>>>>> ")) {
hunk_no++;
hunk = 0;
if (memcmp(one->ptr, two->ptr, one->nr < two->nr ?
diff --git a/builtin-rev-list.c b/builtin-rev-list.c
index 1bb3a0668..c2db5a5b0 100644
--- a/builtin-rev-list.c
+++ b/builtin-rev-list.c
@@ -226,6 +226,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
int i;
int read_from_stdin = 0;
+ git_config(git_default_config);
init_revisions(&revs, prefix);
revs.abbrev = 0;
revs.commit_format = CMIT_FMT_UNSPECIFIED;
diff --git a/builtin-rev-parse.c b/builtin-rev-parse.c
index d53deaa36..37addb25f 100644
--- a/builtin-rev-parse.c
+++ b/builtin-rev-parse.c
@@ -233,7 +233,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
}
continue;
}
- if (!strncmp(arg,"-n",2)) {
+ if (!prefixcmp(arg, "-n")) {
if ((filter & DO_FLAGS) && (filter & DO_REVS))
show(arg);
continue;
@@ -274,7 +274,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
continue;
}
if (!strcmp(arg, "--short") ||
- !strncmp(arg, "--short=", 8)) {
+ !prefixcmp(arg, "--short=")) {
filter &= ~(DO_FLAGS|DO_NOREV);
verify = 1;
abbrev = DEFAULT_ABBREV;
@@ -352,19 +352,19 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
: "false");
continue;
}
- if (!strncmp(arg, "--since=", 8)) {
+ if (!prefixcmp(arg, "--since=")) {
show_datestring("--max-age=", arg+8);
continue;
}
- if (!strncmp(arg, "--after=", 8)) {
+ if (!prefixcmp(arg, "--after=")) {
show_datestring("--max-age=", arg+8);
continue;
}
- if (!strncmp(arg, "--before=", 9)) {
+ if (!prefixcmp(arg, "--before=")) {
show_datestring("--min-age=", arg+9);
continue;
}
- if (!strncmp(arg, "--until=", 8)) {
+ if (!prefixcmp(arg, "--until=")) {
show_datestring("--min-age=", arg+8);
continue;
}
diff --git a/builtin-shortlog.c b/builtin-shortlog.c
index edb40429e..2f71a2a6e 100644
--- a/builtin-shortlog.c
+++ b/builtin-shortlog.c
@@ -124,7 +124,7 @@ static void insert_author_oneline(struct path_list *list,
else
free(buffer);
- if (!strncmp(oneline, "[PATCH", 6)) {
+ if (!prefixcmp(oneline, "[PATCH")) {
char *eob = strchr(oneline, ']');
if (eob) {
@@ -179,7 +179,7 @@ static void read_from_stdin(struct path_list *list)
while (fgets(buffer, sizeof(buffer), stdin) != NULL) {
char *bob;
if ((buffer[0] == 'A' || buffer[0] == 'a') &&
- !strncmp(buffer + 1, "uthor: ", 7) &&
+ !prefixcmp(buffer + 1, "uthor: ") &&
(bob = strchr(buffer + 7, '<')) != NULL) {
char buffer2[1024], offset = 0;
@@ -230,7 +230,7 @@ static void get_from_rev(struct rev_info *rev, struct path_list *list)
else
eol++;
- if (!strncmp(buffer, "author ", 7)) {
+ if (!prefixcmp(buffer, "author ")) {
char *bracket = strchr(buffer, '<');
if (bracket == NULL || bracket > eol)
diff --git a/builtin-show-branch.c b/builtin-show-branch.c
index 0d94e40df..67ae6bacd 100644
--- a/builtin-show-branch.c
+++ b/builtin-show-branch.c
@@ -266,7 +266,7 @@ static void show_one_commit(struct commit *commit, int no_name)
pretty, sizeof(pretty), 0, NULL, NULL, 0);
else
strcpy(pretty, "(unavailable)");
- if (!strncmp(pretty, "[PATCH] ", 8))
+ if (!prefixcmp(pretty, "[PATCH] "))
cp = pretty + 8;
else
cp = pretty;
@@ -378,7 +378,7 @@ static int append_head_ref(const char *refname, const unsigned char *sha1, int f
{
unsigned char tmp[20];
int ofs = 11;
- if (strncmp(refname, "refs/heads/", ofs))
+ if (prefixcmp(refname, "refs/heads/"))
return 0;
/* If both heads/foo and tags/foo exists, get_sha1 would
* get confused.
@@ -392,7 +392,7 @@ static int append_remote_ref(const char *refname, const unsigned char *sha1, int
{
unsigned char tmp[20];
int ofs = 13;
- if (strncmp(refname, "refs/remotes/", ofs))
+ if (prefixcmp(refname, "refs/remotes/"))
return 0;
/* If both heads/foo and tags/foo exists, get_sha1 would
* get confused.
@@ -404,7 +404,7 @@ static int append_remote_ref(const char *refname, const unsigned char *sha1, int
static int append_tag_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
{
- if (strncmp(refname, "refs/tags/", 10))
+ if (prefixcmp(refname, "refs/tags/"))
return 0;
return append_ref(refname + 5, sha1, 0);
}
@@ -435,9 +435,9 @@ static int append_matching_ref(const char *refname, const unsigned char *sha1, i
return 0;
if (fnmatch(match_ref_pattern, tail, 0))
return 0;
- if (!strncmp("refs/heads/", refname, 11))
+ if (!prefixcmp(refname, "refs/heads/"))
return append_head_ref(refname, sha1, flag, cb_data);
- if (!strncmp("refs/tags/", refname, 10))
+ if (!prefixcmp(refname, "refs/tags/"))
return append_tag_ref(refname, sha1, flag, cb_data);
return append_ref(refname, sha1, 0);
}
@@ -462,11 +462,11 @@ static int rev_is_head(char *head, int headlen, char *name,
if ((!head[0]) ||
(head_sha1 && sha1 && hashcmp(head_sha1, sha1)))
return 0;
- if (!strncmp(head, "refs/heads/", 11))
+ if (!prefixcmp(head, "refs/heads/"))
head += 11;
- if (!strncmp(name, "refs/heads/", 11))
+ if (!prefixcmp(name, "refs/heads/"))
name += 11;
- else if (!strncmp(name, "heads/", 6))
+ else if (!prefixcmp(name, "heads/"))
name += 6;
return !strcmp(head, name);
}
@@ -635,7 +635,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
with_current_branch = 1;
else if (!strcmp(arg, "--sha1-name"))
sha1_name = 1;
- else if (!strncmp(arg, "--more=", 7))
+ else if (!prefixcmp(arg, "--more="))
extra = atoi(arg + 7);
else if (!strcmp(arg, "--merge-base"))
merge_base = 1;
@@ -652,9 +652,9 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
else if (!strcmp(arg, "--reflog") || !strcmp(arg, "-g")) {
reflog = DEFAULT_REFLOG;
}
- else if (!strncmp(arg, "--reflog=", 9))
+ else if (!prefixcmp(arg, "--reflog="))
parse_reflog_param(arg + 9, &reflog, &reflog_base);
- else if (!strncmp(arg, "-g=", 3))
+ else if (!prefixcmp(arg, "-g="))
parse_reflog_param(arg + 3, &reflog, &reflog_base);
else
usage(show_branch_usage);
diff --git a/builtin-show-ref.c b/builtin-show-ref.c
index 853f13f6a..ae0edddac 100644
--- a/builtin-show-ref.c
+++ b/builtin-show-ref.c
@@ -28,8 +28,8 @@ static int show_ref(const char *refname, const unsigned char *sha1, int flag, vo
if (tags_only || heads_only) {
int match;
- match = heads_only && !strncmp(refname, "refs/heads/", 11);
- match |= tags_only && !strncmp(refname, "refs/tags/", 10);
+ match = heads_only && !prefixcmp(refname, "refs/heads/");
+ match |= tags_only && !prefixcmp(refname, "refs/tags/");
if (!match)
return 0;
}
@@ -178,8 +178,8 @@ int cmd_show_ref(int argc, const char **argv, const char *prefix)
hash_only = 1;
continue;
}
- if (!strncmp(arg, "--hash=", 7) ||
- (!strncmp(arg, "--abbrev", 8) &&
+ if (!prefixcmp(arg, "--hash=") ||
+ (!prefixcmp(arg, "--abbrev") &&
(arg[8] == '=' || arg[8] == '\0'))) {
if (arg[2] != 'h' && !arg[8])
/* --abbrev only */
@@ -215,7 +215,7 @@ int cmd_show_ref(int argc, const char **argv, const char *prefix)
}
if (!strcmp(arg, "--exclude-existing"))
return exclude_existing(NULL);
- if (!strncmp(arg, "--exclude-existing=", 19))
+ if (!prefixcmp(arg, "--exclude-existing="))
return exclude_existing(arg + 19);
usage(show_ref_usage);
}
@@ -224,7 +224,7 @@ int cmd_show_ref(int argc, const char **argv, const char *prefix)
unsigned char sha1[20];
while (*pattern) {
- if (!strncmp(*pattern, "refs/", 5) &&
+ if (!prefixcmp(*pattern, "refs/") &&
resolve_ref(*pattern, sha1, 1, NULL)) {
if (!quiet)
show_one(*pattern, sha1);
diff --git a/builtin-tar-tree.c b/builtin-tar-tree.c
index 8055ddab9..b04719ef2 100644
--- a/builtin-tar-tree.c
+++ b/builtin-tar-tree.c
@@ -31,7 +31,7 @@ int cmd_tar_tree(int argc, const char **argv, const char *prefix)
nargv[nargc++] = "git-archive";
nargv[nargc++] = "--format=tar";
- if (2 <= argc && !strncmp("--remote=", argv[1], 9)) {
+ if (2 <= argc && !prefixcmp(argv[1], "--remote=")) {
nargv[nargc++] = argv[1];
argv++;
argc--;
diff --git a/builtin-unpack-objects.c b/builtin-unpack-objects.c
index d351e0264..8f8e89851 100644
--- a/builtin-unpack-objects.c
+++ b/builtin-unpack-objects.c
@@ -369,7 +369,7 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix)
recover = 1;
continue;
}
- if (!strncmp(arg, "--pack_header=", 14)) {
+ if (!prefixcmp(arg, "--pack_header=")) {
struct pack_header *hdr;
char *c;
diff --git a/builtin-update-index.c b/builtin-update-index.c
index 1ac613a78..772aaba7b 100644
--- a/builtin-update-index.c
+++ b/builtin-update-index.c
@@ -109,16 +109,17 @@ static int add_file_to_cache(const char *path)
ce->ce_flags = htons(namelen);
fill_stat_cache_info(ce, &st);
- ce->ce_mode = create_ce_mode(st.st_mode);
- if (!trust_executable_bit) {
+ if (trust_executable_bit)
+ ce->ce_mode = create_ce_mode(st.st_mode);
+ else {
/* If there is an existing entry, pick the mode bits
* from it, otherwise assume unexecutable.
*/
+ struct cache_entry *ent;
int pos = cache_name_pos(path, namelen);
- if (0 <= pos)
- ce->ce_mode = active_cache[pos]->ce_mode;
- else if (S_ISREG(st.st_mode))
- ce->ce_mode = create_ce_mode(S_IFREG | 0666);
+
+ ent = (0 <= pos) ? active_cache[pos] : NULL;
+ ce->ce_mode = ce_mode_from_stat(ent, st.st_mode);
}
if (index_path(ce->sha1, path, &st, !info_only))
diff --git a/builtin-write-tree.c b/builtin-write-tree.c
index 50670dc7b..90fc1cfcf 100644
--- a/builtin-write-tree.c
+++ b/builtin-write-tree.c
@@ -70,7 +70,7 @@ int cmd_write_tree(int argc, const char **argv, const char *unused_prefix)
const char *arg = argv[1];
if (!strcmp(arg, "--missing-ok"))
missing_ok = 1;
- else if (!strncmp(arg, "--prefix=", 9))
+ else if (!prefixcmp(arg, "--prefix="))
prefix = arg + 9;
else
usage(write_tree_usage);
diff --git a/builtin.h b/builtin.h
index 5108fd2d7..57e8741ff 100644
--- a/builtin.h
+++ b/builtin.h
@@ -29,7 +29,6 @@ extern int cmd_describe(int argc, const char **argv, const char *prefix);
extern int cmd_diff_files(int argc, const char **argv, const char *prefix);
extern int cmd_diff_index(int argc, const char **argv, const char *prefix);
extern int cmd_diff(int argc, const char **argv, const char *prefix);
-extern int cmd_diff_stages(int argc, const char **argv, const char *prefix);
extern int cmd_diff_tree(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_for_each_ref(int argc, const char **argv, const char *prefix);
@@ -45,6 +44,7 @@ extern int cmd_ls_files(int argc, const char **argv, const char *prefix);
extern int cmd_ls_tree(int argc, const char **argv, const char *prefix);
extern int cmd_mailinfo(int argc, const char **argv, const char *prefix);
extern int cmd_mailsplit(int argc, const char **argv, const char *prefix);
+extern int cmd_merge_base(int argc, const char **argv, const char *prefix);
extern int cmd_merge_file(int argc, const char **argv, const char *prefix);
extern int cmd_mv(int argc, const char **argv, const char *prefix);
extern int cmd_name_rev(int argc, const char **argv, const char *prefix);
diff --git a/cache.h b/cache.h
index c62b0b090..8bbc14299 100644
--- a/cache.h
+++ b/cache.h
@@ -106,6 +106,16 @@ static inline unsigned int create_ce_mode(unsigned int mode)
return htonl(S_IFLNK);
return htonl(S_IFREG | ce_permissions(mode));
}
+static inline unsigned int ce_mode_from_stat(struct cache_entry *ce, unsigned int mode)
+{
+ extern int trust_executable_bit;
+ if (!trust_executable_bit && S_ISREG(mode)) {
+ if (ce && S_ISREG(ntohl(ce->ce_mode)))
+ return ce->ce_mode;
+ return create_ce_mode(0666);
+ }
+ return create_ce_mode(mode);
+}
#define canon_mode(mode) \
(S_ISREG(mode) ? (S_IFREG | ce_permissions(mode)) : \
S_ISLNK(mode) ? S_IFLNK : S_IFDIR)
@@ -201,6 +211,7 @@ extern const char *apply_default_whitespace;
extern int zlib_compression_level;
extern size_t packed_git_window_size;
extern size_t packed_git_limit;
+extern int auto_crlf;
#define GIT_REPO_VERSION 0
extern int repository_format_version;
@@ -468,4 +479,8 @@ extern int nfvasprintf(char **str, const char *fmt, va_list va);
extern void trace_printf(const char *format, ...);
extern void trace_argv_printf(const char **argv, int count, const char *format, ...);
+/* convert.c */
+extern int convert_to_git(const char *path, char **bufp, unsigned long *sizep);
+extern int convert_to_working_tree(const char *path, char **bufp, unsigned long *sizep);
+
#endif /* CACHE_H */
diff --git a/commit.c b/commit.c
index 3e8c87294..8d279b0b6 100644
--- a/commit.c
+++ b/commit.c
@@ -1187,14 +1187,17 @@ struct commit_list *get_merge_bases(struct commit *one,
return result;
}
-int in_merge_bases(struct commit *rev1, struct commit *rev2)
+int in_merge_bases(struct commit *commit, struct commit **reference, int num)
{
struct commit_list *bases, *b;
int ret = 0;
- bases = get_merge_bases(rev1, rev2, 1);
+ if (num == 1)
+ bases = get_merge_bases(commit, *reference, 1);
+ else
+ die("not yet");
for (b = bases; b; b = b->next) {
- if (!hashcmp(rev1->object.sha1, b->item->object.sha1)) {
+ if (!hashcmp(commit->object.sha1, b->item->object.sha1)) {
ret = 1;
break;
}
diff --git a/commit.h b/commit.h
index 491b0c4aa..c73744463 100644
--- a/commit.h
+++ b/commit.h
@@ -114,5 +114,5 @@ 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);
-int in_merge_bases(struct commit *rev1, struct commit *rev2);
+int in_merge_bases(struct commit *, struct commit **, int);
#endif /* COMMIT_H */
diff --git a/compat/strtoumax.c b/compat/strtoumax.c
new file mode 100644
index 000000000..5541353a7
--- /dev/null
+++ b/compat/strtoumax.c
@@ -0,0 +1,10 @@
+#include "../git-compat-util.h"
+
+uintmax_t gitstrtoumax (const char *nptr, char **endptr, int base)
+{
+#if defined(NO_STRTOULL)
+ return strtoul(nptr, endptr, base);
+#else
+ return strtoull(nptr, endptr, base);
+#endif
+}
diff --git a/config.c b/config.c
index d82107124..8b6cf1aaa 100644
--- a/config.c
+++ b/config.c
@@ -310,12 +310,14 @@ int git_default_config(const char *var, const char *value)
}
if (!strcmp(var, "core.packedgitwindowsize")) {
- int pgsz = getpagesize();
+ int pgsz_x2 = getpagesize() * 2;
packed_git_window_size = git_config_int(var, value);
- packed_git_window_size /= pgsz;
- if (packed_git_window_size < 2)
- packed_git_window_size = 2;
- packed_git_window_size *= pgsz;
+
+ /* This value must be multiple of (pagesize * 2) */
+ packed_git_window_size /= pgsz_x2;
+ if (packed_git_window_size < 1)
+ packed_git_window_size = 1;
+ packed_git_window_size *= pgsz_x2;
return 0;
}
@@ -324,6 +326,15 @@ int git_default_config(const char *var, const char *value)
return 0;
}
+ if (!strcmp(var, "core.autocrlf")) {
+ if (value && !strcasecmp(value, "input")) {
+ auto_crlf = -1;
+ return 0;
+ }
+ auto_crlf = git_config_bool(var, value);
+ return 0;
+ }
+
if (!strcmp(var, "user.name")) {
strlcpy(git_default_name, value, sizeof(git_default_name));
return 0;
diff --git a/configure.ac b/configure.ac
index 7cfb3a066..3a8e778de 100644
--- a/configure.ac
+++ b/configure.ac
@@ -114,13 +114,32 @@ AC_CHECK_LIB([expat], [XML_ParserCreate],
[NO_EXPAT=YesPlease])
AC_SUBST(NO_EXPAT)
#
-# Define NEEDS_LIBICONV if linking with libc is not enough (Darwin).
+# Define NEEDS_LIBICONV if linking with libc is not enough (Darwin and
+# some Solaris installations).
# Define NO_ICONV if neither libc nor libiconv support iconv.
-AC_CHECK_LIB([c], [iconv],
- [NEEDS_LIBICONV=],
- AC_CHECK_LIB([iconv], [iconv],
- [NEEDS_LIBICONV=YesPlease],
- [NO_ICONV=YesPlease]))
+AC_DEFUN([ICONVTEST_SRC], [
+#include <iconv.h>
+
+int main(void)
+{
+ iconv_open("", "");
+ return 0;
+}
+])
+AC_MSG_CHECKING([for iconv in -lc])
+AC_LINK_IFELSE(ICONVTEST_SRC,
+ [AC_MSG_RESULT([yes])
+ NEEDS_LIBICONV=],
+ [AC_MSG_RESULT([no])
+ old_LIBS="$LIBS"
+ LIBS="$LIBS -liconv"
+ AC_MSG_CHECKING([for iconv in -liconv])
+ AC_LINK_IFELSE(ICONVTEST_SRC,
+ [AC_MSG_RESULT([yes])
+ NEEDS_LIBICONV=YesPlease],
+ [AC_MSG_RESULT([no])
+ NO_ICONV=YesPlease])
+ LIBS="$old_LIBS"])
AC_SUBST(NEEDS_LIBICONV)
AC_SUBST(NO_ICONV)
test -n "$NEEDS_LIBICONV" && LIBS="$LIBS -liconv"
diff --git a/connect.c b/connect.c
index 78448889d..8a8a13bb7 100644
--- a/connect.c
+++ b/connect.c
@@ -96,7 +96,7 @@ int get_ack(int fd, unsigned char *result_sha1)
line[--len] = 0;
if (!strcmp(line, "NAK"))
return 0;
- if (!strncmp(line, "ACK ", 4)) {
+ if (!prefixcmp(line, "ACK ")) {
if (!get_sha1_hex(line+4, result_sha1)) {
if (strstr(line+45, "continue"))
return 2;
@@ -196,8 +196,8 @@ static int count_refspec_match(const char *pattern,
*/
if (namelen != patlen &&
patlen != namelen - 5 &&
- strncmp(name, "refs/heads/", 11) &&
- strncmp(name, "refs/tags/", 10)) {
+ prefixcmp(name, "refs/heads/") &&
+ prefixcmp(name, "refs/tags/")) {
/* We want to catch the case where only weak
* matches are found and there are multiple
* matches, and where more than one strong
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 5d3d40205..7c0340348 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -269,7 +269,6 @@ __git_commands ()
cvsimport) : import;;
cvsserver) : daemon;;
daemon) : daemon;;
- diff-stages) : nobody uses it;;
fast-import) : import;;
fsck-objects) : plumbing;;
fetch-pack) : plumbing;;
@@ -298,7 +297,6 @@ __git_commands ()
reflog) : plumbing;;
repo-config) : plumbing;;
rerere) : plumbing;;
- resolve) : dead dont use;;
rev-list) : plumbing;;
rev-parse) : plumbing;;
runstatus) : plumbing;;
diff --git a/git-resolve.sh b/contrib/examples/git-resolve.sh
index 36b90e384..36b90e384 100755
--- a/git-resolve.sh
+++ b/contrib/examples/git-resolve.sh
diff --git a/contrib/fast-import/import-tars.perl b/contrib/fast-import/import-tars.perl
index 990c9e70b..5585a8b2c 100755
--- a/contrib/fast-import/import-tars.perl
+++ b/contrib/fast-import/import-tars.perl
@@ -25,11 +25,14 @@ foreach my $tar_file (@ARGV)
my $tar_name = $1;
if ($tar_name =~ s/\.(tar\.gz|tgz)$//) {
- open(I, '-|', 'gzcat', $tar_file) or die "Unable to gzcat $tar_file: $!\n";
+ open(I, '-|', 'gunzip', '-c', $tar_file)
+ or die "Unable to gunzip -c $tar_file: $!\n";
} elsif ($tar_name =~ s/\.(tar\.bz2|tbz2)$//) {
- open(I, '-|', 'bzcat', $tar_file) or die "Unable to bzcat $tar_file: $!\n";
+ open(I, '-|', 'bunzip2', '-c', $tar_file)
+ or die "Unable to bunzip2 -c $tar_file: $!\n";
} elsif ($tar_name =~ s/\.tar\.Z$//) {
- open(I, '-|', 'zcat', $tar_file) or die "Unable to zcat $tar_file: $!\n";
+ open(I, '-|', 'uncompress', '-c', $tar_file)
+ or die "Unable to uncompress -c $tar_file: $!\n";
} elsif ($tar_name =~ s/\.tar$//) {
open(I, $tar_file) or die "Unable to open $tar_file: $!\n";
} else {
diff --git a/convert.c b/convert.c
new file mode 100644
index 000000000..898bfe3eb
--- /dev/null
+++ b/convert.c
@@ -0,0 +1,186 @@
+#include "cache.h"
+/*
+ * convert.c - convert a file when checking it out and checking it in.
+ *
+ * This should use the pathname to decide on whether it wants to do some
+ * more interesting conversions (automatic gzip/unzip, general format
+ * conversions etc etc), but by default it just does automatic CRLF<->LF
+ * translation when the "auto_crlf" option is set.
+ */
+
+struct text_stat {
+ /* CR, LF and CRLF counts */
+ unsigned cr, lf, crlf;
+
+ /* These are just approximations! */
+ unsigned printable, nonprintable;
+};
+
+static void gather_stats(const char *buf, unsigned long size, struct text_stat *stats)
+{
+ unsigned long i;
+
+ memset(stats, 0, sizeof(*stats));
+
+ for (i = 0; i < size; i++) {
+ unsigned char c = buf[i];
+ if (c == '\r') {
+ stats->cr++;
+ if (i+1 < size && buf[i+1] == '\n')
+ stats->crlf++;
+ continue;
+ }
+ if (c == '\n') {
+ stats->lf++;
+ continue;
+ }
+ if (c == 127)
+ /* DEL */
+ stats->nonprintable++;
+ else if (c < 32) {
+ switch (c) {
+ /* BS, HT, ESC and FF */
+ case '\b': case '\t': case '\033': case '\014':
+ stats->printable++;
+ break;
+ default:
+ stats->nonprintable++;
+ }
+ }
+ else
+ stats->printable++;
+ }
+}
+
+/*
+ * The same heuristics as diff.c::mmfile_is_binary()
+ */
+static int is_binary(unsigned long size, struct text_stat *stats)
+{
+
+ if ((stats->printable >> 7) < stats->nonprintable)
+ return 1;
+ /*
+ * Other heuristics? Average line length might be relevant,
+ * as might LF vs CR vs CRLF counts..
+ *
+ * NOTE! It might be normal to have a low ratio of CRLF to LF
+ * (somebody starts with a LF-only file and edits it with an editor
+ * that adds CRLF only to lines that are added..). But do we
+ * want to support CR-only? Probably not.
+ */
+ return 0;
+}
+
+int convert_to_git(const char *path, char **bufp, unsigned long *sizep)
+{
+ char *buffer, *nbuf;
+ unsigned long size, nsize;
+ struct text_stat stats;
+
+ /*
+ * FIXME! Other pluggable conversions should go here,
+ * based on filename patterns. Right now we just do the
+ * stupid auto-CRLF one.
+ */
+ if (!auto_crlf)
+ return 0;
+
+ size = *sizep;
+ if (!size)
+ return 0;
+ buffer = *bufp;
+
+ gather_stats(buffer, size, &stats);
+
+ /* No CR? Nothing to convert, regardless. */
+ if (!stats.cr)
+ return 0;
+
+ /*
+ * We're currently not going to even try to convert stuff
+ * that has bare CR characters. Does anybody do that crazy
+ * stuff?
+ */
+ if (stats.cr != stats.crlf)
+ return 0;
+
+ /*
+ * And add some heuristics for binary vs text, of course...
+ */
+ if (is_binary(size, &stats))
+ return 0;
+
+ /*
+ * Ok, allocate a new buffer, fill it in, and return true
+ * to let the caller know that we switched buffers on it.
+ */
+ nsize = size - stats.crlf;
+ nbuf = xmalloc(nsize);
+ *bufp = nbuf;
+ *sizep = nsize;
+ do {
+ unsigned char c = *buffer++;
+ if (c != '\r')
+ *nbuf++ = c;
+ } while (--size);
+
+ return 1;
+}
+
+int convert_to_working_tree(const char *path, char **bufp, unsigned long *sizep)
+{
+ char *buffer, *nbuf;
+ unsigned long size, nsize;
+ struct text_stat stats;
+ unsigned char last;
+
+ /*
+ * FIXME! Other pluggable conversions should go here,
+ * based on filename patterns. Right now we just do the
+ * stupid auto-CRLF one.
+ */
+ if (auto_crlf <= 0)
+ return 0;
+
+ size = *sizep;
+ if (!size)
+ return 0;
+ buffer = *bufp;
+
+ gather_stats(buffer, size, &stats);
+
+ /* No LF? Nothing to convert, regardless. */
+ if (!stats.lf)
+ return 0;
+
+ /* Was it already in CRLF format? */
+ if (stats.lf == stats.crlf)
+ return 0;
+
+ /* If we have any bare CR characters, we're not going to touch it */
+ if (stats.cr != stats.crlf)
+ return 0;
+
+ if (is_binary(size, &stats))
+ return 0;
+
+ /*
+ * Ok, allocate a new buffer, fill it in, and return true
+ * to let the caller know that we switched buffers on it.
+ */
+ nsize = size + stats.lf - stats.crlf;
+ nbuf = xmalloc(nsize);
+ *bufp = nbuf;
+ *sizep = nsize;
+ last = 0;
+ do {
+ unsigned char c = *buffer++;
+ if (c == '\n' && last != '\r')
+ *nbuf++ = '\r';
+ *nbuf++ = c;
+ last = c;
+ } while (--size);
+
+ return 1;
+}
diff --git a/daemon.c b/daemon.c
index 2a20ca55c..e74ecac95 100644
--- a/daemon.c
+++ b/daemon.c
@@ -286,7 +286,7 @@ static int service_enabled;
static int git_daemon_config(const char *var, const char *value)
{
- if (!strncmp(var, "daemon.", 7) &&
+ if (!prefixcmp(var, "daemon.") &&
!strcmp(var + 7, service_looking_at->config_name)) {
service_enabled = git_config_bool(var, value);
return 0;
@@ -562,7 +562,7 @@ static int execute(struct sockaddr *addr)
for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
struct daemon_service *s = &(daemon_service[i]);
int namelen = strlen(s->name);
- if (!strncmp("git-", line, 4) &&
+ if (!prefixcmp(line, "git-") &&
!strncmp(s->name, line + 4, namelen) &&
line[namelen + 4] == ' ') {
/*
@@ -773,6 +773,7 @@ static int socksetup(char *listen_addr, int listen_port, int **socklist_p)
char pbuf[NI_MAXSERV];
struct addrinfo hints, *ai0, *ai;
int gai;
+ long flags;
sprintf(pbuf, "%d", listen_port);
memset(&hints, 0, sizeof(hints));
@@ -820,6 +821,10 @@ static int socksetup(char *listen_addr, int listen_port, int **socklist_p)
continue; /* not fatal */
}
+ flags = fcntl(sockfd, F_GETFD, 0);
+ if (flags >= 0)
+ fcntl(sockfd, F_SETFD, flags | FD_CLOEXEC);
+
socklist = xrealloc(socklist, sizeof(int) * (socknum + 1));
socklist[socknum++] = sockfd;
@@ -839,6 +844,7 @@ static int socksetup(char *listen_addr, int listen_port, int **socklist_p)
{
struct sockaddr_in sin;
int sockfd;
+ long flags;
memset(&sin, 0, sizeof sin);
sin.sin_family = AF_INET;
@@ -871,6 +877,10 @@ static int socksetup(char *listen_addr, int listen_port, int **socklist_p)
return 0;
}
+ flags = fcntl(sockfd, F_GETFD, 0);
+ if (flags >= 0)
+ fcntl(sockfd, F_SETFD, flags | FD_CLOEXEC);
+
*socklist_p = xmalloc(sizeof(int));
**socklist_p = sockfd;
return 1;
@@ -1001,7 +1011,7 @@ int main(int argc, char **argv)
for (i = 1; i < argc; i++) {
char *arg = argv[i];
- if (!strncmp(arg, "--listen=", 9)) {
+ if (!prefixcmp(arg, "--listen=")) {
char *p = arg + 9;
char *ph = listen_addr = xmalloc(strlen(arg + 9) + 1);
while (*p)
@@ -1009,7 +1019,7 @@ int main(int argc, char **argv)
*ph = 0;
continue;
}
- if (!strncmp(arg, "--port=", 7)) {
+ if (!prefixcmp(arg, "--port=")) {
char *end;
unsigned long n;
n = strtoul(arg+7, &end, 0);
@@ -1035,11 +1045,11 @@ int main(int argc, char **argv)
export_all_trees = 1;
continue;
}
- if (!strncmp(arg, "--timeout=", 10)) {
+ if (!prefixcmp(arg, "--timeout=")) {
timeout = atoi(arg+10);
continue;
}
- if (!strncmp(arg, "--init-timeout=", 15)) {
+ if (!prefixcmp(arg, "--init-timeout=")) {
init_timeout = atoi(arg+15);
continue;
}
@@ -1047,11 +1057,11 @@ int main(int argc, char **argv)
strict_paths = 1;
continue;
}
- if (!strncmp(arg, "--base-path=", 12)) {
+ if (!prefixcmp(arg, "--base-path=")) {
base_path = arg+12;
continue;
}
- if (!strncmp(arg, "--interpolated-path=", 20)) {
+ if (!prefixcmp(arg, "--interpolated-path=")) {
interpolated_path = arg+20;
continue;
}
@@ -1063,11 +1073,11 @@ int main(int argc, char **argv)
user_path = "";
continue;
}
- if (!strncmp(arg, "--user-path=", 12)) {
+ if (!prefixcmp(arg, "--user-path=")) {
user_path = arg + 12;
continue;
}
- if (!strncmp(arg, "--pid-file=", 11)) {
+ if (!prefixcmp(arg, "--pid-file=")) {
pid_file = arg + 11;
continue;
}
@@ -1076,27 +1086,27 @@ int main(int argc, char **argv)
log_syslog = 1;
continue;
}
- if (!strncmp(arg, "--user=", 7)) {
+ if (!prefixcmp(arg, "--user=")) {
user_name = arg + 7;
continue;
}
- if (!strncmp(arg, "--group=", 8)) {
+ if (!prefixcmp(arg, "--group=")) {
group_name = arg + 8;
continue;
}
- if (!strncmp(arg, "--enable=", 9)) {
+ if (!prefixcmp(arg, "--enable=")) {
enable_service(arg + 9, 1);
continue;
}
- if (!strncmp(arg, "--disable=", 10)) {
+ if (!prefixcmp(arg, "--disable=")) {
enable_service(arg + 10, 0);
continue;
}
- if (!strncmp(arg, "--allow-override=", 17)) {
+ if (!prefixcmp(arg, "--allow-override=")) {
make_service_overridable(arg + 17, 1);
continue;
}
- if (!strncmp(arg, "--forbid-override=", 18)) {
+ if (!prefixcmp(arg, "--forbid-override=")) {
make_service_overridable(arg + 18, 0);
continue;
}
diff --git a/diff-lib.c b/diff-lib.c
index 91cd87742..556d5345b 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -170,9 +170,7 @@ static int get_stat_data(struct cache_entry *ce,
}
changed = ce_match_stat(ce, &st, 0);
if (changed) {
- mode = create_ce_mode(st.st_mode);
- if (!trust_executable_bit && S_ISREG(st.st_mode))
- mode = ce->ce_mode;
+ mode = ce_mode_from_stat(ce, st.st_mode);
sha1 = no_sha1;
}
}
diff --git a/diff.c b/diff.c
index 13b9b6c56..5ecb12225 100644
--- a/diff.c
+++ b/diff.c
@@ -77,7 +77,7 @@ int git_diff_ui_config(const char *var, const char *value)
diff_detect_rename_default = DIFF_DETECT_RENAME;
return 0;
}
- if (!strncmp(var, "diff.color.", 11) || !strncmp(var, "color.diff.", 11)) {
+ if (!prefixcmp(var, "diff.color.") || !prefixcmp(var, "color.diff.")) {
int slot = parse_diff_color_slot(var, 11);
color_parse(value, var, diff_colors[slot]);
return 0;
@@ -184,42 +184,59 @@ static void print_line_count(int count)
}
}
-static void copy_file(int prefix, const char *data, int size)
+static void copy_file(int prefix, const char *data, int size,
+ const char *set, const char *reset)
{
int ch, nl_just_seen = 1;
while (0 < size--) {
ch = *data++;
- if (nl_just_seen)
+ if (nl_just_seen) {
+ fputs(set, stdout);
putchar(prefix);
- putchar(ch);
- if (ch == '\n')
+ }
+ if (ch == '\n') {
nl_just_seen = 1;
- else
+ fputs(reset, stdout);
+ } else
nl_just_seen = 0;
+ putchar(ch);
}
if (!nl_just_seen)
- printf("\n\\ No newline at end of file\n");
+ printf("%s\n\\ No newline at end of file\n", reset);
}
static void emit_rewrite_diff(const char *name_a,
const char *name_b,
struct diff_filespec *one,
- struct diff_filespec *two)
+ struct diff_filespec *two,
+ int color_diff)
{
int lc_a, lc_b;
+ const char *name_a_tab, *name_b_tab;
+ const char *metainfo = diff_get_color(color_diff, DIFF_METAINFO);
+ const char *fraginfo = diff_get_color(color_diff, DIFF_FRAGINFO);
+ const char *old = diff_get_color(color_diff, DIFF_FILE_OLD);
+ const char *new = diff_get_color(color_diff, DIFF_FILE_NEW);
+ const char *reset = diff_get_color(color_diff, DIFF_RESET);
+
+ name_a_tab = strchr(name_a, ' ') ? "\t" : "";
+ name_b_tab = strchr(name_b, ' ') ? "\t" : "";
+
diff_populate_filespec(one, 0);
diff_populate_filespec(two, 0);
lc_a = count_lines(one->data, one->size);
lc_b = count_lines(two->data, two->size);
- printf("--- a/%s\n+++ b/%s\n@@ -", name_a, name_b);
+ printf("%s--- a/%s%s%s\n%s+++ b/%s%s%s\n%s@@ -",
+ metainfo, name_a, name_a_tab, reset,
+ metainfo, name_b, name_b_tab, reset, fraginfo);
print_line_count(lc_a);
printf(" +");
print_line_count(lc_b);
- printf(" @@\n");
+ printf(" @@%s\n", reset);
if (lc_a)
- copy_file('-', one->data, one->size);
+ copy_file('-', one->data, one->size, old, reset);
if (lc_b)
- copy_file('+', two->data, two->size);
+ copy_file('+', two->data, two->size, new, reset);
}
static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one)
@@ -398,22 +415,16 @@ static void emit_line(const char *set, const char *reset, const char *line, int
puts(reset);
}
-static void emit_add_line(const char *reset, struct emit_callback *ecbdata, const char *line, int len)
+static void emit_line_with_ws(int nparents,
+ const char *set, const char *reset, const char *ws,
+ const char *line, int len)
{
- int col0 = ecbdata->nparents;
+ int col0 = nparents;
int last_tab_in_indent = -1;
int last_space_in_indent = -1;
int i;
int tail = len;
int need_highlight_leading_space = 0;
- const char *ws = diff_get_color(ecbdata->color_diff, DIFF_WHITESPACE);
- const char *set = diff_get_color(ecbdata->color_diff, DIFF_FILE_NEW);
-
- if (!*ws) {
- emit_line(set, reset, line, len);
- return;
- }
-
/* The line is a newly added line. Does it have funny leading
* whitespaces? In indent, SP should never precede a TAB.
*/
@@ -468,6 +479,18 @@ static void emit_add_line(const char *reset, struct emit_callback *ecbdata, cons
emit_line(set, reset, line + i, len - i);
}
+static void emit_add_line(const char *reset, struct emit_callback *ecbdata, const char *line, int len)
+{
+ const char *ws = diff_get_color(ecbdata->color_diff, DIFF_WHITESPACE);
+ const char *set = diff_get_color(ecbdata->color_diff, DIFF_FILE_NEW);
+
+ if (!*ws)
+ emit_line(set, reset, line, len);
+ else
+ emit_line_with_ws(ecbdata->nparents, set, reset, ws,
+ line, len);
+}
+
static void fn_out_consume(void *priv, char *line, unsigned long len)
{
int i;
@@ -477,8 +500,15 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
const char *reset = diff_get_color(ecbdata->color_diff, DIFF_RESET);
if (ecbdata->label_path[0]) {
- printf("%s--- %s%s\n", set, ecbdata->label_path[0], reset);
- printf("%s+++ %s%s\n", set, ecbdata->label_path[1], reset);
+ const char *name_a_tab, *name_b_tab;
+
+ name_a_tab = strchr(ecbdata->label_path[0], ' ') ? "\t" : "";
+ name_b_tab = strchr(ecbdata->label_path[1], ' ') ? "\t" : "";
+
+ printf("%s--- %s%s%s\n",
+ set, ecbdata->label_path[0], reset, name_a_tab);
+ printf("%s+++ %s%s%s\n",
+ set, ecbdata->label_path[1], reset, name_b_tab);
ecbdata->label_path[0] = ecbdata->label_path[1] = NULL;
}
@@ -870,30 +900,44 @@ static void show_numstat(struct diffstat_t* data, struct diff_options *options)
struct checkdiff_t {
struct xdiff_emit_state xm;
const char *filename;
- int lineno;
+ int lineno, color_diff;
};
static void checkdiff_consume(void *priv, char *line, unsigned long len)
{
struct checkdiff_t *data = priv;
+ const char *ws = diff_get_color(data->color_diff, DIFF_WHITESPACE);
+ const char *reset = diff_get_color(data->color_diff, DIFF_RESET);
+ const char *set = diff_get_color(data->color_diff, DIFF_FILE_NEW);
if (line[0] == '+') {
- int i, spaces = 0;
+ int i, spaces = 0, space_before_tab = 0, white_space_at_end = 0;
/* check space before tab */
for (i = 1; i < len && (line[i] == ' ' || line[i] == '\t'); i++)
if (line[i] == ' ')
spaces++;
if (line[i - 1] == '\t' && spaces)
- printf("%s:%d: space before tab:%.*s\n",
- data->filename, data->lineno, (int)len, line);
+ space_before_tab = 1;
/* check white space at line end */
if (line[len - 1] == '\n')
len--;
if (isspace(line[len - 1]))
- printf("%s:%d: white space at end: %.*s\n",
- data->filename, data->lineno, (int)len, line);
+ white_space_at_end = 1;
+
+ if (space_before_tab || white_space_at_end) {
+ printf("%s:%d: %s", data->filename, data->lineno, ws);
+ if (space_before_tab) {
+ printf("space before tab");
+ if (white_space_at_end)
+ putchar(',');
+ }
+ if (white_space_at_end)
+ printf("white space at end");
+ printf(":%s ", reset);
+ emit_line_with_ws(1, set, reset, ws, line, len);
+ }
data->lineno++;
} else if (line[0] == ' ')
@@ -1050,7 +1094,8 @@ static void builtin_diff(const char *name_a,
if ((one->mode ^ two->mode) & S_IFMT)
goto free_ab_and_return;
if (complete_rewrite) {
- emit_rewrite_diff(name_a, name_b, one, two);
+ emit_rewrite_diff(name_a, name_b, one, two,
+ o->color_diff);
goto free_ab_and_return;
}
}
@@ -1085,9 +1130,9 @@ static void builtin_diff(const char *name_a,
xecfg.flags = XDL_EMIT_FUNCNAMES;
if (!diffopts)
;
- else if (!strncmp(diffopts, "--unified=", 10))
+ else if (!prefixcmp(diffopts, "--unified="))
xecfg.ctxlen = strtoul(diffopts + 10, NULL, 10);
- else if (!strncmp(diffopts, "-u", 2))
+ else if (!prefixcmp(diffopts, "-u"))
xecfg.ctxlen = strtoul(diffopts + 2, NULL, 10);
ecb.outf = xdiff_outf;
ecb.priv = &ecbdata;
@@ -1151,7 +1196,7 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
static void builtin_checkdiff(const char *name_a, const char *name_b,
struct diff_filespec *one,
- struct diff_filespec *two)
+ struct diff_filespec *two, struct diff_options *o)
{
mmfile_t mf1, mf2;
struct checkdiff_t data;
@@ -1163,6 +1208,7 @@ static void builtin_checkdiff(const char *name_a, const char *name_b,
data.xm.consume = checkdiff_consume;
data.filename = name_b ? name_b : name_a;
data.lineno = 0;
+ data.color_diff = o->color_diff;
if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
die("unable to read files to diff");
@@ -1332,6 +1378,9 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)
reuse_worktree_file(s->path, s->sha1, 0)) {
struct stat st;
int fd;
+ char *buf;
+ unsigned long size;
+
if (lstat(s->path, &st) < 0) {
if (errno == ENOENT) {
err_empty:
@@ -1364,7 +1413,19 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)
s->data = xmmap(NULL, s->size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
s->should_munmap = 1;
- /* FIXME! CRLF -> LF conversion goes here, based on "s->path" */
+
+ /*
+ * Convert from working tree format to canonical git format
+ */
+ buf = s->data;
+ size = s->size;
+ if (convert_to_git(s->path, &buf, &size)) {
+ munmap(s->data, s->size);
+ s->should_munmap = 0;
+ s->data = buf;
+ s->size = size;
+ s->should_free = 1;
+ }
}
else {
char type[20];
@@ -1773,7 +1834,7 @@ static void run_checkdiff(struct diff_filepair *p, struct diff_options *o)
diff_fill_sha1_info(p->one);
diff_fill_sha1_info(p->two);
- builtin_checkdiff(name, other, p->one, p->two);
+ builtin_checkdiff(name, other, p->one, p->two, o);
}
void diff_setup(struct diff_options *options)
@@ -1922,7 +1983,7 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
else if (!strcmp(arg, "--shortstat")) {
options->output_format |= DIFF_FORMAT_SHORTSTAT;
}
- else if (!strncmp(arg, "--stat", 6)) {
+ else if (!prefixcmp(arg, "--stat")) {
char *end;
int width = options->stat_width;
int name_width = options->stat_name_width;
@@ -1931,9 +1992,9 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
switch (*arg) {
case '-':
- if (!strncmp(arg, "-width=", 7))
+ if (!prefixcmp(arg, "-width="))
width = strtoul(arg + 7, &end, 10);
- else if (!strncmp(arg, "-name-width=", 12))
+ else if (!prefixcmp(arg, "-name-width="))
name_width = strtoul(arg + 12, &end, 10);
break;
case '=':
@@ -1958,7 +2019,7 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
}
else if (!strcmp(arg, "-z"))
options->line_termination = 0;
- else if (!strncmp(arg, "-l", 2))
+ else if (!prefixcmp(arg, "-l"))
options->rename_limit = strtoul(arg+2, NULL, 10);
else if (!strcmp(arg, "--full-index"))
options->full_index = 1;
@@ -1975,31 +2036,31 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
options->output_format |= DIFF_FORMAT_NAME_STATUS;
else if (!strcmp(arg, "-R"))
options->reverse_diff = 1;
- else if (!strncmp(arg, "-S", 2))
+ else if (!prefixcmp(arg, "-S"))
options->pickaxe = arg + 2;
else if (!strcmp(arg, "-s")) {
options->output_format |= DIFF_FORMAT_NO_OUTPUT;
}
- else if (!strncmp(arg, "-O", 2))
+ else if (!prefixcmp(arg, "-O"))
options->orderfile = arg + 2;
- else if (!strncmp(arg, "--diff-filter=", 14))
+ else if (!prefixcmp(arg, "--diff-filter="))
options->filter = arg + 14;
else if (!strcmp(arg, "--pickaxe-all"))
options->pickaxe_opts = DIFF_PICKAXE_ALL;
else if (!strcmp(arg, "--pickaxe-regex"))
options->pickaxe_opts = DIFF_PICKAXE_REGEX;
- else if (!strncmp(arg, "-B", 2)) {
+ else if (!prefixcmp(arg, "-B")) {
if ((options->break_opt =
diff_scoreopt_parse(arg)) == -1)
return -1;
}
- else if (!strncmp(arg, "-M", 2)) {
+ else if (!prefixcmp(arg, "-M")) {
if ((options->rename_score =
diff_scoreopt_parse(arg)) == -1)
return -1;
options->detect_rename = DIFF_DETECT_RENAME;
}
- else if (!strncmp(arg, "-C", 2)) {
+ else if (!prefixcmp(arg, "-C")) {
if ((options->rename_score =
diff_scoreopt_parse(arg)) == -1)
return -1;
@@ -2009,7 +2070,7 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
options->find_copies_harder = 1;
else if (!strcmp(arg, "--abbrev"))
options->abbrev = DEFAULT_ABBREV;
- else if (!strncmp(arg, "--abbrev=", 9)) {
+ else if (!prefixcmp(arg, "--abbrev=")) {
options->abbrev = strtoul(arg + 9, NULL, 10);
if (options->abbrev < MINIMUM_ABBREV)
options->abbrev = MINIMUM_ABBREV;
@@ -2024,6 +2085,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
options->xdl_opts |= XDF_IGNORE_WHITESPACE;
else if (!strcmp(arg, "-b") || !strcmp(arg, "--ignore-space-change"))
options->xdl_opts |= XDF_IGNORE_WHITESPACE_CHANGE;
+ else if (!strcmp(arg, "--ignore-space-at-eol"))
+ options->xdl_opts |= XDF_IGNORE_WHITESPACE_AT_EOL;
else if (!strcmp(arg, "--color-words"))
options->color_diff = options->color_diff_words = 1;
else if (!strcmp(arg, "--no-renames"))
@@ -2516,7 +2579,7 @@ static void patch_id_consume(void *priv, char *line, unsigned long len)
int new_len;
/* Ignore line numbers when computing the SHA1 of the patch */
- if (!strncmp(line, "@@ -", 4))
+ if (!prefixcmp(line, "@@ -"))
return;
new_len = remove_space(line, len);
diff --git a/entry.c b/entry.c
index c2641ddef..472a9ef32 100644
--- a/entry.c
+++ b/entry.c
@@ -78,6 +78,9 @@ static int write_entry(struct cache_entry *ce, char *path, struct checkout *stat
path, sha1_to_hex(ce->sha1));
}
switch (ntohl(ce->ce_mode) & S_IFMT) {
+ char *buf;
+ unsigned long nsize;
+
case S_IFREG:
if (to_tempfile) {
strcpy(path, ".merge_file_XXXXXX");
@@ -89,7 +92,18 @@ static int write_entry(struct cache_entry *ce, char *path, struct checkout *stat
return error("git-checkout-index: unable to create file %s (%s)",
path, strerror(errno));
}
- /* FIXME: LF -> CRLF conversion goes here, based on "ce->name" */
+
+ /*
+ * Convert from git internal format to working tree format
+ */
+ buf = new;
+ nsize = size;
+ if (convert_to_working_tree(ce->name, &buf, &nsize)) {
+ free(new);
+ new = buf;
+ size = nsize;
+ }
+
wrote = write_in_full(fd, new, size);
close(fd);
free(new);
diff --git a/environment.c b/environment.c
index 54c22f824..570e32ac3 100644
--- a/environment.c
+++ b/environment.c
@@ -28,6 +28,7 @@ size_t packed_git_window_size = DEFAULT_PACKED_GIT_WINDOW_SIZE;
size_t packed_git_limit = DEFAULT_PACKED_GIT_LIMIT;
int pager_in_use;
int pager_use_color = 1;
+int auto_crlf = 0; /* 1: both ways, -1: only when adding git objects */
static const char *git_dir;
static char *git_object_dir, *git_index_file, *git_refs_dir, *git_graft_file;
diff --git a/exec_cmd.c b/exec_cmd.c
index 3996bce33..9b74ed2f4 100644
--- a/exec_cmd.c
+++ b/exec_cmd.c
@@ -56,7 +56,7 @@ int execv_git_cmd(const char **argv)
len = strlen(git_command);
/* Trivial cleanup */
- while (!strncmp(exec_dir, "./", 2)) {
+ while (!prefixcmp(exec_dir, "./")) {
exec_dir += 2;
while (*exec_dir == '/')
exec_dir++;
diff --git a/fast-import.c b/fast-import.c
index fd3b11757..5d040fdb0 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -133,6 +133,10 @@ Format of STDIN stream:
#define PACK_ID_BITS 16
#define MAX_PACK_ID ((1<<PACK_ID_BITS)-1)
+#ifndef PRIuMAX
+#define PRIuMAX "llu"
+#endif
+
struct object_entry
{
struct object_entry *next;
@@ -475,7 +479,7 @@ static struct object_entry *find_mark(uintmax_t idnum)
oe = s->data.marked[idnum];
}
if (!oe)
- die("mark :%ju not declared", orig_idnum);
+ die("mark :%" PRIuMAX " not declared", orig_idnum);
return oe;
}
@@ -1308,7 +1312,7 @@ static int update_branch(struct branch *b)
return error("Branch %s is missing commits.", b->name);
}
- if (!in_merge_bases(old_cmit, new_cmit)) {
+ if (!in_merge_bases(old_cmit, &new_cmit, 1)) {
unlock_ref(lock);
warn("Not updating %s"
" (new tip %s does not contain %s)",
@@ -1361,7 +1365,7 @@ static void dump_marks_helper(FILE *f,
} else {
for (k = 0; k < 1024; k++) {
if (m->data.marked[k])
- fprintf(f, ":%ju %s\n", base + k,
+ fprintf(f, ":%" PRIuMAX " %s\n", base + k,
sha1_to_hex(m->data.marked[k]->sha1));
}
}
@@ -1388,7 +1392,7 @@ static void read_next_command(void)
static void cmd_mark(void)
{
- if (!strncmp("mark :", command_buf.buf, 6)) {
+ if (!prefixcmp(command_buf.buf, "mark :")) {
next_mark = strtoumax(command_buf.buf + 6, NULL, 10);
read_next_command();
}
@@ -1401,10 +1405,10 @@ static void *cmd_data (size_t *size)
size_t length;
char *buffer;
- if (strncmp("data ", command_buf.buf, 5))
+ if (prefixcmp(command_buf.buf, "data "))
die("Expected 'data n' command, found: %s", command_buf.buf);
- if (!strncmp("<<", command_buf.buf + 5, 2)) {
+ if (!prefixcmp(command_buf.buf + 5, "<<")) {
char *term = xstrdup(command_buf.buf + 5 + 2);
size_t sz = 8192, term_len = command_buf.len - 5 - 2;
length = 0;
@@ -1591,7 +1595,7 @@ static void file_change_m(struct branch *b)
oe = find_mark(strtoumax(p + 1, &x, 10));
hashcpy(sha1, oe->sha1);
p = x;
- } else if (!strncmp("inline", p, 6)) {
+ } else if (!prefixcmp(p, "inline")) {
inline_data = 1;
p += 6;
} else {
@@ -1664,7 +1668,7 @@ static void cmd_from(struct branch *b)
const char *from;
struct branch *s;
- if (strncmp("from ", command_buf.buf, 5))
+ if (prefixcmp(command_buf.buf, "from "))
return;
if (b->branch_tree.tree) {
@@ -1687,7 +1691,7 @@ static void cmd_from(struct branch *b)
unsigned long size;
char *buf;
if (oe->type != OBJ_COMMIT)
- die("Mark :%ju not a commit", idnum);
+ die("Mark :%" PRIuMAX " not a commit", idnum);
hashcpy(b->sha1, oe->sha1);
buf = gfi_unpack_entry(oe, &size);
if (!buf || size < 46)
@@ -1730,7 +1734,7 @@ static struct hash_list *cmd_merge(unsigned int *count)
struct branch *s;
*count = 0;
- while (!strncmp("merge ", command_buf.buf, 6)) {
+ while (!prefixcmp(command_buf.buf, "merge ")) {
from = strchr(command_buf.buf, ' ') + 1;
n = xmalloc(sizeof(*n));
s = lookup_branch(from);
@@ -1740,7 +1744,7 @@ static struct hash_list *cmd_merge(unsigned int *count)
uintmax_t idnum = strtoumax(from + 1, NULL, 10);
struct object_entry *oe = find_mark(idnum);
if (oe->type != OBJ_COMMIT)
- die("Mark :%ju not a commit", idnum);
+ die("Mark :%" PRIuMAX " not a commit", idnum);
hashcpy(n->sha1, oe->sha1);
} else if (get_sha1(from, n->sha1))
die("Invalid ref name or SHA1 expression: %s", from);
@@ -1776,11 +1780,11 @@ static void cmd_new_commit(void)
read_next_command();
cmd_mark();
- if (!strncmp("author ", command_buf.buf, 7)) {
+ if (!prefixcmp(command_buf.buf, "author ")) {
author = parse_ident(command_buf.buf + 7);
read_next_command();
}
- if (!strncmp("committer ", command_buf.buf, 10)) {
+ if (!prefixcmp(command_buf.buf, "committer ")) {
committer = parse_ident(command_buf.buf + 10);
read_next_command();
}
@@ -1801,9 +1805,9 @@ static void cmd_new_commit(void)
for (;;) {
if (1 == command_buf.len)
break;
- else if (!strncmp("M ", command_buf.buf, 2))
+ else if (!prefixcmp(command_buf.buf, "M "))
file_change_m(b);
- else if (!strncmp("D ", command_buf.buf, 2))
+ else if (!prefixcmp(command_buf.buf, "D "))
file_change_d(b);
else if (!strcmp("deleteall", command_buf.buf))
file_change_deleteall(b);
@@ -1873,7 +1877,7 @@ static void cmd_new_tag(void)
read_next_command();
/* from ... */
- if (strncmp("from ", command_buf.buf, 5))
+ if (prefixcmp(command_buf.buf, "from "))
die("Expected from command, got %s", command_buf.buf);
from = strchr(command_buf.buf, ' ') + 1;
s = lookup_branch(from);
@@ -1884,7 +1888,7 @@ static void cmd_new_tag(void)
from_mark = strtoumax(from + 1, NULL, 10);
oe = find_mark(from_mark);
if (oe->type != OBJ_COMMIT)
- die("Mark :%ju not a commit", from_mark);
+ die("Mark :%" PRIuMAX " not a commit", from_mark);
hashcpy(sha1, oe->sha1);
} else if (!get_sha1(from, sha1)) {
unsigned long size;
@@ -1900,7 +1904,7 @@ static void cmd_new_tag(void)
read_next_command();
/* tagger ... */
- if (strncmp("tagger ", command_buf.buf, 7))
+ if (prefixcmp(command_buf.buf, "tagger "))
die("Expected tagger command, got %s", command_buf.buf);
tagger = parse_ident(command_buf.buf + 7);
@@ -1977,7 +1981,7 @@ int main(int argc, const char **argv)
if (*a != '-' || !strcmp(a, "--"))
break;
- else if (!strncmp(a, "--date-format=", 14)) {
+ else if (!prefixcmp(a, "--date-format=")) {
const char *fmt = a + 14;
if (!strcmp(fmt, "raw"))
whenspec = WHENSPEC_RAW;
@@ -1988,15 +1992,15 @@ int main(int argc, const char **argv)
else
die("unknown --date-format argument %s", fmt);
}
- else if (!strncmp(a, "--max-pack-size=", 16))
+ else if (!prefixcmp(a, "--max-pack-size="))
max_packsize = strtoumax(a + 16, NULL, 0) * 1024 * 1024;
- else if (!strncmp(a, "--depth=", 8))
+ else if (!prefixcmp(a, "--depth="))
max_depth = strtoul(a + 8, NULL, 0);
- else if (!strncmp(a, "--active-branches=", 18))
+ else if (!prefixcmp(a, "--active-branches="))
max_active_branches = strtoul(a + 18, NULL, 0);
- else if (!strncmp(a, "--export-marks=", 15))
+ else if (!prefixcmp(a, "--export-marks="))
mark_file = a + 15;
- else if (!strncmp(a, "--export-pack-edges=", 20)) {
+ else if (!prefixcmp(a, "--export-pack-edges=")) {
if (pack_edges)
fclose(pack_edges);
pack_edges = fopen(a + 20, "a");
@@ -2029,11 +2033,11 @@ int main(int argc, const char **argv)
break;
else if (!strcmp("blob", command_buf.buf))
cmd_new_blob();
- else if (!strncmp("commit ", command_buf.buf, 7))
+ else if (!prefixcmp(command_buf.buf, "commit "))
cmd_new_commit();
- else if (!strncmp("tag ", command_buf.buf, 4))
+ else if (!prefixcmp(command_buf.buf, "tag "))
cmd_new_tag();
- else if (!strncmp("reset ", command_buf.buf, 6))
+ else if (!prefixcmp(command_buf.buf, "reset "))
cmd_reset_branch();
else if (!strcmp("checkpoint", command_buf.buf))
cmd_checkpoint();
@@ -2059,18 +2063,18 @@ int main(int argc, const char **argv)
fprintf(stderr, "%s statistics:\n", argv[0]);
fprintf(stderr, "---------------------------------------------------------------------\n");
- fprintf(stderr, "Alloc'd objects: %10ju\n", alloc_count);
- fprintf(stderr, "Total objects: %10ju (%10ju duplicates )\n", total_count, duplicate_count);
- fprintf(stderr, " blobs : %10ju (%10ju duplicates %10ju deltas)\n", object_count_by_type[OBJ_BLOB], duplicate_count_by_type[OBJ_BLOB], delta_count_by_type[OBJ_BLOB]);
- fprintf(stderr, " trees : %10ju (%10ju duplicates %10ju deltas)\n", object_count_by_type[OBJ_TREE], duplicate_count_by_type[OBJ_TREE], delta_count_by_type[OBJ_TREE]);
- fprintf(stderr, " commits: %10ju (%10ju duplicates %10ju deltas)\n", object_count_by_type[OBJ_COMMIT], duplicate_count_by_type[OBJ_COMMIT], delta_count_by_type[OBJ_COMMIT]);
- fprintf(stderr, " tags : %10ju (%10ju duplicates %10ju deltas)\n", object_count_by_type[OBJ_TAG], duplicate_count_by_type[OBJ_TAG], delta_count_by_type[OBJ_TAG]);
+ fprintf(stderr, "Alloc'd objects: %10" PRIuMAX "\n", alloc_count);
+ fprintf(stderr, "Total objects: %10" PRIuMAX " (%10" PRIuMAX " duplicates )\n", total_count, duplicate_count);
+ fprintf(stderr, " blobs : %10" PRIuMAX " (%10" PRIuMAX " duplicates %10" PRIuMAX " deltas)\n", object_count_by_type[OBJ_BLOB], duplicate_count_by_type[OBJ_BLOB], delta_count_by_type[OBJ_BLOB]);
+ fprintf(stderr, " trees : %10" PRIuMAX " (%10" PRIuMAX " duplicates %10" PRIuMAX " deltas)\n", object_count_by_type[OBJ_TREE], duplicate_count_by_type[OBJ_TREE], delta_count_by_type[OBJ_TREE]);
+ fprintf(stderr, " commits: %10" PRIuMAX " (%10" PRIuMAX " duplicates %10" PRIuMAX " deltas)\n", object_count_by_type[OBJ_COMMIT], duplicate_count_by_type[OBJ_COMMIT], delta_count_by_type[OBJ_COMMIT]);
+ fprintf(stderr, " tags : %10" PRIuMAX " (%10" PRIuMAX " duplicates %10" PRIuMAX " deltas)\n", object_count_by_type[OBJ_TAG], duplicate_count_by_type[OBJ_TAG], delta_count_by_type[OBJ_TAG]);
fprintf(stderr, "Total branches: %10lu (%10lu loads )\n", branch_count, branch_load_count);
- fprintf(stderr, " marks: %10ju (%10ju unique )\n", (((uintmax_t)1) << marks->shift) * 1024, marks_set_count);
+ fprintf(stderr, " marks: %10" PRIuMAX " (%10" PRIuMAX " unique )\n", (((uintmax_t)1) << marks->shift) * 1024, marks_set_count);
fprintf(stderr, " atoms: %10u\n", atom_cnt);
- fprintf(stderr, "Memory total: %10ju KiB\n", (total_allocd + alloc_count*sizeof(struct object_entry))/1024);
+ fprintf(stderr, "Memory total: %10" PRIuMAX " KiB\n", (total_allocd + alloc_count*sizeof(struct object_entry))/1024);
fprintf(stderr, " pools: %10lu KiB\n", (unsigned long)(total_allocd/1024));
- fprintf(stderr, " objects: %10ju KiB\n", (alloc_count*sizeof(struct object_entry))/1024);
+ fprintf(stderr, " objects: %10" PRIuMAX " KiB\n", (alloc_count*sizeof(struct object_entry))/1024);
fprintf(stderr, "---------------------------------------------------------------------\n");
pack_report();
fprintf(stderr, "---------------------------------------------------------------------\n");
diff --git a/fetch-pack.c b/fetch-pack.c
index c78710676..41bdd27b8 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -198,13 +198,13 @@ static int find_common(int fd[2], unsigned char *result_sha1,
int len;
while ((len = packet_read_line(fd[0], line, sizeof(line)))) {
- if (!strncmp("shallow ", line, 8)) {
+ if (!prefixcmp(line, "shallow ")) {
if (get_sha1_hex(line + 8, sha1))
die("invalid shallow line: %s", line);
register_shallow(sha1);
continue;
}
- if (!strncmp("unshallow ", line, 10)) {
+ if (!prefixcmp(line, "unshallow ")) {
if (get_sha1_hex(line + 10, sha1))
die("invalid unshallow line: %s", line);
if (!lookup_object(sha1))
@@ -346,7 +346,7 @@ static void filter_refs(struct ref **refs, int nr_match, char **match)
check_ref_format(ref->name + 5))
; /* trash */
else if (fetch_all &&
- (!depth || strncmp(ref->name, "refs/tags/", 10) )) {
+ (!depth || prefixcmp(ref->name, "refs/tags/") )) {
*newtail = ref;
ref->next = NULL;
newtail = &ref->next;
@@ -683,11 +683,11 @@ int main(int argc, char **argv)
char *arg = argv[i];
if (*arg == '-') {
- if (!strncmp("--upload-pack=", arg, 14)) {
+ if (!prefixcmp(arg, "--upload-pack=")) {
uploadpack = arg + 14;
continue;
}
- if (!strncmp("--exec=", arg, 7)) {
+ if (!prefixcmp(arg, "--exec=")) {
uploadpack = arg + 7;
continue;
}
@@ -712,7 +712,7 @@ int main(int argc, char **argv)
verbose = 1;
continue;
}
- if (!strncmp("--depth=", arg, 8)) {
+ if (!prefixcmp(arg, "--depth=")) {
depth = strtol(arg + 8, NULL, 0);
if (stat(git_path("shallow"), &st))
st.st_mtime = 0;
diff --git a/git-commit.sh b/git-commit.sh
index ec506d956..476f4f18d 100755
--- a/git-commit.sh
+++ b/git-commit.sh
@@ -318,6 +318,10 @@ esac
case "$all,$also" in
t,)
+ if test ! -f "$THIS_INDEX"
+ then
+ die 'nothing to commit (use "git add file1 file2" to include for commit)'
+ fi
save_index &&
(
cd_to_toplevel &&
diff --git a/git-compat-util.h b/git-compat-util.h
index c1bcb001a..5d154faef 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -1,6 +1,8 @@
#ifndef GIT_COMPAT_UTIL_H
#define GIT_COMPAT_UTIL_H
+#define _FILE_OFFSET_BITS 64
+
#ifndef FLEX_ARRAY
#if defined(__GNUC__) && (__GNUC__ < 3)
#define FLEX_ARRAY 0
@@ -96,11 +98,14 @@ extern void set_warn_routine(void (*routine)(const char *warn, va_list params));
extern void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
extern int git_munmap(void *start, size_t length);
+/* This value must be multiple of (pagesize * 2) */
#define DEFAULT_PACKED_GIT_WINDOW_SIZE (1 * 1024 * 1024)
#else /* NO_MMAP */
#include <sys/mman.h>
+
+/* This value must be multiple of (pagesize * 2) */
#define DEFAULT_PACKED_GIT_WINDOW_SIZE \
(sizeof(void*) >= 8 \
? 1 * 1024 * 1024 * 1024 \
@@ -136,6 +141,11 @@ extern char *gitstrcasestr(const char *haystack, const char *needle);
extern size_t gitstrlcpy(char *, const char *, size_t);
#endif
+#ifdef NO_STRTOUMAX
+#define strtoumax gitstrtoumax
+extern uintmax_t gitstrtoumax(const char *, char **, int);
+#endif
+
extern void release_pack_memory(size_t);
static inline char* xstrdup(const char *str)
@@ -271,4 +281,9 @@ static inline int sane_case(int x, int high)
return x;
}
+static inline int prefixcmp(const char *str, const char *prefix)
+{
+ return strncmp(str, prefix, strlen(prefix));
+}
+
#endif
diff --git a/git-cvsexportcommit.perl b/git-cvsexportcommit.perl
index 870554ead..d08216cfd 100755
--- a/git-cvsexportcommit.perl
+++ b/git-cvsexportcommit.perl
@@ -15,14 +15,21 @@ unless ($ENV{GIT_DIR} && -r $ENV{GIT_DIR}){
die "GIT_DIR is not defined or is unreadable";
}
-our ($opt_h, $opt_P, $opt_p, $opt_v, $opt_c, $opt_f, $opt_a, $opt_m );
+our ($opt_h, $opt_P, $opt_p, $opt_v, $opt_c, $opt_f, $opt_a, $opt_m, $opt_d);
-getopts('hPpvcfam:');
+getopts('hPpvcfam:d:');
$opt_h && usage();
die "Need at least one commit identifier!" unless @ARGV;
+my @cvs;
+if ($opt_d) {
+ @cvs = ('cvs', '-d', $opt_d);
+} else {
+ @cvs = ('cvs');
+}
+
# setup a tempdir
our ($tmpdir, $tmpdirname) = tempdir('git-cvsapplycommit-XXXXXX',
TMPDIR => 1,
@@ -160,7 +167,7 @@ foreach my $f (@afiles) {
my $p = $1;
next if (grep { $_ eq $p } @dirs);
}
- my @status = grep(m/^File/, safe_pipe_capture('cvs', '-q', 'status' ,$f));
+ my @status = grep(m/^File/, safe_pipe_capture(@cvs, '-q', 'status' ,$f));
if (@status > 1) { warn 'Strange! cvs status returned more than one line?'};
if (-d dirname $f and $status[0] !~ m/Status: Unknown$/
and $status[0] !~ m/^File: no file /) {
@@ -173,7 +180,7 @@ foreach my $f (@afiles) {
foreach my $f (@files) {
next if grep { $_ eq $f } @afiles;
# TODO:we need to handle removed in cvs
- my @status = grep(m/^File/, safe_pipe_capture('cvs', '-q', 'status' ,$f));
+ my @status = grep(m/^File/, safe_pipe_capture(@cvs, '-q', 'status' ,$f));
if (@status > 1) { warn 'Strange! cvs status returned more than one line?'};
unless ($status[0] =~ m/Status: Up-to-date$/) {
$dirty = 1;
@@ -194,7 +201,7 @@ print "Applying\n";
print "Patch applied successfully. Adding new files and directories to CVS\n";
my $dirtypatch = 0;
foreach my $d (@dirs) {
- if (system('cvs','add',$d)) {
+ if (system(@cvs,'add',$d)) {
$dirtypatch = 1;
warn "Failed to cvs add directory $d -- you may need to do it manually";
}
@@ -202,9 +209,9 @@ foreach my $d (@dirs) {
foreach my $f (@afiles) {
if (grep { $_ eq $f } @bfiles) {
- system('cvs', 'add','-kb',$f);
+ system(@cvs, 'add','-kb',$f);
} else {
- system('cvs', 'add', $f);
+ system(@cvs, 'add', $f);
}
if ($?) {
$dirtypatch = 1;
@@ -213,7 +220,7 @@ foreach my $f (@afiles) {
}
foreach my $f (@dfiles) {
- system('cvs', 'rm', '-f', $f);
+ system(@cvs, 'rm', '-f', $f);
if ($?) {
$dirtypatch = 1;
warn "Failed to cvs rm -f $f -- you may need to do it manually";
@@ -223,7 +230,7 @@ foreach my $f (@dfiles) {
print "Commit to CVS\n";
print "Patch title (first comment line): $title\n";
my @commitfiles = map { unless (m/\s/) { '\''.$_.'\''; } else { $_; }; } (@files);
-my $cmd = "cvs commit -F .msg @commitfiles";
+my $cmd = join(' ', @cvs)." commit -F .msg @commitfiles";
if ($dirtypatch) {
print "NOTE: One or more hunks failed to apply cleanly.\n";
@@ -236,7 +243,7 @@ if ($dirtypatch) {
if ($opt_c) {
print "Autocommit\n $cmd\n";
- print safe_pipe_capture('cvs', 'commit', '-F', '.msg', @files);
+ print safe_pipe_capture(@cvs, 'commit', '-F', '.msg', @files);
if ($?) {
die "Exiting: The commit did not succeed";
}
diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index 9371788fa..84520e7ad 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -1171,6 +1171,21 @@ sub req_ci
exit;
}
+ # Check that this is allowed, just as we would with a receive-pack
+ my @cmd = ( $ENV{GIT_DIR}.'hooks/update', "refs/heads/$state->{module}",
+ $parenthash, $commithash );
+ if( -x $cmd[0] ) {
+ unless( system( @cmd ) == 0 )
+ {
+ $log->warn("Commit failed (update hook declined to update ref)");
+ print "error 1 Commit failed (update hook declined)\n";
+ close LOCKFILE;
+ unlink($lockfile);
+ chdir "/";
+ exit;
+ }
+ }
+
print LOCKFILE $commithash;
$updater->update();
diff --git a/git-fetch.sh b/git-fetch.sh
index ca984e739..d230995f6 100755
--- a/git-fetch.sh
+++ b/git-fetch.sh
@@ -243,6 +243,15 @@ then
orig_head=$(git-rev-parse --verify HEAD 2>/dev/null)
fi
+# Allow --notags from remote.$1.tagopt
+case "$tags$no_tags" in
+'')
+ case "$(git-config --get "remote.$1.tagopt")" in
+ --no-tags)
+ no_tags=t ;;
+ esac
+esac
+
# If --tags (and later --heads or --all) is specified, then we are
# not talking about defaults stored in Pull: line of remotes or
# branches file, and just fetch those and refspecs explicitly given.
diff --git a/git-gui/.gitignore b/git-gui/.gitignore
index c714d382e..805ca2e1c 100644
--- a/git-gui/.gitignore
+++ b/git-gui/.gitignore
@@ -1,3 +1,4 @@
+CREDITS-FILE
GIT-VERSION-FILE
git-citool
git-gui
diff --git a/git-gui/CREDITS-GEN b/git-gui/CREDITS-GEN
new file mode 100755
index 000000000..da2c07629
--- /dev/null
+++ b/git-gui/CREDITS-GEN
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+CF=CREDITS-FILE
+tip=
+
+tree_search ()
+{
+ head=$1
+ tree=$2
+ for p in $(git rev-list --parents --max-count=1 $head 2>/dev/null)
+ do
+ test $tree = $(git rev-parse $p^{tree} 2>/dev/null) &&
+ vn=$(git describe --abbrev=4 $p 2>/dev/null) &&
+ case "$vn" in
+ gitgui-[0-9]*) echo $p; break;;
+ esac
+ done
+}
+
+generate_credits ()
+{
+ tip=$1 &&
+ rm -f $CF &&
+ git shortlog -n -s $tip | sed 's/: .*$//' >$CF || exit
+}
+
+# Always use the tarball credits file if found, just
+# in case we are somehow contained in a larger git
+# repository that doesn't actually track our state.
+# (At least one package manager is doing this.)
+#
+# We may be a subproject, so try looking for the merge
+# commit that supplied this directory content if we are
+# not at the toplevel. We probably will always be the
+# second parent in the commit, but we shouldn't rely on
+# that fact.
+#
+
+if test -f credits
+then
+ rm -f $CF &&
+ cp credits $CF || exit
+elif prefix="$(git rev-parse --show-prefix 2>/dev/null)" &&
+ test -n "$prefix" &&
+ head=$(git rev-list --max-count=1 HEAD -- . 2>/dev/null) &&
+ tree=$(git rev-parse --verify "HEAD:$prefix" 2>/dev/null) &&
+ tip=$(tree_search $head $tree) &&
+ test -n "$tip"
+then
+ generate_credits $tip || exit
+elif tip="$(git rev-parse --verify HEAD 2>/dev/null)" &&
+ test -n "$tip"
+then
+ generate_credits $tip || exit
+else
+ echo "error: Cannot locate authorship information." >&2
+ exit 1
+fi
diff --git a/git-gui/GIT-VERSION-GEN b/git-gui/GIT-VERSION-GEN
index 9966126da..2741c1e14 100755
--- a/git-gui/GIT-VERSION-GEN
+++ b/git-gui/GIT-VERSION-GEN
@@ -20,6 +20,11 @@ tree_search ()
done
}
+# Always use the tarball version file if found, just
+# in case we are somehow contained in a larger git
+# repository that doesn't actually track our state.
+# (At least one package manager is doing this.)
+#
# We may be a subproject, so try looking for the merge
# commit that supplied this directory content if we are
# not at the toplevel. We probably will always be the
@@ -27,10 +32,13 @@ tree_search ()
# that fact.
#
# If we are at the toplevel or the merge assumption fails
-# try looking for a gitgui-* tag, or fallback onto the
-# distributed version file.
+# try looking for a gitgui-* tag.
-if prefix="$(git rev-parse --show-prefix 2>/dev/null)"
+if test -f version &&
+ VN=$(cat version)
+then
+ : happy
+elif prefix="$(git rev-parse --show-prefix 2>/dev/null)"
test -n "$prefix" &&
head=$(git rev-list --max-count=1 HEAD -- . 2>/dev/null) &&
tree=$(git rev-parse --verify "HEAD:$prefix" 2>/dev/null) &&
@@ -48,9 +56,6 @@ elif VN=$(git describe --abbrev=4 HEAD 2>/dev/null) &&
esac
then
VN=$(echo "$VN" | sed -e 's/^gitgui-//;s/-/./g');
-elif test -f version
-then
- VN=$(cat version) || VN="$DEF_VER"
else
VN="$DEF_VER"
fi
diff --git a/git-gui/Makefile b/git-gui/Makefile
index fd82d9d16..66538ba1a 100644
--- a/git-gui/Makefile
+++ b/git-gui/Makefile
@@ -4,9 +4,8 @@ GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
@$(SHELL_PATH) ./GIT-VERSION-GEN
-include GIT-VERSION-FILE
-SCRIPT_SH = git-gui.sh
GITGUI_BUILT_INS = git-citool
-ALL_PROGRAMS = $(GITGUI_BUILT_INS) $(patsubst %.sh,%,$(SCRIPT_SH))
+ALL_PROGRAMS = git-gui $(GITGUI_BUILT_INS)
ifndef SHELL_PATH
SHELL_PATH = /bin/sh
@@ -24,20 +23,24 @@ DESTDIR_SQ = $(subst ','\'',$(DESTDIR))
gitexecdir_SQ = $(subst ','\'',$(gitexecdir))
SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
-$(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
+git-gui: git-gui.sh GIT-VERSION-FILE CREDITS-FILE
rm -f $@ $@+
- sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
+ sed -n \
+ -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
-e 's/@@GITGUI_VERSION@@/$(GITGUI_VERSION)/g' \
+ -e '1,/^set gitgui_credits /p' \
$@.sh >$@+
+ cat CREDITS-FILE >>$@+
+ sed -e '1,/^set gitgui_credits /d' $@.sh >>$@+
chmod +x $@+
mv $@+ $@
+CREDITS-FILE: CREDITS-GEN .FORCE-CREDITS-FILE
+ $(SHELL_PATH) ./CREDITS-GEN
+
$(GITGUI_BUILT_INS): git-gui
rm -f $@ && ln git-gui $@
-# These can record GITGUI_VERSION
-$(patsubst %.sh,%,$(SCRIPT_SH)): GIT-VERSION-FILE
-
all:: $(ALL_PROGRAMS)
install: all
@@ -45,12 +48,14 @@ install: all
$(INSTALL) git-gui '$(DESTDIR_SQ)$(gitexecdir_SQ)'
$(foreach p,$(GITGUI_BUILT_INS), rm -f '$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' && ln '$(DESTDIR_SQ)$(gitexecdir_SQ)/git-gui' '$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' ;)
-dist-version:
+dist-version: CREDITS-FILE
@mkdir -p $(TARDIR)
@echo $(GITGUI_VERSION) > $(TARDIR)/version
+ @cat CREDITS-FILE > $(TARDIR)/credits
clean::
- rm -f $(ALL_PROGRAMS) GIT-VERSION-FILE
+ rm -f $(ALL_PROGRAMS) GIT-VERSION-FILE CREDITS-FILE
.PHONY: all install dist-version clean
.PHONY: .FORCE-GIT-VERSION-FILE
+.PHONY: .FORCE-CREDITS-FILE
diff --git a/git-gui/TODO b/git-gui/TODO
deleted file mode 100644
index b95a13732..000000000
--- a/git-gui/TODO
+++ /dev/null
@@ -1,44 +0,0 @@
-Items outstanding:
-
- * Add file to .gitignore or info/excludes.
-
- * Populate the pull menu with local branches.
-
- * Make use of the new default merge data stored in repo-config.
-
- * Checkout a different local branch.
-
- * Push any local branch to a remote branch.
-
- * Merge any local branches through a real merge UI.
-
- * Allow user to define keyboard shortcuts for frequently used fetch
- or merge operations. Or maybe just define a keyboard shortcut
- for default fetch/default merge of current branch is enough;
- but I do know a few users who merge a couple of common branches
- also into the same branch so one default isn't quite enough.
-
- * Better organize fetch/push/pull console windows.
-
- * Clone UI (to download a new repository).
-
- * Remotes editor (for .git/config format only).
-
- * Show a shortlog of the last couple of commits in the main window,
- to give the user warm fuzzy feelings that we have their data
- saved. Actually this may be the set of commits not yet in
- the upstream (aka default merge branch remote repository).
-
- * GUI configuration editor for options listed in
- git.git/Documentation/config.txt. Ideally this would
- parse that file and generate the options dialog from
- the documentation itself, and include the help text
- from the documentation as part of the UI somehow.
-
-Known bugs:
-
- * git-gui sometimes just closes on Windows with no error message.
- I'm not sure what the problem is here. I suspect the wish
- process is just terminating due to a segfault or something,
- as the do_quit proc in git-gui doesn't run. It often seems to
- occur while writing a commit message in the buffer. Odd.
diff --git a/git-gui/git-gui.sh b/git-gui/git-gui.sh
index f5010dd47..f84ba3382 100755
--- a/git-gui/git-gui.sh
+++ b/git-gui/git-gui.sh
@@ -4,7 +4,7 @@ exec wish "$0" -- "$@"
set appvers {@@GITGUI_VERSION@@}
set copyright {
-Copyright © 2006, 2007 Shawn Pearce, Paul Mackerras.
+Copyright © 2006, 2007 Shawn Pearce, et. al.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -19,6 +19,9 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA}
+set gitgui_credits {
+Paul Mackerras
+}
######################################################################
##
@@ -46,7 +49,7 @@ proc gitdir {args} {
proc gitexec {args} {
global _gitexec
if {$_gitexec eq {}} {
- if {[catch {set _gitexec [exec git --exec-path]} err]} {
+ if {[catch {set _gitexec [git --exec-path]} err]} {
error "Git not installed?\n\n$err"
}
}
@@ -202,14 +205,14 @@ proc save_config {} {
set value $global_config_new($name)
if {$value ne $global_config($name)} {
if {$value eq $default_config($name)} {
- catch {exec git config --global --unset $name}
+ catch {git config --global --unset $name}
} else {
regsub -all "\[{}\]" $value {"} value
- exec git config --global $name $value
+ git config --global $name $value
}
set global_config($name) $value
if {$value eq $repo_config($name)} {
- catch {exec git config --unset $name}
+ catch {git config --unset $name}
set repo_config($name) $value
}
}
@@ -219,16 +222,24 @@ proc save_config {} {
set value $repo_config_new($name)
if {$value ne $repo_config($name)} {
if {$value eq $global_config($name)} {
- catch {exec git config --unset $name}
+ catch {git config --unset $name}
} else {
regsub -all "\[{}\]" $value {"} value
- exec git config $name $value
+ git config $name $value
}
set repo_config($name) $value
}
}
}
+######################################################################
+##
+## handy utils
+
+proc git {args} {
+ return [eval exec git $args]
+}
+
proc error_popup {msg} {
set title [appname]
if {[reponame] ne {}} {
@@ -289,10 +300,42 @@ proc ask_popup {msg} {
######################################################################
##
+## version check
+
+set req_maj 1
+set req_min 5
+
+if {[catch {set v [git --version]} err]} {
+ catch {wm withdraw .}
+ error_popup "Cannot determine Git version:
+
+$err
+
+[appname] requires Git $req_maj.$req_min or later."
+ exit 1
+}
+if {[regexp {^git version (\d+)\.(\d+)} $v _junk act_maj act_min]} {
+ if {$act_maj < $req_maj
+ || ($act_maj == $req_maj && $act_min < $req_min)} {
+ catch {wm withdraw .}
+ error_popup "[appname] requires Git $req_maj.$req_min or later.
+
+You are using $v."
+ exit 1
+ }
+} else {
+ catch {wm withdraw .}
+ error_popup "Cannot parse Git version string:\n\n$v"
+ exit 1
+}
+unset -nocomplain v _junk act_maj act_min req_maj req_min
+
+######################################################################
+##
## repository setup
if { [catch {set _gitdir $env(GIT_DIR)}]
- && [catch {set _gitdir [exec git rev-parse --git-dir]} err]} {
+ && [catch {set _gitdir [git rev-parse --git-dir]} err]} {
catch {wm withdraw .}
error_popup "Cannot find the git directory:\n\n$err"
exit 1
@@ -321,6 +364,24 @@ set _reponame [lindex [file split \
######################################################################
##
+## global init
+
+set current_diff_path {}
+set current_diff_side {}
+set diff_actions [list]
+set ui_status_value {Initializing...}
+
+set HEAD {}
+set PARENT {}
+set MERGE_HEAD [list]
+set commit_type {}
+set empty_tree {}
+set current_branch {}
+set current_diff_path {}
+set selected_commit_type new
+
+######################################################################
+##
## task management
set rescan_active 0
@@ -365,7 +426,7 @@ proc repository_state {ctvar hdvar mhvar} {
set mh [list]
- if {[catch {set current_branch [exec git symbolic-ref HEAD]}]} {
+ if {[catch {set current_branch [git symbolic-ref HEAD]}]} {
set current_branch {}
} else {
regsub ^refs/((heads|tags|remotes)/)? \
@@ -374,7 +435,7 @@ proc repository_state {ctvar hdvar mhvar} {
current_branch
}
- if {[catch {set hd [exec git rev-parse --verify HEAD]}]} {
+ if {[catch {set hd [git rev-parse --verify HEAD]}]} {
set hd {}
set ct initial
return
@@ -402,7 +463,7 @@ proc PARENT {} {
return $p
}
if {$empty_tree eq {}} {
- set empty_tree [exec git mktree << {}]
+ set empty_tree [git mktree << {}]
}
return $empty_tree
}
@@ -642,8 +703,9 @@ proc reshow_diff {} {
global current_diff_path current_diff_side
set p $current_diff_path
- if {$p eq {}
- || $current_diff_side eq {}
+ if {$p eq {}} {
+ # No diff is being shown.
+ } elseif {$current_diff_side eq {}
|| [catch {set s $file_states($p)}]
|| [lsearch -sorted -exact $file_lists($current_diff_side) $p] == -1} {
clear_diff
@@ -1042,7 +1104,7 @@ proc committer_ident {} {
global GIT_COMMITTER_IDENT
if {$GIT_COMMITTER_IDENT eq {}} {
- if {[catch {set me [exec git var GIT_COMMITTER_IDENT]} err]} {
+ if {[catch {set me [git var GIT_COMMITTER_IDENT]} err]} {
error_popup "Unable to obtain your identity:\n\n$err"
return {}
}
@@ -1256,14 +1318,6 @@ proc commit_committree {fd_wt curHEAD msg} {
return
}
- # -- Make sure our current branch exists.
- #
- if {$commit_type eq {initial}} {
- lappend all_heads $current_branch
- set all_heads [lsort -unique $all_heads]
- populate_branch_menu
- }
-
# -- Cleanup after ourselves.
#
catch {file delete $msg_p}
@@ -1275,7 +1329,7 @@ proc commit_committree {fd_wt curHEAD msg} {
# -- Let rerere do its thing.
#
if {[file isdirectory [gitdir rr-cache]]} {
- catch {exec git rerere}
+ catch {git rerere}
}
# -- Run the post-commit hook.
@@ -1299,6 +1353,14 @@ proc commit_committree {fd_wt curHEAD msg} {
if {[is_enabled singlecommit]} do_quit
+ # -- Make sure our current branch exists.
+ #
+ if {$commit_type eq {initial}} {
+ lappend all_heads $current_branch
+ set all_heads [lsort -unique $all_heads]
+ populate_branch_menu
+ }
+
# -- Update in memory status
#
set selected_commit_type new
@@ -1876,11 +1938,24 @@ proc all_tracking_branches {} {
return [lsort -unique $all_trackings]
}
+proc load_all_tags {} {
+ set all_tags [list]
+ set fd [open "| git for-each-ref --format=%(refname) refs/tags" r]
+ while {[gets $fd line] > 0} {
+ if {![regsub ^refs/tags/ $line {} name]} continue
+ lappend all_tags $name
+ }
+ close $fd
+
+ return [lsort $all_tags]
+}
+
proc do_create_branch_action {w} {
global all_heads null_sha1 repo_config
global create_branch_checkout create_branch_revtype
global create_branch_head create_branch_trackinghead
global create_branch_name create_branch_revexp
+ global create_branch_tag
set newbranch $create_branch_name
if {$newbranch eq {}
@@ -1894,7 +1969,7 @@ proc do_create_branch_action {w} {
focus $w.desc.name_t
return
}
- if {![catch {exec git show-ref --verify -- "refs/heads/$newbranch"}]} {
+ if {![catch {git show-ref --verify -- "refs/heads/$newbranch"}]} {
tk_messageBox \
-icon error \
-type ok \
@@ -1904,7 +1979,7 @@ proc do_create_branch_action {w} {
focus $w.desc.name_t
return
}
- if {[catch {exec git check-ref-format "heads/$newbranch"}]} {
+ if {[catch {git check-ref-format "heads/$newbranch"}]} {
tk_messageBox \
-icon error \
-type ok \
@@ -1919,9 +1994,10 @@ proc do_create_branch_action {w} {
switch -- $create_branch_revtype {
head {set rev $create_branch_head}
tracking {set rev $create_branch_trackinghead}
+ tag {set rev $create_branch_tag}
expression {set rev $create_branch_revexp}
}
- if {[catch {set cmt [exec git rev-parse --verify "${rev}^0"]}]} {
+ if {[catch {set cmt [git rev-parse --verify "${rev}^0"]}]} {
tk_messageBox \
-icon error \
-type ok \
@@ -1964,6 +2040,8 @@ trace add variable create_branch_head write \
[list radio_selector create_branch_revtype head]
trace add variable create_branch_trackinghead write \
[list radio_selector create_branch_revtype tracking]
+trace add variable create_branch_tag write \
+ [list radio_selector create_branch_revtype tag]
trace add variable delete_branch_head write \
[list radio_selector delete_branch_checktype head]
@@ -1975,6 +2053,7 @@ proc do_create_branch {} {
global create_branch_checkout create_branch_revtype
global create_branch_head create_branch_trackinghead
global create_branch_name create_branch_revexp
+ global create_branch_tag
set w .branch_editor
toplevel $w
@@ -2038,6 +2117,19 @@ proc do_create_branch {} {
$all_trackings
grid $w.from.tracking_r $w.from.tracking_m -sticky w
}
+ set all_tags [load_all_tags]
+ if {$all_tags ne {}} {
+ set create_branch_tag [lindex $all_tags 0]
+ radiobutton $w.from.tag_r \
+ -text {Tag:} \
+ -value tag \
+ -variable create_branch_revtype \
+ -font font_ui
+ eval tk_optionMenu $w.from.tag_m \
+ create_branch_tag \
+ $all_tags
+ grid $w.from.tag_r $w.from.tag_m -sticky w
+ }
radiobutton $w.from.exp_r \
-text {Revision Expression:} \
-value expression \
@@ -2100,7 +2192,7 @@ proc do_delete_branch_action {w} {
}
if {$check_rev eq {:none}} {
set check_cmt {}
- } elseif {[catch {set check_cmt [exec git rev-parse --verify "${check_rev}^0"]}]} {
+ } elseif {[catch {set check_cmt [git rev-parse --verify "${check_rev}^0"]}]} {
tk_messageBox \
-icon error \
-type ok \
@@ -2114,10 +2206,10 @@ proc do_delete_branch_action {w} {
set not_merged [list]
foreach i [$w.list.l curselection] {
set b [$w.list.l get $i]
- if {[catch {set o [exec git rev-parse --verify $b]}]} continue
+ if {[catch {set o [git rev-parse --verify $b]}]} continue
if {$check_cmt ne {}} {
if {$b eq $check_rev} continue
- if {[catch {set m [exec git merge-base $o $check_cmt]}]} continue
+ if {[catch {set m [git merge-base $o $check_cmt]}]} continue
if {$o ne $m} {
lappend not_merged $b
continue
@@ -2155,7 +2247,7 @@ Delete the selected branches?}
foreach i $to_delete {
set b [lindex $i 0]
set o [lindex $i 1]
- if {[catch {exec git update-ref -d "refs/heads/$b" $o} err]} {
+ if {[catch {git update-ref -d "refs/heads/$b" $o} err]} {
append failed " - $b: $err\n"
} else {
set x [lsearch -sorted -exact $all_heads $b]
@@ -2366,7 +2458,7 @@ Staying on branch '$current_branch'."
# here, it Just Works(tm). If it doesn't we are in some really ugly
# state that is difficult to recover from within git-gui.
#
- if {[catch {exec git symbolic-ref HEAD "refs/heads/$new_branch"} err]} {
+ if {[catch {git symbolic-ref HEAD "refs/heads/$new_branch"} err]} {
error_popup "Failed to set current branch.
This working directory is only partially switched.
@@ -2876,14 +2968,16 @@ proc do_local_merge {} {
pack $w.source -fill both -expand 1 -pady 5 -padx 5
set cmd [list git for-each-ref]
- lappend cmd {--format=%(objectname) %(refname)}
+ lappend cmd {--format=%(objectname) %(*objectname) %(refname)}
lappend cmd refs/heads
lappend cmd refs/remotes
+ lappend cmd refs/tags
set fr_fd [open "| $cmd" r]
fconfigure $fr_fd -translation binary
while {[gets $fr_fd line] > 0} {
set line [split $line { }]
- set sha1([lindex $line 0]) [lindex $line 1]
+ set sha1([lindex $line 0]) [lindex $line 2]
+ set sha1([lindex $line 1]) [lindex $line 2]
}
close $fr_fd
@@ -2891,7 +2985,7 @@ proc do_local_merge {} {
set fr_fd [open "| git rev-list --all --not HEAD"]
while {[gets $fr_fd line] > 0} {
if {[catch {set ref $sha1($line)}]} continue
- regsub ^refs/(heads|remotes)/ $ref {} ref
+ regsub ^refs/(heads|remotes|tags)/ $ref {} ref
lappend to_show $ref
}
close $fr_fd
@@ -2972,7 +3066,14 @@ proc new_browser {commit} {
global next_browser_id cursor_ptr M1B
global browser_commit browser_status browser_stack browser_path browser_busy
- set w .browser[incr next_browser_id]
+ if {[winfo ismapped .]} {
+ set w .browser[incr next_browser_id]
+ set tl $w
+ toplevel $w
+ } else {
+ set w {}
+ set tl .
+ }
set w_list $w.list.l
set browser_commit($w_list) $commit
set browser_status($w_list) {Starting...}
@@ -2980,7 +3081,6 @@ proc new_browser {commit} {
set browser_path($w_list) $browser_commit($w_list):
set browser_busy($w_list) 1
- toplevel $w
label $w.path -textvariable browser_path($w_list) \
-anchor w \
-justify left \
@@ -3030,8 +3130,8 @@ proc new_browser {commit} {
bind $w_list <Left> break
bind $w_list <Right> break
- bind $w <Visibility> "focus $w"
- bind $w <Destroy> "
+ bind $tl <Visibility> "focus $w"
+ bind $tl <Destroy> "
array unset browser_buffer $w_list
array unset browser_files $w_list
array unset browser_status $w_list
@@ -3040,7 +3140,7 @@ proc new_browser {commit} {
array unset browser_commit $w_list
array unset browser_busy $w_list
"
- wm title $w "[appname] ([reponame]): File Browser"
+ wm title $tl "[appname] ([reponame]): File Browser"
ls_tree $w_list $browser_commit($w_list) {}
}
@@ -4161,7 +4261,7 @@ proc do_quit {} {
set rc_geometry {}
}
if {$cfg_geometry ne $rc_geometry} {
- catch {exec git config gui.geometry $cfg_geometry}
+ catch {git config gui.geometry $cfg_geometry}
}
}
@@ -4380,6 +4480,61 @@ proc do_commit {} {
commit_tree
}
+proc do_credits {} {
+ global gitgui_credits
+
+ set w .credits_dialog
+
+ toplevel $w
+ wm geometry $w "+[winfo rootx .]+[winfo rooty .]"
+
+ label $w.header -text {git-gui Contributors} -font font_uibold
+ pack $w.header -side top -fill x
+
+ frame $w.buttons
+ button $w.buttons.close -text {Close} \
+ -font font_ui \
+ -command [list destroy $w]
+ pack $w.buttons.close -side right
+ pack $w.buttons -side bottom -fill x -pady 10 -padx 10
+
+ frame $w.credits
+ text $w.credits.t \
+ -background [$w.header cget -background] \
+ -yscrollcommand [list $w.credits.sby set] \
+ -width 20 \
+ -height 10 \
+ -wrap none \
+ -borderwidth 1 \
+ -relief solid \
+ -padx 5 -pady 5 \
+ -font font_ui
+ scrollbar $w.credits.sby -command [list $w.credits.t yview]
+ pack $w.credits.sby -side right -fill y
+ pack $w.credits.t -fill both -expand 1
+ pack $w.credits -side top -fill both -expand 1 -padx 5 -pady 5
+
+ label $w.desc \
+ -text "All portions are copyrighted by their respective authors
+and are distributed under the GNU General Public License." \
+ -padx 5 -pady 5 \
+ -justify left \
+ -anchor w \
+ -borderwidth 1 \
+ -relief solid \
+ -font font_ui
+ pack $w.desc -side top -fill x -padx 5 -pady 5
+
+ $w.credits.t insert end "[string trim $gitgui_credits]\n"
+ $w.credits.t conf -state disabled
+ $w.credits.t see 1.0
+
+ bind $w <Visibility> "grab $w; focus $w"
+ bind $w <Key-Escape> [list destroy $w]
+ wm title $w [$w.header cget -text]
+ tkwait window $w
+}
+
proc do_about {} {
global appvers copyright
global tcl_patchLevel tk_patchLevel
@@ -4396,11 +4551,15 @@ proc do_about {} {
button $w.buttons.close -text {Close} \
-font font_ui \
-command [list destroy $w]
+ button $w.buttons.credits -text {Contributors} \
+ -font font_ui \
+ -command do_credits
+ pack $w.buttons.credits -side left
pack $w.buttons.close -side right
pack $w.buttons -side bottom -fill x -pady 10 -padx 10
label $w.desc \
- -text "[appname] - a commit creation tool for Git.
+ -text "git-gui - a graphical user interface for Git.
$copyright" \
-padx 5 -pady 5 \
-justify left \
@@ -4411,8 +4570,8 @@ $copyright" \
pack $w.desc -side top -fill x -padx 5 -pady 5
set v {}
- append v "[appname] version $appvers\n"
- append v "[exec git version]\n"
+ append v "git-gui version $appvers\n"
+ append v "[git version]\n"
append v "\n"
if {$tcl_patchLevel eq $tk_patchLevel} {
append v "Tcl/Tk version $tcl_patchLevel"
@@ -4471,7 +4630,7 @@ proc do_options {} {
toplevel $w
wm geometry $w "+[winfo rootx .]+[winfo rooty .]"
- label $w.header -text "[appname] Options" \
+ label $w.header -text "Options" \
-font font_uibold
pack $w.header -side top -fill x
@@ -4945,6 +5104,9 @@ enable_option branch
enable_option transport
switch -- $subcommand {
+--version -
+version -
+browser -
blame {
disable_option multicommit
disable_option branch
@@ -5177,7 +5339,7 @@ if {[is_MacOSX]} {
.mbar.apple add command -label "About [appname]" \
-command do_about \
-font font_ui
- .mbar.apple add command -label "[appname] Options..." \
+ .mbar.apple add command -label "Options..." \
-command do_options \
-font font_ui
} else {
@@ -5236,7 +5398,7 @@ set doc_path [file dirname [gitexec]]
set doc_path [file join $doc_path Documentation index.html]
if {[is_Cygwin]} {
- set doc_path [exec cygpath --windows $doc_path]
+ set doc_path [exec cygpath --mixed $doc_path]
}
if {$browser eq {}} {
@@ -5280,6 +5442,20 @@ bind all <$M1B-Key-W> {destroy [winfo toplevel %W]}
# -- Not a normal commit type invocation? Do that instead!
#
switch -- $subcommand {
+--version -
+version {
+ puts "git-gui version $appvers"
+ exit
+}
+browser {
+ if {[llength $argv] != 1} {
+ puts stderr "usage: $argv0 browser commit"
+ exit 1
+ }
+ set current_branch [lindex $argv 0]
+ new_browser $current_branch
+ return
+}
blame {
if {[llength $argv] != 2} {
puts stderr "usage: $argv0 blame commit path"
@@ -5302,7 +5478,7 @@ gui {
# fall through to setup UI for commits
}
default {
- puts stderr "usage: $argv0 \[{blame|citool}\]"
+ puts stderr "usage: $argv0 \[{blame|browser|citool}\]"
exit 1
}
}
@@ -5552,9 +5728,6 @@ bind_button3 $ui_comm "tk_popup $ctxm %X %Y"
# -- Diff Header
#
-set current_diff_path {}
-set current_diff_side {}
-set diff_actions [list]
proc trace_current_diff_path {varname args} {
global current_diff_path diff_actions file_states
if {$current_diff_path eq {}} {
@@ -5747,7 +5920,6 @@ unset ui_diff_applyhunk
# -- Status Bar
#
-set ui_status_value {Initializing...}
label .status -textvariable ui_status_value \
-anchor w \
-justify left \
@@ -5821,15 +5993,6 @@ unset i
set file_lists($ui_index) [list]
set file_lists($ui_workdir) [list]
-set HEAD {}
-set PARENT {}
-set MERGE_HEAD [list]
-set commit_type {}
-set empty_tree {}
-set current_branch {}
-set current_diff_path {}
-set selected_commit_type new
-
wm title . "[appname] ([file normalize [file dirname [gitdir]]])"
focus -force $ui_comm
@@ -5904,7 +6067,7 @@ if {[is_enabled transport]} {
if {[is_enabled multicommit]} {
set object_limit 2000
if {[is_Windows]} {set object_limit 200}
- regexp {^([0-9]+) objects,} [exec git count-objects] _junk objects_current
+ regexp {^([0-9]+) objects,} [git count-objects] _junk objects_current
if {$objects_current >= $object_limit} {
if {[ask_popup \
"This repository currently has $objects_current loose objects.
diff --git a/git-merge.sh b/git-merge.sh
index 04a5eb0f2..498c938c4 100755
--- a/git-merge.sh
+++ b/git-merge.sh
@@ -254,12 +254,15 @@ esac
for s in $use_strategies
do
- case " $s " in
- *" $no_trivial_merge_strategies "*)
- index_merge=f
- break
- ;;
- esac
+ for nt in $no_trivial_merge_strategies
+ do
+ case " $s " in
+ *" $nt "*)
+ index_merge=f
+ break
+ ;;
+ esac
+ done
done
case "$#" in
diff --git a/git-remote.perl b/git-remote.perl
index c56c5a84a..bd70bf1dd 100755
--- a/git-remote.perl
+++ b/git-remote.perl
@@ -67,7 +67,7 @@ sub list_remote {
$git->command(qw(config --get-regexp), '^remote\.');
};
for (@remotes) {
- if (/^remote\.([^.]*)\.(\S*)\s+(.*)$/) {
+ if (/^remote\.(\S+?)\.([^.\s]+)\s+(.*)$/) {
add_remote_config(\%seen, $1, $2, $3);
}
}
@@ -274,6 +274,31 @@ sub add_remote {
}
}
+sub update_remote {
+ my ($name) = @_;
+
+ my $conf = $git->config("remotes." . $name);
+ if (defined($conf)) {
+ @remotes = split(' ', $conf);
+ } elsif ($name eq 'default') {
+ undef @remotes;
+ for (sort keys %$remote) {
+ my $do_fetch = $git->config_boolean("remote." . $_ .
+ ".skipDefaultUpdate");
+ if (!defined($do_fetch) || $do_fetch ne "true") {
+ push @remotes, $_;
+ }
+ }
+ } else {
+ print STDERR "Remote group $name does not exists.\n";
+ exit(1);
+ }
+ for (@remotes) {
+ print "Updating $_\n";
+ $git->command('fetch', "$_");
+ }
+}
+
sub add_usage {
print STDERR "Usage: git remote add [-f] [-t track]* [-m master] <name> <url>\n";
exit(1);
@@ -303,6 +328,15 @@ elsif ($ARGV[0] eq 'show') {
show_remote($ARGV[$i], $ls_remote);
}
}
+elsif ($ARGV[0] eq 'update') {
+ if (@ARGV <= 1) {
+ update_remote("default");
+ exit(1);
+ }
+ for ($i = 1; $i < @ARGV; $i++) {
+ update_remote($ARGV[$i]);
+ }
+}
elsif ($ARGV[0] eq 'prune') {
my $ls_remote = 1;
my $i;
@@ -360,5 +394,6 @@ else {
print STDERR " git remote add <name> <url>\n";
print STDERR " git remote show <name>\n";
print STDERR " git remote prune <name>\n";
+ print STDERR " git remote update [group]\n";
exit(1);
}
diff --git a/git.c b/git.c
index 45265f14d..83f3d90ee 100644
--- a/git.c
+++ b/git.c
@@ -48,7 +48,7 @@ static int handle_options(const char*** argv, int* argc)
/*
* Check remaining flags.
*/
- if (!strncmp(cmd, "--exec-path", 11)) {
+ if (!prefixcmp(cmd, "--exec-path")) {
cmd += 11;
if (*cmd == '=')
git_set_exec_path(cmd + 1);
@@ -66,7 +66,7 @@ static int handle_options(const char*** argv, int* argc)
setenv(GIT_DIR_ENVIRONMENT, (*argv)[1], 1);
(*argv)++;
(*argc)--;
- } else if (!strncmp(cmd, "--git-dir=", 10)) {
+ } else if (!prefixcmp(cmd, "--git-dir=")) {
setenv(GIT_DIR_ENVIRONMENT, cmd + 10, 1);
} else if (!strcmp(cmd, "--bare")) {
static char git_dir[PATH_MAX+1];
@@ -88,7 +88,7 @@ static char *alias_string;
static int git_alias_config(const char *var, const char *value)
{
- if (!strncmp(var, "alias.", 6) && !strcmp(var + 6, alias_command)) {
+ if (!prefixcmp(var, "alias.") && !strcmp(var + 6, alias_command)) {
alias_string = xstrdup(value);
}
return 0;
@@ -240,7 +240,6 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
{ "diff", cmd_diff, RUN_SETUP | USE_PAGER },
{ "diff-files", cmd_diff_files, RUN_SETUP },
{ "diff-index", cmd_diff_index, RUN_SETUP },
- { "diff-stages", cmd_diff_stages, RUN_SETUP },
{ "diff-tree", cmd_diff_tree, RUN_SETUP },
{ "fmt-merge-msg", cmd_fmt_merge_msg, RUN_SETUP },
{ "for-each-ref", cmd_for_each_ref, RUN_SETUP },
@@ -248,7 +247,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
{ "fsck", cmd_fsck, RUN_SETUP },
{ "fsck-objects", cmd_fsck, RUN_SETUP },
{ "get-tar-commit-id", cmd_get_tar_commit_id },
- { "grep", cmd_grep, RUN_SETUP },
+ { "grep", cmd_grep, RUN_SETUP | USE_PAGER },
{ "help", cmd_help },
{ "init", cmd_init_db },
{ "init-db", cmd_init_db },
@@ -257,6 +256,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
{ "ls-tree", cmd_ls_tree, RUN_SETUP },
{ "mailinfo", cmd_mailinfo },
{ "mailsplit", cmd_mailsplit },
+ { "merge-base", cmd_merge_base, RUN_SETUP },
{ "merge-file", cmd_merge_file },
{ "mv", cmd_mv, RUN_SETUP | NOT_BARE },
{ "name-rev", cmd_name_rev, RUN_SETUP },
@@ -348,7 +348,7 @@ int main(int argc, const char **argv, char **envp)
* So we just directly call the internal command handler, and
* die if that one cannot handle it.
*/
- if (!strncmp(cmd, "git-", 4)) {
+ if (!prefixcmp(cmd, "git-")) {
cmd += 4;
argv[0] = cmd;
handle_internal_command(argc, argv, envp);
@@ -360,7 +360,7 @@ int main(int argc, const char **argv, char **envp)
argc--;
handle_options(&argv, &argc);
if (argc > 0) {
- if (!strncmp(argv[0], "--", 2))
+ if (!prefixcmp(argv[0], "--"))
argv[0] += 2;
} else {
/* Default command: "help" */
diff --git a/help.c b/help.c
index b6674635a..0893fea02 100644
--- a/help.c
+++ b/help.c
@@ -130,7 +130,7 @@ static void list_commands(const char *exec_path, const char *pattern)
struct stat st;
int entlen;
- if (strncmp(de->d_name, "git-", 4))
+ if (prefixcmp(de->d_name, "git-"))
continue;
strcpy(path+dirlen, de->d_name);
if (stat(path, &st) || /* stat, not lstat */
@@ -179,7 +179,7 @@ static void show_man_page(const char *git_cmd)
{
const char *page;
- if (!strncmp(git_cmd, "git", 3))
+ if (!prefixcmp(git_cmd, "git"))
page = git_cmd;
else {
int page_len = strlen(git_cmd) + 4;
diff --git a/http-fetch.c b/http-fetch.c
index 9f790a08e..e6cd11db7 100644
--- a/http-fetch.c
+++ b/http-fetch.c
@@ -717,8 +717,8 @@ static int fetch_indices(struct alt_base *repo)
case 'P':
i++;
if (i + 52 <= buffer.posn &&
- !strncmp(data + i, " pack-", 6) &&
- !strncmp(data + i + 46, ".pack\n", 6)) {
+ !prefixcmp(data + i, " pack-") &&
+ !prefixcmp(data + i + 46, ".pack\n")) {
get_sha1_hex(data + i + 6, sha1);
setup_index(repo, sha1);
i += 51;
diff --git a/http-push.c b/http-push.c
index b128c0146..9ad6fd00b 100644
--- a/http-push.c
+++ b/http-push.c
@@ -1060,8 +1060,8 @@ static int fetch_indices(void)
case 'P':
i++;
if (i + 52 < buffer.posn &&
- !strncmp(data + i, " pack-", 6) &&
- !strncmp(data + i + 46, ".pack\n", 6)) {
+ !prefixcmp(data + i, " pack-") &&
+ !prefixcmp(data + i + 46, ".pack\n")) {
get_sha1_hex(data + i + 6, sha1);
setup_index(sha1);
i += 51;
@@ -1206,11 +1206,11 @@ static void handle_new_lock_ctx(struct xml_ctx *ctx, int tag_closed)
lock->owner = xmalloc(strlen(ctx->cdata) + 1);
strcpy(lock->owner, ctx->cdata);
} else if (!strcmp(ctx->name, DAV_ACTIVELOCK_TIMEOUT)) {
- if (!strncmp(ctx->cdata, "Second-", 7))
+ if (!prefixcmp(ctx->cdata, "Second-"))
lock->timeout =
strtol(ctx->cdata + 7, NULL, 10);
} else if (!strcmp(ctx->name, DAV_ACTIVELOCK_TOKEN)) {
- if (!strncmp(ctx->cdata, "opaquelocktoken:", 16)) {
+ if (!prefixcmp(ctx->cdata, "opaquelocktoken:")) {
lock->token = xmalloc(strlen(ctx->cdata) - 15);
strcpy(lock->token, ctx->cdata + 16);
}
@@ -2168,7 +2168,7 @@ static void fetch_symref(const char *path, char **symref, unsigned char *sha1)
return;
/* If it's a symref, set the refname; otherwise try for a sha1 */
- if (!strncmp((char *)buffer.buffer, "ref: ", 5)) {
+ if (!prefixcmp((char *)buffer.buffer, "ref: ")) {
*symref = xmalloc(buffer.posn - 5);
strlcpy(*symref, (char *)buffer.buffer + 5, buffer.posn - 5);
} else {
diff --git a/imap-send.c b/imap-send.c
index 3eaf02572..84df2fabb 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -1192,7 +1192,7 @@ count_messages( msg_data_t *msg )
char *p = msg->data;
while (1) {
- if (!strncmp( "From ", p, 5 )) {
+ if (!prefixcmp(p, "From ")) {
count++;
p += 5;
}
@@ -1216,7 +1216,7 @@ split_msg( msg_data_t *all_msgs, msg_data_t *msg, int *ofs )
data = &all_msgs->data[ *ofs ];
msg->len = all_msgs->len - *ofs;
- if (msg->len < 5 || strncmp( data, "From ", 5 ))
+ if (msg->len < 5 || prefixcmp(data, "From "))
return 0;
p = strchr( data, '\n' );
@@ -1267,12 +1267,12 @@ git_imap_config(const char *key, const char *val)
imap_folder = xstrdup( val );
} else if (!strcmp( "host", key )) {
{
- if (!strncmp( "imap:", val, 5 ))
+ if (!prefixcmp(val, "imap:"))
val += 5;
if (!server.port)
server.port = 143;
}
- if (!strncmp( "//", val, 2 ))
+ if (!prefixcmp(val, "//"))
val += 2;
server.host = xstrdup( val );
}
diff --git a/index-pack.c b/index-pack.c
index 72e096241..fa9a0e748 100644
--- a/index-pack.c
+++ b/index-pack.c
@@ -849,9 +849,9 @@ int main(int argc, char **argv)
fix_thin_pack = 1;
} else if (!strcmp(arg, "--keep")) {
keep_msg = "";
- } else if (!strncmp(arg, "--keep=", 7)) {
+ } else if (!prefixcmp(arg, "--keep=")) {
keep_msg = arg + 7;
- } else if (!strncmp(arg, "--pack_header=", 14)) {
+ } else if (!prefixcmp(arg, "--pack_header=")) {
struct pack_header *hdr;
char *c;
diff --git a/peek-remote.c b/peek-remote.c
index ef3c76ce5..96bfac498 100644
--- a/peek-remote.c
+++ b/peek-remote.c
@@ -35,11 +35,11 @@ int main(int argc, char **argv)
char *arg = argv[i];
if (*arg == '-') {
- if (!strncmp("--upload-pack=", arg, 14)) {
+ if (!prefixcmp(arg, "--upload-pack=")) {
uploadpack = arg + 14;
continue;
}
- if (!strncmp("--exec=", arg, 7)) {
+ if (!prefixcmp(arg, "--exec=")) {
uploadpack = arg + 7;
continue;
}
diff --git a/perl/Git.pm b/perl/Git.pm
index f2c156cde..b5b1cf5ed 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -516,6 +516,36 @@ sub config {
}
+=item config_boolean ( VARIABLE )
+
+Retrieve the boolean configuration C<VARIABLE>.
+
+Must be called on a repository instance.
+
+This currently wraps command('config') so it is not so fast.
+
+=cut
+
+sub config_boolean {
+ my ($self, $var) = @_;
+ $self->repo_path()
+ or throw Error::Simple("not a repository");
+
+ try {
+ return $self->command_oneline('config', '--bool', '--get',
+ $var);
+ } catch Git::Error::Command with {
+ my $E = shift;
+ if ($E->value() == 1) {
+ # Key not found.
+ return undef;
+ } else {
+ throw $E;
+ }
+ };
+}
+
+
=item ident ( TYPE | IDENTSTR )
=item ident_person ( TYPE | IDENTSTR | IDENTARRAY )
diff --git a/read-cache.c b/read-cache.c
index c54a61187..605b35239 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -344,16 +344,17 @@ int add_file_to_index(const char *path, int verbose)
ce->ce_flags = htons(namelen);
fill_stat_cache_info(ce, &st);
- ce->ce_mode = create_ce_mode(st.st_mode);
- if (!trust_executable_bit) {
+ if (trust_executable_bit)
+ ce->ce_mode = create_ce_mode(st.st_mode);
+ else {
/* If there is an existing entry, pick the mode bits
* from it, otherwise assume unexecutable.
*/
+ struct cache_entry *ent;
int pos = cache_name_pos(path, namelen);
- if (pos >= 0)
- ce->ce_mode = active_cache[pos]->ce_mode;
- else if (S_ISREG(st.st_mode))
- ce->ce_mode = create_ce_mode(S_IFREG | 0666);
+
+ ent = (0 <= pos) ? active_cache[pos] : NULL;
+ ce->ce_mode = ce_mode_from_stat(ent, st.st_mode);
}
if (index_path(ce->sha1, path, &st, 1))
diff --git a/receive-pack.c b/receive-pack.c
index 7311c822d..7f1dcc045 100644
--- a/receive-pack.c
+++ b/receive-pack.c
@@ -109,7 +109,7 @@ static int update(struct command *cmd)
struct ref_lock *lock;
cmd->error_string = NULL;
- if (!strncmp(name, "refs/", 5) && check_ref_format(name + 5)) {
+ if (!prefixcmp(name, "refs/") && check_ref_format(name + 5)) {
cmd->error_string = "funny refname";
return error("refusing to create funny ref '%s' locally",
name);
@@ -125,7 +125,7 @@ static int update(struct command *cmd)
}
if (deny_non_fast_forwards && !is_null_sha1(new_sha1) &&
!is_null_sha1(old_sha1) &&
- !strncmp(name, "refs/heads/", 11)) {
+ !prefixcmp(name, "refs/heads/")) {
struct commit *old_commit, *new_commit;
struct commit_list *bases, *ent;
diff --git a/refs.c b/refs.c
index 638770378..d347876c8 100644
--- a/refs.c
+++ b/refs.c
@@ -828,8 +828,8 @@ int rename_ref(const char *oldref, const char *newref, const char *logmsg)
goto rollback;
}
- if (!strncmp(oldref, "refs/heads/", 11) &&
- !strncmp(newref, "refs/heads/", 11)) {
+ if (!prefixcmp(oldref, "refs/heads/") &&
+ !prefixcmp(newref, "refs/heads/")) {
char oldsection[1024], newsection[1024];
snprintf(oldsection, 1024, "branch.%s", oldref + 11);
@@ -894,8 +894,8 @@ static int log_ref_write(const char *ref_name, const unsigned char *old_sha1,
log_file = git_path("logs/%s", ref_name);
if (log_all_ref_updates &&
- (!strncmp(ref_name, "refs/heads/", 11) ||
- !strncmp(ref_name, "refs/remotes/", 13) ||
+ (!prefixcmp(ref_name, "refs/heads/") ||
+ !prefixcmp(ref_name, "refs/remotes/") ||
!strcmp(ref_name, "HEAD"))) {
if (safe_create_leading_directories(log_file) < 0)
return error("unable to create directory for %s",
diff --git a/revision.c b/revision.c
index 15bdaf609..622afe3aa 100644
--- a/revision.c
+++ b/revision.c
@@ -813,11 +813,11 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
const char *arg = argv[i];
if (*arg == '-') {
int opts;
- if (!strncmp(arg, "--max-count=", 12)) {
+ if (!prefixcmp(arg, "--max-count=")) {
revs->max_count = atoi(arg + 12);
continue;
}
- if (!strncmp(arg, "--skip=", 7)) {
+ if (!prefixcmp(arg, "--skip=")) {
revs->skip_count = atoi(arg + 7);
continue;
}
@@ -832,31 +832,31 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
revs->max_count = atoi(argv[++i]);
continue;
}
- if (!strncmp(arg,"-n",2)) {
+ if (!prefixcmp(arg, "-n")) {
revs->max_count = atoi(arg + 2);
continue;
}
- if (!strncmp(arg, "--max-age=", 10)) {
+ if (!prefixcmp(arg, "--max-age=")) {
revs->max_age = atoi(arg + 10);
continue;
}
- if (!strncmp(arg, "--since=", 8)) {
+ if (!prefixcmp(arg, "--since=")) {
revs->max_age = approxidate(arg + 8);
continue;
}
- if (!strncmp(arg, "--after=", 8)) {
+ if (!prefixcmp(arg, "--after=")) {
revs->max_age = approxidate(arg + 8);
continue;
}
- if (!strncmp(arg, "--min-age=", 10)) {
+ if (!prefixcmp(arg, "--min-age=")) {
revs->min_age = atoi(arg + 10);
continue;
}
- if (!strncmp(arg, "--before=", 9)) {
+ if (!prefixcmp(arg, "--before=")) {
revs->min_age = approxidate(arg + 9);
continue;
}
- if (!strncmp(arg, "--until=", 8)) {
+ if (!prefixcmp(arg, "--until=")) {
revs->min_age = approxidate(arg + 8);
continue;
}
@@ -944,7 +944,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
revs->num_ignore_packed = 0;
continue;
}
- if (!strncmp(arg, "--unpacked=", 11)) {
+ if (!prefixcmp(arg, "--unpacked=")) {
revs->unpacked = 1;
add_ignore_packed(revs, arg+11);
continue;
@@ -980,7 +980,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
revs->verbose_header = 1;
continue;
}
- if (!strncmp(arg, "--pretty", 8)) {
+ if (!prefixcmp(arg, "--pretty")) {
revs->verbose_header = 1;
revs->commit_format = get_commit_format(arg+8);
continue;
@@ -1005,7 +1005,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
revs->abbrev = DEFAULT_ABBREV;
continue;
}
- if (!strncmp(arg, "--abbrev=", 9)) {
+ if (!prefixcmp(arg, "--abbrev=")) {
revs->abbrev = strtoul(arg + 9, NULL, 10);
if (revs->abbrev < MINIMUM_ABBREV)
revs->abbrev = MINIMUM_ABBREV;
@@ -1034,15 +1034,15 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
/*
* Grepping the commit log
*/
- if (!strncmp(arg, "--author=", 9)) {
+ if (!prefixcmp(arg, "--author=")) {
add_header_grep(revs, "author", arg+9);
continue;
}
- if (!strncmp(arg, "--committer=", 12)) {
+ if (!prefixcmp(arg, "--committer=")) {
add_header_grep(revs, "committer", arg+12);
continue;
}
- if (!strncmp(arg, "--grep=", 7)) {
+ if (!prefixcmp(arg, "--grep=")) {
add_message_grep(revs, arg+7);
continue;
}
@@ -1050,7 +1050,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
all_match = 1;
continue;
}
- if (!strncmp(arg, "--encoding=", 11)) {
+ if (!prefixcmp(arg, "--encoding=")) {
arg += 11;
if (strcmp(arg, "none"))
git_log_output_encoding = strdup(arg);
@@ -1058,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) {
@@ -1286,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)
diff --git a/revision.h b/revision.h
index d93481f68..5fec1846f 100644
--- a/revision.h
+++ b/revision.h
@@ -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,
diff --git a/send-pack.c b/send-pack.c
index 33e69dbe1..512b660e9 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -379,11 +379,11 @@ int main(int argc, char **argv)
char *arg = *argv;
if (*arg == '-') {
- if (!strncmp(arg, "--receive-pack=", 15)) {
+ if (!prefixcmp(arg, "--receive-pack=")) {
receivepack = arg + 15;
continue;
}
- if (!strncmp(arg, "--exec=", 7)) {
+ if (!prefixcmp(arg, "--exec=")) {
receivepack = arg + 7;
continue;
}
diff --git a/setup.c b/setup.c
index e9d3f5aab..dda67d268 100644
--- a/setup.c
+++ b/setup.c
@@ -251,7 +251,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
offset++;
cwd[len++] = '/';
cwd[len] = 0;
- inside_git_dir = !strncmp(cwd + offset, ".git/", 5);
+ inside_git_dir = !prefixcmp(cwd + offset, ".git/");
return cwd + offset;
}
diff --git a/sha1_file.c b/sha1_file.c
index 8ad7fad82..9a1dee051 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -407,7 +407,6 @@ static unsigned int peak_pack_open_windows;
static unsigned int pack_open_windows;
static size_t peak_pack_mapped;
static size_t pack_mapped;
-static size_t page_size;
struct packed_git *packed_git;
void pack_report()
@@ -416,7 +415,7 @@ void pack_report()
"pack_report: getpagesize() = %10" SZ_FMT "\n"
"pack_report: core.packedGitWindowSize = %10" SZ_FMT "\n"
"pack_report: core.packedGitLimit = %10" SZ_FMT "\n",
- page_size,
+ (size_t) getpagesize(),
packed_git_window_size,
packed_git_limit);
fprintf(stderr,
@@ -662,10 +661,9 @@ unsigned char* use_pack(struct packed_git *p,
break;
}
if (!win) {
- if (!page_size)
- page_size = getpagesize();
+ size_t window_align = packed_git_window_size / 2;
win = xcalloc(1, sizeof(*win));
- win->offset = (offset / page_size) * page_size;
+ win->offset = (offset / window_align) * window_align;
win->len = p->pack_size - win->offset;
if (win->len > packed_git_window_size)
win->len = packed_git_window_size;
@@ -1547,11 +1545,13 @@ int pretend_sha1_file(void *buf, unsigned long len, const char *type, unsigned c
co = &cached_objects[cached_object_nr++];
co->size = len;
co->type = strdup(type);
+ co->buf = xmalloc(len);
+ memcpy(co->buf, buf, len);
hashcpy(co->sha1, sha1);
return 0;
}
-void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size)
+void *read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size)
{
unsigned long mapsize;
void *map, *buf;
@@ -2082,7 +2082,7 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, con
{
unsigned long size = st->st_size;
void *buf;
- int ret;
+ int ret, re_allocated = 0;
buf = "";
if (size)
@@ -2091,11 +2091,30 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, con
if (!type)
type = blob_type;
- /* FIXME: CRLF -> LF conversion here for blobs! We'll need the path! */
+
+ /*
+ * Convert blobs to git internal format
+ */
+ if (!strcmp(type, blob_type)) {
+ unsigned long nsize = size;
+ char *nbuf = buf;
+ if (convert_to_git(NULL, &nbuf, &nsize)) {
+ if (size)
+ munmap(buf, size);
+ size = nsize;
+ buf = nbuf;
+ re_allocated = 1;
+ }
+ }
+
if (write_object)
ret = write_sha1_file(buf, size, type, sha1);
else
ret = hash_sha1_file(buf, size, type, sha1);
+ if (re_allocated) {
+ free(buf);
+ return ret;
+ }
if (size)
munmap(buf, size);
return ret;
diff --git a/shell.c b/shell.c
index 8c08cf0fb..c983fc7b8 100644
--- a/shell.c
+++ b/shell.c
@@ -8,7 +8,7 @@ static int do_generic_cmd(const char *me, char *arg)
if (!arg || !(arg = sq_dequote(arg)))
die("bad argument");
- if (strncmp(me, "git-", 4))
+ if (prefixcmp(me, "git-"))
die("bad command");
my_argv[0] = me + 4;
diff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh
new file mode 100755
index 000000000..723b29ad1
--- /dev/null
+++ b/t/t0020-crlf.sh
@@ -0,0 +1,217 @@
+#!/bin/sh
+
+test_description='CRLF conversion'
+
+. ./test-lib.sh
+
+append_cr () {
+ sed -e 's/$/Q/' | tr Q '\015'
+}
+
+remove_cr () {
+ tr '\015' Q <"$1" | grep Q >/dev/null &&
+ tr '\015' Q <"$1" | sed -ne 's/Q$//p'
+}
+
+test_expect_success setup '
+
+ git repo-config core.autocrlf false &&
+
+ for w in Hello world how are you; do echo $w; done >one &&
+ mkdir dir &&
+ for w in I am very very fine thank you; do echo $w; done >dir/two &&
+ git add . &&
+
+ git commit -m initial &&
+
+ one=`git rev-parse HEAD:one` &&
+ dir=`git rev-parse HEAD:dir` &&
+ two=`git rev-parse HEAD:dir/two` &&
+
+ for w in Some extra lines here; do echo $w; done >>one &&
+ git diff >patch.file &&
+ patched=`git hash-object --stdin <one` &&
+ git read-tree --reset -u HEAD &&
+
+ echo happy.
+'
+
+test_expect_success 'update with autocrlf=input' '
+
+ rm -f tmp one dir/two &&
+ git read-tree --reset -u HEAD &&
+ git repo-config core.autocrlf input &&
+
+ for f in one dir/two
+ do
+ append_cr <$f >tmp && mv -f tmp $f &&
+ git update-index -- $f || {
+ echo Oops
+ false
+ break
+ }
+ done &&
+
+ differs=`git diff-index --cached HEAD` &&
+ test -z "$differs" || {
+ echo Oops "$differs"
+ false
+ }
+
+'
+
+test_expect_success 'update with autocrlf=true' '
+
+ rm -f tmp one dir/two &&
+ git read-tree --reset -u HEAD &&
+ git repo-config core.autocrlf true &&
+
+ for f in one dir/two
+ do
+ append_cr <$f >tmp && mv -f tmp $f &&
+ git update-index -- $f || {
+ echo "Oops $f"
+ false
+ break
+ }
+ done &&
+
+ differs=`git diff-index --cached HEAD` &&
+ test -z "$differs" || {
+ echo Oops "$differs"
+ false
+ }
+
+'
+
+test_expect_success 'checkout with autocrlf=true' '
+
+ rm -f tmp one dir/two &&
+ git repo-config core.autocrlf true &&
+ git read-tree --reset -u HEAD &&
+
+ for f in one dir/two
+ do
+ remove_cr "$f" >tmp && mv -f tmp $f &&
+ git update-index -- $f || {
+ echo "Eh? $f"
+ false
+ break
+ }
+ done &&
+ test "$one" = `git hash-object --stdin <one` &&
+ test "$two" = `git hash-object --stdin <dir/two` &&
+ differs=`git diff-index --cached HEAD` &&
+ test -z "$differs" || {
+ echo Oops "$differs"
+ false
+ }
+'
+
+test_expect_success 'checkout with autocrlf=input' '
+
+ rm -f tmp one dir/two &&
+ git repo-config core.autocrlf input &&
+ git read-tree --reset -u HEAD &&
+
+ for f in one dir/two
+ do
+ if remove_cr "$f" >/dev/null
+ then
+ echo "Eh? $f"
+ false
+ break
+ else
+ git update-index -- $f
+ fi
+ done &&
+ test "$one" = `git hash-object --stdin <one` &&
+ test "$two" = `git hash-object --stdin <dir/two` &&
+ differs=`git diff-index --cached HEAD` &&
+ test -z "$differs" || {
+ echo Oops "$differs"
+ false
+ }
+'
+
+test_expect_success 'apply patch (autocrlf=input)' '
+
+ rm -f tmp one dir/two &&
+ git repo-config core.autocrlf input &&
+ git read-tree --reset -u HEAD &&
+
+ git apply patch.file &&
+ test "$patched" = "`git hash-object --stdin <one`" || {
+ echo "Eh? apply without index"
+ false
+ }
+'
+
+test_expect_success 'apply patch --cached (autocrlf=input)' '
+
+ rm -f tmp one dir/two &&
+ git repo-config core.autocrlf input &&
+ git read-tree --reset -u HEAD &&
+
+ git apply --cached patch.file &&
+ test "$patched" = `git rev-parse :one` || {
+ echo "Eh? apply with --cached"
+ false
+ }
+'
+
+test_expect_success 'apply patch --index (autocrlf=input)' '
+
+ rm -f tmp one dir/two &&
+ git repo-config core.autocrlf input &&
+ git read-tree --reset -u HEAD &&
+
+ git apply --index patch.file &&
+ test "$patched" = `git rev-parse :one` &&
+ test "$patched" = `git hash-object --stdin <one` || {
+ echo "Eh? apply with --index"
+ false
+ }
+'
+
+test_expect_success 'apply patch (autocrlf=true)' '
+
+ rm -f tmp one dir/two &&
+ git repo-config core.autocrlf true &&
+ git read-tree --reset -u HEAD &&
+
+ git apply patch.file &&
+ test "$patched" = "`remove_cr one | git hash-object --stdin`" || {
+ echo "Eh? apply without index"
+ false
+ }
+'
+
+test_expect_success 'apply patch --cached (autocrlf=true)' '
+
+ rm -f tmp one dir/two &&
+ git repo-config core.autocrlf true &&
+ git read-tree --reset -u HEAD &&
+
+ git apply --cached patch.file &&
+ test "$patched" = `git rev-parse :one` || {
+ echo "Eh? apply without index"
+ false
+ }
+'
+
+test_expect_success 'apply patch --index (autocrlf=true)' '
+
+ rm -f tmp one dir/two &&
+ git repo-config core.autocrlf true &&
+ git read-tree --reset -u HEAD &&
+
+ git apply --index patch.file &&
+ test "$patched" = `git rev-parse :one` &&
+ test "$patched" = "`remove_cr one | git hash-object --stdin`" || {
+ echo "Eh? apply with --index"
+ false
+ }
+'
+
+test_done
diff --git a/t/t1200-tutorial.sh b/t/t1200-tutorial.sh
index eebe643bd..ca2c30f7a 100755
--- a/t/t1200-tutorial.sh
+++ b/t/t1200-tutorial.sh
@@ -101,7 +101,9 @@ echo "Play, play, play" >>hello
echo "Lots of fun" >>example
git commit -m 'Some fun.' -i hello example
-test_expect_failure 'git resolve now fails' 'git resolve HEAD mybranch "Merge work in mybranch"'
+test_expect_failure 'git resolve now fails' '
+ git merge -m "Merge work in mybranch" mybranch
+'
cat > hello << EOF
Hello World
@@ -134,8 +136,8 @@ Updating from VARIABLE to VARIABLE
2 files changed, 2 insertions(+), 0 deletions(-)
EOF
-git resolve HEAD master "Merge upstream changes." | \
- sed -e "1s/[0-9a-f]\{40\}/VARIABLE/g" > resolve.output
+git merge -s "Merge upstream changes." master | \
+ sed -e "1s/[0-9a-f]\{40\}/VARIABLE/g" >resolve.output
test_expect_success 'git resolve' 'cmp resolve.expect resolve.output'
cat > show-branch2.expect << EOF
diff --git a/t/t3700-add.sh b/t/t3700-add.sh
index caaab26c2..08e035220 100755
--- a/t/t3700-add.sh
+++ b/t/t3700-add.sh
@@ -30,6 +30,16 @@ test_expect_success \
*) echo fail; git-ls-files --stage xfoo1; (exit 1);;
esac'
+test_expect_success 'git-add: filemode=0 should not get confused by symlink' '
+ rm -f xfoo1 &&
+ ln -s foo xfoo1 &&
+ git-add xfoo1 &&
+ case "`git-ls-files --stage xfoo1`" in
+ 120000" "*xfoo1) echo ok;;
+ *) echo fail; git-ls-files --stage xfoo1; (exit 1);;
+ esac
+'
+
test_expect_success \
'git-update-index --add: Test that executable bit is not used...' \
'git config core.filemode 0 &&
@@ -41,6 +51,16 @@ test_expect_success \
*) echo fail; git-ls-files --stage xfoo2; (exit 1);;
esac'
+test_expect_success 'git-add: filemode=0 should not get confused by symlink' '
+ rm -f xfoo2 &&
+ ln -s foo xfoo2 &&
+ git update-index --add xfoo2 &&
+ case "`git-ls-files --stage xfoo2`" in
+ 120000" "*xfoo2) echo ok;;
+ *) echo fail; git-ls-files --stage xfoo2; (exit 1);;
+ esac
+'
+
test_expect_success \
'git-update-index --add: Test that executable bit is not used...' \
'git config core.filemode 0 &&
diff --git a/t/t4016-diff-quote.sh b/t/t4016-diff-quote.sh
index edde8f556..2e7cd5f25 100755
--- a/t/t4016-diff-quote.sh
+++ b/t/t4016-diff-quote.sh
@@ -13,6 +13,10 @@ P1='pathname with HT'
P2='pathname with SP'
P3='pathname
with LF'
+: >"$P1" 2>&1 && test -f "$P1" && rm -f "$P1" || {
+ echo >&2 'Filesystem does not support tabs in names'
+ test_done
+}
test_expect_success setup '
echo P0.0 >"$P0.0" &&
diff --git a/templates/hooks--update b/templates/hooks--update
index e8c536fb6..fd1f73d6a 100644
--- a/templates/hooks--update
+++ b/templates/hooks--update
@@ -57,7 +57,7 @@ announcerecipients=$(git-repo-config hooks.announcelist)
allowunannotated=$(git-repo-config --bool hooks.allowunannotated)
# --- Check types
-newrev_type=$(git-cat-file -t "$newrev")
+newrev_type=$(git-cat-file -t $newrev)
case "$refname","$newrev_type" in
refs/tags/*,commit)
@@ -165,7 +165,7 @@ case "$refname_type" in
baserev=$(git-merge-base $oldrev $newrev)
# Commit with a parent
- for rev in $(git-rev-list $newrev ^$baserev)
+ for rev in $(git-rev-parse --not --all | git-rev-list --stdin $newrev ^$baserev)
do
revtype=$(git-cat-file -t "$rev")
echo " via $rev ($revtype)"
@@ -190,7 +190,8 @@ case "$refname_type" in
fi
echo ""
echo $LOGBEGIN
- git-rev-list --pretty $newrev ^$baserev
+ git-rev-parse --not --all |
+ git-rev-list --stdin --pretty $newrev ^$baserev
echo $LOGEND
echo ""
echo "Diffstat:"
diff --git a/upload-pack.c b/upload-pack.c
index 3648aae1a..804bbb6c9 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -455,7 +455,7 @@ static int get_common_commits(void)
continue;
}
len = strip(line, len);
- if (!strncmp(line, "have ", 5)) {
+ if (!prefixcmp(line, "have ")) {
switch (got_sha1(line+5, sha1)) {
case -1: /* they have what we do not */
if (multi_ack && ok_to_give_up())
@@ -502,7 +502,7 @@ static void receive_needs(void)
if (!len)
break;
- if (!strncmp("shallow ", line, 8)) {
+ if (!prefixcmp(line, "shallow ")) {
unsigned char sha1[20];
struct object *object;
use_thin_pack = 0;
@@ -515,7 +515,7 @@ static void receive_needs(void)
add_object_array(object, NULL, &shallows);
continue;
}
- if (!strncmp("deepen ", line, 7)) {
+ if (!prefixcmp(line, "deepen ")) {
char *end;
use_thin_pack = 0;
depth = strtol(line + 7, &end, 0);
@@ -523,7 +523,7 @@ static void receive_needs(void)
die("Invalid deepen: %s", line);
continue;
}
- if (strncmp("want ", line, 5) ||
+ if (prefixcmp(line, "want ") ||
get_sha1_hex(line+5, sha1_buf))
die("git-upload-pack: protocol error, "
"expected to get sha, not '%s'", line);
@@ -656,7 +656,7 @@ int main(int argc, char **argv)
strict = 1;
continue;
}
- if (!strncmp(arg, "--timeout=", 10)) {
+ if (!prefixcmp(arg, "--timeout=")) {
timeout = atoi(arg+10);
continue;
}
diff --git a/wt-status.c b/wt-status.c
index 2879c3d5e..035e546ed 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -298,7 +298,7 @@ void wt_status_print(struct wt_status *s)
if (s->branch) {
const char *on_what = "On branch ";
const char *branch_name = s->branch;
- if (!strncmp(branch_name, "refs/heads/", 11))
+ if (!prefixcmp(branch_name, "refs/heads/"))
branch_name += 11;
else if (!strcmp(branch_name, "HEAD")) {
branch_name = "";
@@ -344,7 +344,7 @@ int git_status_config(const char *k, const char *v)
wt_status_use_color = git_config_colorbool(k, v);
return 0;
}
- if (!strncmp(k, "status.color.", 13) || !strncmp(k, "color.status.", 13)) {
+ if (!prefixcmp(k, "status.color.") || !prefixcmp(k, "color.status.")) {
int slot = parse_status_slot(k, 13);
color_parse(v, k, wt_status_colors[slot]);
}
diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h
index fa409d523..e874a7c46 100644
--- a/xdiff/xdiff.h
+++ b/xdiff/xdiff.h
@@ -31,7 +31,8 @@ extern "C" {
#define XDF_NEED_MINIMAL (1 << 1)
#define XDF_IGNORE_WHITESPACE (1 << 2)
#define XDF_IGNORE_WHITESPACE_CHANGE (1 << 3)
-#define XDF_WHITESPACE_FLAGS (XDF_IGNORE_WHITESPACE | XDF_IGNORE_WHITESPACE_CHANGE)
+#define XDF_IGNORE_WHITESPACE_AT_EOL (1 << 4)
+#define XDF_WHITESPACE_FLAGS (XDF_IGNORE_WHITESPACE | XDF_IGNORE_WHITESPACE_CHANGE | XDF_IGNORE_WHITESPACE_AT_EOL)
#define XDL_PATCH_NORMAL '-'
#define XDL_PATCH_REVERSE '+'
diff --git a/xdiff/xutils.c b/xdiff/xutils.c
index 1b899f32c..3653864e4 100644
--- a/xdiff/xutils.c
+++ b/xdiff/xutils.c
@@ -215,6 +215,21 @@ int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)
return 0;
}
return (i1 >= s1 && i2 >= s2);
+ } else if (flags & XDF_IGNORE_WHITESPACE_AT_EOL) {
+ for (i1 = i2 = 0; i1 < s1 && i2 < s2; ) {
+ if (l1[i1] != l2[i2]) {
+ while (i1 < s1 && isspace(l1[i1]))
+ i1++;
+ while (i2 < s2 && isspace(l2[i2]))
+ i2++;
+ if (i1 < s1 || i2 < s2)
+ return 0;
+ return 1;
+ }
+ i1++;
+ i2++;
+ }
+ return i1 >= s1 && i2 >= s2;
} else
return s1 == s2 && !memcmp(l1, l2, s1);
@@ -227,6 +242,7 @@ unsigned long xdl_hash_record(char const **data, char const *top, long flags) {
for (; ptr < top && *ptr != '\n'; ptr++) {
if (isspace(*ptr) && (flags & XDF_WHITESPACE_FLAGS)) {
+ const char *ptr2 = ptr;
while (ptr + 1 < top && isspace(ptr[1])
&& ptr[1] != '\n')
ptr++;
@@ -235,6 +251,14 @@ unsigned long xdl_hash_record(char const **data, char const *top, long flags) {
ha += (ha << 5);
ha ^= (unsigned long) ' ';
}
+ if (flags & XDF_IGNORE_WHITESPACE_AT_EOL
+ && ptr[1] != '\n') {
+ while (ptr2 != ptr + 1) {
+ ha += (ha << 5);
+ ha ^= (unsigned long) *ptr2;
+ ptr2++;
+ }
+ }
continue;
}
ha += (ha << 5);