Merge 1.5.3.7 in
authorJunio C Hamano <gitster@pobox.com>
Sat, 1 Dec 2007 20:48:19 +0000 (12:48 -0800)
committerJunio C Hamano <gitster@pobox.com>
Sat, 1 Dec 2007 20:49:51 +0000 (12:49 -0800)
Signed-off-by: Junio C Hamano <gitster@pobox.com>
393 files changed:
.gitignore
.mailmap
Documentation/RelNotes-1.5.4.txt [new file with mode: 0644]
Documentation/cmd-list.perl
Documentation/config.txt
Documentation/core-tutorial.txt
Documentation/diff-options.txt
Documentation/git-add.txt
Documentation/git-bisect.txt
Documentation/git-branch.txt
Documentation/git-cherry-pick.txt
Documentation/git-clone.txt
Documentation/git-cvsexportcommit.txt
Documentation/git-diff.txt
Documentation/git-for-each-ref.txt
Documentation/git-format-patch.txt
Documentation/git-gc.txt
Documentation/git-http-push.txt
Documentation/git-index-pack.txt
Documentation/git-instaweb.txt
Documentation/git-local-fetch.txt [deleted file]
Documentation/git-lost-found.txt
Documentation/git-ls-files.txt
Documentation/git-merge-index.txt
Documentation/git-merge.txt
Documentation/git-mergetool.txt
Documentation/git-mv.txt
Documentation/git-pack-objects.txt
Documentation/git-peek-remote.txt
Documentation/git-push.txt
Documentation/git-rebase.txt
Documentation/git-remote.txt
Documentation/git-reset.txt
Documentation/git-rev-list.txt
Documentation/git-rev-parse.txt
Documentation/git-revert.txt
Documentation/git-rm.txt
Documentation/git-send-email.txt
Documentation/git-send-pack.txt
Documentation/git-ssh-fetch.txt [deleted file]
Documentation/git-ssh-upload.txt [deleted file]
Documentation/git-stash.txt
Documentation/git-submodule.txt
Documentation/git-svn.txt
Documentation/git-symbolic-ref.txt
Documentation/git-tag.txt
Documentation/git-tools.txt
Documentation/git.txt
Documentation/gitattributes.txt
Documentation/glossary.txt
Documentation/hooks.txt
Documentation/howto/maintain-git.txt [new file with mode: 0644]
Documentation/howto/recover-corrupted-blob-object.txt [new file with mode: 0644]
Documentation/merge-options.txt
Documentation/urls.txt
Documentation/user-manual.txt
GIT-VERSION-GEN
Makefile
RelNotes
archive-tar.c
archive-zip.c
archive.h
attr.c
builtin-add.c
builtin-apply.c
builtin-archive.c
builtin-blame.c
builtin-branch.c
builtin-bundle.c
builtin-check-attr.c
builtin-checkout-index.c
builtin-clean.c [new file with mode: 0644]
builtin-commit-tree.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-fetch--tool.c
builtin-fetch-pack.c [moved from fetch-pack.c with 81% similarity]
builtin-fetch.c [new file with mode: 0644]
builtin-fmt-merge-msg.c
builtin-for-each-ref.c
builtin-fsck.c
builtin-gc.c
builtin-http-fetch.c [new file with mode: 0644]
builtin-init-db.c
builtin-log.c
builtin-ls-files.c
builtin-ls-remote.c [new file with mode: 0644]
builtin-ls-tree.c
builtin-mailinfo.c
builtin-mailsplit.c
builtin-merge-ours.c [new file with mode: 0644]
builtin-mv.c
builtin-name-rev.c
builtin-pack-objects.c
builtin-pack-refs.c
builtin-prune-packed.c
builtin-push.c
builtin-rerere.c
builtin-reset.c [new file with mode: 0644]
builtin-rev-list.c
builtin-rev-parse.c
builtin-revert.c
builtin-rm.c
builtin-send-pack.c [new file with mode: 0644]
builtin-shortlog.c
builtin-show-branch.c
builtin-stripspace.c
builtin-symbolic-ref.c
builtin-tag.c
builtin-unpack-objects.c
builtin-update-index.c
builtin-update-ref.c
builtin-verify-tag.c
builtin.h
bundle.c [new file with mode: 0644]
bundle.h [new file with mode: 0644]
cache-tree.c
cache-tree.h
cache.h
color.c
color.h
combine-diff.c
commit.c
commit.h
compat/memmem.c [new file with mode: 0644]
compat/mkdtemp.c [new file with mode: 0644]
config.c
config.mak.in
configure.ac
connect.c
contrib/completion/git-completion.bash
contrib/convert-objects/convert-objects.c [moved from convert-objects.c with 100% similarity]
contrib/convert-objects/git-convert-objects.txt [moved from Documentation/git-convert-objects.txt with 100% similarity]
contrib/emacs/git.el
contrib/examples/git-clean.sh [moved from git-clean.sh with 57% similarity]
contrib/examples/git-fetch.sh [moved from git-fetch.sh with 100% similarity]
contrib/examples/git-ls-remote.sh [moved from git-ls-remote.sh with 100% similarity]
contrib/examples/git-merge-ours.sh [moved from git-merge-ours.sh with 100% similarity]
contrib/examples/git-reset.sh [moved from git-reset.sh with 100% similarity]
contrib/examples/git-svnimport.perl [moved from git-svnimport.perl with 97% similarity]
contrib/examples/git-svnimport.txt [moved from Documentation/git-svnimport.txt with 100% similarity]
contrib/fast-import/git-import.perl [new file with mode: 0755]
contrib/fast-import/git-import.sh [new file with mode: 0755]
contrib/fast-import/git-p4
contrib/gitview/gitview
contrib/hg-to-git/hg-to-git.py
contrib/hooks/post-receive-email
contrib/hooks/setgitperms.perl [new file with mode: 0644]
convert.c
csum-file.c
csum-file.h
daemon.c
date.c
diff-delta.c
diff-lib.c
diff.c
diff.h
diffcore-delta.c
diffcore-order.c
diffcore-rename.c
diffcore.h
dir.c
dir.h
entry.c
exec_cmd.c
exec_cmd.h
fast-import.c
fetch-pack.h [new file with mode: 0644]
fetch.h [deleted file]
git-add--interactive.perl
git-am.sh
git-bisect.sh
git-checkout.sh
git-clone.sh
git-commit.sh
git-compat-util.h
git-cvsexportcommit.perl
git-cvsimport.perl
git-filter-branch.sh
git-gui/.gitignore
git-gui/GIT-VERSION-GEN
git-gui/Makefile
git-gui/git-gui.sh
git-gui/lib/about.tcl [new file with mode: 0644]
git-gui/lib/blame.tcl
git-gui/lib/branch_checkout.tcl
git-gui/lib/branch_create.tcl
git-gui/lib/branch_delete.tcl
git-gui/lib/branch_rename.tcl
git-gui/lib/browser.tcl
git-gui/lib/checkout_op.tcl
git-gui/lib/choose_repository.tcl [new file with mode: 0644]
git-gui/lib/choose_rev.tcl
git-gui/lib/commit.tcl
git-gui/lib/console.tcl
git-gui/lib/database.tcl
git-gui/lib/date.tcl [new file with mode: 0644]
git-gui/lib/diff.tcl
git-gui/lib/error.tcl
git-gui/lib/git-gui.ico [new file with mode: 0644]
git-gui/lib/index.tcl
git-gui/lib/logo.tcl [new file with mode: 0644]
git-gui/lib/merge.tcl
git-gui/lib/option.tcl
git-gui/lib/remote.tcl
git-gui/lib/remote_branch_delete.tcl
git-gui/lib/shortcut.tcl
git-gui/lib/status_bar.tcl
git-gui/lib/transport.tcl
git-gui/lib/win32.tcl [new file with mode: 0644]
git-gui/lib/win32_shortcut.js [new file with mode: 0644]
git-gui/macosx/AppMain.tcl [new file with mode: 0644]
git-gui/macosx/Info.plist [new file with mode: 0644]
git-gui/macosx/git-gui.icns [new file with mode: 0644]
git-gui/po/.gitignore [new file with mode: 0644]
git-gui/po/README [new file with mode: 0644]
git-gui/po/de.po [new file with mode: 0644]
git-gui/po/git-gui.pot [new file with mode: 0644]
git-gui/po/glossary/Makefile [new file with mode: 0644]
git-gui/po/glossary/de.po [new file with mode: 0644]
git-gui/po/glossary/git-gui-glossary.pot [new file with mode: 0644]
git-gui/po/glossary/git-gui-glossary.txt [new file with mode: 0644]
git-gui/po/glossary/it.po [new file with mode: 0644]
git-gui/po/glossary/txt-to-pot.sh [new file with mode: 0755]
git-gui/po/glossary/zh_cn.po [new file with mode: 0644]
git-gui/po/hu.po [new file with mode: 0644]
git-gui/po/it.po [new file with mode: 0644]
git-gui/po/ja.po [new file with mode: 0644]
git-gui/po/po2msg.sh [new file with mode: 0644]
git-gui/po/ru.po [new file with mode: 0644]
git-gui/po/zh_cn.po [new file with mode: 0644]
git-gui/windows/git-gui.sh [new file with mode: 0644]
git-instaweb.sh
git-lost-found.sh
git-merge.sh
git-mergetool.sh
git-pull.sh
git-quiltimport.sh
git-rebase--interactive.sh
git-rebase.sh
git-remote.perl
git-repack.sh
git-request-pull.sh
git-send-email.perl
git-sh-setup.sh
git-stash.sh
git-submodule.sh
git-svn.perl
git.c
gitk
gitweb/gitweb.css
gitweb/gitweb.perl
hash.c [new file with mode: 0644]
hash.h [new file with mode: 0644]
help.c
http-push.c
http-walker.c [moved from http-fetch.c with 84% similarity]
http.c
http.h
imap-send.c
index-pack.c
interpolate.c
local-fetch.c [deleted file]
lockfile.c
log-tree.c
log-tree.h
match-trees.c
merge-recursive.c
mktag.c
mktree.c
pack-write.c
pack.h
pager.c
parse-options.c [new file with mode: 0644]
parse-options.h [new file with mode: 0644]
patch-ids.c
peek-remote.c [deleted file]
perl/Git.pm
pretty.c [new file with mode: 0644]
progress.c
progress.h
quote.c
quote.h
read-cache.c
receive-pack.c
refs.c
refs.h
remote.c
remote.h
revision.c
revision.h
rsh.c [deleted file]
rsh.h [deleted file]
run-command.c
run-command.h
send-pack.c [deleted file]
send-pack.h [new file with mode: 0644]
server-info.c
setup.c
sha1_file.c
shell.c
show-index.c
sideband.c
ssh-fetch.c [deleted file]
ssh-pull.c [deleted file]
ssh-push.c [deleted file]
ssh-upload.c [deleted file]
strbuf.c
strbuf.h
t/t0021-conversion.sh
t/t0040-parse-options.sh [new file with mode: 0755]
t/t2008-checkout-subdir.sh [new file with mode: 0755]
t/t3402-rebase-merge.sh
t/t3403-rebase-skip.sh
t/t3404-rebase-interactive.sh
t/t3502-cherry-pick-merge.sh [new file with mode: 0755]
t/t3902-quoted.sh
t/t4021-format-patch-numbered.sh [new file with mode: 0755]
t/t4022-diff-rewrite.sh [new file with mode: 0755]
t/t4119-apply-config.sh
t/t5000-tar-tree.sh
t/t5100/sample.mbox
t/t5300-pack-object.sh
t/t5302-pack-index.sh
t/t5402-post-merge-hook.sh [new file with mode: 0755]
t/t5403-post-checkout-hook.sh [new file with mode: 0755]
t/t5404-tracking-branches.sh [new file with mode: 0755]
t/t5405-send-pack-rewind.sh [new file with mode: 0755]
t/t5406-remote-rejects.sh [new file with mode: 0755]
t/t5502-quickfetch.sh
t/t5505-remote.sh [new file with mode: 0755]
t/t5510-fetch.sh
t/t5512-ls-remote.sh [new file with mode: 0755]
t/t5515-fetch-merge-logic.sh
t/t5515/fetch.br-branches-default-merge
t/t5515/fetch.br-branches-default-merge_branches-default
t/t5515/fetch.br-branches-default-octopus
t/t5515/fetch.br-branches-default-octopus_branches-default
t/t5515/fetch.br-branches-one-merge
t/t5515/fetch.br-branches-one-merge_branches-one
t/t5515/fetch.br-branches-one-octopus
t/t5515/fetch.br-branches-one-octopus_branches-one
t/t5515/fetch.br-config-glob-octopus
t/t5515/fetch.br-config-glob-octopus_config-glob
t/t5515/fetch.br-remote-glob-octopus
t/t5515/fetch.br-remote-glob-octopus_remote-glob
t/t5516-fetch-push.sh
t/t5517-push-mirror.sh [new file with mode: 0755]
t/t5530-upload-pack-error.sh [new file with mode: 0755]
t/t5700-clone-reference.sh
t/t6006-rev-list-format.sh
t/t6030-bisect-porcelain.sh
t/t6300-for-each-ref.sh [new file with mode: 0755]
t/t7004-tag.sh
t/t7005-editor.sh
t/t7102-reset.sh [new file with mode: 0755]
t/t7201-co.sh
t/t7300-clean.sh
t/t7500-commit.sh
t/t7501-commit.sh
t/t7600-merge.sh [new file with mode: 0755]
t/t9001-send-email.sh
t/t9101-git-svn-props.sh
t/t9104-git-svn-follow-parent.sh
t/t9106-git-svn-dcommit-clobber-series.sh
t/t9116-git-svn-log.sh
t/t9117-git-svn-init-clone.sh [new file with mode: 0755]
t/t9118-git-svn-funky-branch-names.sh [new file with mode: 0755]
t/t9119-git-svn-info.sh [new file with mode: 0755]
t/t9500-gitweb-standalone-no-errors.sh
t/test-lib.sh
tag.c
templates/hooks--pre-commit
templates/hooks--update
test-parse-options.c [new file with mode: 0644]
trace.c
transport.c [new file with mode: 0644]
transport.h [new file with mode: 0644]
tree-diff.c
unpack-trees.c
upload-pack.c
utf8.c
walker.c [moved from fetch.c with 73% similarity]
walker.h [new file with mode: 0644]
wt-status.c
wt-status.h
xdiff/xdiffi.c
xdiff/xutils.c

index 63c918c..c8c13f5 100644 (file)
@@ -25,7 +25,6 @@ git-clone
 git-commit
 git-commit-tree
 git-config
-git-convert-objects
 git-count-objects
 git-cvsexportcommit
 git-cvsimport
@@ -129,7 +128,6 @@ git-status
 git-stripspace
 git-submodule
 git-svn
-git-svnimport
 git-symbolic-ref
 git-tag
 git-tar-tree
@@ -155,6 +153,7 @@ test-delta
 test-dump-cache-tree
 test-genrandom
 test-match-trees
+test-parse-options
 test-sha1
 common-cmds.h
 *.tar.gz
@@ -172,3 +171,6 @@ config.status
 config.mak.autogen
 config.mak.append
 configure
+tags
+TAGS
+cscope*
index 5529b19..3b2ce57 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -37,6 +37,7 @@ Sam Vilain <sam@vilain.net>
 Santi Béjar <sbejar@gmail.com>
 Sean Estabrooks <seanlkml@sympatico.ca>
 Shawn O. Pearce <spearce@spearce.org>
+Steven Grimm <koreth@midwinter.com>
 Theodore Ts'o <tytso@mit.edu>
 Tony Luck <tony.luck@intel.com>
 Uwe Kleine-König <Uwe_Zeisberger@digi.com>
