Merge branch 'rh/test-color-avoid-terminfo-in-original-home'
authorJunio C Hamano <gitster@pobox.com>
Wed, 14 Jan 2015 20:36:45 +0000 (12:36 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 14 Jan 2015 20:36:45 +0000 (12:36 -0800)
We try to see if "tput" gives a useful result before switching TERM
to dumb and moving HOME to point to our fake location for stability
of the tests, and then use the command when coloring the output
from the tests, but there is no guarantee "tput" works after
switching HOME.

* rh/test-color-avoid-terminfo-in-original-home:
test-lib.sh: do tests for color support after changing HOME
test-lib: use 'test ...' instead of '[ ... ]'

71 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/log.c
builtin/merge-base.c
builtin/merge.c
builtin/pack-objects.c
builtin/remote.c
builtin/rev-parse.c
commit.c
commit.h
contrib/completion/git-completion.bash
contrib/completion/git-completion.zsh
contrib/completion/git-prompt.sh
contrib/subtree/git-subtree.txt
date.c
diffcore-break.c
git-add--interactive.perl
git-bisect.sh
git-compat-util.h
git-send-email.perl
imap-send.c
list-objects.c
lockfile.c
merge-recursive.c
notes-merge.c
refs.c
remote.c
revision.c
revision.h
send-pack.c
server-info.c
sha1_name.c
strbuf.c
submodule.c
t/t0006-date.sh
t/t0030-stripspace.sh
t/t0090-cache-tree.sh
t/t1301-shared-repo.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/t5505-remote.sh
t/t5700-clone-reference.sh
t/t6030-bisect-porcelain.sh
t/t9001-send-email.sh
t/t9903-bash-prompt.sh
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..f248a8665e1f775edb6932af69b68b7081e1687c 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
 ~~~~~~~
@@ -209,10 +214,15 @@ must be used for each option.
        Legacy alias for '--smtp-encryption ssl'.
 
 --smtp-ssl-cert-path::
-       Path to ca-certificates (either a directory or a single file).
-       Set it to an empty string to disable certificate verification.
-       Defaults to the value set to the 'sendemail.smtpsslcertpath'
-       configuration variable, if set, or `/etc/ssl/certs` otherwise.
+       Path to a store of trusted CA certificates for SMTP SSL/TLS
+       certificate validation (either a directory that has been processed
+       by 'c_rehash', or a single file containing one or more PEM format
+       certificates concatenated together: see verify(1) -CAfile and
+       -CApath for more information on these). Set it to an empty string
+       to disable certificate verification. Defaults to the value of the
+       'sendemail.smtpsslcertpath' configuration variable, if set, or the
+       backing SSL library's compiled-in default otherwise (which should
+       be the best choice on most platforms).
 
 --smtp-user=<user>::
        Username for SMTP-AUTH. Default is the value of 'sendemail.smtpuser';
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 f2a9f0156d8a8b15c7c879355b137b669dea8cf2..923ffe72ced41f12a2258f732be418731bc2e4a8 100644 (file)
@@ -38,8 +38,8 @@ static const char *fmt_patch_subject_prefix = "PATCH";
 static const char *fmt_pretty;
 
 static const char * const builtin_log_usage[] = {
-       N_("git log [<options>] [<revision range>] [[--] <path>...]\n")
-       N_("   or: git show [options] <object>..."),
+       N_("git log [<options>] [<revision range>] [[--] <path>...]"),
+       N_("git show [options] <object>..."),
        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 46ecfd9f7b0dd0b28169341d14132df376e509bc..b4ff4689770e402675faba2ce400150b4803a360 100644 (file)
@@ -180,7 +180,9 @@ static int add(int argc, const char **argv)
        url = argv[1];
 
        remote = remote_get(name);
-       if (remote && (remote->url_nr > 1 || strcmp(name, remote->url[0]) ||
+       if (remote && (remote->url_nr > 1 ||
+                       (strcmp(name, remote->url[0]) &&
+                               strcmp(url, remote->url[0])) ||
                        remote->fetch_refspec_nr))
                die(_("remote %s already exists."), name);
 
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 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..8cfee95f88006269e4227f98701b9af8587af0bd 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.
 #
@@ -1693,6 +1693,7 @@ _git_rebase ()
                        --committer-date-is-author-date --ignore-date
                        --ignore-whitespace --whitespace=
                        --autosquash --fork-point --no-fork-point
+                       --autostash
                        "
 
                return
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..214e859f99e7d896a6fa45a737b5b3e2a629176f 100644 (file)
 # GIT_PS1_SHOWCOLORHINTS to a nonempty value. The colors are based on
 # the colored output of "git status -sb" and are available only when
 # using __git_ps1 for PROMPT_COMMAND or precmd.
+#
+# If you would like __git_ps1 to do nothing in the case when the current
+# directory is set up to be ignored by git, then set
+# GIT_PS1_HIDE_IF_PWD_IGNORED to a nonempty value. Override this on the
+# repository level by setting bash.hideIfPwdIgnored to "false".
 
 # check whether printf supports -v
 __git_printf_supports_v=
@@ -288,6 +293,8 @@ __git_eread ()
 # In this mode you can request colored hints using GIT_PS1_SHOWCOLORHINTS=true
 __git_ps1 ()
 {
+       # preserve exit status
+       local exit=$?
        local pcmode=no
        local detached=no
        local ps1pc_start='\u@\h:\w '
@@ -299,10 +306,14 @@ __git_ps1 ()
                        ps1pc_start="$1"
                        ps1pc_end="$2"
                        printf_format="${3:-$printf_format}"
+                       # set PS1 to a plain prompt so that we can
+                       # simply return early if the prompt should not
+                       # be decorated
+                       PS1="$ps1pc_start$ps1pc_end"
                ;;
                0|1)    printf_format="${1:-$printf_format}"
                ;;
-               *)      return
+               *)      return $exit
                ;;
        esac
 
@@ -350,11 +361,7 @@ __git_ps1 ()
        rev_parse_exit_code="$?"
 
        if [ -z "$repo_info" ]; then
-               if [ $pcmode = yes ]; then
-                       #In PC mode PS1 always needs to be set
-                       PS1="$ps1pc_start$ps1pc_end"
-               fi
-               return
+               return $exit
        fi
 
        local short_sha
@@ -369,6 +376,14 @@ __git_ps1 ()
        local inside_gitdir="${repo_info##*$'\n'}"
        local g="${repo_info%$'\n'*}"
 
+       if [ "true" = "$inside_worktree" ] &&
+          [ -n "${GIT_PS1_HIDE_IF_PWD_IGNORED-}" ] &&
+          [ "$(git config --bool bash.hideIfPwdIgnored)" != "false" ] &&
+          git check-ignore -q .
+       then
+               return $exit
+       fi
+
        local r=""
        local b=""
        local step=""
@@ -412,10 +427,7 @@ __git_ps1 ()
                else
                        local head=""
                        if ! __git_eread "$g/HEAD" head; then
-                               if [ $pcmode = yes ]; then
-                                       PS1="$ps1pc_start$ps1pc_end"
-                               fi
-                               return
+                               return $exit
                        fi
                        # is it a symbolic ref?
                        b="${head#ref: }"
@@ -511,4 +523,6 @@ __git_ps1 ()
        else
                printf -- "$printf_format" "$gitstring"
        fi
+
+       return $exit
 }
