Merge 1.6.4.4 in
authorJunio C Hamano <gitster@pobox.com>
Wed, 16 Sep 2009 22:04:21 +0000 (15:04 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 16 Sep 2009 22:04:21 +0000 (15:04 -0700)
Signed-off-by: Junio C Hamano <gitster@pobox.com>
269 files changed:
.gitignore
.mailmap
Documentation/RelNotes-1.6.5.txt [new file with mode: 0644]
Documentation/config.txt
Documentation/git-add.txt
Documentation/git-am.txt
Documentation/git-apply.txt
Documentation/git-archive.txt
Documentation/git-branch.txt
Documentation/git-checkout.txt
Documentation/git-clean.txt
Documentation/git-clone.txt
Documentation/git-commit.txt
Documentation/git-fast-export.txt
Documentation/git-grep.txt
Documentation/git-init-db.txt
Documentation/git-init.txt
Documentation/git-instaweb.txt
Documentation/git-ls-files.txt
Documentation/git-mailinfo.txt
Documentation/git-merge-base.txt
Documentation/git-mv.txt
Documentation/git-prune-packed.txt
Documentation/git-push.txt
Documentation/git-quiltimport.txt
Documentation/git-read-tree.txt
Documentation/git-rebase.txt
Documentation/git-remote-helpers.txt [new file with mode: 0644]
Documentation/git-replace.txt [new file with mode: 0644]
Documentation/git-reset.txt
Documentation/git-rev-list.txt
Documentation/git-send-email.txt
Documentation/git-show-branch.txt
Documentation/git-stash.txt
Documentation/git-submodule.txt
Documentation/git-svn.txt
Documentation/git-tag.txt
Documentation/git-upload-pack.txt
Documentation/git-verify-pack.txt
Documentation/githooks.txt
Documentation/pt_BR/gittutorial.txt [new file with mode: 0644]
Documentation/technical/api-run-command.txt
Documentation/technical/api-tree-walking.txt
Documentation/urls.txt
GIT-VERSION-GEN
INSTALL
Makefile
RelNotes
abspath.c
advice.c [new file with mode: 0644]
advice.h [new file with mode: 0644]
archive.c
arm/sha1.c [deleted file]
arm/sha1.h [deleted file]
arm/sha1_arm.S [deleted file]
block-sha1/sha1.c [new file with mode: 0644]
block-sha1/sha1.h [new file with mode: 0644]
builtin-add.c
builtin-apply.c
builtin-archive.c
builtin-blame.c
builtin-branch.c
builtin-checkout.c
builtin-clean.c
builtin-clone.c
builtin-commit.c
builtin-describe.c
builtin-diff.c
builtin-fast-export.c
builtin-fetch.c
builtin-for-each-ref.c
builtin-fsck.c
builtin-grep.c
builtin-init-db.c
builtin-log.c
builtin-mailinfo.c
builtin-mailsplit.c
builtin-merge-base.c
builtin-merge.c
builtin-mv.c
builtin-pack-objects.c
builtin-prune-packed.c
builtin-prune.c
builtin-push.c
builtin-read-tree.c
builtin-receive-pack.c
builtin-reflog.c
builtin-remote.c
builtin-replace.c [new file with mode: 0644]
builtin-reset.c
builtin-send-pack.c
builtin-shortlog.c
builtin-show-branch.c
builtin-tag.c
builtin-unpack-objects.c
builtin-update-server-info.c [new file with mode: 0644]
builtin-verify-pack.c
builtin-verify-tag.c
builtin-write-tree.c
builtin.h
bundle.c
cache.h
commit.c
commit.h
compat/bswap.h [new file with mode: 0644]
compat/mingw.c
compat/mingw.h
compat/snprintf.c
config.c
configure.ac
connect.c
contrib/completion/git-completion.bash
contrib/emacs/git.el
contrib/fast-import/git-p4
contrib/fast-import/import-directories.perl [new file with mode: 0755]
contrib/fast-import/import-tars.perl
convert.c
copy.c
date.c
diff-delta.c
diff-lib.c
diff.c
environment.c
git-add--interactive.perl
git-am.sh
git-compat-util.h
git-cvsimport.perl
git-instaweb.sh
git-pull.sh
git-rebase.sh
git-request-pull.sh
git-stash.sh
git-submodule.sh
git-svn.perl
git-web--browse.sh
git.c
git.spec.in
gitk-git/gitk
gitweb/INSTALL
gitweb/git-favicon.png
gitweb/git-logo.png
gitweb/gitweb.css
gitweb/gitweb.perl
graph.c
grep.h
http-fetch.c [moved from builtin-http-fetch.c with 95% similarity]
http.c
ll-merge.c
merge-recursive.c
mktag.c
mozilla-sha1/sha1.c [deleted file]
mozilla-sha1/sha1.h [deleted file]
object.c
pack-redundant.c
pager.c
parse-options.c
parse-options.h
patch-delta.c
progress.c
read-cache.c
refs.c
refs.h
remote-curl.c [new file with mode: 0644]
remote.c
replace_object.c [new file with mode: 0644]
rerere.c
revision.c
revision.h
run-command.c
run-command.h
send-pack.h
sha1_file.c
strbuf.c
strbuf.h
t/Makefile
t/gitweb-lib.sh [new file with mode: 0644]
t/lib-cvs.sh [new file with mode: 0644]
t/lib-git-svn.sh
t/lib-patch-mode.sh [new file with mode: 0755]
t/t0001-init.sh
t/t0006-date.sh [new file with mode: 0755]
t/t1009-read-tree-new-index.sh [new file with mode: 0755]
t/t2016-checkout-patch.sh [new file with mode: 0755]
t/t3400-rebase.sh
t/t3404-rebase-interactive.sh
t/t3411-rebase-preserve-around-merges.sh
t/t3414-rebase-preserve-onto.sh
t/t3903-stash.sh
t/t3904-stash-patch.sh [new file with mode: 0755]
t/t4014-format-patch.sh
t/t4020-diff-external.sh
t/t4039-diff-assume-unchanged.sh [new file with mode: 0755]
t/t4107-apply-ignore-whitespace.sh [new file with mode: 0755]
t/t5100-mailinfo.sh
t/t5100/info0014 [new file with mode: 0644]
t/t5100/info0014--scissors [new file with mode: 0644]
t/t5100/msg0014 [new file with mode: 0644]
t/t5100/msg0014--scissors [new file with mode: 0644]
t/t5100/patch0014 [new file with mode: 0644]
t/t5100/patch0014--scissors [new file with mode: 0644]
t/t5100/sample.mbox
t/t5304-prune.sh
t/t5500-fetch-pack.sh
t/t5501-post-upload-pack.sh [new file with mode: 0755]
t/t5516-fetch-push.sh
t/t5520-pull.sh
t/t5530-upload-pack-error.sh
t/t5706-clone-branch.sh [new file with mode: 0755]
t/t6010-merge-base.sh
t/t6015-rev-list-show-all-parents.sh [new file with mode: 0755]
t/t6016-rev-list-graph-simplify-history.sh [new file with mode: 0755]
t/t6020-merge-df.sh
t/t6050-replace.sh [new file with mode: 0755]
t/t7002-grep.sh
t/t7060-wtstatus.sh [new file with mode: 0755]
t/t7102-reset.sh
t/t7105-reset-patch.sh [new file with mode: 0755]
t/t7401-submodule-summary.sh
t/t7407-submodule-foreach.sh [new file with mode: 0755]
t/t7408-submodule-reference.sh [moved from t/t7406-submodule-reference.sh with 100% similarity]
t/t9101-git-svn-props.sh
t/t9104-git-svn-follow-parent.sh
t/t9107-git-svn-migrate.sh
t/t9120-git-svn-clone-with-percent-escapes.sh
t/t9135-git-svn-moved-branch-empty-file.sh
t/t9143-git-svn-gc.sh
t/t9144-git-svn-old-rev_map.sh [new file with mode: 0755]
t/t9145-git-svn-master-branch.sh [new file with mode: 0755]
t/t9500-gitweb-standalone-no-errors.sh
t/t9501-gitweb-standalone-http-status.sh [new file with mode: 0644]
t/t9600-cvsimport.sh
t/t9601-cvsimport-vendor-branch.sh [new file with mode: 0755]
t/t9601/cvsroot/.gitattributes [new file with mode: 0644]
t/t9601/cvsroot/CVSROOT/.gitignore [new file with mode: 0644]
t/t9601/cvsroot/module/added-imported.txt,v [new file with mode: 0644]
t/t9601/cvsroot/module/imported-anonymously.txt,v [new file with mode: 0644]
t/t9601/cvsroot/module/imported-modified-imported.txt,v [new file with mode: 0644]
t/t9601/cvsroot/module/imported-modified.txt,v [new file with mode: 0644]
t/t9601/cvsroot/module/imported-once.txt,v [new file with mode: 0644]
t/t9601/cvsroot/module/imported-twice.txt,v [new file with mode: 0644]
t/t9602-cvsimport-branches-tags.sh [new file with mode: 0755]
t/t9602/README [new file with mode: 0644]
t/t9602/cvsroot/.gitattributes [new file with mode: 0644]
t/t9602/cvsroot/CVSROOT/.gitignore [new file with mode: 0644]
t/t9602/cvsroot/module/default,v [new file with mode: 0644]
t/t9602/cvsroot/module/sub1/default,v [new file with mode: 0644]
t/t9602/cvsroot/module/sub1/subsubA/default,v [new file with mode: 0644]
t/t9602/cvsroot/module/sub1/subsubB/default,v [new file with mode: 0644]
t/t9602/cvsroot/module/sub2/Attic/branch_B_MIXED_only,v [new file with mode: 0644]
t/t9602/cvsroot/module/sub2/default,v [new file with mode: 0644]
t/t9602/cvsroot/module/sub2/subsubA/default,v [new file with mode: 0644]
t/t9602/cvsroot/module/sub3/default,v [new file with mode: 0644]
t/t9603-cvsimport-patchsets.sh [new file with mode: 0755]
t/t9603/cvsroot/.gitattributes [new file with mode: 0644]
t/t9603/cvsroot/CVSROOT/.gitignore [new file with mode: 0644]
t/t9603/cvsroot/module/a,v [new file with mode: 0644]
t/t9603/cvsroot/module/b,v [new file with mode: 0644]
t/test-lib.sh
test-date.c
test-delta.c
transport-helper.c [new file with mode: 0644]
transport.c
transport.h
unpack-trees.h
update-server-info.c [deleted file]
upload-pack.c
var.c
wt-status.c
wt-status.h

index 41c0b20..47672b0 100644 (file)
@@ -104,7 +104,9 @@ git-receive-pack
 git-reflog
 git-relink
 git-remote
+git-remote-curl
 git-repack
+git-replace
 git-repo-config
 git-request-pull
 git-rerere
index 373476b..975e675 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -41,6 +41,7 @@ Michele Ballabio <barra_cuda@katamail.com>
 Nanako Shiraishi <nanako3@bluebottle.com>
 Nanako Shiraishi <nanako3@lavabit.com>
 Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
+<nico@fluxnic.net> <nico@cam.org>
 Philippe Bruhat <book@cpan.org>
 Ramsay Allan Jones <ramsay@ramsay1.demon.co.uk>
 René Scharfe <rene.scharfe@lsrfire.ath.cx>
diff --git a/Documentation/RelNotes-1.6.5.txt b/Documentation/RelNotes-1.6.5.txt
new file mode 100644 (file)
index 0000000..25529f7
--- /dev/null
@@ -0,0 +1,161 @@
+GIT v1.6.5 Release Notes
+========================
+
+In git 1.7.0, which was planned to be the release after 1.6.5, "git
+push" into a branch that is currently checked out will be refused by
+default.
+
+You can choose what should happen upon such a push by setting the
+configuration variable receive.denyCurrentBranch in the receiving
+repository.
+
+Also, "git push $there :$killed" to delete the branch $killed in a remote
+repository $there, when $killed branch is the current branch pointed at by
+its HEAD, will be refused by default.
+
+You can choose what should happen upon such a push by setting the
+configuration variable receive.denyDeleteCurrent in the receiving
+repository.
+
+To ease the transition plan, the receiving repository of such a
+push running this release will issue a big warning when the
+configuration variable is missing.  Please refer to:
+
+  http://git.or.cz/gitwiki/GitFaq#non-bare
+  http://thread.gmane.org/gmane.comp.version-control.git/107758/focus=108007
+
+for more details on the reason why this change is needed and the
+transition plan.
+
+Updates since v1.6.4
+--------------------
+
+(subsystems)
+
+ * various updates to git-svn and gitweb.
+
+(portability)
+
+ * more improvements on mingw port.
+
+ * mingw will also give FRSX as the default value for the LESS
+   environment variable when the user does not have one.
+
+(performance)
+
+ * On major platforms, the system can be compiled to use with Linus's
+   block-sha1 implementation of the SHA-1 hash algorithm, which
+   outperforms the default fallback implementation we borrowed from
+   Mozzilla.
+
+ * Unnecessary inefficiency in deepening of a shallow repository has
+   been removed.
+
+ * The "git" main binary used to link with libcurl, which then dragged
+   in a large number of external libraries.  When using basic plumbing
+   commands in scripts, this unnecessarily slowed things down.  We now
+   implement http/https/ftp transfer as a separate executable as we
+   used to.
+
+ * "git clone" run locally hardlinks or copies the files in .git/ to
+   newly created repository.  It used to give new mtime to copied files,
+   but this delayed garbage collection to trigger unnecessarily in the
+   cloned repository.  We now preserve mtime for these files to avoid
+   this issue.
+
+(usability, bells and whistles)
+
+ * Human writable date format to various options, e.g. --since=yesterday,
+   master@{2000.09.17}, are taught to infer some omitted input properly.
+
+ * A few programs gave verbose "advice" messages to help uninitiated
+   people when issuing error messages.  An infrastructure to allow
+   users to squelch them has been introduced, and a few such messages
+   can be silenced now.
+
+ * refs/replace/ hierarchy is designed to be usable as a replacement
+   of the "grafts" mechanism, with the added advantage that it can be
+   transferred across repositories.
+
+ * "git am" learned to optionally ignore whitespace differences.
+
+ * "git am" handles input e-mail files that has CRLF line endings sensibly.
+
+ * "git am" learned "--scissors" option to allow you to discard early part
+   of an incoming e-mail.
+
+ * "git checkout", "git reset" and "git stash" learned to pick and
+   choose to use selected changes you made, similar to "git add -p".
+
+ * "git clone" learned a "-b" option to pick a HEAD to check out
+   different from the remote's default branch.
+
+ * "git commit --dry-run $args" is a new recommended way to ask "what would
+   happen if I try to commit with these arguments."
+
+ * "git commit --dry-run" and "git status" shows conflicted paths in a
+   separate section to make them easier to spot during a merge.
+
+ * "git cvsimport" now supports password-protected pserver access even
+   when the password is not taken from ~/.cvspass file.
+
+ * "git fast-export" learned --no-data option that can be useful when
+   reordering commits and trees without touching the contents of
+   blobs.
+
+ * "git fast-import" has a pair of new front-end in contrib/ area.
+
+ * "git init" learned to mkdir/chdir into a directory when given an
+   extra argument (i.e. "git init this").
+
+ * "git instaweb" optionally can use mongoose as the web server.
+
+ * "git log --decorate" can optionally be told with --decorate=full to
+   give the reference name in full.
+
+ * "git merge" issued an unnecessarily scary message when it detected
+   that the merge may have to touch the path that the user has local
+   uncommitted changes to. The message has been reworded to make it
+   clear that the command aborted, without doing any harm.
+
+ * "git push" can be told to be --quiet.
+
+ * "git push" pays attention to url.$base.pushInsteadOf and uses a URL
+   that is derived from the URL used for fetching.
+
+ * informational output from "git reset" that lists the locally modified
+   paths is made consistent with that of "git checkout $another_branch".
+
+ * "git submodule" learned to give submodule name to scripts run with
+   "foreach" subcommand.
+
+ * various subcommands to "git submodule" learned --recursive option.
+
+ * "git submodule summary" learned --files option to compare the work
+   tree vs the commit bound at submodule path, instead of comparing
+   the index.
+
+ * "git upload-pack", which is the server side support for "git clone" and
+   "git fetch", can call a new post-upload-pack hook for statistics purposes.
+
+(developers)
+
+ * With GIT_TEST_OPTS="--root=/p/a/t/h", tests can be run outside the
+   source directory; using tmpfs may give faster turnaround.
+
+
+Fixes since v1.6.4
+------------------
+
+# All of the fixes in v1.6.4.X maintenance series are included in this
+# release, unless otherwise noted.
+
+# Here are fixes that this release has, but have not been backported to
+# v1.6.4.X series.
+
+--
+exec >/var/tmp/1
+O=v1.6.4.2-298-gdf01e7c
+O=v1.6.5-rc0-49-g5f2b1e6
+echo O=$(git describe master)
+git shortlog --no-merges $O..master --not maint
index 2632c51..be0b8ca 100644 (file)
@@ -113,6 +113,21 @@ For command-specific variables, you will find a more detailed description
 in the appropriate manual page. You will find a description of non-core
 porcelain configuration variables in the respective porcelain documentation.
 
+advice.*::
+       When set to 'true', display the given optional help message.
+       When set to 'false', do not display. The configuration variables
+       are:
++
+--
+       pushNonFastForward::
+               Advice shown when linkgit:git-push[1] refuses
+               non-fast-forward refs. Default: true.
+       statusHints::
+               Directions on how to stage/unstage/add shown in the
+               output of linkgit:git-status[1] and the template shown
+               when writing commit messages. Default: true.
+--
+
 core.fileMode::
        If false, the executable bit differences between the index and
        the working copy are ignored; useful on broken filesystems like FAT.
@@ -461,6 +476,14 @@ it will be treated as a shell command.  For example, defining
 executed from the top-level directory of a repository, which may
 not necessarily be the current directory.
 
+apply.ignorewhitespace::
+       When set to 'change', tells 'git-apply' to ignore changes in
+       whitespace, in the same way as the '--ignore-space-change'
+       option.
+       When set to one of: no, none, never, false tells 'git-apply' to
+       respect all whitespace differences.
+       See linkgit:git-apply[1].
+
 apply.whitespace::
        Tells 'git-apply' how to handle whitespaces, in the same way
        as the '--whitespace' option. See linkgit:git-apply[1].
@@ -1492,6 +1515,19 @@ url.<base>.insteadOf::
        never-before-seen repository on the site.  When more than one
        insteadOf strings match a given URL, the longest match is used.
 
+url.<base>.pushInsteadOf::
+       Any URL that starts with this value will not be pushed to;
+       instead, it will be rewritten to start with <base>, and the
+       resulting URL will be pushed to. In cases where some site serves
+       a large number of repositories, and serves them with multiple
+       access methods, some of which do not allow push, this feature
+       allows people to specify a pull-only URL and have git
+       automatically use an appropriate URL to push, even for a
+       never-before-seen repository on the site.  When more than one
+       pushInsteadOf strings match a given URL, the longest match is
+       used.  If a remote has an explicit pushurl, git will ignore this
+       setting for that remote.
+
 user.email::
        Your email address to be recorded in any newly created commits.
        Can be overridden by the 'GIT_AUTHOR_EMAIL', 'GIT_COMMITTER_EMAIL', and
index e67b7e8..45ebf87 100644 (file)
@@ -72,9 +72,14 @@ OPTIONS
 
 -p::
 --patch::
-       Similar to Interactive mode but the initial command loop is
-       bypassed and the 'patch' subcommand is invoked using each of
-       the specified filepatterns before exiting.
+       Interactively choose hunks of patch between the index and the
+       work tree and add them to the index. This gives the user a chance
+       to review the difference before adding modified contents to the
+       index.
+
+       This effectively runs ``add --interactive``, but bypasses the
+       initial command menu and directly jumps to `patch` subcommand.
+       See ``Interactive mode'' for details.
 
 -e, \--edit::
        Open the diff vs. the index in an editor and let the user
index 32e689b..67ad5da 100644 (file)
@@ -11,9 +11,9 @@ SYNOPSIS
 [verse]
 'git am' [--signoff] [--keep] [--utf8 | --no-utf8]
         [--3way] [--interactive] [--committer-date-is-author-date]
-        [--ignore-date]
+        [--ignore-date] [--ignore-space-change | --ignore-whitespace]
         [--whitespace=<option>] [-C<n>] [-p<n>] [--directory=<dir>]
-        [--reject] [-q | --quiet]
+        [--reject] [-q | --quiet] [--scissors | --no-scissors]
         [<mbox> | <Maildir>...]
 'git am' (--skip | --resolved | --abort)
 
@@ -39,6 +39,14 @@ OPTIONS
 --keep::
        Pass `-k` flag to 'git-mailinfo' (see linkgit:git-mailinfo[1]).
 
+-c::
+--scissors::
+       Remove everything in body before a scissors line (see
+       linkgit:git-mailinfo[1]).
+
+---no-scissors::
+       Ignore scissors lines (see linkgit:git-mailinfo[1]).
+
 -q::
 --quiet::
        Be quiet. Only print error messages.
@@ -65,6 +73,9 @@ default.   You can use `--no-utf8` to override this.
        it is supposed to apply to and we have those blobs
        available locally.
 
+--ignore-date::
+--ignore-space-change::
+--ignore-whitespace::
 --whitespace=<option>::
 -C<n>::
 -p<n>::
@@ -125,10 +136,8 @@ the commit, after stripping common prefix "[PATCH <anything>]".
 The "Subject: " line is supposed to concisely describe what the
 commit is about in one line of text.
 
-"From: " and "Subject: " lines starting the body (the rest of the
-message after the blank line terminating the RFC2822 headers)
-override the respective commit author name and title values taken
-from the headers.
+"From: " and "Subject: " lines starting the body override the respective
+commit author name and title values taken from the headers.
 
 The commit message is formed by the title taken from the
 "Subject: ", a blank line and the body of the message up to
index 735374d..5ee8c91 100644 (file)
@@ -13,6 +13,7 @@ SYNOPSIS
          [--apply] [--no-add] [--build-fake-ancestor=<file>] [-R | --reverse]
          [--allow-binary-replacement | --binary] [--reject] [-z]
          [-pNUM] [-CNUM] [--inaccurate-eof] [--recount] [--cached]
+         [--ignore-space-change | --ignore-whitespace ]
          [--whitespace=<nowarn|warn|fix|error|error-all>]
          [--exclude=PATH] [--include=PATH] [--directory=<root>]
          [--verbose] [<patch>...]
@@ -149,6 +150,14 @@ patch to each path is used.  A patch to a path that does not match any
 include/exclude pattern is used by default if there is no include pattern
 on the command line, and ignored if there is any include pattern.
 
+--ignore-space-change::
+--ignore-whitespace::
+       When applying a patch, ignore changes in whitespace in context
+       lines if necessary.
+       Context lines will preserve their whitespace, and they will not
+       undergo whitespace fixing regardless of the value of the
+       `--whitespace` option. New lines will still be fixed, though.
+
 --whitespace=<action>::
        When applying a patch, detect a new or modified line that has
        whitespace errors.  What are considered whitespace errors is
@@ -205,6 +214,10 @@ running `git apply --directory=modules/git-gui`.
 Configuration
 -------------
 
+apply.ignorewhitespace::
+       Set to 'change' if you want changes in whitespace to be ignored by default.
+       Set to one of: no, none, never, false if you want changes in
+       whitespace to be significant.
 apply.whitespace::
        When no `--whitespace` flag is given from the command
        line, this configuration item is used as the default.
index 92444dd..3d1c1e7 100644 (file)
@@ -10,7 +10,7 @@ SYNOPSIS
 --------
 [verse]
 'git archive' [--format=<fmt>] [--list] [--prefix=<prefix>/] [<extra>]
-             [--output=<file>] [--worktree-attributes]
+             [-o | --output=<file>] [--worktree-attributes]
              [--remote=<repo> [--exec=<git-upload-archive>]] <tree-ish>
              [path...]
 
@@ -34,8 +34,11 @@ OPTIONS
 -------
 
 --format=<fmt>::
-       Format of the resulting archive: 'tar' or 'zip'.  The default
-       is 'tar'.
+       Format of the resulting archive: 'tar' or 'zip'. If this option
+       is not given, and the output file is specified, the format is
+       inferred from the filename if possible (e.g. writing to "foo.zip"
+       makes the output to be in the zip format). Otherwise the output
+       format is `tar`.
 
 -l::
 --list::
@@ -48,6 +51,7 @@ OPTIONS
 --prefix=<prefix>/::
        Prepend <prefix>/ to each filename in the archive.
 
+-o <file>::
 --output=<file>::
        Write the archive to <file> instead of stdout.
 
@@ -129,6 +133,12 @@ git archive --format=zip --prefix=git-docs/ HEAD:Documentation/ > git-1.4.0-docs
        Put everything in the current head's Documentation/ directory
        into 'git-1.4.0-docs.zip', with the prefix 'git-docs/'.
 
+git archive -o latest.zip HEAD::
+
+       Create a Zip archive that contains the contents of the latest
+       commit on the current branch. Note that the output format is
+       inferred by the extension of the output file.
+
 
 SEE ALSO
 --------
index ae201de..aad71dc 100644 (file)
@@ -76,6 +76,7 @@ OPTIONS
        based sha1 expressions such as "<branchname>@\{yesterday}".
 
 -f::
+--force::
        Reset <branchname> to <startpoint> if <branchname> exists
        already. Without `-f` 'git-branch' refuses to change an existing branch.
 
@@ -209,6 +210,12 @@ but different purposes:
 - `--no-merged` is used to find branches which are candidates for merging
   into HEAD, since those branches are not fully contained by HEAD.
 
+SEE ALSO
+--------
+linkgit:git-check-ref-format[1],
+linkgit:git-fetch[1],
+linkgit:git-remote[1].
+
 Author
 ------
 Written by Linus Torvalds <torvalds@osdl.org> and Junio C Hamano <gitster@pobox.com>
index ad4b31e..37c1810 100644 (file)
@@ -11,6 +11,7 @@ SYNOPSIS
 'git checkout' [-q] [-f] [-m] [<branch>]
 'git checkout' [-q] [-f] [-m] [-b <new_branch>] [<start_point>]
 'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>...
+'git checkout' --patch [<tree-ish>] [--] [<paths>...]
 
 DESCRIPTION
 -----------
@@ -25,7 +26,7 @@ use the --track or --no-track options, which will be passed to `git
 branch`.  As a convenience, --track without `-b` implies branch
 creation; see the description of --track below.
 
-When <paths> are given, this command does *not* switch
+When <paths> or --patch are given, this command does *not* switch
 branches.  It updates the named paths in the working tree from
 the index file, or from a named <tree-ish> (most often a commit).  In
 this case, the `-b` and `--track` options are meaningless and giving
@@ -45,9 +46,11 @@ file can be discarded to recreate the original conflicted merge result.
 OPTIONS
 -------
 -q::
+--quiet::
        Quiet, suppress feedback messages.
 
 -f::
+--force::
        When switching branches, proceed even if the index or the
        working tree differs from HEAD.  This is used to throw away
        local changes.
@@ -113,6 +116,16 @@ the conflicted merge in the specified paths.
        "merge" (default) and "diff3" (in addition to what is shown by
        "merge" style, shows the original contents).
 
+-p::
+--patch::
+       Interactively select hunks in the difference between the
+       <tree-ish> (or the index, if unspecified) and the working
+       tree.  The chosen hunks are then applied in reverse to the
+       working tree (and if a <tree-ish> was specified, the index).
++
+This means that you can use `git checkout -p` to selectively discard
+edits from your current working tree.
+
 <branch>::
        Branch to checkout; if it refers to a branch (i.e., a name that,
        when prepended with "refs/heads/", is a valid ref), then that
index ae8938b..9d291bd 100644 (file)
@@ -32,6 +32,7 @@ OPTIONS
        if you really want to remove such a directory.
 
 -f::
+--force::
        If the git configuration specifies clean.requireForce as true,
        'git-clean' will refuse to run unless given -f or -n.
 
index 1709a2d..aacf4fd 100644 (file)
@@ -12,7 +12,7 @@ SYNOPSIS
 'git clone' [--template=<template_directory>]
          [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror]
          [-o <name>] [-u <upload-pack>] [--reference <repository>]
-         [--depth <depth>] [--] <repository> [<directory>]
+         [--depth <depth>] [--recursive] [--] <repository> [<directory>]
 
 DESCRIPTION
 -----------
@@ -127,6 +127,13 @@ objects from the source repository into a pack in the cloned repository.
        Instead of using the remote name 'origin' to keep track
        of the upstream repository, use <name>.
 
+--branch <name>::
+-b <name>::
+       Instead of pointing the newly created HEAD to the branch pointed
+       to by the cloned repository's HEAD, point to <name> branch
+       instead. In a non-bare repository, this is the branch that will
+       be checked out.
+
 --upload-pack <upload-pack>::
 -u <upload-pack>::
        When given, and the repository to clone from is accessed
@@ -147,6 +154,14 @@ objects from the source repository into a pack in the cloned repository.
        with a long history, and would want to send in fixes
        as patches.
 
+--recursive::
+       After the clone is created, initialize all submodules within,
+       using their default settings. This is equivalent to running
+       'git submodule update --init --recursive' immediately after
+       the clone is finished. This option is ignored if the cloned
+       repository does not have a worktree/checkout (i.e. if any of
+       `--no-checkout`/`-n`, `--bare`, or `--mirror` is given)
+
 <repository>::
        The (possibly remote) repository to clone from.  See the
        <<URLS,URLS>> section below for more information on specifying
index b5d81be..0578a40 100644 (file)
@@ -8,7 +8,7 @@ git-commit - Record changes to the repository
 SYNOPSIS
 --------
 [verse]
-'git commit' [-a | --interactive] [-s] [-v] [-u<mode>] [--amend]
+'git commit' [-a | --interactive] [-s] [-v] [-u<mode>] [--amend] [--dry-run]
           [(-c | -C) <commit>] [-F <file> | -m <msg>]
           [--allow-empty] [--no-verify] [-e] [--author=<author>]
           [--cleanup=<mode>] [--] [[-i | -o ]<file>...]
@@ -42,10 +42,9 @@ The content to be added can be specified in several ways:
    by one which files should be part of the commit, before finalizing the
    operation.  Currently, this is done by invoking 'git-add --interactive'.
 
-The 'git-status' command can be used to obtain a
+The `--dry-run` option can be used to obtain a
 summary of what is included by any of the above for the next
-commit by giving the same set of parameters you would give to
-this command.
+commit by giving the same set of parameters (options and paths).
 
 If you make a commit and then find a mistake immediately after
 that, you can recover from it with 'git-reset'.
@@ -198,6 +197,11 @@ specified.
 --quiet::
        Suppress commit summary message.
 
+--dry-run::
+       Do not create a commit, but show a list of paths that are
+       to be committed, paths with local changes that will be left
+       uncommitted and paths that are untracked.
+
 \--::
        Do not interpret any more arguments as options.
 
index af2328d..75b06f3 100644 (file)
@@ -82,6 +82,14 @@ marks the same across runs.
        allow that.  So fake a tagger to be able to fast-import the
        output.
 
+--no-data::
+       Skip output of blob objects and instead refer to blobs via
+       their original SHA-1 hash.  This is useful when rewriting the
+       directory structure or history of a repository without
+       touching the contents of individual files.  Note that the
+       resulting stream can only be used by a repository which
+       already contains the necessary objects.
+
 [git-rev-list-args...]::
        A list of arguments, acceptable to 'git-rev-parse' and
        'git-rev-list', that specifies the specific objects and references
index b753c9d..8c70020 100644 (file)
@@ -17,6 +17,7 @@ SYNOPSIS
           [-l | --files-with-matches] [-L | --files-without-match]
           [-z | --null]
           [-c | --count] [--all-match]
+          [--max-depth <depth>]
           [--color | --no-color]
           [-A <post-context>] [-B <pre-context>] [-C <context>]
           [-f <file>] [-e] <pattern>
@@ -47,6 +48,10 @@ OPTIONS
 -I::
        Don't match the pattern in binary files.
 
+--max-depth <depth>::
+       For each pathspec given on command line, descend at most <depth>
+       levels of directories. A negative value means no limit.
+
 -w::
 --word-regexp::
        Match the pattern only at word boundary (either begin at the
index 1fd0ff2..eba3cb4 100644 (file)
@@ -8,7 +8,7 @@ git-init-db - Creates an empty git repository
 
 SYNOPSIS
 --------
-'git init-db' [-q | --quiet] [--template=<template_directory>] [--shared[=<permissions>]]
+'git init-db' [-q | --quiet] [--bare] [--template=<template_directory>] [--shared[=<permissions>]]
 
 
 DESCRIPTION
index 7151d12..f081b24 100644 (file)
@@ -8,7 +8,7 @@ git-init - Create an empty git repository or reinitialize an existing one
 
 SYNOPSIS
 --------
-'git init' [-q | --quiet] [--bare] [--template=<template_directory>] [--shared[=<permissions>]]
+'git init' [-q | --quiet] [--bare] [--template=<template_directory>] [--shared[=<permissions>]] [directory]
 
 
 OPTIONS
@@ -74,6 +74,9 @@ By default, the configuration flag receive.denyNonFastForwards is enabled
 in shared repositories, so that you cannot force a non fast-forwarding push
 into it.
 
+If you name a (possibly non-existent) directory at the end of the command
+line, the command is run inside the directory (possibly after creating it).
+
 --
 
 
index 22da21a..0771f25 100644 (file)
@@ -29,7 +29,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, apache2 and webrick are supported.
+       Currently apache2, lighttpd, mongoose and webrick are supported.
        (Default: lighttpd)
 
 -m::
index 057a021..021066e 100644 (file)
@@ -44,7 +44,7 @@ OPTIONS
 
 -o::
 --others::
-       Show other files in the output
+       Show other (i.e. untracked) files in the output
 
 -i::
 --ignored::
index 8d95aaa..996c3fc 100644 (file)
@@ -8,7 +8,7 @@ git-mailinfo - Extracts patch and authorship from a single e-mail message
 
 SYNOPSIS
 --------
-'git mailinfo' [-k] [-u | --encoding=<encoding> | -n] <msg> <patch>
+'git mailinfo' [-k] [-u | --encoding=<encoding> | -n] [--scissors] <msg> <patch>
 
 
 DESCRIPTION
@@ -49,6 +49,25 @@ conversion, even with this flag.
 -n::
        Disable all charset re-coding of the metadata.
 
+--scissors::
+       Remove everything in body before a scissors line.  A line that
+       mainly consists of scissors (either ">8" or "8<") and perforation
+       (dash "-") marks is called a scissors line, and is used to request
+       the reader to cut the message at that line.  If such a line
+       appears in the body of the message before the patch, everything
+       before it (including the scissors line itself) is ignored when
+       this option is used.
++
+This is useful if you want to begin your message in a discussion thread
+with comments and suggestions on the message you are responding to, and to
+conclude it with a patch submission, separating the discussion and the
+beginning of the proposed commit log message with a scissors line.
++
+This can enabled by default with the configuration option mailinfo.scissors.
+
+--no-scissors::
+       Ignore scissors lines. Useful for overriding mailinfo.scissors settings.
+
 <msg>::
        The commit log message extracted from e-mail, usually
        except the title line which comes from e-mail Subject.
index 767486c..ce5b369 100644 (file)
@@ -8,12 +8,12 @@ git-merge-base - Find as good common ancestors as possible for a merge
 
 SYNOPSIS
 --------
-'git merge-base' [--all] <commit> <commit>...
+'git merge-base' [-a|--all] <commit> <commit>...
 
 DESCRIPTION
 -----------
 
-'git-merge-base' finds best common ancestor(s) between two commits to use
+'git merge-base' finds best common ancestor(s) between two commits to use
 in a three-way merge.  One common ancestor is 'better' than another common
 ancestor if the latter is an ancestor of the former.  A common ancestor
 that does not have any better common ancestor is a 'best common
@@ -27,8 +27,13 @@ commits on the command line.  As the most common special case, specifying only
 two commits on the command line means computing the merge base between
 the given two commits.
 
+As a consequence, the 'merge base' is not necessarily contained in each of the
+commit arguments if more than two commits are specified. This is different
+from linkgit:git-show-branch[1] when used with the `--merge-base` option.
+
 OPTIONS
 -------
+-a::
 --all::
        Output all merge bases for the commits, instead of just one.
 
index 9c56602..bdcb585 100644 (file)
@@ -28,6 +28,7 @@ committed.
 OPTIONS
 -------
 -f::
+--force::
        Force renaming or moving of a file even if the target exists
 -k::
         Skip move or rename actions which would lead to an error
index b5f26ce..abfc6b6 100644 (file)
@@ -8,7 +8,7 @@ git-prune-packed - Remove extra objects that are already in pack files
 
 SYNOPSIS
 --------
-'git prune-packed' [-n] [-q]
+'git prune-packed' [-n|--dry-run] [-q|--quiet]
 
 
 DESCRIPTION
@@ -28,10 +28,12 @@ disk storage, etc.
 OPTIONS
 -------
 -n::
+--dry-run::
         Don't actually remove any objects, only show those that would have been
         removed.
 
 -q::
+--quiet::
        Squelch the progress indicator.
 
 Author
index 58d2bd5..ba6a8a2 100644 (file)
@@ -9,7 +9,7 @@ git-push - Update remote refs along with associated objects
 SYNOPSIS
 --------
 [verse]
-'git push' [--all | --mirror | --tags] [--dry-run] [--receive-pack=<git-receive-pack>]
+'git push' [--all | --mirror | --tags] [-n | --dry-run] [--receive-pack=<git-receive-pack>]
           [--repo=<repository>] [-f | --force] [-v | --verbose]
           [<repository> <refspec>...]
 
@@ -82,6 +82,7 @@ nor in any Push line of the corresponding remotes file---see below).
        if the configuration option `remote.<remote>.mirror` is
        set.
 
+-n::
 --dry-run::
        Do everything except actually send the updates.
 
index d4037de..579e8d2 100644 (file)
@@ -9,7 +9,7 @@ git-quiltimport - Applies a quilt patchset onto the current branch
 SYNOPSIS
 --------
 [verse]
-'git quiltimport' [--dry-run] [--author <author>] [--patches <dir>]
+'git quiltimport' [--dry-run | -n] [--author <author>] [--patches <dir>]
 
 
 DESCRIPTION
index 7160fa1..4a932b0 100644 (file)
@@ -8,7 +8,10 @@ git-read-tree - Reads tree information into the index
 
 SYNOPSIS
 --------
-'git read-tree' (<tree-ish> | [[-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>] [-u | -i]] [--exclude-per-directory=<gitignore>] [--index-output=<file>] <tree-ish1> [<tree-ish2> [<tree-ish3>]])
+'git read-tree' [[-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>]
+               [-u [--exclude-per-directory=<gitignore>] | -i]]
+               [--index-output=<file>]
+               <tree-ish1> [<tree-ish2> [<tree-ish3>]]
 
 
 DESCRIPTION
index db1b71d..0aefc34 100644 (file)
@@ -268,8 +268,9 @@ OPTIONS
        exit with the message "Current branch is up to date" in such a
        situation.
 
+--ignore-whitespace::
 --whitespace=<option>::
-       This flag is passed to the 'git-apply' program
+       These flag are passed to the 'git-apply' program
        (see linkgit:git-apply[1]) that applies the patch.
        Incompatible with the --interactive option.
 
diff --git a/Documentation/git-remote-helpers.txt b/Documentation/git-remote-helpers.txt
new file mode 100644 (file)
index 0000000..173ee23
--- /dev/null
@@ -0,0 +1,71 @@
+git-remote-helpers(1)
+=====================
+
+NAME
+----
+git-remote-helpers - Helper programs for interoperation with remote git
+
+SYNOPSIS
+--------
+'git remote-<transport>' <remote>
+
+DESCRIPTION
+-----------
+
+These programs are normally not used directly by end users, but are
+invoked by various git programs that interact with remote repositories
+when the repository they would operate on will be accessed using
+transport code not linked into the main git binary. Various particular
+helper programs will behave as documented here.
+
+COMMANDS
+--------
+
+Commands are given by the caller on the helper's standard input, one per line.
+
+'capabilities'::
+       Lists the capabilities of the helper, one per line, ending
+       with a blank line.
+
+'list'::
+       Lists the refs, one per line, in the format "<value> <name>
+       [<attr> ...]". The value may be a hex sha1 hash, "@<dest>" for
+       a symref, or "?" to indicate that the helper could not get the
+       value of the ref. A space-separated list of attributes follows
+       the name; unrecognized attributes are ignored. After the
+       complete list, outputs a blank line.
+
+'fetch' <sha1> <name>::
+       Fetches the given object, writing the necessary objects to the
+       database. Outputs a blank line when the fetch is
+       complete. Only objects which were reported in the ref list
+       with a sha1 may be fetched this way.
++
+Supported if the helper has the "fetch" capability.
+
+If a fatal error occurs, the program writes the error message to
+stderr and exits. The caller should expect that a suitable error
+message has been printed if the child closes the connection without
+completing a valid response for the current command.
+
+Additional commands may be supported, as may be determined from
+capabilities reported by the helper.
+
+CAPABILITIES
+------------
+
+'fetch'::
+       This helper supports the 'fetch' command.
+
+REF LIST ATTRIBUTES
+-------------------
+
+None are defined yet, but the caller must accept any which are supplied.
+
+Documentation
+-------------
+Documentation by Daniel Barkalow.
+
+GIT
+---
+Part of the linkgit:git[1] suite
diff --git a/Documentation/git-replace.txt b/Documentation/git-replace.txt
new file mode 100644 (file)
index 0000000..915cb77
--- /dev/null
@@ -0,0 +1,71 @@
+git-replace(1)
+==============
+
+NAME
+----
+git-replace - Create, list, delete refs to replace objects
+
+SYNOPSIS
+--------
+[verse]
+'git replace' [-f] <object> <replacement>
+'git replace' -d <object>...
+'git replace' -l [<pattern>]
+
+DESCRIPTION
+-----------
+Adds a 'replace' reference in `.git/refs/replace/`
+
+The name of the 'replace' reference is the SHA1 of the object that is
+replaced. The content of the replace reference is the SHA1 of the
+replacement object.
+
+Unless `-f` is given, the replace reference must not yet exist in
+`.git/refs/replace/` directory.
+
+OPTIONS
+-------
+-f::
+       If an existing replace ref for the same object exists, it will
+       be overwritten (instead of failing).
+
+-d::
+       Delete existing replace refs for the given objects.
+
+-l <pattern>::
+       List replace refs for objects that match the given pattern (or
+       all if no pattern is given).
+       Typing "git replace" without arguments, also lists all replace
+       refs.
+
+BUGS
+----
+Comparing blobs or trees that have been replaced with those that
+replace them will not work properly. And using 'git reset --hard' to
+go back to a replaced commit will move the branch to the replacement
+commit instead of the replaced commit.
+
+There may be other problems when using 'git rev-list' related to
+pending objects. And of course things may break if an object of one
+type is replaced by an object of another type (for example a blob
+replaced by a commit).
+
+SEE ALSO
+--------
+linkgit:git-tag[1]
+linkgit:git-branch[1]
+
+Author
+------
+Written by Christian Couder <chriscool@tuxfamily.org> and Junio C
+Hamano <gitster@pobox.com>, based on 'git tag' by Kristian Hogsberg
+<krh@redhat.com> and Carlos Rica <jasampler@gmail.com>.
+
+Documentation
+--------------
+Documentation by Christian Couder <chriscool@tuxfamily.org> and the
+git-list <git@vger.kernel.org>, based on 'git tag' documentation.
+
+GIT
+---
+Part of the linkgit:git[1] suite
index abb25d1..469cf6d 100644 (file)
@@ -10,6 +10,7 @@ SYNOPSIS
 [verse]
 'git reset' [--mixed | --soft | --hard | --merge] [-q] [<commit>]
 'git reset' [-q] [<commit>] [--] <paths>...
+'git reset' --patch [<commit>] [--] [<paths>...]
 
 DESCRIPTION
 -----------
@@ -23,8 +24,9 @@ the undo in the history.
 If you want to undo a commit other than the latest on a branch,
 linkgit:git-revert[1] is your friend.
 
-The second form with 'paths' is used to revert selected paths in
-the index from a given commit, without moving HEAD.
+The second and third forms with 'paths' and/or --patch are used to
+revert selected paths in the index from a given commit, without moving
+HEAD.
 
 
 OPTIONS
@@ -50,6 +52,15 @@ OPTIONS
        and updates the files that are different between the named commit
        and the current commit in the working tree.
 
+-p::
+--patch::
+       Interactively select hunks in the difference between the index
+       and <commit> (defaults to HEAD).  The chosen hunks are applied
+       in reverse to the index.
++
+This means that `git reset -p` is the opposite of `git add -p` (see
+linkgit:git-add[1]).
+
 -q::
        Be quiet, only report errors.
 
index 974d9f5..3341d1b 100644 (file)
@@ -51,20 +51,26 @@ SYNOPSIS
 DESCRIPTION
 -----------
 
-Lists commit objects in reverse chronological order starting at the
-given commit(s), taking ancestry relationship into account.  This is
-useful to produce human-readable log output.
+List commits that are reachable by following the `parent` links from the
+given commit(s), but exclude commits that are reachable from the one(s)
+given with a '{caret}' in front of them.  The output is given in reverse
+chronological order by default.
 
-Commits which are stated with a preceding '{caret}' cause listing to
-stop at that point. Their parents are implied. Thus the following
-command:
+You can think of this as a set operation.  Commits given on the command
+line form a set of commits that are reachable from any of them, and then
+commits reachable from any of the ones given with '{caret}' in front are
+subtracted from that set.  The remaining commits are what comes out in the
+command's output.  Various other options and paths parameters can be used
+to further limit the result.
+
+Thus, the following command:
 
 -----------------------------------------------------------------------
        $ git rev-list foo bar ^baz
 -----------------------------------------------------------------------
 
-means "list all the commits which are included in 'foo' and 'bar', but
-not in 'baz'".
+means "list all the commits which are reachable from 'foo' or 'bar', but
+not from 'baz'".
 
 A special notation "'<commit1>'..'<commit2>'" can be used as a
 short-hand for "{caret}'<commit1>' '<commit2>'". For example, either of
index d6b192b..767cf4d 100644 (file)
@@ -142,8 +142,9 @@ user is prompted for a password while the input is masked for privacy.
 
 --smtp-server-port=<port>::
        Specifies a port different from the default port (SMTP
-       servers typically listen to smtp port 25 and ssmtp port
-       465); symbolic port names (e.g. "submission" instead of 465)
+       servers typically listen to smtp port 25, but may also listen to
+       submission port 587, or the common SSL smtp port 465);
+       symbolic port names (e.g. "submission" instead of 587)
        are also accepted. The port can also be set with the
        'sendemail.smtpserverport' configuration variable.
 
