Merge branch 'jc/run-receive-hook-cleanup' into maint
authorJunio C Hamano <gitster@pobox.com>
Wed, 26 Oct 2011 23:13:31 +0000 (16:13 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 26 Oct 2011 23:13:31 +0000 (16:13 -0700)
* jc/run-receive-hook-cleanup:
refactor run_receive_hook()

86 files changed:
Documentation/RelNotes/1.7.6.3.txt [new file with mode: 0644]
Documentation/RelNotes/1.7.6.4.txt [new file with mode: 0644]
Documentation/RelNotes/1.7.7.1.txt [new file with mode: 0644]
Documentation/RelNotes/1.7.7.txt
Documentation/SubmittingPatches
Documentation/config.txt
Documentation/diff-options.txt
Documentation/git-mergetool.txt
Documentation/git-read-tree.txt
Documentation/git-remote-helpers.txt
Documentation/git-remote-testgit.txt [new file with mode: 0644]
Documentation/git-svn.txt
Documentation/git-update-index.txt
Documentation/git.txt
Documentation/gitnamespaces.txt
Documentation/howto/maintain-git.txt
GIT-VERSION-GEN
Makefile
RelNotes
branch.c
branch.h
builtin/apply.c
builtin/archive.c
builtin/branch.c
builtin/bundle.c
builtin/checkout.c
builtin/commit.c
builtin/config.c
builtin/fetch.c
builtin/fmt-merge-msg.c
builtin/fsck.c
builtin/grep.c
builtin/log.c
builtin/merge.c
builtin/patch-id.c
builtin/remote.c
bundle.c
bundle.h
commit.c
commit.h
contrib/hooks/post-receive-email
date.c
diff-lib.c
diff.c
git-filter-branch.sh
git-merge-one-file.sh
git-mergetool--lib.sh
git-mergetool.sh
git-rebase--interactive.sh
git-remote-testgit.py
git-svn.perl
gitweb/static/js/javascript-detection.js
http-push.c
merge-recursive.c
notes-merge.c
revision.c
revision.h
strbuf.c
submodule.c
t/t0006-date.sh
t/t1300-repo-config.sh
t/t1304-default-acl.sh
t/t2022-checkout-paths.sh [new file with mode: 0755]
t/t3200-branch.sh
t/t3404-rebase-interactive.sh
t/t4014-format-patch.sh
t/t4254-am-corrupt.sh [new file with mode: 0755]
t/t5505-remote.sh
t/t6019-rev-list-ancestry-path.sh
t/t7607-merge-overwrite.sh
t/t7609-merge-co-error-msgs.sh
t/t7610-mergetool.sh
t/t9159-git-svn-no-parent-mergeinfo.sh
t/t9161-git-svn-mergeinfo-push.sh [new file with mode: 0755]
t/t9161/branches.dump [new file with mode: 0644]
t/test-lib.sh
templates/hooks--post-commit.sample [deleted file]
templates/hooks--post-receive.sample [deleted file]
templates/hooks--pre-commit.sample
transport.c
tree-walk.c
tree-walk.h
unpack-trees.c
unpack-trees.h
wt-status.c
xdiff/xprepare.c
diff --git a/Documentation/RelNotes/1.7.6.3.txt b/Documentation/RelNotes/1.7.6.3.txt
new file mode 100644 (file)
index 0000000..9597183
--- /dev/null
@@ -0,0 +1,24 @@
+Git v1.7.6.3 Release Notes
+==========================
+
+Fixes since v1.7.6.2
+--------------------
+
+ * "git -c var=value subcmd" misparsed the custom configuration when
+   value contained an equal sign.
+
+ * "git fetch" had a major performance regression, wasting many
+   needless cycles in a repository where there is no submodules
+   present. This was especially bad, when there were many refs.
+
+ * "git reflog $refname" did not default to the "show" subcommand as
+   the documentation advertised the command to do.
+
+ * "git reset" did not leave meaningful log message in the reflog.
+
+ * "git status --ignored" did not show ignored items when there is no
+   untracked items.
+
+ * "git tag --contains $commit" was unnecessarily inefficient.
+
+Also contains minor fixes and documentation updates.
diff --git a/Documentation/RelNotes/1.7.6.4.txt b/Documentation/RelNotes/1.7.6.4.txt
new file mode 100644 (file)
index 0000000..e19acac
--- /dev/null
@@ -0,0 +1,32 @@
+Git v1.7.6.4 Release Notes
+==========================
+
+Fixes since v1.7.6.3
+--------------------
+
+ * The error reporting logic of "git am" when the command is fed a file
+   whose mail-storage format is unknown was fixed.
+
+ * "git branch --set-upstream @{-1} foo" did not expand @{-1} correctly.
+
+ * "git check-ref-format --print" used to parrot a candidate string that
+   began with a slash (e.g. /refs/heads/master) without stripping it, to make
+   the result a suitably normalized string the caller can append to "$GIT_DIR/".
+
+ * "git clone" failed to clone locally from a ".git" file that itself
+   is not a directory but is a pointer to one.
+
+ * "git clone" from a local repository that borrows from another
+   object store using a relative path in its objects/info/alternates
+   file did not adjust the alternates in the resulting repository.
+
+ * "git describe --dirty" did not refresh the index before checking the
+   state of the working tree files.
+
+ * "git ls-files ../$path" that is run from a subdirectory reported errors
+   incorrectly when there is no such path that matches the given pathspec.
+
+ * "git mergetool" could loop forever prompting when nothing can be read
+   from the standard input.
+
+Also contains minor fixes and documentation updates.
diff --git a/Documentation/RelNotes/1.7.7.1.txt b/Documentation/RelNotes/1.7.7.1.txt
new file mode 100644 (file)
index 0000000..ac9b838
--- /dev/null
@@ -0,0 +1,60 @@
+Git v1.7.7.1 Release Notes
+==========================
+
+Fixes since v1.7.7
+------------------
+
+ * On some BSD systems, adding +s bit on directories is detrimental
+   (it is not necessary on BSD to begin with). "git init --shared"
+   has been updated to take this into account without extra makefile
+   settings on platforms the Makefile knows about.
+
+ * After incorrectly written third-party tools store a tag object in
+   HEAD, git diagnosed it as a repository corruption and refused to
+   proceed in order to avoid spreading the damage. We now gracefully
+   recover from such a situation by pretending as if the commit that
+   is pointed at by the tag were in HEAD.
+
+ * "git apply --whitespace=error" did not bother to report the exact
+   line number in the patch that introduced new blank lines at the end
+   of the file.
+
+ * "git apply --index" did not check corrupted patch.
+
+ * "git checkout $tree $directory/" resurrected paths locally removed or
+   modified only in the working tree in $directory/ that did not appear
+   in $directory of the given $tree. They should have been kept intact.
+
+ * "git diff $tree $path" used to apply the pathspec at the output stage,
+   reading the whole tree, wasting resources.
+
+ * The code to check for updated submodules during a "git fetch" of the
+   superproject had an unnecessary quadratic loop.
+
+ * "git fetch" from a large bundle did not enable the progress output.
+
+ * When "git fsck --lost-and-found" found that an empty blob object in the
+   object store is unreachable, it incorrectly reported an error after
+   writing the lost blob out successfully.
+
+ * "git filter-branch" did not refresh the index before checking that the
+   working tree was clean.
+
+ * "git grep $tree" when run with multiple threads had an unsafe access to
+   the object database that should have been protected with mutex.
+
+ * The "--ancestry-path" option to "git log" and friends misbehaved in a
+   history with complex criss-cross merges and showed an uninteresting
+   side history as well.
+
+ * Test t1304 assumed LOGNAME is always set, which may not be true on
+   some systems.
+
+ * Tests with --valgrind failed to find "mergetool" scriptlets.
+
+ * "git patch-id" miscomputed the patch-id in a patch that has a line longer
+   than 1kB.
+
+ * When an "exec" insn failed after modifying the index and/or the working
+   tree during "rebase -i", we now check and warn that the changes need to
+   be cleaned up.
index d81995622d8bda7b53c87a8974d8b69d10da4a71..7655cccfaa1585a14257b5a86d663f501c06bf1d 100644 (file)
@@ -8,7 +8,7 @@ Updates since v1.7.6
 
  * Interix, Cygwin and Minix ports got updated.
 
- * Various updates git-p4 (in contrib/), fast-import, and git-svn.
+ * Various updates to git-p4 (in contrib/), fast-import, and git-svn.
 
  * Gitweb learned to read from /etc/gitweb-common.conf when it exists,
    before reading from gitweb_config.perl or from /etc/gitweb.conf
@@ -20,7 +20,7 @@ Updates since v1.7.6
    platforms with 64-bit long, which has been corrected.
 
  * Git now recognizes loose objects written by other implementations that
-   uses non-standard window size for zlib deflation (e.g. Agit running on
+   use a non-standard window size for zlib deflation (e.g. Agit running on
    Android with 4kb window). We used to reject anything that was not
    deflated with 32kb window.
 
@@ -28,59 +28,59 @@ Updates since v1.7.6
    been improved, especially when a command that is not built-in was
    involved.
 
- * "git am" learned to pass "--exclude=<path>" option through to underlying
+ * "git am" learned to pass the "--exclude=<path>" option through to underlying
    "git apply".
 
- * You can now feed many empty lines before feeding a mbox file to
+ * You can now feed many empty lines before feeding an mbox file to
    "git am".
 
  * "git archive" can be told to pass the output to gzip compression and
    produce "archive.tar.gz".
 
- * "git bisect" can be used in a bare repository (provided if the test
+ * "git bisect" can be used in a bare repository (provided that the test
    you perform per each iteration does not need a working tree, of
    course).
 
  * The length of abbreviated object names in "git branch -v" output
-   now honors core.abbrev configuration variable.
+   now honors the core.abbrev configuration variable.
 
  * "git check-attr" can take relative paths from the command line.
 
- * "git check-attr" learned "--all" option to list the attributes for a
+ * "git check-attr" learned an "--all" option to list the attributes for a
    given path.
 
  * "git checkout" (both the code to update the files upon checking out a
-   different branch, the code to checkout specific set of files) learned
+   different branch and the code to checkout a specific set of files) learned
    to stream the data from object store when possible, without having to
-   read the entire contents of a file in memory first. An earlier round
+   read the entire contents of a file into memory first. An earlier round
    of this code that is not in any released version had a large leak but
    now it has been plugged.
 
- * "git clone" can now take "--config key=value" option to set the
+ * "git clone" can now take "--config key=value" option to set the
    repository configuration options that affect the initial checkout.
 
  * "git commit <paths>..." now lets you feed relative pathspecs that
-   refer outside your current subdirectory.
+   refer to outside your current subdirectory.
 
- * "git diff --stat" learned --stat-count option to limit the output of
-   diffstat report.
+ * "git diff --stat" learned --stat-count option to limit the output of
+   diffstat report.
 
- * "git diff" learned "--histogram" option, to use a different diff
+ * "git diff" learned a "--histogram" option to use a different diff
    generation machinery stolen from jgit, which might give better
    performance.
 
- * "git diff" had a wierd worst case behaviour that can be triggered
+ * "git diff" had a weird worst case behaviour that can be triggered
    when comparing files with potentially many places that could match.
 
  * "git fetch", "git push" and friends no longer show connection
-   errors for addresses that couldn't be connected when at least one
+   errors for addresses that couldn't be connected to when at least one
    address succeeds (this is arguably a regression but a deliberate
    one).
 
- * "git grep" learned --break and --heading options, to let users mimic
-   output format of "ack".
+ * "git grep" learned "--break" and "--heading" options, to let users mimic
+   the output format of "ack".
 
- * "git grep" learned "-W" option that shows wider context using the same
+ * "git grep" learned "-W" option that shows wider context using the same
    logic used by "git diff" to determine the hunk header.
 
  * Invoking the low-level "git http-fetch" without "-a" option (which
@@ -91,25 +91,25 @@ Updates since v1.7.6
    highlight grafted and replaced commits.
 
  * "git rebase master topci" no longer spews usage hints after giving
-   "fatal: no such branch: topci" error message.
+   the "fatal: no such branch: topci" error message.
 
  * The recursive merge strategy implementation got a fairly large
-   fixes for many corner cases that may rarely happen in real world
+   fix for many corner cases that may rarely happen in real world
    projects (it has been verified that none of the 16000+ merges in
    the Linux kernel history back to v2.6.12 is affected with the
    corner case bugs this update fixes).
 
- * "git stash" learned --include-untracked option.
+ * "git stash" learned an "--include-untracked option".
 
  * "git submodule update" used to stop at the first error updating a
    submodule; it now goes on to update other submodules that can be
    updated, and reports the ones with errors at the end.
 
- * "git push" can be told with --recurse-submodules=check option to
+ * "git push" can be told with the "--recurse-submodules=check" option to
    refuse pushing of the supermodule, if any of its submodules'
    commits hasn't been pushed out to their remotes.
 
- * "git upload-pack" and "git receive-pack" learned to pretend only a
+ * "git upload-pack" and "git receive-pack" learned to pretend that only a
    subset of the refs exist in a repository. This may help a site to
    put many tiny repositories into one repository (this would not be
    useful for larger repositories as repacking would be problematic).
@@ -118,7 +118,7 @@ Updates since v1.7.6
    that is more efficient in reading objects in packfiles.
 
  * test scripts for gitweb tried to run even when CGI-related perl modules
-   are not installed; it now exits early when they are unavailable.
+   are not installed; they now exit early when the latter are unavailable.
 
 Also contains various documentation updates and minor miscellaneous
 changes.
@@ -127,46 +127,8 @@ changes.
 Fixes since v1.7.6
 ------------------
 
-Unless otherwise noted, all the fixes in 1.7.6.X maintenance track are
+Unless otherwise noted, all fixes in the 1.7.6.X maintenance track are
 included in this release.
 
- * The error reporting logic of "git am" when the command is fed a file
-   whose mail-storage format is unknown was fixed.
-   (merge dff4b0e gb/maint-am-patch-format-error-message later to 'maint').
-
- * "git branch --set-upstream @{-1} foo" did not expand @{-1} correctly.
-   (merge e9d4f74 mg/branch-set-upstream-previous later to 'maint').
-
  * "git branch -m" and "git checkout -b" incorrectly allowed the tip
    of the branch that is currently checked out updated.
-   (merge 55c4a67 ci/forbid-unwanted-current-branch-update later to 'maint').
-
- * "git check-ref-format --print" used to parrot a candidate string that
-   began with a slash (e.g. /refs/heads/master) without stripping it, to make
-   the result a suitably normalized string the caller can append to "$GIT_DIR/".
-   (merge f3738c1 mh/check-ref-format-print-normalize later to 'maint').
-
- * "git clone" failed to clone locally from a ".git" file that itself
-   is not a directory but is a pointer to one.
-   (merge 9b0ebc7 nd/maint-clone-gitdir later to 'maint').
-
- * "git clone" from a local repository that borrows from another
-   object store using a relative path in its objects/info/alternates
-   file did not adjust the alternates in the resulting repository.
-   (merge e6baf4a1 jc/maint-clone-alternates later to 'maint').
-
- * "git describe --dirty" did not refresh the index before checking the
-   state of the working tree files.
-   (cherry-pick bb57148 ac/describe-dirty-refresh later to 'maint').
-
- * "git ls-files ../$path" that is run from a subdirectory reported errors
-   incorrectly when there is no such path that matches the given pathspec.
-   (merge 0f64bfa cb/maint-ls-files-error-report later to 'maint').
-
---
-exec >/var/tmp/1
-echo O=$(git describe master)
-O=v1.7.7-rc0-185-gb648557
-git log --first-parent --oneline $O..master
-echo
-git shortlog --no-merges ^maint ^$O master
index 938eccf2a5ac9dd629be1bc6bb53a59723c99083..0dbf2c9843dd3eed014d788892c8719036287308 100644 (file)
@@ -134,8 +134,7 @@ Another thing: NULL pointers shall be written as NULL, not as 0.
 
 (2) Generate your patch using git tools out of your commits.
 
-git based diff tools (git, Cogito, and StGIT included) generate
-unidiff which is the preferred format.
+git based diff tools generate unidiff which is the preferred format.
 
 You do not have to be afraid to use -M option to "git diff" or
 "git format-patch", if your patch involves file renames.  The
index 0658ffb889320d408f2cad9214e138879059c766..eae75a39c0bcc779ed2c66ef6fa9b03a24a4a2fd 100644 (file)
@@ -147,7 +147,7 @@ advice.*::
 
 core.fileMode::
        If false, the executable bit differences between the index and
-       the working copy are ignored; useful on broken filesystems like FAT.
+       the working tree are ignored; useful on broken filesystems like FAT.
        See linkgit:git-update-index[1].
 +
 The default is true, except linkgit:git-clone[1] or linkgit:git-init[1]
@@ -179,7 +179,7 @@ is created.
 
 core.trustctime::
        If false, the ctime differences between the index and the
-       working copy are ignored; useful when the inode change time
+       working tree are ignored; useful when the inode change time
        is regularly modified by something outside Git (file system
        crawlers and some backup systems).
        See linkgit:git-update-index[1]. True by default.
@@ -292,7 +292,7 @@ core.ignoreStat::
        If true, commands which modify both the working tree and the index
        will mark the updated paths with the "assume unchanged" bit in the
        index. These marked files are then assumed to stay unchanged in the
-       working copy, until you mark them otherwise manually - Git will not
+       working tree, until you mark them otherwise manually - Git will not
        detect the file changes by lstat() calls. This is useful on systems
        where those are very slow, such as Microsoft Windows.
        See linkgit:git-update-index[1].
@@ -1453,7 +1453,8 @@ notes.rewriteRef::
        You may also specify this configuration several times.
 +
 Does not have a default value; you must configure this variable to
-enable note rewriting.
+enable note rewriting.  Set it to `refs/notes/commits` to enable
+rewriting for the default commit notes.
 +
 This setting can be overridden with the `GIT_NOTES_REWRITE_REF`
 environment variable, which must be a colon separated list of refs or
index b620b3afeca14166840fb76b4cefe1e4038fb47e..5c53bdba948ea817e01e169a9fc183d4fc2d1313 100644 (file)
@@ -45,6 +45,10 @@ ifndef::git-format-patch[]
        Synonym for `-p --raw`.
 endif::git-format-patch[]
 
+--minimal::
+       Spend extra time to make sure the smallest possible
+       diff is produced.
+
 --patience::
        Generate a diff using the "patience diff" algorithm.
 
index 347091010995af95e43ced744b159b277bdb6cdc..2a49de7cfe5188b531bc02f1115e253bfa10e0e0 100644 (file)
@@ -17,9 +17,10 @@ Use `git mergetool` to run one of several merge utilities to resolve
 merge conflicts.  It is typically run after 'git merge'.
 
 If one or more <file> parameters are given, the merge tool program will
-be run to resolve differences on each file.  If no <file> names are
-specified, 'git mergetool' will run the merge tool program on every file
-with merge conflicts.
+be run to resolve differences on each file (skipping those without
+conflicts).  Specifying a directory will include all unresolved files in
+that path.  If no <file> names are specified, 'git mergetool' will run
+the merge tool program on every file with merge conflicts.
 
 OPTIONS
 -------
index c45d53c6e150479bd01bf3d643354348d8ce9273..5375549820bd6b9fecf3540b1e60ae50e74da0e6 100644 (file)
@@ -47,7 +47,7 @@ OPTIONS
 
 -i::
        Usually a merge requires the index file as well as the
-       files in the working tree are up to date with the
+       files in the working tree to be up to date with the
        current head commit, in order not to lose local
        changes.  This flag disables the check with the working
        tree and is meant to be used when creating a merge of
@@ -71,21 +71,21 @@ OPTIONS
 --aggressive::
        Usually a three-way merge by 'git read-tree' resolves
        the merge for really trivial cases and leaves other
-       cases unresolved in the index, so that Porcelains can
+       cases unresolved in the index, so that porcelains can
        implement different merge policies.  This flag makes the
-       command to resolve a few more cases internally:
+       command resolve a few more cases internally:
 +
 * when one side removes a path and the other side leaves the path
   unmodified.  The resolution is to remove that path.
 * when both sides remove a path.  The resolution is to remove that path.
-* when both sides adds a path identically.  The resolution
+* when both sides add a path identically.  The resolution
   is to add that path.
 
 --prefix=<prefix>/::
        Keep the current index contents, and read the contents
-       of named tree-ish under directory at `<prefix>`.  The
+       of the named tree-ish under the directory at `<prefix>`. The
        original index file cannot have anything at the path
-       `<prefix>` itself, and have nothing in `<prefix>/`
+       `<prefix>` itself, nor anything in the `<prefix>/`
        directory.  Note that the `<prefix>/` value must end
        with a slash.
 
@@ -379,45 +379,45 @@ have finished your work-in-progress), attempt the merge again.
 Sparse checkout
 ---------------
 
-"Sparse checkout" allows to sparsely populate working directory.
-It uses skip-worktree bit (see linkgit:git-update-index[1]) to tell
-Git whether a file on working directory is worth looking at.
+"Sparse checkout" allows populating the working directory sparsely.
+It uses the skip-worktree bit (see linkgit:git-update-index[1]) to tell
+Git whether a file in the working directory is worth looking at.
 
-"git read-tree" and other merge-based commands ("git merge", "git
-checkout"...) can help maintaining skip-worktree bitmap and working
+'git read-tree' and other merge-based commands ('git merge', 'git
+checkout'...) can help maintaining the skip-worktree bitmap and working
 directory update. `$GIT_DIR/info/sparse-checkout` is used to
-define the skip-worktree reference bitmap. When "git read-tree" needs
-to update working directory, it will reset skip-worktree bit in index
+define the skip-worktree reference bitmap. When 'git read-tree' needs
+to update the working directory, it resets the skip-worktree bit in the index
 based on this file, which uses the same syntax as .gitignore files.
-If an entry matches a pattern in this file, skip-worktree will be
-set on that entry. Otherwise, skip-worktree will be unset.
+If an entry matches a pattern in this file, skip-worktree will not be
+set on that entry. Otherwise, skip-worktree will be set.
 
 Then it compares the new skip-worktree value with the previous one. If
-skip-worktree turns from unset to set, it will add the corresponding
-file back. If it turns from set to unset, that file will be removed.
+skip-worktree turns from set to unset, it will add the corresponding
+file back. If it turns from unset to set, that file will be removed.
 
 While `$GIT_DIR/info/sparse-checkout` is usually used to specify what
-files are in. You can also specify what files are _not_ in, using
-negate patterns. For example, to remove file "unwanted":
+files are in, you can also specify what files are _not_ in, using
+negate patterns. For example, to remove the file `unwanted`:
 
 ----------------
-*
+/*
 !unwanted
 ----------------
 
-Another tricky thing is fully repopulating working directory when you
+Another tricky thing is fully repopulating the working directory when you
 no longer want sparse checkout. You cannot just disable "sparse
-checkout" because skip-worktree are still in the index and you working
-directory is still sparsely populated. You should re-populate working
+checkout" because skip-worktree bits are still in the index and your working
+directory is still sparsely populated. You should re-populate the working
 directory with the `$GIT_DIR/info/sparse-checkout` file content as
 follows:
 
 ----------------
-*
+/*
 ----------------
 
-Then you can disable sparse checkout. Sparse checkout support in "git
-read-tree" and similar commands is disabled by default. You need to
+Then you can disable sparse checkout. Sparse checkout support in 'git
+read-tree' and similar commands is disabled by default. You need to
 turn `core.sparseCheckout` on in order to have sparse checkout
 support.
 
index 4f83dea5a39ca2f8e695a2426e90cf0450533696..674797cd8308801dc3e3b4f3d6f581005a0a0d2a 100644 (file)
@@ -24,22 +24,141 @@ output. Because a remote helper runs as an independent process from
 git, there is no need to re-link git to add a new helper, nor any
 need to link the helper with the implementation of git.
 
-Every helper must support the "capabilities" command, which git will
-use to determine what other commands the helper will accept.  Other
-commands generally concern facilities like discovering and updating
-remote refs, transporting objects between the object database and
-the remote repository, and updating the local object store.
-
-Helpers supporting the 'fetch' capability can discover refs from the
-remote repository and transfer objects reachable from those refs to
-the local object store. Helpers supporting the 'push' capability can
-transfer local objects to the remote repository and update remote refs.
+Every helper must support the "capabilities" command, which git
+uses to determine what other commands the helper will accept.  Those
+other commands can be used to discover and update remote refs,
+transport objects between the object database and the remote repository,
+and update the local object store.
 
 Git comes with a "curl" family of remote helpers, that handle various
 transport protocols, such as 'git-remote-http', 'git-remote-https',
 'git-remote-ftp' and 'git-remote-ftps'. They implement the capabilities
 'fetch', 'option', and 'push'.
 
+INPUT FORMAT
+------------
+
+Git sends the remote helper a list of commands on standard input, one
+per line.  The first command is always the 'capabilities' command, in
+response to which the remote helper must print a list of the
+capabilities it supports (see below) followed by a blank line.  The
+response to the capabilities command determines what commands Git uses
+in the remainder of the command stream.
+
+The command stream is terminated by a blank line.  In some cases
+(indicated in the documentation of the relevant commands), this blank
+line is followed by a payload in some other protocol (e.g., the pack
+protocol), while in others it indicates the end of input.
+
+Capabilities
+~~~~~~~~~~~~
+
+Each remote helper is expected to support only a subset of commands.
+The operations a helper supports are declared to git in the response
+to the `capabilities` command (see COMMANDS, below).
+
+'option'::
+       For specifying settings like `verbosity` (how much output to
+       write to stderr) and `depth` (how much history is wanted in the
+       case of a shallow clone) that affect how other commands are
+       carried out.
+
+'connect'::
+       For fetching and pushing using git's native packfile protocol
+       that requires a bidirectional, full-duplex connection.
+
+'push'::
+       For listing remote refs and pushing specified objects from the
+       local object store to remote refs.
+
+'fetch'::
+       For listing remote refs and fetching the associated history to
+       the local object store.
+
+'import'::
+       For listing remote refs and fetching the associated history as
+       a fast-import stream.
+
+'refspec' <refspec>::
+       This modifies the 'import' capability, allowing the produced
+       fast-import stream to modify refs in a private namespace
+       instead of writing to refs/heads or refs/remotes directly.
+       It is recommended that all importers providing the 'import'
+       capability use this.
++
+A helper advertising the capability
+`refspec refs/heads/{asterisk}:refs/svn/origin/branches/{asterisk}`
+is saying that, when it is asked to `import refs/heads/topic`, the
+stream it outputs will update the `refs/svn/origin/branches/topic`
+ref.
++
+This capability can be advertised multiple times.  The first
+applicable refspec takes precedence.  The left-hand of refspecs
+advertised with this capability must cover all refs reported by
+the list command.  If no 'refspec' capability is advertised,
+there is an implied `refspec {asterisk}:{asterisk}`.
+
+Capabilities for Pushing
+~~~~~~~~~~~~~~~~~~~~~~~~
+'connect'::
+       Can attempt to connect to 'git receive-pack' (for pushing),
+       'git upload-pack', etc for communication using the
+       packfile protocol.
++
+Supported commands: 'connect'.
+
+'push'::
+       Can discover remote refs and push local commits and the
+       history leading up to them to new or existing remote refs.
++
+Supported commands: 'list for-push', 'push'.
+
+If a helper advertises both 'connect' and 'push', git will use
+'connect' if possible and fall back to 'push' if the helper requests
+so when connecting (see the 'connect' command under COMMANDS).
+
+Capabilities for Fetching
+~~~~~~~~~~~~~~~~~~~~~~~~~
+'connect'::
+       Can try to connect to 'git upload-pack' (for fetching),
+       'git receive-pack', etc for communication using the
+       packfile protocol.
++
+Supported commands: 'connect'.
+
+'fetch'::
+       Can discover remote refs and transfer objects reachable from
+       them to the local object store.
++
+Supported commands: 'list', 'fetch'.
+
+'import'::
+       Can discover remote refs and output objects reachable from
+       them as a stream in fast-import format.
++
+Supported commands: 'list', 'import'.
+
+If a helper advertises 'connect', git will use it if possible and
+fall back to another capability if the helper requests so when
+connecting (see the 'connect' command under COMMANDS).
+When choosing between 'fetch' and 'import', git prefers 'fetch'.
+Other frontends may have some other order of preference.
+
+'refspec' <refspec>::
+       This modifies the 'import' capability.
++
+A helper advertising
+`refspec refs/heads/{asterisk}:refs/svn/origin/branches/{asterisk}`
+in its capabilities is saying that, when it handles
+`import refs/heads/topic`, the stream it outputs will update the
+`refs/svn/origin/branches/topic` ref.
++
+This capability can be advertised multiple times.  The first
+applicable refspec takes precedence.  The left-hand of refspecs
+advertised with this capability must cover all refs reported by
+the list command.  If no 'refspec' capability is advertised,
+there is an implied `refspec {asterisk}:{asterisk}`.
+
 INVOCATION
 ----------
 
@@ -122,7 +241,22 @@ Supported if the helper has the "fetch" capability.
 'push' +<src>:<dst>::
        Pushes the given local <src> commit or branch to the
        remote branch described by <dst>.  A batch sequence of
-       one or more push commands is terminated with a blank line.
+       one or more 'push' commands is terminated with a blank line
+       (if there is only one reference to push, a single 'push' command
+       is followed by a blank line). For example, the following would
+       be two batches of 'push', the first asking the remote-helper
+       to push the local ref 'master' to the remote ref 'master' and
+       the local 'HEAD' to the remote 'branch', and the second
+       asking to push ref 'foo' to ref 'bar' (forced update requested
+       by the '+').
++
+------------
+push refs/heads/master:refs/heads/master
+push HEAD:refs/heads/branch
+\n
+push +refs/heads/foo:refs/heads/bar
+\n
+------------
 +
 Zero or more protocol options may be entered after the last 'push'
 command, before the batch's terminating blank line.
@@ -147,6 +281,11 @@ Supported if the helper has the "push" capability.
 Especially useful for interoperability with a foreign versioning
 system.
 +
+Just like 'push', a batch sequence of one or more 'import' is
+terminated with a blank line. For each batch of 'import', the remote
+helper should produce a fast-import stream terminated by a 'done'
+command.
++
 Supported if the helper has the "import" capability.
 
 'connect' <service>::
@@ -171,26 +310,6 @@ completing a valid response for the current command.
 Additional commands may be supported, as may be determined from
 capabilities reported by the helper.
 
-CAPABILITIES
-------------
-
-'fetch'::
-'option'::
-'push'::
-'import'::
-'connect'::
-       This helper supports the corresponding command with the same name.
-
-'refspec' 'spec'::
-       When using the import command, expect the source ref to have
-       been written to the destination ref. The earliest applicable
-       refspec takes precedence. For example
-       "refs/heads/{asterisk}:refs/svn/origin/branches/{asterisk}" means
-       that, after an "import refs/heads/name", the script has written to
-       refs/svn/origin/branches/name. If this capability is used at
-       all, it must cover all refs reported by the list command; if
-       it is not used, it is effectively "{asterisk}:{asterisk}"
-
 REF LIST ATTRIBUTES
 -------------------
 
@@ -243,6 +362,8 @@ SEE ALSO
 --------
 linkgit:git-remote[1]
 
+linkgit:git-remote-testgit[1]
+
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-remote-testgit.txt b/Documentation/git-remote-testgit.txt
new file mode 100644 (file)
index 0000000..2a67d45
--- /dev/null
@@ -0,0 +1,30 @@
+git-remote-testgit(1)
+=====================
+
+NAME
+----
+git-remote-testgit - Example remote-helper
+
+
+SYNOPSIS
+--------
+[verse]
+git clone testgit::<source-repo> [<destination>]
+
+DESCRIPTION
+-----------
+
+This command is a simple remote-helper, that is used both as a
+testcase for the remote-helper functionality, and as an example to
+show remote-helper authors one possible implementation.
+
+The best way to learn more is to read the comments and source code in
+'git-remote-testgit.py'.
+
+SEE ALSO
+--------
+linkgit:git-remote-helpers[1]
+
+GIT
+---
+Part of the linkgit:git[1] suite
index e75fc191d35fa98eac96dbc2e0cbf3d6069e5737..f977e8780b5e152b18d07a61fde8c2f86f98a0ce 100644 (file)
@@ -225,6 +225,14 @@ discouraged.
        version 1.5 can make use of it. To specify merge information from multiple
        branches, use a single space character between the branches
        (`--mergeinfo="/branches/foo:1-10 /branches/bar:3,5-6,8"`)
++
+[verse]
+config key: svn.pushmergeinfo
++
+This option will cause git-svn to attempt to automatically populate the
+svn:mergeinfo property in the SVN repository when possible. Currently, this can
+only be done when dcommitting non-fast-forward merges where all parents but the
+first have already been pushed into SVN.
 
 'branch'::
        Create a branch in the SVN repository.
@@ -310,7 +318,7 @@ Any other arguments are passed directly to 'git log'
        Show what revision and author last modified each line of a file. The
        output of this mode is format-compatible with the output of
        `svn blame' by default. Like the SVN blame command,
-       local uncommitted changes in the working copy are ignored;
+       local uncommitted changes in the working tree are ignored;
        the version of the file in the HEAD revision is annotated. Unknown
        arguments are passed directly to 'git blame'.
 +
index d3931294d174e5c06adb81e428e31e00fbfa3b5e..a3081f4e237747dc858fd105302cbb9a489de41b 100644 (file)
@@ -264,7 +264,9 @@ tree files, you have to explicitly tell git about it by dropping
 "assume unchanged" bit, either before or after you modify them.
 
 In order to set "assume unchanged" bit, use `--assume-unchanged`
-option.  To unset, use `--no-assume-unchanged`.
+option.  To unset, use `--no-assume-unchanged`. To see which files
+have the "assume unchanged" bit set, use `git ls-files -v`
+(see linkgit:git-ls-files[1]).
 
 The command looks at `core.ignorestat` configuration variable.  When
 this is true, paths updated with `git update-index paths...` and
@@ -363,7 +365,8 @@ ctime for marking files processed) (see linkgit:git-config[1]).
 SEE ALSO
 --------
 linkgit:git-config[1],
-linkgit:git-add[1]
+linkgit:git-add[1],
+linkgit:git-ls-files[1]
 
 GIT
 ---
index 651e155d1de0dc7251e6592e867141d9ce841723..5e80cfd71a5529225b607bd3f1732d19f05d0c1d 100644 (file)
@@ -44,9 +44,17 @@ unreleased) version of git, that is available from 'master'
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
-* link:v1.7.6.2/git.html[documentation for release 1.7.6.2]
+* link:v1.7.7.1/git.html[documentation for release 1.7.7.1]
 
 * release notes for
+  link:RelNotes/1.7.7.1.txt[1.7.7.1],
+  link:RelNotes/1.7.7.txt[1.7.7].
+
+* link:v1.7.6.4/git.html[documentation for release 1.7.6.4]
+
+* release notes for
+  link:RelNotes/1.7.6.4.txt[1.7.6.4],
+  link:RelNotes/1.7.6.3.txt[1.7.6.3],
   link:RelNotes/1.7.6.2.txt[1.7.6.2],
   link:RelNotes/1.7.6.1.txt[1.7.6.1],
   link:RelNotes/1.7.6.txt[1.7.6].
index ed8924e856ee0c6cc707135555df0d265dabccc7..c6713cf5d77b5b46f576bfb41e6c0565c4afa088 100644 (file)
@@ -5,6 +5,13 @@ NAME
 ----
 gitnamespaces - Git namespaces
 
+SYNOPSIS
+--------
+[verse]
+GIT_NAMESPACE=<namespace> 'git upload-pack'
+GIT_NAMESPACE=<namespace> 'git receive-pack'
+
+
 DESCRIPTION
 -----------
 
index d527b307707c676e82a08f18cb9fdd7d3abcb228..8823a37067811037487a9f0496736bfafdc8b7ad 100644 (file)
@@ -176,7 +176,7 @@ by doing the following:
  - Update "What's cooking" message to review the updates to
    existing topics, newly added topics and graduated topics.
 
-   This step is helped with Meta/UWC script (where Meta/ contains
+   This step is helped with Meta/cook script (where Meta/ contains
    a checkout of the 'todo' branch).
 
  - Merge topics to 'next'.  For each branch whose tip is not
@@ -197,10 +197,9 @@ by doing the following:
 
    - Nothing is next-worthy; do not do anything.
 
- - Rebase topics that do not have any commit in next yet.  This
-   step is optional but sometimes is worth doing when an old
-   series that is not in next can take advantage of low-level
-   framework change that is merged to 'master' already.
+ - [** OBSOLETE **] Optionally rebase topics that do not have any commit
+   in next yet, when they can take advantage of low-level framework
+   change that is merged to 'master' already.
 
      $ git rebase master ai/topic
 
@@ -209,7 +208,7 @@ by doing the following:
    pre-rebase hook to make sure that topics that are already in
    'next' are not rebased beyond the merged commit.
 
- - Rebuild "pu" to merge the tips of topics not in 'next'.
+ - [** OBSOLETE **] Rebuild "pu" to merge the tips of topics not in 'next'.
 
      $ git checkout pu
      $ git reset --hard next
@@ -241,7 +240,7 @@ by doing the following:
 
  - Fetch html and man branches back from k.org, and push four
    integration branches and the two documentation branches to
-   repo.or.cz
+   repo.or.cz and other mirrors.
 
 
 Some observations to be made.
index fea63c14beaf06caece3958bd26fcf3647bb1ac1..dbdb4c137f162cc807ee57adcc52a10e067029c9 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v1.7.7-rc0
+DEF_VER=v1.7.7.1
 
 LF='
 '
index 8d6d4515d2d635ff8b5e59e0ce38ffa566f5bb64..924749edae3b515b31a48bb3db85f44a40529b9d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -820,6 +820,7 @@ ifeq ($(uname_S),GNU/kFreeBSD)
        NO_STRLCPY = YesPlease
        NO_MKSTEMPS = YesPlease
        HAVE_PATHS_H = YesPlease
+       DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease
 endif
 ifeq ($(uname_S),UnixWare)
        CC = cc
index 6372427426d80b01b03437fd1a55fd412fb8f75d..77a28d448a76cb0387565b254d4f886924c315b6 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/1.7.7.txt
\ No newline at end of file
+Documentation/RelNotes/1.7.7.1.txt
\ No newline at end of file
index 478d82567d7773d62c686d73780659b86594eede..fecedd3b4635c79adcbe0e26613af079beff64d0 100644 (file)
--- a/branch.c
+++ b/branch.c
@@ -135,23 +135,25 @@ static int setup_tracking(const char *new_ref, const char *orig_ref,
        return 0;
 }
 
-int validate_new_branchname(const char *name, struct strbuf *ref, int force)
+int validate_new_branchname(const char *name, struct strbuf *ref,
+                           int force, int attr_only)
 {
-       const char *head;
-       unsigned char sha1[20];
-
        if (strbuf_check_branch_ref(ref, name))
                die("'%s' is not a valid branch name.", name);
 
        if (!ref_exists(ref->buf))
                return 0;
-       else if (!force)
+       else if (!force && !attr_only)
                die("A branch named '%s' already exists.", ref->buf + strlen("refs/heads/"));
 
-       head = resolve_ref("HEAD", sha1, 0, NULL);
-       if (!is_bare_repository() && head && !strcmp(head, ref->buf))
-               die("Cannot force update the current branch.");
+       if (!attr_only) {
+               const char *head;
+               unsigned char sha1[20];
 
+               head = resolve_ref("HEAD", sha1, 0, NULL);
+               if (!is_bare_repository() && head && !strcmp(head, ref->buf))
+                       die("Cannot force update the current branch.");
+       }
        return 1;
 }
 
@@ -171,7 +173,8 @@ void create_branch(const char *head,
        if (track == BRANCH_TRACK_EXPLICIT || track == BRANCH_TRACK_OVERRIDE)
                explicit_tracking = 1;
 
-       if (validate_new_branchname(name, &ref, force || track == BRANCH_TRACK_OVERRIDE)) {
+       if (validate_new_branchname(name, &ref, force,
+                                   track == BRANCH_TRACK_OVERRIDE)) {
                if (!force)
                        dont_change_ref = 1;
                else
index 01544e25cbbf77c573da38c73f105a8b62c55f99..1285158dd4f26e5bbb0e0d7133055f168fee773f 100644 (file)
--- a/branch.h
+++ b/branch.h
@@ -20,8 +20,18 @@ void create_branch(const char *head, const char *name, const char *start_name,
  * interpreted ref in ref, force indicates whether (non-head) branches
  * may be overwritten. A non-zero return value indicates that the force
  * parameter was non-zero and the branch already exists.
+ *
+ * Contrary to all of the above, when attr_only is 1, the caller is
+ * not interested in verifying if it is Ok to update the named
+ * branch to point at a potentially different commit. It is merely
+ * asking if it is OK to change some attribute for the named branch
+ * (e.g. tracking upstream).
+ *
+ * NEEDSWORK: This needs to be split into two separate functions in the
+ * longer run for sanity.
+ *
  */
-int validate_new_branchname(const char *name, struct strbuf *ref, int force);
+int validate_new_branchname(const char *name, struct strbuf *ref, int force, int attr_only);
 
 /*
  * Remove information about the state of working on the current
index f2edc52818e817e83717f992a6bbd66dad4ef24d..311a94e18195c611b55de7d1619da890aca240af 100644 (file)
@@ -1407,6 +1407,9 @@ static int find_header(char *line, unsigned long size, int *hdrsize, struct patc
                                            "%d leading pathname components (line %d)" , p_value, linenr);
                                patch->old_name = patch->new_name = patch->def_name;
                        }
+                       if (!patch->is_delete && !patch->new_name)
+                               die("git diff header lacks filename information "
+                                   "(line %d)", linenr);
                        patch->is_toplevel_relative = 1;
                        *hdrsize = git_hdr_len;
                        return offset;
@@ -2447,6 +2450,8 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
        char *old, *oldlines;
        struct strbuf newlines;
        int new_blank_lines_at_end = 0;
+       int found_new_blank_lines_at_end = 0;
+       int hunk_linenr = frag->linenr;
        unsigned long leading, trailing;
        int pos, applied_pos;
        struct image preimage;
@@ -2540,14 +2545,18 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
                                error("invalid start of line: '%c'", first);
                        return -1;
                }
-               if (added_blank_line)
+               if (added_blank_line) {
+                       if (!new_blank_lines_at_end)
+                               found_new_blank_lines_at_end = hunk_linenr;
                        new_blank_lines_at_end++;
+               }
                else if (is_blank_context)
                        ;
                else
                        new_blank_lines_at_end = 0;
                patch += len;
                size -= len;
+               hunk_linenr++;
        }
        if (inaccurate_eof &&
            old > oldlines && old[-1] == '\n' &&
@@ -2629,7 +2638,8 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
                    preimage.nr + applied_pos >= img->nr &&
                    (ws_rule & WS_BLANK_AT_EOF) &&
                    ws_error_action != nowarn_ws_error) {
-                       record_ws_error(WS_BLANK_AT_EOF, "+", 1, frag->linenr);
+                       record_ws_error(WS_BLANK_AT_EOF, "+", 1,
+                                       found_new_blank_lines_at_end);
                        if (ws_error_action == correct_ws_error) {
                                while (new_blank_lines_at_end--)
                                        remove_last_line(&postimage);
index 883c0092ad43d602136e68d2afde8e319a904676..931956def986bbdf5b77e163f1b18c961e7be09c 100644 (file)
@@ -61,6 +61,8 @@ static int run_remote_archiver(int argc, const char **argv,
        if (strcmp(buf, "ACK")) {
                if (len > 5 && !prefixcmp(buf, "NACK "))
                        die(_("git archive: NACK %s"), buf + 5);
+               if (len > 4 && !prefixcmp(buf, "ERR "))
+                       die(_("remote error: %s"), buf + 4);
                die(_("git archive: protocol error"));
        }
 
index aa705a0fb0b7d4cdd0fb29fc4853b8c8c05c625d..f49596f826228e22d354194ddbb73ec100d8728e 100644 (file)
@@ -566,7 +566,7 @@ static void rename_branch(const char *oldname, const char *newname, int force)
                        die(_("Invalid branch name: '%s'"), oldname);
        }
 
-       validate_new_branchname(newname, &newref, force);
+       validate_new_branchname(newname, &newref, force, 0);
 
        strbuf_addf(&logmsg, "Branch: renamed %s to %s",
                 oldref.buf, newref.buf);
index 81046a9cb870aab59a56492e175a51c032ad96ce..92a8a6026a9bd6da5394e7b37f07dbe91f73db9c 100644 (file)
@@ -58,7 +58,7 @@ int cmd_bundle(int argc, const char **argv, const char *prefix)
        } else if (!strcmp(cmd, "unbundle")) {
                if (!startup_info->have_repository)
                        die(_("Need a repository to unbundle."));
-               return !!unbundle(&header, bundle_fd) ||
+               return !!unbundle(&header, bundle_fd, 0) ||
                        list_bundle_refs(&header, argc, argv);
        } else
                usage(builtin_bundle_usage);
index 3bb652591bb0ee53f2c4d7aed2c32dc480f6e5ae..75dbe761361aa5f5dec2b7ed83556a7035868625 100644 (file)
@@ -71,7 +71,7 @@ static int update_some(const unsigned char *sha1, const char *base, int baselen,
        hashcpy(ce->sha1, sha1);
        memcpy(ce->name, base, baselen);
        memcpy(ce->name + baselen, pathname, len - baselen);
-       ce->ce_flags = create_ce_flags(len, 0);
+       ce->ce_flags = create_ce_flags(len, 0) | CE_UPDATE;
        ce->ce_mode = create_ce_mode(mode);
        add_cache_entry(ce, ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE);
        return 0;
@@ -228,6 +228,8 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec,
 
        for (pos = 0; pos < active_nr; pos++) {
                struct cache_entry *ce = active_cache[pos];
+               if (source_tree && !(ce->ce_flags & CE_UPDATE))
+                       continue;
                match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, ps_matched);
        }
 
@@ -266,6 +268,8 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec,
        state.refresh_cache = 1;
        for (pos = 0; pos < active_nr; pos++) {
                struct cache_entry *ce = active_cache[pos];
+               if (source_tree && !(ce->ce_flags & CE_UPDATE))
+                       continue;
                if (match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, NULL)) {
                        if (!ce_stage(ce)) {
                                errs |= checkout_entry(ce, &state, NULL);
@@ -1073,7 +1077,8 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
        if (opts.new_branch) {
                struct strbuf buf = STRBUF_INIT;
 
-               opts.branch_exists = validate_new_branchname(opts.new_branch, &buf, !!opts.new_branch_force);
+               opts.branch_exists = validate_new_branchname(opts.new_branch, &buf,
+                                                            !!opts.new_branch_force, 0);
 
                strbuf_release(&buf);
        }
index cbc9613ec661bc2cef8274cd66efb06b9cab55b6..66ffe31736933d1ad15fdeb7bb321f10fcab1dd3 100644 (file)
@@ -1392,7 +1392,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
        if (get_sha1("HEAD", sha1))
                current_head = NULL;
        else {
-               current_head = lookup_commit(sha1);
+               current_head = lookup_commit_or_die(sha1, "HEAD");
                if (!current_head || parse_commit(current_head))
                        die(_("could not parse HEAD commit"));
        }
@@ -1424,6 +1424,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
                        pptr = &commit_list_insert(c->item, pptr)->next;
        } else if (whence == FROM_MERGE) {
                struct strbuf m = STRBUF_INIT;
+               struct commit *commit;
                FILE *fp;
 
                if (!reflog_msg)
@@ -1437,7 +1438,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
                        unsigned char sha1[20];
                        if (get_sha1_hex(m.buf, sha1) < 0)
                                die(_("Corrupt MERGE_HEAD file (%s)"), m.buf);
-                       pptr = &commit_list_insert(lookup_commit(sha1), pptr)->next;
+                       commit = lookup_commit_or_die(sha1, "MERGE_HEAD");
+                       pptr = &commit_list_insert(commit, pptr)->next;
                }
                fclose(fp);
                strbuf_release(&m);
index 0b4ecac855dce9b70878de4d15f4d317254d9ef3..0315ad76f881aab9a64084f8d2fdd2019907e4cb 100644 (file)
@@ -99,6 +99,7 @@ static int show_config(const char *key_, const char *value_, void *cb)
        const char *vptr = value;
        int must_free_vptr = 0;
        int dup_error = 0;
+       int must_print_delim = 0;
 
        if (!use_key_regexp && strcmp(key_, key))
                return 0;
@@ -109,10 +110,8 @@ static int show_config(const char *key_, const char *value_, void *cb)
                return 0;
 
        if (show_keys) {
-               if (value_)
-                       printf("%s%c", key_, key_delim);
-               else
-                       printf("%s", key_);
+               printf("%s", key_);
+               must_print_delim = 1;
        }
        if (seen && !do_all)
                dup_error = 1;
@@ -130,16 +129,23 @@ static int show_config(const char *key_, const char *value_, void *cb)
        } else if (types == TYPE_PATH) {
                git_config_pathname(&vptr, key_, value_);
                must_free_vptr = 1;
+       } else if (value_) {
+               vptr = value_;
+       } else {
+               /* Just show the key name */
+               vptr = "";
+               must_print_delim = 0;
        }
-       else
-               vptr = value_?value_:"";
        seen++;
        if (dup_error) {
                error("More than one value for the key %s: %s",
                                key_, vptr);
        }
-       else
+       else {
+               if (must_print_delim)
+                       printf("%c", key_delim);
                printf("%s%c", vptr, term);
+       }
        if (must_free_vptr)
                /* If vptr must be freed, it's a pointer to a
                 * dynamically allocated buffer, it's safe to cast to
index 93c99385a95e6ab525fa64c1dbb70d5d4ca103ba..e422ced9299521bb2e7f3c5ff59a434c8403a4ea 100644 (file)
@@ -941,6 +941,15 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
        argc = parse_options(argc, argv, prefix,
                             builtin_fetch_options, builtin_fetch_usage, 0);
 
+       if (recurse_submodules != RECURSE_SUBMODULES_OFF) {
+               if (recurse_submodules_default) {
+                       int arg = parse_fetch_recurse_submodules_arg("--recurse-submodules-default", recurse_submodules_default);
+                       set_config_fetch_recurse_submodules(arg);
+               }
+               gitmodules_config();
+               git_config(submodule_config, NULL);
+       }
+
        if (all) {
                if (argc == 1)
                        die(_("fetch --all does not take a repository argument"));
@@ -976,12 +985,6 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
        if (!result && (recurse_submodules != RECURSE_SUBMODULES_OFF)) {
                const char *options[10];
                int num_options = 0;
-               if (recurse_submodules_default) {
-                       int arg = parse_fetch_recurse_submodules_arg("--recurse-submodules-default", recurse_submodules_default);
-                       set_config_fetch_recurse_submodules(arg);
-               }
-               gitmodules_config();
-               git_config(submodule_config, NULL);
                add_options_to_argv(&num_options, options);
                result = fetch_populated_submodules(num_options, options,
                                                    submodule_prefix,
index 75816329d6153c35e0763b35f70cfaf165f2a4b8..7e2f22589dcb14d5ba95ce1331ef816a458533d0 100644 (file)
@@ -293,7 +293,7 @@ static int do_fmt_merge_msg(int merge_title, struct strbuf *in,
                struct commit *head;
                struct rev_info rev;
 
-               head = lookup_commit(head_sha1);
+               head = lookup_commit_or_die(head_sha1, "HEAD");
                init_revisions(&rev, NULL);
                rev.commit_format = CMIT_FMT_ONELINE;
                rev.ignore_merges = 1;
index 5ae0366bc8cfe52f226c2af151a66d39b9df02aa..df1a88b51ae7773a15276d144113c0002fddb1cd 100644 (file)
@@ -231,12 +231,9 @@ static void check_unreachable_object(struct object *obj)
                                unsigned long size;
                                char *buf = read_sha1_file(obj->sha1,
                                                &type, &size);
-                               if (buf) {
-                                       if (fwrite(buf, size, 1, f) != 1)
-                                               die_errno("Could not write '%s'",
-                                                         filename);
-                                       free(buf);
-                               }
+                               if (buf && fwrite(buf, 1, size, f) != size)
+                                       die_errno("Could not write '%s'", filename);
+                               free(buf);
                        } else
                                fprintf(f, "%s\n", sha1_to_hex(obj->sha1));
                        if (fclose(f))
index 1c359c2671536287d97f2049b27a390d33b51e88..a286692e467710d92346ab6900e98f1126cb967d 100644 (file)
@@ -598,8 +598,11 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
                struct strbuf base;
                int hit, len;
 
+               read_sha1_lock();
                data = read_object_with_reference(obj->sha1, tree_type,
                                                  &size, NULL);
+               read_sha1_unlock();
+
                if (!data)
                        die(_("unable to read tree (%s)"), sha1_to_hex(obj->sha1));
 
index d760ee0885763e964afd9cdaf09a0986da606804..f5d49305903911eb7aa0fb3f73e0fd950b896228 100644 (file)
@@ -608,7 +608,8 @@ static int git_format_config(const char *var, const char *value, void *cb)
                string_list_append(&extra_cc, value);
                return 0;
        }
-       if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff")) {
+       if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff") ||
+           !strcmp(var, "color.ui")) {
                return 0;
        }
        if (!strcmp(var, "format.numbered")) {
index ab4077f272919fb47e3c5f179dc42fc9baad68bb..581f494aee01f97bb87a94dbfd1fba4d14afaa69 100644 (file)
@@ -50,7 +50,6 @@ static int fast_forward_only;
 static int allow_trivial = 1, have_message;
 static struct strbuf merge_msg;
 static struct commit_list *remoteheads;
-static unsigned char head[20], stash[20];
 static struct strategy **use_strategies;
 static size_t use_strategies_nr, use_strategies_alloc;
 static const char **xopts;
@@ -217,7 +216,7 @@ static void drop_save(void)
        unlink(git_path("MERGE_MODE"));
 }
 
-static void save_state(void)
+static int save_state(unsigned char *stash)
 {
        int len;
        struct child_process cp;
@@ -236,11 +235,12 @@ static void save_state(void)
 
        if (finish_command(&cp) || len < 0)
                die(_("stash failed"));
-       else if (!len)
-               return;
+       else if (!len)          /* no changes */
+               return -1;
        strbuf_setlen(&buffer, buffer.len-1);
        if (get_sha1(buffer.buf, stash))
                die(_("not a valid object: %s"), buffer.buf);
+       return 0;
 }
 
 static void read_empty(unsigned const char *sha1, int verbose)
@@ -278,7 +278,8 @@ static void reset_hard(unsigned const char *sha1, int verbose)
                die(_("read-tree failed"));
 }
 
-static void restore_state(void)
+static void restore_state(const unsigned char *head,
+                         const unsigned char *stash)
 {
        struct strbuf sb = STRBUF_INIT;
        const char *args[] = { "stash", "apply", NULL, NULL };
@@ -308,10 +309,9 @@ static void finish_up_to_date(const char *msg)
        drop_save();
 }
 
-static void squash_message(void)
+static void squash_message(struct commit *commit)
 {
        struct rev_info rev;
-       struct commit *commit;
        struct strbuf out = STRBUF_INIT;
        struct commit_list *j;
        int fd;
@@ -326,7 +326,6 @@ static void squash_message(void)
        rev.ignore_merges = 1;
        rev.commit_format = CMIT_FMT_MEDIUM;
 
-       commit = lookup_commit(head);
        commit->object.flags |= UNINTERESTING;
        add_pending_object(&rev, &commit->object, NULL);
 
@@ -355,9 +354,11 @@ static void squash_message(void)
        strbuf_release(&out);
 }
 
-static void finish(const unsigned char *new_head, const char *msg)
+static void finish(struct commit *head_commit,
+                  const unsigned char *new_head, const char *msg)
 {
        struct strbuf reflog_message = STRBUF_INIT;
+       const unsigned char *head = head_commit->object.sha1;
 
        if (!msg)
                strbuf_addstr(&reflog_message, getenv("GIT_REFLOG_ACTION"));
@@ -368,7 +369,7 @@ static void finish(const unsigned char *new_head, const char *msg)
                        getenv("GIT_REFLOG_ACTION"), msg);
        }
        if (squash) {
-               squash_message();
+               squash_message(head_commit);
        } else {
                if (verbosity >= 0 && !merge_msg.len)
                        printf(_("No merge message -- not updating HEAD\n"));
@@ -661,7 +662,7 @@ int try_merge_command(const char *strategy, size_t xopts_nr,
 }
 
 static int try_merge_strategy(const char *strategy, struct commit_list *common,
-                             const char *head_arg)
+                             struct commit *head, const char *head_arg)
 {
        int index_fd;
        struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));