diff --git a/Documentation/RelNotes-1.5.4.txt b/Documentation/RelNotes-1.5.4.txt
new file mode 100644 (file)
index 0000000..c9c5376
--- /dev/null
@@ -0,0 +1,154 @@
+GIT v1.5.4 Release Notes
+========================
+
+Updates since v1.5.3
+--------------------
+
+ * Comes with much improved gitk.
+
+ * Comes with git-gui 0.9.0 with i18n.
+
+ * git-lost-found was deprecated in favor of git-fsck's --lost-found
+   option.
+
+ * git-peek-remote is deprecated, as git-ls-remote was written in C and
+   works for all transports.
+
+ * "progress display" from many commands are a lot nicer to the
+   eye.  Transfer commands show throughput data.
+
+ * git-reset is now built-in and its output can be squelched with -q.
+
+ * git-send-email can optionally talk over ssmtp and use SMTP-AUTH.
+
+ * git-rebase learned --whitespace option.
+
+ * In git-rebase, when you decide not to replay a particular change
+   after the command stopped with a conflict, you can say "git-rebase
+   --skip" without first running "git reset --hard", as the command now
+   runs it for you.
+
+ * git-remote knows --mirror mode.
+
+ * git-merge can call the "post-merge" hook.
+
+ * git-pack-objects can optionally run deltification with multiple threads.
+
+ * git-archive can optionally substitute keywords in files marked with
+   export-subst attribute.
+
+ * git-for-each-ref learned %(xxxdate:<dateformat>) syntax to
+   show the various date fields in different formats.
+
+ * git-gc --auto is a low-impact way to automatically run a
+   variant of git-repack that does not lose unreferenced objects
+   (read: safer than the usual one) after the user accumulates
+   too many loose objects.
+
+ * You need to explicitly set clean.requireForce to "false" to allow
+   git-clean without -f to do any damage (lack of the configuration
+   variable used to mean "do not require", but we now use the safer
+   default).
+
+ * git-clean has been rewritten in C.
+
+ * git-push has been rewritten in C.
+
+ * git-push learned --dry-run option to show what would happen
+   if a push is run.
+
+ * git-push does not update a tracking ref on the pushing side when the
+   remote refused to update the corresponding ref.
+
+ * git-push learned --mirror option.  This is to push the local refs
+   one-to-one to the remote, and deletes refs from the remote that do
+   not exist anymore in the repository on the pushing side.
+
+ * git-remote learned "rm" subcommand.
+
+ * git-rebase --interactive mode can now work on detached HEAD.
+
+ * git-cvsserver can be run via git-shell.
+
+ * git-am and git-rebase are far less verbose.
+
+ * git-pull learned to pass --[no-]ff option to underlying git-merge.
+
+ * Various Perforce importer updates.
+
+ * "git log" learned --early-output option to help interactive
+   GUI implementations.
+
+ * git-svnimport was removed in favor of git-svn.
+
+ * git-bisect learned "skip" action to mark untestable commits.
+
+ * git-format-patch learned "format.numbered" configuration variable
+   to automatically turn --numbered option on when more than one
+   commits are formatted.
+
+ * git-ls-files learned "--exclude-standard" to use the canned
+   set of exclude files.
+
+ * git-rebase now detaches head during its operation, so after a
+   successful "git rebase" operation, the reflog entry branch@{1}
+   for the current branch points at the commit before the rebase
+   was started.
+
+ * "git-tag -a -f existing" begins the editor session using the
+   existing annotation message.
+
+ * "git cvsexportcommit" learned -w option to specify and switch
+   to the CVS working directory.
+
+ * "git checkout" from a subdirectory learned to use "../path"
+   to allow checking out a path outside the current directory
+   without cd'ing up.
+
+ * "git send-email --dry-run" shows full headers for easier
+   diagnosis.
+
+ * "git merge-ours" is built-in.
+
+ * "git svn" learned "info" subcommand.
+
+ * "git status" from a subdirectory now shows relative paths
+   which makes copy-and-pasting for git-checkout/git-add/git-rm
+   easier.
+
+ * Output processing for '--pretty=format:<user format>' has
+   been optimized.
+
+ * Rename detection diff family, while detecting exact matches,
+   has been greatly optimized.
+
+ * Example update and post-receive hooks have been improved.
+
+ * In addition there are quite a few internal clean-ups. Notably
+
+   - many fork/exec have been replaced with run-command API,
+     brought from the msysgit effort.
+
+   - introduction and more use of the option parser API.
+
+   - enhancement and more use of the strbuf API.
+
+
+Fixes since v1.5.3
+------------------
+
+All of the fixes in v1.5.3 maintenance series are included in
+this release, unless otherwise noted.
+
+ * git-svn talking with the SVN over http will correctly quote branch
+   and project names.
+
+ * "git rev-list --objects A..B" choked when the lower boundary
+   of the range involved a subproject.  This fix is also queued
+   for 'maint' (but not in there yet).
+
+--
+exec >/var/tmp/1
+O=v1.5.3.6-950-gda03a58
+echo O=`git describe refs/heads/master`
+git shortlog --no-merges $O..refs/heads/master ^refs/heads/maint
index 4ee76ea..b709551 100755 (executable)
@@ -3,7 +3,8 @@
 use File::Compare qw(compare);
 
 sub format_one {
-       my ($out, $name) = @_;
+       my ($out, $nameattr) = @_;
+       my ($name, $attr) = @$nameattr;
        my ($state, $description);
        $state = 0;
        open I, '<', "$name.txt" or die "No such file $name.txt";
@@ -26,8 +27,11 @@ sub format_one {
                die "No description found in $name.txt";
        }
        if (my ($verify_name, $text) = ($description =~ /^($name) - (.*)/)) {
-               print $out "gitlink:$name\[1\]::\n";
-               print $out "\t$text.\n\n";
+               print $out "gitlink:$name\[1\]::\n\t";
+               if ($attr) {
+                       print $out "($attr) ";
+               }
+               print $out "$text.\n\n";
        }
        else {
                die "Description does not match $name: $description";
@@ -39,8 +43,8 @@ while (<DATA>) {
        next if /^#/;
 
        chomp;
-       my ($name, $cat) = /^(\S+)\s+(.*)$/;
-       push @{$cmds{$cat}}, $name;
+       my ($name, $cat, $attr) = /^(\S+)\s+(.*?)(?:\s+(.*))?$/;
+       push @{$cmds{$cat}}, [$name, $attr];
 }
 
 for my $cat (qw(ancillaryinterrogators
@@ -94,7 +98,6 @@ git-clone                               mainporcelain
 git-commit                              mainporcelain
 git-commit-tree                         plumbingmanipulators
 git-config                              ancillarymanipulators
-git-convert-objects                     ancillarymanipulators
 git-count-objects                       ancillaryinterrogators
 git-cvsexportcommit                     foreignscminterface
 git-cvsimport                           foreignscminterface
@@ -125,9 +128,8 @@ git-index-pack                          plumbingmanipulators
 git-init                                mainporcelain
 git-instaweb                            ancillaryinterrogators
 gitk                                    mainporcelain
-git-local-fetch                         synchingrepositories
 git-log                                 mainporcelain
-git-lost-found                          ancillarymanipulators
+git-lost-found                          ancillarymanipulators  deprecated
 git-ls-files                            plumbinginterrogators
 git-ls-remote                           plumbinginterrogators
 git-ls-tree                             plumbinginterrogators
@@ -149,7 +151,7 @@ git-pack-redundant                      plumbinginterrogators
 git-pack-refs                           ancillarymanipulators
 git-parse-remote                        synchelpers
 git-patch-id                            purehelpers
-git-peek-remote                         purehelpers
+git-peek-remote                         purehelpers    deprecated
 git-prune                               ancillarymanipulators
 git-prune-packed                        plumbingmanipulators
 git-pull                                mainporcelain
@@ -179,17 +181,14 @@ git-show-branch                         ancillaryinterrogators
 git-show-index                          plumbinginterrogators
 git-show-ref                            plumbinginterrogators
 git-sh-setup                            purehelpers
-git-ssh-fetch                           synchingrepositories
-git-ssh-upload                          synchingrepositories
 git-stash                               mainporcelain
 git-status                              mainporcelain
 git-stripspace                          purehelpers
 git-submodule                           mainporcelain
 git-svn                                 foreignscminterface
-git-svnimport                           foreignscminterface
 git-symbolic-ref                        plumbingmanipulators
 git-tag                                 mainporcelain
-git-tar-tree                            plumbinginterrogators
+git-tar-tree                            plumbinginterrogators  deprecated
 git-unpack-file                         plumbinginterrogators
 git-unpack-objects                      plumbingmanipulators
 git-update-index                        plumbingmanipulators
index 83bc33c..39d1ef5 100644 (file)
@@ -188,7 +188,7 @@ core.worktree::
        Set the path to the working tree.  The value will not be
        used in combination with repositories found automatically in
        a .git directory (i.e. $GIT_DIR is not set).
-       This can be overriden by the GIT_WORK_TREE environment
+       This can be overridden by the GIT_WORK_TREE environment
        variable and the '--work-tree' command line option.
 
 core.logAllRefUpdates::
@@ -326,10 +326,11 @@ branch.<name>.remote::
        If this option is not given, `git fetch` defaults to remote "origin".
 
 branch.<name>.merge::
-       When in branch <name>, it tells `git fetch` the default refspec to
-       be marked for merging in FETCH_HEAD. The value has exactly to match
-       a remote part of one of the refspecs which are fetched from the remote
-       given by "branch.<name>.remote".
+       When in branch <name>, it tells `git fetch` the default
+       refspec to be marked for merging in FETCH_HEAD. The value is
+       handled like the remote part of a refspec, and must match a
+       ref which is fetched from the remote given by
+       "branch.<name>.remote".
        The merge information is used by `git pull` (which at first calls
        `git fetch`) to lookup the default branch for merging. Without
        this option, `git pull` defaults to merge the first refspec fetched.
@@ -339,9 +340,15 @@ branch.<name>.merge::
        branch.<name>.merge to the desired branch, and use the special setting
        `.` (a period) for branch.<name>.remote.
 
+branch.<name>.mergeoptions::
+       Sets default options for merging into branch <name>. The syntax and
+       supported options are equal to that of gitlink:git-merge[1], but
+       option values containing whitespace characters are currently not
+       supported.
+
 clean.requireForce::
-       A boolean to make git-clean do nothing unless given -f or -n.  Defaults
-       to false.
+       A boolean to make git-clean do nothing unless given -f
+       or -n.   Defaults to true.
 
 color.branch::
        A boolean to enable/disable color in the output of
@@ -427,6 +434,12 @@ fetch.unpackLimit::
        pack from a push can make the push operation complete faster,
        especially on slow filesystems.
 
+format.numbered::
+       A boolean which can enable sequence numbers in patch subjects.
+       Seting this option to "auto" will enable it only if there is
+       more than one patch.  See --numbered option in
+       gitlink:git-format-patch[1].
+
 format.headers::
        Additional email headers to include in a patch to be submitted
        by mail.  See gitlink:git-format-patch[1].
@@ -441,6 +454,19 @@ gc.aggressiveWindow::
        algorithm used by 'git gc --aggressive'.  This defaults
        to 10.
 
+gc.auto::
+       When there are approximately more than this many loose
+       objects in the repository, `git gc --auto` will pack them.
+       Some Porcelain commands use this command to perform a
+       light-weight garbage collection from time to time.  Setting
+       this to 0 disables it.
+
+gc.autopacklimit::
+       When there are more than this many packs that are not
+       marked with `*.keep` file in the repository, `git gc
+       --auto` consolidates them into one larger pack.  Setting
+       this to 0 disables this.
+
 gc.packrefs::
        `git gc` does not run `git pack-refs` in a bare repository by
        default so that older dumb-transport clients can still fetch
@@ -590,7 +616,7 @@ merge.verbosity::
        message if conflicts were detected. Level 1 outputs only
        conflicts, 2 outputs conflicts and file changes.  Level 5 and
        above outputs debugging information.  The default is level 2.
-       Can be overriden by 'GIT_MERGE_VERBOSITY' environment variable.
+       Can be overridden by 'GIT_MERGE_VERBOSITY' environment variable.
 
 merge.<driver>.name::
        Defines a human readable name for a custom low-level
@@ -634,9 +660,26 @@ pack.deltaCacheSize::
        A value of 0 means no limit. Defaults to 0.
 
 pack.deltaCacheLimit::
-       The maxium size of a delta, that is cached in
+       The maximum size of a delta, that is cached in
        gitlink:git-pack-objects[1]. Defaults to 1000.
 
+pack.threads::
+       Specifies the number of threads to spawn when searching for best
+       delta matches.  This requires that gitlink:git-pack-objects[1]
+       be compiled with pthreads otherwise this option is ignored with a
+       warning. This is meant to reduce packing time on multiprocessor
+       machines. The required amount of memory for the delta search window
+       is however multiplied by the number of threads.
+
+pack.indexVersion::
+       Specify the default pack index version.  Valid values are 1 for
+       legacy pack index used by Git versions prior to 1.5.2, and 2 for
+       the new pack index with capabilities for packs larger than 4 GB
+       as well as proper protection against the repacking of corrupted
+       packs.  Version 2 is selected and this config option ignored
+       whenever the corresponding pack is larger than 2 GB.  Otherwise
+       the default is 1.
+
 pull.octopus::
        The default merge strategy to use when pulling multiple branches
        at once.
index c3f0be5..bd6cd41 100644 (file)
@@ -553,13 +553,8 @@ can explore on your own.
 
 [NOTE]
 Most likely, you are not directly using the core
-git Plumbing commands, but using Porcelain like Cogito on top
-of it. Cogito works a bit differently and you usually do not
-have to run `git-update-index` yourself for changed files (you
-do tell underlying git about additions and removals via
-`cg-add` and `cg-rm` commands). Just before you make a commit
-with `cg-commit`, Cogito figures out which files you modified,
-and runs `git-update-index` on them for you.
+git Plumbing commands, but using Porcelain such as `git-add`, `git-rm'
+and `git-commit'.
 
 
 Tagging a version
@@ -686,8 +681,8 @@ $ git reset
 
 and in fact a lot of the common git command combinations can be scripted
 with the `git xyz` interfaces.  You can learn things by just looking
-at what the various git scripts do.  For example, `git reset` is the
-above two lines implemented in `git-reset`, but some things like
+at what the various git scripts do.  For example, `git reset` used to be
+the above two lines implemented in `git-reset`, but some things like
 `git status` and `git commit` are slightly more complex scripts around
 the basic git commands.
 
@@ -805,8 +800,8 @@ you have, you can say
 $ git branch
 ------------
 
-which is nothing more than a simple script around `ls .git/refs/heads`.
-There will be asterisk in front of the branch you are currently on.
+which used to be nothing more than a simple script around `ls .git/refs/heads`.
+There will be an asterisk in front of the branch you are currently on.
 
 Sometimes you may wish to create a new branch _without_ actually
 checking it out and switching to it. If so, just use the command
@@ -936,12 +931,13 @@ Another useful tool, especially if you do not always work in X-Window
 environment, is `git show-branch`.
 
 ------------------------------------------------
-$ git show-branch --topo-order master mybranch
+$ git-show-branch --topo-order --more=1 master mybranch
 * [master] Merge work in mybranch
  ! [mybranch] Some work.
 --
 -  [master] Merge work in mybranch
 *+ [mybranch] Some work.
+*  [master^] Some fun.
 ------------------------------------------------
 
 The first two lines indicate that it is showing the two branches
@@ -952,17 +948,29 @@ the later output lines is used to show commits contained in the
 `master` branch, and the second column for the `mybranch`
 branch. Three commits are shown along with their log messages.
 All of them have non blank characters in the first column (`*`
-shows an ordinary commit on the current branch, `.` is a merge commit), which
+shows an ordinary commit on the current branch, `-` is a merge commit), which
 means they are now part of the `master` branch. Only the "Some
 work" commit has the plus `+` character in the second column,
 because `mybranch` has not been merged to incorporate these
 commits from the master branch.  The string inside brackets
 before the commit log message is a short name you can use to
 name the commit.  In the above example, 'master' and 'mybranch'
-are branch heads.  'master~1' is the first parent of 'master'
+are branch heads.  'master^' is the first parent of 'master'
 branch head.  Please see 'git-rev-parse' documentation if you
 see more complex cases.
 
+[NOTE]
+Without the '--more=1' option, 'git-show-branch' would not output the
+'[master^]' commit, as '[mybranch]' commit is a common ancestor of
+both 'master' and 'mybranch' tips.  Please see 'git-show-branch'
+documentation for details.
+
+[NOTE]
+If there were more commits on the 'master' branch after the merge, the
+merge commit itself would not be shown by 'git-show-branch' by
+default.  You would need to provide '--sparse' option to make the
+merge commit visible in this case.
+
 Now, let's pretend you are the one who did all the work in
 `mybranch`, and the fruit of your hard work has finally been merged
 to the `master` branch. Let's go back to `mybranch`, and run
@@ -1188,7 +1196,7 @@ $ mb=$(git-merge-base HEAD mybranch)
 
 The command writes the commit object name of the common ancestor
 to the standard output, so we captured its output to a variable,
-because we will be using it in the next step.  BTW, the common
+because we will be using it in the next step.  By the way, the common
 ancestor commit is the "New day." commit in this case.  You can
 tell it by:
 
@@ -1454,8 +1462,7 @@ Although git is a truly distributed system, it is often
 convenient to organize your project with an informal hierarchy
 of developers. Linux kernel development is run this way. There
 is a nice illustration (page 17, "Merges to Mainline") in
-link:http://www.xenotime.net/linux/mentor/linux-mentoring-2006.pdf
-[Randy Dunlap's presentation].
+link:http://www.xenotime.net/linux/mentor/linux-mentoring-2006.pdf[Randy Dunlap's presentation].
 
 It should be stressed that this hierarchy is purely *informal*.
 There is nothing fundamental in git that enforces the "chain of
index b1f528a..e4af393 100644 (file)
@@ -1,5 +1,25 @@
+// Please don't remove this comment as asciidoc behaves badly when
+// the first non-empty line is ifdef/ifndef. The symptom is that
+// without this comment the <git-diff-core> attribute conditionally
+// defined below ends up being defined unconditionally.
+// Last checked with asciidoc 7.0.2.
+
+ifndef::git-format-patch[]
+ifndef::git-diff[]
+:git-diff-core: 1
+endif::git-diff[]
+endif::git-format-patch[]
+
+ifdef::git-format-patch[]
 -p::
-       Generate patch (see section on generating patches)
+       Generate patches without diffstat.
+endif::git-format-patch[]
+
+ifndef::git-format-patch[]
+-p::
+       Generate patch (see section on generating patches).
+       {git-diff? This is the default.}
+endif::git-format-patch[]
 
 -u::
        Synonym for "-p".
@@ -13,6 +33,7 @@
 
 --raw::
        Generate the raw format.
+       {git-diff-core? This is the default.}
 
 --patch-with-raw::
        Synonym for "-p --raw".
@@ -41,6 +62,7 @@
 
 --patch-with-stat::
        Synonym for "-p --stat".
+       {git-format-patch? This is the default.}
 
 -z::
        NUL-line termination on output.  This affects the --raw
index fd82fc1..63829d9 100644 (file)
@@ -50,10 +50,10 @@ OPTIONS
        and `dir/file2`) can be given to add all files in the
        directory, recursively.
 
--n::
+-n, \--dry-run::
         Don't actually add the file(s), just show if they exist.
 
--v::
+-v, \--verbose::
         Be verbose.
 
 -f::
index 1072fb8..4795349 100644 (file)
@@ -16,8 +16,9 @@ The command takes various subcommands, and different options depending
 on the subcommand:
 
  git bisect start [<bad> [<good>...]] [--] [<paths>...]
- git bisect bad <rev>
- git bisect good <rev>
+ git bisect bad [<rev>]
+ git bisect good [<rev>...]
+ git bisect skip [<rev>...]
  git bisect reset [<branch>]
  git bisect visualize
  git bisect replay <logfile>
@@ -134,6 +135,20 @@ $ git reset --hard HEAD~3          # try 3 revs before what
 Then compile and test the one you chose to try. After that, tell
 bisect what the result was as usual.
 
+Bisect skip
+~~~~~~~~~~~~
+
+Instead of choosing by yourself a nearby commit, you may just want git
+to do it for you using:
+
+------------
+$ git bisect skip                 # Current version cannot be tested
+------------
+
+But computing the commit to test may be slower afterwards and git may
+eventually not be able to tell the first bad among a bad and one or
+more "skip"ped commits.
+
 Cutting down bisection by giving more parameters to bisect start
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -167,14 +182,18 @@ $ git bisect run my_script
 ------------
 
 Note that the "run" script (`my_script` in the above example) should
-exit with code 0 in case the current source code is good and with a
-code between 1 and 127 (included) in case the current source code is
-bad.
+exit with code 0 in case the current source code is good.  Exit with a
+code between 1 and 127 (inclusive), except 125, if the current
+source code is bad.
 
 Any other exit code will abort the automatic bisect process. (A
 program that does "exit(-1)" leaves $? = 255, see exit(3) manual page,
 the value is chopped with "& 0377".)
 
+The special exit code 125 should be used when the current source code
+cannot be tested. If the "run" script exits with this code, the current
+revision will be skipped, see `git bisect skip` above.
+
 You may often find that during bisect you want to have near-constant
 tweaks (e.g., s/#define DEBUG 0/#define DEBUG 1/ in a header file, or
 "revision that does not have this commit needs this patch applied to
index d64ad25..f87b696 100644 (file)
@@ -90,7 +90,7 @@ OPTIONS
 -a::
        List both remote-tracking branches and local branches.
 
--v::
+-v, --verbose::
        Show sha1 and commit subject line for each head.
 
 --abbrev=<length>::
index 47b1e8c..937c4a7 100644 (file)
@@ -7,7 +7,7 @@ git-cherry-pick - Apply the change introduced by an existing commit
 
 SYNOPSIS
 --------
-'git-cherry-pick' [--edit] [-n] [-x] <commit>
+'git-cherry-pick' [--edit] [-n] [-m parent-number] [-x] <commit>
 
 DESCRIPTION
 -----------
@@ -27,11 +27,12 @@ OPTIONS
        message prior committing.
 
 -x::
-       Cause the command to append which commit was
-       cherry-picked after the original commit message when
-       making a commit.  Do not use this option if you are
-       cherry-picking from your private branch because the
-       information is useless to the recipient.  If on the
+       When recording the commit, append to the original commit
+       message a note that indicates which commit this change
+       was cherry-picked from.  Append the note only for cherry
+       picks without conflicts.  Do not use this option if
+       you are cherry-picking from your private branch because
+       the information is useless to the recipient.  If on the
        other hand you are cherry-picking between two publicly
        visible branches (e.g. backporting a fix to a
        maintenance branch for an older release from a
@@ -43,6 +44,13 @@ OPTIONS
        described above, and `-r` was to disable it.  Now the
        default is not to do `-x` so this option is a no-op.
 
+-m parent-number|--mainline parent-number::
+       Usually you cannot revert a merge because you do not know which
+       side of the merge should be considered the mainline.  This
+       option specifies the parent number (starting from 1) of
+       the mainline and allows cherry-pick to replay the change
+       relative to the specified parent.
+
 -n|--no-commit::
        Usually the command automatically creates a commit with
        a commit log message stating which commit was
index cca14d6..c90bcec 100644 (file)
@@ -12,7 +12,7 @@ SYNOPSIS
 'git-clone' [--template=<template_directory>]
          [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare]
          [-o <name>] [-u <upload-pack>] [--reference <repository>]
-         [--depth <depth>] <repository> [<directory>]
+         [--depth <depth>] [--] <repository> [<directory>]
 
 DESCRIPTION
 -----------
@@ -130,6 +130,7 @@ OPTIONS
        for "host.xz:foo/.git").  Cloning into an existing directory
        is not allowed.
 
+:git-clone: 1
 include::urls.txt[]
 
 Examples
index c3922f9..3f9d229 100644 (file)
@@ -8,7 +8,7 @@ git-cvsexportcommit - Export a single commit to a CVS checkout
 
 SYNOPSIS
 --------
-'git-cvsexportcommit' [-h] [-u] [-v] [-c] [-P] [-p] [-a] [-d cvsroot] [-f] [-m msgprefix] [PARENTCOMMIT] COMMITID
+'git-cvsexportcommit' [-h] [-u] [-v] [-c] [-P] [-p] [-a] [-d cvsroot] [-w cvsworkdir] [-f] [-m msgprefix] [PARENTCOMMIT] COMMITID
 
 
 DESCRIPTION
@@ -16,8 +16,9 @@ DESCRIPTION
 Exports a commit from GIT to a CVS checkout, making it easier
 to merge patches from a git repository into a CVS repository.
 
-Execute it from the root of the CVS working copy. GIT_DIR must be defined.
-See examples below.
+Specify the name of a CVS checkout using the -w switch or execute it
+from the root of the CVS working copy. In the latter case GIT_DIR must
+be defined. See examples below.
 
 It does its best to do the safe thing, it will check that the files are
 unchanged and up to date in the CVS checkout, and it will not autocommit
@@ -61,6 +62,11 @@ OPTIONS
 -u::
        Update affected files from CVS repository before attempting export.
 
+-w::
+       Specify the location of the CVS checkout to use for the export. This
+       option does not require GIT_DIR to be set before execution if the
+       current directory is within a git repository.
+
 -v::
        Verbose.
 
@@ -76,6 +82,12 @@ $ git-cvsexportcommit -v <commit-sha1>
 $ cvs commit -F .msg <files>
 ------------
 
+Merge one patch into CVS (-c and -w options). The working directory is within the Git Repo::
++
+------------
+       $ git-cvsexportcommit -v -c -w ~/project_cvs_checkout <commit-sha1>
+------------
+
 Merge pending patches into CVS automatically -- only if you really know what you are doing::
 +
 ------------
@@ -86,11 +98,11 @@ $ git-cherry cvshead myhead | sed -n 's/^+ //p' | xargs -l1 git-cvsexportcommit
 
 Author
 ------
-Written by Martin Langhoff <martin@catalyst.net.nz>
+Written by Martin Langhoff <martin@catalyst.net.nz> and others.
 
 Documentation
 --------------
-Documentation by Martin Langhoff <martin@catalyst.net.nz>
+Documentation by Martin Langhoff <martin@catalyst.net.nz> and others.
 
 GIT
 ---
index 201d5da..2808a5e 100644 (file)
@@ -75,6 +75,7 @@ and the range notations ("<commit>..<commit>" and
 
 OPTIONS
 -------
+:git-diff: 1
 include::diff-options.txt[]
 
 <path>...::
@@ -128,7 +129,7 @@ $ git diff topic...master  <3>
 +
 <1> Changes between the tips of the topic and the master branches.
 <2> Same as above.
-<3> Changes that occured on the master branch since when the topic
+<3> Changes that occurred on the master branch since when the topic
 branch was started off it.
 
 Limiting the diff output::
index 6df8e85..f1f90cc 100644 (file)
@@ -100,6 +100,11 @@ In any case, a field name that refers to a field inapplicable to
 the object referred by the ref does not cause an error.  It
 returns an empty string instead.
 
+As a special case for the date-type fields, you may specify a format for
+the date by adding one of `:default`, `:relative`, `:short`, `:local`,
+`:iso8601` or `:rfc2822` to the end of the fieldname; e.g.
+`%(taggerdate:relative)`.
+
 
 EXAMPLES
 --------
index f0617ef..6fb9429 100644 (file)
@@ -9,9 +9,10 @@ git-format-patch - Prepare patches for e-mail submission
 SYNOPSIS
 --------
 [verse]
-'git-format-patch' [-n | -k] [-o <dir> | --stdout] [--thread]
+'git-format-patch' [-k] [-o <dir> | --stdout] [--thread]
                    [--attach[=<boundary>] | --inline[=<boundary>]]
                    [-s | --signoff] [<common diff options>]
+                   [-n | --numbered | -N | --no-numbered]
                    [--start-number <n>] [--numbered-files]
                    [--in-reply-to=Message-Id] [--suffix=.<sfx>]
                    [--ignore-if-in-upstream]
@@ -65,6 +66,7 @@ reference.
 
 OPTIONS
 -------
+:git-format-patch: 1
 include::diff-options.txt[]
 
 -<n>::
@@ -77,6 +79,9 @@ include::diff-options.txt[]
 -n|--numbered::
        Name output in '[PATCH n/m]' format.
 
+-N|--no-numbered::
+       Name output in '[PATCH]' format.
+
 --start-number <n>::
        Start numbering the patches at <n> instead of 1.
 
@@ -142,15 +147,16 @@ not add any suffix.
 
 CONFIGURATION
 -------------
-You can specify extra mail header lines to be added to each
-message in the repository configuration.  You can also specify
-new defaults for the subject prefix and file suffix.
+You can specify extra mail header lines to be added to each message
+in the repository configuration, new defaults for the subject prefix
+and file suffix, and number patches when outputting more than one.
 
 ------------
 [format]
         headers = "Organization: git-foo\n"
         subjectprefix = CHANGE
         suffix = .txt
+        numbered = auto
 ------------
 
 
index c7742ca..872056e 100644 (file)
@@ -8,7 +8,7 @@ git-gc - Cleanup unnecessary files and optimize the local repository
 
 SYNOPSIS
 --------
-'git-gc' [--prune] [--aggressive]
+'git-gc' [--prune] [--aggressive] [--auto]
 
 DESCRIPTION
 -----------
@@ -19,7 +19,8 @@ created from prior invocations of gitlink:git-add[1].
 
 Users are encouraged to run this task on a regular basis within
 each repository to maintain good disk space utilization and good
-operating performance.
+operating performance. Some git commands may automatically run
+`git-gc`; see the `--auto` flag below for details.
 
 OPTIONS
 -------
@@ -43,6 +44,25 @@ OPTIONS
        persistent, so this option only needs to be used occasionally; every
        few hundred changesets or so.
 
+--auto::
+       With this option, `git gc` checks whether any housekeeping is
+       required; if not, it exits without performing any work.
+       Some git commands run `git gc --auto` after performing
+       operations that could create many loose objects.
++
+Housekeeping is required if there are too many loose objects or
+too many packs in the repository. If the number of loose objects
+exceeds the value of the `gc.auto` configuration variable, then
+all loose objects are combined into a single pack using
+`git-repack -d -l`.  Setting the value of `gc.auto` to 0
+disables automatic packing of loose objects.
++
+If the number of packs exceeds the value of `gc.autopacklimit`,
+then existing packs (except those marked with a `.keep` file)
+are consolidated into a single pack by using the `-A` option of
+`git-repack`. Setting `gc.autopacklimit` to 0 disables
+automatic consolidation of packs.
+
 Configuration
 -------------
 
index 9afb860..3a69b71 100644 (file)
@@ -8,7 +8,7 @@ git-http-push - Push objects over HTTP/DAV to another repository
 
 SYNOPSIS
 --------
-'git-http-push' [--all] [--force] [--verbose] <url> <ref> [<ref>...]
+'git-http-push' [--all] [--dry-run] [--force] [--verbose] <url> <ref> [<ref>...]
 
 DESCRIPTION
 -----------
@@ -30,6 +30,9 @@ OPTIONS
        the remote repository can lose commits; use it with
        care.
 
+--dry-run::
+       Do everything except actually send the updates.
+
 --verbose::
        Report the list of objects being walked locally and the
        list of objects successfully sent to the remote repository.
index a8a7f6f..bf5c2bd 100644 (file)
@@ -43,7 +43,7 @@ OPTIONS
        a default name determined from the pack content.  If
        <pack-file> is not specified consider using --keep to
        prevent a race condition between this process and
-       gitlink::git-repack[1] .
+       gitlink::git-repack[1].
 
 --fix-thin::
        It is possible for gitlink:git-pack-objects[1] to build
index cec60ee..735008c 100644 (file)
@@ -27,7 +27,7 @@ OPTIONS
        The HTTP daemon command-line that will be executed.
        Command-line options may be specified here, and the
        configuration file will be added at the end of the command-line.
-       Currently, lighttpd and apache2 are the only supported servers.
+       Currently lighttpd, apache2 and webrick are supported.
        (Default: lighttpd)
 
 -m|--module-path::
diff --git a/Documentation/git-local-fetch.txt b/Documentation/git-local-fetch.txt
deleted file mode 100644 (file)
index e830dee..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-git-local-fetch(1)
-==================
-
-NAME
-----
-git-local-fetch - Duplicate another git repository on a local system
-
-
-SYNOPSIS
---------
-[verse]
-'git-local-fetch' [-c] [-t] [-a] [-d] [-v] [-w filename] [--recover] [-l] [-s] [-n]
-                  commit-id path
-
-DESCRIPTION
------------
-THIS COMMAND IS DEPRECATED.
-
-Duplicates another git repository on a local system.
-
-OPTIONS
--------
--c::
-       Get the commit objects.
--t::
-       Get trees associated with the commit objects.
--a::
-       Get all the objects.
--v::
-       Report what is downloaded.
--s::
-       Instead of regular file-to-file copying use symbolic links to the objects
-       in the remote repository.
--l::
-       Before attempting symlinks (if -s is specified) or file-to-file copying the
-       remote objects, try to hardlink the remote objects into the local
-       repository.
--n::
-       Never attempt to file-to-file copy remote objects.  Only useful with
-       -s or -l command-line options.
-
--w <filename>::
-        Writes the commit-id into the filename under $GIT_DIR/refs/<filename> on
-        the local end after the transfer is complete.
-
---stdin::
-       Instead of a commit id on the command line (which is not expected in this
-       case), 'git-local-fetch' expects lines on stdin in the format
-
-               <commit-id>['\t'<filename-as-in--w>]
-
---recover::
-       Verify that everything reachable from target is fetched.  Used after
-       an earlier fetch is interrupted.
-
-Author
-------
-Written by Junio C Hamano <junkio@cox.net>
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
-GIT
----
-Part of the gitlink:git[7] suite
index bc73911..7f808fc 100644 (file)
@@ -11,6 +11,10 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
+
+*NOTE*: this command is deprecated.  Use gitlink:git-fsck[1] with
+the option '--lost-found' instead.
+
 Finds dangling commits and tags from the object database, and
 creates refs to them in the .git/lost-found/ directory.  Commits and
 tags that dereference to commits are stored in .git/lost-found/commit,
index 9e454f0..2ec0c0d 100644 (file)
@@ -15,6 +15,7 @@ SYNOPSIS
                [-x <pattern>|--exclude=<pattern>]
                [-X <file>|--exclude-from=<file>]
                [--exclude-per-directory=<file>]
+               [--exclude-standard]
                [--error-unmatch] [--with-tree=<tree-ish>]
                [--full-name] [--abbrev] [--] [<file>]\*
 
@@ -77,6 +78,10 @@ OPTIONS
        read additional exclude patterns that apply only to the
        directory and its subdirectories in <file>.
 
+--exclude-standard::
+       Add the standard git exclusions: .git/info/exclude, .gitignore
+       in each directory, and the user's global exclusion file.
+
 --error-unmatch::
        If any <file> does not appear in the index, treat this as an
        error (return 1).
index 17e9f10..b726ddf 100644 (file)
@@ -40,7 +40,7 @@ If "git-merge-index" is called with multiple <file>s (or -a) then it
 processes them in turn only stopping if merge returns a non-zero exit
 code.
 
-Typically this is run with the a script calling git's imitation of
+Typically this is run with a script calling git's imitation of
 the merge command from the RCS package.
 
 A sample script called "git-merge-one-file" is included in the
index 827838f..eabd7ef 100644 (file)
@@ -59,6 +59,10 @@ merge.verbosity::
        above outputs debugging information.  The default is level 2.
        Can be overridden by 'GIT_MERGE_VERBOSITY' environment variable.
 
+branch.<name>.mergeoptions::
+       Sets default options for merging into branch <name>. The syntax and
+       supported options are equal to that of git-merge, but option values
+       containing whitespace characters are currently not supported.
 
 HOW MERGE WORKS
 ---------------
index 6c32c6d..a26c260 100644 (file)
@@ -25,12 +25,18 @@ OPTIONS
 -t or --tool=<tool>::
        Use the merge resolution program specified by <tool>.
        Valid merge tools are:
-       kdiff3, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff, and opendiff
+       kdiff3, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff, ecmerge, and opendiff
 +
 If a merge resolution program is not specified, 'git mergetool'
 will use the configuration variable merge.tool.  If the
 configuration variable merge.tool is not set, 'git mergetool'
 will pick a suitable default.
++
+You can explicitly provide a full path to the tool by setting the
+configuration variable mergetool.<tool>.path. For example, you
+can configure the absolute path to kdiff3 by setting
+mergetool.kdiff3.path. Otherwise, 'git mergetool' assumes the tool
+is available in PATH.
 
 Author
 ------
index 2c9cf74..3b8ca76 100644 (file)
@@ -34,7 +34,7 @@ OPTIONS
        condition. An error happens when a source is neither existing nor
         controlled by GIT, or when it would overwrite an existing
         file unless '-f' is given.
--n::
+-n, \--dry-run::
        Do nothing; only show what would happen
 
 
index d18259d..5237ab0 100644 (file)
@@ -169,6 +169,14 @@ base-name::
        length, this option typically shrinks the resulting
        packfile by 3-5 per-cent.
 
+--threads=<n>::
+       Specifies the number of threads to spawn when searching for best
+       delta matches.  This requires that pack-objects be compiled with
+       pthreads otherwise this option is ignored with a warning.
+       This is meant to reduce packing time on multiprocessor machines.
+       The required amount of memory for the delta search window is
+       however multiplied by the number of threads.
+
 --index-version=<version>[,<offset>]::
        This is intended to be used by the test suite only. It allows
        to force the version for the generated pack index, and to force
index abc1712..38a5325 100644 (file)
@@ -12,8 +12,7 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-Lists the references the remote repository has, and optionally
-stores them in the local repository under the same name.
+This command is deprecated; use `git-ls-remote` instead.
 
 OPTIONS
 -------
index 6bc559d..b8003c6 100644 (file)
@@ -9,8 +9,8 @@ git-push - Update remote refs along with associated objects
 SYNOPSIS
 --------
 [verse]
-'git-push' [--all] [--tags] [--receive-pack=<git-receive-pack>]
-           [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]
+'git-push' [--all] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>]
+           [--repo=all] [-f | --force] [-v | --verbose] [<repository> <refspec>...]
 
 DESCRIPTION
 -----------
@@ -63,6 +63,17 @@ the remote repository.
        Instead of naming each ref to push, specifies that all
        refs under `$GIT_DIR/refs/heads/` be pushed.
 
+\--mirror::
+       Instead of naming each ref to push, specifies that all
+       refs under `$GIT_DIR/refs/heads/` and `$GIT_DIR/refs/tags/`
+       be mirrored to the remote repository.  Newly created local
+       refs will be pushed to the remote end, locally updated refs
+       will be force updated on the remote end, and deleted refs
+       will be removed from the remote end.
+
+\--dry-run::
+       Do everything except actually send the updates.
+
 \--tags::
        All refs under `$GIT_DIR/refs/tags` are pushed, in
        addition to refspecs explicitly listed on the command
@@ -92,7 +103,7 @@ the remote repository.
        transfer spends extra cycles to minimize the number of
        objects to be sent and meant to be used on slower connection.
 
--v::
+-v, \--verbose::
        Run verbosely.
 
 include::urls-remotes.txt[]
index dfb8a0d..e4326d3 100644 (file)
@@ -8,8 +8,9 @@ git-rebase - Forward-port local commits to the updated upstream head
 SYNOPSIS
 --------
 [verse]
-'git-rebase' [-i | --interactive] [-v | --verbose] [-m | --merge] [-C<n>]
-       [-p | --preserve-merges] [--onto <newbase>] <upstream> [<branch>]
+'git-rebase' [-i | --interactive] [-v | --verbose] [-m | --merge]
+       [-C<n>] [ --whitespace=<option>] [-p | --preserve-merges]
+       [--onto <newbase>] <upstream> [<branch>]
 'git-rebase' --continue | --skip | --abort
 
 DESCRIPTION
@@ -27,7 +28,10 @@ The current branch is reset to <upstream>, or <newbase> if the
 `git reset --hard <upstream>` (or <newbase>).
 
 The commits that were previously saved into the temporary area are
-then reapplied to the current branch, one by one, in order.
+then reapplied to the current branch, one by one, in order. Note that
+any commits in HEAD which introduce the same textual changes as a commit
+in HEAD..<upstream> are omitted (i.e., a patch already accepted upstream
+with a different commit message or timestamp will be skipped).
 
 It is possible that a merge failure will prevent this process from being
 completely automatic.  You will have to resolve any such merge failure
@@ -61,6 +65,26 @@ would be:
 The latter form is just a short-hand of `git checkout topic`
 followed by `git rebase master`.
 
+If the upstream branch already contains a change you have made (e.g.,
+because you mailed a patch which was applied upstream), then that commit
+will be skipped. For example, running `git-rebase master` on the
+following history (in which A' and A introduce the same set of changes,
+but have different committer information):
+
+------------
+          A---B---C topic
+         /
+    D---E---A'---F master
+------------
+
+will result in:
+
+------------
+                   B'---C' topic
+                  /
+    D---E---A'---F master
+------------
+
 Here is how you would transplant a topic branch based on one
 branch to another, to pretend that you forked the topic branch
 from the latter branch, using `rebase --onto`.
@@ -209,6 +233,10 @@ OPTIONS
        context exist they all must match.  By default no context is
        ever ignored.
 
+--whitespace=<nowarn|warn|error|error-all|strip>::
+       This flag is passed to the `git-apply` program
+       (see gitlink:git-apply[1]) that applies the patch.
+
 -i, \--interactive::
        Make a list of the commits which are about to be rebased.  Let the
        user edit that list before rebasing.  This mode can also be used to
index 886bc03..4b263c2 100644 (file)
@@ -10,7 +10,8 @@ SYNOPSIS
 --------
 [verse]
 'git-remote'
-'git-remote' add [-t <branch>] [-m <branch>] [-f] <name> <url>
+'git-remote' add [-t <branch>] [-m <branch>] [-f] [--mirror] <name> <url>
+'git-remote' rm <name>
 'git-remote' show <name>
 'git-remote' prune <name>
 'git-remote' update [group]
@@ -45,6 +46,15 @@ multiple branches without grabbing all branches.
 With `-m <master>` option, `$GIT_DIR/remotes/<name>/HEAD` is set
 up to point at remote's `<master>` branch instead of whatever
 branch the `HEAD` at the remote repository actually points at.
++
+In mirror mode, enabled with `--mirror`, the refs will not be stored
+in the 'refs/remotes/' namespace, but in 'refs/heads/'.  This option
+only makes sense in bare repositories.
+
+'rm'::
+
+Remove the remote named <name>. All remote tracking branches and
+configuration settings for the remote are removed.
 
 'show'::
 
index 87afa6f..050e4ea 100644 (file)
@@ -8,8 +8,8 @@ git-reset - Reset current HEAD to the specified state
 SYNOPSIS
 --------
 [verse]
-'git-reset' [--mixed | --soft | --hard] [<commit>]
-'git-reset' [--mixed] <commit> [--] <paths>...
+'git-reset' [--mixed | --soft | --hard] [-q] [<commit>]
+'git-reset' [--mixed] [-q] <commit> [--] <paths>...
 
 DESCRIPTION
 -----------
@@ -45,6 +45,9 @@ OPTIONS
        switched to. Any changes to tracked files in the working tree
        since <commit> are lost.
 
+-q::
+       Be quiet, only report errors.
+
 <commit>::
        Commit to make the current HEAD.
 
index 7cd0e89..989fbf3 100644 (file)
@@ -20,6 +20,7 @@ SYNOPSIS
             [ \--not ]
             [ \--all ]
             [ \--stdin ]
+            [ \--quiet ]
             [ \--topo-order ]
             [ \--parents ]
             [ \--timestamp ]
@@ -34,6 +35,7 @@ SYNOPSIS
             [ \--pretty | \--header ]
             [ \--bisect ]
             [ \--bisect-vars ]
+            [ \--bisect-all ]
             [ \--merge ]
             [ \--reverse ]
             [ \--walk-reflogs ]
@@ -269,6 +271,14 @@ limiting may be applied.
        In addition to the '<commit>' listed on the command
        line, read them from the standard input.
 
+--quiet::
+
+       Don't print anything to standard output.  This form of
+       git-rev-list is primarly meant to allow the caller to
+       test the exit status to see if a range of objects is fully
+       connected (or not).  It is faster than redirecting stdout
+       to /dev/null as the output does not have to be formatted.
+
 --cherry-pick::
 
        Omit any commit that introduces the same change as
@@ -354,6 +364,21 @@ the expected number of commits to be tested if `bisect_rev`
 turns out to be bad to `bisect_bad`, and the number of commits
 we are bisecting right now to `bisect_all`.
 
+--bisect-all::
+
+This outputs all the commit objects between the included and excluded
+commits, ordered by their distance to the included and excluded
+commits. The farthest from them is displayed first. (This is the only
+one displayed by `--bisect`.)
+
+This is useful because it makes it easy to choose a good commit to
+test when you want to avoid to test some of them for some reason (they
+may not compile for example).
+
+This option can be used along with `--bisect-vars`, in this case,
+after all the sorted commit objects, there will be the same text as if
+`--bisect-vars` had been used alone.
+
 --
 
 Commit Ordering
index 4758c33..329fce0 100644 (file)
@@ -23,6 +23,13 @@ distinguish between them.
 
 OPTIONS
 -------
+--parseopt::
+       Use `git-rev-parse` in option parsing mode (see PARSEOPT section below).
+
+--keep-dash-dash::
+       Only meaningful in `--parseopt` mode. Tells the option parser to echo
+       out the first `--` met instead of skipping it.
+
 --revs-only::
        Do not output flags and parameters not meant for
        `git-rev-list` command.
@@ -288,10 +295,75 @@ Here are a handful examples:
    C^@              I J F
    F^! D            G H D F
 
+PARSEOPT
+--------
+
+In `--parseopt` mode, `git-rev-parse` helps massaging options to bring to shell
+scripts the same facilities C builtins have. It works as an option normalizer
+(e.g. splits single switches aggregate values), a bit like `getopt(1)` does.
+
+It takes on the standard input the specification of the options to parse and
+understand, and echoes on the standard output a line suitable for `sh(1)` `eval`
+to replace the arguments with normalized ones.  In case of error, it outputs
+usage on the standard error stream, and exits with code 129.
+
+Input Format
+~~~~~~~~~~~~
+
+`git-rev-parse --parseopt` input format is fully text based. It has two parts,
+separated by a line that contains only `--`. The lines before the separator
+(should be more than one) are used for the usage.
+The lines after the separator describe the options.
+
+Each line of options has this format:
+
+------------
+<opt_spec><arg_spec>? SP+ help LF
+------------
+
+`<opt_spec>`::
+       its format is the short option character, then the long option name
+       separated by a comma. Both parts are not required, though at least one
+       is necessary. `h,help`, `dry-run` and `f` are all three correct
+       `<opt_spec>`.
+
+`<arg_spec>`::
+       an `<arg_spec>` tells the option parser if the option has an argument
+       (`=`), an optional one (`?` though its use is discouraged) or none
+       (no `<arg_spec>` in that case).
+
+The remainder of the line, after stripping the spaces, is used
+as the help associated to the option.
+
+Blank lines are ignored, and lines that don't match this specification are used
+as option group headers (start the line with a space to create such
+lines on purpose).
+
+Example
+~~~~~~~
+
+------------
+OPTS_SPEC="\
+some-command [options] <args>...
+
+some-command does foo and bar!
+--
+h,help    show the help
+
+foo       some nifty option --foo
+bar=      some cool option --bar with an argument
+
+  An option group Header
+C?        option C with an optional argument"
+
+eval `echo "$OPTS_SPEC" | git-rev-parse --parseopt -- "$@" || echo exit $?`
+------------
+
+
 Author
 ------
-Written by Linus Torvalds <torvalds@osdl.org> and
-Junio C Hamano <junkio@cox.net>
+Written by Linus Torvalds <torvalds@osdl.org> .
+Junio C Hamano <junkio@cox.net> and Pierre Habouzit <madcoder@debian.org>
 
 Documentation
 --------------
index 69db498..3457c40 100644 (file)
@@ -7,7 +7,7 @@ git-revert - Revert an existing commit
 
 SYNOPSIS
 --------
-'git-revert' [--edit | --no-edit] [-n] <commit>
+'git-revert' [--edit | --no-edit] [-n] [-m parent-number] <commit>
 
 DESCRIPTION
 -----------
@@ -27,6 +27,13 @@ OPTIONS
        message prior committing the revert. This is the default if
        you run the command from a terminal.
 
+-m parent-number|--mainline parent-number::
+       Usually you cannot revert a merge because you do not know which
+       side of the merge should be considered the mainline.  This
+       option specifies the parent number (starting from 1) of
+       the mainline and allows revert to reverse the change
+       relative to the specified parent.
+
 --no-edit::
        With this option, `git-revert` will not start the commit
        message editor.
index be61a82..48c1d97 100644 (file)
@@ -30,7 +30,7 @@ OPTIONS
 -f::
        Override the up-to-date check.
 
--n::
+-n, \--dry-run::
         Don't actually remove the file(s), just show if they exist in
         the index.
 
@@ -51,7 +51,7 @@ OPTIONS
 \--ignore-unmatch::
        Exit with a zero status even if no files matched.
 
-\--quiet::
+-q, \--quiet::
        git-rm normally outputs one line (in the form of an "rm" command)
        for each file removed. This option suppresses that output.
 
index 16bfd7b..659215a 100644 (file)
@@ -75,6 +75,12 @@ The --cc option must be repeated for each user you want on the cc list.
        Make git-send-email less verbose.  One line per email should be
        all that is output.
 
+--identity::
+       A configuration identity. When given, causes values in the
+       'sendemail.<identity>' subsection to take precedence over
+       values in the 'sendemail' section. The default identity is
+       the value of 'sendemail.identity'.
+
 --smtp-server::
        If set, specifies the outgoing SMTP server to use (e.g.
        `smtp.example.com` or a raw IP address).  Alternatively it can
@@ -85,14 +91,29 @@ The --cc option must be repeated for each user you want on the cc list.
        `/usr/lib/sendmail` if such program is available, or
        `localhost` otherwise.
 
+--smtp-server-port::
+       Specifies a port different from the default port (SMTP
+       servers typically listen to smtp port 25 and ssmtp port
+       465).
+
+--smtp-user, --smtp-pass::
+       Username and password for SMTP-AUTH. Defaults are the values of
+       the configuration values 'sendemail.smtpuser' and
+       'sendemail.smtppass', but see also 'sendemail.identity'.
+       If not set, authentication is not attempted.
+
+--smtp-ssl::
+       If set, connects to the SMTP server using SSL.
+       Default is the value of the 'sendemail.smtpssl' configuration value;
+       if that is unspecified, does not use SSL.
+
 --subject::
        Specify the initial subject of the email thread.
        Only necessary if --compose is also set.  If --compose
        is not set, this will be prompted for.
 
 --suppress-from, --no-suppress-from::
-        If this is set, do not add the From: address to the cc: list, if it
-        shows up in a From: line.
+        If this is set, do not add the From: address to the cc: list.
         Default is the value of 'sendemail.suppressfrom' configuration value;
         if that is unspecified, default to --no-suppress-from.
 
@@ -122,6 +143,13 @@ The --to option must be repeated for each user you want on the to list.
 
 CONFIGURATION
 -------------
+sendemail.identity::
+       The default configuration identity. When specified,
+       'sendemail.<identity>.<item>' will have higher precedence than
+       'sendemail.<item>'. This is useful to declare multiple SMTP
+       identities and to hoist sensitive authentication information
+       out of the repository and into the global configuation file.
+
 sendemail.aliasesfile::
        To avoid typing long email addresses, point this to one or more
        email aliases files.  You must also supply 'sendemail.aliasfiletype'.
@@ -130,6 +158,9 @@ sendemail.aliasfiletype::
        Format of the file(s) specified in sendemail.aliasesfile. Must be
        one of 'mutt', 'mailrc', 'pine', or 'gnus'.
 
+sendemail.to::
+       Email address (or alias) to always send to.
+
 sendemail.cccmd::
        Command to execute to generate per patch file specific "Cc:"s.
 
@@ -141,7 +172,16 @@ sendemail.chainreplyto::
        parameter.
 
 sendemail.smtpserver::
-       Default smtp server to use.
+       Default SMTP server to use.
+
+sendemail.smtpuser::
+       Default SMTP-AUTH username.
+
+sendemail.smtppass::
+       Default SMTP-AUTH password.
+
+sendemail.smtpssl::
+       Boolean value specifying the default to the '--smtp-ssl' parameter.
 
 Author
 ------
index 3271e88..2fa01d4 100644 (file)
@@ -8,7 +8,7 @@ git-send-pack - Push objects over git protocol to another repository
 
 SYNOPSIS
 --------
-'git-send-pack' [--all] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]
+'git-send-pack' [--all] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]
 
 DESCRIPTION
 -----------
@@ -34,6 +34,9 @@ OPTIONS
        Instead of explicitly specifying which refs to update,
        update all heads that locally exist.
 
+\--dry-run::
+       Do everything except actually send the updates.
+
 \--force::
        Usually, the command refuses to update a remote ref that
        is not an ancestor of the local ref used to overwrite it.
diff --git a/Documentation/git-ssh-fetch.txt b/Documentation/git-ssh-fetch.txt
deleted file mode 100644 (file)
index 8d3e2ff..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-git-ssh-fetch(1)
-================
-
-NAME
-----
-git-ssh-fetch - Fetch from a remote repository over ssh connection
-
-
-
-SYNOPSIS
---------
-'git-ssh-fetch' [-c] [-t] [-a] [-d] [-v] [-w filename] [--recover] commit-id url
-
-DESCRIPTION
------------
-THIS COMMAND IS DEPRECATED.
-
-Pulls from a remote repository over ssh connection, invoking
-git-ssh-upload on the other end. It functions identically to
-git-ssh-upload, aside from which end you run it on.
-
-
-OPTIONS
--------
-commit-id::
-        Either the hash or the filename under [URL]/refs/ to
-        pull.
-
--c::
-       Get the commit objects.
--t::
-       Get trees associated with the commit objects.
--a::
-       Get all the objects.
--v::
-       Report what is downloaded.
--w::
-        Writes the commit-id into the filename under $GIT_DIR/refs/ on
-        the local end after the transfer is complete.
-
-
-Author
-------
-Written by Daniel Barkalow <barkalow@iabervon.org>
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
-GIT
----
-Part of the gitlink:git[7] suite
diff --git a/Documentation/git-ssh-upload.txt b/Documentation/git-ssh-upload.txt
deleted file mode 100644 (file)
index 5e2ca8d..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-git-ssh-upload(1)
-=================
-
-NAME
-----
-git-ssh-upload - Push to a remote repository over ssh connection
-
-
-SYNOPSIS
---------
-'git-ssh-upload' [-c] [-t] [-a] [-d] [-v] [-w filename] [--recover] commit-id url
-
-DESCRIPTION
------------
-THIS COMMAND IS DEPRECATED.
-
-Pushes from a remote repository over ssh connection, invoking
-git-ssh-fetch on the other end. It functions identically to
-git-ssh-fetch, aside from which end you run it on.
-
-OPTIONS
--------
-commit-id::
-        Id of commit to push.
-
--c::
-        Get the commit objects.
--t::
-        Get tree associated with the requested commit object.
--a::
-        Get all the objects.
--v::
-        Report what is uploaded.
--w::
-        Writes the commit-id into the filename under [URL]/refs/ on
-        the remote end after the transfer is complete.
-
-Author
-------
-Written by Daniel Barkalow <barkalow@iabervon.org>
-
-Documentation
---------------
-Documentation by Daniel Barkalow
-
-GIT
----
-Part of the gitlink:git[7] suite
index 5723bb0..c0147b9 100644 (file)
@@ -57,7 +57,7 @@ stash@{1}: On master: 9cc0589... Add git-stash
 
 show [<stash>]::
 
-       Show the changes recorded in the stash as a diff between the the
+       Show the changes recorded in the stash as a diff between the
        stashed state and its original parent. When no `<stash>` is given,
        shows the latest one. By default, the command shows the diffstat, but
        it will accept any format known to `git-diff` (e.g., `git-stash show
index 2c48936..335e973 100644 (file)
@@ -21,6 +21,9 @@ add::
        repository is cloned at the specified path, added to the
        changeset and registered in .gitmodules.   If no path is
        specified, the path is deduced from the repository specification.
+       If the repository url begins with ./ or ../, it is stored as
+       given but resolved as a relative path from the main project's
+       url when cloning.
 
 status::
        Show the status of the submodules. This will print the SHA-1 of the
index e157c6a..918a992 100644 (file)
@@ -193,6 +193,12 @@ Any other arguments are passed directly to `git log'
        repository (that has been init-ed with git-svn).
        The -r<revision> option is required for this.
 
+'info'::
+       Shows information about a file or directory similar to what
+       `svn info' provides.  Does not currently support a -r/--revision
+       argument.  Use the --url option to output only the value of the
+       'URL:' field.
+
 --
 
 OPTIONS
@@ -404,7 +410,7 @@ section because they affect the 'git-svn-id:' metadata line.
 BASIC EXAMPLES
 --------------
 
-Tracking and contributing to the trunk of a Subversion-managed project:
+Tracking and contributing to the trunk of a Subversion-managed project:
 
 ------------------------------------------------------------------------
 # Clone a repo (like git clone):
index a88f722..694caba 100644 (file)
@@ -26,7 +26,7 @@ a regular file whose contents is `ref: refs/heads/master`.
 OPTIONS
 -------
 
--q::
+-q, --quiet::
        Do not issue an error message if the <name> is not a
        symbolic ref but a detached HEAD; instead exit with
        non-zero status silently.
index 990ae4f..10d3e3f 100644 (file)
@@ -112,7 +112,7 @@ You really want to call the new version "X" too, 'even though'
 others have already seen the old one. So just use "git tag -f"
 again, as if you hadn't already published the old one.
 
-However, Git does *not* (and it should not)change tags behind
+However, Git does *not* (and it should not) change tags behind
 users back. So if somebody already got the old tag, doing a "git
 pull" on your tree shouldn't just make them overwrite the old
 one.
@@ -214,6 +214,27 @@ having tracking branches.  Again, the heuristic to automatically
 follow such tags is a good thing.
 
 
+On Backdating Tags
+~~~~~~~~~~~~~~~~~~
+
+If you have imported some changes from another VCS and would like
+to add tags for major releases of your work, it is useful to be able
+to specify the date to embed inside of the tag object.  The data in
+the tag object affects, for example, the ordering of tags in the
+gitweb interface.
+
+To set the date used in future tag objects, set the environment
+variable GIT_AUTHOR_DATE to one or more of the date and time.  The
+date and time can be specified in a number of ways; the most common
+is "YYYY-MM-DD HH:MM".
+
+An example follows.
+
+------------
+$ GIT_AUTHOR_DATE="2006-10-02 10:31" git tag -s v1.0.1
+------------
+
+
 Author
 ------
 Written by Linus Torvalds <torvalds@osdl.org>,
index 10653ff..a96403c 100644 (file)
@@ -22,6 +22,9 @@ Alternative/Augmentative Porcelains
    providing generally smoother user experience than the "raw" Core GIT
    itself and indeed many other version control systems.
 
+   Cogito is no longer maintained as most of its functionality
+   is now in core GIT.
+
 
    - *pg* (http://www.spearce.org/category/projects/scm/pg/)
 
@@ -33,7 +36,7 @@ Alternative/Augmentative Porcelains
    - *StGit* (http://www.procode.org/stgit/)
 
    Stacked GIT provides a quilt-like patch management functionality in the
-    GIT environment. You can easily manage your patches in the scope of GIT
+   GIT environment. You can easily manage your patches in the scope of GIT
    until they get merged upstream.
 
 
index a7cd91a..9ff4659 100644 (file)
@@ -46,7 +46,14 @@ Documentation for older releases are available here:
 * link:v1.5.3/git.html[documentation for release 1.5.3]
 
 * release notes for
-  link:RelNotes-1.5.3.1.txt[1.5.3.1].
+  link:RelNotes-1.5.3.7.txt[1.5.3.7],
+  link:RelNotes-1.5.3.6.txt[1.5.3.6],
+  link:RelNotes-1.5.3.5.txt[1.5.3.5],
+  link:RelNotes-1.5.3.4.txt[1.5.3.4],
+  link:RelNotes-1.5.3.3.txt[1.5.3.3],
+  link:RelNotes-1.5.3.2.txt[1.5.3.2],
+  link:RelNotes-1.5.3.1.txt[1.5.3.1],
+  link:RelNotes-1.5.3.txt[1.5.3].
 
 * release notes for
   link:RelNotes-1.5.2.5.txt[1.5.2.5],
@@ -323,7 +330,7 @@ For a more complete list of ways to spell object names, see
 File/Directory Structure
 ------------------------
 
-Please see link:repository-layout.html[repository layout] document.
+Please see the link:repository-layout.html[repository layout] document.
 
 Read link:hooks.html[hooks] for more details about each hook.
 
@@ -333,7 +340,7 @@ Higher level SCMs may provide and manage additional information in the
 
 Terminology
 -----------
-Please see link:glossary.html[glossary] document.
+Please see the link:glossary.html[glossary] document.
 
 
 Environment Variables
index cf4ee2e..19bd25f 100644 (file)
@@ -410,6 +410,23 @@ frotz      unspecified
 ----------------------------------------------------------------
 
 
+Creating an archive
+~~~~~~~~~~~~~~~~~~~
+
+`export-subst`
+^^^^^^^^^^^^^^
+
+If the attribute `export-subst` is set for a file then git will expand
+several placeholders when adding this file to an archive.  The
+expansion depends on the availability of a commit ID, i.e. if
+gitlink:git-archive[1] has been given a tree instead of a commit or a
+tag then no replacement will be done.  The placeholders are the same
+as those for the option `--pretty=format:` of gitlink:git-log[1],
+except that they need to be wrapped like this: `$Format:PLACEHOLDERS$`
+in the file.  E.g. the string `$Format:%H$` will be replaced by the
+commit hash.
+
+
 GIT
 ---
 Part of the gitlink:git[7] suite
index 3f7b1e4..fc18744 100644 (file)
@@ -52,8 +52,8 @@ GIT Glossary
 [[def_cherry-picking]]cherry-picking::
        In <<def_SCM,SCM>> jargon, "cherry pick" means to choose a subset of
        changes out of a series of changes (typically commits) and record them
-       as a new series of changes on top of different codebase. In GIT, this is
-       performed by "git cherry-pick" command to extract the change introduced
+       as a new series of changes on top of different codebase. In GIT, this is
+       performed by the "git cherry-pick" command to extract the change introduced
        by an existing <<def_commit,commit>> and to record it based on the tip
        of the current <<def_branch,branch>> as a new commit.
 
@@ -281,7 +281,7 @@ This commit is referred to as a "merge commit", or sometimes just a
 [[def_pickaxe]]pickaxe::
        The term <<def_pickaxe,pickaxe>> refers to an option to the diffcore
        routines that help select changes that add or delete a given text
-       string. With the --pickaxe-all option, it can be used to view the full
+       string. With the `--pickaxe-all` option, it can be used to view the full
        <<def_changeset,changeset>> that introduced or removed, say, a
        particular line of text. See gitlink:git-diff[1].
 
@@ -301,8 +301,8 @@ This commit is referred to as a "merge commit", or sometimes just a
 [[def_push]]push::
        Pushing a <<def_branch,branch>> means to get the branch's
        <<def_head_ref,head ref>> from a remote <<def_repository,repository>>,
-       find out if it is an ancestor to the branch's local
-       head ref is a direct, and in that case, putting all
+       find out if it is a direct ancestor to the branch's local
+       head ref, and in that case, putting all
        objects, which are <<def_reachable,reachable>> from the local
        head ref, and which are missing from the remote
        repository, into the remote
@@ -347,7 +347,7 @@ This commit is referred to as a "merge commit", or sometimes just a
        it as my origin branch head". And `git push
        $URL refs/heads/master:refs/heads/to-upstream` means "publish my
        master branch head as to-upstream branch at $URL". See also
-       gitlink:git-push[1]
+       gitlink:git-push[1].
 
 [[def_repository]]repository::
        A collection of <<def_ref,refs>> together with an
index c39edc5..f110162 100644 (file)
@@ -87,6 +87,33 @@ parameter, and is invoked after a commit is made.
 This hook is meant primarily for notification, and cannot affect
 the outcome of `git-commit`.
 
+post-checkout
+-----------
+
+This hook is invoked when a `git-checkout` is run after having updated the
+worktree.  The hook is given three parameters: the ref of the previous HEAD,
+the ref of the new HEAD (which may or may not have changed), and a flag
+indicating whether the checkout was a branch checkout (changing branches,
+flag=1) or a file checkout (retrieving a file from the index, flag=0).
+This hook cannot affect the outcome of `git-checkout`.
+
+This hook can be used to perform repository validity checks, auto-display
+differences from the previous HEAD if different, or set working dir metadata
+properties.
+
+post-merge
+-----------
+
+This hook is invoked by `git-merge`, which happens when a `git pull`
+is done on a local repository.  The hook takes a single parameter, a status
+flag specifying whether or not the merge being done was a squash merge.
+This hook cannot affect the outcome of `git-merge`.
+
+This hook can be used in conjunction with a corresponding pre-commit hook to
+save and restore any form of metadata associated with the working tree
+(eg: permissions/ownership, ACLS, etc).  See contrib/hooks/setgitperms.perl
+for an example of how to do this.
+
 [[pre-receive]]
 pre-receive
 -----------
diff --git a/Documentation/howto/maintain-git.txt b/Documentation/howto/maintain-git.txt
new file mode 100644 (file)
index 0000000..4357e26
--- /dev/null
@@ -0,0 +1,277 @@
+From: Junio C Hamano <gitster@pobox.com>
+Date: Wed, 21 Nov 2007 16:32:55 -0800
+Subject: Addendum to "MaintNotes"
+Abstract: Imagine that git development is racing along as usual, when our friendly
+ neighborhood maintainer is struck down by a wayward bus. Out of the
+ hordes of suckers (loyal developers), you have been tricked (chosen) to
+ step up as the new maintainer. This howto will show you "how to" do it.
+
+The maintainer's git time is spent on three activities.
+
+ - Communication (60%)
+
+   Mailing list discussions on general design, fielding user
+   questions, diagnosing bug reports; reviewing, commenting on,
+   suggesting alternatives to, and rejecting patches.
+
+ - Integration (30%)
+
+   Applying new patches from the contributors while spotting and
+   correcting minor mistakes, shuffling the integration and
+   testing branches, pushing the results out, cutting the
+   releases, and making announcements.
+
+ - Own development (10%)
+
+   Scratching my own itch and sending proposed patch series out.
+
+The policy on Integration is informally mentioned in "A Note
+from the maintainer" message, which is periodically posted to
+this mailing list after each feature release is made.
+
+The policy.
+
+ - Feature releases are numbered as vX.Y.Z and are meant to
+   contain bugfixes and enhancements in any area, including
+   functionality, performance and usability, without regression.
+
+ - Maintenance releases are numbered as vX.Y.Z.W and are meant
+   to contain only bugfixes for the corresponding vX.Y.Z feature
+   release and earlier maintenance releases vX.Y.Z.V (V < W).
+
+ - 'master' branch is used to prepare for the next feature
+   release. In other words, at some point, the tip of 'master'
+   branch is tagged with vX.Y.Z.
+
+ - 'maint' branch is used to prepare for the next maintenance
+   release.  After the feature release vX.Y.Z is made, the tip
+   of 'maint' branch is set to that release, and bugfixes will
+   accumulate on the branch, and at some point, the tip of the
+   branch is tagged with vX.Y.Z.1, vX.Y.Z.2, and so on.
+
+ - 'next' branch is used to publish changes (both enhancements
+   and fixes) that (1) have worthwhile goal, (2) are in a fairly
+   good shape suitable for everyday use, (3) but have not yet
+   demonstrated to be regression free.  New changes are tested
+   in 'next' before merged to 'master'.
+
+ - 'pu' branch is used to publish other proposed changes that do
+   not yet pass the criteria set for 'next'.
+
+ - The tips of 'master', 'maint' and 'next' branches will always
+   fast forward, to allow people to build their own
+   customization on top of them.
+
+ - Usually 'master' contains all of 'maint', 'next' contains all
+   of 'master' and 'pu' contains all of 'next'.
+
+ - The tip of 'master' is meant to be more stable than any
+   tagged releases, and the users are encouraged to follow it.
+
+ - The 'next' branch is where new action takes place, and the
+   users are encouraged to test it so that regressions and bugs
+   are found before new topics are merged to 'master'.
+
+
+A typical git day for the maintainer implements the above policy
+by doing the following:
+
+ - Scan mailing list and #git channel log.  Respond with review
+   comments, suggestions etc.  Kibitz.  Collect potentially
+   usable patches from the mailing list.  Patches about a single
+   topic go to one mailbox (I read my mail in Gnus, and type
+   \C-o to save/append messages in files in mbox format).
+
+ - Review the patches in the saved mailboxes.  Edit proposed log
+   message for typofixes and clarifications, and add Acks
+   collected from the list.  Edit patch to incorporate "Oops,
+   that should have been like this" fixes from the discussion.
+
+ - Classify the collected patches and handle 'master' and
+   'maint' updates:
+
+   - Obviously correct fixes that pertain to the tip of 'maint'
+     are directly applied to 'maint'.
+
+   - Obviously correct fixes that pertain to the tip of 'master'
+     are directly applied to 'master'.
+
+   This step is done with "git am".
+
+     $ git checkout master    ;# or "git checkout maint"
+     $ git am -3 -s mailbox
+     $ make test
+
+ - Merge downwards (maint->master):
+
+     $ git checkout master
+     $ git merge maint
+     $ make test
+
+ - Review the last issue of "What's cooking" message, review the
+   topics scheduled for merging upwards (topic->master and
+   topic->maint), and merge.
+
+     $ git checkout master    ;# or "git checkout maint"
+     $ git merge ai/topic     ;# or "git merge ai/maint-topic"
+     $ git log -p ORIG_HEAD.. ;# final review
+     $ git diff ORIG_HEAD..   ;# final review
+     $ make test              ;# final review
+     $ git branch -d ai/topic ;# or "git branch -d ai/maint-topic"
+
+ - Merge downwards (maint->master) if needed:
+
+     $ git checkout master
+     $ git merge maint
+     $ make test
+
+ - Merge downwards (master->next) if needed:
+
+     $ git checkout next
+     $ git merge master
+     $ make test
+
+ - Handle the remaining patches:
+
+   - Anything unobvious that is applicable to 'master' (in other
+     words, does not depend on anything that is still in 'next'
+     and not in 'master') is applied to a new topic branch that
+     is forked from the tip of 'master'.  This includes both
+     enhancements and unobvious fixes to 'master'.  A topic
+     branch is named as ai/topic where "ai" is typically
+     author's initial and "topic" is a descriptive name of the
+     topic (in other words, "what's the series is about").
+
+   - An unobvious fix meant for 'maint' is applied to a new
+     topic branch that is forked from the tip of 'maint'.  The
+     topic is named as ai/maint-topic.
+
+   - Changes that pertain to an existing topic are applied to
+     the branch, but:
+
+     - obviously correct ones are applied first;
+
+     - questionable ones are discarded or applied to near the tip;
+
+   - Replacement patches to an existing topic are accepted only
+     for commits not in 'next'.
+
+   The above except the "replacement" are all done with:
+
+     $ git am -3 -s mailbox
+
+   while patch replacement is often done by:
+
+     $ git format-patch ai/topic~$n..ai/topic ;# export existing
+
+   then replace some parts with the new patch, and reapplying:
+
+     $ git reset --hard ai/topic~$n
+     $ git am -3 -s 000*.txt
+
+   The full test suite is always run for 'maint' and 'master'
+   after patch application; for topic branches the tests are run
+   as time permits.
+
+ - Update "What's cooking" message to review the updates to
+   existing topics, newly added topics and graduated topics.
+
+   This step is helped with Meta/UWC script (where Meta/ contains
+   a checkout of the 'todo' branch).
+
+ - Merge topics to 'next'.  For each branch whose tip is not
+   merged to 'next', one of three things can happen:
+
+   - The commits are all next-worthy; merge the topic to next:
+
+     $ git checkout next
+     $ git merge ai/topic     ;# or "git merge ai/maint-topic"
+     $ make test
+
+   - The new parts are of mixed quality, but earlier ones are
+     next-worthy; merge the early parts to next:
+
+     $ git checkout next
+     $ git merge ai/topic~2   ;# the tip two are dubious
+     $ make test
+
+   - Nothing is next-worthy; do not do anything.
+
+ - Rebase topics that do not have any commit in next yet.  This
+   step is optional but sometimes is worth doing when an old
+   series that is not in next can take advantage of low-level
+   framework change that is merged to 'master' already.
+
+     $ git rebase master ai/topic
+
+   This step is helped with Meta/git-topic.perl script to
+   identify which topic is rebaseable.  There also is a
+   pre-rebase hook to make sure that topics that are already in
+   'next' are not rebased beyond the merged commit.
+
+ - Rebuild "pu" to merge the tips of topics not in 'next'.
+
+     $ git checkout pu
+     $ git reset --hard next
+     $ git merge ai/topic     ;# repeat for all remaining topics
+     $ make test
+
+   This step is helped with Meta/PU script
+
+ - Push four integration branches to a private repository at
+   k.org and run "make test" on all of them.
+
+ - Push four integration branches to /pub/scm/git/git.git at
+   k.org.  This triggers its post-update hook which:
+
+    (1) runs "git pull" in $HOME/git-doc/ repository to pull
+        'master' just pushed out;
+
+    (2) runs "make doc" in $HOME/git-doc/, install the generated
+        documentation in staging areas, which are separate
+        repositories that have html and man branches checked
+        out.
+
+    (3) runs "git commit" in the staging areas, and run "git
+        push" back to /pub/scm/git/git.git/ to update the html
+        and man branches.
+
+    (4) installs generated documentation to /pub/software/scm/git/docs/
+        to be viewed from http://www.kernel.org/
+
+ - Fetch html and man branches back from k.org, and push four
+   integration branches and the two documentation branches to
+   repo.or.cz
+
+
+Some observations to be made.
+
+ * Each topic is tested individually, and also together with
+   other topics cooking in 'next'.  Until it matures, none part
+   of it is merged to 'master'.
+
+ * A topic already in 'next' can get fixes while still in
+   'next'.  Such a topic will have many merges to 'next' (in
+   other words, "git log --first-parent next" will show many
+   "Merge ai/topic to next" for the same topic.
+
+ * An unobvious fix for 'maint' is cooked in 'next' and then
+   merged to 'master' to make extra sure it is Ok and then
+   merged to 'maint'.
+
+ * Even when 'next' becomes empty (in other words, all topics
+   prove stable and are merged to 'master' and "git diff master
+   next" shows empty), it has tons of merge commits that will
+   never be in 'master'.
+
+ * In principle, "git log --first-parent master..next" should
+   show nothing but merges (in practice, there are fixup commits
+   and reverts that are not merges).
+
+ * Commits near the tip of a topic branch that are not in 'next'
+   are fair game to be discarded, replaced or rewritten.
+   Commits already merged to 'next' will not be.
+
+ * Being in the 'next' branch is not a guarantee for a topic to
+   be included in the next feature release.  Being in the
+   'master' branch typically is.
diff --git a/Documentation/howto/recover-corrupted-blob-object.txt b/Documentation/howto/recover-corrupted-blob-object.txt
new file mode 100644 (file)
index 0000000..323b513
--- /dev/null
@@ -0,0 +1,134 @@
+Date: Fri, 9 Nov 2007 08:28:38 -0800 (PST)
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Subject: corrupt object on git-gc
+Abstract: Some tricks to reconstruct blob objects in order to fix
+ a corrupted repository.
+
+On Fri, 9 Nov 2007, Yossi Leybovich wrote:
+>
+> Did not help still the repository look for this object?
+> Any one know how can I track this object and understand which file is it
+
+So exactly *because* the SHA1 hash is cryptographically secure, the hash
+itself doesn't actually tell you anything, in order to fix a corrupt
+object you basically have to find the "original source" for it.
+
+The easiest way to do that is almost always to have backups, and find the
+same object somewhere else. Backups really are a good idea, and git makes
+it pretty easy (if nothing else, just clone the repository somewhere else,
+and make sure that you do *not* use a hard-linked clone, and preferably
+not the same disk/machine).
+
+But since you don't seem to have backups right now, the good news is that
+especially with a single blob being corrupt, these things *are* somewhat
+debuggable.
+
+First off, move the corrupt object away, and *save* it. The most common
+cause of corruption so far has been memory corruption, but even so, there
+are people who would be interested in seeing the corruption - but it's
+basically impossible to judge the corruption until we can also see the
+original object, so right now the corrupt object is useless, but it's very
+interesting for the future, in the hope that you can re-create a
+non-corrupt version.
+
+So:
+
+> ib]$ mv .git/objects/4b/9458b3786228369c63936db65827de3cc06200 ../
+
+This is the right thing to do, although it's usually best to save it under
+it's full SHA1 name (you just dropped the "4b" from the result ;).
+
+Let's see what that tells us:
+
+> ib]$ git-fsck --full
+> broken link from    tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
+>              to    blob 4b9458b3786228369c63936db65827de3cc06200
+> missing blob 4b9458b3786228369c63936db65827de3cc06200
+
+Ok, I removed the "dangling commit" messages, because they are just
+messages about the fact that you probably have rebased etc, so they're not
+at all interesting. But what remains is still very useful. In particular,
+we now know which tree points to it!
+
+Now you can do
+
+       git ls-tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
+
+which will show something like
+
+       100644 blob 8d14531846b95bfa3564b58ccfb7913a034323b8    .gitignore
+       100644 blob ebf9bf84da0aab5ed944264a5db2a65fe3a3e883    .mailmap
+       100644 blob ca442d313d86dc67e0a2e5d584b465bd382cbf5c    COPYING
+       100644 blob ee909f2cc49e54f0799a4739d24c4cb9151ae453    CREDITS
+       040000 tree 0f5f709c17ad89e72bdbbef6ea221c69807009f6    Documentation
+       100644 blob 1570d248ad9237e4fa6e4d079336b9da62d9ba32    Kbuild
+       100644 blob 1c7c229a092665b11cd46a25dbd40feeb31661d9    MAINTAINERS
+       ...
+
+and you should now have a line that looks like
+
+       10064 blob 4b9458b3786228369c63936db65827de3cc06200     my-magic-file
+
+in the output. This already tells you a *lot* it tells you what file the
+corrupt blob came from!
+
+Now, it doesn't tell you quite enough, though: it doesn't tell what
+*version* of the file didn't get correctly written! You might be really
+lucky, and it may be the version that you already have checked out in your
+working tree, in which case fixing this problem is really simple, just do
+
+       git hash-object -w my-magic-file
+
+again, and if it outputs the missing SHA1 (4b945..) you're now all done!
+
+But that's the really lucky case, so let's assume that it was some older
+version that was broken. How do you tell which version it was?
+
+The easiest way to do it is to do
+
+       git log --raw --all --full-history -- subdirectory/my-magic-file
+
+and that will show you the whole log for that file (please realize that
+the tree you had may not be the top-level tree, so you need to figure out
+which subdirectory it was in on your own), and because you're asking for
+raw output, you'll now get something like
+
+       commit abc
+       Author:
+       Date:
+         ..
+       :100644 100644 4b9458b... newsha... M  somedirectory/my-magic-file
+
+
+       commit xyz
+       Author:
+       Date:
+
+         ..
+       :100644 100644 oldsha... 4b9458b... M   somedirectory/my-magic-file
+
+and this actually tells you what the *previous* and *subsequent* versions
+of that file were! So now you can look at those ("oldsha" and "newsha"
+respectively), and hopefully you have done commits often, and can
+re-create the missing my-magic-file version by looking at those older and
+newer versions!
+
+If you can do that, you can now recreate the missing object with
+
+       git hash-object -w <recreated-file>
+
+and your repository is good again!
+
+(Btw, you could have ignored the fsck, and started with doing a
+
+       git log --raw --all
+
+and just looked for the sha of the missing object (4b9458b..) in that
+whole thing. It's up to you - git does *have* a lot of information, it is
+just missing one particular blob version.
+
+Trying to recreate trees and especially commits is *much* harder. So you
+were lucky that it's a blob. It's quite possible that you can recreate the
+thing.
+
+                       Linus
index d64c259..9f1fc82 100644 (file)
        not autocommit, to give the user a chance to inspect and
        further tweak the merge result before committing.
 
+--commit::
+       Perform the merge and commit the result. This option can
+       be used to override --no-commit.
+
 --squash::
        Produce the working tree and index state as if a real
        merge happened, but do not actually make a commit or
        top of the current branch whose effect is the same as
        merging another branch (or more in case of an octopus).
 
+--no-squash::
+       Perform the merge and commit the result. This option can
+       be used to override --squash.
+
+--no-ff::
+       Generate a merge commit even if the merge resolved as a
+       fast-forward.
+
+--ff::
+       Do not generate a merge commit if the merge resolved as
+       a fast-forward, only update the branch pointer. This is
+       the default behavior of git-merge.
+
 -s <strategy>, \--strategy=<strategy>::
        Use the given merge strategy; can be supplied more than
        once to specify them in the order they should be tried.
index e67f914..4f66738 100644 (file)
@@ -36,5 +36,11 @@ To sync with a local directory, you can use:
 - file:///path/to/repo.git/
 ===============================================================
 
+ifndef::git-clone[]
 They are mostly equivalent, except when cloning.  See
 gitlink:git-clone[1] for details.
+endif::git-clone[]
+
+ifdef::git-clone[]
+They are equivalent, except the former implies --local option.
+endif::git-clone[]
index 159de30..93a47b4 100644 (file)
@@ -481,7 +481,7 @@ Bisecting: 3537 revisions left to test after this
 If you run "git branch" at this point, you'll see that git has
 temporarily moved you to a new branch named "bisect".  This branch
 points to a commit (with commit id 65934...) that is reachable from
-v2.6.19 but not from v2.6.18.  Compile and test it, and see whether
+"master" but not from v2.6.18.  Compile and test it, and see whether
 it crashes.  Assume it does crash.  Then:
 
 -------------------------------------------------
@@ -939,7 +939,7 @@ file such that it contained the given content either before or after the
 commit.  You can find out with this:
 
 -------------------------------------------------
-$  git log --raw --abbrev=40 --pretty=oneline -- filename |
+$  git log --raw --abbrev=40 --pretty=oneline |
        grep -B 1 `git hash-object filename`
 -------------------------------------------------
 
@@ -1380,7 +1380,7 @@ If you make a commit that you later wish you hadn't, there are two
 fundamentally different ways to fix the problem:
 
        1. You can create a new commit that undoes whatever was done
-       by the previous commit.  This is the correct thing if your
+       by the old commit.  This is the correct thing if your
        mistake has already been made public.
 
        2. You can go back and modify the old commit.  You should
@@ -1508,7 +1508,7 @@ Ensuring good performance
 -------------------------
 
 On large repositories, git depends on compression to keep the history
-information from taking up to much space on disk or in memory.
+information from taking up too much space on disk or in memory.
 
 This compression is not performed automatically.  Therefore you
 should occasionally run gitlink:git-gc[1]:
@@ -1549,7 +1549,7 @@ dangling tree b24c2473f1fd3d91352a624795be026d64c8841f
 Dangling objects are not a problem.  At worst they may take up a little
 extra disk space.  They can sometimes provide a last-resort method for
 recovering lost work--see <<dangling-objects>> for details.  However, if
-you wish, you can remove them with gitlink:git-prune[1] or the --prune
+you wish, you can remove them with gitlink:git-prune[1] or the `--prune`
 option to gitlink:git-gc[1]:
 
 -------------------------------------------------
@@ -1573,7 +1573,7 @@ Recovering lost changes
 Reflogs
 ^^^^^^^
 
-Say you modify a branch with gitlink:git-reset[1] --hard, and then
+Say you modify a branch with `gitlink:git-reset[1] --hard`, and then
 realize that the branch was the only reference you had to that point in
 history.
 
@@ -1585,9 +1585,9 @@ old history using, for example,
 $ git log master@{1}
 -------------------------------------------------
 
-This lists the commits reachable from the previous version of the head.
-This syntax can be used to with any git command that accepts a commit,
-not just with git log.  Some other examples:
+This lists the commits reachable from the previous version of the
+"master" branch head.  This syntax can be used with any git command
+that accepts a commit, not just with git log.  Some other examples:
 
 -------------------------------------------------
 $ git show master@{2}          # See where the branch pointed 2,
@@ -1702,7 +1702,7 @@ $ git pull
 More generally, a branch that is created from a remote branch will pull
 by default from that branch.  See the descriptions of the
 branch.<name>.remote and branch.<name>.merge options in
-gitlink:git-config[1], and the discussion of the --track option in
+gitlink:git-config[1], and the discussion of the `--track` option in
 gitlink:git-checkout[1], to learn how to control these defaults.
 
 In addition to saving you keystrokes, "git pull" also helps you by
@@ -1800,7 +1800,7 @@ $ git clone /path/to/repository
 $ git pull /path/to/other/repository
 -------------------------------------------------
 
-or an ssh url:
+or an ssh URL:
 
 -------------------------------------------------
 $ git clone ssh://yourhost/~you/repository
@@ -1861,7 +1861,7 @@ Exporting a git repository via the git protocol
 This is the preferred method.
 
 If someone else administers the server, they should tell you what
-directory to put the repository in, and what git:// url it will appear
+directory to put the repository in, and what git:// URL it will appear
 at.  You can then skip to the section
 "<<pushing-changes-to-a-public-repository,Pushing changes to a public
 repository>>", below.
@@ -1898,8 +1898,8 @@ $ chmod a+x hooks/post-update
 gitlink:git-update-server-info[1], and the documentation
 link:hooks.html[Hooks used by git].)
 
-Advertise the url of proj.git.  Anybody else should then be able to
-clone or pull from that url, for example with a command line like:
+Advertise the URL of proj.git.  Anybody else should then be able to
+clone or pull from that URL, for example with a command line like:
 
 -------------------------------------------------
 $ git clone http://yourserver.com/~you/proj.git
@@ -2098,7 +2098,7 @@ $ git branch --track test origin/master
 $ git branch --track release origin/master
 -------------------------------------------------
 
-These can be easily kept up to date using gitlink:git-pull[1]
+These can be easily kept up to date using gitlink:git-pull[1].
 
 -------------------------------------------------
 $ git checkout test && git pull
@@ -2190,7 +2190,7 @@ changes are in a specific branch, use:
 $ git log linux..branchname | git-shortlog
 -------------------------------------------------
 
-To see whether it has already been merged into the test or release branches
+To see whether it has already been merged into the test or release branches,
 use:
 
 -------------------------------------------------
@@ -2203,12 +2203,12 @@ or
 $ git log release..branchname
 -------------------------------------------------
 
-(If this branch has not yet been merged you will see some log entries.
+(If this branch has not yet been merged, you will see some log entries.
 If it has been merged, then there will be no output.)
 
 Once a patch completes the great cycle (moving from test to release,
 then pulled by Linus, and finally coming back into your local
-"origin/master" branch) the branch for this change is no longer needed.
+"origin/master" branch), the branch for this change is no longer needed.
 You detect this when the output from:
 
 -------------------------------------------------
@@ -2470,7 +2470,7 @@ $ git rebase --continue
 
 and git will continue applying the rest of the patches.
 
-At any point you may use the --abort option to abort this process and
+At any point you may use the `--abort` option to abort this process and
 return mywork to the state it had before you started the rebase:
 
 -------------------------------------------------
@@ -2539,9 +2539,9 @@ $ git checkout -b mywork-new origin
 $ gitk origin..mywork &
 -------------------------------------------------
 
-And browse through the list of patches in the mywork branch using gitk,
+and browse through the list of patches in the mywork branch using gitk,
 applying them (possibly in a different order) to mywork-new using
-cherry-pick, and possibly modifying them as you go using commit --amend.
+cherry-pick, and possibly modifying them as you go using `commit --amend`.
 The gitlink:git-gui[1] command may also help as it allows you to
 individually select diff hunks for inclusion in the index (by
 right-clicking on the diff hunk and choosing "Stage Hunk for Commit").
@@ -2865,7 +2865,7 @@ others:
 
 - Git can quickly determine whether two objects are identical or not,
   just by comparing names.
-- Since object names are computed the same way in ever repository, the
+- Since object names are computed the same way in every repository, the
   same content stored in two repositories will always be stored under
   the same name.
 - Git can detect errors when it reads an object, by checking that the
@@ -2882,7 +2882,7 @@ There are four different types of objects: "blob", "tree", "commit", and
   "blob" objects into a directory structure. In addition, a tree object
   can refer to other tree objects, thus creating a directory hierarchy.
 - A <<def_commit_object,"commit" object>> ties such directory hierarchies
-  together into a <<def_DAG,directed acyclic graph>> of revisions - each
+  together into a <<def_DAG,directed acyclic graph>> of revisions--each
   commit contains the object name of exactly one tree designating the
   directory hierarchy at the time of the commit. In addition, a commit
   refers to "parent" commit objects that describe the history of how we
@@ -3155,7 +3155,7 @@ There are also other situations that cause dangling objects. For
 example, a "dangling blob" may arise because you did a "git add" of a
 file, but then, before you actually committed it and made it part of the
 bigger picture, you changed something else in that file and committed
-that *updated* thing - the old state that you added originally ends up
+that *updated* thing--the old state that you added originally ends up
 not being pointed to by any commit or tree, so it's now a dangling blob
 object.
 
@@ -3170,7 +3170,7 @@ up pointing to them, so they end up "dangling" in your repository.
 Generally, dangling objects aren't anything to worry about. They can
 even be very useful: if you screw something up, the dangling objects can
 be how you recover your old tree (say, you did a rebase, and realized
-that you really didn't want to - you can look at what dangling objects
+that you really didn't want to--you can look at what dangling objects
 you have, and decide to reset your head to some old dangling state).
 
 For commits, you can just use:
@@ -3214,10 +3214,10 @@ $ git prune
 ------------------------------------------------
 
 and they'll be gone. But you should only run "git prune" on a quiescent
-repository - it's kind of like doing a filesystem fsck recovery: you
+repository--it's kind of like doing a filesystem fsck recovery: you
 don't want to do that while the filesystem is mounted.
 
-(The same is true of "git-fsck" itself, btw - but since
+(The same is true of "git-fsck" itself, btw, but since
 git-fsck never actually *changes* the repository, it just reports
 on what it found, git-fsck itself is never "dangerous" to run.
 Running it while somebody is actually changing the repository can cause
@@ -3336,14 +3336,14 @@ $ git hash-object -w <recreated-file>
 
 and your repository is good again!
 
-(Btw, you could have ignored the fsck, and started with doing a 
+(Btw, you could have ignored the fsck, and started with doing a
 
 ------------------------------------------------
 $ git log --raw --all
 ------------------------------------------------
 
-and just looked for the sha of the missing object (4b9458b..) in that 
-whole thing. It's up to you - git does *have* a lot of information, it is 
+and just looked for the sha of the missing object (4b9458b..) in that
+whole thing. It's up to you - git does *have* a lot of information, it is
 just missing one particular blob version.
 
 [[the-index]]
@@ -3672,9 +3672,10 @@ The Workflow
 ------------
 
 High-level operations such as gitlink:git-commit[1],
-gitlink:git-checkout[1] and git-reset[1] work by moving data between the
-working tree, the index, and the object database.  Git provides
-low-level operations which perform each of these steps individually.
+gitlink:git-checkout[1] and gitlink:git-reset[1] work by moving data
+between the working tree, the index, and the object database.  Git
+provides low-level operations which perform each of these steps
+individually.
 
 Generally, all "git" operations work on the index file. Some operations
 work *purely* on the index file (showing the current state of the
@@ -3729,7 +3730,7 @@ You write your current index file to a "tree" object with the program
 $ git write-tree
 -------------------------------------------------
 
-that doesn't come with any options - it will just write out the
+that doesn't come with any options--it will just write out the
 current index into the set of tree objects that describe that state,
 and it will return the name of the resulting top-level tree. You can
 use that tree to re-generate the index at any time by going in the
@@ -3740,7 +3741,7 @@ object database -> index
 ~~~~~~~~~~~~~~~~~~~~~~~~
 
 You read a "tree" file from the object database, and use that to
-populate (and overwrite - don't do this if your index contains any
+populate (and overwrite--don't do this if your index contains any
 unsaved state that you might want to restore later!) your current
 index.  Normal operation is just
 
@@ -3788,7 +3789,7 @@ Tying it all together
 
 To commit a tree you have instantiated with "git-write-tree", you'd
 create a "commit" object that refers to that tree and the history
-behind it - most notably the "parent" commits that preceded it in
+behind it--most notably the "parent" commits that preceded it in
 history.
 
 Normally a "commit" has one parent: the previous state of the tree
@@ -3931,7 +3932,7 @@ Once you know the three trees you are going to merge (the one "original"
 tree, aka the common tree, and the two "result" trees, aka the branches
 you want to merge), you do a "merge" read into the index. This will
 complain if it has to throw away your old index contents, so you should
-make sure that you've committed those - in fact you would normally
+make sure that you've committed those--in fact you would normally
 always do a merge against your last commit (which should thus match what
 you have in your current index anyway).
 
@@ -3951,7 +3952,7 @@ Merging multiple trees, continued
 ---------------------------------
 
 Sadly, many merges aren't trivial. If there are files that have
-been added.moved or removed, or if both branches have modified the
+been addedmoved or removed, or if both branches have modified the
 same file, you will be left with an index tree that contains "merge
 entries" in it. Such an index tree can 'NOT' be written out to a tree
 object, and you will have to resolve any such merge clashes using
@@ -4203,7 +4204,7 @@ Two things are interesting here:
 
 - `get_sha1()` returns 0 on _success_.  This might surprise some new
   Git hackers, but there is a long tradition in UNIX to return different
-  negative numbers in case of different errors -- and 0 on success.
+  negative numbers in case of different errors--and 0 on success.
 
 - the variable `sha1` in the function signature of `get_sha1()` is `unsigned
   char \*`, but is actually expected to be a pointer to `unsigned
@@ -4308,7 +4309,7 @@ $ git branch new     # create branch "new" starting at current HEAD
 $ git branch -d new  # delete branch "new"
 -----------------------------------------------
 
-Instead of basing new branch on current HEAD (the default), use:
+Instead of basing new branch on current HEAD (the default), use:
 
 -----------------------------------------------
 $ git branch new test    # branch named "test"
index 85314eb..3c0032c 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v1.5.3.7.GIT
+DEF_VER=v1.5.3.GIT
 
 LF='
 '
index c72d40a..e869b85 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -28,6 +28,8 @@ all::
 #
 # Define NO_STRCASESTR if you don't have strcasestr.
 #
+# Define NO_MEMMEM if you don't have memmem.
+#
 # Define NO_STRLCPY if you don't have strlcpy.
 #
 # Define NO_STRTOUMAX if you don't have strtoumax in the C library.
@@ -36,6 +38,8 @@ all::
 #
 # Define NO_SETENV if you don't have setenv in the C library.
 #
+# Define NO_MKDTEMP if you don't have mkdtemp in the C library.
+#
 # Define NO_SYMLINK_HEAD if you never want .git/HEAD to be a symbolic link.
 # Enable it on Windows.  By default, symrefs are still used.
 #
@@ -126,6 +130,9 @@ all::
 # If not set it defaults to the bare 'wish'. If it is set to the empty
 # string then NO_TCLTK will be forced (this is used by configure script).
 #
+# Define THREADED_DELTA_SEARCH if you have pthreads and wish to exploit
+# parallel delta searching when packing objects.
+#
 
 GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
        @$(SHELL_PATH) ./GIT-VERSION-GEN
@@ -164,6 +171,7 @@ GITWEB_CONFIG = gitweb_config.perl
 GITWEB_HOME_LINK_STR = projects
 GITWEB_SITENAME =
 GITWEB_PROJECTROOT = /pub/git
+GITWEB_PROJECT_MAXDEPTH = 2007
 GITWEB_EXPORT_OK =
 GITWEB_STRICT_EXPORT =
 GITWEB_BASE_URL =
@@ -205,16 +213,14 @@ BASIC_LDFLAGS =
 
 SCRIPT_SH = \
        git-bisect.sh git-checkout.sh \
-       git-clean.sh git-clone.sh git-commit.sh \
-       git-fetch.sh \
-       git-ls-remote.sh \
+       git-clone.sh git-commit.sh \
        git-merge-one-file.sh git-mergetool.sh git-parse-remote.sh \
        git-pull.sh git-rebase.sh git-rebase--interactive.sh \
-       git-repack.sh git-request-pull.sh git-reset.sh \
+       git-repack.sh git-request-pull.sh \
        git-sh-setup.sh \
        git-am.sh \
        git-merge.sh git-merge-stupid.sh git-merge-octopus.sh \
-       git-merge-resolve.sh git-merge-ours.sh \
+       git-merge-resolve.sh \
        git-lost-found.sh git-quiltimport.sh git-submodule.sh \
        git-filter-branch.sh \
        git-stash.sh
@@ -222,8 +228,7 @@ SCRIPT_SH = \
 SCRIPT_PERL = \
        git-add--interactive.perl \
        git-archimport.perl git-cvsimport.perl git-relink.perl \
-       git-cvsserver.perl git-remote.perl \
-       git-svnimport.perl git-cvsexportcommit.perl \
+       git-cvsserver.perl git-remote.perl git-cvsexportcommit.perl \
        git-send-email.perl git-svn.perl
 
 SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
@@ -232,15 +237,15 @@ SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
 
 # ... and all the rest that could be moved out of bindir to gitexecdir
 PROGRAMS = \
-       git-convert-objects$X git-fetch-pack$X \
-       git-hash-object$X git-index-pack$X git-local-fetch$X \
+       git-fetch-pack$X \
+       git-hash-object$X git-index-pack$X \
        git-fast-import$X \
        git-daemon$X \
        git-merge-index$X git-mktag$X git-mktree$X git-patch-id$X \
-       git-peek-remote$X git-receive-pack$X \
+       git-receive-pack$X \
        git-send-pack$X git-shell$X \
-       git-show-index$X git-ssh-fetch$X \
-       git-ssh-upload$X git-unpack-file$X \
+       git-show-index$X \
+       git-unpack-file$X \
        git-update-server-info$X \
        git-upload-pack$X \
        git-pack-redundant$X git-var$X \
@@ -268,9 +273,6 @@ ifndef NO_TCLTK
 OTHER_PROGRAMS += gitk-wish
 endif
 
-# Backward compatibility -- to be removed after 1.0
-PROGRAMS += git-ssh-pull$X git-ssh-push$X
-
 # Set paths to tools early so that they can be used for version tests.
 ifndef SHELL_PATH
        SHELL_PATH = /bin/sh
@@ -290,7 +292,7 @@ LIB_H = \
        run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \
        tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h \
        utf8.h reflog-walk.h patch-ids.h attr.h decorate.h progress.h \
-       mailmap.h remote.h
+       mailmap.h remote.h parse-options.h transport.h diffcore.h hash.h
 
 DIFF_OBJS = \
        diff.o diff-lib.o diffcore-break.o diffcore-order.o \
@@ -300,7 +302,7 @@ DIFF_OBJS = \
 LIB_OBJS = \
        blob.o commit.o connect.o csum-file.o cache-tree.o base85.o \
        date.o diff-delta.o entry.o exec_cmd.o ident.o \
-       interpolate.o \
+       pretty.o interpolate.o hash.o \
        lockfile.o \
        patch-ids.o \
        object.o pack-check.o pack-write.o patch-delta.o path.o pkt-line.o \
@@ -312,7 +314,8 @@ LIB_OBJS = \
        write_or_die.o trace.o list-objects.o grep.o match-trees.o \
        alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \
        color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \
-       convert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o
+       convert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o \
+       transport.o bundle.o walker.o parse-options.o
 
 BUILTIN_OBJS = \
        builtin-add.o \
@@ -326,6 +329,7 @@ BUILTIN_OBJS = \
        builtin-check-attr.o \
        builtin-checkout-index.o \
        builtin-check-ref-format.o \
+       builtin-clean.o \
        builtin-commit-tree.o \
        builtin-count-objects.o \
        builtin-describe.o \
@@ -333,6 +337,8 @@ BUILTIN_OBJS = \
        builtin-diff-files.o \
        builtin-diff-index.o \
        builtin-diff-tree.o \
+       builtin-fetch.o \
+       builtin-fetch-pack.o \
        builtin-fetch--tool.o \
        builtin-fmt-merge-msg.o \
        builtin-for-each-ref.o \
@@ -343,10 +349,12 @@ BUILTIN_OBJS = \
        builtin-log.o \
        builtin-ls-files.o \
        builtin-ls-tree.o \
+       builtin-ls-remote.o \
        builtin-mailinfo.o \
        builtin-mailsplit.o \
        builtin-merge-base.o \
        builtin-merge-file.o \
+       builtin-merge-ours.o \
        builtin-mv.o \
        builtin-name-rev.o \
        builtin-pack-objects.o \
@@ -355,8 +363,10 @@ BUILTIN_OBJS = \
        builtin-push.o \
        builtin-read-tree.o \
        builtin-reflog.o \
+       builtin-send-pack.o \
        builtin-config.o \
        builtin-rerere.o \
+       builtin-reset.o \
        builtin-rev-list.o \
        builtin-rev-parse.o \
        builtin-revert.o \
@@ -400,13 +410,16 @@ ifeq ($(uname_S),Darwin)
        NEEDS_LIBICONV = YesPlease
        OLD_ICONV = UnfortunatelyYes
        NO_STRLCPY = YesPlease
+       NO_MEMMEM = YesPlease
 endif
 ifeq ($(uname_S),SunOS)
        NEEDS_SOCKET = YesPlease
        NEEDS_NSL = YesPlease
        SHELL_PATH = /bin/bash
        NO_STRCASESTR = YesPlease
+       NO_MEMMEM = YesPlease
        NO_HSTRERROR = YesPlease
+       NO_MKDTEMP = YesPlease
        ifeq ($(uname_R),5.8)
                NEEDS_LIBICONV = YesPlease
                NO_UNSETENV = YesPlease
@@ -428,6 +441,7 @@ ifeq ($(uname_O),Cygwin)
        NO_D_TYPE_IN_DIRENT = YesPlease
        NO_D_INO_IN_DIRENT = YesPlease
        NO_STRCASESTR = YesPlease
+       NO_MEMMEM = YesPlease
        NO_SYMLINK_HEAD = YesPlease
        NEEDS_LIBICONV = YesPlease
        NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes
@@ -441,11 +455,13 @@ ifeq ($(uname_O),Cygwin)
 endif
 ifeq ($(uname_S),FreeBSD)
        NEEDS_LIBICONV = YesPlease
+       NO_MEMMEM = YesPlease
        BASIC_CFLAGS += -I/usr/local/include
        BASIC_LDFLAGS += -L/usr/local/lib
 endif
 ifeq ($(uname_S),OpenBSD)
        NO_STRCASESTR = YesPlease
+       NO_MEMMEM = YesPlease
        NEEDS_LIBICONV = YesPlease
        BASIC_CFLAGS += -I/usr/local/include
        BASIC_LDFLAGS += -L/usr/local/lib
@@ -460,6 +476,7 @@ ifeq ($(uname_S),NetBSD)
 endif
 ifeq ($(uname_S),AIX)
        NO_STRCASESTR=YesPlease
+       NO_MEMMEM = YesPlease
        NO_STRLCPY = YesPlease
        NEEDS_LIBICONV=YesPlease
 endif
@@ -471,6 +488,7 @@ ifeq ($(uname_S),IRIX64)
        NO_IPV6=YesPlease
        NO_SETENV=YesPlease
        NO_STRCASESTR=YesPlease
+       NO_MEMMEM = YesPlease
        NO_STRLCPY = YesPlease
        NO_SOCKADDR_STORAGE=YesPlease
        SHELL_PATH=/usr/gnu/bin/bash
@@ -508,7 +526,9 @@ else
        CC_LD_DYNPATH = -R
 endif
 
-ifndef NO_CURL
+ifdef NO_CURL
+       BASIC_CFLAGS += -DNO_CURL
+else
        ifdef CURLDIR
                # Try "-Wl,-rpath=$(CURLDIR)/$(lib)" in such a case.
                BASIC_CFLAGS += -I$(CURLDIR)/include
@@ -516,7 +536,9 @@ ifndef NO_CURL
        else
                CURL_LIBCURL = -lcurl
        endif
-       PROGRAMS += git-http-fetch$X
+       BUILTIN_OBJS += builtin-http-fetch.o
+       EXTLIBS += $(CURL_LIBCURL)
+       LIB_OBJS += http.o http-walker.o
        curl_check := $(shell (echo 070908; curl-config --vernum) | sort -r | sed -ne 2p)
        ifeq "$(curl_check)" "070908"
                ifndef NO_EXPAT
@@ -598,6 +620,10 @@ ifdef NO_SETENV
        COMPAT_CFLAGS += -DNO_SETENV
        COMPAT_OBJS += compat/setenv.o
 endif
+ifdef NO_MKDTEMP
+       COMPAT_CFLAGS += -DNO_MKDTEMP
+       COMPAT_OBJS += compat/mkdtemp.o
+endif
 ifdef NO_UNSETENV
        COMPAT_CFLAGS += -DNO_UNSETENV
        COMPAT_OBJS += compat/unsetenv.o
@@ -669,6 +695,15 @@ ifdef NO_HSTRERROR
        COMPAT_CFLAGS += -DNO_HSTRERROR
        COMPAT_OBJS += compat/hstrerror.o
 endif
+ifdef NO_MEMMEM
+       COMPAT_CFLAGS += -DNO_MEMMEM
+       COMPAT_OBJS += compat/memmem.o
+endif
+
+ifdef THREADED_DELTA_SEARCH
+       BASIC_CFLAGS += -DTHREADED_DELTA_SEARCH
+       EXTLIBS += -lpthread
+endif
 
 ifeq ($(TCLTK_PATH),)
 NO_TCLTK=NoThanks
@@ -721,7 +756,7 @@ TCLTK_PATH_SQ = $(subst ','\'',$(TCLTK_PATH))
 LIBS = $(GITLIBS) $(EXTLIBS)
 
 BASIC_CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER_SQ)' \
-       -DETC_GITCONFIG='"$(ETC_GITCONFIG_SQ)"' $(COMPAT_CFLAGS)
+       $(COMPAT_CFLAGS)
 LIB_OBJS += $(COMPAT_OBJS)
 
 ALL_CFLAGS += $(BASIC_CFLAGS)
@@ -817,6 +852,7 @@ gitweb/gitweb.cgi: gitweb/gitweb.perl
            -e 's|++GITWEB_HOME_LINK_STR++|$(GITWEB_HOME_LINK_STR)|g' \
            -e 's|++GITWEB_SITENAME++|$(GITWEB_SITENAME)|g' \
            -e 's|++GITWEB_PROJECTROOT++|$(GITWEB_PROJECTROOT)|g' \
+           -e 's|"++GITWEB_PROJECT_MAXDEPTH++"|$(GITWEB_PROJECT_MAXDEPTH)|g' \
            -e 's|++GITWEB_EXPORT_OK++|$(GITWEB_EXPORT_OK)|g' \
            -e 's|++GITWEB_STRICT_EXPORT++|$(GITWEB_STRICT_EXPORT)|g' \
            -e 's|++GITWEB_BASE_URL++|$(GITWEB_BASE_URL)|g' \
@@ -869,39 +905,30 @@ exec_cmd.o: exec_cmd.c GIT-CFLAGS
 builtin-init-db.o: builtin-init-db.c GIT-CFLAGS
        $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $<
 
+config.o: config.c GIT-CFLAGS
+       $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DETC_GITCONFIG='"$(ETC_GITCONFIG_SQ)"' $<
+
 http.o: http.c GIT-CFLAGS
        $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DGIT_USER_AGENT='"git/$(GIT_VERSION)"' $<
 
 ifdef NO_EXPAT
-http-fetch.o: http-fetch.c http.h GIT-CFLAGS
+http-walker.o: http-walker.c http.h GIT-CFLAGS
        $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DNO_EXPAT $<
 endif
 
 git-%$X: %.o $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
 
-ssh-pull.o: ssh-fetch.c
-ssh-push.o: ssh-upload.c
-git-local-fetch$X: fetch.o
-git-ssh-fetch$X: rsh.o fetch.o
-git-ssh-upload$X: rsh.o
-git-ssh-pull$X: rsh.o fetch.o
-git-ssh-push$X: rsh.o
-
 git-imap-send$X: imap-send.o $(LIB_FILE)
 
-http.o http-fetch.o http-push.o: http.h
-git-http-fetch$X: fetch.o http.o http-fetch.o $(GITLIBS)
-       $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
-               $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
+http.o http-walker.o http-push.o: http.h
 
 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)
 
-$(LIB_OBJS) $(BUILTIN_OBJS) fetch.o: $(LIB_H)
+$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
 $(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
-$(DIFF_OBJS): diffcore.h
 builtin-revert.o builtin-runstatus.o wt-status.o: wt-status.h
 
 $(LIB_FILE): $(LIB_OBJS)
@@ -930,6 +957,10 @@ tags:
        $(RM) tags
        $(FIND) . -name '*.[hcS]' -print | xargs ctags -a
 
+cscope:
+       $(RM) cscope*
+       $(FIND) . -name '*.[hcS]' -print | xargs cscope -b
+
 ### Detect prefix changes
 TRACK_CFLAGS = $(subst ','\'',$(ALL_CFLAGS)):\
              $(bindir_SQ):$(gitexecdir_SQ):$(template_dir_SQ):$(prefix_SQ)
@@ -957,7 +988,7 @@ endif
 
 ### Testing rules
 
-TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-absolute-path$X
+TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-absolute-path$X test-parse-options$X
 
 all:: $(TEST_PROGRAMS)
 
@@ -974,6 +1005,8 @@ test-date$X: date.o ctype.o
 
 test-delta$X: diff-delta.o patch-delta.o
 
+test-parse-options$X: parse-options.o
+
 .PRECIOUS: $(patsubst test-%$X,test-%.o,$(TEST_PROGRAMS))
 
 test-%$X: test-%.o $(GITLIBS)
@@ -1079,7 +1112,7 @@ clean:
                $(LIB_FILE) $(XDIFF_LIB)
        $(RM) $(ALL_PROGRAMS) $(BUILT_INS) git$X
        $(RM) $(TEST_PROGRAMS)
-       $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo common-cmds.h TAGS tags
+       $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo common-cmds.h TAGS tags cscope*
        $(RM) -r autom4te.cache
        $(RM) config.log config.mak.autogen config.mak.append config.status config.cache
        $(RM) -r $(GIT_TARNAME) .doc-tmp-dir
@@ -1097,19 +1130,19 @@ endif
        $(RM) GIT-VERSION-FILE GIT-CFLAGS GIT-GUI-VARS
 
 .PHONY: all install clean strip
-.PHONY: .FORCE-GIT-VERSION-FILE TAGS tags .FORCE-GIT-CFLAGS
+.PHONY: .FORCE-GIT-VERSION-FILE TAGS tags cscope .FORCE-GIT-CFLAGS
 
 ### Check documentation
 #
 check-docs::
-       @for v in $(ALL_PROGRAMS) $(BUILT_INS) git$X gitk; \
+       @(for v in $(ALL_PROGRAMS) $(BUILT_INS) git gitk; \
        do \
                case "$$v" in \
                git-merge-octopus | git-merge-ours | git-merge-recursive | \
-               git-merge-resolve | git-merge-stupid | \
+               git-merge-resolve | git-merge-stupid | git-merge-subtree | \
                git-add--interactive | git-fsck-objects | git-init-db | \
-               git-repo-config | git-fetch--tool | \
-               git-ssh-pull | git-ssh-push ) continue ;; \
+               git-rebase--interactive | \
+               git-repo-config | git-fetch--tool ) continue ;; \
                esac ; \
                test -f "Documentation/$$v.txt" || \
                echo "no doc: $$v"; \
@@ -1119,7 +1152,30 @@ check-docs::
                git) ;; \
                *) echo "no link: $$v";; \
                esac ; \