index 89ec536..7343361 100644 (file)
@@ -8,11 +8,12 @@ git-show-branch - Show branches and their commits
 SYNOPSIS
 --------
 [verse]
-'git show-branch' [--all] [--remotes] [--topo-order | --date-order]
-               [--current] [--color | --no-color]
+'git show-branch' [-a|--all] [-r|--remotes] [--topo-order | --date-order]
+               [--current] [--color | --no-color] [--sparse]
                [--more=<n> | --list | --independent | --merge-base]
                [--no-name | --sha1-name] [--topics]
                [<rev> | <glob>]...
+
 'git show-branch' (-g|--reflog)[=<n>[,<base>]] [--list] [<ref>]
 
 DESCRIPTION
@@ -81,9 +82,11 @@ OPTIONS
        Synonym to `--more=-1`
 
 --merge-base::
-       Instead of showing the commit list, just act like the
-       'git-merge-base -a' command, except that it can accept
-       more than two heads.
+       Instead of showing the commit list, determine possible
+       merge bases for the specified commits. All merge bases
+       will be contained in all specified commits. This is
+       different from how linkgit:git-merge-base[1] handles
+       the case of three or more commits.
 
 --independent::
        Among the <reference>s given, display only the ones that
index 1c64a02..3f14b72 100644 (file)
@@ -13,7 +13,7 @@ SYNOPSIS
 'git stash' drop [-q|--quiet] [<stash>]
 'git stash' ( pop | apply ) [--index] [-q|--quiet] [<stash>]
 'git stash' branch <branchname> [<stash>]
-'git stash' [save [--keep-index] [-q|--quiet] [<message>]]
+'git stash' [save [--patch] [-k|--[no-]keep-index] [-q|--quiet] [<message>]]
 'git stash' clear
 'git stash' create
 
@@ -42,15 +42,27 @@ is also possible).
 OPTIONS
 -------
 
