Merge branch 'js/remote-add-with-insteadof'
authorJunio C Hamano <gitster@pobox.com>
Wed, 14 Jan 2015 20:29:47 +0000 (12:29 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 14 Jan 2015 20:29:47 +0000 (12:29 -0800)
"git remote add $name $URL" is now allowed when "url.$URL.insteadOf"
is already defined.

* js/remote-add-with-insteadof:
Add a regression test for 'git remote add <existing> <same-url>'
git remote: allow adding remotes agreeing with url.<...>.insteadOf

69 files changed:
Documentation/RelNotes/2.2.2.txt
Documentation/RelNotes/2.3.0.txt
Documentation/SubmittingPatches
Documentation/config.txt
Documentation/git-clone.txt
Documentation/git-imap-send.txt
Documentation/git-pack-objects.txt
Documentation/git-rev-list.txt
Documentation/git-send-email.txt
Documentation/git.txt
Documentation/rev-list-options.txt
GIT-VERSION-GEN
INSTALL
Makefile
bisect.c
builtin/checkout-index.c
builtin/clone.c
builtin/commit-tree.c
builtin/merge-base.c
builtin/merge.c
builtin/pack-objects.c
builtin/rev-parse.c
builtin/update-ref.c
commit.c
commit.h
contrib/completion/git-completion.bash
contrib/completion/git-completion.zsh
contrib/completion/git-prompt.sh
date.c
diffcore-break.c
git-add--interactive.perl
git-bisect.sh
git-compat-util.h
git-send-email.perl
git-svn.perl
imap-send.c
list-objects.c
lockfile.c
merge-recursive.c
notes-merge.c
perl/Git/SVN/Editor.pm
refs.c
remote.c
revision.c
revision.h
send-pack.c
sha1_name.c
strbuf.c
submodule.c
t/t0006-date.sh
t/t0030-stripspace.sh
t/t0090-cache-tree.sh
t/t1400-update-ref.sh
t/t1450-fsck.sh
t/t2004-checkout-cache-temp.sh
t/t2024-checkout-dwim.sh
t/t2107-update-index-basic.sh
t/t4008-diff-break-rewrite.sh
t/t4023-diff-rename-typechange.sh
t/t5400-send-pack.sh
t/t5700-clone-reference.sh
t/t6030-bisect-porcelain.sh
t/t9001-send-email.sh
t/t9148-git-svn-propset.sh [new file with mode: 0755]
templates/hooks--pre-push.sample
transport.c
update_unicode.sh
upload-pack.c
utf8.c
index 29e1a3b324e7f06c390f68f0c428ce2aa3e2b86a..b19a35d94f683f8e9cea99ebb82f712817ac2d0d 100644 (file)
@@ -30,4 +30,34 @@ Fixes since v2.2.1
  * The build procedure did not bother fixing perl and python scripts
    when NO_PERL and NO_PYTHON build-time configuration changed.
 
+ * The code that reads the reflog from the newer to the older entries
+   did not handle an entry that crosses a boundary of block it uses to
+   read them correctly.
+
+ * "git apply" was described in the documentation to take --ignore-date
+   option, which it does not.
+
+ * Traditionally we tried to avoid interpreting date strings given by
+   the user as future dates, e.g. GIT_COMMITTER_DATE=2014-12-10 when
+   used early November 2014 was taken as "October 12, 2014" because it
+   is likely that a date in the future, December 10, is a mistake.
+   This heuristics has been loosened to allow people to express future
+   dates (most notably, --until=<date> may want to be far in the
+   future) and we no longer tiebreak by future-ness of the date when
+
+    (1) ISO-like format is used, and
+    (2) the string can make sense interpreted as both y-m-d and y-d-m.
+
+   Git may still have to use the heuristics to tiebreak between dd/mm/yy
+   and mm/dd/yy, though.
+
+ * The code to abbreviate an object name to its short unique prefix
+   has been optimized when no abbreviation was requested.
+
+ * "git add --ignore-errors ..." did not ignore an error to
+   give a file that did not exist.
+
+ * Git did not correctly read an overlong refname from a packed refs
+   file.
+
 Also contains typofixes, documentation updates and trivial code clean-ups.
index 1b1dcbb5840c86b62fbe2f8cb9a758b1498d4ef0..72db8d211fbf94ae94f8f372237b4b1de153b932 100644 (file)
@@ -26,9 +26,19 @@ UI, Workflows & Features
  * "git am" learned "--message-id" option to copy the message ID of
    the incoming e-mail to the log message of resulting commit.
 
+ * "git clone --reference=<over there>" learned the "--dissociate"
+   option to go with it; it borrows objects from the reference object
+   store while cloning only to reduce network traffic and then
+   dissociates the resulting clone from the reference by performing
+   local copies of borrowed objects.
+
  * "git send-email" learned "--transfer-encoding" option to force a
    non-fault Content-Transfer-Encoding header (e.g. base64).
 
+ * "git send-email" normally identifies itself via X-Mailer: header in
+   the message it sends out.  A new command line flag --no-xmailer
+   allows the user to squelch the header.
+
  * "git push" into a repository with a working tree normally refuses
    to modify the branch that is checked out.  The command learned to
    optionally do an equivalent of "git reset --hard" only when there
@@ -53,9 +63,31 @@ UI, Workflows & Features
  * "diff-highlight" filter (in contrib/) allows its color output to be
    customized via configuration variables.
 
+ * "git imap-send" learned to take "-v" (verbose) and "-q" (quiet)
+   command line options.
+
+ * "git imap-send" now can be built to use cURL library to talk to
+   IMAP servers (if the library is recent enough, of course).
+   This allows you to use authenticate method other than CRAM-MD5,
+   among other things.
+
 
 Performance, Internal Implementation, Development Support etc.
 
+ * Earlier we made "rev-list --object-edge" more aggressively list the
+   objects at the edge commits, in order to reduce number of objects 
+   fetched into a shallow repository, but the change affected cases
+   other than "fetching into a shallow repository" and made it
+   unusably slow (e.g. fetching into a normal repository should not
+   have to suffer the overhead from extra processing).  Limit it to a
+   more specific case by introducing --objects-edge-aggressive, a new
+   option to rev-list.
+
+ * Squelched useless compiler warnings on Mac OS X regarding the
+   crypto API.
+
+ * The procedure to generate unicode table has been simplified.
+
  * Some filesystems assign filemodes in a strange way, fooling then
    automatic "filemode trustability" check done during a new
    repository creation.  The initialization codepath has been hardened
@@ -64,6 +96,9 @@ Performance, Internal Implementation, Development Support etc.
  * The codepath in "git remote update --prune" to drop many refs has
    been optimized.
 
+ * The API into get_merge_bases*() family of functions was easy to
+   misuse, which has been corrected to make it harder to do so.
+
  * Long overdue departure from the assumption that S_IFMT is shared by
    everybody made in 2005, which was necessary to port to z/OS.
 
@@ -87,10 +122,49 @@ Unless otherwise noted, all the fixes since v2.2 in the maintenance
 track are contained in this release (see the maintenance releases'
 notes for details).
 
+ * The logic in "git bisect bad HEAD" etc. to avoid forcing the test
+   of the common ancestor of bad and good commits was broken.
+   (merge 07913d5 cc/bisect-rev-parsing later to maint).
+
+ * "git checkout-index --temp=$target $path" did not work correctly
+   for paths outside the current subdirectory in the project.
+   (merge 74c4de5 es/checkout-index-temp later to maint).
+
+ * The report from "git checkout" on a branch that builds on another
+   local branch by setting its branch.*.merge to branch name (not a
+   full refname) incorrectly said that the upstream is gone.
+   (merge 05e7368 jc/checkout-local-track-report later to maint).
+
+ * With The git-prompt support (in contrib/), using the exit status of
+   the last command in the prompt, e.g.  PS1='$(__git_ps1) $? ', did
+   not work well, because the helper function stomped on the exit
+   status.
+   (merge eb443e3 tf/prompt-preserve-exit-status later to maint).
+
+
  * Recent update to "git commit" broke amending an existing commit
    with bogus author/committer lines without a valid e-mail address.
    (merge c83a509 jk/commit-date-approxidate later to maint).
 
+ * The lockfile API used to get confused which file to clean up when
+   the process moved the $cwd after creating a lockfile.
+   (merge fa137f6 nd/lockfile-absolute later to maint).
+
+ * Traditionally we tried to avoid interpreting date strings given by
+   the user as future dates, e.g. GIT_COMMITTER_DATE=2014-12-10 when
+   used early November 2014 was taken as "October 12, 2014" because it
+   is likely that a date in the future, December 10, is a mistake.
+   This heuristics has been loosened to allow people to express future
+   dates (most notably, --until=<date> may want to be far in the
+   future) and we no longer tiebreak by future-ness of the date when
+
+    (1) ISO-like format is used, and
+    (2) the string can make sense interpreted as both y-m-d and y-d-m.
+
+   Git may still have to use the heuristics to tiebreak between dd/mm/yy
+   and mm/dd/yy, though.
+   (merge d372395 jk/approxidate-avoid-y-d-m-over-future-dates later to maint).
+
  * Git did not correctly read an overlong refname from a packed refs
    file.
    (merge ea41783 jk/read-packed-refs-without-path-max later to maint).
@@ -99,6 +173,14 @@ notes for details).
    option, which it does not.
    (merge 0cef4e7 rw/apply-does-not-take-ignore-date later to maint).
 
+ * "git add -i" did not notice when the interactive command input
+   stream went away and kept asking the same question.
+   (merge a8bec7a jk/add-i-read-error later to maint).
+
+ * "git send-email" did not handle RFC 2047 encoded headers quite
+   right.
+   (merge ab47e2a rd/send-email-2047-fix later to maint).
+
  * New tag object format validation added in 2.2 showed garbage after
    a tagname it reported in its error message.
    (merge a1e920a js/fsck-tag-validation later to maint).
@@ -108,6 +190,23 @@ notes for details).
    read them correctly.
    (merge 69216bf jk/for-each-reflog-ent-reverse later to maint).
 
+ * "git diff -B -M" after making a new copy B out of an existing file
+   A and then editing A extensively ought to report that B was created
+   by copying A and A was modified, which is what "git diff -C"
+   reports, but it instead said A was renamed to B and A was edited
+   heavily in place.  This was not just incoherent but also failed to
+   apply with "git apply".  The report has been corrected to match what
+   "git diff -C" produces for this case.
+   (merge 6936b58 jc/diff-b-m later to maint).
+
+ * In files we pre-populate for the user to edit with commented hints,
+   a line of hint that is indented with a tab used to show as '#' (or
+   any comment char), ' ' (space), and then the hint text that began
+   with the tab, which some editors flag as an indentation error (tab
+   following space).  We now omit the space after the comment char in
+   such a case.
+   (merge d55aeb7 jc/strbuf-add-lines-avoid-sp-ht-sequence later to maint).
+
  * "git ls-tree" does not support path selection based on negative
    pathspecs, but did not error out when negative pathspecs are given.
    (merge f1f6224 nd/ls-tree-pathspec later to maint).
index e3c942e57902abc2767c202978a4bd5060ca449f..ef0eeb40cd225925b1cd034221c426eea1c88f1b 100644 (file)
@@ -176,8 +176,11 @@ message starts, you can put a "From: " line to name that person.
 
 You often want to add additional explanation about the patch,
 other than the commit message itself.  Place such "cover letter"
-material between the three dash lines and the diffstat. Git-notes
-can also be inserted using the `--notes` option.
+material between the three-dash line and the diffstat.  For
+patches requiring multiple iterations of review and discussion,
+an explanation of changes between each iteration can be kept in
+Git-notes and inserted automatically following the three-dash
+line via `git format-patch --notes`.
 
 Do not attach the patch as a MIME attachment, compressed or not.
 Do not let your e-mail client send quoted-printable.  Do not let
@@ -255,15 +258,15 @@ pretty simple: if you can certify the below:
             person who certified (a), (b) or (c) and I have not modified
             it.
 
-       (d) I understand and agree that this project and the contribution
-           are public and that a record of the contribution (including all
-           personal information I submit with it, including my sign-off) is
-           maintained indefinitely and may be redistributed consistent with
-           this project or the open source license(s) involved.
+        (d) I understand and agree that this project and the contribution
+            are public and that a record of the contribution (including all
+            personal information I submit with it, including my sign-off) is
+            maintained indefinitely and may be redistributed consistent with
+            this project or the open source license(s) involved.
 
 then you just add a line saying
 
-       Signed-off-by: Random J Developer <random@developer.example.org>
+        Signed-off-by: Random J Developer <random@developer.example.org>
 
 This line can be automatically added by Git if you run the git-commit
 command with the -s option.
index 6862e3e30155b7139c960ce2f42f5fba96f11886..cc887b1279cb04c33cc2e67c373c6ed61daff520 100644 (file)
@@ -2329,6 +2329,7 @@ sendemail.smtpuser::
 sendemail.thread::
 sendemail.transferencoding::
 sendemail.validate::
+sendemail.xmailer::
        See linkgit:git-send-email[1] for description.
 
 sendemail.signedoffcc::
index 0363d0039b274093e6d230a83fcf99c3ff6700d8..f1f2a3f7ea92282756a0b2b72271469561b442df 100644 (file)
@@ -12,7 +12,7 @@ SYNOPSIS
 'git clone' [--template=<template_directory>]
          [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror]
          [-o <name>] [-b <name>] [-u <upload-pack>] [--reference <repository>]
-         [--separate-git-dir <git dir>]
+         [--dissociate] [--separate-git-dir <git dir>]
          [--depth <depth>] [--[no-]single-branch]
          [--recursive | --recurse-submodules] [--] <repository>
          [<directory>]
@@ -98,7 +98,14 @@ objects from the source repository into a pack in the cloned repository.
        require fewer objects to be copied from the repository
        being cloned, reducing network and local storage costs.
 +
-*NOTE*: see the NOTE for the `--shared` option.
+*NOTE*: see the NOTE for the `--shared` option, and also the
+`--dissociate` option.
+
+--dissociate::
+       Borrow the objects from reference repositories specified
+       with the `--reference` options only to reduce network
+       transfer and stop borrowing from them after a clone is made
+       by making necessary local copies of borrowed objects.
 
 --quiet::
 -q::
index c7c0d21429bb745d1abcfc775308e8ccac8f499a..77aacf130936435970a945e4d687d01c12b1a0f9 100644 (file)
@@ -9,7 +9,7 @@ git-imap-send - Send a collection of patches from stdin to an IMAP folder
 SYNOPSIS
 --------
 [verse]
-'git imap-send'
+'git imap-send' [-v] [-q] [--[no-]curl]
 
 
 DESCRIPTION
@@ -26,6 +26,27 @@ Typical usage is something like:
 git format-patch --signoff --stdout --attach origin | git imap-send
 
 
+OPTIONS
+-------
+
+-v::
+--verbose::
+       Be verbose.
+
+-q::
+--quiet::
+       Be quiet.
+
+--curl::
+       Use libcurl to communicate with the IMAP server, unless tunneling
+       into it.  Ignored if Git was built without the USE_CURL_FOR_IMAP_SEND
+       option set.
+
+--no-curl::
+       Talk to the IMAP server using git's own IMAP routines instead of
+       using libcurl.
+
+
 CONFIGURATION
 -------------
 
@@ -75,7 +96,9 @@ imap.preformattedHTML::
 
 imap.authMethod::
        Specify authenticate method for authentication with IMAP server.
-       Current supported method is 'CRAM-MD5' only. If this is not set
+       If Git was built with the NO_CURL option, or if your curl version is older
+       than 7.34.0, or if you're running git-imap-send with the `--no-curl`
+       option, the only supported method is 'CRAM-MD5'. If this is not set
        then 'git imap-send' uses the basic IMAP plaintext LOGIN command.
 
 Examples
index d2d8f4792afaf5dc1105457493b070bcf163ecef..c2f76fb1ea476aa551963349ee976ad8745f10e2 100644 (file)
@@ -13,7 +13,7 @@ SYNOPSIS
        [--no-reuse-delta] [--delta-base-offset] [--non-empty]
        [--local] [--incremental] [--window=<n>] [--depth=<n>]
        [--revs [--unpacked | --all]] [--stdout | base-name]
-       [--keep-true-parents] < object-list
+       [--shallow] [--keep-true-parents] < object-list
 
 
 DESCRIPTION
@@ -190,6 +190,11 @@ required objects and is thus unusable by Git without making it
 self-contained. Use `git index-pack --fix-thin`
 (see linkgit:git-index-pack[1]) to restore the self-contained property.
 
+--shallow::
+       Optimize a pack that will be provided to a client with a shallow
+       repository.  This option, combined with \--thin, can result in a
+       smaller pack at the cost of speed.
+
 --delta-base-offset::
        A packed archive can express the base object of a delta as
        either a 20-byte object name or as an offset in the
index fd7f8b5bc1840bc93273dd7b076d86499626912a..5b119220bf168153d63bf2051a065e40b68c1ed3 100644 (file)
@@ -46,7 +46,8 @@ SYNOPSIS
             [ \--extended-regexp | -E ]
             [ \--fixed-strings | -F ]
             [ \--date=(local|relative|default|iso|iso-strict|rfc|short) ]
-            [ [\--objects | \--objects-edge] [ \--unpacked ] ]
+            [ [ \--objects | \--objects-edge | \--objects-edge-aggressive ]
+              [ \--unpacked ] ]
             [ \--pretty | \--header ]
             [ \--bisect ]
             [ \--bisect-vars ]
index a9efa5c2ec18776e12c5bdbb250df5b8e0f41581..e04849e3961257500f86441611e738e9b4d0f330 100644 (file)
@@ -141,6 +141,11 @@ Note that no attempts whatsoever are made to validate the encoding.
        configuration value; if that is unspecified, git will use 8bit and not
        add a Content-Transfer-Encoding header.
 
+--xmailer::
+--no-xmailer::
+       Add (or prevent adding) the "X-Mailer:" header.  By default,
+       the header is added, but it can be turned off by setting the
+       `sendemail.xmailer` configuration variable to `false`.
 
 Sending
 ~~~~~~~
index 179615195fd260d4d6d87bc1cda6f5c8a699719d..9d334314270003d4ce54ef233691506dd4f10197 100644 (file)
@@ -43,9 +43,10 @@ unreleased) version of Git, that is available from the 'master'
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
-* link:v2.2.1/git.html[documentation for release 2.2.1]
+* link:v2.2.2/git.html[documentation for release 2.2.2]
 
 * release notes for
+  link:RelNotes/2.2.2.txt[2.2.2],
   link:RelNotes/2.2.1.txt[2.2.1],
   link:RelNotes/2.2.0.txt[2.2].
 
index afccfdc23a38f2dca84ebeff2cc8624eb8a0e23e..2984f407a9f3084235fd0207a82ea44a424942ed 100644 (file)
@@ -653,10 +653,15 @@ These options are mostly targeted for packing of Git repositories.
 --objects-edge::
        Similar to `--objects`, but also print the IDs of excluded
        commits prefixed with a ``-'' character.  This is used by