-       done | sort
+       done; \
+       ( \
+               sed -e '1,/^__DATA__/d' \
+                   -e 's/[     ].*//' \
+                   -e 's/^/listed /' Documentation/cmd-list.perl; \
+               ls -1 Documentation/git*txt | \
+               sed -e 's|Documentation/|documented |' \
+                   -e 's/\.txt//'; \
+       ) | while read how cmd; \
+       do \
+               case "$$how,$$cmd" in \
+               *,git-citool | \
+               *,git-gui | \
+               documented,gitattributes | \
+               documented,gitignore | \
+               documented,gitmodules | \
+               documented,git-tools | \
+               sentinel,not,matching,is,ok ) continue ;; \
+               esac; \
+               case " $(ALL_PROGRAMS) $(BUILT_INS) git gitk " in \
+               *" $$cmd "*)    ;; \
+               *) echo "removed but $$how: $$cmd" ;; \
+               esac; \
+       done ) | sort
 
 ### Make sure built-ins do not have dups and listed in git.c
 #
index 509b3f6..46308ce 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes-1.5.3.7.txt
\ No newline at end of file
+Documentation/RelNotes-1.5.4.txt
\ No newline at end of file
index 66fe3e3..e1bced5 100644 (file)
@@ -3,7 +3,6 @@
  */
 #include "cache.h"
 #include "commit.h"