-save [--keep-index] [-q|--quiet] [<message>]::
+save [--patch] [--[no-]keep-index] [-q|--quiet] [<message>]::
 
        Save your local modifications to a new 'stash', and run `git reset
-       --hard` to revert them.  This is the default action when no
-       subcommand is given. The <message> part is optional and gives
-       the description along with the stashed state.
+       --hard` to revert them.  The <message> part is optional and gives
+       the description along with the stashed state.  For quickly making
+       a snapshot, you can omit _both_ "save" and <message>, but giving
+       only <message> does not trigger this action to prevent a misspelled
+       subcommand from making an unwanted stash.
 +
 If the `--keep-index` option is used, all changes already added to the
 index are left intact.
++
+With `--patch`, you can interactively select hunks from in the diff
+between HEAD and the working tree to be stashed.  The stash entry is
+constructed such that its index state is the same as the index state
+of your repository, and its worktree contains only the changes you
+selected interactively.  The selected changes are then rolled back
+from your worktree.
++
+The `--patch` option implies `--keep-index`.  You can use
+`--no-keep-index` to override this.
 
 list [<options>]::
 
@@ -114,7 +126,8 @@ no conflicts.
 
 clear::
        Remove all the stashed states. Note that those states will then
-       be subject to pruning, and may be difficult or impossible to recover.
+       be subject to pruning, and may be impossible to recover (see
+       'Examples' below for a possible strategy).
 
 drop [-q|--quiet] [<stash>]::
 
@@ -217,6 +230,20 @@ $ edit/build/test remaining parts
 $ git commit foo -m 'Remaining parts'
 ----------------------------------------------------------------
 
+Recovering stashes that were cleared/dropped erroneously::
+
+If you mistakenly drop or clear stashes, they cannot be recovered
+through the normal safety mechanisms.  However, you can try the
+following incantation to get a list of stashes that are still in your
+repository, but not reachable any more:
++
+----------------------------------------------------------------
+git fsck --unreachable |
+grep commit | cut -d\  -f3 |
+xargs git log --merges --no-walk --grep=WIP
+----------------------------------------------------------------
+
+
 SEE ALSO
 --------
 linkgit:git-checkout[1],
index 7dd73ae..5ccdd18 100644 (file)
@@ -11,12 +11,12 @@ SYNOPSIS
 [verse]
 'git submodule' [--quiet] add [-b branch]
              [--reference <repository>] [--] <repository> <path>
-'git submodule' [--quiet] status [--cached] [--] [<path>...]
+'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]
 'git submodule' [--quiet] init [--] [<path>...]
 'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--rebase]
-             [--reference <repository>] [--merge] [--] [<path>...]
-'git submodule' [--quiet] summary [--cached] [--summary-limit <n>] [commit] [--] [<path>...]
-'git submodule' [--quiet] foreach <command>
+             [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
+'git submodule' [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
+'git submodule' [--quiet] foreach [--recursive] <command>
 'git submodule' [--quiet] sync [--] [<path>...]
 
 
@@ -100,6 +100,9 @@ status::
        initialized and `+` if the currently checked out submodule commit
        does not match the SHA-1 found in the index of the containing
        repository. This command is the default command for 'git-submodule'.
++
+If '--recursive' is specified, this command will recurse into nested
+submodules, and show their status as well.
 
 init::
        Initialize the submodules, i.e. register each submodule name
@@ -122,21 +125,31 @@ update::
 If the submodule is not yet initialized, and you just want to use the
 setting as stored in .gitmodules, you can automatically initialize the
 submodule with the --init option.
++
+If '--recursive' is specified, this command will recurse into the
+registered submodules, and update any nested submodules within.
 
 summary::
        Show commit summary between the given commit (defaults to HEAD) and
        working tree/index. For a submodule in question, a series of commits
        in the submodule between the given super project commit and the
-       index or working tree (switched by --cached) are shown.
+       index or working tree (switched by --cached) are shown. If the option
+       --files is given, show the series of commits in the submodule between
+       the index of the super project and the working tree of the submodule
+       (this option doesn't allow to use the --cached option or to provide an
+       explicit commit).
 
 foreach::
        Evaluates an arbitrary shell command in each checked out submodule.
-       The command has access to the variables $path and $sha1:
+       The command has access to the variables $name, $path and $sha1:
+       $name is the name of the relevant submodule section in .gitmodules,
        $path is the name of the submodule directory relative to the
        superproject, and $sha1 is the commit as recorded in the superproject.
        Any submodules defined in the superproject but not checked out are
        ignored by this command. Unless given --quiet, foreach prints the name
        of each submodule before evaluating the command.
+       If --recursive is given, submodules are traversed recursively (i.e.
+       the given shell command is evaluated in nested submodules as well).
        A non-zero return from the command in any submodule causes
        the processing to terminate. This can be overridden by adding '|| :'
        to the end of the command.
@@ -169,6 +182,11 @@ OPTIONS
        commands typically use the commit found in the submodule HEAD, but
        with this option, the commit stored in the index is used instead.
 
+--files::
+       This option is only valid for the summary command. This command
+       compares the commit in the index with that in the submodule HEAD
+       when this option is used.
+
 -n::
 --summary-limit::
        This option is only valid for the summary command.
@@ -209,6 +227,12 @@ OPTIONS
 *NOTE*: Do *not* use this option unless you have read the note
 for linkgit:git-clone[1]'s --reference and --shared options carefully.
 
+--recursive::
+       This option is only valid for foreach, update and status commands.
+       Traverse submodules recursively. The operation is performed not
+       only in the submodules of the current repo, but also
+       in any nested submodules inside those submodules (and so on).
+
 <path>...::
        Paths to submodule(s). When specified this will restrict the command
        to only operate on the submodules found at the specified paths.
index 22a0389..1812890 100644 (file)
@@ -102,9 +102,6 @@ COMMANDS
        Store Git commit times in the local timezone instead of UTC.  This
        makes 'git log' (even without --date=local) show the same times
        that `svn log` would in the local timezone.
-
---parent;;
-       Fetch only from the SVN parent of the current HEAD.
 +
 This doesn't interfere with interoperating with the Subversion
 repository you cloned from, but if you wish for your local Git
@@ -112,6 +109,9 @@ repository to be able to interoperate with someone else's local Git
 repository, either don't use this option or you should both use it in
 the same local timezone.
 
+--parent;;
+       Fetch only from the SVN parent of the current HEAD.
+
 --ignore-paths=<regex>;;
        This allows one to specify a Perl regular expression that will
        cause skipping of all matching paths from checkout from SVN.
index fa73321..299b04f 100644 (file)
@@ -10,14 +10,15 @@ SYNOPSIS
 --------
 [verse]
 'git tag' [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>]
-       <name> [<commit> | <object>]
-'git tag' -d <name>...
+       <tagname> [<commit> | <object>]
+'git tag' -d <tagname>...
 'git tag' [-n[<num>]] -l [--contains <commit>] [<pattern>]
-'git tag' -v <name>...
+'git tag' -v <tagname>...
 
 DESCRIPTION
 -----------
-Adds a 'tag' reference in `.git/refs/tags/`
+
+Adds a tag reference in `.git/refs/tags/`.
 
 Unless `-f` is given, the tag must not yet exist in
 `.git/refs/tags/` directory.
@@ -50,6 +51,7 @@ OPTIONS
        Make a GPG-signed tag, using the given key
 
 -f::
+--force::
        Replace an existing tag with the given name (instead of failing)
 
 -d::
@@ -85,6 +87,12 @@ OPTIONS
        Implies `-a` if none of `-a`, `-s`, or `-u <key-id>`
        is given.
 
+<tagname>::
+       The name of the tag to create, delete, or describe.
+       The new tag name must pass all checks defined by
+       linkgit:git-check-ref-format[1].  Some of these checks
+       may restrict the characters allowed in a tag name.
+
 CONFIGURATION
 -------------
 By default, 'git-tag' in sign-with-default mode (-s) will use your
@@ -249,6 +257,10 @@ $ GIT_COMMITTER_DATE="2006-10-02 10:31" git tag -s v1.0.1
 ------------
 
 
+SEE ALSO
+--------
+linkgit:git-check-ref-format[1].
+
 Author
 ------
 Written by Linus Torvalds <torvalds@osdl.org>,
index b8e49dc..63f3b5c 100644 (file)
@@ -20,6 +20,8 @@ The UI for the protocol is on the 'git-fetch-pack' side, and the
 program pair is meant to be used to pull updates from a remote
 repository.  For push operations, see 'git-send-pack'.
 
+After finishing the operation successfully, `post-upload-pack`
+hook is called (see linkgit:githooks[5]).
 
 OPTIONS
 -------
index c861163..97f7f91 100644 (file)
@@ -8,7 +8,7 @@ git-verify-pack - Validate packed git archive files
 
 SYNOPSIS
 --------
-'git verify-pack' [-v] [--] <pack>.idx ...
+'git verify-pack' [-v|--verbose] [--] <pack>.idx ...
 
 
 DESCRIPTION
@@ -23,8 +23,15 @@ OPTIONS
        The idx files to verify.
 
 -v::
+--verbose::
        After verifying the pack, show list of objects contained
-       in the pack.
+       in the pack and a histogram of delta chain length.
+
+-s::
+--stat-only::
+       Do not verify the pack contents; only show the histogram of delta
+       chain length.  With `--verbose`, list of objects is also shown.
+
 \--::
        Do not interpret any more arguments as options.
 
index acc408d..06e0f31 100644 (file)
@@ -245,7 +245,7 @@ Both standard output and standard error output are forwarded to
 for the user.
 
 The default 'update' hook, when enabled--and with
-`hooks.allowunannotated` config option turned on--prevents
+`hooks.allowunannotated` config option unset or set to false--prevents
 unannotated tags to be pushed.
 
 [[post-receive]]
@@ -310,6 +310,35 @@ Both standard output and standard error output are forwarded to
 'git-send-pack' on the other end, so you can simply `echo` messages
 for the user.
 
+post-upload-pack
+----------------
+
+After upload-pack successfully finishes its operation, this hook is called
+for logging purposes.
+
+The hook is passed various pieces of information, one per line, from its
+standard input.  Currently the following items can be fed to the hook, but
+more types of information may be added in the future:
+
+want SHA-1::
+    40-byte hexadecimal object name the client asked to include in the
+    resulting pack.  Can occur one or more times in the input.
+
+have SHA-1::
+    40-byte hexadecimal object name the client asked to exclude from
+    the resulting pack, claiming to have them already.  Can occur zero
+    or more times in the input.
+
+time float::
+    Number of seconds spent for creating the packfile.
+
+size decimal::
+    Size of the resulting packfile in bytes.
+
+kind string:
+    Either "clone" (when the client did not give us any "have", and asked
+    for all our refs with "want"), or "fetch" (otherwise).
+
 pre-auto-gc
 ~~~~~~~~~~~
 
diff --git a/Documentation/pt_BR/gittutorial.txt b/Documentation/pt_BR/gittutorial.txt
new file mode 100644 (file)
index 0000000..81e7ad7
--- /dev/null
@@ -0,0 +1,675 @@
+gittutorial(7)
+==============
+
+NAME
+----
+gittutorial - Um tutorial de introdução ao git (para versão 1.5.1 ou mais nova)
+
+SYNOPSIS
+--------
+git *
+
+DESCRIPTION
+-----------
+
+Este tutorial explica como importar um novo projeto para o git,
+adicionar mudanças a ele, e compartilhar mudanças com outros
+desenvolvedores.
+
+Se, ao invés disso, você está interessado primariamente em usar git para
+obter um projeto, por exemplo, para testar a última versão, você pode
+preferir começar com os primeiros dois capítulos de
+link:user-manual.html[O Manual do Usuário Git].
+
+Primeiro, note que você pode obter documentação para um comando como
+`git log --graph` com:
+
+------------------------------------------------
+$ man git-log
+------------------------------------------------
+
+ou:
+
+------------------------------------------------
+$ git help log
+------------------------------------------------
+
+Com a última forma, você pode usar o visualizador de manual de sua
+escolha; veja linkgit:git-help[1] para maior informação.
+
+É uma boa idéia informar ao git seu nome e endereço público de email
+antes de fazer qualquer operação. A maneira mais fácil de fazê-lo é:
+
+------------------------------------------------
+$ git config --global user.name "Seu Nome Vem Aqui"
+$ git config --global user.email voce@seudominio.exemplo.com
+------------------------------------------------
+
+
+Importando um novo projeto
+-----------------------
+
+Assuma que você tem um tarball project.tar.gz com seu trabalho inicial.
+Você pode colocá-lo sob controle de revisão git da seguinte forma:
+
+------------------------------------------------
+$ tar xzf project.tar.gz
+$ cd project
+$ git init
+------------------------------------------------
+
+Git irá responder
+
+------------------------------------------------
+Initialized empty Git repository in .git/
+------------------------------------------------
+
+Você agora iniciou seu diretório de trabalho--você deve ter notado um
+novo diretório criado, com o nome de ".git".
+
+A seguir, diga ao git para gravar um instantâneo do conteúdo de todos os
+arquivos sob o diretório corrente (note o '.'), com 'git-add':
+
+------------------------------------------------
+$ git add .
+------------------------------------------------
+
+Este instantâneo está agora armazenado em uma área temporária que o git
+chama de "index" ou índice. Você pode armazenar permanentemente o
+conteúdo do índice no repositório com 'git-commit':
+
+------------------------------------------------
+$ git commit
+------------------------------------------------
+
+Isto vai te pedir por uma mensagem de commit. Você agora gravou sua
+primeira versão de seu projeto no git.
+
+Fazendo mudanças
+--------------
+
+Modifique alguns arquivos, e, então, adicione seu conteúdo atualizado ao
+índice:
+
+------------------------------------------------
+$ git add file1 file2 file3
+------------------------------------------------
+
+Você está agora pronto para fazer o commit. Você pode ver o que está
+para ser gravado usando 'git-diff' com a opção --cached:
+
+------------------------------------------------
+$ git diff --cached
+------------------------------------------------
+
+(Sem --cached, o comando 'git-diff' irá te mostrar quaisquer mudanças
+que você tenha feito mas ainda não adicionou ao índice.) Você também
+pode obter um breve sumário da situação com 'git-status':
+
+------------------------------------------------
+$ git status
+# On branch master
+# Changes to be committed:
+#   (use "git reset HEAD <file>..." to unstage)
+#
+#      modified:   file1
+#      modified:   file2
+#      modified:   file3
+#
+------------------------------------------------
+
+Se você precisar fazer qualquer outro ajuste, faça-o agora, e, então,
+adicione qualquer conteúdo modificado ao índice. Finalmente, grave suas
+mudanças com:
+
+------------------------------------------------
+$ git commit
+------------------------------------------------
+
+Isto irá novamente te pedir por uma mensagem descrevendo a mudança, e,
+então, gravar a nova versão do projeto.
+
+Alternativamente, ao invés de executar 'git-add' antes, você pode usar
+
+------------------------------------------------
+$ git commit -a
+------------------------------------------------
+
+o que irá automaticamente notar quaisquer arquivos modificados (mas não
+novos), adicioná-los ao índices, e gravar, tudo em um único passo.
+
+Uma nota em mensagens de commit: Apesar de não ser exigido, é uma boa
+idéia começar a mensagem com uma simples e curta (menos de 50
+caracteres) linha sumarizando a mudança, seguida de uma linha em branco
+e, então, uma descrição mais detalhada. Ferramentas que transformam
+commits em email, por exemplo, usam a primeira linha no campo de
+cabeçalho Subject: e o resto no corpo.
+
+Git rastreia conteúdo, não arquivos
+----------------------------
+
+Muitos sistemas de controle de revisão provêem um comando `add` que diz
+ao sistema para começar a rastrear mudanças em um novo arquivo. O
+comando `add` do git faz algo mais simples e mais poderoso: 'git-add' é
+usado tanto para arquivos novos e arquivos recentemente modificados, e
+em ambos os casos, ele tira o instantâneo dos arquivos dados e armazena
+o conteúdo no índice, pronto para inclusão do próximo commit.
+
+Visualizando história do projeto
+-----------------------
+
+Em qualquer ponto você pode visualizar a história das suas mudanças
+usando
+
+------------------------------------------------
+$ git log
+------------------------------------------------
+
+Se você também quer ver a diferença completa a cada passo, use
+
+------------------------------------------------
+$ git log -p
+------------------------------------------------
+
+Geralmente, uma visão geral da mudança é útil para ter a sensação de
+cada passo
+
+------------------------------------------------
+$ git log --stat --summary
+------------------------------------------------
+
+Gerenciando "branches"/ramos
+-----------------
+
+Um simples repositório git pode manter múltiplos ramos de
+desenvolvimento. Para criar um novo ramo chamado "experimental", use
+
+------------------------------------------------
+$ git branch experimental
+------------------------------------------------
+
+Se você executar agora
+
+------------------------------------------------
+$ git branch
+------------------------------------------------
+
+você vai obter uma lista de todos os ramos existentes:
+
+------------------------------------------------
+  experimental
+* master
+------------------------------------------------
+
+O ramo "experimental" é o que você acaba de criar, e o ramo "master" é o
+ramo padrão que foi criado pra você automaticamente. O asterisco marca
+o ramo em que você está atualmente; digite
+
+------------------------------------------------
+$ git checkout experimental
+------------------------------------------------
+
+para mudar para o ramo experimental. Agora edite um arquivo, grave a
+mudança, e mude de volta para o ramo master:
+
+------------------------------------------------
+(edita arquivo)
+$ git commit -a
+$ git checkout master
+------------------------------------------------
+
+Verifique que a mudança que você fez não está mais visível, já que ela
+foi feita no ramo experimental e você está de volta ao ramo master.
+
+Você pode fazer uma mudança diferente no ramo master:
+
+------------------------------------------------
+(edit file)
+$ git commit -a
+------------------------------------------------
+
+neste ponto, os dois ramos divergiram, com diferentes mudanças feitas em
+cada um. Para unificar as mudanças feitas no experimental para o
+master, execute
+
+------------------------------------------------
+$ git merge experimental
+------------------------------------------------
+
+Se as mudanças não conflitarem, estará pronto. Se existirem conflitos,
+marcadores serão deixados nos arquivos problemáticos exibindo o
+conflito;
+
+------------------------------------------------
+$ git diff
+------------------------------------------------
+
+vai exibir isto. Após você editar os arquivos para resolver os
+conflitos,
+
+------------------------------------------------
+$ git commit -a
+------------------------------------------------
+
+irá gravar o resultado da unificação. Finalmente,
+
+------------------------------------------------
+$ gitk
+------------------------------------------------
+
+vai mostrar uma bela representação gráfica da história resultante.
+
+Neste ponto você pode remover seu ramo experimental com
+
+------------------------------------------------
+$ git branch -d experimental
+------------------------------------------------
+
+Este comando garante que as mudanças no ramo experimental já estão no
+ramo atual.
+
+Se você desenvolve em um ramo ideia-louca, e se arrepende, você pode
+sempre remover o ramo com
+
+-------------------------------------
+$ git branch -D ideia-louca
+-------------------------------------
+
+Ramos são baratos e fáceis, então isto é uma boa maneira de experimentar
+alguma coisa.
+
+Usando git para colaboração
+---------------------------
+
+Suponha que Alice começou um novo projeto com um repositório git em
+/home/alice/project, e que Bob, que tem um diretório home na mesma
+máquina, quer contribuir.
+
+Bob começa com:
+
+------------------------------------------------
+bob$ git clone /home/alice/project myrepo
+------------------------------------------------
+
+Isso cria um novo diretório "myrepo" contendo um clone do repositório de
+Alice. O clone está no mesmo pé que o projeto original, possuindo sua
+própria cópia da história do projeto original.
+
+Bob então faz algumas mudanças e as grava:
+
+------------------------------------------------
+(editar arquivos)
+bob$ git commit -a
+(repetir conforme necessário)
+------------------------------------------------
+
+Quanto está pronto, ele diz a Alice para puxar as mudanças do
+repositório em /home/bob/myrepo. Ela o faz com:
+
+------------------------------------------------
+alice$ cd /home/alice/project
+alice$ git pull /home/bob/myrepo master
+------------------------------------------------
+
+Isto unifica as mudanças do ramo "master" do Bob ao ramo atual de Alice.
+Se Alice fez suas próprias mudanças no intervalo, ela, então, pode
+precisar corrigir manualmente quaisquer conflitos. (Note que o argumento
+"master" no comando acima é, de fato, desnecessário, já que é o padrão.)
+
+O comando "pull" executa, então, duas operações: ele obtém mudanças de
+um ramo remoto, e, então, as unifica no ramo atual.
+
+Note que, em geral, Alice gostaria que suas mudanças locais fossem
+gravadas antes de iniciar este "pull". Se o trabalho de Bob conflita
+com o que Alice fez desde que suas histórias se ramificaram, Alice irá
+usar seu diretório de trabalho e o índice para resolver conflitos, e
+mudanças locais existentes irão interferir com o processo de resolução
+de conflitos (git ainda irá realizar a obtenção mas irá se recusar a
+unificar --- Alice terá que se livrar de suas mudanças locais de alguma
+forma e puxar de novo quando isso acontecer).
+
+Alice pode espiar o que Bob fez sem unificar primeiro, usando o comando
+"fetch"; isto permite Alice inspecionar o que Bob fez, usando um símbolo
+especial "FETCH_HEAD", com o fim de determinar se ele tem alguma coisa
+que vale puxar, assim:
+
+------------------------------------------------
+alice$ git fetch /home/bob/myrepo master
+alice$ git log -p HEAD..FETCH_HEAD
+------------------------------------------------
+
+Esta operação é segura mesmo se Alice tem mudanças locais não gravadas.
+A notação de intervalo "HEAD..FETCH_HEAD" significa mostrar tudo que é
+alcançável de FETCH_HEAD mas exclua tudo o que é alcançável de HEAD.
+Alice já sabe tudo que leva a seu estado atual (HEAD), e revisa o que Bob
+tem em seu estado (FETCH_HEAD) que ela ainda não viu com esse comando.
+
+Se Alice quer visualizar o que Bob fez desde que suas histórias se
+ramificaram, ela pode disparar o seguinte comando:
+
+------------------------------------------------
+$ gitk HEAD..FETCH_HEAD
+------------------------------------------------
+
+Isto usa a mesma notação de intervalo que vimos antes com 'git log'.
+
+Alice pode querer ver o que ambos fizeram desde que ramificaram. Ela
+pode usar a forma com três pontos ao invés da forma com dois pontos:
+
+------------------------------------------------
+$ gitk HEAD...FETCH_HEAD
+------------------------------------------------
+
+Isto significa "mostre tudo que é alcançável de qualquer um deles, mas
+exclua tudo que é alcançável a partir de ambos".
+
+Por favor, note que essas notações de intervalo podem ser usadas tanto
+com gitk quanto com "git log".
+
+Após inspecionar o que Bob fez, se não há nada urgente, Alice pode
+decidir continuar trabalhando sem puxar de Bob. Se a história de Bob
+tem alguma coisa que Alice precisa imediatamente, Alice pode optar por
+separar seu trabalho em progresso primeiro, fazer um "pull", e, então,
+finalmente, retomar seu trabalho em progresso em cima da história
+resultante.
+
+Quando você está trabalhando em um pequeno grupo unido, não é incomum
+interagir com o mesmo repositório várias e várias vezes. Definindo um
+repositório remoto antes de tudo, você pode fazê-lo mais facilmente:
+
+------------------------------------------------
+alice$ git remote add bob /home/bob/myrepo
+------------------------------------------------
+
+Com isso, Alice pode executar a primeira parte da operação "pull" usando
+o comando 'git-fetch' sem unificar suas mudanças com seu próprio ramo,
+usando:
+
+-------------------------------------
+alice$ git fetch bob
+-------------------------------------
+
+Diferente da forma longa, quando Alice obteve de Bob usando um
+repositório remoto antes definido com 'git-remote', o que foi obtido é
+armazenado em um ramo remoto, neste caso `bob/master`. Então, após isso:
+
+-------------------------------------
+alice$ git log -p master..bob/master
+-------------------------------------
+
+mostra uma lista de todas as mudanças que Bob fez desde que ramificou do
+ramo master de Alice.
+
+Após examinar essas mudanças, Alice pode unificá-las em seu ramo master:
+
+-------------------------------------
+alice$ git merge bob/master
+-------------------------------------
+
+Esse `merge` pode também ser feito puxando de seu próprio ramo remoto,
+assim:
+
+-------------------------------------
+alice$ git pull . remotes/bob/master
+-------------------------------------
+
+Note que 'git pull' sempre unifica ao ramo atual, independente do que
+mais foi passado na linha de comando.
+
+Depois, Bob pode atualizar seu repositório com as últimas mudanças de
+Alice, usando
+
+-------------------------------------
+bob$ git pull
+-------------------------------------
+
+Note que ele não precisa dar o caminho do repositório de Alice; quando
+Bob clonou seu repositório, o git armazenou a localização de seu
+repositório na configuração do mesmo, e essa localização é usada
+para puxar:
+
+-------------------------------------
+bob$ git config --get remote.origin.url
+/home/alice/project
+-------------------------------------
+
+(A configuração completa criada por 'git-clone' é visível usando `git
+config -l`, e a página de manual linkgit:git-config[1] explica o
+significado de cada opção.)
+
+Git também mantém uma cópia limpa do ramo master de Alice sob o nome
+"origin/master":
+
+-------------------------------------
+bob$ git branch -r
+  origin/master
+-------------------------------------
+
+Se Bob decidir depois em trabalhar em um host diferente, ele ainda pode
+executar clones e puxar usando o protocolo ssh:
+
+-------------------------------------
+bob$ git clone alice.org:/home/alice/project myrepo
+-------------------------------------
+
+Alternativamente, o git tem um protocolo nativo, ou pode usar rsync ou
+http; veja linkgit:git-pull[1] para detalhes.
+
+Git pode também ser usado em um modo parecido com CVS, com um
+repositório central para o qual vários usuários empurram modificações;
+veja linkgit:git-push[1] e linkgit:gitcvs-migration[7].
+
+Explorando história
+-----------------
+
+A história no git é representada como uma série de commits
+interrelacionados. Nós já vimos que o comando 'git-log' pode listar
+esses commits. Note que a primeira linha de cada entrada no log também
+dá o nome para o commit:
+
+-------------------------------------
+$ git log
+commit c82a22c39cbc32576f64f5c6b3f24b99ea8149c7
+Author: Junio C Hamano <junkio@cox.net>
+Date:   Tue May 16 17:18:22 2006 -0700
+
+    merge-base: Clarify the comments on post processing.
+-------------------------------------
+
+Nós podemos dar este nome ao 'git-show' para ver os detalhes sobre este
+commit.
+
+-------------------------------------
+$ git show c82a22c39cbc32576f64f5c6b3f24b99ea8149c7
+-------------------------------------
+
+Mas há outras formas de se referir aos commits. Você pode usar qualquer
+parte inicial do nome que seja longo o bastante para identificar
+unicamente o commit:
+
+-------------------------------------
+$ git show c82a22c39c  # os primeiros caracteres do nome são o bastante
+                       # usualmente
+$ git show HEAD                # a ponta do ramo atual
+$ git show experimental        # a ponta do ramo "experimental"
+-------------------------------------
+
+Todo commit normalmente tem um commit "pai" que aponta para o estado
+anterior do projeto:
+
+-------------------------------------
+$ git show HEAD^  # para ver o pai de HEAD
+$ git show HEAD^^ # para ver o avô de HEAD
+$ git show HEAD~4 # para ver o trisavô de HEAD
+-------------------------------------
+
+Note que commits de unificação podem ter mais de um pai:
+
+-------------------------------------
+$ git show HEAD^1 # mostra o primeiro pai de HEAD (o mesmo que HEAD^)
+$ git show HEAD^2 # mostra o segundo pai de HEAD
+-------------------------------------
+
+Você também pode dar aos commits nomes à sua escolha; após executar
+
+-------------------------------------
+$ git tag v2.5 1b2e1d63ff
+-------------------------------------
+
+você pode se referir a 1b2e1d63ff pelo nome "v2.5". Se você pretende
+compartilhar esse nome com outras pessoas (por exemplo, para identificar
+uma versão de lançamento), você deveria criar um objeto "tag", e talvez
+assiná-lo; veja linkgit:git-tag[1] para detalhes.
+
+Qualquer comando git que precise conhecer um commit pode receber
+quaisquer desses nomes. Por exemplo:
+
+-------------------------------------
+$ git diff v2.5 HEAD    # compara o HEAD atual com v2.5
+$ git branch stable v2.5 # inicia um novo ramo chamado "stable" baseado
+                        # em v2.5
+$ git reset --hard HEAD^ # reseta seu ramo atual e seu diretório de
+                        # trabalho a seu estado em HEAD^
+-------------------------------------
+
+Seja cuidadoso com o último comando: além de perder quaisquer mudanças
+em seu diretório de trabalho, ele também remove todos os commits
+posteriores desse ramo. Se esse ramo é o único ramo contendo esses
+commits, eles serão perdidos. Também, não use 'git-reset' num ramo
+publicamente visível de onde outros desenvolvedores puxam, já que vai
+forçar unificações desnecessárias para que outros desenvolvedores limpem
+a história. Se você precisa desfazer mudanças que você empurrou, use
+'git-revert' no lugar.
+
+O comando 'git-grep' pode buscar strings em qualquer versão de seu
+projeto, então
+
+-------------------------------------
+$ git grep "hello" v2.5
+-------------------------------------
+
+procura por todas as ocorrências de "hello" em v2.5.
+
+Se você deixar de fora o nome do commit, 'git-grep' irá procurar
+quaisquer dos arquivos que ele gerencia no diretório corrente. Então
+
+-------------------------------------
+$ git grep "hello"
+-------------------------------------
+
+é uma forma rápida de buscar somente os arquivos que são rastreados pelo
+git.
+
+Muitos comandos git também recebem um conjunto de commits, o que pode
+ser especificado de várias formas. Aqui estão alguns exemplos com 'git-log':
+
+-------------------------------------
+$ git log v2.5..v2.6            # commits entre v2.5 e v2.6
+$ git log v2.5..                # commits desde v2.5
+$ git log --since="2 weeks ago" # commits das últimas 2 semanas
+$ git log v2.5.. Makefile       # commits desde v2.5 que modificam
+                               # Makefile
+-------------------------------------
+
+Você também pode dar ao 'git-log' um "intervalo" de commits onde o
+primeiro não é necessariamente um ancestral do segundo; por exemplo, se
+as pontas dos ramos "stable" e "master" divergiram de um commit
+comum algum tempo atrás, então
+
+-------------------------------------
+$ git log stable..master
+-------------------------------------
+
+irá listar os commits feitos no ramo "master" mas não no ramo
+"stable", enquanto
+
+-------------------------------------
+$ git log master..stable
+-------------------------------------
+
+irá listar a lista de commits feitos no ramo "stable" mas não no ramo
+"master".
+
+O comando 'git-log' tem uma fraqueza: ele precisa mostrar os commits em
+uma lista. Quando a história tem linhas de desenvolvimento que
+divergiram e então foram unificadas novamente, a ordem em que 'git-log'
+apresenta essas mudanças é irrelevante.
+
+A maioria dos projetos com múltiplos contribuidores (como o kernel
+Linux, ou o próprio git) tem unificações frequentes, e 'gitk' faz um
+trabalho melhor de visualizar sua história. Por exemplo,
+
+-------------------------------------
+$ gitk --since="2 weeks ago" drivers/
+-------------------------------------
+
+permite a você navegar em quaisquer commits desde as últimas duas semanas
+de commits que modificaram arquivos sob o diretório "drivers". (Nota:
+você pode ajustar as fontes do gitk segurando a tecla control enquanto
+pressiona "-" ou "+".)
+
+Finalmente, a maioria dos comandos que recebem nomes de arquivo permitirão
+também, opcionalmente, preceder qualquer nome de arquivo por um
+commit, para especificar uma versão particular do arquivo:
+
+-------------------------------------
+$ git diff v2.5:Makefile HEAD:Makefile.in
+-------------------------------------
+
+Você pode usar 'git-show' para ver tal arquivo:
+
+-------------------------------------
+$ git show v2.5:Makefile
+-------------------------------------
+
+Próximos passos
+----------
+
+Este tutorial deve ser o bastante para operar controle de revisão
+distribuído básico para seus projetos. No entanto, para entender
+plenamente a profundidade e o poder do git você precisa entender duas
+idéias simples nas quais ele se baseia:
+
+  * A base de objetos é um sistema bem elegante usado para armazenar a
+    história de seu projeto--arquivos, diretórios, e commits.
+
+  * O arquivo de índice é um cache do estado de uma árvore de diretório,
+    usado para criar commits, restaurar diretórios de trabalho, e
+    armazenar as várias árvores envolvidas em uma unificação.
+
+A parte dois deste tutorial explica a base de objetos, o arquivo de
+índice, e algumas outras coisinhas que você vai precisar pra usar o
+máximo do git. Você pode encontrá-la em linkgit:gittutorial-2[7].
+
+Se você não quiser continuar com o tutorial agora nesse momento, algumas
+outras digressões que podem ser interessantes neste ponto são:
+
+  * linkgit:git-format-patch[1], linkgit:git-am[1]: Estes convertem
+    séries de commits em patches para email, e vice-versa, úteis para
+    projetos como o kernel Linux que dependem fortemente de patches
+    enviados por email.
+
+  * linkgit:git-bisect[1]: Quando há uma regressão em seu projeto, uma
+    forma de rastrear um bug é procurando pela história para encontrar o
+    commit culpado. Git bisect pode ajudar a executar uma busca binária
+    por esse commit. Ele é inteligente o bastante para executar uma
+    busca próxima da ótima mesmo no caso de uma história complexa
+    não-linear com muitos ramos unificados.
+
+  * link:everyday.html[GIT diariamente com 20 e tantos comandos]
+
+  * linkgit:gitcvs-migration[7]: Git para usuários de CVS.
+
+VEJA TAMBÉM
+--------
+linkgit:gittutorial-2[7],
+linkgit:gitcvs-migration[7],
+linkgit:gitcore-tutorial[7],
+linkgit:gitglossary[7],
+linkgit:git-help[1],
+link:everyday.html[git diariamente],
+link:user-manual.html[O Manual do Usuário git]
+
+GIT
+---
+Parte da suite linkgit:git[1].
index 2efe7a4..b26c281 100644 (file)
@@ -35,12 +35,32 @@ Functions
        Convenience functions that encapsulate a sequence of
        start_command() followed by finish_command(). The argument argv
        specifies the program and its arguments. The argument opt is zero
-       or more of the flags `RUN_COMMAND_NO_STDIN`, `RUN_GIT_CMD`, or
-       `RUN_COMMAND_STDOUT_TO_STDERR` that correspond to the members
-       .no_stdin, .git_cmd, .stdout_to_stderr of `struct child_process`.
+       or more of the flags `RUN_COMMAND_NO_STDIN`, `RUN_GIT_CMD`,
+       `RUN_COMMAND_STDOUT_TO_STDERR`, or `RUN_SILENT_EXEC_FAILURE`
+       that correspond to the members .no_stdin, .git_cmd,
+       .stdout_to_stderr, .silent_exec_failure of `struct child_process`.
        The argument dir corresponds the member .dir. The argument env
        corresponds to the member .env.
 
+The functions above do the following:
+
+. If a system call failed, errno is set and -1 is returned. A diagnostic
+  is printed.
+
+. If the program was not found, then -1 is returned and errno is set to
+  ENOENT; a diagnostic is printed only if .silent_exec_failure is 0.
+
+. Otherwise, the program is run. If it terminates regularly, its exit
+  code is returned. No diagnistic is printed, even if the exit code is
+  non-zero.
+
+. If the program terminated due to a signal, then the return value is the
+  signal number - 128, ie. it is negative and so indicates an unusual
+  condition; a diagnostic is printed. This return value can be passed to
+  exit(2), which will report the same code to the parent process that a
+  POSIX shell's $? would report for a program that died from the signal.
+
+
 `start_async`::
 
        Run a function asynchronously. Takes a pointer to a `struct
@@ -143,6 +163,11 @@ string pointers (NULL terminated) in .env:
 To specify a new initial working directory for the sub-process,
 specify it in the .dir member.
 
+If the program cannot be found, the functions return -1 and set
+errno to ENOENT. Normally, an error message is printed, but if
+.silent_exec_failure is set to 1, no message is printed for this
+special error condition.
+
 
 * `struct async`
 
index e3ddf91..55b7286 100644 (file)
 tree walking API
 ================
 
-Talk about <tree-walk.h>, things like
+The tree walking API is used to traverse and inspect trees.
 
-* struct tree_desc
-* init_tree_desc
-* tree_entry_extract
-* update_tree_entry
-* get_tree_entry
+Data Structures
+---------------
 
