Code

Merge branch 'sb/format-patch-patchname'
authorJunio C Hamano <gitster@pobox.com>
Mon, 6 Apr 2009 07:42:23 +0000 (00:42 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 6 Apr 2009 07:42:23 +0000 (00:42 -0700)
* sb/format-patch-patchname:
  format_sanitized_subject: Don't trim past initial length of strbuf
  log-tree: fix patch filename computation in "git format-patch"
  format-patch: --numbered-files and --stdout aren't mutually exclusive
  format-patch: --attach/inline uses filename instead of SHA1
  format-patch: move get_patch_filename() into log-tree
  format-patch: pass a commit to reopen_stdout()
  format-patch: construct patch filename in one function
  pretty.c: add %f format specifier to format_commit_message()

152 files changed:
Documentation/Makefile
Documentation/RelNotes-1.6.2.2.txt
Documentation/RelNotes-1.6.3.txt
Documentation/asciidoc.conf
Documentation/callouts.xsl [deleted file]
Documentation/config.txt
Documentation/docbook-xsl.css
Documentation/git-bisect.txt
Documentation/git-bundle.txt
Documentation/git-cat-file.txt
Documentation/git-check-attr.txt
Documentation/git-check-ref-format.txt
Documentation/git-clone.txt
Documentation/git-cvsimport.txt
Documentation/git-format-patch.txt
Documentation/git-merge.txt
Documentation/git-pack-refs.txt
Documentation/git-patch-id.txt
Documentation/git-svn.txt
Documentation/git-tag.txt
Documentation/githooks.txt
Documentation/manpage-1.72.xsl
Documentation/manpage-base.xsl [new file with mode: 0644]
Documentation/manpage-bold-literal.xsl [new file with mode: 0644]
Documentation/manpage-normal.xsl [new file with mode: 0644]
Documentation/manpage-suppress-sp.xsl [new file with mode: 0644]
Documentation/merge-strategies.txt
Documentation/technical/api-history-graph.txt
Documentation/user-manual.txt
Makefile
attr.c
attr.h
builtin-apply.c
builtin-blame.c
builtin-branch.c
builtin-checkout.c
builtin-clone.c
builtin-commit.c
builtin-fast-export.c
builtin-fetch-pack.c
builtin-fetch.c
builtin-init-db.c
builtin-log.c
builtin-pack-objects.c
builtin-push.c
builtin-remote.c
builtin-rm.c
builtin-send-pack.c
builtin-show-branch.c
builtin-show-ref.c
cache.h
compat/mingw.c
config.c
contrib/completion/git-completion.bash
contrib/fast-import/import-zips.py
diff-no-index.c
diff.c
environment.c
exec_cmd.c
fast-import.c
git-bisect.sh
git-filter-branch.sh
git-rebase.sh
git-repack.sh
git-send-email.perl
git-submodule.sh
git-svn.perl
http-push.c
http.c
mailmap.c
reflog-walk.c
reflog-walk.h
refs.c
refs.h
remote.c
revision.c
revision.h
run-command.h
send-pack.h
sha1_file.c
t/Makefile
t/lib-git-svn.sh
t/lib-httpd.sh
t/t0000-basic.sh
t/t0004-unwritable.sh
t/t0020-crlf.sh
t/t0024-crlf-archive.sh
t/t0050-filesystem.sh
t/t0055-beyond-symlinks.sh
t/t0060-path-utils.sh
t/t1004-read-tree-m-u-wf.sh
t/t1020-subdirectory.sh
t/t1300-repo-config.sh
t/t1301-shared-repo.sh
t/t1411-reflog-show.sh [new file with mode: 0755]
t/t1504-ceiling-dirs.sh
t/t2001-checkout-cache-clash.sh
t/t2003-checkout-cache-mkdir.sh
t/t2004-checkout-cache-temp.sh
t/t2007-checkout-symlink.sh
t/t2100-update-cache-badpath.sh
t/t2200-add-update.sh
t/t2201-add-update-typechange.sh
t/t2300-cd-to-toplevel.sh
t/t3000-ls-files-others.sh
t/t3010-ls-files-killed-modified.sh
t/t3100-ls-tree-restrict.sh
t/t3200-branch.sh
t/t3600-rm.sh
t/t3700-add.sh
t/t3701-add-interactive.sh
t/t4004-diff-rename-symlink.sh
t/t4008-diff-break-rewrite.sh
t/t4011-diff-symlink.sh
t/t4014-format-patch.sh
t/t4020-diff-external.sh
t/t4023-diff-rename-typechange.sh
t/t4102-apply-rename.sh
t/t4114-apply-typechange.sh
t/t4115-apply-symlink.sh
t/t4122-apply-symlink-inside.sh
t/t4129-apply-samemode.sh
t/t5000-tar-tree.sh
t/t5302-pack-index.sh
t/t5503-tagfollow.sh
t/t5522-pull-symlink.sh
t/t5540-http-push.sh
t/t6031-merge-recursive.sh
t/t6200-fmt-merge-msg.sh
t/t7001-mv.sh
t/t7004-tag.sh
t/t7005-editor.sh
t/t7502-commit.sh
t/t7503-pre-commit-hook.sh
t/t7504-commit-msg-hook.sh
t/t7700-repack.sh
t/t9001-send-email.sh
t/t9100-git-svn-basic.sh
t/t9129-git-svn-i18n-commitencoding.sh
t/t9131-git-svn-empty-symlink.sh
t/t9132-git-svn-broken-symlink.sh
t/t9200-git-cvsexportcommit.sh
t/t9301-fast-export.sh
t/t9400-git-cvsserver-server.sh
t/t9401-git-cvsserver-crlf.sh
t/t9500-gitweb-standalone-no-errors.sh
t/t9600-cvsimport.sh
t/test-lib.sh
transport.c
transport.h
unpack-trees.c
usage.c

index 144ec32f12a7950746dd71e2ddde5b3f0cab57b0..dba97dc21da79a738b75b4334d082847784c2990 100644 (file)
@@ -41,7 +41,8 @@ man7dir=$(mandir)/man7
 
 ASCIIDOC=asciidoc
 ASCIIDOC_EXTRA =
-MANPAGE_XSL = callouts.xsl
+MANPAGE_XSL = manpage-normal.xsl
+XMLTO_EXTRA =
 INSTALL?=install
 RM ?= rm -f
 DOC_REF = origin/man
@@ -59,12 +60,47 @@ endif
 -include ../config.mak.autogen
 -include ../config.mak
 
+#
+# For asciidoc ...
+#      -7.1.2, no extra settings are needed.
+#      8.0-,   set ASCIIDOC8.
+#
+
+#
+# For docbook-xsl ...
+#      -1.68.1,        set ASCIIDOC_NO_ROFF? (based on changelog from 1.73.0)
+#      1.69.0,         no extra settings are needed?
+#      1.69.1-1.71.0,  set DOCBOOK_SUPPRESS_SP?
+#      1.71.1,         no extra settings are needed?
+#      1.72.0,         set DOCBOOK_XSL_172.
+#      1.73.0-,        set ASCIIDOC_NO_ROFF
+#
+
+#
+# If you had been using DOCBOOK_XSL_172 in an attempt to get rid
+# of 'the ".ft C" problem' in your generated manpages, and you
+# instead ended up with weird characters around callouts, try
+# using ASCIIDOC_NO_ROFF instead (it works fine with ASCIIDOC8).
+#
+
 ifdef ASCIIDOC8
 ASCIIDOC_EXTRA += -a asciidoc7compatible
 endif
 ifdef DOCBOOK_XSL_172
-ASCIIDOC_EXTRA += -a docbook-xsl-172
+ASCIIDOC_EXTRA += -a git-asciidoc-no-roff
 MANPAGE_XSL = manpage-1.72.xsl
+else
+       ifdef ASCIIDOC_NO_ROFF
+       # docbook-xsl after 1.72 needs the regular XSL, but will not
+       # pass-thru raw roff codes from asciidoc.conf, so turn them off.
+       ASCIIDOC_EXTRA += -a git-asciidoc-no-roff
+       endif
+endif
+ifdef MAN_BOLD_LITERAL
+XMLTO_EXTRA += -m manpage-bold-literal.xsl
+endif
+ifdef DOCBOOK_SUPPRESS_SP
+XMLTO_EXTRA += -m manpage-suppress-sp.xsl
 endif
 
 #
@@ -76,6 +112,32 @@ endif
 # yourself - yes, all 6 characters of it!
 #
 
+QUIET_SUBDIR0  = +$(MAKE) -C # space to separate -C and subdir
+QUIET_SUBDIR1  =
+
+ifneq ($(findstring $(MAKEFLAGS),w),w)
+PRINT_DIR = --no-print-directory
+else # "make -w"
+NO_SUBDIR = :
+endif
+
+ifneq ($(findstring $(MAKEFLAGS),s),s)
+ifndef V
+       QUIET_ASCIIDOC  = @echo '   ' ASCIIDOC $@;
+       QUIET_XMLTO     = @echo '   ' XMLTO $@;
+       QUIET_DB2TEXI   = @echo '   ' DB2TEXI $@;
+       QUIET_MAKEINFO  = @echo '   ' MAKEINFO $@;
+       QUIET_DBLATEX   = @echo '   ' DBLATEX $@;
+       QUIET_XSLTPROC  = @echo '   ' XSLTPROC $@;
+       QUIET_GEN       = @echo '   ' GEN $@;
+       QUIET_STDERR    = 2> /dev/null
+       QUIET_SUBDIR0   = +@subdir=
+       QUIET_SUBDIR1   = ;$(NO_SUBDIR) echo '   ' SUBDIR $$subdir; \
+                         $(MAKE) $(PRINT_DIR) -C $$subdir
+       export V
+endif
+endif
+
 all: html man
 
 html: $(DOC_HTML)
@@ -119,7 +181,7 @@ install-html: html
        sh ./install-webdoc.sh $(DESTDIR)$(htmldir)
 
 ../GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
-       $(MAKE) -C ../ GIT-VERSION-FILE
+       $(QUIET_SUBDIR0)../ $(QUIET_SUBDIR1) GIT-VERSION-FILE
 
 -include ../GIT-VERSION-FILE
 
@@ -127,8 +189,8 @@ install-html: html
 # Determine "include::" file references in asciidoc files.
 #
 doc.dep : $(wildcard *.txt) build-docdep.perl
-       $(RM) $@+ $@
-       $(PERL_PATH) ./build-docdep.perl >$@+
+       $(QUIET_GEN)$(RM) $@+ $@ && \
+       $(PERL_PATH) ./build-docdep.perl >$@+ $(QUIET_STDERR) && \
        mv $@+ $@
 
 -include doc.dep
@@ -146,91 +208,94 @@ cmds_txt = cmds-ancillaryinterrogators.txt \
 $(cmds_txt): cmd-list.made
 
 cmd-list.made: cmd-list.perl ../command-list.txt $(MAN1_TXT)
-       $(RM) $@
-       $(PERL_PATH) ./cmd-list.perl ../command-list.txt
+       $(QUIET_GEN)$(RM) $@ && \
+       $(PERL_PATH) ./cmd-list.perl ../command-list.txt $(QUIET_STDERR) && \
        date >$@
 
 clean:
        $(RM) *.xml *.xml+ *.html *.html+ *.1 *.5 *.7
-       $(RM) *.texi *.texi+ git.info gitman.info
+       $(RM) *.texi *.texi+ *.texi++ git.info gitman.info
        $(RM) howto-index.txt howto/*.html doc.dep
        $(RM) technical/api-*.html technical/api-index.txt
        $(RM) $(cmds_txt) *.made
 
 $(MAN_HTML): %.html : %.txt
-       $(RM) $@+ $@
+       $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
        $(ASCIIDOC) -b xhtml11 -d manpage -f asciidoc.conf \
-               $(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) -o $@+ $<
+               $(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) -o $@+ $< && \
        mv $@+ $@
 
 %.1 %.5 %.7 : %.xml
-       $(RM) $@
-       xmlto -m $(MANPAGE_XSL) man $<
+       $(QUIET_XMLTO)$(RM) $@ && \
+       xmlto -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $<
 
 %.xml : %.txt
-       $(RM) $@+ $@
+       $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
        $(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf \
-               $(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) -o $@+ $<
+               $(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) -o $@+ $< && \
        mv $@+ $@
 
 user-manual.xml: user-manual.txt user-manual.conf
-       $(ASCIIDOC) -b docbook -d book $<
+       $(QUIET_ASCIIDOC)$(ASCIIDOC) -b docbook -d book $<
 
 technical/api-index.txt: technical/api-index-skel.txt \
        technical/api-index.sh $(patsubst %,%.txt,$(API_DOCS))
-       cd technical && sh ./api-index.sh
+       $(QUIET_GEN)cd technical && sh ./api-index.sh
 
 $(patsubst %,%.html,$(API_DOCS) technical/api-index): %.html : %.txt
-       $(ASCIIDOC) -b xhtml11 -f asciidoc.conf \
+       $(QUIET_ASCIIDOC)$(ASCIIDOC) -b xhtml11 -f asciidoc.conf \
                $(ASCIIDOC_EXTRA) -agit_version=$(GIT_VERSION) $*.txt
 
 XSLT = docbook.xsl
 XSLTOPTS = --xinclude --stringparam html.stylesheet docbook-xsl.css
 
 user-manual.html: user-manual.xml
-       xsltproc $(XSLTOPTS) -o $@ $(XSLT) $<
+       $(QUIET_XSLTPROC)xsltproc $(XSLTOPTS) -o $@ $(XSLT) $<
 
 git.info: user-manual.texi
-       $(MAKEINFO) --no-split -o $@ user-manual.texi
+       $(QUIET_MAKEINFO)$(MAKEINFO) --no-split -o $@ user-manual.texi
 
 user-manual.texi: user-manual.xml
-       $(RM) $@+ $@
-       $(DOCBOOK2X_TEXI) user-manual.xml --encoding=UTF-8 --to-stdout | \
-               $(PERL_PATH) fix-texi.perl >$@+
+       $(QUIET_DB2TEXI)$(RM) $@+ $@ && \
+       $(DOCBOOK2X_TEXI) user-manual.xml --encoding=UTF-8 --to-stdout >$@++ && \
+       $(PERL_PATH) fix-texi.perl <$@++ >$@+ && \
+       rm $@++ && \
        mv $@+ $@
 
 user-manual.pdf: user-manual.xml
-       $(RM) $@+ $@
-       $(DBLATEX) -o $@+ -p /etc/asciidoc/dblatex/asciidoc-dblatex.xsl -s /etc/asciidoc/dblatex/asciidoc-dblatex.sty $<
+       $(QUIET_DBLATEX)$(RM) $@+ $@ && \
+       $(DBLATEX) -o $@+ -p /etc/asciidoc/dblatex/asciidoc-dblatex.xsl -s /etc/asciidoc/dblatex/asciidoc-dblatex.sty $< && \
        mv $@+ $@
 
 gitman.texi: $(MAN_XML) cat-texi.perl
-       $(RM) $@+ $@
+       $(QUIET_DB2TEXI)$(RM) $@+ $@ && \
        ($(foreach xml,$(MAN_XML),$(DOCBOOK2X_TEXI) --encoding=UTF-8 \
-               --to-stdout $(xml);)) | $(PERL_PATH) cat-texi.perl $@ >$@+
+               --to-stdout $(xml) &&) true) > $@++ && \
+       $(PERL_PATH) cat-texi.perl $@ <$@++ >$@+ && \
+       rm $@++ && \
        mv $@+ $@
 
 gitman.info: gitman.texi
-       $(MAKEINFO) --no-split --no-validate $*.texi
+       $(QUIET_MAKEINFO)$(MAKEINFO) --no-split --no-validate $*.texi
 
 $(patsubst %.txt,%.texi,$(MAN_TXT)): %.texi : %.xml
-       $(RM) $@+ $@
-       $(DOCBOOK2X_TEXI) --to-stdout $*.xml >$@+
+       $(QUIET_DB2TEXI)$(RM) $@+ $@ && \
+       $(DOCBOOK2X_TEXI) --to-stdout $*.xml >$@+ && \
        mv $@+ $@
 
 howto-index.txt: howto-index.sh $(wildcard howto/*.txt)
-       $(RM) $@+ $@
-       sh ./howto-index.sh $(wildcard howto/*.txt) >$@+
+       $(QUIET_GEN)$(RM) $@+ $@ && \
+       sh ./howto-index.sh $(wildcard howto/*.txt) >$@+ && \
        mv $@+ $@
 
 $(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt
-       $(ASCIIDOC) -b xhtml11 $*.txt
+       $(QUIET_ASCIIDOC)$(ASCIIDOC) -b xhtml11 $*.txt
 
 WEBDOC_DEST = /pub/software/scm/git/docs
 
 $(patsubst %.txt,%.html,$(wildcard howto/*.txt)): %.html : %.txt
-       $(RM) $@+ $@
-       sed -e '1,/^$$/d' $< | $(ASCIIDOC) -b xhtml11 - >$@+
+       $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
+       sed -e '1,/^$$/d' $< | $(ASCIIDOC) -b xhtml11 - >$@+ && \
        mv $@+ $@
 
 install-webdoc : html
index 28bfa5399b4a7378633740fcb76a894040b2feea..fafa9986b0e540151b2670df3431482f4898c267 100644 (file)
@@ -7,9 +7,15 @@ Fixes since v1.6.2.1
 * A longstanding confusing description of what --pickaxe option of
   git-diff does has been clarified in the documentation.
 
+* "git-blame -S" did not quite work near the commits that were given
+  on the command line correctly.
+
 * "git diff --pickaxe-regexp" did not count overlapping matches
   correctly.
 
+* "git diff" did not feed files in work-tree representation to external
+  diff and textconv.
+
 * "git-fetch" in a repository that was not cloned from anywhere said
   it cannot find 'origin', which was hard to understand for new people.
 
@@ -27,9 +33,13 @@ Fixes since v1.6.2.1
 * 'git-submodule add' did not tolerate extra slashes and ./ in the path it
   accepted from the command line; it now is more lenient.
 
+* git-svn misbehaved when the project contained a path that began with
+  two dashes.
+
+* import-zips script (in contrib) did not compute the common directory
+  prefix correctly.
+
+* miscompilation of negated enum constants by old gcc (2.9) affected the
+  codepaths to spawn subprocesses.
 
----
-exec >/var/tmp/1
-O=v1.6.2.1-23-g67c176f
-echo O=$(git describe maint)
-git shortlog --no-merges $O..maint
+Many small documentation updates are included as well.
index 5860b515f57adee9ebf0e3ddb4f8042a7f46dc8a..db6956205d4fe12dbb4adefb71bc01030f15dde7 100644 (file)
@@ -22,6 +22,13 @@ branch pointed at by its HEAD, gets a large warning.  You can choose what
 should happen upon such a push by setting the configuration variable
 receive.denyDeleteCurrent in the receiving repository.
 
+When the user does not tell "git push" what to push, it has always
+pushed matching refs.  For some people it is unexpected, and a new
+configuration variable push.default has been introduced to allow
+changing a different default behaviour.  To advertise the new feature,
+a big warning is issued if this is not configured and a git push without
+arguments is attempted.
+
 
 Updates since v1.6.2
 --------------------
@@ -39,6 +46,9 @@ Updates since v1.6.2
   repositories.  It may not be useful in practice; meant primarily for
   testing.
 
+* http transport learned to prompt and use password when fetching from or
+  pushing to http://user@host.xz/ URL.
+
 * (msysgit) progress output that is sent over the sideband protocol can
   be handled appropriately in Windows console.
 
@@ -52,6 +62,10 @@ Updates since v1.6.2
   with the 'edit' action in git-add -i/-p, you can abort the editor to
   tell git not to apply it.
 
+* The number of commits shown in "you are ahead/behind your upstream"
+  messages given by "git checkout" and "git status" used to count merge
+  commits; now it doesn't.
+
 * git-archive learned --output=<file> option.
 
 * git-bisect shows not just the number of remaining commits whose goodness
@@ -67,11 +81,17 @@ Updates since v1.6.2
 
 * git-clone runs post-checkout hook when run without --no-checkout.
 
+* git-fast-export choked when seeing a tag that does not point at commit.
+
 * git-format-patch can be told to use attachment with a new configuration,
   format.attach.
 
 * git-format-patch can be told to produce deep or shallow message threads.
 
+* git-format-patch learned format.headers configuration to add extra
+  header fields to the output.  This behaviour is similar to the existing
+  --add-header=<header> option of the command.
+
 * git-grep learned to highlight the found substrings in color.
 
 * git-imap-send learned to work around Thunderbird's inability to easily
@@ -85,6 +105,11 @@ Updates since v1.6.2
 
 * Output from git-remote command has been vastly improved.
 
+* git-repack (invoked from git-gc) did not work as nicely as it should in
+  a repository that borrows objects from neighbours via alternates
+  mechanism especially when some packs are marked with the ".keep" flag
+  to prevent them from being repacked.
+
 * git-send-email learned --confirm option to review the Cc: list before
   sending the messages out.
 
@@ -92,9 +117,18 @@ Updates since v1.6.2
 
 * Test scripts can be run under valgrind.
 
+* Test scripts can be run with installed git.
+
 * Makefile learned 'coverage' option to run the test suites with
   coverage tracking enabled.
 
+* Building the manpages with docbook-xsl between 1.69.1 and 1.71.1 now
+  requires setting DOCBOOK_SUPPRESS_SP to work around a docbook-xsl bug.
+  This workaround used to be enabled by default, but causes problems
+  with newer versions of docbook-xsl.  In addition, there are a few more
+  knobs you can tweak to work around issues with various versions of the
+  docbook-xsl package.  See comments in Documentation/Makefile for details.
+
 Fixes since v1.6.2
 ------------------
 
@@ -104,11 +138,14 @@ release, unless otherwise noted.
 Here are fixes that this release has, but have not been backported to
 v1.6.2.X series.
 
+* The initial checkout did not read the attributes from the .gitattribute
+  file that is being checked out.
+
 * git-gc spent excessive amount of time to decide if an object appears
   in a locally existing pack (if needed, backport by merging 69e020a).
 
 ---
 exec >/var/tmp/1
-O=v1.6.2.1-213-g7d4e3a7
+O=v1.6.2.2-403-g8130949
 echo O=$(git describe master)
 git shortlog --no-merges $O..master ^maint
index 1e735df3bb5ba15b7f088442439e48a99ca85dbd..dc76e7f073f23cd911da0b0d0d49b72726576f1a 100644 (file)
@@ -27,7 +27,7 @@ ifdef::backend-docbook[]
 endif::backend-docbook[]
 
 ifdef::backend-docbook[]
-ifndef::docbook-xsl-172[]
+ifndef::git-asciidoc-no-roff[]
 # "unbreak" docbook-xsl v1.68 for manpages. v1.69 works with or without this.
 # v1.72 breaks with this because it replaces dots not in roff requests.
 [listingblock]
@@ -42,16 +42,16 @@ ifdef::doctype-manpage[]
 endif::doctype-manpage[]
 </literallayout>
 {title#}</example>
-endif::docbook-xsl-172[]
+endif::git-asciidoc-no-roff[]
 
-ifdef::docbook-xsl-172[]
+ifdef::git-asciidoc-no-roff[]
 ifdef::doctype-manpage[]
 # The following two small workarounds insert a simple paragraph after screen
 [listingblock]
 <example><title>{title}</title>
-<screen>
+<literallayout>
 |
-</screen><simpara></simpara>
+</literallayout><simpara></simpara>
 {title#}</example>
 
 [verseblock]
@@ -59,10 +59,11 @@ ifdef::doctype-manpage[]
 {title%}<literallayout{id? id="{id}"}>
 {title#}<literallayout>
 |
-</literallayout><simpara></simpara>
+</literallayout>
 {title#}</para></formalpara>
+{title%}<simpara></simpara>
 endif::doctype-manpage[]
-endif::docbook-xsl-172[]
+endif::git-asciidoc-no-roff[]
 endif::backend-docbook[]
 
 ifdef::doctype-manpage[]
diff --git a/Documentation/callouts.xsl b/Documentation/callouts.xsl
deleted file mode 100644 (file)
index 6a361a2..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-<!-- callout.xsl: converts asciidoc callouts to man page format -->
-<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
-<xsl:template match="co">
-       <xsl:value-of select="concat('\fB(',substring-after(@id,'-'),')\fR')"/>
-</xsl:template>
-<xsl:template match="calloutlist">
-       <xsl:text>.sp&#10;</xsl:text>
-       <xsl:apply-templates/>
-       <xsl:text>&#10;</xsl:text>
-</xsl:template>
-<xsl:template match="callout">
-       <xsl:value-of select="concat('\fB',substring-after(@arearefs,'-'),'. \fR')"/>
-       <xsl:apply-templates/>
-       <xsl:text>.br&#10;</xsl:text>
-</xsl:template>
-
-<!-- sorry, this is not about callouts, but attempts to work around
- spurious .sp at the tail of the line docbook stylesheets seem to add -->
-<xsl:template match="simpara">
-  <xsl:variable name="content">
-    <xsl:apply-templates/>
-  </xsl:variable>
-  <xsl:value-of select="normalize-space($content)"/>
-  <xsl:if test="not(ancestor::authorblurb) and
-                not(ancestor::personblurb)">
-    <xsl:text>&#10;&#10;</xsl:text>
-  </xsl:if>
-</xsl:template>
-
-</xsl:stylesheet>
index 12540b605f4f15e93703bed226ab43c0b8d6716b..3afd124749fc6301069a0832071000a769e5053b 100644 (file)
@@ -473,10 +473,14 @@ branch.autosetuprebase::
        This option defaults to never.
 
 branch.<name>.remote::
-       When in branch <name>, it tells 'git-fetch' which remote to fetch.
-       If this option is not given, 'git-fetch' defaults to remote "origin".
+       When in branch <name>, it tells 'git-fetch' and 'git-push' which
+       remote to fetch from/push to.  It defaults to `origin` if no remote is
+       configured. `origin` is also used if you are not on any branch.
 
 branch.<name>.merge::
+       Defines, together with branch.<name>.remote, the upstream branch
+       for the given branch. It tells 'git-fetch'/'git-pull' which
+       branch to merge and can also affect 'git-push' (see push.default).
        When in branch <name>, it tells 'git-fetch' the default
        refspec to be marked for merging in FETCH_HEAD. The value is
        handled like the remote part of a refspec, and must match a
@@ -711,6 +715,13 @@ format.thread::
        A true boolean value is the same as `shallow`, and a false
        value disables threading.
 
+format.signoff::
+    A boolean value which lets you enable the `-s/--signoff` option of
+    format-patch by default. *Note:* Adding the Signed-off-by: line to a
+    patch should be a conscious act and means that you certify you have
+    the rights to submit this work under the same open source license.
+    Please see the 'SubmittingPatches' document for further discussion.
+
 gc.aggressiveWindow::
        The window size parameter used in the delta compression
        algorithm used by 'git-gc --aggressive'.  This defaults
@@ -1194,6 +1205,19 @@ pull.octopus::
 pull.twohead::
        The default merge strategy to use when pulling a single branch.
 
+push.default::
+       Defines the action git push should take if no refspec is given
+       on the command line, no refspec is configured in the remote, and
+       no refspec is implied by any of the options given on the command
+       line. Possible values are:
++
+* `nothing` do not push anything.
+* `matching` push all matching branches.
+  All branches having the same name in both ends are considered to be
+  matching. This is the default.
+* `tracking` push the current branch to the branch it is tracking.
+* `current` push the current branch to a branch of the same name.
+
 rebase.stat::
        Whether to show a diffstat of what changed upstream since the last
        rebase. False by default.
index b878b385c6967f4c64ba30bdfe8f9bd24bef91e3..e11c8f053ad753f218a0a79ddacfe62862603bb9 100644 (file)
@@ -16,6 +16,7 @@ body blockquote {
 html body {
   margin: 1em 5% 1em 5%;
   line-height: 1.2;
+  font-family: sans-serif;
 }
 
 body div {
@@ -128,6 +129,15 @@ body pre {
 
 tt.literal, code.literal {
   color: navy;
+  font-family: sans-serif;
+}
+
+code.literal:before { content: "'"; }
+code.literal:after { content: "'"; }
+
+em {
+  font-style: italic;
+  color: #064;
 }
 
 div.literallayout p {
@@ -137,7 +147,6 @@ div.literallayout p {
 
 div.literallayout {
   font-family: monospace;
-#  margin: 0.5em 10% 0.5em 1em;
   margin: 0em;
   color: navy;
   border: 1px solid silver;
@@ -187,7 +196,8 @@ dt {
 }
 
 dt span.term {
-  font-style: italic;
+  font-style: normal;
+  color: navy;
 }
 
 div.variablelist dd p {
index 93d9fc0299c0f4aeeb97f6ec228415d67c398dcb..ffc02c737cf0a8d2bdb3cd812e0a23d43ee27fd7 100644 (file)
@@ -81,7 +81,7 @@ will have been left with the first bad kernel revision in "refs/bisect/bad".
 Bisect reset
 ~~~~~~~~~~~~
 
-To return to the original head after a bisect session, you issue the
+To return to the original head after a bisect session, issue the
 following command:
 
 ------------------------------------------------
@@ -95,8 +95,8 @@ the bisection state).
 Bisect visualize
 ~~~~~~~~~~~~~~~~
 
-To see the currently remaining suspects in 'gitk', the following command
-is issued during the bisection process:
+To see the currently remaining suspects in 'gitk', issue the following
+command during the bisection process:
 
 ------------
 $ git bisect visualize
@@ -115,7 +115,7 @@ $ git bisect view --stat
 Bisect log and bisect replay
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-After having marked revisions as good or bad, you issue the following
+After having marked revisions as good or bad, issue the following
 command to show what has been done so far:
 
 ------------
@@ -135,7 +135,7 @@ $ git bisect replay that-file
 Avoiding testing a commit
 ~~~~~~~~~~~~~~~~~~~~~~~~~
 
-If in the middle of a bisect session, you know that the next suggested
+If, in the middle of a bisect session, you know that the next suggested
 revision is not a good one to test (e.g. the change the commit
 introduces is known not to work in your environment and you know it
 does not have anything to do with the bug you are chasing), you may
@@ -151,8 +151,8 @@ $ git reset --hard HEAD~3           # try 3 revisions before what
                                        # was suggested
 ------------
 
-Then compile and test the chosen revision. Afterwards the revision
-is marked as good or bad in the usual manner.
+Then compile and test the chosen revision, and afterwards mark
+the revision as good or bad in the usual manner.
 
 Bisect skip
 ~~~~~~~~~~~~
@@ -175,8 +175,8 @@ using the "'<commit1>'..'<commit2>'" notation. For example:
 $ git bisect skip v2.5..v2.6
 ------------
 
-The effect of this would be that no commit between `v2.5` excluded and
-`v2.6` included could be tested.
+This tells the bisect process that no commit after `v2.5`, up to and
+including `v2.6`, should be tested.
 
 Note that if you also want to skip the first commit of the range you
 would issue the command:
@@ -185,8 +185,8 @@ would issue the command:
 $ git bisect skip v2.5 v2.5..v2.6
 ------------
 
-This would cause the commits between `v2.5` included and `v2.6` included
-to be skipped.
+This tells the bisect process that the commits between `v2.5` included
+and `v2.6` included should be skipped.
 
 
 Cutting down bisection by giving more parameters to bisect start
index 57590b148011c44485d28d93d31c6a75a681bfb0..aee7e4a8c9396225e6d82d6a85618128c4170ce0 100644 (file)
@@ -19,13 +19,13 @@ DESCRIPTION
 
 Some workflows require that one or more branches of development on one
 machine be replicated on another machine, but the two machines cannot
-be directly connected so the interactive git protocols (git, ssh,
-rsync, http) cannot be used.  This command provides support for
+be directly connected, and therefore the interactive git protocols (git,
+ssh, rsync, http) cannot be used.  This command provides support for
 'git-fetch' and 'git-pull' to operate by packaging objects and references
 in an archive at the originating machine, then importing those into
 another repository using 'git-fetch' and 'git-pull'
 after moving the archive by some means (i.e., by sneakernet).  As no
-direct connection between repositories exists, the user must specify a
+direct connection between the repositories exists, the user must specify a
 basis for the bundle that is held by the destination repository: the
 bundle assumes that all objects in the basis are already in the
 destination repository.
@@ -43,7 +43,7 @@ verify <file>::
        bundle format itself as well as checking that the prerequisite
        commits exist and are fully linked in the current repository.
        'git-bundle' prints a list of missing commits, if any, and exits
-       with non-zero status.
+       with non-zero status.
 
 list-heads <file>::
        Lists the references defined in the bundle.  If followed by a
@@ -53,14 +53,14 @@ list-heads <file>::
 unbundle <file>::
        Passes the objects in the bundle to 'git-index-pack'
        for storage in the repository, then prints the names of all
-       defined references. If a reflist is given, only references
-       matching those in the given list are printed. This command is
+       defined references. If a list of references is given, only
+       references matching those in the list are printed. This command is
        really plumbing, intended to be called only by 'git-fetch'.
 
 [git-rev-list-args...]::
        A list of arguments, acceptable to 'git-rev-parse' and
-       'git-rev-list', that specify the specific objects and references
-       to transport.  For example, "master~10..master" causes the
+       'git-rev-list', that specifies the specific objects and references
+       to transport.  For example, `master\~10..master` causes the
        current master reference to be packaged along with all objects
        added since its 10th ancestor commit.  There is no explicit
        limit to the number of references and objects that may be
@@ -71,24 +71,24 @@ unbundle <file>::
        A list of references used to limit the references reported as
        available. This is principally of use to 'git-fetch', which
        expects to receive only those references asked for and not
-       necessarily everything in the pack (in this case, 'git-bundle' is
-       acting like 'git-fetch-pack').
+       necessarily everything in the pack (in this case, 'git-bundle' acts
+       like 'git-fetch-pack').
 
 SPECIFYING REFERENCES
 ---------------------
 
 'git-bundle' will only package references that are shown by
 'git-show-ref': this includes heads, tags, and remote heads.  References
-such as master~1 cannot be packaged, but are perfectly suitable for
+such as `master\~1` cannot be packaged, but are perfectly suitable for
 defining the basis.  More than one reference may be packaged, and more
 than one basis can be specified.  The objects packaged are those not
 contained in the union of the given bases.  Each basis can be
-specified explicitly (e.g., ^master~10), or implicitly (e.g.,
-master~10..master, --since=10.days.ago master).
+specified explicitly (e.g. `^master\~10`), or implicitly (e.g.
+`master\~10..master`, `--since=10.days.ago master`).
 
 It is very important that the basis used be held by the destination.
-It is okay to err on the side of conservatism, causing the bundle file
-to contain objects already in the destination as these are ignored
+It is okay to err on the side of caution, causing the bundle file
+to contain objects already in the destination, as these are ignored
 when unpacking at the destination.
 
 EXAMPLE
@@ -97,13 +97,13 @@ EXAMPLE
 Assume you want to transfer the history from a repository R1 on machine A
 to another repository R2 on machine B.
 For whatever reason, direct connection between A and B is not allowed,
-but we can move data from A to B via some mechanism (CD, email, etc).
-We want to update R2 with developments made on branch master in R1.
+but we can move data from A to B via some mechanism (CD, email, etc.).
+We want to update R2 with development made on the branch master in R1.
 
-To bootstrap the process, you can first create a bundle that doesn't have
-any basis. You can use a tag to remember up to what commit you sent out
-in order to make it easy to later update the other repository with
-incremental bundle,
+To bootstrap the process, you can first create a bundle that does not have
+any basis. You can use a tag to remember up to what commit you last
+processed, in order to make it easy to later update the other repository
+with an incremental bundle:
 
 ----------------
 machineA$ cd R1
@@ -111,17 +111,17 @@ machineA$ git bundle create file.bundle master
 machineA$ git tag -f lastR2bundle master
 ----------------
 
-Then you sneakernet file.bundle to the target machine B. Because you don't
-have to have any object to extract objects from such a bundle, not only
-you can fetch/pull from a bundle, you can clone from it as if it was a
-remote repository.
+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:
 
 ----------------
 machineB$ git clone /home/me/tmp/file.bundle R2
 ----------------
 
 This will define a remote called "origin" in the resulting repository that
-lets you fetch and pull from the bundle. $GIT_DIR/config file in R2 may
+lets you fetch and pull from the bundle. The $GIT_DIR/config file in R2 will
 have an entry like this:
 
 ------------------------
@@ -130,12 +130,12 @@ have an entry like this:
     fetch = refs/heads/*:refs/remotes/origin/*
 ------------------------
 
-You can fetch/pull to update the resulting mine.git repository after
-replacing the bundle you store at /home/me/tmp/file.bundle with incremental
-updates from here on.
+To update the resulting mine.git repository, you can fetch or pull after
+replacing the bundle stored at /home/me/tmp/file.bundle with incremental
+updates.
 
-After working more in the original repository, you can create an
-incremental bundle to update the other:
+After working some more in the original repository, you can create an
+incremental bundle to update the other repository:
 
 ----------------
 machineA$ cd R1
@@ -143,8 +143,8 @@ machineA$ git bundle create file.bundle lastR2bundle..master
 machineA$ git tag -f lastR2bundle master
 ----------------
 
-and sneakernet it to the other machine to replace /home/me/tmp/file.bundle,
-and pull from it.
+You then transfer the bundle to the other machine to replace
+/home/me/tmp/file.bundle, and pull from it.
 
 ----------------
 machineB$ cd R2
@@ -152,49 +152,49 @@ machineB$ git pull
 ----------------
 
 If you know up to what commit the intended recipient repository should
-have the necessary objects for, you can use that knowledge to specify the
+have the necessary objects, you can use that knowledge to specify the
 basis, giving a cut-off point to limit the revisions and objects that go
 in the resulting bundle. The previous example used lastR2bundle tag
-for this purpose, but you can use other options you would give to
+for this purpose, but you can use any other options that you would give to
 the linkgit:git-log[1] command. Here are more examples:
 
-You can use a tag that is present in both.
+You can use a tag that is present in both:
 
 ----------------
 $ git bundle create mybundle v1.0.0..master
 ----------------
 
-You can use a basis based on time.
+You can use a basis based on time:
 
 ----------------
 $ git bundle create mybundle --since=10.days master
 ----------------
 
-Or you can use the number of commits.
+You can use the number of commits:
 
 ----------------
 $ git bundle create mybundle -10 master
 ----------------
 
 You can run `git-bundle verify` to see if you can extract from a bundle
-that was created with a basis.
+that was created with a basis:
 
 ----------------
 $ git bundle verify mybundle
 ----------------
 
 This will list what commits you must have in order to extract from the
-bundle and will error out if you don't have them.
+bundle and will error out if you do not have them.
 
 A bundle from a recipient repository's point of view is just like a
-regular repository it fetches/pulls from. You can for example map
-refs, like this example, when fetching:
+regular repository which it fetches or pulls from. You can, for example, map
+references when fetching:
 
 ----------------
 $ git fetch mybundle master:localRef
 ----------------
 
-Or see what refs it offers.
+You can also see what references it offers.
 
 ----------------
 $ git ls-remote mybundle
index 668f697c2a03c29f589e249de832ddf01b9b1e6d..b191276d7a44511bfce60febe6f5cb9a025ec9a3 100644 (file)
@@ -3,7 +3,7 @@ git-cat-file(1)
 
 NAME
 ----
-git-cat-file - Provide content or type/size information for repository objects
+git-cat-file - Provide content or type and size information for repository objects
 
 
 SYNOPSIS
@@ -14,19 +14,19 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-In the first form, provides content or type of objects in the repository. The
-type is required unless '-t' or '-p' is used to find the object type, or '-s'
-is used to find the object size.
+In its first form, the command provides the content or the type of an object in
+the repository. The type is required unless '-t' or '-p' is used to find the
+object type, or '-s' is used to find the object size.
 
-In the second form, a list of object (separated by LFs) is provided on stdin,
-and the SHA1, type, and size of each object is printed on stdout.
+In the second form, a list of objects (separated by linefeeds) is provided on
+stdin, and the SHA1, type, and size of each object is printed on stdout.
 
 OPTIONS
 -------
 <object>::
        The name of the object to show.
        For a more complete list of ways to spell object names, see
-       "SPECIFYING REVISIONS" section in linkgit:git-rev-parse[1].
+       the "SPECIFYING REVISIONS" section in linkgit:git-rev-parse[1].
 
 -t::
        Instead of the content, show the object type identified by
@@ -56,8 +56,8 @@ OPTIONS
        stdin. May not be combined with any other options or arguments.
 
 --batch-check::
-       Print the SHA1, type, and size of each object provided on stdin. May not be
-       combined with any other options or arguments.
+       Print the SHA1, type, and size of each object provided on stdin. May not
+       be combined with any other options or arguments.
 
 OUTPUT
 ------
index 8c2ac12f5d316a5db8c5a9be2c4d9639ca30653b..50824e3a2d7d00370d7311088349da84ee23b728 100644 (file)
@@ -14,7 +14,7 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-For every pathname, this command will list if each attr is 'unspecified',
+For every pathname, this command will list if each attribute is 'unspecified',
 'set', or 'unset' as a gitattribute on that pathname.
 
 OPTIONS
@@ -23,11 +23,11 @@ OPTIONS
        Read file names from stdin instead of from the command-line.
 
 -z::
-       Only meaningful with `--stdin`; paths are separated with
-       NUL character instead of LF.
+       Only meaningful with `--stdin`; paths are separated with a
+       NUL character instead of a linefeed character.
 
 \--::
-       Interpret all preceding arguments as attributes, and all following
+       Interpret all preceding arguments as attributes and all following
        arguments as path names. If not supplied, only the first argument will
        be treated as an attribute.
 
@@ -37,12 +37,12 @@ OUTPUT
 The output is of the form:
 <path> COLON SP <attribute> COLON SP <info> LF
 
-Where <path> is the path of a file being queried, <attribute> is an attribute
+<path> is the path of a file being queried, <attribute> is an attribute
 being queried and <info> can be either:
 
 'unspecified';; when the attribute is not defined for the path.
-'unset';;      when the attribute is defined to false.
-'set';;                when the attribute is defined to true.
+'unset';;      when the attribute is defined as false.
+'set';;                when the attribute is defined as true.
 <value>;;      when a value has been assigned to the attribute.
 
 EXAMPLES
@@ -69,7 +69,7 @@ org/example/MyClass.java: diff: java
 org/example/MyClass.java: myAttr: set
 ---------------
 
-* Listing attribute for multiple files:
+* Listing an attribute for multiple files:
 ---------------
 $ git check-attr myAttr -- org/example/MyClass.java org/example/NoMyAttr.java
 org/example/MyClass.java: myAttr: set
index 034223cc5ace81dd0b63da44d79db5e83a1d492a..171b68377d6604167fde4f5e4266432fa9048345 100644 (file)
@@ -3,7 +3,7 @@ git-check-ref-format(1)
 
 NAME
 ----
-git-check-ref-format - Make sure ref name is well formed
+git-check-ref-format - Ensures that a reference name is well formed
 
 SYNOPSIS
 --------
@@ -11,40 +11,40 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-Checks if a given 'refname' is acceptable, and exits non-zero if
-it is not.
+Checks if a given 'refname' is acceptable, and exits with a non-zero
+status if it is not.
 
 A reference is used in git to specify branches and tags.  A
-branch head is stored under `$GIT_DIR/refs/heads` directory, and
-a tag is stored under `$GIT_DIR/refs/tags` directory.  git
-imposes the following rules on how refs are named:
+branch head is stored under the `$GIT_DIR/refs/heads` directory, and
+a tag is stored under the `$GIT_DIR/refs/tags` directory.  git
+imposes the following rules on how references are named:
 
-. It can include slash `/` for hierarchical (directory)
+. They can include slash `/` for hierarchical (directory)
   grouping, but no slash-separated component can begin with a
-  dot `.`;
+  dot `.`.
 
-. It cannot have two consecutive dots `..` anywhere;
+. They cannot have two consecutive dots `..` anywhere.
 
-. It cannot have ASCII control character (i.e. bytes whose
+. They cannot have ASCII control characters (i.e. bytes whose
   values are lower than \040, or \177 `DEL`), space, tilde `~`,
   caret `{caret}`, colon `:`, question-mark `?`, asterisk `*`,
-  or open bracket `[` anywhere;
+  or open bracket `[` anywhere.
 
-. It cannot end with a slash `/`.
+. They cannot end with a slash `/`.
 
-These rules makes it easy for shell script based tools to parse
-refnames, pathname expansion by the shell when a refname is used
+These rules make it easy for shell script based tools to parse
+reference names, pathname expansion by the shell when a reference name is used
 unquoted (by mistake), and also avoids ambiguities in certain
-refname expressions (see linkgit:git-rev-parse[1]).  Namely:
+reference name expressions (see linkgit:git-rev-parse[1]):
 
-. double-dot `..` are often used as in `ref1..ref2`, and in some
-  context this notation means `{caret}ref1 ref2` (i.e. not in
-  ref1 and in ref2).
+. A double-dot `..` is often used as in `ref1..ref2`, and in some
+  contexts this notation means `{caret}ref1 ref2` (i.e. not in
+  `ref1` and in `ref2`).
 
-. tilde `~` and caret `{caret}` are used to introduce postfix
+. A tilde `~` and caret `{caret}` are used to introduce the postfix
   'nth parent' and 'peel onion' operation.
 
-. colon `:` is used as in `srcref:dstref` to mean "use srcref\'s
+. colon `:` is used as in `srcref:dstref` to mean "use srcref\'s
   value and store it in dstref" in fetch and push operations.
   It may also be used to select a specific object such as with
   'git-cat-file': "git cat-file blob v1.3.3:refs.c".
index 95f08b911464b348525e4c65cca32946c583e762..4072f40d7ae5417c51d1cddcf587b674aa1dc0e5 100644 (file)
@@ -117,7 +117,7 @@ then the cloned repository will become corrupt.
 --origin <name>::
 -o <name>::
        Instead of using the remote name 'origin' to keep track
-       of the upstream repository, use <name> instead.
+       of the upstream repository, use <name>.
 
 --upload-pack <upload-pack>::
 -u <upload-pack>::
index b7a8c10b8709108c1c8a0d14f661c179c2b4f22c..d7bab13f6c35762cbb83c5b244a827790da4c816 100644 (file)
@@ -24,6 +24,9 @@ repository, or incrementally import into an existing one.
 Splitting the CVS log into patch sets is done by 'cvsps'.
 At least version 2.1 is required.
 
+*WARNING:* for certain situations the import leads to incorrect results.
+Please see the section <<issues,ISSUES>> for further reference.
+
 You should *never* do any work of your own on the branches that are
 created by 'git-cvsimport'.  By default initial import will create and populate a
 "master" branch from the CVS repository's main branch which you're free
@@ -62,7 +65,7 @@ OPTIONS
 -r <remote>::
        The git remote to import this CVS repository into.
        Moves all CVS branches into remotes/<remote>/<branch>
-       akin to the 'git-clone' "--use-separate-remote" option.
+       akin to the way 'git-clone' uses 'origin' by default.
 
 -o <branch-for-HEAD>::
        When no remote is specified (via -r) the 'HEAD' branch
@@ -164,6 +167,39 @@ If '-v' is specified, the script reports what it is doing.
 Otherwise, success is indicated the Unix way, i.e. by simply exiting with
 a zero exit status.
 
+[[issues]]
+ISSUES
+------
+Problems related to timestamps:
+
+ * If timestamps of commits in the cvs repository are not stable enough
+   to be used for ordering commits changes may show up in the wrong
+   order.
+ * If any files were ever "cvs import"ed more than once (e.g., import of
+   more than one vendor release) the HEAD contains the wrong content.
+ * If the timestamp order of different files cross the revision order
+   within the commit matching time window the order of commits may be
+   wrong.
+
+Problems related to branches:
+
+ * Branches on which no commits have been made are not imported.
+ * All files from the branching point are added to a branch even if
+   never added in cvs.
+ * This applies to files added to the source branch *after* a daughter
+   branch was created: if previously no commit was made on the daughter
+   branch they will erroneously be added to the daughter branch in git.
+
+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 practise:
+
+* cvs2git (part of cvs2svn), `http://cvs2svn.tigris.org`
+* parsecvs, `http://cgit.freedesktop.org/~keithp/parsecvs`
 
 Author
 ------
index c2eb5fab4caff69b98fbcd3cb66d78e3371f81e4..eb2fbcff1a103c2b973eccbb449a20d3b68f157f 100644 (file)
@@ -40,15 +40,11 @@ There are two ways to specify which commits to operate on.
    REVISIONS" section in linkgit:git-rev-parse[1]) means the
    commits in the specified range.
 
-A single commit, when interpreted as a <revision range>
-expression, means "everything that leads to that commit", but
-if you write 'git format-patch <commit>', the previous rule
-applies to that command line and you do not get "everything
-since the beginning of the time".  If you want to format
-everything since project inception to one commit, say "git
-format-patch \--root <commit>" to make it clear that it is the
-latter case.  If you want to format a single commit, you can do
-this with "git format-patch -1 <commit>".
+The first rule takes precedence in the case of a single <commit>.  To
+apply the second rule, i.e., format everything since the beginning of
+history up until <commit>, use the '\--root' option: "git format-patch
+\--root <commit>".  If you want to format only <commit> itself, you
+can do this with "git format-patch -1 <commit>".
 
 By default, each output file is numbered sequentially from 1, and uses the
 first line of the commit message (massaged for pathname safety) as
@@ -161,6 +157,11 @@ if that is not set.
        Add a "Cc:" header to the email headers. This is in addition
        to any configured headers, and may be used multiple times.
 
+--add-header=<header>::
+       Add an arbitrary header to the email headers.  This is in addition
+       to any configured headers, and may be used multiple times.
+       For example, --add-header="Organization: git-foo"
+
 --cover-letter::
        In addition to the patches, generate a cover letter file
        containing the shortlog and the overall diffstat.  You can
@@ -182,6 +183,13 @@ not add any suffix.
        applied.  By default the contents of changes in those files are
        encoded in the patch.
 
+--root::
+       Treat the revision argument as a <revision range>, even if it
+       is just a single commit (that would normally be treated as a
+       <since>).  Note that root commits included in the specified
+       range are always formatted as creation patches, independently
+       of this flag.
+
 CONFIGURATION
 -------------
 You can specify extra mail header lines to be added to each message
@@ -197,6 +205,7 @@ more than one.
        numbered = auto
        cc = <email>
        attach [ = mime-boundary-string ]
+       signoff = true
 ------------
 
 
index cc0d30fe7e6c96d25304181ef2fdd9cbd02e7817..c04ae739edd409307d286fe31e6f87e41f977eac 100644 (file)
@@ -40,8 +40,8 @@ include::merge-options.txt[]
 include::merge-strategies.txt[]
 
 
-If you tried a merge which resulted in complex conflicts and
-would want to start over, you can recover with 'git-reset'.
+If you tried a merge which resulted in complex conflicts and
+want to start over, you can recover with 'git-reset'.
 
 CONFIGURATION
 -------------
index a5244d35f49f10b7954d8fa52164663e3d167d4b..1ee99c208ce4893d2fa2367544b22ed0c8b18044 100644 (file)
@@ -26,7 +26,7 @@ problem by stashing the refs in a single file,
 traditional `$GIT_DIR/refs` hierarchy, it is looked up in this
 file and used if found.
 
-Subsequent updates to branches always creates new file under
+Subsequent updates to branches always create new files under
 `$GIT_DIR/refs` hierarchy.
 
 A recommended practice to deal with a repository with too many
@@ -35,7 +35,7 @@ occasionally run `git pack-refs \--prune`.  Tags are by
 definition stationary and are not expected to change.  Branch
 heads will be packed with the initial `pack-refs --all`, but
 only the currently active branch heads will become unpacked,
-and next `pack-refs` (without `--all`) will leave them
+and the next `pack-refs` (without `--all`) will leave them
 unpacked.
 
 
index 477785e13418e1971156f5210015da4ab9d77cab..253fc0fc255a0f82778d120647031eaa66eb647a 100644 (file)
@@ -20,7 +20,7 @@ IOW, you can use this thing to look for likely duplicate commits.
 
 When dealing with 'git-diff-tree' output, it takes advantage of
 the fact that the patch is prefixed with the object name of the
-commit, and outputs two 40-byte hexadecimal string.  The first
+commit, and outputs two 40-byte hexadecimal strings.  The first
 string is the patch ID, and the second string is the commit ID.
 This can be used to make a mapping from patch ID to commit ID.
 
index cda3389331edd615cab316574e4dedc5cc30bd31..b7b1af813d79a88aab3d74a39b7a63570c44871c 100644 (file)
@@ -385,7 +385,8 @@ config key: svn.authorsfile
 
 -q::
 --quiet::
-       Make 'git-svn' less verbose.
+       Make 'git-svn' less verbose. Specify a second time to make it
+       even less verbose.
 
 --repack[=<n>]::
 --repack-flags=<flags>::
@@ -672,9 +673,9 @@ listed below are allowed:
 ------------------------------------------------------------------------
 [svn-remote "project-a"]
        url = http://server.org/svn
+       fetch = trunk/project-a:refs/remotes/project-a/trunk
        branches = branches/*/project-a:refs/remotes/project-a/branches/*
        tags = tags/*/project-a:refs/remotes/project-a/tags/*
-       trunk = trunk/project-a:refs/remotes/project-a/trunk
 ------------------------------------------------------------------------
 
 Keep in mind that the '*' (asterisk) wildcard of the local ref
index 533d18bbd5634bf6197960f546a20772386c824a..fa733214ab0259dec1c866e9cb629dd0e7b69f3a 100644 (file)
@@ -63,6 +63,7 @@ OPTIONS
        are printed when using -l.
        The default is not to print any annotation lines.
        If no number is given to `-n`, only the first line is printed.
+       If the tag is not annotated, the commit message is displayed instead.
 
 -l <pattern>::
        List tags with names that match the given pattern (or all if no pattern is given).
index 1fd512bca2e12f5eb0abac0edb0dfb2a86949cec..1c736738ccc91b6929226a27e02716221ec3ef05 100644 (file)
@@ -151,6 +151,10 @@ indicating whether the checkout was a branch checkout (changing branches,
 flag=1) or a file checkout (retrieving a file from the index, flag=0).
 This hook cannot affect the outcome of 'git-checkout'.
 
+It is also run after 'git-clone', unless the --no-checkout (-n) option is
+used. The first parameter given to the hook is the null-ref, the second the
+ref of the new HEAD and the flag is always 1.
+
 This hook can be used to perform repository validity checks, auto-display
 differences from the previous HEAD if different, or set working dir metadata
 properties.
index 4065a3a27a38be73132b9f509e1d63546b3fddef..b4d315cb8c4792c25cfad7892e056356543e85e1 100644 (file)
@@ -1,21 +1,14 @@
-<!-- Based on callouts.xsl. Fixes man page callouts for DocBook 1.72 XSL -->
-<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<!-- manpage-1.72.xsl:
+     special settings for manpages rendered from asciidoc+docbook
+     handles peculiarities in docbook-xsl 1.72.0 -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+               version="1.0">
 
-<xsl:param name="man.output.quietly" select="1"/>
-<xsl:param name="refentry.meta.get.quietly" select="1"/>
+<xsl:import href="manpage-base.xsl"/>
 
-<xsl:template match="co">
-       <xsl:value-of select="concat('&#x2593;fB(',substring-after(@id,'-'),')&#x2593;fR')"/>
-</xsl:template>
-<xsl:template match="calloutlist">
-       <xsl:text>&#x2302;sp&#10;</xsl:text>
-       <xsl:apply-templates/>
-       <xsl:text>&#10;</xsl:text>
-</xsl:template>
-<xsl:template match="callout">
-       <xsl:value-of select="concat('&#x2593;fB',substring-after(@arearefs,'-'),'. &#x2593;fR')"/>
-       <xsl:apply-templates/>
-       <xsl:text>&#x2302;br&#10;</xsl:text>
-</xsl:template>
+<!-- these are the special values for the roff control characters
+     needed for docbook-xsl 1.72.0 -->
+<xsl:param name="git.docbook.backslash">&#x2593;</xsl:param>
+<xsl:param name="git.docbook.dot"      >&#x2302;</xsl:param>
 
 </xsl:stylesheet>
diff --git a/Documentation/manpage-base.xsl b/Documentation/manpage-base.xsl
new file mode 100644 (file)
index 0000000..a264fa6
--- /dev/null
@@ -0,0 +1,35 @@
+<!-- manpage-base.xsl:
+     special formatting for manpages rendered from asciidoc+docbook -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+               version="1.0">
+
+<!-- these params silence some output from xmlto -->
+<xsl:param name="man.output.quietly" select="1"/>
+<xsl:param name="refentry.meta.get.quietly" select="1"/>
+
+<!-- convert asciidoc callouts to man page format;
+     git.docbook.backslash and git.docbook.dot params
+     must be supplied by another XSL file or other means -->
+<xsl:template match="co">
+       <xsl:value-of select="concat(
+                             $git.docbook.backslash,'fB(',
+                             substring-after(@id,'-'),')',
+                             $git.docbook.backslash,'fR')"/>
+</xsl:template>
+<xsl:template match="calloutlist">
+       <xsl:value-of select="$git.docbook.dot"/>
+       <xsl:text>sp&#10;</xsl:text>
+       <xsl:apply-templates/>
+       <xsl:text>&#10;</xsl:text>
+</xsl:template>
+<xsl:template match="callout">
+       <xsl:value-of select="concat(
+                             $git.docbook.backslash,'fB',
+                             substring-after(@arearefs,'-'),
+                             '. ',$git.docbook.backslash,'fR')"/>
+       <xsl:apply-templates/>
+       <xsl:value-of select="$git.docbook.dot"/>
+       <xsl:text>br&#10;</xsl:text>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/Documentation/manpage-bold-literal.xsl b/Documentation/manpage-bold-literal.xsl
new file mode 100644 (file)
index 0000000..608eb5d
--- /dev/null
@@ -0,0 +1,17 @@
+<!-- manpage-bold-literal.xsl:
+     special formatting for manpages rendered from asciidoc+docbook -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+               version="1.0">
+
+<!-- render literal text as bold (instead of plain or monospace);
+     this makes literal text easier to distinguish in manpages
+     viewed on a tty -->
+<xsl:template match="literal">
+       <xsl:value-of select="$git.docbook.backslash"/>
+       <xsl:text>fB</xsl:text>
+       <xsl:apply-templates/>
+       <xsl:value-of select="$git.docbook.backslash"/>
+       <xsl:text>fR</xsl:text>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/Documentation/manpage-normal.xsl b/Documentation/manpage-normal.xsl
new file mode 100644 (file)
index 0000000..a48f5b1
--- /dev/null
@@ -0,0 +1,13 @@
+<!-- manpage-normal.xsl:
+     special settings for manpages rendered from asciidoc+docbook
+     handles anything we want to keep away from docbook-xsl 1.72.0 -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+               version="1.0">
+
+<xsl:import href="manpage-base.xsl"/>
+
+<!-- these are the normal values for the roff control characters -->
+<xsl:param name="git.docbook.backslash">\</xsl:param>
+<xsl:param name="git.docbook.dot"      >.</xsl:param>
+
+</xsl:stylesheet>
diff --git a/Documentation/manpage-suppress-sp.xsl b/Documentation/manpage-suppress-sp.xsl
new file mode 100644 (file)
index 0000000..a63c763
--- /dev/null
@@ -0,0 +1,21 @@
+<!-- manpage-suppress-sp.xsl:
+     special settings for manpages rendered from asciidoc+docbook
+     handles erroneous, inline .sp in manpage output of some
+     versions of docbook-xsl -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+               version="1.0">
+
+<!-- attempt to work around spurious .sp at the tail of the line
+     that some versions of docbook stylesheets seem to add -->
+<xsl:template match="simpara">
+  <xsl:variable name="content">
+    <xsl:apply-templates/>
+  </xsl:variable>
+  <xsl:value-of select="normalize-space($content)"/>
+  <xsl:if test="not(ancestor::authorblurb) and
+                not(ancestor::personblurb)">
+    <xsl:text>&#10;&#10;</xsl:text>
+  </xsl:if>
+</xsl:template>
+
+</xsl:stylesheet>
index 1276f858ade29bec40716d19cf56fe6e3882fc25..4365b7e8420fa96d6cbfa14a5aa49d956ba2de16 100644 (file)
@@ -3,15 +3,15 @@ MERGE STRATEGIES
 
 resolve::
        This can only resolve two heads (i.e. the current branch
-       and another branch you pulled from) using 3-way merge
+       and another branch you pulled from) using 3-way merge
        algorithm.  It tries to carefully detect criss-cross
        merge ambiguities and is considered generally safe and
        fast.
 
 recursive::
-       This can only resolve two heads using 3-way merge
-       algorithm.  When there are more than one common
-       ancestors that can be used for 3-way merge, it creates a
+       This can only resolve two heads using 3-way merge
+       algorithm.  When there is more than one common
+       ancestor that can be used for 3-way merge, it creates a
        merged tree of the common ancestors and uses that as
        the reference tree for the 3-way merge.  This has been
        reported to result in fewer merge conflicts without
@@ -22,11 +22,11 @@ recursive::
        pulling or merging one branch.
 
 octopus::
-       This resolves more than two-head case, but refuses to do
-       complex merge that needs manual resolution.  It is
+       This resolves cases with more than two heads, but refuses to do
+       complex merge that needs manual resolution.  It is
        primarily meant to be used for bundling topic branch
        heads together.  This is the default merge strategy when
-       pulling or merging more than one branches.
+       pulling or merging more than one branch.
 
 ours::
        This resolves any number of heads, but the result of the
index e9559790a32185b1d4ac8ae72881f4f63f082538..d66e61b1eca3d87ffcf14ee0e0447b6ccb75a2bb 100644 (file)
@@ -148,22 +148,22 @@ outputting that information, if desired.
 ------------
 *
 *
-M
+*
 |\
 * |
 | | *
 | \ \
 |  \ \
-M-. \ \
+*-. \ \
 |\ \ \ \
 | | * | |
 | | | | | *
 | | | | | *
-| | | | | M
+| | | | | *
 | | | | | |\
 | | | | | | *
 | * | | | | |
-| | | | | M  \
+| | | | | *  \
 | | | | | |\  |
 | | | | * | | |
 | | | | * | | |
index e33b29b1dd58b373a23a939aa2c587b4430b4ff4..dbbeb7e7c7856776450bc64321ff5f1de26202bb 100644 (file)
@@ -188,7 +188,7 @@ As you can see, a commit shows who made the latest change, what they
 did, and why.
 
 Every commit has a 40-hexdigit id, sometimes called the "object name" or the
-"SHA1 id", shown on the first line of the "git-show" output.  You can usually
+"SHA-1 id", shown on the first line of the "git show" output.  You can usually
 refer to a commit by a shorter name, such as a tag or a branch name, but this
 longer name can also be useful.  Most importantly, it is a globally unique
 name for this commit: so if you tell somebody else the object name (for
@@ -307,7 +307,7 @@ ref: refs/heads/master
 Examining an old version without creating a new branch
 ------------------------------------------------------
 
-The git-checkout command normally expects a branch head, but will also
+The `git checkout` command normally expects a branch head, but will also
 accept an arbitrary commit; for example, you can check out the commit
 referenced by a tag:
 
@@ -320,7 +320,7 @@ If you want to create a new branch from this checkout, you may do so
 HEAD is now at 427abfa... Linux v2.6.17
 ------------------------------------------------
 
-The HEAD then refers to the SHA1 of the commit instead of to a branch,
+The HEAD then refers to the SHA-1 of the commit instead of to a branch,
 and git branch shows that you are no longer on a branch:
 
 ------------------------------------------------
@@ -400,7 +400,7 @@ references with the same shorthand name, see the "SPECIFYING
 REVISIONS" section of linkgit:git-rev-parse[1].
 
 [[Updating-a-repository-With-git-fetch]]
-Updating a repository with git-fetch
+Updating a repository with git fetch
 ------------------------------------
 
 Eventually the developer cloned from will do additional work in her
@@ -427,7 +427,7 @@ $ git fetch linux-nfs
 -------------------------------------------------
 
 New remote-tracking branches will be stored under the shorthand name
-that you gave "git-remote add", in this case linux-nfs:
+that you gave "git remote add", in this case linux-nfs:
 
 -------------------------------------------------
 $ git branch -r
@@ -516,7 +516,7 @@ $ git bisect reset
 
 to return you to the branch you were on before.
 
-Note that the version which git-bisect checks out for you at each
+Note that the version which `git bisect` checks out for you at each
 point is just a suggestion, and you're free to try a different
 version if you think it would be a good idea.  For example,
 occasionally you may land on a commit that broke something unrelated;
@@ -592,11 +592,11 @@ In addition to HEAD, there are several other special names for
 commits:
 
 Merges (to be discussed later), as well as operations such as
-git-reset, which change the currently checked-out commit, generally
+`git reset`, which change the currently checked-out commit, generally
 set ORIG_HEAD to the value HEAD had before the current operation.
 
-The git-fetch operation always stores the head of the last fetched
-branch in FETCH_HEAD.  For example, if you run git fetch without
+The `git fetch` operation always stores the head of the last fetched
+branch in FETCH_HEAD.  For example, if you run `git fetch` without
 specifying a local branch as the target of the operation
 
 -------------------------------------------------
@@ -739,7 +739,7 @@ $ git log --pretty=oneline origin..mybranch | wc -l
 -------------------------------------------------
 
 Alternatively, you may often see this sort of thing done with the
-lower-level command linkgit:git-rev-list[1], which just lists the SHA1's
+lower-level command linkgit:git-rev-list[1], which just lists the SHA-1's
 of all the given commits:
 
 -------------------------------------------------
@@ -1073,9 +1073,9 @@ $ git diff
 
 shows the difference between the working tree and the index file.
 
-Note that "git-add" always adds just the current contents of a file
+Note that "git add" always adds just the current contents of a file
 to the index; further changes to the same file will be ignored unless
-you run git-add on the file again.
+you run `git add` on the file again.
 
 When you're ready, just run
 
@@ -1136,7 +1136,7 @@ Ignoring files
 A project will often generate files that you do 'not' want to track with git.
 This typically includes files generated by a build process or temporary
 backup files made by your editor. Of course, 'not' tracking files with git
-is just a matter of 'not' calling `git-add` on them. But it quickly becomes
+is just a matter of 'not' calling `git add` on them. But it quickly becomes
 annoying to have these untracked files lying around; e.g. they make
 `git add .` practically useless, and they keep showing up in the output of
 `git status`.
@@ -1349,7 +1349,7 @@ $ git add file.txt
 -------------------------------------------------
 
 the different stages of that file will be "collapsed", after which
-git-diff will (by default) no longer show diffs for that file.
+`git diff` will (by default) no longer show diffs for that file.
 
 [[undoing-a-merge]]
 Undoing a merge
@@ -1446,7 +1446,7 @@ Fixing a mistake by rewriting history
 
 If the problematic commit is the most recent commit, and you have not
 yet made that commit public, then you may just
-<<undoing-a-merge,destroy it using git-reset>>.
+<<undoing-a-merge,destroy it using `git reset`>>.
 
 Alternatively, you
 can edit the working directory and update the index to fix your
@@ -1474,7 +1474,7 @@ Checking out an old version of a file
 
 In the process of undoing a previous bad change, you may find it
 useful to check out an older version of a particular file using
-linkgit:git-checkout[1].  We've used git-checkout before to switch
+linkgit:git-checkout[1].  We've used `git checkout` before to switch
 branches, but it has quite different behavior if it is given a path
 name: the command
 
@@ -1542,7 +1542,7 @@ $ git gc
 -------------------------------------------------
 
 to recompress the archive.  This can be very time-consuming, so
-you may prefer to run git-gc when you are not doing other work.
+you may prefer to run `git gc` when you are not doing other work.
 
 
 [[ensuring-reliability]]
@@ -1634,7 +1634,7 @@ In some situations the reflog may not be able to save you.  For example,
 suppose you delete a branch, then realize you need the history it
 contained.  The reflog is also deleted; however, if you have not yet
 pruned the repository, then you may still be able to find the lost
-commits in the dangling objects that git-fsck reports.  See
+commits in the dangling objects that `git fsck` reports.  See
 <<dangling-objects>> for the details.
 
 -------------------------------------------------
@@ -1676,7 +1676,7 @@ Sharing development with others
 ===============================
 
 [[getting-updates-With-git-pull]]
-Getting updates with git-pull
+Getting updates with git pull
 -----------------------------
 
 After you clone a repository and make a few changes of your own, you
@@ -1722,7 +1722,7 @@ repository that you pulled from.
 <<fast-forwards,fast forward>>; instead, your branch will just be
 updated to point to the latest commit from the upstream branch.)
 
-The git-pull command can also be given "." as the "remote" repository,
+The `git pull` command can also be given "." as the "remote" repository,
 in which case it just merges in a branch from the current repository; so
 the commands
 
@@ -1795,7 +1795,7 @@ Public git repositories
 Another way to submit changes to a project is to tell the maintainer
 of that project to pull the changes from your repository using
 linkgit:git-pull[1].  In the section "<<getting-updates-With-git-pull,
-Getting updates with git-pull>>" we described this as a way to get
+Getting updates with `git pull`>>" we described this as a way to get
 updates from the "main" repository, but it works just as well in the
 other direction.
 
@@ -1847,7 +1847,7 @@ Setting up a public repository
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Assume your personal repository is in the directory ~/proj.  We
-first create a new clone of the repository and tell git-daemon that it
+first create a new clone of the repository and tell `git daemon` that it
 is meant to be public:
 
 -------------------------------------------------
@@ -1878,10 +1878,10 @@ repository>>", below.
 Otherwise, all you need to do is start linkgit:git-daemon[1]; it will
 listen on port 9418.  By default, it will allow access to any directory
 that looks like a git directory and contains the magic file
-git-daemon-export-ok.  Passing some directory paths as git-daemon
+git-daemon-export-ok.  Passing some directory paths as `git daemon`
 arguments will further restrict the exports to those paths.
 
-You can also run git-daemon as an inetd service; see the
+You can also run `git daemon` as an inetd service; see the
 linkgit:git-daemon[1] man page for details.  (See especially the
 examples section.)
 
@@ -1942,7 +1942,7 @@ or just
 $ git push ssh://yourserver.com/~you/proj.git master
 -------------------------------------------------
 
-As with git-fetch, git-push will complain if this does not result in a
+As with `git fetch`, `git push` will complain if this does not result in a
 <<fast-forwards,fast forward>>; see the following section for details on
 handling this case.
 
@@ -1952,7 +1952,7 @@ repository that has a checked-out working tree, but the working tree
 will not be updated by the push.  This may lead to unexpected results if
 the branch you push to is the currently checked-out branch!
 
-As with git-fetch, you may also set up configuration options to
+As with `git fetch`, you may also set up configuration options to
 save typing; so, for example, after
 
 -------------------------------------------------
@@ -1988,13 +1988,13 @@ error: failed to push to 'ssh://yourserver.com/~you/proj.git'
 
 This can happen, for example, if you:
 
-       - use `git-reset --hard` to remove already-published commits, or
-       - use `git-commit --amend` to replace already-published commits
+       - use `git reset --hard` to remove already-published commits, or
+       - use `git commit --amend` to replace already-published commits
          (as in <<fixing-a-mistake-by-rewriting-history>>), or
-       - use `git-rebase` to rebase any already-published commits (as
+       - use `git rebase` to rebase any already-published commits (as
          in <<using-git-rebase>>).
 
-You may force git-push to perform the update anyway by preceding the
+You may force `git push` to perform the update anyway by preceding the
 branch name with a plus sign:
 
 -------------------------------------------------
@@ -2036,7 +2036,7 @@ advantages over the central shared repository:
 
        - Git's ability to quickly import and merge patches allows a
          single maintainer to process incoming changes even at very
-         high rates.  And when that becomes too much, git-pull provides
+         high rates.  And when that becomes too much, `git pull` provides
          an easy way for that maintainer to delegate this job to other
          maintainers while still allowing optional review of incoming
          changes.
@@ -2404,7 +2404,7 @@ use them, and then explain some of the problems that can arise because
 you are rewriting history.
 
 [[using-git-rebase]]
-Keeping a patch series up to date using git-rebase
+Keeping a patch series up to date using git rebase
 --------------------------------------------------
 
 Suppose that you create a branch "mywork" on a remote-tracking branch
@@ -2468,9 +2468,9 @@ patches to the new mywork.  The result will look like:
 ................................................
 
 In the process, it may discover conflicts.  In that case it will stop
-and allow you to fix the conflicts; after fixing conflicts, use "git-add"
+and allow you to fix the conflicts; after fixing conflicts, use `git add`
 to update the index with those contents, and then, instead of
-running git-commit, just run
+running `git commit`, just run
 
 -------------------------------------------------
 $ git rebase --continue
@@ -2508,7 +2508,7 @@ with
 $ git tag bad mywork~5
 -------------------------------------------------
 
-(Either gitk or git-log may be useful for finding the commit.)
+(Either gitk or `git log` may be useful for finding the commit.)
 
 Then check out that commit, edit it, and rebase the rest of the series
 on top of it (note that we could check out the commit on a temporary
@@ -2549,12 +2549,12 @@ $ gitk origin..mywork &
 
 and browse through the list of patches in the mywork branch using gitk,
 applying them (possibly in a different order) to mywork-new using
-cherry-pick, and possibly modifying them as you go using `commit --amend`.
+cherry-pick, and possibly modifying them as you go using `git commit --amend`.
 The linkgit:git-gui[1] command may also help as it allows you to
 individually select diff hunks for inclusion in the index (by
 right-clicking on the diff hunk and choosing "Stage Hunk for Commit").
 
-Another technique is to use git-format-patch to create a series of
+Another technique is to use `git format-patch` to create a series of
 patches, then reset the state to before the patches:
 
 -------------------------------------------------
@@ -2662,7 +2662,7 @@ you know is that D is bad, that Z is good, and that
 linkgit:git-bisect[1] identifies C as the culprit, how will you
 figure out that the problem is due to this change in semantics?
 
-When the result of a git-bisect is a non-merge commit, you should
+When the result of a `git bisect` is a non-merge commit, you should
 normally be able to discover the problem by examining just that commit.
 Developers can make this easy by breaking their changes into small
 self-contained commits.  That won't help in the case above, however,
@@ -2725,7 +2725,7 @@ master branch.  In more detail:
 git fetch and fast-forwards
 ---------------------------
 
-In the previous example, when updating an existing branch, "git-fetch"
+In the previous example, when updating an existing branch, "git fetch"
 checks to make sure that the most recent commit on the remote
 branch is a descendant of the most recent commit on your copy of the
 branch before updating your copy of the branch to point at the new
@@ -2751,7 +2751,7 @@ resulting in a situation like:
             o--o--o <-- new head of the branch
 ................................................
 
-In this case, "git-fetch" will fail, and print out a warning.
+In this case, "git fetch" will fail, and print out a warning.
 
 In that case, you can still force git to update to the new head, as
 described in the following section.  However, note that in the
@@ -2760,7 +2760,7 @@ unless you've already created a reference of your own pointing to
 them.
 
 [[forcing-fetch]]
-Forcing git-fetch to do non-fast-forward updates
+Forcing git fetch to do non-fast-forward updates
 ------------------------------------------------
 
 If git fetch fails because the new head of a branch is not a
@@ -2865,8 +2865,8 @@ The Object Database
 We already saw in <<understanding-commits>> that all commits are stored
 under a 40-digit "object name".  In fact, all the information needed to
 represent the history of a project is stored in objects with such names.
-In each case the name is calculated by taking the SHA1 hash of the
-contents of the object.  The SHA1 hash is a cryptographic hash function.
+In each case the name is calculated by taking the SHA-1 hash of the
+contents of the object.  The SHA-1 hash is a cryptographic hash function.
 What that means to us is that it is impossible to find two different
 objects with the same name.  This has a number of advantages; among
 others:
@@ -2877,10 +2877,10 @@ others:
   same content stored in two repositories will always be stored under
   the same name.
 - Git can detect errors when it reads an object, by checking that the
-  object's name is still the SHA1 hash of its contents.
+  object's name is still the SHA-1 hash of its contents.
 
 (See <<object-details>> for the details of the object formatting and
-SHA1 calculation.)
+SHA-1 calculation.)
 
 There are four different types of objects: "blob", "tree", "commit", and
 "tag".
@@ -2926,9 +2926,9 @@ committer Junio C Hamano <gitster@pobox.com> 1187591163 -0700
 
 As you can see, a commit is defined by:
 
-- a tree: The SHA1 name of a tree object (as defined below), representing
+- a tree: The SHA-1 name of a tree object (as defined below), representing
   the contents of a directory at a certain point in time.
-- parent(s): The SHA1 name of some number of commits which represent the
+- parent(s): The SHA-1 name of some number of commits which represent the
   immediately previous step(s) in the history of the project.  The
   example above has one parent; merge commits may have more than
   one.  A commit with no parents is called a "root" commit, and
@@ -2977,13 +2977,13 @@ $ git ls-tree fb3a8bdd0ce
 ------------------------------------------------
 
 As you can see, a tree object contains a list of entries, each with a
-mode, object type, SHA1 name, and name, sorted by name.  It represents
+mode, object type, SHA-1 name, and name, sorted by name.  It represents
 the contents of a single directory tree.
 
 The object type may be a blob, representing the contents of a file, or
 another tree, representing the contents of a subdirectory.  Since trees
-and blobs, like all other objects, are named by the SHA1 hash of their
-contents, two trees have the same SHA1 name if and only if their
+and blobs, like all other objects, are named by the SHA-1 hash of their
+contents, two trees have the same SHA-1 name if and only if their
 contents (including, recursively, the contents of all subdirectories)
 are identical.  This allows git to quickly determine the differences
 between two related tree objects, since it can ignore any entries with
@@ -3029,15 +3029,15 @@ currently checked out.
 Trust
 ~~~~~
 
-If you receive the SHA1 name of a blob from one source, and its contents
+If you receive the SHA-1 name of a blob from one source, and its contents
 from another (possibly untrusted) source, you can still trust that those
-contents are correct as long as the SHA1 name agrees.  This is because
-the SHA1 is designed so that it is infeasible to find different contents
+contents are correct as long as the SHA-1 name agrees.  This is because
+the SHA-1 is designed so that it is infeasible to find different contents
 that produce the same hash.
 
-Similarly, you need only trust the SHA1 name of a top-level tree object
+Similarly, you need only trust the SHA-1 name of a top-level tree object
 to trust the contents of the entire directory that it refers to, and if
-you receive the SHA1 name of a commit from a trusted source, then you
+you receive the SHA-1 name of a commit from a trusted source, then you
 can easily verify the entire history of commits reachable through
 parents of that commit, and all of those contents of the trees referred
 to by those commits.
@@ -3049,7 +3049,7 @@ that you trust that commit, and the immutability of the history of
 commits tells others that they can trust the whole history.
 
 In other words, you can easily validate a whole archive by just
-sending out a single email that tells the people the name (SHA1 hash)
+sending out a single email that tells the people the name (SHA-1 hash)
 of the top commit, and digitally sign that email using something
 like GPG/PGP.
 
@@ -3090,7 +3090,7 @@ How git stores objects efficiently: pack files
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Newly created objects are initially created in a file named after the
-object's SHA1 hash (stored in .git/objects).
+object's SHA-1 hash (stored in .git/objects).
 
 Unfortunately this system becomes inefficient once a project has a
 lot of objects.  Try this on an old project:
@@ -3131,7 +3131,7 @@ $ git prune
 
 to remove any of the "loose" objects that are now contained in the
 pack.  This will also remove any unreferenced objects (which may be
-created when, for example, you use "git-reset" to remove a commit).
+created when, for example, you use "git reset" to remove a commit).
 You can verify that the loose objects are gone by looking at the
 .git/objects directory or by running
 
@@ -3160,7 +3160,7 @@ branch still exists, as does everything it pointed to. The branch
 pointer itself just doesn't, since you replaced it with another one.
 
 There are also other situations that cause dangling objects. For
-example, a "dangling blob" may arise because you did a "git-add" of a
+example, a "dangling blob" may arise because you did a "git add" of a
 file, but then, before you actually committed it and made it part of the
 bigger picture, you changed something else in that file and committed
 that *updated* thing--the old state that you added originally ends up
@@ -3210,7 +3210,7 @@ Usually, dangling blobs and trees aren't very interesting. They're
 almost always the result of either being a half-way mergebase (the blob
 will often even have the conflict markers from a merge in it, if you
 have had conflicting merges that you fixed up by hand), or simply
-because you interrupted a "git-fetch" with ^C or something like that,
+because you interrupted a "git fetch" with ^C or something like that,
 leaving _some_ of the new objects in the object database, but just
 dangling and useless.
 
@@ -3225,9 +3225,9 @@ and they'll be gone. But you should only run "git prune" on a quiescent
 repository--it's kind of like doing a filesystem fsck recovery: you
 don't want to do that while the filesystem is mounted.
 
-(The same is true of "git-fsck" itself, btw, but since
-git-fsck never actually *changes* the repository, it just reports
-on what it found, git-fsck itself is never "dangerous" to run.
+(The same is true of "git fsck" itself, btw, but since
+`git fsck` never actually *changes* the repository, it just reports
+on what it found, `git fsck` itself is never 'dangerous' to run.
 Running it while somebody is actually changing the repository can cause
 confusing and scary messages, but it won't actually do anything bad. In
 contrast, running "git prune" while somebody is actively changing the
@@ -3297,7 +3297,7 @@ $ git hash-object -w somedirectory/myfile
 ------------------------------------------------
 
 which will create and store a blob object with the contents of
-somedirectory/myfile, and output the sha1 of that object.  if you're
+somedirectory/myfile, and output the SHA-1 of that object.  if you're
 extremely lucky it might be 4b9458b3786228369c63936db65827de3cc06200, in
 which case you've guessed right, and the corruption is fixed!
 
@@ -3359,7 +3359,7 @@ The index
 -----------
 
 The index is a binary file (generally kept in .git/index) containing a
-sorted list of path names, each with permissions and the SHA1 of a blob
+sorted list of path names, each with permissions and the SHA-1 of a blob
 object; linkgit:git-ls-files[1] can show you the contents of the index:
 
 -------------------------------------------------
@@ -3489,14 +3489,14 @@ done
 
 NOTE: Do not use local URLs here if you plan to publish your superproject!
 
-See what files `git-submodule` created:
+See what files `git submodule` created:
 
 -------------------------------------------------
 $ ls -a
 .  ..  .git  .gitmodules  a  b  c  d
 -------------------------------------------------
 
-The `git-submodule add <repo> <path>` command does a couple of things:
+The `git submodule add <repo> <path>` command does a couple of things:
 
 - It clones the submodule from <repo> to the given <path> under the
   current directory and by default checks out the master branch.
@@ -3542,7 +3542,7 @@ init` to add the submodule repository URLs to `.git/config`:
 $ git submodule init
 -------------------------------------------------
 
-Now use `git-submodule update` to clone the repositories and check out the
+Now use `git submodule update` to clone the repositories and check out the
 commits specified in the superproject:
 
 -------------------------------------------------
@@ -3552,8 +3552,8 @@ $ ls -a
 .  ..  .git  a.txt
 -------------------------------------------------
 
-One major difference between `git-submodule update` and `git-submodule add` is
-that `git-submodule update` checks out a specific commit, rather than the tip
+One major difference between `git submodule update` and `git submodule add` is
+that `git submodule update` checks out a specific commit, rather than the tip
 of a branch. It's like checking out a tag: the head is detached, so you're not
 working on a branch.
 
@@ -3754,7 +3754,7 @@ unsaved state that you might want to restore later!) your current
 index.  Normal operation is just
 
 -------------------------------------------------
-$ git read-tree <sha1 of tree>
+$ git read-tree <SHA-1 of tree>
 -------------------------------------------------
 
 and your index file will now be equivalent to the tree that you saved
@@ -3769,7 +3769,7 @@ You update your working directory from the index by "checking out"
 files. This is not a very common operation, since normally you'd just
 keep your files updated, and rather than write to your working
 directory, you'd tell the index files about the changes in your
-working directory (i.e. `git-update-index`).
+working directory (i.e. `git update-index`).
 
 However, if you decide to jump to a new version, or check out somebody
 else's version, or just restore a previous tree, you'd populate your
@@ -3782,7 +3782,7 @@ $ git checkout-index filename
 
 or, if you want to check out all of the index, use `-a`.
 
-NOTE! git-checkout-index normally refuses to overwrite old files, so
+NOTE! `git checkout-index` normally refuses to overwrite old files, so
 if you have an old version of the tree already checked out, you will
 need to use the "-f" flag ('before' the "-a" flag or the filename) to
 'force' the checkout.
@@ -3820,7 +3820,7 @@ $ git commit-tree <tree> -p <parent> [-p <parent2> ..]
 and then giving the reason for the commit on stdin (either through
 redirection from a pipe or file, or by just typing it at the tty).
 
-git-commit-tree will return the name of the object that represents
+`git commit-tree` will return the name of the object that represents
 that commit, and you should save it away for later use. Normally,
 you'd commit a new `HEAD` state, and while git doesn't care where you
 save the note about that state, in practice we tend to just write the
@@ -3889,7 +3889,7 @@ $ git cat-file blob|tree|commit|tag <objectname>
 
 to show its contents. NOTE! Trees have binary content, and as a result
 there is a special helper for showing that content, called
-`git-ls-tree`, which turns the binary content into a more easily
+`git ls-tree`, which turns the binary content into a more easily
 readable form.
 
 It's especially instructive to look at "commit" objects, since those
@@ -3978,13 +3978,13 @@ $ git ls-files --unmerged
 ------------------------------------------------
 
 Each line of the `git ls-files --unmerged` output begins with
-the blob mode bits, blob SHA1, 'stage number', and the
+the blob mode bits, blob SHA-1, 'stage number', and the
 filename.  The 'stage number' is git's way to say which tree it
 came from: stage 1 corresponds to `$orig` tree, stage 2 `HEAD`
 tree, and stage3 `$target` tree.
 
 Earlier we said that trivial merges are done inside
-`git-read-tree -m`.  For example, if the file did not change
+`git read-tree -m`.  For example, if the file did not change
 from `$orig` to `HEAD` nor `$target`, or if the file changed
 from `$orig` to `HEAD` and `$orig` to `$target` the same way,
 obviously the final outcome is what is in `HEAD`.  What the
@@ -4011,20 +4011,20 @@ $ mv -f hello.c~2 hello.c
 $ git update-index hello.c
 -------------------------------------------------
 
-When a path is in the "unmerged" state, running `git-update-index` for
+When a path is in the "unmerged" state, running `git update-index` for
 that path tells git to mark the path resolved.
 
 The above is the description of a git merge at the lowest level,
 to help you understand what conceptually happens under the hood.
-In practice, nobody, not even git itself, runs `git-cat-file` three times
-for this.  There is a `git-merge-index` program that extracts the
+In practice, nobody, not even git itself, runs `git cat-file` three times
+for this.  There is a `git merge-index` program that extracts the
 stages to temporary files and calls a "merge" script on it:
 
 -------------------------------------------------
 $ git merge-index git-merge-one-file hello.c
 -------------------------------------------------
 
-and that is what higher level `git-merge -s resolve` is implemented with.
+and that is what higher level `git merge -s resolve` is implemented with.
 
 [[hacking-git]]
 Hacking git
@@ -4045,12 +4045,12 @@ objects).  There are currently four different object types: "blob",
 Regardless of object type, all objects share the following
 characteristics: they are all deflated with zlib, and have a header
 that not only specifies their type, but also provides size information
-about the data in the object.  It's worth noting that the SHA1 hash
+about the data in the object.  It's worth noting that the SHA-1 hash
 that is used to name the object is the hash of the original data
 plus this header, so `sha1sum` 'file' does not match the object name
 for 'file'.
 (Historical note: in the dawn of the age of git the hash
-was the sha1 of the 'compressed' object.)
+was the SHA-1 of the 'compressed' object.)
 
 As a result, the general consistency of an object can always be tested
 independently of the contents or the type of the object: all objects can
@@ -4061,7 +4061,7 @@ size> {plus} <byte\0> {plus} <binary object data>.
 
 The structured objects can further have their structure and
 connectivity to other objects verified. This is generally done with
-the `git-fsck` program, which generates a full dependency graph
+the `git fsck` program, which generates a full dependency graph
 of all objects, and verifies their internal consistency (in addition
 to just verifying their superficial consistency through the hash).
 
@@ -4120,7 +4120,7 @@ functions like `get_sha1_basic()` or the likes.
 This is just to get you into the groove for the most libified part of Git:
 the revision walker.
 
-Basically, the initial version of `git-log` was a shell script:
+Basically, the initial version of `git log` was a shell script:
 
 ----------------------------------------------------------------
 $ git-rev-list --pretty $(git-rev-parse --default HEAD "$@") | \
@@ -4129,20 +4129,20 @@ $ git-rev-list --pretty $(git-rev-parse --default HEAD "$@") | \
 
 What does this mean?
 
-`git-rev-list` is the original version of the revision walker, which
+`git rev-list` is the original version of the revision walker, which
 _always_ printed a list of revisions to stdout.  It is still functional,
 and needs to, since most new Git programs start out as scripts using
-`git-rev-list`.
+`git rev-list`.
 
-`git-rev-parse` is not as important any more; it was only used to filter out
+`git rev-parse` is not as important any more; it was only used to filter out
 options that were relevant for the different plumbing commands that were
 called by the script.
 
-Most of what `git-rev-list` did is contained in `revision.c` and
+Most of what `git rev-list` did is contained in `revision.c` and
 `revision.h`.  It wraps the options in a struct named `rev_info`, which
 controls how and what revisions are walked, and more.
 
-The original job of `git-rev-parse` is now taken by the function
+The original job of `git rev-parse` is now taken by the function
 `setup_revisions()`, which parses the revisions and the common command line
 options for the revision walker. This information is stored in the struct
 `rev_info` for later consumption. You can do your own command line option
@@ -4155,7 +4155,7 @@ just have a look at the first implementation of `cmd_log()`; call
 `git show v1.3.0{tilde}155^2{tilde}4` and scroll down to that function (note that you
 no longer need to call `setup_pager()` directly).
 
-Nowadays, `git-log` is a builtin, which means that it is _contained_ in the
+Nowadays, `git log` is a builtin, which means that it is _contained_ in the
 command `git`.  The source side of a builtin is
 
 - a function called `cmd_<bla>`, typically defined in `builtin-<bla>.c`,
@@ -4171,7 +4171,7 @@ since they share quite a bit of code.  In that case, the commands which are
 _not_ named like the `.c` file in which they live have to be listed in
 `BUILT_INS` in the `Makefile`.
 
-`git-log` looks more complicated in C than it does in the original script,
+`git log` looks more complicated in C than it does in the original script,
 but that allows for a much greater flexibility and performance.
 
 Here again it is a good point to take a pause.
@@ -4182,9 +4182,9 @@ the organization of Git (after you know the basic concepts).
 So, think about something which you are interested in, say, "how can I
 access a blob just knowing the object name of it?".  The first step is to
 find a Git command with which you can do it.  In this example, it is either
-`git-show` or `git-cat-file`.
+`git show` or `git cat-file`.
 
-For the sake of clarity, let's stay with `git-cat-file`, because it
+For the sake of clarity, let's stay with `git cat-file`, because it
 
 - is plumbing, and
 
@@ -4198,7 +4198,7 @@ it does.
 ------------------------------------------------------------------
         git_config(git_default_config);
         if (argc != 3)
-                usage("git-cat-file [-t|-s|-e|-p|<type>] <sha1>");
+               usage("git cat-file [-t|-s|-e|-p|<type>] <sha1>");
         if (get_sha1(argv[2], sha1))
                 die("Not a valid object name %s", argv[2]);
 ------------------------------------------------------------------
@@ -4243,10 +4243,10 @@ To find out how the result can be used, just read on in `cmd_cat_file()`:
 -----------------------------------
 
 Sometimes, you do not know where to look for a feature.  In many such cases,
-it helps to search through the output of `git log`, and then `git-show` the
+it helps to search through the output of `git log`, and then `git show` the
 corresponding commit.
 
-Example: If you know that there was some test case for `git-bundle`, but
+Example: If you know that there was some test case for `git bundle`, but
 do not remember where it was (yes, you _could_ `git grep bundle t/`, but that
 does not illustrate the point!):
 
@@ -4530,7 +4530,7 @@ The basic requirements:
 - Whenever possible, section headings should clearly describe the task
   they explain how to do, in language that requires no more knowledge
   than necessary: for example, "importing patches into a project" rather
-  than "the git-am command"
+  than "the `git am` command"
 
 Think about how to create a clear chapter dependency graph that will
 allow people to get to important topics without necessarily reading
index aae3b094116892e54208f0a7198cff4abc0d8b20..7867eaccdb90729aef26dc9f67a45a5a74961aae 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -263,6 +263,18 @@ SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
 BASIC_CFLAGS =
 BASIC_LDFLAGS =
 
+# Guard against environment variables
+BUILTIN_OBJS =
+BUILT_INS =
+COMPAT_CFLAGS =
+COMPAT_OBJS =
+LIB_H =
+LIB_OBJS =
+PROGRAMS =
+SCRIPT_PERL =
+SCRIPT_SH =
+TEST_PROGRAMS =
+
 SCRIPT_SH += git-am.sh
 SCRIPT_SH += git-bisect.sh
 SCRIPT_SH += git-filter-branch.sh
@@ -713,6 +725,7 @@ ifeq ($(uname_S),FreeBSD)
        BASIC_CFLAGS += -I/usr/local/include
        BASIC_LDFLAGS += -L/usr/local/lib
        DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease
+       USE_ST_TIMESPEC = YesPlease
        THREADED_DELTA_SEARCH = YesPlease
        ifeq ($(shell expr "$(uname_R)" : '4\.'),2)
                PTHREAD_LIBS = -pthread
diff --git a/attr.c b/attr.c
index 17f6a4dca521d9690377f2e93a0192d8a874d2ad..43259e5b01f7c8368e5b5d53d8ed4af9dba593ee 100644 (file)
--- a/attr.c
+++ b/attr.c
@@ -1,3 +1,4 @@
+#define NO_THE_INDEX_COMPATIBILITY_MACROS
 #include "cache.h"
 #include "attr.h"
 
@@ -318,6 +319,9 @@ static struct attr_stack *read_attr_from_array(const char **list)
        return res;
 }
 
+static enum git_attr_direction direction;
+static struct index_state *use_index;
+
 static struct attr_stack *read_attr_from_file(const char *path, int macro_ok)
 {
        FILE *fp = fopen(path, "r");
@@ -340,9 +344,10 @@ static void *read_index_data(const char *path)
        unsigned long sz;
        enum object_type type;
        void *data;
+       struct index_state *istate = use_index ? use_index : &the_index;
 
        len = strlen(path);
-       pos = cache_name_pos(path, len);
+       pos = index_name_pos(istate, path, len);
        if (pos < 0) {
                /*
                 * We might be in the middle of a merge, in which
@@ -350,15 +355,15 @@ static void *read_index_data(const char *path)
                 */
                int i;
                for (i = -pos - 1;
-                    (pos < 0 && i < active_nr &&
-                     !strcmp(active_cache[i]->name, path));
+                    (pos < 0 && i < istate->cache_nr &&
+                     !strcmp(istate->cache[i]->name, path));
                     i++)
-                       if (ce_stage(active_cache[i]) == 2)
+                       if (ce_stage(istate->cache[i]) == 2)
                                pos = i;
        }
        if (pos < 0)
                return NULL;
-       data = read_sha1_file(active_cache[pos]->sha1, &type, &sz);
+       data = read_sha1_file(istate->cache[pos]->sha1, &type, &sz);
        if (!data || type != OBJ_BLOB) {
                free(data);
                return NULL;
@@ -366,27 +371,17 @@ static void *read_index_data(const char *path)
        return data;
 }
 
-static struct attr_stack *read_attr(const char *path, int macro_ok)
+static struct attr_stack *read_attr_from_index(const char *path, int macro_ok)
 {
        struct attr_stack *res;
        char *buf, *sp;
        int lineno = 0;
 
-       res = read_attr_from_file(path, macro_ok);
-       if (res)
-               return res;
-
-       res = xcalloc(1, sizeof(*res));
-
-       /*
-        * There is no checked out .gitattributes file there, but
-        * we might have it in the index.  We allow operation in a
-        * sparsely checked out work tree, so read from it.
-        */
        buf = read_index_data(path);
        if (!buf)
-               return res;
+               return NULL;
 
+       res = xcalloc(1, sizeof(*res));
        for (sp = buf; *sp; ) {
                char *ep;
                int more;
@@ -401,6 +396,30 @@ static struct attr_stack *read_attr(const char *path, int macro_ok)
        return res;
 }
 
+static struct attr_stack *read_attr(const char *path, int macro_ok)
+{
+       struct attr_stack *res;
+
+       if (direction == GIT_ATTR_CHECKOUT) {
+               res = read_attr_from_index(path, macro_ok);
+               if (!res)
+                       res = read_attr_from_file(path, macro_ok);
+       }
+       else {
+               res = read_attr_from_file(path, macro_ok);
+               if (!res)
+                       /*
+                        * There is no checked out .gitattributes file there, but
+                        * we might have it in the index.  We allow operation in a
+                        * sparsely checked out work tree, so read from it.
+                        */
+                       res = read_attr_from_index(path, macro_ok);
+       }
+       if (!res)
+               res = xcalloc(1, sizeof(*res));
+       return res;
+}
+
 #if DEBUG_ATTR
 static void debug_info(const char *what, struct attr_stack *elem)
 {
@@ -428,6 +447,15 @@ static void debug_set(const char *what, const char *match, struct git_attr *attr
 #define debug_set(a,b,c,d) do { ; } while (0)
 #endif
 
+static void drop_attr_stack(void)
+{
+       while (attr_stack) {
+               struct attr_stack *elem = attr_stack;
+               attr_stack = elem->prev;
+               free_attr_elem(elem);
+       }
+}
+
 static void bootstrap_attr_stack(void)
 {
        if (!attr_stack) {
@@ -642,3 +670,12 @@ int git_checkattr(const char *path, int num, struct git_attr_check *check)
 
        return 0;
 }
+
+void git_attr_set_direction(enum git_attr_direction new, struct index_state *istate)
+{
+       enum git_attr_direction old = direction;
+       direction = new;
+       if (new != old)
+               drop_attr_stack();
+       use_index = istate;
+}
diff --git a/attr.h b/attr.h
index f1c2038b0923d3130937eef965667204a8634e6d..3a2f4ec1a09cca06fadedeb32bd86c5e279ad75c 100644 (file)
--- a/attr.h
+++ b/attr.h
@@ -31,4 +31,10 @@ struct git_attr_check {
 
 int git_checkattr(const char *path, int, struct git_attr_check *);
 
+enum git_attr_direction {
+       GIT_ATTR_CHECKIN,
+       GIT_ATTR_CHECKOUT
+};
+void git_attr_set_direction(enum git_attr_direction, struct index_state *);
+
 #endif /* ATTR_H */
index b52aa20cfaea76f957741d32240a6cb6e161d60e..1926cd80559d3e6d6e917d1ed37c308c3a06d987 100644 (file)
@@ -2451,7 +2451,7 @@ static int check_preimage(struct patch *patch, struct cache_entry **ce, struct s
        if ((st_mode ^ patch->old_mode) & S_IFMT)
                return error("%s: wrong type", old_name);
        if (st_mode != patch->old_mode)
-               fprintf(stderr, "warning: %s has type %o, expected %o\n",
+               warning("%s has type %o, expected %o",
                        old_name, st_mode, patch->old_mode);
        if (!patch->new_mode && !patch->is_delete)
                patch->new_mode = st_mode;
@@ -2932,8 +2932,7 @@ static int write_out_one_reject(struct patch *patch)
        cnt = strlen(patch->new_name);
        if (ARRAY_SIZE(namebuf) <= cnt + 5) {
                cnt = ARRAY_SIZE(namebuf) - 5;
-               fprintf(stderr,
-                       "warning: truncating .rej filename to %.*s.rej",
+               warning("truncating .rej filename to %.*s.rej",
                        cnt - 1, patch->new_name);
        }
        memcpy(namebuf, patch->new_name, cnt);
@@ -3315,8 +3314,8 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
                    squelch_whitespace_errors < whitespace_error) {
                        int squelched =
                                whitespace_error - squelch_whitespace_errors;
-                       fprintf(stderr, "warning: squelched %d "
-                               "whitespace error%s\n",
+                       warning("squelched %d "
+                               "whitespace error%s",
                                squelched,
                                squelched == 1 ? "" : "s");
                }
@@ -3326,12 +3325,12 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
                            whitespace_error == 1 ? "" : "s",
                            whitespace_error == 1 ? "s" : "");
                if (applied_after_fixing_ws && apply)
-                       fprintf(stderr, "warning: %d line%s applied after"
-                               " fixing whitespace errors.\n",
+                       warning("%d line%s applied after"
+                               " fixing whitespace errors.",
                                applied_after_fixing_ws,
                                applied_after_fixing_ws == 1 ? "" : "s");
                else if (whitespace_error)
-                       fprintf(stderr, "warning: %d line%s add%s whitespace errors.\n",
+                       warning("%d line%s add%s whitespace errors.",
                                whitespace_error,
                                whitespace_error == 1 ? "" : "s",
                                whitespace_error == 1 ? "s" : "");
index 2aedd17c39fdfa12b72551d61af559f534dd65a7..83141fc84e22ad4852f255fa1ad453cc125a3255 100644 (file)
@@ -2250,6 +2250,10 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
 parse_done:
        argc = parse_options_end(&ctx);
 
+       if (revs_file && read_ancestry(revs_file))
+               die("reading graft file %s failed: %s",
+                   revs_file, strerror(errno));
+
        if (cmd_is_annotate) {
                output_option |= OUTPUT_ANNOTATE_COMPAT;
                blame_date_mode = DATE_ISO8601;
@@ -2418,10 +2422,6 @@ parse_done:
        sb.ent = ent;
        sb.path = path;
 
-       if (revs_file && read_ancestry(revs_file))
-               die("reading graft file %s failed: %s",
-                   revs_file, strerror(errno));
-
        read_mailmap(&mailmap, NULL);
 
        if (!incremental)
index 14d4b917e5bb929f40efd3fc5e010cec5d3507de..07a440eebacc1aa4e944874704bedfed7efb00e8 100644 (file)
@@ -171,7 +171,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)
                        ret = 1;
                } else {
                        struct strbuf buf = STRBUF_INIT;
-                       printf("Deleted %sbranch %s (%s).\n", remote,
+                       printf("Deleted %sbranch %s (was %s).\n", remote,
                               bname.buf,
                               find_unique_abbrev(sha1, DEFAULT_ABBREV));
                        strbuf_addf(&buf, "branch.%s", bname.buf);
index 9fdfc58d1a198164727431352e083585d91f2d30..fc55bbe14d58df66e71a9e1975bb7c4eecdc1a49 100644 (file)
@@ -558,8 +558,8 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
 
        if (!old.commit && !opts->force) {
                if (!opts->quiet) {
-                       fprintf(stderr, "warning: You appear to be on a branch yet to be born.\n");
-                       fprintf(stderr, "warning: Forcing checkout of %s.\n", new->name);
+                       warning("You appear to be on a branch yet to be born.");
+                       warning("Forcing checkout of %s.", new->name);
                }
                opts->force = 1;
        }
index 0031b5f51cd96525a265dab02494700e9d36fce8..880373f279dd073ea7f0ae8564daca1cc687e529 100644 (file)
@@ -270,7 +270,7 @@ static const struct ref *clone_local(const char *src_repo,
 
 static const char *junk_work_tree;
 static const char *junk_git_dir;
-pid_t junk_pid;
+static pid_t junk_pid;
 
 static void remove_junk(void)
 {
@@ -406,7 +406,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
        atexit(remove_junk);
        sigchain_push_common(remove_junk_on_signal);
 
-       setenv(CONFIG_ENVIRONMENT, xstrdup(mkpath("%s/config", git_dir)), 1);
+       setenv(CONFIG_ENVIRONMENT, mkpath("%s/config", git_dir), 1);
 
        if (safe_create_leading_directories_const(git_dir) < 0)
                die("could not create leading directories of '%s'", git_dir);
index 46e649cd7ca0a2ede8f010a6d3bf294f81b85d55..81371b1d2698a48dba36046d7ff9d849f830a762 100644 (file)
@@ -224,7 +224,8 @@ static char *prepare_index(int argc, const char **argv, const char *prefix)
        const char **pathspec = NULL;
 
        if (interactive) {
-               interactive_add(argc, argv, prefix);
+               if (interactive_add(argc, argv, prefix) != 0)
+                       die("interactive add failed");
                if (read_cache_preload(NULL) < 0)
                        die("index file corrupt");
                commit_style = COMMIT_AS_IS;
index fdf4ae9ebdba7832a0ac736d56a7b564bba41baa..6731713223d4df24614417cc4285cbee793151d3 100644 (file)
@@ -221,7 +221,8 @@ static void handle_commit(struct commit *commit, struct rev_info *rev)
        if (message)
                message += 2;
 
-       if (commit->parents) {
+       if (commit->parents &&
+           get_object_mark(&commit->parents->item->object) != 0) {
                parse_commit(commit->parents->item);
                diff_tree_sha1(commit->parents->item->tree->object.sha1,
                               commit->tree->object.sha1, "", &rev->diffopt);
@@ -362,7 +363,10 @@ static void get_tags_and_duplicates(struct object_array *pending,
                        break;
                case OBJ_TAG:
                        tag = (struct tag *)e->item;
+
+                       /* handle nested tags */
                        while (tag && tag->object.type == OBJ_TAG) {
+                               parse_object(tag->object.sha1);
                                string_list_append(full_name, extra_refs)->util = tag;
                                tag = (struct tag *)tag->tagged;
                        }
@@ -375,11 +379,17 @@ static void get_tags_and_duplicates(struct object_array *pending,
                        case OBJ_BLOB:
                                handle_object(tag->object.sha1);
                                continue;
+                       default: /* OBJ_TAG (nested tags) is already handled */
+                               warning("Tag points to object of unexpected type %s, skipping.",
+                                       typename(tag->object.type));
+                               continue;
                        }
                        break;
                default:
-                       die ("Unexpected object of type %s",
-                            typename(e->item->type));
+                       warning("%s: Unexpected object of type %s, skipping.",
+                               e->name,
+                               typename(e->item->type));
+                       continue;
                }
                if (commit->util)
                        /* more than one name for the same object */
index d571253a56c80e0b644b220c870b27726c8f3dfc..5d134be47c85019dd66aed742eb845f6245cbf4d 100644 (file)
@@ -605,7 +605,7 @@ static struct ref *do_fetch_pack(int fd[2],
                        /* When cloning, it is not unusual to have
                         * no common commit.
                         */
-                       fprintf(stderr, "warning: no common commits\n");
+                       warning("no common commits");
 
        if (get_pack(fd, pack_lockfile))
                die("git fetch-pack: fetch failed.");
index 7fb35fca9d1b57dacaebfd3cb9b2af4d035e750c..3c998ea740adf474ee980fc763bd7156b9ce81af 100644 (file)
@@ -197,11 +197,7 @@ static int update_local_ref(struct ref *ref,
        struct commit *current = NULL, *updated;
        enum object_type type;
        struct branch *current_branch = branch_get(NULL);
-       const char *pretty_ref = ref->name + (
-               !prefixcmp(ref->name, "refs/heads/") ? 11 :
-               !prefixcmp(ref->name, "refs/tags/") ? 10 :
-               !prefixcmp(ref->name, "refs/remotes/") ? 13 :
-               0);
+       const char *pretty_ref = prettify_ref(ref);
 
        *display = 0;
        type = sha1_object_info(ref->new_sha1, NULL);
@@ -544,7 +540,8 @@ static void check_not_current_branch(struct ref *ref_map)
        for (; ref_map; ref_map = ref_map->next)
                if (ref_map->peer_ref && !strcmp(current_branch->refname,
                                        ref_map->peer_ref->name))
-                       die("Refusing to fetch into current branch");
+                       die("Refusing to fetch into current branch %s "
+                           "of non-bare repository", current_branch->refname);
 }
 
 static int do_fetch(struct transport *transport,
index ee3911f8eef5c00eeb4868c843f2b8c5c83d688d..fc63d0fce5d3067bec884ac3ccaf12e0fd0d4468 100644 (file)
@@ -130,8 +130,7 @@ static void copy_templates(const char *template_dir)
        }
        dir = opendir(template_path);
        if (!dir) {
-               fprintf(stderr, "warning: templates not found %s\n",
-                       template_dir);
+               warning("templates not found %s", template_dir);
                return;
        }
 
@@ -144,8 +143,8 @@ static void copy_templates(const char *template_dir)
 
        if (repository_format_version &&
            repository_format_version != GIT_REPO_VERSION) {
-               fprintf(stderr, "warning: not copying templates of "
-                       "a wrong format version %d from '%s'\n",
+               warning("not copying templates of "
+                       "a wrong format version %d from '%s'",
                        repository_format_version,
                        template_dir);
                closedir(dir);
index 3e3cbc11fd80d3409a9e880c2307680e9701afb7..5eaec5d24e6ca70af2879ce9439eb2ba831211b6 100644 (file)
@@ -458,6 +458,7 @@ static void add_header(const char *value)
 #define THREAD_SHALLOW 1
 #define THREAD_DEEP 2
 static int thread = 0;
+static int do_signoff = 0;
 
 static int git_format_config(const char *var, const char *value, void *cb)
 {
@@ -507,6 +508,10 @@ static int git_format_config(const char *var, const char *value, void *cb)
                thread = git_config_bool(var, value) && THREAD_SHALLOW;
                return 0;
        }
+       if (!strcmp(var, "format.signoff")) {
+               do_signoff = git_config_bool(var, value);
+               return 0;
+       }
 
        return git_log_config(var, value, cb);
 }
@@ -818,13 +823,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                }
                else if (!strcmp(argv[i], "--signoff") ||
                         !strcmp(argv[i], "-s")) {
-                       const char *committer;
-                       const char *endpos;
-                       committer = git_committer_info(IDENT_ERROR_ON_NO_NAME);
-                       endpos = strchr(committer, '>');
-                       if (!endpos)
-                               die("bogus committer info %s", committer);
-                       add_signoff = xmemdupz(committer, endpos - committer + 1);
+                       do_signoff = 1;
                }
                else if (!strcmp(argv[i], "--attach")) {
                        rev.mime_boundary = git_version_string;
@@ -871,11 +870,23 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                        cover_letter = 1;
                else if (!strcmp(argv[i], "--no-binary"))
                        no_binary_diff = 1;
+               else if (!prefixcmp(argv[i], "--add-header="))
+                       add_header(argv[i] + 13);
                else
                        argv[j++] = argv[i];
        }
        argc = j;
 
+       if (do_signoff) {
+               const char *committer;
+               const char *endpos;
+               committer = git_committer_info(IDENT_ERROR_ON_NO_NAME);
+               endpos = strchr(committer, '>');
+               if (!endpos)
+                       die("bogus committer info %s", committer);
+               add_signoff = xmemdupz(committer, endpos - committer + 1);
+       }
+
        for (i = 0; i < extra_hdr_nr; i++) {
                strbuf_addstr(&buf, extra_hdr[i]);
                strbuf_addch(&buf, '\n');
index 1c6d2c498bae77aab0aaf32ba6f857fbb7ead44f..9fc3b355470466bd5663e1fca1fe759e18869ee2 100644 (file)
@@ -1293,7 +1293,7 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
                max_size = trg_entry->delta_size;
                ref_depth = trg->depth;
        }
-       max_size = max_size * (max_depth - src->depth) /
+       max_size = (uint64_t)max_size * (max_depth - src->depth) /
                                                (max_depth - ref_depth + 1);
        if (max_size == 0)
                return 0;
@@ -1966,7 +1966,7 @@ static void add_objects_in_unpacked_packs(struct rev_info *revs)
                const unsigned char *sha1;
                struct object *o;
 
-               if (p->pack_keep)
+               if (!p->pack_local || p->pack_keep)
                        continue;
                if (open_pack_index(p))
                        die("cannot open pack index");
@@ -1995,6 +1995,29 @@ static void add_objects_in_unpacked_packs(struct rev_info *revs)
        free(in_pack.array);
 }
 
+static int has_sha1_pack_kept_or_nonlocal(const unsigned char *sha1)
+{
+       static struct packed_git *last_found = (void *)1;
+       struct packed_git *p;
+
+       p = (last_found != (void *)1) ? last_found : packed_git;
+
+       while (p) {
+               if ((!p->pack_local || p->pack_keep) &&
+                       find_pack_entry_one(sha1, p)) {
+                       last_found = p;
+                       return 1;
+               }
+               if (p == last_found)
+                       p = packed_git;
+               else
+                       p = p->next;
+               if (p == last_found)
+                       p = p->next;
+       }
+       return 0;
+}
+
 static void loosen_unused_packed_objects(struct rev_info *revs)
 {
        struct packed_git *p;
@@ -2002,7 +2025,7 @@ static void loosen_unused_packed_objects(struct rev_info *revs)
        const unsigned char *sha1;
 
        for (p = packed_git; p; p = p->next) {
-               if (p->pack_keep)
+               if (!p->pack_local || p->pack_keep)
                        continue;
 
                if (open_pack_index(p))
@@ -2010,7 +2033,8 @@ static void loosen_unused_packed_objects(struct rev_info *revs)
 
                for (i = 0; i < p->num_objects; i++) {
                        sha1 = nth_packed_object_sha1(p, i);
-                       if (!locate_object_entry(sha1))
+                       if (!locate_object_entry(sha1) &&
+                               !has_sha1_pack_kept_or_nonlocal(sha1))
                                if (force_object_loose(sha1, p->mtime))
                                        die("unable to force loose object");
                }
@@ -2200,7 +2224,6 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
                        continue;
                }
                if (!strcmp("--unpacked", arg) ||
-                   !strcmp("--kept-pack-only", arg) ||
                    !strcmp("--reflog", arg) ||
                    !strcmp("--all", arg)) {
                        use_internal_rev_list = 1;
index ca36fb1e5834fc581bc7bf8ed54184bbecdc2389..2eabcd3bdfb3f5d5705125a8f74d21d4ab1deafc 100644 (file)
@@ -48,6 +48,71 @@ static void set_refspecs(const char **refs, int nr)
        }
 }
 
+static void setup_push_tracking(void)
+{
+       struct strbuf refspec = STRBUF_INIT;
+       struct branch *branch = branch_get(NULL);
+       if (!branch)
+               die("You are not currently on a branch.");
+       if (!branch->merge_nr)
+               die("The current branch %s is not tracking anything.",
+                   branch->name);
+       if (branch->merge_nr != 1)
+               die("The current branch %s is tracking multiple branches, "
+                   "refusing to push.", branch->name);
+       strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src);
+       add_refspec(refspec.buf);
+}
+
+static const char *warn_unconfigured_push_msg[] = {
+       "You did not specify any refspecs to push, and the current remote",
+       "has not configured any push refspecs. The default action in this",
+       "case is to push all matching refspecs, that is, all branches",
+       "that exist both locally and remotely will be updated.  This may",
+       "not necessarily be what you want to happen.",
+       "",
+       "You can specify what action you want to take in this case, and",
+       "avoid seeing this message again, by configuring 'push.default' to:",
+       "  'nothing'  : Do not push anything",
+       "  'matching' : Push all matching branches (default)",
+       "  'tracking' : Push the current branch to whatever it is tracking",
+       "  'current'  : Push the current branch"
+};
+
+static void warn_unconfigured_push(void)
+{
+       int i;
+       for (i = 0; i < ARRAY_SIZE(warn_unconfigured_push_msg); i++)
+               warning("%s", warn_unconfigured_push_msg[i]);
+}
+
+static void setup_default_push_refspecs(void)
+{
+       git_config(git_default_config, NULL);
+       switch (push_default) {
+       case PUSH_DEFAULT_UNSPECIFIED:
+               warn_unconfigured_push();
+               /* fallthrough */
+
+       case PUSH_DEFAULT_MATCHING:
+               add_refspec(":");
+               break;
+
+       case PUSH_DEFAULT_TRACKING:
+               setup_push_tracking();
+               break;
+
+       case PUSH_DEFAULT_CURRENT:
+               add_refspec("HEAD");
+               break;
+
+       case PUSH_DEFAULT_NOTHING:
+               die("You didn't specify any refspecs to push, and "
+                   "push.default is \"nothing\".");
+               break;
+       }
+}
+
 static int do_push(const char *repo, int flags)
 {
        int i, errs;
@@ -79,11 +144,12 @@ static int do_push(const char *repo, int flags)
                return error("--all and --mirror are incompatible");
        }
 
-       if (!refspec
-               && !(flags & TRANSPORT_PUSH_ALL)
-               && remote->push_refspec_nr) {
-               refspec = remote->push_refspec;
-               refspec_nr = remote->push_refspec_nr;
+       if (!refspec && !(flags & TRANSPORT_PUSH_ALL)) {
+               if (remote->push_refspec_nr) {
+                       refspec = remote->push_refspec;
+                       refspec_nr = remote->push_refspec_nr;
+               } else if (!(flags & TRANSPORT_PUSH_MIRROR))
+                       setup_default_push_refspecs();
        }
        errs = 0;
        for (i = 0; i < remote->url_nr; i++) {
index 993acd6a09869e23b3f8e67f0dddbddc946e6c5f..9ef846f6a48d60f743f5a8fdd769633a5727caf9 100644 (file)
@@ -922,6 +922,20 @@ int add_push_to_show_info(struct string_list_item *push_item, void *cb_data)
        return 0;
 }
 
+/*
+ * Sorting comparison for a string list that has push_info
+ * structs in its util field
+ */
+static int cmp_string_with_push(const void *va, const void *vb)
+{
+       const struct string_list_item *a = va;
+       const struct string_list_item *b = vb;
+       const struct push_info *a_push = a->util;
+       const struct push_info *b_push = b->util;
+       int cmp = strcmp(a->string, b->string);
+       return cmp ? cmp : strcmp(a_push->dest, b_push->dest);
+}
+
 int show_push_info_item(struct string_list_item *item, void *cb_data)
 {
        struct show_info *show_info = cb_data;
@@ -1032,7 +1046,8 @@ static int show(int argc, const char **argv)
 
                info.width = info.width2 = 0;
                for_each_string_list(add_push_to_show_info, &states.push, &info);
-               sort_string_list(info.list);
+               qsort(info.list->items, info.list->nr,
+                       sizeof(*info.list->items), cmp_string_with_push);
                if (info.list->nr)
                        printf("  Local ref%s configured for 'git push'%s:\n",
                                info.list->nr > 1 ? "s" : "",
index c11f45585825962e61bdee4bdd6df206f0a141c6..269d60890ac6732f05b835e88bdb60a10bb3d441 100644 (file)
@@ -59,8 +59,7 @@ static int check_local_mod(unsigned char *head, int index_only)
 
                if (lstat(ce->name, &st) < 0) {
                        if (errno != ENOENT)
-                               fprintf(stderr, "warning: '%s': %s",
-                                       ce->name, strerror(errno));
+                               warning("'%s': %s", ce->name, strerror(errno));
                        /* It already vanished from the working tree */
                        continue;
                }
index 9072905f10cbbb0f8297bc1b1c7dfb12613c80a7..d5a1c48d0e2abab16c646ce86ac9670b95dddc07 100644 (file)
@@ -10,9 +10,7 @@ static const char send_pack_usage[] =
 "git send-pack [--all | --mirror] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\n"
 "  --all and explicit <ref> specification are mutually exclusive.";
 
-static struct send_pack_args args = {
-       /* .receivepack = */ "git-receive-pack",
-};
+static struct send_pack_args args;
 
 static int feed_object(const unsigned char *sha1, int fd, int negative)
 {
@@ -31,7 +29,7 @@ static int feed_object(const unsigned char *sha1, int fd, int negative)
 /*
  * Make a pack stream and spit it out into file descriptor fd
  */
-static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *extra)
+static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *extra, struct send_pack_args *args)
 {
        /*
         * The child becomes pack-objects --revs; we feed
@@ -49,7 +47,7 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext
        struct child_process po;
        int i;
 
-       if (args.use_thin_pack)
+       if (args->use_thin_pack)
                argv[4] = "--thin";
        memset(&po, 0, sizeof(po));
        po.argv = argv;
@@ -83,8 +81,6 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext
        return 0;
 }
 
-static struct ref *remote_refs, **remote_tail;
-
 static int receive_status(int in, struct ref *refs)
 {
        struct ref *hint;
@@ -172,16 +168,6 @@ static void update_tracking_ref(struct remote *remote, struct ref *ref)
        }
 }
 
-static const char *prettify_ref(const struct ref *ref)
-{
-       const char *name = ref->name;
-       return name + (
-               !prefixcmp(name, "refs/heads/") ? 11 :
-               !prefixcmp(name, "refs/tags/") ? 10 :
-               !prefixcmp(name, "refs/remotes/") ? 13 :
-               0);
-}
-
 #define SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3)
 
 static void print_ref_status(char flag, const char *summary, struct ref *to, struct ref *from, const char *msg)
@@ -310,27 +296,19 @@ static int refs_pushed(struct ref *ref)
        return 0;
 }
 
-static int do_send_pack(int in, int out, struct remote *remote, const char *dest, int nr_refspec, const char **refspec)
+int send_pack(struct send_pack_args *args,
+             int fd[], struct child_process *conn,
+             struct ref *remote_refs,
+             struct extra_have_objects *extra_have)
 {
-       struct ref *ref, *local_refs;
+       int in = fd[0];
+       int out = fd[1];
+       struct ref *ref;
        int new_refs;
        int ask_for_status_report = 0;
        int allow_deleting_refs = 0;
        int expect_status_report = 0;
-       int flags = MATCH_REFS_NONE;
        int ret;
-       struct extra_have_objects extra_have;
-
-       memset(&extra_have, 0, sizeof(extra_have));
-       if (args.send_all)
-               flags |= MATCH_REFS_ALL;
-       if (args.send_mirror)
-               flags |= MATCH_REFS_MIRROR;
-
-       /* No funny business with the matcher */
-       remote_tail = get_remote_heads(in, &remote_refs, 0, NULL, REF_NORMAL,
-                                      &extra_have);
-       local_refs = get_local_heads();
 
        /* Does the other end support the reporting? */
        if (server_supports("report-status"))
@@ -338,19 +316,9 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
        if (server_supports("delete-refs"))
                allow_deleting_refs = 1;
 
-       /* match them up */
-       if (!remote_tail)
-               remote_tail = &remote_refs;
-       if (match_refs(local_refs, remote_refs, &remote_tail,
-                      nr_refspec, refspec, flags)) {
-               close(out);
-               return -1;
-       }
-
        if (!remote_refs) {
                fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
                        "Perhaps you should specify a branch such as 'master'.\n");
-               close(out);
                return 0;
        }
 
@@ -362,7 +330,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
 
                if (ref->peer_ref)
                        hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
-               else if (!args.send_mirror)
+               else if (!args->send_mirror)
                        continue;
 
                ref->deletion = is_null_sha1(ref->new_sha1);
@@ -401,7 +369,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
                    (!has_sha1_file(ref->old_sha1)
                      || !ref_newer(ref->new_sha1, ref->old_sha1));
 
-               if (ref->nonfastforward && !ref->force && !args.force_update) {
+               if (ref->nonfastforward && !ref->force && !args->force_update) {
                        ref->status = REF_STATUS_REJECT_NONFASTFORWARD;
                        continue;
                }
@@ -409,7 +377,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
                if (!ref->deletion)
                        new_refs++;
 
-               if (!args.dry_run) {
+               if (!args->dry_run) {
                        char *old_hex = sha1_to_hex(ref->old_sha1);
                        char *new_hex = sha1_to_hex(ref->new_sha1);
 
@@ -430,27 +398,19 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
        }
 
        packet_flush(out);
-       if (new_refs && !args.dry_run) {
-               if (pack_objects(out, remote_refs, &extra_have) < 0)
+       if (new_refs && !args->dry_run) {
+               if (pack_objects(out, remote_refs, extra_have, args) < 0) {
+                       for (ref = remote_refs; ref; ref = ref->next)
+                               ref->status = REF_STATUS_NONE;
                        return -1;
+               }
        }
-       else
-               close(out);
 
        if (expect_status_report)
                ret = receive_status(in, remote_refs);
        else
                ret = 0;
 
-       print_push_status(dest, remote_refs);
-
-       if (!args.dry_run && remote) {
-               for (ref = remote_refs; ref; ref = ref->next)
-                       update_tracking_ref(remote, ref);
-       }
-
-       if (!refs_pushed(remote_refs))
-               fprintf(stderr, "Everything up-to-date\n");
        if (ret < 0)
                return ret;
        for (ref = remote_refs; ref; ref = ref->next) {
@@ -499,11 +459,19 @@ static void verify_remote_names(int nr_heads, const char **heads)
 
 int cmd_send_pack(int argc, const char **argv, const char *prefix)
 {
-       int i, nr_heads = 0;
-       const char **heads = NULL;
+       int i, nr_refspecs = 0;
+       const char **refspecs = NULL;
        const char *remote_name = NULL;
        struct remote *remote = NULL;
        const char *dest = NULL;
+       int fd[2];
+       struct child_process *conn;
+       struct extra_have_objects extra_have;
+       struct ref *remote_refs, **remote_tail, *local_refs;
+       int ret;
+       int send_all = 0;
+       const char *receivepack = "git-receive-pack";
+       int flags;
 
        argv++;
        for (i = 1; i < argc; i++, argv++) {
@@ -511,11 +479,11 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
 
                if (*arg == '-') {
                        if (!prefixcmp(arg, "--receive-pack=")) {
-                               args.receivepack = arg + 15;
+                               receivepack = arg + 15;
                                continue;
                        }
                        if (!prefixcmp(arg, "--exec=")) {
-                               args.receivepack = arg + 7;
+                               receivepack = arg + 7;
                                continue;
                        }
                        if (!prefixcmp(arg, "--remote=")) {
@@ -523,7 +491,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
                                continue;
                        }
                        if (!strcmp(arg, "--all")) {
-                               args.send_all = 1;
+                               send_all = 1;
                                continue;
                        }
                        if (!strcmp(arg, "--dry-run")) {
@@ -552,8 +520,8 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
                        dest = arg;
                        continue;
                }
-               heads = (const char **) argv;
-               nr_heads = argc - i;
+               refspecs = (const char **) argv;
+               nr_refspecs = argc - i;
                break;
        }
        if (!dest)
@@ -562,8 +530,8 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
         * --all and --mirror are incompatible; neither makes sense
         * with any refspecs.
         */
-       if ((heads && (args.send_all || args.send_mirror)) ||
-                                       (args.send_all && args.send_mirror))
+       if ((refspecs && (send_all || args.send_mirror)) ||
+           (send_all && args.send_mirror))
                usage(send_pack_usage);
 
        if (remote_name) {
@@ -574,24 +542,50 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
                }
        }
 
-       return send_pack(&args, dest, remote, nr_heads, heads);
-}
+       conn = git_connect(fd, dest, receivepack, args.verbose ? CONNECT_VERBOSE : 0);
 
-int send_pack(struct send_pack_args *my_args,
-             const char *dest, struct remote *remote,
-             int nr_heads, const char **heads)
-{
-       int fd[2], ret;
-       struct child_process *conn;
+       memset(&extra_have, 0, sizeof(extra_have));
+
+       get_remote_heads(fd[0], &remote_refs, 0, NULL, REF_NORMAL,
+                        &extra_have);
 
-       memcpy(&args, my_args, sizeof(args));
+       verify_remote_names(nr_refspecs, refspecs);
+
+       local_refs = get_local_heads();
+
+       flags = MATCH_REFS_NONE;
+
+       if (send_all)
+               flags |= MATCH_REFS_ALL;
+       if (args.send_mirror)
+               flags |= MATCH_REFS_MIRROR;
+
+       /* match them up */
+       remote_tail = &remote_refs;
+       while (*remote_tail)
+               remote_tail = &((*remote_tail)->next);
+       if (match_refs(local_refs, remote_refs, &remote_tail,
+                      nr_refspecs, refspecs, flags)) {
+               return -1;
+       }
 
-       verify_remote_names(nr_heads, heads);
+       ret = send_pack(&args, fd, conn, remote_refs, &extra_have);
 
-       conn = git_connect(fd, dest, args.receivepack, args.verbose ? CONNECT_VERBOSE : 0);
-       ret = do_send_pack(fd[0], fd[1], remote, dest, nr_heads, heads);
+       close(fd[1]);
        close(fd[0]);
-       /* do_send_pack always closes fd[1] */
+
        ret |= finish_connect(conn);
-       return !!ret;
+
+       print_push_status(dest, remote_refs);
+
+       if (!args.dry_run && remote) {
+               struct ref *ref;
+               for (ref = remote_refs; ref; ref = ref->next)
+                       update_tracking_ref(remote, ref);
+       }
+
+       if (!ret && !refs_pushed(remote_refs))
+               fprintf(stderr, "Everything up-to-date\n");
+
+       return ret;
 }
index 306b850c720ecef7030bd7139f7c7d2758125ac4..828e6f86de22f8def68a49b702a27521c248a012 100644 (file)
@@ -365,8 +365,7 @@ static int append_ref(const char *refname, const unsigned char *sha1,
                                return 0;
        }
        if (MAX_REVS <= ref_name_cnt) {
-               fprintf(stderr, "warning: ignoring %s; "
-                       "cannot handle more than %d refs\n",
+               warning("ignoring %s; cannot handle more than %d refs",
                        refname, MAX_REVS);
                return 0;
        }
index 572b114119db15f5f42dd79e3bc15e6d219f71db..dc76c5090f2367426201b37c5b13c2a5cbf00de2 100644 (file)
@@ -140,7 +140,7 @@ static int exclude_existing(const char *match)
                                continue;
                }
                if (check_ref_format(ref)) {
-                       fprintf(stderr, "warning: ref '%s' ignored\n", ref);
+                       warning("ref '%s' ignored", ref);
                        continue;
                }
                if (!string_list_has_string(&existing_refs, ref)) {
diff --git a/cache.h b/cache.h
index 39789ee94a2f2e7dd1600115f4033ccf0e52c07b..9cf5a13c2cbec321aa728f5024a48e3291fb697d 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -542,8 +542,17 @@ enum rebase_setup_type {
        AUTOREBASE_ALWAYS,
 };
 
+enum push_default_type {
+       PUSH_DEFAULT_UNSPECIFIED = -1,
+       PUSH_DEFAULT_NOTHING = 0,
+       PUSH_DEFAULT_MATCHING,
+       PUSH_DEFAULT_TRACKING,
+       PUSH_DEFAULT_CURRENT,
+};
+
 extern enum branch_track git_branch_track;
 extern enum rebase_setup_type autorebase;
+extern enum push_default_type push_default;
 
 #define GIT_REPO_VERSION 0
 extern int repository_format_version;
@@ -646,7 +655,6 @@ extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned l
 extern int move_temp_to_file(const char *tmpfile, const char *filename);
 
 extern int has_sha1_pack(const unsigned char *sha1);
-extern int has_sha1_kept_pack(const unsigned char *sha1);
 extern int has_sha1_file(const unsigned char *sha1);
 extern int has_loose_object_nonlocal(const unsigned char *sha1);
 
index 171fa85e4ae9fa026bbb72e2e8b8b098d2ba22ed..2839d9df6ee8ed1e7227769877b04dd9b542f496 100644 (file)
@@ -457,7 +457,7 @@ static const char *quote_arg(const char *arg)
        const char *p = arg;
        if (!*p) force_quotes = 1;
        while (*p) {
-               if (isspace(*p) || *p == '*' || *p == '?' || *p == '{')
+               if (isspace(*p) || *p == '*' || *p == '?' || *p == '{' || *p == '\'')
                        force_quotes = 1;
                else if (*p == '"')
                        n++;
index 50efd639c4d68af1428a8a45606ae4897a8d2dd9..b76fe4c6dcc966f8c7c15da44d15f7cf45740f5b 100644 (file)
--- a/config.c
+++ b/config.c
@@ -565,6 +565,31 @@ static int git_default_branch_config(const char *var, const char *value)
        return 0;
 }
 
+static int git_default_push_config(const char *var, const char *value)
+{
+       if (!strcmp(var, "push.default")) {
+               if (!value)
+                       return config_error_nonbool(var);
+               else if (!strcmp(value, "nothing"))
+                       push_default = PUSH_DEFAULT_NOTHING;
+               else if (!strcmp(value, "matching"))
+                       push_default = PUSH_DEFAULT_MATCHING;
+               else if (!strcmp(value, "tracking"))
+                       push_default = PUSH_DEFAULT_TRACKING;
+               else if (!strcmp(value, "current"))
+                       push_default = PUSH_DEFAULT_CURRENT;
+               else {
+                       error("Malformed value for %s: %s", var, value);
+                       return error("Must be one of nothing, matching, "
+                                    "tracking or current.");
+               }
+               return 0;
+       }
+
+       /* Add other config variables here and to Documentation/config.txt. */
+       return 0;
+}
+
 static int git_default_mailmap_config(const char *var, const char *value)
 {
        if (!strcmp(var, "mailmap.file"))
@@ -588,6 +613,9 @@ int git_default_config(const char *var, const char *value, void *dummy)
        if (!prefixcmp(var, "branch."))
                return git_default_branch_config(var, value);
 
+       if (!prefixcmp(var, "push."))
+               return git_default_push_config(var, value);
+
        if (!prefixcmp(var, "mailmap."))
                return git_default_mailmap_config(var, value);
 
index ed235f759645c0f657d47b3f0d73a3bcfbf6b1d6..d3d8203171a3c7c221399dd6d79c8429c5006bcc 100755 (executable)
@@ -646,7 +646,8 @@ _git_am ()
                ;;
        --*)
                __gitcomp "
-                       --signoff --utf8 --binary --3way --interactive
+                       --3way --committer-date-is-author-date --ignore-date
+                       --interactive --keep --no-utf8 --signoff --utf8
                        --whitespace=
                        "
                return
@@ -899,7 +900,7 @@ _git_diff ()
        local cur="${COMP_WORDS[COMP_CWORD]}"
        case "$cur" in
        --*)
-               __gitcomp "--cached --pickaxe-all --pickaxe-regex
+               __gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
                        --base --ours --theirs
                        $__git_diff_common_options
                        "
@@ -930,15 +931,21 @@ _git_format_patch ()
 {
        local cur="${COMP_WORDS[COMP_CWORD]}"
        case "$cur" in
+       --thread=*)
+               __gitcomp "
+                       deep shallow
+                       " "" "${cur##--thread=}"
+               return
+               ;;
        --*)
                __gitcomp "
-                       --stdout --attach --thread
+                       --stdout --attach --no-attach --thread --thread=
                        --output-directory
                        --numbered --start-number
                        --numbered-files
                        --keep-subject
                        --signoff
-                       --in-reply-to=
+                       --in-reply-to= --cc=
                        --full-index --binary
                        --not --all
                        --cover-letter
@@ -952,6 +959,21 @@ _git_format_patch ()
        __git_complete_revlist
 }
 
+_git_fsck ()
+{
+       local cur="${COMP_WORDS[COMP_CWORD]}"
+       case "$cur" in
+       --*)
+               __gitcomp "
+                       --tags --root --unreachable --cache --no-reflogs --full
+                       --strict --verbose --lost-found
+                       "
+               return
+               ;;
+       esac
+       COMPREPLY=()
+}
+
 _git_gc ()
 {
        local cur="${COMP_WORDS[COMP_CWORD]}"
@@ -1082,7 +1104,7 @@ _git_log ()
        local cur="${COMP_WORDS[COMP_CWORD]}"
        local g="$(git rev-parse --git-dir 2>/dev/null)"
        local merge=""
-       if [ -f $g/MERGE_HEAD ]; then
+       if [ -f "$g/MERGE_HEAD" ]; then
                merge="--merge"
        fi
        case "$cur" in
@@ -1249,8 +1271,8 @@ _git_send_email ()
        local cur="${COMP_WORDS[COMP_CWORD]}"
        case "$cur" in
        --*)
-               __gitcomp "--bcc --cc --cc-cmd --chain-reply-to --compose
-                       --dry-run --envelope-sender --from --identity
+               __gitcomp "--annotate --bcc --cc --cc-cmd --chain-reply-to
+                       --compose --dry-run --envelope-sender --from --identity
                        --in-reply-to --no-chain-reply-to --no-signed-off-by-cc
                        --no-suppress-from --no-thread --quiet
                        --signed-off-by-cc --smtp-pass --smtp-server
@@ -1880,6 +1902,7 @@ _git ()
        diff)        _git_diff ;;
        fetch)       _git_fetch ;;
        format-patch) _git_format_patch ;;
+       fsck)        _git_fsck ;;
        gc)          _git_gc ;;
        grep)        _git_grep ;;
        help)        _git_help ;;
@@ -1921,7 +1944,7 @@ _gitk ()
        local cur="${COMP_WORDS[COMP_CWORD]}"
        local g="$(__gitdir)"
        local merge=""
-       if [ -f $g/MERGE_HEAD ]; then
+       if [ -f "$g/MERGE_HEAD" ]; then
                merge="--merge"
        fi
        case "$cur" in
index c674fa2d1b5c6ab47ebb5e828c427c6d47bb50fc..7051a83a59758277dd60fe026dea730eb7b6b115 100755 (executable)
@@ -44,7 +44,8 @@ for zipfile in argv[1:]:
                        common_prefix = name[:name.rfind('/') + 1]
                else:
                        while not name.startswith(common_prefix):
-                               common_prefix = name[:name.rfind('/') + 1]
+                               last_slash = common_prefix[:-1].rfind('/') + 1
+                               common_prefix = common_prefix[:last_slash]
 
                mark[name] = ':' + str(next_mark)
                next_mark += 1
index 598687b50ac7b88ca0860faf1670d03047bb3603..42c1dd8ad3b0633767bf577975a895722f882565 100644 (file)
@@ -205,8 +205,6 @@ void diff_no_index(struct rev_info *revs,
                    no_index ? "--no-index" : "[--no-index]");
 
        diff_setup(&revs->diffopt);
-       if (!revs->diffopt.output_format)
-               revs->diffopt.output_format = DIFF_FORMAT_PATCH;
        for (i = 1; i < argc - 2; ) {
                int j;
                if (!strcmp(argv[i], "--no-index"))
@@ -252,6 +250,8 @@ void diff_no_index(struct rev_info *revs,
                revs->diffopt.paths = argv + argc - 2;
        revs->diffopt.nr_paths = 2;
        revs->diffopt.skip_stat_unmatch = 1;
+       if (!revs->diffopt.output_format)
+               revs->diffopt.output_format = DIFF_FORMAT_PATCH;
 
        DIFF_OPT_SET(&revs->diffopt, EXIT_WITH_STATUS);
        DIFF_OPT_SET(&revs->diffopt, NO_INDEX);
diff --git a/diff.c b/diff.c
index 75d9fab8f87033ba86f687fbc92c5d4ee4c68d7b..e0fa78c84d99387227048008a3276d410c5a71c8 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -1757,7 +1757,8 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int
        struct stat st;
        int pos, len;
 
-       /* We do not read the cache ourselves here, because the
+       /*
+        * We do not read the cache ourselves here, because the
         * benchmark with my previous version that always reads cache
         * shows that it makes things worse for diff-tree comparing
         * two linux-2.6 kernel trees in an already checked out work
@@ -1797,6 +1798,13 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int
        if (hashcmp(sha1, ce->sha1) || !S_ISREG(ce->ce_mode))
                return 0;
 
+       /*
+        * If ce is marked as "assume unchanged", there is no
+        * guarantee that work tree matches what we are looking for.
+        */
+       if (ce->ce_flags & CE_VALID)
+               return 0;
+
        /*
         * If ce matches the file in the work tree, we can reuse it.
         */
@@ -1946,17 +1954,23 @@ void diff_free_filespec_data(struct diff_filespec *s)
        s->cnt_data = NULL;
 }
 
-static void prep_temp_blob(struct diff_tempfile *temp,
+static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
                           void *blob,
                           unsigned long size,
                           const unsigned char *sha1,
                           int mode)
 {
        int fd;
+       struct strbuf buf = STRBUF_INIT;
 
        fd = git_mkstemp(temp->tmp_path, PATH_MAX, ".diff_XXXXXX");
        if (fd < 0)
                die("unable to create temp-file: %s", strerror(errno));
+       if (convert_to_working_tree(path,
+                       (const char *)blob, (size_t)size, &buf)) {
+               blob = buf.buf;
+               size = buf.len;
+       }
        if (write_in_full(fd, blob, size) != size)
                die("unable to write temp-file");
        close(fd);
@@ -1964,6 +1978,7 @@ static void prep_temp_blob(struct diff_tempfile *temp,
        strcpy(temp->hex, sha1_to_hex(sha1));
        temp->hex[40] = 0;
        sprintf(temp->mode, "%06o", mode);
+       strbuf_release(&buf);
 }
 
 static struct diff_tempfile *prepare_temp_file(const char *name,
@@ -2004,7 +2019,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name,
                                die("readlink(%s)", name);
                        if (ret == sizeof(buf))
                                die("symlink too long: %s", name);
-                       prep_temp_blob(temp, buf, ret,
+                       prep_temp_blob(name, temp, buf, ret,
                                       (one->sha1_valid ?
                                        one->sha1 : null_sha1),
                                       (one->sha1_valid ?
@@ -2030,7 +2045,7 @@ static struct diff_tempfile *prepare_temp_file(const char *name,
        else {
                if (diff_populate_filespec(one, 0))
                        die("cannot read data blob for %s", one->path);
-               prep_temp_blob(temp, one->data, one->size,
+               prep_temp_blob(name, temp, one->data, one->size,
                               one->sha1, one->mode);
        }
        return temp;
index e278bce0ea5f1ddda2dab9012663c6d1d4c6bd89..4696885b224ac12964fce2eb06617b7ab5633854 100644 (file)
@@ -42,6 +42,7 @@ enum safe_crlf safe_crlf = SAFE_CRLF_WARN;
 unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
 enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;
 enum rebase_setup_type autorebase = AUTOREBASE_NEVER;
+enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;
 
 /* Parallel index stat data preload? */
 int core_preload_index = 0;
index 217c12577f52b8ff9d535a086ec75d54107ee01c..408e4e55e1c58931444c772d35d23b505bf3e2ea 100644 (file)
@@ -61,6 +61,10 @@ const char *git_extract_argv0_path(const char *argv0)
 void git_set_argv_exec_path(const char *exec_path)
 {
        argv_exec_path = exec_path;
+       /*
+        * Propagate this setting to external programs.
+        */
+       setenv(EXEC_PATH_ENVIRONMENT, exec_path, 1);
 }
 
 
index beeac0d0049d920726befab88a2ffa4eeddcb163..db44da3e096fcd7cb5cc1664b1d9881535585591 100644 (file)
@@ -1,4 +1,5 @@
 /*
+(See Documentation/git-fast-import.txt for maintained documentation.)
 Format of STDIN stream:
 
   stream ::= cmd*;
@@ -18,8 +19,8 @@ Format of STDIN stream:
 
   new_commit ::= 'commit' sp ref_str lf
     mark?
-    ('author' sp name '<' email '>' when lf)?
-    'committer' sp name '<' email '>' when lf
+    ('author' sp name sp '<' email '>' sp when lf)?
+    'committer' sp name sp '<' email '>' sp when lf
     commit_msg
     ('from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)?
     ('merge' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)*
@@ -43,7 +44,7 @@ Format of STDIN stream:
 
   new_tag ::= 'tag' sp tag_str lf
     'from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf
-    ('tagger' sp name '<' email '>' when lf)?
+    ('tagger' sp name sp '<' email '>' sp when lf)?
     tag_msg;
   tag_msg ::= data;
 
index e313bdea70d0a765106aa42a17a66f01d3d0f7d8..df0ae63b4e40f9aa7373269e9a7fb7eeeb66cd18 100755 (executable)
@@ -77,7 +77,7 @@ bisect_start() {
        then
                # Reset to the rev from where we started.
                start_head=$(cat "$GIT_DIR/BISECT_START")
-               git checkout "$start_head" || exit
+               git checkout "$start_head" -- || exit
        else
                # Get rev from where we start.
                case "$head" in
@@ -370,7 +370,7 @@ bisect_checkout() {
        _msg="$2"
        echo "Bisecting: $_msg"
        mark_expected_rev "$_rev"
-       git checkout -q "$_rev" || exit
+       git checkout -q "$_rev" -- || exit
        git show-branch "$_rev"
 }
 
@@ -549,7 +549,7 @@ bisect_reset() {
        *)
            usage ;;
        esac
-       git checkout "$branch" && bisect_clean_state
+       git checkout "$branch" -- && bisect_clean_state
 }
 
 bisect_clean_state() {
index 20f6f5175070f62ab74eda4839c637afe1004d49..b90d3df3a7db97dbc8a16e9e73b705d52bf8fd20 100755 (executable)
@@ -272,10 +272,10 @@ test $commits -eq 0 && die "Found nothing to rewrite"
 
 # Rewrite the commits
 
-i=0
+git_filter_branch__commit_count=0
 while read commit parents; do
-       i=$(($i+1))
-       printf "\rRewrite $commit ($i/$commits)"
+       git_filter_branch__commit_count=$(($git_filter_branch__commit_count+1))
+       printf "\rRewrite $commit ($git_filter_branch__commit_count/$commits)"
 
        case "$filter_subdir" in
        "")
index 0ade6992289a807a268ad887d8a71ba54a87cf49..b83fd3f970161d9ca8a4212a0b335f784fc3ff84 100755 (executable)
@@ -319,7 +319,7 @@ do
        --root)
                rebase_root=t
                ;;
-       -f|--f|--fo|--for|--forc|force|--force-r|--force-re|--force-reb|--force-reba|--force_rebas|--force-rebase)
+       -f|--f|--fo|--for|--forc|force|--force-r|--force-re|--force-reb|--force-reba|--force-rebas|--force-rebase)
                force_rebase=t
                ;;
        -*)
index 0144c2d7b95d5393b7993c95e6aff46f18f01e8b..0868734723b3c96144bfa9360a9e19ebae1995f7 100755 (executable)
@@ -71,11 +71,7 @@ case ",$all_into_one," in
                                existing="$existing $e"
                        fi
                done
-               if test -n "$existing"
-               then
-                       args="--kept-pack-only"
-               fi
-               if test -n "$args" -a -n "$unpack_unreachable" -a \
+               if test -n "$existing" -a -n "$unpack_unreachable" -a \
                        -n "$remove_redundant"
                then
                        args="$args $unpack_unreachable"
@@ -185,5 +181,5 @@ fi
 
 case "$no_update_info" in
 t) : ;;
-*) git-update-server-info ;;
+*) git update-server-info ;;
 esac
index 546d2ebc0c72d4a330b3b40ca886af9340afb5af..172b53c2d5b8ccad6a1bee592bccbe27d8f3127c 100755 (executable)
@@ -606,32 +606,43 @@ EOT
        do_edit(@files);
 }
 
+sub ask {
+       my ($prompt, %arg) = @_;
+       my $valid_re = $arg{valid_re};
+       my $default = $arg{default};
+       my $resp;
+       my $i = 0;
+       return defined $default ? $default : undef
+               unless defined $term->IN and defined fileno($term->IN) and
+                      defined $term->OUT and defined fileno($term->OUT);
+       while ($i++ < 10) {
+               $resp = $term->readline($prompt);
+               if (!defined $resp) { # EOF
+                       print "\n";
+                       return defined $default ? $default : undef;
+               }
+               if ($resp eq '' and defined $default) {
+                       return $default;
+               }
+               if (!defined $valid_re or $resp =~ /$valid_re/) {
+                       return $resp;
+               }
+       }
+       return undef;
+}
+
 my $prompting = 0;
 if (!defined $sender) {
        $sender = $repoauthor || $repocommitter || '';
-
-       while (1) {
-               $_ = $term->readline("Who should the emails appear to be from? [$sender] ");
-               last if defined $_;
-               print "\n";
-       }
-
-       $sender = $_ if ($_);
+       $sender = ask("Who should the emails appear to be from? [$sender] ",
+                     default => $sender);
        print "Emails will be sent from: ", $sender, "\n";
        $prompting++;
 }
 
 if (!@to) {
-
-
-       while (1) {
-               $_ = $term->readline("Who should the emails be sent to? ", "");
-               last if defined $_;
-               print "\n";
-       }
-
-       my $to = $_;
-       push @to, parse_address_line($to);
+       my $to = ask("Who should the emails be sent to? ");
+       push @to, parse_address_line($to) if defined $to; # sanitized/validated later
        $prompting++;
 }
 
@@ -651,13 +662,8 @@ sub expand_aliases {
 @bcclist = expand_aliases(@bcclist);
 
 if ($thread && !defined $initial_reply_to && $prompting) {
-       while (1) {
-               $_= $term->readline("Message-ID to be used as In-Reply-To for the first email? ", $initial_reply_to);
-               last if defined $_;
-               print "\n";
-       }
-
-       $initial_reply_to = $_;
+       $initial_reply_to = ask(
+               "Message-ID to be used as In-Reply-To for the first email? ");
 }
 if (defined $initial_reply_to) {
        $initial_reply_to =~ s/^\s*<?//;
@@ -681,7 +687,7 @@ if ($compose && $compose > 0) {
 
 # Variables we set as part of the loop over files
 our ($message_id, %mail, $subject, $reply_to, $references, $message,
-       $needs_confirm, $message_num);
+       $needs_confirm, $message_num, $ask_default);
 
 sub extract_valid_address {
        my $address = shift;
@@ -770,12 +776,13 @@ sub sanitize_address
        }
 
        # if recipient_name is already quoted, do nothing
-       if ($recipient_name =~ /^(".*"|=\?utf-8\?q\?.*\?=)$/) {
+       if ($recipient_name =~ /^("[[:ascii:]]*"|=\?utf-8\?q\?.*\?=)$/) {
                return $recipient;
        }
 
        # rfc2047 is needed if a non-ascii char is included
        if ($recipient_name =~ /[^[:ascii:]]/) {
+               $recipient_name =~ s/^"(.*)"$/$1/;
                $recipient_name = quote_rfc2047($recipient_name);
        }
 
@@ -841,6 +848,7 @@ X-Mailer: git-send-email $gitversion
                print "\n$header\n";
                if ($needs_confirm eq "inform") {
                        $confirm_unconfigured = 0; # squelch this message for the rest of this run
+                       $ask_default = "y"; # assume yes on EOF since user hasn't explicitly asked for confirmation
                        print "    The Cc list above has been expanded by additional\n";
                        print "    addresses found in the patch commit message. By default\n";
                        print "    send-email prompts before sending whenever this occurs.\n";
@@ -851,13 +859,10 @@ X-Mailer: git-send-email $gitversion
                        print "    To retain the current behavior, but squelch this message,\n";
                        print "    run 'git config --global sendemail.confirm auto'.\n\n";
                }
-               while (1) {
-                       chomp ($_ = $term->readline(
-                               "Send this email? ([y]es|[n]o|[q]uit|[a]ll): "
-                       ));
-                       last if /^(?:yes|y|no|n|quit|q|all|a)/i;
-                       print "\n";
-               }
+               $_ = ask("Send this email? ([y]es|[n]o|[q]uit|[a]ll): ",
+                        valid_re => qr/^(?:yes|y|no|n|quit|q|all|a)/i,
+                        default => $ask_default);
+               die "Send this email reply required" unless defined $_;
                if (/^n/i) {
                        return;
                } elsif (/^q/i) {
index 0a27232b90456b5471ee64d5dcf9965ad73f28af..7c2e060ae770710ed7ed27d0aed4cfd2e8145810 100755 (executable)
@@ -5,7 +5,7 @@
 # Copyright (c) 2007 Lars Hjemli
 
 USAGE="[--quiet] [--cached] \
-[add <repo> [-b branch] <path>]|[status|init|update [-i|--init] [-N|--no-fetch]|summary [-n|--summary-limit <n>] [<commit>]] \
+[add [-b branch] <repo> <path>]|[status|init|update [-i|--init] [-N|--no-fetch]|summary [-n|--summary-limit <n>] [<commit>]] \
 [--] [<path>...]|[foreach <command>]|[sync [--] [<path>...]]"
 OPTIONS_SPEC=
 . git-sh-setup
index 8be6be00c6cc76bcf2fc2d9b1fe331ec5e81fd2e..d9197989d2e063ecf0bbbac143a046f8de79ce52 100755 (executable)
@@ -68,6 +68,7 @@ my ($_stdin, $_help, $_edit,
        $_prefix, $_no_checkout, $_url, $_verbose,
        $_git_format, $_commit_url, $_tag);
 $Git::SVN::_follow_parent = 1;
+$_q ||= 0;
 my %remote_opts = ( 'username=s' => \$Git::SVN::Prompt::_username,
                     'config-dir=s' => \$Git::SVN::Ra::config_dir,
                     'no-auth-cache' => \$Git::SVN::Prompt::_no_auth_cache,
@@ -80,7 +81,7 @@ my %fc_opts = ( 'follow-parent|follow!' => \$Git::SVN::_follow_parent,
                'useSvnsyncProps' => \$Git::SVN::_use_svnsync_props,
                'log-window-size=i' => \$Git::SVN::Ra::_log_window_size,
                'no-checkout' => \$_no_checkout,
-               'quiet|q' => \$_q,
+               'quiet|q+' => \$_q,
                'repack-flags|repack-args|repack-opts=s' =>
                   \$Git::SVN::_repack_flags,
                'use-log-author' => \$Git::SVN::_use_log_author,
@@ -2331,13 +2332,13 @@ sub do_git_commit {
 
        $self->{last_rev} = $log_entry->{revision};
        $self->{last_commit} = $commit;
-       print "r$log_entry->{revision}";
+       print "r$log_entry->{revision}" unless $::_q > 1;
        if (defined $log_entry->{svm_revision}) {
-                print " (\@$log_entry->{svm_revision})";
+                print " (\@$log_entry->{svm_revision})" unless $::_q > 1;
                 $self->rev_map_set($log_entry->{svm_revision}, $commit,
                                   0, $self->svm_uuid);
        }
-       print " = $commit ($self->{ref_id})\n";
+       print " = $commit ($self->{ref_id})\n" unless $::_q > 1;
        if (--$_gc_nr == 0) {
                $_gc_nr = $_gc_period;
                gc();
@@ -3387,15 +3388,18 @@ sub delete_entry {
        return undef if ($gpath eq '');
 
        # remove entire directories.
-       if (command('ls-tree', $self->{c}, '--', $gpath) =~ /^040000 tree/) {
+       my ($tree) = (command('ls-tree', '-z', $self->{c}, "./$gpath")
+                        =~ /\A040000 tree ([a-f\d]{40})\t\Q$gpath\E\0/);
+       if ($tree) {
                my ($ls, $ctx) = command_output_pipe(qw/ls-tree
                                                     -r --name-only -z/,
-                                                    $self->{c}, '--', $gpath);
+                                                    $tree);
                local $/ = "\0";
                while (<$ls>) {
                        chomp;
-                       $self->{gii}->remove($_);
-                       print "\tD\t$_\n" unless $::_q;
+                       my $rmpath = "$gpath/$_";
+                       $self->{gii}->remove($rmpath);
+                       print "\tD\t$rmpath\n" unless $::_q;
                }
                print "\tD\t$gpath/\n" unless $::_q;
                command_close_pipe($ls, $ctx);
@@ -3414,8 +3418,8 @@ sub open_file {
        goto out if is_path_ignored($path);
 
        my $gpath = $self->git_path($path);
-       ($mode, $blob) = (command('ls-tree', $self->{c}, '--', $gpath)
-                            =~ /^(\d{6}) blob ([a-f\d]{40})\t/);
+       ($mode, $blob) = (command('ls-tree', '-z', $self->{c}, "./$gpath")
+                            =~ /\A(\d{6}) blob ([a-f\d]{40})\t\Q$gpath\E\0/);
        unless (defined $mode && defined $blob) {
                die "$path was not found in commit $self->{c} (r$rev)\n";
        }
index 48e5f38fe0f8848ffe0941d48eae10b8edc14dd8..6ce5a1d550d4cf781673c62599bd681fc5e318b5 100644 (file)
@@ -97,7 +97,7 @@ struct repo
        struct remote_lock *locks;
 };
 
-static struct repo *remote;
+static struct repo *repo;
 
 enum transfer_state {
        NEED_FETCH,
@@ -324,7 +324,7 @@ static void start_fetch_loose(struct transfer_request *request)
 
        git_SHA1_Init(&request->c);
 
-       url = get_remote_object_url(remote->url, hex, 0);
+       url = get_remote_object_url(repo->url, hex, 0);
        request->url = xstrdup(url);
 
        /* If a previous temp file is present, process what was already
@@ -389,7 +389,7 @@ static void start_fetch_loose(struct transfer_request *request)
        request->state = RUN_FETCH_LOOSE;
        if (!start_active_slot(slot)) {
                fprintf(stderr, "Unable to start GET request\n");
-               remote->can_update_info_refs = 0;
+               repo->can_update_info_refs = 0;
                release_request(request);
        }
 }
@@ -399,7 +399,7 @@ static void start_mkcol(struct transfer_request *request)
        char *hex = sha1_to_hex(request->obj->sha1);
        struct active_request_slot *slot;
 
-       request->url = get_remote_object_url(remote->url, hex, 1);
+       request->url = get_remote_object_url(repo->url, hex, 1);
 
        slot = get_active_slot();
        slot->callback_func = process_response;
@@ -434,10 +434,10 @@ static void start_fetch_packed(struct transfer_request *request)
        struct transfer_request *check_request = request_queue_head;
        struct active_request_slot *slot;
 
-       target = find_sha1_pack(request->obj->sha1, remote->packs);
+       target = find_sha1_pack(request->obj->sha1, repo->packs);
        if (!target) {
                fprintf(stderr, "Unable to fetch %s, will not be able to update server info refs\n", sha1_to_hex(request->obj->sha1));
-               remote->can_update_info_refs = 0;
+               repo->can_update_info_refs = 0;
                release_request(request);
                return;
        }
@@ -450,9 +450,9 @@ static void start_fetch_packed(struct transfer_request *request)
        snprintf(request->tmpfile, sizeof(request->tmpfile),
                 "%s.temp", filename);
 
-       url = xmalloc(strlen(remote->url) + 64);
+       url = xmalloc(strlen(repo->url) + 64);
        sprintf(url, "%sobjects/pack/pack-%s.pack",
-               remote->url, sha1_to_hex(target->sha1));
+               repo->url, sha1_to_hex(target->sha1));
 
        /* Make sure there isn't another open request for this pack */
        while (check_request) {
@@ -469,7 +469,7 @@ static void start_fetch_packed(struct transfer_request *request)
        if (!packfile) {
                fprintf(stderr, "Unable to open local file %s for pack",
                        request->tmpfile);
-               remote->can_update_info_refs = 0;
+               repo->can_update_info_refs = 0;
                free(url);
                return;
        }
@@ -505,7 +505,7 @@ static void start_fetch_packed(struct transfer_request *request)
        request->state = RUN_FETCH_PACKED;
        if (!start_active_slot(slot)) {
                fprintf(stderr, "Unable to start GET request\n");
-               remote->can_update_info_refs = 0;
+               repo->can_update_info_refs = 0;
                release_request(request);
        }
 }
@@ -554,10 +554,10 @@ static void start_put(struct transfer_request *request)
        request->buffer.buf.len = stream.total_out;
 
        strbuf_addstr(&buf, "Destination: ");
-       append_remote_object_url(&buf, remote->url, hex, 0);
+       append_remote_object_url(&buf, repo->url, hex, 0);
        request->dest = strbuf_detach(&buf, NULL);
 
-       append_remote_object_url(&buf, remote->url, hex, 0);
+       append_remote_object_url(&buf, repo->url, hex, 0);
        strbuf_add(&buf, request->lock->tmpfile_suffix, 41);
        request->url = strbuf_detach(&buf, NULL);
 
@@ -648,7 +648,7 @@ static int refresh_lock(struct remote_lock *lock)
 
 static void check_locks(void)
 {
-       struct remote_lock *lock = remote->locks;
+       struct remote_lock *lock = repo->locks;
        time_t current_time = time(NULL);
        int time_remaining;
 
@@ -759,7 +759,7 @@ static void finish_request(struct transfer_request *request)
                        }
                } else {
                        if (request->http_code == 416)
-                               fprintf(stderr, "Warning: requested range invalid; we may already have all the data.\n");
+                               warning("requested range invalid; we may already have all the data.");
 
                        git_inflate_end(&request->stream);
                        git_SHA1_Final(request->real_sha1, &request->c);
@@ -788,7 +788,7 @@ static void finish_request(struct transfer_request *request)
                if (request->curl_result != CURLE_OK) {
                        fprintf(stderr, "Unable to get pack file %s\n%s",
                                request->url, curl_errorstr);
-                       remote->can_update_info_refs = 0;
+                       repo->can_update_info_refs = 0;
                } else {
                        off_t pack_size = ftell(request->local_stream);
 
@@ -798,7 +798,7 @@ static void finish_request(struct transfer_request *request)
                                               request->filename)) {
                                target = (struct packed_git *)request->userData;
                                target->pack_size = pack_size;
-                               lst = &remote->packs;
+                               lst = &repo->packs;
                                while (*lst != target)
                                        lst = &((*lst)->next);
                                *lst = (*lst)->next;
@@ -806,7 +806,7 @@ static void finish_request(struct transfer_request *request)
                                if (!verify_pack(target))
                                        install_packed_git(target);
                                else
-                                       remote->can_update_info_refs = 0;
+                                       repo->can_update_info_refs = 0;
                        }
                }
                release_request(request);
@@ -889,7 +889,7 @@ static int add_send_request(struct object *obj, struct remote_lock *lock)
                get_remote_object_list(obj->sha1[0]);
        if (obj->flags & (REMOTE | PUSHING))
                return 0;
-       target = find_sha1_pack(obj->sha1, remote->packs);
+       target = find_sha1_pack(obj->sha1, repo->packs);
        if (target) {
                obj->flags |= REMOTE;
                return 0;
@@ -930,8 +930,8 @@ static int fetch_index(unsigned char *sha1)
        struct slot_results results;
 
        /* Don't use the index if the pack isn't there */
-       url = xmalloc(strlen(remote->url) + 64);
-       sprintf(url, "%sobjects/pack/pack-%s.pack", remote->url, hex);
+       url = xmalloc(strlen(repo->url) + 64);
+       sprintf(url, "%sobjects/pack/pack-%s.pack", repo->url, hex);
        slot = get_active_slot();
        slot->results = &results;
        curl_easy_setopt(slot->curl, CURLOPT_URL, url);
@@ -956,7 +956,7 @@ static int fetch_index(unsigned char *sha1)
        if (push_verbosely)
                fprintf(stderr, "Getting index for pack %s\n", hex);
 
-       sprintf(url, "%sobjects/pack/pack-%s.idx", remote->url, hex);
+       sprintf(url, "%sobjects/pack/pack-%s.idx", repo->url, hex);
 
        filename = sha1_pack_index_name(sha1);
        snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
@@ -1018,8 +1018,8 @@ static int setup_index(unsigned char *sha1)
                return -1;
 
        new_pack = parse_pack_index(sha1);
-       new_pack->next = remote->packs;
-       remote->packs = new_pack;
+       new_pack->next = repo->packs;
+       repo->packs = new_pack;
        return 0;
 }
 
@@ -1037,8 +1037,8 @@ static int fetch_indices(void)
        if (push_verbosely)
                fprintf(stderr, "Getting pack list\n");
 
-       url = xmalloc(strlen(remote->url) + 20);
-       sprintf(url, "%sobjects/info/packs", remote->url);
+       url = xmalloc(strlen(repo->url) + 20);
+       sprintf(url, "%sobjects/info/packs", repo->url);
 
        slot = get_active_slot();
        slot->results = &results;
@@ -1223,11 +1223,11 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
        struct curl_slist *dav_headers = NULL;
        struct xml_ctx ctx;
 
-       url = xmalloc(strlen(remote->url) + strlen(path) + 1);
-       sprintf(url, "%s%s", remote->url, path);
+       url = xmalloc(strlen(repo->url) + strlen(path) + 1);
+       sprintf(url, "%s%s", repo->url, path);
 
        /* Make sure leading directories exist for the remote ref */
-       ep = strchr(url + strlen(remote->url) + 1, '/');
+       ep = strchr(url + strlen(repo->url) + 1, '/');
        while (ep) {
                char saved_character = ep[1];
                ep[1] = '\0';
@@ -1319,8 +1319,8 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
        } else {
                lock->url = url;
                lock->start_time = time(NULL);
-               lock->next = remote->locks;
-               remote->locks = lock;
+               lock->next = repo->locks;
+               repo->locks = lock;
        }
 
        return lock;
@@ -1330,7 +1330,7 @@ static int unlock_remote(struct remote_lock *lock)
 {
        struct active_request_slot *slot;
        struct slot_results results;
-       struct remote_lock *prev = remote->locks;
+       struct remote_lock *prev = repo->locks;
        struct curl_slist *dav_headers;
        int rc = 0;
 
@@ -1356,8 +1356,8 @@ static int unlock_remote(struct remote_lock *lock)
 
        curl_slist_free_all(dav_headers);
 
-       if (remote->locks == lock) {
-               remote->locks = lock->next;
+       if (repo->locks == lock) {
+               repo->locks = lock->next;
        } else {
                while (prev && prev->next != lock)
                        prev = prev->next;
@@ -1375,7 +1375,7 @@ static int unlock_remote(struct remote_lock *lock)
 
 static void remove_locks(void)
 {
-       struct remote_lock *lock = remote->locks;
+       struct remote_lock *lock = repo->locks;
 
        fprintf(stderr, "Removing remote locks...\n");
        while (lock) {
@@ -1457,7 +1457,7 @@ static void handle_remote_ls_ctx(struct xml_ctx *ctx, int tag_closed)
                                }
                        }
                        if (path) {
-                               path += remote->path_len;
+                               path += repo->path_len;
                                ls->dentry_name = xstrdup(path);
                        }
                } else if (!strcmp(ctx->name, DAV_PROPFIND_COLLECTION)) {
@@ -1480,7 +1480,7 @@ static void remote_ls(const char *path, int flags,
                      void (*userFunc)(struct remote_ls_ctx *ls),
                      void *userData)
 {
-       char *url = xmalloc(strlen(remote->url) + strlen(path) + 1);
+       char *url = xmalloc(strlen(repo->url) + strlen(path) + 1);
        struct active_request_slot *slot;
        struct slot_results results;
        struct strbuf in_buffer = STRBUF_INIT;
@@ -1496,7 +1496,7 @@ static void remote_ls(const char *path, int flags,
        ls.userData = userData;
        ls.userFunc = userFunc;
 
-       sprintf(url, "%s%s", remote->url, path);
+       sprintf(url, "%s%s", repo->url, path);
 
        strbuf_addf(&out_buffer.buf, PROPFIND_ALL_REQUEST);
 
@@ -1574,7 +1574,7 @@ static int locking_available(void)
        struct xml_ctx ctx;
        int lock_flags = 0;
 
-       strbuf_addf(&out_buffer.buf, PROPFIND_SUPPORTEDLOCK_REQUEST, remote->url);
+       strbuf_addf(&out_buffer.buf, PROPFIND_SUPPORTEDLOCK_REQUEST, repo->url);
 
        dav_headers = curl_slist_append(dav_headers, "Depth: 0");
        dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
@@ -1586,7 +1586,7 @@ static int locking_available(void)
        curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
        curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
        curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
-       curl_easy_setopt(slot->curl, CURLOPT_URL, remote->url);
+       curl_easy_setopt(slot->curl, CURLOPT_URL, repo->url);
        curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
        curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PROPFIND);
        curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
@@ -1616,16 +1616,16 @@ static int locking_available(void)
                        }
                        XML_ParserFree(parser);
                        if (!lock_flags)
-                               error("Error: no DAV locking support on %s",
-                                     remote->url);
+                               error("no DAV locking support on %s",
+                                     repo->url);
 
                } else {
                        error("Cannot access URL %s, return code %d",
-                             remote->url, results.curl_result);
+                             repo->url, results.curl_result);
                        lock_flags = 0;
                }
        } else {
-               error("Unable to start PROPFIND request on %s", remote->url);
+               error("Unable to start PROPFIND request on %s", repo->url);
        }
 
        strbuf_release(&out_buffer.buf);
@@ -1801,10 +1801,10 @@ static void one_remote_ref(char *refname)
 
        ref = alloc_ref(refname);
 
-       if (http_fetch_ref(remote->url, ref) != 0) {
+       if (http_fetch_ref(repo->url, ref) != 0) {
                fprintf(stderr,
                        "Unable to fetch ref %s from %s\n",
-                       refname, remote->url);
+                       refname, repo->url);
                free(ref);
                return;
        }
@@ -1813,7 +1813,7 @@ static void one_remote_ref(char *refname)
         * Fetch a copy of the object if it doesn't exist locally - it
         * may be required for updating server info later.
         */
-       if (remote->can_update_info_refs && !has_sha1_file(ref->old_sha1)) {
+       if (repo->can_update_info_refs && !has_sha1_file(ref->old_sha1)) {
                obj = lookup_unknown_object(ref->old_sha1);
                if (obj) {
                        fprintf(stderr, "  fetch %s for %s\n",
@@ -1853,10 +1853,10 @@ static void add_remote_info_ref(struct remote_ls_ctx *ls)
 
        ref = alloc_ref(ls->dentry_name);
 
-       if (http_fetch_ref(remote->url, ref) != 0) {
+       if (http_fetch_ref(repo->url, ref) != 0) {
                fprintf(stderr,
                        "Unable to fetch ref %s from %s\n",
-                       ls->dentry_name, remote->url);
+                       ls->dentry_name, repo->url);
                aborted = 1;
                free(ref);
                return;
@@ -1931,12 +1931,12 @@ static void update_remote_info_refs(struct remote_lock *lock)
 
 static int remote_exists(const char *path)
 {
-       char *url = xmalloc(strlen(remote->url) + strlen(path) + 1);
+       char *url = xmalloc(strlen(repo->url) + strlen(path) + 1);
        struct active_request_slot *slot;
        struct slot_results results;
        int ret = -1;
 
-       sprintf(url, "%s%s", remote->url, path);
+       sprintf(url, "%s%s", repo->url, path);
 
        slot = get_active_slot();
        slot->results = &results;
@@ -1966,8 +1966,8 @@ static void fetch_symref(const char *path, char **symref, unsigned char *sha1)
        struct active_request_slot *slot;
        struct slot_results results;
 
-       url = xmalloc(strlen(remote->url) + strlen(path) + 1);
-       sprintf(url, "%s%s", remote->url, path);
+       url = xmalloc(strlen(repo->url) + strlen(path) + 1);
+       sprintf(url, "%s%s", repo->url, path);
 
        slot = get_active_slot();
        slot->results = &results;
@@ -2082,7 +2082,7 @@ static int delete_remote_branch(char *pattern, int force)
                                     "of your current HEAD.\n"
                                     "If you are sure you want to delete it,"
                                     " run:\n\t'git http-push -D %s %s'",
-                                    remote_ref->name, remote->url, pattern);
+                                    remote_ref->name, repo->url, pattern);
                }
        }
 
@@ -2090,8 +2090,8 @@ static int delete_remote_branch(char *pattern, int force)
        fprintf(stderr, "Removing remote branch '%s'\n", remote_ref->name);
        if (dry_run)
                return 0;
-       url = xmalloc(strlen(remote->url) + strlen(remote_ref->name) + 1);
-       sprintf(url, "%s%s", remote->url, remote_ref->name);
+       url = xmalloc(strlen(repo->url) + strlen(remote_ref->name) + 1);
+       sprintf(url, "%s%s", repo->url, remote_ref->name);
        slot = get_active_slot();
        slot->results = &results;
        curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
@@ -2128,13 +2128,14 @@ int main(int argc, char **argv)
        int i;
        int new_refs;
        struct ref *ref, *local_refs;
+       struct remote *remote;
        char *rewritten_url = NULL;
 
        git_extract_argv0_path(argv[0]);
 
        setup_git_directory();
 
-       remote = xcalloc(sizeof(*remote), 1);
+       repo = xcalloc(sizeof(*repo), 1);
 
        argv++;
        for (i = 1; i < argc; i++, argv++) {
@@ -2167,14 +2168,14 @@ int main(int argc, char **argv)
                                continue;
                        }
                }
-               if (!remote->url) {
+               if (!repo->url) {
                        char *path = strstr(arg, "//");
-                       remote->url = arg;
-                       remote->path_len = strlen(arg);
+                       repo->url = arg;
+                       repo->path_len = strlen(arg);
                        if (path) {
-                               remote->path = strchr(path+2, '/');
-                               if (remote->path)
-                                       remote->path_len = strlen(remote->path);
+                               repo->path = strchr(path+2, '/');
+                               if (repo->path)
+                                       repo->path_len = strlen(repo->path);
                        }
                        continue;
                }
@@ -2187,7 +2188,7 @@ int main(int argc, char **argv)
        die("git-push is not available for http/https repository when not compiled with USE_CURL_MULTI");
 #endif
 
-       if (!remote->url)
+       if (!repo->url)
                usage(http_push_usage);
 
        if (delete_branch && nr_refspec != 1)
@@ -2195,17 +2196,24 @@ int main(int argc, char **argv)
 
        memset(remote_dir_exists, -1, 256);
 
-       http_init(NULL);
+       /*
+        * Create a minimum remote by hand to give to http_init(),
+        * primarily to allow it to look at the URL.
+        */
+       remote = xcalloc(sizeof(*remote), 1);
+       ALLOC_GROW(remote->url, remote->url_nr + 1, remote->url_alloc);
+       remote->url[remote->url_nr++] = repo->url;
+       http_init(remote);
 
        no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
 
-       if (remote->url && remote->url[strlen(remote->url)-1] != '/') {
-               rewritten_url = xmalloc(strlen(remote->url)+2);
-               strcpy(rewritten_url, remote->url);
+       if (repo->url && repo->url[strlen(repo->url)-1] != '/') {
+               rewritten_url = xmalloc(strlen(repo->url)+2);
+               strcpy(rewritten_url, repo->url);
                strcat(rewritten_url, "/");
-               remote->path = rewritten_url + (remote->path - remote->url);
-               remote->path_len++;
-               remote->url = rewritten_url;
+               repo->path = rewritten_url + (repo->path - repo->url);
+               repo->path_len++;
+               repo->url = rewritten_url;
        }
 
        /* Verify DAV compliance/lock support */
@@ -2217,20 +2225,20 @@ int main(int argc, char **argv)
        sigchain_push_common(remove_locks_on_signal);
 
        /* Check whether the remote has server info files */
-       remote->can_update_info_refs = 0;
-       remote->has_info_refs = remote_exists("info/refs");
-       remote->has_info_packs = remote_exists("objects/info/packs");
-       if (remote->has_info_refs) {
+       repo->can_update_info_refs = 0;
+       repo->has_info_refs = remote_exists("info/refs");
+       repo->has_info_packs = remote_exists("objects/info/packs");
+       if (repo->has_info_refs) {
                info_ref_lock = lock_remote("info/refs", LOCK_TIME);
                if (info_ref_lock)
-                       remote->can_update_info_refs = 1;
+                       repo->can_update_info_refs = 1;
                else {
-                       fprintf(stderr, "Error: cannot lock existing info/refs\n");
+                       error("cannot lock existing info/refs");
                        rc = 1;
                        goto cleanup;
                }
        }
-       if (remote->has_info_packs)
+       if (repo->has_info_packs)
                fetch_indices();
 
        /* Get a list of all local and remote heads to validate refspecs */
@@ -2388,8 +2396,8 @@ int main(int argc, char **argv)
        }
 
        /* Update remote server info if appropriate */
-       if (remote->has_info_refs && new_refs) {
-               if (info_ref_lock && remote->can_update_info_refs) {
+       if (repo->has_info_refs && new_refs) {
+               if (info_ref_lock && repo->can_update_info_refs) {
                        fprintf(stderr, "Updating remote server info\n");
                        if (!dry_run)
                                update_remote_info_refs(info_ref_lock);
@@ -2402,7 +2410,7 @@ int main(int argc, char **argv)
        free(rewritten_url);
        if (info_ref_lock)
                unlock_remote(info_ref_lock);
-       free(remote);
+       free(repo);
 
        curl_slist_free_all(no_pragma_header);
 
diff --git a/http.c b/http.c
index 56f18f1b03984ac3a81cb357751e2ae4fce269e0..2fc55d671e2e8c5302eaf140f5ecff0b1d701cef 100644 (file)
--- a/http.c
+++ b/http.c
@@ -1,7 +1,7 @@
 #include "http.h"
 
 int data_received;
-int active_requests = 0;
+int active_requests;
 
 #ifdef USE_CURL_MULTI
 static int max_requests = -1;
@@ -13,22 +13,23 @@ static CURL *curl_default;
 char curl_errorstr[CURL_ERROR_SIZE];
 
 static int curl_ssl_verify = -1;
-static const char *ssl_cert = NULL;
+static const char *ssl_cert;
 #if LIBCURL_VERSION_NUM >= 0x070902
-static const char *ssl_key = NULL;
+static const char *ssl_key;
 #endif
 #if LIBCURL_VERSION_NUM >= 0x070908
-static const char *ssl_capath = NULL;
+static const char *ssl_capath;
 #endif
-static const char *ssl_cainfo = NULL;
+static const char *ssl_cainfo;
 static long curl_low_speed_limit = -1;
 static long curl_low_speed_time = -1;
-static int curl_ftp_no_epsv = 0;
-static const char *curl_http_proxy = NULL;
+static int curl_ftp_no_epsv;
+static const char *curl_http_proxy;
+static char *user_name, *user_pass;
 
 static struct curl_slist *pragma_header;
 
-static struct active_request_slot *active_queue_head = NULL;
+static struct active_request_slot *active_queue_head;
 
 size_t fread_buffer(void *ptr, size_t eltsize, size_t nmemb, void *buffer_)
 {
@@ -94,53 +95,33 @@ static void process_curl_messages(void)
 static int http_options(const char *var, const char *value, void *cb)
 {
        if (!strcmp("http.sslverify", var)) {
-               if (curl_ssl_verify == -1) {
-                       curl_ssl_verify = git_config_bool(var, value);
-               }
-               return 0;
-       }
-
-       if (!strcmp("http.sslcert", var)) {
-               if (ssl_cert == NULL)
-                       return git_config_string(&ssl_cert, var, value);
+               curl_ssl_verify = git_config_bool(var, value);
                return 0;
        }
+       if (!strcmp("http.sslcert", var))
+               return git_config_string(&ssl_cert, var, value);
 #if LIBCURL_VERSION_NUM >= 0x070902
-       if (!strcmp("http.sslkey", var)) {
-               if (ssl_key == NULL)
-                       return git_config_string(&ssl_key, var, value);
-               return 0;
-       }
+       if (!strcmp("http.sslkey", var))
+               return git_config_string(&ssl_key, var, value);
 #endif
 #if LIBCURL_VERSION_NUM >= 0x070908
-       if (!strcmp("http.sslcapath", var)) {
-               if (ssl_capath == NULL)
-                       return git_config_string(&ssl_capath, var, value);
-               return 0;
-       }
+       if (!strcmp("http.sslcapath", var))
+               return git_config_string(&ssl_capath, var, value);
 #endif
-       if (!strcmp("http.sslcainfo", var)) {
-               if (ssl_cainfo == NULL)
-                       return git_config_string(&ssl_cainfo, var, value);
-               return 0;
-       }
-
+       if (!strcmp("http.sslcainfo", var))
+               return git_config_string(&ssl_cainfo, var, value);
 #ifdef USE_CURL_MULTI
        if (!strcmp("http.maxrequests", var)) {
-               if (max_requests == -1)
-                       max_requests = git_config_int(var, value);
+               max_requests = git_config_int(var, value);
                return 0;
        }
 #endif
-
        if (!strcmp("http.lowspeedlimit", var)) {
-               if (curl_low_speed_limit == -1)
-                       curl_low_speed_limit = (long)git_config_int(var, value);
+               curl_low_speed_limit = (long)git_config_int(var, value);
                return 0;
        }
        if (!strcmp("http.lowspeedtime", var)) {
-               if (curl_low_speed_time == -1)
-                       curl_low_speed_time = (long)git_config_int(var, value);
+               curl_low_speed_time = (long)git_config_int(var, value);
                return 0;
        }
 
@@ -148,19 +129,28 @@ static int http_options(const char *var, const char *value, void *cb)
                curl_ftp_no_epsv = git_config_bool(var, value);
                return 0;
        }
-       if (!strcmp("http.proxy", var)) {
-               if (curl_http_proxy == NULL)
-                       return git_config_string(&curl_http_proxy, var, value);
-               return 0;
-       }
+       if (!strcmp("http.proxy", var))
+               return git_config_string(&curl_http_proxy, var, value);
 
        /* Fall back on the default ones */
        return git_default_config(var, value, cb);
 }
 
-static CURL* get_curl_handle(void)
+static void init_curl_http_auth(CURL *result)
+{
+       if (user_name) {
+               struct strbuf up = STRBUF_INIT;
+               if (!user_pass)
+                       user_pass = xstrdup(getpass("Password: "));
+               strbuf_addf(&up, "%s:%s", user_name, user_pass);
+               curl_easy_setopt(result, CURLOPT_USERPWD,
+                                strbuf_detach(&up, NULL));
+       }
+}
+
+static CURL *get_curl_handle(void)
 {
-       CURLresult = curl_easy_init();
+       CURL *result = curl_easy_init();
 
        if (!curl_ssl_verify) {
                curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, 0);
@@ -176,6 +166,8 @@ static CURL* get_curl_handle(void)
        curl_easy_setopt(result, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
 #endif
 
+       init_curl_http_auth(result);
+
        if (ssl_cert != NULL)
                curl_easy_setopt(result, CURLOPT_SSLCERT, ssl_cert);
 #if LIBCURL_VERSION_NUM >= 0x070902
@@ -213,11 +205,60 @@ static CURL* get_curl_handle(void)
        return result;
 }
 
+static void http_auth_init(const char *url)
+{
+       char *at, *colon, *cp, *slash;
+       int len;
+
+       cp = strstr(url, "://");
+       if (!cp)
+               return;
+
+       /*
+        * Ok, the URL looks like "proto://something".  Which one?
+        * "proto://<user>:<pass>@<host>/...",
+        * "proto://<user>@<host>/...", or just
+        * "proto://<host>/..."?
+        */
+       cp += 3;
+       at = strchr(cp, '@');
+       colon = strchr(cp, ':');
+       slash = strchrnul(cp, '/');
+       if (!at || slash <= at)
+               return; /* No credentials */
+       if (!colon || at <= colon) {
+               /* Only username */
+               len = at - cp;
+               user_name = xmalloc(len + 1);
+               memcpy(user_name, cp, len);
+               user_name[len] = '\0';
+               user_pass = NULL;
+       } else {
+               len = colon - cp;
+               user_name = xmalloc(len + 1);
+               memcpy(user_name, cp, len);
+               user_name[len] = '\0';
+               len = at - (colon + 1);
+               user_pass = xmalloc(len + 1);
+               memcpy(user_pass, colon + 1, len);
+               user_pass[len] = '\0';
+       }
+}
+
+static void set_from_env(const char **var, const char *envname)
+{
+       const char *val = getenv(envname);
+       if (val)
+               *var = val;
+}
+
 void http_init(struct remote *remote)
 {
        char *low_speed_limit;
        char *low_speed_time;
 
+       git_config(http_options, NULL);
+
        curl_global_init(CURL_GLOBAL_ALL);
 
        if (remote && remote->http_proxy)
@@ -242,14 +283,14 @@ void http_init(struct remote *remote)
        if (getenv("GIT_SSL_NO_VERIFY"))
                curl_ssl_verify = 0;
 
-       ssl_cert = getenv("GIT_SSL_CERT");
+       set_from_env(&ssl_cert, "GIT_SSL_CERT");
 #if LIBCURL_VERSION_NUM >= 0x070902
-       ssl_key = getenv("GIT_SSL_KEY");
+       set_from_env(&ssl_key, "GIT_SSL_KEY");
 #endif
 #if LIBCURL_VERSION_NUM >= 0x070908
-       ssl_capath = getenv("GIT_SSL_CAPATH");
+       set_from_env(&ssl_capath, "GIT_SSL_CAPATH");
 #endif
-       ssl_cainfo = getenv("GIT_SSL_CAINFO");
+       set_from_env(&ssl_cainfo, "GIT_SSL_CAINFO");
 
        low_speed_limit = getenv("GIT_HTTP_LOW_SPEED_LIMIT");
        if (low_speed_limit != NULL)
@@ -258,8 +299,6 @@ void http_init(struct remote *remote)
        if (low_speed_time != NULL)
                curl_low_speed_time = strtol(low_speed_time, NULL, 10);
 
-       git_config(http_options, NULL);
-
        if (curl_ssl_verify == -1)
                curl_ssl_verify = 1;
 
@@ -271,6 +310,9 @@ void http_init(struct remote *remote)
        if (getenv("GIT_CURL_FTP_NO_EPSV"))
                curl_ftp_no_epsv = 1;
 
+       if (remote && remote->url && remote->url[0])
+               http_auth_init(remote->url[0]);
+
 #ifndef NO_CURL_EASY_DUPHANDLE
        curl_default = get_curl_handle();
 #endif
@@ -322,15 +364,14 @@ struct active_request_slot *get_active_slot(void)
        /* Wait for a slot to open up if the queue is full */
        while (active_requests >= max_requests) {
                curl_multi_perform(curlm, &num_transfers);
-               if (num_transfers < active_requests) {
+               if (num_transfers < active_requests)
                        process_curl_messages();
-               }
        }
 #endif
 
-       while (slot != NULL && slot->in_use) {
+       while (slot != NULL && slot->in_use)
                slot = slot->next;
-       }
+
        if (slot == NULL) {
                newslot = xmalloc(sizeof(*newslot));
                newslot->curl = NULL;
@@ -341,9 +382,8 @@ struct active_request_slot *get_active_slot(void)
                if (slot == NULL) {
                        active_queue_head = newslot;
                } else {
-                       while (slot->next != NULL) {
+                       while (slot->next != NULL)
                                slot = slot->next;
-                       }
                        slot->next = newslot;
                }
                slot = newslot;
@@ -404,7 +444,7 @@ struct fill_chain {
        struct fill_chain *next;
 };
 
-static struct fill_chain *fill_cfg = NULL;
+static struct fill_chain *fill_cfg;
 
 void add_fill_function(void *data, int (*fill)(void *))
 {
@@ -535,9 +575,8 @@ static void finish_active_slot(struct active_request_slot *slot)
        }
 
        /* Run callback if appropriate */
-       if (slot->callback_func != NULL) {
+       if (slot->callback_func != NULL)
                slot->callback_func(slot->callback_data);
-       }
 }
 
 void finish_all_active_slots(void)
@@ -567,8 +606,10 @@ static inline int needs_quote(int ch)
 
 static inline int hex(int v)
 {
-       if (v < 10) return '0' + v;
-       else return 'A' + v - 10;
+       if (v < 10)
+               return '0' + v;
+       else
+               return 'A' + v - 10;
 }
 
 static char *quote_ref_url(const char *base, const char *ref)
index f12bb45a3f734e48f003a7a2943d168c26778603..bb1f2fb711a588d2af0d61decbd4b3eb2f2aebbe 100644 (file)
--- a/mailmap.c
+++ b/mailmap.c
@@ -50,6 +50,15 @@ static void add_mapping(struct string_list *map,
 {
        struct mailmap_entry *me;
        int index;
+       char *p;
+
+       if (old_email)
+               for (p = old_email; *p; p++)
+                       *p = tolower(*p);
+       if (new_email)
+               for (p = new_email; *p; p++)
+                       *p = tolower(*p);
+
        if (old_email == NULL) {
                old_email = new_email;
                new_email = NULL;
@@ -90,7 +99,8 @@ static void add_mapping(struct string_list *map,
                 old_name, old_email, new_name, new_email);
 }
 
-static char *parse_name_and_email(char *buffer, char **name, char **email)
+static char *parse_name_and_email(char *buffer, char **name,
+               char **email, int allow_empty_email)
 {
        char *left, *right, *nstart, *nend;
        *name = *email = 0;
@@ -99,7 +109,7 @@ static char *parse_name_and_email(char *buffer, char **name, char **email)
                return NULL;
        if ((right = strchr(left+1, '>')) == NULL)
                return NULL;
-       if (left+1 == right)
+       if (!allow_empty_email && (left+1 == right))
                return NULL;
 
        /* remove whitespace from beginning and end of name */
@@ -150,8 +160,8 @@ static int read_single_mailmap(struct string_list *map, const char *filename, ch
                        }
                        continue;
                }
-               if ((name2 = parse_name_and_email(buffer, &name1, &email1)) != NULL)
-                       parse_name_and_email(name2, &name2, &email2);
+               if ((name2 = parse_name_and_email(buffer, &name1, &email1, 0)) != NULL)
+                       parse_name_and_email(name2, &name2, &email2, 1);
 
                if (email1)
                        add_mapping(map, name1, email1, name2, email2);
index f751fdc8d832cae54647c1a70d888e979d324fd8..fd065f4e1a689176a3f3255b2d88270bce094ff0 100644 (file)
@@ -242,7 +242,7 @@ void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit)
 }
 
 void show_reflog_message(struct reflog_walk_info* info, int oneline,
-       int relative_date)
+       enum date_mode dmode)
 {
        if (info && info->last_commit_reflog) {
                struct commit_reflog *commit_reflog = info->last_commit_reflog;
@@ -251,8 +251,10 @@ void show_reflog_message(struct reflog_walk_info* info, int oneline,
                info = &commit_reflog->reflogs->items[commit_reflog->recno+1];
                if (oneline) {
                        printf("%s@{", commit_reflog->reflogs->ref);
-                       if (commit_reflog->flag || relative_date)
-                               printf("%s", show_date(info->timestamp, 0, 1));
+                       if (commit_reflog->flag || dmode)
+                               printf("%s", show_date(info->timestamp,
+                                                      info->tz,
+                                                      dmode));
                        else
                                printf("%d", commit_reflog->reflogs->nr
                                       - 2 - commit_reflog->recno);
@@ -260,10 +262,10 @@ void show_reflog_message(struct reflog_walk_info* info, int oneline,
                }
                else {
                        printf("Reflog: %s@{", commit_reflog->reflogs->ref);
-                       if (commit_reflog->flag || relative_date)
+                       if (commit_reflog->flag || dmode)
                                printf("%s", show_date(info->timestamp,
                                                        info->tz,
-                                                       relative_date));
+                                                       dmode));
                        else
                                printf("%d", commit_reflog->reflogs->nr
                                       - 2 - commit_reflog->recno);
index 7ca1438f4d74b652f962c6bdfddd08fe0d75802d..74c90964bd95dcd97a5acde83c83b2f3b61c2441 100644 (file)
@@ -1,11 +1,14 @@
 #ifndef REFLOG_WALK_H
 #define REFLOG_WALK_H
 
+#include "cache.h"
+
 extern void init_reflog_walk(struct reflog_walk_info** info);
 extern int add_reflog_for_walk(struct reflog_walk_info *info,
                struct commit *commit, const char *name);
 extern void fake_reflog_parent(struct reflog_walk_info *info,
                struct commit *commit);
-extern void show_reflog_message(struct reflog_walk_info *info, int, int);
+extern void show_reflog_message(struct reflog_walk_info *info, int,
+               enum date_mode);
 
 #endif
diff --git a/refs.c b/refs.c
index 8d3c502a151648abefc4afae70d1ec5f7b5d41b6..26b001453bd1566f2ab3554fffeb63ec0437ceaa 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -737,6 +737,16 @@ int check_ref_format(const char *ref)
        }
 }
 
+const char *prettify_ref(const struct ref *ref)
+{
+       const char *name = ref->name;
+       return name + (
+               !prefixcmp(name, "refs/heads/") ? 11 :
+               !prefixcmp(name, "refs/tags/") ? 10 :
+               !prefixcmp(name, "refs/remotes/") ? 13 :
+               0);
+}
+
 const char *ref_rev_parse_rules[] = {
        "%.*s",
        "refs/%.*s",
@@ -996,7 +1006,7 @@ int delete_ref(const char *refname, const unsigned char *sha1, int delopt)
 
        err = unlink(git_path("logs/%s", lock->ref_name));
        if (err && errno != ENOENT)
-               fprintf(stderr, "warning: unlink(%s) failed: %s",
+               warning("unlink(%s) failed: %s",
                        git_path("logs/%s", lock->ref_name), strerror(errno));
        invalidate_cached_refs();
        unlock_ref(lock);
@@ -1438,8 +1448,7 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *
                                if (get_sha1_hex(rec + 41, sha1))
                                        die("Log %s is corrupt.", logfile);
                                if (hashcmp(logged_sha1, sha1)) {
-                                       fprintf(stderr,
-                                               "warning: Log %s has gap after %s.\n",
+                                       warning("Log %s has gap after %s.",
                                                logfile, show_date(date, tz, DATE_RFC2822));
                                }
                        }
@@ -1451,8 +1460,7 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *
                                if (get_sha1_hex(rec + 41, logged_sha1))
                                        die("Log %s is corrupt.", logfile);
                                if (hashcmp(logged_sha1, sha1)) {
-                                       fprintf(stderr,
-                                               "warning: Log %s unexpectedly ended on %s.\n",
+                                       warning("Log %s unexpectedly ended on %s.",
                                                logfile, show_date(date, tz, DATE_RFC2822));
                                }
                        }
diff --git a/refs.h b/refs.h
index 29bdcecd4edb5e7281a4da36a06aa05e025f38a7..68c2d16d5388f5591a610e1d6fcf2f731159ecb2 100644 (file)
--- a/refs.h
+++ b/refs.h
@@ -79,6 +79,8 @@ extern int for_each_reflog(each_ref_fn, void *);
 #define CHECK_REF_FORMAT_WILDCARD (-3)
 extern int check_ref_format(const char *target);
 
+extern const char *prettify_ref(const struct ref *ref);
+
 /** rename ref, return 0 on success **/
 extern int rename_ref(const char *oldref, const char *newref, const char *logmsg);
 
index e5d6b100d738c388bff91bff68b14f69dea87166..2b037f11b29d86e38d6608a58c65e79e0ffd3800 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -1401,9 +1401,10 @@ int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs)
        if (theirs == ours)
                return 0;
 
-       /* Run "rev-list --left-right ours...theirs" internally... */
+       /* Run "rev-list --no-merges --left-right ours...theirs" internally... */
        rev_argc = 0;
        rev_argv[rev_argc++] = NULL;
+       rev_argv[rev_argc++] = "--no-merges";
        rev_argv[rev_argc++] = "--left-right";
        rev_argv[rev_argc++] = symmetric;
        rev_argv[rev_argc++] = "--";
index f5771c7898a939e34effb8c757c5a237830075b9..b6215cc72c77baa3f72d652e8457d3ace6e5f439 100644 (file)
@@ -1106,10 +1106,6 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
                revs->edge_hint = 1;
        } else if (!strcmp(arg, "--unpacked")) {
                revs->unpacked = 1;
-               revs->kept_pack_only = 0;
-       } else if (!strcmp(arg, "--kept-pack-only")) {
-               revs->unpacked = 1;
-               revs->kept_pack_only = 1;
        } else if (!prefixcmp(arg, "--unpacked=")) {
                die("--unpacked=<packfile> no longer supported.");
        } else if (!strcmp(arg, "-r")) {
@@ -1679,10 +1675,7 @@ enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit)
 {
        if (commit->object.flags & SHOWN)
                return commit_ignore;
-       if (revs->unpacked &&
-           (revs->kept_pack_only
-            ? has_sha1_kept_pack(commit->object.sha1)
-            : has_sha1_pack(commit->object.sha1)))
+       if (revs->unpacked && has_sha1_pack(commit->object.sha1))
                return commit_ignore;
        if (revs->show_all)
                return commit_show;
index 5259ed519272d49ad8a73e88eb6cb838f62cfd11..5adfc9140544429254bd67ff10504730c7424e1b 100644 (file)
@@ -50,7 +50,6 @@ struct rev_info {
                        edge_hint:1,
                        limited:1,
                        unpacked:1,
-                       kept_pack_only:1,
                        boundary:2,
                        left_right:1,
                        rewrite_parents:1,
index 15e870a65eb037cd49d1e01251711915da06d260..e3455028435eab958d5f86a3e86249f1704b9c1b 100644 (file)
@@ -10,7 +10,7 @@ enum {
        ERR_RUN_COMMAND_WAITPID_SIGNAL,
        ERR_RUN_COMMAND_WAITPID_NOEXIT,
 };
-#define IS_RUN_COMMAND_ERR(x) ((x) <= -ERR_RUN_COMMAND_FORK)
+#define IS_RUN_COMMAND_ERR(x) (-(x) >= ERR_RUN_COMMAND_FORK)
 
 struct child_process {
        const char **argv;
index 8ff1dc35390083c3648c4ee5790f35633d956069..83d76c7e35183ded9eec5a56c59d4da549c0b584 100644 (file)
@@ -2,9 +2,7 @@
 #define SEND_PACK_H
 
 struct send_pack_args {
-       const char *receivepack;
        unsigned verbose:1,
-               send_all:1,
                send_mirror:1,
                force_update:1,
                use_thin_pack:1,
@@ -12,7 +10,7 @@ struct send_pack_args {
 };
 
 int send_pack(struct send_pack_args *args,
-             const char *dest, struct remote *remote,
-             int nr_heads, const char **heads);
+             int fd[], struct child_process *conn,
+             struct ref *remote_refs, struct extra_have_objects *extra_have);
 
 #endif
index 456317356f323eb744c207d787a2e7598ad9601e..37e833b77d1ee556d18256154073a706ab11b3a4 100644 (file)
@@ -1919,8 +1919,7 @@ off_t find_pack_entry_one(const unsigned char *sha1,
        return 0;
 }
 
-static int find_pack_ent(const unsigned char *sha1, struct pack_entry *e,
-                        int kept_pack_only)
+static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
 {
        static struct packed_git *last_found = (void *)1;
        struct packed_git *p;
@@ -1932,8 +1931,6 @@ static int find_pack_ent(const unsigned char *sha1, struct pack_entry *e,
        p = (last_found == (void *)1) ? packed_git : last_found;
 
        do {
-               if (kept_pack_only && !p->pack_keep)
-                       goto next;
                if (p->num_bad_objects) {
                        unsigned i;
                        for (i = 0; i < p->num_bad_objects; i++)
@@ -1973,16 +1970,6 @@ static int find_pack_ent(const unsigned char *sha1, struct pack_entry *e,
        return 0;
 }
 
-static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
-{
-       return find_pack_ent(sha1, e, 0);
-}
-
-static int find_kept_pack_entry(const unsigned char *sha1, struct pack_entry *e)
-{
-       return find_pack_ent(sha1, e, 1);
-}
-
 struct packed_git *find_sha1_pack(const unsigned char *sha1,
                                  struct packed_git *packs)
 {
@@ -2287,7 +2274,7 @@ static void close_sha1_file(int fd)
                fsync_or_die(fd, "sha1 file");
        fchmod(fd, 0444);
        if (close(fd) != 0)
-               die("unable to write sha1 file");
+               die("error when closing sha1 file (%s)", strerror(errno));
 }
 
 /* Size of directory component, including the ending '/' */
@@ -2456,12 +2443,6 @@ int has_sha1_pack(const unsigned char *sha1)
        return find_pack_entry(sha1, &e);
 }
 
-int has_sha1_kept_pack(const unsigned char *sha1)
-{
-       struct pack_entry e;
-       return find_kept_pack_entry(sha1, &e);
-}
-
 int has_sha1_file(const unsigned char *sha1)
 {
        struct pack_entry e;
index 09623414a755dc7e964a0d21768e136dba4556e2..bf816fc8505508c91999175ad6544a67febabb33 100644 (file)
@@ -24,7 +24,7 @@ pre-clean:
        $(RM) -r test-results
 
 clean:
-       $(RM) -r 'trash directory' test-results
+       $(RM) -r 'trash directory'.* test-results
 
 aggregate-results-and-cleanup: $(T)
        $(MAKE) aggregate-results
index de384e6ac3a125e59156abbf897a3371f736bbfa..cdd7ccdd2ac87e27bd6912e92477e986517c32ad 100644 (file)
@@ -7,7 +7,6 @@ if test -n "$NO_SVN_TESTS"
 then
        say 'skipping git svn tests, NO_SVN_TESTS defined'
        test_done
-       exit
 fi
 
 GIT_DIR=$PWD/.git
@@ -19,7 +18,6 @@ if test $? -ne 1
 then
     say 'skipping git svn tests, svn not found'
     test_done
-    exit
 fi
 
 svnrepo=$PWD/svnrepo
@@ -43,7 +41,6 @@ then
        fi
        say "$err"
        test_done
-       exit
 fi
 
 rawsvnrepo="$svnrepo"
@@ -144,7 +141,6 @@ require_svnserve () {
     then
         say 'skipping svnserve test. (set $SVNSERVE_PORT to enable)'
         test_done
-        exit
     fi
 }
 
index 589aaf82149916c43d42fad488567e34b26aebaa..cde659d14ac599e78bb4cd12a2ad88eab179549e 100644 (file)
@@ -8,7 +8,6 @@ then
        say "skipping test, network testing disabled by default"
        say "(define GIT_TEST_HTTPD to enable)"
        test_done
-       exit
 fi
 
 HTTPD_PARA=""
@@ -36,7 +35,6 @@ if ! test -x "$LIB_HTTPD_PATH"
 then
        say "skipping test, no web server found at '$LIB_HTTPD_PATH'"
        test_done
-       exit
 fi
 
 HTTPD_VERSION=`$LIB_HTTPD_PATH -v | \
@@ -50,7 +48,6 @@ then
                then
                        say "skipping test, at least Apache version 2 is required"
                        test_done
-                       exit
                fi
 
                LIB_HTTPD_MODULE_PATH="$DEFAULT_HTTPD_MODULE_PATH"
index ddcd5b0efb318a07c18e1bb7b908d1c402a974ed..f4ca4fc85c6b52a2ba919528284f2b668e6bd3d2 100755 (executable)
@@ -57,6 +57,21 @@ test_expect_failure 'pretend we have a known breakage' '
 test_expect_failure 'pretend we have fixed a known breakage' '
     :
 '
+test_set_prereq HAVEIT
+haveit=no
+test_expect_success HAVEIT 'test runs if prerequisite is satisfied' '
+    test_have_prereq HAVEIT &&
+    haveit=yes
+'
+donthaveit=yes
+test_expect_success DONTHAVEIT 'unmet prerequisite causes test to be skipped' '
+    donthaveit=no
+'
+if test $haveit$donthaveit != yesyes
+then
+       say "bug in test framework: prerequisite tags do not work reliably"
+       exit 1
+fi
 
 ################################################################
 # Basics of the basics
@@ -100,12 +115,31 @@ test_expect_success \
     'test "$tree" = 4b825dc642cb6eb9a060e54bf8d69288fbee4904'
 
 # Various types of objects
+# Some filesystems do not support symblic links; on such systems
+# some expected values are different
 mkdir path2 path3 path3/subp3
-for p in path0 path2/file2 path3/file3 path3/subp3/file3
+paths='path0 path2/file2 path3/file3 path3/subp3/file3'
+for p in $paths
 do
     echo "hello $p" >$p
-    ln -s "hello $p" ${p}sym
 done
+if test_have_prereq SYMLINKS
+then
+       for p in $paths
+       do
+               ln -s "hello $p" ${p}sym
+       done
+       expectfilter=cat
+       expectedtree=087704a96baf1c2d1c869a8b084481e121c88b5b
+       expectedptree1=21ae8269cacbe57ae09138dcc3a2887f904d02b3
+       expectedptree2=3c5e5399f3a333eddecce7a9b9465b63f65f51e2
+else
+       expectfilter='grep -v sym'
+       expectedtree=8e18edf7d7edcf4371a3ac6ae5f07c2641db7c46
+       expectedptree1=cfb8591b2f65de8b8cc1020cd7d9e67e7793b325
+       expectedptree2=ce580448f0148b985a513b693fdf7d802cacb44f
+fi
+
 test_expect_success \
     'adding various types of objects with git update-index --add.' \
     'find path* ! -type d -print | xargs git update-index --add'
@@ -115,7 +149,7 @@ test_expect_success \
     'showing stage with git ls-files --stage' \
     'git ls-files --stage >current'
 
-cat >expected <<\EOF
+$expectfilter >expected <<\EOF
 100644 f87290f8eb2cbbea7857214459a0739927eab154 0      path0
 120000 15a98433ae33114b085f3eb3bb03b832b3180a01 0      path0sym
 100644 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 0      path2/file2
@@ -134,7 +168,7 @@ test_expect_success \
     'tree=$(git write-tree)'
 test_expect_success \
     'validate object ID for a known tree.' \
-    'test "$tree" = 087704a96baf1c2d1c869a8b084481e121c88b5b'
+    'test "$tree" = "$expectedtree"'
 
 test_expect_success \
     'showing tree with git ls-tree' \
@@ -145,7 +179,7 @@ cat >expected <<\EOF
 040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe   path2
 040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3   path3
 EOF
-test_expect_success \
+test_expect_success SYMLINKS \
     'git ls-tree output for a known tree.' \
     'test_cmp expected current'
 
@@ -154,7 +188,7 @@ test_expect_success \
 test_expect_success \
     'showing tree with git ls-tree -r' \
     'git ls-tree -r $tree >current'
-cat >expected <<\EOF
+$expectfilter >expected <<\EOF
 100644 blob f87290f8eb2cbbea7857214459a0739927eab154   path0
 120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01   path0sym
 100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7   path2/file2
@@ -185,7 +219,7 @@ cat >expected <<\EOF
 100644 blob 00fb5908cb97c2564a9783c0c64087333b3b464f   path3/subp3/file3
 120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c   path3/subp3/file3sym
 EOF
-test_expect_success \
+test_expect_success SYMLINKS \
     'git ls-tree -r output for a known tree.' \
     'test_cmp expected current'
 
@@ -194,14 +228,14 @@ test_expect_success \
     'ptree=$(git write-tree --prefix=path3)'
 test_expect_success \
     'validate object ID for a known tree.' \
-    'test "$ptree" = 21ae8269cacbe57ae09138dcc3a2887f904d02b3'
+    'test "$ptree" = "$expectedptree1"'
 
 test_expect_success \
     'writing partial tree out with git write-tree --prefix.' \
     'ptree=$(git write-tree --prefix=path3/subp3)'
 test_expect_success \
     'validate object ID for a known tree.' \
-    'test "$ptree" = 3c5e5399f3a333eddecce7a9b9465b63f65f51e2'
+    'test "$ptree" = "$expectedptree2"'
 
 cat >badobjects <<EOF
 100644 blob 1000000000000000000000000000000000000000   dir/file1
@@ -234,7 +268,7 @@ test_expect_success \
      newtree=$(git write-tree) &&
      test "$newtree" = "$tree"'
 
-cat >expected <<\EOF
+$expectfilter >expected <<\EOF
 :100644 100644 f87290f8eb2cbbea7857214459a0739927eab154 0000000000000000000000000000000000000000 M     path0
 :120000 120000 15a98433ae33114b085f3eb3bb03b832b3180a01 0000000000000000000000000000000000000000 M     path0sym
 :100644 100644 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 0000000000000000000000000000000000000000 M     path2/file2
@@ -257,7 +291,7 @@ test_expect_success \
     'git diff-files >current && cmp -s current /dev/null'
 
 ################################################################
-P=087704a96baf1c2d1c869a8b084481e121c88b5b
+P=$expectedtree
 test_expect_success \
     'git commit-tree records the correct tree in a commit.' \
     'commit0=$(echo NO | git commit-tree $P) &&
@@ -293,7 +327,7 @@ test_expect_success 'update-index D/F conflict' '
        test $numpath0 = 1
 '
 
-test_expect_success 'absolute path works as expected' '
+test_expect_success SYMLINKS 'absolute path works as expected' '
        mkdir first &&
        ln -s ../.git first/.git &&
        mkdir second &&
index 63e1217e7162435c3da8ec7984b5f6a53b3a10e2..2342ac5788a9976b591cb78593279f092d1dc2f6 100755 (executable)
@@ -15,7 +15,7 @@ test_expect_success setup '
 
 '
 
-test_expect_success 'write-tree should notice unwritable repository' '
+test_expect_success POSIXPERM 'write-tree should notice unwritable repository' '
 
        (
                chmod a-w .git/objects .git/objects/?? &&
@@ -27,7 +27,7 @@ test_expect_success 'write-tree should notice unwritable repository' '
 
 '
 
-test_expect_success 'commit should notice unwritable repository' '
+test_expect_success POSIXPERM 'commit should notice unwritable repository' '
 
        (
                chmod a-w .git/objects .git/objects/?? &&
@@ -39,7 +39,7 @@ test_expect_success 'commit should notice unwritable repository' '
 
 '
 
-test_expect_success 'update-index should notice unwritable repository' '
+test_expect_success POSIXPERM 'update-index should notice unwritable repository' '
 
        (
                echo 6O >file &&
@@ -52,7 +52,7 @@ test_expect_success 'update-index should notice unwritable repository' '
 
 '
 
-test_expect_success 'add should notice unwritable repository' '
+test_expect_success POSIXPERM 'add should notice unwritable repository' '
 
        (
                echo b >file &&
index 1be7446d8d9f8a46b463f2474a8c25bdd33044d2..4e72b53140bd35db87a6c873eda9e75e896e1cdd 100755 (executable)
@@ -429,6 +429,37 @@ test_expect_success 'in-tree .gitattributes (4)' '
        }
 '
 
+test_expect_success 'checkout with existing .gitattributes' '
+
+       git config core.autocrlf true &&
+       git config --unset core.safecrlf &&
+       echo ".file2 -crlfQ" | q_to_cr >> .gitattributes &&
+       git add .gitattributes &&
+       git commit -m initial &&
+       echo ".file -crlfQ" | q_to_cr >> .gitattributes &&
+       echo "contents" > .file &&
+       git add .gitattributes .file &&
+       git commit -m second &&
+
+       git checkout master~1 &&
+       git checkout master &&
+       test "$(git diff-files --raw)" = ""
+
+'
+
+test_expect_success 'checkout when deleting .gitattributes' '
+
+       git rm .gitattributes &&
+       echo "contentsQ" | q_to_cr > .file2 &&
+       git add .file2 &&
+       git commit -m third
+
+       git checkout master~1 &&
+       git checkout master &&
+       remove_cr .file2 >/dev/null
+
+'
+
 test_expect_success 'invalid .gitattributes (must not crash)' '
 
        echo "three +crlf" >>.gitattributes &&
index ae90d34f6cf50c9ffcbb386fb27b8a15042109ed..c7d0324374e9df5131a58a9ae0cadf7ee4dc03e7 100755 (executable)
@@ -29,11 +29,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"
-       test_done
-       exit
+else
+       test_set_prereq UNZIP
 fi
 
-test_expect_success 'zip archive' '
+test_expect_success UNZIP 'zip archive' '
 
        git archive --format=zip HEAD >test.zip &&
 
index a449580c8a2e41c665e1f29c56877e271fd17fef..89282ccf7a1a73d4b5ee085c4236b1204dc502c8 100755 (executable)
@@ -9,7 +9,8 @@ aumlcdiar=`printf '\x61\xcc\x88'`
 
 case_insensitive=
 unibad=
-test_expect_success 'see if we expect ' '
+no_symlinks=
+test_expect_success 'see what we expect' '
 
        test_case=test_expect_success
        test_unicode=test_expect_success
@@ -31,13 +32,21 @@ test_expect_success 'see if we expect ' '
                ;;
        *)      ;;
        esac &&
-       rm -fr junk
+       rm -fr junk &&
+       {
+               ln -s x y 2> /dev/null &&
+               test -h y 2> /dev/null ||
+               no_symlinks=1
+               rm -f y
+       }
 '
 
 test "$case_insensitive" &&
        say "will test on a case insensitive filesystem"
 test "$unibad" &&
        say "will test on a unicode corrupting filesystem"
+test "$no_symlinks" &&
+       say "will test on a filesystem lacking symbolic links"
 
 if test "$case_insensitive"
 then
@@ -53,6 +62,21 @@ test_expect_success "detection of case insensitive filesystem during repo init"
 '
 fi
 
+if test "$no_symlinks"
+then
+test_expect_success "detection of filesystem w/o symlink support during repo init" '
+
+       v=$(git config --bool core.symlinks) &&
+       test "$v" = false
+'
+else
+test_expect_success "detection of filesystem w/o symlink support during repo init" '
+
+       test_must_fail git config --bool core.symlinks ||
+       test "$(git config --bool core.symlinks)" = true
+'
+fi
+
 test_expect_success "setup case tests" '
 
        git config core.ignorecase true &&
index b29c37a5a4de42239474c4fdf87c86c6f27b6ade..0c6ff567a1d47f52492dd89bd098b25bae737bad 100755 (executable)
@@ -4,7 +4,7 @@ test_description='update-index and add refuse to add beyond symlinks'
 
 . ./test-lib.sh
 
-test_expect_success setup '
+test_expect_success SYMLINKS setup '
        >a &&
        mkdir b &&
        ln -s b c &&
@@ -12,12 +12,12 @@ test_expect_success setup '
        git update-index --add a b/d
 '
 
-test_expect_success 'update-index --add beyond symlinks' '
+test_expect_success SYMLINKS 'update-index --add beyond symlinks' '
        test_must_fail git update-index --add c/d &&
        ! ( git ls-files | grep c/d )
 '
 
-test_expect_success 'add beyond symlinks' '
+test_expect_success SYMLINKS 'add beyond symlinks' '
        test_must_fail git add c/d &&
        ! ( git ls-files | grep c/d )
 '
index 8336114f9820aa5972d38efe316de7d9e39bcc5c..53cf1f8dc4acad959fdec359b738387aeb126b1e 100755 (executable)
@@ -7,41 +7,91 @@ test_description='Test various path utilities'
 
 . ./test-lib.sh
 
-norm_abs() {
-       test_expect_success "normalize absolute: $1 => $2" \
+norm_path() {
+       test_expect_success $3 "normalize path: $1 => $2" \
        "test \"\$(test-path-utils normalize_path_copy '$1')\" = '$2'"
 }
 
+# On Windows, we are using MSYS's bash, which mangles the paths.
+# Absolute paths are anchored at the MSYS installation directory,
+# which means that the path / accounts for this many characters:
+rootoff=$(test-path-utils normalize_path_copy / | wc -c)
+# Account for the trailing LF:
+if test $rootoff = 2; then
+       rootoff=        # we are on Unix
+else
+       rootoff=$(($rootoff-1))
+fi
+
 ancestor() {
-       test_expect_success "longest ancestor: $1 $2 => $3" \
-       "test \"\$(test-path-utils longest_ancestor_length '$1' '$2')\" = '$3'"
+       # We do some math with the expected ancestor length.
+       expected=$3
+       if test -n "$rootoff" && test "x$expected" != x-1; then
+               expected=$(($expected+$rootoff))
+       fi
+       test_expect_success "longest ancestor: $1 $2 => $expected" \
+       "actual=\$(test-path-utils longest_ancestor_length '$1' '$2') &&
+        test \"\$actual\" = '$expected'"
 }
 
-norm_abs "" ""
-norm_abs / /
-norm_abs // /
-norm_abs /// /
-norm_abs /. /
-norm_abs /./ /
-norm_abs /./.. ++failed++
-norm_abs /../. ++failed++
-norm_abs /./../.// ++failed++
-norm_abs /dir/.. /
-norm_abs /dir/sub/../.. /
-norm_abs /dir/sub/../../.. ++failed++
-norm_abs /dir /dir
-norm_abs /dir// /dir/
-norm_abs /./dir /dir
-norm_abs /dir/. /dir/
-norm_abs /dir///./ /dir/
-norm_abs /dir//sub/.. /dir/
-norm_abs /dir/sub/../ /dir/
-norm_abs //dir/sub/../. /dir/
-norm_abs /dir/s1/../s2/ /dir/s2/
-norm_abs /d1/s1///s2/..//../s3/ /d1/s3/
-norm_abs /d1/s1//../s2/../../d2 /d2
-norm_abs /d1/.../d2 /d1/.../d2
-norm_abs /d1/..././../d2 /d1/d2
+# Absolute path tests must be skipped on Windows because due to path mangling
+# the test program never sees a POSIX-style absolute path
+case $(uname -s) in
+*MINGW*)
+       ;;
+*)
+       test_set_prereq POSIX
+       ;;
+esac
+
+norm_path "" ""
+norm_path . ""
+norm_path ./ ""
+norm_path ./. ""
+norm_path ./.. ++failed++
+norm_path ../. ++failed++
+norm_path ./../.// ++failed++
+norm_path dir/.. ""
+norm_path dir/sub/../.. ""
+norm_path dir/sub/../../.. ++failed++
+norm_path dir dir
+norm_path dir// dir/
+norm_path ./dir dir
+norm_path dir/. dir/
+norm_path dir///./ dir/
+norm_path dir//sub/.. dir/
+norm_path dir/sub/../ dir/
+norm_path dir/sub/../. dir/
+norm_path dir/s1/../s2/ dir/s2/
+norm_path d1/s1///s2/..//../s3/ d1/s3/
+norm_path d1/s1//../s2/../../d2 d2
+norm_path d1/.../d2 d1/.../d2
+norm_path d1/..././../d2 d1/d2
+
+norm_path / / POSIX
+norm_path // / POSIX
+norm_path /// / POSIX
+norm_path /. / POSIX
+norm_path /./ / POSIX
+norm_path /./.. ++failed++ POSIX
+norm_path /../. ++failed++ POSIX
+norm_path /./../.// ++failed++ POSIX
+norm_path /dir/.. / POSIX
+norm_path /dir/sub/../.. / POSIX
+norm_path /dir/sub/../../.. ++failed++ POSIX
+norm_path /dir /dir POSIX
+norm_path /dir// /dir/ POSIX
+norm_path /./dir /dir POSIX
+norm_path /dir/. /dir/ POSIX
+norm_path /dir///./ /dir/ POSIX
+norm_path /dir//sub/.. /dir/ POSIX
+norm_path /dir/sub/../ /dir/ POSIX
+norm_path //dir/sub/../. /dir/ POSIX
+norm_path /dir/s1/../s2/ /dir/s2/ POSIX
+norm_path /d1/s1///s2/..//../s3/ /d1/s3/ POSIX
+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
@@ -80,10 +130,10 @@ 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 .:/foo/. 4
+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 570d3729bd2312a8d9cf90f3d2e1121a58f43de6..f19b4a2a4afa89fd1242d1acccb1e999e6a88c6d 100755 (executable)
@@ -157,7 +157,7 @@ test_expect_success '3-way not overwriting local changes (their side)' '
 
 '
 
-test_expect_success 'funny symlink in work tree' '
+test_expect_success SYMLINKS 'funny symlink in work tree' '
 
        git reset --hard &&
        git checkout -b sym-b side-b &&
@@ -177,7 +177,7 @@ test_expect_success 'funny symlink in work tree' '
 
 '
 
-test_expect_success 'funny symlink in work tree, un-unlink-able' '
+test_expect_success SYMLINKS 'funny symlink in work tree, un-unlink-able' '
 
        rm -fr a b &&
        git reset --hard &&
@@ -189,7 +189,7 @@ test_expect_success 'funny symlink in work tree, un-unlink-able' '
 '
 
 # clean-up from the above test
-chmod a+w a
+chmod a+w a 2>/dev/null
 rm -fr a b
 
 test_expect_success 'D/F setup' '
index fc386ba033ac165a5f4a9fca0c6c6f5db49a314e..210e594f6f3c83cc1b0c423a0f692380ff57176b 100755 (executable)
@@ -126,7 +126,7 @@ test_expect_success 'no file/rev ambiguity check inside a bare repo' '
        cd foo.git && git show -s HEAD
 '
 
-test_expect_success 'detection should not be fooled by a symlink' '
+test_expect_success SYMLINKS 'detection should not be fooled by a symlink' '
        cd "$HERE" &&
        rm -fr foo.git &&
        git clone -s .git another &&
index 9c81e041b9f688ebeffacce06b3ff94e153bb9b2..43ea283242c4afc25e53d4a8c894140793649717 100755 (executable)
@@ -733,7 +733,7 @@ echo >>result
 
 test_expect_success '--null --get-regexp' 'cmp result expect'
 
-test_expect_success 'symlinked configuration' '
+test_expect_success SYMLINKS 'symlinked configuration' '
 
        ln -s notyet myconfig &&
        GIT_CONFIG=myconfig git config test.frotz nitfol &&
index 653362ba221ee017512264c83a216b1ad1723bcd..dc4485409dd5e5f28d07c71c2decce1f35237bf4 100755 (executable)
@@ -26,7 +26,7 @@ modebits () {
 
 for u in 002 022
 do
-       test_expect_success "shared=1 does not clear bits preset by umask $u" '
+       test_expect_success POSIXPERM "shared=1 does not clear bits preset by umask $u" '
                mkdir sub && (
                        cd sub &&
                        umask $u &&
@@ -54,7 +54,7 @@ test_expect_success 'shared=all' '
        test 2 = $(git config core.sharedrepository)
 '
 
-test_expect_success 'update-server-info honors core.sharedRepository' '
+test_expect_success POSIXPERM 'update-server-info honors core.sharedRepository' '
        : > a1 &&
        git add a1 &&
        test_tick &&
@@ -85,7 +85,7 @@ do
        git config core.sharedrepository "$u" &&
        umask 0277 &&
 
-       test_expect_success "shared = $u ($y) ro" '
+       test_expect_success POSIXPERM "shared = $u ($y) ro" '
 
                rm -f .git/info/refs &&
                git update-server-info &&
@@ -97,7 +97,7 @@ do
        '
 
        umask 077 &&
-       test_expect_success "shared = $u ($x) rw" '
+       test_expect_success POSIXPERM "shared = $u ($x) rw" '
 
                rm -f .git/info/refs &&
                git update-server-info &&
@@ -111,7 +111,7 @@ do
 
 done
 
-test_expect_success 'git reflog expire honors core.sharedRepository' '
+test_expect_success POSIXPERM 'git reflog expire honors core.sharedRepository' '
        git config core.sharedRepository group &&
        git reflog expire --all &&
        actual="$(ls -l .git/logs/refs/heads/master)" &&
diff --git a/t/t1411-reflog-show.sh b/t/t1411-reflog-show.sh
new file mode 100755 (executable)
index 0000000..c18ed8e
--- /dev/null
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+test_description='Test reflog display routines'
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+       echo content >file &&
+       git add file &&
+       test_tick &&
+       git commit -m one
+'
+
+cat >expect <<'EOF'
+Reflog: HEAD@{0} (C O Mitter <committer@example.com>)
+Reflog message: commit (initial): one
+EOF
+test_expect_success 'log -g shows reflog headers' '
+       git log -g -1 >tmp &&
+       grep ^Reflog <tmp >actual &&
+       test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+e46513e HEAD@{0}: commit (initial): one
+EOF
+test_expect_success 'oneline reflog format' '
+       git log -g -1 --oneline >actual &&
+       test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+Reflog: HEAD@{Thu Apr 7 15:13:13 2005 -0700} (C O Mitter <committer@example.com>)
+Reflog message: commit (initial): one
+EOF
+test_expect_success 'using @{now} syntax shows reflog date (multiline)' '
+       git log -g -1 HEAD@{now} >tmp &&
+       grep ^Reflog <tmp >actual &&
+       test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+e46513e HEAD@{Thu Apr 7 15:13:13 2005 -0700}: commit (initial): one
+EOF
+test_expect_success 'using @{now} syntax shows reflog date (oneline)' '
+       git log -g -1 --oneline HEAD@{now} >actual &&
+       test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+Reflog: HEAD@{1112911993 -0700} (C O Mitter <committer@example.com>)
+Reflog message: commit (initial): one
+EOF
+test_expect_success 'using --date= shows reflog date (multiline)' '
+       git log -g -1 --date=raw >tmp &&
+       grep ^Reflog <tmp >actual &&
+       test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+e46513e HEAD@{1112911993 -0700}: commit (initial): one
+EOF
+test_expect_success 'using --date= shows reflog date (oneline)' '
+       git log -g -1 --oneline --date=raw >actual &&
+       test_cmp expect actual
+'
+
+test_done
index e377d48902cd5fd539a0ce4cb1fb32ceb8732632..df5ad8c686a959c9b03355c1ebc325f3c755ed46 100755 (executable)
@@ -13,7 +13,7 @@ test_fail() {
        "git rev-parse --show-prefix"
 }
 
-TRASH_ROOT="$(pwd)"
+TRASH_ROOT="$PWD"
 ROOT_PARENT=$(dirname "$TRASH_ROOT")
 
 
index ef007532b15108d72445f7c95a2906a3039fbbbb..98aa73e8239355eba098253edfd156d4ea254be2 100755 (executable)
@@ -59,10 +59,10 @@ test_expect_success \
     'git read-tree -m $tree1 && git checkout-index -f -a'
 test_debug 'show_files $tree1'
 
-ln -s path0 path1
-test_expect_success \
+test_expect_success SYMLINKS \
     'git update-index --add a symlink.' \
-    'git update-index --add path1'
+    'ln -s path0 path1 &&
+     git update-index --add path1'
 test_expect_success \
     'writing tree out with git write-tree' \
     'tree3=$(git write-tree)'
index 71894b37439bd1b9c72194cbbabe37680d2f9743..02a4fc5d36a08d1046b9384c799f697640da0c4e 100755 (executable)
@@ -19,7 +19,7 @@ test_expect_success \
     echo rezrov >path1/file1 &&
     git update-index --add path0 path1/file1'
 
-test_expect_success \
+test_expect_success SYMLINKS \
     'have symlink in place where dir is expected.' \
     'rm -fr path0 path1 &&
      mkdir path2 &&
@@ -59,7 +59,7 @@ test_expect_success \
      test ! -f path1/file1'
 
 # Linus fix #1
-test_expect_success \
+test_expect_success SYMLINKS \
     'use --prefix=tmp/orary/ where tmp is a symlink' \
     'rm -fr path0 path1 path2 tmp* &&
      mkdir tmp1 tmp1/orary &&
@@ -71,7 +71,7 @@ test_expect_success \
      test -h tmp'
 
 # Linus fix #2
-test_expect_success \
+test_expect_success SYMLINKS \
     'use --prefix=tmp/orary- where tmp is a symlink' \
     'rm -fr path0 path1 path2 tmp* &&
      mkdir tmp1 &&
@@ -82,7 +82,7 @@ test_expect_success \
      test -h tmp'
 
 # Linus fix #3
-test_expect_success \
+test_expect_success SYMLINKS \
     'use --prefix=tmp- where tmp-path1 is a symlink' \
     'rm -fr path0 path1 path2 tmp* &&
      mkdir tmp1 &&
index 39133b8c7a4b56cb7273cec607ea89081a426eff..36cca14d957f85733174d6ce514e22acfff3b1c9 100755 (executable)
@@ -194,7 +194,7 @@ test_expect_success \
  test $(cat ../$s1) = tree1asubdir/path5)
 )'
 
-test_expect_success \
+test_expect_success SYMLINKS \
 'checkout --temp symlink' '
 rm -f path* .merge_* out .git/index &&
 ln -s b a &&
index 0526fce163fc13273daf035a0920a6b53a3acefb..20f33436d00077b64dcc855fc263cd5d0efcca38 100755 (executable)
@@ -6,6 +6,12 @@ test_description='git checkout to switch between branches with symlink<->dir'
 
 . ./test-lib.sh
 
+if ! test_have_prereq SYMLINKS
+then
+       say "symbolic links not supported - skipping tests"
+       test_done
+fi
+
 test_expect_success setup '
 
        mkdir frotz &&
index 6ef2dcfd8afece86aaf6345630179af179eb2ed9..2df3fdde8bf665a2b531dd367b70a7a767ee3dbc 100755 (executable)
@@ -26,7 +26,12 @@ All of the attempts should fail.
 
 mkdir path2 path3
 date >path0
-ln -s xyzzy path1
+if test_have_prereq SYMLINKS
+then
+       ln -s xyzzy path1
+else
+       date > path1
+fi
 date >path2/file2
 date >path3/file3
 
@@ -38,7 +43,12 @@ rm -fr path?
 
 mkdir path0 path1
 date >path2
-ln -s frotz path3
+if test_have_prereq SYMLINKS
+then
+       ln -s frotz path3
+else
+       date > path3
+fi
 date >path0/file0
 date >path1/file1
 
index 5a8d52f2ff5ecfea8a1d4f9d39a2ed4a08c822e0..912075063b9946d38a9ff72621cb80bcf2c05399 100755 (executable)
@@ -80,7 +80,7 @@ test_expect_success 'change gets noticed' '
 
 '
 
-test_expect_success 'replace a file with a symlink' '
+test_expect_success SYMLINKS 'replace a file with a symlink' '
 
        rm foo &&
        ln -s top foo &&
index d24c7d9e5fce0e9c0f8ef5576dab86ffdbc11331..2e8f70245204bd4dc78e67f227e86838e1cdad5b 100755 (executable)
@@ -11,7 +11,13 @@ test_expect_success setup '
        _empty=$(git hash-object --stdin <xyzzy) &&
        >yomin &&
        >caskly &&
-       ln -s frotz nitfol &&
+       if test_have_prereq SYMLINKS; then
+               ln -s frotz nitfol &&
+               T_letter=T
+       else
+               printf %s frotz > nitfol &&
+               T_letter=M
+       fi &&
        mkdir rezrov &&
        >rezrov/bozbar &&
        git add caskly xyzzy yomin nitfol rezrov/bozbar &&
@@ -29,7 +35,11 @@ test_expect_success modify '
        >nitfol &&
        # rezrov/bozbar disappears
        rm -fr rezrov &&
-       ln -s xyzzy rezrov &&
+       if test_have_prereq SYMLINKS; then
+               ln -s xyzzy rezrov
+       else
+               printf %s xyzzy > rezrov
+       fi &&
        # xyzzy disappears (not a submodule)
        mkdir xyzzy &&
        echo gnusto >xyzzy/bozbar &&
@@ -71,7 +81,7 @@ test_expect_success modify '
                                s/blob/000000/
                        }
                        /       nitfol/{
-                               s/      nitfol/ $_z40 T&/
+                               s/      nitfol/ $_z40 $T_letter&/
                                s/blob/100644/
                        }
                        /       rezrov.bozbar/{
index 293dc353b1601e137f86dfe441fff57b96c92753..3b01ad2e4de152d23bbe8267d3b1a5cafd615e88 100755 (executable)
@@ -5,7 +5,7 @@ test_description='cd_to_toplevel'
 . ./test-lib.sh
 
 test_cd_to_toplevel () {
-       test_expect_success "$2" '
+       test_expect_success $3 "$2" '
                (
                        cd '"'$1'"' &&
                        . git-sh-setup &&
@@ -24,14 +24,14 @@ test_cd_to_toplevel repo 'at physical root'
 
 test_cd_to_toplevel repo/sub/dir 'at physical subdir'
 
-ln -s repo symrepo
-test_cd_to_toplevel symrepo 'at symbolic root'
+ln -s repo symrepo 2>/dev/null
+test_cd_to_toplevel symrepo 'at symbolic root' SYMLINKS
 
-ln -s repo/sub/dir subdir-link
-test_cd_to_toplevel subdir-link 'at symbolic subdir'
+ln -s repo/sub/dir subdir-link 2>/dev/null
+test_cd_to_toplevel subdir-link 'at symbolic subdir' SYMLINKS
 
 cd repo
-ln -s sub/dir internal-link
-test_cd_to_toplevel internal-link 'at internal symbolic subdir'
+ln -s sub/dir internal-link 2>/dev/null
+test_cd_to_toplevel internal-link 'at internal symbolic subdir' SYMLINKS
 
 test_done
index 379d963ceafd64fa989fdfd1bba4e420e479bbf8..86291e839942e6842bf1d2b40f2d7f7c1d8d4a9f 100755 (executable)
@@ -18,7 +18,12 @@ filesystem.
 . ./test-lib.sh
 
 date >path0
-ln -s xyzzy path1
+if test_have_prereq SYMLINKS
+then
+       ln -s xyzzy path1
+else
+       date > path1
+fi
 mkdir path2 path3 path4
 date >path2/file2
 date >path2-junk
index e4f02a0968331f3a03a6eb1d1bbf2420152caa12..95671c205364a12bea02173b33d0d427d5c546fe 100755 (executable)
@@ -38,7 +38,12 @@ modified without reporting path9 and path10.
 . ./test-lib.sh
 
 date >path0
-ln -s xyzzy path1
+if test_have_prereq SYMLINKS
+then
+       ln -s xyzzy path1
+else
+       date > path1
+fi
 mkdir path2 path3
 date >path2/file2
 date >path3/file3
@@ -52,8 +57,14 @@ test_expect_success \
 
 rm -fr path? ;# leave path10 alone
 date >path2
-ln -s frotz path3
-ln -s nitfol path5
+if test_have_prereq SYMLINKS
+then
+       ln -s frotz path3
+       ln -s nitfol path5
+else
+       date > path3
+       date > path5
+fi
 mkdir path0 path1 path6
 date >path0/file0
 date >path1/file1
index 6e6a2542a22712006ae23874069c55943a3cba27..ee60d03fe8a582100e9df5511f6fea8900bcc543 100755 (executable)
@@ -22,9 +22,21 @@ test_expect_success \
     'setup' \
     'mkdir path2 path2/baz &&
      echo Hi >path0 &&
-     ln -s path0 path1 &&
+     if test_have_prereq SYMLINKS
+     then
+       ln -s path0 path1 &&
+       ln -s ../path1 path2/bazbo
+       make_expected () {
+               cat >expected
+       }
+     else
+       printf path0 > path1 &&
+       printf ../path1 > path2/bazbo
+       make_expected () {
+               sed -e "s/120000 /100644 /" >expected
+       }
+     fi &&
      echo Lo >path2/foo &&
-     ln -s ../path1 path2/bazbo &&
      echo Mi >path2/baz/b &&
      find path? \( -type f -o -type l \) -print |
      xargs git update-index --add &&
@@ -41,7 +53,7 @@ test_output () {
 test_expect_success \
     'ls-tree plain' \
     'git ls-tree $tree >current &&
-     cat >expected <<\EOF &&
+     make_expected <<\EOF &&
 100644 blob X  path0
 120000 blob X  path1
 040000 tree X  path2
@@ -51,7 +63,7 @@ EOF
 test_expect_success \
     'ls-tree recursive' \
     'git ls-tree -r $tree >current &&
-     cat >expected <<\EOF &&
+     make_expected <<\EOF &&
 100644 blob X  path0
 120000 blob X  path1
 100644 blob X  path2/baz/b
@@ -63,7 +75,7 @@ EOF
 test_expect_success \
     'ls-tree recursive with -t' \
     'git ls-tree -r -t $tree >current &&
-     cat >expected <<\EOF &&
+     make_expected <<\EOF &&
 100644 blob X  path0
 120000 blob X  path1
 040000 tree X  path2
@@ -77,7 +89,7 @@ EOF
 test_expect_success \
     'ls-tree recursive with -d' \
     'git ls-tree -r -d $tree >current &&
-     cat >expected <<\EOF &&
+     make_expected <<\EOF &&
 040000 tree X  path2
 040000 tree X  path2/baz
 EOF
@@ -86,7 +98,7 @@ EOF
 test_expect_success \
     'ls-tree filtered with path' \
     'git ls-tree $tree path >current &&
-     cat >expected <<\EOF &&
+     make_expected <<\EOF &&
 EOF
      test_output'
 
@@ -96,7 +108,7 @@ EOF
 test_expect_success \
     'ls-tree filtered with path1 path0' \
     'git ls-tree $tree path1 path0 >current &&
-     cat >expected <<\EOF &&
+     make_expected <<\EOF &&
 100644 blob X  path0
 120000 blob X  path1
 EOF
@@ -105,7 +117,7 @@ EOF
 test_expect_success \
     'ls-tree filtered with path0/' \
     'git ls-tree $tree path0/ >current &&
-     cat >expected <<\EOF &&
+     make_expected <<\EOF &&
 EOF
      test_output'
 
@@ -114,7 +126,7 @@ EOF
 test_expect_success \
     'ls-tree filtered with path2' \
     'git ls-tree $tree path2 >current &&
-     cat >expected <<\EOF &&
+     make_expected <<\EOF &&
 040000 tree X  path2
 EOF
      test_output'
@@ -123,7 +135,7 @@ EOF
 test_expect_success \
     'ls-tree filtered with path2/' \
     'git ls-tree $tree path2/ >current &&
-     cat >expected <<\EOF &&
+     make_expected <<\EOF &&
 040000 tree X  path2/baz
 120000 blob X  path2/bazbo
 100644 blob X  path2/foo
@@ -135,7 +147,7 @@ EOF
 test_expect_success \
     'ls-tree filtered with path2/baz' \
     'git ls-tree $tree path2/baz >current &&
-     cat >expected <<\EOF &&
+     make_expected <<\EOF &&
 040000 tree X  path2/baz
 EOF
      test_output'
@@ -143,14 +155,14 @@ EOF
 test_expect_success \
     'ls-tree filtered with path2/bak' \
     'git ls-tree $tree path2/bak >current &&
-     cat >expected <<\EOF &&
+     make_expected <<\EOF &&
 EOF
      test_output'
 
 test_expect_success \
     'ls-tree -t filtered with path2/bak' \
     'git ls-tree -t $tree path2/bak >current &&
-     cat >expected <<\EOF &&
+     make_expected <<\EOF &&
 040000 tree X  path2
 EOF
      test_output'
index 61a2010f5b0e24a50c6cddda9a17bad67f3214b8..d59a9b4aef5fc53e42ec95a3b96a18fb67aa82cb 100755 (executable)
@@ -121,7 +121,7 @@ test_expect_success 'renaming a symref is not allowed' \
        ! test -f .git/refs/heads/master3
 '
 
-test_expect_success \
+test_expect_success SYMLINKS \
     'git branch -m u v should fail when the reflog for u is a symlink' '
      git branch -l u &&
      mv .git/logs/refs/heads/u real-u &&
@@ -195,7 +195,7 @@ test_expect_success 'test deleting branch deletes branch config' \
 test_expect_success 'test deleting branch without config' \
     'git branch my7 s &&
      sha1=$(git rev-parse my7 | cut -c 1-7) &&
-     test "$(git branch -d my7 2>&1)" = "Deleted branch my7 ($sha1)."'
+     test "$(git branch -d my7 2>&1)" = "Deleted branch my7 (was $sha1)."'
 
 test_expect_success 'test --track without .fetch entries' \
     'git branch --track my8 &&
index 2aefbcf47137f9be5cff8786123ce1252656abc6..76b1bb45456a18a8c1c33256695396cc2b65a3a9 100755 (executable)
@@ -12,31 +12,37 @@ test_expect_success \
     'Initialize test directory' \
     "touch -- foo bar baz 'space embedded' -q &&
      git add -- foo bar baz 'space embedded' -q &&
-     git commit -m 'add normal files' &&
-     test_tabs=y &&
-     if touch -- 'tab  embedded' 'newline
-embedded'
-     then
+     git commit -m 'add normal files'"
+
+if touch -- 'tab       embedded' 'newline
+embedded' 2>/dev/null
+then
+       test_set_prereq FUNNYNAMES
+else
+       say 'Your filesystem does not allow tabs in filenames.'
+fi
+
+test_expect_success FUNNYNAMES 'add files with funny names' "
      git add -- 'tab   embedded' 'newline
 embedded' &&
      git commit -m 'add files with tabs and newlines'
-     else
-         test_tabs=n
-     fi"
-
-test "$test_tabs" = n && say 'Your filesystem does not allow tabs in filenames.'
+"
 
+# Determine rm behavior
 # Later we will try removing an unremovable path to make sure
 # git rm barfs, but if the test is run as root that cannot be
 # arranged.
-test_expect_success \
-    'Determine rm behavior' \
-    ': >test-file
-     chmod a-w .
-     rm -f test-file
-     test -f test-file && test_failed_remove=y
-     chmod 775 .
-     rm -f test-file'
+: >test-file
+chmod a-w .
+rm -f test-file 2>/dev/null
+if test -f test-file
+then
+       test_set_prereq RO_DIR
+else
+       say 'skipping removal failure test (perhaps running as root?)'
+fi
+chmod 775 .
+rm -f test-file
 
 test_expect_success \
     'Pre-check that foo exists and is in index before git rm foo' \
@@ -101,20 +107,16 @@ test_expect_success \
     'Test that "git rm -- -q" succeeds (remove a file that looks like an option)' \
     'git rm -- -q'
 
-test "$test_tabs" = y && test_expect_success \
+test_expect_success FUNNYNAMES \
     "Test that \"git rm -f\" succeeds with embedded space, tab, or newline characters." \
     "git rm -f 'space embedded' 'tab   embedded' 'newline
 embedded'"
 
-if test "$test_failed_remove" = y; then
-chmod a-w .
-test_expect_success \
-    'Test that "git rm -f" fails if its rm fails' \
-    'test_must_fail git rm -f baz'
-chmod 775 .
-else
-    say 'skipping removal failure test (perhaps running as root?)'
-fi
+test_expect_success RO_DIR 'Test that "git rm -f" fails if its rm fails' '
+       chmod a-w . &&
+       test_must_fail git rm -f baz &&
+       chmod 775 .
+'
 
 test_expect_success \
     'When the rm in "git rm -f" fails, it should not remove the file from the index' \
index 9f6454d2ffa22ef8a207b1a4e5e2ba156e84cdb9..050de42ef4148a730c30520ccaad5e9871e536bd 100755 (executable)
@@ -30,7 +30,7 @@ test_expect_success \
         *) echo fail; git ls-files --stage xfoo1; (exit 1);;
         esac'
 
-test_expect_success 'git add: filemode=0 should not get confused by symlink' '
+test_expect_success SYMLINKS 'git add: filemode=0 should not get confused by symlink' '
        rm -f xfoo1 &&
        ln -s foo xfoo1 &&
        git add xfoo1 &&
@@ -51,7 +51,7 @@ test_expect_success \
         *) echo fail; git ls-files --stage xfoo2; (exit 1);;
         esac'
 
-test_expect_success 'git add: filemode=0 should not get confused by symlink' '
+test_expect_success SYMLINKS 'git add: filemode=0 should not get confused by symlink' '
        rm -f xfoo2 &&
        ln -s foo xfoo2 &&
        git update-index --add xfoo2 &&
@@ -61,7 +61,7 @@ test_expect_success 'git add: filemode=0 should not get confused by symlink' '
        esac
 '
 
-test_expect_success \
+test_expect_success SYMLINKS \
        'git update-index --add: Test that executable bit is not used...' \
        'git config core.filemode 0 &&
         ln -s xfoo2 xfoo3 &&
@@ -179,7 +179,7 @@ test_expect_success 'git add --refresh' '
        test -z "`git diff-index HEAD -- foo`"
 '
 
-test_expect_success 'git add should fail atomically upon an unreadable file' '
+test_expect_success POSIXPERM 'git add should fail atomically upon an unreadable file' '
        git reset --hard &&
        date >foo1 &&
        date >foo2 &&
@@ -190,7 +190,7 @@ test_expect_success 'git add should fail atomically upon an unreadable file' '
 
 rm -f foo2
 
-test_expect_success 'git add --ignore-errors' '
+test_expect_success POSIXPERM 'git add --ignore-errors' '
        git reset --hard &&
        date >foo1 &&
        date >foo2 &&
@@ -201,7 +201,7 @@ test_expect_success 'git add --ignore-errors' '
 
 rm -f foo2
 
-test_expect_success 'git add (add.ignore-errors)' '
+test_expect_success POSIXPERM 'git add (add.ignore-errors)' '
        git config add.ignore-errors 1 &&
        git reset --hard &&
        date >foo1 &&
@@ -212,7 +212,7 @@ test_expect_success 'git add (add.ignore-errors)' '
 '
 rm -f foo2
 
-test_expect_success 'git add (add.ignore-errors = false)' '
+test_expect_success POSIXPERM 'git add (add.ignore-errors = false)' '
        git config add.ignore-errors 0 &&
        git reset --hard &&
        date >foo1 &&
@@ -222,7 +222,7 @@ test_expect_success 'git add (add.ignore-errors = false)' '
        ! ( git ls-files foo1 | grep foo1 )
 '
 
-test_expect_success 'git add '\''fo\[ou\]bar'\'' ignores foobar' '
+test_expect_success BSLASHPSPEC "git add 'fo\\[ou\\]bar' ignores foobar" '
        git reset --hard &&
        touch fo\[ou\]bar foobar &&
        git add '\''fo\[ou\]bar'\'' &&
index e95663d8e66d5b94e574a6b956625fccfd341a05..fe017839c467d10b82f5527bcd143a6c480c878a 100755 (executable)
@@ -135,10 +135,12 @@ test_expect_success 'real edit works' '
 
 if test "$(git config --bool core.filemode)" = false
 then
-    say 'skipping filemode tests (filesystem does not properly support modes)'
+       say 'skipping filemode tests (filesystem does not properly support modes)'
 else
+       test_set_prereq FILEMODE
+fi
 
-test_expect_success 'patch does not affect mode' '
+test_expect_success FILEMODE 'patch does not affect mode' '
        git reset --hard &&
        echo content >>file &&
        chmod +x file &&
@@ -147,7 +149,7 @@ test_expect_success 'patch does not affect mode' '
        git diff file | grep "new mode"
 '
 
-test_expect_success 'stage mode but not hunk' '
+test_expect_success FILEMODE 'stage mode but not hunk' '
        git reset --hard &&
        echo content >>file &&
        chmod +x file &&
@@ -156,7 +158,6 @@ test_expect_success 'stage mode but not hunk' '
        git diff          file | grep "+content"
 '
 
-fi
 # end of tests disabled when filemode is not usable
 
 test_done
index b35af9b42d318904bd12649562be309fd49977a3..a4da1196a93a00502c8945a14e3aafd628efda53 100755 (executable)
@@ -12,6 +12,12 @@ by an edit for them.
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/diff-lib.sh
 
+if ! test_have_prereq SYMLINKS
+then
+       say 'Symbolic links not supported, skipping tests.'
+       test_done
+fi
+
 test_expect_success \
     'prepare reference tree' \
     'echo xyzzy | tr -d '\\\\'012 >yomin &&
index 7e343a9cd130a73547ed1df9a4d9cd364e60bf9f..e19ca65885a1e49916f68eee4abbe65e98227c50 100755 (executable)
@@ -99,7 +99,7 @@ test_expect_success \
     'validate result of -B -M (#4)' \
     'compare_diff_raw expected current'
 
-test_expect_success \
+test_expect_success SYMLINKS \
     'make file0 into something completely different' \
     'rm -f file0 &&
      ln -s frotz file0 &&
@@ -114,7 +114,7 @@ cat >expected <<\EOF
 :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 M100  file1
 EOF
 
-test_expect_success \
+test_expect_success SYMLINKS \
     'validate result of -B (#5)' \
     'compare_diff_raw expected current'
 
@@ -129,7 +129,7 @@ cat >expected <<\EOF
 :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 R     file0   file1
 EOF
 
-test_expect_success \
+test_expect_success SYMLINKS \
     'validate result of -B -M (#6)' \
     'compare_diff_raw expected current'
 
@@ -144,7 +144,7 @@ cat >expected <<\EOF
 :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 M     file1
 EOF
 
-test_expect_success \
+test_expect_success SYMLINKS \
     'validate result of -M (#7)' \
     'compare_diff_raw expected current'
 
index 9055c8b318aa8cfa8b89fd19b20e94a7435ee155..d7e327cc5bc5984546032fb085fb581de5755e11 100755 (executable)
@@ -9,6 +9,12 @@ test_description='Test diff of symlinks.
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/diff-lib.sh
 
+if ! test_have_prereq SYMLINKS
+then
+       say 'Symbolic links not supported, skipping tests.'
+       test_done
+fi
+
 cat > expected << EOF
 diff --git a/frotz b/frotz
 new file mode 120000
index f187d15e328aa43f3d7a7b9030158e0128cc4812..11061ddd5bd122a1e180509c018e1b8bea42ddc3 100755 (executable)
@@ -128,6 +128,21 @@ test_expect_success 'additional command line cc' '
        grep "^ *S. E. Cipient <scipient@example.com>$" patch5
 '
 
+test_expect_success 'command line headers' '
+
+       git config --unset-all format.headers &&
+       git format-patch --add-header="Cc: R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^$/q" >patch6 &&
+       grep "^Cc: R. E. Cipient <rcipient@example.com>$" patch6
+'
+
+test_expect_success 'configuration headers and command line headers' '
+
+       git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" &&
+       git format-patch --add-header="Cc: S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^$/q" >patch7 &&
+       grep "^Cc: R. E. Cipient <rcipient@example.com>,$" patch7 &&
+       grep "^ *S. E. Cipient <scipient@example.com>$" patch7
+'
+
 test_expect_success 'multiple files' '
 
        rm -rf patches/ &&
index 281680d95afacb291d56d9d7f23efed1f3169e93..0720001281db6aeb5a3b6bb46cd6914ad7d78d33 100755 (executable)
@@ -136,4 +136,28 @@ test_expect_success 'GIT_EXTERNAL_DIFF with more than one changed files' '
        GIT_EXTERNAL_DIFF=echo git diff
 '
 
+echo "#!$SHELL_PATH" >fake-diff.sh
+cat >> fake-diff.sh <<\EOF
+cat $2 >> crlfed.txt
+EOF
+chmod a+x fake-diff.sh
+
+keep_only_cr () {
+       tr -dc '\015'
+}
+
+test_expect_success 'external diff with autocrlf = true' '
+       git config core.autocrlf true &&
+       GIT_EXTERNAL_DIFF=./fake-diff.sh git diff &&
+       test $(wc -l < crlfed.txt) = $(cat crlfed.txt | keep_only_cr | wc -c)
+'
+
+test_expect_success 'diff --cached' '
+       git add file &&
+       git update-index --assume-unchanged file &&
+       echo second >file &&
+       git diff --cached >actual &&
+       test_cmp ../t4020/diff.NUL actual
+'
+
 test_done
index 297ddb5a25b682412851aed70370771aa5a15976..9bdf6596d82878f709a375084095697124a97609 100755 (executable)
@@ -4,6 +4,12 @@ test_description='typechange rename detection'
 
 . ./test-lib.sh
 
+if ! test_have_prereq SYMLINKS
+then
+       say 'Symbolic links not supported, skipping tests.'
+       test_done
+fi
+
 test_expect_success setup '
 
        rm -f foo bar &&
index d42abff1ad59343fa1c84bded9a82c3212370da0..1597965241c3566aa3a14e986fd5a630fb348479 100755 (executable)
@@ -31,14 +31,16 @@ test_expect_success setup \
 test_expect_success apply \
     'git apply --index --stat --summary --apply test-patch'
 
-if [ "$(git config --get core.filemode)" = false ]
+if test "$(git config --bool core.filemode)" = false
 then
        say 'filemode disabled on the filesystem'
 else
-       test_expect_success validate \
-           'test -f bar && ls -l bar | grep "^-..x......"'
+       test_set_prereq FILEMODE
 fi
 
+test_expect_success FILEMODE validate \
+           'test -f bar && ls -l bar | grep "^-..x......"'
+
 test_expect_success 'apply reverse' \
     'git apply -R --index --stat --summary --apply test-patch &&
      test "$(cat foo)" = "This is foo"'
index 0f185caa44f3a9d048a2c058d963a1e86e9984fd..99ec13dd531c71299681acc3eb678b490ff68707 100755 (executable)
@@ -9,6 +9,12 @@ test_description='git apply should not get confused with type changes.
 
 . ./test-lib.sh
 
+if ! test_have_prereq SYMLINKS
+then
+       say 'Symbolic links not supported, skipping tests.'
+       test_done
+fi
+
 test_expect_success 'setup repository and commits' '
        echo "hello world" > foo &&
        echo "hi planet" > bar &&
index 9ace578f17a07aafc050ccaf935aef8a4a3cab4e..b852e5898009bca0205c231033f8f72f48962b81 100755 (executable)
@@ -9,6 +9,12 @@ test_description='git apply symlinks and partial files
 
 . ./test-lib.sh
 
+if ! test_have_prereq SYMLINKS
+then
+       say 'Symbolic links not supported, skipping tests.'
+       test_done
+fi
+
 test_expect_success setup '
 
        ln -s path1/path2/path3/path4/path5 link1 &&
index 841773f75fc085d07836b39b3775f49bde5d8d19..0d3c1d5dd5c0f35f9cc44eab4fcba5ba2e36ddd7 100755 (executable)
@@ -3,6 +3,12 @@
 test_description='apply to deeper directory without getting fooled with symlink'
 . ./test-lib.sh
 
+if ! test_have_prereq SYMLINKS
+then
+       say 'Symbolic links not supported, skipping tests.'
+       test_done
+fi
+
 lecho () {
        for l_
        do
index adfcbb5a3b9a6ec7e77f45141c2753cb79ed3763..fc7af0493102f12438d59ac5ed6e3e96eda8c841 100755 (executable)
@@ -4,6 +4,13 @@ test_description='applying patch with mode bits'
 
 . ./test-lib.sh
 
+if test "$(git config --bool core.filemode)" = false
+then
+       say 'filemode disabled on the filesystem'
+else
+       test_set_prereq FILEMODE
+fi
+
 test_expect_success setup '
        echo original >file &&
        git add file &&
@@ -16,14 +23,14 @@ test_expect_success setup '
        git diff --stat -p >patch-1.txt
 '
 
-test_expect_success 'same mode (no index)' '
+test_expect_success FILEMODE 'same mode (no index)' '
        git reset --hard &&
        chmod +x file &&
        git apply patch-0.txt &&
        test -x file
 '
 
-test_expect_success 'same mode (with index)' '
+test_expect_success FILEMODE 'same mode (with index)' '
        git reset --hard &&
        chmod +x file &&
        git add file &&
@@ -32,7 +39,7 @@ test_expect_success 'same mode (with index)' '
        git diff --exit-code
 '
 
-test_expect_success 'same mode (index only)' '
+test_expect_success FILEMODE 'same mode (index only)' '
        git reset --hard &&
        chmod +x file &&
        git add file &&
@@ -40,20 +47,20 @@ test_expect_success 'same mode (index only)' '
        git ls-files -s file | grep "^100755"
 '
 
-test_expect_success 'mode update (no index)' '
+test_expect_success FILEMODE 'mode update (no index)' '
        git reset --hard &&
        git apply patch-1.txt &&
        test -x file
 '
 
-test_expect_success 'mode update (with index)' '
+test_expect_success FILEMODE 'mode update (with index)' '
        git reset --hard &&
        git apply --index patch-1.txt &&
        test -x file &&
        git diff --exit-code
 '
 
-test_expect_success 'mode update (index only)' '
+test_expect_success FILEMODE 'mode update (index only)' '
        git reset --hard &&
        git apply --cached patch-1.txt &&
        git ls-files -s file | grep "^100755"
index 7a84ab61d0de86798d84eaa9e1768688f6b5ad77..7641e0dd46cc4f33231817664843787c90a01802 100755 (executable)
@@ -37,7 +37,11 @@ test_expect_success \
      cp /bin/sh a/bin &&
      printf "A\$Format:%s\$O" "$SUBSTFORMAT" >a/substfile1 &&
      printf "A not substituted O" >a/substfile2 &&
-     ln -s a a/l1 &&
+     if test_have_prereq SYMLINKS; then
+       ln -s a a/l1
+     else
+       printf %s a > a/l1
+     fi &&
      (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) &&
@@ -183,20 +187,20 @@ test_expect_success 'git archive --format=zip with --output' \
 $UNZIP -v >/dev/null 2>&1
 if [ $? -eq 127 ]; then
        say "Skipping ZIP tests, because unzip was not found"
-       test_done
-       exit
+else
+       test_set_prereq UNZIP
 fi
 
-test_expect_success \
+test_expect_success UNZIP \
     'extract ZIP archive' \
     '(mkdir d && cd d && $UNZIP ../d.zip)'
 
-test_expect_success \
+test_expect_success UNZIP \
     'validate filenames' \
     '(cd d/a && find .) | sort >d.lst &&
      test_cmp a.lst d.lst'
 
-test_expect_success \
+test_expect_success UNZIP \
     'validate file contents' \
     'diff -r a d/a'
 
@@ -204,16 +208,16 @@ test_expect_success \
     'git archive --format=zip with prefix' \
     'git archive --format=zip --prefix=prefix/ HEAD >e.zip'
 
-test_expect_success \
+test_expect_success UNZIP \
     'extract ZIP archive with prefix' \
     '(mkdir e && cd e && $UNZIP ../e.zip)'
 
-test_expect_success \
+test_expect_success UNZIP \
     'validate filenames with prefix' \
     '(cd e/prefix/a && find .) | sort >e.lst &&
      test_cmp a.lst e.lst'
 
-test_expect_success \
+test_expect_success UNZIP \
     'validate file contents with prefix' \
     'diff -r a e/prefix/a'
 
index 77982cdeacff246580993f03fedbc6dea4d25f0d..4360e77d317bfdaf7b40795859b4a023a5b89c13 100755 (executable)
@@ -69,32 +69,27 @@ test_expect_success \
     'index v2: force some 64-bit offsets with pack-objects' \
     'pack3=$(git pack-objects --index-version=2,0x40000 test-3 <obj-list)'
 
-have_64bits=
 if msg=$(git verify-pack -v "test-3-${pack3}.pack" 2>&1) ||
        ! (echo "$msg" | grep "pack too large .* off_t")
 then
-       have_64bits=t
+       test_set_prereq OFF64_T
 else
        say "skipping tests concerning 64-bit offsets"
 fi
 
-test "$have_64bits" &&
-test_expect_success \
+test_expect_success OFF64_T \
     'index v2: verify a pack with some 64-bit offsets' \
     'git verify-pack -v "test-3-${pack3}.pack"'
 
-test "$have_64bits" &&
-test_expect_success \
+test_expect_success OFF64_T \
     '64-bit offsets: should be different from previous index v2 results' \
     '! cmp "test-2-${pack2}.idx" "test-3-${pack3}.idx"'
 
-test "$have_64bits" &&
-test_expect_success \
+test_expect_success OFF64_T \
     'index v2: force some 64-bit offsets with index-pack' \
     'git index-pack --index-version=2,0x40000 -o 3.idx "test-1-${pack1}.pack"'
 
-test "$have_64bits" &&
-test_expect_success \
+test_expect_success OFF64_T \
     '64-bit offsets: index-pack result should match pack-objects one' \
     'cmp "test-3-${pack3}.idx" "3.idx"'
 
index 4074e23ffa2c7a93fdbd4a367e273118224b9038..d5db75d826c8584e1d7f0f5ef298021fecd6f055 100755 (executable)
@@ -4,6 +4,12 @@ test_description='test automatic tag following'
 
 . ./test-lib.sh
 
+case $(uname -s) in
+*MINGW*)
+       say "GIT_DEBUG_SEND_PACK not supported - skipping tests"
+       test_done
+esac
+
 # End state of the repository:
 #
 #         T - tag1          S - tag2
index 5672b51e2ea8db0e080e95315b292c91480a0000..86bbd7d024ff6b1ee775ec737c550d54f9371ad7 100755 (executable)
@@ -4,6 +4,12 @@ test_description='pulling from symlinked subdir'
 
 . ./test-lib.sh
 
+if ! test_have_prereq SYMLINKS
+then
+       say 'Symbolic links not supported, skipping tests.'
+       test_done
+fi
+
 # The scenario we are building:
 #
 #   trash\ directory/
index c46592f03de2adfbb04f81ad2167e33a161d6d1b..5fe479e1c2362ba05d059805d412b605aa7a83aa 100755 (executable)
@@ -17,7 +17,6 @@ if git http-push > /dev/null 2>&1 || [ $? -eq 128 ]
 then
        say "skipping test, USE_CURL_MULTI is not defined"
        test_done
-       exit
 fi
 
 . "$TEST_DIRECTORY"/lib-httpd.sh
index 41c6860be239a2abbab8b66ad8d4909b8913a9cc..8a3304fb0b5901fb02435d3b77c3d049404f4e25 100755 (executable)
@@ -3,6 +3,11 @@
 test_description='merge-recursive: handle file mode'
 . ./test-lib.sh
 
+if ! test "$(git config --bool core.filemode)" = false
+then
+       test_set_prereq FILEMODE
+fi
+
 test_expect_success 'mode change in one branch: keep changed version' '
        : >file1 &&
        git add file1 &&
@@ -16,6 +21,10 @@ test_expect_success 'mode change in one branch: keep changed version' '
        git commit -m b1 &&
        git checkout a1 &&
        git merge-recursive master -- a1 b1 &&
+       git ls-files -s file1 | grep ^100755
+'
+
+test_expect_success FILEMODE 'verify executable bit on file' '
        test -x file1
 '
 
@@ -41,6 +50,10 @@ test_expect_success 'mode change in both branches: expect conflict' '
                echo "100644 $H 3       file2"
        ) >expect &&
        test_cmp actual expect &&
+       git ls-files -s file2 | grep ^100755
+'
+
+test_expect_success FILEMODE 'verify executable bit on file' '
        test -x file2
 '
 
index 8f5a06f7dd8383722022eb7a8abd0ff9bafa6f45..2049ab6cf844da233837b58857cfde8a2d563252 100755 (executable)
@@ -83,13 +83,13 @@ test_expect_success 'merge-msg test #1' '
 '
 
 cat >expected <<EOF
-Merge branch 'left' of $TEST_DIRECTORY/$test
+Merge branch 'left' of $(pwd)
 EOF
 
 test_expect_success 'merge-msg test #2' '
 
        git checkout master &&
-       git fetch "$TEST_DIRECTORY/$test" left &&
+       git fetch "$(pwd)" left &&
 
        git fmt-merge-msg <.git/FETCH_HEAD >actual &&
        test_cmp expected actual
index 8fb3a56838dd476b9b0923f835ce70bd95499f2b..10b8f8c44befdb4eb00b3959f8b29cbebb7a22e1 100755 (executable)
@@ -206,7 +206,7 @@ test_expect_success 'git mv should not change sha1 of moved cache entry' '
 
 rm -f dirty dirty2
 
-test_expect_success 'git mv should overwrite symlink to a file' '
+test_expect_success SYMLINKS 'git mv should overwrite symlink to a file' '
 
        rm -fr .git &&
        git init &&
@@ -225,7 +225,7 @@ test_expect_success 'git mv should overwrite symlink to a file' '
 
 rm -f moved symlink
 
-test_expect_success 'git mv should overwrite file with a symlink' '
+test_expect_success SYMLINKS 'git mv should overwrite file with a symlink' '
 
        rm -fr .git &&
        git init &&
index 1c27ffb45effdafaace54a29c3ce63f07d6899e6..73dbc4360b58c95ae135577031fb8e60b3f395f7 100755 (executable)
@@ -581,28 +581,38 @@ test_expect_success \
 '
 
 # subsequent tests require gpg; check if it is available
-gpg --version >/dev/null
+gpg --version >/dev/null 2>/dev/null
 if [ $? -eq 127 ]; then
        say "gpg not found - skipping tag signing and verification tests"
-       test_done
-       exit
+else
+       # As said here: http://www.gnupg.org/documentation/faqs.html#q6.19
+       # the gpg version 1.0.6 didn't parse trust packets correctly, so for
+       # that version, creation of signed tags using the generated key fails.
+       case "$(gpg --version)" in
+       'gpg (GnuPG) 1.0.6'*)
+               say "Skipping signed tag tests, because a bug in 1.0.6 version"
+               ;;
+       *)
+               test_set_prereq GPG
+               ;;
+       esac
 fi
 
 # trying to verify annotated non-signed tags:
 
-test_expect_success \
+test_expect_success GPG \
        'trying to verify an annotated non-signed tag should fail' '
        tag_exists annotated-tag &&
        test_must_fail git tag -v annotated-tag
 '
 
-test_expect_success \
+test_expect_success GPG \
        'trying to verify a file-annotated non-signed tag should fail' '
        tag_exists file-annotated-tag &&
        test_must_fail git tag -v file-annotated-tag
 '
 
-test_expect_success \
+test_expect_success GPG \
        'trying to verify two annotated non-signed tags should fail' '
        tag_exists annotated-tag file-annotated-tag &&
        test_must_fail git tag -v annotated-tag file-annotated-tag
@@ -610,17 +620,6 @@ test_expect_success \
 
 # creating and verifying signed tags:
 
-# As said here: http://www.gnupg.org/documentation/faqs.html#q6.19
-# the gpg version 1.0.6 didn't parse trust packets correctly, so for
-# that version, creation of signed tags using the generated key fails.
-case "$(gpg --version)" in
-'gpg (GnuPG) 1.0.6'*)
-       say "Skipping signed tag tests, because a bug in 1.0.6 version"
-       test_done
-       exit
-       ;;
-esac
-
 # key generation info: gpg --homedir t/t7004 --gen-key
 # Type DSA and Elgamal, size 2048 bits, no expiration date.
 # Name and email: C O Mitter <committer@example.com>
@@ -634,7 +633,7 @@ export GNUPGHOME
 get_tag_header signed-tag $commit commit $time >expect
 echo 'A signed tag message' >>expect
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success 'creating a signed tag with -m message should succeed' '
+test_expect_success GPG 'creating a signed tag with -m message should succeed' '
        git tag -s -m "A signed tag message" signed-tag &&
        get_tag_msg signed-tag >actual &&
        test_cmp expect actual
@@ -643,7 +642,7 @@ test_expect_success 'creating a signed tag with -m message should succeed' '
 get_tag_header u-signed-tag $commit commit $time >expect
 echo 'Another message' >>expect
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success 'sign with a given key id' '
+test_expect_success GPG 'sign with a given key id' '
 
        git tag -u committer@example.com -m "Another message" u-signed-tag &&
        get_tag_msg u-signed-tag >actual &&
@@ -651,14 +650,14 @@ test_expect_success 'sign with a given key id' '
 
 '
 
-test_expect_success 'sign with an unknown id (1)' '
+test_expect_success GPG 'sign with an unknown id (1)' '
 
        test_must_fail git tag -u author@example.com \
                -m "Another message" o-signed-tag
 
 '
 
-test_expect_success 'sign with an unknown id (2)' '
+test_expect_success GPG 'sign with an unknown id (2)' '
 
        test_must_fail git tag -u DEADBEEF -m "Another message" o-signed-tag
 
@@ -675,7 +674,7 @@ chmod +x fakeeditor
 get_tag_header implied-sign $commit commit $time >expect
 ./fakeeditor >>expect
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success '-u implies signed tag' '
+test_expect_success GPG '-u implies signed tag' '
        GIT_EDITOR=./fakeeditor git tag -u CDDE430D implied-sign &&
        get_tag_msg implied-sign >actual &&
        test_cmp expect actual
@@ -688,7 +687,7 @@ EOF
 get_tag_header file-signed-tag $commit commit $time >expect
 cat sigmsgfile >>expect
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
        'creating a signed tag with -F messagefile should succeed' '
        git tag -s -F sigmsgfile file-signed-tag &&
        get_tag_msg file-signed-tag >actual &&
@@ -702,7 +701,7 @@ EOF
 get_tag_header stdin-signed-tag $commit commit $time >expect
 cat siginputmsg >>expect
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success 'creating a signed tag with -F - should succeed' '
+test_expect_success GPG 'creating a signed tag with -F - should succeed' '
        git tag -s -F - stdin-signed-tag <siginputmsg &&
        get_tag_msg stdin-signed-tag >actual &&
        test_cmp expect actual
@@ -711,13 +710,13 @@ test_expect_success 'creating a signed tag with -F - should succeed' '
 get_tag_header implied-annotate $commit commit $time >expect
 ./fakeeditor >>expect
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success '-s implies annotated tag' '
+test_expect_success GPG '-s implies annotated tag' '
        GIT_EDITOR=./fakeeditor git tag -s implied-annotate &&
        get_tag_msg implied-annotate >actual &&
        test_cmp expect actual
 '
 
-test_expect_success \
+test_expect_success GPG \
        'trying to create a signed tag with non-existing -F file should fail' '
        ! test -f nonexistingfile &&
        ! tag_exists nosigtag &&
@@ -725,13 +724,13 @@ test_expect_success \
        ! tag_exists nosigtag
 '
 
-test_expect_success 'verifying a signed tag should succeed' \
+test_expect_success GPG 'verifying a signed tag should succeed' \
        'git tag -v signed-tag'
 
-test_expect_success 'verifying two signed tags in one command should succeed' \
+test_expect_success GPG 'verifying two signed tags in one command should succeed' \
        'git tag -v signed-tag file-signed-tag'
 
-test_expect_success \
+test_expect_success GPG \
        'verifying many signed and non-signed tags should fail' '
        test_must_fail git tag -v signed-tag annotated-tag &&
        test_must_fail git tag -v file-annotated-tag file-signed-tag &&
@@ -740,7 +739,7 @@ test_expect_success \
        test_must_fail git tag -v signed-tag annotated-tag file-signed-tag
 '
 
-test_expect_success 'verifying a forged tag should fail' '
+test_expect_success GPG 'verifying a forged tag should fail' '
        forged=$(git cat-file tag signed-tag |
                sed -e "s/signed-tag/forged-tag/" |
                git mktag) &&
@@ -752,7 +751,7 @@ test_expect_success 'verifying a forged tag should fail' '
 
 get_tag_header empty-signed-tag $commit commit $time >expect
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
        'creating a signed tag with an empty -m message should succeed' '
        git tag -s -m "" empty-signed-tag &&
        get_tag_msg empty-signed-tag >actual &&
@@ -763,7 +762,7 @@ test_expect_success \
 >sigemptyfile
 get_tag_header emptyfile-signed-tag $commit commit $time >expect
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
        'creating a signed tag with an empty -F messagefile should succeed' '
        git tag -s -F sigemptyfile emptyfile-signed-tag &&
        get_tag_msg emptyfile-signed-tag >actual &&
@@ -786,7 +785,7 @@ Trailing spaces
 Trailing blank lines
 EOF
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
        'extra blanks in the message for a signed tag should be removed' '
        git tag -s -F sigblanksfile blanks-signed-tag &&
        get_tag_msg blanks-signed-tag >actual &&
@@ -796,7 +795,7 @@ test_expect_success \
 
 get_tag_header blank-signed-tag $commit commit $time >expect
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
        'creating a signed tag with a blank -m message should succeed' '
        git tag -s -m "     " blank-signed-tag &&
        get_tag_msg blank-signed-tag >actual &&
@@ -809,7 +808,7 @@ echo ''      >>sigblankfile
 echo '  '    >>sigblankfile
 get_tag_header blankfile-signed-tag $commit commit $time >expect
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
        'creating a signed tag with blank -F file with spaces should succeed' '
        git tag -s -F sigblankfile blankfile-signed-tag &&
        get_tag_msg blankfile-signed-tag >actual &&
@@ -820,7 +819,7 @@ test_expect_success \
 printf '      ' >sigblanknonlfile
 get_tag_header blanknonlfile-signed-tag $commit commit $time >expect
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
        'creating a signed tag with spaces and no newline should succeed' '
        git tag -s -F sigblanknonlfile blanknonlfile-signed-tag &&
        get_tag_msg blanknonlfile-signed-tag >actual &&
@@ -857,7 +856,7 @@ Another line.
 Last line.
 EOF
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
        'creating a signed tag with a -F file with #comments should succeed' '
        git tag -s -F sigcommentsfile comments-signed-tag &&
        get_tag_msg comments-signed-tag >actual &&
@@ -867,7 +866,7 @@ test_expect_success \
 
 get_tag_header comment-signed-tag $commit commit $time >expect
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
        'creating a signed tag with #commented -m message should succeed' '
        git tag -s -m "#comment" comment-signed-tag &&
        get_tag_msg comment-signed-tag >actual &&
@@ -880,7 +879,7 @@ echo ''         >>sigcommentfile
 echo '####'     >>sigcommentfile
 get_tag_header commentfile-signed-tag $commit commit $time >expect
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
        'creating a signed tag with #commented -F messagefile should succeed' '
        git tag -s -F sigcommentfile commentfile-signed-tag &&
        get_tag_msg commentfile-signed-tag >actual &&
@@ -891,7 +890,7 @@ test_expect_success \
 printf '#comment' >sigcommentnonlfile
 get_tag_header commentnonlfile-signed-tag $commit commit $time >expect
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
        'creating a signed tag with a #comment and no newline should succeed' '
        git tag -s -F sigcommentnonlfile commentnonlfile-signed-tag &&
        get_tag_msg commentnonlfile-signed-tag >actual &&
@@ -901,7 +900,7 @@ test_expect_success \
 
 # listing messages for signed tags:
 
-test_expect_success \
+test_expect_success GPG \
        'listing the one-line message of a signed tag should succeed' '
        git tag -s -m "A message line signed" stag-one-line &&
 
@@ -926,7 +925,7 @@ test_expect_success \
        test_cmp expect actual
 '
 
-test_expect_success \
+test_expect_success GPG \
        'listing the zero-lines message of a signed tag should succeed' '
        git tag -s -m "" stag-zero-lines &&
 
@@ -954,7 +953,7 @@ test_expect_success \
 echo 'stag line one' >sigtagmsg
 echo 'stag line two' >>sigtagmsg
 echo 'stag line three' >>sigtagmsg
-test_expect_success \
+test_expect_success GPG \
        'listing many message lines of a signed tag should succeed' '
        git tag -s -F sigtagmsg stag-lines &&
 
@@ -999,12 +998,12 @@ test_expect_success \
 
 tree=$(git rev-parse HEAD^{tree})
 blob=$(git rev-parse HEAD:foo)
-tag=$(git rev-parse signed-tag)
+tag=$(git rev-parse signed-tag 2>/dev/null)
 
 get_tag_header tree-signed-tag $tree tree $time >expect
 echo "A message for a tree" >>expect
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
        'creating a signed tag pointing to a tree should succeed' '
        git tag -s -m "A message for a tree" tree-signed-tag HEAD^{tree} &&
        get_tag_msg tree-signed-tag >actual &&
@@ -1014,7 +1013,7 @@ test_expect_success \
 get_tag_header blob-signed-tag $blob blob $time >expect
 echo "A message for a blob" >>expect
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
        'creating a signed tag pointing to a blob should succeed' '
        git tag -s -m "A message for a blob" blob-signed-tag HEAD:foo &&
        get_tag_msg blob-signed-tag >actual &&
@@ -1024,7 +1023,7 @@ test_expect_success \
 get_tag_header tag-signed-tag $tag tag $time >expect
 echo "A message for another tag" >>expect
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
-test_expect_success \
+test_expect_success GPG \
        'creating a signed tag pointing to another tag should succeed' '
        git tag -s -m "A message for another tag" tag-signed-tag signed-tag &&
        get_tag_msg tag-signed-tag >actual &&
@@ -1033,7 +1032,7 @@ test_expect_success \
 
 # try to sign with bad user.signingkey
 git config user.signingkey BobTheMouse
-test_expect_success \
+test_expect_success GPG \
        'git tag -s fails if gpg is misconfigured' \
        'test_must_fail git tag -s -m tail tag-gpg-failure'
 git config --unset user.signingkey
@@ -1041,7 +1040,7 @@ git config --unset user.signingkey
 # try to verify without gpg:
 
 rm -rf gpghome
-test_expect_success \
+test_expect_success GPG \
        'verify signed tag fails when public key is not present' \
        'test_must_fail git tag -v signed-tag'
 
index 2f8404afbbc38e9bed17b1d3c9dde22ddcb2eaa2..b647957d75fa0d0ce4d88c7c3c7243f31af38b4a 100755 (executable)
@@ -7,6 +7,7 @@ test_description='GIT_EDITOR, core.editor, and stuff'
 for i in GIT_EDITOR core_editor EDITOR VISUAL vi
 do
        cat >e-$i.sh <<-EOF
+       #!$SHELL_PATH
        echo "Edited by $i" >"\$1"
        EOF
        chmod +x e-$i.sh
@@ -91,7 +92,6 @@ if ! echo 'echo space > "$1"' > "e space.sh"
 then
        say "Skipping; FS does not support spaces in filenames"
        test_done
-       exit
 fi
 
 test_expect_success 'editor with a space' '
index ad42c78d7c21497a6ebb4e9cef4efd6334f947da..56cd866019dcc871e5dea684f1d879fcf2c1b884 100755 (executable)
@@ -234,7 +234,7 @@ cat >.git/FAKE_EDITOR <<EOF
 # kill -TERM command added below.
 EOF
 
-test_expect_success 'a SIGTERM should break locks' '
+test_expect_success EXECKEEPSPID 'a SIGTERM should break locks' '
        echo >>negative &&
        ! "$SHELL_PATH" -c '\''
          echo kill -TERM $$ >> .git/FAKE_EDITOR
index b06909599564a1c8afa027b0f9c71ef6bb61d6e4..8528f64c8d1491fd3c279f030b6f8aee2050cdf7 100755 (executable)
@@ -69,7 +69,7 @@ test_expect_success '--no-verify with failing hook' '
 '
 
 chmod -x "$HOOK"
-test_expect_success 'with non-executable hook' '
+test_expect_success POSIXPERM 'with non-executable hook' '
 
        echo "content" >> file &&
        git add file &&
@@ -77,7 +77,7 @@ test_expect_success 'with non-executable hook' '
 
 '
 
-test_expect_success '--no-verify with non-executable hook' '
+test_expect_success POSIXPERM '--no-verify with non-executable hook' '
 
        echo "more content" >> file &&
        git add file &&
index 47680e6df41c2bc14f23514b010a8aefb3fedcd7..1f53ea8090355c9a351da1983388e1a49fd88ae3 100755 (executable)
@@ -136,7 +136,7 @@ test_expect_success '--no-verify with failing hook (editor)' '
 '
 
 chmod -x "$HOOK"
-test_expect_success 'with non-executable hook' '
+test_expect_success POSIXPERM 'with non-executable hook' '
 
        echo "content" >> file &&
        git add file &&
@@ -144,7 +144,7 @@ test_expect_success 'with non-executable hook' '
 
 '
 
-test_expect_success 'with non-executable hook (editor)' '
+test_expect_success POSIXPERM 'with non-executable hook (editor)' '
 
        echo "content again" >> file &&
        git add file &&
@@ -153,7 +153,7 @@ test_expect_success 'with non-executable hook (editor)' '
 
 '
 
-test_expect_success '--no-verify with non-executable hook' '
+test_expect_success POSIXPERM '--no-verify with non-executable hook' '
 
        echo "more content" >> file &&
        git add file &&
@@ -161,7 +161,7 @@ test_expect_success '--no-verify with non-executable hook' '
 
 '
 
-test_expect_success '--no-verify with non-executable hook (editor)' '
+test_expect_success POSIXPERM '--no-verify with non-executable hook (editor)' '
 
        echo "even more content" >> file &&
        git add file &&
index f5682d66db2832311774fb68b7264002dfeb091f..6b29bff782f5a46bb6970d70598fd3be82c679fa 100755 (executable)
@@ -88,5 +88,66 @@ test_expect_failure 'packed obs in alt ODB are repacked when local repo has pack
        done
 '
 
+test_expect_success 'packed obs in alternate ODB kept pack are repacked' '
+       # swap the .keep so the commit object is in the pack with .keep
+       for p in alt_objects/pack/*.pack
+       do
+               base_name=$(basename $p .pack)
+               if test -f alt_objects/pack/$base_name.keep
+               then
+                       rm alt_objects/pack/$base_name.keep
+               else
+                       touch alt_objects/pack/$base_name.keep
+               fi
+       done
+       git repack -a -d &&
+       myidx=$(ls -1 .git/objects/pack/*.idx) &&
+       test -f "$myidx" &&
+       for p in alt_objects/pack/*.idx; do
+               git verify-pack -v $p | sed -n -e "/^[0-9a-f]\{40\}/p"
+       done | while read sha1 rest; do
+               if ! ( git verify-pack -v $myidx | grep "^$sha1" ); then
+                       echo "Missing object in local pack: $sha1"
+                       return 1
+               fi
+       done
+'
+
+test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '
+       rm -f alt_objects/pack/*.keep &&
+       mv .git/objects/pack/* alt_objects/pack/ &&
+       csha1=$(git rev-parse HEAD^{commit}) &&
+       git reset --hard HEAD^ &&
+       sleep 1 &&
+       git reflog expire --expire=now --expire-unreachable=now --all &&
+       # The pack-objects call on the next line is equivalent to
+       # git repack -A -d without the call to prune-packed
+       git pack-objects --honor-pack-keep --non-empty --all --reflog \
+           --unpack-unreachable </dev/null pack &&
+       rm -f .git/objects/pack/* &&
+       mv pack-* .git/objects/pack/ &&
+       test 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |
+               egrep "^$csha1 " | sort | uniq | wc -l) &&
+       echo > .git/objects/info/alternates &&
+       test_must_fail git show $csha1
+'
+
+test_expect_success 'local packed unreachable obs that exist in alternate ODB are not loosened' '
+       echo `pwd`/alt_objects > .git/objects/info/alternates &&
+       echo "$csha1" | git pack-objects --non-empty --all --reflog pack &&
+       rm -f .git/objects/pack/* &&
+       mv pack-* .git/objects/pack/ &&
+       # The pack-objects call on the next line is equivalent to
+       # git repack -A -d without the call to prune-packed
+       git pack-objects --honor-pack-keep --non-empty --all --reflog \
+           --unpack-unreachable </dev/null pack &&
+       rm -f .git/objects/pack/* &&
+       mv pack-* .git/objects/pack/ &&
+       test 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |
+               egrep "^$csha1 " | sort | uniq | wc -l) &&
+       echo > .git/objects/info/alternates &&
+       test_must_fail git show $csha1
+'
+
 test_done
 
index e426c96fb7d0f72b2822d4379b7fa671a04ab733..3c90c4fc1c0ee798b5e37729d1a67018499f0a92 100755 (executable)
@@ -130,6 +130,19 @@ test_expect_success 'Show all headers' '
        test_cmp expected-show-all-headers actual-show-all-headers
 '
 
+test_expect_success 'Prompting works' '
+       clean_fake_sendmail &&
+       (echo "Example <from@example.com>"
+        echo "to@example.com"
+        echo ""
+       ) | GIT_SEND_EMAIL_NOTTY=1 git send-email \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               $patches \
+               2>errors &&
+               grep "^From: Example <from@example.com>$" msgtxt1 &&
+               grep "^To: to@example.com$" msgtxt1
+'
+
 z8=zzzzzzzz
 z64=$z8$z8$z8$z8$z8$z8$z8$z8
 z512=$z64$z64$z64$z64$z64$z64$z64$z64
@@ -421,8 +434,8 @@ test_confirm () {
                --from="Example <nobody@example.com>" \
                --to=nobody@example.com \
                --smtp-server="$(pwd)/fake.sendmail" \
-               $@ \
-               $patches | grep "Send this email"
+               $@ $patches > stdout &&
+       grep "Send this email" stdout
 }
 
 test_expect_success '--confirm=always' '
@@ -444,8 +457,10 @@ test_expect_success '--confirm=compose' '
 test_expect_success 'confirm by default (due to cc)' '
        CONFIRM=$(git config --get sendemail.confirm) &&
        git config --unset sendemail.confirm &&
-       test_confirm &&
-       git config sendemail.confirm $CONFIRM
+       test_confirm
+       ret="$?"
+       git config sendemail.confirm ${CONFIRM:-never}
+       test $ret = "0"
 '
 
 test_expect_success 'confirm by default (due to --compose)' '
@@ -457,6 +472,65 @@ test_expect_success 'confirm by default (due to --compose)' '
        test $ret = "0"
 '
 
+test_expect_success 'confirm detects EOF (inform assumes y)' '
+       CONFIRM=$(git config --get sendemail.confirm) &&
+       git config --unset sendemail.confirm &&
+       rm -fr outdir &&
+       git format-patch -2 -o outdir &&
+       GIT_SEND_EMAIL_NOTTY=1 \
+               git send-email \
+                       --from="Example <nobody@example.com>" \
+                       --to=nobody@example.com \
+                       --smtp-server="$(pwd)/fake.sendmail" \
+                       outdir/*.patch < /dev/null
+       ret="$?"
+       git config sendemail.confirm ${CONFIRM:-never}
+       test $ret = "0"
+'
+
+test_expect_success 'confirm detects EOF (auto causes failure)' '
+       CONFIRM=$(git config --get sendemail.confirm) &&
+       git config sendemail.confirm auto &&
+       GIT_SEND_EMAIL_NOTTY=1 &&
+       export GIT_SEND_EMAIL_NOTTY &&
+               test_must_fail git send-email \
+                       --from="Example <nobody@example.com>" \
+                       --to=nobody@example.com \
+                       --smtp-server="$(pwd)/fake.sendmail" \
+                       $patches < /dev/null
+       ret="$?"
+       git config sendemail.confirm ${CONFIRM:-never}
+       test $ret = "0"
+'
+
+test_expect_success 'confirm doesnt loop forever' '
+       CONFIRM=$(git config --get sendemail.confirm) &&
+       git config sendemail.confirm auto &&
+       GIT_SEND_EMAIL_NOTTY=1 &&
+       export GIT_SEND_EMAIL_NOTTY &&
+               yes "bogus" | test_must_fail git send-email \
+                       --from="Example <nobody@example.com>" \
+                       --to=nobody@example.com \
+                       --smtp-server="$(pwd)/fake.sendmail" \
+                       $patches
+       ret="$?"
+       git config sendemail.confirm ${CONFIRM:-never}
+       test $ret = "0"
+'
+
+test_expect_success 'utf8 Cc is rfc2047 encoded' '
+       clean_fake_sendmail &&
+       rm -fr outdir &&
+       git format-patch -1 -o outdir --cc="àéìöú <utf8@example.com>" &&
+       git send-email \
+       --from="Example <nobody@example.com>" \
+       --to=nobody@example.com \
+       --smtp-server="$(pwd)/fake.sendmail" \
+       outdir/*.patch &&
+       grep "^Cc:" msgtxt1 |
+       grep "=?utf-8?q?=C3=A0=C3=A9=C3=AC=C3=B6=C3=BA?= <utf8@example.com>"
+'
+
 test_expect_success '--compose adds MIME for utf8 body' '
        clean_fake_sendmail &&
        (echo "#!$SHELL_PATH" &&
index bb921af56af2c9a559c843dd4c3b69993c34206c..4eee2e9fa6bacdc0d130a692f727885c5fa42e49 100755 (executable)
@@ -6,19 +6,19 @@
 test_description='git svn basic tests'
 GIT_SVN_LC_ALL=${LC_ALL:-$LANG}
 
+. ./lib-git-svn.sh
+
+say 'define NO_SVN_TESTS to skip git svn tests'
+
 case "$GIT_SVN_LC_ALL" in
 *.UTF-8)
-       have_utf8=t
+       test_set_prereq UTF8
        ;;
 *)
-       have_utf8=
+       say "UTF-8 locale not set, some tests skipped ($GIT_SVN_LC_ALL)"
        ;;
 esac
 
-. ./lib-git-svn.sh
-
-say 'define NO_SVN_TESTS to skip git svn tests'
-
 test_expect_success \
     'initialize git svn' '
        mkdir import &&
@@ -171,20 +171,15 @@ test_expect_success "$name" '
        test ! -L "$SVN_TREE"/exec-2.sh &&
        test_cmp help "$SVN_TREE"/exec-2.sh'
 
-if test "$have_utf8" = t
-then
-       name="commit with UTF-8 message: locale: $GIT_SVN_LC_ALL"
-       LC_ALL="$GIT_SVN_LC_ALL"
-       export LC_ALL
-       test_expect_success "$name" "
-               echo '# hello' >> exec-2.sh &&
-               git update-index exec-2.sh &&
-               git commit -m 'éï∏' &&
-               git svn set-tree HEAD"
-       unset LC_ALL
-else
-       say "UTF-8 locale not set, test skipped ($GIT_SVN_LC_ALL)"
-fi
+name="commit with UTF-8 message: locale: $GIT_SVN_LC_ALL"
+LC_ALL="$GIT_SVN_LC_ALL"
+export LC_ALL
+test_expect_success UTF8 "$name" "
+       echo '# hello' >> exec-2.sh &&
+       git update-index exec-2.sh &&
+       git commit -m 'éï∏' &&
+       git svn set-tree HEAD"
+unset LC_ALL
 
 name='test fetch functionality (svn => git) with alternate GIT_SVN_ID'
 GIT_SVN_ID=alt
@@ -197,7 +192,7 @@ test_expect_success "$name" \
 
 name='check imported tree checksums expected tree checksums'
 rm -f expected
-if test "$have_utf8" = t
+if test_have_prereq UTF8
 then
        echo tree bf522353586b1b883488f2bc73dab0d9f774b9a9 > expected
 fi
index 9c7b1ad18bca943e6c5b6e50f55d914ccadbfce8..3200ab38efa03076b81b94713e74205d740e38e8 100755 (executable)
@@ -70,24 +70,26 @@ do
 done
 
 if locale -a |grep -q en_US.utf8; then
-       test_expect_success 'ISO-8859-1 should match UTF-8 in svn' '
+       test_set_prereq UTF8
+else
+       say "UTF-8 locale not available, test skipped"
+fi
+
+test_expect_success UTF8 'ISO-8859-1 should match UTF-8 in svn' '
        (
                cd ISO-8859-1 &&
                compare_svn_head_with "$TEST_DIRECTORY"/t3900/1-UTF-8.txt
        )
-       '
+'
 
-       for H in EUCJP ISO-2022-JP
-       do
-               test_expect_success '$H should match UTF-8 in svn' '
+for H in EUCJP ISO-2022-JP
+do
+       test_expect_success UTF8 "$H should match UTF-8 in svn" '
                (
                        cd $H &&
                        compare_svn_head_with "$TEST_DIRECTORY"/t3900/2-UTF-8.txt
                )
-               '
-       done
-else
-       say "UTF-8 locale not available, test skipped"
-fi
+       '
+done
 
 test_done
index 8f35e294aa885e7afbb704186c9afe9467172570..9a24a65b64111b4540db28315fedd4efd3b19ae7 100755 (executable)
@@ -88,7 +88,7 @@ test_expect_success 'enable broken symlink workaround' \
 test_expect_success '"bar" is an empty file' 'test -f x/bar && ! test -s x/bar'
 test_expect_success 'get "bar" => symlink fix from svn' \
                '(cd x && git svn rebase)'
-test_expect_success '"bar" becomes a symlink' 'test -L x/bar'
+test_expect_success SYMLINKS '"bar" becomes a symlink' 'test -L x/bar'
 
 
 test_expect_success 'clone using git svn' 'git svn clone -r1 "$svnrepo" y'
index b8de59e493cbf0f0e85e60daf49fd4dc716244e1..6c4c90b03694d2ebe986897b744444fbc00b7125 100755 (executable)
@@ -85,7 +85,7 @@ EOF
 
 test_expect_success 'clone using git svn' 'git svn clone -r1 "$svnrepo" x'
 
-test_expect_success '"bar" is a symlink that points to "asdf"' '
+test_expect_success SYMLINKS '"bar" is a symlink that points to "asdf"' '
        test -L x/bar &&
        (cd x && test xasdf = x"`git cat-file blob HEAD:bar`")
 '
@@ -94,7 +94,7 @@ test_expect_success 'get "bar" => symlink fix from svn' '
        (cd x && git svn rebase)
 '
 
-test_expect_success '"bar" remains a proper symlink' '
+test_expect_success SYMLINKS '"bar" remains a proper symlink' '
        test -L x/bar &&
        (cd x && test xdoink = x"`git cat-file blob HEAD:bar`")
 '
index d28b71b8cf4bfefb987956be1d36203d69525677..36656923ac2dbf76a76173181b8244fcfa55edc2 100755 (executable)
@@ -11,7 +11,6 @@ if test $? -ne 1
 then
     say 'skipping git cvsexportcommit tests, cvs not found'
     test_done
-    exit
 fi
 
 CVSROOT=$(pwd)/cvsroot
@@ -225,11 +224,12 @@ test_expect_success \
       test_must_fail git cvsexportcommit -c $id
       )'
 
-case "$(git config --bool core.filemode)" in
-false)
-       ;;
-*)
-test_expect_success \
+if ! test "$(git config --bool core.filemode)" = false
+then
+       test_set_prereq FILEMODE
+fi
+
+test_expect_success FILEMODE \
      'Retain execute bit' \
      'mkdir G &&
       echo executeon >G/on &&
@@ -243,8 +243,6 @@ test_expect_success \
       test -x G/on &&
       ! test -x G/off
       )'
-       ;;
-esac
 
 test_expect_success '-w option should work with relative GIT_DIR' '
       mkdir W &&
index 86c376088ccd04d0b0cbb14424eef7a9b89b45d3..8da9ce54596416af6fc9779a5ac3f7131958aec8 100755 (executable)
@@ -8,6 +8,9 @@ test_description='git fast-export'
 
 test_expect_success 'setup' '
 
+       echo break it > file0 &&
+       git add file0 &&
+       test_tick &&
        echo Wohlauf > file &&
        git add file &&
        test_tick &&
@@ -57,8 +60,8 @@ test_expect_success 'fast-export master~2..master' '
                (cd new &&
                 git fast-import &&
                 test $MASTER != $(git rev-parse --verify refs/heads/partial) &&
-                git diff master..partial &&
-                git diff master^..partial^ &&
+                git diff --exit-code master partial &&
+                git diff --exit-code master^ partial^ &&
                 test_must_fail git rev-parse partial~2)
 
 '
@@ -259,4 +262,19 @@ test_expect_success 'cope with tagger-less tags' '
 
 '
 
+test_expect_success 'set-up a few more tags for tag export tests' '
+       git checkout -f master &&
+       HEAD_TREE=`git show -s --pretty=raw HEAD | grep tree | sed "s/tree //"` &&
+       git tag    tree_tag        -m "tagging a tree" $HEAD_TREE &&
+       git tag -a tree_tag-obj    -m "tagging a tree" $HEAD_TREE &&
+       git tag    tag-obj_tag     -m "tagging a tag" tree_tag-obj &&
+       git tag -a tag-obj_tag-obj -m "tagging a tag" tree_tag-obj
+'
+
+# NEEDSWORK: not just check return status, but validate the output
+test_expect_success 'tree_tag'        'git fast-export tree_tag'
+test_expect_success 'tree_tag-obj'    'git fast-export tree_tag-obj'
+test_expect_success 'tag-obj_tag'     'git fast-export tag-obj_tag'
+test_expect_success 'tag-obj_tag-obj' 'git fast-export tag-obj_tag-obj'
+
 test_done
index 466240cd415fe544ed55d991e176129e7f869b79..39185db6c962ee95caf35cc5ad9d26f228224f44 100755 (executable)
@@ -15,12 +15,10 @@ if test $? -ne 1
 then
     say 'skipping git-cvsserver tests, cvs not found'
     test_done
-    exit
 fi
 perl -e 'use DBI; use DBD::SQLite' >/dev/null 2>&1 || {
     say 'skipping git-cvsserver tests, Perl SQLite interface unavailable'
     test_done
-    exit
 }
 
 unset GIT_DIR GIT_CONFIG
index 888223013444999817a93082418fb60690a425e3..12e0e508226cb9197ad3f419387dfcfb3ab9e0d9 100755 (executable)
@@ -51,12 +51,10 @@ if test $? -ne 1
 then
     say 'skipping git-cvsserver tests, cvs not found'
     test_done
-    exit
 fi
 perl -e 'use DBI; use DBD::SQLite' >/dev/null 2>&1 || {
     say 'skipping git-cvsserver tests, Perl SQLite interface unavailable'
     test_done
-    exit
 }
 
 unset GIT_DIR GIT_CONFIG
index dce06bcc9733f010463692cc2f41400d5a518106..0bd332c4932c796f9bb3547d4a708cebbd9cfc2c 100755 (executable)
@@ -68,7 +68,6 @@ gitweb_run () {
 perl -MEncode -e 'decode_utf8("", Encode::FB_CROAK)' >/dev/null 2>&1 || {
     say 'skipping gitweb tests, perl version is too old'
     test_done
-    exit
 }
 
 gitweb_init
@@ -246,7 +245,7 @@ test_expect_success \
         gitweb_run "p=.git;a=commitdiff"'
 test_debug 'cat gitweb.log'
 
-test_expect_success \
+test_expect_success SYMLINKS \
        'commitdiff(0): file to symlink' \
        'rm renamed_file &&
         ln -s file renamed_file &&
@@ -308,7 +307,7 @@ test_debug 'cat gitweb.log'
 # ----------------------------------------------------------------------
 # commitdiff testing (taken from t4114-apply-typechange.sh)
 
-test_expect_success 'setup typechange commits' '
+test_expect_success SYMLINKS 'setup typechange commits' '
        echo "hello world" > foo &&
        echo "hi planet" > bar &&
        git update-index --add foo bar &&
@@ -418,7 +417,12 @@ test_expect_success \
         git mv 04-rename-from 04-rename-to &&
         echo "Changed" >> 04-rename-to &&
         test_chmod +x 05-mode-change &&
-        rm -f 06-file-or-symlink && ln -s 01-change 06-file-or-symlink &&
+        rm -f 06-file-or-symlink &&
+        if test_have_prereq SYMLINKS; then
+               ln -s 01-change 06-file-or-symlink
+        else
+               printf %s 01-change > 06-file-or-symlink
+        fi &&
         echo "Changed and have mode changed" > 07-change-mode-change   &&
         test_chmod +x 07-change-mode-change &&
         git commit -a -m "Large commit" &&
index d2379e7f62a4da76791e65dbc2c70f4dfe14ff3b..33eb51938dbf90f93d10c2cf1d0edfc788befece 100755 (executable)
@@ -14,7 +14,6 @@ if ! type cvs >/dev/null 2>&1
 then
        say 'skipping cvsimport tests, cvs not found'
        test_done
-       exit
 fi
 
 cvsps_version=`cvsps -h 2>&1 | sed -ne 's/cvsps version //p'`
@@ -24,12 +23,10 @@ case "$cvsps_version" in
 '')
        say 'skipping cvsimport tests, cvsps not found'
        test_done
-       exit
        ;;
 *)
        say 'skipping cvsimport tests, unsupported cvsps version'
        test_done
-       exit
        ;;
 esac
 
index 7ff75644c056f8fc9ea3017ca369e6f58161f4e5..b050196cb7bb1b668925afe4c9307ea578c97166 100644 (file)
@@ -247,6 +247,31 @@ test_chmod () {
        git update-index --add "--chmod=$@"
 }
 
+# Use test_set_prereq to tell that a particular prerequisite is available.
+# The prerequisite can later be checked for in two ways:
+#
+# - Explicitly using test_have_prereq.
+#
+# - Implicitly by specifying the prerequisite tag in the calls to
+#   test_expect_{success,failure,code}.
+#
+# The single parameter is the prerequisite tag (a simple word, in all
+# capital letters by convention).
+
+test_set_prereq () {
+       satisfied="$satisfied$1 "
+}
+satisfied=" "
+
+test_have_prereq () {
+       case $satisfied in
+       *" $1 "*)
+               : yes, have it ;;
+       *)
+               ! : nope ;;
+       esac
+}
+
 # You are not expected to call test_ok_ and test_failure_ directly, use
 # the text_expect_* functions instead.
 
@@ -293,6 +318,11 @@ test_skip () {
                        to_skip=t
                esac
        done
+       if test -z "$to_skip" && test -n "$prereq" &&
+          ! test_have_prereq "$prereq"
+       then
+               to_skip=t
+       fi
        case "$to_skip" in
        t)
                say_color skip >&3 "skipping test: $@"
@@ -306,8 +336,9 @@ test_skip () {
 }
 
 test_expect_failure () {
+       test "$#" = 3 && { prereq=$1; shift; } || prereq=
        test "$#" = 2 ||
-       error "bug in the test script: not 2 parameters to test-expect-failure"
+       error "bug in the test script: not 2 or 3 parameters to test-expect-failure"
        if ! test_skip "$@"
        then
                say >&3 "checking known breakage: $2"
@@ -323,8 +354,9 @@ test_expect_failure () {
 }
 
 test_expect_success () {
+       test "$#" = 3 && { prereq=$1; shift; } || prereq=
        test "$#" = 2 ||
-       error "bug in the test script: not 2 parameters to test-expect-success"
+       error "bug in the test script: not 2 or 3 parameters to test-expect-success"
        if ! test_skip "$@"
        then
                say >&3 "expecting success: $2"
@@ -340,8 +372,9 @@ test_expect_success () {
 }
 
 test_expect_code () {
+       test "$#" = 4 && { prereq=$1; shift; } || prereq=
        test "$#" = 3 ||
-       error "bug in the test script: not 3 parameters to test-expect-code"
+       error "bug in the test script: not 3 or 4 parameters to test-expect-code"
        if ! test_skip "$@"
        then
                say >&3 "expecting exit code $1: $3"
@@ -365,8 +398,9 @@ test_expect_code () {
 # Usage: test_external description command arguments...
 # Example: test_external 'Perl API' perl ../path/to/test.pl
 test_external () {
-       test "$#" -eq 3 ||
-       error >&5 "bug in the test script: not 3 parameters to test_external"
+       test "$#" = 4 && { prereq=$1; shift; } || prereq=
+       test "$#" = 3 ||
+       error >&5 "bug in the test script: not 3 or 4 parameters to test_external"
        descr="$1"
        shift
        if ! test_skip "$descr" "$@"
@@ -489,14 +523,6 @@ test_done () {
        fi
        case "$test_failure" in
        0)
-               # We could:
-               # cd .. && rm -fr 'trash directory'
-               # but that means we forbid any tests that use their own
-               # subdirectory from calling test_done without coming back
-               # to where they started from.
-               # The Makefile provided will clean this test area so
-               # we will leave things as they are.
-
                say_color pass "passed all $msg"
 
                test -d "$remove_trash" &&
@@ -643,3 +669,35 @@ do
                test_done
        esac
 done
+
+# Fix some commands on Windows
+case $(uname -s) in
+*MINGW*)
+       # Windows has its own (incompatible) sort and find
+       sort () {
+               /usr/bin/sort "$@"
+       }
+       find () {
+               /usr/bin/find "$@"
+       }
+       sum () {
+               md5sum "$@"
+       }
+       # git sees Windows-style pwd
+       pwd () {
+               builtin pwd -W
+       }
+       # no POSIX permissions
+       # backslashes in pathspec are converted to '/'
+       # exec does not inherit the PID
+       ;;
+*)
+       test_set_prereq POSIXPERM
+       test_set_prereq BSLASHPSPEC
+       test_set_prereq EXECKEEPSPID
+       ;;
+esac
+
+# test whether the filesystem supports symbolic links
+ln -s x y 2>/dev/null && test -h y 2>/dev/null && test_set_prereq SYMLINKS
+rm -f y
index 9ae92cd39c3f45cb2a58a24801a790ce6622d22c..3dfb03c06ed82102f60045d6889db97cf036651e 100644 (file)
@@ -143,7 +143,7 @@ static const char *rsync_url(const char *url)
        return prefixcmp(url, "rsync://") ? skip_prefix(url, "rsync:") : url;
 }
 
-static struct ref *get_refs_via_rsync(struct transport *transport)
+static struct ref *get_refs_via_rsync(struct transport *transport, int for_push)
 {
        struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT;
        struct ref dummy, *tail = &dummy;
@@ -151,6 +151,9 @@ static struct ref *get_refs_via_rsync(struct transport *transport)
        const char *args[5];
        int temp_dir_len;
 
+       if (for_push)
+               return NULL;
+
        /* copy the refs to the temporary directory */
 
        strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX"));
@@ -429,7 +432,7 @@ static int curl_transport_push(struct transport *transport, int refspec_nr, cons
        return !!err;
 }
 
-static struct ref *get_refs_via_curl(struct transport *transport)
+static struct ref *get_refs_via_curl(struct transport *transport, int for_push)
 {
        struct strbuf buffer = STRBUF_INIT;
        char *data, *start, *mid;
@@ -446,6 +449,9 @@ static struct ref *get_refs_via_curl(struct transport *transport)
 
        struct walker *walker;
 
+       if (for_push)
+               return NULL;
+
        if (!transport->data)
                transport->data = get_http_walker(transport->url,
                                                transport->remote);
@@ -532,12 +538,15 @@ struct bundle_transport_data {
        struct bundle_header header;
 };
 
-static struct ref *get_refs_from_bundle(struct transport *transport)
+static struct ref *get_refs_from_bundle(struct transport *transport, int for_push)
 {
        struct bundle_transport_data *data = transport->data;
        struct ref *result = NULL;
        int i;
 
+       if (for_push)
+               return NULL;
+
        if (data->fd > 0)
                close(data->fd);
        data->fd = read_bundle_header(transport->url, &data->header);
@@ -578,6 +587,7 @@ struct git_transport_data {
        int fd[2];
        const char *uploadpack;
        const char *receivepack;
+       struct extra_have_objects extra_have;
 };
 
 static int set_git_option(struct transport *connection,
@@ -609,20 +619,23 @@ static int set_git_option(struct transport *connection,
        return 1;
 }
 
-static int connect_setup(struct transport *transport)
+static int connect_setup(struct transport *transport, int for_push, int verbose)
 {
        struct git_transport_data *data = transport->data;
-       data->conn = git_connect(data->fd, transport->url, data->uploadpack, 0);
+       data->conn = git_connect(data->fd, transport->url,
+                                for_push ? data->receivepack : data->uploadpack,
+                                verbose ? CONNECT_VERBOSE : 0);
        return 0;
 }
 
-static struct ref *get_refs_via_connect(struct transport *transport)
+static struct ref *get_refs_via_connect(struct transport *transport, int for_push)
 {
        struct git_transport_data *data = transport->data;
        struct ref *refs;
 
-       connect_setup(transport);
-       get_remote_heads(data->fd[0], &refs, 0, NULL, 0, NULL);
+       connect_setup(transport, for_push, 0);
+       get_remote_heads(data->fd[0], &refs, 0, NULL,
+                        for_push ? REF_NORMAL : 0, &data->extra_have);
 
        return refs;
 }
@@ -654,7 +667,7 @@ static int fetch_refs_via_pack(struct transport *transport,
                origh[i] = heads[i] = xstrdup(to_fetch[i]->name);
 
        if (!data->conn) {
-               connect_setup(transport);
+               connect_setup(transport, 0, 0);
                get_remote_heads(data->fd[0], &refs_tmp, 0, NULL, 0, NULL);
        }
 
@@ -677,20 +690,216 @@ static int fetch_refs_via_pack(struct transport *transport,
        return (refs ? 0 : -1);
 }
 
-static int git_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags)
+static int refs_pushed(struct ref *ref)
+{
+       for (; ref; ref = ref->next) {
+               switch(ref->status) {
+               case REF_STATUS_NONE:
+               case REF_STATUS_UPTODATE:
+                       break;
+               default:
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+static void update_tracking_ref(struct remote *remote, struct ref *ref, int verbose)
+{
+       struct refspec rs;
+
+       if (ref->status != REF_STATUS_OK && ref->status != REF_STATUS_UPTODATE)
+               return;
+
+       rs.src = ref->name;
+       rs.dst = NULL;
+
+       if (!remote_find_tracking(remote, &rs)) {
+               if (verbose)
+                       fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst);
+               if (ref->deletion) {
+                       delete_ref(rs.dst, NULL, 0);
+               } else
+                       update_ref("update by push", rs.dst,
+                                       ref->new_sha1, NULL, 0, 0);
+               free(rs.dst);
+       }
+}
+
+#define SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3)
+
+static void print_ref_status(char flag, const char *summary, struct ref *to, struct ref *from, const char *msg)
+{
+       fprintf(stderr, " %c %-*s ", flag, SUMMARY_WIDTH, summary);
+       if (from)
+               fprintf(stderr, "%s -> %s", prettify_ref(from), prettify_ref(to));
+       else
+               fputs(prettify_ref(to), stderr);
+       if (msg) {
+               fputs(" (", stderr);
+               fputs(msg, stderr);
+               fputc(')', stderr);
+       }
+       fputc('\n', stderr);
+}
+
+static const char *status_abbrev(unsigned char sha1[20])
+{
+       return find_unique_abbrev(sha1, DEFAULT_ABBREV);
+}
+
+static void print_ok_ref_status(struct ref *ref)
+{
+       if (ref->deletion)
+               print_ref_status('-', "[deleted]", ref, NULL, NULL);
+       else if (is_null_sha1(ref->old_sha1))
+               print_ref_status('*',
+                       (!prefixcmp(ref->name, "refs/tags/") ? "[new tag]" :
+                         "[new branch]"),
+                       ref, ref->peer_ref, NULL);
+       else {
+               char quickref[84];
+               char type;
+               const char *msg;
+
+               strcpy(quickref, status_abbrev(ref->old_sha1));
+               if (ref->nonfastforward) {
+                       strcat(quickref, "...");
+                       type = '+';
+                       msg = "forced update";
+               } else {
+                       strcat(quickref, "..");
+                       type = ' ';
+                       msg = NULL;
+               }
+               strcat(quickref, status_abbrev(ref->new_sha1));
+
+               print_ref_status(type, quickref, ref, ref->peer_ref, msg);
+       }
+}
+
+static int print_one_push_status(struct ref *ref, const char *dest, int count)
+{
+       if (!count)
+               fprintf(stderr, "To %s\n", dest);
+
+       switch(ref->status) {
+       case REF_STATUS_NONE:
+               print_ref_status('X', "[no match]", ref, NULL, NULL);
+               break;
+       case REF_STATUS_REJECT_NODELETE:
+               print_ref_status('!', "[rejected]", ref, NULL,
+                               "remote does not support deleting refs");
+               break;
+       case REF_STATUS_UPTODATE:
+               print_ref_status('=', "[up to date]", ref,
+                               ref->peer_ref, NULL);
+               break;
+       case REF_STATUS_REJECT_NONFASTFORWARD:
+               print_ref_status('!', "[rejected]", ref, ref->peer_ref,
+                               "non-fast forward");
+               break;
+       case REF_STATUS_REMOTE_REJECT:
+               print_ref_status('!', "[remote rejected]", ref,
+                               ref->deletion ? NULL : ref->peer_ref,
+                               ref->remote_status);
+               break;
+       case REF_STATUS_EXPECTING_REPORT:
+               print_ref_status('!', "[remote failure]", ref,
+                               ref->deletion ? NULL : ref->peer_ref,
+                               "remote failed to report status");
+               break;
+       case REF_STATUS_OK:
+               print_ok_ref_status(ref);
+               break;
+       }
+
+       return 1;
+}
+
+static void print_push_status(const char *dest, struct ref *refs, int verbose)
+{
+       struct ref *ref;
+       int n = 0;
+
+       if (verbose) {
+               for (ref = refs; ref; ref = ref->next)
+                       if (ref->status == REF_STATUS_UPTODATE)
+                               n += print_one_push_status(ref, dest, n);
+       }
+
+       for (ref = refs; ref; ref = ref->next)
+               if (ref->status == REF_STATUS_OK)
+                       n += print_one_push_status(ref, dest, n);
+
+       for (ref = refs; ref; ref = ref->next) {
+               if (ref->status != REF_STATUS_NONE &&
+                   ref->status != REF_STATUS_UPTODATE &&
+                   ref->status != REF_STATUS_OK)
+                       n += print_one_push_status(ref, dest, n);
+       }
+}
+
+static void verify_remote_names(int nr_heads, const char **heads)
+{
+       int i;
+
+       for (i = 0; i < nr_heads; i++) {
+               const char *local = heads[i];
+               const char *remote = strrchr(heads[i], ':');
+
+               if (*local == '+')
+                       local++;
+
+               /* A matching refspec is okay.  */
+               if (remote == local && remote[1] == '\0')
+                       continue;
+
+               remote = remote ? (remote + 1) : local;
+               switch (check_ref_format(remote)) {
+               case 0: /* ok */
+               case CHECK_REF_FORMAT_ONELEVEL:
+                       /* ok but a single level -- that is fine for
+                        * a match pattern.
+                        */
+               case CHECK_REF_FORMAT_WILDCARD:
+                       /* ok but ends with a pattern-match character */
+                       continue;
+               }
+               die("remote part of refspec is not a valid name in %s",
+                   heads[i]);
+       }
+}
+
+static int git_transport_push(struct transport *transport, struct ref *remote_refs, int flags)
 {
        struct git_transport_data *data = transport->data;
        struct send_pack_args args;
+       int ret;
+
+       if (!data->conn) {
+               struct ref *tmp_refs;
+               connect_setup(transport, 1, 0);
+
+               get_remote_heads(data->fd[0], &tmp_refs, 0, NULL, REF_NORMAL,
+                                NULL);
+       }
 
-       args.receivepack = data->receivepack;
-       args.send_all = !!(flags & TRANSPORT_PUSH_ALL);
        args.send_mirror = !!(flags & TRANSPORT_PUSH_MIRROR);
        args.force_update = !!(flags & TRANSPORT_PUSH_FORCE);
        args.use_thin_pack = data->thin;
        args.verbose = !!(flags & TRANSPORT_PUSH_VERBOSE);
        args.dry_run = !!(flags & TRANSPORT_PUSH_DRY_RUN);
 
-       return send_pack(&args, transport->url, transport->remote, refspec_nr, refspec);
+       ret = send_pack(&args, data->fd, data->conn, remote_refs,
+                       &data->extra_have);
+
+       close(data->fd[1]);
+       close(data->fd[0]);
+       ret |= finish_connect(data->conn);
+       data->conn = NULL;
+
+       return ret;
 }
 
 static int disconnect_git(struct transport *transport)
@@ -760,7 +969,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
                ret->set_option = set_git_option;
                ret->get_refs_list = get_refs_via_connect;
                ret->fetch = fetch_refs_via_pack;
-               ret->push = git_transport_push;
+               ret->push_refs = git_transport_push;
                ret->disconnect = disconnect_git;
 
                data->thin = 1;
@@ -787,15 +996,53 @@ int transport_set_option(struct transport *transport,
 int transport_push(struct transport *transport,
                   int refspec_nr, const char **refspec, int flags)
 {
-       if (!transport->push)
-               return 1;
-       return transport->push(transport, refspec_nr, refspec, flags);
+       verify_remote_names(refspec_nr, refspec);
+
+       if (transport->push)
+               return transport->push(transport, refspec_nr, refspec, flags);
+       if (transport->push_refs) {
+               struct ref *remote_refs =
+                       transport->get_refs_list(transport, 1);
+               struct ref **remote_tail;
+               struct ref *local_refs = get_local_heads();
+               int match_flags = MATCH_REFS_NONE;
+               int verbose = flags & TRANSPORT_PUSH_VERBOSE;
+               int ret;
+
+               if (flags & TRANSPORT_PUSH_ALL)
+                       match_flags |= MATCH_REFS_ALL;
+               if (flags & TRANSPORT_PUSH_MIRROR)
+                       match_flags |= MATCH_REFS_MIRROR;
+
+               remote_tail = &remote_refs;
+               while (*remote_tail)
+                       remote_tail = &((*remote_tail)->next);
+               if (match_refs(local_refs, remote_refs, &remote_tail,
+                              refspec_nr, refspec, match_flags)) {
+                       return -1;
+               }
+
+               ret = transport->push_refs(transport, remote_refs, flags);
+
+               print_push_status(transport->url, remote_refs, verbose);
+
+               if (!(flags & TRANSPORT_PUSH_DRY_RUN)) {
+                       struct ref *ref;
+                       for (ref = remote_refs; ref; ref = ref->next)
+                               update_tracking_ref(transport->remote, ref, verbose);
+               }
+
+               if (!ret && !refs_pushed(remote_refs))
+                       fprintf(stderr, "Everything up-to-date\n");
+               return ret;
+       }
+       return 1;
 }
 
 const struct ref *transport_get_remote_refs(struct transport *transport)
 {
        if (!transport->remote_refs)
-               transport->remote_refs = transport->get_refs_list(transport);
+               transport->remote_refs = transport->get_refs_list(transport, 0);
        return transport->remote_refs;
 }
 
index 6bbc1a82642ab9e5722cfe6ab34ec4246b3a9dd4..b1c225276619c3bc4dda5dcd0469e242ab421ea0 100644 (file)
@@ -18,8 +18,9 @@ struct transport {
        int (*set_option)(struct transport *connection, const char *name,
                          const char *value);
 
-       struct ref *(*get_refs_list)(struct transport *transport);
+       struct ref *(*get_refs_list)(struct transport *transport, int for_push);
        int (*fetch)(struct transport *transport, int refs_nr, const struct ref **refs);
+       int (*push_refs)(struct transport *transport, struct ref *refs, int flags);
        int (*push)(struct transport *connection, int refspec_nr, const char **refspec, int flags);
 
        int (*disconnect)(struct transport *connection);
index 86e28650b887b4fcc1b05cc4d3102367df18a9ac..6847c2d966c5e1d0299b21682d6fef2637329071 100644 (file)
@@ -7,6 +7,7 @@
 #include "unpack-trees.h"
 #include "progress.h"
 #include "refs.h"
+#include "attr.h"
 
 /*
  * Error messages expected by scripts out of plumbing commands such as
@@ -86,6 +87,7 @@ static int check_updates(struct unpack_trees_options *o)
                cnt = 0;
        }
 
+       git_attr_set_direction(GIT_ATTR_CHECKOUT, &o->result);
        for (i = 0; i < index->cache_nr; i++) {
                struct cache_entry *ce = index->cache[i];
 
@@ -110,6 +112,7 @@ static int check_updates(struct unpack_trees_options *o)
                }
        }
        stop_progress(&progress);
+       git_attr_set_direction(GIT_ATTR_CHECKIN, NULL);
        return errs != 0;
 }
 
diff --git a/usage.c b/usage.c
index 24f5fc00c2501c1a1cc317f0b74b458ea50c8b0e..820d09f92b03b6cc96fbe9a954c37fd2d5e5a417 100644 (file)
--- a/usage.c
+++ b/usage.c
@@ -7,7 +7,7 @@
 
 static void report(const char *prefix, const char *err, va_list params)
 {
-       char msg[256];
+       char msg[1024];
        vsnprintf(msg, sizeof(msg), err, params);
        fprintf(stderr, "%s%s\n", prefix, msg);
 }