-#include "strbuf.h"
 #include "tar.h"
 #include "builtin.h"
 #include "archive.h"
@@ -17,6 +16,7 @@ static unsigned long offset;
 static time_t archive_time;
 static int tar_umask = 002;
 static int verbose;
+static const struct commit *commit;
 
 /* writes out the whole block, but only if it is full */
 static void write_if_needed(void)
@@ -78,19 +78,6 @@ static void write_trailer(void)
        }
 }
 
-static void strbuf_append_string(struct strbuf *sb, const char *s)
-{
-       int slen = strlen(s);
-       int total = sb->len + slen;
-       if (total + 1 > sb->alloc) {
-               sb->buf = xrealloc(sb->buf, total + 1);
-               sb->alloc = total + 1;
-       }
-       memcpy(sb->buf + sb->len, s, slen);
-       sb->len = total;
-       sb->buf[total] = '\0';
-}
-
 /*
  * pax extended header records have the format "%u %s=%s\n".  %u contains
  * the size of the whole string (including the %u), the first %s is the
@@ -100,26 +87,17 @@ static void strbuf_append_string(struct strbuf *sb, const char *s)
 static void strbuf_append_ext_header(struct strbuf *sb, const char *keyword,
                                      const char *value, unsigned int valuelen)
 {
-       char *p;
-       int len, total, tmp;
+       int len, tmp;
 
        /* "%u %s=%s\n" */
        len = 1 + 1 + strlen(keyword) + 1 + valuelen + 1;
        for (tmp = len; tmp > 9; tmp /= 10)
                len++;
 