-(JC, Linus)
+`struct name_entry`::
+
+       An entry in a tree. Each entry has a sha1 identifier, pathname, and
+       mode.
+
+`struct tree_desc`::
+
+       A semi-opaque data structure used to maintain the current state of the
+       walk.
++
+* `buffer` is a pointer into the memory representation of the tree. It always
+points at the current entry being visited.
+
+* `size` counts the number of bytes left in the `buffer`.
+
+* `entry` points to the current entry being visited.
+
+`struct traverse_info`::
+
+       A structure used to maintain the state of a traversal.
++
+* `prev` points to the traverse_info which was used to descend into the
+current tree. If this is the top-level tree `prev` will point to
+a dummy traverse_info.
+
+* `name` is the entry for the current tree (if the tree is a subtree).
+
+* `pathlen` is the length of the full path for the current tree.
+
+* `conflicts` can be used by callbacks to maintain directory-file conflicts.
+
+* `fn` is a callback called for each entry in the tree. See Traversing for more
+information.
+
+* `data` can be anything the `fn` callback would want to use.
+
+Initializing
+------------
+
+`init_tree_desc`::
+
+       Initialize a `tree_desc` and decode its first entry. The buffer and
+       size parameters are assumed to be the same as the buffer and size
+       members of `struct tree`.
+
+`fill_tree_descriptor`::
+
+       Initialize a `tree_desc` and decode its first entry given the sha1 of
+       a tree. Returns the `buffer` member if the sha1 is a valid tree
+       identifier and NULL otherwise.
+
+`setup_traverse_info`::
+
+       Initialize a `traverse_info` given the pathname of the tree to start
+       traversing from. The `base` argument is assumed to be the `path`
+       member of the `name_entry` being recursed into unless the tree is a
+       top-level tree in which case the empty string ("") is used.
+
+Walking
+-------
+
+`tree_entry`::
+
+       Visit the next entry in a tree. Returns 1 when there are more entries
+       left to visit and 0 when all entries have been visited. This is
+       commonly used in the test of a while loop.
+
+`tree_entry_len`::
+
+       Calculate the length of a tree entry's pathname. This utilizes the
+       memory structure of a tree entry to avoid the overhead of using a
+       generic strlen().
+
+`update_tree_entry`::
+
+       Walk to the next entry in a tree. This is commonly used in conjunction
+       with `tree_entry_extract` to inspect the current entry.
+
+`tree_entry_extract`::
+
+       Decode the entry currently being visited (the one pointed to by
+       `tree_desc's` `entry` member) and return the sha1 of the entry. The
+       `pathp` and `modep` arguments are set to the entry's pathname and mode
+       respectively.
+
+`get_tree_entry`::
+
+       Find an entry in a tree given a pathname and the sha1 of a tree to
+       search. Returns 0 if the entry is found and -1 otherwise. The third
+       and fourth parameters are set to the entry's sha1 and mode
+       respectively.
+
+Traversing
+----------
+
+`traverse_trees`::
+
+       Traverse `n` number of trees in parallel. The `fn` callback member of
+       `traverse_info` is called once for each tree entry.
+
+`traverse_callback_t`::
+       The arguments passed to the traverse callback are as follows:
++
+* `n` counts the number of trees being traversed.
+
+* `mask` has its nth bit set if something exists in the nth entry.
+
+* `dirmask` has its nth bit set if the nth tree's entry is a directory.
+
+* `entry` is an array of size `n` where the nth entry is from the nth tree.
+
+* `info` maintains the state of the traversal.
+
++
+Returning a negative value will terminate the traversal. Otherwise the
+return value is treated as an update mask. If the nth bit is set the nth tree
+will be updated and if the bit is not set the nth tree entry will be the
+same in the next callback invocation.
+
+`make_traverse_path`::
+
+       Generate the full pathname of a tree entry based from the root of the
+       traversal. For example, if the traversal has recursed into another
+       tree named "bar" the pathname of an entry "baz" in the "bar"
+       tree would be "bar/baz".
+
+`traverse_path_len`::
+
+       Calculate the length of a pathname returned by `make_traverse_path`.
+       This utilizes the memory structure of a tree entry to avoid the
+       overhead of using a generic strlen().
+
+Authors
+-------
+
+Written by Junio C Hamano <gitster@pobox.com> and Linus Torvalds
+<torvalds@linux-foundation.org>
index 5355ebc..d813ceb 100644 (file)
@@ -67,3 +67,21 @@ For example, with this:
 a URL like "work:repo.git" or like "host.xz:/path/to/repo.git" will be
 rewritten in any context that takes a URL to be "git://git.host.xz/repo.git".
 
+If you want to rewrite URLs for push only, you can create a
+configuration section of the form:
+
+------------
+       [url "<actual url base>"]
+               pushInsteadOf = <other url base>
+------------
+
+For example, with this:
+
+------------
+       [url "ssh://example.org/"]
+               pushInsteadOf = git://example.org/
+------------
+
+a URL like "git://example.org/path/to/repo.git" will be rewritten to
+"ssh://example.org/path/to/repo.git" for pushes, but pulls will still
+use the original URL.
index 68b9573..d7d9a9a 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v1.6.4.4
+DEF_VER=v1.6.4.GIT
 
 LF='
 '
diff --git a/INSTALL b/INSTALL
index ae7f750..be504c9 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -13,6 +13,10 @@ that uses $prefix, the built results have some paths encoded,
 which are derived from $prefix, so "make all; make prefix=/usr
 install" would not work.
 
+The beginning of the Makefile documents many variables that affect the way
+git is built.  You can override them either from the command line, or in a
+config.mak file.
+
 Alternatively you can use autoconf generated ./configure script to
 set up install paths (via config.mak.autogen), so you can write instead
 
@@ -48,32 +52,42 @@ Issues of note:
        export GIT_EXEC_PATH PATH GITPERLLIB
 
  - Git is reasonably self-sufficient, but does depend on a few external
-   programs and libraries:
+   programs and libraries.  Git can be used without most of them by adding
+   the approriate "NO_<LIBRARY>=YesPlease" to the make command line or
+   config.mak file.
 
        - "zlib", the compression library. Git won't build without it.
 
-       - "openssl".  Unless you specify otherwise, you'll get the SHA1
-         library from here.
+       - "ssh" is used to push and pull over the net.
 
-         If you don't have openssl, you can use one of the SHA1 libraries
-         that come with git (git includes the one from Mozilla, and has
-         its own PowerPC and ARM optimized ones too - see the Makefile).
+       - A POSIX-compliant shell is required to run many scripts needed
+         for everyday use (e.g. "bisect", "pull").
 
-       - libcurl library; git-http-fetch and git-fetch use them.  You
-         might also want the "curl" executable for debugging purposes.
-         If you do not use http transfer, you are probably OK if you
-         do not have them.
+       - "Perl" is needed to use some of the features (e.g. preparing a
+         partial commit using "git add -i/-p", interacting with svn
+         repositories with "git svn").  If you can live without these, use
+         NO_PERL.
 
-       - expat library; git-http-push uses it for remote lock
-         management over DAV.  Similar to "curl" above, this is optional.
+       - "openssl" library is used by git-imap-send to use IMAP over SSL.
+         If you don't need it, use NO_OPENSSL.
 
-        - "wish", the Tcl/Tk windowing shell is used in gitk to show the
-          history graphically, and in git-gui.
+         By default, git uses OpenSSL for SHA1 but it will use it's own
+         library (inspired by Mozilla's) with either NO_OPENSSL or
+         BLK_SHA1.  Also included is a version optimized for PowerPC
+         (PPC_SHA1).
+
+       - "libcurl" library is used by git-http-fetch and git-fetch.  You
+         might also want the "curl" executable for debugging purposes.
+         If you do not use http:// or https:// repositories, you do not
+         have to have them (use NO_CURL).
 
-       - "ssh" is used to push and pull over the net
+       - "expat" library; git-http-push uses it for remote lock
+         management over DAV.  Similar to "curl" above, this is optional
+         (with NO_EXPAT).
 
-       - "perl" and POSIX-compliant shells are needed to use most of
-         the bare-bones Porcelainish scripts.
+       - "wish", the Tcl/Tk windowing shell is used in gitk to show the
+         history graphically, and in git-gui.  If you don't want gitk or
+         git-gui, you can use NO_TCLTK.
 
  - Some platform specific issues are dealt with Makefile rules,
    but depending on your specific installation, you may not
index daf4296..d4958b8 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@ all::
 # when attempting to read from an fopen'ed directory.
 #
 # Define NO_OPENSSL environment variable if you do not have OpenSSL.
-# This also implies MOZILLA_SHA1.
+# This also implies BLK_SHA1.
 #
 # Define NO_CURL if you do not have libcurl installed.  git-http-pull and
 # git-http-push are not built, and you cannot use http:// and https://
@@ -84,18 +84,16 @@ all::
 # specify your own (or DarwinPort's) include directories and
 # library directories by defining CFLAGS and LDFLAGS appropriately.
 #
+# Define BLK_SHA1 environment variable if you want the C version
+# of the SHA1 that assumes you can do unaligned 32-bit loads and
+# have a fast htonl() function.
+#
 # Define PPC_SHA1 environment variable when running make to make use of
 # a bundled SHA1 routine optimized for PowerPC.
 #
-# Define ARM_SHA1 environment variable when running make to make use of
-# a bundled SHA1 routine optimized for ARM.
-#
-# Define MOZILLA_SHA1 environment variable when running make to make use of
-# a bundled SHA1 routine coming from Mozilla. It is GPL'd and should be fast
-# on non-x86 architectures (e.g. PowerPC), while the OpenSSL version (default
-# choice) has very fast version optimized for i586.
+# Define NEEDS_CRYPTO_WITH_SSL if you need -lcrypto when using -lssl (Darwin).
 #
-# Define NEEDS_SSL_WITH_CRYPTO if you need -lcrypto with -lssl (Darwin).
+# Define NEEDS_SSL_WITH_CRYPTO if you need -lssl when using -lcrypto (Darwin).
 #
 # Define NEEDS_LIBICONV if linking with libc is not enough (Darwin).
 #
@@ -361,7 +359,6 @@ PROGRAMS += git-patch-id$X
 PROGRAMS += git-shell$X
 PROGRAMS += git-show-index$X
 PROGRAMS += git-unpack-file$X
-PROGRAMS += git-update-server-info$X
 PROGRAMS += git-upload-pack$X
 PROGRAMS += git-var$X
 
@@ -383,7 +380,8 @@ BUILT_INS += git-stage$X
 BUILT_INS += git-status$X
 BUILT_INS += git-whatchanged$X
 
-# what 'all' will build and 'install' will install, in gitexecdir
+# what 'all' will build and 'install' will install in gitexecdir,
+# excluding programs for built-in commands
 ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
 
 # what 'all' will build but not install in gitexecdir
@@ -402,6 +400,7 @@ export PERL_PATH
 LIB_FILE=libgit.a
 XDIFF_LIB=xdiff/lib.a
 
+LIB_H += advice.h
 LIB_H += archive.h
 LIB_H += attr.h
 LIB_H += blob.h
@@ -459,6 +458,7 @@ LIB_H += utf8.h
 LIB_H += wt-status.h
 
 LIB_OBJS += abspath.o
+LIB_OBJS += advice.o
 LIB_OBJS += alias.o
 LIB_OBJS += alloc.o
 LIB_OBJS += archive.o
@@ -532,6 +532,7 @@ LIB_OBJS += read-cache.o
 LIB_OBJS += reflog-walk.o
 LIB_OBJS += refs.o
 LIB_OBJS += remote.o
+LIB_OBJS += replace_object.o
 LIB_OBJS += rerere.o
 LIB_OBJS += revision.o
 LIB_OBJS += run-command.o
@@ -549,6 +550,7 @@ LIB_OBJS += symlinks.o
 LIB_OBJS += tag.o
 LIB_OBJS += trace.o
 LIB_OBJS += transport.o
+LIB_OBJS += transport-helper.o
 LIB_OBJS += tree-diff.o
 LIB_OBJS += tree.o
 LIB_OBJS += tree-walk.o
@@ -621,6 +623,7 @@ BUILTIN_OBJS += builtin-read-tree.o
 BUILTIN_OBJS += builtin-receive-pack.o
 BUILTIN_OBJS += builtin-reflog.o
 BUILTIN_OBJS += builtin-remote.o
+BUILTIN_OBJS += builtin-replace.o
 BUILTIN_OBJS += builtin-rerere.o
 BUILTIN_OBJS += builtin-reset.o
 BUILTIN_OBJS += builtin-rev-list.o
@@ -638,6 +641,7 @@ BUILTIN_OBJS += builtin-tar-tree.o
 BUILTIN_OBJS += builtin-unpack-objects.o
 BUILTIN_OBJS += builtin-update-index.o
 BUILTIN_OBJS += builtin-update-ref.o
+BUILTIN_OBJS += builtin-update-server-info.o
 BUILTIN_OBJS += builtin-upload-archive.o
 BUILTIN_OBJS += builtin-verify-pack.o
 BUILTIN_OBJS += builtin-verify-tag.o
@@ -706,6 +710,7 @@ ifeq ($(uname_S),SCO_SV)
        TAR = gtar
 endif
 ifeq ($(uname_S),Darwin)
+       NEEDS_CRYPTO_WITH_SSL = YesPlease
        NEEDS_SSL_WITH_CRYPTO = YesPlease
        NEEDS_LIBICONV = YesPlease
        ifeq ($(shell expr "$(uname_R)" : '[15678]\.'),2)
@@ -751,9 +756,6 @@ ifeq ($(uname_S),SunOS)
                NO_C99_FORMAT = YesPlease
                NO_STRTOUMAX = YesPlease
        endif
-       ifdef NO_IPV6
-               NEEDS_RESOLV = YesPlease
-       endif
        INSTALL = /usr/ucb/install
        TAR = gtar
        BASIC_CFLAGS += -D__EXTENSIONS__ -D__sun__ -DHAVE_ALLOCA_H
@@ -922,10 +924,6 @@ else
        NO_PTHREADS = YesPlease
 endif
 endif
-ifneq (,$(findstring arm,$(uname_M)))
-       ARM_SHA1 = YesPlease
-       NO_MKSTEMPS = YesPlease
-endif
 
 -include config.mak.autogen
 -include config.mak
@@ -979,9 +977,7 @@ else
        else
                CURL_LIBCURL = -lcurl
        endif
-       BUILTIN_OBJS += builtin-http-fetch.o
-       EXTLIBS += $(CURL_LIBCURL)
-       LIB_OBJS += http.o http-walker.o
+       PROGRAMS += git-remote-curl$X git-http-fetch$X
        curl_check := $(shell (echo 070908; curl-config --vernum) | sort -r | sed -ne 2p)
        ifeq "$(curl_check)" "070908"
                ifndef NO_EXPAT
@@ -1016,9 +1012,12 @@ ifndef NO_OPENSSL
        else
                OPENSSL_LINK =
        endif
+       ifdef NEEDS_CRYPTO_WITH_SSL
+               OPENSSL_LINK += -lcrypto
+       endif
 else
        BASIC_CFLAGS += -DNO_OPENSSL
-       MOZILLA_SHA1 = 1
+       BLK_SHA1 = 1
        OPENSSL_LIBSSL =
 endif
 ifdef NEEDS_SSL_WITH_CRYPTO
@@ -1167,23 +1166,18 @@ ifdef NO_DEFLATE_BOUND
        BASIC_CFLAGS += -DNO_DEFLATE_BOUND
 endif
 
+ifdef BLK_SHA1
+       SHA1_HEADER = "block-sha1/sha1.h"
+       LIB_OBJS += block-sha1/sha1.o
+else
 ifdef PPC_SHA1
        SHA1_HEADER = "ppc/sha1.h"
        LIB_OBJS += ppc/sha1.o ppc/sha1ppc.o
-else
-ifdef ARM_SHA1
-       SHA1_HEADER = "arm/sha1.h"
-       LIB_OBJS += arm/sha1.o arm/sha1_arm.o
-else
-ifdef MOZILLA_SHA1
-       SHA1_HEADER = "mozilla-sha1/sha1.h"
-       LIB_OBJS += mozilla-sha1/sha1.o
 else
        SHA1_HEADER = <openssl/sha.h>
        EXTLIBS += $(LIB_4_CRYPTO)
 endif
 endif
-endif
 ifdef NO_PERL_MAKEMAKER
        export NO_PERL_MAKEMAKER
 endif
@@ -1257,6 +1251,7 @@ ifndef V
        QUIET_LINK     = @echo '   ' LINK $@;
        QUIET_BUILT_IN = @echo '   ' BUILTIN $@;
        QUIET_GEN      = @echo '   ' GEN $@;
+       QUIET_LNCP     = @echo '   ' LN/CP $@;
        QUIET_SUBDIR0  = +@subdir=
        QUIET_SUBDIR1  = ;$(NO_SUBDIR) echo '   ' SUBDIR $$subdir; \
                         $(MAKE) $(PRINT_DIR) -C $$subdir
@@ -1484,12 +1479,21 @@ git-imap-send$X: imap-send.o $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
                $(LIBS) $(OPENSSL_LINK) $(OPENSSL_LIBSSL)
 
-http.o http-walker.o http-push.o transport.o: http.h
+http.o http-walker.o http-push.o: http.h
+
+http.o http-walker.o: $(LIB_H)
 
+git-http-fetch$X: revision.o http.o http-walker.o http-fetch.o $(GITLIBS)
+       $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
+               $(LIBS) $(CURL_LIBCURL)
 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)
 
