Code

Merge branch 'ap/trackinfo' v1.6.0-rc0
authorJunio C Hamano <gitster@pobox.com>
Mon, 21 Jul 2008 01:00:27 +0000 (18:00 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 21 Jul 2008 01:00:27 +0000 (18:00 -0700)
* ap/trackinfo:
  Reword "your branch has diverged..." lines to reduce line length

198 files changed:
.mailmap
Documentation/RelNotes-1.5.6.4.txt [new file with mode: 0644]
Documentation/RelNotes-1.6.0.txt
Documentation/git-add.txt
Documentation/git-am.txt
Documentation/git-cherry-pick.txt
Documentation/git-fast-import.txt
Documentation/git-merge.txt
Documentation/git-revert.txt
Documentation/git-submodule.txt
Documentation/git-update-index.txt
Documentation/git.txt
Documentation/gitignore.txt
Documentation/technical/api-run-command.txt
Makefile
archive-tar.c
archive-zip.c
archive.c
archive.h
attr.c
builtin-add.c
builtin-apply.c
builtin-archive.c
builtin-blame.c
builtin-branch.c
builtin-cat-file.c
builtin-check-attr.c
builtin-checkout-index.c
builtin-checkout.c
builtin-clean.c
builtin-clone.c
builtin-commit.c
builtin-config.c
builtin-count-objects.c
builtin-describe.c
builtin-diff-files.c
builtin-diff-index.c
builtin-diff-tree.c
builtin-diff.c
builtin-fast-export.c
builtin-fetch-pack.c
builtin-fetch.c
builtin-fmt-merge-msg.c
builtin-for-each-ref.c
builtin-fsck.c
builtin-gc.c
builtin-grep.c
builtin-init-db.c
builtin-log.c
builtin-ls-files.c
builtin-ls-remote.c
builtin-ls-tree.c
builtin-mailinfo.c
builtin-mailsplit.c
builtin-merge-base.c
builtin-merge-recursive.c
builtin-merge.c
builtin-mv.c
builtin-name-rev.c
builtin-pack-refs.c
builtin-prune-packed.c
builtin-prune.c
builtin-push.c
builtin-reflog.c
builtin-remote.c
builtin-rerere.c
builtin-reset.c
builtin-rev-list.c
builtin-rev-parse.c
builtin-revert.c
builtin-rm.c
builtin-send-pack.c
builtin-shortlog.c
builtin-show-branch.c
builtin-symbolic-ref.c
builtin-tag.c
builtin-tar-tree.c
builtin-update-index.c
builtin-update-ref.c
builtin-upload-archive.c
builtin-verify-tag.c
builtin-write-tree.c
cache-tree.c
cache-tree.h
cache.h
compat/mingw.c
compat/mingw.h
compat/winansi.c [new file with mode: 0644]
contrib/examples/git-merge.sh
daemon.c
diff-lib.c
diff.c
diff.h
fast-import.c
fixup-builtins
git-am.sh
git-archimport.perl
git-bisect.sh
git-cvsexportcommit.perl
git-cvsimport.perl
git-cvsserver.perl
git-instaweb.sh
git-pull.sh
git-quiltimport.sh
git-rebase--interactive.sh
git-rebase.sh
git-relink.perl
git-repack.sh
git-send-email.perl
git-sh-setup.sh
git-svn.perl
hash-object.c
help.c
http-push.c
http-walker.c
index-pack.c
pack-redundant.c
parse-options.c
read-cache.c
rerere.c
revision.c
strbuf.c
strbuf.h
t/Makefile
t/aggregate-results.sh
t/lib-git-svn.sh
t/t0000-basic.sh
t/t0001-init.sh
t/t0020-crlf.sh
t/t0050-filesystem.sh
t/t1007-hash-object.sh
t/t1200-tutorial.sh
t/t1300-repo-config.sh
t/t1302-repo-version.sh
t/t1400-update-ref.sh
t/t2000-checkout-cache-clash.sh
t/t2100-update-cache-badpath.sh
t/t2103-update-index-ignore-missing.sh [new file with mode: 0755]
t/t2202-add-addremove.sh [new file with mode: 0755]
t/t3020-ls-files-error-unmatch.sh
t/t3200-branch.sh
t/t3210-pack-refs.sh
t/t3403-rebase-skip.sh
t/t3502-cherry-pick-merge.sh
t/t3600-rm.sh
t/t3700-add.sh
t/t4015-diff-whitespace.sh
t/t4018-diff-funcname.sh
t/t4103-apply-binary.sh
t/t4113-apply-ending.sh
t/t4150-am.sh
t/t4151-am-abort.sh [new file with mode: 0755]
t/t4200-rerere.sh
t/t5300-pack-object.sh
t/t5302-pack-index.sh
t/t5401-update-hooks.sh
t/t5404-tracking-branches.sh
t/t5406-remote-rejects.sh
t/t5500-fetch-pack.sh
t/t5505-remote.sh
t/t5510-fetch.sh
t/t5516-fetch-push.sh
t/t5530-upload-pack-error.sh
t/t5540-http-push.sh
t/t5600-clone-fail-cleanup.sh
t/t6023-merge-file.sh
t/t6024-recursive-merge.sh
t/t6025-merge-symlinks.sh
t/t6101-rev-parse-parents.sh
t/t7001-mv.sh
t/t7004-tag.sh
t/t7102-reset.sh
t/t7103-reset-bare.sh
t/t7300-clean.sh
t/t7400-submodule-basic.sh
t/t7402-submodule-rebase.sh
t/t7500-commit.sh
t/t7501-commit.sh
t/t7503-pre-commit-hook.sh
t/t7504-commit-msg-hook.sh
t/t7600-merge.sh
t/t7610-mergetool.sh
t/t9001-send-email.sh
t/t9100-git-svn-basic.sh
t/t9106-git-svn-commit-diff-clobber.sh
t/t9106-git-svn-dcommit-clobber-series.sh
t/t9200-git-cvsexportcommit.sh
t/t9300-fast-import.sh
t/t9301-fast-export.sh
t/t9400-git-cvsserver-server.sh
t/t9600-cvsimport.sh
t/test-lib.sh
tree-diff.c
tree.c
tree.h
update-server-info.c
wrapper.c
write_or_die.c

index f88ae77a1f298004320bb8cc9e6a2bd9b0cafd06..373476bdc03f718b4c01471dd9996ee4497f43a8 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -5,22 +5,28 @@
 # same person appearing not to be so.
 #
 
+Alexander Gavrilov <angavrilov@gmail.com>
 Aneesh Kumar K.V <aneesh.kumar@gmail.com>
 Brian M. Carlson <sandals@crustytoothpaste.ath.cx>
 Chris Shoemaker <c.shoemaker@cox.net>
 Dana L. How <danahow@gmail.com>
 Dana L. How <how@deathvalley.cswitch.com>
 Daniel Barkalow <barkalow@iabervon.org>
+David D. Kilzer <ddkilzer@kilzer.net>
 David Kågedal <davidk@lysator.liu.se>
+David S. Miller <davem@davemloft.net>
+Dirk Süsserott <newsletter@dirk.my1.cc>
 Fredrik Kuivinen <freku045@student.liu.se>
 H. Peter Anvin <hpa@bonde.sc.orionmulti.com>
 H. Peter Anvin <hpa@tazenda.sc.orionmulti.com>
 H. Peter Anvin <hpa@trantor.hos.anvin.org>
 Horst H. von Brand <vonbrand@inf.utfsm.cl>
+İsmail Dönmez <ismail@pardus.org.tr>
 Jay Soffian <jaysoffian+git@gmail.com>
 Joachim Berdal Haga <cjhaga@fys.uio.no>
 Jon Loeliger <jdl@freescale.com>
 Jon Seymour <jon@blackcubes.dyndns.org>
+Jonathan Nieder <jrnieder@uchicago.edu>
 Junio C Hamano <junio@twinsun.com>
 Karl Hasselström <kha@treskal.com>
 Kent Engstrom <kent@lysator.liu.se>
@@ -30,9 +36,12 @@ Li Hong <leehong@pku.edu.cn>
 Lukas Sandström <lukass@etek.chalmers.se>
 Martin Langhoff <martin@catalyst.net.nz>
 Michael Coleman <tutufan@gmail.com>
+Michael W. Olson <mwolson@gnu.org>
 Michele Ballabio <barra_cuda@katamail.com>
 Nanako Shiraishi <nanako3@bluebottle.com>
+Nanako Shiraishi <nanako3@lavabit.com>
 Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
+Philippe Bruhat <book@cpan.org>
 Ramsay Allan Jones <ramsay@ramsay1.demon.co.uk>
 René Scharfe <rene.scharfe@lsrfire.ath.cx>
 Robert Fitzsimons <robfitz@273k.net>
diff --git a/Documentation/RelNotes-1.5.6.4.txt b/Documentation/RelNotes-1.5.6.4.txt
new file mode 100644 (file)
index 0000000..d8968f1
--- /dev/null
@@ -0,0 +1,47 @@
+GIT v1.5.6.4 Release Notes
+==========================
+
+Fixes since v1.5.6.3
+--------------------
+
+* Various commands could overflow its internal buffer on a platform
+  with small PATH_MAX value in a repository that has contents with
+  long pathnames.
+
+* There wasn't a way to make --pretty=format:%<> specifiers to honor
+  .mailmap name rewriting for authors and committers.  Now you can with
+  %aN and %cN.
+
+* Bash completion wasted too many cycles; this has been optimized to be
+  usable again.
+
+* Bash completion lost ref part when completing something like "git show
+  pu:Makefile".
+
+* "git-cvsserver" did not clean up its temporary working area after annotate
+  request.
+
+* "git-daemon" called syslog() from its signal handler, which was a
+  no-no.
+
+* "git-fetch" into an empty repository used to remind that the fetch will
+   be huge by saying "no common commits", but this was an unnecessary
+   noise; it is already known by the user anyway.
+
+* "git-http-fetch" would have segfaulted when pack idx file retrieved
+  from the other side was corrupt.
+
+* "git-index-pack" used too much memory when dealing with a deep delta chain.
+
+* "git-mailinfo" (hence "git-am") did not correctly handle in-body [PATCH]
+  line to override the commit title taken from the mail Subject header.
+
+* "git-rebase -i -p" lost parents that are not involved in the history
+  being rewritten.
+
+* "git-rm" lost track of where the index file was when GIT_DIR was
+  specified as a relative path.
+
+* "git-rev-list --quiet" was not quiet as advertised.
+
+Contains other various documentation fixes.
index 89ea1e9385bdea0ec42891c1f5ac7763cdbf8a73..7da62d08d6a18332eb7b3a492f8c9435f9f77396 100644 (file)
@@ -21,13 +21,19 @@ main git.git codebase.
 By default, packfiles created with this version uses delta-base-offset
 encoding introduced in v1.4.4.  Pack idx files are using version 2 that
 allows larger packs and added robustness thanks to its CRC checking,
-introduced in v1.5.2.
+introduced in v1.5.2 and v1.4.4.5.  If you want to keep your repositories
+backwards compatible past these versions, set repack.useDeltaBaseOffset
+to false or pack.indexVersion to 1, respectively.
 
 GIT_CONFIG, which was only documented as affecting "git config", but
 actually affected all git commands, now only affects "git config".
 GIT_LOCAL_CONFIG, also only documented as affecting "git config" and
 not different from GIT_CONFIG in a useful way, is removed.
 
+The ".dotest" temporary area "git am" and "git rebase" use is now moved
+inside the $GIT_DIR, to avoid mistakes of adding it to the project by
+accident.
+
 An ancient merge strategy "stupid" has been removed.
 
 
@@ -67,7 +73,8 @@ Updates since v1.5.6
 
 (performance, robustness, sanity etc.)
 
-* even more documentation pages are now accessible via "man" and "git help".
+* index-pack used too much memory when dealing with a deep delta chain.
+  This has been optimized.
 
 * reduced excessive inlining to shrink size of the "git" binary.
 
@@ -79,6 +86,8 @@ Updates since v1.5.6
   repack -a -f" can be used to fix such a corruption as long as necessary
   objects are available.
 
+* Performance of "git-blame -C -C" operation is vastly improved.
+
 * git-clone does not create refs in loose form anymore (it behaves as
   if you immediately ran git-pack-refs after cloning).  This will help
   repositories with insanely large number of refs.
@@ -92,6 +101,8 @@ Updates since v1.5.6
 
 (usability, bells and whistles)
 
+* even more documentation pages are now accessible via "man" and "git help".
+
 * A new environment variable GIT_CEILING_DIRECTORIES can be used to stop
   the discovery process of the toplevel of working tree; this may be useful
   when you are working in a slow network disk and are outside any working tree,
@@ -125,6 +136,9 @@ Updates since v1.5.6
 * git-archive can be told to omit certain paths from its output using
   export-ignore attributes.
 
+* git-archive uses the zlib default compression level when creating
+  zip archive.
+
 * With -v option, git-branch describes the remote tracking statistics
   similar to the way git-checkout reports by how many commits your branch
   is ahead/behind.
@@ -144,6 +158,8 @@ Updates since v1.5.6
 * git-clone can clone from a remote whose URL would be rewritten by
   configuration stored in $HOME/.gitconfig now.
 
+* git-cvsserver learned to respond to "cvs co -c".
+
 * git-diff --check now checks leftover merge conflict markers.
 
 * When remote side used to have branch 'foo' and git-fetch finds that now
@@ -155,6 +171,8 @@ Updates since v1.5.6
 * fast-export learned to export and import marks file; this can be used to
   interface with fast-import incrementally.
 
+* fast-import and fast-export learned to export and import gitlinks.
+
 * git-rebase records the original tip of branch in ORIG_HEAD before it is
   rewound.
 
@@ -188,6 +206,8 @@ Updates since v1.5.6
 
 (internal)
 
+* git-merge has been reimplemented in C.
+
 
 Fixes since v1.5.6
 ------------------
@@ -195,12 +215,8 @@ Fixes since v1.5.6
 All of the fixes in v1.5.6 maintenance series are included in
 this release, unless otherwise noted.
 
- * "git fetch" into an empty repository used to remind the fetch will
-   be huge by saying "no common commits", but it is already known by
-   the user anyway (need to backport 8cb560f to 'maint').
-
 ---
 exec >/var/tmp/1
-O=v1.5.6.3-350-g499027b
+O=v1.5.6.4-432-g6796399
 echo O=$(git describe refs/heads/master)
 git shortlog --no-merges $O..refs/heads/master ^refs/heads/maint
index 3558905a92a20f1f615a48821638ce239ecb6232..2b6d6c86547b2cec370d34b14ddef25264404892 100644 (file)
@@ -9,7 +9,7 @@ SYNOPSIS
 --------
 [verse]
 'git add' [-n] [-v] [--force | -f] [--interactive | -i] [--patch | -p]
-         [--update | -u] [--refresh] [--ignore-errors] [--]
+         [--all | [--update | -u]] [--refresh] [--ignore-errors] [--]
          <filepattern>...
 
 DESCRIPTION
@@ -86,6 +86,12 @@ OPTIONS
        command line. If no paths are specified, all tracked files in the
        current directory and its subdirectories are updated.
 
+-A::
+--all::
+       Update files that git already knows about (same as '\--update')
+       and add all untracked files that are not ignored by '.gitignore'
+       mechanism.
+
 --refresh::
        Don't add the file(s), but only refresh their stat()
        information in the index.
index 2d7f162594cb69d5a5f6d8ef1714111ad0bbc67a..e010a164930362dea6990a4e3dda1655bc8c3500 100644 (file)
@@ -13,7 +13,7 @@ SYNOPSIS
          [--3way] [--interactive] [--binary]
          [--whitespace=<option>] [-C<n>] [-p<n>]
         [<mbox> | <Maildir>...]
-'git am' (--skip | --resolved)
+'git am' (--skip | --resolved | --abort)
 
 DESCRIPTION
 -----------
@@ -99,6 +99,9 @@ default.   You could use `--no-utf8` to override this.
        or `--skip` to handle the failure.  This is solely
        for internal use between 'git-rebase' and 'git-am'.
 
+--abort::
+       Restore the original branch and abort the patching operation.
+
 DISCUSSION
 ----------
 
index a691173ba13370330b97907cf751342cf1c0fe44..50fb3d5d545351ce5caf1576f529dc537d8353da 100644 (file)
@@ -58,14 +58,14 @@ OPTIONS
        Usually the command automatically creates a commit with
        a commit log message stating which commit was
        cherry-picked.  This flag applies the change necessary
-       to cherry-pick the named commit to your working tree,
-       but does not make the commit.  In addition, when this
-       option is used, your working tree does not have to match
+       to cherry-pick the named commit to your working tree
+       and the index, but does not make the commit.  In addition,
+       when this option is used, your index does not have to match
        the HEAD commit.  The cherry-pick is done against the
-       beginning state of your working tree.
+       beginning state of your index.
 +
 This is useful when cherry-picking more than one commits'
-effect to your working tree in a row.
+effect to your index in a row.
 
 -s::
 --signoff::
index 2d01d0d1000d1ed3a65a5448029e1b9f6bbe6a39..c2f483a8d2aed8dc017f3172e2d5fff4bed2c450 100644 (file)
@@ -481,6 +481,9 @@ in octal.  Git only supports the following modes:
   what you want.
 * `100755` or `755`: A normal, but executable, file.
 * `120000`: A symlink, the content of the file will be the link target.
+* `160000`: A gitlink, SHA-1 of the object refers to a commit in
+  another repository. Git links can only be specified by SHA or through
+  a commit mark. They are used to implement submodules.
 
 In both formats `<path>` is the complete path of the file to be added
 (if not already existing) or modified (if already existing).
index 019e4ca8f503e146814bf7b9f6e2ef2920d940e2..a7487d3dfdb20dc56909a7ebccaac6e3b7b36e48 100644 (file)
@@ -57,50 +57,31 @@ HOW MERGE WORKS
 
 A merge is always between the current `HEAD` and one or more
 commits (usually, branch head or tag), and the index file must
-exactly match the
-tree of `HEAD` commit (i.e. the contents of the last commit) when
-it happens.  In other words, `git diff --cached HEAD` must
-report no changes.
-
-[NOTE]
-This is a bit of a lie.  In certain special cases, your index is
-allowed to be different from the tree of the `HEAD` commit.  The most
-notable case is when your `HEAD` commit is already ahead of what
-is being merged, in which case your index can have arbitrary
-differences from your `HEAD` commit.  Also, your index entries
-may have differences from your `HEAD` commit that match
-the result of a trivial merge (e.g. you received the same patch
-from an external source to produce the same result as what you are
-merging).  For example, if a path did not exist in the common
-ancestor and your head commit but exists in the tree you are
-merging into your repository, and if you already happen to have
-that path exactly in your index, the merge does not have to
-fail.
-
-Otherwise, merge will refuse to do any harm to your repository
-(that is, it may fetch the objects from remote, and it may even
-update the local branch used to keep track of the remote branch
-with `git pull remote rbranch:lbranch`, but your working tree,
-`.git/HEAD` pointer and index file are left intact).  In addition,
-merge always sets `.git/ORIG_HEAD` to the original state of HEAD so
-a problematic merge can be removed by using `git reset ORIG_HEAD`.
-
-You may have local modifications in the working tree files.  In
-other words, 'git-diff' is allowed to report changes.
-However, the merge uses your working tree as the working area,
-and in order to prevent the merge operation from losing such
-changes, it makes sure that they do not interfere with the
-merge. Those complex tables in read-tree documentation define
-what it means for a path to "interfere with the merge".  And if
-your local modifications interfere with the merge, again, it
-stops before touching anything.
-
-So in the above two "failed merge" case, you do not have to
-worry about loss of data --- you simply were not ready to do
-a merge, so no merge happened at all.  You may want to finish
-whatever you were in the middle of doing, and retry the same
-pull after you are done and ready.
-
+match the tree of `HEAD` commit (i.e. the contents of the last commit)
+when it starts out.  In other words, `git diff --cached HEAD` must
+report no changes.  (One exception is when the changed index
+entries are already in the same state that would result from
+the merge anyway.)
+
+Three kinds of merge can happen:
+
+* The merged commit is already contained in `HEAD`. This is the
+  simplest case, called "Already up-to-date."
+
+* `HEAD` is already contained in the merged commit. This is the
+  most common case especially when involved through 'git pull':
+  you are tracking an upstream repository, committed no local
+  changes and now you want to update to a newer upstream revision.
+  Your `HEAD` (and the index) is updated to at point the merged
+  commit, without creating an extra merge commit.  This is
+  called "Fast-forward".
+
+* Both the merged commit and `HEAD` are independent and must be
+  tied together by a merge commit that has them both as its parents.
+  The rest of this section describes this "True merge" case.
+
+The chosen merge strategy merges the two commits into a single
+new source tree.
 When things cleanly merge, these things happen:
 
 1. The results are updated both in the index file and in your
@@ -142,12 +123,13 @@ After seeing a conflict, you can do two things:
 
  * Decide not to merge.  The only clean-up you need are to reset
    the index file to the `HEAD` commit to reverse 2. and to clean
-   up working tree changes made by 2. and 3.; 'git-reset' can
+   up working tree changes made by 2. and 3.; 'git-reset --hard' can
    be used for this.
 
  * Resolve the conflicts.  `git diff` would report only the
-   conflicting paths because of the above 2. and 3.  Edit the
-   working tree files into a desirable shape, 'git-add' or 'git-rm'
+   conflicting paths because of the above 2. and 3.
+   Edit the working tree files into a desirable shape
+   ('git mergetool' can ease this task), '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.
 
index 5411edca96b50e28996357bf75ce4e32796ee620..271850f51134ee9b991048b5da07775b5dde65fc 100644 (file)
@@ -43,16 +43,16 @@ OPTIONS
 -n::
 --no-commit::
        Usually the command automatically creates a commit with
-       a commit log message stating which commit was reverted.
-       This flag applies the change necessary to revert the
-       named commit to your working tree, but does not make the
-       commit.  In addition, when this option is used, your
-       working tree does not have to match the HEAD commit.
-       The revert is done against the beginning state of your
-       working tree.
+       a commit log message stating which commit was
+       reverted.  This flag applies the change necessary
+       to revert the named commit to your working tree
+       and the index, but does not make the commit.  In addition,
+       when this option is used, your index does not have to match
+       the HEAD commit.  The revert is done against the
+       beginning state of your index.
 +
 This is useful when reverting more than one commits'
-effect to your working tree in a row.
+effect to your index in a row.
 
 -s::
 --signoff::
index 76702a0a5aa2b8825096ebf37f76d090a1c2627b..829b03201d0bc365983ed98034c3df284081c1d3 100644 (file)
@@ -16,6 +16,48 @@ SYNOPSIS
 'git submodule' [--quiet] summary [--summary-limit <n>] [commit] [--] [<path>...]
 
 
+DESCRIPTION
+-----------
+Submodules allow foreign repositories to be embedded within
+a dedicated subdirectory of the source tree, always pointed
+at a particular commit.
+
+They are not to be confused with remotes, which are meant mainly
+for branches of the same project; submodules are meant for
+different projects you would like to make part of your source tree,
+while the history of the two projects still stays completely
+independent and you cannot modify the contents of the submodule
+from within the main project.
+If you want to merge the project histories and want to treat the
+aggregated whole as a single project from then on, you may want to
+add a remote for the other project and use the 'subtree' merge strategy,
+instead of treating the other project as a submodule. Directories
+that come from both projects can be cloned and checked out as a whole
+if you choose to go that route.
+
+Submodules are composed from a so-called `gitlink` tree entry
+in the main repository that refers to a particular commit object
+within the inner repository that is completely separate.
+A record in the `.gitmodules` file at the root of the source
+tree assigns a logical name to the submodule and describes
+the default URL the submodule shall be cloned from.
+The logical name can be used for overriding this URL within your
+local repository configuration (see 'submodule init').
+
+This command will manage the tree entries and contents of the
+gitmodules file for you, as well as inspect the status of your
+submodules and update them.
+When adding a new submodule to the tree, the 'add' subcommand
+is to be used.  However, when pulling a tree containing submodules,
+these will not be checked out by default;
+the 'init' and 'update' subcommands will maintain submodules
+checked out and at appropriate revision in your working tree.
+You can briefly inspect the up-to-date status of your submodules
+using the 'status' subcommand and get a detailed overview of the
+difference between the index and checkouts using the 'summary'
+subcommand.
+
+
 COMMANDS
 --------
 add::
@@ -56,10 +98,15 @@ status::
        repository. This command is the default command for 'git-submodule'.
 
 init::
-       Initialize the submodules, i.e. register in .git/config each submodule
-       name and url found in .gitmodules. The key used in .git/config is
-       `submodule.$name.url`. This command does not alter existing information
-       in .git/config.
+       Initialize the submodules, i.e. register each submodule name
+       and url found in .gitmodules into .git/config.
+       The key used in .git/config is `submodule.$name.url`.
+       This command does not alter existing information in .git/config.
+       You can then customize the submodule clone URLs in .git/config
+       for your local setup and proceed to 'git submodule update';
+       you can also just use 'git submodule update --init' without
+       the explicit 'init' step if you do not intend to customize
+       any submodule locations.
 
 update::
        Update the registered submodules, i.e. clone missing submodules and
index a91fd214d2246b6fbf20543a8d285f619ecd7e58..6b930bc16303e6a17554a551badfe01febaf3ca1 100644 (file)
@@ -88,6 +88,16 @@ OPTIONS
        sometimes helpful when working with a big project on a
        filesystem that has very slow lstat(2) system call
        (e.g. cifs).
++
+This option can be also used as a coarse file-level mechanism
+to ignore uncommitted changes in tracked files (akin to what
+`.gitignore` does for untracked files).
+You should remember that an explicit 'git add' operation will
+still cause the file to be refreshed from the working tree.
+Git will fail (gracefully) in case it needs to modify this file
+in the index e.g. when merging in a commit;
+thus, in case the assumed-untracked file is changed upstream,
+you will need to handle the situation manually.
 
 -g::
 --again::
index 27b9d31f7e274b4be45891a97a984ec566927ccc..44ea35e949dbbc0e5785ba2831072059881058f8 100644 (file)
@@ -43,12 +43,13 @@ unreleased) version of git, that is available from 'master'
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
-* link:v1.5.6.3/git.html[documentation for release 1.5.6.3]
+* link:v1.5.6.4/git.html[documentation for release 1.5.6.4]
 
 * release notes for
-  link:RelNotes-1.5.6.3.txt[1.5.6.3].
-  link:RelNotes-1.5.6.2.txt[1.5.6.2].
-  link:RelNotes-1.5.6.1.txt[1.5.6.1].
+  link:RelNotes-1.5.6.4.txt[1.5.6.4],
+  link:RelNotes-1.5.6.3.txt[1.5.6.3],
+  link:RelNotes-1.5.6.2.txt[1.5.6.2],
+  link:RelNotes-1.5.6.1.txt[1.5.6.1],
   link:RelNotes-1.5.6.txt[1.5.6].
 
 * link:v1.5.5.4/git.html[documentation for release 1.5.5.4]
index fc0efd8ec8dcc791c528d0eca362172f7e445164..59321a2e82b1e141746d94c439452b52b84994ad 100644 (file)
@@ -13,9 +13,14 @@ DESCRIPTION
 -----------
 
 A `gitignore` file specifies intentionally untracked files that
-git should ignore.  Each line in a `gitignore` file specifies a
-pattern.
-
+git should ignore.
+Note that all the `gitignore` files really concern only files
+that are not already tracked by git;
+in order to ignore uncommitted changes in already tracked files,
+please refer to the 'git update-index --assume-unchanged'
+documentation.
+
+Each line in a `gitignore` file specifies a pattern.
 When deciding whether to ignore a path, git normally checks
 `gitignore` patterns from multiple sources, with the following
 order of precedence, from highest to lowest (within one level of
index 3e1342acf405adb322054a19123cd98fc12b69a9..75aa5d49234ec36857a7c8d2f3900001af5cbcde 100644 (file)
@@ -30,7 +30,7 @@ Functions
        start_command() followed by finish_command(). Takes a pointer
        to a `struct child_process` that specifies the details.
 
-`run_command_v_opt`, `run_command_v_opt_dir`, `run_command_v_opt_cd_env`::
+`run_command_v_opt`, `run_command_v_opt_cd`, `run_command_v_opt_cd_env`::
 
        Convenience functions that encapsulate a sequence of
        start_command() followed by finish_command(). The argument argv
index 9b52071b7304b5b3b2f88802210f7ed13274c0bd..551bde9ff0745e5da0bc6cfa3ab3cb915c73b298 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -324,6 +324,7 @@ endif
 export PERL_PATH
 
 LIB_FILE=libgit.a
+COMPAT_LIB = compat/lib.a
 XDIFF_LIB=xdiff/lib.a
 
 LIB_H += archive.h
@@ -741,7 +742,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
        COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat
        COMPAT_CFLAGS += -DSNPRINTF_SIZE_CORR=1
        COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
-       COMPAT_OBJS += compat/mingw.o compat/fnmatch.o compat/regex.o
+       COMPAT_OBJS += compat/mingw.o compat/fnmatch.o compat/regex.o compat/winansi.o
        EXTLIBS += -lws2_32
        X = .exe
        template_dir = ../share/git-core/templates/
@@ -1203,6 +1204,12 @@ git-http-push$X: revision.o http.o http-push.o $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
                $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
 
+$(COMPAT_LIB): $(COMPAT_OBJS)
+       $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(COMPAT_OBJS)
+
+git-shell$X: abspath.o ctype.o exec_cmd.o quote.o strbuf.o usage.o wrapper.o shell.o $(COMPAT_LIB)
+       $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(COMPAT_LIB)
+
 $(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
 $(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
 builtin-revert.o wt-status.o: wt-status.h
@@ -1298,7 +1305,7 @@ check: common-cmds.h
        for i in *.c; do sparse $(ALL_CFLAGS) $(SPARSE_FLAGS) $$i || exit; done
 
 remove-dashes:
-       ./fixup-builtins $(BUILT_INS)
+       ./fixup-builtins $(BUILT_INS) $(PROGRAMS) $(SCRIPTS)
 
 ### Installation rules
 
@@ -1399,7 +1406,7 @@ distclean: clean
 
 clean:
        $(RM) *.o mozilla-sha1/*.o arm/*.o ppc/*.o compat/*.o xdiff/*.o \
-               $(LIB_FILE) $(XDIFF_LIB)
+               $(LIB_FILE) $(XDIFF_LIB) $(COMPAT_LIB)
        $(RM) $(ALL_PROGRAMS) $(BUILT_INS) git$X
        $(RM) $(TEST_PROGRAMS)
        $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo common-cmds.h TAGS tags cscope*
index 99db58f1cf21ee30f150c54acd6ffefbb14b6f57..13029619e5ec34bac4ba61a6fc08800ab36f4a1b 100644 (file)
@@ -2,9 +2,7 @@
  * Copyright (c) 2005, 2006 Rene Scharfe
  */
 #include "cache.h"
-#include "commit.h"
 #include "tar.h"
-#include "builtin.h"
 #include "archive.h"
 
 #define RECORDSIZE     (512)
 static char block[BLOCKSIZE];
 static unsigned long offset;
 
-static time_t archive_time;
 static int tar_umask = 002;
-static int verbose;
-static const struct commit *commit;
-static size_t base_len;
 
 /* writes out the whole block, but only if it is full */
 static void write_if_needed(void)
@@ -114,22 +108,24 @@ static unsigned int ustar_header_chksum(const struct ustar_header *header)
        return chksum;
 }
 
-static int get_path_prefix(const struct strbuf *path, int maxlen)
+static size_t get_path_prefix(const char *path, size_t pathlen, size_t maxlen)
 {
-       int i = path->len;
+       size_t i = pathlen;
        if (i > maxlen)
                i = maxlen;
        do {
                i--;
-       } while (i > 0 && path->buf[i] != '/');
+       } while (i > 0 && path[i] != '/');
        return i;
 }
 
-static void write_entry(const unsigned char *sha1, struct strbuf *path,
-                        unsigned int mode, void *buffer, unsigned long size)
+static int write_tar_entry(struct archiver_args *args,
+               const unsigned char *sha1, const char *path, size_t pathlen,
+               unsigned int mode, void *buffer, unsigned long size)
 {
        struct ustar_header header;
        struct strbuf ext_header;
+       int err = 0;
 
        memset(&header, 0, sizeof(header));
        strbuf_init(&ext_header, 0);
@@ -143,8 +139,6 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
                mode = 0100666;
                sprintf(header.name, "%s.paxheader", sha1_to_hex(sha1));
        } else {
-               if (verbose)
-                       fprintf(stderr, "%.*s\n", (int)path->len, path->buf);
                if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
                        *header.typeflag = TYPEFLAG_DIR;
                        mode = (mode | 0777) & ~tar_umask;
@@ -155,24 +149,24 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
                        *header.typeflag = TYPEFLAG_REG;
                        mode = (mode | ((mode & 0100) ? 0777 : 0666)) & ~tar_umask;
                } else {
-                       error("unsupported file mode: 0%o (SHA1: %s)",
-                             mode, sha1_to_hex(sha1));
-                       return;
+                       return error("unsupported file mode: 0%o (SHA1: %s)",
+                                       mode, sha1_to_hex(sha1));
                }
-               if (path->len > sizeof(header.name)) {
-                       int plen = get_path_prefix(path, sizeof(header.prefix));
-                       int rest = path->len - plen - 1;
+               if (pathlen > sizeof(header.name)) {
+                       size_t plen = get_path_prefix(path, pathlen,
+                                       sizeof(header.prefix));
+                       size_t rest = pathlen - plen - 1;
                        if (plen > 0 && rest <= sizeof(header.name)) {
-                               memcpy(header.prefix, path->buf, plen);
-                               memcpy(header.name, path->buf + plen + 1, rest);
+                               memcpy(header.prefix, path, plen);
+                               memcpy(header.name, path + plen + 1, rest);
                        } else {
                                sprintf(header.name, "%s.data",
                                        sha1_to_hex(sha1));
                                strbuf_append_ext_header(&ext_header, "path",
-                                                        path->buf, path->len);
+                                               path, pathlen);
                        }
                } else
-                       memcpy(header.name, path->buf, path->len);
+                       memcpy(header.name, path, pathlen);
        }
 
        if (S_ISLNK(mode) && buffer) {
@@ -187,7 +181,7 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
 
        sprintf(header.mode, "%07o", mode & 07777);
        sprintf(header.size, "%011lo", S_ISREG(mode) ? size : 0);
-       sprintf(header.mtime, "%011lo", archive_time);
+       sprintf(header.mtime, "%011lo", args->time);
 
        sprintf(header.uid, "%07o", 0);
        sprintf(header.gid, "%07o", 0);
@@ -202,22 +196,30 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
        sprintf(header.chksum, "%07o", ustar_header_chksum(&header));
 
        if (ext_header.len > 0) {
-               write_entry(sha1, NULL, 0, ext_header.buf, ext_header.len);
+               err = write_tar_entry(args, sha1, NULL, 0, 0, ext_header.buf,
+                               ext_header.len);
+               if (err)
+                       return err;
        }
        strbuf_release(&ext_header);
        write_blocked(&header, sizeof(header));
        if (S_ISREG(mode) && buffer && size > 0)
                write_blocked(buffer, size);
+       return err;
 }
 
-static void write_global_extended_header(const unsigned char *sha1)
+static int write_global_extended_header(struct archiver_args *args)
 {
+       const unsigned char *sha1 = args->commit_sha1;
        struct strbuf ext_header;
+       int err;
 
        strbuf_init(&ext_header, 0);
        strbuf_append_ext_header(&ext_header, "comment", sha1_to_hex(sha1), 40);
-       write_entry(NULL, NULL, 0, ext_header.buf, ext_header.len);
+       err = write_tar_entry(args, NULL, NULL, 0, 0, ext_header.buf,
+                       ext_header.len);
        strbuf_release(&ext_header);
+       return err;
 }
 
 static int git_tar_config(const char *var, const char *value, void *cb)
@@ -234,64 +236,17 @@ static int git_tar_config(const char *var, const char *value, void *cb)
        return git_default_config(var, value, cb);
 }
 
-static int write_tar_entry(const unsigned char *sha1,
-                           const char *base, int baselen,
-                           const char *filename, unsigned mode, int stage)
-{
-       static struct strbuf path = STRBUF_INIT;
-       void *buffer;
-       enum object_type type;
-       unsigned long size;
-
-       strbuf_reset(&path);
-       strbuf_grow(&path, PATH_MAX);
-       strbuf_add(&path, base, baselen);
-       strbuf_addstr(&path, filename);
-       if (is_archive_path_ignored(path.buf + base_len))
-               return 0;
-       if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
-               strbuf_addch(&path, '/');
-               buffer = NULL;
-               size = 0;
-       } else {
-               buffer = sha1_file_to_archive(path.buf + base_len, sha1, mode,
-                               &type, &size, commit);
-               if (!buffer)
-                       die("cannot read %s", sha1_to_hex(sha1));
-       }
-
-       write_entry(sha1, &path, mode, buffer, size);
-       free(buffer);
-
-       return READ_TREE_RECURSIVE;
-}
-
 int write_tar_archive(struct archiver_args *args)
 {
-       int plen = args->base ? strlen(args->base) : 0;
+       int err = 0;
 
        git_config(git_tar_config, NULL);
 
-       archive_time = args->time;
-       verbose = args->verbose;
-       commit = args->commit;
-       base_len = args->base ? strlen(args->base) : 0;
-
        if (args->commit_sha1)
-               write_global_extended_header(args->commit_sha1);
-
-       if (args->base && plen > 0 && args->base[plen - 1] == '/') {
-               char *base = xstrdup(args->base);
-               int baselen = strlen(base);
-
-               while (baselen > 0 && base[baselen - 1] == '/')
-                       base[--baselen] = '\0';
-               write_tar_entry(args->tree->object.sha1, "", 0, base, 040777, 0);
-               free(base);
-       }
-       read_tree_recursive(args->tree, args->base, plen, 0,
-                           args->pathspec, write_tar_entry);
-       write_trailer();
-
-       return 0;
+               err = write_global_extended_header(args);
+       if (!err)
+               err = write_archive_entries(args, write_tar_entry);
+       if (!err)
+               write_trailer();
+       return err;
 }
index 5742762ac30c92e796255b74d2ed1ea087f3fba0..cf285044e3576d0127c3215cb1253443d67517dc 100644 (file)
@@ -2,18 +2,10 @@
  * Copyright (c) 2006 Rene Scharfe
  */
 #include "cache.h"
-#include "commit.h"
-#include "blob.h"
-#include "tree.h"
-#include "quote.h"
-#include "builtin.h"
 #include "archive.h"
 
-static int verbose;
 static int zip_date;
 static int zip_time;
-static const struct commit *commit;
-static size_t base_len;
 
 static unsigned char *zip_dir;
 static unsigned int zip_dir_size;
@@ -96,7 +88,7 @@ static void copy_le32(unsigned char *dest, unsigned int n)
 }
 
 static void *zlib_deflate(void *data, unsigned long size,
-                          unsigned long *compressed_size)
+               int compression_level, unsigned long *compressed_size)
 {
        z_stream stream;
        unsigned long maxsize;
@@ -104,7 +96,7 @@ static void *zlib_deflate(void *data, unsigned long size,
        int result;
 
        memset(&stream, 0, sizeof(stream));
-       deflateInit(&stream, zlib_compression_level);
+       deflateInit(&stream, compression_level);
        maxsize = deflateBound(&stream, size);
        buffer = xmalloc(maxsize);
 
@@ -128,33 +120,9 @@ static void *zlib_deflate(void *data, unsigned long size,
        return buffer;
 }
 
-static char *construct_path(const char *base, int baselen,
-                            const char *filename, int isdir, int *pathlen)
-{
-       int filenamelen = strlen(filename);
-       int len = baselen + filenamelen;
-       char *path, *p;
-
-       if (isdir)
-               len++;
-       p = path = xmalloc(len + 1);
-
-       memcpy(p, base, baselen);
-       p += baselen;
-       memcpy(p, filename, filenamelen);
-       p += filenamelen;
-       if (isdir)
-               *p++ = '/';
-       *p = '\0';
-
-       *pathlen = len;
-
-       return path;
-}
-
-static int write_zip_entry(const unsigned char *sha1,
-                           const char *base, int baselen,
-                           const char *filename, unsigned mode, int stage)
+static int write_zip_entry(struct archiver_args *args,
+               const unsigned char *sha1, const char *path, size_t pathlen,
+               unsigned int mode, void *buffer, unsigned long size)
 {
        struct zip_local_header header;
        struct zip_dir_header dirent;
@@ -163,33 +131,20 @@ static int write_zip_entry(const unsigned char *sha1,
        unsigned long uncompressed_size;
        unsigned long crc;
        unsigned long direntsize;
-       unsigned long size;
        int method;
-       int result = -1;
-       int pathlen;
        unsigned char *out;
-       char *path;
-       enum object_type type;
-       void *buffer = NULL;
        void *deflated = NULL;
 
        crc = crc32(0, NULL, 0);
 
-       path = construct_path(base, baselen, filename, S_ISDIR(mode), &pathlen);
-       if (is_archive_path_ignored(path + base_len))
-               return 0;
-       if (verbose)
-               fprintf(stderr, "%s\n", path);
        if (pathlen > 0xffff) {
-               error("path too long (%d chars, SHA1: %s): %s", pathlen,
-                     sha1_to_hex(sha1), path);
-               goto out;
+               return error("path too long (%d chars, SHA1: %s): %s",
+                               (int)pathlen, sha1_to_hex(sha1), path);
        }
 
        if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
                method = 0;
                attr2 = 16;
-               result = (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0);
                out = NULL;
                uncompressed_size = 0;
                compressed_size = 0;
@@ -197,25 +152,20 @@ static int write_zip_entry(const unsigned char *sha1,
                method = 0;
                attr2 = S_ISLNK(mode) ? ((mode | 0777) << 16) :
                        (mode & 0111) ? ((mode) << 16) : 0;
-               if (S_ISREG(mode) && zlib_compression_level != 0)
+               if (S_ISREG(mode) && args->compression_level != 0)
                        method = 8;
-               result = 0;
-               buffer = sha1_file_to_archive(path + base_len, sha1, mode,
-                               &type, &size, commit);
-               if (!buffer)
-                       die("cannot read %s", sha1_to_hex(sha1));
                crc = crc32(crc, buffer, size);
                out = buffer;
                uncompressed_size = size;
                compressed_size = size;
        } else {
-               error("unsupported file mode: 0%o (SHA1: %s)", mode,
-                     sha1_to_hex(sha1));
-               goto out;
+               return error("unsupported file mode: 0%o (SHA1: %s)", mode,
+                               sha1_to_hex(sha1));
        }
 
        if (method == 8) {
-               deflated = zlib_deflate(buffer, size, &compressed_size);
+               deflated = zlib_deflate(buffer, size, args->compression_level,
+                               &compressed_size);
                if (deflated && compressed_size - 6 < size) {
                        /* ZLIB --> raw compressed data (see RFC 1950) */
                        /* CMF and FLG ... */
@@ -278,12 +228,9 @@ static int write_zip_entry(const unsigned char *sha1,
                zip_offset += compressed_size;
        }
 
-out:
-       free(buffer);
        free(deflated);
-       free(path);
 
-       return result;
+       return 0;
 }
 
 static void write_zip_trailer(const unsigned char *sha1)
@@ -316,43 +263,18 @@ static void dos_time(time_t *time, int *dos_date, int *dos_time)
 
 int write_zip_archive(struct archiver_args *args)
 {
-       int plen = strlen(args->base);
+       int err;
 
        dos_time(&args->time, &zip_date, &zip_time);
 
        zip_dir = xmalloc(ZIP_DIRECTORY_MIN_SIZE);
        zip_dir_size = ZIP_DIRECTORY_MIN_SIZE;
-       verbose = args->verbose;
-       commit = args->commit;
-       base_len = args->base ? strlen(args->base) : 0;
-
-       if (args->base && plen > 0 && args->base[plen - 1] == '/') {
-               char *base = xstrdup(args->base);
-               int baselen = strlen(base);
-
-               while (baselen > 0 && base[baselen - 1] == '/')
-                       base[--baselen] = '\0';
-               write_zip_entry(args->tree->object.sha1, "", 0, base, 040777, 0);
-               free(base);
-       }
-       read_tree_recursive(args->tree, args->base, plen, 0,
-                           args->pathspec, write_zip_entry);
-       write_zip_trailer(args->commit_sha1);
-
-       free(zip_dir);
 
-       return 0;
-}
+       err = write_archive_entries(args, write_zip_entry);
+       if (!err)
+               write_zip_trailer(args->commit_sha1);
 
-void *parse_extra_zip_args(int argc, const char **argv)
-{
-       for (; argc > 0; argc--, argv++) {
-               const char *arg = argv[0];
+       free(zip_dir);
 
-               if (arg[0] == '-' && isdigit(arg[1]) && arg[2] == '\0')
-                       zlib_compression_level = arg[1] - '0';
-               else
-                       die("Unknown argument for zip format: %s", arg);
-       }
-       return NULL;
+       return err;
 }
index 6502b76ef10a182e9d9f0e60ad926c55a31a737a..b8b45bad77230b0258622e993dbbac3a20e3716c 100644 (file)
--- a/archive.c
+++ b/archive.c
@@ -1,6 +1,7 @@
 #include "cache.h"
 #include "commit.h"
 #include "attr.h"
+#include "archive.h"
 
 static void format_subst(const struct commit *commit,
                          const char *src, size_t len,
@@ -35,34 +36,9 @@ static void format_subst(const struct commit *commit,
        free(to_free);
 }
 
-static int convert_to_archive(const char *path,
-                              const void *src, size_t len,
-                              struct strbuf *buf,
-                              const struct commit *commit)
-{
-       static struct git_attr *attr_export_subst;
-       struct git_attr_check check[1];
-
-       if (!commit)
-               return 0;
-
-       if (!attr_export_subst)
-               attr_export_subst = git_attr("export-subst", 12);
-
-       check[0].attr = attr_export_subst;
-       if (git_checkattr(path, ARRAY_SIZE(check), check))
-               return 0;
-       if (!ATTR_TRUE(check[0].value))
-               return 0;
-
-       format_subst(commit, src, len, buf);
-       return 1;
-}
-
-void *sha1_file_to_archive(const char *path, const unsigned char *sha1,
-                           unsigned int mode, enum object_type *type,
-                           unsigned long *sizep,
-                           const struct commit *commit)
+static void *sha1_file_to_archive(const char *path, const unsigned char *sha1,
+               unsigned int mode, enum object_type *type,
+               unsigned long *sizep, const struct commit *commit)
 {
        void *buffer;
 
@@ -74,7 +50,8 @@ void *sha1_file_to_archive(const char *path, const unsigned char *sha1,
                strbuf_init(&buf, 0);
                strbuf_attach(&buf, buffer, *sizep, *sizep + 1);
                convert_to_working_tree(path, buf.buf, buf.len, &buf);
-               convert_to_archive(path, buf.buf, buf.len, &buf, commit);
+               if (commit)
+                       format_subst(commit, buf.buf, buf.len, &buf);
                buffer = strbuf_detach(&buf, &size);
                *sizep = size;
        }
@@ -82,16 +59,99 @@ void *sha1_file_to_archive(const char *path, const unsigned char *sha1,
        return buffer;
 }
 
-int is_archive_path_ignored(const char *path)
+static void setup_archive_check(struct git_attr_check *check)
 {
        static struct git_attr *attr_export_ignore;
-       struct git_attr_check check[1];
+       static struct git_attr *attr_export_subst;
 
-       if (!attr_export_ignore)
+       if (!attr_export_ignore) {
                attr_export_ignore = git_attr("export-ignore", 13);
-
+               attr_export_subst = git_attr("export-subst", 12);
+       }
        check[0].attr = attr_export_ignore;
-       if (git_checkattr(path, ARRAY_SIZE(check), check))
-               return 0;
-       return ATTR_TRUE(check[0].value);
+       check[1].attr = attr_export_subst;
+}
+
+struct archiver_context {
+       struct archiver_args *args;
+       write_archive_entry_fn_t write_entry;
+};
+
+static int write_archive_entry(const unsigned char *sha1, const char *base,
+               int baselen, const char *filename, unsigned mode, int stage,
+               void *context)
+{
+       static struct strbuf path = STRBUF_INIT;
+       struct archiver_context *c = context;
+       struct archiver_args *args = c->args;
+       write_archive_entry_fn_t write_entry = c->write_entry;
+       struct git_attr_check check[2];
+       const char *path_without_prefix;
+       int convert = 0;
+       int err;
+       enum object_type type;
+       unsigned long size;
+       void *buffer;
+
+       strbuf_reset(&path);
+       strbuf_grow(&path, PATH_MAX);
+       strbuf_add(&path, base, baselen);
+       strbuf_addstr(&path, filename);
+       path_without_prefix = path.buf + args->baselen;
+
+       setup_archive_check(check);
+       if (!git_checkattr(path_without_prefix, ARRAY_SIZE(check), check)) {
+               if (ATTR_TRUE(check[0].value))
+                       return 0;
+               convert = ATTR_TRUE(check[1].value);
+       }
+
+       if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
+               strbuf_addch(&path, '/');
+               if (args->verbose)
+                       fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
+               err = write_entry(args, sha1, path.buf, path.len, mode, NULL, 0);
+               if (err)
+                       return err;
+               return READ_TREE_RECURSIVE;
+       }
+
+       buffer = sha1_file_to_archive(path_without_prefix, sha1, mode,
+                       &type, &size, convert ? args->commit : NULL);
+       if (!buffer)
+               return error("cannot read %s", sha1_to_hex(sha1));
+       if (args->verbose)
+               fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
+       err = write_entry(args, sha1, path.buf, path.len, mode, buffer, size);
+       free(buffer);
+       return err;
+}
+
+int write_archive_entries(struct archiver_args *args,
+               write_archive_entry_fn_t write_entry)
+{
+       struct archiver_context context;
+       int err;
+
+       if (args->baselen > 0 && args->base[args->baselen - 1] == '/') {
+               size_t len = args->baselen;
+
+               while (len > 1 && args->base[len - 2] == '/')
+                       len--;
+               if (args->verbose)
+                       fprintf(stderr, "%.*s\n", (int)len, args->base);
+               err = write_entry(args, args->tree->object.sha1, args->base,
+                               len, 040777, NULL, 0);
+               if (err)
+                       return err;
+       }
+
+       context.args = args;
+       context.write_entry = write_entry;
+
+       err =  read_tree_recursive(args->tree, args->base, args->baselen, 0,
+                       args->pathspec, write_archive_entry, &context);
+       if (err == READ_TREE_RECURSIVE)
+               err = 0;
+       return err;
 }
index ddf004acdfa2125a73df11e923eda902d3ca8277..4a02371f374a159604ab55102be5ba5b9d3f7cd2 100644 (file)
--- a/archive.h
+++ b/archive.h
@@ -6,29 +6,27 @@
 
 struct archiver_args {
        const char *base;
+       size_t baselen;
        struct tree *tree;
        const unsigned char *commit_sha1;
        const struct commit *commit;
        time_t time;
        const char **pathspec;
        unsigned int verbose : 1;
-       void *extra;
+       int compression_level;
 };
 
 typedef int (*write_archive_fn_t)(struct archiver_args *);
 
-typedef void *(*parse_extra_args_fn_t)(int argc, const char **argv);
+typedef int (*write_archive_entry_fn_t)(struct archiver_args *args, const unsigned char *sha1, const char *path, size_t pathlen, unsigned int mode, void *buffer, unsigned long size);
 
 struct archiver {
        const char *name;
-       struct archiver_args args;
        write_archive_fn_t write_archive;
-       parse_extra_args_fn_t parse_extra;
+       unsigned int flags;
 };
 
-extern int parse_archive_args(int argc,
-                             const char **argv,
-                             struct archiver *ar);
+extern int parse_archive_args(int argc, const char **argv, const struct archiver **ar, struct archiver_args *args);
 
 extern void parse_treeish_arg(const char **treeish,
                              struct archiver_args *ar_args,
@@ -41,9 +39,7 @@ extern void parse_pathspec_arg(const char **pathspec,
  */
 extern int write_tar_archive(struct archiver_args *);
 extern int write_zip_archive(struct archiver_args *);
-extern void *parse_extra_zip_args(int argc, const char **argv);
 
-extern void *sha1_file_to_archive(const char *path, const unsigned char *sha1, unsigned int mode, enum object_type *type, unsigned long *size, const struct commit *commit);
-extern int is_archive_path_ignored(const char *path);
+extern int write_archive_entries(struct archiver_args *args, write_archive_entry_fn_t write_entry);
 
 #endif /* ARCHIVE_H */
diff --git a/attr.c b/attr.c
index 0fb47d34346ca96addde5cb3722fa5e586057285..17f6a4dca521d9690377f2e93a0192d8a874d2ad 100644 (file)
--- a/attr.c
+++ b/attr.c
@@ -459,7 +459,9 @@ static void prepare_attr_stack(const char *path, int dirlen)
 {
        struct attr_stack *elem, *info;
        int len;
-       char pathbuf[PATH_MAX];
+       struct strbuf pathbuf;
+
+       strbuf_init(&pathbuf, dirlen+2+strlen(GITATTRIBUTES_FILE));
 
        /*
         * At the bottom of the attribute stack is the built-in
@@ -510,13 +512,14 @@ static void prepare_attr_stack(const char *path, int dirlen)
                        len = strlen(attr_stack->origin);
                        if (dirlen <= len)
                                break;
-                       memcpy(pathbuf, path, dirlen);
-                       memcpy(pathbuf + dirlen, "/", 2);
-                       cp = strchr(pathbuf + len + 1, '/');
+                       strbuf_reset(&pathbuf);
+                       strbuf_add(&pathbuf, path, dirlen);
+                       strbuf_addch(&pathbuf, '/');
+                       cp = strchr(pathbuf.buf + len + 1, '/');
                        strcpy(cp + 1, GITATTRIBUTES_FILE);
-                       elem = read_attr(pathbuf, 0);
+                       elem = read_attr(pathbuf.buf, 0);
                        *cp = '\0';
-                       elem->origin = strdup(pathbuf);
+                       elem->origin = strdup(pathbuf.buf);
                        elem->prev = attr_stack;
                        attr_stack = elem;
                        debug_push(elem);
index 9930cf53f5e94cb7389e7c0b2b760b113a366e51..fc3f96eaefff91e4e85adb92162716939f0ecd72 100644 (file)
@@ -16,7 +16,7 @@
 #include "parse-options.h"
 
 static const char * const builtin_add_usage[] = {
-       "git-add [options] [--] <filepattern>...",
+       "git add [options] [--] <filepattern>...",
        NULL
 };
 static int patch_interactive = 0, add_interactive = 0;
@@ -140,9 +140,8 @@ static void refresh(int verbose, const char **pathspec)
        for (specs = 0; pathspec[specs];  specs++)
                /* nothing */;
        seen = xcalloc(specs, 1);
-       if (read_cache() < 0)
-               die("index file corrupt");
-       refresh_index(&the_index, verbose ? 0 : REFRESH_QUIET, pathspec, seen);
+       refresh_index(&the_index, verbose ? REFRESH_SAY_CHANGED : REFRESH_QUIET,
+                     pathspec, seen);
        for (i = 0; i < specs; i++) {
                if (!seen[i])
                        die("pathspec '%s' did not match any files", pathspec[i]);
@@ -192,7 +191,7 @@ static const char ignore_error[] =
 "The following paths are ignored by one of your .gitignore files:\n";
 
 static int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0;
-static int ignore_add_errors;
+static int ignore_add_errors, addremove;
 
 static struct option builtin_add_options[] = {
        OPT__DRY_RUN(&show_only),
@@ -202,6 +201,7 @@ static struct option builtin_add_options[] = {
        OPT_BOOLEAN('p', "patch", &patch_interactive, "interactive patching"),
        OPT_BOOLEAN('f', "force", &ignored_too, "allow adding otherwise ignored files"),
        OPT_BOOLEAN('u', "update", &take_worktree_changes, "update tracked files"),
+       OPT_BOOLEAN('A', "all", &addremove, "add all, noticing removal of tracked files"),
        OPT_BOOLEAN( 0 , "refresh", &refresh_only, "don't add, only refresh the index"),
        OPT_BOOLEAN( 0 , "ignore-errors", &ignore_add_errors, "just skip files which cannot be added because of errors"),
        OPT_END(),
@@ -216,13 +216,36 @@ static int add_config(const char *var, const char *value, void *cb)
        return git_default_config(var, value, cb);
 }
 
+static int add_files(struct dir_struct *dir, int flags)
+{
+       int i, exit_status = 0;
+
+       if (dir->ignored_nr) {
+               fprintf(stderr, ignore_error);
+               for (i = 0; i < dir->ignored_nr; i++)
+                       fprintf(stderr, "%s\n", dir->ignored[i]->name);
+               fprintf(stderr, "Use -f if you really want to add them.\n");
+               die("no files added");
+       }
+
+       for (i = 0; i < dir->nr; i++)
+               if (add_file_to_cache(dir->entries[i]->name, flags)) {
+                       if (!ignore_add_errors)
+                               die("adding files failed");
+                       exit_status = 1;
+               }
+       return exit_status;
+}
+
 int cmd_add(int argc, const char **argv, const char *prefix)
 {
        int exit_status = 0;
-       int i, newfd;
+       int newfd;
        const char **pathspec;
        struct dir_struct dir;
        int flags;
+       int add_new_files;
+       int require_pathspec;
 
        argc = parse_options(argc, argv, builtin_add_options,
                          builtin_add_usage, 0);
@@ -233,53 +256,51 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 
        git_config(add_config, NULL);
 
+       if (addremove && take_worktree_changes)
+               die("-A and -u are mutually incompatible");
+       if (addremove && !argc) {
+               static const char *here[2] = { ".", NULL };
+               argc = 1;
+               argv = here;
+       }
+
+       add_new_files = !take_worktree_changes && !refresh_only;
+       require_pathspec = !take_worktree_changes;
+
        newfd = hold_locked_index(&lock_file, 1);
 
        flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |
                 (show_only ? ADD_CACHE_PRETEND : 0) |
                 (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0));
 
-       if (take_worktree_changes) {
-               const char **pathspec;
-               if (read_cache() < 0)
-                       die("index file corrupt");
-               pathspec = get_pathspec(prefix, argv);
-               exit_status = add_files_to_cache(prefix, pathspec, flags);
-               goto finish;
-       }
-
-       if (argc == 0) {
+       if (require_pathspec && argc == 0) {
                fprintf(stderr, "Nothing specified, nothing added.\n");
                fprintf(stderr, "Maybe you wanted to say 'git add .'?\n");
                return 0;
        }
        pathspec = get_pathspec(prefix, argv);
 
-       if (refresh_only) {
-               refresh(verbose, pathspec);
-               goto finish;
-       }
-
-       fill_directory(&dir, pathspec, ignored_too);
+       /*
+        * If we are adding new files, we need to scan the working
+        * tree to find the ones that match pathspecs; this needs
+        * to be done before we read the index.
+        */
+       if (add_new_files)
+               fill_directory(&dir, pathspec, ignored_too);
 
        if (read_cache() < 0)
                die("index file corrupt");
 
-       if (dir.ignored_nr) {
-               fprintf(stderr, ignore_error);
-               for (i = 0; i < dir.ignored_nr; i++) {
-                       fprintf(stderr, "%s\n", dir.ignored[i]->name);
-               }
-               fprintf(stderr, "Use -f if you really want to add them.\n");
-               die("no files added");
+       if (refresh_only) {
+               refresh(verbose, pathspec);
+               goto finish;
        }
 
-       for (i = 0; i < dir.nr; i++)
-               if (add_file_to_cache(dir.entries[i]->name, flags)) {
-                       if (!ignore_add_errors)
-                               die("adding files failed");
-                       exit_status = 1;
-               }
+       if (take_worktree_changes || addremove)
+               exit_status |= add_files_to_cache(prefix, pathspec, flags);
+
+       if (add_new_files)
+               exit_status |= add_files(&dir, flags);
 
  finish:
        if (active_cache_changed) {
index d13313f1051eb3f7374cf4119923b230fd6f81d8..e15471b5b6d13eaffa6108535c067b5002a2b0c0 100644 (file)
@@ -46,7 +46,7 @@ static const char *fake_ancestor;
 static int line_termination = '\n';
 static unsigned long p_context = ULONG_MAX;
 static const char apply_usage[] =
-"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--cached] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [--reverse] [--reject] [--verbose] [-z] [-pNUM] [-CNUM] [--whitespace=<nowarn|warn|fix|error|error-all>] <patch>...";
+"git apply [--stat] [--numstat] [--summary] [--check] [--index] [--cached] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [--reverse] [--reject] [--verbose] [-z] [-pNUM] [-CNUM] [--whitespace=<nowarn|warn|fix|error|error-all>] <patch>...";
 
 static enum ws_error_action {
        nowarn_ws_error,
index c2e0c1ea5a676f30baa52151d9e6a2a94d4cd091..df9772469681285d69f968b59172c4aaee2eb679 100644 (file)
@@ -7,22 +7,17 @@
 #include "archive.h"
 #include "commit.h"
 #include "tree-walk.h"
-#include "exec_cmd.h"
 #include "pkt-line.h"
 #include "sideband.h"
-#include "attr.h"
 
 static const char archive_usage[] = \
-"git-archive --format=<fmt> [--prefix=<prefix>/] [--verbose] [<extra>] <tree-ish> [path...]";
+"git archive --format=<fmt> [--prefix=<prefix>/] [--verbose] [<extra>] <tree-ish> [path...]";
 
-static struct archiver_desc
-{
-       const char *name;
-       write_archive_fn_t write_archive;
-       parse_extra_args_fn_t parse_extra;
-} archivers[] = {
-       { "tar", write_tar_archive, NULL },
-       { "zip", write_zip_archive, parse_extra_zip_args },
+#define USES_ZLIB_COMPRESSION 1
+
+const struct archiver archivers[] = {
+       { "tar", write_tar_archive },
+       { "zip", write_zip_archive, USES_ZLIB_COMPRESSION },
 };
 
 static int run_remote_archiver(const char *remote, int argc,
@@ -79,21 +74,15 @@ static int run_remote_archiver(const char *remote, int argc,
        return !!rv;
 }
 
-static int init_archiver(const char *name, struct archiver *ar)
+static const struct archiver *lookup_archiver(const char *name)
 {
-       int rv = -1, i;
+       int i;
 
        for (i = 0; i < ARRAY_SIZE(archivers); i++) {
-               if (!strcmp(name, archivers[i].name)) {
-                       memset(ar, 0, sizeof(*ar));
-                       ar->name = archivers[i].name;
-                       ar->write_archive = archivers[i].write_archive;
-                       ar->parse_extra = archivers[i].parse_extra;
-                       rv = 0;
-                       break;
-               }
+               if (!strcmp(name, archivers[i].name))
+                       return &archivers[i];
        }
-       return rv;
+       return NULL;
 }
 
 void parse_pathspec_arg(const char **pathspec, struct archiver_args *ar_args)
@@ -145,12 +134,12 @@ void parse_treeish_arg(const char **argv, struct archiver_args *ar_args,
        ar_args->time = archive_time;
 }
 
-int parse_archive_args(int argc, const char **argv, struct archiver *ar)
+int parse_archive_args(int argc, const char **argv, const struct archiver **ar,
+               struct archiver_args *args)
 {
-       const char *extra_argv[MAX_EXTRA_ARGS];
-       int extra_argc = 0;
        const char *format = "tar";
        const char *base = "";
+       int compression_level = -1;
        int verbose = 0;
        int i;
 
@@ -178,29 +167,34 @@ int parse_archive_args(int argc, const char **argv, struct archiver *ar)
                        i++;
                        break;
                }
-               if (arg[0] == '-') {
-                       if (extra_argc > MAX_EXTRA_ARGS - 1)
-                               die("Too many extra options");
-                       extra_argv[extra_argc++] = arg;
+               if (arg[0] == '-' && isdigit(arg[1]) && arg[2] == '\0') {
+                       compression_level = arg[1] - '0';
                        continue;
                }
+               if (arg[0] == '-')
+                       die("Unknown argument: %s", arg);
                break;
        }
 
        /* We need at least one parameter -- tree-ish */
        if (argc - 1 < i)
                usage(archive_usage);
-       if (init_archiver(format, ar) < 0)
+       *ar = lookup_archiver(format);
+       if (!*ar)
                die("Unknown archive format '%s'", format);
 
-       if (extra_argc) {
-               if (!ar->parse_extra)
-                       die("'%s' format does not handle %s",
-                           ar->name, extra_argv[0]);
-               ar->args.extra = ar->parse_extra(extra_argc, extra_argv);
+       args->compression_level = Z_DEFAULT_COMPRESSION;
+       if (compression_level != -1) {
+               if ((*ar)->flags & USES_ZLIB_COMPRESSION)
+                       args->compression_level = compression_level;
+               else {
+                       die("Argument not supported for format '%s': -%d",
+                                       format, compression_level);
+               }
        }
-       ar->args.verbose = verbose;
-       ar->args.base = base;
+       args->verbose = verbose;
+       args->base = base;
+       args->baselen = strlen(base);
 
        return i;
 }
@@ -238,7 +232,8 @@ static const char *extract_remote_arg(int *ac, const char **av)
 
 int cmd_archive(int argc, const char **argv, const char *prefix)
 {
-       struct archiver ar;
+       const struct archiver *ar = NULL;
+       struct archiver_args args;
        int tree_idx;
        const char *remote = NULL;
 
@@ -248,14 +243,13 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
 
        setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
 
-       memset(&ar, 0, sizeof(ar));
-       tree_idx = parse_archive_args(argc, argv, &ar);
+       tree_idx = parse_archive_args(argc, argv, &ar, &args);
        if (prefix == NULL)
                prefix = setup_git_directory();
 
        argv += tree_idx;
-       parse_treeish_arg(argv, &ar.args, prefix);
-       parse_pathspec_arg(argv + 1, &ar.args);
+       parse_treeish_arg(argv, &args, prefix);
+       parse_pathspec_arg(argv + 1, &args);
 
-       return ar.write_archive(&ar.args);
+       return ar->write_archive(&args);
 }
index 06c7de429799f4af5303253775f21b7f37723b94..9bced3b2626eb72ccb4b8756b47163db4c026540 100644 (file)
@@ -20,7 +20,7 @@
 #include "mailmap.h"
 #include "parse-options.h"
 
-static char blame_usage[] = "git-blame [options] [rev-opts] [rev] [--] file";
+static char blame_usage[] = "git blame [options] [rev-opts] [rev] [--] file";
 
 static const char *blame_opt_usage[] = {
        blame_usage,
@@ -153,6 +153,10 @@ struct blame_entry {
         */
        char guilty;
 
+       /* true if the entry has been scanned for copies in the current parent
+        */
+       char scanned;
+
        /* the line number of the first line of this group in the
         * suspect's file; internally all line numbers are 0 based.
         */
@@ -1008,7 +1012,8 @@ static int find_move_in_parent(struct scoreboard *sb,
        while (made_progress) {
                made_progress = 0;
                for (e = sb->ent; e; e = e->next) {
-                       if (e->guilty || !same_suspect(e->suspect, target))
+                       if (e->guilty || !same_suspect(e->suspect, target) ||
+                           ent_score(sb, e) < blame_move_score)
                                continue;
                        find_copy_in_blob(sb, e, parent, split, &file_p);
                        if (split[1].suspect &&
@@ -1033,6 +1038,7 @@ struct blame_list {
  */
 static struct blame_list *setup_blame_list(struct scoreboard *sb,
                                           struct origin *target,
+                                          int min_score,
                                           int *num_ents_p)
 {
        struct blame_entry *e;
@@ -1040,18 +1046,32 @@ static struct blame_list *setup_blame_list(struct scoreboard *sb,
        struct blame_list *blame_list = NULL;
 
        for (e = sb->ent, num_ents = 0; e; e = e->next)
-               if (!e->guilty && same_suspect(e->suspect, target))
+               if (!e->scanned && !e->guilty &&
+                   same_suspect(e->suspect, target) &&
+                   min_score < ent_score(sb, e))
                        num_ents++;
        if (num_ents) {
                blame_list = xcalloc(num_ents, sizeof(struct blame_list));
                for (e = sb->ent, i = 0; e; e = e->next)
-                       if (!e->guilty && same_suspect(e->suspect, target))
+                       if (!e->scanned && !e->guilty &&
+                           same_suspect(e->suspect, target) &&
+                           min_score < ent_score(sb, e))
                                blame_list[i++].ent = e;
        }
        *num_ents_p = num_ents;
        return blame_list;
 }
 
+/*
+ * Reset the scanned status on all entries.
+ */
+static void reset_scanned_flag(struct scoreboard *sb)
+{
+       struct blame_entry *e;
+       for (e = sb->ent; e; e = e->next)
+               e->scanned = 0;
+}
+
 /*
  * For lines target is suspected for, see if we can find code movement
  * across file boundary from the parent commit.  porigin is the path
@@ -1070,7 +1090,7 @@ static int find_copy_in_parent(struct scoreboard *sb,
        struct blame_list *blame_list;
        int num_ents;
 
-       blame_list = setup_blame_list(sb, target, &num_ents);
+       blame_list = setup_blame_list(sb, target, blame_copy_score, &num_ents);
        if (!blame_list)
                return 1; /* nothing remains for this target */
 
@@ -1144,18 +1164,21 @@ static int find_copy_in_parent(struct scoreboard *sb,
                                split_blame(sb, split, blame_list[j].ent);
                                made_progress = 1;
                        }
+                       else
+                               blame_list[j].ent->scanned = 1;
                        decref_split(split);
                }
                free(blame_list);
 
                if (!made_progress)
                        break;
-               blame_list = setup_blame_list(sb, target, &num_ents);
+               blame_list = setup_blame_list(sb, target, blame_copy_score, &num_ents);
                if (!blame_list) {
                        retval = 1;
                        break;
                }
        }
+       reset_scanned_flag(sb);
        diff_flush(&diff_opts);
        diff_tree_release_paths(&diff_opts);
        return retval;
index 7dae22c0197c2d3d062b0fa34c15b6c9a489eb31..b885bd132b5e5b2979afd451f4e81f184ec9c969 100644 (file)
 #include "branch.h"
 
 static const char * const builtin_branch_usage[] = {
-       "git-branch [options] [-r | -a] [--merged | --no-merged]",
-       "git-branch [options] [-l] [-f] <branchname> [<start-point>]",
-       "git-branch [options] [-r] (-d | -D) <branchname>",
-       "git-branch [options] (-m | -M) [<oldbranch>] <newbranch>",
+       "git branch [options] [-r | -a] [--merged | --no-merged]",
+       "git branch [options] [-l] [-f] <branchname> [<start-point>]",
+       "git branch [options] [-r] (-d | -D) <branchname>",
+       "git branch [options] (-m | -M) [<oldbranch>] <newbranch>",
        NULL
 };
 
index 880e75af5e1951689a417aa47e64f99a20d46ae6..7441a56acdbefdd8044a406f4d756ce8a4f06644 100644 (file)
@@ -202,8 +202,8 @@ static int batch_objects(int print_contents)
 }
 
 static const char * const cat_file_usage[] = {
-       "git-cat-file [-t|-s|-e|-p|<type>] <sha1>",
-       "git-cat-file [--batch|--batch-check] < <list_of_sha1s>",
+       "git cat-file [-t|-s|-e|-p|<type>] <sha1>",
+       "git cat-file [--batch|--batch-check] < <list_of_sha1s>",
        NULL
 };
 
index 6afdfa10a166a97c1115b1430221262228622c5c..cb783fc77e75515a02ed2268dfb37ee3bbd03749 100644 (file)
@@ -4,7 +4,7 @@
 #include "quote.h"
 
 static const char check_attr_usage[] =
-"git-check-attr attr... [--] pathname...";
+"git check-attr attr... [--] pathname...";
 
 int cmd_check_attr(int argc, const char **argv, const char *prefix)
 {
index eb1fc9aa6f7f61a817a198feaf94ca9d983eb14b..71ebabf9903bd90b7da59c47f1c0819b5f25c538 100644 (file)
@@ -154,7 +154,7 @@ static void checkout_all(const char *prefix, int prefix_length)
 }
 
 static const char checkout_cache_usage[] =
-"git-checkout-index [-u] [-q] [-a] [-f] [-n] [--stage=[123]|all] [--prefix=<string>] [--temp] [--] <file>...";
+"git checkout-index [-u] [-q] [-a] [-f] [-n] [--stage=[123]|all] [--prefix=<string>] [--temp] [--] <file>...";
 
 static struct lock_file lock_file;
 
index d6641c2c562c6b35bfed1cd3053945b460472581..fbd5105a8302a6c00e191ef49f3dfef1fc979c53 100644 (file)
@@ -43,7 +43,7 @@ static int post_checkout_hook(struct commit *old, struct commit *new,
 }
 
 static int update_some(const unsigned char *sha1, const char *base, int baselen,
-                      const char *pathname, unsigned mode, int stage)
+               const char *pathname, unsigned mode, int stage, void *context)
 {
        int len;
        struct cache_entry *ce;
@@ -67,7 +67,7 @@ static int update_some(const unsigned char *sha1, const char *base, int baselen,
 
 static int read_tree_some(struct tree *tree, const char **pathspec)
 {
-       read_tree_recursive(tree, "", 0, 0, pathspec, update_some);
+       read_tree_recursive(tree, "", 0, 0, pathspec, update_some, NULL);
 
        /* update the index with the given tree's info
         * for all args, expanding wildcards, and exit
index 80a7ff9ae45035b44bbac44a9436152645c4fb38..48bf29f40a5e06fd588b34c468535e04abcf206b 100644 (file)
@@ -15,7 +15,7 @@
 static int force = -1; /* unset */
 
 static const char *const builtin_clean_usage[] = {
-       "git-clean [-d] [-f] [-n] [-q] [-x | -X] [--] <paths>...",
+       "git clean [-d] [-f] [-n] [-q] [-x | -X] [--] <paths>...",
        NULL
 };
 
index ec362096003be447f1d84f8203d37e577911f4f9..352224591f3be1eaff858b1fe10dac8f852f32c2 100644 (file)
@@ -29,7 +29,7 @@
  *
  */
 static const char * const builtin_clone_usage[] = {
-       "git-clone [options] [--] <repo> [<dir>]",
+       "git clone [options] [--] <repo> [<dir>]",
        NULL
 };
 
@@ -95,35 +95,38 @@ static char *get_repo_path(const char *repo, int *is_bundle)
 
 static char *guess_dir_name(const char *repo, int is_bundle)
 {
-       const char *p, *start, *end, *limit;
-       int after_slash_or_colon;
-
-       /* Guess dir name from repository: strip trailing '/',
-        * strip trailing '[:/]*.{git,bundle}', strip leading '.*[/:]'. */
-
-       after_slash_or_colon = 1;
-       limit = repo + strlen(repo);
-       start = repo;
-       end = limit;
-       for (p = repo; p < limit; p++) {
-               const char *prefix = is_bundle ? ".bundle" : ".git";
-               if (!prefixcmp(p, prefix)) {
-                       if (!after_slash_or_colon)
-                               end = p;
-                       p += strlen(prefix) - 1;
-               } else if (!prefixcmp(p, ".bundle")) {
-                       if (!after_slash_or_colon)
-                               end = p;
-                       p += 7;
-               } else if (*p == '/' || *p == ':') {
-                       if (end == limit)
-                               end = p;
-                       after_slash_or_colon = 1;
-               } else if (after_slash_or_colon) {
-                       start = p;
-                       end = limit;
-                       after_slash_or_colon = 0;
-               }
+       const char *end = repo + strlen(repo), *start;
+
+       /*
+        * Strip trailing slashes and /.git
+        */
+       while (repo < end && is_dir_sep(end[-1]))
+               end--;
+       if (end - repo > 5 && is_dir_sep(end[-5]) &&
+           !strncmp(end - 4, ".git", 4)) {
+               end -= 5;
+               while (repo < end && is_dir_sep(end[-1]))
+                       end--;
+       }
+
+       /*
+        * Find last component, but be prepared that repo could have
+        * the form  "remote.example.com:foo.git", i.e. no slash
+        * in the directory part.
+        */
+       start = end;
+       while (repo < start && !is_dir_sep(start[-1]) && start[-1] != ':')
+               start--;
+
+       /*
+        * Strip .{bundle,git}.
+        */
+       if (is_bundle) {
+               if (end - start > 7 && !strncmp(end - 7, ".bundle", 7))
+                       end -= 7;
+       } else {
+               if (end - start > 4 && !strncmp(end - 4, ".git", 4))
+                       end -= 4;
        }
 
        return xstrndup(start, end - start);
index bdc83df55bcaeb51eb51b1a3198033eb69236409..ed3fe3f7ee033e09f87c0a86dc7db70b13c6a262 100644 (file)
 #include "unpack-trees.h"
 
 static const char * const builtin_commit_usage[] = {
-       "git-commit [options] [--] <filepattern>...",
+       "git commit [options] [--] <filepattern>...",
        NULL
 };
 
 static const char * const builtin_status_usage[] = {
-       "git-status [options] [--] <filepattern>...",
+       "git status [options] [--] <filepattern>...",
        NULL
 };
 
index 39f63d7b10f93a0a021d8b9af9fdec46ed0333f6..0cf191a11294f902d25aeda29e7290f3ab78b482 100644 (file)
@@ -3,7 +3,7 @@
 #include "color.h"
 
 static const char git_config_set_usage[] =
-"git-config [ --global | --system | [ -f | --file ] config-file ] [ --bool | --int | --bool-or-int ] [ -z | --null ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --remove-section name | --list | --get-color var [default] | --get-colorbool name [stdout-is-tty]";
+"git config [ --global | --system | [ -f | --file ] config-file ] [ --bool | --int | --bool-or-int ] [ -z | --null ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --remove-section name | --list | --get-color var [default] | --get-colorbool name [stdout-is-tty]";
 
 static char *key;
 static regex_t *key_regexp;
index f00306fb677acb6003444b931dc9b2bf719bc562..91b5487478998e39bb8ae4a5cb667360cff82c9a 100644 (file)
@@ -67,7 +67,7 @@ static void count_objects(DIR *d, char *path, int len, int verbose,
 }
 
 static char const * const count_objects_usage[] = {
-       "git-count-objects [-v]",
+       "git count-objects [-v]",
        NULL
 };
 
index e515f9ca9b5d0ec13e96a7866e27bdd9e852b435..ec404c839b6542deb4e15ca342fd3c0afbbedd2e 100644 (file)
@@ -10,7 +10,7 @@
 #define MAX_TAGS       (FLAG_BITS - 1)
 
 static const char * const describe_usage[] = {
-       "git-describe [options] <committish>*",
+       "git describe [options] <committish>*",
        NULL
 };
 
@@ -20,7 +20,7 @@ static int tags;      /* But allow any tags if --tags is specified */
 static int longformat;
 static int abbrev = DEFAULT_ABBREV;
 static int max_candidates = 10;
-const char *pattern = NULL;
+static const char *pattern;
 static int always;
 
 struct commit_name {
index 384d871263383e89c6f8f52b16e9e7e147426d1d..9bf10bb37e2f56ec2a10239d7419db8fbb641745 100644 (file)
@@ -10,7 +10,7 @@
 #include "builtin.h"
 
 static const char diff_files_usage[] =
-"git-diff-files [-q] [-0/-1/2/3 |-c|--cc] [<common diff options>] [<path>...]"
+"git diff-files [-q] [-0/-1/2/3 |-c|--cc] [<common diff options>] [<path>...]"
 COMMON_DIFF_OPTIONS_HELP;
 
 int cmd_diff_files(int argc, const char **argv, const char *prefix)
index 2f44ebfcdd86cde2347258dbeb1e5c4b9cab0622..17d851b29ee5de33e01745eabcd5cd735c30b352 100644 (file)
@@ -5,7 +5,7 @@
 #include "builtin.h"
 
 static const char diff_cache_usage[] =
-"git-diff-index [-m] [--cached] "
+"git diff-index [-m] [--cached] "
 "[<common diff options>] <tree-ish> [<path>...]"
 COMMON_DIFF_OPTIONS_HELP;
 
index 9d2a48fd6833038fee1b608175f71a867bb9f3e6..415cb1612f5322da89850874ba81885e41808678 100644 (file)
@@ -53,7 +53,7 @@ static int diff_tree_stdin(char *line)
 }
 
 static const char diff_tree_usage[] =
-"git-diff-tree [--stdin] [-m] [-c] [--cc] [-s] [-v] [--pretty] [-t] [-r] [--root] "
+"git diff-tree [--stdin] [-m] [-c] [--cc] [-s] [-v] [--pretty] [-t] [-r] [--root] "
 "[<common diff options>] <tree-ish> [<tree-ish>] [<path>...]\n"
 "  -r            diff recursively\n"
 "  --root        include the initial commit as diff against /dev/null\n"
index 4c289e798a25ee3893a483abd8465740999dcbef..faaa85a1d45ce6c5f398a44b1241f6325430918b 100644 (file)
@@ -21,7 +21,7 @@ struct blobinfo {
 };
 
 static const char builtin_diff_usage[] =
-"git-diff <options> <rev>{0,2} -- <path>*";
+"git diff <options> <rev>{0,2} -- <path>*";
 
 static void stuff_change(struct diff_options *opt,
                         unsigned old_mode, unsigned new_mode,
index 75132bacfac08591ccb70eca0260be23d0e04a92..a443d594602b3b80964763d3105aaa2480780a87 100644 (file)
@@ -18,7 +18,7 @@
 #include "parse-options.h"
 
 static const char *fast_export_usage[] = {
-       "git-fast-export [rev-list-opts]",
+       "git fast-export [rev-list-opts]",
        NULL
 };
 
@@ -136,9 +136,18 @@ static void show_filemodify(struct diff_queue_struct *q,
                if (is_null_sha1(spec->sha1))
                        printf("D %s\n", spec->path);
                else {
-                       struct object *object = lookup_object(spec->sha1);
-                       printf("M %06o :%d %s\n", spec->mode,
-                              get_object_mark(object), spec->path);
+                       /*
+                        * Links refer to objects in another repositories;
+                        * output the SHA-1 verbatim.
+                        */
+                       if (S_ISGITLINK(spec->mode))
+                               printf("M %06o %s %s\n", spec->mode,
+                                      sha1_to_hex(spec->sha1), spec->path);
+                       else {
+                               struct object *object = lookup_object(spec->sha1);
+                               printf("M %06o :%d %s\n", spec->mode,
+                                      get_object_mark(object), spec->path);
+                       }
                }
        }
 }
@@ -196,8 +205,10 @@ static void handle_commit(struct commit *commit, struct rev_info *rev)
                diff_root_tree_sha1(commit->tree->object.sha1,
                                    "", &rev->diffopt);
 
+       /* Export the referenced blobs, and remember the marks. */
        for (i = 0; i < diff_queued_diff.nr; i++)
-               handle_object(diff_queued_diff.queue[i]->two->sha1);
+               if (!S_ISGITLINK(diff_queued_diff.queue[i]->two->mode))
+                       handle_object(diff_queued_diff.queue[i]->two->sha1);
 
        mark_next_object(&commit->object);
        if (!is_encoding_utf8(encoding))
index 1ea704063928d77fe1048b1abde35e42fcfb20e4..273239af3be61736ee4ff484d628950c4de7311a 100644 (file)
@@ -18,7 +18,7 @@ static struct fetch_pack_args args = {
 };
 
 static const char fetch_pack_usage[] =
-"git-fetch-pack [--all] [--quiet|-q] [--keep|-k] [--thin] [--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] [--no-progress] [-v] [<host>:]<directory> [<refs>...]";
+"git fetch-pack [--all] [--quiet|-q] [--keep|-k] [--thin] [--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] [--no-progress] [-v] [<host>:]<directory> [<refs>...]";
 
 #define COMPLETE       (1U << 0)
 #define COMMON         (1U << 1)
index 97fdc51e3188143e0546512f59be9d2542dcac9a..61de50a020ace25e110ed1b2fc5d21286bd885d7 100644 (file)
@@ -12,7 +12,7 @@
 #include "parse-options.h"
 
 static const char * const builtin_fetch_usage[] = {
-       "git-fetch [options] [<repository> <refspec>...]",
+       "git fetch [options] [<repository> <refspec>...]",
        NULL
 };
 
index dbd7d2ddae2d4b44bcccf9977d435cf334a0c418..df02ba7afdd615492361a1897a9dedd6ab233c96 100644 (file)
@@ -6,7 +6,7 @@
 #include "tag.h"
 
 static const char *fmt_merge_msg_usage =
-       "git-fmt-merge-msg [--log] [--no-log] [--file <file>]";
+       "git fmt-merge-msg [--log] [--no-log] [--file <file>]";
 
 static int merge_summary;
 
index fef93d7488d15fac28e96f887f26556755cc6ca8..76282ad79193e2a5f0ec2ba8e5027025f8a7bee1 100644 (file)
@@ -831,7 +831,7 @@ int opt_parse_sort(const struct option *opt, const char *arg, int unset)
 }
 
 static char const * const for_each_ref_usage[] = {
-       "git-for-each-ref [options] [<pattern>]",
+       "git for-each-ref [options] [<pattern>]",
        NULL
 };
 
index b0f9648f862248d1b985f31406b8f3de26b47aff..7326dc33a586dfbadf5bc35ac628b1f8690a6a09 100644 (file)
@@ -539,7 +539,7 @@ static int fsck_cache_tree(struct cache_tree *it)
 }
 
 static char const * const fsck_usage[] = {
-       "git-fsck [options] [<object>...]",
+       "git fsck [options] [<object>...]",
        NULL
 };
 
index f5625bb9fb090f5af4dfb782dc04005a4149a5c8..fac200e0b08360625afc81b02913128c9b87f486 100644 (file)
@@ -18,7 +18,7 @@
 #define FAILED_RUN "failed to run %s"
 
 static const char * const builtin_gc_usage[] = {
-       "git-gc [options]",
+       "git gc [options]",
        NULL
 };
 
index ef299108f529fa5fa931d765828f04535c3a6351..631129ddfd0ffe06f919882d22cfc494d9553f50 100644 (file)
@@ -427,33 +427,35 @@ static int grep_tree(struct grep_opt *opt, const char **paths,
        struct name_entry entry;
        char *down;
        int tn_len = strlen(tree_name);
-       char *path_buf = xmalloc(PATH_MAX + tn_len + 100);
+       struct strbuf pathbuf;
+
+       strbuf_init(&pathbuf, PATH_MAX + tn_len);
 
        if (tn_len) {
-               tn_len = sprintf(path_buf, "%s:", tree_name);
-               down = path_buf + tn_len;
-               strcat(down, base);
-       }
-       else {
-               down = path_buf;
-               strcpy(down, base);
+               strbuf_add(&pathbuf, tree_name, tn_len);
+               strbuf_addch(&pathbuf, ':');
+               tn_len = pathbuf.len;
        }
-       len = strlen(path_buf);
+       strbuf_addstr(&pathbuf, base);
+       len = pathbuf.len;
 
        while (tree_entry(tree, &entry)) {
-               strcpy(path_buf + len, entry.path);
+               int te_len = tree_entry_len(entry.path, entry.sha1);
+               pathbuf.len = len;
+               strbuf_add(&pathbuf, entry.path, te_len);
 
                if (S_ISDIR(entry.mode))
                        /* Match "abc/" against pathspec to
                         * decide if we want to descend into "abc"
                         * directory.
                         */
-                       strcpy(path_buf + len + tree_entry_len(entry.path, entry.sha1), "/");
+                       strbuf_addch(&pathbuf, '/');
 
+               down = pathbuf.buf + tn_len;
                if (!pathspec_matches(paths, down))
                        ;
                else if (S_ISREG(entry.mode))
-                       hit |= grep_sha1(opt, entry.sha1, path_buf, tn_len);
+                       hit |= grep_sha1(opt, entry.sha1, pathbuf.buf, tn_len);
                else if (S_ISDIR(entry.mode)) {
                        enum object_type type;
                        struct tree_desc sub;
@@ -469,6 +471,7 @@ static int grep_tree(struct grep_opt *opt, const char **paths,
                        free(data);
                }
        }
+       strbuf_release(&pathbuf);
        return hit;
 }
 
@@ -495,7 +498,7 @@ static int grep_object(struct grep_opt *opt, const char **paths,
 }
 
 static const char builtin_grep_usage[] =
-"git-grep <option>* <rev>* [-e] <pattern> [<path>...]";
+"git grep <option>* [-e] <pattern> <rev>* [[--] <path>...]";
 
 static const char emsg_invalid_context_len[] =
 "%s: invalid context length argument";
index 5ba213a595fb9d7de4d36ff5cab888bde2035722..38b4fcb6db547cf6b7a814db621e6f05b583c420 100644 (file)
@@ -354,7 +354,7 @@ static int guess_repository_type(const char *git_dir)
 }
 
 static const char init_db_usage[] =
-"git-init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]]";
+"git init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]]";
 
 /*
  * If you want to, you can share the DB area with any number of branches.
index 430d87661e37a4b08963de1ee5c31b8143ebc373..f4975cf35f7f1555739f7657ee62ed983d18cb84 100644 (file)
@@ -313,7 +313,7 @@ static int show_object(const unsigned char *sha1, int show_tag_object,
 
 static int show_tree_object(const unsigned char *sha1,
                const char *base, int baselen,
-               const char *pathname, unsigned mode, int stage)
+               const char *pathname, unsigned mode, int stage, void *context)
 {
        printf("%s%s\n", pathname, S_ISDIR(mode) ? "/" : "");
        return 0;
@@ -366,7 +366,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
                                        name,
                                        diff_get_color_opt(&rev.diffopt, DIFF_RESET));
                        read_tree_recursive((struct tree *)o, "", 0, 0, NULL,
-                                       show_tree_object);
+                                       show_tree_object, NULL);
                        break;
                case OBJ_COMMIT:
                        rev.pending.nr = rev.pending.alloc = 0;
@@ -1082,7 +1082,7 @@ static int add_pending_commit(const char *arg, struct rev_info *revs, int flags)
 }
 
 static const char cherry_usage[] =
-"git-cherry [-v] <upstream> [<head>] [<limit>]";
+"git cherry [-v] <upstream> [<head>] [<limit>]";
 int cmd_cherry(int argc, const char **argv, const char *prefix)
 {
        struct rev_info revs;
index 75ba42246ee340634d317ec39948ed983171a42f..e8d568eed7ab700bc338af8f589d2f61e81f323c 100644 (file)
@@ -423,7 +423,7 @@ int report_path_error(const char *ps_matched, const char **pathspec, int prefix_
 }
 
 static const char ls_files_usage[] =
-       "git-ls-files [-z] [-t] [-v] (--[cached|deleted|others|stage|unmerged|killed|modified])* "
+       "git ls-files [-z] [-t] [-v] (--[cached|deleted|others|stage|unmerged|killed|modified])* "
        "[ --ignored ] [--exclude=<pattern>] [--exclude-from=<file>] "
        "[ --exclude-per-directory=<filename> ] [--exclude-standard] "
        "[--full-name] [--abbrev] [--] [<file>]*";
index 06ab8da1fb1e5ebc5fedb82e74d7e6a7374cee0e..c21b841e7c5e8d27a6e66e7f70786d77aa4653b5 100644 (file)
@@ -4,7 +4,7 @@
 #include "remote.h"
 
 static const char ls_remote_usage[] =
-"git-ls-remote [--upload-pack=<git-upload-pack>] [<host>:]<directory>";
+"git ls-remote [--upload-pack=<git-upload-pack>] [<host>:]<directory>";
 
 /*
  * Is there one among the list of patterns that match the tail part
index f4a75ddbc3fecb9c1690a94d39ce230e82fefd8d..d25767a1f7eb0a8b45bc1eed6b9aa95de0847f18 100644 (file)
@@ -23,7 +23,7 @@ static int chomp_prefix;
 static const char *ls_tree_prefix;
 
 static const char ls_tree_usage[] =
-       "git-ls-tree [-d] [-r] [-t] [-l] [-z] [--name-only] [--name-status] [--full-name] [--abbrev[=<n>]] <tree-ish> [path...]";
+       "git ls-tree [-d] [-r] [-t] [-l] [-z] [--name-only] [--name-status] [--full-name] [--abbrev[=<n>]] <tree-ish> [path...]";
 
 static int show_recursive(const char *base, int baselen, const char *pathname)
 {
@@ -56,7 +56,7 @@ static int show_recursive(const char *base, int baselen, const char *pathname)
 }
 
 static int show_tree(const unsigned char *sha1, const char *base, int baselen,
-                    const char *pathname, unsigned mode, int stage)
+               const char *pathname, unsigned mode, int stage, void *context)
 {
        int retval = 0;
        const char *type = blob_type;
@@ -189,7 +189,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
        tree = parse_tree_indirect(sha1);
        if (!tree)
                die("not a tree object");
-       read_tree_recursive(tree, "", 0, 0, pathspec, show_tree);
+       read_tree_recursive(tree, "", 0, 0, pathspec, show_tree, NULL);
 
        return 0;
 }
index 13f0502b9e0bca9e4119896c01786b99cc54441e..b99a5b6f9679061d75e9c48e2fa5877e27920dc3 100644 (file)
@@ -5,14 +5,15 @@
 #include "cache.h"
 #include "builtin.h"
 #include "utf8.h"
+#include "strbuf.h"
 
 static FILE *cmitmsg, *patchfile, *fin, *fout;
 
 static int keep_subject;
 static const char *metainfo_charset;
-static char line[1000];
-static char name[1000];
-static char email[1000];
+static struct strbuf line = STRBUF_INIT;
+static struct strbuf name = STRBUF_INIT;
+static struct strbuf email = STRBUF_INIT;
 
 static enum  {
        TE_DONTCARE, TE_QP, TE_BASE64,
@@ -21,74 +22,79 @@ static enum  {
        TYPE_TEXT, TYPE_OTHER,
 } message_type;
 
-static char charset[256];
+static struct strbuf charset = STRBUF_INIT;
 static int patch_lines;
-static char **p_hdr_data, **s_hdr_data;
+static struct strbuf **p_hdr_data, **s_hdr_data;
 
 #define MAX_HDR_PARSED 10
 #define MAX_BOUNDARIES 5
 
-static char *sanity_check(char *name, char *email)
+static void get_sane_name(struct strbuf *out, struct strbuf *name, struct strbuf *email)
 {
-       int len = strlen(name);
-       if (len < 3 || len > 60)
-               return email;
-       if (strchr(name, '@') || strchr(name, '<') || strchr(name, '>'))
-               return email;
-       return name;
+       struct strbuf *src = name;
+       if (name->len < 3 || 60 < name->len || strchr(name->buf, '@') ||
+               strchr(name->buf, '<') || strchr(name->buf, '>'))
+               src = email;
+       else if (name == out)
+               return;
+       strbuf_reset(out);
+       strbuf_addbuf(out, src);
 }
 
-static int bogus_from(char *line)
+static void parse_bogus_from(const struct strbuf *line)
 {
        /* John Doe <johndoe> */
-       char *bra, *ket, *dst, *cp;
 
+       char *bra, *ket;
        /* This is fallback, so do not bother if we already have an
         * e-mail address.
         */
-       if (*email)
-               return 0;
+       if (email.len)
+               return;
 
-       bra = strchr(line, '<');
+       bra = strchr(line->buf, '<');
        if (!bra)
-               return 0;
+               return;
        ket = strchr(bra, '>');
        if (!ket)
-               return 0;
+               return;
 
-       for (dst = email, cp = bra+1; cp < ket; )
-               *dst++ = *cp++;
-       *dst = 0;
-       for (cp = line; isspace(*cp); cp++)
-               ;
-       for (bra--; isspace(*bra); bra--)
-               *bra = 0;
-       cp = sanity_check(cp, email);
-       strcpy(name, cp);
-       return 1;
+       strbuf_reset(&email);
+       strbuf_add(&email, bra + 1, ket - bra - 1);
+
+       strbuf_reset(&name);
+       strbuf_add(&name, line->buf, bra - line->buf);
+       strbuf_trim(&name);
+       get_sane_name(&name, &name, &email);
 }
 
-static int handle_from(char *in_line)
+static void handle_from(const struct strbuf *from)
 {
-       char line[1000];
        char *at;
-       char *dst;
+       size_t el;
+       struct strbuf f;
 
-       strcpy(line, in_line);
-       at = strchr(line, '@');
-       if (!at)
-               return bogus_from(line);
+       strbuf_init(&f, from->len);
+       strbuf_addbuf(&f, from);
+
+       at = strchr(f.buf, '@');
+       if (!at) {
+               parse_bogus_from(from);
+               return;
+       }
 
        /*
         * If we already have one email, don't take any confusing lines
         */
-       if (*email && strchr(at+1, '@'))
-               return 0;
+       if (email.len && strchr(at + 1, '@')) {
+               strbuf_release(&f);
+               return;
+       }
 
        /* Pick up the string around '@', possibly delimited with <>
-        * pair; that is the email part.  White them out while copying.
+        * pair; that is the email part.
         */
-       while (at > line) {
+       while (at > f.buf) {
                char c = at[-1];
                if (isspace(c))
                        break;
@@ -98,56 +104,35 @@ static int handle_from(char *in_line)
                }
                at--;
        }
-       dst = email;
-       for (;;) {
-               unsigned char c = *at;
-               if (!c || c == '>' || isspace(c)) {
-                       if (c == '>')
-                               *at = ' ';
-                       break;
-               }
-               *at++ = ' ';
-               *dst++ = c;
-       }
-       *dst++ = 0;
+       el = strcspn(at, " \n\t\r\v\f>");
+       strbuf_reset(&email);
+       strbuf_add(&email, at, el);
+       strbuf_remove(&f, at - f.buf, el + 1);
 
        /* The remainder is name.  It could be "John Doe <john.doe@xz>"
-        * or "john.doe@xz (John Doe)", but we have whited out the
+        * or "john.doe@xz (John Doe)", but we have removed the
         * email part, so trim from both ends, possibly removing
         * the () pair at the end.
         */
-       at = line + strlen(line);
-       while (at > line) {
-               unsigned char c = *--at;
-               if (!isspace(c)) {
-                       at[(c == ')') ? 0 : 1] = 0;
-                       break;
-               }
-       }
+       strbuf_trim(&f);
+       if (f.buf[0] == '(')
+               strbuf_remove(&name, 0, 1);
+       if (f.len && f.buf[f.len - 1] == ')')
+               strbuf_setlen(&f, f.len - 1);
 
-       at = line;
-       for (;;) {
-               unsigned char c = *at;
-               if (!c || !isspace(c)) {
-                       if (c == '(')
-                               at++;
-                       break;
-               }
-               at++;
-       }
-       at = sanity_check(at, email);
-       strcpy(name, at);
-       return 1;
+       get_sane_name(&name, &f, &email);
+       strbuf_release(&f);
 }
 
-static int handle_header(char *line, char *data, int ofs)
+static void handle_header(struct strbuf **out, const struct strbuf *line)
 {
-       if (!line || !data)
-               return 1;
+       if (!*out) {
+               *out = xmalloc(sizeof(struct strbuf));
+               strbuf_init(*out, line->len);
+       } else
+               strbuf_reset(*out);
 
-       strcpy(data, line+ofs);
-
-       return 0;
+       strbuf_addbuf(*out, line);
 }
 
 /* NOTE NOTE NOTE.  We do not claim we do full MIME.  We just attempt
@@ -156,13 +141,13 @@ static int handle_header(char *line, char *data, int ofs)
  * case insensitively.
  */
 
-static int slurp_attr(const char *line, const char *name, char *attr)
+static int slurp_attr(const char *line, const char *name, struct strbuf *attr)
 {
        const char *ends, *ap = strcasestr(line, name);
        size_t sz;
 
        if (!ap) {
-               *attr = 0;
+               strbuf_setlen(attr, 0);
                return 0;
        }
        ap += strlen(name);
@@ -173,182 +158,171 @@ static int slurp_attr(const char *line, const char *name, char *attr)
        else
                ends = "; \t";
        sz = strcspn(ap, ends);
-       memcpy(attr, ap, sz);
-       attr[sz] = 0;
+       strbuf_add(attr, ap, sz);
        return 1;
 }
 
-struct content_type {
-       char *boundary;
-       int boundary_len;
-};
-
-static struct content_type content[MAX_BOUNDARIES];
+static struct strbuf *content[MAX_BOUNDARIES];
 
-static struct content_type *content_top = content;
+static struct strbuf **content_top = content;
 
-static int handle_content_type(char *line)
+static void handle_content_type(struct strbuf *line)
 {
-       char boundary[256];
+       struct strbuf *boundary = xmalloc(sizeof(struct strbuf));
+       strbuf_init(boundary, line->len);
 
-       if (strcasestr(line, "text/") == NULL)
+       if (!strcasestr(line->buf, "text/"))
                 message_type = TYPE_OTHER;
-       if (slurp_attr(line, "boundary=", boundary + 2)) {
-               memcpy(boundary, "--", 2);
+       if (slurp_attr(line->buf, "boundary=", boundary)) {
+               strbuf_insert(boundary, 0, "--", 2);
                if (content_top++ >= &content[MAX_BOUNDARIES]) {
                        fprintf(stderr, "Too many boundaries to handle\n");
                        exit(1);
                }
-               content_top->boundary_len = strlen(boundary);
-               content_top->boundary = xmalloc(content_top->boundary_len+1);
-               strcpy(content_top->boundary, boundary);
+               *content_top = boundary;
+               boundary = NULL;
        }
-       if (slurp_attr(line, "charset=", charset)) {
-               int i, c;
-               for (i = 0; (c = charset[i]) != 0; i++)
-                       charset[i] = tolower(c);
+       if (slurp_attr(line->buf, "charset=", &charset))
+               strbuf_tolower(&charset);
+
+       if (boundary) {
+               strbuf_release(boundary);
+               free(boundary);
        }
-       return 0;
 }
 
-static int handle_content_transfer_encoding(char *line)
+static void handle_content_transfer_encoding(const struct strbuf *line)
 {
-       if (strcasestr(line, "base64"))
+       if (strcasestr(line->buf, "base64"))
                transfer_encoding = TE_BASE64;
-       else if (strcasestr(line, "quoted-printable"))
+       else if (strcasestr(line->buf, "quoted-printable"))
                transfer_encoding = TE_QP;
        else
                transfer_encoding = TE_DONTCARE;
-       return 0;
 }
 
-static int is_multipart_boundary(const char *line)
+static int is_multipart_boundary(const struct strbuf *line)
 {
-       return (!memcmp(line, content_top->boundary, content_top->boundary_len));
+       return !strbuf_cmp(line, *content_top);
 }
 
-static int eatspace(char *line)
+static void cleanup_subject(struct strbuf *subject)
 {
-       int len = strlen(line);
-       while (len > 0 && isspace(line[len-1]))
-               line[--len] = 0;
-       return len;
-}
-
-static char *cleanup_subject(char *subject)
-{
-       for (;;) {
-               char *p;
-               int len, remove;
-               switch (*subject) {
+       char *pos;
+       size_t remove;
+       while (subject->len) {
+               switch (*subject->buf) {
                case 'r': case 'R':
-                       if (!memcmp("e:", subject+1, 2)) {
-                               subject += 3;
+                       if (subject->len <= 3)
+                               break;
+                       if (!memcmp(subject->buf + 1, "e:", 2)) {
+                               strbuf_remove(subject, 0, 3);
                                continue;
                        }
                        break;
                case ' ': case '\t': case ':':
-                       subject++;
+                       strbuf_remove(subject, 0, 1);
                        continue;
-
                case '[':
-                       p = strchr(subject, ']');
-                       if (!p) {
-                               subject++;
-                               continue;
-                       }
-                       len = strlen(p);
-                       remove = p - subject;
-                       if (remove <= len *2) {
-                               subject = p+1;
-                               continue;
-                       }
+                       if ((pos = strchr(subject->buf, ']'))) {
+                               remove = pos - subject->buf;
+                               if (remove <= (subject->len - remove) * 2) {
+                                       strbuf_remove(subject, 0, remove + 1);
+                                       continue;
+                               }
+                       } else
+                               strbuf_remove(subject, 0, 1);
                        break;
                }
-               eatspace(subject);
-               return subject;
+               strbuf_trim(subject);
+               return;
        }
 }
 
-static void cleanup_space(char *buf)
+static void cleanup_space(struct strbuf *sb)
 {
-       unsigned char c;
-       while ((c = *buf) != 0) {
-               buf++;
-               if (isspace(c)) {
-                       buf[-1] = ' ';
-                       c = *buf;
-                       while (isspace(c)) {
-                               int len = strlen(buf);
-                               memmove(buf, buf+1, len);
-                               c = *buf;
-                       }
+       size_t pos, cnt;
+       for (pos = 0; pos < sb->len; pos++) {
+               if (isspace(sb->buf[pos])) {
+                       sb->buf[pos] = ' ';
+                       for (cnt = 0; isspace(sb->buf[pos + cnt + 1]); cnt++);
+                       strbuf_remove(sb, pos + 1, cnt);
                }
        }
 }
 
-static void decode_header(char *it, unsigned itsize);
+static void decode_header(struct strbuf *line);
 static const char *header[MAX_HDR_PARSED] = {
        "From","Subject","Date",
 };
 
-static int check_header(char *line, unsigned linesize, char **hdr_data, int overwrite)
+static inline int cmp_header(const struct strbuf *line, const char *hdr)
 {
-       int i;
+       int len = strlen(hdr);
+       return !strncasecmp(line->buf, hdr, len) && line->len > len &&
+                       line->buf[len] == ':' && isspace(line->buf[len + 1]);
+}
 
+static int check_header(const struct strbuf *line,
+                               struct strbuf *hdr_data[], int overwrite)
+{
+       int i, ret = 0, len;
+       struct strbuf sb = STRBUF_INIT;
        /* search for the interesting parts */
        for (i = 0; header[i]; i++) {
                int len = strlen(header[i]);
-               if ((!hdr_data[i] || overwrite) &&
-                   !strncasecmp(line, header[i], len) &&
-                   line[len] == ':' && isspace(line[len + 1])) {
+               if ((!hdr_data[i] || overwrite) && cmp_header(line, header[i])) {
                        /* Unwrap inline B and Q encoding, and optionally
                         * normalize the meta information to utf8.
                         */
-                       decode_header(line + len + 2, linesize - len - 2);
-                       hdr_data[i] = xmalloc(1000 * sizeof(char));
-                       if (! handle_header(line, hdr_data[i], len + 2)) {
-                               return 1;
-                       }
+                       strbuf_add(&sb, line->buf + len + 2, line->len - len - 2);
+                       decode_header(&sb);
+                       handle_header(&hdr_data[i], &sb);
+                       ret = 1;
+                       goto check_header_out;
                }
        }
 
        /* Content stuff */
-       if (!strncasecmp(line, "Content-Type", 12) &&
-               line[12] == ':' && isspace(line[12 + 1])) {
-               decode_header(line + 12 + 2, linesize - 12 - 2);
-               if (! handle_content_type(line)) {
-                       return 1;
-               }
-       }
-       if (!strncasecmp(line, "Content-Transfer-Encoding", 25) &&
-               line[25] == ':' && isspace(line[25 + 1])) {
-               decode_header(line + 25 + 2, linesize - 25 - 2);
-               if (! handle_content_transfer_encoding(line)) {
-                       return 1;
-               }
+       if (cmp_header(line, "Content-Type")) {
+               len = strlen("Content-Type: ");
+               strbuf_add(&sb, line->buf + len, line->len - len);
+               decode_header(&sb);
+               strbuf_insert(&sb, 0, "Content-Type: ", len);
+               handle_content_type(&sb);
+               ret = 1;
+               goto check_header_out;
+       }
+       if (cmp_header(line, "Content-Transfer-Encoding")) {
+               len = strlen("Content-Transfer-Encoding: ");
+               strbuf_add(&sb, line->buf + len, line->len - len);
+               decode_header(&sb);
+               handle_content_transfer_encoding(&sb);
+               ret = 1;
+               goto check_header_out;
        }
 
        /* for inbody stuff */
-       if (!memcmp(">From", line, 5) && isspace(line[5]))
-               return 1;
-       if (!memcmp("[PATCH]", line, 7) && isspace(line[7])) {
+       if (!prefixcmp(line->buf, ">From") && isspace(line->buf[5])) {
+               ret = 1; /* Should this return 0? */
+               goto check_header_out;
+       }
+       if (!prefixcmp(line->buf, "[PATCH]") && isspace(line->buf[7])) {
                for (i = 0; header[i]; i++) {
                        if (!memcmp("Subject", header[i], 7)) {
-                               if (!hdr_data[i])
-                                       hdr_data[i] = xmalloc(linesize + 20);
-                               if (! handle_header(line, hdr_data[i], 0)) {
-                                       return 1;
-                               }
+                               handle_header(&hdr_data[i], line);
+                               ret = 1;
+                               goto check_header_out;
                        }
                }
        }
 
-       /* no match */
-       return 0;
+check_header_out:
+       strbuf_release(&sb);
+       return ret;
 }
 
-static int is_rfc2822_header(char *line)
+static int is_rfc2822_header(const struct strbuf *line)
 {
        /*
         * The section that defines the loosest possible
@@ -359,15 +333,15 @@ static int is_rfc2822_header(char *line)
         * ftext = %d33-57 / %59-126
         */
        int ch;
-       char *cp = line;
+       char *cp = line->buf;
 
        /* Count mbox From headers as headers */
-       if (!memcmp(line, "From ", 5) || !memcmp(line, ">From ", 6))
+       if (!prefixcmp(cp, "From ") || !prefixcmp(cp, ">From "))
                return 1;
 
        while ((ch = *cp++)) {
                if (ch == ':')
-                       return cp != line;
+                       return 1;
                if ((33 <= ch && ch <= 57) ||
                    (59 <= ch && ch <= 126))
                        continue;
@@ -376,34 +350,20 @@ static int is_rfc2822_header(char *line)
        return 0;
 }
 
-/*
- * sz is size of 'line' buffer in bytes.  Must be reasonably
- * long enough to hold one physical real-world e-mail line.
- */
-static int read_one_header_line(char *line, int sz, FILE *in)
+static int read_one_header_line(struct strbuf *line, FILE *in)
 {
-       int len;
-
-       /*
-        * We will read at most (sz-1) bytes and then potentially
-        * re-add NUL after it.  Accessing line[sz] after this is safe
-        * and we can allow len to grow up to and including sz.
-        */
-       sz--;
-
        /* Get the first part of the line. */
-       if (!fgets(line, sz, in))
+       if (strbuf_getline(line, in, '\n'))
                return 0;
 
        /*
         * Is it an empty line or not a valid rfc2822 header?
         * If so, stop here, and return false ("not a header")
         */
-       len = eatspace(line);
-       if (!len || !is_rfc2822_header(line)) {
+       strbuf_rtrim(line);
+       if (!line->len || !is_rfc2822_header(line)) {
                /* Re-add the newline */
-               line[len] = '\n';
-               line[len + 1] = '\0';
+               strbuf_addch(line, '\n');
                return 0;
        }
 
@@ -412,65 +372,53 @@ static int read_one_header_line(char *line, int sz, FILE *in)
         * Yuck, 2822 header "folding"
         */
        for (;;) {
-               int peek, addlen;
-               static char continuation[1000];
+               int peek;
+               struct strbuf continuation = STRBUF_INIT;
 
                peek = fgetc(in); ungetc(peek, in);
                if (peek != ' ' && peek != '\t')
                        break;
-               if (!fgets(continuation, sizeof(continuation), in))
+               if (strbuf_getline(&continuation, in, '\n'))
                        break;
-               addlen = eatspace(continuation);
-               if (len < sz - 1) {
-                       if (addlen >= sz - len)
-                               addlen = sz - len - 1;
-                       memcpy(line + len, continuation, addlen);
-                       line[len] = '\n';
-                       len += addlen;
-               }
+               continuation.buf[0] = '\n';
+               strbuf_rtrim(&continuation);
+               strbuf_addbuf(line, &continuation);
        }
-       line[len] = 0;
 
        return 1;
 }
 
-static int decode_q_segment(char *in, char *ot, unsigned otsize, char *ep, int rfc2047)
+static struct strbuf *decode_q_segment(const struct strbuf *q_seg, int rfc2047)
 {
-       char *otbegin = ot;
-       char *otend = ot + otsize;
+       const char *in = q_seg->buf;
        int c;
-       while ((c = *in++) != 0 && (in <= ep)) {
-               if (ot == otend) {
-                       *--ot = '\0';
-                       return -1;
-               }
+       struct strbuf *out = xmalloc(sizeof(struct strbuf));
+       strbuf_init(out, q_seg->len);
+
+       while ((c = *in++) != 0) {
                if (c == '=') {
                        int d = *in++;
                        if (d == '\n' || !d)
                                break; /* drop trailing newline */
-                       *ot++ = ((hexval(d) << 4) | hexval(*in++));
+                       strbuf_addch(out, (hexval(d) << 4) | hexval(*in++));
                        continue;
                }
                if (rfc2047 && c == '_') /* rfc2047 4.2 (2) */
                        c = 0x20;
-               *ot++ = c;
+               strbuf_addch(out, c);
        }
-       *ot = 0;
-       return (ot - otbegin);
+       return out;
 }
 
-static int decode_b_segment(char *in, char *ot, unsigned otsize, char *ep)
+static struct strbuf *decode_b_segment(const struct strbuf *b_seg)
 {
        /* Decode in..ep, possibly in-place to ot */
        int c, pos = 0, acc = 0;
-       char *otbegin = ot;
-       char *otend = ot + otsize;
+       const char *in = b_seg->buf;
+       struct strbuf *out = xmalloc(sizeof(struct strbuf));
+       strbuf_init(out, b_seg->len);
 
-       while ((c = *in++) != 0 && (in <= ep)) {
-               if (ot == otend) {
-                       *--ot = '\0';
-                       return -1;
-               }
+       while ((c = *in++) != 0) {
                if (c == '+')
                        c = 62;
                else if (c == '/')
@@ -495,21 +443,20 @@ static int decode_b_segment(char *in, char *ot, unsigned otsize, char *ep)
                        acc = (c << 2);
                        break;
                case 1:
-                       *ot++ = (acc | (c >> 4));
+                       strbuf_addch(out, (acc | (c >> 4)));
                        acc = (c & 15) << 4;
                        break;
                case 2:
-                       *ot++ = (acc | (c >> 2));
+                       strbuf_addch(out, (acc | (c >> 2)));
                        acc = (c & 3) << 6;
                        break;
                case 3:
-                       *ot++ = (acc | c);
+                       strbuf_addch(out, (acc | c));
                        acc = pos = 0;
                        break;
                }
        }
-       *ot = 0;
-       return (ot - otbegin);
+       return out;
 }
 
 /*
@@ -523,16 +470,16 @@ static int decode_b_segment(char *in, char *ot, unsigned otsize, char *ep)
  * Otherwise, we default to assuming it is Latin1 for historical
  * reasons.
  */
-static const char *guess_charset(const char *line, const char *target_charset)
+static const char *guess_charset(const struct strbuf *line, const char *target_charset)
 {
        if (is_encoding_utf8(target_charset)) {
-               if (is_utf8(line))
+               if (is_utf8(line->buf))
                        return NULL;
        }
        return "latin1";
 }
 
-static void convert_to_utf8(char *line, unsigned linesize, const char *charset)
+static void convert_to_utf8(struct strbuf *line, const char *charset)
 {
        char *out;
 
@@ -544,112 +491,118 @@ static void convert_to_utf8(char *line, unsigned linesize, const char *charset)
 
        if (!strcmp(metainfo_charset, charset))
                return;
-       out = reencode_string(line, metainfo_charset, charset);
+       out = reencode_string(line->buf, metainfo_charset, charset);
        if (!out)
                die("cannot convert from %s to %s\n",
                    charset, metainfo_charset);
-       strlcpy(line, out, linesize);
-       free(out);
+       strbuf_attach(line, out, strlen(out), strlen(out));
 }
 
-static int decode_header_bq(char *it, unsigned itsize)
+static int decode_header_bq(struct strbuf *it)
 {
-       char *in, *out, *ep, *cp, *sp;
-       char outbuf[1000];
+       char *in, *ep, *cp;
+       struct strbuf outbuf = STRBUF_INIT, *dec;
+       struct strbuf charset_q = STRBUF_INIT, piecebuf = STRBUF_INIT;
        int rfc2047 = 0;
 
-       in = it;
-       out = outbuf;
-       while ((ep = strstr(in, "=?")) != NULL) {
-               int sz, encoding;
-               char charset_q[256], piecebuf[256];
+       in = it->buf;
+       while (in - it->buf <= it->len && (ep = strstr(in, "=?")) != NULL) {
+               int encoding;
+               strbuf_reset(&charset_q);
+               strbuf_reset(&piecebuf);
                rfc2047 = 1;
 
                if (in != ep) {
-                       sz = ep - in;
-                       memcpy(out, in, sz);
-                       out += sz;
-                       in += sz;
+                       strbuf_add(&outbuf, in, ep - in);
+                       in = ep;
                }
                /* E.g.
                 * ep : "=?iso-2022-jp?B?GyR...?= foo"
                 * ep : "=?ISO-8859-1?Q?Foo=FCbar?= baz"
                 */
                ep += 2;
-               cp = strchr(ep, '?');
-               if (!cp)
-                       return rfc2047; /* no munging */
-               for (sp = ep; sp < cp; sp++)
-                       charset_q[sp - ep] = tolower(*sp);
-               charset_q[cp - ep] = 0;
+
+               if (ep - it->buf >= it->len || !(cp = strchr(ep, '?')))
+                       goto decode_header_bq_out;
+
+               if (cp + 3 - it->buf > it->len)
+                       goto decode_header_bq_out;
+               strbuf_add(&charset_q, ep, cp - ep);
+               strbuf_tolower(&charset_q);
+
                encoding = cp[1];
                if (!encoding || cp[2] != '?')
-                       return rfc2047; /* no munging */
+                       goto decode_header_bq_out;
                ep = strstr(cp + 3, "?=");
                if (!ep)
-                       return rfc2047; /* no munging */
+                       goto decode_header_bq_out;
+               strbuf_add(&piecebuf, cp + 3, ep - cp - 3);
                switch (tolower(encoding)) {
                default:
-                       return rfc2047; /* no munging */
+                       goto decode_header_bq_out;
                case 'b':
-                       sz = decode_b_segment(cp + 3, piecebuf, sizeof(piecebuf), ep);
+                       dec = decode_b_segment(&piecebuf);
                        break;
                case 'q':
-                       sz = decode_q_segment(cp + 3, piecebuf, sizeof(piecebuf), ep, 1);
+                       dec = decode_q_segment(&piecebuf, 1);
                        break;
                }
-               if (sz < 0)
-                       return rfc2047;
                if (metainfo_charset)
-                       convert_to_utf8(piecebuf, sizeof(piecebuf), charset_q);
+                       convert_to_utf8(dec, charset_q.buf);
 
-               sz = strlen(piecebuf);
-               if (outbuf + sizeof(outbuf) <= out + sz)
-                       return rfc2047; /* no munging */
-               strcpy(out, piecebuf);
-               out += sz;
+               strbuf_addbuf(&outbuf, dec);
+               strbuf_release(dec);
+               free(dec);
                in = ep + 2;
        }
-       strcpy(out, in);
-       strlcpy(it, outbuf, itsize);
+       strbuf_addstr(&outbuf, in);
+       strbuf_reset(it);
+       strbuf_addbuf(it, &outbuf);
+decode_header_bq_out:
+       strbuf_release(&outbuf);
+       strbuf_release(&charset_q);
+       strbuf_release(&piecebuf);
        return rfc2047;
 }
 
-static void decode_header(char *it, unsigned itsize)
+static void decode_header(struct strbuf *it)
 {
-
-       if (decode_header_bq(it, itsize))
+       if (decode_header_bq(it))
                return;
        /* otherwise "it" is a straight copy of the input.
         * This can be binary guck but there is no charset specified.
         */
        if (metainfo_charset)
-               convert_to_utf8(it, itsize, "");
+               convert_to_utf8(it, "");
 }
 
-static int decode_transfer_encoding(char *line, unsigned linesize, int inputlen)
+static void decode_transfer_encoding(struct strbuf *line)
 {
-       char *ep;
+       struct strbuf *ret;
 
        switch (transfer_encoding) {
        case TE_QP:
-               ep = line + inputlen;
-               return decode_q_segment(line, line, linesize, ep, 0);
+               ret = decode_q_segment(line, 0);
+               break;
        case TE_BASE64:
-               ep = line + inputlen;
-               return decode_b_segment(line, line, linesize, ep);
+               ret = decode_b_segment(line);
+               break;
        case TE_DONTCARE:
        default:
-               return inputlen;
+               return;
        }
+       strbuf_reset(line);
+       strbuf_addbuf(line, ret);
+       strbuf_release(ret);
+       free(ret);
 }
 
-static int handle_filter(char *line, unsigned linesize, int linelen);
+static void handle_filter(struct strbuf *line);
 
 static int find_boundary(void)
 {
-       while(fgets(line, sizeof(line), fin) != NULL) {
-               if (is_multipart_boundary(line))
+       while (!strbuf_getline(&line, fin, '\n')) {
+               if (is_multipart_boundary(&line))
                        return 1;
        }
        return 0;
@@ -657,12 +610,17 @@ static int find_boundary(void)
 
 static int handle_boundary(void)
 {
-       char newline[]="\n";
+       struct strbuf newline = STRBUF_INIT;
+
+       strbuf_addch(&newline, '\n');
 again:
-       if (!memcmp(line+content_top->boundary_len, "--", 2)) {
+       if (line.len >= (*content_top)->len + 2 &&
+           !memcmp(line.buf + (*content_top)->len, "--", 2)) {
                /* we hit an end boundary */
                /* pop the current boundary off the stack */
-               free(content_top->boundary);
+               strbuf_release(*content_top);
+               free(*content_top);
+               *content_top = NULL;
 
                /* technically won't happen as is_multipart_boundary()
                   will fail first.  But just in case..
@@ -672,7 +630,8 @@ again:
                                        "can't recover\n");
                        exit(1);
                }
-               handle_filter(newline, sizeof(newline), strlen(newline));
+               handle_filter(&newline);
+               strbuf_release(&newline);
 
                /* skip to the next boundary */
                if (!find_boundary())
@@ -682,39 +641,44 @@ again:
 
        /* set some defaults */
        transfer_encoding = TE_DONTCARE;
-       charset[0] = 0;
+       strbuf_reset(&charset);
        message_type = TYPE_TEXT;
 
        /* slurp in this section's info */
-       while (read_one_header_line(line, sizeof(line), fin))
-               check_header(line, sizeof(line), p_hdr_data, 0);
+       while (read_one_header_line(&line, fin))
+               check_header(&line, p_hdr_data, 0);
 
+       strbuf_release(&newline);
        /* eat the blank line after section info */
-       return (fgets(line, sizeof(line), fin) != NULL);
+       return (strbuf_getline(&line, fin, '\n') == 0);
 }
 
-static inline int patchbreak(const char *line)
+static inline int patchbreak(const struct strbuf *line)
 {
+       size_t i;
+
        /* Beginning of a "diff -" header? */
-       if (!memcmp("diff -", line, 6))
+       if (!prefixcmp(line->buf, "diff -"))
                return 1;
 
        /* CVS "Index: " line? */
-       if (!memcmp("Index: ", line, 7))
+       if (!prefixcmp(line->buf, "Index: "))
                return 1;
 
        /*
         * "--- <filename>" starts patches without headers
         * "---<sp>*" is a manual separator
         */
-       if (!memcmp("---", line, 3)) {
-               line += 3;
+       if (line->len < 4)
+               return 0;
+
+       if (!prefixcmp(line->buf, "---")) {
                /* space followed by a filename? */
-               if (line[0] == ' ' && !isspace(line[1]))
+               if (line->buf[3] == ' ' && !isspace(line->buf[4]))
                        return 1;
                /* Just whitespace? */
-               for (;;) {
-                       unsigned char c = *line++;
+               for (i = 3; i < line->len; i++) {
+                       unsigned char c = line->buf[i];
                        if (c == '\n')
                                return 1;
                        if (!isspace(c))
@@ -725,32 +689,24 @@ static inline int patchbreak(const char *line)
        return 0;
 }
 
-
-static int handle_commit_msg(char *line, unsigned linesize)
+static int handle_commit_msg(struct strbuf *line)
 {
        static int still_looking = 1;
-       char *endline = line + linesize;
 
        if (!cmitmsg)
                return 0;
 
        if (still_looking) {
-               char *cp = line;
-               if (isspace(*line)) {
-                       for (cp = line + 1; *cp; cp++) {
-                               if (!isspace(*cp))
-                                       break;
-                       }
-                       if (!*cp)
-                               return 0;
-               }
-               if ((still_looking = check_header(cp, endline - cp, s_hdr_data, 0)) != 0)
+               strbuf_ltrim(line);
+               if (!line->len)
+                       return 0;
+               if ((still_looking = check_header(line, s_hdr_data, 0)) != 0)
                        return 0;
        }
 
        /* normalize the log message to UTF-8. */
        if (metainfo_charset)
-               convert_to_utf8(line, endline - line, charset);
+               convert_to_utf8(line, charset.buf);
 
        if (patchbreak(line)) {
                fclose(cmitmsg);
@@ -758,142 +714,132 @@ static int handle_commit_msg(char *line, unsigned linesize)
                return 1;
        }
 
-       fputs(line, cmitmsg);
+       fputs(line->buf, cmitmsg);
        return 0;
 }
 
-static int handle_patch(char *line, int len)
+static void handle_patch(const struct strbuf *line)
 {
-       fwrite(line, 1, len, patchfile);
+       fwrite(line->buf, 1, line->len, patchfile);
        patch_lines++;
-       return 0;
 }
 
-static int handle_filter(char *line, unsigned linesize, int linelen)
+static void handle_filter(struct strbuf *line)
 {
        static int filter = 0;
 
-       /* filter tells us which part we left off on
-        * a non-zero return indicates we hit a filter point
-        */
+       /* filter tells us which part we left off on */
        switch (filter) {
        case 0:
-               if (!handle_commit_msg(line, linesize))
+               if (!handle_commit_msg(line))
                        break;
                filter++;
        case 1:
-               if (!handle_patch(line, linelen))
-                       break;
-               filter++;
-       default:
-               return 1;
+               handle_patch(line);
+               break;
        }
-
-       return 0;
 }
 
 static void handle_body(void)
 {
-       int rc = 0;
-       static char newline[2000];
-       static char *np = newline;
-       int len = strlen(line);
+       int len = 0;
+       struct strbuf prev = STRBUF_INIT;
 
        /* Skip up to the first boundary */
-       if (content_top->boundary) {
+       if (*content_top) {
                if (!find_boundary())
-                       return;
+                       goto handle_body_out;
        }
 
        do {
+               strbuf_setlen(&line, line.len + len);
+
                /* process any boundary lines */
-               if (content_top->boundary && is_multipart_boundary(line)) {
+               if (*content_top && is_multipart_boundary(&line)) {
                        /* flush any leftover */
-                       if (np != newline)
-                               handle_filter(newline, sizeof(newline),
-                                             np - newline);
+                       if (line.len)
+                               handle_filter(&line);
+
                        if (!handle_boundary())
-                               return;
-                       len = strlen(line);
+                               goto handle_body_out;
                }
 
                /* Unwrap transfer encoding */
-               len = decode_transfer_encoding(line, sizeof(line), len);
-               if (len < 0) {
-                       error("Malformed input line");
-                       return;
-               }
+               decode_transfer_encoding(&line);
 
                switch (transfer_encoding) {
                case TE_BASE64:
                case TE_QP:
                {
-                       char *op = line;
+                       struct strbuf **lines, **it, *sb;
+
+                       /* Prepend any previous partial lines */
+                       strbuf_insert(&line, 0, prev.buf, prev.len);
+                       strbuf_reset(&prev);
 
                        /* binary data most likely doesn't have newlines */
                        if (message_type != TYPE_TEXT) {
-                               rc = handle_filter(line, sizeof(line), len);
+                               handle_filter(&line);
                                break;
                        }
-
                        /*
                         * This is a decoded line that may contain
                         * multiple new lines.  Pass only one chunk
                         * at a time to handle_filter()
                         */
-                       do {
-                               while (op < line + len && *op != '\n')
-                                       *np++ = *op++;
-                               *np = *op;
-                               if (*np != 0) {
-                                       /* should be sitting on a new line */
-                                       *(++np) = 0;
-                                       op++;
-                                       rc = handle_filter(newline, sizeof(newline), np - newline);
-                                       np = newline;
-                               }
-                       } while (op < line + len);
+                       lines = strbuf_split(&line, '\n');
+                       for (it = lines; (sb = *it); it++) {
+                               if (*(it + 1) == NULL) /* The last line */
+                                       if (sb->buf[sb->len - 1] != '\n') {
+                                               /* Partial line, save it for later. */
+                                               strbuf_addbuf(&prev, sb);
+                                               break;
+                                       }
+                               handle_filter(sb);
+                       }
                        /*
-                        * The partial chunk is saved in newline and will be
+                        * The partial chunk is saved in "prev" and will be
                         * appended by the next iteration of read_line_with_nul().
                         */
+                       strbuf_list_free(lines);
                        break;
                }
                default:
-                       rc = handle_filter(line, sizeof(line), len);
+                       handle_filter(&line);
                }
-               if (rc)
-                       /* nothing left to filter */
-                       break;
-       } while ((len = read_line_with_nul(line, sizeof(line), fin)));
 
-       return;
+               strbuf_reset(&line);
+               if (strbuf_avail(&line) < 100)
+                       strbuf_grow(&line, 100);
+       } while ((len = read_line_with_nul(line.buf, strbuf_avail(&line), fin)));
+
+handle_body_out:
+       strbuf_release(&prev);
 }
 
-static void output_header_lines(FILE *fout, const char *hdr, char *data)
+static void output_header_lines(FILE *fout, const char *hdr, const struct strbuf *data)
 {
+       const char *sp = data->buf;
        while (1) {
-               char *ep = strchr(data, '\n');
+               char *ep = strchr(sp, '\n');
                int len;
                if (!ep)
-                       len = strlen(data);
+                       len = strlen(sp);
                else
-                       len = ep - data;
-               fprintf(fout, "%s: %.*s\n", hdr, len, data);
+                       len = ep - sp;
+               fprintf(fout, "%s: %.*s\n", hdr, len, sp);
                if (!ep)
                        break;
-               data = ep + 1;
+               sp = ep + 1;
        }
 }
 
 static void handle_info(void)
 {
-       char *sub;
-       char *hdr;
+       struct strbuf *hdr;
        int i;
 
        for (i = 0; header[i]; i++) {
-
                /* only print inbody headers if we output a patch file */
                if (patch_lines && s_hdr_data[i])
                        hdr = s_hdr_data[i];
@@ -903,20 +849,18 @@ static void handle_info(void)
                        continue;
 
                if (!memcmp(header[i], "Subject", 7)) {
-                       if (keep_subject)
-                               sub = hdr;
-                       else {
-                               sub = cleanup_subject(hdr);
-                               cleanup_space(sub);
+                       if (!keep_subject) {
+                               cleanup_subject(hdr);
+                               cleanup_space(hdr);
                        }
-                       output_header_lines(fout, "Subject", sub);
+                       output_header_lines(fout, "Subject", hdr);
                } else if (!memcmp(header[i], "From", 4)) {
                        handle_from(hdr);
-                       fprintf(fout, "Author: %s\n", name);
-                       fprintf(fout, "Email: %s\n", email);
+                       fprintf(fout, "Author: %s\n", name.buf);
+                       fprintf(fout, "Email: %s\n", email.buf);
                } else {
                        cleanup_space(hdr);
-                       fprintf(fout, "%s: %s\n", header[i], hdr);
+                       fprintf(fout, "%s: %s\n", header[i], hdr->buf);
                }
        }
        fprintf(fout, "\n");
@@ -943,8 +887,8 @@ static int mailinfo(FILE *in, FILE *out, int ks, const char *encoding,
                return -1;
        }
 
-       p_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(char *));
-       s_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(char *));
+       p_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(*p_hdr_data));
+       s_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(*s_hdr_data));
 
        do {
                peek = fgetc(in);
@@ -952,8 +896,8 @@ static int mailinfo(FILE *in, FILE *out, int ks, const char *encoding,
        ungetc(peek, in);
 
        /* process the email header */
-       while (read_one_header_line(line, sizeof(line), fin))
-               check_header(line, sizeof(line), p_hdr_data, 1);
+       while (read_one_header_line(&line, fin))
+               check_header(&line, p_hdr_data, 1);
 
        handle_body();
        handle_info();
@@ -962,7 +906,7 @@ static int mailinfo(FILE *in, FILE *out, int ks, const char *encoding,
 }
 
 static const char mailinfo_usage[] =
-       "git-mailinfo [-k] [-u | --encoding=<encoding> | -n] msg patch <mail >info";
+       "git mailinfo [-k] [-u | --encoding=<encoding> | -n] msg patch <mail >info";
 
 int cmd_mailinfo(int argc, const char **argv, const char *prefix)
 {
index e8cbe678ecdc0863ebe92e6499dd2b1eacf77db6..13c60c39a402834fbcdb58928c5b5686b7b05a51 100644 (file)
@@ -9,7 +9,7 @@
 #include "path-list.h"
 
 static const char git_mailsplit_usage[] =
-"git-mailsplit [-d<prec>] [-f<n>] [-b] -o<directory> [<mbox>|<Maildir>...]";
+"git mailsplit [-d<prec>] [-f<n>] [-b] -o<directory> [<mbox>|<Maildir>...]";
 
 static int is_from_line(const char *line, int len)
 {
index bcf9395aafb475edd22459eaf05cf5e180ca9b8f..1cb2925d2f3dc6dc1a38c31bcec1c10ae8146a22 100644 (file)
@@ -20,7 +20,7 @@ static int show_merge_base(struct commit *rev1, struct commit *rev2, int show_al
 }
 
 static const char merge_base_usage[] =
-"git-merge-base [--all] <commit-id> <commit-id>";
+"git merge-base [--all] <commit-id> <commit-id>";
 
 int cmd_merge_base(int argc, const char **argv, const char *prefix)
 {
index 3731853f83be37d3790a5db8ef037af0b0a4f7c5..652a2c32bb0913108e0435de86392764da3ad611 100644 (file)
@@ -248,7 +248,7 @@ struct tree *write_tree_from_memory(void)
 
 static int save_files_dirs(const unsigned char *sha1,
                const char *base, int baselen, const char *path,
-               unsigned int mode, int stage)
+               unsigned int mode, int stage, void *context)
 {
        int len = strlen(path);
        char *newpath = xmalloc(baselen + len + 1);
@@ -268,7 +268,7 @@ static int save_files_dirs(const unsigned char *sha1,
 static int get_files_dirs(struct tree *tree)
 {
        int n;
-       if (read_tree_recursive(tree, "", 0, 0, NULL, save_files_dirs) != 0)
+       if (read_tree_recursive(tree, "", 0, 0, NULL, save_files_dirs, NULL))
                return 0;
        n = current_file_set.nr + current_directory_set.nr;
        return n;
index 129b4e62dd3bc3662f8f076e39c90b109f4bd669..e97c79e60cdb8227ad682a3927ae955005cbe1f3 100644 (file)
@@ -50,11 +50,9 @@ static size_t use_strategies_nr, use_strategies_alloc;
 static const char *branch;
 
 static struct strategy all_strategy[] = {
-       { "recur",      NO_TRIVIAL },
        { "recursive",  DEFAULT_TWOHEAD | NO_TRIVIAL },
        { "octopus",    DEFAULT_OCTOPUS },
        { "resolve",    0 },
-       { "stupid",     0 },
        { "ours",       NO_FAST_FORWARD | NO_TRIVIAL },
        { "subtree",    NO_FAST_FORWARD | NO_TRIVIAL },
 };
@@ -68,10 +66,11 @@ static int option_parse_message(const struct option *opt,
 
        if (unset)
                strbuf_setlen(buf, 0);
-       else {
+       else if (arg) {
                strbuf_addf(buf, "%s\n\n", arg);
                have_message = 1;
-       }
+       } else
+               return error("switch `m' requires a value");
        return 0;
 }
 
index 5530e11b89c2c05c95c8ab1e82999eec0fdcc4c5..ba9cedab6dcb92afb83646b2fdb48247d0184f7d 100644 (file)
@@ -11,7 +11,7 @@
 #include "parse-options.h"
 
 static const char * const builtin_mv_usage[] = {
-       "git-mv [options] <source>... <destination>",
+       "git mv [options] <source>... <destination>",
        NULL
 };
 
index f153da012f4e89ff8744ede70911cd4690de79b2..85612c4dcb719b460623204046e35486e9d9fe97 100644 (file)
@@ -172,7 +172,7 @@ static void show_name(const struct object *obj,
 }
 
 static char const * const name_rev_usage[] = {
-       "git-name-rev [options] ( --all | --stdin | <commit>... )",
+       "git name-rev [options] ( --all | --stdin | <commit>... )",
        NULL
 };
 
index ff90aefa1c1818b90391223c8cf6971923207e97..34246df4ec946273d9f42e6f0848b02d8510beea 100644 (file)
@@ -3,7 +3,7 @@
 #include "pack-refs.h"
 
 static char const * const pack_refs_usage[] = {
-       "git-pack-refs [options]",
+       "git pack-refs [options]",
        NULL
 };
 
index 241afbbab54cef58361b0a8284fe1cefcd5dc2a8..10cb8df8457fd5f2ba9be62ecd0f9384e21c3e63 100644 (file)
@@ -3,7 +3,7 @@
 #include "progress.h"
 
 static const char prune_packed_usage[] =
-"git-prune-packed [-n] [-q]";
+"git prune-packed [-n] [-q]";
 
 #define DRY_RUN 01
 #define VERBOSE 02
index bd3d2f67f3eb54cedb1a6c18582c7e10aa3f7bc6..7de4cabe078a67e1272ad9a483d302a8642bd4f7 100644 (file)
@@ -7,7 +7,7 @@
 #include "parse-options.h"
 
 static const char * const prune_usage[] = {
-       "git-prune [-n] [--expire <time>] [--] [<head>...]",
+       "git prune [-n] [--expire <time>] [--] [<head>...]",
        NULL
 };
 static int show_only;
index b35aad68e9154bb755c51323106c738ab4fc61e9..c1ed68d938f67343c6938cfef54d5ff69a522a63 100644 (file)
 #include "parse-options.h"
 
 static const char * const push_usage[] = {
-       "git-push [--all | --mirror] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]",
+       "git push [--all | --mirror] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]",
        NULL,
 };
 
-static int thin, verbose;
+static int thin;
 static const char *receivepack;
 
 static const char **refspec;
@@ -84,7 +84,7 @@ static int do_push(const char *repo, int flags)
                if (thin)
                        transport_set_option(transport, TRANS_OPT_THIN, "yes");
 
-               if (verbose)
+               if (flags & TRANSPORT_PUSH_VERBOSE)
                        fprintf(stderr, "Pushing to %s\n", remote->url[i]);
                err = transport_push(transport, refspec_nr, refspec, flags);
                err |= transport_disconnect(transport);
@@ -101,22 +101,19 @@ static int do_push(const char *repo, int flags)
 int cmd_push(int argc, const char **argv, const char *prefix)
 {
        int flags = 0;
-       int all = 0;
-       int mirror = 0;
-       int dry_run = 0;
-       int force = 0;
        int tags = 0;
        int rc;
        const char *repo = NULL;        /* default repository */
 
        struct option options[] = {
-               OPT__VERBOSE(&verbose),
+               OPT_BIT('v', "verbose", &flags, "be verbose", TRANSPORT_PUSH_VERBOSE),
                OPT_STRING( 0 , "repo", &repo, "repository", "repository"),
-               OPT_BOOLEAN( 0 , "all", &all, "push all refs"),
-               OPT_BOOLEAN( 0 , "mirror", &mirror, "mirror all refs"),
+               OPT_BIT( 0 , "all", &flags, "push all refs", TRANSPORT_PUSH_ALL),
+               OPT_BIT( 0 , "mirror", &flags, "mirror all refs",
+                           (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
                OPT_BOOLEAN( 0 , "tags", &tags, "push tags"),
-               OPT_BOOLEAN( 0 , "dry-run", &dry_run, "dry run"),
-               OPT_BOOLEAN('f', "force", &force, "force updates"),
+               OPT_BIT( 0 , "dry-run", &flags, "dry run", TRANSPORT_PUSH_DRY_RUN),
+               OPT_BIT('f', "force", &flags, "force updates", TRANSPORT_PUSH_FORCE),
                OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"),
                OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"),
                OPT_STRING( 0 , "exec", &receivepack, "receive-pack", "receive pack program"),
@@ -125,18 +122,8 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 
        argc = parse_options(argc, argv, options, push_usage, 0);
 
-       if (force)
-               flags |= TRANSPORT_PUSH_FORCE;
-       if (dry_run)
-               flags |= TRANSPORT_PUSH_DRY_RUN;
-       if (verbose)
-               flags |= TRANSPORT_PUSH_VERBOSE;
        if (tags)
                add_refspec("refs/tags/*");
-       if (all)
-               flags |= TRANSPORT_PUSH_ALL;
-       if (mirror)
-               flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
 
        if (argc > 0) {
                repo = argv[0];
index 125d455b97ca499806ff417871ab6ce7aad922c5..0c34e378199064e87aa09caf0fa0a2346333ec69 100644 (file)
@@ -13,9 +13,9 @@
  */
 
 static const char reflog_expire_usage[] =
-"git-reflog (show|expire) [--verbose] [--dry-run] [--stale-fix] [--expire=<time>] [--expire-unreachable=<time>] [--all] <refs>...";
+"git reflog (show|expire) [--verbose] [--dry-run] [--stale-fix] [--expire=<time>] [--expire-unreachable=<time>] [--all] <refs>...";
 static const char reflog_delete_usage[] =
-"git-reflog delete [--verbose] [--dry-run] [--rewrite] [--updateref] <refs>...";
+"git reflog delete [--verbose] [--dry-run] [--rewrite] [--updateref] <refs>...";
 
 static unsigned long default_reflog_expire;
 static unsigned long default_reflog_expire_unreachable;
@@ -630,7 +630,7 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix)
  */
 
 static const char reflog_usage[] =
-"git-reflog (expire | ...)";
+"git reflog (expire | ...)";
 
 int cmd_reflog(int argc, const char **argv, const char *prefix)
 {
index 1491354a9d5d22546acde09021b0f666f6740257..db12668cfeb87ca405e7b24f54b11505a701f83c 100644 (file)
@@ -147,6 +147,15 @@ struct branch_info {
 
 static struct path_list branch_list;
 
+static const char *abbrev_ref(const char *name, const char *prefix)
+{
+       const char *abbrev = skip_prefix(name, prefix);
+       if (abbrev)
+               return abbrev;
+       return name;
+}
+#define abbrev_branch(name) abbrev_ref((name), "refs/heads/")
+
 static int config_read_branches(const char *key, const char *value, void *cb)
 {
        if (!prefixcmp(key, "branch.")) {
@@ -176,18 +185,12 @@ static int config_read_branches(const char *key, const char *value, void *cb)
                        info->remote = xstrdup(value);
                } else {
                        char *space = strchr(value, ' ');
-                       const char *ptr = skip_prefix(value, "refs/heads/");
-                       if (ptr)
-                               value = ptr;
+                       value = abbrev_branch(value);
                        while (space) {
                                char *merge;
                                merge = xstrndup(value, space - value);
                                path_list_append(merge, &info->merge);
-                               ptr = skip_prefix(space + 1, "refs/heads/");
-                               if (ptr)
-                                       value = ptr;
-                               else
-                                       value = space + 1;
+                               value = abbrev_branch(space + 1);
                                space = strchr(value, ' ');
                        }
                        path_list_append(xstrdup(value), &info->merge);
@@ -219,12 +222,7 @@ static int handle_one_branch(const char *refname,
        refspec.dst = (char *)refname;
        if (!remote_find_tracking(states->remote, &refspec)) {
                struct path_list_item *item;
-               const char *name, *ptr;
-               ptr = skip_prefix(refspec.src, "refs/heads/");
-               if (ptr)
-                       name = ptr;
-               else
-                       name = refspec.src;
+               const char *name = abbrev_branch(refspec.src);
                /* symbolic refs pointing nowhere were handled already */
                if ((flags & REF_ISSYMREF) ||
                                unsorted_path_list_has_path(&states->tracked,
@@ -253,7 +251,6 @@ static int get_ref_states(const struct ref *ref, struct ref_states *states)
                struct path_list *target = &states->tracked;
                unsigned char sha1[20];
                void *util = NULL;
-               const char *ptr;
 
                if (!ref->peer_ref || read_ref(ref->peer_ref->name, sha1))
                        target = &states->new;
@@ -262,10 +259,7 @@ static int get_ref_states(const struct ref *ref, struct ref_states *states)
                        if (hashcmp(sha1, ref->new_sha1))
                                util = &states;
                }
-               ptr = skip_prefix(ref->name, "refs/heads/");
-               if (!ptr)
-                       ptr = ref->name;
-               path_list_append(ptr, target)->util = util;
+               path_list_append(abbrev_branch(ref->name), target)->util = util;
        }
        free_refs(fetch_map);
 
@@ -460,10 +454,8 @@ static int append_ref_to_tracked_list(const char *refname,
 
        memset(&refspec, 0, sizeof(refspec));
        refspec.dst = (char *)refname;
-       if (!remote_find_tracking(states->remote, &refspec)) {
-               path_list_append(skip_prefix(refspec.src, "refs/heads/"),
-                       &states->tracked);
-       }
+       if (!remote_find_tracking(states->remote, &refspec))
+               path_list_append(abbrev_branch(refspec.src), &states->tracked);
 
        return 0;
 }
@@ -530,15 +522,10 @@ static int show(int argc, const char **argv)
                                        "es" : "");
                        for (i = 0; i < states.remote->push_refspec_nr; i++) {
                                struct refspec *spec = states.remote->push + i;
-                               const char *p = "", *q = "";
-                               if (spec->src)
-                                       p = skip_prefix(spec->src, "refs/heads/");
-                               if (spec->dst)
-                                       q = skip_prefix(spec->dst, "refs/heads/");
                                printf(" %s%s%s%s", spec->force ? "+" : "",
-                                       p ? p : spec->src,
-                                       spec->dst ? ":" : "",
-                                       q ? q : spec->dst);
+                                      abbrev_branch(spec->src),
+                                      spec->dst ? ":" : "",
+                                      spec->dst ? abbrev_branch(spec->dst) : "");
                        }
                        printf("\n");
                }
@@ -588,7 +575,7 @@ static int prune(int argc, const char **argv)
                                result |= delete_ref(refname, NULL);
 
                        printf(" * [%s] %s\n", dry_run ? "would prune" : "pruned",
-                              skip_prefix(refname, "refs/remotes/"));
+                              abbrev_ref(refname, "refs/remotes/"));
                }
 
                /* NEEDSWORK: free remote */
index 5d40e16932a4d8f3761b9aaebc21b630be904f8a..580580502cc0d84400edca8e2bda5ce607b43b58 100644 (file)
@@ -6,7 +6,7 @@
 #include "xdiff-interface.h"
 
 static const char git_rerere_usage[] =
-"git-rerere [clear | status | diff | gc]";
+"git rerere [clear | status | diff | gc]";
 
 /* these values are days */
 static int cutoff_noresolve = 15;
index a0321694c5c3d5798d28f8fe14493652e0dd0054..4d246c31b19381778848024ff49aebf3e77fdbbc 100644 (file)
@@ -20,8 +20,8 @@
 #include "parse-options.h"
 
 static const char * const git_reset_usage[] = {
-       "git-reset [--mixed | --soft | --hard] [-q] [<commit>]",
-       "git-reset [--mixed] <commit> [--] <paths>...",
+       "git reset [--mixed | --soft | --hard] [-q] [<commit>]",
+       "git reset [--mixed] <commit> [--] <paths>...",
        NULL
 };
 
@@ -96,7 +96,7 @@ static int update_index_refresh(int fd, struct lock_file *index_lock)
 
        if (read_cache() < 0)
                return error("Could not read index");
-       result = refresh_cache(0) ? 1 : 0;
+       result = refresh_cache(REFRESH_SAY_CHANGED) ? 1 : 0;
        if (write_cache(fd, active_cache, active_nr) ||
                        commit_locked_index(index_lock))
                return error ("Could not refresh index");
index b4a2c447f22163b3165a0c6081899498e3048b51..893762c80f4910fadf2d6df414bd835cccb7faaa 100644 (file)
@@ -17,7 +17,7 @@
 #define COUNTED                (1u<<16)
 
 static const char rev_list_usage[] =
-"git-rev-list [OPTION] <commit-id>... [ -- paths... ]\n"
+"git rev-list [OPTION] <commit-id>... [ -- paths... ]\n"
 "  limiting output:\n"
 "    --max-count=nr\n"
 "    --max-age=epoch\n"
@@ -590,6 +590,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
        revs.commit_format = CMIT_FMT_UNSPECIFIED;
        argc = setup_revisions(argc, argv, &revs, NULL);
 
+       quiet = DIFF_OPT_TST(&revs.diffopt, QUIET);
        for (i = 1 ; i < argc; i++) {
                const char *arg = argv[i];
 
@@ -621,10 +622,6 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
                        read_revisions_from_stdin(&revs);
                        continue;
                }
-               if (!strcmp(arg, "--quiet")) {
-                       quiet = 1;
-                       continue;
-               }
                usage(rev_list_usage);
 
        }
index a7860ed75ac4a7b1895bfe088e34a39b24448f57..aa71f4a4fac819531e47f87293bc7b01b22bab94 100644 (file)
@@ -268,7 +268,7 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
 {
        static int keep_dashdash = 0;
        static char const * const parseopt_usage[] = {
-               "git-rev-parse --parseopt [options] -- [<args>...]",
+               "git rev-parse --parseopt [options] -- [<args>...]",
                NULL
        };
        static struct option parseopt_opts[] = {
index f3d452418c25b0d95a911a050f75ba190d6513c1..e9da870d22c14c32a0e0a6cb71b933c79a2d8b53 100644 (file)
  */
 
 static const char * const revert_usage[] = {
-       "git-revert [options] <commit-ish>",
+       "git revert [options] <commit-ish>",
        NULL
 };
 
 static const char * const cherry_pick_usage[] = {
-       "git-cherry-pick [options] <commit-ish>",
+       "git cherry-pick [options] <commit-ish>",
        NULL
 };
 
index 22c9bd1c6cf2d372e0262506cc1e21daebdf579a..ee8247b08cd007f73d5dfffa560a9efe33d327b9 100644 (file)
@@ -11,7 +11,7 @@
 #include "parse-options.h"
 
 static const char * const builtin_rm_usage[] = {
-       "git-rm [options] [--] <file>...",
+       "git rm [options] [--] <file>...",
        NULL
 };
 
@@ -146,11 +146,6 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
 
        git_config(git_default_config, NULL);
 
-       newfd = hold_locked_index(&lock_file, 1);
-
-       if (read_cache() < 0)
-               die("index file corrupt");
-
        argc = parse_options(argc, argv, builtin_rm_options, builtin_rm_usage, 0);
        if (!argc)
                usage_with_options(builtin_rm_usage, builtin_rm_options);
@@ -158,6 +153,11 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
        if (!index_only)
                setup_work_tree();
 
+       newfd = hold_locked_index(&lock_file, 1);
+
+       if (read_cache() < 0)
+               die("index file corrupt");
+
        pathspec = get_pathspec(prefix, argv);
        seen = NULL;
        for (i = 0; pathspec[i] ; i++)
index a708d0af48e210fd4439c336c2faa3e7400b5fa4..7588d22885d0af24ae80f1d687ccd097fe365021 100644 (file)
@@ -8,7 +8,7 @@
 #include "send-pack.h"
 
 static const char send_pack_usage[] =
-"git-send-pack [--all | --mirror] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\n"
+"git send-pack [--all | --mirror] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\n"
 "  --all and explicit <ref> specification are mutually exclusive.";
 
 static struct send_pack_args args = {
index f8bcbfce4009337c4aea0b923a620fc4697e4df3..94c4723856924a9643bcaf6c14fd9679667cbbdd 100644 (file)
@@ -10,7 +10,7 @@
 #include "parse-options.h"
 
 static char const * const shortlog_usage[] = {
-       "git-shortlog [-n] [-s] [-e] [-w] [rev-opts] [--] [<commit-id>... ]",
+       "git shortlog [-n] [-s] [-e] [-w] [rev-opts] [--] [<commit-id>... ]",
        "",
        "[rev-opts] are documented in git-rev-list(1)",
        NULL
index 93047f5117796fb7556fa23871397e68e9f5e4c2..233eed499d0b8790781326ff0455bdc7f09fe4d4 100644 (file)
@@ -4,7 +4,7 @@
 #include "builtin.h"
 
 static const char show_branch_usage[] =
-"git-show-branch [--sparse] [--current] [--all] [--remotes] [--topo-order] [--more=count | --list | --independent | --merge-base ] [--topics] [<refs>...] | --reflog[=n[,b]] <branch>";
+"git show-branch [--sparse] [--current] [--all] [--remotes] [--topo-order] [--more=count | --list | --independent | --merge-base ] [--topics] [<refs>...] | --reflog[=n[,b]] <branch>";
 static const char show_branch_usage_reflog[] =
 "--reflog is incompatible with --all, --remotes, --independent or --merge-base";
 
index b49bdb6900f2c49b55880f9f220597bf3f156810..bfc78bb3f6eff2f8e39649b9649ae7263f143ad9 100644 (file)
@@ -4,7 +4,7 @@
 #include "parse-options.h"
 
 static const char * const git_symbolic_ref_usage[] = {
-       "git-symbolic-ref [options] name [ref]",
+       "git symbolic-ref [options] name [ref]",
        NULL
 };
 
index a70922b21c4bc2ff552e00cd65ecba6c17a33000..c2cca6cb6dc46a221c65092d7c419445d6442b5f 100644 (file)
 #include "parse-options.h"
 
 static const char * const git_tag_usage[] = {
-       "git-tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]",
-       "git-tag -d <tagname>...",
-       "git-tag -l [-n[<num>]] [<pattern>]",
-       "git-tag -v <tagname>...",
+       "git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]",
+       "git tag -d <tagname>...",
+       "git tag -l [-n[<num>]] [<pattern>]",
+       "git tag -v <tagname>...",
        NULL
 };
 
index b04719ef20929d40ef0c898c37616a5e7316f272..f4bea4a322c26a54734286073c5e67444555c2d9 100644 (file)
@@ -8,7 +8,7 @@
 #include "quote.h"
 
 static const char tar_tree_usage[] =
-"git-tar-tree [--remote=<repo>] <tree-ish> [basedir]\n"
+"git tar-tree [--remote=<repo>] <tree-ish> [basedir]\n"
 "*** Note that this command is now deprecated; use git-archive instead.";
 
 int cmd_tar_tree(int argc, const char **argv, const char *prefix)
index 9e0d7ab11ee01c6a1def223820038a94113f348c..38eb53ccba2b97a0fccf50d6ba0b7424fe2d1bcb 100644 (file)
@@ -387,7 +387,7 @@ static void read_index_info(int line_termination)
 }
 
 static const char update_index_usage[] =
-"git-update-index [-q] [--add] [--replace] [--remove] [--unmerged] [--refresh] [--really-refresh] [--cacheinfo] [--chmod=(+|-)x] [--assume-unchanged] [--info-only] [--force-remove] [--stdin] [--index-info] [--unresolve] [--again | -g] [--ignore-missing] [-z] [--verbose] [--] <file>...";
+"git update-index [-q] [--add] [--replace] [--remove] [--unmerged] [--refresh] [--really-refresh] [--cacheinfo] [--chmod=(+|-)x] [--assume-unchanged] [--info-only] [--force-remove] [--stdin] [--index-info] [--unresolve] [--again | -g] [--ignore-missing] [-z] [--verbose] [--] <file>...";
 
 static unsigned char head_sha1[20];
 static unsigned char merge_head_sha1[20];
index d90d11d2e35c38baab32f05f58125aaf1baee6cc..56a0b1b39cf4c4fc51dbbff256240655bc36a038 100644 (file)
@@ -4,8 +4,8 @@
 #include "parse-options.h"
 
 static const char * const git_update_ref_usage[] = {
-       "git-update-ref [options] -d <refname> [<oldval>]",
-       "git-update-ref [options]    <refname> <newval> [<oldval>]",
+       "git update-ref [options] -d <refname> [<oldval>]",
+       "git update-ref [options]    <refname> <newval> [<oldval>]",
        NULL
 };
 
index 371400d49a5ff9f6ce297d7af07eb3fd6426c9ee..13a6c6203eff7d8dc96a56fa5709dc9eb69da0a6 100644 (file)
@@ -8,18 +8,19 @@
 #include "sideband.h"
 
 static const char upload_archive_usage[] =
-       "git-upload-archive <repo>";
+       "git upload-archive <repo>";
 
 static const char deadchild[] =
-"git-upload-archive: archiver died with error";
+"git upload-archive: archiver died with error";
 
 static const char lostchild[] =
-"git-upload-archive: archiver process was lost";
+"git upload-archive: archiver process was lost";
 
 
 static int run_upload_archive(int argc, const char **argv, const char *prefix)
 {
-       struct archiver ar;
+       const struct archiver *ar;
+       struct archiver_args args;
        const char *sent_argv[MAX_ARGS];
        const char *arg_cmd = "argument ";
        char *p, buf[4096];
@@ -65,12 +66,12 @@ static int run_upload_archive(int argc, const char **argv, const char *prefix)
        sent_argv[sent_argc] = NULL;
 
        /* parse all options sent by the client */
-       treeish_idx = parse_archive_args(sent_argc, sent_argv, &ar);
+       treeish_idx = parse_archive_args(sent_argc, sent_argv, &ar, &args);
 
-       parse_treeish_arg(sent_argv + treeish_idx, &ar.args, prefix);
-       parse_pathspec_arg(sent_argv + treeish_idx + 1, &ar.args);
+       parse_treeish_arg(sent_argv + treeish_idx, &args, prefix);
+       parse_pathspec_arg(sent_argv + treeish_idx + 1, &args);
 
-       return ar.write_archive(&ar.args);
+       return ar->write_archive(&args);
 }
 
 static void error_clnt(const char *fmt, ...)
index 92eaa89a45eff2e76e531a914bdccca5fafe98b0..7d837f0f98bfdf558d4c8eaf5a9090fa3be35b6d 100644 (file)
@@ -12,7 +12,7 @@
 #include <signal.h>
 
 static const char builtin_verify_tag_usage[] =
-               "git-verify-tag [-v|--verbose] <tag>...";
+               "git verify-tag [-v|--verbose] <tag>...";
 
 #define PGP_SIGNATURE "-----BEGIN PGP SIGNATURE-----"
 
index c2187997447df64948577d8a9a78f4462239b369..52a3c015ff8e4611522bd41078bdb2934d288d35 100644 (file)
@@ -9,7 +9,7 @@
 #include "cache-tree.h"
 
 static const char write_tree_usage[] =
-"git-write-tree [--missing-ok] [--prefix=<prefix>/]";
+"git write-tree [--missing-ok] [--prefix=<prefix>/]";
 
 int cmd_write_tree(int argc, const char **argv, const char *unused_prefix)
 {
index 73cb3407077275f82677839d2c9e794c12833c95..5f8ee87bb1c446341b640c2f978a658d6bfcfcd0 100644 (file)
@@ -507,7 +507,7 @@ struct cache_tree *cache_tree_read(const char *buffer, unsigned long size)
        return read_one(&buffer, &size);
 }
 
-struct cache_tree *cache_tree_find(struct cache_tree *it, const char *path)
+static struct cache_tree *cache_tree_find(struct cache_tree *it, const char *path)
 {
        while (*path) {
                const char *slash;
index 44aad426d319b83eda013e115f35e066cc590cb8..cf8b790874c4a4f5890b360c237ccdd4a5a03de4 100644 (file)
@@ -28,8 +28,6 @@ struct cache_tree *cache_tree_read(const char *buffer, unsigned long size);
 int cache_tree_fully_valid(struct cache_tree *);
 int cache_tree_update(struct cache_tree *, struct cache_entry **, int, int, int);
 
-struct cache_tree *cache_tree_find(struct cache_tree *, const char *);
-
 #define WRITE_TREE_UNREADABLE_INDEX (-1)
 #define WRITE_TREE_UNMERGED_INDEX (-2)
 #define WRITE_TREE_PREFIX_ERROR (-3)
diff --git a/cache.h b/cache.h
index a779d9207c8ea4d4e8455a89b17f312e0e71332d..38985aa63eaa41ee7ddc322c682a7482a8204cbe 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -397,7 +397,8 @@ extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);
 #define REFRESH_UNMERGED       0x0002  /* allow unmerged */
 #define REFRESH_QUIET          0x0004  /* be quiet about it */
 #define REFRESH_IGNORE_MISSING 0x0008  /* ignore non-existent */
-#define REFRESH_IGNORE_SUBMODULES      0x0008  /* ignore submodules */
+#define REFRESH_IGNORE_SUBMODULES      0x0010  /* ignore submodules */
+#define REFRESH_SAY_CHANGED    0x0020  /* say "changed" not "needs update" */
 extern int refresh_index(struct index_state *, unsigned int flags, const char **pathspec, char *seen);
 
 struct lock_file {
index c0bc849e45dc511202d1e7602f570de47630e6aa..772cad510d5d260fdf33b4f7d6ff79f9f3367b05 100644 (file)
@@ -536,7 +536,8 @@ static char *lookup_prog(const char *dir, const char *cmd, int isexe, int exe_on
                return xstrdup(path);
        path[strlen(path)-4] = '\0';
        if ((!exe_only || isexe) && access(path, F_OK) == 0)
-               return xstrdup(path);
+               if (!(GetFileAttributes(path) & FILE_ATTRIBUTE_DIRECTORY))
+                       return xstrdup(path);
        return NULL;
 }
 
index 5a3bcee29b7e39f52dcae40aeed611c01cec920e..8ffec51e73f49a54d82dd40f1e301e9c5479ffcf 100644 (file)
@@ -193,6 +193,17 @@ static inline unsigned int git_ntohl(unsigned int x)
 sig_handler_t mingw_signal(int sig, sig_handler_t handler);
 #define signal mingw_signal
 
+/*
+ * ANSI emulation wrappers
+ */
+
+int winansi_fputs(const char *str, FILE *stream);
+int winansi_printf(const char *format, ...) __attribute__((format (printf, 1, 2)));
+int winansi_fprintf(FILE *stream, const char *format, ...) __attribute__((format (printf, 2, 3)));
+#define fputs winansi_fputs
+#define printf(...) winansi_printf(__VA_ARGS__)
+#define fprintf(...) winansi_fprintf(__VA_ARGS__)
+
 /*
  * git specific compatibility
  */
diff --git a/compat/winansi.c b/compat/winansi.c
new file mode 100644 (file)
index 0000000..e2d96df
--- /dev/null
@@ -0,0 +1,345 @@
+/*
+ * Copyright 2008 Peter Harris <git@peter.is-a-geek.org>
+ */
+
+#include <windows.h>
+#include "../git-compat-util.h"
+
+/*
+ Functions to be wrapped:
+*/
+#undef printf
+#undef fprintf
+#undef fputs
+/* TODO: write */
+
+/*
+ ANSI codes used by git: m, K
+
+ This file is git-specific. Therefore, this file does not attempt
+ to implement any codes that are not used by git.
+
+ TODO: K
+*/
+
+static HANDLE console;
+static WORD plain_attr;
+static WORD attr;
+static int negative;
+
+static void init(void)
+{
+       CONSOLE_SCREEN_BUFFER_INFO sbi;
+
+       static int initialized = 0;
+       if (initialized)
+               return;
+
+       console = GetStdHandle(STD_OUTPUT_HANDLE);
+       if (console == INVALID_HANDLE_VALUE)
+               console = NULL;
+
+       if (!console)
+               return;
+
+       GetConsoleScreenBufferInfo(console, &sbi);
+       attr = plain_attr = sbi.wAttributes;
+       negative = 0;
+
+       initialized = 1;
+}
+
+
+#define FOREGROUND_ALL (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
+#define BACKGROUND_ALL (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)
+
+static void set_console_attr(void)
+{
+       WORD attributes = attr;
+       if (negative) {
+               attributes &= ~FOREGROUND_ALL;
+               attributes &= ~BACKGROUND_ALL;
+
+               /* This could probably use a bitmask
+                  instead of a series of ifs */
+               if (attr & FOREGROUND_RED)
+                       attributes |= BACKGROUND_RED;
+               if (attr & FOREGROUND_GREEN)
+                       attributes |= BACKGROUND_GREEN;
+               if (attr & FOREGROUND_BLUE)
+                       attributes |= BACKGROUND_BLUE;
+
+               if (attr & BACKGROUND_RED)
+                       attributes |= FOREGROUND_RED;
+               if (attr & BACKGROUND_GREEN)
+                       attributes |= FOREGROUND_GREEN;
+               if (attr & BACKGROUND_BLUE)
+                       attributes |= FOREGROUND_BLUE;
+       }
+       SetConsoleTextAttribute(console, attributes);
+}
+
+static const char *set_attr(const char *str)
+{
+       const char *func;
+       size_t len = strspn(str, "0123456789;");
+       func = str + len;
+
+       switch (*func) {
+       case 'm':
+               do {
+                       long val = strtol(str, (char **)&str, 10);
+                       switch (val) {
+                       case 0: /* reset */
+                               attr = plain_attr;
+                               negative = 0;
+                               break;
+                       case 1: /* bold */
+                               attr |= FOREGROUND_INTENSITY;
+                               break;
+                       case 2:  /* faint */
+                       case 22: /* normal */
+                               attr &= ~FOREGROUND_INTENSITY;
+                               break;
+                       case 3:  /* italic */
+                               /* Unsupported */
+                               break;
+                       case 4:  /* underline */
+                       case 21: /* double underline */
+                               /* Wikipedia says this flag does nothing */
+                               /* Furthermore, mingw doesn't define this flag
+                               attr |= COMMON_LVB_UNDERSCORE; */
+                               break;
+                       case 24: /* no underline */
+                               /* attr &= ~COMMON_LVB_UNDERSCORE; */
+                               break;
+                       case 5:  /* slow blink */
+                       case 6:  /* fast blink */
+                               /* We don't have blink, but we do have
+                                  background intensity */
+                               attr |= BACKGROUND_INTENSITY;
+                               break;
+                       case 25: /* no blink */
+                               attr &= ~BACKGROUND_INTENSITY;
+                               break;
+                       case 7:  /* negative */
+                               negative = 1;
+                               break;
+                       case 27: /* positive */
+                               negative = 0;
+                               break;
+                       case 8:  /* conceal */
+                       case 28: /* reveal */
+                               /* Unsupported */
+                               break;
+                       case 30: /* Black */
+                               attr &= ~FOREGROUND_ALL;
+                               break;
+                       case 31: /* Red */
+                               attr &= ~FOREGROUND_ALL;
+                               attr |= FOREGROUND_RED;
+                               break;
+                       case 32: /* Green */
+                               attr &= ~FOREGROUND_ALL;
+                               attr |= FOREGROUND_GREEN;
+                               break;
+                       case 33: /* Yellow */
+                               attr &= ~FOREGROUND_ALL;
+                               attr |= FOREGROUND_RED | FOREGROUND_GREEN;
+                               break;
+                       case 34: /* Blue */
+                               attr &= ~FOREGROUND_ALL;
+                               attr |= FOREGROUND_BLUE;
+                               break;
+                       case 35: /* Magenta */
+                               attr &= ~FOREGROUND_ALL;
+                               attr |= FOREGROUND_RED | FOREGROUND_BLUE;
+                               break;
+                       case 36: /* Cyan */
+                               attr &= ~FOREGROUND_ALL;
+                               attr |= FOREGROUND_GREEN | FOREGROUND_BLUE;
+                               break;
+                       case 37: /* White */
+                               attr |= FOREGROUND_RED |
+                                       FOREGROUND_GREEN |
+                                       FOREGROUND_BLUE;
+                               break;
+                       case 38: /* Unknown */
+                               break;
+                       case 39: /* reset */
+                               attr &= ~FOREGROUND_ALL;
+                               attr |= (plain_attr & FOREGROUND_ALL);
+                               break;
+                       case 40: /* Black */
+                               attr &= ~BACKGROUND_ALL;
+                               break;
+                       case 41: /* Red */
+                               attr &= ~BACKGROUND_ALL;
+                               attr |= BACKGROUND_RED;
+                               break;
+                       case 42: /* Green */
+                               attr &= ~BACKGROUND_ALL;
+                               attr |= BACKGROUND_GREEN;
+                               break;
+                       case 43: /* Yellow */
+                               attr &= ~BACKGROUND_ALL;
+                               attr |= BACKGROUND_RED | BACKGROUND_GREEN;
+                               break;
+                       case 44: /* Blue */
+                               attr &= ~BACKGROUND_ALL;
+                               attr |= BACKGROUND_BLUE;
+                               break;
+                       case 45: /* Magenta */
+                               attr &= ~BACKGROUND_ALL;
+                               attr |= BACKGROUND_RED | BACKGROUND_BLUE;
+                               break;
+                       case 46: /* Cyan */
+                               attr &= ~BACKGROUND_ALL;
+                               attr |= BACKGROUND_GREEN | BACKGROUND_BLUE;
+                               break;
+                       case 47: /* White */
+                               attr |= BACKGROUND_RED |
+                                       BACKGROUND_GREEN |
+                                       BACKGROUND_BLUE;
+                               break;
+                       case 48: /* Unknown */
+                               break;
+                       case 49: /* reset */
+                               attr &= ~BACKGROUND_ALL;
+                               attr |= (plain_attr & BACKGROUND_ALL);
+                               break;
+                       default:
+                               /* Unsupported code */
+                               break;
+                       }
+                       str++;
+               } while (*(str-1) == ';');
+
+               set_console_attr();
+               break;
+       case 'K':
+               /* TODO */
+               break;
+       default:
+               /* Unsupported code */
+               break;
+       }
+
+       return func + 1;
+}
+
+static int ansi_emulate(const char *str, FILE *stream)
+{
+       int rv = 0;
+       const char *pos = str;
+
+       while (*pos) {
+               pos = strstr(str, "\033[");
+               if (pos) {
+                       size_t len = pos - str;
+
+                       if (len) {
+                               size_t out_len = fwrite(str, 1, len, stream);
+                               rv += out_len;
+                               if (out_len < len)
+                                       return rv;
+                       }
+
+                       str = pos + 2;
+                       rv += 2;
+
+                       fflush(stream);
+
+                       pos = set_attr(str);
+                       rv += pos - str;
+                       str = pos;
+               } else {
+                       rv += strlen(str);
+                       fputs(str, stream);
+                       return rv;
+               }
+       }
+       return rv;
+}
+
+int winansi_fputs(const char *str, FILE *stream)
+{
+       int rv;
+
+       if (!isatty(fileno(stream)))
+               return fputs(str, stream);
+
+       init();
+
+       if (!console)
+               return fputs(str, stream);
+
+       rv = ansi_emulate(str, stream);
+
+       if (rv >= 0)
+               return 0;
+       else
+               return EOF;
+}
+
+static int winansi_vfprintf(FILE *stream, const char *format, va_list list)
+{
+       int len, rv;
+       char small_buf[256];
+       char *buf = small_buf;
+       va_list cp;
+
+       if (!isatty(fileno(stream)))
+               goto abort;
+
+       init();
+
+       if (!console)
+               goto abort;
+
+       va_copy(cp, list);
+       len = vsnprintf(small_buf, sizeof(small_buf), format, cp);
+       va_end(cp);
+
+       if (len > sizeof(small_buf) - 1) {
+               buf = malloc(len + 1);
+               if (!buf)
+                       goto abort;
+
+               len = vsnprintf(buf, len + 1, format, list);
+       }
+
+       rv = ansi_emulate(buf, stream);
+
+       if (buf != small_buf)
+               free(buf);
+       return rv;
+
+abort:
+       rv = vfprintf(stream, format, list);
+       return rv;
+}
+
+int winansi_fprintf(FILE *stream, const char *format, ...)
+{
+       va_list list;
+       int rv;
+
+       va_start(list, format);
+       rv = winansi_vfprintf(stream, format, list);
+       va_end(list);
+
+       return rv;
+}
+
+int winansi_printf(const char *format, ...)
+{
+       va_list list;
+       int rv;
+
+       va_start(list, format);
+       rv = winansi_vfprintf(stdout, format, list);
+       va_end(list);
+
+       return rv;
+}
index 8026ccff4a459a75148740382646f7fe10b00255..e9588eec33ba5b64d186ff048bb040c18c57e6bc 100755 (executable)
@@ -5,8 +5,8 @@
 
 OPTIONS_KEEPDASHDASH=
 OPTIONS_SPEC="\
-git-merge [options] <remote>...
-git-merge [options] <msg> HEAD <remote>
+git merge [options] <remote>...
+git merge [options] <msg> HEAD <remote>
 --
 stat                 show a diffstat at the end of the merge
 n                    don't show a diffstat at the end of the merge
index ce3a6f58f3c5c6bb88617510422c4053e0d545a2..7df41a6a49359f31991d383f73b8d9cb11e992a9 100644 (file)
--- a/daemon.c
+++ b/daemon.c
@@ -18,7 +18,7 @@ static int verbose;
 static int reuseaddr;
 
 static const char daemon_usage[] =
-"git-daemon [--verbose] [--syslog] [--export-all]\n"
+"git daemon [--verbose] [--syslog] [--export-all]\n"
 "           [--timeout=n] [--init-timeout=n] [--strict-paths]\n"
 "           [--base-path=path] [--base-path-relaxed]\n"
 "           [--user-path | --user-path=path]\n"
index b17722d66a7008b822125bb96ab1b7921e8b627b..e7eaff9a68ccbcc692522c9956f0dae9af45f3f1 100644 (file)
@@ -171,7 +171,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
                        if (silent_on_removed)
                                continue;
                        diff_addremove(&revs->diffopt, '-', ce->ce_mode,
-                                      ce->sha1, ce->name, NULL);
+                                      ce->sha1, ce->name);
                        continue;
                }
                changed = ce_match_stat(ce, &st, ce_option);
@@ -184,7 +184,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
                newmode = ce_mode_from_stat(ce, st.st_mode);
                diff_change(&revs->diffopt, oldmode, newmode,
                            ce->sha1, (changed ? null_sha1 : ce->sha1),
-                           ce->name, NULL);
+                           ce->name);
 
        }
        diffcore_std(&revs->diffopt);
@@ -208,7 +208,7 @@ static void diff_index_show_file(struct rev_info *revs,
                                 const unsigned char *sha1, unsigned int mode)
 {
        diff_addremove(&revs->diffopt, prefix[0], mode,
-                      sha1, ce->name, NULL);
+                      sha1, ce->name);
 }
 
 static int get_stat_data(struct cache_entry *ce,
@@ -312,7 +312,7 @@ static int show_modified(struct oneway_unpack_data *cbdata,
                return 0;
 
        diff_change(&revs->diffopt, oldmode, mode,
-                   old->sha1, sha1, old->name, NULL);
+                   old->sha1, sha1, old->name);
        return 0;
 }
 
diff --git a/diff.c b/diff.c
index 6a39b393f3e276dd0e0352b5c05eec6989940854..a07812c5c75f1f579295df392efed27f6a5f6fc1 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -3412,9 +3412,8 @@ int diff_result_code(struct diff_options *opt, int status)
 void diff_addremove(struct diff_options *options,
                    int addremove, unsigned mode,
                    const unsigned char *sha1,
-                   const char *base, const char *path)
+                   const char *concatpath)
 {
-       char concatpath[PATH_MAX];
        struct diff_filespec *one, *two;
 
        if (DIFF_OPT_TST(options, IGNORE_SUBMODULES) && S_ISGITLINK(mode))
@@ -3436,9 +3435,6 @@ void diff_addremove(struct diff_options *options,
                addremove = (addremove == '+' ? '-' :
                             addremove == '-' ? '+' : addremove);
 
-       if (!path) path = "";
-       sprintf(concatpath, "%s%s", base, path);
-
        if (options->prefix &&
            strncmp(concatpath, options->prefix, options->prefix_length))
                return;
@@ -3459,9 +3455,8 @@ void diff_change(struct diff_options *options,
                 unsigned old_mode, unsigned new_mode,
                 const unsigned char *old_sha1,
                 const unsigned char *new_sha1,
-                const char *base, const char *path)
+                const char *concatpath)
 {
-       char concatpath[PATH_MAX];
        struct diff_filespec *one, *two;
 
        if (DIFF_OPT_TST(options, IGNORE_SUBMODULES) && S_ISGITLINK(old_mode)
@@ -3474,8 +3469,6 @@ void diff_change(struct diff_options *options,
                tmp = old_mode; old_mode = new_mode; new_mode = tmp;
                tmp_c = old_sha1; old_sha1 = new_sha1; new_sha1 = tmp_c;
        }
-       if (!path) path = "";
-       sprintf(concatpath, "%s%s", base, path);
 
        if (options->prefix &&
            strncmp(concatpath, options->prefix, options->prefix_length))
diff --git a/diff.h b/diff.h
index 5dc0cb595b64868ca8b8e26e5311d2df102c89e0..50fb5ddb0bec02b0cd5498d6ecc37d44bf874476 100644 (file)
--- a/diff.h
+++ b/diff.h
@@ -14,12 +14,12 @@ typedef void (*change_fn_t)(struct diff_options *options,
                 unsigned old_mode, unsigned new_mode,
                 const unsigned char *old_sha1,
                 const unsigned char *new_sha1,
-                const char *base, const char *path);
+                const char *fullpath);
 
 typedef void (*add_remove_fn_t)(struct diff_options *options,
                    int addremove, unsigned mode,
                    const unsigned char *sha1,
-                   const char *base, const char *path);
+                   const char *fullpath);
 
 typedef void (*diff_format_fn_t)(struct diff_queue_struct *q,
                struct diff_options *options, void *data);
@@ -164,14 +164,13 @@ extern void diff_addremove(struct diff_options *,
                           int addremove,
                           unsigned mode,
                           const unsigned char *sha1,
-                          const char *base,
-                          const char *path);
+                          const char *fullpath);
 
 extern void diff_change(struct diff_options *,
                        unsigned mode1, unsigned mode2,
                        const unsigned char *sha1,
                        const unsigned char *sha2,
-                       const char *base, const char *path);
+                       const char *fullpath);
 
 extern void diff_unmerge(struct diff_options *,
                         const char *path,
index e72b28679410155cb43968d315f02588e89fd5f1..7089e6f9e6c5fa9142f468e54afe7d33a6d2eec7 100644 (file)
@@ -1868,6 +1868,7 @@ static void file_change_m(struct branch *b)
        case S_IFREG | 0644:
        case S_IFREG | 0755:
        case S_IFLNK:
+       case S_IFGITLINK:
        case 0644:
        case 0755:
                /* ok */
@@ -1900,7 +1901,20 @@ static void file_change_m(struct branch *b)
                p = uq.buf;
        }
 
-       if (inline_data) {
+       if (S_ISGITLINK(mode)) {
+               if (inline_data)
+                       die("Git links cannot be specified 'inline': %s",
+                               command_buf.buf);
+               else if (oe) {
+                       if (oe->type != OBJ_COMMIT)
+                               die("Not a commit (actually a %s): %s",
+                                       typename(oe->type), command_buf.buf);
+               }
+               /*
+                * Accept the sha1 without checking; it expected to be in
+                * another repository.
+                */
+       } else if (inline_data) {
                static struct strbuf buf = STRBUF_INIT;
 
                if (p != uq.buf) {
@@ -2374,7 +2388,7 @@ static int git_pack_config(const char *k, const char *v, void *cb)
 }
 
 static const char fast_import_usage[] =
-"git-fast-import [--date-format=f] [--max-pack-size=n] [--depth=n] [--active-branches=n] [--export-marks=marks.file]";
+"git fast-import [--date-format=f] [--max-pack-size=n] [--depth=n] [--active-branches=n] [--export-marks=marks.file]";
 
 int main(int argc, const char **argv)
 {
index 49e861d2acb7fce8fde14f304d9cd9d2025656f6..63dfa4c475ae3632fc5cfd093d949a41683a5458 100755 (executable)
@@ -1,16 +1,16 @@
 #!/bin/sh
 while [ "$1" ]
 do
-       old="$1"
-       new=$(echo "$1" | sed 's/git-/git /')
-       echo "Converting '$old' to '$new'"
-       git ls-files '*.sh' | while read file
-       do
-               sed "s/\\<$old\\>/$new/g" < $file > $file.new
-               chmod --reference=$file $file.new
-               mv $file.new $file
-       done
+       if [ "$1" != "git-sh-setup" -a "$1" != "git-parse-remote" -a "$1" != "git-svn" ]; then
+               old="$1"
+               new=$(echo "$1" | sed 's/git-/git /')
+               echo "Converting '$old' to '$new'"
+               sed -i "s/\\<$old\\>/$new/g" $(git ls-files '*.sh')
+       fi
        shift
 done
+
+sed -i 's/git merge-one-file/git-merge-one-file/g
+s/git rebase-todo/git-rebase-todo/g' $(git ls-files '*.sh')
 git update-index --refresh >& /dev/null
 exit 0
index cc8787b460e601889fd90c5dba2055e9eb85bc22..60aaa4a583d3e2466ea788d7047a9fc8252b1fe6 100755 (executable)
--- a/git-am.sh
+++ b/git-am.sh
@@ -5,9 +5,9 @@
 SUBDIRECTORY_OK=Yes
 OPTIONS_KEEPDASHDASH=
 OPTIONS_SPEC="\
-git-am [options] [<mbox>|<Maildir>...]
-git-am [options] --resolved
-git-am [options] --skip
+git am [options] [<mbox>|<Maildir>...]
+git am [options] --resolved
+git am [options] --skip
 --
 d,dotest=       (removed -- do not use)
 i,interactive   run interactively
@@ -22,6 +22,7 @@ p=              pass it through git-apply
 resolvemsg=     override error message when patch failure occurs
 r,resolved      to be used after a patch failure
 skip            skip the current patch
+abort           restore the original branch and abort the patching operation.
 rebasing        (internal use for git-rebase)"
 
 . git-sh-setup
@@ -54,6 +55,7 @@ stop_here_user_resolve () {
     fi
     echo "When you have resolved this problem run \"$cmdline --resolved\"."
     echo "If you would prefer to skip this patch, instead run \"$cmdline --skip\"."
+    echo "To restore the original branch and stop patching run \"$cmdline --abort\"."
 
     stop_here $1
 }
@@ -120,7 +122,7 @@ It does not apply to blobs recorded in its index."
 
 prec=4
 dotest="$GIT_DIR/rebase"
-sign= utf8=t keep= skip= interactive= resolved= binary= rebasing=
+sign= utf8=t keep= skip= interactive= resolved= binary= rebasing= abort=
 resolvemsg= resume=
 git_apply_opt=
 
@@ -145,6 +147,8 @@ do
                resolved=t ;;
        --skip)
                skip=t ;;
+       --abort)
+               abort=t ;;
        --rebasing)
                rebasing=t threeway=t keep=t binary=t ;;
        -d|--dotest)
@@ -177,7 +181,7 @@ fi
 
 if test -d "$dotest"
 then
-       case "$#,$skip$resolved" in
+       case "$#,$skip$resolved$abort" in
        0,*t*)
                # Explicit resume command and we do not have file, so
                # we are happy.
@@ -197,9 +201,18 @@ then
        esac ||
        die "previous rebase directory $dotest still exists but mbox given."
        resume=yes
+
+       case "$abort" in
+       t)
+               git rerere clear
+               git read-tree --reset -u HEAD ORIG_HEAD
+               git reset ORIG_HEAD
+               rm -fr "$dotest"
+               exit ;;
+       esac
 else
-       # Make sure we are not given --skip nor --resolved
-       test ",$skip,$resolved," = ,,, ||
+       # Make sure we are not given --skip, --resolved, nor --abort
+       test "$skip$resolved$abort" = "" ||
                die "Resolve operation not in progress, we are not resuming."
 
        # Start afresh.
index 9a7a90640fa02eef50c522d4276616bae006e6fe..98f3ede566a6cb0c902ce84795f7de8f8afbe633 100755 (executable)
@@ -9,7 +9,7 @@
 
 =head1 Invocation
 
-    git-archimport [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ]
+    git archimport [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ]
        [ -D depth] [ -t tempdir ] <archive>/<branch> [ <archive>/<branch> ]
 
 Imports a project from one or more Arch repositories. It will follow branches
@@ -74,7 +74,7 @@ our($opt_h,$opt_f,$opt_v,$opt_T,$opt_t,$opt_D,$opt_a,$opt_o);
 
 sub usage() {
     print STDERR <<END;
-Usage: ${\basename $0}     # fetch/update GIT from Arch
+Usage: git archimport     # fetch/update GIT from Arch
        [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ] [ -D depth ] [ -t tempdir ]
        repository/arch-branch [ repository/arch-branch] ...
 END
index 991b2ef37e5121d89f40d1b10964bf5d5beed40b..3cac20db79e1e408a321b0e9d272501985a3c49b 100755 (executable)
@@ -149,7 +149,7 @@ bisect_start() {
        echo "$start_head" >"$GIT_DIR/BISECT_START" &&
        sq "$@" >"$GIT_DIR/BISECT_NAMES" &&
        eval "$eval" &&
-       echo "git-bisect start$orig_args" >>"$GIT_DIR/BISECT_LOG" || exit
+       echo "git bisect start$orig_args" >>"$GIT_DIR/BISECT_LOG" || exit
        #
        # Check if we can proceed to the next bisect state.
        #
@@ -169,7 +169,7 @@ bisect_write() {
        esac
        git update-ref "refs/bisect/$tag" "$rev" || exit
        echo "# $state: $(git show-branch $rev)" >>"$GIT_DIR/BISECT_LOG"
-       test -n "$nolog" || echo "git-bisect $state $rev" >>"$GIT_DIR/BISECT_LOG"
+       test -n "$nolog" || echo "git bisect $state $rev" >>"$GIT_DIR/BISECT_LOG"
 }
 
 bisect_state() {
@@ -426,9 +426,13 @@ bisect_clean_state() {
 bisect_replay () {
        test -r "$1" || die "cannot read $1 for replaying"
        bisect_reset
-       while read bisect command rev
+       while read git bisect command rev
        do
-               test "$bisect" = "git-bisect" || continue
+               test "$git $bisect" = "git bisect" -o "$git" = "git-bisect" || continue
+               if test "$git" = "git-bisect"; then
+                       rev="$command"
+                       command="$bisect"
+               fi
                case "$command" in
                start)
                        cmd="bisect_start $rev"
index c6c70e9eba37d14b353e43444c17d815403e66fb..6d9f0ef0f989133422cf8c0302e63dab15a999d5 100755 (executable)
@@ -370,7 +370,7 @@ sleep(1);
 
 sub usage {
        print STDERR <<END;
-Usage: GIT_DIR=/path/to/.git ${\basename $0} [-h] [-p] [-v] [-c] [-f] [-u] [-w cvsworkdir] [-m msgprefix] [ parent ] commit
+Usage: GIT_DIR=/path/to/.git git cvsexportcommit [-h] [-p] [-v] [-c] [-f] [-u] [-w cvsworkdir] [-m msgprefix] [ parent ] commit
 END
        exit(1);
 }
index cacbfc0259fd1ae353117d93e345cd8c4dd41188..e2664ef01308fd0fb65d47b25e0ae73a65aa6262 100755 (executable)
@@ -36,7 +36,7 @@ sub usage(;$) {
        my $msg = shift;
        print(STDERR "Error: $msg\n") if $msg;
        print STDERR <<END;
-Usage: ${\basename $0}     # fetch/update GIT from CVS
+Usage: git cvsimport     # fetch/update GIT from CVS
        [-o branch-for-HEAD] [-h] [-v] [-d CVSROOT] [-A author-conv-file]
        [-p opts-for-cvsps] [-P file] [-C GIT_repository] [-z fuzz] [-i] [-k]
        [-u] [-s subst] [-a] [-m] [-M regex] [-S regex] [-L commitlimit]
index 920bbe15a3bbc7768d47a2adbc84aa81264e2226..b0a805c688f59af29e1f25b514d73f3991285dee 100755 (executable)
@@ -101,7 +101,7 @@ my $work =
 $log->info("--------------- STARTING -----------------");
 
 my $usage =
-    "Usage: git-cvsserver [options] [pserver|server] [<directory> ...]\n".
+    "Usage: git cvsserver [options] [pserver|server] [<directory> ...]\n".
     "    --base-path <path>  : Prepend to requested CVSROOT\n".
     "    --strict-paths      : Don't allow recursing into subdirectories\n".
     "    --export-all        : Don't check for gitcvs.enabled in config\n".
@@ -801,6 +801,18 @@ sub req_co
 
     argsplit("co");
 
+    # Provide list of modules, if -c was used.
+    if (exists $state->{opt}{c}) {
+        my $showref = `git show-ref --heads`;
+        for my $line (split '\n', $showref) {
+            if ( $line =~ m% refs/heads/(.*)$% ) {
+                print "M $1\t$1\n";
+            }
+        }
+        print "ok\n";
+        return 1;
+    }
+
     my $module = $state->{args}[0];
     $state->{module} = $module;
     my $checkout_path = $module;
@@ -947,21 +959,15 @@ sub req_update
     # projects (heads in this case) to checkout.
     #
     if ($state->{module} eq '') {
-       my $heads_dir = $state->{CVSROOT} . '/refs/heads';
-       if (!opendir HEADS, $heads_dir) {
-           print "E [server aborted]: Failed to open directory, "
-             . "$heads_dir: $!\nerror\n";
-           return 0;
-       }
+        my $showref = `git show-ref --heads`;
         print "E cvs update: Updating .\n";
-       while (my $head = readdir(HEADS)) {
-           if (-f $state->{CVSROOT} . '/refs/heads/' . $head) {
-               print "E cvs update: New directory `$head'\n";
-           }
-       }
-       closedir HEADS;
-       print "ok\n";
-       return 1;
+        for my $line (split '\n', $showref) {
+            if ( $line =~ m% refs/heads/(.*)$% ) {
+                print "E cvs update: New directory `$1'\n";
+            }
+        }
+        print "ok\n";
+        return 1;
     }
 
 
@@ -1884,7 +1890,7 @@ sub req_annotate
     }
 
     # done; get out of the tempdir
-    cleanupWorkDir();
+    cleanupWorkTree();
 
     print "ok\n";
 
index af0fde538cefe8531031629cf78847da5eac4fa5..0843372b57371b62cd68f2818f634209f55d5395 100755 (executable)
@@ -6,7 +6,7 @@
 PERL='@@PERL@@'
 OPTIONS_KEEPDASHDASH=
 OPTIONS_SPEC="\
-git-instaweb [options] (--start | --stop | --restart)
+git instaweb [options] (--start | --stop | --restart)
 --
 l,local        only bind on 127.0.0.1
 p,port=        the port to bind to
index 809e537a4d81233966aad23df11c13931d6250c1..6afd4e2f4e5859728d748fe51f68e5bfcb934488 100755 (executable)
@@ -121,7 +121,7 @@ test true = "$rebase" && {
                "refs/remotes/$origin/$reflist" 2>/dev/null)"
 }
 orig_head=$(git rev-parse --verify HEAD 2>/dev/null)
-git-fetch --update-head-ok "$@" || exit 1
+git fetch --update-head-ok "$@" || exit 1
 
 curr_head=$(git rev-parse --verify HEAD 2>/dev/null)
 if test "$curr_head" != "$orig_head"
index d1efa1d7419c23b65af1dccf4b8a00ed0e94c79c..c9aecfd9132f2cb199add497d6c6ab2ebb79fdba 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 OPTIONS_KEEPDASHDASH=
 OPTIONS_SPEC="\
-git-quiltimport [options]
+git quiltimport [options]
 --
 n,dry-run     dry run
 author=       author name and email address for patches without any
index da79a2456814e4038a42238e0865d8950c14dff0..e63a864c7b1b5057737fda1e52c88d1d5e40322f 100755 (executable)
@@ -174,6 +174,8 @@ pick_one_preserving_merges () {
                                new_parents="$new_parents $new_p"
                                ;;
                        esac
+               else
+                       new_parents="$new_parents $p"
                fi
        done
        case $fast_forward in
index 56cf6f0316ddd000221ecaf343f7fc58c8636590..6ef5754814babdb908d794ea030aceca6597b190 100755 (executable)
@@ -376,8 +376,7 @@ fi
 
 # Detach HEAD and reset the tree
 echo "First, rewinding head to replay your work on top of it..."
-git checkout "$onto^0" >/dev/null 2>&1 ||
-       die "could not detach HEAD"
+git checkout -q "$onto^0" || die "could not detach HEAD"
 git update-ref ORIG_HEAD $branch
 
 # If the $onto is a proper descendant of the tip of the branch, then
index 15fb932021e03e2b7b856b3a2285021be2ebac61..937c69a74858a8a3c63bb41a23705b579df1b3a3 100755 (executable)
@@ -163,7 +163,7 @@ sub link_two_files($$) {
 
 
 sub usage() {
-       print("Usage: $0 [--safe] <dir> [<dir> ...] <master_dir> \n");
+       print("Usage: git relink [--safe] <dir> [<dir> ...] <master_dir> \n");
        print("All directories should contain a .git/objects/ subdirectory.\n");
        print("Options\n");
        print("\t--safe\t" .
index 8c3bc134add87f38a764f24c63b9e09f562ad6b1..683960b04d6b743e687b2eb640d2b0e00ccfd313 100755 (executable)
@@ -5,7 +5,7 @@
 
 OPTIONS_KEEPDASHDASH=
 OPTIONS_SPEC="\
-git-repack [options]
+git repack [options]
 --
 a               pack everything in a single pack
 A               same as -a, and turn unreachable objects loose
index 6adb66947279e290d90be7da154f49e696894528..2e4a44ad29c923eb48c3136e768870e384df06c2 100755 (executable)
@@ -38,7 +38,7 @@ package main;
 
 sub usage {
        print <<EOT;
-git-send-email [options] <file | directory>...
+git send-email [options] <file | directory>...
 Options:
    --from         Specify the "From:" line of the email to be sent.
 
index 9cceb21a82881b5f12e85769fcbfeb2146631d3c..dbdf209ec0e7d6468c199d1905c3e7788a9cd246 100755 (executable)
@@ -32,15 +32,16 @@ if test -n "$OPTIONS_SPEC"; then
                echo exit $?
        )"
 else
+       dashless=$(basename "$0" | sed -e 's/-/ /')
        usage() {
-               die "Usage: $0 $USAGE"
+               die "Usage: $dashless $USAGE"
        }
 
        if [ -z "$LONG_USAGE" ]
        then
-               LONG_USAGE="Usage: $0 $USAGE"
+               LONG_USAGE="Usage: $dashless $USAGE"
        else
-               LONG_USAGE="Usage: $0 $USAGE
+               LONG_USAGE="Usage: $dashless $USAGE
 
 $LONG_USAGE"
        fi
index 3750e47c202ebdcb25e657eecd69ef5252d45221..2e0e55242ff089cda3c87ae57f7c776c13508a56 100755 (executable)
@@ -261,7 +261,7 @@ sub usage {
        my $fd = $exit ? \*STDERR : \*STDOUT;
        print $fd <<"";
 git-svn - bidirectional operations between a single Subversion tree and git
-Usage: $0 <command> [options] [arguments]\n
+Usage: git svn <command> [options] [arguments]\n
 
        print $fd "Available commands:\n" unless $cmd;
 
@@ -1226,7 +1226,7 @@ sub linearize_history {
 
 sub find_file_type_and_diff_status {
        my ($path) = @_;
-       return ('dir', '') if $path eq '.';
+       return ('dir', '') if $path eq '';
 
        my $diff_output =
            command_oneline(qw(diff --cached --name-status --), $path) || "";
index 48d522368454d2663d5cc075045d87f120058ced..46c06a9552dac5475afc607c3fe2bf00801eb055 100644 (file)
@@ -52,7 +52,7 @@ static void hash_stdin_paths(const char *type, int write_objects)
 }
 
 static const char hash_object_usage[] =
-"git-hash-object [ [-t <type>] [-w] [--stdin] <file>... | --stdin-paths < <list-of-paths> ]";
+"git hash-object [ [-t <type>] [-w] [--stdin] <file>... | --stdin-paths < <list-of-paths> ]";
 
 int main(int argc, char **argv)
 {
diff --git a/help.c b/help.c
index 52d39b88a36e92b00828fdb8c8d056f9b79a37e0..bfc84aed10d49b1eb641d920a102e94d2e905fda 100644 (file)
--- a/help.c
+++ b/help.c
@@ -40,7 +40,7 @@ static struct option builtin_help_options[] = {
 };
 
 static const char * const builtin_help_usage[] = {
-       "git-help [--all] [--man|--web|--info] [command]",
+       "git help [--all] [--man|--web|--info] [command]",
        NULL
 };
 
index 2cd068a6f1ef0199cc27a1564678c91b66237a9b..68052888570af7d09535db8831b8cf3ef2881589 100644 (file)
@@ -14,7 +14,7 @@
 #include <expat.h>
 
 static const char http_push_usage[] =
-"git-http-push [--all] [--dry-run] [--force] [--verbose] <remote> [<head>...]\n";
+"git http-push [--all] [--dry-run] [--force] [--verbose] <remote> [<head>...]\n";
 
 #ifndef XML_STATUS_OK
 enum XML_Status {
index 51c18f2685aa1bdb7e4ed471d0ec5d31c6684fda..9dc6b27b457a2979a95018679a0b885e6fb62d9a 100644 (file)
@@ -442,6 +442,8 @@ static int setup_index(struct walker *walker, struct alt_base *repo, unsigned ch
                return -1;
 
        new_pack = parse_pack_index(sha1);
+       if (!new_pack)
+               return -1; /* parse_pack_index() already issued error message */
        new_pack->next = repo->packs;
        repo->packs = new_pack;
        return 0;
index 25db5db24b239409657510e8c2eeb3845b374bbf..ac20a46d1594ee1350b11d001f92bf0a8d887890 100644 (file)
@@ -10,7 +10,7 @@
 #include "fsck.h"
 
 static const char index_pack_usage[] =
-"git-index-pack [-v] [-o <index-file>] [{ ---keep | --keep=<msg> }] [--strict] { <pack-file> | --stdin [--fix-thin] [<pack-file>] }";
+"git index-pack [-v] [-o <index-file>] [{ ---keep | --keep=<msg> }] [--strict] { <pack-file> | --stdin [--fix-thin] [<pack-file>] }";
 
 struct object_entry
 {
@@ -26,6 +26,14 @@ union delta_base {
        off_t offset;
 };
 
+struct base_data {
+       struct base_data *base;
+       struct base_data *child;
+       struct object_entry *obj;
+       void *data;
+       unsigned long size;
+};
+
 /*
  * Even if sizeof(union delta_base) == 24 on 64-bit archs, we really want
  * to memcmp() only the first 20 bytes.
@@ -43,6 +51,8 @@ struct delta_entry
 
 static struct object_entry *objects;
 static struct delta_entry *deltas;
+static struct base_data *base_cache;
+static size_t base_cache_used;
 static int nr_objects;
 static int nr_deltas;
 static int nr_resolved_deltas;
@@ -211,6 +221,46 @@ static void bad_object(unsigned long offset, const char *format, ...)
        die("pack has bad object at offset %lu: %s", offset, buf);
 }
 
+static void prune_base_data(struct base_data *retain)
+{
+       struct base_data *b = base_cache;
+       for (b = base_cache;
+            base_cache_used > delta_base_cache_limit && b;
+            b = b->child) {
+               if (b->data && b != retain) {
+                       free(b->data);
+                       b->data = NULL;
+                       base_cache_used -= b->size;
+               }
+       }
+}
+
+static void link_base_data(struct base_data *base, struct base_data *c)
+{
+       if (base)
+               base->child = c;
+       else
+               base_cache = c;
+
+       c->base = base;
+       c->child = NULL;
+       base_cache_used += c->size;
+       prune_base_data(c);
+}
+
+static void unlink_base_data(struct base_data *c)
+{
+       struct base_data *base = c->base;
+       if (base)
+               base->child = NULL;
+       else
+               base_cache = NULL;
+       if (c->data) {
+               free(c->data);
+               base_cache_used -= c->size;
+       }
+}
+
 static void *unpack_entry_data(unsigned long offset, unsigned long size)
 {
        z_stream stream;
@@ -426,33 +476,60 @@ static void sha1_object(const void *data, unsigned long size,
        }
 }
 
-static void resolve_delta(struct object_entry *delta_obj, void *base_data,
-                         unsigned long base_size, enum object_type type)
+static void *get_base_data(struct base_data *c)
+{
+       if (!c->data) {
+               struct object_entry *obj = c->obj;
+
+               if (obj->type == OBJ_REF_DELTA || obj->type == OBJ_OFS_DELTA) {
+                       void *base = get_base_data(c->base);
+                       void *raw = get_data_from_pack(obj);
+                       c->data = patch_delta(
+                               base, c->base->size,
+                               raw, obj->size,
+                               &c->size);
+                       free(raw);
+                       if (!c->data)
+                               bad_object(obj->idx.offset, "failed to apply delta");
+               } else
+                       c->data = get_data_from_pack(obj);
+
+               base_cache_used += c->size;
+               prune_base_data(c);
+       }
+       return c->data;
+}
+
+static void resolve_delta(struct object_entry *delta_obj,
+                         struct base_data *base_obj, enum object_type type)
 {
        void *delta_data;
        unsigned long delta_size;
-       void *result;
-       unsigned long result_size;
        union delta_base delta_base;
        int j, first, last;
+       struct base_data result;
 
        delta_obj->real_type = type;
        delta_data = get_data_from_pack(delta_obj);
        delta_size = delta_obj->size;
-       result = patch_delta(base_data, base_size, delta_data, delta_size,
-                            &result_size);
+       result.data = patch_delta(get_base_data(base_obj), base_obj->size,
+                            delta_data, delta_size,
+                            &result.size);
        free(delta_data);
-       if (!result)
+       if (!result.data)
                bad_object(delta_obj->idx.offset, "failed to apply delta");
-       sha1_object(result, result_size, type, delta_obj->idx.sha1);
+       sha1_object(result.data, result.size, type, delta_obj->idx.sha1);
        nr_resolved_deltas++;
 
+       result.obj = delta_obj;
+       link_base_data(base_obj, &result);
+
        hashcpy(delta_base.sha1, delta_obj->idx.sha1);
        if (!find_delta_children(&delta_base, &first, &last)) {
                for (j = first; j <= last; j++) {
                        struct object_entry *child = objects + deltas[j].obj_no;
                        if (child->real_type == OBJ_REF_DELTA)
-                               resolve_delta(child, result, result_size, type);
+                               resolve_delta(child, &result, type);
                }
        }
 
@@ -462,11 +539,11 @@ static void resolve_delta(struct object_entry *delta_obj, void *base_data,
                for (j = first; j <= last; j++) {
                        struct object_entry *child = objects + deltas[j].obj_no;
                        if (child->real_type == OBJ_OFS_DELTA)
-                               resolve_delta(child, result, result_size, type);
+                               resolve_delta(child, &result, type);
                }
        }
 
-       free(result);
+       unlink_base_data(&result);
 }
 
 static int compare_delta_entry(const void *a, const void *b)
@@ -481,7 +558,6 @@ static void parse_pack_objects(unsigned char *sha1)
 {
        int i;
        struct delta_entry *delta = deltas;
-       void *data;
        struct stat st;
 
        /*
@@ -496,7 +572,7 @@ static void parse_pack_objects(unsigned char *sha1)
                                nr_objects);
        for (i = 0; i < nr_objects; i++) {
                struct object_entry *obj = &objects[i];
-               data = unpack_raw_entry(obj, &delta->base);
+               void *data = unpack_raw_entry(obj, &delta->base);
                obj->real_type = obj->type;
                if (obj->type == OBJ_REF_DELTA || obj->type == OBJ_OFS_DELTA) {
                        nr_deltas++;
@@ -545,6 +621,7 @@ static void parse_pack_objects(unsigned char *sha1)
                struct object_entry *obj = &objects[i];
                union delta_base base;
                int j, ref, ref_first, ref_last, ofs, ofs_first, ofs_last;
+               struct base_data base_obj;
 
                if (obj->type == OBJ_REF_DELTA || obj->type == OBJ_OFS_DELTA)
                        continue;
@@ -555,22 +632,24 @@ static void parse_pack_objects(unsigned char *sha1)
                ofs = !find_delta_children(&base, &ofs_first, &ofs_last);
                if (!ref && !ofs)
                        continue;
-               data = get_data_from_pack(obj);
+               base_obj.data = get_data_from_pack(obj);
+               base_obj.size = obj->size;
+               base_obj.obj = obj;
+               link_base_data(NULL, &base_obj);
+
                if (ref)
                        for (j = ref_first; j <= ref_last; j++) {
                                struct object_entry *child = objects + deltas[j].obj_no;
                                if (child->real_type == OBJ_REF_DELTA)
-                                       resolve_delta(child, data,
-                                                     obj->size, obj->type);
+                                       resolve_delta(child, &base_obj, obj->type);
                        }
                if (ofs)
                        for (j = ofs_first; j <= ofs_last; j++) {
                                struct object_entry *child = objects + deltas[j].obj_no;
                                if (child->real_type == OBJ_OFS_DELTA)
-                                       resolve_delta(child, data,
-                                                     obj->size, obj->type);
+                                       resolve_delta(child, &base_obj, obj->type);
                        }
-               free(data);
+               unlink_base_data(&base_obj);
                display_progress(progress, nr_resolved_deltas);
        }
 }
@@ -601,7 +680,8 @@ static int write_compressed(int fd, void *in, unsigned int size, uint32_t *obj_c
        return size;
 }
 
-static void append_obj_to_pack(const unsigned char *sha1, void *buf,
+static struct object_entry *append_obj_to_pack(
+                              const unsigned char *sha1, void *buf,
                               unsigned long size, enum object_type type)
 {
        struct object_entry *obj = &objects[nr_objects++];
@@ -622,6 +702,7 @@ static void append_obj_to_pack(const unsigned char *sha1, void *buf,
        obj[1].idx.offset = obj[0].idx.offset + n;
        obj[1].idx.offset += write_compressed(output_fd, buf, size, &obj[0].idx.crc32);
        hashcpy(obj->idx.sha1, sha1);
+       return obj;
 }
 
 static int delta_pos_compare(const void *_a, const void *_b)
@@ -656,28 +737,31 @@ static void fix_unresolved_deltas(int nr_unresolved)
 
        for (i = 0; i < n; i++) {
                struct delta_entry *d = sorted_by_pos[i];
-               void *data;
-               unsigned long size;
                enum object_type type;
                int j, first, last;
+               struct base_data base_obj;
 
                if (objects[d->obj_no].real_type != OBJ_REF_DELTA)
                        continue;
-               data = read_sha1_file(d->base.sha1, &type, &size);
-               if (!data)
+               base_obj.data = read_sha1_file(d->base.sha1, &type, &base_obj.size);
+               if (!base_obj.data)
                        continue;
 
+               if (check_sha1_signature(d->base.sha1, base_obj.data,
+                               base_obj.size, typename(type)))
+                       die("local object %s is corrupt", sha1_to_hex(d->base.sha1));
+               base_obj.obj = append_obj_to_pack(d->base.sha1, base_obj.data,
+                       base_obj.size, type);
+               link_base_data(NULL, &base_obj);
+
                find_delta_children(&d->base, &first, &last);
                for (j = first; j <= last; j++) {
                        struct object_entry *child = objects + deltas[j].obj_no;
                        if (child->real_type == OBJ_REF_DELTA)
-                               resolve_delta(child, data, size, type);
+                               resolve_delta(child, &base_obj, type);
                }
 
-               if (check_sha1_signature(d->base.sha1, data, size, typename(type)))
-                       die("local object %s is corrupt", sha1_to_hex(d->base.sha1));
-               append_obj_to_pack(d->base.sha1, data, size, type);
-               free(data);
+               unlink_base_data(&base_obj);
                display_progress(progress, nr_resolved_deltas);
        }
        free(sorted_by_pos);
index f5cd0ac59e5794a375172b998399a546eaef4ab1..25b81a445c8fafe0c00ce30082b7d9a7c22ccf1e 100644 (file)
@@ -11,7 +11,7 @@
 #define BLKSIZE 512
 
 static const char pack_redundant_usage[] =
-"git-pack-redundant [ --verbose ] [ --alt-odb ] < --all | <.pack filename> ...>";
+"git pack-redundant [ --verbose ] [ --alt-odb ] < --all | <.pack filename> ...>";
 
 static int load_all_packs, verbose, alt_odb;
 
index 2fd5edbf53546ac449a077439aa59ca5dd992274..987b0157192b9fe4c7451d94f5948bdbd7f524bb 100644 (file)
@@ -214,7 +214,7 @@ is_abbreviated:
        return -2;
 }
 
-void check_typos(const char *arg, const struct option *options)
+static void check_typos(const char *arg, const struct option *options)
 {
        if (strlen(arg) < 3)
                return;
index d801f9d1cf9eca5ddeff2f0af4549bbc1e72423f..a50a851125db765f06f3869873623bf7592de405 100644 (file)
@@ -528,7 +528,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
                ce = create_alias_ce(ce, alias);
        ce->ce_flags |= CE_ADDED;
 
-       /* It was suspected to be recily clean, but it turns out to be Ok */
+       /* It was suspected to be racily clean, but it turns out to be Ok */
        was_same = (alias &&
                    !ce_stage(alias) &&
                    !hashcmp(alias->sha1, ce->sha1) &&
@@ -980,7 +980,10 @@ int refresh_index(struct index_state *istate, unsigned int flags, const char **p
        int not_new = (flags & REFRESH_IGNORE_MISSING) != 0;
        int ignore_submodules = (flags & REFRESH_IGNORE_SUBMODULES) != 0;
        unsigned int options = really ? CE_MATCH_IGNORE_VALID : 0;
+       const char *needs_update_message;
 
+       needs_update_message = ((flags & REFRESH_SAY_CHANGED)
+                               ? "locally modified" : "needs update");
        for (i = 0; i < istate->cache_nr; i++) {
                struct cache_entry *ce, *new;
                int cache_errno = 0;
@@ -1019,7 +1022,7 @@ int refresh_index(struct index_state *istate, unsigned int flags, const char **p
                        }
                        if (quiet)
                                continue;
-                       printf("%s: needs update\n", ce->name);
+                       printf("%s: %s\n", ce->name, needs_update_message);
                        has_errors = 1;
                        continue;
                }
index 12589215e867bff37d5f2848083e8f138331e8ee..0456aa6376caa1387284aa8fe42fc1ff66629822 100644 (file)
--- a/rerere.c
+++ b/rerere.c
@@ -278,10 +278,13 @@ static int do_plain_rerere(struct path_list *rr, int fd)
 
                if (has_resolution(name)) {
                        if (!merge(name, path)) {
-                               fprintf(stderr, "Resolved '%s' using "
-                                               "previous resolution.\n", path);
                                if (rerere_autoupdate)
                                        path_list_insert(path, &update);
+                               fprintf(stderr,
+                                       "%s '%s' using previous resolution.\n",
+                                       rerere_autoupdate
+                                       ? "Staged" : "Resolved",
+                                       path);
                                goto mark_resolved;
                        }
                }
index 846af7bd20274fba2801fbafe50dc12b7252aecc..3897fec53170c50921eb1952bc4bdf9c08480638 100644 (file)
@@ -260,7 +260,7 @@ static int tree_difference = REV_TREE_SAME;
 static void file_add_remove(struct diff_options *options,
                    int addremove, unsigned mode,
                    const unsigned char *sha1,
-                   const char *base, const char *path)
+                   const char *fullpath)
 {
        int diff = REV_TREE_DIFFERENT;
 
@@ -286,7 +286,7 @@ static void file_change(struct diff_options *options,
                 unsigned old_mode, unsigned new_mode,
                 const unsigned char *old_sha1,
                 const unsigned char *new_sha1,
-                const char *base, const char *path)
+                const char *fullpath)
 {
        tree_difference = REV_TREE_DIFFERENT;
        DIFF_OPT_SET(options, HAS_CHANGES);
index 4aed75265e945d7b8dfafb36913006376768b4d3..720737d856b694bc5239f0c18af372959c99e744 100644 (file)
--- a/strbuf.c
+++ b/strbuf.c
@@ -60,6 +60,18 @@ void strbuf_grow(struct strbuf *sb, size_t extra)
        ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc);
 }
 
+void strbuf_trim(struct strbuf *sb)
+{
+       char *b = sb->buf;
+       while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))
+               sb->len--;
+       while (sb->len > 0 && isspace(*b)) {
+               b++;
+               sb->len--;
+       }
+       memmove(sb->buf, b, sb->len);
+       sb->buf[sb->len] = '\0';
+}
 void strbuf_rtrim(struct strbuf *sb)
 {
        while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))
@@ -67,7 +79,65 @@ void strbuf_rtrim(struct strbuf *sb)
        sb->buf[sb->len] = '\0';
 }
 
-int strbuf_cmp(struct strbuf *a, struct strbuf *b)
+void strbuf_ltrim(struct strbuf *sb)
+{
+       char *b = sb->buf;
+       while (sb->len > 0 && isspace(*b)) {
+               b++;
+               sb->len--;
+       }
+       memmove(sb->buf, b, sb->len);
+       sb->buf[sb->len] = '\0';
+}
+
+void strbuf_tolower(struct strbuf *sb)
+{
+       int i;
+       for (i = 0; i < sb->len; i++)
+               sb->buf[i] = tolower(sb->buf[i]);
+}
+
+struct strbuf **strbuf_split(const struct strbuf *sb, int delim)
+{
+       int alloc = 2, pos = 0;
+       char *n, *p;
+       struct strbuf **ret;
+       struct strbuf *t;
+
+       ret = xcalloc(alloc, sizeof(struct strbuf *));
+       p = n = sb->buf;
+       while (n < sb->buf + sb->len) {
+               int len;
+               n = memchr(n, delim, sb->len - (n - sb->buf));
+               if (pos + 1 >= alloc) {
+                       alloc = alloc * 2;
+                       ret = xrealloc(ret, sizeof(struct strbuf *) * alloc);
+               }
+               if (!n)
+                       n = sb->buf + sb->len - 1;
+               len = n - p + 1;
+               t = xmalloc(sizeof(struct strbuf));
+               strbuf_init(t, len);
+               strbuf_add(t, p, len);
+               ret[pos] = t;
+               ret[++pos] = NULL;
+               p = ++n;
+       }
+       return ret;
+}
+
+void strbuf_list_free(struct strbuf **sbs)
+{
+       struct strbuf **s = sbs;
+
+       while (*s) {
+               strbuf_release(*s);
+               free(*s++);
+       }
+       free(sbs);
+}
+
+int strbuf_cmp(const struct strbuf *a, const struct strbuf *b)
 {
        int cmp;
        if (a->len < b->len) {
index faec2291d9e622c76dcdb3ef13d0876c5e3e6f28..0c6ffad53a8f0362a9d5fe9b0685aeaa96346076 100644 (file)
--- a/strbuf.h
+++ b/strbuf.h
@@ -61,7 +61,7 @@ static inline void strbuf_swap(struct strbuf *a, struct strbuf *b) {
 }
 
 /*----- strbuf size related -----*/
-static inline size_t strbuf_avail(struct strbuf *sb) {
+static inline size_t strbuf_avail(const struct strbuf *sb) {
        return sb->alloc ? sb->alloc - sb->len - 1 : 0;
 }
 
@@ -77,8 +77,14 @@ static inline void strbuf_setlen(struct strbuf *sb, size_t len) {
 #define strbuf_reset(sb)  strbuf_setlen(sb, 0)
 
 /*----- content related -----*/
+extern void strbuf_trim(struct strbuf *);
 extern void strbuf_rtrim(struct strbuf *);
-extern int strbuf_cmp(struct strbuf *, struct strbuf *);
+extern void strbuf_ltrim(struct strbuf *);
+extern int strbuf_cmp(const struct strbuf *, const struct strbuf *);
+extern void strbuf_tolower(struct strbuf *);
+
+extern struct strbuf **strbuf_split(const struct strbuf *, int delim);
+extern void strbuf_list_free(struct strbuf **);
 
 /*----- add data in your buffer -----*/
 static inline void strbuf_addch(struct strbuf *sb, int c) {
@@ -98,7 +104,7 @@ extern void strbuf_add(struct strbuf *, const void *, size_t);
 static inline void strbuf_addstr(struct strbuf *sb, const char *s) {
        strbuf_add(sb, s, strlen(s));
 }
-static inline void strbuf_addbuf(struct strbuf *sb, struct strbuf *sb2) {
+static inline void strbuf_addbuf(struct strbuf *sb, const struct strbuf *sb2) {
        strbuf_add(sb, sb2->buf, sb2->len);
 }
 extern void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len);
index a778865ae7d015535763b856391ba751f2a9f87c..0d65cedaa6566a6dd654753cb574c9ee64b1c90b 100644 (file)
@@ -26,7 +26,7 @@ clean:
        $(RM) -r 'trash directory' test-results
 
 aggregate-results:
-       ./aggregate-results.sh test-results/t*-*
+       '$(SHELL_PATH_SQ)' ./aggregate-results.sh test-results/t*-*
 
 # we can test NO_OPTIMIZE_COMMITS independently of LC_ALL
 full-svn-test:
index 52e88e30465b8de4f0d9bd592bdd525e0f31145a..d5bab75d7da49ebb53e368d67f6b867f5417a125 100755 (executable)
@@ -10,9 +10,9 @@ for file
 do
        while read type value
        do
-               case $type in
-               '')
-                       continue ;;
+               case $type in
+               '')
+                       continue ;;
                fixed)
                        fixed=$(($fixed + $value)) ;;
                success)
@@ -20,9 +20,9 @@ do
                failed)
                        failed=$(($failed + $value)) ;;
                broken)
-                       broken=$(( $broken + $value)) ;;
+                       broken=$(($broken + $value)) ;;
                total)
-                       total=$(( $total + $value)) ;;
+                       total=$(($total + $value)) ;;
                esac
        done <"$file"
 done
index 5d3bd9dda916d454997da0015c35d0fa7d9f72c0..a841df2a9e3a9ed64e81ab7b9778e59cfc714cad 100644 (file)
@@ -98,7 +98,7 @@ LoadModule dav_module $SVN_HTTPD_MODULE_PATH/mod_dav.so
 LoadModule dav_svn_module $SVN_HTTPD_MODULE_PATH/mod_dav_svn.so
 <Location /$repo_base_path>
        DAV svn
-       SVNPath $rawsvnrepo
+       SVNPath "$rawsvnrepo"
 </Location>
 EOF
        "$SVN_HTTPD_PATH" -f "$GIT_DIR"/httpd.conf -k start
index d7cbc5c6dae538fe8c053a2f3760502422615e2c..70df15cbd8339b552a56a95ca0c0893138550201 100755 (executable)
@@ -63,7 +63,7 @@ test_expect_failure 'pretend we have fixed a known breakage' '
 
 # updating a new file without --add should fail.
 test_expect_success 'git update-index without --add should fail adding.' '
-    ! git update-index should-be-empty
+    test_must_fail git update-index should-be-empty
 '
 
 # and with --add it should succeed, even if it is empty (it used to fail).
@@ -83,7 +83,7 @@ test_expect_success \
 # Removing paths.
 rm -f should-be-empty full-of-directories
 test_expect_success 'git update-index without --remove should fail removing.' '
-    ! git update-index should-be-empty
+    test_must_fail git update-index should-be-empty
 '
 
 test_expect_success \
@@ -217,7 +217,7 @@ test_expect_success \
     'git update-index --index-info < badobjects'
 
 test_expect_success 'writing this tree without --missing-ok.' '
-    ! git write-tree
+    test_must_fail git write-tree
 '
 
 test_expect_success \
index d31887f9bf35a7fa9e31b1eb859a9cf21c918d6c..2a38d98cb46ec5392093dc3c0eedf28d6f56c96b 100755 (executable)
@@ -83,11 +83,11 @@ test_expect_success 'init --bare' '
 
        (
                unset GIT_DIR GIT_WORK_TREE GIT_CONFIG
-               mkdir git-init-bare.git &&
-               cd git-init-bare.git &&
+               mkdir init-bare.git &&
+               cd init-bare.git &&
                git init --bare
        ) &&
-       check_config git-init-bare.git true unset
+       check_config init-bare.git true unset
 '
 
 test_expect_success 'GIT_DIR non-bare' '
index 2bfeac986eadeca0064b1aee808d08b2f86082c4..1be7446d8d9f8a46b463f2474a8c25bdd33044d2 100755 (executable)
@@ -52,7 +52,7 @@ test_expect_success 'safecrlf: autocrlf=input, all CRLF' '
        git config core.safecrlf true &&
 
        for w in I am all CRLF; do echo $w; done | append_cr >allcrlf &&
-       ! git add allcrlf
+       test_must_fail git add allcrlf
 '
 
 test_expect_success 'safecrlf: autocrlf=input, mixed LF/CRLF' '
@@ -61,7 +61,7 @@ test_expect_success 'safecrlf: autocrlf=input, mixed LF/CRLF' '
        git config core.safecrlf true &&
 
        for w in Oh here is CRLFQ in text; do echo $w; done | q_to_cr >mixed &&
-       ! git add mixed
+       test_must_fail git add mixed
 '
 
 test_expect_success 'safecrlf: autocrlf=true, all LF' '
@@ -70,7 +70,7 @@ test_expect_success 'safecrlf: autocrlf=true, all LF' '
        git config core.safecrlf true &&
 
        for w in I am all LF; do echo $w; done >alllf &&
-       ! git add alllf
+       test_must_fail git add alllf
 '
 
 test_expect_success 'safecrlf: autocrlf=true mixed LF/CRLF' '
@@ -79,7 +79,7 @@ test_expect_success 'safecrlf: autocrlf=true mixed LF/CRLF' '
        git config core.safecrlf true &&
 
        for w in Oh here is CRLFQ in text; do echo $w; done | q_to_cr >mixed &&
-       ! git add mixed
+       test_must_fail git add mixed
 '
 
 test_expect_success 'safecrlf: print warning only once' '
index c5360e23d9ff1a5f31d42919eabdb2561f0d2e3d..b177174ef53e7689cc8c18b134afdbe90be72744 100755 (executable)
@@ -43,7 +43,7 @@ test_expect_success "detection of case insensitive filesystem during repo init"
 else
 test_expect_success "detection of case insensitive filesystem during repo init" '
 
-       ! git config --bool core.ignorecase >/dev/null ||
+       test_must_fail git config --bool core.ignorecase >/dev/null ||
        test $(git config --bool core.ignorecase) = false
 '
 fi
index 05262954abbd5aa054fbde44f946d58e07a54574..1ec0535138c72bbd1e497c35c21bc5ea46b0315f 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-test_description=git-hash-object
+test_description="git-hash-object"
 
 . ./test-lib.sh
 
index dcb3108c290813dae178394011bb2b44f2f7ca9e..09a8199335cbdf96f8aba75d47a321f0cfb828d9 100755 (executable)
@@ -102,7 +102,7 @@ echo "Lots of fun" >>example
 git commit -m 'Some fun.' -i hello example
 
 test_expect_success 'git resolve now fails' '
-       ! git merge -m "Merge work in mybranch" mybranch
+       test_must_fail git merge -m "Merge work in mybranch" mybranch
 '
 
 cat > hello << EOF
index afe7e663fb96484474f69af51268d42c78a04185..64567fb94d5c3f9587b643333212cdb37a4661ac 100755 (executable)
@@ -201,7 +201,7 @@ test_expect_success 'non-match value' \
        'test wow = $(git config --get nextsection.nonewline !for)'
 
 test_expect_success 'ambiguous get' '
-       ! git config --get nextsection.nonewline
+       test_must_fail git config --get nextsection.nonewline
 '
 
 test_expect_success 'get multivar' \
@@ -223,15 +223,15 @@ EOF
 test_expect_success 'multivar replace' 'cmp .git/config expect'
 
 test_expect_success 'ambiguous value' '
-       ! git config nextsection.nonewline
+       test_must_fail git config nextsection.nonewline
 '
 
 test_expect_success 'ambiguous unset' '
-       ! git config --unset nextsection.nonewline
+       test_must_fail git config --unset nextsection.nonewline
 '
 
 test_expect_success 'invalid unset' '
-       ! git config --unset somesection.nonewline
+       test_must_fail git config --unset somesection.nonewline
 '
 
 git config --unset nextsection.nonewline "wow3$"
@@ -248,7 +248,7 @@ EOF
 
 test_expect_success 'multivar unset' 'cmp .git/config expect'
 
-test_expect_success 'invalid key' '! git config inval.2key blabla'
+test_expect_success 'invalid key' 'test_must_fail git config inval.2key blabla'
 
 test_expect_success 'correct key' 'git config 123456.a123 987'
 
@@ -430,7 +430,8 @@ EOF
 test_expect_success "rename succeeded" "test_cmp expect .git/config"
 
 test_expect_success "rename non-existing section" '
-       ! git config --rename-section branch."world domination" branch.drei
+       test_must_fail git config --rename-section \
+               branch."world domination" branch.drei
 '
 
 test_expect_success "rename succeeded" "test_cmp expect .git/config"
@@ -545,11 +546,11 @@ test_expect_success bool '
 test_expect_success 'invalid bool (--get)' '
 
        git config bool.nobool foobar &&
-       ! git config --bool --get bool.nobool'
+       test_must_fail git config --bool --get bool.nobool'
 
 test_expect_success 'invalid bool (set)' '
 
-       ! git config --bool bool.nobool foobar'
+       test_must_fail git config --bool bool.nobool foobar'
 
 rm .git/config
 
@@ -669,7 +670,7 @@ EOF
 test_expect_success 'quoting' 'cmp .git/config expect'
 
 test_expect_success 'key with newline' '
-       ! git config "key.with
+       test_must_fail git config "key.with
 newline" 123'
 
 test_expect_success 'value with newline' 'git config key.sub value.with\\\
index 9be0770e7627ee094349af85b0d4702e156ff6cd..8d305b43725f8cf60e7ee802df1923feb98eeae5 100755 (executable)
@@ -41,7 +41,7 @@ test_expect_success 'gitdir required mode on normal repos' '
        cd test && git apply --check --index ../test.patch)'
 
 test_expect_success 'gitdir required mode on unsupported repo' '
-       (cd test2 && ! git apply --check --index ../test.patch)
+       (cd test2 && test_must_fail git apply --check --index ../test.patch)
 '
 
 test_done
index ca99d37616aaaae9584ecfd1c5d74378c727d077..b31e4b1ac66e56d67ba48ab213c4ef9c32f05ea8 100755 (executable)
@@ -76,7 +76,7 @@ test_expect_success "delete $m (by HEAD)" '
 rm -f .git/$m
 
 test_expect_success '(not) create HEAD with old sha1' "
-       ! git update-ref HEAD $A $B
+       test_must_fail git update-ref HEAD $A $B
 "
 test_expect_success "(not) prior created .git/$m" "
        ! test -f .git/$m
@@ -87,7 +87,7 @@ test_expect_success \
        "create HEAD" \
        "git update-ref HEAD $A"
 test_expect_success '(not) change HEAD with wrong SHA1' "
-       ! git update-ref HEAD $B $Z
+       test_must_fail git update-ref HEAD $B $Z
 "
 test_expect_success "(not) changed .git/$m" "
        ! test $B"' = $(cat .git/'"$m"')
index 5141fab7cf567fc5d16a8e9a296d2aff5f6c67e6..f7e1a735ec8699616280a086f59dc50c078bfaa7 100755 (executable)
@@ -38,7 +38,7 @@ date >path1
 
 test_expect_success \
     'git checkout-index without -f should fail on conflicting work tree.' \
-    '! git checkout-index -a'
+    'test_must_fail git checkout-index -a'
 
 test_expect_success \
     'git checkout-index with -f should succeed.' \
index 9beaecd18b25cb7e22b09c11234c05a8fa1d4116..6ef2dcfd8afece86aaf6345630179af179eb2ed9 100755 (executable)
@@ -46,6 +46,6 @@ for p in path0/file0 path1/file1 path2 path3
 do
        test_expect_success \
            "git update-index to add conflicting path $p should fail." \
-           "! git update-index --add -- $p"
+           "test_must_fail git update-index --add -- $p"
 done
 test_done
diff --git a/t/t2103-update-index-ignore-missing.sh b/t/t2103-update-index-ignore-missing.sh
new file mode 100755 (executable)
index 0000000..332694e
--- /dev/null
@@ -0,0 +1,89 @@
+#!/bin/sh
+
+test_description='update-index with options'
+
+. ./test-lib.sh
+
+test_expect_success basics '
+       >one &&
+       >two &&
+       >three &&
+
+       # need --add when adding
+       test_must_fail git update-index one &&
+       test -z "$(git ls-files)" &&
+       git update-index --add one &&
+       test zone = "z$(git ls-files)" &&
+
+       # update-index is atomic
+       echo 1 >one &&
+       test_must_fail git update-index one two &&
+       echo "M one" >expect &&
+       git diff-files --name-status >actual &&
+       test_cmp expect actual &&
+
+       git update-index --add one two three &&
+       for i in one three two; do echo $i; done >expect &&
+       git ls-files >actual &&
+       test_cmp expect actual &&
+
+       test_tick &&
+       (
+               test_create_repo xyzzy &&
+               cd xyzzy &&
+               >file &&
+               git add file
+               git commit -m "sub initial"
+       ) &&
+       git add xyzzy &&
+
+       test_tick &&
+       git commit -m initial &&
+       git tag initial
+'
+
+test_expect_success '--ignore-missing --refresh' '
+       git reset --hard initial &&
+       echo 2 >one &&
+       test_must_fail git update-index --refresh &&
+       echo 1 >one &&
+       git update-index --refresh &&
+       rm -f two &&
+       test_must_fail git update-index --refresh &&
+       git update-index --ignore-missing --refresh
+
+'
+
+test_expect_success '--unmerged --refresh' '
+       git reset --hard initial &&
+       info=$(git ls-files -s one | sed -e "s/ 0       / 1     /") &&
+       git rm --cached one &&
+       echo "$info" | git update-index --index-info &&
+       test_must_fail git update-index --refresh &&
+       git update-index --unmerged --refresh &&
+       echo 2 >two &&
+       test_must_fail git update-index --unmerged --refresh >actual &&
+       grep two actual &&
+       ! grep one actual &&
+       ! grep three actual
+'
+
+test_expect_success '--ignore-submodules --refresh (1)' '
+       git reset --hard initial &&
+       rm -f two &&
+       test_must_fail git update-index --ignore-submodules --refresh
+'
+
+test_expect_success '--ignore-submodules --refresh (2)' '
+       git reset --hard initial &&
+       test_tick &&
+       (
+               cd xyzzy &&
+               git commit -m "sub second" --allow-empty
+       ) &&
+       test_must_fail git update-index --refresh &&
+       test_must_fail git update-index --ignore-missing --refresh &&
+       git update-index --ignore-submodules --refresh
+'
+
+test_done
diff --git a/t/t2202-add-addremove.sh b/t/t2202-add-addremove.sh
new file mode 100755 (executable)
index 0000000..6a81510
--- /dev/null
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+test_description='git add --all'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+       (
+               echo .gitignore
+               echo will-remove
+       ) >expect &&
+       (
+               echo actual
+               echo expect
+               echo ignored
+       ) >.gitignore &&
+       >will-remove &&
+       git add --all &&
+       test_tick &&
+       git commit -m initial &&
+       git ls-files >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'git add --all' '
+       (
+               echo .gitignore
+               echo not-ignored
+               echo "M .gitignore"
+               echo "A not-ignored"
+               echo "D will-remove"
+       ) >expect &&
+       >ignored &&
+       >not-ignored &&
+       echo modification >>.gitignore &&
+       rm -f will-remove &&
+       git add --all &&
+       git update-index --refresh &&
+       git ls-files >actual &&
+       git diff-index --name-status --cached HEAD >>actual &&
+       test_cmp expect actual
+'
+
+test_done
index f4da869932e40429f94d19a9cf2e18dc1e838f0a..af8c4121abfc28b7e289b39936df45bd5b82cf22 100755 (executable)
@@ -17,7 +17,7 @@ git-commit -m "add foo bar"
 
 test_expect_success \
     'git ls-files --error-unmatch should fail with unmatched path.' \
-    '! git ls-files --error-unmatch foo bar-does-not-match'
+    'test_must_fail git ls-files --error-unmatch foo bar-does-not-match'
 
 test_expect_success \
     'git ls-files --error-unmatch should succeed eith matched paths.' \
index 8d8768688d8dde3637a50ece28fb8720b7612ddd..7c583c8055627d6f3c4a18bcce9c04005e0514d5 100755 (executable)
@@ -78,13 +78,13 @@ test_expect_success \
 test_expect_success 'git branch -m o/o o should fail when o/p exists' '
        git branch o/o &&
         git branch o/p &&
-       ! git branch -m o/o o
+       test_must_fail git branch -m o/o o
 '
 
 test_expect_success 'git branch -m q r/q should fail when r exists' '
        git branch q &&
        git branch r &&
-       ! git branch -m q r/q
+       test_must_fail git branch -m q r/q
 '
 
 mv .git/config .git/config-saved
@@ -110,14 +110,14 @@ test_expect_success \
 
 test_expect_success 'config information was renamed, too' \
        "test $(git config branch.s.dummy) = Hello &&
-        ! git config branch.s/s/dummy"
+        test_must_fail git config branch.s/s/dummy"
 
 test_expect_success \
     'git branch -m u v should fail when the reflog for u is a symlink' '
      git branch -l u &&
      mv .git/logs/refs/heads/u real-u &&
      ln -s real-u .git/logs/refs/heads/u &&
-     ! git branch -m u v
+     test_must_fail git branch -m u v
 '
 
 test_expect_success 'test tracking setup via --track' \
index b64ccfbc5bcf40717f8e04bdadc841bc8cd6c51f..c2dec1c6320a0f9b555e3cd38d164c4e3efcb51e 100755 (executable)
@@ -43,7 +43,7 @@ test_expect_success 'git branch c/d should barf if branch c exists' '
      git branch c &&
      git pack-refs --all &&
      rm -f .git/refs/heads/c &&
-     ! git branch c/d
+     test_must_fail git branch c/d
 '
 
 test_expect_success \
@@ -72,7 +72,7 @@ test_expect_success \
 test_expect_success 'git branch i/j/k should barf if branch i exists' '
      git branch i &&
      git pack-refs --all --prune &&
-     ! git branch i/j/k
+     test_must_fail git branch i/j/k
 '
 
 test_expect_success \
index 0a26099658f4307f06fe594feb3fc046ff267076..0d33c71daa557e68268dfb2279a02fe2afca1ed7 100755 (executable)
@@ -32,7 +32,7 @@ test_expect_success setup '
        '
 
 test_expect_success 'rebase with git am -3 (default)' '
-       ! git rebase master
+       test_must_fail git rebase master
 '
 
 test_expect_success 'rebase --skip with am -3' '
@@ -43,7 +43,7 @@ test_expect_success 'rebase moves back to skip-reference' '
        test refs/heads/skip-reference = $(git symbolic-ref HEAD) &&
        git branch post-rebase &&
        git reset --hard pre-rebase &&
-       ! git rebase master &&
+       test_must_fail git rebase master &&
        echo "hello" > hello &&
        git add hello &&
        git rebase --continue &&
@@ -53,7 +53,9 @@ test_expect_success 'rebase moves back to skip-reference' '
 
 test_expect_success 'checkout skip-merge' 'git checkout -f skip-merge'
 
-test_expect_success 'rebase with --merge' '! git rebase --merge master'
+test_expect_success 'rebase with --merge' '
+       test_must_fail git rebase --merge master
+'
 
 test_expect_success 'rebase --skip with --merge' '
        git rebase --skip
index 7c92e261fcc87adc1a00c1832284816e40dee55d..0ab52da902c8d602e9c4d64660aa4a7e8e35544f 100755 (executable)
@@ -35,7 +35,7 @@ test_expect_success 'cherry-pick a non-merge with -m should fail' '
 
        git reset --hard &&
        git checkout a^0 &&
-       ! git cherry-pick -m 1 b &&
+       test_must_fail git cherry-pick -m 1 b &&
        git diff --exit-code a --
 
 '
@@ -44,7 +44,7 @@ test_expect_success 'cherry pick a merge without -m should fail' '
 
        git reset --hard &&
        git checkout a^0 &&
-       ! git cherry-pick c &&
+       test_must_fail git cherry-pick c &&
        git diff --exit-code a --
 
 '
@@ -71,7 +71,7 @@ test_expect_success 'cherry pick a merge relative to nonexistent parent should f
 
        git reset --hard &&
        git checkout b^0 &&
-       ! git cherry-pick -m 3 c
+       test_must_fail git cherry-pick -m 3 c
 
 '
 
@@ -79,7 +79,7 @@ test_expect_success 'revert a non-merge with -m should fail' '
 
        git reset --hard &&
        git checkout c^0 &&
-       ! git revert -m 1 b &&
+       test_must_fail git revert -m 1 b &&
        git diff --exit-code c
 
 '
@@ -88,7 +88,7 @@ test_expect_success 'revert a merge without -m should fail' '
 
        git reset --hard &&
        git checkout c^0 &&
-       ! git revert c &&
+       test_must_fail git revert c &&
        git diff --exit-code c
 
 '
@@ -115,7 +115,7 @@ test_expect_success 'revert a merge relative to nonexistent parent should fail'
 
        git reset --hard &&
        git checkout c^0 &&
-       ! git revert -m 3 c &&
+       test_must_fail git revert -m 3 c &&
        git diff --exit-code c
 
 '
index f542f0af41989aee51f75b9844abf97943d9e33f..79c06adf1f035cf727771974b2f9713da9d2fb8c 100755 (executable)
@@ -67,7 +67,7 @@ test_expect_success \
      echo "other content" > foo
      git add foo
      echo "yet another content" > foo
-     ! git rm --cached foo
+     test_must_fail git rm --cached foo
 '
 
 test_expect_success \
@@ -82,7 +82,7 @@ test_expect_success \
 
 test_expect_success \
     'Post-check that foo exists but is not in index after git rm foo' \
-    '[ -f foo ] && ! git ls-files --error-unmatch foo'
+    '[ -f foo ] && test_must_fail git ls-files --error-unmatch foo'
 
 test_expect_success \
     'Pre-check that bar exists and is in index before "git rm bar"' \
@@ -94,7 +94,7 @@ test_expect_success \
 
 test_expect_success \
     'Post-check that bar does not exist and is not in index after "git rm -f bar"' \
-    '! [ -f bar ] && ! git ls-files --error-unmatch bar'
+    '! [ -f bar ] && test_must_fail git ls-files --error-unmatch bar'
 
 test_expect_success \
     'Test that "git rm -- -q" succeeds (remove a file that looks like an option)' \
@@ -109,7 +109,7 @@ if test "$test_failed_remove" = y; then
 chmod a-w .
 test_expect_success \
     'Test that "git rm -f" fails if its rm fails' \
-    '! git rm -f baz'
+    'test_must_fail git rm -f baz'
 chmod 775 .
 else
     test_expect_success 'skipping removal failure (perhaps running as root?)' :
@@ -151,7 +151,7 @@ test_expect_success 'Re-add foo and baz' '
 
 test_expect_success 'Modify foo -- rm should refuse' '
        echo >>foo &&
-       ! git rm foo baz &&
+       test_must_fail git rm foo baz &&
        test -f foo &&
        test -f baz &&
        git ls-files --error-unmatch foo baz
@@ -161,8 +161,8 @@ test_expect_success 'Modified foo -- rm -f should work' '
        git rm -f foo baz &&
        test ! -f foo &&
        test ! -f baz &&
-       ! git ls-files --error-unmatch foo &&
-       ! git ls-files --error-unmatch bar
+       test_must_fail git ls-files --error-unmatch foo &&
+       test_must_fail git ls-files --error-unmatch bar
 '
 
 test_expect_success 'Re-add foo and baz for HEAD tests' '
@@ -173,7 +173,7 @@ test_expect_success 'Re-add foo and baz for HEAD tests' '
 '
 
 test_expect_success 'foo is different in index from HEAD -- rm should refuse' '
-       ! git rm foo baz &&
+       test_must_fail git rm foo baz &&
        test -f foo &&
        test -f baz &&
        git ls-files --error-unmatch foo baz
@@ -183,8 +183,8 @@ test_expect_success 'but with -f it should work.' '
        git rm -f foo baz &&
        test ! -f foo &&
        test ! -f baz &&
-       ! git ls-files --error-unmatch foo
-       ! git ls-files --error-unmatch baz
+       test_must_fail git ls-files --error-unmatch foo
+       test_must_fail git ls-files --error-unmatch baz
 '
 
 test_expect_success 'Recursive test setup' '
@@ -195,14 +195,14 @@ test_expect_success 'Recursive test setup' '
 '
 
 test_expect_success 'Recursive without -r fails' '
-       ! git rm frotz &&
+       test_must_fail git rm frotz &&
        test -d frotz &&
        test -f frotz/nitfol
 '
 
 test_expect_success 'Recursive with -r but dirty' '
        echo qfwfq >>frotz/nitfol
-       ! git rm -r frotz &&
+       test_must_fail git rm -r frotz &&
        test -d frotz &&
        test -f frotz/nitfol
 '
@@ -214,7 +214,19 @@ test_expect_success 'Recursive with -r -f' '
 '
 
 test_expect_success 'Remove nonexistent file returns nonzero exit status' '
-       ! git rm nonexistent
+       test_must_fail git rm nonexistent
+'
+
+test_expect_success 'Call "rm" from outside the work tree' '
+       mkdir repo &&
+       cd repo &&
+       git init &&
+       echo something > somefile &&
+       git add somefile &&
+       git commit -m "add a file" &&
+       (cd .. &&
+        git --git-dir=repo/.git --work-tree=repo rm somefile) &&
+       test_must_fail git ls-files --error-unmatch somefile
 '
 
 test_done
index e83fa1f6894dd13eb11cae6afb8ecbd3dcb999db..7d123d17fc156c61a8e85a399c3762e8075485de 100755 (executable)
@@ -85,12 +85,12 @@ test_expect_success '.gitignore is honored' '
 '
 
 test_expect_success 'error out when attempting to add ignored ones without -f' '
-       ! git add a.?? &&
+       test_must_fail git add a.?? &&
        ! (git ls-files | grep "\\.ig")
 '
 
 test_expect_success 'error out when attempting to add ignored ones without -f' '
-       ! git add d.?? &&
+       test_must_fail git add d.?? &&
        ! (git ls-files | grep "\\.ig")
 '
 
index 0922c708f16fea490a85d16d5d4d366df0fb2088..a27fccc8dce431169ce41f7137fb75f44149719c 100755 (executable)
@@ -144,7 +144,7 @@ test_expect_success 'check with no whitespace errors' '
 test_expect_success 'check with trailing whitespace' '
 
        echo "foo(); " > x &&
-       ! git diff --check
+       test_must_fail git diff --check
 
 '
 
@@ -152,7 +152,7 @@ test_expect_success 'check with space before tab in indent' '
 
        # indent has space followed by hard tab
        echo "  foo();" > x &&
-       ! git diff --check
+       test_must_fail git diff --check
 
 '
 
@@ -181,7 +181,7 @@ test_expect_success 'check staged with trailing whitespace' '
 
        echo "foo(); " > x &&
        git add x &&
-       ! git diff --cached --check
+       test_must_fail git diff --cached --check
 
 '
 
@@ -190,7 +190,7 @@ test_expect_success 'check staged with space before tab in indent' '
        # indent has space followed by hard tab
        echo "  foo();" > x &&
        git add x &&
-       ! git diff --cached --check
+       test_must_fail git diff --cached --check
 
 '
 
@@ -206,7 +206,7 @@ test_expect_success 'check with trailing whitespace (diff-index)' '
 
        echo "foo(); " > x &&
        git add x &&
-       ! git diff-index --check HEAD
+       test_must_fail git diff-index --check HEAD
 
 '
 
@@ -215,7 +215,7 @@ test_expect_success 'check with space before tab in indent (diff-index)' '
        # indent has space followed by hard tab
        echo "  foo();" > x &&
        git add x &&
-       ! git diff-index --check HEAD
+       test_must_fail git diff-index --check HEAD
 
 '
 
@@ -231,7 +231,7 @@ test_expect_success 'check staged with trailing whitespace (diff-index)' '
 
        echo "foo(); " > x &&
        git add x &&
-       ! git diff-index --cached --check HEAD
+       test_must_fail git diff-index --cached --check HEAD
 
 '
 
@@ -240,7 +240,7 @@ test_expect_success 'check staged with space before tab in indent (diff-index)'
        # indent has space followed by hard tab
        echo "  foo();" > x &&
        git add x &&
-       ! git diff-index --cached --check HEAD
+       test_must_fail git diff-index --cached --check HEAD
 
 '
 
@@ -256,7 +256,7 @@ test_expect_success 'check with trailing whitespace (diff-tree)' '
 
        echo "foo(); " > x &&
        git commit -m "another commit" x &&
-       ! git diff-tree --check HEAD^ HEAD
+       test_must_fail git diff-tree --check HEAD^ HEAD
 
 '
 
@@ -265,7 +265,7 @@ test_expect_success 'check with space before tab in indent (diff-tree)' '
        # indent has space followed by hard tab
        echo "  foo();" > x &&
        git commit -m "yet another" x &&
-       ! git diff-tree --check HEAD^ HEAD
+       test_must_fail git diff-tree --check HEAD^ HEAD
 
 '
 
@@ -281,7 +281,7 @@ test_expect_success 'check trailing whitespace (trailing-space: on)' '
 
        git config core.whitespace "trailing-space" &&
        echo "foo ();   " > x &&
-       ! git diff --check
+       test_must_fail git diff --check
 
 '
 
@@ -299,7 +299,7 @@ test_expect_success 'check space before tab in indent (space-before-tab: on)' '
        # indent contains space followed by HT
        git config core.whitespace "space-before-tab" &&
        echo "  foo ();   " > x &&
-       ! git diff --check
+       test_must_fail git diff --check
 
 '
 
@@ -315,7 +315,7 @@ test_expect_success 'check spaces as indentation (indent-with-non-tab: on)' '
 
        git config core.whitespace "indent-with-non-tab" &&
        echo "        foo ();" > x &&
-       ! git diff --check
+       test_must_fail git diff --check
 
 '
 
@@ -323,7 +323,7 @@ test_expect_success 'check tabs and spaces as indentation (indent-with-non-tab:
 
        git config core.whitespace "indent-with-non-tab" &&
        echo "                  foo ();" > x &&
-       ! git diff --check
+       test_must_fail git diff --check
 
 '
 
index 6d3ef6c60bd5a26e2ed4d533fc4db7711bb92cfb..833d6cbcfc063f336d97689ae4e547cf5e956b69 100755 (executable)
@@ -54,7 +54,7 @@ test_expect_success 'custom pattern' '
 
 test_expect_success 'last regexp must not be negated' '
        git config diff.java.funcname "!static" &&
-       ! git diff --no-index Beer.java Beer-correct.java
+       test_must_fail git diff --no-index Beer.java Beer-correct.java
 '
 
 test_done
index 1b58233da6cfa09092e6953f7d9c6bc38d7bae56..7da0b4bb8bfa96765b9f6eaa1693e2e24e82d335 100755 (executable)
@@ -48,22 +48,22 @@ test_expect_success 'stat binary diff (copy) -- should not fail.' \
 
 test_expect_success 'check binary diff -- should fail.' \
        'git-checkout master &&
-        ! git apply --check B.diff'
+        test_must_fail git apply --check B.diff'
 
 test_expect_success 'check binary diff (copy) -- should fail.' \
        'git-checkout master &&
-        ! git apply --check C.diff'
+        test_must_fail git apply --check C.diff'
 
 test_expect_success \
        'check incomplete binary diff with replacement -- should fail.' '
        git-checkout master &&
-       ! git apply --check --allow-binary-replacement B.diff
+       test_must_fail git apply --check --allow-binary-replacement B.diff
 '
 
 test_expect_success \
     'check incomplete binary diff with replacement (copy) -- should fail.' '
         git-checkout master &&
-        ! git apply --check --allow-binary-replacement C.diff
+        test_must_fail git apply --check --allow-binary-replacement C.diff
 '
 
 test_expect_success 'check binary diff with replacement.' \
@@ -84,19 +84,19 @@ do_reset () {
 
 test_expect_success 'apply binary diff -- should fail.' \
        'do_reset &&
-        ! git apply B.diff'
+        test_must_fail git apply B.diff'
 
 test_expect_success 'apply binary diff -- should fail.' \
        'do_reset &&
-        ! git apply --index B.diff'
+        test_must_fail git apply --index B.diff'
 
 test_expect_success 'apply binary diff (copy) -- should fail.' \
        'do_reset &&
-        ! git apply C.diff'
+        test_must_fail git apply C.diff'
 
 test_expect_success 'apply binary diff (copy) -- should fail.' \
        'do_reset &&
-        ! git apply --index C.diff'
+        test_must_fail git apply --index C.diff'
 
 test_expect_success 'apply binary diff without replacement.' \
        'do_reset &&
index d74103988201b0c189e7a2564bfb0894e434c056..66fa51591eb7ee8f102fd86e30e54af2da3ea310 100755 (executable)
@@ -30,7 +30,7 @@ test_expect_success setup \
 # test
 
 test_expect_success 'apply at the end' \
-    '! git apply --index test-patch'
+    'test_must_fail git apply --index test-patch'
 
 cat >test-patch <<\EOF
 diff a/file b/file
@@ -48,6 +48,6 @@ c'
 git update-index file
 
 test_expect_success 'apply at the beginning' \
-       '! git apply --index test-patch'
+       'test_must_fail git apply --index test-patch'
 
 test_done
index 5cbd5ef6798bcef1c011893a4759cac4047dc6b7..98ba020d895f05c269fbba2a91c66d874245b145 100755 (executable)
@@ -182,7 +182,7 @@ test_expect_success 'am -3 falls back to 3-way merge' '
 
 test_expect_success 'am pauses on conflict' '
        git checkout lorem2^^ &&
-       ! git am lorem-move.patch &&
+       test_must_fail git am lorem-move.patch &&
        test -d .git/rebase
 '
 
@@ -195,7 +195,7 @@ test_expect_success 'am --skip works' '
 
 test_expect_success 'am --resolved works' '
        git checkout lorem2^^ &&
-       ! git am lorem-move.patch &&
+       test_must_fail git am lorem-move.patch &&
        test -d .git/rebase &&
        echo resolved >>file &&
        git add file &&
@@ -212,13 +212,13 @@ test_expect_success 'am takes patches from a Pine mailbox' '
 '
 
 test_expect_success 'am fails on mail without patch' '
-       ! git am <failmail &&
+       test_must_fail git am <failmail &&
        rm -r .git/rebase/
 '
 
 test_expect_success 'am fails on empty patch' '
        echo "---" >>failmail &&
-       ! git am <failmail &&
+       test_must_fail git am <failmail &&
        git am --skip &&
        ! test -d .git/rebase
 '
diff --git a/t/t4151-am-abort.sh b/t/t4151-am-abort.sh
new file mode 100755 (executable)
index 0000000..dda7e2c
--- /dev/null
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+test_description='am --abort'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+       for i in a b c d e f g
+       do
+               echo $i
+       done >file-1 &&
+       cp file-1 file-2 &&
+       test_tick &&
+       git add file-1 file-2 &&
+       git commit -m initial &&
+       git tag initial &&
+       for i in 2 3 4 5
+       do
+               echo $i >>file-1 &&
+               test_tick &&
+               git commit -a -m $i || break
+       done &&
+       git format-patch initial &&
+       git checkout -b side initial &&
+       echo local change >file-2-expect
+'
+
+for with3 in '' ' -3'
+do
+       test_expect_success "am$with3 stops at a patch that does not apply" '
+
+               git reset --hard initial &&
+               cp file-2-expect file-2 &&
+
+               test_must_fail git am$with3 000[124]-*.patch &&
+               git log --pretty=tformat:%s >actual &&
+               for i in 3 2 initial
+               do
+                       echo $i
+               done >expect &&
+               test_cmp expect actual
+       '
+
+       test_expect_success "am --abort goes back after failed am$with3" '
+               git-am --abort &&
+               git rev-parse HEAD >actual &&
+               git rev-parse initial >expect &&
+               test_cmp expect actual &&
+               test_cmp file-2-expect file-2 &&
+               git diff-index --exit-code --cached HEAD &&
+               test ! -f .git/rr-cache/MERGE_RR
+       '
+
+done
+
+test_done
index b5a4202998f51cd282ae46c7caec6e615ee47e3f..b68ab11f2915789cd04ac6bd43363aeab2079198 100755 (executable)
@@ -45,7 +45,7 @@ git commit -q -a -m second
 
 test_expect_success 'nothing recorded without rerere' '
        (rm -rf .git/rr-cache; git config rerere.enabled false) &&
-       ! git merge first &&
+       test_must_fail git merge first &&
        ! test -d .git/rr-cache
 '
 
@@ -54,7 +54,7 @@ test_expect_success 'conflicting merge' '
        git reset --hard &&
        mkdir .git/rr-cache &&
        git config --unset rerere.enabled &&
-       ! git merge first
+       test_must_fail git merge first
 '
 
 sha1=$(sed -e 's/      .*//' .git/MERGE_RR)
@@ -65,7 +65,7 @@ test_expect_success 'rerere.enabled works, too' '
        rm -rf .git/rr-cache &&
        git config rerere.enabled true &&
        git reset --hard &&
-       ! git merge first &&
+       test_must_fail git merge first &&
        grep ^=======$ $rr/preimage
 '
 
@@ -134,7 +134,7 @@ test_expect_success 'another conflicting merge' '
        git checkout -b third master &&
        git show second^:a1 | sed "s/To die: t/To die! T/" > a1 &&
        git commit -q -a -m third &&
-       ! git pull . first
+       test_must_fail git pull . first
 '
 
 git show first:a1 | sed 's/To die: t/To die! T/' > expect
@@ -189,7 +189,7 @@ test_expect_success 'file2 added differently in two branches' '
        echo Bello > file2 &&
        git add file2 &&
        git commit -m version2 &&
-       ! git merge fourth &&
+       test_must_fail git merge fourth &&
        sha1=$(sed -e "s/       .*//" .git/MERGE_RR) &&
        rr=.git/rr-cache/$sha1 &&
        echo Cello > file2 &&
index 983a39398f17dc2b261771e780e8c010f038a12a..645583f9d729cb04ea7bd9638b0c49c48128822e 100755 (executable)
@@ -266,7 +266,7 @@ test_expect_success \
 
 test_expect_success \
     'make sure index-pack detects the SHA1 collision' \
-    '! git-index-pack -o bad.idx test-3.pack'
+    'test_must_fail git-index-pack -o bad.idx test-3.pack'
 
 test_expect_success \
     'honor pack.packSizeLimit' \
index ecec5916346ce76936a807ebc769c3981fc0bf8c..0639772ac4e1e2c6563e793b16c2c10faf06758a 100755 (executable)
@@ -118,7 +118,7 @@ test_expect_success \
 
 test_expect_success \
     '[index v1] 4) confirm that the pack is actually corrupted' \
-    '! git fsck --full $commit'
+    'test_must_fail git fsck --full $commit'
 
 test_expect_success \
     '[index v1] 5) pack-objects happily reuses corrupted data' \
@@ -127,7 +127,7 @@ test_expect_success \
 
 test_expect_success \
     '[index v1] 6) newly created pack is BAD !' \
-    '! git verify-pack -v "test-4-${pack1}.pack"'
+    'test_must_fail git verify-pack -v "test-4-${pack1}.pack"'
 
 test_expect_success \
     '[index v2] 1) stream pack to repository' \
@@ -156,11 +156,11 @@ test_expect_success \
 
 test_expect_success \
     '[index v2] 4) confirm that the pack is actually corrupted' \
-    '! git fsck --full $commit'
+    'test_must_fail git fsck --full $commit'
 
 test_expect_success \
     '[index v2] 5) pack-objects refuses to reuse corrupted data' \
-    '! git pack-objects test-5 <obj-list'
+    'test_must_fail git pack-objects test-5 <obj-list'
 
 test_expect_success \
     '[index v2] 6) verify-pack detects CRC mismatch' \
@@ -173,7 +173,8 @@ test_expect_success \
      ( while read obj
        do git cat-file -p $obj >/dev/null || exit 1
        done <obj-list ) &&
-     err=$(! git verify-pack ".git/objects/pack/pack-${pack1}.pack" 2>&1) &&
+     err=$(test_must_fail git verify-pack \
+       ".git/objects/pack/pack-${pack1}.pack" 2>&1) &&
      echo "$err" | grep "CRC mismatch"'
 
 test_done
index 2fff3001530bdf3e6acc283042d432a0698cea03..ee769d6695ee91120671c485924d804f14c80424 100755 (executable)
@@ -61,7 +61,8 @@ EOF
 chmod u+x victim/.git/hooks/post-update
 
 test_expect_success push '
-    ! git-send-pack --force ./victim/.git master tofail >send.out 2>send.err
+       test_must_fail git-send-pack --force ./victim/.git \
+               master tofail >send.out 2>send.err
 '
 
 test_expect_success 'updated as expected' '
index 64fe2615acbd3368536b8a79c0b707561b3e16bd..c24003565d635722f07333bb662c8e102d577c9e 100755 (executable)
@@ -35,7 +35,9 @@ test_expect_success 'prepare pushable branches' '
        git commit -a -m aa-master
 '
 
-test_expect_success 'mixed-success push returns error' '! git push'
+test_expect_success 'mixed-success push returns error' '
+       test_must_fail git push
+'
 
 test_expect_success 'check tracking branches updated correctly after push' '
        test "$(git rev-parse origin/master)" = "$(git rev-parse master)"
index 46b2cb4e46d9d8bb2ae8cf2ea5d6b03331d4ac05..59e80a5ea253607bf83ac4eed670744df950eb81 100755 (executable)
@@ -17,7 +17,7 @@ test_expect_success 'setup' '
        git commit -a -m 2
 '
 
-test_expect_success 'push reports error' '! git push 2>stderr'
+test_expect_success 'push reports error' 'test_must_fail git push 2>stderr'
 
 test_expect_success 'individual ref reports error' 'grep rejected stderr'
 
index 140e8745811b9f25abfa2c9c24a0569f8dd39c66..362cf7e928090fb3752936317f78a4d128810127 100755 (executable)
@@ -177,6 +177,6 @@ test_expect_success "clone shallow object count" \
        "test \"count: 18\" = \"$(grep count count.shallow)\""
 
 test_expect_success "pull in shallow repo with missing merge base" \
-       "(cd shallow && ! git pull --depth 4 .. A)"
+       "(cd shallow && test_must_fail git pull --depth 4 .. A)"
 
 test_done
index 1e192a2207a4b56d477e8e3efc382c3a296ba776..be9ee9326fc4590dcc875e31b6cf64b800451bc5 100755 (executable)
@@ -164,7 +164,7 @@ test_expect_success 'prune' '
         git fetch origin &&
         git remote prune origin &&
         git rev-parse refs/remotes/origin/side2 &&
-        ! git rev-parse refs/remotes/origin/side)
+        test_must_fail git rev-parse refs/remotes/origin/side)
 '
 
 cat > test/expect << EOF
@@ -179,7 +179,7 @@ test_expect_success 'prune --dry-run' '
        (cd test &&
         git remote prune --dry-run origin > output &&
         git rev-parse refs/remotes/origin/side2 &&
-        ! git rev-parse refs/remotes/origin/side &&
+        test_must_fail git rev-parse refs/remotes/origin/side &&
        (cd ../one &&
         git branch -m side side2) &&
         test_cmp expect output)
@@ -194,10 +194,10 @@ test_expect_success 'add --mirror && prune' '
         git branch -m side2 side) &&
        (cd mirror &&
         git rev-parse --verify refs/heads/side2 &&
-        ! git rev-parse --verify refs/heads/side &&
+        test_must_fail git rev-parse --verify refs/heads/side &&
         git fetch origin &&
         git remote prune origin &&
-        ! git rev-parse --verify refs/heads/side2 &&
+        test_must_fail git rev-parse --verify refs/heads/side2 &&
         git rev-parse --verify refs/heads/side)
 '
 
@@ -212,10 +212,10 @@ test_expect_success 'add alt && prune' '
         git branch -m side side2) &&
        (cd alttst &&
         git rev-parse --verify refs/remotes/origin/side &&
-        ! git rev-parse --verify refs/remotes/origin/side2 &&
+        test_must_fail git rev-parse --verify refs/remotes/origin/side2 &&
         git fetch alt &&
         git remote prune alt &&
-        ! git rev-parse --verify refs/remotes/origin/side &&
+        test_must_fail git rev-parse --verify refs/remotes/origin/side &&
         git rev-parse --verify refs/remotes/origin/side2)
 '
 
@@ -320,7 +320,7 @@ test_expect_success '"remote show" does not show symbolic refs' '
 
 test_expect_success 'reject adding remote with an invalid name' '
 
-       ! git remote add some:url desired-name
+       test_must_fail git remote add some:url desired-name
 
 '
 
index df7750f7d1ede6e888ec3071397115022e067eb3..13d1d826c20293c26c739c70c0a36ed48bbb41d1 100755 (executable)
@@ -104,7 +104,7 @@ test_expect_success 'fetch must not resolve short tag name' '
        cd five &&
        git init &&
 
-       ! git fetch .. anno:five
+       test_must_fail git fetch .. anno:five
 
 '
 
@@ -117,7 +117,7 @@ test_expect_success 'fetch must not resolve short remote name' '
        cd six &&
        git init &&
 
-       ! git fetch .. six:six
+       test_must_fail git fetch .. six:six
 
 '
 
@@ -143,7 +143,7 @@ test_expect_success 'create bundle 2' '
 test_expect_success 'unbundle 1' '
        cd "$D/bundle" &&
        git checkout -b some-branch &&
-       ! git fetch "$D/bundle1" master:master
+       test_must_fail git fetch "$D/bundle1" master:master
 '
 
 test_expect_success 'bundle 1 has only 3 files ' '
@@ -236,7 +236,7 @@ test_expect_success 'fetch with a non-applying branch.<name>.merge' '
 
 # the strange name is: a\!'b
 test_expect_success 'quoting of a strangely named repo' '
-       ! git fetch "a\\!'\''b" > result 2>&1 &&
+       test_must_fail git fetch "a\\!'\''b" > result 2>&1 &&
        cat result &&
        grep "fatal: '\''a\\\\!'\''b'\''" result
 '
@@ -264,7 +264,7 @@ test_expect_success 'explicit fetch should not update tracking' '
                git fetch origin master &&
                n=$(git rev-parse --verify refs/remotes/origin/master) &&
                test "$o" = "$n" &&
-               ! git rev-parse --verify refs/remotes/origin/side
+               test_must_fail git rev-parse --verify refs/remotes/origin/side
        )
 '
 
@@ -278,7 +278,7 @@ test_expect_success 'explicit pull should not update tracking' '
                git pull origin master &&
                n=$(git rev-parse --verify refs/remotes/origin/master) &&
                test "$o" = "$n" &&
-               ! git rev-parse --verify refs/remotes/origin/side
+               test_must_fail git rev-parse --verify refs/remotes/origin/side
        )
 '
 
index 6805032a05cba00536f8d0621873741773a49f92..f0030ad00e4a6478fcb3ccfc503e576bd58003bd 100755 (executable)
@@ -178,7 +178,7 @@ test_expect_success 'failed (non-fast-forward) push with matching heads' '
        mk_test heads/master &&
        git push testrepo : &&
        git commit --amend -massaged &&
-       ! git push testrepo &&
+       test_must_fail git push testrepo &&
        check_push_result $the_commit heads/master &&
        git reset --hard $the_commit
 
@@ -374,7 +374,7 @@ test_expect_success 'push with +HEAD' '
 
        # Without force rewinding should fail
        git reset --hard HEAD^ &&
-       ! git push testrepo HEAD &&
+       test_must_fail git push testrepo HEAD &&
        check_push_result $the_commit heads/local &&
 
        # With force rewinding should succeed
@@ -448,7 +448,7 @@ test_expect_success 'push does not update local refs on failure' '
        git clone parent child &&
        (cd child &&
                echo two >foo && git commit -a -m two &&
-               ! git push &&
+               test_must_fail git push &&
                test $(git rev-parse master) != \
                        $(git rev-parse remotes/origin/master))
 
@@ -459,7 +459,7 @@ test_expect_success 'allow deleting an invalid remote ref' '
        pwd &&
        rm -f testrepo/.git/objects/??/* &&
        git push testrepo :refs/heads/master &&
-       (cd testrepo && ! git rev-parse --verify refs/heads/master)
+       (cd testrepo && test_must_fail git rev-parse --verify refs/heads/master)
 
 '
 
index 8b0509106951c5ddf2995862bc2a3887c963bfe6..1a15817cd5f8e838812723ad14dbec59a108680c 100755 (executable)
@@ -27,7 +27,7 @@ test_expect_success 'setup and corrupt repository' '
 '
 
 test_expect_success 'fsck fails' '
-       ! git fsck
+       test_must_fail git fsck
 '
 
 test_expect_success 'upload-pack fails due to error in pack-objects' '
@@ -46,7 +46,7 @@ test_expect_success 'corrupt repo differently' '
 '
 
 test_expect_success 'fsck fails' '
-       ! git fsck
+       test_must_fail git fsck
 '
 test_expect_success 'upload-pack fails due to error in rev-list' '
 
@@ -66,7 +66,7 @@ test_expect_success 'create empty repository' '
 
 test_expect_success 'fetch fails' '
 
-       ! git fetch .. master
+       test_must_fail git fetch .. master
 
 '
 
index 21dbb557b7cfad412ba1796519a7a63a403c35bb..f8c17cd96cc86ca8f2db2ff51467f712d65f8956 100755 (executable)
@@ -73,7 +73,7 @@ test_expect_failure 'create and delete remote branch' '
        git push origin :dev &&
        git branch -d -r origin/dev &&
        git fetch &&
-       ! git show-ref --verify refs/remotes/origin/dev
+       test_must_fail git show-ref --verify refs/remotes/origin/dev
 '
 
 stop_httpd
index acf34cec8f0ce5930f48a6e31ef84b8843097d74..3c013e2b6aa5c659c80134baf43c99e0d89e2e38 100755 (executable)
@@ -13,7 +13,7 @@ remove the directory before attempting a clone again.'
 
 test_expect_success \
     'clone of non-existent source should fail' \
-    '! git-clone foo bar'
+    'test_must_fail git-clone foo bar'
 
 test_expect_success \
     'failed clone should not leave a directory' \
@@ -29,7 +29,7 @@ test_create_repo foo
 # current path not to the target dir
 test_expect_success \
     'clone of non-existent (relative to $PWD) source should fail' \
-    '! git-clone ../foo baz'
+    'test_must_fail git-clone ../foo baz'
 
 test_expect_success \
     'clone should work now that source exists' \
index 74e9e6618e5b104c6d7e0731fd2772c0b95eefab..f674c48cab3e80d63b5a5831c667b8e08b542905 100755 (executable)
@@ -67,7 +67,7 @@ test_expect_success "merge result added missing LF" \
 
 cp test.txt backup.txt
 test_expect_success "merge with conflicts" \
-       "! git merge-file test.txt orig.txt new3.txt"
+       "test_must_fail git merge-file test.txt orig.txt new3.txt"
 
 cat > expect.txt << EOF
 <<<<<<< test.txt
@@ -90,7 +90,7 @@ test_expect_success "expected conflict markers" "test_cmp test.txt expect.txt"
 
 cp backup.txt test.txt
 test_expect_success "merge with conflicts, using -L" \
-       "! git merge-file -L 1 -L 2 test.txt orig.txt new3.txt"
+       "test_must_fail git merge-file -L 1 -L 2 test.txt orig.txt new3.txt"
 
 cat > expect.txt << EOF
 <<<<<<< 1
@@ -114,7 +114,7 @@ test_expect_success "expected conflict markers, with -L" \
 
 sed "s/ tu / TU /" < new1.txt > new5.txt
 test_expect_success "conflict in removed tail" \
-       "! git merge-file -p orig.txt new1.txt new5.txt > out"
+       "test_must_fail git merge-file -p orig.txt new1.txt new5.txt > out"
 
 cat > expect << EOF
 Dominus regit me,
@@ -135,7 +135,8 @@ EOF
 test_expect_success "expected conflict markers" "test_cmp expect out"
 
 test_expect_success 'binary files cannot be merged' '
-       ! git merge-file -p orig.txt ../test4012.png new1.txt 2> merge.err &&
+       test_must_fail git merge-file -p \
+               orig.txt ../test4012.png new1.txt 2> merge.err &&
        grep "Cannot merge binary files" merge.err
 '
 
@@ -144,7 +145,7 @@ sed -e "s/deerit.$/deerit,/" -e "s/me;$/me,/" < new5.txt > new7.txt
 
 test_expect_success 'MERGE_ZEALOUS simplifies non-conflicts' '
 
-       ! git merge-file -p new6.txt new5.txt new7.txt > output &&
+       test_must_fail git merge-file -p new6.txt new5.txt new7.txt > output &&
        test 1 = $(grep ======= < output | wc -l)
 
 '
@@ -154,7 +155,8 @@ sed -e 's/deerit./&\n\n\n\n/' -e "s/locavit,/locavit --/" < new7.txt > new9.txt
 
 test_expect_success 'ZEALOUS_ALNUM' '
 
-       ! git merge-file -p new8.txt new5.txt new9.txt > merge.out &&
+       test_must_fail git merge-file -p \
+               new8.txt new5.txt new9.txt > merge.out &&
        test 1 = $(grep ======= < merge.out | wc -l)
 
 '
index 6a6a13002d3dc66c043a43df910a79940b178da4..802d0d06ebddec9db6e3a109e689b3974f1e0ff1 100755 (executable)
@@ -60,7 +60,9 @@ git update-index a1 &&
 GIT_AUTHOR_DATE="2006-12-12 23:00:08" git commit -m F
 '
 
-test_expect_success "combined merge conflicts" "! git merge -m final G"
+test_expect_success "combined merge conflicts" "
+       test_must_fail git merge -m final G
+"
 
 cat > expect << EOF
 <<<<<<< HEAD:a1
@@ -90,7 +92,7 @@ test_expect_success 'refuse to merge binary files' '
        printf "\0\0" > binary-file &&
        git add binary-file &&
        git commit -m binary2 &&
-       ! git merge F > merge.out 2> merge.err &&
+       test_must_fail git merge F > merge.out 2> merge.err &&
        grep "Cannot merge binary files: HEAD:binary-file vs. F:binary-file" \
                merge.err
 '
index 6004deb43228836f61e0c4b8762a2511a2c1780a..fc58456a11eef7ecb4cf60d37a9e9d5cbe13f970 100755 (executable)
@@ -33,7 +33,7 @@ git-commit -m b-file'
 test_expect_success \
 'merge master into b-symlink, which has a different symbolic link' '
 git-checkout b-symlink &&
-! git-merge master'
+test_must_fail git-merge master'
 
 test_expect_success \
 'the merge result must be a file' '
@@ -42,7 +42,7 @@ test -f symlink'
 test_expect_success \
 'merge master into b-file, which has a file instead of a symbolic link' '
 git-reset --hard && git-checkout b-file &&
-! git-merge master'
+test_must_fail git-merge master'
 
 test_expect_success \
 'the merge result must be a file' '
@@ -52,7 +52,7 @@ test_expect_success \
 'merge b-file, which has a file instead of a symbolic link, into master' '
 git-reset --hard &&
 git-checkout master &&
-! git-merge b-file'
+test_must_fail git-merge b-file'
 
 test_expect_success \
 'the merge result must be a file' '
index 2328b699474cbe338def30179b07f25fa7fa357a..efc831363e7bfa2b38353f22ada751fd7db35a3e 100755 (executable)
@@ -26,7 +26,7 @@ test_expect_success 'final^1^1^1 = final^^^' "test $(git rev-parse final^1^1^1)
 test_expect_success 'final^1^2' "test $(git rev-parse start2) = $(git rev-parse final^1^2)"
 test_expect_success 'final^1^2 != final^1^1' "test $(git rev-parse final^1^2) != $(git rev-parse final^1^1)"
 test_expect_success 'final^1^3 not valid' "if git rev-parse --verify final^1^3; then false; else :; fi"
-test_expect_success '--verify start2^1' '! git rev-parse --verify start2^1'
+test_expect_success '--verify start2^1' 'test_must_fail git rev-parse --verify start2^1'
 test_expect_success '--verify start2^0' 'git rev-parse --verify start2^0'
 
 test_expect_success 'repack for next test' 'git repack -a -d'
index fa382c58da08a6eeca1aa51d4af47215e3e1c107..336cfaa1c5f1b6dd8a4189ee784e35a0651d52b5 100755 (executable)
@@ -80,7 +80,7 @@ test_expect_success \
 
 test_expect_success \
     'do not move directory over existing directory' \
-    'mkdir path0 && mkdir path0/path2 && ! git mv path2 path0'
+    'mkdir path0 && mkdir path0/path2 && test_must_fail git mv path2 path0'
 
 test_expect_success \
     'move into "."' \
@@ -149,7 +149,7 @@ test_expect_success 'absolute pathname outside should fail' '(
        >sub/file &&
        git add sub/file &&
 
-       ! git mv sub "$out/out" &&
+       test_must_fail git mv sub "$out/out" &&
        test -d sub &&
        ! test -d ../in &&
        git ls-files --error-unmatch sub/file
index 241c70dc66f71d9f53ddc6637e2f813020e740d6..bc7ce2cbbb712f890245688da03be96146a1d9ed 100755 (executable)
@@ -30,17 +30,17 @@ test_expect_success 'looking for a tag in an empty tree should fail' \
        '! (tag_exists mytag)'
 
 test_expect_success 'creating a tag in an empty tree should fail' '
-       ! git-tag mynotag &&
+       test_must_fail git-tag mynotag &&
        ! tag_exists mynotag
 '
 
 test_expect_success 'creating a tag for HEAD in an empty tree should fail' '
-       ! git-tag mytaghead HEAD &&
+       test_must_fail git-tag mytaghead HEAD &&
        ! tag_exists mytaghead
 '
 
 test_expect_success 'creating a tag for an unknown revision should fail' '
-       ! git-tag mytagnorev aaaaaaaaaaa &&
+       test_must_fail git-tag mytagnorev aaaaaaaaaaa &&
        ! tag_exists mytagnorev
 '
 
@@ -85,16 +85,16 @@ test_expect_success \
 
 test_expect_success \
        'trying to create a tag with the name of one existing should fail' \
-       '! git tag mytag'
+       'test_must_fail git tag mytag'
 
 test_expect_success \
        'trying to create a tag with a non-valid name should fail' '
        test `git-tag -l | wc -l` -eq 1 &&
-       ! git tag "" &&
-       ! git tag .othertag &&
-       ! git tag "other tag" &&
-       ! git tag "othertag^" &&
-       ! git tag "other~tag" &&
+       test_must_fail git tag "" &&
+       test_must_fail git tag .othertag &&
+       test_must_fail git tag "other tag" &&
+       test_must_fail git tag "othertag^" &&
+       test_must_fail git tag "other~tag" &&
        test `git-tag -l | wc -l` -eq 1
 '
 
@@ -107,7 +107,7 @@ test_expect_success 'creating a tag using HEAD directly should succeed' '
 
 test_expect_success 'trying to delete an unknown tag should fail' '
        ! tag_exists unknown-tag &&
-       ! git-tag -d unknown-tag
+       test_must_fail git-tag -d unknown-tag
 '
 
 cat >expect <<EOF
@@ -141,13 +141,13 @@ test_expect_success \
        'trying to delete two tags, existing and not, should fail in the 2nd' '
        tag_exists mytag &&
        ! tag_exists myhead &&
-       ! git-tag -d mytag anothertag &&
+       test_must_fail git-tag -d mytag anothertag &&
        ! tag_exists mytag &&
        ! tag_exists myhead
 '
 
 test_expect_success 'trying to delete an already deleted tag should fail' \
-       '! git-tag -d mytag'
+       'test_must_fail git-tag -d mytag'
 
 # listing various tags with pattern matching:
 
@@ -266,15 +266,15 @@ test_expect_success \
 '
 
 test_expect_success 'trying to verify an unknown tag should fail' \
-       '! git-tag -v unknown-tag'
+       'test_must_fail git-tag -v unknown-tag'
 
 test_expect_success \
        'trying to verify a non-annotated and non-signed tag should fail' \
-       '! git-tag -v non-annotated-tag'
+       'test_must_fail git-tag -v non-annotated-tag'
 
 test_expect_success \
        'trying to verify many non-annotated or unknown tags, should fail' \
-       '! git-tag -v unknown-tag1 non-annotated-tag unknown-tag2'
+       'test_must_fail git-tag -v unknown-tag1 non-annotated-tag unknown-tag2'
 
 # creating annotated tags:
 
@@ -334,7 +334,7 @@ test_expect_success \
        'trying to create a tag with a non-existing -F file should fail' '
        ! test -f nonexistingfile &&
        ! tag_exists notag &&
-       ! git-tag -F nonexistingfile notag &&
+       test_must_fail git-tag -F nonexistingfile notag &&
        ! tag_exists notag
 '
 
@@ -343,11 +343,12 @@ test_expect_success \
        echo "message file 1" >msgfile1 &&
        echo "message file 2" >msgfile2 &&
        ! tag_exists msgtag &&
-       ! git-tag -m "message 1" -F msgfile1 msgtag &&
+       test_must_fail git-tag -m "message 1" -F msgfile1 msgtag &&
        ! tag_exists msgtag &&
-       ! git-tag -F msgfile1 -m "message 1" msgtag &&
+       test_must_fail git-tag -F msgfile1 -m "message 1" msgtag &&
        ! tag_exists msgtag &&
-       ! git-tag -m "message 1" -F msgfile1 -m "message 2" msgtag &&
+       test_must_fail git-tag -m "message 1" -F msgfile1 \
+               -m "message 2" msgtag &&
        ! tag_exists msgtag
 '
 
@@ -591,19 +592,19 @@ fi
 test_expect_success \
        'trying to verify an annotated non-signed tag should fail' '
        tag_exists annotated-tag &&
-       ! git-tag -v annotated-tag
+       test_must_fail git-tag -v annotated-tag
 '
 
 test_expect_success \
        'trying to verify a file-annotated non-signed tag should fail' '
        tag_exists file-annotated-tag &&
-       ! git-tag -v file-annotated-tag
+       test_must_fail git-tag -v file-annotated-tag
 '
 
 test_expect_success \
        'trying to verify two annotated non-signed tags should fail' '
        tag_exists annotated-tag file-annotated-tag &&
-       ! git-tag -v annotated-tag file-annotated-tag
+       test_must_fail git-tag -v annotated-tag file-annotated-tag
 '
 
 # creating and verifying signed tags:
@@ -651,13 +652,14 @@ test_expect_success 'sign with a given key id' '
 
 test_expect_success 'sign with an unknown id (1)' '
 
-       ! git tag -u author@example.com -m "Another message" o-signed-tag
+       test_must_fail git tag -u author@example.com \
+               -m "Another message" o-signed-tag
 
 '
 
 test_expect_success 'sign with an unknown id (2)' '
 
-       ! git tag -u DEADBEEF -m "Another message" o-signed-tag
+       test_must_fail git tag -u DEADBEEF -m "Another message" o-signed-tag
 
 '
 
@@ -718,7 +720,7 @@ test_expect_success \
        'trying to create a signed tag with non-existing -F file should fail' '
        ! test -f nonexistingfile &&
        ! tag_exists nosigtag &&
-       ! git-tag -s -F nonexistingfile nosigtag &&
+       test_must_fail git-tag -s -F nonexistingfile nosigtag &&
        ! tag_exists nosigtag
 '
 
@@ -730,10 +732,11 @@ test_expect_success 'verifying two signed tags in one command should succeed' \
 
 test_expect_success \
        'verifying many signed and non-signed tags should fail' '
-       ! git-tag -v signed-tag annotated-tag &&
-       ! git-tag -v file-annotated-tag file-signed-tag &&
-       ! git-tag -v annotated-tag file-signed-tag file-annotated-tag &&
-       ! git-tag -v signed-tag annotated-tag file-signed-tag
+       test_must_fail git-tag -v signed-tag annotated-tag &&
+       test_must_fail git-tag -v file-annotated-tag file-signed-tag &&
+       test_must_fail git-tag -v annotated-tag \
+               file-signed-tag file-annotated-tag &&
+       test_must_fail git-tag -v signed-tag annotated-tag file-signed-tag
 '
 
 test_expect_success 'verifying a forged tag should fail' '
@@ -741,7 +744,7 @@ test_expect_success 'verifying a forged tag should fail' '
                sed -e "s/signed-tag/forged-tag/" |
                git mktag) &&
        git tag forged-tag $forged &&
-       ! git-tag -v forged-tag
+       test_must_fail git-tag -v forged-tag
 '
 
 # blank and empty messages for signed tags:
@@ -1031,7 +1034,7 @@ test_expect_success \
 git config user.signingkey BobTheMouse
 test_expect_success \
        'git-tag -s fails if gpg is misconfigured' \
-       '! git tag -s -m tail tag-gpg-failure'
+       'test_must_fail git tag -s -m tail tag-gpg-failure'
 git config --unset user.signingkey
 
 # try to verify without gpg:
@@ -1039,7 +1042,7 @@ git config --unset user.signingkey
 rm -rf gpghome
 test_expect_success \
        'verify signed tag fails when public key is not present' \
-       '! git-tag -v signed-tag'
+       'test_must_fail git-tag -v signed-tag'
 
 test_expect_success \
        'git-tag -a fails if tag annotation is empty' '
index 96d15083fb5ac540a0825b8c00dc43c8843a6dec..29f5678b4c93485ad492fa865a5da58a3cc05b7c 100755 (executable)
@@ -52,10 +52,10 @@ secondfile:
 EOF
 
 test_expect_success 'giving a non existing revision should fail' '
-       ! git reset aaaaaa &&
-       ! git reset --mixed aaaaaa &&
-       ! git reset --soft aaaaaa &&
-       ! git reset --hard aaaaaa &&
+       test_must_fail git reset aaaaaa &&
+       test_must_fail git reset --mixed aaaaaa &&
+       test_must_fail git reset --soft aaaaaa &&
+       test_must_fail git reset --hard aaaaaa &&
        check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
 '
 
@@ -63,29 +63,29 @@ test_expect_success 'reset --soft with unmerged index should fail' '
        touch .git/MERGE_HEAD &&
        echo "100644 44c5b5884550c17758737edcced463447b91d42b 1 un" |
                git update-index --index-info &&
-       ! git reset --soft HEAD &&
+       test_must_fail git reset --soft HEAD &&
        rm .git/MERGE_HEAD &&
        git rm --cached -- un
 '
 
 test_expect_success \
        'giving paths with options different than --mixed should fail' '
-       ! git reset --soft -- first &&
-       ! git reset --hard -- first &&
-       ! git reset --soft HEAD^ -- first &&
-       ! git reset --hard HEAD^ -- first &&
+       test_must_fail git reset --soft -- first &&
+       test_must_fail git reset --hard -- first &&
+       test_must_fail git reset --soft HEAD^ -- first &&
+       test_must_fail git reset --hard HEAD^ -- first &&
        check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
 '
 
 test_expect_success 'giving unrecognized options should fail' '
-       ! git reset --other &&
-       ! git reset -o &&
-       ! git reset --mixed --other &&
-       ! git reset --mixed -o &&
-       ! git reset --soft --other &&
-       ! git reset --soft -o &&
-       ! git reset --hard --other &&
-       ! git reset --hard -o &&
+       test_must_fail git reset --other &&
+       test_must_fail git reset -o &&
+       test_must_fail git reset --mixed --other &&
+       test_must_fail git reset --mixed -o &&
+       test_must_fail git reset --soft --other &&
+       test_must_fail git reset --soft -o &&
+       test_must_fail git reset --hard --other &&
+       test_must_fail git reset --hard -o &&
        check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
 '
 
@@ -102,8 +102,8 @@ test_expect_success \
        echo "3rd line in branch2" >>secondfile &&
        git commit -a -m "change in branch2" &&
 
-       ! git merge branch1 &&
-       ! git reset --soft &&
+       test_must_fail git merge branch1 &&
+       test_must_fail git reset --soft &&
 
        printf "1st line 2nd file\n2nd line 2nd file\n3rd line" >secondfile &&
        git commit -a -m "the change in branch2" &&
@@ -126,7 +126,7 @@ test_expect_success \
        echo "3rd line in branch4" >>secondfile &&
 
        git checkout -m branch3 &&
-       ! git reset --soft &&
+       test_must_fail git reset --soft &&
 
        printf "1st line 2nd file\n2nd line 2nd file\n3rd line" >secondfile &&
        git commit -a -m "the line in branch3" &&
@@ -326,7 +326,7 @@ test_expect_success '--hard reset to HEAD should clear a failed merge' '
        echo "3rd line in branch2" >>secondfile &&
        git commit -a -m "change in branch2" &&
 
-       ! git pull . branch1 &&
+       test_must_fail git pull . branch1 &&
        git reset --hard &&
        check_changes 77abb337073fb4369a7ad69ff6f5ec0e4d6b54bb
 '
@@ -388,7 +388,7 @@ test_expect_success 'test --mixed <paths>' '
        echo 4 > file4 &&
        echo 5 > file1 &&
        git add file1 file3 file4 &&
-       ! git reset HEAD -- file1 file2 file3 &&
+       test_must_fail git reset HEAD -- file1 file2 file3 &&
        git diff > output &&
        test_cmp output expect &&
        git diff --cached > output &&
@@ -402,11 +402,11 @@ test_expect_success 'test resetting the index at give paths' '
        >sub/file2 &&
        git update-index --add sub/file1 sub/file2 &&
        T=$(git write-tree) &&
-       ! git reset HEAD sub/file2 &&
+       test_must_fail git reset HEAD sub/file2 &&
        U=$(git write-tree) &&
        echo "$T" &&
        echo "$U" &&
-       ! git diff-index --cached --exit-code "$T" &&
+       test_must_fail git diff-index --cached --exit-code "$T" &&
        test "$T" != "$U"
 
 '
@@ -419,7 +419,7 @@ test_expect_success 'resetting an unmodified path is a no-op' '
 '
 
 cat > expect << EOF
-file2: needs update
+file2: locally modified
 EOF
 
 test_expect_success '--mixed refreshes the index' '
index b25a77f910fcdd589775ce901bdf878c23677dd4..cdecebe456c7a9cf30465b112a24ce7bcf76f344 100755 (executable)
@@ -17,7 +17,7 @@ test_expect_success 'setup bare' '
 '
 
 test_expect_success 'hard reset is not allowed' '
-       ! git reset --hard HEAD^
+       test_must_fail  git reset --hard HEAD^
 '
 
 test_expect_success 'soft reset is allowed' '
index bd7723970869aa0ce8f48b83fdc568821fdf737c..2b51c0d7d8ab727a5fb0be8338938f1d3b2eb6a3 100755 (executable)
@@ -316,14 +316,14 @@ test_expect_success 'git-clean -d -X' '
 test_expect_success 'clean.requireForce defaults to true' '
 
        git config --unset clean.requireForce &&
-       ! git-clean
+       test_must_fail git clean
 
 '
 
 test_expect_success 'clean.requireForce' '
 
        git config clean.requireForce true &&
-       ! git-clean
+       test_must_fail git clean
 
 '
 
index 6c7b9024822024ca24f7d1ddea63c94d3aa016b0..cbc0c34ce2487959ef0e8f89f7c2a5d4a68be826 100755 (executable)
@@ -75,7 +75,7 @@ test_expect_success 'init should register submodule url in .git/config' '
        then
                echo "[OOPS] init succeeded but submodule url is wrong"
                false
-       elif ! git config submodule.example.url ./.subrepo
+       elif test_must_fail git config submodule.example.url ./.subrepo
        then
                echo "[OOPS] init succeeded but update of url failed"
                false
index 5becb3ec5481b2407a18e59a426241be8f684051..f919c8d34de41b2ec3fe08c217dd2c6276cf8472 100755 (executable)
@@ -71,7 +71,7 @@ test_expect_success 'rebase with dirty file and submodule fails' '
        test_tick &&
        git commit -m rewrite file &&
        echo dirty > file &&
-       ! git rebase --onto HEAD~2 HEAD^
+       test_must_fail git rebase --onto HEAD~2 HEAD^
 
 '
 
index baed6ce96beb260a32e027dd573313c82202ea7b..d89f91a6fb7fa12d41cc4a346829bff7cbd3e76b 100755 (executable)
@@ -23,12 +23,12 @@ test_expect_success 'a basic commit in an empty tree should succeed' '
 test_expect_success 'nonexistent template file should return error' '
        echo changes >> foo &&
        git add foo &&
-       ! git commit --template "$PWD"/notexist
+       test_must_fail git commit --template "$PWD"/notexist
 '
 
 test_expect_success 'nonexistent template file in config should return error' '
        git config commit.template "$PWD"/notexist &&
-       ! git commit &&
+       test_must_fail git commit &&
        git config --unset commit.template
 '
 
@@ -37,12 +37,12 @@ TEMPLATE="$PWD"/template
 
 test_expect_success 'unedited template should not commit' '
        echo "template line" > "$TEMPLATE" &&
-       ! git commit --template "$TEMPLATE"
+       test_must_fail git commit --template "$TEMPLATE"
 '
 
 test_expect_success 'unedited template with comments should not commit' '
        echo "# comment in template" >> "$TEMPLATE" &&
-       ! git commit --template "$TEMPLATE"
+       test_must_fail git commit --template "$TEMPLATE"
 '
 
 test_expect_success 'a Signed-off-by line by itself should not commit' '
index d3370ff7ff66240f14b8231de7ba0198e73e8deb..0edd9ddf73b7053c21595ce1ac1dd157c77d1bca 100755 (executable)
@@ -19,7 +19,7 @@ test_expect_success \
 
 test_expect_success \
        "fail initial amend" \
-       "! git-commit --amend"
+       "test_must_fail git-commit --amend"
 
 test_expect_success \
        "initial commit" \
@@ -27,16 +27,16 @@ test_expect_success \
 
 test_expect_success \
        "invalid options 1" \
-       "! git-commit -m foo -m bar -F file"
+       "test_must_fail git-commit -m foo -m bar -F file"
 
 test_expect_success \
        "invalid options 2" \
-       "! git-commit -C HEAD -m illegal"
+       "test_must_fail git-commit -C HEAD -m illegal"
 
 test_expect_success \
        "using paths with -a" \
        "echo King of the bongo >file &&
-       ! git-commit -m foo -a file"
+       test_must_fail git-commit -m foo -a file"
 
 test_expect_success \
        "using paths with --interactive" \
@@ -45,11 +45,11 @@ test_expect_success \
 
 test_expect_success \
        "using invalid commit with -C" \
-       "! git-commit -C bogus"
+       "test_must_fail git-commit -C bogus"
 
 test_expect_success \
        "testing nothing to commit" \
-       "! git-commit -m initial"
+       "test_must_fail git-commit -m initial"
 
 test_expect_success \
        "next commit" \
@@ -59,7 +59,7 @@ test_expect_success \
 test_expect_success \
        "commit message from non-existing file" \
        "echo 'more bongo: bongo bongo bongo bongo' >file && \
-        ! git-commit -F gah -a"
+        test_must_fail git-commit -F gah -a"
 
 # Empty except stray tabs and spaces on a few lines.
 sed -e 's/@$//' >msg <<EOF
@@ -70,7 +70,7 @@ Signed-off-by: hula
 EOF
 test_expect_success \
        "empty commit message" \
-       "! git-commit -F msg -a"
+       "test_must_fail git-commit -F msg -a"
 
 test_expect_success \
        "commit message from file" \
@@ -91,7 +91,7 @@ test_expect_success \
 test_expect_success \
        "passing -m and -F" \
        "echo 'enough with the bongos' >file && \
-        ! git-commit -F msg -m amending ."
+        test_must_fail git-commit -F msg -m amending ."
 
 test_expect_success \
        "using message from other commit" \
index 2dd5a5e30279e6c3e5ac2be9425c19328a65aff1..b06909599564a1c8afa027b0f9c71ef6bb61d6e4 100755 (executable)
@@ -56,7 +56,7 @@ test_expect_success 'with failing hook' '
 
        echo "another" >> file &&
        git add file &&
-       ! git commit -m "another"
+       test_must_fail git commit -m "another"
 
 '
 
index 88577af9535b5ed7027ec2b6b752df3b78d7bab4..47680e6df41c2bc14f23514b010a8aefb3fedcd7 100755 (executable)
@@ -105,7 +105,7 @@ test_expect_success 'with failing hook' '
 
        echo "another" >> file &&
        git add file &&
-       ! git commit -m "another"
+       test_must_fail git commit -m "another"
 
 '
 
index d4cf6289a4c06ec9436235b7325379f26a388e06..5eeb6c2b2708d582a6e86cd2e06e2b00b7b7b391 100755 (executable)
@@ -126,7 +126,7 @@ verify_merge() {
                echo "[OOPS] unmerged files"
                false
        fi &&
-       if ! git diff --exit-code
+       if test_must_fail git diff --exit-code
        then
                echo "[OOPS] working tree != index"
                false
@@ -222,36 +222,12 @@ test_expect_success 'setup' '
 test_debug 'gitk --all'
 
 test_expect_success 'test option parsing' '
-       if git merge -$ c1
-       then
-               echo "[OOPS] -$ accepted"
-               false
-       fi &&
-       if git merge --no-such c1
-       then
-               echo "[OOPS] --no-such accepted"
-               false
-       fi &&
-       if git merge -s foobar c1
-       then
-               echo "[OOPS] -s foobar accepted"
-               false
-       fi &&
-       if git merge -s=foobar c1
-       then
-               echo "[OOPS] -s=foobar accepted"
-               false
-       fi &&
-       if git merge -m
-       then
-               echo "[OOPS] missing commit msg accepted"
-               false
-       fi &&
-       if git merge
-       then
-               echo "[OOPS] missing commit references accepted"
-               false
-       fi
+       test_must_fail git merge -$ c1 &&
+       test_must_fail git merge --no-such c1 &&
+       test_must_fail git merge -s foobar c1 &&
+       test_must_fail git merge -s=foobar c1 &&
+       test_must_fail git merge -m &&
+       test_must_fail git merge
 '
 
 test_expect_success 'merge c0 with c1' '
index 6b0483f3e9b77e0bdc42b0c7421db6c60868cf5d..9285071c473dcfe7d37845d01ba20226b5ab585d 100755 (executable)
@@ -35,7 +35,7 @@ test_expect_success 'custom mergetool' '
     git config mergetool.mytool.cmd "cat \"\$REMOTE\" >\"\$MERGED\"" &&
     git config mergetool.mytool.trustExitCode true &&
        git checkout branch1 &&
-    ! git merge master >/dev/null 2>&1 &&
+    test_must_fail git merge master >/dev/null 2>&1 &&
     ( yes "" | git mergetool file1>/dev/null 2>&1 ) &&
     ( yes "" | git mergetool file2>/dev/null 2>&1 ) &&
     test "$(cat file1)" = "master updated" &&
index 3e4eb63f1c4d63d6ff38c79ff1f7a47fa3aa1597..1c857cf4ab6e359d7009d2c6b5018bb61c916e93 100755 (executable)
@@ -13,7 +13,7 @@ test_expect_success \
 
 test_expect_success \
     'Setup helper tool' \
-    '(echo "#!/bin/sh"
+    '(echo "#!$SHELL_PATH"
       echo shift
       echo output=1
       echo "while test -f commandline\$output; do output=\$((\$output+1)); done"
@@ -91,7 +91,7 @@ test_expect_success 'reject long lines' '
        clean_fake_sendmail &&
        cp $patches longline.patch &&
        echo $z512$z512 >>longline.patch &&
-       ! git send-email \
+       test_must_fail git send-email \
                --from="Example <nobody@example.com>" \
                --to=nobody@example.com \
                --smtp-server="$(pwd)/fake.sendmail" \
@@ -138,7 +138,7 @@ test_expect_success 'Valid In-Reply-To when prompting' '
 '
 
 test_expect_success 'setup fake editor' '
-       (echo "#!/bin/sh" &&
+       (echo "#!$SHELL_PATH" &&
         echo "echo fake edit >>\"\$1\""
        ) >fake-editor &&
        chmod +x fake-editor
@@ -235,7 +235,7 @@ test_expect_success 'sendemail.cc unset' '
 
 test_expect_success '--compose adds MIME for utf8 body' '
        clean_fake_sendmail &&
-       (echo "#!/bin/sh" &&
+       (echo "#!$SHELL_PATH" &&
         echo "echo utf8 body: àéìöú >>\"\$1\""
        ) >fake-editor-utf8 &&
        chmod +x fake-editor-utf8 &&
@@ -254,7 +254,7 @@ test_expect_success '--compose adds MIME for utf8 body' '
 
 test_expect_success '--compose respects user mime type' '
        clean_fake_sendmail &&
-       (echo "#!/bin/sh" &&
+       (echo "#!$SHELL_PATH" &&
         echo "(echo MIME-Version: 1.0"
         echo " echo Content-Type: text/plain\\; charset=iso-8859-1"
         echo " echo Content-Transfer-Encoding: 8bit"
index 3bc6164125f683d26213035ee9b1ea9199be5792..843a5013b96c675a629bd7f738eca220861e6ff8 100755 (executable)
@@ -63,7 +63,7 @@ test_expect_success "$name" "
        git update-index --remove dir/file &&
        git update-index --add dir/file/file &&
        git commit -m '$name' &&
-       ! git-svn set-tree --find-copies-harder --rmdir \
+       test_must_fail git-svn set-tree --find-copies-harder --rmdir \
                remotes/git-svn..mybranch" || true
 
 
@@ -77,7 +77,7 @@ test_expect_success "$name" '
        git update-index --remove -- bar/zzz &&
        git update-index --add -- bar &&
        git commit -m "$name" &&
-       ! git-svn set-tree --find-copies-harder --rmdir \
+       test_must_fail git-svn set-tree --find-copies-harder --rmdir \
                remotes/git-svn..mybranch2' || true
 
 
@@ -91,7 +91,7 @@ test_expect_success "$name" '
        echo yyy > bar/zzz/yyy &&
        git update-index --add bar/zzz/yyy &&
        git commit -m "$name" &&
-       ! git-svn set-tree --find-copies-harder --rmdir \
+       test_must_fail git-svn set-tree --find-copies-harder --rmdir \
                remotes/git-svn..mybranch3' || true
 
 
@@ -105,7 +105,7 @@ test_expect_success "$name" '
        echo asdf > dir &&
        git update-index --add -- dir &&
        git commit -m "$name" &&
-       ! git-svn set-tree --find-copies-harder --rmdir \
+       test_must_fail git-svn set-tree --find-copies-harder --rmdir \
                remotes/git-svn..mybranch4' || true
 
 
@@ -216,7 +216,7 @@ test_expect_success "$name" "test_cmp a expected"
 test_expect_success 'exit if remote refs are ambigious' "
         git config --add svn-remote.svn.fetch \
                               bar:refs/remotes/git-svn &&
-       ! git-svn migrate
+       test_must_fail git-svn migrate
 "
 
 test_expect_success 'exit if init-ing a would clobber a URL' '
@@ -224,7 +224,7 @@ test_expect_success 'exit if init-ing a would clobber a URL' '
         svn mkdir -m "mkdir bar" "${svnrepo}2/bar" &&
         git config --unset svn-remote.svn.fetch \
                                 "^bar:refs/remotes/git-svn$" &&
-       ! git-svn init "${svnrepo}2/bar"
+       test_must_fail git-svn init "${svnrepo}2/bar"
         '
 
 test_expect_success \
index 27a65e05df20c2695b9fb849be62d715c968a433..08bf1f08e331790d1a4e2fd1c698ecd5ea860e41 100755 (executable)
@@ -27,7 +27,7 @@ test_expect_success 'commit change from svn side' '
 test_expect_success 'commit conflicting change from git' '
        echo second line from git >> file &&
        git commit -a -m "second line from git" &&
-       ! git-svn commit-diff -r1 HEAD~1 HEAD "$svnrepo"
+       test_must_fail git-svn commit-diff -r1 HEAD~1 HEAD "$svnrepo"
 '
 
 test_expect_success 'commit complementing change from git' '
@@ -52,7 +52,7 @@ test_expect_success 'dcommit fails to commit because of conflict' '
        rm -rf t.svn &&
        echo "fourth line from git" >> file &&
        git commit -a -m "fourth line from git" &&
-       ! git-svn dcommit
+       test_must_fail git-svn dcommit
        '
 
 test_expect_success 'dcommit does the svn equivalent of an index merge' "
@@ -83,7 +83,7 @@ test_expect_success 'multiple dcommit from git-svn will not clobber svn' "
        git commit -a -m 'new file' &&
        echo clobber > file &&
        git commit -a -m 'clobber' &&
-       ! git svn dcommit
+       test_must_fail git svn dcommit
        "
 
 
index f8f4718c361fc16749fd82fe9bd797643a7a399b..bc37db9d62071ba92463276524675964c3e91593 100755 (executable)
@@ -57,7 +57,7 @@ test_expect_success 'change file but in unrelated area' "
 test_expect_success 'attempt to dcommit with a dirty index' '
        echo foo >>file &&
        git add file &&
-       ! git svn dcommit
+       test_must_fail git svn dcommit
 '
 
 test_done
index b1dc32d056929ee0cafbd94f6df52669350935b2..3e32e84e6cd32413f98b5189f869bfb8f0a7f354 100755 (executable)
@@ -100,7 +100,7 @@ test_expect_success \
      git commit -a -m "generation 2" &&
      id=$(git rev-list --max-count=1 HEAD) &&
      (cd "$CVSWORK" &&
-     ! git cvsexportcommit -c $id
+     test_must_fail git cvsexportcommit -c $id
      )'
 
 #test_expect_success \
@@ -112,7 +112,7 @@ test_expect_success \
 #     git commit -a -m "generation 3" &&
 #     id=$(git rev-list --max-count=1 HEAD) &&
 #     (cd "$CVSWORK" &&
-#     ! git cvsexportcommit -c $id
+#     test_must_fail git cvsexportcommit -c $id
 #     )'
 
 # We reuse the state from two tests back here
@@ -222,7 +222,7 @@ test_expect_success \
       git commit -a -m "Update two" &&
       id=$(git rev-list --max-count=1 HEAD) &&
       (cd "$CVSWORK" &&
-      ! git-cvsexportcommit -c $id
+      test_must_fail git-cvsexportcommit -c $id
       )'
 
 case "$(git config --bool core.filemode)" in
index 5edf56f198dc25b9db47ff363fe49958e5299162..1fc06c5a23b50d54c33755a9fce4ddd9ed3b9c79 100755 (executable)
@@ -166,7 +166,7 @@ M 755 0000000000000000000000000000000000000001 zero1
 
 INPUT_END
 test_expect_success 'B: fail on invalid blob sha1' '
-    ! git-fast-import <input
+    test_must_fail git-fast-import <input
 '
 rm -f .git/objects/pack_* .git/objects/index_*
 
@@ -181,7 +181,7 @@ from refs/heads/master
 
 INPUT_END
 test_expect_success 'B: fail on invalid branch name ".badbranchname"' '
-    ! git-fast-import <input
+    test_must_fail git-fast-import <input
 '
 rm -f .git/objects/pack_* .git/objects/index_*
 
@@ -196,7 +196,7 @@ from refs/heads/master
 
 INPUT_END
 test_expect_success 'B: fail on invalid branch name "bad[branch]name"' '
-    ! git-fast-import <input
+    test_must_fail git-fast-import <input
 '
 rm -f .git/objects/pack_* .git/objects/index_*
 
@@ -340,7 +340,7 @@ from refs/heads/branch^0
 
 INPUT_END
 test_expect_success 'E: rfc2822 date, --date-format=raw' '
-    ! git-fast-import --date-format=raw <input
+    test_must_fail git-fast-import --date-format=raw <input
 '
 test_expect_success \
     'E: rfc2822 date, --date-format=rfc2822' \
@@ -918,4 +918,156 @@ test_expect_success \
         grep "progress " <input >expect &&
         test_cmp expect actual'
 
+###
+### series P (gitlinks)
+###
+
+cat >input <<INPUT_END
+blob
+mark :1
+data 10
+test file
+
+reset refs/heads/sub
+commit refs/heads/sub
+mark :2
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data 12
+sub_initial
+M 100644 :1 file
+
+blob
+mark :3
+data <<DATAEND
+[submodule "sub"]
+       path = sub
+       url = "`pwd`/sub"
+DATAEND
+
+commit refs/heads/subuse1
+mark :4
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data 8
+initial
+from refs/heads/master
+M 100644 :3 .gitmodules
+M 160000 :2 sub
+
+blob
+mark :5
+data 20
+test file
+more data
+
+commit refs/heads/sub
+mark :6
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data 11
+sub_second
+from :2
+M 100644 :5 file
+
+commit refs/heads/subuse1
+mark :7
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data 7
+second
+from :4
+M 160000 :6 sub
+
+INPUT_END
+
+test_expect_success \
+       'P: supermodule & submodule mix' \
+       'git-fast-import <input &&
+        git checkout subuse1 &&
+        rm -rf sub && mkdir sub && cd sub &&
+        git init &&
+        git fetch .. refs/heads/sub:refs/heads/master &&
+        git checkout master &&
+        cd .. &&
+        git submodule init &&
+        git submodule update'
+
+SUBLAST=$(git-rev-parse --verify sub)
+SUBPREV=$(git-rev-parse --verify sub^)
+
+cat >input <<INPUT_END
+blob
+mark :1
+data <<DATAEND
+[submodule "sub"]
+       path = sub
+       url = "`pwd`/sub"
+DATAEND
+
+commit refs/heads/subuse2
+mark :2
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data 8
+initial
+from refs/heads/master
+M 100644 :1 .gitmodules
+M 160000 $SUBPREV sub
+
+commit refs/heads/subuse2
+mark :3
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data 7
+second
+from :2
+M 160000 $SUBLAST sub
+
+INPUT_END
+
+test_expect_success \
+       'P: verbatim SHA gitlinks' \
+       'git branch -D sub &&
+        git gc && git prune &&
+        git-fast-import <input &&
+        test $(git-rev-parse --verify subuse2) = $(git-rev-parse --verify subuse1)'
+
+test_tick
+cat >input <<INPUT_END
+commit refs/heads/subuse3
+mark :1
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+corrupt
+COMMIT
+
+from refs/heads/subuse2
+M 160000 inline sub
+data <<DATA
+$SUBPREV
+DATA
+
+INPUT_END
+
+test_expect_success 'P: fail on inline gitlink' '
+    ! git-fast-import <input'
+
+test_tick
+cat >input <<INPUT_END
+blob
+mark :1
+data <<DATA
+$SUBPREV
+DATA
+
+commit refs/heads/subuse3
+mark :2
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+corrupt
+COMMIT
+
+from refs/heads/subuse2
+M 160000 :1 sub
+
+INPUT_END
+
+test_expect_success 'P: fail on blob mark in gitlink' '
+    ! git-fast-import <input'
+
 test_done
index f1bc5ceef0453fcdf711afd6225a5f0cd5dc69e5..8324f6e3bd214e6c735051b52ca095970d9f61f1 100755 (executable)
@@ -59,7 +59,7 @@ test_expect_success 'fast-export master~2..master' '
                 test $MASTER != $(git rev-parse --verify refs/heads/partial) &&
                 git diff master..partial &&
                 git diff master^..partial^ &&
-                ! git rev-parse partial~2)
+                test_must_fail git rev-parse partial~2)
 
 '
 
@@ -125,7 +125,7 @@ test_expect_success 'set up faked signed tag' '
 
 test_expect_success 'signed-tags=abort' '
 
-       ! git fast-export --signed-tags=abort sign-your-name
+       test_must_fail git fast-export --signed-tags=abort sign-your-name
 
 '
 
@@ -143,4 +143,46 @@ test_expect_success 'signed-tags=strip' '
 
 '
 
+test_expect_success 'setup submodule' '
+
+       git checkout -f master &&
+       mkdir sub &&
+       cd sub &&
+       git init  &&
+       echo test file > file &&
+       git add file &&
+       git commit -m sub_initial &&
+       cd .. &&
+       git submodule add "`pwd`/sub" sub &&
+       git commit -m initial &&
+       test_tick &&
+       cd sub &&
+       echo more data >> file &&
+       git add file &&
+       git commit -m sub_second &&
+       cd .. &&
+       git add sub &&
+       git commit -m second
+
+'
+
+test_expect_success 'submodule fast-export | fast-import' '
+
+       SUBENT1=$(git ls-tree master^ sub) &&
+       SUBENT2=$(git ls-tree master sub) &&
+       rm -rf new &&
+       mkdir new &&
+       git --git-dir=new/.git init &&
+       git fast-export --signed-tags=strip --all |
+       (cd new &&
+        git fast-import &&
+        test "$SUBENT1" = "$(git ls-tree refs/heads/master^ sub)" &&
+        test "$SUBENT2" = "$(git ls-tree refs/heads/master sub)" &&
+        git checkout master &&
+        git submodule init &&
+        git submodule update &&
+        cmp sub/file ../sub/file)
+
+'
+
 test_done
index e97aaa6c2a2fdcc476e538ffe903cef65274c280..4b91f8d4c45dad075d69028c9c70aa9cb1959e2b 100755 (executable)
@@ -438,6 +438,13 @@ test_expect_success 'cvs update (-p)' '
     test -z "$(cat failures)"
 '
 
+cd "$WORKDIR"
+test_expect_success 'cvs update (module list supports packed refs)' '
+    GIT_DIR="$SERVERDIR" git pack-refs --all &&
+    GIT_CONFIG="$git_config" cvs -n up -d 2> out &&
+    grep "cvs update: New directory \`master'\''" < out
+'
+
 #------------
 # CVS STATUS
 #------------
@@ -470,4 +477,15 @@ test_expect_success 'cvs status (no subdirs in header)' '
     ! grep / <../out
 '
 
+#------------
+# CVS CHECKOUT
+#------------
+
+cd "$WORKDIR"
+test_expect_success 'cvs co -c (shows module database)' '
+    GIT_CONFIG="$git_config" cvs co -c > out &&
+    grep "^master[      ]\+master$" < out &&
+    ! grep -v "^master[         ]\+master$" < out
+'
+
 test_done
index 1e01e5c7483c2772964aa5250bc436b25454de7d..0d7786a8c730d17fa194346f1da2978d23256da9 100755 (executable)
@@ -5,6 +5,7 @@ test_description='git-cvsimport basic tests'
 
 CVSROOT=$(pwd)/cvsroot
 export CVSROOT
+unset CVS_SERVER
 # for clean cvsps cache
 HOME=$(pwd)
 export HOME
index 8e2849b5ce915c3984894628e8e3ce990812ddfd..11c027571b44c429b4f6fdca88bff9c3360c7545 100644 (file)
@@ -379,7 +379,7 @@ test_external_without_stderr () {
 
 test_must_fail () {
        "$@"
-       test $? -gt 0 -a $? -le 129
+       test $? -gt 0 -a $? -le 129 -o $? -gt 192
 }
 
 # test_cmp is a helper function to compare actual and expected output.
index e1e2e6c6ce3c4effffb26e9aed7c6bdd2b00a5ae..bbb126fc46cfb28a0bc92cc0842c0dc72017751d 100644 (file)
@@ -15,6 +15,15 @@ static char *malloc_base(const char *base, int baselen, const char *path, int pa
        return newbase;
 }
 
+static char *malloc_fullname(const char *base, int baselen, const char *path, int pathlen)
+{
+       char *fullname = xmalloc(baselen + pathlen + 1);
+       memcpy(fullname, base, baselen);
+       memcpy(fullname + baselen, path, pathlen);
+       fullname[baselen + pathlen] = 0;
+       return fullname;
+}
+
 static void show_entry(struct diff_options *opt, const char *prefix, struct tree_desc *desc,
                       const char *base, int baselen);
 
@@ -24,6 +33,7 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const
        const char *path1, *path2;
        const unsigned char *sha1, *sha2;
        int cmp, pathlen1, pathlen2;
+       char *fullname;
 
        sha1 = tree_entry_extract(t1, &path1, &mode1);
        sha2 = tree_entry_extract(t2, &path2, &mode2);
@@ -55,15 +65,20 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const
        if (DIFF_OPT_TST(opt, RECURSIVE) && S_ISDIR(mode1)) {
                int retval;
                char *newbase = malloc_base(base, baselen, path1, pathlen1);
-               if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE))
+               if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE)) {
+                       newbase[baselen + pathlen1] = 0;
                        opt->change(opt, mode1, mode2,
-                                   sha1, sha2, base, path1);
+                                   sha1, sha2, newbase);
+                       newbase[baselen + pathlen1] = '/';
+               }
                retval = diff_tree_sha1(sha1, sha2, newbase, opt);
                free(newbase);
                return retval;
        }
 
-       opt->change(opt, mode1, mode2, sha1, sha2, base, path1);
+       fullname = malloc_fullname(base, baselen, path1, pathlen1);
+       opt->change(opt, mode1, mode2, sha1, sha2, fullname);
+       free(fullname);
        return 0;
 }
 
@@ -205,10 +220,10 @@ static void show_entry(struct diff_options *opt, const char *prefix, struct tree
        unsigned mode;
        const char *path;
        const unsigned char *sha1 = tree_entry_extract(desc, &path, &mode);
+       int pathlen = tree_entry_len(path, sha1);
 
        if (DIFF_OPT_TST(opt, RECURSIVE) && S_ISDIR(mode)) {
                enum object_type type;
-               int pathlen = tree_entry_len(path, sha1);
                char *newbase = malloc_base(base, baselen, path, pathlen);
                struct tree_desc inner;
                void *tree;
@@ -224,7 +239,9 @@ static void show_entry(struct diff_options *opt, const char *prefix, struct tree
                free(tree);
                free(newbase);
        } else {
-               opt->add_remove(opt, prefix[0], mode, sha1, base, path);
+               char *fullname = malloc_fullname(base, baselen, path, pathlen);
+               opt->add_remove(opt, prefix[0], mode, sha1, fullname);
+               free(fullname);
        }
 }
 
diff --git a/tree.c b/tree.c
index 4b1825c2adac94ad806d729862c90cf8dfa37e9a..03e782a9cabc0a12ed5baec0ef59c99f19dbc843 100644 (file)
--- a/tree.c
+++ b/tree.c
@@ -29,7 +29,7 @@ static int read_one_entry_opt(const unsigned char *sha1, const char *base, int b
        return add_cache_entry(ce, opt);
 }
 
-static int read_one_entry(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage)
+static int read_one_entry(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, void *context)
 {
        return read_one_entry_opt(sha1, base, baselen, pathname, mode, stage,
                                  ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DFCHECK);
@@ -39,7 +39,7 @@ static int read_one_entry(const unsigned char *sha1, const char *base, int basel
  * This is used when the caller knows there is no existing entries at
  * the stage that will conflict with the entry being added.
  */
-static int read_one_entry_quick(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage)
+static int read_one_entry_quick(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, void *context)
 {
        return read_one_entry_opt(sha1, base, baselen, pathname, mode, stage,
                                  ADD_CACHE_JUST_APPEND);
@@ -92,7 +92,7 @@ static int match_tree_entry(const char *base, int baselen, const char *path, uns
 int read_tree_recursive(struct tree *tree,
                        const char *base, int baselen,
                        int stage, const char **match,
-                       read_tree_fn_t fn)
+                       read_tree_fn_t fn, void *context)
 {
        struct tree_desc desc;
        struct name_entry entry;
@@ -106,7 +106,7 @@ int read_tree_recursive(struct tree *tree,
                if (!match_tree_entry(base, baselen, entry.path, entry.mode, match))
                        continue;
 
-               switch (fn(entry.sha1, base, baselen, entry.path, entry.mode, stage)) {
+               switch (fn(entry.sha1, base, baselen, entry.path, entry.mode, stage, context)) {
                case 0:
                        continue;
                case READ_TREE_RECURSIVE:
@@ -126,7 +126,7 @@ int read_tree_recursive(struct tree *tree,
                        retval = read_tree_recursive(lookup_tree(entry.sha1),
                                                     newbase,
                                                     baselen + pathlen + 1,
-                                                    stage, match, fn);
+                                                    stage, match, fn, context);
                        free(newbase);
                        if (retval)
                                return -1;
@@ -174,7 +174,7 @@ int read_tree(struct tree *tree, int stage, const char **match)
 
        if (!fn)
                fn = read_one_entry_quick;
-       err = read_tree_recursive(tree, "", 0, stage, match, fn);
+       err = read_tree_recursive(tree, "", 0, stage, match, fn, NULL);
        if (fn == read_one_entry || err)
                return err;
 
diff --git a/tree.h b/tree.h
index dd25c539efbb0ab018caa4cda2d133285634e9b5..2ff01a4f839ecc2206fcc1c13fee9d5d202b1128 100644 (file)
--- a/tree.h
+++ b/tree.h
@@ -21,12 +21,12 @@ int parse_tree(struct tree *tree);
 struct tree *parse_tree_indirect(const unsigned char *sha1);
 
 #define READ_TREE_RECURSIVE 1
-typedef int (*read_tree_fn_t)(const unsigned char *, const char *, int, const char *, unsigned int, int);
+typedef int (*read_tree_fn_t)(const unsigned char *, const char *, int, const char *, unsigned int, int, void *);
 
 extern int read_tree_recursive(struct tree *tree,
                               const char *base, int baselen,
                               int stage, const char **match,
-                              read_tree_fn_t fn);
+                              read_tree_fn_t fn, void *context);
 
 extern int read_tree(struct tree *tree, int stage, const char **paths);
 
index 0b6c3835bd19241ff447c37f442de75791186020..7e8209ea4b43995737b36bc58db47e7dd6eadb19 100644 (file)
@@ -1,7 +1,7 @@
 #include "cache.h"
 
 static const char update_server_info_usage[] =
-"git-update-server-info [--force]";
+"git update-server-info [--force]";
 
 int main(int ac, char **av)
 {
index 4e04f7661b4943059243fa5f8a33baeec4a96583..93562f03eef21b26945d2d9bbdc96818f4de6567 100644 (file)
--- a/wrapper.c
+++ b/wrapper.c
@@ -133,6 +133,44 @@ ssize_t xwrite(int fd, const void *buf, size_t len)
        }
 }
 
+ssize_t read_in_full(int fd, void *buf, size_t count)
+{
+       char *p = buf;
+       ssize_t total = 0;
+
+       while (count > 0) {
+               ssize_t loaded = xread(fd, p, count);
+               if (loaded <= 0)
+                       return total ? total : loaded;
+               count -= loaded;
+               p += loaded;
+               total += loaded;
+       }
+
+       return total;
+}
+
+ssize_t write_in_full(int fd, const void *buf, size_t count)
+{
+       const char *p = buf;
+       ssize_t total = 0;
+
+       while (count > 0) {
+               ssize_t written = xwrite(fd, p, count);
+               if (written < 0)
+                       return -1;
+               if (!written) {
+                       errno = ENOSPC;
+                       return -1;
+               }
+               count -= written;
+               p += written;
+               total += written;
+       }
+
+       return total;
+}
+
 int xdup(int fd)
 {
        int ret = dup(fd);
index e4c8e225fd232dfd642aa13d7ae5b64b9827c915..4c29255df1b637f93ab3d59e0dcab1fa3b40e10b 100644 (file)
@@ -45,44 +45,6 @@ void maybe_flush_or_die(FILE *f, const char *desc)
        }
 }
 
-ssize_t read_in_full(int fd, void *buf, size_t count)
-{
-       char *p = buf;
-       ssize_t total = 0;
-
-       while (count > 0) {
-               ssize_t loaded = xread(fd, p, count);
-               if (loaded <= 0)
-                       return total ? total : loaded;
-               count -= loaded;
-               p += loaded;
-               total += loaded;
-       }
-
-       return total;
-}
-
-ssize_t write_in_full(int fd, const void *buf, size_t count)
-{
-       const char *p = buf;
-       ssize_t total = 0;
-
-       while (count > 0) {
-               ssize_t written = xwrite(fd, p, count);
-               if (written < 0)
-                       return -1;
-               if (!written) {
-                       errno = ENOSPC;
-                       return -1;
-               }
-               count -= written;
-               p += written;
-               total += written;
-       }
-
-       return total;
-}
-
 void fsync_or_die(int fd, const char *msg)
 {
        if (fsync(fd) < 0) {