-       total = sb->len + len;
-       if (total > sb->alloc) {
-               sb->buf = xrealloc(sb->buf, total);
-               sb->alloc = total;
-       }
-
-       p = sb->buf;
-       p += sprintf(p, "%u %s=", len, keyword);
-       memcpy(p, value, valuelen);
-       p += valuelen;
-       *p = '\n';
-       sb->len = total;
+       strbuf_grow(sb, len);
+       strbuf_addf(sb, "%u %s=", len, keyword);
+       strbuf_add(sb, value, valuelen);
+       strbuf_addch(sb, '\n');
 }
 
 static unsigned int ustar_header_chksum(const struct ustar_header *header)
@@ -153,8 +131,7 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
        struct strbuf ext_header;
 
        memset(&header, 0, sizeof(header));
-       ext_header.buf = NULL;
-       ext_header.len = ext_header.alloc = 0;
+       strbuf_init(&ext_header, 0);
 
        if (!sha1) {
                *header.typeflag = TYPEFLAG_GLOBAL_HEADER;
@@ -166,7 +143,7 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
                sprintf(header.name, "%s.paxheader", sha1_to_hex(sha1));
        } else {
                if (verbose)
-                       fprintf(stderr, "%.*s\n", path->len, path->buf);
+                       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;
@@ -225,8 +202,8 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
 
        if (ext_header.len > 0) {
                write_entry(sha1, NULL, 0, ext_header.buf, ext_header.len);
-               free(ext_header.buf);
        }
+       strbuf_release(&ext_header);
        write_blocked(&header, sizeof(header));
        if (S_ISREG(mode) && buffer && size > 0)
                write_blocked(buffer, size);
@@ -235,11 +212,11 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
 static void write_global_extended_header(const unsigned char *sha1)
 {
        struct strbuf ext_header;
-       ext_header.buf = NULL;
-       ext_header.len = ext_header.alloc = 0;
+
+       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);
-       free(ext_header.buf);
+       strbuf_release(&ext_header);
 }
 
 static int git_tar_config(const char *var, const char *value)
