Merge branch 'nd/fix-directory-attrs-off-by-one' into maint
authorJunio C Hamano <gitster@pobox.com>
Tue, 29 Jan 2013 19:18:54 +0000 (11:18 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 29 Jan 2013 19:20:10 +0000 (11:20 -0800)
The attribute mechanism didn't allow limiting attributes to be
applied to only a single directory itself with "path/" like the
exclude mechanism does. The initial implementation of this that was
merged to 'maint' and 1.8.1.1 had severe performance degradations.

* nd/fix-directory-attrs-off-by-one:
attr: avoid calling find_basename() twice per path
attr: fix off-by-one directory component length calculation

118 files changed:
.gitignore
.mailmap
Documentation/CodingGuidelines
Documentation/Makefile
Documentation/RelNotes/1.8.0.3.txt [new file with mode: 0644]
Documentation/RelNotes/1.8.1.1.txt [new file with mode: 0644]
Documentation/RelNotes/1.8.1.2.txt [new file with mode: 0644]
Documentation/RelNotes/1.8.1.txt
Documentation/SubmittingPatches
Documentation/config.txt
Documentation/diff-options.txt
Documentation/fetch-options.txt
Documentation/git-bundle.txt
Documentation/git-checkout.txt
Documentation/git-commit-tree.txt
Documentation/git-config.txt
Documentation/git-cvsimport.txt
Documentation/git-diff.txt
Documentation/git-fast-import.txt
Documentation/git-for-each-ref.txt
Documentation/git-remote-helpers.txt
Documentation/git-shortlog.txt
Documentation/git-svn.txt
Documentation/git-tag.txt
Documentation/git.txt
Documentation/howto/new-command.txt [new file with mode: 0644]
Documentation/mailmap.txt
Documentation/pt_BR/gittutorial.txt [deleted file]
Documentation/technical/api-allocation-growing.txt
Documentation/technical/api-command.txt [deleted file]
Documentation/technical/api-history-graph.txt
Documentation/technical/api-index-skel.txt
Documentation/technical/api-run-command.txt
Documentation/technical/api-string-list.txt
Documentation/technical/index-format.txt
GIT-VERSION-GEN
Makefile
README
RelNotes
abspath.c
archive-tar.c
archive-zip.c
attr.c
builtin.h
builtin/apply.c
builtin/clone.c
builtin/fmt-merge-msg.c
builtin/merge.c
builtin/pack-redundant.c
builtin/shortlog.c
cache-tree.c
cache-tree.h
cache.h
compat/fnmatch/fnmatch.c
compat/nedmalloc/nedmalloc.c
config.c
configure.ac
contrib/completion/git-completion.bash
contrib/completion/git-completion.tcsh
contrib/completion/git-prompt.sh
contrib/remote-helpers/git-remote-hg
contrib/remote-helpers/test-hg-bidi.sh
contrib/stats/mailmap.pl
contrib/subtree/.gitignore
contrib/subtree/git-subtree.txt
contrib/vim/README
dir.c
editor.c
git-compat-util.h
git-rebase--interactive.sh
git-send-email.perl
git-sh-setup.sh
gitweb/gitweb.perl
graph.c
http.c
path.c
perl/Git.pm
perl/Git/SVN/Prompt.pm
pretty.c
refs.c
remote-testsvn.c
remote.c
run-command.c
setup.c
string-list.c
string-list.h
t/Makefile
t/lib-gettext.sh
t/t0024-crlf-archive.sh
t/t0060-path-utils.sh
t/t0063-string-list.sh
t/t1020-subdirectory.sh
t/t1402-check-ref-format.sh
t/t2203-add-intent.sh
t/t3600-rm.sh
t/t4014-format-patch.sh
t/t4201-shortlog.sh
t/t4202-log.sh
t/t5000-tar-tree.sh
t/t5003-archive-zip.sh [new file with mode: 0755]
t/t5003/infozip-symlinks.zip [new file with mode: 0644]
t/t5535-fetch-push-symref.sh [new file with mode: 0755]
t/t5600-clone-fail-cleanup.sh
t/t7004-tag.sh
t/t7061-wtstatus-ignore.sh [new file with mode: 0755]
t/t7505-prepare-commit-msg-hook.sh
t/t9020-remote-svn.sh
t/t9200-git-cvsexportcommit.sh
t/t9502-gitweb-standalone-parse-output.sh
t/t9810-git-p4-rcs.sh
t/test-lib.sh
t/test-terminal.perl
test-path-utils.c
test-string-list.c
utf8.c
utf8.h
wrapper.c
wt-status.c
index f702415c12c5a4a66180f7ffd697347e5343ac4a..726db73450189ccd1ab6975ba9ca872f53a79c44 100644 (file)
@@ -3,6 +3,7 @@
 /GIT-LDFLAGS
 /GIT-GUI-VARS
 /GIT-PREFIX
+/GIT-PYTHON-VARS
 /GIT-SCRIPT-DEFINES
 /GIT-USER-AGENT
 /GIT-VERSION-FILE
index bcf4f8770f0751a61cf1c1b89a0d66cff559c54e..c7e86183001a00ad2105765708b5b59852ef6640 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -9,7 +9,9 @@ Alex Bennée <kernel-hacker@bennee.com>
 Alexander Gavrilov <angavrilov@gmail.com>
 Aneesh Kumar K.V <aneesh.kumar@gmail.com>
 Brian M. Carlson <sandals@crustytoothpaste.ath.cx>
+Cheng Renquan <crquan@gmail.com>
 Chris Shoemaker <c.shoemaker@cox.net>
+Dan Johnson <computerdruid@gmail.com>
 Dana L. How <danahow@gmail.com>
 Dana L. How <how@deathvalley.cswitch.com>
 Daniel Barkalow <barkalow@iabervon.org>
@@ -18,14 +20,18 @@ David KÃ¥gedal <davidk@lysator.liu.se>
 David S. Miller <davem@davemloft.net>
 Deskin Miller <deskinm@umich.edu>
 Dirk Süsserott <newsletter@dirk.my1.cc>
+Eric S. Raymond <esr@thyrsus.com>
 Erik Faye-Lund <kusmabite@gmail.com> <kusmabite@googlemail.com>
 Fredrik Kuivinen <freku045@student.liu.se>
+Frédéric Heitzmann <frederic.heitzmann@gmail.com>
 H. Peter Anvin <hpa@bonde.sc.orionmulti.com>
 H. Peter Anvin <hpa@tazenda.sc.orionmulti.com>
 H. Peter Anvin <hpa@trantor.hos.anvin.org>
 Horst H. von Brand <vonbrand@inf.utfsm.cl>
 Ä°smail Dönmez <ismail@pardus.org.tr>
+Jakub NarÄ™bski <jnareb@gmail.com>
 Jay Soffian <jaysoffian+git@gmail.com>
+Jeff King <peff@peff.net> <peff@github.com>
 Joachim Berdal Haga <cjhaga@fys.uio.no>
 Johannes Sixt <j6t@kdbg.org> <johannes.sixt@telecom.at>
 Johannes Sixt <j6t@kdbg.org> <j.sixt@viscovery.net>
@@ -41,12 +47,21 @@ Junio C Hamano <gitster@pobox.com> <junio@hera.kernel.org>
 Junio C Hamano <gitster@pobox.com> <junio@kernel.org>
 Junio C Hamano <gitster@pobox.com> <junkio@cox.net>
 Karl Hasselström <kha@treskal.com>
+Kevin Leung <kevinlsk@gmail.com>
 Kent Engstrom <kent@lysator.liu.se>
 Lars Doelle <lars.doelle@on-line ! de>
 Lars Doelle <lars.doelle@on-line.de>
 Li Hong <leehong@pku.edu.cn>
+Linus Torvalds <torvalds@linux-foundation.org> <torvalds@woody.linux-foundation.org>
+Linus Torvalds <torvalds@linux-foundation.org> <torvalds@osdl.org>
+Linus Torvalds <torvalds@linux-foundation.org> <torvalds@g5.osdl.org>
+Linus Torvalds <torvalds@linux-foundation.org> <torvalds@evo.osdl.org>
+Linus Torvalds <torvalds@linux-foundation.org> <torvalds@ppc970.osdl.org>
+Linus Torvalds <torvalds@linux-foundation.org> <torvalds@ppc970.osdl.org.(none)>
 Lukas Sandström <lukass@etek.chalmers.se>
-Martin Langhoff <martin@laptop.org>
+Marc-André Lureau <marcandre.lureau@gmail.com>
+Mark Rada <marada@uwaterloo.ca>
+Martin Langhoff <martin@laptop.org> <martin@catalyst.net.nz>
 Martin von Zweigbergk <martinvonz@gmail.com> <martin.von.zweigbergk@gmail.com>
 Michael Coleman <tutufan@gmail.com>
 Michael J Gruber <git@drmicha.warpmail.net> <michaeljgruber+gmane@fastmail.fm>
@@ -63,11 +78,13 @@ Ralf Thielow <ralf.thielow@gmail.com> <ralf.thielow@googlemail.com>
 Ramsay Allan Jones <ramsay@ramsay1.demon.co.uk>
 René Scharfe <rene.scharfe@lsrfire.ath.cx>
 Robert Fitzsimons <robfitz@273k.net>
+Robert Zeh <robert.a.zeh@gmail.com>
 Sam Vilain <sam@vilain.net>
 Santi Béjar <sbejar@gmail.com>
 Sean Estabrooks <seanlkml@sympatico.ca>
 Shawn O. Pearce <spearce@spearce.org>
 Steven Grimm <koreth@midwinter.com>
+Tay Ray Chuan <rctay89@gmail.com>
 Theodore Ts'o <tytso@mit.edu>
 Thomas Rast <trast@inf.ethz.ch> <trast@student.ethz.ch>
 Tony Luck <tony.luck@intel.com>
index 57da6aadeb8b4d65037035afaa269f391e989c38..69f7e9b76c3f9b87b7951fb0df6a9720edadeb3e 100644 (file)
@@ -112,6 +112,14 @@ For C programs:
 
  - We try to keep to at most 80 characters per line.
 
+ - We try to support a wide range of C compilers to compile git with,
+   including old ones. That means that you should not use C99
+   initializers, even if a lot of compilers grok it.
+
+ - Variables have to be declared at the beginning of the block.
+
+ - NULL pointers shall be written as NULL, not as 0.
+
  - When declaring pointers, the star sides with the variable
    name, i.e. "char *string", not "char* string" or
    "char * string".  This makes it easier to understand code
index 361550422a6e180f5614305985cfd12aa964ffe0..971977b8aa3cfbc97f2f60f1be051d7327c00beb 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)))
@@ -178,8 +178,6 @@ all: html man
 
 html: $(DOC_HTML)
 
-$(DOC_HTML) $(DOC_MAN1) $(DOC_MAN5) $(DOC_MAN7): asciidoc.conf
-
 man: man1 man5 man7
 man1: $(DOC_MAN1)
 man5: $(DOC_MAN5)
@@ -257,7 +255,7 @@ clean:
        $(RM) $(cmds_txt) *.made
        $(RM) manpage-base-url.xsl
 
-$(MAN_HTML): %.html : %.txt
+$(MAN_HTML): %.html : %.txt asciidoc.conf
        $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
        $(ASCIIDOC) -b xhtml11 -d manpage -f asciidoc.conf \
                $(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) -o $@+ $< && \
@@ -270,7 +268,7 @@ manpage-base-url.xsl: manpage-base-url.xsl.in
        $(QUIET_XMLTO)$(RM) $@ && \
        $(XMLTO) -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $<
 
