Merge branch 'tc/minix'
authorJunio C Hamano <gitster@pobox.com>
Fri, 5 Aug 2011 21:55:00 +0000 (14:55 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 5 Aug 2011 21:55:00 +0000 (14:55 -0700)
* tc/minix:
Makefile: add Minix configuration options.

160 files changed:
Documentation/RelNotes/1.7.7.txt
Documentation/config.txt
Documentation/git-annotate.txt
Documentation/git-archive.txt
Documentation/git-bisect.txt
Documentation/git-cherry-pick.txt
Documentation/git-cherry.txt
Documentation/git-citool.txt
Documentation/git-commit-tree.txt
Documentation/git-count-objects.txt
Documentation/git-cvsexportcommit.txt
Documentation/git-diff-files.txt
Documentation/git-diff-index.txt
Documentation/git-difftool.txt
Documentation/git-fast-export.txt
Documentation/git-fast-import.txt
Documentation/git-fetch-pack.txt
Documentation/git-fetch.txt
Documentation/git-filter-branch.txt
Documentation/git-fsck-objects.txt
Documentation/git-gc.txt
Documentation/git-get-tar-commit-id.txt
Documentation/git-grep.txt
Documentation/git-gui.txt
Documentation/git-help.txt
Documentation/git-http-fetch.txt
Documentation/git-http-push.txt
Documentation/git-imap-send.txt
Documentation/git-init-db.txt
Documentation/git-init.txt
Documentation/git-log.txt
Documentation/git-lost-found.txt
Documentation/git-mailinfo.txt
Documentation/git-mailsplit.txt
Documentation/git-merge-file.txt
Documentation/git-merge-index.txt
Documentation/git-merge-one-file.txt
Documentation/git-merge-tree.txt
Documentation/git-mergetool--lib.txt
Documentation/git-mergetool.txt
Documentation/git-mktag.txt
Documentation/git-mktree.txt
Documentation/git-mv.txt
Documentation/git-pack-redundant.txt
Documentation/git-pack-refs.txt
Documentation/git-parse-remote.txt
Documentation/git-patch-id.txt
Documentation/git-peek-remote.txt
Documentation/git-prune-packed.txt
Documentation/git-prune.txt
Documentation/git-pull.txt
Documentation/git-push.txt
Documentation/git-read-tree.txt
Documentation/git-rebase.txt
Documentation/git-receive-pack.txt
Documentation/git-reflog.txt
Documentation/git-relink.txt
Documentation/git-remote-ext.txt
Documentation/git-remote-fd.txt
Documentation/git-remote-helpers.txt
Documentation/git-repack.txt
Documentation/git-repo-config.txt
Documentation/git-request-pull.txt
Documentation/git-rerere.txt
Documentation/git-rev-parse.txt
Documentation/git-revert.txt
Documentation/git-rm.txt
Documentation/git-send-email.txt
Documentation/git-send-pack.txt
Documentation/git-sh-i18n.txt
Documentation/git-sh-setup.txt
Documentation/git-shell.txt
Documentation/git-show-branch.txt
Documentation/git-show-index.txt
Documentation/git-show.txt
Documentation/git-stash.txt
Documentation/git-status.txt
Documentation/git-stripspace.txt
Documentation/git-submodule.txt
Documentation/git-svn.txt
Documentation/git-symbolic-ref.txt
Documentation/git-tar-tree.txt
Documentation/git-unpack-file.txt
Documentation/git-unpack-objects.txt
Documentation/git-update-ref.txt
Documentation/git-update-server-info.txt
Documentation/git-upload-archive.txt
Documentation/git-upload-pack.txt
Documentation/git-var.txt
Documentation/git-verify-pack.txt
Documentation/git-verify-tag.txt
Documentation/git-web--browse.txt
Documentation/git-whatchanged.txt
Documentation/git-write-tree.txt
Documentation/gitattributes.txt
Documentation/gitcvs-migration.txt
Documentation/gitdiffcore.txt
Documentation/gitk.txt
Documentation/gittutorial-2.txt
Documentation/gittutorial.txt
Documentation/gitworkflows.txt
Documentation/rev-list-options.txt
Documentation/technical/api-builtin.txt
Documentation/technical/index-format.txt
abspath.c
builtin/checkout.c
builtin/clone.c
builtin/fast-export.c
builtin/pack-objects.c
builtin/reset.c
builtin/tag.c
cache.h
config.c
connect.c
contrib/convert-objects/git-convert-objects.txt
contrib/fast-import/git-p4
contrib/gitview/gitview.txt
contrib/hooks/post-receive-email
contrib/svn-fe/svn-fe.txt
diff-lib.c
environment.c
fast-import.c
git-mergetool.sh
git-rebase.sh
git-remote-testgit.py
git-stash.sh
git-submodule.sh
git_remote_helpers/git/exporter.py
git_remote_helpers/git/importer.py
git_remote_helpers/git/non_local.py
git_remote_helpers/git/repo.py
git_remote_helpers/util.py
gitweb/gitweb.perl
help.c
remote-curl.c
remote.c
remote.h
sha1_file.c
streaming.c
t/aggregate-results.sh
t/t3307-notes-man.sh
t/t3905-stash-include-untracked.sh [new file with mode: 0755]
t/t4012-diff-binary.sh
t/t5000-tar-tree.sh
t/t5707-clone-detached.sh [new file with mode: 0755]
t/t5800-remote-helpers.sh
t/t6023-merge-file.sh
t/t6027-merge-binary.sh
t/t7102-reset.sh
t/t7400-submodule-basic.sh
t/t9200-git-cvsexportcommit.sh
t/t9300-fast-import.sh
t/t9800-git-p4.sh
t/test-binary-1.png [new file with mode: 0644]
t/test-binary-2.png [new file with mode: 0644]
t/test4012.png [deleted file]
t/test9200a.png [deleted file]
t/test9200b.png [deleted file]
transport-helper.c
unpack-trees.c
index 42982e5b24432e0c8cc03065411a4f7e5366764d..6d3bfd19680faaee7272d2451e12cea4e7440cdb 100644 (file)
@@ -26,12 +26,19 @@ Updates since v1.7.6
  * "git diff --stat" learned --stat-count option to limit the output of
    diffstat report.
 
+ * "git fetch", "git push" and friends no longer show connection
+   errors for addresses that couldn't be connected 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 rebase master topci" no longer spews usage hints after giving
    "fatal: no such branch: topci" error message.
 
+ * "git stash" learned --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.
@@ -52,6 +59,10 @@ Fixes since v1.7.6
 Unless otherwise noted, all the fixes in 1.7.6.X maintenance track are
 included in this release.
 
+ * "git checkout -b <branch>" sometimes wrote a bogus reflog entry,
+   causing later "git checkout -" fail.
+   (merge 71ee7fd jc/checkout-reflog-fix~1 later).
+
  * "git diff --cc" learned to correctly ignore binary files.
    (merge 0508fe5 jk/combine-diff-binary-etc later)
 
@@ -61,6 +72,10 @@ included in this release.
  * "git rebase -i -p" incorrectly dropped commits from side branches.
    (merge 12bf828 aw/rebase-i-p later)
 
+ * "git submodule add" did not allow a relative repository path when
+   the superproject did not have any default remote url.
+   (merge f22a17e8 jl/submodule-add-relurl-wo-upstream later)
+
  * "git submodule foreach" failed to correctly give the standard input to
    the user-supplied command it invoked.
    (merge 4dca1aa bc/submodule-foreach-stdin-fix-1.7.4 later)
@@ -77,7 +92,7 @@ included in this release.
 --
 exec >/var/tmp/1
 echo O=$(git describe master)
-O=v1.7.6-232-gd907bf8
+O=v1.7.6-344-g22f4128
 git log --first-parent --oneline $O..master
 echo
 git shortlog --no-merges ^maint ^$O master
index b56959b5dce4d9cec9e9eb5a9aa7894ab6421b52..0658ffb889320d408f2cad9214e138879059c766 100644 (file)
@@ -344,7 +344,9 @@ core.logAllRefUpdates::
        SHA1, the date/time and the reason of the update, but
        only when the file exists.  If this configuration
        variable is set to true, missing "$GIT_DIR/logs/<ref>"
-       file is automatically created for branch heads.
+       file is automatically created for branch heads (i.e. under
+       refs/heads/), remote refs (i.e. under refs/remotes/),
+       note refs (i.e. under refs/notes/), and the symbolic ref HEAD.
 +
 This information can be used to determine what commit
 was the tip of a branch "2 days ago".
index 9eb75c37dae574f4f9d4699b795f53e94e6fa0dd..05fd482b74ed00445613c7cc9b8a0b019ae31550 100644 (file)
@@ -7,6 +7,7 @@ git-annotate - Annotate file lines with commit information
 
 SYNOPSIS
 --------
+[verse]
 'git annotate' [options] file [revision]
 
 DESCRIPTION
index 1320c873ad61281ef33891170da8683dc785f011..ac7006e6400d85c31bf31a3022a38225373fe3f7 100644 (file)
@@ -142,41 +142,41 @@ while archiving any tree in your `$GIT_DIR/info/attributes` file.
 
 EXAMPLES
 --------
-git archive --format=tar --prefix=junk/ HEAD | (cd /var/tmp/ && tar xf -)::
+`git archive --format=tar --prefix=junk/ HEAD | (cd /var/tmp/ && tar xf -)`::
 
        Create a tar archive that contains the contents of the
        latest commit on the current branch, and extract it in the
        `/var/tmp/junk` directory.
 
-git archive --format=tar --prefix=git-1.4.0/ v1.4.0 | gzip >git-1.4.0.tar.gz::
+`git archive --format=tar --prefix=git-1.4.0/ v1.4.0 | gzip >git-1.4.0.tar.gz`::
 
        Create a compressed tarball for v1.4.0 release.
 
-git archive --format=tar.gz --prefix=git-1.4.0/ v1.4.0 >git-1.4.0.tar.gz::
+`git archive --format=tar.gz --prefix=git-1.4.0/ v1.4.0 >git-1.4.0.tar.gz`::
 
        Same as above, but using the builtin tar.gz handling.
 
-git archive --prefix=git-1.4.0/ -o git-1.4.0.tar.gz v1.4.0::
+`git archive --prefix=git-1.4.0/ -o git-1.4.0.tar.gz v1.4.0`::
 
        Same as above, but the format is inferred from the output file.
 
-git archive --format=tar --prefix=git-1.4.0/ v1.4.0{caret}\{tree\} | gzip >git-1.4.0.tar.gz::
+`git archive --format=tar --prefix=git-1.4.0/ v1.4.0{caret}\{tree\} | gzip >git-1.4.0.tar.gz`::
 
        Create a compressed tarball for v1.4.0 release, but without a
        global extended pax header.
 
-git archive --format=zip --prefix=git-docs/ HEAD:Documentation/ > git-1.4.0-docs.zip::
+`git archive --format=zip --prefix=git-docs/ HEAD:Documentation/ > git-1.4.0-docs.zip`::
 
        Put everything in the current head's Documentation/ directory
        into 'git-1.4.0-docs.zip', with the prefix 'git-docs/'.
 
-git archive -o latest.zip HEAD::
+`git archive -o latest.zip HEAD`::
 
        Create a Zip archive that contains the contents of the latest
        commit on the current branch. Note that the output format is
        inferred by the extension of the output file.
 
-git config tar.tar.xz.command "xz -c"::
+`git config tar.tar.xz.command "xz -c"`::
 
        Configure a "tar.xz" format for making LZMA-compressed tarfiles.
        You can use it specifying `--format=tar.xz`, or by creating an
index 7b7bafba0c514755f9eec423b5aed19db640c091..ab60a1847042a8ef28e019c8ad1a620ef5fd41d7 100644 (file)
@@ -8,6 +8,7 @@ git-bisect - Find by binary search the change that introduced a bug
 
 SYNOPSIS
 --------
+[verse]
 'git bisect' <subcommand> <options>
 
 DESCRIPTION
index 9d8fe0d26145ae45f566d3e8d4253c396630b41f..7cfa3d92ac8dc7a90068311c0047c667f98515a8 100644 (file)
@@ -7,6 +7,7 @@ git-cherry-pick - Apply the changes introduced by some existing commits
 
 SYNOPSIS
 --------
+[verse]
 'git cherry-pick' [--edit] [-n] [-m parent-number] [-s] [-x] [--ff] <commit>...
 
 DESCRIPTION
@@ -111,31 +112,31 @@ effect to your index in a row.
 
 EXAMPLES
 --------
-git cherry-pick master::
+`git cherry-pick master`::
 
        Apply the change introduced by the commit at the tip of the
        master branch and create a new commit with this change.
 
-git cherry-pick ..master::
-git cherry-pick ^HEAD master::
+`git cherry-pick ..master`::
+`git cherry-pick ^HEAD master`::
 
        Apply the changes introduced by all commits that are ancestors
        of master but not of HEAD to produce new commits.
 
-git cherry-pick master{tilde}4 master{tilde}2::
+`git cherry-pick master{tilde}4 master{tilde}2`::
 
        Apply the changes introduced by the fifth and third last
        commits pointed to by master and create 2 new commits with
        these changes.
 
-git cherry-pick -n master~1 next::
+`git cherry-pick -n master~1 next`::
 
        Apply to the working tree and the index the changes introduced
        by the second last commit pointed to by master and by the last
        commit pointed to by next, but do not create any commit with
        these changes.
 
-git cherry-pick --ff ..next::
+`git cherry-pick --ff ..next`::
 
        If history is linear and HEAD is an ancestor of next, update
        the working tree and advance the HEAD pointer to match next.
@@ -143,7 +144,7 @@ git cherry-pick --ff ..next::
        are in next but not HEAD to the current branch, creating a new
        commit for each new change.
 
-git rev-list --reverse master \-- README | git cherry-pick -n --stdin::
+`git rev-list --reverse master \-- README | git cherry-pick -n --stdin`::
 
        Apply the changes introduced by all commits on the master
        branch that touched README to the working tree and index,
index 79448c505bd66f370ab0d79fd9f6a31af84752be..f6c19c734d0fad09e7f7203a69959546f4b6a052 100644 (file)
@@ -7,6 +7,7 @@ git-cherry - Find commits not merged upstream
 
 SYNOPSIS
 --------
+[verse]
 'git cherry' [-v] [<upstream> [<head> [<limit>]]]
 
 DESCRIPTION
index 6e5c8126f595b95f70df2b02c0779cb06527bfa7..c7a11c36c10039f9b06241c28731a8cc208c53c7 100644 (file)
@@ -7,6 +7,7 @@ git-citool - Graphical alternative to git-commit
 
 SYNOPSIS
 --------
+[verse]
 'git citool'
 
 DESCRIPTION
index f524d76019960512ba65a0110a542fedf9a54ebb..0fdb82ee8697a53beab6defd4db9eca8840b1dd0 100644 (file)
@@ -8,6 +8,7 @@ git-commit-tree - Create a new commit object
 
 SYNOPSIS
 --------
+[verse]
 'git commit-tree' <tree> [(-p <parent commit>)...] < changelog
 
 DESCRIPTION
index a73933a931161ba81d6bf8dfaa9f2fe4287e0331..23c80cea6465d23476935abcfabba8e1deb915ee 100644 (file)
@@ -7,6 +7,7 @@ git-count-objects - Count unpacked number of objects and their disk consumption
 
 SYNOPSIS
 --------
+[verse]
 'git count-objects' [-v]
 
 DESCRIPTION
index ad93a3e84e732291bbd1e4de196ddb8ce23eea32..7f79cec3f8e9f90f61e461521eed2ca23fba69d1 100644 (file)
@@ -8,6 +8,7 @@ git-cvsexportcommit - Export a single commit to a CVS checkout
 
 SYNOPSIS
 --------
+[verse]
 'git cvsexportcommit' [-h] [-u] [-v] [-c] [-P] [-p] [-a] [-d cvsroot]
        [-w cvsworkdir] [-W] [-f] [-m msgprefix] [PARENTCOMMIT] COMMITID
 
index 8d481948bd9b29393c8884abfef9d0a76c922c2d..906774f0f7e0f907740d1382d48f7859219478e7 100644 (file)
@@ -8,6 +8,7 @@ git-diff-files - Compares files in the working tree and the index
 
 SYNOPSIS
 --------
+[verse]
 'git diff-files' [-q] [-0|-1|-2|-3|-c|--cc] [<common diff options>] [<path>...]
 
 DESCRIPTION
index 2ea22abca2bc72abb0cedfe6f47616c52a60d3f4..c0b7c581add35e24128a6b7e9aa79a50f914aad5 100644 (file)
@@ -8,6 +8,7 @@ git-diff-index - Compares content and mode of blobs between the index and reposi
 
 SYNOPSIS
 --------
+[verse]
 'git diff-index' [-m] [--cached] [<common diff options>] <tree-ish> [<path>...]
 
 DESCRIPTION
index 590f410abf0b902160eca0e92888191a2e2a0b89..a03515f1eccddded2efbd46ca522f3bac8896d90 100644 (file)
@@ -7,6 +7,7 @@ git-difftool - Show changes using common diff tools
 
 SYNOPSIS
 --------
+[verse]
 'git difftool' [<options>] [<commit> [<commit>]] [--] [<path>...]
 
 DESCRIPTION
index 781bd6edc3cce9d1488bf793231d08119e142948..f37eada63a449995861f41e5020c04f26d40c6f2 100644 (file)
@@ -8,6 +8,7 @@ git-fast-export - Git data exporter
 
 SYNOPSIS
 --------
+[verse]
 'git fast-export [options]' | 'git fast-import'
 
 DESCRIPTION
@@ -82,6 +83,10 @@ marks the same across runs.
        allow that.  So fake a tagger to be able to fast-import the
        output.
 
+--use-done-feature::
+       Start the stream with a 'feature done' stanza, and terminate
+       it with a 'done' command.
+
 --no-data::
        Skip output of blob objects and instead refer to blobs via
        their original SHA-1 hash.  This is useful when rewriting the
index 249249aac7b2b9def824794b2bf71e2c7fe497ce..2969388880a6d827a9970dd9d67fd81224a5bc34 100644 (file)
@@ -8,6 +8,7 @@ git-fast-import - Backend for fast Git data importers
 
 SYNOPSIS
 --------
+[verse]
 frontend | 'git fast-import' [options]
 
 DESCRIPTION
@@ -101,6 +102,12 @@ OPTIONS
        when the `cat-blob` command is encountered in the stream.
        The default behaviour is to write to `stdout`.
 
+--done::
+       Require a `done` command at the end of the stream.
+       This option might be useful for detecting errors that
+       cause the frontend to terminate before it has started to
+       write a stream.
+
 --export-pack-edges=<file>::
        After creating a packfile, print a line of data to
        <file> listing the filename of the packfile and the last
@@ -330,6 +337,11 @@ and control the current import process.  More detailed discussion
        standard output.  This command is optional and is not needed
        to perform an import.
 
+`done`::
+       Marks the end of the stream. This command is optional
+       unless the `done` feature was requested using the
+       `--done` command line option or `feature done` command.
+
 `cat-blob`::
        Causes fast-import to print a blob in 'cat-file --batch'
        format to the file descriptor set with `--cat-blob-fd` or
@@ -648,9 +660,14 @@ paths for a commit are encouraged to do so.
 
 `notemodify`
 ^^^^^^^^^^^^
-Included in a `commit` command to add a new note (annotating a given
-commit) or change the content of an existing note.  This command has
-two different means of specifying the content of the note.
+Included in a `commit` `<notes_ref>` command to add a new note
+annotating a `<committish>` or change this annotation contents.
+Internally it is similar to filemodify 100644 on `<committish>`
+path (maybe split into subdirectories). It's not advised to
+use any other commands to write to the `<notes_ref>` tree except
+`filedeleteall` to delete all existing notes in this tree.
+This command has two different means of specifying the content
+of the note.
 
 External data format::
        The data content for the note was already supplied by a prior
@@ -1015,6 +1032,11 @@ notes::
        Versions of fast-import not supporting notes will exit
        with a message indicating so.
 
+done::
+       Error out if the stream ends without a 'done' command.
+       Without this feature, errors causing the frontend to end
+       abruptly at a convenient point in the stream can go
+       undetected.
 
 `option`
 ~~~~~~~~
@@ -1044,6 +1066,15 @@ not be passed as option:
 * cat-blob-fd
 * force
 
+`done`
+~~~~~~
+If the `done` feature is not in use, treated as if EOF was read.
+This can be used to tell fast-import to finish early.
+
+If the `--done` command line option or `feature done` command is
+in use, the `done` command is mandatory and marks the end of the
+stream.
+
 Crash Reports
 -------------
 If fast-import is supplied invalid input it will terminate with a
index 48d4bf6d68fd51d9374f896ac839351936580e31..ed1bdaacd10788ab35a2ae1de870d5972e30d432 100644 (file)
@@ -8,6 +8,7 @@ git-fetch-pack - Receive missing objects from another repository
 
 SYNOPSIS
 --------
+[verse]
 'git fetch-pack' [--all] [--quiet|-q] [--keep|-k] [--thin] [--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] [--no-progress] [-v] [<host>:]<directory> [<refs>...]
 
 DESCRIPTION
index 60ac8d26eb3203abd29adc4c0a007f80bb616caa..b41d7c1de1e501e267bc9dfb0c13819b04e3b8aa 100644 (file)
@@ -8,12 +8,10 @@ git-fetch - Download objects and refs from another repository
 
 SYNOPSIS
 --------
+[verse]
 'git fetch' [<options>] [<repository> [<refspec>...]]
-
 'git fetch' [<options>] <group>
-
 'git fetch' --multiple [<options>] [(<repository> | <group>)...]
-
 'git fetch' --all [<options>]
 
 
index 9dc1f2a94708d40daf428a427dd2ea4256cc172a..0f2f1173834bdee77bd1d8d77e070af07a7b3580 100644 (file)
@@ -32,8 +32,9 @@ changes, which would normally have no effect.  Nevertheless, this may be
 useful in the future for compensating for some git bugs or such,
 therefore such a usage is permitted.
 
-*NOTE*: This command honors `.git/info/grafts`. If you have any grafts
-defined, running this command will make them permanent.
+*NOTE*: This command honors `.git/info/grafts` and `.git/refs/replace/`.
+If you have any grafts or replacement refs defined, running this command
+will make them permanent.
 
 *WARNING*! The rewritten history will have different object names for all
 the objects and will not converge with the original branch.  You will not
index 90ebb8a59401ddd16622533cc998bbb218137e34..eec4bdb600d8ca03a6fd7138e945dceb6dc43ec7 100644 (file)
@@ -8,6 +8,7 @@ git-fsck-objects - Verifies the connectivity and validity of the objects in the
 
 SYNOPSIS
 --------
+[verse]
 'git fsck-objects' ...
 
 DESCRIPTION
index 4966cb57846412b097bbc8ba15d09005f4019340..815afcb9228aada96a143a4e5dcdec0e0ee807e5 100644 (file)
@@ -8,6 +8,7 @@ git-gc - Cleanup unnecessary files and optimize the local repository
 
 SYNOPSIS
 --------
+[verse]
 'git gc' [--aggressive] [--auto] [--quiet] [--prune=<date> | --no-prune]
 
 DESCRIPTION
index 8035736c9682d5615c98dc83eaff6cf389d6c463..1e2a20dd265c2c41aef0ea66ca9831321d951d5c 100644 (file)
@@ -8,6 +8,7 @@ git-get-tar-commit-id - Extract commit ID from an archive created using git-arch
 
 SYNOPSIS
 --------
+[verse]
 'git get-tar-commit-id' < <tarfile>
 
 
index 07b3c6a0866c5b4ff0b4653b462b332ea0d348c9..062711139c0da753125ae429d7cc3c8a1368a279 100644 (file)
@@ -215,15 +215,15 @@ OPTIONS
 Examples
 --------
 
-git grep {apostrophe}time_t{apostrophe} \-- {apostrophe}*.[ch]{apostrophe}::
+`git grep {apostrophe}time_t{apostrophe} \-- {apostrophe}*.[ch]{apostrophe}`::
        Looks for `time_t` in all tracked .c and .h files in the working
        directory and its subdirectories.
 
-git grep -e {apostrophe}#define{apostrophe} --and \( -e MAX_PATH -e PATH_MAX \)::
+`git grep -e {apostrophe}#define{apostrophe} --and \( -e MAX_PATH -e PATH_MAX \)`::
        Looks for a line that has `#define` and either `MAX_PATH` or
        `PATH_MAX`.
 
-git grep --all-match -e NODE -e Unexpected::
+`git grep --all-match -e NODE -e Unexpected`::
        Looks for a line that has `NODE` or `Unexpected` in
        files that have lines that match both.
 
index 32a833e0ae522f034b9b7c9115c486aa68658b2c..0041994443c42033ee7c378ffad8983b0163489e 100644 (file)
@@ -7,6 +7,7 @@ git-gui - A portable graphical interface to Git
 
 SYNOPSIS
 --------
+[verse]
 'git gui' [<command>] [arguments]
 
 DESCRIPTION
@@ -49,7 +50,7 @@ version::
 
 Examples
 --------
-git gui blame Makefile::
+`git gui blame Makefile`::
 
        Show the contents of the file 'Makefile' in the current
        working directory, and provide annotations for both the
@@ -58,41 +59,41 @@ git gui blame Makefile::
        uncommitted changes (if any) are explicitly attributed to
        'Not Yet Committed'.
 
-git gui blame v0.99.8 Makefile::
+`git gui blame v0.99.8 Makefile`::
 
        Show the contents of 'Makefile' in revision 'v0.99.8'
        and provide annotations for each line.  Unlike the above
        example the file is read from the object database and not
        the working directory.
 
-git gui blame --line=100 Makefile::
+`git gui blame --line=100 Makefile`::
 
        Loads annotations as described above and automatically
        scrolls the view to center on line '100'.
 
-git gui citool::
+`git gui citool`::
 
        Make one commit and return to the shell when it is complete.
        This command returns a non-zero exit code if the window was
        closed in any way other than by making a commit.
 
-git gui citool --amend::
+`git gui citool --amend`::
 
        Automatically enter the 'Amend Last Commit' mode of
        the interface.
 
-git gui citool --nocommit::
+`git gui citool --nocommit`::
 
        Behave as normal citool, but instead of making a commit
        simply terminate with a zero exit code. It still checks
        that the index does not contain any unmerged entries, so
        you can use it as a GUI version of linkgit:git-mergetool[1]
 
-git citool::
+`git citool`::
 
        Same as `git gui citool` (above).
 
-git gui browser maint::
+`git gui browser maint`::
 
        Show a browser for the tree of the 'maint' branch.  Files
        selected in the browser can be viewed with the internal
index 42aa2b0c012aaa559162517ee8913ba8bbe72212..9e0b3f68116321dfb6a01f0095c6cdfa5a1a4f20 100644 (file)
@@ -7,6 +7,7 @@ git-help - display help information about git
 
 SYNOPSIS
 --------
+[verse]
 'git help' [-a|--all|-i|--info|-m|--man|-w|--web] [COMMAND]
 
 DESCRIPTION
index fefa75219822331f7c7bc426a1224978a5da6795..4d42073867b09317dc674b0c0f5f1b76d4129a03 100644 (file)
@@ -8,6 +8,7 @@ git-http-fetch - Download from a remote git repository via HTTP
 
 SYNOPSIS
 --------
+[verse]
 'git http-fetch' [-c] [-t] [-a] [-d] [-v] [-w filename] [--recover] [--stdin] <commit> <url>
 
 DESCRIPTION
index 82ae34b9b80d8f3fd8605d5c06cc37c7a203f758..2e67362bd4b60607e7ccfeafbfebdc4cf68058e7 100644 (file)
@@ -8,6 +8,7 @@ git-http-push - Push objects over HTTP/DAV to another repository
 
 SYNOPSIS
 --------
+[verse]
 'git http-push' [--all] [--dry-run] [--force] [--verbose] <url> <ref> [<ref>...]
 
 DESCRIPTION
index 4e09708cc96fbf88b468141c0234095ee35fee3c..875d2831a541170402849e2c8598fabafa42a0df 100644 (file)
@@ -8,6 +8,7 @@ git-imap-send - Send a collection of patches from stdin to an IMAP folder
 
 SYNOPSIS
 --------
+[verse]
 'git imap-send'
 
 
index 9f97f5a91584a7469a3b0d2f8705febbe5c5ab58..a21e34678933ee5a6b222afc40293fec4166b110 100644 (file)
@@ -8,6 +8,7 @@ git-init-db - Creates an empty git repository
 
 SYNOPSIS
 --------
+[verse]
 'git init-db' [-q | --quiet] [--bare] [--template=<template_directory>] [--separate-git-dir <git dir>] [--shared[=<permissions>]]
 
 
index f2777a7786e6bf9c0cb907c77134b06321523654..9ac2bbaa565455b25146a6fe0e24d0deebd90c4c 100644 (file)
@@ -8,6 +8,7 @@ git-init - Create an empty git repository or reinitialize an existing one
 
 SYNOPSIS
 --------
+[verse]
 'git init' [-q | --quiet] [--bare] [--template=<template_directory>]
          [--separate-git-dir <git dir>]
          [--shared[=<permissions>]] [directory]
index de5c0d37a5c1c8c948aa01e276c3e198eb617be6..6c934660d7bf0b5822bf2a7e6f8eb68cecbfc501 100644 (file)
@@ -8,6 +8,7 @@ git-log - Show commit logs
 
 SYNOPSIS
 --------
+[verse]
 'git log' [<options>] [<since>..<until>] [[\--] <path>...]
 
 DESCRIPTION
@@ -87,45 +88,45 @@ include::diff-generate-patch.txt[]
 
 Examples
 --------
-git log --no-merges::
+`git log --no-merges`::
 
        Show the whole commit history, but skip any merges
 
-git log v2.6.12.. include/scsi drivers/scsi::
+`git log v2.6.12.. include/scsi drivers/scsi`::
 
        Show all commits since version 'v2.6.12' that changed any file
        in the include/scsi or drivers/scsi subdirectories
 
-git log --since="2 weeks ago" \-- gitk::
+`git log --since="2 weeks ago" \-- gitk`::
 
        Show the changes during the last two weeks to the file 'gitk'.
        The "--" is necessary to avoid confusion with the *branch* named
        'gitk'
 
-git log --name-status release..test::
+`git log --name-status release..test`::
 
        Show the commits that are in the "test" branch but not yet
        in the "release" branch, along with the list of paths
        each commit modifies.
 
-git log --follow builtin-rev-list.c::
+`git log --follow builtin-rev-list.c`::
 
        Shows the commits that changed builtin-rev-list.c, including
        those commits that occurred before the file was given its
        present name.
 
-git log --branches --not --remotes=origin::
+`git log --branches --not --remotes=origin`::
 
        Shows all commits that are in any of local branches but not in
        any of remote-tracking branches for 'origin' (what you have that
        origin doesn't).
 
-git log master --not --remotes=*/master::
+`git log master --not --remotes=*/master`::
 
        Shows all commits that are in local master but not in any remote
        repository master branches.
 
-git log -p -m --first-parent::
+`git log -p -m --first-parent`::
 
        Shows the history including change diffs, but only from the
        "main branch" perspective, skipping commits that come from merged
index adf7e1c0557b3dab145403d73687f5e125ae73f4..c406a1100159471cf904629b5d4afc0469c382c0 100644 (file)
@@ -7,6 +7,7 @@ git-lost-found - Recover lost refs that luckily have not yet been pruned
 
 SYNOPSIS
 --------
+[verse]
 'git lost-found'
 
 DESCRIPTION
index ed45662cc9bb0ef93c6748d02e3791ac915830f9..51dc3257486b07edaec71fe98fed6533e17e1a77 100644 (file)
@@ -8,6 +8,7 @@ git-mailinfo - Extracts patch and authorship from a single e-mail message
 
 SYNOPSIS
 --------
+[verse]
 'git mailinfo' [-k|-b] [-u | --encoding=<encoding> | -n] [--scissors] <msg> <patch>
 
 
index 9b2049d674a5d0b71a9454b2ce4afbfa59e2db34..4d1b871d96177ca36e7fadd115685316292dc727 100644 (file)
@@ -7,6 +7,7 @@ git-mailsplit - Simple UNIX mbox splitter program
 
 SYNOPSIS
 --------
+[verse]
 'git mailsplit' [-b] [-f<nn>] [-d<prec>] [--keep-cr] -o<directory> [--] [(<mbox>|<Maildir>)...]
 
 DESCRIPTION
index 635c66956e90452c58938f2d48e84454983f22e6..d7db2a3737fbdb032747bc6dd2740be1a56dfced 100644 (file)
@@ -76,12 +76,12 @@ OPTIONS
 EXAMPLES
 --------
 
-git merge-file README.my README README.upstream::
+`git merge-file README.my README README.upstream`::
 
        combines the changes of README.my and README.upstream since README,
        tries to merge them and writes the result into README.my.
 
-git merge-file -L a -L b -L c tmp/a123 tmp/b234 tmp/c345::
+`git merge-file -L a -L b -L c tmp/a123 tmp/b234 tmp/c345`::
 
        merges tmp/a123 and tmp/c345 with the base tmp/b234, but uses labels
        `a` and `c` instead of `tmp/a123` and `tmp/c345`.
index 6ce54673b0c239a04503ce9da231826c61470bd1..e0df1b33408df881057963896fb0d0d3cd5edd66 100644 (file)
@@ -8,6 +8,7 @@ git-merge-index - Run a merge for files needing merging
 
 SYNOPSIS
 --------
+[verse]
 'git merge-index' [-o] [-q] <merge-program> (-a | [--] <file>*)
 
 DESCRIPTION
index ee059def79f85e770b23b34bce1dfc293434aa8b..04e803d5d3362c97e92efc22bdec4fe526946c6f 100644 (file)
@@ -8,6 +8,7 @@ git-merge-one-file - The standard helper program to use with git-merge-index
 
 SYNOPSIS
 --------
+[verse]
 'git merge-one-file'
 
 DESCRIPTION
index 3bfa7b422026181f675a7398d41e1153fdfbd837..c5f84b649504f1708be9cd925023af3afd685337 100644 (file)
@@ -8,6 +8,7 @@ git-merge-tree - Show three-way merge without touching index
 
 SYNOPSIS
 --------
+[verse]
 'git merge-tree' <base-tree> <branch1> <branch2>
 
 DESCRIPTION
index 5b0d51f7f8cfc52739463dd90827fe5d0dc1b58c..f98a41b87c16007d6d9fa916c6a3bb31fb049216 100644 (file)
@@ -7,6 +7,7 @@ git-mergetool--lib - Common git merge tool shell scriptlets
 
 SYNOPSIS
 --------
+[verse]
 'TOOL_MODE=(diff|merge) . "$(git --exec-path)/git-mergetool{litdd}lib"'
 
 DESCRIPTION
index 8c79ae8d2a610bf4f1dea1a840bfc52e85d90fd9..347091010995af95e43ced744b159b277bdb6cdc 100644 (file)
@@ -7,6 +7,7 @@ git-mergetool - Run merge conflict resolution tools to resolve merge conflicts
 
 SYNOPSIS
 --------
+[verse]
 'git mergetool' [--tool=<tool>] [-y|--no-prompt|--prompt] [<file>...]
 
 DESCRIPTION
index 037ab1045d91b730e5cae9073226bd09ebe67b9a..65e167a5c580c694a66cbb391938359a38ddd3e0 100644 (file)
@@ -8,6 +8,7 @@ git-mktag - Creates a tag object
 
 SYNOPSIS
 --------
+[verse]
 'git mktag' < signature_file
 
 DESCRIPTION
index afe21be64dfa9ea2540f9c4fc24d97413643879f..5c6ebdfad93ea87f973194b2fe31e784033dc3c6 100644 (file)
@@ -8,6 +8,7 @@ git-mktree - Build a tree-object from ls-tree formatted text
 
 SYNOPSIS
 --------
+[verse]
 'git mktree' [-z] [--missing] [--batch]
 
 DESCRIPTION
index db0e030d69f92a1f52cd7c98de99504e850ab2db..b8db3739640491566dee6e381bae319b7e7be8c6 100644 (file)
@@ -8,6 +8,7 @@ git-mv - Move or rename a file, a directory, or a symlink
 
 SYNOPSIS
 --------
+[verse]
 'git mv' <options>... <args>...
 
 DESCRIPTION
index db9f0f70554d997fab9d8441f78c10e523dda178..f2869da57282658e8f689905a686ba2f74bc9020 100644 (file)
@@ -8,6 +8,7 @@ git-pack-redundant - Find redundant pack files
 
 SYNOPSIS
 --------
+[verse]
 'git pack-redundant' [ --verbose ] [ --alt-odb ] < --all | .pack filename ... >
 
 DESCRIPTION
index 54b92534ceb7895dadf1bec22782af3d09f1ef78..a3c6677bfaaf628410eb85ce06f58d3c2b4df966 100644 (file)
@@ -7,6 +7,7 @@ git-pack-refs - Pack heads and tags for efficient repository access
 
 SYNOPSIS
 --------
+[verse]
 'git pack-refs' [--all] [--no-prune]
 
 DESCRIPTION
index 02217f6ba2007bb7bc55c577b77773dfcce93225..a45ea1ece81a1340de7748afa2390ca6f03ab549 100644 (file)
@@ -8,6 +8,7 @@ git-parse-remote - Routines to help parsing remote repository access parameters
 
 SYNOPSIS
 --------
+[verse]
 '. "$(git --exec-path)/git-parse-remote"'
 
 DESCRIPTION
index 50e26f43c1cd9fde593760d1557ac57b3695ae5c..90268f02e7381b6f1403e54103988bfde6522073 100644 (file)
@@ -7,6 +7,7 @@ git-patch-id - Compute unique ID for a patch
 
 SYNOPSIS
 --------
+[verse]
 'git patch-id' < <patch>
 
 DESCRIPTION
index a34d62f0daa3ada5c5287008b05d989eb52cc8f0..87ea3fb05418f858ed3aac3d34eceb371bc0e07f 100644 (file)
@@ -8,6 +8,7 @@ git-peek-remote - List the references in a remote repository
 
 SYNOPSIS
 --------
+[verse]
 'git peek-remote' [--upload-pack=<git-upload-pack>] [<host>:]<directory>
 
 DESCRIPTION
index 9e6202cdffd01fc685a78d1bd2c56128a8b8b73a..80dc022edea58b76aeea2f7df0876fd98bc6dc05 100644 (file)
@@ -8,6 +8,7 @@ git-prune-packed - Remove extra objects that are already in pack files
 
 SYNOPSIS
 --------
+[verse]
 'git prune-packed' [-n|--dry-run] [-q|--quiet]
 
 
index f616a739efdab16a58c33e9c2671e8afbaf13b98..80d01b05710e250a5f1d548fca3fba54d50e0f29 100644 (file)
@@ -8,6 +8,7 @@ git-prune - Prune all unreachable objects from the object database
 
 SYNOPSIS
 --------
+[verse]
 'git prune' [-n] [-v] [--expire <expire>] [--] [<head>...]
 
 DESCRIPTION
index 14609cbd4dc2f7f3c16f7b660e4aff76eca6065b..e1da46876682e9d95a7505e1bc116cbe07f2ec61 100644 (file)
@@ -8,6 +8,7 @@ git-pull - Fetch from and merge with another repository or a local branch
 
 SYNOPSIS
 --------
+[verse]
 'git pull' [options] [<repository> [<refspec>...]]
 
 
index 88acfcd4cc8e0eeafc809df0d72b37daded6f8a6..49c6e9fa51daea75272ea7eec8a360bfd324a467 100644 (file)
@@ -327,12 +327,12 @@ a case where you do mean to lose history.
 Examples
 --------
 
-git push::
+`git push`::
        Works like `git push <remote>`, where <remote> is the
        current branch's remote (or `origin`, if no remote is
        configured for the current branch).
 
-git push origin::
+`git push origin`::
        Without additional configuration, works like
        `git push origin :`.
 +
@@ -344,45 +344,45 @@ use `git config remote.origin.push HEAD`.  Any valid <refspec> (like
 the ones in the examples below) can be configured as the default for
 `git push origin`.
 
-git push origin :::
+`git push origin :`::
        Push "matching" branches to `origin`. See
        <refspec> in the <<OPTIONS,OPTIONS>> section above for a
        description of "matching" branches.
 
-git push origin master::
+`git push origin master`::
        Find a ref that matches `master` in the source repository
        (most likely, it would find `refs/heads/master`), and update
        the same ref (e.g. `refs/heads/master`) in `origin` repository
        with it.  If `master` did not exist remotely, it would be
        created.
 
-git push origin HEAD::
+`git push origin HEAD`::
        A handy way to push the current branch to the same name on the
        remote.
 
-git push origin master:satellite/master dev:satellite/dev::
+`git push origin master:satellite/master dev:satellite/dev`::
        Use the source ref that matches `master` (e.g. `refs/heads/master`)
        to update the ref that matches `satellite/master` (most probably
        `refs/remotes/satellite/master`) in the `origin` repository, then
        do the same for `dev` and `satellite/dev`.
 
-git push origin HEAD:master::
+`git push origin HEAD:master`::
        Push the current branch to the remote ref matching `master` in the
        `origin` repository. This form is convenient to push the current
        branch without thinking about its local name.
 
-git push origin master:refs/heads/experimental::
+`git push origin master:refs/heads/experimental`::
        Create the branch `experimental` in the `origin` repository
        by copying the current `master` branch.  This form is only
        needed to create a new branch or tag in the remote repository when
        the local name and the remote name are different; otherwise,
        the ref name on its own will work.
 
-git push origin :experimental::
+`git push origin :experimental`::
        Find a ref that matches `experimental` in the `origin` repository
        (e.g. `refs/heads/experimental`), and delete it.
 
-git push origin {plus}dev:master::
+`git push origin {plus}dev:master`::
        Update the origin repository's master branch with the dev branch,
        allowing non-fast-forward updates.  *This can leave unreferenced
        commits dangling in the origin repository.*  Consider the
index 46a96f2313e0cb48bff9d5de26f403b35d327d2c..c45d53c6e150479bd01bf3d643354348d8ce9273 100644 (file)
@@ -8,6 +8,7 @@ git-read-tree - Reads tree information into the index
 
 SYNOPSIS
 --------
+[verse]
 'git read-tree' [[-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>]
                [-u [--exclude-per-directory=<gitignore>] | -i]]
                [--index-output=<file>] [--no-sparse-checkout]
index 9a075bc4d24d59c7b585e204e6feb50326c762f3..504945c69153a30252527c16945836fd2aa2ec5a 100644 (file)
@@ -12,7 +12,6 @@ SYNOPSIS
        [<upstream>] [<branch>]
 'git rebase' [-i | --interactive] [options] --onto <newbase>
        --root [<branch>]
-
 'git rebase' --continue | --skip | --abort
 
 DESCRIPTION
@@ -46,7 +45,7 @@ with a different commit message or timestamp will be skipped).
 It is possible that a merge failure will prevent this process from being
 completely automatic.  You will have to resolve any such merge failure
 and run `git rebase --continue`.  Another option is to bypass the commit