@@ -260,32 +237,22 @@ 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;
-       int filenamelen = strlen(filename);
+       static struct strbuf path = STRBUF_INIT;
        void *buffer;
        enum object_type type;
        unsigned long size;
 
-       if (!path.alloc) {
-               path.buf = xmalloc(PATH_MAX);
-               path.alloc = PATH_MAX;
-               path.len = path.eof = 0;
-       }
-       if (path.alloc < baselen + filenamelen + 1) {
-               free(path.buf);
-               path.buf = xmalloc(baselen + filenamelen + 1);
-               path.alloc = baselen + filenamelen + 1;
-       }
-       memcpy(path.buf, base, baselen);
-       memcpy(path.buf + baselen, filename, filenamelen);
-       path.len = baselen + filenamelen;
-       path.buf[path.len] = '\0';
+       strbuf_reset(&path);
+       strbuf_grow(&path, PATH_MAX);
+       strbuf_add(&path, base, baselen);
+       strbuf_addstr(&path, filename);
        if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
-               strbuf_append_string(&path, "/");
+               strbuf_addch(&path, '/');
                buffer = NULL;
                size = 0;
        } else {
-               buffer = convert_sha1_file(path.buf, sha1, mode, &type, &size);
+               buffer = sha1_file_to_archive(path.buf, sha1, mode, &type,
+                                             &size, commit);
                if (!buffer)
                        die("cannot read %s", sha1_to_hex(sha1));
        }
@@ -304,6 +271,7 @@ int write_tar_archive(struct archiver_args *args)
 
        archive_time = args->time;
        verbose = args->verbose;
+       commit = args->commit;
 
        if (args->commit_sha1)
                write_global_extended_header(args->commit_sha1);
index 444e162..74e30f6 100644 (file)
@@ -12,6 +12,7 @@
 static int verbose;
 static int zip_date;
 static int zip_time;
+static const struct commit *commit;
 
 static unsigned char *zip_dir;
 static unsigned int zip_dir_size;