index 8272100ff56973417d426af33687f4e08c4a9e7b..54e4b4a24331045d97d92355b681b675048a5df7 100644 (file)
@@ -81,12 +81,11 @@ merge::
        changes into the latest <commit>.  With '--squash',
        creates only one commit that contains all the changes,
        rather than merging in the entire history.
-
-       If you use '--squash', the merge direction doesn't
-       always have to be forward; you can use this command to
-       go back in time from v2.5 to v2.4, for example.  If your
-       merge introduces a conflict, you can resolve it in the
-       usual ways.
++
+If you use '--squash', the merge direction doesn't always have to be
+forward; you can use this command to go back in time from v2.5 to v2.4,
+for example.  If your merge introduces a conflict, you can resolve it in
+the usual ways.
        
 pull::
        Exactly like 'merge', but parallels 'git pull' in that
@@ -107,21 +106,19 @@ split::
        contents of <prefix> at the root of the project instead
        of in a subdirectory.  Thus, the newly created history
        is suitable for export as a separate git repository.
-       
-       After splitting successfully, a single commit id is
-       printed to stdout.  This corresponds to the HEAD of the
-       newly created tree, which you can manipulate however you
-       want.
-       
-       Repeated splits of exactly the same history are
-       guaranteed to be identical (i.e. to produce the same
-       commit ids).  Because of this, if you add new commits
-       and then re-split, the new commits will be attached as
-       commits on top of the history you generated last time,
-       so 'git merge' and friends will work as expected.
-       
-       Note that if you use '--squash' when you merge, you
-       should usually not just '--rejoin' when you split.
++
+After splitting successfully, a single commit id is printed to stdout.
+This corresponds to the HEAD of the newly created tree, which you can
+manipulate however you want.
++
+Repeated splits of exactly the same history are guaranteed to be
+identical (i.e. to produce the same commit ids).  Because of this, if
+you add new commits and then re-split, the new commits will be attached
+as commits on top of the history you generated last time, so 'git merge'
+and friends will work as expected.
++
+Note that if you use '--squash' when you merge, you should usually not
+just '--rejoin' when you split.
 
 
 OPTIONS