-%.xml : %.txt
+%.xml : %.txt asciidoc.conf
        $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
        $(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf \
                $(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) -o $@+ $< && \
@@ -286,7 +284,7 @@ technical/api-index.txt: technical/api-index-skel.txt \
        $(QUIET_GEN)cd technical && '$(SHELL_PATH_SQ)' ./api-index.sh
 
 technical/%.html: ASCIIDOC_EXTRA += -a git-relative-html-prefix=../
-$(patsubst %,%.html,$(API_DOCS) technical/api-index $(TECH_DOCS)): %.html : %.txt
+$(patsubst %,%.html,$(API_DOCS) technical/api-index $(TECH_DOCS)): %.html : %.txt asciidoc.conf
        $(QUIET_ASCIIDOC)$(ASCIIDOC) -b xhtml11 -f asciidoc.conf \
                $(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) $*.txt
 
@@ -331,7 +329,7 @@ $(patsubst %.txt,%.texi,$(MAN_TXT)): %.texi : %.xml
 
 howto-index.txt: howto-index.sh $(wildcard howto/*.txt)
        $(QUIET_GEN)$(RM) $@+ $@ && \
-       '$(SHELL_PATH_SQ)' ./howto-index.sh $(wildcard howto/*.txt) >$@+ && \
+       '$(SHELL_PATH_SQ)' ./howto-index.sh $(sort $(wildcard howto/*.txt)) >$@+ && \
        mv $@+ $@
 
 $(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt
diff --git a/Documentation/RelNotes/1.8.0.3.txt b/Documentation/RelNotes/1.8.0.3.txt
new file mode 100644 (file)
index 0000000..92b1e4b
--- /dev/null
@@ -0,0 +1,14 @@
+Git v1.8.0.3 Release Notes
+==========================
+
+Fixes since v1.8.0.2
+--------------------
+
+ * "git log -p -S<string>" did not apply the textconv filter while
+   looking for the <string>.
+
+ * In the documentation, some invalid example e-mail addresses were
+   formatted into mailto: links.
+
+Also contains many documentation updates backported from the 'master'
+branch that is preparing for the upcoming 1.8.1 release.
diff --git a/Documentation/RelNotes/1.8.1.1.txt b/Documentation/RelNotes/1.8.1.1.txt
new file mode 100644 (file)
index 0000000..6cde07b
--- /dev/null
@@ -0,0 +1,87 @@
+Git 1.8.1.1 Release Notes
+=========================
+
+Fixes since v1.8.1
+------------------
+
+ * The attribute mechanism didn't allow limiting attributes to be
+   applied to only a single directory itself with "path/" like the
+   exclude mechanism does.
+
+ * When attempting to read the XDG-style $HOME/.config/git/config and
+   finding that $HOME/.config/git is a file, we gave a wrong error
+   message, instead of treating the case as "a custom config file does
+   not exist there" and moving on.
+
+ * After failing to create a temporary file using mkstemp(), failing
+   pathname was not reported correctly on some platforms.
+
+ * http transport was wrong to ask for the username when the
+   authentication is done by certificate identity.
+
+ * 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.
+
+ * A child process that was killed by a signal (e.g. SIGINT) was
+   reported in an inconsistent way depending on how the process was
+   spawned by us, with or without a shell in between.
+
+ * After "git add -N" and then writing a tree object out of the
+   index, the cache-tree data structure got corrupted.
+
+ * "git apply" misbehaved when fixing whitespace breakages by removing
+   excess trailing blank lines in some corner cases.
+
+ * A tar archive created by "git archive" recorded a directory in a
+   way that made NetBSD's implementation of "tar" sometimes unhappy.
+
+ * When "git clone --separate-git-dir=$over_there" is interrupted, it
+   failed to remove the real location of the $GIT_DIR it created.
+   This was most visible when interrupting a submodule update.
+
+ * "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.
+
+ * The "log --graph" codepath fell into infinite loop in some
+   corner cases.
+
+ * "git merge" started calling prepare-commit-msg hook like "git
+   commit" does some time ago, but forgot to pay attention to the exit
+   status of the hook.
+
+ * "git pack-refs" that ran in parallel to another process that
+   created new refs had a race that can lose new ones.
+
+ * 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.
+
+ * The way "git svn" asked for password using SSH_ASKPASS and
+   GIT_ASKPASS was not in line with the rest of the system.
+
+ * "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.
+
+ * "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.
+
+ * When autoconf is used, any build on a different commit always ran
+   "config.status --recheck" even when unnecessary.
+
+ * Some scripted programs written in Python did not get updated when
+   PYTHON_PATH changed.
+
+ * We have been carrying a translated and long-unmaintained copy of an
+   old version of the tutorial; removed.
+
+ * Portability issues in many self-test scripts have been addressed.
+
+
+Also contains other minor fixes and documentation updates.
diff --git a/Documentation/RelNotes/1.8.1.2.txt b/Documentation/RelNotes/1.8.1.2.txt
new file mode 100644 (file)
index 0000000..5ab7b18
--- /dev/null
@@ -0,0 +1,25 @@
+Git 1.8.1.2 Release Notes
+=========================
+
+Fixes since v1.8.1.1
+--------------------
+
+ * 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.
+
+ * Command line completion for "tcsh" emitted an unwanted space
+   after completing a single directory name.
+
+ * Command line completion leaked an unnecessary error message while
+   looking for possible matches with paths in <tree-ish>.
+
+ * "git archive" did not record uncompressed size in the header when
+   streaming a zip archive, which confused some implementations of unzip.
+
+ * When users spelled "cc:" in lowercase in the fake "header" in the
+   trailer part, "git send-email" failed to pick up the addresses from
+   there. As e-mail headers field names are case insensitive, this
+   script should follow suit and treat "cc:" and "Cc:" the same way.
+
+Also contains various documentation fixes.
index 6aa24c64c00282556df58f6b152de6838b58740d..d6f9555923ae900bd9ff04e8283b513a678c1395 100644 (file)
@@ -29,24 +29,17 @@ UI, Workflows & Features
 
  * Command-line completion scripts for tcsh and zsh have been added.
 
- * A new remote-helper interface for Mercurial has been added to
-   contrib/remote-helpers.
+ * "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.
 
- * Some documentation pages that used to ship only in the plain text
-   format are now formatted in HTML as well.
-
- * "git-prompt" scriptlet (in contrib/completion) can be told to paint
-   pieces of the hints in the prompt string in colors.
-
- * 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.
-
  * 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
@@ -60,13 +53,17 @@ UI, Workflows & Features
    API regression but it is expected that nobody will notice it in
    practice.
 
- * "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.
+ * 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".
 
@@ -116,11 +113,20 @@ Foreign Interface
  * 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
index 3d8b2fe4d18875f8505b91850dd33ec79b122076..90133d8c3b2ea7ea8af55a2bac0876b10aff8f3e 100644 (file)
@@ -1,65 +1,5 @@
-Checklist (and a short version for the impatient):
-
-       Commits:
-
-       - make commits of logical units
-       - check for unnecessary whitespace with "git diff --check"
-         before committing
-       - do not check in commented out code or unneeded files
-       - the first line of the commit message should be a short
-         description (50 characters is the soft limit, see DISCUSSION
-         in git-commit(1)), and should skip the full stop
-       - the body should provide a meaningful commit message, which:
-         . explains the problem the change tries to solve, iow, what
-           is wrong with the current code without the change.
-         . justifies the way the change solves the problem, iow, why
-           the result with the change is better.
-         . alternate solutions considered but discarded, if any.
-       - describe changes in imperative mood, e.g. "make xyzzy do frotz"
-         instead of "[This patch] makes xyzzy do frotz" or "[I] changed
-         xyzzy to do frotz", as if you are giving orders to the codebase
-         to change its behaviour.
-       - try to make sure your explanation can be understood without
-         external resources. Instead of giving a URL to a mailing list
-         archive, summarize the relevant points of the discussion.
-       - add a "Signed-off-by: Your Name <you@example.com>" line to the
-         commit message (or just use the option "-s" when committing)
-         to confirm that you agree to the Developer's Certificate of Origin
-       - make sure that you have tests for the bug you are fixing
-       - make sure that the test suite passes after your commit
-
-       Patch:
-
-       - use "git format-patch -M" to create the patch
-       - do not PGP sign your patch
-       - do not attach your patch, but read in the mail
-         body, unless you cannot teach your mailer to
-         leave the formatting of the patch alone.
-       - be careful doing cut & paste into your mailer, not to
-         corrupt whitespaces.
-       - provide additional information (which is unsuitable for
-         the commit message) between the "---" and the diffstat
-       - if you change, add, or remove a command line option or
-         make some other user interface change, the associated
-         documentation should be updated as well.
-       - if your name is not writable in ASCII, make sure that
-         you send off a message in the correct encoding.
-       - send the patch to the list (git@vger.kernel.org) and the
-         maintainer (gitster@pobox.com) if (and only if) the patch
-         is ready for inclusion. If you use git-send-email(1),
-         please test it first by sending email to yourself.
-       - see below for instructions specific to your mailer
-
-Long version:
-
-I started reading over the SubmittingPatches document for Linux
-kernel, primarily because I wanted to have a document similar to
-it for the core GIT to make sure people understand what they are
-doing when they write "Signed-off-by" line.
-
-But the patch submission requirements are a lot more relaxed
-here on the technical/contents front, because the core GIT is
-thousand times smaller ;-).  So here is only the relevant bits.
+Here are some guidelines for people who want to contribute their code
+to this software.
 
 (0) Decide what to base your work on.
 
@@ -86,6 +26,10 @@ change is relevant to.
    wait until some of the dependent topics graduate to 'master', and
    rebase your work.
 
+ - Some parts of the system have dedicated maintainers with their own
+   repositories (see the section "Subsystems" below).  Changes to
+   these parts should be based on their trees.
+
 To find the tip of a topic branch, run "git log --first-parent
 master..pu" and look for the merge commit. The second parent of this
 commit is the tip of the topic branch.
@@ -113,26 +57,53 @@ change, the approach taken by the change, and if relevant how this
 differs substantially from the prior version, are all good things
 to have.
 
+Make sure that you have tests for the bug you are fixing.
+
+When adding a new feature, make sure that you have new tests to show
+the feature triggers the new behaviour when it should, and to show the
+feature does not trigger when it shouldn't.  Also make sure that the
+test suite passes after your commit.  Do not forget to update the
+documentation to describe the updated behaviour.
+
 Oh, another thing.  I am picky about whitespaces.  Make sure your
 changes do not trigger errors with the sample pre-commit hook shipped
 in templates/hooks--pre-commit.  To help ensure this does not happen,
 run git diff --check on your changes before you commit.
 
 
-(1a) Try to be nice to older C compilers
+(2) Describe your changes well.
+
+The first line of the commit message should be a short description (50
+characters is the soft limit, see DISCUSSION in git-commit(1)), and
+should skip the full stop.  It is also conventional in most cases to
+prefix the first line with "area: " where the area is a filename or
+identifier for the general area of the code being modified, e.g.
+
+  . archive: ustar header checksum is computed unsigned
+  . git-cherry-pick.txt: clarify the use of revision range notation
+
+If in doubt which identifier to use, run "git log --no-merges" on the
+files you are modifying to see the current conventions.
 
-We try to support a wide range of C compilers to compile
-git with. That means that you should not use C99 initializers, even
-if a lot of compilers grok it.
+The body should provide a meaningful commit message, which:
 
-Also, variables have to be declared at the beginning of the block
-(you can check this with gcc, using the -Wdeclaration-after-statement
-option).
+  . explains the problem the change tries to solve, iow, what is wrong
+    with the current code without the change.
 
-Another thing: NULL pointers shall be written as NULL, not as 0.
+  . justifies the way the change solves the problem, iow, why the
+    result with the change is better.
 
+  . alternate solutions considered but discarded, if any.
 
-(2) Generate your patch using git tools out of your commits.
+Describe your changes in imperative mood, e.g. "make xyzzy do frotz"
+instead of "[This patch] makes xyzzy do frotz" or "[I] changed xyzzy
+to do frotz", as if you are giving orders to the codebase to change
+its behaviour.  Try to make sure your explanation can be understood
+without external resources. Instead of giving a URL to a mailing list
+archive, summarize the relevant points of the discussion.
+
+
+(3) Generate your patch using git tools out of your commits.
 
 git based diff tools generate unidiff which is the preferred format.
 
@@ -140,22 +111,27 @@ You do not have to be afraid to use -M option to "git diff" or
 "git format-patch", if your patch involves file renames.  The
 receiving end can handle them just fine.
 
-Please make sure your patch does not include any extra files
-which do not belong in a patch submission.  Make sure to review
+Please make sure your patch does not add commented out debugging code,
+or include any extra files which do not relate to what your patch
+is trying to achieve. Make sure to review
 your patch after generating it, to ensure accuracy.  Before
 sending out, please make sure it cleanly applies to the "master"
 branch head.  If you are preparing a work based on "next" branch,
 that is fine, but please mark it as such.
 
 
-(3) Sending your patches.
+(4) Sending your patches.
 
 People on the git mailing list need to be able to read and
 comment on the changes you are submitting.  It is important for
 a developer to be able to "quote" your changes, using standard
 e-mail tools, so that they may comment on specific portions of
 your code.  For this reason, all patches should be submitted
-"inline".  WARNING: Be wary of your MUAs word-wrap
+"inline".  If your log message (including your name on the
+Signed-off-by line) is not writable in ASCII, make sure that
+you send off a message in the correct encoding.
+
+WARNING: Be wary of your MUAs word-wrap
 corrupting your patch.  Do not cut-n-paste your patch; you can
 lose tabs that way if you are not careful.
 
@@ -208,19 +184,25 @@ patch, format it as "multipart/signed", not a text/plain message
 that starts with '-----BEGIN PGP SIGNED MESSAGE-----'.  That is
 not a text/plain, it's something else.
 
-Unless your patch is a very trivial and an obviously correct one,
-first send it with "To:" set to the mailing list, with "cc:" listing
+Send your patch with "To:" set to the mailing list, with "cc:" listing
 people who are involved in the area you are touching (the output from
 "git blame $path" and "git shortlog --no-merges $path" would help to
-identify them), to solicit comments and reviews.  After the list
-reached a consensus that it is a good idea to apply the patch, re-send
-it with "To:" set to the maintainer and optionally "cc:" the list for
-inclusion.  Do not forget to add trailers such as "Acked-by:",
-"Reviewed-by:" and "Tested-by:" after your "Signed-off-by:" line as
-necessary.
+identify them), to solicit comments and reviews.
+
+After the list reached a consensus that it is a good idea to apply the
+patch, re-send it with "To:" set to the maintainer [*1*] and "cc:" the
+list [*2*] for inclusion.
+
+Do not forget to add trailers such as "Acked-by:", "Reviewed-by:" and
+"Tested-by:" lines as necessary to credit people who helped your
+patch.
 
+    [Addresses]
+     *1* The current maintainer: gitster@pobox.com
+     *2* The mailing list: git@vger.kernel.org
 
-(4) Sign your work
+
+(5) Sign your work
 
 To improve tracking of who did what, we've borrowed the
 "sign-off" procedure from the Linux kernel project on patches
@@ -290,6 +272,26 @@ If you like, you can put extra tags at the end:
 You can also create your own tag or use one that's in common usage
 such as "Thanks-to:", "Based-on-patch-by:", or "Mentored-by:".
 
+------------------------------------------------
+Subsystems with dedicated maintainers
+
+Some parts of the system have dedicated maintainers with their own
+repositories.
+
+ - git-gui/ comes from git-gui project, maintained by Pat Thoyts:
+
+        git://repo.or.cz/git-gui.git
+
+ - gitk-git/ comes from Paul Mackerras's gitk project:
+
+        git://ozlabs.org/~paulus/gitk
+
+ - po/ comes from the localization coordinator, Jiang Xin:
+
+       https://github.com/git-l10n/git-po/
+
+Patches to these parts should be based on their trees.
+
 ------------------------------------------------
 An ideal patch flow
 
index bf8f911e1ffe7820a8e903ec669c690d39612150..e452ff89ba1f2935d6b22d030251b04db48a3cef 100644 (file)
@@ -1351,6 +1351,12 @@ help.autocorrect::
        value is 0 - the command will be just shown but not executed.
        This is the default.
 
+help.htmlpath::
+       Specify the path where the HTML documentation resides. File system paths
+       and URLs are supported. HTML pages will be prefixed with this path when
+       help is displayed in the 'web' format. This defaults to the documentation
+       path of your Git installation.
+
 http.proxy::
        Override the HTTP proxy, normally configured using the 'http_proxy',
        'https_proxy', and 'all_proxy' environment variables (see
index f4f7e250c53c8fc51e17d5643b5b3b93d4036efc..39f2c5074c1ac370976bce36cbceb1a676064cfe 100644 (file)
@@ -309,7 +309,11 @@ endif::git-log[]
        index (i.e. amount of addition/deletions compared to the
        file's size). For example, `-M90%` means git should consider a
        delete/add pair to be a rename if more than 90% of the file
-       hasn't changed.
+       hasn't changed.  Without a `%` sign, the number is to be read as
+       a fraction, with a decimal point before it.  I.e., `-M5` becomes
+       0.5, and is thus the same as `-M50%`.  Similarly, `-M05` is
+       the same as `-M5%`.  To limit detection to exact renames, use
+       `-M100%`.
 
 -C[<n>]::
 --find-copies[=<n>]::
index b4d6476ac898db8ff99ab3639efce08050ef71c4..6e98bdf1490a0a5718dd14a4c2d8b2baaee7383e 100644 (file)
@@ -57,14 +57,11 @@ endif::git-pull[]
 ifndef::git-pull[]
 -t::
 --tags::
-       Most of the tags are fetched automatically as branch
-       heads are downloaded, but tags that do not point at
-       objects reachable from the branch heads that are being
-       tracked will not be fetched by this mechanism.  This
-       flag lets all tags and their associated objects be
-       downloaded. The default behavior for a remote may be
-       specified with the remote.<name>.tagopt setting. See
-       linkgit:git-config[1].
+       This is a short-hand for giving "refs/tags/*:refs/tags/*"
+       refspec from the command line, to ask all tags to be fetched
+       and stored locally.  Because this acts as an explicit
+       refspec, the default refspecs (configured with the
+       remote.$name.fetch variable) are overridden and not used.
 
 --recurse-submodules[=yes|on-demand|no]::
        This option controls if and under what conditions new commits of
index 16a6b0acebc7e15bfae0850d6d6c716fd5a32eaa..bc023cc5f3bb6be8cd664ec6a74743f46b396283 100644 (file)
@@ -112,13 +112,12 @@ machineA$ git bundle create file.bundle master
 machineA$ git tag -f lastR2bundle master
 ----------------
 
-Then you transfer file.bundle to the target machine B. If you are creating
-the repository on machine B, then you can clone from the bundle as if it
-were a remote repository instead of creating an empty repository and then
-pulling or fetching objects from the bundle:
+Then you transfer file.bundle to the target machine B. Because this
+bundle does not require any existing object to be extracted, you can
+create a new repository on machine B by cloning from it:
 
 ----------------
-machineB$ git clone /home/me/tmp/file.bundle R2
+machineB$ git clone -b master /home/me/tmp/file.bundle R2
 ----------------
 
 This will define a remote called "origin" in the resulting repository that
index 7958a4700642270ad3f801e314cf870331cf4512..6f04d22f5e15ea0805fb44c9c856952d759bc050 100644 (file)
@@ -21,18 +21,34 @@ or the specified tree.  If no paths are given, 'git checkout' will
 also update `HEAD` to set the specified branch as the current
 branch.
 
-'git checkout' [<branch>]::
+'git checkout' <branch>::
+       To prepare for working on <branch>, switch to it by updating
+       the index and the files in the working tree, and by pointing
+       HEAD at the branch. Local modifications to the files in the
+       working tree are kept, so that they can be committed to the
+       <branch>.
++
+If <branch> is not found but there does exist a tracking branch in
+exactly one remote (call it <remote>) with a matching name, treat as
+equivalent to
++
+------------
+$ git checkout -b <branch> --track <remote>/<branch>
+------------
++
+You could omit <branch>, in which case the command degenerates to
+"check out the current branch", which is a glorified no-op with a
+rather expensive side-effects to show only the tracking information,
+if exists, for the current branch.
+
 'git checkout' -b|-B <new_branch> [<start point>]::
-'git checkout' [--detach] [<commit>]::
 
-       This form switches branches by updating the index, working
-       tree, and HEAD to reflect the specified branch or commit.
-+
-If `-b` is given, a new branch is created as if linkgit:git-branch[1]
-were called and then checked out; in this case you can
-use the `--track` or `--no-track` options, which will be passed to
-'git branch'.  As a convenience, `--track` without `-b` implies branch
-creation; see the description of `--track` below.
+       Specifying `-b` causes a new branch to be created as if
+       linkgit:git-branch[1] were called and then checked out.  In
+       this case you can use the `--track` or `--no-track` options,
+       which will be passed to 'git branch'.  As a convenience,
+       `--track` without `-b` implies branch creation; see the
+       description of `--track` below.
 +
 If `-B` is given, <new_branch> is created if it doesn't exist; otherwise, it
 is reset. This is the transactional equivalent of
@@ -45,6 +61,21 @@ $ git checkout <branch>
 that is to say, the branch is not reset/created unless "git checkout" is
 successful.
 
+'git checkout' --detach [<branch>]::
+'git checkout' <commit>::
+
+       Prepare to work on top of <commit>, by detaching HEAD at it
+       (see "DETACHED HEAD" section), and updating the index and the
+       files in the working tree.  Local modifications to the files
+       in the working tree are kept, so that the resulting working
+       tree will be the state recorded in the commit plus the local
+       modifications.
++
+Passing `--detach` forces this behavior in the case of a <branch> (without
+the option, giving a branch name to the command would check out the branch,
+instead of detaching HEAD at it), or the current commit,
+if no <branch> is specified.
+
 'git checkout' [-p|--patch] [<tree-ish>] [--] <pathspec>...::
 
        When <paths> or `--patch` are given, 'git checkout' does *not*
index 6d5a04c83b6461396b44b3972a539eaae6368a19..a22116951527e4181d85ed23acb029f6920ee1ff 100644 (file)
@@ -72,13 +72,13 @@ if set:
        GIT_COMMITTER_NAME
        GIT_COMMITTER_EMAIL
        GIT_COMMITTER_DATE
-       EMAIL
 
 (nb "<", ">" and "\n"s are stripped)
 
 In case (some of) these environment variables are not set, the information
 is taken from the configuration items user.name and user.email, or, if not
-present, system user name and the hostname used for outgoing mail (taken
+present, the environment variable EMAIL, or, if that is not set,
+system user name and the hostname used for outgoing mail (taken
 from `/etc/mailname` and falling back to the fully qualified hostname when
 that file does not exist).
 
index eaea0791657386469e448def614b949c0a1f45e9..9ae2508f3fb79b9da5fb4481a4fe2120f4a082b1 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 98d9881d7e891e4728c09f6536c3506b3688d145..9d5353e8be4a56cb92c1987e40a3695b23733d56 100644 (file)
@@ -213,11 +213,9 @@ Problems related to tags:
 * Multiple tags on the same revision are not imported.
 
 If you suspect that any of these issues may apply to the repository you
-want to import consider using these alternative tools which proved to be
-more stable in practice:
+want to imort, consider using cvs2git:
 
-* cvs2git (part of cvs2svn), `http://cvs2svn.tigris.org`
-* parsecvs, `http://cgit.freedesktop.org/~keithp/parsecvs`
+* cvs2git (part of cvs2svn), `http://subversion.apache.org/`
 
 GIT
 ---
index f8d0819113c52ac7c6388ec27eb96083a8c86d4a..f8c06013f3588a96e66d08265afe8131f054b7ff 100644 (file)
@@ -12,6 +12,7 @@ SYNOPSIS
 'git diff' [options] [<commit>] [--] [<path>...]
 'git diff' [options] --cached [<commit>] [--] [<path>...]
 'git diff' [options] <commit> <commit> [--] [<path>...]
+'git diff' [options] <blob> <blob>
 'git diff' [options] [--no-index] [--] <path> <path>
 
 DESCRIPTION
@@ -55,6 +56,11 @@ directories. This behavior can be forced by --no-index.
        This is to view the changes between two arbitrary
        <commit>.
 
+'git diff' [options] <blob> <blob>::
+
+       This form is to view the differences between the raw
+       contents of two blob objects.
+
 'git diff' [--options] <commit>..<commit> [--] [<path>...]::
 
        This is synonymous to the previous form.  If <commit> on
@@ -72,8 +78,7 @@ directories. This behavior can be forced by --no-index.
 Just in case if you are doing something exotic, it should be
 noted that all of the <commit> in the above description, except
 in the last two forms that use ".." notations, can be any
-<tree>.  The third form ('git diff <commit> <commit>') can also
-be used to compare two <blob> objects.
+<tree>.
 
 For a more complete list of ways to spell <commit>, see
 "SPECIFYING REVISIONS" section in linkgit:gitrevisions[7].
index d1844ead4a4883cc31447c20763b61091f66ed8e..bf1a02a80d5f4a61f5bbd0d826ae7df3bce58911 100644 (file)
@@ -33,38 +33,46 @@ the frontend program in use.
 
 OPTIONS
 -------
---date-format=<fmt>::
-       Specify the type of dates the frontend will supply to
-       fast-import within `author`, `committer` and `tagger` commands.
-       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
        not contain the old commit).
 
---max-pack-size=<n>::
-       Maximum size of each output packfile.
-       The default is unlimited.
+--quiet::
+       Disable all non-fatal output, making fast-import silent when it
+       is successful.  This option disables the output shown by
+       \--stats.
 
---big-file-threshold=<n>::
-       Maximum size of a blob that fast-import will attempt to
-       create a delta for, expressed in bytes.  The default is 512m
-       (512 MiB).  Some importers may wish to lower this on systems
-       with constrained memory.
+--stats::
+       Display some basic statistics about the objects fast-import has
+       created, the packfiles they were stored into, and the
+       memory used by fast-import during this run.  Showing this output
+       is currently the default, but can be disabled with \--quiet.
 
---depth=<n>::
-       Maximum delta depth, for blob and tree deltification.
-       Default is 10.
+Options for Frontends
+~~~~~~~~~~~~~~~~~~~~~
 
---active-branches=<n>::
-       Maximum number of branches to maintain active at once.
-       See ``Memory Utilization'' below for details.  Default is 5.
+--cat-blob-fd=<fd>::
+       Write responses to `cat-blob` and `ls` queries to the
+       file descriptor <fd> instead of `stdout`.  Allows `progress`
+       output intended for the end-user to be separated from other
+       output.
+
+--date-format=<fmt>::
+       Specify the type of dates the frontend will supply to
+       fast-import within `author`, `committer` and `tagger` commands.
+       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.  This option might be useful for detecting errors
+       that cause the frontend to terminate before it has started to
+       write a stream.
+
+Locations of Marks Files
+~~~~~~~~~~~~~~~~~~~~~~~~
 
 --export-marks=<file>::
        Dumps the internal marks table to <file> when complete.
@@ -87,31 +95,33 @@ OPTIONS
        Like --import-marks but instead of erroring out, silently
        skips the file if it does not exist.
 
---relative-marks::
+--[no-]relative-marks::
        After specifying --relative-marks the paths specified
        with --import-marks= and --export-marks= are relative
        to an internal directory in the current repository.
        In git-fast-import this means that the paths are relative
        to the .git/info/fast-import directory. However, other
        importers may use a different location.
++
+Relative and non-relative marks may be combined by interweaving
+--(no-)-relative-marks with the --(import|export)-marks= options.
 
---no-relative-marks::
-       Negates a previous --relative-marks. Allows for combining
-       relative and non-relative marks by interweaving
-       --(no-)-relative-marks with the --(import|export)-marks=
-       options.
+Performance and Compression Tuning
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
---cat-blob-fd=<fd>::
-       Write responses to `cat-blob` and `ls` queries to the
-       file descriptor <fd> instead of `stdout`.  Allows `progress`
-       output intended for the end-user to be separated from other
-       output.
+--active-branches=<n>::
+       Maximum number of branches to maintain active at once.
+       See ``Memory Utilization'' below for details.  Default is 5.
 
---done::
-       Require a `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.
+--big-file-threshold=<n>::
+       Maximum size of a blob that fast-import will attempt to
+       create a delta for, expressed in bytes.  The default is 512m
+       (512 MiB).  Some importers may wish to lower this on systems
+       with constrained memory.
+
+--depth=<n>::
+       Maximum delta depth, for blob and tree deltification.
+       Default is 10.
 
 --export-pack-edges=<file>::
        After creating a packfile, print a line of data to
@@ -122,16 +132,9 @@ OPTIONS
        as these commits can be used as edge points during calls
        to 'git pack-objects'.
 
---quiet::
-       Disable all non-fatal output, making fast-import silent when it
-       is successful.  This option disables the output shown by
-       \--stats.
-
---stats::
-       Display some basic statistics about the objects fast-import has
-       created, the packfiles they were stored into, and the
-       memory used by fast-import during this run.  Showing this output
-       is currently the default, but can be disabled with \--quiet.
+--max-pack-size=<n>::
+       Maximum size of each output packfile.
+       The default is unlimited.
 
 
 Performance
@@ -427,7 +430,7 @@ they made it.
 
 Here `<name>` is the person's display name (for example
 ``Com M Itter'') and `<email>` is the person's email address
-(``cm@example.com'').  `LT` and `GT` are the literal less-than (\x3c)
+(``\cm@example.com'').  `LT` and `GT` are the literal less-than (\x3c)
 and greater-than (\x3e) symbols.  These are required to delimit
 the email address from the other fields in the line.  Note that
 `<name>` and `<email>` are free-form and may contain any sequence
index db55a4e0bbc524c20f08e6862daaa97dd1785b71..f2e08d11c19cf127c5f7d484b0c3d66fc475d547 100644 (file)
@@ -117,7 +117,7 @@ returns an empty string instead.
 
 As a special case for the date-type fields, you may specify a format for
 the date by adding one of `:default`, `:relative`, `:short`, `:local`,
-`:iso8601` or `:rfc2822` to the end of the fieldname; e.g.
+`:iso8601`, `:rfc2822` or `:raw` to the end of the fieldname; e.g.
 `%(taggerdate:relative)`.
 
 
index 5ce4cda8e72ff27a46cd79ae66e8587a9cc2b7d8..6d696e0f90b3f0b67adde7ef4aa4fa6816e391eb 100644 (file)
@@ -35,6 +35,37 @@ transport protocols, such as 'git-remote-http', 'git-remote-https',
 'git-remote-ftp' and 'git-remote-ftps'. They implement the capabilities
 'fetch', 'option', and 'push'.
 
+INVOCATION
+----------
+
+Remote helper programs are invoked with one or (optionally) two
+arguments. The first argument specifies a remote repository as in git;
+it is either the name of a configured remote or a URL. The second
+argument specifies a URL; it is usually of the form
+'<transport>://<address>', but any arbitrary string is possible.
+The 'GIT_DIR' environment variable is set up for the remote helper
+and can be used to determine where to store additional data or from
+which directory to invoke auxiliary git commands.
+
+When git encounters a URL of the form '<transport>://<address>', where
+'<transport>' is a protocol that it cannot handle natively, it
+automatically invokes 'git remote-<transport>' with the full URL as
+the second argument. If such a URL is encountered directly on the
+command line, the first argument is the same as the second, and if it
+is encountered in a configured remote, the first argument is the name
+of that remote.
+
+A URL of the form '<transport>::<address>' explicitly instructs git to
+invoke 'git remote-<transport>' with '<address>' as the second
+argument. If such a URL is encountered directly on the command line,
+the first argument is '<address>', and if it is encountered in a
+configured remote, the first argument is the name of that remote.
+
+Additionally, when a configured remote has 'remote.<name>.vcs' set to
+'<transport>', git explicitly invokes 'git remote-<transport>' with
+'<name>' as the first argument. If set, the second argument is
+'remote.<name>.url'; otherwise, the second argument is omitted.
+
 INPUT FORMAT
 ------------
 
@@ -57,67 +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 *:*`.
-
-'bidi-import'::
-       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.
+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'.
 
@@ -127,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'.
 
@@ -158,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
@@ -173,36 +177,33 @@ advertised with this capability must cover all refs reported by
 the list command.  If no 'refspec' capability is advertised,
 there is an implied `refspec *:*`.
 
-INVOCATION
-----------
+'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.
 
-Remote helper programs are invoked with one or (optionally) two
-arguments. The first argument specifies a remote repository as in git;
-it is either the name of a configured remote or a URL. The second
-argument specifies a URL; it is usually of the form
-'<transport>://<address>', but any arbitrary string is possible.
-The 'GIT_DIR' environment variable is set up for the remote helper
-and can be used to determine where to store additional data or from
-which directory to invoke auxiliary git commands.
+'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].
 
-When git encounters a URL of the form '<transport>://<address>', where
-'<transport>' is a protocol that it cannot handle natively, it
-automatically invokes 'git remote-<transport>' with the full URL as
-the second argument. If such a URL is encountered directly on the
-command line, the first argument is the same as the second, and if it
-is encountered in a configured remote, the first argument is the name
-of that remote.
 
-A URL of the form '<transport>::<address>' explicitly instructs git to
-invoke 'git remote-<transport>' with '<address>' as the second
-argument. If such a URL is encountered directly on the command line,
-the first argument is '<address>', and if it is encountered in a
-configured remote, the first argument is the name of that remote.
 
-Additionally, when a configured remote has 'remote.<name>.vcs' set to
-'<transport>', git explicitly invokes 'git remote-<transport>' with
-'<name>' as the first argument. If set, the second argument is
-'remote.<name>.url'; otherwise, the second argument is omitted.
 
 COMMANDS
 --------
@@ -212,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>
@@ -224,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
@@ -236,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>::
@@ -244,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
@@ -305,7 +321,23 @@ 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.
+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
@@ -332,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
@@ -343,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 afeb4cdf16df91f63197d390fdbf1540eff66837..c308e91537a02817560d3108be5517d1806b0c9e 100644 (file)
@@ -56,6 +56,9 @@ OPTIONS
        line of each entry is indented by `indent1` spaces, and the second
        and subsequent lines are indented by `indent2` spaces. `width`,
        `indent1`, and `indent2` default to 76, 6 and 9 respectively.
++
+If width is `0` (zero) then indent the lines of the output without wrapping
+them.
 
 
 MAPPING AUTHORS
index 8b0d3adfede9ebffbddc294d6f30eedea0e2dfa0..69decb13b0ec672cd9ccc83a67a08f1725473324 100644 (file)
@@ -628,10 +628,19 @@ ADVANCED OPTIONS
        Default: "svn"
 
 --follow-parent::
+       This option is only relevant if we are tracking branches (using
+       one of the repository layout options --trunk, --tags,
+       --branches, --stdlayout). For each tracked branch, try to find
+       out where its revision was copied from, and set
+       a suitable parent in the first git commit for the branch.
        This is especially helpful when we're tracking a directory
-       that has been moved around within the repository, or if we
-       started tracking a branch and never tracked the trunk it was
-       descended from. This feature is enabled by default, use
+       that has been moved around within the repository.  If this
+       feature is disabled, the branches created by 'git svn' will all
+       be linear and not share any history, meaning that there will be
+       no information on where branches were branched off or merged.
+       However, following long/convoluted histories can take a long
+       time, so disabling this feature may speed up the cloning
+       process. This feature is enabled by default, use
        --no-follow-parent to disable it.
 +
 [verse]
@@ -739,7 +748,8 @@ for rewriteRoot and rewriteUUID which can be used together.
 BASIC EXAMPLES
 --------------
 
-Tracking and contributing to the trunk of a Subversion-managed project:
+Tracking and contributing to the trunk of a Subversion-managed project
+(ignoring tags and branches):
 
 ------------------------------------------------------------------------
 # Clone a repo (like git clone):
@@ -764,8 +774,10 @@ Tracking and contributing to an entire Subversion-managed project
 (complete with a trunk, tags and branches):
 
 ------------------------------------------------------------------------
-# Clone a repo (like git clone):
-       git svn clone http://svn.example.com/project -T trunk -b branches -t tags
+# Clone a repo with standard SVN directory layout (like git clone):
+       git svn clone http://svn.example.com/project --stdlayout
+# Or, if the repo uses a non-standard directory layout:
+       git svn clone http://svn.example.com/project -T tr -b branch -t tag
 # View all branches and tags you have cloned:
        git branch -r
 # Create a new branch in SVN
@@ -830,6 +842,52 @@ inside git back upstream to SVN users.  Therefore it is advised that
 users keep history as linear as possible inside git to ease
 compatibility with SVN (see the CAVEATS section below).
 
+HANDLING OF SVN BRANCHES
+------------------------
+If 'git svn' is configured to fetch branches (and --follow-branches
+is in effect), it sometimes creates multiple git branches for one
+SVN branch, where the addtional branches have names of the form
+'branchname@nnn' (with nnn an SVN revision number).  These additional
+branches are created if 'git svn' cannot find a parent commit for the
+first commit in an SVN branch, to connect the branch to the history of
+the other branches.
+
+Normally, the first commit in an SVN branch consists
+of a copy operation. 'git svn' will read this commit to get the SVN
+revision the branch was created from. It will then try to find the
+git commit that corresponds to this SVN revision, and use that as the
+parent of the branch. However, it is possible that there is no suitable
+git commit to serve as parent.  This will happen, among other reasons,
+if the SVN branch is a copy of a revision that was not fetched by 'git
+svn' (e.g. because it is an old revision that was skipped with
+'--revision'), or if in SVN a directory was copied that is not tracked
+by 'git svn' (such as a branch that is not tracked at all, or a
+subdirectory of a tracked branch). In these cases, 'git svn' will still
+create a git branch, but instead of using an existing git commit as the
+parent of the branch, it will read the SVN history of the directory the
+branch was copied from and create appropriate git commits.  This is
+indicated by the message "Initializing parent: <branchname>".
+
+Additionally, it will create a special branch named
+'<branchname>@<SVN-Revision>', where <SVN-Revision> is the SVN revision
+number the branch was copied from.  This branch will point to the newly
+created parent commit of the branch.  If in SVN the branch was deleted
+and later recreated from a different version, there will be multiple
+such branches with an '@'.
+
+Note that this may mean that multiple git commits are created for a
+single SVN revision.
+
+An example: in an SVN repository with a standard
+trunk/tags/branches layout, a directory trunk/sub is created in r.100.
+In r.200, trunk/sub is branched by copying it to branches/. 'git svn
+clone -s' will then create a branch 'sub'. It will also create new git
+commits for r.100 through r.199 and use these as the history of branch
+'sub'. Thus there will be two git commits for each revision from r.100
+to r.199 (one containing trunk/, one containing trunk/sub/). Finally,
+it will create a branch 'sub@200' pointing to the new parent commit of
+branch 'sub' (i.e. the commit for r.200 and trunk/sub/).
+
 CAVEATS
 -------
 
@@ -871,6 +929,21 @@ already dcommitted.  It is considered bad practice to --amend commits
 you've already pushed to a remote repository for other users, and
 dcommit with SVN is analogous to that.
 
+When cloning an SVN repository, if none of the options for describing
+the repository layout is used (--trunk, --tags, --branches,
+--stdlayout), 'git svn clone' will create a git repository with
+completely linear history, where branches and tags appear as separate
+directories in the working copy.  While this is the easiest way to get a
+copy of a complete repository, for projects with many branches it will
+lead to a working copy many times larger than just the trunk. Thus for
+projects using the standard directory structure (trunk/branches/tags),
+it is recommended to clone with option '--stdlayout'. If the project
+uses a non-standard structure, and/or if branches and tags are not
+required, it is easiest to only clone one directory (typically trunk),
+without giving any repository layout options.  If the full history with
+branches and tags is required, the options '--trunk' / '--branches' /
+'--tags' must be used.
+
 When using multiple --branches or --tags, 'git svn' does not automatically
 handle name collisions (for example, if two branches from different paths have
 the same name, or if a branch and a tag have the same name).  In these cases,
@@ -894,6 +967,12 @@ the possible corner cases (git doesn't do it, either).  Committing
 renamed and copied files is fully supported if they're similar enough
 for git to detect them.
 
+In SVN, it is possible (though discouraged) to commit changes to a tag
+(because a tag is just a directory copy, thus technically the same as a
+branch). When cloning an SVN repository, 'git svn' cannot know if such a
+commit to a tag will happen in the future. Thus it acts conservatively
+and imports all SVN tags as branches, prefixing the tag name with 'tags/'.
+
 CONFIGURATION
 -------------
 
index 247534e908d9f5b804a60b6707d1962eccc9bb1a..6470cffd325f919d8daa6ddb2ef70cf79334c30f 100644 (file)
@@ -129,7 +129,7 @@ This option is only applicable when listing tags without annotation lines.
 CONFIGURATION
 -------------
 By default, 'git tag' in sign-with-default mode (-s) will use your
-committer identity (of the form "Your Name <your@email.address>") to
+committer identity (of the form "Your Name <\your@email.address>") to
 find a key.  If you want to use a different default key, you can specify
 it in the repository configuration as follows:
 
index 25e2f3a60e6e608f866e8be8cce3e500f907c605..276491223a1e4536cd7a6913b1bf1fb75f7012b0 100644 (file)
@@ -43,9 +43,16 @@ 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.0.2/git.html[documentation for release 1.8.0.2]
+* link:v1.8.1.1/git.html[documentation for release 1.8.1.1]
 
 * release notes for
+  link:RelNotes/1.8.1.1.txt[1.8.1.1],
+  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
+  link:RelNotes/1.8.0.3.txt[1.8.0.3],
   link:RelNotes/1.8.0.2.txt[1.8.0.2],
   link:RelNotes/1.8.0.1.txt[1.8.0.1],
   link:RelNotes/1.8.0.txt[1.8.0].
@@ -650,6 +657,7 @@ git so take care if using Cogito etc.
        If the 'GIT_DIR' environment variable is set then it
        specifies a path to use instead of the default `.git`
        for the base of the repository.
+       The '--git-dir' command-line option also sets this value.
 
 'GIT_WORK_TREE'::
        Set the path to the working tree.  The value will not be
@@ -765,6 +773,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',
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 288f04e70c8ea5f0b93a4b099a4a49d1fee13b79..dd89fca3f8996e119ce9d0cec0a6d9fc6616525d 100644 (file)
@@ -46,7 +46,7 @@ Jane Doe         <jane@desktop.(none)>
 Joe R. Developer <joe@example.com>
 ------------
 
-Note how there is no need for an entry for <jane@laptop.(none)>, because the
+Note how there is no need for an entry for `<jane@laptop.(none)>`, because the
 real name of that author is already correct.
 
 Example 2: Your repository contains commits from the following
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 43dbe09f735525b0a1549ccfb4de2f2ca87252a0..542946b1ba701069837b702cbd8fe8079cecf56d 100644 (file)
@@ -5,7 +5,9 @@ Dynamically growing an array using realloc() is error prone and boring.
 
 Define your array with:
 
-* a pointer (`ary`) that points at the array, initialized to `NULL`;
+* a pointer (`item`) that points at the array, initialized to `NULL`
+  (although please name the variable based on its contents, not on its
+  type);
 
 * an integer variable (`alloc`) that keeps track of how big the current
   allocation is, initialized to `0`;
@@ -13,22 +15,22 @@ Define your array with:
 * another integer variable (`nr`) to keep track of how many elements the
   array currently has, initialized to `0`.
 
-Then before adding `n`th element to the array, call `ALLOC_GROW(ary, n,
+Then before adding `n`th element to the item, call `ALLOC_GROW(item, n,
 alloc)`.  This ensures that the array can hold at least `n` elements by
 calling `realloc(3)` and adjusting `alloc` variable.
 
 ------------
-sometype *ary;
+sometype *item;
 size_t nr;
 size_t alloc
 
 for (i = 0; i < nr; i++)
-       if (we like ary[i] already)
+       if (we like item[i] already)
                return;
 
 /* we did not like any existing one, so add one */
-ALLOC_GROW(ary, nr + 1, alloc);
-ary[nr++] = value you like;
+ALLOC_GROW(item, nr + 1, alloc);
+item[nr++] = value you like;
 ------------
 
 You are responsible for updating the `nr` variable.
diff --git a/Documentation/technical/api-command.txt b/Documentation/technical/api-command.txt
deleted file mode 100644 (file)
index ea9b2ed..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-Integrating 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.
-
-0. Don't forget to sign off your patch!
-
-1. Append your command name to one of the variables BUILTIN_OBJS,
-EXTRA_PROGRAMS, SCRIPT_SH, SCRIPT_PERL or SCRIPT_PYTHON.
-
-2. Drop its test in the t directory.
-
-3. 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.
-
-4. If your command has any dependency on a particular version of
-your language, document it in the INSTALL file.
-
-5. 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.
-
-6. 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 d6fc90ac7eb210bd492057422748817a59cfc2a3..18142b6d29283bbf6e325ce71d50761a3f50a227 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 af7cc2e395f1399830f9eacc52468376b216fb86..730cfacf783ef26b408f22c13599420db46e28b4 100644 (file)
@@ -11,5 +11,3 @@ documents them.
 ////////////////////////////////////////////////////////////////
 // table of contents end
 ////////////////////////////////////////////////////////////////
-
-2007-11-24
index f18b4f4817448530a5adbe2c8835bb7791add42a..5d7d7f2d32f58f8682ca5efb2fd98fe7e74247dd 100644 (file)
@@ -55,10 +55,8 @@ The functions above do the following:
   non-zero.
 
 . If the program terminated due to a signal, then the return value is the
-  signal number - 128, ie. it is negative and so indicates an unusual
-  condition; a diagnostic is printed. This return value can be passed to
-  exit(2), which will report the same code to the parent process that a
-  POSIX shell's $? would report for a program that died from the signal.
+  signal number + 128, ie. the same value that a POSIX shell's $? would
+  report.  A diagnostic is printed.
 
 
 `start_async`::
index 7386bcab3ec30a06f4663c953fa46e78ed26c07b..20be3488349c2ddbafbd90c0200f2a7d3862a12f 100644 (file)
@@ -82,14 +82,6 @@ Functions
        call free() on the util members of any items that have to be
        deleted.  Preserve the order of the items that are retained.
 
-`string_list_longest_prefix`::
-
-       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).
-
 `print_string_list`::
 
        Dump a string_list to stdout, useful mainly for debugging purposes. It
index 57d6f915b143765b9e58b3793f14795ddab71200..73241548381fcb0b3c0dbd2cb09f9526a64e637d 100644 (file)
@@ -161,8 +161,9 @@ GIT index format
     this span of index as a tree.
 
   An entry can be in an invalidated state and is represented by having
-  -1 in the entry_count field. In this case, there is no object name
-  and the next entry starts immediately after the newline.
+  a negative number in the entry_count field. In this case, there is no
+  object name and the next entry starts immediately after the newline.
+  When writing an invalid entry, -1 should always be used as entry_count.
 
   The entries are written out in the top-down, depth-first order.  The
   first entry represents the root level of the repository, followed by the
index 4bc073cc135f6bda73a06b24c7b368d6c653224e..2edb996ab12cba8842658af168d7e29ecd138ba4 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v1.8.1-rc1
+DEF_VER=v1.8.1.2
 
 LF='
 '
index 736ecd45b58da32575cc20019d41a2b178843a09..05d241bc1212eeff301a383a887ffa34605faced 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -273,6 +273,10 @@ all::
 #
 # Define NO_REGEX if you have no or inferior regex support in your C library.
 #
+# Define CYGWIN_V15_WIN32API if you are using Cygwin v1.7.x but are not
+# using the current w32api packages. The recommended approach, however,
+# is to update your installation if compilation errors occur.
+#
 # Define HAVE_DEV_TTY if your system can open /dev/tty to interact with the
 # user.
 #
@@ -2245,7 +2249,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 \
@@ -2275,8 +2279,14 @@ configure: configure.ac GIT-VERSION-FILE
        $(RM) $<+
 
 ifdef AUTOCONFIGURED
-config.status: configure
-       $(QUIET_GEN)if test -f config.status; then \
+# We avoid depending on 'configure' here, because it gets rebuilt
+# every time GIT-VERSION-FILE is modified, only to update the embedded
+# version number string, which config.status does not care about.  We
+# do want to recheck when the platform/environment detection logic
+# changes, hence this depends on configure.ac.
+config.status: configure.ac
+       $(QUIET_GEN)$(MAKE) configure && \
+       if test -f config.status; then \
          ./config.status --recheck; \
        else \
          ./configure; \
@@ -2636,6 +2646,18 @@ GIT-GUI-VARS: FORCE
             fi
 endif
 
+### Detect Python interpreter path changes
+ifndef NO_PYTHON
+TRACK_PYTHON = $(subst ','\'',-DPYTHON_PATH='$(PYTHON_PATH_SQ)')
+
+GIT-PYTHON-VARS: FORCE
+       @VARS='$(TRACK_PYTHON)'; \
+           if test x"$$VARS" != x"`cat $@ 2>/dev/null`" ; then \
+               echo 1>&2 "    * new Python interpreter location"; \
+               echo "$$VARS" >$@; \
+            fi
+endif
+
 test_bindir_programs := $(patsubst %,bin-wrappers/%,$(BINDIR_PROGRAMS_NEED_X) $(BINDIR_PROGRAMS_NO_X) $(TEST_PROGRAMS_NEED_X))
 
 all:: $(TEST_PROGRAMS) $(test_bindir_programs)
@@ -2911,7 +2933,7 @@ ifndef NO_TCLTK
        $(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-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
diff --git a/README b/README
index d2690ec8dc6e5f054c33a5f3b4c26f6ad038706d..a960ca8f28d6b5a50872f69e65fbff741cde4c02 100644 (file)
--- a/README
+++ b/README
@@ -19,9 +19,10 @@ Git is a fast, scalable, distributed revision control system with an
 unusually rich command set that provides both high-level operations
 and full access to internals.
 
-Git is an Open Source project covered by the GNU General Public License.
-It was originally written by Linus Torvalds with help of a group of
-hackers around the net. It is currently maintained by Junio C Hamano.
+Git is an Open Source project covered by the GNU General Public
+License version 2 (some parts of it are under different licenses,
+compatible with the GPLv2). It was originally written by Linus
+Torvalds with help of a group of hackers around the net.
 
 Please read the file INSTALL for installation instructions.
 
@@ -46,11 +47,10 @@ requests, comments and patches to git@vger.kernel.org (read
 Documentation/SubmittingPatches for instructions on patch submission).
 To subscribe to the list, send an email with just "subscribe git" in
 the body to majordomo@vger.kernel.org. The mailing list archives are
-available at http://marc.theaimsgroup.com/?l=git and other archival
-sites.
-
-The messages titled "A note from the maintainer", "What's in
-git.git (stable)" and "What's cooking in git.git (topics)" and
-the discussion following them on the mailing list give a good
-reference for project status, development direction and
-remaining tasks.
+available at http://news.gmane.org/gmane.comp.version-control.git/,
+http://marc.info/?l=git and other archival sites.
+
+The maintainer frequently sends the "What's cooking" reports that
+list the current status of various development topics to the mailing
+list.  The discussion following them give a good reference for
+project status, development direction and remaining tasks.
index 28607146f3fec3b69cf5edacf2727e37ca2c89de..db86b8cbfea74af25fee0d24db2fc3b3071fe760 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/1.8.1.txt
\ No newline at end of file
+Documentation/RelNotes/1.8.1.2.txt
\ No newline at end of file
index 05f2d7934878a832f5a2efdf4222c16223050853..40cdc46219d4eba87ba947d9f5556eb80dfdfa9b 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 0ba3f25cf579d6629566a39d4d5ac19b51293ed5..d1cce46e3310d64af32b231de697449ae90ddccf 100644 (file)
@@ -153,6 +153,8 @@ static unsigned int ustar_header_chksum(const struct ustar_header *header)
 static size_t get_path_prefix(const char *path, size_t pathlen, size_t maxlen)
 {
        size_t i = pathlen;
+       if (i > 1 && path[i - 1] == '/')
+               i--;
        if (i > maxlen)
                i = maxlen;
        do {
index 55f66b4060c64789bdb443f6c71f82a75ef22d0b..d3aef532b7e4b844f2ac9995b2e987d378737079 100644 (file)
@@ -240,7 +240,7 @@ static int write_zip_entry(struct archiver_args *args,
                        (mode & 0111) ? ((mode) << 16) : 0;
                if (S_ISREG(mode) && args->compression_level != 0 && size > 0)
                        method = 8;
-               compressed_size = size;
+               compressed_size = (method == 0) ? size : 0;
 
                if (S_ISREG(mode) && type == OBJ_BLOB && !args->convert &&
                    size > big_file_threshold) {
@@ -313,10 +313,7 @@ static int write_zip_entry(struct archiver_args *args,
        copy_le16(header.compression_method, method);
        copy_le16(header.mtime, zip_time);
        copy_le16(header.mdate, zip_date);
-       if (flags & ZIP_STREAM)
-               set_zip_header_data_desc(&header, 0, 0, 0);
-       else
-               set_zip_header_data_desc(&header, size, compressed_size, crc);
+       set_zip_header_data_desc(&header, size, compressed_size, crc);
        copy_le16(header.filename_length, pathlen);
        copy_le16(header.extra_length, ZIP_EXTRA_MTIME_SIZE);
        write_or_die(1, &header, ZIP_LOCAL_HEADER_SIZE);
diff --git a/attr.c b/attr.c
index ab2aab28de88e9850d3c51163a8360191ee2e340..8985c5c25b365276259838c1a50945b7e600dc31 100644 (file)
--- a/attr.c
+++ b/attr.c
@@ -691,7 +691,7 @@ static int fill_one(const char *what, struct match_attr *a, int rem)
 
                if (*n == ATTR__UNKNOWN) {
                        debug_set(what,
-                                 a->is_macro ? a->u.attr->name : a->u.pattern,
+                                 a->is_macro ? a->u.attr->name : a->u.pat.pattern,
                                  attr, v);
                        *n = v;
                        rem--;
index 3faf9d6691413c006f4c82702aa5e0c5e4bc88a0..7e7bbd665a905b0fdf9ce5351f6f09dfd3dd7e8a 100644 (file)
--- a/builtin.h
+++ b/builtin.h
@@ -15,7 +15,8 @@ extern const char git_more_info_string[];
 extern void prune_packed_objects(int);
 
 struct fmt_merge_msg_opts {
-       unsigned add_title:1;
+       unsigned add_title:1,
+               credit_people:1;
        int shortlog_len;
 };
 
index 156b3ce3b72f51013baacff0a8ffd37ac97e6158..6c11e8bc73892b15f91fcb65d65e18ee05956ec8 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 ec2f75b4f3b9d9acfb8aa6b423f3b0fc7fbbafdf..8d23a62e8a1b875f1415f78a4c283f4cdefac011 100644 (file)
@@ -771,8 +771,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
                die(_("could not create leading directories of '%s'"), git_dir);
 
        set_git_dir_init(git_dir, real_git_dir, 0);
-       if (real_git_dir)
+       if (real_git_dir) {
                git_dir = real_git_dir;
+               junk_git_dir = real_git_dir;
+       }
 
        if (0 <= option_verbosity) {
                if (option_bare)
index e2e27b2c404a1c451a20e396a7aa03dece722dad..d9af43c257150c957bf3bc3c3b7a7e43e370174c 100644 (file)
@@ -232,8 +232,9 @@ static void record_person(int which, struct string_list *people,
 {
        char *name_buf, *name, *name_end;
        struct string_list_item *elem;
-       const char *field = (which == 'a') ? "\nauthor " : "\ncommitter ";
+       const char *field;
 
+       field = (which == 'a') ? "\nauthor " : "\ncommitter ";
        name = strstr(commit->buffer, field);
        if (!name)
                return;
@@ -323,7 +324,8 @@ static void add_people_info(struct strbuf *out,
 static void shortlog(const char *name,
                     struct origin_data *origin_data,
                     struct commit *head,
-                    struct rev_info *rev, int limit,
+                    struct rev_info *rev,
+                    struct fmt_merge_msg_opts *opts,
                     struct strbuf *out)
 {
        int i, count = 0;
@@ -335,6 +337,7 @@ static void shortlog(const char *name,
        int flags = UNINTERESTING | TREESAME | SEEN | SHOWN | ADDED;
        struct strbuf sb = STRBUF_INIT;
        const unsigned char *sha1 = origin_data->sha1;
+       int limit = opts->shortlog_len;
 
        branch = deref_tag(parse_object(sha1), sha1_to_hex(sha1), 40);
        if (!branch || branch->type != OBJ_COMMIT)
@@ -351,13 +354,15 @@ static void shortlog(const char *name,
 
                if (commit->parents && commit->parents->next) {
                        /* do not list a merge but count committer */
-                       record_person('c', &committers, commit);
+                       if (opts->credit_people)
+                               record_person('c', &committers, commit);
                        continue;
                }
-               if (!count)
+               if (!count && opts->credit_people)
                        /* the 'tip' committer */
                        record_person('c', &committers, commit);
-               record_person('a', &authors, commit);
+               if (opts->credit_people)
+                       record_person('a', &authors, commit);
                count++;
                if (subjects.nr > limit)
                        continue;
@@ -372,7 +377,8 @@ static void shortlog(const char *name,
                        string_list_append(&subjects, strbuf_detach(&sb, NULL));
        }
 
-       add_people_info(out, &authors, &committers);
+       if (opts->credit_people)
+               add_people_info(out, &authors, &committers);
        if (count > limit)
                strbuf_addf(out, "\n* %s: (%d commits)\n", name, count);
        else
@@ -635,7 +641,7 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
                for (i = 0; i < origins.nr; i++)
                        shortlog(origins.items[i].string,
                                 origins.items[i].util,
-                                head, &rev, opts->shortlog_len, out);
+                                head, &rev, opts, out);
        }
 
        strbuf_complete_line(out);
@@ -690,6 +696,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
 
        memset(&opts, 0, sizeof(opts));
        opts.add_title = !message;
+       opts.credit_people = 1;
        opts.shortlog_len = shortlog_len;
 
        ret = fmt_merge_msg(&input, &output, &opts);
index a96e8eac19911c710f0f6870a53bda480b09747b..9307e9c726587461d002530938dbf2c0d74d55a1 100644 (file)
@@ -800,8 +800,9 @@ static void prepare_to_commit(struct commit_list *remoteheads)
        if (0 < option_edit)
                strbuf_add_lines(&msg, "# ", comment, strlen(comment));
        write_merge_msg(&msg);
-       run_hook(get_index_file(), "prepare-commit-msg",
-                git_path("MERGE_MSG"), "merge", NULL, NULL);
+       if (run_hook(get_index_file(), "prepare-commit-msg",
+                    git_path("MERGE_MSG"), "merge", NULL, NULL))
+               abort_commit(remoteheads, NULL);
        if (0 < option_edit) {
                if (launch_editor(git_path("MERGE_MSG"), NULL, NULL))
                        abort_commit(remoteheads, NULL);
@@ -1221,6 +1222,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                        memset(&opts, 0, sizeof(opts));
                        opts.add_title = !have_message;
                        opts.shortlog_len = shortlog_len;
+                       opts.credit_people = (0 < option_edit);
 
                        fmt_merge_msg(&merge_names, &merge_msg, &opts);
                        if (merge_msg.len)
index f5c6afc5dd46c8f856d0f125287724bbfdc65db7..649c3aaa93ccdaae21b7884209bd4f28fb558f3e 100644 (file)
@@ -301,14 +301,14 @@ static void pll_free(struct pll *l)
  */
 static struct pll * get_permutations(struct pack_list *list, int n)
 {
-       struct pll *subset, *ret = NULL, *new_pll = NULL, *pll;
+       struct pll *subset, *ret = NULL, *new_pll = NULL;
 
        if (list == NULL || pack_list_size(list) < n || n == 0)
                return NULL;
 
        if (n == 1) {
                while (list) {
-                       new_pll = xmalloc(sizeof(pll));
+                       new_pll = xmalloc(sizeof(*new_pll));
                        new_pll->pl = NULL;
                        pack_list_insert(&new_pll->pl, list);
                        new_pll->next = ret;
@@ -321,7 +321,7 @@ static struct pll * get_permutations(struct pack_list *list, int n)
        while (list->next) {
                subset = get_permutations(list->next, n - 1);
                while (subset) {
-                       new_pll = xmalloc(sizeof(pll));
+                       new_pll = xmalloc(sizeof(*new_pll));
                        new_pll->pl = subset->pl;
                        pack_list_insert(&new_pll->pl, list);
                        new_pll->next = ret;
index b316cf37ca768f1502c5d0cfa64372a9b322a572..83605143ac0cea68b421dd9a3c056d3a27f66be9 100644 (file)
@@ -306,9 +306,8 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix)
 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 28ed6574a2faf3151056aa20e681e06a157e4a2d..37e4d008b59420338ce97f1b2cf2eb660dab8a34 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 d8cb2e9e39d2be9c4dad67db44a464c2a1004d2f..55d0f59f2b7a42b40fe4be32297b56656206983d 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 18fdd18f3674b1d7c62de65509bdb7bc57743395..2b192d24ac63181b0bba08805c09f004af8ef1dc 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -714,10 +714,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);
index 0ff1d273a5839d15a908a4ed90b56d59b151e6e0..b8b7dc254373fb0f7b2a7b16163fa72e1e8c5f7b 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 d9a17a8057c5740edea3d7888c4607e63af9eddd..91c4e7f27b4063c7ceffeeb1cd43530ce18cf096 100644 (file)
@@ -603,7 +603,10 @@ static NOINLINE mstate FindMSpace(nedpool *p, threadcache *tc, int *lastUsed, si
                }
                /* We really want to make sure this goes into memory now but we
                have to be careful of breaking aliasing rules, so write it twice */
-               *((volatile struct malloc_state **) &p->m[end])=p->m[end]=temp;
+               {
+                       volatile struct malloc_state **_m=(volatile struct malloc_state **) &p->m[end];
+                       *_m=(p->m[end]=temp);
+               }
                ACQUIRE_LOCK(&p->m[end]->mutex);
                /*printf("Created mspace idx %d\n", end);*/
                RELEASE_LOCK(&p->mutex);
index fb3f8681eed21ee81cfe36296c438ed135b98485..b5696354fa0e2b176c6d99ae0f34ba1bf1ecc5f7 100644 (file)
--- a/config.c
+++ b/config.c
@@ -58,7 +58,7 @@ static int handle_path_include(const char *path, struct config_include_data *inc
                path = buf.buf;
        }
 
-       if (!access_or_warn(path, R_OK)) {
+       if (!access_or_die(path, R_OK)) {
                if (++inc->depth > MAX_INCLUDE_DEPTH)
                        die(include_depth_advice, MAX_INCLUDE_DEPTH, path,
                            cf && cf->name ? cf->name : "the command line");
@@ -938,23 +938,23 @@ int git_config_early(config_fn_t fn, void *data, const char *repo_config)
 
        home_config_paths(&user_config, &xdg_config, "config");
 
-       if (git_config_system() && !access_or_warn(git_etc_gitconfig(), R_OK)) {
+       if (git_config_system() && !access_or_die(git_etc_gitconfig(), R_OK)) {
                ret += git_config_from_file(fn, git_etc_gitconfig(),
                                            data);
                found += 1;
        }
 
-       if (xdg_config && !access_or_warn(xdg_config, R_OK)) {
+       if (xdg_config && !access_or_die(xdg_config, R_OK)) {
                ret += git_config_from_file(fn, xdg_config, data);
                found += 1;
        }
 
-       if (user_config && !access_or_warn(user_config, R_OK)) {
+       if (user_config && !access_or_die(user_config, R_OK)) {
                ret += git_config_from_file(fn, user_config, data);
                found += 1;
        }
 
-       if (repo_config && !access_or_warn(repo_config, R_OK)) {
+       if (repo_config && !access_or_die(repo_config, R_OK)) {
                ret += git_config_from_file(fn, repo_config, data);
                found += 1;
        }
index ad215cc4a10ed95804e7cec929f003c985d25a3d..41ac9a5e2d29b5f797a03052c3a17a8b42dac093 100644 (file)
@@ -1021,7 +1021,17 @@ if test -n "$USER_NOPTHREAD"; then
 # -D_REENTRANT' or some such.
 elif test -z "$PTHREAD_CFLAGS"; then
   threads_found=no
-  for opt in -mt -pthread -lpthread; do
+  # Attempt to compile and link some code using pthreads to determine
+  # required linker flags. The order is somewhat important here: We
+  # first try it without any extra flags, to catch systems where
+  # pthreads are part of the C library, then go on testing various other
+  # flags. We do so to avoid false positives. For example, on Mac OS X
+  # pthreads are part of the C library; moreover, the compiler allows us
+  # to add "-mt" to the CFLAGS (although it will do nothing except
+  # trigger a warning about an unused flag). Hence if we checked for
+  # "-mt" before "" we would end up picking it. But unfortunately this
+  # would then trigger compiler warnings on every single file we compile.
+  for opt in "" -mt -pthread -lpthread; do
      old_CFLAGS="$CFLAGS"
      CFLAGS="$opt $CFLAGS"
      AC_MSG_CHECKING([for POSIX Threads with '$opt'])
index 0b77eb1fa4074fb8ed5ef4cd4c37513f49804e7e..14dd5e7ca272350b3fa13d6fc8da3ccb46e12227 100644 (file)
@@ -397,7 +397,7 @@ __git_complete_revlist_file ()
                *)   pfx="$ref:$pfx" ;;
                esac
 
-               __gitcomp_nl "$(git --git-dir="$(__gitdir)" ls-tree "$ls" \
+               __gitcomp_nl "$(git --git-dir="$(__gitdir)" ls-tree "$ls" 2>/dev/null \
                                | sed '/^100... blob /{
                                           s,^.*        ,,
                                           s,$, ,
@@ -971,6 +971,13 @@ _git_commit ()
 {
        __git_has_doubledash && return
 
+       case "$prev" in
+       -c|-C)
+               __gitcomp_nl "$(__git_refs)" "" "${cur}"
+               return
+               ;;
+       esac
+
        case "$cur" in
        --cleanup=*)
                __gitcomp "default strip verbatim whitespace
index 8aafb63315c52a08e6f581e0ef13aa9c239b03a8..3e3889f2b4fd3acb441e56284750cb22fef80547 100644 (file)
@@ -13,6 +13,7 @@
 #
 # To use this completion script:
 #
+#    0) You need tcsh 6.16.00 or newer.
 #    1) Copy both this file and the bash completion script to ${HOME}.
 #       You _must_ use the name ${HOME}/.git-completion.bash for the
 #       bash script.
 #        set autolist=ambiguous
 #       It will tell tcsh to list the possible completion choices.
 
+set __git_tcsh_completion_version = `\echo ${tcsh} | \sed 's/\./ /g'`
+if ( ${__git_tcsh_completion_version[1]} < 6 || \
+     ( ${__git_tcsh_completion_version[1]} == 6 && \
+       ${__git_tcsh_completion_version[2]} < 16 ) ) then
+       echo "git-completion.tcsh: Your version of tcsh is too old, you need version 6.16.00 or newer.  Git completion will not work."
+       exit
+endif
+unset __git_tcsh_completion_version
+
 set __git_tcsh_completion_original_script = ${HOME}/.git-completion.bash
 set __git_tcsh_completion_script = ${HOME}/.git-completion.tcsh.bash
 
@@ -64,9 +74,7 @@ fi
 _\${1}
 
 IFS=\$'\n'
-if [ \${#COMPREPLY[*]} -gt 0 ]; then
-       echo "\${COMPREPLY[*]}" | sort | uniq
-else
+if [ \${#COMPREPLY[*]} -eq 0 ]; then
        # No completions suggested.  In this case, we want tcsh to perform
        # standard file completion.  However, there does not seem to be way
        # to tell tcsh to do that.  To help the user, we try to simulate
@@ -85,19 +93,20 @@ else
                # We don't support ~ expansion: too tricky.
                if [ "\${TO_COMPLETE:0:1}" != "~" ]; then
                        # Use ls so as to add the '/' at the end of directories.
-                       RESULT=(\`ls -dp \${TO_COMPLETE}* 2> /dev/null\`)
-                       echo \${RESULT[*]}
-
-                       # If there is a single completion and it is a directory,
-                       # we output it a second time to trick tcsh into not adding a space
-                       # after it.
-                       if [ \${#RESULT[*]} -eq 1 ] && [ "\${RESULT[0]: -1}" == "/" ]; then
-                               echo \${RESULT[*]}
-                       fi
+                       COMPREPLY=(\`ls -dp \${TO_COMPLETE}* 2> /dev/null\`)
                fi
        fi
 fi
 
+# tcsh does not automatically remove duplicates, so we do it ourselves
+echo "\${COMPREPLY[*]}" | sort | uniq
+
+# If there is a single completion and it is a directory, we output it
+# a second time to trick tcsh into not adding a space after it.
+if [ \${#COMPREPLY[*]} -eq 1 ] && [ "\${COMPREPLY[0]: -1}" == "/" ]; then
+       echo "\${COMPREPLY[*]}"
+fi
+
 EOF
 
 # Don't need this variable anymore, so don't pollute the users environment
index 9b074e148d980e5b96819345be23f9b614db849d..9bef0531c5d9358e906bb7872f0775e165caac2c 100644 (file)
@@ -24,6 +24,8 @@
 #        will show username, at-sign, host, colon, cwd, then
 #        various status string, followed by dollar and SP, as
 #        your prompt.
+#        Optionally, you can supply a third argument with a printf
+#        format string to finetune the output of the branch status
 #
 # The argument to __git_ps1 will be displayed only if you are currently
 # in a git repository.  The %s token will be the name of the current
@@ -222,10 +224,12 @@ __git_ps1_show_upstream ()
 # when called from PS1 using command substitution
 # in this mode it prints text to add to bash PS1 prompt (includes branch name)
 #
-# __git_ps1 requires 2 arguments when called from PROMPT_COMMAND (pc)
+# __git_ps1 requires 2 or 3 arguments when called from PROMPT_COMMAND (pc)
 # in that case it _sets_ PS1. The arguments are parts of a PS1 string.
-# when both arguments are given, the first is prepended and the second appended
+# when two arguments are given, the first is prepended and the second appended
 # to the state string when assigned to PS1.
+# The optional third parameter will be used as printf format string to further
+# customize the output of the git-status string.
 # In this mode you can request colored hints using GIT_PS1_SHOWCOLORHINTS=true
 __git_ps1 ()
 {
@@ -236,9 +240,10 @@ __git_ps1 ()
        local printf_format=' (%s)'
 
        case "$#" in
-               2)      pcmode=yes
+               2|3)    pcmode=yes
                        ps1pc_start="$1"
                        ps1pc_end="$2"
+                       printf_format="${3:-$printf_format}"
                ;;
                0|1)    printf_format="${1:-$printf_format}"
                ;;
@@ -339,6 +344,7 @@ __git_ps1 ()
 
                local f="$w$i$s$u"
                if [ $pcmode = yes ]; then
+                       local gitstring=
                        if [ -n "${GIT_PS1_SHOWCOLORHINTS-}" ]; then
                                local c_red='\e[31m'
                                local c_green='\e[32m'
@@ -356,29 +362,31 @@ __git_ps1 ()
                                        branch_color="$bad_color"
                                fi
 
-                               # Setting PS1 directly with \[ and \] around colors
+                               # Setting gitstring directly with \[ and \] around colors
                                # is necessary to prevent wrapping issues!
-                               PS1="$ps1pc_start (\[$branch_color\]$branchstring\[$c_clear\]"
+                               gitstring="\[$branch_color\]$branchstring\[$c_clear\]"
 
                                if [ -n "$w$i$s$u$r$p" ]; then
-                                       PS1="$PS1 "
+                                       gitstring="$gitstring "
                                fi
                                if [ "$w" = "*" ]; then
-                                       PS1="$PS1\[$bad_color\]$w"
+                                       gitstring="$gitstring\[$bad_color\]$w"
                                fi
                                if [ -n "$i" ]; then
-                                       PS1="$PS1\[$ok_color\]$i"
+                                       gitstring="$gitstring\[$ok_color\]$i"
                                fi
                                if [ -n "$s" ]; then
-                                       PS1="$PS1\[$flags_color\]$s"
+                                       gitstring="$gitstring\[$flags_color\]$s"
                                fi
                                if [ -n "$u" ]; then
-                                       PS1="$PS1\[$bad_color\]$u"
+                                       gitstring="$gitstring\[$bad_color\]$u"
                                fi
-                               PS1="$PS1\[$c_clear\]$r$p)$ps1pc_end"
+                               gitstring="$gitstring\[$c_clear\]$r$p"
                        else
-                               PS1="$ps1pc_start ($c${b##refs/heads/}${f:+ $f}$r$p)$ps1pc_end"
+                               gitstring="$c${b##refs/heads/}${f:+ $f}$r$p"
                        fi
+                       gitstring=$(printf -- "$printf_format" "$gitstring")
+                       PS1="$ps1pc_start$gitstring$ps1pc_end"
                else
                        # NO color option unless in PROMPT_COMMAND mode
                        printf -- "$printf_format" "$c${b##refs/heads/}${f:+ $f}$r$p"
index 016cdadb4d8d5af3b0b68c21c1df3054dd1c5f17..c7006000a6f4a19fa4e5f4bf3fc543d4756a1f4d 100755 (executable)
@@ -31,7 +31,7 @@ import urllib
 # hg:
 # Emulate hg-git.
 # Only hg bookmarks are exported as git branches.
-# Commits are modified to preserve hg information and allow biridectionality.
+# Commits are modified to preserve hg information and allow bidirectionality.
 #
 
 NAME_RE = re.compile('^([^<>]+)')
index a94eb28092503c060cc725b720715d611d54527a..1d6198243667c655639781019d8d608e0791e00b 100755 (executable)
@@ -6,7 +6,7 @@
 # https://bitbucket.org/durin42/hg-git/src
 #
 
-test_description='Test biridectionality of remote-hg'
+test_description='Test bidirectionality of remote-hg'
 
 . ./test-lib.sh
 
index 4b852e2455bab324e3bd16e02ec712fbacbf34b0..9513f5e35b443c13cead1f73a27b5e76f94e8d66 100755 (executable)
@@ -1,38 +1,70 @@
-#!/usr/bin/perl -w
-my %mailmap = ();
-open I, "<", ".mailmap";
-while (<I>) {
-       chomp;
-       next if /^#/;
-       if (my ($author, $mail) = /^(.*?)\s+<(.+)>$/) {
-               $mailmap{$mail} = $author;
-       }
+#!/usr/bin/perl
+
+use warnings 'all';
+use strict;
+use Getopt::Long;
+
+my $match_emails;
+my $match_names;
+my $order_by = 'count';
+Getopt::Long::Configure(qw(bundling));
+GetOptions(
+       'emails|e!' => \$match_emails,
+       'names|n!'  => \$match_names,
+       'count|c'   => sub { $order_by = 'count' },
+       'time|t'    => sub { $order_by = 'stamp' },
+) or exit 1;
+$match_emails = 1 unless $match_names;
+
+my $email = {};
+my $name = {};
+
+open(my $fh, '-|', "git log --format='%at <%aE> %aN'");
+while(<$fh>) {
+       my ($t, $e, $n) = /(\S+) <(\S+)> (.*)/;
+       mark($email, $e, $n, $t);
+       mark($name, $n, $e, $t);
 }
-close I;
-
-my %mail2author = ();
-open I, "git log --pretty='format:%ae  %an' |";
-while (<I>) {
-       chomp;
-       my ($mail, $author) = split(/\t/, $_);
-       next if exists $mailmap{$mail};
-       $mail2author{$mail} ||= {};
-       $mail2author{$mail}{$author} ||= 0;
-       $mail2author{$mail}{$author}++;
+close($fh);
+
+if ($match_emails) {
+       foreach my $e (dups($email)) {
+               foreach my $n (vals($email->{$e})) {
+                       show($n, $e, $email->{$e}->{$n});
+               }
+               print "\n";
+       }
 }
-close I;
-
-while (my ($mail, $authorcount) = each %mail2author) {
-       # %$authorcount is ($author => $count);
-       # sort and show the names from the most frequent ones.
-       my @names = (map { $_->[0] }
-               sort { $b->[1] <=> $a->[1] }
-               map { [$_, $authorcount->{$_}] }
-               keys %$authorcount);
-       if (1 < @names) {
-               for (@names) {
-                       print "$_ <$mail>\n";
+if ($match_names) {
+       foreach my $n (dups($name)) {
+               foreach my $e (vals($name->{$n})) {
+                       show($n, $e, $name->{$n}->{$e});
                }
+               print "\n";
        }
 }
+exit 0;
 
+sub mark {
+       my ($h, $k, $v, $t) = @_;
+       my $e = $h->{$k}->{$v} ||= { count => 0, stamp => 0 };
+       $e->{count}++;
+       $e->{stamp} = $t unless $t < $e->{stamp};
+}
+
+sub dups {
+       my $h = shift;
+       return grep { keys($h->{$_}) > 1 } keys($h);
+}
+
+sub vals {
+       my $h = shift;
+       return sort {
+               $h->{$b}->{$order_by} <=> $h->{$a}->{$order_by}
+       } keys($h);
+}
+
+sub show {
+       my ($n, $e, $h) = @_;
+       print "$n <$e> ($h->{$order_by})\n";
+}
index 7e77c9d0229e949c034c8c46811e19d2325e9cca..91360a3d7f0ad2d589dfe0365d4456d56853e7c0 100644 (file)
@@ -1,4 +1,5 @@
 *~
+git-subtree
 git-subtree.xml
 git-subtree.1
 mainline
index 0c44fda011bcfd39fd8c464c35017df620a91ff9..c5bce41ac7ccd88013f3de3c663f980d2277938c 100644 (file)
@@ -93,7 +93,7 @@ pull::
        repository.
        
 push::
-       Does a 'split' (see above) using the <prefix> supplied
+       Does a 'split' (see below) using the <prefix> supplied
        and then does a 'git push' to push the result to the 
        repository and refspec. This can be used to push your
        subtree to different branches of the remote repository.
index fca1e17251f1f414a1d97bf6e6240bdf20daa648..8f16d069721c5b9885b2e700981618878b54191e 100644 (file)
@@ -17,16 +17,6 @@ To install:
 
   1. Copy these files to vim's syntax directory $HOME/.vim/syntax
   2. To auto-detect the editing of various git-related filetypes:
-       $ cat >>$HOME/.vim/filetype.vim <<'EOF'
-       autocmd BufNewFile,BufRead *.git/COMMIT_EDITMSG    setf gitcommit
-       autocmd BufNewFile,BufRead *.git/config,.gitconfig setf gitconfig
-       autocmd BufNewFile,BufRead git-rebase-todo         setf gitrebase
-       autocmd BufNewFile,BufRead .msg.[0-9]*
-               \ if getline(1) =~ '^From.*# This line is ignored.$' |
-               \   setf gitsendemail |
-               \ endif
-       autocmd BufNewFile,BufRead *.git/**
-               \ if getline(1) =~ '^\x\{40\}\>\|^ref: ' |
-               \   setf git |
-               \ endif
-       EOF
+
+       $ curl http://ftp.vim.org/pub/vim/runtime/filetype.vim |
+               sed -ne '/^" Git$/, /^$/ p' >>$HOME/.vim/filetype.vim
diff --git a/dir.c b/dir.c
index 5a83aa7897f270279c403778f43aea6db1efc5af..a473ca23fba1272483bd8041e1bf901b8e12c32e 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -732,7 +732,8 @@ static struct dir_entry *dir_entry_new(const char *pathname, int len)
 
 static struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathname, int len)
 {
-       if (cache_name_exists(pathname, len, ignore_case))
+       if (!(dir->flags & DIR_SHOW_IGNORED) &&
+           cache_name_exists(pathname, len, ignore_case))
                return NULL;
 
        ALLOC_GROW(dir->entries, dir->nr+1, dir->alloc);
@@ -834,8 +835,9 @@ static enum exist_status directory_exists_in_index(const char *dirname, int len)
  * traversal routine.
  *
  * Case 1: If we *already* have entries in the index under that
- * directory name, we always recurse into the directory to see
- * all the files.
+ * directory name, we recurse into the directory to see all the files,
+ * unless the directory is excluded and we want to show ignored
+ * directories
  *
  * Case 2: If we *already* have that directory name as a gitlink,
  * we always continue to see it as a gitlink, regardless of whether
@@ -849,6 +851,9 @@ static enum exist_status directory_exists_in_index(const char *dirname, int len)
  *      just a directory, unless "hide_empty_directories" is
  *      also true and the directory is empty, in which case
  *      we just ignore it entirely.
+ *      if we are looking for ignored directories, look if it
+ *      contains only ignored files to decide if it must be shown as
+ *      ignored or not.
  *  (b) if it looks like a git directory, and we don't have
  *      'no_gitlinks' set we treat it as a gitlink, and show it
  *      as a directory.
@@ -861,12 +866,15 @@ enum directory_treatment {
 };
 
 static enum directory_treatment treat_directory(struct dir_struct *dir,
-       const char *dirname, int len,
+       const char *dirname, int len, int exclude,
        const struct path_simplify *simplify)
 {
        /* The "len-1" is to strip the final '/' */
        switch (directory_exists_in_index(dirname, len-1)) {
        case index_directory:
+               if ((dir->flags & DIR_SHOW_OTHER_DIRECTORIES) && exclude)
+                       break;
+
                return recurse_into_directory;
 
        case index_gitdir:
@@ -886,13 +894,68 @@ static enum directory_treatment treat_directory(struct dir_struct *dir,
        }
 
        /* This is the "show_other_directories" case */
-       if (!(dir->flags & DIR_HIDE_EMPTY_DIRECTORIES))
+
+       /*
+        * We are looking for ignored files and our directory is not ignored,
+        * check if it contains only ignored files
+        */
+       if ((dir->flags & DIR_SHOW_IGNORED) && !exclude) {
+               int ignored;
+               dir->flags &= ~DIR_SHOW_IGNORED;
+               dir->flags |= DIR_HIDE_EMPTY_DIRECTORIES;
+               ignored = read_directory_recursive(dir, dirname, len, 1, simplify);
+               dir->flags &= ~DIR_HIDE_EMPTY_DIRECTORIES;
+               dir->flags |= DIR_SHOW_IGNORED;
+
+               return ignored ? ignore_directory : show_directory;
+       }
+       if (!(dir->flags & DIR_SHOW_IGNORED) &&
+           !(dir->flags & DIR_HIDE_EMPTY_DIRECTORIES))
                return show_directory;
        if (!read_directory_recursive(dir, dirname, len, 1, simplify))
                return ignore_directory;
        return show_directory;
 }
 
+/*
+ * Decide what to do when we find a file while traversing the
+ * filesystem. Mostly two cases:
+ *
+ *  1. We are looking for ignored files
+ *   (a) File is ignored, include it
+ *   (b) File is in ignored path, include it
+ *   (c) File is not ignored, exclude it
+ *
+ *  2. Other scenarios, include the file if not excluded
+ *
+ * Return 1 for exclude, 0 for include.
+ */
+static int treat_file(struct dir_struct *dir, struct strbuf *path, int exclude, int *dtype)
+{
+       struct path_exclude_check check;
+       int exclude_file = 0;
+
+       if (exclude)
+               exclude_file = !(dir->flags & DIR_SHOW_IGNORED);
+       else if (dir->flags & DIR_SHOW_IGNORED) {
+               /* Always exclude indexed files */
+               struct cache_entry *ce = index_name_exists(&the_index,
+                   path->buf, path->len, ignore_case);
+
+               if (ce)
+                       return 1;
+
+               path_exclude_check_init(&check, dir);
+
+               if (!path_excluded(&check, path->buf, path->len, dtype))
+                       exclude_file = 1;
+
+               path_exclude_check_clear(&check);
+       }
+
+       return exclude_file;
+}
+
 /*
  * This is an inexact early pruning of any recursive directory
  * reading - if the path cannot possibly be in the pathspec,
@@ -1031,27 +1094,14 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
        if (dtype == DT_UNKNOWN)
                dtype = get_dtype(de, path->buf, path->len);
 
-       /*
-        * Do we want to see just the ignored files?
-        * We still need to recurse into directories,
-        * even if we don't ignore them, since the
-        * directory may contain files that we do..
-        */
-       if (!exclude && (dir->flags & DIR_SHOW_IGNORED)) {
-               if (dtype != DT_DIR)
-                       return path_ignored;
-       }
-
        switch (dtype) {
        default:
                return path_ignored;
        case DT_DIR:
                strbuf_addch(path, '/');
-               switch (treat_directory(dir, path->buf, path->len, simplify)) {
+
+               switch (treat_directory(dir, path->buf, path->len, exclude, simplify)) {
                case show_directory:
-                       if (exclude != !!(dir->flags
-                                         & DIR_SHOW_IGNORED))
-                               return path_ignored;
                        break;
                case recurse_into_directory:
                        return path_recurse;
@@ -1061,7 +1111,12 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
                break;
        case DT_REG:
        case DT_LNK:
-               break;
+               switch (treat_file(dir, path, exclude, &dtype)) {
+               case 1:
+                       return path_ignored;
+               default:
+                       break;
+               }
        }
        return path_handled;
 }
index d8340031d24828483697c10257806efedfe041f5..27bdecdaf3d99d3179737e07be971d2458408660 100644 (file)
--- a/editor.c
+++ b/editor.c
@@ -1,6 +1,7 @@
 #include "cache.h"
 #include "strbuf.h"
 #include "run-command.h"
+#include "sigchain.h"
 
 #ifndef DEFAULT_EDITOR
 #define DEFAULT_EDITOR "vi"
@@ -37,8 +38,25 @@ int launch_editor(const char *path, struct strbuf *buffer, const char *const *en
 
        if (strcmp(editor, ":")) {
                const char *args[] = { editor, path, NULL };
+               struct child_process p;
+               int ret, sig;
 
-               if (run_command_v_opt_cd_env(args, RUN_USING_SHELL, NULL, env))
+               memset(&p, 0, sizeof(p));
+               p.argv = args;
+               p.env = env;
+               p.use_shell = 1;
+               if (start_command(&p) < 0)
+                       return error("unable to start editor '%s'", editor);
+
+               sigchain_push(SIGINT, SIG_IGN);
+               sigchain_push(SIGQUIT, SIG_IGN);
+               ret = finish_command(&p);
+               sig = ret - 128;
+               sigchain_pop(SIGINT);
+               sigchain_pop(SIGQUIT);
+               if (sig == SIGINT || sig == SIGQUIT)
+                       raise(sig);
+               if (ret)
                        return error("There was a problem with the editor '%s'.",
                                        editor);
        }
index 2e79b8a2f379d7c72a0934b36c7538db2143c722..590d5d3188aed8f3a2b0b7050f2502b28cb4f5fa 100644 (file)
@@ -637,8 +637,12 @@ int rmdir_or_warn(const char *path);
  */
 int remove_or_warn(unsigned int mode, const char *path);
 
-/* Call access(2), but warn for any error besides ENOENT. */
+/*
+ * Call access(2), but warn for any error except "missing file"
+ * (ENOENT or ENOTDIR).
+ */
 int access_or_warn(const char *path, int mode);
+int access_or_die(const char *path, int mode);
 
 /* Warn on an inaccessible file that ought to be accessible */
 void warn_on_inaccessible(const char *path);
index 44901d53c43d972e03a71bfbe0b769f2e8f22d7b..8ed7fccc18507b6f3e2508bb117ce056a764de77 100644 (file)
@@ -190,6 +190,11 @@ is_empty_commit() {
        test "$tree" = "$ptree"
 }
 
+is_merge_commit()
+{
+       git rev-parse --verify --quiet "$1"^2 >/dev/null 2>&1
+}
+
 # Run command with GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and
 # GIT_AUTHOR_DATE exported from the current environment.
 do_with_author () {
@@ -874,7 +879,7 @@ git rev-list $merges_option --pretty=oneline --abbrev-commit \
 while read -r shortsha1 rest
 do
 
-       if test -z "$keep_empty" && is_empty_commit $shortsha1
+       if test -z "$keep_empty" && is_empty_commit $shortsha1 && ! is_merge_commit $shortsha1
        then
                comment_out="# "
        else
index 94c7f76a156f1eaa4c622db267710f2982cf7826..be809e5b59394a4fd2f4f2b73cad6bac47a39600 100755 (executable)
@@ -1285,10 +1285,10 @@ sub send_message {
                }
 
                if (defined $input_format && $input_format eq 'mbox') {
-                       if (/^Subject:\s+(.*)$/) {
+                       if (/^Subject:\s+(.*)$/i) {
                                $subject = $1;
                        }
-                       elsif (/^From:\s+(.*)$/) {
+                       elsif (/^From:\s+(.*)$/i) {
                                ($author, $author_encoding) = unquote_rfc2047($1);
                                next if $suppress_cc{'author'};
                                next if $suppress_cc{'self'} and $author eq $sender;
@@ -1296,14 +1296,14 @@ sub send_message {
                                        $1, $_) unless $quiet;
                                push @cc, $1;
                        }
-                       elsif (/^To:\s+(.*)$/) {
+                       elsif (/^To:\s+(.*)$/i) {
                                foreach my $addr (parse_address_line($1)) {
                                        printf("(mbox) Adding to: %s from line '%s'\n",
                                                $addr, $_) unless $quiet;
                                        push @to, $addr;
                                }
                        }
-                       elsif (/^Cc:\s+(.*)$/) {
+                       elsif (/^Cc:\s+(.*)$/i) {
                                foreach my $addr (parse_address_line($1)) {
                                        if (unquote_rfc2047($addr) eq $sender) {
                                                next if ($suppress_cc{'self'});
@@ -1325,7 +1325,7 @@ sub send_message {
                        elsif (/^Message-Id: (.*)/i) {
                                $message_id = $1;
                        }
-                       elsif (!/^Date:\s/ && /^[-A-Za-z]+:\s+\S/) {
+                       elsif (!/^Date:\s/i && /^[-A-Za-z]+:\s+\S/) {
                                push @xh, $_;
                        }
 
index 22f0aed6db366c3d4a291b3ae646c45002ff86c1..795edd2852aa1c680c3db1776bb84aca7662899d 100644 (file)
 # But we protect ourselves from such a user mistake nevertheless.
 unset CDPATH
 
-# Similarly for IFS
-unset IFS
+# Similarly for IFS, but some shells (e.g. FreeBSD 7.2) are buggy and
+# do not equate an unset IFS with IFS with the default, so here is
+# an explicit SP HT LF.
+IFS='  
+'
 
 git_broken_path_fix () {
        case ":$PATH:" in
index 0f207f2e20b0c3c30e62c1fd6f0526d38868776f..c6bafe6ead815ece2e820d303e442270749c5c4b 100755 (executable)
@@ -1556,7 +1556,7 @@ sub sanitize {
        return undef unless defined $str;
 
        $str = to_utf8($str);
-       $str =~ s|([[:cntrl:]])|($1 =~ /[\t\n\r]/ ? $1 : quot_cec($1))|eg;
+       $str =~ s|([[:cntrl:]])|(index("\t\n\r", $1) != -1 ? $1 : quot_cec($1))|eg;
        return $str;
 }
 
@@ -5528,23 +5528,30 @@ sub fill_project_list_info {
 
 sub sort_projects_list {
        my ($projlist, $order) = @_;
-       my @projects;
 
-       my %order_info = (
-               project => { key => 'path', type => 'str' },
-               descr => { key => 'descr_long', type => 'str' },
-               owner => { key => 'owner', type => 'str' },
-               age => { key => 'age', type => 'num' }
-       );
-       my $oi = $order_info{$order};
-       return @$projlist unless defined $oi;
-       if ($oi->{'type'} eq 'str') {
-               @projects = sort {$a->{$oi->{'key'}} cmp $b->{$oi->{'key'}}} @$projlist;
-       } else {
-               @projects = sort {$a->{$oi->{'key'}} <=> $b->{$oi->{'key'}}} @$projlist;
+       sub order_str {
+               my $key = shift;
+               return sub { $a->{$key} cmp $b->{$key} };
        }
 
-       return @projects;
+       sub order_num_then_undef {
+               my $key = shift;
+               return sub {
+                       defined $a->{$key} ?
+                               (defined $b->{$key} ? $a->{$key} <=> $b->{$key} : -1) :
+                               (defined $b->{$key} ? 1 : 0)
+               };
+       }
+
+       my %orderings = (
+               project => order_str('path'),
+               descr => order_str('descr_long'),
+               owner => order_str('owner'),
+               age => order_num_then_undef('age'),
+       );
+
+       my $ordering = $orderings{$order};
+       return defined $ordering ? sort $ordering @$projlist : @$projlist;
 }
 
 # returns a hash of categories, containing the list of project
diff --git a/graph.c b/graph.c
index e864fe2c6a21379398e454e60627e78a63a09462..391a712e5eafbc05b8d4b739d96aaca0dd481460 100644 (file)
--- a/graph.c
+++ b/graph.c
@@ -1227,7 +1227,7 @@ void graph_show_commit(struct git_graph *graph)
        if (!graph)
                return;
 
-       while (!shown_commit_line) {
+       while (!shown_commit_line && !graph_is_commit_finished(graph)) {
                shown_commit_line = graph_next_line(graph, &msgbuf);
                fwrite(msgbuf.buf, sizeof(char), msgbuf.len, stdout);
                if (!shown_commit_line)
diff --git a/http.c b/http.c
index 0a8abf3be369a18fae8e743d4cc9b5f2c2f63f03..44f35256e44ffdda2ffb0ce67825008bef89700f 100644 (file)
--- a/http.c
+++ b/http.c
@@ -236,6 +236,7 @@ static int has_cert_password(void)
                return 0;
        if (!cert_auth.password) {
                cert_auth.protocol = xstrdup("cert");
+               cert_auth.username = xstrdup("");
                cert_auth.path = xstrdup(ssl_cert);
                credential_fill(&cert_auth);
        }
diff --git a/path.c b/path.c
index cbbdf7d6ba68160a3a9936976e53d773d181ceac..d3d3f8b8ad75b9817df3014296aabc34b6a4eb14 100644 (file)
--- a/path.c
+++ b/path.c
@@ -12,6 +12,7 @@
  */
 #include "cache.h"
 #include "strbuf.h"
+#include "string-list.h"
 
 static char bad_path[] = "/bad-path/";
 
@@ -569,43 +570,38 @@ int normalize_path_copy(char *dst, const char *src)
 
 /*
  * path = Canonical absolute path
- * prefix_list = Colon-separated list of absolute paths
+ * prefixes = string_list containing normalized, absolute paths without
+ * trailing slashes (except for the root directory, which is denoted by "/").
  *
- * Determines, for each path in prefix_list, whether the "prefix" really
+ * Determines, for each path in prefixes, whether the "prefix"
  * is an ancestor directory of path.  Returns the length of the longest
  * ancestor directory, excluding any trailing slashes, or -1 if no prefix
- * is an ancestor.  (Note that this means 0 is returned if prefix_list is
- * "/".) "/foo" is not considered an ancestor of "/foobar".  Directories
+ * is an ancestor.  (Note that this means 0 is returned if prefixes is
+ * ["/"].) "/foo" is not considered an ancestor of "/foobar".  Directories
  * are not considered to be their own ancestors.  path must be in a
  * canonical form: empty components, or "." or ".." components are not
- * allowed.  prefix_list may be null, which is like "".
+ * allowed.
  */
-int longest_ancestor_length(const char *path, const char *prefix_list)
+int longest_ancestor_length(const char *path, struct string_list *prefixes)
 {
-       char buf[PATH_MAX+1];
-       const char *ceil, *colon;
-       int len, max_len = -1;
+       int i, max_len = -1;
 
-       if (prefix_list == NULL || !strcmp(path, "/"))
+       if (!strcmp(path, "/"))
                return -1;
 
-       for (colon = ceil = prefix_list; *colon; ceil = colon+1) {
-               for (colon = ceil; *colon && *colon != PATH_SEP; colon++);
-               len = colon - ceil;
-               if (len == 0 || len > PATH_MAX || !is_absolute_path(ceil))
-                       continue;
-               strlcpy(buf, ceil, len+1);
-               if (normalize_path_copy(buf, buf) < 0)
-                       continue;
-               len = strlen(buf);
-               if (len > 0 && buf[len-1] == '/')
-                       buf[--len] = '\0';
+       for (i = 0; i < prefixes->nr; i++) {
+               const char *ceil = prefixes->items[i].string;
+               int len = strlen(ceil);
 
-               if (!strncmp(path, buf, len) &&
-                   path[len] == '/' &&
-                   len > max_len) {
+               if (len == 1 && ceil[0] == '/')
+                       len = 0; /* root matches anything, with length 0 */
+               else if (!strncmp(path, ceil, len) && path[len] == '/')
+                       ; /* match of length len */
+               else
+                       continue; /* no match */
+
+               if (len > max_len)
                        max_len = len;
-               }
        }
 
        return max_len;
index 497f420178a73061901393f8c21a9feb17054b6d..931047c51da22cddefe0eab08d0fdaa595daefef 100644 (file)
@@ -58,7 +58,7 @@ =head1 SYNOPSIS
                 command_output_pipe command_input_pipe command_close_pipe
                 command_bidi_pipe command_close_bidi_pipe
                 version exec_path html_path hash_object git_cmd_try
-                remote_refs
+                remote_refs prompt
                 temp_acquire temp_release temp_reset temp_path);
 
 
@@ -511,6 +511,58 @@ sub version {
 
 sub html_path { command_oneline('--html-path') }
 
+=item prompt ( PROMPT , ISPASSWORD  )
+
+Query user C<PROMPT> and return answer from user.
+
+Honours GIT_ASKPASS and SSH_ASKPASS environment variables for querying
+the user. If no *_ASKPASS variable is set or an error occoured,
+the terminal is tried as a fallback.
+If C<ISPASSWORD> is set and true, the terminal disables echo.
+
+=cut
+
+sub prompt {
+       my ($prompt, $isPassword) = @_;
+       my $ret;
+       if (exists $ENV{'GIT_ASKPASS'}) {
+               $ret = _prompt($ENV{'GIT_ASKPASS'}, $prompt);
+       }
+       if (!defined $ret && exists $ENV{'SSH_ASKPASS'}) {
+               $ret = _prompt($ENV{'SSH_ASKPASS'}, $prompt);
+       }
+       if (!defined $ret) {
+               print STDERR $prompt;
+               STDERR->flush;
+               if (defined $isPassword && $isPassword) {
+                       require Term::ReadKey;
+                       Term::ReadKey::ReadMode('noecho');
+                       $ret = '';
+                       while (defined(my $key = Term::ReadKey::ReadKey(0))) {
+                               last if $key =~ /[\012\015]/; # \n\r
+                               $ret .= $key;
+                       }
+                       Term::ReadKey::ReadMode('restore');
+                       print STDERR "\n";
+                       STDERR->flush;
+               } else {
+                       chomp($ret = <STDIN>);
+               }
+       }
+       return $ret;
+}
+
+sub _prompt {
+       my ($askpass, $prompt) = @_;
+       return unless length $askpass;
+       $prompt =~ s/\n/ /g;
+       my $ret;
+       open my $fh, "-|", $askpass, $prompt or return;
+       $ret = <$fh>;
+       $ret =~ s/[\015\012]//g; # strip \r\n, chomp does not work on all systems (i.e. windows) as expected
+       close ($fh);
+       return $ret;
+}
 
 =item repo_path ()
 
index 3a6f8af0d9849c5f2fc886f8fc3ac9a8575e271e..74daa7a597fcf55a649a4e90367b1e783a74fcd5 100644 (file)
@@ -62,16 +62,16 @@ sub ssl_server_trust {
                                       issuer_dname fingerprint);
        my $choice;
 prompt:
-       print STDERR $may_save ?
+       my $options = $may_save ?
              "(R)eject, accept (t)emporarily or accept (p)ermanently? " :
              "(R)eject or accept (t)emporarily? ";
        STDERR->flush;
-       $choice = lc(substr(<STDIN> || 'R', 0, 1));
-       if ($choice =~ /^t$/i) {
+       $choice = lc(substr(Git::prompt("Certificate problem.\n" . $options) || 'R', 0, 1));
+       if ($choice eq 't') {
                $cred->may_save(undef);
-       } elsif ($choice =~ /^r$/i) {
+       } elsif ($choice eq 'r') {
                return -1;
-       } elsif ($may_save && $choice =~ /^p$/i) {
+       } elsif ($may_save && $choice eq 'p') {
                $cred->may_save($may_save);
        } else {
                goto prompt;
@@ -109,9 +109,7 @@ sub username {
        if (defined $_username) {
                $username = $_username;
        } else {
-               print STDERR "Username: ";
-               STDERR->flush;
-               chomp($username = <STDIN>);
+               $username = Git::prompt("Username: ");
        }
        $cred->username($username);
        $cred->may_save($may_save);
@@ -120,25 +118,7 @@ sub username {
 
 sub _read_password {
        my ($prompt, $realm) = @_;
-       my $password = '';
-       if (exists $ENV{GIT_ASKPASS}) {
-               open(PH, "-|", $ENV{GIT_ASKPASS}, $prompt);
-               $password = <PH>;
-               $password =~ s/[\012\015]//; # \n\r
-               close(PH);
-       } else {
-               print STDERR $prompt;
-               STDERR->flush;
-               require Term::ReadKey;
-               Term::ReadKey::ReadMode('noecho');
-               while (defined(my $key = Term::ReadKey::ReadKey(0))) {
-                       last if $key =~ /[\012\015]/; # \n\r
-                       $password .= $key;
-               }
-               Term::ReadKey::ReadMode('restore');
-               print STDERR "\n";
-               STDERR->flush;
-       }
+       my $password = Git::prompt($prompt, 1);
        $password;
 }
 
index 5bdc2e70bcd1e8fc0c7e625c3eac26397d8c96d2..91bb2d3ef675b12ac5425ae71600e13c1adc34f9 100644 (file)
--- a/pretty.c
+++ b/pretty.c
@@ -567,7 +567,7 @@ char *logmsg_reencode(const struct commit *commit,
        char *encoding;
        char *out;
 
-       if (!*output_encoding)
+       if (!output_encoding || !*output_encoding)
                return NULL;
        encoding = get_header(commit, "encoding");
        use_encoding = encoding ? encoding : utf8;
@@ -1250,23 +1250,15 @@ void format_commit_message(const struct commit *commit,
                           const struct pretty_print_context *pretty_ctx)
 {
        struct format_commit_context context;
-       static const char utf8[] = "UTF-8";
        const char *output_enc = pretty_ctx->output_encoding;
 
        memset(&context, 0, sizeof(context));
        context.commit = commit;
        context.pretty_ctx = pretty_ctx;
        context.wrap_start = sb->len;
-       context.message = commit->buffer;
-       if (output_enc) {
-               char *enc = get_header(commit, "encoding");
-               if (strcmp(enc ? enc : utf8, output_enc)) {
-                       context.message = logmsg_reencode(commit, output_enc);
-                       if (!context.message)
-                               context.message = commit->buffer;
-               }
-               free(enc);
-       }
+       context.message = logmsg_reencode(commit, output_enc);
+       if (!context.message)
+               context.message = commit->buffer;
 
        strbuf_expand(sb, format, format_commit_item, &context);
        rewrap_message_tail(sb, &context, 0, 0, 0);
diff --git a/refs.c b/refs.c
index 6cec1c8bdf70589a41c2ace4ba4f21f4035e4ed4..541fec20658082f13ef4b73b621787512b300ba6 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -1744,7 +1744,8 @@ static struct lock_file packlock;
 static int repack_without_ref(const char *refname)
 {
        struct repack_without_ref_sb data;
-       struct ref_dir *packed = get_packed_refs(get_ref_cache(NULL));
+       struct ref_cache *refs = get_ref_cache(NULL);
+       struct ref_dir *packed = get_packed_refs(refs);
        if (find_ref(packed, refname) == NULL)
                return 0;
        data.refname = refname;
@@ -1753,6 +1754,8 @@ static int repack_without_ref(const char *refname)
                unable_to_lock_error(git_path("packed-refs"), errno);
                return error("cannot delete '%s' from packed refs", refname);
        }
+       clear_packed_ref_cache(refs);
+       packed = get_packed_refs(refs);
        do_for_each_ref_in_dir(packed, 0, "", repack_without_ref_fn, 0, 0, &data);
        return commit_lock_file(&packlock);
 }
index 51fba059a242103fd13bb4b01c471662e205ec43..5ddf11cc61e22e39f28b3cbe0dbd1075c0881556 100644 (file)
@@ -90,10 +90,12 @@ static int parse_rev_note(const char *msg, struct rev_note *res)
                        if (end == value || i < 0 || i > UINT32_MAX)
                                return -1;
                        res->rev_nr = i;
+                       return 0;
                }
                msg += len + 1;
        }
-       return 0;
+       /* didn't find it */
+       return -1;
 }
 
 static int note2mark_cb(const unsigned char *object_sha1,
index 6aa49c03df13245486b20b04315437811b260882..ca1f8f2eafbef40046f2890501ad757bde9585f1 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -1370,6 +1370,16 @@ int branch_merge_matches(struct branch *branch,
        return refname_match(branch->merge[i]->src, refname, ref_fetch_rules);
 }
 
+static int ignore_symref_update(const char *refname)
+{
+       unsigned char sha1[20];
+       int flag;
+
+       if (!resolve_ref_unsafe(refname, sha1, 0, &flag))
+               return 0; /* non-existing refs are OK */
+       return (flag & REF_ISSYMREF);
+}
+
 static struct ref *get_expanded_map(const struct ref *remote_refs,
                                    const struct refspec *refspec)
 {
@@ -1383,7 +1393,8 @@ static struct ref *get_expanded_map(const struct ref *remote_refs,
                if (strchr(ref->name, '^'))
                        continue; /* a dereference item */
                if (match_name_with_pattern(refspec->src, ref->name,
-                                           refspec->dst, &expn_name)) {
+                                           refspec->dst, &expn_name) &&
+                   !ignore_symref_update(expn_name)) {
                        struct ref *cpy = copy_ref(ref);
 
                        cpy->peer_ref = alloc_ref(expn_name);
index 3b982e4d55274ebe87c5751fa198bee53e371d9b..04712191e8acfbf000c526a5b1b0a80541e8e174 100644 (file)
@@ -226,7 +226,7 @@ static inline void set_cloexec(int fd)
                fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
 }
 
-static int wait_or_whine(pid_t pid, const char *argv0, int silent_exec_failure)
+static int wait_or_whine(pid_t pid, const char *argv0)
 {
        int status, code = -1;
        pid_t waiting;
@@ -242,13 +242,14 @@ static int wait_or_whine(pid_t pid, const char *argv0, int silent_exec_failure)
                error("waitpid is confused (%s)", argv0);
        } else if (WIFSIGNALED(status)) {
                code = WTERMSIG(status);
-               error("%s died of signal %d", argv0, code);
+               if (code != SIGINT && code != SIGQUIT)
+                       error("%s died of signal %d", argv0, code);
                /*
                 * This return value is chosen so that code & 0xff
                 * mimics the exit code that a POSIX shell would report for
                 * a program that died from this signal.
                 */
-               code -= 128;
+               code += 128;
        } else if (WIFEXITED(status)) {
                code = WEXITSTATUS(status);
                /*
@@ -432,8 +433,7 @@ int start_command(struct child_process *cmd)
                 * At this point we know that fork() succeeded, but execvp()
                 * failed. Errors have been reported to our stderr.
                 */
-               wait_or_whine(cmd->pid, cmd->argv[0],
-                             cmd->silent_exec_failure);
+               wait_or_whine(cmd->pid, cmd->argv[0]);
                failed_errno = errno;
                cmd->pid = -1;
        }
@@ -538,7 +538,7 @@ int start_command(struct child_process *cmd)
 
 int finish_command(struct child_process *cmd)
 {
-       return wait_or_whine(cmd->pid, cmd->argv[0], cmd->silent_exec_failure);
+       return wait_or_whine(cmd->pid, cmd->argv[0]);
 }
 
 int run_command(struct child_process *cmd)
@@ -725,7 +725,7 @@ int start_async(struct async *async)
 int finish_async(struct async *async)
 {
 #ifdef NO_PTHREADS
-       return wait_or_whine(async->pid, "child process", 0);
+       return wait_or_whine(async->pid, "child process");
 #else
        void *ret = (void *)(intptr_t)(-1);
 
diff --git a/setup.c b/setup.c
index 3a1b2fd45580cad7ecd55efa755872efc81075ad..f108c4b990c0e4f6a98c1fe34d3031040c84195a 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -1,5 +1,6 @@
 #include "cache.h"
 #include "dir.h"
+#include "string-list.h"
 
 static int inside_git_dir = -1;
 static int inside_work_tree = -1;
@@ -620,6 +621,27 @@ static dev_t get_device_or_die(const char *path, const char *prefix, int prefix_
        return buf.st_dev;
 }
 
+/*
+ * A "string_list_each_func_t" function that canonicalizes an entry
+ * from GIT_CEILING_DIRECTORIES using real_path_if_valid(), or
+ * discards it if unusable.
+ */
+static int canonicalize_ceiling_entry(struct string_list_item *item,
+                                     void *unused)
+{
+       char *ceil = item->string;
+       const char *real_path;
+
+       if (!*ceil || !is_absolute_path(ceil))
+               return 0;
+       real_path = real_path_if_valid(ceil);
+       if (!real_path)
+               return 0;
+       free(item->string);
+       item->string = xstrdup(real_path);
+       return 1;
+}
+
 /*
  * We cannot decide in this function whether we are in the work tree or
  * not, since the config can only be read _after_ this function was called.
@@ -627,10 +649,11 @@ static dev_t get_device_or_die(const char *path, const char *prefix, int prefix_
 static const char *setup_git_directory_gently_1(int *nongit_ok)
 {
        const char *env_ceiling_dirs = getenv(CEILING_DIRECTORIES_ENVIRONMENT);
+       struct string_list ceiling_dirs = STRING_LIST_INIT_DUP;
        static char cwd[PATH_MAX+1];
        const char *gitdirenv, *ret;
        char *gitfile;
-       int len, offset, offset_parent, ceil_offset;
+       int len, offset, offset_parent, ceil_offset = -1;
        dev_t current_device = 0;
        int one_filesystem = 1;
 
@@ -655,7 +678,14 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
        if (gitdirenv)
                return setup_explicit_git_dir(gitdirenv, cwd, len, nongit_ok);
 
-       ceil_offset = longest_ancestor_length(cwd, env_ceiling_dirs);
+       if (env_ceiling_dirs) {
+               string_list_split(&ceiling_dirs, env_ceiling_dirs, PATH_SEP, -1);
+               filter_string_list(&ceiling_dirs, 0,
+                                  canonicalize_ceiling_entry, NULL);
+               ceil_offset = longest_ancestor_length(cwd, &ceiling_dirs);
+               string_list_clear(&ceiling_dirs, 0);
+       }
+
        if (ceil_offset < 0 && has_dos_drive_prefix(cwd))
                ceil_offset = 1;
 
index 397e6cfa7db82bdb17f7cdbe4662a1607c0773af..480173fe6dbee5428e3b135ff27ba7551c527ad8 100644 (file)
@@ -145,26 +145,6 @@ void string_list_remove_empty_items(struct string_list *list, int free_util) {
        filter_string_list(list, free_util, item_is_not_empty, NULL);
 }
 
-char *string_list_longest_prefix(const struct string_list *prefixes,
-                                const char *string)
-{
-       int i, max_len = -1;
-       char *retval = NULL;
-
-       for (i = 0; i < prefixes->nr; i++) {
-               char *prefix = prefixes->items[i].string;
-               if (!prefixcmp(string, prefix)) {
-                       int len = strlen(prefix);
-                       if (len > max_len) {
-                               retval = prefix;
-                               max_len = len;
-                       }
-               }
-       }
-
-       return retval;
-}
-
 void string_list_clear(struct string_list *list, int free_util)
 {
        if (list->items) {
index c50b0d0deac086cd5a50a5c021103a5f5e76c1cd..db1284861adb707b675714edc1ecacf9357f6661 100644 (file)
@@ -45,15 +45,6 @@ void filter_string_list(struct string_list *list, int free_util,
  */
 void string_list_remove_empty_items(struct string_list *list, int free_util);
 
-/*
- * Return the longest string in prefixes that is a prefix (in the
- * sense of prefixcmp()) of string, or NULL if no such prefix exists.
- * This function does not require the string_list to be sorted (it
- * does a linear search).
- */
-char *string_list_longest_prefix(const struct string_list *prefixes, const char *string);
-
-
 /* Use these functions only on sorted lists: */
 int string_list_has_string(const struct string_list *list, const char *string);
 int string_list_find_insert_index(const struct string_list *list, const char *string,
index 3025418ff57c8c16cd11dd0db4f9d442743118fa..5c6de8169bfc02fc280d2dcb8cf34a912f0b0f6a 100644 (file)
@@ -13,6 +13,7 @@ TAR ?= $(TAR)
 RM ?= rm -f
 PROVE ?= prove
 DEFAULT_TEST_TARGET ?= test
+TEST_LINT ?= test-lint-duplicates test-lint-executable
 
 # Shell quote;
 SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
index 0f76f6cdc06b88c3e099c64cab76bfe7a019f8db..ae8883a07514c47b0568c9323698e879b38703e5 100644 (file)
@@ -14,12 +14,14 @@ export GIT_TEXTDOMAINDIR GIT_PO_PATH
 if test_have_prereq GETTEXT && ! test_have_prereq GETTEXT_POISON
 then
        # is_IS.UTF-8 on Solaris and FreeBSD, is_IS.utf8 on Debian
-       is_IS_locale=$(locale -a | sed -n '/^is_IS\.[uU][tT][fF]-*8$/{
+       is_IS_locale=$(locale -a 2>/dev/null |
+               sed -n '/^is_IS\.[uU][tT][fF]-*8$/{
                p
                q
        }')
        # is_IS.ISO8859-1 on Solaris and FreeBSD, is_IS.iso88591 on Debian
-       is_IS_iso_locale=$(locale -a | sed -n '/^is_IS\.[iI][sS][oO]8859-*1$/{
+       is_IS_iso_locale=$(locale -a 2>/dev/null |
+               sed -n '/^is_IS\.[iI][sS][oO]8859-*1$/{
                p
                q
        }')
index ec6c1b3f8a7eac0e1734883a0ad2f2d68f11bf96..5378787e1b23bf18796c28c33533f677b389289c 100755 (executable)
@@ -3,7 +3,12 @@
 test_description='respect crlf in git archive'
 
 . ./test-lib.sh
-UNZIP=${UNZIP:-unzip}
+GIT_UNZIP=${GIT_UNZIP:-unzip}
+
+test_lazy_prereq UNZIP '
+       "$GIT_UNZIP" -v
+       test $? -ne 127
+'
 
 test_expect_success setup '
 
@@ -26,18 +31,11 @@ test_expect_success 'tar archive' '
 
 '
 
-"$UNZIP" -v >/dev/null 2>&1
-if [ $? -eq 127 ]; then
-       say "Skipping ZIP test, because unzip was not found"
-else
-       test_set_prereq UNZIP
-fi
-
 test_expect_success UNZIP 'zip archive' '
 
        git archive --format=zip HEAD >test.zip &&
 
-       ( mkdir unzipped && cd unzipped && unzip ../test.zip ) &&
+       ( mkdir unzipped && cd unzipped && "$GIT_UNZIP" ../test.zip ) &&
 
        test_cmp sample unzipped/sample
 
index 4ef2345982fe0e0c175ed67edcb20b04c81b9680..09a42a428e1d286c5ab9e1003d49481ef6df3e44 100755 (executable)
@@ -93,47 +93,32 @@ norm_path /d1/s1//../s2/../../d2 /d2 POSIX
 norm_path /d1/.../d2 /d1/.../d2 POSIX
 norm_path /d1/..././../d2 /d1/d2 POSIX
 
-ancestor / "" -1
 ancestor / / -1
-ancestor /foo "" -1
-ancestor /foo : -1
-ancestor /foo ::. -1
-ancestor /foo ::..:: -1
 ancestor /foo / 0
 ancestor /foo /fo -1
 ancestor /foo /foo -1
-ancestor /foo /foo/ -1
 ancestor /foo /bar -1
-ancestor /foo /bar/ -1
 ancestor /foo /foo/bar -1
-ancestor /foo /foo:/bar/ -1
-ancestor /foo /foo/:/bar/ -1
-ancestor /foo /foo::/bar/ -1
-ancestor /foo /:/foo:/bar/ 0
-ancestor /foo /foo:/:/bar/ 0
-ancestor /foo /:/bar/:/foo 0
-ancestor /foo/bar "" -1
+ancestor /foo /foo:/bar -1
+ancestor /foo /:/foo:/bar 0
+ancestor /foo /foo:/:/bar 0
+ancestor /foo /:/bar:/foo 0
 ancestor /foo/bar / 0
 ancestor /foo/bar /fo -1
-ancestor /foo/bar foo -1
 ancestor /foo/bar /foo 4
-ancestor /foo/bar /foo/ 4
 ancestor /foo/bar /foo/ba -1
 ancestor /foo/bar /:/fo 0
 ancestor /foo/bar /foo:/foo/ba 4
 ancestor /foo/bar /bar -1
-ancestor /foo/bar /bar/ -1
-ancestor /foo/bar /fo: -1
-ancestor /foo/bar :/fo -1
-ancestor /foo/bar /foo:/bar/ 4
-ancestor /foo/bar /:/foo:/bar/ 4
-ancestor /foo/bar /foo:/:/bar/ 4
-ancestor /foo/bar /:/bar/:/fo 0
-ancestor /foo/bar /:/bar/ 0
-ancestor /foo/bar .:/foo/. 4
-ancestor /foo/bar .:/foo/.:.: 4
-ancestor /foo/bar /foo/./:.:/bar 4
-ancestor /foo/bar .:/bar -1
+ancestor /foo/bar /fo -1
+ancestor /foo/bar /foo:/bar 4
+ancestor /foo/bar /:/foo:/bar 4
+ancestor /foo/bar /foo:/:/bar 4
+ancestor /foo/bar /:/bar:/fo 0
+ancestor /foo/bar /:/bar 0
+ancestor /foo/bar /foo 4
+ancestor /foo/bar /foo:/bar 4
+ancestor /foo/bar /bar -1
 
 test_expect_success 'strip_path_suffix' '
        test c:/msysgit = $(test-path-utils strip_path_suffix \
index 41c8826a74db9a5c34ad3365f4875f6317a5bca0..dbfc05ebdc3990bf4ea5b0163afb4c6a9e698fa7 100755 (executable)
@@ -17,14 +17,6 @@ test_split () {
        "
 }
 
-test_longest_prefix () {
-       test "$(test-string-list longest_prefix "$1" "$2")" = "$3"
-}
-
-test_no_longest_prefix () {
-       test_must_fail test-string-list longest_prefix "$1" "$2"
-}
-
 test_split "foo:bar:baz" ":" "-1" <<EOF
 3
 [0]: "foo"
@@ -96,26 +88,4 @@ test_expect_success "test remove_duplicates" '
        test a:b:c = "$(test-string-list remove_duplicates a:a:a:b:b:b:c:c:c)"
 '
 
-test_expect_success "test longest_prefix" '
-       test_no_longest_prefix - '' &&
-       test_no_longest_prefix - x &&
-       test_longest_prefix "" x "" &&
-       test_longest_prefix x x x &&
-       test_longest_prefix "" foo "" &&
-       test_longest_prefix : foo "" &&
-       test_longest_prefix f foo f &&
-       test_longest_prefix foo foobar foo &&
-       test_longest_prefix foo foo foo &&
-       test_no_longest_prefix bar foo &&
-       test_no_longest_prefix bar:bar foo &&
-       test_no_longest_prefix foobar foo &&
-       test_longest_prefix foo:bar foo foo &&
-       test_longest_prefix foo:bar bar bar &&
-       test_longest_prefix foo::bar foo foo &&
-       test_longest_prefix foo:foobar foo foo &&
-       test_longest_prefix foobar:foo foo foo &&
-       test_longest_prefix foo: bar "" &&
-       test_longest_prefix :foo bar ""
-'
-
 test_done
index e23ac0e69da8d3dba32f0d256a249a987356e825..1e2945ec7e397cf6b2e3b00bee0ca1df40a0e6a9 100755 (executable)
@@ -111,19 +111,19 @@ test_expect_success 'read-tree' '
 
 test_expect_success 'alias expansion' '
        (
-               git config alias.ss status &&
+               git config alias.test-status-alias status &&
                cd dir &&
                git status &&
-               git ss
+               git test-status-alias
        )
 '
 
 test_expect_success NOT_MINGW '!alias expansion' '
        pwd >expect &&
        (
-               git config alias.test !pwd &&
+               git config alias.test-alias-directory !pwd &&
                cd dir &&
-               git test >../actual
+               git test-alias-directory >../actual
        ) &&
        test_cmp expect actual
 '
@@ -131,9 +131,9 @@ test_expect_success NOT_MINGW '!alias expansion' '
 test_expect_success 'GIT_PREFIX for !alias' '
        printf "dir/" >expect &&
        (
-               git config alias.test "!sh -c \"printf \$GIT_PREFIX\"" &&
+               git config alias.test-alias-directory "!sh -c \"printf \$GIT_PREFIX\"" &&
                cd dir &&
-               git test >../actual
+               git test-alias-directory >../actual
        ) &&
        test_cmp expect actual
 '
index 1ae4d87c929ec55a66d44bb23aecea8a2aea4346..1a5a5f39fd94f9eb98824b3d84983782b9ff71bb 100755 (executable)
@@ -11,7 +11,8 @@ valid_ref() {
                prereq=$1
                shift
        esac
-       test_expect_success $prereq "ref name '$1' is valid${2:+ with options $2}" "
+       desc="ref name '$1' is valid${2:+ with options $2}"
+       test_expect_success $prereq "$desc" "
                git check-ref-format $2 '$1'
        "
 }
@@ -22,7 +23,8 @@ invalid_ref() {
                prereq=$1
                shift
        esac
-       test_expect_success $prereq "ref name '$1' is invalid${2:+ with options $2}" "
+       desc="ref name '$1' is invalid${2:+ with options $2}"
+       test_expect_success $prereq "$desc" "
                test_must_fail git check-ref-format $2 '$1'
        "
 }
index ec35409f9cbe9bcdd3d21a6a5a15996b165d2fff..2a4a749b4fa3b07963a18b645d29ef774c01bbd1 100755 (executable)
@@ -62,5 +62,25 @@ test_expect_success 'can "commit -a" with an i-t-a entry' '
        git commit -a -m all
 '
 
+test_expect_success 'cache-tree invalidates i-t-a paths' '
+       git reset --hard &&
+       mkdir dir &&
+       : >dir/foo &&
+       git add dir/foo &&
+       git commit -m foo &&
+
+       : >dir/bar &&
+       git add -N dir/bar &&
+       git diff --cached --name-only >actual &&
+       echo dir/bar >expect &&
+       test_cmp expect actual &&
+
+       git write-tree >/dev/null &&
+
+       git diff --cached --name-only >actual &&
+       echo dir/bar >expect &&
+       test_cmp expect actual
+'
+
 test_done
 
index 06f63848eab384ae33eacd1fb46d5dc048143721..37bf5f13b07a632cb8e96e865a75b51f1b7844aa 100755 (executable)
@@ -474,7 +474,7 @@ test_expect_success 'rm of a conflicted populated submodule with a .git director
        git submodule update &&
        (cd submod &&
                rm .git &&
-               cp -a ../.git/modules/sub .git &&
+               cp -R ../.git/modules/sub .git &&
                GIT_WORK_TREE=. git config --unset core.worktree
        ) &&
        test_must_fail git merge conflict2 &&
@@ -508,7 +508,7 @@ test_expect_success 'rm of a populated submodule with a .git directory fails eve
        git submodule update &&
        (cd submod &&
                rm .git &&
-               cp -a ../.git/modules/sub .git &&
+               cp -R ../.git/modules/sub .git &&
                GIT_WORK_TREE=. git config --unset core.worktree
        ) &&
        test_must_fail git rm submod &&
@@ -606,7 +606,7 @@ test_expect_success 'rm of a populated nested submodule with a nested .git direc
        git submodule update --recursive &&
        (cd submod/subsubmod &&
                rm .git &&
-               cp -a ../../.git/modules/sub/modules/sub .git &&
+               cp -R ../../.git/modules/sub/modules/sub .git &&
                GIT_WORK_TREE=. git config --unset core.worktree
        ) &&
        test_must_fail git rm submod &&
index 16a4ca1d6061122cf7ed3abd68390e27794f79b0..90fd598c747482354c7fa1a9fa281c26c06e9de8 100755 (executable)
@@ -155,7 +155,7 @@ test_expect_failure 'additional command line cc (rfc822)' '
        git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
        git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch5 &&
        grep "^Cc: R E Cipient <rcipient@example.com>,\$" patch5 &&
-       grep "^ *"S. E. Cipient" <scipient@example.com>\$" patch5
+       grep "^ *\"S. E. Cipient\" <scipient@example.com>\$" patch5
 '
 
 test_expect_success 'command line headers' '
@@ -183,7 +183,7 @@ test_expect_success 'command line To: header (ascii)' '
 test_expect_failure 'command line To: header (rfc822)' '
 
        git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
-       grep "^To: "R. E. Cipient" <rcipient@example.com>\$" patch8
+       grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" patch8
 '
 
 test_expect_failure 'command line To: header (rfc2047)' '
@@ -203,7 +203,7 @@ test_expect_failure 'configuration To: header (rfc822)' '
 
        git config format.to "R. E. Cipient <rcipient@example.com>" &&
        git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
-       grep "^To: "R. E. Cipient" <rcipient@example.com>\$" patch9
+       grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" patch9
 '
 
 test_expect_failure 'configuration To: header (rfc2047)' '
index 6872ba1a42ce289c0983b1ed62f05defb493bf49..5493500ef15d2f561bd14ca0bdf5f519ec6f49be 100755 (executable)
@@ -120,6 +120,30 @@ test_expect_success 'shortlog from non-git directory' '
        test_cmp expect out
 '
 
+test_expect_success 'shortlog should add newline when input line matches wraplen' '
+       cat >expect <<\EOF &&
+A U Thor (2):
+      bbbbbbbbbbbbbbbbbb: bbbbbbbb bbb bbbb bbbbbbb bb bbbb bbb bbbbb bbbbbb
+      aaaaaaaaaaaaaaaaaaaaaa: aaaaaa aaaaaaaaaa aaaa aaaaaaaa aa aaaa aa aaa
+
+EOF
+       git shortlog -w >out <<\EOF &&
+commit 0000000000000000000000000000000000000001
+Author: A U Thor <author@example.com>
+Date:   Thu Apr 7 15:14:13 2005 -0700
+
+    aaaaaaaaaaaaaaaaaaaaaa: aaaaaa aaaaaaaaaa aaaa aaaaaaaa aa aaaa aa aaa
+
+commit 0000000000000000000000000000000000000002
+Author: A U Thor <author@example.com>
+Date:   Thu Apr 7 15:14:13 2005 -0700
+
+    bbbbbbbbbbbbbbbbbb: bbbbbbbb bbb bbbb bbbbbbb bb bbbb bbb bbbbb bbbbbb
+
+EOF
+       test_cmp expect out
+'
+
 iconvfromutf8toiso88591() {
        printf "%s" "$*" | iconv -f UTF-8 -t ISO8859-1
 }
index a343bf6c629f8e6acaf7559d3168a97fcce9d286..fa686b887d6b49ab8e6d30893501744645f72a91 100755 (executable)
@@ -280,6 +280,16 @@ test_expect_success 'log --graph with merge' '
        test_cmp expect actual
 '
 
+test_expect_success 'log --raw --graph -m with merge' '
+       git log --raw --graph --oneline -m master | head -n 500 >actual &&
+       grep "initial" actual
+'
+
+test_expect_success 'diff-tree --graph' '
+       git diff-tree --graph master^ | head -n 500 >actual &&
+       grep "one" actual
+'
+
 cat > expect <<\EOF
 *   commit master
 |\  Merge: A B
index ecf00edab2079099e201237c1936cf715148a684..e7c240fc1f8333c933f22bc1af6bf57eb9ae27cb 100755 (executable)
@@ -25,32 +25,11 @@ commit id embedding:
 '
 
 . ./test-lib.sh
-UNZIP=${UNZIP:-unzip}
 GZIP=${GZIP:-gzip}
 GUNZIP=${GUNZIP:-gzip -d}
 
 SUBSTFORMAT=%H%n
 
-check_zip() {
-       zipfile=$1.zip
-       listfile=$1.lst
-       dir=$1
-       dir_with_prefix=$dir/$2
-
-       test_expect_success UNZIP " extract ZIP archive" "
-               (mkdir $dir && cd $dir && $UNZIP ../$zipfile)
-       "
-
-       test_expect_success UNZIP " validate filenames" "
-               (cd ${dir_with_prefix}a && find .) | sort >$listfile &&
-               test_cmp a.lst $listfile
-       "
-
-       test_expect_success UNZIP " validate file contents" "
-               diff -r a ${dir_with_prefix}a
-       "
-}
-
 test_expect_success \
     'populate workdir' \
     'mkdir a b c &&
@@ -201,61 +180,11 @@ test_expect_success \
       test_cmp a/substfile2 g/prefix/a/substfile2
 '
 
-$UNZIP -v >/dev/null 2>&1
-if [ $? -eq 127 ]; then
-       say "Skipping ZIP tests, because unzip was not found"
-else
-       test_set_prereq UNZIP
-fi
-
-test_expect_success \
-    'git archive --format=zip' \
-    'git archive --format=zip HEAD >d.zip'
-
-check_zip d
-
-test_expect_success \
-    'git archive --format=zip in a bare repo' \
-    '(cd bare.git && git archive --format=zip HEAD) >d1.zip'
-
-test_expect_success \
-    'git archive --format=zip vs. the same in a bare repo' \
-    'test_cmp d.zip d1.zip'
-
-test_expect_success 'git archive --format=zip with --output' \
-    'git archive --format=zip --output=d2.zip HEAD &&
-    test_cmp d.zip d2.zip'
-
-test_expect_success 'git archive with --output, inferring format' '
-       git archive --output=d3.zip HEAD &&
-       test_cmp d.zip d3.zip
-'
-
 test_expect_success 'git archive with --output, override inferred format' '
        git archive --format=tar --output=d4.zip HEAD &&
        test_cmp b.tar d4.zip
 '
 
-test_expect_success \
-    'git archive --format=zip with prefix' \
-    'git archive --format=zip --prefix=prefix/ HEAD >e.zip'
-
-check_zip e prefix/
-
-test_expect_success 'git archive -0 --format=zip on large files' '
-       test_config core.bigfilethreshold 1 &&
-       git archive -0 --format=zip HEAD >large.zip
-'
-
-check_zip large
-
-test_expect_success 'git archive --format=zip on large files' '
-       test_config core.bigfilethreshold 1 &&
-       git archive --format=zip HEAD >large-compressed.zip
-'
-
-check_zip large-compressed
-
 test_expect_success \
     'git archive --list outside of a git repo' \
     'GIT_DIR=some/non-existing/directory git archive --list'
diff --git a/t/t5003-archive-zip.sh b/t/t5003-archive-zip.sh
new file mode 100755 (executable)
index 0000000..7cfe9ca
--- /dev/null
@@ -0,0 +1,131 @@
+#!/bin/sh
+
+test_description='git archive --format=zip test'
+
+. ./test-lib.sh
+GIT_UNZIP=${GIT_UNZIP:-unzip}
+
+SUBSTFORMAT=%H%n
+
+test_lazy_prereq UNZIP '
+       "$GIT_UNZIP" -v
+       test $? -ne 127
+'
+
+test_lazy_prereq UNZIP_SYMLINKS '
+       (
+               mkdir unzip-symlinks &&
+               cd unzip-symlinks &&
+               "$GIT_UNZIP" "$TEST_DIRECTORY"/t5003/infozip-symlinks.zip &&
+               test -h symlink
+       )
+'
+
+check_zip() {
+       zipfile=$1.zip
+       listfile=$1.lst
+       dir=$1
+       dir_with_prefix=$dir/$2
+
+       test_expect_success UNZIP " extract ZIP archive" '
+               (mkdir $dir && cd $dir && "$GIT_UNZIP" ../$zipfile)
+       '
+
+       test_expect_success UNZIP " validate filenames" "
+               (cd ${dir_with_prefix}a && find .) | sort >$listfile &&
+               test_cmp a.lst $listfile
+       "
+
+       test_expect_success UNZIP " validate file contents" "
+               diff -r a ${dir_with_prefix}a
+       "
+}
+
+test_expect_success \
+    'populate workdir' \
+    'mkdir a b c &&
+     echo simple textfile >a/a &&
+     mkdir a/bin &&
+     cp /bin/sh a/bin &&
+     printf "A\$Format:%s\$O" "$SUBSTFORMAT" >a/substfile1 &&
+     printf "A not substituted O" >a/substfile2 &&
+     (p=long_path_to_a_file && cd a &&
+      for depth in 1 2 3 4 5; do mkdir $p && cd $p; done &&
+      echo text >file_with_long_path)
+'
+
+test_expect_success SYMLINKS,UNZIP_SYMLINKS 'add symlink' '
+       ln -s a a/symlink_to_a
+'
+
+test_expect_success 'prepare file list' '
+       (cd a && find .) | sort >a.lst
+'
+
+test_expect_success \
+    'add ignored file' \
+    'echo ignore me >a/ignored &&
+     echo ignored export-ignore >.git/info/attributes'
+
+test_expect_success \
+    'add files to repository' \
+    'find a -type f | xargs git update-index --add &&
+     find a -type l | xargs git update-index --add &&
+     treeid=`git write-tree` &&
+     echo $treeid >treeid &&
+     git update-ref HEAD $(TZ=GMT GIT_COMMITTER_DATE="2005-05-27 22:00:00" \
+     git commit-tree $treeid </dev/null)'
+
+test_expect_success \
+    'create bare clone' \
+    'git clone --bare . bare.git &&
+     cp .git/info/attributes bare.git/info/attributes'
+
+test_expect_success \
+    'remove ignored file' \
+    'rm a/ignored'
+
+test_expect_success \
+    'git archive --format=zip' \
+    'git archive --format=zip HEAD >d.zip'
+
+check_zip d
+
+test_expect_success \
+    'git archive --format=zip in a bare repo' \
+    '(cd bare.git && git archive --format=zip HEAD) >d1.zip'
+
+test_expect_success \
+    'git archive --format=zip vs. the same in a bare repo' \
+    'test_cmp d.zip d1.zip'
+
+test_expect_success 'git archive --format=zip with --output' \
+    'git archive --format=zip --output=d2.zip HEAD &&
+    test_cmp d.zip d2.zip'
+
+test_expect_success 'git archive with --output, inferring format' '
+       git archive --output=d3.zip HEAD &&
+       test_cmp d.zip d3.zip
+'
+
+test_expect_success \
+    'git archive --format=zip with prefix' \
+    'git archive --format=zip --prefix=prefix/ HEAD >e.zip'
+
+check_zip e prefix/
+
+test_expect_success 'git archive -0 --format=zip on large files' '
+       test_config core.bigfilethreshold 1 &&
+       git archive -0 --format=zip HEAD >large.zip
+'
+
+check_zip large
+
+test_expect_success 'git archive --format=zip on large files' '
+       test_config core.bigfilethreshold 1 &&
+       git archive --format=zip HEAD >large-compressed.zip
+'
+
+check_zip large-compressed
+
+test_done
diff --git a/t/t5003/infozip-symlinks.zip b/t/t5003/infozip-symlinks.zip
new file mode 100644 (file)
index 0000000..065728c
Binary files /dev/null and b/t/t5003/infozip-symlinks.zip differ
diff --git a/t/t5535-fetch-push-symref.sh b/t/t5535-fetch-push-symref.sh
new file mode 100755 (executable)
index 0000000..8ed58d2
--- /dev/null
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+test_description='avoiding conflicting update thru symref aliasing'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+       test_commit one &&
+       git clone . src &&
+       git clone src dst1 &&
+       git clone src dst2 &&
+       test_commit two &&
+       ( cd src && git pull )
+'
+
+test_expect_success 'push' '
+       (
+               cd src &&
+               git push ../dst1 "refs/remotes/*:refs/remotes/*"
+       ) &&
+       git ls-remote src "refs/remotes/*" >expect &&
+       git ls-remote dst1 "refs/remotes/*" >actual &&
+       test_cmp expect actual &&
+       ( cd src && git symbolic-ref refs/remotes/origin/HEAD ) >expect &&
+       ( cd dst1 && git symbolic-ref refs/remotes/origin/HEAD ) >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'fetch' '
+       (
+               cd dst2 &&
+               git fetch ../src "refs/remotes/*:refs/remotes/*"
+       ) &&
+       git ls-remote src "refs/remotes/*" >expect &&
+       git ls-remote dst2 "refs/remotes/*" >actual &&
+       test_cmp expect actual &&
+       ( cd src && git symbolic-ref refs/remotes/origin/HEAD ) >expect &&
+       ( cd dst2 && git symbolic-ref refs/remotes/origin/HEAD ) >actual &&
+       test_cmp expect actual
+'
+
+test_done
index ee06d2864949de71b000402fda4378c9b483fe72..4435693bb2ca48d053003c87fccd8f8612d8b4a9 100755 (executable)
@@ -37,6 +37,16 @@ test_expect_success \
 
 test_expect_success \
     'successful clone must leave the directory' \
-    'cd bar'
+    'test -d bar'
+
+test_expect_success 'failed clone --separate-git-dir should not leave any directories' '
+       mkdir foo/.git/objects.bak/ &&
+       mv foo/.git/objects/* foo/.git/objects.bak/ &&
+       test_must_fail git clone --separate-git-dir gitdir foo worktree &&
+       test_must_fail test -e gitdir &&
+       test_must_fail test -e worktree &&
+       mv foo/.git/objects.bak/* foo/.git/objects/ &&
+       rmdir foo/.git/objects.bak
+'
 
 test_done
index 518944653477225da94db0826d77936eaa0d249a..f5a79b13aecf4020b8a453f5f27568ce4f88bbbc 100755 (executable)
@@ -1066,12 +1066,12 @@ test_expect_success GPG \
 '
 
 # usage with rfc1991 signatures
-echo "rfc1991" > gpghome/gpg.conf
 get_tag_header rfc1991-signed-tag $commit commit $time >expect
 echo "RFC1991 signed tag" >>expect
 echo '-----BEGIN PGP MESSAGE-----' >>expect
 test_expect_success GPG \
        'creating a signed tag with rfc1991' '
+       echo "rfc1991" >gpghome/gpg.conf &&
        git tag -s -m "RFC1991 signed tag" rfc1991-signed-tag $commit &&
        get_tag_msg rfc1991-signed-tag >actual &&
        test_cmp expect actual
@@ -1085,6 +1085,7 @@ chmod +x fakeeditor
 
 test_expect_success GPG \
        'reediting a signed tag body omits signature' '
+       echo "rfc1991" >gpghome/gpg.conf &&
        echo "RFC1991 signed tag" >expect &&
        GIT_EDITOR=./fakeeditor git tag -f -s rfc1991-signed-tag $commit &&
        test_cmp expect actual
@@ -1092,11 +1093,13 @@ test_expect_success GPG \
 
 test_expect_success GPG \
        'verifying rfc1991 signature' '
+       echo "rfc1991" >gpghome/gpg.conf &&
        git tag -v rfc1991-signed-tag
 '
 
 test_expect_success GPG \
        'list tag with rfc1991 signature' '
+       echo "rfc1991" >gpghome/gpg.conf &&
        echo "rfc1991-signed-tag RFC1991 signed tag" >expect &&
        git tag -l -n1 rfc1991-signed-tag >actual &&
        test_cmp expect actual &&
diff --git a/t/t7061-wtstatus-ignore.sh b/t/t7061-wtstatus-ignore.sh
new file mode 100755 (executable)
index 0000000..0da1214
--- /dev/null
@@ -0,0 +1,146 @@
+#!/bin/sh
+
+test_description='git-status ignored files'
+
+. ./test-lib.sh
+
+cat >expected <<\EOF
+?? .gitignore
+?? actual
+?? expected
+?? untracked/
+EOF
+
+test_expect_success 'status untracked directory with --ignored' '
+       echo "ignored" >.gitignore &&
+       mkdir untracked &&
+       : >untracked/ignored &&
+       : >untracked/uncommitted &&
+       git status --porcelain --ignored >actual &&
+       test_cmp expected actual
+'
+
+cat >expected <<\EOF
+?? .gitignore
+?? actual
+?? expected
+?? untracked/uncommitted
+!! untracked/ignored
+EOF
+
+test_expect_success 'status untracked directory with --ignored -u' '
+       git status --porcelain --ignored -u >actual &&
+       test_cmp expected actual
+'
+
+cat >expected <<\EOF
+?? .gitignore
+?? actual
+?? expected
+!! ignored/
+EOF
+
+test_expect_success 'status ignored directory with --ignore' '
+       rm -rf untracked &&
+       mkdir ignored &&
+       : >ignored/uncommitted &&
+       git status --porcelain --ignored >actual &&
+       test_cmp expected actual
+'
+
+cat >expected <<\EOF
+?? .gitignore
+?? actual
+?? expected
+!! ignored/uncommitted
+EOF
+
+test_expect_success 'status ignored directory with --ignore -u' '
+       git status --porcelain --ignored -u >actual &&
+       test_cmp expected actual
+'
+
+cat >expected <<\EOF
+?? .gitignore
+?? actual
+?? expected
+!! untracked-ignored/
+EOF
+
+test_expect_success 'status untracked directory with ignored files with --ignore' '
+       rm -rf ignored &&
+       mkdir untracked-ignored &&
+       mkdir untracked-ignored/test &&
+       : >untracked-ignored/ignored &&
+       : >untracked-ignored/test/ignored &&
+       git status --porcelain --ignored >actual &&
+       test_cmp expected actual
+'
+
+cat >expected <<\EOF
+?? .gitignore
+?? actual
+?? expected
+!! untracked-ignored/ignored
+!! untracked-ignored/test/ignored
+EOF
+
+test_expect_success 'status untracked directory with ignored files with --ignore -u' '
+       git status --porcelain --ignored -u >actual &&
+       test_cmp expected actual
+'
+
+cat >expected <<\EOF
+?? .gitignore
+?? actual
+?? expected
+EOF
+
+test_expect_success 'status ignored tracked directory with --ignore' '
+       rm -rf untracked-ignored &&
+       mkdir tracked &&
+       : >tracked/committed &&
+       git add tracked/committed &&
+       git commit -m. &&
+       echo "tracked" >.gitignore &&
+       git status --porcelain --ignored >actual &&
+       test_cmp expected actual
+'
+
+cat >expected <<\EOF
+?? .gitignore
+?? actual
+?? expected
+EOF
+
+test_expect_success 'status ignored tracked directory with --ignore -u' '
+       git status --porcelain --ignored -u >actual &&
+       test_cmp expected actual
+'
+
+cat >expected <<\EOF
+?? .gitignore
+?? actual
+?? expected
+!! tracked/
+EOF
+
+test_expect_success 'status ignored tracked directory and uncommitted file with --ignore' '
+       : >tracked/uncommitted &&
+       git status --porcelain --ignored >actual &&
+       test_cmp expected actual
+'
+
+cat >expected <<\EOF
+?? .gitignore
+?? actual
+?? expected
+!! tracked/uncommitted
+EOF
+
+test_expect_success 'status ignored tracked directory and uncommitted file with --ignore -u' '
+       git status --porcelain --ignored -u >actual &&
+       test_cmp expected actual
+'
+
+test_done
index 5b4b694f1801f5c2284346f882cb496df9e7d74e..357375151d79d03d11275875dd10ceea42a3ba47 100755 (executable)
@@ -167,5 +167,19 @@ test_expect_success 'with failing hook (--no-verify)' '
 
 '
 
+test_expect_success 'with failing hook (merge)' '
+
+       git checkout -B other HEAD@{1} &&
+       echo "more" >> file &&
+       git add file &&
+       rm -f "$HOOK" &&
+       git commit -m other &&
+       write_script "$HOOK" <<-EOF
+       exit 1
+       EOF
+       git checkout - &&
+       test_must_fail git merge other
+
+'
 
 test_done
index 4f2dfe0e3d00010679c77e66c81b3ab4509e2522..2d2f016f6f8b151f10b08e4419dc6d3bdef3d0a8 100755 (executable)
@@ -12,9 +12,13 @@ then
        test_done
 fi
 
-# We override svnrdump by placing a symlink to the svnrdump-emulator in .
-export PATH="$HOME:$PATH"
-ln -sf $GIT_BUILD_DIR/contrib/svn-fe/svnrdump_sim.py "$HOME/svnrdump"
+# Override svnrdump with our simulator
+PATH="$HOME:$PATH"
+export PATH PYTHON_PATH GIT_BUILD_DIR
+
+write_script "$HOME/svnrdump" <<\EOF
+exec "$PYTHON_PATH" "$GIT_BUILD_DIR/contrib/svn-fe/svnrdump_sim.py" "$@"
+EOF
 
 init_git () {
        rm -fr .git &&
@@ -32,8 +36,8 @@ fi
 
 test_debug '
        git --version
-       which git
-       which svnrdump
+       type git
+       type svnrdump
 '
 
 test_expect_success REMOTE_SVN 'simple fetch' '
index 69934b2e775c8591ca209c9275abc40b921ecab6..3fb3368903686c8588c51e881beaee1f29808575 100755 (executable)
@@ -25,8 +25,9 @@ GIT_DIR=$PWD/.git
 export CVSROOT CVSWORK GIT_DIR
 
 rm -rf "$CVSROOT" "$CVSWORK"
-mkdir "$CVSROOT" &&
+
 cvs init &&
+test -d "$CVSROOT" &&
 cvs -Q co -d "$CVSWORK" . &&
 echo >empty &&
 git add empty &&
index 3a8e7d3f5aa1dc6a4d13467babd96a293ee1bb6e..86dfee2e4f93750aa72c0b24df57c77faa091aa7 100755 (executable)
@@ -40,7 +40,7 @@ check_snapshot () {
        echo "basename=$basename"
        grep "filename=.*$basename.tar" gitweb.headers >/dev/null 2>&1 &&
        "$TAR" tf gitweb.body >file_list &&
-       ! grep -v "^$prefix/" file_list
+       ! grep -v -e "^$prefix$" -e "^$prefix/" -e "^pax_global_header$" file_list
 }
 
 test_expect_success setup '
index 0c2fc3ea1a28268e216a3a93ed12b09f0cf55ef2..34fbc900055d9bbaa9e533063b7c69e384e07e5a 100755 (executable)
@@ -26,10 +26,8 @@ test_expect_success 'init depot' '
                line7
                line8
                EOF
-               cp filek fileko &&
-               sed -i "s/Revision/Revision: do not scrub me/" fileko
-               cp fileko file_text &&
-               sed -i "s/Id/Id: do not scrub me/" file_text
+               sed "s/Revision/Revision: do not scrub me/" <filek >fileko &&
+               sed "s/Id/Id: do not scrub me/" <fileko >file_text &&
                p4 add -t text+k filek &&
                p4 submit -d "filek" &&
                p4 add -t text+ko fileko &&
@@ -88,7 +86,8 @@ test_expect_success 'edit far away from RCS lines' '
        (
                cd "$git" &&
                git config git-p4.skipSubmitEdit true &&
-               sed -i "s/^line7/line7 edit/" filek &&
+               sed "s/^line7/line7 edit/" <filek >filek.tmp &&
+               mv -f filek.tmp filek &&
                git commit -m "filek line7 edit" filek &&
                git p4 submit &&
                scrub_k_check filek
@@ -105,7 +104,8 @@ test_expect_success 'edit near RCS lines' '
                cd "$git" &&
                git config git-p4.skipSubmitEdit true &&
                git config git-p4.attemptRCSCleanup true &&
-               sed -i "s/^line4/line4 edit/" filek &&
+               sed "s/^line4/line4 edit/" <filek >filek.tmp &&
+               mv -f filek.tmp filek &&
                git commit -m "filek line4 edit" filek &&
                git p4 submit &&
                scrub_k_check filek
@@ -122,7 +122,8 @@ test_expect_success 'edit keyword lines' '
                cd "$git" &&
                git config git-p4.skipSubmitEdit true &&
                git config git-p4.attemptRCSCleanup true &&
-               sed -i "/Revision/d" filek &&
+               sed "/Revision/d" <filek >filek.tmp &&
+               mv -f filek.tmp filek &&
                git commit -m "filek remove Revision line" filek &&
                git p4 submit &&
                scrub_k_check filek
@@ -139,7 +140,8 @@ test_expect_success 'scrub ko files differently' '
                cd "$git" &&
                git config git-p4.skipSubmitEdit true &&
                git config git-p4.attemptRCSCleanup true &&
-               sed -i "s/^line4/line4 edit/" fileko &&
+               sed "s/^line4/line4 edit/" <fileko >fileko.tmp &&
+               mv -f fileko.tmp fileko &&
                git commit -m "fileko line4 edit" fileko &&
                git p4 submit &&
                scrub_ko_check fileko &&
@@ -189,12 +191,14 @@ test_expect_success 'do not scrub plain text' '
                cd "$git" &&
                git config git-p4.skipSubmitEdit true &&
                git config git-p4.attemptRCSCleanup true &&
-               sed -i "s/^line4/line4 edit/" file_text &&
+               sed "s/^line4/line4 edit/" <file_text >file_text.tmp &&
+               mv -f file_text.tmp file_text &&
                git commit -m "file_text line4 edit" file_text &&
                (
                        cd "$cli" &&
                        p4 open file_text &&
-                       sed -i "s/^line5/line5 p4 edit/" file_text &&
+                       sed "s/^line5/line5 p4 edit/" <file_text >file_text.tmp &&
+                       mv -f file_text.tmp file_text &&
                        p4 submit -d "file5 p4 edit"
                ) &&
                echo s | test_expect_code 1 git p4 submit &&
index f50f8341d40c6ec87565d01a263d97209fb68680..fc42d3a9c4f7e0bf98b657826163a04f2905f366 100644 (file)
@@ -85,6 +85,7 @@ unset VISUAL EMAIL LANGUAGE COLUMNS $("$PERL_PATH" -e '
                .*_TEST
                PROVE
                VALGRIND
+               UNZIP
                PERF_AGGREGATING_LATER
        ));
        my @vars = grep(/^GIT_/ && !/^GIT_($ok)/o, @env);
@@ -128,6 +129,7 @@ fi
 unset CDPATH
 
 unset GREP_OPTIONS
+unset UNZIP
 
 case $(echo $GIT_TRACE |tr "[A-Z]" "[a-z]") in
 1|2|true)
index 10172aee18292b50aa24b3a8694b5383c1cfd98e..1fb373f25bac42648a0779ffd42f1ae0eaec359a 100755 (executable)
@@ -31,7 +31,7 @@ sub finish_child {
        } elsif ($? & 127) {
                my $code = $? & 127;
                warn "died of signal $code";
-               return $code - 128;
+               return $code + 128;
        } else {
                return $? >> 8;
        }
index 3bc20e91da561f4edd5c3eddb0988735759234e4..0092cbf3540e2fdfd2e882461ba39ba2a833b672 100644 (file)
@@ -1,4 +1,32 @@
 #include "cache.h"
+#include "string-list.h"
+
+/*
+ * A "string_list_each_func_t" function that normalizes an entry from
+ * GIT_CEILING_DIRECTORIES.  If the path is unusable for some reason,
+ * die with an explanation.
+ */
+static int normalize_ceiling_entry(struct string_list_item *item, void *unused)
+{
+       const char *ceil = item->string;
+       int len = strlen(ceil);
+       char buf[PATH_MAX+1];
+
+       if (len == 0)
+               die("Empty path is not supported");
+       if (len > PATH_MAX)
+               die("Path \"%s\" is too long", ceil);
+       if (!is_absolute_path(ceil))
+               die("Path \"%s\" is not absolute", ceil);
+       if (normalize_path_copy(buf, ceil) < 0)
+               die("Path \"%s\" could not be normalized", ceil);
+       len = strlen(buf);
+       if (len > 1 && buf[len-1] == '/')
+               die("Normalized path \"%s\" ended with slash", buf);
+       free(item->string);
+       item->string = xstrdup(buf);
+       return 1;
+}
 
 int main(int argc, char **argv)
 {
@@ -30,7 +58,28 @@ int main(int argc, char **argv)
        }
 
        if (argc == 4 && !strcmp(argv[1], "longest_ancestor_length")) {
-               int len = longest_ancestor_length(argv[2], argv[3]);
+               int len;
+               struct string_list ceiling_dirs = STRING_LIST_INIT_DUP;
+               char *path = xstrdup(argv[2]);
+
+               /*
+                * We have to normalize the arguments because under
+                * Windows, bash mangles arguments that look like
+                * absolute POSIX paths or colon-separate lists of
+                * absolute POSIX paths into DOS paths (e.g.,
+                * "/foo:/foo/bar" might be converted to
+                * "D:\Src\msysgit\foo;D:\Src\msysgit\foo\bar"),
+                * whereas longest_ancestor_length() requires paths
+                * that use forward slashes.
+                */
+               if (normalize_path_copy(path, path))
+                       die("Path \"%s\" could not be normalized", argv[2]);
+               string_list_split(&ceiling_dirs, argv[3], PATH_SEP, -1);
+               filter_string_list(&ceiling_dirs, 0,
+                                  normalize_ceiling_entry, NULL);
+               len = longest_ancestor_length(path, &ceiling_dirs);
+               string_list_clear(&ceiling_dirs, 0);
+               free(path);
                printf("%d\n", len);
                return 0;
        }
index 4693295a98ca713fa65eb9b67d50113ec97ecf71..00ce6c9a129674c1922e0c388366592c5ae7c8c7 100644 (file)
@@ -97,26 +97,6 @@ int main(int argc, char **argv)
                return 0;
        }
 
-       if (argc == 4 && !strcmp(argv[1], "longest_prefix")) {
-               /* arguments: <colon-separated-prefixes>|- <string> */
-               struct string_list prefixes = STRING_LIST_INIT_DUP;
-               int retval;
-               const char *prefix_string = argv[2];
-               const char *string = argv[3];
-               const char *match;
-
-               parse_string_list(&prefixes, prefix_string);
-               match = string_list_longest_prefix(&prefixes, string);
-               if (match) {
-                       printf("%s\n", match);
-                       retval = 0;
-               }
-               else
-                       retval = 1;
-               string_list_clear(&prefixes, 0);
-               return retval;
-       }
-
        fprintf(stderr, "%s: unknown function name: %s\n", argv[0],
                argv[1] ? argv[1] : "(there was none)");
        return 1;
diff --git a/utf8.c b/utf8.c
index 5c61bbe1131e7bbdd939c8b815bd5222b872e3fb..a4ee6650ef6c4c487c083aabf0a950b8ec317b09 100644 (file)
--- a/utf8.c
+++ b/utf8.c
@@ -323,7 +323,7 @@ static size_t display_mode_esc_sequence_len(const char *s)
  * If indent is negative, assume that already -indent columns have been
  * consumed (and no extra indent is necessary for the first line).
  */
-int strbuf_add_wrapped_text(struct strbuf *buf,
+void strbuf_add_wrapped_text(struct strbuf *buf,
                const char *text, int indent1, int indent2, int width)
 {
        int indent, w, assume_utf8 = 1;
@@ -332,7 +332,7 @@ int strbuf_add_wrapped_text(struct strbuf *buf,
 
        if (width <= 0) {
                strbuf_add_indented_text(buf, text, indent1, indent2);
-               return 1;
+               return;
        }
 
 retry:
@@ -356,14 +356,14 @@ int strbuf_add_wrapped_text(struct strbuf *buf,
                        if (w <= width || !space) {
                                const char *start = bol;
                                if (!c && text == start)
-                                       return w;
+                                       return;
                                if (space)
                                        start = space;
                                else
                                        strbuf_addchars(buf, ' ', indent);
                                strbuf_add(buf, start, text - start);
                                if (!c)
-                                       return w;
+                                       return;
                                space = text;
                                if (c == '\t')
                                        w |= 0x07;
@@ -405,13 +405,12 @@ int strbuf_add_wrapped_text(struct strbuf *buf,
        }
 }
 
-int strbuf_add_wrapped_bytes(struct strbuf *buf, const char *data, int len,
+void strbuf_add_wrapped_bytes(struct strbuf *buf, const char *data, int len,
                             int indent, int indent2, int width)
 {
        char *tmp = xstrndup(data, len);
-       int r = strbuf_add_wrapped_text(buf, tmp, indent, indent2, width);
+       strbuf_add_wrapped_text(buf, tmp, indent, indent2, width);
        free(tmp);
-       return r;
 }
 
 int is_encoding_utf8(const char *name)
diff --git a/utf8.h b/utf8.h
index 93ef60042c2fad93184b573f30e771ecddc842be..a214238bdd70c6b4eb41edf6626c5b396489ab50 100644 (file)
--- a/utf8.h
+++ b/utf8.h
@@ -9,9 +9,9 @@ int is_utf8(const char *text);
 int is_encoding_utf8(const char *name);
 int same_encoding(const char *, const char *);
 
-int strbuf_add_wrapped_text(struct strbuf *buf,
+void strbuf_add_wrapped_text(struct strbuf *buf,
                const char *text, int indent, int indent2, int width);
-int strbuf_add_wrapped_bytes(struct strbuf *buf, const char *data, int len,
+void strbuf_add_wrapped_bytes(struct strbuf *buf, const char *data, int len,
                             int indent, int indent2, int width);
 
 #ifndef NO_ICONV
index 68739aaa3b9e9e1a1bbbd43c75c9b5c244fb6c3e..bac59d2c41bae7441038b30728c696b6280f4c2d 100644 (file)
--- a/wrapper.c
+++ b/wrapper.c
@@ -229,7 +229,7 @@ int xmkstemp(char *template)
                int saved_errno = errno;
                const char *nonrelative_template;
 
-               if (!template[0])
+               if (strlen(template) != strlen(origtemplate))
                        template = origtemplate;
 
                nonrelative_template = absolute_path(template);
@@ -411,11 +411,19 @@ void warn_on_inaccessible(const char *path)
 int access_or_warn(const char *path, int mode)
 {
        int ret = access(path, mode);
-       if (ret && errno != ENOENT)
+       if (ret && errno != ENOENT && errno != ENOTDIR)
                warn_on_inaccessible(path);
        return ret;
 }
 
+int access_or_die(const char *path, int mode)
+{
+       int ret = access(path, mode);
+       if (ret && errno != ENOENT && errno != ENOTDIR)
+               die_errno(_("unable to access '%s'"), path);
+       return ret;
+}
+
 struct passwd *xgetpwuid_self(void)
 {
        struct passwd *pw;
index 2a9658bad4c5035893e9363b51985f285dd3b34c..d7cfe8f31cd3d2b4b8bdc18c5da2449255b0531b 100644 (file)
@@ -516,7 +516,9 @@ static void wt_status_collect_untracked(struct wt_status *s)
 
        if (s->show_ignored_files) {
                dir.nr = 0;
-               dir.flags = DIR_SHOW_IGNORED | DIR_SHOW_OTHER_DIRECTORIES;
+               dir.flags = DIR_SHOW_IGNORED;
+               if (s->show_untracked_files != SHOW_ALL_UNTRACKED_FILES)
+                       dir.flags |= DIR_SHOW_OTHER_DIRECTORIES;
                fill_directory(&dir, s->pathspec);
                for (i = 0; i < dir.nr; i++) {
                        struct dir_entry *ent = dir.entries[i];