Merge branch 'ls/travis-scriptify' into maint
authorJunio C Hamano <gitster@pobox.com>
Mon, 23 Oct 2017 05:17:53 +0000 (14:17 +0900)
committerJunio C Hamano <gitster@pobox.com>
Mon, 23 Oct 2017 05:17:53 +0000 (14:17 +0900)
The scripts to drive TravisCI has been reorganized and then an
optimization to avoid spending cycles on a branch whose tip is
tagged has been implemented.

* ls/travis-scriptify:
travis-ci: fix "skip_branch_tip_with_tag()" string comparison
travis: dedent a few scripts that are indented overly deeply
travis-ci: skip a branch build if equal tag is present
travis-ci: move Travis CI code into dedicated scripts

162 files changed:
.mailmap
Documentation/RelNotes/2.10.5.txt [new file with mode: 0644]
Documentation/RelNotes/2.11.4.txt [new file with mode: 0644]
Documentation/RelNotes/2.12.5.txt [new file with mode: 0644]
Documentation/RelNotes/2.13.6.txt [new file with mode: 0644]
Documentation/RelNotes/2.14.2.txt
Documentation/RelNotes/2.14.3.txt [new file with mode: 0644]
Documentation/config.txt
Documentation/git-add.txt
Documentation/git-branch.txt
Documentation/git-cat-file.txt
Documentation/git-checkout.txt
Documentation/git-for-each-ref.txt
Documentation/git-grep.txt
Documentation/git-merge.txt
Documentation/git-notes.txt
Documentation/git-pack-objects.txt
Documentation/git-read-tree.txt
Documentation/git-shell.txt
Documentation/git-status.txt
Documentation/git-tag.txt
Documentation/git-update-index.txt
Documentation/git.txt
Documentation/gitattributes.txt
Documentation/glossary-content.txt
Documentation/merge-strategies.txt
Documentation/technical/api-builtin.txt [deleted file]
Makefile
RelNotes
apply.c
apply.h
archive.c
branch.c
builtin.h
builtin/add.c
builtin/am.c
builtin/branch.c
builtin/cat-file.c
builtin/clean.c
builtin/clone.c
builtin/commit-tree.c
builtin/describe.c
builtin/fast-export.c
builtin/for-each-ref.c
builtin/fsck.c
builtin/gc.c
builtin/grep.c
builtin/merge.c
builtin/name-rev.c
builtin/rev-list.c
builtin/rev-parse.c
builtin/revert.c
builtin/show-branch.c
builtin/submodule--helper.c
builtin/tag.c
cache.h
color.c
commit.h
compat/poll/poll.c
compat/win32/syslog.c
config.c
contrib/coccinelle/array.cocci
contrib/completion/git-completion.bash
contrib/diff-highlight/Makefile
convert.c
convert.h
diff.c
exec_cmd.c
fast-import.c
fsck.c
git-archimport.perl
git-cvsimport.perl
git-cvsserver.perl
git-merge-octopus.sh
git-merge-one-file.sh
git-merge-resolve.sh
git-rebase--am.sh
git-rebase--interactive.sh
git-request-pull.sh
git-send-email.perl
git-stash.sh
git-submodule.sh
git.c
grep.c
http-push.c
mailinfo.c
path.c
perl/Git.pm
perl/Git/SVN.pm
pkt-line.c
ref-filter.c
refs.c
refs.h
revision.c
revision.h
run-command.c
sequencer.c
sha1-lookup.c
sha1-lookup.h
sha1_file.c
shell.c
strbuf.c
strbuf.h
string-list.h
sub-process.c
submodule.c
submodule.h
t/README
t/check-non-portable-shell.pl
t/helper/test-path-utils.c
t/helper/test-string-list.c
t/lib-gpg.sh
t/t0001-init.sh
t/t1002-read-tree-m-u-2way.sh
t/t1450-fsck.sh
t/t3200-branch.sh
t/t3203-branch-output.sh
t/t3205-branch-color.sh
t/t3418-rebase-continue.sh
t/t3504-cherry-pick-rerere.sh
t/t3700-add.sh
t/t3701-add-interactive.sh
t/t4015-diff-whitespace.sh
t/t4062-diff-pickaxe.sh
t/t4124-apply-ws-rule.sh
t/t4150-am.sh
t/t4202-log.sh
t/t5001-archive-attr.sh
t/t5002-archive-attr-pattern.sh
t/t5004-archive-corner-cases.sh
t/t5150-request-pull.sh
t/t5308-pack-detect-duplicates.sh
t/t5526-fetch-submodules.sh
t/t5531-deep-submodule-push.sh
t/t6002-rev-list-bisect.sh
t/t6006-rev-list-format.sh
t/t6018-rev-list-glob.sh
t/t6120-describe.sh
t/t6132-pathspec-exclude.sh
t/t6300-for-each-ref.sh
t/t7004-tag.sh
t/t7006-pager.sh
t/t7400-submodule-basic.sh
t/t7502-commit.sh
t/t7508-status.sh
t/t7600-merge.sh
t/t7810-grep.sh
t/t8010-cat-file-filters.sh
t/t9001-send-email.sh
t/t9300-fast-import.sh
t/t9350-fast-export.sh
t/t9400-git-cvsserver-server.sh
t/test-lib.sh
t/test-terminal.perl
tag.c
userdiff.c
vcs-svn/fast_export.c
vcs-svn/fast_export.h
vcs-svn/repo_tree.c [deleted file]
vcs-svn/repo_tree.h [deleted file]
vcs-svn/svndump.c
worktree.c
index ab85e0d16d6383b13954220a0b41202bd68d5d73..224db83887e7e875422742048e3f68274917291d 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -194,6 +194,7 @@ Philippe Bruhat <book@cpan.org>
 Ralf Thielow <ralf.thielow@gmail.com> <ralf.thielow@googlemail.com>
 Ramsay Jones <ramsay@ramsayjones.plus.com> <ramsay@ramsay1.demon.co.uk>
 René Scharfe <l.s.r@web.de> <rene.scharfe@lsrfire.ath.cx>
+René Scharfe <l.s.r@web.de> Rene Scharfe
 Richard Hansen <rhansen@rhansen.org> <hansenr@google.com>
 Richard Hansen <rhansen@rhansen.org> <rhansen@bbn.com>
 Robert Fitzsimons <robfitz@273k.net>
diff --git a/Documentation/RelNotes/2.10.5.txt b/Documentation/RelNotes/2.10.5.txt
new file mode 100644 (file)
index 0000000..a498fd6
--- /dev/null
@@ -0,0 +1,17 @@
+Git v2.10.5 Release Notes
+=========================
+
+Fixes since v2.10.4
+-------------------
+
+ * "git cvsserver" no longer is invoked by "git daemon" by default,
+   as it is old and largely unmaintained.
+
+ * Various Perl scripts did not use safe_pipe_capture() instead of
+   backticks, leaving them susceptible to end-user input.  They have
+   been corrected.
+
+Credits go to joernchen <joernchen@phenoelit.de> for finding the
+unsafe constructs in "git cvsserver", and to Jeff King at GitHub for
+finding and fixing instances of the same issue in other scripts.
+
diff --git a/Documentation/RelNotes/2.11.4.txt b/Documentation/RelNotes/2.11.4.txt
new file mode 100644 (file)
index 0000000..ad4da8e
--- /dev/null
@@ -0,0 +1,17 @@
+Git v2.11.4 Release Notes
+=========================
+
+Fixes since v2.11.3
+-------------------
+
+ * "git cvsserver" no longer is invoked by "git daemon" by default,
+   as it is old and largely unmaintained.
+
+ * Various Perl scripts did not use safe_pipe_capture() instead of
+   backticks, leaving them susceptible to end-user input.  They have
+   been corrected.
+
+Credits go to joernchen <joernchen@phenoelit.de> for finding the
+unsafe constructs in "git cvsserver", and to Jeff King at GitHub for
+finding and fixing instances of the same issue in other scripts.
+
diff --git a/Documentation/RelNotes/2.12.5.txt b/Documentation/RelNotes/2.12.5.txt
new file mode 100644 (file)
index 0000000..8fa73cf
--- /dev/null
@@ -0,0 +1,17 @@
+Git v2.12.5 Release Notes
+=========================
+
+Fixes since v2.12.4
+-------------------
+
+ * "git cvsserver" no longer is invoked by "git daemon" by default,
+   as it is old and largely unmaintained.
+
+ * Various Perl scripts did not use safe_pipe_capture() instead of
+   backticks, leaving them susceptible to end-user input.  They have
+   been corrected.
+
+Credits go to joernchen <joernchen@phenoelit.de> for finding the
+unsafe constructs in "git cvsserver", and to Jeff King at GitHub for
+finding and fixing instances of the same issue in other scripts.
+
diff --git a/Documentation/RelNotes/2.13.6.txt b/Documentation/RelNotes/2.13.6.txt
new file mode 100644 (file)
index 0000000..afcae9c
--- /dev/null
@@ -0,0 +1,17 @@
+Git v2.13.6 Release Notes
+=========================
+
+Fixes since v2.13.5
+-------------------
+
+ * "git cvsserver" no longer is invoked by "git daemon" by default,
+   as it is old and largely unmaintained.
+
+ * Various Perl scripts did not use safe_pipe_capture() instead of
+   backticks, leaving them susceptible to end-user input.  They have
+   been corrected.
+
+Credits go to joernchen <joernchen@phenoelit.de> for finding the
+unsafe constructs in "git cvsserver", and to Jeff King at GitHub for
+finding and fixing instances of the same issue in other scripts.
+
index 5517afcf5920b8fa023e2ba0babf6c4a1d92509b..bec9186adefe6eeec3d2dd18c871f5fd2047ff6a 100644 (file)
@@ -32,4 +32,74 @@ Fixes since v2.14.1
    daemon is torn down were flaky.  This was fixed by reacting to
    ECONNRESET and behaving as if we got an EOF.
 
+ * Some versions of GnuPG fail to kill gpg-agent it auto-spawned
+   and such a left-over agent can interfere with a test.  Work it
+   around by attempting to kill one before starting a new test.
+
+ * "git log --tag=no-such-tag" showed log starting from HEAD, which
+   has been fixed---it now shows nothing.
+
+ * The "tag.pager" configuration variable was useless for those who
+   actually create tag objects, as it interfered with the use of an
+   editor.  A new mechanism has been introduced for commands to enable
+   pager depending on what operation is being carried out to fix this,
+   and then "git tag -l" is made to run pager by default.
+
+ * "git push --recurse-submodules $there HEAD:$target" was not
+   propagated down to the submodules, but now it is.
+
+ * Commands like "git rebase" accepted the --rerere-autoupdate option
+   from the command line, but did not always use it.  This has been
+   fixed.
+
+ * "git clone --recurse-submodules --quiet" did not pass the quiet
+   option down to submodules.
+
+ * "git am -s" has been taught that some input may end with a trailer
+   block that is not Signed-off-by: and it should refrain from adding
+   an extra blank line before adding a new sign-off in such a case.
+
+ * "git svn" used with "--localtime" option did not compute the tz
+   offset for the timestamp in question and instead always used the
+   current time, which has been corrected.
+
+ * Memory leaks in a few error codepaths have been plugged.
+
+ * bash 4.4 or newer gave a warning on NUL byte in command
+   substitution done in "git stash"; this has been squelched.
+
+ * "git grep -L" and "git grep --quiet -L" reported different exit
+   codes; this has been corrected.
+
+ * When handshake with a subprocess filter notices that the process
+   asked for an unknown capability, Git did not report what program
+   the offending subprocess was running.  This has been corrected.
+
+ * "git apply" that is used as a better "patch -p1" failed to apply a
+   taken from a file with CRLF line endings to a file with CRLF line
+   endings.  The root cause was because it misused convert_to_git()
+   that tried to do "safe-crlf" processing by looking at the index
+   entry at the same path, which is a nonsense---in that mode, "apply"
+   is not working on the data in (or derived from) the index at all.
+   This has been fixed.
+
+ * Killing "git merge --edit" before the editor returns control left
+   the repository in a state with MERGE_MSG but without MERGE_HEAD,
+   which incorrectly tells the subsequent "git commit" that there was
+   a squash merge in progress.  This has been fixed.
+
+ * "git archive" did not work well with pathspecs and the
+   export-ignore attribute.
+
+ * "git cvsserver" no longer is invoked by "git daemon" by default,
+   as it is old and largely unmaintained.
+
+ * Various Perl scripts did not use safe_pipe_capture() instead of
+   backticks, leaving them susceptible to end-user input.  They have
+   been corrected.
+
 Also contains various documentation updates and code clean-ups.