@@ -151,109 +148,96 @@ OPTIONS FOR add, merge, push, pull
 --squash::
        This option is only valid for add, merge, push and pull
        commands.
-
-       Instead of merging the entire history from the subtree
-       project, produce only a single commit that contains all
-       the differences you want to merge, and then merge that
-       new commit into your project.
-       
-       Using this option helps to reduce log clutter. People
-       rarely want to see every change that happened between
-       v1.0 and v1.1 of the library they're using, since none of the
-       interim versions were ever included in their application.
-       
-       Using '--squash' also helps avoid problems when the same
-       subproject is included multiple times in the same
-       project, or is removed and then re-added.  In such a
-       case, it doesn't make sense to combine the histories
-       anyway, since it's unclear which part of the history
-       belongs to which subtree.
-       
-       Furthermore, with '--squash', you can switch back and
-       forth between different versions of a subtree, rather
-       than strictly forward.  'git subtree merge --squash'
-       always adjusts the subtree to match the exactly
-       specified commit, even if getting to that commit would
-       require undoing some changes that were added earlier.
-       
-       Whether or not you use '--squash', changes made in your
-       local repository remain intact and can be later split
-       and send upstream to the subproject.
++
+Instead of merging the entire history from the subtree project, produce
+only a single commit that contains all the differences you want to
+merge, and then merge that new commit into your project.
++
+Using this option helps to reduce log clutter. People rarely want to see
+every change that happened between v1.0 and v1.1 of the library they're
+using, since none of the interim versions were ever included in their
+application.
++
+Using '--squash' also helps avoid problems when the same subproject is
+included multiple times in the same project, or is removed and then
+re-added.  In such a case, it doesn't make sense to combine the
+histories anyway, since it's unclear which part of the history belongs
+to which subtree.
++
+Furthermore, with '--squash', you can switch back and forth between
+different versions of a subtree, rather than strictly forward.  'git
+subtree merge --squash' always adjusts the subtree to match the exactly
+specified commit, even if getting to that commit would require undoing
+some changes that were added earlier.
++
+Whether or not you use '--squash', changes made in your local repository
+remain intact and can be later split and send upstream to the
+subproject.
 
 
 OPTIONS FOR split
 -----------------
 --annotate=<annotation>::
        This option is only valid for the split command.
-
-       When generating synthetic history, add <annotation> as a
-       prefix to each commit message.  Since we're creating new
-       commits with the same commit message, but possibly
-       different content, from the original commits, this can help
-       to differentiate them and avoid confusion.
-       
-       Whenever you split, you need to use the same
-       <annotation>, or else you don't have a guarantee that
-       the new re-created history will be identical to the old
-       one.  That will prevent merging from working correctly. 
-       git subtree tries to make it work anyway, particularly
-       if you use --rejoin, but it may not always be effective.
++
+When generating synthetic history, add <annotation> as a prefix to each
+commit message.  Since we're creating new commits with the same commit
+message, but possibly different content, from the original commits, this
+can help to differentiate them and avoid confusion.
++
+Whenever you split, you need to use the same <annotation>, or else you
+don't have a guarantee that the new re-created history will be identical
+to the old one.  That will prevent merging from working correctly.  git
+subtree tries to make it work anyway, particularly if you use --rejoin,
+but it may not always be effective.
 
 -b <branch>::
 --branch=<branch>::
        This option is only valid for the split command.
-
-       After generating the synthetic history, create a new
-       branch called <branch> that contains the new history. 
-       This is suitable for immediate pushing upstream. 
-       <branch> must not already exist.
++
+After generating the synthetic history, create a new branch called
+<branch> that contains the new history.  This is suitable for immediate
+pushing upstream.  <branch> must not already exist.
 
 --ignore-joins::
        This option is only valid for the split command.