-       linkgit:git-pack-objects[1] to build ``thin'' pack, which records
+       linkgit:git-pack-objects[1] to build ``thin'' pack, which records
        objects in deltified form based on objects contained in these
        excluded commits to reduce network traffic.
 
+--objects-edge-aggressive::
+       Similar to `--objects-edge`, but it tries harder to find excluded
+       commits at the cost of increased time.  This is used instead of
+       `--objects-edge` to build ``thin'' packs for shallow repositories.
+
 --unpacked::
        Only useful with `--objects`; print the object IDs that are not
        in packs.
index 53dd6b328563c143181a932c119754c62b4dc9b3..57dc9635aaf9f699bb56418701e05473d983de91 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.2.0.GIT
+DEF_VER=v2.3.0-rc0
 
 LF='
 '
diff --git a/INSTALL b/INSTALL
index 6ec7a24e1a7ff1d9bb380e6c9bdb1c16dbf5d1c1..ffb071e9f03a79a052beaa4372fa790ecbabbb7b 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -108,18 +108,21 @@ Issues of note:
          so you might need to install additional packages other than Perl
          itself, e.g. Time::HiRes.
 
-       - "openssl" library is used by git-imap-send to use IMAP over SSL.
-         If you don't need it, use NO_OPENSSL.
+       - git-imap-send needs the OpenSSL library to talk IMAP over SSL if
+         you are using libcurl older than 7.34.0.  Otherwise you can use
+         NO_OPENSSL without losing git-imap-send.
 
          By default, git uses OpenSSL for SHA1 but it will use its own
          library (inspired by Mozilla's) with either NO_OPENSSL or
          BLK_SHA1.  Also included is a version optimized for PowerPC
          (PPC_SHA1).
 
-       - "libcurl" library is used by git-http-fetch and git-fetch.  You
-         might also want the "curl" executable for debugging purposes.
-         If you do not use http:// or https:// repositories, you do not
-         have to have them (use NO_CURL).
+       - "libcurl" library is used by git-http-fetch, git-fetch, and, if
+         the curl version >= 7.34.0, for git-imap-send.  You might also
+         want the "curl" executable for debugging purposes. If you do not
+         use http:// or https:// repositories, and do not want to put
+         patches into an IMAP mailbox, you do not have to have them
+         (use NO_CURL).
 
        - "expat" library; git-http-push uses it for remote lock
          management over DAV.  Similar to "curl" above, this is optional
index 86bc0c2f04b8f3b45412a407a4e6124b16897867..06e5d24312e47e9a6e7e33def74c70f54c21f2e1 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -999,6 +999,9 @@ ifdef HAVE_ALLOCA_H
        BASIC_CFLAGS += -DHAVE_ALLOCA_H
 endif
 
+IMAP_SEND_BUILDDEPS =
+IMAP_SEND_LDFLAGS = $(OPENSSL_LINK) $(OPENSSL_LIBSSL) $(LIB_4_CRYPTO)
+
 ifdef NO_CURL
        BASIC_CFLAGS += -DNO_CURL
        REMOTE_CURL_PRIMARY =
@@ -1033,6 +1036,15 @@ else
                        PROGRAM_OBJS += http-push.o
                endif
        endif
+       curl_check := $(shell (echo 072200; curl-config --vernum) 2>/dev/null | sort -r | sed -ne 2p)
+       ifeq "$(curl_check)" "072200"
+               USE_CURL_FOR_IMAP_SEND = YesPlease
+       endif
+       ifdef USE_CURL_FOR_IMAP_SEND
+               BASIC_CFLAGS += -DUSE_CURL_FOR_IMAP_SEND
+               IMAP_SEND_BUILDDEPS = http.o
+               IMAP_SEND_LDFLAGS += $(CURL_LIBCURL)
+       endif
        ifndef NO_EXPAT
                ifdef EXPATDIR
                        BASIC_CFLAGS += -I$(EXPATDIR)/include
@@ -1888,7 +1900,7 @@ gettext.sp gettext.s gettext.o: GIT-PREFIX
 gettext.sp gettext.s gettext.o: EXTRA_CPPFLAGS = \
        -DGIT_LOCALE_PATH='"$(localedir_SQ)"'
 
-http-push.sp http.sp http-walker.sp remote-curl.sp: SPARSE_FLAGS += \
+http-push.sp http.sp http-walker.sp remote-curl.sp imap-send.sp: SPARSE_FLAGS += \
        -DCURL_DISABLE_TYPECHECK
 
 ifdef NO_EXPAT
@@ -1909,9 +1921,9 @@ endif
 git-%$X: %.o GIT-LDFLAGS $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
 
-git-imap-send$X: imap-send.o GIT-LDFLAGS $(GITLIBS)
+git-imap-send$X: imap-send.o $(IMAP_SEND_BUILDDEPS) GIT-LDFLAGS $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
-               $(LIBS) $(OPENSSL_LINK) $(OPENSSL_LIBSSL) $(LIB_4_CRYPTO)
+               $(LIBS) $(IMAP_SEND_LDFLAGS)
 
 git-http-fetch$X: http.o http-walker.o http-fetch.o GIT-LDFLAGS $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
index df09cbc8cabe9dcb87a0023445babcf14c3d7691..8c6d843699ab04bc0fe952268d14965943446a17 100644 (file)
--- a/bisect.c
+++ b/bisect.c
@@ -777,7 +777,7 @@ static void check_merge_bases(int no_checkout)
        int rev_nr;
        struct commit **rev = get_bad_and_good_commits(&rev_nr);
 
-       result = get_merge_bases_many(rev[0], rev_nr - 1, rev + 1, 0);
+       result = get_merge_bases_many(rev[0], rev_nr - 1, rev + 1);
 
        for (; result; result = result->next) {
                const unsigned char *mb = result->item->object.sha1;
index 383dccf93ef4eceb873eee4cd63e6781854b295c..031780f49e0b3a3e7a8e1aa4904e33858f11542d 100644 (file)
@@ -18,7 +18,7 @@ static char topath[4][TEMPORARY_FILENAME_LENGTH + 1];
 
 static struct checkout state;
 
-static void write_tempfile_record(const char *name, int prefix_length)
+static void write_tempfile_record(const char *name, const char *prefix)
 {
        int i;
 
@@ -35,14 +35,14 @@ static void write_tempfile_record(const char *name, int prefix_length)
                fputs(topath[checkout_stage], stdout);
 
        putchar('\t');
-       write_name_quoted(name + prefix_length, stdout, line_termination);
+       write_name_quoted_relative(name, prefix, stdout, line_termination);
 
        for (i = 0; i < 4; i++) {
                topath[i][0] = 0;
        }
 }
 
-static int checkout_file(const char *name, int prefix_length)
+static int checkout_file(const char *name, const char *prefix)
 {
        int namelen = strlen(name);
        int pos = cache_name_pos(name, namelen);
@@ -71,7 +71,7 @@ static int checkout_file(const char *name, int prefix_length)
 
        if (did_checkout) {
                if (to_tempfile)
-                       write_tempfile_record(name, prefix_length);
+                       write_tempfile_record(name, prefix);
                return errs > 0 ? -1 : 0;
        }
 
@@ -106,7 +106,7 @@ static void checkout_all(const char *prefix, int prefix_length)
                if (last_ce && to_tempfile) {
                        if (ce_namelen(last_ce) != ce_namelen(ce)
                            || memcmp(last_ce->name, ce->name, ce_namelen(ce)))
-                               write_tempfile_record(last_ce->name, prefix_length);
+                               write_tempfile_record(last_ce->name, prefix);
                }
                if (checkout_entry(ce, &state,
                    to_tempfile ? topath[ce_stage(ce)] : NULL) < 0)
@@ -114,7 +114,7 @@ static void checkout_all(const char *prefix, int prefix_length)
                last_ce = ce;
        }
        if (last_ce && to_tempfile)
-               write_tempfile_record(last_ce->name, prefix_length);
+               write_tempfile_record(last_ce->name, prefix);
        if (errs)
                /* we have already done our error reporting.
                 * exit with the same code as die().
@@ -248,7 +248,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
                if (read_from_stdin)
                        die("git checkout-index: don't mix '--stdin' and explicit filenames");
                p = prefix_path(prefix, prefix_length, arg);
-               checkout_file(p, prefix_length);
+               checkout_file(p, prefix);
                if (p < arg || p > arg + strlen(arg))
                        free((char *)p);
        }
@@ -268,7 +268,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
                                strbuf_swap(&buf, &nbuf);
                        }
                        p = prefix_path(prefix, prefix_length, buf.buf);
-                       checkout_file(p, prefix_length);
+                       checkout_file(p, prefix);
                        if (p < buf.buf || p > buf.buf + buf.len)
                                free((char *)p);
                }
index d5e7532105aa66c5b7e04e170489cf905928b5bb..316c75d0b342d039696608c18adfabaa3366b0e7 100644 (file)
@@ -49,6 +49,7 @@ static int option_verbosity;
 static int option_progress = -1;
 static struct string_list option_config;
 static struct string_list option_reference;
+static int option_dissociate;
 
 static int opt_parse_reference(const struct option *opt, const char *arg, int unset)
 {
@@ -94,6 +95,8 @@ static struct option builtin_clone_options[] = {
                    N_("create a shallow clone of that depth")),
        OPT_BOOL(0, "single-branch", &option_single_branch,
                    N_("clone only one branch, HEAD or --branch")),
+       OPT_BOOL(0, "dissociate", &option_dissociate,
+                N_("use --reference only while cloning")),
        OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
                   N_("separate git dir from working tree")),
        OPT_STRING_LIST('c', "config", &option_config, N_("key=value"),
@@ -735,6 +738,16 @@ static void write_refspec_config(const char *src_ref_prefix,
        strbuf_release(&value);
 }
 
+static void dissociate_from_references(void)
+{
+       static const char* argv[] = { "repack", "-a", "-d", NULL };
+
+       if (run_command_v_opt(argv, RUN_GIT_CMD|RUN_COMMAND_NO_STDIN))
+               die(_("cannot repack to clean up"));
+       if (unlink(git_path("objects/info/alternates")) && errno != ENOENT)
+               die_errno(_("cannot unlink temporary alternates file"));
+}
+
 int cmd_clone(int argc, const char **argv, const char *prefix)
 {
        int is_bundle = 0, is_local;
@@ -880,6 +893,10 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 
        if (option_reference.nr)
                setup_reference();
+       else if (option_dissociate) {
+               warning(_("--dissociate given, but there is no --reference"));
+               option_dissociate = 0;
+       }
 
        fetch_pattern = value.buf;
        refspec = parse_fetch_refspec(1, &fetch_pattern);
@@ -993,6 +1010,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
        transport_unlock_pack(transport);
        transport_disconnect(transport);
 
+       if (option_dissociate)
+               dissociate_from_references();
+
        junk_mode = JUNK_LEAVE_REPO;
        err = checkout();
 
index 8a66c74e0fd405a06e6c767d385013ff7150db04..25aa2cdef3557c67a9482492a4d0294bc7b89b04 100644 (file)
@@ -66,10 +66,8 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
                        continue;
                }
 
-               if (!memcmp(arg, "-S", 2)) {
-                       sign_commit = arg + 2;
+               if (skip_prefix(arg, "-S", &sign_commit))
                        continue;
-               }
 
                if (!strcmp(arg, "--no-gpg-sign")) {
                        sign_commit = NULL;
index 0ecde8da30615996f54563014e4774b67812c531..fdebef6fa157e920a4560e68c1215665f1e20baf 100644 (file)
@@ -10,7 +10,7 @@ static int show_merge_base(struct commit **rev, int rev_nr, int show_all)
 {
        struct commit_list *result;
 
-       result = get_merge_bases_many(rev[0], rev_nr - 1, rev + 1, 0);
+       result = get_merge_bases_many_dirty(rev[0], rev_nr - 1, rev + 1);
 
        if (!result)
                return 1;
@@ -176,7 +176,7 @@ static int handle_fork_point(int argc, const char **argv)
        for (i = 0; i < revs.nr; i++)
                revs.commit[i]->object.flags &= ~TMP_MARK;
 
-       bases = get_merge_bases_many(derived, revs.nr, revs.commit, 0);
+       bases = get_merge_bases_many_dirty(derived, revs.nr, revs.commit);
 
        /*
         * There should be one and only one merge base, when we found
index 215d4856e507f671139f41c73b57e661d8d1bf87..c638fd5a9a8165c58d46d4edeeb0f3bbe8c0f9a1 100644 (file)
@@ -894,6 +894,7 @@ static int suggest_conflicts(void)
 
        append_conflicts_hint(&msgbuf);
        fputs(msgbuf.buf, fp);
+       strbuf_release(&msgbuf);
        fclose(fp);
        rerere(allow_rerere_auto);
        printf(_("Automatic merge failed; "
@@ -1312,7 +1313,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
        if (!remoteheads)
                ; /* already up-to-date */
        else if (!remoteheads->next)
-               common = get_merge_bases(head_commit, remoteheads->item, 1);
+               common = get_merge_bases(head_commit, remoteheads->item);
        else {
                struct commit_list *list = remoteheads;
                commit_list_insert(head_commit, &list);
@@ -1409,7 +1410,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                         * merge_bases again, otherwise "git merge HEAD^
                         * HEAD^^" would be missed.
                         */
-                       common_one = get_merge_bases(head_commit, j->item, 1);
+                       common_one = get_merge_bases(head_commit, j->item);
                        if (hashcmp(common_one->item->object.sha1,
                                j->item->object.sha1)) {
                                up_to_date = 0;
index 3f9f5c7760a63bc2deb32b75f500ac0d1bc87538..d8165878e1d466e49719038b1badc524d5627270 100644 (file)
@@ -2613,6 +2613,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 {
        int use_internal_rev_list = 0;
        int thin = 0;
+       int shallow = 0;
        int all_progress_implied = 0;
        struct argv_array rp = ARGV_ARRAY_INIT;
        int rev_list_unpacked = 0, rev_list_all = 0, rev_list_reflog = 0;
@@ -2677,6 +2678,8 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
                  PARSE_OPT_OPTARG, option_parse_unpack_unreachable },
                OPT_BOOL(0, "thin", &thin,
                         N_("create thin packs")),
+               OPT_BOOL(0, "shallow", &shallow,
+                        N_("create packs suitable for shallow fetches")),
                OPT_BOOL(0, "honor-pack-keep", &ignore_packed_keep,
                         N_("ignore packs that have companion .keep file")),
                OPT_INTEGER(0, "compression", &pack_compression_level,
@@ -2711,7 +2714,9 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
        argv_array_push(&rp, "pack-objects");
        if (thin) {
                use_internal_rev_list = 1;
-               argv_array_push(&rp, "--objects-edge");
+               argv_array_push(&rp, shallow
+                               ? "--objects-edge-aggressive"
+                               : "--objects-edge");
        } else
                argv_array_push(&rp, "--objects");
 
index 35d3c43ed656bf28b78501426f4502c0dff1e7b0..95328b80d930260915ad86a30a21ecd3c1b7d1f4 100644 (file)
@@ -279,7 +279,7 @@ static int try_difference(const char *arg)
                        struct commit *a, *b;
                        a = lookup_commit_reference(sha1);
                        b = lookup_commit_reference(end);
-                       exclude = get_merge_bases(a, b, 1);
+                       exclude = get_merge_bases(a, b);
                        while (exclude) {
                                struct commit_list *n = exclude->next;
                                show_rev(REVERSED,
index 6c9be051284a78cbdbe6630dbcaae4846288c667..1993529521c0ef20860795168392d1dd7209c991 100644 (file)
@@ -282,26 +282,22 @@ static const char *parse_cmd_verify(struct ref_transaction *transaction,
        char *refname;
        unsigned char new_sha1[20];
        unsigned char old_sha1[20];
-       int have_old;
 
        refname = parse_refname(input, &next);
        if (!refname)
                die("verify: missing <ref>");
 
        if (parse_next_sha1(input, &next, old_sha1, "verify", refname,
-                           PARSE_SHA1_OLD)) {
-               hashclr(new_sha1);
-               have_old = 0;
-       } else {
-               hashcpy(new_sha1, old_sha1);
-               have_old = 1;
-       }
+                           PARSE_SHA1_OLD))
+               hashclr(old_sha1);
+
+       hashcpy(new_sha1, old_sha1);
 
        if (*next != line_termination)
                die("verify %s: extra input: %s", refname, next);
 
        if (ref_transaction_update(transaction, refname, new_sha1, old_sha1,
-                                  update_flags, have_old, msg, &err))
+                                  update_flags, 1, msg, &err))
                die("%s", err.buf);
 
        update_flags = 0;
index a54cb9a454fdce3ccf9dff58338e43d73945d728..a8c7577d28a4b2a0b5fc13420f8a141871626087 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -867,7 +867,7 @@ struct commit_list *get_octopus_merge_bases(struct commit_list *in)
 
                for (j = ret; j; j = j->next) {
                        struct commit_list *bases;
-                       bases = get_merge_bases(i->item, j->item, 1);
+                       bases = get_merge_bases(i->item, j->item);
                        if (!new)
                                new = bases;
                        else
@@ -936,10 +936,10 @@ static int remove_redundant(struct commit **array, int cnt)
        return filled;
 }
 
-struct commit_list *get_merge_bases_many(struct commit *one,
-                                        int n,
-                                        struct commit **twos,
-                                        int cleanup)
+static struct commit_list *get_merge_bases_many_0(struct commit *one,
+                                                 int n,
+                                                 struct commit **twos,
+                                                 int cleanup)
 {
        struct commit_list *list;
        struct commit **rslt;
@@ -977,10 +977,23 @@ struct commit_list *get_merge_bases_many(struct commit *one,
        return result;
 }
 
-struct commit_list *get_merge_bases(struct commit *one, struct commit *two,
-                                   int cleanup)
+struct commit_list *get_merge_bases_many(struct commit *one,
+                                        int n,
+                                        struct commit **twos)
+{
+       return get_merge_bases_many_0(one, n, twos, 1);
+}
+
+struct commit_list *get_merge_bases_many_dirty(struct commit *one,
+                                              int n,
+                                              struct commit **twos)
+{
+       return get_merge_bases_many_0(one, n, twos, 0);
+}
+
+struct commit_list *get_merge_bases(struct commit *one, struct commit *two)
 {
-       return get_merge_bases_many(one, 1, &two, cleanup);
+       return get_merge_bases_many_0(one, 1, &two, 1);
 }
 
 /*
index cd35ac150acd076047eed2e3200d1be12e4e7d5e..5cc1e7ec9ee80965d1669e0f96dfeab03f3b0798 100644 (file)
--- a/commit.h
+++ b/commit.h
@@ -236,10 +236,13 @@ struct commit_graft *read_graft_line(char *buf, int len);
 int register_commit_graft(struct commit_graft *, int);
 struct commit_graft *lookup_commit_graft(const unsigned char *sha1);
 
-extern struct commit_list *get_merge_bases(struct commit *rev1, struct commit *rev2, int cleanup);
-extern struct commit_list *get_merge_bases_many(struct commit *one, int n, struct commit **twos, int cleanup);
+extern struct commit_list *get_merge_bases(struct commit *rev1, struct commit *rev2);
+extern struct commit_list *get_merge_bases_many(struct commit *one, int n, struct commit **twos);
 extern struct commit_list *get_octopus_merge_bases(struct commit_list *in);
 
+/* To be used only when object flags after this call no longer matter */
+extern struct commit_list *get_merge_bases_many_dirty(struct commit *one, int n, struct commit **twos);
+
 /* largest positive number a signed 32-bit integer can contain */
 #define INFINITE_DEPTH 0x7fffffff
 
index 23988ec124a85d766006c6cd569c8341d3612c8b..cd765795ae42edfdf21a054619b64d5c3800f4f6 100644 (file)
@@ -16,9 +16,9 @@
 #
 # To use these routines:
 #
-#    1) Copy this file to somewhere (e.g. ~/.git-completion.sh).
+#    1) Copy this file to somewhere (e.g. ~/.git-completion.bash).
 #    2) Add the following line to your .bashrc/.zshrc:
-#        source ~/.git-completion.sh
+#        source ~/.git-completion.bash
 #    3) Consider changing your PS1 to also show the current branch,
 #       see git-prompt.sh for details.
 #
index 9f6f0fa5581002a2371e062fd5def0978733edc1..e25541308a1c269285a26b205d2d9990a789060a 100644 (file)
@@ -9,7 +9,7 @@
 #
 # If your script is somewhere else, you can configure it on your ~/.zshrc:
 #
-#  zstyle ':completion:*:*:git:*' script ~/.git-completion.sh
+#  zstyle ':completion:*:*:git:*' script ~/.git-completion.zsh
 #
 # The recommended way to install this script is to copy to '~/.zsh/_git', and
 # then add the following to your ~/.zshrc file:
index 729f7694795d1116ccedfc653f82da757e6e4ef4..3c3fc6d5d94c5dc6a9ec291fc217b590a11c5be3 100644 (file)
@@ -288,6 +288,7 @@ __git_eread ()
 # In this mode you can request colored hints using GIT_PS1_SHOWCOLORHINTS=true
 __git_ps1 ()
 {
+       local exit=$?
        local pcmode=no
        local detached=no
        local ps1pc_start='\u@\h:\w '
@@ -511,4 +512,7 @@ __git_ps1 ()
        else
                printf -- "$printf_format" "$gitstring"
        fi
+
+       # preserve exit status
+       return $exit
 }
diff --git a/date.c b/date.c
index 59dfe579c6a0c65abe0a34052cdbf16643afbfb8..3eba2dfe8841cee28850e2f1f4177e1e32f1c8a8 100644 (file)
--- a/date.c
+++ b/date.c
@@ -405,9 +405,9 @@ static int is_date(int year, int month, int day, struct tm *now_tm, time_t now,
        return 0;
 }
 
-static int match_multi_number(unsigned long num, char c, const char *date, char *end, struct tm *tm)
+static int match_multi_number(unsigned long num, char c, const char *date,
+                             char *end, struct tm *tm, time_t now)
 {
-       time_t now;
        struct tm now_tm;
        struct tm *refuse_future;
        long num2, num3;
@@ -433,17 +433,18 @@ static int match_multi_number(unsigned long num, char c, const char *date, char
        case '-':
        case '/':
        case '.':
-               now = time(NULL);
+               if (!now)
+                       now = time(NULL);
                refuse_future = NULL;
                if (gmtime_r(&now, &now_tm))
                        refuse_future = &now_tm;
 
                if (num > 70) {
                        /* yyyy-mm-dd? */
-                       if (is_date(num, num2, num3, refuse_future, now, tm))
+                       if (is_date(num, num2, num3, NULL, now, tm))
                                break;
                        /* yyyy-dd-mm? */
-                       if (is_date(num, num3, num2, refuse_future, now, tm))
+                       if (is_date(num, num3, num2, NULL, now, tm))
                                break;
                }
                /* Our eastern European friends say dd.mm.yy[yy]
@@ -513,7 +514,7 @@ static int match_digit(const char *date, struct tm *tm, int *offset, int *tm_gmt
        case '/':
        case '-':
                if (isdigit(end[1])) {
-                       int match = match_multi_number(num, *end, date, end, tm);
+                       int match = match_multi_number(num, *end, date, end, tm, 0);
                        if (match)
                                return match;
                }
@@ -1013,7 +1014,8 @@ static const char *approxidate_alpha(const char *date, struct tm *tm, struct tm
        return end;
 }
 
-static const char *approxidate_digit(const char *date, struct tm *tm, int *num)
+static const char *approxidate_digit(const char *date, struct tm *tm, int *num,
+                                    time_t now)
 {
        char *end;
        unsigned long number = strtoul(date, &end, 10);
@@ -1024,7 +1026,8 @@ static const char *approxidate_digit(const char *date, struct tm *tm, int *num)
        case '/':
        case '-':
                if (isdigit(end[1])) {
-                       int match = match_multi_number(number, *end, date, end, tm);
+                       int match = match_multi_number(number, *end, date, end,
+                                                      tm, now);
                        if (match)
                                return date + match;
                }
@@ -1087,7 +1090,7 @@ static unsigned long approxidate_str(const char *date,
                date++;
                if (isdigit(c)) {
                        pending_number(&tm, &number);
-                       date = approxidate_digit(date-1, &tm, &number);
+                       date = approxidate_digit(date-1, &tm, &number, time_sec);
                        touched = 1;
                        continue;
                }
index 1d9e530a84758e34d616690684c4842cd1af4cfc..5473493e10551633659d0727626ffc2273ef4f73 100644 (file)
@@ -246,6 +246,13 @@ static void merge_broken(struct diff_filepair *p,
 
        dp = diff_queue(outq, d->one, c->two);
        dp->score = p->score;
+       /*
+        * We will be one extra user of the same src side of the
+        * broken pair, if it was used as the rename source for other
+        * paths elsewhere.  Increment to mark that the path stays
+        * in the resulting tree.
+        */
+       d->one->rename_used++;
        diff_free_filespec_data(d->two);
        diff_free_filespec_data(c->one);
        free(d);
index 1fadd69f8809f91337a27b98f244a3cf7183b23f..c7256741cc2a28f333d6a9be5f12e248df99ed5e 100755 (executable)
@@ -1356,6 +1356,7 @@ sub patch_update_file {
                  $patch_mode_flavour{TARGET},
                  " [y,n,q,a,d,/$other,?]? ";
                my $line = prompt_single_character;
+               last unless defined $line;
                if ($line) {
                        if ($line =~ /^y/i) {
                                $hunk[$ix]{USE} = 1;
index 6cda2b5a601c54d138ab3126a25c59371f6f7188..2fc07acb0f242154fec868207cfd77f448929200 100755 (executable)
@@ -237,15 +237,18 @@ bisect_state() {
                check_expected_revs "$rev" ;;
        2,bad|*,good|*,skip)
                shift
-               eval=''
+               hash_list=''
                for rev in "$@"
                do
                        sha=$(git rev-parse --verify "$rev^{commit}") ||
                                die "$(eval_gettext "Bad rev input: \$rev")"
-                       eval="$eval bisect_write '$state' '$sha'; "
+                       hash_list="$hash_list $sha"
                done
-               eval "$eval"
-               check_expected_revs "$@" ;;
+               for rev in $hash_list
+               do
+                       bisect_write "$state" "$rev"
+               done
+               check_expected_revs $hash_list ;;
        *,bad)
                die "$(gettext "'git bisect bad' can take only one argument.")" ;;
        *)
index b763a4e2693a5f08977132513196e78951868d5b..dcecd857f159357ff7d79cde218895f43795d944 100644 (file)
@@ -212,8 +212,12 @@ extern char *gitbasename(char *);
 #endif
 
 #ifndef NO_OPENSSL
+#define __AVAILABILITY_MACROS_USES_AVAILABILITY 0
+#define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_6
 #include <openssl/ssl.h>
 #include <openssl/err.h>
+#undef MAC_OS_X_VERSION_MIN_REQUIRED
+#undef __AVAILABILITY_MACROS_USES_AVAILABILITY
 #endif
 
 /* On most systems <netdb.h> would have given us this, but
index 82c6feaa4640e993051bfbe57df593c0f012a9ba..3092ab356c765cd593d2a988d020665c8b626ea1 100755 (executable)
@@ -54,6 +54,7 @@ sub usage {
     --[no-]bcc              <str>  * Email Bcc:
     --subject               <str>  * Email "Subject:"
     --in-reply-to           <str>  * Email "In-Reply-To:"
+    --[no-]xmailer                 * Add "X-Mailer:" header (default).
     --[no-]annotate                * Review each patch that will be sent in an editor.
     --compose                      * Open an editor for introduction.
     --compose-encoding      <str>  * Encoding to assume for introduction.
@@ -146,10 +147,15 @@ sub format_2822_time {
 my $smtp;
 my $auth;
 
+# Regexes for RFC 2047 productions.
+my $re_token = qr/[^][()<>@,;:\\"\/?.= \000-\037\177-\377]+/;
+my $re_encoded_text = qr/[^? \000-\037\177-\377]+/;
+my $re_encoded_word = qr/=\?($re_token)\?($re_token)\?($re_encoded_text)\?=/;
+
 # Variables we fill in automatically, or via prompting:
 my (@to,$no_to,@initial_to,@cc,$no_cc,@initial_cc,@bcclist,$no_bcc,@xh,
        $initial_reply_to,$initial_subject,@files,
-       $author,$sender,$smtp_authpass,$annotate,$compose,$time);
+       $author,$sender,$smtp_authpass,$annotate,$use_xmailer,$compose,$time);
 
 my $envelope_sender;
 
@@ -221,7 +227,8 @@ sub do_edit {
     "signedoffcc" => [\$signed_off_by_cc, undef],      # Deprecated
     "validate" => [\$validate, 1],
     "multiedit" => [\$multiedit, undef],
-    "annotate" => [\$annotate, undef]
+    "annotate" => [\$annotate, undef],
+    "xmailer" => [\$use_xmailer, 1]
 );
 
 my %config_settings = (
@@ -322,6 +329,7 @@ sub signal_handler {
                    "8bit-encoding=s" => \$auto_8bit_encoding,
                    "compose-encoding=s" => \$compose_encoding,
                    "force" => \$force,
+                   "xmailer!" => \$use_xmailer,
         );
 
 usage() if $help;
@@ -917,15 +925,26 @@ sub make_message_id {
 
 sub unquote_rfc2047 {
        local ($_) = @_;
-       my $encoding;
-       s{=\?([^?]+)\?q\?(.*?)\?=}{
-               $encoding = $1;
-               my $e = $2;
-               $e =~ s/_/ /g;
-               $e =~ s/=([0-9A-F]{2})/chr(hex($1))/eg;
-               $e;
+       my $charset;
+       my $sep = qr/[ \t]+/;
+       s{$re_encoded_word(?:$sep$re_encoded_word)*}{
+               my @words = split $sep, $&;
+               foreach (@words) {
+                       m/$re_encoded_word/;
+                       $charset = $1;
+                       my $encoding = $2;
+                       my $text = $3;
+                       if ($encoding eq 'q' || $encoding eq 'Q') {
+                               $_ = $text;
+                               s/_/ /g;
+                               s/=([0-9A-F]{2})/chr(hex($1))/egi;
+                       } else {
+                               # other encodings not supported yet
+                       }
+               }
+               join '', @words;
        }eg;
-       return wantarray ? ($_, $encoding) : $_;
+       return wantarray ? ($_, $charset) : $_;
 }
 
 sub quote_rfc2047 {
@@ -938,10 +957,8 @@ sub quote_rfc2047 {
 
 sub is_rfc2047_quoted {
        my $s = shift;
-       my $token = qr/[^][()<>@,;:"\/?.= \000-\037\177-\377]+/;
-       my $encoded_text = qr/[!->@-~]+/;
        length($s) <= 75 &&
-       $s =~ m/^(?:"[[:ascii:]]*"|=\?$token\?$token\?$encoded_text\?=)$/o;
+       $s =~ m/^(?:"[[:ascii:]]*"|$re_encoded_word)$/o;
 }
 
 sub subject_needs_rfc2047_quoting {
@@ -1167,8 +1184,10 @@ sub send_message {
 Subject: $subject
 Date: $date
 Message-Id: $message_id
-X-Mailer: git-send-email $gitversion
 ";
+       if ($use_xmailer) {
+               $header .= "X-Mailer: git-send-email $gitversion\n";
+       }
        if ($reply_to) {
 
                $header .= "In-Reply-To: $reply_to\n";
index b6e2186cef0fcddc7c7b82378b07941d9f671a92..60f8814cc52fdfea17be989228a56a951cc0e867 100755 (executable)
@@ -115,7 +115,7 @@ sub _req_svn {
        $_before, $_after,
        $_merge, $_strategy, $_preserve_merges, $_dry_run, $_parents, $_local,
        $_prefix, $_no_checkout, $_url, $_verbose,
-       $_commit_url, $_tag, $_merge_info, $_interactive);
+       $_commit_url, $_tag, $_merge_info, $_interactive, $_set_svn_props);
 
 # This is a refactoring artifact so Git::SVN can get at this git-svn switch.
 sub opt_prefix { return $_prefix || '' }
@@ -193,6 +193,7 @@ sub _req_svn {
                          'dry-run|n' => \$_dry_run,
                          'fetch-all|all' => \$_fetch_all,
                          'commit-url=s' => \$_commit_url,
+                         'set-svn-props=s' => \$_set_svn_props,
                          'revision|r=i' => \$_revision,
                          'no-rebase' => \$_no_rebase,
                          'mergeinfo=s' => \$_merge_info,
@@ -228,6 +229,9 @@ sub _req_svn {
         'propget' => [ \&cmd_propget,
                       'Print the value of a property on a file or directory',
                       { 'revision|r=i' => \$_revision } ],
+        'propset' => [ \&cmd_propset,
+                      'Set the value of a property on a file or directory - will be set on commit',
+                      {} ],
         'proplist' => [ \&cmd_proplist,
                       'List all properties of a file or directory',
                       { 'revision|r=i' => \$_revision } ],
@@ -1376,6 +1380,49 @@ sub cmd_propget {
        print $props->{$prop} . "\n";
 }
 
+# cmd_propset (PROPNAME, PROPVAL, PATH)
+# ------------------------
+# Adjust the SVN property PROPNAME to PROPVAL for PATH.
+sub cmd_propset {
+       my ($propname, $propval, $path) = @_;
+       $path = '.' if not defined $path;
+       $path = $cmd_dir_prefix . $path;
+       usage(1) if not defined $propname;
+       usage(1) if not defined $propval;
+       my $file = basename($path);
+       my $dn = dirname($path);
+       my $cur_props = Git::SVN::Editor::check_attr( "svn-properties", $path );
+       my @new_props;
+       if (!$cur_props || $cur_props eq "unset" || $cur_props eq "" || $cur_props eq "set") {
+               push @new_props, "$propname=$propval";
+       } else {
+               # TODO: handle combining properties better
+               my @props = split(/;/, $cur_props);
+               my $replaced_prop;
+               foreach my $prop (@props) {
+                       # Parse 'name=value' syntax and set the property.
+                       if ($prop =~ /([^=]+)=(.*)/) {
+                               my ($n,$v) = ($1,$2);
+                               if ($n eq $propname) {
+                                       $v = $propval;
+                                       $replaced_prop = 1;
+                               }
+                               push @new_props, "$n=$v";
+                       }
+               }
+               if (!$replaced_prop) {
+                       push @new_props, "$propname=$propval";
+               }
+       }
+       my $attrfile = "$dn/.gitattributes";
+       open my $attrfh, '>>', $attrfile or die "Can't open $attrfile: $!\n";
+       # TODO: don't simply append here if $file already has svn-properties
+       my $new_props = join(';', @new_props);
+       print $attrfh "$file svn-properties=$new_props\n" or
+               die "write to $attrfile: $!\n";
+       close $attrfh or die "close $attrfile: $!\n";
+}
+
 # cmd_proplist (PATH)
 # -------------------
 # Print the list of SVN properties for PATH.
index 70bcc7a4e533bb04e8c515e8831a75ec93d2d066..4dfe4c25d76649e982858c69e6bc7ff1ec32f645 100644 (file)
 #include "credential.h"
 #include "exec_cmd.h"
 #include "run-command.h"
+#include "parse-options.h"
 #ifdef NO_OPENSSL
 typedef void *SSL;
 #endif
+#ifdef USE_CURL_FOR_IMAP_SEND
+#include "http.h"
+#endif
+
+static int verbosity;
+static int use_curl; /* strictly opt in */
 
-static const char imap_send_usage[] = "git imap-send < <mbox>";
+static const char * const imap_send_usage[] = { "git imap-send [-v] [-q] [--[no-]curl] < <mbox>", NULL };
+
+static struct option imap_send_options[] = {
+       OPT__VERBOSITY(&verbosity),
+       OPT_BOOL(0, "curl", &use_curl, "use libcurl to communicate with the IMAP server"),
+       OPT_END()
+};
 
 #undef DRV_OK
 #define DRV_OK          0
@@ -38,8 +51,6 @@ static const char imap_send_usage[] = "git imap-send < <mbox>";
 #define DRV_BOX_BAD     -2
 #define DRV_STORE_BAD   -3
 
-static int Verbose, Quiet;
-
 __attribute__((format (printf, 1, 2)))
 static void imap_info(const char *, ...);
 __attribute__((format (printf, 1, 2)))
@@ -418,7 +429,7 @@ static int buffer_gets(struct imap_buffer *b, char **s)
                        if (b->buf[b->offset + 1] == '\n') {
                                b->buf[b->offset] = 0;  /* terminate the string */
                                b->offset += 2; /* next line */
-                               if (Verbose)
+                               if (0 < verbosity)
                                        puts(*s);
                                return 0;
                        }
@@ -433,7 +444,7 @@ static void imap_info(const char *msg, ...)
 {
        va_list va;
 
-       if (!Quiet) {
+       if (0 <= verbosity) {
                va_start(va, msg);
                vprintf(msg, va);
                va_end(va);
@@ -445,7 +456,7 @@ static void imap_warn(const char *msg, ...)
 {
        va_list va;
 
-       if (Quiet < 2) {
+       if (-2 < verbosity) {
                va_start(va, msg);
                vfprintf(stderr, msg, va);
                va_end(va);
@@ -522,7 +533,7 @@ static struct imap_cmd *issue_imap_cmd(struct imap_store *ctx,
                                  cmd->tag, cmd->cmd, cmd->cb.dlen,
                                  CAP(LITERALPLUS) ? "+" : "");
 
-       if (Verbose) {
+       if (0 < verbosity) {
                if (imap->num_in_progress)
                        printf("(%d in progress) ", imap->num_in_progress);
                if (!starts_with(cmd->cmd, "LOGIN"))
@@ -1338,26 +1349,166 @@ static void git_imap_config(void)
        git_config_get_string("imap.authmethod", &server.auth_method);
 }
 
-int main(int argc, char **argv)
+static int append_msgs_to_imap(struct imap_server_conf *server,
+                              struct strbuf* all_msgs, int total)
 {
-       struct strbuf all_msgs = STRBUF_INIT;
        struct strbuf msg = STRBUF_INIT;
        struct imap_store *ctx = NULL;
        int ofs = 0;
        int r;
-       int total, n = 0;
+       int n = 0;
+
+       ctx = imap_open_store(server, server->folder);
+       if (!ctx) {
+               fprintf(stderr, "failed to open store\n");
+               return 1;
+       }
+       ctx->name = server->folder;
+
+       fprintf(stderr, "sending %d message%s\n", total, (total != 1) ? "s" : "");
+       while (1) {
+               unsigned percent = n * 100 / total;
+
+               fprintf(stderr, "%4u%% (%d/%d) done\r", percent, n, total);
+
+               if (!split_msg(all_msgs, &msg, &ofs))
+                       break;
+               if (server->use_html)
+                       wrap_in_html(&msg);
+               r = imap_store_msg(ctx, &msg);
+               if (r != DRV_OK)
+                       break;
+               n++;
+       }
+       fprintf(stderr, "\n");
+
+       imap_close_store(ctx);
+
+       return 0;
+}
+
+#ifdef USE_CURL_FOR_IMAP_SEND
+static CURL *setup_curl(struct imap_server_conf *srvc)
+{
+       CURL *curl;
+       struct strbuf path = STRBUF_INIT;
+
+       if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK)
+               die("curl_global_init failed");
+
+       curl = curl_easy_init();
+
+       if (!curl)
+               die("curl_easy_init failed");
+
+       curl_easy_setopt(curl, CURLOPT_USERNAME, server.user);
+       curl_easy_setopt(curl, CURLOPT_PASSWORD, server.pass);
+
+       strbuf_addstr(&path, server.host);
+       if (!path.len || path.buf[path.len - 1] != '/')
+               strbuf_addch(&path, '/');
+       strbuf_addstr(&path, server.folder);
+
+       curl_easy_setopt(curl, CURLOPT_URL, path.buf);
+       strbuf_release(&path);
+       curl_easy_setopt(curl, CURLOPT_PORT, server.port);
+
+       if (server.auth_method) {
+               struct strbuf auth = STRBUF_INIT;
+               strbuf_addstr(&auth, "AUTH=");
+               strbuf_addstr(&auth, server.auth_method);
+               curl_easy_setopt(curl, CURLOPT_LOGIN_OPTIONS, auth.buf);
+               strbuf_release(&auth);
+       }
+
+       if (server.use_ssl)
+               curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
+
+       curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, server.ssl_verify);
+       curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, server.ssl_verify);
+
+       curl_easy_setopt(curl, CURLOPT_READFUNCTION, fread_buffer);
+
+       curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
+
+       if (0 < verbosity)
+               curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+
+       return curl;
+}
+
+static int curl_append_msgs_to_imap(struct imap_server_conf *server,
+                                   struct strbuf* all_msgs, int total) {
+       int ofs = 0;
+       int n = 0;
+       struct buffer msgbuf = { STRBUF_INIT, 0 };
+       CURL *curl;
+       CURLcode res = CURLE_OK;
+
+       curl = setup_curl(server);
+       curl_easy_setopt(curl, CURLOPT_READDATA, &msgbuf);
+
+       fprintf(stderr, "sending %d message%s\n", total, (total != 1) ? "s" : "");
+       while (1) {
+               unsigned percent = n * 100 / total;
+               int prev_len;
+
+               fprintf(stderr, "%4u%% (%d/%d) done\r", percent, n, total);
+
+               prev_len = msgbuf.buf.len;
+               if (!split_msg(all_msgs, &msgbuf.buf, &ofs))
+                       break;
+               if (server->use_html)
+                       wrap_in_html(&msgbuf.buf);
+               lf_to_crlf(&msgbuf.buf);
+
+               curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE,
+                                (curl_off_t)(msgbuf.buf.len-prev_len));
+
+               res = curl_easy_perform(curl);
+
+               if(res != CURLE_OK) {
+                       fprintf(stderr, "curl_easy_perform() failed: %s\n",
+                                       curl_easy_strerror(res));
+                       break;
+               }
+
+               n++;
+       }
+       fprintf(stderr, "\n");
+
+       curl_easy_cleanup(curl);
+       curl_global_cleanup();
+
+       return 0;
+}
+#endif
+
+int main(int argc, char **argv)
+{
+       struct strbuf all_msgs = STRBUF_INIT;
+       int total;
        int nongit_ok;
 
        git_extract_argv0_path(argv[0]);
 
        git_setup_gettext();
 
-       if (argc != 1)
-               usage(imap_send_usage);
-
        setup_git_directory_gently(&nongit_ok);
        git_imap_config();
 
+       argc = parse_options(argc, (const char **)argv, "", imap_send_options, imap_send_usage, 0);
+
+       if (argc)
+               usage_with_options(imap_send_usage, imap_send_options);
+
+#ifndef USE_CURL_FOR_IMAP_SEND
+       if (use_curl) {
+               warning("--use-curl not supported in this build");
+               use_curl = 0;
+       }
+#endif
+
        if (!server.port)
                server.port = server.use_ssl ? 993 : 143;
 
@@ -1391,29 +1542,14 @@ int main(int argc, char **argv)
        }
 
        /* write it to the imap server */
-       ctx = imap_open_store(&server, server.folder);
-       if (!ctx) {
-               fprintf(stderr, "failed to open store\n");
-               return 1;
-       }
-
-       fprintf(stderr, "sending %d message%s\n", total, (total != 1) ? "s" : "");
-       while (1) {
-               unsigned percent = n * 100 / total;
 
-               fprintf(stderr, "%4u%% (%d/%d) done\r", percent, n, total);
-               if (!split_msg(&all_msgs, &msg, &ofs))
-                       break;
-               if (server.use_html)
-                       wrap_in_html(&msg);
-               r = imap_store_msg(ctx, &msg);
-               if (r != DRV_OK)
-                       break;
-               n++;
-       }
-       fprintf(stderr, "\n");
+       if (server.tunnel)
+               return append_msgs_to_imap(&server, &all_msgs, total);
 
-       imap_close_store(ctx);
+#ifdef USE_CURL_FOR_IMAP_SEND
+       if (use_curl)
+               return curl_append_msgs_to_imap(&server, &all_msgs, total);
+#endif
 
-       return 0;
+       return append_msgs_to_imap(&server, &all_msgs, total);
 }
index 2910becd6c65b66670215aefdf08e1933895aa39..2a139b6ced68809f3a324f493325ec62c3a44044 100644 (file)
@@ -157,7 +157,7 @@ void mark_edges_uninteresting(struct rev_info *revs, show_edge_fn show_edge)
 
                if (commit->object.flags & UNINTERESTING) {
                        mark_tree_uninteresting(commit->tree);
-                       if (revs->edge_hint && !(commit->object.flags & SHOWN)) {
+                       if (revs->edge_hint_aggressive && !(commit->object.flags & SHOWN)) {
                                commit->object.flags |= SHOWN;
                                show_edge(commit);
                        }
@@ -165,7 +165,7 @@ void mark_edges_uninteresting(struct rev_info *revs, show_edge_fn show_edge)
                }
                mark_edge_parents_uninteresting(commit, revs, show_edge);
        }
-       if (revs->edge_hint) {
+       if (revs->edge_hint_aggressive) {
                for (i = 0; i < revs->cmdline.nr; i++) {
                        struct object *obj = revs->cmdline.rev[i].item;
                        struct commit *commit = (struct commit *)obj;
index 4f16ee78ce3dbc263a762a8800dfe9ddfcfaecd5..988927775169487df7677a17465b512a567488dd 100644 (file)
@@ -128,9 +128,17 @@ static int lock_file(struct lock_file *lk, const char *path, int flags)
                    path);
        }
 
-       strbuf_add(&lk->filename, path, pathlen);
-       if (!(flags & LOCK_NO_DEREF))
-               resolve_symlink(&lk->filename);
+       if (flags & LOCK_NO_DEREF) {
+               strbuf_add_absolute_path(&lk->filename, path);
+       } else {
+               struct strbuf resolved_path = STRBUF_INIT;
+
+               strbuf_add(&resolved_path, path, pathlen);
+               resolve_symlink(&resolved_path);
+               strbuf_add_absolute_path(&lk->filename, resolved_path.buf);
+               strbuf_release(&resolved_path);
+       }
+
        strbuf_addstr(&lk->filename, LOCK_SUFFIX);
        lk->fd = open(lk->filename.buf, O_RDWR | O_CREAT | O_EXCL, 0666);
        if (lk->fd < 0) {
index 25c067e4a71f1ed2c5d4971d41ab6b4e1108e9e4..771f5e21b09aac6976297b8a6e9028f90787a764 100644 (file)
@@ -1901,7 +1901,7 @@ int merge_recursive(struct merge_options *o,
        }
 
        if (!ca) {
-               ca = get_merge_bases(h1, h2, 1);
+               ca = get_merge_bases(h1, h2);
                ca = reverse_commit_list(ca);
        }
 
index 7eb9d7a0103ad8447e4fde50976a5669a75d8cdd..109ff4ef410b77a814cca282f728f1b88948e4ec 100644 (file)
@@ -594,7 +594,7 @@ int notes_merge(struct notes_merge_options *o,
        assert(local && remote);
 
        /* Find merge bases */
-       bases = get_merge_bases(local, remote, 1);
+       bases = get_merge_bases(local, remote);
        if (!bases) {
                base_sha1 = null_sha1;
                base_tree_sha1 = EMPTY_TREE_SHA1_BIN;
index 34e8af966c4a97bd3fafd5d9cfecbfb982f78897..4088f13e723a51a6e1cee0c616a7c279a780461d 100644 (file)
@@ -288,6 +288,40 @@ sub apply_autoprops {
        }
 }
 
+sub check_attr {
+       my ($attr,$path) = @_;
+       my $val = command_oneline("check-attr", $attr, "--", $path);
+       if ($val) { $val =~ s/^[^:]*:\s*[^:]*:\s*(.*)\s*$/$1/; }
+       return $val;
+}
+
+sub apply_manualprops {
+       my ($self, $file, $fbat) = @_;
+       my $pending_properties = check_attr( "svn-properties", $file );
+       if ($pending_properties eq "") { return; }
+       # Parse the list of properties to set.
+       my @props = split(/;/, $pending_properties);
+       # TODO: get existing properties to compare to
+       # - this fails for add so currently not done
+       # my $existing_props = ::get_svnprops($file);
+       my $existing_props = {};
+       # TODO: caching svn properties or storing them in .gitattributes
+       # would make that faster
+       foreach my $prop (@props) {
+               # Parse 'name=value' syntax and set the property.
+               if ($prop =~ /([^=]+)=(.*)/) {
+                       my ($n,$v) = ($1,$2);
+                       for ($n, $v) {
+                               s/^\s+//; s/\s+$//;
+                       }
+                       my $existing = $existing_props->{$n};
+                       if (!defined($existing) || $existing ne $v) {
+                           $self->change_file_prop($fbat, $n, $v);
+                       }
+               }
+       }
+}
+
 sub A {
        my ($self, $m, $deletions) = @_;
        my ($dir, $file) = split_path($m->{file_b});
@@ -296,6 +330,7 @@ sub A {
                                        undef, -1);
        print "\tA\t$m->{file_b}\n" unless $::_q;
        $self->apply_autoprops($file, $fbat);
+       $self->apply_manualprops($m->{file_b}, $fbat);
        $self->chg_file($fbat, $m);
        $self->close_file($fbat,undef,$self->{pool});
 }
@@ -311,6 +346,7 @@ sub C {
        my $fbat = $self->add_file($self->repo_path($m->{file_b}), $pbat,
                                $upa, $self->{r});
        print "\tC\t$m->{file_a} => $m->{file_b}\n" unless $::_q;
+       $self->apply_manualprops($m->{file_b}, $fbat);
        $self->chg_file($fbat, $m);
        $self->close_file($fbat,undef,$self->{pool});
 }
@@ -333,6 +369,7 @@ sub R {
                                $upa, $self->{r});
        print "\tR\t$m->{file_a} => $m->{file_b}\n" unless $::_q;
        $self->apply_autoprops($file, $fbat);
+       $self->apply_manualprops($m->{file_b}, $fbat);
        $self->chg_file($fbat, $m);
        $self->close_file($fbat,undef,$self->{pool});
 
@@ -348,6 +385,7 @@ sub M {
        my $fbat = $self->open_file($self->repo_path($m->{file_b}),
                                $pbat,$self->{r},$self->{pool});
        print "\t$m->{chg}\t$m->{file_b}\n" unless $::_q;
+       $self->apply_manualprops($m->{file_b}, $fbat);
        $self->chg_file($fbat, $m);
        $self->close_file($fbat,undef,$self->{pool});
 }
diff --git a/refs.c b/refs.c
index 5fcacc6c41e6c7033367cc9c4cf7c18b33eea286..ed3b2cb405cc576f16e5b94d83683953b94e1e89 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -2334,7 +2334,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
                        struct strbuf err = STRBUF_INIT;
                        unable_to_lock_message(ref_file, errno, &err);
                        error("%s", err.buf);
-                       strbuf_reset(&err);
+                       strbuf_release(&err);
                        goto error_return;
                }
        }
index ae4ecfa1163137f7372fd02a51dc8a93319d218f..5b9c6931c1e66adb03f5d505aa8dd57169452eae 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -1631,6 +1631,27 @@ void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
        }
 }
 
+static void set_merge(struct branch *ret)
+{
+       char *ref;
+       unsigned char sha1[20];
+       int i;
+
+       ret->merge = xcalloc(ret->merge_nr, sizeof(*ret->merge));
+       for (i = 0; i < ret->merge_nr; i++) {
+               ret->merge[i] = xcalloc(1, sizeof(**ret->merge));
+               ret->merge[i]->src = xstrdup(ret->merge_name[i]);
+               if (!remote_find_tracking(ret->remote, ret->merge[i]) ||
+                   strcmp(ret->remote_name, "."))
+                       continue;
+               if (dwim_ref(ret->merge_name[i], strlen(ret->merge_name[i]),
+                            sha1, &ref) == 1)
+                       ret->merge[i]->dst = ref;
+               else
+                       ret->merge[i]->dst = xstrdup(ret->merge_name[i]);
+       }
+}
+
 struct branch *branch_get(const char *name)
 {
        struct branch *ret;
@@ -1642,17 +1663,8 @@ struct branch *branch_get(const char *name)
                ret = make_branch(name, 0);
        if (ret && ret->remote_name) {
                ret->remote = remote_get(ret->remote_name);
-               if (ret->merge_nr) {
-                       int i;
-                       ret->merge = xcalloc(ret->merge_nr, sizeof(*ret->merge));
-                       for (i = 0; i < ret->merge_nr; i++) {
-                               ret->merge[i] = xcalloc(1, sizeof(**ret->merge));
-                               ret->merge[i]->src = xstrdup(ret->merge_name[i]);
-                               if (remote_find_tracking(ret->remote, ret->merge[i])
-                                   && !strcmp(ret->remote_name, "."))
-                                       ret->merge[i]->dst = xstrdup(ret->merge_name[i]);
-                       }
-               }
+               if (ret->merge_nr)
+                       set_merge(ret);
        }
        return ret;
 }
index 75dda928ea6be1dacd2fbeba5c0ce207ea46dd25..86406a26a2d4599ea401d1faa9a817cadb3b7bcd 100644 (file)
@@ -1441,7 +1441,7 @@ static void prepare_show_merge(struct rev_info *revs)
        other = lookup_commit_or_die(sha1, "MERGE_HEAD");
        add_pending_object(revs, &head->object, "HEAD");
        add_pending_object(revs, &other->object, "MERGE_HEAD");
-       bases = get_merge_bases(head, other, 1);
+       bases = get_merge_bases(head, other);
        add_rev_cmdline_list(revs, bases, REV_CMD_MERGE_BASE, UNINTERESTING | BOTTOM);
        add_pending_commit_list(revs, bases, UNINTERESTING | BOTTOM);
        free_commit_list(bases);
@@ -1546,7 +1546,7 @@ int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsi
                                     : lookup_commit_reference(b_obj->sha1));
                                if (!a || !b)
                                        goto missing;
-                               exclude = get_merge_bases(a, b, 1);
+                               exclude = get_merge_bases(a, b);
                                add_rev_cmdline_list(revs, exclude,
                                                     REV_CMD_MERGE_BASE,
                                                     flags_exclude);
@@ -1853,6 +1853,12 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
                revs->tree_objects = 1;
                revs->blob_objects = 1;
                revs->edge_hint = 1;
+       } else if (!strcmp(arg, "--objects-edge-aggressive")) {
+               revs->tag_objects = 1;
+               revs->tree_objects = 1;
+               revs->blob_objects = 1;
+               revs->edge_hint = 1;
+               revs->edge_hint_aggressive = 1;
        } else if (!strcmp(arg, "--verify-objects")) {
                revs->tag_objects = 1;
                revs->tree_objects = 1;
index 9cb5adc4ea25bfdc37ced8b8a98b1fd58661c9e9..033a24460e71b723f95ef91f4b6f0dbfd8c2c390 100644 (file)
@@ -93,6 +93,7 @@ struct rev_info {
                        blob_objects:1,
                        verify_objects:1,
                        edge_hint:1,
+                       edge_hint_aggressive:1,
                        limited:1,
                        unpacked:1,
                        boundary:2,
index 949cb61aa0d681e30b7e8199ef9e31ff0caee089..25947d7df9dd3af6e665d5d5eb63ec970617aef1 100644 (file)
@@ -47,6 +47,7 @@ static int pack_objects(int fd, struct ref *refs, struct sha1_array *extra, stru
                NULL,
                NULL,
                NULL,
+               NULL,
        };
        struct child_process po = CHILD_PROCESS_INIT;
        int i;
@@ -60,6 +61,8 @@ static int pack_objects(int fd, struct ref *refs, struct sha1_array *extra, stru
                argv[i++] = "-q";
        if (args->progress)
                argv[i++] = "--progress";
+       if (is_repository_shallow())
+               argv[i++] = "--shallow";
        po.argv = argv;
        po.in = -1;
        po.out = args->stateless_rpc ? -1 : fd;
index cb88170252a26c37d90f5c03263136439ec60e54..cf2a83b14381ae02e737e6135561aab401f1f7e8 100644 (file)
@@ -993,7 +993,7 @@ int get_sha1_mb(const char *name, unsigned char *sha1)
        two = lookup_commit_reference_gently(sha1_tmp, 0);
        if (!two)
                return -1;
-       mbs = get_merge_bases(one, two, 1);
+       mbs = get_merge_bases(one, two);
        if (!mbs || mbs->next)
                st = -1;
        else {
index 0346e74a47d14ef13757cadfe2a0de778b5c4cc4..88cafd4a70b8179a4e911c18704fb4ab0f2a21f5 100644 (file)
--- a/strbuf.c
+++ b/strbuf.c
@@ -229,7 +229,8 @@ static void add_lines(struct strbuf *out,
                const char *next = memchr(buf, '\n', size);
                next = next ? (next + 1) : (buf + size);
 
-               prefix = (prefix2 && buf[0] == '\n') ? prefix2 : prefix1;
+               prefix = ((prefix2 && (buf[0] == '\n' || buf[0] == '\t'))
+                         ? prefix2 : prefix1);
                strbuf_addstr(out, prefix);
                strbuf_add(out, buf, next - buf);
                size -= next - buf;
index 0690dc50d07e9fd30242e41afe149476a34fc105..d37d400b2227c58f352795b9f6ede20a9cd54631 100644 (file)
@@ -301,7 +301,7 @@ static int prepare_submodule_summary(struct rev_info *rev, const char *path,
        left->object.flags |= SYMMETRIC_LEFT;
        add_pending_object(rev, &left->object, path);
        add_pending_object(rev, &right->object, path);
-       merge_bases = get_merge_bases(left, right, 1);
+       merge_bases = get_merge_bases(left, right);
        if (merge_bases) {
                if (merge_bases->item == left)
                        *fast_forward = 1;
index e53cf6d36d573c3d758f0005c95aa4a364df82b1..fac0986134fefa5c61763f4c56873da8ba28072a 100755 (executable)
@@ -82,4 +82,7 @@ check_approxidate 'Jun 6, 5AM' '2009-06-06 05:00:00'
 check_approxidate '5AM Jun 6' '2009-06-06 05:00:00'
 check_approxidate '6AM, June 7, 2009' '2009-06-07 06:00:00'
 
+check_approxidate '2008-12-01' '2008-12-01 19:20:00'
+check_approxidate '2009-12-01' '2009-12-01 19:20:00'
+
 test_done
index 0333dd9875af9fbbad04cf05eb9f0e9fe37ae182..29e91d861cbd6473d80c7343a0e292b010d83173 100755 (executable)
@@ -432,4 +432,10 @@ test_expect_success '-c with changed comment char' '
        test_cmp expect actual
 '
 
+test_expect_success 'avoid SP-HT sequence in commented line' '
+       printf "#\tone\n#\n# two\n" >expect &&
+       printf "\tone\n\ntwo\n" | git stripspace -c >actual &&
+       test_cmp expect actual
+'
+
 test_done
index 067f4c6e52abe86e952367d8cf576a80aa5139bd..601d02d71f735b4247528cc45b0ea055299ee7a0 100755 (executable)
@@ -22,7 +22,7 @@ generate_expected_cache_tree_rec () {
        # ls-files might have foo/bar, foo/bar/baz, and foo/bar/quux
        # We want to count only foo because it's the only direct child
        subtrees=$(git ls-files|grep /|cut -d / -f 1|uniq) &&
-       subtree_count=$(echo "$subtrees"|awk -v c=0 '$1 {++c} END {print c}') &&
+       subtree_count=$(echo "$subtrees"|awk -v c=0 '$1 != "" {++c} END {print c}') &&
        entries=$(git ls-files|wc -l) &&
        printf "SHA $dir (%d entries, %d subtrees)\n" "$entries" "$subtree_count" &&
        for subtree in $subtrees
index 7b4707b776f493ad4b2df9877926dd420e94ca81..6805b9e6bb5b7e6a6b6b9546e96023ebeb557bd0 100755 (executable)
@@ -619,6 +619,52 @@ test_expect_success 'stdin update/create/verify combination works' '
        test_must_fail git rev-parse --verify -q $c
 '
 
+test_expect_success 'stdin verify succeeds for correct value' '
+       git rev-parse $m >expect &&
+       echo "verify $m $m" >stdin &&
+       git update-ref --stdin <stdin &&
+       git rev-parse $m >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'stdin verify succeeds for missing reference' '
+       echo "verify refs/heads/missing $Z" >stdin &&
+       git update-ref --stdin <stdin &&
+       test_must_fail git rev-parse --verify -q refs/heads/missing
+'
+
+test_expect_success 'stdin verify treats no value as missing' '
+       echo "verify refs/heads/missing" >stdin &&
+       git update-ref --stdin <stdin &&
+       test_must_fail git rev-parse --verify -q refs/heads/missing
+'
+
+test_expect_success 'stdin verify fails for wrong value' '
+       git rev-parse $m >expect &&
+       echo "verify $m $m~1" >stdin &&
+       test_must_fail git update-ref --stdin <stdin &&
+       git rev-parse $m >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'stdin verify fails for mistaken null value' '
+       git rev-parse $m >expect &&
+       echo "verify $m $Z" >stdin &&
+       test_must_fail git update-ref --stdin <stdin &&
+       git rev-parse $m >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'stdin verify fails for mistaken empty value' '
+       M=$(git rev-parse $m) &&
+       test_when_finished "git update-ref $m $M" &&
+       git rev-parse $m >expect &&
+       echo "verify $m" >stdin &&
+       test_must_fail git update-ref --stdin <stdin &&
+       git rev-parse $m >actual &&
+       test_cmp expect actual
+'
+
 test_expect_success 'stdin update refs works with identity updates' '
        cat >stdin <<-EOF &&
        update $a $m $m
@@ -938,6 +984,52 @@ test_expect_success 'stdin -z update/create/verify combination works' '
        test_must_fail git rev-parse --verify -q $c
 '
 
+test_expect_success 'stdin -z verify succeeds for correct value' '
+       git rev-parse $m >expect &&
+       printf $F "verify $m" "$m" >stdin &&
+       git update-ref -z --stdin <stdin &&
+       git rev-parse $m >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'stdin -z verify succeeds for missing reference' '
+       printf $F "verify refs/heads/missing" "$Z" >stdin &&
+       git update-ref -z --stdin <stdin &&
+       test_must_fail git rev-parse --verify -q refs/heads/missing
+'
+
+test_expect_success 'stdin -z verify treats no value as missing' '
+       printf $F "verify refs/heads/missing" "" >stdin &&
+       git update-ref -z --stdin <stdin &&
+       test_must_fail git rev-parse --verify -q refs/heads/missing
+'
+
+test_expect_success 'stdin -z verify fails for wrong value' '
+       git rev-parse $m >expect &&
+       printf $F "verify $m" "$m~1" >stdin &&
+       test_must_fail git update-ref -z --stdin <stdin &&
+       git rev-parse $m >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'stdin -z verify fails for mistaken null value' '
+       git rev-parse $m >expect &&
+       printf $F "verify $m" "$Z" >stdin &&
+       test_must_fail git update-ref -z --stdin <stdin &&
+       git rev-parse $m >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'stdin -z verify fails for mistaken empty value' '
+       M=$(git rev-parse $m) &&
+       test_when_finished "git update-ref $m $M" &&
+       git rev-parse $m >expect &&
+       printf $F "verify $m" "" >stdin &&
+       test_must_fail git update-ref -z --stdin <stdin &&
+       git rev-parse $m >actual &&
+       test_cmp expect actual
+'
+
 test_expect_success 'stdin -z update refs works with identity updates' '
        printf $F "update $a" "$m" "$m" "update $b" "$m" "$m" "update $c" "$Z" "" >stdin &&
        git update-ref -z --stdin <stdin &&
index 1f04b8aa3ff925f469ffa60ce47f9d5659b9acaa..cfb32b62420dc162e79aaea29a36f7d78f3353f5 100755 (executable)
@@ -349,6 +349,21 @@ dot-backslash-case .\\\\.GIT\\\\foobar
 dotgit-case-backslash .git\\\\foobar
 EOF
 
+test_expect_success 'fsck allows .Ňit' '
+       (
+               git init not-dotgit &&
+               cd not-dotgit &&
+               echo content >file &&
+               git add file &&
+               git commit -m base &&
+               blob=$(git rev-parse :file) &&
+               printf "100644 blob $blob\t.\\305\\207it" >tree &&
+               tree=$(git mktree <tree) &&
+               git fsck 2>err &&
+               test_line_count = 0 err
+       )
+'
+
 # create a static test repo which is broken by omitting
 # one particular object ($1, which is looked up via rev-parse
 # in the new repository).
index f171a5578b6b81e4d7cb03ef0b6b9272ef610ffc..a12afe93f32948dd994d55418ed93485757d2ba8 100755 (executable)
@@ -10,202 +10,212 @@ rather than the tracked path.'
 
 . ./test-lib.sh
 
-test_expect_success \
-'preparation' '
-mkdir asubdir &&
-echo tree1path0 >path0 &&
-echo tree1path1 >path1 &&
-echo tree1path3 >path3 &&
-echo tree1path4 >path4 &&
-echo tree1asubdir/path5 >asubdir/path5 &&
-git update-index --add path0 path1 path3 path4 asubdir/path5 &&
-t1=$(git write-tree) &&
-rm -f path* .merge_* out .git/index &&
-echo tree2path0 >path0 &&
-echo tree2path1 >path1 &&
-echo tree2path2 >path2 &&
-echo tree2path4 >path4 &&
-git update-index --add path0 path1 path2 path4 &&
-t2=$(git write-tree) &&
-rm -f path* .merge_* out .git/index &&
-echo tree2path0 >path0 &&
-echo tree3path1 >path1 &&
-echo tree3path2 >path2 &&
-echo tree3path3 >path3 &&
-git update-index --add path0 path1 path2 path3 &&
-t3=$(git write-tree)'
-
-test_expect_success \
-'checkout one stage 0 to temporary file' '
-rm -f path* .merge_* out .git/index &&
-git read-tree $t1 &&
-git checkout-index --temp -- path1 >out &&
-test_line_count = 1 out &&
-test $(cut "-d " -f2 out) = path1 &&
-p=$(cut "-d    " -f1 out) &&
-test -f $p &&
-test $(cat $p) = tree1path1'
-
-test_expect_success \
-'checkout all stage 0 to temporary files' '
-rm -f path* .merge_* out .git/index &&
-git read-tree $t1 &&
-git checkout-index -a --temp >out &&
-test_line_count = 5 out &&
-for f in path0 path1 path3 path4 asubdir/path5
-do
-       test $(grep $f out | cut "-d    " -f2) = $f &&
-       p=$(grep $f out | cut "-d       " -f1) &&
+test_expect_success 'setup' '
+       mkdir asubdir &&
+       echo tree1path0 >path0 &&
+       echo tree1path1 >path1 &&
+       echo tree1path3 >path3 &&
+       echo tree1path4 >path4 &&
+       echo tree1asubdir/path5 >asubdir/path5 &&
+       git update-index --add path0 path1 path3 path4 asubdir/path5 &&
+       t1=$(git write-tree) &&
+       rm -f path* .merge_* actual .git/index &&
+       echo tree2path0 >path0 &&
+       echo tree2path1 >path1 &&
+       echo tree2path2 >path2 &&
+       echo tree2path4 >path4 &&
+       git update-index --add path0 path1 path2 path4 &&
+       t2=$(git write-tree) &&
+       rm -f path* .merge_* actual .git/index &&
+       echo tree2path0 >path0 &&
+       echo tree3path1 >path1 &&
+       echo tree3path2 >path2 &&
+       echo tree3path3 >path3 &&
+       git update-index --add path0 path1 path2 path3 &&
+       t3=$(git write-tree)
+'
+
+test_expect_success 'checkout one stage 0 to temporary file' '
+       rm -f path* .merge_* actual .git/index &&
+       git read-tree $t1 &&
+       git checkout-index --temp -- path1 >actual &&
+       test_line_count = 1 actual &&
+       test $(cut "-d  " -f2 actual) = path1 &&
+       p=$(cut "-d     " -f1 actual) &&
        test -f $p &&
-       test $(cat $p) = tree1$f
-done'
-
-test_expect_success \
-'prepare 3-way merge' '
-rm -f path* .merge_* out .git/index &&
-git read-tree -m $t1 $t2 $t3'
-
-test_expect_success \
-'checkout one stage 2 to temporary file' '
-rm -f path* .merge_* out &&
-git checkout-index --stage=2 --temp -- path1 >out &&
-test_line_count = 1 out &&
-test $(cut "-d " -f2 out) = path1 &&
-p=$(cut "-d    " -f1 out) &&
-test -f $p &&
-test $(cat $p) = tree2path1'
-
-test_expect_success \
-'checkout all stage 2 to temporary files' '
-rm -f path* .merge_* out &&
-git checkout-index --all --stage=2 --temp >out &&
-test_line_count = 3 out &&
-for f in path1 path2 path4
-do
-       test $(grep $f out | cut "-d    " -f2) = $f &&
-       p=$(grep $f out | cut "-d       " -f1) &&
+       test $(cat $p) = tree1path1
+'
+
+test_expect_success 'checkout all stage 0 to temporary files' '
+       rm -f path* .merge_* actual .git/index &&
+       git read-tree $t1 &&
+       git checkout-index -a --temp >actual &&
+       test_line_count = 5 actual &&
+       for f in path0 path1 path3 path4 asubdir/path5
+       do
+               test $(grep $f actual | cut "-d " -f2) = $f &&
+               p=$(grep $f actual | cut "-d    " -f1) &&
+               test -f $p &&
+               test $(cat $p) = tree1$f
+       done
+'
+
+test_expect_success 'setup 3-way merge' '
+       rm -f path* .merge_* actual .git/index &&
+       git read-tree -m $t1 $t2 $t3
+'
+
+test_expect_success 'checkout one stage 2 to temporary file' '
+       rm -f path* .merge_* actual &&
+       git checkout-index --stage=2 --temp -- path1 >actual &&
+       test_line_count = 1 actual &&
+       test $(cut "-d  " -f2 actual) = path1 &&
+       p=$(cut "-d     " -f1 actual) &&
        test -f $p &&
-       test $(cat $p) = tree2$f
-done'
-
-test_expect_success \
-'checkout all stages/one file to nothing' '
-rm -f path* .merge_* out &&
-git checkout-index --stage=all --temp -- path0 >out &&
-test_line_count = 0 out'
-
-test_expect_success \
-'checkout all stages/one file to temporary files' '
-rm -f path* .merge_* out &&
-git checkout-index --stage=all --temp -- path1 >out &&
-test_line_count = 1 out &&
-test $(cut "-d " -f2 out) = path1 &&
-cut "-d        " -f1 out | (read s1 s2 s3 &&
-test -f $s1 &&
-test -f $s2 &&
-test -f $s3 &&
-test $(cat $s1) = tree1path1 &&
-test $(cat $s2) = tree2path1 &&
-test $(cat $s3) = tree3path1)'
-
-test_expect_success \
-'checkout some stages/one file to temporary files' '
-rm -f path* .merge_* out &&
-git checkout-index --stage=all --temp -- path2 >out &&
-test_line_count = 1 out &&
-test $(cut "-d " -f2 out) = path2 &&
-cut "-d        " -f1 out | (read s1 s2 s3 &&
-test $s1 = . &&
-test -f $s2 &&
-test -f $s3 &&
-test $(cat $s2) = tree2path2 &&
-test $(cat $s3) = tree3path2)'
-
-test_expect_success \
-'checkout all stages/all files to temporary files' '
-rm -f path* .merge_* out &&
-git checkout-index -a --stage=all --temp >out &&
-test_line_count = 5 out'
-
-test_expect_success \
-'-- path0: no entry' '
-test x$(grep path0 out | cut "-d       " -f2) = x'
-
-test_expect_success \
-'-- path1: all 3 stages' '
-test $(grep path1 out | cut "-d        " -f2) = path1 &&
-grep path1 out | cut "-d       " -f1 | (read s1 s2 s3 &&
-test -f $s1 &&
-test -f $s2 &&
-test -f $s3 &&
-test $(cat $s1) = tree1path1 &&
-test $(cat $s2) = tree2path1 &&
-test $(cat $s3) = tree3path1)'
-
-test_expect_success \
-'-- path2: no stage 1, have stage 2 and 3' '
-test $(grep path2 out | cut "-d        " -f2) = path2 &&
-grep path2 out | cut "-d       " -f1 | (read s1 s2 s3 &&
-test $s1 = . &&
-test -f $s2 &&
-test -f $s3 &&
-test $(cat $s2) = tree2path2 &&
-test $(cat $s3) = tree3path2)'
-
-test_expect_success \
-'-- path3: no stage 2, have stage 1 and 3' '
-test $(grep path3 out | cut "-d        " -f2) = path3 &&
-grep path3 out | cut "-d       " -f1 | (read s1 s2 s3 &&
-test -f $s1 &&
-test $s2 = . &&
-test -f $s3 &&
-test $(cat $s1) = tree1path3 &&
-test $(cat $s3) = tree3path3)'
-
-test_expect_success \
-'-- path4: no stage 3, have stage 1 and 3' '
-test $(grep path4 out | cut "-d        " -f2) = path4 &&
-grep path4 out | cut "-d       " -f1 | (read s1 s2 s3 &&
-test -f $s1 &&
-test -f $s2 &&
-test $s3 = . &&
-test $(cat $s1) = tree1path4 &&
-test $(cat $s2) = tree2path4)'
-
-test_expect_success \
-'-- asubdir/path5: no stage 2 and 3 have stage 1' '
-test $(grep asubdir/path5 out | cut "-d        " -f2) = asubdir/path5 &&
-grep asubdir/path5 out | cut "-d       " -f1 | (read s1 s2 s3 &&
-test -f $s1 &&
-test $s2 = . &&
-test $s3 = . &&
-test $(cat $s1) = tree1asubdir/path5)'
-
-test_expect_success \
-'checkout --temp within subdir' '
-(cd asubdir &&
- git checkout-index -a --stage=all >out &&
- test_line_count = 1 out &&
- test $(grep path5 out | cut "-d       " -f2) = path5 &&
- grep path5 out | cut "-d      " -f1 | (read s1 s2 s3 &&
- test -f ../$s1 &&
- test $s2 = . &&
- test $s3 = . &&
- test $(cat ../$s1) = tree1asubdir/path5)
-)'
-
-test_expect_success \
-'checkout --temp symlink' '
-rm -f path* .merge_* out .git/index &&
-test_ln_s_add b a &&
-t4=$(git write-tree) &&
-rm -f .git/index &&
-git read-tree $t4 &&
-git checkout-index --temp -a >out &&
-test_line_count = 1 out &&
-test $(cut "-d " -f2 out) = a &&
-p=$(cut "-d    " -f1 out) &&
-test -f $p &&
-test $(cat $p) = b'
+       test $(cat $p) = tree2path1
+'
+
+test_expect_success 'checkout all stage 2 to temporary files' '
+       rm -f path* .merge_* actual &&
+       git checkout-index --all --stage=2 --temp >actual &&
+       test_line_count = 3 actual &&
+       for f in path1 path2 path4
+       do
+               test $(grep $f actual | cut "-d " -f2) = $f &&
+               p=$(grep $f actual | cut "-d    " -f1) &&
+               test -f $p &&
+               test $(cat $p) = tree2$f
+       done
+'
+
+test_expect_success 'checkout all stages/one file to nothing' '
+       rm -f path* .merge_* actual &&
+       git checkout-index --stage=all --temp -- path0 >actual &&
+       test_line_count = 0 actual
+'
+
+test_expect_success 'checkout all stages/one file to temporary files' '
+       rm -f path* .merge_* actual &&
+       git checkout-index --stage=all --temp -- path1 >actual &&
+       test_line_count = 1 actual &&
+       test $(cut "-d  " -f2 actual) = path1 &&
+       cut "-d " -f1 actual | (read s1 s2 s3 &&
+       test -f $s1 &&
+       test -f $s2 &&
+       test -f $s3 &&
+       test $(cat $s1) = tree1path1 &&
+       test $(cat $s2) = tree2path1 &&
+       test $(cat $s3) = tree3path1)
+'
+
+test_expect_success 'checkout some stages/one file to temporary files' '
+       rm -f path* .merge_* actual &&
+       git checkout-index --stage=all --temp -- path2 >actual &&
+       test_line_count = 1 actual &&
+       test $(cut "-d  " -f2 actual) = path2 &&
+       cut "-d " -f1 actual | (read s1 s2 s3 &&
+       test $s1 = . &&
+       test -f $s2 &&
+       test -f $s3 &&
+       test $(cat $s2) = tree2path2 &&
+       test $(cat $s3) = tree3path2)
+'
+
+test_expect_success 'checkout all stages/all files to temporary files' '
+       rm -f path* .merge_* actual &&
+       git checkout-index -a --stage=all --temp >actual &&
+       test_line_count = 5 actual
+'
+
+test_expect_success '-- path0: no entry' '
+       test x$(grep path0 actual | cut "-d     " -f2) = x
+'
+
+test_expect_success '-- path1: all 3 stages' '
+       test $(grep path1 actual | cut "-d      " -f2) = path1 &&
+       grep path1 actual | cut "-d     " -f1 | (read s1 s2 s3 &&
+       test -f $s1 &&
+       test -f $s2 &&
+       test -f $s3 &&
+       test $(cat $s1) = tree1path1 &&
+       test $(cat $s2) = tree2path1 &&
+       test $(cat $s3) = tree3path1)
+'
+
+test_expect_success '-- path2: no stage 1, have stage 2 and 3' '
+       test $(grep path2 actual | cut "-d      " -f2) = path2 &&
+       grep path2 actual | cut "-d     " -f1 | (read s1 s2 s3 &&
+       test $s1 = . &&
+       test -f $s2 &&
+       test -f $s3 &&
+       test $(cat $s2) = tree2path2 &&
+       test $(cat $s3) = tree3path2)
+'
+
+test_expect_success '-- path3: no stage 2, have stage 1 and 3' '
+       test $(grep path3 actual | cut "-d      " -f2) = path3 &&
+       grep path3 actual | cut "-d     " -f1 | (read s1 s2 s3 &&
+       test -f $s1 &&
+       test $s2 = . &&
+       test -f $s3 &&
+       test $(cat $s1) = tree1path3 &&
+       test $(cat $s3) = tree3path3)
+'
+
+test_expect_success '-- path4: no stage 3, have stage 1 and 3' '
+       test $(grep path4 actual | cut "-d      " -f2) = path4 &&
+       grep path4 actual | cut "-d     " -f1 | (read s1 s2 s3 &&
+       test -f $s1 &&
+       test -f $s2 &&
+       test $s3 = . &&
+       test $(cat $s1) = tree1path4 &&
+       test $(cat $s2) = tree2path4)
+'
+
+test_expect_success '-- asubdir/path5: no stage 2 and 3 have stage 1' '
+       test $(grep asubdir/path5 actual | cut "-d      " -f2) = asubdir/path5 &&
+       grep asubdir/path5 actual | cut "-d     " -f1 | (read s1 s2 s3 &&
+       test -f $s1 &&
+       test $s2 = . &&
+       test $s3 = . &&
+       test $(cat $s1) = tree1asubdir/path5)
+'
+
+test_expect_success 'checkout --temp within subdir' '
+       (
+               cd asubdir &&
+               git checkout-index -a --stage=all >actual &&
+               test_line_count = 1 actual &&
+               test $(grep path5 actual | cut "-d      " -f2) = path5 &&
+               grep path5 actual | cut "-d     " -f1 | (read s1 s2 s3 &&
+               test -f ../$s1 &&
+               test $s2 = . &&
+               test $s3 = . &&
+               test $(cat ../$s1) = tree1asubdir/path5)
+       )
+'
+
+test_expect_success 'checkout --temp symlink' '
+       rm -f path* .merge_* actual .git/index &&
+       test_ln_s_add path7 path6 &&
+       git checkout-index --temp -a >actual &&
+       test_line_count = 1 actual &&
+       test $(cut "-d  " -f2 actual) = path6 &&
+       p=$(cut "-d     " -f1 actual) &&
+       test -f $p &&
+       test $(cat $p) = path7
+'
+
+test_expect_success 'emit well-formed relative path' '
+       rm -f path* .merge_* actual .git/index &&
+       >path0123456789 &&
+       git update-index --add path0123456789 &&
+       (
+               cd asubdir &&
+               git checkout-index --temp -- ../path0123456789 >actual &&
+               test_line_count = 1 actual &&
+               test $(cut "-d  " -f2 actual) = ../path0123456789
+       )
+'
 
 test_done
index 6ecb559465b43e528a5cb1511b758cc48d940e92..468a000e4bbb113d004ee8df8ef0db9b8260fdb5 100755 (executable)
@@ -185,4 +185,22 @@ test_expect_success 'checkout <branch> -- succeeds, even if a file with the same
        test_branch_upstream spam repo_c spam
 '
 
+test_expect_success 'loosely defined local base branch is reported correctly' '
+
+       git checkout master &&
+       git branch strict &&
+       git branch loose &&
+       git commit --allow-empty -m "a bit more" &&
+
+       test_config branch.strict.remote . &&
+       test_config branch.loose.remote . &&
+       test_config branch.strict.merge refs/heads/master &&
+       test_config branch.loose.merge master &&
+
+       git checkout strict | sed -e "s/strict/BRANCHNAME/g" >expect &&
+       git checkout loose | sed -e "s/loose/BRANCHNAME/g" >actual &&
+
+       test_cmp expect actual
+'
+
 test_done
index 1bafb9098c7fae33969e9231fbdee1c0370830a1..dfe02f48183ad77a93d72c0f5e952380b63a9229 100755 (executable)
@@ -65,4 +65,19 @@ test_expect_success '--cacheinfo mode,sha1,path (new syntax)' '
        test_cmp expect actual
 '
 
+test_expect_success '.lock files cleaned up' '
+       mkdir cleanup &&
+       (
+       cd cleanup &&
+       mkdir worktree &&
+       git init repo &&
+       cd repo &&
+       git config core.worktree ../../worktree &&
+       # --refresh triggers late setup_work_tree,
+       # active_cache_changed is zero, rollback_lock_file fails
+       git update-index --refresh &&
+       ! test -f .git/index.lock
+       )
+'
+
 test_done
index 27e98a8f9d6c858468904542c500236b9e9f99c2..89204648965b2b6b7d7984e3398b3ef21a8d7c7e 100755 (executable)
@@ -123,10 +123,10 @@ test_expect_success \
     'git diff-index -B -M "$tree" >current'
 
 # file0 changed from regular to symlink.  file1 is very close to the preimage of file0.
-# because we break file0, file1 can become a rename of it.
+# the change does not make file0 disappear, so file1 is denoted as a copy of file0
 cat >expected <<\EOF
 :100644 120000 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 67be421f88824578857624f7b3dc75e99a8a1481 T     file0
-:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 R     file0   file1
+:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 C     file0   file1
 EOF
 
 test_expect_success \
index 55d549fcf441be927bc43b2c41107a90aa614c2a..8c9823765e66aca886a1ec32a8ad523c1c28e1bc 100755 (executable)
@@ -76,7 +76,8 @@ test_expect_success 'moves and renames' '
 
        git diff-tree three four -r --name-status -B -M | sort >actual &&
        {
-               echo "R100      foo     bar"
+               # see -B -M (#6) in t4008
+               echo "C100      foo     bar"
                echo "T100      foo"
        } | sort >expect &&
        test_cmp expect actual
index 0736bcbcd52a76ef3400c046e7d3558dd1a866c7..04cea97f87784bfb9a9a04fdb7341478e64fd5b6 100755 (executable)
@@ -76,8 +76,7 @@ test_expect_success 'refuse pushing rewound head without --force' '
        test "$victim_head" = "$pushed_head"
 '
 
-test_expect_success \
-        'push can be used to delete a ref' '
+test_expect_success 'push can be used to delete a ref' '
        ( cd victim && git branch extra master ) &&
        git send-pack ./victim :extra master &&
        ( cd victim &&
@@ -196,19 +195,6 @@ rewound_push_setup() {
        )
 }
 
-rewound_push_succeeded() {
-       cmp ../parent/.git/refs/heads/master .git/refs/heads/master
-}
-
-rewound_push_failed() {
-       if rewound_push_succeeded
-       then
-               false
-       else
-               true
-       fi
-}
-
 test_expect_success 'pushing explicit refspecs respects forcing' '
        rewound_push_setup &&
        parent_orig=$(cd parent && git rev-parse --verify master) &&
index 6537911a4300656706c995226b2f0444a760bae0..3e783fc450d21c8de6fae2cb3677e9eaebacf927 100755 (executable)
@@ -198,4 +198,21 @@ test_expect_success 'clone using repo pointed at by gitfile as reference' '
        test_cmp expected "$base_dir/O/.git/objects/info/alternates"
 '
 
+test_expect_success 'clone and dissociate from reference' '
+       git init P &&
+       (
+               cd P && test_commit one
+       ) &&
+       git clone P Q &&
+       (
+               cd Q && test_commit two
+       ) &&
+       git clone --no-local --reference=P Q R &&
+       git clone --no-local --reference=P --dissociate Q S &&
+       # removing the reference P would corrupt R but not S
+       rm -fr P &&
+       test_must_fail git -C R fsck &&
+       git -C S fsck
+'
+
 test_done
index 064f5cefeb4cf7e3bfa2c104384094492dc54f91..e6abe65d5c3370a53e3f034486101a8e9ee4055b 100755 (executable)
@@ -779,4 +779,13 @@ test_expect_success 'bisect log: only skip commits left' '
        git bisect reset
 '
 
+test_expect_success '"git bisect bad HEAD" behaves as "git bisect bad"' '
+       git checkout parallel &&
+       git bisect start HEAD $HASH1 &&
+       git bisect good HEAD &&
+       git bisect bad HEAD &&
+       test "$HASH6" = $(git rev-parse --verify HEAD) &&
+       git bisect reset
+'
+
 test_done
index e5016f457398a0770ebfc0e98d6f60fdfa4be2fc..af6a3e8904ab1d953b359707de1e0c9a09b3ce1f 100755 (executable)
@@ -6,35 +6,37 @@ test_description='git send-email'
 # May be altered later in the test
 PREREQ="PERL"
 
-test_expect_success $PREREQ \
-    'prepare reference tree' \
-    'echo "1A quick brown fox jumps over the" >file &&
-     echo "lazy dog" >>file &&
-     git add file &&
-     GIT_AUTHOR_NAME="A" git commit -a -m "Initial."'
-
-test_expect_success $PREREQ \
-    'Setup helper tool' \
-    '(echo "#!$SHELL_PATH"
-      echo shift
-      echo output=1
-      echo "while test -f commandline\$output; do output=\$((\$output+1)); done"
-      echo for a
-      echo do
-      echo "  echo \"!\$a!\""
-      echo "done >commandline\$output"
-      echo "cat > msgtxt\$output"
-      ) >fake.sendmail &&
-     chmod +x ./fake.sendmail &&
-     git add fake.sendmail &&
-     GIT_AUTHOR_NAME="A" git commit -a -m "Second."'
-
-clean_fake_sendmail() {
+test_expect_success $PREREQ 'prepare reference tree' '
+       echo "1A quick brown fox jumps over the" >file &&
+       echo "lazy dog" >>file &&
+       git add file &&
+       GIT_AUTHOR_NAME="A" git commit -a -m "Initial."
+'
+
+test_expect_success $PREREQ 'Setup helper tool' '
+       write_script fake.sendmail <<-\EOF &&
+       shift
+       output=1
+       while test -f commandline$output
+       do
+               output=$(($output+1))
+       done
+       for a
+       do
+               echo "!$a!"
+       done >commandline$output
+       cat >"msgtxt$output"
+       EOF
+       git add fake.sendmail &&
+       GIT_AUTHOR_NAME="A" git commit -a -m "Second."
+'
+
+clean_fake_sendmail () {
        rm -f commandline* msgtxt*
 }
 
 test_expect_success $PREREQ 'Extract patches' '
-    patches=`git format-patch -s --cc="One <one@example.com>" --cc=two@example.com -n HEAD^1`
+       patches=`git format-patch -s --cc="One <one@example.com>" --cc=two@example.com -n HEAD^1`
 '
 
 # Test no confirm early to ensure remaining tests will not hang
@@ -47,9 +49,9 @@ test_no_confirm () {
                --to=nobody@example.com \
                --smtp-server="$(pwd)/fake.sendmail" \
                $@ \
-               $patches > stdout &&
+               $patches >stdout &&
                test_must_fail grep "Send this email" stdout &&
-               > no_confirm_okay
+               >no_confirm_okay
 }
 
 # Exit immediately to prevent hang if a no-confirm test fails
@@ -82,61 +84,61 @@ test_expect_success $PREREQ 'No confirm with sendemail.confirm=never' '
 '
 
 test_expect_success $PREREQ 'Send patches' '
-     git send-email --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors
+       git send-email --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors
 '
 
 test_expect_success $PREREQ 'setup expect' '
-cat >expected <<\EOF
-!nobody@example.com!
-!author@example.com!
-!one@example.com!
-!two@example.com!
-EOF
+       cat >expected <<-\EOF
+       !nobody@example.com!
+       !author@example.com!
+       !one@example.com!
+       !two@example.com!
+       EOF
 '
 
-test_expect_success $PREREQ \
-    'Verify commandline' \
-    'test_cmp expected commandline1'
+test_expect_success $PREREQ 'Verify commandline' '
+       test_cmp expected commandline1
+'
 
 test_expect_success $PREREQ 'Send patches with --envelope-sender' '
-    clean_fake_sendmail &&
-     git send-email --envelope-sender="Patch Contributor <patch@example.com>" --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors
+       clean_fake_sendmail &&
+       git send-email --envelope-sender="Patch Contributor <patch@example.com>" --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors
 '
 
 test_expect_success $PREREQ 'setup expect' '
-cat >expected <<\EOF
-!patch@example.com!
-!-i!
-!nobody@example.com!
-!author@example.com!
-!one@example.com!
-!two@example.com!
-EOF
+       cat >expected <<-\EOF
+       !patch@example.com!
+       !-i!
+       !nobody@example.com!
+       !author@example.com!
+       !one@example.com!
+       !two@example.com!
+       EOF
 '
 
-test_expect_success $PREREQ \
-    'Verify commandline' \
-    'test_cmp expected commandline1'
+test_expect_success $PREREQ 'Verify commandline' '
+       test_cmp expected commandline1
+'
 
 test_expect_success $PREREQ 'Send patches with --envelope-sender=auto' '
-    clean_fake_sendmail &&
-     git send-email --envelope-sender=auto --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors
+       clean_fake_sendmail &&
+       git send-email --envelope-sender=auto --suppress-cc=sob --from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" $patches 2>errors
 '
 
 test_expect_success $PREREQ 'setup expect' '
-cat >expected <<\EOF
-!nobody@example.com!
-!-i!
-!nobody@example.com!
-!author@example.com!
-!one@example.com!
-!two@example.com!
-EOF
+       cat >expected <<-\EOF
+       !nobody@example.com!
+       !-i!
+       !nobody@example.com!
+       !author@example.com!
+       !one@example.com!
+       !two@example.com!
+       EOF
 '
 
-test_expect_success $PREREQ \
-    'Verify commandline' \
-    'test_cmp expected commandline1'
+test_expect_success $PREREQ 'Verify commandline' '
+       test_cmp expected commandline1
+'
 
 test_expect_success $PREREQ 'setup expect' "
 cat >expected-show-all-headers <<\EOF
@@ -240,6 +242,13 @@ test_expect_success $PREREQ 'non-ascii self name is suppressed' "
                'non_ascii_self_suppressed'
 "
 
+# This name is long enough to force format-patch to split it into multiple
+# encoded-words, assuming it uses UTF-8 with the "Q" encoding.
+test_expect_success $PREREQ 'long non-ascii self name is suppressed' "
+       test_suppress_self_quoted 'Ƒüñníęř €. Nâṁé' 'odd_?=mail@example.com' \
+               'long_non_ascii_self_suppressed'
+"
+
 test_expect_success $PREREQ 'sanitized self name is suppressed' "
        test_suppress_self_unquoted '\"A U. Thor\"' 'author@example.com' \
                'self_name_sanitized_suppressed'
@@ -307,11 +316,9 @@ test_expect_success $PREREQ 'tocmd works' '
        clean_fake_sendmail &&
        cp $patches tocmd.patch &&
        echo tocmd--tocmd@example.com >>tocmd.patch &&
-       {
-         echo "#!$SHELL_PATH"
-         echo sed -n -e s/^tocmd--//p \"\$1\"
-       } > tocmd-sed &&
-       chmod +x tocmd-sed &&
+       write_script tocmd-sed <<-\EOF &&
+       sed -n -e "s/^tocmd--//p" "$1"
+       EOF
        git send-email \
                --from="Example <nobody@example.com>" \
                --to-cmd=./tocmd-sed \
@@ -325,11 +332,9 @@ test_expect_success $PREREQ 'cccmd works' '
        clean_fake_sendmail &&
        cp $patches cccmd.patch &&
        echo "cccmd--  cccmd@example.com" >>cccmd.patch &&
-       {
-         echo "#!$SHELL_PATH"
-         echo sed -n -e s/^cccmd--//p \"\$1\"
-       } > cccmd-sed &&
-       chmod +x cccmd-sed &&
+       write_script cccmd-sed <<-\EOF &&
+       sed -n -e "s/^cccmd--//p" "$1"
+       EOF
        git send-email \
                --from="Example <nobody@example.com>" \
                --to=nobody@example.com \
@@ -367,7 +372,7 @@ test_expect_success $PREREQ 'Author From: in message body' '
                --to=nobody@example.com \
                --smtp-server="$(pwd)/fake.sendmail" \
                $patches &&
-       sed "1,/^\$/d" < msgtxt1 > msgbody1 &&
+       sed "1,/^\$/d" <msgtxt1 >msgbody1 &&
        grep "From: A <author@example.com>" msgbody1
 '
 
@@ -378,7 +383,7 @@ test_expect_success $PREREQ 'Author From: not in message body' '
                --to=nobody@example.com \
                --smtp-server="$(pwd)/fake.sendmail" \
                $patches &&
-       sed "1,/^\$/d" < msgtxt1 > msgbody1 &&
+       sed "1,/^\$/d" <msgtxt1 >msgbody1 &&
        ! grep "From: A <author@example.com>" msgbody1
 '
 
@@ -459,10 +464,9 @@ test_expect_success $PREREQ 'In-Reply-To with --chain-reply-to' '
 '
 
 test_expect_success $PREREQ 'setup fake editor' '
-       (echo "#!$SHELL_PATH" &&
-        echo "echo fake edit >>\"\$1\""
-       ) >fake-editor &&
-       chmod +x fake-editor
+       write_script fake-editor <<-\EOF
+       echo fake edit >>"$1"
+       EOF
 '
 
 test_set_editor "$(pwd)/fake-editor"
@@ -598,8 +602,9 @@ EOF
 "
 
 test_expect_success $PREREQ 'sendemail.cccmd' '
-       echo echo cc-cmd@example.com > cccmd &&
-       chmod +x cccmd &&
+       write_script cccmd <<-\EOF &&
+       echo cc-cmd@example.com
+       EOF
        git config sendemail.cccmd ./cccmd &&
        test_suppression cccmd
 '
@@ -792,7 +797,7 @@ test_confirm () {
                --from="Example <nobody@example.com>" \
                --to=nobody@example.com \
                --smtp-server="$(pwd)/fake.sendmail" \
-               $@ $patches > stdout &&
+               $@ $patches >stdout &&
        grep "Send this email" stdout
 }
 
@@ -840,7 +845,7 @@ test_expect_success $PREREQ 'confirm detects EOF (inform assumes y)' '
                        --from="Example <nobody@example.com>" \
                        --to=nobody@example.com \
                        --smtp-server="$(pwd)/fake.sendmail" \
-                       outdir/*.patch < /dev/null
+                       outdir/*.patch </dev/null
        ret="$?"
        git config sendemail.confirm ${CONFIRM:-never}
        test $ret = "0"
@@ -855,7 +860,7 @@ test_expect_success $PREREQ 'confirm detects EOF (auto causes failure)' '
                        --from="Example <nobody@example.com>" \
                        --to=nobody@example.com \
                        --smtp-server="$(pwd)/fake.sendmail" \
-                       $patches < /dev/null
+                       $patches </dev/null
        ret="$?"
        git config sendemail.confirm ${CONFIRM:-never}
        test $ret = "0"
@@ -891,39 +896,39 @@ test_expect_success $PREREQ 'utf8 Cc is rfc2047 encoded' '
 
 test_expect_success $PREREQ '--compose adds MIME for utf8 body' '
        clean_fake_sendmail &&
-       (echo "#!$SHELL_PATH" &&
-        echo "echo utf8 body: àéìöú >>\"\$1\""
-       ) >fake-editor-utf8 &&
-       chmod +x fake-editor-utf8 &&
-         GIT_EDITOR="\"$(pwd)/fake-editor-utf8\"" \
-         git send-email \
-         --compose --subject foo \
-         --from="Example <nobody@example.com>" \
-         --to=nobody@example.com \
-         --smtp-server="$(pwd)/fake.sendmail" \
-         $patches &&
+       write_script fake-editor-utf8 <<-\EOF &&
+       echo "utf8 body: àéìöú" >>"$1"
+       EOF
+       GIT_EDITOR="\"$(pwd)/fake-editor-utf8\"" \
+       git send-email \
+               --compose --subject foo \
+               --from="Example <nobody@example.com>" \
+               --to=nobody@example.com \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               $patches &&
        grep "^utf8 body" msgtxt1 &&
        grep "^Content-Type: text/plain; charset=UTF-8" msgtxt1
 '
 
 test_expect_success $PREREQ '--compose respects user mime type' '
        clean_fake_sendmail &&
-       (echo "#!$SHELL_PATH" &&
-        echo "(echo MIME-Version: 1.0"
-        echo " echo Content-Type: text/plain\\; charset=iso-8859-1"
-        echo " echo Content-Transfer-Encoding: 8bit"
-        echo " echo Subject: foo"
-        echo " echo "
-        echo " echo utf8 body: àéìöú) >\"\$1\""
-       ) >fake-editor-utf8-mime &&
-       chmod +x fake-editor-utf8-mime &&
-         GIT_EDITOR="\"$(pwd)/fake-editor-utf8-mime\"" \
-         git send-email \
-         --compose --subject foo \
-         --from="Example <nobody@example.com>" \
-         --to=nobody@example.com \
-         --smtp-server="$(pwd)/fake.sendmail" \
-         $patches &&
+       write_script fake-editor-utf8-mime <<-\EOF &&
+       cat >"$1" <<-\EOM
+       MIME-Version: 1.0
+       Content-Type: text/plain; charset=iso-8859-1
+       Content-Transfer-Encoding: 8bit
+       Subject: foo
+
+       utf8 body: àéìöú
+       EOM
+       EOF
+       GIT_EDITOR="\"$(pwd)/fake-editor-utf8-mime\"" \
+       git send-email \
+               --compose --subject foo \
+               --from="Example <nobody@example.com>" \
+               --to=nobody@example.com \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               $patches &&
        grep "^utf8 body" msgtxt1 &&
        grep "^Content-Type: text/plain; charset=iso-8859-1" msgtxt1 &&
        ! grep "^Content-Type: text/plain; charset=UTF-8" msgtxt1
@@ -931,13 +936,13 @@ test_expect_success $PREREQ '--compose respects user mime type' '
 
 test_expect_success $PREREQ '--compose adds MIME for utf8 subject' '
        clean_fake_sendmail &&
-         GIT_EDITOR="\"$(pwd)/fake-editor\"" \
-         git send-email \
-         --compose --subject utf8-sübjëct \
-         --from="Example <nobody@example.com>" \
-         --to=nobody@example.com \
-         --smtp-server="$(pwd)/fake.sendmail" \
-         $patches &&
+       GIT_EDITOR="\"$(pwd)/fake-editor\"" \
+       git send-email \
+               --compose --subject utf8-sübjëct \
+               --from="Example <nobody@example.com>" \
+               --to=nobody@example.com \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               $patches &&
        grep "^fake edit" msgtxt1 &&
        grep "^Subject: =?UTF-8?q?utf8-s=C3=BCbj=C3=ABct?=" msgtxt1
 '
@@ -949,9 +954,9 @@ test_expect_success $PREREQ 'utf8 author is correctly passed on' '
        git commit --amend --author "Füñný Nâmé <odd_?=mail@example.com>" &&
        git format-patch --stdout -1 >funny_name.patch &&
        git send-email --from="Example <nobody@example.com>" \
-         --to=nobody@example.com \
-         --smtp-server="$(pwd)/fake.sendmail" \
-         funny_name.patch &&
+               --to=nobody@example.com \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               funny_name.patch &&
        grep "^From: Füñný Nâmé <odd_?=mail@example.com>" msgtxt1
 '
 
@@ -962,9 +967,9 @@ test_expect_success $PREREQ 'utf8 sender is not duplicated' '
        git commit --amend --author "Füñný Nâmé <odd_?=mail@example.com>" &&
        git format-patch --stdout -1 >funny_name.patch &&
        git send-email --from="Füñný Nâmé <odd_?=mail@example.com>" \
-         --to=nobody@example.com \
-         --smtp-server="$(pwd)/fake.sendmail" \
-         funny_name.patch &&
+               --to=nobody@example.com \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               funny_name.patch &&
        grep "^From: " msgtxt1 >msgfrom &&
        test_line_count = 1 msgfrom
 '
@@ -972,35 +977,33 @@ test_expect_success $PREREQ 'utf8 sender is not duplicated' '
 test_expect_success $PREREQ 'sendemail.composeencoding works' '
        clean_fake_sendmail &&
        git config sendemail.composeencoding iso-8859-1 &&
-       (echo "#!$SHELL_PATH" &&
-        echo "echo utf8 body: àéìöú >>\"\$1\""
-       ) >fake-editor-utf8 &&
-       chmod +x fake-editor-utf8 &&
-         GIT_EDITOR="\"$(pwd)/fake-editor-utf8\"" \
-         git send-email \
-         --compose --subject foo \
-         --from="Example <nobody@example.com>" \
-         --to=nobody@example.com \
-         --smtp-server="$(pwd)/fake.sendmail" \
-         $patches &&
+       write_script fake-editor-utf8 <<-\EOF &&
+       echo "utf8 body: àéìöú" >>"$1"
+       EOF
+       GIT_EDITOR="\"$(pwd)/fake-editor-utf8\"" \
+       git send-email \
+               --compose --subject foo \
+               --from="Example <nobody@example.com>" \
+               --to=nobody@example.com \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               $patches &&
        grep "^utf8 body" msgtxt1 &&
        grep "^Content-Type: text/plain; charset=iso-8859-1" msgtxt1
 '
 
 test_expect_success $PREREQ '--compose-encoding works' '
        clean_fake_sendmail &&
-       (echo "#!$SHELL_PATH" &&
-        echo "echo utf8 body: àéìöú >>\"\$1\""
-       ) >fake-editor-utf8 &&
-       chmod +x fake-editor-utf8 &&
-         GIT_EDITOR="\"$(pwd)/fake-editor-utf8\"" \
-         git send-email \
-         --compose-encoding iso-8859-1 \
-         --compose --subject foo \
-         --from="Example <nobody@example.com>" \
-         --to=nobody@example.com \
-         --smtp-server="$(pwd)/fake.sendmail" \
-         $patches &&
+       write_script fake-editor-utf8 <<-\EOF &&
+       echo "utf8 body: àéìöú" >>"$1"
+       EOF
+       GIT_EDITOR="\"$(pwd)/fake-editor-utf8\"" \
+       git send-email \
+               --compose-encoding iso-8859-1 \
+               --compose --subject foo \
+               --from="Example <nobody@example.com>" \
+               --to=nobody@example.com \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               $patches &&
        grep "^utf8 body" msgtxt1 &&
        grep "^Content-Type: text/plain; charset=iso-8859-1" msgtxt1
 '
@@ -1008,38 +1011,37 @@ test_expect_success $PREREQ '--compose-encoding works' '
 test_expect_success $PREREQ '--compose-encoding overrides sendemail.composeencoding' '
        clean_fake_sendmail &&
        git config sendemail.composeencoding iso-8859-1 &&
-       (echo "#!$SHELL_PATH" &&
-        echo "echo utf8 body: àéìöú >>\"\$1\""
-       ) >fake-editor-utf8 &&
-       chmod +x fake-editor-utf8 &&
-         GIT_EDITOR="\"$(pwd)/fake-editor-utf8\"" \
-         git send-email \
-         --compose-encoding iso-8859-2 \
-         --compose --subject foo \
-         --from="Example <nobody@example.com>" \
-         --to=nobody@example.com \
-         --smtp-server="$(pwd)/fake.sendmail" \
-         $patches &&
+       write_script fake-editor-utf8 <<-\EOF &&
+       echo "utf8 body: àéìöú" >>"$1"
+       EOF
+       GIT_EDITOR="\"$(pwd)/fake-editor-utf8\"" \
+       git send-email \
+               --compose-encoding iso-8859-2 \
+               --compose --subject foo \
+               --from="Example <nobody@example.com>" \
+               --to=nobody@example.com \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               $patches &&
        grep "^utf8 body" msgtxt1 &&
        grep "^Content-Type: text/plain; charset=iso-8859-2" msgtxt1
 '
 
 test_expect_success $PREREQ '--compose-encoding adds correct MIME for subject' '
        clean_fake_sendmail &&
-         GIT_EDITOR="\"$(pwd)/fake-editor\"" \
-         git send-email \
-         --compose-encoding iso-8859-2 \
-         --compose --subject utf8-sübjëct \
-         --from="Example <nobody@example.com>" \
-         --to=nobody@example.com \
-         --smtp-server="$(pwd)/fake.sendmail" \
-         $patches &&
+       GIT_EDITOR="\"$(pwd)/fake-editor\"" \
+       git send-email \
+               --compose-encoding iso-8859-2 \
+               --compose --subject utf8-sübjëct \
+               --from="Example <nobody@example.com>" \
+               --to=nobody@example.com \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               $patches &&
        grep "^fake edit" msgtxt1 &&
        grep "^Subject: =?iso-8859-2?q?utf8-s=C3=BCbj=C3=ABct?=" msgtxt1
 '
 
 test_expect_success $PREREQ 'detects ambiguous reference/file conflict' '
-       echo master > master &&
+       echo master >master &&
        git add master &&
        git commit -m"add master" &&
        test_must_fail git send-email --dry-run master 2>errors &&
@@ -1050,10 +1052,10 @@ test_expect_success $PREREQ 'feed two files' '
        rm -fr outdir &&
        git format-patch -2 -o outdir &&
        git send-email \
-       --dry-run \
-       --from="Example <nobody@example.com>" \
-       --to=nobody@example.com \
-       outdir/000?-*.patch 2>errors >out &&
+               --dry-run \
+               --from="Example <nobody@example.com>" \
+               --to=nobody@example.com \
+               outdir/000?-*.patch 2>errors >out &&
        grep "^Subject: " out >subjects &&
        test "z$(sed -n -e 1p subjects)" = "zSubject: [PATCH 1/2] Second." &&
        test "z$(sed -n -e 2p subjects)" = "zSubject: [PATCH 2/2] add master"
@@ -1197,7 +1199,7 @@ test_expect_success $PREREQ 'To headers from files reset each patch' '
 '
 
 test_expect_success $PREREQ 'setup expect' '
-cat >email-using-8bit <<EOF
+cat >email-using-8bit <<\EOF
 From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
 Message-Id: <bogus-message-id@example.com>
 From: author@example.com
@@ -1209,9 +1211,7 @@ EOF
 '
 
 test_expect_success $PREREQ 'setup expect' '
-cat >expected <<EOF
-Subject: subject goes here
-EOF
+       echo "Subject: subject goes here" >expected
 '
 
 test_expect_success $PREREQ 'ASCII subject is not RFC2047 quoted' '
@@ -1226,11 +1226,11 @@ test_expect_success $PREREQ 'ASCII subject is not RFC2047 quoted' '
 '
 
 test_expect_success $PREREQ 'setup expect' '
-cat >content-type-decl <<EOF
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-EOF
+       cat >content-type-decl <<-\EOF
+       MIME-Version: 1.0
+       Content-Type: text/plain; charset=UTF-8
+       Content-Transfer-Encoding: 8bit
+       EOF
 '
 
 test_expect_success $PREREQ 'asks about and fixes 8bit encodings' '
@@ -1270,21 +1270,21 @@ test_expect_success $PREREQ '--8bit-encoding overrides sendemail.8bitEncoding' '
 '
 
 test_expect_success $PREREQ 'setup expect' '
-cat >email-using-8bit <<EOF
-From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
-Message-Id: <bogus-message-id@example.com>
-From: author@example.com
-Date: Sat, 12 Jun 2010 15:53:58 +0200
-Subject: Dieser Betreff enthält auch einen Umlaut!
-
-Nothing to see here.
-EOF
+       cat >email-using-8bit <<-\EOF
+       From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
+       Message-Id: <bogus-message-id@example.com>
+       From: author@example.com
+       Date: Sat, 12 Jun 2010 15:53:58 +0200
+       Subject: Dieser Betreff enthält auch einen Umlaut!
+
+       Nothing to see here.
+       EOF
 '
 
 test_expect_success $PREREQ 'setup expect' '
-cat >expected <<EOF
-Subject: =?UTF-8?q?Dieser=20Betreff=20enth=C3=A4lt=20auch=20einen=20Umlaut!?=
-EOF
+       cat >expected <<-\EOF
+       Subject: =?UTF-8?q?Dieser=20Betreff=20enth=C3=A4lt=20auch=20einen=20Umlaut!?=
+       EOF
 '
 
 test_expect_success $PREREQ '--8bit-encoding also treats subject' '
@@ -1299,26 +1299,26 @@ test_expect_success $PREREQ '--8bit-encoding also treats subject' '
 '
 
 test_expect_success $PREREQ 'setup expect' '
-cat >email-using-8bit <<EOF
-From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
-Message-Id: <bogus-message-id@example.com>
-From: A U Thor <author@example.com>
-Date: Sat, 12 Jun 2010 15:53:58 +0200
-Content-Type: text/plain; charset=UTF-8
-Subject: Nothing to see here.
-
-Dieser Betreff enthält auch einen Umlaut!
-EOF
+       cat >email-using-8bit <<-\EOF
+       From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
+       Message-Id: <bogus-message-id@example.com>
+       From: A U Thor <author@example.com>
+       Date: Sat, 12 Jun 2010 15:53:58 +0200
+       Content-Type: text/plain; charset=UTF-8
+       Subject: Nothing to see here.
+
+       Dieser Betreff enthält auch einen Umlaut!
+       EOF
 '
 
 test_expect_success $PREREQ 'sendemail.transferencoding=7bit fails on 8bit data' '
        clean_fake_sendmail &&
        git config sendemail.transferEncoding 7bit &&
        test_must_fail git send-email \
-         --transfer-encoding=7bit \
-         --smtp-server="$(pwd)/fake.sendmail" \
-         email-using-8bit \
-         2>errors >out &&
+               --transfer-encoding=7bit \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               email-using-8bit \
+               2>errors >out &&
        grep "cannot send message as 7bit" errors &&
        test -z "$(ls msgtxt*)"
 '
@@ -1327,10 +1327,10 @@ test_expect_success $PREREQ '--transfer-encoding overrides sendemail.transferEnc
        clean_fake_sendmail &&
        git config sendemail.transferEncoding 8bit
        test_must_fail git send-email \
-         --transfer-encoding=7bit \
-         --smtp-server="$(pwd)/fake.sendmail" \
-         email-using-8bit \
-         2>errors >out &&
+               --transfer-encoding=7bit \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               email-using-8bit \
+               2>errors >out &&
        grep "cannot send message as 7bit" errors &&
        test -z "$(ls msgtxt*)"
 '
@@ -1338,77 +1338,77 @@ test_expect_success $PREREQ '--transfer-encoding overrides sendemail.transferEnc
 test_expect_success $PREREQ 'sendemail.transferencoding=8bit' '
        clean_fake_sendmail &&
        git send-email \
-         --transfer-encoding=8bit \
-         --smtp-server="$(pwd)/fake.sendmail" \
-         email-using-8bit \
-         2>errors >out &&
+               --transfer-encoding=8bit \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               email-using-8bit \
+               2>errors >out &&
        sed '1,/^$/d' msgtxt1 >actual &&
        sed '1,/^$/d' email-using-8bit >expected &&
        test_cmp expected actual
 '
 
 test_expect_success $PREREQ 'setup expect' '
-cat >expected <<EOF
-Dieser Betreff enth=C3=A4lt auch einen Umlaut!
-EOF
+       cat >expected <<-\EOF
+       Dieser Betreff enth=C3=A4lt auch einen Umlaut!
+       EOF
 '
 
 test_expect_success $PREREQ '8-bit and sendemail.transferencoding=quoted-printable' '
        clean_fake_sendmail &&
        git send-email \
-         --transfer-encoding=quoted-printable \
-         --smtp-server="$(pwd)/fake.sendmail" \
-         email-using-8bit \
-         2>errors >out &&
+               --transfer-encoding=quoted-printable \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               email-using-8bit \
+               2>errors >out &&
        sed '1,/^$/d' msgtxt1 >actual &&
        test_cmp expected actual
 '
 
 test_expect_success $PREREQ 'setup expect' '
-cat >expected <<EOF
-RGllc2VyIEJldHJlZmYgZW50aMOkbHQgYXVjaCBlaW5lbiBVbWxhdXQhCg==
-EOF
+       cat >expected <<-\EOF
+       RGllc2VyIEJldHJlZmYgZW50aMOkbHQgYXVjaCBlaW5lbiBVbWxhdXQhCg==
+       EOF
 '
 
 test_expect_success $PREREQ '8-bit and sendemail.transferencoding=base64' '
        clean_fake_sendmail &&
        git send-email \
-         --transfer-encoding=base64 \
-         --smtp-server="$(pwd)/fake.sendmail" \
-         email-using-8bit \
-         2>errors >out &&
+               --transfer-encoding=base64 \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               email-using-8bit \
+               2>errors >out &&
        sed '1,/^$/d' msgtxt1 >actual &&
        test_cmp expected actual
 '
 
 test_expect_success $PREREQ 'setup expect' '
-cat >email-using-qp <<EOF
-From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
-Message-Id: <bogus-message-id@example.com>
-From: A U Thor <author@example.com>
-Date: Sat, 12 Jun 2010 15:53:58 +0200
-MIME-Version: 1.0
-Content-Transfer-Encoding: quoted-printable
-Content-Type: text/plain; charset=UTF-8
-Subject: Nothing to see here.
-
-Dieser Betreff enth=C3=A4lt auch einen Umlaut!
-EOF
+       cat >email-using-qp <<-\EOF
+       From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
+       Message-Id: <bogus-message-id@example.com>
+       From: A U Thor <author@example.com>
+       Date: Sat, 12 Jun 2010 15:53:58 +0200
+       MIME-Version: 1.0
+       Content-Transfer-Encoding: quoted-printable
+       Content-Type: text/plain; charset=UTF-8
+       Subject: Nothing to see here.
+
+       Dieser Betreff enth=C3=A4lt auch einen Umlaut!
+       EOF
 '
 
 test_expect_success $PREREQ 'convert from quoted-printable to base64' '
        clean_fake_sendmail &&
        git send-email \
-         --transfer-encoding=base64 \
-         --smtp-server="$(pwd)/fake.sendmail" \
-         email-using-qp \
-         2>errors >out &&
+               --transfer-encoding=base64 \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               email-using-qp \
+               2>errors >out &&
        sed '1,/^$/d' msgtxt1 >actual &&
        test_cmp expected actual
 '
 
 test_expect_success $PREREQ 'setup expect' "
-tr -d '\\015' | tr '%' '\\015' > email-using-crlf <<EOF
+tr -d '\\015' | tr '%' '\\015' >email-using-crlf <<EOF
 From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001
 Message-Id: <bogus-message-id@example.com>
 From: A U Thor <author@example.com>
@@ -1421,35 +1421,35 @@ EOF
 "
 
 test_expect_success $PREREQ 'setup expect' '
-cat >expected <<EOF
-Look, I have a CRLF and an =3D sign!=0D
-EOF
+       cat >expected <<-\EOF
+       Look, I have a CRLF and an =3D sign!=0D
+       EOF
 '
 
 test_expect_success $PREREQ 'CRLF and sendemail.transferencoding=quoted-printable' '
        clean_fake_sendmail &&
        git send-email \
-         --transfer-encoding=quoted-printable \
-         --smtp-server="$(pwd)/fake.sendmail" \
-         email-using-crlf \
-         2>errors >out &&
+               --transfer-encoding=quoted-printable \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               email-using-crlf \
+               2>errors >out &&
        sed '1,/^$/d' msgtxt1 >actual &&
        test_cmp expected actual
 '
 
 test_expect_success $PREREQ 'setup expect' '
-cat >expected <<EOF
-TG9vaywgSSBoYXZlIGEgQ1JMRiBhbmQgYW4gPSBzaWduIQ0K
-EOF
+       cat >expected <<-\EOF
+       TG9vaywgSSBoYXZlIGEgQ1JMRiBhbmQgYW4gPSBzaWduIQ0K
+       EOF
 '
 
 test_expect_success $PREREQ 'CRLF and sendemail.transferencoding=base64' '
        clean_fake_sendmail &&
        git send-email \
-         --transfer-encoding=base64 \
-         --smtp-server="$(pwd)/fake.sendmail" \
-         email-using-crlf \
-         2>errors >out &&
+               --transfer-encoding=base64 \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               email-using-crlf \
+               2>errors >out &&
        sed '1,/^$/d' msgtxt1 >actual &&
        test_cmp expected actual
 '
@@ -1463,13 +1463,13 @@ test_expect_success $PREREQ 'refusing to send cover letter template' '
        rm -fr outdir &&
        git format-patch --cover-letter -2 -o outdir &&
        test_must_fail git send-email \
-         --from="Example <nobody@example.com>" \
-         --to=nobody@example.com \
-         --smtp-server="$(pwd)/fake.sendmail" \
-         outdir/0002-*.patch \
-         outdir/0000-*.patch \
-         outdir/0001-*.patch \
-         2>errors >out &&
+               --from="Example <nobody@example.com>" \
+               --to=nobody@example.com \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               outdir/0002-*.patch \
+               outdir/0000-*.patch \
+               outdir/0001-*.patch \
+               2>errors >out &&
        grep "SUBJECT HERE" errors &&
        test -z "$(ls msgtxt*)"
 '
@@ -1479,14 +1479,14 @@ test_expect_success $PREREQ '--force sends cover letter template anyway' '
        rm -fr outdir &&
        git format-patch --cover-letter -2 -o outdir &&
        git send-email \
-         --force \
-         --from="Example <nobody@example.com>" \
-         --to=nobody@example.com \
-         --smtp-server="$(pwd)/fake.sendmail" \
-         outdir/0002-*.patch \
-         outdir/0000-*.patch \
-         outdir/0001-*.patch \
-         2>errors >out &&
+               --force \
+               --from="Example <nobody@example.com>" \
+               --to=nobody@example.com \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               outdir/0002-*.patch \
+               outdir/0000-*.patch \
+               outdir/0001-*.patch \
+               2>errors >out &&
        ! grep "SUBJECT HERE" errors &&
        test -n "$(ls msgtxt*)"
 '
@@ -1501,15 +1501,15 @@ test_cover_addresses () {
        mv $cover cover-to-edit.patch &&
        perl -pe "s/^From:/$header: extra\@address.com\nFrom:/" cover-to-edit.patch >"$cover" &&
        git send-email \
-         --force \
-         --from="Example <nobody@example.com>" \
-         --no-to --no-cc \
-         "$@" \
-         --smtp-server="$(pwd)/fake.sendmail" \
-         outdir/0000-*.patch \
-         outdir/0001-*.patch \
-         outdir/0002-*.patch \
-         2>errors >out &&
+               --force \
+               --from="Example <nobody@example.com>" \
+               --no-to --no-cc \
+               "$@" \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               outdir/0000-*.patch \
+               outdir/0001-*.patch \
+               outdir/0002-*.patch \
+               2>errors >out &&
        grep "^$header: extra@address.com" msgtxt1 >to1 &&
        grep "^$header: extra@address.com" msgtxt2 >to2 &&
        grep "^$header: extra@address.com" msgtxt3 >to3 &&
@@ -1542,11 +1542,11 @@ test_expect_success $PREREQ 'sendemail.aliasfiletype=mailrc' '
        git config --replace-all sendemail.aliasesfile "$(pwd)/.mailrc" &&
        git config sendemail.aliasfiletype mailrc &&
        git send-email \
-         --from="Example <nobody@example.com>" \
-         --to=sbd \
-         --smtp-server="$(pwd)/fake.sendmail" \
-         outdir/0001-*.patch \
-         2>errors >out &&
+               --from="Example <nobody@example.com>" \
+               --to=sbd \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               outdir/0001-*.patch \
+               2>errors >out &&
        grep "^!somebody@example\.org!$" commandline1
 '
 
@@ -1556,12 +1556,45 @@ test_expect_success $PREREQ 'sendemail.aliasfile=~/.mailrc' '
        git config --replace-all sendemail.aliasesfile "~/.mailrc" &&
        git config sendemail.aliasfiletype mailrc &&
        git send-email \
-         --from="Example <nobody@example.com>" \
-         --to=sbd \
-         --smtp-server="$(pwd)/fake.sendmail" \
-         outdir/0001-*.patch \
-         2>errors >out &&
+               --from="Example <nobody@example.com>" \
+               --to=sbd \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               outdir/0001-*.patch \
+               2>errors >out &&
        grep "^!someone@example\.org!$" commandline1
 '
 
+do_xmailer_test () {
+       expected=$1 params=$2 &&
+       git format-patch -1 &&
+       git send-email \
+               --from="Example <nobody@example.com>" \
+               --to=someone@example.com \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               $params \
+               0001-*.patch \
+               2>errors >out &&
+       { grep '^X-Mailer:' out || :; } >mailer &&
+       test_line_count = $expected mailer
+}
+
+test_expect_success $PREREQ '--[no-]xmailer without any configuration' '
+       do_xmailer_test 1 "--xmailer" &&
+       do_xmailer_test 0 "--no-xmailer"
+'
+
+test_expect_success $PREREQ '--[no-]xmailer with sendemail.xmailer=true' '
+       test_config sendemail.xmailer true &&
+       do_xmailer_test 1 "" &&
+       do_xmailer_test 0 "--no-xmailer" &&
+       do_xmailer_test 1 "--xmailer"
+'
+
+test_expect_success $PREREQ '--[no-]xmailer with sendemail.xmailer=false' '
+       test_config sendemail.xmailer false &&
+       do_xmailer_test 0 "" &&
+       do_xmailer_test 0 "--no-xmailer" &&
+       do_xmailer_test 1 "--xmailer"
+'
+
 test_done
diff --git a/t/t9148-git-svn-propset.sh b/t/t9148-git-svn-propset.sh
new file mode 100755 (executable)
index 0000000..1026390
--- /dev/null
@@ -0,0 +1,95 @@
+#!/bin/sh
+#
+# Copyright (c) 2014 Alfred Perlstein
+#
+
+test_description='git svn propset tests'
+
+. ./lib-git-svn.sh
+
+foo_subdir2="subdir/subdir2/foo_subdir2"
+
+set -e
+mkdir import &&
+(set -e ; cd import
+       mkdir subdir
+       mkdir subdir/subdir2
+       touch foo               # for 'add props top level'
+       touch subdir/foo_subdir # for 'add props relative'
+       touch "$foo_subdir2"    # for 'add props subdir'
+       svn_cmd import -m 'import for git svn' . "$svnrepo" >/dev/null
+)
+rm -rf import
+
+test_expect_success 'initialize git svn' '
+       git svn init "$svnrepo"
+       '
+
+test_expect_success 'fetch revisions from svn' '
+       git svn fetch
+       '
+
+set_props () {
+       subdir="$1"
+       file="$2"
+       shift;shift;
+       (cd "$subdir" &&
+               while [ $# -gt 0 ] ; do
+                       git svn propset "$1" "$2" "$file" || exit 1
+                       shift;shift;
+               done &&
+               echo hello >> "$file" &&
+               git commit -m "testing propset" "$file")
+}
+
+confirm_props () {
+       subdir="$1"
+       file="$2"
+       shift;shift;
+       (set -e ; cd "svn_project/$subdir" &&
+               while [ $# -gt 0 ] ; do
+                       test "$(svn_cmd propget "$1" "$file")" = "$2" || exit 1
+                       shift;shift;
+               done)
+}
+
+
+#The current implementation has a restriction:
+#svn propset will be taken as a delta for svn dcommit only
+#if the file content is also modified
+test_expect_success 'add props top level' '
+       set_props "." "foo" "svn:keywords" "FreeBSD=%H" &&
+       git svn dcommit &&
+       svn_cmd co "$svnrepo" svn_project &&
+       confirm_props "." "foo" "svn:keywords" "FreeBSD=%H" &&
+       rm -rf svn_project
+       '
+
+test_expect_success 'add multiple props' '
+       set_props "." "foo" \
+               "svn:keywords" "FreeBSD=%H" fbsd:nokeywords yes &&
+       git svn dcommit &&
+       svn_cmd co "$svnrepo" svn_project &&
+       confirm_props "." "foo" \
+               "svn:keywords" "FreeBSD=%H" fbsd:nokeywords yes &&
+       rm -rf svn_project
+       '
+
+test_expect_success 'add props subdir' '
+       set_props "." "$foo_subdir2" svn:keywords "FreeBSD=%H" &&
+       git svn dcommit &&
+       svn_cmd co "$svnrepo" svn_project &&
+       confirm_props "." "$foo_subdir2" "svn:keywords" "FreeBSD=%H" &&
+       rm -rf svn_project
+       '
+
+test_expect_success 'add props relative' '
+       set_props "subdir/subdir2" "../foo_subdir" \
+               svn:keywords "FreeBSD=%H" &&
+       git svn dcommit &&
+       svn_cmd co "$svnrepo" svn_project &&
+       confirm_props "subdir/subdir2" "../foo_subdir" \
+               svn:keywords "FreeBSD=%H" &&
+       rm -rf svn_project
+       '
+test_done
index 69e3c67b00f482449e77945eb114f58244078b1e..6187dbf4390fc6e28445dd3d988aefb9d1111988 100755 (executable)
@@ -24,7 +24,6 @@ url="$2"
 
 z40=0000000000000000000000000000000000000000
 
-IFS=' '
 while read local_ref local_sha remote_ref remote_sha
 do
        if [ "$local_sha" = $z40 ]
index 70d38e4c4b35c6207e226ab7cb54095c34bb4766..08bcd3a4eba42d2e72b9d84ec89e190c763300fa 100644 (file)
@@ -971,9 +971,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
        } else {
                /* Unknown protocol in URL. Pass to external handler. */
                int len = external_specification_len(url);
-               char *handler = xmalloc(len + 1);
-               handler[len] = 0;
-               strncpy(handler, url, len);
+               char *handler = xmemdupz(url, len);
                transport_helper_init(ret, handler);
        }
 
index 000b937e6828d378829cfe8a25e93ce07c531574..27af77c7df63f8a9039d77b332ebb06d69f02f65 100755 (executable)
@@ -27,11 +27,14 @@ fi &&
                fi &&
                make
        ) &&
-       echo "static const struct interval zero_width[] = {" >$UNICODEWIDTH_H &&
-       UNICODE_DIR=. ./uniset/uniset --32 cat:Me,Mn,Cf + U+1160..U+11FF - U+00AD |
-       grep -v plane >>$UNICODEWIDTH_H &&
-       echo "};" >>$UNICODEWIDTH_H &&
-       echo "static const struct interval double_width[] = {" >>$UNICODEWIDTH_H &&
-       UNICODE_DIR=. ./uniset/uniset --32 eaw:F,W >>$UNICODEWIDTH_H &&
-       echo "};" >>$UNICODEWIDTH_H
+       UNICODE_DIR=. && export UNICODE_DIR &&
+       cat >$UNICODEWIDTH_H <<-EOF
+       static const struct interval zero_width[] = {
+               $(uniset/uniset --32 cat:Me,Mn,Cf + U+1160..U+11FF - U+00AD |
+                 grep -v plane)
+       };
+       static const struct interval double_width[] = {
+               $(uniset/uniset --32 eaw:F,W)
+       };
+       EOF
 )
index ac9ac1592d818da5ae90ec065581e3bf218ffc39..b531a325d2864e94bdc86e689f78663255bb7cf2 100644 (file)
@@ -86,7 +86,7 @@ static void create_pack_file(void)
                "corruption on the remote side.";
        int buffered = -1;
        ssize_t sz;
-       const char *argv[12];
+       const char *argv[13];
        int i, arg = 0;
        FILE *pipe_fd;
 
@@ -100,6 +100,8 @@ static void create_pack_file(void)
                argv[arg++] = "--thin";
 
        argv[arg++] = "--stdout";
+       if (shallow_nr)
+               argv[arg++] = "--shallow";
        if (!no_progress)
                argv[arg++] = "--progress";
        if (use_ofs_delta)
diff --git a/utf8.c b/utf8.c
index 9a3f4ad23293bf6a3fc06a1942fd324fa1b74ded..520fbb4994ab1bdcfa0bc4589a0ca5131a89c490 100644 (file)
--- a/utf8.c
+++ b/utf8.c
@@ -563,8 +563,8 @@ int mbs_chrlen(const char **text, size_t *remainder_p, const char *encoding)
 }
 
 /*
- * Pick the next char from the stream, folding as an HFS+ filename comparison
- * would. Note that this is _not_ complete by any means. It's just enough
+ * Pick the next char from the stream, ignoring codepoints an HFS+ would.
+ * Note that this is _not_ complete by any means. It's just enough
  * to make is_hfs_dotgit() work, and should not be used otherwise.
  */
 static ucs_char_t next_hfs_char(const char **in)
@@ -601,12 +601,7 @@ static ucs_char_t next_hfs_char(const char **in)
                        continue;
                }
 
-               /*
-                * there's a great deal of other case-folding that occurs,
-                * but this is enough to catch anything that will convert
-                * to ".git"
-                */
-               return tolower(out);
+               return out;
        }
 }
 
@@ -614,10 +609,23 @@ int is_hfs_dotgit(const char *path)
 {
        ucs_char_t c;
 
-       if (next_hfs_char(&path) != '.' ||
-           next_hfs_char(&path) != 'g' ||
-           next_hfs_char(&path) != 'i' ||
-           next_hfs_char(&path) != 't')
+       c = next_hfs_char(&path);
+       if (c != '.')
+               return 0;
+       c = next_hfs_char(&path);
+
+       /*
+        * there's a great deal of other case-folding that occurs
+        * in HFS+, but this is enough to catch anything that will
+        * convert to ".git"
+        */
+       if (c != 'g' && c != 'G')
+               return 0;
+       c = next_hfs_char(&path);
+       if (c != 'i' && c != 'I')
+               return 0;
+       c = next_hfs_char(&path);
+       if (c != 't' && c != 'T')
                return 0;
        c = next_hfs_char(&path);
        if (c && !is_dir_sep(c))