-that caused the merge failure with `git rebase --skip`.  To restore the
+that caused the merge failure with `git rebase --skip`.  To check out the
 original <branch> and remove the .git/rebase-apply working files, use the
 command `git rebase --abort` instead.
 
@@ -233,7 +232,11 @@ leave out at most one of A and B, in which case it defaults to HEAD.
        Restart the rebasing process after having resolved a merge conflict.
 
 --abort::
-       Restore the original branch and abort the rebase operation.
+       Abort the rebase operation and reset HEAD to the original
+       branch. If <branch> was provided when the rebase operation was
+       started, then HEAD will be reset to <branch>. Otherwise HEAD
+       will be reset to where it was when the rebase operation was
+       started.
 
 --skip::
        Restart the rebasing process by skipping the current patch.
index f34e0ae1bd4bf9f3d0fa5de1e8b0eba47637f7a6..459c08598f31fccf1b5db31f2f1cd9680654b389 100644 (file)
@@ -8,6 +8,7 @@ git-receive-pack - Receive what is pushed into the repository
 
 SYNOPSIS
 --------
+[verse]
 'git-receive-pack' <directory>
 
 DESCRIPTION
index 09057bf90cbea3a360cf65c212c358d9c848f11a..976dc1493799c46bc2a390fde36063ae4e7a0e11 100644 (file)
@@ -8,6 +8,7 @@ git-reflog - Manage reflog information
 
 SYNOPSIS
 --------
+[verse]
 'git reflog' <subcommand> <options>
 
 DESCRIPTION
index 98933764870fa73d693c636e713fd1f08eb8244d..3b33c995103060e97977e2977d8114389a29ae3c 100644 (file)
@@ -7,6 +7,7 @@ git-relink - Hardlink common objects in local repositories
 
 SYNOPSIS
 --------
+[verse]
 'git relink' [--safe] <dir>... <master_dir>
 
 DESCRIPTION
index 68263a6a538b3d4659ca9dc0afd2253170143fb6..8a8e1d775d3650bc59ea7db2335cad356a8036b4 100644 (file)
@@ -7,6 +7,7 @@ git-remote-ext - Bridge smart transport to external command.
 
 SYNOPSIS
 --------
+[verse]
 git remote add <nick> "ext::<command>[ <arguments>...]"
 
 DESCRIPTION
index 4aecd4d1878e0af6c3e6c87a63df1375606ff65a..f095d57d09f215e48e1f832ca0698e5666119f2b 100644 (file)
@@ -35,19 +35,19 @@ GIT_TRANSLOOP_DEBUG::
 
 EXAMPLES
 --------
-git fetch fd::17 master::
+`git fetch fd::17 master`::
        Fetch master, using file descriptor #17 to communicate with
        git-upload-pack.
 
-git fetch fd::17/foo master::
+`git fetch fd::17/foo master`::
        Same as above.
 
-git push fd::7,8 master (as URL)::
+`git push fd::7,8 master (as URL)`::
        Push master, using file descriptor #7 to read data from
        git-receive-pack and file descriptor #8 to write data to
        same service.
 
-git push fd::7,8/bar master::
+`git push fd::7,8/bar master`::
        Same as above.
 
 Documentation
index 58f6ad4994dae770b1898888d3073fca777743af..4f83dea5a39ca2f8e695a2426e90cf0450533696 100644 (file)
@@ -7,6 +7,7 @@ git-remote-helpers - Helper programs to interact with remote repositories
 
 SYNOPSIS
 --------
+[verse]
 'git remote-<transport>' <repository> [<URL>]
 
 DESCRIPTION
@@ -47,6 +48,9 @@ arguments. The first argument specifies a remote repository as in git;
 it is either the name of a configured remote or a URL. The second
 argument specifies a URL; it is usually of the form
 '<transport>://<address>', but any arbitrary string is possible.
+The 'GIT_DIR' environment variable is set up for the remote helper
+and can be used to determine where to store additional data or from
+which directory to invoke auxiliary git commands.
 
 When git encounters a URL of the form '<transport>://<address>', where
 '<transport>' is a protocol that it cannot handle natively, it
index 0decee240bfbad5c924de36e1867edca9975f39c..40af321153b85845fc362501d91f2178e0b3e42c 100644 (file)
@@ -8,6 +8,7 @@ git-repack - Pack unpacked objects in a repository
 
 SYNOPSIS
 --------