-
-       If you use '--rejoin', git subtree attempts to optimize
-       its history reconstruction to generate only the new
-       commits since the last '--rejoin'.  '--ignore-join'
-       disables this behaviour, forcing it to regenerate the
-       entire history.  In a large project, this can take a
-       long time.
++
+If you use '--rejoin', git subtree attempts to optimize its history
+reconstruction to generate only the new commits since the last
+'--rejoin'.  '--ignore-join' disables this behaviour, forcing it to
+regenerate the entire history.  In a large project, this can take a long
+time.
 
 --onto=<onto>::
        This option is only valid for the split command.
-
-       If your subtree was originally imported using something
-       other than git subtree, its history may not match what
-       git subtree is expecting.  In that case, you can specify
-       the commit id <onto> that corresponds to the first
-       revision of the subproject's history that was imported
-       into your project, and git subtree will attempt to build
-       its history from there.
-       
-       If you used 'git subtree add', you should never need
-       this option.
++
+If your subtree was originally imported using something other than git
+subtree, its history may not match what git subtree is expecting.  In
+that case, you can specify the commit id <onto> that corresponds to the
+first revision of the subproject's history that was imported into your
+project, and git subtree will attempt to build its history from there.
++
+If you used 'git subtree add', you should never need this option.
 
 --rejoin::
        This option is only valid for the split command.
-
-       After splitting, merge the newly created synthetic
-       history back into your main project.  That way, future
-       splits can search only the part of history that has
-       been added since the most recent --rejoin.
-       
-       If your split commits end up merged into the upstream
-       subproject, and then you want to get the latest upstream
-       version, this will allow git's merge algorithm to more
-       intelligently avoid conflicts (since it knows these
-       synthetic commits are already part of the upstream
-       repository).
-       
-       Unfortunately, using this option results in 'git log'
-       showing an extra copy of every new commit that was
-       created (the original, and the synthetic one).
-       
-       If you do all your merges with '--squash', don't use
-       '--rejoin' when you split, because you don't want the
-       subproject's history to be part of your project anyway.
++
+After splitting, merge the newly created synthetic history back into
+your main project.  That way, future splits can search only the part of
+history that has been added since the most recent --rejoin.
++
+If your split commits end up merged into the upstream subproject, and
+then you want to get the latest upstream version, this will allow git's
+merge algorithm to more intelligently avoid conflicts (since it knows
+these synthetic commits are already part of the upstream repository).
++
+Unfortunately, using this option results in 'git log' showing an extra
+copy of every new commit that was created (the original, and the
+synthetic one).
++
+If you do all your merges with '--squash', don't use '--rejoin' when you
+split, because you don't want the subproject's history to be part of
+your project anyway.
 
 
 EXAMPLE 1. Add command
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 70bcc7a4e533bb04e8c515e8831a75ec93d2d066..d69887da5a8530b204a5f5baf7081787224fc3bd 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_TRY);
+
+       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 || getenv("GIT_CURL_VERBOSE"))
+               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;
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 31f4a749fbad73b9f7bc1f1ebf9b11fd743ab374..34b0253177a0e6d09e317064cd3ec31e26002520 100644 (file)
@@ -17,7 +17,7 @@ static int update_info_file(char *path, int (*generate)(FILE *))
        FILE *fp = NULL;
 
        safe_create_leading_directories(path);
-       fd = mkstemp(tmp);
+       fd = git_mkstemp_mode(tmp, 0666);
        if (fd < 0)
                goto out;
        fp = fdopen(fd, "w");
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 de42d21c922045415abedf3c81163682d0754eb5..7eecfb836a05cac56b8eca1ac56f67e8b22b1fbd 100755 (executable)
@@ -111,7 +111,18 @@ do
 
 done
 
+test_expect_success POSIXPERM 'info/refs respects umask in unshared repo' '
+       rm -f .git/info/refs &&
+       test_unconfig core.sharedrepository &&
+       umask 002 &&
+       git update-server-info &&
+       echo "-rw-rw-r--" >expect &&
+       modebits .git/info/refs >actual &&
+       test_cmp expect actual
+'
+
 test_expect_success POSIXPERM 'git reflog expire honors core.sharedRepository' '
+       umask 077 &&
        git config core.sharedRepository group &&
        git reflog expire --all &&
        actual="$(ls -l .git/logs/refs/heads/master)" &&
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 ac79dd915da4a520e90fca6a11a239aba6e688d7..17c6330f988ecc98735307fbfd8bded5283feb61 100755 (executable)
@@ -1113,4 +1113,9 @@ test_extra_arg set-url origin newurl oldurl
 # prune takes any number of args
 # update takes any number of args
 