@@ -707,7 +708,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
                        commit_list_insert(j->item, &reversed);
 
                index_fd = hold_locked_index(lock, 1);
-               clean = merge_recursive(&o, lookup_commit(head),
+               clean = merge_recursive(&o, head,
                                remoteheads->item, reversed, &result);
                if (active_cache_changed &&
                                (write_cache(index_fd, active_cache, active_nr) ||
@@ -858,25 +859,26 @@ static void run_prepare_commit_msg(void)
        read_merge_msg();
 }
 
-static int merge_trivial(void)
+static int merge_trivial(struct commit *head)
 {
        unsigned char result_tree[20], result_commit[20];
        struct commit_list *parent = xmalloc(sizeof(*parent));
 
        write_tree_trivial(result_tree);
        printf(_("Wonderful.\n"));
-       parent->item = lookup_commit(head);
+       parent->item = head;
        parent->next = xmalloc(sizeof(*parent->next));
        parent->next->item = remoteheads->item;
        parent->next->next = NULL;
        run_prepare_commit_msg();
        commit_tree(merge_msg.buf, result_tree, parent, result_commit, NULL);
-       finish(result_commit, "In-index merge");
+       finish(head, result_commit, "In-index merge");
        drop_save();
        return 0;
 }
 
-static int finish_automerge(struct commit_list *common,
+static int finish_automerge(struct commit *head,
+                           struct commit_list *common,
                            unsigned char *result_tree,
                            const char *wt_strategy)
 {
@@ -887,12 +889,12 @@ static int finish_automerge(struct commit_list *common,
        free_commit_list(common);
        if (allow_fast_forward) {
                parents = remoteheads;
-               commit_list_insert(lookup_commit(head), &parents);
+               commit_list_insert(head, &parents);
                parents = reduce_heads(parents);
        } else {
                struct commit_list **pptr = &parents;
 
-               pptr = &commit_list_insert(lookup_commit(head),
+               pptr = &commit_list_insert(head,
                                pptr)->next;
                for (j = remoteheads; j; j = j->next)
                        pptr = &commit_list_insert(j->item, pptr)->next;
@@ -902,7 +904,7 @@ static int finish_automerge(struct commit_list *common,
        run_prepare_commit_msg();
        commit_tree(merge_msg.buf, result_tree, parents, result_commit, NULL);
        strbuf_addf(&buf, "Merge made by the '%s' strategy.", wt_strategy);
-       finish(result_commit, buf.buf);
+       finish(head, result_commit, buf.buf);
        strbuf_release(&buf);
        drop_save();
        return 0;
@@ -936,7 +938,8 @@ static int suggest_conflicts(int renormalizing)
        return 1;
 }
 
-static struct commit *is_old_style_invocation(int argc, const char **argv)
+static struct commit *is_old_style_invocation(int argc, const char **argv,
+                                             const unsigned char *head)
 {
        struct commit *second_token = NULL;
        if (argc > 2) {
@@ -1008,9 +1011,12 @@ static int setup_with_upstream(const char ***argv)
 int cmd_merge(int argc, const char **argv, const char *prefix)
 {
        unsigned char result_tree[20];
+       unsigned char stash[20];
+       unsigned char head_sha1[20];
+       struct commit *head_commit;
        struct strbuf buf = STRBUF_INIT;
        const char *head_arg;
-       int flag, head_invalid = 0, i;
+       int flag, i;
        int best_cnt = -1, merge_was_ok = 0, automerge_was_ok = 0;
        struct commit_list *common = NULL;
        const char *best_strategy = NULL, *wt_strategy = NULL;
@@ -1023,11 +1029,13 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
         * Check if we are _not_ on a detached HEAD, i.e. if there is a
         * current branch.
         */
-       branch = resolve_ref("HEAD", head, 0, &flag);
+       branch = resolve_ref("HEAD", head_sha1, 0, &flag);
        if (branch && !prefixcmp(branch, "refs/heads/"))
                branch += 11;
-       if (is_null_sha1(head))
-               head_invalid = 1;
+       if (!branch || is_null_sha1(head_sha1))
+               head_commit = NULL;
+       else
+               head_commit = lookup_commit_or_die(head_sha1, "HEAD");
 
        git_config(git_merge_config, NULL);
 
@@ -1104,12 +1112,13 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
         * additional safety measure to check for it.
         */
 
-       if (!have_message && is_old_style_invocation(argc, argv)) {
+       if (!have_message && head_commit &&
+           is_old_style_invocation(argc, argv, head_commit->object.sha1)) {
                strbuf_addstr(&merge_msg, argv[0]);
                head_arg = argv[1];
                argv += 2;
                argc -= 2;
-       } else if (head_invalid) {
+       } else if (!head_commit) {
                struct object *remote_head;
                /*
                 * If the merged head is a valid one there is no reason
@@ -1156,7 +1165,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                }
        }
 
-       if (head_invalid || !argc)
+       if (!head_commit || !argc)
                usage_with_options(builtin_merge_usage,
                        builtin_merge_options);
 
@@ -1197,17 +1206,16 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
        }
 
        if (!remoteheads->next)
-               common = get_merge_bases(lookup_commit(head),
-                               remoteheads->item, 1);
+               common = get_merge_bases(head_commit, remoteheads->item, 1);
        else {
                struct commit_list *list = remoteheads;
-               commit_list_insert(lookup_commit(head), &list);
+               commit_list_insert(head_commit, &list);
                common = get_octopus_merge_bases(list);
                free(list);
        }
 
-       update_ref("updating ORIG_HEAD", "ORIG_HEAD", head, NULL, 0,
-               DIE_ON_ERR);
+       update_ref("updating ORIG_HEAD", "ORIG_HEAD", head_commit->object.sha1,
+                  NULL, 0, DIE_ON_ERR);
 
        if (!common)
                ; /* No common ancestors found. We need a real merge. */
@@ -1221,13 +1229,13 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                return 0;
        } else if (allow_fast_forward && !remoteheads->next &&
                        !common->next &&
-                       !hashcmp(common->item->object.sha1, head)) {
+                       !hashcmp(common->item->object.sha1, head_commit->object.sha1)) {
                /* Again the most common case of merging one remote. */
                struct strbuf msg = STRBUF_INIT;
                struct object *o;
                char hex[41];
 
-               strcpy(hex, find_unique_abbrev(head, DEFAULT_ABBREV));
+               strcpy(hex, find_unique_abbrev(head_commit->object.sha1, DEFAULT_ABBREV));
 
                if (verbosity >= 0)
                        printf(_("Updating %s..%s\n"),
@@ -1243,10 +1251,10 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                if (!o)
                        return 1;
 
-               if (checkout_fast_forward(head, remoteheads->item->object.sha1))
+               if (checkout_fast_forward(head_commit->object.sha1, remoteheads->item->object.sha1))
                        return 1;
 
-               finish(o->sha1, msg.buf);
+               finish(head_commit, o->sha1, msg.buf);
                drop_save();
                return 0;
        } else if (!remoteheads->next && common->next)
@@ -1266,8 +1274,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                        git_committer_info(IDENT_ERROR_ON_NO_NAME);
                        printf(_("Trying really trivial in-index merge...\n"));
                        if (!read_tree_trivial(common->item->object.sha1,
-                                       head, remoteheads->item->object.sha1))
-                               return merge_trivial();
+                                       head_commit->object.sha1, remoteheads->item->object.sha1))
+                               return merge_trivial(head_commit);
                        printf(_("Nope.\n"));
                }
        } else {
@@ -1286,8 +1294,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                         * merge_bases again, otherwise "git merge HEAD^
                         * HEAD^^" would be missed.
                         */
-                       common_one = get_merge_bases(lookup_commit(head),
-                               j->item, 1);
+                       common_one = get_merge_bases(head_commit, j->item, 1);
                        if (hashcmp(common_one->item->object.sha1,
                                j->item->object.sha1)) {
                                up_to_date = 0;
@@ -1314,21 +1321,18 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
         * sync with the head commit.  The strategies are responsible
         * to ensure this.
         */
-       if (use_strategies_nr != 1) {
-               /*
-                * Stash away the local changes so that we can try more
-                * than one.
-                */
-               save_state();
-       } else {
-               memcpy(stash, null_sha1, 20);
-       }
+       if (use_strategies_nr == 1 ||
+           /*
+            * Stash away the local changes so that we can try more than one.
+            */
+           save_state(stash))
+               hashcpy(stash, null_sha1);
 
        for (i = 0; i < use_strategies_nr; i++) {
                int ret;
                if (i) {
                        printf(_("Rewinding the tree to pristine...\n"));
-                       restore_state();
+                       restore_state(head_commit->object.sha1, stash);
                }
                if (use_strategies_nr != 1)
                        printf(_("Trying merge strategy %s...\n"),
@@ -1340,7 +1344,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                wt_strategy = use_strategies[i]->name;
 
                ret = try_merge_strategy(use_strategies[i]->name,
-                       common, head_arg);
+                                        common, head_commit, head_arg);
                if (!option_commit && !ret) {
                        merge_was_ok = 1;
                        /*
@@ -1382,14 +1386,15 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
         * auto resolved the merge cleanly.
         */
        if (automerge_was_ok)
-               return finish_automerge(common, result_tree, wt_strategy);
+               return finish_automerge(head_commit, common, result_tree,
+                                       wt_strategy);
 
        /*
         * Pick the result from the best strategy and have the user fix
         * it up.
         */
        if (!best_strategy) {
-               restore_state();
+               restore_state(head_commit->object.sha1, stash);
                if (use_strategies_nr > 1)
                        fprintf(stderr,
                                _("No merge strategy handled the merge.\n"));
@@ -1401,14 +1406,14 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                ; /* We already have its result in the working tree. */
        else {
                printf(_("Rewinding the tree to pristine...\n"));
-               restore_state();
+               restore_state(head_commit->object.sha1, stash);
                printf(_("Using the %s to prepare resolving by hand.\n"),
                        best_strategy);
-               try_merge_strategy(best_strategy, common, head_arg);
+               try_merge_strategy(best_strategy, common, head_commit, head_arg);
        }
 
        if (squash)
-               finish(NULL, NULL);
+               finish(head_commit, NULL, NULL);
        else {
                int fd;
                struct commit_list *j;
index f821eb3f0b864c26d5e822cc7c5b0747340abee5..3cfe02d5a5716de1a3aaa5edc1ca0e3d74c03b03 100644 (file)
@@ -56,13 +56,13 @@ static int scan_hunk_header(const char *p, int *p_before, int *p_after)
        return 1;
 }
 
-static int get_one_patchid(unsigned char *next_sha1, git_SHA_CTX *ctx)
+static int get_one_patchid(unsigned char *next_sha1, git_SHA_CTX *ctx, struct strbuf *line_buf)
 {
-       static char line[1000];
        int patchlen = 0, found_next = 0;
        int before = -1, after = -1;
 
-       while (fgets(line, sizeof(line), stdin) != NULL) {
+       while (strbuf_getwholeline(line_buf, stdin, '\n') != EOF) {
+               char *line = line_buf->buf;
                char *p = line;
                int len;
 
@@ -133,14 +133,16 @@ static void generate_id_list(void)
        unsigned char sha1[20], n[20];
        git_SHA_CTX ctx;
        int patchlen;
+       struct strbuf line_buf = STRBUF_INIT;
 
        git_SHA1_Init(&ctx);
        hashclr(sha1);
        while (!feof(stdin)) {
-               patchlen = get_one_patchid(n, &ctx);
+               patchlen = get_one_patchid(n, &ctx, &line_buf);
                flush_current_id(patchlen, sha1, &ctx);
                hashcpy(sha1, n);
        }
+       strbuf_release(&line_buf);
 }
 
 static const char patch_id_usage[] = "git patch-id < patch";
index f2a9c26dc3494c0881ca3f91b44785c4b52caae7..b25dfb44227c42a5d8dadb72c04e5aa694d2ace2 100644 (file)
@@ -570,7 +570,7 @@ static int read_remote_branches(const char *refname,
        unsigned char orig_sha1[20];
        const char *symref;
 
-       strbuf_addf(&buf, "refs/remotes/%s", rename->old);
+       strbuf_addf(&buf, "refs/remotes/%s/", rename->old);
        if (!prefixcmp(refname, buf.buf)) {
                item = string_list_append(rename->remote_branches, xstrdup(refname));
                symref = resolve_ref(refname, orig_sha1, 1, &flag);
@@ -621,10 +621,11 @@ static int mv(int argc, const char **argv)
                OPT_END()
        };
        struct remote *oldremote, *newremote;
-       struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT, buf3 = STRBUF_INIT;
+       struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT, buf3 = STRBUF_INIT,
+               old_remote_context = STRBUF_INIT;
        struct string_list remote_branches = STRING_LIST_INIT_NODUP;
        struct rename_info rename;
-       int i;
+       int i, refspec_updated = 0;
 
        if (argc != 3)
                usage_with_options(builtin_remote_rename_usage, options);
@@ -659,15 +660,25 @@ static int mv(int argc, const char **argv)
        strbuf_addf(&buf, "remote.%s.fetch", rename.new);
        if (git_config_set_multivar(buf.buf, NULL, NULL, 1))
                return error("Could not remove config section '%s'", buf.buf);
+       strbuf_addf(&old_remote_context, ":refs/remotes/%s/", rename.old);
        for (i = 0; i < oldremote->fetch_refspec_nr; i++) {
                char *ptr;
 
                strbuf_reset(&buf2);
                strbuf_addstr(&buf2, oldremote->fetch_refspec[i]);
-               ptr = strstr(buf2.buf, rename.old);
-               if (ptr)
-                       strbuf_splice(&buf2, ptr-buf2.buf, strlen(rename.old),
-                                       rename.new, strlen(rename.new));
+               ptr = strstr(buf2.buf, old_remote_context.buf);
+               if (ptr) {
+                       refspec_updated = 1;
+                       strbuf_splice(&buf2,
+                                     ptr-buf2.buf + strlen(":refs/remotes/"),
+                                     strlen(rename.old), rename.new,
+                                     strlen(rename.new));
+               } else
+                       warning("Not updating non-default fetch respec\n"
+                               "\t%s\n"
+                               "\tPlease update the configuration manually if necessary.",
+                               buf2.buf);
+
                if (git_config_set_multivar(buf.buf, buf2.buf, "^$", 0))
                        return error("Could not append '%s'", buf.buf);
        }
@@ -685,6 +696,9 @@ static int mv(int argc, const char **argv)
                }
        }
 
+       if (!refspec_updated)
+               return 0;
+
        /*
         * First remove symrefs, then rename the rest, finally create
         * the new symrefs.
index f48fd7d4c1c706b68e879e4dfabdd3fb8597a328..6bf849740c6de45fe8ca11eca2a06a52c7ebc0bb 100644 (file)
--- a/bundle.c
+++ b/bundle.c
@@ -380,12 +380,15 @@ int create_bundle(struct bundle_header *header, const char *path,
        return 0;
 }
 
-int unbundle(struct bundle_header *header, int bundle_fd)
+int unbundle(struct bundle_header *header, int bundle_fd, int flags)
 {
        const char *argv_index_pack[] = {"index-pack",
-               "--fix-thin", "--stdin", NULL};
+                                        "--fix-thin", "--stdin", NULL, NULL};
        struct child_process ip;
 
+       if (flags & BUNDLE_VERBOSE)
+               argv_index_pack[3] = "-v";
+
        if (verify_bundle(header, 0))
                return -1;
        memset(&ip, 0, sizeof(ip));
index e2aedd60d6ad1482bb6da173c853e6ba4805c8d7..c5a22c8d10c7bf5e27536a3b84033b77f3542445 100644 (file)
--- a/bundle.h
+++ b/bundle.h
@@ -18,7 +18,8 @@ int read_bundle_header(const char *path, struct bundle_header *header);
 int create_bundle(struct bundle_header *header, const char *path,
                int argc, const char **argv);
 int verify_bundle(struct bundle_header *header, int verbose);
-int unbundle(struct bundle_header *header, int bundle_fd);
+#define BUNDLE_VERBOSE 1
+int unbundle(struct bundle_header *header, int bundle_fd, int flags);
 int list_bundle_refs(struct bundle_header *header,
                int argc, const char **argv);
 
index 97b43279cdf46159462d5f56abc20f2161f4c7ea..9f4cc636dd74e99a1311500e15501bdb4875cb9d 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -39,6 +39,18 @@ struct commit *lookup_commit_reference(const unsigned char *sha1)
        return lookup_commit_reference_gently(sha1, 0);
 }
 
+struct commit *lookup_commit_or_die(const unsigned char *sha1, const char *ref_name)
+{
+       struct commit *c = lookup_commit_reference(sha1);
+       if (!c)
+               die(_("could not parse %s"), ref_name);
+       if (hashcmp(sha1, c->object.sha1)) {
+               warning(_("%s %s is not a commit!"),
+                       ref_name, sha1_to_hex(sha1));
+       }
+       return c;
+}
+
 struct commit *lookup_commit(const unsigned char *sha1)
 {
        struct object *obj = lookup_object(sha1);
index 12d100b8b6fcd092f3a6886a75c720011ef1b7dc..14f6a5a2ed91e2176cce4543798774f88a8628b1 100644 (file)
--- a/commit.h
+++ b/commit.h
@@ -38,6 +38,13 @@ struct commit *lookup_commit_reference_gently(const unsigned char *sha1,
                                              int quiet);
 struct commit *lookup_commit_reference_by_name(const char *name);
 
+/*
+ * Look up object named by "sha1", dereference tag as necessary,
+ * get a commit and return it. If "sha1" does not dereference to
+ * a commit, use ref_name to report an error and die.
+ */
+struct commit *lookup_commit_or_die(const unsigned char *sha1, const char *ref_name);
+
 int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long size);
 int parse_commit(struct commit *item);
 
index fa6d41a1ab8c5f3de777c1ba93d241eb5140a3c7..ba077c13f96779d5b29237e83974b0910b4bbdde 100755 (executable)
 # will have put this somewhere standard.  You should make this script
 # executable then link to it in the repository you would like to use it in.
 # For example, on debian the hook is stored in
-# /usr/share/doc/git-core/contrib/hooks/post-receive-email:
+# /usr/share/git-core/contrib/hooks/post-receive-email:
 #
 #  chmod a+x post-receive-email
 #  cd /path/to/your/repository.git
-#  ln -sf /usr/share/doc/git-core/contrib/hooks/post-receive-email hooks/post-receive
+#  ln -sf /usr/share/git-core/contrib/hooks/post-receive-email hooks/post-receive
 #
 # This hook script assumes it is enabled on the central repository of a
 # project, with all users pushing only to it and not between each other.  It
diff --git a/date.c b/date.c
index 896fbb48060c673b8dc2f2aa6ea3de3c1042fbd2..353e0a5e53f13c36549e65452931f254de3423c4 100644 (file)
--- a/date.c
+++ b/date.c
@@ -552,23 +552,35 @@ static int match_digit(const char *date, struct tm *tm, int *offset, int *tm_gmt
 static int match_tz(const char *date, int *offp)
 {
        char *end;
-       int offset = strtoul(date+1, &end, 10);
-       int min, hour;
-       int n = end - date - 1;
+       int hour = strtoul(date + 1, &end, 10);
+       int n = end - (date + 1);
+       int min = 0;
 
-       min = offset % 100;
-       hour = offset / 100;
+       if (n == 4) {
+               /* hhmm */
+               min = hour % 100;
+               hour = hour / 100;
+       } else if (n != 2) {
+               min = 99; /* random crap */
+       } else if (*end == ':') {
+               /* hh:mm? */
+               min = strtoul(end + 1, &end, 10);
+               if (end - (date + 1) != 5)
+                       min = 99; /* random crap */
+       } /* otherwise we parsed "hh" */
 
        /*
-        * Don't accept any random crap.. At least 3 digits, and
-        * a valid minute. We might want to check that the minutes
-        * are divisible by 30 or something too.
+        * Don't accept any random crap. Even though some places have
+        * offset larger than 12 hours (e.g. Pacific/Kiritimati is at
+        * UTC+14), there is something wrong if hour part is much
+        * larger than that. We might also want to check that the
+        * minutes are divisible by 15 or something too. (Offset of
+        * Kathmandu, Nepal is UTC+5:45)
         */
-       if (min < 60 && n > 2) {
-               offset = hour*60+min;
+       if (min < 60 && hour < 24) {
+               int offset = hour * 60 + min;
                if (*date == '-')
                        offset = -offset;
-
                *offp = offset;
        }
        return end - date;
index f8454dd2918dc74bee43d9f2faa1837cc5665abd..62f4cd94cfbc4d3fe9e46c84f318af6624349a48 100644 (file)
@@ -289,7 +289,7 @@ static void show_new_file(struct rev_info *revs,
 
        /*
         * New file in the index: it might actually be different in
-        * the working copy.
+        * the working tree.
         */
        if (get_stat_data(new, &sha1, &mode, cached, match_missing,
            &dirty_submodule, &revs->diffopt) < 0)
@@ -468,6 +468,7 @@ static int diff_cache(struct rev_info *revs,
        opts.unpack_data = revs;
        opts.src_index = &the_index;
        opts.dst_index = NULL;
+       opts.pathspec = &revs->diffopt.pathspec;
 
        init_tree_desc(&t, tree->buffer, tree->size);
        return unpack_trees(1, &t, &opts);
diff --git a/diff.c b/diff.c
index fcc0078074c364d0a4c2bd75a6d390e517eb7f87..977ca7125b9acc603ce6c1d27c57a75c9d21fbdf 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -3385,6 +3385,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
        }
 
        /* xdiff options */
+       else if (!strcmp(arg, "--minimal"))
+               DIFF_XDL_SET(options, NEED_MINIMAL);
+       else if (!strcmp(arg, "--no-minimal"))
+               DIFF_XDL_CLR(options, NEED_MINIMAL);
        else if (!strcmp(arg, "-w") || !strcmp(arg, "--ignore-all-space"))
                DIFF_XDL_SET(options, IGNORE_WHITESPACE);
        else if (!strcmp(arg, "-b") || !strcmp(arg, "--ignore-space-change"))
index 804a7f4bc912ab0c9c51038456d9abe4216947a5..add2c0247fa91e0f629428c295fc581f19cf85e1 100755 (executable)
@@ -108,9 +108,7 @@ OPTIONS_SPEC=
 . git-sh-setup
 
 if [ "$(is_bare_repository)" = false ]; then
-       git diff-files --ignore-submodules --quiet &&
-       git diff-index --cached --quiet HEAD -- ||
-       die "Cannot rewrite branch(es) with a dirty working directory."
+       require_clean_work_tree 'rewrite branches'
 fi
 
 tempdir=.git-rewrite
index 7aeb96952f668baef2fd18383806e13a20415f19..f612cb847aca981e16cb6006fa08d870497c6263 100755 (executable)
@@ -117,7 +117,7 @@ case "${1:-.}${2:-.}${3:-.}" in
 
                # If we do not have enough common material, it is not
                # worth trying two-file merge using common subsections.
-               expr "$sz0" \< "$sz1" \* 2 >/dev/null || : >$orig
+               expr $sz0 \< $sz1 \* 2 >/dev/null || : >$orig
                ;;
        *)
                echo "Auto-merging $4"
index 8fc65d0400545e30fd56f890e6b17052f54f857c..ed630b208a80a36d729b5074a39bc53df0cabd59 100644 (file)
@@ -21,7 +21,7 @@ check_unchanged () {
                do
                        echo "$MERGED seems unchanged."
                        printf "Was the merge successful? [y/n] "
-                       read answer
+                       read answer || return 1
                        case "$answer" in
                        y*|Y*) status=0; break ;;
                        n*|N*) status=1; break ;;
index 3c157bcd26232c758572bf908add44216cb8e2e7..085e213a126e5864befc8e3436832ae3c587a624 100755 (executable)
@@ -72,7 +72,7 @@ describe_file () {
 resolve_symlink_merge () {
     while true; do
        printf "Use (l)ocal or (r)emote, or (a)bort? "
-       read ans
+       read ans || return 1
        case "$ans" in
            [lL]*)
                git checkout-index -f --stage=2 -- "$MERGED"
@@ -342,64 +342,42 @@ merge_keep_temporaries="$(git config --bool mergetool.keepTemporaries || echo fa
 
 last_status=0
 rollup_status=0
-rerere=false
-
-files_to_merge() {
-    if test "$rerere" = true
-    then
-       git rerere remaining
-    else
-       git ls-files -u | sed -e 's/^[^ ]*      //' | sort -u
-    fi
-}
-
+files=
 
 if test $# -eq 0 ; then
     cd_to_toplevel
 
     if test -e "$GIT_DIR/MERGE_RR"
     then
-       rerere=true
-    fi
-
-    files=$(files_to_merge)
-    if test -z "$files" ; then
-       echo "No files need merging"
-       exit 0
+       files=$(git rerere remaining)
+    else
+       files=$(git ls-files -u | sed -e 's/^[^ ]*      //' | sort -u)
     fi
+else
+    files=$(git ls-files -u -- "$@" | sed -e 's/^[^    ]*      //' | sort -u)
+fi
 
-    # Save original stdin
-    exec 3<&0
+if test -z "$files" ; then
+    echo "No files need merging"
+    exit 0
+fi
 
-    printf "Merging:\n"
-    printf "$files\n"
+printf "Merging:\n"
+printf "$files\n"
 
-    files_to_merge |
-    while IFS= read i
-    do
-       if test $last_status -ne 0; then
-           prompt_after_failed_merge <&3 || exit 1
-       fi
-       printf "\n"
-       merge_file "$i" <&3
-       last_status=$?
-       if test $last_status -ne 0; then
-           rollup_status=1
-       fi
-    done
-else
-    while test $# -gt 0; do
-       if test $last_status -ne 0; then
-           prompt_after_failed_merge || exit 1
-       fi
-       printf "\n"
-       merge_file "$1"
-       last_status=$?
-       if test $last_status -ne 0; then
-           rollup_status=1
-       fi
-       shift
-    done
-fi
+IFS='
+'
+for i in $files
+do
+    if test $last_status -ne 0; then
+       prompt_after_failed_merge || exit 1
+    fi
+    printf "\n"
+    merge_file "$i"
+    last_status=$?
+    if test $last_status -ne 0; then
+       rollup_status=1
+    fi
+done
 
 exit $rollup_status
index c6ba7c15510935353bd17b2b8d8188fe16052907..94f36c254c53366ba53d256c0bd50a1de07cdb85 100644 (file)
@@ -472,18 +472,24 @@ do_next () {
                git rev-parse --verify HEAD > "$state_dir"/stopped-sha
                ${SHELL:-@SHELL_PATH@} -c "$rest" # Actual execution
                status=$?
+               # Run in subshell because require_clean_work_tree can die.
+               dirty=f
+               (require_clean_work_tree "rebase" 2>/dev/null) || dirty=t
                if test "$status" -ne 0
                then
                        warn "Execution failed: $rest"
+                       test "$dirty" = f ||
+                       warn "and made changes to the index and/or the working tree"
+
                        warn "You can fix the problem, and then run"
                        warn
                        warn "  git rebase --continue"
                        warn
                        exit "$status"
-               fi
-               # Run in subshell because require_clean_work_tree can die.
-               if ! (require_clean_work_tree "rebase")
+               elif test "$dirty" = t
                then
+                       warn "Execution succeeded: $rest"
+                       warn "but left changes to the index and/or the working tree"
                        warn "Commit or stash your changes, and then run"
                        warn
                        warn "  git rebase --continue"
@@ -647,8 +653,24 @@ continue)
        then
                : Nothing to commit -- skip this
        else
+               if ! test -f "$author_script"
+               then
+                       die "You have staged changes in your working tree. If these changes are meant to be
+squashed into the previous commit, run:
+
+  git commit --amend
+
+If they are meant to go into a new commit, run:
+
+  git commit
+
+In both case, once you're done, continue with:
+
+  git rebase --continue
+"
+               fi
                . "$author_script" ||
-                       die "Cannot find the author identity"
+                       die "Error trying to find the author identity to amend commit"
                current_head=
                if test -f "$amend"
                then
index e9c832bfd3da7db771cc2113027d3e590dc51d59..3dc4851cfc70a2804b23a8eca4dac7702ae93c87 100644 (file)
@@ -1,5 +1,18 @@
 #!/usr/bin/env python
 
+# This command is a simple remote-helper, that is used both as a
+# testcase for the remote-helper functionality, and as an example to
+# show remote-helper authors one possible implementation.
+#
+# This is a Git <-> Git importer/exporter, that simply uses git
+# fast-import and git fast-export to consume and produce fast-import
+# streams.
+#
+# To understand better the way things work, one can activate debug
+# traces by setting (to any value) the environment variables
+# GIT_TRANSPORT_HELPER_DEBUG and GIT_DEBUG_TESTGIT, to see messages
+# from the transport-helper side, or from this example remote-helper.
+
 # hashlib is only available in python >= 2.5
 try:
     import hashlib
index d0678372b9fd263d1ef896a04cb1fd0d8f1ba564..351e743a902568c8b6f68ffaf4030f087ba8568d 100755 (executable)
@@ -508,6 +508,195 @@ sub cmd_set_tree {
        unlink $gs->{index};
 }
 
+sub split_merge_info_range {
+       my ($range) = @_;
+       if ($range =~ /(\d+)-(\d+)/) {
+               return (int($1), int($2));
+       } else {
+               return (int($range), int($range));
+       }
+}
+
+sub combine_ranges {
+       my ($in) = @_;
+
+       my @fnums = ();
+       my @arr = split(/,/, $in);
+       for my $element (@arr) {
+               my ($start, $end) = split_merge_info_range($element);
+               push @fnums, $start;
+       }
+
+       my @sorted = @arr [ sort {
+               $fnums[$a] <=> $fnums[$b]
+       } 0..$#arr ];
+
+       my @return = ();
+       my $last = -1;
+       my $first = -1;
+       for my $element (@sorted) {
+               my ($start, $end) = split_merge_info_range($element);
+
+               if ($last == -1) {
+                       $first = $start;
+                       $last = $end;
+                       next;
+               }
+               if ($start <= $last+1) {
+                       if ($end > $last) {
+                               $last = $end;
+                       }
+                       next;
+               }
+               if ($first == $last) {
+                       push @return, "$first";
+               } else {
+                       push @return, "$first-$last";
+               }
+               $first = $start;
+               $last = $end;
+       }
+
+       if ($first != -1) {
+               if ($first == $last) {
+                       push @return, "$first";
+               } else {
+                       push @return, "$first-$last";
+               }
+       }
+
+       return join(',', @return);
+}
+
+sub merge_revs_into_hash {
+       my ($hash, $minfo) = @_;
+       my @lines = split(' ', $minfo);
+
+       for my $line (@lines) {
+               my ($branchpath, $revs) = split(/:/, $line);
+
+               if (exists($hash->{$branchpath})) {
+                       # Merge the two revision sets
+                       my $combined = "$hash->{$branchpath},$revs";
+                       $hash->{$branchpath} = combine_ranges($combined);
+               } else {
+                       # Just do range combining for consolidation
+                       $hash->{$branchpath} = combine_ranges($revs);
+               }
+       }
+}
+
+sub merge_merge_info {
+       my ($mergeinfo_one, $mergeinfo_two) = @_;
+       my %result_hash = ();
+
+       merge_revs_into_hash(\%result_hash, $mergeinfo_one);
+       merge_revs_into_hash(\%result_hash, $mergeinfo_two);
+
+       my $result = '';
+       # Sort below is for consistency's sake
+       for my $branchname (sort keys(%result_hash)) {
+               my $revlist = $result_hash{$branchname};
+               $result .= "$branchname:$revlist\n"
+       }
+       return $result;
+}
+
+sub populate_merge_info {
+       my ($d, $gs, $uuid, $linear_refs, $rewritten_parent) = @_;
+
+       my %parentshash;
+       read_commit_parents(\%parentshash, $d);
+       my @parents = @{$parentshash{$d}};
+       if ($#parents > 0) {
+               # Merge commit
+               my $all_parents_ok = 1;
+               my $aggregate_mergeinfo = '';
+               my $rooturl = $gs->repos_root;
+
+               if (defined($rewritten_parent)) {
+                       # Replace first parent with newly-rewritten version
+                       shift @parents;
+                       unshift @parents, $rewritten_parent;
+               }
+
+               foreach my $parent (@parents) {
+                       my ($branchurl, $svnrev, $paruuid) =
+                               cmt_metadata($parent);
+
+                       unless (defined($svnrev)) {
+                               # Should have been caught be preflight check
+                               fatal "merge commit $d has ancestor $parent, but that change "
+                     ."does not have git-svn metadata!";
+                       }
+                       unless ($branchurl =~ /^$rooturl(.*)/) {
+                               fatal "commit $parent git-svn metadata changed mid-run!";
+                       }
+                       my $branchpath = $1;
+
+                       my $ra = Git::SVN::Ra->new($branchurl);
+                       my (undef, undef, $props) =
+                               $ra->get_dir(canonicalize_path("."), $svnrev);
+                       my $par_mergeinfo = $props->{'svn:mergeinfo'};
+                       unless (defined $par_mergeinfo) {
+                               $par_mergeinfo = '';
+                       }
+                       # Merge previous mergeinfo values
+                       $aggregate_mergeinfo =
+                               merge_merge_info($aggregate_mergeinfo,
+                                                                $par_mergeinfo, 0);
+
+                       next if $parent eq $parents[0]; # Skip first parent
+                       # Add new changes being placed in tree by merge
+                       my @cmd = (qw/rev-list --reverse/,
+                                          $parent, qw/--not/);
+                       foreach my $par (@parents) {
+                               unless ($par eq $parent) {
+                                       push @cmd, $par;
+                               }
+                       }
+                       my @revsin = ();
+                       my ($revlist, $ctx) = command_output_pipe(@cmd);
+                       while (<$revlist>) {
+                               my $irev = $_;
+                               chomp $irev;
+                               my (undef, $csvnrev, undef) =
+                                       cmt_metadata($irev);
+                               unless (defined $csvnrev) {
+                                       # A child is missing SVN annotations...
+                                       # this might be OK, or might not be.
+                                       warn "W:child $irev is merged into revision "
+                                                ."$d but does not have git-svn metadata. "
+                                                ."This means git-svn cannot determine the "
+                                                ."svn revision numbers to place into the "
+                                                ."svn:mergeinfo property. You must ensure "
+                                                ."a branch is entirely committed to "
+                                                ."SVN before merging it in order for "
+                                                ."svn:mergeinfo population to function "
+                                                ."properly";
+                               }
+                               push @revsin, $csvnrev;
+                       }
+                       command_close_pipe($revlist, $ctx);
+
+                       last unless $all_parents_ok;
+
+                       # We now have a list of all SVN revnos which are
+                       # merged by this particular parent. Integrate them.
+                       next if $#revsin == -1;
+                       my $newmergeinfo = "$branchpath:" . join(',', @revsin);
+                       $aggregate_mergeinfo =
+                               merge_merge_info($aggregate_mergeinfo,
+                                                                $newmergeinfo, 1);
+               }
+               if ($all_parents_ok and $aggregate_mergeinfo) {
+                       return $aggregate_mergeinfo;
+               }
+       }
+
+       return undef;
+}
+
 sub cmd_dcommit {
        my $head = shift;
        command_noisy(qw/update-index --refresh/);
@@ -558,6 +747,62 @@ sub cmd_dcommit {
                     "without --no-rebase may be required."
        }
        my $expect_url = $url;
+
+       my $push_merge_info = eval {
+               command_oneline(qw/config --get svn.pushmergeinfo/)
+               };
+       if (not defined($push_merge_info)
+                       or $push_merge_info eq "false"
+                       or $push_merge_info eq "no"
+                       or $push_merge_info eq "never") {
+               $push_merge_info = 0;
+       }
+
+       unless (defined($_merge_info) || ! $push_merge_info) {
+               # Preflight check of changes to ensure no issues with mergeinfo
+               # This includes check for uncommitted-to-SVN parents
+               # (other than the first parent, which we will handle),
+               # information from different SVN repos, and paths
+               # which are not underneath this repository root.
+               my $rooturl = $gs->repos_root;
+               foreach my $d (@$linear_refs) {
+                       my %parentshash;
+                       read_commit_parents(\%parentshash, $d);
+                       my @realparents = @{$parentshash{$d}};
+                       if ($#realparents > 0) {
+                               # Merge commit
+                               shift @realparents; # Remove/ignore first parent
+                               foreach my $parent (@realparents) {
+                                       my ($branchurl, $svnrev, $paruuid) = cmt_metadata($parent);
+                                       unless (defined $paruuid) {
+                                               # A parent is missing SVN annotations...
+                                               # abort the whole operation.
+                                               fatal "$parent is merged into revision $d, "
+                                                        ."but does not have git-svn metadata. "
+                                                        ."Either dcommit the branch or use a "
+                                                        ."local cherry-pick, FF merge, or rebase "
+                                                        ."instead of an explicit merge commit.";
+                                       }
+
+                                       unless ($paruuid eq $uuid) {
+                                               # Parent has SVN metadata from different repository
+                                               fatal "merge parent $parent for change $d has "
+                                                        ."git-svn uuid $paruuid, while current change "
+                                                        ."has uuid $uuid!";
+                                       }
+
+                                       unless ($branchurl =~ /^$rooturl(.*)/) {
+                                               # This branch is very strange indeed.
+                                               fatal "merge parent $parent for $d is on branch "
+                                                        ."$branchurl, which is not under the "
+                                                        ."git-svn root $rooturl!";
+                                       }
+                               }
+                       }
+               }
+       }
+
+       my $rewritten_parent;
        Git::SVN::remove_username($expect_url);
        if (defined($_merge_info)) {
                $_merge_info =~ tr{ }{\n};
@@ -575,6 +820,14 @@ sub cmd_dcommit {
                        print "diff-tree $d~1 $d\n";
                } else {
                        my $cmt_rev;
+
+                       unless (defined($_merge_info) || ! $push_merge_info) {
+                               $_merge_info = populate_merge_info($d, $gs,
+                                                            $uuid,
+                                                            $linear_refs,
+                                                            $rewritten_parent);
+                       }
+
                        my %ed_opts = ( r => $last_rev,
                                        log => get_commit_entry($d)->{log},
                                        ra => Git::SVN::Ra->new($url),
@@ -617,6 +870,9 @@ sub cmd_dcommit {
                                @finish = qw/reset --mixed/;
                        }
                        command_noisy(@finish, $gs->refname);
+
+                       $rewritten_parent = command_oneline(qw/rev-parse HEAD/);
+
                        if (@diff) {
                                @refs = ();
                                my ($url_, $rev_, $uuid_, $gs_) =
index 93dd2bdd91b2b4b851f4ddc3b806e58bde792d56..fa2596f77c645b87e79aceb242d6074d6b2764ea 100644 (file)
@@ -16,7 +16,7 @@
  * and other reasons to not add 'js=1' param at the end of link
  * @constant
  */
-var jsExceptionsRe = /[;?]js=[01]$/;
+var jsExceptionsRe = /[;?]js=[01](#.*)?$/;
 
 /**
  * Add '?js=1' or ';js=1' to the end of every link in the document
@@ -33,9 +33,9 @@ function fixLinks() {
        var allLinks = document.getElementsByTagName("a") || document.links;
        for (var i = 0, len = allLinks.length; i < len; i++) {
                var link = allLinks[i];
-               if (!jsExceptionsRe.test(link)) { // =~ /[;?]js=[01]$/;
-                       link.href +=
-                               (link.href.indexOf('?') === -1 ? '?' : ';') + 'js=1';
+               if (!jsExceptionsRe.test(link)) {
+                       link.href = link.href.replace(/(#|$)/,
+                               (link.href.indexOf('?') === -1 ? '?' : ';') + 'js=1$1');
                }
        }
 }
index 376331a76fcde24e6828eba0b88fec26d93fe56f..44f814cda2a9756a55cb7f332d5fef0e5484256b 100644 (file)
@@ -1606,10 +1606,10 @@ static void fetch_symref(const char *path, char **symref, unsigned char *sha1)
        strbuf_release(&buffer);
 }
 
-static int verify_merge_base(unsigned char *head_sha1, unsigned char *branch_sha1)
+static int verify_merge_base(unsigned char *head_sha1, struct ref *remote)
 {
-       struct commit *head = lookup_commit(head_sha1);
-       struct commit *branch = lookup_commit(branch_sha1);
+       struct commit *head = lookup_commit_or_die(head_sha1, "HEAD");
+       struct commit *branch = lookup_commit_or_die(remote->old_sha1, remote->name);
        struct commit_list *merge_bases = get_merge_bases(head, branch, 1);
 
        return (merge_bases && !merge_bases->next && merge_bases->item == branch);
@@ -1680,7 +1680,7 @@ static int delete_remote_branch(const char *pattern, int force)
                        return error("Remote branch %s resolves to object %s\nwhich does not exist locally, perhaps you need to fetch?", remote_ref->name, sha1_to_hex(remote_ref->old_sha1));
 
                /* Remote branch must be an ancestor of remote HEAD */
-               if (!verify_merge_base(head_sha1, remote_ref->old_sha1)) {
+               if (!verify_merge_base(head_sha1, remote_ref)) {
                        return error("The branch '%s' is not an ancestor "
                                     "of your current HEAD.\n"
                                     "If you are sure you want to delete it,"
index 6bbc4512a9d44f18e8fc8d38b9ddb79e8e7ff1e6..c34a4f148b65cf81f28e2aed6c35e141e175b324 100644 (file)
@@ -390,7 +390,7 @@ static void record_df_conflict_files(struct merge_options *o,
                                     struct string_list *entries)
 {
        /* If there is a D/F conflict and the file for such a conflict
-        * currently exist in the working copy, we want to allow it to be
+        * currently exist in the working tree, we want to allow it to be
         * removed to make room for the corresponding directory if needed.
         * The files underneath the directories of such D/F conflicts will
         * be processed before the corresponding file involved in the D/F
@@ -1627,7 +1627,7 @@ static int merge_content(struct merge_options *o,
                path_renamed_outside_HEAD = !path2 || !strcmp(path, path2);
                if (!path_renamed_outside_HEAD) {
                        add_cacheinfo(mfi.mode, mfi.sha, path,
-                                     0 /*stage*/, 1 /*refresh*/, 0 /*options*/);
+                                     0, (!o->call_depth), 0);
                        return mfi.clean;
                }
        } else
index e1aaf43b438d0cfb6b7b0c723060a662a915bcea..baaf31f4aed4e4cfd967c278b7cfd4bee6a0ab30 100644 (file)
@@ -680,7 +680,7 @@ int notes_merge_commit(struct notes_merge_options *o,
         * Finally store the new commit object SHA1 into 'result_sha1'.
         */
        struct dir_struct dir;
-       const char *path = git_path(NOTES_MERGE_WORKTREE "/");
+       char *path = xstrdup(git_path(NOTES_MERGE_WORKTREE "/"));
        int path_len = strlen(path), i;
        const char *msg = strstr(partial_commit->buffer, "\n\n");
 
@@ -720,6 +720,7 @@ int notes_merge_commit(struct notes_merge_options *o,
                            result_sha1);
        OUTPUT(o, 4, "Finalized notes merge commit: %s",
               sha1_to_hex(result_sha1));
+       free(path);
        return 0;
 }
 
index c46cfaa3e4d2f06fd67ccd71c7ba47891796fd60..3d2deedaf8e50c6a71b9750dacf602bb5b9238b9 100644 (file)
@@ -729,12 +729,16 @@ static void limit_to_ancestry(struct commit_list *bottom, struct commit_list *li
  * to filter the result of "A..B" further to the ones that can actually
  * reach A.
  */
-static struct commit_list *collect_bottom_commits(struct commit_list *list)
+static struct commit_list *collect_bottom_commits(struct rev_info *revs)
 {
-       struct commit_list *elem, *bottom = NULL;
-       for (elem = list; elem; elem = elem->next)
-               if (elem->item->object.flags & UNINTERESTING)
-                       commit_list_insert(elem->item, &bottom);
+       struct commit_list *bottom = NULL;
+       int i;
+       for (i = 0; i < revs->cmdline.nr; i++) {
+               struct rev_cmdline_entry *elem = &revs->cmdline.rev[i];
+               if ((elem->flags & UNINTERESTING) &&
+                   elem->item->type == OBJ_COMMIT)
+                       commit_list_insert((struct commit *)elem->item, &bottom);
+       }
        return bottom;
 }
 
@@ -765,7 +769,7 @@ static int limit_list(struct rev_info *revs)
        struct commit_list *bottom = NULL;
 
        if (revs->ancestry_path) {
-               bottom = collect_bottom_commits(list);
+               bottom = collect_bottom_commits(revs);
                if (!bottom)
                        die("--ancestry-path given but there are no bottom commits");
        }
@@ -822,6 +826,23 @@ static int limit_list(struct rev_info *revs)
        return 0;
 }
 
+static void add_rev_cmdline(struct rev_info *revs,
+                           struct object *item,
+                           const char *name,
+                           int whence,
+                           unsigned flags)
+{
+       struct rev_cmdline_info *info = &revs->cmdline;
+       int nr = info->nr;
+
+       ALLOC_GROW(info->rev, nr + 1, info->alloc);
+       info->rev[nr].item = item;
+       info->rev[nr].name = name;
+       info->rev[nr].whence = whence;
+       info->rev[nr].flags = flags;
+       info->nr++;
+}
+
 struct all_refs_cb {
        int all_flags;
        int warned_bad_reflog;
@@ -834,6 +855,7 @@ static int handle_one_ref(const char *path, const unsigned char *sha1, int flag,
        struct all_refs_cb *cb = cb_data;
        struct object *object = get_reference(cb->all_revs, path, sha1,
                                              cb->all_flags);
+       add_rev_cmdline(cb->all_revs, object, path, REV_CMD_REF, cb->all_flags);
        add_pending_object(cb->all_revs, object, path);
        return 0;
 }
@@ -860,6 +882,7 @@ static void handle_one_reflog_commit(unsigned char *sha1, void *cb_data)
                struct object *o = parse_object(sha1);
                if (o) {
                        o->flags |= cb->all_flags;
+                       /* ??? CMDLINEFLAGS ??? */
                        add_pending_object(cb->all_revs, o, "");
                }
                else if (!cb->warned_bad_reflog) {
@@ -896,12 +919,13 @@ static void handle_reflog(struct rev_info *revs, unsigned flags)
        for_each_reflog(handle_one_reflog, &cb);
 }
 
-static int add_parents_only(struct rev_info *revs, const char *arg, int flags)
+static int add_parents_only(struct rev_info *revs, const char *arg_, int flags)
 {
        unsigned char sha1[20];
        struct object *it;
        struct commit *commit;
        struct commit_list *parents;
+       const char *arg = arg_;
 
        if (*arg == '^') {
                flags ^= UNINTERESTING;
@@ -925,6 +949,7 @@ static int add_parents_only(struct rev_info *revs, const char *arg, int flags)
        for (parents = commit->parents; parents; parents = parents->next) {
                it = &parents->item->object;
                it->flags |= flags;
+               add_rev_cmdline(revs, it, arg_, REV_CMD_PARENTS_ONLY, flags);
                add_pending_object(revs, it, arg);
        }
        return 1;
@@ -986,10 +1011,12 @@ static void prepare_show_merge(struct rev_info *revs)
        const char **prune = NULL;
        int i, prune_num = 1; /* counting terminating NULL */
 
-       if (get_sha1("HEAD", sha1) || !(head = lookup_commit(sha1)))
+       if (get_sha1("HEAD", sha1))
                die("--merge without HEAD?");
-       if (get_sha1("MERGE_HEAD", sha1) || !(other = lookup_commit(sha1)))
+       head = lookup_commit_or_die(sha1, "HEAD");
+       if (get_sha1("MERGE_HEAD", sha1))
                die("--merge without MERGE_HEAD?");
+       other = lookup_commit_or_die(sha1, "MERGE_HEAD");
        add_pending_object(revs, &head->object, "HEAD");
        add_pending_object(revs, &other->object, "MERGE_HEAD");
        bases = get_merge_bases(head, other, 1);
@@ -1018,7 +1045,7 @@ static void prepare_show_merge(struct rev_info *revs)
        revs->limited = 1;
 }
 
-int handle_revision_arg(const char *arg, struct rev_info *revs,
+int handle_revision_arg(const char *arg_, struct rev_info *revs,
                        int flags,
                        int cant_be_filename)
 {
@@ -1027,6 +1054,7 @@ int handle_revision_arg(const char *arg, struct rev_info *revs,
        struct object *object;
        unsigned char sha1[20];
        int local_flags;
+       const char *arg = arg_;
 
        dotdot = strstr(arg, "..");
        if (dotdot) {
@@ -1035,6 +1063,7 @@ int handle_revision_arg(const char *arg, struct rev_info *revs,
                const char *this = arg;
                int symmetric = *next == '.';
                unsigned int flags_exclude = flags ^ UNINTERESTING;
+               unsigned int a_flags;
 
                *dotdot = 0;
                next += symmetric;
@@ -1069,10 +1098,15 @@ int handle_revision_arg(const char *arg, struct rev_info *revs,
                                add_pending_commit_list(revs, exclude,
                                                        flags_exclude);
                                free_commit_list(exclude);
-                               a->object.flags |= flags | SYMMETRIC_LEFT;
+                               a_flags = flags | SYMMETRIC_LEFT;
                        } else
-                               a->object.flags |= flags_exclude;
+                               a_flags = flags_exclude;
+                       a->object.flags |= a_flags;
                        b->object.flags |= flags;
+                       add_rev_cmdline(revs, &a->object, this,
+                                       REV_CMD_LEFT, a_flags);
+                       add_rev_cmdline(revs, &b->object, next,
+                                       REV_CMD_RIGHT, flags);
                        add_pending_object(revs, &a->object, this);
                        add_pending_object(revs, &b->object, next);
                        return 0;
@@ -1103,6 +1137,7 @@ int handle_revision_arg(const char *arg, struct rev_info *revs,
        if (!cant_be_filename)
                verify_non_filename(revs->prefix, arg);
        object = get_reference(revs, arg, sha1, flags ^ local_flags);
+       add_rev_cmdline(revs, object, arg_, REV_CMD_REV, flags ^ local_flags);
        add_pending_object_with_mode(revs, object, arg, mode);
        return 0;
 }
index 3d64adad18e2c889b7a7b7367f99c239f958dc70..93d31556cb44d3e4c5162d21c8e92d572a36508e 100644 (file)
@@ -24,6 +24,23 @@ struct rev_info;
 struct log_info;
 struct string_list;
 
+struct rev_cmdline_info {
+       unsigned int nr;
+       unsigned int alloc;
+       struct rev_cmdline_entry {
+               struct object *item;
+               const char *name;
+               enum {
+                       REV_CMD_REF,
+                       REV_CMD_PARENTS_ONLY,
+                       REV_CMD_LEFT,
+                       REV_CMD_RIGHT,
+                       REV_CMD_REV
+               } whence;
+               unsigned flags;
+       } *rev;
+};
+
 struct rev_info {
        /* Starting list */
        struct commit_list *commits;
@@ -32,6 +49,9 @@ struct rev_info {
        /* Parents of shown commits */
        struct object_array boundary_commits;
 
+       /* The end-points specified by the end user */
+       struct rev_cmdline_info cmdline;
+
        /* Basic information */
        const char *prefix;
        const char *def;
index 9ff1b597c995780026a32a92fab78a780d60329a..3ad2cc00160fbf24e1e4904bb37ce44e8c414ce5 100644 (file)
--- a/strbuf.c
+++ b/strbuf.c
@@ -357,7 +357,6 @@ int strbuf_getwholeline(struct strbuf *sb, FILE *fp, int term)
 {
        int ch;
 
-       strbuf_grow(sb, 0);
        if (feof(fp))
                return EOF;
 
index 7a76edf911d941722586abb4f38284fc4e6909ec..08756387e207700861cfa6dac039334ecd53c7a1 100644 (file)
@@ -8,12 +8,17 @@
 #include "diffcore.h"
 #include "refs.h"
 #include "string-list.h"
+#include "sha1-array.h"
 
 static struct string_list config_name_for_path;
 static struct string_list config_fetch_recurse_submodules_for_name;
 static struct string_list config_ignore_for_name;
 static int config_fetch_recurse_submodules = RECURSE_SUBMODULES_ON_DEMAND;
 static struct string_list changed_submodule_paths;
+static int initialized_fetch_ref_tips;
+static struct sha1_array ref_tips_before_fetch;
+static struct sha1_array ref_tips_after_fetch;
+
 /*
  * The following flag is set if the .gitmodules file is unmerged. We then
  * disable recursion for all submodules where .git/config doesn't have a
@@ -474,16 +479,76 @@ static void submodule_collect_changed_cb(struct diff_queue_struct *q,
        }
 }
 
+static int add_sha1_to_array(const char *ref, const unsigned char *sha1,
+                            int flags, void *data)
+{
+       sha1_array_append(data, sha1);
+       return 0;
+}
+
 void check_for_new_submodule_commits(unsigned char new_sha1[20])
+{
+       if (!initialized_fetch_ref_tips) {
+               for_each_ref(add_sha1_to_array, &ref_tips_before_fetch);
+               initialized_fetch_ref_tips = 1;
+       }
+
+       sha1_array_append(&ref_tips_after_fetch, new_sha1);
+}
+
+struct argv_array {
+       const char **argv;
+       unsigned int argc;
+       unsigned int alloc;
+};
+
+static void init_argv(struct argv_array *array)
+{
+       array->argv = NULL;
+       array->argc = 0;
+       array->alloc = 0;
+}
+
+static void push_argv(struct argv_array *array, const char *value)
+{
+       ALLOC_GROW(array->argv, array->argc + 2, array->alloc);
+       array->argv[array->argc++] = xstrdup(value);
+       array->argv[array->argc] = NULL;
+}
+
+static void clear_argv(struct argv_array *array)
+{
+       int i;
+       for (i = 0; i < array->argc; i++)
+               free((char **)array->argv[i]);
+       free(array->argv);
+       init_argv(array);
+}
+
+static void add_sha1_to_argv(const unsigned char sha1[20], void *data)
+{
+       push_argv(data, sha1_to_hex(sha1));
+}
+
+static void calculate_changed_submodule_paths(void)
 {
        struct rev_info rev;
        struct commit *commit;
-       const char *argv[] = {NULL, NULL, "--not", "--all", NULL};
-       int argc = ARRAY_SIZE(argv) - 1;
+       struct argv_array argv;
+
+       /* No need to check if there are no submodules configured */
+       if (!config_name_for_path.nr)
+               return;
 
        init_revisions(&rev, NULL);
-       argv[1] = xstrdup(sha1_to_hex(new_sha1));
-       setup_revisions(argc, argv, &rev, NULL);
+       init_argv(&argv);
+       push_argv(&argv, "--"); /* argv[0] program name */
+       sha1_array_for_each_unique(&ref_tips_after_fetch,
+                                  add_sha1_to_argv, &argv);
+       push_argv(&argv, "--not");
+       sha1_array_for_each_unique(&ref_tips_before_fetch,
+                                  add_sha1_to_argv, &argv);
+       setup_revisions(argv.argc, argv.argv, &rev, NULL);
        if (prepare_revision_walk(&rev))
                die("revision walk setup failed");
 
@@ -507,7 +572,11 @@ void check_for_new_submodule_commits(unsigned char new_sha1[20])
                        parent = parent->next;
                }
        }
-       free((char *)argv[1]);
+
+       clear_argv(&argv);
+       sha1_array_clear(&ref_tips_before_fetch);
+       sha1_array_clear(&ref_tips_after_fetch);
+       initialized_fetch_ref_tips = 0;
 }
 
 int fetch_populated_submodules(int num_options, const char **options,
@@ -541,6 +610,8 @@ int fetch_populated_submodules(int num_options, const char **options,
        cp.git_cmd = 1;
        cp.no_stdin = 1;
 
+       calculate_changed_submodule_paths();
+
        for (i = 0; i < active_nr; i++) {
                struct strbuf submodule_path = STRBUF_INIT;
                struct strbuf submodule_git_dir = STRBUF_INIT;
index f87abb5a0682d7a2fc7c3947789301c4157d331d..1d29810a7a94dad15645869c2f4f015a470fa622 100755 (executable)
@@ -40,6 +40,12 @@ check_parse 2008-02 bad
 check_parse 2008-02-14 bad
 check_parse '2008-02-14 20:30:45' '2008-02-14 20:30:45 +0000'
 check_parse '2008-02-14 20:30:45 -0500' '2008-02-14 20:30:45 -0500'
+check_parse '2008-02-14 20:30:45 -0015' '2008-02-14 20:30:45 -0015'
+check_parse '2008-02-14 20:30:45 -5' '2008-02-14 20:30:45 +0000'
+check_parse '2008-02-14 20:30:45 -5:' '2008-02-14 20:30:45 +0000'
+check_parse '2008-02-14 20:30:45 -05' '2008-02-14 20:30:45 -0500'
+check_parse '2008-02-14 20:30:45 -:30' '2008-02-14 20:30:45 +0000'
+check_parse '2008-02-14 20:30:45 -05:00' '2008-02-14 20:30:45 -0500'
 check_parse '2008-02-14 20:30:45' '2008-02-14 20:30:45 -0500' EST5
 
 check_approxidate() {
index 3e140c18f4183c41c76aaab0834f1d23ce7bcd2d..dffccf84f8f67ae8dc13eae4547eb4c7c687de1d 100755 (executable)
@@ -333,6 +333,12 @@ test_expect_success 'get-regexp variable with no value' \
        'git config --get-regexp novalue > output &&
         cmp output expect'
 
+echo 'novalue.variable true' > expect
+
+test_expect_success 'get-regexp --bool variable with no value' \
+       'git config --bool --get-regexp novalue > output &&
+        cmp output expect'
+
 echo 'emptyvalue.variable ' > expect
 
 test_expect_success 'get-regexp variable with empty value' \
index b5d89a2250e41afe544b0d0f59f638e02d570cdd..2b962cfda70d998e9c2799cf8fc720b330cd118a 100755 (executable)
@@ -25,6 +25,11 @@ else
        test_set_prereq SETFACL
 fi
 
+if test -z "$LOGNAME"
+then
+       LOGNAME=$USER
+fi
+
 check_perms_and_acl () {
        test -r "$1" &&
        getfacl "$1" > actual &&
diff --git a/t/t2022-checkout-paths.sh b/t/t2022-checkout-paths.sh
new file mode 100755 (executable)
index 0000000..56090d2
--- /dev/null
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+test_description='checkout $tree -- $paths'
+. ./test-lib.sh
+
+test_expect_success setup '
+       mkdir dir &&
+       >dir/master &&
+       echo common >dir/common &&
+       git add dir/master dir/common &&
+       test_tick && git commit -m "master has dir/master" &&
+       git checkout -b next &&
+       git mv dir/master dir/next0 &&
+       echo next >dir/next1 &&
+       git add dir &&
+       test_tick && git commit -m "next has dir/next but not dir/master"
+'
+
+test_expect_success 'checking out paths out of a tree does not clobber unrelated paths' '
+       git checkout next &&
+       git reset --hard &&
+       rm dir/next0 &&
+       cat dir/common >expect.common &&
+       echo modified >expect.next1 &&
+       cat expect.next1 >dir/next1 &&
+       echo untracked >expect.next2 &&
+       cat expect.next2 >dir/next2 &&
+
+       git checkout master dir &&
+
+       test_cmp expect.common dir/common &&
+       test_path_is_file dir/master &&
+       git diff --exit-code master dir/master &&
+
+       test_path_is_missing dir/next0 &&
+       test_cmp expect.next1 dir/next1 &&
+       test_path_is_file dir/next2 &&
+       test_must_fail git ls-files --error-unmatch dir/next2 &&
+       test_cmp expect.next2 dir/next2
+'
+
+test_done
index cb6458d1c820bd131af4659fe878ff9406fbbcac..7633930bb472e1c9aebf2799f3eaf3bc53c7263c 100755 (executable)
@@ -554,4 +554,17 @@ test_expect_success 'attempt to delete a branch merged to its base' '
        test_must_fail git branch -d my10
 '
 
+test_expect_success 'use set-upstream on the current branch' '
+       git checkout master &&
+       git --bare init myupstream.git &&
+       git push myupstream.git master:refs/heads/frotz &&
+       git remote add origin myupstream.git &&
+       git fetch &&
+       git branch --set-upstream master origin/frotz &&
+
+       test "z$(git config branch.master.remote)" = "zorigin" &&
+       test "z$(git config branch.master.merge)" = "zrefs/heads/frotz"
+
+'
+
 test_done
index 8538813d1d0dfa72008da1d711cf2c042796a6ee..b981572d736a1adf8da5281f31e580982e2059af 100755 (executable)
@@ -527,6 +527,20 @@ test_expect_success 'auto-amend only edited commits after "edit"' '
        git rebase --abort
 '
 
+test_expect_success 'clean error after failed "exec"' '
+       test_tick &&
+       test_when_finished "git rebase --abort || :" &&
+       (
+               FAKE_LINES="1 exec_false" &&
+               export FAKE_LINES &&
+               test_must_fail git rebase -i HEAD^
+       ) &&
+       echo "edited again" > file7 &&
+       git add file7 &&
+       test_must_fail git rebase --continue 2>error &&
+       grep "You have staged changes in your working tree." error
+'
+
 test_expect_success 'rebase a detached HEAD' '
        grandparent=$(git rev-parse HEAD~2) &&
        git checkout $(git rev-parse HEAD) &&
index 5cbc066e68e15b1015d9b8838b44a8042d4f04fd..67975129bc3703e16fe52eb916c2e08b7908ff87 100755 (executable)
@@ -457,22 +457,22 @@ test_expect_success 'thread deep cover-letter in-reply-to' '
 '
 
 test_expect_success 'thread via config' '
-       git config format.thread true &&
+       test_config format.thread true &&
        check_threading expect.thread master
 '
 
 test_expect_success 'thread deep via config' '
-       git config format.thread deep &&
+       test_config format.thread deep &&
        check_threading expect.deep master
 '
 
 test_expect_success 'thread config + override' '
-       git config format.thread deep &&
+       test_config format.thread deep &&
        check_threading expect.thread --thread master
 '
 
 test_expect_success 'thread config + --no-thread' '
-       git config format.thread deep &&
+       test_config format.thread deep &&
        check_threading expect.no-threading --no-thread master
 '
 
@@ -886,4 +886,12 @@ test_expect_success 'empty subject prefix does not have extra space' '
        test_cmp expect actual
 '
 
+test_expect_success 'format patch ignores color.ui' '
+       test_unconfig color.ui &&
+       git format-patch --stdout -1 >expect &&
+       test_config color.ui always &&
+       git format-patch --stdout -1 >actual &&
+       test_cmp expect actual
+'
+
 test_done
diff --git a/t/t4254-am-corrupt.sh b/t/t4254-am-corrupt.sh
new file mode 100755 (executable)
index 0000000..b7da95f
--- /dev/null
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+test_description='git am with corrupt input'
+. ./test-lib.sh
+
+# Note the missing "+++" line:
+cat > bad-patch.diff <<'EOF'
+From: A U Thor <au.thor@example.com>
+diff --git a/f b/f
+index 7898192..6178079 100644
+--- a/f
+@@ -1 +1 @@
+-a
++b
+EOF
+
+test_expect_success setup '
+       test $? = 0 &&
+       echo a > f &&
+       git add f &&
+       test_tick &&
+       git commit -m initial
+'
+
+# This used to fail before, too, but with a different diagnostic.
+#   fatal: unable to write file '(null)' mode 100644: Bad address
+# Also, it had the unwanted side-effect of deleting f.
+test_expect_success 'try to apply corrupted patch' '
+       git am bad-patch.diff 2> actual
+       test $? = 1
+'
+
+cat > expected <<EOF
+fatal: git diff header lacks filename information (line 4)
+EOF
+
+test_expect_success 'compare diagnostic; ensure file is still here' '
+       test $? = 0 &&
+       test -f f &&
+       test_cmp expected actual
+'
+
+test_done
index 0d0222ea2ace733ffe3fbfbdee58520abcd40e92..e8af615e6dcdf365416ef9f71825c17a0d601186 100755 (executable)
@@ -631,6 +631,37 @@ test_expect_success 'rename a remote' '
 
 '
 
+test_expect_success 'rename does not update a non-default fetch refspec' '
+
+       git clone one four.one &&
+       (cd four.one &&
+        git config remote.origin.fetch +refs/heads/*:refs/heads/origin/* &&
+        git remote rename origin upstream &&
+        test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/heads/origin/*" &&
+        git rev-parse -q origin/master)
+
+'
+
+test_expect_success 'rename a remote with name part of fetch spec' '
+
+       git clone one four.two &&
+       (cd four.two &&
+        git remote rename origin remote &&
+        git remote rename remote upstream &&
+        test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/remotes/upstream/*")
+
+'
+
+test_expect_success 'rename a remote with name prefix of other remote' '
+
+       git clone one four.three &&
+       (cd four.three &&
+        git remote add o git://example.com/repo.git &&
+        git remote rename o upstream &&
+        test "$(git rev-parse origin/master)" = "$(git rev-parse master)")
+
+'
+
 cat > remotes_origin << EOF
 URL: $(pwd)/one
 Push: refs/heads/master:refs/heads/upstream
index 76410293b34ecede219445e09b1eccb8175ee115..39b4cb0ecdc8801b355b815a0566c6e2df5c5a39 100755 (executable)
@@ -70,4 +70,42 @@ test_expect_success 'rev-list --ancestry-patch D..M -- M.t' '
        test_cmp expect actual
 '
 
+#   b---bc
+#  / \ /
+# a   X
+#  \ / \
+#   c---cb
+#
+# All refnames prefixed with 'x' to avoid confusion with the tags
+# generated by test_commit on case-insensitive systems.
+test_expect_success 'setup criss-cross' '
+       mkdir criss-cross &&
+       (cd criss-cross &&
+        git init &&
+        test_commit A &&
+        git checkout -b xb master &&
+        test_commit B &&
+        git checkout -b xc master &&
+        test_commit C &&
+        git checkout -b xbc xb -- &&
+        git merge xc &&
+        git checkout -b xcb xc -- &&
+        git merge xb &&
+        git checkout master)
+'
+
+# no commits in bc descend from cb
+test_expect_success 'criss-cross: rev-list --ancestry-path cb..bc' '
+       (cd criss-cross &&
+        git rev-list --ancestry-path xcb..xbc > actual &&
+        test -z "$(cat actual)")
+'
+
+# no commits in repository descend from cb
+test_expect_success 'criss-cross: rev-list --ancestry-path --all ^cb' '
+       (cd criss-cross &&
+        git rev-list --ancestry-path --all ^xcb > actual &&
+        test -z "$(cat actual)")
+'
+
 test_done
index 72a8731d5e28d71577d0c53fc25a5ddc1d2ad6de..aa74184c31cd6b2bd2e0e566e6805e60eed7aff8 100755 (executable)
@@ -107,6 +107,7 @@ error: The following untracked working tree files would be overwritten by merge:
        sub
        sub2
 Please move or remove them before you can merge.
+Aborting
 EOF
 
 test_expect_success 'will not overwrite untracked file in leading path' '
index c994836c53224dd0a8302f7a6ab63b35f8b493e3..0e4a682c6428a96af4d98bb7e24b0de7f4be865c 100755 (executable)
@@ -32,6 +32,7 @@ error: The following untracked working tree files would be overwritten by merge:
        three
        two
 Please move or remove them before you can merge.
+Aborting
 EOF
 
 test_expect_success 'untracked files overwritten by merge (fast and non-fast forward)' '
@@ -56,6 +57,7 @@ Please, commit your changes or stash them before you can merge.
 error: The following untracked working tree files would be overwritten by merge:
        five
 Please move or remove them before you can merge.
+Aborting
 EOF
 
 test_expect_success 'untracked files or local changes ovewritten by merge' '
@@ -71,6 +73,7 @@ error: Your local changes to the following files would be overwritten by checkou
        rep/one
        rep/two
 Please, commit your changes or stash them before you can switch branches.
+Aborting
 EOF
 
 test_expect_success 'cannot switch branches because of local changes' '
@@ -92,6 +95,7 @@ error: Your local changes to the following files would be overwritten by checkou
        rep/one
        rep/two
 Please, commit your changes or stash them before you can switch branches.
+Aborting
 EOF
 
 test_expect_success 'not uptodate file porcelain checkout error' '
@@ -105,6 +109,7 @@ error: Updating the following directories would lose untracked files in it:
        rep
        rep2
 
+Aborting
 EOF
 
 test_expect_success 'not_uptodate_dir porcelain checkout error' '
index cbc08e32761c6e35a3eb25519873e74218fd441a..4aab2a75b8ef5836a58f30b6c27a8eec4a733afc 100755 (executable)
@@ -16,6 +16,7 @@ Testing basic merge tool invocation'
 test_expect_success 'setup' '
     git config rerere.enabled true &&
     echo master >file1 &&
+    echo master spaced >"spaced name" &&
     echo master file11 >file11 &&
     echo master file12 >file12 &&
     echo master file13 >file13 &&
@@ -30,13 +31,14 @@ test_expect_success 'setup' '
        git commit -m "Add foo"
     ) &&
     git submodule add git://example.com/submod submod &&
-    git add file1 file1[1-4] subdir/file3 .gitmodules submod &&
+    git add file1 "spaced name" file1[1-4] subdir/file3 .gitmodules submod &&
     git commit -m "add initial versions" &&
 
     git checkout -b branch1 master &&
     git submodule update -N &&
     echo branch1 change >file1 &&
     echo branch1 newfile >file2 &&
+    echo branch1 spaced >"spaced name" &&
     echo branch1 change file11 >file11 &&
     echo branch1 change file13 >file13 &&
     echo branch1 sub >subdir/file3 &&
@@ -47,7 +49,7 @@ test_expect_success 'setup' '
        git commit -m "Add bar on branch1" &&
        git checkout -b submod-branch1
     ) &&
-    git add file1 file11 file13 file2 subdir/file3 submod &&
+    git add file1 "spaced name" file11 file13 file2 subdir/file3 submod &&
     git rm file12 &&
     git commit -m "branch1 changes" &&
 
@@ -55,6 +57,7 @@ test_expect_success 'setup' '
     git submodule update -N &&
     echo master updated >file1 &&
     echo master new >file2 &&
+    echo master updated spaced >"spaced name" &&
     echo master updated file12 >file12 &&
     echo master updated file14 >file14 &&
     echo master new sub >subdir/file3 &&
@@ -65,7 +68,7 @@ test_expect_success 'setup' '
        git commit -m "Add bar on master" &&
        git checkout -b submod-master
     ) &&
-    git add file1 file12 file14 file2 subdir/file3 submod &&
+    git add file1 "spaced name" file12 file14 file2 subdir/file3 submod &&
     git rm file11 &&
     git commit -m "master updates" &&
 
@@ -78,8 +81,8 @@ test_expect_success 'custom mergetool' '
     git checkout -b test1 branch1 &&
     git submodule update -N &&
     test_must_fail git merge master >/dev/null 2>&1 &&
-    ( yes "" | git mergetool file1 >/dev/null 2>&1 ) &&
-    ( yes "" | git mergetool file2 >/dev/null 2>&1 ) &&
+    ( yes "" | git mergetool file1 file1 ) &&
+    ( yes "" | git mergetool file2 "spaced name" >/dev/null 2>&1 ) &&
     ( yes "" | git mergetool subdir/file3 >/dev/null 2>&1 ) &&
     ( yes "d" | git mergetool file11 >/dev/null 2>&1 ) &&
     ( yes "d" | git mergetool file12 >/dev/null 2>&1 ) &&
@@ -97,6 +100,7 @@ test_expect_success 'mergetool crlf' '
     test_must_fail git merge master >/dev/null 2>&1 &&
     ( yes "" | git mergetool file1 >/dev/null 2>&1 ) &&
     ( yes "" | git mergetool file2 >/dev/null 2>&1 ) &&
+    ( yes "" | git mergetool "spaced name" >/dev/null 2>&1 ) &&
     ( yes "" | git mergetool subdir/file3 >/dev/null 2>&1 ) &&
     ( yes "d" | git mergetool file11 >/dev/null 2>&1 ) &&
     ( yes "d" | git mergetool file12 >/dev/null 2>&1 ) &&
@@ -126,7 +130,7 @@ test_expect_success 'mergetool on file in parent dir' '
     (
        cd subdir &&
        ( yes "" | git mergetool ../file1 >/dev/null 2>&1 ) &&
-       ( yes "" | git mergetool ../file2 >/dev/null 2>&1 ) &&
+       ( yes "" | git mergetool ../file2 ../spaced\ name >/dev/null 2>&1 ) &&
        ( yes "d" | git mergetool ../file11 >/dev/null 2>&1 ) &&
        ( yes "d" | git mergetool ../file12 >/dev/null 2>&1 ) &&
        ( yes "l" | git mergetool ../submod >/dev/null 2>&1 ) &&
@@ -180,6 +184,24 @@ test_expect_success 'mergetool skips resolved paths when rerere is active' '
     git reset --hard
 '
 
+test_expect_success 'mergetool takes partial path' '
+    git config rerere.enabled false &&
+    git checkout -b test12 branch1 &&
+    git submodule update -N &&
+    test_must_fail git merge master &&
+
+    #shouldnt need these lines
+    #( yes "d" | git mergetool file11 >/dev/null 2>&1 ) &&
+    #( yes "d" | git mergetool file12 >/dev/null 2>&1 ) &&
+    #( yes "l" | git mergetool submod >/dev/null 2>&1 ) &&
+    #( yes "" | git mergetool file1 file2 >/dev/null 2>&1 ) &&
+
+    ( yes "" | git mergetool subdir ) &&
+
+    test "$(cat subdir/file3)" = "master new sub" &&
+    git reset --hard
+'
+
 test_expect_success 'deleted vs modified submodule' '
     git checkout -b test6 branch1 &&
     git submodule update -N &&
@@ -189,7 +211,7 @@ test_expect_success 'deleted vs modified submodule' '
     git checkout -b test6.a test6 &&
     test_must_fail git merge master &&
     test -n "$(git ls-files -u)" &&
-    ( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
+    ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
     ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
     ( yes "r" | git mergetool submod ) &&
     rmdir submod && mv submod-movedaside submod &&
@@ -205,7 +227,7 @@ test_expect_success 'deleted vs modified submodule' '
     git submodule update -N &&
     test_must_fail git merge master &&
     test -n "$(git ls-files -u)" &&
-    ( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
+    ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
     ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
     ( yes "l" | git mergetool submod ) &&
     test ! -e submod &&
@@ -218,7 +240,7 @@ test_expect_success 'deleted vs modified submodule' '
     git submodule update -N &&
     test_must_fail git merge test6 &&
     test -n "$(git ls-files -u)" &&
-    ( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
+    ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
     ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
     ( yes "r" | git mergetool submod ) &&
     test ! -e submod &&
@@ -233,7 +255,7 @@ test_expect_success 'deleted vs modified submodule' '
     git submodule update -N &&
     test_must_fail git merge test6 &&
     test -n "$(git ls-files -u)" &&
-    ( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
+    ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
     ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
     ( yes "l" | git mergetool submod ) &&
     test "$(cat submod/bar)" = "master submodule" &&
@@ -256,7 +278,7 @@ test_expect_success 'file vs modified submodule' '
     git checkout -b test7.a branch1 &&
     test_must_fail git merge master &&
     test -n "$(git ls-files -u)" &&
-    ( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
+    ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
     ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
     ( yes "r" | git mergetool submod ) &&
     rmdir submod && mv submod-movedaside submod &&
@@ -271,7 +293,7 @@ test_expect_success 'file vs modified submodule' '
     git checkout -b test7.b test7 &&
     test_must_fail git merge master &&
     test -n "$(git ls-files -u)" &&
-    ( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
+    ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
     ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
     ( yes "l" | git mergetool submod ) &&
     git submodule update -N &&
@@ -286,7 +308,7 @@ test_expect_success 'file vs modified submodule' '
     git submodule update -N &&
     test_must_fail git merge test7 &&
     test -n "$(git ls-files -u)" &&
-    ( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
+    ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
     ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
     ( yes "r" | git mergetool submod ) &&
     test -d submod.orig &&
@@ -301,7 +323,7 @@ test_expect_success 'file vs modified submodule' '
     git submodule update -N &&
     test_must_fail git merge test7 &&
     test -n "$(git ls-files -u)" &&
-    ( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
+    ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
     ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
     ( yes "l" | git mergetool submod ) &&
     test "$(cat submod/bar)" = "master submodule" &&
@@ -388,7 +410,7 @@ test_expect_success 'directory vs modified submodule' '
     test "$(cat submod/file16)" = "not a submodule" &&
     rm -rf submod.orig &&
 
-    git reset --hard &&
+    git reset --hard >/dev/null 2>&1 &&
     test_must_fail git merge master &&
     test -n "$(git ls-files -u)" &&
     test ! -e submod.orig &&
@@ -400,7 +422,7 @@ test_expect_success 'directory vs modified submodule' '
     ( cd submod && git clean -f && git reset --hard ) &&
     git submodule update -N &&
     test "$(cat submod/bar)" = "master submodule" &&
-    git reset --hard && rm -rf submod-movedaside &&
+    git reset --hard >/dev/null 2>&1 && rm -rf submod-movedaside &&
 
     git checkout -b test11.c master &&
     git submodule update -N &&
@@ -410,7 +432,7 @@ test_expect_success 'directory vs modified submodule' '
     git submodule update -N &&
     test "$(cat submod/bar)" = "master submodule" &&
 
-    git reset --hard &&
+    git reset --hard >/dev/null 2>&1 &&
     git submodule update -N &&
     test_must_fail git merge test11 &&
     test -n "$(git ls-files -u)" &&
@@ -418,7 +440,7 @@ test_expect_success 'directory vs modified submodule' '
     ( yes "r" | git mergetool submod ) &&
     test "$(cat submod/file16)" = "not a submodule" &&
 
-    git reset --hard master &&
+    git reset --hard master >/dev/null 2>&1 &&
     ( cd submod && git clean -f && git reset --hard ) &&
     git submodule update -N
 '
index 85120b70db8cfb60b8d8c38f85a9038aa856468a..69e4815781c190207d406a4871a5dc5252690239 100755 (executable)
@@ -2,6 +2,14 @@
 test_description='git svn handling of root commits in merge ranges'
 . ./lib-git-svn.sh
 
+svn_ver="$(svn --version --quiet)"
+case $svn_ver in
+0.* | 1.[0-4].*)
+       skip_all="skipping git-svn test - SVN too old ($svn_ver)"
+       test_done
+       ;;
+esac
+
 test_expect_success 'test handling of root commits in merge ranges' '
        mkdir -p init/trunk init/branches init/tags &&
        echo "r1" > init/trunk/file.txt &&
diff --git a/t/t9161-git-svn-mergeinfo-push.sh b/t/t9161-git-svn-mergeinfo-push.sh
new file mode 100755 (executable)
index 0000000..6ef0c0b
--- /dev/null
@@ -0,0 +1,104 @@
+#!/bin/sh
+#
+# Portions copyright (c) 2007, 2009 Sam Vilain
+# Portions copyright (c) 2011 Bryan Jacobs
+#
+
+test_description='git-svn svn mergeinfo propagation'
+
+. ./lib-git-svn.sh
+
+test_expect_success 'load svn dump' "
+       svnadmin load -q '$rawsvnrepo' \
+         < '$TEST_DIRECTORY/t9161/branches.dump' &&
+       git svn init --minimize-url -R svnmerge \
+         -T trunk -b branches '$svnrepo' &&
+       git svn fetch --all
+       "
+
+test_expect_success 'propagate merge information' '
+       git config svn.pushmergeinfo yes &&
+       git checkout svnb1 &&
+       git merge --no-ff svnb2 &&
+       git svn dcommit
+       '
+
+test_expect_success 'check svn:mergeinfo' '
+       mergeinfo=$(svn_cmd propget svn:mergeinfo "$svnrepo"/branches/svnb1)
+       test "$mergeinfo" = "/branches/svnb2:3,8"
+       '
+
+test_expect_success 'merge another branch' '
+       git merge --no-ff svnb3 &&
+       git svn dcommit
+       '
+
+test_expect_success 'check primary parent mergeinfo respected' '
+       mergeinfo=$(svn_cmd propget svn:mergeinfo "$svnrepo"/branches/svnb1)
+       test "$mergeinfo" = "/branches/svnb2:3,8
+/branches/svnb3:4,9"
+       '
+
+test_expect_success 'merge existing merge' '
+       git merge --no-ff svnb4 &&
+       git svn dcommit
+       '
+
+test_expect_success "check both parents' mergeinfo respected" '
+       mergeinfo=$(svn_cmd propget svn:mergeinfo "$svnrepo"/branches/svnb1)
+       test "$mergeinfo" = "/branches/svnb2:3,8
+/branches/svnb3:4,9
+/branches/svnb4:5-6,10-12
+/branches/svnb5:6,11"
+       '
+
+test_expect_success 'make further commits to branch' '
+       git checkout svnb2 &&
+       touch newb2file &&
+       git add newb2file &&
+       git commit -m "later b2 commit" &&
+       touch newb2file-2 &&
+       git add newb2file-2 &&
+       git commit -m "later b2 commit 2" &&
+       git svn dcommit
+       '
+
+test_expect_success 'second forward merge' '
+       git checkout svnb1 &&
+       git merge --no-ff svnb2 &&
+       git svn dcommit
+       '
+
+test_expect_success 'check new mergeinfo added' '
+       mergeinfo=$(svn_cmd propget svn:mergeinfo "$svnrepo"/branches/svnb1)
+       test "$mergeinfo" = "/branches/svnb2:3,8,16-17
+/branches/svnb3:4,9
+/branches/svnb4:5-6,10-12
+/branches/svnb5:6,11"
+       '
+
+test_expect_success 'reintegration merge' '
+       git checkout svnb4 &&
+       git merge --no-ff svnb1 &&
+       git svn dcommit
+       '
+
+test_expect_success 'check reintegration mergeinfo' '
+       mergeinfo=$(svn_cmd propget svn:mergeinfo "$svnrepo"/branches/svnb4)
+       test "$mergeinfo" = "/branches/svnb1:2-4,7-9,13-18
+/branches/svnb2:3,8,16-17
+/branches/svnb3:4,9
+/branches/svnb4:5-6,10-12
+/branches/svnb5:6,11"
+       '
+
+test_expect_success 'dcommit a merge at the top of a stack' '
+       git checkout svnb1 &&
+       touch anotherfile &&
+       git add anotherfile &&
+       git commit -m "a commit" &&
+       git merge svnb4 &&
+       git svn dcommit
+       '
+
+test_done
diff --git a/t/t9161/branches.dump b/t/t9161/branches.dump
new file mode 100644 (file)
index 0000000..e61c3e7
--- /dev/null
@@ -0,0 +1,374 @@
+SVN-fs-dump-format-version: 2
+
+UUID: 1ef08553-f2d1-45df-b38c-19af6b7c926d
+
+Revision-number: 0
+Prop-content-length: 56
+Content-length: 56
+
+K 8
+svn:date
+V 27
+2011-09-02T16:08:02.941384Z
+PROPS-END
+
+Revision-number: 1
+Prop-content-length: 114
+Content-length: 114
+
+K 7
+svn:log
+V 12
+Base commit
+
+K 10
+svn:author
+V 7
+bjacobs
+K 8
+svn:date
+V 27
+2011-09-02T16:08:27.205062Z
+PROPS-END
+
+Node-path: branches
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: trunk
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 2
+Prop-content-length: 121
+Content-length: 121
+
+K 7
+svn:log
+V 19
+Create branch svnb1
+K 10
+svn:author
+V 7
+bjacobs
+K 8
+svn:date
+V 27
+2011-09-02T16:09:43.628137Z
+PROPS-END
+
+Node-path: branches/svnb1
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 1
+Node-copyfrom-path: trunk
+
+
+Revision-number: 3
+Prop-content-length: 121
+Content-length: 121
+
+K 7
+svn:log
+V 19
+Create branch svnb2
+K 10
+svn:author
+V 7
+bjacobs
+K 8
+svn:date
+V 27
+2011-09-02T16:09:46.339930Z
+PROPS-END
+
+Node-path: branches/svnb2
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 1
+Node-copyfrom-path: trunk
+
+
+Revision-number: 4
+Prop-content-length: 121
+Content-length: 121
+
+K 7
+svn:log
+V 19
+Create branch svnb3
+K 10
+svn:author
+V 7
+bjacobs
+K 8
+svn:date
+V 27
+2011-09-02T16:09:49.394515Z
+PROPS-END
+
+Node-path: branches/svnb3
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 1
+Node-copyfrom-path: trunk
+
+
+Revision-number: 5
+Prop-content-length: 121
+Content-length: 121
+
+K 7
+svn:log
+V 19
+Create branch svnb4
+K 10
+svn:author
+V 7
+bjacobs
+K 8
+svn:date
+V 27
+2011-09-02T16:09:54.114607Z
+PROPS-END
+
+Node-path: branches/svnb4
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 1
+Node-copyfrom-path: trunk
+
+
+Revision-number: 6
+Prop-content-length: 121
+Content-length: 121
+
+K 7
+svn:log
+V 19
+Create branch svnb5
+K 10
+svn:author
+V 7
+bjacobs
+K 8
+svn:date
+V 27
+2011-09-02T16:09:58.602623Z
+PROPS-END
+
+Node-path: branches/svnb5
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 1
+Node-copyfrom-path: trunk
+
+
+Revision-number: 7
+Prop-content-length: 110
+Content-length: 110
+
+K 7
+svn:log
+V 9
+b1 commit
+K 10
+svn:author
+V 7
+bjacobs
+K 8
+svn:date
+V 27
+2011-09-02T16:10:20.292369Z
+PROPS-END
+
+Node-path: branches/svnb1/b1file
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 0
+Text-content-md5: d41d8cd98f00b204e9800998ecf8427e
+Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 8
+Prop-content-length: 110
+Content-length: 110
+
+K 7
+svn:log
+V 9
+b2 commit
+K 10
+svn:author
+V 7
+bjacobs
+K 8
+svn:date
+V 27
+2011-09-02T16:10:38.429199Z
+PROPS-END
+
+Node-path: branches/svnb2/b2file
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 0
+Text-content-md5: d41d8cd98f00b204e9800998ecf8427e
+Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 9
+Prop-content-length: 110
+Content-length: 110
+
+K 7
+svn:log
+V 9
+b3 commit
+K 10
+svn:author
+V 7
+bjacobs
+K 8
+svn:date
+V 27
+2011-09-02T16:10:52.843023Z
+PROPS-END
+
+Node-path: branches/svnb3/b3file
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 0
+Text-content-md5: d41d8cd98f00b204e9800998ecf8427e
+Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 10
+Prop-content-length: 110
+Content-length: 110
+
+K 7
+svn:log
+V 9
+b4 commit
+K 10
+svn:author
+V 7
+bjacobs
+K 8
+svn:date
+V 27
+2011-09-02T16:11:17.489870Z
+PROPS-END
+
+Node-path: branches/svnb4/b4file
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 0
+Text-content-md5: d41d8cd98f00b204e9800998ecf8427e
+Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 11
+Prop-content-length: 110
+Content-length: 110
+
+K 7
+svn:log
+V 9
+b5 commit
+K 10
+svn:author
+V 7
+bjacobs
+K 8
+svn:date
+V 27
+2011-09-02T16:11:32.277404Z
+PROPS-END
+
+Node-path: branches/svnb5/b5file
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 0
+Text-content-md5: d41d8cd98f00b204e9800998ecf8427e
+Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 12
+Prop-content-length: 192
+Content-length: 192
+
+K 7
+svn:log
+V 90
+Merge remote-tracking branch 'svnb5' into HEAD
+
+* svnb5:
+  b5 commit
+  Create branch svnb5
+K 10
+svn:author
+V 7
+bjacobs
+K 8
+svn:date
+V 27
+2011-09-02T16:11:54.274722Z
+PROPS-END
+
+Node-path: branches/svnb4
+Node-kind: dir
+Node-action: change
+Prop-content-length: 56
+Content-length: 56
+
+K 13
+svn:mergeinfo
+V 21
+/branches/svnb5:6,11
+
+PROPS-END
+
+
+Node-path: branches/svnb4/b5file
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 0
+Text-content-md5: d41d8cd98f00b204e9800998ecf8427e
+Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709
+Content-length: 10
+
+PROPS-END
+
+
index d7dfc8b0b1939180f16b8245e58465f883e85cbc..bdd9513b84301275330d3dd7e49af05081ef9cd7 100644 (file)
@@ -950,6 +950,8 @@ then
        do
                make_valgrind_symlink $file
        done
+       # special-case the mergetools loadables
+       make_symlink "$GIT_BUILD_DIR"/mergetools "$GIT_VALGRIND/bin/mergetools"
        OLDIFS=$IFS
        IFS=:
        for path in $PATH
diff --git a/templates/hooks--post-commit.sample b/templates/hooks--post-commit.sample
deleted file mode 100755 (executable)
index 2266821..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-#
-# An example hook script that is called after a successful
-# commit is made.
-#
-# To enable this hook, rename this file to "post-commit".
-
-: Nothing
diff --git a/templates/hooks--post-receive.sample b/templates/hooks--post-receive.sample
deleted file mode 100755 (executable)
index 7a83e17..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-#
-# An example hook script for the "post-receive" event.
-#
-# The "post-receive" script is run after receive-pack has accepted a pack
-# and the repository has been updated.  It is passed arguments in through
-# stdin in the form
-#  <oldrev> <newrev> <refname>
-# For example:
-#  aa453216d1b3e49e7f6f98441fa56946ddcd6a20 68f7abf4e6f922807889f52bc043ecd31b79f814 refs/heads/master
-#
-# see contrib/hooks/ for a sample, or uncomment the next line and
-# rename the file to "post-receive".
-
-#. /usr/share/doc/git-core/contrib/hooks/post-receive-email
index b187c4bb1f256e19c25f80dd64f3451ced77e123..18c48297652174ffae65b877dd131711a5746181 100755 (executable)
@@ -18,6 +18,9 @@ fi
 # If you want to allow non-ascii filenames set this variable to true.
 allownonascii=$(git config hooks.allownonascii)
 
+# Redirect output to stderr.
+exec 1>&2
+
 # Cross platform projects tend to avoid non-ascii filenames; prevent
 # them from being added to the repository. We exploit the fact that the
 # printable range starts at the space character and ends with tilde.
@@ -25,8 +28,8 @@ if [ "$allownonascii" != "true" ] &&
        # Note that the use of brackets around a tr range is ok here, (it's
        # even required, for portability to Solaris 10's /usr/bin/tr), since
        # the square bracket bytes happen to fall in the designated range.
-       test "$(git diff --cached --name-only --diff-filter=A -z $against |
-         LC_ALL=C tr -d '[ -~]\0')"
+       test $(git diff --cached --name-only --diff-filter=A -z $against |
+         LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
 then
        echo "Error: Attempt to add a non-ascii file name."
        echo
@@ -43,4 +46,5 @@ then
        exit 1
 fi
 
+# If there are whitespace errors, print the offending file names and fail.
 exec git diff-index --check --cached $against --
index fa279d531fe1b99841424080487e685fbe04e5bb..e1940615e28ebc3b16f80b8f647f216031f64ee8 100644 (file)
@@ -432,7 +432,8 @@ static int fetch_refs_from_bundle(struct transport *transport,
                               int nr_heads, struct ref **to_fetch)
 {
        struct bundle_transport_data *data = transport->data;
-       return unbundle(&data->header, data->fd);
+       return unbundle(&data->header, data->fd,
+                       transport->progress ? BUNDLE_VERBOSE : 0);
 }
 
 static int close_bundle(struct transport *transport)
index 33f749e1e77484694e7b8f40a65755a7818c4abb..808bb55ba3f21d113e6358f6874e2e20cb33bbea 100644 (file)
@@ -309,6 +309,18 @@ static void free_extended_entry(struct tree_desc_x *t)
        }
 }
 
+static inline int prune_traversal(struct name_entry *e,
+                                 struct traverse_info *info,
+                                 struct strbuf *base,
+                                 int still_interesting)
+{
+       if (!info->pathspec || still_interesting == 2)
+               return 2;
+       if (still_interesting < 0)
+               return still_interesting;
+       return tree_entry_interesting(e, base, 0, info->pathspec);
+}
+
 int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info)
 {
        int ret = 0;
@@ -316,10 +328,18 @@ int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info)
        struct name_entry *entry = xmalloc(n*sizeof(*entry));
        int i;
        struct tree_desc_x *tx = xcalloc(n, sizeof(*tx));
+       struct strbuf base = STRBUF_INIT;
+       int interesting = 1;
 
        for (i = 0; i < n; i++)
                tx[i].d = t[i];
 
+       if (info->prev) {
+               strbuf_grow(&base, info->pathlen);
+               make_traverse_path(base.buf, info->prev, &info->name);
+               base.buf[info->pathlen-1] = '/';
+               strbuf_setlen(&base, info->pathlen);
+       }
        for (;;) {
                unsigned long mask, dirmask;
                const char *first = NULL;
@@ -376,16 +396,22 @@ int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info)
                        mask |= 1ul << i;
                        if (S_ISDIR(entry[i].mode))
                                dirmask |= 1ul << i;
+                       e = &entry[i];
                }
                if (!mask)
                        break;
-               ret = info->fn(n, mask, dirmask, entry, info);
-               if (ret < 0) {
-                       error = ret;
-                       if (!info->show_all_errors)
-                               break;
+               interesting = prune_traversal(e, info, &base, interesting);
+               if (interesting < 0)
+                       break;
+               if (interesting) {
+                       ret = info->fn(n, mask, dirmask, entry, info);
+                       if (ret < 0) {
+                               error = ret;
+                               if (!info->show_all_errors)
+                                       break;
+                       }
+                       mask &= ret;
                }
-               mask &= ret;
                ret = 0;
                for (i = 0; i < n; i++)
                        if (mask & (1ul << i))
@@ -395,6 +421,7 @@ int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info)
        for (i = 0; i < n; i++)
                free_extended_entry(tx + i);
        free(tx);
+       strbuf_release(&base);
        return error;
 }
 
index 39524b7dba6a1d0b63c4cd2b42db59a27a030b21..0089581e1dd55800302799a7381d4a7ad01bd79d 100644 (file)
@@ -44,6 +44,7 @@ struct traverse_info {
        struct traverse_info *prev;
        struct name_entry name;
        int pathlen;
+       struct pathspec *pathspec;
 
        unsigned long conflicts;
        traverse_callback_t fn;
index cc616c3f991a655d10fcac15055fcdfafa8620fd..237aed8c766638c55d8d6b870c86ef2ad13a74d3 100644 (file)
@@ -159,7 +159,7 @@ static void display_error_msgs(struct unpack_trees_options *o)
                string_list_clear(rejects, 0);
        }
        if (something_displayed)
-               printf("Aborting\n");
+               fprintf(stderr, "Aborting\n");
 }
 
 /*
@@ -444,6 +444,7 @@ static int traverse_trees_recursive(int n, unsigned long dirmask,
 
        newinfo = *info;
        newinfo.prev = info;
+       newinfo.pathspec = info->pathspec;
        newinfo.name = *p;
        newinfo.pathlen += tree_entry_len(p->path, p->sha1) + 1;
        newinfo.conflicts |= df_conflicts;
@@ -1040,6 +1041,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
                info.fn = unpack_callback;
                info.data = o;
                info.show_all_errors = o->show_all_errors;
+               info.pathspec = o->pathspec;
 
                if (o->prefix) {
                        /*
index 79989483079970e9dad42512e522eef8ea2a75a4..5e432f576eb2304a63510a61a71182e11f777092 100644 (file)
@@ -52,6 +52,7 @@ struct unpack_trees_options {
        const char *prefix;
        int cache_bottom;
        struct dir_struct *dir;
+       struct pathspec *pathspec;
        merge_fn_t fn;
        const char *msgs[NB_UNPACK_TREES_ERROR_TYPES];
        /*
index 8836a527d0b1980bd4ebdd50b3225f7ce37ccf79..70fdb76ff2b5100c6d20f9f3b758e1ac8df314e1 100644 (file)
@@ -396,7 +396,7 @@ static void wt_status_collect_changes_worktree(struct wt_status *s)
        if (s->ignore_submodule_arg) {
                DIFF_OPT_SET(&rev.diffopt, OVERRIDE_SUBMODULE_CONFIG);
                handle_ignore_submodules_arg(&rev.diffopt, s->ignore_submodule_arg);
-    }
+       }
        rev.diffopt.format_callback = wt_status_collect_changed_cb;
        rev.diffopt.format_callback_data = s;
        init_pathspec(&rev.prune_data, s->pathspec);
index 5a33d1a86964472a82a63f18ab3c9b4da9b23165..e419f4f726019a5b0365c589285439fb3bfb8db2 100644 (file)
@@ -383,7 +383,7 @@ static int xdl_clean_mmatch(char const *dis, long i, long s, long e) {
  * might be potentially discarded if they happear in a run of discardable.
  */
 static int xdl_cleanup_records(xdlclassifier_t *cf, xdfile_t *xdf1, xdfile_t *xdf2) {
-       long i, nm, nreff;
+       long i, nm, nreff, mlim;
        xrecord_t **recs;
        xdlclass_t *rcrec;
        char *dis, *dis1, *dis2;
@@ -396,16 +396,20 @@ static int xdl_cleanup_records(xdlclassifier_t *cf, xdfile_t *xdf1, xdfile_t *xd
        dis1 = dis;
        dis2 = dis1 + xdf1->nrec + 1;
 
+       if ((mlim = xdl_bogosqrt(xdf1->nrec)) > XDL_MAX_EQLIMIT)
+               mlim = XDL_MAX_EQLIMIT;
        for (i = xdf1->dstart, recs = &xdf1->recs[xdf1->dstart]; i <= xdf1->dend; i++, recs++) {
                rcrec = cf->rcrecs[(*recs)->ha];
                nm = rcrec ? rcrec->len2 : 0;
-               dis1[i] = (nm == 0) ? 0: 1;
+               dis1[i] = (nm == 0) ? 0: (nm >= mlim) ? 2: 1;
        }
 
+       if ((mlim = xdl_bogosqrt(xdf2->nrec)) > XDL_MAX_EQLIMIT)
+               mlim = XDL_MAX_EQLIMIT;
        for (i = xdf2->dstart, recs = &xdf2->recs[xdf2->dstart]; i <= xdf2->dend; i++, recs++) {
                rcrec = cf->rcrecs[(*recs)->ha];
                nm = rcrec ? rcrec->len1 : 0;
-               dis2[i] = (nm == 0) ? 0: 1;
+               dis2[i] = (nm == 0) ? 0: (nm >= mlim) ? 2: 1;
        }
 
        for (nreff = 0, i = xdf1->dstart, recs = &xdf1->recs[xdf1->dstart];