+[verse]
 'git repack' [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [--window=<n>] [--depth=<n>]
 
 DESCRIPTION
index a0d1fa6594cc4fed65c7ce68a4957e5e611cfa78..9ec115b9e034cee65449eff70f032b7b0c225108 100644 (file)
@@ -8,6 +8,7 @@ git-repo-config - Get and set repository or global options
 
 SYNOPSIS
 --------
+[verse]
 'git repo-config' ...
 
 
index 3521d8e3c88c97f85ab95d82d416256d0debc94c..b99681ce85abc0879f11e99654e1bdb6ba5dd688 100644 (file)
@@ -7,6 +7,7 @@ git-request-pull - Generates a summary of pending changes
 
 SYNOPSIS
 --------
+[verse]
 'git request-pull' [-p] <start> <url> [<end>]
 
 DESCRIPTION
index 52db1d80cfe068f39ae5996a88e95bbfcf095a36..a6253ba617f5ebcd82e4cfb1702999c145fa346c 100644 (file)
@@ -7,6 +7,7 @@ git-rerere - Reuse recorded resolution of conflicted merges
 
 SYNOPSIS
 --------
+[verse]
 'git rerere' ['clear'|'forget' <pathspec>|'diff'|'status'|'gc']
 
 DESCRIPTION
index 02c44c999f361cd7c40a504ae4ccdc2d8b1a18fe..42c9676eaa40f2a3d43514c09509e319258ca8b4 100644 (file)
@@ -8,6 +8,7 @@ git-rev-parse - Pick out and massage parameters
 
 SYNOPSIS
 --------
+[verse]
 'git rev-parse' [ --option ] <args>...
 
 DESCRIPTION
index 6a21b37f95986ad04140be4cbef3ba011cbe5220..b311d59c7c06dd696e3c667c97a5982137bdd87a 100644 (file)
@@ -7,6 +7,7 @@ git-revert - Revert some existing commits
 
 SYNOPSIS
 --------
+[verse]
 'git revert' [--edit | --no-edit] [-n] [-m parent-number] [-s] <commit>...
 
 DESCRIPTION
@@ -92,12 +93,12 @@ effect to your index in a row.
 
 EXAMPLES
 --------
-git revert HEAD~3::
+`git revert HEAD~3`::
 
        Revert the changes specified by the fourth last commit in HEAD
        and create a new commit with the reverted changes.
 
-git revert -n master{tilde}5..master{tilde}2::
+`git revert -n master{tilde}5..master{tilde}2`::
 
        Revert the changes done by commits from the fifth last commit
        in master (included) to the third last commit in master
index 8c0554f9716c0d3ca7570a8f893f48189ea0c6f8..665ad4ddab14da173142914407680605dad9dae6 100644 (file)
@@ -7,6 +7,7 @@ git-rm - Remove files from the working tree and from the index
 
 SYNOPSIS
 --------
+[verse]
 'git rm' [-f | --force] [-n] [-r] [--cached] [--ignore-unmatch] [--quiet] [--] <file>...
 
 DESCRIPTION
@@ -136,7 +137,7 @@ git diff --name-only --diff-filter=D -z | xargs -0 git rm --cached
 
 EXAMPLES
 --------
-git rm Documentation/\*.txt::
+`git rm Documentation/\*.txt`::
        Removes all `*.txt` files from the index that are under the
        `Documentation` directory and any of its subdirectories.
 +
@@ -144,7 +145,7 @@ Note that the asterisk `*` is quoted from the shell in this
 example; this lets git, and not the shell, expand the pathnames
 of files and subdirectories under the `Documentation/` directory.
 
-git rm -f git-*.sh::
+`git rm -f git-*.sh`::
        Because this example lets the shell expand the asterisk
        (i.e. you are listing the files explicitly), it
        does not remove `subdir/git-foo.sh`.
index 5a168cfab2206cf67453bb5f1fd93dbe75bb4ef0..327233c85b4cb9af07b8866b055a83d25b21b569 100644 (file)
@@ -8,6 +8,7 @@ git-send-email - Send a collection of patches as emails
 
 SYNOPSIS
 --------
+[verse]
 'git send-email' [options] <file|directory|rev-list options>...
 
 
index 17f8f5552646cc063fdcc3674c0b133ed070aec9..bd3eaa69bfb6e788d297b3e7d2c871d25a478f80 100644 (file)
@@ -8,6 +8,7 @@ git-send-pack - Push objects over git protocol to another repository
 
 SYNOPSIS
 --------
+[verse]
 'git send-pack' [--all] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]
 
 DESCRIPTION
index eca69e3d82be1a54770c5efba5362410cd0cf43c..60cf49cb2a38df99d4526698576acd5cb6c979c4 100644 (file)
@@ -7,6 +7,7 @@ git-sh-i18n - Git's i18n setup code for shell scripts
 
 SYNOPSIS
 --------
+[verse]
 '. "$(git --exec-path)/git-sh-i18n"'
 
 DESCRIPTION
index 27fd8ba854698dcd31f5348ddc00a607abb64965..a2f346ca710e03a7f5c65574659ac578ab8bf615 100644 (file)
@@ -7,6 +7,7 @@ git-sh-setup - Common git shell script setup code
 
 SYNOPSIS
 --------
+[verse]
 '. "$(git --exec-path)/git-sh-setup"'
 
 DESCRIPTION
index d7d4b92894d143daaf1f0e27fa4bdbcf35aba10d..9b9250600f651eac7d6e2fd6ca7ff320a64de67c 100644 (file)
@@ -8,6 +8,7 @@ git-shell - Restricted login shell for Git-only SSH access
 
 SYNOPSIS
 --------
+[verse]
 'git shell' [-c <command> <argument>]
 
 DESCRIPTION
index ee4559b6f20d6cfe399c2b7e1b8dd9a1e2aafc7a..a8e77b5350c8c6a3cf62c22f811974ea64cff8ae 100644 (file)
@@ -13,7 +13,6 @@ SYNOPSIS
                [--more=<n> | --list | --independent | --merge-base]
                [--no-name | --sha1-name] [--topics]
                [(<rev> | <glob>)...]
-
 'git show-branch' (-g|--reflog)[=<n>[,<base>]] [--list] [<ref>]
 
 DESCRIPTION
index c4d99f10281599ae52f95da455372e8ed759cfe7..2dcbbb245421964d418818878cd05a4eda525513 100644 (file)
@@ -8,6 +8,7 @@ git-show-index - Show packed archive index
 
 SYNOPSIS
 --------
+[verse]
 'git show-index' < idx-file
 
 
index 7f075e84f54e3abc5c16b7cae57af831bd2b5bd7..1e38819e67cda4282ec7ede004ee5668d0a478c8 100644 (file)
@@ -8,6 +8,7 @@ git-show - Show various types of objects
 
 SYNOPSIS
 --------
+[verse]
 'git show' [options] <object>...
 
 DESCRIPTION
@@ -47,23 +48,23 @@ include::pretty-formats.txt[]
 EXAMPLES
 --------
 
-git show v1.0.0::
+`git show v1.0.0`::
        Shows the tag `v1.0.0`, along with the object the tags
        points at.
 
-git show v1.0.0^\{tree\}::
+`git show v1.0.0^\{tree\}`::
        Shows the tree pointed to by the tag `v1.0.0`.
 
-git show -s --format=%s v1.0.0^\{commit\}::
+`git show -s --format=%s v1.0.0^\{commit\}`::
        Shows the subject of the commit pointed to by the
        tag `v1.0.0`.
 
-git show next~10:Documentation/README::
+`git show next~10:Documentation/README`::
        Shows the contents of the file `Documentation/README` as
        they were current in the 10th last commit of the branch
        `next`.
 
-git show master:Makefile master:t/Makefile::
+`git show master:Makefile master:t/Makefile`::
        Concatenates the contents of said Makefiles in the head
        of the branch `master`.
 
index 15f051fa44e4b2e90da8383318c62695359772ce..43af38aa4bd7673bef2127058f171da039732c71 100644 (file)
@@ -13,7 +13,8 @@ SYNOPSIS
 'git stash' drop [-q|--quiet] [<stash>]
 'git stash' ( pop | apply ) [--index] [-q|--quiet] [<stash>]
 'git stash' branch <branchname> [<stash>]
-'git stash' [save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet] [<message>]]
+'git stash' [save [--patch] [-k|--[no-]keep-index] [-q|--quiet]
+            [-u|--include-untracked] [-a|--all] [<message>]]
 'git stash' clear
 'git stash' create
 
@@ -42,7 +43,7 @@ is also possible).
 OPTIONS
 -------
 