+git-remote-curl$X: remote-curl.o http.o http-walker.o $(GITLIBS)
+       $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
+               $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
+
 $(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
 $(patsubst git-%$X,%.o,$(PROGRAMS)) git.o: $(LIB_H) $(wildcard */*.h)
 builtin-revert.o wt-status.o: wt-status.h
index 2dad8b2..b62449d 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes-1.6.4.4.txt
\ No newline at end of file
+Documentation/RelNotes-1.6.5.txt
\ No newline at end of file
index 4bee0ba..b88122c 100644 (file)
--- a/abspath.c
+++ b/abspath.c
@@ -18,7 +18,7 @@ const char *make_absolute_path(const char *path)
 {
        static char bufs[2][PATH_MAX + 1], *buf = bufs[0], *next_buf = bufs[1];
        char cwd[1024] = "";
-       int buf_index = 1, len;
+       int buf_index = 1;
 
        int depth = MAXDEPTH;
        char *last_elem = NULL;
@@ -50,7 +50,7 @@ const char *make_absolute_path(const char *path)
                        die_errno ("Could not get current working directory");
 
                if (last_elem) {
-                       int len = strlen(buf);
+                       size_t len = strlen(buf);
                        if (len + strlen(last_elem) + 2 > PATH_MAX)
                                die ("Too long path name: '%s/%s'",
                                                buf, last_elem);
@@ -61,7 +61,7 @@ const char *make_absolute_path(const char *path)
                }
 
                if (!lstat(buf, &st) && S_ISLNK(st.st_mode)) {
-                       len = readlink(buf, next_buf, PATH_MAX);
+                       ssize_t len = readlink(buf, next_buf, PATH_MAX);
                        if (len < 0)
                                die_errno ("Invalid symlink '%s'", buf);
                        if (PATH_MAX <= len)
diff --git a/advice.c b/advice.c
new file mode 100644 (file)
index 0000000..ae4b1e8
--- /dev/null
+++ b/advice.c
@@ -0,0 +1,27 @@
+#include "cache.h"
+
+int advice_push_nonfastforward = 1;
+int advice_status_hints = 1;
+
+static struct {
+       const char *name;
+       int *preference;
+} advice_config[] = {
+       { "pushnonfastforward", &advice_push_nonfastforward },
+       { "statushints", &advice_status_hints },
+};
+
+int git_default_advice_config(const char *var, const char *value)
+{
+       const char *k = skip_prefix(var, "advice.");
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(advice_config); i++) {
+               if (strcmp(k, advice_config[i].name))
+                       continue;
+               *advice_config[i].preference = git_config_bool(var, value);
+               return 0;
+       }
+
+       return 0;
+}
diff --git a/advice.h b/advice.h
new file mode 100644 (file)
index 0000000..e9df8e0
--- /dev/null
+++ b/advice.h
@@ -0,0 +1,9 @@
+#ifndef ADVICE_H
+#define ADVICE_H
+
+extern int advice_push_nonfastforward;
+extern int advice_status_hints;
+
+int git_default_advice_config(const char *var, const char *value);
+
+#endif /* ADVICE_H */
index 0bca9ca..73b8e8a 100644 (file)
--- a/archive.c
+++ b/archive.c
@@ -283,7 +283,7 @@ static int parse_archive_args(int argc, const char **argv,
                OPT_STRING(0, "format", &format, "fmt", "archive format"),
                OPT_STRING(0, "prefix", &base, "prefix",
                        "prepend prefix to each pathname in the archive"),
-               OPT_STRING(0, "output", &output, "file",
+               OPT_STRING('o', "output", &output, "file",
                        "write the archive to this file"),
                OPT_BOOLEAN(0, "worktree-attributes", &worktree_attributes,
                        "read .gitattributes in working directory"),
diff --git a/arm/sha1.c b/arm/sha1.c
deleted file mode 100644 (file)
index c61ad4a..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * SHA-1 implementation optimized for ARM
- *
- * Copyright:   (C) 2005 by Nicolas Pitre <nico@cam.org>
- * Created:     September 17, 2005
- */
-
-#include <string.h>
-#include "sha1.h"
-
-extern void arm_sha_transform(uint32_t *hash, const unsigned char *data, uint32_t *W);
-
-void arm_SHA1_Init(arm_SHA_CTX *c)
-{
-       c->len = 0;
-       c->hash[0] = 0x67452301;
-       c->hash[1] = 0xefcdab89;
-       c->hash[2] = 0x98badcfe;
-       c->hash[3] = 0x10325476;
-       c->hash[4] = 0xc3d2e1f0;
-}
-
-void arm_SHA1_Update(arm_SHA_CTX *c, const void *p, unsigned long n)
-{
-       uint32_t workspace[80];
-       unsigned int partial;
-       unsigned long done;
-
-       partial = c->len & 0x3f;
-       c->len += n;
-       if ((partial + n) >= 64) {
-               if (partial) {
-                       done = 64 - partial;
-                       memcpy(c->buffer + partial, p, done);
-                       arm_sha_transform(c->hash, c->buffer, workspace);
-                       partial = 0;
-               } else
-                       done = 0;
-               while (n >= done + 64) {
-                       arm_sha_transform(c->hash, p + done, workspace);
-                       done += 64;
-               }
-       } else
-               done = 0;
-       if (n - done)
-               memcpy(c->buffer + partial, p + done, n - done);
-}
-
-void arm_SHA1_Final(unsigned char *hash, arm_SHA_CTX *c)
-{
-       uint64_t bitlen;
-       uint32_t bitlen_hi, bitlen_lo;
-       unsigned int i, offset, padlen;
-       unsigned char bits[8];
-       static const unsigned char padding[64] = { 0x80, };
-
-       bitlen = c->len << 3;
-       offset = c->len & 0x3f;
-       padlen = ((offset < 56) ? 56 : (64 + 56)) - offset;
-       arm_SHA1_Update(c, padding, padlen);
-
-       bitlen_hi = bitlen >> 32;
-       bitlen_lo = bitlen & 0xffffffff;
-       bits[0] = bitlen_hi >> 24;
-       bits[1] = bitlen_hi >> 16;
-       bits[2] = bitlen_hi >> 8;
-       bits[3] = bitlen_hi;
-       bits[4] = bitlen_lo >> 24;
-       bits[5] = bitlen_lo >> 16;
-       bits[6] = bitlen_lo >> 8;
-       bits[7] = bitlen_lo;
-       arm_SHA1_Update(c, bits, 8);
-
-       for (i = 0; i < 5; i++) {
-               uint32_t v = c->hash[i];
-               hash[0] = v >> 24;
-               hash[1] = v >> 16;
-               hash[2] = v >> 8;
-               hash[3] = v;
-               hash += 4;
-       }
-}
diff --git a/arm/sha1.h b/arm/sha1.h
deleted file mode 100644 (file)
index b61b618..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * SHA-1 implementation optimized for ARM
- *
- * Copyright:  (C) 2005 by Nicolas Pitre <nico@cam.org>
- * Created:    September 17, 2005
- */
-
-#include <stdint.h>
-
-typedef struct {
-       uint64_t len;
-       uint32_t hash[5];
-       unsigned char buffer[64];
-} arm_SHA_CTX;
-
-void arm_SHA1_Init(arm_SHA_CTX *c);
-void arm_SHA1_Update(arm_SHA_CTX *c, const void *p, unsigned long n);
-void arm_SHA1_Final(unsigned char *hash, arm_SHA_CTX *c);
-
-#define git_SHA_CTX    arm_SHA_CTX
-#define git_SHA1_Init  arm_SHA1_Init
-#define git_SHA1_Update        arm_SHA1_Update
-#define git_SHA1_Final arm_SHA1_Final
diff --git a/arm/sha1_arm.S b/arm/sha1_arm.S
deleted file mode 100644 (file)
index 41e9263..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- *  SHA transform optimized for ARM
- *
- *  Copyright: (C) 2005 by Nicolas Pitre <nico@cam.org>
- *  Created:   September 17, 2005
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2 as
- *  published by the Free Software Foundation.
- */
-
-       .text
-       .globl  arm_sha_transform
-
-/*
- * void sha_transform(uint32_t *hash, const unsigned char *data, uint32_t *W);
- *
- * note: the "data" pointer may be unaligned.
- */
-
-arm_sha_transform:
-
-       stmfd   sp!, {r4 - r8, lr}
-
-       @ for (i = 0; i < 16; i++)
-       @         W[i] = ntohl(((uint32_t *)data)[i]);
-
-#ifdef __ARMEB__
-       mov     r4, r0
-       mov     r0, r2
-       mov     r2, #64
-       bl      memcpy
-       mov     r2, r0
-       mov     r0, r4
-#else
-       mov     r3, r2
-       mov     lr, #16
-1:     ldrb    r4, [r1], #1
-       ldrb    r5, [r1], #1
-       ldrb    r6, [r1], #1
-       ldrb    r7, [r1], #1
-       subs    lr, lr, #1
-       orr     r5, r5, r4, lsl #8
-       orr     r6, r6, r5, lsl #8
-       orr     r7, r7, r6, lsl #8
-       str     r7, [r3], #4
-       bne     1b
-#endif
-
-       @ for (i = 0; i < 64; i++)
-       @         W[i+16] = ror(W[i+13] ^ W[i+8] ^ W[i+2] ^ W[i], 31);
-
-       sub     r3, r2, #4
-       mov     lr, #64
-2:     ldr     r4, [r3, #4]!
-       subs    lr, lr, #1
-       ldr     r5, [r3, #8]
-       ldr     r6, [r3, #32]
-       ldr     r7, [r3, #52]
-       eor     r4, r4, r5
-       eor     r4, r4, r6
-       eor     r4, r4, r7
-       mov     r4, r4, ror #31
-       str     r4, [r3, #64]
-       bne     2b
-
-       /*
-        * The SHA functions are:
-        *
-        * f1(B,C,D) = (D ^ (B & (C ^ D)))
-        * f2(B,C,D) = (B ^ C ^ D)
-        * f3(B,C,D) = ((B & C) | (D & (B | C)))
-        *
-        * Then the sub-blocks are processed as follows:
-        *
-        * A' = ror(A, 27) + f(B,C,D) + E + K + *W++
-        * B' = A
-        * C' = ror(B, 2)
-        * D' = C
-        * E' = D
-        *
-        * We therefore unroll each loop 5 times to avoid register shuffling.
-        * Also the ror for C (and also D and E which are successivelyderived
-        * from it) is applied in place to cut on an additional mov insn for
-        * each round.
-        */
-
-       .macro  sha_f1, A, B, C, D, E
-       ldr     r3, [r2], #4
-       eor     ip, \C, \D
-       add     \E, r1, \E, ror #2
-       and     ip, \B, ip, ror #2
-       add     \E, \E, \A, ror #27
-       eor     ip, ip, \D, ror #2
-       add     \E, \E, r3
-       add     \E, \E, ip
-       .endm
-
-       .macro  sha_f2, A, B, C, D, E
-       ldr     r3, [r2], #4
-       add     \E, r1, \E, ror #2
-       eor     ip, \B, \C, ror #2
-       add     \E, \E, \A, ror #27
-       eor     ip, ip, \D, ror #2
-       add     \E, \E, r3
-       add     \E, \E, ip
-       .endm
-
-       .macro  sha_f3, A, B, C, D, E
-       ldr     r3, [r2], #4
-       add     \E, r1, \E, ror #2
-       orr     ip, \B, \C, ror #2
-       add     \E, \E, \A, ror #27
-       and     ip, ip, \D, ror #2
-       add     \E, \E, r3
-       and     r3, \B, \C, ror #2
-       orr     ip, ip, r3
-       add     \E, \E, ip
-       .endm
-
-       ldmia   r0, {r4 - r8}
-
-       mov     lr, #4
-       ldr     r1, .L_sha_K + 0
-
-       /* adjust initial values */
-       mov     r6, r6, ror #30
-       mov     r7, r7, ror #30
-       mov     r8, r8, ror #30
-
-3:     subs    lr, lr, #1
-       sha_f1  r4, r5, r6, r7, r8
-       sha_f1  r8, r4, r5, r6, r7
-       sha_f1  r7, r8, r4, r5, r6
-       sha_f1  r6, r7, r8, r4, r5
-       sha_f1  r5, r6, r7, r8, r4
-       bne     3b
-
-       ldr     r1, .L_sha_K + 4
-       mov     lr, #4
-
-4:     subs    lr, lr, #1
-       sha_f2  r4, r5, r6, r7, r8
-       sha_f2  r8, r4, r5, r6, r7
-       sha_f2  r7, r8, r4, r5, r6
-       sha_f2  r6, r7, r8, r4, r5
-       sha_f2  r5, r6, r7, r8, r4
-       bne     4b
-
-       ldr     r1, .L_sha_K + 8
-       mov     lr, #4
-
-5:     subs    lr, lr, #1
-       sha_f3  r4, r5, r6, r7, r8
-       sha_f3  r8, r4, r5, r6, r7
-       sha_f3  r7, r8, r4, r5, r6
-       sha_f3  r6, r7, r8, r4, r5
-       sha_f3  r5, r6, r7, r8, r4
-       bne     5b
-
-       ldr     r1, .L_sha_K + 12
-       mov     lr, #4
-
-6:     subs    lr, lr, #1
-       sha_f2  r4, r5, r6, r7, r8
-       sha_f2  r8, r4, r5, r6, r7
-       sha_f2  r7, r8, r4, r5, r6
-       sha_f2  r6, r7, r8, r4, r5
-       sha_f2  r5, r6, r7, r8, r4
-       bne     6b
-
-       ldmia   r0, {r1, r2, r3, ip, lr}
-       add     r4, r1, r4
-       add     r5, r2, r5
-       add     r6, r3, r6, ror #2
-       add     r7, ip, r7, ror #2
-       add     r8, lr, r8, ror #2
-       stmia   r0, {r4 - r8}
-
-       ldmfd   sp!, {r4 - r8, pc}
-
-.L_sha_K:
-       .word   0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6
diff --git a/block-sha1/sha1.c b/block-sha1/sha1.c
new file mode 100644 (file)
index 0000000..d893475
--- /dev/null
@@ -0,0 +1,282 @@
+/*
+ * SHA1 routine optimized to do word accesses rather than byte accesses,
+ * and to avoid unnecessary copies into the context array.
+ *
+ * This was initially based on the Mozilla SHA1 implementation, although
+ * none of the original Mozilla code remains.
+ */
+
+/* this is only to get definitions for memcpy(), ntohl() and htonl() */
+#include "../git-compat-util.h"
+
+#include "sha1.h"
+
+#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+
+/*
+ * Force usage of rol or ror by selecting the one with the smaller constant.
+ * It _can_ generate slightly smaller code (a constant of 1 is special), but
+ * perhaps more importantly it's possibly faster on any uarch that does a
+ * rotate with a loop.
+ */
+
+#define SHA_ASM(op, x, n) ({ unsigned int __res; __asm__(op " %1,%0":"=r" (__res):"i" (n), "0" (x)); __res; })
+#define SHA_ROL(x,n)   SHA_ASM("rol", x, n)
+#define SHA_ROR(x,n)   SHA_ASM("ror", x, n)
+
+#else
+
+#define SHA_ROT(X,l,r) (((X) << (l)) | ((X) >> (r)))
+#define SHA_ROL(X,n)   SHA_ROT(X,n,32-(n))
+#define SHA_ROR(X,n)   SHA_ROT(X,32-(n),n)
+
+#endif
+
+/*
+ * If you have 32 registers or more, the compiler can (and should)
+ * try to change the array[] accesses into registers. However, on
+ * machines with less than ~25 registers, that won't really work,
+ * and at least gcc will make an unholy mess of it.
+ *
+ * So to avoid that mess which just slows things down, we force
+ * the stores to memory to actually happen (we might be better off
+ * with a 'W(t)=(val);asm("":"+m" (W(t))' there instead, as
+ * suggested by Artur Skawina - that will also make gcc unable to
+ * try to do the silly "optimize away loads" part because it won't
+ * see what the value will be).
+ *
+ * Ben Herrenschmidt reports that on PPC, the C version comes close
+ * to the optimized asm with this (ie on PPC you don't want that
+ * 'volatile', since there are lots of registers).
+ *
+ * On ARM we get the best code generation by forcing a full memory barrier
+ * between each SHA_ROUND, otherwise gcc happily get wild with spilling and
+ * the stack frame size simply explode and performance goes down the drain.
+ */
+
+#if defined(__i386__) || defined(__x86_64__)
+  #define setW(x, val) (*(volatile unsigned int *)&W(x) = (val))
+#elif defined(__GNUC__) && defined(__arm__)
+  #define setW(x, val) do { W(x) = (val); __asm__("":::"memory"); } while (0)
+#else
+  #define setW(x, val) (W(x) = (val))
+#endif
+
+/*
+ * Performance might be improved if the CPU architecture is OK with
+ * unaligned 32-bit loads and a fast ntohl() is available.
+ * Otherwise fall back to byte loads and shifts which is portable,
+ * and is faster on architectures with memory alignment issues.
+ */
+
+#if defined(__i386__) || defined(__x86_64__) || \
+    defined(__ppc__) || defined(__ppc64__) || \
+    defined(__powerpc__) || defined(__powerpc64__) || \
+    defined(__s390__) || defined(__s390x__)
+
+#define get_be32(p)    ntohl(*(unsigned int *)(p))
+#define put_be32(p, v) do { *(unsigned int *)(p) = htonl(v); } while (0)
+
+#else
+
+#define get_be32(p)    ( \
+       (*((unsigned char *)(p) + 0) << 24) | \
+       (*((unsigned char *)(p) + 1) << 16) | \
+       (*((unsigned char *)(p) + 2) <<  8) | \
+       (*((unsigned char *)(p) + 3) <<  0) )
+#define put_be32(p, v) do { \
+       unsigned int __v = (v); \
+       *((unsigned char *)(p) + 0) = __v >> 24; \
+       *((unsigned char *)(p) + 1) = __v >> 16; \
+       *((unsigned char *)(p) + 2) = __v >>  8; \
+       *((unsigned char *)(p) + 3) = __v >>  0; } while (0)
+
+#endif
+
+/* This "rolls" over the 512-bit array */
+#define W(x) (array[(x)&15])
+
+/*
+ * Where do we get the source from? The first 16 iterations get it from
+ * the input data, the next mix it from the 512-bit array.
+ */
+#define SHA_SRC(t) get_be32(data + t)
+#define SHA_MIX(t) SHA_ROL(W(t+13) ^ W(t+8) ^ W(t+2) ^ W(t), 1)
+
+#define SHA_ROUND(t, input, fn, constant, A, B, C, D, E) do { \
+       unsigned int TEMP = input(t); setW(t, TEMP); \
+       E += TEMP + SHA_ROL(A,5) + (fn) + (constant); \
+       B = SHA_ROR(B, 2); } while (0)
+
+#define T_0_15(t, A, B, C, D, E)  SHA_ROUND(t, SHA_SRC, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E )
+#define T_16_19(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E )
+#define T_20_39(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0x6ed9eba1, A, B, C, D, E )
+#define T_40_59(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, ((B&C)+(D&(B^C))) , 0x8f1bbcdc, A, B, C, D, E )
+#define T_60_79(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) ,  0xca62c1d6, A, B, C, D, E )
+
+static void blk_SHA1_Block(blk_SHA_CTX *ctx, const unsigned int *data)
+{
+       unsigned int A,B,C,D,E;
+       unsigned int array[16];
+
+       A = ctx->H[0];
+       B = ctx->H[1];
+       C = ctx->H[2];
+       D = ctx->H[3];
+       E = ctx->H[4];
+
+       /* Round 1 - iterations 0-16 take their input from 'data' */
+       T_0_15( 0, A, B, C, D, E);
+       T_0_15( 1, E, A, B, C, D);
+       T_0_15( 2, D, E, A, B, C);
+       T_0_15( 3, C, D, E, A, B);
+       T_0_15( 4, B, C, D, E, A);
+       T_0_15( 5, A, B, C, D, E);
+       T_0_15( 6, E, A, B, C, D);
+       T_0_15( 7, D, E, A, B, C);
+       T_0_15( 8, C, D, E, A, B);
+       T_0_15( 9, B, C, D, E, A);
+       T_0_15(10, A, B, C, D, E);
+       T_0_15(11, E, A, B, C, D);
+       T_0_15(12, D, E, A, B, C);
+       T_0_15(13, C, D, E, A, B);
+       T_0_15(14, B, C, D, E, A);
+       T_0_15(15, A, B, C, D, E);
+
+       /* Round 1 - tail. Input from 512-bit mixing array */
+       T_16_19(16, E, A, B, C, D);
+       T_16_19(17, D, E, A, B, C);
+       T_16_19(18, C, D, E, A, B);
+       T_16_19(19, B, C, D, E, A);
+
+       /* Round 2 */
+       T_20_39(20, A, B, C, D, E);
+       T_20_39(21, E, A, B, C, D);
+       T_20_39(22, D, E, A, B, C);
+       T_20_39(23, C, D, E, A, B);
+       T_20_39(24, B, C, D, E, A);
+       T_20_39(25, A, B, C, D, E);
+       T_20_39(26, E, A, B, C, D);
+       T_20_39(27, D, E, A, B, C);
+       T_20_39(28, C, D, E, A, B);
+       T_20_39(29, B, C, D, E, A);
+       T_20_39(30, A, B, C, D, E);
+       T_20_39(31, E, A, B, C, D);
+       T_20_39(32, D, E, A, B, C);
+       T_20_39(33, C, D, E, A, B);
+       T_20_39(34, B, C, D, E, A);
+       T_20_39(35, A, B, C, D, E);
+       T_20_39(36, E, A, B, C, D);
+       T_20_39(37, D, E, A, B, C);
+       T_20_39(38, C, D, E, A, B);
+       T_20_39(39, B, C, D, E, A);
+
+       /* Round 3 */
+       T_40_59(40, A, B, C, D, E);
+       T_40_59(41, E, A, B, C, D);
+       T_40_59(42, D, E, A, B, C);
+       T_40_59(43, C, D, E, A, B);
+       T_40_59(44, B, C, D, E, A);
+       T_40_59(45, A, B, C, D, E);
+       T_40_59(46, E, A, B, C, D);
+       T_40_59(47, D, E, A, B, C);
+       T_40_59(48, C, D, E, A, B);
+       T_40_59(49, B, C, D, E, A);
+       T_40_59(50, A, B, C, D, E);
+       T_40_59(51, E, A, B, C, D);
+       T_40_59(52, D, E, A, B, C);
+       T_40_59(53, C, D, E, A, B);
+       T_40_59(54, B, C, D, E, A);
+       T_40_59(55, A, B, C, D, E);
+       T_40_59(56, E, A, B, C, D);
+       T_40_59(57, D, E, A, B, C);
+       T_40_59(58, C, D, E, A, B);
+       T_40_59(59, B, C, D, E, A);
+
+       /* Round 4 */
+       T_60_79(60, A, B, C, D, E);
+       T_60_79(61, E, A, B, C, D);
+       T_60_79(62, D, E, A, B, C);
+       T_60_79(63, C, D, E, A, B);
+       T_60_79(64, B, C, D, E, A);
+       T_60_79(65, A, B, C, D, E);
+       T_60_79(66, E, A, B, C, D);
+       T_60_79(67, D, E, A, B, C);
+       T_60_79(68, C, D, E, A, B);
+       T_60_79(69, B, C, D, E, A);
+       T_60_79(70, A, B, C, D, E);
+       T_60_79(71, E, A, B, C, D);
+       T_60_79(72, D, E, A, B, C);
+       T_60_79(73, C, D, E, A, B);
+       T_60_79(74, B, C, D, E, A);
+       T_60_79(75, A, B, C, D, E);
+       T_60_79(76, E, A, B, C, D);
+       T_60_79(77, D, E, A, B, C);
+       T_60_79(78, C, D, E, A, B);
+       T_60_79(79, B, C, D, E, A);
+
+       ctx->H[0] += A;
+       ctx->H[1] += B;
+       ctx->H[2] += C;
+       ctx->H[3] += D;
+       ctx->H[4] += E;
+}
+
+void blk_SHA1_Init(blk_SHA_CTX *ctx)
+{
+       ctx->size = 0;
+
+       /* Initialize H with the magic constants (see FIPS180 for constants) */
+       ctx->H[0] = 0x67452301;
+       ctx->H[1] = 0xefcdab89;
+       ctx->H[2] = 0x98badcfe;
+       ctx->H[3] = 0x10325476;
+       ctx->H[4] = 0xc3d2e1f0;
+}
+
+void blk_SHA1_Update(blk_SHA_CTX *ctx, const void *data, unsigned long len)
+{
+       int lenW = ctx->size & 63;
+
+       ctx->size += len;
+
+       /* Read the data into W and process blocks as they get full */
+       if (lenW) {
+               int left = 64 - lenW;
+               if (len < left)
+                       left = len;
+               memcpy(lenW + (char *)ctx->W, data, left);
+               lenW = (lenW + left) & 63;
+               len -= left;
+               data = ((const char *)data + left);
+               if (lenW)
+                       return;
+               blk_SHA1_Block(ctx, ctx->W);
+       }
+       while (len >= 64) {
+               blk_SHA1_Block(ctx, data);
+               data = ((const char *)data + 64);
+               len -= 64;
+       }
+       if (len)
+               memcpy(ctx->W, data, len);
+}
+
+void blk_SHA1_Final(unsigned char hashout[20], blk_SHA_CTX *ctx)
+{
+       static const unsigned char pad[64] = { 0x80 };
+       unsigned int padlen[2];
+       int i;
+
+       /* Pad with a binary 1 (ie 0x80), then zeroes, then length */
+       padlen[0] = htonl(ctx->size >> 29);
+       padlen[1] = htonl(ctx->size << 3);
+
+       i = ctx->size & 63;
+       blk_SHA1_Update(ctx, pad, 1+ (63 & (55 - i)));
+       blk_SHA1_Update(ctx, padlen, 8);
+
+       /* Output hash */
+       for (i = 0; i < 5; i++)
+               put_be32(hashout + i*4, ctx->H[i]);
+}
diff --git a/block-sha1/sha1.h b/block-sha1/sha1.h
new file mode 100644 (file)
index 0000000..b864df6
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * SHA1 routine optimized to do word accesses rather than byte accesses,
+ * and to avoid unnecessary copies into the context array.
+ *
+ * This was initially based on the Mozilla SHA1 implementation, although
+ * none of the original Mozilla code remains.
+ */
+
+typedef struct {
+       unsigned long long size;
+       unsigned int H[5];
+       unsigned int W[16];
+} blk_SHA_CTX;
+
+void blk_SHA1_Init(blk_SHA_CTX *ctx);
+void blk_SHA1_Update(blk_SHA_CTX *ctx, const void *dataIn, unsigned long len);
+void blk_SHA1_Final(unsigned char hashout[20], blk_SHA_CTX *ctx);
+
+#define git_SHA_CTX    blk_SHA_CTX
+#define git_SHA1_Init  blk_SHA1_Init
+#define git_SHA1_Update        blk_SHA1_Update
+#define git_SHA1_Final blk_SHA1_Final
index 581a2a1..cb6e590 100644 (file)
@@ -105,8 +105,8 @@ static void refresh(int verbose, const char **pathspec)
        for (specs = 0; pathspec[specs];  specs++)
                /* nothing */;
        seen = xcalloc(specs, 1);
-       refresh_index(&the_index, verbose ? REFRESH_SAY_CHANGED : REFRESH_QUIET,
-                     pathspec, seen);
+       refresh_index(&the_index, verbose ? REFRESH_IN_PORCELAIN : REFRESH_QUIET,
+                     pathspec, seen, "Unstaged changes after refreshing the index:");
        for (i = 0; i < specs; i++) {
                if (!seen[i])
                        die("pathspec '%s' did not match any files", pathspec[i]);
@@ -131,27 +131,27 @@ static const char **validate_pathspec(int argc, const char **argv, const char *p
        return pathspec;
 }
 
-int interactive_add(int argc, const char **argv, const char *prefix)
+int run_add_interactive(const char *revision, const char *patch_mode,
+                       const char **pathspec)
 {
-       int status, ac;
+       int status, ac, pc = 0;
        const char **args;
-       const char **pathspec = NULL;
 
-       if (argc) {
-               pathspec = validate_pathspec(argc, argv, prefix);
-               if (!pathspec)
-                       return -1;
-       }
+       if (pathspec)
+               while (pathspec[pc])
+                       pc++;
 
-       args = xcalloc(sizeof(const char *), (argc + 4));
+       args = xcalloc(sizeof(const char *), (pc + 5));
        ac = 0;
        args[ac++] = "add--interactive";
-       if (patch_interactive)
-               args[ac++] = "--patch";
+       if (patch_mode)
+               args[ac++] = patch_mode;
+       if (revision)
+               args[ac++] = revision;
        args[ac++] = "--";
-       if (argc) {
-               memcpy(&(args[ac]), pathspec, sizeof(const char *) * argc);
-               ac += argc;
+       if (pc) {
+               memcpy(&(args[ac]), pathspec, sizeof(const char *) * pc);
+               ac += pc;
        }
        args[ac] = NULL;
 
@@ -160,6 +160,21 @@ int interactive_add(int argc, const char **argv, const char *prefix)
        return status;
 }
 
+int interactive_add(int argc, const char **argv, const char *prefix)
+{
+       const char **pathspec = NULL;
+
+       if (argc) {
+               pathspec = validate_pathspec(argc, argv, prefix);
+               if (!pathspec)
+                       return -1;
+       }
+
+       return run_add_interactive(NULL,
+                                  patch_interactive ? "--patch" : NULL,
+                                  pathspec);
+}
+
 static int edit_patch(int argc, const char **argv, const char *prefix)
 {
        char *file = xstrdup(git_path("ADD_EDIT.patch"));
@@ -183,7 +198,7 @@ static int edit_patch(int argc, const char **argv, const char *prefix)
        out = open(file, O_CREAT | O_WRONLY, 0644);
        if (out < 0)
                die ("Could not open '%s' for writing.", file);
-       rev.diffopt.file = fdopen(out, "w");
+       rev.diffopt.file = xfdopen(out, "w");
        rev.diffopt.close_file = 1;
        if (run_diff_files(&rev, 0))
                die ("Could not write patch");
index 39dc96a..c8372a0 100644 (file)
@@ -61,6 +61,13 @@ static enum ws_error_action {
 static int whitespace_error;
 static int squelch_whitespace_errors = 5;
 static int applied_after_fixing_ws;
+
+static enum ws_ignore {
+       ignore_ws_none,
+       ignore_ws_change,
+} ws_ignore_action = ignore_ws_none;
+
+
 static const char *patch_input_file;
 static const char *root;
 static int root_len;
@@ -97,6 +104,21 @@ static void parse_whitespace_option(const char *option)
        die("unrecognized whitespace option '%s'", option);
 }
 
+static void parse_ignorewhitespace_option(const char *option)
+{
+       if (!option || !strcmp(option, "no") ||
+           !strcmp(option, "false") || !strcmp(option, "never") ||
+           !strcmp(option, "none")) {
+               ws_ignore_action = ignore_ws_none;
+               return;
+       }
+       if (!strcmp(option, "change")) {
+               ws_ignore_action = ignore_ws_change;
+               return;
+       }
+       die("unrecognized whitespace ignore option '%s'", option);
+}
+
 static void set_default_whitespace_mode(const char *whitespace_option)
 {
        if (!whitespace_option && !apply_default_whitespace)
@@ -214,6 +236,62 @@ static uint32_t hash_line(const char *cp, size_t len)
        return h;
 }
 
+/*
+ * Compare lines s1 of length n1 and s2 of length n2, ignoring
+ * whitespace difference. Returns 1 if they match, 0 otherwise
+ */
+static int fuzzy_matchlines(const char *s1, size_t n1,
+                           const char *s2, size_t n2)
+{
+       const char *last1 = s1 + n1 - 1;
+       const char *last2 = s2 + n2 - 1;
+       int result = 0;
+
+       if (n1 < 0 || n2 < 0)
+               return 0;
+
+       /* ignore line endings */
+       while ((*last1 == '\r') || (*last1 == '\n'))
+               last1--;
+       while ((*last2 == '\r') || (*last2 == '\n'))
+               last2--;
+
+       /* skip leading whitespace */
+       while (isspace(*s1) && (s1 <= last1))
+               s1++;
+       while (isspace(*s2) && (s2 <= last2))
+               s2++;
+       /* early return if both lines are empty */
+       if ((s1 > last1) && (s2 > last2))
+               return 1;
+       while (!result) {
+               result = *s1++ - *s2++;
+               /*
+                * Skip whitespace inside. We check for whitespace on
+                * both buffers because we don't want "a b" to match
+                * "ab"
+                */
+               if (isspace(*s1) && isspace(*s2)) {
+                       while (isspace(*s1) && s1 <= last1)
+                               s1++;
+                       while (isspace(*s2) && s2 <= last2)
+                               s2++;
+               }
+               /*
+                * If we reached the end on one side only,
+                * lines don't match
+                */
+               if (
+                   ((s2 > last2) && (s1 <= last1)) ||
+                   ((s1 > last1) && (s2 <= last2)))
+                       return 0;
+               if ((s1 > last1) && (s2 > last2))
+                       break;
+       }
+
+       return !result;
+}
+
 static void add_line_info(struct image *img, const char *bol, size_t len, unsigned flag)
 {
        ALLOC_GROW(img->line_allocated, img->nr + 1, img->alloc);
@@ -1672,10 +1750,17 @@ static int read_old_data(struct stat *st, const char *path, struct strbuf *buf)
        }
 }
 
+/*
+ * Update the preimage, and the common lines in postimage,
+ * from buffer buf of length len. If postlen is 0 the postimage
+ * is updated in place, otherwise it's updated on a new buffer
+ * of length postlen
+ */
+
 static void update_pre_post_images(struct image *preimage,
                                   struct image *postimage,
                                   char *buf,
-                                  size_t len)
+                                  size_t len, size_t postlen)
 {
        int i, ctx;
        char *new, *old, *fixed;
@@ -1694,11 +1779,19 @@ static void update_pre_post_images(struct image *preimage,
        *preimage = fixed_preimage;
 
        /*
-        * Adjust the common context lines in postimage, in place.
-        * This is possible because whitespace fixing does not make
-        * the string grow.
+        * Adjust the common context lines in postimage. This can be
+        * done in-place when we are just doing whitespace fixing,
+        * which does not make the string grow, but needs a new buffer
+        * when ignoring whitespace causes the update, since in this case
+        * we could have e.g. tabs converted to multiple spaces.
+        * We trust the caller to tell us if the update can be done
+        * in place (postlen==0) or not.
         */
-       new = old = postimage->buf;
+       old = postimage->buf;
+       if (postlen)
+               new = postimage->buf = xmalloc(postlen);
+       else
+               new = old;
        fixed = preimage->buf;
        for (i = ctx = 0; i < postimage->nr; i++) {
                size_t len = postimage->line[i].len;
@@ -1773,12 +1866,56 @@ static int match_fragment(struct image *img,
            !memcmp(img->buf + try, preimage->buf, preimage->len))
                return 1;
 
+       /*
+        * No exact match. If we are ignoring whitespace, run a line-by-line
+        * fuzzy matching. We collect all the line length information because
+        * we need it to adjust whitespace if we match.
+        */
+       if (ws_ignore_action == ignore_ws_change) {
+               size_t imgoff = 0;
+               size_t preoff = 0;
+               size_t postlen = postimage->len;
+               for (i = 0; i < preimage->nr; i++) {
+                       size_t prelen = preimage->line[i].len;
+                       size_t imglen = img->line[try_lno+i].len;
+
+                       if (!fuzzy_matchlines(img->buf + try + imgoff, imglen,
+                                             preimage->buf + preoff, prelen))
+                               return 0;
+                       if (preimage->line[i].flag & LINE_COMMON)
+                               postlen += imglen - prelen;
+                       imgoff += imglen;
+                       preoff += prelen;
+               }
+
+               /*
+                * Ok, the preimage matches with whitespace fuzz. Update it and
+                * the common postimage lines to use the same whitespace as the
+                * target. imgoff now holds the true length of the target that
+                * matches the preimage, and we need to update the line lengths
+                * of the preimage to match the target ones.
+                */
+               fixed_buf = xmalloc(imgoff);
+               memcpy(fixed_buf, img->buf + try, imgoff);
+               for (i = 0; i < preimage->nr; i++)
+                       preimage->line[i].len = img->line[try_lno+i].len;
+
+               /*
+                * Update the preimage buffer and the postimage context lines.
+                */
+               update_pre_post_images(preimage, postimage,
+                               fixed_buf, imgoff, postlen);
+               return 1;
+       }
+
        if (ws_error_action != correct_ws_error)
                return 0;
 
        /*
         * The hunk does not apply byte-by-byte, but the hash says
-        * it might with whitespace fuzz.
+        * it might with whitespace fuzz. We haven't been asked to
+        * ignore whitespace, we were asked to correct whitespace
+        * errors, so let's try matching after whitespace correction.
         */
        fixed_buf = xmalloc(preimage->len + 1);
        buf = fixed_buf;
@@ -1830,7 +1967,7 @@ static int match_fragment(struct image *img,
         * hunk match.  Update the context lines in the postimage.
         */
        update_pre_post_images(preimage, postimage,
-                              fixed_buf, buf - fixed_buf);
+                              fixed_buf, buf - fixed_buf, 0);
        return 1;
 
  unmatch_exit:
@@ -3272,6 +3409,8 @@ static int git_apply_config(const char *var, const char *value, void *cb)
 {
        if (!strcmp(var, "apply.whitespace"))
                return git_config_string(&apply_default_whitespace, var, value);
+       else if (!strcmp(var, "apply.ignorewhitespace"))
+               return git_config_string(&apply_default_ignorewhitespace, var, value);
        return git_default_config(var, value, cb);
 }
 
@@ -3308,6 +3447,16 @@ static int option_parse_z(const struct option *opt,
        return 0;
 }
 
+static int option_parse_space_change(const struct option *opt,
+                         const char *arg, int unset)
+{
+       if (unset)
+               ws_ignore_action = ignore_ws_none;
+       else
+               ws_ignore_action = ignore_ws_change;
+       return 0;
+}
+
 static int option_parse_whitespace(const struct option *opt,
                                   const char *arg, int unset)
 {
@@ -3384,6 +3533,12 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
                { OPTION_CALLBACK, 0, "whitespace", &whitespace_option, "action",
                        "detect new or modified lines that have whitespace errors",
                        0, option_parse_whitespace },
+               { OPTION_CALLBACK, 0, "ignore-space-change", NULL, NULL,
+                       "ignore changes in whitespace when finding context",
+                       PARSE_OPT_NOARG, option_parse_space_change },
+               { OPTION_CALLBACK, 0, "ignore-whitespace", NULL, NULL,
+                       "ignore changes in whitespace when finding context",
+                       PARSE_OPT_NOARG, option_parse_space_change },
                OPT_BOOLEAN('R', "reverse", &apply_in_reverse,
                        "apply the patch in reverse"),
                OPT_BOOLEAN(0, "unidiff-zero", &unidiff_zero,
@@ -3408,6 +3563,8 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
        git_config(git_apply_config, NULL);
        if (apply_default_whitespace)
                parse_whitespace_option(apply_default_whitespace);
+       if (apply_default_ignorewhitespace)
+               parse_ignorewhitespace_option(apply_default_ignorewhitespace);
 
        argc = parse_options(argc, argv, prefix, builtin_apply_options,
                        apply_usage, 0);
index f9a4bea..12351e9 100644 (file)
@@ -60,6 +60,17 @@ static int run_remote_archiver(int argc, const char **argv,
        return !!rv;
 }
 
+static const char *format_from_name(const char *filename)
+{
+       const char *ext = strrchr(filename, '.');
+       if (!ext)
+               return NULL;
+       ext++;
+       if (!strcasecmp(ext, "zip"))
+               return "zip";
+       return NULL;
+}
+
 #define PARSE_OPT_KEEP_ALL ( PARSE_OPT_KEEP_DASHDASH |         \
                             PARSE_OPT_KEEP_ARGV0 |     \
                             PARSE_OPT_KEEP_UNKNOWN |   \
@@ -70,21 +81,39 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
        const char *exec = "git-upload-archive";
        const char *output = NULL;
        const char *remote = NULL;
+       const char *format = NULL;
        struct option local_opts[] = {
-               OPT_STRING(0, "output", &output, "file",
+               OPT_STRING('o', "output", &output, "file",
                        "write the archive to this file"),
                OPT_STRING(0, "remote", &remote, "repo",
                        "retrieve the archive from remote repository <repo>"),
                OPT_STRING(0, "exec", &exec, "cmd",
                        "path to the remote git-upload-archive command"),
+               OPT_STRING(0, "format", &format, "fmt", "archive format"),
                OPT_END()
        };
+       char fmt_opt[32];
 
        argc = parse_options(argc, argv, prefix, local_opts, NULL,
                             PARSE_OPT_KEEP_ALL);
 
-       if (output)
+       if (output) {
                create_output_file(output);
+               if (!format)
+                       format = format_from_name(output);
+       }
+
+       if (format) {
+               sprintf(fmt_opt, "--format=%s", format);
+               /*
+                * This is safe because either --format and/or --output must
+                * have been given on the original command line if we get to
+                * this point, and parse_options() must have eaten at least
+                * one argument, i.e. we have enough room to append to argv[].
+                */
+               argv[argc++] = fmt_opt;
+               argv[argc] = NULL;
+       }
 
        if (remote)
                return run_remote_archiver(argc, argv, remote, exec);
index fd6ca51..7512773 100644 (file)
@@ -1348,7 +1348,7 @@ static void get_ac_line(const char *inbuf, const char *what,
        /*
         * Now, convert both name and e-mail using mailmap
         */
-       if(map_user(&mailmap, mail+1, mail_len-1, person, tmp-person-1)) {
+       if (map_user(&mailmap, mail+1, mail_len-1, person, tmp-person-1)) {
                /* Add a trailing '>' to email, since map_user returns plain emails
                   Note: It already has '<', since we replace from mail+1 */
                mailpos = memchr(mail, '\0', mail_len);
index 1a03d5f..9f57992 100644 (file)
@@ -586,7 +586,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
                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_BOOLEAN('f', "force", &force_create, "force creation (when already exists)"),
                {
                        OPTION_CALLBACK, 0, "no-merged", &merge_filter_ref,
                        "commit", "print only not merged branches",
index c6d6ac9..d050c37 100644 (file)
@@ -566,6 +566,13 @@ static int git_checkout_config(const char *var, const char *value, void *cb)
        return git_xmerge_config(var, value, cb);
 }
 
+static int interactive_checkout(const char *revision, const char **pathspec,
+                               struct checkout_opts *opts)
+{
+       return run_add_interactive(revision, "--patch=checkout", pathspec);
+}
+
+
 int cmd_checkout(int argc, const char **argv, const char *prefix)
 {
        struct checkout_opts opts;
@@ -574,6 +581,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
        struct branch_info new;
        struct tree *source_tree = NULL;
        char *conflict_style = NULL;
+       int patch_mode = 0;
        struct option options[] = {
                OPT__QUIET(&opts.quiet),
                OPT_STRING('b', NULL, &opts.new_branch, "new branch", "branch"),
@@ -584,10 +592,11 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
                            2),
                OPT_SET_INT('3', "theirs", &opts.writeout_stage, "stage",
                            3),
-               OPT_BOOLEAN('f', NULL, &opts.force, "force"),
+               OPT_BOOLEAN('f', "force", &opts.force, "force"),
                OPT_BOOLEAN('m', "merge", &opts.merge, "merge"),
                OPT_STRING(0, "conflict", &conflict_style, "style",
                           "conflict style (merge or diff3)"),
+               OPT_BOOLEAN('p', "patch", &patch_mode, "select hunks interactively"),
                OPT_END(),
        };
        int has_dash_dash;
@@ -602,6 +611,10 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
        argc = parse_options(argc, argv, prefix, options, checkout_usage,
                             PARSE_OPT_KEEP_DASHDASH);
 
+       if (patch_mode && (opts.track > 0 || opts.new_branch
+                          || opts.new_branch_log || opts.merge || opts.force))
+               die ("--patch is incompatible with all other options");
+
        /* --track without -b should DWIM */
        if (0 < opts.track && !opts.new_branch) {
                const char *argv0 = argv[0];
@@ -708,6 +721,9 @@ no_reference:
                if (!pathspec)
                        die("invalid path specification");
 
+               if (patch_mode)
+                       return interactive_checkout(new.name, pathspec, &opts);
+
                /* Checkout paths */
                if (opts.new_branch) {
                        if (argc == 1) {
@@ -723,6 +739,9 @@ no_reference:
                return checkout_paths(source_tree, pathspec, &opts);
        }
 
+       if (patch_mode)
+               return interactive_checkout(new.name, NULL, &opts);
+
        if (opts.new_branch) {
                struct strbuf buf = STRBUF_INIT;
                if (strbuf_check_branch_ref(&buf, opts.new_branch))
index 05c763c..28cdcd0 100644 (file)
@@ -41,7 +41,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
        struct option options[] = {
                OPT__QUIET(&quiet),
                OPT__DRY_RUN(&show_only),
-               OPT_BOOLEAN('f', NULL, &force, "force"),
+               OPT_BOOLEAN('f', "force", &force, "force"),
                OPT_BOOLEAN('d', NULL, &remove_directories,
                                "remove whole directories"),
                OPT_BOOLEAN('x', NULL, &ignored, "remove ignored files, too"),
index e51978a..bab2d84 100644 (file)
@@ -38,9 +38,10 @@ static const char * const builtin_clone_usage[] = {
 };
 
 static int option_quiet, option_no_checkout, option_bare, option_mirror;
-static int option_local, option_no_hardlinks, option_shared;
+static int option_local, option_no_hardlinks, option_shared, option_recursive;
 static char *option_template, *option_reference, *option_depth;
 static char *option_origin = NULL;
+static char *option_branch = NULL;
 static char *option_upload_pack = "git-upload-pack";
 static int option_verbose;
 
@@ -59,12 +60,16 @@ static struct option builtin_clone_options[] = {
                    "don't use local hardlinks, always copy"),
        OPT_BOOLEAN('s', "shared", &option_shared,
                    "setup as shared repository"),
+       OPT_BOOLEAN(0, "recursive", &option_recursive,
+                   "setup as shared repository"),
        OPT_STRING(0, "template", &option_template, "path",
                   "path the template repository"),
        OPT_STRING(0, "reference", &option_reference, "repo",
                   "reference repository"),
        OPT_STRING('o', "origin", &option_origin, "branch",
                   "use <branch> instead of 'origin' to track upstream"),
+       OPT_STRING('b', "branch", &option_branch, "branch",
+                  "checkout <branch> instead of the remote's HEAD"),
        OPT_STRING('u', "upload-pack", &option_upload_pack, "path",
                   "path to git-upload-pack on the remote"),
        OPT_STRING(0, "depth", &option_depth, "depth",
@@ -73,6 +78,10 @@ static struct option builtin_clone_options[] = {
        OPT_END()
 };
 
+static const char *argv_submodule[] = {
+       "submodule", "update", "--init", "--recursive", NULL
+};
+
 static char *get_repo_path(const char *repo, int *is_bundle)
 {
        static char *suffix[] = { "/.git", ".git", "" };
@@ -260,7 +269,7 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest)
                                die_errno("failed to create link '%s'", dest->buf);
                        option_no_hardlinks = 1;
                }
-               if (copy_file(dest->buf, src->buf, 0666))
+               if (copy_file_with_time(dest->buf, src->buf, 0666))
                        die_errno("failed to copy file to '%s'", dest->buf);
        }
        closedir(dir);
@@ -347,7 +356,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
        const char *repo_name, *repo, *work_tree, *git_dir;
        char *path, *dir;
        int dest_exists;
-       const struct ref *refs, *head_points_at, *remote_head, *mapped_refs;
+       const struct ref *refs, *remote_head, *mapped_refs;
+       const struct ref *remote_head_points_at;
+       const struct ref *our_head_points_at;
        struct strbuf key = STRBUF_INIT, value = STRBUF_INIT;
        struct strbuf branch_top = STRBUF_INIT, reflog_msg = STRBUF_INIT;
        struct transport *transport = NULL;
@@ -509,7 +520,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
                                             option_upload_pack);
 
                refs = transport_get_remote_refs(transport);
-               if(refs)
+               if (refs)
                        transport_fetch_refs(transport, refs);
        }
 
@@ -519,11 +530,31 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
                mapped_refs = write_remote_refs(refs, refspec, reflog_msg.buf);
 
                remote_head = find_ref_by_name(refs, "HEAD");
-               head_points_at = guess_remote_head(remote_head, mapped_refs, 0);
+               remote_head_points_at =
+                       guess_remote_head(remote_head, mapped_refs, 0);
+
+               if (option_branch) {
+                       struct strbuf head = STRBUF_INIT;
+                       strbuf_addstr(&head, src_ref_prefix);
+                       strbuf_addstr(&head, option_branch);
+                       our_head_points_at =
+                               find_ref_by_name(mapped_refs, head.buf);
+                       strbuf_release(&head);
+
+                       if (!our_head_points_at) {
+                               warning("Remote branch %s not found in "
+                                       "upstream %s, using HEAD instead",
+                                       option_branch, option_origin);
+                               our_head_points_at = remote_head_points_at;
+                       }
+               }
+               else
+                       our_head_points_at = remote_head_points_at;
        }
        else {
                warning("You appear to have cloned an empty repository.");
-               head_points_at = NULL;
+               our_head_points_at = NULL;
+               remote_head_points_at = NULL;
                remote_head = NULL;
                option_no_checkout = 1;
                if (!option_bare)
@@ -531,41 +562,35 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
                                              "refs/heads/master");
        }
 
-       if (head_points_at) {
-               /* Local default branch link */
-               create_symref("HEAD", head_points_at->name, NULL);
+       if (remote_head_points_at && !option_bare) {
+               struct strbuf head_ref = STRBUF_INIT;
+               strbuf_addstr(&head_ref, branch_top.buf);
+               strbuf_addstr(&head_ref, "HEAD");
+               create_symref(head_ref.buf,
+                             remote_head_points_at->peer_ref->name,
+                             reflog_msg.buf);
+       }
 
+       if (our_head_points_at) {
+               /* Local default branch link */
+               create_symref("HEAD", our_head_points_at->name, NULL);
                if (!option_bare) {
-                       struct strbuf head_ref = STRBUF_INIT;
-                       const char *head = head_points_at->name;
-
-                       if (!prefixcmp(head, "refs/heads/"))
-                               head += 11;
-
-                       /* Set up the initial local branch */
-
-                       /* Local branch initial value */
+                       const char *head = skip_prefix(our_head_points_at->name,
+                                                      "refs/heads/");
                        update_ref(reflog_msg.buf, "HEAD",
-                                  head_points_at->old_sha1,
+                                  our_head_points_at->old_sha1,
                                   NULL, 0, DIE_ON_ERR);
-
-                       strbuf_addstr(&head_ref, branch_top.buf);
-                       strbuf_addstr(&head_ref, "HEAD");
-
-                       /* Remote branch link */
-                       create_symref(head_ref.buf,
-                                     head_points_at->peer_ref->name,
-                                     reflog_msg.buf);
-
                        install_branch_config(0, head, option_origin,
-                                             head_points_at->name);
+                                             our_head_points_at->name);
                }
        } else if (remote_head) {
                /* Source had detached HEAD pointing somewhere. */
-               if (!option_bare)
+               if (!option_bare) {
                        update_ref(reflog_msg.buf, "HEAD",
                                   remote_head->old_sha1,
                                   NULL, REF_NODEREF, DIE_ON_ERR);
+                       our_head_points_at = remote_head;
+               }
        } else {
                /* Nothing to checkout out */
                if (!option_no_checkout)
@@ -599,7 +624,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
                opts.src_index = &the_index;
                opts.dst_index = &the_index;
 
-               tree = parse_tree_indirect(remote_head->old_sha1);
+               tree = parse_tree_indirect(our_head_points_at->old_sha1);
                parse_tree(tree);
                init_tree_desc(&t, tree->buffer, tree->size);
                unpack_trees(1, &t, &opts);
@@ -610,6 +635,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 
                err |= run_hook(NULL, "post-checkout", sha1_to_hex(null_sha1),
                                sha1_to_hex(remote_head->old_sha1), "1", NULL);
+
+               if (!err && option_recursive)
+                       err = run_command_v_opt(argv_submodule, RUN_GIT_CMD);
        }
 
        strbuf_release(&reflog_msg);
index 4bcce06..200ffda 100644 (file)
@@ -51,7 +51,7 @@ static const char *template_file;
 static char *edit_message, *use_message;
 static char *author_name, *author_email, *author_date;
 static int all, edit_flag, also, interactive, only, amend, signoff;
-static int quiet, verbose, no_verify, allow_empty;
+static int quiet, verbose, no_verify, allow_empty, dry_run;
 static char *untracked_files_arg;
 /*
  * The default commit message cleanup mode will remove the lines
@@ -103,6 +103,7 @@ static struct option builtin_commit_options[] = {
        OPT_BOOLEAN(0, "interactive", &interactive, "interactively add files"),
        OPT_BOOLEAN('o', "only", &only, "commit only specified files"),
        OPT_BOOLEAN('n', "no-verify", &no_verify, "bypass pre-commit hook"),
+       OPT_BOOLEAN(0, "dry-run", &dry_run, "show what would be committed"),
        OPT_BOOLEAN(0, "amend", &amend, "amend previous commit"),
        { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, "mode", "show untracked files, optional modes: all, normal, no. (Default: all)", PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
        OPT_BOOLEAN(0, "allow-empty", &allow_empty, "ok to record an empty change"),
@@ -217,12 +218,15 @@ static void create_base_index(void)
                exit(128); /* We've already reported the error, finish dying */
 }
 
-static char *prepare_index(int argc, const char **argv, const char *prefix)
+static char *prepare_index(int argc, const char **argv, const char *prefix, int is_status)
 {
        int fd;
        struct string_list partial;
        const char **pathspec = NULL;
+       int refresh_flags = REFRESH_QUIET;
 
+       if (is_status)
+               refresh_flags |= REFRESH_UNMERGED;
        if (interactive) {
                if (interactive_add(argc, argv, prefix) != 0)
                        die("interactive add failed");
@@ -253,7 +257,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix)
        if (all || (also && pathspec && *pathspec)) {
                int fd = hold_locked_index(&index_lock, 1);
                add_files_to_cache(also ? prefix : NULL, pathspec, 0);
-               refresh_cache(REFRESH_QUIET);
+               refresh_cache(refresh_flags);
                if (write_cache(fd, active_cache, active_nr) ||
                    close_lock_file(&index_lock))
                        die("unable to write new_index file");
@@ -272,7 +276,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix)
         */
        if (!pathspec || !*pathspec) {
                fd = hold_locked_index(&index_lock, 1);
-               refresh_cache(REFRESH_QUIET);
+               refresh_cache(refresh_flags);
                if (write_cache(fd, active_cache, active_nr) ||
                    commit_locked_index(&index_lock))
                        die("unable to write new_index file");
@@ -339,27 +343,24 @@ static char *prepare_index(int argc, const char **argv, const char *prefix)
        return false_lock.filename;
 }
 
-static int run_status(FILE *fp, const char *index_file, const char *prefix, int nowarn)
+static int run_status(FILE *fp, const char *index_file, const char *prefix, int nowarn,
+                     struct wt_status *s)
 {
-       struct wt_status s;
-
-       wt_status_prepare(&s);
-       if (wt_status_relative_paths)
-               s.prefix = prefix;
+       if (s->relative_paths)
+               s->prefix = prefix;
 
        if (amend) {
-               s.amend = 1;
-               s.reference = "HEAD^1";
+               s->amend = 1;
+               s->reference = "HEAD^1";
        }
-       s.verbose = verbose;
-       s.untracked = (show_untracked_files == SHOW_ALL_UNTRACKED_FILES);
-       s.index_file = index_file;
-       s.fp = fp;
-       s.nowarn = nowarn;
+       s->verbose = verbose;
+       s->index_file = index_file;
+       s->fp = fp;
+       s->nowarn = nowarn;
 
-       wt_status_print(&s);
+       wt_status_print(s);
 
-       return s.commitable;
+       return s->commitable;
 }
 
 static int is_a_merge(const unsigned char *sha1)
@@ -413,7 +414,8 @@ static void determine_author_info(void)
        author_date = date;
 }
 
-static int prepare_to_commit(const char *index_file, const char *prefix)
+static int prepare_to_commit(const char *index_file, const char *prefix,
+                            struct wt_status *s)
 {
        struct stat statbuf;
        int commitable, saved_color_setting;
@@ -555,10 +557,10 @@ static int prepare_to_commit(const char *index_file, const char *prefix)
                if (ident_shown)
                        fprintf(fp, "#\n");
 
-               saved_color_setting = wt_status_use_color;
-               wt_status_use_color = 0;
-               commitable = run_status(fp, index_file, prefix, 1);
-               wt_status_use_color = saved_color_setting;
+               saved_color_setting = s->use_color;
+               s->use_color = 0;
+               commitable = run_status(fp, index_file, prefix, 1, s);
+               s->use_color = saved_color_setting;
        } else {
                unsigned char sha1[20];
                const char *parent = "HEAD";
@@ -579,7 +581,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix)
 
        if (!commitable && !in_merge && !allow_empty &&
            !(amend && is_a_merge(head_sha1))) {
-               run_status(stdout, index_file, prefix, 0);
+               run_status(stdout, index_file, prefix, 0, s);
                return 0;
        }
 
@@ -691,7 +693,8 @@ static const char *find_author_by_nickname(const char *name)
 
 static int parse_and_validate_options(int argc, const char *argv[],
                                      const char * const usage[],
-                                     const char *prefix)
+                                     const char *prefix,
+                                     struct wt_status *s)
 {
        int f = 0;
 
@@ -794,11 +797,11 @@ static int parse_and_validate_options(int argc, const char *argv[],
        if (!untracked_files_arg)
                ; /* default already initialized */
        else if (!strcmp(untracked_files_arg, "no"))
-               show_untracked_files = SHOW_NO_UNTRACKED_FILES;
+               s->show_untracked_files = SHOW_NO_UNTRACKED_FILES;
        else if (!strcmp(untracked_files_arg, "normal"))
-               show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
+               s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
        else if (!strcmp(untracked_files_arg, "all"))
-               show_untracked_files = SHOW_ALL_UNTRACKED_FILES;
+               s->show_untracked_files = SHOW_ALL_UNTRACKED_FILES;
        else
                die("Invalid untracked files mode '%s'", untracked_files_arg);
 
@@ -810,28 +813,93 @@ static int parse_and_validate_options(int argc, const char *argv[],
        return argc;
 }
 
-int cmd_status(int argc, const char **argv, const char *prefix)
+static int dry_run_commit(int argc, const char **argv, const char *prefix,
+                         struct wt_status *s)
 {
-       const char *index_file;
        int commitable;
+       const char *index_file;
 
-       git_config(git_status_config, NULL);
+       index_file = prepare_index(argc, argv, prefix, 1);
+       commitable = run_status(stdout, index_file, prefix, 0, s);
+       rollback_index_files();
 
-       if (wt_status_use_color == -1)
-               wt_status_use_color = git_use_color_default;
+       return commitable ? 0 : 1;
+}
 
-       if (diff_use_color_default == -1)
-               diff_use_color_default = git_use_color_default;
+static int parse_status_slot(const char *var, int offset)
+{
+       if (!strcasecmp(var+offset, "header"))
+               return WT_STATUS_HEADER;
+       if (!strcasecmp(var+offset, "updated")
+               || !strcasecmp(var+offset, "added"))
+               return WT_STATUS_UPDATED;
+       if (!strcasecmp(var+offset, "changed"))
+               return WT_STATUS_CHANGED;
+       if (!strcasecmp(var+offset, "untracked"))
+               return WT_STATUS_UNTRACKED;
+       if (!strcasecmp(var+offset, "nobranch"))
+               return WT_STATUS_NOBRANCH;
+       if (!strcasecmp(var+offset, "unmerged"))
+               return WT_STATUS_UNMERGED;
+       die("bad config variable '%s'", var);
+}
 
-       argc = parse_and_validate_options(argc, argv, builtin_status_usage, prefix);
+static int git_status_config(const char *k, const char *v, void *cb)
+{
+       struct wt_status *s = cb;
 
-       index_file = prepare_index(argc, argv, prefix);
+       if (!strcmp(k, "status.submodulesummary")) {
+               int is_bool;
+               s->submodule_summary = git_config_bool_or_int(k, v, &is_bool);
+               if (is_bool && s->submodule_summary)
+                       s->submodule_summary = -1;
+               return 0;
+       }
+       if (!strcmp(k, "status.color") || !strcmp(k, "color.status")) {
+               s->use_color = git_config_colorbool(k, v, -1);
+               return 0;
+       }
+       if (!prefixcmp(k, "status.color.") || !prefixcmp(k, "color.status.")) {
+               int slot = parse_status_slot(k, 13);
+               if (!v)
+                       return config_error_nonbool(k);
+               color_parse(v, k, s->color_palette[slot]);
+               return 0;
+       }
+       if (!strcmp(k, "status.relativepaths")) {
+               s->relative_paths = git_config_bool(k, v);
+               return 0;
+       }
+       if (!strcmp(k, "status.showuntrackedfiles")) {
+               if (!v)
+                       return config_error_nonbool(k);
+               else if (!strcmp(v, "no"))
+                       s->show_untracked_files = SHOW_NO_UNTRACKED_FILES;
+               else if (!strcmp(v, "normal"))
+                       s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
+               else if (!strcmp(v, "all"))
+                       s->show_untracked_files = SHOW_ALL_UNTRACKED_FILES;
+               else
+                       return error("Invalid untracked files mode '%s'", v);
+               return 0;
+       }
+       return git_diff_ui_config(k, v, NULL);
+}
 
-       commitable = run_status(stdout, index_file, prefix, 0);
+int cmd_status(int argc, const char **argv, const char *prefix)
+{
+       struct wt_status s;
 
-       rollback_index_files();
+       wt_status_prepare(&s);
+       git_config(git_status_config, &s);
+       if (s.use_color == -1)
+               s.use_color = git_use_color_default;
+       if (diff_use_color_default == -1)
+               diff_use_color_default = git_use_color_default;
 
-       return commitable ? 0 : 1;
+       argc = parse_and_validate_options(argc, argv, builtin_status_usage,
+                                         prefix, &s);
+       return dry_run_commit(argc, argv, prefix, &s);
 }
 
 static void print_summary(const char *prefix, const unsigned char *sha1)
@@ -883,10 +951,12 @@ static void print_summary(const char *prefix, const unsigned char *sha1)
 
 static int git_commit_config(const char *k, const char *v, void *cb)
 {
+       struct wt_status *s = cb;
+
        if (!strcmp(k, "commit.template"))
                return git_config_string(&template_file, k, v);
 
-       return git_status_config(k, v, cb);
+       return git_status_config(k, v, s);
 }
 
 int cmd_commit(int argc, const char **argv, const char *prefix)
@@ -899,19 +969,26 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
        struct commit_list *parents = NULL, **pptr = &parents;
        struct stat statbuf;
        int allow_fast_forward = 1;
+       struct wt_status s;
 
-       git_config(git_commit_config, NULL);
-
-       if (wt_status_use_color == -1)
-               wt_status_use_color = git_use_color_default;
+       wt_status_prepare(&s);
+       git_config(git_commit_config, &s);
 
-       argc = parse_and_validate_options(argc, argv, builtin_commit_usage, prefix);
+       if (s.use_color == -1)
+               s.use_color = git_use_color_default;
 
-       index_file = prepare_index(argc, argv, prefix);
+       argc = parse_and_validate_options(argc, argv, builtin_commit_usage,
+                                         prefix, &s);
+       if (dry_run) {
+               if (diff_use_color_default == -1)
+                       diff_use_color_default = git_use_color_default;
+               return dry_run_commit(argc, argv, prefix, &s);
+       }
+       index_file = prepare_index(argc, argv, prefix, 0);
 
        /* Set up everything for writing the commit object.  This includes
           running hooks, writing the trees, and interacting with the user.  */
-       if (!prepare_to_commit(index_file, prefix)) {
+       if (!prepare_to_commit(index_file, prefix, &s)) {
                rollback_index_files();
                return 1;
        }
index 7a66298..df67a73 100644 (file)
@@ -20,6 +20,7 @@ static int tags;      /* Allow lightweight tags */
 static int longformat;
 static int abbrev = DEFAULT_ABBREV;
 static int max_candidates = 10;
+static int found_names;
 static const char *pattern;
 static int always;
 
@@ -49,6 +50,7 @@ static void add_to_known_names(const char *path,
                memcpy(e->path, path, len);
                commit->util = e;
        }
+       found_names = 1;
 }
 
 static int get_name(const char *path, const unsigned char *sha1, int flag, void *cb_data)
@@ -195,6 +197,9 @@ static void describe(const char *arg, int last_one)
                for_each_ref(get_name, NULL);
        }
 
+       if (!found_names)
+               die("cannot describe '%s'", sha1_to_hex(sha1));
+
        n = cmit->util;
        if (n) {
                /*
index 2e51f40..ffcdd05 100644 (file)
@@ -218,6 +218,8 @@ static int builtin_diff_files(struct rev_info *revs, int argc, const char **argv
                        revs->max_count = 3;
                else if (!strcmp(argv[1], "-q"))
                        options |= DIFF_SILENT_ON_REMOVED;
+               else if (!strcmp(argv[1], "-h"))
+                       usage(builtin_diff_usage);
                else
                        return error("invalid option: %s", argv[1]);
                argv++; argc--;
index c48c18d..b0a4029 100644 (file)
@@ -26,6 +26,7 @@ static int progress;
 static enum { ABORT, VERBATIM, WARN, STRIP } signed_tag_mode = ABORT;
 static enum { ERROR, DROP, REWRITE } tag_of_filtered_mode = ABORT;
 static int fake_missing_tagger;
+static int no_data;
 
 static int parse_opt_signed_tag_mode(const struct option *opt,
                                     const char *arg, int unset)
@@ -116,6 +117,9 @@ static void handle_object(const unsigned char *sha1)
        char *buf;
        struct object *object;
 
+       if (no_data)
+               return;
+
        if (is_null_sha1(sha1))
                return;
 
@@ -173,7 +177,7 @@ static void show_filemodify(struct diff_queue_struct *q,
                         * Links refer to objects in another repositories;
                         * output the SHA-1 verbatim.
                         */
-                       if (S_ISGITLINK(spec->mode))
+                       if (no_data || S_ISGITLINK(spec->mode))
                                printf("M %06o %s %s\n", spec->mode,
                                       sha1_to_hex(spec->sha1), spec->path);
                        else {
@@ -580,6 +584,9 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
                             "Import marks from this file"),
                OPT_BOOLEAN(0, "fake-missing-tagger", &fake_missing_tagger,
                             "Fake a tagger when tags lack one"),
+               { OPTION_NEGBIT, 0, "data", &no_data, NULL,
+                       "Skip output of blob data",
+                       PARSE_OPT_NOARG | PARSE_OPT_NEGHELP, NULL, 1 },
                OPT_END()
        };
 
index 817dd6b..cb48c57 100644 (file)
@@ -454,7 +454,7 @@ static int quickfetch(struct ref *ref_map)
 
        for (ref = ref_map; ref; ref = ref->next) {
                if (write_in_full(revlist.in, sha1_to_hex(ref->old_sha1), 40) < 0 ||
-                   write_in_full(revlist.in, "\n", 1) < 0) {
+                   write_str_in_full(revlist.in, "\n") < 0) {
                        if (errno != EPIPE && errno != EINVAL)
                                error("failed write to rev-list: %s", strerror(errno));
                        err = -1;
index d7cc8ca..a5a83f1 100644 (file)
@@ -576,7 +576,7 @@ static void populate_value(struct refinfo *ref)
 
                if (!prefixcmp(name, "refname"))
                        refname = ref->refname;
-               else if(!prefixcmp(name, "upstream")) {
+               else if (!prefixcmp(name, "upstream")) {
                        struct branch *branch;
                        /* only local branches may have an upstream */
                        if (prefixcmp(ref->refname, "refs/heads/"))
index b3d38fa..c58b0e3 100644 (file)
@@ -589,6 +589,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
        struct alternate_object_database *alt;
 
        errors_found = 0;
+       read_replace_refs = 0;
 
        argc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0);
        if (write_lost_and_found) {
index fd450bc..761799d 100644 (file)
@@ -53,26 +53,58 @@ static int grep_config(const char *var, const char *value, void *cb)
        return git_color_default_config(var, value, cb);
 }
 
+/*
+ * Return non-zero if max_depth is negative or path has no more then max_depth
+ * slashes.
+ */
+static int accept_subdir(const char *path, int max_depth)
+{
+       if (max_depth < 0)
+               return 1;
+
+       while ((path = strchr(path, '/')) != NULL) {
+               max_depth--;
+               if (max_depth < 0)
+                       return 0;
+               path++;
+       }
+       return 1;
+}
+
+/*
+ * Return non-zero if name is a subdirectory of match and is not too deep.
+ */
+static int is_subdir(const char *name, int namelen,
+               const char *match, int matchlen, int max_depth)
+{
+       if (matchlen > namelen || strncmp(name, match, matchlen))
+               return 0;
+
+       if (name[matchlen] == '\0') /* exact match */
+               return 1;
+
+       if (!matchlen || match[matchlen-1] == '/' || name[matchlen] == '/')
+               return accept_subdir(name + matchlen + 1, max_depth);
+
+       return 0;
+}
+
 /*
  * git grep pathspecs are somewhat different from diff-tree pathspecs;
  * pathname wildcards are allowed.
  */
-static int pathspec_matches(const char **paths, const char *name)
+static int pathspec_matches(const char **paths, const char *name, int max_depth)
 {
        int namelen, i;
        if (!paths || !*paths)
-               return 1;
+               return accept_subdir(name, max_depth);
        namelen = strlen(name);
        for (i = 0; paths[i]; i++) {
                const char *match = paths[i];
                int matchlen = strlen(match);
                const char *cp, *meta;
 
-               if (!matchlen ||
-                   ((matchlen <= namelen) &&
-                    !strncmp(name, match, matchlen) &&
-                    (match[matchlen-1] == '/' ||
-                     name[matchlen] == '\0' || name[matchlen] == '/')))
+               if (is_subdir(name, namelen, match, matchlen, max_depth))
                        return 1;
                if (!fnmatch(match, name, 0))
                        return 1;
@@ -411,7 +443,7 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached)
                int kept;
                if (!S_ISREG(ce->ce_mode))
                        continue;
-               if (!pathspec_matches(paths, ce->name))
+               if (!pathspec_matches(paths, ce->name, opt->max_depth))
                        continue;
                name = ce->name;
                if (name[0] == '-') {
@@ -469,7 +501,7 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached,
                struct cache_entry *ce = active_cache[nr];
                if (!S_ISREG(ce->ce_mode))
                        continue;
-               if (!pathspec_matches(paths, ce->name))
+               if (!pathspec_matches(paths, ce->name, opt->max_depth))
                        continue;
                /*
                 * If CE_VALID is on, we assume worktree file and its cache entry
@@ -529,7 +561,7 @@ static int grep_tree(struct grep_opt *opt, const char **paths,
                        strbuf_addch(&pathbuf, '/');
 
                down = pathbuf.buf + tn_len;
-               if (!pathspec_matches(paths, down))
+               if (!pathspec_matches(paths, down, opt->max_depth))
                        ;
                else if (S_ISREG(entry.mode))
                        hit |= grep_sha1(opt, entry.sha1, pathbuf.buf, tn_len);
@@ -683,6 +715,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                OPT_SET_INT('I', NULL, &opt.binary,
                        "don't match patterns in binary files",
                        GREP_BINARY_NOMATCH),
+               { OPTION_INTEGER, 0, "max-depth", &opt.max_depth, "depth",
+                       "descend at most <depth> levels", PARSE_OPT_NONEG,
+                       NULL, 1 },
                OPT_GROUP(""),
                OPT_BIT('E', "extended-regexp", &opt.regflags,
                        "use extended POSIX regular expressions", REG_EXTENDED),
@@ -760,6 +795,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
        opt.pathname = 1;
        opt.pattern_tail = &opt.pattern_list;
        opt.regflags = REG_NEWLINE;
+       opt.max_depth = -1;
 
        strcpy(opt.color_match, GIT_COLOR_RED GIT_COLOR_BOLD);
        opt.color = -1;
index 4a56006..dd84cae 100644 (file)
@@ -6,6 +6,7 @@
 #include "cache.h"
 #include "builtin.h"
 #include "exec_cmd.h"
+#include "parse-options.h"
 
 #ifndef DEFAULT_GIT_TEMPLATE_DIR
 #define DEFAULT_GIT_TEMPLATE_DIR "/usr/share/git-core/templates"
@@ -370,8 +371,16 @@ static int guess_repository_type(const char *git_dir)
        return 1;
 }
 
-static const char init_db_usage[] =
-"git init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]]";
+static int shared_callback(const struct option *opt, const char *arg, int unset)
+{
+       *((int *) opt->value) = (arg) ? git_config_perm("arg", arg) : PERM_GROUP;
+       return 0;
+}
+
+static const char *const init_db_usage[] = {
+       "git init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]] [directory]",
+       NULL
+};
 
 /*
  * If you want to, you can share the DB area with any number of branches.
@@ -384,25 +393,60 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
        const char *git_dir;
        const char *template_dir = NULL;
        unsigned int flags = 0;
-       int i;
-
-       for (i = 1; i < argc; i++, argv++) {
-               const char *arg = argv[1];
-               if (!prefixcmp(arg, "--template="))
-                       template_dir = arg+11;
-               else if (!strcmp(arg, "--bare")) {
-                       static char git_dir[PATH_MAX+1];
-                       is_bare_repository_cfg = 1;
-                       setenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir,
-                                               sizeof(git_dir)), 0);
-               } else if (!strcmp(arg, "--shared"))
-                       init_shared_repository = PERM_GROUP;
-               else if (!prefixcmp(arg, "--shared="))
-                       init_shared_repository = git_config_perm("arg", arg+9);
-               else if (!strcmp(arg, "-q") || !strcmp(arg, "--quiet"))
-                       flags |= INIT_DB_QUIET;
-               else
-                       usage(init_db_usage);
+       const struct option init_db_options[] = {
+               OPT_STRING(0, "template", &template_dir, "template-directory",
+                               "provide the directory from which templates will be used"),
+               OPT_SET_INT(0, "bare", &is_bare_repository_cfg,
+                               "create a bare repository", 1),
+               { OPTION_CALLBACK, 0, "shared", &init_shared_repository,
+                       "permissions",
+                       "specify that the git repository is to be shared amongst several users",
+                       PARSE_OPT_OPTARG | PARSE_OPT_NONEG, shared_callback, 0},
+               OPT_BIT('q', "quiet", &flags, "be quiet", INIT_DB_QUIET),
+               OPT_END()
+       };
+
+       argc = parse_options(argc, argv, prefix, init_db_options, init_db_usage, 0);
+
+       if (argc == 1) {
+               int mkdir_tried = 0;
+       retry:
+               if (chdir(argv[0]) < 0) {
+                       if (!mkdir_tried) {
+                               int saved;
+                               /*
+                                * At this point we haven't read any configuration,
+                                * and we know shared_repository should always be 0;
+                                * but just in case we play safe.
+                                */
+                               saved = shared_repository;
+                               shared_repository = 0;
+                               switch (safe_create_leading_directories_const(argv[0])) {
+                               case -3:
+                                       errno = EEXIST;
+                                       /* fallthru */
+                               case -1:
+                                       die_errno("cannot mkdir %s", argv[0]);
+                                       break;
+                               default:
+                                       break;
+                               }
+                               shared_repository = saved;
+                               if (mkdir(argv[0], 0777) < 0)
+                                       die_errno("cannot mkdir %s", argv[0]);
+                               mkdir_tried = 1;
+                               goto retry;
+                       }
+                       die_errno("cannot chdir to %s", argv[0]);
+               }
+       } else if (0 < argc) {
+               usage(init_db_usage[0]);
+       }
+       if (is_bare_repository_cfg == 1) {
+               static char git_dir[PATH_MAX+1];
+
+               setenv(GIT_DIR_ENVIRONMENT,
+                       getcwd(git_dir, sizeof(git_dir)), 0);
        }
 
        if (init_shared_repository != -1)
index 8d93c1a..25e21ed 100644 (file)
@@ -27,6 +27,10 @@ static int default_show_root = 1;
 static const char *fmt_patch_subject_prefix = "PATCH";
 static const char *fmt_pretty;
 
+static const char * const builtin_log_usage =
+       "git log [<options>] [<since>..<until>] [[--] <path>...]\n"
+       "   or: git show [options] <object>...";
+
 static void cmd_log_init(int argc, const char **argv, const char *prefix,
                      struct rev_info *rev)
 {
@@ -69,6 +73,8 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
                                die("invalid --decorate option: %s", arg);
                } else if (!strcmp(arg, "--source")) {
                        rev->show_source = 1;
+               } else if (!strcmp(arg, "-h")) {
+                       usage(builtin_log_usage);
                } else
                        die("unrecognized argument: %s", arg);
        }
index 92637ac..d498b1c 100644 (file)
@@ -25,6 +25,7 @@ static enum  {
 static struct strbuf charset = STRBUF_INIT;
 static int patch_lines;
 static struct strbuf **p_hdr_data, **s_hdr_data;
+static int use_scissors;
 
 #define MAX_HDR_PARSED 10
 #define MAX_BOUNDARIES 5
@@ -712,6 +713,56 @@ static inline int patchbreak(const struct strbuf *line)
        return 0;
 }
 
+static int is_scissors_line(const struct strbuf *line)
+{
+       size_t i, len = line->len;
+       int scissors = 0, gap = 0;
+       int first_nonblank = -1;
+       int last_nonblank = 0, visible, perforation = 0, in_perforation = 0;
+       const char *buf = line->buf;
+
+       for (i = 0; i < len; i++) {
+               if (isspace(buf[i])) {
+                       if (in_perforation) {
+                               perforation++;
+                               gap++;
+                       }
+                       continue;
+               }
+               last_nonblank = i;
+               if (first_nonblank < 0)
+                       first_nonblank = i;
+               if (buf[i] == '-') {
+                       in_perforation = 1;
+                       perforation++;
+                       continue;
+               }
+               if (i + 1 < len &&
+                   (!memcmp(buf + i, ">8", 2) || !memcmp(buf + i, "8<", 2))) {
+                       in_perforation = 1;
+                       perforation += 2;
+                       scissors += 2;
+                       i++;
+                       continue;
+               }
+               in_perforation = 0;
+       }
+
+       /*
+        * The mark must be at least 8 bytes long (e.g. "-- >8 --").
+        * Even though there can be arbitrary cruft on the same line
+        * (e.g. "cut here"), in order to avoid misidentification, the
+        * perforation must occupy more than a third of the visible
+        * width of the line, and dashes and scissors must occupy more
+        * than half of the perforation.
+        */
+
+       visible = last_nonblank - first_nonblank + 1;
+       return (scissors && 8 <= visible &&
+               visible < perforation * 3 &&
+               gap * 2 < perforation);
+}
+
 static int handle_commit_msg(struct strbuf *line)
 {
        static int still_looking = 1;
@@ -723,7 +774,8 @@ static int handle_commit_msg(struct strbuf *line)
                strbuf_ltrim(line);
                if (!line->len)
                        return 0;
-               if ((still_looking = check_header(line, s_hdr_data, 0)) != 0)
+               still_looking = check_header(line, s_hdr_data, 0);
+               if (still_looking)
                        return 0;
        }
 
@@ -731,6 +783,24 @@ static int handle_commit_msg(struct strbuf *line)
        if (metainfo_charset)
                convert_to_utf8(line, charset.buf);
 
+       if (use_scissors && is_scissors_line(line)) {
+               int i;
+               rewind(cmitmsg);
+               ftruncate(fileno(cmitmsg), 0);
+               still_looking = 1;
+
+               /*
+                * We may have already read "secondary headers"; purge
+                * them to give ourselves a clean restart.
+                */
+               for (i = 0; header[i]; i++) {
+                       if (s_hdr_data[i])
+                               strbuf_release(s_hdr_data[i]);
+                       s_hdr_data[i] = NULL;
+               }
+               return 0;
+       }
+
        if (patchbreak(line)) {
                fclose(cmitmsg);
                cmitmsg = NULL;
@@ -765,7 +835,6 @@ static void handle_filter(struct strbuf *line)
 
 static void handle_body(void)
 {
-       int len = 0;
        struct strbuf prev = STRBUF_INIT;
 
        /* Skip up to the first boundary */
@@ -775,8 +844,6 @@ static void handle_body(void)
        }
 
        do {
-               strbuf_setlen(&line, line.len + len);
-
                /* process any boundary lines */
                if (*content_top && is_multipart_boundary(&line)) {
                        /* flush any leftover */
@@ -832,10 +899,7 @@ static void handle_body(void)
                        handle_filter(&line);
                }
 
-               strbuf_reset(&line);
-               if (strbuf_avail(&line) < 100)
-                       strbuf_grow(&line, 100);
-       } while ((len = read_line_with_nul(line.buf, strbuf_avail(&line), fin)));
+       } while (!strbuf_getwholeline(&line, fin, '\n'));
 
 handle_body_out:
        strbuf_release(&prev);
@@ -891,12 +955,9 @@ static void handle_info(void)
        fprintf(fout, "\n");
 }
 
-static int mailinfo(FILE *in, FILE *out, int ks, const char *encoding,
-                   const char *msg, const char *patch)
+static int mailinfo(FILE *in, FILE *out, const char *msg, const char *patch)
 {
        int peek;
-       keep_subject = ks;
-       metainfo_charset = encoding;
        fin = in;
        fout = out;
 
@@ -930,8 +991,20 @@ static int mailinfo(FILE *in, FILE *out, int ks, const char *encoding,
        return 0;
 }
 
+static int git_mailinfo_config(const char *var, const char *value, void *unused)
+{
+       if (prefixcmp(var, "mailinfo."))
+               return git_default_config(var, value, unused);
+       if (!strcmp(var, "mailinfo.scissors")) {
+               use_scissors = git_config_bool(var, value);
+               return 0;
+       }
+       /* perhaps others here */
+       return 0;
+}
+
 static const char mailinfo_usage[] =
-       "git mailinfo [-k] [-u | --encoding=<encoding> | -n] msg patch <mail >info";
+       "git mailinfo [-k] [-u | --encoding=<encoding> | -n] [--scissors | --no-scissors] msg patch < mail >info";
 
 int cmd_mailinfo(int argc, const char **argv, const char *prefix)
 {
@@ -940,7 +1013,7 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix)
        /* NEEDSWORK: might want to do the optional .git/ directory
         * discovery
         */
-       git_config(git_default_config, NULL);
+       git_config(git_mailinfo_config, NULL);
 
        def_charset = (git_commit_encoding ? git_commit_encoding : "UTF-8");
        metainfo_charset = def_charset;
@@ -954,6 +1027,10 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix)
                        metainfo_charset = NULL;
                else if (!prefixcmp(argv[1], "--encoding="))
                        metainfo_charset = argv[1] + 11;
+               else if (!strcmp(argv[1], "--scissors"))
+                       use_scissors = 1;
+               else if (!strcmp(argv[1], "--no-scissors"))
+                       use_scissors = 0;
                else
                        usage(mailinfo_usage);
                argc--; argv++;
@@ -962,5 +1039,5 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix)
        if (argc != 3)
                usage(mailinfo_usage);
 
-       return !!mailinfo(stdin, stdout, keep_subject, metainfo_charset, argv[1], argv[2]);
+       return !!mailinfo(stdin, stdout, argv[1], argv[2]);
 }
index ad5f6b5..dfe5b15 100644 (file)
@@ -7,6 +7,7 @@
 #include "cache.h"
 #include "builtin.h"
 #include "string-list.h"
+#include "strbuf.h"
 
 static const char git_mailsplit_usage[] =
 "git mailsplit [-d<prec>] [-f<n>] [-b] -o<directory> [<mbox>|<Maildir>...]";
@@ -42,26 +43,8 @@ static int is_from_line(const char *line, int len)
        return 1;
 }
 
-/* Could be as small as 64, enough to hold a Unix "From " line. */
-static char buf[4096];
-
-/* We cannot use fgets() because our lines can contain NULs */
-int read_line_with_nul(char *buf, int size, FILE *in)
-{
-       int len = 0, c;
-
-       for (;;) {
-               c = getc(in);
-               if (c == EOF)
-                       break;
-               buf[len++] = c;
-               if (c == '\n' || len + 1 >= size)
-                       break;
-       }
-       buf[len] = '\0';
-
-       return len;
-}
+static struct strbuf buf = STRBUF_INIT;
+static int keep_cr;
 
 /* Called with the first line (potentially partial)
  * already in buf[] -- normally that should begin with
@@ -71,10 +54,9 @@ int read_line_with_nul(char *buf, int size, FILE *in)
 static int split_one(FILE *mbox, const char *name, int allow_bare)
 {
        FILE *output = NULL;
-       int len = strlen(buf);
        int fd;
        int status = 0;
-       int is_bare = !is_from_line(buflen);
+       int is_bare = !is_from_line(buf.buf, buf.len);
 
        if (is_bare && !allow_bare)
                goto corrupt;
@@ -82,26 +64,29 @@ static int split_one(FILE *mbox, const char *name, int allow_bare)
        fd = open(name, O_WRONLY | O_CREAT | O_EXCL, 0666);
        if (fd < 0)
                die_errno("cannot open output file '%s'", name);
-       output = fdopen(fd, "w");
+       output = xfdopen(fd, "w");
 
        /* Copy it out, while searching for a line that begins with
         * "From " and having something that looks like a date format.
         */
        for (;;) {
-               int is_partial = len && buf[len-1] != '\n';
+               if (!keep_cr && buf.len > 1 && buf.buf[buf.len-1] == '\n' &&
+                       buf.buf[buf.len-2] == '\r') {
+                       strbuf_setlen(&buf, buf.len-2);
+                       strbuf_addch(&buf, '\n');
+               }
 
-               if (fwrite(buf, 1, len, output) != len)
+               if (fwrite(buf.buf, 1, buf.len, output) != buf.len)
                        die_errno("cannot write output");
 
-               len = read_line_with_nul(buf, sizeof(buf), mbox);
-               if (len == 0) {
+               if (strbuf_getwholeline(&buf, mbox, '\n')) {
                        if (feof(mbox)) {
                                status = 1;
                                break;
                        }
                        die_errno("cannot read mbox");
                }
-               if (!is_partial && !is_bare && is_from_line(buf, len))
+               if (!is_bare && is_from_line(buf.buf, buf.len))
                        break; /* done with one message */
        }
        fclose(output);
@@ -166,7 +151,7 @@ static int split_maildir(const char *maildir, const char *dir,
                        goto out;
                }
 
-               if (fgets(buf, sizeof(buf), f) == NULL) {
+               if (strbuf_getwholeline(&buf, f, '\n')) {
                        error("cannot read mail %s (%s)", file, strerror(errno));
                        goto out;
                }
@@ -203,7 +188,7 @@ static int split_mbox(const char *file, const char *dir, int allow_bare,
        } while (isspace(peek));
        ungetc(peek, f);
 
-       if (fgets(buf, sizeof(buf), f) == NULL) {
+       if (strbuf_getwholeline(&buf, f, '\n')) {
                /* empty stdin is OK */
                if (f != stdin) {
                        error("cannot read mbox %s", file);
@@ -248,6 +233,8 @@ int cmd_mailsplit(int argc, const char **argv, const char *prefix)
                        nr = strtol(arg+2, NULL, 10);
                } else if ( arg[1] == 'b' && !arg[2] ) {
                        allow_bare = 1;
+               } else if (!strcmp(arg, "--keep-cr")) {
+                       keep_cr = 1;
                } else if ( arg[1] == 'o' && arg[2] ) {
                        dir = arg+2;
                } else if ( arg[1] == '-' && !arg[2] ) {
index a6ec2f7..54e7ec2 100644 (file)
@@ -23,7 +23,7 @@ static int show_merge_base(struct commit **rev, int rev_nr, int show_all)
 }
 
 static const char * const merge_base_usage[] = {
-       "git merge-base [--all] <commit-id> <commit-id>...",
+       "git merge-base [-a|--all] <commit> <commit>...",
        NULL
 };
 
index f4de73f..b6b8428 100644 (file)
@@ -598,7 +598,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
                discard_cache();
                if (read_cache() < 0)
                        die("failed to read the cache");
-               return -ret;
+               return ret;
        }
 }
 
index b592c36..1b20028 100644 (file)
@@ -53,7 +53,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
        int verbose = 0, show_only = 0, force = 0, ignore_errors = 0;
        struct option builtin_mv_options[] = {
                OPT__DRY_RUN(&show_only),
-               OPT_BOOLEAN('f', NULL, &force, "force move/rename even if target exists"),
+               OPT_BOOLEAN('f', "force", &force, "force move/rename even if target exists"),
                OPT_BOOLEAN('k', NULL, &ignore_errors, "skip move/rename errors"),
                OPT_END(),
        };
index 9cc8a84..7a390e1 100644 (file)
@@ -1008,6 +1008,33 @@ static void add_preferred_base(unsigned char *sha1)
        it->pcache.tree_size = size;
 }
 
+static void cleanup_preferred_base(void)
+{
+       struct pbase_tree *it;
+       unsigned i;
+
+       it = pbase_tree;
+       pbase_tree = NULL;
+       while (it) {
+               struct pbase_tree *this = it;
+               it = this->next;
+               free(this->pcache.tree_data);
+               free(this);
+       }
+
+       for (i = 0; i < ARRAY_SIZE(pbase_tree_cache); i++) {
+               if (!pbase_tree_cache[i])
+                       continue;
+               free(pbase_tree_cache[i]->tree_data);
+               free(pbase_tree_cache[i]);
+               pbase_tree_cache[i] = NULL;
+       }
+
+       free(done_pbase_paths);
+       done_pbase_paths = NULL;
+       done_pbase_paths_num = done_pbase_paths_alloc = 0;
+}
+
 static void check_object(struct object_entry *entry)
 {
        if (entry->in_pack) {
@@ -1599,7 +1626,7 @@ static void *threaded_find_deltas(void *arg)
 static void ll_find_deltas(struct object_entry **list, unsigned list_size,
                           int window, int depth, unsigned *processed)
 {
-       struct thread_params p[delta_search_threads];
+       struct thread_params *p;
        int i, ret, active_threads = 0;
 
        if (delta_search_threads <= 1) {
@@ -1609,6 +1636,7 @@ static void ll_find_deltas(struct object_entry **list, unsigned list_size,
        if (progress > pack_to_stdout)
                fprintf(stderr, "Delta compression using up to %d threads.\n",
                                delta_search_threads);
+       p = xcalloc(delta_search_threads, sizeof(*p));
 
        /* Partition the work amongst work threads. */
        for (i = 0; i < delta_search_threads; i++) {
@@ -1717,6 +1745,7 @@ static void ll_find_deltas(struct object_entry **list, unsigned list_size,
                        active_threads--;
                }
        }
+       free(p);
 }
 
 #else
@@ -1808,7 +1837,7 @@ static void prepare_pack(int window, int depth)
 
 static int git_pack_config(const char *k, const char *v, void *cb)
 {
-       if(!strcmp(k, "pack.window")) {
+       if (!strcmp(k, "pack.window")) {
                window = git_config_int(k, v);
                return 0;
        }
@@ -2098,6 +2127,8 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
        int rp_ac_alloc = 64;
        int rp_ac;
 
+       read_replace_refs = 0;
+
        rp_av = xcalloc(rp_ac_alloc, sizeof(*rp_av));
 
        rp_av[0] = "pack-objects";
@@ -2308,6 +2339,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
                rp_av[rp_ac] = NULL;
                get_object_list(rp_ac, rp_av);
        }
+       cleanup_preferred_base();
        if (include_tag && nr_result)
                for_each_ref(add_ref_tag, NULL);
        stop_progress(&progress_state);
index 00590b1..be99eb0 100644 (file)
@@ -1,9 +1,12 @@
 #include "builtin.h"
 #include "cache.h"
 #include "progress.h"
+#include "parse-options.h"
 
-static const char prune_packed_usage[] =
-"git prune-packed [-n] [-q]";
+static const char * const prune_packed_usage[] = {
+       "git prune-packed [-n|--dry-run] [-q|--quiet]",
+       NULL
+};
 
 #define DRY_RUN 01
 #define VERBOSE 02
@@ -68,24 +71,16 @@ void prune_packed_objects(int opts)
 
 int cmd_prune_packed(int argc, const char **argv, const char *prefix)
 {
-       int i;
        int opts = VERBOSE;
+       const struct option prune_packed_options[] = {
+               OPT_BIT('n', "dry-run", &opts, "dry run", DRY_RUN),
+               OPT_NEGBIT('q', "quiet", &opts, "be quiet", VERBOSE),
+               OPT_END()
+       };
 
-       for (i = 1; i < argc; i++) {
-               const char *arg = argv[i];
+       argc = parse_options(argc, argv, prefix, prune_packed_options,
+                            prune_packed_usage, 0);
 
-               if (*arg == '-') {
-                       if (!strcmp(arg, "-n"))
-                               opts |= DRY_RUN;
-                       else if (!strcmp(arg, "-q"))
-                               opts &= ~VERBOSE;
-                       else
-                               usage(prune_packed_usage);
-                       continue;
-               }
-               /* Handle arguments here .. */
-               usage(prune_packed_usage);
-       }
        prune_packed_objects(opts);
        return 0;
 }
index 0ed9cce..8459aec 100644 (file)
@@ -140,6 +140,7 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
        char *s;
 
        save_commit_buffer = 0;
+       read_replace_refs = 0;
        init_revisions(&revs, prefix);
 
        argc = parse_options(argc, argv, prefix, options, prune_usage, 0);
index f8376cf..3cb1ee4 100644 (file)
@@ -10,7 +10,7 @@
 #include "parse-options.h"
 
 static const char * const push_usage[] = {
-       "git push [--all | --mirror] [--dry-run] [--porcelain] [--tags] [--receive-pack=<git-receive-pack>] [--repo=<repository>] [-f | --force] [-v] [<repository> <refspec>...]",
+       "git push [--all | --mirror] [-n | --dry-run] [--porcelain] [--tags] [--receive-pack=<git-receive-pack>] [--repo=<repository>] [-f | --force] [-v] [<repository> <refspec>...]",
        NULL,
 };
 
@@ -157,7 +157,7 @@ static int do_push(const char *repo, int flags)
                        continue;
 
                error("failed to push some refs to '%s'", url[i]);
-               if (nonfastforward) {
+               if (nonfastforward && advice_push_nonfastforward) {
                        printf("To prevent you from losing history, non-fast-forward updates were rejected\n"
                               "Merge the remote changes before pushing again.  See the 'non-fast forward'\n"
                               "section of 'git push --help' for details.\n");
@@ -175,13 +175,14 @@ int cmd_push(int argc, const char **argv, const char *prefix)
        const char *repo = NULL;        /* default repository */
 
        struct option options[] = {
+               OPT_BIT('q', "quiet", &flags, "be quiet", TRANSPORT_PUSH_QUIET),
                OPT_BIT('v', "verbose", &flags, "be verbose", TRANSPORT_PUSH_VERBOSE),
                OPT_STRING( 0 , "repo", &repo, "repository", "repository"),
                OPT_BIT( 0 , "all", &flags, "push all refs", TRANSPORT_PUSH_ALL),
                OPT_BIT( 0 , "mirror", &flags, "mirror all refs",
                            (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
                OPT_BOOLEAN( 0 , "tags", &tags, "push tags"),
-               OPT_BIT( 0 , "dry-run", &flags, "dry run", TRANSPORT_PUSH_DRY_RUN),
+               OPT_BIT('n' , "dry-run", &flags, "dry run", TRANSPORT_PUSH_DRY_RUN),
                OPT_BIT( 0,  "porcelain", &flags, "machine-readable output", TRANSPORT_PUSH_PORCELAIN),
                OPT_BIT('f', "force", &flags, "force updates", TRANSPORT_PUSH_FORCE),
                OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"),
index 82e25ea..14c836b 100644 (file)
@@ -12,6 +12,7 @@
 #include "unpack-trees.h"
 #include "dir.h"
 #include "builtin.h"
+#include "parse-options.h"
 
 static int nr_trees;
 static struct tree *trees[MAX_UNPACK_TREES];
@@ -29,7 +30,39 @@ static int list_tree(unsigned char *sha1)
        return 0;
 }
 
-static const char read_tree_usage[] = "git read-tree (<sha> | [[-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>] [-u | -i]] [--exclude-per-directory=<gitignore>] [--index-output=<file>] <sha1> [<sha2> [<sha3>]])";
+static const char * const read_tree_usage[] = {
+       "git read-tree [[-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>] [-u [--exclude-per-directory=<gitignore>] | -i]]  [--index-output=<file>] <tree-ish1> [<tree-ish2> [<tree-ish3>]]",
+       NULL
+};
+
+static int index_output_cb(const struct option *opt, const char *arg,
+                                int unset)
+{
+       set_alternate_index_output(arg);
+       return 0;
+}
+
+static int exclude_per_directory_cb(const struct option *opt, const char *arg,
+                                   int unset)
+{
+       struct dir_struct *dir;
+       struct unpack_trees_options *opts;
+
+       opts = (struct unpack_trees_options *)opt->value;
+
+       if (opts->dir)
+               die("more than one --exclude-per-directory given.");
+
+       dir = xcalloc(1, sizeof(*opts->dir));
+       dir->flags |= DIR_SHOW_IGNORED;
+       dir->exclude_per_dir = arg;
+       opts->dir = dir;
+       /* We do not need to nor want to do read-directory
+        * here; we are merely interested in reusing the
+        * per directory ignore stack mechanism.
+        */
+       return 0;
+}
 
 static struct lock_file lock_file;
 
@@ -39,6 +72,34 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
        unsigned char sha1[20];
        struct tree_desc t[MAX_UNPACK_TREES];
        struct unpack_trees_options opts;
+       int prefix_set = 0;
+       const struct option read_tree_options[] = {
+               { OPTION_CALLBACK, 0, "index-output", NULL, "FILE",
+                 "write resulting index to <FILE>",
+                 PARSE_OPT_NONEG, index_output_cb },
+               OPT__VERBOSE(&opts.verbose_update),
+               OPT_GROUP("Merging"),
+               OPT_SET_INT('m', NULL, &opts.merge,
+                           "perform a merge in addition to a read", 1),
+               OPT_SET_INT(0, "trivial", &opts.trivial_merges_only,
+                           "3-way merge if no file level merging required", 1),
+               OPT_SET_INT(0, "aggressive", &opts.aggressive,
+                           "3-way merge in presence of adds and removes", 1),
+               OPT_SET_INT(0, "reset", &opts.reset,
+                           "same as -m, but discard unmerged entries", 1),
+               { OPTION_STRING, 0, "prefix", &opts.prefix, "<subdirectory>/",
+                 "read the tree into the index under <subdirectory>/",
+                 PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP },
+               OPT_SET_INT('u', NULL, &opts.update,
+                           "update working tree with merge result", 1),
+               { OPTION_CALLBACK, 0, "exclude-per-directory", &opts,
+                 "gitignore",
+                 "allow explicitly ignored files to be overwritten",
+                 PARSE_OPT_NONEG, exclude_per_directory_cb },
+               OPT_SET_INT('i', NULL, &opts.index_only,
+                           "don't check the working tree after merging", 1),
+               OPT_END()
+       };
 
        memset(&opts, 0, sizeof(opts));
        opts.head_idx = -1;
@@ -49,105 +110,21 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
 
        newfd = hold_locked_index(&lock_file, 1);
 
-       for (i = 1; i < argc; i++) {
-               const char *arg = argv[i];
-
-               /* "-u" means "update", meaning that a merge will update
-                * the working tree.
-                */
-               if (!strcmp(arg, "-u")) {
-                       opts.update = 1;
-                       continue;
-               }
+       argc = parse_options(argc, argv, unused_prefix, read_tree_options,
+                            read_tree_usage, 0);
 
-               if (!strcmp(arg, "-v")) {
-                       opts.verbose_update = 1;
-                       continue;
-               }
+       prefix_set = opts.prefix ? 1 : 0;
+       if (1 < opts.merge + opts.reset + prefix_set)
+               die("Which one? -m, --reset, or --prefix?");
 
-               /* "-i" means "index only", meaning that a merge will
-                * not even look at the working tree.
-                */
-               if (!strcmp(arg, "-i")) {
-                       opts.index_only = 1;
-                       continue;
-               }
-
-               if (!prefixcmp(arg, "--index-output=")) {
-                       set_alternate_index_output(arg + 15);
-                       continue;
-               }
-
-               /* "--prefix=<subdirectory>/" means keep the current index
-                *  entries and put the entries from the tree under the
-                * given subdirectory.
-                */
-               if (!prefixcmp(arg, "--prefix=")) {
-                       if (stage || opts.merge || opts.prefix)
-                               usage(read_tree_usage);
-                       opts.prefix = arg + 9;
-                       opts.merge = 1;
-                       stage = 1;
-                       if (read_cache_unmerged())
-                               die("you need to resolve your current index first");
-                       continue;
-               }
-
-               /* This differs from "-m" in that we'll silently ignore
-                * unmerged entries and overwrite working tree files that
-                * correspond to them.
-                */
-               if (!strcmp(arg, "--reset")) {
-                       if (stage || opts.merge || opts.prefix)
-                               usage(read_tree_usage);
-                       opts.reset = 1;
-                       opts.merge = 1;
-                       stage = 1;
-                       read_cache_unmerged();
-                       continue;
-               }
-
-               if (!strcmp(arg, "--trivial")) {
-                       opts.trivial_merges_only = 1;
-                       continue;
-               }
-
-               if (!strcmp(arg, "--aggressive")) {
-                       opts.aggressive = 1;
-                       continue;
-               }
-
-               /* "-m" stands for "merge", meaning we start in stage 1 */
-               if (!strcmp(arg, "-m")) {
-                       if (stage || opts.merge || opts.prefix)
-                               usage(read_tree_usage);
-                       if (read_cache_unmerged())
-                               die("you need to resolve your current index first");
-                       stage = 1;
-                       opts.merge = 1;
-                       continue;
-               }
-
-               if (!prefixcmp(arg, "--exclude-per-directory=")) {
-                       struct dir_struct *dir;
-
-                       if (opts.dir)
-                               die("more than one --exclude-per-directory are given.");
-
-                       dir = xcalloc(1, sizeof(*opts.dir));
-                       dir->flags |= DIR_SHOW_IGNORED;
-                       dir->exclude_per_dir = arg + 24;
-                       opts.dir = dir;
-                       /* We do not need to nor want to do read-directory
-                        * here; we are merely interested in reusing the
-                        * per directory ignore stack mechanism.
-                        */
-                       continue;
-               }
+       if (opts.reset || opts.merge || opts.prefix) {
+               if (read_cache_unmerged() && (opts.prefix || opts.merge))
+                       die("You need to resolve your current index first");
+               stage = opts.merge = 1;
+       }
 
-               /* using -u and -i at the same time makes no sense */
-               if (1 < opts.index_only + opts.update)
-                       usage(read_tree_usage);
+       for (i = 0; i < argc; i++) {
+               const char *arg = argv[i];
 
                if (get_sha1(arg, sha1))
                        die("Not a valid object name %s", arg);
@@ -155,8 +132,11 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
                        die("failed to unpack tree object %s", arg);
                stage++;
        }
+       if (1 < opts.index_only + opts.update)
+               die("-u and -i at the same time makes no sense");
        if ((opts.update||opts.index_only) && !opts.merge)
-               usage(read_tree_usage);
+               die("%s is meaningless without -m, --reset, or --prefix",
+                   opts.update ? "-u" : "-i");
        if ((opts.dir && !opts.update))
                die("--exclude-per-directory is meaningless unless -u");
        if (opts.merge && !opts.index_only)
index 6ec1d05..b771fe9 100644 (file)
@@ -123,31 +123,6 @@ static struct command *commands;
 static const char pre_receive_hook[] = "hooks/pre-receive";
 static const char post_receive_hook[] = "hooks/post-receive";
 
-static int run_status(int code, const char *cmd_name)
-{
-       switch (code) {
-       case 0:
-               return 0;
-       case -ERR_RUN_COMMAND_FORK:
-               return error("fork of %s failed", cmd_name);
-       case -ERR_RUN_COMMAND_EXEC:
-               return error("execute of %s failed", cmd_name);
-       case -ERR_RUN_COMMAND_PIPE:
-               return error("pipe failed");
-       case -ERR_RUN_COMMAND_WAITPID:
-               return error("waitpid failed");
-       case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
-               return error("waitpid is confused");
-       case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
-               return error("%s died of signal", cmd_name);
-       case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
-               return error("%s died strangely", cmd_name);
-       default:
-               error("%s exited with error code %d", cmd_name, -code);
-               return -code;
-       }
-}
-
 static int run_receive_hook(const char *hook_name)
 {
        static char buf[sizeof(commands->old_sha1) * 2 + PATH_MAX + 4];
@@ -174,7 +149,7 @@ static int run_receive_hook(const char *hook_name)
 
        code = start_command(&proc);
        if (code)
-               return run_status(code, hook_name);
+               return code;
        for (cmd = commands; cmd; cmd = cmd->next) {
                if (!cmd->error_string) {
                        size_t n = snprintf(buf, sizeof(buf), "%s %s %s\n",
@@ -186,7 +161,7 @@ static int run_receive_hook(const char *hook_name)
                }
        }
        close(proc.in);
-       return run_status(finish_command(&proc), hook_name);
+       return finish_command(&proc);
 }
 
 static int run_update_hook(struct command *cmd)
@@ -203,9 +178,8 @@ static int run_update_hook(struct command *cmd)
        argv[3] = sha1_to_hex(cmd->new_sha1);
        argv[4] = NULL;
 
-       return run_status(run_command_v_opt(argv, RUN_COMMAND_NO_STDIN |
-                                       RUN_COMMAND_STDOUT_TO_STDERR),
-                       update_hook);
+       return run_command_v_opt(argv, RUN_COMMAND_NO_STDIN |
+                                       RUN_COMMAND_STDOUT_TO_STDERR);
 }
 
 static int is_ref_checked_out(const char *ref)
@@ -419,7 +393,6 @@ static void run_update_post_hook(struct command *cmd)
        argv[argc] = NULL;
        status = run_command_v_opt(argv, RUN_COMMAND_NO_STDIN
                        | RUN_COMMAND_STDOUT_TO_STDERR);
-       run_status(status, update_post_hook);
 }
 
 static void execute_commands(const char *unpacker_error)
@@ -537,7 +510,6 @@ static const char *unpack(void)
                code = run_command_v_opt(unpacker, RUN_GIT_CMD);
                if (!code)
                        return NULL;
-               run_status(code, unpacker[0]);
                return "unpack-objects abnormal exit";
        } else {
                const char *keeper[7];
@@ -563,7 +535,6 @@ static const char *unpack(void)
                ip.git_cmd = 1;
                status = start_command(&ip);
                if (status) {
-                       run_status(status, keeper[0]);
                        return "index-pack fork failed";
                }
                pack_lockfile = index_pack_lockfile(ip.out);
@@ -573,7 +544,6 @@ static const char *unpack(void)
                        reprepare_packed_git();
                        return NULL;
                }
-               run_status(status, keeper[0]);
                return "index-pack abnormal exit";
        }
 }
index 95198c5..e23b5ef 100644 (file)
@@ -362,7 +362,7 @@ static int expire_reflog(const char *ref, const unsigned char *sha1, int unused,
                } else if (cmd->updateref &&
                        (write_in_full(lock->lock_fd,
                                sha1_to_hex(cb.last_kept_sha1), 40) != 40 ||
-                        write_in_full(lock->lock_fd, "\n", 1) != 1 ||
+                        write_str_in_full(lock->lock_fd, "\n") != 1 ||
                         close_ref(lock) < 0)) {
                        status |= error("Couldn't write %s",
                                lock->lk->filename);
index 008abfe..0777dd7 100644 (file)
@@ -385,7 +385,7 @@ static int get_head_names(const struct ref *remote_refs, struct ref_states *stat
        get_fetch_map(remote_refs, &refspec, &fetch_map_tail, 0);
        matches = guess_remote_head(find_ref_by_name(remote_refs, "HEAD"),
                                    fetch_map, 1);
-       for(ref = matches; ref; ref = ref->next)
+       for (ref = matches; ref; ref = ref->next)
                string_list_append(abbrev_branch(ref->name), &states->heads);
 
        free_refs(fetch_map);
@@ -484,7 +484,7 @@ static int read_remote_branches(const char *refname,
        const char *symref;
 
        strbuf_addf(&buf, "refs/remotes/%s", rename->old);
-       if(!prefixcmp(refname, buf.buf)) {
+       if (!prefixcmp(refname, buf.buf)) {
                item = string_list_append(xstrdup(refname), rename->remote_branches);
                symref = resolve_ref(refname, orig_sha1, 1, &flag);
                if (flag & REF_ISSYMREF)
diff --git a/builtin-replace.c b/builtin-replace.c
new file mode 100644 (file)
index 0000000..fe3a647
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Builtin "git replace"
+ *
+ * Copyright (c) 2008 Christian Couder <chriscool@tuxfamily.org>
+ *
+ * Based on builtin-tag.c by Kristian Høgsberg <krh@redhat.com>
+ * and Carlos Rica <jasampler@gmail.com> that was itself based on
+ * git-tag.sh and mktag.c by Linus Torvalds.
+ */
+
+#include "cache.h"
+#include "builtin.h"
+#include "refs.h"
+#include "parse-options.h"
+
+static const char * const git_replace_usage[] = {
+       "git replace [-f] <object> <replacement>",
+       "git replace -d <object>...",
+       "git replace -l [<pattern>]",
+       NULL
+};
+
+static int show_reference(const char *refname, const unsigned char *sha1,
+                         int flag, void *cb_data)
+{
+       const char *pattern = cb_data;
+
+       if (!fnmatch(pattern, refname, 0))
+               printf("%s\n", refname);
+
+       return 0;
+}
+
+static int list_replace_refs(const char *pattern)
+{
+       if (pattern == NULL)
+               pattern = "*";
+
+       for_each_replace_ref(show_reference, (void *) pattern);
+
+       return 0;
+}
+
+typedef int (*each_replace_name_fn)(const char *name, const char *ref,
+                                   const unsigned char *sha1);
+
+static int for_each_replace_name(const char **argv, each_replace_name_fn fn)
+{
+       const char **p;
+       char ref[PATH_MAX];
+       int had_error = 0;
+       unsigned char sha1[20];
+
+       for (p = argv; *p; p++) {
+               if (snprintf(ref, sizeof(ref), "refs/replace/%s", *p)
+                                       >= sizeof(ref)) {
+                       error("replace ref name too long: %.*s...", 50, *p);
+                       had_error = 1;
+                       continue;
+               }
+               if (!resolve_ref(ref, sha1, 1, NULL)) {
+                       error("replace ref '%s' not found.", *p);
+                       had_error = 1;
+                       continue;
+               }
+               if (fn(*p, ref, sha1))
+                       had_error = 1;
+       }
+       return had_error;
+}
+
+static int delete_replace_ref(const char *name, const char *ref,
+                             const unsigned char *sha1)
+{
+       if (delete_ref(ref, sha1, 0))
+               return 1;
+       printf("Deleted replace ref '%s'\n", name);
+       return 0;
+}
+
+static int replace_object(const char *object_ref, const char *replace_ref,
+                         int force)
+{
+       unsigned char object[20], prev[20], repl[20];
+       char ref[PATH_MAX];
+       struct ref_lock *lock;
+
+       if (get_sha1(object_ref, object))
+               die("Failed to resolve '%s' as a valid ref.", object_ref);
+       if (get_sha1(replace_ref, repl))
+               die("Failed to resolve '%s' as a valid ref.", replace_ref);
+
+       if (snprintf(ref, sizeof(ref),
+                    "refs/replace/%s",
+                    sha1_to_hex(object)) > sizeof(ref) - 1)
+               die("replace ref name too long: %.*s...", 50, ref);
+       if (check_ref_format(ref))
+               die("'%s' is not a valid ref name.", ref);
+
+       if (!resolve_ref(ref, prev, 1, NULL))
+               hashclr(prev);
+       else if (!force)
+               die("replace ref '%s' already exists", ref);
+
+       lock = lock_any_ref_for_update(ref, prev, 0);
+       if (!lock)
+               die("%s: cannot lock the ref", ref);
+       if (write_ref_sha1(lock, repl, NULL) < 0)
+               die("%s: cannot update the ref", ref);
+
+       return 0;
+}
+
+int cmd_replace(int argc, const char **argv, const char *prefix)
+{
+       int list = 0, delete = 0, force = 0;
+       struct option options[] = {
+               OPT_BOOLEAN('l', NULL, &list, "list replace refs"),
+               OPT_BOOLEAN('d', NULL, &delete, "delete replace refs"),
+               OPT_BOOLEAN('f', NULL, &force, "replace the ref if it exists"),
+               OPT_END()
+       };
+
+       argc = parse_options(argc, argv, prefix, options, git_replace_usage, 0);
+
+       if (list && delete)
+               usage_msg_opt("-l and -d cannot be used together",
+                             git_replace_usage, options);
+
+       if (force && (list || delete))
+               usage_msg_opt("-f cannot be used with -d or -l",
+                             git_replace_usage, options);
+
+       /* Delete refs */
+       if (delete) {
+               if (argc < 1)
+                       usage_msg_opt("-d needs at least one argument",
+                                     git_replace_usage, options);
+               return for_each_replace_name(argv, delete_replace_ref);
+       }
+
+       /* Replace object */
+       if (!list && argc) {
+               if (argc != 2)
+                       usage_msg_opt("bad number of arguments",
+                                     git_replace_usage, options);
+               return replace_object(argv[0], argv[1], force);
+       }
+
+       /* List refs, even if "list" is not set */
+       if (argc > 1)
+               usage_msg_opt("only one pattern can be given with -l",
+                             git_replace_usage, options);
+       if (force)
+               usage_msg_opt("-f needs some arguments",
+                             git_replace_usage, options);
+
+       return list_replace_refs(argv[0]);
+}
index 5fa1789..73e6022 100644 (file)
@@ -108,7 +108,8 @@ static int update_index_refresh(int fd, struct lock_file *index_lock, int flags)
        if (read_cache() < 0)
                return error("Could not read index");
 
-       result = refresh_cache(flags) ? 1 : 0;
+       result = refresh_index(&the_index, (flags), NULL, NULL,
+                              "Unstaged changes after reset:") ? 1 : 0;
        if (write_cache(fd, active_cache, active_nr) ||
                        commit_locked_index(index_lock))
                return error ("Could not refresh index");
@@ -142,6 +143,17 @@ static void update_index_from_diff(struct diff_queue_struct *q,
        }
 }
 
+static int interactive_reset(const char *revision, const char **argv,
+                            const char *prefix)
+{
+       const char **pathspec = NULL;
+
+       if (*argv)
+               pathspec = get_pathspec(prefix, argv);
+
+       return run_add_interactive(revision, "--patch=reset", pathspec);
+}
+
 static int read_from_tree(const char *prefix, const char **argv,
                unsigned char *tree_sha1, int refresh_flags)
 {
@@ -183,6 +195,7 @@ static void prepend_reflog_action(const char *action, char *buf, size_t size)
 int cmd_reset(int argc, const char **argv, const char *prefix)
 {
        int i = 0, reset_type = NONE, update_ref_status = 0, quiet = 0;
+       int patch_mode = 0;
        const char *rev = "HEAD";
        unsigned char sha1[20], *orig = NULL, sha1_orig[20],
                                *old_orig = NULL, sha1_old_orig[20];
@@ -198,6 +211,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
                                "reset HEAD, index and working tree", MERGE),
                OPT_BOOLEAN('q', NULL, &quiet,
                                "disable showing new HEAD in hard reset and progress message"),
+               OPT_BOOLEAN('p', "patch", &patch_mode, "select hunks interactively"),
                OPT_END()
        };
 
@@ -251,6 +265,12 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
                die("Could not parse object '%s'.", rev);
        hashcpy(sha1, commit->object.sha1);
 
+       if (patch_mode) {
+               if (reset_type != NONE)
+                       die("--patch is incompatible with --{hard,mixed,soft}");
+               return interactive_reset(rev, argv + i, prefix);
+       }
+
        /* git reset tree [--] paths... can be used to
         * load chosen paths from the tree into the index without
         * affecting the working tree nor HEAD. */
@@ -261,7 +281,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
                        die("Cannot do %s reset with paths.",
                                        reset_type_names[reset_type]);
                return read_from_tree(prefix, argv + i, sha1,
-                               quiet ? REFRESH_QUIET : REFRESH_SAY_CHANGED);
+                               quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN);
        }
        if (reset_type == NONE)
                reset_type = MIXED; /* by default */
@@ -302,7 +322,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
                break;
        case MIXED: /* Report what has not been updated. */
                update_index_refresh(0, NULL,
-                               quiet ? REFRESH_QUIET : REFRESH_SAY_CHANGED);
+                               quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN);
                break;
        }
 
index 47fb9f7..37e528e 100644 (file)
@@ -44,6 +44,7 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext
                NULL,
                NULL,
                NULL,
+               NULL,
        };
        struct child_process po;
        int i;
@@ -53,6 +54,8 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext
                argv[i++] = "--thin";
        if (args->use_ofs_delta)
                argv[i++] = "--delta-base-offset";
+       if (args->quiet)
+               argv[i++] = "-q";
        memset(&po, 0, sizeof(po));
        po.argv = argv;
        po.in = -1;
index 6a3812e..4d4a3c8 100644 (file)
@@ -56,7 +56,7 @@ static void insert_one_record(struct shortlog *log,
        /* copy author name to namebuf, to support matching on both name and email */
        memcpy(namebuf, author, boemail - author);
        len = boemail - author;
-       while(len > 0 && isspace(namebuf[len-1]))
+       while (len > 0 && isspace(namebuf[len-1]))
                len--;
        namebuf[len] = 0;
 
index 01bea3b..3510a86 100644 (file)
@@ -6,8 +6,8 @@
 #include "parse-options.h"
 
 static const char* show_branch_usage[] = {
-    "git show-branch [--sparse] [--current] [--all] [--remotes] [--topo-order] [--more=count | --list | --independent | --merge-base] [--topics] [--color] [<refs>...]",
-    "--reflog[=n[,b]] [--list] [--color] <branch>",
+    "git show-branch [-a|--all] [-r|--remotes] [--topo-order | --date-order] [--current] [--color | --no-color] [--sparse] [--more=<n> | --list | --independent | --merge-base] [--no-name | --sha1-name] [--topics] [<rev> | <glob>]...",
+    "git show-branch (-g|--reflog)[=<n>[,<base>]] [--list] [<ref>]",
     NULL
 };
 
@@ -665,7 +665,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
                OPT_BOOLEAN(0, "sha1-name", &sha1_name,
                            "name commits with their object names"),
                OPT_BOOLEAN(0, "merge-base", &merge_base,
-                           "act like git merge-base -a"),
+                           "show possible merge bases"),
                OPT_BOOLEAN(0, "independent", &independent,
                            "show refs unreachable from any other ref"),
                OPT_BOOLEAN(0, "topo-order", &lifo,
index a51a6d1..c479018 100644 (file)
@@ -390,7 +390,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
                OPT_BOOLEAN('s', NULL, &sign, "annotated and GPG-signed tag"),
                OPT_STRING('u', NULL, &keyid, "key-id",
                                        "use another key to sign the tag"),
-               OPT_BOOLEAN('f', NULL, &force, "replace the tag if exists"),
+               OPT_BOOLEAN('f', "force", &force, "replace the tag if exists"),
 
                OPT_GROUP("Tag listing options"),
                {
index 3d650a1..685566e 100644 (file)
@@ -497,6 +497,8 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix)
        int i;
        unsigned char sha1[20];
 
+       read_replace_refs = 0;
+
        git_config(git_default_config, NULL);
 
        quiet = !isatty(2);
diff --git a/builtin-update-server-info.c b/builtin-update-server-info.c
new file mode 100644 (file)
index 0000000..2b3fddc
--- /dev/null
@@ -0,0 +1,25 @@
+#include "cache.h"
+#include "builtin.h"
+#include "parse-options.h"
+
+static const char * const update_server_info_usage[] = {
+       "git update-server-info [--force]",
+       NULL
+};
+
+int cmd_update_server_info(int argc, const char **argv, const char *prefix)
+{
+       int force = 0;
+       struct option options[] = {
+               OPT_BOOLEAN('f', "force", &force,
+                       "update the info files from scratch"),
+               OPT_END()
+       };
+
+       argc = parse_options(argc, argv, prefix, options,
+                            update_server_info_usage, 0);
+       if (argc > 0)
+               usage_with_options(update_server_info_usage, options);
+
+       return !!update_server_info(force);
+}
index a18df04..b6079ae 100644 (file)
@@ -2,13 +2,18 @@
 #include "cache.h"
 #include "pack.h"
 #include "pack-revindex.h"
+#include "parse-options.h"
 
 #define MAX_CHAIN 50
 
-static void show_pack_info(struct packed_git *p)
+#define VERIFY_PACK_VERBOSE 01
+#define VERIFY_PACK_STAT_ONLY 02
+
+static void show_pack_info(struct packed_git *p, unsigned int flags)
 {
        uint32_t nr_objects, i;
        int cnt;
+       int stat_only = flags & VERIFY_PACK_STAT_ONLY;
        unsigned long chain_histogram[MAX_CHAIN+1], baseobjects;
 
        nr_objects = p->num_objects;
@@ -31,16 +36,19 @@ static void show_pack_info(struct packed_git *p)
                type = packed_object_info_detail(p, offset, &size, &store_size,
                                                 &delta_chain_length,
                                                 base_sha1);
-               printf("%s ", sha1_to_hex(sha1));
+               if (!stat_only)
+                       printf("%s ", sha1_to_hex(sha1));
                if (!delta_chain_length) {
-                       printf("%-6s %lu %lu %"PRIuMAX"\n",
-                              type, size, store_size, (uintmax_t)offset);
+                       if (!stat_only)
+                               printf("%-6s %lu %lu %"PRIuMAX"\n",
+                                      type, size, store_size, (uintmax_t)offset);
                        baseobjects++;
                }
                else {
-                       printf("%-6s %lu %lu %"PRIuMAX" %u %s\n",
-                              type, size, store_size, (uintmax_t)offset,
-                              delta_chain_length, sha1_to_hex(base_sha1));
+                       if (!stat_only)
+                               printf("%-6s %lu %lu %"PRIuMAX" %u %s\n",
+                                      type, size, store_size, (uintmax_t)offset,
+                                      delta_chain_length, sha1_to_hex(base_sha1));
                        if (delta_chain_length <= MAX_CHAIN)
                                chain_histogram[delta_chain_length]++;
                        else
@@ -65,10 +73,12 @@ static void show_pack_info(struct packed_git *p)
                       chain_histogram[0] > 1 ? "s" : "");
 }
 
-static int verify_one_pack(const char *path, int verbose)
+static int verify_one_pack(const char *path, unsigned int flags)
 {
        char arg[PATH_MAX];
        int len;
+       int verbose = flags & VERIFY_PACK_VERBOSE;
+       int stat_only = flags & VERIFY_PACK_STAT_ONLY;
        struct packed_git *pack;
        int err;
 
@@ -104,50 +114,53 @@ static int verify_one_pack(const char *path, int verbose)
                return error("packfile %s not found.", arg);
 
        install_packed_git(pack);
-       err = verify_pack(pack);
 
-       if (verbose) {
+       if (!stat_only)
+               err = verify_pack(pack);
+       else
+               err = open_pack_index(pack);
+
+       if (verbose || stat_only) {
                if (err)
                        printf("%s: bad\n", pack->pack_name);
                else {
-                       show_pack_info(pack);
-                       printf("%s: ok\n", pack->pack_name);
+                       show_pack_info(pack, flags);
+                       if (!stat_only)
+                               printf("%s: ok\n", pack->pack_name);
                }
        }
 
        return err;
 }
 
-static const char verify_pack_usage[] = "git verify-pack [-v] <pack>...";
+static const char * const verify_pack_usage[] = {
+       "git verify-pack [-v|--verbose] [-s|--stat-only] <pack>...",
+       NULL
+};
 
 int cmd_verify_pack(int argc, const char **argv, const char *prefix)
 {
        int err = 0;
-       int verbose = 0;
-       int no_more_options = 0;
-       int nothing_done = 1;
+       unsigned int flags = 0;
+       int i;
+       const struct option verify_pack_options[] = {
+               OPT_BIT('v', "verbose", &flags, "verbose",
+                       VERIFY_PACK_VERBOSE),
+               OPT_BIT('s', "stat-only", &flags, "show statistics only",
+                       VERIFY_PACK_STAT_ONLY),
+               OPT_END()
+       };
 
        git_config(git_default_config, NULL);
-       while (1 < argc) {
-               if (!no_more_options && argv[1][0] == '-') {
-                       if (!strcmp("-v", argv[1]))
-                               verbose = 1;
-                       else if (!strcmp("--", argv[1]))
-                               no_more_options = 1;
-                       else
-                               usage(verify_pack_usage);
-               }
-               else {
-                       if (verify_one_pack(argv[1], verbose))
-                               err = 1;
-                       discard_revindex();
-                       nothing_done = 0;
-               }
-               argc--; argv++;
+       argc = parse_options(argc, argv, prefix, verify_pack_options,
+                            verify_pack_usage, 0);
+       if (argc < 1)
+               usage_with_options(verify_pack_usage, verify_pack_options);
+       for (i = 0; i < argc; i++) {
+               if (verify_one_pack(argv[i], flags))
+                       err = 1;
+               discard_revindex();
        }
 
-       if (nothing_done)
-               usage(verify_pack_usage);
-
        return err;
 }
index 7f7fda4..9f482c2 100644 (file)
 #include "tag.h"
 #include "run-command.h"
 #include <signal.h>
+#include "parse-options.h"
 
-static const char builtin_verify_tag_usage[] =
-               "git verify-tag [-v|--verbose] <tag>...";
+static const char * const verify_tag_usage[] = {
+               "git verify-tag [-v|--verbose] <tag>...",
+               NULL
+};
 
 #define PGP_SIGNATURE "-----BEGIN PGP SIGNATURE-----"
 
@@ -89,17 +92,17 @@ static int verify_tag(const char *name, int verbose)
 int cmd_verify_tag(int argc, const char **argv, const char *prefix)
 {
        int i = 1, verbose = 0, had_error = 0;
+       const struct option verify_tag_options[] = {
+               OPT__VERBOSE(&verbose),
+               OPT_END()
+       };
 
        git_config(git_default_config, NULL);
 
-       if (argc > 1 &&
-           (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--verbose"))) {
-               verbose = 1;
-               i++;
-       }
-
+       argc = parse_options(argc, argv, prefix, verify_tag_options,
+                            verify_tag_usage, PARSE_OPT_KEEP_ARGV0);
        if (argc <= i)
-               usage(builtin_verify_tag_usage);
+               usage_with_options(verify_tag_usage, verify_tag_options);
 
        /* sometimes the program was terminated because this signal
         * was received in the process of writing the gpg input: */