@@ -191,11 +192,13 @@ static int write_zip_entry(const unsigned char *sha1,
                compressed_size = 0;
        } else if (S_ISREG(mode) || S_ISLNK(mode)) {
                method = 0;
-               attr2 = S_ISLNK(mode) ? ((mode | 0777) << 16) : 0;
+               attr2 = S_ISLNK(mode) ? ((mode | 0777) << 16) :
+                       (mode & 0111) ? ((mode) << 16) : 0;
                if (S_ISREG(mode) && zlib_compression_level != 0)
                        method = 8;
                result = 0;
-               buffer = convert_sha1_file(path, sha1, mode, &type, &size);
+               buffer = sha1_file_to_archive(path, sha1, mode, &type, &size,
+                                             commit);
                if (!buffer)
                        die("cannot read %s", sha1_to_hex(sha1));
                crc = crc32(crc, buffer, size);
@@ -229,7 +232,8 @@ static int write_zip_entry(const unsigned char *sha1,
        }
 
        copy_le32(dirent.magic, 0x02014b50);
-       copy_le16(dirent.creator_version, S_ISLNK(mode) ? 0x0317 : 0);
+       copy_le16(dirent.creator_version,
+               S_ISLNK(mode) || (S_ISREG(mode) && (mode & 0111)) ? 0x0317 : 0);
        copy_le16(dirent.version, 10);
        copy_le16(dirent.flags, 0);
        copy_le16(dirent.compression_method, method);
@@ -316,6 +320,7 @@ int write_zip_archive(struct archiver_args *args)
        zip_dir = xmalloc(ZIP_DIRECTORY_MIN_SIZE);
        zip_dir_size = ZIP_DIRECTORY_MIN_SIZE;
        verbose = args->verbose;
+       commit = args->commit;
 
        if (args->base && plen > 0 && args->base[plen - 1] == '/') {
                char *base = xstrdup(args->base);
index 6838dc7..5791e65 100644 (file)
--- a/archive.h
+++ b/archive.h
@@ -8,6 +8,7 @@ struct archiver_args {
        const char *base;
        struct tree *tree;
        const unsigned char *commit_sha1;
+       const struct commit *commit;
        time_t time;
        const char **pathspec;
        unsigned int verbose : 1;
@@ -42,4 +43,6 @@ 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);
+
 #endif /* ARCHIVE_H */
diff --git a/attr.c b/attr.c
index 6e82507..741db3b 100644 (file)
--- a/attr.c
+++ b/attr.c
@@ -160,12 +160,7 @@ static const char *parse_attr(const char *src, int lineno, const char *cp,
                else if (!equals)
                        e->setto = ATTR__TRUE;
                else {
-                       char *value;
-                       int vallen = ep - equals;
-                       value = xmalloc(vallen);
-                       memcpy(value, equals+1, vallen-1);
-                       value[vallen-1] = 0;
-                       e->setto = value;
+                       e->setto = xmemdupz(equals + 1, ep - equals - 1);
                }
                e->attr = git_attr(cp, len);
        }
index 4fc9d6f..cf815a0 100644 (file)
 #include "diffcore.h"
 #include "commit.h"
 #include "revision.h"
+#include "run-command.h"
+#include "parse-options.h"
 
-static const char builtin_add_usage[] =
-"git-add [-n] [-v] [-f] [--interactive | -i] [-u] [--refresh] [--] <filepattern>...";
+static const char * const builtin_add_usage[] = {
+       "git-add [options] [--] <filepattern>...",
+       NULL
+};
 
 static int take_worktree_changes;
 
@@ -66,12 +70,8 @@ static void fill_directory(struct dir_struct *dir, const char **pathspec,
        baselen = common_prefix(pathspec);
        path = ".";
        base = "";
-       if (baselen) {
-               char *common = xmalloc(baselen + 1);
-               memcpy(common, *pathspec, baselen);
-               common[baselen] = 0;
-               path = base = common;
-       }
+       if (baselen)
+               path = base = xmemdupz(*pathspec, baselen);
 
        /* Read the directory and prune it */
        read_directory(dir, path, base, baselen, pathspec);
@@ -98,7 +98,6 @@ static void update_callback(struct diff_queue_struct *q,
                        break;
                case DIFF_STATUS_DELETED:
                        remove_file_from_cache(path);
-                       cache_tree_invalidate_path(active_cache_tree, path);
                        if (verbose)
                                printf("remove '%s'\n", path);
                        break;
@@ -106,7 +105,7 @@ static void update_callback(struct diff_queue_struct *q,
        }
 }
 
-static void update(int verbose, const char *prefix, const char **files)
+void add_files_to_cache(int verbose, const char *prefix, const char **files)
 {
        struct rev_info rev;
        init_revisions(&rev, prefix);
@@ -115,8 +114,6 @@ static void update(int verbose, const char *prefix, const char **files)
        rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
        rev.diffopt.format_callback = update_callback;
        rev.diffopt.format_callback_data = &verbose;
-       if (read_cache() < 0)
-               die("index file corrupt");
        run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
 }
 
@@ -138,80 +135,63 @@ static void refresh(int verbose, const char **pathspec)
         free(seen);
 }
 
+int interactive_add(void)
+{
+       const char *argv[2] = { "add--interactive", NULL };
+
+       return run_command_v_opt(argv, RUN_GIT_CMD);
+}
+
 static struct lock_file lock_file;
 
 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 add_interactive = 0;
+
+static struct option builtin_add_options[] = {
+       OPT__DRY_RUN(&show_only),
+       OPT__VERBOSE(&verbose),
+       OPT_GROUP(""),
+       OPT_BOOLEAN('i', "interactive", &add_interactive, "interactive picking"),
+       OPT_BOOLEAN('f', NULL, &ignored_too, "allow adding otherwise ignored files"),
+       OPT_BOOLEAN('u', NULL, &take_worktree_changes, "update tracked files"),
+       OPT_BOOLEAN( 0 , "refresh", &refresh_only, "don't add, only refresh the index"),
+       OPT_END(),
+};
+
 int cmd_add(int argc, const char **argv, const char *prefix)
 {
-       int i, newfd;
-       int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0;
+       int i, newfd, orig_argc = argc;
        const char **pathspec;
        struct dir_struct dir;
-       int add_interactive = 0;
 
-       for (i = 1; i < argc; i++) {
-               if (!strcmp("--interactive", argv[i]) ||
-                   !strcmp("-i", argv[i]))
-                       add_interactive++;
-       }
+       argc = parse_options(argc, argv, builtin_add_options,
+                         builtin_add_usage, 0);
        if (add_interactive) {
-               const char *args[] = { "add--interactive", NULL };
-
-               if (add_interactive != 1 || argc != 2)
+               if (add_interactive != 1 || orig_argc != 2)
                        die("add --interactive does not take any parameters");
-               execv_git_cmd(args);
-               exit(1);
+               exit(interactive_add());
        }
 
        git_config(git_default_config);
 
        newfd = hold_locked_index(&lock_file, 1);
 
-       for (i = 1; i < argc; i++) {
-               const char *arg = argv[i];
-
-               if (arg[0] != '-')
-                       break;
-               if (!strcmp(arg, "--")) {
-                       i++;
-                       break;
-               }
-               if (!strcmp(arg, "-n")) {
-                       show_only = 1;
-                       continue;
-               }
-               if (!strcmp(arg, "-f")) {
-                       ignored_too = 1;
-                       continue;
-               }
-               if (!strcmp(arg, "-v")) {
-                       verbose = 1;
-                       continue;
-               }
-               if (!strcmp(arg, "-u")) {
-                       take_worktree_changes = 1;
-                       continue;
-               }
-               if (!strcmp(arg, "--refresh")) {
-                       refresh_only = 1;
-                       continue;
-               }
-               usage(builtin_add_usage);
-       }
-
        if (take_worktree_changes) {
-               update(verbose, prefix, argv + i);
+               if (read_cache() < 0)
+                       die("index file corrupt");
+               add_files_to_cache(verbose, prefix, argv);
                goto finish;
        }
 
-       if (argc <= i) {
+       if (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 + i);
+       pathspec = get_pathspec(prefix, argv);
 
        if (refresh_only) {
                refresh(verbose, pathspec);
index 0fff02e..91f8752 100644 (file)
@@ -152,7 +152,7 @@ struct patch {
        unsigned int is_rename:1;
        struct fragment *fragments;
        char *result;
-       unsigned long resultsize;
+       size_t resultsize;
        char old_sha1_prefix[41];
        char new_sha1_prefix[41];
        struct patch *next;
@@ -163,15 +163,14 @@ static void say_patch_name(FILE *output, const char *pre, struct patch *patch, c
        fputs(pre, output);
        if (patch->old_name && patch->new_name &&
            strcmp(patch->old_name, patch->new_name)) {
-               write_name_quoted(NULL, 0, patch->old_name, 1, output);
+               quote_c_style(patch->old_name, NULL, output, 0);
                fputs(" => ", output);
-               write_name_quoted(NULL, 0, patch->new_name, 1, output);
-       }
-       else {
+               quote_c_style(patch->new_name, NULL, output, 0);
+       } else {
                const char *n = patch->new_name;
                if (!n)
                        n = patch->old_name;
-               write_name_quoted(NULL, 0, n, 1, output);
+               quote_c_style(n, NULL, output, 0);
        }
        fputs(post, output);
 }
@@ -179,36 +178,18 @@ static void say_patch_name(FILE *output, const char *pre, struct patch *patch, c
 #define CHUNKSIZE (8192)
 #define SLOP (16)
 
-static void *read_patch_file(int fd, unsigned long *sizep)
+static void read_patch_file(struct strbuf *sb, int fd)
 {
-       unsigned long size = 0, alloc = CHUNKSIZE;
-       void *buffer = xmalloc(alloc);
-
-       for (;;) {
-               ssize_t nr = alloc - size;
-               if (nr < 1024) {
-                       alloc += CHUNKSIZE;
-                       buffer = xrealloc(buffer, alloc);
-                       nr = alloc - size;
-               }
-               nr = xread(fd, (char *) buffer + size, nr);
-               if (!nr)
-                       break;
-               if (nr < 0)
-                       die("git-apply: read returned %s", strerror(errno));
-               size += nr;
-       }
-       *sizep = size;
+       if (strbuf_read(sb, fd, 0) < 0)
+               die("git-apply: read returned %s", strerror(errno));
 
        /*
         * Make sure that we have some slop in the buffer
         * so that we can do speculative "memcmp" etc, and
         * see to it that it is NUL-filled.
         */
-       if (alloc < size + SLOP)
-               buffer = xrealloc(buffer, size + SLOP);
-       memset((char *) buffer + size, 0, SLOP);
-       return buffer;
+       strbuf_grow(sb, SLOP);
+       memset(sb->buf + sb->len, 0, SLOP);
 }
 
 static unsigned long linelen(const char *buffer, unsigned long size)
@@ -244,35 +225,33 @@ static char *find_name(const char *line, char *def, int p_value, int terminate)
 {
        int len;
        const char *start = line;
-       char *name;
 
        if (*line == '"') {
+               struct strbuf name;
+
                /* Proposed "new-style" GNU patch/diff format; see
                 * http://marc.theaimsgroup.com/?l=git&m=112927316408690&w=2
                 */
-               name = unquote_c_style(line, NULL);
-               if (name) {
-                       char *cp = name;
-                       while (p_value) {
+               strbuf_init(&name, 0);
+               if (!unquote_c_style(&name, line, NULL)) {
+                       char *cp;
+
+                       for (cp = name.buf; p_value; p_value--) {
                                cp = strchr(cp, '/');
                                if (!cp)
                                        break;
                                cp++;
-                               p_value--;
                        }
                        if (cp) {
                                /* name can later be freed, so we need
                                 * to memmove, not just return cp
                                 */
-                               memmove(name, cp, strlen(cp) + 1);
+                               strbuf_remove(&name, 0, cp - name.buf);
                                free(def);
-                               return name;
-                       }
-                       else {
-                               free(name);
-                               name = NULL;
+                               return strbuf_detach(&name, NULL);
                        }
                }
+               strbuf_release(&name);
        }
 
        for (;;) {
@@ -304,13 +283,10 @@ static char *find_name(const char *line, char *def, int p_value, int terminate)
                int deflen = strlen(def);
                if (deflen < len && !strncmp(start, def, deflen))
                        return def;
+               free(def);
        }
 
-       name = xmalloc(len + 1);
-       memcpy(name, start, len);
-       name[len] = 0;
-       free(def);
-       return name;
+       return xmemdupz(start, len);
 }
 
 static int count_slashes(const char *cp)
@@ -583,29 +559,30 @@ static const char *stop_at_slash(const char *line, int llen)
  */
 static char *git_header_name(char *line, int llen)
 {
-       int len;
        const char *name;
        const char *second = NULL;
+       size_t len;
 
        line += strlen("diff --git ");
        llen -= strlen("diff --git ");
 
        if (*line == '"') {
                const char *cp;
-               char *first = unquote_c_style(line, &second);
-               if (!first)
-                       return NULL;
+               struct strbuf first;
+               struct strbuf sp;
+
+               strbuf_init(&first, 0);
+               strbuf_init(&sp, 0);
+
+               if (unquote_c_style(&first, line, &second))
+                       goto free_and_fail1;
 
                /* advance to the first slash */
-               cp = stop_at_slash(first, strlen(first));
-               if (!cp || cp == first) {
-                       /* we do not accept absolute paths */
-               free_first_and_fail:
-                       free(first);
-                       return NULL;
-               }
-               len = strlen(cp+1);
-               memmove(first, cp+1, len+1); /* including NUL */
+               cp = stop_at_slash(first.buf, first.len);
+               /* we do not accept absolute paths */
+               if (!cp || cp == first.buf)
+                       goto free_and_fail1;
+               strbuf_remove(&first, 0, cp + 1 - first.buf);
 
                /* second points at one past closing dq of name.
                 * find the second name.
@@ -614,40 +591,40 @@ static char *git_header_name(char *line, int llen)
                        second++;
 
                if (line + llen <= second)
-                       goto free_first_and_fail;
+                       goto free_and_fail1;
                if (*second == '"') {
-                       char *sp = unquote_c_style(second, NULL);
-                       if (!sp)
-                               goto free_first_and_fail;
-                       cp = stop_at_slash(sp, strlen(sp));
-                       if (!cp || cp == sp) {
-                       free_both_and_fail:
-                               free(sp);
-                               goto free_first_and_fail;
-                       }
+                       if (unquote_c_style(&sp, second, NULL))
+                               goto free_and_fail1;
+                       cp = stop_at_slash(sp.buf, sp.len);
+                       if (!cp || cp == sp.buf)
+                               goto free_and_fail1;
                        /* They must match, otherwise ignore */
-                       if (strcmp(cp+1, first))
-                               goto free_both_and_fail;
-                       free(sp);
-                       return first;
+                       if (strcmp(cp + 1, first.buf))
+                               goto free_and_fail1;
+                       strbuf_release(&sp);
+                       return strbuf_detach(&first, NULL);
                }
 
                /* unquoted second */
                cp = stop_at_slash(second, line + llen - second);
                if (!cp || cp == second)
-                       goto free_first_and_fail;
+                       goto free_and_fail1;
                cp++;
-               if (line + llen - cp != len + 1 ||
-                   memcmp(first, cp, len))
-                       goto free_first_and_fail;
-               return first;
+               if (line + llen - cp != first.len + 1 ||
+                   memcmp(first.buf, cp, first.len))
+                       goto free_and_fail1;
+               return strbuf_detach(&first, NULL);
+
+       free_and_fail1:
+               strbuf_release(&first);
+               strbuf_release(&sp);
+               return NULL;
        }
 
        /* unquoted first name */
        name = stop_at_slash(line, llen);
        if (!name || name == line)
                return NULL;
-
        name++;
 
        /* since the first name is unquoted, a dq if exists must be
@@ -655,28 +632,30 @@ static char *git_header_name(char *line, int llen)
         */
        for (second = name; second < line + llen; second++) {
                if (*second == '"') {
-                       const char *cp = second;
+                       struct strbuf sp;
                        const char *np;
-                       char *sp = unquote_c_style(second, NULL);
-
-                       if (!sp)
-                               return NULL;
-                       np = stop_at_slash(sp, strlen(sp));
-                       if (!np || np == sp) {
-                       free_second_and_fail:
-                               free(sp);
-                               return NULL;
-                       }
+
+                       strbuf_init(&sp, 0);
+                       if (unquote_c_style(&sp, second, NULL))
+                               goto free_and_fail2;
+
+                       np = stop_at_slash(sp.buf, sp.len);
+                       if (!np || np == sp.buf)
+                               goto free_and_fail2;
                        np++;
-                       len = strlen(np);
-                       if (len < cp - name &&
+
+                       len = sp.buf + sp.len - np;
+                       if (len < second - name &&
                            !strncmp(np, name, len) &&
                            isspace(name[len])) {
                                /* Good */
-                               memmove(sp, np, len + 1);
-                               return sp;
+                               strbuf_remove(&sp, 0, np - sp.buf);
+                               return strbuf_detach(&sp, NULL);
                        }
-                       goto free_second_and_fail;
+
+               free_and_fail2:
+                       strbuf_release(&sp);
+                       return NULL;
                }
        }
 
@@ -700,14 +679,10 @@ static char *git_header_name(char *line, int llen)
                                        break;
                        }
                        if (second[len] == '\n' && !memcmp(name, second, len)) {
-                               char *ret = xmalloc(len + 1);
-                               memcpy(ret, name, len);
-                               ret[len] = 0;
-                               return ret;
+                               return xmemdupz(name, len);
                        }
                }
        }
-       return NULL;
 }
 
 /* Verify that we recognize the lines following a git header */
@@ -1397,96 +1372,66 @@ static const char minuses[]= "--------------------------------------------------
 
 static void show_stats(struct patch *patch)
 {
-       const char *prefix = "";
-       char *name = patch->new_name;
-       char *qname = NULL;
-       int len, max, add, del, total;
-
-       if (!name)
-               name = patch->old_name;
+       struct strbuf qname;
+       char *cp = patch->new_name ? patch->new_name : patch->old_name;
+       int max, add, del;
 
-       if (0 < (len = quote_c_style(name, NULL, NULL, 0))) {
-               qname = xmalloc(len + 1);
-               quote_c_style(name, qname, NULL, 0);
-               name = qname;
-       }
+       strbuf_init(&qname, 0);
+       quote_c_style(cp, &qname, NULL, 0);
 
        /*
         * "scale" the filename
         */
-       len = strlen(name);
        max = max_len;
        if (max > 50)
                max = 50;
-       if (len > max) {
-               char *slash;
-               prefix = "...";
-               max -= 3;
-               name += len - max;
-               slash = strchr(name, '/');
-               if (slash)
-                       name = slash;
+
+       if (qname.len > max) {
+               cp = strchr(qname.buf + qname.len + 3 - max, '/');
+               if (!cp)
+                       cp = qname.buf + qname.len + 3 - max;
+               strbuf_splice(&qname, 0, cp - qname.buf, "...", 3);
+       }
+
+       if (patch->is_binary) {
+               printf(" %-*s |  Bin\n", max, qname.buf);
+               strbuf_release(&qname);
+               return;
        }
-       len = max;
+
+       printf(" %-*s |", max, qname.buf);
+       strbuf_release(&qname);
 
        /*
         * scale the add/delete
         */
-       max = max_change;
-       if (max + len > 70)
-               max = 70 - len;
-
+       max = max + max_change > 70 ? 70 - max : max_change;
        add = patch->lines_added;
        del = patch->lines_deleted;
-       total = add + del;
 
        if (max_change > 0) {
-               total = (total * max + max_change / 2) / max_change;
+               int total = ((add + del) * max + max_change / 2) / max_change;
                add = (add * max + max_change / 2) / max_change;
                del = total - add;
        }
-       if (patch->is_binary)
-               printf(" %s%-*s |  Bin\n", prefix, len, name);
-       else
-               printf(" %s%-*s |%5d %.*s%.*s\n", prefix,
-                      len, name, patch->lines_added + patch->lines_deleted,
-                      add, pluses, del, minuses);
-       free(qname);
+       printf("%5d %.*s%.*s\n", patch->lines_added + patch->lines_deleted,
+               add, pluses, del, minuses);
 }
 
-static int read_old_data(struct stat *st, const char *path, char **buf_p, unsigned long *alloc_p, unsigned long *size_p)
+static int read_old_data(struct stat *st, const char *path, struct strbuf *buf)
 {
-       int fd;
-       unsigned long got;
-       unsigned long nsize;
-       char *nbuf;
-       unsigned long size = *size_p;
-       char *buf = *buf_p;
-
        switch (st->st_mode & S_IFMT) {
        case S_IFLNK:
-               return readlink(path, buf, size) != size;
+               strbuf_grow(buf, st->st_size);
+               if (readlink(path, buf->buf, st->st_size) != st->st_size)
+                       return -1;
+               strbuf_setlen(buf, st->st_size);
+               return 0;
        case S_IFREG:
-               fd = open(path, O_RDONLY);
-               if (fd < 0)
-                       return error("unable to open %s", path);
-               got = 0;
-               for (;;) {
-                       ssize_t ret = xread(fd, buf + got, size - got);
-                       if (ret <= 0)
-                               break;
-                       got += ret;
-               }
-               close(fd);
-               nsize = got;
-               nbuf = convert_to_git(path, buf, &nsize);
-               if (nbuf) {
-                       free(buf);
-                       *buf_p = nbuf;
-                       *alloc_p = nsize;
-                       *size_p = nsize;
-               }
-               return got != size;
+               if (strbuf_read_file(buf, path, st->st_size) != st->st_size)
+                       return error("unable to open or read %s", path);
+               convert_to_git(path, buf->buf, buf->len, buf);
+               return 0;
        default:
                return -1;
        }
@@ -1591,12 +1536,6 @@ static void remove_last_line(const char **rbuf, int *rsize)
        *rsize = offset + 1;
 }
 
-struct buffer_desc {
-       char *buffer;
-       unsigned long size;
-       unsigned long alloc;
-};
-
 static int apply_line(char *output, const char *patch, int plen)
 {
        /* plen is number of bytes to be copied from patch,
@@ -1673,10 +1612,9 @@ static int apply_line(char *output, const char *patch, int plen)
        return output + plen - buf;
 }
 
-static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag, int inaccurate_eof)
+static int apply_one_fragment(struct strbuf *buf, struct fragment *frag, int inaccurate_eof)
 {
        int match_beginning, match_end;
-       char *buf = desc->buffer;
        const char *patch = frag->patch;
        int offset, size = frag->size;
        char *old = xmalloc(size);
@@ -1787,24 +1725,17 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag, i
        lines = 0;
        pos = frag->newpos;
        for (;;) {
-               offset = find_offset(buf, desc->size,
+               offset = find_offset(buf->buf, buf->len,
                                     oldlines, oldsize, pos, &lines);
-               if (match_end && offset + oldsize != desc->size)
+               if (match_end && offset + oldsize != buf->len)
                        offset = -1;
                if (match_beginning && offset)
                        offset = -1;
                if (offset >= 0) {
-                       int diff;
-                       unsigned long size, alloc;
-
                        if (new_whitespace == strip_whitespace &&
-                           (desc->size - oldsize - offset == 0)) /* end of file? */
+                           (buf->len - oldsize - offset == 0)) /* end of file? */
                                newsize -= new_blank_lines_at_end;
 
-                       diff = newsize - oldsize;
-                       size = desc->size + diff;
-                       alloc = desc->alloc;
-
                        /* Warn if it was necessary to reduce the number
                         * of context lines.
                         */
@@ -1814,19 +1745,8 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag, i
                                        " to apply fragment at %d\n",
                                        leading, trailing, pos + lines);
 
-                       if (size > alloc) {
-                               alloc = size + 8192;
-                               desc->alloc = alloc;
-                               buf = xrealloc(buf, alloc);
-                               desc->buffer = buf;
-                       }
-                       desc->size = size;
-                       memmove(buf + offset + newsize,
-                               buf + offset + oldsize,
-                               size - offset - newsize);
-                       memcpy(buf + offset, newlines, newsize);
+                       strbuf_splice(buf, offset, oldsize, newlines, newsize);
                        offset = 0;
-
                        break;
                }
 
@@ -1862,12 +1782,11 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag, i
        return offset;
 }
 
-static int apply_binary_fragment(struct buffer_desc *desc, struct patch *patch)
+static int apply_binary_fragment(struct strbuf *buf, struct patch *patch)
 {
-       unsigned long dst_size;
        struct fragment *fragment = patch->fragments;
-       void *data;
-       void *result;
+       unsigned long len;
+       void *dst;
 
        /* Binary patch is irreversible without the optional second hunk */
        if (apply_in_reverse) {
@@ -1878,29 +1797,24 @@ static int apply_binary_fragment(struct buffer_desc *desc, struct patch *patch)
                                     ? patch->new_name : patch->old_name);
                fragment = fragment->next;
        }
-       data = (void*) fragment->patch;
        switch (fragment->binary_patch_method) {
        case BINARY_DELTA_DEFLATED:
-               result = patch_delta(desc->buffer, desc->size,
-                                    data,
-                                    fragment->size,
-                                    &dst_size);
-               free(desc->buffer);
-               desc->buffer = result;
-               break;
+               dst = patch_delta(buf->buf, buf->len, fragment->patch,
+                                 fragment->size, &len);
+               if (!dst)
+                       return -1;
+               /* XXX patch_delta NUL-terminates */
+               strbuf_attach(buf, dst, len, len + 1);
+               return 0;
        case BINARY_LITERAL_DEFLATED:
-               free(desc->buffer);
-               desc->buffer = data;
-               dst_size = fragment->size;
-               break;
+               strbuf_reset(buf);
+               strbuf_add(buf, fragment->patch, fragment->size);
+               return 0;
        }
-       if (!desc->buffer)
-               return -1;
-       desc->size = desc->alloc = dst_size;
-       return 0;
+       return -1;
 }
 
-static int apply_binary(struct buffer_desc *desc, struct patch *patch)
+static int apply_binary(struct strbuf *buf, struct patch *patch)
 {
        const char *name = patch->old_name ? patch->old_name : patch->new_name;
        unsigned char sha1[20];
@@ -1919,7 +1833,7 @@ static int apply_binary(struct buffer_desc *desc, struct patch *patch)
                /* See if the old one matches what the patch
                 * applies to.
                 */
-               hash_sha1_file(desc->buffer, desc->size, blob_type, sha1);
+               hash_sha1_file(buf->buf, buf->len, blob_type, sha1);
                if (strcmp(sha1_to_hex(sha1), patch->old_sha1_prefix))
                        return error("the patch applies to '%s' (%s), "
                                     "which does not match the "
@@ -1928,16 +1842,14 @@ static int apply_binary(struct buffer_desc *desc, struct patch *patch)
        }
        else {
                /* Otherwise, the old one must be empty. */
-               if (desc->size)
+               if (buf->len)
                        return error("the patch applies to an empty "
                                     "'%s' but it is not empty", name);
        }
 
        get_sha1_hex(patch->new_sha1_prefix, sha1);
        if (is_null_sha1(sha1)) {
-               free(desc->buffer);
-               desc->alloc = desc->size = 0;
-               desc->buffer = NULL;
+               strbuf_release(buf);
                return 0; /* deletion patch */
        }
 
@@ -1945,43 +1857,44 @@ static int apply_binary(struct buffer_desc *desc, struct patch *patch)
                /* We already have the postimage */
                enum object_type type;
                unsigned long size;
+               char *result;
 
-               free(desc->buffer);
-               desc->buffer = read_sha1_file(sha1, &type, &size);
-               if (!desc->buffer)
+               result = read_sha1_file(sha1, &type, &size);
+               if (!result)
                        return error("the necessary postimage %s for "
                                     "'%s' cannot be read",
                                     patch->new_sha1_prefix, name);
-               desc->alloc = desc->size = size;
-       }
-       else {
-               /* We have verified desc matches the preimage;
+               /* XXX read_sha1_file NUL-terminates */
+               strbuf_attach(buf, result, size, size + 1);
+       else {
+               /* We have verified buf matches the preimage;
                 * apply the patch data to it, which is stored
                 * in the patch->fragments->{patch,size}.
                 */
-               if (apply_binary_fragment(desc, patch))
+               if (apply_binary_fragment(buf, patch))
                        return error("binary patch does not apply to '%s'",
                                     name);
 
                /* verify that the result matches */
-               hash_sha1_file(desc->buffer, desc->size, blob_type, sha1);
+               hash_sha1_file(buf->buf, buf->len, blob_type, sha1);
                if (strcmp(sha1_to_hex(sha1), patch->new_sha1_prefix))
-                       return error("binary patch to '%s' creates incorrect result (expecting %s, got %s)", name, patch->new_sha1_prefix, sha1_to_hex(sha1));
+                       return error("binary patch to '%s' creates incorrect result (expecting %s, got %s)",
+                               name, patch->new_sha1_prefix, sha1_to_hex(sha1));
        }
 
        return 0;
 }
 
-static int apply_fragments(struct buffer_desc *desc, struct patch *patch)
+static int apply_fragments(struct strbuf *buf, struct patch *patch)
 {
        struct fragment *frag = patch->fragments;
        const char *name = patch->old_name ? patch->old_name : patch->new_name;
 
        if (patch->is_binary)
-               return apply_binary(desc, patch);
+               return apply_binary(buf, patch);
 
        while (frag) {
-               if (apply_one_fragment(desc, frag, patch->inaccurate_eof)) {
+               if (apply_one_fragment(buf, frag, patch->inaccurate_eof)) {
                        error("patch failed: %s:%ld", name, frag->oldpos);
                        if (!apply_with_reject)
                                return -1;
@@ -1992,76 +1905,56 @@ static int apply_fragments(struct buffer_desc *desc, struct patch *patch)
        return 0;
 }
 
-static int read_file_or_gitlink(struct cache_entry *ce, char **buf_p,
-                               unsigned long *size_p)
+static int read_file_or_gitlink(struct cache_entry *ce, struct strbuf *buf)
 {
        if (!ce)
                return 0;
 
        if (S_ISGITLINK(ntohl(ce->ce_mode))) {
-               *buf_p = xmalloc(100);
-               *size_p = snprintf(*buf_p, 100,
-                       "Subproject commit %s\n", sha1_to_hex(ce->sha1));
+               strbuf_grow(buf, 100);
+               strbuf_addf(buf, "Subproject commit %s\n", sha1_to_hex(ce->sha1));
        } else {
                enum object_type type;
-               *buf_p = read_sha1_file(ce->sha1, &type, size_p);
-               if (!*buf_p)
+               unsigned long sz;
+               char *result;
+
+               result = read_sha1_file(ce->sha1, &type, &sz);
+               if (!result)
                        return -1;
+               /* XXX read_sha1_file NUL-terminates */
+               strbuf_attach(buf, result, sz, sz + 1);
        }
        return 0;
 }
 
 static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *ce)
 {
-       char *buf;
-       unsigned long size, alloc;
-       struct buffer_desc desc;
+       struct strbuf buf;
 
-       size = 0;
-       alloc = 0;
-       buf = NULL;
+       strbuf_init(&buf, 0);
        if (cached) {
-               if (read_file_or_gitlink(ce, &buf, &size))
+               if (read_file_or_gitlink(ce, &buf))
                        return error("read of %s failed", patch->old_name);
-               alloc = size;
        } else if (patch->old_name) {
                if (S_ISGITLINK(patch->old_mode)) {
-                       if (ce)
-                               read_file_or_gitlink(ce, &buf, &size);
-                       else {
+                       if (ce) {
+                               read_file_or_gitlink(ce, &buf);
+                       else {
                                /*
                                 * There is no way to apply subproject
                                 * patch without looking at the index.
                                 */
                                patch->fragments = NULL;
-                               size = 0;
                        }
-               }
-               else {
-                       size = xsize_t(st->st_size);
-                       alloc = size + 8192;
-                       buf = xmalloc(alloc);
-                       if (read_old_data(st, patch->old_name,
-                                         &buf, &alloc, &size))
-                               return error("read of %s failed",
-                                            patch->old_name);
+               } else {
+                       if (read_old_data(st, patch->old_name, &buf))
+                               return error("read of %s failed", patch->old_name);
                }
        }
 
-       desc.size = size;
-       desc.alloc = alloc;
-       desc.buffer = buf;
-
-       if (apply_fragments(&desc, patch) < 0)
+       if (apply_fragments(&buf, patch) < 0)
                return -1; /* note with --reject this succeeds. */
-
-       /* NUL terminate the result */
-       if (desc.alloc <= desc.size)
-               desc.buffer = xrealloc(desc.buffer, desc.size + 1);
-       desc.buffer[desc.size] = 0;
-
-       patch->result = desc.buffer;
-       patch->resultsize = desc.size;
+       patch->result = strbuf_detach(&buf, &patch->resultsize);
 
        if (0 < patch->is_delete && patch->resultsize)
                return error("removal patch leaves file contents");
@@ -2315,13 +2208,8 @@ static void numstat_patch_list(struct patch *patch)
                if (patch->is_binary)
                        printf("-\t-\t");
                else
-                       printf("%d\t%d\t",
-                              patch->lines_added, patch->lines_deleted);
-               if (line_termination && quote_c_style(name, NULL, NULL, 0))
-                       quote_c_style(name, NULL, stdout, 0);
-               else
-                       fputs(name, stdout);
-               putchar(line_termination);
+                       printf("%d\t%d\t", patch->lines_added, patch->lines_deleted);
+               write_name_quoted(name, stdout, line_termination);
        }
 }
 
@@ -2430,7 +2318,6 @@ static void remove_file(struct patch *patch, int rmdir_empty)
        if (update_index) {
                if (remove_file_from_cache(patch->old_name) < 0)
                        die("unable to remove %s from index", patch->old_name);
-               cache_tree_invalidate_path(active_cache_tree, patch->old_name);
        }
        if (!cached) {
                if (S_ISGITLINK(patch->old_mode)) {
@@ -2487,7 +2374,7 @@ static void add_index_file(const char *path, unsigned mode, void *buf, unsigned
 static int try_create_file(const char *path, unsigned int mode, const char *buf, unsigned long size)
 {
        int fd;
-       char *nbuf;
+       struct strbuf nbuf;
 
        if (S_ISGITLINK(mode)) {
                struct stat st;
@@ -2506,23 +2393,16 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf,
        if (fd < 0)
                return -1;
 
-       nbuf = convert_to_working_tree(path, buf, &size);
-       if (nbuf)
-               buf = nbuf;
-
-       while (size) {
-               int written = xwrite(fd, buf, size);
-               if (written < 0)
-                       die("writing file %s: %s", path, strerror(errno));
-               if (!written)
-                       die("out of space writing file %s", path);
-               buf += written;
-               size -= written;
+       strbuf_init(&nbuf, 0);
+       if (convert_to_working_tree(path, buf, size, &nbuf)) {
+               size = nbuf.len;
+               buf  = nbuf.buf;
        }
+       write_or_die(fd, buf, size);
+       strbuf_release(&nbuf);
+
        if (close(fd) < 0)
                die("closing file %s: %s", path, strerror(errno));
-       if (nbuf)
-               free(nbuf);
        return 0;
 }
 
@@ -2585,7 +2465,6 @@ static void create_file(struct patch *patch)
                mode = S_IFREG | 0644;
        create_one_file(path, mode, buf, size);
        add_index_file(path, mode, buf, size);
-       cache_tree_invalidate_path(active_cache_tree, path);
 }
 
 /* phase zero is to remove, phase one is to create */
@@ -2756,22 +2635,22 @@ static void prefix_patches(struct patch *p)
 
 static int apply_patch(int fd, const char *filename, int inaccurate_eof)
 {
-       unsigned long offset, size;
-       char *buffer = read_patch_file(fd, &size);
+       size_t offset;
+       struct strbuf buf;
        struct patch *list = NULL, **listp = &list;
        int skipped_patch = 0;
 
+       strbuf_init(&buf, 0);
        patch_input_file = filename;
-       if (!buffer)
-               return -1;
+       read_patch_file(&buf, fd);
        offset = 0;
-       while (size > 0) {
+       while (offset < buf.len) {
                struct patch *patch;
                int nr;
 
                patch = xcalloc(1, sizeof(*patch));
                patch->inaccurate_eof = inaccurate_eof;
-               nr = parse_chunk(buffer + offset, size, patch);
+               nr = parse_chunk(buf.buf + offset, buf.len - offset, patch);
                if (nr < 0)
                        break;
                if (apply_in_reverse)
@@ -2789,7 +2668,6 @@ static int apply_patch(int fd, const char *filename, int inaccurate_eof)
                        skipped_patch++;
                }
                offset += nr;
-               size -= nr;
        }
 
        if (whitespace_error && (new_whitespace == error_on_whitespace))
@@ -2824,7 +2702,7 @@ static int apply_patch(int fd, const char *filename, int inaccurate_eof)
        if (summary)
                summary_patch_list(list);
 
-       free(buffer);
+       strbuf_release(&buf);
        return 0;
 }
 
index 187491b..14a1b30 100644 (file)
@@ -10,6 +10,7 @@
 #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...]";
@@ -29,7 +30,7 @@ static int run_remote_archiver(const char *remote, int argc,
 {
        char *url, buf[LARGE_PACKET_MAX];
        int fd[2], i, len, rv;
-       pid_t pid;
+       struct child_process *conn;
        const char *exec = "git-upload-archive";
        int exec_at = 0;
 
@@ -45,9 +46,7 @@ static int run_remote_archiver(const char *remote, int argc,
        }
 
        url = xstrdup(remote);
-       pid = git_connect(fd, url, exec, 0);
-       if (pid < 0)
-               return pid;
+       conn = git_connect(fd, url, exec, 0);
 
        for (i = 1; i < argc; i++) {
                if (i == exec_at)
@@ -75,11 +74,91 @@ static int run_remote_archiver(const char *remote, int argc,
        rv = recv_sideband("archive", fd[0], 1, 2);
        close(fd[0]);
        close(fd[1]);
-       rv |= finish_connect(pid);
+       rv |= finish_connect(conn);
 
        return !!rv;
 }
 
+static void format_subst(const struct commit *commit,
+                         const char *src, size_t len,
+                         struct strbuf *buf)
+{
+       char *to_free = NULL;
+       struct strbuf fmt;
+
+       if (src == buf->buf)
+               to_free = strbuf_detach(buf, NULL);
+       strbuf_init(&fmt, 0);
+       for (;;) {
+               const char *b, *c;
+
+               b = memmem(src, len, "$Format:", 8);
+               if (!b || src + len < b + 9)
+                       break;
+               c = memchr(b + 8, '$', len - 8);
+               if (!c)
+                       break;
+
+               strbuf_reset(&fmt);
+               strbuf_add(&fmt, b + 8, c - b - 8);
+
+               strbuf_add(buf, src, b - src);
+               format_commit_message(commit, fmt.buf, buf);
+               len -= c + 1 - src;
+               src  = c + 1;
+       }
+       strbuf_add(buf, src, len);
+       strbuf_release(&fmt);
+       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)
+{
+       void *buffer;
+
+       buffer = read_sha1_file(sha1, type, sizep);
+       if (buffer && S_ISREG(mode)) {
+               struct strbuf buf;
+               size_t size = 0;
+
+               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);
+               buffer = strbuf_detach(&buf, &size);
+               *sizep = size;
+       }
+
+       return buffer;
+}
+
 static int init_archiver(const char *name, struct archiver *ar)
 {
        int rv = -1, i;
@@ -109,7 +188,7 @@ void parse_treeish_arg(const char **argv, struct archiver_args *ar_args,
        const unsigned char *commit_sha1;
        time_t archive_time;
        struct tree *tree;
-       struct commit *commit;
+       const struct commit *commit;
        unsigned char sha1[20];
 
        if (get_sha1(name, sha1))
@@ -142,6 +221,7 @@ void parse_treeish_arg(const char **argv, struct archiver_args *ar_args,
        }
        ar_args->tree = tree;
        ar_args->commit_sha1 = commit_sha1;
+       ar_args->commit = commit;
        ar_args->time = archive_time;
 }
 
index e17b03d..c158d31 100644 (file)
@@ -335,7 +335,7 @@ static struct origin *find_origin(struct scoreboard *sb,
         * same and diff-tree is fairly efficient about this.
         */
        diff_setup(&diff_opts);
-       diff_opts.recursive = 1;
+       DIFF_OPT_SET(&diff_opts, RECURSIVE);
        diff_opts.detect_rename = 0;
        diff_opts.output_format = DIFF_FORMAT_NO_OUTPUT;
        paths[0] = origin->path;
@@ -409,7 +409,7 @@ static struct origin *find_rename(struct scoreboard *sb,
        const char *paths[2];
 
        diff_setup(&diff_opts);
-       diff_opts.recursive = 1;
+       DIFF_OPT_SET(&diff_opts, RECURSIVE);
        diff_opts.detect_rename = DIFF_DETECT_RENAME;
        diff_opts.output_format = DIFF_FORMAT_NO_OUTPUT;
        diff_opts.single_follow = origin->path;
@@ -1075,7 +1075,7 @@ static int find_copy_in_parent(struct scoreboard *sb,
                return 1; /* nothing remains for this target */
 
        diff_setup(&diff_opts);
-       diff_opts.recursive = 1;
+       DIFF_OPT_SET(&diff_opts, RECURSIVE);
        diff_opts.output_format = DIFF_FORMAT_NO_OUTPUT;
 
        paths[0] = NULL;
@@ -1093,7 +1093,7 @@ static int find_copy_in_parent(struct scoreboard *sb,
        if ((opt & PICKAXE_BLAME_COPY_HARDEST)
            || ((opt & PICKAXE_BLAME_COPY_HARDER)
                && (!porigin || strcmp(target->path, porigin->path))))
-               diff_opts.find_copies_harder = 1;
+               DIFF_OPT_SET(&diff_opts, FIND_COPIES_HARDER);
 
        if (is_null_sha1(target->commit->object.sha1))
                do_diff_cache(parent->tree->object.sha1, &diff_opts);
@@ -1102,7 +1102,7 @@ static int find_copy_in_parent(struct scoreboard *sb,
                               target->commit->tree->object.sha1,
                               "", &diff_opts);
 
-       if (!diff_opts.find_copies_harder)
+       if (!DIFF_OPT_TST(&diff_opts, FIND_COPIES_HARDER))
                diffcore_std(&diff_opts);
 
        retval = 0;
@@ -1430,8 +1430,7 @@ static void get_commit_info(struct commit *commit,
 static void write_filename_info(const char *path)
 {
        printf("filename ");
-       write_name_quoted(NULL, 0, path, 1, stdout);
-       putchar('\n');
+       write_name_quoted(path, stdout, '\n');
 }
 
 /*
@@ -2001,11 +2000,9 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
        struct commit *commit;
        struct origin *origin;
        unsigned char head_sha1[20];
-       char *buf;
+       struct strbuf buf;
        const char *ident;
-       int fd;
        time_t now;
-       unsigned long fin_size;
        int size, len;
        struct cache_entry *ce;
        unsigned mode;
@@ -2023,9 +2020,11 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
 
        origin = make_origin(commit, path);
 
+       strbuf_init(&buf, 0);
        if (!contents_from || strcmp("-", contents_from)) {
                struct stat st;
                const char *read_from;
+               unsigned long fin_size;
 
                if (contents_from) {
                        if (stat(contents_from, &st) < 0)
@@ -2038,19 +2037,16 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
                        read_from = path;
                }
                fin_size = xsize_t(st.st_size);
-               buf = xmalloc(fin_size+1);
                mode = canon_mode(st.st_mode);
                switch (st.st_mode & S_IFMT) {
                case S_IFREG:
-                       fd = open(read_from, O_RDONLY);
-                       if (fd < 0)
-                               die("cannot open %s", read_from);
-                       if (read_in_full(fd, buf, fin_size) != fin_size)
-                               die("cannot read %s", read_from);
+                       if (strbuf_read_file(&buf, read_from, st.st_size) != st.st_size)
+                               die("cannot open or read %s", read_from);
                        break;
                case S_IFLNK:
-                       if (readlink(read_from, buf, fin_size+1) != fin_size)
+                       if (readlink(read_from, buf.buf, buf.alloc) != fin_size)
                                die("cannot readlink %s", read_from);
+                       buf.len = fin_size;
                        break;
                default:
                        die("unsupported file type %s", read_from);
@@ -2059,26 +2055,14 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
        else {
                /* Reading from stdin */
                contents_from = "standard input";
-               buf = NULL;
-               fin_size = 0;
                mode = 0;
-               while (1) {
-                       ssize_t cnt = 8192;
-                       buf = xrealloc(buf, fin_size + cnt);
-                       cnt = xread(0, buf + fin_size, cnt);
-                       if (cnt < 0)
-                               die("read error %s from stdin",
-                                   strerror(errno));
-                       if (!cnt)
-                               break;
-                       fin_size += cnt;
-               }
-               buf = xrealloc(buf, fin_size + 1);
+               if (strbuf_read(&buf, 0, 0) < 0)
+                       die("read error %s from stdin", strerror(errno));
        }
-       buf[fin_size] = 0;
-       origin->file.ptr = buf;
-       origin->file.size = fin_size;
-       pretend_sha1_file(buf, fin_size, OBJ_BLOB, origin->blob_sha1);
+       convert_to_git(path, buf.buf, buf.len, &buf);
+       origin->file.ptr = buf.buf;
+       origin->file.size = buf.len;
+       pretend_sha1_file(buf.buf, buf.len, OBJ_BLOB, origin->blob_sha1);
        commit->util = origin;
 
        /*
@@ -2311,6 +2295,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
                        else if (i != argc - 1)
                                usage(blame_usage); /* garbage at end */
 
+                       setup_work_tree();
                        if (!has_path_in_work_tree(path))
                                die("cannot stat path %s: %s",
                                    path, strerror(errno));
@@ -2358,6 +2343,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
                 * do not default to HEAD, but use the working tree
                 * or "--contents".
                 */
+               setup_work_tree();
                sb.final = fake_working_tree_commit(path, contents_from);
                add_pending_object(&revs, &(sb.final->object), ":");
        }
index c1e9a61..2694c9c 100644 (file)
 #include "commit.h"
 #include "builtin.h"
 #include "remote.h"
-
-static const char builtin_branch_usage[] =
-  "git-branch [-r] (-d | -D) <branchname> | [--track | --no-track] [-l] [-f] <branchname> [<start-point>] | (-m | -M) [<oldbranch>] <newbranch> | [--color | --no-color] [-r | -a] [-v [--abbrev=<length> | --no-abbrev]]";
+#include "parse-options.h"
+
+static const char * const builtin_branch_usage[] = {
+       "git-branch [options] [-r | -a]",
+       "git-branch [options] [-l] [-f] <branchname> [<start-point>]",
+       "git-branch [options] [-r] (-d | -D) <branchname>",
+       "git-branch [options] (-m | -M) [<oldbranch>] <newbranch>",
+       NULL
+};
 
 #define REF_UNKNOWN_TYPE    0x00
 #define REF_LOCAL_BRANCH    0x01
@@ -142,7 +148,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)
 
                if (!force &&
                    !in_merge_bases(rev, &head_rev, 1)) {
-                       error("The branch '%s' is not a strict subset of "
+                       error("The branch '%s' is not an ancestor of "
                                "your current HEAD.\n"
                                "If you are sure you want to delete it, "
                                "run 'git branch -D %s'.", argv[i], argv[i]);
@@ -268,23 +274,22 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
        }
 
        if (verbose) {
-               char *subject = NULL;
-               unsigned long subject_len = 0;
+               struct strbuf subject;
                const char *sub = " **** invalid ref ****";
 
+               strbuf_init(&subject, 0);
+
                commit = lookup_commit(item->sha1);
                if (commit && !parse_commit(commit)) {
-                       pretty_print_commit(CMIT_FMT_ONELINE, commit, ~0,
-                                           &subject, &subject_len, 0,
-                                           NULL, NULL, 0, 0);
-                       sub = subject;
+                       pretty_print_commit(CMIT_FMT_ONELINE, commit,
+                                           &subject, 0, NULL, NULL, 0, 0);
+                       sub = subject.buf;
                }
                printf("%c %s%-*s%s %s %s\n", c, branch_get_color(color),
                       maxwidth, item->name,
                       branch_get_color(COLOR_BRANCH_RESET),
                       find_unique_abbrev(item->sha1, abbrev), sub);
-               if (subject)
-                       free(subject);
+               strbuf_release(&subject);
        } else {
                printf("%c %s%s%s\n", c, branch_get_color(color), item->name,
                       branch_get_color(COLOR_BRANCH_RESET));
@@ -502,97 +507,37 @@ static void rename_branch(const char *oldname, const char *newname, int force)
 
 int cmd_branch(int argc, const char **argv, const char *prefix)
 {
-       int delete = 0, force_delete = 0, force_create = 0;
-       int rename = 0, force_rename = 0;
+       int delete = 0, rename = 0, force_create = 0;
        int verbose = 0, abbrev = DEFAULT_ABBREV, detached = 0;
        int reflog = 0, track;
        int kinds = REF_LOCAL_BRANCH;
-       int i;
+
+       struct option options[] = {
+               OPT_GROUP("Generic options"),
+               OPT__VERBOSE(&verbose),
+               OPT_BOOLEAN( 0 , "track",  &track, "set up tracking mode (see git-pull(1))"),
+               OPT_BOOLEAN( 0 , "color",  &branch_use_color, "use colored output"),
+               OPT_SET_INT('r', NULL,     &kinds, "act on remote-tracking branches",
+                       REF_REMOTE_BRANCH),
+               OPT__ABBREV(&abbrev),
+
+               OPT_GROUP("Specific git-branch actions:"),
+               OPT_SET_INT('a', NULL, &kinds, "list both remote-tracking and local branches",
+                       REF_REMOTE_BRANCH | REF_LOCAL_BRANCH),
+               OPT_BIT('d', NULL, &delete, "delete fully merged branch", 1),
+               OPT_BIT('D', NULL, &delete, "delete branch (even if not merged)", 2),
+               OPT_BIT('m', NULL, &rename, "move/rename a branch and its reflog", 1),
+               OPT_BIT('M', NULL, &rename, "move/rename a branch, even if target exists", 2),
+               OPT_BOOLEAN('l', NULL, &reflog, "create the branch's reflog"),
+               OPT_BOOLEAN('f', NULL, &force_create, "force creation (when already exists)"),
+               OPT_END(),
+       };
 
        git_config(git_branch_config);
        track = branch_track;
-
-       for (i = 1; i < argc; i++) {
-               const char *arg = argv[i];
-
-               if (arg[0] != '-')
-                       break;
-               if (!strcmp(arg, "--")) {
-                       i++;
-                       break;
-               }
-               if (!strcmp(arg, "--track")) {
-                       track = 1;
-                       continue;
-               }
-               if (!strcmp(arg, "--no-track")) {
-                       track = 0;
-                       continue;
-               }
-               if (!strcmp(arg, "-d")) {
-                       delete = 1;
-                       continue;
-               }
-               if (!strcmp(arg, "-D")) {
-                       delete = 1;
-                       force_delete = 1;
-                       continue;
-               }
-               if (!strcmp(arg, "-f")) {
-                       force_create = 1;
-                       continue;
-               }
-               if (!strcmp(arg, "-m")) {
-                       rename = 1;
-                       continue;
-               }
-               if (!strcmp(arg, "-M")) {
-                       rename = 1;
-                       force_rename = 1;
-                       continue;
-               }
-               if (!strcmp(arg, "-r")) {
-                       kinds = REF_REMOTE_BRANCH;
-                       continue;
-               }
-               if (!strcmp(arg, "-a")) {
-                       kinds = REF_REMOTE_BRANCH | REF_LOCAL_BRANCH;
-                       continue;
-               }
-               if (!strcmp(arg, "-l")) {
-                       reflog = 1;
-                       continue;
-               }
-               if (!prefixcmp(arg, "--no-abbrev")) {
-                       abbrev = 0;
-                       continue;
-               }
-               if (!prefixcmp(arg, "--abbrev=")) {
-                       abbrev = strtoul(arg + 9, NULL, 10);
-                       if (abbrev < MINIMUM_ABBREV)
-                               abbrev = MINIMUM_ABBREV;
-                       else if (abbrev > 40)
-                               abbrev = 40;
-                       continue;
-               }
-               if (!strcmp(arg, "-v")) {
-                       verbose = 1;
-                       continue;
-               }
-               if (!strcmp(arg, "--color")) {
-                       branch_use_color = 1;
-                       continue;
-               }
-               if (!strcmp(arg, "--no-color")) {
-                       branch_use_color = 0;
-                       continue;
-               }
-               usage(builtin_branch_usage);
-       }
-
-       if ((delete && rename) || (delete && force_create) ||
-           (rename && force_create))
-               usage(builtin_branch_usage);
+       argc = parse_options(argc, argv, options, builtin_branch_usage, 0);
+       if (!!delete + !!rename + !!force_create > 1)
+               usage_with_options(builtin_branch_usage, options);
 
        head = resolve_ref("HEAD", head_sha1, 0, NULL);
        if (!head)
@@ -600,26 +545,25 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
        head = xstrdup(head);
        if (!strcmp(head, "HEAD")) {
                detached = 1;
-       }
-       else {
+       } else {
                if (prefixcmp(head, "refs/heads/"))
                        die("HEAD not found below refs/heads!");
                head += 11;
        }
 
        if (delete)
-               return delete_branches(argc - i, argv + i, force_delete, kinds);
-       else if (i == argc)
+               return delete_branches(argc, argv, delete > 1, kinds);
+       else if (argc == 0)
                print_ref_list(kinds, detached, verbose, abbrev);
-       else if (rename && (i == argc - 1))
-               rename_branch(head, argv[i], force_rename);
-       else if (rename && (i == argc - 2))
-               rename_branch(argv[i], argv[i + 1], force_rename);
-       else if (i == argc - 1 || i == argc - 2)
-               create_branch(argv[i], (i == argc - 2) ? argv[i+1] : head,
+       else if (rename && (argc == 1))
+               rename_branch(head, argv[0], rename > 1);
+       else if (rename && (argc == 2))
+               rename_branch(argv[0], argv[1], rename > 1);
+       else if (argc <= 2)
+               create_branch(argv[0], (argc == 2) ? argv[1] : head,
                              force_create, reflog, track);
        else
-               usage(builtin_branch_usage);
+               usage_with_options(builtin_branch_usage, options);
 
        return 0;
 }
index d184055..9f38e21 100644 (file)
@@ -1,12 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
-#include "object.h"
-#include "commit.h"
-#include "diff.h"
-#include "revision.h"
-#include "list-objects.h"
-#include "run-command.h"
-#include "refs.h"
+#include "bundle.h"
 
 /*
  * Basic handler for bundle files to connect repositories via sneakernet.
 
 static const char *bundle_usage="git-bundle (create <bundle> <git-rev-list args> | verify <bundle> | list-heads <bundle> [refname]... | unbundle <bundle> [refname]... )";
 
-static const char bundle_signature[] = "# v2 git bundle\n";
-
-struct ref_list {
-       unsigned int nr, alloc;
-       struct ref_list_entry {
-               unsigned char sha1[20];
-               char *name;
-       } *list;
-};
-
-static void add_to_ref_list(const unsigned char *sha1, const char *name,
-               struct ref_list *list)
-{
-       if (list->nr + 1 >= list->alloc) {
-               list->alloc = alloc_nr(list->nr + 1);
-               list->list = xrealloc(list->list,
-                               list->alloc * sizeof(list->list[0]));
-       }
-       memcpy(list->list[list->nr].sha1, sha1, 20);
-       list->list[list->nr].name = xstrdup(name);
-       list->nr++;
-}
-
-struct bundle_header {
-       struct ref_list prerequisites;
-       struct ref_list references;
-};
-
-/* returns an fd */
-static int read_header(const char *path, struct bundle_header *header) {
-       char buffer[1024];
-       int fd;
-       long fpos;
-       FILE *ffd = fopen(path, "rb");
-
-       if (!ffd)
-               return error("could not open '%s'", path);
-       if (!fgets(buffer, sizeof(buffer), ffd) ||
-                       strcmp(buffer, bundle_signature)) {
-               fclose(ffd);
-               return error("'%s' does not look like a v2 bundle file", path);
-       }
-       while (fgets(buffer, sizeof(buffer), ffd)
-                       && buffer[0] != '\n') {
-               int is_prereq = buffer[0] == '-';
-               int offset = is_prereq ? 1 : 0;
-               int len = strlen(buffer);
-               unsigned char sha1[20];
-               struct ref_list *list = is_prereq ? &header->prerequisites
-                       : &header->references;
-               char delim;
-
-               if (buffer[len - 1] == '\n')
-                       buffer[len - 1] = '\0';
-               if (get_sha1_hex(buffer + offset, sha1)) {
-                       warning("unrecognized header: %s", buffer);
-                       continue;
-               }
-               delim = buffer[40 + offset];
-               if (!isspace(delim) && (delim != '\0' || !is_prereq))
-                       die ("invalid header: %s", buffer);
-               add_to_ref_list(sha1, isspace(delim) ?
-                               buffer + 41 + offset : "", list);
-       }
-       fpos = ftell(ffd);
-       fclose(ffd);
-       fd = open(path, O_RDONLY);
-       if (fd < 0)
-               return error("could not open '%s'", path);
-       lseek(fd, fpos, SEEK_SET);
-       return fd;
-}
-
-static int list_refs(struct ref_list *r, int argc, const char **argv)
-{
-       int i;
-
-       for (i = 0; i < r->nr; i++) {
-               if (argc > 1) {
-                       int j;
-                       for (j = 1; j < argc; j++)
-                               if (!strcmp(r->list[i].name, argv[j]))
-                                       break;
-                       if (j == argc)
-                               continue;
-               }
-               printf("%s %s\n", sha1_to_hex(r->list[i].sha1),
-                               r->list[i].name);
-       }
-       return 0;
-}
-
-#define PREREQ_MARK (1u<<16)
-
-static int verify_bundle(struct bundle_header *header, int verbose)
-{
-       /*
-        * Do fast check, then if any prereqs are missing then go line by line
-        * to be verbose about the errors
-        */
-       struct ref_list *p = &header->prerequisites;
-       struct rev_info revs;
-       const char *argv[] = {NULL, "--all"};
-       struct object_array refs;
-       struct commit *commit;
-       int i, ret = 0, req_nr;
-       const char *message = "Repository lacks these prerequisite commits:";
-
-       init_revisions(&revs, NULL);
-       for (i = 0; i < p->nr; i++) {
-               struct ref_list_entry *e = p->list + i;
-               struct object *o = parse_object(e->sha1);
-               if (o) {
-                       o->flags |= PREREQ_MARK;
-                       add_pending_object(&revs, o, e->name);
-                       continue;
-               }
-               if (++ret == 1)
-                       error(message);
-               error("%s %s", sha1_to_hex(e->sha1), e->name);
-       }
-       if (revs.pending.nr != p->nr)
-               return ret;
-       req_nr = revs.pending.nr;
-       setup_revisions(2, argv, &revs, NULL);
-
-       memset(&refs, 0, sizeof(struct object_array));
-       for (i = 0; i < revs.pending.nr; i++) {
-               struct object_array_entry *e = revs.pending.objects + i;
-               add_object_array(e->item, e->name, &refs);
-       }
-
-       prepare_revision_walk(&revs);
-
-       i = req_nr;
-       while (i && (commit = get_revision(&revs)))
-               if (commit->object.flags & PREREQ_MARK)
-                       i--;
-
-       for (i = 0; i < req_nr; i++)
-               if (!(refs.objects[i].item->flags & SHOWN)) {
-                       if (++ret == 1)
-                               error(message);
-                       error("%s %s", sha1_to_hex(refs.objects[i].item->sha1),
-                               refs.objects[i].name);
-               }
-
-       for (i = 0; i < refs.nr; i++)
-               clear_commit_marks((struct commit *)refs.objects[i].item, -1);
-
-       if (verbose) {
-               struct ref_list *r;
-
-               r = &header->references;
-               printf("The bundle contains %d ref%s\n",
-                      r->nr, (1 < r->nr) ? "s" : "");
-               list_refs(r, 0, NULL);
-               r = &header->prerequisites;
-               printf("The bundle requires these %d ref%s\n",
-                      r->nr, (1 < r->nr) ? "s" : "");
-               list_refs(r, 0, NULL);
-       }
-       return ret;
-}
-
-static int list_heads(struct bundle_header *header, int argc, const char **argv)
-{
-       return list_refs(&header->references, argc, argv);
-}
-
-static int create_bundle(struct bundle_header *header, const char *path,
-               int argc, const char **argv)
-{
-       static struct lock_file lock;
-       int bundle_fd = -1;
-       int bundle_to_stdout;
-       const char **argv_boundary = xmalloc((argc + 4) * sizeof(const char *));
-       const char **argv_pack = xmalloc(5 * sizeof(const char *));
-       int i, ref_count = 0;
-       char buffer[1024];
-       struct rev_info revs;
-       struct child_process rls;
-       FILE *rls_fout;
-
-       bundle_to_stdout = !strcmp(path, "-");
-       if (bundle_to_stdout)
-               bundle_fd = 1;
-       else
-               bundle_fd = hold_lock_file_for_update(&lock, path, 1);
-
-       /* write signature */
-       write_or_die(bundle_fd, bundle_signature, strlen(bundle_signature));
-
-       /* init revs to list objects for pack-objects later */
-       save_commit_buffer = 0;
-       init_revisions(&revs, NULL);
-
-       /* write prerequisites */
-       memcpy(argv_boundary + 3, argv + 1, argc * sizeof(const char *));
-       argv_boundary[0] = "rev-list";
-       argv_boundary[1] = "--boundary";
-       argv_boundary[2] = "--pretty=oneline";
-       argv_boundary[argc + 2] = NULL;
-       memset(&rls, 0, sizeof(rls));
-       rls.argv = argv_boundary;
-       rls.out = -1;
-       rls.git_cmd = 1;
-       if (start_command(&rls))
-               return -1;
-       rls_fout = fdopen(rls.out, "r");
-       while (fgets(buffer, sizeof(buffer), rls_fout)) {
-               unsigned char sha1[20];
-               if (buffer[0] == '-') {
-                       write_or_die(bundle_fd, buffer, strlen(buffer));
-                       if (!get_sha1_hex(buffer + 1, sha1)) {
-                               struct object *object = parse_object(sha1);
-                               object->flags |= UNINTERESTING;
-                               add_pending_object(&revs, object, buffer);
-                       }
-               } else if (!get_sha1_hex(buffer, sha1)) {
-                       struct object *object = parse_object(sha1);
-                       object->flags |= SHOWN;
-               }
-       }
-       fclose(rls_fout);
-       if (finish_command(&rls))
-               return error("rev-list died");
-
-       /* write references */
-       argc = setup_revisions(argc, argv, &revs, NULL);
-       if (argc > 1)
-               return error("unrecognized argument: %s'", argv[1]);
-
-       for (i = 0; i < revs.pending.nr; i++) {
-               struct object_array_entry *e = revs.pending.objects + i;
-               unsigned char sha1[20];
-               char *ref;
-               const char *display_ref;
-               int flag;
-
-               if (e->item->flags & UNINTERESTING)
-                       continue;
-               if (dwim_ref(e->name, strlen(e->name), sha1, &ref) != 1)
-                       continue;
-               if (!resolve_ref(e->name, sha1, 1, &flag))
-                       flag = 0;
-               display_ref = (flag & REF_ISSYMREF) ? e->name : ref;
-
-               /*
-                * Make sure the refs we wrote out is correct; --max-count and
-                * other limiting options could have prevented all the tips
-                * from getting output.
-                *
-                * Non commit objects such as tags and blobs do not have
-                * this issue as they are not affected by those extra
-                * constraints.
-                */
-               if (!(e->item->flags & SHOWN) && e->item->type == OBJ_COMMIT) {
-                       warning("ref '%s' is excluded by the rev-list options",
-                               e->name);
-                       free(ref);
-                       continue;
-               }
-               /*
-                * If you run "git bundle create bndl v1.0..v2.0", the
-                * name of the positive ref is "v2.0" but that is the
-                * commit that is referenced by the tag, and not the tag
-                * itself.
-                */
-               if (hashcmp(sha1, e->item->sha1)) {
-                       /*
-                        * Is this the positive end of a range expressed
-                        * in terms of a tag (e.g. v2.0 from the range
-                        * "v1.0..v2.0")?
-                        */
-                       struct commit *one = lookup_commit_reference(sha1);
-                       struct object *obj;
-
-                       if (e->item == &(one->object)) {
-                               /*
-                                * Need to include e->name as an
-                                * independent ref to the pack-objects
-                                * input, so that the tag is included
-                                * in the output; otherwise we would
-                                * end up triggering "empty bundle"
-                                * error.
-                                */
-                               obj = parse_object(sha1);
-                               obj->flags |= SHOWN;
-                               add_pending_object(&revs, obj, e->name);
-                       }
-                       free(ref);
-                       continue;
-               }
-
-               ref_count++;
-               write_or_die(bundle_fd, sha1_to_hex(e->item->sha1), 40);
-               write_or_die(bundle_fd, " ", 1);
-               write_or_die(bundle_fd, display_ref, strlen(display_ref));
-               write_or_die(bundle_fd, "\n", 1);
-               free(ref);
-       }
-       if (!ref_count)
-               die ("Refusing to create empty bundle.");
-
-       /* end header */
-       write_or_die(bundle_fd, "\n", 1);
-
-       /* write pack */
-       argv_pack[0] = "pack-objects";
-       argv_pack[1] = "--all-progress";
-       argv_pack[2] = "--stdout";
-       argv_pack[3] = "--thin";
-       argv_pack[4] = NULL;
-       memset(&rls, 0, sizeof(rls));
-       rls.argv = argv_pack;
-       rls.in = -1;
-       rls.out = bundle_fd;
-       rls.git_cmd = 1;
-       if (start_command(&rls))
-               return error("Could not spawn pack-objects");
-       for (i = 0; i < revs.pending.nr; i++) {
-               struct object *object = revs.pending.objects[i].item;
-               if (object->flags & UNINTERESTING)
-                       write(rls.in, "^", 1);
-               write(rls.in, sha1_to_hex(object->sha1), 40);
-               write(rls.in, "\n", 1);
-       }
-       if (finish_command(&rls))
-               return error ("pack-objects died");
-       close(bundle_fd);
-       if (!bundle_to_stdout)
-               commit_lock_file(&lock);
-       return 0;
-}
-
-static int unbundle(struct bundle_header *header, int bundle_fd,
-               int argc, const char **argv)
-{
-       const char *argv_index_pack[] = {"index-pack",
-               "--fix-thin", "--stdin", NULL};
-       struct child_process ip;
-
-       if (verify_bundle(header, 0))
-               return -1;
-       memset(&ip, 0, sizeof(ip));
-       ip.argv = argv_index_pack;
-       ip.in = bundle_fd;
-       ip.no_stdout = 1;
-       ip.git_cmd = 1;
-       if (run_command(&ip))
-               return error("index-pack died");
-       return list_heads(header, argc, argv);
-}
-
 int cmd_bundle(int argc, const char **argv, const char *prefix)
 {
        struct bundle_header header;
@@ -395,8 +34,8 @@ int cmd_bundle(int argc, const char **argv, const char *prefix)
        }
 
        memset(&header, 0, sizeof(header));
-       if (strcmp(cmd, "create") &&
-                       (bundle_fd = read_header(bundle_file, &header)) < 0)
+       if (strcmp(cmd, "create") && (bundle_fd =
+                               read_bundle_header(bundle_file, &header)) < 0)
                return 1;
 
        if (!strcmp(cmd, "verify")) {
@@ -408,7 +47,7 @@ int cmd_bundle(int argc, const char **argv, const char *prefix)
        }
        if (!strcmp(cmd, "list-heads")) {
                close(bundle_fd);
-               return !!list_heads(&header, argc, argv);
+               return !!list_bundle_refs(&header, argc, argv);
        }
        if (!strcmp(cmd, "create")) {
                if (nongit)
@@ -417,7 +56,8 @@ int cmd_bundle(int argc, const char **argv, const char *prefix)
        } else if (!strcmp(cmd, "unbundle")) {
                if (nongit)
                        die("Need a repository to unbundle.");
-               return !!unbundle(&header, bundle_fd, argc, argv);
+               return !!unbundle(&header, bundle_fd) ||
+                       list_bundle_refs(&header, argc, argv);
        } else
                usage(bundle_usage);
 }
index d949733..6afdfa1 100644 (file)
@@ -56,7 +56,7 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)
                        else if (ATTR_UNSET(value))
                                value = "unspecified";
 
-                       write_name_quoted("", 0, argv[i], 1, stdout);
+                       quote_c_style(argv[i], NULL, stdout, 0);
                        printf(": %s: %s\n", argv[j+1], value);
                }
        }
index 75377b9..70d619d 100644 (file)
@@ -38,7 +38,6 @@
  */
 #include "builtin.h"
 #include &quo