-save [-p|--patch] [--[no-]keep-index] [-q|--quiet] [<message>]::
+save [-p|--patch] [--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [<message>]::
 
        Save your local modifications to a new 'stash', and run `git reset
        --hard` to revert them.  The <message> part is optional and gives
@@ -54,6 +55,11 @@ save [-p|--patch] [--[no-]keep-index] [-q|--quiet] [<message>]::
 If the `--keep-index` option is used, all changes already added to the
 index are left intact.
 +
+If the `--include-untracked` option is used, all untracked files are also
+stashed and then cleaned up with `git clean`, leaving the working directory
+in a very clean state. If the `--all` option is used instead then the
+ignored files are stashed and cleaned in addition to the untracked files.
++
 With `--patch`, you can interactively select hunks from the diff
 between HEAD and the working tree to be stashed.  The stash entry is
 constructed such that its index state is the same as the index state
index 8ecc99d995fb86e4327c018467ed52d5345e6930..3d51717bbe84d0201b1c7a38943b2e99643bd89f 100644 (file)
@@ -8,6 +8,7 @@ git-status - Show the working tree status
 
 SYNOPSIS
 --------
+[verse]
 'git status' [<options>...] [--] [<pathspec>...]
 
 DESCRIPTION
index 10509cc450d47de35387a547cb79e30177f6304c..b78f031cd4464b21be145d4ffa79ff39dc8bd2bb 100644 (file)
@@ -8,6 +8,7 @@ git-stripspace - Filter out empty lines
 
 SYNOPSIS
 --------
+[verse]
 'git stripspace' [-s | --strip-comments] < <stream>
 
 DESCRIPTION
index acb9002fe432c6849bd894567d2272bfbe8efdbc..0ec85742ddc1c360d066659fb562898a259e48f7 100644 (file)
@@ -78,7 +78,9 @@ to exist in the superproject. If <path> is not given, the
 <repository> is the URL of the new submodule's origin repository.
 This may be either an absolute URL, or (if it begins with ./
 or ../), the location relative to the superproject's origin
-repository.
+repository. If the superproject doesn't have an origin configured
+the superproject is its own authoritative upstream and the current
+working directory is used instead.
 +
 <path> is the relative location for the cloned submodule to
 exist in the superproject. If <path> does not exist, then the
index 713e523034d5b95071e2285252c1796cd83c6fcd..ed5eca1fcef50f910d74abb495360dc6c3fbf35b 100644 (file)
@@ -7,6 +7,7 @@ git-svn - Bidirectional operation between a Subversion repository and git
 
 SYNOPSIS
 --------
+[verse]
 'git svn' <command> [options] [arguments]
 
 DESCRIPTION
index d7795ed65777c18e648ba1b23b1b63330b78c9ce..75b1ae5061b78524383221641aee5edd292028e6 100644 (file)
@@ -7,6 +7,7 @@ git-symbolic-ref - Read and modify symbolic refs
 
 SYNOPSIS
 --------
+[verse]
 'git symbolic-ref' [-q] [-m <reason>] <name> [<ref>]
 
 DESCRIPTION
index 5f1575425743118ffb13567472ae81be56698566..346e7a20797c22a29733f09e5fe241c84a46bfa9 100644 (file)
@@ -8,6 +8,7 @@ git-tar-tree - Create a tar archive of the files in the named tree object
 
 SYNOPSIS
 --------
+[verse]
 'git tar-tree' [--remote=<repo>] <tree-ish> [ <base> ]
 
 DESCRIPTION
@@ -52,26 +53,26 @@ tar.umask::
 
 EXAMPLES
 --------
-git tar-tree HEAD junk | (cd /var/tmp/ && tar xf -)::
+`git tar-tree HEAD junk | (cd /var/tmp/ && tar xf -)`::
 
        Create a tar archive that contains the contents of the
        latest commit on the current branch, and extracts it in
        `/var/tmp/junk` directory.
 
-git tar-tree v1.4.0 git-1.4.0 | gzip >git-1.4.0.tar.gz::
+`git tar-tree v1.4.0 git-1.4.0 | gzip >git-1.4.0.tar.gz`::
 
        Create a tarball for v1.4.0 release.
 
-git tar-tree v1.4.0{caret}\{tree\} git-1.4.0 | gzip >git-1.4.0.tar.gz::
+`git tar-tree v1.4.0{caret}\{tree\} git-1.4.0 | gzip >git-1.4.0.tar.gz`::
 
        Create a tarball for v1.4.0 release, but without a
        global extended pax header.
 
-git tar-tree --remote=example.com:git.git v1.4.0 >git-1.4.0.tar::
+`git tar-tree --remote=example.com:git.git v1.4.0 >git-1.4.0.tar`::
 
        Get a tarball v1.4.0 from example.com.
 
-git tar-tree HEAD:Documentation/ git-docs > git-1.4.0-docs.tar::
+`git tar-tree HEAD:Documentation/ git-docs > git-1.4.0-docs.tar`::
 
        Put everything in the current head's Documentation/ directory
        into 'git-1.4.0-docs.tar', with the prefix 'git-docs/'.
index c49d727f7463446c4182807cbd9077db5e34007f..e9f148a00ddbc996e440cd0fd7eecae4eeff3fa8 100644 (file)
@@ -9,6 +9,7 @@ git-unpack-file - Creates a temporary file with a blob's contents
 
 SYNOPSIS
 --------
+[verse]
 'git unpack-file' <blob>
 
 DESCRIPTION
index dd7799095b4dd26a1625015f3fe0fcbd89dd0e70..ff23494e7013c5d491c7a7e2642ec30133906aac 100644 (file)
@@ -8,6 +8,7 @@ git-unpack-objects - Unpack objects from a packed archive
 
 SYNOPSIS
 --------
+[verse]
 'git unpack-objects' [-n] [-q] [-r] [--strict] <pack-file
 
 
index e25a65a80fafb7143957247e2fd85d64a701ddf5..d377a352433cb38536f42c5b3fc6b80ae2b11f7f 100644 (file)
@@ -7,6 +7,7 @@ git-update-ref - Update the object name stored in a ref safely
 
 SYNOPSIS
 --------
+[verse]
 'git update-ref' [-m <reason>] (-d <ref> [<oldvalue>] | [--no-deref] <ref> <newvalue> [<oldvalue>])
 
 DESCRIPTION
@@ -60,8 +61,9 @@ still contains <oldvalue>.
 
 Logging Updates
 ---------------
-If config parameter "core.logAllRefUpdates" is true or the file
-"$GIT_DIR/logs/<ref>" exists then `git update-ref` will append
+If config parameter "core.logAllRefUpdates" is true and the ref is one under
+"refs/heads/", "refs/remotes/", "refs/notes/", or the symbolic ref HEAD; or
+the file "$GIT_DIR/logs/<ref>" exists then `git update-ref` will append
 a line to the log file "$GIT_DIR/logs/<ref>" (dereferencing all
 symbolic refs before creating the log name) describing the change
 in ref value.  Log lines are formatted as:
index 775024da3ed6ed50e8aa587dc31eb79f00030e84..bd0e36492fa0f7b8a8a4707c2ac7db461fcc74c8 100644 (file)
@@ -8,6 +8,7 @@ git-update-server-info - Update auxiliary info file to help dumb servers
 
 SYNOPSIS
 --------
+[verse]
 'git update-server-info' [--force]
 
 DESCRIPTION
index acbf634f85c72d70bbb7dd7653aded63d67dcbf6..4d52d3833aeaa8621f486bc99dd2114d53708e61 100644 (file)
@@ -8,6 +8,7 @@ git-upload-archive - Send archive back to git-archive
 
 SYNOPSIS
 --------
+[verse]
 'git upload-archive' <directory>
 
 DESCRIPTION
index 4c0ca9ded25a27c11636ef9af5f7c1f2e6970c12..a58e90ca8dada4a9847886374968635ea6bc3f9f 100644 (file)
@@ -8,6 +8,7 @@ git-upload-pack - Send objects packed back to git-fetch-pack
 
 SYNOPSIS
 --------
+[verse]
 'git-upload-pack' [--strict] [--timeout=<n>] <directory>
 
 DESCRIPTION
index 6498f7cb69be3d3fcece285a714679ac7f4f6454..5317cc247454b1a080b2609139befeba487d5ff5 100644 (file)
@@ -8,6 +8,7 @@ git-var - Show a git logical variable
 
 SYNOPSIS
 --------
+[verse]
 'git var' ( -l | <variable> )
 
 DESCRIPTION
index 7c2428d5692ce7e3961821c865c9539c30dca113..cd230769fdc6db2575d274d2a64608fe414c0d2e 100644 (file)
@@ -8,6 +8,7 @@ git-verify-pack - Validate packed git archive files
 
 SYNOPSIS
 --------
+[verse]
 'git verify-pack' [-v|--verbose] [-s|--stat-only] [--] <pack>.idx ...
 
 
index 8c9a71865b45120700c21a52d1e06aad45f3221f..5ff76e892aed19ff7943848edbf32c772b845d3d 100644 (file)
@@ -7,6 +7,7 @@ git-verify-tag - Check the GPG signature of tags
 
 SYNOPSIS
 --------
+[verse]
 'git verify-tag' <tag>...
 
 DESCRIPTION
index 9b0d1fe395df42d18ee47bb2c1c2a207639c85b8..c2bc87bc61da28a9eb451ef1cb5b4d811b02e4f7 100644 (file)
@@ -7,6 +7,7 @@ git-web--browse - git helper script to launch a web browser
 
 SYNOPSIS
 --------
+[verse]
 'git web{litdd}browse' [OPTIONS] URL/FILE ...
 
 DESCRIPTION
index 31f3663ae7fe2cc97d6e61b85181a02424323fb2..76c7f7eec5bb8ba01262762909939070b55ef5c9 100644 (file)
@@ -8,6 +8,7 @@ git-whatchanged - Show logs with difference each commit introduces
 
 SYNOPSIS
 --------
+[verse]
 'git whatchanged' <option>...
 
 DESCRIPTION
@@ -52,12 +53,12 @@ include::pretty-formats.txt[]
 
 Examples
 --------
-git whatchanged -p v2.6.12.. include/scsi drivers/scsi::
+`git whatchanged -p v2.6.12.. include/scsi drivers/scsi`::
 
        Show as patches the commits since version 'v2.6.12' that changed
        any file in the include/scsi or drivers/scsi subdirectories
 
-git whatchanged --since="2 weeks ago" \-- gitk::
+`git whatchanged --since="2 weeks ago" \-- gitk`::
 
        Show the changes during the last two weeks to the file 'gitk'.
        The "--" is necessary to avoid confusion with the *branch* named
index e8c94c1352a8f1a889225ee063b4c59799cbb7e6..f22041a9dc3965b4a4f704e84ec7700a5993d5c6 100644 (file)
@@ -8,6 +8,7 @@ git-write-tree - Create a tree object from the current index
 
 SYNOPSIS
 --------
+[verse]
 'git write-tree' [--missing-ok] [--prefix=<prefix>/]
 
 DESCRIPTION
index 412c55b549354471a56a4e56ca5533277c83bc54..2bbe76b5d88e4a38f22bdaef8612a48ddf1fe8ba 100644 (file)
@@ -79,7 +79,7 @@ Attributes for all users on a system should be placed in the
 `$(prefix)/etc/gitattributes` file.
 
 Sometimes you would need to override an setting of an attribute
-for a path to `unspecified` state.  This can be done by listing
+for a path to `Unspecified` state.  This can be done by listing
 the name of the attribute prefixed with an exclamation point `!`.
 
 
@@ -868,7 +868,7 @@ If this attribute is not set or has an invalid value, the value of the
 (See linkgit:git-config[1]).
 
 
-USING ATTRIBUTE MACROS
+USING MACRO ATTRIBUTES
 ----------------------
 
 You do not want any end-of-line conversions applied to, nor textual diffs
@@ -879,24 +879,27 @@ produced for, any binary file you track.  You would need to specify e.g.
 ------------
 
 but that may become cumbersome, when you have many attributes.  Using
-attribute macros, you can specify groups of attributes set or unset at
-the same time.  The system knows a built-in attribute macro, `binary`:
+macro attributes, you can define an attribute that, when set, also
+sets or unsets a number of other attributes at the same time.  The
+system knows a built-in macro attribute, `binary`:
 
 ------------
 *.jpg binary
 ------------
 
-which is equivalent to the above.  Note that the attribute macros can only
-be "Set" (see the above example that sets "binary" macro as if it were an
-ordinary attribute --- setting it in turn unsets "text" and "diff").
+Setting the "binary" attribute also unsets the "text" and "diff"
+attributes as above.  Note that macro attributes can only be "Set",
+though setting one might have the effect of setting or unsetting other
+attributes or even returning other attributes to the "Unspecified"
+state.
 
 
-DEFINING ATTRIBUTE MACROS
+DEFINING MACRO ATTRIBUTES
 -------------------------
 
-Custom attribute macros can be defined only in the `.gitattributes` file
-at the toplevel (i.e. not in any subdirectory).  The built-in attribute
-macro "binary" is equivalent to:
+Custom macro attributes can be defined only in the `.gitattributes`
+file at the toplevel (i.e. not in any subdirectory).  The built-in
+macro attribute "binary" is equivalent to:
 
 ------------
 [attr]binary -diff -text
index d861ec452f8f115017830422b4b459861f8bd703..aeb0cdc9732593672a4a53a3c177f40f07a86a37 100644 (file)
@@ -7,7 +7,8 @@ gitcvs-migration - git for CVS users
 
 SYNOPSIS
 --------
-git cvsimport *
+[verse]
+'git cvsimport' *
 
 DESCRIPTION
 -----------
index 6af29a4603de57e0040c4bcd819b831dd6649f92..370624c17174ddc67d4d29fd54127096f4f5b070 100644 (file)
@@ -7,6 +7,7 @@ gitdiffcore - Tweaking diff output
 
 SYNOPSIS
 --------
+[verse]
 'git diff' *
 
 DESCRIPTION
index e10ac58cae4f0a825f391a5fa1eab8114aa27a18..a17a3549363ec2813eb0bc8a3087d0bd9dc032f4 100644 (file)
@@ -7,6 +7,7 @@ gitk - The git repository browser
 
 SYNOPSIS
 --------
+[verse]
 'gitk' [<option>...] [<revs>] [--] [<path>...]
 
 DESCRIPTION
index 7fe5848d1f7ef77748448c03c4b2b2b33d82f03c..f1e4422acc4ddba515da5617759f818b52cb151d 100644 (file)
@@ -7,6 +7,7 @@ gittutorial-2 - A tutorial introduction to git: part two
 
 SYNOPSIS
 --------
+[verse]
 git *
 
 DESCRIPTION
index 0982f74ef6212577afb74d86079472662e2bffba..dee050567e65301066629c566613b84c6c065169 100644 (file)
@@ -7,6 +7,7 @@ gittutorial - A tutorial introduction to git (for version 1.5.1 or newer)
 
 SYNOPSIS
 --------
+[verse]
 git *
 
 DESCRIPTION
index 1ef55fffcf6815a12a1f9845809592104e208092..5e4f362ff8073bc5fc5f651f5219834d6173517b 100644 (file)
@@ -7,6 +7,7 @@ gitworkflows - An overview of recommended workflows with git
 
 SYNOPSIS
 --------
+[verse]
 git *
 
 
index 554ab8c88bdef6bb64ba9496295b563083657077..39e62072691d408519ff377cb6e91e8d95175ec4 100644 (file)
@@ -272,7 +272,7 @@ Default mode::
 
 --full-history::
 
-       As the default mode but does not prune some history.
+       Same as the default mode, but does not prune some history.
 
 --dense::
 
index 5cb2b0590abb1fc4e4685097ba3cdd3d0683a95f..b0cafe87bee046dc9b2d4e61e0d057e787a6f1f6 100644 (file)
@@ -49,6 +49,8 @@ Additionally, if `foo` is a new command, there are 3 more things to do:
 
 . Add an entry for `git-foo` to `command-list.txt`.
 
+. Add an entry for `/git-foo` to `.gitignore`.
+
 
 How a built-in is called
 ------------------------
index 7b233ca19676c2f89b1fb0231d7085e70c7eaaf6..8930b3fabceebfc7e03ddabdf5f7bfb228babf6b 100644 (file)
@@ -147,8 +147,9 @@ GIT index format
   - 160-bit object name for the object that would result from writing
     this span of index as a tree.
 
-  An entry can be in an invalidated state and is represented by having -1
-  in the entry_count field.
+  An entry can be in an invalidated state and is represented by having
+  -1 in the entry_count field. In this case, there is no object name
+  and the next entry starts immediately after the newline.
 
   The entries are written out in the top-down, depth-first order.  The
   first entry represents the root level of the repository, followed by the
index 01858eb7bca277a125c414ef4bf1904fd0ea9059..37287f86c18f8b532feb38b5c70541c8cb3d3a44 100644 (file)
--- a/abspath.c
+++ b/abspath.c
@@ -102,7 +102,8 @@ static const char *get_pwd_cwd(void)
        pwd = getenv("PWD");
        if (pwd && strcmp(pwd, cwd)) {
                stat(cwd, &cwd_stat);
-               if (!stat(pwd, &pwd_stat) &&
+               if ((cwd_stat.st_dev || cwd_stat.st_ino) &&
+                   !stat(pwd, &pwd_stat) &&
                    pwd_stat.st_dev == cwd_stat.st_dev &&
                    pwd_stat.st_ino == cwd_stat.st_ino) {
                        strlcpy(cwd, pwd, PATH_MAX);
index f152adf9ab71287e02e9e85c0b84aae096e5bec7..d647a313036df65d928d028463564b5390756901 100644 (file)
@@ -716,10 +716,12 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
        unsigned char rev[20];
        int flag;
        memset(&old, 0, sizeof(old));
-       old.path = resolve_ref("HEAD", rev, 0, &flag);
+       old.path = xstrdup(resolve_ref("HEAD", rev, 0, &flag));
        old.commit = lookup_commit_reference_gently(rev, 1);
-       if (!(flag & REF_ISSYMREF))
+       if (!(flag & REF_ISSYMREF)) {
+               free((char *)old.path);
                old.path = NULL;
+       }
 
        if (old.path && !prefixcmp(old.path, "refs/heads/"))
                old.name = old.path + strlen("refs/heads/");
@@ -742,6 +744,7 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
        update_refs_for_switch(opts, &old, new);
 
        ret = post_checkout_hook(old.commit, new->commit, 1);
+       free((char *)old.path);
        return ret || opts->writeout_error;
 }
 
index a15784a7b8406be3ead20839aab0f8de2cc52f3d..7663bc22c9a3cb35b803815762791fec44d4c477 100644 (file)
@@ -345,8 +345,9 @@ static void remove_junk_on_signal(int signo)
 static struct ref *wanted_peer_refs(const struct ref *refs,
                struct refspec *refspec)
 {
-       struct ref *local_refs = NULL;
-       struct ref **tail = &local_refs;
+       struct ref *head = copy_ref(find_ref_by_name(refs, "HEAD"));
+       struct ref *local_refs = head;
+       struct ref **tail = head ? &head->next : &local_refs;
 
        get_fetch_map(refs, refspec, &tail, 0);
        if (!option_mirror)
@@ -359,8 +360,11 @@ static void write_remote_refs(const struct ref *local_refs)
 {
        const struct ref *r;
 
-       for (r = local_refs; r; r = r->next)
+       for (r = local_refs; r; r = r->next) {
+               if (!r->peer_ref)
+                       continue;
                add_extra_ref(r->peer_ref->name, r->old_sha1, 0);
+       }
 
        pack_refs(PACK_REFS_ALL);
        clear_extra_refs();
index daf19451ba7df541d1314c880679749232ccce35..becef8578283ea0a8620041ce7e974baf7b6e27d 100644 (file)
@@ -26,6 +26,7 @@ static int progress;
 static enum { ABORT, VERBATIM, WARN, STRIP } signed_tag_mode = ABORT;
 static enum { ERROR, DROP, REWRITE } tag_of_filtered_mode = ABORT;
 static int fake_missing_tagger;
+static int use_done_feature;
 static int no_data;
 static int full_tree;
 
@@ -627,6 +628,8 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
                             "Fake a tagger when tags lack one"),
                OPT_BOOLEAN(0, "full-tree", &full_tree,
                             "Output full tree for each commit"),
+               OPT_BOOLEAN(0, "use-done-feature", &use_done_feature,
+                            "Use the done feature to terminate the stream"),
                { OPTION_NEGBIT, 0, "data", &no_data, NULL,
                        "Skip output of blob data",
                        PARSE_OPT_NOARG | PARSE_OPT_NEGHELP, NULL, 1 },
@@ -648,6 +651,9 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
        if (argc > 1)
                usage_with_options (fast_export_usage, options);
 
+       if (use_done_feature)
+               printf("feature done\n");
+
        if (import_filename)
                import_marks(import_filename);
 
@@ -675,5 +681,8 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
        if (export_filename)
                export_marks(export_filename);
 
+       if (use_done_feature)
+               printf("done\n");
+
        return 0;
 }
index 84e6dafb12657a6f0431f2a287d0cca976269c35..27f24d3aafbee239301628a2649dca83fcd12081 100644 (file)
@@ -51,6 +51,8 @@ struct object_entry {
                                       * objects against.
                                       */
        unsigned char no_try_delta;
+       unsigned char tagged; /* near the very tip of refs */
+       unsigned char filled; /* assigned write-order */
 };
 
 /*
@@ -96,6 +98,7 @@ static unsigned long window_memory_limit = 0;
  */
 static int *object_ix;
 static int object_ix_hashsz;
+static struct object_entry *locate_object_entry(const unsigned char *sha1);
 
 /*
  * stats
@@ -200,6 +203,7 @@ static void copy_pack_data(struct sha1file *f,
        }
 }
 
+/* Return 0 if we will bust the pack-size limit */
 static unsigned long write_object(struct sha1file *f,
                                  struct object_entry *entry,
                                  off_t write_offset)
@@ -434,6 +438,134 @@ static int write_one(struct sha1file *f,
        return 1;
 }
 
+static int mark_tagged(const char *path, const unsigned char *sha1, int flag,
+                      void *cb_data)
+{
+       unsigned char peeled[20];
+       struct object_entry *entry = locate_object_entry(sha1);
+
+       if (entry)
+               entry->tagged = 1;
+       if (!peel_ref(path, peeled)) {
+               entry = locate_object_entry(peeled);
+               if (entry)
+                       entry->tagged = 1;
+       }
+       return 0;
+}
+
+static void add_to_write_order(struct object_entry **wo,
+                              int *endp,
+                              struct object_entry *e)
+{
+       if (e->filled)
+               return;
+       wo[(*endp)++] = e;
+       e->filled = 1;
+}
+
+static void add_descendants_to_write_order(struct object_entry **wo,
+                                          int *endp,
+                                          struct object_entry *e)
+{
+       struct object_entry *child;
+
+       for (child = e->delta_child; child; child = child->delta_sibling)
+               add_to_write_order(wo, endp, child);
+       for (child = e->delta_child; child; child = child->delta_sibling)
+               add_descendants_to_write_order(wo, endp, child);
+}
+
+static void add_family_to_write_order(struct object_entry **wo,
+                                     int *endp,
+                                     struct object_entry *e)
+{
+       struct object_entry *root;
+
+       for (root = e; root->delta; root = root->delta)
+               ; /* nothing */
+       add_to_write_order(wo, endp, root);
+       add_descendants_to_write_order(wo, endp, root);
+}
+
+static struct object_entry **compute_write_order(void)
+{
+       int i, wo_end;
+
+       struct object_entry **wo = xmalloc(nr_objects * sizeof(*wo));
+
+       for (i = 0; i < nr_objects; i++) {
+               objects[i].tagged = 0;
+               objects[i].filled = 0;
+               objects[i].delta_child = NULL;
+               objects[i].delta_sibling = NULL;
+       }
+
+       /*
+        * Fully connect delta_child/delta_sibling network.
+        * Make sure delta_sibling is sorted in the original
+        * recency order.
+        */
+       for (i = nr_objects - 1; 0 <= i; i--) {
+               struct object_entry *e = &objects[i];
+               if (!e->delta)
+                       continue;
+               /* Mark me as the first child */
+               e->delta_sibling = e->delta->delta_child;
+               e->delta->delta_child = e;
+       }
+
+       /*
+        * Mark objects that are at the tip of tags.
+        */
+       for_each_tag_ref(mark_tagged, NULL);
+
+       /*
+        * Give the commits in the original recency order until
+        * we see a tagged tip.
+        */
+       for (i = wo_end = 0; i < nr_objects; i++) {
+               if (objects[i].tagged)
+                       break;
+               add_to_write_order(wo, &wo_end, &objects[i]);
+       }
+
+       /*
+        * Then fill all the tagged tips.
+        */
+       for (; i < nr_objects; i++) {
+               if (objects[i].tagged)
+                       add_to_write_order(wo, &wo_end, &objects[i]);
+       }
+
+       /*
+        * And then all remaining commits and tags.
+        */
+       for (i = 0; i < nr_objects; i++) {
+               if (objects[i].type != OBJ_COMMIT &&
+                   objects[i].type != OBJ_TAG)
+                       continue;
+               add_to_write_order(wo, &wo_end, &objects[i]);
+       }
+
+       /*
+        * And then all the trees.
+        */
+       for (i = 0; i < nr_objects; i++) {
+               if (objects[i].type != OBJ_TREE)
+                       continue;
+               add_to_write_order(wo, &wo_end, &objects[i]);
+       }
+
+       /*
+        * Finally all the rest in really tight order
+        */
+       for (i = 0; i < nr_objects; i++)
+               add_family_to_write_order(wo, &wo_end, &objects[i]);
+
+       return wo;
+}
+
 static void write_pack_file(void)
 {
        uint32_t i = 0, j;
@@ -442,10 +574,12 @@ static void write_pack_file(void)
        struct pack_header hdr;
        uint32_t nr_remaining = nr_result;
        time_t last_mtime = 0;
+       struct object_entry **write_order;
 
        if (progress > pack_to_stdout)
                progress_state = start_progress("Writing objects", nr_result);
        written_list = xmalloc(nr_objects * sizeof(*written_list));
+       write_order = compute_write_order();
 
        do {
                unsigned char sha1[20];
@@ -469,7 +603,8 @@ static void write_pack_file(void)
                offset = sizeof(hdr);
                nr_written = 0;
                for (; i < nr_objects; i++) {
-                       if (!write_one(f, objects + i, &offset))
+                       struct object_entry *e = write_order[i];
+                       if (!write_one(f, e, &offset))
                                break;
                        display_progress(progress_state, written);
                }
@@ -546,6 +681,7 @@ static void write_pack_file(void)
        } while (nr_remaining && i < nr_objects);
 
        free(written_list);
+       free(write_order);
        stop_progress(&progress_state);
        if (written != nr_result)
                die("wrote %"PRIu32" objects while expecting %"PRIu32,
index 98bca044c1267fa63cb084a45aaf621e85f7d9b6..777e7c612900f867c5a52723ebdd56c9db793489 100644 (file)
@@ -162,7 +162,7 @@ static void update_index_from_diff(struct diff_queue_struct *q,
 
        for (i = 0; i < q->nr; i++) {
                struct diff_filespec *one = q->queue[i]->one;
-               if (one->mode) {
+               if (one->mode && !is_null_sha1(one->sha1)) {
                        struct cache_entry *ce;
                        ce = make_cache_entry(one->mode, one->sha1, one->path,
                                0, 0);
index cef27263bc79e519398ae5eb0a49d78f3b389090..667515e5278d22548fb83507347ab652533a67b2 100644 (file)
@@ -12,6 +12,8 @@
 #include "tag.h"
 #include "run-command.h"
 #include "parse-options.h"
+#include "diff.h"
+#include "revision.h"
 
 static const char * const git_tag_usage[] = {
        "git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]",
@@ -40,6 +42,48 @@ static int match_pattern(const char **patterns, const char *ref)
        return 0;
 }
 
+static int in_commit_list(const struct commit_list *want, struct commit *c)
+{
+       for (; want; want = want->next)
+               if (!hashcmp(want->item->object.sha1, c->object.sha1))
+                       return 1;
+       return 0;
+}
+
+static int contains_recurse(struct commit *candidate,
+                           const struct commit_list *want)
+{
+       struct commit_list *p;
+
+       /* was it previously marked as containing a want commit? */
+       if (candidate->object.flags & TMP_MARK)
+               return 1;
+       /* or marked as not possibly containing a want commit? */
+       if (candidate->object.flags & UNINTERESTING)
+               return 0;
+       /* or are we it? */
+       if (in_commit_list(want, candidate))
+               return 1;
+
+       if (parse_commit(candidate) < 0)
+               return 0;
+
+       /* Otherwise recurse and mark ourselves for future traversals. */
+       for (p = candidate->parents; p; p = p->next) {
+               if (contains_recurse(p->item, want)) {
+                       candidate->object.flags |= TMP_MARK;
+                       return 1;
+               }
+       }
+       candidate->object.flags |= UNINTERESTING;
+       return 0;
+}
+
+static int contains(struct commit *candidate, const struct commit_list *want)
+{
+       return contains_recurse(candidate, want);
+}
+
 static int show_reference(const char *refname, const unsigned char *sha1,
                          int flag, void *cb_data)
 {
@@ -58,7 +102,7 @@ static int show_reference(const char *refname, const unsigned char *sha1,
                        commit = lookup_commit_reference_gently(sha1, 1);
                        if (!commit)
                                return 0;
-                       if (!is_descendant_of(commit, filter->with_commit))
+                       if (!contains(commit, filter->with_commit))
                                return 0;
                }
 
diff --git a/cache.h b/cache.h
index 9e12d55470435102215f2dd99eb3432856612dbd..f49eaf92638340425f6bbd8f659bb779865a69a0 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -773,6 +773,9 @@ extern int parse_sha1_header(const char *hdr, unsigned long *sizep);
 /* global flag to enable extra checks when accessing packed objects */
 extern int do_check_packed_object_crc;
 
+/* for development: log offset of pack access */
+extern const char *log_pack_access;
+
 extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned long size, const char *type);
 
 extern int move_temp_to_file(const char *tmpfile, const char *filename);
index 6b61a849d26c7a35f57d74c9d5f0adbb1f85c72d..4183f80262ea9f24e286295a2295f93459548b78 100644 (file)
--- a/config.c
+++ b/config.c
@@ -576,6 +576,9 @@ static int git_default_core_config(const char *var, const char *value)
                return 0;
        }
 
+       if (!strcmp(var, "core.logpackaccess"))
+               return git_config_string(&log_pack_access, var, value);
+
        if (!strcmp(var, "core.autocrlf")) {
                if (value && !strcasecmp(value, "input")) {
                        if (core_eol == EOL_CRLF)
@@ -1499,10 +1502,10 @@ int git_config_rename_section(const char *old_name, const char *new_name)
                }
        }
        fclose(config_file);
- unlock_and_out:
+unlock_and_out:
        if (commit_lock_file(lock) < 0)
                ret = error("could not commit config file %s", config_filename);
- out:
+out:
        free(config_filename);
        return ret;
 }
index 2119c3f74edcd2a976ff0e375c5d8d60d40da2ec..d2ce57f850fa6d0a6de04f6f714dec487ff9f1ed 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -192,7 +192,8 @@ static const char *ai_name(const struct addrinfo *ai)
  */
 static int git_tcp_connect_sock(char *host, int flags)
 {
-       int sockfd = -1, saved_errno = 0;
+       struct strbuf error_message = STRBUF_INIT;
+       int sockfd = -1;
        const char *port = STR(DEFAULT_GIT_PORT);
        struct addrinfo hints, *ai0, *ai;
        int gai;
@@ -216,21 +217,15 @@ static int git_tcp_connect_sock(char *host, int flags)
        if (flags & CONNECT_VERBOSE)
                fprintf(stderr, "done.\nConnecting to %s (port %s) ... ", host, port);
 
-       for (ai0 = ai; ai; ai = ai->ai_next) {
+       for (ai0 = ai; ai; ai = ai->ai_next, cnt++) {
                sockfd = socket(ai->ai_family,
                                ai->ai_socktype, ai->ai_protocol);
-               if (sockfd < 0) {
-                       saved_errno = errno;
-                       continue;
-               }
-               if (connect(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
-                       saved_errno = errno;
-                       fprintf(stderr, "%s[%d: %s]: errno=%s\n",
-                               host,
-                               cnt,
-                               ai_name(ai),
-                               strerror(saved_errno));
-                       close(sockfd);
+               if ((sockfd < 0) ||
+                   (connect(sockfd, ai->ai_addr, ai->ai_addrlen) < 0)) {
+                       strbuf_addf(&error_message, "%s[%d: %s]: errno=%s\n",
+                                   host, cnt, ai_name(ai), strerror(errno));
+                       if (0 <= sockfd)
+                               close(sockfd);
                        sockfd = -1;
                        continue;
                }
@@ -242,11 +237,13 @@ static int git_tcp_connect_sock(char *host, int flags)
        freeaddrinfo(ai0);
 
        if (sockfd < 0)
-               die("unable to connect a socket (%s)", strerror(saved_errno));
+               die("unable to connect to %s:\n%s", host, error_message.buf);
 
        if (flags & CONNECT_VERBOSE)
                fprintf(stderr, "done.\n");
 
+       strbuf_release(&error_message);
+
        return sockfd;
 }
 
index 9718abf86d8cd36ddae1eae8cf2337e35b927959..0565d83fc42c3d689b34299b38f0d2a7a0ae4212 100644 (file)
@@ -8,6 +8,7 @@ git-convert-objects - Converts old-style git repository
 
 SYNOPSIS
 --------
+[verse]
 'git-convert-objects'
 
 DESCRIPTION
index 98d2aee67fc1f6bfdfc960527b6f0bf6acf5122a..6b9de9e7e0e3304d42048ff3680eac9270330ee4 100755 (executable)
@@ -1649,7 +1649,8 @@ class P4Sync(Command, P4UserMap):
     def importHeadRevision(self, revision):
         print "Doing initial import of %s from revision %s into %s" % (' '.join(self.depotPaths), revision, self.branch)
 
-        details = { "user" : "git perforce import user", "time" : int(time.time()) }
+        details = {}
+        details["user"] = "git perforce import user"
         details["desc"] = ("Initial import of %s from the state at revision %s\n"
                            % (' '.join(self.depotPaths), revision))
         details["change"] = revision
@@ -1689,6 +1690,18 @@ class P4Sync(Command, P4UserMap):
             fileCnt = fileCnt + 1
 
         details["change"] = newestRevision
+
+        # Use time from top-most change so that all git-p4 clones of
+        # the same p4 repo have the same commit SHA1s.
+        res = p4CmdList("describe -s %d" % newestRevision)
+        newestTime = None
+        for r in res:
+            if r.has_key('time'):
+                newestTime = int(r['time'])
+        if newestTime is None:
+            die("\"describe -s\" on newest change %d did not give a time")
+        details["time"] = newestTime
+
         self.updateOptionDict(details)
         try:
             self.commit(details, self.extractFilesFromCommit(details), self.branch, self.depotPaths)
index 77c29de305fabc518edf060b0e6634d9c5c9f71e..9e12f978425cbc45e5cd072b8bfb2fc57fae610b 100644 (file)
@@ -7,6 +7,7 @@ gitview - A GTK based repository browser for git
 
 SYNOPSIS
 --------
+[verse]
 'gitview' [options] [args]
 
 DESCRIPTION
index 21989fc6ab84c0503cdc9418673d9d0bf06f9d49..fa6d41a1ab8c5f3de777c1ba93d241eb5140a3c7 100755 (executable)
 #   email body. If not specified, there is no limit.
 #   Lines beyond the limit are suppressed and counted, and a final
 #   line is added indicating the number of suppressed lines.
+# hooks.diffopts
+#   Alternate options for the git diff-tree invocation that shows changes.
+#   Default is "--stat --summary --find-copies-harder". Add -p to those
+#   options to include a unified diff of changes in addition to the usual
+#   summary output.
 #
 # Notes
 # -----
@@ -446,7 +451,7 @@ generate_update_branch_email()
        # non-fast-forward updates.
        echo ""
        echo "Summary of changes:"
-       git diff-tree --stat --summary --find-copies-harder $oldrev..$newrev
+       git diff-tree $diffopts $oldrev..$newrev
 }
 
 #
@@ -723,6 +728,8 @@ envelopesender=$(git config hooks.envelopesender)
 emailprefix=$(git config hooks.emailprefix || echo '[SCM] ')
 custom_showrev=$(git config hooks.showrev)
 maxlines=$(git config hooks.emailmaxlines)
+diffopts=$(git config hooks.diffopts)
+: ${diffopts:="--stat --summary --find-copies-harder"}
 
 # --- Main loop
 # Allow dual mode: run from the command line just like the update hook, or
index cd075b96c54419fdaa25c56b24133dd080f440ca..72ffea0b3a6a29d69cb8c88989adc0692cd01f34 100644 (file)
@@ -7,6 +7,7 @@ svn-fe - convert an SVN "dumpfile" to a fast-import stream
 
 SYNOPSIS
 --------
+[verse]
 svnadmin dump --incremental REPO | svn-fe [url] | git fast-import
 
 DESCRIPTION
index 2e09500c8210e22d6c81484aa198f1d811a9933d..b3797592c63a86b46a3af0d875b6fe04ea43f536 100644 (file)
@@ -379,7 +379,8 @@ static void do_oneway_diff(struct unpack_trees_options *o,
        if (cached && idx && ce_stage(idx)) {
                struct diff_filepair *pair;
                pair = diff_unmerge(&revs->diffopt, idx->name);
-               fill_filespec(pair->one, idx->sha1, idx->ce_mode);
+               if (tree)
+                       fill_filespec(pair->one, tree->sha1, tree->ce_mode);
                return;
        }
 
index 94d58fd24413ec1d1a5769029bd5149b609f0d4e..19351024f5ef61ba0e5237aa039fc9e657ad81a0 100644 (file)
@@ -36,6 +36,7 @@ size_t packed_git_window_size = DEFAULT_PACKED_GIT_WINDOW_SIZE;
 size_t packed_git_limit = DEFAULT_PACKED_GIT_LIMIT;
 size_t delta_base_cache_limit = 16 * 1024 * 1024;
 unsigned long big_file_threshold = 512 * 1024 * 1024;
+const char *log_pack_access;
 const char *pager_program;
 int pager_use_color = 1;
 const char *editor_program;
index 9e8d1868aa3b178f4b61ef57430883854898b044..7cc22625e5b73d2778566a154bce94316311b0c8 100644 (file)
@@ -355,6 +355,7 @@ static unsigned int cmd_save = 100;
 static uintmax_t next_mark;
 static struct strbuf new_data = STRBUF_INIT;
 static int seen_data_command;
+static int require_explicit_termination;
 
 /* Signal handling */
 static volatile sig_atomic_t checkpoint_requested;
@@ -3140,6 +3141,8 @@ static int parse_one_feature(const char *feature, int from_stream)
                relative_marks_paths = 1;
        } else if (!strcmp(feature, "no-relative-marks")) {
                relative_marks_paths = 0;
+       } else if (!strcmp(feature, "done")) {
+               require_explicit_termination = 1;
        } else if (!strcmp(feature, "force")) {
                force_update = 1;
        } else if (!strcmp(feature, "notes") || !strcmp(feature, "ls")) {
@@ -3290,6 +3293,8 @@ int main(int argc, const char **argv)
                        parse_reset_branch();
                else if (!strcmp("checkpoint", command_buf.buf))
                        parse_checkpoint();
+               else if (!strcmp("done", command_buf.buf))
+                       break;
                else if (!prefixcmp(command_buf.buf, "progress "))
                        parse_progress();
                else if (!prefixcmp(command_buf.buf, "feature "))
@@ -3309,6 +3314,9 @@ int main(int argc, const char **argv)
        if (!seen_data_command)
                parse_argv();
 
+       if (require_explicit_termination && feof(stdin))
+               die("stream ends early");
+
        end_packfile();
 
        dump_branches();
index 3aab5aae844b963fc4178675a56da20e02488dfd..3c157bcd26232c758572bf908add44216cb8e2e7 100755 (executable)
@@ -100,7 +100,7 @@ resolve_deleted_merge () {
        else
            printf "Use (c)reated or (d)eleted file, or (a)bort? "
        fi
-       read ans
+       read ans || return 1
        case "$ans" in
            [mMcC]*)
                git add -- "$MERGED"
@@ -122,7 +122,7 @@ resolve_deleted_merge () {
 resolve_submodule_merge () {
     while true; do
        printf "Use (l)ocal or (r)emote, or (a)bort? "
-       read ans
+       read ans || return 1
        case "$ans" in
            [lL]*)
                if ! local_present; then
@@ -249,7 +249,7 @@ merge_file () {
     describe_file "$remote_mode" "remote" "$REMOTE"
     if "$prompt" = true; then
        printf "Hit return to start merge resolution tool (%s): " "$merge_tool"
-       read ans
+       read ans || return 1
     fi
 
     if base_present; then
@@ -320,7 +320,7 @@ done
 prompt_after_failed_merge() {
     while true; do
        printf "Continue merging other unresolved paths (y/n) ? "
-       read ans
+       read ans || return 1
        case "$ans" in
 
            [yY]*)
index 4761f288906a53f0336161142ddcf7799a38c4b8..266a4c13bb3607ad635df19bf6dd80f205effae2 100755 (executable)
@@ -13,7 +13,7 @@ It then attempts to create a new commit for each commit from the original
 It is possible that a merge failure will prevent this process from being
 completely automatic.  You will have to resolve any such merge failure
 and run git rebase --continue.  Another option is to bypass the commit
-that caused the merge failure with git rebase --skip.  To restore the
+that caused the merge failure with git rebase --skip.  To check out the
 original <branch> and remove the .git/rebase-apply working files, use the
 command git rebase --abort instead.
 
@@ -57,9 +57,9 @@ whitespace=!       passed to 'git apply'
 ignore-whitespace! passed to 'git apply'
 C=!                passed to 'git apply'
  Actions:
-continue!          continue rebasing process
-abort!             abort rebasing process and restore original branch
-skip!              skip current patch and continue rebasing process
+continue!          continue
+abort!             abort and check out the original branch
+skip!              skip current patch and continue
 "
 . git-sh-setup
 set_reflog_action rebase
@@ -72,7 +72,7 @@ ok_to_skip_pre_rebase=
 resolvemsg="
 When you have resolved this problem run \"git rebase --continue\".
 If you would prefer to skip this patch, instead run \"git rebase --skip\".
-To restore the original branch and stop rebasing run \"git rebase --abort\".
+To check out the original branch and stop rebasing run \"git rebase --abort\".
 "
 unset onto
 strategy=
index df9d512f1a966635828cb7a8dadde3b0c2b7b9d8..e9c832bfd3da7db771cc2113027d3e590dc51d59 100644 (file)
@@ -35,7 +35,7 @@ def get_repo(alias, url):
     prefix = 'refs/testgit/%s/' % alias
     debug("prefix: '%s'", prefix)
 
-    repo.gitdir = ""
+    repo.gitdir = os.environ["GIT_DIR"]
     repo.alias = alias
     repo.prefix = prefix
 
@@ -70,9 +70,19 @@ def do_capabilities(repo, args):
 
     print "import"
     print "export"
-    print "gitdir"
     print "refspec refs/heads/*:%s*" % repo.prefix
 
+    dirname = repo.get_base_path(repo.gitdir)
+
+    if not os.path.exists(dirname):
+        os.makedirs(dirname)
+
+    path = os.path.join(dirname, 'testgit.marks')
+
+    print "*export-marks %s" % path
+    if os.path.exists(path):
+        print "*import-marks %s" % path
+
     print # end capabilities
 
 
@@ -121,8 +131,24 @@ def do_import(repo, args):
     if not repo.gitdir:
         die("Need gitdir to import")
 
+    ref = args[0]
+    refs = [ref]
+
+    while True:
+        line = sys.stdin.readline()
+        if line == '\n':
+            break
+        if not line.startswith('import '):
+            die("Expected import line.")
+
+        # strip of leading 'import '
+        ref = line[7:].strip()
+        refs.append(ref)
+
     repo = update_local_repo(repo)
-    repo.exporter.export_repo(repo.gitdir)
+    repo.exporter.export_repo(repo.gitdir, refs)
+
+    print "done"
 
 
 def do_export(repo, args):
@@ -132,32 +158,15 @@ def do_export(repo, args):
     if not repo.gitdir:
         die("Need gitdir to export")
 
-    dirname = repo.get_base_path(repo.gitdir)
-
-    if not os.path.exists(dirname):
-        os.makedirs(dirname)
-
-    path = os.path.join(dirname, 'testgit.marks')
-    print path
-    if os.path.exists(path):
-        print path
-    else:
-        print ""
-    sys.stdout.flush()
-
     update_local_repo(repo)
-    repo.importer.do_import(repo.gitdir)
-    repo.non_local.push(repo.gitdir)
-
-
-def do_gitdir(repo, args):
-    """Stores the location of the gitdir.
-    """
+    changed = repo.importer.do_import(repo.gitdir)
 
-    if not args:
-        die("gitdir needs an argument")
+    if not repo.local:
+        repo.non_local.push(repo.gitdir)
 
-    repo.gitdir = ' '.join(args)
+    for ref in changed:
+        print "ok %s" % ref
+    print
 
 
 COMMANDS = {
@@ -165,7 +174,6 @@ def do_gitdir(repo, args):
     'list': do_list,
     'import': do_import,
     'export': do_export,
-    'gitdir': do_gitdir,
 }
 
 
index 5619da5c10f968a7eaeeaafc497ed03e763c9439..f4e6f05ee212f452a1b3e13c492960a9222029f7 100755 (executable)
@@ -7,7 +7,8 @@ USAGE="list [<options>]
    or: $dashless drop [-q|--quiet] [<stash>]
    or: $dashless ( pop | apply ) [--index] [-q|--quiet] [<stash>]
    or: $dashless branch <branchname> [<stash>]
-   or: $dashless [save [--patch] [-k|--[no-]keep-index] [-q|--quiet] [<message>]]
+   or: $dashless [save [--patch] [-k|--[no-]keep-index] [-q|--quiet]
+                      [-u|--include-untracked] [-a|--all] [<message>]]
    or: $dashless clear"
 
 SUBDIRECTORY_OK=Yes
@@ -34,7 +35,14 @@ fi
 
 no_changes () {
        git diff-index --quiet --cached HEAD --ignore-submodules -- &&
-       git diff-files --quiet --ignore-submodules
+       git diff-files --quiet --ignore-submodules &&
+       (test -z "$untracked" || test -z "$(untracked_files)")
+}
+
+untracked_files () {
+       excl_opt=--exclude-standard
+       test "$untracked" = "all" && excl_opt=
+       git ls-files -o -z $excl_opt
 }
 
 clear_stash () {
@@ -50,6 +58,7 @@ clear_stash () {
 
 create_stash () {
        stash_msg="$1"
+       untracked="$2"
 
        git update-index -q --refresh
        if no_changes
@@ -79,6 +88,25 @@ create_stash () {
                git commit-tree $i_tree -p $b_commit) ||
                die "$(gettext "Cannot save the current index state")"
 
+       if test -n "$untracked"
+       then
+               # Untracked files are stored by themselves in a parentless commit, for
+               # ease of unpacking later.
+               u_commit=$(
+                       untracked_files | (
+                               export GIT_INDEX_FILE="$TMPindex"
+                               rm -f "$TMPindex" &&
+                               git update-index -z --add --remove --stdin &&
+                               u_tree=$(git write-tree) &&
+                               printf 'untracked files on %s\n' "$msg" | git commit-tree $u_tree  &&
+                               rm -f "$TMPindex"
+               ) ) || die "Cannot save the untracked files"
+
+               untracked_commit_option="-p $u_commit";
+       else
+               untracked_commit_option=
+       fi
+
        if test -z "$patch_mode"
        then
 
@@ -123,13 +151,14 @@ create_stash () {
                stash_msg=$(printf 'On %s: %s' "$branch" "$stash_msg")
        fi
        w_commit=$(printf '%s\n' "$stash_msg" |
-               git commit-tree $w_tree -p $b_commit -p $i_commit) ||
-               die "$(gettext "Cannot record working tree state")"
+       git commit-tree $w_tree -p $b_commit -p $i_commit $untracked_commit_option) ||
+       die "$(gettext "Cannot record working tree state")"
 }
 
 save_stash () {
        keep_index=
        patch_mode=
+       untracked=
        while test $# != 0
        do
                case "$1" in
@@ -147,6 +176,12 @@ save_stash () {
                -q|--quiet)
                        GIT_QUIET=t
                        ;;
+               -u|--include-untracked)
+                       untracked=untracked
+                       ;;
+               -a|--all)
+                       untracked=all
+                       ;;
                --)
                        shift
                        break
@@ -174,6 +209,11 @@ save_stash () {
                shift
        done
 
+       if test -n "$patch_mode" && test -n "$untracked"
+       then
+           die "Can't use --patch and ---include-untracked or --all at the same time"
+       fi
+
        stash_msg="$*"
 
        git update-index -q --refresh
@@ -185,7 +225,7 @@ save_stash () {
        test -f "$GIT_DIR/logs/$ref_stash" ||
                clear_stash || die "$(gettext "Cannot initialize stash")"
 
-       create_stash "$stash_msg"
+       create_stash "$stash_msg" $untracked
 
        # Make sure the reflog for stash is kept.
        : >>"$GIT_DIR/logs/$ref_stash"
@@ -197,6 +237,11 @@ save_stash () {
        if test -z "$patch_mode"
        then
                git reset --hard ${GIT_QUIET:+-q}
+               test "$untracked" = "all" && CLEAN_X_OPTION=-x || CLEAN_X_OPTION=
+               if test -n "$untracked"
+               then
+                       git clean --force --quiet $CLEAN_X_OPTION
+               fi
 
                if test "$keep_index" = "t" && test -n $i_tree
                then
@@ -246,9 +291,11 @@ show_stash () {
 #   w_commit is set to the commit containing the working tree
 #   b_commit is set to the base commit
 #   i_commit is set to the commit containing the index tree
+#   u_commit is set to the commit containing the untracked files tree
 #   w_tree is set to the working tree
 #   b_tree is set to the base tree
 #   i_tree is set to the index tree
+#   u_tree is set to the untracked files tree
 #
 #   GIT_QUIET is set to t if -q is specified
 #   INDEX_OPTION is set to --index if --index is specified.
@@ -273,9 +320,11 @@ parse_flags_and_rev()
        w_commit=
        b_commit=
        i_commit=
+       u_commit=
        w_tree=
        b_tree=
        i_tree=
+       u_tree=
 
        REV=$(git rev-parse --no-flags --symbolic "$@") || exit 1
 
@@ -326,6 +375,9 @@ parse_flags_and_rev()
        IS_STASH_LIKE=t &&
        test "$ref_stash" = "$(git rev-parse --symbolic-full-name "${REV%@*}")" &&
        IS_STASH_REF=t
+
+       u_commit=$(git rev-parse --quiet --verify $REV^3 2>/dev/null) &&
+       u_tree=$(git rev-parse $REV^3: 2>/dev/null)
 }
 
 is_stash_like()
@@ -374,6 +426,14 @@ apply_stash () {
                git reset
        fi
 
+       if test -n "$u_tree"
+       then
+               GIT_INDEX_FILE="$TMPindex" git-read-tree "$u_tree" &&
+               GIT_INDEX_FILE="$TMPindex" git checkout-index --all &&
+               rm -f "$TMPindex" ||
+               die 'Could not restore untracked files from stash'
+       fi
+
        eval "
                GITHEAD_$w_tree='Stashed changes' &&
                GITHEAD_$c_tree='Updated upstream' &&
index 3daa0c834cad1ed402376adf535c73e1c06172e4..bc1d3fa663a5eb39dd96f6ad2ca17437073ceb0a 100755 (executable)
@@ -35,7 +35,7 @@ resolve_relative_url ()
 {
        remote=$(get_default_remote)
        remoteurl=$(git config "remote.$remote.url") ||
-               die "$(eval_gettext "remote (\$remote) does not have a url defined in .git/config")"
+               remoteurl=$(pwd) # the repository is its own authoritative upstream
        url="$1"
        remoteurl=${remoteurl%/}
        sep=/
@@ -242,14 +242,6 @@ Use -f if you really want to add it." &&
                        die "$(eval_gettext "'\$path' already exists and is not a valid git repo")"
                fi
 
-               case "$repo" in
-               ./*|../*)
-                       url=$(resolve_relative_url "$repo") || exit
-                   ;;
-               *)
-                       url="$repo"
-                       ;;
-               esac
        else
 
                module_clone "$path" "$realrepo" "$reference" || exit
@@ -263,7 +255,7 @@ Use -f if you really want to add it." &&
                        esac
                ) || die "$(eval_gettext "Unable to checkout submodule '\$path'")"
        fi
-       git config submodule."$path".url "$url"
+       git config submodule."$path".url "$realrepo"
 
        git add $force "$path" ||
        die "$(eval_gettext "Failed to add submodule '\$path'")"
index f40f9d6a29cda39ee7f989e11ef66cdf3d54d625..9ee5f96d4ce313f4f94505ff65b560943bfd21cb 100644 (file)
@@ -2,6 +2,8 @@
 import subprocess
 import sys
 
+from git_remote_helpers.util import check_call
+
 
 class GitExporter(object):
     """An exporter for testgit repositories.
@@ -15,7 +17,7 @@ def __init__(self, repo):
 
         self.repo = repo
 
-    def export_repo(self, base):
+    def export_repo(self, base, refs=None):
         """Exports a fast-export stream for the given directory.
 
         Simply delegates to git fast-epxort and pipes it through sed
@@ -23,8 +25,13 @@ def export_repo(self, base):
         default refs/heads. This is to demonstrate how the export
         data can be stored under it's own ref (using the refspec
         capability).
+
+        If None, refs defaults to ["HEAD"].
         """
 
+        if not refs:
+            refs = ["HEAD"]
+
         dirname = self.repo.get_base_path(base)
         path = os.path.abspath(os.path.join(dirname, 'testgit.marks'))
 
@@ -42,12 +49,10 @@ def export_repo(self, base):
         if os.path.exists(path):
             args.append("--import-marks=" + path)
 
-        args.append("HEAD")
+        args.extend(refs)
 
         p1 = subprocess.Popen(args, stdout=subprocess.PIPE)
 
         args = ["sed", "s_refs/heads/_" + self.repo.prefix + "_g"]
 
-        child = subprocess.Popen(args, stdin=p1.stdout)
-        if child.wait() != 0:
-            raise CalledProcessError
+        check_call(args, stdin=p1.stdout)
index 70a712729b63047b9760b72d3e2b0a45ff176646..5c6b595e16665bc508625ab0e96c95776bacba1a 100644 (file)
@@ -1,6 +1,8 @@
 import os
 import subprocess
 
+from git_remote_helpers.util import check_call, check_output
+
 
 class GitImporter(object):
     """An importer for testgit repositories.
@@ -14,6 +16,18 @@ def __init__(self, repo):
 
         self.repo = repo
 
+    def get_refs(self, gitdir):
+        """Returns a dictionary with refs.
+        """
+        args = ["git", "--git-dir=" + gitdir, "for-each-ref", "refs/heads"]
+        lines = check_output(args).strip().split('\n')
+        refs = {}
+        for line in lines:
+            value, name = line.split(' ')
+            name = name.strip('commit\t')
+            refs[name] = value
+        return refs
+
     def do_import(self, base):
         """Imports a fast-import stream to the given directory.
 
@@ -30,11 +44,23 @@ def do_import(self, base):
         if not os.path.exists(dirname):
             os.makedirs(dirname)
 
+        refs_before = self.get_refs(gitdir)
+
         args = ["git", "--git-dir=" + gitdir, "fast-import", "--quiet", "--export-marks=" + path]
 
         if os.path.exists(path):
             args.append("--import-marks=" + path)
 
-        child = subprocess.Popen(args)
-        if child.wait() != 0:
-            raise CalledProcessError
+        check_call(args)
+
+        refs_after = self.get_refs(gitdir)
+
+        changed = {}
+
+        for name, value in refs_after.iteritems():
+            if refs_before.get(name) == value:
+                continue
+
+            changed[name] = value
+
+        return changed
index f27389bb945ef423dc412c2368762439086f593e..e70025095dcfb31d3944e72ac1f83dd7d4109103 100644 (file)
@@ -1,7 +1,7 @@
 import os
 import subprocess
 
-from git_remote_helpers.util import die, warn
+from git_remote_helpers.util import check_call, die, warn
 
 
 class NonLocalGit(object):
@@ -29,9 +29,7 @@ def clone(self, base):
         os.makedirs(path)
         args = ["git", "clone", "--bare", "--quiet", self.repo.gitpath, path]
 
-        child = subprocess.Popen(args)
-        if child.wait() != 0:
-            raise CalledProcessError
+        check_call(args)
 
         return path
 
@@ -45,14 +43,10 @@ def update(self, base):
             die("could not find repo at %s", path)
 
         args = ["git", "--git-dir=" + path, "fetch", "--quiet", self.repo.gitpath]
-        child = subprocess.Popen(args)
-        if child.wait() != 0:
-            raise CalledProcessError
+        check_call(args)
 
         args = ["git", "--git-dir=" + path, "update-ref", "refs/heads/master", "FETCH_HEAD"]
-        child = subprocess.Popen(args)
-        if child.wait() != 0:
-            raise CalledProcessError
+        child = check_call(args)
 
     def push(self, base):
         """Pushes from the non-local repo to base.
@@ -63,7 +57,5 @@ def push(self, base):
         if not os.path.exists(path):
             die("could not find repo at %s", path)
 
-        args = ["git", "--git-dir=" + path, "push", "--quiet", self.repo.gitpath]
-        child = subprocess.Popen(args)
-        if child.wait() != 0:
-            raise CalledProcessError
+        args = ["git", "--git-dir=" + path, "push", "--quiet", self.repo.gitpath, "--all"]
+        child = check_call(args)
index 58e1cdb560fa0fe1a4745f971064e5e967408502..acbf8d7785e2253777456f8910e2352992dda474 100644 (file)
@@ -1,6 +1,9 @@
 import os
 import subprocess
 
+from git_remote_helpers.util import check_call
+
+
 def sanitize(rev, sep='\t'):
     """Converts a for-each-ref line to a name/value pair.
     """
@@ -53,9 +56,7 @@ def get_revs(self):
         path = ".cached_revs"
         ofile = open(path, "w")
 
-        child = subprocess.Popen(args, stdout=ofile)
-        if child.wait() != 0:
-            raise CalledProcessError
+        check_call(args, stdout=ofile)
         output = open(path).readlines()
         self.revmap = dict(sanitize(i) for i in output)
         if "HEAD" in self.revmap:
index dce83e60660825ba115c503ce0776955d90c1a44..fbbb01b14619c1d2ed6bcc8f304f019fbe98697f 100644 (file)
 import os
 import subprocess
 
+try:
+    from subprocess import CalledProcessError
+except ImportError:
+    # from python2.7:subprocess.py
+    # Exception classes used by this module.
+    class CalledProcessError(Exception):
+        """This exception is raised when a process run by check_call() returns
+        a non-zero exit status.  The exit status will be stored in the
+        returncode attribute."""
+        def __init__(self, returncode, cmd):
+            self.returncode = returncode
+            self.cmd = cmd
+        def __str__(self):
+            return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode)
+
 
 # Whether or not to show debug messages
 DEBUG = False
@@ -128,6 +143,72 @@ def run_command (args, cwd = None, shell = False, add_env = None,
     return (exit_code, output, errors)
 
 
+# from python2.7:subprocess.py
+def call(*popenargs, **kwargs):
+    """Run command with arguments.  Wait for command to complete, then
+    return the returncode attribute.
+
+    The arguments are the same as for the Popen constructor.  Example:
+
+    retcode = call(["ls", "-l"])
+    """
+    return subprocess.Popen(*popenargs, **kwargs).wait()
+
+
+# from python2.7:subprocess.py
+def check_call(*popenargs, **kwargs):
+    """Run command with arguments.  Wait for command to complete.  If
+    the exit code was zero then return, otherwise raise
+    CalledProcessError.  The CalledProcessError object will have the
+    return code in the returncode attribute.
+
+    The arguments are the same as for the Popen constructor.  Example:
+
+    check_call(["ls", "-l"])
+    """
+    retcode = call(*popenargs, **kwargs)
+    if retcode:
+        cmd = kwargs.get("args")
+        if cmd is None:
+            cmd = popenargs[0]
+        raise CalledProcessError(retcode, cmd)
+    return 0
+
+
+# from python2.7:subprocess.py
+def check_output(*popenargs, **kwargs):
+    r"""Run command with arguments and return its output as a byte string.
+
+    If the exit code was non-zero it raises a CalledProcessError.  The
+    CalledProcessError object will have the return code in the returncode
+    attribute and output in the output attribute.
+
+    The arguments are the same as for the Popen constructor.  Example:
+
+    >>> check_output(["ls", "-l", "/dev/null"])
+    'crw-rw-rw- 1 root root 1, 3 Oct 18  2007 /dev/null\n'
+
+    The stdout argument is not allowed as it is used internally.
+    To capture standard error in the result, use stderr=STDOUT.
+
+    >>> check_output(["/bin/sh", "-c",
+    ...               "ls -l non_existent_file ; exit 0"],
+    ...              stderr=STDOUT)
+    'ls: non_existent_file: No such file or directory\n'
+    """
+    if 'stdout' in kwargs:
+        raise ValueError('stdout argument not allowed, it will be overridden.')
+    process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs)
+    output, unused_err = process.communicate()
+    retcode = process.poll()
+    if retcode:
+        cmd = kwargs.get("args")
+        if cmd is None:
+            cmd = popenargs[0]
+        raise subprocess.CalledProcessError(retcode, cmd)
+    return output
+
+
 def file_reader_method (missing_ok = False):
     """Decorator for simplifying reading of files.
 
index f3e567c8d7bc0bc556583326224e92e7c813f534..48def3841f13264134e1ab27673b8785d8b31f5b 100755 (executable)
@@ -321,6 +321,10 @@ sub evaluate_uri {
        # Enable text search, which will list the commits which match author,
        # committer or commit text to a given string.  Enabled by default.
        # Project specific override is not supported.
+       #
+       # Note that this controls all search features, which means that if
+       # it is disabled, then 'grep' and 'pickaxe' search would also be
+       # disabled.
        'search' => {
                'override' => 0,
                'default' => [1]},
@@ -5521,6 +5525,216 @@ sub git_remotes_body {
        }
 }
 
+sub git_search_message {
+       my %co = @_;
+
+       my $greptype;
+       if ($searchtype eq 'commit') {
+               $greptype = "--grep=";
+       } elsif ($searchtype eq 'author') {
+               $greptype = "--author=";
+       } elsif ($searchtype eq 'committer') {
+               $greptype = "--committer=";
+       }
+       $greptype .= $searchtext;
+       my @commitlist = parse_commits($hash, 101, (100 * $page), undef,
+                                      $greptype, '--regexp-ignore-case',
+                                      $search_use_regexp ? '--extended-regexp' : '--fixed-strings');
+
+       my $paging_nav = '';
+       if ($page > 0) {
+               $paging_nav .=
+                       $cgi->a({-href => href(-replay=>1, page=>undef)},
+                               "first") .
+                       " &sdot; " .
+                       $cgi->a({-href => href(-replay=>1, page=>$page-1),
+                                -accesskey => "p", -title => "Alt-p"}, "prev");
+       } else {
+               $paging_nav .= "first &sdot; prev";
+       }
+       my $next_link = '';
+       if ($#commitlist >= 100) {
+               $next_link =
+                       $cgi->a({-href => href(-replay=>1, page=>$page+1),
+                                -accesskey => "n", -title => "Alt-n"}, "next");
+               $paging_nav .= " &sdot; $next_link";
+       } else {
+               $paging_nav .= " &sdot; next";
+       }
+
+       git_header_html();
+
+       git_print_page_nav('','', $hash,$co{'tree'},$hash, $paging_nav);
+       git_print_header_div('commit', esc_html($co{'title'}), $hash);
+       if ($page == 0 && !@commitlist) {
+               print "<p>No match.</p>\n";
+       } else {
+               git_search_grep_body(\@commitlist, 0, 99, $next_link);
+       }
+
+       git_footer_html();
+}
+
+sub git_search_changes {
+       my %co = @_;
+
+       local $/ = "\n";
+       open my $fd, '-|', git_cmd(), '--no-pager', 'log', @diff_opts,
+               '--pretty=format:%H', '--no-abbrev', '--raw', "-S$searchtext",
+               ($search_use_regexp ? '--pickaxe-regex' : ())
+                       or die_error(500, "Open git-log failed");
+
+       git_header_html();
+
+       git_print_page_nav('','', $hash,$co{'tree'},$hash);
+       git_print_header_div('commit', esc_html($co{'title'}), $hash);
+
+       print "<table class=\"pickaxe search\">\n";
+       my $alternate = 1;
+       undef %co;
+       my @files;
+       while (my $line = <$fd>) {
+               chomp $line;
+               next unless $line;
+
+               my %set = parse_difftree_raw_line($line);
+               if (defined $set{'commit'}) {
+                       # finish previous commit
+                       if (%co) {
+                               print "</td>\n" .
+                                     "<td class=\"link\">" .
+                                     $cgi->a({-href => href(action=>"commit", hash=>$co{'id'})},
+                                             "commit") .
+                                     " | " .
+                                     $cgi->a({-href => href(action=>"tree", hash=>$co{'tree'},
+                                                            hash_base=>$co{'id'})},
+                                             "tree") .
+                                     "</td>\n" .
+                                     "</tr>\n";
+                       }
+
+                       if ($alternate) {
+                               print "<tr class=\"dark\">\n";
+                       } else {
+                               print "<tr class=\"light\">\n";
+                       }
+                       $alternate ^= 1;
+                       %co = parse_commit($set{'commit'});
+                       my $author = chop_and_escape_str($co{'author_name'}, 15, 5);
+                       print "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
+                             "<td><i>$author</i></td>\n" .
+                             "<td>" .
+                             $cgi->a({-href => href(action=>"commit", hash=>$co{'id'}),
+                                     -class => "list subject"},
+                                     chop_and_escape_str($co{'title'}, 50) . "<br/>");
+               } elsif (defined $set{'to_id'}) {
+                       next if ($set{'to_id'} =~ m/^0{40}$/);
+
+                       print $cgi->a({-href => href(action=>"blob", hash_base=>$co{'id'},
+                                                    hash=>$set{'to_id'}, file_name=>$set{'to_file'}),
+                                     -class => "list"},
+                                     "<span class=\"match\">" . esc_path($set{'file'}) . "</span>") .
+                             "<br/>\n";
+               }
+       }
+       close $fd;
+
+       # finish last commit (warning: repetition!)
+       if (%co) {
+               print "</td>\n" .
+                     "<td class=\"link\">" .
+                     $cgi->a({-href => href(action=>"commit", hash=>$co{'id'})},
+                             "commit") .
+                     " | " .
+                     $cgi->a({-href => href(action=>"tree", hash=>$co{'tree'},
+                                            hash_base=>$co{'id'})},
+                             "tree") .
+                     "</td>\n" .
+                     "</tr>\n";
+       }
+
+       print "</table>\n";
+
+       git_footer_html();
+}
+
+sub git_search_files {
+       my %co = @_;
+
+       local $/ = "\n";
+       open my $fd, "-|", git_cmd(), 'grep', '-n',
+               $search_use_regexp ? ('-E', '-i') : '-F',
+               $searchtext, $co{'tree'}
+                       or die_error(500, "Open git-grep failed");
+
+       git_header_html();
+
+       git_print_page_nav('','', $hash,$co{'tree'},$hash);
+       git_print_header_div('commit', esc_html($co{'title'}), $hash);
+
+       print "<table class=\"grep_search\">\n";
+       my $alternate = 1;
+       my $matches = 0;
+       my $lastfile = '';
+       while (my $line = <$fd>) {
+               chomp $line;
+               my ($file, $lno, $ltext, $binary);
+               last if ($matches++ > 1000);
+               if ($line =~ /^Binary file (.+) matches$/) {
+                       $file = $1;
+                       $binary = 1;
+               } else {
+                       (undef, $file, $lno, $ltext) = split(/:/, $line, 4);
+               }
+               if ($file ne $lastfile) {
+                       $lastfile and print "</td></tr>\n";
+                       if ($alternate++) {
+                               print "<tr class=\"dark\">\n";
+                       } else {
+                               print "<tr class=\"light\">\n";
+                       }
+                       print "<td class=\"list\">".
+                               $cgi->a({-href => href(action=>"blob", hash=>$co{'hash'},
+                                                      file_name=>"$file"),
+                                       -class => "list"}, esc_path($file));
+                       print "</td><td>\n";
+                       $lastfile = $file;
+               }
+               if ($binary) {
+                       print "<div class=\"binary\">Binary file</div>\n";
+               } else {
+                       $ltext = untabify($ltext);
+                       if ($ltext =~ m/^(.*)($search_regexp)(.*)$/i) {
+                               $ltext = esc_html($1, -nbsp=>1);
+                               $ltext .= '<span class="match">';
+                               $ltext .= esc_html($2, -nbsp=>1);
+                               $ltext .= '</span>';
+                               $ltext .= esc_html($3, -nbsp=>1);
+                       } else {
+                               $ltext = esc_html($ltext, -nbsp=>1);
+                       }
+                       print "<div class=\"pre\">" .
+                               $cgi->a({-href => href(action=>"blob", hash=>$co{'hash'},
+                                                      file_name=>"$file").'#l'.$lno,
+                                       -class => "linenr"}, sprintf('%4i', $lno))
+                               . ' ' .  $ltext . "</div>\n";
+               }
+       }
+       if ($lastfile) {
+               print "</td></tr>\n";
+               if ($matches > 1000) {
+                       print "<div class=\"diff nodifferences\">Too many matches, listing trimmed</div>\n";
+               }
+       } else {
+               print "<div class=\"diff nodifferences\">No matches found</div>\n";
+       }
+       close $fd;
+
+       print "</table>\n";
+
+       git_footer_html();
+}
+
 sub git_search_grep_body {
        my ($commitlist, $from, $to, $extra) = @_;
        $from = 0 unless defined $from;
@@ -6251,7 +6465,7 @@ sub git_blob {
                        $nr++;
                        $line = untabify($line);
                        printf qq!<div class="pre"><a id="l%i" href="%s#l%i" class="linenr">%4i</a> %s</div>\n!,
-                              $nr, esc_attr(href(-replay => 1)), $nr, $nr, $syntax ? $line : esc_html($line, -nbsp=>1);
+                              $nr, esc_attr(href(-replay => 1)), $nr, $nr, $syntax ? to_utf8($line) : esc_html($line, -nbsp=>1);
                }
        }
        close $fd
@@ -7076,7 +7290,23 @@ sub git_history {
 }
 
 sub git_search {
-       gitweb_check_feature('search') or die_error(403, "Search is disabled");
+       $searchtype ||= 'commit';
+
+       # check if appropriate features are enabled
+       gitweb_check_feature('search')
+               or die_error(403, "Search is disabled");
+       if ($searchtype eq 'pickaxe') {
+               # pickaxe may take all resources of your box and run for several minutes
+               # with every query - so decide by yourself how public you make this feature
+               gitweb_check_feature('pickaxe')
+                       or die_error(403, "Pickaxe search is disabled");
+       }
+       if ($searchtype eq 'grep') {
+               # grep search might be potentially CPU-intensive, too
+               gitweb_check_feature('grep')
+                       or die_error(403, "Grep search is disabled");
+       }
+
        if (!defined $searchtext) {
                die_error(400, "Text field is empty");
        }
@@ -7091,205 +7321,17 @@ sub git_search {
                $page = 0;
        }
 
-       $searchtype ||= 'commit';
-       if ($searchtype eq 'pickaxe') {
-               # pickaxe may take all resources of your box and run for several minutes
-               # with every query - so decide by yourself how public you make this feature
-               gitweb_check_feature('pickaxe')
-                   or die_error(403, "Pickaxe is disabled");
-       }
-       if ($searchtype eq 'grep') {
-               gitweb_check_feature('grep')
-                   or die_error(403, "Grep is disabled");
-       }
-
-       git_header_html();
-
-       if ($searchtype eq 'commit' or $searchtype eq 'author' or $searchtype eq 'committer') {
-               my $greptype;
-               if ($searchtype eq 'commit') {
-                       $greptype = "--grep=";
-               } elsif ($searchtype eq 'author') {
-                       $greptype = "--author=";
-               } elsif ($searchtype eq 'committer') {
-                       $greptype = "--committer=";
-               }
-               $greptype .= $searchtext;
-               my @commitlist = parse_commits($hash, 101, (100 * $page), undef,
-                                              $greptype, '--regexp-ignore-case',
-                                              $search_use_regexp ? '--extended-regexp' : '--fixed-strings');
-
-               my $paging_nav = '';
-               if ($page > 0) {
-                       $paging_nav .=
-                               $cgi->a({-href => href(action=>"search", hash=>$hash,
-                                                      searchtext=>$searchtext,
-                                                      searchtype=>$searchtype)},
-                                       "first");
-                       $paging_nav .= " &sdot; " .
-                               $cgi->a({-href => href(-replay=>1, page=>$page-1),
-                                        -accesskey => "p", -title => "Alt-p"}, "prev");
-               } else {
-                       $paging_nav .= "first";
-                       $paging_nav .= " &sdot; prev";
-               }
-               my $next_link = '';
-               if ($#commitlist >= 100) {
-                       $next_link =
-                               $cgi->a({-href => href(-replay=>1, page=>$page+1),
-                                        -accesskey => "n", -title => "Alt-n"}, "next");
-                       $paging_nav .= " &sdot; $next_link";
-               } else {
-                       $paging_nav .= " &sdot; next";
-               }
-
-               git_print_page_nav('','', $hash,$co{'tree'},$hash, $paging_nav);
-               git_print_header_div('commit', esc_html($co{'title'}), $hash);
-               if ($page == 0 && !@commitlist) {
-                       print "<p>No match.</p>\n";
-               } else {
-                       git_search_grep_body(\@commitlist, 0, 99, $next_link);
-               }
-       }
-
-       if ($searchtype eq 'pickaxe') {
-               git_print_page_nav('','', $hash,$co{'tree'},$hash);
-               git_print_header_div('commit', esc_html($co{'title'}), $hash);
-
-               print "<table class=\"pickaxe search\">\n";
-               my $alternate = 1;
-               local $/ = "\n";
-               open my $fd, '-|', git_cmd(), '--no-pager', 'log', @diff_opts,
-                       '--pretty=format:%H', '--no-abbrev', '--raw', "-S$searchtext",
-                       ($search_use_regexp ? '--pickaxe-regex' : ());
-               undef %co;
-               my @files;
-               while (my $line = <$fd>) {
-                       chomp $line;
-                       next unless $line;
-
-                       my %set = parse_difftree_raw_line($line);
-                       if (defined $set{'commit'}) {
-                               # finish previous commit
-                               if (%co) {
-                                       print "</td>\n" .
-                                             "<td class=\"link\">" .
-                                             $cgi->a({-href => href(action=>"commit", hash=>$co{'id'})}, "commit") .
-                                             " | " .
-                                             $cgi->a({-href => href(action=>"tree", hash=>$co{'tree'}, hash_base=>$co{'id'})}, "tree");
-                                       print "</td>\n" .
-                                             "</tr>\n";
-                               }
-
-                               if ($alternate) {
-                                       print "<tr class=\"dark\">\n";
-                               } else {
-                                       print "<tr class=\"light\">\n";
-                               }
-                               $alternate ^= 1;
-                               %co = parse_commit($set{'commit'});
-                               my $author = chop_and_escape_str($co{'author_name'}, 15, 5);
-                               print "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
-                                     "<td><i>$author</i></td>\n" .
-                                     "<td>" .
-                                     $cgi->a({-href => href(action=>"commit", hash=>$co{'id'}),
-                                             -class => "list subject"},
-                                             chop_and_escape_str($co{'title'}, 50) . "<br/>");
-                       } elsif (defined $set{'to_id'}) {
-                               next if ($set{'to_id'} =~ m/^0{40}$/);
-
-                               print $cgi->a({-href => href(action=>"blob", hash_base=>$co{'id'},
-                                                            hash=>$set{'to_id'}, file_name=>$set{'to_file'}),
-                                             -class => "list"},
-                                             "<span class=\"match\">" . esc_path($set{'file'}) . "</span>") .
-                                     "<br/>\n";
-                       }
-               }
-               close $fd;
-
-               # finish last commit (warning: repetition!)
-               if (%co) {
-                       print "</td>\n" .
-                             "<td class=\"link\">" .
-                             $cgi->a({-href => href(action=>"commit", hash=>$co{'id'})}, "commit") .
-                             " | " .
-                             $cgi->a({-href => href(action=>"tree", hash=>$co{'tree'}, hash_base=>$co{'id'})}, "tree");
-                       print "</td>\n" .
-                             "</tr>\n";
-               }
-
-               print "</table>\n";
-       }
-
-       if ($searchtype eq 'grep') {
-               git_print_page_nav('','', $hash,$co{'tree'},$hash);
-               git_print_header_div('commit', esc_html($co{'title'}), $hash);
-
-               print "<table class=\"grep_search\">\n";
-               my $alternate = 1;
-               my $matches = 0;
-               local $/ = "\n";
-               open my $fd, "-|", git_cmd(), 'grep', '-n',
-                       $search_use_regexp ? ('-E', '-i') : '-F',
-                       $searchtext, $co{'tree'};
-               my $lastfile = '';
-               while (my $line = <$fd>) {
-                       chomp $line;
-                       my ($file, $lno, $ltext, $binary);
-                       last if ($matches++ > 1000);
-                       if ($line =~ /^Binary file (.+) matches$/) {
-                               $file = $1;
-                               $binary = 1;
-                       } else {
-                               (undef, $file, $lno, $ltext) = split(/:/, $line, 4);
-                       }
-                       if ($file ne $lastfile) {
-                               $lastfile and print "</td></tr>\n";
-                               if ($alternate++) {
-                                       print "<tr class=\"dark\">\n";
-                               } else {
-                                       print "<tr class=\"light\">\n";
-                               }
-                               print "<td class=\"list\">".
-                                       $cgi->a({-href => href(action=>"blob", hash=>$co{'hash'},
-                                                              file_name=>"$file"),
-                                               -class => "list"}, esc_path($file));
-                               print "</td><td>\n";
-                               $lastfile = $file;
-                       }
-                       if ($binary) {
-                               print "<div class=\"binary\">Binary file</div>\n";
-                       } else {
-                               $ltext = untabify($ltext);
-                               if ($ltext =~ m/^(.*)($search_regexp)(.*)$/i) {
-                                       $ltext = esc_html($1, -nbsp=>1);
-                                       $ltext .= '<span class="match">';
-                                       $ltext .= esc_html($2, -nbsp=>1);
-                                       $ltext .= '</span>';
-                                       $ltext .= esc_html($3, -nbsp=>1);
-                               } else {
-                                       $ltext = esc_html($ltext, -nbsp=>1);
-                               }
-                               print "<div class=\"pre\">" .
-                                       $cgi->a({-href => href(action=>"blob", hash=>$co{'hash'},
-                                                              file_name=>"$file").'#l'.$lno,
-                                               -class => "linenr"}, sprintf('%4i', $lno))
-                                       . ' ' .  $ltext . "</div>\n";
-                       }
-               }
-               if ($lastfile) {
-                       print "</td></tr>\n";
-                       if ($matches > 1000) {
-                               print "<div class=\"diff nodifferences\">Too many matches, listing trimmed</div>\n";
-                       }
-               } else {
-                       print "<div class=\"diff nodifferences\">No matches found</div>\n";
-               }
-               close $fd;
-
-               print "</table>\n";
+       if ($searchtype eq 'commit' ||
+           $searchtype eq 'author' ||
+           $searchtype eq 'committer') {
+               git_search_message(%co);
+       } elsif ($searchtype eq 'pickaxe') {
+               git_search_changes(%co);
+       } elsif ($searchtype eq 'grep') {
+               git_search_files(%co);
+       } else {
+               die_error(400, "Unknown search type");
        }
-       git_footer_html();
 }
 
 sub git_search_help {
diff --git a/help.c b/help.c
index e925ca1f8973a05a66b5c09b45e3451f65e3a1e7..cbbe966f685b276cac702bb0fd9a44bfbf5f0e79 100644 (file)
--- a/help.c
+++ b/help.c
@@ -305,6 +305,10 @@ static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
 #define SIMILARITY_FLOOR 7
 #define SIMILAR_ENOUGH(x) ((x) < SIMILARITY_FLOOR)
 
+static const char bad_interpreter_advice[] =
+       N_("'%s' appears to be a git command, but we were not\n"
+       "able to execute it. Maybe git-%s is broken?");
+
 const char *help_unknown_cmd(const char *cmd)
 {
        int i, n, best_similarity = 0;
@@ -329,6 +333,14 @@ const char *help_unknown_cmd(const char *cmd)
                int cmp = 0; /* avoid compiler stupidity */
                const char *candidate = main_cmds.names[i]->name;
 
+               /*
+                * An exact match means we have the command, but
+                * for some reason exec'ing it gave us ENOENT; probably
+                * it's a bad interpreter in the #! line.
+                */
+               if (!strcmp(candidate, cmd))
+                       die(_(bad_interpreter_advice), cmd, cmd);
+
                /* Does the candidate appear in common_cmds list? */
                while (n < ARRAY_SIZE(common_cmds) &&
                       (cmp = strcmp(common_cmds[n].name, candidate)) < 0)
index faaeda44a9225ff56d45e9566cccf1a2278abb27..b8cf45a7dd439b83c80bcf7a397e1b8e34c70f67 100644 (file)
@@ -227,6 +227,8 @@ static struct ref *parse_info_refs(struct discovery *heads)
                if (data[i] == '\t')
                        mid = &data[i];
                if (data[i] == '\n') {
+                       if (mid - start != 40)
+                               die("%sinfo/refs not valid: is this a git repository?", url);
                        data[i] = 0;
                        ref_name = mid + 1;
                        ref = xmalloc(sizeof(struct ref) +
@@ -853,7 +855,14 @@ int main(int argc, const char **argv)
        http_init(remote);
 
        do {
-               if (strbuf_getline(&buf, stdin, '\n') == EOF)
+               if (strbuf_getline(&buf, stdin, '\n') == EOF) {
+                       if (ferror(stdin))
+                               fprintf(stderr, "Error reading command stream\n");
+                       else
+                               fprintf(stderr, "Unexpected end of command stream\n");
+                       return 1;
+               }
+               if (buf.len == 0)
                        break;
                if (!prefixcmp(buf.buf, "fetch ")) {
                        if (nongit)
@@ -893,6 +902,7 @@ int main(int argc, const char **argv)
                        printf("\n");
                        fflush(stdout);
                } else {
+                       fprintf(stderr, "Unknown command '%s'\n", buf.buf);
                        return 1;
                }
                strbuf_reset(&buf);
index ca42a126ad04514f0ed8378768ebce98cfc5a659..b8ecfa5d9558e3824872ad6778fc344681cc8d5c 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -896,7 +896,7 @@ struct ref *alloc_ref(const char *name)
        return alloc_ref_with_prefix("", 0, name);
 }
 
-static struct ref *copy_ref(const struct ref *ref)
+struct ref *copy_ref(const struct ref *ref)
 {
        struct ref *cpy;
        size_t len;
@@ -1667,7 +1667,9 @@ struct ref *guess_remote_head(const struct ref *head,
 
        /* Look for another ref that points there */
        for (r = refs; r; r = r->next) {
-               if (r != head && !hashcmp(r->old_sha1, head->old_sha1)) {
+               if (r != head &&
+                   !prefixcmp(r->name, "refs/heads/") &&
+                   !hashcmp(r->old_sha1, head->old_sha1)) {
                        *tail = copy_ref(r);
                        tail = &((*tail)->next);
                        if (!all)
index 888d7c15de2eacc56d869a96d4463aefca7a7a06..9a30a9dba64825950f7a0448ad8b64581c0b8fae 100644 (file)
--- a/remote.h
+++ b/remote.h
@@ -70,7 +70,7 @@ struct refspec {
 extern const struct refspec *tag_refspec;
 
 struct ref *alloc_ref(const char *name);
-
+struct ref *copy_ref(const struct ref *ref);
 struct ref *copy_ref_list(const struct ref *ref);
 
 int check_ref_type(const struct ref *ref, int flags);
index 89d7e5eb57ea80a7bca3f361530903032fbe2b03..d5616dca0809bdb9fd6a7a1980b92ded9ae6e230 100644 (file)
@@ -1797,6 +1797,24 @@ static void *unpack_delta_entry(struct packed_git *p,
        return result;
 }
 
+static void write_pack_access_log(struct packed_git *p, off_t obj_offset)
+{
+       static FILE *log_file;
+
+       if (!log_file) {
+               log_file = fopen(log_pack_access, "w");
+               if (!log_file) {
+                       error("cannot open pack access log '%s' for writing: %s",
+                             log_pack_access, strerror(errno));
+                       log_pack_access = NULL;
+                       return;
+               }
+       }
+       fprintf(log_file, "%s %"PRIuMAX"\n",
+               p->pack_name, (uintmax_t)obj_offset);
+       fflush(log_file);
+}
+
 int do_check_packed_object_crc;
 
 void *unpack_entry(struct packed_git *p, off_t obj_offset,
@@ -1806,6 +1824,9 @@ void *unpack_entry(struct packed_git *p, off_t obj_offset,
        off_t curpos = obj_offset;
        void *data;
 
+       if (log_pack_access)
+               write_pack_access_log(p, obj_offset);
+
        if (do_check_packed_object_crc && p->index_version > 1) {
                struct revindex_entry *revidx = find_pack_revindex(p, obj_offset);
                unsigned long len = revidx[1].offset - obj_offset;
index 25c9a209bb1ba9cec8bb49623ae45fc19fdca2c7..71072e1b1da670cdb4b048a3a6e83a4ae806bf5f 100644 (file)
@@ -94,7 +94,9 @@ struct git_istream {
 
 int close_istream(struct git_istream *st)
 {
-       return st->vtbl->close(st);
+       int r = st->vtbl->close(st);
+       free(st);
+       return r;
 }
 
 ssize_t read_istream(struct git_istream *st, char *buf, size_t sz)
index d206b7c4cfa4f7d61d151cebc35a0f296fbe4c6b..7913e206ed6b73d16779e91d6a9197e602626c57 100755 (executable)
@@ -1,5 +1,6 @@
 #!/bin/sh
 
+failed_tests=
 fixed=0
 success=0
 failed=0
@@ -18,7 +19,13 @@ do
                success)
                        success=$(($success + $value)) ;;
                failed)
-                       failed=$(($failed + $value)) ;;
+                       failed=$(($failed + $value))
+                       if test $value != 0
+                       then
+                               testnum=$(expr "$file" : 'test-results/\(t[0-9]*\)-')
+                               failed_tests="$failed_tests $testnum"
+                       fi
+                       ;;
                broken)
                        broken=$(($broken + $value)) ;;
                total)
@@ -27,6 +34,11 @@ do
        done <"$file"
 done
 
+if test -n "$failed_tests"
+then
+       printf "\nfailed test(s):$failed_tests\n\n"
+fi
+
 printf "%-8s%d\n" fixed $fixed
 printf "%-8s%d\n" success $success
 printf "%-8s%d\n" failed $failed
index 2ea3be6546f43fd5c224aa8df6add96fa9df6ac2..1aa366a410e9a3e2ad4c2fa84431198fbb553a5f 100755 (executable)
@@ -26,13 +26,13 @@ test_expect_success 'example 1: notes to add an Acked-by line' '
 '
 
 test_expect_success 'example 2: binary notes' '
-       cp "$TEST_DIRECTORY"/test4012.png . &&
+       cp "$TEST_DIRECTORY"/test-binary-1.png . &&
        git checkout B &&
-       blob=$(git hash-object -w test4012.png) &&
+       blob=$(git hash-object -w test-binary-1.png) &&
        git notes --ref=logo add -C "$blob" &&
        git notes --ref=logo copy B C &&
        git notes --ref=logo show C >actual &&
-       test_cmp test4012.png actual
+       test_cmp test-binary-1.png actual
 '
 
 test_done
diff --git a/t/t3905-stash-include-untracked.sh b/t/t3905-stash-include-untracked.sh
new file mode 100755 (executable)
index 0000000..4f2eedf
--- /dev/null
@@ -0,0 +1,155 @@
+#!/bin/sh
+#
+# Copyright (c) 2011 David Caldwell
+#
+
+test_description='Test git stash --include-untracked'
+
+. ./test-lib.sh
+
+test_expect_success 'stash save --include-untracked some dirty working directory' '
+       echo 1 > file &&
+       git add file &&
+       test_tick &&
+       git commit -m initial &&
+       echo 2 > file &&
+       git add file &&
+       echo 3 > file &&
+       test_tick &&
+       echo 1 > file2 &&
+       git stash --include-untracked &&
+       git diff-files --quiet &&
+       git diff-index --cached --quiet HEAD
+'
+
+cat > expect <<EOF
+?? expect
+?? output
+EOF
+
+test_expect_success 'stash save --include-untracked cleaned the untracked files' '
+       git status --porcelain > output
+       test_cmp output expect
+'
+
+cat > expect.diff <<EOF
+diff --git a/file2 b/file2
+new file mode 100644
+index 0000000..d00491f
+--- /dev/null
++++ b/file2
+@@ -0,0 +1 @@
++1
+EOF
+cat > expect.lstree <<EOF
+file2
+EOF
+
+test_expect_success 'stash save --include-untracked stashed the untracked files' '
+       test "!" -f file2 &&
+       git diff HEAD..stash^3 -- file2 > output &&
+       test_cmp output expect.diff &&
+       git ls-tree --name-only stash^3: > output &&
+       test_cmp output expect.lstree
+'
+test_expect_success 'stash save --patch --include-untracked fails' '
+       test_must_fail git stash --patch --include-untracked
+'
+
+test_expect_success 'stash save --patch --all fails' '
+       test_must_fail git stash --patch --all
+'
+
+git clean --force --quiet
+
+cat > expect <<EOF
+ M file
+?? expect
+?? file2
+?? output
+EOF
+
+test_expect_success 'stash pop after save --include-untracked leaves files untracked again' '
+       git stash pop &&
+       git status --porcelain > output
+       test_cmp output expect
+'
+
+git clean --force --quiet
+
+test_expect_success 'stash save -u dirty index' '
+       echo 4 > file3 &&
+       git add file3 &&
+       test_tick &&
+       git stash -u
+'
+
+cat > expect <<EOF
+diff --git a/file3 b/file3
+new file mode 100644
+index 0000000..b8626c4
+--- /dev/null
++++ b/file3
+@@ -0,0 +1 @@
++4
+EOF
+
+test_expect_success 'stash save --include-untracked dirty index got stashed' '
+       git stash pop --index &&
+       git diff --cached > output &&
+       test_cmp output expect
+'
+
+git reset > /dev/null
+
+test_expect_success 'stash save --include-untracked -q is quiet' '
+       echo 1 > file5 &&
+       git stash save --include-untracked --quiet > output.out 2>&1 &&
+       test ! -s output.out
+'
+
+test_expect_success 'stash save --include-untracked removed files' '
+       rm -f file &&
+       git stash save --include-untracked &&
+       echo 1 > expect &&
+       test_cmp file expect
+'
+
+rm -f expect
+
+test_expect_success 'stash save --include-untracked removed files got stashed' '
+       git stash pop &&
+       test ! -f file
+'
+
+cat > .gitignore <<EOF
+.gitignore
+ignored
+EOF
+
+test_expect_success 'stash save --include-untracked respects .gitignore' '
+       echo ignored > ignored &&
+       git stash -u &&
+       test -s ignored &&
+       test -s .gitignore
+'
+
+test_expect_success 'stash save -u can stash with only untracked files different' '
+       echo 4 > file4 &&
+       git stash -u
+       test "!" -f file4
+'
+
+test_expect_success 'stash save --all does not respect .gitignore' '
+       git stash -a &&
+       test "!" -f ignored &&
+       test "!" -f .gitignore
+'
+
+test_expect_success 'stash save --all is stash poppable' '
+       git stash pop &&
+       test -s ignored &&
+       test -s .gitignore
+'
+
+test_done
index 05ec0628322ccc103343515feb70d27a9a0e6c76..2d9f9a0cf1555cab24af19f264d495e134c27352 100755 (executable)
@@ -12,7 +12,7 @@ test_expect_success 'prepare repository' \
        'echo AIT >a && echo BIT >b && echo CIT >c && echo DIT >d &&
         git update-index --add a b c d &&
         echo git >a &&
-        cat "$TEST_DIRECTORY"/test4012.png >b &&
+        cat "$TEST_DIRECTORY"/test-binary-1.png >b &&
         echo git >c &&
         cat b b >d'
 
index 9e3ba98fc8d6f0242af38c3f7dc062e6c6ab9604..d9068981f8475c37d30e584bc6b795075a2f3063 100755 (executable)
@@ -266,7 +266,7 @@ test_expect_success 'archive --list mentions user filter' '
        grep "^bar\$" output
 '
 
-test_expect_success 'archive --list shows only enabled remote filters' '
+test_expect_success NOT_MINGW 'archive --list shows only enabled remote filters' '
        git archive --list --remote=. >output &&
        ! grep "^tar\.foo\$" output &&
        grep "^bar\$" output
@@ -298,7 +298,7 @@ test_expect_success 'extension matching requires dot' '
        test_cmp b.tar config-implicittar.foo
 '
 
-test_expect_success 'only enabled filters are available remotely' '
+test_expect_success NOT_MINGW 'only enabled filters are available remotely' '
        test_must_fail git archive --remote=. --format=tar.foo HEAD \
                >remote.tar.foo &&
        git archive --remote=. --format=bar >remote.bar HEAD &&
@@ -341,12 +341,12 @@ test_expect_success GZIP,GUNZIP 'extract tgz file' '
        test_cmp b.tar j.tar
 '
 
-test_expect_success GZIP 'remote tar.gz is allowed by default' '
+test_expect_success GZIP,NOT_MINGW 'remote tar.gz is allowed by default' '
        git archive --remote=. --format=tar.gz HEAD >remote.tar.gz &&
        test_cmp j.tgz remote.tar.gz
 '
 
-test_expect_success GZIP 'remote tar.gz can be disabled' '
+test_expect_success GZIP,NOT_MINGW 'remote tar.gz can be disabled' '
        git config tar.tar.gz.remote false &&
        test_must_fail git archive --remote=. --format=tar.gz HEAD \
                >remote.tar.gz
diff --git a/t/t5707-clone-detached.sh b/t/t5707-clone-detached.sh
new file mode 100755 (executable)
index 0000000..8b0d607
--- /dev/null
@@ -0,0 +1,76 @@
+#!/bin/sh
+
+test_description='test cloning a repository with detached HEAD'
+. ./test-lib.sh
+
+head_is_detached() {
+       git --git-dir=$1/.git rev-parse --verify HEAD &&
+       test_must_fail git --git-dir=$1/.git symbolic-ref HEAD
+}
+
+test_expect_success 'setup' '
+       echo one >file &&
+       git add file &&
+       git commit -m one &&
+       echo two >file &&
+       git commit -a -m two &&
+       git tag two &&
+       echo three >file &&
+       git commit -a -m three
+'
+
+test_expect_success 'clone repo (detached HEAD points to branch)' '
+       git checkout master^0 &&
+       git clone "file://$PWD" detached-branch
+'
+test_expect_success 'cloned HEAD matches' '
+       echo three >expect &&
+       git --git-dir=detached-branch/.git log -1 --format=%s >actual &&
+       test_cmp expect actual
+'
+test_expect_failure 'cloned HEAD is detached' '
+       head_is_detached detached-branch
+'
+
+test_expect_success 'clone repo (detached HEAD points to tag)' '
+       git checkout two^0 &&
+       git clone "file://$PWD" detached-tag
+'
+test_expect_success 'cloned HEAD matches' '
+       echo two >expect &&
+       git --git-dir=detached-tag/.git log -1 --format=%s >actual &&
+       test_cmp expect actual
+'
+test_expect_success 'cloned HEAD is detached' '
+       head_is_detached detached-tag
+'
+
+test_expect_success 'clone repo (detached HEAD points to history)' '
+       git checkout two^ &&
+       git clone "file://$PWD" detached-history
+'
+test_expect_success 'cloned HEAD matches' '
+       echo one >expect &&
+       git --git-dir=detached-history/.git log -1 --format=%s >actual &&
+       test_cmp expect actual
+'
+test_expect_success 'cloned HEAD is detached' '
+       head_is_detached detached-history
+'
+
+test_expect_success 'clone repo (orphan detached HEAD)' '
+       git checkout master^0 &&
+       echo four >file &&
+       git commit -a -m four &&
+       git clone "file://$PWD" detached-orphan
+'
+test_expect_success 'cloned HEAD matches' '
+       echo four >expect &&
+       git --git-dir=detached-orphan/.git log -1 --format=%s >actual &&
+       test_cmp expect actual
+'
+test_expect_success 'cloned HEAD is detached' '
+       head_is_detached detached-orphan
+'
+
+test_done
index 1fb6380fceb294f1a7cc73359f5e39740260d8f0..1c62001fce76a73cc951dd18bcf6cb6f650f69e8 100755 (executable)
@@ -7,17 +7,27 @@ test_description='Test remote-helper import and export commands'
 
 . ./test-lib.sh
 
-if test_have_prereq PYTHON && "$PYTHON_PATH" -c '
+if ! test_have_prereq PYTHON ; then
+       skip_all='skipping git-remote-hg tests, python not available'
+       test_done
+fi
+
+"$PYTHON_PATH" -c '
 import sys
 if sys.hexversion < 0x02040000:
     sys.exit(1)
-'
-then
-    # Requires Python 2.4 or newer
-       test_set_prereq PYTHON_24
-fi
+' || {
+       skip_all='skipping git-remote-hg tests, python version < 2.4'
+       test_done
+}
+
+compare_refs() {
+       git --git-dir="$1/.git" rev-parse --verify $2 >expect &&
+       git --git-dir="$3/.git" rev-parse --verify $4 >actual &&
+       test_cmp expect actual
+}
 
-test_expect_success PYTHON_24 'setup repository' '
+test_expect_success 'setup repository' '
        git init --bare server/.git &&
        git clone server public &&
        (cd public &&
@@ -27,54 +37,99 @@ test_expect_success PYTHON_24 'setup repository' '
         git push origin master)
 '
 
-test_expect_success PYTHON_24 'cloning from local repo' '
+test_expect_success 'cloning from local repo' '
        git clone "testgit::${PWD}/server" localclone &&
        test_cmp public/file localclone/file
 '
 
-test_expect_success PYTHON_24 'cloning from remote repo' '
+test_expect_success 'cloning from remote repo' '
        git clone "testgit::file://${PWD}/server" clone &&
        test_cmp public/file clone/file
 '
 
-test_expect_success PYTHON_24 'create new commit on remote' '
+test_expect_success 'create new commit on remote' '
        (cd public &&
         echo content >>file &&
         git commit -a -m two &&
         git push)
 '
 
-test_expect_success PYTHON_24 'pulling from local repo' '
+test_expect_success 'pulling from local repo' '
        (cd localclone && git pull) &&
        test_cmp public/file localclone/file
 '
 
-test_expect_success PYTHON_24 'pulling from remote remote' '
+test_expect_success 'pulling from remote remote' '
        (cd clone && git pull) &&
        test_cmp public/file clone/file
 '
 
-test_expect_success PYTHON_24 'pushing to local repo' '
+test_expect_success 'pushing to local repo' '
        (cd localclone &&
        echo content >>file &&
        git commit -a -m three &&
        git push) &&
-       HEAD=$(git --git-dir=localclone/.git rev-parse --verify HEAD) &&
-       test $HEAD = $(git --git-dir=server/.git rev-parse --verify HEAD)
+       compare_refs localclone HEAD server HEAD
 '
 
-test_expect_success PYTHON_24 'synch with changes from localclone' '
+test_expect_success 'synch with changes from localclone' '
        (cd clone &&
         git pull)
 '
 
-test_expect_success PYTHON_24 'pushing remote local repo' '
+test_expect_success 'pushing remote local repo' '
        (cd clone &&
        echo content >>file &&
        git commit -a -m four &&
        git push) &&
-       HEAD=$(git --git-dir=clone/.git rev-parse --verify HEAD) &&
-       test $HEAD = $(git --git-dir=server/.git rev-parse --verify HEAD)
+       compare_refs clone HEAD server HEAD
+'
+
+test_expect_success 'fetch new branch' '
+       (cd public &&
+        git checkout -b new &&
+        echo content >>file &&
+        git commit -a -m five &&
+        git push origin new
+       ) &&
+       (cd localclone &&
+        git fetch origin new
+       ) &&
+       compare_refs public HEAD localclone FETCH_HEAD
+'
+
+test_expect_success 'fetch multiple branches' '
+       (cd localclone &&
+        git fetch
+       ) &&
+       compare_refs server master localclone refs/remotes/origin/master &&
+       compare_refs server new localclone refs/remotes/origin/new
+'
+
+test_expect_success 'push when remote has extra refs' '
+       (cd clone &&
+        echo content >>file &&
+        git commit -a -m six &&
+        git push
+       ) &&
+       compare_refs clone master server master
+'
+
+test_expect_success 'push new branch by name' '
+       (cd clone &&
+        git checkout -b new-name  &&
+        echo content >>file &&
+        git commit -a -m seven &&
+        git push origin new-name
+       ) &&
+       compare_refs clone HEAD server refs/heads/new-name
+'
+
+test_expect_failure 'push new branch with old:new refspec' '
+       (cd clone &&
+        git push origin new-name:new-refspec
+       ) &&
+       compare_refs clone HEAD server refs/heads/new-refspec
 '
 
 test_done
index d9f343942c7eb9d1e80e98db2252cb29135544fa..432f086c063198e82ad8a2f7c8dd175a8685fdf5 100755 (executable)
@@ -154,7 +154,7 @@ test_expect_success "expected conflict markers" "test_cmp expect out"
 
 test_expect_success 'binary files cannot be merged' '
        test_must_fail git merge-file -p \
-               orig.txt "$TEST_DIRECTORY"/test4012.png new1.txt 2> merge.err &&
+               orig.txt "$TEST_DIRECTORY"/test-binary-1.png new1.txt 2> merge.err &&
        grep "Cannot merge binary files" merge.err
 '
 
index b519626ca09255a433b0d1cb32780a6feafa09f6..07735410b9536ba7639134c7ca0cda4f486f8291 100755 (executable)
@@ -6,7 +6,7 @@ test_description='ask merge-recursive to merge binary files'
 
 test_expect_success setup '
 
-       cat "$TEST_DIRECTORY"/test4012.png >m &&
+       cat "$TEST_DIRECTORY"/test-binary-1.png >m &&
        git add m &&
        git ls-files -s | sed -e "s/ 0  / 1     /" >E1 &&
        test_tick &&
index f1cfc9ac959ee281d50f7b8a51fdcefd2d0670e7..b096dc88c2f4caf28887cf8fea5d700f0132f5a3 100755 (executable)
@@ -429,6 +429,21 @@ test_expect_success '--mixed refreshes the index' '
        test_i18ncmp expect output
 '
 
+test_expect_success 'resetting specific path that is unmerged' '
+       git rm --cached file2 &&
+       F1=$(git rev-parse HEAD:file1) &&
+       F2=$(git rev-parse HEAD:file2) &&
+       F3=$(git rev-parse HEAD:secondfile) &&
+       {
+               echo "100644 $F1 1      file2" &&
+               echo "100644 $F2 2      file2" &&
+               echo "100644 $F3 3      file2"
+       } | git update-index --index-info &&
+       git ls-files -u &&
+       test_must_fail git reset HEAD file2 &&
+       git diff-index --exit-code --cached HEAD
+'
+
 test_expect_success 'disambiguation (1)' '
 
        git reset --hard &&
index b2b26b72d05a392d8adb83be50c1bb9e73c4eb2d..14dc92723c3dc96c1c3c15724df668226edf578e 100755 (executable)
@@ -47,8 +47,10 @@ test_expect_success 'setup - repository to add submodules to' '
 '
 
 # The 'submodule add' tests need some repository to add as a submodule.
-# The trash directory is a good one as any.
-submodurl=$TRASH_DIRECTORY
+# The trash directory is a good one as any. We need to canonicalize
+# the name, though, as some tests compare it to the absolute path git
+# generates, which will expand symbolic links.
+submodurl=$(pwd -P)
 
 listbranches() {
        git for-each-ref --format='%(refname)' 'refs/heads/*'
@@ -446,6 +448,16 @@ test_expect_success 'add should fail when path is used by an existing directory'
        )
 '
 
+test_expect_success 'use superproject as upstream when path is relative and no url is set there' '
+       (
+               cd addtest &&
+               git submodule add ../repo relative &&
+               test "$(git config -f .gitmodules submodule.relative.url)" = ../repo &&
+               git submodule sync relative &&
+               test "$(git config submodule.relative.url)" = "$submodurl/repo"
+       )
+'
+
 test_expect_success 'set up for relative path tests' '
        mkdir reltest &&
        (
index e5da65b99fa1459836e516772fe8d13d038f502e..41db05cb4af6f42ef3065ba0576d8cfa3509c0ca 100755 (executable)
@@ -50,8 +50,8 @@ test_expect_success \
     'mkdir A B C D E F &&
      echo hello1 >A/newfile1.txt &&
      echo hello2 >B/newfile2.txt &&
-     cp "$TEST_DIRECTORY"/test9200a.png C/newfile3.png &&
-     cp "$TEST_DIRECTORY"/test9200a.png D/newfile4.png &&
+     cp "$TEST_DIRECTORY"/test-binary-1.png C/newfile3.png &&
+     cp "$TEST_DIRECTORY"/test-binary-1.png D/newfile4.png &&
      git add A/newfile1.txt &&
      git add B/newfile2.txt &&
      git add C/newfile3.png &&
@@ -76,8 +76,8 @@ test_expect_success \
      rm -f B/newfile2.txt &&
      rm -f C/newfile3.png &&
      echo Hello5  >E/newfile5.txt &&
-     cp "$TEST_DIRECTORY"/test9200b.png D/newfile4.png &&
-     cp "$TEST_DIRECTORY"/test9200a.png F/newfile6.png &&
+     cp "$TEST_DIRECTORY"/test-binary-2.png D/newfile4.png &&
+     cp "$TEST_DIRECTORY"/test-binary-1.png F/newfile6.png &&
      git add E/newfile5.txt &&
      git add F/newfile6.png &&
      git commit -a -m "Test: Remove, add and update" &&
@@ -165,7 +165,7 @@ test_expect_success \
      'mkdir "G g" &&
       echo ok then >"G g/with spaces.txt" &&
       git add "G g/with spaces.txt" && \
-      cp "$TEST_DIRECTORY"/test9200a.png "G g/with spaces.png" && \
+      cp "$TEST_DIRECTORY"/test-binary-1.png "G g/with spaces.png" && \
       git add "G g/with spaces.png" &&
       git commit -a -m "With spaces" &&
       id=$(git rev-list --max-count=1 HEAD) &&
@@ -177,7 +177,7 @@ test_expect_success \
 test_expect_success \
      'Update file with spaces in file name' \
      'echo Ok then >>"G g/with spaces.txt" &&
-      cat "$TEST_DIRECTORY"/test9200a.png >>"G g/with spaces.png" && \
+      cat "$TEST_DIRECTORY"/test-binary-1.png >>"G g/with spaces.png" && \
       git add "G g/with spaces.png" &&
       git commit -a -m "Update with spaces" &&
       id=$(git rev-list --max-count=1 HEAD) &&
@@ -202,7 +202,7 @@ test_expect_success \
      'mkdir -p Ã…/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/Ã¥/ä/ö &&
       echo Foo >Ã…/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/Ã¥/ä/ö/gÃ¥rdetsÃ¥gÃ¥rdet.txt &&
       git add Ã…/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/Ã¥/ä/ö/gÃ¥rdetsÃ¥gÃ¥rdet.txt &&
-      cp "$TEST_DIRECTORY"/test9200a.png Ã…/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/Ã¥/ä/ö/gÃ¥rdetsÃ¥gÃ¥rdet.png &&
+      cp "$TEST_DIRECTORY"/test-binary-1.png Ã…/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/Ã¥/ä/ö/gÃ¥rdetsÃ¥gÃ¥rdet.png &&
       git add Ã…/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/Ã¥/ä/ö/gÃ¥rdetsÃ¥gÃ¥rdet.png &&
       git commit -a -m "GÃ¥r det sÃ¥ gÃ¥r det" && \
       id=$(git rev-list --max-count=1 HEAD) &&
index 2a53640c5b29c19a2327570148638dbf94bc2afa..f256475020549a157297481e21859e235a5cfcc1 100755 (executable)
@@ -2197,6 +2197,48 @@ test_expect_success 'R: quiet option results in no stats being output' '
     test_cmp empty output
 '
 
+test_expect_success 'R: feature done means terminating "done" is mandatory' '
+       echo feature done | test_must_fail git fast-import &&
+       test_must_fail git fast-import --done </dev/null
+'
+
+test_expect_success 'R: terminating "done" with trailing gibberish is ok' '
+       git fast-import <<-\EOF &&
+       feature done
+       done
+       trailing gibberish
+       EOF
+       git fast-import <<-\EOF
+       done
+       more trailing gibberish
+       EOF
+'
+
+test_expect_success 'R: terminating "done" within commit' '
+       cat >expect <<-\EOF &&
+       OBJID
+       :000000 100644 OBJID OBJID A    hello.c
+       :000000 100644 OBJID OBJID A    hello2.c
+       EOF
+       git fast-import <<-EOF &&
+       commit refs/heads/done-ends
+       committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+       data <<EOT
+       Commit terminated by "done" command
+       EOT
+       M 100644 inline hello.c
+       data <<EOT
+       Hello, world.
+       EOT
+       C hello.c hello2.c
+       done
+       EOF
+       git rev-list done-ends |
+       git diff-tree -r --stdin --root --always |
+       sed -e "s/$_x40/OBJID/g" >actual &&
+       test_cmp expect actual
+'
+
 cat >input <<EOF
 option git non-existing-option
 EOF
index 33b0127651da0c4c178e62c269179b641e15f9f6..97ec9753b45b4f2786e247e2897b3185b7b66df8 100755 (executable)
@@ -45,29 +45,33 @@ test_expect_success 'add p4 files' '
        cd "$TRASH_DIRECTORY"
 '
 
+cleanup_git() {
+       cd "$TRASH_DIRECTORY" &&
+       rm -rf "$git" &&
+       mkdir "$git"
+}
+
 test_expect_success 'basic git-p4 clone' '
        "$GITP4" clone --dest="$git" //depot &&
+       test_when_finished cleanup_git &&
        cd "$git" &&
        git log --oneline >lines &&
-       test_line_count = 1 lines &&
-       cd .. &&
-       rm -rf "$git" && mkdir "$git"
+       test_line_count = 1 lines
 '
 
 test_expect_success 'git-p4 clone @all' '
        "$GITP4" clone --dest="$git" //depot@all &&
+       test_when_finished cleanup_git &&
        cd "$git" &&
        git log --oneline >lines &&
-       test_line_count = 2 lines &&
-       cd .. &&
-       rm -rf "$git" && mkdir "$git"
+       test_line_count = 2 lines
 '
 
 test_expect_success 'git-p4 sync uninitialized repo' '
        test_create_repo "$git" &&
+       test_when_finished cleanup_git &&
        cd "$git" &&
-       test_must_fail "$GITP4" sync &&
-       rm -rf "$git" && mkdir "$git"
+       test_must_fail "$GITP4" sync
 '
 
 #
@@ -76,19 +80,18 @@ test_expect_success 'git-p4 sync uninitialized repo' '
 #
 test_expect_success 'git-p4 sync new branch' '
        test_create_repo "$git" &&
+       test_when_finished cleanup_git &&
        cd "$git" &&
        test_commit head &&
        "$GITP4" sync --branch=refs/remotes/p4/depot //depot@all &&
        git log --oneline p4/depot >lines &&
-       cat lines &&
-       test_line_count = 2 lines &&
-       cd .. &&
-       rm -rf "$git" && mkdir "$git"
+       test_line_count = 2 lines
 '
 
 test_expect_success 'exit when p4 fails to produce marshaled output' '
        badp4dir="$TRASH_DIRECTORY/badp4dir" &&
        mkdir -p "$badp4dir" &&
+       test_when_finished "rm -rf $badp4dir" &&
        cat >"$badp4dir"/p4 <<-EOF &&
        #!$SHELL_PATH
        exit 1
@@ -106,29 +109,26 @@ test_expect_success 'add p4 files with wildcards in the names' '
        echo file-wild-at >file-wild@at &&
        echo file-wild-percent >file-wild%percent &&
        p4 add -f file-wild* &&
-       p4 submit -d "file wildcards" &&
-       cd "$TRASH_DIRECTORY"
+       p4 submit -d "file wildcards"
 '
 
 test_expect_success 'wildcard files git-p4 clone' '
        "$GITP4" clone --dest="$git" //depot &&
+       test_when_finished cleanup_git &&
        cd "$git" &&
        test -f file-wild#hash &&
        test -f file-wild\*star &&
        test -f file-wild@at &&
-       test -f file-wild%percent &&
-       cd "$TRASH_DIRECTORY" &&
-       rm -rf "$git" && mkdir "$git"
+       test -f file-wild%percent
 '
 
 test_expect_success 'clone bare' '
        "$GITP4" clone --dest="$git" --bare //depot &&
+       test_when_finished cleanup_git &&
        cd "$git" &&
        test ! -d .git &&
        bare=`git config --get core.bare` &&
-       test "$bare" = true &&
-       cd "$TRASH_DIRECTORY" &&
-       rm -rf "$git" && mkdir "$git"
+       test "$bare" = true
 '
 
 p4_add_user() {
@@ -173,6 +173,7 @@ test_expect_success 'preserve users' '
        p4_add_user bob Bob &&
        p4_grant_admin alice &&
        "$GITP4" clone --dest="$git" //depot &&
+       test_when_finished cleanup_git &&
        cd "$git" &&
        echo "username: a change by alice" >> file1 &&
        echo "username: a change by bob" >> file2 &&
@@ -181,29 +182,28 @@ test_expect_success 'preserve users' '
        git config git-p4.skipSubmitEditCheck true &&
        P4EDITOR=touch P4USER=alice P4PASSWD=secret "$GITP4" commit --preserve-user &&
        p4_check_commit_author file1 alice &&
-       p4_check_commit_author file2 bob &&
-       cd "$TRASH_DIRECTORY" &&
-       rm -rf "$git" && mkdir "$git"
+       p4_check_commit_author file2 bob
 '
 
 # Test username support, submitting as bob, who lacks admin rights. Should
 # not submit change to p4 (git diff should show deltas).
 test_expect_success 'refuse to preserve users without perms' '
        "$GITP4" clone --dest="$git" //depot &&
+       test_when_finished cleanup_git &&
        cd "$git" &&
+       git config git-p4.skipSubmitEditCheck true &&
        echo "username-noperms: a change by alice" >> file1 &&
        git commit --author "Alice <alice@localhost>" -m "perms: a change by alice" file1 &&
        ! P4EDITOR=touch P4USER=bob P4PASSWD=secret "$GITP4" commit --preserve-user &&
-       ! git diff --exit-code HEAD..p4/master > /dev/null &&
-       cd "$TRASH_DIRECTORY" &&
-       rm -rf "$git" && mkdir "$git"
+       ! git diff --exit-code HEAD..p4/master > /dev/null
 '
 
 # What happens with unknown author? Without allowMissingP4Users it should fail.
 test_expect_success 'preserve user where author is unknown to p4' '
        "$GITP4" clone --dest="$git" //depot &&
+       test_when_finished cleanup_git &&
        cd "$git" &&
-       git config git-p4.skipSubmitEditCheck true
+       git config git-p4.skipSubmitEditCheck true &&
        echo "username-bob: a change by bob" >> file1 &&
        git commit --author "Bob <bob@localhost>" -m "preserve: a change by bob" file1 &&
        echo "username-unknown: a change by charlie" >> file1 &&
@@ -215,9 +215,7 @@ test_expect_success 'preserve user where author is unknown to p4' '
        git config git-p4.preserveUser true &&
        P4EDITOR=touch P4USER=alice P4PASSWD=secret "$GITP4" commit &&
        git diff --exit-code HEAD..p4/master > /dev/null &&
-       p4_check_commit_author file1 alice &&
-       cd "$TRASH_DIRECTORY" &&
-       rm -rf "$git" && mkdir "$git"
+       p4_check_commit_author file1 alice
 '
 
 # If we're *not* using --preserve-user, git-p4 should warn if we're submitting
@@ -226,33 +224,50 @@ test_expect_success 'preserve user where author is unknown to p4' '
 # Test: warning disabled and user is the same.
 test_expect_success 'not preserving user with mixed authorship' '
        "$GITP4" clone --dest="$git" //depot &&
-       (
-               cd "$git" &&
-               git config git-p4.skipSubmitEditCheck true &&
-               p4_add_user derek Derek &&
-
-               make_change_by_user usernamefile3 Derek derek@localhost &&
-               P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit >actual &&
-               grep "git author derek@localhost does not match" actual &&
-
-               make_change_by_user usernamefile3 Charlie charlie@localhost &&
-               P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit >actual &&
-               grep "git author charlie@localhost does not match" actual &&
-
-               make_change_by_user usernamefile3 alice alice@localhost &&
-               P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit >actual &&
-               ! grep "git author.*does not match" actual &&
-
-               git config git-p4.skipUserNameCheck true &&
-               make_change_by_user usernamefile3 Charlie charlie@localhost &&
-               P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit >actual &&
-               ! grep "git author.*does not match" actual &&
-
-               p4_check_commit_author usernamefile3 alice
-       ) &&
-       rm -rf "$git" && mkdir "$git"
+       test_when_finished cleanup_git &&
+       cd "$git" &&
+       git config git-p4.skipSubmitEditCheck true &&
+       p4_add_user derek Derek &&
+
+       make_change_by_user usernamefile3 Derek derek@localhost &&
+       P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit >actual &&
+       grep "git author derek@localhost does not match" actual &&
+
+       make_change_by_user usernamefile3 Charlie charlie@localhost &&
+       P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit >actual &&
+       grep "git author charlie@localhost does not match" actual &&
+
+       make_change_by_user usernamefile3 alice alice@localhost &&
+       P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit >actual &&
+       ! grep "git author.*does not match" actual &&
+
+       git config git-p4.skipUserNameCheck true &&
+       make_change_by_user usernamefile3 Charlie charlie@localhost &&
+       P4EDITOR=cat P4USER=alice P4PASSWD=secret "$GITP4" commit >actual &&
+       ! grep "git author.*does not match" actual &&
+
+       p4_check_commit_author usernamefile3 alice
 '
 
+marshal_dump() {
+       what=$1
+       python -c 'import marshal, sys; d = marshal.load(sys.stdin); print d["'$what'"]'
+}
+
+# Sleep a bit so that the top-most p4 change did not happen "now".  Then
+# import the repo and make sure that the initial import has the same time
+# as the top-most change.
+test_expect_success 'initial import time from top change time' '
+       p4change=$(p4 -G changes -m 1 //depot/... | marshal_dump change) &&
+       p4time=$(p4 -G changes -m 1 //depot/... | marshal_dump time) &&
+       sleep 3 &&
+       "$GITP4" clone --dest="$git" //depot &&
+       test_when_finished cleanup_git &&
+       cd "$git" &&
+       gittime=$(git show -s --raw --pretty=format:%at HEAD) &&
+       echo $p4time $gittime &&
+       test $p4time = $gittime
+'
 
 test_expect_success 'shutdown' '
        pid=`pgrep -f p4d` &&
diff --git a/t/test-binary-1.png b/t/test-binary-1.png
new file mode 100644 (file)
index 0000000..7b181d1
Binary files /dev/null and b/t/test-binary-1.png differ
diff --git a/t/test-binary-2.png b/t/test-binary-2.png
new file mode 100644 (file)
index 0000000..ac22ccb
Binary files /dev/null and b/t/test-binary-2.png differ
diff --git a/t/test4012.png b/t/test4012.png
deleted file mode 100644 (file)
index 7b181d1..0000000
Binary files a/t/test4012.png and /dev/null differ
diff --git a/t/test9200a.png b/t/test9200a.png
deleted file mode 100644 (file)
index 7b181d1..0000000
Binary files a/t/test9200a.png and /dev/null differ
diff --git a/t/test9200b.png b/t/test9200b.png
deleted file mode 100644 (file)
index ac22ccb..0000000
Binary files a/t/test9200b.png and /dev/null differ
index 660147f9e96be7b69379a9040c4220c141c7be4c..4eab844d4abfa29ce53b6245a5821ee7be03641b 100644 (file)
@@ -23,6 +23,8 @@ struct helper_data {
                push : 1,
                connect : 1,
                no_disconnect_req : 1;
+       char *export_marks;
+       char *import_marks;
        /* These go from remote name (as in "list") to private name */
        struct refspec *refspecs;
        int refspec_nr;
@@ -105,6 +107,12 @@ static struct child_process *get_helper(struct transport *transport)
        int refspec_alloc = 0;
        int duped;
        int code;
+       char git_dir_buf[sizeof(GIT_DIR_ENVIRONMENT) + PATH_MAX + 1];
+       const char *helper_env[] = {
+               git_dir_buf,
+               NULL
+       };
+
 
        if (data->helper)
                return data->helper;
@@ -120,6 +128,10 @@ static struct child_process *get_helper(struct transport *transport)
        helper->argv[2] = remove_ext_force(transport->url);
        helper->git_cmd = 0;
        helper->silent_exec_failure = 1;
+
+       snprintf(git_dir_buf, sizeof(git_dir_buf), "%s=%s", GIT_DIR_ENVIRONMENT, get_git_dir());
+       helper->env = helper_env;
+
        code = start_command(helper);
        if (code < 0 && errno == ENOENT)
                die("Unable to find remote helper for '%s'", data->name);
@@ -171,14 +183,19 @@ static struct child_process *get_helper(struct transport *transport)
                        ALLOC_GROW(refspecs,
                                   refspec_nr + 1,
                                   refspec_alloc);
-                       refspecs[refspec_nr++] = strdup(buf.buf + strlen("refspec "));
+                       refspecs[refspec_nr++] = strdup(capname + strlen("refspec "));
                } else if (!strcmp(capname, "connect")) {
                        data->connect = 1;
-               } else if (!strcmp(buf.buf, "gitdir")) {
-                       struct strbuf gitdir = STRBUF_INIT;
-                       strbuf_addf(&gitdir, "gitdir %s\n", get_git_dir());
-                       sendline(data, &gitdir);
-                       strbuf_release(&gitdir);
+               } else if (!prefixcmp(capname, "export-marks ")) {
+                       struct strbuf arg = STRBUF_INIT;
+                       strbuf_addstr(&arg, "--export-marks=");
+                       strbuf_addstr(&arg, capname + strlen("export-marks "));
+                       data->export_marks = strbuf_detach(&arg, NULL);
+               } else if (!prefixcmp(capname, "import-marks")) {
+                       struct strbuf arg = STRBUF_INIT;
+                       strbuf_addstr(&arg, "--import-marks=");
+                       strbuf_addstr(&arg, capname + strlen("import-marks "));
+                       data->import_marks = strbuf_detach(&arg, NULL);
                } else if (mandatory) {
                        die("Unknown mandatory capability %s. This remote "
                            "helper probably needs newer version of Git.\n",
@@ -204,6 +221,7 @@ static int disconnect_helper(struct transport *transport)
 {
        struct helper_data *data = transport->data;
        struct strbuf buf = STRBUF_INIT;
+       int res = 0;
 
        if (data->helper) {
                if (debug)
@@ -215,13 +233,13 @@ static int disconnect_helper(struct transport *transport)
                close(data->helper->in);
                close(data->helper->out);
                fclose(data->out);
-               finish_command(data->helper);
+               res = finish_command(data->helper);
                free((char *)data->helper->argv[0]);
                free(data->helper->argv);
                free(data->helper);
                data->helper = NULL;
        }
-       return 0;
+       return res;
 }
 
 static const char *unsupported_options[] = {
@@ -299,12 +317,13 @@ static void standard_options(struct transport *t)
 
 static int release_helper(struct transport *transport)
 {
+       int res = 0;
        struct helper_data *data = transport->data;
        free_refspec(data->refspec_nr, data->refspecs);
        data->refspecs = NULL;
-       disconnect_helper(transport);
+       res = disconnect_helper(transport);
        free(transport->data);
-       return 0;
+       return res;
 }
 
 static int fetch_with_fetch(struct transport *transport,
@@ -362,10 +381,9 @@ static int get_importer(struct transport *transport, struct child_process *fasti
 
 static int get_exporter(struct transport *transport,
                        struct child_process *fastexport,
-                       const char *export_marks,
-                       const char *import_marks,
                        struct string_list *revlist_args)
 {
+       struct helper_data *data = transport->data;
        struct child_process *helper = get_helper(transport);
        int argc = 0, i;
        memset(fastexport, 0, sizeof(*fastexport));
@@ -373,12 +391,13 @@ static int get_exporter(struct transport *transport,
        /* we need to duplicate helper->in because we want to use it after
         * fastexport is done with it. */
        fastexport->out = dup(helper->in);
-       fastexport->argv = xcalloc(4 + revlist_args->nr, sizeof(*fastexport->argv));
+       fastexport->argv = xcalloc(5 + revlist_args->nr, sizeof(*fastexport->argv));
        fastexport->argv[argc++] = "fast-export";
-       if (export_marks)
-               fastexport->argv[argc++] = export_marks;
-       if (import_marks)
-               fastexport->argv[argc++] = import_marks;
+       fastexport->argv[argc++] = "--use-done-feature";
+       if (data->export_marks)
+               fastexport->argv[argc++] = data->export_marks;
+       if (data->import_marks)
+               fastexport->argv[argc++] = data->import_marks;
 
        for (i = 0; i < revlist_args->nr; i++)
                fastexport->argv[argc++] = revlist_args->items[i].string;
@@ -410,8 +429,11 @@ static int fetch_with_import(struct transport *transport,
                sendline(data, &buf);
                strbuf_reset(&buf);
        }
-       disconnect_helper(transport);
-       finish_command(&fastimport);
+
+       write_constant(data->helper->in, "\n");
+
+       if (finish_command(&fastimport))
+               die("Error while running fast-import");
        free(fastimport.argv);
        fastimport.argv = NULL;
 
@@ -554,6 +576,88 @@ static int fetch(struct transport *transport,
        return -1;
 }
 
+static void push_update_ref_status(struct strbuf *buf,
+                                  struct ref **ref,
+                                  struct ref *remote_refs)
+{
+       char *refname, *msg;
+       int status;
+
+       if (!prefixcmp(buf->buf, "ok ")) {
+               status = REF_STATUS_OK;
+               refname = buf->buf + 3;
+       } else if (!prefixcmp(buf->buf, "error ")) {
+               status = REF_STATUS_REMOTE_REJECT;
+               refname = buf->buf + 6;
+       } else
+               die("expected ok/error, helper said '%s'\n", buf->buf);
+
+       msg = strchr(refname, ' ');
+       if (msg) {
+               struct strbuf msg_buf = STRBUF_INIT;
+               const char *end;
+
+               *msg++ = '\0';
+               if (!unquote_c_style(&msg_buf, msg, &end))
+                       msg = strbuf_detach(&msg_buf, NULL);
+               else
+                       msg = xstrdup(msg);
+               strbuf_release(&msg_buf);
+
+               if (!strcmp(msg, "no match")) {
+                       status = REF_STATUS_NONE;
+                       free(msg);
+                       msg = NULL;
+               }
+               else if (!strcmp(msg, "up to date")) {
+                       status = REF_STATUS_UPTODATE;
+                       free(msg);
+                       msg = NULL;
+               }
+               else if (!strcmp(msg, "non-fast forward")) {
+                       status = REF_STATUS_REJECT_NONFASTFORWARD;
+                       free(msg);
+                       msg = NULL;
+               }
+       }
+
+       if (*ref)
+               *ref = find_ref_by_name(*ref, refname);
+       if (!*ref)
+               *ref = find_ref_by_name(remote_refs, refname);
+       if (!*ref) {
+               warning("helper reported unexpected status of %s", refname);
+               return;
+       }
+
+       if ((*ref)->status != REF_STATUS_NONE) {
+               /*
+                * Earlier, the ref was marked not to be pushed, so ignore the ref
+                * status reported by the remote helper if the latter is 'no match'.
+                */
+               if (status == REF_STATUS_NONE)
+                       return;
+       }
+
+       (*ref)->status = status;
+       (*ref)->remote_status = msg;
+}
+
+static void push_update_refs_status(struct helper_data *data,
+                                   struct ref *remote_refs)
+{
+       struct strbuf buf = STRBUF_INIT;
+       struct ref *ref = remote_refs;
+       for (;;) {
+               recvline(data, &buf);
+               if (!buf.len)
+                       break;
+
+               push_update_ref_status(&buf, &ref, remote_refs);
+       }
+       strbuf_release(&buf);
+}
+
 static int push_refs_with_push(struct transport *transport,
                struct ref *remote_refs, int flags)
 {
@@ -608,76 +712,9 @@ static int push_refs_with_push(struct transport *transport,
 
        strbuf_addch(&buf, '\n');
        sendline(data, &buf);
-
-       ref = remote_refs;
-       while (1) {
-               char *refname, *msg;
-               int status;
-
-               recvline(data, &buf);
-               if (!buf.len)
-                       break;
-
-               if (!prefixcmp(buf.buf, "ok ")) {
-                       status = REF_STATUS_OK;
-                       refname = buf.buf + 3;
-               } else if (!prefixcmp(buf.buf, "error ")) {
-                       status = REF_STATUS_REMOTE_REJECT;
-                       refname = buf.buf + 6;
-               } else
-                       die("expected ok/error, helper said '%s'\n", buf.buf);
-
-               msg = strchr(refname, ' ');
-               if (msg) {
-                       struct strbuf msg_buf = STRBUF_INIT;
-                       const char *end;
-
-                       *msg++ = '\0';
-                       if (!unquote_c_style(&msg_buf, msg, &end))
-                               msg = strbuf_detach(&msg_buf, NULL);
-                       else
-                               msg = xstrdup(msg);
-                       strbuf_release(&msg_buf);
-
-                       if (!strcmp(msg, "no match")) {
-                               status = REF_STATUS_NONE;
-                               free(msg);
-                               msg = NULL;
-                       }
-                       else if (!strcmp(msg, "up to date")) {
-                               status = REF_STATUS_UPTODATE;
-                               free(msg);
-                               msg = NULL;
-                       }
-                       else if (!strcmp(msg, "non-fast forward")) {
-                               status = REF_STATUS_REJECT_NONFASTFORWARD;
-                               free(msg);
-                               msg = NULL;
-                       }
-               }
-
-               if (ref)
-                       ref = find_ref_by_name(ref, refname);
-               if (!ref)
-                       ref = find_ref_by_name(remote_refs, refname);
-               if (!ref) {
-                       warning("helper reported unexpected status of %s", refname);
-                       continue;
-               }
-
-               if (ref->status != REF_STATUS_NONE) {
-                       /*
-                        * Earlier, the ref was marked not to be pushed, so ignore the ref
-                        * status reported by the remote helper if the latter is 'no match'.
-                        */
-                       if (status == REF_STATUS_NONE)
-                               continue;
-               }
-
-               ref->status = status;
-               ref->remote_status = msg;
-       }
        strbuf_release(&buf);
+
+       push_update_refs_status(data, remote_refs);
        return 0;
 }
 
@@ -687,7 +724,6 @@ static int push_refs_with_export(struct transport *transport,
        struct ref *ref;
        struct child_process *helper, exporter;
        struct helper_data *data = transport->data;
-       char *export_marks = NULL, *import_marks = NULL;
        struct string_list revlist_args = STRING_LIST_INIT_NODUP;
        struct strbuf buf = STRBUF_INIT;
 
@@ -695,26 +731,6 @@ static int push_refs_with_export(struct transport *transport,
 
        write_constant(helper->in, "export\n");
 
-       recvline(data, &buf);
-       if (debug)
-               fprintf(stderr, "Debug: Got export_marks '%s'\n", buf.buf);
-       if (buf.len) {
-               struct strbuf arg = STRBUF_INIT;
-               strbuf_addstr(&arg, "--export-marks=");
-               strbuf_addbuf(&arg, &buf);
-               export_marks = strbuf_detach(&arg, NULL);
-       }
-
-       recvline(data, &buf);
-       if (debug)
-               fprintf(stderr, "Debug: Got import_marks '%s'\n", buf.buf);
-       if (buf.len) {
-               struct strbuf arg = STRBUF_INIT;
-               strbuf_addstr(&arg, "--import-marks=");
-               strbuf_addbuf(&arg, &buf);
-               import_marks = strbuf_detach(&arg, NULL);
-       }
-
        strbuf_reset(&buf);
 
        for (ref = remote_refs; ref; ref = ref->next) {
@@ -728,18 +744,23 @@ static int push_refs_with_export(struct transport *transport,
                        strbuf_addf(&buf, "^%s", private);
                        string_list_append(&revlist_args, strbuf_detach(&buf, NULL));
                }
+               free(private);
+
+               if (ref->deletion) {
+                       die("remote-helpers do not support ref deletion");
+               }
 
-               string_list_append(&revlist_args, ref->name);
+               if (ref->peer_ref)
+                       string_list_append(&revlist_args, ref->peer_ref->name);
 
        }
 
-       if (get_exporter(transport, &exporter,
-                        export_marks, import_marks, &revlist_args))
+       if (get_exporter(transport, &exporter, &revlist_args))
                die("Couldn't run fast-export");
 
-       data->no_disconnect_req = 1;
-       finish_command(&exporter);
-       disconnect_helper(transport);
+       if (finish_command(&exporter))
+               die("Error while running fast-export");
+       push_update_refs_status(data, remote_refs);
        return 0;
 }
 
index 3a61d821ee85a9cfb026909c6ae90def360a7681..cc616c3f991a655d10fcac15055fcdfafa8620fd 100644 (file)
@@ -1168,11 +1168,22 @@ static int verify_uptodate_1(struct cache_entry *ce,
 {
        struct stat st;
 
-       if (o->index_only || (!((ce->ce_flags & CE_VALID) || ce_skip_worktree(ce)) && (o->reset || ce_uptodate(ce))))
+       if (o->index_only)
+               return 0;
+
+       /*
+        * CE_VALID and CE_SKIP_WORKTREE cheat, we better check again
+        * if this entry is truly up-to-date because this file may be
+        * overwritten.
+        */
+       if ((ce->ce_flags & CE_VALID) || ce_skip_worktree(ce))
+               ; /* keep checking */
+       else if (o->reset || ce_uptodate(ce))
                return 0;
 
        if (!lstat(ce->name, &st)) {
-               unsigned changed = ie_match_stat(o->src_index, ce, &st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE);
+               int flags = CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE;
+               unsigned changed = ie_match_stat(o->src_index, ce, &st, flags);
                if (!changed)
                        return 0;
                /*