Merge branch 'as/test-name-alias-uniquely'
authorJunio C Hamano <gitster@pobox.com>
Tue, 8 Jan 2013 21:23:21 +0000 (13:23 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 8 Jan 2013 21:23:22 +0000 (13:23 -0800)
A few short-and-bland aliases used in the tests were interfering
with git-custom command in user's $PATH.

* as/test-name-alias-uniquely:
  Use longer alias names in subdirectory tests

234 files changed:
.gitignore
Documentation/Makefile
Documentation/RelNotes/1.8.1.txt [new file with mode: 0644]
Documentation/RelNotes/1.8.2.txt [new file with mode: 0644]
Documentation/SubmittingPatches
Documentation/config.txt
Documentation/diff-config.txt
Documentation/diff-options.txt
Documentation/git-commit.txt
Documentation/git-config.txt
Documentation/git-cvsimport.txt
Documentation/git-fast-import.txt
Documentation/git-format-patch.txt
Documentation/git-log.txt
Documentation/git-notes.txt
Documentation/git-push.txt
Documentation/git-remote-helpers.txt
Documentation/git-remote-testgit.txt
Documentation/git-rm.txt
Documentation/git-send-email.txt
Documentation/git-status.txt
Documentation/git-submodule.txt
Documentation/git-symbolic-ref.txt
Documentation/git.txt
Documentation/gitattributes.txt
Documentation/gitmodules.txt
Documentation/howto/new-command.txt [new file with mode: 0644]
Documentation/mailmap.txt
Documentation/pretty-formats.txt
Documentation/pt_BR/gittutorial.txt [deleted file]
Documentation/rev-list-options.txt
Documentation/technical/api-argv-array.txt
Documentation/technical/api-history-graph.txt
Documentation/technical/api-strbuf.txt
Documentation/technical/api-string-list.txt
Documentation/user-manual.txt
GIT-VERSION-GEN
Makefile
RelNotes
abspath.c
advice.c
advice.h
archive.c
argv-array.c
argv-array.h
attr.c
bisect.c
bisect.h
builtin.h
builtin/apply.c
builtin/blame.c
builtin/commit.c
builtin/config.c
builtin/describe.c
builtin/diff-index.c
builtin/diff.c
builtin/fast-export.c
builtin/fetch-pack.c
builtin/log.c
builtin/ls-files.c
builtin/ls-tree.c
builtin/merge.c
builtin/pack-objects.c
builtin/push.c
builtin/replace.c
builtin/rev-list.c
builtin/rm.c
builtin/send-pack.c
builtin/shortlog.c
builtin/show-ref.c
builtin/symbolic-ref.c
builtin/update-index.c
cache-tree.c
cache-tree.h
cache.h
commit.c
commit.h
compat/cygwin.c
compat/fnmatch/fnmatch.c
compat/mingw.c
compat/mingw.h
compat/nedmalloc/nedmalloc.c
compat/terminal.c
config.c
config.mak.in
configure.ac
contrib/completion/git-completion.bash
contrib/completion/git-completion.tcsh [new file with mode: 0644]
contrib/completion/git-completion.zsh [new file with mode: 0644]
contrib/completion/git-prompt.sh
contrib/emacs/git.el
contrib/remote-helpers/Makefile [new file with mode: 0644]
contrib/remote-helpers/git-remote-hg [new file with mode: 0755]
contrib/remote-helpers/test-hg-bidi.sh [new file with mode: 0755]
contrib/remote-helpers/test-hg-hg-git.sh [new file with mode: 0755]
contrib/remote-helpers/test-hg.sh [new file with mode: 0755]
contrib/subtree/.gitignore
contrib/subtree/git-subtree.txt
contrib/svn-fe/svn-fe.c
contrib/svn-fe/svnrdump_sim.py [new file with mode: 0755]
diff.c
diff.h
dir.c
dir.h
editor.c
fetch-pack.c [new file with mode: 0644]
fsck.c
git-compat-util.h
git-cvsimport.perl
git-cvsserver.perl
git-filter-branch.sh
git-p4.py
git-remote-testgit [new file with mode: 0755]
git-remote-testpy.py [moved from git-remote-testgit.py with 99% similarity]
git-send-email.perl
git-sh-setup.sh
git-submodule.sh
git.c
git_remote_helpers/git/importer.py
gitweb/gitweb.perl
graph.c
http-push.c
http.c
http.h
ident.c
imap-send.c
log-tree.c
mailmap.c
merge-recursive.h
merge.c [new file with mode: 0644]
mergetools/p4merge
notes.c
notes.h
pager.c
parse-options.c
parse-options.h
path.c
perl/Git.pm
perl/Git/SVN/Prompt.pm
po/de.po
po/git.pot
po/sv.po
po/vi.po
pretty.c
refs.c
remote-curl.c
remote-testsvn.c [new file with mode: 0644]
remote.c
revision.c
revision.h
run-command.c
run-command.h
send-pack.c [new file with mode: 0644]
sequencer.c
setup.c
sha1_file.c
strbuf.c
strbuf.h
string-list.c
string-list.h
submodule.c
submodule.h
t/Makefile
t/lib-gettext.sh
t/lib-httpd/apache.conf
t/t0000-basic.sh
t/t0003-attributes.sh
t/t0007-git-var.sh [new file with mode: 0755]
t/t0060-path-utils.sh
t/t0063-string-list.sh
t/t1300-repo-config.sh
t/t1401-symbolic-ref.sh
t/t1450-fsck.sh
t/t2020-checkout-detach.sh
t/t2203-add-intent.sh
t/t3001-ls-files-others-exclude.sh
t/t3600-rm.sh
t/t4014-format-patch.sh
t/t4041-diff-submodule-option.sh
t/t4055-diff-context.sh [new file with mode: 0755]
t/t4201-shortlog.sh
t/t4202-log.sh
t/t4203-mailmap.sh
t/t5002-archive-attr-pattern.sh [new file with mode: 0755]
t/t5516-fetch-push.sh
t/t5535-fetch-push-symref.sh [new file with mode: 0755]
t/t5551-http-fetch.sh
t/t5800-remote-testpy.sh [moved from t/t5800-remote-helpers.sh with 87% similarity]
t/t5801-remote-helpers.sh [new file with mode: 0755]
t/t6006-rev-list-format.sh
t/t6050-replace.sh
t/t6130-pathspec-noglob.sh [new file with mode: 0755]
t/t7003-filter-branch.sh
t/t7400-submodule-basic.sh
t/t7403-submodule-sync.sh
t/t7406-submodule-update.sh
t/t7407-submodule-foreach.sh
t/t7502-commit.sh
t/t9001-send-email.sh
t/t9020-remote-svn.sh [new file with mode: 0755]
t/t9200-git-cvsexportcommit.sh
t/t9350-fast-export.sh
t/t9400-git-cvsserver-server.sh
t/t9401-git-cvsserver-crlf.sh
t/t9502-gitweb-standalone-parse-output.sh
t/t9604-cvsimport-timestamps.sh [new file with mode: 0755]
t/t9604/cvsroot/.gitattributes [new file with mode: 0644]
t/t9604/cvsroot/CVSROOT/.gitignore [new file with mode: 0644]
t/t9604/cvsroot/module/a,v [new file with mode: 0644]
t/t9700/test.pl
t/t9800-git-p4-basic.sh
t/t9810-git-p4-rcs.sh
t/t9814-git-p4-rename.sh
t/t9902-completion.sh
t/test-lib-functions.sh
t/test-lib.sh
test-path-utils.c
test-string-list.c
test-svn-fe.c
transport-helper.c
transport.c
transport.h
tree-walk.c
unpack-trees.c
upload-pack.c
usage.c
utf8.c
utf8.h
vcs-svn/fast_export.c
vcs-svn/fast_export.h
vcs-svn/svndump.c
vcs-svn/svndump.h
wrapper.c
write_or_die.c

index a188a82..8e8dc27 100644 (file)
@@ -1,8 +1,8 @@
 /GIT-BUILD-OPTIONS
 /GIT-CFLAGS
 /GIT-LDFLAGS
-/GIT-GUI-VARS
 /GIT-PREFIX
+/GIT-PYTHON-VARS
 /GIT-SCRIPT-DEFINES
 /GIT-USER-AGENT
 /GIT-VERSION-FILE
 /git-remote-ftps
 /git-remote-fd
 /git-remote-ext
-/git-remote-testgit
+/git-remote-testpy
+/git-remote-testsvn
 /git-repack
 /git-replace
 /git-repo-config
 /git-whatchanged
 /git-write-tree
 /git-core-*/?*
-/gitk-git/gitk-wish
 /gitweb/GITWEB-BUILD-OPTIONS
 /gitweb/gitweb.cgi
 /gitweb/static/gitweb.js
index fe9a91d..e53d333 100644 (file)
@@ -21,6 +21,7 @@ ARTICLES += git-tools
 ARTICLES += git-bisect-lk2009
 # with their own formatting rules.
 SP_ARTICLES = user-manual
+SP_ARTICLES += howto/new-command
 SP_ARTICLES += howto/revert-branch-rebase
 SP_ARTICLES += howto/using-merge-subtree
 SP_ARTICLES += howto/using-signed-tag-in-pull-request
@@ -31,7 +32,6 @@ SP_ARTICLES += howto/separating-topic-branches
 SP_ARTICLES += howto/revert-a-faulty-merge
 SP_ARTICLES += howto/recover-corrupted-blob-object
 SP_ARTICLES += howto/rebuild-from-update-hook
-SP_ARTICLES += howto/rebuild-from-update-hook
 SP_ARTICLES += howto/rebase-from-internal-branch
 SP_ARTICLES += howto/maintain-git
 API_DOCS = $(patsubst %.txt,%,$(filter-out technical/api-index-skel.txt technical/api-index.txt, $(wildcard technical/api-*.txt)))
diff --git a/Documentation/RelNotes/1.8.1.txt b/Documentation/RelNotes/1.8.1.txt
new file mode 100644 (file)
index 0000000..d6f9555
--- /dev/null
@@ -0,0 +1,241 @@
+Git v1.8.1 Release Notes
+========================
+
+Backward compatibility notes
+----------------------------
+
+In the next major release (not *this* one), we will change the
+behavior of the "git push" command.
+
+When "git push [$there]" does not say what to push, we have used the
+traditional "matching" semantics so far (all your branches were sent
+to the remote as long as there already are branches of the same name
+over there).  We will use the "simple" semantics that pushes the
+current branch to the branch with the same name, only when the current
+branch is set to integrate with that remote branch.  There is a user
+preference configuration variable "push.default" to change this, and
+"git push" will warn about the upcoming change until you set this
+variable in this release.
+
+"git branch --set-upstream" is deprecated and may be removed in a
+relatively distant future.  "git branch [-u|--set-upstream-to]" has
+been introduced with a saner order of arguments to replace it.
+
+
+Updates since v1.8.0
+--------------------
+
+UI, Workflows & Features
+
+ * Command-line completion scripts for tcsh and zsh have been added.
+
+ * "git-prompt" scriptlet (in contrib/completion) can be told to paint
+   pieces of the hints in the prompt string in colors.
+
+ * Some documentation pages that used to ship only in the plain text
+   format are now formatted in HTML as well.
+
+ * We used to have a workaround for a bug in ancient "less" that
+   causes it to exit without any output when the terminal is resized.
+   The bug has been fixed in "less" version 406 (June 2007), and the
+   workaround has been removed in this release.
+
+ * When "git checkout" checks out a branch, it tells the user how far
+   behind (or ahead) the new branch is relative to the remote tracking
+   branch it builds upon.  The message now also advises how to sync
+   them up by pushing or pulling.  This can be disabled with the
+   advice.statusHints configuration variable.
+
+ * "git config --get" used to diagnose presence of multiple
+   definitions of the same variable in the same configuration file as
+   an error, but it now applies the "last one wins" rule used by the
+   internal configuration logic.  Strictly speaking, this may be an
+   API regression but it is expected that nobody will notice it in
+   practice.
+
+ * A new configuration variable "diff.context" can be used to
+   give the default number of context lines in the patch output, to
+   override the hardcoded default of 3 lines.
+
+ * "git format-patch" learned the "--notes=<ref>" option to give
+   notes for the commit after the three-dash lines in its output.
+
+ * "git log -p -S<string>" now looks for the <string> after applying
+   the textconv filter (if defined); earlier it inspected the contents
+   of the blobs without filtering.
+
+ * "git log --grep=<pcre>" learned to honor the "grep.patterntype"
+   configuration set to "perl".
+
+ * "git replace -d <object>" now interprets <object> as an extended
+   SHA-1 (e.g. HEAD~4 is allowed), instead of only accepting full hex
+   object name.
+
+ * "git rm $submodule" used to punt on removing a submodule working
+   tree to avoid losing the repository embedded in it.  Because
+   recent git uses a mechanism to separate the submodule repository
+   from the submodule working tree, "git rm" learned to detect this
+   case and removes the submodule working tree when it is safe to do so.
+
+ * "git send-email" used to prompt for the sender address, even when
+   the committer identity is well specified (e.g. via user.name and
+   user.email configuration variables).  The command no longer gives
+   this prompt when not necessary.
+
+ * "git send-email" did not allow non-address garbage strings to
+   appear after addresses on Cc: lines in the patch files (and when
+   told to pick them up to find more recipients), e.g.
+
+     Cc: Stable Kernel <stable@k.org> # for v3.2 and up
+
+   The command now strips " # for v3.2 and up" part before adding the
+   remainder of this line to the list of recipients.
+
+ * "git submodule add" learned to add a new submodule at the same
+   path as the path where an unrelated submodule was bound to in an
+   existing revision via the "--name" option.
+
+ * "git submodule sync" learned the "--recursive" option.
+
+ * "diff.submodule" configuration variable can be used to give custom
+   default value to the "git diff --submodule" option.
+
+ * "git symbolic-ref" learned the "-d $symref" option to delete the
+   named symbolic ref, which is more intuitive way to spell it than
+   "update-ref -d --no-deref $symref".
+
+
+Foreign Interface
+
+ * "git cvsimport" can be told to record timezones (other than GMT)
+   per-author via its author info file.
+
+ * The remote helper interface to interact with subversion
+   repositories (one of the GSoC 2012 projects) has been merged.
+
+ * A new remote-helper interface for Mercurial has been added to
+   contrib/remote-helpers.
+
+ * The documentation for git(1) was pointing at a page at an external
+   site for the list of authors that no longer existed.  The link has
+   been updated to point at an alternative site.
+
+
+Performance, Internal Implementation, etc.
+
+ * Compilation on Cygwin with newer header files are supported now.
+
+ * A couple of low-level implementation updates on MinGW.
+
+ * The logic to generate the initial advertisement from "upload-pack"
+   (i.e. what is invoked by "git fetch" on the other side of the
+   connection) to list what refs are available in the repository has
+   been optimized.
+
+ * The logic to find set of attributes that match a given path has
+   been optimized.
+
+ * Use preloadindex in "git diff-index" and "git update-index", which
+   has a nice speedup on systems with slow stat calls (and even on
+   Linux).
+
+
+Also contains minor documentation updates and code clean-ups.
+
+
+Fixes since v1.8.0
+------------------
+
+Unless otherwise noted, all the fixes since v1.8.0 in the maintenance
+track are contained in this release (see release notes to them for
+details).
+
+ * The configuration parser had an unnecessary hardcoded limit on
+   variable names that was not checked consistently.
+
+ * The "say" function in the test scaffolding incorrectly allowed
+   "echo" to interpret "\a" as if it were a C-string asking for a
+   BEL output.
+
+ * "git mergetool" feeds /dev/null as a common ancestor when dealing
+   with an add/add conflict, but p4merge backend cannot handle
+   it. Work it around by passing a temporary empty file.
+
+ * "git log -F -E --grep='<ere>'" failed to use the given <ere>
+   pattern as extended regular expression, and instead looked for the
+   string literally.
+
+ * "git grep -e pattern <tree>" asked the attribute system to read
+   "<tree>:.gitattributes" file in the working tree, which was
+   nonsense.
+
+ * A symbolic ref refs/heads/SYM was not correctly removed with "git
+   branch -d SYM"; the command removed the ref pointed by SYM
+   instead.
+
+ * Update "remote tracking branch" in the documentation to
+   "remote-tracking branch".
+
+ * "git pull --rebase" run while the HEAD is detached tried to find
+   the upstream branch of the detached HEAD (which by definition
+   does not exist) and emitted unnecessary error messages.
+
+ * The refs/replace hierarchy was not mentioned in the
+   repository-layout docs.
+
+ * Various rfc2047 quoting issues around a non-ASCII name on the
+   From: line in the output from format-patch have been corrected.
+
+ * Sometimes curl_multi_timeout() function suggested a wrong timeout
+   value when there is no file descriptor to wait on and the http
+   transport ended up sleeping for minutes in select(2) system call.
+   A workaround has been added for this.
+
+ * For a fetch refspec (or the result of applying wildcard on one),
+   we always want the RHS to map to something inside "refs/"
+   hierarchy, but the logic to check it was not exactly right.
+   (merge 5c08c1f jc/maint-fetch-tighten-refname-check later to maint).
+
+ * "git diff -G<pattern>" did not honor textconv filter when looking
+   for changes.
+
+ * Some HTTP servers ask for auth only during the actual packing phase
+   (not in ls-remote phase); this is not really a recommended
+   configuration, but the clients used to fail to authenticate with
+   such servers.
+   (merge 2e736fd jk/maint-http-half-auth-fetch later to maint).
+
+ * "git p4" used to try expanding malformed "$keyword$" that spans
+   across multiple lines.
+
+ * Syntax highlighting in "gitweb" was not quite working.
+
+ * RSS feed from "gitweb" had a xss hole in its title output.
+
+ * "git config --path $key" segfaulted on "[section] key" (a boolean
+   "true" spelled without "=", not "[section] key = true").
+
+ * "git checkout -b foo" while on an unborn branch did not say
+   "Switched to a new branch 'foo'" like other cases.
+
+ * Various codepaths have workaround for a common misconfiguration to
+   spell "UTF-8" as "utf8", but it was not used uniformly.  Most
+   notably, mailinfo (which is used by "git am") lacked this support.
+
+ * We failed to mention a file without any content change but whose
+   permission bit was modified, or (worse yet) a new file without any
+   content in the "git diff --stat" output.
+
+ * When "--stat-count" hides a diffstat for binary contents, the total
+   number of added and removed lines at the bottom was computed
+   incorrectly.
+
+ * When "--stat-count" hides a diffstat for unmerged paths, the total
+   number of affected files at the bottom of the "diff --stat" output
+   was computed incorrectly.
+
+ * "diff --shortstat" miscounted the total number of affected files
+   when there were unmerged paths.
+
+ * "update-ref -d --deref SYM" to delete a ref through a symbolic ref
+   that points to it did not remove it correctly.
diff --git a/Documentation/RelNotes/1.8.2.txt b/Documentation/RelNotes/1.8.2.txt
new file mode 100644 (file)
index 0000000..92de751
--- /dev/null
@@ -0,0 +1,147 @@
+Git v1.8.2 Release Notes
+========================
+
+Backward compatibility notes
+----------------------------
+
+In the upcoming major release (tentatively called 1.8.2), we will
+change the behavior of the "git push" command.
+
+When "git push [$there]" does not say what to push, we have used the
+traditional "matching" semantics so far (all your branches were sent
+to the remote as long as there already are branches of the same name
+over there).  We will use the "simple" semantics that pushes the
+current branch to the branch with the same name, only when the current
+branch is set to integrate with that remote branch.  There is a user
+preference configuration variable "push.default" to change this.
+
+
+Updates since v1.8.1
+--------------------
+
+UI, Workflows & Features
+
+ * Initial ports to QNX and z/OS UNIX System Services have started.
+
+ * Output from the tests is coloured using "green is okay, yellow is
+   questionable, red is bad and blue is informative" scheme.
+
+ * In bare repositories, "git shortlog" and other commands now read
+   mailmap files from the tip of the history, to help running these
+   tools in server settings.
+
+ * Color specifiers, e.g. "%C(blue)Hello%C(reset)", used in the
+   "--format=" option of "git log" and friends can be disabled when
+   the output is not sent to a terminal by prefixing them with
+   "auto,", e.g. "%C(auto,blue)Hello%C(auto,reset)".
+
+ * Scripts can ask Git that wildcard patterns in pathspecs they give do
+   not have any significance, i.e. take them as literal strings.
+
+ * "git fetch --mirror" and fetch that uses other forms of refspec
+   with wildcard used to attempt to update a symbolic ref that match
+   the wildcard on the receiving end, which made little sense (the
+   real ref that is pointed at by the symbolic ref would be updated
+   anyway).  Symbolic refs no longer are affected by such a fetch.
+
+ * "git push" now requires "-f" to update a tag, even if it is a
+   fast-forward, as tags are meant to be fixed points.
+
+ * "git submodule" started learning a new mode to integrate with the
+   tip of the remote branch (as opposed to integrating with the commit
+   recorded in the superproject's gitlink).
+
+
+Foreign Interface
+
+ * "git fast-export" has been updated for its use in the context of
+   the remote helper interface.
+
+
+Performance, Internal Implementation, etc.
+
+ * "git fsck" has been taught to be pickier about entries in tree
+   objects that should not be there, e.g. ".", ".git", and "..".
+
+ * Matching paths with common forms of pathspecs that contain wildcard
+   characters has been optimized further.
+
+ * The implementation of "imap-send" has been updated to reuse xml
+   quoting code from http-push codepath.
+
+
+Also contains minor documentation updates and code clean-ups.
+
+
+Fixes since v1.8.1
+------------------
+
+Unless otherwise noted, all the fixes since v1.8.1 in the maintenance
+track are contained in this release (see release notes to them for
+details).
+
+ * An element on GIT_CEILING_DIRECTORIES list that does not name the
+   real path to a directory (i.e. a symbolic link) could have caused
+   the GIT_DIR discovery logic to escape the ceiling.
+   (merge 059b379 mh/ceiling later to maint).
+
+ * t4014, t9502 and t0200 tests had various portability issues that
+   broke on OpenBSD.
+   (merge 27f6342 jc/maint-test-portability later to maint).
+
+ * t9020 and t3600 tests had various portability issues.
+   (merge 5a02966 jc/test-portability later to maint).
+
+ * t9200 runs "cvs init" on a directory that already exists, but a
+   platform can configure this fail for the current user (e.g. you
+   need to be in the cvsadmin group on NetBSD 6.0).
+   (merge 8666df0 jc/test-cvs-no-init-in-existing-dir later to maint).
+
+ * The behaviour visible to the end users was confusing, when they
+   attempt to kill a process spawned in the editor that was in turn
+   launched by Git with SIGINT (or SIGQUIT), as Git would catch that
+   signal and die.  We ignore these signals now.
+   (merge 1250857 pf/editor-ignore-sigint later to maint).
+
+ * After failing to create a temporary file using mkstemp(), failing
+   pathname was not reported correctly on some platforms.
+   (merge f7be59b jc/mkstemp-more-careful-error-reporting later to maint).
+
+ * The attribute mechanism didn't allow limiting attributes to be
+   applied to only a single directory itself with "path/" like the
+   exclude mechanism does.
+   (merge 94bc671 ja/directory-attrs later to maint).
+
+ * The way "git svn" asked for password using SSH_ASKPASS and
+   GIT_ASKPASS was not in line with the rest of the system.
+   (merge e9263e4 ss/svn-prompt later to maint).
+
+ * The --graph code fell into infinite loop when asked to do what the
+   code did not expect.
+   (merge 656197a mk/maint-graph-infinity-loop later to maint).
+
+ * http transport was wrong to ask for the username when the
+   authentication is done by certificate identity.
+   (merge 75e9a40 rb/http-cert-cred-no-username-prompt later to maint).
+
+ * "git pack-refs" that ran in parallel to another process that
+   created new refs had a nasty race.
+   (merge b3f1280 jk/repack-ref-racefix later to maint).
+
+ * After "git add -N" and then writing a tree object out of the
+   index, the cache-tree data structure got corrupted.
+   (merge eec3e7e nd/invalidate-i-t-a-cache-tree later to maint).
+
+ * "gitweb", when sorting by age to show repositories with new
+   activities first, used to sort repositories with absolutely
+   nothing in it early, which was not very useful.
+   (merge 28dae18 md/gitweb-sort-by-age later to maint).
+
+ * When a line to be wrapped has a solid run of non space characters
+   whose length exactly is the wrap width, "git shortlog -w" failed
+   to add a newline after such a line.
+   (merge e0db176 sp/shortlog-missing-lf later to maint).
+
+ * Some shells do not behave correctly when IFS is unset; work it
+   around by explicitly setting it to the default value.
+   (merge 393050c jc/maint-fbsd-sh-ifs-workaround later to maint).
index c34c9d1..75935d5 100644 (file)
@@ -174,7 +174,8 @@ message starts, you can put a "From: " line to name that person.
 
 You often want to add additional explanation about the patch,
 other than the commit message itself.  Place such "cover letter"
-material between the three dash lines and the diffstat.
+material between the three dash lines and the diffstat. Git-notes
+can also be inserted using the `--notes` option.
 
 Do not attach the patch as a MIME attachment, compressed or not.
 Do not let your e-mail client send quoted-printable.  Do not let
index d1de857..53c4ca1 100644 (file)
@@ -140,10 +140,11 @@ advice.*::
        can tell Git that you do not need help by setting these to 'false':
 +
 --
-       pushNonFastForward::
+       pushUpdateRejected::
                Set this variable to 'false' if you want to disable
-               'pushNonFFCurrent', 'pushNonFFDefault', and
-               'pushNonFFMatching' simultaneously.
+               'pushNonFFCurrent', 'pushNonFFDefault',
+               'pushNonFFMatching', and 'pushAlreadyExists'
+               simultaneously.
        pushNonFFCurrent::
                Advice shown when linkgit:git-push[1] fails due to a
                non-fast-forward update to the current branch.
@@ -158,11 +159,15 @@ advice.*::
                'matching refs' explicitly (i.e. you used ':', or
                specified a refspec that isn't your current branch) and
                it resulted in a non-fast-forward error.
+       pushAlreadyExists::
+               Shown when linkgit:git-push[1] rejects an update that
+               does not qualify for fast-forwarding (e.g., a tag.)
        statusHints::
                Show directions on how to proceed from the current
-               state in the output of linkgit:git-status[1] and in
+               state in the output of linkgit:git-status[1], in
                the template shown when writing commit messages in
-               linkgit:git-commit[1].
+               linkgit:git-commit[1], and in the help message shown
+               by linkgit:git-checkout[1] when switching branch.
        commitBeforeMerge::
                Advice shown when linkgit:git-merge[1] refuses to
                merge to avoid overwriting local changes.
@@ -538,14 +543,14 @@ core.pager::
        `LESS` variable to some other value.  Alternately,
        these settings can be overridden on a project or
        global basis by setting the `core.pager` option.
-       Setting `core.pager` has no affect on the `LESS`
+       Setting `core.pager` has no effect on the `LESS`
        environment variable behaviour above, so if you want
        to override git's default settings this way, you need
        to be explicit.  For example, to disable the S option
        in a backward compatible manner, set `core.pager`
-       to `less -+$LESS -FRX`.  This will be passed to the
-       shell by git, which will translate the final command to
-       `LESS=FRSX less -+FRSX -FRX`.
+       to `less -+S`.  This will be passed to the shell by
+       git, which will translate the final command to
+       `LESS=FRSX less -+S`.
 
 core.whitespace::
        A comma separated list of common whitespace problems to
@@ -1516,6 +1521,14 @@ mailmap.file::
        subdirectory, or somewhere outside of the repository itself.
        See linkgit:git-shortlog[1] and linkgit:git-blame[1].
 
+mailmap.blob::
+       Like `mailmap.file`, but consider the value as a reference to a
+       blob in the repository. If both `mailmap.file` and
+       `mailmap.blob` are given, both are parsed, with entries from
+       `mailmap.file` taking precedence. In a bare repository, this
+       defaults to `HEAD:.mailmap`. In a non-bare repository, it
+       defaults to empty.
+
 man.viewer::
        Specify the programs that may be used to display help in the
        'man' format. See linkgit:git-help[1].
@@ -1994,6 +2007,12 @@ submodule.<name>.update::
        URL and other values found in the `.gitmodules` file.  See
        linkgit:git-submodule[1] and linkgit:gitmodules[5] for details.
 
+submodule.<name>.branch::
+       The remote branch name for a submodule, used by `git submodule
+       update --remote`.  Set this option to override the value found in
+       the `.gitmodules` file.  See linkgit:git-submodule[1] and
+       linkgit:gitmodules[5] for details.
+
 submodule.<name>.fetchRecurseSubmodules::
        This option can be used to control recursive fetching of this
        submodule. It can be overridden by using the --[no-]recurse-submodules
index c2b94f9..4314ad0 100644 (file)
@@ -56,6 +56,10 @@ diff.statGraphWidth::
        Limit the width of the graph part in --stat output. If set, applies
        to all commands generating --stat output except format-patch.
 
+diff.context::
+       Generate diffs with <n> lines of context instead of the default
+       of 3. This value is overridden by the -U option.
+
 diff.external::
        If this config variable is set, diff generation is not
        performed using the internal diff machinery, but using the
@@ -103,6 +107,13 @@ diff.suppressBlankEmpty::
        A boolean to inhibit the standard behavior of printing a space
        before each empty output line. Defaults to false.
 
+diff.submodule::
+       Specify the format in which differences in submodules are
+       shown.  The "log" format lists the commits in the range like
+       linkgit:git-submodule[1] `summary` does.  The "short" format
+       format just shows the names of the commits at the beginning
+       and end of the range.  Defaults to short.
+
 diff.wordRegex::
        A POSIX Extended Regular Expression used to determine what is a "word"
        when performing word-by-word difference calculations.  Character
index 1fb6f2d..39f2c50 100644 (file)
@@ -170,7 +170,8 @@ any of those replacements occurred.
        the commits in the range like linkgit:git-submodule[1] `summary` does.
        Omitting the `--submodule` option or specifying `--submodule=short`,
        uses the 'short' format. This format just shows the names of the commits
-       at the beginning and end of the range.
+       at the beginning and end of the range.  Can be tweaked via the
+       `diff.submodule` configuration variable.
 
 --color[=<when>]::
        Show colored diff.
index 19cbb90..7bdb039 100644 (file)
@@ -109,6 +109,10 @@ OPTIONS
        format. See linkgit:git-status[1] for details. Implies
        `--dry-run`.
 
+--long::
+       When doing a dry-run, give the output in a the long-format.
+       Implies `--dry-run`.
+
 -z::
 --null::
        When showing `short` or `porcelain` status output, terminate
index eaea079..9ae2508 100644 (file)
@@ -240,6 +240,10 @@ GIT_CONFIG::
        Using the "--global" option forces this to ~/.gitconfig. Using the
        "--system" option forces this to $(prefix)/etc/gitconfig.
 
+GIT_CONFIG_NOSYSTEM::
+       Whether to skip reading settings from the system-wide
+       $(prefix)/etc/gitconfig file. See linkgit:git[1] for details.
+
 See also <<FILES>>.
 
 
index 6695ab3..98d9881 100644 (file)
@@ -137,17 +137,19 @@ This option can be used several times to provide several detection regexes.
 -A <author-conv-file>::
        CVS by default uses the Unix username when writing its
        commit logs. Using this option and an author-conv-file
-       in this format
+       maps the name recorded in CVS to author name, e-mail and
+       optional timezone:
 +
 ---------
        exon=Andreas Ericsson <ae@op5.se>
-       spawn=Simon Pawn <spawn@frog-pond.org>
+       spawn=Simon Pawn <spawn@frog-pond.org> America/Chicago
 
 ---------
 +
 'git cvsimport' will make it appear as those authors had
 their GIT_AUTHOR_NAME and GIT_AUTHOR_EMAIL set properly
-all along.
+all along.  If a timezone is specified, GIT_AUTHOR_DATE will
+have the corresponding offset applied.
 +
 For convenience, this data is saved to `$GIT_DIR/cvs-authors`
 each time the '-A' option is provided and read from that same
index 68bca1a..3da5cc2 100644 (file)
@@ -39,10 +39,6 @@ OPTIONS
        See ``Date Formats'' below for details about which formats
        are supported, and their syntax.
 
--- done::
-       Terminate with error if there is no 'done' command at the
-       end of the stream.
-
 --force::
        Force updating modified existing branches, even if doing
        so would cause commits to be lost (as the new commit does
@@ -108,7 +104,8 @@ OPTIONS
        output.
 
 --done::
-       Require a `done` command at the end of the stream.
+       Terminate with error if there is no `done` command at the
+       end of the stream.
        This option might be useful for detecting errors that
        cause the frontend to terminate before it has started to
        write a stream.
index 6d43f56..259dce4 100644 (file)
@@ -20,7 +20,7 @@ SYNOPSIS
                   [--ignore-if-in-upstream]
                   [--subject-prefix=Subject-Prefix]
                   [--to=<email>] [--cc=<email>]
-                  [--cover-letter] [--quiet]
+                  [--cover-letter] [--quiet] [--notes[=<ref>]]
                   [<common diff options>]
                   [ <since> | <revision range> ]
 
@@ -191,6 +191,18 @@ will want to ensure that threading is disabled for `git send-email`.
        containing the shortlog and the overall diffstat.  You can
        fill in a description in the file before sending it out.
 
+--notes[=<ref>]::
+       Append the notes (see linkgit:git-notes[1]) for the commit
+       after the three-dash line.
++
+The expected use case of this is to write supporting explanation for
+the commit that does not belong to the commit log message proper,
+and include it with the patch submission. While one can simply write
+these explanations after `format-patch` has run but before sending,
+keeping them as git notes allows them to be maintained between versions
+of the patch series (but see the discussion of the `notes.rewrite`
+configuration options in linkgit:git-notes[1] to use this workflow).
+
 --[no]-signature=<signature>::
        Add a signature to each message produced. Per RFC 3676 the signature
        is separated from the body by a line with '-- ' on it. If the
index 585dac4..08a185d 100644 (file)
@@ -167,7 +167,7 @@ log.showroot::
        `git log -p` output would be shown without a diff attached.
        The default is `true`.
 
-mailmap.file::
+mailmap.*::
        See linkgit:git-shortlog[1].
 
 notes.displayRef::
index b95aafa..46ef046 100644 (file)
@@ -39,6 +39,10 @@ message stored in the commit object, the notes are indented like the
 message, after an unindented line saying "Notes (<refname>):" (or
 "Notes:" for `refs/notes/commits`).
 
+Notes can also be added to patches prepared with `git format-patch` by
+using the `--notes` option. Such notes are added as a patch commentary
+after a three dash separator line.
+
 To change which notes are shown by 'git log', see the
 "notes.displayRef" configuration in linkgit:git-log[1].
 
index 8b637d3..c964b79 100644 (file)
@@ -51,10 +51,11 @@ be named. If `:`<dst> is omitted, the same ref as <src> will be
 updated.
 +
 The object referenced by <src> is used to update the <dst> reference
-on the remote side, but by default this is only allowed if the
-update can fast-forward <dst>.  By having the optional leading `+`,
-you can tell git to update the <dst> ref even when the update is not a
-fast-forward.  This does *not* attempt to merge <src> into <dst>.  See
+on the remote side.  By default this is only allowed if <dst> is not
+a tag (annotated or lightweight), and then only if it can fast-forward
+<dst>.  By having the optional leading `+`, you can tell git to update
+the <dst> ref even if it is not allowed by default (e.g., it is not a
+fast-forward.)  This does *not* attempt to merge <src> into <dst>.  See
 EXAMPLES below for details.
 +
 `tag <tag>` means the same as `refs/tags/<tag>:refs/tags/<tag>`.
index 4f81a5b..6d696e0 100644 (file)
@@ -88,53 +88,17 @@ Each remote helper is expected to support only a subset of commands.
 The operations a helper supports are declared to git in the response
 to the `capabilities` command (see COMMANDS, below).
 
-'option'::
-       For specifying settings like `verbosity` (how much output to
-       write to stderr) and `depth` (how much history is wanted in the
-       case of a shallow clone) that affect how other commands are
-       carried out.
-
-'connect'::
-       For fetching and pushing using git's native packfile protocol
-       that requires a bidirectional, full-duplex connection.
-
-'push'::
-       For listing remote refs and pushing specified objects from the
-       local object store to remote refs.
-
-'fetch'::
-       For listing remote refs and fetching the associated history to
-       the local object store.
-
-'import'::
-       For listing remote refs and fetching the associated history as
-       a fast-import stream.
-
-'refspec' <refspec>::
-       This modifies the 'import' capability, allowing the produced
-       fast-import stream to modify refs in a private namespace
-       instead of writing to refs/heads or refs/remotes directly.
-       It is recommended that all importers providing the 'import'
-       capability use this.
-+
-A helper advertising the capability
-`refspec refs/heads/*:refs/svn/origin/branches/*`
-is saying that, when it is asked to `import refs/heads/topic`, the
-stream it outputs will update the `refs/svn/origin/branches/topic`
-ref.
-+
-This capability can be advertised multiple times.  The first
-applicable refspec takes precedence.  The left-hand of refspecs
-advertised with this capability must cover all refs reported by
-the list command.  If no 'refspec' capability is advertised,
-there is an implied `refspec *:*`.
+In the following, we list all defined capabilities and for
+each we list which commands a helper with that capability
+must provide.
 
 Capabilities for Pushing
-~~~~~~~~~~~~~~~~~~~~~~~~
+^^^^^^^^^^^^^^^^^^^^^^^^
 'connect'::
        Can attempt to connect to 'git receive-pack' (for pushing),
-       'git upload-pack', etc for communication using the
-       packfile protocol.
+       'git upload-pack', etc for communication using
+       git's native packfile protocol. This
+       requires a bidirectional, full-duplex connection.
 +
 Supported commands: 'connect'.
 
@@ -144,16 +108,26 @@ Supported commands: 'connect'.
 +
 Supported commands: 'list for-push', 'push'.
 
-If a helper advertises both 'connect' and 'push', git will use
-'connect' if possible and fall back to 'push' if the helper requests
-so when connecting (see the 'connect' command under COMMANDS).
+'export'::
+       Can discover remote refs and push specified objects from a
+       fast-import stream to remote refs.
++
+Supported commands: 'list for-push', 'export'.
+
+If a helper advertises 'connect', git will use it if possible and
+fall back to another capability if the helper requests so when
+connecting (see the 'connect' command under COMMANDS).
+When choosing between 'push' and 'export', git prefers 'push'.
+Other frontends may have some other order of preference.
+
 
 Capabilities for Fetching
-~~~~~~~~~~~~~~~~~~~~~~~~~
+^^^^^^^^^^^^^^^^^^^^^^^^^
 'connect'::
        Can try to connect to 'git upload-pack' (for fetching),
        'git receive-pack', etc for communication using the
-       packfile protocol.
+       git's native packfile protocol. This
+       requires a bidirectional, full-duplex connection.
 +
 Supported commands: 'connect'.
 
@@ -175,14 +149,27 @@ connecting (see the 'connect' command under COMMANDS).
 When choosing between 'fetch' and 'import', git prefers 'fetch'.
 Other frontends may have some other order of preference.
 
+Miscellaneous capabilities
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+'option'::
+       For specifying settings like `verbosity` (how much output to
+       write to stderr) and `depth` (how much history is wanted in the
+       case of a shallow clone) that affect how other commands are
+       carried out.
+
 'refspec' <refspec>::
-       This modifies the 'import' capability.
+       This modifies the 'import' capability, allowing the produced
+       fast-import stream to modify refs in a private namespace
+       instead of writing to refs/heads or refs/remotes directly.
+       It is recommended that all importers providing the 'import'
+       capability use this.
 +
-A helper advertising
+A helper advertising the capability
 `refspec refs/heads/*:refs/svn/origin/branches/*`
-in its capabilities is saying that, when it handles
-`import refs/heads/topic`, the stream it outputs will update the
-`refs/svn/origin/branches/topic` ref.
+is saying that, when it is asked to `import refs/heads/topic`, the
+stream it outputs will update the `refs/svn/origin/branches/topic`
+ref.
 +
 This capability can be advertised multiple times.  The first
 applicable refspec takes precedence.  The left-hand of refspecs
@@ -190,6 +177,34 @@ advertised with this capability must cover all refs reported by
 the list command.  If no 'refspec' capability is advertised,
 there is an implied `refspec *:*`.
 
+'bidi-import'::
+       This modifies the 'import' capability.
+       The fast-import commands 'cat-blob' and 'ls' can be used by remote-helpers
+       to retrieve information about blobs and trees that already exist in
+       fast-import's memory. This requires a channel from fast-import to the
+       remote-helper.
+       If it is advertised in addition to "import", git establishes a pipe from
+       fast-import to the remote-helper's stdin.
+       It follows that git and fast-import are both connected to the
+       remote-helper's stdin. Because git can send multiple commands to
+       the remote-helper it is required that helpers that use 'bidi-import'
+       buffer all 'import' commands of a batch before sending data to fast-import.
+       This is to prevent mixing commands and fast-import responses on the
+       helper's stdin.
+
+'export-marks' <file>::
+       This modifies the 'export' capability, instructing git to dump the
+       internal marks table to <file> when complete. For details,
+       read up on '--export-marks=<file>' in linkgit:git-fast-export[1].
+
+'import-marks' <file>::
+       This modifies the 'export' capability, instructing git to load the
+       marks specified in <file> before processing any input. For details,
+       read up on '--import-marks=<file>' in linkgit:git-fast-export[1].
+
+
+
+
 COMMANDS
 --------
 
@@ -198,9 +213,11 @@ 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. Each capability may be preceded with '*',
-       which marks them mandatory for git version using the remote
-       helper to understand (unknown mandatory capability is fatal
-       error).
+       which marks them mandatory for git versions using the remote
+       helper to understand. Any unknown mandatory capability is a
+       fatal error.
++
+Support for this command is mandatory.
 
 'list'::
        Lists the refs, one per line, in the format "<value> <name>
@@ -210,9 +227,20 @@ Commands are given by the caller on the helper's standard input, one per line.
        the name; unrecognized attributes are ignored. The list ends
        with a blank line.
 +
-If 'push' is supported this may be called as 'list for-push'
-to obtain the current refs prior to sending one or more 'push'
-commands to the helper.
+See REF LIST ATTRIBUTES for a list of currently defined attributes.
++
+Supported if the helper has the "fetch" or "import" capability.
+
+'list for-push'::
+       Similar to 'list', except that it is used if and only if
+       the caller wants to the resulting ref list to prepare
+       push commands.
+       A helper supporting both push and fetch can use this
+       to distinguish for which operation the output of 'list'
+       is going to be used, possibly reducing the amount
+       of work that needs to be performed.
++
+Supported if the helper has the "push" or "export" capability.
 
 'option' <name> <value>::
        Sets the transport helper option <name> to <value>.  Outputs a
@@ -222,6 +250,8 @@ commands to the helper.
        for it).  Options should be set before other commands,
        and may influence the behavior of those commands.
 +
+See OPTIONS for a list of currently defined options.
++
 Supported if the helper has the "option" capability.
 
 'fetch' <sha1> <name>::
@@ -230,7 +260,7 @@ Supported if the helper has the "option" capability.
        per line, terminated with a blank line.
        Outputs a single blank line when all fetch commands in the
        same batch are complete. Only objects which were reported
-       in the ref list with a sha1 may be fetched this way.
+       in the output of 'list' with a sha1 may be fetched this way.
 +
 Optionally may output a 'lock <file>' line indicating a file under
 GIT_DIR/objects/pack which is keeping a pack until refs can be
@@ -286,8 +316,29 @@ terminated with a blank line. For each batch of 'import', the remote
 helper should produce a fast-import stream terminated by a 'done'
 command.
 +
+Note that if the 'bidi-import' capability is used the complete batch
+sequence has to be buffered before starting to send data to fast-import
+to prevent mixing of commands and fast-import responses on the helper's
+stdin.
++
 Supported if the helper has the "import" capability.
 
+'export'::
+       Instructs the remote helper that any subsequent input is
+       part of a fast-import stream (generated by 'git fast-export')
+       containing objects which should be pushed to the remote.
++
+Especially useful for interoperability with a foreign versioning
+system.
++
+The 'export-marks' and 'import-marks' capabilities, if specified,
+affect this command in so far as they are passed on to 'git
+fast-export', which then will load/store a table of marks for
+local objects. This can be used to implement for incremental
+operations.
++
+Supported if the helper has the "export" capability.
+
 'connect' <service>::
        Connects to given service. Standard input and standard output
        of helper are connected to specified service (git prefix is
@@ -313,10 +364,9 @@ capabilities reported by the helper.
 REF LIST ATTRIBUTES
 -------------------
 
-'for-push'::
-       The caller wants to use the ref list to prepare push
-       commands.  A helper might chose to acquire the ref list by
-       opening a different type of connection to the destination.
+The 'list' command produces a list of refs in which each ref
+may be followed by a list of attributes. The following ref list
+attributes are defined.
 
 'unchanged'::
        This ref is unchanged since the last import or fetch, although
@@ -324,6 +374,10 @@ REF LIST ATTRIBUTES
 
 OPTIONS
 -------
+
+The following options are defined and (under suitable circumstances)
+set by git if the remote helper has the 'option' capability.
+
 'option verbosity' <n>::
        Changes the verbosity of messages displayed by the helper.
        A value of 0 for <n> means that processes operate
index 2a67d45..612a625 100644 (file)
@@ -19,7 +19,7 @@ testcase for the remote-helper functionality, and as an example to
 show remote-helper authors one possible implementation.
 
 The best way to learn more is to read the comments and source code in
-'git-remote-testgit.py'.
+'git-remote-testgit'.
 
 SEE ALSO
 --------
index 5d31860..262436b 100644 (file)
@@ -134,6 +134,21 @@ use the following command:
 git diff --name-only --diff-filter=D -z | xargs -0 git rm --cached
 ----------------
 
+Submodules
+~~~~~~~~~~
+Only submodules using a gitfile (which means they were cloned
+with a git version 1.7.8 or newer) will be removed from the work
+tree, as their repository lives inside the .git directory of the
+superproject. If a submodule (or one of those nested inside it)
+still uses a .git directory, `git rm` will fail - no matter if forced
+or not - to protect the submodule's history.
+
+A submodule is considered up-to-date when the HEAD is the same as
+recorded in the index, no tracked files are modified and no untracked
+files that aren't ignored are present in the submodules work tree.
+Ignored files are deemed expendable and won't stop a submodule's work
+tree from being removed.
+
 EXAMPLES
 --------
 `git rm Documentation/\*.txt`::
index 3241170..eeb561c 100644 (file)
@@ -126,6 +126,10 @@ The --to option must be repeated for each user you want on the to list.
 +
 Note that no attempts whatsoever are made to validate the encoding.
 
+--compose-encoding=<encoding>::
+       Specify encoding of compose message. Default is the value of the
+       'sendemail.composeencoding'; if that is unspecified, UTF-8 is assumed.
+
 
 Sending
 ~~~~~~~
index 67e5f53..9f1ef9a 100644 (file)
@@ -38,6 +38,9 @@ OPTIONS
        across git versions and regardless of user configuration. See
        below for details.
 
+--long::
+       Give the output in the long-format. This is the default.
+
 -u[<mode>]::
 --untracked-files[=<mode>]::
        Show untracked files.
index a65f38e..b1996f1 100644 (file)
@@ -9,11 +9,11 @@ git-submodule - Initialize, update or inspect submodules
 SYNOPSIS
 --------
 [verse]
-'git submodule' [--quiet] add [-b <branch>] [-f|--force]
+'git submodule' [--quiet] add [-b <branch>] [-f|--force] [--name <name>]
              [--reference <repository>] [--] <repository> [<path>]
 'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]
 'git submodule' [--quiet] init [--] [<path>...]
-'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--rebase]
+'git submodule' [--quiet] update [--init] [--remote] [-N|--no-fetch] [--rebase]
              [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
 'git submodule' [--quiet] summary [--cached|--files] [(-n|--summary-limit) <n>]
              [commit] [--] [<path>...]
@@ -208,6 +208,8 @@ OPTIONS
 -b::
 --branch::
        Branch of repository to add as submodule.
+       The name of the branch is recorded as `submodule.<path>.branch` in
+       `.gitmodules` for `update --remote`.
 
 -f::
 --force::
@@ -236,6 +238,27 @@ OPTIONS
        (the default). This limit only applies to modified submodules. The
        size is always limited to 1 for added/deleted/typechanged submodules.
 
+--remote::
+       This option is only valid for the update command.  Instead of using
+       the superproject's recorded SHA-1 to update the submodule, use the
+       status of the submodule's remote tracking branch.  The remote used
+       is branch's remote (`branch.<name>.remote`), defaulting to `origin`.
+       The remote branch used defaults to `master`, but the branch name may
+       be overridden by setting the `submodule.<name>.branch` option in
+       either `.gitmodules` or `.git/config` (with `.git/config` taking
+       precedence).
++
+This works for any of the supported update procedures (`--checkout`,
+`--rebase`, etc.).  The only change is the source of the target SHA-1.
+For example, `submodule update --remote --merge` will merge upstream
+submodule changes into the submodules, while `submodule update
+--merge` will merge superproject gitlink changes into the submodules.
++
+In order to ensure a current tracking branch state, `update --remote`
+fetches the submodule's remote repository before calculating the
+SHA-1.  If you don't want to fetch, you should use `submodule update
+--remote --no-fetch`.
+
 -N::
 --no-fetch::
        This option is only valid for the update command.
@@ -265,6 +288,11 @@ OPTIONS
        Initialize all submodules for which "git submodule init" has not been
        called so far before updating.
 
+--name::
+       This option is only valid for the add command. It sets the submodule's
+       name to the given string instead of defaulting to its path. The name
+       must be valid as a directory name and may not end with a '/'.
+
 --reference <repository>::
        This option is only valid for add and update commands.  These
        commands sometimes need to clone a remote repository. In this case,
index 981d3a8..ef68ad2 100644 (file)
@@ -3,13 +3,14 @@ git-symbolic-ref(1)
 
 NAME
 ----
-git-symbolic-ref - Read and modify symbolic refs
+git-symbolic-ref - Read, modify and delete symbolic refs
 
 SYNOPSIS
 --------
 [verse]
 'git symbolic-ref' [-m <reason>] <name> <ref>
 'git symbolic-ref' [-q] [--short] <name>
+'git symbolic-ref' --delete [-q] <name>
 
 DESCRIPTION
 -----------
@@ -21,6 +22,9 @@ argument to see which branch your working tree is on.
 Given two arguments, creates or updates a symbolic ref <name> to
 point at the given branch <ref>.
 
+Given `--delete` and an additional argument, deletes the given
+symbolic ref.
+
 A symbolic ref is a regular file that stores a string that
 begins with `ref: refs/`.  For example, your `.git/HEAD` is
 a regular file whose contents is `ref: refs/heads/master`.
@@ -28,6 +32,10 @@ a regular file whose contents is `ref: refs/heads/master`.
 OPTIONS
 -------
 
+-d::
+--delete::
+       Delete the symbolic ref <name>.
+
 -q::
 --quiet::
        Do not issue an error message if the <name> is not a
index b0e8f02..c03b7ad 100644 (file)
@@ -43,6 +43,11 @@ unreleased) version of git, that is available from 'master'
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
+* link:v1.8.1/git.html[documentation for release 1.8.1]
+
+* release notes for
+  link:RelNotes/1.8.1.txt[1.8.1].
+
 * link:v1.8.0.3/git.html[documentation for release 1.8.0.3]
 
 * release notes for
@@ -423,6 +428,11 @@ help ...`.
        Do not use replacement refs to replace git objects. See
        linkgit:git-replace[1] for more information.
 
+--literal-pathspecs::
+       Treat pathspecs literally, rather than as glob patterns. This is
+       equivalent to setting the `GIT_LITERAL_PATHSPECS` environment
+       variable to `1`.
+
 
 GIT COMMANDS
 ------------
@@ -767,6 +777,14 @@ for further details.
        and read the password from its STDOUT. See also the 'core.askpass'
        option in linkgit:git-config[1].
 
+'GIT_CONFIG_NOSYSTEM'::
+       Whether to skip reading settings from the system-wide
+       `$(prefix)/etc/gitconfig` file.  This environment variable can
+       be used along with `$HOME` and `$XDG_CONFIG_HOME` to create a
+       predictable environment for a picky script, or you can set it
+       temporarily to avoid using a buggy `/etc/gitconfig` file while
+       waiting for someone with sufficient permissions to fix it.
+
 'GIT_FLUSH'::
        If this environment variable is set to "1", then commands such
        as 'git blame' (in incremental mode), 'git rev-list', 'git log',
@@ -791,6 +809,16 @@ for further details.
        as a file path and will try to write the trace messages
        into it.
 
+GIT_LITERAL_PATHSPECS::
+       Setting this variable to `1` will cause git to treat all
+       pathspecs literally, rather than as glob patterns. For example,
+       running `GIT_LITERAL_PATHSPECS=1 git log -- '*.c'` will search
+       for commits that touch the path `*.c`, not any paths that the
+       glob `*.c` matches. You might want this if you are feeding
+       literal paths to git (e.g., paths previously given to you by
+       `git ls-tree`, `--raw` diff output, etc).
+
+
 Discussion[[Discussion]]
 ------------------------
 
index ba02d4d..2698f63 100644 (file)
@@ -56,6 +56,7 @@ When more than one pattern matches the path, a later line
 overrides an earlier line.  This overriding is done per
 attribute.  The rules how the pattern matches paths are the
 same as in `.gitignore` files; see linkgit:gitignore[5].
+Unlike `.gitignore`, negative patterns are forbidden.
 
 When deciding what attributes are assigned to a path, git
 consults `$GIT_DIR/info/attributes` file (which has the highest
index 4effd78..52d7ae4 100644 (file)
@@ -18,7 +18,9 @@ working tree, is a text file with a syntax matching the requirements
 of linkgit:git-config[1].
 
 The file contains one subsection per submodule, and the subsection value
-is the name of the submodule. Each submodule section also contains the
+is the name of the submodule. The name is set to the path where the
+submodule has been added unless it was customized with the '--name'
+option of 'git submodule add'. Each submodule section also contains the
 following required keys:
 
 submodule.<name>.path::
@@ -47,6 +49,11 @@ submodule.<name>.update::
        This config option is overridden if 'git submodule update' is given
        the '--merge', '--rebase' or '--checkout' options.
 
+submodule.<name>.branch::
+       A remote branch name for tracking updates in the upstream submodule.
+       If the option is not specified, it defaults to 'master'.  See the
+       `--remote` documentation in linkgit:git-submodule[1] for details.
+
 submodule.<name>.fetchRecurseSubmodules::
        This option can be used to control recursive fetching of this
        submodule. If this option is also present in the submodules entry in
diff --git a/Documentation/howto/new-command.txt b/Documentation/howto/new-command.txt
new file mode 100644 (file)
index 0000000..36502f6
--- /dev/null
@@ -0,0 +1,104 @@
+From: Eric S. Raymond <esr@thyrsus.com>
+Abstract: This is how-to documentation for people who want to add extension
+ commands to git.  It should be read alongside api-builtin.txt.
+Content-type: text/asciidoc
+
+How to integrate new subcommands
+================================
+
+This is how-to documentation for people who want to add extension
+commands to git.  It should be read alongside api-builtin.txt.
+
+Runtime environment
+-------------------
+
+git subcommands are standalone executables that live in the git exec
+path, normally /usr/lib/git-core.  The git executable itself is a
+thin wrapper that knows where the subcommands live, and runs them by
+passing command-line arguments to them.
+
+(If "git foo" is not found in the git exec path, the wrapper
+will look in the rest of your $PATH for it.  Thus, it's possible
+to write local git extensions that don't live in system space.)
+
+Implementation languages
+------------------------
+
+Most subcommands are written in C or shell.  A few are written in
+Perl.
+
+While we strongly encourage coding in portable C for portability,
+these specific scripting languages are also acceptable.  We won't
+accept more without a very strong technical case, as we don't want
+to broaden the git suite's required dependencies.  Import utilities,
+surgical tools, remote helpers and other code at the edges of the
+git suite are more lenient and we allow Python (and even Tcl/tk),
+but they should not be used for core functions.
+
+This may change in the future.  Especially Python is not allowed in
+core because we need better Python integration in the git Windows
+installer before we can be confident people in that environment
+won't experience an unacceptably large loss of capability.
+
+C commands are normally written as single modules, named after the
+command, that link a collection of functions called libgit.  Thus,
+your command 'git-foo' would normally be implemented as a single
+"git-foo.c" (or "builtin/foo.c" if it is to be linked to the main
+binary); this organization makes it easy for people reading the code
+to find things.
+
+See the CodingGuidelines document for other guidance on what we consider
+good practice in C and shell, and api-builtin.txt for the support
+functions available to built-in commands written in C.
+
+What every extension command needs
+----------------------------------
+
+You must have a man page, written in asciidoc (this is what git help
+followed by your subcommand name will display).  Be aware that there is
+a local asciidoc configuration and macros which you should use.  It's
+often helpful to start by cloning an existing page and replacing the
+text content.
+
+You must have a test, written to report in TAP (Test Anything Protocol).
+Tests are executables (usually shell scripts) that live in the 't'
+subdirectory of the tree.  Each test name begins with 't' and a sequence
+number that controls where in the test sequence it will be executed;
+conventionally the rest of the name stem is that of the command
+being tested.
+
+Read the file t/README to learn more about the conventions to be used
+in writing tests, and the test support library.
+
+Integrating a command
+---------------------
+
+Here are the things you need to do when you want to merge a new
+subcommand into the git tree.
+
+1. Don't forget to sign off your patch!
+
+2. Append your command name to one of the variables BUILTIN_OBJS,
+EXTRA_PROGRAMS, SCRIPT_SH, SCRIPT_PERL or SCRIPT_PYTHON.
+
+3. Drop its test in the t directory.
+
+4. If your command is implemented in an interpreted language with a
+p-code intermediate form, make sure .gitignore in the main directory
+includes a pattern entry that ignores such files.  Python .pyc and
+.pyo files will already be covered.
+
+5. If your command has any dependency on a particular version of
+your language, document it in the INSTALL file.
+
+6. There is a file command-list.txt in the distribution main directory
+that categorizes commands by type, so they can be listed in appropriate
+subsections in the documentation's summary command list.  Add an entry
+for yours.  To understand the categories, look at git-cmmands.txt
+in the main directory.
+
+7. Give the maintainer one paragraph to include in the RelNotes file
+to describe the new feature; a good place to do so is in the cover
+letter [PATCH 0/n].
+
+That's all there is to it.
index dd89fca..4a8c276 100644 (file)
@@ -1,5 +1,6 @@
 If the file `.mailmap` exists at the toplevel of the repository, or at
-the location pointed to by the mailmap.file configuration option, it
+the location pointed to by the mailmap.file or mailmap.blob
+configuration options, it
 is used to map author and committer names and email addresses to
 canonical real names and email addresses.
 
index d9edded..105f18a 100644 (file)
@@ -144,7 +144,11 @@ The placeholders are:
 - '%Cgreen': switch color to green
 - '%Cblue': switch color to blue
 - '%Creset': reset color
-- '%C(...)': color specification, as described in color.branch.* config option
+- '%C(...)': color specification, as described in color.branch.* config option;
+  adding `auto,` at the beginning will emit color only when colors are
+  enabled for log output (by `color.diff`, `color.ui`, or `--color`, and
+  respecting the `auto` settings of the former if we are going to a
+  terminal)
 - '%m': left, right or boundary mark
 - '%n': newline
 - '%%': a raw '%'
diff --git a/Documentation/pt_BR/gittutorial.txt b/Documentation/pt_BR/gittutorial.txt
deleted file mode 100644 (file)
index beba065..0000000
+++ /dev/null
@@ -1,675 +0,0 @@
-gittutorial(7)
-==============
-
-NOME
-----
-gittutorial - Um tutorial de introdução ao git (para versão 1.5.1 ou mais nova)
-
-SINOPSE
---------
-git *
-
-DESCRIÇÃO
------------
-
-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/
-------------------------------------------------
-
-Agora que você iniciou seu diretório de trabalho, você deve ter notado que um
-novo diretório foi 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 atual (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
-------------------------------------------------
-
-Ao executar esse comando, ele irá te pedir uma mensagem descrevendo a mudança,
-e, então, irá 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 a história do projeto
------------------------
-
-Em qualquer ponto você pode visualizar a história das suas mudanças
-usando
-
-------------------------------------------------
-$ git log
-------------------------------------------------
-
-Se você também quiser 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 ee49743..1ec14a0 100644 (file)
@@ -79,6 +79,11 @@ if it is part of the log message.
 
        Match the regexp limiting patterns without regard to letters case.
 
+--basic-regexp::
+
+       Consider the limiting patterns to be basic regular expressions;
+       this is the default.
+
 -E::
 --extended-regexp::
 
@@ -91,6 +96,11 @@ if it is part of the log message.
        Consider the limiting patterns to be fixed strings (don't interpret
        pattern as a regular expression).
 
+--perl-regexp::
+
+       Consider the limiting patterns to be Perl-compatible regexp.
+       Requires libpcre to be compiled in.
+
 --remove-empty::
 
        Stop when a given path disappears from the tree.
index 1a79781..a959517 100644 (file)
@@ -53,3 +53,11 @@ Functions
 `argv_array_clear`::
        Free all memory associated with the array and return it to the
        initial, empty state.
+
+`argv_array_detach`::
+       Detach the argv array from the `struct argv_array`, transfering
+       ownership of the allocated array and strings.
+
+`argv_array_free_detached`::
+       Free the memory allocated by a `struct argv_array` that was later
+       detached and is now no longer needed.
index d6fc90a..18142b6 100644 (file)
@@ -33,11 +33,11 @@ The following utility functions are wrappers around `graph_next_line()` and
 They can all be called with a NULL graph argument, in which case no graph
 output will be printed.
 
-* `graph_show_commit()` calls `graph_next_line()` until it returns non-zero.
-  This prints all graph lines up to, and including, the line containing this
-  commit.  Output is printed to stdout.  The last line printed does not contain
-  a terminating newline.  This should not be called if the commit line has
-  already been printed, or it will loop forever.
+* `graph_show_commit()` calls `graph_next_line()` and
+  `graph_is_commit_finished()` until one of them return non-zero.  This prints
+  all graph lines up to, and including, the line containing this commit.
+  Output is printed to stdout.  The last line printed does not contain a
+  terminating newline.
 
 * `graph_show_oneline()` calls `graph_next_line()` and prints the result to
   stdout.  The line printed does not contain a terminating newline.
index 95a8bf3..84686b5 100644 (file)
@@ -279,6 +279,22 @@ same behaviour as well.
        Strip whitespace from a buffer. The second parameter controls if
        comments are considered contents to be removed or not.
 
+`strbuf_split_buf`::
+`strbuf_split_str`::
+`strbuf_split_max`::
+`strbuf_split`::
+
+       Split a string or strbuf into a list of strbufs at a specified
+       terminator character.  The returned substrings include the
+       terminator characters.  Some of these functions take a `max`
+       parameter, which, if positive, limits the output to that
+       number of substrings.
+
+`strbuf_list_free`::
+
+       Free a list of strbufs (for example, the return values of the
+       `strbuf_split()` functions).
+
 `launch_editor`::
 
        Launch the user preferred editor to edit a file and fill the buffer
index 94d7a2b..20be348 100644 (file)
@@ -38,7 +38,8 @@ member (you need this if you add things later) and you should set the
   `unsorted_string_list_delete_item`.
 
 . Can remove items not matching a criterion from a sorted or unsorted
-  list using `filter_string_list`.
+  list using `filter_string_list`, or remove empty strings using
+  `string_list_remove_empty_items`.
 
 . Finally it should free the list using `string_list_clear`.
 
@@ -75,13 +76,11 @@ Functions
        to be deleted.  Preserve the order of the items that are
        retained.
 
-`string_list_longest_prefix`::
+`string_list_remove_empty_items`::
 
-       Return the longest string within a string_list that is a
-       prefix (in the sense of prefixcmp()) of the specified string,
-       or NULL if no such prefix exists.  This function does not
-       require the string_list to be sorted (it does a linear
-       search).
+       Remove any empty strings from the list.  If free_util is true,
+       call free() on the util members of any items that have to be
+       deleted.  Preserve the order of the items that are retained.
 
 `print_string_list`::
 
index 85651b5..1b377dc 100644 (file)
@@ -1787,6 +1787,13 @@ $ git format-patch origin
 will produce a numbered series of files in the current directory, one
 for each patch in the current branch but not in origin/HEAD.
 
+`git format-patch` can include an initial "cover letter". You can insert
+commentary on individual patches after the three dash line which
+`format-patch` places after the commit message but before the patch
+itself.  If you use `git notes` to track your cover letter material,
+`git format-patch --notes` will include the commit's notes in a similar
+manner.
+
 You can then import these into your mail client and send them by
 hand.  However, if you have a lot to send at once, you may prefer to
 use the linkgit:git-send-email[1] script to automate the process.
index 4fae90f..e9f7abc 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v1.8.0.3
+DEF_VER=v1.8.1.GIT
 
 LF='
 '
index 6b73c14..56424b4 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -74,10 +74,14 @@ all::
 # Define NO_D_TYPE_IN_DIRENT if your platform defines DT_UNKNOWN but lacks
 # d_type in struct dirent (Cygwin 1.5, fixed in Cygwin 1.7).
 #
+# Define HAVE_STRINGS_H if you have strings.h and need it for strcasecmp.
+#
 # Define NO_STRCASESTR if you don't have strcasestr.
 #
 # Define NO_MEMMEM if you don't have memmem.
 #
+# Define NO_GETPAGESIZE if you don't have getpagesize.
+#
 # Define NO_STRLCPY if you don't have strlcpy.
 #
 # Define NO_STRTOUMAX if you don't have both strtoimax and strtoumax in the
@@ -165,6 +169,10 @@ all::
 # Define NO_POLL if you do not have or don't want to use poll().
 # This also implies NO_SYS_POLL_H.
 #
+# Define NEEDS_SYS_PARAM_H if you need to include sys/param.h to compile,
+# *PLEASE* REPORT to git@vger.kernel.org if your platform needs this;
+# we want to know more about the issue.
+#
 # Define NO_PTHREADS if you do not have or do not want to use Pthreads.
 #
 # Define NO_PREAD if you have a problem with pread() system call (e.g.
@@ -374,7 +382,7 @@ htmldir = share/doc/git-doc
 ETC_GITCONFIG = $(sysconfdir)/gitconfig
 ETC_GITATTRIBUTES = $(sysconfdir)/gitattributes
 lib = lib
-# DESTDIR=
+# DESTDIR =
 pathsep = :
 
 export prefix bindir sharedir sysconfdir gitwebdir localedir
@@ -470,7 +478,7 @@ SCRIPT_PERL += git-relink.perl
 SCRIPT_PERL += git-send-email.perl
 SCRIPT_PERL += git-svn.perl
 
-SCRIPT_PYTHON += git-remote-testgit.py
+SCRIPT_PYTHON += git-remote-testpy.py
 SCRIPT_PYTHON += git-p4.py
 
 SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
@@ -495,6 +503,7 @@ PROGRAM_OBJS += sh-i18n--envsubst.o
 PROGRAM_OBJS += shell.o
 PROGRAM_OBJS += show-index.o
 PROGRAM_OBJS += upload-pack.o
+PROGRAM_OBJS += remote-testsvn.o
 
 # Binary suffix, set to .exe for Windows builds
 X =
@@ -574,9 +583,9 @@ endif
 export PERL_PATH
 export PYTHON_PATH
 
-LIB_FILE=libgit.a
-XDIFF_LIB=xdiff/lib.a
-VCSSVN_LIB=vcs-svn/lib.a
+LIB_FILE = libgit.a
+XDIFF_LIB = xdiff/lib.a
+VCSSVN_LIB = vcs-svn/lib.a
 
 LIB_H += xdiff/xinclude.h
 LIB_H += xdiff/xmacros.h
@@ -745,6 +754,7 @@ LIB_OBJS += editor.o
 LIB_OBJS += entry.o
 LIB_OBJS += environment.o
 LIB_OBJS += exec_cmd.o
+LIB_OBJS += fetch-pack.o
 LIB_OBJS += fsck.o
 LIB_OBJS += gettext.o
 LIB_OBJS += gpg-interface.o
@@ -762,6 +772,7 @@ LIB_OBJS += lockfile.o
 LIB_OBJS += log-tree.o
 LIB_OBJS += mailmap.o
 LIB_OBJS += match-trees.o
+LIB_OBJS += merge.o
 LIB_OBJS += merge-file.o
 LIB_OBJS += merge-recursive.o
 LIB_OBJS += mergesort.o
@@ -796,6 +807,7 @@ LIB_OBJS += rerere.o
 LIB_OBJS += resolve-undo.o
 LIB_OBJS += revision.o
 LIB_OBJS += run-command.o
+LIB_OBJS += send-pack.o
 LIB_OBJS += sequencer.o
 LIB_OBJS += server-info.o
 LIB_OBJS += setup.o
@@ -1082,6 +1094,7 @@ ifeq ($(uname_O),Cygwin)
                NO_SYMLINK_HEAD = YesPlease
                NO_IPV6 = YesPlease
                OLD_ICONV = UnfortunatelyYes
+               CYGWIN_V15_WIN32API = YesPlease
        endif
        NO_THREAD_SAFE_PREAD = YesPlease
        NEEDS_LIBICONV = YesPlease
@@ -1134,7 +1147,7 @@ ifeq ($(uname_S),NetBSD)
 endif
 ifeq ($(uname_S),AIX)
        DEFAULT_PAGER = more
-       NO_STRCASESTR=YesPlease
+       NO_STRCASESTR = YesPlease
        NO_MEMMEM = YesPlease
        NO_MKDTEMP = YesPlease
        NO_MKSTEMPS = YesPlease
@@ -1142,7 +1155,7 @@ ifeq ($(uname_S),AIX)
        NO_NSEC = YesPlease
        FREAD_READS_DIRECTORIES = UnfortunatelyYes
        INTERNAL_QSORT = UnfortunatelyYes
-       NEEDS_LIBICONV=YesPlease
+       NEEDS_LIBICONV = YesPlease
        BASIC_CFLAGS += -D_LARGE_FILES
        ifeq ($(shell expr "$(uname_V)" : '[1234]'),1)
                NO_PTHREADS = YesPlease
@@ -1150,13 +1163,13 @@ ifeq ($(uname_S),AIX)
                PTHREAD_LIBS = -lpthread
        endif
        ifeq ($(shell expr "$(uname_V).$(uname_R)" : '5\.1'),3)
-               INLINE=''
+               INLINE = ''
        endif
        GIT_TEST_CMP = cmp
 endif
 ifeq ($(uname_S),GNU)
        # GNU/Hurd
-       NO_STRLCPY=YesPlease
+       NO_STRLCPY = YesPlease
        NO_MKSTEMPS = YesPlease
        HAVE_PATHS_H = YesPlease
        LIBC_CONTAINS_LIBINTL = YesPlease
@@ -1182,9 +1195,9 @@ ifeq ($(uname_S),IRIX)
        NEEDS_LIBGEN = YesPlease
 endif
 ifeq ($(uname_S),IRIX64)
-       NO_SETENV=YesPlease
+       NO_SETENV = YesPlease
        NO_UNSETENV = YesPlease
-       NO_STRCASESTR=YesPlease
+       NO_STRCASESTR = YesPlease
        NO_MEMMEM = YesPlease
        NO_MKSTEMPS = YesPlease
        NO_MKDTEMP = YesPlease
@@ -1198,14 +1211,14 @@ ifeq ($(uname_S),IRIX64)
        NO_REGEX = YesPlease
        NO_FNMATCH_CASEFOLD = YesPlease
        SNPRINTF_RETURNS_BOGUS = YesPlease
-       SHELL_PATH=/usr/gnu/bin/bash
+       SHELL_PATH = /usr/gnu/bin/bash
        NEEDS_LIBGEN = YesPlease
 endif
 ifeq ($(uname_S),HP-UX)
        INLINE = __inline
-       NO_IPV6=YesPlease
-       NO_SETENV=YesPlease
-       NO_STRCASESTR=YesPlease
+       NO_IPV6 = YesPlease
+       NO_SETENV = YesPlease
+       NO_STRCASESTR = YesPlease
        NO_MEMMEM = YesPlease
        NO_MKSTEMPS = YesPlease
        NO_STRLCPY = YesPlease
@@ -1348,6 +1361,7 @@ ifeq ($(uname_S),NONSTOP_KERNEL)
        # Added manually, see above.
        NEEDS_SSL_WITH_CURL = YesPlease
        HAVE_LIBCHARSET_H = YesPlease
+       HAVE_STRINGS_H = YesPlease
        NEEDS_LIBICONV = YesPlease
        NEEDS_LIBINTL_BEFORE_LIBICONV = YesPlease
        NO_SYS_SELECT_H = UnfortunatelyYes
@@ -1381,6 +1395,10 @@ ifeq ($(uname_S),NONSTOP_KERNEL)
        MKDIR_WO_TRAILING_SLASH = YesPlease
        # RFE 10-120912-4693 submitted to HP NonStop development.
        NO_SETITIMER = UnfortunatelyYes
+       SANE_TOOL_PATH = /usr/coreutils/bin:/usr/local/bin
+       SHELL_PATH = /usr/local/bin/bash
+       # as of H06.25/J06.14, we might better use this
+       #SHELL_PATH = /usr/coreutils/bin/bash
 endif
 ifneq (,$(findstring MINGW,$(uname_S)))
        pathsep = ;
@@ -1428,7 +1446,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
        X = .exe
        SPARSE_FLAGS = -Wno-one-bit-signed-bitfield
 ifneq (,$(wildcard ../THIS_IS_MSYSGIT))
-       htmldir=doc/git/html/
+       htmldir = doc/git/html/
        prefix =
        INSTALL = /bin/install
        EXTLIBS += /mingw/lib/libz.a
@@ -1439,6 +1457,22 @@ else
        NO_CURL = YesPlease
 endif
 endif
+ifeq ($(uname_S),QNX)
+       COMPAT_CFLAGS += -DSA_RESTART=0
+       HAVE_STRINGS_H = YesPlease
+       NEEDS_SOCKET = YesPlease
+       NO_FNMATCH_CASEFOLD = YesPlease
+       NO_GETPAGESIZE = YesPlease
+       NO_ICONV = YesPlease
+       NO_MEMMEM = YesPlease
+       NO_MKDTEMP = YesPlease
+       NO_MKSTEMPS = YesPlease
+       NO_NSEC = YesPlease
+       NO_PTHREADS = YesPlease
+       NO_R_TO_GCC_LINKER = YesPlease
+       NO_STRCASESTR = YesPlease
+       NO_STRLCPY = YesPlease
+endif
 
 -include config.mak.autogen
 -include config.mak
@@ -1550,7 +1584,7 @@ else
                CURL_LIBCURL = -lcurl
        endif
        ifdef NEEDS_SSL_WITH_CURL
-               CURL_LIBCURL += -lssl
+               CURL_LIBCURL += -lssl
                ifdef NEEDS_CRYPTO_WITH_SSL
                        CURL_LIBCURL += -lcrypto
                endif
@@ -1646,6 +1680,9 @@ endif
 ifdef NO_D_INO_IN_DIRENT
        BASIC_CFLAGS += -DNO_D_INO_IN_DIRENT
 endif
+ifdef NO_GECOS_IN_PWENT
+       BASIC_CFLAGS += -DNO_GECOS_IN_PWENT
+endif
 ifdef NO_ST_BLOCKS_IN_STRUCT_STAT
        BASIC_CFLAGS += -DNO_ST_BLOCKS_IN_STRUCT_STAT
 endif
@@ -1739,6 +1776,9 @@ endif
 ifdef NO_SYS_POLL_H
        BASIC_CFLAGS += -DNO_SYS_POLL_H
 endif
+ifdef NEEDS_SYS_PARAM_H
+       BASIC_CFLAGS += -DNEEDS_SYS_PARAM_H
+endif
 ifdef NO_INTTYPES_H
        BASIC_CFLAGS += -DNO_INTTYPES_H
 endif
@@ -1759,7 +1799,7 @@ ifdef OBJECT_CREATION_USES_RENAMES
 endif
 ifdef NO_STRUCT_ITIMERVAL
        COMPAT_CFLAGS += -DNO_STRUCT_ITIMERVAL
-       NO_SETITIMER=YesPlease
+       NO_SETITIMER = YesPlease
 endif
 ifdef NO_SETITIMER
        COMPAT_CFLAGS += -DNO_SETITIMER
@@ -1850,6 +1890,9 @@ ifdef NO_MEMMEM
        COMPAT_CFLAGS += -DNO_MEMMEM
        COMPAT_OBJS += compat/memmem.o
 endif
+ifdef NO_GETPAGESIZE
+       COMPAT_CFLAGS += -DNO_GETPAGESIZE
+endif
 ifdef INTERNAL_QSORT
        COMPAT_CFLAGS += -DINTERNAL_QSORT
        COMPAT_OBJS += compat/qsort.o
@@ -1875,6 +1918,10 @@ ifdef HAVE_LIBCHARSET_H
        EXTLIBS += $(CHARSET_LIB)
 endif
 
+ifdef HAVE_STRINGS_H
+       BASIC_CFLAGS += -DHAVE_STRINGS_H
+endif
+
 ifdef HAVE_DEV_TTY
        BASIC_CFLAGS += -DHAVE_DEV_TTY
 endif
@@ -1889,6 +1936,9 @@ ifdef NO_REGEX
        COMPAT_CFLAGS += -Icompat/regex
        COMPAT_OBJS += compat/regex/regex.o
 endif
+ifdef CYGWIN_V15_WIN32API
+       COMPAT_CFLAGS += -DCYGWIN_V15_WIN32API
+endif
 
 ifdef USE_NED_ALLOCATOR
        COMPAT_CFLAGS += -Icompat/nedmalloc
@@ -1908,15 +1958,15 @@ ifneq (,$(XDL_FAST_HASH))
 endif
 
 ifeq ($(TCLTK_PATH),)
-NO_TCLTK=NoThanks
+NO_TCLTK = NoThanks
 endif
 
 ifeq ($(PERL_PATH),)
-NO_PERL=NoThanks
+NO_PERL = NoThanks
 endif
 
 ifeq ($(PYTHON_PATH),)
-NO_PYTHON=NoThanks
+NO_PYTHON = NoThanks
 endif
 
 QUIET_SUBDIR0  = +$(MAKE) -C # space to separate -C and subdir
@@ -1963,13 +2013,13 @@ PROFILE_DIR := $(CURDIR)
 ifeq ("$(PROFILE)","GEN")
        CFLAGS += -fprofile-generate=$(PROFILE_DIR) -DNO_NORETURN=1
        EXTLIBS += -lgcov
-       export CCACHE_DISABLE=t
-       V=1
+       export CCACHE_DISABLE = t
+       V = 1
 else
 ifneq ("$(PROFILE)","")
        CFLAGS += -fprofile-use=$(PROFILE_DIR) -fprofile-correction -DNO_NORETURN=1
-       export CCACHE_DISABLE=t
-       V=1
+       export CCACHE_DISABLE = t
+       V = 1
 endif
 endif
 
@@ -2171,7 +2221,7 @@ endef
 GIT-SCRIPT-DEFINES: FORCE
        @FLAGS='$(SCRIPT_DEFINES)'; \
            if test x"$$FLAGS" != x"`cat $@ 2>/dev/null`" ; then \
-               echo 1>&2 "    * new script parameters"; \
+               echo >&2 "    * new script parameters"; \
                echo "$$FLAGS" >$@; \
             fi
 
@@ -2233,7 +2283,7 @@ $(patsubst %.perl,%,$(SCRIPT_PERL)) git-instaweb: % : unimplemented.sh
 endif # NO_PERL
 
 ifndef NO_PYTHON
-$(patsubst %.py,%,$(SCRIPT_PYTHON)): GIT-CFLAGS GIT-PREFIX
+$(patsubst %.py,%,$(SCRIPT_PYTHON)): GIT-CFLAGS GIT-PREFIX GIT-PYTHON-VARS
 $(patsubst %.py,%,$(SCRIPT_PYTHON)): % : %.py
        $(QUIET_GEN)$(RM) $@ $@+ && \
        INSTLIBDIR=`MAKEFLAGS= $(MAKE) -C git_remote_helpers -s \
@@ -2449,6 +2499,10 @@ git-http-push$X: revision.o http.o http-push.o GIT-LDFLAGS $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
                $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
 
+git-remote-testsvn$X: remote-testsvn.o GIT-LDFLAGS $(GITLIBS) $(VCSSVN_LIB)
+       $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) \
+       $(VCSSVN_LIB)
+
 $(REMOTE_CURL_ALIASES): $(REMOTE_CURL_PRIMARY)
        $(QUIET_LNCP)$(RM) $@ && \
        ln $< $@ 2>/dev/null || \
@@ -2548,7 +2602,7 @@ TRACK_PREFIX = $(bindir_SQ):$(gitexecdir_SQ):$(template_dir_SQ):$(prefix_SQ):\
 GIT-PREFIX: FORCE
        @FLAGS='$(TRACK_PREFIX)'; \
        if test x"$$FLAGS" != x"`cat GIT-PREFIX 2>/dev/null`" ; then \
-               echo 1>&2 "    * new prefix flags"; \
+               echo >&2 "    * new prefix flags"; \
                echo "$$FLAGS" >GIT-PREFIX; \
        fi
 
@@ -2557,7 +2611,7 @@ TRACK_CFLAGS = $(CC):$(subst ','\'',$(ALL_CFLAGS)):$(USE_GETTEXT_SCHEME)
 GIT-CFLAGS: FORCE
        @FLAGS='$(TRACK_CFLAGS)'; \
            if test x"$$FLAGS" != x"`cat GIT-CFLAGS 2>/dev/null`" ; then \
-               echo 1>&2 "    * new build flags"; \
+               echo >&2 "    * new build flags"; \
                echo "$$FLAGS" >GIT-CFLAGS; \
             fi
 
@@ -2566,7 +2620,7 @@ TRACK_LDFLAGS = $(subst ','\'',$(ALL_LDFLAGS))
 GIT-LDFLAGS: FORCE
        @FLAGS='$(TRACK_LDFLAGS)'; \
            if test x"$$FLAGS" != x"`cat GIT-LDFLAGS 2>/dev/null`" ; then \
-               echo 1>&2 "    * new link flags"; \
+               echo >&2 "    * new link flags"; \
                echo "$$FLAGS" >GIT-LDFLAGS; \
             fi
 
@@ -2608,14 +2662,14 @@ ifdef GIT_PERF_MAKE_OPTS
        @echo GIT_PERF_MAKE_OPTS=\''$(subst ','\'',$(subst ','\'',$(GIT_PERF_MAKE_OPTS)))'\' >>$@
 endif
 
-### Detect Tck/Tk interpreter path changes
-ifndef NO_TCLTK
-TRACK_VARS = $(subst ','\'',-DTCLTK_PATH='$(TCLTK_PATH_SQ)')
+### Detect Python interpreter path changes
+ifndef NO_PYTHON
+TRACK_PYTHON = $(subst ','\'',-DPYTHON_PATH='$(PYTHON_PATH_SQ)')
 
-GIT-GUI-VARS: FORCE
-       @VARS='$(TRACK_VARS)'; \
+GIT-PYTHON-VARS: FORCE
+       @VARS='$(TRACK_PYTHON)'; \
            if test x"$$VARS" != x"`cat $@ 2>/dev/null`" ; then \
-               echo 1>&2 "    * new Tcl/Tk interpreter location"; \
+               echo >&2 "    * new Python interpreter location"; \
                echo "$$VARS" >$@; \
             fi
 endif
@@ -2814,7 +2868,7 @@ git.spec: git.spec.in GIT-VERSION-FILE
        sed -e 's/@@VERSION@@/$(GIT_VERSION)/g' < $< > $@+
        mv $@+ $@
 
-GIT_TARNAME=git-$(GIT_VERSION)
+GIT_TARNAME = git-$(GIT_VERSION)
 dist: git.spec git-archive$(X) configure
        ./git-archive --format=tar \
                --prefix=$(GIT_TARNAME)/ HEAD^{tree} > $(GIT_TARNAME).tar
@@ -2894,8 +2948,8 @@ ifndef NO_TCLTK
        $(MAKE) -C gitk-git clean
        $(MAKE) -C git-gui clean
 endif
-       $(RM) GIT-VERSION-FILE GIT-CFLAGS GIT-LDFLAGS GIT-GUI-VARS GIT-BUILD-OPTIONS
-       $(RM) GIT-USER-AGENT GIT-PREFIX GIT-SCRIPT-DEFINES
+       $(RM) GIT-VERSION-FILE GIT-CFLAGS GIT-LDFLAGS GIT-BUILD-OPTIONS
+       $(RM) GIT-USER-AGENT GIT-PREFIX GIT-SCRIPT-DEFINES GIT-PYTHON-VARS
 
 .PHONY: all install profile-clean clean strip
 .PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
index afcfb70..bdce313 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/1.8.0.3.txt
\ No newline at end of file
+Documentation/RelNotes/1.8.2.txt
\ No newline at end of file
index 05f2d79..40cdc46 100644 (file)
--- a/abspath.c
+++ b/abspath.c
@@ -15,16 +15,34 @@ int is_directory(const char *path)
 #define MAXDEPTH 5
 
 /*
- * Use this to get the real path, i.e. resolve links. If you want an
- * absolute path but don't mind links, use absolute_path.
+ * Return the real path (i.e., absolute path, with symlinks resolved
+ * and extra slashes removed) equivalent to the specified path.  (If
+ * you want an absolute path but don't mind links, use
+ * absolute_path().)  The return value is a pointer to a static
+ * buffer.
+ *
+ * The input and all intermediate paths must be shorter than MAX_PATH.
+ * The directory part of path (i.e., everything up to the last
+ * dir_sep) must denote a valid, existing directory, but the last
+ * component need not exist.  If die_on_error is set, then die with an
+ * informative error message if there is a problem.  Otherwise, return
+ * NULL on errors (without generating any output).
  *
  * If path is our buffer, then return path, as it's already what the
  * user wants.
  */
-const char *real_path(const char *path)
+static const char *real_path_internal(const char *path, int die_on_error)
 {
        static char bufs[2][PATH_MAX + 1], *buf = bufs[0], *next_buf = bufs[1];
+       char *retval = NULL;
+
+       /*
+        * If we have to temporarily chdir(), store the original CWD
+        * here so that we can chdir() back to it at the end of the
+        * function:
+        */
        char cwd[1024] = "";
+
        int buf_index = 1;
 
        int depth = MAXDEPTH;
@@ -35,11 +53,19 @@ const char *real_path(const char *path)
        if (path == buf || path == next_buf)
                return path;
 
-       if (!*path)
-               die("The empty string is not a valid path");
+       if (!*path) {
+               if (die_on_error)
+                       die("The empty string is not a valid path");
+               else
+                       goto error_out;
+       }
 
-       if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
-               die ("Too long path: %.*s", 60, path);
+       if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX) {
+               if (die_on_error)
+                       die("Too long path: %.*s", 60, path);
+               else
+                       goto error_out;
+       }
 
        while (depth--) {
                if (!is_directory(buf)) {
@@ -54,20 +80,36 @@ const char *real_path(const char *path)
                }
 
                if (*buf) {
-                       if (!*cwd && !getcwd(cwd, sizeof(cwd)))
-                               die_errno ("Could not get current working directory");
+                       if (!*cwd && !getcwd(cwd, sizeof(cwd))) {
+                               if (die_on_error)
+                                       die_errno("Could not get current working directory");
+                               else
+                                       goto error_out;
+                       }
 
-                       if (chdir(buf))
-                               die_errno ("Could not switch to '%s'", buf);
+                       if (chdir(buf)) {
+                               if (die_on_error)
+                                       die_errno("Could not switch to '%s'", buf);
+                               else
+                                       goto error_out;
+                       }
+               }
+               if (!getcwd(buf, PATH_MAX)) {
+                       if (die_on_error)
+                               die_errno("Could not get current working directory");
+                       else
+                               goto error_out;
                }
-               if (!getcwd(buf, PATH_MAX))
-                       die_errno ("Could not get current working directory");
 
                if (last_elem) {
                        size_t len = strlen(buf);
-                       if (len + strlen(last_elem) + 2 > PATH_MAX)
-                               die ("Too long path name: '%s/%s'",
-                                               buf, last_elem);
+                       if (len + strlen(last_elem) + 2 > PATH_MAX) {
+                               if (die_on_error)
+                                       die("Too long path name: '%s/%s'",
+                                           buf, last_elem);
+                               else
+                                       goto error_out;
+                       }
                        if (len && !is_dir_sep(buf[len-1]))
                                buf[len++] = '/';
                        strcpy(buf + len, last_elem);
@@ -77,10 +119,18 @@ const char *real_path(const char *path)
 
                if (!lstat(buf, &st) && S_ISLNK(st.st_mode)) {
                        ssize_t len = readlink(buf, next_buf, PATH_MAX);
-                       if (len < 0)
-                               die_errno ("Invalid symlink '%s'", buf);
-                       if (PATH_MAX <= len)
-                               die("symbolic link too long: %s", buf);
+                       if (len < 0) {
+                               if (die_on_error)
+                                       die_errno("Invalid symlink '%s'", buf);
+                               else
+                                       goto error_out;
+                       }
+                       if (PATH_MAX <= len) {
+                               if (die_on_error)
+                                       die("symbolic link too long: %s", buf);
+                               else
+                                       goto error_out;
+                       }
                        next_buf[len] = '\0';
                        buf = next_buf;
                        buf_index = 1 - buf_index;
@@ -89,10 +139,23 @@ const char *real_path(const char *path)
                        break;
        }
 
+       retval = buf;
+error_out:
+       free(last_elem);
        if (*cwd && chdir(cwd))
                die_errno ("Could not change back to '%s'", cwd);
 
-       return buf;
+       return retval;
+}
+
+const char *real_path(const char *path)
+{
+       return real_path_internal(path, 1);
+}
+
+const char *real_path_if_valid(const char *path)
+{
+       return real_path_internal(path, 0);
 }
 
 static const char *get_pwd_cwd(void)
index edfbd4a..d287927 100644 (file)
--- a/advice.c
+++ b/advice.c
@@ -1,9 +1,10 @@
 #include "cache.h"
 
-int advice_push_nonfastforward = 1;
+int advice_push_update_rejected = 1;
 int advice_push_non_ff_current = 1;
 int advice_push_non_ff_default = 1;
 int advice_push_non_ff_matching = 1;
+int advice_push_already_exists = 1;
 int advice_status_hints = 1;
 int advice_commit_before_merge = 1;
 int advice_resolve_conflict = 1;
@@ -14,15 +15,19 @@ static struct {
        const char *name;
        int *preference;
 } advice_config[] = {
-       { "pushnonfastforward", &advice_push_nonfastforward },
+       { "pushupdaterejected", &advice_push_update_rejected },
        { "pushnonffcurrent", &advice_push_non_ff_current },
        { "pushnonffdefault", &advice_push_non_ff_default },
        { "pushnonffmatching", &advice_push_non_ff_matching },
+       { "pushalreadyexists", &advice_push_already_exists },
        { "statushints", &advice_status_hints },
        { "commitbeforemerge", &advice_commit_before_merge },
        { "resolveconflict", &advice_resolve_conflict },
        { "implicitidentity", &advice_implicit_identity },
        { "detachedhead", &advice_detached_head },
+
+       /* make this an alias for backward compatibility */
+       { "pushnonfastforward", &advice_push_update_rejected }
 };
 
 void advise(const char *advice, ...)
index f3cdbbf..8bf6356 100644 (file)
--- a/advice.h
+++ b/advice.h
@@ -3,10 +3,11 @@
 
 #include "git-compat-util.h"
 
-extern int advice_push_nonfastforward;
+extern int advice_push_update_rejected;
 extern int advice_push_non_ff_current;
 extern int advice_push_non_ff_default;
 extern int advice_push_non_ff_matching;
+extern int advice_push_already_exists;
 extern int advice_status_hints;
 extern int advice_commit_before_merge;
 extern int advice_resolve_conflict;
index 4666404..93e00bb 100644 (file)
--- a/archive.c
+++ b/archive.c
@@ -120,6 +120,8 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
        strbuf_add(&path, args->base, args->baselen);
        strbuf_add(&path, base, baselen);
        strbuf_addstr(&path, filename);
+       if (S_ISDIR(mode) || S_ISGITLINK(mode))
+               strbuf_addch(&path, '/');
        path_without_prefix = path.buf + args->baselen;
 
        setup_archive_check(check);
@@ -130,7 +132,6 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
        }
 
        if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
-               strbuf_addch(&path, '/');
                if (args->verbose)
                        fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
                err = write_entry(args, sha1, path.buf, path.len, mode);
index 256741d..9e960d5 100644 (file)
@@ -68,3 +68,23 @@ void argv_array_clear(struct argv_array *array)
        }
        argv_array_init(array);
 }
+
+const char **argv_array_detach(struct argv_array *array, int *argc)
+{
+       const char **argv =
+               array->argv == empty_argv || array->argc == 0 ? NULL : array->argv;
+       if (argc)
+               *argc = array->argc;
+       argv_array_init(array);
+       return argv;
+}
+
+void argv_array_free_detached(const char **argv)
+{
+       if (argv) {
+               int i;
+               for (i = 0; argv[i]; i++)
+                       free((char **)argv[i]);
+               free(argv);
+       }
+}
index f4b9866..40248d4 100644 (file)
@@ -18,5 +18,7 @@ void argv_array_pushf(struct argv_array *, const char *fmt, ...);
 void argv_array_pushl(struct argv_array *, ...);
 void argv_array_pop(struct argv_array *);
 void argv_array_clear(struct argv_array *);
+const char **argv_array_detach(struct argv_array *array, int *argc);
+void argv_array_free_detached(const char **argv);
 
 #endif /* ARGV_ARRAY_H */
diff --git a/attr.c b/attr.c
index 887a9ae..466c93f 100644 (file)
--- a/attr.c
+++ b/attr.c
@@ -115,6 +115,13 @@ struct attr_state {
        const char *setto;
 };
 
+struct pattern {
+       const char *pattern;
+       int patternlen;
+       int nowildcardlen;
+       int flags;              /* EXC_FLAG_* */
+};
+
 /*
  * One rule, as from a .gitattributes file.
  *
@@ -131,7 +138,7 @@ struct attr_state {
  */
 struct match_attr {
        union {
-               char *pattern;
+               struct pattern pat;
                struct git_attr *attr;
        } u;
        char is_macro;
@@ -241,9 +248,16 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
        if (is_macro)
                res->u.attr = git_attr_internal(name, namelen);
        else {
-               res->u.pattern = (char *)&(res->state[num_attr]);
-               memcpy(res->u.pattern, name, namelen);
-               res->u.pattern[namelen] = 0;
+               char *p = (char *)&(res->state[num_attr]);
+               memcpy(p, name, namelen);
+               res->u.pat.pattern = p;
+               parse_exclude_pattern(&res->u.pat.pattern,
+                                     &res->u.pat.patternlen,
+                                     &res->u.pat.flags,
+                                     &res->u.pat.nowildcardlen);
+               if (res->u.pat.flags & EXC_FLAG_NEGATIVE)
+                       die(_("Negative patterns are forbidden in git attributes\n"
+                             "Use '\\!' for literal leading exclamation."));
        }
        res->is_macro = is_macro;
        res->num_attr = num_attr;
@@ -277,6 +291,7 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
 static struct attr_stack {
        struct attr_stack *prev;
        char *origin;
+       size_t originlen;
        unsigned num_matches;
        unsigned alloc;
        struct match_attr **attrs;
@@ -535,6 +550,7 @@ static void bootstrap_attr_stack(void)
        if (!is_bare_repository() || direction == GIT_ATTR_INDEX) {
                elem = read_attr(GITATTRIBUTES_FILE, 1);
                elem->origin = xstrdup("");
+               elem->originlen = 0;
                elem->prev = attr_stack;
                attr_stack = elem;
                debug_push(elem);
@@ -548,17 +564,24 @@ static void bootstrap_attr_stack(void)
        attr_stack = elem;
 }
 
+static const char *find_basename(const char *path)
+{
+       const char *cp, *last_slash = NULL;
+
+       for (cp = path; *cp; cp++) {
+               if (*cp == '/' && cp[1])
+                       last_slash = cp;
+       }
+       return last_slash ? last_slash + 1 : path;
+}
+
 static void prepare_attr_stack(const char *path)
 {
        struct attr_stack *elem, *info;
        int dirlen, len;
        const char *cp;
 
-       cp = strrchr(path, '/');
-       if (!cp)
-               dirlen = 0;
-       else
-               dirlen = cp - path;
+       dirlen = find_basename(path) - path;
 
        /*
         * At the bottom of the attribute stack is the built-in
@@ -628,7 +651,7 @@ static void prepare_attr_stack(const char *path)
                        strbuf_addstr(&pathbuf, GITATTRIBUTES_FILE);
                        elem = read_attr(pathbuf.buf, 0);
                        strbuf_setlen(&pathbuf, cp - path);
-                       elem->origin = strbuf_detach(&pathbuf, NULL);
+                       elem->origin = strbuf_detach(&pathbuf, &elem->originlen);
                        elem->prev = attr_stack;
                        attr_stack = elem;
                        debug_push(elem);
@@ -645,28 +668,26 @@ static void prepare_attr_stack(const char *path)
 }
 
 static int path_matches(const char *pathname, int pathlen,
-                       const char *pattern,
+                       const char *basename,
+                       const struct pattern *pat,
                        const char *base, int baselen)
 {
-       if (!strchr(pattern, '/')) {
-               /* match basename */
-               const char *basename = strrchr(pathname, '/');
-               basename = basename ? basename + 1 : pathname;
-               return (fnmatch_icase(pattern, basename, 0) == 0);
-       }
-       /*
-        * match with FNM_PATHNAME; the pattern has base implicitly
-        * in front of it.
-        */
-       if (*pattern == '/')
-               pattern++;
-       if (pathlen < baselen ||
-           (baselen && pathname[baselen] != '/') ||
-           strncmp(pathname, base, baselen))
+       const char *pattern = pat->pattern;
+       int prefix = pat->nowildcardlen;
+
+       if ((pat->flags & EXC_FLAG_MUSTBEDIR) &&
+           ((!pathlen) || (pathname[pathlen-1] != '/')))
                return 0;
-       if (baselen != 0)
-               baselen++;
-       return fnmatch_icase(pattern, pathname + baselen, FNM_PATHNAME) == 0;
+
+       if (pat->flags & EXC_FLAG_NODIR) {
+               return match_basename(basename,
+                                     pathlen - (basename - pathname),
+                                     pattern, prefix,
+                                     pat->patternlen, pat->flags);
+       }
+       return match_pathname(pathname, pathlen,
+                             base, baselen,
+                             pattern, prefix, pat->patternlen, pat->flags);
 }
 
 static int macroexpand_one(int attr_nr, int rem);
@@ -693,7 +714,8 @@ static int fill_one(const char *what, struct match_attr *a, int rem)
        return rem;
 }
 
-static int fill(const char *path, int pathlen, struct attr_stack *stk, int rem)
+static int fill(const char *path, int pathlen, const char *basename,
+               struct attr_stack *stk, int rem)
 {
        int i;
        const char *base = stk->origin ? stk->origin : "";
@@ -702,8 +724,8 @@ static int fill(const char *path, int pathlen, struct attr_stack *stk, int rem)
                struct match_attr *a = stk->attrs[i];
                if (a->is_macro)
                        continue;
-               if (path_matches(path, pathlen,
-                                a->u.pattern, base, strlen(base)))
+               if (path_matches(path, pathlen, basename,
+                                &a->u.pat, base, stk->originlen))
                        rem = fill_one("fill", a, rem);
        }
        return rem;
@@ -741,15 +763,17 @@ static void collect_all_attrs(const char *path)
 {
        struct attr_stack *stk;
        int i, pathlen, rem;
+       const char *basename;
 
        prepare_attr_stack(path);
        for (i = 0; i < attr_nr; i++)
                check_all_attr[i].value = ATTR__UNKNOWN;
 
+       basename = find_basename(path);
        pathlen = strlen(path);
        rem = attr_nr;
        for (stk = attr_stack; 0 < rem && stk; stk = stk->prev)
-               rem = fill(path, pathlen, stk, rem);
+               rem = fill(path, pathlen, basename, stk, rem);
 }
 
 int git_check_attr(const char *path, int num, struct git_attr_check *check)
index 1aad49b..bd1b7b5 100644 (file)
--- a/bisect.c
+++ b/bisect.c
@@ -956,3 +956,41 @@ int bisect_next_all(const char *prefix, int no_checkout)
        return bisect_checkout(bisect_rev_hex, no_checkout);
 }
 
+static inline int log2i(int n)
+{
+       int log2 = 0;
+
+       for (; n > 1; n >>= 1)
+               log2++;
+
+       return log2;
+}
+
+static inline int exp2i(int n)
+{
+       return 1 << n;
+}
+
+/*
+ * Estimate the number of bisect steps left (after the current step)
+ *
+ * For any x between 0 included and 2^n excluded, the probability for
+ * n - 1 steps left looks like:
+ *
+ * P(2^n + x) == (2^n - x) / (2^n + x)
+ *
+ * and P(2^n + x) < 0.5 means 2^n < 3x
+ */
+int estimate_bisect_steps(int all)
+{
+       int n, x, e;
+
+       if (all < 3)
+               return 0;
+
+       n = log2i(all);
+       e = exp2i(n);
+       x = all - e;
+
+       return (e < 3 * x) ? n : n - 1;
+}
index ec3c3ff..2a6c831 100644 (file)
--- a/bisect.h
+++ b/bisect.h
@@ -11,10 +11,6 @@ extern struct commit_list *filter_skipped(struct commit_list *list,
                                          int *count,
                                          int *skipped_first);
 
-extern void print_commit_list(struct commit_list *list,
-                             const char *format_cur,
-                             const char *format_last);
-
 #define BISECT_SHOW_ALL                (1<<0)
 #define REV_LIST_QUIET         (1<<1)
 
index 95116b8..3faf9d6 100644 (file)
--- a/builtin.h
+++ b/builtin.h
@@ -37,10 +37,6 @@ int copy_note_for_rewrite(struct notes_rewrite_cfg *c,
                          const unsigned char *from_obj, const unsigned char *to_obj);
 void finish_copy_notes_for_rewrite(struct notes_rewrite_cfg *c);
 
-extern int check_pager_config(const char *cmd);
-struct diff_options;
-extern void setup_diff_pager(struct diff_options *);
-
 extern int textconv_object(const char *path, unsigned mode, const unsigned char *sha1, int sha1_valid, char **buf, unsigned long *buf_size);
 
 extern int cmd_add(int argc, const char **argv, const char *prefix);
index 156b3ce..6c11e8b 100644 (file)
@@ -2095,7 +2095,7 @@ static void update_pre_post_images(struct image *preimage,
                                   char *buf,
                                   size_t len, size_t postlen)
 {
-       int i, ctx;
+       int i, ctx, reduced;
        char *new, *old, *fixed;
        struct image fixed_preimage;
 
@@ -2105,8 +2105,10 @@ static void update_pre_post_images(struct image *preimage,
         * free "oldlines".
         */
        prepare_image(&fixed_preimage, buf, len, 1);
-       assert(fixed_preimage.nr == preimage->nr);
-       for (i = 0; i < preimage->nr; i++)
+       assert(postlen
+              ? fixed_preimage.nr == preimage->nr
+              : fixed_preimage.nr <= preimage->nr);
+       for (i = 0; i < fixed_preimage.nr; i++)
                fixed_preimage.line[i].flag = preimage->line[i].flag;
        free(preimage->line_allocated);
        *preimage = fixed_preimage;
@@ -2126,7 +2128,8 @@ static void update_pre_post_images(struct image *preimage,
        else
                new = old;
        fixed = preimage->buf;
-       for (i = ctx = 0; i < postimage->nr; i++) {
+
+       for (i = reduced = ctx = 0; i < postimage->nr; i++) {
                size_t len = postimage->line[i].len;
                if (!(postimage->line[i].flag & LINE_COMMON)) {
                        /* an added line -- no counterparts in preimage */
@@ -2145,8 +2148,15 @@ static void update_pre_post_images(struct image *preimage,
                        fixed += preimage->line[ctx].len;
                        ctx++;
                }
-               if (preimage->nr <= ctx)
-                       die(_("oops"));
+
+               /*
+                * preimage is expected to run out, if the caller
+                * fixed addition of trailing blank lines.
+                */
+               if (preimage->nr <= ctx) {
+                       reduced++;
+                       continue;
+               }
 
                /* and copy it in, while fixing the line length */
                len = preimage->line[ctx].len;
@@ -2159,6 +2169,7 @@ static void update_pre_post_images(struct image *preimage,
 
        /* Fix the length of the whole thing */
        postimage->len = new - postimage->buf;
+       postimage->nr -= reduced;
 }
 
 static int match_fragment(struct image *img,
index c27ef21..cfae569 100644 (file)
@@ -1425,7 +1425,7 @@ static void get_commit_info(struct commit *commit,
                            int detailed)
 {
        int len;
-       const char *subject;
+       const char *subject, *encoding;
        char *reencoded, *message;
        static char author_name[1024];
        static char author_mail[1024];
@@ -1446,7 +1446,8 @@ static void get_commit_info(struct commit *commit,
                        die("Cannot read commit %s",
                            sha1_to_hex(commit->object.sha1));
        }
-       reencoded = reencode_commit_message(commit, NULL);
+       encoding = get_log_output_encoding();
+       reencoded = logmsg_reencode(commit, encoding);
        message   = reencoded ? reencoded : commit->buffer;
        ret->author = author_name;
        ret->author_mail = author_mail;
index a17a5df..d6dd3df 100644 (file)
@@ -112,10 +112,11 @@ static const char *only_include_assumed;
 static struct strbuf message = STRBUF_INIT;
 
 static enum {
+       STATUS_FORMAT_NONE = 0,
        STATUS_FORMAT_LONG,
        STATUS_FORMAT_SHORT,
        STATUS_FORMAT_PORCELAIN
-} status_format = STATUS_FORMAT_LONG;
+} status_format;
 
 static int opt_parse_m(const struct option *opt, const char *arg, int unset)
 {
@@ -454,6 +455,7 @@ static int run_status(FILE *fp, const char *index_file, const char *prefix, int
        case STATUS_FORMAT_PORCELAIN:
                wt_porcelain_print(s);
                break;
+       case STATUS_FORMAT_NONE:
        case STATUS_FORMAT_LONG:
                wt_status_print(s);
                break;
@@ -753,7 +755,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
                                ident_shown++ ? "" : "\n",
                                author_ident->buf);
 
-               if (!user_ident_sufficiently_given())
+               if (!committer_ident_sufficiently_given())
                        status_printf_ln(s, GIT_COLOR_NORMAL,
                                _("%s"
                                "Committer: %s"),
@@ -1058,9 +1060,13 @@ static int parse_and_validate_options(int argc, const char *argv[],
        if (all && argc > 0)
                die(_("Paths with -a does not make sense."));
 
-       if (s->null_termination && status_format == STATUS_FORMAT_LONG)
-               status_format = STATUS_FORMAT_PORCELAIN;
-       if (status_format != STATUS_FORMAT_LONG)
+       if (s->null_termination) {
+               if (status_format == STATUS_FORMAT_NONE)
+                       status_format = STATUS_FORMAT_PORCELAIN;
+               else if (status_format == STATUS_FORMAT_LONG)
+                       die(_("--long and -z are incompatible"));
+       }
+       if (status_format != STATUS_FORMAT_NONE)
                dry_run = 1;
 
        return argc;
@@ -1159,6 +1165,9 @@ int cmd_status(int argc, const char **argv, const char *prefix)
                OPT_SET_INT(0, "porcelain", &status_format,
                            N_("machine-readable output"),
                            STATUS_FORMAT_PORCELAIN),
+               OPT_SET_INT(0, "long", &status_format,
+                           N_("show status in long format (default)"),
+                           STATUS_FORMAT_LONG),
                OPT_BOOLEAN('z', "null", &s.null_termination,
                            N_("terminate entries with NUL")),
                { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg,
@@ -1186,8 +1195,12 @@ int cmd_status(int argc, const char **argv, const char *prefix)
                             builtin_status_usage, 0);
        finalize_colopts(&s.colopts, -1);
 
-       if (s.null_termination && status_format == STATUS_FORMAT_LONG)
-               status_format = STATUS_FORMAT_PORCELAIN;
+       if (s.null_termination) {
+               if (status_format == STATUS_FORMAT_NONE)
+                       status_format = STATUS_FORMAT_PORCELAIN;
+               else if (status_format == STATUS_FORMAT_LONG)
+                       die(_("--long and -z are incompatible"));
+       }
 
        handle_untracked_files_arg(&s);
        if (show_ignored_in_status)
@@ -1216,6 +1229,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
        case STATUS_FORMAT_PORCELAIN:
                wt_porcelain_print(&s);
                break;
+       case STATUS_FORMAT_NONE:
        case STATUS_FORMAT_LONG:
                s.verbose = verbose;
                s.ignore_submodule_arg = ignore_submodule_arg;
@@ -1251,7 +1265,7 @@ static void print_summary(const char *prefix, const unsigned char *sha1,
                strbuf_addstr(&format, "\n Author: ");
                strbuf_addbuf_percentquote(&format, &author_ident);
        }
-       if (!user_ident_sufficiently_given()) {
+       if (!committer_ident_sufficiently_given()) {
                strbuf_addstr(&format, "\n Committer: ");
                strbuf_addbuf_percentquote(&format, &committer_ident);
                if (advice_implicit_identity) {
@@ -1386,6 +1400,9 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
                OPT_BOOLEAN(0, "branch", &s.show_branch, N_("show branch information")),
                OPT_SET_INT(0, "porcelain", &status_format,
                            N_("machine-readable output"), STATUS_FORMAT_PORCELAIN),
+               OPT_SET_INT(0, "long", &status_format,
+                           N_("show status in long format (default)"),
+                           STATUS_FORMAT_LONG),
                OPT_BOOLEAN('z', "null", &s.null_termination,
                            N_("terminate entries with NUL")),
                OPT_BOOLEAN(0, "amend", &amend, N_("amend previous commit")),
index 505bbc7..33c9bf9 100644 (file)
@@ -15,7 +15,6 @@ static int show_keys;
 static int use_key_regexp;
 static int do_all;
 static int do_not_match;
-static int seen;
 static char delim = '=';
 static char key_delim = ' ';
 static char term = '\n';
@@ -95,12 +94,19 @@ static int show_all_config(const char *key_, const char *value_, void *cb)
        return 0;
 }
 
-static int show_config(const char *key_, const char *value_, void *cb)
+struct strbuf_list {
+       struct strbuf *items;
+       int nr;
+       int alloc;
+};
+
+static int collect_config(const char *key_, const char *value_, void *cb)
 {
+       struct strbuf_list *values = cb;
+       struct strbuf *buf;
        char value[256];
        const char *vptr = value;
        int must_free_vptr = 0;
-       int dup_error = 0;
        int must_print_delim = 0;
 
        if (!use_key_regexp && strcmp(key_, key))
@@ -111,12 +117,14 @@ static int show_config(const char *key_, const char *value_, void *cb)
            (do_not_match ^ !!regexec(regexp, (value_?value_:""), 0, NULL, 0)))
                return 0;
 
+       ALLOC_GROW(values->items, values->nr + 1, values->alloc);
+       buf = &values->items[values->nr++];
+       strbuf_init(buf, 0);
+
        if (show_keys) {
-               printf("%s", key_);
+               strbuf_addstr(buf, key_);
                must_print_delim = 1;
        }
-       if (seen && !do_all)
-               dup_error = 1;
        if (types == TYPE_INT)
                sprintf(value, "%d", git_config_int(key_, value_?value_:""));
        else if (types == TYPE_BOOL)
@@ -139,16 +147,12 @@ static int show_config(const char *key_, const char *value_, void *cb)
                vptr = "";
                must_print_delim = 0;
        }
-       seen++;
-       if (dup_error) {
-               error("More than one value for the key %s: %s",
-                               key_, vptr);
-       }
-       else {
-               if (must_print_delim)
-                       printf("%c", key_delim);
-               printf("%s%c", vptr, term);
-       }
+
+       if (must_print_delim)
+               strbuf_addch(buf, key_delim);
+       strbuf_addstr(buf, vptr);
+       strbuf_addch(buf, term);
+
        if (must_free_vptr)
                /* If vptr must be freed, it's a pointer to a
                 * dynamically allocated buffer, it's safe to cast to
@@ -162,19 +166,8 @@ static int show_config(const char *key_, const char *value_, void *cb)
 static int get_value(const char *key_, const char *regex_)
 {
        int ret = CONFIG_GENERIC_ERROR;
-       char *global = NULL, *xdg = NULL, *repo_config = NULL;
-       const char *system_wide = NULL, *local;
-       struct config_include_data inc = CONFIG_INCLUDE_INIT;
-       config_fn_t fn;
-       void *data;
-
-       local = given_config_file;
-       if (!local) {
-               local = repo_config = git_pathdup("config");
-               if (git_config_system())
-                       system_wide = git_etc_gitconfig();
-               home_config_paths(&global, &xdg, "config");
-       }
+       struct strbuf_list values = {NULL};
+       int i;
 
        if (use_key_regexp) {
                char *tl;
@@ -196,7 +189,8 @@ static int get_value(const char *key_, const char *regex_)
                key_regexp = (regex_t*)xmalloc(sizeof(regex_t));
                if (regcomp(key_regexp, key, REG_EXTENDED)) {
                        fprintf(stderr, "Invalid key pattern: %s\n", key_);
-                       free(key);
+                       free(key_regexp);
+                       key_regexp = NULL;
                        ret = CONFIG_INVALID_PATTERN;
                        goto free_strings;
                }
@@ -216,53 +210,37 @@ static int get_value(const char *key_, const char *regex_)
                regexp = (regex_t*)xmalloc(sizeof(regex_t));
                if (regcomp(regexp, regex_, REG_EXTENDED)) {
                        fprintf(stderr, "Invalid pattern: %s\n", regex_);
+                       free(regexp);
+                       regexp = NULL;
                        ret = CONFIG_INVALID_PATTERN;
                        goto free_strings;
                }
        }
 
-       fn = show_config;
-       data = NULL;
-       if (respect_includes) {
-               inc.fn = fn;
-               inc.data = data;
-               fn = git_config_include;
-               data = &inc;
-       }
-
-       if (do_all && system_wide)
-               git_config_from_file(fn, system_wide, data);
-       if (do_all && xdg)
-               git_config_from_file(fn, xdg, data);
-       if (do_all && global)
-               git_config_from_file(fn, global, data);
-       if (do_all)
-               git_config_from_file(fn, local, data);
-       git_config_from_parameters(fn, data);
-       if (!do_all && !seen)
-               git_config_from_file(fn, local, data);
-       if (!do_all && !seen && global)
-               git_config_from_file(fn, global, data);
-       if (!do_all && !seen && xdg)
-               git_config_from_file(fn, xdg, data);
-       if (!do_all && !seen && system_wide)
-               git_config_from_file(fn, system_wide, data);
+       git_config_with_options(collect_config, &values,
+                               given_config_file, respect_includes);
+
+       ret = !values.nr;
 
+       for (i = 0; i < values.nr; i++) {
+               struct strbuf *buf = values.items + i;
+               if (do_all || i == values.nr - 1)
+                       fwrite(buf->buf, 1, buf->len, stdout);
+               strbuf_release(buf);
+       }
+       free(values.items);
+
+free_strings:
        free(key);
+       if (key_regexp) {
+               regfree(key_regexp);
+               free(key_regexp);
+       }
        if (regexp) {
                regfree(regexp);
                free(regexp);
        }
 
-       if (do_all)
-               ret = !seen;
-       else
-               ret = (seen == 1) ? 0 : seen > 1 ? 2 : 1;
-
-free_strings:
-       free(repo_config);
-       free(global);
-       free(xdg);
        return ret;
 }
 
index 9fe11ed..04c185b 100644 (file)
@@ -144,7 +144,7 @@ static int get_name(const char *path, const unsigned char *sha1, int flag, void
        if (!all && !might_be_tag)
                return 0;
 
-       if (!peel_ref(path, peeled) && !is_null_sha1(peeled)) {
+       if (!peel_ref(path, peeled)) {
                is_tag = !!hashcmp(sha1, peeled);
        } else {
                hashcpy(peeled, sha1);
index 2eb32bd..1c737f7 100644 (file)
@@ -41,9 +41,13 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix)
        if (rev.pending.nr != 1 ||
            rev.max_count != -1 || rev.min_age != -1 || rev.max_age != -1)
                usage(diff_cache_usage);
-       if (!cached)
+       if (!cached) {
                setup_work_tree();
-       if (read_cache() < 0) {
+               if (read_cache_preload(rev.diffopt.pathspec.raw) < 0) {
+                       perror("read_cache_preload");
+                       return -1;
+               }
+       } else if (read_cache() < 0) {
                perror("read_cache");
                return -1;
        }
index 9650be2..8c2af6c 100644 (file)
@@ -130,8 +130,6 @@ static int builtin_diff_index(struct rev_info *revs,
                        usage(builtin_diff_usage);
                argv++; argc--;
        }
-       if (!cached)
-               setup_work_tree();
        /*
         * Make sure there is one revision (i.e. pending object),
         * and there is no revision filtering parameters.
@@ -140,8 +138,14 @@ static int builtin_diff_index(struct rev_info *revs,
            revs->max_count != -1 || revs->min_age != -1 ||
            revs->max_age != -1)
                usage(builtin_diff_usage);
-       if (read_cache_preload(revs->diffopt.pathspec.raw) < 0) {
-               perror("read_cache_preload");
+       if (!cached) {
+               setup_work_tree();
+               if (read_cache_preload(revs->diffopt.pathspec.raw) < 0) {
+                       perror("read_cache_preload");
+                       return -1;
+               }
+       } else if (read_cache() < 0) {
+               perror("read_cache");
                return -1;
        }
        return run_diff_index(revs, cached);
@@ -418,19 +422,3 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
                refresh_index_quietly();
        return result;
 }
-
-void setup_diff_pager(struct diff_options *opt)
-{
-       /*
-        * If the user asked for our exit code, then either they want --quiet
-        * or --exit-code. We should definitely not bother with a pager in the
-        * former case, as we will generate no output. Since we still properly
-        * report our exit code even when a pager is run, we _could_ run a
-        * pager with --exit-code. But since we have not done so historically,
-        * and because it is easy to find people oneline advising "git diff
-        * --exit-code" in hooks and other scripts, we do not do so.
-        */
-       if (!DIFF_OPT_TST(opt, EXIT_WITH_STATUS) &&
-           check_pager_config("diff") != 0)
-               setup_pager();
-}
index 12220ad..77dffd1 100644 (file)
@@ -474,18 +474,21 @@ static void handle_tag(const char *name, struct tag *tag)
               (int)message_size, (int)message_size, message ? message : "");
 }
 
-static void get_tags_and_duplicates(struct object_array *pending,
+static void get_tags_and_duplicates(struct rev_cmdline_info *info,
                                    struct string_list *extra_refs)
 {
        struct tag *tag;
        int i;
 
-       for (i = 0; i < pending->nr; i++) {
-               struct object_array_entry *e = pending->objects + i;
+       for (i = 0; i < info->nr; i++) {
+               struct rev_cmdline_entry *e = info->rev + i;
                unsigned char sha1[20];
-               struct commit *commit = commit;
+               struct commit *commit;
                char *full_name;
 
+               if (e->flags & UNINTERESTING)
+                       continue;
+
                if (dwim_ref(e->name, strlen(e->name), sha1, &full_name) != 1)
                        continue;
 
@@ -523,10 +526,14 @@ static void get_tags_and_duplicates(struct object_array *pending,
                                typename(e->item->type));
                        continue;
                }
-               if (commit->util)
-                       /* more than one name for the same object */
+
+               /*
+                * This ref will not be updated through a commit, lets make
+                * sure it gets properly updated eventually.
+                */
+               if (commit->util || commit->object.flags & SHOWN)
                        string_list_append(extra_refs, full_name)->util = commit;
-               else
+               if (!commit->util)
                        commit->util = full_name;
        }
 }
@@ -614,6 +621,10 @@ static void import_marks(char *input_file)
                if (object->flags & SHOWN)
                        error("Object %s already has a mark", sha1_to_hex(sha1));
 
+               if (object->type != OBJ_COMMIT)
+                       /* only commits */
+                       continue;
+
                mark_object(object, mark);
                if (last_idnum < mark)
                        last_idnum = mark;
@@ -677,7 +688,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
        if (import_filename && revs.prune_data.nr)
                full_tree = 1;
 
-       get_tags_and_duplicates(&revs.pending, &extra_refs);
+       get_tags_and_duplicates(&revs.cmdline, &extra_refs);
 
        if (prepare_revision_walk(&revs))
                die("revision walk setup failed");
index e644398..940ae35 100644 (file)
 #include "builtin.h"
-#include "refs.h"
 #include "pkt-line.h"
-#include "commit.h"
-#include "tag.h"
-#include "exec_cmd.h"
-#include "pack.h"
-#include "sideband.h"
 #include "fetch-pack.h"
-#include "remote.h"
-#include "run-command.h"
-#include "transport.h"
-#include "version.h"
-
-static int transfer_unpack_limit = -1;
-static int fetch_unpack_limit = -1;
-static int unpack_limit = 100;
-static int prefer_ofs_delta = 1;
-static int no_done;
-static int fetch_fsck_objects = -1;
-static int transfer_fsck_objects = -1;
-static int agent_supported;
-static struct fetch_pack_args args = {
-       /* .uploadpack = */ "git-upload-pack",
-};
 
 static const char fetch_pack_usage[] =
 "git fetch-pack [--all] [--stdin] [--quiet|-q] [--keep|-k] [--thin] "
 "[--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] "
 "[--no-progress] [-v] [<host>:]<directory> [<refs>...]";
 
-#define COMPLETE       (1U << 0)
-#define COMMON         (1U << 1)
-#define COMMON_REF     (1U << 2)
-#define SEEN           (1U << 3)
-#define POPPED         (1U << 4)
-
-static int marked;
-
-/*
- * After sending this many "have"s if we do not get any new ACK , we
- * give up traversing our history.
- */
-#define MAX_IN_VAIN 256
-
-static struct commit_list *rev_list;
-static int non_common_revs, multi_ack, use_sideband;
-
-static void rev_list_push(struct commit *commit, int mark)
-{
-       if (!(commit->object.flags & mark)) {
-               commit->object.flags |= mark;
-
-               if (!(commit->object.parsed))
-                       if (parse_commit(commit))
-                               return;
-
-               commit_list_insert_by_date(commit, &rev_list);
-
-               if (!(commit->object.flags & COMMON))
-                       non_common_revs++;
-       }
-}
-
-static int rev_list_insert_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
-{
-       struct object *o = deref_tag(parse_object(sha1), refname, 0);
-
-       if (o && o->type == OBJ_COMMIT)
-               rev_list_push((struct commit *)o, SEEN);
-
-       return 0;
-}
-
-static int clear_marks(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
-{
-       struct object *o = deref_tag(parse_object(sha1), refname, 0);
-
-       if (o && o->type == OBJ_COMMIT)
-               clear_commit_marks((struct commit *)o,
-                                  COMMON | COMMON_REF | SEEN | POPPED);
-       return 0;
-}
-
-/*
-   This function marks a rev and its ancestors as common.
-   In some cases, it is desirable to mark only the ancestors (for example
-   when only the server does not yet know that they are common).
-*/
-
-static void mark_common(struct commit *commit,
-               int ancestors_only, int dont_parse)
-{
-       if (commit != NULL && !(commit->object.flags & COMMON)) {
-               struct object *o = (struct object *)commit;
-
-               if (!ancestors_only)
-                       o->flags |= COMMON;
-
-               if (!(o->flags & SEEN))
-                       rev_list_push(commit, SEEN);
-               else {
-                       struct commit_list *parents;
-
-                       if (!ancestors_only && !(o->flags & POPPED))
-                               non_common_revs--;
-                       if (!o->parsed && !dont_parse)
-                               if (parse_commit(commit))
-                                       return;
-
-                       for (parents = commit->parents;
-                                       parents;
-                                       parents = parents->next)
-                               mark_common(parents->item, 0, dont_parse);
-               }
-       }
-}
-
-/*
-  Get the next rev to send, ignoring the common.
-*/
-
-static const unsigned char *get_rev(void)
-{
-       struct commit *commit = NULL;
-
-       while (commit == NULL) {
-               unsigned int mark;
-               struct commit_list *parents;
-
-               if (rev_list == NULL || non_common_revs == 0)
-                       return NULL;
-
-               commit = rev_list->item;
-               if (!commit->object.parsed)
-                       parse_commit(commit);
-               parents = commit->parents;
-
-               commit->object.flags |= POPPED;
-               if (!(commit->object.flags & COMMON))
-                       non_common_revs--;
-
-               if (commit->object.flags & COMMON) {
-                       /* do not send "have", and ignore ancestors */
-                       commit = NULL;
-                       mark = COMMON | SEEN;
-               } else if (commit->object.flags & COMMON_REF)
-                       /* send "have", and ignore ancestors */
-                       mark = COMMON | SEEN;
-               else
-                       /* send "have", also for its ancestors */
-                       mark = SEEN;
-
-               while (parents) {
-                       if (!(parents->item->object.flags & SEEN))
-                               rev_list_push(parents->item, mark);
-                       if (mark & COMMON)
-                               mark_common(parents->item, 1, 0);
-                       parents = parents->next;
-               }
-
-               rev_list = rev_list->next;
-       }
-
-       return commit->object.sha1;
-}
-
-enum ack_type {
-       NAK = 0,
-       ACK,
-       ACK_continue,
-       ACK_common,
-       ACK_ready
-};
-
-static void consume_shallow_list(int fd)
-{
-       if (args.stateless_rpc && args.depth > 0) {
-               /* If we sent a depth we will get back "duplicate"
-                * shallow and unshallow commands every time there
-                * is a block of have lines exchanged.
-                */
-               char line[1000];
-               while (packet_read_line(fd, line, sizeof(line))) {
-                       if (!prefixcmp(line, "shallow "))
-                               continue;
-                       if (!prefixcmp(line, "unshallow "))
-                               continue;
-                       die("git fetch-pack: expected shallow list");
-               }
-       }
-}
-
-struct write_shallow_data {
-       struct strbuf *out;
-       int use_pack_protocol;
-       int count;
-};
-
-static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
-{
-       struct write_shallow_data *data = cb_data;
-       const char *hex = sha1_to_hex(graft->sha1);
-       data->count++;
-       if (data->use_pack_protocol)
-               packet_buf_write(data->out, "shallow %s", hex);
-       else {
-               strbuf_addstr(data->out, hex);
-               strbuf_addch(data->out, '\n');
-       }
-       return 0;
-}
-
-static int write_shallow_commits(struct strbuf *out, int use_pack_protocol)
-{
-       struct write_shallow_data data;
-       data.out = out;
-       data.use_pack_protocol = use_pack_protocol;
-       data.count = 0;
-       for_each_commit_graft(write_one_shallow, &data);
-       return data.count;
-}
-
-static enum ack_type get_ack(int fd, unsigned char *result_sha1)
-{
-       static char line[1000];
-       int len = packet_read_line(fd, line, sizeof(line));
-
-       if (!len)
-               die("git fetch-pack: expected ACK/NAK, got EOF");
-       if (line[len-1] == '\n')
-               line[--len] = 0;
-       if (!strcmp(line, "NAK"))
-               return NAK;
-       if (!prefixcmp(line, "ACK ")) {
-               if (!get_sha1_hex(line+4, result_sha1)) {
-                       if (strstr(line+45, "continue"))
-                               return ACK_continue;
-                       if (strstr(line+45, "common"))
-                               return ACK_common;
-                       if (strstr(line+45, "ready"))
-                               return ACK_ready;
-                       return ACK;
-               }
-       }
-       die("git fetch_pack: expected ACK/NAK, got '%s'", line);
-}
-
-static void send_request(int fd, struct strbuf *buf)
-{
-       if (args.stateless_rpc) {
-               send_sideband(fd, -1, buf->buf, buf->len, LARGE_PACKET_MAX);
-               packet_flush(fd);
-       } else
-               safe_write(fd, buf->buf, buf->len);
-}
-
-static void insert_one_alternate_ref(const struct ref *ref, void *unused)
-{
-       rev_list_insert_ref(NULL, ref->old_sha1, 0, NULL);
-}
-
-#define INITIAL_FLUSH 16
-#define PIPESAFE_FLUSH 32
-#define LARGE_FLUSH 1024
-
-static int next_flush(int count)
-{
-       int flush_limit = args.stateless_rpc ? LARGE_FLUSH : PIPESAFE_FLUSH;
-
-       if (count < flush_limit)
-               count <<= 1;
-       else
-               count += flush_limit;
-       return count;
-}
-
-static int find_common(int fd[2], unsigned char *result_sha1,
-                      struct ref *refs)
-{
-       int fetching;
-       int count = 0, flushes = 0, flush_at = INITIAL_FLUSH, retval;
-       const unsigned char *sha1;
-       unsigned in_vain = 0;
-       int got_continue = 0;
-       int got_ready = 0;
-       struct strbuf req_buf = STRBUF_INIT;
-       size_t state_len = 0;
-
-       if (args.stateless_rpc && multi_ack == 1)
-               die("--stateless-rpc requires multi_ack_detailed");
-       if (marked)
-               for_each_ref(clear_marks, NULL);
-       marked = 1;
-
-       for_each_ref(rev_list_insert_ref, NULL);
-       for_each_alternate_ref(insert_one_alternate_ref, NULL);
-
-       fetching = 0;
-       for ( ; refs ; refs = refs->next) {
-               unsigned char *remote = refs->old_sha1;
-               const char *remote_hex;
-               struct object *o;
-
-               /*
-                * If that object is complete (i.e. it is an ancestor of a
-                * local ref), we tell them we have it but do not have to
-                * tell them about its ancestors, which they already know
-                * about.
-                *
-                * We use lookup_object here because we are only
-                * interested in the case we *know* the object is
-                * reachable and we have already scanned it.
-                */
-               if (((o = lookup_object(remote)) != NULL) &&
-                               (o->flags & COMPLETE)) {
-                       continue;
-               }
-
-               remote_hex = sha1_to_hex(remote);
-               if (!fetching) {
-                       struct strbuf c = STRBUF_INIT;
-                       if (multi_ack == 2)     strbuf_addstr(&c, " multi_ack_detailed");
-                       if (multi_ack == 1)     strbuf_addstr(&c, " multi_ack");
-                       if (no_done)            strbuf_addstr(&c, " no-done");
-                       if (use_sideband == 2)  strbuf_addstr(&c, " side-band-64k");
-                       if (use_sideband == 1)  strbuf_addstr(&c, " side-band");
-                       if (args.use_thin_pack) strbuf_addstr(&c, " thin-pack");
-                       if (args.no_progress)   strbuf_addstr(&c, " no-progress");
-                       if (args.include_tag)   strbuf_addstr(&c, " include-tag");
-                       if (prefer_ofs_delta)   strbuf_addstr(&c, " ofs-delta");
-                       if (agent_supported)    strbuf_addf(&c, " agent=%s",
-                                                           git_user_agent_sanitized());
-                       packet_buf_write(&req_buf, "want %s%s\n", remote_hex, c.buf);
-                       strbuf_release(&c);
-               } else
-                       packet_buf_write(&req_buf, "want %s\n", remote_hex);
-               fetching++;
-       }
-
-       if (!fetching) {
-               strbuf_release(&req_buf);
-               packet_flush(fd[1]);
-               return 1;
-       }
-
-       if (is_repository_shallow())
-               write_shallow_commits(&req_buf, 1);
-       if (args.depth > 0)
-               packet_buf_write(&req_buf, "deepen %d", args.depth);
-       packet_buf_flush(&req_buf);
-       state_len = req_buf.len;
-
-       if (args.depth > 0) {
-               char line[1024];
-               unsigned char sha1[20];
-
-               send_request(fd[1], &req_buf);
-               while (packet_read_line(fd[0], line, sizeof(line))) {
-                       if (!prefixcmp(line, "shallow ")) {
-                               if (get_sha1_hex(line + 8, sha1))
-                                       die("invalid shallow line: %s", line);
-                               register_shallow(sha1);
-                               continue;
-                       }
-                       if (!prefixcmp(line, "unshallow ")) {
-                               if (get_sha1_hex(line + 10, sha1))
-                                       die("invalid unshallow line: %s", line);
-                               if (!lookup_object(sha1))
-                                       die("object not found: %s", line);
-                               /* make sure that it is parsed as shallow */
-                               if (!parse_object(sha1))
-                                       die("error in object: %s", line);
-                               if (unregister_shallow(sha1))
-                                       die("no shallow found: %s", line);
-                               continue;
-                       }
-                       die("expected shallow/unshallow, got %s", line);
-               }
-       } else if (!args.stateless_rpc)
-               send_request(fd[1], &req_buf);
-
-       if (!args.stateless_rpc) {
-               /* If we aren't using the stateless-rpc interface
-                * we don't need to retain the headers.
-                */
-               strbuf_setlen(&req_buf, 0);
-               state_len = 0;
-       }
-
-       flushes = 0;
-       retval = -1;
-       while ((sha1 = get_rev())) {
-               packet_buf_write(&req_buf, "have %s\n", sha1_to_hex(sha1));
-               if (args.verbose)
-                       fprintf(stderr, "have %s\n", sha1_to_hex(sha1));
-               in_vain++;
-               if (flush_at <= ++count) {
-                       int ack;
-
-                       packet_buf_flush(&req_buf);
-                       send_request(fd[1], &req_buf);
-                       strbuf_setlen(&req_buf, state_len);
-                       flushes++;
-                       flush_at = next_flush(count);
-
-                       /*
-                        * We keep one window "ahead" of the other side, and
-                        * will wait for an ACK only on the next one
-                        */
-                       if (!args.stateless_rpc && count == INITIAL_FLUSH)
-                               continue;
-
-                       consume_shallow_list(fd[0]);
-                       do {
-                               ack = get_ack(fd[0], result_sha1);
-                               if (args.verbose && ack)
-                                       fprintf(stderr, "got ack %d %s\n", ack,
-                                                       sha1_to_hex(result_sha1));
-                               switch (ack) {
-                               case ACK:
-                                       flushes = 0;
-                                       multi_ack = 0;
-                                       retval = 0;
-                                       goto done;
-                               case ACK_common:
-                               case ACK_ready:
-                               case ACK_continue: {
-                                       struct commit *commit =
-                                               lookup_commit(result_sha1);
-                                       if (!commit)
-                                               die("invalid commit %s", sha1_to_hex(result_sha1));
-                                       if (args.stateless_rpc
-                                        && ack == ACK_common
-                                        && !(commit->object.flags & COMMON)) {
-                                               /* We need to replay the have for this object
-                                                * on the next RPC request so the peer knows
-                                                * it is in common with us.
-                                                */
-                                               const char *hex = sha1_to_hex(result_sha1);
-                                               packet_buf_write(&req_buf, "have %s\n", hex);
-                                               state_len = req_buf.len;
-                                       }
-                                       mark_common(commit, 0, 1);
-                                       retval = 0;
-                                       in_vain = 0;
-                                       got_continue = 1;
-                                       if (ack == ACK_ready) {
-                                               rev_list = NULL;
-                                               got_ready = 1;
-                                       }
-                                       break;
-                                       }
-                               }
-                       } while (ack);
-                       flushes--;
-                       if (got_continue && MAX_IN_VAIN < in_vain) {
-                               if (args.verbose)
-                                       fprintf(stderr, "giving up\n");
-                               break; /* give up */
-                       }
-               }
-       }
-done:
-       if (!got_ready || !no_done) {
-               packet_buf_write(&req_buf, "done\n");
-               send_request(fd[1], &req_buf);
-       }
-       if (args.verbose)
-               fprintf(stderr, "done\n");
-       if (retval != 0) {
-               multi_ack = 0;
-               flushes++;
-       }
-       strbuf_release(&req_buf);
-
-       consume_shallow_list(fd[0]);
-       while (flushes || multi_ack) {
-               int ack = get_ack(fd[0], result_sha1);
-               if (ack) {
-                       if (args.verbose)
-                               fprintf(stderr, "got ack (%d) %s\n", ack,
-                                       sha1_to_hex(result_sha1));
-                       if (ack == ACK)
-                               return 0;
-                       multi_ack = 1;
-                       continue;
-               }
-               flushes--;
-       }
-       /* it is no error to fetch into a completely empty repo */
-       return count ? retval : 0;
-}
-
-static struct commit_list *complete;
-
-static int mark_complete(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
-{
-       struct object *o = parse_object(sha1);
-
-       while (o && o->type == OBJ_TAG) {
-               struct tag *t = (struct tag *) o;
-               if (!t->tagged)
-                       break; /* broken repository */
-               o->flags |= COMPLETE;
-               o = parse_object(t->tagged->sha1);
-       }
-       if (o && o->type == OBJ_COMMIT) {
-               struct commit *commit = (struct commit *)o;
-               if (!(commit->object.flags & COMPLETE)) {
-                       commit->object.flags |= COMPLETE;
-                       commit_list_insert_by_date(commit, &complete);
-               }
-       }
-       return 0;
-}
-
-static void mark_recent_complete_commits(unsigned long cutoff)
-{
-       while (complete && cutoff <= complete->item->date) {
-               if (args.verbose)
-                       fprintf(stderr, "Marking %s as complete\n",
-                               sha1_to_hex(complete->item->object.sha1));
-               pop_most_recent_commit(&complete, COMPLETE);
-       }
-}
-
-static int non_matching_ref(struct string_list_item *item, void *unused)
-{
-       if (item->util) {
-               item->util = NULL;
-               return 0;
-       }
-       else
-               return 1;
-}
-
-static void filter_refs(struct ref **refs, struct string_list *sought)
-{
-       struct ref *newlist = NULL;
-       struct ref **newtail = &newlist;
-       struct ref *ref, *next;
-       int sought_pos;
-
-       sought_pos = 0;
-       for (ref = *refs; ref; ref = next) {
-               int keep = 0;
-               next = ref->next;
-               if (!memcmp(ref->name, "refs/", 5) &&
-                   check_refname_format(ref->name + 5, 0))
-                       ; /* trash */
-               else {
-                       while (sought_pos < sought->nr) {
-                               int cmp = strcmp(ref->name, sought->items[sought_pos].string);
-                               if (cmp < 0)
-                                       break; /* definitely do not have it */
-                               else if (cmp == 0) {
-                                       keep = 1; /* definitely have it */
-                                       sought->items[sought_pos++].util = "matched";
-                                       break;
-                               }
-                               else
-                                       sought_pos++; /* might have it; keep looking */
-                       }
-               }
-
-               if (! keep && args.fetch_all &&
-                   (!args.depth || prefixcmp(ref->name, "refs/tags/")))
-                       keep = 1;
-
-               if (keep) {
-                       *newtail = ref;
-                       ref->next = NULL;
-                       newtail = &ref->next;
-               } else {
-                       free(ref);
-               }
-       }
-
-       filter_string_list(sought, 0, non_matching_ref, NULL);
-       *refs = newlist;
-}
-
-static void mark_alternate_complete(const struct ref *ref, void *unused)
-{
-       mark_complete(NULL, ref->old_sha1, 0, NULL);
-}
-
-static int everything_local(struct ref **refs, struct string_list *sought)
-{
-       struct ref *ref;
-       int retval;
-       unsigned long cutoff = 0;
-
-       save_commit_buffer = 0;
-
-       for (ref = *refs; ref; ref = ref->next) {
-               struct object *o;
-
-               o = parse_object(ref->old_sha1);
-               if (!o)
-                       continue;
-
-               /* We already have it -- which may mean that we were
-                * in sync with the other side at some time after
-                * that (it is OK if we guess wrong here).
-                */
-               if (o->type == OBJ_COMMIT) {
-                       struct commit *commit = (struct commit *)o;
-                       if (!cutoff || cutoff < commit->date)
-                               cutoff = commit->date;
-               }
-       }
-
-       if (!args.depth) {
-               for_each_ref(mark_complete, NULL);
-               for_each_alternate_ref(mark_alternate_complete, NULL);
-               if (cutoff)
-                       mark_recent_complete_commits(cutoff);
-       }
-
-       /*
-        * Mark all complete remote refs as common refs.
-        * Don't mark them common yet; the server has to be told so first.
-        */
-       for (ref = *refs; ref; ref = ref->next) {
-               struct object *o = deref_tag(lookup_object(ref->old_sha1),
-                                            NULL, 0);
-
-               if (!o || o->type != OBJ_COMMIT || !(o->flags & COMPLETE))
-                       continue;
-
-               if (!(o->flags & SEEN)) {
-                       rev_list_push((struct commit *)o, COMMON_REF | SEEN);
-
-                       mark_common((struct commit *)o, 1, 1);
-               }
-       }
-
-       filter_refs(refs, sought);
-
-       for (retval = 1, ref = *refs; ref ; ref = ref->next) {
-               const unsigned char *remote = ref->old_sha1;
-               unsigned char local[20];
-               struct object *o;
-
-               o = lookup_object(remote);
-               if (!o || !(o->flags & COMPLETE)) {
-                       retval = 0;
-                       if (!args.verbose)
-                               continue;
-                       fprintf(stderr,
-                               "want %s (%s)\n", sha1_to_hex(remote),
-                               ref->name);
-                       continue;
-               }
-
-               hashcpy(ref->new_sha1, local);
-               if (!args.verbose)
-                       continue;
-               fprintf(stderr,
-                       "already have %s (%s)\n", sha1_to_hex(remote),
-                       ref->name);
-       }
-       return retval;
-}
-
-static int sideband_demux(int in, int out, void *data)
-{
-       int *xd = data;
-
-       int ret = recv_sideband("fetch-pack", xd[0], out);
-       close(out);
-       return ret;
-}
-
-static int get_pack(int xd[2], char **pack_lockfile)
-{
-       struct async demux;
-       const char *argv[20];
-       char keep_arg[256];
-       char hdr_arg[256];
-       const char **av;
-       int do_keep = args.keep_pack;
-       struct child_process cmd;
-
-       memset(&demux, 0, sizeof(demux));
-       if (use_sideband) {
-               /* xd[] is talking with upload-pack; subprocess reads from
-                * xd[0], spits out band#2 to stderr, and feeds us band#1
-                * through demux->out.
-                */
-               demux.proc = sideband_demux;
-               demux.data = xd;
-               demux.out = -1;
-               if (start_async(&demux))
-                       die("fetch-pack: unable to fork off sideband"
-                           " demultiplexer");
-       }
-       else
-               demux.out = xd[0];
-
-       memset(&cmd, 0, sizeof(cmd));
-       cmd.argv = argv;
-       av = argv;
-       *hdr_arg = 0;
-       if (!args.keep_pack && unpack_limit) {
-               struct pack_header header;
-
-               if (read_pack_header(demux.out, &header))
-                       die("protocol error: bad pack header");
-               snprintf(hdr_arg, sizeof(hdr_arg),
-                        "--pack_header=%"PRIu32",%"PRIu32,
-                        ntohl(header.hdr_version), ntohl(header.hdr_entries));
-               if (ntohl(header.hdr_entries) < unpack_limit)
-                       do_keep = 0;
-               else
-                       do_keep = 1;
-       }
-
-       if (do_keep) {
-               if (pack_lockfile)
-                       cmd.out = -1;
-               *av++ = "index-pack";
-               *av++ = "--stdin";
-               if (!args.quiet && !args.no_progress)
-                       *av++ = "-v";
-               if (args.use_thin_pack)
-                       *av++ = "--fix-thin";
-               if (args.lock_pack || unpack_limit) {
-                       int s = sprintf(keep_arg,
-                                       "--keep=fetch-pack %"PRIuMAX " on ", (uintmax_t) getpid());
-                       if (gethostname(keep_arg + s, sizeof(keep_arg) - s))
-                               strcpy(keep_arg + s, "localhost");
-                       *av++ = keep_arg;
-               }
-       }
-       else {
-               *av++ = "unpack-objects";
-               if (args.quiet || args.no_progress)
-                       *av++ = "-q";
-       }
-       if (*hdr_arg)
-               *av++ = hdr_arg;
-       if (fetch_fsck_objects >= 0
-           ? fetch_fsck_objects
-           : transfer_fsck_objects >= 0
-           ? transfer_fsck_objects
-           : 0)
-               *av++ = "--strict";
-       *av++ = NULL;
-
-       cmd.in = demux.out;
-       cmd.git_cmd = 1;
-       if (start_command(&cmd))
-               die("fetch-pack: unable to fork off %s", argv[0]);
-       if (do_keep && pack_lockfile) {
-               *pack_lockfile = index_pack_lockfile(cmd.out);
-               close(cmd.out);
-       }
-
-       if (finish_command(&cmd))
-               die("%s failed", argv[0]);
-       if (use_sideband && finish_async(&demux))
-               die("error in sideband demultiplexer");
-       return 0;
-}
-
-static struct ref *do_fetch_pack(int fd[2],
-               const struct ref *orig_ref,
-               struct string_list *sought,
-               char **pack_lockfile)
-{
-       struct ref *ref = copy_ref_list(orig_ref);
-       unsigned char sha1[20];
-       const char *agent_feature;
-       int agent_len;
-
-       sort_ref_list(&ref, ref_compare_name);
-
-       if (is_repository_shallow() && !server_supports("shallow"))
-               die("Server does not support shallow clients");
-       if (server_supports("multi_ack_detailed")) {
-               if (args.verbose)
-                       fprintf(stderr, "Server supports multi_ack_detailed\n");
-               multi_ack = 2;
-               if (server_supports("no-done")) {
-                       if (args.verbose)
-                               fprintf(stderr, "Server supports no-done\n");
-                       if (args.stateless_rpc)
-                               no_done = 1;
-               }
-       }
-       else if (server_supports("multi_ack")) {
-               if (args.verbose)
-                       fprintf(stderr, "Server supports multi_ack\n");
-               multi_ack = 1;
-       }
-       if (server_supports("side-band-64k")) {
-               if (args.verbose)
-                       fprintf(stderr, "Server supports side-band-64k\n");
-               use_sideband = 2;
-       }
-       else if (server_supports("side-band")) {
-               if (args.verbose)
-                       fprintf(stderr, "Server supports side-band\n");
-               use_sideband = 1;
-       }
-       if (!server_supports("thin-pack"))
-               args.use_thin_pack = 0;
-       if (!server_supports("no-progress"))
-               args.no_progress = 0;
-       if (!server_supports("include-tag"))
-               args.include_tag = 0;
-       if (server_supports("ofs-delta")) {
-               if (args.verbose)
-                       fprintf(stderr, "Server supports ofs-delta\n");
-       } else
-               prefer_ofs_delta = 0;
-
-       if ((agent_feature = server_feature_value("agent", &agent_len))) {
-               agent_supported = 1;
-               if (args.verbose && agent_len)
-                       fprintf(stderr, "Server version is %.*s\n",
-                               agent_len, agent_feature);
-       }
-
-       if (everything_local(&ref, sought)) {
-               packet_flush(fd[1]);
-               goto all_done;
-       }
-       if (find_common(fd, sha1, ref) < 0)
-               if (!args.keep_pack)
-                       /* When cloning, it is not unusual to have
-                        * no common commit.
-                        */
-                       warning("no common commits");
-
-       if (args.stateless_rpc)
-               packet_flush(fd[1]);
-       if (get_pack(fd, pack_lockfile))
-               die("git fetch-pack: fetch failed.");
-
- all_done:
-       return ref;
-}
-
-static int fetch_pack_config(const char *var, const char *value, void *cb)
-{
-       if (strcmp(var, "fetch.unpacklimit") == 0) {
-               fetch_unpack_limit = git_config_int(var, value);
-               return 0;
-       }
-
-       if (strcmp(var, "transfer.unpacklimit") == 0) {
-               transfer_unpack_limit = git_config_int(var, value);
-               return 0;
-       }
-
-       if (strcmp(var, "repack.usedeltabaseoffset") == 0) {
-               prefer_ofs_delta = git_config_bool(var, value);
-               return 0;
-       }
-
-       if (!strcmp(var, "fetch.fsckobjects")) {
-               fetch_fsck_objects = git_config_bool(var, value);
-               return 0;
-       }
-
-       if (!strcmp(var, "transfer.fsckobjects")) {
-               transfer_fsck_objects = git_config_bool(var, value);
-               return 0;
-       }
-
-       return git_default_config(var, value, cb);
-}
-
-static struct lock_file lock;
-
-static void fetch_pack_setup(void)
-{
-       static int did_setup;
-       if (did_setup)
-               return;
-       git_config(fetch_pack_config, NULL);
-       if (0 <= transfer_unpack_limit)
-               unpack_limit = transfer_unpack_limit;
-       else if (0 <= fetch_unpack_limit)
-               unpack_limit = fetch_unpack_limit;
-       did_setup = 1;
-}
-
 int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
 {
        int i, ret;
@@ -900,9 +17,13 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
        char *pack_lockfile = NULL;
        char **pack_lockfile_ptr = NULL;
        struct child_process *conn;
+       struct fetch_pack_args args;
 
        packet_trace_identity("fetch-pack");
 
+       memset(&args, 0, sizeof(args));
+       args.uploadpack = "git-upload-pack";
+
        for (i = 1; i < argc && *argv[i] == '-'; i++) {
                const char *arg = argv[i];
 
@@ -1038,66 +159,3 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
 
        return ret;
 }
-
-struct ref *fetch_pack(struct fetch_pack_args *my_args,
-                      int fd[], struct child_process *conn,
-                      const struct ref *ref,
-                      const char *dest,
-                      struct string_list *sought,
-                      char **pack_lockfile)
-{
-       struct stat st;
-       struct ref *ref_cpy;
-
-       fetch_pack_setup();
-       if (&args != my_args)
-               memcpy(&args, my_args, sizeof(args));
-       if (args.depth > 0) {
-               if (stat(git_path("shallow"), &st))
-                       st.st_mtime = 0;
-       }
-
-       if (sought->nr) {
-               sort_string_list(sought);
-               string_list_remove_duplicates(sought, 0);
-       }
-
-       if (!ref) {
-               packet_flush(fd[1]);
-               die("no matching remote head");
-       }
-       ref_cpy = do_fetch_pack(fd, ref, sought, pack_lockfile);
-
-       if (args.depth > 0) {
-               struct cache_time mtime;
-               struct strbuf sb = STRBUF_INIT;
-               char *shallow = git_path("shallow");
-               int fd;
-
-               mtime.sec = st.st_mtime;
-               mtime.nsec = ST_MTIME_NSEC(st);
-               if (stat(shallow, &st)) {
-                       if (mtime.sec)
-                               die("shallow file was removed during fetch");
-               } else if (st.st_mtime != mtime.sec
-#ifdef USE_NSEC
-                               || ST_MTIME_NSEC(st) != mtime.nsec
-#endif
-                         )
-                       die("shallow file was changed during fetch");
-
-               fd = hold_lock_file_for_update(&lock, shallow,
-                                              LOCK_DIE_ON_ERROR);
-               if (!write_shallow_commits(&sb, 0)
-                || write_in_full(fd, sb.buf, sb.len) != sb.len) {
-                       unlink_or_warn(shallow);
-                       rollback_lock_file(&lock);
-               } else {
-                       commit_lock_file(&lock);
-               }
-               strbuf_release(&sb);
-       }
-
-       reprepare_packed_git();
-       return ref_cpy;
-}
index 09cf43e..e7b7db1 100644 (file)
@@ -351,7 +351,8 @@ static int git_log_config(const char *var, const char *value, void *cb)
        }
        if (!prefixcmp(var, "color.decorate."))
                return parse_decorate_color_config(var, 15, value);
-
+       if (grep_config(var, value, cb) < 0)
+               return -1;
        return git_diff_ui_config(var, value, cb);
 }
 
@@ -360,6 +361,7 @@ int cmd_whatchanged(int argc, const char **argv, const char *prefix)
        struct rev_info rev;
        struct setup_revision_opt opt;
 
+       init_grep_defaults();
        git_config(git_log_config, NULL);
 
        init_revisions(&rev, prefix);
@@ -450,6 +452,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
        struct pathspec match_all;
        int i, count, ret = 0;
 
+       init_grep_defaults();
        git_config(git_log_config, NULL);
 
        init_pathspec(&match_all, NULL);
@@ -530,6 +533,7 @@ int cmd_log_reflog(int argc, const char **argv, const char *prefix)
        struct rev_info rev;
        struct setup_revision_opt opt;
 
+       init_grep_defaults();
        git_config(git_log_config, NULL);
 
        init_revisions(&rev, prefix);
@@ -552,6 +556,7 @@ int cmd_log(int argc, const char **argv, const char *prefix)
        struct rev_info rev;
        struct setup_revision_opt opt;
 
+       init_grep_defaults();
        git_config(git_log_config, NULL);
 
        init_revisions(&rev, prefix);
@@ -1121,6 +1126,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
        extra_hdr.strdup_strings = 1;
        extra_to.strdup_strings = 1;
        extra_cc.strdup_strings = 1;
+       init_grep_defaults();
        git_config(git_format_config, NULL);
        init_revisions(&rev, prefix);
        rev.commit_format = CMIT_FMT_EMAIL;
index b5434af..4a9ee69 100644 (file)
@@ -337,7 +337,7 @@ void overlay_tree_on_cache(const char *tree_name, const char *prefix)
                matchbuf[0] = prefix;
                matchbuf[1] = NULL;
                init_pathspec(&pathspec, matchbuf);
-               pathspec.items[0].use_wildcard = 0;
+               pathspec.items[0].nowildcard_len = pathspec.items[0].len;
        } else
                init_pathspec(&pathspec, NULL);
        if (read_tree(tree, 1, &pathspec))
index 235c17c..fb76e38 100644 (file)
@@ -168,7 +168,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
 
        init_pathspec(&pathspec, get_pathspec(prefix, argv + 1));
        for (i = 0; i < pathspec.nr; i++)
-               pathspec.items[i].use_wildcard = 0;
+               pathspec.items[i].nowildcard_len = pathspec.items[i].len;
        pathspec.has_wildcard = 0;
        tree = parse_tree_indirect(sha1);
        if (!tree)
index 0ec8f0d..a96e8ea 100644 (file)
@@ -628,59 +628,6 @@ static void write_tree_trivial(unsigned char *sha1)
                die(_("git write-tree failed to write a tree"));
 }
 
-static const char *merge_argument(struct commit *commit)
-{
-       if (commit)
-               return sha1_to_hex(commit->object.sha1);
-       else
-               return EMPTY_TREE_SHA1_HEX;
-}
-
-int try_merge_command(const char *strategy, size_t xopts_nr,
-                     const char **xopts, struct commit_list *common,
-                     const char *head_arg, struct commit_list *remotes)
-{
-       const char **args;
-       int i = 0, x = 0, ret;
-       struct commit_list *j;
-       struct strbuf buf = STRBUF_INIT;
-
-       args = xmalloc((4 + xopts_nr + commit_list_count(common) +
-                       commit_list_count(remotes)) * sizeof(char *));
-       strbuf_addf(&buf, "merge-%s", strategy);
-       args[i++] = buf.buf;
-       for (x = 0; x < xopts_nr; x++) {
-               char *s = xmalloc(strlen(xopts[x])+2+1);
-               strcpy(s, "--");
-               strcpy(s+2, xopts[x]);
-               args[i++] = s;
-       }
-       for (j = common; j; j = j->next)
-               args[i++] = xstrdup(merge_argument(j->item));
-       args[i++] = "--";
-       args[i++] = head_arg;
-       for (j = remotes; j; j = j->next)
-               args[i++] = xstrdup(merge_argument(j->item));
-       args[i] = NULL;
-       ret = run_command_v_opt(args, RUN_GIT_CMD);
-       strbuf_release(&buf);
-       i = 1;
-       for (x = 0; x < xopts_nr; x++)
-               free((void *)args[i++]);
-       for (j = common; j; j = j->next)
-               free((void *)args[i++]);
-       i += 2;
-       for (j = remotes; j; j = j->next)
-               free((void *)args[i++]);
-       free(args);
-       discard_cache();
-       if (read_cache() < 0)
-               die(_("failed to read the cache"));
-       resolve_undo_clear();
-
-       return ret;
-}
-
 static int try_merge_strategy(const char *strategy, struct commit_list *common,
                              struct commit_list *remoteheads,
                              struct commit *head, const char *head_arg)
@@ -762,56 +709,6 @@ static int count_unmerged_entries(void)
        return ret;
 }
 
-int checkout_fast_forward(const unsigned char *head, const unsigned char *remote)
-{
-       struct tree *trees[MAX_UNPACK_TREES];
-       struct unpack_trees_options opts;
-       struct tree_desc t[MAX_UNPACK_TREES];
-       int i, fd, nr_trees = 0;
-       struct dir_struct dir;
-       struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file));
-
-       refresh_cache(REFRESH_QUIET);
-
-       fd = hold_locked_index(lock_file, 1);
-
-       memset(&trees, 0, sizeof(trees));
-       memset(&opts, 0, sizeof(opts));
-       memset(&t, 0, sizeof(t));
-       if (overwrite_ignore) {
-               memset(&dir, 0, sizeof(dir));
-               dir.flags |= DIR_SHOW_IGNORED;
-               setup_standard_excludes(&dir);
-               opts.dir = &dir;
-       }
-
-       opts.head_idx = 1;
-       opts.src_index = &the_index;
-       opts.dst_index = &the_index;
-       opts.update = 1;
-       opts.verbose_update = 1;
-       opts.merge = 1;
-       opts.fn = twoway_merge;
-       setup_unpack_trees_porcelain(&opts, "merge");
-
-       trees[nr_trees] = parse_tree_indirect(head);
-       if (!trees[nr_trees++])
-               return -1;
-       trees[nr_trees] = parse_tree_indirect(remote);
-       if (!trees[nr_trees++])
-               return -1;
-       for (i = 0; i < nr_trees; i++) {
-               parse_tree(trees[i]);
-               init_tree_desc(t+i, trees[i]->buffer, trees[i]->size);
-       }
-       if (unpack_trees(nr_trees, t, &opts))
-               return -1;
-       if (write_cache(fd, active_cache, active_nr) ||
-               commit_locked_index(lock_file))
-               die(_("unable to write new index file"));
-       return 0;
-}
-
 static void split_merge_strategies(const char *string, struct strategy **list,
                                   int *nr, int *alloc)
 {
@@ -1424,7 +1321,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                }
 
                if (checkout_fast_forward(head_commit->object.sha1,
-                                         commit->object.sha1)) {
+                                         commit->object.sha1,
+                                         overwrite_ignore)) {
                        ret = 1;
                        goto done;
                }
index 5e14064..f069462 100644 (file)
@@ -2033,7 +2033,6 @@ static int add_ref_tag(const char *path, const unsigned char *sha1, int flag, vo
 
        if (!prefixcmp(path, "refs/tags/") && /* is a tag? */
            !peel_ref(path, peeled)        && /* peelable? */
-           !is_null_sha1(peeled)          && /* annotated tag? */
            locate_object_entry(peeled))      /* object packed? */
                add_object_entry(sha1, OBJ_TAG, NULL, 0);
        return 0;
index db9ba30..8491e43 100644 (file)
@@ -220,31 +220,42 @@ static const char message_advice_checkout_pull_push[] =
           "(e.g. 'git pull') before pushing again.\n"
           "See the 'Note about fast-forwards' in 'git push --help' for details.");
 
+static const char message_advice_ref_already_exists[] =
+       N_("Updates were rejected because the destination reference already exists\n"
+          "in the remote.");
+
 static void advise_pull_before_push(void)
 {
-       if (!advice_push_non_ff_current || !advice_push_nonfastforward)
+       if (!advice_push_non_ff_current || !advice_push_update_rejected)
                return;
        advise(_(message_advice_pull_before_push));
 }
 
 static void advise_use_upstream(void)
 {
-       if (!advice_push_non_ff_default || !advice_push_nonfastforward)
+       if (!advice_push_non_ff_default || !advice_push_update_rejected)
                return;
        advise(_(message_advice_use_upstream));
 }
 
 static void advise_checkout_pull_push(void)
 {
-       if (!advice_push_non_ff_matching || !advice_push_nonfastforward)
+       if (!advice_push_non_ff_matching || !advice_push_update_rejected)
                return;
        advise(_(message_advice_checkout_pull_push));
 }
 
+static void advise_ref_already_exists(void)
+{
+       if (!advice_push_already_exists || !advice_push_update_rejected)
+               return;
+       advise(_(message_advice_ref_already_exists));
+}
+
 static int push_with_options(struct transport *transport, int flags)
 {
        int err;
-       int nonfastforward;
+       unsigned int reject_reasons;
 
        transport_set_verbosity(transport, verbosity, progress);
 
@@ -257,7 +268,7 @@ static int push_with_options(struct transport *transport, int flags)
        if (verbosity > 0)
                fprintf(stderr, _("Pushing to %s\n"), transport->url);
        err = transport_push(transport, refspec_nr, refspec, flags,
-                            &nonfastforward);
+                            &reject_reasons);
        if (err != 0)
                error(_("failed to push some refs to '%s'"), transport->url);
 
@@ -265,18 +276,15 @@ static int push_with_options(struct transport *transport, int flags)
        if (!err)
                return 0;
 
-       switch (nonfastforward) {
-       default:
-               break;
-       case NON_FF_HEAD:
+       if (reject_reasons & REJECT_NON_FF_HEAD) {
                advise_pull_before_push();
-               break;
-       case NON_FF_OTHER:
+       } else if (reject_reasons & REJECT_NON_FF_OTHER) {
                if (default_matching_used)
                        advise_use_upstream();
                else
                        advise_checkout_pull_push();
-               break;
+       } else if (reject_reasons & REJECT_ALREADY_EXISTS) {
+               advise_ref_already_exists();
        }
 
        return 1;
index e3aaf70..398ccd5 100644 (file)
@@ -46,24 +46,27 @@ typedef int (*each_replace_name_fn)(const char *name, const char *ref,
 
 static int for_each_replace_name(const char **argv, each_replace_name_fn fn)
 {
-       const char **p;
+       const char **p, *full_hex;
        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);
+               if (get_sha1(*p, sha1)) {
+                       error("Failed to resolve '%s' as a valid ref.", *p);
                        had_error = 1;
                        continue;
                }
+               full_hex = sha1_to_hex(sha1);
+               snprintf(ref, sizeof(ref), "refs/replace/%s", full_hex);
+               /* read_ref() may reuse the buffer */
+               full_hex = ref + strlen("refs/replace/");
                if (read_ref(ref, sha1)) {
-                       error("replace ref '%s' not found.", *p);
+                       error("replace ref '%s' not found.", full_hex);
                        had_error = 1;
                        continue;
                }
-               if (fn(*p, ref, sha1))
+               if (fn(full_hex, ref, sha1))
                        had_error = 1;
        }
        return had_error;
index ff5a383..67701be 100644 (file)
@@ -201,55 +201,6 @@ static void show_edge(struct commit *commit)
        printf("-%s\n", sha1_to_hex(commit->object.sha1));
 }
 
-static inline int log2i(int n)
-{
-       int log2 = 0;
-
-       for (; n > 1; n >>= 1)
-               log2++;
-
-       return log2;
-}
-
-static inline int exp2i(int n)
-{
-       return 1 << n;
-}
-
-/*
- * Estimate the number of bisect steps left (after the current step)
- *
- * For any x between 0 included and 2^n excluded, the probability for
- * n - 1 steps left looks like:
- *
- * P(2^n + x) == (2^n - x) / (2^n + x)
- *
- * and P(2^n + x) < 0.5 means 2^n < 3x
- */
-int estimate_bisect_steps(int all)
-{
-       int n, x, e;
-
-       if (all < 3)
-               return 0;
-
-       n = log2i(all);
-       e = exp2i(n);
-       x = all - e;
-
-       return (e < 3 * x) ? n : n - 1;
-}
-
-void print_commit_list(struct commit_list *list,
-                      const char *format_cur,
-                      const char *format_last)
-{
-       for ( ; list; list = list->next) {
-               const char *format = list->next ? format_cur : format_last;
-               printf(format, sha1_to_hex(list->item->object.sha1));
-       }
-}
-
 static void print_var_str(const char *var, const char *val)
 {
        printf("%s='%s'\n", var, val);
index b384c4c..dabfcf6 100644 (file)
@@ -9,6 +9,7 @@
 #include "cache-tree.h"
 #include "tree-walk.h"
 #include "parse-options.h"
+#include "submodule.h"
 
 static const char * const builtin_rm_usage[] = {
        N_("git rm [options] [--] <file>..."),
@@ -17,9 +18,58 @@ static const char * const builtin_rm_usage[] = {
 
 static struct {
        int nr, alloc;
-       const char **name;
+       struct {
+               const char *name;
+               char is_submodule;
+       } *entry;
 } list;
 
+static int get_ours_cache_pos(const char *path, int pos)
+{
+       int i = -pos - 1;
+
+       while ((i < active_nr) && !strcmp(active_cache[i]->name, path)) {
+               if (ce_stage(active_cache[i]) == 2)
+                       return i;
+               i++;
+       }
+       return -1;
+}
+
+static int check_submodules_use_gitfiles(void)
+{
+       int i;
+       int errs = 0;
+
+       for (i = 0; i < list.nr; i++) {
+               const char *name = list.entry[i].name;
+               int pos;
+               struct cache_entry *ce;
+               struct stat st;
+
+               pos = cache_name_pos(name, strlen(name));
+               if (pos < 0) {
+                       pos = get_ours_cache_pos(name, pos);
+                       if (pos < 0)
+                               continue;
+               }
+               ce = active_cache[pos];
+
+               if (!S_ISGITLINK(ce->ce_mode) ||
+                   (lstat(ce->name, &st) < 0) ||
+                   is_empty_dir(name))
+                       continue;
+
+               if (!submodule_uses_gitfile(name))
+                       errs = error(_("submodule '%s' (or one of its nested "
+                                    "submodules) uses a .git directory\n"
+                                    "(use 'rm -rf' if you really want to remove "
+                                    "it including all of its history)"), name);
+       }
+
+       return errs;
+}
+
 static int check_local_mod(unsigned char *head, int index_only)
 {
        /*
@@ -37,15 +87,26 @@ static int check_local_mod(unsigned char *head, int index_only)
                struct stat st;
                int pos;
                struct cache_entry *ce;
-               const char *name = list.name[i];
+               const char *name = list.entry[i].name;
                unsigned char sha1[20];
                unsigned mode;
                int local_changes = 0;
                int staged_changes = 0;
 
                pos = cache_name_pos(name, strlen(name));
-               if (pos < 0)
-                       continue; /* removing unmerged entry */
+               if (pos < 0) {
+                       /*
+                        * Skip unmerged entries except for populated submodules
+                        * that could lose history when removed.
+                        */
+                       pos = get_ours_cache_pos(name, pos);
+                       if (pos < 0)
+                               continue;
+
+                       if (!S_ISGITLINK(active_cache[pos]->ce_mode) ||
+                           is_empty_dir(name))
+                               continue;
+               }
                ce = active_cache[pos];
 
                if (lstat(ce->name, &st) < 0) {
@@ -58,9 +119,10 @@ static int check_local_mod(unsigned char *head, int index_only)
                        /* if a file was removed and it is now a
                         * directory, that is the same as ENOENT as
                         * far as git is concerned; we do not track
-                        * directories.
+                        * directories unless they are submodules.
                         */
-                       continue;
+                       if (!S_ISGITLINK(ce->ce_mode))
+                               continue;
                }
 
                /*
@@ -80,8 +142,11 @@ static int check_local_mod(unsigned char *head, int index_only)
 
                /*
                 * Is the index different from the file in the work tree?
+                * If it's a submodule, is its work tree modified?
                 */
-               if (ce_match_stat(ce, &st, 0))
+               if (ce_match_stat(ce, &st, 0) ||
+                   (S_ISGITLINK(ce->ce_mode) &&
+                    !ok_to_remove_submodule(ce->name)))
                        local_changes = 1;
 
                /*
@@ -115,10 +180,18 @@ static int check_local_mod(unsigned char *head, int index_only)
                                errs = error(_("'%s' has changes staged in the index\n"
                                             "(use --cached to keep the file, "
                                             "or -f to force removal)"), name);
-                       if (local_changes)
-                               errs = error(_("'%s' has local modifications\n"
-                                            "(use --cached to keep the file, "
-                                            "or -f to force removal)"), name);
+                       if (local_changes) {
+                               if (S_ISGITLINK(ce->ce_mode) &&
+                                   !submodule_uses_gitfile(name)) {
+                                       errs = error(_("submodule '%s' (or one of its nested "
+                                                    "submodules) uses a .git directory\n"
+                                                    "(use 'rm -rf' if you really want to remove "
+                                                    "it including all of its history)"), name);
+                               } else
+                                       errs = error(_("'%s' has local modifications\n"
+                                                    "(use --cached to keep the file, "
+                                                    "or -f to force removal)"), name);
+                       }
                }
        }
        return errs;
@@ -161,6 +234,21 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
        if (read_cache() < 0)
                die(_("index file corrupt"));
 
+       /*
+        * Drop trailing directory separators from directories so we'll find
+        * submodules in the index.
+        */
+       for (i = 0; i < argc; i++) {
+               size_t pathlen = strlen(argv[i]);
+               if (pathlen && is_dir_sep(argv[i][pathlen - 1]) &&
+                   is_directory(argv[i])) {
+                       do {
+                               pathlen--;
+                       } while (pathlen && is_dir_sep(argv[i][pathlen - 1]));
+                       argv[i] = xmemdupz(argv[i], pathlen);
+               }
+       }
+
        pathspec = get_pathspec(prefix, argv);
        refresh_index(&the_index, REFRESH_QUIET, pathspec, NULL, NULL);
 
@@ -173,8 +261,9 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
                struct cache_entry *ce = active_cache[i];
                if (!match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, seen))
                        continue;
-               ALLOC_GROW(list.name, list.nr + 1, list.alloc);
-               list.name[list.nr++] = ce->name;
+               ALLOC_GROW(list.entry, list.nr + 1, list.alloc);
+               list.entry[list.nr].name = ce->name;
+               list.entry[list.nr++].is_submodule = S_ISGITLINK(ce->ce_mode);
        }
 
        if (pathspec) {
@@ -215,6 +304,9 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
                        hashclr(sha1);
                if (check_local_mod(sha1, index_only))
                        exit(1);
+       } else if (!index_only) {
+               if (check_submodules_use_gitfiles())
+                       exit(1);
        }
 
        /*
@@ -222,7 +314,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
         * the index unless all of them succeed.
         */
        for (i = 0; i < list.nr; i++) {
-               const char *path = list.name[i];
+               const char *path = list.entry[i].name;
                if (!quiet)
                        printf("rm '%s'\n", path);
 
@@ -244,7 +336,25 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
        if (!index_only) {
                int removed = 0;
                for (i = 0; i < list.nr; i++) {
-                       const char *path = list.name[i];
+                       const char *path = list.entry[i].name;
+                       if (list.entry[i].is_submodule) {
+                               if (is_empty_dir(path)) {
+                                       if (!rmdir(path)) {
+                                               removed = 1;
+                                               continue;
+                                       }
+                               } else {
+                                       struct strbuf buf = STRBUF_INIT;
+                                       strbuf_addstr(&buf, path);
+                                       if (!remove_dir_recursively(&buf, 0)) {
+                                               removed = 1;
+                                               strbuf_release(&buf);
+                                               continue;
+                                       }
+                                       strbuf_release(&buf);
+                                       /* Fallthrough and let remove_path() fail. */
+                               }
+                       }
                        if (!remove_path(path)) {
                                removed = 1;
                                continue;
index 7d05064..f849e0a 100644 (file)
@@ -16,164 +16,6 @@ static const char send_pack_usage[] =
 
 static struct send_pack_args args;
 
-static int feed_object(const unsigned char *sha1, int fd, int negative)
-{
-       char buf[42];
-
-       if (negative && !has_sha1_file(sha1))
-               return 1;
-
-       memcpy(buf + negative, sha1_to_hex(sha1), 40);
-       if (negative)
-               buf[0] = '^';
-       buf[40 + negative] = '\n';
-       return write_or_whine(fd, buf, 41 + negative, "send-pack: send refs");
-}
-
-/*
- * Make a pack stream and spit it out into file descriptor fd
- */
-static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *extra, struct send_pack_args *args)
-{
-       /*
-        * The child becomes pack-objects --revs; we feed
-        * the revision parameters to it via its stdin and
-        * let its stdout go back to the other end.
-        */
-       const char *argv[] = {
-               "pack-objects",
-               "--all-progress-implied",
-               "--revs",
-               "--stdout",
-               NULL,
-               NULL,
-               NULL,
-               NULL,
-               NULL,
-       };
-       struct child_process po;
-       int i;
-
-       i = 4;
-       if (args->use_thin_pack)
-               argv[i++] = "--thin";
-       if (args->use_ofs_delta)
-               argv[i++] = "--delta-base-offset";
-       if (args->quiet || !args->progress)
-               argv[i++] = "-q";
-       if (args->progress)
-               argv[i++] = "--progress";
-       memset(&po, 0, sizeof(po));
-       po.argv = argv;
-       po.in = -1;
-       po.out = args->stateless_rpc ? -1 : fd;
-       po.git_cmd = 1;
-       if (start_command(&po))
-               die_errno("git pack-objects failed");
-
-       /*
-        * We feed the pack-objects we just spawned with revision
-        * parameters by writing to the pipe.
-        */
-       for (i = 0; i < extra->nr; i++)
-               if (!feed_object(extra->array[i], po.in, 1))
-                       break;
-
-       while (refs) {
-               if (!is_null_sha1(refs->old_sha1) &&
-                   !feed_object(refs->old_sha1, po.in, 1))
-                       break;
-               if (!is_null_sha1(refs->new_sha1) &&
-                   !feed_object(refs->new_sha1, po.in, 0))
-                       break;
-               refs = refs->next;
-       }
-
-       close(po.in);
-
-       if (args->stateless_rpc) {
-               char *buf = xmalloc(LARGE_PACKET_MAX);
-               while (1) {
-                       ssize_t n = xread(po.out, buf, LARGE_PACKET_MAX);
-                       if (n <= 0)
-                               break;
-                       send_sideband(fd, -1, buf, n, LARGE_PACKET_MAX);
-               }
-               free(buf);
-               close(po.out);
-               po.out = -1;
-       }
-
-       if (finish_command(&po))
-               return -1;
-       return 0;
-}
-
-static int receive_status(int in, struct ref *refs)
-{
-       struct ref *hint;
-       char line[1000];
-       int ret = 0;
-       int len = packet_read_line(in, line, sizeof(line));
-       if (len < 10 || memcmp(line, "unpack ", 7))
-               return error("did not receive remote status");
-       if (memcmp(line, "unpack ok\n", 10)) {
-               char *p = line + strlen(line) - 1;
-               if (*p == '\n')
-                       *p = '\0';
-               error("unpack failed: %s", line + 7);
-               ret = -1;
-       }
-       hint = NULL;
-       while (1) {
-               char *refname;
-               char *msg;
-               len = packet_read_line(in, line, sizeof(line));
-               if (!len)
-                       break;
-               if (len < 3 ||
-                   (memcmp(line, "ok ", 3) && memcmp(line, "ng ", 3))) {
-                       fprintf(stderr, "protocol error: %s\n", line);
-                       ret = -1;
-                       break;
-               }
-
-               line[strlen(line)-1] = '\0';
-               refname = line + 3;
-               msg = strchr(refname, ' ');
-               if (msg)
-                       *msg++ = '\0';
-
-               /* first try searching at our hint, falling back to all refs */
-               if (hint)
-                       hint = find_ref_by_name(hint, refname);
-               if (!hint)
-                       hint = find_ref_by_name(refs, refname);
-               if (!hint) {
-                       warning("remote reported status on unknown ref: %s",
-                                       refname);
-                       continue;
-               }
-               if (hint->status != REF_STATUS_EXPECTING_REPORT) {
-                       warning("remote reported status on unexpected ref: %s",
-                                       refname);
-                       continue;
-               }
-
-               if (line[0] == 'o' && line[1] == 'k')
-                       hint->status = REF_STATUS_OK;
-               else {
-                       hint->status = REF_STATUS_REMOTE_REJECT;
-                       ret = -1;
-               }
-               if (msg)
-                       hint->remote_status = xstrdup(msg);
-               /* start our next search from the next ref */
-               hint = hint->next;
-       }
-       return ret;
-}
-
 static void print_helper_status(struct ref *ref)
 {
        struct strbuf buf = STRBUF_INIT;
@@ -202,6 +44,11 @@ static void print_helper_status(struct ref *ref)
                        msg = "non-fast forward";
                        break;
 
+               case REF_STATUS_REJECT_ALREADY_EXISTS:
+                       res = "error";
+                       msg = "already exists";
+                       break;
+
                case REF_STATUS_REJECT_NODELETE:
                case REF_STATUS_REMOTE_REJECT:
                        res = "error";
@@ -227,181 +74,6 @@ static void print_helper_status(struct ref *ref)
        strbuf_release(&buf);
 }
 
-static int sideband_demux(int in, int out, void *data)
-{
-       int *fd = data, ret;
-#ifdef NO_PTHREADS
-       close(fd[1]);
-#endif
-       ret = recv_sideband("send-pack", fd[0], out);
-       close(out);
-       return ret;
-}
-
-int send_pack(struct send_pack_args *args,
-             int fd[], struct child_process *conn,
-             struct ref *remote_refs,
-             struct extra_have_objects *extra_have)
-{
-       int in = fd[0];
-       int out = fd[1];
-       struct strbuf req_buf = STRBUF_INIT;
-       struct ref *ref;
-       int new_refs;
-       int allow_deleting_refs = 0;
-       int status_report = 0;
-       int use_sideband = 0;
-       int quiet_supported = 0;
-       int agent_supported = 0;
-       unsigned cmds_sent = 0;
-       int ret;
-       struct async demux;
-
-       /* Does the other end support the reporting? */
-       if (server_supports("report-status"))
-               status_report = 1;
-       if (server_supports("delete-refs"))
-               allow_deleting_refs = 1;
-       if (server_supports("ofs-delta"))
-               args->use_ofs_delta = 1;
-       if (server_supports("side-band-64k"))
-               use_sideband = 1;
-       if (server_supports("quiet"))
-               quiet_supported = 1;
-       if (server_supports("agent"))
-               agent_supported = 1;
-
-       if (!remote_refs) {
-               fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
-                       "Perhaps you should specify a branch such as 'master'.\n");
-               return 0;
-       }
-
-       /*
-        * Finally, tell the other end!
-        */
-       new_refs = 0;
-       for (ref = remote_refs; ref; ref = ref->next) {
-               if (!ref->peer_ref && !args->send_mirror)
-                       continue;
-
-               /* Check for statuses set by set_ref_status_for_push() */
-               switch (ref->status) {
-               case REF_STATUS_REJECT_NONFASTFORWARD:
-               case REF_STATUS_UPTODATE:
-                       continue;
-               default:
-                       ; /* do nothing */
-               }
-
-               if (ref->deletion && !allow_deleting_refs) {
-                       ref->status = REF_STATUS_REJECT_NODELETE;
-                       continue;
-               }
-
-               if (!ref->deletion)
-                       new_refs++;
-
-               if (args->dry_run) {
-                       ref->status = REF_STATUS_OK;
-               } else {
-                       char *old_hex = sha1_to_hex(ref->old_sha1);
-                       char *new_hex = sha1_to_hex(ref->new_sha1);
-                       int quiet = quiet_supported && (args->quiet || !args->progress);
-
-                       if (!cmds_sent && (status_report || use_sideband ||
-                                          quiet || agent_supported)) {
-                               packet_buf_write(&req_buf,
-                                                "%s %s %s%c%s%s%s%s%s",
-                                                old_hex, new_hex, ref->name, 0,
-                                                status_report ? " report-status" : "",
-                                                use_sideband ? " side-band-64k" : "",
-                                                quiet ? " quiet" : "",
-                                                agent_supported ? " agent=" : "",
-                                                agent_supported ? git_user_agent_sanitized() : ""
-                                               );
-                       }
-                       else
-                               packet_buf_write(&req_buf, "%s %s %s",
-                                                old_hex, new_hex, ref->name);
-                       ref->status = status_report ?
-                               REF_STATUS_EXPECTING_REPORT :
-                               REF_STATUS_OK;
-                       cmds_sent++;
-               }
-       }
-
-       if (args->stateless_rpc) {
-               if (!args->dry_run && cmds_sent) {
-                       packet_buf_flush(&req_buf);
-                       send_sideband(out, -1, req_buf.buf, req_buf.len, LARGE_PACKET_MAX);
-               }
-       } else {
-               safe_write(out, req_buf.buf, req_buf.len);
-               packet_flush(out);
-       }
-       strbuf_release(&req_buf);
-
-       if (use_sideband && cmds_sent) {
-               memset(&demux, 0, sizeof(demux));
-               demux.proc = sideband_demux;
-               demux.data = fd;
-               demux.out = -1;
-               if (start_async(&demux))
-                       die("send-pack: unable to fork off sideband demultiplexer");
-               in = demux.out;
-       }
-
-       if (new_refs && cmds_sent) {
-               if (pack_objects(out, remote_refs, extra_have, args) < 0) {
-                       for (ref = remote_refs; ref; ref = ref->next)
-                               ref->status = REF_STATUS_NONE;
-                       if (args->stateless_rpc)
-                               close(out);
-                       if (git_connection_is_socket(conn))
-                               shutdown(fd[0], SHUT_WR);
-                       if (use_sideband)
-                               finish_async(&demux);
-                       return -1;
-               }
-       }
-       if (args->stateless_rpc && cmds_sent)
-               packet_flush(out);
-
-       if (status_report && cmds_sent)
-               ret = receive_status(in, remote_refs);
-       else
-               ret = 0;
-       if (args->stateless_rpc)
-               packet_flush(out);
-
-       if (use_sideband && cmds_sent) {
-               if (finish_async(&demux)) {
-                       error("error in sideband demultiplexer");
-                       ret = -1;
-               }
-               close(demux.out);
-       }
-
-       if (ret < 0)
-               return ret;
-
-       if (args->porcelain)
-               return 0;
-
-       for (ref = remote_refs; ref; ref = ref->next) {
-               switch (ref->status) {
-               case REF_STATUS_NONE:
-               case REF_STATUS_UPTODATE:
-               case REF_STATUS_OK:
-                       break;
-               default:
-                       return -1;
-               }
-       }
-       return 0;
-}
-
 int cmd_send_pack(int argc, const char **argv, const char *prefix)
 {
        int i, nr_refspecs = 0;
@@ -418,7 +90,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
        int send_all = 0;
        const char *receivepack = "git-receive-pack";
        int flags;
-       int nonfastforward = 0;
+       unsigned int reject_reasons;
        int progress = -1;
 
        argv++;
@@ -556,7 +228,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
        ret |= finish_connect(conn);
 
        if (!helper_status)
-               transport_print_push_status(dest, remote_refs, args.verbose, 0, &nonfastforward);
+               transport_print_push_status(dest, remote_refs, args.verbose, 0, &reject_reasons);
 
        if (!args.dry_run && remote) {
                struct ref *ref;
index b316cf3..8360514 100644 (file)
@@ -306,9 +306,8 @@ parse_done:
 static void add_wrapped_shortlog_msg(struct strbuf *sb, const char *s,
                                     const struct shortlog *log)
 {
-       int col = strbuf_add_wrapped_text(sb, s, log->in1, log->in2, log->wrap);
-       if (col != log->wrap)
-               strbuf_addch(sb, '\n');
+       strbuf_add_wrapped_text(sb, s, log->in1, log->in2, log->wrap);
+       strbuf_addch(sb, '\n');
 }
 
 void shortlog_output(struct shortlog *log)
index 4eb016d..8d9b76a 100644 (file)
@@ -28,7 +28,6 @@ static void show_one(const char *refname, const unsigned char *sha1)
 
 static int show_ref(const char *refname, const unsigned char *sha1, int flag, void *cbdata)
 {
-       struct object *obj;
        const char *hex;
        unsigned char peeled[20];
 
@@ -79,25 +78,9 @@ match:
        if (!deref_tags)
                return 0;
 
-       if ((flag & REF_ISPACKED) && !peel_ref(refname, peeled)) {
-               if (!is_null_sha1(peeled)) {
-                       hex = find_unique_abbrev(peeled, abbrev);
-                       printf("%s %s^{}\n", hex, refname);
-               }
-       }
-       else {
-               obj = parse_object(sha1);
-               if (!obj)
-                       die("git show-ref: bad ref %s (%s)", refname,
-                           sha1_to_hex(sha1));
-               if (obj->type == OBJ_TAG) {
-                       obj = deref_tag(obj, refname, 0);
-                       if (!obj)
-                               die("git show-ref: bad tag at ref %s (%s)", refname,
-                                   sha1_to_hex(sha1));
-                       hex = find_unique_abbrev(obj->sha1, abbrev);
-                       printf("%s %s^{}\n", hex, refname);
-               }
+       if (!peel_ref(refname, peeled)) {
+               hex = find_unique_abbrev(peeled, abbrev);
+               printf("%s %s^{}\n", hex, refname);
        }
        return 0;
 }
index 9e92828..f481959 100644 (file)
@@ -5,12 +5,11 @@
 
 static const char * const git_symbolic_ref_usage[] = {
        N_("git symbolic-ref [options] name [ref]"),
+       N_("git symbolic-ref -d [-q] name"),
        NULL
 };
 
-static int shorten;
-
-static void check_symref(const char *HEAD, int quiet)
+static int check_symref(const char *HEAD, int quiet, int shorten, int print)
 {
        unsigned char sha1[20];
        int flag;
@@ -22,20 +21,24 @@ static void check_symref(const char *HEAD, int quiet)
                if (!quiet)
                        die("ref %s is not a symbolic ref", HEAD);
                else
-                       exit(1);
+                       return 1;
+       }
+       if (print) {
+               if (shorten)
+                       refname = shorten_unambiguous_ref(refname, 0);
+               puts(refname);
        }
-       if (shorten)
-               refname = shorten_unambiguous_ref(refname, 0);
-       puts(refname);
+       return 0;
 }
 
 int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
 {
-       int quiet = 0;
+       int quiet = 0, delete = 0, shorten = 0, ret = 0;
        const char *msg = NULL;
        struct option options[] = {
                OPT__QUIET(&quiet,
                        N_("suppress error message for non-symbolic (detached) refs")),
+               OPT_BOOL('d', "delete", &delete, N_("delete symbolic ref")),
                OPT_BOOL(0, "short", &shorten, N_("shorten ref output")),
                OPT_STRING('m', NULL, &msg, N_("reason"), N_("reason of the update")),
                OPT_END(),
@@ -46,9 +49,19 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
                             git_symbolic_ref_usage, 0);
        if (msg &&!*msg)
                die("Refusing to perform update with empty message");
+
+       if (delete) {
+               if (argc != 1)
+                       usage_with_options(git_symbolic_ref_usage, options);
+               ret = check_symref(argv[0], 1, 0, 0);
+               if (ret)
+                       die("Cannot delete %s, not a symbolic ref", argv[0]);
+               return delete_ref(argv[0], NULL, REF_NODEREF);
+       }
+
        switch (argc) {
        case 1:
-               check_symref(argv[0], quiet);
+               ret = check_symref(argv[0], quiet, shorten, 1);
                break;
        case 2:
                if (!strcmp(argv[0], "HEAD") &&
@@ -59,5 +72,5 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
        default:
                usage_with_options(git_symbolic_ref_usage, options);
        }
-       return 0;
+       return ret;
 }
index 74986bf..ada1dff 100644 (file)
@@ -593,6 +593,7 @@ struct refresh_params {
 static int refresh(struct refresh_params *o, unsigned int flag)
 {
        setup_work_tree();
+       read_cache_preload(NULL);
        *o->has_errors |= refresh_cache(o->flags | flag);
        return 0;
 }
index 28ed657..37e4d00 100644 (file)
@@ -166,12 +166,8 @@ static int verify_cache(struct cache_entry **cache,
                                fprintf(stderr, "...\n");
                                break;
                        }
-                       if (ce_stage(ce))
-                               fprintf(stderr, "%s: unmerged (%s)\n",
-                                       ce->name, sha1_to_hex(ce->sha1));
-                       else
-                               fprintf(stderr, "%s: not added yet\n",
-                                       ce->name);
+                       fprintf(stderr, "%s: unmerged (%s)\n",
+                               ce->name, sha1_to_hex(ce->sha1));
                }
        }
        if (funny)
@@ -242,13 +238,17 @@ static int update_one(struct cache_tree *it,
                      int entries,
                      const char *base,
                      int baselen,
+                     int *skip_count,
                      int flags)
 {
        struct strbuf buffer;
        int missing_ok = flags & WRITE_TREE_MISSING_OK;
        int dryrun = flags & WRITE_TREE_DRY_RUN;
+       int to_invalidate = 0;
        int i;
 
+       *skip_count = 0;
+
        if (0 <= it->entry_count && has_sha1_file(it->sha1))
                return it->entry_count;
 
@@ -263,11 +263,12 @@ static int update_one(struct cache_tree *it,
        /*
         * Find the subtrees and update them.
         */
-       for (i = 0; i < entries; i++) {
+       i = 0;
+       while (i < entries) {
                struct cache_entry *ce = cache[i];
                struct cache_tree_sub *sub;
                const char *path, *slash;
-               int pathlen, sublen, subcnt;
+               int pathlen, sublen, subcnt, subskip;
 
                path = ce->name;
                pathlen = ce_namelen(ce);
@@ -275,8 +276,10 @@ static int update_one(struct cache_tree *it,
                        break; /* at the end of this level */
 
                slash = strchr(path + baselen, '/');
-               if (!slash)
+               if (!slash) {
+                       i++;
                        continue;
+               }
                /*
                 * a/bbb/c (base = a/, slash = /c)
                 * ==>
@@ -290,10 +293,13 @@ static int update_one(struct cache_tree *it,
                                    cache + i, entries - i,
                                    path,
                                    baselen + sublen + 1,
+                                   &subskip,
                                    flags);
                if (subcnt < 0)
                        return subcnt;
-               i += subcnt - 1;
+               i += subcnt;
+               sub->count = subcnt; /* to be used in the next loop */
+               *skip_count += subskip;
                sub->used = 1;
        }
 
@@ -304,7 +310,8 @@ static int update_one(struct cache_tree *it,
         */
        strbuf_init(&buffer, 8192);
 
-       for (i = 0; i < entries; i++) {
+       i = 0;
+       while (i < entries) {
                struct cache_entry *ce = cache[i];
                struct cache_tree_sub *sub;
                const char *path, *slash;
@@ -324,14 +331,17 @@ static int update_one(struct cache_tree *it,
                        if (!sub)
                                die("cache-tree.c: '%.*s' in '%s' not found",
                                    entlen, path + baselen, path);
-                       i += sub->cache_tree->entry_count - 1;
+                       i += sub->count;
                        sha1 = sub->cache_tree->sha1;
                        mode = S_IFDIR;
+                       if (sub->cache_tree->entry_count < 0)
+                               to_invalidate = 1;
                }
                else {
                        sha1 = ce->sha1;
                        mode = ce->ce_mode;
                        entlen = pathlen - baselen;
+                       i++;
                }
                if (mode != S_IFGITLINK && !missing_ok && !has_sha1_file(sha1)) {
                        strbuf_release(&buffer);
@@ -339,8 +349,25 @@ static int update_one(struct cache_tree *it,
                                mode, sha1_to_hex(sha1), entlen+baselen, path);
                }
 
-               if (ce->ce_flags & (CE_REMOVE | CE_INTENT_TO_ADD))
-                       continue; /* entry being removed or placeholder */
+               /*
+                * CE_REMOVE entries are removed before the index is
+                * written to disk. Skip them to remain consistent
+                * with the future on-disk index.
+                */
+               if (ce->ce_flags & CE_REMOVE) {
+                       *skip_count = *skip_count + 1;
+                       continue;
+               }
+
+               /*
+                * CE_INTENT_TO_ADD entries exist on on-disk index but
+                * they are not part of generated trees. Invalidate up
+                * to root to force cache-tree users to read elsewhere.
+                */
+               if (ce->ce_flags & CE_INTENT_TO_ADD) {
+                       to_invalidate = 1;
+                       continue;
+               }
 
                strbuf_grow(&buffer, entlen + 100);
                strbuf_addf(&buffer, "%o %.*s%c", mode, entlen, path + baselen, '\0');
@@ -360,7 +387,7 @@ static int update_one(struct cache_tree *it,
        }
 
        strbuf_release(&buffer);
-       it->entry_count = i;
+       it->entry_count = to_invalidate ? -1 : i - *skip_count;
 #if DEBUG
        fprintf(stderr, "cache-tree update-one (%d ent, %d subtree) %s\n",
                it->entry_count, it->subtree_nr,
@@ -374,11 +401,11 @@ int cache_tree_update(struct cache_tree *it,
                      int entries,
                      int flags)
 {
-       int i;
+       int i, skip;
        i = verify_cache(cache, entries, flags);
        if (i)
                return i;
-       i = update_one(it, cache, entries, "", 0, flags);
+       i = update_one(it, cache, entries, "", 0, &skip, flags);
        if (i < 0)
                return i;
        return 0;
index d8cb2e9..55d0f59 100644 (file)
@@ -7,6 +7,7 @@
 struct cache_tree;
 struct cache_tree_sub {
        struct cache_tree *cache_tree;
+       int count;              /* internally used by update_one() */
        int namelen;
        int used;
        char name[FLEX_ARRAY];
diff --git a/cache.h b/cache.h
index a58df84..c257953 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -362,6 +362,7 @@ static inline enum object_type object_type(unsigned int mode)
 #define GIT_NOTES_DISPLAY_REF_ENVIRONMENT "GIT_NOTES_DISPLAY_REF"
 #define GIT_NOTES_REWRITE_REF_ENVIRONMENT "GIT_NOTES_REWRITE_REF"
 #define GIT_NOTES_REWRITE_MODE_ENVIRONMENT "GIT_NOTES_REWRITE_MODE"
+#define GIT_LITERAL_PATHSPECS_ENVIRONMENT "GIT_LITERAL_PATHSPECS"
 
 /*
  * Repository-local GIT_* environment variables
@@ -473,6 +474,8 @@ extern int index_name_is_other(const struct index_state *, const char *, int);
 extern int ie_match_stat(const struct index_state *, struct cache_entry *, struct stat *, unsigned int);
 extern int ie_modified(const struct index_state *, struct cache_entry *, struct stat *, unsigned int);
 
+#define PATHSPEC_ONESTAR 1     /* the pathspec pattern sastisfies GFNM_ONESTAR */
+
 struct pathspec {
        const char **raw; /* get_pathspec() result, not freed by free_pathspec() */
        int nr;
@@ -482,7 +485,8 @@ struct pathspec {
        struct pathspec_item {
                const char *match;
                int len;
-               unsigned int use_wildcard:1;
+               int nowildcard_len;
+               int flags;
        } *items;
 };
 
@@ -490,6 +494,8 @@ extern int init_pathspec(struct pathspec *, const char **);
 extern void free_pathspec(struct pathspec *);
 extern int ce_path_match(const struct cache_entry *ce, const struct pathspec *pathspec);
 
+extern int limit_pathspec_to_literal(void);
+
 #define HASH_WRITE_OBJECT 1
 #define HASH_FORMAT_CHECK 2
 extern int index_fd(unsigned char *sha1, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags);
@@ -714,10 +720,11 @@ static inline int is_absolute_path(const char *path)
 }
 int is_directory(const char *);
 const char *real_path(const char *path);
+const char *real_path_if_valid(const char *path);
 const char *absolute_path(const char *path);
 const char *relative_path(const char *abs, const char *base);
 int normalize_path_copy(char *dst, const char *src);
-int longest_ancestor_length(const char *path, const char *prefix_list);
+int longest_ancestor_length(const char *path, struct string_list *prefixes);
 char *strip_path_suffix(const char *path, const char *suffix);
 int daemon_avoid_alias(const char *path);
 int offset_1st_component(const char *path);
@@ -999,14 +1006,19 @@ struct ref {
        unsigned char old_sha1[20];
        unsigned char new_sha1[20];
        char *symref;
-       unsigned int force:1,
+       unsigned int
+               force:1,
+               requires_force:1,
                merge:1,
                nonfastforward:1,
+               not_forwardable:1,
+               update:1,
                deletion:1;
        enum {
                REF_STATUS_NONE = 0,
                REF_STATUS_OK,
                REF_STATUS_REJECT_NONFASTFORWARD,
+               REF_STATUS_REJECT_ALREADY_EXISTS,
                REF_STATUS_REJECT_NODELETE,
                REF_STATUS_UPTODATE,
                REF_STATUS_REMOTE_REJECT,
@@ -1136,6 +1148,9 @@ extern int check_repository_format_version(const char *var, const char *value, v
 extern int git_env_bool(const char *, int);
 extern int git_config_system(void);
 extern int config_error_nonbool(const char *);
+#ifdef __GNUC__
+#define config_error_nonbool(s) (config_error_nonbool(s), -1)
+#endif
 extern const char *get_log_output_encoding(void);
 extern const char *get_commit_output_encoding(void);
 
@@ -1149,15 +1164,13 @@ struct config_include_data {
 #define CONFIG_INCLUDE_INIT { 0 }
 extern int git_config_include(const char *name, const char *value, void *data);
 
-#define IDENT_NAME_GIVEN 01
-#define IDENT_MAIL_GIVEN 02
-#define IDENT_ALL_GIVEN (IDENT_NAME_GIVEN|IDENT_MAIL_GIVEN)
-extern int user_ident_explicitly_given;
-extern int user_ident_sufficiently_given(void);
+extern int committer_ident_sufficiently_given(void);
+extern int author_ident_sufficiently_given(void);
 
 extern const char *git_commit_encoding;
 extern const char *git_log_output_encoding;
 extern const char *git_mailmap_file;
+extern const char *git_mailmap_blob;
 
 /* IO helper functions */
 extern void maybe_flush_or_die(FILE *, const char *);
@@ -1183,6 +1196,7 @@ extern int pager_in_use(void);
 extern int pager_use_color;
 extern int term_columns(void);
 extern int decimal_width(int);
+extern int check_pager_config(const char *cmd);
 
 extern const char *editor_program;
 extern const char *askpass_program;
@@ -1265,8 +1279,15 @@ struct startup_info {
 };
 extern struct startup_info *startup_info;
 
-/* builtin/merge.c */
-int checkout_fast_forward(const unsigned char *from, const unsigned char *to);
+/* merge.c */
+struct commit_list;
+int try_merge_command(const char *strategy, size_t xopts_nr,
+               const char **xopts, struct commit_list *common,
+               const char *head_arg, struct commit_list *remotes);
+int checkout_fast_forward(const unsigned char *from,
+                         const unsigned char *to,
+                         int overwrite_ignore);
+
 
 int sane_execvp(const char *file, char *const argv[]);
 
index 213bc98..e8eb0ae 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -1347,3 +1347,13 @@ struct commit_list **commit_list_append(struct commit *commit,
        new->next = NULL;
        return &new->next;
 }
+
+void print_commit_list(struct commit_list *list,
+                      const char *format_cur,
+                      const char *format_last)
+{
+       for ( ; list; list = list->next) {
+               const char *format = list->next ? format_cur : format_last;
+               printf(format, sha1_to_hex(list->item->object.sha1));
+       }
+}
index 9f21313..0f469e5 100644 (file)
--- a/commit.h
+++ b/commit.h
@@ -86,9 +86,10 @@ struct pretty_print_context {
        enum date_mode date_mode;
        unsigned date_mode_explicit:1;
        int need_8bit_cte;
-       int show_notes;
+       char *notes_message;
        struct reflog_walk_info *reflog_info;
        const char *output_encoding;
+       int color;
 };
 
 struct userformat_want {
@@ -99,8 +100,6 @@ extern int has_non_ascii(const char *text);
 struct rev_info; /* in revision.h, it circularly uses enum cmit_fmt */
 extern char *logmsg_reencode(const struct commit *commit,
                             const char *output_encoding);
-extern char *reencode_commit_message(const struct commit *commit,
-                                    const char **encoding_p);
 extern void get_commit_format(const char *arg, struct rev_info *);
 extern const char *format_subject(struct strbuf *sb, const char *msg,
                                  const char *line_separator);
@@ -222,4 +221,8 @@ struct commit *get_merge_parent(const char *name);
 
 extern int parse_signed_commit(const unsigned char *sha1,
                               struct strbuf *message, struct strbuf *signature);
+extern void print_commit_list(struct commit_list *list,
+                             const char *format_cur,
+                             const char *format_last);
+
 #endif /* COMMIT_H */
index dfe9b30..5428858 100644 (file)
@@ -1,6 +1,13 @@
 #define WIN32_LEAN_AND_MEAN
+#ifdef CYGWIN_V15_WIN32API
 #include "../git-compat-util.h"
 #include "win32.h"
+#else
+#include <sys/stat.h>
+#include <sys/errno.h>
+#include "win32.h"
+#include "../git-compat-util.h"
+#endif
 #include "../cache.h" /* to read configuration */
 
 static inline void filetime_to_timespec(const FILETIME *ft, struct timespec *ts)
index 0ff1d27..b8b7dc2 100644 (file)
@@ -135,9 +135,9 @@ extern int errno;
 
 # if !defined HAVE___STRCHRNUL && !defined _LIBC
 static char *
-__strchrnul (s, c)
-     const char *s;
-     int c;
+__strchrnul (const char *s, int c)
+
+
 {
   char *result = strchr (s, c);
   if (result == NULL)
@@ -159,11 +159,11 @@ static int internal_fnmatch __P ((const char *pattern, const char *string,
      internal_function;
 static int
 internal_function
-internal_fnmatch (pattern, string, no_leading_period, flags)
-     const char *pattern;
-     const char *string;
-     int no_leading_period;
-     int flags;
+internal_fnmatch (const char *pattern, const char *string, int no_leading_period, int flags)
+
+
+
+
 {
   register const char *p = pattern, *n = string;
   register unsigned char c;
@@ -481,10 +481,10 @@ internal_fnmatch (pattern, string, no_leading_period, flags)
 
 
 int
-fnmatch (pattern, string, flags)
-     const char *pattern;
-     const char *string;
-     int flags;
+fnmatch (const char *pattern, const char *string, int flags)
+
+
+
 {
   return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags);
 }
index afc892d..b673625 100644 (file)
@@ -256,6 +256,8 @@ int mingw_rmdir(const char *pathname)
 
        while ((ret = rmdir(pathname)) == -1 && tries < ARRAY_SIZE(delay)) {
                if (!is_file_in_use_error(GetLastError()))
+                       errno = err_win_to_posix(GetLastError());
+               if (errno != EACCES)
                        break;
                if (!is_dir_empty(pathname)) {
                        errno = ENOTEMPTY;
@@ -271,7 +273,7 @@ int mingw_rmdir(const char *pathname)
                Sleep(delay[tries]);
                tries++;
        }
-       while (ret == -1 && is_file_in_use_error(GetLastError()) &&
+       while (ret == -1 && errno == EACCES && is_file_in_use_error(GetLastError()) &&
               ask_yes_no_if_possible("Deletion of directory '%s' failed. "
                        "Should I try again?", pathname))
               ret = rmdir(pathname);
@@ -319,6 +321,31 @@ ssize_t mingw_write(int fd, const void *buf, size_t count)
        return write(fd, buf, min(count, 31 * 1024 * 1024));
 }
 
+static BOOL WINAPI ctrl_ignore(DWORD type)
+{
+       return TRUE;
+}
+
+#undef fgetc
+int mingw_fgetc(FILE *stream)
+{
+       int ch;
+       if (!isatty(_fileno(stream)))
+               return fgetc(stream);
+
+       SetConsoleCtrlHandler(ctrl_ignore, TRUE);
+       while (1) {
+               ch = fgetc(stream);
+               if (ch != EOF || GetLastError() != ERROR_OPERATION_ABORTED)
+                       break;
+
+               /* Ctrl+C was pressed, simulate SIGINT and retry */
+               mingw_raise(SIGINT);
+       }
+       SetConsoleCtrlHandler(ctrl_ignore, FALSE);
+       return ch;
+}
+
 #undef fopen
 FILE *mingw_fopen (const char *filename, const char *otype)
 {
@@ -335,6 +362,28 @@ FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream)
        return freopen(filename, otype, stream);
 }
 
+#undef fflush
+int mingw_fflush(FILE *stream)
+{
+       int ret = fflush(stream);
+
+       /*
+        * write() is used behind the scenes of stdio output functions.
+        * Since git code does not check for errors after each stdio write
+        * operation, it can happen that write() is called by a later
+        * stdio function even if an earlier write() call failed. In the
+        * case of a pipe whose readable end was closed, only the first
+        * call to write() reports EPIPE on Windows. Subsequent write()
+        * calls report EINVAL. It is impossible to notice whether this
+        * fflush invocation triggered such a case, therefore, we have to
+        * catch all EINVAL errors whole-sale.
+        */
+       if (ret && errno == EINVAL)
+               errno = EPIPE;
+
+       return ret;
+}
+
 /*
  * The unit of FILETIME is 100-nanoseconds since January 1, 1601, UTC.