+
+Credits go to joernchen <joernchen@phenoelit.de> for finding the
+unsafe constructs in "git cvsserver", and to Jeff King at GitHub for
+finding and fixing instances of the same issue in other scripts.
diff --git a/Documentation/RelNotes/2.14.3.txt b/Documentation/RelNotes/2.14.3.txt
new file mode 100644 (file)
index 0000000..61f569a
--- /dev/null
@@ -0,0 +1,75 @@
+Git v2.14.3 Release Notes
+=========================
+
+Fixes since v2.14.2
+-------------------
+
+ * A helper function to read a single whole line into strbuf
+   mistakenly triggered OOM error at EOF under certain conditions,
+   which has been fixed.
+
+ * In addition to "cc: <a@dd.re.ss> # cruft", "cc: a@dd.re.ss # cruft"
+   was taught to "git send-email" as a valid way to tell it that it
+   needs to also send a carbon copy to <a@dd.re.ss> in the trailer
+   section.
+
+ * Fix regression to "gitk --bisect" by a recent update.
+
+ * Unlike "git commit-tree < file", "git commit-tree -F file" did not
+   pass the contents of the file verbatim and instead completed an
+   incomplete line at the end, if exists.  The latter has been updated
+   to match the behaviour of the former.
+
+ * "git archive", especially when used with pathspec, stored an empty
+   directory in its output, even though Git itself never does so.
+   This has been fixed.
+
+ * API error-proofing which happens to also squelch warnings from GCC.
+
+ * "git gc" tries to avoid running two instances at the same time by
+   reading and writing pid/host from and to a lock file; it used to
+   use an incorrect fscanf() format when reading, which has been
+   corrected.
+
+ * The test linter has been taught that we do not like "echo -e".
+
+ * Code cmp.std.c nitpick.
+
+ * "git describe --match" learned to take multiple patterns in v2.13
+   series, but the feature ignored the patterns after the first one
+   and did not work at all.  This has been fixed.
+
+ * "git cat-file --textconv" started segfaulting recently, which
+   has been corrected.
+
+ * The built-in pattern to detect the "function header" for HTML did
+   not match <H1>..<H6> elements without any attributes, which has
+   been fixed.
+
+ * "git mailinfo" was loose in decoding quoted printable and produced
+   garbage when the two letters after the equal sign are not
+   hexadecimal.  This has been fixed.
+
+ * The documentation for '-X<option>' for merges was misleadingly
+   written to suggest that "-s theirs" exists, which is not the case.
+
+ * Spell the name of our system as "Git" in the output from
+   request-pull script.
+
+ * Fixes for a handful memory access issues identified by valgrind.
+
+ * Backports a moral equivalent of 2015 fix to the poll emulation from
+   the upstream gnulib to fix occasional breakages on HPE NonStop.
+
+ * In the "--format=..." option of the "git for-each-ref" command (and
+   its friends, i.e. the listing mode of "git branch/tag"), "%(atom:)"
+   (e.g. "%(refname:)", "%(body:)" used to error out.  Instead, treat
+   them as if the colon and an empty string that follows it were not
+   there.
+
+ * Users with "color.ui = always" in their configuration were broken
+   by a recent change that made plumbing commands to pay attention to
+   them as the patch created internally by "git add -p" were colored
+   (heh) and made unusable.  This has been fixed.
+
+Also contains various documentation updates and code clean-ups.
index d5c9c4cab60531d178d5c11d623a5c3f1036a0d0..2271809d90a5855c40de64bf1952c58a48b0d386 100644 (file)
@@ -216,15 +216,15 @@ boolean::
        synonyms are accepted for 'true' and 'false'; these are all
        case-insensitive.
 
-       true;; Boolean true can be spelled as `yes`, `on`, `true`,
-               or `1`.  Also, a variable defined without `= <value>`
+       true;; Boolean true literals are `yes`, `on`, `true`,
+               and `1`.  Also, a variable defined without `= <value>`
                is taken as true.
 
-       false;; Boolean false can be spelled as `no`, `off`,
-               `false`, or `0`.
+       false;; Boolean false literals are `no`, `off`, `false`,
+               `0` and the empty string.
 +
 When converting value to the canonical form using `--bool` type
-specifier; 'git config' will ensure that the output is "true" or
+specifier, 'git config' will ensure that the output is "true" or
 "false" (spelled in lowercase).
 
 integer::
@@ -2912,8 +2912,8 @@ sendemail.smtpsslcertpath::
 
 sendemail.<identity>.*::
        Identity-specific versions of the 'sendemail.*' parameters
-       found below, taking precedence over those when the this
-       identity is selected, through command-line or
+       found below, taking precedence over those when this
+       identity is selected, through either the command-line or
        `sendemail.identity`.
 
 sendemail.aliasesFile::
index f4169fb1ec4c61068cc70756c31a5abcc31496f6..b700beaff5ad2eaa407bfb3818e016a5bb27d87c 100644 (file)
@@ -61,6 +61,9 @@ OPTIONS
        the working tree.  Note that older versions of Git used
        to ignore removed files; use `--no-all` option if you want
        to add modified or new files but ignore removed ones.
++
+For more details about the <pathspec> syntax, see the 'pathspec' entry
+in linkgit:gitglossary[7].
 
 -n::
 --dry-run::
index 81bd0a7b7741f175cf7a99e2aa9cbcacf42da78e..7463dc44a71a897f3c3aa8eda76e7711f263b118 100644 (file)
@@ -92,10 +92,10 @@ OPTIONS
        all changes made to the branch ref, enabling use of date
        based sha1 expressions such as "<branchname>@\{yesterday}".
        Note that in non-bare repositories, reflogs are usually
-       enabled by default by the `core.logallrefupdates` config option.
+       enabled by default by the `core.logAllRefUpdates` config option.
        The negated form `--no-create-reflog` only overrides an earlier
        `--create-reflog`, but currently does not negate the setting of
-       `core.logallrefupdates`.
+       `core.logAllRefUpdates`.
 
 -f::
 --force::
@@ -267,8 +267,8 @@ start-point is either a local or remote-tracking branch.
        Only list branches of the given object.
 
 --format <format>::
-       A string that interpolates `%(fieldname)` from the object
-       pointed at by a ref being shown.  The format is the same as
+       A string that interpolates `%(fieldname)` from a branch ref being shown
+       and the object it points at.  The format is the same as
        that of linkgit:git-for-each-ref[1].
 
 Examples
index 204541c690ce24bdf5b6e20baa0ddca928920f71..fb09cd69d63fec03ad1987970fdbdffe8d8a4339 100644 (file)
@@ -192,7 +192,7 @@ newline. The available atoms are:
        The 40-hex object name of the object.
 
 `objecttype`::
-       The type of of the object (the same as `cat-file -t` reports).
+       The type of the object (the same as `cat-file -t` reports).
 
 `objectsize`::
        The size, in bytes, of the object (the same as `cat-file -s`
index d6399c0af86bb84cd86b82500ce706cbcd93cd93..e108b0f74bb6dc4d9f3fc27e7c3fe571b19a9d2f 100644 (file)
@@ -13,7 +13,8 @@ SYNOPSIS
 'git checkout' [-q] [-f] [-m] [--detach] <commit>
 'git checkout' [-q] [-f] [-m] [[-b|-B|--orphan] <new_branch>] [<start_point>]
 'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>...
-'git checkout' [-p|--patch] [<tree-ish>] [--] [<paths>...]
+'git checkout' [<tree-ish>] [--] <pathspec>...
+'git checkout' (-p|--patch) [<tree-ish>] [--] [<paths>...]
 
 DESCRIPTION
 -----------
@@ -38,7 +39,7 @@ $ git checkout -b <branch> --track <remote>/<branch>
 ------------
 +
 You could omit <branch>, in which case the command degenerates to
-"check out the current branch", which is a glorified no-op with a
+"check out the current branch", which is a glorified no-op with
 rather expensive side-effects to show only the tracking information,
 if exists, for the current branch.
 
@@ -78,20 +79,13 @@ be used to detach HEAD at the tip of the branch (`git checkout
 +
 Omitting <branch> detaches HEAD at the tip of the current branch.
 
-'git checkout' [-p|--patch] [<tree-ish>] [--] <pathspec>...::
+'git checkout' [<tree-ish>] [--] <pathspec>...::
 
-       When <paths> or `--patch` are given, 'git checkout' does *not*
-       switch branches.  It updates the named paths in the working tree
-       from the index file or from a named <tree-ish> (most often a
-       commit).  In this case, the `-b` and `--track` options are
-       meaningless and giving either of them results in an error.  The
-       <tree-ish> argument can be used to specify a specific tree-ish
-       (i.e.  commit, tag or tree) to update the index for the given
-       paths before updating the working tree.
-+
-'git checkout' with <paths> or `--patch` is used to restore modified or
-deleted paths to their original contents from the index or replace paths
-with the contents from a named <tree-ish> (most often a commit-ish).
+       Overwrite paths in the working tree by replacing with the
+       contents in the index or in the <tree-ish> (most often a
+       commit).  When a <tree-ish> is given, the paths that
+       match the <pathspec> are updated both in the index and in
+       the working tree.
 +
 The index may contain unmerged entries because of a previous failed merge.
 By default, if you try to check out such an entry from the index, the
@@ -101,6 +95,14 @@ specific side of the merge can be checked out of the index by
 using `--ours` or `--theirs`.  With `-m`, changes made to the working tree
 file can be discarded to re-create the original conflicted merge result.
 
+'git checkout' (-p|--patch) [<tree-ish>] [--] [<pathspec>...]::
+       This is similar to the "check out paths to the working tree
+       from either the index or from a tree-ish" mode described
+       above, but lets you use the interactive interface to show
+       the "diff" output and choose which hunks to use in the
+       result.  See below for the description of `--patch` option.
+
+
 OPTIONS
 -------
 -q::
index cc42c128323d32bd1a9bf47688722321857a5d65..cbd0a6212a62a618252e7b56397239d4066dcbd7 100644 (file)
@@ -10,8 +10,9 @@ SYNOPSIS
 [verse]
 'git for-each-ref' [--count=<count>] [--shell|--perl|--python|--tcl]
                   [(--sort=<key>)...] [--format=<format>] [<pattern>...]
-                  [--points-at <object>] [(--merged | --no-merged) [<object>]]
-                  [--contains [<object>]] [--no-contains [<object>]]
+                  [--points-at=<object>]
+                  (--merged[=<object>] | --no-merged[=<object>])
+                  [--contains[=<object>]] [--no-contains[=<object>]]
 
 DESCRIPTION
 -----------
@@ -25,35 +26,41 @@ host language allowing their direct evaluation in that language.
 
 OPTIONS
 -------
-<count>::
+<pattern>...::
+       If one or more patterns are given, only refs are shown that
+       match against at least one pattern, either using fnmatch(3) or
+       literally, in the latter case matching completely or from the
+       beginning up to a slash.
+
+--count=<count>::
        By default the command shows all refs that match
        `<pattern>`.  This option makes it stop after showing
        that many refs.
 
-<key>::
+--sort=<key>::
        A field name to sort on.  Prefix `-` to sort in
        descending order of the value.  When unspecified,
        `refname` is used.  You may use the --sort=<key> option
        multiple times, in which case the last key becomes the primary
        key.
 
-<format>::
-       A string that interpolates `%(fieldname)` from the
-       object pointed at by a ref being shown.  If `fieldname`
+--format=<format>::
+       A string that interpolates `%(fieldname)` from a ref being shown
+       and the object it points at.  If `fieldname`
        is prefixed with an asterisk (`*`) and the ref points
-       at a tag object, the value for the field in the object
-       tag refers is used.  When unspecified, defaults to
+       at a tag object, use the value for the field in the object
+       which the tag object refers to (instead of the field in the tag object).
+       When unspecified, `<format>` defaults to
        `%(objectname) SPC %(objecttype) TAB %(refname)`.
        It also interpolates `%%` to `%`, and `%xx` where `xx`
        are hex digits interpolates to character with hex code
        `xx`; for example `%00` interpolates to `\0` (NUL),
        `%09` to `\t` (TAB) and `%0a` to `\n` (LF).
 
-<pattern>...::
-       If one or more patterns are given, only refs are shown that
-       match against at least one pattern, either using fnmatch(3) or
-       literally, in the latter case matching completely or from the
-       beginning up to a slash.
+--color[=<when>]:
+       Respect any colors specified in the `--format` option. The
+       `<when>` field must be one of `always`, `never`, or `auto` (if
+       `<when>` is absent, behave as if `always` was given).
 
 --shell::
 --perl::
@@ -64,24 +71,24 @@ OPTIONS
        the specified host language.  This is meant to produce
        a scriptlet that can directly be `eval`ed.
 
---points-at <object>::
+--points-at=<object>::
        Only list refs which points at the given object.
 
---merged [<object>]::
+--merged[=<object>]::
        Only list refs whose tips are reachable from the
        specified commit (HEAD if not specified),
        incompatible with `--no-merged`.
 
---no-merged [<object>]::
+--no-merged[=<object>]::
        Only list refs whose tips are not reachable from the
        specified commit (HEAD if not specified),
        incompatible with `--merged`.
 
---contains [<object>]::
+--contains[=<object>]::
        Only list refs which contain the specified commit (HEAD if not
        specified).
 
---no-contains [<object>]::
+--no-contains[=<object>]::
        Only list refs which don't contain the specified commit (HEAD
        if not specified).
 
index 5033483db496286910dd24507f3374e18ff6c2b5..5edb1da46fe0a7ccca2608807c28305be72483b5 100644 (file)
@@ -296,6 +296,9 @@ providing this option will cause it to die.
 <pathspec>...::
        If given, limit the search to paths matching at least one pattern.
        Both leading paths match and glob(7) patterns are supported.
++
+For more details about the <pathspec> syntax, see the 'pathspec' entry
+in linkgit:gitglossary[7].
 
 Examples
 --------
@@ -312,6 +315,9 @@ Examples
        Looks for a line that has `NODE` or `Unexpected` in
        files that have lines that match both.
 
+`git grep solution -- :^Documentation`::
+       Looks for `solution`, excluding files in `Documentation`.
+
 GIT
 ---
 Part of the linkgit:git[1] suite
index 04fdd8cf086db6413a01421c306a80c9583f7fa4..f90faf7aaa250b2fea09d611e4efac31968ce6db 100644 (file)
@@ -280,7 +280,10 @@ After seeing a conflict, you can do two things:
 
  * Resolve the conflicts.  Git will mark the conflicts in
    the working tree.  Edit the files into shape and
-   'git add' them to the index.  Use 'git commit' to seal the deal.
+   'git add' them to the index.  Use 'git commit' or
+   'git merge --continue' to seal the deal. The latter command
+   checks whether there is a (interrupted) merge in progress
+   before calling 'git commit'.
 
 You can work through the conflict with a number of tools:
 
index be7db3048d4776200c6ed8781b25ffccb68a41eb..43677297f3b85814c18c972a159b81c8076bc445 100644 (file)
@@ -171,7 +171,7 @@ OPTIONS
        object that does not have notes attached to it.
 
 --stdin::
-       Also read the object names to remove notes from from the standard
+       Also read the object names to remove notes from the standard
        input (there is no reason you cannot combine this with object
        names from the command line).
 
index 8973510a41c1e31319dad85d4987b3f0dfd7d8ca..473a16135abf867a77af26b35016dab0a2b6954d 100644 (file)
@@ -18,8 +18,9 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-Reads list of objects from the standard input, and writes a packed
-archive with specified base-name, or to the standard output.
+Reads list of objects from the standard input, and writes either one or
+more packed archives with the specified base-name to disk, or a packed
+archive to the standard output.
 
 A packed archive is an efficient way to transfer a set of objects
 between two repositories as well as an access efficient archival
@@ -47,9 +48,9 @@ transport by their peers.
 OPTIONS
 -------
 base-name::
-       Write into a pair of files (.pack and .idx), using
+       Write into pairs of files (.pack and .idx), using
        <base-name> to determine the name of the created file.
-       When this option is used, the two files are written in
+       When this option is used, the two files in a pair are written in
        <base-name>-<SHA-1>.{pack,idx} files.  <SHA-1> is a hash
        based on the pack content and is written to the standard
        output of the command.
@@ -108,9 +109,13 @@ base-name::
        is taken from the `pack.windowMemory` configuration variable.
 
 --max-pack-size=<n>::
-       Maximum size of each output pack file. The size can be suffixed with
+       In unusual scenarios, you may not be able to create files
+       larger than a certain size on your filesystem, and this option
+       can be used to tell the command to split the output packfile
+       into multiple independent packfiles, each not larger than the
+       given size. The size can be suffixed with
        "k", "m", or "g". The minimum size allowed is limited to 1 MiB.
-       If specified, multiple packfiles may be created, which also
+       This option
        prevents the creation of a bitmap index.
        The default is unlimited, unless the config variable
        `pack.packSizeLimit` is set.
index 02576d8c0ae6008fc22d7c7c706909efde5856da..72bd809fb8d59812d79e402f6b9608d09f0d52ec 100644 (file)
@@ -179,6 +179,7 @@ Here are the "carry forward" rules, where "I" denotes the index,
 "clean" means that index and work tree coincide, and "exists"/"nothing"
 refer to the presence of a path in the specified commit:
 
+....
        I                   H        M        Result
        -------------------------------------------------------
      0  nothing             nothing  nothing  (does not happen)
@@ -217,6 +218,7 @@ refer to the presence of a path in the specified commit:
      19 no    no    yes     exists   exists   keep index
      20 yes   yes   no      exists   exists   use M
      21 no    yes   no      exists   exists   fail
+....
 
 In all "keep index" cases, the index entry stays as in the
 original index file.  If the entry is not up to date,
index 2e30a3e42d4e4e2bab580b0dcb5701ca3b33aeed..54cf2560bebbfc538644c636f696d4e500f1d852 100644 (file)
@@ -79,6 +79,22 @@ EOF
 $ chmod +x $HOME/git-shell-commands/no-interactive-login
 ----------------
 
+To enable git-cvsserver access (which should generally have the
+`no-interactive-login` example above as a prerequisite, as creating
+the git-shell-commands directory allows interactive logins):
+
+----------------
+$ cat >$HOME/git-shell-commands/cvs <<\EOF
+if ! test $# = 1 && test "$1" = "server"
+then
+       echo >&2 "git-cvsserver only handles \"server\""
+       exit 1
+fi
+exec git cvsserver server
+EOF
+$ chmod +x $HOME/git-shell-commands/cvs
+----------------
+
 SEE ALSO
 --------
 ssh(1),
index d47f198f15cd4c767b03c14580b816bf750e9ee1..9f3a78a36c48c55318ee0eea8e96a64ccce5bfa2 100644 (file)
@@ -111,6 +111,8 @@ configuration variable documented in linkgit:git-config[1].
        without options are equivalent to 'always' and 'never'
        respectively.
 
+<pathspec>...::
+       See the 'pathspec' entry in linkgit:gitglossary[7].
 
 OUTPUT
 ------
index 1eb15afa1ce8a533d65c5f5ace0bcd694d7f6ffd..956fc019f984bca1754a72dc0d7308b39a28445d 100644 (file)
@@ -115,6 +115,11 @@ options for details.
        variable if it exists, or lexicographic order otherwise. See
        linkgit:git-config[1].
 
+--color[=<when>]:
+       Respect any colors specified in the `--format` option. The
+       `<when>` field must be one of `always`, `never`, or `auto` (if
+       `<when>` is absent, behave as if `always` was given).
+
 -i::
 --ignore-case::
        Sorting and filtering tags are case insensitive.
@@ -174,7 +179,7 @@ This option is only applicable when listing tags without annotation lines.
        `core.logAllRefUpdates` in linkgit:git-config[1].
        The negated form `--no-create-reflog` only overrides an earlier
        `--create-reflog`, but currently does not negate the setting of
-       `core.logallrefupdates`.
+       `core.logAllRefUpdates`.
 
 <tagname>::
        The name of the tag to create, delete, or describe.
@@ -188,8 +193,8 @@ This option is only applicable when listing tags without annotation lines.
        Defaults to HEAD.
 
 <format>::
-       A string that interpolates `%(fieldname)` from the object
-       pointed at by a ref being shown.  The format is the same as
+       A string that interpolates `%(fieldname)` from a tag ref being shown
+       and the object it points at.  The format is the same as
        that of linkgit:git-for-each-ref[1].  When unspecified,
        defaults to `%(refname:strip=2)`.
 
@@ -205,6 +210,9 @@ it in the repository configuration as follows:
     signingKey = <gpg-keyid>
 -------------------------------------
 
+`pager.tag` is only respected when listing tags, i.e., when `-l` is
+used or implied. The default is to use a pager.
+See linkgit:git-config[1].
 
 DISCUSSION
 ----------
index 1579abf3c3b45f4e63f8f17746dde31a06a3a564..a14e6aebd9dc8e3b523b4145236fc413e00d4492 100644 (file)
@@ -153,7 +153,7 @@ you will need to handle the situation manually.
 +
 Version 4 performs a simple pathname compression that reduces index
 size by 30%-50% on large repositories, which results in faster load
-time. Version 4 is relatively young (first released in in 1.8.0 in
+time. Version 4 is relatively young (first released in 1.8.0 in
 October 2012). Other Git implementations such as JGit and libgit2
 may not support it yet.
 
index 7dd5e03280b09f21f59289b0b00cd6fdee0ca3cb..98b9b46b9e52f2c3f1c55e4172a6a9659e02eb6b 100644 (file)
@@ -75,7 +75,8 @@ example the following invocations are equivalent:
 Note that omitting the `=` in `git -c foo.bar ...` is allowed and sets
 `foo.bar` to the boolean true value (just like `[foo]bar` would in a
 config file). Including the equals but with an empty value (like `git -c
-foo.bar= ...`) sets `foo.bar` to the empty string.
+foo.bar= ...`) sets `foo.bar` to the empty string which `git config
+--bool` will convert to `false`.
 
 --exec-path[=<path>]::
        Path to wherever your core Git programs are installed.
index c4f2be2542d1fcd417c69596dafdf89bc3a93f00..4c68bc19d5108d1ba0c91b05d35acf8060eb2c9d 100644 (file)
@@ -151,7 +151,10 @@ unspecified.
 
 This attribute sets a specific line-ending style to be used in the
 working directory.  It enables end-of-line conversion without any
-content checks, effectively setting the `text` attribute.
+content checks, effectively setting the `text` attribute.  Note that
+setting this attribute on paths which are in the index with CRLF line
+endings may make the paths to be considered dirty.  Adding the path to
+the index again will normalize the line endings in the index.
 
 Set to string value "crlf"::
 
index b71b943b12eda2eab1792dfc910e405ad2ad540c..6b8888d123826179ace38660f5043d897eb5ce70 100644 (file)
@@ -407,7 +407,7 @@ these forms:
 
 exclude;;
        After a path matches any non-exclude pathspec, it will be run
-       through all exclude pathspec (magic signature: `!` or its
+       through all exclude pathspecs (magic signature: `!` or its
        synonym `^`). If it matches, the path is ignored.  When there
        is no non-exclude pathspec, the exclusion is applied to the
        result set as if invoked without any pathspec.
index 2eb92b93274df9fb5002336114654fe869903808..a09d5974639fa772ba86c5547fe70716fd044f73 100644 (file)
@@ -39,7 +39,8 @@ even look at what the other tree contains at all.  It discards everything
 the other tree did, declaring 'our' history contains all that happened in it.
 
 theirs;;
-       This is the opposite of 'ours'.
+       This is the opposite of 'ours'; note that, unlike 'ours', there is
+       no 'theirs' merge stragegy to confuse this merge option with.
 
 patience;;
        With this option, 'merge-recursive' spends a little extra time
diff --git a/Documentation/technical/api-builtin.txt b/Documentation/technical/api-builtin.txt
deleted file mode 100644 (file)
index 22a39b9..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-builtin API
-===========
-
-Adding a new built-in
----------------------
-
-There are 4 things to do to add a built-in command implementation to
-Git:
-
-. Define the implementation of the built-in command `foo` with
-  signature:
-
-       int cmd_foo(int argc, const char **argv, const char *prefix);
-
-. Add the external declaration for the function to `builtin.h`.
-
-. Add the command to the `commands[]` table defined in `git.c`.
-  The entry should look like:
-
-       { "foo", cmd_foo, <options> },
-+
-where options is the bitwise-or of:
-
-`RUN_SETUP`::
-       If there is not a Git directory to work on, abort.  If there
-       is a work tree, chdir to the top of it if the command was
-       invoked in a subdirectory.  If there is no work tree, no
-       chdir() is done.
-
-`RUN_SETUP_GENTLY`::
-       If there is a Git directory, chdir as per RUN_SETUP, otherwise,
-       don't chdir anywhere.
-
-`USE_PAGER`::
-
-       If the standard output is connected to a tty, spawn a pager and
-       feed our output to it.
-
-`NEED_WORK_TREE`::
-
-       Make sure there is a work tree, i.e. the command cannot act
-       on bare repositories.
-       This only makes sense when `RUN_SETUP` is also set.
-
-. Add `builtin/foo.o` to `BUILTIN_OBJS` in `Makefile`.
-
-Additionally, if `foo` is a new command, there are 3 more things to do:
-
-. Add tests to `t/` directory.
-
-. Write documentation in `Documentation/git-foo.txt`.
-
-. Add an entry for `git-foo` to `command-list.txt`.
-
-. Add an entry for `/git-foo` to `.gitignore`.
-
-
-How a built-in is called
-------------------------
-
-The implementation `cmd_foo()` takes three parameters, `argc`, `argv,
-and `prefix`.  The first two are similar to what `main()` of a
-standalone command would be called with.
-
-When `RUN_SETUP` is specified in the `commands[]` table, and when you
-were started from a subdirectory of the work tree, `cmd_foo()` is called
-after chdir(2) to the top of the work tree, and `prefix` gets the path
-to the subdirectory the command started from.  This allows you to
-convert a user-supplied pathname (typically relative to that directory)
-to a pathname relative to the top of the work tree.
-
-The return value from `cmd_foo()` becomes the exit status of the
-command.
index 461c845d33cbc5f201096ea4b3e1048492cb0a6a..043ec8377b72ff3d86193982eb866a2f055f752c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2037,7 +2037,6 @@ XDIFF_OBJS += xdiff/xhistogram.o
 
 VCSSVN_OBJS += vcs-svn/line_buffer.o
 VCSSVN_OBJS += vcs-svn/sliding_window.o
-VCSSVN_OBJS += vcs-svn/repo_tree.o
 VCSSVN_OBJS += vcs-svn/fast_export.o
 VCSSVN_OBJS += vcs-svn/svndiff.o
 VCSSVN_OBJS += vcs-svn/svndump.o
index 29ef98331028ae5b1cdc10be75626e48b173a961..8612bbde73895d034ea383209d1cdca707a76000 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.14.2.txt
\ No newline at end of file
+Documentation/RelNotes/2.14.3.txt
\ No newline at end of file
diff --git a/apply.c b/apply.c
index 40707ca50c50331c392ab51375a83f4fb97edee1..0c7b25989cdf58b411190744c97d93450be9b53e 100644 (file)
--- a/apply.c
+++ b/apply.c
@@ -80,7 +80,6 @@ int init_apply_state(struct apply_state *state,
 {
        memset(state, 0, sizeof(*state));
        state->prefix = prefix;
-       state->prefix_length = state->prefix ? strlen(state->prefix) : 0;
        state->lock_file = lock_file;
        state->newfd = -1;
        state->apply = 1;
@@ -220,6 +219,7 @@ struct patch {
        unsigned int recount:1;
        unsigned int conflicted_threeway:1;
        unsigned int direct_to_threeway:1;
+       unsigned int crlf_in_old:1;
        struct fragment *fragments;
        char *result;
        size_t resultsize;
@@ -786,11 +786,11 @@ static int guess_p_value(struct apply_state *state, const char *nameline)
                 * Does it begin with "a/$our-prefix" and such?  Then this is
                 * very likely to apply to our directory.
                 */
-               if (!strncmp(name, state->prefix, state->prefix_length))
+               if (starts_with(name, state->prefix))
                        val = count_slashes(state->prefix);
                else {
                        cp++;
-                       if (!strncmp(cp, state->prefix, state->prefix_length))
+                       if (starts_with(cp, state->prefix))
                                val = count_slashes(state->prefix) + 1;
                }
        }
@@ -1662,6 +1662,19 @@ static void check_whitespace(struct apply_state *state,
        record_ws_error(state, result, line + 1, len - 2, state->linenr);
 }
 
+/*
+ * Check if the patch has context lines with CRLF or
+ * the patch wants to remove lines with CRLF.
+ */
+static void check_old_for_crlf(struct patch *patch, const char *line, int len)
+{
+       if (len >= 2 && line[len-1] == '\n' && line[len-2] == '\r') {
+               patch->ws_rule |= WS_CR_AT_EOL;
+               patch->crlf_in_old = 1;
+       }
+}
+
+
 /*
  * Parse a unified diff. Note that this really needs to parse each
  * fragment separately, since the only way to know the difference
@@ -1712,11 +1725,14 @@ static int parse_fragment(struct apply_state *state,
                        if (!deleted && !added)
                                leading++;
                        trailing++;
+                       check_old_for_crlf(patch, line, len);
                        if (!state->apply_in_reverse &&
                            state->ws_error_action == correct_ws_error)
                                check_whitespace(state, line, len, patch->ws_rule);
                        break;
                case '-':
+                       if (!state->apply_in_reverse)
+                               check_old_for_crlf(patch, line, len);
                        if (state->apply_in_reverse &&
                            state->ws_error_action != nowarn_ws_error)
                                check_whitespace(state, line, len, patch->ws_rule);
@@ -1725,6 +1741,8 @@ static int parse_fragment(struct apply_state *state,
                        trailing = 0;
                        break;
                case '+':
+                       if (state->apply_in_reverse)
+                               check_old_for_crlf(patch, line, len);
                        if (!state->apply_in_reverse &&
                            state->ws_error_action != nowarn_ws_error)
                                check_whitespace(state, line, len, patch->ws_rule);
@@ -2089,10 +2107,9 @@ static int use_patch(struct apply_state *state, struct patch *p)
        int i;
 
        /* Paths outside are not touched regardless of "--include" */
-       if (0 < state->prefix_length) {
-               int pathlen = strlen(pathname);
-               if (pathlen <= state->prefix_length ||
-                   memcmp(state->prefix, pathname, state->prefix_length))
+       if (state->prefix && *state->prefix) {
+               const char *rest;
+               if (!skip_prefix(pathname, state->prefix, &rest) || !*rest)
                        return 0;
        }
 
@@ -2268,8 +2285,11 @@ static void show_stats(struct apply_state *state, struct patch *patch)
                add, pluses, del, minuses);
 }
 
-static int read_old_data(struct stat *st, const char *path, struct strbuf *buf)
+static int read_old_data(struct stat *st, struct patch *patch,
+                        const char *path, struct strbuf *buf)
 {
+       enum safe_crlf safe_crlf = patch->crlf_in_old ?
+               SAFE_CRLF_KEEP_CRLF : SAFE_CRLF_RENORMALIZE;
        switch (st->st_mode & S_IFMT) {
        case S_IFLNK:
                if (strbuf_readlink(buf, path, st->st_size) < 0)
@@ -2278,7 +2298,15 @@ static int read_old_data(struct stat *st, const char *path, struct strbuf *buf)
        case S_IFREG:
                if (strbuf_read_file(buf, path, st->st_size) != st->st_size)
                        return error(_("unable to open or read %s"), path);
-               convert_to_git(&the_index, path, buf->buf, buf->len, buf, 0);
+               /*
+                * "git apply" without "--index/--cached" should never look
+                * at the index; the target file may not have been added to
+                * the index yet, and we may not even be in any Git repository.
+                * Pass NULL to convert_to_git() to stress this; the function
+                * should never look at the index when explicit crlf option
+                * is given.
+                */
+               convert_to_git(NULL, path, buf->buf, buf->len, buf, safe_crlf);
                return 0;
        default:
                return -1;
@@ -3381,6 +3409,7 @@ static int load_patch_target(struct apply_state *state,
                             struct strbuf *buf,
                             const struct cache_entry *ce,
                             struct stat *st,
+                            struct patch *patch,
                             const char *name,
                             unsigned expected_mode)
 {
@@ -3396,7 +3425,7 @@ static int load_patch_target(struct apply_state *state,
                } else if (has_symlink_leading_path(name, strlen(name))) {
                        return error(_("reading from '%s' beyond a symbolic link"), name);
                } else {
-                       if (read_old_data(st, name, buf))
+                       if (read_old_data(st, patch, name, buf))
                                return error(_("failed to read %s"), name);
                }
        }
@@ -3429,7 +3458,7 @@ static int load_preimage(struct apply_state *state,
                /* We have a patched copy in memory; use that. */
                strbuf_add(&buf, previous->result, previous->resultsize);
        } else {
-               status = load_patch_target(state, &buf, ce, st,
+               status = load_patch_target(state, &buf, ce, st, patch,
                                           patch->old_name, patch->old_mode);
                if (status < 0)
                        return status;
@@ -3517,7 +3546,7 @@ static int load_current(struct apply_state *state,
        if (verify_index_match(ce, &st))
                return error(_("%s: does not match index"), name);
 
-       status = load_patch_target(state, &buf, ce, &st, name, mode);
+       status = load_patch_target(state, &buf, ce, &st, patch, name, mode);
        if (status < 0)
                return status;
        else if (status)
diff --git a/apply.h b/apply.h
index b3d6783d55344de5aaa3d4b81a22abed0b6972fb..d9b395770364b5495fc1136248efd64bd3a5e66d 100644 (file)
--- a/apply.h
+++ b/apply.h
@@ -35,7 +35,6 @@ enum apply_verbosity {
 
 struct apply_state {
        const char *prefix;
-       int prefix_length;
 
        /* These are lock_file related */
        struct lock_file *lock_file;
index 60b3035a7a6a9e7c2e69b4ba7de00ebdf8bfdbb8..f81bd3649a1f4bf20bc03100d12fc157401bdc14 100644 (file)
--- a/archive.c
+++ b/archive.c
@@ -103,17 +103,34 @@ struct archiver_context {
        struct directory *bottom;
 };
 
+static const struct attr_check *get_archive_attrs(const char *path)
+{
+       static struct attr_check *check;
+       if (!check)
+               check = attr_check_initl("export-ignore", "export-subst", NULL);
+       return git_check_attr(path, check) ? NULL : check;
+}
+
+static int check_attr_export_ignore(const struct attr_check *check)
+{
+       return check && ATTR_TRUE(check->items[0].value);
+}
+
+static int check_attr_export_subst(const struct attr_check *check)
+{
+       return check && ATTR_TRUE(check->items[1].value);
+}
+
 static int write_archive_entry(const unsigned char *sha1, const char *base,
                int baselen, const char *filename, unsigned mode, int stage,
                void *context)
 {
        static struct strbuf path = STRBUF_INIT;
-       static struct attr_check *check;
        struct archiver_context *c = context;
        struct archiver_args *args = c->args;
        write_archive_entry_fn_t write_entry = c->write_entry;
-       const char *path_without_prefix;
        int err;
+       const char *path_without_prefix;
 
        args->convert = 0;
        strbuf_reset(&path);
@@ -125,12 +142,12 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
                strbuf_addch(&path, '/');
        path_without_prefix = path.buf + args->baselen;
 
-       if (!check)
-               check = attr_check_initl("export-ignore", "export-subst", NULL);
-       if (!git_check_attr(path_without_prefix, check)) {
-               if (ATTR_TRUE(check->items[0].value))
+       if (!S_ISDIR(mode)) {
+               const struct attr_check *check;
+               check = get_archive_attrs(path_without_prefix);
+               if (check_attr_export_ignore(check))
                        return 0;
-               args->convert = ATTR_TRUE(check->items[1].value);
+               args->convert = check_attr_export_subst(check);
        }
 
        if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
@@ -147,14 +164,6 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
        return write_entry(args, sha1, path.buf, path.len, mode);
 }
 
-static int write_archive_entry_buf(const unsigned char *sha1, struct strbuf *base,
-               const char *filename, unsigned mode, int stage,
-               void *context)
-{
-       return write_archive_entry(sha1, base->buf, base->len,
-                                    filename, mode, stage, context);
-}
-
 static void queue_directory(const unsigned char *sha1,
                struct strbuf *base, const char *filename,
                unsigned mode, int stage, struct archiver_context *c)
@@ -204,6 +213,17 @@ static int queue_or_write_archive_entry(const unsigned char *sha1,
        }
 
        if (S_ISDIR(mode)) {
+               size_t baselen = base->len;
+               const struct attr_check *check;
+
+               /* Borrow base, but restore its original value when done. */
+               strbuf_addstr(base, filename);
+               strbuf_addch(base, '/');
+               check = get_archive_attrs(base->buf);
+               strbuf_setlen(base, baselen);
+
+               if (check_attr_export_ignore(check))
+                       return 0;
                queue_directory(sha1, base, filename,
                                mode, stage, c);
                return READ_TREE_RECURSIVE;
@@ -257,9 +277,7 @@ int write_archive_entries(struct archiver_args *args,
        }
 
        err = read_tree_recursive(args->tree, "", 0, 0, &args->pathspec,
-                                 args->pathspec.has_wildcard ?
-                                 queue_or_write_archive_entry :
-                                 write_archive_entry_buf,
+                                 queue_or_write_archive_entry,
                                  &context);
        if (err == READ_TREE_RECURSIVE)
                err = 0;
index 36541d05cd7b934bceba1af4fd4c121e51cd862b..86360d36b3edca403255b855b6edc8bdaf700de8 100644 (file)
--- a/branch.c
+++ b/branch.c
@@ -357,8 +357,9 @@ int replace_each_worktree_head_symref(const char *oldref, const char *newref,
 
                if (worktrees[i]->is_detached)
                        continue;
-               if (worktrees[i]->head_ref &&
-                   strcmp(oldref, worktrees[i]->head_ref))
+               if (!worktrees[i]->head_ref)
+                       continue;
+               if (strcmp(oldref, worktrees[i]->head_ref))
                        continue;
 
                refs = get_worktree_ref_store(worktrees[i]);
index 498ac80d07bc5b00a9c66e9e62449d7700bc7550..42378f3aa471eb79594d96736ad2410b54d6c4dd 100644 (file)
--- a/builtin.h
+++ b/builtin.h
@@ -6,6 +6,94 @@
 #include "cache.h"
 #include "commit.h"
 
+/*
+ * builtin API
+ * ===========
+ *
+ * Adding a new built-in
+ * ---------------------
+ *
+ * There are 4 things to do to add a built-in command implementation to
+ * Git:
+ *
+ * . Define the implementation of the built-in command `foo` with
+ *   signature:
+ *
+ *     int cmd_foo(int argc, const char **argv, const char *prefix);
+ *
+ * . Add the external declaration for the function to `builtin.h`.
+ *
+ * . Add the command to the `commands[]` table defined in `git.c`.
+ *   The entry should look like:
+ *
+ *     { "foo", cmd_foo, <options> },
+ *
+ * where options is the bitwise-or of:
+ *
+ * `RUN_SETUP`:
+ *     If there is not a Git directory to work on, abort.  If there
+ *     is a work tree, chdir to the top of it if the command was
+ *     invoked in a subdirectory.  If there is no work tree, no
+ *     chdir() is done.
+ *
+ * `RUN_SETUP_GENTLY`:
+ *     If there is a Git directory, chdir as per RUN_SETUP, otherwise,
+ *     don't chdir anywhere.
+ *
+ * `USE_PAGER`:
+ *
+ *     If the standard output is connected to a tty, spawn a pager and
+ *     feed our output to it.
+ *
+ * `NEED_WORK_TREE`:
+ *
+ *     Make sure there is a work tree, i.e. the command cannot act
+ *     on bare repositories.
+ *     This only makes sense when `RUN_SETUP` is also set.
+ *
+ * `SUPPORT_SUPER_PREFIX`:
+ *
+ *     The built-in supports `--super-prefix`.
+ *
+ * `DELAY_PAGER_CONFIG`:
+ *
+ *     If RUN_SETUP or RUN_SETUP_GENTLY is set, git.c normally handles
+ *     the `pager.<cmd>`-configuration. If this flag is used, git.c
+ *     will skip that step, instead allowing the built-in to make a
+ *     more informed decision, e.g., by ignoring `pager.<cmd>` for
+ *     certain subcommands.
+ *
+ * . Add `builtin/foo.o` to `BUILTIN_OBJS` in `Makefile`.
+ *
+ * Additionally, if `foo` is a new command, there are 4 more things to do:
+ *
+ * . Add tests to `t/` directory.
+ *
+ * . Write documentation in `Documentation/git-foo.txt`.
+ *
+ * . Add an entry for `git-foo` to `command-list.txt`.
+ *
+ * . Add an entry for `/git-foo` to `.gitignore`.
+ *
+ *
+ * How a built-in is called
+ * ------------------------
+ *
+ * The implementation `cmd_foo()` takes three parameters, `argc`, `argv,
+ * and `prefix`.  The first two are similar to what `main()` of a
+ * standalone command would be called with.
+ *
+ * When `RUN_SETUP` is specified in the `commands[]` table, and when you
+ * were started from a subdirectory of the work tree, `cmd_foo()` is called
+ * after chdir(2) to the top of the work tree, and `prefix` gets the path
+ * to the subdirectory the command started from.  This allows you to
+ * convert a user-supplied pathname (typically relative to that directory)
+ * to a pathname relative to the top of the work tree.
+ *
+ * The return value from `cmd_foo()` becomes the exit status of the
+ * command.
+ */
+
 #define DEFAULT_MERGE_LOG_LEN 20
 
 extern const char git_usage_string[];
@@ -25,6 +113,18 @@ struct fmt_merge_msg_opts {
 extern int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
                         struct fmt_merge_msg_opts *);
 
+/**
+ * If a built-in has DELAY_PAGER_CONFIG set, the built-in should call this early
+ * when it wishes to respect the `pager.foo`-config. The `cmd` is the name of
+ * the built-in, e.g., "foo". If a paging-choice has already been setup, this
+ * does nothing. The default in `def` should be 0 for "pager off", 1 for "pager
+ * on" or -1 for "punt".
+ *
+ * You should most likely use a default of 0 or 1. "Punt" (-1) could be useful
+ * to be able to fall back to some historical compatibility name.
+ */
+extern void setup_auto_pager(const char *cmd, int def);
+
 extern int is_builtin(const char *s);
 
 extern int cmd_add(int argc, const char **argv, const char *prefix);
index e888fb8c5f2a1fa2be33e834724460dec8072726..5d5773d5cd2fc9e713498a72da7b57b84fd25d19 100644 (file)
@@ -32,7 +32,7 @@ struct update_callback_data {
        int add_errors;
 };
 
-static void chmod_pathspec(struct pathspec *pathspec, int force_mode)
+static void chmod_pathspec(struct pathspec *pathspec, char flip)
 {
        int i;
 
@@ -42,8 +42,8 @@ static void chmod_pathspec(struct pathspec *pathspec, int force_mode)
                if (pathspec && !ce_path_match(ce, pathspec, NULL))
                        continue;
 
-               if (chmod_cache_entry(ce, force_mode) < 0)
-                       fprintf(stderr, "cannot chmod '%s'", ce->name);
+               if (chmod_cache_entry(ce, flip) < 0)
+                       fprintf(stderr, "cannot chmod %cx '%s'\n", flip, ce->name);
        }
 }
 
index c973bd96dcb5d630d56e935733bfa4530ccd2872..73f542bec51d77b92d39ced0dfefcc5b6b649db8 100644 (file)
@@ -431,6 +431,14 @@ static void am_load(struct am_state *state)
        read_state_file(&sb, state, "utf8", 1);
        state->utf8 = !strcmp(sb.buf, "t");
 
+       if (file_exists(am_path(state, "rerere-autoupdate"))) {
+               read_state_file(&sb, state, "rerere-autoupdate", 1);
+               state->allow_rerere_autoupdate = strcmp(sb.buf, "t") ?
+                       RERERE_NOAUTOUPDATE : RERERE_AUTOUPDATE;
+       } else {
+               state->allow_rerere_autoupdate = 0;
+       }
+
        read_state_file(&sb, state, "keep", 1);
        if (!strcmp(sb.buf, "t"))
                state->keep = KEEP_TRUE;
@@ -1003,6 +1011,10 @@ static void am_setup(struct am_state *state, enum patch_format patch_format,
        write_state_bool(state, "sign", state->signoff);
        write_state_bool(state, "utf8", state->utf8);
 
+       if (state->allow_rerere_autoupdate)
+               write_state_bool(state, "rerere-autoupdate",
+                        state->allow_rerere_autoupdate == RERERE_AUTOUPDATE);
+
        switch (state->keep) {
        case KEEP_FALSE:
                str = "f";
@@ -1181,34 +1193,10 @@ static void NORETURN die_user_resolve(const struct am_state *state)
  */
 static void am_append_signoff(struct am_state *state)
 {
-       char *cp;
-       struct strbuf mine = STRBUF_INIT;
        struct strbuf sb = STRBUF_INIT;
 
        strbuf_attach(&sb, state->msg, state->msg_len, state->msg_len);
-
-       /* our sign-off */
-       strbuf_addf(&mine, "\n%s%s\n",
-                   sign_off_header,
-                   fmt_name(getenv("GIT_COMMITTER_NAME"),
-                            getenv("GIT_COMMITTER_EMAIL")));
-
-       /* Does sb end with it already? */
-       if (mine.len < sb.len &&
-           !strcmp(mine.buf, sb.buf + sb.len - mine.len))
-               goto exit; /* no need to duplicate */
-
-       /* Does it have any Signed-off-by: in the text */
-       for (cp = sb.buf;
-            cp && *cp && (cp = strstr(cp, sign_off_header)) != NULL;
-            cp = strchr(cp, '\n')) {
-               if (sb.buf == cp || cp[-1] == '\n')
-                       break;
-       }
-
-       strbuf_addstr(&sb, mine.buf + !!cp);
-exit:
-       strbuf_release(&mine);
+       append_signoff(&sb, 0, 0);
        state->msg = strbuf_detach(&sb, &state->msg_len);
 }
 
index 16d391b407c9fa688b48a3e28f77800dcc1e2e0c..8f779b02b5f09907e0984dfb27024778026f0b4f 100644 (file)
@@ -92,7 +92,7 @@ static int git_branch_config(const char *var, const char *value, void *cb)
                        return config_error_nonbool(var);
                return color_parse(value, branch_colors[slot]);
        }
-       return git_default_config(var, value, cb);
+       return git_color_default_config(var, value, cb);
 }
 
 static const char *branch_get_color(enum color_branch ix)
@@ -216,7 +216,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
                if (!head_rev)
                        die(_("Couldn't look up commit object for HEAD"));
        }
-       for (i = 0; i < argc; i++, strbuf_release(&bname)) {
+       for (i = 0; i < argc; i++, strbuf_reset(&bname)) {
                char *target = NULL;
                int flags = 0;
 
@@ -281,8 +281,9 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
        }
 
        free(name);
+       strbuf_release(&bname);
 
-       return(ret);
+       return ret;
 }
 
 static int calc_maxwidth(struct ref_array *refs, int remote_bonus)
index 96b786e4892aec0ed7e5d07ac8d3261c7b765f33..188ddc3e507acdae6e3fb361a3763da620efcb90 100644 (file)
@@ -96,7 +96,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
                return !has_object_file(&oid);
 
        case 'w':
-               if (!path[0])
+               if (!path)
                        die("git cat-file --filters %s: <object> must be "
                            "<sha1:path>", obj_name);
 
@@ -106,7 +106,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
                break;
 
        case 'c':
-               if (!path[0])
+               if (!path)
                        die("git cat-file --textconv %s: <object> must be <sha1:path>",
                            obj_name);
 
index c1bafda5b63324b0aba7400535cc0ba745e46004..057fc97fe4494338e6a85ac9f695563f1fcb9596 100644 (file)
@@ -125,7 +125,8 @@ static int git_clean_config(const char *var, const char *value, void *cb)
                return 0;
        }
 