+test_expect_success 'add remote matching the "insteadOf" URL' '
+       git config url.xyz@example.com.insteadOf backup &&
+       git remote add backup xyz@example.com
+'
+
 test_done
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 e37efef5ca6fce69b0ec5e0103a2ca9f5f5cb234..af6a3e8904ab1d953b359707de1e0c9a09b3ce1f 100755 (executable)
@@ -242,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'
@@ -1557,4 +1564,37 @@ test_expect_success $PREREQ 'sendemail.aliasfile=~/.mailrc' '
        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
index 915098418495b488b748db9e610c79f81223a960..51ecd3e4c157ea267557a4484d574748b9757bd4 100755 (executable)
@@ -35,6 +35,8 @@ test_expect_success 'setup for prompt tests' '
        git commit -m "another b2" file &&
        echo 000 >file &&
        git commit -m "yet another b2" file &&
+       mkdir ignored_dir &&
+       echo "ignored_dir/" >>.gitignore &&
        git checkout master
 '
 
@@ -588,4 +590,108 @@ test_expect_success 'prompt - zsh color pc mode' '
        test_cmp expected "$actual"
 '
 
+test_expect_success 'prompt - hide if pwd ignored - env var unset, config disabled' '
+       printf " (master)" >expected &&
+       test_config bash.hideIfPwdIgnored false &&
+       (
+               cd ignored_dir &&
+               __git_ps1 >"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - hide if pwd ignored - env var unset, config disabled, pc mode' '
+       printf "BEFORE: (\${__git_ps1_branch_name}):AFTER" >expected &&
+       test_config bash.hideIfPwdIgnored false &&
+       (
+               cd ignored_dir &&
+               __git_ps1 "BEFORE:" ":AFTER" &&
+               printf "%s" "$PS1" >"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - hide if pwd ignored - env var unset, config unset' '
+       printf " (master)" >expected &&
+       (
+               cd ignored_dir &&
+               __git_ps1 >"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - hide if pwd ignored - env var unset, config unset, pc mode' '
+       printf "BEFORE: (\${__git_ps1_branch_name}):AFTER" >expected &&
+       (
+               cd ignored_dir &&
+               __git_ps1 "BEFORE:" ":AFTER" &&
+               printf "%s" "$PS1" >"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - hide if pwd ignored - env var set, config disabled' '
+       printf " (master)" >expected &&
+       test_config bash.hideIfPwdIgnored false &&
+       (
+               cd ignored_dir &&
+               GIT_PS1_HIDE_IF_PWD_IGNORED=y &&
+               __git_ps1 >"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - hide if pwd ignored - env var set, config disabled, pc mode' '
+       printf "BEFORE: (\${__git_ps1_branch_name}):AFTER" >expected &&
+       test_config bash.hideIfPwdIgnored false &&
+       (
+               cd ignored_dir &&
+               GIT_PS1_HIDE_IF_PWD_IGNORED=y &&
+               __git_ps1 "BEFORE:" ":AFTER" &&
+               printf "%s" "$PS1" >"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - hide if pwd ignored - env var set, config unset' '
+       printf "" >expected &&
+       (
+               cd ignored_dir &&
+               GIT_PS1_HIDE_IF_PWD_IGNORED=y &&
+               __git_ps1 >"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - hide if pwd ignored - env var set, config unset, pc mode' '
+       printf "BEFORE::AFTER" >expected &&
+       (
+               cd ignored_dir &&
+               GIT_PS1_HIDE_IF_PWD_IGNORED=y &&
+               __git_ps1 "BEFORE:" ":AFTER" &&
+               printf "%s" "$PS1" >"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - hide if pwd ignored - inside gitdir (stdout)' '
+       printf " (GIT_DIR!)" >expected &&
+       (
+               GIT_PS1_HIDE_IF_PWD_IGNORED=y &&
+               cd .git &&
+               __git_ps1 >"$actual" 2>/dev/null
+       ) &&
+       test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - hide if pwd ignored - inside gitdir (stderr)' '
+       printf "" >expected &&
+       (
+               GIT_PS1_HIDE_IF_PWD_IGNORED=y &&
+               cd .git &&
+               __git_ps1 >/dev/null 2>"$actual"
+       ) &&
+       test_cmp expected "$actual"
+'
+
 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))