-       return git_default_config(var, value, cb);
+       /* inspect the color.ui config variable and others */
+       return git_color_default_config(var, value, cb);
 }
 
 static const char *clean_get_color(enum color_clean ix)
index 08b5cc433c6fcad5eea2dfc3321aea28a599d51f..f7e17d22951cfd8e498143c009fa0303d0ff8319 100644 (file)
@@ -768,6 +768,9 @@ static int checkout(int submodule_progress)
                if (submodule_progress)
                        argv_array_push(&args, "--progress");
 
+               if (option_verbosity < 0)
+                       argv_array_push(&args, "--quiet");
+
                err = run_command_v_opt(args.argv, RUN_GIT_CMD);
                argv_array_clear(&args);
        }
index a4a923d7c0b688e162c8e4d0411ff9b72748fb5c..c1de41c67f8c245ab53b3c3c86a9ad981f433917 100644 (file)
@@ -102,7 +102,6 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
                        if (fd && close(fd))
                                die_errno("git commit-tree: failed to close '%s'",
                                          argv[i]);
-                       strbuf_complete_line(&buffer);
                        continue;
                }
 
index 89ea1cdd60a215473ecb52ff2a4ce51932e1cf6d..94ff2fba0b024dd351d65f11510cb07070084d4d 100644 (file)
@@ -155,18 +155,21 @@ static int get_name(const char *path, const struct object_id *oid, int flag, voi
         * pattern.
         */
        if (patterns.nr) {
+               int found = 0;
                struct string_list_item *item;
 
                if (!is_tag)
                        return 0;
 
                for_each_string_list_item(item, &patterns) {
-                       if (!wildmatch(item->string, path + 10, 0))
+                       if (!wildmatch(item->string, path + 10, 0)) {
+                               found = 1;
                                break;
+                       }
+               }
 
-                       /* If we get here, no pattern matched. */
+               if (!found)
                        return 0;
-               }
        }
 
        /* Is it annotated? */
index d412c0a8f354659acade8ea6271f5c60826a0b3f..da42ee5e604b72a8b3ac1edf38d8f75bd6805419 100644 (file)
@@ -344,6 +344,7 @@ static void show_filemodify(struct diff_queue_struct *q,
                            struct diff_options *options, void *data)
 {
        int i;
+       struct string_list *changed = data;
 
        /*
         * Handle files below a directory first, in case they are all deleted
@@ -359,20 +360,31 @@ static void show_filemodify(struct diff_queue_struct *q,
                case DIFF_STATUS_DELETED:
                        printf("D ");
                        print_path(spec->path);
+                       string_list_insert(changed, spec->path);
                        putchar('\n');
                        break;
 
                case DIFF_STATUS_COPIED:
                case DIFF_STATUS_RENAMED:
-                       printf("%c ", q->queue[i]->status);
-                       print_path(ospec->path);
-                       putchar(' ');
-                       print_path(spec->path);
-                       putchar('\n');
-
-                       if (!oidcmp(&ospec->oid, &spec->oid) &&
-                           ospec->mode == spec->mode)
-                               break;
+                       /*
+                        * If a change in the file corresponding to ospec->path
+                        * has been observed, we cannot trust its contents
+                        * because the diff is calculated based on the prior
+                        * contents, not the current contents.  So, declare a
+                        * copy or rename only if there was no change observed.
+                        */
+                       if (!string_list_has_string(changed, ospec->path)) {
+                               printf("%c ", q->queue[i]->status);
+                               print_path(ospec->path);
+                               putchar(' ');
+                               print_path(spec->path);
+                               string_list_insert(changed, spec->path);
+                               putchar('\n');
+
+                               if (!oidcmp(&ospec->oid, &spec->oid) &&
+                                   ospec->mode == spec->mode)
+                                       break;
+                       }
                        /* fallthrough */
 
                case DIFF_STATUS_TYPE_CHANGED:
@@ -393,6 +405,7 @@ static void show_filemodify(struct diff_queue_struct *q,
                                       get_object_mark(object));
                        }
                        print_path(spec->path);
+                       string_list_insert(changed, spec->path);
                        putchar('\n');
                        break;
 
@@ -528,7 +541,8 @@ static void anonymize_ident_line(const char **beg, const char **end)
        *end = out->buf + out->len;
 }
 
-static void handle_commit(struct commit *commit, struct rev_info *rev)
+static void handle_commit(struct commit *commit, struct rev_info *rev,
+                         struct string_list *paths_of_changed_objects)
 {
        int saved_output_format = rev->diffopt.output_format;
        const char *commit_buffer;
@@ -615,6 +629,7 @@ static void handle_commit(struct commit *commit, struct rev_info *rev)
        if (full_tree)
                printf("deleteall\n");
        log_tree_diff_flush(rev);
+       string_list_clear(paths_of_changed_objects, 0);
        rev->diffopt.output_format = saved_output_format;
 
        printf("\n");
@@ -630,14 +645,15 @@ static void *anonymize_tag(const void *old, size_t *len)
        return strbuf_detach(&out, len);
 }
 
-static void handle_tail(struct object_array *commits, struct rev_info *revs)
+static void handle_tail(struct object_array *commits, struct rev_info *revs,
+                       struct string_list *paths_of_changed_objects)
 {
        struct commit *commit;
        while (commits->nr) {
                commit = (struct commit *)commits->objects[commits->nr - 1].item;
                if (has_unshown_parent(commit))
                        return;
-               handle_commit(commit, revs);
+               handle_commit(commit, revs, paths_of_changed_objects);
                commits->nr--;
        }
 }
@@ -977,6 +993,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
        char *export_filename = NULL, *import_filename = NULL;
        uint32_t lastimportid;
        struct string_list refspecs_list = STRING_LIST_INIT_NODUP;
+       struct string_list paths_of_changed_objects = STRING_LIST_INIT_DUP;
        struct option options[] = {
                OPT_INTEGER(0, "progress", &progress,
                            N_("show progress after <n> objects")),
@@ -1049,14 +1066,15 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
        if (prepare_revision_walk(&revs))
                die("revision walk setup failed");
        revs.diffopt.format_callback = show_filemodify;
+       revs.diffopt.format_callback_data = &paths_of_changed_objects;
        DIFF_OPT_SET(&revs.diffopt, RECURSIVE);
        while ((commit = get_revision(&revs))) {
                if (has_unshown_parent(commit)) {
                        add_object_array(&commit->object, NULL, &commits);
                }
                else {
-                       handle_commit(commit, &revs);
-                       handle_tail(&commits, &revs);
+                       handle_commit(commit, &revs, &paths_of_changed_objects);
+                       handle_tail(&commits, &revs, &paths_of_changed_objects);
                }
        }
 
index 5d7c921a773718d6bee7f85b8d868fc22602377d..e931be9ce4d9f180de23d09d227e5a2f571f4f1a 100644 (file)
@@ -36,6 +36,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
                OPT_GROUP(""),
                OPT_INTEGER( 0 , "count", &maxcount, N_("show only <n> matched refs")),
                OPT_STRING(  0 , "format", &format.format, N_("format"), N_("format to use for the output")),
+               OPT__COLOR(&format.use_color, N_("respect format colors")),
                OPT_CALLBACK(0 , "sort", sorting_tail, N_("key"),
                            N_("field name to sort on"), &parse_opt_ref_sorting),
                OPT_CALLBACK(0, "points-at", &filter.points_at,
index 64542ac3dea48e3a92901319233aa3a1e0c4cb9a..d18244ab546bae863e6ef81d58663dc5c27c49c0 100644 (file)
@@ -326,6 +326,8 @@ static void check_connectivity(void)
 
 static int fsck_obj(struct object *obj)
 {
+       int err;
+
        if (obj->flags & SEEN)
                return 0;
        obj->flags |= SEEN;
@@ -336,20 +338,13 @@ static int fsck_obj(struct object *obj)
 
        if (fsck_walk(obj, NULL, &fsck_obj_options))
                objerror(obj, "broken links");
-       if (fsck_object(obj, NULL, 0, &fsck_obj_options))
-               return -1;
-
-       if (obj->type == OBJ_TREE) {
-               struct tree *item = (struct tree *) obj;
-
-               free_tree_buffer(item);
-       }
+       err = fsck_object(obj, NULL, 0, &fsck_obj_options);
+       if (err)
+               goto out;
 
        if (obj->type == OBJ_COMMIT) {
                struct commit *commit = (struct commit *) obj;
 
-               free_commit_buffer(commit);
-
                if (!commit->parents && show_root)
                        printf("root %s\n", describe_object(&commit->object));
        }
@@ -365,7 +360,12 @@ static int fsck_obj(struct object *obj)
                }
        }
 
-       return 0;
+out:
+       if (obj->type == OBJ_TREE)
+               free_tree_buffer((struct tree *)obj);
+       if (obj->type == OBJ_COMMIT)
+               free_commit_buffer((struct commit *)obj);
+       return err;
 }
 
 static int fsck_obj_buffer(const struct object_id *oid, enum object_type type,
index e6b84475aef6aeab05beda137fb2882f663fac0f..53c19be8b2c2e6b5495c879d7ab77a6123e3c1b6 100644 (file)
@@ -257,7 +257,7 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid)
                int should_exit;
 
                if (!scan_fmt)
-                       scan_fmt = xstrfmt("%s %%%dc", "%"SCNuMAX, HOST_NAME_MAX);
+                       scan_fmt = xstrfmt("%s %%%ds", "%"SCNuMAX, HOST_NAME_MAX);
                fp = fopen(pidfile_path, "r");
                memset(locking_host, 0, sizeof(locking_host));
                should_exit =
index 42ff87065a0e72c999488d2844463f901fd73a5c..7e79eb1a754a5f604829e3e9e6d98d83712be9b6 100644 (file)
@@ -284,7 +284,7 @@ static int wait_all(void)
 static int grep_cmd_config(const char *var, const char *value, void *cb)
 {
        int st = grep_config(var, value, cb);
-       if (git_default_config(var, value, cb) < 0)
+       if (git_color_default_config(var, value, cb) < 0)
                st = -1;
 
        if (!strcmp(var, "grep.threads")) {
index d5797b8fe77c99c89323348f3a0bd1d68ae9b453..23c53a3082b26e8f89f8be1f14985acc491d9907 100644 (file)
@@ -756,13 +756,17 @@ N_("Please enter a commit message to explain why this merge is necessary,\n"
    "Lines starting with '%c' will be ignored, and an empty message aborts\n"
    "the commit.\n");
 
+static void write_merge_heads(struct commit_list *);
 static void prepare_to_commit(struct commit_list *remoteheads)
 {
        struct strbuf msg = STRBUF_INIT;
        strbuf_addbuf(&msg, &merge_msg);
        strbuf_addch(&msg, '\n');
+       if (squash)
+               BUG("the control must not reach here under --squash");
        if (0 < option_edit)
                strbuf_commented_addf(&msg, _(merge_editor_comment), comment_line_char);
+       write_merge_heads(remoteheads);
        write_file_buf(git_path_merge_msg(), msg.buf, msg.len);
        if (run_commit_hook(0 < option_edit, get_index_file(), "prepare-commit-msg",
                            git_path_merge_msg(), "merge", NULL))
@@ -904,7 +908,7 @@ static int setup_with_upstream(const char ***argv)
        return i;
 }
 
-static void write_merge_state(struct commit_list *remoteheads)
+static void write_merge_heads(struct commit_list *remoteheads)
 {
        struct commit_list *j;
        struct strbuf buf = STRBUF_INIT;
@@ -920,8 +924,6 @@ static void write_merge_state(struct commit_list *remoteheads)
                strbuf_addf(&buf, "%s\n", oid_to_hex(oid));
        }
        write_file_buf(git_path_merge_head(), buf.buf, buf.len);
-       strbuf_addch(&merge_msg, '\n');
-       write_file_buf(git_path_merge_msg(), merge_msg.buf, merge_msg.len);
 
        strbuf_reset(&buf);
        if (fast_forward == FF_NO)
@@ -929,6 +931,13 @@ static void write_merge_state(struct commit_list *remoteheads)
        write_file_buf(git_path_merge_mode(), buf.buf, buf.len);
 }
 
+static void write_merge_state(struct commit_list *remoteheads)
+{
+       write_merge_heads(remoteheads);
+       strbuf_addch(&merge_msg, '\n');
+       write_file_buf(git_path_merge_msg(), merge_msg.buf, merge_msg.len);
+}
+
 static int default_edit_option(void)
 {
        static const char name[] = "GIT_MERGE_AUTOEDIT";
@@ -1117,8 +1126,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
         * current branch.
         */
        branch = branch_to_free = resolve_refdup("HEAD", 0, head_oid.hash, NULL);
-       if (branch && starts_with(branch, "refs/heads/"))
-               branch += 11;
+       if (branch)
+               skip_prefix(branch, "refs/heads/", &branch);
        if (!branch || is_null_oid(&head_oid))
                head_commit = NULL;
        else
index c41ea7c2a62ba868061884e511256c24f4d020d9..598da6c8bc75e9de50f85eac78d3051f27f96a6c 100644 (file)
@@ -253,7 +253,7 @@ static int name_ref(const char *path, const struct object_id *oid, int flags, vo
                struct commit *commit = (struct commit *)o;
                int from_tag = starts_with(path, "refs/tags/");
 
-               if (taggerdate == ULONG_MAX)
+               if (taggerdate == TIME_MAX)
                        taggerdate = ((struct commit *)o)->date;
                path = name_ref_abbrev(path, can_abbreviate_output);
                name_rev(commit, xstrdup(path), taggerdate, 0, 0,
index e8f50489038644ef7a6dc0d217563c65fa9d6083..95b4128250c850eb130fbdfea2407bad819a85b8 100644 (file)
@@ -352,7 +352,8 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
 
        if ((!revs.commits && reflog_walk_empty(revs.reflog_info) &&
             (!(revs.tag_objects || revs.tree_objects || revs.blob_objects) &&
-             !revs.pending.nr)) ||
+             !revs.pending.nr) &&
+            !revs.rev_input_given) ||
            revs.diff)
                usage(rev_list_usage);
 
index c78b7b33d6604bb38a16e30d64cfabee0fd67f40..7f965fe74e5e98496522eddb3ef87fa831265e17 100644 (file)
@@ -757,8 +757,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
                                continue;
                        }
                        if (!strcmp(arg, "--bisect")) {
-                               for_each_ref_in("refs/bisect/bad", show_reference, NULL);
-                               for_each_ref_in("refs/bisect/good", anti_reference, NULL);
+                               for_each_fullref_in("refs/bisect/bad", show_reference, NULL, 0);
+                               for_each_fullref_in("refs/bisect/good", anti_reference, NULL, 0);
                                continue;
                        }
                        if (opt_with_value(arg, "--branches", &arg)) {
index 16028b9ea82edee9cf41044c69a47e8994d78fc6..b9d927eb09c9ed87c84681df1396f4e6d9b13c97 100644 (file)
@@ -155,6 +155,8 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts)
                                "--strategy-option", opts->xopts ? 1 : 0,
                                "-x", opts->record_origin,
                                "--ff", opts->allow_ff,
+                               "--rerere-autoupdate", opts->allow_rerere_auto == RERERE_AUTOUPDATE,
+                               "--no-rerere-autoupdate", opts->allow_rerere_auto == RERERE_NOAUTOUPDATE,
                                NULL);
        }
 
index 28f245c8cccbc20c96a189516e9df77d238c7e96..7073a3eb9769cae1f00e714a93528b33ca651d9c 100644 (file)
@@ -554,7 +554,7 @@ static int git_show_branch_config(const char *var, const char *value, void *cb)
                return 0;
        }
 
-       return git_default_config(var, value, cb);
+       return git_color_default_config(var, value, cb);
 }
 
 static int omit_in_dense(struct commit *commit, struct commit **rev, int n)
index 3a3c9ca72b678f1a446013cc17cc36caa3e47355..895555c93a3bb86ad5511a2ded2350614732d618 100644 (file)
@@ -1108,9 +1108,28 @@ static int resolve_remote_submodule_branch(int argc, const char **argv,
 static int push_check(int argc, const char **argv, const char *prefix)
 {
        struct remote *remote;
+       const char *superproject_head;
+       char *head;
+       int detached_head = 0;
+       struct object_id head_oid;
 
-       if (argc < 2)
-               die("submodule--helper push-check requires at least 1 argument");
+       if (argc < 3)
+               die("submodule--helper push-check requires at least 2 arguments");
+
+       /*
+        * superproject's resolved head ref.
+        * if HEAD then the superproject is in a detached head state, otherwise
+        * it will be the resolved head ref.
+        */
+       superproject_head = argv[1];
+       argv++;
+       argc--;
+       /* Get the submodule's head ref and determine if it is detached */
+       head = resolve_refdup("HEAD", 0, head_oid.hash, NULL);
+       if (!head)
+               die(_("Failed to resolve HEAD as a valid ref."));
+       if (!strcmp(head, "HEAD"))
+               detached_head = 1;
 
        /*
         * The remote must be configured.
@@ -1133,18 +1152,30 @@ static int push_check(int argc, const char **argv, const char *prefix)
                        if (rs->pattern || rs->matching)
                                continue;
 
-                       /*
-                        * LHS must match a single ref
-                        * NEEDSWORK: add logic to special case 'HEAD' once
-                        * working with submodules in a detached head state
-                        * ceases to be the norm.
-                        */
-                       if (count_refspec_match(rs->src, local_refs, NULL) != 1)
+                       /* LHS must match a single ref */
+                       switch (count_refspec_match(rs->src, local_refs, NULL)) {
+                       case 1:
+                               break;
+                       case 0:
+                               /*
+                                * If LHS matches 'HEAD' then we need to ensure
+                                * that it matches the same named branch
+                                * checked out in the superproject.
+                                */
+                               if (!strcmp(rs->src, "HEAD")) {
+                                       if (!detached_head &&
+                                           !strcmp(head, superproject_head))
+                                               break;
+                                       die("HEAD does not match the named branch in the superproject");
+                               }
+                       default:
                                die("src refspec '%s' must name a ref",
                                    rs->src);
+                       }
                }
                free_refspec(refspec_nr, refspec);
        }
+       free(head);
 
        return 0;
 }
index 66e35b823b6e0a3e732fb84e402dd0af6830a471..00382a56f564bf55de13ba712b8e728b3b1c9b86 100644 (file)
@@ -158,7 +158,7 @@ static int git_tag_config(const char *var, const char *value, void *cb)
 
        if (starts_with(var, "column."))
                return git_column_config(var, value, "tag", &colopts);
-       return git_default_config(var, value, cb);
+       return git_color_default_config(var, value, cb);
 }
 
 static void write_tag_body(int fd, const struct object_id *oid)
@@ -411,6 +411,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
                },
                OPT_STRING(  0 , "format", &format.format, N_("format"),
                           N_("format to use for the output")),
+               OPT__COLOR(&format.use_color, N_("respect format colors")),
                OPT_BOOL('i', "ignore-case", &icase, N_("sorting and filtering are case insensitive")),
                OPT_END()
        };
@@ -440,6 +441,9 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
                        cmdmode = 'l';
        }
 
+       if (cmdmode == 'l')
+               setup_auto_pager("tag", 1);
+
        if ((create_tag_object || force) && (cmdmode != 0))
                usage_with_options(git_tag_usage, options);
 
diff --git a/cache.h b/cache.h
index 25c98b68093858e5ffc37fd33cf2efb0b2561ba7..849bc0dcdd0d6bc572d3524f2646ea7f719eb7a9 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -939,14 +939,7 @@ extern const struct object_id null_oid;
 
 static inline int hashcmp(const unsigned char *sha1, const unsigned char *sha2)
 {
-       int i;
-
-       for (i = 0; i < GIT_SHA1_RAWSZ; i++, sha1++, sha2++) {
-               if (*sha1 != *sha2)
-                       return *sha1 - *sha2;
-       }
-
-       return 0;
+       return memcmp(sha1, sha2, GIT_SHA1_RAWSZ);
 }
 
 static inline int oidcmp(const struct object_id *oid1, const struct object_id *oid2)
@@ -1552,7 +1545,6 @@ extern struct alternate_object_database {
        char path[FLEX_ARRAY];
 } *alt_odb_list;
 extern void prepare_alt_odb(void);
-extern void read_info_alternates(const char * relative_base, int depth);
 extern char *compute_alternate_path(const char *path, struct strbuf *err);
 typedef int alt_odb_fn(struct alternate_object_database *, void *);
 extern int foreach_alt_odb(alt_odb_fn, void*);
diff --git a/color.c b/color.c
index 7aa8b076f045e5c0b74826153030e2923c0fc56e..31b6207a00de42a386e98c5656209ea7a010abe4 100644 (file)
--- a/color.c
+++ b/color.c
@@ -361,6 +361,14 @@ int git_color_config(const char *var, const char *value, void *cb)
        return 0;
 }
 
+int git_color_default_config(const char *var, const char *value, void *cb)
+{
+       if (git_color_config(var, value, cb) < 0)
+               return -1;
+
+       return git_default_config(var, value, cb);
+}
+
 void color_print_strbuf(FILE *fp, const char *color, const struct strbuf *sb)
 {
        if (*color)
index 4127c298cb1370a9ab56ca9d003e853b3e26b67e..f3805fec6b3a5853316d1476619adc5410224a7e 100644 (file)
--- a/commit.h
+++ b/commit.h
@@ -313,11 +313,6 @@ extern int interactive_add(int argc, const char **argv, const char *prefix, int
 extern int run_add_interactive(const char *revision, const char *patch_mode,
                               const struct pathspec *pathspec);
 
-static inline int single_parent(struct commit *commit)
-{
-       return commit->parents && !commit->parents->next;
-}
-
 struct commit_list *reduce_heads(struct commit_list *heads);
 
 struct commit_extra_header {
index b10adc780fc334383f2684d21fa1c5a8d92771b9..ae03b74a6f4e9c8ff6d519d9a784ab6b84179872 100644 (file)
@@ -438,6 +438,10 @@ poll (struct pollfd *pfd, nfds_t nfd, int timeout)
            pfd[i].revents = happened;
            rc++;
          }
+       else
+         {
+           pfd[i].revents = 0;
+         }
       }
 
   return rc;
index 6c7c9b60538d932d6dbc2d32774a6f64f8687c69..161978d720aed9db5a00c77d1c6bd9a073544f15 100644 (file)
@@ -43,8 +43,10 @@ void syslog(int priority, const char *fmt, ...)
        va_end(ap);
 
        while ((pos = strstr(str, "%1")) != NULL) {
+               char *oldstr = str;
                str = realloc(str, st_add(++str_len, 1));
                if (!str) {
+                       free(oldstr);
                        warning_errno("realloc failed");
                        return;
                }
index acebc85d81372f15d3d490d84dc751f59bde26c4..c6bc2ff715147d16734e3b997c18fdd49642fd00 100644 (file)
--- a/config.c
+++ b/config.c
@@ -16,7 +16,6 @@
 #include "string-list.h"
 #include "utf8.h"
 #include "dir.h"
-#include "color.h"
 
 struct config_source {
        struct config_source *prev;
@@ -1351,9 +1350,6 @@ int git_default_config(const char *var, const char *value, void *dummy)
        if (starts_with(var, "advice."))
                return git_default_advice_config(var, value);
 
-       if (git_color_config(var, value, dummy) < 0)
-               return -1;
-
        if (!strcmp(var, "pager.color") || !strcmp(var, "color.pager")) {
                pager_use_color = git_config_bool(var,value);
                return 0;
@@ -2404,7 +2400,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
 {
        int fd = -1, in_fd = -1;
        int ret;
-       struct lock_file *lock = NULL;
+       static struct lock_file lock;
        char *filename_buf = NULL;
        char *contents = NULL;
        size_t contents_sz;
@@ -2423,8 +2419,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
         * The lock serves a purpose in addition to locking: the new
         * contents of .git/config will be written into it.
         */
-       lock = xcalloc(1, sizeof(struct lock_file));
-       fd = hold_lock_file_for_update(lock, config_filename, 0);
+       fd = hold_lock_file_for_update(&lock, config_filename, 0);
        if (fd < 0) {
                error_errno("could not lock config file %s", config_filename);
                free(store.key);
@@ -2537,8 +2532,8 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
                close(in_fd);
                in_fd = -1;
 
-               if (chmod(get_lock_file_path(lock), st.st_mode & 07777) < 0) {
-                       error_errno("chmod on %s failed", get_lock_file_path(lock));
+               if (chmod(get_lock_file_path(&lock), st.st_mode & 07777) < 0) {
+                       error_errno("chmod on %s failed", get_lock_file_path(&lock));
                        ret = CONFIG_NO_WRITE;
                        goto out_free;
                }
@@ -2593,28 +2588,19 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
                contents = NULL;
        }
 
-       if (commit_lock_file(lock) < 0) {
+       if (commit_lock_file(&lock) < 0) {
                error_errno("could not write config file %s", config_filename);
                ret = CONFIG_NO_WRITE;
-               lock = NULL;
                goto out_free;
        }
 
-       /*
-        * lock is committed, so don't try to roll it back below.
-        * NOTE: Since lockfile.c keeps a linked list of all created
-        * lock_file structures, it isn't safe to free(lock).  It's
-        * better to just leave it hanging around.
-        */
-       lock = NULL;
        ret = 0;
 
        /* Invalidate the config cache */
        git_config_clear();
 
 out_free:
-       if (lock)
-               rollback_lock_file(lock);
+       rollback_lock_file(&lock);
        free(filename_buf);
        if (contents)
                munmap(contents, contents_sz);
@@ -2623,7 +2609,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
        return ret;
 
 write_err_out:
-       ret = write_error(get_lock_file_path(lock));
+       ret = write_error(get_lock_file_path(&lock));
        goto out_free;
 
 }
index c61d1ca8dc49f1da8dd70cf0c00ce97b1f18fcd2..01586821dc7c15be2a94c30bfbf4f3b4c94ac5f3 100644 (file)
@@ -4,7 +4,7 @@ T *dst;
 T *src;
 expression n;
 @@
-- memcpy(dst, src, n * sizeof(*dst));
+- memcpy(dst, src, (n) * sizeof(*dst));
 + COPY_ARRAY(dst, src, n);
 
 @@
@@ -13,7 +13,7 @@ T *dst;
 T *src;
 expression n;
 @@
-- memcpy(dst, src, n * sizeof(*src));
+- memcpy(dst, src, (n) * sizeof(*src));
 + COPY_ARRAY(dst, src, n);
 
 @@
@@ -22,7 +22,7 @@ T *dst;
 T *src;
 expression n;
 @@
-- memcpy(dst, src, n * sizeof(T));
+- memcpy(dst, src, (n) * sizeof(T));
 + COPY_ARRAY(dst, src, n);
 
 @@
@@ -47,7 +47,7 @@ type T;
 T *ptr;
 expression n;
 @@
-- ptr = xmalloc(n * sizeof(*ptr));
+- ptr = xmalloc((n) * sizeof(*ptr));
 + ALLOC_ARRAY(ptr, n);
 
 @@
@@ -55,5 +55,5 @@ type T;
 T *ptr;
 expression n;
 @@
-- ptr = xmalloc(n * sizeof(T));
+- ptr = xmalloc((n) * sizeof(T));
 + ALLOC_ARRAY(ptr, n);
index d93441747523ab2971e114cd6a02d56b79ba3382..0e16f017a4144220043d27e0c1556a6d1edbdf01 100644 (file)
@@ -1385,7 +1385,7 @@ _git_describe ()
                __gitcomp "
                        --all --tags --contains --abbrev= --candidates=
                        --exact-match --debug --long --match --always --first-parent
-                       --exclude
+                       --exclude --dirty --broken
                        "
                return
        esac
index fbf5c582496eece56b29a91a2f3085716f4b0e9f..f2be7cc92437191219d16ddf1536883da23541c0 100644 (file)
@@ -17,4 +17,7 @@ shebang.perl: FORCE
 test: all
        $(MAKE) -C t
 
+clean:
+       $(RM) diff-highlight
+
 .PHONY: FORCE
index 4936fcc26b907ca6338ef74bcadc03079b3a3075..387c1c5455be954d2be3d35f8be794bb5bd7f3e8 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -1133,10 +1133,12 @@ int convert_to_git(const struct index_state *istate,
                src = dst->buf;
                len = dst->len;
        }
-       ret |= crlf_to_git(istate, path, src, len, dst, ca.crlf_action, checksafe);
-       if (ret && dst) {
-               src = dst->buf;
-               len = dst->len;
+       if (checksafe != SAFE_CRLF_KEEP_CRLF) {
+               ret |= crlf_to_git(istate, path, src, len, dst, ca.crlf_action, checksafe);
+               if (ret && dst) {
+                       src = dst->buf;
+                       len = dst->len;
+               }
        }
        return ret | ident_to_git(path, src, len, dst, ca.ident);
 }
index 6b06144281c797a08c10e0dc5bf72f97d260be88..4f2da225a8926f92e465c7dea27cdc4589864e1f 100644 (file)
--- a/convert.h
+++ b/convert.h
@@ -12,7 +12,8 @@ enum safe_crlf {
        SAFE_CRLF_FALSE = 0,
        SAFE_CRLF_FAIL = 1,
        SAFE_CRLF_WARN = 2,
-       SAFE_CRLF_RENORMALIZE = 3
+       SAFE_CRLF_RENORMALIZE = 3,
+       SAFE_CRLF_KEEP_CRLF = 4
 };
 
 extern enum safe_crlf safe_crlf;
diff --git a/diff.c b/diff.c
index 9c382580306e340ed6333f96bc4919c4c507a7b9..85e714f6c68d24e11228b69d2511c49811c979b4 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -299,6 +299,9 @@ int git_diff_ui_config(const char *var, const char *value, void *cb)
                return 0;
        }
 
+       if (git_color_config(var, value, cb) < 0)
+               return -1;
+
        return git_diff_basic_config(var, value, cb);
 }
 
index fb94aeba9cef2893ea7173e5634640e596659474..ce192a2d64c846e9d7ccffe10c9476f9c5abb8b8 100644 (file)
@@ -5,21 +5,14 @@
 #define MAX_ARGS       32
 
 static const char *argv_exec_path;
+
+#ifdef RUNTIME_PREFIX
 static const char *argv0_path;
 
-char *system_path(const char *path)
+static const char *system_prefix(void)
 {
-#ifdef RUNTIME_PREFIX
        static const char *prefix;
-#else
-       static const char *prefix = PREFIX;
-#endif
-       struct strbuf d = STRBUF_INIT;
-
-       if (is_absolute_path(path))
-               return xstrdup(path);
 
-#ifdef RUNTIME_PREFIX
        assert(argv0_path);
        assert(is_absolute_path(argv0_path));
 
@@ -32,10 +25,7 @@ char *system_path(const char *path)
                                "but prefix computation failed.  "
                                "Using static fallback '%s'.\n", prefix);
        }
-#endif
-
-       strbuf_addf(&d, "%s/%s", prefix, path);
-       return strbuf_detach(&d, NULL);
+       return prefix;
 }
 
 void git_extract_argv0_path(const char *argv0)
@@ -51,6 +41,30 @@ void git_extract_argv0_path(const char *argv0)
                argv0_path = xstrndup(argv0, slash - argv0);
 }
 
+#else
+
+static const char *system_prefix(void)
+{
+       return PREFIX;
+}
+
+void git_extract_argv0_path(const char *argv0)
+{
+}
+
+#endif /* RUNTIME_PREFIX */
+
+char *system_path(const char *path)
+{
+       struct strbuf d = STRBUF_INIT;
+
+       if (is_absolute_path(path))
+               return xstrdup(path);
+
+       strbuf_addf(&d, "%s/%s", system_prefix(), path);
+       return strbuf_detach(&d, NULL);
+}
+
 void git_set_argv_exec_path(const char *exec_path)
 {
        argv_exec_path = exec_path;
index a959161b4631e134602aa9b5502105ee5c5bcfb8..365d3191aa1abfb42b4d0da6973612126cc74f3b 100644 (file)
@@ -3188,10 +3188,10 @@ static void checkpoint(void)
        checkpoint_requested = 0;
        if (object_count) {
                cycle_packfile();
-               dump_branches();
-               dump_tags();
-               dump_marks();
        }
+       dump_branches();
+       dump_tags();
+       dump_marks();
 }
 
 static void parse_checkpoint(void)
diff --git a/fsck.c b/fsck.c
index b4204d772b39335c5feb5c85a11c517bcedcd562..b1579c7e2821a99729af85b1382f7ea5c3824b8f 100644 (file)
--- a/fsck.c
+++ b/fsck.c
@@ -358,15 +358,15 @@ static int fsck_walk_tree(struct tree *tree, void *data, struct fsck_options *op
                        continue;
 
                if (S_ISDIR(entry.mode)) {
-                       obj = &lookup_tree(entry.oid)->object;
-                       if (name)
+                       obj = (struct object *)lookup_tree(entry.oid);
+                       if (name && obj)
                                put_object_name(options, obj, "%s%s/", name,
                                        entry.path);
                        result = options->walk(obj, OBJ_TREE, data, options);
                }
                else if (S_ISREG(entry.mode) || S_ISLNK(entry.mode)) {
-                       obj = &lookup_blob(entry.oid)->object;
-                       if (name)
+                       obj = (struct object *)lookup_blob(entry.oid);
+                       if (name && obj)
                                put_object_name(options, obj, "%s%s", name,
                                        entry.path);
                        result = options->walk(obj, OBJ_BLOB, data, options);
index 9cb123a07df88c975cf1b0d6c5832cb410175dd0..b7c173c345544d61a887cfbebb58703478a29d2d 100755 (executable)
@@ -983,7 +983,7 @@ sub find_parents {
        # check that we actually know about the branch
        next unless -e "$git_dir/refs/heads/$branch";
 
-       my $mergebase = `git-merge-base $branch $ps->{branch}`;
+       my $mergebase = safe_pipe_capture(qw(git-merge-base), $branch, $ps->{branch});
        if ($?) {
            # Don't die here, Arch supports one-way cherry-picking
            # between branches with no common base (or any relationship
@@ -1074,7 +1074,7 @@ sub find_parents {
 
 sub git_rev_parse {
     my $name = shift;
-    my $val  = `git-rev-parse $name`;
+    my $val  = safe_pipe_capture(qw(git-rev-parse), $name);
     die "Error: git-rev-parse $name" if $?;
     chomp $val;
     return $val;
index 1e4e65a45d16cfcc5a36e6855216e9be8fe0e0b4..36929921ea79006dc659f6996ae158131ccf2b73 100755 (executable)
@@ -642,6 +642,7 @@ sub is_sha1 {
 
 sub get_headref ($) {
        my $name = shift;
+       $name =~ s/'/'\\''/;
        my $r = `git rev-parse --verify '$name' 2>/dev/null`;
        return undef unless $? == 0;
        chomp $r;
index d50c85ed7ba719a0dc04f7ca96cf05216104599d..ae1044273d01125af96a06f1d68cbbd3d0e25c41 100755 (executable)
@@ -356,7 +356,7 @@ sub req_Root
        return 0;
     }
 
-    my @gitvars = `git config -l`;
+    my @gitvars = safe_pipe_capture(qw(git config -l));
     if ($?) {
        print "E problems executing git-config on the server -- this is not a git repository or the PATH is not set correctly.\n";
         print "E \n";
@@ -841,7 +841,7 @@ sub req_Modified
     # Save the file data in $state
     $state->{entries}{$state->{directory}.$data}{modified_filename} = $filename;
     $state->{entries}{$state->{directory}.$data}{modified_mode} = $mode;
-    $state->{entries}{$state->{directory}.$data}{modified_hash} = `git hash-object $filename`;
+    $state->{entries}{$state->{directory}.$data}{modified_hash} = safe_pipe_capture('git','hash-object',$filename);
     $state->{entries}{$state->{directory}.$data}{modified_hash} =~ s/\s.*$//s;
 
     #$log->debug("req_Modified : file=$data mode=$mode size=$size");
@@ -943,7 +943,7 @@ sub req_co
 
     # Provide list of modules, if -c was used.
     if (exists $state->{opt}{c}) {
-        my $showref = `git show-ref --heads`;
+        my $showref = safe_pipe_capture(qw(git show-ref --heads));
         for my $line (split '\n', $showref) {
             if ( $line =~ m% refs/heads/(.*)$% ) {
                 print "M $1\t$1\n";
@@ -1181,7 +1181,7 @@ sub req_update
     # projects (heads in this case) to checkout.
     #
     if ($state->{module} eq '') {
-        my $showref = `git show-ref --heads`;
+        my $showref = safe_pipe_capture(qw(git show-ref --heads));
         print "E cvs update: Updating .\n";
         for my $line (split '\n', $showref) {
             if ( $line =~ m% refs/heads/(.*)$% ) {
@@ -1463,7 +1463,7 @@ sub req_update
                 # transmit file, format is single integer on a line by itself (file
                 # size) followed by the file contents
                 # TODO : we should copy files in blocks
-                my $data = `cat $mergedFile`;
+                my $data = safe_pipe_capture('cat', $mergedFile);
                 $log->debug("File size : " . length($data));
                 print length($data) . "\n";
                 print $data;
@@ -1579,7 +1579,7 @@ sub req_ci
                 $branchRef = "refs/heads/$stickyInfo->{tag}";
             }
 
-            $parenthash = `git show-ref -s $branchRef`;
+            $parenthash = safe_pipe_capture('git', 'show-ref', '-s', $branchRef);
             chomp $parenthash;
             if ($parenthash !~ /^[0-9a-f]{40}$/)
             {
@@ -1687,7 +1687,7 @@ sub req_ci
         return;
     }
 
-    my $treehash = `git write-tree`;
+    my $treehash = safe_pipe_capture(qw(git write-tree));
     chomp $treehash;
 
     $log->debug("Treehash : $treehash, Parenthash : $parenthash");
@@ -1704,7 +1704,7 @@ sub req_ci
     }
     close $msg_fh;
 
-    my $commithash = `git commit-tree $treehash -p $parenthash < $msg_filename`;
+    my $commithash = safe_pipe_capture('git', 'commit-tree', $treehash, '-p', $parenthash, '-F', $msg_filename);
     chomp($commithash);
     $log->info("Commit hash : $commithash");
 
@@ -2854,12 +2854,12 @@ sub transmitfile
 
     die "Need filehash" unless ( defined ( $filehash ) and $filehash =~ /^[a-zA-Z0-9]{40}$/ );
 
-    my $type = `git cat-file -t $filehash`;
+    my $type = safe_pipe_capture('git', 'cat-file', '-t', $filehash);
     chomp $type;
 
     die ( "Invalid type '$type' (expected 'blob')" ) unless ( defined ( $type ) and $type eq "blob" );
 
-    my $size = `git cat-file -s $filehash`;
+    my $size = safe_pipe_capture('git', 'cat-file', '-s', $filehash);
     chomp $size;
 
     $log->debug("transmitfile($filehash) size=$size, type=$type");
@@ -3040,7 +3040,7 @@ sub ensureWorkTree
     chdir $work->{emptyDir} or
         die "Unable to chdir to $work->{emptyDir}\n";
 
-    my $ver = `git show-ref -s refs/heads/$state->{module}`;
+    my $ver = safe_pipe_capture('git', 'show-ref', '-s', "refs/heads/$state->{module}");
     chomp $ver;
     if ($ver !~ /^[0-9a-f]{40}$/)
     {
@@ -3287,7 +3287,7 @@ sub open_blob_or_die
             die "Need filehash\n";
         }
 
-        my $type = `git cat-file -t $name`;
+        my $type = safe_pipe_capture('git', 'cat-file', '-t', $name);
         chomp $type;
 
         unless ( defined ( $type ) and $type eq "blob" )
@@ -3296,7 +3296,7 @@ sub open_blob_or_die
             die ( "Invalid type '$type' (expected 'blob')" )
         }
 
-        my $size = `git cat-file -s $name`;
+        my $size = safe_pipe_capture('git', 'cat-file', '-s', $name);
         chomp $size;
 
         $log->debug("open_blob_or_die($name) size=$size, type=$type");
@@ -3406,6 +3406,22 @@ sub refHashEqual
     return $out;
 }
 
+# an alternative to `command` that allows input to be passed as an array
+# to work around shell problems with weird characters in arguments
+
+sub safe_pipe_capture {
+
+    my @output;
+
+    if (my $pid = open my $child, '-|') {
+        @output = (<$child>);
+        close $child or die join(' ',@_).": $! $?";
+    } else {
+        exec(@_) or die "$! $?"; # exec() can fail the executable can't be found
+    }
+    return wantarray ? @output : join('',@output);
+}
+
 
 package GITCVS::log;
 
@@ -3797,10 +3813,10 @@ sub update
     # first lets get the commit list
     $ENV{GIT_DIR} = $self->{git_path};
 
-    my $commitsha1 = `git rev-parse $self->{module}`;
+    my $commitsha1 = ::safe_pipe_capture('git', 'rev-parse', $self->{module});
     chomp $commitsha1;
 
-    my $commitinfo = `git cat-file commit $self->{module} 2>&1`;
+    my $commitinfo = ::safe_pipe_capture('git', 'cat-file', 'commit', $self->{module});
     unless ( $commitinfo =~ /tree\s+[a-zA-Z0-9]{40}/ )
     {
         die("Invalid module '$self->{module}'");
@@ -3882,7 +3898,7 @@ sub update
                     # several candidate merge bases. let's assume
                     # that the first one is the best one.
                    my $base = eval {
-                           safe_pipe_capture('git', 'merge-base',
+                           ::safe_pipe_capture('git', 'merge-base',
                                                 $lastpicked, $parent);
                    };
                    # The two branches may not be related at all,
@@ -4749,7 +4765,7 @@ sub getMetaFromCommithash
         return $retVal;
     }
 
-    my($fileHash)=safe_pipe_capture("git","rev-parse","$revCommit:$filename");
+    my($fileHash) = ::safe_pipe_capture("git","rev-parse","$revCommit:$filename");
     chomp $fileHash;
     if(!($fileHash=~/^[0-9a-f]{40}$/))
     {
@@ -4844,8 +4860,8 @@ sub lookupCommitRef
         return $commitHash;
     }
 
-    $commitHash=safe_pipe_capture("git","rev-parse","--verify","--quiet",
-                                  $self->unescapeRefName($ref));
+    $commitHash = ::safe_pipe_capture("git","rev-parse","--verify","--quiet",
+                                     $self->unescapeRefName($ref));
     $commitHash=~s/\s*$//;
     if(!($commitHash=~/^[0-9a-f]{40}$/))
     {
@@ -4854,7 +4870,7 @@ sub lookupCommitRef
 
     if( defined($commitHash) )
     {
-        my $type=safe_pipe_capture("git","cat-file","-t",$commitHash);
+        my $type = ::safe_pipe_capture("git","cat-file","-t",$commitHash);
         if( ! ($type=~/^commit\s*$/ ) )
         {
             $commitHash=undef;
@@ -4907,7 +4923,7 @@ sub commitmessage
         return $message;
     }
 
-    my @lines = safe_pipe_capture("git", "cat-file", "commit", $commithash);
+    my @lines = ::safe_pipe_capture("git", "cat-file", "commit", $commithash);
     shift @lines while ( $lines[0] =~ /\S/ );
     $message = join("",@lines);
     $message .= " " if ( $message =~ /\n$/ );
@@ -5056,25 +5072,6 @@ sub in_array
     return $retval;
 }
 
-=head2 safe_pipe_capture
-
-an alternative to `command` that allows input to be passed as an array
-to work around shell problems with weird characters in arguments
-
-=cut
-sub safe_pipe_capture {
-
-    my @output;
-
-    if (my $pid = open my $child, '-|') {
-        @output = (<$child>);
-        close $child or die join(' ',@_).": $! $?";
-    } else {
-        exec(@_) or die "$! $?"; # exec() can fail the executable can't be found
-    }
-    return wantarray ? @output : join('',@output);
-}
-
 =head2 mangle_dirname
 
 create a string from a directory name that is suitable to use as
index bcf0d92ec223bf9e1f0995c5acef6376d1299502..6c390d6c229d7ef8cca8ae01d33b42b57e29c3b3 100755 (executable)
@@ -100,7 +100,7 @@ do
        if test $? -ne 0
        then
                gettextln "Simple merge did not work, trying automatic merge."
-               git-merge-index -o git-merge-one-file -a ||
+               git merge-index -o git-merge-one-file -a ||
                OCTOPUS_FAILURE=1
                next=$(git write-tree 2>/dev/null)
        fi
index 424b034e34b4b40e7c44da16ddf83a31dee6f6a0..9879c59395edff1a02e390397fc623bc60724c57 100755 (executable)
@@ -115,16 +115,16 @@ case "${1:-.}${2:-.}${3:-.}" in
                ;;
        esac
 
-       src1=$(git-unpack-file $2)
-       src2=$(git-unpack-file $3)
+       src1=$(git unpack-file $2)
+       src2=$(git unpack-file $3)
        case "$1" in
        '')
                echo "Added $4 in both, but differently."
-               orig=$(git-unpack-file e69de29bb2d1d6434b8b29ae775ad8c2e48c5391)
+               orig=$(git unpack-file e69de29bb2d1d6434b8b29ae775ad8c2e48c5391)
                ;;
        *)
                echo "Auto-merging $4"
-               orig=$(git-unpack-file $1)
+               orig=$(git unpack-file $1)
                ;;
        esac
 
index c9da747fcfe504b1fd233c68d91e549def0f3571..343fe7bccd0d64f0caff1ad5d3f981729a8e5fc9 100755 (executable)
@@ -45,7 +45,7 @@ then
        exit 0
 else
        echo "Simple merge failed, trying Automatic merge."
-       if git-merge-index -o git-merge-one-file -a
+       if git merge-index -o git-merge-one-file -a
        then
                exit 0
        else
index 375239341fbfe885e51a25e9e0dc2d4fee791345..319933e70a34f9da4ec93d063eb102eff33b6787 100644 (file)
@@ -45,7 +45,7 @@ then
        # itself well to recording empty patches.  fortunately, cherry-pick
        # makes this easy
        git cherry-pick ${gpg_sign_opt:+"$gpg_sign_opt"} --allow-empty \
-               --right-only "$revisions" \
+               $allow_rerere_autoupdate --right-only "$revisions" \
                ${restrict_revision+^$restrict_revision}
        ret=$?
 else
@@ -82,6 +82,7 @@ else
        fi
 
        git am $git_am_opt --rebasing --resolvemsg="$resolvemsg" \
+               $allow_rerere_autoupdate \
                ${gpg_sign_opt:+"$gpg_sign_opt"} <"$GIT_DIR/rebased-patches"
        ret=$?
 
index 90b1fbe9cf6e8dfb2f4331916809fa40bf9050d2..29b7e8824b53abeaa68780b95d5954f67f734098 100644 (file)
@@ -281,7 +281,7 @@ pick_one () {
 
        test -d "$rewritten" &&
                pick_one_preserving_merges "$@" && return
-       output eval git cherry-pick \
+       output eval git cherry-pick $allow_rerere_autoupdate \
                        ${gpg_sign_opt:+$(git rev-parse --sq-quote "$gpg_sign_opt")} \
                        "$strategy_args" $empty_args $ff "$@"
 
@@ -393,7 +393,8 @@ pick_one_preserving_merges () {
                        merge_args="--no-log --no-ff"
                        if ! do_with_author output eval \
                        'git merge ${gpg_sign_opt:+"$gpg_sign_opt"} \
-                               $merge_args $strategy_args -m "$msg_content" $new_parents'
+                               $allow_rerere_autoupdate $merge_args \
+                               $strategy_args -m "$msg_content" $new_parents'
                        then
                                printf "%s\n" "$msg_content" > "$GIT_DIR"/MERGE_MSG
                                die_with_patch $sha1 "$(eval_gettext "Error redoing merge \$sha1")"
@@ -401,7 +402,7 @@ pick_one_preserving_merges () {
                        echo "$sha1 $(git rev-parse HEAD^0)" >> "$rewritten_list"
                        ;;
                *)
-                       output eval git cherry-pick \
+                       output eval git cherry-pick $allow_rerere_autoupdate \
                                ${gpg_sign_opt:+$(git rev-parse --sq-quote "$gpg_sign_opt")} \
                                "$strategy_args" "$@" ||
                                die_with_patch $sha1 "$(eval_gettext "Could not pick \$sha1")"
index eebd33276da9028afa1f2ed3b03e60f037d7e646..13c172bd94fc5d4a9658b27fae9733f73a272376 100755 (executable)
@@ -128,7 +128,7 @@ git show -s --format='The following changes since commit %H:
 
   %s (%ci)
 
-are available in the git repository at:
+are available in the Git repository at:
 ' $merge_base &&
 echo "  $url $pretty_remote" &&
 git show -s --format='
index fa6526986ed40143a12ffcd6563fd52b49d209e7..2208dcc2139be7130749fd3bae462320f17d3b21 100755 (executable)
@@ -155,7 +155,6 @@ sub format_2822_time {
 }
 
 my $have_email_valid = eval { require Email::Valid; 1 };
-my $have_mail_address = eval { require Mail::Address; 1 };
 my $smtp;
 my $auth;
 my $num_sent = 0;
@@ -490,11 +489,7 @@ sub read_config {
 ($repocommitter) = Git::ident_person(@repo, 'committer');
 
 sub parse_address_line {
-       if ($have_mail_address) {
-               return map { $_->format } Mail::Address->parse($_[0]);
-       } else {
-               return Git::parse_mailboxes($_[0]);
-       }
+       return Git::parse_mailboxes($_[0]);
 }
 
 sub split_addrs {
@@ -1089,6 +1084,26 @@ sub sanitize_address {
 
 }
 
+sub strip_garbage_one_address {
+       my ($addr) = @_;
+       chomp $addr;
+       if ($addr =~ /^(("[^"]*"|[^"<]*)? *<[^>]*>).*/) {
+               # "Foo Bar" <foobar@example.com> [possibly garbage here]
+               # Foo Bar <foobar@example.com> [possibly garbage here]
+               return $1;
+       }
+       if ($addr =~ /^(<[^>]*>).*/) {
+               # <foo@example.com> [possibly garbage here]
+               # if garbage contains other addresses, they are ignored.
+               return $1;
+       }
+       if ($addr =~ /^([^"#,\s]*)/) {
+               # address without quoting: remove anything after the address
+               return $1;
+       }
+       return $addr;
+}
+
 sub sanitize_address_list {
        return (map { sanitize_address($_) } @_);
 }
@@ -1590,10 +1605,12 @@ sub send_message {
        # Now parse the message body
        while(<$fh>) {
                $message .=  $_;
-               if (/^(Signed-off-by|Cc): ([^>]*>?)/i) {
+               if (/^(Signed-off-by|Cc): (.*)/i) {
                        chomp;
                        my ($what, $c) = ($1, $2);
-                       chomp $c;
+                       # strip garbage for the address we'll use:
+                       $c = strip_garbage_one_address($c);
+                       # sanitize a bit more to decide whether to suppress the address:
                        my $sc = sanitize_address($c);
                        if ($sc eq $sender) {
                                next if ($suppress_cc{'self'});
index 9b6c2da7b4b75980403d836f6fa1fc516bdc3639..328cd80d83a03a674e0541bddb6bce0532c682b7 100755 (executable)
@@ -43,9 +43,16 @@ no_changes () {
 }
 
 untracked_files () {
+       if test "$1" = "-z"
+       then
+               shift
+               z=-z
+       else
+               z=
+       fi
        excl_opt=--exclude-standard
        test "$untracked" = "all" && excl_opt=
-       git ls-files -o -z $excl_opt -- "$@"
+       git ls-files -o $z $excl_opt -- "$@"
 }
 
 clear_stash () {
@@ -114,7 +121,7 @@ create_stash () {
                # Untracked files are stored by themselves in a parentless commit, for
                # ease of unpacking later.
                u_commit=$(
-                       untracked_files "$@" | (
+                       untracked_files -z "$@" | (
                                GIT_INDEX_FILE="$TMPindex" &&
                                export GIT_INDEX_FILE &&
                                rm -f "$TMPindex" &&
@@ -573,7 +580,7 @@ apply_stash () {
 
        if test -n "$u_tree"
        then
-               GIT_INDEX_FILE="$TMPindex" git-read-tree "$u_tree" &&
+               GIT_INDEX_FILE="$TMPindex" git read-tree "$u_tree" &&
                GIT_INDEX_FILE="$TMPindex" git checkout-index --all &&
                rm -f "$TMPindex" ||
                die "$(gettext "Could not restore untracked files from stash entry")"
index e131760eecf944aee97e18a68ab1f171fc0e1d1b..66d1ae8ef6c5f12c856a2f88eabce515dcafd489 100755 (executable)
@@ -611,7 +611,6 @@ cmd_update()
                die_if_unmatched "$mode" "$sha1"
 
                name=$(git submodule--helper name "$sm_path") || exit
-               url=$(git config submodule."$name".url)
                if ! test -z "$update"
                then
                        update_module=$update
@@ -864,7 +863,7 @@ cmd_summary() {
                                test $status != A && test $ignore_config = all && continue
                        fi
                        # Also show added or modified modules which are checked out
-                       GIT_DIR="$sm_path/.git" git-rev-parse --git-dir >/dev/null 2>&1 &&
+                       GIT_DIR="$sm_path/.git" git rev-parse --git-dir >/dev/null 2>&1 &&
                        printf '%s\n' "$sm_path"
                done
        )
@@ -898,11 +897,11 @@ cmd_summary() {
                missing_dst=
 
                test $mod_src = 160000 &&
-               ! GIT_DIR="$name/.git" git-rev-parse -q --verify $sha1_src^0 >/dev/null &&
+               ! GIT_DIR="$name/.git" git rev-parse -q --verify $sha1_src^0 >/dev/null &&
                missing_src=t
 
                test $mod_dst = 160000 &&
-               ! GIT_DIR="$name/.git" git-rev-parse -q --verify $sha1_dst^0 >/dev/null &&
+               ! GIT_DIR="$name/.git" git rev-parse -q --verify $sha1_dst^0 >/dev/null &&
                missing_dst=t
 
                display_name=$(git submodule--helper relative-path "$name" "$wt_prefix")
diff --git a/git.c b/git.c
index 489aab4d83a1e222c3e5f3b3bd812b4f29ecd34f..6b6d9f68e1ea010cb951501cab1fdfa82037b878 100644 (file)
--- a/git.c
+++ b/git.c
@@ -33,6 +33,16 @@ static void commit_pager_choice(void) {
        }
 }
 
+void setup_auto_pager(const char *cmd, int def)
+{
+       if (use_pager != -1 || pager_in_use())
+               return;
+       use_pager = check_pager_config(cmd);
+       if (use_pager == -1)
+               use_pager = def;
+       commit_pager_choice();
+}
+
 static int handle_options(const char ***argv, int *argc, int *envchanged)
 {
        const char **orig_argv = *argv;
@@ -283,6 +293,7 @@ static int handle_alias(int *argcp, const char ***argv)
  */
 #define NEED_WORK_TREE         (1<<3)
 #define SUPPORT_SUPER_PREFIX   (1<<4)
+#define DELAY_PAGER_CONFIG     (1<<5)
 
 struct cmd_struct {
        const char *cmd;
@@ -306,7 +317,8 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
                        prefix = setup_git_directory_gently(&nongit_ok);
                }
 
-               if (use_pager == -1 && p->option & (RUN_SETUP | RUN_SETUP_GENTLY))
+               if (use_pager == -1 && p->option & (RUN_SETUP | RUN_SETUP_GENTLY) &&
+                   !(p->option & DELAY_PAGER_CONFIG))
                        use_pager = check_pager_config(p->cmd);
                if (use_pager == -1 && p->option & USE_PAGER)
                        use_pager = 1;
@@ -454,7 +466,7 @@ static struct cmd_struct commands[] = {
        { "stripspace", cmd_stripspace },
        { "submodule--helper", cmd_submodule__helper, RUN_SETUP | SUPPORT_SUPER_PREFIX},
        { "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
-       { "tag", cmd_tag, RUN_SETUP },
+       { "tag", cmd_tag, RUN_SETUP | DELAY_PAGER_CONFIG },
        { "unpack-file", cmd_unpack_file, RUN_SETUP },
        { "unpack-objects", cmd_unpack_objects, RUN_SETUP },
        { "update-index", cmd_update_index, RUN_SETUP },
@@ -547,7 +559,7 @@ static void execv_dashed_external(const char **argv)
        if (get_super_prefix())
                die("%s doesn't support --super-prefix", argv[0]);
 
-       if (use_pager == -1)
+       if (use_pager == -1 && !is_builtin(argv[0]))
                use_pager = check_pager_config(argv[0]);
        commit_pager_choice();
 
diff --git a/grep.c b/grep.c
index 2efec0e182d5c20fb77903fc61dedd09a8ee7ba3..c9e7cc735681ed4c670abd7f319336204391173b 100644 (file)
--- a/grep.c
+++ b/grep.c
@@ -1821,7 +1821,7 @@ static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int colle
                return 0;
 
        if (opt->status_only)
-               return 0;
+               return opt->unmatch_name_only;
        if (opt->unmatch_name_only) {
                /* We did not see any hit, so we want to show this */
                show_name(opt, gs->name);
index c91f40a610541d6201edf2a2c95b8fef203f3c2f..df969609beed88439845d9324b2fed15ff32b109 100644 (file)
@@ -1017,7 +1017,7 @@ static int get_oid_hex_from_objpath(const char *path, struct object_id *oid)
        memcpy(hex, path, 2);
        path += 2;
        path++; /* skip '/' */
-       memcpy(hex, path, GIT_SHA1_HEXSZ - 2);
+       memcpy(hex + 2, path, GIT_SHA1_HEXSZ - 2);
 
        return get_oid_hex(hex, oid);
 }
index bd574cb75210334b1a4628f182743b49bd389cd7..70187e3eb30b102c7038a1d1c4e0033d856c99ac 100644 (file)
@@ -368,11 +368,16 @@ static struct strbuf *decode_q_segment(const struct strbuf *q_seg, int rfc2047)
 
        while ((c = *in++) != 0) {
                if (c == '=') {
-                       int d = *in++;
+                       int ch, d = *in;
                        if (d == '\n' || !d)
                                break; /* drop trailing newline */
-                       strbuf_addch(out, (hexval(d) << 4) | hexval(*in++));
-                       continue;
+                       ch = hex2chr(in);
+                       if (ch >= 0) {
+                               strbuf_addch(out, ch);
+                               in += 2;
+                               continue;
+                       }
+                       /* garbage -- fall through */
                }
                if (rfc2047 && c == '_') /* rfc2047 4.2 (2) */
                        c = 0x20;
diff --git a/path.c b/path.c
index e50d2befcf826680c70ac59295c06004dd6221cf..335d4dd8777bccfe84415f8d8b738a9a844e248d 100644 (file)
--- a/path.c
+++ b/path.c
@@ -33,11 +33,10 @@ static struct strbuf *get_pathname(void)
        return sb;
 }
 
-static char *cleanup_path(char *path)
+static const char *cleanup_path(const char *path)
 {
        /* Clean it up */
-       if (!memcmp(path, "./", 2)) {
-               path += 2;
+       if (skip_prefix(path, "./", &path)) {
                while (*path == '/')
                        path++;
        }
@@ -46,7 +45,7 @@ static char *cleanup_path(char *path)
 
 static void strbuf_cleanup_path(struct strbuf *sb)
 {
-       char *path = cleanup_path(sb->buf);
+       const char *path = cleanup_path(sb->buf);
        if (path > sb->buf)
                strbuf_remove(sb, 0, path - sb->buf);
 }
@@ -63,7 +62,7 @@ char *mksnpath(char *buf, size_t n, const char *fmt, ...)
                strlcpy(buf, bad_path, n);
                return buf;
        }
-       return cleanup_path(buf);
+       return (char *)cleanup_path(buf);
 }
 
 static int dir_prefix(const char *buf, const char *dir)
@@ -636,8 +635,9 @@ void strbuf_git_common_path(struct strbuf *sb,
 int validate_headref(const char *path)
 {
        struct stat st;
-       char *buf, buffer[256];
-       unsigned char sha1[20];
+       char buffer[256];
+       const char *refname;
+       struct object_id oid;
        int fd;
        ssize_t len;
 
@@ -661,24 +661,24 @@ int validate_headref(const char *path)
        len = read_in_full(fd, buffer, sizeof(buffer)-1);
        close(fd);
 
+       if (len < 0)
+               return -1;
+       buffer[len] = '\0';
+
        /*
         * Is it a symbolic ref?
         */
-       if (len < 4)
-               return -1;
-       if (!memcmp("ref:", buffer, 4)) {
-               buf = buffer + 4;
-               len -= 4;
-               while (len && isspace(*buf))
-                       buf++, len--;
-               if (len >= 5 && !memcmp("refs/", buf, 5))
+       if (skip_prefix(buffer, "ref:", &refname)) {
+               while (isspace(*refname))
+                       refname++;
+               if (starts_with(refname, "refs/"))
                        return 0;
        }
 
        /*
         * Is this a detached HEAD?
         */
-       if (!get_sha1_hex(buffer, sha1))
+       if (!get_oid_hex(buffer, &oid))
                return 0;
 
        return -1;
index f4b56e6d4d38cbc4365ecfc9073f5caf3a05377a..ffa09ace924e0a7b079d039e905363435b08cf9b 100644 (file)
@@ -532,7 +532,7 @@ sub version {
 =cut
 
 sub get_tz_offset {
-       # some systmes don't handle or mishandle %z, so be creative.
+       # some systems don't handle or mishandle %z, so be creative.
        my $t = shift || time;
        my $gm = timegm(localtime($t));
        my $sign = qw( + + - )[ $gm <=> $t ];
index 98518f4ddb4c031417e313dcf4daaa68e9955be0..bc4eed3d75461444f8af0e27e2930ccb25663312 100644 (file)
@@ -1416,7 +1416,7 @@ sub parse_svn_date {
                        delete $ENV{TZ};
                }
 
-               my $our_TZ = get_tz_offset();
+               my $our_TZ = get_tz_offset($epoch_in_UTC);
 
                # This converts $epoch_in_UTC into our local timezone.
                my ($sec, $min, $hour, $mday, $mon, $year,
index 7db9119573abe2c8308bd37c670c027c07b425c8..f364944b931a756b3b4819fb49ff5e9e01daf676 100644 (file)
@@ -136,9 +136,10 @@ static void format_packet(struct strbuf *out, const char *fmt, va_list args)
 static int packet_write_fmt_1(int fd, int gently,
                              const char *fmt, va_list args)
 {
-       struct strbuf buf = STRBUF_INIT;
+       static struct strbuf buf = STRBUF_INIT;
        ssize_t count;
 
+       strbuf_reset(&buf);
        format_packet(&buf, fmt, args);
        count = write_in_full(fd, buf.buf, buf.len);
        if (count == buf.len)
index bc591f4f3de0c07b0cfe3813d5d9daaf1ad44b63..f3e53d4448f10ca1002e546890ca682c02ecc9ad 100644 (file)
@@ -415,8 +415,16 @@ static int parse_ref_filter_atom(const struct ref_format *format,
        REALLOC_ARRAY(used_atom, used_atom_cnt);
        used_atom[at].name = xmemdupz(atom, ep - atom);
        used_atom[at].type = valid_atom[i].cmp_type;
-       if (arg)
+       if (arg) {
                arg = used_atom[at].name + (arg - atom) + 1;
+               if (!*arg) {
+                       /*
+                        * Treat empty sub-arguments list as NULL (i.e.,
+                        * "%(atom:)" is equivalent to "%(atom)").
+                        */
+                       arg = NULL;
+               }
+       }
        memset(&used_atom[at].u, 0, sizeof(used_atom[at].u));
        if (valid_atom[i].parser)
                valid_atom[i].parser(format, &used_atom[at], arg);
diff --git a/refs.c b/refs.c
index ea2b9f84f8d3fab5452105f10f4492d672cd1d90..41aec6505d1309fa2efed2bd9aca0a0ef2646444 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -921,6 +921,8 @@ int ref_transaction_update(struct ref_transaction *transaction,
                return -1;
        }
 
+       flags &= REF_TRANSACTION_UPDATE_ALLOWED_FLAGS;
+
        flags |= (new_sha1 ? REF_HAVE_NEW : 0) | (old_sha1 ? REF_HAVE_OLD : 0);
 
        ref_transaction_add_update(transaction, refname, flags,
diff --git a/refs.h b/refs.h
index 6daa78eb50ddc195c6d5bfb568d0b05ab08f7923..4d75c207e18bd6504a5613a373adf9dd8c745034 100644 (file)
--- a/refs.h
+++ b/refs.h
@@ -354,6 +354,14 @@ int refs_pack_refs(struct ref_store *refs, unsigned int flags);
 #define REF_NODEREF    0x01
 #define REF_FORCE_CREATE_REFLOG 0x40
 
+/*
+ * Flags that can be passed in to ref_transaction_update
+ */
+#define REF_TRANSACTION_UPDATE_ALLOWED_FLAGS \
+       REF_ISPRUNING |                      \
+       REF_FORCE_CREATE_REFLOG |            \
+       REF_NODEREF
+
 /*
  * Setup reflog before using. Fill in err and return -1 on failure.
  */
index 2631b013a52980f1c338ba1cd539da50784475f4..f032ab2e5c5c73c691338cdaf99d5b3b3d16b674 100644 (file)
@@ -1166,6 +1166,7 @@ static void init_all_refs_cb(struct all_refs_cb *cb, struct rev_info *revs,
 {
        cb->all_revs = revs;
        cb->all_flags = flags;
+       revs->rev_input_given = 1;
 }
 
 void clear_ref_exclusion(struct string_list **ref_excludes_p)
@@ -2313,7 +2314,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
                opt->tweak(revs, opt);
        if (revs->show_merge)
                prepare_show_merge(revs);
-       if (revs->def && !revs->pending.nr && !got_rev_arg) {
+       if (revs->def && !revs->pending.nr && !revs->rev_input_given && !got_rev_arg) {
                struct object_id oid;
                struct object *object;
                struct object_context oc;
index f96e7f7f49debccac9f85e7c4f0fc06c0be16ca8..bc18487d6fff5e86dff60748c084995a77d2b588 100644 (file)
@@ -71,6 +71,13 @@ struct rev_info {
        const char *def;
        struct pathspec prune_data;
 
+       /*
+        * Whether the arguments parsed by setup_revisions() included any
+        * "input" revisions that might still have yielded an empty pending
+        * list (e.g., patterns like "--all" or "--glob").
+        */
+       int rev_input_given;
+
        /* topo-sort */
        enum rev_sort_order sort_order;
 
index b5e6eb37c0eb3d6ed0cbd4fc35e879bf9fbd3db6..014b2165b5a2f92ff18869effafd4c6df01b33eb 100644 (file)
@@ -452,7 +452,7 @@ static char **prep_childenv(const char *const *deltaenv)
        }
 
        /* Create an array of 'char *' to be used as the childenv */
-       childenv = xmalloc((env.nr + 1) * sizeof(char *));
+       ALLOC_ARRAY(childenv, env.nr + 1);
        for (i = 0; i < env.nr; i++)
                childenv[i] = env.items[i].util;
        childenv[env.nr] = NULL;
index 3010faf86398697469e903318a35421d911acb23..e0e66b987b27072da4aea6304a565ab708be91e4 100644 (file)
@@ -127,6 +127,7 @@ static GIT_PATH_FUNC(rebase_path_onto, "rebase-merge/onto")
 static GIT_PATH_FUNC(rebase_path_autostash, "rebase-merge/autostash")
 static GIT_PATH_FUNC(rebase_path_strategy, "rebase-merge/strategy")
 static GIT_PATH_FUNC(rebase_path_strategy_opts, "rebase-merge/strategy_opts")
+static GIT_PATH_FUNC(rebase_path_allow_rerere_autoupdate, "rebase-merge/allow_rerere_autoupdate")
 
 static inline int is_rebase_i(const struct replay_opts *opts)
 {
@@ -1438,7 +1439,11 @@ static int populate_opts_cb(const char *key, const char *value, void *data)
        else if (!strcmp(key, "options.strategy-option")) {
                ALLOC_GROW(opts->xopts, opts->xopts_nr + 1, opts->xopts_alloc);
                opts->xopts[opts->xopts_nr++] = xstrdup(value);
-       } else
+       } else if (!strcmp(key, "options.allow-rerere-auto"))
+               opts->allow_rerere_auto =
+                       git_config_bool_or_int(key, value, &error_flag) ?
+                               RERERE_AUTOUPDATE : RERERE_NOAUTOUPDATE;
+       else
                return error(_("invalid key: %s"), key);
 
        if (!error_flag)
@@ -1479,6 +1484,15 @@ static int read_populate_opts(struct replay_opts *opts)
                                free(opts->gpg_sign);
                                opts->gpg_sign = xstrdup(buf.buf + 2);
                        }
+                       strbuf_reset(&buf);
+               }
+
+               if (read_oneliner(&buf, rebase_path_allow_rerere_autoupdate(), 1)) {
+                       if (!strcmp(buf.buf, "--rerere-autoupdate"))
+                               opts->allow_rerere_auto = RERERE_AUTOUPDATE;
+                       else if (!strcmp(buf.buf, "--no-rerere-autoupdate"))
+                               opts->allow_rerere_auto = RERERE_NOAUTOUPDATE;
+                       strbuf_reset(&buf);
                }
 
                if (file_exists(rebase_path_verbose()))
@@ -1742,6 +1756,10 @@ static int save_opts(struct replay_opts *opts)
                                                        "options.strategy-option",
                                                        opts->xopts[i], "^$", 0);
        }
+       if (opts->allow_rerere_auto)
+               res |= git_config_set_in_file_gently(opts_file, "options.allow-rerere-auto",
+                                                    opts->allow_rerere_auto == RERERE_AUTOUPDATE ?
+                                                    "true" : "false");
        return res;
 }
 
index 5f069214d9060da8ceb001e6c037607c1d0096bf..2552b7902c70154282eb278ffed7e21b2d618514 100644 (file)
@@ -99,219 +99,3 @@ int sha1_pos(const unsigned char *sha1, void *table, size_t nr,
        } while (lo < hi);
        return -lo-1;
 }
-
-/*
- * Conventional binary search loop looks like this:
- *
- *     unsigned lo, hi;
- *      do {
- *              unsigned mi = (lo + hi) / 2;
- *              int cmp = "entry pointed at by mi" minus "target";
- *              if (!cmp)
- *                      return (mi is the wanted one)
- *              if (cmp > 0)
- *                      hi = mi; "mi is larger than target"
- *              else
- *                      lo = mi+1; "mi is smaller than target"
- *      } while (lo < hi);
- *
- * The invariants are:
- *
- * - When entering the loop, lo points at a slot that is never
- *   above the target (it could be at the target), hi points at a
- *   slot that is guaranteed to be above the target (it can never
- *   be at the target).
- *
- * - We find a point 'mi' between lo and hi (mi could be the same
- *   as lo, but never can be as same as hi), and check if it hits
- *   the target.  There are three cases:
- *
- *    - if it is a hit, we are happy.
- *
- *    - if it is strictly higher than the target, we set it to hi,
- *      and repeat the search.
- *
- *    - if it is strictly lower than the target, we update lo to
- *      one slot after it, because we allow lo to be at the target.
- *
- *   If the loop exits, there is no matching entry.
- *
- * When choosing 'mi', we do not have to take the "middle" but
- * anywhere in between lo and hi, as long as lo <= mi < hi is
- * satisfied.  When we somehow know that the distance between the
- * target and lo is much shorter than the target and hi, we could
- * pick mi that is much closer to lo than the midway.
- *
- * Now, we can take advantage of the fact that SHA-1 is a good hash
- * function, and as long as there are enough entries in the table, we
- * can expect uniform distribution.  An entry that begins with for
- * example "deadbeef..." is much likely to appear much later than in
- * the midway of the table.  It can reasonably be expected to be near
- * 87% (222/256) from the top of the table.
- *
- * However, we do not want to pick "mi" too precisely.  If the entry at
- * the 87% in the above example turns out to be higher than the target
- * we are looking for, we would end up narrowing the search space down
- * only by 13%, instead of 50% we would get if we did a simple binary
- * search.  So we would want to hedge our bets by being less aggressive.
- *
- * The table at "table" holds at least "nr" entries of "elem_size"
- * bytes each.  Each entry has the SHA-1 key at "key_offset".  The
- * table is sorted by the SHA-1 key of the entries.  The caller wants
- * to find the entry with "key", and knows that the entry at "lo" is
- * not higher than the entry it is looking for, and that the entry at
- * "hi" is higher than the entry it is looking for.
- */
-int sha1_entry_pos(const void *table,
-                  size_t elem_size,
-                  size_t key_offset,
-                  unsigned lo, unsigned hi, unsigned nr,
-                  const unsigned char *key)
-{
-       const unsigned char *base = table;
-       const unsigned char *hi_key, *lo_key;
-       unsigned ofs_0;
-       static int debug_lookup = -1;
-
-       if (debug_lookup < 0)
-               debug_lookup = !!getenv("GIT_DEBUG_LOOKUP");
-
-       if (!nr || lo >= hi)
-               return -1;
-
-       if (nr == hi)
-               hi_key = NULL;
-       else
-               hi_key = base + elem_size * hi + key_offset;
-       lo_key = base + elem_size * lo + key_offset;
-
-       ofs_0 = 0;
-       do {
-               int cmp;
-               unsigned ofs, mi, range;
-               unsigned lov, hiv, kyv;
-               const unsigned char *mi_key;
-
-               range = hi - lo;
-               if (hi_key) {
-                       for (ofs = ofs_0; ofs < 20; ofs++)
-                               if (lo_key[ofs] != hi_key[ofs])
-                                       break;
-                       ofs_0 = ofs;
-                       /*
-                        * byte 0 thru (ofs-1) are the same between
-                        * lo and hi; ofs is the first byte that is
-                        * different.
-                        *
-                        * If ofs==20, then no bytes are different,
-                        * meaning we have entries with duplicate
-                        * keys. We know that we are in a solid run
-                        * of this entry (because the entries are
-                        * sorted, and our lo and hi are the same,
-                        * there can be nothing but this single key
-                        * in between). So we can stop the search.
-                        * Either one of these entries is it (and
-                        * we do not care which), or we do not have
-                        * it.
-                        *
-                        * Furthermore, we know that one of our
-                        * endpoints must be the edge of the run of
-                        * duplicates. For example, given this
-                        * sequence:
-                        *
-                        *     idx 0 1 2 3 4 5
-                        *     key A C C C C D
-                        *
-                        * If we are searching for "B", we might
-                        * hit the duplicate run at lo=1, hi=3
-                        * (e.g., by first mi=3, then mi=0). But we
-                        * can never have lo > 1, because B < C.
-                        * That is, if our key is less than the
-                        * run, we know that "lo" is the edge, but
-                        * we can say nothing of "hi". Similarly,
-                        * if our key is greater than the run, we
-                        * know that "hi" is the edge, but we can
-                        * say nothing of "lo".
-                        *
-                        * Therefore if we do not find it, we also
-                        * know where it would go if it did exist:
-                        * just on the far side of the edge that we
-                        * know about.
-                        */
-                       if (ofs == 20) {
-                               mi = lo;
-                               mi_key = base + elem_size * mi + key_offset;
-                               cmp = memcmp(mi_key, key, 20);
-                               if (!cmp)
-                                       return mi;
-                               if (cmp < 0)
-                                       return -1 - hi;
-                               else
-                                       return -1 - lo;
-                       }
-
-                       hiv = hi_key[ofs_0];
-                       if (ofs_0 < 19)
-                               hiv = (hiv << 8) | hi_key[ofs_0+1];
-               } else {
-                       hiv = 256;
-                       if (ofs_0 < 19)
-                               hiv <<= 8;
-               }
-               lov = lo_key[ofs_0];
-               kyv = key[ofs_0];
-               if (ofs_0 < 19) {
-                       lov = (lov << 8) | lo_key[ofs_0+1];
-                       kyv = (kyv << 8) | key[ofs_0+1];
-               }
-               assert(lov < hiv);
-
-               if (kyv < lov)
-                       return -1 - lo;
-               if (hiv < kyv)
-                       return -1 - hi;
-
-               /*
-                * Even if we know the target is much closer to 'hi'
-                * than 'lo', if we pick too precisely and overshoot
-                * (e.g. when we know 'mi' is closer to 'hi' than to
-                * 'lo', pick 'mi' that is higher than the target), we
-                * end up narrowing the search space by a smaller
-                * amount (i.e. the distance between 'mi' and 'hi')
-                * than what we would have (i.e. about half of 'lo'
-                * and 'hi').  Hedge our bets to pick 'mi' less
-                * aggressively, i.e. make 'mi' a bit closer to the
-                * middle than we would otherwise pick.
-                */
-               kyv = (kyv * 6 + lov + hiv) / 8;
-               if (lov < hiv - 1) {
-                       if (kyv == lov)
-                               kyv++;
-                       else if (kyv == hiv)
-                               kyv--;
-               }
-               mi = (range - 1) * (kyv - lov) / (hiv - lov) + lo;
-
-               if (debug_lookup) {
-                       printf("lo %u hi %u rg %u mi %u ", lo, hi, range, mi);
-                       printf("ofs %u lov %x, hiv %x, kyv %x\n",
-                              ofs_0, lov, hiv, kyv);
-               }
-               if (!(lo <= mi && mi < hi))
-                       die("assertion failure lo %u mi %u hi %u %s",
-                           lo, mi, hi, sha1_to_hex(key));
-
-               mi_key = base + elem_size * mi + key_offset;
-               cmp = memcmp(mi_key + ofs_0, key + ofs_0, 20 - ofs_0);
-               if (!cmp)
-                       return mi;
-               if (cmp > 0) {
-                       hi = mi;
-                       hi_key = mi_key;
-               } else {
-                       lo = mi + 1;
-                       lo_key = mi_key + elem_size;
-               }
-       } while (lo < hi);
-       return -lo-1;
-}
index 20af2856818ed51b2afb1718a7e317133ee0d7bd..cf5314f402ce78f0d5ab2bd72ee7f334b6394e04 100644 (file)
@@ -7,10 +7,4 @@ extern int sha1_pos(const unsigned char *sha1,
                    void *table,
                    size_t nr,
                    sha1_access_fn fn);
-
-extern int sha1_entry_pos(const void *table,
-                         size_t elem_size,
-                         size_t key_offset,
-                         unsigned lo, unsigned hi, unsigned nr,
-                         const unsigned char *key);
 #endif
index b60ae15f7068c157df6407933ea7ee94a53f0640..5911364a81fa3d1351fa13d14a63c8854fd60e22 100644 (file)
@@ -347,6 +347,7 @@ static int alt_odb_usable(struct strbuf *path, const char *normalized_objdir)
  * SHA1, an extra slash for the first level indirection, and the
  * terminating NUL.
  */
+static void read_info_alternates(const char * relative_base, int depth);
 static int link_alt_odb_entry(const char *entry, const char *relative_base,
        int depth, const char *normalized_objdir)
 {
@@ -448,7 +449,7 @@ static void link_alt_odb_entries(const char *alt, int len, int sep,
        strbuf_release(&objdirbuf);
 }
 
-void read_info_alternates(const char * relative_base, int depth)
+static void read_info_alternates(const char * relative_base, int depth)
 {
        char *map;
        size_t mapsz;
@@ -2542,8 +2543,8 @@ void *unpack_entry(struct packed_git *p, off_t obj_offset,
                                error("bad packed object CRC for %s",
                                      sha1_to_hex(sha1));
                                mark_bad_packed_object(p, sha1);
-                               unuse_pack(&w_curs);
-                               return NULL;
+                               data = NULL;
+                               goto out;
                        }
                }
 
@@ -2681,6 +2682,7 @@ void *unpack_entry(struct packed_git *p, off_t obj_offset,
        if (final_size)
                *final_size = size;
 
+out:
        unuse_pack(&w_curs);
 
        if (delta_stack != small_delta_stack)
@@ -2759,7 +2761,6 @@ off_t find_pack_entry_one(const unsigned char *sha1,
        const uint32_t *level1_ofs = p->index_data;
        const unsigned char *index = p->index_data;
        unsigned hi, lo, stride;
-       static int use_lookup = -1;
        static int debug_lookup = -1;
 
        if (debug_lookup < 0)
@@ -2789,17 +2790,7 @@ off_t find_pack_entry_one(const unsigned char *sha1,
                printf("%02x%02x%02x... lo %u hi %u nr %"PRIu32"\n",
                       sha1[0], sha1[1], sha1[2], lo, hi, p->num_objects);
 
-       if (use_lookup < 0)
-               use_lookup = !!getenv("GIT_USE_LOOKUP");
-       if (use_lookup) {
-               int pos = sha1_entry_pos(index, stride, 0,
-                                        lo, hi, p->num_objects, sha1);
-               if (pos < 0)
-                       return 0;
-               return nth_packed_object_offset(p, pos);
-       }
-
-       do {
+       while (lo < hi) {
                unsigned mi = (lo + hi) / 2;
                int cmp = hashcmp(index + mi * stride, sha1);
 
@@ -2812,7 +2803,7 @@ off_t find_pack_entry_one(const unsigned char *sha1,
                        hi = mi;
                else
                        lo = mi+1;
-       } while (lo < hi);
+       }
        return 0;
 }
 
@@ -2961,10 +2952,14 @@ static int sha1_loose_object_info(const unsigned char *sha1,
        } else if ((status = parse_sha1_header_extended(hdr, oi, flags)) < 0)
                status = error("unable to parse %s header", sha1_to_hex(sha1));
 
-       if (status >= 0 && oi->contentp)
+       if (status >= 0 && oi->contentp) {
                *oi->contentp = unpack_sha1_rest(&stream, hdr,
                                                 *oi->sizep, sha1);
-       else
+               if (!*oi->contentp) {
+                       git_inflate_end(&stream);
+                       status = -1;
+               }
+       } else
                git_inflate_end(&stream);
 
        munmap(map, mapsize);
diff --git a/shell.c b/shell.c
index fe2d314593ba5ee3b985b778c2e7ebfdcd9da44c..234b2d4f16fe79e9260c8409bd4d7c964fe27e72 100644 (file)
--- a/shell.c
+++ b/shell.c
@@ -25,19 +25,6 @@ static int do_generic_cmd(const char *me, char *arg)
        return execv_git_cmd(my_argv);
 }
 
-static int do_cvs_cmd(const char *me, char *arg)
-{
-       const char *cvsserver_argv[3] = {
-               "cvsserver", "server", NULL
-       };
-
-       if (!arg || strcmp(arg, "server"))
-               die("git-cvsserver only handles server: %s", arg);
-
-       setup_path();
-       return execv_git_cmd(cvsserver_argv);
-}
-
 static int is_valid_cmd_name(const char *cmd)
 {
        /* Test command contains no . or / characters */
@@ -134,7 +121,6 @@ static struct commands {
        { "git-receive-pack", do_generic_cmd },
        { "git-upload-pack", do_generic_cmd },
        { "git-upload-archive", do_generic_cmd },
-       { "cvs", do_cvs_cmd },
        { NULL },
 };
 
index 89d22e3b0903a220fa958b8d912607828ab2a9ba..323c49ceb35cb053434248df869578e649ccadc0 100644 (file)
--- a/strbuf.c
+++ b/strbuf.c
@@ -476,6 +476,7 @@ int strbuf_getwholeline(struct strbuf *sb, FILE *fp, int term)
        /* Translate slopbuf to NULL, as we cannot call realloc on it */
        if (!sb->alloc)
                sb->buf = NULL;
+       errno = 0;
        r = getdelim(&sb->buf, &sb->alloc, term, fp);
 
        if (r > 0) {
index 2075384e0b2df97a6d113acebcbcdcc853237166..80112a8c264a02caf0ffd813557969249ddf25ac 100644 (file)
--- a/strbuf.h
+++ b/strbuf.h
@@ -82,8 +82,12 @@ extern char strbuf_slopbuf[];
 extern void strbuf_init(struct strbuf *, size_t);
 
 /**
- * Release a string buffer and the memory it used. You should not use the
- * string buffer after using this function, unless you initialize it again.
+ * Release a string buffer and the memory it used. After this call, the
+ * strbuf points to an empty string that does not need to be free()ed, as
+ * if it had been set to `STRBUF_INIT` and never modified.
+ *
+ * To clear a strbuf in preparation for further use without the overhead
+ * of free()ing and malloc()ing again, use strbuf_reset() instead.
  */
 extern void strbuf_release(struct strbuf *);
 
@@ -91,6 +95,9 @@ extern void strbuf_release(struct strbuf *);
  * Detach the string from the strbuf and returns it; you now own the
  * storage the string occupies and it is your responsibility from then on
  * to release it with `free(3)` when you are done with it.
+ *
+ * The strbuf that previously held the string is reset to `STRBUF_INIT` so
+ * it can be reused after calling this function.
  */
 extern char *strbuf_detach(struct strbuf *, size_t *);
 
index 29bfb7ae45931686e14c91b1a47a703e7b32fe52..79ae567cbc3bfbd7574b8156aa9fcf56581cad83 100644 (file)
@@ -32,8 +32,10 @@ void string_list_clear_func(struct string_list *list, string_list_clear_func_t c
 typedef int (*string_list_each_func_t)(struct string_list_item *, void *);
 int for_each_string_list(struct string_list *list,
                         string_list_each_func_t, void *cb_data);
-#define for_each_string_list_item(item,list) \
-       for (item = (list)->items; item < (list)->items + (list)->nr; ++item)
+#define for_each_string_list_item(item,list)            \
+       for (item = (list)->items;                      \
+            item && item < (list)->items + (list)->nr; \
+            ++item)
 
 /*
  * Apply want to each item in list, retaining only the ones for which
index 86de8d7bfbcd781b50571f867f0669c84093eca3..80571567f2a64be451fe2ac92c230f66fa04c844 100644 (file)
@@ -74,13 +74,12 @@ int subprocess_start(struct hashmap *hashmap, struct subprocess_entry *entry, co
 {
        int err;
        struct child_process *process;
-       const char *argv[] = { cmd, NULL };
 
        entry->cmd = cmd;
        process = &entry->process;
 
        child_process_init(process);
-       process->argv = argv;
+       argv_array_push(&process->args, cmd);
        process->use_shell = 1;
        process->in = -1;
        process->out = -1;
@@ -181,8 +180,8 @@ static int handshake_capabilities(struct child_process *process,
                        if (supported_capabilities)
                                *supported_capabilities |= capabilities[i].flag;
                } else {
-                       warning("external filter requested unsupported filter capability '%s'",
-                               p);
+                       die("subprocess '%s' requested unsupported capability '%s'",
+                           process->argv[0], p);
                }
        }
 
index 6531c5d6094e47b251e69ce741699abfee7a64df..36f45f5a5a2adedd7e598371f98f6a54880668df 100644 (file)
@@ -1015,7 +1015,8 @@ static int push_submodule(const char *path,
  * Perform a check in the submodule to see if the remote and refspec work.
  * Die if the submodule can't be pushed.
  */
-static void submodule_push_check(const char *path, const struct remote *remote,
+static void submodule_push_check(const char *path, const char *head,
+                                const struct remote *remote,
                                 const char **refspec, int refspec_nr)
 {
        struct child_process cp = CHILD_PROCESS_INIT;
@@ -1023,6 +1024,7 @@ static void submodule_push_check(const char *path, const struct remote *remote,
 
        argv_array_push(&cp.args, "submodule--helper");
        argv_array_push(&cp.args, "push-check");
+       argv_array_push(&cp.args, head);
        argv_array_push(&cp.args, remote->name);
 
        for (i = 0; i < refspec_nr; i++)
@@ -1061,10 +1063,20 @@ int push_unpushed_submodules(struct oid_array *commits,
         * won't be propagated due to the remote being unconfigured (e.g. a URL
         * instead of a remote name).
         */
-       if (remote->origin != REMOTE_UNCONFIGURED)
+       if (remote->origin != REMOTE_UNCONFIGURED) {
+               char *head;
+               struct object_id head_oid;
+
+               head = resolve_refdup("HEAD", 0, head_oid.hash, NULL);
+               if (!head)
+                       die(_("Failed to resolve HEAD as a valid ref."));
+
                for (i = 0; i < needs_pushing.nr; i++)
                        submodule_push_check(needs_pushing.items[i].string,
-                                            remote, refspec, refspec_nr);
+                                            head, remote,
+                                            refspec, refspec_nr);
+               free(head);
+       }
 
        /* Actually push the submodules */
        for (i = 0; i < needs_pushing.nr; i++) {
index e85b1448638ac7255a48a1bc1e2d6409c3a85ba6..3c239d1ecf445abbec9528bdf27b92aaaa5ec52e 100644 (file)
@@ -129,7 +129,7 @@ extern int submodule_move_head(const char *path,
 
 /*
  * Prepare the "env_array" parameter of a "struct child_process" for executing
- * a submodule by clearing any repo-specific envirionment variables, but
+ * a submodule by clearing any repo-specific environment variables, but
  * retaining any config in the environment.
  */
 extern void prepare_submodule_repo_env(struct argv_array *out);
index 2f958603697515f40520a7ff9df31de13eefc2d7..4b079e4494d9324f0b03dfe8f714b3717292c0b6 100644 (file)
--- a/t/README
+++ b/t/README
@@ -265,12 +265,12 @@ or:
 
     $ sh ./t9200-git-cvsexport-commit.sh --run='-3 21'
 
-As noted above, the test set is built going though items left to
-right, so this:
+As noted above, the test set is built by going through the items
+from left to right, so this:
 
     $ sh ./t9200-git-cvsexport-commit.sh --run='1-4 !3'
 
-will run tests 1, 2, and 4.  Items that comes later have higher
+will run tests 1, 2, and 4.  Items that come later have higher
 precedence.  It means that this:
 
     $ sh ./t9200-git-cvsexport-commit.sh --run='!3 1-4'
index b170cbc0452ca1b5a624f5cf330d420c397cb760..03dc9d28525730cdf57c74d13cab22da59dcdfbd 100755 (executable)
@@ -17,7 +17,7 @@ sub err {
 while (<>) {
        chomp;
        /\bsed\s+-i/ and err 'sed -i is not portable';
-       /\becho\s+-n/ and err 'echo -n is not portable (please use printf)';
+       /\becho\s+-[neE]/ and err 'echo with option is not portable (please use printf)';
        /^\s*declare\s+/ and err 'arrays/declare not portable';
        /^\s*[^#]\s*which\s/ and err 'which is not portable (please use type)';
        /\btest\s+[^=]*==/ and err '"test a == b" is not portable (please use =)';
index 1ebe0f750c648cd4d92983c11ace9e8a86327dd1..2b3c5092a199835ea2e84339b473a9e29778178d 100644 (file)
@@ -38,6 +38,20 @@ struct test_data {
        const char *alternative; /* output: ... or this.      */
 };
 
+/*
+ * Compatibility wrappers for OpenBSD, whose basename(3) and dirname(3)
+ * have const parameters.
+ */
+static char *posix_basename(char *path)
+{
+       return basename(path);
+}
+
+static char *posix_dirname(char *path)
+{
+       return dirname(path);
+}
+
 static int test_function(struct test_data *data, char *(*func)(char *input),
        const char *funcname)
 {
@@ -251,10 +265,10 @@ int cmd_main(int argc, const char **argv)
        }
 
        if (argc == 2 && !strcmp(argv[1], "basename"))
-               return test_function(basename_data, basename, argv[1]);
+               return test_function(basename_data, posix_basename, argv[1]);
 
        if (argc == 2 && !strcmp(argv[1], "dirname"))
-               return test_function(dirname_data, dirname, argv[1]);
+               return test_function(dirname_data, posix_dirname, argv[1]);
 
        fprintf(stderr, "%s: unknown function name: %s\n", argv[0],
                argv[1] ? argv[1] : "(there was none)");
index c502fa16d307957b6fe23cbd5481fc35f49c00da..829ec3d7d2f58b9538bb3bbab47213eddb9e62ec 100644 (file)
@@ -108,7 +108,7 @@ int cmd_main(int argc, const char **argv)
                 * Split by newline, but don't create a string_list item
                 * for the empty string after the last separator.
                 */
-               if (sb.buf[sb.len - 1] == '\n')
+               if (sb.len && sb.buf[sb.len - 1] == '\n')
                        strbuf_setlen(&sb, sb.len - 1);
                string_list_split_in_place(&list, sb.buf, '\n', -1);
 
index ec2aa8f6879d68078caeccaff25d89178b9fb902..43679a4c640e874aed8d3a378a378b1a6080fc1c 100755 (executable)
@@ -31,6 +31,7 @@ then
                chmod 0700 ./gpghome &&
                GNUPGHOME="$(pwd)/gpghome" &&
                export GNUPGHOME &&
+               (gpgconf --kill gpg-agent 2>&1 >/dev/null || : ) &&
                gpg --homedir "${GNUPGHOME}" 2>/dev/null --import \
                        "$TEST_DIRECTORY"/lib-gpg/keyring.gpg &&
                gpg --homedir "${GNUPGHOME}" 2>/dev/null --import-ownertrust \
index c4814d248fc96e7dc0177b6987baa18853c6213c..86c1a51654fa6c1b049a313fe8d880c6a266ee62 100755 (executable)
@@ -315,18 +315,44 @@ test_expect_success 'init with separate gitdir' '
        test_path_is_dir realgitdir/refs
 '
 
-test_expect_success 'init in long base path' '
+test_lazy_prereq GETCWD_IGNORES_PERMS '
+       base=GETCWD_TEST_BASE_DIR &&
+       mkdir -p $base/dir &&
+       chmod 100 $base ||
+       error "bug in test script: cannot prepare $base"
+
+       (cd $base/dir && /bin/pwd -P)
+       status=$?
+
+       chmod 700 $base &&
+       rm -rf $base ||
+       error "bug in test script: cannot clean $base"
+       return $status
+'
+
+check_long_base_path () {
        # exceed initial buffer size of strbuf_getcwd()
        component=123456789abcdef &&
        test_when_finished "chmod 0700 $component; rm -rf $component" &&
        p31=$component/$component &&
        p127=$p31/$p31/$p31/$p31 &&
        mkdir -p $p127 &&
-       chmod 0111 $component &&
+       if test $# = 1
+       then
+               chmod $1 $component
+       fi &&
        (
                cd $p127 &&
                git init newdir
        )
+}
+
+test_expect_success 'init in long base path' '
+       check_long_base_path
+'
+
+test_expect_success GETCWD_IGNORES_PERMS 'init in long restricted base path' '
+       check_long_base_path 0111
 '
 
 test_expect_success 're-init on .git file' '
index e3bf821694553354a0be2e93b71038bddb1d689d..7ca2e65d102afd76dc4136a9f12c53a5ba0fce25 100755 (executable)
@@ -51,7 +51,9 @@ test_expect_success \
      treeM=$(git write-tree) &&
      echo treeM $treeM &&
      git ls-tree $treeM &&
-     sum bozbar frotz nitfol >M.sum &&
+     cp bozbar bozbar.M &&
+     cp frotz frotz.M &&
+     cp nitfol nitfol.M &&
      git diff-tree $treeH $treeM'
 
 test_expect_success \
@@ -61,8 +63,9 @@ test_expect_success \
      read_tree_u_must_succeed -m -u $treeH $treeM &&
      git ls-files --stage >1-3.out &&
      cmp M.out 1-3.out &&
-     sum bozbar frotz nitfol >actual3.sum &&
-     cmp M.sum actual3.sum &&
+     test_cmp bozbar.M bozbar &&
+     test_cmp frotz.M frotz &&
+     test_cmp nitfol.M nitfol &&
      check_cache_at bozbar clean &&
      check_cache_at frotz clean &&
      check_cache_at nitfol clean'
@@ -79,8 +82,9 @@ test_expect_success \
      test_might_fail git diff -U0 --no-index M.out 4.out >4diff.out &&
      compare_change 4diff.out expected &&
      check_cache_at yomin clean &&
-     sum bozbar frotz nitfol >actual4.sum &&
-     cmp M.sum actual4.sum &&
+     test_cmp bozbar.M bozbar &&
+     test_cmp frotz.M frotz &&
+     test_cmp nitfol.M nitfol &&
      echo yomin >yomin1 &&
      diff yomin yomin1 &&
      rm -f yomin1'
@@ -98,8 +102,9 @@ test_expect_success \
      test_might_fail git diff -U0 --no-index M.out 5.out >5diff.out &&
      compare_change 5diff.out expected &&
      check_cache_at yomin dirty &&
-     sum bozbar frotz nitfol >actual5.sum &&
-     cmp M.sum actual5.sum &&
+     test_cmp bozbar.M bozbar &&
+     test_cmp frotz.M frotz &&
+     test_cmp nitfol.M nitfol &&
      : dirty index should have prevented -u from checking it out. &&
      echo yomin yomin >yomin1 &&
      diff yomin yomin1 &&
@@ -115,8 +120,9 @@ test_expect_success \
      git ls-files --stage >6.out &&
      test_cmp M.out 6.out &&
      check_cache_at frotz clean &&
-     sum bozbar frotz nitfol >actual3.sum &&
-     cmp M.sum actual3.sum &&
+     test_cmp bozbar.M bozbar &&
+     test_cmp frotz.M frotz &&
+     test_cmp nitfol.M nitfol &&
      echo frotz >frotz1 &&
      diff frotz frotz1 &&
      rm -f frotz1'
@@ -132,8 +138,8 @@ test_expect_success \
      git ls-files --stage >7.out &&
      test_cmp M.out 7.out &&
      check_cache_at frotz dirty &&
-     sum bozbar frotz nitfol >actual7.sum &&
-     if cmp M.sum actual7.sum; then false; else :; fi &&
+     test_cmp bozbar.M bozbar &&
+     test_cmp nitfol.M nitfol &&
      : dirty index should have prevented -u from checking it out. &&
      echo frotz frotz >frotz1 &&
      diff frotz frotz1 &&
@@ -165,8 +171,10 @@ test_expect_success \
      read_tree_u_must_succeed -m -u $treeH $treeM &&
      git ls-files --stage >10.out &&
      cmp M.out 10.out &&
-     sum bozbar frotz nitfol >actual10.sum &&
-     cmp M.sum actual10.sum'
+     test_cmp bozbar.M bozbar &&
+     test_cmp frotz.M frotz &&
+     test_cmp nitfol.M nitfol
+'
 
 test_expect_success \
     '11 - dirty path removed.' \
@@ -209,11 +217,8 @@ test_expect_success \
      git ls-files --stage >14.out &&
      test_must_fail git diff -U0 --no-index M.out 14.out >14diff.out &&
      compare_change 14diff.out expected &&
-     sum bozbar frotz >actual14.sum &&
-     grep -v nitfol M.sum > expected14.sum &&
-     cmp expected14.sum actual14.sum &&
-     sum bozbar frotz nitfol >actual14a.sum &&
-     if cmp M.sum actual14a.sum; then false; else :; fi &&
+     test_cmp bozbar.M bozbar &&
+     test_cmp frotz.M frotz &&
      check_cache_at nitfol clean &&
      echo nitfol nitfol >nitfol1 &&
      diff nitfol nitfol1 &&
@@ -231,11 +236,8 @@ test_expect_success \
      test_must_fail git diff -U0 --no-index M.out 15.out >15diff.out &&
      compare_change 15diff.out expected &&
      check_cache_at nitfol dirty &&
-     sum bozbar frotz >actual15.sum &&
-     grep -v nitfol M.sum > expected15.sum &&
-     cmp expected15.sum actual15.sum &&
-     sum bozbar frotz nitfol >actual15a.sum &&
-     if cmp M.sum actual15a.sum; then false; else :; fi &&
+     test_cmp bozbar.M bozbar &&
+     test_cmp frotz.M frotz &&
      echo nitfol nitfol nitfol >nitfol1 &&
      diff nitfol nitfol1 &&
      rm -f nitfol1'
@@ -267,8 +269,10 @@ test_expect_success \
      git ls-files --stage >18.out &&
      test_cmp M.out 18.out &&
      check_cache_at bozbar clean &&
-     sum bozbar frotz nitfol >actual18.sum &&
-     cmp M.sum actual18.sum'
+     test_cmp bozbar.M bozbar &&
+     test_cmp frotz.M frotz &&
+     test_cmp nitfol.M nitfol
+'
 
 test_expect_success \
     '19 - local change already having a good result, further modified.' \
@@ -281,11 +285,8 @@ test_expect_success \
      git ls-files --stage >19.out &&
      test_cmp M.out 19.out &&
      check_cache_at bozbar dirty &&
-     sum frotz nitfol >actual19.sum &&
-     grep -v bozbar  M.sum > expected19.sum &&
-     cmp expected19.sum actual19.sum &&
-     sum bozbar frotz nitfol >actual19a.sum &&
-     if cmp M.sum actual19a.sum; then false; else :; fi &&
+     test_cmp frotz.M frotz &&
+     test_cmp nitfol.M nitfol &&
      echo gnusto gnusto >bozbar1 &&
      diff bozbar bozbar1 &&
      rm -f bozbar1'
@@ -300,8 +301,10 @@ test_expect_success \
      git ls-files --stage >20.out &&
      test_cmp M.out 20.out &&
      check_cache_at bozbar clean &&
-     sum bozbar frotz nitfol >actual20.sum &&
-     cmp M.sum actual20.sum'
+     test_cmp bozbar.M bozbar &&
+     test_cmp frotz.M frotz &&
+     test_cmp nitfol.M nitfol
+'
 
 test_expect_success \
     '21 - no local change, dirty cache.' \
index 4087150db1b787540abc5a5f648839efbe4d78e3..cb4b66e29dd8c38c734f5d29df3e8062c78884a9 100755 (executable)
@@ -222,6 +222,28 @@ test_expect_success 'unparseable tree object' '
        test_i18ngrep ! "fatal: empty filename in tree entry" out
 '
 
+hex2oct() {
+       perl -ne 'printf "\\%03o", hex for /../g'
+}
+
+test_expect_success 'tree entry with type mismatch' '
+       test_when_finished "remove_object \$blob" &&
+       test_when_finished "remove_object \$tree" &&
+       test_when_finished "remove_object \$commit" &&
+       test_when_finished "git update-ref -d refs/heads/type_mismatch" &&
+       blob=$(echo blob | git hash-object -w --stdin) &&
+       blob_bin=$(echo $blob | hex2oct) &&
+       tree=$(
+               printf "40000 dir\0${blob_bin}100644 file\0${blob_bin}" |
+               git hash-object -t tree --stdin -w --literally
+       ) &&
+       commit=$(git commit-tree $tree) &&
+       git update-ref refs/heads/type_mismatch $commit &&
+       test_must_fail git fsck >out 2>&1 &&
+       test_i18ngrep "is a blob, not a tree" out &&
+       test_i18ngrep ! "dangling blob" out
+'
+
 test_expect_success 'tag pointing to nonexistent' '
        cat >invalid-tag <<-\EOF &&
        object ffffffffffffffffffffffffffffffffffffffff
index 9d707d2a40a457abcd85fb93d9f8195946d09d01..5fc2fb425b007c3fec736df5cf13782b8e881f58 100755 (executable)
@@ -162,6 +162,19 @@ test_expect_success 'git branch -M baz bam should add entries to .git/logs/HEAD'
        grep "^0\{40\}.*$msg$" .git/logs/HEAD
 '
 
+test_expect_success 'git branch -M should leave orphaned HEAD alone' '
+       git init orphan &&
+       (
+               cd orphan &&
+               test_commit initial &&
+               git checkout --orphan lonely &&
+               grep lonely .git/HEAD &&
+               test_path_is_missing .git/refs/head/lonely &&
+               git branch -M master mistress &&
+               grep lonely .git/HEAD
+       )
+'
+
 test_expect_success 'resulting reflog can be shown by log -g' '
        oid=$(git rev-parse HEAD) &&
        cat >expect <<-EOF &&
index d2aec0f38b7913b27687b332029dc78be59bc182..ee6787614c80edb9b5b24065277dd413350a6fc6 100755 (executable)
@@ -253,13 +253,7 @@ test_expect_success '%(color) omitted without tty' '
 '
 
 test_expect_success TTY '%(color) present with tty' '
-       test_terminal env TERM=vt100 git branch $color_args >actual.raw &&
-       test_decode_color <actual.raw >actual &&
-       test_cmp expect.color actual
-'
-
-test_expect_success 'color.branch=always overrides auto-color' '
-       git -c color.branch=always branch $color_args >actual.raw &&
+       test_terminal git branch $color_args >actual.raw &&
        test_decode_color <actual.raw >actual &&
        test_cmp expect.color actual
 '
index 9343550f50a011ff563c1455384cd1b14fd83888..4f1e16bb44e279a0c5c0fc96f95eb285e4b22c3c 100755 (executable)
@@ -12,7 +12,6 @@ test_expect_success 'set up some sample branches' '
 # choose non-default colors to make sure config
 # is taking effect
 test_expect_success 'set up some color config' '
-       git config color.branch always &&
        git config color.branch.local blue &&
        git config color.branch.remote yellow &&
        git config color.branch.current cyan
@@ -24,7 +23,7 @@ test_expect_success 'regular output shows colors' '
          <BLUE>other<RESET>
          <YELLOW>remotes/origin/master<RESET>
        EOF
-       git branch -a >actual.raw &&
+       git branch --color -a >actual.raw &&
        test_decode_color <actual.raw >actual &&
        test_cmp expect actual
 '
@@ -36,7 +35,7 @@ test_expect_success 'verbose output shows colors' '
          <BLUE>other                <RESET> $oid foo
          <YELLOW>remotes/origin/master<RESET> $oid foo
        EOF
-       git branch -v -a >actual.raw &&
+       git branch --color -v -a >actual.raw &&
        test_decode_color <actual.raw >actual &&
        test_cmp expect actual
 '
index 4428b9086e8bcb383df801834d0de323f316f4fa..fcfdd197bd352a9dca10233c2ba6d2aa4a66149e 100755 (executable)
@@ -40,25 +40,6 @@ test_expect_success 'non-interactive rebase --continue works with touched file'
        git rebase --continue
 '
 
-test_expect_success 'non-interactive rebase --continue with rerere enabled' '
-       test_config rerere.enabled true &&
-       test_when_finished "test_might_fail git rebase --abort" &&
-       git reset --hard commit-new-file-F2-on-topic-branch &&
-       git checkout master &&
-       rm -fr .git/rebase-* &&
-
-       test_must_fail git rebase --onto master master topic &&
-       echo "Resolved" >F2 &&
-       git add F2 &&
-       cp F2 F2.expected &&
-       git rebase --continue &&
-
-       git reset --hard commit-new-file-F2-on-topic-branch &&
-       git checkout master &&
-       test_must_fail git rebase --onto master master topic &&
-       test_cmp F2.expected F2
-'
-
 test_expect_success 'rebase --continue can not be used with other options' '
        test_must_fail git rebase -v --continue &&
        test_must_fail git rebase --continue -v
@@ -93,25 +74,75 @@ test_expect_success 'rebase --continue remembers merge strategy and options' '
        test -f funny.was.run
 '
 
-test_expect_success 'rebase --continue remembers --rerere-autoupdate' '
+test_expect_success 'setup rerere database' '
        rm -fr .git/rebase-* &&
        git reset --hard commit-new-file-F3-on-topic-branch &&
        git checkout master &&
        test_commit "commit-new-file-F3" F3 3 &&
-       git config rerere.enabled true &&
+       test_config rerere.enabled true &&
        test_must_fail git rebase -m master topic &&
        echo "Resolved" >F2 &&
+       cp F2 expected-F2 &&
        git add F2 &&
        test_must_fail git rebase --continue &&
        echo "Resolved" >F3 &&
+       cp F3 expected-F3 &&
        git add F3 &&
        git rebase --continue &&
-       git reset --hard topic@{1} &&
-       test_must_fail git rebase -m --rerere-autoupdate master &&
-       test "$(cat F2)" = "Resolved" &&
-       test_must_fail git rebase --continue &&
-       test "$(cat F3)" = "Resolved" &&
-       git rebase --continue
+       git reset --hard topic@{1}
 '
 
+prepare () {
+       rm -fr .git/rebase-* &&
+       git reset --hard commit-new-file-F3-on-topic-branch &&
+       git checkout master &&
+       test_config rerere.enabled true
+}
+
+test_rerere_autoupdate () {
+       action=$1 &&
+       test_expect_success "rebase $action --continue remembers --rerere-autoupdate" '
+               prepare &&
+               test_must_fail git rebase $action --rerere-autoupdate master topic &&
+               test_cmp expected-F2 F2 &&
+               git diff-files --quiet &&
+               test_must_fail git rebase --continue &&
+               test_cmp expected-F3 F3 &&
+               git diff-files --quiet &&
+               git rebase --continue
+       '
+
+       test_expect_success "rebase $action --continue honors rerere.autoUpdate" '
+               prepare &&
+               test_config rerere.autoupdate true &&
+               test_must_fail git rebase $action master topic &&
+               test_cmp expected-F2 F2 &&
+               git diff-files --quiet &&
+               test_must_fail git rebase --continue &&
+               test_cmp expected-F3 F3 &&
+               git diff-files --quiet &&
+               git rebase --continue
+       '
+
+       test_expect_success "rebase $action --continue remembers --no-rerere-autoupdate" '
+               prepare &&
+               test_config rerere.autoupdate true &&
+               test_must_fail git rebase $action --no-rerere-autoupdate master topic &&
+               test_cmp expected-F2 F2 &&
+               test_must_fail git diff-files --quiet &&
+               git add F2 &&
+               test_must_fail git rebase --continue &&
+               test_cmp expected-F3 F3 &&
+               test_must_fail git diff-files --quiet &&
+               git add F3 &&
+               git rebase --continue
+       '
+}
+
+test_rerere_autoupdate
+test_rerere_autoupdate -m
+GIT_SEQUENCE_EDITOR=: && export GIT_SEQUENCE_EDITOR
+test_rerere_autoupdate -i
+test_rerere_autoupdate --preserve-merges
+
 test_done
index e6a64816efef0e53018c7a56784d1af62602e9d3..a267b2d144df4a84f18ba4907b317e757ba98f16 100755 (executable)
@@ -5,14 +5,13 @@ test_description='cherry-pick should rerere for conflicts'
 . ./test-lib.sh
 
 test_expect_success setup '
-       echo foo >foo &&
-       git add foo && test_tick && git commit -q -m 1 &&
-       echo foo-master >foo &&
-       git add foo && test_tick && git commit -q -m 2 &&
-
-       git checkout -b dev HEAD^ &&
-       echo foo-dev >foo &&
-       git add foo && test_tick && git commit -q -m 3 &&
+       test_commit foo &&
+       test_commit foo-master foo &&
+       test_commit bar-master bar &&
+
+       git checkout -b dev foo &&
+       test_commit foo-dev foo &&
+       test_commit bar-dev bar &&
        git config rerere.enabled true
 '
 
@@ -21,23 +20,80 @@ test_expect_success 'conflicting merge' '
 '
 
 test_expect_success 'fixup' '
-       echo foo-dev >foo &&
-       git add foo && test_tick && git commit -q -m 4 &&
-       git reset --hard HEAD^ &&
-       echo foo-dev >expect
+       echo foo-resolved >foo &&
+       echo bar-resolved >bar &&
+       git commit -am resolved &&
+       cp foo foo-expect &&
+       cp bar bar-expect &&
+       git reset --hard HEAD^
 '
 
-test_expect_success 'cherry-pick conflict' '
-       test_must_fail git cherry-pick master &&
-       test_cmp expect foo
+test_expect_success 'cherry-pick conflict with --rerere-autoupdate' '
+       test_must_fail git cherry-pick --rerere-autoupdate foo..bar-master &&
+       test_cmp foo-expect foo &&
+       git diff-files --quiet &&
+       test_must_fail git cherry-pick --continue &&
+       test_cmp bar-expect bar &&
+       git diff-files --quiet &&
+       git cherry-pick --continue &&
+       git reset --hard bar-dev
+'
+
+test_expect_success 'cherry-pick conflict repsects rerere.autoUpdate' '
+       test_config rerere.autoUpdate true &&
+       test_must_fail git cherry-pick foo..bar-master &&
+       test_cmp foo-expect foo &&
+       git diff-files --quiet &&
+       test_must_fail git cherry-pick --continue &&
+       test_cmp bar-expect bar &&
+       git diff-files --quiet &&
+       git cherry-pick --continue &&
+       git reset --hard bar-dev
+'
+
+test_expect_success 'cherry-pick conflict with --no-rerere-autoupdate' '
+       test_config rerere.autoUpdate true &&
+       test_must_fail git cherry-pick --no-rerere-autoupdate foo..bar-master &&
+       test_cmp foo-expect foo &&
+       test_must_fail git diff-files --quiet &&
+       git add foo &&
+       test_must_fail git cherry-pick --continue &&
+       test_cmp bar-expect bar &&
+       test_must_fail git diff-files --quiet &&
+       git add bar &&
+       git cherry-pick --continue &&
+       git reset --hard bar-dev
+'
+
+test_expect_success 'cherry-pick --continue rejects --rerere-autoupdate' '
+       test_must_fail git cherry-pick --rerere-autoupdate foo..bar-master &&
+       test_cmp foo-expect foo &&
+       git diff-files --quiet &&
+       test_must_fail git cherry-pick --continue --rerere-autoupdate >actual 2>&1 &&
+       echo "fatal: cherry-pick: --rerere-autoupdate cannot be used with --continue" >expect &&
+       test_i18ncmp expect actual &&
+       test_must_fail git cherry-pick --continue --no-rerere-autoupdate >actual 2>&1 &&
+       echo "fatal: cherry-pick: --no-rerere-autoupdate cannot be used with --continue" >expect &&
+       test_i18ncmp expect actual &&
+       git cherry-pick --abort
 '
 
-test_expect_success 'reconfigure' '
-       git config rerere.enabled false &&
-       git reset --hard
+test_expect_success 'cherry-pick --rerere-autoupdate more than once' '
+       test_must_fail git cherry-pick --rerere-autoupdate --rerere-autoupdate foo..bar-master &&
+       test_cmp foo-expect foo &&
+       git diff-files --quiet &&
+       git cherry-pick --abort &&
+       test_must_fail git cherry-pick --rerere-autoupdate --no-rerere-autoupdate --rerere-autoupdate foo..bar-master &&
+       test_cmp foo-expect foo &&
+       git diff-files --quiet &&
+       git cherry-pick --abort &&
+       test_must_fail git cherry-pick --rerere-autoupdate --no-rerere-autoupdate foo..bar-master &&
+       test_must_fail git diff-files --quiet &&
+       git cherry-pick --abort
 '
 
 test_expect_success 'cherry-pick conflict without rerere' '
+       test_config rerere.enabled false &&
        test_must_fail git cherry-pick master &&
        test_must_fail test_cmp expect foo
 '
index f3a4b4a913f344ce140344ec7b70482a6d36bcbe..0aae21d6984bf0bd5c7c7de425a021da6122beee 100755 (executable)
@@ -356,6 +356,7 @@ test_expect_success POSIXPERM,SYMLINKS 'git add --chmod=+x with symlinks' '
 
 test_expect_success 'git add --chmod=[+-]x changes index with already added file' '
        rm -f foo3 xfoo3 &&
+       git reset --hard &&
        echo foo >foo3 &&
        git add foo3 &&
        git add --chmod=+x foo3 &&
index 2f3e7cea64e897299d87196135032de22050354b..a49c12c79b28fac8545dffcbaba8e8905c8d6222 100755 (executable)
@@ -2,6 +2,7 @@
 
 test_description='add -i basic tests'
 . ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-terminal.sh
 
 if ! test_have_prereq PERL
 then
@@ -380,14 +381,11 @@ test_expect_success 'patch mode ignores unmerged entries' '
        test_cmp expected diff
 '
 
-test_expect_success 'diffs can be colorized' '
+test_expect_success TTY 'diffs can be colorized' '
        git reset --hard &&
 
-       # force color even though the test script has no terminal
-       test_config color.ui always &&
-
        echo content >test &&
-       printf y | git add -p >output 2>&1 &&
+       printf y | test_terminal git add -p >output 2>&1 &&
 
        # We do not want to depend on the exact coloring scheme
        # git uses for diffs, so just check that we saw some kind of color.
@@ -485,4 +483,14 @@ test_expect_success 'hunk-editing handles custom comment char' '
        git diff --exit-code
 '
 
+test_expect_success 'add -p works even with color.ui=always' '
+       git reset --hard &&
+       echo change >>file &&
+       test_config color.ui always &&
+       echo y | git add -p &&
+       echo file >expect &&
+       git diff --cached --name-only >actual &&
+       test_cmp expect actual
+'
+
 test_done
index 289806d0c7eb02e0acc5244df5e3999d45b4e085..94597ff284da22ac55f0bfd6bc00434e5df7d40b 100755 (executable)
@@ -821,7 +821,7 @@ test_expect_success 'diff that introduces a line with only tabs' '
        echo "test" >x &&
        git commit -m "initial" x &&
        echo "{NTN}" | tr "NT" "\n\t" >>x &&
-       git -c color.diff=always diff | test_decode_color >current &&
+       git diff --color | test_decode_color >current &&
 
        cat >expected <<-\EOF &&
        <BOLD>diff --git a/x b/x<RESET>
@@ -851,7 +851,7 @@ test_expect_success 'diff that introduces and removes ws breakages' '
                echo "2. and a new line "
        } >x &&
 
-       git -c color.diff=always diff |
+       git diff --color |
        test_decode_color >current &&
 
        cat >expected <<-\EOF &&
@@ -923,15 +923,15 @@ test_expect_success 'ws-error-highlight test setup' '
 
 test_expect_success 'test --ws-error-highlight option' '
 
-       git -c color.diff=always diff --ws-error-highlight=default,old |
+       git diff --color --ws-error-highlight=default,old |
        test_decode_color >current &&
        test_cmp expect.default-old current &&
 
-       git -c color.diff=always diff --ws-error-highlight=all |
+       git diff --color --ws-error-highlight=all |
        test_decode_color >current &&
        test_cmp expect.all current &&
 
-       git -c color.diff=always diff --ws-error-highlight=none |
+       git diff --color --ws-error-highlight=none |
        test_decode_color >current &&
        test_cmp expect.none current
 
@@ -939,15 +939,15 @@ test_expect_success 'test --ws-error-highlight option' '
 
 test_expect_success 'test diff.wsErrorHighlight config' '
 
-       git -c color.diff=always -c diff.wsErrorHighlight=default,old diff |
+       git -c diff.wsErrorHighlight=default,old diff --color |
        test_decode_color >current &&
        test_cmp expect.default-old current &&
 
-       git -c color.diff=always -c diff.wsErrorHighlight=all diff |
+       git -c diff.wsErrorHighlight=all diff --color |
        test_decode_color >current &&
        test_cmp expect.all current &&
 
-       git -c color.diff=always -c diff.wsErrorHighlight=none diff |
+       git -c diff.wsErrorHighlight=none diff --color |
        test_decode_color >current &&
        test_cmp expect.none current
 
@@ -955,18 +955,18 @@ test_expect_success 'test diff.wsErrorHighlight config' '
 
 test_expect_success 'option overrides diff.wsErrorHighlight' '
 
-       git -c color.diff=always -c diff.wsErrorHighlight=none \
-               diff --ws-error-highlight=default,old |
+       git -c diff.wsErrorHighlight=none \
+               diff --color --ws-error-highlight=default,old |
        test_decode_color >current &&
        test_cmp expect.default-old current &&
 
-       git -c color.diff=always -c diff.wsErrorHighlight=default \
-               diff --ws-error-highlight=all |
+       git -c diff.wsErrorHighlight=default \
+               diff --color --ws-error-highlight=all |
        test_decode_color >current &&
        test_cmp expect.all current &&
 
-       git -c color.diff=always -c diff.wsErrorHighlight=all \
-               diff --ws-error-highlight=none |
+       git -c diff.wsErrorHighlight=all \
+               diff --color --ws-error-highlight=none |
        test_decode_color >current &&
        test_cmp expect.none current
 
index 7c4903f49713a22d7fba28a608acf07f1330110b..1130c8019b4c14975744f31f360886ffb4c3f14c 100755 (executable)
@@ -14,8 +14,10 @@ test_expect_success setup '
        test_tick &&
        git commit -m "A 4k file"
 '
+
+# OpenBSD only supports up to 255 repetitions, so repeat twice for 64*64=4096.
 test_expect_success '-G matches' '
-       git diff --name-only -G "^0{4096}$" HEAD^ >out &&
+       git diff --name-only -G "^(0{64}){64}$" HEAD^ >out &&
        test 4096-zeroes.txt = "$(cat out)"
 '
 
index d350065f25c2fb8cd61d9f12f720cf315aa3436d..4fc27c51f7322ccb49a58d369185e64278ea246b 100755 (executable)
@@ -467,21 +467,42 @@ test_expect_success 'same, but with CR-LF line endings && cr-at-eol set' '
        test_cmp one expect
 '
 
-test_expect_success 'same, but with CR-LF line endings && cr-at-eol unset' '
+test_expect_success 'CR-LF line endings && add line && text=auto' '
        git config --unset core.whitespace &&
        printf "a\r\n" >one &&
+       cp one save-one &&
+       git add one &&
        printf "b\r\n" >>one &&
-       printf "c\r\n" >>one &&
+       cp one expect &&
+       git diff -- one >patch &&
+       mv save-one one &&
+       echo "one text=auto" >.gitattributes &&
+       git apply patch &&
+       test_cmp one expect
+'
+
+test_expect_success 'CR-LF line endings && change line && text=auto' '
+       printf "a\r\n" >one &&
        cp one save-one &&
-       printf "                 \r\n" >>one &&
        git add one &&
+       printf "b\r\n" >one &&
        cp one expect &&
-       printf "d\r\n" >>one &&
        git diff -- one >patch &&
        mv save-one one &&
-       echo d >>expect &&
+       echo "one text=auto" >.gitattributes &&
+       git apply patch &&
+       test_cmp one expect
+'
 
-       git apply --ignore-space-change --whitespace=fix patch &&
+test_expect_success 'LF in repo, CRLF in worktree && change line && text=auto' '
+       printf "a\n" >one &&
+       git add one &&
+       printf "b\r\n" >one &&
+       git diff -- one >patch &&
+       printf "a\r\n" >one &&
+       echo "one text=auto" >.gitattributes &&
+       git -c core.eol=CRLF apply patch &&
+       printf "b\r\n" >expect &&
        test_cmp one expect
 '
 
index 44807e218d7016f58bd41b89af71104a37f31a8b..73b67b4280b99e0328e201e6b69c3d88b766ea84 100755 (executable)
@@ -40,6 +40,8 @@ test_expect_success 'setup: messages' '
        dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio
        dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te
        feugait nulla facilisi.
+
+       Reported-by: A N Other <a.n.other@example.com>
        EOF
 
        cat >failmail <<-\EOF &&
@@ -93,7 +95,7 @@ test_expect_success setup '
        echo world >>file &&
        git add file &&
        test_tick &&
-       git commit -s -F msg &&
+       git commit -F msg &&
        git tag second &&
 
        git format-patch --stdout first >patch1 &&
@@ -124,8 +126,6 @@ test_expect_success setup '
                echo "Date: $GIT_AUTHOR_DATE" &&
                echo &&
                sed -e "1,2d" msg &&
-               echo &&
-               echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" &&
                echo "---" &&
                git diff-tree --no-commit-id --stat -p second
        } >patch1-stgit.eml &&
@@ -144,8 +144,6 @@ test_expect_success setup '
                echo "# Parent  $_z40" &&
                cat msg &&
                echo &&
-               echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" &&
-               echo &&
                git diff-tree --no-commit-id -p second
        } >patch1-hg.eml &&
 
@@ -470,13 +468,15 @@ test_expect_success 'am --signoff adds Signed-off-by: line' '
        git reset --hard &&
        git checkout -b master2 first &&
        git am --signoff <patch2 &&
-       printf "%s\n" "$signoff" >expected &&
-       echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >>expected &&
-       git cat-file commit HEAD^ | grep "Signed-off-by:" >actual &&
-       test_cmp expected actual &&
-       echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >expected &&
-       git cat-file commit HEAD | grep "Signed-off-by:" >actual &&
-       test_cmp expected actual
+       {
+               printf "third\n\nSigned-off-by: %s <%s>\n\n" \
+                       "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" &&
+               cat msg &&
+               printf "Signed-off-by: %s <%s>\n\n" \
+                       "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL"
+       } >expected-log &&
+       git log --pretty=%B -2 HEAD >actual &&
+       test_cmp expected-log actual
 '
 
 test_expect_success 'am stays in branch' '
@@ -486,17 +486,60 @@ test_expect_success 'am stays in branch' '
 '
 
 test_expect_success 'am --signoff does not add Signed-off-by: line if already there' '
-       git format-patch --stdout HEAD^ >patch3 &&
-       sed -e "/^Subject/ s,\[PATCH,Re: Re: Re: & 1/5 v2] [foo," patch3 >patch4 &&
-       rm -fr .git/rebase-apply &&
-       git reset --hard &&
-       git checkout HEAD^ &&
-       git am --signoff patch4 &&
-       git cat-file commit HEAD >actual &&
-       test $(grep -c "^Signed-off-by:" actual) -eq 1
+       git format-patch --stdout first >patch3 &&
+       git reset --hard first &&
+       git am --signoff <patch3 &&
+       git log --pretty=%B -2 HEAD >actual &&
+       test_cmp expected-log actual
+'
+
+test_expect_success 'am --signoff adds Signed-off-by: if another author is preset' '
+       NAME="A N Other" &&
+       EMAIL="a.n.other@example.com" &&
+       {
+               printf "third\n\nSigned-off-by: %s <%s>\nSigned-off-by: %s <%s>\n\n" \
+                       "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" \
+                       "$NAME" "$EMAIL" &&
+               cat msg &&
+               printf "Signed-off-by: %s <%s>\nSigned-off-by: %s <%s>\n\n" \
+                       "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" \
+                       "$NAME" "$EMAIL"
+       } >expected-log &&
+       git reset --hard first &&
+       GIT_COMMITTER_NAME="$NAME" GIT_COMMITTER_EMAIL="$EMAIL" \
+               git am --signoff <patch3 &&
+       git log --pretty=%B -2 HEAD >actual &&
+       test_cmp expected-log actual
+'
+
+test_expect_success 'am --signoff duplicates Signed-off-by: if it is not the last one' '
+       NAME="A N Other" &&
+       EMAIL="a.n.other@example.com" &&
+       {
+               printf "third\n\nSigned-off-by: %s <%s>\n\
+Signed-off-by: %s <%s>\nSigned-off-by: %s <%s>\n\n" \
+                       "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" \
+                       "$NAME" "$EMAIL" \
+                       "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" &&
+               cat msg &&
+               printf "Signed-off-by: %s <%s>\nSigned-off-by: %s <%s>\n\
+Signed-off-by: %s <%s>\n\n" \
+                       "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" \
+                       "$NAME" "$EMAIL" \
+                       "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL"
+       } >expected-log &&
+       git format-patch --stdout first >patch3 &&
+       git reset --hard first &&
+       git am --signoff <patch3 &&
+       git log --pretty=%B -2 HEAD >actual &&
+       test_cmp expected-log actual
 '
 
 test_expect_success 'am without --keep removes Re: and [PATCH] stuff' '
+       git format-patch --stdout HEAD^ >tmp &&
+       sed -e "/^Subject/ s,\[PATCH,Re: Re: Re: & 1/5 v2] [foo," tmp >patch4 &&
+       git reset --hard HEAD^ &&
+       git am <patch4 &&
        git rev-parse HEAD >expected &&
        git rev-parse master2 >actual &&
        test_cmp expected actual
index 3f3531f0a49be39e29b20a36a55f0d27f04b4fc8..8f155da7a50a657db9fd092e24639f67cd03cd24 100755 (executable)
@@ -750,7 +750,7 @@ test_expect_success 'log.decorate config parsing' '
 '
 
 test_expect_success TTY 'log output on a TTY' '
-       git log --oneline --decorate >expect.short &&
+       git log --color --oneline --decorate >expect.short &&
 
        test_terminal git log --oneline >actual &&
        test_cmp expect.short actual
@@ -1523,6 +1523,12 @@ test_expect_success 'log diagnoses bogus HEAD' '
        test_i18ngrep broken stderr
 '
 
+test_expect_success 'log does not default to HEAD when rev input is given' '
+       >expect &&
+       git log --branches=does-not-exist >actual &&
+       test_cmp expect actual
+'
+
 test_expect_success 'set up --source tests' '
        git checkout --orphan source-a &&
        test_commit one &&
index b04d955bfa8229a9c864ad53d1f9f1ec06260637..e9aa97117ab41beab708f4ded34628b015021e4e 100755 (executable)
@@ -7,11 +7,15 @@ test_description='git archive attribute tests'
 SUBSTFORMAT='%H (%h)%n'
 
 test_expect_exists() {
-       test_expect_success " $1 exists" "test -e $1"
+       test_expect_${2:-success} " $1 exists" "test -e $1"
 }
 
 test_expect_missing() {
-       test_expect_success " $1 does not exist" "test ! -e $1"
+       test_expect_${2:-success} " $1 does not exist" "test ! -e $1"
+}
+
+extract_tar_to_dir () {
+       (mkdir "$1" && cd "$1" && "$TAR" xf -) <"$1.tar"
 }
 
 test_expect_success 'setup' '
@@ -21,12 +25,19 @@ test_expect_success 'setup' '
 
        echo ignored by tree >ignored-by-tree &&
        echo ignored-by-tree export-ignore >.gitattributes &&
-       git add ignored-by-tree .gitattributes &&
+       mkdir ignored-by-tree.d &&
+       >ignored-by-tree.d/file &&
+       echo ignored-by-tree.d export-ignore >>.gitattributes &&
+       git add ignored-by-tree ignored-by-tree.d .gitattributes &&
 
        echo ignored by worktree >ignored-by-worktree &&
        echo ignored-by-worktree export-ignore >.gitattributes &&
        git add ignored-by-worktree &&
 
+       mkdir excluded-by-pathspec.d &&
+       >excluded-by-pathspec.d/file &&
+       git add excluded-by-pathspec.d &&
+
        printf "A\$Format:%s\$O" "$SUBSTFORMAT" >nosubstfile &&
        printf "A\$Format:%s\$O" "$SUBSTFORMAT" >substfile1 &&
        printf "A not substituted O" >substfile2 &&
@@ -46,7 +57,37 @@ test_expect_success 'git archive' '
 
 test_expect_missing    archive/ignored
 test_expect_missing    archive/ignored-by-tree
+test_expect_missing    archive/ignored-by-tree.d
+test_expect_missing    archive/ignored-by-tree.d/file
 test_expect_exists     archive/ignored-by-worktree
+test_expect_exists     archive/excluded-by-pathspec.d
+test_expect_exists     archive/excluded-by-pathspec.d/file
+
+test_expect_success 'git archive with pathspec' '
+       git archive HEAD ":!excluded-by-pathspec.d" >archive-pathspec.tar &&
+       extract_tar_to_dir archive-pathspec
+'
+
+test_expect_missing    archive-pathspec/ignored
+test_expect_missing    archive-pathspec/ignored-by-tree
+test_expect_missing    archive-pathspec/ignored-by-tree.d
+test_expect_missing    archive-pathspec/ignored-by-tree.d/file
+test_expect_exists     archive-pathspec/ignored-by-worktree
+test_expect_missing    archive-pathspec/excluded-by-pathspec.d
+test_expect_missing    archive-pathspec/excluded-by-pathspec.d/file
+
+test_expect_success 'git archive with wildcard pathspec' '
+       git archive HEAD ":!excluded-by-p*" >archive-pathspec-wildcard.tar &&
+       extract_tar_to_dir archive-pathspec-wildcard
+'
+
+test_expect_missing    archive-pathspec-wildcard/ignored
+test_expect_missing    archive-pathspec-wildcard/ignored-by-tree
+test_expect_missing    archive-pathspec-wildcard/ignored-by-tree.d
+test_expect_missing    archive-pathspec-wildcard/ignored-by-tree.d/file
+test_expect_exists     archive-pathspec-wildcard/ignored-by-worktree
+test_expect_missing    archive-pathspec-wildcard/excluded-by-pathspec.d
+test_expect_missing    archive-pathspec-wildcard/excluded-by-pathspec.d/file
 
 test_expect_success 'git archive with worktree attributes' '
        git archive --worktree-attributes HEAD >worktree.tar &&
index 6667d159ab0950f10a3271f1cb81a63953214f17..bda6d7d7e9e835213f9b1323407222850db47ad6 100755 (executable)
@@ -76,7 +76,7 @@ test_expect_missing   archive/deep/and/slashless/ &&
 test_expect_missing    archive/deep/and/slashless/foo &&
 test_expect_missing    archive/deep/with/wildcard/ &&
 test_expect_missing    archive/deep/with/wildcard/foo &&
-test_expect_exists     archive/one-level-lower/
+test_expect_missing    archive/one-level-lower/
 test_expect_missing    archive/one-level-lower/two-levels-lower/ignored-only-if-dir/
 test_expect_missing    archive/one-level-lower/two-levels-lower/ignored-ony-if-dir/ignored-by-ignored-dir
 
index f6207f42b5a4ed382b819cb81631cd0acab61463..ced44355cab99fc4f5fd9768daf10f5a2c1b21c7 100755 (executable)
@@ -108,14 +108,14 @@ test_expect_success 'archive empty subtree with no pathspec' '
        git archive --format=tar $root_tree >subtree-all.tar &&
        make_dir extract &&
        "$TAR" xf subtree-all.tar -C extract &&
-       check_dir extract sub
+       check_dir extract
 '
 
 test_expect_success 'archive empty subtree by direct pathspec' '
        git archive --format=tar $root_tree -- sub >subtree-path.tar &&
        make_dir extract &&
        "$TAR" xf subtree-path.tar -C extract &&
-       check_dir extract sub
+       check_dir extract
 '
 
 ZIPINFO=zipinfo
index 82c33b88e710b5fb6163a7bdcd9ecb783633aa83..08c210f03586ab8cd26d69cb0761180ef5588f58 100755 (executable)
@@ -68,7 +68,7 @@ test_expect_success 'setup: two scripts for reading pull requests' '
        cat <<-\EOT >read-request.sed &&
        #!/bin/sed -nf
        # Note that a request could ask for "tag $tagname"
-       / in the git repository at:$/!d
+       / in the Git repository at:$/!d
        n
        /^$/ n
        s/ tag \([^ ]*\)$/ tag--\1/
@@ -192,7 +192,7 @@ test_expect_success 'pull request format' '
 
          SUBJECT (DATE)
 
-       are available in the git repository at:
+       are available in the Git repository at:
 
          URL BRANCH
 
index 9c5a8766ab0af40382b83cf3340b13a32f7f0c8e..156ae9e9d335029e63430a6cc7d0ec2fd0d68dd3 100755 (executable)
@@ -56,20 +56,11 @@ test_expect_success 'create batch-check test vectors' '
        EOF
 '
 
-test_expect_success 'lookup in duplicated pack (binary search)' '
+test_expect_success 'lookup in duplicated pack' '
        git cat-file --batch-check <input >actual &&
        test_cmp expect actual
 '
 
-test_expect_success 'lookup in duplicated pack (GIT_USE_LOOKUP)' '
-       (
-               GIT_USE_LOOKUP=1 &&
-               export GIT_USE_LOOKUP &&
-               git cat-file --batch-check <input >actual
-       ) &&
-       test_cmp expect actual
-'
-
 test_expect_success 'index-pack can reject packs with duplicates' '
        clear_packs &&
        create_pack dups.pack 2 &&
index 162baf101f340885619e0a1e67b0b14cf37a2347..42251f7f3af0865a31fd38722fbf7433d81fe3f0 100755 (executable)
@@ -193,7 +193,7 @@ test_expect_success "recurseSubmodules=true propagates into submodules" '
        add_upstream_commit &&
        (
                cd downstream &&
-               git config fetch.recurseSubmodules true
+               git config fetch.recurseSubmodules true &&
                git fetch >../actual.out 2>../actual.err
        ) &&
        test_must_be_empty actual.out &&
@@ -218,7 +218,7 @@ test_expect_success "--no-recurse-submodules overrides config setting" '
        add_upstream_commit &&
        (
                cd downstream &&
-               git config fetch.recurseSubmodules true
+               git config fetch.recurseSubmodules true &&
                git fetch --no-recurse-submodules >../actual.out 2>../actual.err
        ) &&
        ! test -s actual.out &&
@@ -232,7 +232,7 @@ test_expect_success "Recursion doesn't happen when no new commits are fetched in
                        cd submodule &&
                        git config --unset fetch.recurseSubmodules
                ) &&
-               git config --unset fetch.recurseSubmodules
+               git config --unset fetch.recurseSubmodules &&
                git fetch >../actual.out 2>../actual.err
        ) &&
        ! test -s actual.out &&
@@ -312,7 +312,7 @@ test_expect_success "Recursion picks up all submodules when necessary" '
                ) &&
                head1=$(git rev-parse --short HEAD^) &&
                git add subdir/deepsubmodule &&
-               git commit -m "new deepsubmodule"
+               git commit -m "new deepsubmodule" &&
                head2=$(git rev-parse --short HEAD) &&
                echo "Fetching submodule submodule" > ../expect.err.sub &&
                echo "From $pwd/submodule" >> ../expect.err.sub &&
index beff65b8ace505d78c3997a737711ee7fc6383b5..0f84a53146f3bac1bded4d2b11212b8ddef1bf2c 100755 (executable)
@@ -533,7 +533,8 @@ test_expect_success 'push propagating refspec to a submodule' '
        # Fails when refspec includes an object id
        test_must_fail git -C work push --recurse-submodules=on-demand origin \
                "$(git -C work rev-parse branch2):refs/heads/branch2" &&
-       # Fails when refspec includes 'HEAD' as it is unsupported at this time
+       # Fails when refspec includes HEAD and parent and submodule do not
+       # have the same named branch checked out
        test_must_fail git -C work push --recurse-submodules=on-demand origin \
                HEAD:refs/heads/branch2 &&
 
@@ -548,4 +549,26 @@ test_expect_success 'push propagating refspec to a submodule' '
        test_cmp expected_pub actual_pub
 '
 
+test_expect_success 'push propagating HEAD refspec to a submodule' '
+       git -C work/gar/bage checkout branch2 &&
+       > work/gar/bage/junk12 &&
+       git -C work/gar/bage add junk12 &&
+       git -C work/gar/bage commit -m "Twelfth junk" &&
+
+       git -C work checkout branch2 &&
+       git -C work add gar/bage &&
+       git -C work commit -m "updating gar/bage in branch2" &&
+
+       # Passes since the superproject and submodules HEAD are both on branch2
+       git -C work push --recurse-submodules=on-demand origin \
+               HEAD:refs/heads/branch2 &&
+
+       git -C submodule.git rev-parse branch2 >actual_submodule &&
+       git -C pub.git rev-parse branch2 >actual_pub &&
+       git -C work/gar/bage rev-parse branch2 >expected_submodule &&
+       git -C work rev-parse branch2 >expected_pub &&
+       test_cmp expected_submodule actual_submodule &&
+       test_cmp expected_pub actual_pub
+'
+
 test_done
index 534903bbd2972301965a3d7eed6fa8e380eeeb86..a6614080388353c828fdd3894c093ef03f71511d 100755 (executable)
@@ -236,17 +236,31 @@ test_sequence "--bisect"
 #
 #
 
-test_expect_success '--bisect can default to good/bad refs' '
+test_expect_success 'set up fake --bisect refs' '
        git update-ref refs/bisect/bad c3 &&
        good=$(git rev-parse b1) &&
        git update-ref refs/bisect/good-$good $good &&
        good=$(git rev-parse c1) &&
-       git update-ref refs/bisect/good-$good $good &&
+       git update-ref refs/bisect/good-$good $good
+'
 
+test_expect_success 'rev-list --bisect can default to good/bad refs' '
        # the only thing between c3 and c1 is c2
        git rev-parse c2 >expect &&
        git rev-list --bisect >actual &&
        test_cmp expect actual
 '
 
+test_expect_success 'rev-parse --bisect can default to good/bad refs' '
+       git rev-parse c3 ^b1 ^c1 >expect &&
+       git rev-parse --bisect >actual &&
+
+       # output order depends on the refnames, which in turn depends on
+       # the exact sha1s. We just want to make sure we have the same set
+       # of lines in any order.
+       sort <expect >expect.sorted &&
+       sort <actual >actual.sorted &&
+       test_cmp expect.sorted actual.sorted
+'
+
 test_done
index b326d550f3e281e4b19ab669b95f08e8c63bf555..98be78b4a2123cad7e16911ae2eedff5695ba3d3 100755 (executable)
@@ -229,8 +229,7 @@ do
        '
 
        test_expect_success TTY "$desc respects --color=auto (stdout is tty)" '
-               test_terminal env TERM=vt100 \
-                       git log --format=$color -1 --color=auto >actual &&
+               test_terminal git log --format=$color -1 --color=auto >actual &&
                has_color actual
        '
 
index 381f35ed16d152e7926774587c1c0a006a600ee6..d3453c583c1921a10409c16b5e2cf949edde6cd2 100755 (executable)
@@ -255,27 +255,19 @@ test_expect_success 'rev-list accumulates multiple --exclude' '
        compare rev-list "--exclude=refs/remotes/* --exclude=refs/tags/* --all" --branches
 '
 
-
-# "git rev-list<ENTER>" is likely to be a bug in the calling script and may
-# deserve an error message, but do cases where set of refs programmatically
-# given using globbing and/or --stdin need to fail with the same error, or
-# are we better off reporting a success with no output?  The following few
-# tests document the current behaviour to remind us that we might want to
-# think about this issue.
-
-test_expect_failure 'rev-list may want to succeed with empty output on no input (1)' '
+test_expect_failure 'rev-list should succeed with empty output on empty stdin' '
        >expect &&
        git rev-list --stdin <expect >actual &&
        test_cmp expect actual
 '
 
-test_expect_failure 'rev-list may want to succeed with empty output on no input (2)' '
+test_expect_success 'rev-list should succeed with empty output with all refs excluded' '
        >expect &&
        git rev-list --exclude=* --all >actual &&
        test_cmp expect actual
 '
 
-test_expect_failure 'rev-list may want to succeed with empty output on no input (3)' '
+test_expect_success 'rev-list should succeed with empty output with empty --all' '
        (
                test_create_repo empty &&
                cd empty &&
@@ -285,6 +277,12 @@ test_expect_failure 'rev-list may want to succeed with empty output on no input
        )
 '
 
+test_expect_success 'rev-list should succeed with empty output with empty glob' '
+       >expect &&
+       git rev-list --glob=does-not-match-anything >actual &&
+       test_cmp expect actual
+'
+
 test_expect_success 'shortlog accepts --glob/--tags/--remotes' '
 
        compare shortlog "subspace/one subspace/two" --branches=subspace &&
index aa74eb8f0d5dfb4f228b1e8c7b9dbbc0b88adb4d..25110ea55d89656ab3fd4da525d4c94bc75840ac 100755 (executable)
@@ -182,10 +182,14 @@ check_describe "test2-lightweight-*" --tags --match="test2-*"
 
 check_describe "test2-lightweight-*" --long --tags --match="test2-*" HEAD^
 
-check_describe "test1-lightweight-*" --long --tags --match="test1-*" --match="test2-*" HEAD^
+check_describe "test2-lightweight-*" --long --tags --match="test1-*" --match="test2-*" HEAD^
 
 check_describe "test2-lightweight-*" --long --tags --match="test1-*" --no-match --match="test2-*" HEAD^
 
+check_describe "test1-lightweight-*" --long --tags --match="test1-*" --match="test3-*" HEAD
+
+check_describe "test1-lightweight-*" --long --tags --match="test3-*" --match="test1-*" HEAD
+
 test_expect_success 'name-rev with exact tags' '
        echo A >expect &&
        tag_object=$(git rev-parse refs/tags/A) &&
index 9dd5cde5fc53deb365234e815d7142de9a975005..eb829fce97dc7067cbb502b9f5fd2b14c4e74e10 100755 (executable)
@@ -25,7 +25,7 @@ EOF
        test_cmp expect actual
 '
 
-test_expect_success 'exclude only no longer errors out' '
+test_expect_success 'exclude only pathspec uses default implicit pathspec' '
        git log --oneline --format=%s -- . ":(exclude)sub" >expect &&
        git log --oneline --format=%s -- ":(exclude)sub" >actual &&
        test_cmp expect actual
@@ -183,4 +183,15 @@ EOF
        test_cmp expect actual
 '
 
+test_expect_success 'multiple exclusions' '
+       git ls-files -- ":^*/file2" ":^sub2" >actual &&
+       cat <<-\EOF >expect &&
+       file
+       sub/file
+       sub/sub/file
+       sub/sub/sub/file
+       EOF
+       test_cmp expect actual
+'
+
 test_done
index 2274a4b73310bfbc90886e0179a1cb12d9b6f3ed..d0ad90291131a3a714a58f6a867fe4322a08e1c5 100755 (executable)
@@ -51,6 +51,7 @@ test_atom() {
 }
 
 test_atom head refname refs/heads/master
+test_atom head refname: refs/heads/master
 test_atom head refname:short master
 test_atom head refname:lstrip=1 heads/master
 test_atom head refname:lstrip=2 master
@@ -425,8 +426,7 @@ test_expect_success 'set up color tests' '
 '
 
 test_expect_success TTY '%(color) shows color with a tty' '
-       test_terminal env TERM=vt100 \
-               git for-each-ref --format="$color_format" >actual.raw &&
+       test_terminal git for-each-ref --format="$color_format" >actual.raw &&
        test_decode_color <actual.raw >actual &&
        test_cmp expected.color actual
 '
@@ -436,12 +436,17 @@ test_expect_success '%(color) does not show color without tty' '
        test_cmp expected.bare actual
 '
 
-test_expect_success 'color.ui=always can override tty check' '
-       git -c color.ui=always for-each-ref --format="$color_format" >actual.raw &&
+test_expect_success '--color can override tty check' '
+       git for-each-ref --color --format="$color_format" >actual.raw &&
        test_decode_color <actual.raw >actual &&
        test_cmp expected.color actual
 '
 
+test_expect_success 'color.ui=always does not override tty check' '
+       git -c color.ui=always for-each-ref --format="$color_format" >actual &&
+       test_cmp expected.bare actual
+'
+
 cat >expected <<\EOF
 heads/master
 tags/master
index dd5ba450ee4b33801dc39d0b57e4c4b08c1dfd62..62aa322846be36a2794d4089369292cecd319d6b 100755 (executable)
@@ -1888,7 +1888,7 @@ EOF"
        run_with_limited_stack git tag --contains HEAD >actual &&
        test_cmp expect actual &&
        run_with_limited_stack git tag --no-contains HEAD >actual &&
-       test_line_count ">" 10 actual
+       test_line_count "-gt" 10 actual
 '
 
 test_expect_success '--format should list tags as per format given' '
@@ -1914,7 +1914,13 @@ test_expect_success '%(color) omitted without tty' '
 '
 
 test_expect_success TTY '%(color) present with tty' '
-       test_terminal env TERM=vt100 git tag $color_args >actual.raw &&
+       test_terminal git tag $color_args >actual.raw &&
+       test_decode_color <actual.raw >actual &&
+       test_cmp expect.color actual
+'
+
+test_expect_success '--color overrides auto-color' '
+       git tag --color $color_args >actual.raw &&
        test_decode_color <actual.raw >actual &&
        test_cmp expect.color actual
 '
index 20b4d83c281e2fde8812f309bdebef012c6ecb74..f0f1abd1c23d4303a686310d7325cd523d6c921b 100755 (executable)
@@ -134,6 +134,86 @@ test_expect_success TTY 'configuration can enable pager (from subdir)' '
        }
 '
 
+test_expect_success TTY 'git tag -l defaults to paging' '
+       rm -f paginated.out &&
+       test_terminal git tag -l &&
+       test -e paginated.out
+'
+
+test_expect_success TTY 'git tag -l respects pager.tag' '
+       rm -f paginated.out &&
+       test_terminal git -c pager.tag=false tag -l &&
+       ! test -e paginated.out
+'
+
+test_expect_success TTY 'git tag -l respects --no-pager' '
+       rm -f paginated.out &&
+       test_terminal git -c pager.tag --no-pager tag -l &&
+       ! test -e paginated.out
+'
+
+test_expect_success TTY 'git tag with no args defaults to paging' '
+       # no args implies -l so this should page like -l
+       rm -f paginated.out &&
+       test_terminal git tag &&
+       test -e paginated.out
+'
+
+test_expect_success TTY 'git tag with no args respects pager.tag' '
+       # no args implies -l so this should page like -l
+       rm -f paginated.out &&
+       test_terminal git -c pager.tag=false tag &&
+       ! test -e paginated.out
+'
+
+test_expect_success TTY 'git tag --contains defaults to paging' '
+       # --contains implies -l so this should page like -l
+       rm -f paginated.out &&
+       test_terminal git tag --contains &&
+       test -e paginated.out
+'
+
+test_expect_success TTY 'git tag --contains respects pager.tag' '
+       # --contains implies -l so this should page like -l
+       rm -f paginated.out &&
+       test_terminal git -c pager.tag=false tag --contains &&
+       ! test -e paginated.out
+'
+
+test_expect_success TTY 'git tag -a defaults to not paging' '
+       test_when_finished "git tag -d newtag" &&
+       rm -f paginated.out &&
+       test_terminal git tag -am message newtag &&
+       ! test -e paginated.out
+'
+
+test_expect_success TTY 'git tag -a ignores pager.tag' '
+       test_when_finished "git tag -d newtag" &&
+       rm -f paginated.out &&
+       test_terminal git -c pager.tag tag -am message newtag &&
+       ! test -e paginated.out
+'
+
+test_expect_success TTY 'git tag -a respects --paginate' '
+       test_when_finished "git tag -d newtag" &&
+       rm -f paginated.out &&
+       test_terminal git --paginate tag -am message newtag &&
+       test -e paginated.out
+'
+
+test_expect_success TTY 'git tag as alias ignores pager.tag with -a' '
+       test_when_finished "git tag -d newtag" &&
+       rm -f paginated.out &&
+       test_terminal git -c pager.tag -c alias.t=tag t -am message newtag &&
+       ! test -e paginated.out
+'
+
+test_expect_success TTY 'git tag as alias respects pager.tag with -l' '
+       rm -f paginated.out &&
+       test_terminal git -c pager.tag=false -c alias.t=tag t -l &&
+       ! test -e paginated.out
+'
+
 # A colored commit log will begin with an appropriate ANSI escape
 # for the first color; the text "commit" comes later.
 colorful() {
@@ -159,7 +239,7 @@ test_expect_success 'no color when stdout is a regular file' '
 test_expect_success TTY 'color when writing to a pager' '
        rm -f paginated.out &&
        test_config color.ui auto &&
-       test_terminal env TERM=vt100 git log &&
+       test_terminal git log &&
        colorful paginated.out
 '
 
@@ -167,7 +247,7 @@ test_expect_success TTY 'colors are suppressed by color.pager' '
        rm -f paginated.out &&
        test_config color.ui auto &&
        test_config color.pager false &&
-       test_terminal env TERM=vt100 git log &&
+       test_terminal git log &&
        ! colorful paginated.out
 '
 
@@ -186,7 +266,7 @@ test_expect_success 'color when writing to a file intended for a pager' '
 test_expect_success TTY 'colors are sent to pager for external commands' '
        test_config alias.externallog "!git log" &&
        test_config color.ui auto &&
-       test_terminal env TERM=vt100 git -p externallog &&
+       test_terminal git -p externallog &&
        colorful paginated.out
 '
 
index dcac364c5fa2a8ff7fe264a21fb9682ec934a874..e9c3335b78bb6f78c640cf496f7b055462c1e275 100755 (executable)
@@ -1289,4 +1289,10 @@ test_expect_success 'init properly sets the config' '
        test_must_fail git -C multisuper_clone config --get submodule.sub1.active
 '
 
+test_expect_success 'recursive clone respects -q' '
+       test_when_finished "rm -rf multisuper_clone" &&
+       git clone -q --recurse-submodules multisuper multisuper_clone >actual &&
+       test_must_be_empty actual
+'
+
 test_done
index 725687d5d5f26d6535b3f26d1fa221a8c567d57c..d33a3cb331b6c022343aff0bb7091cf8219b40df 100755 (executable)
@@ -171,9 +171,9 @@ test_expect_success 'verbose' '
 
 test_expect_success 'verbose respects diff config' '
 
-       test_config color.diff always &&
+       test_config diff.noprefix true &&
        git status -v >actual &&
-       grep "\[1mdiff --git" actual
+       grep "diff --git negative negative" actual
 '
 
 mesg_with_comment_and_newlines='
index 43d19a9b2292033fd0297afb7df162efa2eb5621..a3d760e63ad5c8387c3b0c0a30ae72918a2736ce 100755 (executable)
@@ -6,6 +6,7 @@
 test_description='git status'
 
 . ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-terminal.sh
 
 test_expect_success 'status -h in broken repository' '
        git config --global advice.statusuoption false &&
@@ -667,7 +668,7 @@ test_expect_success 'setup unique colors' '
 
 '
 
-test_expect_success 'status with color.ui' '
+test_expect_success TTY 'status with color.ui' '
        cat >expect <<\EOF &&
 On branch <GREEN>master<RESET>
 Your branch and '\''upstream'\'' have diverged,
@@ -694,14 +695,14 @@ Untracked files:
        <BLUE>untracked<RESET>
 
 EOF
-       test_config color.ui always &&
-       git status | test_decode_color >output &&
+       test_config color.ui auto &&
+       test_terminal git status | test_decode_color >output &&
        test_i18ncmp expect output
 '
 
-test_expect_success 'status with color.status' '
-       test_config color.status always &&
-       git status | test_decode_color >output &&
+test_expect_success TTY 'status with color.status' '
+       test_config color.status auto &&
+       test_terminal git status | test_decode_color >output &&
        test_i18ncmp expect output
 '
 
@@ -714,19 +715,19 @@ cat >expect <<\EOF
 <BLUE>??<RESET> untracked
 EOF
 
-test_expect_success 'status -s with color.ui' '
+test_expect_success TTY 'status -s with color.ui' '
 
-       git config color.ui always &&
-       git status -s | test_decode_color >output &&
+       git config color.ui auto &&
+       test_terminal git status -s | test_decode_color >output &&
        test_cmp expect output
 
 '
 
-test_expect_success 'status -s with color.status' '
+test_expect_success TTY 'status -s with color.status' '
 
        git config --unset color.ui &&
-       git config color.status always &&
-       git status -s | test_decode_color >output &&
+       git config color.status auto &&
+       test_terminal git status -s | test_decode_color >output &&
        test_cmp expect output
 
 '
@@ -741,9 +742,9 @@ cat >expect <<\EOF
 <BLUE>??<RESET> untracked
 EOF
 
-test_expect_success 'status -s -b with color.status' '
+test_expect_success TTY 'status -s -b with color.status' '
 
-       git status -s -b | test_decode_color >output &&
+       test_terminal git status -s -b | test_decode_color >output &&
        test_i18ncmp expect output
 
 '
@@ -757,20 +758,20 @@ A  dir2/added
 ?? untracked
 EOF
 
-test_expect_success 'status --porcelain ignores color.ui' '
+test_expect_success TTY 'status --porcelain ignores color.ui' '
 
        git config --unset color.status &&
-       git config color.ui always &&
-       git status --porcelain | test_decode_color >output &&
+       git config color.ui auto &&
+       test_terminal git status --porcelain | test_decode_color >output &&
        test_cmp expect output
 
 '
 
-test_expect_success 'status --porcelain ignores color.status' '
+test_expect_success TTY 'status --porcelain ignores color.status' '
 
        git config --unset color.ui &&
-       git config color.status always &&
-       git status --porcelain | test_decode_color >output &&
+       git config color.status auto &&
+       test_terminal git status --porcelain | test_decode_color >output &&
        test_cmp expect output
 
 '
index 2ebda509ac337f99c7ab5651734a5b20d4a0b6f4..80194b79f90c800e7aaeecca9cd502e3ade494b4 100755 (executable)
@@ -774,4 +774,19 @@ test_expect_success 'merge can be completed with --continue' '
        verify_parents $c0 $c1
 '
 
+write_script .git/FAKE_EDITOR <<EOF
+# kill -TERM command added below.
+EOF
+
+test_expect_success EXECKEEPSPID 'killed merge can be completed with --continue' '
+       git reset --hard c0 &&
+       ! "$SHELL_PATH" -c '\''
+         echo kill -TERM $$ >> .git/FAKE_EDITOR
+         GIT_EDITOR=.git/FAKE_EDITOR
+         export GIT_EDITOR
+         exec git merge --no-ff --edit c1'\'' &&
+       git merge --continue &&
+       verify_parents $c0 $c1
+'
+
 test_done
index f1063878205cfb9b0af8e54d997040ddb65bc27e..2a6679c2f596fb13a34786a4aa4b954e61c61113 100755 (executable)
@@ -374,6 +374,11 @@ test_expect_success 'grep -L -C' '
        test_cmp expected actual
 '
 
+test_expect_success 'grep --files-without-match --quiet' '
+       git grep --files-without-match --quiet nonexistent_string >actual &&
+       test_cmp /dev/null actual
+'
+
 cat >expected <<EOF
 file:foo mmap bar_mmap
 EOF
index d8242e467eaa4f0a46cfa0a4ad431a447e58dd6c..0f86c191745d65c88c70881c6520685289bc2405 100755 (executable)
@@ -51,6 +51,11 @@ test_expect_success '--path=<path> complains without --textconv/--filters' '
        grep "path.*needs.*filters" err
 '
 
+test_expect_success '--textconv/--filters complain without path' '
+       test_must_fail git cat-file --textconv HEAD &&
+       test_must_fail git cat-file --filters HEAD
+'
+
 test_expect_success 'cat-file --textconv --batch works' '
        sha1=$(git rev-parse -q --verify HEAD:world.txt) &&
        test_config diff.txt.textconv "tr A-Za-z N-ZA-Mn-za-m <" &&
index d1e4e8ad19f3d3e005e177b98e4eee16f4ef1461..f30980895c2f1b93317870e6b471d67bc99b0fd2 100755 (executable)
@@ -148,6 +148,8 @@ cat >expected-cc <<\EOF
 !two@example.com!
 !three@example.com!
 !four@example.com!
+!five@example.com!
+!six@example.com!
 EOF
 "
 
@@ -161,6 +163,8 @@ test_expect_success $PREREQ 'cc trailer with various syntax' '
        Cc: <two@example.com> # trailing comments are ignored
        Cc: <three@example.com>, <not.four@example.com> one address per line
        Cc: "Some # Body" <four@example.com> [ <also.a.comment> ]
+       Cc: five@example.com # not.six@example.com
+       Cc: six@example.com, not.seven@example.com
        EOF
        clean_fake_sendmail &&
        git send-email -1 --to=recipient@example.com \
index 67b8c50a5ab431345de2909209811fc8e4f12548..d47560b6343db7006461259e4808837f3d35eecb 100755 (executable)
@@ -3120,4 +3120,146 @@ test_expect_success 'U: validate root delete result' '
        compare_diff_raw expect actual
 '
 
+###
+### series V (checkpoint)
+###
+
+# The commands in input_file should not produce any output on the file
+# descriptor set with --cat-blob-fd (or stdout if unspecified).
+#
+# To make sure you're observing the side effects of checkpoint *before*
+# fast-import terminates (and thus writes out its state), check that the
+# fast-import process is still running using background_import_still_running
+# *after* evaluating the test conditions.
+background_import_then_checkpoint () {
+       options=$1
+       input_file=$2
+
+       mkfifo V.input
+       exec 8<>V.input
+       rm V.input
+
+       mkfifo V.output
+       exec 9<>V.output
+       rm V.output
+
+       git fast-import $options <&8 >&9 &
+       echo $! >V.pid
+       # We don't mind if fast-import has already died by the time the test
+       # ends.
+       test_when_finished "exec 8>&-; exec 9>&-; kill $(cat V.pid) || true"
+
+       # Start in the background to ensure we adhere strictly to (blocking)
+       # pipes writing sequence. We want to assume that the write below could
+       # block, e.g. if fast-import blocks writing its own output to &9
+       # because there is no reader on &9 yet.
+       (
+               cat "$input_file"
+               echo "checkpoint"
+               echo "progress checkpoint"
+       ) >&8 &
+
+       error=1 ;# assume the worst
+       while read output <&9
+       do
+               if test "$output" = "progress checkpoint"
+               then
+                       error=0
+                       break
+               fi
+               # otherwise ignore cruft
+               echo >&2 "cruft: $output"
+       done
+
+       if test $error -eq 1
+       then
+               false
+       fi
+}
+
+background_import_still_running () {
+       if ! kill -0 "$(cat V.pid)"
+       then
+               echo >&2 "background fast-import terminated too early"
+               false
+       fi
+}
+
+test_expect_success PIPE 'V: checkpoint helper does not get stuck with extra output' '
+       cat >input <<-INPUT_END &&
+       progress foo
+       progress bar
+
+       INPUT_END
+
+       background_import_then_checkpoint "" input &&
+       background_import_still_running
+'
+
+test_expect_success PIPE 'V: checkpoint updates refs after reset' '
+       cat >input <<-\INPUT_END &&
+       reset refs/heads/V
+       from refs/heads/U
+
+       INPUT_END
+
+       background_import_then_checkpoint "" input &&
+       test "$(git rev-parse --verify V)" = "$(git rev-parse --verify U)" &&
+       background_import_still_running
+'
+
+test_expect_success PIPE 'V: checkpoint updates refs and marks after commit' '
+       cat >input <<-INPUT_END &&
+       commit refs/heads/V
+       mark :1
+       committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+       data 0
+       from refs/heads/U
+
+       INPUT_END
+
+       background_import_then_checkpoint "--export-marks=marks.actual" input &&
+
+       echo ":1 $(git rev-parse --verify V)" >marks.expected &&
+
+       test "$(git rev-parse --verify V^)" = "$(git rev-parse --verify U)" &&
+       test_cmp marks.expected marks.actual &&
+       background_import_still_running
+'
+
+# Re-create the exact same commit, but on a different branch: no new object is
+# created in the database, but the refs and marks still need to be updated.
+test_expect_success PIPE 'V: checkpoint updates refs and marks after commit (no new objects)' '
+       cat >input <<-INPUT_END &&
+       commit refs/heads/V2
+       mark :2
+       committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+       data 0
+       from refs/heads/U
+
+       INPUT_END
+
+       background_import_then_checkpoint "--export-marks=marks.actual" input &&
+
+       echo ":2 $(git rev-parse --verify V2)" >marks.expected &&
+
+       test "$(git rev-parse --verify V2)" = "$(git rev-parse --verify V)" &&
+       test_cmp marks.expected marks.actual &&
+       background_import_still_running
+'
+
+test_expect_success PIPE 'V: checkpoint updates tags after tag' '
+       cat >input <<-INPUT_END &&
+       tag Vtag
+       from refs/heads/V
+       tagger $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+       data 0
+
+       INPUT_END
+
+       background_import_then_checkpoint "" input &&
+       git show-ref -d Vtag &&
+       background_import_still_running
+'
+
 test_done
index 8dcb05c4a5711e95bb64d8ba310e3490744fc015..866ddf60581e3fea1afdbe28e71e7f3137da5722 100755 (executable)
@@ -234,7 +234,7 @@ test_expect_success 'fast-export -C -C | fast-import' '
        mkdir new &&
        git --git-dir=new/.git init &&
        git fast-export -C -C --signed-tags=strip --all > output &&
-       grep "^C file6 file7\$" output &&
+       grep "^C file2 file4\$" output &&
        cat output |
        (cd new &&
         git fast-import &&
@@ -522,4 +522,22 @@ test_expect_success 'delete refspec' '
        test_cmp expected actual
 '
 
+test_expect_success 'when using -C, do not declare copy when source of copy is also modified' '
+       test_create_repo src &&
+       echo a_line >src/file.txt &&
+       git -C src add file.txt &&
+       git -C src commit -m 1st_commit &&
+
+       cp src/file.txt src/file2.txt &&
+       echo another_line >>src/file.txt &&
+       git -C src add file.txt file2.txt &&
+       git -C src commit -m 2nd_commit &&
+
+       test_create_repo dst &&
+       git -C src fast-export --all -C | git -C dst fast-import &&
+       git -C src show >expected &&
+       git -C dst show >actual &&
+       test_cmp expected actual
+'
+
 test_done
index 432c61d246c938192a2b31f2db35f4f9b320a788..c30660d60626c886dfa5993acddaebf2d3364de9 100755 (executable)
@@ -588,4 +588,52 @@ test_expect_success 'cvs annotate' '
     test_cmp ../expect ../actual
 '
 
+#------------
+# running via git-shell
+#------------
+
+cd "$WORKDIR"
+
+test_expect_success 'create remote-cvs helper' '
+       write_script remote-cvs <<-\EOF
+       exec git shell -c "cvs server"
+       EOF
+'
+
+test_expect_success 'cvs server does not run with vanilla git-shell' '
+       (
+               cd cvswork &&
+               CVS_SERVER=$WORKDIR/remote-cvs &&
+               export CVS_SERVER &&
+               test_must_fail cvs log merge
+       )
+'
+
+test_expect_success 'configure git shell to run cvs server' '
+       mkdir "$HOME"/git-shell-commands &&
+
+       write_script "$HOME"/git-shell-commands/cvs <<-\EOF &&
+       if ! test $# = 1 && test "$1" = "server"
+       then
+               echo >&2 "git-cvsserver only handles \"server\""
+               exit 1
+       fi
+       exec git cvsserver server
+       EOF
+
+       # Should not be used, but part of the recommended setup
+       write_script "$HOME"/git-shell-commands/no-interactive-login <<-\EOF
+       echo Interactive login forbidden
+       EOF
+'
+
+test_expect_success 'cvs server can run with recommended config' '
+       (
+               cd cvswork &&
+               CVS_SERVER=$WORKDIR/remote-cvs &&
+               export CVS_SERVER &&
+               cvs log merge
+       )
+'
+
 test_done
index 1b6e53f78aef40673354e5f1911d78808ae8ef4d..5fbd8d4a90b3b88cf57ca53c6b1fe99d5a957460 100644 (file)
@@ -99,7 +99,6 @@ unset VISUAL EMAIL LANGUAGE COLUMNS $("$PERL_PATH" -e '
        my $ok = join("|", qw(
                TRACE
                DEBUG
-               USE_LOOKUP
                TEST
                .*_TEST
                PROVE
@@ -991,9 +990,6 @@ case $uname_s in
        find () {
                /usr/bin/find "$@"
        }
-       sum () {
-               md5sum "$@"
-       }
        # git sees Windows-style pwd
        pwd () {
                builtin pwd -W
index 96b6a03e1c93c9ab6df356c2aad02514232f76ea..46bf6184798442560ad3ae7f68a7972680c5f8eb 100755 (executable)
@@ -80,6 +80,7 @@ sub copy_stdio {
 if ($#ARGV < 1) {
        die "usage: test-terminal program args";
 }
+$ENV{TERM} = 'vt100';
 my $master_in = new IO::Pty;
 my $master_out = new IO::Pty;
 my $master_err = new IO::Pty;
diff --git a/tag.c b/tag.c
index 47f60ae151c2cfd9855d1b6f1660ec2ba178bec3..a3ffffdbfad8022937028a986f690a6e11002531 100644 (file)
--- a/tag.c
+++ b/tag.c
@@ -142,13 +142,13 @@ int parse_tag_buffer(struct tag *item, const void *data, unsigned long size)
        bufptr = nl + 1;
 
        if (!strcmp(type, blob_type)) {
-               item->tagged = &lookup_blob(&oid)->object;
+               item->tagged = (struct object *)lookup_blob(&oid);
        } else if (!strcmp(type, tree_type)) {
-               item->tagged = &lookup_tree(&oid)->object;
+               item->tagged = (struct object *)lookup_tree(&oid);
        } else if (!strcmp(type, commit_type)) {
-               item->tagged = &lookup_commit(&oid)->object;
+               item->tagged = (struct object *)lookup_commit(&oid);
        } else if (!strcmp(type, tag_type)) {
-               item->tagged = &lookup_tag(&oid)->object;
+               item->tagged = (struct object *)lookup_tag(&oid);
        } else {
                error("Unknown type %s", type);
                item->tagged = NULL;
index 2c1502f719a17abaef6c5c56439c560994b45d37..d31466722091c600bcb42420f5e4f38e6763b0fd 100644 (file)
@@ -38,7 +38,7 @@ IPATTERN("fortran",
         "|//|\\*\\*|::|[/<>=]="),
 IPATTERN("fountain", "^((\\.[^.]|(int|ext|est|int\\.?/ext|i/e)[. ]).*)$",
         "[^ \t-]+"),
-PATTERNS("html", "^[ \t]*(<[Hh][1-6][ \t].*>.*)$",
+PATTERNS("html", "^[ \t]*(<[Hh][1-6]([ \t].*)?>.*)$",
         "[^<>= \t]+"),
 PATTERNS("java",
         "!^[ \t]*(catch|do|for|if|instanceof|new|return|switch|throw|while)\n"
index 5a89db30e3ffcb64ee25597fe014592929e07abb..3fd047a8b82b1c2a6b32ec0a5ded3d67913b5be0 100644 (file)
@@ -6,7 +6,6 @@
 #include "cache.h"
 #include "quote.h"
 #include "fast_export.h"
-#include "repo_tree.h"
 #include "strbuf.h"
 #include "svndiff.h"
 #include "sliding_window.h"
@@ -210,7 +209,7 @@ static long apply_delta(off_t len, struct line_buffer *input,
                        die("invalid cat-blob response: %s", response);
                check_preimage_overflow(preimage.max_off, 1);
        }
-       if (old_mode == REPO_MODE_LNK) {
+       if (old_mode == S_IFLNK) {
                strbuf_addstr(&preimage.buf, "link ");
                check_preimage_overflow(preimage.max_off, strlen("link "));
                preimage.max_off += strlen("link ");
@@ -244,7 +243,7 @@ void fast_export_buf_to_data(const struct strbuf *data)
 void fast_export_data(uint32_t mode, off_t len, struct line_buffer *input)
 {
        assert(len >= 0);
-       if (mode == REPO_MODE_LNK) {
+       if (mode == S_IFLNK) {
                /* svn symlink blobs start with "link " */
                if (len < 5)
                        die("invalid dump: symlink too short for \"link\" prefix");
@@ -312,6 +311,40 @@ int fast_export_ls(const char *path, uint32_t *mode, struct strbuf *dataref)
        return parse_ls_response(get_response_line(), mode, dataref);
 }
 
+const char *fast_export_read_path(const char *path, uint32_t *mode_out)
+{
+       int err;
+       static struct strbuf buf = STRBUF_INIT;
+
+       strbuf_reset(&buf);
+       err = fast_export_ls(path, mode_out, &buf);
+       if (err) {
+               if (errno != ENOENT)
+                       die_errno("BUG: unexpected fast_export_ls error");
+               /* Treat missing paths as directories. */
+               *mode_out = S_IFDIR;
+               return NULL;
+       }
+       return buf.buf;
+}
+
+void fast_export_copy(uint32_t revision, const char *src, const char *dst)
+{
+       int err;
+       uint32_t mode;
+       static struct strbuf data = STRBUF_INIT;
+
+       strbuf_reset(&data);
+       err = fast_export_ls_rev(revision, src, &mode, &data);
+       if (err) {
+               if (errno != ENOENT)
+                       die_errno("BUG: unexpected fast_export_ls_rev error");
+               fast_export_delete(dst);
+               return;
+       }
+       fast_export_modify(dst, mode, data.buf);
+}
+
 void fast_export_blob_delta(uint32_t mode,
                                uint32_t old_mode, const char *old_data,
                                off_t len, struct line_buffer *input)
@@ -320,7 +353,7 @@ void fast_export_blob_delta(uint32_t mode,
 
        assert(len >= 0);
        postimage_len = apply_delta(len, input, old_data, old_mode);
-       if (mode == REPO_MODE_LNK) {
+       if (mode == S_IFLNK) {
                buffer_skip_bytes(&postimage, strlen("link "));
                postimage_len -= strlen("link ");
        }
index b9a3b71c99fd59312f493d6b1eb24c9a0b44578c..60b79c35b97cbdc9589fe3778ac1f4b5f61646ff 100644 (file)
@@ -28,4 +28,7 @@ int fast_export_ls_rev(uint32_t rev, const char *path,
 int fast_export_ls(const char *path,
                        uint32_t *mode_out, struct strbuf *dataref_out);
 
+void fast_export_copy(uint32_t revision, const char *src, const char *dst);
+const char *fast_export_read_path(const char *path, uint32_t *mode_out);
+
 #endif
diff --git a/vcs-svn/repo_tree.c b/vcs-svn/repo_tree.c
deleted file mode 100644 (file)
index 67d27f0..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed under a two-clause BSD-style license.
- * See LICENSE for details.
- */
-
-#include "git-compat-util.h"
-#include "strbuf.h"
-#include "repo_tree.h"
-#include "fast_export.h"
-
-const char *repo_read_path(const char *path, uint32_t *mode_out)
-{
-       int err;
-       static struct strbuf buf = STRBUF_INIT;
-
-       strbuf_reset(&buf);
-       err = fast_export_ls(path, mode_out, &buf);
-       if (err) {
-               if (errno != ENOENT)
-                       die_errno("BUG: unexpected fast_export_ls error");
-               /* Treat missing paths as directories. */
-               *mode_out = REPO_MODE_DIR;
-               return NULL;
-       }
-       return buf.buf;
-}
-
-void repo_copy(uint32_t revision, const char *src, const char *dst)
-{
-       int err;
-       uint32_t mode;
-       static struct strbuf data = STRBUF_INIT;
-
-       strbuf_reset(&data);
-       err = fast_export_ls_rev(revision, src, &mode, &data);
-       if (err) {
-               if (errno != ENOENT)
-                       die_errno("BUG: unexpected fast_export_ls_rev error");
-               fast_export_delete(dst);
-               return;
-       }
-       fast_export_modify(dst, mode, data.buf);
-}
-
-void repo_delete(const char *path)
-{
-       fast_export_delete(path);
-}
diff --git a/vcs-svn/repo_tree.h b/vcs-svn/repo_tree.h
deleted file mode 100644 (file)
index 889c6a3..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef REPO_TREE_H_
-#define REPO_TREE_H_
-
-struct strbuf;
-
-#define REPO_MODE_DIR 0040000
-#define REPO_MODE_BLB 0100644
-#define REPO_MODE_EXE 0100755
-#define REPO_MODE_LNK 0120000
-
-uint32_t next_blob_mark(void);
-void repo_copy(uint32_t revision, const char *src, const char *dst);
-void repo_add(const char *path, uint32_t mode, uint32_t blob_mark);
-const char *repo_read_path(const char *path, uint32_t *mode_out);
-void repo_delete(const char *path);
-void repo_commit(uint32_t revision, const char *author,
-               const struct strbuf *log, const char *uuid, const char *url,
-               long unsigned timestamp);
-void repo_diff(uint32_t r1, uint32_t r2);
-void repo_init(void);
-void repo_reset(void);
-
-#endif
index 1846685a21a44decfe5790f0020dcf933c8d6583..ec6b350611d367fd75f909c4695d9faf2d68f91e 100644 (file)
@@ -8,7 +8,6 @@
  */
 
 #include "cache.h"
-#include "repo_tree.h"
 #include "fast_export.h"
 #include "line_buffer.h"
 #include "strbuf.h"
@@ -134,13 +133,13 @@ static void handle_property(const struct strbuf *key_buf,
                        die("invalid dump: sets type twice");
                }
                if (!val) {
-                       node_ctx.type = REPO_MODE_BLB;
+                       node_ctx.type = S_IFREG | 0644;
                        return;
                }
                *type_set = 1;
                node_ctx.type = keylen == strlen("svn:executable") ?
-                               REPO_MODE_EXE :
-                               REPO_MODE_LNK;
+                               (S_IFREG | 0755) :
+                               S_IFLNK;
        }
 }
 
@@ -219,45 +218,45 @@ static void handle_node(void)
         */
        static const char *const empty_blob = "::empty::";
        const char *old_data = NULL;
-       uint32_t old_mode = REPO_MODE_BLB;
+       uint32_t old_mode = S_IFREG | 0644;
 
        if (node_ctx.action == NODEACT_DELETE) {
                if (have_text || have_props || node_ctx.srcRev)
                        die("invalid dump: deletion node has "
                                "copyfrom info, text, or properties");
-               repo_delete(node_ctx.dst.buf);
+               fast_export_delete(node_ctx.dst.buf);
                return;
        }
        if (node_ctx.action == NODEACT_REPLACE) {
-               repo_delete(node_ctx.dst.buf);
+               fast_export_delete(node_ctx.dst.buf);
                node_ctx.action = NODEACT_ADD;
        }
        if (node_ctx.srcRev) {
-               repo_copy(node_ctx.srcRev, node_ctx.src.buf, node_ctx.dst.buf);
+               fast_export_copy(node_ctx.srcRev, node_ctx.src.buf, node_ctx.dst.buf);
                if (node_ctx.action == NODEACT_ADD)
                        node_ctx.action = NODEACT_CHANGE;
        }
-       if (have_text && type == REPO_MODE_DIR)
+       if (have_text && type == S_IFDIR)
                die("invalid dump: directories cannot have text attached");
 
        /*
         * Find old content (old_data) and decide on the new mode.
         */
        if (node_ctx.action == NODEACT_CHANGE && !*node_ctx.dst.buf) {
-               if (type != REPO_MODE_DIR)
+               if (type != S_IFDIR)
                        die("invalid dump: root of tree is not a regular file");
                old_data = NULL;
        } else if (node_ctx.action == NODEACT_CHANGE) {
                uint32_t mode;
-               old_data = repo_read_path(node_ctx.dst.buf, &mode);
-               if (mode == REPO_MODE_DIR && type != REPO_MODE_DIR)
+               old_data = fast_export_read_path(node_ctx.dst.buf, &mode);
+               if (mode == S_IFDIR && type != S_IFDIR)
                        die("invalid dump: cannot modify a directory into a file");
-               if (mode != REPO_MODE_DIR && type == REPO_MODE_DIR)
+               if (mode != S_IFDIR && type == S_IFDIR)
                        die("invalid dump: cannot modify a file into a directory");
                node_ctx.type = mode;
                old_mode = mode;
        } else if (node_ctx.action == NODEACT_ADD) {
-               if (type == REPO_MODE_DIR)
+               if (type == S_IFDIR)
                        old_data = NULL;
                else if (have_text)
                        old_data = empty_blob;
@@ -280,7 +279,7 @@ static void handle_node(void)
        /*
         * Save the result.
         */
-       if (type == REPO_MODE_DIR)      /* directories are not tracked. */
+       if (type == S_IFDIR)    /* directories are not tracked. */
                return;
        assert(old_data);
        if (old_data == empty_blob)
@@ -385,9 +384,9 @@ void svndump_read(const char *url, const char *local_ref, const char *notes_ref)
                                continue;
                        strbuf_addf(&rev_ctx.note, "%s\n", t);
                        if (!strcmp(val, "dir"))
-                               node_ctx.type = REPO_MODE_DIR;
+                               node_ctx.type = S_IFDIR;
                        else if (!strcmp(val, "file"))
-                               node_ctx.type = REPO_MODE_BLB;
+                               node_ctx.type = S_IFREG | 0644;
                        else
                                fprintf(stderr, "Unknown node-kind: %s\n", val);
                        break;
index e28ffbeb096a85d67b2e885c48ab096340b5d295..c0c5a2b3735c89fc98d7aa29863eb4a28651d808 100644 (file)
@@ -30,7 +30,7 @@ static void add_head_info(struct worktree *wt)
 
        target = refs_resolve_ref_unsafe(get_worktree_ref_store(wt),
                                         "HEAD",
-                                        RESOLVE_REF_READING,
+                                        0,
                                         wt->head_sha1, &flags);
        if (!target)
                return;