Code

Merge branch 'sp/maint-bash-completion-optim'
authorJunio C Hamano <gitster@pobox.com>
Tue, 15 Jul 2008 06:36:08 +0000 (23:36 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 15 Jul 2008 06:36:08 +0000 (23:36 -0700)
* sp/maint-bash-completion-optim:
  bash completion: Resolve git show ref:path<tab> losing ref: portion
  bash completion: Append space after file names have been completed

354 files changed:
.gitignore
Documentation/RelNotes-1.5.6.3.txt
Documentation/RelNotes-1.6.0.txt [new file with mode: 0644]
Documentation/SubmittingPatches
Documentation/asciidoc.conf
Documentation/config.txt
Documentation/diff-options.txt
Documentation/fetch-options.txt
Documentation/git-add.txt
Documentation/git-am.txt
Documentation/git-annotate.txt
Documentation/git-apply.txt
Documentation/git-archimport.txt
Documentation/git-archive.txt
Documentation/git-bisect.txt
Documentation/git-blame.txt
Documentation/git-branch.txt
Documentation/git-bundle.txt
Documentation/git-cat-file.txt
Documentation/git-check-attr.txt
Documentation/git-check-ref-format.txt
Documentation/git-checkout-index.txt
Documentation/git-checkout.txt
Documentation/git-cherry-pick.txt
Documentation/git-cherry.txt
Documentation/git-citool.txt
Documentation/git-clean.txt
Documentation/git-clone.txt
Documentation/git-commit-tree.txt
Documentation/git-commit.txt
Documentation/git-config.txt
Documentation/git-count-objects.txt
Documentation/git-cvsexportcommit.txt
Documentation/git-cvsimport.txt
Documentation/git-cvsserver.txt
Documentation/git-daemon.txt
Documentation/git-describe.txt
Documentation/git-diff-files.txt
Documentation/git-diff-index.txt
Documentation/git-diff-tree.txt
Documentation/git-diff.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-fmt-merge-msg.txt
Documentation/git-for-each-ref.txt
Documentation/git-format-patch.txt
Documentation/git-fsck-objects.txt
Documentation/git-fsck.txt
Documentation/git-gc.txt
Documentation/git-get-tar-commit-id.txt
Documentation/git-grep.txt
Documentation/git-gui.txt
Documentation/git-hash-object.txt
Documentation/git-help.txt
Documentation/git-http-fetch.txt
Documentation/git-http-push.txt
Documentation/git-imap-send.txt
Documentation/git-index-pack.txt
Documentation/git-init-db.txt
Documentation/git-init.txt
Documentation/git-instaweb.txt
Documentation/git-log.txt
Documentation/git-lost-found.txt
Documentation/git-ls-files.txt
Documentation/git-ls-remote.txt
Documentation/git-ls-tree.txt
Documentation/git-mailinfo.txt
Documentation/git-mailsplit.txt
Documentation/git-merge-base.txt
Documentation/git-merge-file.txt
Documentation/git-merge-index.txt
Documentation/git-merge-one-file.txt
Documentation/git-merge-tree.txt
Documentation/git-merge.txt
Documentation/git-mergetool.txt
Documentation/git-mktag.txt
Documentation/git-mktree.txt
Documentation/git-mv.txt
Documentation/git-name-rev.txt
Documentation/git-pack-objects.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-quiltimport.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.txt
Documentation/git-repack.txt
Documentation/git-repo-config.txt
Documentation/git-request-pull.txt
Documentation/git-rerere.txt
Documentation/git-reset.txt
Documentation/git-rev-list.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-setup.txt
Documentation/git-shell.txt
Documentation/git-shortlog.txt
Documentation/git-show-branch.txt
Documentation/git-show-index.txt
Documentation/git-show-ref.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-tag.txt
Documentation/git-tar-tree.txt
Documentation/git-unpack-file.txt
Documentation/git-unpack-objects.txt
Documentation/git-update-index.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/git.txt
Documentation/gitattributes.txt
Documentation/gitcli.txt
Documentation/gitcore-tutorial.txt
Documentation/gitcvs-migration.txt
Documentation/gitdiffcore.txt
Documentation/gitglossary.txt
Documentation/githooks.txt
Documentation/gitignore.txt
Documentation/gitk.txt
Documentation/gitrepository-layout.txt
Documentation/gittutorial-2.txt
Documentation/gittutorial.txt
Documentation/howto/update-hook-example.txt
Documentation/i18n.txt
Documentation/install-doc-quick.sh
Documentation/merge-options.txt
Documentation/pull-fetch-param.txt
Documentation/rev-list-options.txt
Documentation/urls-remotes.txt
Documentation/user-manual.txt
GIT-VERSION-GEN
INSTALL
Makefile
RelNotes
abspath.c [new file with mode: 0644]
archive-tar.c
archive-zip.c
archive.c
archive.h
builtin-apply.c
builtin-blame.c
builtin-branch.c
builtin-checkout.c
builtin-clone.c
builtin-commit-tree.c
builtin-commit.c
builtin-config.c
builtin-fast-export.c
builtin-fetch-pack.c
builtin-fsck.c
builtin-mailinfo.c
builtin-mailsplit.c
builtin-pack-objects.c
builtin-pack-refs.c
builtin-reflog.c
builtin-rerere.c
builtin-rev-list.c
builtin-revert.c
builtin-shortlog.c
builtin-unpack-objects.c
builtin-update-ref.c
builtin-verify-pack.c
bundle.c
cache.h
check_bindir [new file with mode: 0755]
compat/fnmatch.c [new file with mode: 0644]
compat/fnmatch.h [new file with mode: 0644]
compat/mingw.c [new file with mode: 0644]
compat/mingw.h [new file with mode: 0644]
compat/regex.c [new file with mode: 0644]
compat/regex.h [new file with mode: 0644]
compat/snprintf.c
config.c
config.mak.in
connect.c
contrib/completion/git-completion.bash
contrib/examples/git-remote.perl
contrib/fast-import/git-p4
contrib/fast-import/import-zips.py [new file with mode: 0755]
contrib/hg-to-git/hg-to-git.py
contrib/thunderbird-patch-inline/README [new file with mode: 0644]
contrib/thunderbird-patch-inline/appp.sh [new file with mode: 0755]
daemon.c
date.c
decorate.c
diff.c
environment.c
exec_cmd.c
git-add--interactive.perl
git-am.sh
git-compat-util.h
git-gui/git-gui.sh
git-gui/lib/diff.tcl
git-merge-stupid.sh [deleted file]
git-mergetool.sh
git-rebase--interactive.sh
git-repack.sh
git-request-pull.sh
git-send-email.perl
git-sh-setup.sh
git-stash.sh
git-submodule.sh
git-svn.perl
git.c
git.spec.in
gitweb/INSTALL
gitweb/README
gitweb/gitweb.perl
help.c
http-push.c
http-walker.c
index-pack.c
pack-check.c
pack-refs.c [new file with mode: 0644]
pack-refs.h [new file with mode: 0644]
pack-revindex.c
pack-revindex.h
pack-write.c
pack.h
pager.c
parse-options.c
parse-options.h
path.c
perl/Git.pm
quote.c
receive-pack.c
refs.c
remote.c
remote.h
revision.c
revision.h
run-command.c
run-command.h
setup.c
sha1_file.c
shell.c
show-index.c
t/.gitattributes
t/.gitignore
t/Makefile
t/README
t/aggregate-results.sh [new file with mode: 0755]
t/lib-httpd.sh
t/lib-httpd/apache.conf
t/t0000-basic.sh
t/t0004-unwritable.sh
t/t0060-path-utils.sh [new file with mode: 0755]
t/t1301-shared-repo.sh
t/t1400-update-ref.sh
t/t1502-rev-parse-parseopt.sh
t/t1504-ceiling-dirs.sh [new file with mode: 0755]
t/t3404-rebase-interactive.sh
t/t3503-cherry-pick-root.sh [new file with mode: 0755]
t/t3701-add-interactive.sh
t/t3800-mktag.sh
t/t3903-stash.sh
t/t4014-format-patch.sh
t/t4015-diff-whitespace.sh
t/t4016-diff-quote.sh
t/t4017-diff-retval.sh
t/t4100-apply-stat.sh
t/t4100/t-apply-8.expect [new file with mode: 0644]
t/t4100/t-apply-8.patch [new file with mode: 0644]
t/t4100/t-apply-9.expect [new file with mode: 0644]
t/t4100/t-apply-9.patch [new file with mode: 0644]
t/t4109-apply-multifrag.sh
t/t4109/patch1.patch [new file with mode: 0644]
t/t4109/patch2.patch [new file with mode: 0644]
t/t4109/patch3.patch [new file with mode: 0644]
t/t4109/patch4.patch [new file with mode: 0644]
t/t4112-apply-renames.sh
t/t4119-apply-config.sh
t/t4127-apply-same-fn.sh [new file with mode: 0755]
t/t4128-apply-root.sh [new file with mode: 0755]
t/t4150-am.sh
t/t4200-rerere.sh
t/t5000-tar-tree.sh
t/t5302-pack-index.sh
t/t5303-pack-corruption-resilience.sh [new file with mode: 0755]
t/t5515-fetch-merge-logic.sh
t/t5540-http-push.sh
t/t6008-rev-list-submodule.sh
t/t6011-rev-list-with-bad-commit.sh [new file with mode: 0755]
t/t6040-tracking-info.sh [new file with mode: 0755]
t/t6300-for-each-ref.sh
t/t7502-status.sh
t/t7701-repack-unpack-unreachable.sh
t/t9100-git-svn-basic.sh
t/t9106-git-svn-dcommit-clobber-series.sh
t/t9110-git-svn-use-svm-props.sh
t/t9113-git-svn-dcommit-new-file.sh
t/t9301-fast-export.sh
t/t9700-perl-git.sh [new file with mode: 0755]
t/t9700/test.pl [new file with mode: 0755]
t/test-lib.sh
templates/Makefile
templates/hooks--applypatch-msg [deleted file]
templates/hooks--applypatch-msg.sample [new file with mode: 0755]
templates/hooks--commit-msg [deleted file]
templates/hooks--commit-msg.sample [new file with mode: 0755]
templates/hooks--post-commit [deleted file]
templates/hooks--post-commit.sample [new file with mode: 0755]
templates/hooks--post-receive [deleted file]
templates/hooks--post-receive.sample [new file with mode: 0755]
templates/hooks--post-update [deleted file]
templates/hooks--post-update.sample [new file with mode: 0755]
templates/hooks--pre-applypatch [deleted file]
templates/hooks--pre-applypatch.sample [new file with mode: 0755]
templates/hooks--pre-commit [deleted file]
templates/hooks--pre-commit.sample [new file with mode: 0755]
templates/hooks--pre-rebase [deleted file]
templates/hooks--pre-rebase.sample [new file with mode: 0755]
templates/hooks--prepare-commit-msg [deleted file]
templates/hooks--prepare-commit-msg.sample [new file with mode: 0755]
templates/hooks--update [deleted file]
templates/hooks--update.sample [new file with mode: 0755]
test-absolute-path.c [deleted file]
test-path-utils.c [new file with mode: 0644]
transport.c
upload-pack.c
wrapper.c [new file with mode: 0644]
write_or_die.c
ws.c
wt-status.c
wt-status.h

index 4ff2fec2785d21055bdcb5d9661d5090624b92da..a213e8e25bb2442326e86cbfb9ef56319f482869 100644 (file)
@@ -75,7 +75,6 @@ git-merge-one-file
 git-merge-ours
 git-merge-recursive
 git-merge-resolve
-git-merge-stupid
 git-merge-subtree
 git-mergetool
 git-mktag
@@ -142,7 +141,6 @@ git-write-tree
 git-core-*/?*
 gitk-wish
 gitweb/gitweb.cgi
-test-absolute-path
 test-chmtime
 test-date
 test-delta
@@ -150,6 +148,7 @@ test-dump-cache-tree
 test-genrandom
 test-match-trees
 test-parse-options
+test-path-utils
 test-sha1
 common-cmds.h
 *.tar.gz
index dd0559b64a07e6ba010374d49bb19cf3b1169142..942611299d59abd4bdd820e1258662067a304d62 100644 (file)
@@ -4,8 +4,16 @@ GIT v1.5.6.3 Release Notes
 Fixes since v1.5.6.2
 --------------------
 
+* Setting core.sharerepository to traditional "true" value was supposed to make
+  the repository group writable but should not affect permission for others.
+  However, since 1.5.6, it was broken to drop permission for others when umask is
+  022, making the repository unreadable by others.
+
 * Setting GIT_TRACE will report spawning of external process via run_command().
 
+* Using an object with very deep delta chain pinned memory needed for extracting
+  intermediate base objects unnecessarily long, leading to excess memory usage.
+
 * Bash completion script did not notice '--' marker on the command
   line and tried the relatively slow "ref completion" even when
   completing arguments after one.
@@ -14,6 +22,12 @@ Fixes since v1.5.6.2
   tree file for it confused "racy-git avoidance" logic into thinking
   that the path is now unchanged.
 
+* The section that describes attributes related to git-archive were placed
+  in a wrong place in the gitattributes(5) manual page.
+
+* "git am" was not helpful to the users when it detected that the committer
+  information is not set up properly yet.
+
 * "git clone" had a leftover debugging fprintf().
 
 * "git clone -q" was not quiet enough as it used to and gave object count
@@ -23,8 +37,10 @@ Fixes since v1.5.6.2
   good thing if the remote side is well packed but otherwise not,
   especially for a project that is not really big.
 
-* The section that describes attributes related to git-archive were placed
-  in a wrong place in the gitattributes(5) manual page.
+* "git daemon" used to call syslog() from a signal handler, which
+  could raise signals of its own but generally is not reentrant.  This
+  was fixed by restructuring the code to report syslog() after the handler
+  returns.
 
 * When "git push" tries to remove a remote ref, and corresponding
   tracking ref is missing, we used to report error (i.e. failure to
@@ -34,9 +50,3 @@ Fixes since v1.5.6.2
   MIME multipart mail correctly.
 
 Contains other various documentation fixes.
-
---
-exec >/var/tmp/1
-O=v1.5.6.2-23-ge965647
-echo O=$(git describe maint)
-git shortlog --no-merges $O..maint
diff --git a/Documentation/RelNotes-1.6.0.txt b/Documentation/RelNotes-1.6.0.txt
new file mode 100644 (file)
index 0000000..9125ee0
--- /dev/null
@@ -0,0 +1,190 @@
+GIT v1.6.0 Release Notes
+========================
+
+User visible changes
+--------------------
+
+With the default Makefile settings, most of the programs are now
+installed outside your $PATH, except for "git", "gitk", "git-gui" and
+some server side programs that need to be accessible for technical
+reasons.  Invoking a git subcommand as "git-xyzzy" from the command
+line has been deprecated since early 2006 (and officially announced in
+1.5.4 release notes); use of them from your scripts after adding
+output from "git --exec-path" to the $PATH is still supported in this
+release, but users are again strongly encouraged to adjust their
+scripts to use "git xyzzy" form, as we will stop installing
+"git-xyzzy" hardlinks for built-in commands in later releases.
+
+Source changes needed for porting to MinGW environment are now all in the
+main git.git codebase.
+
+By default, packfiles created with this version uses delta-base-offset
+encoding introduced in v1.4.4.  Pack idx files are using version 2 that
+allows larger packs and added robustness thanks to its CRC checking,
+introduced in v1.5.2.
+
+GIT_CONFIG, which was only documented as affecting "git config", but
+actually affected all git commands, now only affects "git config".
+GIT_LOCAL_CONFIG, also only documented as affecting "git config" and
+not different from GIT_CONFIG in a useful way, is removed.
+
+An ancient merge strategy "stupid" has been removed.
+
+
+Updates since v1.5.6
+--------------------
+
+(subsystems)
+
+* git-p4 in contrib learned "allowSubmit" configuration to control on
+  which branch to allow "submit" subcommand.
+
+* git-gui learned to stage changes per-line.
+
+(portability)
+
+* Changes for MinGW port have been merged, thanks to Johannes Sixt and
+  gangs.
+
+* Sample hook scripts shipped in templates/ are now suffixed with
+  *.sample.  We used to prevent them from triggering by default by
+  relying on the fact that we install them as unexecutable, but on
+  some filesystems this approach does not work.  Instead of running
+  "chmod +x" on them, the users who want to activate these samples
+  as-is can now rename them dropping *.sample suffix.
+
+* perl's in-place edit (-i) does not work well without backup files on Windows;
+  some tests are rewritten to cope with this.
+
+(documentation)
+
+* Updated howto/update-hook-example
+
+* Got rid of usage of "git-foo" from the tutorial and made typography
+  more consistent.
+
+* Disambiguating "--" between revs and paths is finally documented.
+
+(performance, robustness, sanity etc.)
+
+* even more documentation pages are now accessible via "man" and "git help".
+
+* reduced excessive inlining to shrink size of the "git" binary.
+
+* verify-pack checks the object CRC when using version 2 idx files.
+
+* When an object is corrupt in a pack, the object became unusable even
+  when the same object is available in a loose form,  We now try harder to
+  fall back to these redundant objects when able.  In particular, "git
+  repack -a -f" can be used to fix such a corruption as long as necessary
+  objects are available.
+
+* git-clone does not create refs in loose form anymore (it behaves as
+  if you immediately ran git-pack-refs after cloning).  This will help
+  repositories with insanely large number of refs.
+
+* core.fsyncobjectfiles configuration can be used to ensure that the loose
+  objects created will be fsync'ed (this is only useful on filesystems
+  that does not order data writes properly).
+
+* "git commit-tree" plumbing can make Octopus with more than 16 parents.
+  "git commit" has been capable of this for quite some time.
+
+(usability, bells and whistles)
+
+* A new environment variable GIT_CEILING_DIRECTORIES can be used to stop
+  the discovery process of the toplevel of working tree; this may be useful
+  when you are working in a slow network disk and are outside any working tree,
+  as bash-completion and "git help" may still need to run in these places.
+
+* By default, stash entries never expire.  Set reflogexpire in [gc
+  "refs/stash"] to a reasonable value to get traditional auto-expiration
+  behaviour back
+
+* Longstanding latency issue with bash completion script has been
+  addressed.  This will need to be backmerged to 'maint' later.
+
+* pager.<cmd> configuration variable can be used to enable/disable the
+  default paging behaviour per command.
+
+* "git-add -i" has a new action 'e/dit' to allow you edit the patch hunk
+  manually.
+
+* git-apply can handle a patch that touches the same path more than once
+  much better than before.
+
+* git-apply can be told not to trust the line counts recorded in the input
+  patch but recount, with the new --recount option.
+
+* git-apply can be told to apply a patch to a path deeper than what the
+  patch records with --directory option.
+
+* git-archive can be told to omit certain paths from its output using
+  export-ignore attributes.
+
+* With -v option, git-branch describes the remote tracking statistics
+  similar to the way git-checkout reports by how many commits your branch
+  is ahead/behind.
+
+* git-bundle can read the revision arguments from the standard input.
+
+* git-cherry-pick can replay a root commit now.
+
+* git-clone can clone from a remote whose URL would be rewritten by
+  configuration stored in $HOME/.gitconfig now.
+
+* git-diff --check now checks leftover merge conflict markers.
+
+* When remote side used to have branch 'foo' and git-fetch finds that now
+  it has branch 'foo/bar', it refuses to lose the existing remote tracking
+  branch and its reflog.  The error message has been improved to suggest
+  pruning the remote if the user wants to proceed and get the latest set
+  of branches from the remote, including such 'foo/bar'.
+
+* fast-export learned to export and import marks file; this can be used to
+  interface with fast-import incrementally.
+
+* "git rerere" can be told to update the index with auto-reused resolution
+  with rerere.autoupdate configuration variable.
+
+* git-rev-list learned --children option to show child commits it
+  encountered during the traversal, instead of shoing parent commits.
+
+* git-send-mail can talk not just over SSL but over TLS now.
+
+* "git-stash save" learned --keep-index option.  This lets you stash away the
+  local changes and bring the changes staged in the index to your working
+  tree for examination and testing.
+
+* git-stash also learned branch subcommand to create a new branch out of
+  stashed changes.
+
+* git-status gives the remote tracking statistics similar to the way
+  git-checkout reports by how many commits your branch is ahead/behind.
+
+* You can tell "git status -u" to even more aggressively omit checking
+  untracked files with --untracked-files=no.
+
+* Original SHA-1 value for "update-ref -d" is optional now.
+
+* Error codes from gitweb are made more descriptive where possible, rather
+  than "403 forbidden" as we used to issue everywhere.
+
+(internal)
+
+
+Fixes since v1.5.6
+------------------
+
+All of the fixes in v1.5.6 maintenance series are included in
+this release, unless otherwise noted.
+
+ * "git fetch" into an empty repository used to remind the fetch will
+   be huge by saying "no common commits", but it is already known by
+   the user anyway (need to backport 8cb560f to 'maint').
+
+---
+exec >/var/tmp/1
+O=v1.5.6.3-315-g10ce020
+echo O=$(git describe refs/heads/master)
+git shortlog --no-merges $O..refs/heads/master ^refs/heads/maint
index 0e155c936c25255706bc6d47651c2b336c628417..b1164753e13dbe015d073346bc0b7c992532efe8 100644 (file)
@@ -419,6 +419,11 @@ settings but I haven't tried, yet.
        mail.identity.default.compose_html      => false
        mail.identity.id?.compose_html          => false
 
+(Lukas Sandström)
+
+There is a script in contrib/thunderbird-patch-inline which can help
+you include patches with Thunderbird in an easy way. To use it, do the
+steps above and then use the script as the external editor.
 
 Gnus
 ----
index 10c1a151a4c38fa594bd83f124f4b654dcfd11e3..40d43b78ee9d6c3827bcf631c1f41f54d0e3dfbc 100644 (file)
@@ -8,6 +8,7 @@
 # the command.
 
 [attributes]
+asterisk=&#42;
 plus=&#43;
 caret=&#94;
 startsb=&#91;
index 5331b450ea051334d53ce3f1e727e33def2ea2cf..e7848055a90c38f48ad7180cb538d0b00e482710 100644 (file)
@@ -63,7 +63,7 @@ The values following the equals sign in variable assign are all either
 a string, an integer, or a boolean.  Boolean values may be given as yes/no,
 0/1 or true/false.  Case is not significant in boolean values, when
 converting value to the canonical form using '--bool' type specifier;
-`git-config` will ensure that the output is "true" or "false".
+'git-config' will ensure that the output is "true" or "false".
 
 String values may be entirely or partially enclosed in double quotes.
 You need to enclose variable value in double quotes if you want to
@@ -118,8 +118,8 @@ core.fileMode::
        See linkgit:git-update-index[1]. True by default.
 
 core.quotepath::
-       The commands that output paths (e.g. `ls-files`,
-       `diff`), when not given the `-z` option, will quote
+       The commands that output paths (e.g. 'ls-files',
+       'diff'), when not given the `-z` option, will quote
        "unusual" characters in the pathname by enclosing the
        pathname in a double-quote pair and with backslashes the
        same way strings in C source code are quoted.  If this
@@ -356,8 +356,8 @@ core.pager::
 
 core.whitespace::
        A comma separated list of common whitespace problems to
-       notice.  `git diff` will use `color.diff.whitespace` to
-       highlight them, and `git apply --whitespace=error` will
+       notice.  'git-diff' will use `color.diff.whitespace` to
+       highlight them, and 'git-apply --whitespace=error' will
        consider them as errors:
 +
 * `trailing-space` treats trailing whitespaces at the end of the line
@@ -372,6 +372,14 @@ core.whitespace::
   does not trigger if the character before such a carriage-return
   is not a whitespace (not enabled by default).
 
+core.fsyncobjectfiles::
+       This boolean will enable 'fsync()' when writing object files.
++
+This is a total waste of time and effort on a filesystem that orders
+data writes properly, but can be useful for filesystems that do not use
+journalling (traditional UNIX filesystems) or that only journal metadata
+and not file contents (OS X's HFS+, or Linux ext3 with "data=writeback").
+
 alias.*::
        Command aliases for the linkgit:git[1] command wrapper - e.g.
        after defining "alias.last = cat-file commit HEAD", the invocation
@@ -388,11 +396,11 @@ it will be treated as a shell command.  For example, defining
 "gitk --all --not ORIG_HEAD".
 
 apply.whitespace::
-       Tells `git-apply` how to handle whitespaces, in the same way
+       Tells 'git-apply' how to handle whitespaces, in the same way
        as the '--whitespace' option. See linkgit:git-apply[1].
 
 branch.autosetupmerge::
-       Tells `git-branch` and `git-checkout` to setup new branches
+       Tells 'git-branch' and 'git-checkout' to setup new branches
        so that linkgit:git-pull[1] will appropriately merge from the
        starting point branch. Note that even if this option is not set,
        this behavior can be chosen per-branch using the `--track`
@@ -403,7 +411,7 @@ branch.autosetupmerge::
        branch. This option defaults to true.
 
 branch.autosetuprebase::
-       When a new branch is created with `git-branch` or `git-checkout`
+       When a new branch is created with 'git-branch' or 'git-checkout'
        that tracks another branch, this variable tells git to set
        up pull to rebase instead of merge (see "branch.<name>.rebase").
        When `never`, rebase is never automatically set to true.
@@ -418,20 +426,20 @@ branch.autosetuprebase::
        This option defaults to never.
 
 branch.<name>.remote::
-       When in branch <name>, it tells `git fetch` which remote to fetch.
-       If this option is not given, `git fetch` defaults to remote "origin".
+       When in branch <name>, it tells 'git-fetch' which remote to fetch.
+       If this option is not given, 'git-fetch' defaults to remote "origin".
 
 branch.<name>.merge::
-       When in branch <name>, it tells `git fetch` the default
+       When in branch <name>, it tells 'git-fetch' the default
        refspec to be marked for merging in FETCH_HEAD. The value is
        handled like the remote part of a refspec, and must match a
        ref which is fetched from the remote given by
        "branch.<name>.remote".
-       The merge information is used by `git pull` (which at first calls
-       `git fetch`) to lookup the default branch for merging. Without
-       this option, `git pull` defaults to merge the first refspec fetched.
+       The merge information is used by 'git-pull' (which at first calls
+       'git-fetch') to lookup the default branch for merging. Without
+       this option, 'git-pull' defaults to merge the first refspec fetched.
        Specify multiple values to get an octopus merge.
-       If you wish to setup `git pull` so that it merges into <name> from
+       If you wish to setup 'git-pull' so that it merges into <name> from
        another branch in the local repository, you can point
        branch.<name>.merge to the desired branch, and use the special setting
        `.` (a period) for branch.<name>.remote.
@@ -500,12 +508,12 @@ color.diff.<slot>::
 
 color.interactive::
        When set to `always`, always use colors for interactive prompts
-       and displays (such as those used by "git add --interactive").
+       and displays (such as those used by "git-add --interactive").
        When false (or `never`), never.  When set to `true` or `auto`, use
        colors only when the output is to the terminal. Defaults to false.
 
 color.interactive.<slot>::
-       Use customized color for `git add --interactive`
+       Use customized color for 'git-add --interactive'
        output. `<slot>` may be `prompt`, `header`, or `help`, for
        three distinct types of normal output from interactive
        programs.  The values of these variables may be specified as
@@ -542,14 +550,14 @@ color.ui::
        take precedence over this setting. Defaults to false.
 
 diff.autorefreshindex::
-       When using `git diff` to compare with work tree
+       When using 'git-diff' to compare with work tree
        files, do not consider stat-only change as changed.
        Instead, silently run `git update-index --refresh` to
        update the cached stat information for paths whose
        contents in the work tree match the contents in the
        index.  This option defaults to true.  Note that this
-       affects only `git diff` Porcelain, and not lower level
-       `diff` commands, such as `git diff-files`.
+       affects only 'git-diff' Porcelain, and not lower level
+       'diff' commands, such as 'git-diff-files'.
 
 diff.external::
        If this config variable is set, diff generation is not
@@ -560,7 +568,7 @@ diff.external::
 
 diff.renameLimit::
        The number of files to consider when performing the copy/rename
-       detection; equivalent to the git diff option '-l'.
+       detection; equivalent to the 'git-diff' option '-l'.
 
 diff.renames::
        Tells git to detect renames.  If set to any boolean value, it
@@ -600,7 +608,7 @@ format.pretty::
 
 gc.aggressiveWindow::
        The window size parameter used in the delta compression
-       algorithm used by 'git gc --aggressive'.  This defaults
+       algorithm used by 'git-gc --aggressive'.  This defaults
        to 10.
 
 gc.auto::
@@ -617,39 +625,44 @@ gc.autopacklimit::
        default value is 50.  Setting this to 0 disables it.
 
 gc.packrefs::
-       `git gc` does not run `git pack-refs` in a bare repository by
+       'git-gc' does not run `git pack-refs` in a bare repository by
        default so that older dumb-transport clients can still fetch
-       from the repository.  Setting this to `true` lets `git
-       gc` to run `git pack-refs`.  Setting this to `false` tells
-       `git gc` never to run `git pack-refs`. The default setting is
+       from the repository.  Setting this to `true` lets 'git-gc'
+       to run `git pack-refs`.  Setting this to `false` tells
+       'git-gc' never to run `git pack-refs`. The default setting is
        `notbare`. Enable it only when you know you do not have to
        support such clients.  The default setting will change to `true`
        at some stage, and setting this to `false` will continue to
-       prevent `git pack-refs` from being run from `git gc`.
+       prevent `git pack-refs` from being run from 'git-gc'.
 
 gc.pruneexpire::
-       When `git gc` is run, it will call `prune --expire 2.weeks.ago`.
+       When 'git-gc' is run, it will call 'prune --expire 2.weeks.ago'.
        Override the grace period with this config variable.
 
 gc.reflogexpire::
-       `git reflog expire` removes reflog entries older than
+       'git-reflog expire' removes reflog entries older than
        this time; defaults to 90 days.
 
 gc.reflogexpireunreachable::
-       `git reflog expire` removes reflog entries older than
+       'git-reflog expire' removes reflog entries older than
        this time and are not reachable from the current tip;
        defaults to 30 days.
 
 gc.rerereresolved::
        Records of conflicted merge you resolved earlier are
-       kept for this many days when `git rerere gc` is run.
+       kept for this many days when 'git-rerere gc' is run.
        The default is 60 days.  See linkgit:git-rerere[1].
 
 gc.rerereunresolved::
        Records of conflicted merge you have not resolved are
-       kept for this many days when `git rerere gc` is run.
+       kept for this many days when 'git-rerere gc' is run.
        The default is 15 days.  See linkgit:git-rerere[1].
 
+rerere.autoupdate::
+       When set to true, `git-rerere` updates the index with the
+       resulting contents after it cleanly resolves conflicts using
+       previously recorded resolution.  Defaults to false.
+
 rerere.enabled::
        Activate recording of resolved conflicts, so that identical
        conflict hunks can be resolved automatically, should they
@@ -672,7 +685,7 @@ gitcvs.usecrlfattr
        treat it as text. If `crlf` is explicitly unset, the file
        will be set with '-kb' mode, which supresses any newline munging
        the client might otherwise do. If `crlf` is not specified,
-       then 'gitcvs.allbinary' is used. See linkgit:gitattribute[5].
+       then 'gitcvs.allbinary' is used. See linkgit:gitattributes[5].
 
 gitcvs.allbinary::
        This is used if 'gitcvs.usecrlfattr' does not resolve
@@ -813,7 +826,7 @@ i18n.commitEncoding::
 
 i18n.logOutputEncoding::
        Character encoding the commit messages are converted to when
-       running `git-log` and friends.
+       running 'git-log' and friends.
 
 instaweb.browser::
        Specify the program that will be used to browse your working
@@ -836,7 +849,7 @@ instaweb.port::
 
 log.date::
        Set default date-time mode for the log command. Setting log.date
-       value is similar to using git log's --date option. The value is one of
+       value is similar to using 'git-log'\'s --date option. The value is one of the
        following alternatives: {relative,local,default,iso,rfc,short}.
        See linkgit:git-log[1].
 
@@ -937,9 +950,17 @@ pack.indexVersion::
        legacy pack index used by Git versions prior to 1.5.2, and 2 for
        the new pack index with capabilities for packs larger than 4 GB
        as well as proper protection against the repacking of corrupted
-       packs.  Version 2 is selected and this config option ignored
-       whenever the corresponding pack is larger than 2 GB.  Otherwise
-       the default is 1.
+       packs.  Version 2 is the default.  Note that version 2 is enforced
+       and this config option ignored whenever the corresponding pack is
+       larger than 2 GB.
++
+If you have an old git that does not understand the version 2 `{asterisk}.idx` file,
+cloning or fetching over a non native protocol (e.g. "http" and "rsync")
+that will copy both `{asterisk}.pack` file and corresponding `{asterisk}.idx` file from the
+other side may give you a repository that cannot be accessed with your
+older version of git. If the `{asterisk}.pack` file is smaller than 2 GB, however,
+you can use linkgit:git-index-pack[1] on the *.pack file to regenerate
+the `{asterisk}.idx` file.
 
 pack.packSizeLimit::
        The default maximum size of a pack.  This setting only affects
@@ -996,12 +1017,12 @@ remotes.<group>::
        <group>".  See linkgit:git-remote[1].
 
 repack.usedeltabaseoffset::
-       Allow linkgit:git-repack[1] to create packs that uses
-       delta-base offset.  Defaults to false.
-
-show.difftree::
-       The default linkgit:git-diff-tree[1] arguments to be used
-       for linkgit:git-show[1].
+       By default, linkgit:git-repack[1] creates packs that use
+       delta-base offset. If you need to share your repository with
+       git older than version 1.4.4, either directly or via a dumb
+       protocol such as http, then you need to set this option to
+       "false" and repack. Access from old git versions over the
+       native protocol are unaffected by this option.
 
 showbranch.default::
        The default set of branches for linkgit:git-show-branch[1].
@@ -1013,6 +1034,25 @@ status.relativePaths::
        relative to the repository root (this was the default for git
        prior to v1.5.4).
 
+status.showUntrackedFiles::
+       By default, linkgit:git-status[1] and linkgit:git-commit[1] show
+       files which are not currently tracked by Git. Directories which
+       contain only untracked files, are shown with the directory name
+       only. Showing untracked files means that Git needs to lstat() all
+       all the files in the whole repository, which might be slow on some
+       systems. So, this variable controls how the commands displays
+       the untracked files. Possible values are:
++
+--
+       - 'no'     - Show no untracked files
+       - 'normal' - Shows untracked files and directories
+       - 'all'    - Shows also individual files in untracked directories.
+--
++
+If this variable is not specified, it defaults to 'normal'.
+This variable can be overridden with the -u|--untracked-files option
+of linkgit:git-status[1] and linkgit:git-commit[1].
+
 tar.umask::
        This variable can be used to restrict the permission bits of
        tar archive entries.  The default is 0002, which turns off the
@@ -1048,10 +1088,6 @@ user.signingkey::
        unchanged to gpg's --local-user parameter, so you may specify a key
        using any method that gpg supports.
 
-whatchanged.difftree::
-       The default linkgit:git-diff-tree[1] arguments to be used
-       for linkgit:git-whatchanged[1].
-
 imap::
        The configuration variables in the 'imap' section are described
        in linkgit:git-imap-send[1].
index 572154834b35675ccf56920efd540bf872d1ab25..cba90fd27c6a1baaca884328e96adc8a6da8fc36 100644 (file)
@@ -241,4 +241,4 @@ endif::git-format-patch[]
        Do not show any source or destination prefix.
 
 For more detailed explanation on these common options, see also
-linkgit:gitdiffcore[7][diffcore documentation].
+linkgit:gitdiffcore[7].
index 85c87180db59906f5401eafbe6460f49a60ee9dc..d313795fdbc420e3395adc42aebe82fabda037d4 100644 (file)
@@ -21,7 +21,7 @@
 
 -f::
 --force::
-       When `git-fetch` is used with `<rbranch>:<lbranch>`
+       When 'git-fetch' is used with `<rbranch>:<lbranch>`
        refspec, it refuses to update the local branch
        `<lbranch>` unless the remote branch `<rbranch>` it
        fetches is a descendant of `<lbranch>`.  This option
@@ -53,10 +53,10 @@ endif::git-pull[]
 
 -u::
 --update-head-ok::
-       By default `git-fetch` refuses to update the head which
+       By default 'git-fetch' refuses to update the head which
        corresponds to the current branch.  This flag disables the
-       check.  This is purely for the internal use for `git-pull`
-       to communicate with `git-fetch`, and unless you are
+       check.  This is purely for the internal use for 'git-pull'
+       to communicate with 'git-fetch', and unless you are
        implementing your own Porcelain you are not supposed to
        use it.
 
index b8e3fa67598037bc5d0de30818b977048bbada72..46dd56c12a8167c3861a304e820c664e3c92ca4f 100644 (file)
@@ -8,7 +8,7 @@ git-add - Add file contents to the index
 SYNOPSIS
 --------
 [verse]
-'git-add' [-n] [-v] [--force | -f] [--interactive | -i] [--patch | -p]
+'git add' [-n] [-v] [--force | -f] [--interactive | -i] [--patch | -p]
          [--update | -u] [--refresh] [--ignore-errors] [--]
          <filepattern>...
 
@@ -107,7 +107,7 @@ Configuration
 The optional configuration variable 'core.excludesfile' indicates a path to a
 file containing patterns of file names to exclude from git-add, similar to
 $GIT_DIR/info/exclude.  Patterns in the exclude file are used in addition to
-those in info/exclude.  See linkgit:gitrepository-layout[5][repository layout].
+those in info/exclude.  See linkgit:gitrepository-layout[5].
 
 
 EXAMPLES
@@ -236,6 +236,7 @@ patch::
        k - leave this hunk undecided, see previous undecided hunk
        K - leave this hunk undecided, see previous hunk
        s - split the current hunk into smaller hunks
+       e - manually edit the current hunk
        ? - print help
 +
 After deciding the fate for all hunks, if there is any hunk
index 46544a07694a90db908729b6badf92370f37226b..eeb23b25b0d70c4ccc3eb9d091971b1f20ad4b4b 100644 (file)
@@ -9,11 +9,11 @@ git-am - Apply a series of patches from a mailbox
 SYNOPSIS
 --------
 [verse]
-'git-am' [--signoff] [--keep] [--utf8 | --no-utf8]
+'git am' [--signoff] [--keep] [--utf8 | --no-utf8]
          [--3way] [--interactive] [--binary]
          [--whitespace=<option>] [-C<n>] [-p<n>]
-         <mbox>|<Maildir>...
-'git-am' [--skip | --resolved]
+        [<mbox> | <Maildir>...]
+'git am' (--skip | --resolved)
 
 DESCRIPTION
 -----------
@@ -35,11 +35,11 @@ OPTIONS
 
 -k::
 --keep::
-       Pass `-k` flag to `git-mailinfo` (see linkgit:git-mailinfo[1]).
+       Pass `-k` flag to 'git-mailinfo' (see linkgit:git-mailinfo[1]).
 
 -u::
 --utf8::
-       Pass `-u` flag to `git-mailinfo` (see linkgit:git-mailinfo[1]).
+       Pass `-u` flag to 'git-mailinfo' (see linkgit:git-mailinfo[1]).
        The proposed commit log message taken from the e-mail
        is re-coded into UTF-8 encoding (configuration variable
        `i18n.commitencoding` can be used to specify project's
@@ -49,7 +49,7 @@ This was optional in prior versions of git, but now it is the
 default.   You could use `--no-utf8` to override this.
 
 --no-utf8::
-       Pass `-n` flag to `git-mailinfo` (see
+       Pass `-n` flag to 'git-mailinfo' (see
        linkgit:git-mailinfo[1]).
 
 -3::
@@ -61,17 +61,17 @@ default.   You could use `--no-utf8` to override this.
 
 -b::
 --binary::
-       Pass `--allow-binary-replacement` flag to `git-apply`
+       Pass `--allow-binary-replacement` flag to 'git-apply'
        (see linkgit:git-apply[1]).
 
 --whitespace=<option>::
-       This flag is passed to the `git-apply` (see linkgit:git-apply[1])
+       This flag is passed to the 'git-apply' (see linkgit:git-apply[1])
        program that applies
        the patch.
 
 -C<n>::
 -p<n>::
-       These flags are passed to the `git-apply` (see linkgit:git-apply[1])
+       These flags are passed to the 'git-apply' (see linkgit:git-apply[1])
        program that applies
        the patch.
 
@@ -97,7 +97,7 @@ default.   You could use `--no-utf8` to override this.
        to the screen before exiting.  This overrides the
        standard message informing you to use `--resolved`
        or `--skip` to handle the failure.  This is solely
-       for internal use between `git-rebase` and `git-am`.
+       for internal use between 'git-rebase' and 'git-am'.
 
 DISCUSSION
 ----------
index da15379ae53046b2c6384e505c9e28595171fa66..8b6b56a54409dd586047a1a6cdf1138e8bb0e77b 100644 (file)
@@ -7,7 +7,7 @@ git-annotate - Annotate file lines with commit info
 
 SYNOPSIS
 --------
-git-annotate [options] file [revision]
+'git annotate' [options] file [revision]
 
 DESCRIPTION
 -----------
index c8347637da55e32ec4c637280d7027dc8883c264..feb51f124ac8a806e65d41f6274c58de64d2991f 100644 (file)
@@ -9,16 +9,16 @@ git-apply - Apply a patch on a git index file and a working tree
 SYNOPSIS
 --------
 [verse]
-'git-apply' [--stat] [--numstat] [--summary] [--check] [--index]
+'git apply' [--stat] [--numstat] [--summary] [--check] [--index]
          [--apply] [--no-add] [--build-fake-ancestor <file>] [-R | --reverse]
          [--allow-binary-replacement | --binary] [--reject] [-z]
-         [-pNUM] [-CNUM] [--inaccurate-eof] [--cached]
+         [-pNUM] [-CNUM] [--inaccurate-eof] [--recount] [--cached]
          [--whitespace=<nowarn|warn|fix|error|error-all>]
-         [--exclude=PATH] [--verbose] [<patch>...]
+         [--exclude=PATH] [--directory=<root>] [--verbose] [<patch>...]
 
 DESCRIPTION
 -----------
-Reads supplied diff output and applies it on a git index file
+Reads supplied 'diff' output and applies it on a git index file
 and a work tree.
 
 OPTIONS
@@ -64,7 +64,7 @@ OPTIONS
        without using the working tree. This implies '--index'.
 
 --build-fake-ancestor <file>::
-       Newer git-diff output has embedded 'index information'
+       Newer 'git-diff' output has embedded 'index information'
        for each blob to help identify the original version that
        the patch applies to.  When this flag is given, and if
        the original versions of the blobs is available locally,
@@ -78,7 +78,7 @@ the information is read from the current index instead.
        Apply the patch in reverse.
 
 --reject::
-       For atomicity, linkgit:git-apply[1] by default fails the whole patch and
+       For atomicity, 'git-apply' by default fails the whole patch and
        does not touch the working tree when some of the hunks
        do not apply.  This option makes it apply
        the parts of the patch that are applicable, and leave the
@@ -102,7 +102,7 @@ the information is read from the current index instead.
        ever ignored.
 
 --unidiff-zero::
-       By default, linkgit:git-apply[1] expects that the patch being
+       By default, 'git-apply' expects that the patch being
        applied is a unified diff with at least one line of context.
        This provides good safety measures, but breaks down when
        applying a diff generated with --unified=0. To bypass these
@@ -113,7 +113,7 @@ discouraged.
 
 --apply::
        If you use any of the options marked "Turns off
-       'apply'" above, linkgit:git-apply[1] reads and outputs the
+       'apply'" above, 'git-apply' reads and outputs the
        information you asked without actually applying the
        patch.  Give this flag after those flags to also apply
        the patch.
@@ -121,7 +121,7 @@ discouraged.
 --no-add::
        When applying a patch, ignore additions made by the
        patch.  This can be used to extract the common part between
-       two files by first running `diff` on them and applying
+       two files by first running 'diff' on them and applying
        the result with this option, which would apply the
        deletion part but not addition part.
 
@@ -147,7 +147,7 @@ discouraged.
        considered whitespace errors.
 +
 By default, the command outputs warning messages but applies the patch.
-When linkgit:git-apply[1] is used for statistics and not applying a
+When `git-apply is used for statistics and not applying a
 patch, it defaults to `nowarn`.
 +
 You can use different `<action>` to control this
@@ -165,9 +165,9 @@ behavior:
 * `error-all` is similar to `error` but shows all errors.
 
 --inaccurate-eof::
-       Under certain circumstances, some versions of diff do not correctly
+       Under certain circumstances, some versions of 'diff' do not correctly
        detect a missing new-line at the end of the file. As a result, patches
-       created by such diff programs do not record incomplete lines
+       created by such 'diff' programs do not record incomplete lines
        correctly. This option adds support for applying such patches by
        working around this bug.
 
@@ -177,6 +177,19 @@ behavior:
        current patch being applied will be printed. This option will cause
        additional information to be reported.
 
+--recount::
+       Do not trust the line counts in the hunk headers, but infer them
+       by inspecting the patch (e.g. after editing the patch without
+       adjusting the hunk headers appropriately).
+
+--directory=<root>::
+       Prepend <root> to all filenames.  If a "-p" argument was passed, too,
+       it is applied before prepending the new root.
++
+For example, a patch that talks about updating `a/git-gui.sh` to `b/git-gui.sh`
+can be applied to the file in the working tree `modules/git-gui/git-gui.sh` by
+running `git apply --directory=modules/git-gui`.
+
 Configuration
 -------------
 
@@ -186,7 +199,7 @@ apply.whitespace::
 
 Submodules
 ----------
-If the patch contains any changes to submodules then linkgit:git-apply[1]
+If the patch contains any changes to submodules then 'git-apply'
 treats these changes as follows.
 
 If --index is specified (explicitly or implicitly), then the submodule
index 603117c796619ba9c1ed93ae0646bd242cbd37b2..c7a6e3ec050b7ceeec79d468b5ffa123314c8f5d 100644 (file)
@@ -9,7 +9,7 @@ git-archimport - Import an Arch repository into git
 SYNOPSIS
 --------
 [verse]
-'git-archimport' [-h] [-v] [-o] [-a] [-f] [-T] [-D depth] [-t tempdir]
+'git archimport' [-h] [-v] [-o] [-a] [-f] [-T] [-D depth] [-t tempdir]
                <archive/branch>[:<git-branch>] ...
 
 DESCRIPTION
@@ -29,17 +29,17 @@ branches that have different roots, it will refuse to run. In that case,
 edit your <archive/branch> parameters to define clearly the scope of the
 import.
 
-`git-archimport` uses `tla` extensively in the background to access the
+'git-archimport' uses `tla` extensively in the background to access the
 Arch repository.
 Make sure you have a recent version of `tla` available in the path. `tla` must
-know about the repositories you pass to `git-archimport`.
+know about the repositories you pass to 'git-archimport'.
 
-For the initial import `git-archimport` expects to find itself in an empty
+For the initial import, 'git-archimport' expects to find itself in an empty
 directory. To follow the development of a project that uses Arch, rerun
-`git-archimport` with the same parameters as the initial import to perform
+'git-archimport' with the same parameters as the initial import to perform
 incremental imports.
 
-While git-archimport will try to create sensible branch names for the
+While 'git-archimport' will try to create sensible branch names for the
 archives that it imports, it is also possible to specify git branch names
 manually.  To do so, write a git branch name after each <archive/branch>
 parameter, separated by a colon.  This way, you can shorten the Arch
@@ -84,7 +84,7 @@ OPTIONS
 
 -o::
        Use this for compatibility with old-style branch names used by
-       earlier versions of git-archimport.  Old-style branch names
+       earlier versions of 'git-archimport'.  Old-style branch names
        were category--branch, whereas new-style branch names are
        archive,category--branch--version.  In both cases, names given
        on the command-line will override the automatically-generated
index 9b5f3ae5ed8cf6b79545f09d68797490c69f6596..41cbf9c0819872a322321455b8a5cb805efcc26b 100644 (file)
@@ -9,7 +9,7 @@ git-archive - Create an archive of files from a named tree
 SYNOPSIS
 --------
 [verse]
-'git-archive' --format=<fmt> [--list] [--prefix=<prefix>/] [<extra>]
+'git archive' --format=<fmt> [--list] [--prefix=<prefix>/] [<extra>]
              [--remote=<repo> [--exec=<git-upload-archive>]] <tree-ish>
              [path...]
 
@@ -57,7 +57,7 @@ OPTIONS
 
 --exec=<git-upload-archive>::
        Used with --remote to specify the path to the
-       git-upload-archive executable on the remote side.
+       'git-upload-archive' on the remote side.
 
 <tree-ish>::
        The tree or commit to produce an archive for.
index 3ca0d330ad06e76d73657189c5f90e0994ba4505..c7981efcd9b86287bbea9ddcaf187a9bd48c77eb 100644 (file)
@@ -26,7 +26,7 @@ on the subcommand:
  git bisect log
  git bisect run <cmd>...
 
-This command uses 'git-rev-list --bisect' option to help drive the
+This command uses 'git-rev-list --bisect' to help drive the
 binary search process to find which change introduced a bug, given an
 old "good" commit object name and a later "bad" commit object name.
 
@@ -98,10 +98,10 @@ During the bisection process, you can say
 $ git bisect visualize
 ------------
 
-to see the currently remaining suspects in `gitk`.  `visualize` is a bit
+to see the currently remaining suspects in 'gitk'.  `visualize` is a bit
 too long to type and `view` is provided as a synonym.
 
-If `DISPLAY` environment variable is not set, `git log` is used
+If 'DISPLAY' environment variable is not set, 'git-log' is used
 instead.  You can even give command line options such as `-p` and
 `--stat`.
 
@@ -215,13 +215,13 @@ tweaks (e.g., s/#define DEBUG 0/#define DEBUG 1/ in a header file, or
 work around other problem this bisection is not interested in")
 applied to the revision being tested.
 
-To cope with such a situation, after the inner git-bisect finds the
+To cope with such a situation, after the inner 'git-bisect' finds the
 next revision to test, with the "run" script, you can apply that tweak
 before compiling, run the real test, and after the test decides if the
 revision (possibly with the needed tweaks) passed the test, rewind the
 tree to the pristine state.  Finally the "run" script can exit with
-the status of the real test to let "git bisect run" command loop to
-know the outcome.
+the status of the real test to let the "git bisect run" command loop to
+determine the outcome.
 
 EXAMPLES
 --------
index 8f4fb46685624d07f5940eb973a7fd03aefb5aa0..34b24a3cad2309486c06e29e0e45c429388d0319 100644 (file)
@@ -8,7 +8,7 @@ git-blame - Show what revision and author last modified each line of a file
 SYNOPSIS
 --------
 [verse]
-'git-blame' [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-p] [-w] [--incremental] [-L n,m]
+'git blame' [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-p] [-w] [--incremental] [-L n,m]
             [-S <revs-file>] [-M] [-C] [-C] [--since=<date>]
             [<rev> | --contents <file>] [--] <file>
 
@@ -21,7 +21,7 @@ last modified the line. Optionally, start annotating from the given revision.
 Also it can limit the range of lines annotated.
 
 This report doesn't tell you anything about lines which have been deleted or
-replaced; you need to use a tool such as linkgit:git-diff[1] or the "pickaxe"
+replaced; you need to use a tool such as 'git-diff' or the "pickaxe"
 interface briefly mentioned in the following paragraph.
 
 Apart from supporting file annotation, git also supports searching the
@@ -49,7 +49,7 @@ include::blame-options.txt[]
        file (see `-M`).  The first number listed is the score.
        This is the number of alphanumeric characters detected
        to be moved between or within files.  This must be above
-       a certain threshold for git-blame to consider those lines
+       a certain threshold for 'git-blame' to consider those lines
        of code to have been moved.
 
 -f::
@@ -100,7 +100,7 @@ header elements later.
 SPECIFYING RANGES
 -----------------
 
-Unlike `git-blame` and `git-annotate` in older git, the extent
+Unlike 'git-blame' and 'git-annotate' in older git, the extent
 of annotation can be limited to both line ranges and revision
 ranges.  When you are interested in finding the origin for
 ll. 40-60 for file `foo`, you can use `-L` option like these
@@ -118,7 +118,7 @@ would limit the annotation to the body of `hello` subroutine.
 
 When you are not interested in changes older than the version
 v2.6.18, or changes older than 3 weeks, you can use revision
-range specifiers  similar to `git-rev-list`:
+range specifiers  similar to 'git-rev-list':
 
        git blame v2.6.18.. -- foo
        git blame --since=3.weeks -- foo
index 0fd58083eb2afdb7fed7ebf01bab3b5e1cae1421..b3e62ed011f0a99ce3f173a3f22758edc457f72b 100644 (file)
@@ -8,12 +8,12 @@ git-branch - List, create, or delete branches
 SYNOPSIS
 --------
 [verse]
-'git-branch' [--color | --no-color] [-r | -a] [--merged | --no-merged]
+'git branch' [--color | --no-color] [-r | -a] [--merged | --no-merged]
           [-v [--abbrev=<length> | --no-abbrev]]
           [--contains <commit>]
-'git-branch' [--track | --no-track] [-l] [-f] <branchname> [<start-point>]
-'git-branch' (-m | -M) [<oldbranch>] <newbranch>
-'git-branch' (-d | -D) [-r] <branchname>...
+'git branch' [--track | --no-track] [-l] [-f] <branchname> [<start-point>]
+'git branch' (-m | -M) [<oldbranch>] <newbranch>
+'git branch' (-d | -D) [-r] <branchname>...
 
 DESCRIPTION
 -----------
@@ -37,7 +37,7 @@ working tree to it; use "git checkout <newbranch>" to switch to the
 new branch.
 
 When a local branch is started off a remote branch, git sets up the
-branch so that linkgit:git-pull[1] will appropriately merge from
+branch so that 'git-pull' will appropriately merge from
 the remote branch. This behavior may be changed via the global
 `branch.autosetupmerge` configuration flag. That setting can be
 overridden by using the `--track` and `--no-track` options.
@@ -54,7 +54,7 @@ has a reflog then the reflog will also be deleted.
 
 Use -r together with -d to delete remote-tracking branches. Note, that it
 only makes sense to delete remote-tracking branches if they no longer exist
-in remote repository or if linkgit:git-fetch[1] was configured not to fetch
+in remote repository or if 'git-fetch' was configured not to fetch
 them again. See also 'prune' subcommand of linkgit:git-remote[1] for way to
 clean up all obsolete remote-tracking branches.
 
@@ -107,14 +107,14 @@ OPTIONS
        Display the full sha1s in output listing rather than abbreviating them.
 
 --track::
-       When creating a new branch, set up configuration so that git-pull
+       When creating a new branch, set up configuration so that 'git-pull'
        will automatically retrieve data from the start point, which must be
        a branch. Use this if you always pull from the same upstream branch
        into the new branch, and if you don't want to use "git pull
        <repository> <refspec>" explicitly. This behavior is the default
        when the start point is a remote branch. Set the
        branch.autosetupmerge configuration variable to `false` if you want
-       git-checkout and git-branch to always behave as if '--no-track' were
+       'git-checkout' and 'git-branch' to always behave as if '--no-track' were
        given. Set it to `always` if you want this behavior when the
        start-point is either a local or remote branch.
 
index f6a06129abfbd79a9cbb2b7d8f2d5902923ef594..1b66ab743c64d980a43a028d57ca2f6505d97845 100644 (file)
@@ -9,10 +9,10 @@ git-bundle - Move objects and refs by archive
 SYNOPSIS
 --------
 [verse]
-'git-bundle' create <file> <git-rev-list args>
-'git-bundle' verify <file>
-'git-bundle' list-heads <file> [refname...]
-'git-bundle' unbundle <file> [refname...]
+'git bundle' create <file> <git-rev-list args>
+'git bundle' verify <file>
+'git bundle' list-heads <file> [refname...]
+'git bundle' unbundle <file> [refname...]
 
 DESCRIPTION
 -----------
@@ -21,9 +21,9 @@ Some workflows require that one or more branches of development on one
 machine be replicated on another machine, but the two machines cannot
 be directly connected so the interactive git protocols (git, ssh,
 rsync, http) cannot be used.  This command provides support for
-git-fetch and git-pull to operate by packaging objects and references
+'git-fetch' and 'git-pull' to operate by packaging objects and references
 in an archive at the originating machine, then importing those into
-another repository using linkgit:git-fetch[1] and linkgit:git-pull[1]
+another repository using 'git-fetch' and 'git-pull'
 after moving the archive by some means (i.e., by sneakernet).  As no
 direct connection between repositories exists, the user must specify a
 basis for the bundle that is held by the destination repository: the
@@ -35,14 +35,14 @@ OPTIONS
 
 create <file>::
        Used to create a bundle named 'file'.  This requires the
-       git-rev-list arguments to define the bundle contents.
+       'git-rev-list' arguments to define the bundle contents.
 
 verify <file>::
        Used to check that a bundle file is valid and will apply
        cleanly to the current repository.  This includes checks on the
        bundle format itself as well as checking that the prerequisite
        commits exist and are fully linked in the current repository.
-       git-bundle prints a list of missing commits, if any, and exits
+       'git-bundle' prints a list of missing commits, if any, and exits
        with non-zero status.
 
 list-heads <file>::
@@ -51,16 +51,15 @@ list-heads <file>::
        printed out.
 
 unbundle <file>::
-       Passes the objects in the bundle to linkgit:git-index-pack[1]
+       Passes the objects in the bundle to 'git-index-pack'
        for storage in the repository, then prints the names of all
        defined references. If a reflist is given, only references
        matching those in the given list are printed. This command is
-       really plumbing, intended to be called only by
-       linkgit:git-fetch[1].
+       really plumbing, intended to be called only by 'git-fetch'.
 
 [git-rev-list-args...]::
-       A list of arguments, acceptable to git-rev-parse and
-       git-rev-list, that specify the specific objects and references
+       A list of arguments, acceptable to 'git-rev-parse' and
+       'git-rev-list', that specify the specific objects and references
        to transport.  For example, "master~10..master" causes the
        current master reference to be packaged along with all objects
        added since its 10th ancestor commit.  There is no explicit
@@ -70,16 +69,16 @@ unbundle <file>::
 
 [refname...]::
        A list of references used to limit the references reported as
-       available. This is principally of use to git-fetch, which
+       available. This is principally of use to 'git-fetch', which
        expects to receive only those references asked for and not
-       necessarily everything in the pack (in this case, git-bundle is
-       acting like linkgit:git-fetch-pack[1]).
+       necessarily everything in the pack (in this case, 'git-bundle' is
+       acting like 'git-fetch-pack').
 
 SPECIFYING REFERENCES
 ---------------------
 
-git-bundle will only package references that are shown by
-git-show-ref: this includes heads, tags, and remote heads.  References
+'git-bundle' will only package references that are shown by
+'git-show-ref': this includes heads, tags, and remote heads.  References
 such as master~1 cannot be packaged, but are perfectly suitable for
 defining the basis.  More than one reference may be packaged, and more
 than one basis can be specified.  The objects packaged are those not
@@ -116,7 +115,7 @@ We set a tag in R1 (lastR2bundle) after the previous such transport,
 and move it afterwards to help build the bundle.
 
 ------------
-$ git-bundle create mybundle master ^lastR2bundle
+$ git bundle create mybundle master ^lastR2bundle
 $ git tag -f lastR2bundle master
 ------------
 
@@ -141,8 +140,8 @@ $ git bundle create mybundle master -n 10
 Then you move mybundle from A to B, and in R2 on B:
 
 ------------
-$ git-bundle verify mybundle
-$ git-fetch mybundle master:localRef
+$ git bundle verify mybundle
+$ git fetch mybundle master:localRef
 ------------
 
 With something like this in the config in R2:
index f58013ca605631437e5a4806cdd07dba18d8a982..d35e8a04fe28b095b5405ae2e0b09e3ab448bf63 100644 (file)
@@ -9,8 +9,8 @@ git-cat-file - Provide content or type/size information for repository objects
 SYNOPSIS
 --------
 [verse]
-'git-cat-file' [-t | -s | -e | -p | <type>] <object>
-'git-cat-file' [--batch | --batch-check] < <list-of-objects>
+'git cat-file' [-t | -s | -e | -p | <type>] <object>
+'git cat-file' [--batch | --batch-check] < <list-of-objects>
 
 DESCRIPTION
 -----------
index ef16b93982f92dd0bc567a3c9bdeaa7703eeac3a..abe1f1b7ddb4e47ac6c9ba327cb6f2c7e2b5fc9e 100644 (file)
@@ -8,7 +8,7 @@ git-check-attr - Display gitattributes information.
 
 SYNOPSIS
 --------
-'git-check-attr' attr... [--] pathname...
+'git check-attr' attr... [--] pathname...
 
 DESCRIPTION
 -----------
index c560c0aa6de5d01de7e954b10e3e170b94641d5b..034223cc5ace81dd0b63da44d79db5e83a1d492a 100644 (file)
@@ -7,7 +7,7 @@ git-check-ref-format - Make sure ref name is well formed
 
 SYNOPSIS
 --------
-'git-check-ref-format' <refname>
+'git check-ref-format' <refname>
 
 DESCRIPTION
 -----------
@@ -47,7 +47,7 @@ refname expressions (see linkgit:git-rev-parse[1]).  Namely:
 . colon `:` is used as in `srcref:dstref` to mean "use srcref\'s
   value and store it in dstref" in fetch and push operations.
   It may also be used to select a specific object such as with
-  linkgit:git-cat-file[1] "git-cat-file blob v1.3.3:refs.c".
+  'git-cat-file': "git cat-file blob v1.3.3:refs.c".
 
 
 GIT
index 676203b2ebcc1261dc5ad8d0ab8caa0bc730112c..62d84836b8a0d77c2a6ea534566ff8462b0eb37a 100644 (file)
@@ -9,7 +9,7 @@ git-checkout-index - Copy files from the index to the working tree
 SYNOPSIS
 --------
 [verse]
-'git-checkout-index' [-u] [-q] [-a] [-f] [-n] [--prefix=<string>]
+'git checkout-index' [-u] [-q] [-a] [-f] [-n] [--prefix=<string>]
                   [--stage=<number>|all]
                   [--temp]
                   [-z] [--stdin]
@@ -73,25 +73,25 @@ OPTIONS
 
 The order of the flags used to matter, but not anymore.
 
-Just doing `git-checkout-index` does nothing. You probably meant
-`git-checkout-index -a`. And if you want to force it, you want
-`git-checkout-index -f -a`.
+Just doing `git checkout-index` does nothing. You probably meant
+`git checkout-index -a`. And if you want to force it, you want
+`git checkout-index -f -a`.
 
 Intuitiveness is not the goal here. Repeatability is. The reason for
 the "no arguments means no work" behavior is that from scripts you are
 supposed to be able to do:
 
 ----------------
-$ find . -name '*.h' -print0 | xargs -0 git-checkout-index -f --
+$ find . -name '*.h' -print0 | xargs -0 git checkout-index -f --
 ----------------
 
 which will force all existing `*.h` files to be replaced with their
 cached copies. If an empty command line implied "all", then this would
 force-refresh everything in the index, which was not the point.  But
-since git-checkout-index accepts --stdin it would be faster to use:
+since 'git-checkout-index' accepts --stdin it would be faster to use:
 
 ----------------
-$ find . -name '*.h' -print0 | git-checkout-index -f -z --stdin
+$ find . -name '*.h' -print0 | git checkout-index -f -z --stdin
 ----------------
 
 The `--` is just a good idea when you know the rest will be filenames;
@@ -102,7 +102,7 @@ Using `--` is probably a good policy in scripts.
 Using --temp or --stage=all
 ---------------------------
 When `--temp` is used (or implied by `--stage=all`)
-`git-checkout-index` will create a temporary file for each index
+'git-checkout-index' will create a temporary file for each index
 entry being checked out.  The index will not be updated with stat
 information.  These options can be useful if the caller needs all
 stages of all unmerged entries so that the unmerged files can be
@@ -144,19 +144,19 @@ EXAMPLES
 To update and refresh only the files already checked out::
 +
 ----------------
-$ git-checkout-index -n -f -a && git-update-index --ignore-missing --refresh
+$ git checkout-index -n -f -a && git update-index --ignore-missing --refresh
 ----------------
 
-Using `git-checkout-index` to "export an entire tree"::
+Using 'git-checkout-index' to "export an entire tree"::
        The prefix ability basically makes it trivial to use
-       `git-checkout-index` as an "export as tree" function.
+       'git-checkout-index' as an "export as tree" function.
        Just read the desired tree into the index, and do:
 +
 ----------------
-$ git-checkout-index --prefix=git-export-dir/ -a
+$ git checkout-index --prefix=git-export-dir/ -a
 ----------------
 +
-`git-checkout-index` will "export" the index into the specified
+`git checkout-index` will "export" the index into the specified
 directory.
 +
 The final "/" is important. The exported name is literally just
@@ -166,7 +166,7 @@ following example.
 Export files with a prefix::
 +
 ----------------
-$ git-checkout-index --prefix=.merged- Makefile
+$ git checkout-index --prefix=.merged- Makefile
 ----------------
 +
 This will check out the currently cached copy of `Makefile`
index 3ad9760a4d6949837c1e186402c9810b59a0138d..2abfbdaadb27ca9a97c23c9c00cc18fb07232d00 100644 (file)
@@ -8,8 +8,8 @@ git-checkout - Checkout a branch or paths to the working tree
 SYNOPSIS
 --------
 [verse]
-'git-checkout' [-q] [-f] [[--track | --no-track] -b <new_branch> [-l]] [-m] [<branch>]
-'git-checkout' [<tree-ish>] <paths>...
+'git checkout' [-q] [-f] [[--track | --no-track] -b <new_branch> [-l]] [-m] [<branch>]
+'git checkout' [<tree-ish>] <paths>...
 
 DESCRIPTION
 -----------
@@ -23,7 +23,7 @@ options, which will be passed to `git branch`.
 
 When <paths> are given, this command does *not* switch
 branches.  It updates the named paths in the working tree from
-the index file (i.e. it runs `git-checkout-index -f -u`), or
+the index file (i.e. it runs `git checkout-index -f -u`), or
 from a named commit.  In
 this case, the `-f` and `-b` options are meaningless and giving
 either of them results in an error.  <tree-ish> argument can be
@@ -49,14 +49,14 @@ OPTIONS
 
 -t::
 --track::
-       When creating a new branch, set up configuration so that git-pull
+       When creating a new branch, set up configuration so that 'git-pull'
        will automatically retrieve data from the start point, which must be
        a branch. Use this if you always pull from the same upstream branch
        into the new branch, and if you don't want to use "git pull
        <repository> <refspec>" explicitly. This behavior is the default
        when the start point is a remote branch. Set the
        branch.autosetupmerge configuration variable to `false` if you want
-       git-checkout and git-branch to always behave as if '--no-track' were
+       'git-checkout' and 'git-branch' to always behave as if '--no-track' were
        given. Set it to `always` if you want this behavior when the
        start-point is either a local or remote branch.
 
@@ -112,7 +112,7 @@ current branch and directly point at the commit named by the tag
 (`v2.6.18` in the above example).
 
 You can use usual git commands while in this state.  You can use
-`git-reset --hard $othercommit` to further move around, for
+`git reset --hard $othercommit` to further move around, for
 example.  You can make changes and create a new commit on top of
 a detached HEAD.  You can even create a merge by using `git
 merge $othercommit`.
index 5ac9cfb0ef2e2eb26ebe5cce6a5c7ed54d4e39ec..a691173ba13370330b97907cf751342cf1c0fe44 100644 (file)
@@ -7,7 +7,7 @@ git-cherry-pick - Apply the change introduced by an existing commit
 
 SYNOPSIS
 --------
-'git-cherry-pick' [--edit] [-n] [-m parent-number] [-s] [-x] <commit>
+'git cherry-pick' [--edit] [-n] [-m parent-number] [-s] [-x] <commit>
 
 DESCRIPTION
 -----------
@@ -19,12 +19,12 @@ OPTIONS
 -------
 <commit>::
        Commit to cherry-pick.
-       For a more complete list of ways to spell commits, see
+       For a more complete list of ways to spell commits, see the
        "SPECIFYING REVISIONS" section in linkgit:git-rev-parse[1].
 
 -e::
 --edit::
-       With this option, `git-cherry-pick` will let you edit the commit
+       With this option, 'git-cherry-pick' will let you edit the commit
        message prior to committing.
 
 -x::
index ef7caf61e1d344ea447b0b874063cabc0a83fdec..d761a73423e606a38f8e390117107a99b9ae3bd3 100644 (file)
@@ -7,14 +7,14 @@ git-cherry - Find commits not merged upstream
 
 SYNOPSIS
 --------
-'git-cherry' [-v] <upstream> [<head>] [<limit>]
+'git cherry' [-v] <upstream> [<head>] [<limit>]
 
 DESCRIPTION
 -----------
 The changeset (or "diff") of each commit between the fork-point and <head>
 is compared against each commit between the fork-point and <upstream>.
-The commits are compared with their 'patch id', obtained from linkgit:git-patch-id[1]
-program.
+The commits are compared with their 'patch id', obtained from
+the 'git-patch-id' program.
 
 Every commit that doesn't exist in the <upstream> branch
 has its id (sha1) reported, prefixed by a symbol.  The ones that have
@@ -37,8 +37,8 @@ to and including <limit> are not reported:
               \__*__*__<limit>__-__+__> <head>
 
 
-Because git-cherry compares the changeset rather than the commit id
-(sha1), you can use git-cherry to find out if a commit you made locally
+Because 'git-cherry' compares the changeset rather than the commit id
+(sha1), you can use 'git-cherry' to find out if a commit you made locally
 has been applied <upstream> under a different commit id.  For example,
 this will happen if you're feeding patches <upstream> via email rather
 than pushing or pulling commits directly.
index 09108d0e6617fd3b2383ec48cd48fe921ed98a29..670cb02b6cc035e4fbcf1a1016f66b7a85cd4ef7 100644 (file)
@@ -14,9 +14,9 @@ DESCRIPTION
 A Tcl/Tk based graphical interface to review modified files, stage
 them into the index, enter a commit message and record the new
 commit onto the current branch.  This interface is an alternative
-to the less interactive linkgit:git-commit[1] program.
+to the less interactive 'git-commit' program.
 
-git-citool is actually a standard alias for 'git gui citool'.
+'git-citool' is actually a standard alias for `git gui citool`.
 See linkgit:git-gui[1] for more details.
 
 Author
index 37a82ee4b8ed2dc939e56140821a42d452e1b4b5..7dcc1ba58c3879cb14ce243a4af00bca9e850799 100644 (file)
@@ -8,7 +8,7 @@ git-clean - Remove untracked files from the working tree
 SYNOPSIS
 --------
 [verse]
-'git-clean' [-d] [-f] [-n] [-q] [-x | -X] [--] <paths>...
+'git clean' [-d] [-f] [-n] [-q] [-x | -X] [--] <paths>...
 
 DESCRIPTION
 -----------
@@ -27,7 +27,7 @@ OPTIONS
 
 -f::
        If the git configuration specifies clean.requireForce as true,
-       git-clean will refuse to run unless given -f or -n.
+       'git-clean' will refuse to run unless given -f or -n.
 
 -n::
 --dry-run::
@@ -41,7 +41,7 @@ OPTIONS
 -x::
        Don't use the ignore rules.  This allows removing all untracked
        files, including build products.  This can be used (possibly in
-       conjunction with linkgit:git-reset[1]) to create a pristine
+       conjunction with 'git-reset') to create a pristine
        working directory to test a clean build.
 
 -X::
index 7973e6af4c2aa31ea9ae9b91b4c4cd5ee2256762..91efac920ec969455b75f0a5c1761dac648d2b1b 100644 (file)
@@ -9,7 +9,7 @@ git-clone - Clone a repository into a new directory
 SYNOPSIS
 --------
 [verse]
-'git-clone' [--template=<template_directory>]
+'git clone' [--template=<template_directory>]
          [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare]
          [-o <name>] [-u <upload-pack>] [--reference <repository>]
          [--depth <depth>] [--] <repository> [<directory>]
@@ -68,10 +68,10 @@ it unless you understand what it does. If you clone your
 repository using this option and then delete branches (or use any
 other git command that makes any existing commit unreferenced) in the
 source repository, some objects may become unreferenced (or dangling).
-These objects may be removed by normal git operations (such as git-commit[1])
-which automatically call git-gc[1]. If these objects are removed and
-were referenced by the cloned repository, then the cloned repository
-will become corrupt.
+These objects may be removed by normal git operations (such as 'git-commit')
+which automatically call `git gc --auto`. (See linkgit:git-gc[1].)
+If these objects are removed and were referenced by the cloned repository,
+then the cloned repository will become corrupt.
 
 
 
@@ -88,7 +88,7 @@ will become corrupt.
 --quiet::
 -q::
        Operate quietly.  This flag is passed to "rsync" and
-       "git-fetch-pack" commands when given.
+       'git-fetch-pack' commands when given.
 
 --no-checkout::
 -n::
@@ -114,7 +114,7 @@ will become corrupt.
 --upload-pack <upload-pack>::
 -u <upload-pack>::
        When given, and the repository to clone from is handled
-       by 'git-fetch-pack', '--exec=<upload-pack>' is passed to
+       by 'git-fetch-pack', `--exec=<upload-pack>` is passed to
        the command to specify non-default path for the command
        run on the other end.
 
index 728c2fae892f0a4a66e9fb1854a7e31f4a5f4917..feec58400b64c65c8f96f2d1834016455c89829e 100644 (file)
@@ -8,7 +8,7 @@ git-commit-tree - Create a new commit object
 
 SYNOPSIS
 --------
-'git-commit-tree' <tree> [-p <parent commit>]\* < changelog
+'git commit-tree' <tree> [-p <parent commit>]\* < changelog
 
 DESCRIPTION
 -----------
@@ -70,7 +70,7 @@ is taken from the configuration items user.name and user.email, or, if not
 present, system user name and fully qualified hostname.
 
 A commit comment is read from stdin. If a changelog
-entry is not provided via "<" redirection, "git-commit-tree" will just wait
+entry is not provided via "<" redirection, 'git-commit-tree' will just wait
 for one to be entered and terminated with ^D.
 
 
index 7e8b4ff72c0192f01523118b9a8caeddbcbda09c..01bd2d6b77da49b759e1887cf98b8c5b3bf98c38 100644 (file)
@@ -8,23 +8,23 @@ git-commit - Record changes to the repository
 SYNOPSIS
 --------
 [verse]
-'git-commit' [-a | --interactive] [-s] [-v] [-u] [--amend]
+'git commit' [-a | --interactive] [-s] [-v] [-u<mode>] [--amend]
           [(-c | -C) <commit>] [-F <file> | -m <msg>]
           [--allow-empty] [--no-verify] [-e] [--author=<author>]
           [--cleanup=<mode>] [--] [[-i | -o ]<file>...]
 
 DESCRIPTION
 -----------
-Use 'git commit' to store the current contents of the index in a new
-commit along with a log message describing the changes you have made.
+Stores the current contents of the index in a new commit along
+with a log message from the user describing the changes.
 
 The content to be added can be specified in several ways:
 
-1. by using linkgit:git-add[1] to incrementally "add" changes to the
+1. by using 'git-add' to incrementally "add" changes to the
    index before using the 'commit' command (Note: even modified
    files must be "added");
 
-2. by using linkgit:git-rm[1] to remove files from the working tree
+2. by using 'git-rm' to remove files from the working tree
    and the index, again before using the 'commit' command;
 
 3. by listing files as arguments to the 'commit' command, in which
@@ -39,15 +39,15 @@ The content to be added can be specified in several ways:
 
 5. by using the --interactive switch with the 'commit' command to decide one
    by one which files should be part of the commit, before finalizing the
-   operation.  Currently, this is done by invoking `git-add --interactive`.
+   operation.  Currently, this is done by invoking 'git-add --interactive'.
 
-The linkgit:git-status[1] command can be used to obtain a
+The 'git-status' command can be used to obtain a
 summary of what is included by any of the above for the next
 commit by giving the same set of parameters you would give to
 this command.
 
-If you make a commit and then found a mistake immediately after
-that, you can recover from it with linkgit:git-reset[1].
+If you make a commit and then find a mistake immediately after
+that, you can recover from it with 'git-reset'.
 
 
 OPTIONS
@@ -97,7 +97,7 @@ OPTIONS
 -n::
 --no-verify::
        This option bypasses the pre-commit and commit-msg hooks.
-       See also linkgit:githooks[5][hooks].
+       See also linkgit:githooks[5].
 
 --allow-empty::
        Usually recording a commit that has the exact same tree as its
@@ -155,20 +155,29 @@ but can be used to amend a merge commit.
        Make a commit only from the paths specified on the
        command line, disregarding any contents that have been
        staged so far. This is the default mode of operation of
-       'git commit' if any paths are given on the command line,
+       'git-commit' if any paths are given on the command line,
        in which case this option can be omitted.
        If this option is specified together with '--amend', then
        no paths need be specified, which can be used to amend
        the last commit without committing changes that have
        already been staged.
 
--u::
---untracked-files::
-       Show all untracked files, also those in uninteresting
-       directories, in the "Untracked files:" section of commit
-       message template.  Without this option only its name and
-       a trailing slash are displayed for each untracked
-       directory.
+-u[<mode>]::
+--untracked-files[=<mode>]::
+       Show untracked files (Default: 'all').
++
+The mode parameter is optional, and is used to specify
+the handling of untracked files. The possible options are:
++
+--
+       - 'no'     - Show no untracked files
+       - 'normal' - Shows untracked files and directories
+       - 'all'    - Also shows individual files in untracked directories.
+--
++
+See linkgit:git-config[1] for configuration variable
+used to change the default for when the option is not
+specified.
 
 -v::
 --verbose::
@@ -196,10 +205,10 @@ EXAMPLES
 --------
 When recording your own work, the contents of modified files in
 your working tree are temporarily stored to a staging area
-called the "index" with linkgit:git-add[1].  A file can be
+called the "index" with 'git-add'.  A file can be
 reverted back, only in the index but not in the working tree,
-to that of the last commit with `git-reset HEAD -- <file>`,
-which effectively reverts `git-add` and prevents the changes to
+to that of the last commit with `git reset HEAD -- <file>`,
+which effectively reverts 'git-add' and prevents the changes to
 this file from participating in the next commit.  After building
 the state to be committed incrementally with these commands,
 `git commit` (without any pathname parameter) is used to record what
@@ -255,13 +264,13 @@ $ git commit
 this second commit would record the changes to `hello.c` and
 `hello.h` as expected.
 
-After a merge (initiated by either linkgit:git-merge[1] or
-linkgit:git-pull[1]) stops because of conflicts, cleanly merged
+After a merge (initiated by 'git-merge' or 'git-pull') stops
+because of conflicts, cleanly merged
 paths are already staged to be committed for you, and paths that
 conflicted are left in unmerged state.  You would have to first
-check which paths are conflicting with linkgit:git-status[1]
+check which paths are conflicting with 'git-status'
 and after fixing them manually in your working tree, you would
-stage the result as usual with linkgit:git-add[1]:
+stage the result as usual with 'git-add':
 
 ------------
 $ git status | grep unmerged
@@ -307,7 +316,7 @@ order).
 HOOKS
 -----
 This command can run `commit-msg`, `prepare-commit-msg`, `pre-commit`,
-and `post-commit` hooks.  See linkgit:githooks[5][hooks] for more
+and `post-commit` hooks.  See linkgit:githooks[5] for more
 information.
 
 
index c90421ee7f3b6a3fe1f08c4868b5652d4d7db569..697824cbabdd4bab487b8c943277d3a1d703e59a 100644 (file)
@@ -9,19 +9,19 @@ git-config - Get and set repository or global options
 SYNOPSIS
 --------
 [verse]
-'git-config' [<file-option>] [type] [-z|--null] name [value [value_regex]]
-'git-config' [<file-option>] [type] --add name value
-'git-config' [<file-option>] [type] --replace-all name [value [value_regex]]
-'git-config' [<file-option>] [type] [-z|--null] --get name [value_regex]
-'git-config' [<file-option>] [type] [-z|--null] --get-all name [value_regex]
-'git-config' [<file-option>] [type] [-z|--null] --get-regexp name_regex [value_regex]
-'git-config' [<file-option>] --unset name [value_regex]
-'git-config' [<file-option>] --unset-all name [value_regex]
-'git-config' [<file-option>] --rename-section old_name new_name
-'git-config' [<file-option>] --remove-section name
-'git-config' [<file-option>] [-z|--null] -l | --list
-'git-config' [<file-option>] --get-color name [default]
-'git-config' [<file-option>] --get-colorbool name [stdout-is-tty]
+'git config' [<file-option>] [type] [-z|--null] name [value [value_regex]]
+'git config' [<file-option>] [type] --add name value
+'git config' [<file-option>] [type] --replace-all name [value [value_regex]]
+'git config' [<file-option>] [type] [-z|--null] --get name [value_regex]
+'git config' [<file-option>] [type] [-z|--null] --get-all name [value_regex]
+'git config' [<file-option>] [type] [-z|--null] --get-regexp name_regex [value_regex]
+'git config' [<file-option>] --unset name [value_regex]
+'git config' [<file-option>] --unset-all name [value_regex]
+'git config' [<file-option>] --rename-section old_name new_name
+'git config' [<file-option>] --remove-section name
+'git config' [<file-option>] [-z|--null] -l | --list
+'git config' [<file-option>] --get-color name [default]
+'git config' [<file-option>] --get-colorbool name [stdout-is-tty]
 
 DESCRIPTION
 -----------
@@ -122,10 +122,10 @@ See also <<FILES>>.
        List all variables set in config file.
 
 --bool::
-       git-config will ensure that the output is "true" or "false"
+       'git-config' will ensure that the output is "true" or "false"
 
 --int::
-       git-config will ensure that the output is a simple
+       'git-config' will ensure that the output is a simple
        decimal number.  An optional value suffix of 'k', 'm', or 'g'
        in the config file will cause the value to be multiplied
        by 1024, 1048576, or 1073741824 prior to output.
@@ -162,7 +162,7 @@ FILES
 -----
 
 If not set explicitly with '--file', there are three files where
-git-config will search for configuration options:
+'git-config' will search for configuration options:
 
 $GIT_DIR/config::
        Repository specific configuration file. (The filename is
@@ -179,23 +179,18 @@ $(prefix)/etc/gitconfig::
 If no further options are given, all reading options will read all of these
 files that are available. If the global or the system-wide configuration
 file are not available they will be ignored. If the repository configuration
-file is not available or readable, git-config will exit with a non-zero
+file is not available or readable, 'git-config' will exit with a non-zero
 error code. However, in neither case will an error message be issued.
 
 All writing options will per default write to the repository specific
 configuration file. Note that this also affects options like '--replace-all'
-and '--unset'. *git-config will only ever change one file at a time*.
+and '--unset'. *'git-config' will only ever change one file at a time*.
 
 You can override these rules either by command line options or by environment
 variables. The '--global' and the '--system' options will limit the file used
 to the global or system-wide file respectively. The GIT_CONFIG environment
 variable has a similar effect, but you can specify any filename you want.
 
-The GIT_CONFIG_LOCAL environment variable on the other hand only changes
-the name used instead of the repository configuration file. The global and
-the system-wide configuration files will still be read. (For writing options
-this will obviously result in the same behavior as using GIT_CONFIG.)
-
 
 ENVIRONMENT
 -----------
@@ -205,10 +200,6 @@ GIT_CONFIG::
        Using the "--global" option forces this to ~/.gitconfig. Using the
        "--system" option forces this to $(prefix)/etc/gitconfig.
 
-GIT_CONFIG_LOCAL::
-       Take the configuration from the given file instead if .git/config.
-       Still read the global and the system-wide configuration files, though.
-
 See also <<FILES>>.
 
 
index 1ba85a259a2d8896b5634f3496542b5561dbf2de..c069cc8b04a63084856b60814669457c95dac2db 100644 (file)
@@ -7,7 +7,7 @@ git-count-objects - Count unpacked number of objects and their disk consumption
 
 SYNOPSIS
 --------
-'git-count-objects' [-v]
+'git count-objects' [-v]
 
 DESCRIPTION
 -----------
@@ -22,7 +22,7 @@ OPTIONS
        In addition to the number of loose objects and disk
        space consumed, it reports the number of in-pack
        objects, number of packs, and number of objects that can be
-       removed by running `git-prune-packed`.
+       removed by running `git prune-packed`.
 
 
 Author
index 5fa91e51ad70c3fed2bf3170bf14268f410aec5f..2da8588f4fd6edb842a9824181165b3f043ec87b 100644 (file)
@@ -8,7 +8,8 @@ git-cvsexportcommit - Export a single commit to a CVS checkout
 
 SYNOPSIS
 --------
-'git-cvsexportcommit' [-h] [-u] [-v] [-c] [-P] [-p] [-a] [-d cvsroot] [-w cvsworkdir] [-W] [-f] [-m msgprefix] [PARENTCOMMIT] COMMITID
+'git cvsexportcommit' [-h] [-u] [-v] [-c] [-P] [-p] [-a] [-d cvsroot]
+       [-w cvsworkdir] [-W] [-f] [-m msgprefix] [PARENTCOMMIT] COMMITID
 
 
 DESCRIPTION
@@ -26,8 +27,8 @@ by default.
 
 Supports file additions, removals, and commits that affect binary files.
 
-If the commit is a merge commit, you must tell git-cvsexportcommit what parent
-should the changeset be done against.
+If the commit is a merge commit, you must tell 'git-cvsexportcommit' what
+parent the changeset should be done against.
 
 OPTIONS
 -------
@@ -89,14 +90,14 @@ Merge one patch into CVS::
 ------------
 $ export GIT_DIR=~/project/.git
 $ cd ~/project_cvs_checkout
-$ git-cvsexportcommit -v <commit-sha1>
+$ git cvsexportcommit -v <commit-sha1>
 $ cvs commit -F .msg <files>
 ------------
 
 Merge one patch into CVS (-c and -w options). The working directory is within the Git Repo::
 +
 ------------
-       $ git-cvsexportcommit -v -c -w ~/project_cvs_checkout <commit-sha1>
+       $ git cvsexportcommit -v -c -w ~/project_cvs_checkout <commit-sha1>
 ------------
 
 Merge pending patches into CVS automatically -- only if you really know what you are doing::
@@ -104,7 +105,7 @@ Merge pending patches into CVS automatically -- only if you really know what you
 ------------
 $ export GIT_DIR=~/project/.git
 $ cd ~/project_cvs_checkout
-$ git-cherry cvshead myhead | sed -n 's/^+ //p' | xargs -l1 git-cvsexportcommit -c -p -v
+$ git cherry cvshead myhead | sed -n 's/^+ //p' | xargs -l1 git cvsexportcommit -c -p -v
 ------------
 
 Author
index 93b7d2dc998f9e7c8bedf39f686b81c95deffa6c..b7a8c10b8709108c1c8a0d14f661c179c2b4f22c 100644 (file)
@@ -9,7 +9,7 @@ git-cvsimport - Salvage your data out of another SCM people love to hate
 SYNOPSIS
 --------
 [verse]
-'git-cvsimport' [-o <branch-for-HEAD>] [-h] [-v] [-d <CVSROOT>]
+'git cvsimport' [-o <branch-for-HEAD>] [-h] [-v] [-d <CVSROOT>]
              [-A <author-conv-file>] [-p <options-for-cvsps>] [-P <file>]
              [-C <git_repository>] [-z <fuzz>] [-i] [-k] [-u] [-s <subst>]
              [-a] [-m] [-M <regex>] [-S <regex>] [-L <commitlimit>]
@@ -25,9 +25,9 @@ Splitting the CVS log into patch sets is done by 'cvsps'.
 At least version 2.1 is required.
 
 You should *never* do any work of your own on the branches that are
-created by git-cvsimport.  By default initial import will create and populate a
+created by 'git-cvsimport'.  By default initial import will create and populate a
 "master" branch from the CVS repository's main branch which you're free
-to work with; after that, you need to 'git merge' incremental imports, or
+to work with; after that, you need to 'git-merge' incremental imports, or
 any CVS branches, yourself.  It is advisable to specify a named remote via
 -r to separate and protect the incoming branches.
 
@@ -46,13 +46,13 @@ OPTIONS
 -d <CVSROOT>::
        The root of the CVS archive. May be local (a simple path) or remote;
        currently, only the :local:, :ext: and :pserver: access methods
-       are supported. If not given, git-cvsimport will try to read it
+       are supported. If not given, 'git-cvsimport' will try to read it
        from `CVS/Root`. If no such file exists, it checks for the
        `CVSROOT` environment variable.
 
 <CVS_module>::
        The CVS module you want to import. Relative to <CVSROOT>.
-       If not given, git-cvsimport tries to read it from
+       If not given, 'git-cvsimport' tries to read it from
        `CVS/Repository`.
 
 -C <target-dir>::
@@ -62,14 +62,14 @@ OPTIONS
 -r <remote>::
        The git remote to import this CVS repository into.
        Moves all CVS branches into remotes/<remote>/<branch>
-       akin to the git-clone --use-separate-remote option.
+       akin to the 'git-clone' "--use-separate-remote" option.
 
 -o <branch-for-HEAD>::
        When no remote is specified (via -r) the 'HEAD' branch
        from CVS is imported to the 'origin' branch within the git
        repository, as 'HEAD' already has a special meaning for git.
        When a remote is specified the 'HEAD' branch is named
-       remotes/<remote>/master mirroring git-clone behaviour.
+       remotes/<remote>/master mirroring 'git-clone' behaviour.
        Use this option if you want to import into a different
        branch.
 +
@@ -142,17 +142,17 @@ This option can be used several times to provide several detection regexes.
 
 ---------
 +
-git-cvsimport will make it appear as those authors had
+'git-cvsimport' will make it appear as those authors had
 their GIT_AUTHOR_NAME and GIT_AUTHOR_EMAIL set properly
 all along.
 +
 For convenience, this data is saved to `$GIT_DIR/cvs-authors`
 each time the '-A' option is provided and read from that same
-file each time git-cvsimport is run.
+file each time 'git-cvsimport' is run.
 +
 It is not recommended to use this feature if you intend to
 export changes back to CVS again later with
-linkgit:git-cvsexportcommit[1].
+'git-cvsexportcommit'.
 
 -h::
        Print a short usage message and exit.
index 19da87e71d252e666335de7c97a5abcdd5fadbf8..c2d3c90d27084e7de7e0f7c37b40f130f6960244 100644 (file)
@@ -22,7 +22,7 @@ cvspserver stream tcp nowait nobody /usr/bin/git-cvsserver git-cvsserver pserver
 Usage:
 
 [verse]
-'git-cvsserver' [options] [pserver|server] [<directory> ...]
+'git cvsserver' [options] [pserver|server] [<directory> ...]
 
 OPTIONS
 -------
@@ -77,7 +77,7 @@ over pserver for anonymous CVS access.
 
 CVS clients cannot tag, branch or perform GIT merges.
 
-git-cvsserver maps GIT branches to CVS modules. This is very different
+'git-cvsserver' maps GIT branches to CVS modules. This is very different
 from what most CVS users would expect since in CVS modules usually represent
 one or more directories.
 
@@ -103,7 +103,7 @@ looks like
 ------
 No special setup is needed for SSH access, other than having GIT tools
 in the PATH. If you have clients that do not accept the CVS_SERVER
-environment variable, you can rename git-cvsserver to cvs.
+environment variable, you can rename 'git-cvsserver' to `cvs`.
 
 Note: Newer CVS versions (>= 1.12.11) also support specifying
 CVS_SERVER directly in CVSROOT like
@@ -113,9 +113,9 @@ cvs -d ":ext;CVS_SERVER=git-cvsserver:user@server/path/repo.git" co <HEAD_name>
 ------
 This has the advantage that it will be saved in your 'CVS/Root' files and
 you don't need to worry about always setting the correct environment
-variable.  SSH users restricted to git-shell don't need to override the default
-with CVS_SERVER (and shouldn't) as git-shell understands `cvs` to mean
-git-cvsserver and pretends that the other end runs the real cvs better.
+variable.  SSH users restricted to 'git-shell' don't need to override the default
+with CVS_SERVER (and shouldn't) as 'git-shell' understands `cvs` to mean
+'git-cvsserver' and pretends that the other end runs the real 'cvs' better.
 --
 2. For each repo that you want accessible from CVS you need to edit config in
    the repo and add the following section.
@@ -128,7 +128,7 @@ git-cvsserver and pretends that the other end runs the real cvs better.
         logfile=/path/to/logfile
 
 ------
-Note: you need to ensure each user that is going to invoke git-cvsserver has
+Note: you need to ensure each user that is going to invoke 'git-cvsserver' has
 write access to the log file and to the database (see
 <<dbbackend,Database Backend>>. If you want to offer write access over
 SSH, the users of course also need write access to the git repository itself.
@@ -153,7 +153,7 @@ allowing access over SSH.
    automatically saving it in your 'CVS/Root' files, then you need to set them
    explicitly in your environment.  CVSROOT should be set as per normal, but the
    directory should point at the appropriate git repo.  As above, for SSH clients
-   _not_ restricted to git-shell, CVS_SERVER should be set to git-cvsserver.
+   _not_ restricted to 'git-shell', CVS_SERVER should be set to 'git-cvsserver'.
 +
 --
 ------
@@ -181,27 +181,27 @@ allowing access over SSH.
 Database Backend
 ----------------
 
-git-cvsserver uses one database per git head (i.e. CVS module) to
+'git-cvsserver' uses one database per git head (i.e. CVS module) to
 store information about the repository for faster access. The
 database doesn't contain any persistent data and can be completely
 regenerated from the git repository at any time. The database
 needs to be updated (i.e. written to) after every commit.
 
-If the commit is done directly by using git (as opposed to
-using git-cvsserver) the update will need to happen on the
-next repository access by git-cvsserver, independent of
+If the commit is done directly by using `git` (as opposed to
+using 'git-cvsserver') the update will need to happen on the
+next repository access by 'git-cvsserver', independent of
 access method and requested operation.
 
 That means that even if you offer only read access (e.g. by using
-the pserver method), git-cvsserver should have write access to
+the pserver method), 'git-cvsserver' should have write access to
 the database to work reliably (otherwise you need to make sure
-that the database is up-to-date any time git-cvsserver is executed).
+that the database is up-to-date any time 'git-cvsserver' is executed).
 
 By default it uses SQLite databases in the git directory, named
 `gitcvs.<module_name>.sqlite`. Note that the SQLite backend creates
 temporary files in the same directory as the database file on
 write so it might not be enough to grant the users using
-git-cvsserver write access to the database file without granting
+'git-cvsserver' write access to the database file without granting
 them write access to the directory, too.
 
 You can configure the database backend with the following
@@ -210,7 +210,7 @@ configuration variables:
 Configuring database backend
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-git-cvsserver uses the Perl DBI module. Please also read
+'git-cvsserver' uses the Perl DBI module. Please also read
 its documentation if changing these variables, especially
 about `DBI->connect()`.
 
@@ -262,7 +262,7 @@ In `dbdriver` and `dbuser` you can use the following variables:
 %a::
        access method (one of "ext" or "pserver")
 %u::
-       Name of the user running git-cvsserver.
+       Name of the user running 'git-cvsserver'.
        If no name can be determined, the
        numeric uid is used.
 
@@ -288,8 +288,8 @@ you will definitely want to have SSH keys setup.
 
 Alternatively, you can just use the non-standard extssh protocol that Eclipse
 offer. In that case CVS_SERVER is ignored, and you will have to replace
-the cvs utility on the server with git-cvsserver or manipulate your `.bashrc`
-so that calling 'cvs' effectively calls git-cvsserver.
+the cvs utility on the server with 'git-cvsserver' or manipulate your `.bashrc`
+so that calling 'cvs' effectively calls 'git-cvsserver'.
 
 Clients known to work
 ---------------------
@@ -331,14 +331,13 @@ is left blank. But if `gitcvs.allbinary` is set to "guess", then
 the correct '-k' mode will be guessed based on the contents of
 the file.
 
-For best consistency with cvs, it is probably best to override the
+For best consistency with 'cvs', it is probably best to override the
 defaults by setting `gitcvs.usecrlfattr` to true,
 and `gitcvs.allbinary` to "guess".
 
 Dependencies
 ------------
-
-git-cvsserver depends on DBD::SQLite.
+'git-cvsserver' depends on DBD::SQLite.
 
 Copyright and Authors
 ---------------------
index 344f24ea59a7f85473da4e865219bcdc0fb9db33..4ba4b75c1126d87c48935e7697e05f0d5210ad2d 100644 (file)
@@ -8,12 +8,12 @@ git-daemon - A really simple server for git repositories
 SYNOPSIS
 --------
 [verse]
-'git-daemon' [--verbose] [--syslog] [--export-all]
-             [--timeout=n] [--init-timeout=n] [--strict-paths]
-             [--base-path=path] [--user-path | --user-path=path]
-             [--interpolated-path=pathtemplate]
-             [--reuseaddr] [--detach] [--pid-file=file]
-             [--enable=service] [--disable=service]
+'git daemon' [--verbose] [--syslog] [--export-all]
+            [--timeout=n] [--init-timeout=n] [--strict-paths]
+            [--base-path=path] [--user-path | --user-path=path]
+            [--interpolated-path=pathtemplate]
+            [--reuseaddr] [--detach] [--pid-file=file]
+            [--enable=service] [--disable=service]
             [--allow-override=service] [--forbid-override=service]
             [--inetd | [--listen=host_or_ipaddr] [--port=n] [--user=user [--group=group]]
             [directory...]
@@ -31,32 +31,32 @@ pass some directory paths as 'git-daemon' arguments, you can further restrict
 the offers to a whitelist comprising of those.
 
 By default, only `upload-pack` service is enabled, which serves
-`git-fetch-pack` and `git-ls-remote` clients, which are invoked
-from `git-fetch`, `git-pull`, and `git-clone`.
+'git-fetch-pack' and 'git-ls-remote' clients, which are invoked
+from 'git-fetch', 'git-pull', and 'git-clone'.
 
 This is ideally suited for read-only updates, i.e., pulling from
 git repositories.
 
-An `upload-archive` also exists to serve `git-archive`.
+An `upload-archive` also exists to serve 'git-archive'.
 
 OPTIONS
 -------
 --strict-paths::
        Match paths exactly (i.e. don't allow "/foo/repo" when the real path is
        "/foo/repo.git" or "/foo/repo/.git") and don't do user-relative paths.
-       git-daemon will refuse to start when this option is enabled and no
+       'git-daemon' will refuse to start when this option is enabled and no
        whitelist is specified.
 
 --base-path::
        Remap all the path requests as relative to the given path.
-       This is sort of "GIT root" - if you run git-daemon with
+       This is sort of "GIT root" - if you run 'git-daemon' with
        '--base-path=/srv/git' on example.com, then if you later try to pull
-       'git://example.com/hello.git', `git-daemon` will interpret the path
+       'git://example.com/hello.git', 'git-daemon' will interpret the path
        as '/srv/git/hello.git'.
 
 --base-path-relaxed::
        If --base-path is enabled and repo lookup fails, with this option
-       `git-daemon` will attempt to lookup without prefixing the base path.
+       'git-daemon' will attempt to lookup without prefixing the base path.
        This is useful for switching to --base-path usage, while still
        allowing the old paths.
 
@@ -138,7 +138,7 @@ OPTIONS
 +
 Giving these options is an error when used with `--inetd`; use
 the facility of inet daemon to achieve the same before spawning
-`git-daemon` if needed.
+'git-daemon' if needed.
 
 --enable=service::
 --disable=service::
@@ -164,24 +164,24 @@ SERVICES
 
 These services can be globally enabled/disabled using the
 command line options of this command.  If a finer-grained
-control is desired (e.g. to allow `git-archive` to be run
+control is desired (e.g. to allow 'git-archive' to be run
 against only in a few selected repositories the daemon serves),
 the per-repository configuration file can be used to enable or
 disable them.
 
 upload-pack::
-       This serves `git-fetch-pack` and `git-ls-remote`
+       This serves 'git-fetch-pack' and 'git-ls-remote'
        clients.  It is enabled by default, but a repository can
        disable it by setting `daemon.uploadpack` configuration
        item to `false`.
 
 upload-archive::
-       This serves `git-archive --remote`.  It is disabled by
+       This serves 'git-archive --remote'.  It is disabled by
        default, but a repository can enable it by setting
        `daemon.uploadarch` configuration item to `true`.
 
 receive-pack::
-       This serves `git-send-pack` clients, allowing anonymous
+       This serves 'git-send-pack' clients, allowing anonymous
        push.  It is disabled by default, as there is _no_
        authentication in the protocol (in other words, anybody
        can push anything into the repository, including removal
@@ -199,28 +199,28 @@ $ grep 9418 /etc/services
 git            9418/tcp                # Git Version Control System
 ------------
 
-git-daemon as inetd server::
-       To set up `git-daemon` as an inetd service that handles any
+'git-daemon' as inetd server::
+       To set up 'git-daemon' as an inetd service that handles any
        repository under the whitelisted set of directories, /pub/foo
        and /pub/bar, place an entry like the following into
        /etc/inetd all on one line:
 +
 ------------------------------------------------
-       git stream tcp nowait nobody  /usr/bin/git-daemon
-               git-daemon --inetd --verbose --export-all
+       git stream tcp nowait nobody  /usr/bin/git
+               git daemon --inetd --verbose --export-all
                /pub/foo /pub/bar
 ------------------------------------------------
 
 
-git-daemon as inetd server for virtual hosts::
-       To set up `git-daemon` as an inetd service that handles
+'git-daemon' as inetd server for virtual hosts::
+       To set up 'git-daemon' as an inetd service that handles
        repositories for different virtual hosts, `www.example.com`
        and `www.example.org`, place an entry like the following into
        `/etc/inetd` all on one line:
 +
 ------------------------------------------------
-       git stream tcp nowait nobody /usr/bin/git-daemon
-               git-daemon --inetd --verbose --export-all
+       git stream tcp nowait nobody /usr/bin/git
+               git daemon --inetd --verbose --export-all
                --interpolated-path=/pub/%H%D
                /pub/www.example.org/software
                /pub/www.example.com/software
@@ -235,13 +235,13 @@ clients, a symlink from `/software` into the appropriate
 default repository could be made as well.
 
 
-git-daemon as regular daemon for virtual hosts::
-       To set up `git-daemon` as a regular, non-inetd service that
+'git-daemon' as regular daemon for virtual hosts::
+       To set up 'git-daemon' as a regular, non-inetd service that
        handles repositories for multiple virtual hosts based on
        their IP addresses, start the daemon like this:
 +
 ------------------------------------------------
-       git-daemon --verbose --export-all
+       git daemon --verbose --export-all
                --interpolated-path=/pub/%IP/%D
                /pub/192.168.1.200/software
                /pub/10.10.220.23/software
@@ -253,7 +253,7 @@ Repositories can still be accessed by hostname though, assuming
 they correspond to these IP addresses.
 
 selectively enable/disable services per repository::
-       To enable `git-archive --remote` and disable `git-fetch` against
+       To enable 'git-archive --remote' and disable 'git-fetch' against
        a repository, have the following in the configuration file in the
        repository (that is the file 'config' next to 'HEAD', 'refs' and
        'objects').
index 9f6f4831864a3112119bc7d7fec22aa7a72225e5..44b166888a00567d12f287416a6fa50135b36cfb 100644 (file)
@@ -8,7 +8,7 @@ git-describe - Show the most recent tag that is reachable from a commit
 
 SYNOPSIS
 --------
-'git-describe' [--all] [--tags] [--contains] [--abbrev=<n>] <committish>...
+'git describe' [--all] [--tags] [--contains] [--abbrev=<n>] <committish>...
 
 DESCRIPTION
 -----------
@@ -78,7 +78,7 @@ EXAMPLES
 
 With something like git.git current tree, I get:
 
-       [torvalds@g5 git]$ git-describe parent
+       [torvalds@g5 git]$ git describe parent
        v1.0.4-14-g2414721
 
 i.e. the current head of my "parent" branch is based on v1.0.4,
@@ -92,9 +92,9 @@ of commits which would be displayed by "git log v1.0.4..parent".
 The hash suffix is "-g" + 7-char abbreviation for the tip commit
 of parent (which was `2414721b194453f058079d897d13c4e377f92dc6`).
 
-Doing a "git-describe" on a tag-name will just show the tag name:
+Doing a 'git-describe' on a tag-name will just show the tag name:
 
-       [torvalds@g5 git]$ git-describe v1.0.4
+       [torvalds@g5 git]$ git describe v1.0.4
        v1.0.4
 
 With --all, the command can use branch heads as references, so
@@ -115,13 +115,13 @@ closest tagname without any suffix:
 SEARCH STRATEGY
 ---------------
 
-For each committish supplied "git describe" will first look for
+For each committish supplied, 'git-describe' will first look for
 a tag which tags exactly that commit.  Annotated tags will always
 be preferred over lightweight tags, and tags with newer dates will
 always be preferred over tags with older dates.  If an exact match
 is found, its name will be output and searching will stop.
 
-If an exact match was not found "git describe" will walk back
+If an exact match was not found, 'git-describe' will walk back
 through the commit history to locate an ancestor commit which
 has been tagged.  The ancestor's tag will be output along with an
 abbreviation of the input committish's SHA1.
@@ -129,7 +129,7 @@ abbreviation of the input committish's SHA1.
 If multiple tags were found during the walk then the tag which
 has the fewest commits different from the input committish will be
 selected and output.  Here fewest commits different is defined as
-the number of commits which would be shown by "git log tag..input"
+the number of commits which would be shown by `git log tag..input`
 will be the smallest number of commits possible.
 
 
index 8a64869d2705071afe3d1a122b6b85a086413a0a..5c8c1d95a89b15e936816f486a8114cbc6788fb9 100644 (file)
@@ -8,14 +8,14 @@ git-diff-files - Compares files in the working tree and the index
 
 SYNOPSIS
 --------
-'git-diff-files' [-q] [-0|-1|-2|-3|-c|--cc] [<common diff options>] [<path>...]
+'git diff-files' [-q] [-0|-1|-2|-3|-c|--cc] [<common diff options>] [<path>...]
 
 DESCRIPTION
 -----------
 Compares the files in the working tree and the index.  When paths
 are specified, compares only those named paths.  Otherwise all
 entries in the index are compared.  The output format is the
-same as "git-diff-index" and "git-diff-tree".
+same as for 'git-diff-index' and 'git-diff-tree'.
 
 OPTIONS
 -------
index f6e844fe61f66c02a448e7d8e48e9fecc6393bd0..26920d4f63cd213ff17ab28d8dd0dbea94482147 100644 (file)
@@ -8,7 +8,7 @@ git-diff-index - Compares content and mode of blobs between the index and reposi
 
 SYNOPSIS
 --------
-'git-diff-index' [-m] [--cached] [<common diff options>] <tree-ish> [<path>...]
+'git diff-index' [-m] [--cached] [<common diff options>] <tree-ish> [<path>...]
 
 DESCRIPTION
 -----------
@@ -31,7 +31,7 @@ include::diff-options.txt[]
 -m::
        By default, files recorded in the index but not checked
        out are reported as deleted.  This flag makes
-       "git-diff-index" say that all non-checked-out files are up
+       'git-diff-index' say that all non-checked-out files are up
        to date.
 
 Output format
@@ -50,31 +50,31 @@ Cached Mode
 If '--cached' is specified, it allows you to ask:
 
        show me the differences between HEAD and the current index
-       contents (the ones I'd write with a "git-write-tree")
+       contents (the ones I'd write using 'git-write-tree')
 
 For example, let's say that you have worked on your working directory, updated
 some files in the index and are ready to commit. You want to see exactly
 *what* you are going to commit, without having to write a new tree
 object and compare it that way, and to do that, you just do
 
-       git-diff-index --cached HEAD
+       git diff-index --cached HEAD
 
 Example: let's say I had renamed `commit.c` to `git-commit.c`, and I had
-done an "git-update-index" to make that effective in the index file.
-"git-diff-files" wouldn't show anything at all, since the index file
-matches my working directory. But doing a "git-diff-index" does:
+done an `update-index` to make that effective in the index file.
+`git diff-files` wouldn't show anything at all, since the index file
+matches my working directory. But doing a 'git-diff-index' does:
 
-  torvalds@ppc970:~/git> git-diff-index --cached HEAD
+  torvalds@ppc970:~/git> git diff-index --cached HEAD
   -100644 blob    4161aecc6700a2eb579e842af0b7f22b98443f74        commit.c
   +100644 blob    4161aecc6700a2eb579e842af0b7f22b98443f74        git-commit.c
 
 You can see easily that the above is a rename.
 
-In fact, "git-diff-index --cached" *should* always be entirely equivalent to
-actually doing a "git-write-tree" and comparing that. Except this one is much
+In fact, `git diff-index --cached` *should* always be entirely equivalent to
+actually doing a 'git-write-tree' and comparing that. Except this one is much
 nicer for the case where you just want to check where you are.
 
-So doing a "git-diff-index --cached" is basically very useful when you are
+So doing a 'git-diff-index --cached' is basically very useful when you are
 asking yourself "what have I already marked for being committed, and
 what's the difference to a previous tree".
 
@@ -82,23 +82,23 @@ Non-cached Mode
 ---------------
 The "non-cached" mode takes a different approach, and is potentially
 the more useful of the two in that what it does can't be emulated with
-a "git-write-tree" + "git-diff-tree". Thus that's the default mode.
+a 'git-write-tree' + 'git-diff-tree'. Thus that's the default mode.
 The non-cached version asks the question:
 
   show me the differences between HEAD and the currently checked out
   tree - index contents _and_ files that aren't up-to-date
 
 which is obviously a very useful question too, since that tells you what
-you *could* commit. Again, the output matches the "git-diff-tree -r"
+you *could* commit. Again, the output matches the 'git-diff-tree -r'
 output to a tee, but with a twist.
 
 The twist is that if some file doesn't match the index, we don't have
 a backing store thing for it, and we use the magic "all-zero" sha1 to
 show that. So let's say that you have edited `kernel/sched.c`, but
-have not actually done a "git-update-index" on it yet - there is no
+have not actually done a 'git-update-index' on it yet - there is no
 "object" associated with the new state, and you get:
 
-  torvalds@ppc970:~/v2.6/linux> git-diff-index HEAD
+  torvalds@ppc970:~/v2.6/linux> git diff-index HEAD
   *100644->100664 blob    7476bb......->000000......      kernel/sched.c
 
 i.e., it shows that the tree has changed, and that `kernel/sched.c` has is
@@ -106,11 +106,11 @@ not up-to-date and may contain new stuff. The all-zero sha1 means that to
 get the real diff, you need to look at the object in the working directory
 directly rather than do an object-to-object diff.
 
-NOTE: As with other commands of this type, "git-diff-index" does not
+NOTE: As with other commands of this type, 'git-diff-index' does not
 actually look at the contents of the file at all. So maybe
 `kernel/sched.c` hasn't actually changed, and it's just that you
 touched it. In either case, it's a note that you need to
-"git-update-index" it to make the index be in sync.
+'git-update-index' it to make the index be in sync.
 
 NOTE: You can have a mixture of files show up as "has been updated"
 and "is still dirty in the working directory" together. You can always
index 56caeb2d26f2f8eab1234be6f146201ded5b098a..0e45b58d8332cc9f48e0e18165f536adb94a5c6f 100644 (file)
@@ -9,7 +9,7 @@ git-diff-tree - Compares the content and mode of blobs found via two tree object
 SYNOPSIS
 --------
 [verse]
-'git-diff-tree' [--stdin] [-m] [-s] [-v] [--no-commit-id] [--pretty]
+'git diff-tree' [--stdin] [-m] [-s] [-v] [--no-commit-id] [--pretty]
              [-t] [-r] [-c | --cc] [--root] [<common diff options>]
              <tree-ish> [<tree-ish>] [<path>...]
 
@@ -20,7 +20,7 @@ Compares the content and mode of the blobs found via two tree objects.
 If there is only one <tree-ish> given, the commit is compared with its parents
 (see --stdin below).
 
-Note that "git-diff-tree" can use the tree encapsulated in a commit object.
+Note that 'git-diff-tree' can use the tree encapsulated in a commit object.
 
 OPTIONS
 -------
@@ -58,25 +58,25 @@ behavior.  This does not apply to the case where two <tree-ish>
 separated with a single space are given.
 
 -m::
-       By default, "git-diff-tree --stdin" does not show
+       By default, 'git-diff-tree --stdin' does not show
        differences for merge commits.  With this flag, it shows
        differences to that commit from all of its parents. See
        also '-c'.
 
 -s::
-       By default, "git-diff-tree --stdin" shows differences,
+       By default, 'git-diff-tree --stdin' shows differences,
        either in machine-readable form (without '-p') or in patch
        form (with '-p').  This output can be suppressed.  It is
        only useful with '-v' flag.
 
 -v::
-       This flag causes "git-diff-tree --stdin" to also show
+       This flag causes 'git-diff-tree --stdin' to also show
        the commit message before the differences.
 
 include::pretty-options.txt[]
 
 --no-commit-id::
-       git-diff-tree outputs a line with the commit ID when
+       'git-diff-tree' outputs a line with the commit ID when
        applicable.  This flag suppressed the commit ID output.
 
 -c::
@@ -112,13 +112,13 @@ Limiting Output
 If you're only interested in differences in a subset of files, for
 example some architecture-specific files, you might do:
 
-       git-diff-tree -r <tree-ish> <tree-ish> arch/ia64 include/asm-ia64
+       git diff-tree -r <tree-ish> <tree-ish> arch/ia64 include/asm-ia64
 
 and it will only show you what changed in those two directories.
 
 Or if you are searching for what changed in just `kernel/sched.c`, just do
 
-       git-diff-tree -r <tree-ish> <tree-ish> kernel/sched.c
+       git diff-tree -r <tree-ish> <tree-ish> kernel/sched.c
 
 and it will ignore all differences to other files.
 
@@ -129,7 +129,7 @@ so it can be used to name subdirectories.
 
 An example of normal usage is:
 
-  torvalds@ppc970:~/git> git-diff-tree 5319e4......
+  torvalds@ppc970:~/git> git diff-tree 5319e4......
   *100664->100664 blob    ac348b.......->a01513.......      git-fsck-objects.c
 
 which tells you that the last commit changed just one file (it's from
index 7acd428964a9e6ffc4b876ce01731c1daf3a72bc..c53eba557d0a242a0d8553d9569ce8b2eb86331b 100644 (file)
@@ -8,14 +8,14 @@ git-diff - Show changes between commits, commit and working tree, etc
 
 SYNOPSIS
 --------
-'git-diff' [<common diff options>] <commit>{0,2} [--] [<path>...]
+'git diff' [<common diff options>] <commit>{0,2} [--] [<path>...]
 
 DESCRIPTION
 -----------
 Show changes between two trees, a tree and the working tree, a
 tree and the index file, or the index file and the working tree.
 
-'git-diff' [--options] [--] [<path>...]::
+'git diff' [--options] [--] [<path>...]::
 
        This form is to view the changes you made relative to
        the index (staging area for the next commit).  In other
@@ -27,14 +27,14 @@ If exactly two paths are given, and at least one is untracked,
 compare the two files / directories. This behavior can be
 forced by --no-index.
 
-'git-diff' [--options] --cached [<commit>] [--] [<path>...]::
+'git diff' [--options] --cached [<commit>] [--] [<path>...]::
 
        This form is to view the changes you staged for the next
        commit relative to the named <commit>.  Typically you
        would want comparison with the latest commit, so if you
        do not give <commit>, it defaults to HEAD.
 
-'git-diff' [--options] <commit> [--] [<path>...]::
+'git diff' [--options] <commit> [--] [<path>...]::
 
        This form is to view the changes you have in your
        working tree relative to the named <commit>.  You can
@@ -42,23 +42,23 @@ forced by --no-index.
        branch name to compare with the tip of a different
        branch.
 
-'git-diff' [--options] <commit> <commit> [--] [<path>...]::
+'git diff' [--options] <commit> <commit> [--] [<path>...]::
 
        This is to view the changes between two arbitrary
        <commit>.
 
-'git-diff' [--options] <commit>..<commit> [--] [<path>...]::
+'git diff' [--options] <commit>..<commit> [--] [<path>...]::
 
        This is synonymous to the previous form.  If <commit> on
        one side is omitted, it will have the same effect as
        using HEAD instead.
 
-'git-diff' [--options] <commit>\...<commit> [--] [<path>...]::
+'git diff' [--options] <commit>\...<commit> [--] [<path>...]::
 
        This form is to view the changes on the branch containing
        and up to the second <commit>, starting at a common ancestor
-       of both <commit>.  "git-diff A\...B" is equivalent to
-       "git-diff $(git-merge-base A B) B".  You can omit any one
+       of both <commit>.  "git diff A\...B" is equivalent to
+       "git diff $(git-merge-base A B) B".  You can omit any one
        of <commit>, which has the same effect as using HEAD instead.
 
 Just in case if you are doing something exotic, it should be
index 332346cc5dfd7fffa3e80ad6ca6b413bbbfdb0c2..4956964d857fd27d27fbff54de724623b79286db 100644 (file)
@@ -8,23 +8,23 @@ git-fast-export - Git data exporter
 
 SYNOPSIS
 --------
-'git-fast-export [options]' | 'git-fast-import'
+'git fast-export [options]' | 'git fast-import'
 
 DESCRIPTION
 -----------
 This program dumps the given revisions in a form suitable to be piped
-into linkgit:git-fast-import[1].
+into 'git-fast-import'.
 
 You can use it as a human readable bundle replacement (see
 linkgit:git-bundle[1]), or as a kind of an interactive
-linkgit:git-filter-branch[1].
+'git-filter-branch'.
 
 
 OPTIONS
 -------
 --progress=<n>::
        Insert 'progress' statements every <n> objects, to be shown by
-       linkgit:git-fast-import[1] during import.
+       'git-fast-import' during import.
 
 --signed-tags=(verbatim|warn|strip|abort)::
        Specify how to handle signed tags.  Since any transformation
@@ -36,6 +36,26 @@ when encountering a signed tag.  With 'strip', the tags will be made
 unsigned, with 'verbatim', they will be silently exported
 and with 'warn', they will be exported, but you will see a warning.
 
+--export-marks=<file>::
+       Dumps the internal marks table to <file> when complete.
+       Marks are written one per line as `:markid SHA-1`. Only marks
+       for revisions are dumped; marks for blobs are ignored.
+       Backends can use this file to validate imports after they
+       have been completed, or to save the marks table across
+       incremental runs.  As <file> is only opened and truncated
+       at completion, the same path can also be safely given to
+       \--import-marks.
+
+--import-marks=<file>::
+       Before processing any input, load the marks specified in
+       <file>.  The input file must exist, must be readable, and
+       must use the same format as produced by \--export-marks.
++
+Any commits that have already been marked will not be exported again.
+If the backend uses a similar \--import-marks file, this allows for
+incremental bidirectional exporting of the repository by keeping the
+marks the same across runs.
+
 
 EXAMPLES
 --------
@@ -65,7 +85,7 @@ referenced by that revision range contains the string
 Limitations
 -----------
 
-Since linkgit:git-fast-import[1] cannot tag trees, you will not be
+Since 'git-fast-import' cannot tag trees, you will not be
 able to export the linux-2.6.git repository completely, as it contains
 a tag referencing a tree instead of a commit.
 
index 395c055f9571bfe66edd335ca84ac2c515ad2b86..2d01d0d1000d1ed3a65a5448029e1b9f6bbe6a39 100644 (file)
@@ -8,14 +8,14 @@ git-fast-import - Backend for fast Git data importers
 
 SYNOPSIS
 --------
-frontend | 'git-fast-import' [options]
+frontend | 'git fast-import' [options]
 
 DESCRIPTION
 -----------
 This program is usually not what the end user wants to run directly.
 Most end users want to use one of the existing frontend programs,
 which parses a specific type of foreign source and feeds the contents
-stored there to git-fast-import.
+stored there to 'git-fast-import'.
 
 fast-import reads a mixed command/data stream from standard input and
 writes one or more packfiles directly into the current repository.
@@ -24,7 +24,7 @@ updated branch and tag refs, fully updating the current repository
 with the newly imported data.
 
 The fast-import backend itself can import into an empty repository (one that
-has already been initialized by linkgit:git-init[1]) or incrementally
+has already been initialized by 'git-init') or incrementally
 update an existing populated repository.  Whether or not incremental
 imports are supported from a particular foreign source depends on
 the frontend program in use.
@@ -82,11 +82,11 @@ OPTIONS
        This information may be useful after importing projects
        whose total object set exceeds the 4 GiB packfile limit,
        as these commits can be used as edge points during calls
-       to linkgit:git-pack-objects[1].
+       to 'git-pack-objects'.
 
 --quiet::
        Disable all non-fatal output, making fast-import silent when it
-       is successful.  This option disables the output shown by
+       is successful.  This option disables the output shown by
        \--stats.
 
 --stats::
@@ -124,9 +124,9 @@ an ideal situation, given that most conversion tools are throw-away
 
 Parallel Operation
 ------------------
-Like `git-push` or `git-fetch`, imports handled by fast-import are safe to
+Like 'git-push' or 'git-fetch', imports handled by fast-import are safe to
 run alongside parallel `git repack -a -d` or `git gc` invocations,
-or any other Git operation (including `git prune`, as loose objects
+or any other Git operation (including 'git-prune', as loose objects
 are never used by fast-import).
 
 fast-import does not lock the branch or tag refs it is actively importing.
@@ -220,7 +220,7 @@ variation in formatting will cause fast-import to reject the value.
 +
 An example value is ``Tue Feb 6 11:22:18 2007 -0500''.  The Git
 parser is accurate, but a little on the lenient side.  It is the
-same parser used by linkgit:git-am[1] when applying patches
+same parser used by 'git-am' when applying patches
 received from email.
 +
 Some malformed strings may be accepted as valid dates.  In some of
@@ -256,7 +256,7 @@ timezone.
 This particular format is supplied as its short to implement and
 may be useful to a process that wants to create a new commit
 right now, without needing to use a working directory or
-linkgit:git-update-index[1].
+'git-update-index'.
 +
 If separate `author` and `committer` commands are used in a `commit`
 the timestamps may not match, as the system clock will be polled
@@ -654,7 +654,7 @@ recommended, as the frontend does not (easily) have access to the
 complete set of bytes which normally goes into such a signature.
 If signing is required, create lightweight tags from within fast-import with
 `reset`, then create the annotated versions of those tags offline
-with the standard linkgit:git-tag[1] process.
+with the standard 'git-tag' process.
 
 `reset`
 ~~~~~~~
@@ -803,7 +803,7 @@ Callers may wish to process the output through a tool such as sed to
 remove the leading part of the line, for example:
 
 ====
-       frontend | git-fast-import | sed 's/^progress //'
+       frontend | git fast-import | sed 's/^progress //'
 ====
 
 Placing a `progress` command immediately after a `checkpoint` will
@@ -851,7 +851,7 @@ An example crash:
        M 777 inline bob
        END_OF_INPUT
 
-       $ git-fast-import <in
+       $ git fast-import <in
        fatal: Corrupt mode: M 777 inline bob
        fast-import: dumping crash report to .git/fast_import_crash_8434
 
@@ -955,7 +955,7 @@ is not `refs/heads/TAG_FIXUP`).
 
 When committing fixups, consider using `merge` to connect the
 commit(s) which are supplying file revisions to the fixup branch.
-Doing so will allow tools such as linkgit:git-blame[1] to track
+Doing so will allow tools such as 'git-blame' to track
 through the real commit history and properly annotate the source
 files.
 
@@ -984,7 +984,7 @@ Repacking Historical Data
 ~~~~~~~~~~~~~~~~~~~~~~~~~
 If you are repacking very old imported data (e.g. older than the
 last year), consider expending some extra CPU time and supplying
-\--window=50 (or higher) when you run linkgit:git-repack[1].
+\--window=50 (or higher) when you run 'git-repack'.
 This will take longer, but will also produce a smaller packfile.
 You only need to expend the effort once, and everyone using your
 project will benefit from the smaller repository.
index 282fcaf17fed50ac51129dde8fcf105c1b9c11d9..47448da22eeebf51fe5829717df2dc7129a9b17e 100644 (file)
@@ -8,14 +8,14 @@ git-fetch-pack - Receive missing objects from another repository
 
 SYNOPSIS
 --------
-'git-fetch-pack' [--all] [--quiet|-q] [--keep|-k] [--thin] [--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] [--no-progress] [-v] [<host>:]<directory> [<refs>...]
+'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
 -----------
-Usually you would want to use linkgit:git-fetch[1] which is a
-higher level wrapper of this command instead.
+Usually you would want to use 'git-fetch', which is a
+higher level wrapper of this command, instead.
 
-Invokes 'git-upload-pack' on a potentially remote repository,
+Invokes 'git-upload-pack' on a possibly remote repository
 and asks it to send objects missing from this repository, to
 update the named heads.  The list of commits available locally
 is found out by scanning local $GIT_DIR/refs/ and sent to
index 489b2b17e69c0a0f6b2df0ce4b2da6f38f809546..9e048a8a280f896c0da2396b07eeeddd211f0b75 100644 (file)
@@ -8,7 +8,7 @@ git-fetch - Download objects and refs from another repository
 
 SYNOPSIS
 --------
-'git-fetch' <options> <repository> <refspec>...
+'git fetch' <options> <repository> <refspec>...
 
 
 DESCRIPTION
@@ -18,7 +18,7 @@ the objects necessary to complete them.
 
 The ref names and their object names of fetched refs are stored
 in `.git/FETCH_HEAD`.  This information is left for a later merge
-operation done by "git merge".
+operation done by 'git-merge'.
 
 When <refspec> stores the fetched result in tracking branches,
 the tags that point at these branches are automatically
index ea77f1fce505fbb9c1691f7e75aa014e7a1d5be5..a3edc0024600e34d956b8e8d76dd8a6a8bd6c8bd 100644 (file)
@@ -8,7 +8,7 @@ git-filter-branch - Rewrite branches
 SYNOPSIS
 --------
 [verse]
-'git-filter-branch' [--env-filter <command>] [--tree-filter <command>]
+'git filter-branch' [--env-filter <command>] [--tree-filter <command>]
        [--index-filter <command>] [--parent-filter <command>]
        [--msg-filter <command>] [--commit-filter <command>]
        [--tag-name-filter <command>] [--subdirectory-filter <directory>]
@@ -95,7 +95,7 @@ OPTIONS
        This is the filter for rewriting the commit's parent list.
        It will receive the parent string on stdin and shall output
        the new parent string on stdout.  The parent string is in
-       a format accepted by linkgit:git-commit-tree[1]: empty for
+       the format described in linkgit:git-commit-tree[1]: empty for
        the initial commit, "-p parent" for a normal commit and
        "-p parent1 -p parent2 -p parent3 ..." for a merge commit.
 
@@ -108,7 +108,7 @@ OPTIONS
 --commit-filter <command>::
        This is the filter for performing the commit.
        If this filter is specified, it will be called instead of the
-       linkgit:git-commit-tree[1] command, with arguments of the form
+       'git-commit-tree' command, with arguments of the form
        "<TREE_ID> [-p <PARENT_COMMIT_ID>]..." and the log message on
        stdin.  The commit id is expected on stdout.
 +
@@ -119,7 +119,7 @@ have all of them as parents.
 You can use the 'map' convenience function in this filter, and other
 convenience functions, too.  For example, calling 'skip_commit "$@"'
 will leave out the current commit (but not its changes! If you want
-that, use linkgit:git-rebase[1] instead).
+that, use 'git-rebase' instead).
 
 --tag-name-filter <command>::
        This is the filter for rewriting tag names. When passed,
@@ -163,13 +163,13 @@ to other tags will be rewritten to point to the underlying commit.
 
 -f::
 --force::
-       `git filter-branch` refuses to start with an existing temporary
+       'git-filter-branch' refuses to start with an existing temporary
        directory or when there are already refs starting with
        'refs/original/', unless forced.
 
 <rev-list-options>::
        When options are given after the new branch name, they will
-       be passed to linkgit:git-rev-list[1].  Only commits in the resulting
+       be passed to 'git-rev-list'.  Only commits in the resulting
        output will be filtered, although the filtered commits can still
        reference parents which are outside of that set.
 
@@ -255,7 +255,7 @@ and all children of the merge will become merge commits with P1,P2
 as their parents instead of the merge commit.
 
 You can rewrite the commit log messages using `--msg-filter`.  For
-example, `git-svn-id` strings in a repository created by `git-svn` can
+example, 'git-svn-id' strings in a repository created by 'git-svn' can
 be removed this way:
 
 -------------------------------------------------------
@@ -266,13 +266,13 @@ git filter-branch --msg-filter '
 
 To restrict rewriting to only part of the history, specify a revision
 range in addition to the new branch name.  The new branch name will
-point to the top-most revision that a 'git rev-list' of this range
+point to the top-most revision that a 'git-rev-list' of this range
 will print.
 
 *NOTE* the changes introduced by the commits, and which are not reverted
 by subsequent commits, will still be in the rewritten branch. If you want
 to throw out _changes_ together with the commits, you should use the
-interactive mode of linkgit:git-rebase[1].
+interactive mode of 'git-rebase'.
 
 
 Consider this history:
index 2a7cfb980b7f0b6fa2bd741b3601467f07025691..885edf005a8442dba6f509751f67f8c0e1939a08 100644 (file)
@@ -9,17 +9,17 @@ git-fmt-merge-msg - Produce a merge commit message
 SYNOPSIS
 --------
 [verse]
-git-fmt-merge-msg [--log | --no-log] <$GIT_DIR/FETCH_HEAD
-git-fmt-merge-msg [--log | --no-log] -F <file>
+'git fmt-merge-msg' [--log | --no-log] <$GIT_DIR/FETCH_HEAD
+'git fmt-merge-msg' [--log | --no-log] -F <file>
 
 DESCRIPTION
 -----------
 Takes the list of merged objects on stdin and produces a suitable
 commit message to be used for the merge commit, usually to be
-passed as the '<merge-message>' argument of `git-merge`.
+passed as the '<merge-message>' argument of 'git-merge'.
 
 This script is intended mostly for internal use by scripts
-automatically invoking `git-merge`.
+automatically invoking 'git-merge'.
 
 OPTIONS
 -------
index b347bfbb14784a4292124a4575086411a4697527..727d84e6735417baa82fe7abff5b6945f6d6cef4 100644 (file)
@@ -8,7 +8,7 @@ git-for-each-ref - Output information on each ref
 SYNOPSIS
 --------
 [verse]
-'git-for-each-ref' [--count=<count>] [--shell|--perl|--python|--tcl]
+'git for-each-ref' [--count=<count>] [--shell|--perl|--python|--tcl]
                   [--sort=<key>]\* [--format=<format>] [<pattern>...]
 
 DESCRIPTION
@@ -79,7 +79,7 @@ objecttype::
        The type of the object (`blob`, `tree`, `commit`, `tag`).
 
 objectsize::
-       The size of the object (the same as `git-cat-file -s` reports).
+       The size of the object (the same as 'git-cat-file -s' reports).
 
 objectname::
        The object name (aka SHA-1).
@@ -119,7 +119,7 @@ An example directly producing formatted text.  Show the most recent
 ------------
 #!/bin/sh
 
-git-for-each-ref --count=3 --sort='-*authordate' \
+git for-each-ref --count=3 --sort='-*authordate' \
 --format='From: %(*authorname) %(*authoremail)
 Subject: %(*subject)
 Date: %(*authordate)
@@ -135,7 +135,7 @@ demonstrating the use of --shell.  List the prefixes of all heads::
 ------------
 #!/bin/sh
 
-git-for-each-ref --shell --format="ref=%(refname)" refs/heads | \
+git for-each-ref --shell --format="ref=%(refname)" refs/heads | \
 while read entry
 do
        eval "$entry"
@@ -189,7 +189,7 @@ Its message reads as:
        fi
 '
 
-eval=`git-for-each-ref --shell --format="$fmt" \
+eval=`git for-each-ref --shell --format="$fmt" \
        --sort='*objecttype' \
        --sort=-taggerdate \
        refs/tags`
index 4dafa39a9211d9d35498f4c88418713b1aa33284..7c2ff3eb2d496a23bb5d2536c16097697ef8e236 100644 (file)
@@ -9,7 +9,7 @@ git-format-patch - Prepare patches for e-mail submission
 SYNOPSIS
 --------
 [verse]
-'git-format-patch' [-k] [-o <dir> | --stdout] [--thread]
+'git format-patch' [-k] [-o <dir> | --stdout] [--thread]
                   [--attach[=<boundary>] | --inline[=<boundary>]]
                   [-s | --signoff] [<common diff options>]
                   [-n | --numbered | -N | --no-numbered]
@@ -27,7 +27,7 @@ DESCRIPTION
 Prepare each commit with its patch in
 one file per commit, formatted to resemble UNIX mailbox format.
 The output of this command is convenient for e-mail submission or
-for use with linkgit:git-am[1].
+for use with 'git-am'.
 
 There are two ways to specify which commits to operate on.
 
@@ -61,7 +61,7 @@ they are created in the current working directory.
 If -n is specified, instead of "[PATCH] Subject", the first line
 is formatted as "[PATCH n/m] Subject".
 
-If given --thread, git-format-patch will generate In-Reply-To and
+If given --thread, 'git-format-patch' will generate In-Reply-To and
 References headers to make the second and subsequent patch mails appear
 as replies to the first mail; this also generates a Message-Id header to
 reference.
@@ -175,10 +175,10 @@ and file suffix, and number patches when outputting more than one.
 
 ------------
 [format]
-        headers = "Organization: git-foo\n"
-        subjectprefix = CHANGE
-        suffix = .txt
-        numbered = auto
+       headers = "Organization: git-foo\n"
+       subjectprefix = CHANGE
+       suffix = .txt
+       numbered = auto
        cc = <email>
 ------------
 
@@ -187,10 +187,10 @@ EXAMPLES
 --------
 
 * Extract commits between revisions R1 and R2, and apply them on top of
-the current branch using `git-am` to cherry-pick them:
+the current branch using 'git-am' to cherry-pick them:
 +
 ------------
-$ git format-patch -k --stdout R1..R2 | git-am -3 -k
+$ git format-patch -k --stdout R1..R2 | git am -3 -k
 ------------
 
 * Extract all commits which are in the current branch but not in the
@@ -206,7 +206,7 @@ For each commit a separate file is created in the current directory.
 project:
 +
 ------------
-$ git format-patch \--root origin
+$ git format-patch --root origin
 ------------
 
 * The same as the previous one:
index 6e9f717642e6db0caf6182ea49bbb60d2bc9583d..965a8279c1b17df6fbf82f4fbcadbd254049a7d5 100644 (file)
@@ -8,7 +8,7 @@ git-fsck-objects - Verifies the connectivity and validity of the objects in the
 
 SYNOPSIS
 --------
-'git-fsck-objects' ...
+'git fsck-objects' ...
 
 DESCRIPTION
 -----------
index 9846c859cf3f4c76525aae124e0ef516fa55779f..d5a76472196a5e67bc6e62411d90377ec3b46e3a 100644 (file)
@@ -9,7 +9,7 @@ git-fsck - Verifies the connectivity and validity of the objects in the database
 SYNOPSIS
 --------
 [verse]
-'git-fsck' [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]
+'git fsck' [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]
         [--full] [--strict] [--verbose] [--lost-found] [<object>*]
 
 DESCRIPTION
@@ -21,7 +21,7 @@ OPTIONS
 <object>::
        An object to treat as the head of an unreachability trace.
 +
-If no objects are given, git-fsck defaults to using the
+If no objects are given, 'git-fsck' defaults to using the
 index file, all SHA1 references in .git/refs/*, and all reflogs (unless
 --no-reflogs is given) as heads.
 
@@ -79,15 +79,15 @@ that aren't readable from any of the specified head nodes.
 
 So for example
 
-       git-fsck --unreachable HEAD $(cat .git/refs/heads/*)
+       git fsck --unreachable HEAD $(cat .git/refs/heads/*)
 
 will do quite a _lot_ of verification on the tree. There are a few
 extra validity tests to be added (make sure that tree objects are
-sorted properly etc), but on the whole if "git-fsck" is happy, you
+sorted properly etc), but on the whole if 'git-fsck' is happy, you
 do have a valid tree.
 
 Any corrupt objects you will have to find in backups or other archives
-(i.e., you can just remove them and do an "rsync" with some other site in
+(i.e., you can just remove them and do an 'rsync' with some other site in
 the hopes that somebody else has the object you have corrupted).
 
 Of course, "valid tree" doesn't mean that it wasn't generated by some
index 6ace615d807e3afe91800094e13797fc15d2bae4..7086eea74a38b036130f61db362bae209a065e47 100644 (file)
@@ -8,20 +8,20 @@ git-gc - Cleanup unnecessary files and optimize the local repository
 
 SYNOPSIS
 --------
-'git-gc' [--aggressive] [--auto] [--quiet]
+'git gc' [--aggressive] [--auto] [--quiet]
 
 DESCRIPTION
 -----------
 Runs a number of housekeeping tasks within the current repository,
 such as compressing file revisions (to reduce disk space and increase
 performance) and removing unreachable objects which may have been
-created from prior invocations of linkgit:git-add[1].
+created from prior invocations of 'git-add'.
 
 Users are encouraged to run this task on a regular basis within
 each repository to maintain good disk space utilization and good
 operating performance.
 
-Some git commands may automatically run `git-gc`; see the `--auto` flag
+Some git commands may automatically run 'git-gc'; see the `--auto` flag
 below for details. If you know what you're doing and all you want is to
 disable this behavior permanently without further considerations, just do:
 
@@ -35,13 +35,13 @@ OPTIONS
 --aggressive::
        Usually 'git-gc' runs very quickly while providing good disk
        space utilization and performance.  This option will cause
-       git-gc to more aggressively optimize the repository at the expense
+       'git-gc' to more aggressively optimize the repository at the expense
        of taking much more time.  The effects of this optimization are
        persistent, so this option only needs to be used occasionally; every
        few hundred changesets or so.
 
 --auto::
-       With this option, `git gc` checks whether any housekeeping is
+       With this option, 'git-gc' checks whether any housekeeping is
        required; if not, it exits without performing any work.
        Some git commands run `git gc --auto` after performing
        operations that could create many loose objects.
@@ -50,13 +50,13 @@ Housekeeping is required if there are too many loose objects or
 too many packs in the repository. If the number of loose objects
 exceeds the value of the `gc.auto` configuration variable, then
 all loose objects are combined into a single pack using
-`git-repack -d -l`.  Setting the value of `gc.auto` to 0
+'git-repack -d -l'.  Setting the value of `gc.auto` to 0
 disables automatic packing of loose objects.
 +
 If the number of packs exceeds the value of `gc.autopacklimit`,
 then existing packs (except those marked with a `.keep` file)
 are consolidated into a single pack by using the `-A` option of
-`git-repack`. Setting `gc.autopacklimit` to 0 disables
+'git-repack'. Setting `gc.autopacklimit` to 0 disables
 automatic consolidation of packs.
 
 --quiet::
@@ -89,7 +89,7 @@ how long records of conflicted merge you have not resolved are
 kept.  This defaults to 15 days.
 
 The optional configuration variable 'gc.packrefs' determines if
-`git gc` runs `git-pack-refs`. This can be set to "nobare" to enable
+'git-gc' runs 'git-pack-refs'. This can be set to "nobare" to enable
 it within all non-bare repos or it can be set to a boolean value.
 This defaults to true.
 
@@ -108,10 +108,10 @@ default is "2 weeks ago".
 Notes
 -----
 
-git-gc tries very hard to be safe about the garbage it collects. In
+'git-gc' tries very hard to be safe about the garbage it collects. In
 particular, it will keep not only objects referenced by your current set
 of branches and tags, but also objects referenced by the index, remote
-tracking branches, refs saved by linkgit:git-filter-branch[1] in
+tracking branches, refs saved by 'git-filter-branch' in
 refs/original/, or reflogs (which may references commits in branches
 that were later amended or rewound).
 
index c13bf98697e8e4aef236583f1dbcab21780b5013..84f23ee525336fc2bdd289991b97eafecddc14b2 100644 (file)
@@ -8,18 +8,18 @@ git-get-tar-commit-id - Extract commit ID from an archive created using git-arch
 
 SYNOPSIS
 --------
-'git-get-tar-commit-id' < <tarfile>
+'git get-tar-commit-id' < <tarfile>
 
 
 DESCRIPTION
 -----------
 Acts as a filter, extracting the commit ID stored in archives created by
-linkgit:git-archive[1].  It reads only the first 1024 bytes of input, thus its
+'git-archive'.  It reads only the first 1024 bytes of input, thus its
 runtime is not influenced by the size of <tarfile> very much.
 
-If no commit ID is found, git-get-tar-commit-id quietly exists with a
+If no commit ID is found, 'git-get-tar-commit-id' quietly exists with a
 return code of 1.  This can happen if <tarfile> had not been created
-using git-archive or if the first parameter of git-archive had been
+using 'git-archive' or if the first parameter of 'git-archive' had been
 a tree ID instead of a commit ID or tag.
 
 
index 1b646b73f069e72bc6faa3a058d61ace77c9934c..fa4d133c1bccc088d3c8da65bce4e15cafd394aa 100644 (file)
@@ -9,7 +9,7 @@ git-grep - Print lines matching a pattern
 SYNOPSIS
 --------
 [verse]
-'git-grep' [--cached]
+'git grep' [--cached]
           [-a | --text] [-I] [-i | --ignore-case] [-w | --word-regexp]
           [-v | --invert-match] [-h|-H] [--full-name]
           [-E | --extended-regexp] [-G | --basic-regexp]
@@ -91,7 +91,7 @@ OPTIONS
 --files-without-match::
        Instead of showing every matched line, show only the
        names of files that contain (or do not contain) matches.
-       For better compatibility with git-diff, --name-only is a
+       For better compatibility with 'git-diff', --name-only is a
        synonym for --files-with-matches.
 
 -c::
index 105397f2bdb6c947498d27e9926dbbe6e069056d..0e650f497bd456e633334a91bd929053a08eb0d3 100644 (file)
@@ -11,19 +11,19 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-A Tcl/Tk based graphical user interface to Git.  git-gui focuses
+A Tcl/Tk based graphical user interface to Git.  'git-gui' focuses
 on allowing users to make changes to their repository by making
 new commits, amending existing ones, creating branches, performing
 local merges, and fetching/pushing to remote repositories.
 
-Unlike linkgit:gitk[1], git-gui focuses on commit generation
-and single file annotation, and does not show project history.
-It does however supply menu actions to start a gitk session from
-within git-gui.
+Unlike 'gitk', 'git-gui' focuses on commit generation
+and single file annotation and does not show project history.
+It does however supply menu actions to start a 'gitk' session from
+within 'git-gui'.
 
-git-gui is known to work on all popular UNIX systems, Mac OS X,
+'git-gui' is known to work on all popular UNIX systems, Mac OS X,
 and Windows (under both Cygwin and MSYS).  To the extent possible
-OS specific user interface guidelines are followed, making git-gui
+OS specific user interface guidelines are followed, making 'git-gui'
 a fairly native interface for users.
 
 COMMANDS
@@ -34,17 +34,17 @@ blame::
 
 browser::
        Start a tree browser showing all files in the specified
-       commit (or 'HEAD' by default).  Files selected through the
+       commit (or 'HEAD' by default).  Files selected through the
        browser are opened in the blame viewer.
 
 citool::
-       Start git-gui and arrange to make exactly one commit before
+       Start 'git-gui' and arrange to make exactly one commit before
        exiting and returning to the shell.  The interface is limited
        to only commit actions, slightly reducing the application's
        startup time and simplifying the menubar.
 
 version::
-       Display the currently running version of git-gui.
+       Display the currently running version of 'git-gui'.
 
 
 Examples
@@ -61,7 +61,7 @@ git gui blame 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
+       and provide annotations for each line.  Unlike the above
        example the file is read from the object database and not
        the working directory.
 
@@ -71,7 +71,7 @@ git gui citool::
 
 git citool::
 
-       Same as 'git gui citool' (above).
+       Same as `git gui citool` (above).
 
 git gui browser maint::
 
@@ -84,15 +84,15 @@ SEE ALSO
 linkgit:gitk[1]::
        The git repository browser.  Shows branches, commit history
        and file differences.  gitk is the utility started by
-       git-gui's Repository Visualize actions.
+       'git-gui''s Repository Visualize actions.
 
 Other
 -----
-git-gui is actually maintained as an independent project, but stable
+'git-gui' is actually maintained as an independent project, but stable
 versions are distributed as part of the Git suite for the convenience
 of end users.
 
-A git-gui development repository can be obtained from:
+A 'git-gui' development repository can be obtained from:
 
   git clone git://repo.or.cz/git-gui.git
 
index cf3dce8a4a77d480a719260b7c8549c16f7c8e17..9e654fc41cc2b4a97806b2cb9430650214522711 100644 (file)
@@ -8,7 +8,7 @@ git-hash-object - Compute object ID and optionally creates a blob from a file
 
 SYNOPSIS
 --------
-'git-hash-object' [-t <type>] [-w] [--stdin | --stdin-paths] [--] <file>...
+'git hash-object' [-t <type>] [-w] [--stdin | --stdin-paths] [--] <file>...
 
 DESCRIPTION
 -----------
@@ -16,7 +16,7 @@ Computes the object ID value for an object with specified type
 with the contents of the named file (which can be outside of the
 work tree), and optionally writes the resulting object into the
 object database.  Reports its object ID to its standard output.
-This is used by "git-cvsimport" to update the index
+This is used by 'git-cvsimport' to update the index
 without modifying files in the work tree.  When <type> is not
 specified, it defaults to "blob".
 
index faecd6bb907b9622aa0a6a3a9fab2665c867354e..f414583fc48e85e4785fbf5f9431bb81a96ccd9d 100644 (file)
@@ -23,7 +23,7 @@ If a git command is named, a manual page for that command is brought
 up. The 'man' program is used by default for this purpose, but this
 can be overridden by other options or configuration variables.
 
-Note that 'git --help ...' is identical as 'git help ...' because the
+Note that `git --help ...` is identical to `git help ...` because the
 former is internally converted into the latter.
 
 OPTIONS
@@ -120,7 +120,7 @@ man.<tool>.path
 You can explicitly provide a full path to your preferred man viewer by
 setting the configuration variable 'man.<tool>.path'. For example, you
 can configure the absolute path to konqueror by setting
-'man.konqueror.path'. Otherwise, 'git help' assumes the tool is
+'man.konqueror.path'. Otherwise, 'git-help' assumes the tool is
 available in PATH.
 
 man.<tool>.cmd
index 70fb635291876e20acbc75451c875dcecffa9056..e7c796155fdd0ad644decf5dc488c6d780a2d164 100644 (file)
@@ -8,7 +8,7 @@ git-http-fetch - Download from a remote git repository via HTTP
 
 SYNOPSIS
 --------
-'git-http-fetch' [-c] [-t] [-a] [-d] [-v] [-w filename] [--recover] [--stdin] <commit> <url>
+'git http-fetch' [-c] [-t] [-a] [-d] [-v] [-w filename] [--recover] [--stdin] <commit> <url>
 
 DESCRIPTION
 -----------
index d69b20549bf956a5c7c3f64f5315a17ec71af038..aef383e0b142bd603b77620cad720c102d70c4b7 100644 (file)
@@ -8,7 +8,7 @@ git-http-push - Push objects over HTTP/DAV to another repository
 
 SYNOPSIS
 --------
-'git-http-push' [--all] [--dry-run] [--force] [--verbose] <url> <ref> [<ref>...]
+'git http-push' [--all] [--dry-run] [--force] [--verbose] <url> <ref> [<ref>...]
 
 DESCRIPTION
 -----------
index f4fdc242839d52ea97a32780526b133655ef9762..b3d8da33ee64730794821440c287f30c4bb85789 100644 (file)
@@ -8,7 +8,7 @@ git-imap-send - Dump a mailbox from stdin into an imap folder
 
 SYNOPSIS
 --------
-'git-imap-send'
+'git imap-send'
 
 
 DESCRIPTION
@@ -20,13 +20,13 @@ files directly.
 
 Typical usage is something like:
 
-git-format-patch --signoff --stdout --attach origin | git-imap-send
+git format-patch --signoff --stdout --attach origin | git imap-send
 
 
 CONFIGURATION
 -------------
 
-git-imap-send requires the following values in the repository
+'git-imap-send' requires the following values in the repository
 configuration file (shown with examples):
 
 ..........................
index 6409363ae5e80264b5b45d50bd9a0180ec68e05b..4b5c743c1e5f11281e2b9df7508d57e9878ee5d2 100644 (file)
@@ -9,8 +9,8 @@ git-index-pack - Build pack index file for an existing packed archive
 SYNOPSIS
 --------
 [verse]
-'git-index-pack' [-v] [-o <index-file>] <pack-file>
-'git-index-pack' --stdin [--fix-thin] [--keep] [-v] [-o <index-file>]
+'git index-pack' [-v] [-o <index-file>] <pack-file>
+'git index-pack' --stdin [--fix-thin] [--keep] [-v] [-o <index-file>]
                  [<pack-file>]
 
 
@@ -43,10 +43,10 @@ OPTIONS
        a default name determined from the pack content.  If
        <pack-file> is not specified consider using --keep to
        prevent a race condition between this process and
-       linkgit:git-repack[1].
+       'git-repack'.
 
 --fix-thin::
-       It is possible for linkgit:git-pack-objects[1] to build
+       It is possible for 'git-pack-objects' to build
        "thin" pack, which records objects in deltified form based on
        objects not included in the pack to reduce network traffic.
        Those objects are expected to be present on the receiving end
@@ -59,7 +59,7 @@ OPTIONS
        Before moving the index into its final destination
        create an empty .keep file for the associated pack file.
        This option is usually necessary with --stdin to prevent a
-       simultaneous linkgit:git-repack[1] process from deleting
+       simultaneous 'git-repack' process from deleting
        the newly constructed pack and index before refs can be
        updated to use objects contained in the pack.
 
@@ -86,7 +86,7 @@ Once the index has been created, the list of object names is sorted
 and the SHA1 hash of that list is printed to stdout. If --stdin was
 also used then this is prefixed by either "pack\t", or "keep\t" if a
 new .keep file was successfully created. This is useful to remove a
-.keep file used as a lock to prevent the race with linkgit:git-repack[1]
+.keep file used as a lock to prevent the race with 'git-repack'
 mentioned above.
 
 
index 439cabb737a48e009ea0a3a4e5bb323c1b2ccca9..1fd0ff2610a1375bcf0defe2a234b2dee1a7997a 100644 (file)
@@ -8,7 +8,7 @@ git-init-db - Creates an empty git repository
 
 SYNOPSIS
 --------
-'git-init-db' [-q | --quiet] [--template=<template_directory>] [--shared[=<permissions>]]
+'git init-db' [-q | --quiet] [--template=<template_directory>] [--shared[=<permissions>]]
 
 
 DESCRIPTION
index 792643c80916f4b72704f046c0de89d8d55fa17c..71749c09d309f4cae2da9788969359d2620224a9 100644 (file)
@@ -8,7 +8,7 @@ git-init - Create an empty git repository or reinitialize an existing one
 
 SYNOPSIS
 --------
-'git-init' [-q | --quiet] [--bare] [--template=<template_directory>] [--shared[=<permissions>]]
+'git init' [-q | --quiet] [--bare] [--template=<template_directory>] [--shared[=<permissions>]]
 
 
 OPTIONS
@@ -86,11 +86,11 @@ If the object storage directory is specified via the `$GIT_OBJECT_DIRECTORY`
 environment variable then the sha1 directories are created underneath -
 otherwise the default `$GIT_DIR/objects` directory is used.
 
-Running `git-init` in an existing repository is safe. It will not overwrite
-things that are already there. The primary reason for rerunning `git-init`
+Running 'git-init' in an existing repository is safe. It will not overwrite
+things that are already there. The primary reason for rerunning 'git-init'
 is to pick up newly added templates.
 
-Note that `git-init` is the same as `git-init-db`.  The command
+Note that 'git-init' is the same as 'git-init-db'.  The command
 was primarily meant to initialize the object database, but over
 time it has become responsible for setting up the other aspects
 of the repository, such as installing the default hooks and
@@ -105,8 +105,8 @@ Start a new git repository for an existing code base::
 +
 ----------------
 $ cd /path/to/my/codebase
-$ git-init      <1>
-$ git-add .     <2>
+$ git init      <1>
+$ git add .     <2>
 ----------------
 +
 <1> prepare /path/to/my/codebase/.git directory
index 7da5b8d9a9af04a5bf2188523587b086301bfd67..22da21a54f625c434216945889127ec283d3d09f 100644 (file)
@@ -8,13 +8,13 @@ git-instaweb - Instantly browse your working repository in gitweb
 SYNOPSIS
 --------
 [verse]
-'git-instaweb' [--local] [--httpd=<httpd>] [--port=<port>]
+'git instaweb' [--local] [--httpd=<httpd>] [--port=<port>]
                [--browser=<browser>]
-'git-instaweb' [--start] [--stop] [--restart]
+'git instaweb' [--start] [--stop] [--restart]
 
 DESCRIPTION
 -----------
-A simple script to setup gitweb and a web server for browsing the local
+A simple script to set up `gitweb` and a web server for browsing the local
 repository.
 
 OPTIONS
index db61bc96c7e23132c41bb75724d669a6224a3d76..5a58d5b03ded77d04d3de0857a798b6d3193adb2 100644 (file)
@@ -8,15 +8,15 @@ git-log - Show commit logs
 
 SYNOPSIS
 --------
-'git-log' <option>...
+'git log' <option>...
 
 DESCRIPTION
 -----------
 Shows the commit logs.
 
-The command takes options applicable to the linkgit:git-rev-list[1]
+The command takes options applicable to the 'git-rev-list'
 command to control what is shown and how, and options applicable to
-the linkgit:git-diff-tree[1] commands to control how the changes
+the 'git-diff-*' commands to control how the changes
 each commit introduces are shown.
 
 
index 4dc475e0de14ea5daf8594f023dd6f6d1993c867..602b8d5d4de8f7649cb88e6622108c012f484933 100644 (file)
@@ -7,7 +7,7 @@ git-lost-found - Recover lost refs that luckily have not yet been pruned
 
 SYNOPSIS
 --------
-'git-lost-found'
+'git lost-found'
 
 DESCRIPTION
 -----------
index 560594e25fdb4ef73aaaba55576c41d704f9ef8b..f43af417404d4f0f658933d57742d23c847f1619 100644 (file)
@@ -9,7 +9,7 @@ git-ls-files - Show information about files in the index and the working tree
 SYNOPSIS
 --------
 [verse]
-'git-ls-files' [-z] [-t] [-v]
+'git ls-files' [-z] [-t] [-v]
                (--[cached|deleted|others|ignored|stage|unmerged|killed|modified])\*
                (-[c|d|o|i|s|u|k|m])\*
                [-x <pattern>|--exclude=<pattern>]
@@ -143,14 +143,14 @@ which case it outputs:
 
         [<tag> ]<mode> <object> <stage> <file>
 
-"git-ls-files --unmerged" and "git-ls-files --stage" can be used to examine
+'git-ls-files --unmerged' and 'git-ls-files --stage' can be used to examine
 detailed information on unmerged paths.
 
 For an unmerged path, instead of recording a single mode/SHA1 pair,
 the index records up to three such pairs; one from tree O in stage
 1, A in stage 2, and B in stage 3.  This information can be used by
 the user (or the porcelain) to see what should eventually be recorded at the
-path. (see git-read-tree for more information on state)
+path. (see linkgit:git-read-tree[1] for more information on state)
 
 When `-z` option is not used, TAB, LF, and backslash characters
 in pathnames are represented as `\t`, `\n`, and `\\`,
index f92f3ca1860f9d3e0d5b3f21674a9c2baf61b4d9..4f252441ed6a5fb0348012e76134aad3d3ddde65 100644 (file)
@@ -9,7 +9,7 @@ git-ls-remote - List references in a remote repository
 SYNOPSIS
 --------
 [verse]
-'git-ls-remote' [--heads] [--tags]  [-u <exec> | --upload-pack <exec>]
+'git ls-remote' [--heads] [--tags]  [-u <exec> | --upload-pack <exec>]
              <repository> <refs>...
 
 DESCRIPTION
@@ -31,7 +31,7 @@ OPTIONS
 
 -u <exec>::
 --upload-pack=<exec>::
-       Specify the full path of linkgit:git-upload-pack[1] on the remote
+       Specify the full path of 'git-upload-pack' on the remote
        host. This allows listing references from repositories accessed via
        SSH and where the SSH daemon does not use the PATH configured by the
        user.
index d9881fbbbedb84f400bf0b630dcb60acd5ad4e9e..1cdec222a1998d90df750d7dfeb8f9b528965aed 100644 (file)
@@ -9,7 +9,7 @@ git-ls-tree - List the contents of a tree object
 SYNOPSIS
 --------
 [verse]
-'git-ls-tree' [-d] [-r] [-t] [-l] [-z]
+'git ls-tree' [-d] [-r] [-t] [-l] [-z]
            [--name-only] [--name-status] [--full-name] [--abbrev=[<n>]]
            <tree-ish> [paths...]
 
index 183dc1dd75c1268b199257496ac778e0d5dd7743..316bcc679628c47c9734e0906665ce5f6e8e68fb 100644 (file)
@@ -8,7 +8,7 @@ git-mailinfo - Extracts patch and authorship from a single e-mail message
 
 SYNOPSIS
 --------
-'git-mailinfo' [-k] [-u | --encoding=<encoding>] <msg> <patch>
+'git mailinfo' [-k] [-u | --encoding=<encoding> | -n] <msg> <patch>
 
 
 DESCRIPTION
@@ -16,7 +16,7 @@ DESCRIPTION
 Reading a single e-mail message from the standard input, and
 writes the commit log message in <msg> file, and the patches in
 <patch> file.  The author name, e-mail and e-mail subject are
-written out to the standard output to be used by git-am
+written out to the standard output to be used by 'git-am'
 to create a commit.  It is usually not necessary to use this
 command directly.  See linkgit:git-am[1] instead.
 
@@ -29,8 +29,8 @@ OPTIONS
        among which (1) remove 'Re:' or 're:', (2) leading
        whitespaces, (3) '[' up to ']', typically '[PATCH]', and
        then prepends "[PATCH] ".  This flag forbids this
-       munging, and is most useful when used to read back 'git
-       format-patch -k' output.
+       munging, and is most useful when used to read back
+       'git-format-patch -k' output.
 
 -u::
        The commit log message, author name and author email are
@@ -46,6 +46,9 @@ conversion, even with this flag.
        from what is specified by i18n.commitencoding, this flag
        can be used to override it.
 
+-n::
+       Disable all charset re-coding of the metadata.
+
 <msg>::
        The commit log message extracted from e-mail, usually
        except the title line which comes from e-mail Subject.
index 9a2aedd480c24018d12bde419b69f865be2b8825..acd712b1cd75164acb78df38942aa1a35e4d80ca 100644 (file)
@@ -7,7 +7,7 @@ git-mailsplit - Simple UNIX mbox splitter program
 
 SYNOPSIS
 --------
-'git-mailsplit' [-b] [-f<nn>] [-d<prec>] -o<directory> [--] [<mbox>|<Maildir>...]
+'git mailsplit' [-b] [-f<nn>] [-d<prec>] -o<directory> [--] [<mbox>|<Maildir>...]
 
 DESCRIPTION
 -----------
index bbe85123977e3fc11abc2fc9f16489215b4bd7a3..1a7ecbf8f39381b0c7b2da513dfa26eacec15cf6 100644 (file)
@@ -8,20 +8,20 @@ git-merge-base - Find as good common ancestors as possible for a merge
 
 SYNOPSIS
 --------
-'git-merge-base' [--all] <commit> <commit>
+'git merge-base' [--all] <commit> <commit>
 
 DESCRIPTION
 -----------
 
-"git-merge-base" finds as good a common ancestor as possible between
-the two commits. That is, given two commits A and B 'git-merge-base A
-B' will output a commit which is reachable from both A and B through
+'git-merge-base' finds as good a common ancestor as possible between
+the two commits. That is, given two commits A and B, `git merge-base A
+B` will output a commit which is reachable from both A and B through
 the parent relationship.
 
 Given a selection of equally good common ancestors it should not be
 relied on to decide in any particular way.
 
-The "git-merge-base" algorithm is still in flux - use the source...
+The 'git-merge-base' algorithm is still in flux - use the source...
 
 OPTIONS
 -------
index 149f1310519bb5b732fca0926f786f80a153f8da..024ec015a3a3e0d3677a82e082e72a36c4572827 100644 (file)
@@ -9,21 +9,21 @@ git-merge-file - Run a three-way file merge
 SYNOPSIS
 --------
 [verse]
-'git-merge-file' [-L <current-name> [-L <base-name> [-L <other-name>]]]
+'git merge-file' [-L <current-name> [-L <base-name> [-L <other-name>]]]
        [-p|--stdout] [-q|--quiet] <current-file> <base-file> <other-file>
 
 
 DESCRIPTION
 -----------
-git-file-merge incorporates all changes that lead from the `<base-file>`
+'git-file-merge' incorporates all changes that lead from the `<base-file>`
 to `<other-file>` into `<current-file>`. The result ordinarily goes into
-`<current-file>`. git-merge-file is useful for combining separate changes
+`<current-file>`. 'git-merge-file' is useful for combining separate changes
 to an original. Suppose `<base-file>` is the original, and both
 `<current-file>` and `<other-file>` are modifications of `<base-file>`.
-Then git-merge-file combines both changes.
+Then 'git-merge-file' combines both changes.
 
 A conflict occurs if both `<current-file>` and `<other-file>` have changes
-in a common segment of lines. If a conflict is found, git-merge-file
+in a common segment of lines. If a conflict is found, 'git-merge-file'
 normally outputs a warning and brackets the conflict with <<<<<<< and
 >>>>>>> lines. A typical conflict will look like this:
 
@@ -39,8 +39,8 @@ the alternatives.
 The exit value of this program is negative on error, and the number of
 conflicts otherwise. If the merge was clean, the exit value is 0.
 
-git-merge-file is designed to be a minimal clone of RCS merge, that is, it
-implements all of RCS merge's functionality which is needed by
+'git-merge-file' is designed to be a minimal clone of RCS 'merge'; that is, it
+implements all of RCS 'merge''s functionality which is needed by
 linkgit:git[1].
 
 
@@ -51,7 +51,7 @@ OPTIONS
        This option may be given up to three times, and
        specifies labels to be used in place of the
        corresponding file names in conflict reports. That is,
-       `git-merge-file -L x -L y -L z a b c` generates output that
+       `git merge-file -L x -L y -L z a b c` generates output that
        looks like it came from files x, y and z instead of
        from files a, b and c.
 
@@ -85,7 +85,7 @@ Written by Johannes Schindelin <johannes.schindelin@gmx.de>
 Documentation
 --------------
 Documentation by Johannes Schindelin and the git-list <git@vger.kernel.org>,
-with parts copied from the original documentation of RCS merge.
+with parts copied from the original documentation of RCS 'merge'.
 
 GIT
 ---
index a0ead2bbf33d7b244ec94e6f7dc06c062e52cb8d..ff088c5c294527dd97c542012483aafe3ca64314 100644 (file)
@@ -8,7 +8,7 @@ git-merge-index - Run a merge for files needing merging
 
 SYNOPSIS
 --------
-'git-merge-index' [-o] [-q] <merge-program> (-a | [--] <file>\*)
+'git merge-index' [-o] [-q] <merge-program> (-a | [--] <file>\*)
 
 DESCRIPTION
 -----------
@@ -36,24 +36,24 @@ OPTIONS
        failure usually indicates conflicts during merge). This is for
        porcelains which might want to emit custom messages.
 
-If "git-merge-index" is called with multiple <file>s (or -a) then it
+If 'git-merge-index' is called with multiple <file>s (or -a) then it
 processes them in turn only stopping if merge returns a non-zero exit
 code.
 
 Typically this is run with a script calling git's imitation of
-the merge command from the RCS package.
+the 'merge' command from the RCS package.
 
-A sample script called "git-merge-one-file" is included in the
+A sample script called 'git-merge-one-file' is included in the
 distribution.
 
 ALERT ALERT ALERT! The git "merge object order" is different from the
-RCS "merge" program merge object order. In the above ordering, the
+RCS 'merge' program merge object order. In the above ordering, the
 original is first. But the argument order to the 3-way merge program
-"merge" is to have the original in the middle. Don't ask me why.
+'merge' is to have the original in the middle. Don't ask me why.
 
 Examples:
 
-  torvalds@ppc970:~/merge-test> git-merge-index cat MM
+  torvalds@ppc970:~/merge-test> git merge-index cat MM
   This is MM from the original tree.                   # original
   This is modified MM in the branch A.                 # merge1
   This is modified MM in the branch B.                 # merge2
@@ -61,17 +61,17 @@ Examples:
 
 or
 
-  torvalds@ppc970:~/merge-test> git-merge-index cat AA MM
+  torvalds@ppc970:~/merge-test> git merge-index cat AA MM
   cat: : No such file or directory
   This is added AA in the branch A.
   This is added AA in the branch B.
   This is added AA in the branch B.
   fatal: merge program failed
 
-where the latter example shows how "git-merge-index" will stop trying to
-merge once anything has returned an error (i.e., "cat" returned an error
+where the latter example shows how 'git-merge-index' will stop trying to
+merge once anything has returned an error (i.e., `cat` returned an error
 for the AA file, because it didn't exist in the original, and thus
-"git-merge-index" didn't even try to merge the MM thing).
+'git-merge-index' didn't even try to merge the MM thing).
 
 Author
 ------
index 5c9ce641ec814a980b9a5d32291cccba32a0cc8b..1dd134538da40a1f3547c55c49be3b418e6be0ab 100644 (file)
@@ -12,8 +12,8 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-This is the standard helper program to use with "git-merge-index"
-to resolve a merge after the trivial merge done with "git-read-tree -m".
+This is the standard helper program to use with 'git-merge-index'
+to resolve a merge after the trivial merge done with 'git-read-tree -m'.
 
 Author
 ------
index b785e0f6e0c02ef688d4c6a60e19939aafd1a8d3..dbb0c18668ff0fb60c31c12b02c27d92b430c24a 100644 (file)
@@ -8,7 +8,7 @@ git-merge-tree - Show three-way merge without touching index
 
 SYNOPSIS
 --------
-'git-merge-tree' <base-tree> <branch1> <branch2>
+'git merge-tree' <base-tree> <branch1> <branch2>
 
 DESCRIPTION
 -----------
index 55bc3674797366496d7c1ca1f5b6564b06c01de1..62f99b5f3b8991c93d0f2e06cd382312069bccaf 100644 (file)
@@ -9,9 +9,9 @@ git-merge - Join two or more development histories together
 SYNOPSIS
 --------
 [verse]
-'git-merge' [-n] [--stat] [--no-commit] [--squash] [-s <strategy>]...
+'git merge' [-n] [--stat] [--no-commit] [--squash] [-s <strategy>]...
        [-m <msg>] <remote> <remote>...
-'git-merge' <msg> HEAD <remote>...
+'git merge' <msg> HEAD <remote>...
 
 DESCRIPTION
 -----------
@@ -29,8 +29,8 @@ include::merge-options.txt[]
 
 -m <msg>::
        The commit message to be used for the merge commit (in case
-       it is created). The `git-fmt-merge-msg` script can be used
-       to give a good default for automated `git-merge` invocations.
+       it is created). The 'git-fmt-merge-msg' script can be used
+       to give a good default for automated 'git-merge' invocations.
 
 <remote>::
        Other branch head merged into our branch.  You need at
@@ -41,8 +41,7 @@ include::merge-strategies.txt[]
 
 
 If you tried a merge which resulted in a complex conflicts and
-would want to start over, you can recover with
-linkgit:git-reset[1].
+would want to start over, you can recover with 'git-reset'.
 
 CONFIGURATION
 -------------
@@ -50,7 +49,7 @@ include::merge-config.txt[]
 
 branch.<name>.mergeoptions::
        Sets default options for merging into branch <name>. The syntax and
-       supported options are equal to that of git-merge, but option values
+       supported options are equal to that of 'git-merge', but option values
        containing whitespace characters are currently not supported.
 
 HOW MERGE WORKS
@@ -60,7 +59,7 @@ A merge is always between the current `HEAD` and one or more
 commits (usually, branch head or tag), and the index file must
 exactly match the
 tree of `HEAD` commit (i.e. the contents of the last commit) when
-it happens.  In other words, `git-diff --cached HEAD` must
+it happens.  In other words, `git diff --cached HEAD` must
 report no changes.
 
 [NOTE]
@@ -85,7 +84,7 @@ with `git pull remote rbranch:lbranch`, but your working tree,
 `.git/HEAD` pointer and index file are left intact).
 
 You may have local modifications in the working tree files.  In
-other words, `git-diff` is allowed to report changes.
+other words, 'git-diff' is allowed to report changes.
 However, the merge uses your working tree as the working area,
 and in order to prevent the merge operation from losing such
 changes, it makes sure that they do not interfere with the
@@ -128,7 +127,7 @@ When there are conflicts, these things happen:
 3. For conflicting paths, the index file records up to three
    versions; stage1 stores the version from the common ancestor,
    stage2 from `HEAD`, and stage3 from the remote branch (you
-   can inspect the stages with `git-ls-files -u`).  The working
+   can inspect the stages with `git ls-files -u`).  The working
    tree files have the result of "merge" program; i.e. 3-way
    merge result with familiar conflict markers `<<< === >>>`.
 
@@ -141,21 +140,24 @@ After seeing a conflict, you can do two things:
 
  * Decide not to merge.  The only clean-up you need are to reset
    the index file to the `HEAD` commit to reverse 2. and to clean
-   up working tree changes made by 2. and 3.; `git-reset` can
+   up working tree changes made by 2. and 3.; 'git-reset' can
    be used for this.
 
- * Resolve the conflicts.  `git-diff` would report only the
-   conflicting paths because of the above 2. and 3..  Edit the
-   working tree files into a desirable shape, `git-add` or `git-rm`
+ * Resolve the conflicts.  `git diff` would report only the
+   conflicting paths because of the above 2. and 3.  Edit the
+   working tree files into a desirable shape, 'git-add' or 'git-rm'
    them, to make the index file contain what the merge result
-   should be, and run `git-commit` to commit the result.
+   should be, and run 'git-commit' to commit the result.
 
 
 SEE ALSO
 --------
 linkgit:git-fmt-merge-msg[1], linkgit:git-pull[1],
-linkgit:gitattributes[5]
-
+linkgit:gitattributes[5],
+linkgit:git-reset[1],
+linkgit:git-diff[1], linkgit:git-ls-files[1],
+linkgit:git-add[1], linkgit:git-rm[1],
+linkgit:git-mergetool[1]
 
 Author
 ------
index 83525609c6ff3e4d82c9e8021b3107517c682496..31570b1e27af6a603df98868c627da08d91c17cc 100644 (file)
@@ -7,17 +7,17 @@ git-mergetool - Run merge conflict resolution tools to resolve merge conflicts
 
 SYNOPSIS
 --------
-'git-mergetool' [--tool=<tool>] [<file>]...
+'git mergetool' [--tool=<tool>] [<file>]...
 
 DESCRIPTION
 -----------
 
 Use `git mergetool` to run one of several merge utilities to resolve
-merge conflicts.  It is typically run after linkgit:git-merge[1].
+merge conflicts.  It is typically run after 'git-merge'.
 
 If one or more <file> parameters are given, the merge tool program will
 be run to resolve differences on each file.  If no <file> names are
-specified, `git mergetool` will run the merge tool program on every file
+specified, 'git-mergetool' will run the merge tool program on every file
 with merge conflicts.
 
 OPTIONS
@@ -27,23 +27,23 @@ OPTIONS
        Valid merge tools are:
        kdiff3, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff, ecmerge, and opendiff
 +
-If a merge resolution program is not specified, `git mergetool`
+If a merge resolution program is not specified, 'git-mergetool'
 will use the configuration variable `merge.tool`.  If the
-configuration variable `merge.tool` is not set, `git mergetool`
+configuration variable `merge.tool` is not set, 'git-mergetool'
 will pick a suitable default.
 +
 You can explicitly provide a full path to the tool by setting the
 configuration variable `mergetool.<tool>.path`. For example, you
 can configure the absolute path to kdiff3 by setting
-`mergetool.kdiff3.path`. Otherwise, `git mergetool` assumes the
+`mergetool.kdiff3.path`. Otherwise, 'git-mergetool' assumes the
 tool is available in PATH.
 +
 Instead of running one of the known merge tool programs
-`git mergetool` can be customized to run an alternative program
+'git-mergetool' can be customized to run an alternative program
 by specifying the command line to invoke in a configration
 variable `mergetool.<tool>.cmd`.
 +
-When `git mergetool` is invoked with this tool (either through the
+When 'git-mergetool' is invoked with this tool (either through the
 `-t` or `--tool` option or the `merge.tool` configuration
 variable) the configured command line will be invoked with `$BASE`
 set to the name of a temporary file containing the common base for
@@ -57,7 +57,7 @@ merge resolution.
 If the custom merge tool correctly indicates the success of a
 merge resolution with its exit code then the configuration
 variable `mergetool.<tool>.trustExitCode` can be set to `true`.
-Otherwise, `git mergetool` will prompt the user to indicate the
+Otherwise, 'git-mergetool' will prompt the user to indicate the
 success of the resolution after the custom tool has exited.
 
 Author
index 232bc1a338468274f4304bea684f148b5b58aee8..8bcc11443dce7322ac5b0fa70e07b2465f762615 100644 (file)
@@ -8,7 +8,7 @@ git-mktag - Creates a tag object
 
 SYNOPSIS
 --------
-'git-mktag' < signature_file
+'git mktag' < signature_file
 
 DESCRIPTION
 -----------
index 1ddbf00afccf93d2c31d3c6d0deabd82ff4fe779..0be32e26126c075b408f37212f8658394b272297 100644 (file)
@@ -8,7 +8,7 @@ git-mktree - Build a tree-object from ls-tree formatted text
 
 SYNOPSIS
 --------
-'git-mktree' [-z]
+'git mktree' [-z]
 
 DESCRIPTION
 -----------
index 339190600a292eca9b56771316118481236d46fb..9c5660275b326661bf7dc9a5162e5177b8a62b0f 100644 (file)
@@ -8,14 +8,14 @@ git-mv - Move or rename a file, a directory, or a symlink
 
 SYNOPSIS
 --------
-'git-mv' <options>... <args>...
+'git mv' <options>... <args>...
 
 DESCRIPTION
 -----------
 This script is used to move or rename a file, directory or symlink.
 
- git-mv [-f] [-n] <source> <destination>
- git-mv [-f] [-n] [-k] <source> ... <destination directory>
+ git mv [-f] [-n] <source> <destination>
+ git mv [-f] [-n] [-k] <source> ... <destination directory>
 
 In the first form, it renames <source>, which must exist and be either
 a file, symlink or directory, to <destination>.
index ffac3f8f564bf5f5e2ca317b986db9b01f5dc026..6e77ab135353aaf713b638a70701717db1706c2c 100644 (file)
@@ -9,13 +9,13 @@ git-name-rev - Find symbolic names for given revs
 SYNOPSIS
 --------
 [verse]
-'git-name-rev' [--tags] [--refs=<pattern>]
+'git name-rev' [--tags] [--refs=<pattern>]
               ( --all | --stdin | <committish>... )
 
 DESCRIPTION
 -----------
 Finds symbolic names suitable for human digestion for revisions given in any
-format parsable by git-rev-parse.
+format parsable by 'git-rev-parse'.
 
 
 OPTIONS
@@ -38,7 +38,7 @@ OPTIONS
        Instead of printing both the SHA-1 and the name, print only
        the name.  If given with --tags the usual tag prefix of
        "tags/" is also omitted from the name, matching the output
-       of linkgit:git-describe[1] more closely.  This option
+       of 'git-describe' more closely.  This option
        cannot be combined with --stdin.
 
 --no-undefined::
@@ -56,7 +56,7 @@ wrote you about that fantastic commit 33db5f4d9027a10e477ccf054b2c1ab94f74c85a.
 Of course, you look into the commit, but that only tells you what happened, but
 not the context.
 
-Enter git-name-rev:
+Enter 'git-name-rev':
 
 ------------
 % git name-rev 33db5f4d9027a10e477ccf054b2c1ab94f74c85a
index f4d8d68e34b223f6ed06bceca706f9b91232c15f..8c354bd47014825de71243d73158b6b080ecb350 100644 (file)
@@ -9,7 +9,7 @@ git-pack-objects - Create a packed archive of objects
 SYNOPSIS
 --------
 [verse]
-'git-pack-objects' [-q] [--no-reuse-delta] [--delta-base-offset] [--non-empty]
+'git pack-objects' [-q] [--no-reuse-delta] [--delta-base-offset] [--non-empty]
        [--local] [--incremental] [--window=N] [--depth=N] [--all-progress]
        [--revs [--unpacked | --all]*] [--stdout | base-name] < object-list
 
@@ -30,7 +30,7 @@ Placing both in the pack/ subdirectory of $GIT_OBJECT_DIRECTORY (or
 any of the directories on $GIT_ALTERNATE_OBJECT_DIRECTORIES)
 enables git to read from such an archive.
 
-'git-unpack-objects' command can read the packed archive and
+The 'git-unpack-objects' command can read the packed archive and
 expand the objects contained in the pack into "one-file
 one-object" format; this is typically done by the smart-pull
 commands when a pack is created on-the-fly for efficient network
@@ -59,7 +59,7 @@ base-name::
 --revs::
        Read the revision arguments from the standard input, instead of
        individual object names.  The revision arguments are processed
-       the same way as linkgit:git-rev-list[1] with `--objects` flag
+       the same way as 'git-rev-list' with the `--objects` flag
        uses its `commit` arguments to build the list of objects it
        outputs.  The objects on the resulting list are packed.
 
@@ -163,14 +163,14 @@ base-name::
        generated pack.  If not specified,  pack compression level is
        determined first by pack.compression,  then by core.compression,
        and defaults to -1,  the zlib default,  if neither is set.
-       Add \--no-reuse-object if you want to force a uniform compression
+       Add --no-reuse-object if you want to force a uniform compression
        level on all data no matter the source.
 
 --delta-base-offset::
        A packed archive can express base object of a delta as
        either 20-byte object name or as an offset in the
        stream, but older version of git does not understand the
-       latter.  By default, git-pack-objects only uses the
+       latter.  By default, 'git-pack-objects' only uses the
        former format for better compatibility.  This option
        allows the command to use the latter format for
        compactness.  Depending on the average delta chain
index 6737326f0b63108a9ecbd746824363e20f9a2ae2..5f9435e59b49fec1e37c65f1bfdc38be3704c4e5 100644 (file)
@@ -8,21 +8,21 @@ git-pack-redundant - Find redundant pack files
 
 SYNOPSIS
 --------
-'git-pack-redundant' [ --verbose ] [ --alt-odb ] < --all | .pack filename ... >
+'git pack-redundant' [ --verbose ] [ --alt-odb ] < --all | .pack filename ... >
 
 DESCRIPTION
 -----------
 This program computes which packs in your repository
 are redundant. The output is suitable for piping to
-'xargs rm' if you are in the root of the repository.
+`xargs rm` if you are in the root of the repository.
 
-git-pack-redundant accepts a list of objects on standard input. Any objects
+'git-pack-redundant' accepts a list of objects on standard input. Any objects
 given will be ignored when checking which packs are required. This makes the
 following command useful when wanting to remove packs which contain unreachable
 objects.
 
-git-fsck --full --unreachable | cut -d ' ' -f3 | \
-git-pack-redundant --all | xargs rm
+git fsck --full --unreachable | cut -d ' ' -f3 | \
+git pack-redundant --all | xargs rm
 
 OPTIONS
 -------
index c0718468d563e7ee5f8bd37c5f583ec7dc9d3d62..a5244d35f49f10b7954d8fa52164663e3d167d4b 100644 (file)
@@ -7,7 +7,7 @@ git-pack-refs - Pack heads and tags for efficient repository access
 
 SYNOPSIS
 --------
-'git-pack-refs' [--all] [--no-prune]
+'git pack-refs' [--all] [--no-prune]
 
 DESCRIPTION
 -----------
@@ -31,7 +31,7 @@ Subsequent updates to branches always creates new file under
 
 A recommended practice to deal with a repository with too many
 refs is to pack its refs with `--all --prune` once, and
-occasionally run `git-pack-refs \--prune`.  Tags are by
+occasionally run `git pack-refs \--prune`.  Tags are by
 definition stationary and are not expected to change.  Branch
 heads will be packed with the initial `pack-refs --all`, but
 only the currently active branch heads will become unpacked,
index 951dbd6c830a15cafaa7281cb1c6de357d97b4cc..cd43069874d59504627211e011250a3554aeee5a 100644 (file)
@@ -8,7 +8,7 @@ git-parse-remote - Routines to help parsing remote repository access parameters
 
 SYNOPSIS
 --------
-'. git-parse-remote'
+'. "$(git --exec-path)/git-parse-remote"'
 
 DESCRIPTION
 -----------
@@ -32,7 +32,7 @@ get_remote_refs_for_fetch::
 get_remote_refs_for_push::
        Given the list of user-supplied `<repo> <refspec>...`,
        return the list of refs to push in a form suitable to be
-       fed to the `git-send-pack` command.  When `<refspec>...`
+       fed to the 'git-send-pack' command.  When `<refspec>...`
        is empty the returned list of refs consists of the
        defaults for the given `<repo>`, if specified in
        `$GIT_DIR/remotes/`.
index bb8a079254e7fed097504cd181eee71a888d2280..477785e13418e1971156f5210015da4ab9d77cab 100644 (file)
@@ -7,7 +7,7 @@ git-patch-id - Compute unique ID for a patch
 
 SYNOPSIS
 --------
-'git-patch-id' < <patch>
+'git patch-id' < <patch>
 
 DESCRIPTION
 -----------
@@ -18,7 +18,7 @@ ID" are almost guaranteed to be the same thing.
 
 IOW, you can use this thing to look for likely duplicate commits.
 
-When dealing with git-diff-tree output, it takes advantage of
+When dealing with 'git-diff-tree' output, it takes advantage of
 the fact that the patch is prefixed with the object name of the
 commit, and outputs two 40-byte hexadecimal string.  The first
 string is the patch ID, and the second string is the commit ID.
index ffbf93a7993cee0386c42bef1c827a8488f04d8e..79c03ee7f7ea886094e2dfa85211f0539f51a4ab 100644 (file)
@@ -8,11 +8,11 @@ git-peek-remote - List the references in a remote repository
 
 SYNOPSIS
 --------
-'git-peek-remote' [--upload-pack=<git-upload-pack>] [<host>:]<directory>
+'git peek-remote' [--upload-pack=<git-upload-pack>] [<host>:]<directory>
 
 DESCRIPTION
 -----------
-This command is deprecated; use `git-ls-remote` instead.
+This command is deprecated; use 'git-ls-remote' instead.
 
 OPTIONS
 -------
index f330b8a5b9bbd89414571456659fefcbf812254f..b5f26cee132622185457d92522fb932302dec97d 100644 (file)
@@ -8,7 +8,7 @@ git-prune-packed - Remove extra objects that are already in pack files
 
 SYNOPSIS
 --------
-'git-prune-packed' [-n] [-q]
+'git prune-packed' [-n] [-q]
 
 
 DESCRIPTION
index ec335d6fab6e9639a7f7d93c5b88002e2192fd4c..54f1dab38de9e01d8452753ac6028875b91d5f6b 100644 (file)
@@ -13,16 +13,16 @@ SYNOPSIS
 DESCRIPTION
 -----------
 
-NOTE: In most cases, users should run linkgit:git-gc[1], which calls
-git-prune. See the section "NOTES", below.
+NOTE: In most cases, users should run 'git-gc', which calls
+'git-prune'. See the section "NOTES", below.
 
-This runs `git-fsck --unreachable` using all the refs
+This runs 'git-fsck --unreachable' using all the refs
 available in `$GIT_DIR/refs`, optionally with additional set of
 objects specified on the command line, and prunes all unpacked
 objects unreachable from any of these head objects from the object database.
 In addition, it
 prunes the unpacked objects that are also found in packs by
-running `git prune-packed`.
+running 'git-prune-packed'.
 
 Note that unreachable, packed objects will remain.  If this is
 not desired, see linkgit:git-repack[1].
@@ -53,18 +53,18 @@ borrows from your repository via its
 `.git/objects/info/alternates`:
 
 ------------
-$ git prune $(cd ../another && $(git-rev-parse --all))
+$ git prune $(cd ../another && $(git rev-parse --all))
 ------------
 
 Notes
 -----
 
-In most cases, users will not need to call git-prune directly, but
-should instead call linkgit:git-gc[1], which handles pruning along with
+In most cases, users will not need to call 'git-prune' directly, but
+should instead call 'git-gc', which handles pruning along with
 many other housekeeping tasks.
 
 For a description of which objects are considered for pruning, see
-git-fsck's --unreachable option.
+'git-fsck''s --unreachable option.
 
 SEE ALSO
 --------
index d0f1595f7e9051b5d58d1dba030ea3a7d80bdab5..092d1b8a3e49b3c512bf4d2daf3b70b5a7694b60 100644 (file)
@@ -8,21 +8,21 @@ git-pull - Fetch from and merge with another repository or a local branch
 
 SYNOPSIS
 --------
-'git-pull' <options> <repository> <refspec>...
+'git pull' <options> <repository> <refspec>...
 
 
 DESCRIPTION
 -----------
-Runs `git-fetch` with the given parameters, and calls `git-merge`
+Runs 'git-fetch' with the given parameters, and calls 'git-merge'
 to merge the retrieved head(s) into the current branch.
-With `--rebase`, calls `git-rebase` instead of `git-merge`.
+With `--rebase`, calls 'git-rebase' instead of 'git-merge'.
 
 Note that you can use `.` (current directory) as the
 <repository> to pull from the local repository -- this is useful
 when merging local branches into the current branch.
 
-Also note that options meant for `git-pull` itself and underlying
-`git-merge` must be given before the options meant for `git-fetch`.
+Also note that options meant for 'git-pull' itself and underlying
+'git-merge' must be given before the options meant for 'git-fetch'.
 
 OPTIONS
 -------
@@ -182,8 +182,7 @@ The final command then merges the newly fetched `tmp` into master.
 
 
 If you tried a pull which resulted in a complex conflicts and
-would want to start over, you can recover with
-linkgit:git-reset[1].
+would want to start over, you can recover with 'git-reset'.
 
 
 SEE ALSO
index 89e0049bce1367f308c58d3306266f93a6cd7b75..c44dce374a39566c2ad349c657e582c6a8a8d8ec 100644 (file)
@@ -9,7 +9,7 @@ git-push - Update remote refs along with associated objects
 SYNOPSIS
 --------
 [verse]
-'git-push' [--all] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>]
+'git push' [--all] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>]
            [--repo=all] [-f | --force] [-v | --verbose] [<repository> <refspec>...]
 
 DESCRIPTION
@@ -67,7 +67,8 @@ nor in any Push line of the corresponding remotes file---see below).
 
 --mirror::
        Instead of naming each ref to push, specifies that all
-       refs under `$GIT_DIR/refs/heads/` and `$GIT_DIR/refs/tags/`
+       refs under `$GIT_DIR/refs/` (which includes but is not
+       limited to `refs/heads/`, `refs/remotes/`, and `refs/tags/`)
        be mirrored to the remote repository.  Newly created local
        refs will be pushed to the remote end, locally updated refs
        will be force updated on the remote end, and deleted refs
@@ -105,7 +106,7 @@ nor in any Push line of the corresponding remotes file---see below).
 
 --thin::
 --no-thin::
-       These options are passed to `git-send-pack`.  Thin
+       These options are passed to 'git-send-pack'.  Thin
        transfer spends extra cycles to minimize the number of
        objects to be sent and meant to be used on slower connection.
 
index 0600379394ee7c2b00743379170b9a4718bf7db6..d4037de5124010e9c90dcc97e8b64e6011dbed21 100644 (file)
@@ -9,7 +9,7 @@ git-quiltimport - Applies a quilt patchset onto the current branch
 SYNOPSIS
 --------
 [verse]
-'git-quiltimport' [--dry-run] [--author <author>] [--patches <dir>]
+'git quiltimport' [--dry-run] [--author <author>] [--patches <dir>]
 
 
 DESCRIPTION
index 58fb906ef68e8b800b0616a5655aa757a362ed6e..6f4b9b017f7b504a2b9e909639a61b1ef7750af0 100644 (file)
@@ -8,7 +8,7 @@ git-read-tree - Reads tree information into the index
 
 SYNOPSIS
 --------
-'git-read-tree' (<tree-ish> | [[-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>] [-u | -i]] [--exclude-per-directory=<gitignore>] [--index-output=<file>] <tree-ish1> [<tree-ish2> [<tree-ish3>]])
+'git read-tree' (<tree-ish> | [[-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>] [-u | -i]] [--exclude-per-directory=<gitignore>] [--index-output=<file>] <tree-ish1> [<tree-ish2> [<tree-ish3>]])
 
 
 DESCRIPTION
@@ -22,8 +22,8 @@ fast-forward (i.e. 2-way) merge, or a 3-way merge, with the `-m`
 flag.  When used with `-m`, the `-u` flag causes it to also update
 the files in the work tree with the result of the merge.
 
-Trivial merges are done by `git-read-tree` itself.  Only conflicting paths
-will be in unmerged state when `git-read-tree` returns.
+Trivial merges are done by 'git-read-tree' itself.  Only conflicting paths
+will be in unmerged state when 'git-read-tree' returns.
 
 OPTIONS
 -------
@@ -54,13 +54,13 @@ OPTIONS
        Show the progress of checking files out.
 
 --trivial::
-       Restrict three-way merge by `git-read-tree` to happen
+       Restrict three-way merge by 'git-read-tree' to happen
        only if there is no file-level merging required, instead
        of resolving merge for trivial cases and leaving
        conflicting files unresolved in the index.
 
 --aggressive::
-       Usually a three-way merge by `git-read-tree` resolves
+       Usually a three-way merge by 'git-read-tree' resolves
        the merge for really trivial cases and leaves other
        cases unresolved in the index, so that Porcelains can
        implement different merge policies.  This flag makes the
@@ -113,7 +113,7 @@ OPTIONS
 
 Merging
 -------
-If `-m` is specified, `git-read-tree` can perform 3 kinds of
+If `-m` is specified, 'git-read-tree' can perform 3 kinds of
 merge, a single tree merge if only 1 tree is given, a
 fast-forward merge with 2 trees, or a 3-way merge if 3 trees are
 provided.
@@ -121,29 +121,29 @@ provided.
 
 Single Tree Merge
 ~~~~~~~~~~~~~~~~~
-If only 1 tree is specified, git-read-tree operates as if the user did not
+If only 1 tree is specified, 'git-read-tree' operates as if the user did not
 specify `-m`, except that if the original index has an entry for a
 given pathname, and the contents of the path matches with the tree
 being read, the stat info from the index is used. (In other words, the
 index's stat()s take precedence over the merged tree's).
 
-That means that if you do a `git-read-tree -m <newtree>` followed by a
-`git-checkout-index -f -u -a`, the `git-checkout-index` only checks out
+That means that if you do a `git read-tree -m <newtree>` followed by a
+`git checkout-index -f -u -a`, the 'git-checkout-index' only checks out
 the stuff that really changed.
 
-This is used to avoid unnecessary false hits when `git-diff-files` is
-run after `git-read-tree`.
+This is used to avoid unnecessary false hits when 'git-diff-files' is
+run after 'git-read-tree'.
 
 
 Two Tree Merge
 ~~~~~~~~~~~~~~
 
-Typically, this is invoked as `git-read-tree -m $H $M`, where $H
+Typically, this is invoked as `git read-tree -m $H $M`, where $H
 is the head commit of the current repository, and $M is the head
 of a foreign tree, which is simply ahead of $H (i.e. we are in a
 fast forward situation).
 
-When two trees are specified, the user is telling git-read-tree
+When two trees are specified, the user is telling 'git-read-tree'
 the following:
 
      1. The current index and work tree is derived from $H, but
@@ -151,7 +151,7 @@ the following:
 
      2. The user wants to fast-forward to $M.
 
-In this case, the `git-read-tree -m $H $M` command makes sure
+In this case, the `git read-tree -m $H $M` command makes sure
 that no local change is lost as the result of this "merge".
 Here are the "carry forward" rules:
 
@@ -193,18 +193,18 @@ Here are the "carry forward" rules:
 
 In all "keep index" cases, the index entry stays as in the
 original index file.  If the entry were not up to date,
-git-read-tree keeps the copy in the work tree intact when
+'git-read-tree' keeps the copy in the work tree intact when
 operating under the -u flag.
 
-When this form of git-read-tree returns successfully, you can
+When this form of 'git-read-tree' returns successfully, you can
 see what "local changes" you made are carried forward by running
-`git-diff-index --cached $M`.  Note that this does not
-necessarily match `git-diff-index --cached $H` would have
+`git diff-index --cached $M`.  Note that this does not
+necessarily match `git diff-index --cached $H` would have
 produced before such a two tree merge.  This is because of cases
 18 and 19 --- if you already had the changes in $M (e.g. maybe
-you picked it up via e-mail in a patch form), `git-diff-index
+you picked it up via e-mail in a patch form), `git diff-index
 --cached $H` would have told you about the change before this
-merge, but it would not show in `git-diff-index --cached $M`
+merge, but it would not show in `git diff-index --cached $M`
 output after two-tree merge.
 
 
@@ -213,13 +213,13 @@ output after two-tree merge.
 Each "index" entry has two bits worth of "stage" state. stage 0 is the
 normal one, and is the only one you'd see in any kind of normal use.
 
-However, when you do `git-read-tree` with three trees, the "stage"
+However, when you do 'git-read-tree' with three trees, the "stage"
 starts out at 1.
 
 This means that you can do
 
 ----------------
-$ git-read-tree -m <tree1> <tree2> <tree3>
+$ git read-tree -m <tree1> <tree2> <tree3>
 ----------------
 
 and you will end up with an index with all of the <tree1> entries in
@@ -229,7 +229,7 @@ branch into the current branch, we use the common ancestor tree
 as <tree1>, the current branch head as <tree2>, and the other
 branch head as <tree3>.
 
-Furthermore, `git-read-tree` has special-case logic that says: if you see
+Furthermore, 'git-read-tree' has special-case logic that says: if you see
 a file that matches in all respects in the following states, it
 "collapses" back to "stage0":
 
@@ -245,7 +245,7 @@ a file that matches in all respects in the following states, it
    - stage 1 and stage 3 are the same and stage 2 is different take
      stage 2 (we did something while they did nothing)
 
-The `git-write-tree` command refuses to write a nonsensical tree, and it
+The 'git-write-tree' command refuses to write a nonsensical tree, and it
 will complain about unmerged entries if it sees a single entry that is not
 stage 0.
 
@@ -261,7 +261,7 @@ start a 3-way merge with an index file that is already
 populated.  Here is an outline of how the algorithm works:
 
 - if a file exists in identical format in all three trees, it will
-  automatically collapse to "merged" state by git-read-tree.
+  automatically collapse to "merged" state by 'git-read-tree'.
 
 - a file that has _any_ difference what-so-ever in the three trees
   will stay as separate entries in the index. It's up to "porcelain
@@ -285,8 +285,8 @@ populated.  Here is an outline of how the algorithm works:
     matching "stage1" entry if it exists too.  .. all the normal
     trivial rules ..
 
-You would normally use `git-merge-index` with supplied
-`git-merge-one-file` to do this last step.  The script updates
+You would normally use 'git-merge-index' with supplied
+'git-merge-one-file' to do this last step.  The script updates
 the files in the working tree as it merges each path and at the
 end of a successful merge.
 
@@ -304,16 +304,16 @@ commit.  To illustrate, suppose you start from what has been
 committed last to your repository:
 
 ----------------
-$ JC=`git-rev-parse --verify "HEAD^0"`
-$ git-checkout-index -f -u -a $JC
+$ JC=`git rev-parse --verify "HEAD^0"`
+$ git checkout-index -f -u -a $JC
 ----------------
 
-You do random edits, without running git-update-index.  And then
+You do random edits, without running 'git-update-index'.  And then
 you notice that the tip of your "upstream" tree has advanced
 since you pulled from him:
 
 ----------------
-$ git-fetch git://.... linus
+$ git fetch git://.... linus
 $ LT=`cat .git/FETCH_HEAD`
 ----------------
 
@@ -323,10 +323,10 @@ added or modified index entries since $JC, and if you haven't,
 then does the right thing.  So with the following sequence:
 
 ----------------
-$ git-read-tree -m -u `git-merge-base $JC $LT` $JC $LT
-$ git-merge-index git-merge-one-file -a
+$ git read-tree -m -u `git merge-base $JC $LT` $JC $LT
+$ git merge-index git-merge-one-file -a
 $ echo "Merge with Linus" | \
-  git-commit-tree `git-write-tree` -p $JC -p $LT
+  git commit-tree `git write-tree` -p $JC -p $LT
 ----------------
 
 what you would commit is a pure merge between $JC and $LT without
@@ -334,14 +334,14 @@ your work-in-progress changes, and your work tree would be
 updated to the result of the merge.
 
 However, if you have local changes in the working tree that
-would be overwritten by this merge,`git-read-tree` will refuse
+would be overwritten by this merge, 'git-read-tree' will refuse
 to run to prevent your changes from being lost.
 
 In other words, there is no need to worry about what exists only
 in the working tree.  When you have local changes in a part of
 the project that is not involved in the merge, your changes do
 not interfere with the merge, and are kept intact.  When they
-*do* interfere, the merge does not even start (`git-read-tree`
+*do* interfere, the merge does not even start ('git-read-tree'
 complains loudly and fails without modifying anything).  In such
 a case, you can simply continue doing what you were in the
 middle of doing, and when your working tree is ready (i.e. you
index 7166414355e7469c5aeae0262f3902ce7398c989..f3459c7de7c9629f2abfdb684a359bb264ea82ed 100644 (file)
@@ -8,15 +8,15 @@ git-rebase - Forward-port local commits to the updated upstream head
 SYNOPSIS
 --------
 [verse]
-'git-rebase' [-i | --interactive] [-v | --verbose] [-m | --merge]
+'git rebase' [-i | --interactive] [-v | --verbose] [-m | --merge]
        [-s <strategy> | --strategy=<strategy>]
        [-C<n>] [ --whitespace=<option>] [-p | --preserve-merges]
        [--onto <newbase>] <upstream> [<branch>]
-'git-rebase' --continue | --skip | --abort
+'git rebase' --continue | --skip | --abort
 
 DESCRIPTION
 -----------
-If <branch> is specified, git-rebase will perform an automatic
+If <branch> is specified, 'git-rebase' will perform an automatic
 `git checkout <branch>` before doing anything else.  Otherwise
 it remains on the current branch.
 
@@ -52,8 +52,8 @@ Assume the following history exists and the current branch is "topic":
 From this point, the result of either of the following commands:
 
 
-    git-rebase master
-    git-rebase master topic
+    git rebase master
+    git rebase master topic
 
 would be:
 
@@ -68,7 +68,7 @@ followed by `git rebase master`.
 
 If the upstream branch already contains a change you have made (e.g.,
 because you mailed a patch which was applied upstream), then that commit
-will be skipped. For example, running `git-rebase master` on the
+will be skipped. For example, running `git rebase master` on the
 following history (in which A' and A introduce the same set of changes,
 but have different committer information):
 
@@ -116,7 +116,7 @@ got merged into more stable 'master' branch, like this:
 
 We can get this using the following command:
 
-    git-rebase --onto master next topic
+    git rebase --onto master next topic
 
 
 Another example of --onto option is to rebase part of a
@@ -132,7 +132,7 @@ branch.  If we have the following situation:
 
 then the command
 
-    git-rebase --onto master topicA topicB
+    git rebase --onto master topicA topicB
 
 would result in:
 
@@ -155,7 +155,7 @@ the following situation:
 
 then the command
 
-    git-rebase --onto topicA~5 topicA~3 topicA
+    git rebase --onto topicA~5 topicA~3 topicA
 
 would result in the removal of commits F and G:
 
@@ -167,8 +167,8 @@ This is useful if F and G were flawed in some way, or should not be
 part of topicA.  Note that the argument to --onto and the <upstream>
 parameter can be any valid commit-ish.
 
-In case of conflict, git-rebase will stop at the first problematic commit
-and leave conflict markers in the tree.  You can use git diff to locate
+In case of conflict, 'git-rebase' will stop at the first problematic commit
+and leave conflict markers in the tree.  You can use 'git-diff' to locate
 the markers (<<<<<<) and make edits to resolve the conflict.  For each
 file you edit, you need to tell git that the conflict has been resolved,
 typically this would be done with
@@ -184,7 +184,7 @@ desired resolution, you can continue the rebasing process with
     git rebase --continue
 
 
-Alternatively, you can undo the git-rebase with
+Alternatively, you can undo the 'git-rebase' with
 
 
     git rebase --abort
@@ -224,8 +224,8 @@ OPTIONS
        Use the given merge strategy; can be supplied more than
        once to specify them in the order they should be tried.
        If there is no `-s` option, a built-in list of strategies
-       is used instead (`git-merge-recursive` when merging a single
-       head, `git-merge-octopus` otherwise).  This implies --merge.
+       is used instead ('git-merge-recursive' when merging a single
+       head, 'git-merge-octopus' otherwise).  This implies --merge.
 
 -v::
 --verbose::
@@ -238,7 +238,7 @@ OPTIONS
        ever ignored.
 
 --whitespace=<nowarn|warn|error|error-all|strip>::
-       This flag is passed to the `git-apply` program
+       This flag is passed to the 'git-apply' program
        (see linkgit:git-apply[1]) that applies the patch.
 
 -i::
@@ -259,10 +259,10 @@ NOTES
 When you rebase a branch, you are changing its history in a way that
 will cause problems for anyone who already has a copy of the branch
 in their repository and tries to pull updates from you.  You should
-understand the implications of using 'git rebase' on a repository that
+understand the implications of using 'git-rebase' on a repository that
 you share.
 
-When the git rebase command is run, it will first execute a "pre-rebase"
+When the git-rebase command is run, it will first execute a "pre-rebase"
 hook if one exists.  You can use this hook to do sanity checks and
 reject the rebase if it isn't appropriate.  Please see the template
 pre-rebase hook script for an example.
@@ -314,12 +314,12 @@ pick fa1afe1 The oneline of the next commit
 ...
 -------------------------------------------
 
-The oneline descriptions are purely for your pleasure; `git-rebase` will
+The oneline descriptions are purely for your pleasure; 'git-rebase' will
 not look at them but at the commit names ("deadbee" and "fa1afe1" in this
 example), so do not delete or edit the names.
 
 By replacing the command "pick" with the command "edit", you can tell
-`git-rebase` to stop after applying that commit, so that you can edit
+'git-rebase' to stop after applying that commit, so that you can edit
 the files and/or the commit message, amend the commit, and continue
 rebasing.
 
@@ -334,7 +334,7 @@ the loop with `git rebase --continue`.
 
 For example, if you want to reorder the last 5 commits, such that what
 was HEAD~4 becomes the new HEAD. To achieve that, you would call
-`git-rebase` like this:
+'git-rebase' like this:
 
 ----------------------
 $ git rebase -i HEAD~5
@@ -364,34 +364,34 @@ SPLITTING COMMITS
 -----------------
 
 In interactive mode, you can mark commits with the action "edit".  However,
-this does not necessarily mean that 'git rebase' expects the result of this
+this does not necessarily mean that 'git-rebase' expects the result of this
 edit to be exactly one commit.  Indeed, you can undo the commit, or you can
 add other commits.  This can be used to split a commit into two:
 
-- Start an interactive rebase with 'git rebase -i <commit>^', where
+- Start an interactive rebase with `git rebase -i <commit>^`, where
   <commit> is the commit you want to split.  In fact, any commit range
   will do, as long as it contains that commit.
 
 - Mark the commit you want to split with the action "edit".
 
-- When it comes to editing that commit, execute 'git reset HEAD^'.  The
+- When it comes to editing that commit, execute `git reset HEAD^`.  The
   effect is that the HEAD is rewound by one, and the index follows suit.
   However, the working tree stays the same.
 
 - Now add the changes to the index that you want to have in the first
-  commit.  You can use linkgit:git-add[1] (possibly interactively) and/or
-  linkgit:git-gui[1] to do that.
+  commit.  You can use `git add` (possibly interactively) or
+  'git-gui' (or both) to do that.
 
 - Commit the now-current index with whatever commit message is appropriate
   now.
 
 - Repeat the last two steps until your working tree is clean.
 
-- Continue the rebase with 'git rebase --continue'.
+- Continue the rebase with `git rebase --continue`.
 
 If you are not absolutely sure that the intermediate revisions are
 consistent (they compile, pass the testsuite, etc.) you should use
-linkgit:git-stash[1] to stash away the not-yet-committed changes
+'git-stash' to stash away the not-yet-committed changes
 after each commit, test, and amend the commit if fixes are necessary.
 
 
index a70c7168f60f8cbb6666a34334114e2759424ccd..6b2f8c4de7c32927f270e561362d4766193986fa 100644 (file)
@@ -8,7 +8,7 @@ git-receive-pack - Receive what is pushed into the repository
 
 SYNOPSIS
 --------
-'git-receive-pack' <directory>
+'git receive-pack' <directory>
 
 DESCRIPTION
 -----------
@@ -18,17 +18,17 @@ information fed from the remote end.
 This command is usually not invoked directly by the end user.
 The UI for the protocol is on the 'git-send-pack' side, and the
 program pair is meant to be used to push updates to remote
-repository.  For pull operations, see 'git-fetch-pack'.
+repository.  For pull operations, see linkgit:git-fetch-pack[1].
 
 The command allows for creation and fast forwarding of sha1 refs
 (heads/tags) on the remote end (strictly speaking, it is the
-local end receive-pack runs, but to the user who is sitting at
+local end 'git-receive-pack' runs, but to the user who is sitting at
 the send-pack end, it is updating the remote.  Confused?)
 
 There are other real-world examples of using update and
 post-update hooks found in the Documentation/howto directory.
 
-git-receive-pack honours the receive.denyNonFastForwards config
+'git-receive-pack' honours the receive.denyNonFastForwards config
 option, which tells it if updates to a ref should be denied if they
 are not fast-forwards.
 
@@ -111,10 +111,10 @@ ref listing the commits pushed to the repository:
                if expr "$oval" : '0*$' >/dev/null
                then
                        echo "Created a new ref, with the following commits:"
-                       git-rev-list --pretty "$nval"
+                       git rev-list --pretty "$nval"
                else
                        echo "New commits:"
-                       git-rev-list --pretty "$nval" "^$oval"
+                       git rev-list --pretty "$nval" "^$oval"
                fi |
                mail -s "Changes to ref $ref" commit-list@mydomain
        done
@@ -125,7 +125,7 @@ non-zero exit code will generate an error message.
 
 Note that it is possible for refname to not have sha1-new when this
 hook runs.  This can easily occur if another user modifies the ref
-after it was updated by receive-pack, but before the hook was able
+after it was updated by 'git-receive-pack', but before the hook was able
 to evaluate it.  It is recommended that hooks rely on sha1-new
 rather than the current value of refname.
 
@@ -137,14 +137,14 @@ post-update will called with the list of refs that have been updated.
 This can be used to implement any repository wide cleanup tasks.
 
 The exit code from this hook invocation is ignored; the only thing
-left for git-receive-pack to do at that point is to exit itself
+left for 'git-receive-pack' to do at that point is to exit itself
 anyway.
 
-This hook can be used, for example, to run "git-update-server-info"
+This hook can be used, for example, to run `git update-server-info`
 if the repository is packed and is served via a dumb transport.
 
        #!/bin/sh
-       exec git-update-server-info
+       exec git update-server-info
 
 
 SEE ALSO
index 8492aeacf1823bed947d4dc318f45e2488cac574..146d7f545cb2f85177c8143b7e7b999ae8303d71 100644 (file)
@@ -16,12 +16,12 @@ The command takes various subcommands, and different options
 depending on the subcommand:
 
 [verse]
-git reflog expire [--dry-run] [--stale-fix] [--verbose]
+'git reflog expire' [--dry-run] [--stale-fix] [--verbose]
        [--expire=<time>] [--expire-unreachable=<time>] [--all] <refs>...
-
-git reflog delete ref@\{specifier\}...
-
-git reflog [show] [log-options] [<ref>]
++
+'git reflog delete' ref@\{specifier\}...
++
+'git reflog' ['show'] [log-options] [<ref>]
 
 Reflog is a mechanism to record when the tip of branches are
 updated.  This command is to manage the information recorded in it.
@@ -36,7 +36,7 @@ The subcommand "show" (which is also the default, in the absence of any
 subcommands) will take all the normal log options, and show the log of
 the reference provided in the command-line (or `HEAD`, by default).
 The reflog will cover all recent actions (HEAD reflog records branch switching
-as well).  It is an alias for 'git log -g --abbrev-commit --pretty=oneline';
+as well).  It is an alias for `git log -g --abbrev-commit --pretty=oneline`;
 see linkgit:git-log[1].
 
 The reflog is useful in various git commands, to specify the old value
@@ -46,7 +46,7 @@ point to one week ago", and so on. See linkgit:git-rev-parse[1] for
 more details.
 
 To delete single entries from the reflog, use the subcommand "delete"
-and specify the _exact_ entry (e.g. ``git reflog delete master@\{2\}'').
+and specify the _exact_ entry (e.g. "`git reflog delete master@\{2\}`").
 
 
 OPTIONS
@@ -60,7 +60,7 @@ OPTIONS
        refs.
 +
 This computation involves traversing all the reachable objects, i.e. it
-has the same cost as 'git prune'.  Fortunately, once this is run, we
+has the same cost as 'git-prune'.  Fortunately, once this is run, we
 should not have to ever worry about missing objects, because the current
 prune and pack-objects know about reflogs and protect objects referred by
 them.
index f6dafd4495f8f24d1f6759c5c2e7ee5d387e31a5..25ff8f9dcbe0db52675338f1429e9169052b9cf1 100644 (file)
@@ -7,7 +7,7 @@ git-relink - Hardlink common objects in local repositories
 
 SYNOPSIS
 --------
-'git-relink' [--safe] <dir> [<dir>]\* <master_dir>
+'git relink' [--safe] <dir> [<dir>]\* <master_dir>
 
 DESCRIPTION
 -----------
index 345943a26466dab73034b41698c54ca317cc4d75..bb99810ec76f93ff1cdc59aacdf592c64419701a 100644 (file)
@@ -9,12 +9,12 @@ git-remote - manage set of tracked repositories
 SYNOPSIS
 --------
 [verse]
-'git-remote' [-v | --verbose]
-'git-remote' add [-t <branch>] [-m <master>] [-f] [--mirror] <name> <url>
-'git-remote' rm <name>
-'git-remote' show [-n] <name>
-'git-remote' prune [-n | --dry-run] <name>
-'git-remote' update [group]
+'git remote' [-v | --verbose]
+'git remote add' [-t <branch>] [-m <master>] [-f] [--mirror] <name> <url>
+'git remote rm' <name>
+'git remote show' [-n] <name>
+'git remote prune' [-n | --dry-run] <name>
+'git remote update' [group]
 
 DESCRIPTION
 -----------
@@ -124,7 +124,7 @@ $ git checkout -b nfs linux-nfs/master
 ...
 ------------
 
-* Imitate 'git clone' but track only selected branches
+* Imitate 'git-clone' but track only selected branches
 +
 ------------
 $ mkdir project.git
index 04d6f1fbc445efc8046e09fa70e9340d1374ea65..38ac60947bc6c4cbfc8aae70a92f9163fefed442 100644 (file)
@@ -8,7 +8,7 @@ git-repack - Pack unpacked objects in a repository
 
 SYNOPSIS
 --------
-'git-repack' [-a] [-A] [-d] [-f] [-l] [-n] [-q] [--window=N] [--depth=N]
+'git repack' [-a] [-A] [-d] [-f] [-l] [-n] [-q] [--window=N] [--depth=N]
 
 DESCRIPTION
 -----------
@@ -47,31 +47,32 @@ OPTIONS
        deleted by way of being left in the old pack and then
        removed.  Instead, the loose unreachable objects
        will be pruned according to normal expiry rules
-       with the next linkgit:git-gc[1].
+       with the next 'git-gc' invocation. See linkgit:git-gc[1].
 
 -d::
        After packing, if the newly created packs make some
        existing packs redundant, remove the redundant packs.
-       Also runs linkgit:git-prune-packed[1].
+       Also run  'git-prune-packed' to remove redundant
+       loose object files.
 
 -l::
-        Pass the `--local` option to `git pack-objects`, see
+       Pass the `--local` option to 'git-pack-objects'. See
        linkgit:git-pack-objects[1].
 
 -f::
-        Pass the `--no-reuse-delta` option to `git pack-objects`, see
+       Pass the `--no-reuse-delta` option to 'git-pack-objects'. See
        linkgit:git-pack-objects[1].
 
 -q::
-        Pass the `-q` option to `git pack-objects`, see
+       Pass the `-q` option to 'git-pack-objects'. See
        linkgit:git-pack-objects[1].
 
 -n::
        Do not update the server information with
-       `git update-server-info`.  This option skips
+       'git-update-server-info'.  This option skips
        updating local catalog files needed to publish
        this repository (or a direct copy of it)
-       over HTTP or FTP.  See gitlink:git-update-server-info[1].
+       over HTTP or FTP.  See linkgit:git-update-server-info[1].
 
 --window=[N]::
 --depth=[N]::
@@ -106,7 +107,7 @@ Configuration
 
 When configuration variable `repack.UseDeltaBaseOffset` is set
 for the repository, the command passes `--delta-base-offset`
-option to `git-pack-objects`; this typically results in slightly
+option to 'git-pack-objects'; this typically results in slightly
 smaller packs, but the generated packs are incompatible with
 versions of git older than (and including) v1.4.3; do not set
 the variable in a repository that older version of git needs to
index 2ca39946b715f54e7deb451f7b59644fede08a84..e5bdb5533e61687874ad36d30534b2ac9e58d7cb 100644 (file)
@@ -8,7 +8,7 @@ git-repo-config - Get and set repository or global options
 
 SYNOPSIS
 --------
-'git-repo-config' ...
+'git repo-config' ...
 
 
 DESCRIPTION
index c71d86985ea2136e7c7da5e4ca758ca7ef675409..ca6843032a47617b348a3862be8beb5ce6f28ed6 100644 (file)
@@ -7,7 +7,7 @@ git-request-pull - Generates a summary of pending changes
 
 SYNOPSIS
 --------
-'git-request-pull' <start> <url> [<end>]
+'git request-pull' <start> <url> [<end>]
 
 DESCRIPTION
 -----------
index 8030ec4d01de8cf2c7a62a7b1fd8d917e6d14b53..678bfd3cdeb1e223138438431bd46257ec8adcea 100644 (file)
@@ -7,7 +7,7 @@ git-rerere - Reuse recorded resolution of conflicted merges
 
 SYNOPSIS
 --------
-'git-rerere' [clear|diff|status|gc]
+'git rerere' ['clear'|'diff'|'status'|'gc']
 
 DESCRIPTION
 -----------
@@ -30,26 +30,26 @@ enable this command.
 COMMANDS
 --------
 
-Normally, git-rerere is run without arguments or user-intervention.
+Normally, 'git-rerere' is run without arguments or user-intervention.
 However, it has several commands that allow it to interact with
 its working state.
 
 'clear'::
 
 This resets the metadata used by rerere if a merge resolution is to be
-is aborted.  Calling linkgit:git-am[1] --skip or linkgit:git-rebase[1]
-[--skip|--abort] will automatically invoke this command.
+is aborted.  Calling 'git-am --skip' or 'git-rebase [--skip|--abort]'
+will automatically invoke this command.
 
 'diff'::
 
 This displays diffs for the current state of the resolution.  It is
 useful for tracking what has changed while the user is resolving
 conflicts.  Additional arguments are passed directly to the system
-diff(1) command installed in PATH.
+'diff' command installed in PATH.
 
 'status'::
 
-Like diff, but this only prints the filenames that will be tracked
+Like 'diff', but this only prints the filenames that will be tracked
 for resolutions.
 
 'gc'::
@@ -142,33 +142,33 @@ finally ready and merged into the master branch.  This merge
 would require you to resolve the conflict, introduced by the
 commits marked with `*`.  However, often this conflict is the
 same conflict you resolved when you created the test merge you
-blew away.  `git-rerere` command helps you to resolve this final
+blew away.  'git-rerere' command helps you to resolve this final
 conflicted merge using the information from your earlier hand
 resolve.
 
-Running `git-rerere` command immediately after a conflicted
+Running the 'git-rerere' command immediately after a conflicted
 automerge records the conflicted working tree files, with the
 usual conflict markers `<<<<<<<`, `=======`, and `>>>>>>>` in
 them.  Later, after you are done resolving the conflicts,
-running `git-rerere` again records the resolved state of these
+running 'git-rerere' again records the resolved state of these
 files.  Suppose you did this when you created the test merge of
 master into the topic branch.
 
-Next time, running `git-rerere` after seeing a conflicted
+Next time, running 'git-rerere' after seeing a conflicted
 automerge, if the conflict is the same as the earlier one
 recorded, it is noticed and a three-way merge between the
 earlier conflicted automerge, the earlier manual resolution, and
 the current conflicted automerge is performed by the command.
 If this three-way merge resolves cleanly, the result is written
 out to your working tree file, so you would not have to manually
-resolve it.  Note that `git-rerere` leaves the index file alone,
+resolve it.  Note that 'git-rerere' leaves the index file alone,
 so you still need to do the final sanity checks with `git diff`
-(or `git diff -c`) and `git add` when you are satisfied.
+(or `git diff -c`) and 'git-add' when you are satisfied.
 
-As a convenience measure, `git-merge` automatically invokes
-`git-rerere` when it exits with a failed automerge, which
+As a convenience measure, 'git-merge' automatically invokes
+'git-rerere' when it exits with a failed automerge, which
 records it if it is a new conflict, or reuses the earlier hand
-resolve when it is not.  `git-commit` also invokes `git-rerere`
+resolve when it is not.  'git-commit' also invokes 'git-rerere'
 when recording a merge result.  What this means is that you do
 not have to do anything special yourself (Note: you still have
 to set the config variable rerere.enabled to enable this command).
@@ -178,8 +178,8 @@ resolution is recorded, and it will be reused when you do the
 actual merge later with updated master and topic branch, as long
 as the earlier resolution is still applicable.
 
-The information `git-rerere` records is also used when running
-`git-rebase`.  After blowing away the test merge and continuing
+The information 'git-rerere' records is also used when running
+'git-rebase'.  After blowing away the test merge and continuing
 development on the topic branch:
 
 ------------
@@ -198,7 +198,7 @@ you could run `git rebase master topic`, to keep yourself
 up-to-date even before your topic is ready to be sent upstream.
 This would result in falling back to three-way merge, and it
 would conflict the same way the test merge you resolved earlier.
-`git-rerere` is run by `git rebase` to help you resolve this
+'git-rerere' is run by 'git-rebase' to help you resolve this
 conflict.
 
 
index 12ea9b23c5b55366f142319451bb45db4e10affe..c8d175768cc665533517952fc613279b42e47f18 100644 (file)
@@ -37,7 +37,7 @@ OPTIONS
 --soft::
        Does not touch the index file nor the working tree at all, but
        requires them to be in a good order. This leaves all your changed
-       files "Changes to be committed", as linkgit:git-status[1] would
+       files "Changes to be committed", as 'git-status' would
        put it.
 
 --hard::
index c9b09503210cd23a3528bd67cbbf8577d1e670e2..fd1de92e34b459cdc89928e1561ee6934cd63c19 100644 (file)
@@ -59,7 +59,7 @@ stop at that point. Their parents are implied. Thus the following
 command:
 
 -----------------------------------------------------------------------
-       $ git-rev-list foo bar ^baz
+       $ git rev-list foo bar ^baz
 -----------------------------------------------------------------------
 
 means "list all the commits which are included in 'foo' and 'bar', but
@@ -70,8 +70,8 @@ short-hand for "{caret}'<commit1>' '<commit2>'". For example, either of
 the following may be used interchangeably:
 
 -----------------------------------------------------------------------
-       $ git-rev-list origin..HEAD
-       $ git-rev-list HEAD ^origin
+       $ git rev-list origin..HEAD
+       $ git rev-list HEAD ^origin
 -----------------------------------------------------------------------
 
 Another special notation is "'<commit1>'...'<commit2>'" which is useful
@@ -79,15 +79,15 @@ for merges.  The resulting set of commits is the symmetric difference
 between the two operands.  The following two commands are equivalent:
 
 -----------------------------------------------------------------------
-       $ git-rev-list A B --not $(git-merge-base --all A B)
-       $ git-rev-list A...B
+       $ git rev-list A B --not $(git merge-base --all A B)
+       $ git rev-list A...B
 -----------------------------------------------------------------------
 
-linkgit:git-rev-list[1] is a very essential git program, since it
+'git-rev-list' is a very essential git program, since it
 provides the ability to build and traverse commit ancestry graphs. For
 this reason, it has a lot of different options that enables it to be
-used by commands as different as linkgit:git-bisect[1] and
-linkgit:git-repack[1].
+used by commands as different as 'git-bisect' and
+'git-repack'.
 
 OPTIONS
 -------
index ba65bfa16bcc3ef36556fed0705798cf30af7028..088f971b790ddd11d39ab2c3b441833961e53a0f 100644 (file)
@@ -8,23 +8,23 @@ git-rev-parse - Pick out and massage parameters
 
 SYNOPSIS
 --------
-'git-rev-parse' [ --option ] <args>...
+'git rev-parse' [ --option ] <args>...
 
 DESCRIPTION
 -----------
 
 Many git porcelainish commands take mixture of flags
 (i.e. parameters that begin with a dash '-') and parameters
-meant for underlying `git-rev-list` command they use internally
-and flags and parameters for other commands they use as the
-downstream of `git-rev-list`.  This command is used to
+meant for the underlying 'git-rev-list' command they use internally
+and flags and parameters for the other commands they use
+downstream of 'git-rev-list'.  This command is used to
 distinguish between them.
 
 
 OPTIONS
 -------
 --parseopt::
-       Use `git-rev-parse` in option parsing mode (see PARSEOPT section below).
+       Use 'git-rev-parse' in option parsing mode (see PARSEOPT section below).
 
 --keep-dash-dash::
        Only meaningful in `--parseopt` mode. Tells the option parser to echo
@@ -32,11 +32,11 @@ OPTIONS
 
 --revs-only::
        Do not output flags and parameters not meant for
-       `git-rev-list` command.
+       'git-rev-list' command.
 
 --no-revs::
        Do not output flags and parameters meant for
-       `git-rev-list` command.
+       'git-rev-list' command.
 
 --flags::
        Do not output non-flag parameters.
@@ -64,7 +64,7 @@ OPTIONS
        properly quoted for consumption by shell.  Useful when
        you expect your parameter to contain whitespaces and
        newlines (e.g. when using pickaxe `-S` with
-       `git-diff-\*`).
+       'git-diff-\*').
 
 --not::
        When showing object names, prefix them with '{caret}' and
@@ -128,13 +128,13 @@ OPTIONS
 
 --since=datestring::
 --after=datestring::
-       Parses the date string, and outputs corresponding
-       --max-age= parameter for git-rev-list command.
+       Parse the date string, and output the corresponding
+       --max-age= parameter for 'git-rev-list'.
 
 --until=datestring::
 --before=datestring::
-       Parses the date string, and outputs corresponding
-       --min-age= parameter for git-rev-list command.
+       Parse the date string, and output the corresponding
+       --min-age= parameter for 'git-rev-list'.
 
 <args>...::
        Flags and parameters to be parsed.
@@ -155,7 +155,7 @@ blobs contained in a commit.
   name the same commit object if there are no other object in
   your repository whose object name starts with dae86e.
 
-* An output from `git-describe`; i.e. a closest tag, followed by a
+* An output from 'git-describe'; i.e. a closest tag, followed by a
   dash, a `g`, and an abbreviated object name.
 
 * A symbolic ref name.  E.g. 'master' typically means the commit
@@ -166,7 +166,7 @@ blobs contained in a commit.
   first match in the following rules:
 
   . if `$GIT_DIR/<name>` exists, that is what you mean (this is usually
-    useful only for `HEAD`, `FETCH_HEAD` and `MERGE_HEAD`);
+    useful only for `HEAD`, `FETCH_HEAD`, `ORIG_HEAD` and `MERGE_HEAD`);
 
   . otherwise, `$GIT_DIR/refs/<name>` if exists;
 
@@ -177,6 +177,16 @@ blobs contained in a commit.
   . otherwise, `$GIT_DIR/refs/remotes/<name>` if exists;
 
   . otherwise, `$GIT_DIR/refs/remotes/<name>/HEAD` if exists.
++
+HEAD names the commit your changes in the working tree is based on.
+FETCH_HEAD records the branch you fetched from a remote repository
+with your last 'git-fetch' invocation.
+ORIG_HEAD is created by commands that moves your HEAD in a drastic
+way, to record the position of the HEAD before their operation, so that
+you can change the tip of the branch back to the state before you ran
+them easily.
+MERGE_HEAD records the commit(s) you are merging into your branch
+when you run 'git-merge'.
 
 * A ref followed by the suffix '@' with a date specification
   enclosed in a brace
@@ -278,7 +288,7 @@ G   H   I   J
 SPECIFYING RANGES
 -----------------
 
-History traversing commands such as `git-log` operate on a set
+History traversing commands such as 'git-log' operate on a set
 of commits, not just a single commit.  To these commands,
 specifying a single revision with the notation described in the
 previous section means the set of commits reachable from that
@@ -289,14 +299,14 @@ notation is used.  E.g. "`{caret}r1 r2`" means commits reachable
 from `r2` but exclude the ones reachable from `r1`.
 
 This set operation appears so often that there is a shorthand
-for it.  "`r1..r2`" is equivalent to "`{caret}r1 r2`".  It is
-the difference of two sets (subtract the set of commits
-reachable from `r1` from the set of commits reachable from
-`r2`).
+for it.  When you have two commits `r1` and `r2` (named according
+to the syntax explained in SPECIFYING REVISIONS above), you can ask
+for commits that are reachable from r2 excluding those that are reachable
+from r1 by "`{caret}r1 r2`" and it can be written as "`r1..r2`".
 
 A similar notation "`r1\...r2`" is called symmetric difference
 of `r1` and `r2` and is defined as
-"`r1 r2 --not $(git-merge-base --all r1 r2)`".
+"`r1 r2 --not $(git merge-base --all r1 r2)`".
 It is the set of commits that are reachable from either one of
 `r1` or `r2` but not from both.
 
@@ -319,7 +329,7 @@ Here are a handful of examples:
 PARSEOPT
 --------
 
-In `--parseopt` mode, `git-rev-parse` helps massaging options to bring to shell
+In `--parseopt` mode, 'git-rev-parse' helps massaging options to bring to shell
 scripts the same facilities C builtins have. It works as an option normalizer
 (e.g. splits single switches aggregate values), a bit like `getopt(1)` does.
 
@@ -331,7 +341,7 @@ usage on the standard error stream, and exits with code 129.
 Input Format
 ~~~~~~~~~~~~
 
-`git-rev-parse --parseopt` input format is fully text based. It has two parts,
+'git-rev-parse --parseopt' input format is fully text based. It has two parts,
 separated by a line that contains only `--`. The lines before the separator
 (should be more than one) are used for the usage.
 The lines after the separator describe the options.
@@ -384,7 +394,7 @@ bar=      some cool option --bar with an argument
   An option group Header
 C?        option C with an optional argument"
 
-eval `echo "$OPTS_SPEC" | git-rev-parse --parseopt -- "$@" || echo exit $?`
+eval `echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?`
 ------------
 
 EXAMPLES
index 5b49b813862c5318701e40f1a798ca04cd1d3a63..5411edca96b50e28996357bf75ce4e32796ee620 100644 (file)
@@ -7,7 +7,7 @@ git-revert - Revert an existing commit
 
 SYNOPSIS
 --------
-'git-revert' [--edit | --no-edit] [-n] [-m parent-number] [-s] <commit>
+'git revert' [--edit | --no-edit] [-n] [-m parent-number] [-s] <commit>
 
 DESCRIPTION
 -----------
@@ -24,7 +24,7 @@ OPTIONS
 
 -e::
 --edit::
-       With this option, `git-revert` will let you edit the commit
+       With this option, 'git-revert' will let you edit the commit
        message prior to committing the revert. This is the default if
        you run the command from a terminal.
 
@@ -37,7 +37,7 @@ OPTIONS
        relative to the specified parent.
 
 --no-edit::
-       With this option, `git-revert` will not start the commit
+       With this option, 'git-revert' will not start the commit
        message editor.
 
 -n::
index d88554bedcaa9acdf8828e9abe6d5169e32446a3..4d0c495bc3ecb5482165a46956efe73dfdc5ee72 100644 (file)
@@ -7,12 +7,12 @@ git-rm - Remove files from the working tree and from the index
 
 SYNOPSIS
 --------
-'git-rm' [-f] [-n] [-r] [--cached] [--ignore-unmatch] [--quiet] [--] <file>...
+'git rm' [-f] [-n] [-r] [--cached] [--ignore-unmatch] [--quiet] [--] <file>...
 
 DESCRIPTION
 -----------
 Remove files from the index, or from the working tree and the index.
-`git rm` will not remove a file from just your working directory.
+'git-rm' will not remove a file from just your working directory.
 (There is no option to remove a file only from the work tree
 and yet keep it in the index; use `/bin/rm` if you want to do that.)
 The files being removed have to be identical to the tip of the branch,
@@ -63,7 +63,7 @@ OPTIONS
 
 -q::
 --quiet::
-       git-rm normally outputs one line (in the form of an "rm" command)
+       'git-rm' normally outputs one line (in the form of an "rm" command)
        for each file removed. This option suppresses that output.
 
 
@@ -82,7 +82,7 @@ also remove all of directory `d2`.
 
 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.
 +
@@ -90,7 +90,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 251d661afd9fc93b556e2673b202523dd30383c6..afbb294a7faadc7ff6d4039246dc1c085575cd4f 100644 (file)
@@ -8,7 +8,7 @@ git-send-email - Send a collection of patches as emails
 
 SYNOPSIS
 --------
-'git-send-email' [options] <file|directory> [... file|directory]
+'git send-email' [options] <file|directory> [... file|directory]
 
 
 
@@ -133,10 +133,13 @@ or on the command line. If a username has been specified (with
 specified (with --smtp-pass or a configuration variable), then the
 user is prompted for a password while the input is masked for privacy.
 
+--smtp-encryption::
+       Specify the encryption to use, either 'ssl' or 'tls'.  Any other
+       value reverts to plain SMTP.  Default is the value of
+       'sendemail.smtpencryption'.
+
 --smtp-ssl::
-       If set, connects to the SMTP server using SSL.
-       Default is the value of the 'sendemail.smtpssl' configuration value;
-       if that is unspecified, does not use SSL.
+       Legacy alias for '--smtp-encryption=ssl'.
 
 --subject::
        Specify the initial subject of the email thread.
@@ -229,8 +232,13 @@ sendemail.smtpuser::
 sendemail.smtppass::
        Default SMTP-AUTH password.
 
+sendemail.smtpencryption::
+       Default encryption method.  Use 'ssl' for SSL (and specify an
+       appropriate port), or 'tls' for TLS.  Takes precedence over
+       'smtpssl' if both are specified.
+
 sendemail.smtpssl::
-       Boolean value specifying the default to the '--smtp-ssl' parameter.
+       Legacy boolean that sets 'smtpencryption=ssl' if enabled.
 
 Author
 ------
index ba2fdaec08913e921189395e7feb2ed4d229ece5..399821832c2a5cd6a718a7dc37a87e6b5bc0b213 100644 (file)
@@ -8,12 +8,12 @@ git-send-pack - Push objects over git protocol to another repository
 
 SYNOPSIS
 --------
-'git-send-pack' [--all] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]
+'git send-pack' [--all] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]
 
 DESCRIPTION
 -----------
-Usually you would want to use linkgit:git-push[1] which is a
-higher level wrapper of this command instead.
+Usually you would want to use 'git-push', which is a
+higher-level wrapper of this command, instead. See linkgit:git-push[1].
 
 Invokes 'git-receive-pack' on a possibly remote repository, and
 updates it from the current repository, sending named refs.
@@ -86,8 +86,8 @@ and the destination side (after the colon).  The ref to be
 pushed is determined by finding a match that matches the source
 side, and where it is pushed is determined by using the
 destination side. The rules used to match a ref are the same
-rules used by linkgit:git-rev-parse[1] to resolve a symbolic ref
-name.
+rules used by 'git-rev-parse' to resolve a symbolic ref
+name. See linkgit:git-rev-parse[1].
 
  - It is an error if <src> does not match exactly one of the
    local refs.
index c543170342030e318e87e75c29f23334655ee7ce..18f14b5be89b4e0240f59b13313308f3c09d012c 100644 (file)
@@ -7,7 +7,7 @@ git-sh-setup - Common git shell script setup code
 
 SYNOPSIS
 --------
-'git-sh-setup'
+'. "$(git --exec-path)/git-sh-setup"'
 
 DESCRIPTION
 -----------
@@ -16,7 +16,7 @@ This is not a command the end user would want to run.  Ever.
 This documentation is meant for people who are studying the
 Porcelain-ish scripts and/or are writing new ones.
 
-The `git-sh-setup` scriptlet is designed to be sourced (using
+The 'git-sh-setup' scriptlet is designed to be sourced (using
 `.`) by other shell scripts to set up some variables pointing at
 the normal git directories and a few helper shell functions.
 
index bd09196acccf75ecde10d6965e3f59fdcc1c2e21..ff420f8f8c52eb598976a134916000da9b8f3976 100644 (file)
@@ -8,7 +8,7 @@ git-shell - Restricted login shell for GIT-only SSH access
 
 SYNOPSIS
 --------
-'git-shell' -c <command> <argument>
+'$(git --exec-path)/git-shell' -c <command> <argument>
 
 DESCRIPTION
 -----------
@@ -18,7 +18,7 @@ of server-side GIT commands implementing the pull/push functionality.
 The commands can be executed only by the '-c' option; the shell is not
 interactive.
 
-Currently, only the `git-receive-pack` and `git-upload-pack` commands
+Currently, only the 'git-receive-pack' and 'git-upload-pack' commands
 are permitted to be called, with a single required argument.
 
 Author
index daa64d4d8165a0dfe5d87f54cd44c4bb6b476eba..7ccf31ccc401fd35a0ed65667be001805436249b 100644 (file)
@@ -3,17 +3,17 @@ git-shortlog(1)
 
 NAME
 ----
-git-shortlog - Summarize 'git log' output
+git-shortlog - Summarize 'git-log' output
 
 SYNOPSIS
 --------
 [verse]
-git-log --pretty=short | 'git-shortlog' [-h] [-n] [-s] [-e] [-w]
-git-shortlog [-n|--numbered] [-s|--summary] [-e|--email] [-w[<width>[,<indent1>[,<indent2>]]]] [<committish>...]
+git log --pretty=short | 'git shortlog' [-h] [-n] [-s] [-e] [-w]
+git shortlog [-n|--numbered] [-s|--summary] [-e|--email] [-w[<width>[,<indent1>[,<indent2>]]]] [<committish>...]
 
 DESCRIPTION
 -----------
-Summarizes 'git log' output in a format suitable for inclusion
+Summarizes 'git-log' output in a format suitable for inclusion
 in release announcements. Each commit will be grouped by author and
 the first line of the commit message will be shown.
 
index de9e8f885f794692bcc45b871e791ebbd7c806cd..14e10362b164379bb8fb7eb4e7925f916bea0c12 100644 (file)
@@ -8,10 +8,10 @@ git-show-branch - Show branches and their commits
 SYNOPSIS
 --------
 [verse]
-'git-show-branch' [--all] [--remotes] [--topo-order] [--current]
+'git show-branch' [--all] [--remotes] [--topo-order] [--current]
                [--more=<n> | --list | --independent | --merge-base]
                [--no-name | --sha1-name] [--topics] [<rev> | <glob>]...
-'git-show-branch' (-g|--reflog)[=<n>[,<base>]] [--list] [<ref>]
+'git show-branch' (-g|--reflog)[=<n>[,<base>]] [--list] [<ref>]
 
 DESCRIPTION
 -----------
@@ -29,7 +29,7 @@ no <rev> nor <glob> is given on the command line.
 OPTIONS
 -------
 <rev>::
-       Arbitrary extended SHA1 expression (see `git-rev-parse`)
+       Arbitrary extended SHA1 expression (see linkgit:git-rev-parse[1])
        that typically names a branch HEAD or a tag.
 
 <glob>::
index 891f0eff27557acddd1212eae62aca293525d5dd..e3285aacfd310cc269cdb03aa9243c939c24def7 100644 (file)
@@ -8,13 +8,13 @@ git-show-index - Show packed archive index
 
 SYNOPSIS
 --------
-'git-show-index' < idx-file
+'git show-index' < idx-file
 
 
 DESCRIPTION
 -----------
 Reads given idx file for packed git archive created with
-git-pack-objects command, and dumps its contents.
+'git-pack-objects' command, and dumps its contents.
 
 The information it outputs is subset of what you can get from
 'git-verify-pack -v'; this command only shows the packfile
index 6b99529b6bb659ec1e1ffd741208ef03762c0356..9a4389981ca067633d773e28393a1d72ac6552ae 100644 (file)
@@ -8,9 +8,9 @@ git-show-ref - List references in a local repository
 SYNOPSIS
 --------
 [verse]
-'git-show-ref' [-q|--quiet] [--verify] [-h|--head] [-d|--dereference]
+'git show-ref' [-q|--quiet] [--verify] [-h|--head] [-d|--dereference]
             [-s|--hash] [--abbrev] [--tags] [--heads] [--] <pattern>...
-'git-show-ref' --exclude-existing[=pattern]
+'git show-ref' --exclude-existing[=pattern]
 
 DESCRIPTION
 -----------
@@ -74,7 +74,7 @@ OPTIONS
 --exclude-existing::
 --exclude-existing=pattern::
 
-       Make git-show-ref act as a filter that reads refs from stdin of the
+       Make 'git-show-ref' act as a filter that reads refs from stdin of the
        form "^(?:<anything>\s)?<refname>(?:\^\{\})?$" and performs the
        following actions on each:
        (1) strip "^{}" at the end of line if any;
@@ -137,14 +137,14 @@ When using the '--verify' flag, the command requires an exact path:
 
 will only match the exact branch called "master".
 
-If nothing matches, linkgit:git-show-ref[1] will return an error code of 1,
+If nothing matches, 'git-show-ref' will return an error code of 1,
 and in the case of verification, it will show an error message.
 
 For scripting, you can ask it to be quiet with the "--quiet" flag, which
 allows you to do things like
 
 -----------------------------------------------------------------------------
-       git-show-ref --quiet --verify -- "refs/heads/$headname" ||
+       git show-ref --quiet --verify -- "refs/heads/$headname" ||
                echo "$headname is not a valid branch"
 -----------------------------------------------------------------------------
 
index baaf2bc8feefe4fb88a1ec43d2f70bbfdfe6fbf6..e0b52bcb3732c4d3d320010f9af07f40bdff49bc 100644 (file)
@@ -8,7 +8,7 @@ git-show - Show various types of objects
 
 SYNOPSIS
 --------
-'git-show' [options] <object>...
+'git show' [options] <object>...
 
 DESCRIPTION
 -----------
@@ -20,12 +20,12 @@ presents the merge commit in a special format as produced by
 
 For tags, it shows the tag message and the referenced objects.
 
-For trees, it shows the names (equivalent to linkgit:git-ls-tree[1]
+For trees, it shows the names (equivalent to 'git-ls-tree'
 with \--name-only).
 
 For plain blobs, it shows the plain contents.
 
-The command takes options applicable to the linkgit:git-diff-tree[1] command to
+The command takes options applicable to the 'git-diff-tree' command to
 control how the changes the commit introduces are shown.
 
 This manual page describes only the most frequently used options.
index baa4f55b48ac2fad72b18651a98bc542d1f38f5c..7d50d74cc9a945f0dd82b0c26509bf0392eff837 100644 (file)
@@ -8,22 +8,25 @@ git-stash - Stash the changes in a dirty working directory away
 SYNOPSIS
 --------
 [verse]
-'git-stash' (list | show [<stash>] | apply [<stash>] | clear | drop [<stash>] | pop [<stash>])
-'git-stash' [save [<message>]]
+'git stash' list
+'git stash' (show | apply | drop | pop ) [<stash>]
+'git stash' branch <branchname> [<stash>]
+'git stash' [save [<message>]]
+'git stash' clear
 
 DESCRIPTION
 -----------
 
-Use 'git-stash' when you want to record the current state of the
+Use 'git stash' when you want to record the current state of the
 working directory and the index, but want to go back to a clean
 working directory.  The command saves your local modifications away
 and reverts the working directory to match the `HEAD` commit.
 
 The modifications stashed away by this command can be listed with
-`git-stash list`, inspected with `git-stash show`, and restored
-(potentially on top of a different commit) with `git-stash apply`.
-Calling git-stash without any arguments is equivalent to `git-stash
-save`.  A stash is by default listed as "WIP on 'branchname' ...", but
+`git stash list`, inspected with `git stash show`, and restored
+(potentially on top of a different commit) with `git stash apply`.
+Calling `git stash` without any arguments is equivalent to `git stash save`.
+A stash is by default listed as "WIP on 'branchname' ...", but
 you can give a more descriptive message on the command line when
 you create one.
 
@@ -36,12 +39,15 @@ is also possible).
 OPTIONS
 -------
 
-save [<message>]::
+save [--keep-index] [<message>]::
 
-       Save your local modifications to a new 'stash', and run `git-reset
+       Save your local modifications to a new 'stash', and run `git reset
        --hard` to revert them.  This is the default action when no
        subcommand is given. The <message> part is optional and gives
        the description along with the stashed state.
++
+If the `--keep-index` option is used, all changes already added to the
+index are left intact.
 
 list [<options>]::
 
@@ -56,15 +62,15 @@ stash@{0}: WIP on submit: 6ebd0e2... Update git-stash documentation
 stash@{1}: On master: 9cc0589... Add git-stash
 ----------------------------------------------------------------
 +
-The command takes options applicable to the linkgit:git-log[1]
-command to control what is shown and how.
+The command takes options applicable to the 'git-log'
+command to control what is shown and how. See linkgit:git-log[1].
 
 show [<stash>]::
 
        Show the changes recorded in the stash as a diff between the
        stashed state and its original parent. When no `<stash>` is given,
        shows the latest one. By default, the command shows the diffstat, but
-       it will accept any format known to `git-diff` (e.g., `git-stash show
+       it will accept any format known to 'git-diff' (e.g., `git stash show
        -p stash@\{1}` to view the second most recent stash in patch form).
 
 apply [--index] [<stash>]::
@@ -81,6 +87,20 @@ tree's changes, but also the index's ones. However, this can fail, when you
 have conflicts (which are stored in the index, where you therefore can no
 longer apply the changes as they were originally).
 
+branch <branchname> [<stash>]::
+
+       Creates and checks out a new branch named `<branchname>` starting from
+       the commit at which the `<stash>` was originally created, applies the
+       changes recorded in `<stash>` to the new working tree and index, then
+       drops the `<stash>` if that completes successfully. When no `<stash>`
+       is given, applies the latest one.
++
+This is useful if the branch on which you ran `git stash save` has
+changed enough that `git stash apply` fails due to conflicts. Since
+the stash is applied on top of the commit that was HEAD at the time
+`git stash` was run, it restores the originally stashed state with
+no conflicts.
+
 clear::
        Remove all the stashed states. Note that those states will then
        be subject to pruning, and may be difficult or impossible to recover.
@@ -158,7 +178,7 @@ $ git reset --soft HEAD^
 ... continue hacking ...
 ----------------------------------------------------------------
 +
-You can use `git-stash` to simplify the above, like this:
+You can use 'git-stash' to simplify the above, like this:
 +
 ----------------------------------------------------------------
 ... hack hack hack ...
@@ -169,6 +189,24 @@ $ git stash apply
 ... continue hacking ...
 ----------------------------------------------------------------
 
+Testing partial commits::
+
+You can use `git stash save --keep-index` when you want to make two or
+more commits out of the changes in the work tree, and you want to test
+each change before committing:
++
+----------------------------------------------------------------
+... hack hack hack ...
+$ git add --patch foo            # add just first part to the index
+$ git stash save --keep-index    # save all other changes to the stash
+$ edit/build/test first part
+$ git commit foo -m 'First part' # commit fully tested change
+$ git stash pop                  # prepare to work on all other changes
+... repeat above five steps until one commit remains ...
+$ edit/build/test remaining parts
+$ git commit foo -m 'Remaining parts'
+----------------------------------------------------------------
+
 SEE ALSO
 --------
 linkgit:git-checkout[1],
index fef62b16df365301f01f4c129fdba02fef84234a..57b7498239287779e7bae92bb09a0bb9eb0eed76 100644 (file)
@@ -8,7 +8,7 @@ git-status - Show the working tree status
 
 SYNOPSIS
 --------
-'git-status' <options>...
+'git status' <options>...
 
 DESCRIPTION
 -----------
@@ -17,16 +17,16 @@ current HEAD commit, paths that have differences between the working
 tree and the index file, and paths in the working tree that are not
 tracked by git (and are not ignored by linkgit:gitignore[5]). The first
 are what you _would_ commit by running `git commit`; the second and
-third are what you _could_ commit by running `git add` before running
+third are what you _could_ commit by running 'git-add' before running
 `git commit`.
 
-The command takes the same set of options as `git-commit`; it
+The command takes the same set of options as 'git-commit'; it
 shows what would be committed if the same options are given to
-`git-commit`.
+'git-commit'.
 
 If there is no path that is different between the index file and
 the current HEAD commit (i.e., there is nothing to commit by running
-`git-commit`), the command exits with non-zero status.
+`git commit`), the command exits with non-zero status.
 
 
 OUTPUT
index 8421a39f26ac4807afd42e8f3ac084686b170871..7508c0e42d2cd50ac522fc80a3a866411b7b51c5 100644 (file)
@@ -8,7 +8,7 @@ git-stripspace - Filter out empty lines
 
 SYNOPSIS
 --------
-'git-stripspace' [-s | --strip-comments] < <stream>
+'git stripspace' [-s | --strip-comments] < <stream>
 
 DESCRIPTION
 -----------
index 441ae1483bf57aca849c0470c6e19e963c9ebf19..76702a0a5aa2b8825096ebf37f76d090a1c2627b 100644 (file)
@@ -9,34 +9,51 @@ git-submodule - Initialize, update or inspect submodules
 SYNOPSIS
 --------
 [verse]
-'git-submodule' [--quiet] add [-b branch] [--] <repository> [<path>]
-'git-submodule' [--quiet] status [--cached] [--] [<path>...]
-'git-submodule' [--quiet] init [--] [<path>...]
-'git-submodule' [--quiet] update [--init] [--] [<path>...]
-'git-submodule' [--quiet] summary [--summary-limit <n>] [commit] [--] [<path>...]
+'git submodule' [--quiet] add [-b branch] [--] <repository> <path>
+'git submodule' [--quiet] status [--cached] [--] [<path>...]
+'git submodule' [--quiet] init [--] [<path>...]
+'git submodule' [--quiet] update [--init] [--] [<path>...]
+'git submodule' [--quiet] summary [--summary-limit <n>] [commit] [--] [<path>...]
 
 
 COMMANDS
 --------
 add::
        Add the given repository as a submodule at the given path
-       to the changeset to be committed next.  If path is a valid
-       repository within the project, it is added as is. Otherwise,
-       repository is cloned at the specified path. path is added to the
-       changeset and registered in .gitmodules.   If no path is
-       specified, the path is deduced from the repository specification.
-       If the repository url begins with ./ or ../, it is stored as
-       given but resolved as a relative path from the main project's
-       url when cloning.
+       to the changeset to be committed next to the current
+       project: the current project is termed termed the "superproject".
++
+This requires two arguments: <repository> and <path>.
++
+<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.
++
+<path> is the relative location for the cloned submodule to
+exist in the superproject. If <path> does not exist, then the
+submodule is created by cloning from the named URL. If <path> does
+exist and is already a valid git repository, then this is added
+to the changeset without cloning. This second form is provided
+to ease creating a new submodule from scratch, and presumes
+the user will later push the submodule to the given URL.
++
+In either case, the given URL is recorded into .gitmodules for
+use by subsequent users cloning the superproject. If the URL is
+given relative to the superproject's repository, the presumption
+is the superproject and submodule repositories will be kept
+together in the same relative location, and only the
+superproject's URL need be provided: git-submodule will correctly
+locate the submodule using the relative URL in .gitmodules.
 
 status::
        Show the status of the submodules. This will print the SHA-1 of the
        currently checked out commit for each submodule, along with the
-       submodule path and the output of linkgit:git-describe[1] for the
+       submodule path and the output of 'git-describe' for the
        SHA-1. Each SHA-1 will be prefixed with `-` if the submodule is not
        initialized and `+` if the currently checked out submodule commit
        does not match the SHA-1 found in the index of the containing
-       repository. This command is the default command for git-submodule.
+       repository. This command is the default command for 'git-submodule'.
 
 init::
        Initialize the submodules, i.e. register in .git/config each submodule
@@ -85,6 +102,7 @@ OPTIONS
 <path>::
        Path to submodule(s). When specified this will restrict the command
        to only operate on the submodules found at the specified paths.
+       (This argument is required with add).
 
 FILES
 -----
index c350ad0f83b413fa4c7810195f64cdfbbfdd1717..e7c0f1c959d39739e177096875dd8aac5fd185d9 100644 (file)
@@ -7,21 +7,21 @@ git-svn - Bidirectional operation between a single Subversion branch and git
 
 SYNOPSIS
 --------
-'git-svn' <command> [options] [arguments]
+'git svn' <command> [options] [arguments]
 
 DESCRIPTION
 -----------
-git-svn is a simple conduit for changesets between Subversion and git.
+'git-svn' is a simple conduit for changesets between Subversion and git.
 It is not to be confused with linkgit:git-svnimport[1], which is
 read-only.
 
-git-svn was originally designed for an individual developer who wants a
+'git-svn' was originally designed for an individual developer who wants a
 bidirectional flow of changesets between a single branch in Subversion
 and an arbitrary number of branches in git.  Since its inception,
-git-svn has gained the ability to track multiple branches in a manner
-similar to git-svnimport.
+'git-svn' has gained the ability to track multiple branches in a manner
+similar to 'git-svnimport'.
 
-git-svn is especially useful when it comes to tracking repositories
+'git-svn' is especially useful when it comes to tracking repositories
 not organized in the way Subversion developers recommend (trunk,
 branches, tags directories).
 
@@ -31,7 +31,7 @@ COMMANDS
 
 'init'::
        Initializes an empty git repository with additional
-       metadata directories for git-svn.  The Subversion URL
+       metadata directories for 'git-svn'.  The Subversion URL
        may be specified as a command-line argument, or as full
        URL arguments to -T/-t/-b.  Optionally, the target
        directory to operate on can be specified as a second
@@ -107,12 +107,12 @@ COMMANDS
        This fetches revisions from the SVN parent of the current HEAD
        and rebases the current (uncommitted to SVN) work against it.
 
-This works similarly to 'svn update' or 'git-pull' except that
+This works similarly to `svn update` or 'git-pull' except that
 it preserves linear history with 'git-rebase' instead of
-'git-merge' for ease of dcommiting with git-svn.
+'git-merge' for ease of dcommiting with 'git-svn'.
 
 This accepts all options that 'git-svn fetch' and 'git-rebase'
-accepts.  However '--fetch-all' only fetches from the current
+accept.  However, '--fetch-all' only fetches from the current
 [svn-remote], and not all [svn-remote] definitions.
 
 Like 'git-rebase'; this requires that the working tree be clean
@@ -128,7 +128,7 @@ and have no uncommitted changes.
        repository, and then rebase or reset (depending on whether or
        not there is a diff between SVN and head).  This will create
        a revision in SVN for each commit in git.
-       It is recommended that you run git-svn fetch and rebase (not
+       It is recommended that you run 'git-svn' fetch and rebase (not
        pull or merge) your commits against the latest changes in the
        SVN repository.
        An optional command-line argument may be specified as an
@@ -173,7 +173,7 @@ NOTE: SVN itself only stores times in UTC and nothing else. The regular svn
 client converts the UTC time to the local time (or based on the TZ=
 environment). This command has the same behaviour.
 +
-Any other arguments are passed directly to `git log'
+Any other arguments are passed directly to 'git-log'
 
 'blame'::
        Show what revision and author last modified each line of a file. The
@@ -181,10 +181,10 @@ Any other arguments are passed directly to `git log'
        `svn blame' by default. Like the SVN blame command,
        local uncommitted changes in the working copy are ignored;
        the version of the file in the HEAD revision is annotated. Unknown
-       arguments are passed directly to git-blame.
+       arguments are passed directly to 'git-blame'.
 +
 --git-format;;
-       Produce output in the same format as `git blame', but with
+       Produce output in the same format as 'git-blame', but with
        SVN revision numbers instead of git commit hashes. In this mode,
        changes that haven't been committed to SVN (including local
        working-copy edits) are shown as revision 0.
@@ -203,7 +203,7 @@ Any other arguments are passed directly to `git log'
        absolutely no attempts to do patching when committing to SVN, it
        simply overwrites files with those specified in the tree or
        commit.  All merging is assumed to have taken place
-       independently of git-svn functions.
+       independently of 'git-svn' functions.
 
 'create-ignore'::
        Recursively finds the svn:ignore property on directories and
@@ -219,12 +219,12 @@ Any other arguments are passed directly to `git log'
 'commit-diff'::
        Commits the diff of two tree-ish arguments from the
        command-line.  This command is intended for interoperability with
-       git-svnimport and does not rely on being inside an git-svn
-       init-ed repository.  This command takes three arguments, (a) the
+       'git-svnimport' and does not rely on being inside an `git-svn
+       init`-ed repository.  This command takes three arguments, (a) the
        original tree to diff against, (b) the new tree result, (c) the
        URL of the target Subversion repository.  The final argument
-       (URL) may be omitted if you are working from a git-svn-aware
-       repository (that has been init-ed with git-svn).
+       (URL) may be omitted if you are working from a 'git-svn'-aware
+       repository (that has been `init`-ed with 'git-svn').
        The -r<revision> option is required for this.
 
 'info'::
@@ -255,7 +255,7 @@ OPTIONS
 --shared[={false|true|umask|group|all|world|everybody}]::
 --template=<template_directory>::
        Only used with the 'init' command.
-       These are passed directly to linkgit:git-init[1].
+       These are passed directly to 'git-init'.
 
 -r <ARG>::
 --revision <ARG>::
@@ -277,7 +277,7 @@ Only used with the 'set-tree' command.
 
 Read a list of commits from stdin and commit them in reverse
 order.  Only the leading sha1 is read from each line, so
-git-rev-list --pretty=oneline output can be used.
+'git-rev-list --pretty=oneline' output can be used.
 
 --rmdir::
 
@@ -307,7 +307,7 @@ config key: svn.edit
 
 Only used with the 'dcommit', 'set-tree' and 'commit-diff' commands.
 
-They are both passed directly to git-diff-tree see
+They are both passed directly to 'git-diff-tree'; see
 linkgit:git-diff-tree[1] for more information.
 
 [verse]
@@ -317,24 +317,24 @@ config key: svn.findcopiesharder
 -A<filename>::
 --authors-file=<filename>::
 
-Syntax is compatible with the files used by git-svnimport and
-git-cvsimport:
+Syntax is compatible with the files used by 'git-svnimport' and
+'git-cvsimport':
 
 ------------------------------------------------------------------------
        loginname = Joe User <user@example.com>
 ------------------------------------------------------------------------
 
-If this option is specified and git-svn encounters an SVN
-committer name that does not exist in the authors-file, git-svn
+If this option is specified and 'git-svn' encounters an SVN
+committer name that does not exist in the authors-file, 'git-svn'
 will abort operation. The user will then have to add the
-appropriate entry.  Re-running the previous git-svn command
+appropriate entry.  Re-running the previous 'git-svn' command
 after the authors-file is modified should continue operation.
 
 config key: svn.authorsfile
 
 -q::
 --quiet::
-       Make git-svn less verbose.
+       Make 'git-svn' less verbose.
 
 --repack[=<n>]::
 --repack-flags=<flags>::
@@ -346,7 +346,7 @@ with many revisions.
 to fetch before repacking.  This defaults to repacking every
 1000 commits fetched if no argument is specified.
 
---repack-flags are passed directly to linkgit:git-repack[1].
+--repack-flags are passed directly to 'git-repack'.
 
 [verse]
 config key: svn.repack
@@ -359,8 +359,8 @@ config key: svn.repackflags
 
 These are only used with the 'dcommit' and 'rebase' commands.
 
-Passed directly to git-rebase when using 'dcommit' if a
-'git-reset' cannot be used (see dcommit).
+Passed directly to 'git-rebase' when using 'dcommit' if a
+'git-reset' cannot be used (see 'dcommit').
 
 -n::
 --dry-run::
@@ -411,9 +411,9 @@ CONFIG FILE-ONLY OPTIONS
 svn.noMetadata::
 svn-remote.<name>.noMetadata::
 
-This gets rid of the git-svn-id: lines at the end of every commit.
+This gets rid of the 'git-svn-id:' lines at the end of every commit.
 
-If you lose your .git/svn/git-svn/.rev_db file, git-svn will not
+If you lose your .git/svn/git-svn/.rev_db file, 'git-svn' will not
 be able to rebuild it and you won't be able to fetch again,
 either.  This is fine for one-shot imports.
 
@@ -424,7 +424,7 @@ option for (hopefully) obvious reasons.
 svn.useSvmProps::
 svn-remote.<name>.useSvmProps::
 
-This allows git-svn to re-map repository URLs and UUIDs from
+This allows 'git-svn' to re-map repository URLs and UUIDs from
 mirrors created using SVN::Mirror (or svk) for metadata.
 
 If an SVN revision has a property, "svm:headrev", it is likely
@@ -443,7 +443,7 @@ svn-remote.<name>.useSvnsyncprops::
 
 svn-remote.<name>.rewriteRoot::
        This allows users to create repositories from alternate
-       URLs.  For example, an administrator could run git-svn on the
+       URLs.  For example, an administrator could run 'git-svn' on the
        server locally (accessing via file://) but wish to distribute
        the repository with a public http:// or svn:// URL in the
        metadata so users of it will see the public URL.
@@ -451,7 +451,7 @@ svn-remote.<name>.rewriteRoot::
 --
 
 Since the noMetadata, rewriteRoot, useSvnsyncProps and useSvmProps
-options all affect the metadata generated and used by git-svn; they
+options all affect the metadata generated and used by 'git-svn'; they
 *must* be set in the configuration file before any history is imported
 and these settings should never be changed once they are set.
 
@@ -466,7 +466,7 @@ Tracking and contributing to the trunk of a Subversion-managed project:
 
 ------------------------------------------------------------------------
 # Clone a repo (like git clone):
-       git-svn clone http://svn.foo.org/project/trunk
+       git svn clone http://svn.foo.org/project/trunk
 # Enter the newly cloned directory:
        cd trunk
 # You should be on master branch, double-check with git-branch
@@ -475,12 +475,12 @@ Tracking and contributing to the trunk of a Subversion-managed project:
        git commit ...
 # Something is committed to SVN, rebase your local changes against the
 # latest changes in SVN:
-       git-svn rebase
+       git svn rebase
 # Now commit your changes (that were committed previously using git) to SVN,
 # as well as automatically updating your working HEAD:
-       git-svn dcommit
+       git svn dcommit
 # Append svn:ignore settings to the default git exclude file:
-       git-svn show-ignore >> .git/info/exclude
+       git svn show-ignore >> .git/info/exclude
 ------------------------------------------------------------------------
 
 Tracking and contributing to an entire Subversion-managed project
@@ -488,7 +488,7 @@ Tracking and contributing to an entire Subversion-managed project
 
 ------------------------------------------------------------------------
 # Clone a repo (like git clone):
-       git-svn clone http://svn.foo.org/project -T trunk -b branches -t tags
+       git svn clone http://svn.foo.org/project -T trunk -b branches -t tags
 # View all branches and tags you have cloned:
        git branch -r
 # Reset your master to trunk (or any other branch, replacing 'trunk'
@@ -501,45 +501,45 @@ Tracking and contributing to an entire Subversion-managed project
 The initial 'git-svn clone' can be quite time-consuming
 (especially for large Subversion repositories). If multiple
 people (or one person with multiple machines) want to use
-git-svn to interact with the same Subversion repository, you can
+'git-svn' to interact with the same Subversion repository, you can
 do the initial 'git-svn clone' to a repository on a server and
-have each person clone that repository with 'git clone':
+have each person clone that repository with 'git-clone':
 
 ------------------------------------------------------------------------
 # Do the initial import on a server
-       ssh server "cd /pub && git-svn clone http://svn.foo.org/project
+       ssh server "cd /pub && git svn clone http://svn.foo.org/project
 # Clone locally - make sure the refs/remotes/ space matches the server
        mkdir project
        cd project
-       git-init
+       git init
        git remote add origin server:/pub/project
        git config --add remote.origin.fetch '+refs/remotes/*:refs/remotes/*'
        git fetch
 # Initialize git-svn locally (be sure to use the same URL and -T/-b/-t options as were used on server)
-       git-svn init http://svn.foo.org/project
+       git svn init http://svn.foo.org/project
 # Pull the latest changes from Subversion
-       git-svn rebase
+       git svn rebase
 ------------------------------------------------------------------------
 
 REBASE VS. PULL/MERGE
 ---------------------
 
-Originally, git-svn recommended that the remotes/git-svn branch be
+Originally, 'git-svn' recommended that the 'remotes/git-svn' branch be
 pulled or merged from.  This is because the author favored
-'git-svn set-tree B' to commit a single head rather than the
-'git-svn set-tree A..B' notation to commit multiple commits.
+`git svn set-tree B` to commit a single head rather than the
+`git svn set-tree A..B` notation to commit multiple commits.
 
-If you use 'git-svn set-tree A..B' to commit several diffs and you do
+If you use `git svn set-tree A..B` to commit several diffs and you do
 not have the latest remotes/git-svn merged into my-branch, you should
-use 'git-svn rebase' to update your work branch instead of 'git pull' or
-'git merge'.  'pull/merge' can cause non-linear history to be flattened
+use `git svn rebase` to update your work branch instead of `git pull` or
+`git merge`.  `pull`/`merge' can cause non-linear history to be flattened
 when committing into SVN, which can lead to merge commits reversing
 previous commits in SVN.
 
 DESIGN PHILOSOPHY
 -----------------
 Merge tracking in Subversion is lacking and doing branched development
-with Subversion can be cumbersome as a result.  While git-svn can track
+with Subversion can be cumbersome as a result.  While 'git-svn' can track
 copy history (including branches and tags) for repositories adopting a
 standard layout, it cannot yet represent merge history that happened
 inside git back upstream to SVN users.  Therefore it is advised that
@@ -550,30 +550,30 @@ CAVEATS
 -------
 
 For the sake of simplicity and interoperating with a less-capable system
-(SVN), it is recommended that all git-svn users clone, fetch and dcommit
-directly from the SVN server, and avoid all git-clone/pull/merge/push
+(SVN), it is recommended that all 'git-svn' users clone, fetch and dcommit
+directly from the SVN server, and avoid all 'git-clone'/'pull'/'merge'/'push'
 operations between git repositories and branches.  The recommended
 method of exchanging code between git branches and users is
-git-format-patch and git-am, or just dcommiting to the SVN repository.
+'git-format-patch' and 'git-am', or just 'dcommit'ing to the SVN repository.
 
 Running 'git-merge' or 'git-pull' is NOT recommended on a branch you
-plan to dcommit from.  Subversion does not represent merges in any
+plan to 'dcommit' from.  Subversion does not represent merges in any
 reasonable or useful fashion; so users using Subversion cannot see any
 merges you've made.  Furthermore, if you merge or pull from a git branch
-that is a mirror of an SVN branch, dcommit may commit to the wrong
+that is a mirror of an SVN branch, 'dcommit' may commit to the wrong
 branch.
 
 'git-clone' does not clone branches under the refs/remotes/ hierarchy or
-any git-svn metadata, or config.  So repositories created and managed with
-using git-svn should use rsync(1) for cloning, if cloning is to be done
+any 'git-svn' metadata, or config.  So repositories created and managed with
+using 'git-svn' should use 'rsync' for cloning, if cloning is to be done
 at all.
 
-Since 'dcommit' uses rebase internally, any git branches you git-push to
-before dcommit on will require forcing an overwrite of the existing ref
+Since 'dcommit' uses rebase internally, any git branches you 'git-push' to
+before 'dcommit' on will require forcing an overwrite of the existing ref
 on the remote repository.  This is generally considered bad practice,
-see the git-push(1) documentation for details.
+see the linkgit:git-push[1] documentation for details.
 
-Do not use the --amend option of git-commit(1) on a change you've
+Do not use the --amend option of linkgit:git-commit[1] on a change you've
 already dcommitted.  It is considered bad practice to --amend commits
 you've already pushed to a remote repository for other users, and
 dcommit with SVN is analogous to that.
@@ -594,7 +594,7 @@ for git to detect them.
 CONFIGURATION
 -------------
 
-git-svn stores [svn-remote] configuration information in the
+'git-svn' stores [svn-remote] configuration information in the
 repository .git/config file.  It is similar the core git
 [remote] sections except 'fetch' keys do not accept glob
 arguments; but they are instead handled by the 'branches'
@@ -615,8 +615,7 @@ Keep in mind that the '*' (asterisk) wildcard of the local ref
 however the remote wildcard may be anywhere as long as it's own
 independent path component (surrounded by '/' or EOL).   This
 type of configuration is not automatically created by 'init' and
-should be manually entered with a text-editor or using
-linkgit:git-config[1]
+should be manually entered with a text-editor or using 'git-config'.
 
 SEE ALSO
 --------
index 3d3a059c5e2e91bff2de173c5d6f8107d10b7e62..6266e6f6589388571d981153500ee52c55e9870d 100644 (file)
@@ -7,7 +7,7 @@ git-symbolic-ref - Read and modify symbolic refs
 
 SYNOPSIS
 --------
-'git-symbolic-ref' [-q] [-m <reason>] <name> [<ref>]
+'git symbolic-ref' [-q] [-m <reason>] <name> [<ref>]
 
 DESCRIPTION
 -----------
@@ -49,7 +49,7 @@ cumbersome.  On some platforms, `ln -sf` does not even work as
 advertised (horrors).  Therefore symbolic links are now deprecated
 and symbolic refs are used by default.
 
-git-symbolic-ref will exit with status 0 if the contents of the
+'git-symbolic-ref' will exit with status 0 if the contents of the
 symbolic ref were printed correctly, with status 1 if the requested
 name is not a symbolic ref, or 128 if another error occurs.
 
index 8f40f4bf0df8bb8db58830e32d85964542d6cd6a..b605e6caa2a9510ffd0825d6f721b881f1826863 100644 (file)
@@ -9,10 +9,10 @@ git-tag - Create, list, delete or verify a tag object signed with GPG
 SYNOPSIS
 --------
 [verse]
-'git-tag' [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>]  <name> [<head>]
-'git-tag' -d <name>...
-'git-tag' [-n[<num>]] -l [<pattern>]
-'git-tag' -v <name>...
+'git tag' [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>]  <name> [<head>]
+'git tag' -d <name>...
+'git tag' [-n[<num>]] -l [<pattern>]
+'git tag' -v <name>...
 
 DESCRIPTION
 -----------
@@ -82,7 +82,7 @@ OPTIONS
 
 CONFIGURATION
 -------------
-By default, git-tag in sign-with-default mode (-s) will use your
+By default, 'git-tag' in sign-with-default mode (-s) will use your
 committer identity (of the form "Your Name <your@email.address>") to
 find a key.  If you want to use a different default key, you can specify
 it in the repository configuration as follows:
@@ -118,12 +118,12 @@ and be done with it.
 
 . The insane thing.
 You really want to call the new version "X" too, 'even though'
-others have already seen the old one. So just use "git tag -f"
+others have already seen the old one. So just use 'git-tag -f'
 again, as if you hadn't already published the old one.
 
 However, Git does *not* (and it should not) change tags behind
-users back. So if somebody already got the old tag, doing a "git
-pull" on your tree shouldn't just make them overwrite the old
+users back. So if somebody already got the old tag, doing a
+'git-pull' on your tree shouldn't just make them overwrite the old
 one.
 
 If somebody got a release tag from you, you cannot just change
@@ -177,7 +177,7 @@ private anchor point tags from the other person.
 
 You would notice "please pull" messages on the mailing list says
 repo URL and branch name alone.  This is designed to be easily
-cut&pasted to "git fetch" command line:
+cut&pasted to a 'git-fetch' command line:
 
 ------------
 Linus, please pull from
index 74ed06525e8f920017469301f9773e4b36080ee9..a5d9558dd1eabd71e838026721d707c5f1ecc369 100644 (file)
@@ -8,23 +8,23 @@ git-tar-tree - Create a tar archive of the files in the named tree object
 
 SYNOPSIS
 --------
-'git-tar-tree' [--remote=<repo>] <tree-ish> [ <base> ]
+'git tar-tree' [--remote=<repo>] <tree-ish> [ <base> ]
 
 DESCRIPTION
 -----------
-THIS COMMAND IS DEPRECATED.  Use `git-archive` with `--format=tar`
+THIS COMMAND IS DEPRECATED.  Use 'git-archive' with `--format=tar`
 option instead (and move the <base> argument to `--prefix=base/`).
 
 Creates a tar archive containing the tree structure for the named tree.
 When <base> is specified it is added as a leading path to the files in the
 generated tar archive.
 
-git-tar-tree behaves differently when given a tree ID versus when given
+'git-tar-tree' behaves differently when given a tree ID versus when given
 a commit ID or tag ID.  In the first case the current time is used as
 modification time of each file in the archive.  In the latter case the
 commit time as recorded in the referenced commit object is used instead.
 Additionally the commit ID is stored in a global extended pax header.
-It can be extracted using git-get-tar-commit-id.
+It can be extracted using 'git-get-tar-commit-id'.
 
 OPTIONS
 -------
index d0552b2c74b25c12e99ba071bb91f12ccd29681a..995db9feadf68df6f22de745d90790a145128e44 100644 (file)
@@ -9,7 +9,7 @@ git-unpack-file - Creates a temporary file with a blob's contents
 
 SYNOPSIS
 --------
-'git-unpack-file' <blob>
+'git unpack-file' <blob>
 
 DESCRIPTION
 -----------
index b9c4279a880c722a1e751469244f79323e618eb8..36d1038056101a459a33e32b6729d75e03f127ce 100644 (file)
@@ -8,7 +8,7 @@ git-unpack-objects - Unpack objects from a packed archive
 
 SYNOPSIS
 --------
-'git-unpack-objects' [-n] [-q] [-r] [--strict] <pack-file
+'git unpack-objects' [-n] [-q] [-r] [--strict] <pack-file
 
 
 DESCRIPTION
@@ -21,7 +21,7 @@ Objects that already exist in the repository will *not* be unpacked
 from the pack-file.  Therefore, nothing will be unpacked if you use
 this command on a pack-file that exists within the target repository.
 
-Please see the `git-repack` documentation for options to generate
+See linkgit:git-repack[1] for options to generate
 new packs and replace existing ones.
 
 OPTIONS
index bbb0a6ad57187c4387412a08ff301ddfc7173726..a91fd214d2246b6fbf20543a8d285f619ecd7e58 100644 (file)
@@ -9,7 +9,7 @@ git-update-index - Register file contents in the working tree to the index
 SYNOPSIS
 --------
 [verse]
-'git-update-index'
+'git update-index'
             [--add] [--remove | --force-remove] [--replace]
             [--refresh] [-q] [--unmerged] [--ignore-missing]
             [--cacheinfo <mode> <object> <file>]\*
@@ -31,7 +31,7 @@ cleared.
 See also linkgit:git-add[1] for a more user-friendly way to do some of
 the most common operations on the index.
 
-The way "git-update-index" handles files it is told about can be modified
+The way 'git-update-index' handles files it is told about can be modified
 using the various options:
 
 OPTIONS
@@ -53,7 +53,7 @@ OPTIONS
 -q::
         Quiet.  If --refresh finds that the index needs an update, the
         default behavior is to error out.  This option makes
-        git-update-index continue anyway.
+       'git-update-index' continue anyway.
 
 --ignore-submodules:
        Do not try to update submodules.  This option is only respected
@@ -61,7 +61,7 @@ OPTIONS
 
 --unmerged::
         If --refresh finds unmerged changes in the index, the default
-        behavior is to error out.  This option makes git-update-index
+       behavior is to error out.  This option makes 'git-update-index'
         continue anyway.
 
 --ignore-missing::
@@ -91,7 +91,7 @@ OPTIONS
 
 -g::
 --again::
-       Runs `git-update-index` itself on the paths whose index
+       Runs 'git-update-index' itself on the paths whose index
        entries are different from those from the `HEAD` commit.
 
 --unresolve::
@@ -109,7 +109,7 @@ OPTIONS
 
 --replace::
        By default, when a file `path` exists in the index,
-       git-update-index refuses an attempt to add `path/file`.
+       'git-update-index' refuses an attempt to add `path/file`.
        Similarly if a file `path/file` exists, a file `path`
        cannot be added.  With --replace flag, existing entries
        that conflicts with the entry being added are
@@ -145,7 +145,7 @@ up-to-date for mode/content changes. But what it *does* do is to
 can refresh the index for a file that hasn't been changed but where
 the stat entry is out of date.
 
-For example, you'd want to do this after doing a "git-read-tree", to link
+For example, you'd want to do this after doing a 'git-read-tree', to link
 up the stat index details with the proper files.
 
 Using --cacheinfo or --info-only
@@ -157,7 +157,7 @@ merging.
 To pretend you have a file with mode and sha1 at path, say:
 
 ----------------
-$ git-update-index --cacheinfo mode sha1 path
+$ git update-index --cacheinfo mode sha1 path
 ----------------
 
 '--info-only' is used to register files without placing them in the object
@@ -186,13 +186,13 @@ back on 3-way merge.
 
     . mode SP type SP sha1          TAB path
 +
-The second format is to stuff git-ls-tree output
+The second format is to stuff 'git-ls-tree' output
 into the index file.
 
     . mode         SP sha1 SP stage TAB path
 +
 This format is to put higher order stages into the
-index file and matches git-ls-files --stage output.
+index file and matches 'git-ls-files --stage' output.
 
 To place a higher stage entry to the index, the path should
 first be removed by feeding a mode=0 entry for the path, and
@@ -247,13 +247,13 @@ In order to set "assume unchanged" bit, use `--assume-unchanged`
 option.  To unset, use `--no-assume-unchanged`.
 
 The command looks at `core.ignorestat` configuration variable.  When
-this is true, paths updated with `git-update-index paths...` and
+this is true, paths updated with `git update-index paths...` and
 paths updated with other git commands that update both index and
-working tree (e.g. `git-apply --index`, `git-checkout-index -u`,
-and `git-read-tree -u`) are automatically marked as "assume
+working tree (e.g. 'git-apply --index', 'git-checkout-index -u',
+and 'git-read-tree -u') are automatically marked as "assume
 unchanged".  Note that "assume unchanged" bit is *not* set if
-`git-update-index --refresh` finds the working tree file matches
-the index (use `git-update-index --really-refresh` if you want
+`git update-index --refresh` finds the working tree file matches
+the index (use `git update-index --really-refresh` if you want
 to mark them as "assume unchanged").
 
 
@@ -262,7 +262,7 @@ Examples
 To update and refresh only the files already checked out:
 
 ----------------
-$ git-checkout-index -n -f -a && git-update-index --ignore-missing --refresh
+$ git checkout-index -n -f -a && git update-index --ignore-missing --refresh
 ----------------
 
 On an inefficient filesystem with `core.ignorestat` set::
@@ -303,7 +303,7 @@ unreliable, this should be set to 'false' (see linkgit:git-config[1]).
 This causes the command to ignore differences in file modes recorded
 in the index and the file mode on the filesystem if they differ only on
 executable bit.   On such an unfortunate filesystem, you may
-need to use `git-update-index --chmod=`.
+need to use 'git-update-index --chmod='.
 
 Quite similarly, if `core.symlinks` configuration variable is set
 to 'false' (see linkgit:git-config[1]), symbolic links are checked out
index 7f7e3d197bafbbb2efe610096b0cad6901488be5..9639f705afafab6fcf0cd21ad2693627ab42f66d 100644 (file)
@@ -7,18 +7,18 @@ git-update-ref - Update the object name stored in a ref safely
 
 SYNOPSIS
 --------
-'git-update-ref' [-m <reason>] (-d <ref> <oldvalue> | [--no-deref] <ref> <newvalue> [<oldvalue>])
+'git update-ref' [-m <reason>] (-d <ref> [<oldvalue>] | [--no-deref] <ref> <newvalue> [<oldvalue>])
 
 DESCRIPTION
 -----------
 Given two arguments, stores the <newvalue> in the <ref>, possibly
-dereferencing the symbolic refs.  E.g. `git-update-ref HEAD
+dereferencing the symbolic refs.  E.g. `git update-ref HEAD
 <newvalue>` updates the current branch head to the new object.
 
 Given three arguments, stores the <newvalue> in the <ref>,
 possibly dereferencing the symbolic refs, after verifying that
 the current value of the <ref> matches <oldvalue>.
-E.g. `git-update-ref refs/heads/master <newvalue> <oldvalue>`
+E.g. `git update-ref refs/heads/master <newvalue> <oldvalue>`
 updates the master branch head to <newvalue> only if its current
 value is <oldvalue>.  You can specify 40 "0" or an empty string
 as <oldvalue> to make sure that the ref you are creating does
@@ -41,7 +41,7 @@ the result of following the symbolic pointers.
 
 In general, using
 
-       git-update-ref HEAD "$head"
+       git update-ref HEAD "$head"
 
 should be a _lot_ safer than doing
 
@@ -61,7 +61,7 @@ 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
+"$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 d21be41d0646c80e7ec9aeb1ed46ce617022e3cc..bc1207a317b9c1e93ba35c5a9e82a5e243b4a42e 100644 (file)
@@ -8,7 +8,7 @@ git-update-server-info - Update auxiliary info file to help dumb servers
 
 SYNOPSIS
 --------
-'git-update-server-info' [--force]
+'git update-server-info' [--force]
 
 DESCRIPTION
 -----------
@@ -31,7 +31,7 @@ OUTPUT
 ------
 
 Currently the command updates the following files.  Please see
-linkgit:gitrepository-layout[5][repository-layout] for description of
+linkgit:gitrepository-layout[5] for description of
 what they are for:
 
 * objects/info/packs
index e49f68f68e490d7230963eec06b91ab09c34e19a..bbd7617587084b0c66fd8e0b9f623cac50be2c03 100644 (file)
@@ -8,7 +8,7 @@ git-upload-archive - Send archive back to git-archive
 
 SYNOPSIS
 --------
-'git-upload-archive' <directory>
+'git upload-archive' <directory>
 
 DESCRIPTION
 -----------
index bac465e13f2b2d0aaadaedf00fd03ab6f3f9a62c..b8e49dce4a19a4d7083459468f27c273c1d91fea 100644 (file)
@@ -8,7 +8,7 @@ git-upload-pack - Send objects packed back to git-fetch-pack
 
 SYNOPSIS
 --------
-'git-upload-pack' [--strict] [--timeout=<n>] <directory>
+'git upload-pack' [--strict] [--timeout=<n>] <directory>
 
 DESCRIPTION
 -----------
index 67e8e1f93a37d19183a41b1119569d980cc43eea..3647dd6c8f9c74a688f7a143119386ba89a8f13d 100644 (file)
@@ -8,7 +8,7 @@ git-var - Show a git logical variable
 
 SYNOPSIS
 --------
-'git-var' [ -l | <variable> ]
+'git var' [ -l | <variable> ]
 
 DESCRIPTION
 -----------
@@ -20,11 +20,11 @@ OPTIONS
        Cause the logical variables to be listed. In addition, all the
        variables of the git configuration file .git/config are listed
        as well. (However, the configuration variables listing functionality
-       is deprecated in favor of `git-config -l`.)
+       is deprecated in favor of 'git-config -l'.)
 
 EXAMPLE
 --------
-       $ git-var GIT_AUTHOR_IDENT
+       $ git var GIT_AUTHOR_IDENT
        Eric W. Biederman <ebiederm@lnxi.com> 1121223278 -0600
 
 
index 478f236996eac55c8142d48de8bda1456b426d4a..53a9ce308541c73b6a0fc880d699ed7bed1817cb 100644 (file)
@@ -8,13 +8,13 @@ git-verify-pack - Validate packed git archive files
 
 SYNOPSIS
 --------
-'git-verify-pack' [-v] [--] <pack>.idx ...
+'git verify-pack' [-v] [--] <pack>.idx ...
 
 
 DESCRIPTION
 -----------
-Reads given idx file for packed git archive created with
-git-pack-objects command and verifies idx file and the
+Reads given idx file for packed git archive created with the
+'git-pack-objects' command and verifies idx file and the
 corresponding pack file.
 
 OPTIONS
index dffba8906ae27bbb305f14732c390eea39bbdca5..ba837df4bc66e2b828fcd49c94f35957c27322df 100644 (file)
@@ -7,11 +7,11 @@ git-verify-tag - Check the GPG signature of tags
 
 SYNOPSIS
 --------
-'git-verify-tag' <tag>...
+'git verify-tag' <tag>...
 
 DESCRIPTION
 -----------
-Validates the gpg signature created by git-tag.
+Validates the gpg signature created by 'git-tag'.
 
 OPTIONS
 -------
index e80a7c1cc4c1b62bc4fbdb0a91f063022542d38d..36afad8d4e0d67a8d9dd33d3bc590789e9f6604d 100644 (file)
@@ -7,7 +7,7 @@ git-web--browse - git helper script to launch a web browser
 
 SYNOPSIS
 --------
-'git-web--browse' [OPTIONS] URL/FILE ...
+'git web--browse' [OPTIONS] URL/FILE ...
 
 DESCRIPTION
 -----------
@@ -70,7 +70,7 @@ browser.<tool>.cmd
 When the browser, specified by options or configuration variables, is
 not among the supported ones, then the corresponding
 'browser.<tool>.cmd' configuration variable will be looked up. If this
-variable exists then "git web--browse" will treat the specified tool
+variable exists then 'git-web--browse' will treat the specified tool
 as a custom command and will use a shell eval to run the command with
 the URLs passed as arguments.
 
@@ -96,7 +96,7 @@ the following:
                cmd = A_PATH_TO/konqueror
 ------------------------------------------------
 
-Note about git config --global
+Note about git-config --global
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Note that these configuration variables should probably be set using
@@ -112,7 +112,7 @@ See linkgit:git-config[1] for more information about this.
 Author
 ------
 Written by Christian Couder <chriscool@tuxfamily.org> and the git-list
-<git@vger.kernel.org>, based on git-mergetool by Theodore Y. Ts'o.
+<git@vger.kernel.org>, based on 'git-mergetool' by Theodore Y. Ts'o.
 
 Documentation
 -------------
index f5d39c7870b9f6d07c8fadd3823df5d56da2dfe0..d7fad1532936d909f9daf59f209e9c59c17c74c5 100644 (file)
@@ -8,7 +8,7 @@ git-whatchanged - Show logs with difference each commit introduces
 
 SYNOPSIS
 --------
-'git-whatchanged' <option>...
+'git whatchanged' <option>...
 
 DESCRIPTION
 -----------
@@ -52,12 +52,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 8744f6535d4c411b620e1504c92a04791f0246df..26d3850e7317c22dcf0999e0c4a6afe9a5ea2e03 100644 (file)
@@ -8,7 +8,7 @@ git-write-tree - Create a tree object from the current index
 
 SYNOPSIS
 --------
-'git-write-tree' [--missing-ok] [--prefix=<prefix>/]
+'git write-tree' [--missing-ok] [--prefix=<prefix>/]
 
 DESCRIPTION
 -----------
@@ -16,17 +16,17 @@ Creates a tree object using the current index.
 
 The index must be in a fully merged state.
 
-Conceptually, `git-write-tree` sync()s the current index contents
+Conceptually, 'git-write-tree' sync()s the current index contents
 into a set of tree files.
 In order to have that match what is actually in your directory right
-now, you need to have done a `git-update-index` phase before you did the
-`git-write-tree`.
+now, you need to have done a 'git-update-index' phase before you did the
+'git-write-tree'.
 
 
 OPTIONS
 -------
 --missing-ok::
-       Normally `git-write-tree` ensures that the objects referenced by the
+       Normally 'git-write-tree' ensures that the objects referenced by the
        directory exist in the object database.  This option disables this
        check.
 
index 0d6fe9cf79a5d6c65d3c94cb237cf85ccade2aef..27b9d31f7e274b4be45891a97a984ec566927ccc 100644 (file)
@@ -20,11 +20,11 @@ Git is a fast, scalable, distributed revision control system with an
 unusually rich command set that provides both high-level operations
 and full access to internals.
 
-See this linkgit:gittutorial[7][tutorial] to get started, then see
+See linkgit:gittutorial[7] to get started, then see
 link:everyday.html[Everyday Git] for a useful minimum set of commands, and
 "man git-commandname" for documentation of each command.  CVS users may
-also want to read linkgit:gitcvs-migration[7][CVS migration].  See
-link:user-manual.html[Git User's Manual] for a more in-depth
+also want to read linkgit:gitcvs-migration[7].  See
+the link:user-manual.html[Git User's Manual] for a more in-depth
 introduction.
 
 The COMMAND is either a name of a Git command (see below) or an alias
@@ -43,9 +43,10 @@ unreleased) version of git, that is available from 'master'
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
-* link:v1.5.6.2/git.html[documentation for release 1.5.6.2]
+* link:v1.5.6.3/git.html[documentation for release 1.5.6.3]
 
 * release notes for
+  link:RelNotes-1.5.6.3.txt[1.5.6.3].
   link:RelNotes-1.5.6.2.txt[1.5.6.2].
   link:RelNotes-1.5.6.1.txt[1.5.6.1].
   link:RelNotes-1.5.6.txt[1.5.6].
@@ -136,13 +137,13 @@ OPTIONS
 +
 Other options are available to control how the manual page is
 displayed. See linkgit:git-help[1] for more information,
-because 'git --help ...' is converted internally into 'git
-help ...'.
+because `git --help ...` is converted internally into `git
+help ...`.
 
 --exec-path::
        Path to wherever your core git programs are installed.
        This can also be controlled by setting the GIT_EXEC_PATH
-       environment variable. If no path is given 'git' will print
+       environment variable. If no path is given, 'git' will print
        the current setting and then exit.
 
 -p::
@@ -183,13 +184,14 @@ See the references above to get started using git.  The following is
 probably more detail than necessary for a first-time user.
 
 The link:user-manual.html#git-concepts[git concepts chapter of the
-user-manual] and the linkgit:gitcore-tutorial[7][Core tutorial] both provide
+user-manual] and linkgit:gitcore-tutorial[7] both provide
 introductions to the underlying git architecture.
 
 See also the link:howto-index.html[howto] documents for some useful
 examples.
 
-The internals are documented link:technical/api-index.html[here].
+The internals are documented in the
+link:technical/api-index.html[GIT API documentation].
 
 GIT COMMANDS
 ------------
@@ -373,10 +375,9 @@ For a more complete list of ways to spell object names, see
 File/Directory Structure
 ------------------------
 
-Please see the linkgit:gitrepository-layout[5][repository layout]
-document.
+Please see the linkgit:gitrepository-layout[5] document.
 
-Read linkgit:githooks[5][hooks] for more details about each hook.
+Read linkgit:githooks[5] for more details about each hook.
 
 Higher level SCMs may provide and manage additional information in the
 `$GIT_DIR`.
@@ -384,7 +385,7 @@ Higher level SCMs may provide and manage additional information in the
 
 Terminology
 -----------
-Please see the linkgit:gitglossary[7][glossary] document.
+Please see linkgit:gitglossary[7].
 
 
 Environment Variables
@@ -411,9 +412,9 @@ git so take care if using Cogito etc.
 'GIT_ALTERNATE_OBJECT_DIRECTORIES'::
        Due to the immutable nature of git objects, old objects can be
        archived into shared, read-only directories. This variable
-       specifies a ":" separated list of git object directories which
-       can be used to search for git objects. New objects will not be
-       written to these directories.
+       specifies a ":" separated (on Windows ";" separated) list
+       of git object directories which can be used to search for git
+       objects. New objects will not be written to these directories.
 
 'GIT_DIR'::
        If the 'GIT_DIR' environment variable is set then it
@@ -427,6 +428,14 @@ git so take care if using Cogito etc.
        This can also be controlled by the '--work-tree' command line
        option and the core.worktree configuration variable.
 
+'GIT_CEILING_DIRECTORIES'::
+       This should be a colon-separated list of absolute paths.
+       If set, it is a list of directories that git should not chdir
+       up into while looking for a repository directory.
+       It will not exclude the current working directory or
+       a GIT_DIR set on the command line or in the environment.
+       (Useful for excluding slow-loading network directories.)
+
 git Commits
 ~~~~~~~~~~~
 'GIT_AUTHOR_NAME'::
@@ -484,10 +493,10 @@ other
        a pager.
 
 'GIT_SSH'::
-       If this environment variable is set then linkgit:git-fetch[1]
-       and linkgit:git-push[1] will use this command instead
-       of `ssh` when they need to connect to a remote system.
-       The 'GIT_SSH' command will be given exactly two arguments:
+       If this environment variable is set then 'git-fetch'
+       and 'git-push' will use this command instead
+       of 'ssh' when they need to connect to a remote system.
+       The '$GIT_SSH' command will be given exactly two arguments:
        the 'username@host' (or just 'host') from the URL and the
        shell command to execute on that remote system.
 +
@@ -501,8 +510,8 @@ for further details.
 
 'GIT_FLUSH'::
        If this environment variable is set to "1", then commands such
-       as git-blame (in incremental mode), git-rev-list, git-log,
-       git-whatchanged, etc., will force a flush of the output stream
+       as 'git-blame' (in incremental mode), 'git-rev-list', 'git-log',
+       and 'git-whatchanged' will force a flush of the output stream
        after each commit-oriented record have been flushed.   If this
        variable is set to "0", the output of these commands will be done
        using completely buffered I/O.   If this environment variable is
@@ -528,7 +537,7 @@ Discussion[[Discussion]]
 
 More detail on the following is available from the
 link:user-manual.html#git-concepts[git concepts chapter of the
-user-manual] and the linkgit:gitcore-tutorial[7][Core tutorial].
+user-manual] and linkgit:gitcore-tutorial[7].
 
 A git project normally consists of a working directory with a ".git"
 subdirectory at the top level.  The .git directory contains, among other
@@ -592,9 +601,9 @@ contributors on the git-list <git@vger.kernel.org>.
 SEE ALSO
 --------
 linkgit:gittutorial[7], linkgit:gittutorial-2[7],
-linkgit:giteveryday[7], linkgit:gitcvs-migration[7],
+linkgit:everyday[7], linkgit:gitcvs-migration[7],
 linkgit:gitglossary[7], linkgit:gitcore-tutorial[7],
-link:user-manual.html[The Git User's Manual]
+linkgit:gitcli[7], link:user-manual.html[The Git User's Manual]
 
 GIT
 ---
index ef06d94ca8dd57762fcefe3b87921799d49dffb6..d7b41142d2c843bc5460f03c73c609b1c53ff4a6 100644 (file)
@@ -87,9 +87,9 @@ Checking-out and checking-in
 
 These attributes affect how the contents stored in the
 repository are copied to the working tree files when commands
-such as `git checkout` and `git merge` run.  They also affect how
+such as 'git-checkout' and 'git-merge' run.  They also affect how
 git stores the contents you prepare in the working tree in the
-repository upon `git add` and `git commit`.
+repository upon 'git-add' and 'git-commit'.
 
 `crlf`
 ^^^^^^
@@ -148,16 +148,16 @@ an irreversible conversion.  The safety triggers to prevent such
 a conversion done to the files in the work tree, but there are a
 few exceptions.  Even though...
 
-- "git add" itself does not touch the files in the work tree, the
+- 'git-add' itself does not touch the files in the work tree, the
   next checkout would, so the safety triggers;
 
-- "git apply" to update a text file with a patch does touch the files
+- 'git-apply' to update a text file with a patch does touch the files
   in the work tree, but the operation is about text files and CRLF
   conversion is about fixing the line ending inconsistencies, so the
   safety does not trigger;
 
-- "git diff" itself does not touch the files in the work tree, it is
-  often run to inspect the changes you intend to next "git add".  To
+- 'git-diff' itself does not touch the files in the work tree, it is
+  often run to inspect the changes you intend to next 'git-add'.  To
   catch potential problems early, safety triggers.
 
 
@@ -214,7 +214,7 @@ with `crlf`, and then `ident` and fed to `filter`.
 Generating diff text
 ~~~~~~~~~~~~~~~~~~~~
 
-The attribute `diff` affects if `git diff` generates textual
+The attribute `diff` affects if 'git-diff' generates textual
 patch for the path or just says `Binary files differ`.  It also
 can affect what line is shown on the hunk header `@@ -k,l +n,m @@`
 line.
@@ -278,7 +278,7 @@ is prefixed with a line of the form:
 
 The text is called 'hunk header', and by default a line that
 begins with an alphabet, an underscore or a dollar sign is used,
-which matches what GNU `diff -p` output uses.  This default
+which matches what GNU 'diff -p' output uses.  This default
 selection however is not suited for some contents, and you can
 use customized pattern to make a selection.
 
@@ -322,7 +322,7 @@ and other programs such as `git revert` and `git cherry-pick`.
 Set::
 
        Built-in 3-way merge driver is used to merge the
-       contents in a way similar to `merge` command of `RCS`
+       contents in a way similar to 'merge' command of `RCS`
        suite.  This is suitable for ordinary text files.
 
 Unset::
@@ -426,7 +426,7 @@ Checking whitespace errors
 ^^^^^^^^^^^^
 
 The `core.whitespace` configuration variable allows you to define what
-`diff` and `apply` should consider whitespace errors for all paths in
+'diff' and 'apply' should consider whitespace errors for all paths in
 the project (See linkgit:git-config[1]).  This attribute gives you finer
 control per path.
 
@@ -453,12 +453,18 @@ String::
 Creating an archive
 ~~~~~~~~~~~~~~~~~~~
 
+`export-ignore`
+^^^^^^^^^^^^^^^
+
+Files and directories with the attribute `export-ignore` won't be added to
+archive files.
+
 `export-subst`
 ^^^^^^^^^^^^^^
 
 If the attribute `export-subst` is set for a file then git will expand
 several placeholders when adding this file to an archive.  The
-expansion depends on the availability of a commit ID, i.e. if
+expansion depends on the availability of a commit ID, i.e., if
 linkgit:git-archive[1] has been given a tree instead of a commit or a
 tag then no replacement will be done.  The placeholders are the same
 as those for the option `--pretty=format:` of linkgit:git-log[1],
index 8fb5d889e5757ad5c25717c4d9ed0a3ef378f794..29e5929db22257346a2bed16cbd5ca6531698676 100644 (file)
@@ -13,8 +13,37 @@ gitcli
 DESCRIPTION
 -----------
 
-This manual describes best practice in how to use git CLI.  Here are
-the rules that you should follow when you are scripting git:
+This manual describes the convention used throughout git CLI.
+
+Many commands take revisions (most often "commits", but sometimes
+"tree-ish", depending on the context and command) and paths as their
+arguments.  Here are the rules:
+
+ * Revisions come first and then paths.
+   E.g. in `git diff v1.0 v2.0 arch/x86 include/asm-x86`,
+   `v1.0` and `v2.0` are revisions and `arch/x86` and `include/asm-x86`
+   are paths.
+
+ * When an argument can be misunderstood as either a revision or a path,
+   they can be disambiguated by placing `\--` between them.
+   E.g. `git diff \-- HEAD` is, "I have a file called HEAD in my work
+   tree.  Please show changes between the version I staged in the index
+   and what I have in the work tree for that file". not "show difference
+   between the HEAD commit and the work tree as a whole".  You can say
+   `git diff HEAD \--` to ask for the latter.
+
+ * Without disambiguating `\--`, git makes a reasonable guess, but errors
+   out and asking you to disambiguate when ambiguous.  E.g. if you have a
+   file called HEAD in your work tree, `git diff HEAD` is ambiguous, and
+   you have to say either `git diff HEAD \--` or `git diff \-- HEAD` to
+   disambiguate.
+
+When writing a script that is expected to handle random user-input, it is
+a good practice to make it explicit which arguments are which by placing
+disambiguating `\--` at appropriate places.
+
+Here are the rules regarding the "flags" that you should follow when you are
+scripting git:
 
  * it's preferred to use the non dashed form of git commands, which means that
    you should prefer `"git foo"` to `"git-foo"`.
@@ -34,8 +63,8 @@ the rules that you should follow when you are scripting git:
    if you happen to have a file called `HEAD` in the work tree.
 
 
-ENHANCED CLI
-------------
+ENHANCED OPTION PARSER
+----------------------
 From the git 1.5.4 series and further, many git commands (not all of them at the
 time of the writing though) come with an enhanced option parser.
 
@@ -104,9 +133,45 @@ $ git describe --abbrev 10 HEAD  # NOT WHAT YOU MEANT
 ----------------------------
 
 
+NOTES ON FREQUENTLY CONFUSED OPTIONS
+------------------------------------
+
+Many commands that can work on files in the working tree
+and/or in the index can take `--cached` and/or `--index`
+options.  Sometimes people incorrectly think that, because
+the index was originally called cache, these two are
+synonyms.  They are *not* -- these two options mean very
+different things.
+
+ * The `--cached` option is used to ask a command that
+   usually works on files in the working tree to *only* work
+   with the index.  For example, `git grep`, when used
+   without a commit to specify from which commit to look for
+   strings in, usually works on files in the working tree,
+   but with the `--cached` option, it looks for strings in
+   the index.
+
+ * The `--index` option is used to ask a command that
+   usually works on files in the working tree to *also*
+   affect the index.  For example, `git stash apply` usually
+   merges changes recorded in a stash to the working tree,
+   but with the `--index` option, it also merges changes to
+   the index as well.
+
+`git apply` command can be used with `--cached` and
+`--index` (but not at the same time).  Usually the command
+only affects the files in the working tree, but with
+`--index`, it patches both the files and their index
+entries, and with `--cached`, it modifies only the index
+entries.
+
+See also http://marc.info/?l=git&m=116563135620359 and
+http://marc.info/?l=git&m=119150393620273 for further
+information.
+
 Documentation
 -------------
-Documentation by Pierre Habouzit.
+Documentation by Pierre Habouzit and the git-list <git@vger.kernel.org>.
 
 GIT
 ---
index cb4ec4044092961a925bd954d0aa3199c0001620..49179b0a00fad1ecda1fdf0537ccbce77f5fc494 100644 (file)
@@ -16,8 +16,8 @@ This tutorial explains how to use the "core" git programs to set up and
 work with a git repository.
 
 If you just need to use git as a revision control system you may prefer
-to start with linkgit:gittutorial[7][a tutorial introduction to git] or
-link:user-manual.html[the git user manual].
+to start with "A Tutorial Introduction to GIT" (linkgit:gittutorial[7]) or
+link:user-manual.html[the GIT User Manual].
 
 However, an understanding of these low-level tools can be helpful if
 you want to understand git's internals.
@@ -42,14 +42,14 @@ one for a totally new project, or an existing working tree that you want
 to import into git.
 
 For our first example, we're going to start a totally new repository from
-scratch, with no pre-existing files, and we'll call it `git-tutorial`.
+scratch, with no pre-existing files, and we'll call it 'git-tutorial'.
 To start up, create a subdirectory for it, change into that
-subdirectory, and initialize the git infrastructure with `git-init`:
+subdirectory, and initialize the git infrastructure with 'git-init':
 
 ------------------------------------------------
 $ mkdir git-tutorial
 $ cd git-tutorial
-$ git-init
+$ git init
 ------------------------------------------------
 
 to which git will reply
@@ -61,7 +61,7 @@ Initialized empty Git repository in .git/
 which is just git's way of saying that you haven't been doing anything
 strange, and that it will have created a local `.git` directory setup for
 your new project. You will now have a `.git` directory, and you can
-inspect that with `ls`. For your new empty project, it should show you
+inspect that with 'ls'. For your new empty project, it should show you
 three entries, among other things:
 
  - a file called `HEAD`, that has `ref: refs/heads/master` in it.
@@ -108,8 +108,7 @@ references in these `refs` subdirectories when you actually start
 populating your tree.
 
 [NOTE]
-An advanced user may want to take a look at the
-linkgit:gitrepository-layout[5][repository layout] document
+An advanced user may want to take a look at linkgit:gitrepository-layout[5]
 after finishing this tutorial.
 
 You have now created your first git repository. Of course, since it's
@@ -140,7 +139,7 @@ but to actually check in your hard work, you will have to go through two steps:
  - commit that index file as an object.
 
 The first step is trivial: when you want to tell git about any changes
-to your working tree, you use the `git-update-index` program. That
+to your working tree, you use the 'git-update-index' program. That
 program normally just takes a list of filenames you want to update, but
 to avoid trivial mistakes, it refuses to add new entries to the index
 (or remove existing ones) unless you explicitly tell it that you're
@@ -150,7 +149,7 @@ adding a new entry with the `\--add` flag (or removing an entry with the
 So to populate the index with the two files you just created, you can do
 
 ------------------------------------------------
-$ git-update-index --add hello example
+$ git update-index --add hello example
 ------------------------------------------------
 
 and you have now told git to track those two files.
@@ -174,19 +173,19 @@ and see two files:
 which correspond with the objects with names of `557db...` and
 `f24c7...` respectively.
 
-If you want to, you can use `git-cat-file` to look at those objects, but
+If you want to, you can use 'git-cat-file' to look at those objects, but
 you'll have to use the object name, not the filename of the object:
 
 ----------------
-$ git-cat-file -t 557db03de997c86a4a028e1ebd3a1ceb225be238
+$ git cat-file -t 557db03de997c86a4a028e1ebd3a1ceb225be238
 ----------------
 
-where the `-t` tells `git-cat-file` to tell you what the "type" of the
+where the `-t` tells 'git-cat-file' to tell you what the "type" of the
 object is. git will tell you that you have a "blob" object (i.e., just a
 regular file), and you can see the contents with
 
 ----------------
-$ git-cat-file "blob" 557db03
+$ git cat-file "blob" 557db03
 ----------------
 
 which will print out "Hello World". The object `557db03` is nothing
@@ -206,7 +205,7 @@ hexadecimal digits in most places.
 Anyway, as we mentioned previously, you normally never actually take a
 look at the objects themselves, and typing long 40-character hex
 names is not something you'd normally want to do. The above digression
-was just to show that `git-update-index` did something magical, and
+was just to show that 'git-update-index' did something magical, and
 actually saved away the contents of your files into the git object
 database.
 
@@ -229,22 +228,22 @@ $ echo "It's a new day for git" >>hello
 
 and you can now, since you told git about the previous state of `hello`, ask
 git what has changed in the tree compared to your old index, using the
-`git-diff-files` command:
+'git-diff-files' command:
 
 ------------
-$ git-diff-files
+$ git diff-files
 ------------
 
 Oops. That wasn't very readable. It just spit out its own internal
-version of a `diff`, but that internal version really just tells you
+version of a 'diff', but that internal version really just tells you
 that it has noticed that "hello" has been modified, and that the old object
 contents it had have been replaced with something else.
 
-To make it readable, we can tell git-diff-files to output the
+To make it readable, we can tell 'git-diff-files' to output the
 differences as a patch, using the `-p` flag:
 
 ------------
-$ git-diff-files -p
+$ git diff-files -p
 diff --git a/hello b/hello
 index 557db03..263414f 100644
 --- a/hello
@@ -256,11 +255,11 @@ index 557db03..263414f 100644
 
 i.e. the diff of the change we caused by adding another line to `hello`.
 
-In other words, `git-diff-files` always shows us the difference between
+In other words, 'git-diff-files' always shows us the difference between
 what is recorded in the index, and what is currently in the working
 tree. That's very useful.
 
-A common shorthand for `git-diff-files -p` is to just write `git
+A common shorthand for `git diff-files -p` is to just write `git
 diff`, which will do the same thing.
 
 ------------
@@ -284,15 +283,15 @@ that in two phases: creating a 'tree' object, and committing that 'tree'
 object as a 'commit' object together with an explanation of what the
 tree was all about, along with information of how we came to that state.
 
-Creating a tree object is trivial, and is done with `git-write-tree`.
-There are no options or other input: git-write-tree will take the
+Creating a tree object is trivial, and is done with 'git-write-tree'.
+There are no options or other input: `git write-tree` will take the
 current index state, and write an object that describes that whole
 index. In other words, we're now tying together all the different
 filenames with their contents (and their permissions), and we're
 creating the equivalent of a git "directory" object:
 
 ------------------------------------------------
-$ git-write-tree
+$ git write-tree
 ------------------------------------------------
 
 and this will just output the name of the resulting tree, in this case
@@ -303,34 +302,34 @@ and this will just output the name of the resulting tree, in this case
 ----------------
 
 which is another incomprehensible object name. Again, if you want to,
-you can use `git-cat-file -t 8988d\...` to see that this time the object
+you can use `git cat-file -t 8988d\...` to see that this time the object
 is not a "blob" object, but a "tree" object (you can also use
-`git-cat-file` to actually output the raw object contents, but you'll see
+`git cat-file` to actually output the raw object contents, but you'll see
 mainly a binary mess, so that's less interesting).
 
-However -- normally you'd never use `git-write-tree` on its own, because
+However -- normally you'd never use 'git-write-tree' on its own, because
 normally you always commit a tree into a commit object using the
-`git-commit-tree` command. In fact, it's easier to not actually use
-`git-write-tree` on its own at all, but to just pass its result in as an
-argument to `git-commit-tree`.
+'git-commit-tree' command. In fact, it's easier to not actually use
+'git-write-tree' on its own at all, but to just pass its result in as an
+argument to 'git-commit-tree'.
 
-`git-commit-tree` normally takes several arguments -- it wants to know
+'git-commit-tree' normally takes several arguments -- it wants to know
 what the 'parent' of a commit was, but since this is the first commit
 ever in this new repository, and it has no parents, we only need to pass in
-the object name of the tree. However, `git-commit-tree` also wants to get a
+the object name of the tree. However, 'git-commit-tree' also wants to get a
 commit message on its standard input, and it will write out the resulting
 object name for the commit to its standard output.
 
 And this is where we create the `.git/refs/heads/master` file
 which is pointed at by `HEAD`. This file is supposed to contain
 the reference to the top-of-tree of the master branch, and since
-that's exactly what `git-commit-tree` spits out, we can do this
+that's exactly what 'git-commit-tree' spits out, we can do this
 all with a sequence of simple shell commands:
 
 ------------------------------------------------
-$ tree=$(git-write-tree)
-$ commit=$(echo 'Initial commit' | git-commit-tree $tree)
-$ git-update-ref HEAD $commit
+$ tree=$(git write-tree)
+$ commit=$(echo 'Initial commit' | git commit-tree $tree)
+$ git update-ref HEAD $commit
 ------------------------------------------------
 
 In this case this creates a totally new commit that is not related to
@@ -346,37 +345,37 @@ instead, and it would have done the above magic scripting for you.
 Making a change
 ---------------
 
-Remember how we did the `git-update-index` on file `hello` and then we
+Remember how we did the 'git-update-index' on file `hello` and then we
 changed `hello` afterward, and could compare the new state of `hello` with the
 state we saved in the index file?
 
-Further, remember how I said that `git-write-tree` writes the contents
+Further, remember how I said that 'git-write-tree' writes the contents
 of the *index* file to the tree, and thus what we just committed was in
 fact the *original* contents of the file `hello`, not the new ones. We did
 that on purpose, to show the difference between the index state, and the
 state in the working tree, and how they don't have to match, even
 when we commit things.
 
-As before, if we do `git-diff-files -p` in our git-tutorial project,
+As before, if we do `git diff-files -p` in our git-tutorial project,
 we'll still see the same difference we saw last time: the index file
 hasn't changed by the act of committing anything. However, now that we
 have committed something, we can also learn to use a new command:
-`git-diff-index`.
+'git-diff-index'.
 
-Unlike `git-diff-files`, which showed the difference between the index
-file and the working tree, `git-diff-index` shows the differences
+Unlike 'git-diff-files', which showed the difference between the index
+file and the working tree, 'git-diff-index' shows the differences
 between a committed *tree* and either the index file or the working
-tree. In other words, `git-diff-index` wants a tree to be diffed
+tree. In other words, 'git-diff-index' wants a tree to be diffed
 against, and before we did the commit, we couldn't do that, because we
 didn't have anything to diff against.
 
 But now we can do
 
 ----------------
-$ git-diff-index -p HEAD
+$ git diff-index -p HEAD
 ----------------
 
-(where `-p` has the same meaning as it did in `git-diff-files`), and it
+(where `-p` has the same meaning as it did in 'git-diff-files'), and it
 will show us the same difference, but for a totally different reason.
 Now we're comparing the working tree not against the index file,
 but against the tree we just wrote. It just so happens that those two
@@ -391,16 +390,16 @@ $ git diff HEAD
 
 which ends up doing the above for you.
 
-In other words, `git-diff-index` normally compares a tree against the
+In other words, 'git-diff-index' normally compares a tree against the
 working tree, but when given the `\--cached` flag, it is told to
 instead compare against just the index cache contents, and ignore the
 current working tree state entirely. Since we just wrote the index
-file to HEAD, doing `git-diff-index \--cached -p HEAD` should thus return
+file to HEAD, doing `git diff-index \--cached -p HEAD` should thus return
 an empty set of differences, and that's exactly what it does.
 
 [NOTE]
 ================
-`git-diff-index` really always uses the index for its
+'git-diff-index' really always uses the index for its
 comparisons, and saying that it compares a tree against the working
 tree is thus not strictly accurate. In particular, the list of
 files to compare (the "meta-data") *always* comes from the index file,
@@ -423,17 +422,17 @@ work through the index file, so the first thing we need to do is to
 update the index cache:
 
 ------------------------------------------------
-$ git-update-index hello
+$ git update-index hello
 ------------------------------------------------
 
 (note how we didn't need the `\--add` flag this time, since git knew
 about the file already).
 
-Note what happens to the different `git-diff-\*` versions here. After
-we've updated `hello` in the index, `git-diff-files -p` now shows no
-differences, but `git-diff-index -p HEAD` still *does* show that the
+Note what happens to the different 'git-diff-\*' versions here. After
+we've updated `hello` in the index, `git diff-files -p` now shows no
+differences, but `git diff-index -p HEAD` still *does* show that the
 current state is different from the state we committed. In fact, now
-`git-diff-index` shows the same difference whether we use the `--cached`
+'git-diff-index' shows the same difference whether we use the `--cached`
 flag or not, since now the index is coherent with the working tree.
 
 Now, since we've updated `hello` in the index, we can commit the new
@@ -461,7 +460,7 @@ You've now made your first real git commit. And if you're interested in
 looking at what `git commit` really does, feel free to investigate:
 it's a few very simple shell scripts to generate the helpful (?) commit
 message headers, and a few one-liners that actually do the
-commit itself (`git-commit`).
+commit itself ('git-commit').
 
 
 Inspecting Changes
@@ -469,16 +468,16 @@ Inspecting Changes
 
 While creating changes is useful, it's even more useful if you can tell
 later what changed. The most useful command for this is another of the
-`diff` family, namely `git-diff-tree`.
+'diff' family, namely 'git-diff-tree'.
 
-`git-diff-tree` can be given two arbitrary trees, and it will tell you the
+'git-diff-tree' can be given two arbitrary trees, and it will tell you the
 differences between them. Perhaps even more commonly, though, you can
 give it just a single commit object, and it will figure out the parent
 of that commit itself, and show the difference directly. Thus, to get
 the same diff that we've already seen several times, we can now do
 
 ----------------
-$ git-diff-tree -p HEAD
+$ git diff-tree -p HEAD
 ----------------
 
 (again, `-p` means to show the difference as a human-readable patch),
@@ -519,15 +518,15 @@ various diff-\* commands compare things.
                     +-----------+
 ============
 
-More interestingly, you can also give `git-diff-tree` the `--pretty` flag,
+More interestingly, you can also give 'git-diff-tree' the `--pretty` flag,
 which tells it to also show the commit message and author and date of the
 commit, and you can tell it to show a whole series of diffs.
 Alternatively, you can tell it to be "silent", and not show the diffs at
 all, but just show the actual commit message.
 
-In fact, together with the `git-rev-list` program (which generates a
-list of revisions), `git-diff-tree` ends up being a veritable fount of
-changes. A trivial (but very useful) script called `git-whatchanged` is
+In fact, together with the 'git-rev-list' program (which generates a
+list of revisions), 'git-diff-tree' ends up being a veritable fount of
+changes. A trivial (but very useful) script called 'git-whatchanged' is
 included with git which does exactly this, and shows a log of recent
 activities.
 
@@ -543,7 +542,7 @@ with the associated patches use the more complex (and much more
 powerful)
 
 ----------------
-$ git-whatchanged -p
+$ git whatchanged -p
 ----------------
 
 and you will see exactly what has changed in the repository over its
@@ -554,14 +553,14 @@ When using the above two commands, the initial commit will be shown.
 If this is a problem because it is huge, you can hide it by setting
 the log.showroot configuration variable to false. Having this, you
 can still show it for each command just adding the `\--root` option,
-which is a flag for `git-diff-tree` accepted by both commands.
+which is a flag for 'git-diff-tree' accepted by both commands.
 
 With that, you should now be having some inkling of what git does, and
 can explore on your own.
 
 [NOTE]
 Most likely, you are not directly using the core
-git Plumbing commands, but using Porcelain such as `git-add`, `git-rm'
+git Plumbing commands, but using Porcelain such as 'git-add', `git-rm'
 and `git-commit'.
 
 
@@ -596,7 +595,7 @@ pointer to the state you want to tag, but also a small tag name and
 message, along with optionally a PGP signature that says that yes,
 you really did
 that tag. You create these annotated tags with either the `-a` or
-`-s` flag to `git tag`:
+`-s` flag to 'git-tag':
 
 ----------------
 $ git tag -s <tagname>
@@ -643,7 +642,7 @@ and it will be gone. There's no external repository, and there's no
 history outside the project you created.
 
  - if you want to move or duplicate a git repository, you can do so. There
-   is `git clone` command, but if all you want to do is just to
+   is 'git-clone' command, but if all you want to do is just to
    create a copy of your repository (with all the full history that
    went along with it), you can do so with a regular
    `cp -a git-tutorial new-git-tutorial`.
@@ -654,31 +653,31 @@ information for the files involved) will likely need to be refreshed.
 So after you do a `cp -a` to create a new copy, you'll want to do
 +
 ----------------
-$ git-update-index --refresh
+$ git update-index --refresh
 ----------------
 +
 in the new repository to make sure that the index file is up-to-date.
 
 Note that the second point is true even across machines. You can
 duplicate a remote git repository with *any* regular copy mechanism, be it
-`scp`, `rsync` or `wget`.
+'scp', 'rsync' or 'wget'.
 
 When copying a remote repository, you'll want to at a minimum update the
 index cache when you do this, and especially with other peoples'
 repositories you often want to make sure that the index cache is in some
 known state (you don't know *what* they've done and not yet checked in),
-so usually you'll precede the `git-update-index` with a
+so usually you'll precede the 'git-update-index' with a
 
 ----------------
-$ git-read-tree --reset HEAD
-$ git-update-index --refresh
+$ git read-tree --reset HEAD
+$ git update-index --refresh
 ----------------
 
 which will force a total index re-build from the tree pointed to by `HEAD`.
-It resets the index contents to `HEAD`, and then the `git-update-index`
+It resets the index contents to `HEAD`, and then the 'git-update-index'
 makes sure to match up all index entries with the checked-out files.
 If the original repository had uncommitted changes in its
-working tree, `git-update-index --refresh` notices them and
+working tree, `git update-index --refresh` notices them and
 tells you they need to be updated.
 
 The above can also be written as simply
@@ -690,8 +689,8 @@ $ git reset
 and in fact a lot of the common git command combinations can be scripted
 with the `git xyz` interfaces.  You can learn things by just looking
 at what the various git scripts do.  For example, `git reset` used to be
-the above two lines implemented in `git-reset`, but some things like
-`git status` and `git commit` are slightly more complex scripts around
+the above two lines implemented in 'git-reset', but some things like
+'git-status' and 'git-commit' are slightly more complex scripts around
 the basic git commands.
 
 Many (most?) public remote repositories will not contain any of
@@ -714,7 +713,7 @@ $ rsync -rL rsync://rsync.kernel.org/pub/scm/git/git.git/ .git
 followed by
 
 ----------------
-$ git-read-tree HEAD
+$ git read-tree HEAD
 ----------------
 
 to populate the index. However, now you have populated the index, and
@@ -723,14 +722,14 @@ actually have any of the working tree files to work on. To get
 those, you'd check them out with
 
 ----------------
-$ git-checkout-index -u -a
+$ git checkout-index -u -a
 ----------------
 
 where the `-u` flag means that you want the checkout to keep the index
 up-to-date (so that you don't have to refresh it afterward), and the
 `-a` flag means "check out all files" (if you have a stale copy or an
 older version of a checked out tree you may also need to add the `-f`
-flag first, to tell git-checkout-index to *force* overwriting of any old
+flag first, to tell 'git-checkout-index' to *force* overwriting of any old
 files).
 
 Again, this can all be simplified with
@@ -777,7 +776,7 @@ to it.
 ================================================
 If you make the decision to start your new branch at some
 other point in the history than the current `HEAD`, you can do so by
-just telling `git checkout` what the base of the checkout would be.
+just telling 'git-checkout' what the base of the checkout would be.
 In other words, if you have an earlier tag or branch, you'd just do
 
 ------------
@@ -820,7 +819,7 @@ $ git branch <branchname> [startingpoint]
 
 which will simply _create_ the branch, but will not do anything further.
 You can then later -- once you decide that you want to actually develop
-on that branch -- switch to that branch with a regular `git checkout`
+on that branch -- switch to that branch with a regular 'git-checkout'
 with the branchname as the argument.
 
 
@@ -840,7 +839,7 @@ $ git commit -m "Some work." -i hello
 ------------------------------------------------
 
 Here, we just added another line to `hello`, and we used a shorthand for
-doing both `git-update-index hello` and `git commit` by just giving the
+doing both `git update-index hello` and `git commit` by just giving the
 filename directly to `git commit`, with an `-i` flag (it tells
 git to 'include' that file in addition to what you have done to
 the index file so far when making the commit).  The `-m` flag is to give the
@@ -879,10 +878,10 @@ means: normally it will just show you your current `HEAD`) and their
 histories. You can also see exactly how they came to be from a common
 source.
 
-Anyway, let's exit `gitk` (`^Q` or the File menu), and decide that we want
+Anyway, let's exit 'gitk' (`^Q` or the File menu), and decide that we want
 to merge the work we did on the `mybranch` branch into the `master`
 branch (which is currently our `HEAD` too). To do that, there's a nice
-script called `git merge`, which wants to know which branches you want
+script called 'git-merge', which wants to know which branches you want
 to resolve and what the merge is all about:
 
 ------------
@@ -926,7 +925,7 @@ $ git commit -i hello
 
 which will very loudly warn you that you're now committing a merge
 (which is correct, so never mind), and you can write a small merge
-message about your adventures in git-merge-land.
+message about your adventures in 'git-merge'-land.
 
 After you're done, start up `gitk \--all` to see graphically what the
 history looks like. Notice that `mybranch` still exists, and you can
@@ -939,7 +938,7 @@ Another useful tool, especially if you do not always work in X-Window
 environment, is `git show-branch`.
 
 ------------------------------------------------
-$ git-show-branch --topo-order --more=1 master mybranch
+$ git show-branch --topo-order --more=1 master mybranch
 * [master] Merge work in mybranch
  ! [mybranch] Some work.
 --
@@ -964,14 +963,14 @@ commits from the master branch.  The string inside brackets
 before the commit log message is a short name you can use to
 name the commit.  In the above example, 'master' and 'mybranch'
 are branch heads.  'master^' is the first parent of 'master'
-branch head.  Please see 'git-rev-parse' documentation if you
+branch head.  Please see linkgit:git-rev-parse[1] if you want to
 see more complex cases.
 
 [NOTE]
 Without the '--more=1' option, 'git-show-branch' would not output the
 '[master^]' commit, as '[mybranch]' commit is a common ancestor of
-both 'master' and 'mybranch' tips.  Please see 'git-show-branch'
-documentation for details.
+both 'master' and 'mybranch' tips.  Please see linkgit:git-show-branch[1]
+for details.
 
 [NOTE]
 If there were more commits on the 'master' branch after the merge, the
@@ -982,7 +981,7 @@ merge commit visible in this case.
 Now, let's pretend you are the one who did all the work in
 `mybranch`, and the fruit of your hard work has finally been merged
 to the `master` branch. Let's go back to `mybranch`, and run
-`git merge` to get the "upstream changes" back to your branch.
+'git-merge' to get the "upstream changes" back to your branch.
 
 ------------
 $ git checkout mybranch
@@ -1007,7 +1006,7 @@ the tree of your branch to that of the `master` branch. This is
 often called 'fast forward' merge.
 
 You can run `gitk \--all` again to see how the commit ancestry
-looks like, or run `show-branch`, which tells you this.
+looks like, or run 'show-branch', which tells you this.
 
 ------------------------------------------------
 $ git show-branch master mybranch
@@ -1024,12 +1023,12 @@ Merging external work
 It's usually much more common that you merge with somebody else than
 merging with your own branches, so it's worth pointing out that git
 makes that very easy too, and in fact, it's not that different from
-doing a `git merge`. In fact, a remote merge ends up being nothing
+doing a 'git-merge'. In fact, a remote merge ends up being nothing
 more than "fetch the work from a remote repository into a temporary tag"
-followed by a `git merge`.
+followed by a 'git-merge'.
 
 Fetching from a remote repository is done by, unsurprisingly,
-`git fetch`:
+'git-fetch':
 
 ----------------
 $ git fetch <remote-repository>
@@ -1067,9 +1066,9 @@ most efficient way to exchange git objects between repositories.
 Local directory::
        `/path/to/repo.git/`
 +
-This transport is the same as SSH transport but uses `sh` to run
+This transport is the same as SSH transport but uses 'sh' to run
 both ends on the local machine instead of running other end on
-the remote machine via `ssh`.
+the remote machine via 'ssh'.
 
 git Native::
        `git://remote.machine/path/to/repo.git/`
@@ -1096,7 +1095,7 @@ The 'commit walkers' are sometimes also called 'dumb
 transports', because they do not require any git aware smart
 server like git Native transport does.  Any stock HTTP server
 that does not even support directory index would suffice.  But
-you must prepare your repository with `git-update-server-info`
+you must prepare your repository with 'git-update-server-info'
 to help dumb transport downloaders.
 
 Once you fetch from the remote repository, you `merge` that
@@ -1116,7 +1115,7 @@ argument.
 [NOTE]
 You could do without using any branches at all, by
 keeping as many local repositories as you would like to have
-branches, and merging between them with `git pull`, just like
+branches, and merging between them with 'git-pull', just like
 you merge between branches. The advantage of this approach is
 that it lets you keep a set of files for each `branch` checked
 out and you may find it easier to switch back and forth if you
@@ -1133,7 +1132,7 @@ like this:
 $ git config remote.linus.url http://www.kernel.org/pub/scm/git/git.git/
 ------------------------------------------------
 
-and use the "linus" keyword with `git pull` instead of the full URL.
+and use the "linus" keyword with 'git-pull' instead of the full URL.
 
 Examples.
 
@@ -1169,7 +1168,7 @@ $ git show-branch --more=2 master mybranch
 +* [master^] Some fun.
 ------------
 
-Remember, before running `git merge`, our `master` head was at
+Remember, before running 'git-merge', our `master` head was at
 "Some fun." commit, while our `mybranch` head was at "Some
 work." commit.
 
@@ -1196,10 +1195,10 @@ Now we are ready to experiment with the merge by hand.
 
 `git merge` command, when merging two branches, uses 3-way merge
 algorithm.  First, it finds the common ancestor between them.
-The command it uses is `git-merge-base`:
+The command it uses is 'git-merge-base':
 
 ------------
-$ mb=$(git-merge-base HEAD mybranch)
+$ mb=$(git merge-base HEAD mybranch)
 ------------
 
 The command writes the commit object name of the common ancestor
@@ -1209,7 +1208,7 @@ ancestor commit is the "New day." commit in this case.  You can
 tell it by:
 
 ------------
-$ git-name-rev $mb
+$ git name-rev $mb
 my-first-tag
 ------------
 
@@ -1217,10 +1216,10 @@ After finding out a common ancestor commit, the second step is
 this:
 
 ------------
-$ git-read-tree -m -u $mb HEAD mybranch
+$ git read-tree -m -u $mb HEAD mybranch
 ------------
 
-This is the same `git-read-tree` command we have already seen,
+This is the same 'git-read-tree' command we have already seen,
 but it takes three trees, unlike previous examples.  This reads
 the contents of each tree into different 'stage' in the index
 file (the first tree goes to stage 1, the second to stage 2,
@@ -1236,7 +1235,7 @@ trees are left in non-zero stages.  At this point, you can
 inspect the index file with this command:
 
 ------------
-$ git-ls-files --stage
+$ git ls-files --stage
 100644 7f8b141b65fdcee47321e399a2598a235a032422 0      example
 100644 263414f423d0e4d70dae8fe53fa34614ff3e2860 1      hello
 100644 06fa6a24256dc7e560efa5687fa84b51f0263c3a 2      hello
@@ -1253,7 +1252,7 @@ stages.
 To look at only non-zero stages, use `\--unmerged` flag:
 
 ------------
-$ git-ls-files --unmerged
+$ git ls-files --unmerged
 100644 263414f423d0e4d70dae8fe53fa34614ff3e2860 1      hello
 100644 06fa6a24256dc7e560efa5687fa84b51f0263c3a 2      hello
 100644 cc44c73eb783565da5831b4d820c962954019b69 3      hello
@@ -1261,29 +1260,29 @@ $ git-ls-files --unmerged
 
 The next step of merging is to merge these three versions of the
 file, using 3-way merge.  This is done by giving
-`git-merge-one-file` command as one of the arguments to
-`git-merge-index` command:
+'git-merge-one-file' command as one of the arguments to
+'git-merge-index' command:
 
 ------------
-$ git-merge-index git-merge-one-file hello
+$ git merge-index git-merge-one-file hello
 Auto-merging hello.
 merge: warning: conflicts during merge
 ERROR: Merge conflict in hello.
 fatal: merge program failed
 ------------
 
-`git-merge-one-file` script is called with parameters to
+'git-merge-one-file' script is called with parameters to
 describe those three versions, and is responsible to leave the
 merge results in the working tree.
 It is a fairly straightforward shell script, and
-eventually calls `merge` program from RCS suite to perform a
-file-level 3-way merge.  In this case, `merge` detects
+eventually calls 'merge' program from RCS suite to perform a
+file-level 3-way merge.  In this case, 'merge' detects
 conflicts, and the merge result with conflict marks is left in
 the working tree..  This can be seen if you run `ls-files
 --stage` again at this point:
 
 ------------
-$ git-ls-files --stage
+$ git ls-files --stage
 100644 7f8b141b65fdcee47321e399a2598a235a032422 0      example
 100644 263414f423d0e4d70dae8fe53fa34614ff3e2860 1      hello
 100644 06fa6a24256dc7e560efa5687fa84b51f0263c3a 2      hello
@@ -1291,9 +1290,9 @@ $ git-ls-files --stage
 ------------
 
 This is the state of the index file and the working file after
-`git merge` returns control back to you, leaving the conflicting
+'git-merge' returns control back to you, leaving the conflicting
 merge for you to resolve.  Notice that the path `hello` is still
-unmerged, and what you see with `git diff` at this point is
+unmerged, and what you see with 'git-diff' at this point is
 differences since stage 2 (i.e. your version).
 
 
@@ -1321,7 +1320,7 @@ how git repositories at `kernel.org` are managed.
 Publishing the changes from your local (private) repository to
 your remote (public) repository requires a write privilege on
 the remote machine. You need to have an SSH account there to
-run a single command, `git-receive-pack`.
+run a single command, 'git-receive-pack'.
 
 First, you need to create an empty repository on the remote
 machine that will house your public repository. This empty
@@ -1330,8 +1329,8 @@ into it later. Obviously, this repository creation needs to be
 done only once.
 
 [NOTE]
-`git push` uses a pair of programs,
-`git-send-pack` on your local machine, and `git-receive-pack`
+'git-push' uses a pair of programs,
+'git-send-pack' on your local machine, and 'git-receive-pack'
 on the remote machine. The communication between the two over
 the network internally uses an SSH connection.
 
@@ -1346,30 +1345,30 @@ $ mkdir my-git.git
 ------------
 
 Then, make that directory into a git repository by running
-`git init`, but this time, since its name is not the usual
+'git-init', but this time, since its name is not the usual
 `.git`, we do things slightly differently:
 
 ------------
-$ GIT_DIR=my-git.git git-init
+$ GIT_DIR=my-git.git git init
 ------------
 
 Make sure this directory is available for others you want your
 changes to be pulled by via the transport of your choice. Also
-you need to make sure that you have the `git-receive-pack`
+you need to make sure that you have the 'git-receive-pack'
 program on the `$PATH`.
 
 [NOTE]
 Many installations of sshd do not invoke your shell as the login
 shell when you directly run programs; what this means is that if
-your login shell is `bash`, only `.bashrc` is read and not
+your login shell is 'bash', only `.bashrc` is read and not
 `.bash_profile`. As a workaround, make sure `.bashrc` sets up
-`$PATH` so that you can run `git-receive-pack` program.
+`$PATH` so that you can run 'git-receive-pack' program.
 
 [NOTE]
 If you plan to publish this repository to be accessed over http,
 you should do `chmod +x my-git.git/hooks/post-update` at this
 point.  This makes sure that every time you push into this
-repository, `git-update-server-info` is run.
+repository, `git update-server-info` is run.
 
 Your "public repository" is now ready to accept your changes.
 Come back to the machine you have your private repository. From
@@ -1408,7 +1407,7 @@ $ git repack
 
 will do it for you. If you followed the tutorial examples, you
 would have accumulated about 17 objects in `.git/objects/??/`
-directories by now. `git repack` tells you how many objects it
+directories by now. 'git-repack' tells you how many objects it
 packed, and stores the packed file in `.git/objects/pack`
 directory.
 
@@ -1421,7 +1420,7 @@ them together. The former holds all the data from the objects
 in the pack, and the latter holds the index for random
 access.
 
-If you are paranoid, running `git-verify-pack` command would
+If you are paranoid, running 'git-verify-pack' command would
 detect if you have a corrupt pack, but do not worry too much.
 Our programs are always perfect ;-).
 
@@ -1488,17 +1487,17 @@ If other people are pulling from your repository over dumb
 transport protocols (HTTP), you need to keep this repository
 'dumb transport friendly'.  After `git init`,
 `$GIT_DIR/hooks/post-update` copied from the standard templates
-would contain a call to `git-update-server-info` but the
+would contain a call to 'git-update-server-info' but the
 `post-update` hook itself is disabled by default -- enable it
-with `chmod +x post-update`.  This makes sure `git-update-server-info`
+with `chmod +x post-update`.  This makes sure 'git-update-server-info'
 keeps the necessary files up-to-date.
 
 3. Push into the public repository from your primary
    repository.
 
-4. `git repack` the public repository. This establishes a big
+4. 'git-repack' the public repository. This establishes a big
    pack that contains the initial set of objects as the
-   baseline, and possibly `git prune` if the transport
+   baseline, and possibly 'git-prune' if the transport
    used for pulling from your repository supports packed
    repositories.
 
@@ -1512,14 +1511,14 @@ You can repack this private repository whenever you feel like.
 6. Push your changes to the public repository, and announce it
    to the public.
 
-7. Every once in a while, "git repack" the public repository.
+7. Every once in a while, "git-repack" the public repository.
    Go back to step 5. and continue working.
 
 
 A recommended work cycle for a "subsystem maintainer" who works
 on that project and has an own "public repository" goes like this:
 
-1. Prepare your work repository, by `git clone` the public
+1. Prepare your work repository, by 'git-clone' the public
    repository of the "project lead". The URL used for the
    initial cloning is stored in the remote.origin.url
    configuration variable.
@@ -1534,7 +1533,7 @@ on that project and has an own "public repository" goes like this:
    point at the repository you are borrowing from.
 
 4. Push into the public repository from your primary
-   repository. Run `git repack`, and possibly `git prune` if the
+   repository. Run 'git-repack', and possibly 'git-prune' if the
    transport used for pulling from your repository supports
    packed repositories.
 
@@ -1551,7 +1550,7 @@ like.
    "project lead" and possibly your "sub-subsystem
    maintainers" to pull from it.
 
-7. Every once in a while, `git repack` the public repository.
+7. Every once in a while, 'git-repack' the public repository.
    Go back to step 5. and continue working.
 
 
@@ -1559,7 +1558,7 @@ A recommended work cycle for an "individual developer" who does
 not have a "public" repository is somewhat different. It goes
 like this:
 
-1. Prepare your work repository, by `git clone` the public
+1. Prepare your work repository, by 'git-clone' the public
    repository of the "project lead" (or a "subsystem
    maintainer", if you work on a subsystem). The URL used for
    the initial cloning is stored in the remote.origin.url
@@ -1589,7 +1588,7 @@ suggested in the previous section may be new to you. You do not
 have to worry. git supports "shared public repository" style of
 cooperation you are probably more familiar with as well.
 
-See linkgit:gitcvs-migration[7][git for CVS users] for the details.
+See linkgit:gitcvs-migration[7] for the details.
 
 Bundling your work together
 ---------------------------
@@ -1656,9 +1655,9 @@ branch before these two merges by resetting it to 'master~2':
 $ git reset --hard master~2
 ------------
 
-You can make sure 'git show-branch' matches the state before
-those two 'git merge' you just did.  Then, instead of running
-two 'git merge' commands in a row, you would merge these two
+You can make sure `git show-branch` matches the state before
+those two 'git-merge' you just did.  Then, instead of running
+two 'git-merge' commands in a row, you would merge these two
 branch heads (this is known as 'making an Octopus'):
 
 ------------
@@ -1691,7 +1690,7 @@ to follow, not easier.
 SEE ALSO
 --------
 linkgit:gittutorial[7], linkgit:gittutorial-2[7],
-linkgit:giteveryday[7], linkgit:gitcvs-migration[7],
+linkgit:everyday[7], linkgit:gitcvs-migration[7],
 link:user-manual.html[The Git User's Manual]
 
 GIT
index 0325d6759d5ee329f284dac625ef4c40c31082c7..aaa7ef737a4c190c60e37e2849ce42f3bdb5dda7 100644 (file)
@@ -18,9 +18,9 @@ important than any other.  However, you can emulate the CVS model by
 designating a single shared repository which people can synchronize with;
 this document explains how to do that.
 
-Some basic familiarity with git is required.  This
-linkgit:gittutorial[7][tutorial introduction to git] and the
-linkgit:gitglossary[7][git glossary] should be sufficient.
+Some basic familiarity with git is required. Having gone through
+linkgit:gittutorial[7] and
+linkgit:gitglossary[7] should be sufficient.
 
 Developing against a shared repository
 --------------------------------------
@@ -34,7 +34,7 @@ $ git clone foo.com:/pub/repo.git/ my-project
 $ cd my-project
 ------------------------------------------------
 
-and hack away.  The equivalent of `cvs update` is
+and hack away.  The equivalent of 'cvs update' is
 
 ------------------------------------------------
 $ git pull origin
@@ -46,28 +46,28 @@ them first before running git pull.
 
 [NOTE]
 ================================
-The `pull` command knows where to get updates from because of certain
-configuration variables that were set by the first `git clone`
+The 'pull' command knows where to get updates from because of certain
+configuration variables that were set by the first 'git-clone'
 command; see `git config -l` and the linkgit:git-config[1] man
 page for details.
 ================================
 
 You can update the shared repository with your changes by first committing
-your changes, and then using the linkgit:git-push[1] command:
+your changes, and then using the 'git-push' command:
 
 ------------------------------------------------
 $ git push origin master
 ------------------------------------------------
 
 to "push" those commits to the shared repository.  If someone else has
-updated the repository more recently, `git push`, like `cvs commit`, will
+updated the repository more recently, 'git-push', like 'cvs commit', will
 complain, in which case you must pull any changes before attempting the
 push again.
 
-In the `git push` command above we specify the name of the remote branch
-to update (`master`).  If we leave that out, `git push` tries to update
+In the 'git-push' command above we specify the name of the remote branch
+to update (`master`).  If we leave that out, 'git-push' tries to update
 any branches in the remote repository that have the same name as a branch
-in the local repository.  So the last `push` can be done with either of:
+in the local repository.  So the last 'push' can be done with either of:
 
 ------------
 $ git push origin
@@ -81,8 +81,8 @@ Setting Up a Shared Repository
 ------------------------------
 
 We assume you have already created a git repository for your project,
-possibly created from scratch or from a tarball (see the
-linkgit:gittutorial[7][tutorial]), or imported from an already existing CVS
+possibly created from scratch or from a tarball (see
+linkgit:gittutorial[7]), or imported from an already existing CVS
 repository (see the next section).
 
 Assume your existing repo is at /home/alice/myproject.  Create a new "bare"
@@ -118,7 +118,7 @@ Importing a CVS archive
 First, install version 2.1 or higher of cvsps from
 link:http://www.cobite.com/cvsps/[http://www.cobite.com/cvsps/] and make
 sure it is in your path.  Then cd to a checked out CVS working directory
-of the project you are interested in and run linkgit:git-cvsimport[1]:
+of the project you are interested in and run 'git-cvsimport':
 
 -------------------------------------------
 $ git cvsimport -C <destination> <module>
@@ -153,7 +153,7 @@ Advanced Shared Repository Management
 
 Git allows you to specify scripts called "hooks" to be run at certain
 points.  You can use these, for example, to send all commits to the shared
-repository to a mailing list.  See linkgit:githooks[5][Hooks used by git].
+repository to a mailing list.  See linkgit:githooks[5].
 
 You can enforce finer grained permissions using update hooks.  See
 link:howto/update-hook-example.txt[Controlling access to branches using
index 4d56c85260b98de81d8db2e8281cb7d8efff4ea7..2bdbc3d4f6a97c1a1d970f0c5f27222ef9e31274 100644 (file)
@@ -7,34 +7,34 @@ gitdiffcore - Tweaking diff output (June 2005)
 
 SYNOPSIS
 --------
-git diff *
+'git diff' *
 
 DESCRIPTION
 -----------
 
-The diff commands git-diff-index, git-diff-files, and git-diff-tree
+The diff commands 'git-diff-index', 'git-diff-files', and 'git-diff-tree'
 can be told to manipulate differences they find in
-unconventional ways before showing diff(1) output.  The manipulation
+unconventional ways before showing 'diff' output.  The manipulation
 is collectively called "diffcore transformation".  This short note
-describes what they are and how to use them to produce diff outputs
-that are easier to understand than the conventional kind.
+describes what they are and how to use them to produce 'diff' output
+that is easier to understand than the conventional kind.
 
 
 The chain of operation
 ----------------------
 
-The git-diff-* family works by first comparing two sets of
+The 'git-diff-{asterisk}' family works by first comparing two sets of
 files:
 
- - git-diff-index compares contents of a "tree" object and the
+ - 'git-diff-index' compares contents of a "tree" object and the
    working directory (when '\--cached' flag is not used) or a
    "tree" object and the index file (when '\--cached' flag is
    used);
 
- - git-diff-files compares contents of the index file and the
+ - 'git-diff-files' compares contents of the index file and the
    working directory;
 
- - git-diff-tree compares contents of two "tree" objects;
+ - 'git-diff-tree' compares contents of two "tree" objects;
 
 In all of these cases, the commands themselves compare
 corresponding paths in the two sets of files.  The result of
@@ -61,12 +61,12 @@ into another list.  There are currently 6 such transformations:
 - diffcore-pickaxe
 - diffcore-order
 
-These are applied in sequence.  The set of filepairs git-diff-\*
+These are applied in sequence.  The set of filepairs 'git-diff-{asterisk}'
 commands find are used as the input to diffcore-pathspec, and
 the output from diffcore-pathspec is used as the input to the
 next transformation.  The final result is then passed to the
 output routine and generates either diff-raw format (see Output
-format sections of the manual for git-diff-\* commands) or
+format sections of the manual for 'git-diff-{asterisk}' commands) or
 diff-patch format.
 
 
@@ -75,7 +75,7 @@ diffcore-pathspec: For Ignoring Files Outside Our Consideration
 
 The first transformation in the chain is diffcore-pathspec, and
 is controlled by giving the pathname parameters to the
-git-diff-* commands on the command line.  The pathspec is used
+'git-diff-{asterisk}' commands on the command line.  The pathspec is used
 to limit the world diff operates in.  It removes the filepairs
 outside the specified set of pathnames.  E.g. If the input set
 of filepairs included:
@@ -84,11 +84,11 @@ of filepairs included:
 :100644 100644 bcd1234... 0123456... M junkfile
 ------------------------------------------------
 
-but the command invocation was "git-diff-files myfile", then the
+but the command invocation was `git diff-files myfile`, then the
 junkfile entry would be removed from the list because only "myfile"
 is under consideration.
 
-Implementation note.  For performance reasons, git-diff-tree
+Implementation note.  For performance reasons, 'git-diff-tree'
 uses the pathname parameters on the command line to cull set of
 filepairs it feeds the diffcore mechanism itself, and does not
 use diffcore-pathspec, but the end result is the same.
@@ -98,7 +98,7 @@ diffcore-break: For Splitting Up "Complete Rewrites"
 ----------------------------------------------------
 
 The second transformation in the chain is diffcore-break, and is
-controlled by the -B option to the git-diff-* commands.  This is
+controlled by the -B option to the 'git-diff-{asterisk}' commands.  This is
 used to detect a filepair that represents "complete rewrite" and
 break such filepair into two filepairs that represent delete and
 create.  E.g.  If the input contained this filepair:
@@ -134,7 +134,7 @@ diffcore-rename: For Detection Renames and Copies
 
 This transformation is used to detect renames and copies, and is
 controlled by the -M option (to detect renames) and the -C option
-(to detect copies as well) to the git-diff-* commands.  If the
+(to detect copies as well) to the 'git-diff-{asterisk}' commands.  If the
 input contained these filepairs:
 
 ------------------------------------------------
@@ -179,11 +179,11 @@ number after the "-M" or "-C" option (e.g. "-M8" to tell it to use
 8/10 = 80%).
 
 Note.  When the "-C" option is used with `\--find-copies-harder`
-option, git-diff-\* commands feed unmodified filepairs to
+option, 'git-diff-{asterisk}' commands feed unmodified filepairs to
 diffcore mechanism as well as modified ones.  This lets the copy
 detector consider unmodified files as copy source candidates at
 the expense of making it slower.  Without `\--find-copies-harder`,
-git-diff-\* commands can detect copies only if the file that was
+'git-diff-{asterisk}' commands can detect copies only if the file that was
 copied happened to have been modified in the same changeset.
 
 
@@ -234,7 +234,7 @@ diffcore-pickaxe: For Detecting Addition/Deletion of Specified String
 
 This transformation is used to find filepairs that represent
 changes that touch a specified string, and is controlled by the
--S option and the `\--pickaxe-all` option to the git-diff-*
+-S option and the `\--pickaxe-all` option to the 'git-diff-{asterisk}'
 commands.
 
 When diffcore-pickaxe is in use, it checks if there are
@@ -257,7 +257,7 @@ diffcore-order: For Sorting the Output Based on Filenames
 
 This is used to reorder the filepairs according to the user's
 (or project's) taste, and is controlled by the -O option to the
-git-diff-* commands.
+'git-diff-{asterisk}' commands.
 
 This takes a text file each of whose lines is a shell glob
 pattern.  Filepairs that match a glob pattern on an earlier line
index 5c5c31d31c6057d9f3c6da7a5f6d6cdc40c023f6..565719ed5f8516e17229ec11bbec5e1354580397 100644 (file)
@@ -17,7 +17,7 @@ include::glossary-content.txt[]
 SEE ALSO
 --------
 linkgit:gittutorial[7], linkgit:gittutorial-2[7],
-linkgit:giteveryday[7], linkgit:gitcvs-migration[7],
+linkgit:everyday[7], linkgit:gitcvs-migration[7],
 link:user-manual.html[The Git User's Manual]
 
 GIT
index 4f06ae0ed4bd625bf5a33fca215c90fb1b5810c9..046a2a7fe7cf8ec301d3a20f7ebc587a09d210e3 100644 (file)
@@ -15,19 +15,20 @@ DESCRIPTION
 
 Hooks are little scripts you can place in `$GIT_DIR/hooks`
 directory to trigger action at certain points.  When
-`git-init` is run, a handful example hooks are copied in the
+'git-init' is run, a handful example hooks are copied in the
 `hooks` directory of the new repository, but by default they are
-all disabled.  To enable a hook, make it executable with `chmod +x`.
+all disabled.  To enable a hook, rename it by removing its `.sample`
+suffix.
 
 This document describes the currently defined hooks.
 
 applypatch-msg
 --------------
 
-This hook is invoked by `git-am` script.  It takes a single
+This hook is invoked by 'git-am' script.  It takes a single
 parameter, the name of the file that holds the proposed commit
 log message.  Exiting with non-zero status causes
-`git-am` to abort before applying the patch.
+'git-am' to abort before applying the patch.
 
 The hook is allowed to edit the message file in place, and can
 be used to normalize the message into some project standard
@@ -40,7 +41,7 @@ The default 'applypatch-msg' hook, when enabled, runs the
 pre-applypatch
 --------------
 
-This hook is invoked by `git-am`.  It takes no parameter, and is
+This hook is invoked by 'git-am'.  It takes no parameter, and is
 invoked after the patch is applied, but before a commit is made.
 
 If it exits with non-zero status, then the working tree will not be
@@ -55,33 +56,33 @@ The default 'pre-applypatch' hook, when enabled, runs the
 post-applypatch
 ---------------
 
-This hook is invoked by `git-am`.  It takes no parameter,
+This hook is invoked by 'git-am'.  It takes no parameter,
 and is invoked after the patch is applied and a commit is made.
 
 This hook is meant primarily for notification, and cannot affect
-the outcome of `git-am`.
+the outcome of 'git-am'.
 
 pre-commit
 ----------
 
-This hook is invoked by `git-commit`, and can be bypassed
+This hook is invoked by 'git-commit', and can be bypassed
 with `\--no-verify` option.  It takes no parameter, and is
 invoked before obtaining the proposed commit log message and
 making a commit.  Exiting with non-zero status from this script
-causes the `git-commit` to abort.
+causes the 'git-commit' to abort.
 
 The default 'pre-commit' hook, when enabled, catches introduction
 of lines with trailing whitespaces and aborts the commit when
 such a line is found.
 
-All the `git-commit` hooks are invoked with the environment
+All the 'git-commit' hooks are invoked with the environment
 variable `GIT_EDITOR=:` if the command will not bring up an editor
 to modify the commit message.
 
 prepare-commit-msg
 ------------------
 
-This hook is invoked by `git-commit` right after preparing the
+This hook is invoked by 'git-commit' right after preparing the
 default log message, and before the editor is started.
 
 It takes one to three parameters.  The first is the name of the file
@@ -93,7 +94,7 @@ commit is a merge or a `.git/MERGE_MSG` file exists); `squash`
 (if a `.git/SQUASH_MSG` file exists); or `commit`, followed by
 a commit SHA1 (if a `\-c`, `\-C` or `\--amend` option was given).
 
-If the exit status is non-zero, `git-commit` will abort.
+If the exit status is non-zero, 'git-commit' will abort.
 
 The purpose of the hook is to edit the message file in place, and
 it is not suppressed by the `\--no-verify` option.  A non-zero exit
@@ -106,10 +107,10 @@ out the `Conflicts:` part of a merge's commit message.
 commit-msg
 ----------
 
-This hook is invoked by `git-commit`, and can be bypassed
+This hook is invoked by 'git-commit', and can be bypassed
 with `\--no-verify` option.  It takes a single parameter, the
 name of the file that holds the proposed commit log message.
-Exiting with non-zero status causes the `git-commit` to
+Exiting with non-zero status causes the 'git-commit' to
 abort.
 
 The hook is allowed to edit the message file in place, and can
@@ -123,21 +124,21 @@ The default 'commit-msg' hook, when enabled, detects duplicate
 post-commit
 -----------
 
-This hook is invoked by `git-commit`.  It takes no
+This hook is invoked by 'git-commit'.  It takes no
 parameter, and is invoked after a commit is made.
 
 This hook is meant primarily for notification, and cannot affect
-the outcome of `git-commit`.
+the outcome of 'git-commit'.
 
 post-checkout
 -----------
 
-This hook is invoked when a `git-checkout` is run after having updated the
+This hook is invoked when a 'git-checkout' is run after having updated the
 worktree.  The hook is given three parameters: the ref of the previous HEAD,
 the ref of the new HEAD (which may or may not have changed), and a flag
 indicating whether the checkout was a branch checkout (changing branches,
 flag=1) or a file checkout (retrieving a file from the index, flag=0).
-This hook cannot affect the outcome of `git-checkout`.
+This hook cannot affect the outcome of 'git-checkout'.
 
 This hook can be used to perform repository validity checks, auto-display
 differences from the previous HEAD if different, or set working dir metadata
@@ -146,10 +147,10 @@ properties.
 post-merge
 -----------
 
-This hook is invoked by `git-merge`, which happens when a `git pull`
+This hook is invoked by 'git-merge', which happens when a 'git-pull'
 is done on a local repository.  The hook takes a single parameter, a status
 flag specifying whether or not the merge being done was a squash merge.
-This hook cannot affect the outcome of `git-merge` and is not executed,
+This hook cannot affect the outcome of 'git-merge' and is not executed,
 if the merge failed due to conflicts.
 
 This hook can be used in conjunction with a corresponding pre-commit hook to
@@ -161,8 +162,8 @@ for an example of how to do this.
 pre-receive
 -----------
 
-This hook is invoked by `git-receive-pack` on the remote repository,
-which happens when a `git push` is done on a local repository.
+This hook is invoked by 'git-receive-pack' on the remote repository,
+which happens when a 'git-push' is done on a local repository.
 Just before starting to update refs on the remote repository, the
 pre-receive hook is invoked.  Its exit status determines the success
 or failure of the update.
@@ -183,15 +184,15 @@ updated. If the hook exits with zero, updating of individual refs can
 still be prevented by the <<update,'update'>> hook.
 
 Both standard output and standard error output are forwarded to
-`git-send-pack` on the other end, so you can simply `echo` messages
+'git-send-pack' on the other end, so you can simply `echo` messages
 for the user.
 
 [[update]]
 update
 ------
 
-This hook is invoked by `git-receive-pack` on the remote repository,
-which happens when a `git push` is done on a local repository.
+This hook is invoked by 'git-receive-pack' on the remote repository,
+which happens when a 'git-push' is done on a local repository.
 Just before updating the ref on the remote repository, the update hook
 is invoked.  Its exit status determines the success or failure of
 the ref update.
@@ -204,7 +205,7 @@ three parameters:
  - and the new objectname to be stored in the ref.
 
 A zero exit from the update hook allows the ref to be updated.
-Exiting with a non-zero status prevents `git-receive-pack`
+Exiting with a non-zero status prevents 'git-receive-pack'
 from updating that ref.
 
 This hook can be used to prevent 'forced' update on certain refs by
@@ -222,7 +223,7 @@ implement access control which is finer grained than the one
 based on filesystem group.
 
 Both standard output and standard error output are forwarded to
-`git-send-pack` on the other end, so you can simply `echo` messages
+'git-send-pack' on the other end, so you can simply `echo` messages
 for the user.
 
 The default 'update' hook, when enabled--and with
@@ -233,8 +234,8 @@ unannotated tags to be pushed.
 post-receive
 ------------
 
-This hook is invoked by `git-receive-pack` on the remote repository,
-which happens when a `git push` is done on a local repository.
+This hook is invoked by 'git-receive-pack' on the remote repository,
+which happens when a 'git-push' is done on a local repository.
 It executes on the remote repository once after all the refs have
 been updated.
 
@@ -243,7 +244,7 @@ arguments, but gets the same information as the
 <<pre-receive,'pre-receive'>>
 hook does on its standard input.
 
-This hook does not affect the outcome of `git-receive-pack`, as it
+This hook does not affect the outcome of 'git-receive-pack', as it
 is called after the real work is done.
 
 This supersedes the <<post-update,'post-update'>> hook in that it gets
@@ -251,7 +252,7 @@ both old and new values of all the refs in addition to their
 names.
 
 Both standard output and standard error output are forwarded to
-`git-send-pack` on the other end, so you can simply `echo` messages
+'git-send-pack' on the other end, so you can simply `echo` messages
 for the user.
 
 The default 'post-receive' hook is empty, but there is
@@ -263,8 +264,8 @@ emails.
 post-update
 -----------
 
-This hook is invoked by `git-receive-pack` on the remote repository,
-which happens when a `git push` is done on a local repository.
+This hook is invoked by 'git-receive-pack' on the remote repository,
+which happens when a 'git-push' is done on a local repository.
 It executes on the remote repository once after all the refs have
 been updated.
 
@@ -272,7 +273,7 @@ It takes a variable number of parameters, each of which is the
 name of ref that was actually updated.
 
 This hook is meant primarily for notification, and cannot affect
-the outcome of `git-receive-pack`.
+the outcome of 'git-receive-pack'.
 
 The 'post-update' hook can tell what are the heads that were pushed,
 but it does not know what their original and updated values are,
@@ -282,20 +283,20 @@ updated values of the refs. You might consider it instead if you need
 them.
 
 When enabled, the default 'post-update' hook runs
-`git-update-server-info` to keep the information used by dumb
+'git-update-server-info' to keep the information used by dumb
 transports (e.g., HTTP) up-to-date.  If you are publishing
 a git repository that is accessible via HTTP, you should
 probably enable this hook.
 
 Both standard output and standard error output are forwarded to
-`git-send-pack` on the other end, so you can simply `echo` messages
+'git-send-pack' on the other end, so you can simply `echo` messages
 for the user.
 
 pre-auto-gc
 -----------
 
-This hook is invoked by `git-gc --auto`. It takes no parameter, and
-exiting with non-zero status from this script causes the `git-gc --auto`
+This hook is invoked by 'git-gc --auto'. It takes no parameter, and
+exiting with non-zero status from this script causes the 'git-gc --auto'
 to abort.
 
 GIT
index 2881c9cb92941a24d44d5a9f0d6a71cb06a01c23..fc0efd8ec8dcc791c528d0eca362172f7e445164 100644 (file)
@@ -51,10 +51,10 @@ the user's editor of choice) generally go into a file specified by
 `core.excludesfile` in the user's `~/.gitconfig`.
 
 The underlying git plumbing tools, such as
-linkgit:git-ls-files[1] and linkgit:git-read-tree[1], read
+'git-ls-files' and 'git-read-tree', read
 `gitignore` patterns specified by command-line options, or from
 files specified by command-line options.  Higher-level git
-tools, such as linkgit:git-status[1] and linkgit:git-add[1],
+tools, such as 'git-status' and 'git-add',
 use patterns from the sources specified above.
 
 Patterns have the following format:
@@ -92,7 +92,7 @@ Patterns have the following format:
 An example:
 
 --------------------------------------------------------------
-    $ git-status
+    $ git status
     [...]
     # Untracked files:
     [...]
@@ -110,7 +110,7 @@ An example:
     *.html
     # except foo.html which is maintained by hand
     !foo.html
-    $ git-status
+    $ git status
     [...]
     # Untracked files:
     [...]
index f843f39bf2f0d42f568595e1b29192d203b3e403..e02ecf57444df14d61d82dcf2f9e0c3f6b990b91 100644 (file)
@@ -22,7 +22,8 @@ git repository.
 OPTIONS
 -------
 To control which revisions to shown, the command takes options applicable to
-the linkgit:git-rev-list[1] command. This manual page describes only the most
+the 'git-rev-list' command (see linkgit:git-rev-list[1]).
+This manual page describes only the most
 frequently used options.
 
 -n <number>::
index 03c52ff526d6e3691b4463047036c0dc2e4849f8..a969b3fbc3efc99ce490455b93c8bfb912994e2e 100644 (file)
@@ -64,7 +64,7 @@ objects/info/packs::
        are available in this object store.  Whenever a pack is
        added or removed, `git update-server-info` should be run
        to keep this file up-to-date if the repository is
-       published for dumb transports.  `git repack` does this
+       published for dumb transports.  'git-repack' does this
        by default.
 
 objects/info/alternates::
@@ -85,7 +85,7 @@ objects/info/http-alternates::
 
 refs::
        References are stored in subdirectories of this
-       directory.  The `git prune` command knows to keep
+       directory.  The 'git-prune' command knows to keep
        objects reachable from refs found in this directory and
        its subdirectories.
 
@@ -125,7 +125,7 @@ details.
 
 branches::
        A slightly deprecated way to store shorthands to be used
-       to specify URL to `git fetch`, `git pull` and `git push`
+       to specify URL to 'git-fetch', 'git-pull' and 'git-push'
        commands is to store a file in `branches/<name>` and
        give 'name' to these commands in place of 'repository'
        argument.
@@ -133,9 +133,9 @@ branches::
 hooks::
        Hooks are customization scripts used by various git
        commands.  A handful of sample hooks are installed when
-       `git init` is run, but all of them are disabled by
+       'git-init' is run, but all of them are disabled by
        default.  To enable, they need to be made executable.
-       Read linkgit:githooks[5][hooks] for more details about
+       Read linkgit:githooks[5] for more details about
        each hook.
 
 index::
@@ -150,10 +150,10 @@ info/refs::
        This file helps dumb transports discover what refs are
        available in this repository.  If the repository is
        published for dumb transports, this file should be
-       regenerated by `git update-server-info` every time a tag
+       regenerated by 'git-update-server-info' every time a tag
        or branch is created or modified.  This is normally done
        from the `hooks/update` hook, which is run by the
-       `git-receive-pack` command when you `git push` into the
+       'git-receive-pack' command when you 'git-push' into the
        repository.
 
 info/grafts::
@@ -167,18 +167,18 @@ info/grafts::
 info/exclude::
        This file, by convention among Porcelains, stores the
        exclude pattern list. `.gitignore` is the per-directory
-       ignore file.  `git status`, `git add`, `git rm` and `git
-       clean` look at it but the core git commands do not look
+       ignore file.  'git-status', 'git-add', 'git-rm' and
+       'git-clean' look at it but the core git commands do not look
        at it.  See also: linkgit:gitignore[5].
 
 remotes::
        Stores shorthands to be used to give URL and default
-       refnames to interact with remote repository to `git
-       fetch`, `git pull` and `git push` commands.
+       refnames to interact with remote repository to
+       'git-fetch', 'git-pull' and 'git-push' commands.
 
 logs::
        Records of changes made to refs are stored in this
-       directory.  See the documentation on git-update-ref
+       directory.  See linkgit:git-update-ref[1]
        for more information.
 
 logs/refs/heads/`name`::
index e3d5c1fbf004760d4063352c2dd594e6b98b865f..660904686c656fd00078aa272d0b9a5a198e1833 100644 (file)
@@ -12,8 +12,7 @@ git *
 DESCRIPTION
 -----------
 
-You should work through linkgit:gittutorial[7][A tutorial introduction to
-git] before reading this tutorial.
+You should work through linkgit:gittutorial[7] before reading this tutorial.
 
 The goal of this tutorial is to introduce two fundamental pieces of
 git's architecture--the object database and the index file--and to
@@ -55,15 +54,15 @@ following the example above generates a different SHA1 hash than
 the one shown above because the commit object records the time when
 it was created and the name of the person performing the commit.
 
-We can ask git about this particular object with the cat-file
+We can ask git about this particular object with the `cat-file`
 command. Don't copy the 40 hex digits from this example but use those
 from your own version. Note that you can shorten it to only a few
 characters to save yourself typing all 40 hex digits:
 
 ------------------------------------------------
-$ git-cat-file -t 54196cc2
+$ git cat-file -t 54196cc2
 commit
-$ git-cat-file commit 54196cc2
+$ git cat-file commit 54196cc2
 tree 92b8b694ffb1675e5975148e1121810081dbdffe
 author J. Bruce Fields <bfields@puzzle.fieldses.org> 1143414668 -0500
 committer J. Bruce Fields <bfields@puzzle.fieldses.org> 1143414668 -0500
@@ -166,7 +165,7 @@ hello world!
 and the "parent" object refers to the previous commit:
 
 ------------------------------------------------
-$ git-cat-file commit 54196cc2
+$ git cat-file commit 54196cc2
 tree 92b8b694ffb1675e5975148e1121810081dbdffe
 author J. Bruce Fields <bfields@puzzle.fieldses.org> 1143414668 -0500
 committer J. Bruce Fields <bfields@puzzle.fieldses.org> 1143414668 -0500
@@ -213,8 +212,8 @@ designate such an argument.
 The index file
 --------------
 
-The primary tool we've been using to create commits is "git commit
--a", which creates a commit including every change you've made to
+The primary tool we've been using to create commits is `git-commit
+-a`, which creates a commit including every change you've made to
 your working tree.  But what if you want to commit changes only to
 certain files?  Or only certain changes to certain files?
 
@@ -246,7 +245,7 @@ The last diff is empty, but no new commits have been made, and the
 head still doesn't contain the new line:
 
 ------------------------------------------------
-$ git-diff HEAD
+$ git diff HEAD
 diff --git a/file.txt b/file.txt
 index a042389..513feba 100644
 --- a/file.txt
@@ -256,7 +255,7 @@ index a042389..513feba 100644
 +hello world, again
 ------------------------------------------------
 
-So "git diff" is comparing against something other than the head.
+So 'git-diff' is comparing against something other than the head.
 The thing that it's comparing against is actually the index file,
 which is stored in .git/index in a binary format, but whose contents
 we can examine with ls-files:
@@ -271,9 +270,9 @@ hello world!
 hello world, again
 ------------------------------------------------
 
-So what our "git add" did was store a new blob and then put
+So what our 'git-add' did was store a new blob and then put
 a reference to it in the index file.  If we modify the file again,
-we'll see that the new modifications are reflected in the "git-diff"
+we'll see that the new modifications are reflected in the 'git-diff'
 output:
 
 ------------------------------------------------
@@ -288,7 +287,7 @@ index 513feba..ba3da7b 100644
 +again?
 ------------------------------------------------
 
-With the right arguments, git diff can also show us the difference
+With the right arguments, 'git-diff' can also show us the difference
 between the working directory and the last commit, or between the
 index and the last commit:
 
@@ -312,8 +311,8 @@ index a042389..513feba 100644
 +hello world, again
 ------------------------------------------------
 
-At any time, we can create a new commit using "git commit" (without
-the -a option), and verify that the state committed only includes the
+At any time, we can create a new commit using 'git-commit' (without
+the "-a" option), and verify that the state committed only includes the
 changes stored in the index file, not the additional change that is
 still only in our working tree:
 
@@ -330,11 +329,11 @@ index 513feba..ba3da7b 100644
 +again?
 ------------------------------------------------
 
-So by default "git commit" uses the index to create the commit, not
-the working tree; the -a option to commit tells it to first update
+So by default 'git-commit' uses the index to create the commit, not
+the working tree; the "-a" option to commit tells it to first update
 the index with all changes in the working tree.
 
-Finally, it's worth looking at the effect of "git add" on the index
+Finally, it's worth looking at the effect of 'git-add' on the index
 file:
 
 ------------------------------------------------
@@ -342,7 +341,7 @@ $ echo "goodbye, world" >closing.txt
 $ git add closing.txt
 ------------------------------------------------
 
-The effect of the "git add" was to add one entry to the index file:
+The effect of the 'git-add' was to add one entry to the index file:
 
 ------------------------------------------------
 $ git ls-files --stage
@@ -383,14 +382,14 @@ it is marked "changed but not updated".  At this point, running "git
 commit" would create a commit that added closing.txt (with its new
 contents), but that didn't modify file.txt.
 
-Also, note that a bare "git diff" shows the changes to file.txt, but
+Also, note that a bare `git diff` shows the changes to file.txt, but
 not the addition of closing.txt, because the version of closing.txt
 in the index file is identical to the one in the working directory.
 
 In addition to being the staging area for new commits, the index file
 is also populated from the object database when checking out a
 branch, and is used to hold the trees involved in a merge operation.
-See the linkgit:gitcore-tutorial[7][core tutorial] and the relevant man
+See linkgit:gitcore-tutorial[7] and the relevant man
 pages for details.
 
 What next?
@@ -399,20 +398,19 @@ What next?
 At this point you should know everything necessary to read the man
 pages for any of the git commands; one good place to start would be
 with the commands mentioned in link:everyday.html[Everyday git].  You
-should be able to find any unknown jargon in the
-linkgit:gitglossary[7][Glossary].
+should be able to find any unknown jargon in linkgit:gitglossary[7].
 
 The link:user-manual.html[Git User's Manual] provides a more
 comprehensive introduction to git.
 
-The linkgit:gitcvs-migration[7][CVS migration] document explains how to
+linkgit:gitcvs-migration[7] explains how to
 import a CVS repository into git, and shows how to use git in a
 CVS-like way.
 
 For some interesting examples of git use, see the
 link:howto-index.html[howtos].
 
-For git developers, the linkgit:gitcore-tutorial[7][Core tutorial] goes
+For git developers, linkgit:gitcore-tutorial[7] goes
 into detail on the lower-level git mechanisms involved in, for
 example, creating a new commit.
 
index d465aab64e367f1564793b74522d571433d5b53f..48d1454a90cf9453e5e3c9fa01b3dbc369a58f1f 100644 (file)
@@ -19,11 +19,11 @@ If you are instead primarily interested in using git to fetch a project,
 for example, to test the latest version, you may prefer to start with
 the first two chapters of link:user-manual.html[The Git User's Manual].
 
-First, note that you can get documentation for a command such as "git
-diff" with:
+First, note that you can get documentation for a command such as
+`git log --graph` with:
 
 ------------------------------------------------
-$ man git-diff
+$ man git-log
 ------------------------------------------------
 
 It is a good idea to introduce yourself to git with your name and
@@ -58,7 +58,7 @@ You've now initialized the working directory--you may notice a new
 directory created, named ".git".
 
 Next, tell git to take a snapshot of the contents of all files under the
-current directory (note the '.'), with linkgit:git-add[1]:
+current directory (note the '.'), with 'git-add':
 
 ------------------------------------------------
 $ git add .
@@ -66,7 +66,7 @@ $ git add .
 
 This snapshot is now stored in a temporary staging area which git calls
 the "index".  You can permanently store the contents of the index in the
-repository with linkgit:git-commit[1]:
+repository with 'git-commit':
 
 ------------------------------------------------
 $ git commit
@@ -85,15 +85,15 @@ $ git add file1 file2 file3
 ------------------------------------------------
 
 You are now ready to commit.  You can see what is about to be committed
-using linkgit:git-diff[1] with the --cached option:
+using 'git-diff' with the --cached option:
 
 ------------------------------------------------
 $ git diff --cached
 ------------------------------------------------
 
-(Without --cached, linkgit:git-diff[1] will show you any changes that
+(Without --cached, 'git-diff' will show you any changes that
 you've made but not yet added to the index.)  You can also get a brief
-summary of the situation with linkgit:git-status[1]:
+summary of the situation with 'git-status':
 
 ------------------------------------------------
 $ git status
@@ -117,7 +117,7 @@ $ git commit
 This will again prompt you for a message describing the change, and then
 record a new version of the project.
 
-Alternatively, instead of running `git add` beforehand, you can use
+Alternatively, instead of running 'git-add' beforehand, you can use
 
 ------------------------------------------------
 $ git commit -a
@@ -136,9 +136,9 @@ commit in the body.
 Git tracks content not files
 ----------------------------
 
-Many revision control systems provide an "add" command that tells the
-system to start tracking changes to a new file.  Git's "add" command
-does something simpler and more powerful: `git add` is used both for new
+Many revision control systems provide an `add` command that tells the
+system to start tracking changes to a new file.  Git's `add` command
+does something simpler and more powerful: 'git-add' is used both for new
 and newly modified files, and in both cases it takes a snapshot of the
 given files and stages that content in the index, ready for inclusion in
 the next commit.
@@ -274,7 +274,7 @@ same machine, wants to contribute.
 Bob begins with:
 
 ------------------------------------------------
-$ git clone /home/alice/project myrepo
+bob$ git clone /home/alice/project myrepo
 ------------------------------------------------
 
 This creates a new directory "myrepo" containing a clone of Alice's
@@ -285,7 +285,7 @@ Bob then makes some changes and commits them:
 
 ------------------------------------------------
 (edit files)
-$ git commit -a
+bob$ git commit -a
 (repeat as necessary)
 ------------------------------------------------
 
@@ -293,8 +293,8 @@ When he's ready, he tells Alice to pull changes from the repository
 at /home/bob/myrepo.  She does this with:
 
 ------------------------------------------------
-$ cd /home/alice/project
-$ git pull /home/bob/myrepo master
+alice$ cd /home/alice/project
+alice$ git pull /home/bob/myrepo master
 ------------------------------------------------
 
 This merges the changes from Bob's "master" branch into Alice's
@@ -306,30 +306,56 @@ is the default.)
 The "pull" command thus performs two operations: it fetches changes
 from a remote branch, then merges them into the current branch.
 
+Note that in general, Alice would want her local changes committed before
+initiating this "pull".  If Bob's work conflicts with what Alice did since
+their histories forked, Alice will use her working tree and the index to
+resolve conflicts, and existing local changes will interfere with the
+conflict resolution process (git will still perform the fetch but will
+refuse to merge --- Alice will have to get rid of her local changes in
+some way and pull again when this happens).
+
+Alice can peek at what Bob did without merging first, using the "fetch"
+command; this allows Alice to inspect what Bob did, using a special
+symbol "FETCH_HEAD", in order to determine if he has anything worth
+pulling, like this:
+
+------------------------------------------------
+alice$ git fetch /home/bob/myrepo master
+alice$ git log -p ..FETCH_HEAD
+------------------------------------------------
+
+This operation is safe even if Alice has uncommitted local changes.
+
+After inspecting what Bob did, if there is nothing urgent, Alice may
+decide to continue working without pulling from Bob.  If Bob's history
+does have something Alice would immediately need, Alice may choose to
+stash her work-in-progress first, do a "pull", and then finally unstash
+her work-in-progress on top of the resulting history.
+
 When you are working in a small closely knit group, it is not
 unusual to interact with the same repository over and over
 again.  By defining 'remote' repository shorthand, you can make
 it easier:
 
 ------------------------------------------------
-$ git remote add bob /home/bob/myrepo
+alice$ git remote add bob /home/bob/myrepo
 ------------------------------------------------
 
-With this, Alice can perform the first operation alone using the
-"git fetch" command without merging them with her own branch,
+With this, Alice can perform the first part of the "pull" operation alone using the
+'git-fetch' command without merging them with her own branch,
 using:
 
 -------------------------------------
-$ git fetch bob
+alice$ git fetch bob
 -------------------------------------
 
 Unlike the longhand form, when Alice fetches from Bob using a
-remote repository shorthand set up with `git remote`, what was
+remote repository shorthand set up with 'git-remote', what was
 fetched is stored in a remote tracking branch, in this case
 `bob/master`.  So after this:
 
 -------------------------------------
-$ git log -p master..bob/master
+alice$ git log -p master..bob/master
 -------------------------------------
 
 shows a list of all the changes that Bob made since he branched from
@@ -339,14 +365,14 @@ After examining those changes, Alice
 could merge the changes into her master branch:
 
 -------------------------------------
-$ git merge bob/master
+alice$ git merge bob/master
 -------------------------------------
 
 This `merge` can also be done by 'pulling from her own remote
 tracking branch', like this:
 
 -------------------------------------
-$ git pull . remotes/bob/master
+alice$ git pull . remotes/bob/master
 -------------------------------------
 
 Note that git pull always merges into the current branch,
@@ -355,7 +381,7 @@ regardless of what else is given on the command line.
 Later, Bob can update his repo with Alice's latest changes using
 
 -------------------------------------
-$ git pull
+bob$ git pull
 -------------------------------------
 
 Note that he doesn't need to give the path to Alice's repository;
@@ -364,19 +390,19 @@ repository in the repository configuration, and that location is
 used for pulls:
 
 -------------------------------------
-$ git config --get remote.origin.url
+bob$ git config --get remote.origin.url
 /home/alice/project
 -------------------------------------
 
-(The complete configuration created by git-clone is visible using
-"git config -l", and the linkgit:git-config[1] man page
+(The complete configuration created by 'git-clone' is visible using
+`git config -l`, and the linkgit:git-config[1] man page
 explains the meaning of each option.)
 
 Git also keeps a pristine copy of Alice's master branch under the
 name "origin/master":
 
 -------------------------------------
-$ git branch -r
+bob$ git branch -r
   origin/master
 -------------------------------------
 
@@ -384,7 +410,7 @@ If Bob later decides to work from a different host, he can still
 perform clones and pulls using the ssh protocol:
 
 -------------------------------------
-$ git clone alice.org:/home/alice/project myrepo
+bob$ git clone alice.org:/home/alice/project myrepo
 -------------------------------------
 
 Alternatively, git has a native protocol, or can use rsync or http;
@@ -392,13 +418,13 @@ see linkgit:git-pull[1] for details.
 
 Git can also be used in a CVS-like mode, with a central repository
 that various users push changes to; see linkgit:git-push[1] and
-linkgit:gitcvs-migration[7][git for CVS users].
+linkgit:gitcvs-migration[7].
 
 Exploring history
 -----------------
 
 Git history is represented as a series of interrelated commits.  We
-have already seen that the git log command can list those commits.
+have already seen that the 'git-log' command can list those commits.
 Note that first line of each git log entry also gives a name for the
 commit:
 
@@ -411,7 +437,7 @@ Date:   Tue May 16 17:18:22 2006 -0700
     merge-base: Clarify the comments on post processing.
 -------------------------------------
 
-We can give this name to git show to see the details about this
+We can give this name to 'git-show' to see the details about this
 commit.
 
 -------------------------------------
@@ -447,7 +473,7 @@ $ git show HEAD^2 # show the second parent of HEAD
 You can also give commits names of your own; after running
 
 -------------------------------------
-$ git-tag v2.5 1b2e1d63ff
+$ git tag v2.5 1b2e1d63ff
 -------------------------------------
 
 you can refer to 1b2e1d63ff by the name "v2.5".  If you intend to
@@ -469,13 +495,13 @@ $ git reset --hard HEAD^ # reset your current branch and working
 Be careful with that last command: in addition to losing any changes
 in the working directory, it will also remove all later commits from
 this branch.  If this branch is the only branch containing those
-commits, they will be lost.  Also, don't use "git reset" on a
+commits, they will be lost.  Also, don't use 'git-reset' on a
 publicly-visible branch that other developers pull from, as it will
 force needless merges on other developers to clean up the history.
-If you need to undo changes that you have pushed, use linkgit:git-revert[1]
+If you need to undo changes that you have pushed, use 'git-revert'
 instead.
 
-The git grep command can search for strings in any version of your
+The 'git-grep' command can search for strings in any version of your
 project, so
 
 -------------------------------------
@@ -484,7 +510,7 @@ $ git grep "hello" v2.5
 
 searches for all occurrences of "hello" in v2.5.
 
-If you leave out the commit name, git grep will search any of the
+If you leave out the commit name, 'git-grep' will search any of the
 files it manages in your current directory.  So
 
 -------------------------------------
@@ -494,7 +520,7 @@ $ git grep "hello"
 is a quick way to search just the files that are tracked by git.
 
 Many git commands also take sets of commits, which can be specified
-in a number of ways.  Here are some examples with git log:
+in a number of ways.  Here are some examples with 'git-log':
 
 -------------------------------------
 $ git log v2.5..v2.6            # commits between v2.5 and v2.6
@@ -504,7 +530,7 @@ $ git log v2.5.. Makefile       # commits since v2.5 which modify
                                # Makefile
 -------------------------------------
 
-You can also give git log a "range" of commits where the first is not
+You can also give 'git-log' a "range" of commits where the first is not
 necessarily an ancestor of the second; for example, if the tips of
 the branches "stable-release" and "master" diverged from a common
 commit some time ago, then
@@ -523,13 +549,13 @@ $ git log experimental..stable
 will show the list of commits made on the stable branch but not
 the experimental branch.
 
-The "git log" command has a weakness: it must present commits in a
+The 'git-log' command has a weakness: it must present commits in a
 list.  When the history has lines of development that diverged and
-then merged back together, the order in which "git log" presents
+then merged back together, the order in which 'git-log' presents
 those commits is meaningless.
 
 Most projects with multiple contributors (such as the linux kernel,
-or git itself) have frequent merges, and gitk does a better job of
+or git itself) have frequent merges, and 'gitk' does a better job of
 visualizing their history.  For example,
 
 -------------------------------------
@@ -549,7 +575,7 @@ of the file:
 $ git diff v2.5:Makefile HEAD:Makefile.in
 -------------------------------------
 
-You can also use "git show" to see any such file:
+You can also use 'git-show' to see any such file:
 
 -------------------------------------
 $ git show v2.5:Makefile
@@ -571,9 +597,9 @@ is based:
     used to create commits, check out working directories, and
     hold the various trees involved in a merge.
 
-linkgit:gittutorial-2[7][Part two of this tutorial] explains the object
+Part two of this tutorial explains the object
 database, the index file, and a few other odds and ends that you'll
-need to make the most of git.
+need to make the most of git. You can find it at linkgit:gittutorial-2[7].
 
 If you don't want to continue with that right away, a few other
 digressions that may be interesting at this point are:
@@ -592,7 +618,7 @@ digressions that may be interesting at this point are:
 
   * link:everyday.html[Everyday GIT with 20 Commands Or So]
 
-  * linkgit:gitcvs-migration[7][git for CVS users].
+  * linkgit:gitcvs-migration[7]: Git for CVS users.
 
 SEE ALSO
 --------
index a8d3bae408b6c502062ebc89e04603fa22b97b88..8b2ec502f4ad6b32c5f4482e7f06fdaf0011de7a 100644 (file)
@@ -65,7 +65,7 @@ function info {
 
 # Implement generic branch and tag policies.
 # - Tags should not be updated once created.
-# - Branches should only be fast-forwarded.
+# - Branches should only be fast-forwarded unless their pattern starts with '+'
 case "$1" in
   refs/tags/*)
     git rev-parse --verify -q "$1" &&
@@ -80,7 +80,7 @@ case "$1" in
       mb=$(git-merge-base "$2" "$3")
       case "$mb,$2" in
         "$2,$mb") info "Update is fast-forward" ;;
-        *)        deny >/dev/null  "This is not a fast-forward update." ;;
+       *)        noff=y; info "This is not a fast-forward update.";;
       esac
     fi
     ;;
@@ -95,21 +95,30 @@ allowed_users_file=$GIT_DIR/info/allowed-users
 username=$(id -u -n)
 info "The user is: '$username'"
 
-if [ -f "$allowed_users_file" ]; then
+if test -f "$allowed_users_file"
+then
   rc=$(cat $allowed_users_file | grep -v '^#' | grep -v '^$' |
-    while read head_pattern user_patterns; do
-      matchlen=$(expr "$1" : "$head_pattern")
-      if [ "$matchlen" == "${#1}" ]; then
-        info "Found matching head pattern: '$head_pattern'"
-        for user_pattern in $user_patterns; do
-          info "Checking user: '$username' against pattern: '$user_pattern'"
-          matchlen=$(expr "$username" : "$user_pattern")
-          if [ "$matchlen" == "${#username}" ]; then
-            grant "Allowing user: '$username' with pattern: '$user_pattern'"
-          fi
-        done
-        deny "The user is not in the access list for this branch"
-      fi
+    while read heads user_patterns
+    do
+      # does this rule apply to us?
+      head_pattern=${heads#+}
+      matchlen=$(expr "$1" : "${head_pattern#+}")
+      test "$matchlen" = ${#1} || continue
+
+      # if non-ff, $heads must be with the '+' prefix
+      test -n "$noff" &&
+      test "$head_pattern" = "$heads" && continue
+
+      info "Found matching head pattern: '$head_pattern'"
+      for user_pattern in $user_patterns; do
+       info "Checking user: '$username' against pattern: '$user_pattern'"
+       matchlen=$(expr "$username" : "$user_pattern")
+       if test "$matchlen" = "${#username}"
+       then
+         grant "Allowing user: '$username' with pattern: '$user_pattern'"
+       fi
+      done
+      deny "The user is not in the access list for this branch"
     done
   )
   case "$rc" in
@@ -124,23 +133,32 @@ groups=$(id -G -n)
 info "The user belongs to the following groups:"
 info "'$groups'"
 
-if [ -f "$allowed_groups_file" ]; then
+if test -f "$allowed_groups_file"
+then
   rc=$(cat $allowed_groups_file | grep -v '^#' | grep -v '^$' |
-    while read head_pattern group_patterns; do
-      matchlen=$(expr "$1" : "$head_pattern")
-      if [ "$matchlen" == "${#1}" ]; then
-        info "Found matching head pattern: '$head_pattern'"
-        for group_pattern in $group_patterns; do
-          for groupname in $groups; do
-            info "Checking group: '$groupname' against pattern: '$group_pattern'"
-            matchlen=$(expr "$groupname" : "$group_pattern")
-            if [ "$matchlen" == "${#groupname}" ]; then
-              grant "Allowing group: '$groupname' with pattern: '$group_pattern'"
-            fi
-          done
+    while read heads group_patterns
+    do
+      # does this rule apply to us?
+      head_pattern=${heads#+}
+      matchlen=$(expr "$1" : "${head_pattern#+}")
+      test "$matchlen" = ${#1} || continue
+
+      # if non-ff, $heads must be with the '+' prefix
+      test -n "$noff" &&
+      test "$head_pattern" = "$heads" && continue
+
+      info "Found matching head pattern: '$head_pattern'"
+      for group_pattern in $group_patterns; do
+       for groupname in $groups; do
+         info "Checking group: '$groupname' against pattern: '$group_pattern'"
+         matchlen=$(expr "$groupname" : "$group_pattern")
+         if test "$matchlen" = "${#groupname}"
+         then
+           grant "Allowing group: '$groupname' with pattern: '$group_pattern'"
+         fi
         done
-        deny "None of the user's groups are in the access list for this branch"
-      fi
+      done
+      deny "None of the user's groups are in the access list for this branch"
     done
   )
   case "$rc" in
@@ -159,6 +177,7 @@ allowed-groups, to describe which heads can be pushed into by
 whom.  The format of each file would look like this:
 
         refs/heads/master      junio
+       +refs/heads/pu          junio
         refs/heads/cogito$     pasky
         refs/heads/bw/.*       linus
         refs/heads/tmp/.*      .*
@@ -166,7 +185,8 @@ whom.  The format of each file would look like this:
 
 With this, Linus can push or create "bw/penguin" or "bw/zebra"
 or "bw/panda" branches, Pasky can do only "cogito", and JC can
-do master branch and make versioned tags.  And anybody can do
-tmp/blah branches.
+do master and pu branches and make versioned tags.  And anybody
+can do tmp/blah branches. The '+' sign at the pu record means
+that JC can make non-fast-forward pushes on it.
 
 ------------
index 1e188e6e742d06056fcd8eafd89c13ef36685d4e..fb0d7da56b902217f8f1f4d4bc85186d6bf0dc4c 100644 (file)
@@ -21,7 +21,7 @@ project find it more convenient to use legacy encodings, git
 does not forbid it.  However, there are a few things to keep in
 mind.
 
-. `git-commit-tree` (hence, `git-commit` which uses it) issues
+. 'git-commit-tree' (hence, 'git-commit' which uses it) issues
   a warning if the commit log message given to it does not look
   like a valid UTF-8 string, unless you explicitly say your
   project uses a legacy encoding.  The way to say this is to
@@ -37,7 +37,7 @@ of `i18n.commitencoding` in its `encoding` header.  This is to
 help other people who look at them later.  Lack of this header
 implies that the commit log message is encoded in UTF-8.
 
-. `git-log`, `git-show` and friends looks at the `encoding`
+. 'git-log', 'git-show' and friends looks at the `encoding`
   header of a commit object, and tries to re-code the log
   message into UTF-8 unless otherwise specified.  You can
   specify the desired output encoding with
index 5433cf8cedc466d2da56386ec4b5f4f9f462ef5b..35f440876ed182de319b6d3f0b8296b1a1ede29d 100755 (executable)
@@ -6,7 +6,7 @@ head="$1"
 mandir="$2"
 SUBDIRECTORY_OK=t
 USAGE='<refname> <target directory>'
-. git-sh-setup
+. "$(git --exec-path)"/git-sh-setup
 cd_to_toplevel
 
 test -z "$mandir" && usage
index ffbc6e9861094f48fd3f24af3a0b343c9c0ea7f4..007909a82fe77325e46c54799d00dc78493a47f9 100644 (file)
@@ -56,5 +56,5 @@
        Use the given merge strategy; can be supplied more than
        once to specify them in the order they should be tried.
        If there is no `-s` option, a built-in list of strategies
-       is used instead (`git-merge-recursive` when merging a single
-       head, `git-merge-octopus` otherwise).
+       is used instead ('git-merge-recursive' when merging a single
+       head, 'git-merge-octopus' otherwise).
index cbee369947bf43c245994607ba5d3f77246cce6d..00a8d210476089257be3d09ac8a16d1f8e1dd8dc 100644 (file)
@@ -32,7 +32,7 @@ must know this is the expected usage pattern for a branch.
 [NOTE]
 You never do your own development on branches that appear
 on the right hand side of a <refspec> colon on `Pull:` lines;
-they are to be updated by `git-fetch`.  If you intend to do
+they are to be updated by 'git-fetch'.  If you intend to do
 development derived from a remote branch `B`, have a `Pull:`
 line to track it (i.e. `Pull: B:remote-B`), and have a separate
 branch `my-B` to do your development on top of it.  The latter
@@ -44,13 +44,13 @@ on the remote branch, merge it into your development branch with
 +
 [NOTE]
 There is a difference between listing multiple <refspec>
-directly on `git-pull` command line and having multiple
+directly on 'git-pull' command line and having multiple
 `Pull:` <refspec> lines for a <repository> and running
-`git-pull` command without any explicit <refspec> parameters.
+'git-pull' command without any explicit <refspec> parameters.
 <refspec> listed explicitly on the command line are always
 merged into the current branch after fetching.  In other words,
 if you list more than one remote refs, you would be making
-an Octopus.  While `git-pull` run without any explicit <refspec>
+an Octopus.  While 'git-pull' run without any explicit <refspec>
 parameter takes default <refspec>s from `Pull:` lines, it
 merges only the first <refspec> found into the current branch,
 after fetching all the remote refs.  This is because making an
index 37dd1d61ea36d7afb1e1b16cc46bee0d357ad1c8..b6f5d87e723bec4f00a3929274c43bfd478cc083 100644 (file)
@@ -45,6 +45,10 @@ endif::git-rev-list[]
 
        Print the parents of the commit.
 
+--children::
+
+       Print the children of the commit.
+
 ifdef::git-rev-list[]
 --timestamp::
        Print the raw commit timestamp.
index 99753006e290040be941194b23c7ab26d9e9354e..504ae8a53bca42d7c9ec560b65ddfe14699387a4 100644 (file)
@@ -49,8 +49,8 @@ following format:
 
 ------------
 
-`Push:` lines are used by `git-push` and
-`Pull:` lines are used by `git-pull` and `git-fetch`.
+`Push:` lines are used by 'git-push' and
+`Pull:` lines are used by 'git-pull' and 'git-fetch'.
 Multiple `Push:` and `Pull:` lines may
 be specified for additional branch mappings.
 
index 64a820bf60ae5da8aaaac5fd72c169b8dd381c89..92d400753d192b4b6df256fc3b872d775ecaacd4 100644 (file)
@@ -18,7 +18,7 @@ People needing to do actual development will also want to read
 Further chapters cover more specialized topics.
 
 Comprehensive reference documentation is available through the man
-pages.  For a command such as "git clone", just use
+pages.  For a command such as "git clone <repo>", just use
 
 ------------------------------------------------
 $ man git-clone
@@ -178,7 +178,7 @@ As you can see, a commit shows who made the latest change, what they
 did, and why.
 
 Every commit has a 40-hexdigit id, sometimes called the "object name" or the
-"SHA1 id", shown on the first line of the "git show" output.  You can usually
+"SHA1 id", shown on the first line of the "git-show" output.  You can usually
 refer to a commit by a shorter name, such as a tag or a branch name, but this
 longer name can also be useful.  Most importantly, it is a globally unique
 name for this commit: so if you tell somebody else the object name (for
@@ -390,7 +390,7 @@ references with the same shorthand name, see the "SPECIFYING
 REVISIONS" section of linkgit:git-rev-parse[1].
 
 [[Updating-a-repository-with-git-fetch]]
-Updating a repository with git fetch
+Updating a repository with git-fetch
 ------------------------------------
 
 Eventually the developer cloned from will do additional work in her
@@ -417,7 +417,7 @@ $ git fetch linux-nfs
 -------------------------------------------------
 
 New remote-tracking branches will be stored under the shorthand name
-that you gave "git remote add", in this case linux-nfs:
+that you gave "git-remote add", in this case linux-nfs:
 
 -------------------------------------------------
 $ git branch -r
@@ -518,7 +518,7 @@ $ git bisect visualize
 -------------------------------------------------
 
 which will run gitk and label the commit it chose with a marker that
-says "bisect".  Chose a safe-looking commit nearby, note its commit
+says "bisect".  Choose a safe-looking commit nearby, note its commit
 id, and check it out with:
 
 -------------------------------------------------
@@ -1048,7 +1048,7 @@ $ git diff
 
 shows the difference between the working tree and the index file.
 
-Note that "git add" always adds just the current contents of a file
+Note that "git-add" always adds just the current contents of a file
 to the index; further changes to the same file will be ignored unless
 you run git-add on the file again.
 
@@ -1111,7 +1111,7 @@ Ignoring files
 A project will often generate files that you do 'not' want to track with git.
 This typically includes files generated by a build process or temporary
 backup files made by your editor. Of course, 'not' tracking files with git
-is just a matter of 'not' calling "`git add`" on them. But it quickly becomes
+is just a matter of 'not' calling "`git-add`" on them. But it quickly becomes
 annoying to have these untracked files lying around; e.g. they make
 "`git add .`" and "`git commit -a`" practically useless, and they keep
 showing up in the output of "`git status`".
@@ -1303,7 +1303,7 @@ $ git diff -3 file.txt            # diff against stage 3
 $ git diff --theirs file.txt   # same as the above.
 -------------------------------------------------
 
-The linkgit:git-log[1] and gitk[1] commands also provide special help
+The linkgit:git-log[1] and linkgit:gitk[1] commands also provide special help
 for merges:
 
 -------------------------------------------------
@@ -1449,7 +1449,7 @@ Checking out an old version of a file
 
 In the process of undoing a previous bad change, you may find it
 useful to check out an older version of a particular file using
-linkgit:git-checkout[1].  We've used git checkout before to switch
+linkgit:git-checkout[1].  We've used git-checkout before to switch
 branches, but it has quite different behavior if it is given a path
 name: the command
 
@@ -1651,7 +1651,7 @@ Sharing development with others
 ===============================
 
 [[getting-updates-with-git-pull]]
-Getting updates with git pull
+Getting updates with git-pull
 -----------------------------
 
 After you clone a repository and make a few changes of your own, you
@@ -1770,7 +1770,7 @@ Public git repositories
 Another way to submit changes to a project is to tell the maintainer
 of that project to pull the changes from your repository using
 linkgit:git-pull[1].  In the section "<<getting-updates-with-git-pull,
-Getting updates with git pull>>" we described this as a way to get
+Getting updates with git-pull>>" we described this as a way to get
 updates from the "main" repository, but it works just as well in the
 other direction.
 
@@ -1879,8 +1879,7 @@ $ chmod a+x hooks/post-update
 -------------------------------------------------
 
 (For an explanation of the last two lines, see
-linkgit:git-update-server-info[1], and the documentation
-linkgit:githooks[5][Hooks used by git].)
+linkgit:git-update-server-info[1] and linkgit:githooks[5].)
 
 Advertise the URL of proj.git.  Anybody else should then be able to
 clone or pull from that URL, for example with a command line like:
@@ -1964,10 +1963,10 @@ error: failed to push to 'ssh://yourserver.com/~you/proj.git'
 
 This can happen, for example, if you:
 
-       - use `git reset --hard` to remove already-published commits, or
-       - use `git commit --amend` to replace already-published commits
+       - use `git-reset --hard` to remove already-published commits, or
+       - use `git-commit --amend` to replace already-published commits
          (as in <<fixing-a-mistake-by-rewriting-history>>), or
-       - use `git rebase` to rebase any already-published commits (as
+       - use `git-rebase` to rebase any already-published commits (as
          in <<using-git-rebase>>).
 
 You may force git-push to perform the update anyway by preceding the
@@ -1989,10 +1988,10 @@ intend to manage the branch.
 
 It's also possible for a push to fail in this way when other people have
 the right to push to the same repository.  In that case, the correct
-solution is to retry the push after first updating your work by either a
-pull or a fetch followed by a rebase; see the
+solution is to retry the push after first updating your work: either by a
+pull, or by a fetch followed by a rebase; see the
 <<setting-up-a-shared-repository,next section>> and
-linkgit:gitcvs-migration[7][git for CVS users] for more.
+linkgit:gitcvs-migration[7] for more.
 
 [[setting-up-a-shared-repository]]
 Setting up a shared repository
@@ -2001,7 +2000,7 @@ Setting up a shared repository
 Another way to collaborate is by using a model similar to that
 commonly used in CVS, where several developers with special rights
 all push to and pull from a single shared repository.  See
-linkgit:gitcvs-migration[7][git for CVS users] for instructions on how to
+linkgit:gitcvs-migration[7] for instructions on how to
 set this up.
 
 However, while there is nothing wrong with git's support for shared
@@ -2171,7 +2170,7 @@ they are for, or what status they are in.  To get a reminder of what
 changes are in a specific branch, use:
 
 -------------------------------------------------
-$ git log linux..branchname | git-shortlog
+$ git log linux..branchname | git shortlog
 -------------------------------------------------
 
 To see whether it has already been merged into the test or release branches,
@@ -2444,8 +2443,8 @@ patches to the new mywork.  The result will look like:
 ................................................
 
 In the process, it may discover conflicts.  In that case it will stop
-and allow you to fix the conflicts; after fixing conflicts, use "git
-add" to update the index with those contents, and then, instead of
+and allow you to fix the conflicts; after fixing conflicts, use "git-add"
+to update the index with those contents, and then, instead of
 running git-commit, just run
 
 -------------------------------------------------
@@ -2701,8 +2700,8 @@ master branch.  In more detail:
 git fetch and fast-forwards
 ---------------------------
 
-In the previous example, when updating an existing branch, "git
-fetch" checks to make sure that the most recent commit on the remote
+In the previous example, when updating an existing branch, "git-fetch"
+checks to make sure that the most recent commit on the remote
 branch is a descendant of the most recent commit on your copy of the
 branch before updating your copy of the branch to point at the new
 commit.  Git calls this process a <<fast-forwards,fast forward>>.
@@ -2727,7 +2726,7 @@ resulting in a situation like:
             o--o--o <-- new head of the branch
 ................................................
 
-In this case, "git fetch" will fail, and print out a warning.
+In this case, "git-fetch" will fail, and print out a warning.
 
 In that case, you can still force git to update to the new head, as
 described in the following section.  However, note that in the
@@ -2736,7 +2735,7 @@ unless you've already created a reference of your own pointing to
 them.
 
 [[forcing-fetch]]
-Forcing git fetch to do non-fast-forward updates
+Forcing git-fetch to do non-fast-forward updates
 ------------------------------------------------
 
 If git fetch fails because the new head of a branch is not a
@@ -2811,7 +2810,7 @@ You can also add a "+" to force the update each time:
 $ git config remote.example.fetch +master:ref/remotes/example/master
 -------------------------------------------------
 
-Don't do this unless you're sure you won't mind "git fetch" possibly
+Don't do this unless you're sure you won't mind "git-fetch" possibly
 throwing away commits on mybranch.
 
 Also note that all of the above configuration can be performed by
@@ -2862,7 +2861,7 @@ There are four different types of objects: "blob", "tree", "commit", and
 "tag".
 
 - A <<def_blob_object,"blob" object>> is used to store file data.
-- A <<def_tree_object,"tree" object>> is an object that ties one or more
+- A <<def_tree_object,"tree" object>> ties one or more
   "blob" objects into a directory structure. In addition, a tree object
   can refer to other tree objects, thus creating a directory hierarchy.
 - A <<def_commit_object,"commit" object>> ties such directory hierarchies
@@ -3037,7 +3036,7 @@ Tag Object
 
 A tag object contains an object, object type, tag name, the name of the
 person ("tagger") who created the tag, and a message, which may contain
-a signature, as can be seen using the linkgit:git-cat-file[1]:
+a signature, as can be seen using linkgit:git-cat-file[1]:
 
 ------------------------------------------------
 $ git cat-file tag v1.5.0
@@ -3107,7 +3106,7 @@ $ git prune
 
 to remove any of the "loose" objects that are now contained in the
 pack.  This will also remove any unreferenced objects (which may be
-created when, for example, you use "git reset" to remove a commit).
+created when, for example, you use "git-reset" to remove a commit).
 You can verify that the loose objects are gone by looking at the
 .git/objects directory or by running
 
@@ -3136,7 +3135,7 @@ branch still exists, as does everything it pointed to. The branch
 pointer itself just doesn't, since you replaced it with another one.
 
 There are also other situations that cause dangling objects. For
-example, a "dangling blob" may arise because you did a "git add" of a
+example, a "dangling blob" may arise because you did a "git-add" of a
 file, but then, before you actually committed it and made it part of the
 bigger picture, you changed something else in that file and committed
 that *updated* thing--the old state that you added originally ends up
@@ -3186,7 +3185,7 @@ Usually, dangling blobs and trees aren't very interesting. They're
 almost always the result of either being a half-way mergebase (the blob
 will often even have the conflict markers from a merge in it, if you
 have had conflicting merges that you fixed up by hand), or simply
-because you interrupted a "git fetch" with ^C or something like that,
+because you interrupted a "git-fetch" with ^C or something like that,
 leaving _some_ of the new objects in the object database, but just
 dangling and useless.
 
@@ -3235,7 +3234,7 @@ it is with linkgit:git-fsck[1]; this may be time-consuming.
 Assume the output looks like this:
 
 ------------------------------------------------
-$ git-fsck --full
+$ git fsck --full
 broken link from    tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
               to    blob 4b9458b3786228369c63936db65827de3cc06200
 missing blob 4b9458b3786228369c63936db65827de3cc06200
@@ -3465,14 +3464,14 @@ done
 
 NOTE: Do not use local URLs here if you plan to publish your superproject!
 
-See what files `git submodule` created:
+See what files `git-submodule` created:
 
 -------------------------------------------------
 $ ls -a
 .  ..  .git  .gitmodules  a  b  c  d
 -------------------------------------------------
 
-The `git submodule add` command does a couple of things:
+The `git-submodule add` command does a couple of things:
 
 - It clones the submodule under the current directory and by default checks out
   the master branch.
@@ -3518,7 +3517,7 @@ init` to add the submodule repository URLs to `.git/config`:
 $ git submodule init
 -------------------------------------------------
 
-Now use `git submodule update` to clone the repositories and check out the
+Now use `git-submodule update` to clone the repositories and check out the
 commits specified in the superproject:
 
 -------------------------------------------------
@@ -3528,8 +3527,8 @@ $ ls -a
 .  ..  .git  a.txt
 -------------------------------------------------
 
-One major difference between `git submodule update` and `git submodule add` is
-that `git submodule update` checks out a specific commit, rather than the tip
+One major difference between `git-submodule update` and `git-submodule add` is
+that `git-submodule update` checks out a specific commit, rather than the tip
 of a branch. It's like checking out a tag: the head is detached, so you're not
 working on a branch.
 
@@ -3695,7 +3694,7 @@ removed. The only thing `--remove` means is that update-index will be
 considering a removed file to be a valid thing, and if the file really
 does not exist any more, it will update the index accordingly.
 
-As a special case, you can also do `git-update-index --refresh`, which
+As a special case, you can also do `git update-index --refresh`, which
 will refresh the "stat" information of each index to match the current
 stat information. It will 'not' update the object status itself, and
 it will only update the fields that are used to quickly test whether
@@ -3730,7 +3729,7 @@ unsaved state that you might want to restore later!) your current
 index.  Normal operation is just
 
 -------------------------------------------------
-$ git-read-tree <sha1 of tree>
+$ git read-tree <sha1 of tree>
 -------------------------------------------------
 
 and your index file will now be equivalent to the tree that you saved
@@ -3753,7 +3752,7 @@ index file with read-tree, and then you need to check out the result
 with
 
 -------------------------------------------------
-$ git-checkout-index filename
+$ git checkout-index filename
 -------------------------------------------------
 
 or, if you want to check out all of the index, use `-a`.
@@ -3771,7 +3770,7 @@ from one representation to the other:
 Tying it all together
 ~~~~~~~~~~~~~~~~~~~~~
 
-To commit a tree you have instantiated with "git-write-tree", you'd
+To commit a tree you have instantiated with "git write-tree", you'd
 create a "commit" object that refers to that tree and the history
 behind it--most notably the "parent" commits that preceded it in
 history.
@@ -3790,7 +3789,7 @@ You create a commit object by giving it the tree that describes the
 state at the time of the commit, and a list of parents:
 
 -------------------------------------------------
-$ git-commit-tree <tree> -p <parent> [-p <parent2> ..]
+$ git commit-tree <tree> -p <parent> [-p <parent2> ..]
 -------------------------------------------------
 
 and then giving the reason for the commit on stdin (either through
@@ -3853,14 +3852,14 @@ linkgit:git-cat-file[1] to examine details about the
 object:
 
 -------------------------------------------------
-$ git-cat-file -t <objectname>
+$ git cat-file -t <objectname>
 -------------------------------------------------
 
 shows the type of the object, and once you have the type (which is
 usually implicit in where you find the object), you can use
 
 -------------------------------------------------
-$ git-cat-file blob|tree|commit|tag <objectname>
+$ git cat-file blob|tree|commit|tag <objectname>
 -------------------------------------------------
 
 to show its contents. NOTE! Trees have binary content, and as a result
@@ -3874,7 +3873,7 @@ follow the convention of having the top commit name in `.git/HEAD`,
 you can do
 
 -------------------------------------------------
-$ git-cat-file commit HEAD
+$ git cat-file commit HEAD
 -------------------------------------------------
 
 to see what the top commit was.
@@ -3898,7 +3897,7 @@ To get the "base" for the merge, you first look up the common parent
 of two commits with
 
 -------------------------------------------------
-$ git-merge-base <commit1> <commit2>
+$ git merge-base <commit1> <commit2>
 -------------------------------------------------
 
 which will return you the commit they are both based on.  You should
@@ -3906,7 +3905,7 @@ now look up the "tree" objects of those commits, which you can easily
 do with (for example)
 
 -------------------------------------------------
-$ git-cat-file commit <commitname> | head -1
+$ git cat-file commit <commitname> | head -1
 -------------------------------------------------
 
 since the tree object information is always the first line in a commit
@@ -3923,12 +3922,12 @@ you have in your current index anyway).
 To do the merge, do
 
 -------------------------------------------------
-$ git-read-tree -m -u <origtree> <yourtree> <targettree>
+$ git read-tree -m -u <origtree> <yourtree> <targettree>
 -------------------------------------------------
 
 which will do all trivial merge operations for you directly in the
 index file, and you can just write the result out with
-`git-write-tree`.
+`git write-tree`.
 
 
 [[merging-multiple-trees-2]]
@@ -3942,18 +3941,18 @@ entries" in it. Such an index tree can 'NOT' be written out to a tree
 object, and you will have to resolve any such merge clashes using
 other tools before you can write out the result.
 
-You can examine such index state with `git-ls-files --unmerged`
+You can examine such index state with `git ls-files --unmerged`
 command.  An example:
 
 ------------------------------------------------
-$ git-read-tree -m $orig HEAD $target
-$ git-ls-files --unmerged
+$ git read-tree -m $orig HEAD $target
+$ git ls-files --unmerged
 100644 263414f423d0e4d70dae8fe53fa34614ff3e2860 1      hello.c
 100644 06fa6a24256dc7e560efa5687fa84b51f0263c3a 2      hello.c
 100644 cc44c73eb783565da5831b4d820c962954019b69 3      hello.c
 ------------------------------------------------
 
-Each line of the `git-ls-files --unmerged` output begins with
+Each line of the `git ls-files --unmerged` output begins with
 the blob mode bits, blob SHA1, 'stage number', and the
 filename.  The 'stage number' is git's way to say which tree it
 came from: stage 1 corresponds to `$orig` tree, stage 2 `HEAD`
@@ -3971,9 +3970,9 @@ program, e.g.  `diff3`, `merge`, or git's own merge-file, on
 the blob objects from these three stages yourself, like this:
 
 ------------------------------------------------
-$ git-cat-file blob 263414f... >hello.c~1
-$ git-cat-file blob 06fa6a2... >hello.c~2
-$ git-cat-file blob cc44c73... >hello.c~3
+$ git cat-file blob 263414f... >hello.c~1
+$ git cat-file blob 06fa6a2... >hello.c~2
+$ git cat-file blob cc44c73... >hello.c~3
 $ git merge-file hello.c~2 hello.c~1 hello.c~3
 ------------------------------------------------
 
@@ -3984,23 +3983,23 @@ merge result for this file is by:
 
 -------------------------------------------------
 $ mv -f hello.c~2 hello.c
-$ git-update-index hello.c
+$ git update-index hello.c
 -------------------------------------------------
 
-When a path is in unmerged state, running `git-update-index` for
+When a path is in the "unmerged" state, running `git-update-index` for
 that path tells git to mark the path resolved.
 
 The above is the description of a git merge at the lowest level,
 to help you understand what conceptually happens under the hood.
-In practice, nobody, not even git itself, uses three `git-cat-file`
-for this.  There is `git-merge-index` program that extracts the
+In practice, nobody, not even git itself, runs `git-cat-file` three times
+for this.  There is `git-merge-index` program that extracts the
 stages to temporary files and calls a "merge" script on it:
 
 -------------------------------------------------
-$ git-merge-index git-merge-one-file hello.c
+$ git merge-index git-merge-one-file hello.c
 -------------------------------------------------
 
-and that is what higher level `git merge -s resolve` is implemented with.
+and that is what higher level `git-merge -s resolve` is implemented with.
 
 [[hacking-git]]
 Hacking git
@@ -4062,7 +4061,7 @@ Note that terminology has changed since that revision.  For example, the
 README in that revision uses the word "changeset" to describe what we
 now call a <<def_commit_object,commit>>.
 
-Also, we do not call it "cache" any more, but "index", however, the
+Also, we do not call it "cache" any more, but rather "index"; however, the
 file is still called `cache.h`.  Remark: Not much reason to change it now,
 especially since there is no good single name for it anyway, because it is
 basically _the_ header file which is included by _all_ of Git's C sources.
@@ -4096,7 +4095,7 @@ functions like `get_sha1_basic()` or the likes.
 This is just to get you into the groove for the most libified part of Git:
 the revision walker.
 
-Basically, the initial version of `git log` was a shell script:
+Basically, the initial version of `git-log` was a shell script:
 
 ----------------------------------------------------------------
 $ git-rev-list --pretty $(git-rev-parse --default HEAD "$@") | \
@@ -4128,10 +4127,10 @@ commits one by one with the function `get_revision()`.
 
 If you are interested in more details of the revision walking process,
 just have a look at the first implementation of `cmd_log()`; call
-`git-show v1.3.0{tilde}155^2{tilde}4` and scroll down to that function (note that you
+`git show v1.3.0{tilde}155^2{tilde}4` and scroll down to that function (note that you
 no longer need to call `setup_pager()` directly).
 
-Nowadays, `git log` is a builtin, which means that it is _contained_ in the
+Nowadays, `git-log` is a builtin, which means that it is _contained_ in the
 command `git`.  The source side of a builtin is
 
 - a function called `cmd_<bla>`, typically defined in `builtin-<bla>.c`,
@@ -4147,7 +4146,7 @@ since they share quite a bit of code.  In that case, the commands which are
 _not_ named like the `.c` file in which they live have to be listed in
 `BUILT_INS` in the `Makefile`.
 
-`git log` looks more complicated in C than it does in the original script,
+`git-log` looks more complicated in C than it does in the original script,
 but that allows for a much greater flexibility and performance.
 
 Here again it is a good point to take a pause.
@@ -4158,9 +4157,9 @@ the organization of Git (after you know the basic concepts).
 So, think about something which you are interested in, say, "how can I
 access a blob just knowing the object name of it?".  The first step is to
 find a Git command with which you can do it.  In this example, it is either
-`git show` or `git cat-file`.
+`git-show` or `git-cat-file`.
 
-For the sake of clarity, let's stay with `git cat-file`, because it
+For the sake of clarity, let's stay with `git-cat-file`, because it
 
 - is plumbing, and
 
@@ -4219,10 +4218,10 @@ To find out how the result can be used, just read on in `cmd_cat_file()`:
 -----------------------------------
 
 Sometimes, you do not know where to look for a feature.  In many such cases,
-it helps to search through the output of `git log`, and then `git show` the
+it helps to search through the output of `git log`, and then `git-show` the
 corresponding commit.
 
-Example: If you know that there was some test case for `git bundle`, but
+Example: If you know that there was some test case for `git-bundle`, but
 do not remember where it was (yes, you _could_ `git grep bundle t/`, but that
 does not illustrate the point!):
 
index f221447478aea8628c0ab6d098338f7e8630201e..cb7cd4b53827fa6820e84b1318572d0115b3b17f 100755 (executable)
@@ -16,7 +16,7 @@ elif test -d .git -o -f .git &&
        case "$VN" in
        *$LF*) (exit 1) ;;
        v[0-9]*)
-               test -z "$(git diff-index --name-only HEAD)" ||
+               test -z "$(git diff-index --name-only HEAD --)" ||
                VN="$VN-dirty" ;;
        esac
 then
diff --git a/INSTALL b/INSTALL
index 4a4e13fe46567a567b1ceb09a792379674dc6f57..7d0c2c2f865d6ed969038e7543dbeb8933723ec3 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -24,23 +24,15 @@ set up install paths (via config.mak.autogen), so you can write instead
 
 Issues of note:
 
- - git normally installs a helper script wrapper called "git", which
-   conflicts with a similarly named "GNU interactive tools" program.
-
-   Tough.  Either don't use the wrapper script, or delete the old GNU
-   interactive tools.  None of the core git stuff needs the wrapper,
-   it's just a convenient shorthand and while it is documented in some
-   places, you can always replace "git commit" with "git-commit"
-   instead.
-
-   But let's face it, most of us don't have GNU interactive tools, and
-   even if we had it, we wouldn't know what it does.  I don't think it
-   has been actively developed since 1997, and people have moved over to
-   graphical file managers.
-
-   NOTE: As of gnuit-4.9.2, the GNU interactive tools package has been
-         renamed. You can compile gnuit with the --disable-transition
-         option and then it will not conflict with git.
+ - Ancient versions of GNU Interactive Tools (pre-4.9.2) installed a
+   program "git", whose name conflicts with this program.  But with
+   version 4.9.2, after long hiatus without active maintenance (since
+   around 1997), it changed its name to gnuit and the name conflict is no
+   longer a problem.
+
+   NOTE: When compiled with backward compatiblity option, the GNU
+   Interactive Tools package still can install "git", but you can build it
+   with --disable-transition option to avoid this.
 
  - You can use git after building but without installing if you
    wanted to.  Various git commands need to find other git
index b003e3e60a1aecae27497d941d211849bedec02b..4796565ab3a8e7c9bbe7f6fd092713064dce2c1a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -174,7 +174,7 @@ prefix = $(HOME)
 bindir = $(prefix)/bin
 mandir = $(prefix)/share/man
 infodir = $(prefix)/share/info
-gitexecdir = $(bindir)
+gitexecdir = $(prefix)/libexec/git-core
 sharedir = $(prefix)/share
 template_dir = $(sharedir)/git-core/templates
 htmldir=$(sharedir)/doc/git-doc
@@ -205,7 +205,7 @@ GITWEB_FAVICON = git-favicon.png
 GITWEB_SITE_HEADER =
 GITWEB_SITE_FOOTER =
 
-export prefix bindir gitexecdir sharedir template_dir htmldir sysconfdir
+export prefix bindir gitexecdir sharedir htmldir sysconfdir
 
 CC = gcc
 AR = ar
@@ -241,7 +241,6 @@ SCRIPT_SH += git-merge-octopus.sh
 SCRIPT_SH += git-merge-one-file.sh
 SCRIPT_SH += git-merge-resolve.sh
 SCRIPT_SH += git-merge.sh
-SCRIPT_SH += git-merge-stupid.sh
 SCRIPT_SH += git-mergetool.sh
 SCRIPT_SH += git-parse-remote.sh
 SCRIPT_SH += git-pull.sh
@@ -273,11 +272,9 @@ EXTRA_PROGRAMS =
 
 # ... and all the rest that could be moved out of bindir to gitexecdir
 PROGRAMS += $(EXTRA_PROGRAMS)
-PROGRAMS += git-daemon$X
 PROGRAMS += git-fast-import$X
 PROGRAMS += git-fetch-pack$X
 PROGRAMS += git-hash-object$X
-PROGRAMS += git-imap-send$X
 PROGRAMS += git-index-pack$X
 PROGRAMS += git-merge-index$X
 PROGRAMS += git-merge-tree$X
@@ -337,6 +334,7 @@ LIB_H += builtin.h
 LIB_H += cache.h
 LIB_H += cache-tree.h
 LIB_H += commit.h
+LIB_H += compat/mingw.h
 LIB_H += csum-file.h
 LIB_H += decorate.h
 LIB_H += delta.h
@@ -354,6 +352,7 @@ LIB_H += log-tree.h
 LIB_H += mailmap.h
 LIB_H += object.h
 LIB_H += pack.h
+LIB_H += pack-refs.h
 LIB_H += pack-revindex.h
 LIB_H += parse-options.h
 LIB_H += patch-ids.h
@@ -377,6 +376,7 @@ LIB_H += unpack-trees.h
 LIB_H += utf8.h
 LIB_H += wt-status.h
 
+LIB_OBJS += abspath.o
 LIB_OBJS += alias.o
 LIB_OBJS += alloc.o
 LIB_OBJS += archive.o
@@ -429,6 +429,7 @@ LIB_OBJS += merge-file.o
 LIB_OBJS += name-hash.o
 LIB_OBJS += object.o
 LIB_OBJS += pack-check.o
+LIB_OBJS += pack-refs.o
 LIB_OBJS += pack-revindex.o
 LIB_OBJS += pack-write.o
 LIB_OBJS += pager.o
@@ -467,6 +468,7 @@ LIB_OBJS += unpack-trees.o
 LIB_OBJS += usage.o
 LIB_OBJS += utf8.o
 LIB_OBJS += walker.o
+LIB_OBJS += wrapper.o
 LIB_OBJS += write_or_die.o
 LIB_OBJS += ws.o
 LIB_OBJS += wt-status.o
@@ -713,6 +715,36 @@ ifeq ($(uname_S),HP-UX)
        NO_HSTRERROR = YesPlease
        NO_SYS_SELECT_H = YesPlease
 endif
+ifneq (,$(findstring MINGW,$(uname_S)))
+       NO_MMAP = YesPlease
+       NO_PREAD = YesPlease
+       NO_OPENSSL = YesPlease
+       NO_CURL = YesPlease
+       NO_SYMLINK_HEAD = YesPlease
+       NO_IPV6 = YesPlease
+       NO_SETENV = YesPlease
+       NO_UNSETENV = YesPlease
+       NO_STRCASESTR = YesPlease
+       NO_STRLCPY = YesPlease
+       NO_MEMMEM = YesPlease
+       NEEDS_LIBICONV = YesPlease
+       OLD_ICONV = YesPlease
+       NO_C99_FORMAT = YesPlease
+       NO_STRTOUMAX = YesPlease
+       NO_MKDTEMP = YesPlease
+       SNPRINTF_RETURNS_BOGUS = YesPlease
+       NO_SVN_TESTS = YesPlease
+       NO_PERL_MAKEMAKER = YesPlease
+       NO_POSIX_ONLY_PROGRAMS = YesPlease
+       COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat
+       COMPAT_CFLAGS += -DSNPRINTF_SIZE_CORR=1
+       COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
+       COMPAT_OBJS += compat/mingw.o compat/fnmatch.o compat/regex.o
+       EXTLIBS += -lws2_32
+       X = .exe
+       template_dir = ../share/git-core/templates/
+       ETC_GITCONFIG = ../etc/gitconfig
+endif
 ifneq (,$(findstring arm,$(uname_M)))
        ARM_SHA1 = YesPlease
 endif
@@ -773,6 +805,10 @@ ifdef ZLIB_PATH
 endif
 EXTLIBS += -lz
 
+ifndef NO_POSIX_ONLY_PROGRAMS
+       PROGRAMS += git-daemon$X
+       PROGRAMS += git-imap-send$X
+endif
 ifndef NO_OPENSSL
        OPENSSL_LIBSSL = -lssl
        ifdef OPENSSLDIR
@@ -1229,7 +1265,7 @@ endif
 
 ### Testing rules
 
-TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-absolute-path$X test-parse-options$X
+TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-parse-options$X test-path-utils$X
 
 all:: $(TEST_PROGRAMS)
 
@@ -1264,11 +1300,18 @@ remove-dashes:
 
 ### Installation rules
 
+ifeq ($(firstword $(subst /, ,$(template_dir))),..)
+template_instdir = $(gitexecdir)/$(template_dir)
+else
+template_instdir = $(template_dir)
+endif
+export template_instdir
+
 install: all
        $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'
        $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(gitexecdir_SQ)'
        $(INSTALL) $(ALL_PROGRAMS) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
-       $(INSTALL) git$X '$(DESTDIR_SQ)$(bindir_SQ)'
+       $(INSTALL) git$X git-upload-pack$X git-receive-pack$X git-upload-archive$X '$(DESTDIR_SQ)$(bindir_SQ)'
        $(MAKE) -C templates DESTDIR='$(DESTDIR_SQ)' install
        $(MAKE) -C perl prefix='$(prefix_SQ)' DESTDIR='$(DESTDIR_SQ)' install
 ifndef NO_TCLTK
@@ -1286,10 +1329,14 @@ endif
 ifneq (,$X)
        $(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), $(RM) '$(DESTDIR_SQ)$(gitexecdir_SQ)/$p';)
 endif
+       ./check_bindir 'z$(bindir_SQ)' 'z$(gitexecdir_SQ)' '$(DESTDIR_SQ)$(bindir_SQ)/git-shell$X'
 
 install-doc:
        $(MAKE) -C Documentation install
 
+install-html:
+       $(MAKE) -C Documentation install-html
+
 install-info:
        $(MAKE) -C Documentation install-info
 
@@ -1381,7 +1428,7 @@ check-docs::
        do \
                case "$$v" in \
                git-merge-octopus | git-merge-ours | git-merge-recursive | \
-               git-merge-resolve | git-merge-stupid | git-merge-subtree | \
+               git-merge-resolve | git-merge-subtree | \
                git-fsck-objects | git-init-db | \
                git-?*--?* ) continue ;; \
                esac ; \
index a2b8043c8348d785ce3550a9109b785906f370b0..b9a53c3416991b66e1d35c2bbf663b48340b0041 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes-1.5.6.3.txt
\ No newline at end of file
+Documentation/RelNotes-1.6.0.txt
\ No newline at end of file
diff --git a/abspath.c b/abspath.c
new file mode 100644 (file)
index 0000000..4f95a95
--- /dev/null
+++ b/abspath.c
@@ -0,0 +1,68 @@
+#include "cache.h"
+
+/* We allow "recursive" symbolic links. Only within reason, though. */
+#define MAXDEPTH 5
+
+const char *make_absolute_path(const char *path)
+{
+       static char bufs[2][PATH_MAX + 1], *buf = bufs[0], *next_buf = bufs[1];
+       char cwd[1024] = "";
+       int buf_index = 1, len;
+
+       int depth = MAXDEPTH;
+       char *last_elem = NULL;
+       struct stat st;
+
+       if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
+               die ("Too long path: %.*s", 60, path);
+
+       while (depth--) {
+               if (stat(buf, &st) || !S_ISDIR(st.st_mode)) {
+                       char *last_slash = strrchr(buf, '/');
+                       if (last_slash) {
+                               *last_slash = '\0';
+                               last_elem = xstrdup(last_slash + 1);
+                       } else {
+                               last_elem = xstrdup(buf);
+                               *buf = '\0';
+                       }
+               }
+
+               if (*buf) {
+                       if (!*cwd && !getcwd(cwd, sizeof(cwd)))
+                               die ("Could not get current working directory");
+
+                       if (chdir(buf))
+                               die ("Could not switch to '%s'", buf);
+               }
+               if (!getcwd(buf, PATH_MAX))
+                       die ("Could not get current working directory");
+
+               if (last_elem) {
+                       int len = strlen(buf);
+                       if (len + strlen(last_elem) + 2 > PATH_MAX)
+                               die ("Too long path name: '%s/%s'",
+                                               buf, last_elem);
+                       buf[len] = '/';
+                       strcpy(buf + len + 1, last_elem);
+                       free(last_elem);
+                       last_elem = NULL;
+               }
+
+               if (!lstat(buf, &st) && S_ISLNK(st.st_mode)) {
+                       len = readlink(buf, next_buf, PATH_MAX);
+                       if (len < 0)
+                               die ("Invalid symlink: %s", buf);
+                       next_buf[len] = '\0';
+                       buf = next_buf;
+                       buf_index = 1 - buf_index;
+                       next_buf = bufs[buf_index];
+               } else
+                       break;
+       }
+
+       if (*cwd && chdir(cwd))
+               die ("Could not change back to '%s'", cwd);
+
+       return buf;
+}
index d7598f907d9f7fb40c24c8cef815f8fc33a8b19b..99db58f1cf21ee30f150c54acd6ffefbb14b6f57 100644 (file)
@@ -247,6 +247,8 @@ static int write_tar_entry(const unsigned char *sha1,
        strbuf_grow(&path, PATH_MAX);
        strbuf_add(&path, base, baselen);
        strbuf_addstr(&path, filename);
+       if (is_archive_path_ignored(path.buf + base_len))
+               return 0;
        if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
                strbuf_addch(&path, '/');
                buffer = NULL;
index 18c0f8710c6150e3b0211d311a70bf4b34608370..5742762ac30c92e796255b74d2ed1ea087f3fba0 100644 (file)
@@ -176,6 +176,8 @@ static int write_zip_entry(const unsigned char *sha1,
        crc = crc32(0, NULL, 0);
 
        path = construct_path(base, baselen, filename, S_ISDIR(mode), &pathlen);
+       if (is_archive_path_ignored(path + base_len))
+               return 0;
        if (verbose)
                fprintf(stderr, "%s\n", path);
        if (pathlen > 0xffff) {
index 7a32c19d3ca8043f3ca22dadfdbc60dbbb747d59..6502b76ef10a182e9d9f0e60ad926c55a31a737a 100644 (file)
--- a/archive.c
+++ b/archive.c
@@ -82,3 +82,16 @@ void *sha1_file_to_archive(const char *path, const unsigned char *sha1,
        return buffer;
 }
 
+int is_archive_path_ignored(const char *path)
+{
+       static struct git_attr *attr_export_ignore;
+       struct git_attr_check check[1];
+
+       if (!attr_export_ignore)
+               attr_export_ignore = git_attr("export-ignore", 13);
+
+       check[0].attr = attr_export_ignore;
+       if (git_checkattr(path, ARRAY_SIZE(check), check))
+               return 0;
+       return ATTR_TRUE(check[0].value);
+}
index 5791e657e9a0c22081f4f42b9d8ca5b3c536baf2..ddf004acdfa2125a73df11e923eda902d3ca8277 100644 (file)
--- a/archive.h
+++ b/archive.h
@@ -44,5 +44,6 @@ extern int write_zip_archive(struct archiver_args *);
 extern void *parse_extra_zip_args(int argc, const char **argv);
 
 extern void *sha1_file_to_archive(const char *path, const unsigned char *sha1, unsigned int mode, enum object_type *type, unsigned long *size, const struct commit *commit);
+extern int is_archive_path_ignored(const char *path);
 
 #endif /* ARCHIVE_H */
index c4978893122bbcfd80201fe937eb8433b29e1aa0..d13313f1051eb3f7374cf4119923b230fd6f81d8 100644 (file)
@@ -12,6 +12,7 @@
 #include "blob.h"
 #include "delta.h"
 #include "builtin.h"
+#include "path-list.h"
 
 /*
  *  --check turns on checking that the working tree matches the
@@ -57,6 +58,8 @@ static int whitespace_error;
 static int squelch_whitespace_errors = 5;
 static int applied_after_fixing_ws;
 static const char *patch_input_file;
+static const char *root;
+static int root_len;
 
 static void parse_whitespace_option(const char *option)
 {
@@ -153,6 +156,7 @@ struct patch {
        unsigned int is_binary:1;
        unsigned int is_copy:1;
        unsigned int is_rename:1;
+       unsigned int recount:1;
        struct fragment *fragments;
        char *result;
        size_t resultsize;
@@ -185,6 +189,13 @@ struct image {
        struct line *line;
 };
 
+/*
+ * Records filenames that have been touched, in order to handle
+ * the case where more than one patches touch the same file.
+ */
+
+static struct path_list fn_table;
+
 static uint32_t hash_line(const char *cp, size_t len)
 {
        size_t i;
@@ -331,6 +342,8 @@ static char *find_name(const char *line, char *def, int p_value, int terminate)
                                 */
                                strbuf_remove(&name, 0, cp - name.buf);
                                free(def);
+                               if (root)
+                                       strbuf_insert(&name, 0, root, root_len);
                                return strbuf_detach(&name, NULL);
                        }
                }
@@ -369,6 +382,14 @@ static char *find_name(const char *line, char *def, int p_value, int terminate)
                free(def);
        }
 
+       if (root) {
+               char *ret = xmalloc(root_len + len + 1);
+               strcpy(ret, root);
+               memcpy(ret + root_len, start, len);
+               ret[root_len + len] = '\0';
+               return ret;
+       }
+
        return xmemdupz(start, len);
 }
 
@@ -882,6 +903,56 @@ static int parse_range(const char *line, int len, int offset, const char *expect
        return offset + ex;
 }
 
+static void recount_diff(char *line, int size, struct fragment *fragment)
+{
+       int oldlines = 0, newlines = 0, ret = 0;
+
+       if (size < 1) {
+               warning("recount: ignore empty hunk");
+               return;
+       }
+
+       for (;;) {
+               int len = linelen(line, size);
+               size -= len;
+               line += len;
+
+               if (size < 1)
+                       break;
+
+               switch (*line) {
+               case ' ': case '\n':
+                       newlines++;
+                       /* fall through */
+               case '-':
+                       oldlines++;
+                       continue;
+               case '+':
+                       newlines++;
+                       continue;
+               case '\\':
+                       continue;
+               case '@':
+                       ret = size < 3 || prefixcmp(line, "@@ ");
+                       break;
+               case 'd':
+                       ret = size < 5 || prefixcmp(line, "diff ");
+                       break;
+               default:
+                       ret = -1;
+                       break;
+               }
+               if (ret) {
+                       warning("recount: unexpected line: %.*s",
+                               (int)linelen(line, size), line);
+                       return;
+               }
+               break;
+       }
+       fragment->oldlines = oldlines;
+       fragment->newlines = newlines;
+}
+
 /*
  * Parse a unified diff fragment header of the
  * form "@@ -a,b +c,d @@"
@@ -979,8 +1050,7 @@ static int find_header(char *line, unsigned long size, int *hdrsize, struct patc
 static void check_whitespace(const char *line, int len, unsigned ws_rule)
 {
        char *err;
-       unsigned result = check_and_emit_line(line + 1, len - 1, ws_rule,
-           NULL, NULL, NULL, NULL);
+       unsigned result = ws_check(line + 1, len - 1, ws_rule);
        if (!result)
                return;
 
@@ -991,7 +1061,7 @@ static void check_whitespace(const char *line, int len, unsigned ws_rule)
        else {
                err = whitespace_error_string(result);
                fprintf(stderr, "%s:%d: %s.\n%.*s\n",
-                    patch_input_file, linenr, err, len - 2, line + 1);
+                       patch_input_file, linenr, err, len - 2, line + 1);
                free(err);
        }
 }
@@ -1013,6 +1083,8 @@ static int parse_fragment(char *line, unsigned long size,
        offset = parse_fragment_header(line, len, fragment);
        if (offset < 0)
                return -1;
+       if (offset > 0 && patch->recount)
+               recount_diff(line + offset, size - offset, fragment);
        oldlines = fragment->oldlines;
        newlines = fragment->newlines;
        leading = 0;
@@ -2176,15 +2248,63 @@ static int read_file_or_gitlink(struct cache_entry *ce, struct strbuf *buf)
        return 0;
 }
 
+static struct patch *in_fn_table(const char *name)
+{
+       struct path_list_item *item;
+
+       if (name == NULL)
+               return NULL;
+
+       item = path_list_lookup(name, &fn_table);
+       if (item != NULL)
+               return (struct patch *)item->util;
+
+       return NULL;
+}
+
+static void add_to_fn_table(struct patch *patch)
+{
+       struct path_list_item *item;
+
+       /*
+        * Always add new_name unless patch is a deletion
+        * This should cover the cases for normal diffs,
+        * file creations and copies
+        */
+       if (patch->new_name != NULL) {
+               item = path_list_insert(patch->new_name, &fn_table);
+               item->util = patch;
+       }
+
+       /*
+        * store a failure on rename/deletion cases because
+        * later chunks shouldn't patch old names
+        */
+       if ((patch->new_name == NULL) || (patch->is_rename)) {
+               item = path_list_insert(patch->old_name, &fn_table);
+               item->util = (struct patch *) -1;
+       }
+}
+
 static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *ce)
 {
        struct strbuf buf;
        struct image image;
        size_t len;
        char *img;
+       struct patch *tpatch;
 
        strbuf_init(&buf, 0);
-       if (cached) {
+
+       if (!(patch->is_copy || patch->is_rename) &&
+           ((tpatch = in_fn_table(patch->old_name)) != NULL)) {
+               if (tpatch == (struct patch *) -1) {
+                       return error("patch %s has been renamed/deleted",
+                               patch->old_name);
+               }
+               /* We have a patched copy in memory use that */
+               strbuf_add(&buf, tpatch->result, tpatch->resultsize);
+       } else if (cached) {
                if (read_file_or_gitlink(ce, &buf))
                        return error("read of %s failed", patch->old_name);
        } else if (patch->old_name) {
@@ -2211,6 +2331,7 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *
                return -1; /* note with --reject this succeeds. */
        patch->result = image.buf;
        patch->resultsize = image.len;
+       add_to_fn_table(patch);
        free(image.line_allocated);
 
        if (0 < patch->is_delete && patch->resultsize)
@@ -2255,6 +2376,7 @@ static int verify_index_match(struct cache_entry *ce, struct stat *st)
 static int check_preimage(struct patch *patch, struct cache_entry **ce, struct stat *st)
 {
        const char *old_name = patch->old_name;
+       struct patch *tpatch = NULL;
        int stat_ret = 0;
        unsigned st_mode = 0;
 
@@ -2268,12 +2390,20 @@ static int check_preimage(struct patch *patch, struct cache_entry **ce, struct s
                return 0;
 
        assert(patch->is_new <= 0);
-       if (!cached) {
+
+       if (!(patch->is_copy || patch->is_rename) &&
+           (tpatch = in_fn_table(old_name)) != NULL) {
+               if (tpatch == (struct patch *) -1) {
+                       return error("%s: has been deleted/renamed", old_name);
+               }
+               st_mode = tpatch->new_mode;
+       } else if (!cached) {
                stat_ret = lstat(old_name, st);
                if (stat_ret && errno != ENOENT)
                        return error("%s: %s", old_name, strerror(errno));
        }
-       if (check_index) {
+
+       if (check_index && !tpatch) {
                int pos = cache_name_pos(old_name, strlen(old_name));
                if (pos < 0) {
                        if (patch->is_new < 0)
@@ -2325,7 +2455,7 @@ static int check_preimage(struct patch *patch, struct cache_entry **ce, struct s
        return 0;
 }
 
-static int check_patch(struct patch *patch, struct patch *prev_patch)
+static int check_patch(struct patch *patch)
 {
        struct stat st;
        const char *old_name = patch->old_name;
@@ -2342,8 +2472,7 @@ static int check_patch(struct patch *patch, struct patch *prev_patch)
                return status;
        old_name = patch->old_name;
 
-       if (new_name && prev_patch && 0 < prev_patch->is_delete &&
-           !strcmp(prev_patch->old_name, new_name))
+       if (in_fn_table(new_name) == (struct patch *) -1)
                /*
                 * A type-change diff is always split into a patch to
                 * delete old, immediately followed by a patch to
@@ -2393,15 +2522,14 @@ static int check_patch(struct patch *patch, struct patch *prev_patch)
 
 static int check_patch_list(struct patch *patch)
 {
-       struct patch *prev_patch = NULL;
        int err = 0;
 
-       for (prev_patch = NULL; patch ; patch = patch->next) {
+       while (patch) {
                if (apply_verbosely)
                        say_patch_name(stderr,
                                       "Checking patch ", patch, "...\n");
-               err |= check_patch(patch, prev_patch);
-               prev_patch = patch;
+               err |= check_patch(patch);
+               patch = patch->next;
        }
        return err;
 }
@@ -2912,13 +3040,18 @@ static void prefix_patches(struct patch *p)
        }
 }
 
-static int apply_patch(int fd, const char *filename, int inaccurate_eof)
+#define INACCURATE_EOF (1<<0)
+#define RECOUNT                (1<<1)
+
+static int apply_patch(int fd, const char *filename, int options)
 {
        size_t offset;
        struct strbuf buf;
        struct patch *list = NULL, **listp = &list;
        int skipped_patch = 0;
 
+       /* FIXME - memory leak when using multiple patch files as inputs */
+       memset(&fn_table, 0, sizeof(struct path_list));
        strbuf_init(&buf, 0);
        patch_input_file = filename;
        read_patch_file(&buf, fd);
@@ -2928,7 +3061,8 @@ static int apply_patch(int fd, const char *filename, int inaccurate_eof)
                int nr;
 
                patch = xcalloc(1, sizeof(*patch));
-               patch->inaccurate_eof = inaccurate_eof;
+               patch->inaccurate_eof = !!(options & INACCURATE_EOF);
+               patch->recount =  !!(options & RECOUNT);
                nr = parse_chunk(buf.buf + offset, buf.len - offset, patch);
                if (nr < 0)
                        break;
@@ -2997,7 +3131,7 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
 {
        int i;
        int read_stdin = 1;
-       int inaccurate_eof = 0;
+       int options = 0;
        int errs = 0;
        int is_not_gitdir;
 
@@ -3015,7 +3149,7 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
                int fd;
 
                if (!strcmp(arg, "-")) {
-                       errs |= apply_patch(0, "<stdin>", inaccurate_eof);
+                       errs |= apply_patch(0, "<stdin>", options);
                        read_stdin = 0;
                        continue;
                }
@@ -3115,7 +3249,23 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
                        continue;
                }
                if (!strcmp(arg, "--inaccurate-eof")) {
-                       inaccurate_eof = 1;
+                       options |= INACCURATE_EOF;
+                       continue;
+               }
+               if (!strcmp(arg, "--recount")) {
+                       options |= RECOUNT;
+                       continue;
+               }
+               if (!prefixcmp(arg, "--directory=")) {
+                       arg += strlen("--directory=");
+                       root_len = strlen(arg);
+                       if (root_len && arg[root_len - 1] != '/') {
+                               char *new_root;
+                               root = new_root = xmalloc(root_len + 2);
+                               strcpy(new_root, arg);
+                               strcpy(new_root + root_len++, "/");
+                       } else
+                               root = arg;
                        continue;
                }
                if (0 < prefix_length)
@@ -3126,12 +3276,12 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
                        die("can't open patch '%s': %s", arg, strerror(errno));
                read_stdin = 0;
                set_default_whitespace_mode(whitespace_option);
-               errs |= apply_patch(fd, arg, inaccurate_eof);
+               errs |= apply_patch(fd, arg, options);
                close(fd);
        }
        set_default_whitespace_mode(whitespace_option);
        if (read_stdin)
-               errs |= apply_patch(0, "<stdin>", inaccurate_eof);
+               errs |= apply_patch(0, "<stdin>", options);
        if (whitespace_error) {
                if (squelch_whitespace_errors &&
                    squelch_whitespace_errors < whitespace_error) {
index b451f6c64dde8ce6358bb5c8dfccc8bad181a6bb..06c7de429799f4af5303253775f21b7f37723b94 100644 (file)
 #include "cache-tree.h"
 #include "path-list.h"
 #include "mailmap.h"
+#include "parse-options.h"
 
-static char blame_usage[] =
-"git-blame [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-p] [-w] [-L n,m] [-S <revs-file>] [-M] [-C] [-C] [--contents <filename>] [--incremental] [commit] [--] file\n"
-"  -c                  Use the same output mode as git-annotate (Default: off)\n"
-"  -b                  Show blank SHA-1 for boundary commits (Default: off)\n"
-"  -l                  Show long commit SHA1 (Default: off)\n"
-"  --root              Do not treat root commits as boundaries (Default: off)\n"
-"  -t                  Show raw timestamp (Default: off)\n"
-"  -f, --show-name     Show original filename (Default: auto)\n"
-"  -n, --show-number   Show original linenumber (Default: off)\n"
-"  -s                  Suppress author name and timestamp (Default: off)\n"
-"  -p, --porcelain     Show in a format designed for machine consumption\n"
-"  -w                  Ignore whitespace differences\n"
-"  -L n,m              Process only line range n,m, counting from 1\n"
-"  -M, -C              Find line movements within and across files\n"
-"  --incremental       Show blame entries as we find them, incrementally\n"
-"  --contents file     Use <file>'s contents as the final image\n"
-"  -S revs-file        Use revisions from revs-file instead of calling git-rev-list\n";
+static char blame_usage[] = "git-blame [options] [rev-opts] [rev] [--] file";
+
+static const char *blame_opt_usage[] = {
+       blame_usage,
+       "",
+       "[rev-opts] are documented in git-rev-list(1)",
+       NULL
+};
 
 static int longest_file;
 static int longest_author;
@@ -43,6 +35,7 @@ static int max_orig_digits;
 static int max_digits;
 static int max_score_digits;
 static int show_root;
+static int reverse;
 static int blank_boundary;
 static int incremental;
 static int cmd_is_annotate;
@@ -91,7 +84,7 @@ struct origin {
  * Given an origin, prepare mmfile_t structure to be used by the
  * diff machinery
  */
-static char *fill_origin_blob(struct origin *o, mmfile_t *file)
+static void fill_origin_blob(struct origin *o, mmfile_t *file)
 {
        if (!o->file.ptr) {
                enum object_type type;
@@ -106,7 +99,6 @@ static char *fill_origin_blob(struct origin *o, mmfile_t *file)
        }
        else
                *file = o->file;
-       return file->ptr;
 }
 
 /*
@@ -178,7 +170,7 @@ struct blame_entry {
 struct scoreboard {
        /* the final commit (i.e. where we started digging from) */
        struct commit *final;
-
+       struct rev_info *revs;
        const char *path;
 
        /*
@@ -1192,18 +1184,48 @@ static void pass_whole_blame(struct scoreboard *sb,
        }
 }
 
-#define MAXPARENT 16
+/*
+ * We pass blame from the current commit to its parents.  We keep saying
+ * "parent" (and "porigin"), but what we mean is to find scapegoat to
+ * exonerate ourselves.
+ */
+static struct commit_list *first_scapegoat(struct rev_info *revs, struct commit *commit)
+{
+       if (!reverse)
+               return commit->parents;
+       return lookup_decoration(&revs->children, &commit->object);
+}
+
+static int num_scapegoats(struct rev_info *revs, struct commit *commit)
+{
+       int cnt;
+       struct commit_list *l = first_scapegoat(revs, commit);
+       for (cnt = 0; l; l = l->next)
+               cnt++;
+       return cnt;
+}
+
+#define MAXSG 16
 
 static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
 {
-       int i, pass;
+       struct rev_info *revs = sb->revs;
+       int i, pass, num_sg;
        struct commit *commit = origin->commit;
-       struct commit_list *parent;
-       struct origin *parent_origin[MAXPARENT], *porigin;
-
-       memset(parent_origin, 0, sizeof(parent_origin));
+       struct commit_list *sg;
+       struct origin *sg_buf[MAXSG];
+       struct origin *porigin, **sg_origin = sg_buf;
+
+       num_sg = num_scapegoats(revs, commit);
+       if (!num_sg)
+               goto finish;
+       else if (num_sg < ARRAY_SIZE(sg_buf))
+               memset(sg_buf, 0, sizeof(sg_buf));
+       else
+               sg_origin = xcalloc(num_sg, sizeof(*sg_origin));
 
-       /* The first pass looks for unrenamed path to optimize for
+       /*
+        * The first pass looks for unrenamed path to optimize for
         * common cases, then we look for renames in the second pass.
         */
        for (pass = 0; pass < 2; pass++) {
@@ -1211,13 +1233,13 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
                                       struct commit *, struct origin *);
                find = pass ? find_rename : find_origin;
 
-               for (i = 0, parent = commit->parents;
-                    i < MAXPARENT && parent;
-                    parent = parent->next, i++) {
-                       struct commit *p = parent->item;
+               for (i = 0, sg = first_scapegoat(revs, commit);
+                    i < num_sg && sg;
+                    sg = sg->next, i++) {
+                       struct commit *p = sg->item;
                        int j, same;
 
-                       if (parent_origin[i])
+                       if (sg_origin[i])
                                continue;
                        if (parse_commit(p))
                                continue;
@@ -1230,24 +1252,24 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
                                goto finish;
                        }
                        for (j = same = 0; j < i; j++)
-                               if (parent_origin[j] &&
-                                   !hashcmp(parent_origin[j]->blob_sha1,
+                               if (sg_origin[j] &&
+                                   !hashcmp(sg_origin[j]->blob_sha1,
                                             porigin->blob_sha1)) {
                                        same = 1;
                                        break;
                                }
                        if (!same)
-                               parent_origin[i] = porigin;
+                               sg_origin[i] = porigin;
                        else
                                origin_decref(porigin);
                }
        }
 
        num_commits++;
-       for (i = 0, parent = commit->parents;
-            i < MAXPARENT && parent;
-            parent = parent->next, i++) {
-               struct origin *porigin = parent_origin[i];
+       for (i = 0, sg = first_scapegoat(revs, commit);
+            i < num_sg && sg;
+            sg = sg->next, i++) {
+               struct origin *porigin = sg_origin[i];
                if (!porigin)
                        continue;
                if (pass_blame_to_parent(sb, origin, porigin))
@@ -1258,10 +1280,10 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
         * Optionally find moves in parents' files.
         */
        if (opt & PICKAXE_BLAME_MOVE)
-               for (i = 0, parent = commit->parents;
-                    i < MAXPARENT && parent;
-                    parent = parent->next, i++) {
-                       struct origin *porigin = parent_origin[i];
+               for (i = 0, sg = first_scapegoat(revs, commit);
+                    i < num_sg && sg;
+                    sg = sg->next, i++) {
+                       struct origin *porigin = sg_origin[i];
                        if (!porigin)
                                continue;
                        if (find_move_in_parent(sb, origin, porigin))
@@ -1272,23 +1294,25 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
         * Optionally find copies from parents' files.
         */
        if (opt & PICKAXE_BLAME_COPY)
-               for (i = 0, parent = commit->parents;
-                    i < MAXPARENT && parent;
-                    parent = parent->next, i++) {
-                       struct origin *porigin = parent_origin[i];
-                       if (find_copy_in_parent(sb, origin, parent->item,
+               for (i = 0, sg = first_scapegoat(revs, commit);
+                    i < num_sg && sg;
+                    sg = sg->next, i++) {
+                       struct origin *porigin = sg_origin[i];
+                       if (find_copy_in_parent(sb, origin, sg->item,
                                                porigin, opt))
                                goto finish;
                }
 
  finish:
-       for (i = 0; i < MAXPARENT; i++) {
-               if (parent_origin[i]) {
-                       drop_origin_blob(parent_origin[i]);
-                       origin_decref(parent_origin[i]);
+       for (i = 0; i < num_sg; i++) {
+               if (sg_origin[i]) {
+                       drop_origin_blob(sg_origin[i]);
+                       origin_decref(sg_origin[i]);
                }
        }
        drop_origin_blob(origin);
+       if (sg_buf != sg_origin)
+               free(sg_origin);
 }
 
 /*
@@ -1487,8 +1511,10 @@ static void found_guilty_entry(struct blame_entry *ent)
  * is still unknown, pick one blame_entry, and allow its current
  * suspect to pass blames to its parents.
  */
-static void assign_blame(struct scoreboard *sb, struct rev_info *revs, int opt)
+static void assign_blame(struct scoreboard *sb, int opt)
 {
+       struct rev_info *revs = sb->revs;
+
        while (1) {
                struct blame_entry *ent;
                struct commit *commit;
@@ -1509,8 +1535,9 @@ static void assign_blame(struct scoreboard *sb, struct rev_info *revs, int opt)
                commit = suspect->commit;
                if (!commit->object.parsed)
                        parse_commit(commit);
-               if (!(commit->object.flags & UNINTERESTING) &&
-                   !(revs->max_age != -1 && commit->date < revs->max_age))
+               if (reverse ||
+                   (!(commit->object.flags & UNINTERESTING) &&
+                    !(revs->max_age != -1 && commit->date < revs->max_age)))
                        pass_blame(sb, suspect, opt);
                else {
                        commit->object.flags |= UNINTERESTING;
@@ -2006,6 +2033,10 @@ static int git_blame_config(const char *var, const char *value, void *cb)
        return git_default_config(var, value, cb);
 }
 
+/*
+ * Prepare a dummy commit that represents the work tree (or staged) item.
+ * Note that annotating work tree item never works in the reverse.
+ */
 static struct commit *fake_working_tree_commit(const char *path, const char *contents_from)
 {
        struct commit *commit;
@@ -2122,6 +2153,108 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
        return commit;
 }
 
+static const char *prepare_final(struct scoreboard *sb)
+{
+       int i;
+       const char *final_commit_name = NULL;
+       struct rev_info *revs = sb->revs;
+
+       /*
+        * There must be one and only one positive commit in the
+        * revs->pending array.
+        */
+       for (i = 0; i < revs->pending.nr; i++) {
+               struct object *obj = revs->pending.objects[i].item;
+               if (obj->flags & UNINTERESTING)
+                       continue;
+               while (obj->type == OBJ_TAG)
+                       obj = deref_tag(obj, NULL, 0);
+               if (obj->type != OBJ_COMMIT)
+                       die("Non commit %s?", revs->pending.objects[i].name);
+               if (sb->final)
+                       die("More than one commit to dig from %s and %s?",
+                           revs->pending.objects[i].name,
+                           final_commit_name);
+               sb->final = (struct commit *) obj;
+               final_commit_name = revs->pending.objects[i].name;
+       }
+       return final_commit_name;
+}
+
+static const char *prepare_initial(struct scoreboard *sb)
+{
+       int i;
+       const char *final_commit_name = NULL;
+       struct rev_info *revs = sb->revs;
+
+       /*
+        * There must be one and only one negative commit, and it must be
+        * the boundary.
+        */
+       for (i = 0; i < revs->pending.nr; i++) {
+               struct object *obj = revs->pending.objects[i].item;
+               if (!(obj->flags & UNINTERESTING))
+                       continue;
+               while (obj->type == OBJ_TAG)
+                       obj = deref_tag(obj, NULL, 0);
+               if (obj->type != OBJ_COMMIT)
+                       die("Non commit %s?", revs->pending.objects[i].name);
+               if (sb->final)
+                       die("More than one commit to dig down to %s and %s?",
+                           revs->pending.objects[i].name,
+                           final_commit_name);
+               sb->final = (struct commit *) obj;
+               final_commit_name = revs->pending.objects[i].name;
+       }
+       if (!final_commit_name)
+               die("No commit to dig down to?");
+       return final_commit_name;
+}
+
+static int blame_copy_callback(const struct option *option, const char *arg, int unset)
+{
+       int *opt = option->value;
+
+       /*
+        * -C enables copy from removed files;
+        * -C -C enables copy from existing files, but only
+        *       when blaming a new file;
+        * -C -C -C enables copy from existing files for
+        *          everybody
+        */
+       if (*opt & PICKAXE_BLAME_COPY_HARDER)
+               *opt |= PICKAXE_BLAME_COPY_HARDEST;
+       if (*opt & PICKAXE_BLAME_COPY)
+               *opt |= PICKAXE_BLAME_COPY_HARDER;
+       *opt |= PICKAXE_BLAME_COPY | PICKAXE_BLAME_MOVE;
+
+       if (arg)
+               blame_copy_score = parse_score(arg);
+       return 0;
+}
+
+static int blame_move_callback(const struct option *option, const char *arg, int unset)
+{
+       int *opt = option->value;
+
+       *opt |= PICKAXE_BLAME_MOVE;
+
+       if (arg)
+               blame_move_score = parse_score(arg);
+       return 0;
+}
+
+static int blame_bottomtop_callback(const struct option *option, const char *arg, int unset)
+{
+       const char **bottomtop = option->value;
+       if (!arg)
+               return -1;
+       if (*bottomtop)
+               die("More than one '-L n,m' option given");
+       *bottomtop = arg;
+       return 0;
+}
+
 int cmd_blame(int argc, const char **argv, const char *prefix)
 {
        struct rev_info revs;
@@ -2129,102 +2262,66 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
        struct scoreboard sb;
        struct origin *o;
        struct blame_entry *ent;
-       int i, seen_dashdash, unk, opt;
-       long bottom, top, lno;
-       int output_option = 0;
-       int show_stats = 0;
-       const char *revs_file = NULL;
+       long dashdash_pos, bottom, top, lno;
        const char *final_commit_name = NULL;
        enum object_type type;
-       const char *bottomtop = NULL;
-       const char *contents_from = NULL;
+
+       static const char *bottomtop = NULL;
+       static int output_option = 0, opt = 0;
+       static int show_stats = 0;
+       static const char *revs_file = NULL;
+       static const char *contents_from = NULL;
+       static const struct option options[] = {
+               OPT_BOOLEAN(0, "incremental", &incremental, "Show blame entries as we find them, incrementally"),
+               OPT_BOOLEAN('b', NULL, &blank_boundary, "Show blank SHA-1 for boundary commits (Default: off)"),
+               OPT_BOOLEAN(0, "root", &show_root, "Do not treat root commits as boundaries (Default: off)"),
+               OPT_BOOLEAN(0, "show-stats", &show_stats, "Show work cost statistics"),
+               OPT_BIT(0, "score-debug", &output_option, "Show output score for blame entries", OUTPUT_SHOW_SCORE),
+               OPT_BIT('f', "show-name", &output_option, "Show original filename (Default: auto)", OUTPUT_SHOW_NAME),
+               OPT_BIT('n', "show-number", &output_option, "Show original linenumber (Default: off)", OUTPUT_SHOW_NUMBER),
+               OPT_BIT('p', "porcelain", &output_option, "Show in a format designed for machine consumption", OUTPUT_PORCELAIN),
+               OPT_BIT('c', NULL, &output_option, "Use the same output mode as git-annotate (Default: off)", OUTPUT_ANNOTATE_COMPAT),
+               OPT_BIT('t', NULL, &output_option, "Show raw timestamp (Default: off)", OUTPUT_RAW_TIMESTAMP),
+               OPT_BIT('l', NULL, &output_option, "Show long commit SHA1 (Default: off)", OUTPUT_LONG_OBJECT_NAME),
+               OPT_BIT('s', NULL, &output_option, "Suppress author name and timestamp (Default: off)", OUTPUT_NO_AUTHOR),
+               OPT_BIT('w', NULL, &xdl_opts, "Ignore whitespace differences", XDF_IGNORE_WHITESPACE),
+               OPT_STRING('S', NULL, &revs_file, "file", "Use revisions from <file> instead of calling git-rev-list"),
+               OPT_STRING(0, "contents", &contents_from, "file", "Use <file>'s contents as the final image"),
+               { OPTION_CALLBACK, 'C', NULL, &opt, "score", "Find line copies within and across files", PARSE_OPT_OPTARG, blame_copy_callback },
+               { OPTION_CALLBACK, 'M', NULL, &opt, "score", "Find line movements within and across files", PARSE_OPT_OPTARG, blame_move_callback },
+               OPT_CALLBACK('L', NULL, &bottomtop, "n,m", "Process only line range n,m, counting from 1", blame_bottomtop_callback),
+               OPT_END()
+       };
+
+       struct parse_opt_ctx_t ctx;
 
        cmd_is_annotate = !strcmp(argv[0], "annotate");
 
        git_config(git_blame_config, NULL);
+       init_revisions(&revs, NULL);
        save_commit_buffer = 0;
-
-       opt = 0;
-       seen_dashdash = 0;
-       for (unk = i = 1; i < argc; i++) {
-               const char *arg = argv[i];
-               if (*arg != '-')
-                       break;
-               else if (!strcmp("-b", arg))
-                       blank_boundary = 1;
-               else if (!strcmp("--root", arg))
-                       show_root = 1;
-               else if (!strcmp(arg, "--show-stats"))
-                       show_stats = 1;
-               else if (!strcmp("-c", arg))
-                       output_option |= OUTPUT_ANNOTATE_COMPAT;
-               else if (!strcmp("-t", arg))
-                       output_option |= OUTPUT_RAW_TIMESTAMP;
-               else if (!strcmp("-l", arg))
-                       output_option |= OUTPUT_LONG_OBJECT_NAME;
-               else if (!strcmp("-s", arg))
-                       output_option |= OUTPUT_NO_AUTHOR;
-               else if (!strcmp("-w", arg))
-                       xdl_opts |= XDF_IGNORE_WHITESPACE;
-               else if (!strcmp("-S", arg) && ++i < argc)
-                       revs_file = argv[i];
-               else if (!prefixcmp(arg, "-M")) {
-                       opt |= PICKAXE_BLAME_MOVE;
-                       blame_move_score = parse_score(arg+2);
-               }
-               else if (!prefixcmp(arg, "-C")) {
-                       /*
-                        * -C enables copy from removed files;
-                        * -C -C enables copy from existing files, but only
-                        *       when blaming a new file;
-                        * -C -C -C enables copy from existing files for
-                        *          everybody
-                        */
-                       if (opt & PICKAXE_BLAME_COPY_HARDER)
-                               opt |= PICKAXE_BLAME_COPY_HARDEST;
-                       if (opt & PICKAXE_BLAME_COPY)
-                               opt |= PICKAXE_BLAME_COPY_HARDER;
-                       opt |= PICKAXE_BLAME_COPY | PICKAXE_BLAME_MOVE;
-                       blame_copy_score = parse_score(arg+2);
-               }
-               else if (!prefixcmp(arg, "-L")) {
-                       if (!arg[2]) {
-                               if (++i >= argc)
-                                       usage(blame_usage);
-                               arg = argv[i];
-                       }
-                       else
-                               arg += 2;
-                       if (bottomtop)
-                               die("More than one '-L n,m' option given");
-                       bottomtop = arg;
+       dashdash_pos = 0;
+
+       parse_options_start(&ctx, argc, argv, PARSE_OPT_KEEP_DASHDASH |
+                           PARSE_OPT_KEEP_ARGV0);
+       for (;;) {
+               switch (parse_options_step(&ctx, options, blame_opt_usage)) {
+               case PARSE_OPT_HELP:
+                       exit(129);
+               case PARSE_OPT_DONE:
+                       if (ctx.argv[0])
+                               dashdash_pos = ctx.cpidx;
+                       goto parse_done;
                }
-               else if (!strcmp("--contents", arg)) {
-                       if (++i >= argc)
-                               usage(blame_usage);
-                       contents_from = argv[i];
-               }
-               else if (!strcmp("--incremental", arg))
-                       incremental = 1;
-               else if (!strcmp("--score-debug", arg))
-                       output_option |= OUTPUT_SHOW_SCORE;
-               else if (!strcmp("-f", arg) ||
-                        !strcmp("--show-name", arg))
-                       output_option |= OUTPUT_SHOW_NAME;
-               else if (!strcmp("-n", arg) ||
-                        !strcmp("--show-number", arg))
-                       output_option |= OUTPUT_SHOW_NUMBER;
-               else if (!strcmp("-p", arg) ||
-                        !strcmp("--porcelain", arg))
-                       output_option |= OUTPUT_PORCELAIN;
-               else if (!strcmp("--", arg)) {
-                       seen_dashdash = 1;
-                       i++;
-                       break;
+
+               if (!strcmp(ctx.argv[0], "--reverse")) {
+                       ctx.argv[0] = "--children";
+                       reverse = 1;
                }
-               else
-                       argv[unk++] = arg;
+               parse_revision_opt(&revs, &ctx, options, blame_opt_usage);
        }
+parse_done:
+       argc = parse_options_end(&ctx);
 
        if (!blame_move_score)
                blame_move_score = BLAME_DEFAULT_MOVE_SCORE;
@@ -2238,115 +2335,59 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
         *
         * The remaining are:
         *
-        * (1) if seen_dashdash, its either
-        *     "-options -- <path>" or
-        *     "-options -- <path> <rev>".
-        *     but the latter is allowed only if there is no
-        *     options that we passed to revision machinery.
+        * (1) if dashdash_pos != 0, its either
+        *     "blame [revisions] -- <path>" or
+        *     "blame -- <path> <rev>"
         *
-        * (2) otherwise, we may have "--" somewhere later and
-        *     might be looking at the first one of multiple 'rev'
-        *     parameters (e.g. " master ^next ^maint -- path").
-        *     See if there is a dashdash first, and give the
-        *     arguments before that to revision machinery.
-        *     After that there must be one 'path'.
+        * (2) otherwise, its one of the two:
+        *     "blame [revisions] <path>"
+        *     "blame <path> <rev>"
         *
-        * (3) otherwise, its one of the three:
-        *     "-options <path> <rev>"
-        *     "-options <rev> <path>"
-        *     "-options <path>"
-        *     but again the first one is allowed only if
-        *     there is no options that we passed to revision
-        *     machinery.
+        * Note that we must strip out <path> from the arguments: we do not
+        * want the path pruning but we may want "bottom" processing.
         */
-
-       if (seen_dashdash) {
-               /* (1) */
-               if (argc <= i)
-                       usage(blame_usage);
-               path = add_prefix(prefix, argv[i]);
-               if (i + 1 == argc - 1) {
-                       if (unk != 1)
-                               usage(blame_usage);
-                       argv[unk++] = argv[i + 1];
+       if (dashdash_pos) {
+               switch (argc - dashdash_pos - 1) {
+               case 2: /* (1b) */
+                       if (argc != 4)
+                               usage_with_options(blame_opt_usage, options);
+                       /* reorder for the new way: <rev> -- <path> */
+                       argv[1] = argv[3];
+                       argv[3] = argv[2];
+                       argv[2] = "--";
+                       /* FALLTHROUGH */
+               case 1: /* (1a) */
+                       path = add_prefix(prefix, argv[--argc]);
+                       argv[argc] = NULL;
+                       break;
+               default:
+                       usage_with_options(blame_opt_usage, options);
                }
-               else if (i + 1 != argc)
-                       /* garbage at end */
-                       usage(blame_usage);
-       }
-       else {
-               int j;
-               for (j = i; !seen_dashdash && j < argc; j++)
-                       if (!strcmp(argv[j], "--"))
-                               seen_dashdash = j;
-               if (seen_dashdash) {
-                       /* (2) */
-                       if (seen_dashdash + 1 != argc - 1)
-                               usage(blame_usage);
-                       path = add_prefix(prefix, argv[seen_dashdash + 1]);
-                       for (j = i; j < seen_dashdash; j++)
-                               argv[unk++] = argv[j];
+       } else {
+               if (argc < 2)
+                       usage_with_options(blame_opt_usage, options);
+               path = add_prefix(prefix, argv[argc - 1]);
+               if (argc == 3 && !has_path_in_work_tree(path)) { /* (2b) */
+                       path = add_prefix(prefix, argv[1]);
+                       argv[1] = argv[2];
                }
-               else {
-                       /* (3) */
-                       if (argc <= i)
-                               usage(blame_usage);
-                       path = add_prefix(prefix, argv[i]);
-                       if (i + 1 == argc - 1) {
-                               final_commit_name = argv[i + 1];
-
-                               /* if (unk == 1) we could be getting
-                                * old-style
-                                */
-                               if (unk == 1 && !has_path_in_work_tree(path)) {
-                                       path = add_prefix(prefix, argv[i + 1]);
-                                       final_commit_name = argv[i];
-                               }
-                       }
-                       else if (i != argc - 1)
-                               usage(blame_usage); /* garbage at end */
+               argv[argc - 1] = "--";
 
-                       setup_work_tree();
-                       if (!has_path_in_work_tree(path))
-                               die("cannot stat path %s: %s",
-                                   path, strerror(errno));
-               }
+               setup_work_tree();
+               if (!has_path_in_work_tree(path))
+                       die("cannot stat path %s: %s", path, strerror(errno));
        }
 
-       if (final_commit_name)
-               argv[unk++] = final_commit_name;
-
-       /*
-        * Now we got rev and path.  We do not want the path pruning
-        * but we may want "bottom" processing.
-        */
-       argv[unk++] = "--"; /* terminate the rev name */
-       argv[unk] = NULL;
-
-       init_revisions(&revs, NULL);
-       setup_revisions(unk, argv, &revs, NULL);
+       setup_revisions(argc, argv, &revs, NULL);
        memset(&sb, 0, sizeof(sb));
 
-       /*
-        * There must be one and only one positive commit in the
-        * revs->pending array.
-        */
-       for (i = 0; i < revs.pending.nr; i++) {
-               struct object *obj = revs.pending.objects[i].item;
-               if (obj->flags & UNINTERESTING)
-                       continue;
-               while (obj->type == OBJ_TAG)
-                       obj = deref_tag(obj, NULL, 0);
-               if (obj->type != OBJ_COMMIT)
-                       die("Non commit %s?",
-                           revs.pending.objects[i].name);
-               if (sb.final)
-                       die("More than one commit to dig from %s and %s?",
-                           revs.pending.objects[i].name,
-                           final_commit_name);
-               sb.final = (struct commit *) obj;
-               final_commit_name = revs.pending.objects[i].name;
-       }
+       sb.revs = &revs;
+       if (!reverse)
+               final_commit_name = prepare_final(&sb);
+       else if (contents_from)
+               die("--contents and --children do not blend well.");
+       else
+               final_commit_name = prepare_initial(&sb);
 
        if (!sb.final) {
                /*
@@ -2425,7 +2466,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
        if (!incremental)
                setup_pager();
 
-       assign_blame(&sb, &revs, opt);
+       assign_blame(&sb, opt);
 
        if (incremental)
                return 0;
index d279702ba9a90faa020fa2f102d595cec082be21..ff71f3d8a6dd784ae08f89b8a98136e4cd369295 100644 (file)
@@ -282,6 +282,21 @@ static int ref_cmp(const void *r1, const void *r2)
        return strcmp(c1->name, c2->name);
 }
 
+static void fill_tracking_info(char *stat, const char *branch_name)
+{
+       int ours, theirs;
+       struct branch *branch = branch_get(branch_name);
+
+       if (!stat_tracking_info(branch, &ours, &theirs) || (!ours && !theirs))
+               return;
+       if (!ours)
+               sprintf(stat, "[behind %d] ", theirs);
+       else if (!theirs)
+               sprintf(stat, "[ahead %d] ", ours);
+       else
+               sprintf(stat, "[ahead %d, behind %d] ", ours, theirs);
+}
+
 static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
                           int abbrev, int current)
 {
@@ -310,8 +325,10 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
        if (verbose) {
                struct strbuf subject;
                const char *sub = " **** invalid ref ****";
+               char stat[128];
 
                strbuf_init(&subject, 0);
+               stat[0] = '\0';
 
                commit = lookup_commit(item->sha1);
                if (commit && !parse_commit(commit)) {
@@ -319,10 +336,15 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
                                            &subject, 0, NULL, NULL, 0, 0);
                        sub = subject.buf;
                }
-               printf("%c %s%-*s%s %s %s\n", c, branch_get_color(color),
+
+               if (item->kind == REF_LOCAL_BRANCH)
+                       fill_tracking_info(stat, item->name);
+
+               printf("%c %s%-*s%s %s %s%s\n", c, branch_get_color(color),
                       maxwidth, item->name,
                       branch_get_color(COLOR_BRANCH_RESET),
-                      find_unique_abbrev(item->sha1, abbrev), sub);
+                      find_unique_abbrev(item->sha1, abbrev),
+                      stat, sub);
                strbuf_release(&subject);
        } else {
                printf("%c %s%s%s\n", c, branch_get_color(color), item->name,
index 93ea69bfaa083f49a6e808c7317ea1910b29c847..d6641c2c562c6b35bfed1cd3053945b460472581 100644 (file)
@@ -305,97 +305,15 @@ static int merge_working_tree(struct checkout_opts *opts,
        return 0;
 }
 
-static void report_tracking(struct branch_info *new, struct checkout_opts *opts)
+static void report_tracking(struct branch_info *new)
 {
-       /*
-        * We have switched to a new branch; is it building on
-        * top of another branch, and if so does that other branch
-        * have changes we do not have yet?
-        */
-       char *base;
-       unsigned char sha1[20];
-       struct commit *ours, *theirs;
-       char symmetric[84];
-       struct rev_info revs;
-       const char *rev_argv[10];
-       int rev_argc;
-       int num_ours, num_theirs;
-       const char *remote_msg;
+       struct strbuf sb = STRBUF_INIT;
        struct branch *branch = branch_get(new->name);
 
-       /*
-        * Nothing to report unless we are marked to build on top of
-        * somebody else.
-        */
-       if (!branch || !branch->merge || !branch->merge[0] || !branch->merge[0]->dst)
-               return;
-
-       /*
-        * If what we used to build on no longer exists, there is
-        * nothing to report.
-        */
-       base = branch->merge[0]->dst;
-       if (!resolve_ref(base, sha1, 1, NULL))
+       if (!format_tracking_info(branch, &sb))
                return;
-
-       theirs = lookup_commit(sha1);
-       ours = new->commit;
-       if (!hashcmp(sha1, ours->object.sha1))
-               return; /* we are the same */
-
-       /* Run "rev-list --left-right ours...theirs" internally... */
-       rev_argc = 0;
-       rev_argv[rev_argc++] = NULL;
-       rev_argv[rev_argc++] = "--left-right";
-       rev_argv[rev_argc++] = symmetric;
-       rev_argv[rev_argc++] = "--";
-       rev_argv[rev_argc] = NULL;
-
-       strcpy(symmetric, sha1_to_hex(ours->object.sha1));
-       strcpy(symmetric + 40, "...");
-       strcpy(symmetric + 43, sha1_to_hex(theirs->object.sha1));
-
-       init_revisions(&revs, NULL);
-       setup_revisions(rev_argc, rev_argv, &revs, NULL);
-       prepare_revision_walk(&revs);
-
-       /* ... and count the commits on each side. */
-       num_ours = 0;
-       num_theirs = 0;
-       while (1) {
-               struct commit *c = get_revision(&revs);
-               if (!c)
-                       break;
-               if (c->object.flags & SYMMETRIC_LEFT)
-                       num_ours++;
-               else
-                       num_theirs++;
-       }
-
-       if (!prefixcmp(base, "refs/remotes/")) {
-               remote_msg = " remote";
-               base += strlen("refs/remotes/");
-       } else {
-               remote_msg = "";
-       }
-
-       if (!num_theirs)
-               printf("Your branch is ahead of the tracked%s branch '%s' "
-                      "by %d commit%s.\n",
-                      remote_msg, base,
-                      num_ours, (num_ours == 1) ? "" : "s");
-       else if (!num_ours)
-               printf("Your branch is behind the tracked%s branch '%s' "
-                      "by %d commit%s,\n"
-                      "and can be fast-forwarded.\n",
-                      remote_msg, base,
-                      num_theirs, (num_theirs == 1) ? "" : "s");
-       else
-               printf("Your branch and the tracked%s branch '%s' "
-                      "have diverged,\nand respectively "
-                      "have %d and %d different commit(s) each.\n",
-                      remote_msg, base,
-                      num_ours, num_theirs);
+       fputs(sb.buf, stdout);
+       strbuf_release(&sb);
 }
 
 static void update_refs_for_switch(struct checkout_opts *opts,
@@ -441,7 +359,7 @@ static void update_refs_for_switch(struct checkout_opts *opts,
        remove_branch_state();
        strbuf_release(&msg);
        if (!opts->quiet && (new->path || !strcmp(new->name, "HEAD")))
-               report_tracking(new, opts);
+               report_tracking(new);
 }
 
 static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
index 7ee82752699f837f89fcbea06b1a20aa286ae6cb..ec362096003be447f1d84f8203d37e577911f4f9 100644 (file)
@@ -18,6 +18,7 @@
 #include "transport.h"
 #include "strbuf.h"
 #include "dir.h"
+#include "pack-refs.h"
 
 /*
  * Overall FIXMEs:
@@ -321,8 +322,11 @@ static struct ref *write_remote_refs(const struct ref *refs,
        get_fetch_map(refs, tag_refspec, &tail, 0);
 
        for (r = local_refs; r; r = r->next)
-               update_ref(reflog,
-                          r->peer_ref->name, r->old_sha1, NULL, 0, DIE_ON_ERR);
+               add_extra_ref(r->peer_ref->name, r->old_sha1, 0);
+
+       pack_refs(PACK_REFS_ALL);
+       clear_extra_refs();
+
        return local_refs;
 }
 
index e5e4bdbe862b23aafe932da411f597b0f3b5c997..3881f6c2f56f317726a688e44b98806987036999 100644 (file)
@@ -24,26 +24,20 @@ static void check_valid(unsigned char *sha1, enum object_type expect)
                    typename(expect));
 }
 
-/*
- * Having more than two parents is not strange at all, and this is
- * how multi-way merges are represented.
- */
-#define MAXPARENT (16)
-static unsigned char parent_sha1[MAXPARENT][20];
-
 static const char commit_tree_usage[] = "git-commit-tree <sha1> [-p <sha1>]* < changelog";
 
-static int new_parent(int idx)
+static void new_parent(struct commit *parent, struct commit_list **parents_p)
 {
-       int i;
-       unsigned char *sha1 = parent_sha1[idx];
-       for (i = 0; i < idx; i++) {
-               if (!hashcmp(parent_sha1[i], sha1)) {
+       unsigned char *sha1 = parent->object.sha1;
+       struct commit_list *parents;
+       for (parents = *parents_p; parents; parents = parents->next) {
+               if (parents->item == parent) {
                        error("duplicate parent %s ignored", sha1_to_hex(sha1));
-                       return 0;
+                       return;
                }
+               parents_p = &parents->next;
        }
-       return 1;
+       commit_list_insert(parent, parents_p);
 }
 
 static const char commit_utf8_warn[] =
@@ -54,7 +48,7 @@ static const char commit_utf8_warn[] =
 int cmd_commit_tree(int argc, const char **argv, const char *prefix)
 {
        int i;
-       int parents = 0;
+       struct commit_list *parents = NULL;
        unsigned char tree_sha1[20];
        unsigned char commit_sha1[20];
        struct strbuf buffer;
@@ -69,18 +63,16 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
 
        check_valid(tree_sha1, OBJ_TREE);
        for (i = 2; i < argc; i += 2) {
+               unsigned char sha1[20];
                const char *a, *b;
                a = argv[i]; b = argv[i+1];
                if (!b || strcmp(a, "-p"))
                        usage(commit_tree_usage);
 
-               if (parents >= MAXPARENT)
-                       die("Too many parents (%d max)", MAXPARENT);
-               if (get_sha1(b, parent_sha1[parents]))
+               if (get_sha1(b, sha1))
                        die("Not a valid object name %s", b);
-               check_valid(parent_sha1[parents], OBJ_COMMIT);
-               if (new_parent(parents))
-                       parents++;
+               check_valid(sha1, OBJ_COMMIT);
+               new_parent(lookup_commit(sha1), &parents);
        }
 
        /* Not having i18n.commitencoding is the same as having utf-8 */
@@ -94,8 +86,13 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
         * different order of parents will be a _different_ changeset even
         * if everything else stays the same.
         */
-       for (i = 0; i < parents; i++)
-               strbuf_addf(&buffer, "parent %s\n", sha1_to_hex(parent_sha1[i]));
+       while (parents) {
+               struct commit_list *next = parents->next;
+               strbuf_addf(&buffer, "parent %s\n",
+                       sha1_to_hex(parents->item->object.sha1));
+               free(parents);
+               parents = next;
+       }
 
        /* Person/date information */
        strbuf_addf(&buffer, "author %s\n", git_author_info(IDENT_ERROR_ON_NO_NAME));
index bcbea3893b6ddb40388f5a5ab49b022af5a88df1..745c11e7735ffcb070683d1af607b4ad85f48e23 100644 (file)
@@ -50,7 +50,8 @@ static const char *template_file;
 static char *edit_message, *use_message;
 static char *author_name, *author_email, *author_date;
 static int all, edit_flag, also, interactive, only, amend, signoff;
-static int quiet, verbose, untracked_files, no_verify, allow_empty;
+static int quiet, verbose, no_verify, allow_empty;
+static char *untracked_files_arg;
 /*
  * The default commit message cleanup mode will remove the lines
  * beginning with # (shell comments) and leading and trailing
@@ -103,7 +104,7 @@ static struct option builtin_commit_options[] = {
        OPT_BOOLEAN('o', "only", &only, "commit only specified files"),
        OPT_BOOLEAN('n', "no-verify", &no_verify, "bypass pre-commit hook"),
        OPT_BOOLEAN(0, "amend", &amend, "amend previous commit"),
-       OPT_BOOLEAN('u', "untracked-files", &untracked_files, "show all untracked files"),
+       { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, "mode", "show untracked files, optional modes: all, normal, no. (Default: all)", PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
        OPT_BOOLEAN(0, "allow-empty", &allow_empty, "ok to record an empty change"),
        OPT_STRING(0, "cleanup", &cleanup_arg, "default", "how to strip spaces and #comments from message"),
 
@@ -348,7 +349,7 @@ static int run_status(FILE *fp, const char *index_file, const char *prefix, int
                s.reference = "HEAD^1";
        }
        s.verbose = verbose;
-       s.untracked = untracked_files;
+       s.untracked = (show_untracked_files == SHOW_ALL_UNTRACKED_FILES);
        s.index_file = index_file;
        s.fp = fp;
        s.nowarn = nowarn;
@@ -503,7 +504,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix)
 
        fp = fopen(git_path(commit_editmsg), "w");
        if (fp == NULL)
-               die("could not open %s", git_path(commit_editmsg));
+               die("could not open %s: %s",
+                   git_path(commit_editmsg), strerror(errno));
 
        if (cleanup_mode != CLEANUP_NONE)
                stripspace(&sb, 0);
@@ -796,6 +798,17 @@ static int parse_and_validate_options(int argc, const char *argv[],
        else
                die("Invalid cleanup mode %s", cleanup_arg);
 
+       if (!untracked_files_arg)
+               ; /* default already initialized */
+       else if (!strcmp(untracked_files_arg, "no"))
+               show_untracked_files = SHOW_NO_UNTRACKED_FILES;
+       else if (!strcmp(untracked_files_arg, "normal"))
+               show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
+       else if (!strcmp(untracked_files_arg, "all"))
+               show_untracked_files = SHOW_ALL_UNTRACKED_FILES;
+       else
+               die("Invalid untracked files mode '%s'", untracked_files_arg);
+
        if (all && argc > 0)
                die("Paths with -a does not make sense.");
        else if (interactive && argc > 0)
index 3a441ef64868b7c477ee9c49546ef1cb39e5acad..39f63d7b10f93a0a021d8b9af9fdec46ed0333f6 100644 (file)
@@ -81,12 +81,10 @@ static int get_value(const char* key_, const char* regex_)
        char *global = NULL, *repo_config = NULL;
        const char *system_wide = NULL, *local;
 
-       local = getenv(CONFIG_ENVIRONMENT);
+       local = config_exclusive_filename;
        if (!local) {
                const char *home = getenv("HOME");
-               local = getenv(CONFIG_LOCAL_ENVIRONMENT);
-               if (!local)
-                       local = repo_config = xstrdup(git_path("config"));
+               local = repo_config = xstrdup(git_path("config"));
                if (git_config_global() && home)
                        global = xstrdup(mkpath("%s/.gitconfig", home));
                if (git_config_system())
@@ -289,6 +287,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)
        char* value;
        const char *file = setup_git_directory_gently(&nongit);
 
+       config_exclusive_filename = getenv(CONFIG_ENVIRONMENT);
+
        while (1 < argc) {
                if (!strcmp(argv[1], "--int"))
                        type = T_INT;
@@ -309,14 +309,13 @@ int cmd_config(int argc, const char **argv, const char *prefix)
                        char *home = getenv("HOME");
                        if (home) {
                                char *user_config = xstrdup(mkpath("%s/.gitconfig", home));
-                               setenv(CONFIG_ENVIRONMENT, user_config, 1);
-                               free(user_config);
+                               config_exclusive_filename = user_config;
                        } else {
                                die("$HOME not set");
                        }
                }
                else if (!strcmp(argv[1], "--system"))
-                       setenv(CONFIG_ENVIRONMENT, git_etc_gitconfig(), 1);
+                       config_exclusive_filename = git_etc_gitconfig();
                else if (!strcmp(argv[1], "--file") || !strcmp(argv[1], "-f")) {
                        if (argc < 3)
                                usage(git_config_set_usage);
@@ -325,7 +324,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
                                                       argv[2]);
                        else
                                file = argv[2];
-                       setenv(CONFIG_ENVIRONMENT, file, 1);
+                       config_exclusive_filename = file;
                        argc--;
                        argv++;
                }
index d0a462ff8b3760a4a21d9a72339a02891a5b4aef..75132bacfac08591ccb70eca0260be23d0e04a92 100644 (file)
@@ -56,10 +56,24 @@ static int has_unshown_parent(struct commit *commit)
 }
 
 /* Since intptr_t is C99, we do not use it here */
-static void mark_object(struct object *object)
+static inline uint32_t *mark_to_ptr(uint32_t mark)
 {
-       last_idnum++;
-       add_decoration(&idnums, object, ((uint32_t *)NULL) + last_idnum);
+       return ((uint32_t *)NULL) + mark;
+}
+
+static inline uint32_t ptr_to_mark(void * mark)
+{
+       return (uint32_t *)mark - (uint32_t *)NULL;
+}
+
+static inline void mark_object(struct object *object, uint32_t mark)
+{
+       add_decoration(&idnums, object, mark_to_ptr(mark));
+}
+
+static inline void mark_next_object(struct object *object)
+{
+       mark_object(object, ++last_idnum);
 }
 
 static int get_object_mark(struct object *object)
@@ -67,7 +81,7 @@ static int get_object_mark(struct object *object)
        void *decoration = lookup_decoration(&idnums, object);
        if (!decoration)
                return 0;
-       return (uint32_t *)decoration - (uint32_t *)NULL;
+       return ptr_to_mark(decoration);
 }
 
 static void show_progress(void)
@@ -100,9 +114,9 @@ static void handle_object(const unsigned char *sha1)
        if (!buf)
                die ("Could not read blob %s", sha1_to_hex(sha1));
 
-       mark_object(object);
+       mark_next_object(object);
 
-       printf("blob\nmark :%d\ndata %lu\n", last_idnum, size);
+       printf("blob\nmark :%"PRIu32"\ndata %lu\n", last_idnum, size);
        if (size && fwrite(buf, size, 1, stdout) != 1)
                die ("Could not write blob %s", sha1_to_hex(sha1));
        printf("\n");
@@ -185,12 +199,12 @@ static void handle_commit(struct commit *commit, struct rev_info *rev)
        for (i = 0; i < diff_queued_diff.nr; i++)
                handle_object(diff_queued_diff.queue[i]->two->sha1);
 
-       mark_object(&commit->object);
+       mark_next_object(&commit->object);
        if (!is_encoding_utf8(encoding))
                reencoded = reencode_string(message, "UTF-8", encoding);
        if (!commit->parents)
                printf("reset %s\n", (const char*)commit->util);
-       printf("commit %s\nmark :%d\n%.*s\n%.*s\ndata %u\n%s",
+       printf("commit %s\nmark :%"PRIu32"\n%.*s\n%.*s\ndata %u\n%s",
               (const char *)commit->util, last_idnum,
               (int)(author_end - author), author,
               (int)(committer_end - committer), committer,
@@ -354,18 +368,85 @@ static void handle_tags_and_duplicates(struct path_list *extra_refs)
        }
 }
 
+static void export_marks(char *file)
+{
+       unsigned int i;
+       uint32_t mark;
+       struct object_decoration *deco = idnums.hash;
+       FILE *f;
+
+       f = fopen(file, "w");
+       if (!f)
+               error("Unable to open marks file %s for writing", file);
+
+       for (i = 0; i < idnums.size; i++) {
+               if (deco->base && deco->base->type == 1) {
+                       mark = ptr_to_mark(deco->decoration);
+                       fprintf(f, ":%u %s\n", mark, sha1_to_hex(deco->base->sha1));
+               }
+               deco++;
+       }
+
+       if (ferror(f) || fclose(f))
+               error("Unable to write marks file %s.", file);
+}
+
+static void import_marks(char *input_file)
+{
+       char line[512];
+       FILE *f = fopen(input_file, "r");
+       if (!f)
+               die("cannot read %s: %s", input_file, strerror(errno));
+
+       while (fgets(line, sizeof(line), f)) {
+               uint32_t mark;
+               char *line_end, *mark_end;
+               unsigned char sha1[20];
+               struct object *object;
+
+               line_end = strchr(line, '\n');
+               if (line[0] != ':' || !line_end)
+                       die("corrupt mark line: %s", line);
+               *line_end = '\0';
+
+               mark = strtoumax(line + 1, &mark_end, 10);
+               if (!mark || mark_end == line + 1
+                       || *mark_end != ' ' || get_sha1(mark_end + 1, sha1))
+                       die("corrupt mark line: %s", line);
+
+               object = parse_object(sha1);
+               if (!object)
+                       die ("Could not read blob %s", sha1_to_hex(sha1));
+
+               if (object->flags & SHOWN)
+                       error("Object %s already has a mark", sha1);
+
+               mark_object(object, mark);
+               if (last_idnum < mark)
+                       last_idnum = mark;
+
+               object->flags |= SHOWN;
+       }
+       fclose(f);
+}
+
 int cmd_fast_export(int argc, const char **argv, const char *prefix)
 {
        struct rev_info revs;
        struct object_array commits = { 0, 0, NULL };
        struct path_list extra_refs = { NULL, 0, 0, 0 };
        struct commit *commit;
+       char *export_filename = NULL, *import_filename = NULL;
        struct option options[] = {
                OPT_INTEGER(0, "progress", &progress,
                            "show progress after <n> objects"),
                OPT_CALLBACK(0, "signed-tags", &signed_tag_mode, "mode",
                             "select handling of signed tags",
                             parse_opt_signed_tag_mode),
+               OPT_STRING(0, "export-marks", &export_filename, "FILE",
+                            "Dump marks to this file"),
+               OPT_STRING(0, "import-marks", &import_filename, "FILE",
+                            "Import marks from this file"),
                OPT_END()
        };
 
@@ -378,6 +459,9 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
        if (argc > 1)
                usage_with_options (fast_export_usage, options);
 
+       if (import_filename)
+               import_marks(import_filename);
+
        get_tags_and_duplicates(&revs.pending, &extra_refs);
 
        if (prepare_revision_walk(&revs))
@@ -400,5 +484,8 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
 
        handle_tags_and_duplicates(&extra_refs);
 
+       if (export_filename)
+               export_marks(export_filename);
+
        return 0;
 }
index de1e8d1365769c7c841749901f705c0b6a78eab3..1ea704063928d77fe1048b1abde35e42fcfb20e4 100644 (file)
@@ -309,7 +309,8 @@ done:
                }
                flushes--;
        }
-       return retval;
+       /* it is no error to fetch into a completely empty repo */
+       return count ? retval : 0;
 }
 
 static struct commit_list *complete;
@@ -519,7 +520,8 @@ static int get_pack(int xd[2], char **pack_lockfile)
 
                if (read_pack_header(demux.out, &header))
                        die("protocol error: bad pack header");
-               snprintf(hdr_arg, sizeof(hdr_arg), "--pack_header=%u,%u",
+               snprintf(hdr_arg, sizeof(hdr_arg),
+                        "--pack_header=%"PRIu32",%"PRIu32,
                         ntohl(header.hdr_version), ntohl(header.hdr_entries));
                if (ntohl(header.hdr_entries) < unpack_limit)
                        do_keep = 0;
@@ -820,5 +822,6 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args,
                }
        }
 
+       reprepare_packed_git();
        return ref_cpy;
 }
index 78a6e1ff7101f7bb616365e5d4c9d9cf7f8963ae..b0f9648f862248d1b985f31406b8f3de26b47aff 100644 (file)
@@ -585,7 +585,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
                prepare_packed_git();
                for (p = packed_git; p; p = p->next)
                        /* verify gives error messages itself */
-                       verify_pack(p, 0);
+                       verify_pack(p);
 
                for (p = packed_git; p; p = p->next) {
                        uint32_t j, num;
index fa6e8f90a4d54eb07f2af80620e35e617c94d605..962aa34c8ea3f603abcbf7f8f94cf6914105cbef 100644 (file)
@@ -960,7 +960,7 @@ static int mailinfo(FILE *in, FILE *out, int ks, const char *encoding,
 }
 
 static const char mailinfo_usage[] =
-       "git-mailinfo [-k] [-u | --encoding=<encoding>] msg patch <mail >info";
+       "git-mailinfo [-k] [-u | --encoding=<encoding> | -n] msg patch <mail >info";
 
 int cmd_mailinfo(int argc, const char **argv, const char *prefix)
 {
index ae2b4cb21bf4e691a044e2ace3cdd4861562ceca..e8cbe678ecdc0863ebe92e6499dd2b1eacf77db6 100644 (file)
@@ -9,7 +9,7 @@
 #include "path-list.h"
 
 static const char git_mailsplit_usage[] =
-"git-mailsplit [-d<prec>] [-f<n>] [-b] -o<directory> <mbox>|<Maildir>...";
+"git-mailsplit [-d<prec>] [-f<n>] [-b] -o<directory> [<mbox>|<Maildir>...]";
 
 static int is_from_line(const char *line, int len)
 {
index 447d492dbbfb578b8903293fa1d2a988eecfefac..2dadec1630c266bbaf42e84810f7059ed5c43b1e 100644 (file)
@@ -209,28 +209,6 @@ static int check_pack_inflate(struct packed_git *p,
                stream.total_in == len) ? 0 : -1;
 }
 
-static int check_pack_crc(struct packed_git *p, struct pack_window **w_curs,
-                         off_t offset, off_t len, unsigned int nr)
-{
-       const uint32_t *index_crc;
-       uint32_t data_crc = crc32(0, Z_NULL, 0);
-
-       do {
-               unsigned int avail;
-               void *data = use_pack(p, w_curs, offset, &avail);
-               if (avail > len)
-                       avail = len;
-               data_crc = crc32(data_crc, data, avail);
-               offset += avail;
-               len -= avail;
-       } while (len);
-
-       index_crc = p->index_data;
-       index_crc += 2 + 256 + p->num_objects * (20/4) + nr;
-
-       return data_crc != ntohl(*index_crc);
-}
-
 static void copy_pack_data(struct sha1file *f,
                struct packed_git *p,
                struct pack_window **w_curs,
@@ -590,7 +568,8 @@ static void write_pack_file(void)
        free(written_list);
        stop_progress(&progress_state);
        if (written != nr_result)
-               die("wrote %u objects while expecting %u", written, nr_result);
+               die("wrote %"PRIu32" objects while expecting %"PRIu32,
+                       written, nr_result);
        /*
         * We have scanned through [0 ... i).  Since we have written
         * the correct number of objects,  the remaining [i ... nr_objects)
@@ -602,7 +581,8 @@ static void write_pack_file(void)
                j += !e->idx.offset && !e->preferred_base;
        }
        if (j)
-               die("wrote %u objects as expected but %u unwritten", written, j);
+               die("wrote %"PRIu32" objects as expected but %"PRIu32
+                       " unwritten", written, j);
 }
 
 static int locate_object_entry_hash(const unsigned char *sha1)
@@ -1148,8 +1128,6 @@ static void get_object_details(void)
                sorted_by_offset[i] = objects + i;
        qsort(sorted_by_offset, nr_objects, sizeof(*sorted_by_offset), pack_offset_sort);
 
-       init_pack_revindex();
-
        for (i = 0; i < nr_objects; i++)
                check_object(sorted_by_offset[i]);
 
@@ -1718,7 +1696,8 @@ static int add_ref_tag(const char *path, const unsigned char *sha1, int flag, vo
 static void prepare_pack(int window, int depth)
 {
        struct object_entry **delta_list;
-       uint32_t i, n, nr_deltas;
+       uint32_t i, nr_deltas;
+       unsigned n;
 
        get_object_details();
 
@@ -1809,7 +1788,8 @@ static int git_pack_config(const char *k, const char *v, void *cb)
        if (!strcmp(k, "pack.indexversion")) {
                pack_idx_default_version = git_config_int(k, v);
                if (pack_idx_default_version > 2)
-                       die("bad pack.indexversion=%d", pack_idx_default_version);
+                       die("bad pack.indexversion=%"PRIu32,
+                               pack_idx_default_version);
                return 0;
        }
        if (!strcmp(k, "pack.packsizelimit")) {
@@ -2243,7 +2223,8 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
                prepare_pack(window, depth);
        write_pack_file();
        if (progress)
-               fprintf(stderr, "Total %u (delta %u), reused %u (delta %u)\n",
+               fprintf(stderr, "Total %"PRIu32" (delta %"PRIu32"),"
+                       " reused %"PRIu32" (delta %"PRIu32")\n",
                        written, written_delta, reused, reused_delta);
        return 0;
 }
index 1aaa76dd1fe42f56e25dac6c3ca0e787eb7b005e..ff90aefa1c1818b90391223c8cf6971923207e97 100644 (file)
@@ -1,125 +1,6 @@
-#include "builtin.h"
 #include "cache.h"
-#include "refs.h"
-#include "object.h"
-#include "tag.h"
 #include "parse-options.h"
-
-struct ref_to_prune {
-       struct ref_to_prune *next;
-       unsigned char sha1[20];
-       char name[FLEX_ARRAY];
-};
-
-#define PACK_REFS_PRUNE        0x0001
-#define PACK_REFS_ALL  0x0002
-
-struct pack_refs_cb_data {
-       unsigned int flags;
-       struct ref_to_prune *ref_to_prune;
-       FILE *refs_file;
-};
-
-static int do_not_prune(int flags)
-{
-       /* If it is already packed or if it is a symref,
-        * do not prune it.
-        */
-       return (flags & (REF_ISSYMREF|REF_ISPACKED));
-}
-
-static int handle_one_ref(const char *path, const unsigned char *sha1,
-                         int flags, void *cb_data)
-{
-       struct pack_refs_cb_data *cb = cb_data;
-       int is_tag_ref;
-
-       /* Do not pack the symbolic refs */
-       if ((flags & REF_ISSYMREF))
-               return 0;
-       is_tag_ref = !prefixcmp(path, "refs/tags/");
-
-       /* ALWAYS pack refs that were already packed or are tags */
-       if (!(cb->flags & PACK_REFS_ALL) && !is_tag_ref && !(flags & REF_ISPACKED))
-               return 0;
-
-       fprintf(cb->refs_file, "%s %s\n", sha1_to_hex(sha1), path);
-       if (is_tag_ref) {
-               struct object *o = parse_object(sha1);
-               if (o->type == OBJ_TAG) {
-                       o = deref_tag(o, path, 0);
-                       if (o)
-                               fprintf(cb->refs_file, "^%s\n",
-                                       sha1_to_hex(o->sha1));
-               }
-       }
-
-       if ((cb->flags & PACK_REFS_PRUNE) && !do_not_prune(flags)) {
-               int namelen = strlen(path) + 1;
-               struct ref_to_prune *n = xcalloc(1, sizeof(*n) + namelen);
-               hashcpy(n->sha1, sha1);
-               strcpy(n->name, path);
-               n->next = cb->ref_to_prune;
-               cb->ref_to_prune = n;
-       }
-       return 0;
-}
-
-/* make sure nobody touched the ref, and unlink */
-static void prune_ref(struct ref_to_prune *r)
-{
-       struct ref_lock *lock = lock_ref_sha1(r->name + 5, r->sha1);
-
-       if (lock) {
-               unlink(git_path("%s", r->name));
-               unlock_ref(lock);
-       }
-}
-
-static void prune_refs(struct ref_to_prune *r)
-{
-       while (r) {
-               prune_ref(r);
-               r = r->next;
-       }
-}
-
-static struct lock_file packed;
-
-static int pack_refs(unsigned int flags)
-{
-       int fd;
-       struct pack_refs_cb_data cbdata;
-
-       memset(&cbdata, 0, sizeof(cbdata));
-       cbdata.flags = flags;
-
-       fd = hold_lock_file_for_update(&packed, git_path("packed-refs"), 1);
-       cbdata.refs_file = fdopen(fd, "w");
-       if (!cbdata.refs_file)
-               die("unable to create ref-pack file structure (%s)",
-                   strerror(errno));
-
-       /* perhaps other traits later as well */
-       fprintf(cbdata.refs_file, "# pack-refs with: peeled \n");
-
-       for_each_ref(handle_one_ref, &cbdata);
-       if (ferror(cbdata.refs_file))
-               die("failed to write ref-pack file");
-       if (fflush(cbdata.refs_file) || fsync(fd) || fclose(cbdata.refs_file))
-               die("failed to write ref-pack file (%s)", strerror(errno));
-       /*
-        * Since the lock file was fdopen()'ed and then fclose()'ed above,
-        * assign -1 to the lock file descriptor so that commit_lock_file()
-        * won't try to close() it.
-        */
-       packed.fd = -1;
-       if (commit_lock_file(&packed) < 0)
-               die("unable to overwrite old ref-pack file (%s)", strerror(errno));
-       if (cbdata.flags & PACK_REFS_PRUNE)
-               prune_refs(cbdata.ref_to_prune);
-       return 0;
-}
+#include "pack-refs.h"
 
 static char const * const pack_refs_usage[] = {
        "git-pack-refs [options]",
index b151e24ff94e06840db7e57014fe4a73ea811575..125d455b97ca499806ff417871ab6ce7aad922c5 100644 (file)
@@ -269,7 +269,9 @@ static int expire_reflog(const char *ref, const unsigned char *sha1, int unused,
        int status = 0;
 
        memset(&cb, 0, sizeof(cb));
-       /* we take the lock for the ref itself to prevent it from
+
+       /*
+        * we take the lock for the ref itself to prevent it from
         * getting updated.
         */
        lock = lock_any_ref_for_update(ref, sha1, 0);
@@ -331,21 +333,130 @@ static int collect_reflog(const char *ref, const unsigned char *sha1, int unused
        return 0;
 }
 
-static int reflog_expire_config(const char *var, const char *value, void *cb)
+static struct reflog_expire_cfg {
+       struct reflog_expire_cfg *next;
+       unsigned long expire_total;
+       unsigned long expire_unreachable;
+       size_t len;
+       char pattern[FLEX_ARRAY];
+} *reflog_expire_cfg, **reflog_expire_cfg_tail;
+
+static struct reflog_expire_cfg *find_cfg_ent(const char *pattern, size_t len)
 {
-       if (!strcmp(var, "gc.reflogexpire")) {
-               if (!value)
-                       config_error_nonbool(var);
-               default_reflog_expire = approxidate(value);
+       struct reflog_expire_cfg *ent;
+
+       if (!reflog_expire_cfg_tail)
+               reflog_expire_cfg_tail = &reflog_expire_cfg;
+
+       for (ent = reflog_expire_cfg; ent; ent = ent->next)
+               if (ent->len == len &&
+                   !memcmp(ent->pattern, pattern, len))
+                       return ent;
+
+       ent = xcalloc(1, (sizeof(*ent) + len));
+       memcpy(ent->pattern, pattern, len);
+       ent->len = len;
+       *reflog_expire_cfg_tail = ent;
+       reflog_expire_cfg_tail = &(ent->next);
+       return ent;
+}
+
+static int parse_expire_cfg_value(const char *var, const char *value, unsigned long *expire)
+{
+       if (!value)
+               return config_error_nonbool(var);
+       if (!strcmp(value, "never") || !strcmp(value, "false")) {
+               *expire = 0;
                return 0;
        }
-       if (!strcmp(var, "gc.reflogexpireunreachable")) {
-               if (!value)
-                       config_error_nonbool(var);
-               default_reflog_expire_unreachable = approxidate(value);
+       *expire = approxidate(value);
+       return 0;
+}
+
+/* expiry timer slot */
+#define EXPIRE_TOTAL   01
+#define EXPIRE_UNREACH 02
+
+static int reflog_expire_config(const char *var, const char *value, void *cb)
+{
+       const char *lastdot = strrchr(var, '.');
+       unsigned long expire;
+       int slot;
+       struct reflog_expire_cfg *ent;
+
+       if (!lastdot || prefixcmp(var, "gc."))
+               return git_default_config(var, value, cb);
+
+       if (!strcmp(lastdot, ".reflogexpire")) {
+               slot = EXPIRE_TOTAL;
+               if (parse_expire_cfg_value(var, value, &expire))
+                       return -1;
+       } else if (!strcmp(lastdot, ".reflogexpireunreachable")) {
+               slot = EXPIRE_UNREACH;
+               if (parse_expire_cfg_value(var, value, &expire))
+                       return -1;
+       } else
+               return git_default_config(var, value, cb);
+
+       if (lastdot == var + 2) {
+               switch (slot) {
+               case EXPIRE_TOTAL:
+                       default_reflog_expire = expire;
+                       break;
+               case EXPIRE_UNREACH:
+                       default_reflog_expire_unreachable = expire;
+                       break;
+               }
                return 0;
        }
-       return git_default_config(var, value, cb);
+
+       ent = find_cfg_ent(var + 3, lastdot - (var+3));
+       if (!ent)
+               return -1;
+       switch (slot) {
+       case EXPIRE_TOTAL:
+               ent->expire_total = expire;
+               break;
+       case EXPIRE_UNREACH:
+               ent->expire_unreachable = expire;
+               break;
+       }
+       return 0;
+}
+
+static void set_reflog_expiry_param(struct cmd_reflog_expire_cb *cb, int slot, const char *ref)
+{
+       struct reflog_expire_cfg *ent;
+
+       if (slot == (EXPIRE_TOTAL|EXPIRE_UNREACH))
+               return; /* both given explicitly -- nothing to tweak */
+
+       for (ent = reflog_expire_cfg; ent; ent = ent->next) {
+               if (!fnmatch(ent->pattern, ref, 0)) {
+                       if (!(slot & EXPIRE_TOTAL))
+                               cb->expire_total = ent->expire_total;
+                       if (!(slot & EXPIRE_UNREACH))
+                               cb->expire_unreachable = ent->expire_unreachable;
+                       return;
+               }
+       }
+
+       /*
+        * If unconfigured, make stash never expire
+        */
+       if (!strcmp(ref, "refs/stash")) {
+               if (!(slot & EXPIRE_TOTAL))
+                       cb->expire_total = 0;
+               if (!(slot & EXPIRE_UNREACH))
+                       cb->expire_unreachable = 0;
+               return;
+       }
+
+       /* Nothing matched -- use the default value */
+       if (!(slot & EXPIRE_TOTAL))
+               cb->expire_total = default_reflog_expire;
+       if (!(slot & EXPIRE_UNREACH))
+               cb->expire_unreachable = default_reflog_expire_unreachable;
 }
 
 static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
@@ -353,6 +464,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
        struct cmd_reflog_expire_cb cb;
        unsigned long now = time(NULL);
        int i, status, do_all;
+       int explicit_expiry = 0;
 
        git_config(reflog_expire_config, NULL);
 
@@ -367,20 +479,18 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
        cb.expire_total = default_reflog_expire;
        cb.expire_unreachable = default_reflog_expire_unreachable;
 
-       /*
-        * We can trust the commits and objects reachable from refs
-        * even in older repository.  We cannot trust what's reachable
-        * from reflog if the repository was pruned with older git.
-        */
-
        for (i = 1; i < argc; i++) {
                const char *arg = argv[i];
                if (!strcmp(arg, "--dry-run") || !strcmp(arg, "-n"))
                        cb.dry_run = 1;
-               else if (!prefixcmp(arg, "--expire="))
+               else if (!prefixcmp(arg, "--expire=")) {
                        cb.expire_total = approxidate(arg + 9);
-               else if (!prefixcmp(arg, "--expire-unreachable="))
+                       explicit_expiry |= EXPIRE_TOTAL;
+               }
+               else if (!prefixcmp(arg, "--expire-unreachable=")) {
                        cb.expire_unreachable = approxidate(arg + 21);
+                       explicit_expiry |= EXPIRE_UNREACH;
+               }
                else if (!strcmp(arg, "--stale-fix"))
                        cb.stalefix = 1;
                else if (!strcmp(arg, "--rewrite"))
@@ -400,6 +510,12 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
                else
                        break;
        }
+
+       /*
+        * We can trust the commits and objects reachable from refs
+        * even in older repository.  We cannot trust what's reachable
+        * from reflog if the repository was pruned with older git.
+        */
        if (cb.stalefix) {
                init_revisions(&cb.revs, prefix);
                if (cb.verbose)
@@ -417,6 +533,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
                for_each_reflog(collect_reflog, &collected);
                for (i = 0; i < collected.nr; i++) {
                        struct collected_reflog *e = collected.e[i];
+                       set_reflog_expiry_param(&cb, explicit_expiry, e->reflog);
                        status |= expire_reflog(e->reflog, e->sha1, 0, &cb);
                        free(e);
                }
@@ -430,6 +547,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
                        status |= error("%s points nowhere!", ref);
                        continue;
                }
+               set_reflog_expiry_param(&cb, explicit_expiry, ref);
                status |= expire_reflog(ref, sha1, 0, &cb);
        }
        return status;
index 85222d9bc591e0b603bf6f33c32d6bb1bad479ee..839b26e8e0a10a498a81bf27d907543e7c256cb8 100644 (file)
@@ -16,6 +16,9 @@ static int cutoff_resolve = 60;
 /* if rerere_enabled == -1, fall back to detection of .git/rr-cache */
 static int rerere_enabled = -1;
 
+/* automatically update cleanly resolved paths to the index */
+static int rerere_autoupdate;
+
 static char *merge_rr_path;
 
 static const char *rr_path(const char *name, const char *file)
@@ -23,6 +26,18 @@ static const char *rr_path(const char *name, const char *file)
        return git_path("rr-cache/%s/%s", name, file);
 }
 
+static time_t rerere_created_at(const char *name)
+{
+       struct stat st;
+       return stat(rr_path(name, "preimage"), &st) ? (time_t) 0 : st.st_mtime;
+}
+
+static int has_resolution(const char *name)
+{
+       struct stat st;
+       return !stat(rr_path(name, "postimage"), &st);
+}
+
 static void read_rr(struct path_list *rr)
 {
        unsigned char sha1[20];
@@ -54,8 +69,12 @@ static int write_rr(struct path_list *rr, int out_fd)
 {
        int i;
        for (i = 0; i < rr->nr; i++) {
-               const char *path = rr->items[i].path;
-               int length = strlen(path) + 1;
+               const char *path;
+               int length;
+               if (!rr->items[i].util)
+                       continue;
+               path = rr->items[i].path;
+               length = strlen(path) + 1;
                if (write_in_full(out_fd, rr->items[i].util, 40) != 40 ||
                    write_in_full(out_fd, "\t", 1) != 1 ||
                    write_in_full(out_fd, path, length) != length)
@@ -98,13 +117,10 @@ static int handle_file(const char *path,
                else if (!prefixcmp(buf, "======="))
                        hunk = 2;
                else if (!prefixcmp(buf, ">>>>>>> ")) {
-                       int cmp = strbuf_cmp(&one, &two);
-
+                       if (strbuf_cmp(&one, &two) > 0)
+                               strbuf_swap(&one, &two);
                        hunk_no++;
                        hunk = 0;
-                       if (cmp > 0) {
-                               strbuf_swap(&one, &two);
-                       }
                        if (out) {
                                fputs("<<<<<<<\n", out);
                                fwrite(one.buf, one.len, 1, out);
@@ -135,6 +151,11 @@ static int handle_file(const char *path,
                fclose(out);
        if (sha1)
                SHA1_Final(sha1, &ctx);
+       if (hunk) {
+               if (output)
+                       unlink(output);
+               return error("Could not parse conflict hunks in %s", path);
+       }
        return hunk_no;
 }
 
@@ -201,33 +222,24 @@ static void unlink_rr_item(const char *name)
 static void garbage_collect(struct path_list *rr)
 {
        struct path_list to_remove = { NULL, 0, 0, 1 };
-       char buf[1024];
        DIR *dir;
        struct dirent *e;
-       int len, i, cutoff;
+       int i, cutoff;
        time_t now = time(NULL), then;
 
-       strlcpy(buf, git_path("rr-cache"), sizeof(buf));
-       len = strlen(buf);
-       dir = opendir(buf);
-       strcpy(buf + len++, "/");
+       dir = opendir(git_path("rr-cache"));
        while ((e = readdir(dir))) {
                const char *name = e->d_name;
-               struct stat st;
-               if (name[0] == '.' && (name[1] == '\0' ||
-                                       (name[1] == '.' && name[2] == '\0')))
+               if (name[0] == '.' &&
+                   (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
                        continue;
-               i = snprintf(buf + len, sizeof(buf) - len, "%s", name);
-               strlcpy(buf + len + i, "/preimage", sizeof(buf) - len - i);
-               if (stat(buf, &st))
+               then = rerere_created_at(name);
+               if (!then)
                        continue;
-               then = st.st_mtime;
-               strlcpy(buf + len + i, "/postimage", sizeof(buf) - len - i);
-               cutoff = stat(buf, &st) ? cutoff_noresolve : cutoff_resolve;
-               if (then < now - cutoff * 86400) {
-                       buf[len + i] = '\0';
-                       path_list_insert(xstrdup(name), &to_remove);
-               }
+               cutoff = (has_resolution(name)
+                         ? cutoff_resolve : cutoff_noresolve);
+               if (then < now - cutoff * 86400)
+                       path_list_append(name, &to_remove);
        }
        for (i = 0; i < to_remove.nr; i++)
                unlink_rr_item(to_remove.items[i].path);
@@ -267,9 +279,36 @@ static int diff_two(const char *file1, const char *label1,
        return 0;
 }
 
+static struct lock_file index_lock;
+
+static int update_paths(struct path_list *update)
+{
+       int i;
+       int fd = hold_locked_index(&index_lock, 0);
+       int status = 0;
+
+       if (fd < 0)
+               return -1;
+
+       for (i = 0; i < update->nr; i++) {
+               struct path_list_item *item = &update->items[i];
+               if (add_file_to_cache(item->path, ADD_CACHE_IGNORE_ERRORS))
+                       status = -1;
+       }
+
+       if (!status && active_cache_changed) {
+               if (write_cache(fd, active_cache, active_nr) ||
+                   commit_locked_index(&index_lock))
+                       die("Unable to write new index file");
+       } else if (fd >= 0)
+               rollback_lock_file(&index_lock);
+       return status;
+}
+
 static int do_plain_rerere(struct path_list *rr, int fd)
 {
        struct path_list conflict = { NULL, 0, 0, 1 };
+       struct path_list update = { NULL, 0, 0, 1 };
        int i;
 
        find_conflict(&conflict);
@@ -306,17 +345,17 @@ static int do_plain_rerere(struct path_list *rr, int fd)
         */
 
        for (i = 0; i < rr->nr; i++) {
-               struct stat st;
                int ret;
                const char *path = rr->items[i].path;
                const char *name = (const char *)rr->items[i].util;
 
-               if (!stat(rr_path(name, "preimage"), &st) &&
-                               !stat(rr_path(name, "postimage"), &st)) {
+               if (has_resolution(name)) {
                        if (!merge(name, path)) {
                                fprintf(stderr, "Resolved '%s' using "
                                                "previous resolution.\n", path);
-                               goto tail_optimization;
+                               if (rerere_autoupdate)
+                                       path_list_insert(path, &update);
+                               goto mark_resolved;
                        }
                }
 
@@ -327,15 +366,13 @@ static int do_plain_rerere(struct path_list *rr, int fd)
 
                fprintf(stderr, "Recorded resolution for '%s'.\n", path);
                copy_file(rr_path(name, "postimage"), path, 0666);
-tail_optimization:
-               if (i < rr->nr - 1)
-                       memmove(rr->items + i,
-                               rr->items + i + 1,
-                               sizeof(rr->items[0]) * (rr->nr - i - 1));
-               rr->nr--;
-               i--;
+       mark_resolved:
+               rr->items[i].util = NULL;
        }
 
+       if (update.nr)
+               update_paths(&update);
+
        return write_rr(rr, fd);
 }
 
@@ -347,6 +384,8 @@ static int git_rerere_config(const char *var, const char *value, void *cb)
                cutoff_noresolve = git_config_int(var, value);
        else if (!strcmp(var, "rerere.enabled"))
                rerere_enabled = git_config_bool(var, value);
+       else if (!strcmp(var, "rerere.autoupdate"))
+               rerere_autoupdate = git_config_bool(var, value);
        else
                return git_default_config(var, value, cb);
        return 0;
@@ -410,11 +449,8 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)
                return do_plain_rerere(&merge_rr, fd);
        else if (!strcmp(argv[1], "clear")) {
                for (i = 0; i < merge_rr.nr; i++) {
-                       struct stat st;
                        const char *name = (const char *)merge_rr.items[i].util;
-                       if (!stat(git_path("rr-cache/%s", name), &st) &&
-                                       S_ISDIR(st.st_mode) &&
-                                       stat(rr_path(name, "postimage"), &st))
+                       if (!has_resolution(name))
                                unlink_rr_item(name);
                }
                unlink(merge_rr_path);
index 83a7b1349e06dbf1a355888272d9b13a7d4c22c4..b4a2c447f22163b3165a0c6081899498e3048b51 100644 (file)
@@ -37,6 +37,7 @@ static const char rev_list_usage[] =
 "    --reverse\n"
 "  formatting output:\n"
 "    --parents\n"
+"    --children\n"
 "    --objects | --objects-edge\n"
 "    --unpacked\n"
 "    --header | --pretty\n"
@@ -90,6 +91,15 @@ static void show_commit(struct commit *commit)
                        parents = parents->next;
                }
        }
+       if (revs.children.name) {
+               struct commit_list *children;
+
+               children = lookup_decoration(&revs.children, &commit->object);
+               while (children) {
+                       printf(" %s", sha1_to_hex(children->item->object.sha1));
+                       children = children->next;
+               }
+       }
        show_decorations(commit);
        if (revs.commit_format == CMIT_FMT_ONELINE)
                putchar(' ');
@@ -565,23 +575,6 @@ static struct commit_list *find_bisection(struct commit_list *list,
        return best;
 }
 
-static void read_revisions_from_stdin(struct rev_info *revs)
-{
-       char line[1000];
-
-       while (fgets(line, sizeof(line), stdin) != NULL) {
-               int len = strlen(line);
-               if (len && line[len - 1] == '\n')
-                       line[--len] = 0;
-               if (!len)
-                       break;
-               if (line[0] == '-')
-                       die("options not supported in --stdin mode");
-               if (handle_revision_arg(line, revs, 0, 1))
-                       die("bad revision '%s'", line);
-       }
-}
-
 int cmd_rev_list(int argc, const char **argv, const char *prefix)
 {
        struct commit_list *list;
index 0270f9b85a8229d30ab3fab5ce73661f383b005e..f3d452418c25b0d95a911a050f75ba190d6513c1 100644 (file)
@@ -206,6 +206,7 @@ static int merge_recursive(const char *base_sha1,
 {
        char buffer[256];
        const char *argv[6];
+       int i = 0;
 
        sprintf(buffer, "GITHEAD_%s", head_sha1);
        setenv(buffer, head_name, 1);
@@ -218,12 +219,13 @@ static int merge_recursive(const char *base_sha1,
         * and $prev on top of us (when reverting), or the change between
         * $prev and $commit on top of us (when cherry-picking or replaying).
         */
-       argv[0] = "merge-recursive";
-       argv[1] = base_sha1;
-       argv[2] = "--";
-       argv[3] = head_sha1;
-       argv[4] = next_sha1;
-       argv[5] = NULL;
+       argv[i++] = "merge-recursive";
+       if (base_sha1)
+               argv[i++] = base_sha1;
+       argv[i++] = "--";
+       argv[i++] = head_sha1;
+       argv[i++] = next_sha1;
+       argv[i++] = NULL;
 
        return run_command_v_opt(argv, RUN_COMMAND_NO_STDIN | RUN_GIT_CMD);
 }
@@ -297,9 +299,12 @@ static int revert_or_cherry_pick(int argc, const char **argv)
                discard_cache();
        }
 
-       if (!commit->parents)
-               die ("Cannot %s a root commit", me);
-       if (commit->parents->next) {
+       if (!commit->parents) {
+               if (action == REVERT)
+                       die ("Cannot revert a root commit");
+               parent = NULL;
+       }
+       else if (commit->parents->next) {
                /* Reverting or cherry-picking a merge commit */
                int cnt;
                struct commit_list *p;
@@ -368,7 +373,8 @@ static int revert_or_cherry_pick(int argc, const char **argv)
                }
        }
 
-       if (merge_recursive(sha1_to_hex(base->object.sha1),
+       if (merge_recursive(base == NULL ?
+                               NULL : sha1_to_hex(base->object.sha1),
                                sha1_to_hex(head), "HEAD",
                                sha1_to_hex(next->object.sha1), oneline) ||
                        write_cache_as_tree(head, 0, NULL)) {
index e6a2865019cceadfcbfc8575a2bd1f97b7159dcb..01362022c0990cc785d7bcc77f21802c5e75b3e2 100644 (file)
@@ -7,9 +7,14 @@
 #include "utf8.h"
 #include "mailmap.h"
 #include "shortlog.h"
+#include "parse-options.h"
 
-static const char shortlog_usage[] =
-"git-shortlog [-n] [-s] [-e] [-w] [<commit-id>... ]";
+static char const * const shortlog_usage[] = {
+       "git-shortlog [-n] [-s] [-e] [-w] [rev-opts] [--] [<commit-id>... ]",
+       "",
+       "[rev-opts] are documented in git-rev-list(1)",
+       NULL
+};
 
 static int compare_by_number(const void *a1, const void *a2)
 {
@@ -164,21 +169,19 @@ static void get_from_rev(struct rev_info *rev, struct shortlog *log)
                shortlog_add_commit(log, commit);
 }
 
-static int parse_uint(char const **arg, int comma)
+static int parse_uint(char const **arg, int comma, int defval)
 {
        unsigned long ul;
        int ret;
        char *endp;
 
        ul = strtoul(*arg, &endp, 10);
-       if (endp != *arg && *endp && *endp != comma)
+       if (*endp && *endp != comma)
                return -1;
-       ret = (int) ul;
-       if (ret != ul)
+       if (ul > INT_MAX)
                return -1;
-       *arg = endp;
-       if (**arg)
-               (*arg)++;
+       ret = *arg == endp ? defval : (int)ul;
+       *arg = *endp ? endp + 1 : endp;
        return ret;
 }
 
@@ -187,30 +190,30 @@ static const char wrap_arg_usage[] = "-w[<width>[,<indent1>[,<indent2>]]]";
 #define DEFAULT_INDENT1 6
 #define DEFAULT_INDENT2 9
 
-static void parse_wrap_args(const char *arg, int *in1, int *in2, int *wrap)
+static int parse_wrap_args(const struct option *opt, const char *arg, int unset)
 {
-       arg += 2; /* skip -w */
-
-       *wrap = parse_uint(&arg, ',');
-       if (*wrap < 0)
-               die(wrap_arg_usage);
-       *in1 = parse_uint(&arg, ',');
-       if (*in1 < 0)
-               die(wrap_arg_usage);
-       *in2 = parse_uint(&arg, '\0');
-       if (*in2 < 0)
-               die(wrap_arg_usage);
-
-       if (!*wrap)
-               *wrap = DEFAULT_WRAPLEN;
-       if (!*in1)
-               *in1 = DEFAULT_INDENT1;
-       if (!*in2)
-               *in2 = DEFAULT_INDENT2;
-       if (*wrap &&
-           ((*in1 && *wrap <= *in1) ||
-            (*in2 && *wrap <= *in2)))
-               die(wrap_arg_usage);
+       struct shortlog *log = opt->value;
+
+       log->wrap_lines = !unset;
+       if (unset)
+               return 0;
+       if (!arg) {
+               log->wrap = DEFAULT_WRAPLEN;
+               log->in1 = DEFAULT_INDENT1;
+               log->in2 = DEFAULT_INDENT2;
+               return 0;
+       }
+
+       log->wrap = parse_uint(&arg, ',', DEFAULT_WRAPLEN);
+       log->in1 = parse_uint(&arg, ',', DEFAULT_INDENT1);
+       log->in2 = parse_uint(&arg, '\0', DEFAULT_INDENT2);
+       if (log->wrap < 0 || log->in1 < 0 || log->in2 < 0)
+               return error(wrap_arg_usage);
+       if (log->wrap &&
+           ((log->in1 && log->wrap <= log->in1) ||
+            (log->in2 && log->wrap <= log->in2)))
+               return error(wrap_arg_usage);
+       return 0;
 }
 
 void shortlog_init(struct shortlog *log)
@@ -227,38 +230,46 @@ void shortlog_init(struct shortlog *log)
 
 int cmd_shortlog(int argc, const char **argv, const char *prefix)
 {
-       struct shortlog log;
-       struct rev_info rev;
+       static struct shortlog log;
+       static struct rev_info rev;
        int nongit;
 
+       static const struct option options[] = {
+               OPT_BOOLEAN('n', "numbered", &log.sort_by_number,
+                           "sort output according to the number of commits per author"),
+               OPT_BOOLEAN('s', "summary", &log.summary,
+                           "Suppress commit descriptions, only provides commit count"),
+               OPT_BOOLEAN('e', "email", &log.email,
+                           "Show the email address of each author"),
+               { OPTION_CALLBACK, 'w', NULL, &log, "w[,i1[,i2]]",
+                       "Linewrap output", PARSE_OPT_OPTARG, &parse_wrap_args },
+               OPT_END(),
+       };
+
+       struct parse_opt_ctx_t ctx;
+
        prefix = setup_git_directory_gently(&nongit);
        shortlog_init(&log);
-
-       /* since -n is a shadowed rev argument, parse our args first */
-       while (argc > 1) {
-               if (!strcmp(argv[1], "-n") || !strcmp(argv[1], "--numbered"))
-                       log.sort_by_number = 1;
-               else if (!strcmp(argv[1], "-s") ||
-                               !strcmp(argv[1], "--summary"))
-                       log.summary = 1;
-               else if (!strcmp(argv[1], "-e") ||
-                        !strcmp(argv[1], "--email"))
-                       log.email = 1;
-               else if (!prefixcmp(argv[1], "-w")) {
-                       log.wrap_lines = 1;
-                       parse_wrap_args(argv[1], &log.in1, &log.in2, &log.wrap);
+       init_revisions(&rev, prefix);
+       parse_options_start(&ctx, argc, argv, PARSE_OPT_KEEP_DASHDASH |
+                           PARSE_OPT_KEEP_ARGV0);
+
+       for (;;) {
+               switch (parse_options_step(&ctx, options, shortlog_usage)) {
+               case PARSE_OPT_HELP:
+                       exit(129);
+               case PARSE_OPT_DONE:
+                       goto parse_done;
                }
-               else if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
-                       usage(shortlog_usage);
-               else
-                       break;
-               argv++;
-               argc--;
+               parse_revision_opt(&rev, &ctx, options, shortlog_usage);
+       }
+parse_done:
+       argc = parse_options_end(&ctx);
+
+       if (setup_revisions(argc, argv, &rev, NULL) != 1) {
+               error("unrecognized argument: %s", argv[1]);
+               usage_with_options(shortlog_usage, options);
        }
-       init_revisions(&rev, prefix);
-       argc = setup_revisions(argc, argv, &rev, NULL);
-       if (argc > 1)
-               die ("unrecognized argument: %s", argv[1]);
 
        /* assume HEAD if from a tty */
        if (!nongit && !rev.pending.nr && isatty(0))
index 85043d1fde917e67746fb1ee106ce2cf78f3d161..a8918666655bb91f952ccdac18715bd9ba4a09f2 100644 (file)
@@ -471,7 +471,8 @@ static void unpack_all(void)
        if (ntohl(hdr->hdr_signature) != PACK_SIGNATURE)
                die("bad pack file");
        if (!pack_version_ok(hdr->hdr_version))
-               die("unknown pack file version %d", ntohl(hdr->hdr_version));
+               die("unknown pack file version %"PRIu32,
+                       ntohl(hdr->hdr_version));
        use(sizeof(struct pack_header));
 
        if (!quiet)
index 93c127196d272d99d8af24a5fbc7ac89efdbb3d4..d90d11d2e35c38baab32f05f58125aaf1baee6cc 100644 (file)
@@ -4,14 +4,14 @@
 #include "parse-options.h"
 
 static const char * const git_update_ref_usage[] = {
-       "git-update-ref [options] -d <refname> <oldval>",
+       "git-update-ref [options] -d <refname> [<oldval>]",
        "git-update-ref [options]    <refname> <newval> [<oldval>]",
        NULL
 };
 
 int cmd_update_ref(int argc, const char **argv, const char *prefix)
 {
-       const char *refname, *value, *oldval, *msg=NULL;
+       const char *refname, *oldval, *msg=NULL;
        unsigned char sha1[20], oldsha1[20];
        int delete = 0, no_deref = 0;
        struct option options[] = {
@@ -27,25 +27,29 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
        if (msg && !*msg)
                die("Refusing to perform update with empty message.");
 
-       if (argc < 2 || argc > 3)
-               usage_with_options(git_update_ref_usage, options);
-       refname = argv[0];
-       value   = argv[1];
-       oldval  = argv[2];
-
-       if (get_sha1(value, sha1))
-               die("%s: not a valid SHA1", value);
-
        if (delete) {
-               if (oldval)
+               if (argc < 1 || argc > 2)
+                       usage_with_options(git_update_ref_usage, options);
+               refname = argv[0];
+               oldval = argv[1];
+       } else {
+               const char *value;
+               if (argc < 2 || argc > 3)
                        usage_with_options(git_update_ref_usage, options);
-               return delete_ref(refname, sha1);
+               refname = argv[0];
+               value = argv[1];
+               oldval = argv[2];
+               if (get_sha1(value, sha1))
+                       die("%s: not a valid SHA1", value);
        }
 
-       hashclr(oldsha1);
+       hashclr(oldsha1); /* all-zero hash in case oldval is the empty string */
        if (oldval && *oldval && get_sha1(oldval, oldsha1))
                die("%s: not a valid old SHA1", oldval);
 
-       return update_ref(msg, refname, sha1, oldval ? oldsha1 : NULL,
-                         no_deref ? REF_NODEREF : 0, DIE_ON_ERR);
+       if (delete)
+               return delete_ref(refname, oldval ? oldsha1 : NULL);
+       else
+               return update_ref(msg, refname, sha1, oldval ? oldsha1 : NULL,
+                                 no_deref ? REF_NODEREF : 0, DIE_ON_ERR);
 }
index 4c515a0570ec2b05e5dca8156d885a70b922251e..f4ac595695b1fff1317ff7d14ea9427780327aea 100644 (file)
@@ -2,6 +2,58 @@
 #include "cache.h"
 #include "pack.h"
 
+
+#define MAX_CHAIN 50
+
+static void show_pack_info(struct packed_git *p)
+{
+       uint32_t nr_objects, i, chain_histogram[MAX_CHAIN+1];
+
+       nr_objects = p->num_objects;
+       memset(chain_histogram, 0, sizeof(chain_histogram));
+
+       for (i = 0; i < nr_objects; i++) {
+               const unsigned char *sha1;
+               unsigned char base_sha1[20];
+               const char *type;
+               unsigned long size;
+               unsigned long store_size;
+               off_t offset;
+               unsigned int delta_chain_length;
+
+               sha1 = nth_packed_object_sha1(p, i);
+               if (!sha1)
+                       die("internal error pack-check nth-packed-object");
+               offset = nth_packed_object_offset(p, i);
+               type = packed_object_info_detail(p, offset, &size, &store_size,
+                                                &delta_chain_length,
+                                                base_sha1);
+               printf("%s ", sha1_to_hex(sha1));
+               if (!delta_chain_length)
+                       printf("%-6s %lu %lu %"PRIuMAX"\n",
+                              type, size, store_size, (uintmax_t)offset);
+               else {
+                       printf("%-6s %lu %lu %"PRIuMAX" %u %s\n",
+                              type, size, store_size, (uintmax_t)offset,
+                              delta_chain_length, sha1_to_hex(base_sha1));
+                       if (delta_chain_length <= MAX_CHAIN)
+                               chain_histogram[delta_chain_length]++;
+                       else
+                               chain_histogram[0]++;
+               }
+       }
+
+       for (i = 0; i <= MAX_CHAIN; i++) {
+               if (!chain_histogram[i])
+                       continue;
+               printf("chain length = %"PRIu32": %"PRIu32" object%s\n", i,
+                      chain_histogram[i], chain_histogram[i] > 1 ? "s" : "");
+       }
+       if (chain_histogram[0])
+               printf("chain length > %d: %"PRIu32" object%s\n", MAX_CHAIN,
+                      chain_histogram[0], chain_histogram[0] > 1 ? "s" : "");
+}
+
 static int verify_one_pack(const char *path, int verbose)
 {
        char arg[PATH_MAX];
@@ -41,7 +93,16 @@ static int verify_one_pack(const char *path, int verbose)
                return error("packfile %s not found.", arg);
 
        install_packed_git(pack);
-       err = verify_pack(pack, verbose);
+       err = verify_pack(pack);
+
+       if (verbose) {
+               if (err)
+                       printf("%s: bad\n", pack->pack_name);
+               else {
+                       show_pack_info(pack);
+                       printf("%s: ok\n", pack->pack_name);
+               }
+       }
 
        return err;
 }
index 0ba5df17e15d679b03fe38af40260c118c9588fa..00b2aabefca49b634f49143523ee31556baa7777 100644 (file)
--- a/bundle.c
+++ b/bundle.c
@@ -178,6 +178,7 @@ int create_bundle(struct bundle_header *header, const char *path,
        int i, ref_count = 0;
        char buffer[1024];
        struct rev_info revs;
+       int read_from_stdin = 0;
        struct child_process rls;
        FILE *rls_fout;
 
@@ -227,8 +228,16 @@ int create_bundle(struct bundle_header *header, const char *path,
 
        /* write references */
        argc = setup_revisions(argc, argv, &revs, NULL);
-       if (argc > 1)
-               return error("unrecognized argument: %s'", argv[1]);
+
+       for (i = 1; i < argc; i++) {
+               if (!strcmp(argv[i], "--stdin")) {
+                       if (read_from_stdin++)
+                               die("--stdin given twice?");
+                       read_revisions_from_stdin(&revs);
+                       continue;
+               }
+               return error("unrecognized argument: %s'", argv[i]);
+       }
 
        for (i = 0; i < revs.pending.nr; i++) {
                struct object_array_entry *e = revs.pending.objects + i;
diff --git a/cache.h b/cache.h
index ca382d4622c7c2ecdfef77fe6daab2ee36173863..a8254e2f9e076b2b69dd214379578e6fc065ddcc 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -298,8 +298,8 @@ static inline enum object_type object_type(unsigned int mode)
 #define GRAFT_ENVIRONMENT "GIT_GRAFT_FILE"
 #define TEMPLATE_DIR_ENVIRONMENT "GIT_TEMPLATE_DIR"
 #define CONFIG_ENVIRONMENT "GIT_CONFIG"
-#define CONFIG_LOCAL_ENVIRONMENT "GIT_CONFIG_LOCAL"
 #define EXEC_PATH_ENVIRONMENT "GIT_EXEC_PATH"
+#define CEILING_DIRECTORIES_ENVIRONMENT "GIT_CEILING_DIRECTORIES"
 #define GITATTRIBUTES_FILE ".gitattributes"
 #define INFOATTRIBUTES_FILE "info/attributes"
 #define ATTRIBUTE_MACRO_PREFIX "[attr]"
@@ -311,7 +311,6 @@ extern char *git_work_tree_cfg;
 extern int is_inside_work_tree(void);
 extern const char *get_git_dir(void);
 extern char *get_object_directory(void);
-extern char *get_refs_directory(void);
 extern char *get_index_file(void);
 extern char *get_graft_file(void);
 extern int set_git_dir(const char *path);
@@ -435,6 +434,7 @@ extern size_t packed_git_window_size;
 extern size_t packed_git_limit;
 extern size_t delta_base_cache_limit;
 extern int auto_crlf;
+extern int fsync_object_files;
 
 enum safe_crlf {
        SAFE_CRLF_FALSE = 0,
@@ -522,11 +522,13 @@ int safe_create_leading_directories_const(const char *path);
 char *enter_repo(char *path, int strict);
 static inline int is_absolute_path(const char *path)
 {
-       return path[0] == '/';
+       return path[0] == '/' || has_dos_drive_prefix(path);
 }
 const char *make_absolute_path(const char *path);
 const char *make_nonrelative_path(const char *path);
 const char *make_relative_path(const char *abs, const char *base);
+int normalize_absolute_path(char *buf, const char *path);
+int longest_ancestor_length(const char *path, const char *prefix_list);
 
 /* Read and unpack a sha1 file into memory, write memory to a sha1 file */
 extern int sha1_object_info(const unsigned char *, unsigned long *);
@@ -536,6 +538,9 @@ extern int write_sha1_file(void *buf, unsigned long len, const char *type, unsig
 extern int pretend_sha1_file(void *, unsigned long, enum object_type, unsigned char *);
 extern int force_object_loose(const unsigned char *sha1, time_t mtime);
 
+/* just like read_sha1_file(), but non fatal in presence of bad objects */
+extern void *read_object(const unsigned char *sha1, enum object_type *type, unsigned long *size);
+
 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);
@@ -643,6 +648,8 @@ extern struct packed_git {
        const void *index_data;
        size_t index_size;
        uint32_t num_objects;
+       uint32_t num_bad_objects;
+       unsigned char *bad_object_sha1;
        int index_version;
        time_t mtime;
        int pack_fd;
@@ -711,6 +718,7 @@ extern void close_pack_windows(struct packed_git *);
 extern void unuse_pack(struct pack_window **);
 extern struct packed_git *add_packed_git(const char *, int, int);
 extern const unsigned char *nth_packed_object_sha1(struct packed_git *, uint32_t);
+extern off_t nth_packed_object_offset(const struct packed_git *, uint32_t);
 extern off_t find_pack_entry_one(const unsigned char *, struct packed_git *);
 extern void *unpack_entry(struct packed_git *, off_t, enum object_type *, unsigned long *);
 extern unsigned long unpack_object_header_gently(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep);
@@ -737,10 +745,10 @@ extern int git_config_set_multivar(const char *, const char *, const char *, int
 extern int git_config_rename_section(const char *, const char *);
 extern const char *git_etc_gitconfig(void);
 extern int check_repository_format_version(const char *var, const char *value, void *cb);
-extern int git_env_bool(const char *, int);
 extern int git_config_system(void);
 extern int git_config_global(void);
 extern int config_error_nonbool(const char *);
+extern const char *config_exclusive_filename;
 
 #define MAX_GITNAME (1000)
 extern char git_default_email[MAX_GITNAME];
@@ -817,11 +825,11 @@ void shift_tree(const unsigned char *, const unsigned char *, unsigned char *, i
 extern unsigned whitespace_rule_cfg;
 extern unsigned whitespace_rule(const char *);
 extern unsigned parse_whitespace_rule(const char *);
-extern unsigned check_and_emit_line(const char *line, int len, unsigned ws_rule,
-    FILE *stream, const char *set,
-    const char *reset, const char *ws);
+extern unsigned ws_check(const char *line, int len, unsigned ws_rule);
+extern void ws_check_emit(const char *line, int len, unsigned ws_rule, FILE *stream, const char *set, const char *reset, const char *ws);
 extern char *whitespace_error_string(unsigned ws);
 extern int ws_fix_copy(char *, const char *, int, unsigned, int *);
+extern int ws_blank_line(const char *line, int len, unsigned ws_rule);
 
 /* ls-files */
 int pathspec_match(const char **spec, char *matched, const char *filename, int skiplen);
diff --git a/check_bindir b/check_bindir
new file mode 100755 (executable)
index 0000000..a1c4c3e
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/sh
+bindir="$1"
+gitexecdir="$2"
+gitcmd="$3"
+if test "$bindir" != "$gitexecdir" -a -x "$gitcmd"
+then
+       echo
+       echo "!! You have installed git-* commands to new gitexecdir."
+       echo "!! Old version git-* commands still remain in bindir."
+       echo "!! Mixing two versions of Git will lead to problems."
+       echo "!! Please remove old version commands in bindir now."
+       echo
+fi
diff --git a/compat/fnmatch.c b/compat/fnmatch.c
new file mode 100644 (file)
index 0000000..1f4ead5
--- /dev/null
@@ -0,0 +1,488 @@
+/* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Enable GNU extensions in fnmatch.h.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE   1
+#endif
+
+#include <errno.h>
+#include <fnmatch.h>
+#include <ctype.h>
+
+#if HAVE_STRING_H || defined _LIBC
+# include <string.h>
+#else
+# include <strings.h>
+#endif
+
+#if defined STDC_HEADERS || defined _LIBC
+# include <stdlib.h>
+#endif
+
+/* For platform which support the ISO C amendement 1 functionality we
+   support user defined character classes.  */
+#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>.  */
+# include <wchar.h>
+# include <wctype.h>
+#endif
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself.  This code is part of the GNU C
+   Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object files,
+   it is simpler to just do this in the source for each such file.  */
+
+#if defined _LIBC || !defined __GNU_LIBRARY__
+
+
+# if defined STDC_HEADERS || !defined isascii
+#  define ISASCII(c) 1
+# else
+#  define ISASCII(c) isascii(c)
+# endif
+
+# ifdef isblank
+#  define ISBLANK(c) (ISASCII (c) && isblank (c))
+# else
+#  define ISBLANK(c) ((c) == ' ' || (c) == '\t')
+# endif
+# ifdef isgraph
+#  define ISGRAPH(c) (ISASCII (c) && isgraph (c))
+# else
+#  define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
+# endif
+
+# define ISPRINT(c) (ISASCII (c) && isprint (c))
+# define ISDIGIT(c) (ISASCII (c) && isdigit (c))
+# define ISALNUM(c) (ISASCII (c) && isalnum (c))
+# define ISALPHA(c) (ISASCII (c) && isalpha (c))
+# define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
+# define ISLOWER(c) (ISASCII (c) && islower (c))
+# define ISPUNCT(c) (ISASCII (c) && ispunct (c))
+# define ISSPACE(c) (ISASCII (c) && isspace (c))
+# define ISUPPER(c) (ISASCII (c) && isupper (c))
+# define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
+
+# define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
+
+# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+/* The GNU C library provides support for user-defined character classes
+   and the functions from ISO C amendement 1.  */
+#  ifdef CHARCLASS_NAME_MAX
+#   define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
+#  else
+/* This shouldn't happen but some implementation might still have this
+   problem.  Use a reasonable default value.  */
+#   define CHAR_CLASS_MAX_LENGTH 256
+#  endif
+
+#  ifdef _LIBC
+#   define IS_CHAR_CLASS(string) __wctype (string)
+#  else
+#   define IS_CHAR_CLASS(string) wctype (string)
+#  endif
+# else
+#  define CHAR_CLASS_MAX_LENGTH  6 /* Namely, `xdigit'.  */
+
+#  define IS_CHAR_CLASS(string)                                                      \
+   (STREQ (string, "alpha") || STREQ (string, "upper")                       \
+    || STREQ (string, "lower") || STREQ (string, "digit")                    \
+    || STREQ (string, "alnum") || STREQ (string, "xdigit")                   \
+    || STREQ (string, "space") || STREQ (string, "print")                    \
+    || STREQ (string, "punct") || STREQ (string, "graph")                    \
+    || STREQ (string, "cntrl") || STREQ (string, "blank"))
+# endif
+
+/* Avoid depending on library functions or files
+   whose names are inconsistent.  */
+
+# if !defined _LIBC && !defined getenv
+extern char *getenv ();
+# endif
+
+# ifndef errno
+extern int errno;
+# endif
+
+/* This function doesn't exist on most systems.  */
+
+# if !defined HAVE___STRCHRNUL && !defined _LIBC
+static char *
+__strchrnul (s, c)
+     const char *s;
+     int c;
+{
+  char *result = strchr (s, c);
+  if (result == NULL)
+    result = strchr (s, '\0');
+  return result;
+}
+# endif
+
+# ifndef internal_function
+/* Inside GNU libc we mark some function in a special way.  In other
+   environments simply ignore the marking.  */
+#  define internal_function
+# endif
+
+/* Match STRING against the filename pattern PATTERN, returning zero if
+   it matches, nonzero if not.  */
+static int internal_fnmatch __P ((const char *pattern, const char *string,
+                                 int no_leading_period, int flags))
+     internal_function;
+static int
+internal_function
+internal_fnmatch (pattern, string, no_leading_period, flags)
+     const char *pattern;
+     const char *string;
+     int no_leading_period;
+     int flags;
+{
+  register const char *p = pattern, *n = string;
+  register unsigned char c;
+
+/* Note that this evaluates C many times.  */
+# ifdef _LIBC
+#  define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
+# else
+#  define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
+# endif
+
+  while ((c = *p++) != '\0')
+    {
+      c = FOLD (c);
+
+      switch (c)
+       {
+       case '?':
+         if (*n == '\0')
+           return FNM_NOMATCH;
+         else if (*n == '/' && (flags & FNM_FILE_NAME))
+           return FNM_NOMATCH;
+         else if (*n == '.' && no_leading_period
+                  && (n == string
+                      || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
+           return FNM_NOMATCH;
+         break;
+
+       case '\\':
+         if (!(flags & FNM_NOESCAPE))
+           {
+             c = *p++;
+             if (c == '\0')
+               /* Trailing \ loses.  */
+               return FNM_NOMATCH;
+             c = FOLD (c);
+           }
+         if (FOLD ((unsigned char) *n) != c)
+           return FNM_NOMATCH;
+         break;
+
+       case '*':
+         if (*n == '.' && no_leading_period
+             && (n == string
+                 || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
+           return FNM_NOMATCH;
+
+         for (c = *p++; c == '?' || c == '*'; c = *p++)
+           {
+             if (*n == '/' && (flags & FNM_FILE_NAME))
+               /* A slash does not match a wildcard under FNM_FILE_NAME.  */
+               return FNM_NOMATCH;
+             else if (c == '?')
+               {
+                 /* A ? needs to match one character.  */
+                 if (*n == '\0')
+                   /* There isn't another character; no match.  */
+                   return FNM_NOMATCH;
+                 else
+                   /* One character of the string is consumed in matching
+                      this ? wildcard, so *??? won't match if there are
+                      less than three characters.  */
+                   ++n;
+               }
+           }
+
+         if (c == '\0')
+           /* The wildcard(s) is/are the last element of the pattern.
+              If the name is a file name and contains another slash
+              this does mean it cannot match.  */
+           return ((flags & FNM_FILE_NAME) && strchr (n, '/') != NULL
+                   ? FNM_NOMATCH : 0);
+         else
+           {
+             const char *endp;
+
+             endp = __strchrnul (n, (flags & FNM_FILE_NAME) ? '/' : '\0');
+
+             if (c == '[')
+               {
+                 int flags2 = ((flags & FNM_FILE_NAME)
+                               ? flags : (flags & ~FNM_PERIOD));
+
+                 for (--p; n < endp; ++n)
+                   if (internal_fnmatch (p, n,
+                                         (no_leading_period
+                                          && (n == string
+                                              || (n[-1] == '/'
+                                                  && (flags
+                                                      & FNM_FILE_NAME)))),
+                                         flags2)
+                       == 0)
+                     return 0;
+               }
+             else if (c == '/' && (flags & FNM_FILE_NAME))
+               {
+                 while (*n != '\0' && *n != '/')
+                   ++n;
+                 if (*n == '/'
+                     && (internal_fnmatch (p, n + 1, flags & FNM_PERIOD,
+                                           flags) == 0))
+                   return 0;
+               }
+             else
+               {
+                 int flags2 = ((flags & FNM_FILE_NAME)
+                               ? flags : (flags & ~FNM_PERIOD));
+
+                 if (c == '\\' && !(flags & FNM_NOESCAPE))
+                   c = *p;
+                 c = FOLD (c);
+                 for (--p; n < endp; ++n)
+                   if (FOLD ((unsigned char) *n) == c
+                       && (internal_fnmatch (p, n,
+                                             (no_leading_period
+                                              && (n == string
+                                                  || (n[-1] == '/'
+                                                      && (flags
+                                                          & FNM_FILE_NAME)))),
+                                             flags2) == 0))
+                     return 0;
+               }
+           }
+
+         /* If we come here no match is possible with the wildcard.  */
+         return FNM_NOMATCH;
+
+       case '[':
+         {
+           /* Nonzero if the sense of the character class is inverted.  */
+           static int posixly_correct;
+           register int not;
+           char cold;
+
+           if (posixly_correct == 0)
+             posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
+
+           if (*n == '\0')
+             return FNM_NOMATCH;
+
+           if (*n == '.' && no_leading_period && (n == string
+                                                  || (n[-1] == '/'
+                                                      && (flags
+                                                          & FNM_FILE_NAME))))
+             return FNM_NOMATCH;
+
+           if (*n == '/' && (flags & FNM_FILE_NAME))
+             /* `/' cannot be matched.  */
+             return FNM_NOMATCH;
+
+           not = (*p == '!' || (posixly_correct < 0 && *p == '^'));
+           if (not)
+             ++p;
+
+           c = *p++;
+           for (;;)
+             {
+               unsigned char fn = FOLD ((unsigned char) *n);
+
+               if (!(flags & FNM_NOESCAPE) && c == '\\')
+                 {
+                   if (*p == '\0')
+                     return FNM_NOMATCH;
+                   c = FOLD ((unsigned char) *p);
+                   ++p;
+
+                   if (c == fn)
+                     goto matched;
+                 }
+               else if (c == '[' && *p == ':')
+                 {
+                   /* Leave room for the null.  */
+                   char str[CHAR_CLASS_MAX_LENGTH + 1];
+                   size_t c1 = 0;
+# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+                   wctype_t wt;
+# endif
+                   const char *startp = p;
+
+                   for (;;)
+                     {
+                       if (c1 == CHAR_CLASS_MAX_LENGTH)
+                         /* The name is too long and therefore the pattern
+                            is ill-formed.  */
+                         return FNM_NOMATCH;
+
+                       c = *++p;
+                       if (c == ':' && p[1] == ']')
+                         {
+                           p += 2;
+                           break;
+                         }
+                       if (c < 'a' || c >= 'z')
+                         {
+                           /* This cannot possibly be a character class name.
+                              Match it as a normal range.  */
+                           p = startp;
+                           c = '[';
+                           goto normal_bracket;
+                         }
+                       str[c1++] = c;
+                     }
+                   str[c1] = '\0';
+
+# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+                   wt = IS_CHAR_CLASS (str);
+                   if (wt == 0)
+                     /* Invalid character class name.  */
+                     return FNM_NOMATCH;
+
+                   if (__iswctype (__btowc ((unsigned char) *n), wt))
+                     goto matched;
+# else
+                   if ((STREQ (str, "alnum") && ISALNUM ((unsigned char) *n))
+                       || (STREQ (str, "alpha") && ISALPHA ((unsigned char) *n))
+                       || (STREQ (str, "blank") && ISBLANK ((unsigned char) *n))
+                       || (STREQ (str, "cntrl") && ISCNTRL ((unsigned char) *n))
+                       || (STREQ (str, "digit") && ISDIGIT ((unsigned char) *n))
+                       || (STREQ (str, "graph") && ISGRAPH ((unsigned char) *n))
+                       || (STREQ (str, "lower") && ISLOWER ((unsigned char) *n))
+                       || (STREQ (str, "print") && ISPRINT ((unsigned char) *n))
+                       || (STREQ (str, "punct") && ISPUNCT ((unsigned char) *n))
+                       || (STREQ (str, "space") && ISSPACE ((unsigned char) *n))
+                       || (STREQ (str, "upper") && ISUPPER ((unsigned char) *n))
+                       || (STREQ (str, "xdigit") && ISXDIGIT ((unsigned char) *n)))
+                     goto matched;
+# endif
+                 }
+               else if (c == '\0')
+                 /* [ (unterminated) loses.  */
+                 return FNM_NOMATCH;
+               else
+                 {
+                 normal_bracket:
+                   if (FOLD (c) == fn)
+                     goto matched;
+
+                   cold = c;
+                   c = *p++;
+
+                   if (c == '-' && *p != ']')
+                     {
+                       /* It is a range.  */
+                       unsigned char cend = *p++;
+                       if (!(flags & FNM_NOESCAPE) && cend == '\\')
+                         cend = *p++;
+                       if (cend == '\0')
+                         return FNM_NOMATCH;
+
+                       if (cold <= fn && fn <= FOLD (cend))
+                         goto matched;
+
+                       c = *p++;
+                     }
+                 }
+
+               if (c == ']')
+                 break;
+             }
+
+           if (!not)
+             return FNM_NOMATCH;
+           break;
+
+         matched:
+           /* Skip the rest of the [...] that already matched.  */
+           while (c != ']')
+             {
+               if (c == '\0')
+                 /* [... (unterminated) loses.  */
+                 return FNM_NOMATCH;
+
+               c = *p++;
+               if (!(flags & FNM_NOESCAPE) && c == '\\')
+                 {
+                   if (*p == '\0')
+                     return FNM_NOMATCH;
+                   /* XXX 1003.2d11 is unclear if this is right.  */
+                   ++p;
+                 }
+               else if (c == '[' && *p == ':')
+                 {
+                   do
+                     if (*++p == '\0')
+                       return FNM_NOMATCH;
+                   while (*p != ':' || p[1] == ']');
+                   p += 2;
+                   c = *p;
+                 }
+             }
+           if (not)
+             return FNM_NOMATCH;
+         }
+         break;
+
+       default:
+         if (c != FOLD ((unsigned char) *n))
+           return FNM_NOMATCH;
+       }
+
+      ++n;
+    }
+
+  if (*n == '\0')
+    return 0;
+
+  if ((flags & FNM_LEADING_DIR) && *n == '/')
+    /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
+    return 0;
+
+  return FNM_NOMATCH;
+
+# undef FOLD
+}
+
+
+int
+fnmatch (pattern, string, flags)
+     const char *pattern;
+     const char *string;
+     int flags;
+{
+  return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags);
+}
+
+#endif /* _LIBC or not __GNU_LIBRARY__.  */
diff --git a/compat/fnmatch.h b/compat/fnmatch.h
new file mode 100644 (file)
index 0000000..cc3ec37
--- /dev/null
@@ -0,0 +1,84 @@
+/* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef        _FNMATCH_H
+#define        _FNMATCH_H      1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32
+# if !defined __GLIBC__ || !defined __P
+#  undef       __P
+#  define __P(protos)  protos
+# endif
+#else /* Not C++ or ANSI C.  */
+# undef        __P
+# define __P(protos)   ()
+/* We can get away without defining `const' here only because in this file
+   it is used only inside the prototype for `fnmatch', which is elided in
+   non-ANSI C where `const' is problematical.  */
+#endif /* C++ or ANSI C.  */
+
+#ifndef const
+# if (defined __STDC__ && __STDC__) || defined __cplusplus
+#  define __const      const
+# else
+#  define __const
+# endif
+#endif
+
+/* We #undef these before defining them because some losing systems
+   (HP-UX A.08.07 for example) define these in <unistd.h>.  */
+#undef FNM_PATHNAME
+#undef FNM_NOESCAPE
+#undef FNM_PERIOD
+
+/* Bits set in the FLAGS argument to `fnmatch'.  */
+#define        FNM_PATHNAME    (1 << 0) /* No wildcard can ever match `/'.  */
+#define        FNM_NOESCAPE    (1 << 1) /* Backslashes don't quote special chars.  */
+#define        FNM_PERIOD      (1 << 2) /* Leading `.' is matched only explicitly.  */
+
+#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _GNU_SOURCE
+# define FNM_FILE_NAME  FNM_PATHNAME   /* Preferred GNU name.  */
+# define FNM_LEADING_DIR (1 << 3)      /* Ignore `/...' after a match.  */
+# define FNM_CASEFOLD   (1 << 4)       /* Compare without regard to case.  */
+#endif
+
+/* Value returned by `fnmatch' if STRING does not match PATTERN.  */
+#define        FNM_NOMATCH     1
+
+/* This value is returned if the implementation does not support
+   `fnmatch'.  Since this is not the case here it will never be
+   returned but the conformance test suites still require the symbol
+   to be defined.  */
+#ifdef _XOPEN_SOURCE
+# define FNM_NOSYS     (-1)
+#endif
+
+/* Match NAME against the filename pattern PATTERN,
+   returning zero if it matches, FNM_NOMATCH if not.  */
+extern int fnmatch __P ((__const char *__pattern, __const char *__name,
+                        int __flags));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* fnmatch.h */
diff --git a/compat/mingw.c b/compat/mingw.c
new file mode 100644 (file)
index 0000000..3a05fe7
--- /dev/null
@@ -0,0 +1,1019 @@
+#include "../git-compat-util.h"
+#include "../strbuf.h"
+
+unsigned int _CRT_fmode = _O_BINARY;
+
+#undef open
+int mingw_open (const char *filename, int oflags, ...)
+{
+       va_list args;
+       unsigned mode;
+       va_start(args, oflags);
+       mode = va_arg(args, int);
+       va_end(args);
+
+       if (!strcmp(filename, "/dev/null"))
+               filename = "nul";
+       int fd = open(filename, oflags, mode);
+       if (fd < 0 && (oflags & O_CREAT) && errno == EACCES) {
+               DWORD attrs = GetFileAttributes(filename);
+               if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY))
+                       errno = EISDIR;
+       }
+       return fd;
+}
+
+static inline time_t filetime_to_time_t(const FILETIME *ft)
+{
+       long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
+       winTime -= 116444736000000000LL; /* Windows to Unix Epoch conversion */
+       winTime /= 10000000;             /* Nano to seconds resolution */
+       return (time_t)winTime;
+}
+
+static inline size_t size_to_blocks(size_t s)
+{
+       return (s+511)/512;
+}
+
+extern int _getdrive( void );
+/* We keep the do_lstat code in a separate function to avoid recursion.
+ * When a path ends with a slash, the stat will fail with ENOENT. In
+ * this case, we strip the trailing slashes and stat again.
+ */
+static int do_lstat(const char *file_name, struct stat *buf)
+{
+       WIN32_FILE_ATTRIBUTE_DATA fdata;
+
+       if (GetFileAttributesExA(file_name, GetFileExInfoStandard, &fdata)) {
+               int fMode = S_IREAD;
+               if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+                       fMode |= S_IFDIR;
+               else
+                       fMode |= S_IFREG;
+               if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
+                       fMode |= S_IWRITE;
+
+               buf->st_ino = 0;
+               buf->st_gid = 0;
+               buf->st_uid = 0;
+               buf->st_mode = fMode;
+               buf->st_size = fdata.nFileSizeLow; /* Can't use nFileSizeHigh, since it's not a stat64 */
+               buf->st_blocks = size_to_blocks(buf->st_size);
+               buf->st_dev = _getdrive() - 1;
+               buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
+               buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
+               buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
+               errno = 0;
+               return 0;
+       }
+
+       switch (GetLastError()) {
+       case ERROR_ACCESS_DENIED:
+       case ERROR_SHARING_VIOLATION:
+       case ERROR_LOCK_VIOLATION:
+       case ERROR_SHARING_BUFFER_EXCEEDED:
+               errno = EACCES;
+               break;
+       case ERROR_BUFFER_OVERFLOW:
+               errno = ENAMETOOLONG;
+               break;
+       case ERROR_NOT_ENOUGH_MEMORY:
+               errno = ENOMEM;
+               break;
+       default:
+               errno = ENOENT;
+               break;
+       }
+       return -1;
+}
+
+/* We provide our own lstat/fstat functions, since the provided
+ * lstat/fstat functions are so slow. These stat functions are
+ * tailored for Git's usage (read: fast), and are not meant to be
+ * complete. Note that Git stat()s are redirected to mingw_lstat()
+ * too, since Windows doesn't really handle symlinks that well.
+ */
+int mingw_lstat(const char *file_name, struct mingw_stat *buf)
+{
+       int namelen;
+       static char alt_name[PATH_MAX];
+
+       if (!do_lstat(file_name, buf))
+               return 0;
+
+       /* if file_name ended in a '/', Windows returned ENOENT;
+        * try again without trailing slashes
+        */
+       if (errno != ENOENT)
+               return -1;
+
+       namelen = strlen(file_name);
+       if (namelen && file_name[namelen-1] != '/')
+               return -1;
+       while (namelen && file_name[namelen-1] == '/')
+               --namelen;
+       if (!namelen || namelen >= PATH_MAX)
+               return -1;
+
+       memcpy(alt_name, file_name, namelen);
+       alt_name[namelen] = 0;
+       return do_lstat(alt_name, buf);
+}
+
+#undef fstat
+#undef stat
+int mingw_fstat(int fd, struct mingw_stat *buf)
+{
+       HANDLE fh = (HANDLE)_get_osfhandle(fd);
+       BY_HANDLE_FILE_INFORMATION fdata;
+
+       if (fh == INVALID_HANDLE_VALUE) {
+               errno = EBADF;
+               return -1;
+       }
+       /* direct non-file handles to MS's fstat() */
+       if (GetFileType(fh) != FILE_TYPE_DISK) {
+               struct stat st;
+               if (fstat(fd, &st))
+                       return -1;
+               buf->st_ino = st.st_ino;
+               buf->st_gid = st.st_gid;
+               buf->st_uid = st.st_uid;
+               buf->st_mode = st.st_mode;
+               buf->st_size = st.st_size;
+               buf->st_blocks = size_to_blocks(buf->st_size);
+               buf->st_dev = st.st_dev;
+               buf->st_atime = st.st_atime;
+               buf->st_mtime = st.st_mtime;
+               buf->st_ctime = st.st_ctime;
+               return 0;
+       }
+
+       if (GetFileInformationByHandle(fh, &fdata)) {
+               int fMode = S_IREAD;
+               if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+                       fMode |= S_IFDIR;
+               else
+                       fMode |= S_IFREG;
+               if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
+                       fMode |= S_IWRITE;
+
+               buf->st_ino = 0;
+               buf->st_gid = 0;
+               buf->st_uid = 0;
+               buf->st_mode = fMode;
+               buf->st_size = fdata.nFileSizeLow; /* Can't use nFileSizeHigh, since it's not a stat64 */
+               buf->st_blocks = size_to_blocks(buf->st_size);
+               buf->st_dev = _getdrive() - 1;
+               buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
+               buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
+               buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
+               return 0;
+       }
+       errno = EBADF;
+       return -1;
+}
+
+static inline void time_t_to_filetime(time_t t, FILETIME *ft)
+{
+       long long winTime = t * 10000000LL + 116444736000000000LL;
+       ft->dwLowDateTime = winTime;
+       ft->dwHighDateTime = winTime >> 32;
+}
+
+int mingw_utime (const char *file_name, const struct utimbuf *times)
+{
+       FILETIME mft, aft;
+       int fh, rc;
+
+       /* must have write permission */
+       if ((fh = open(file_name, O_RDWR | O_BINARY)) < 0)
+               return -1;
+
+       time_t_to_filetime(times->modtime, &mft);
+       time_t_to_filetime(times->actime, &aft);
+       if (!SetFileTime((HANDLE)_get_osfhandle(fh), NULL, &aft, &mft)) {
+               errno = EINVAL;
+               rc = -1;
+       } else
+               rc = 0;
+       close(fh);
+       return rc;
+}
+
+unsigned int sleep (unsigned int seconds)
+{
+       Sleep(seconds*1000);
+       return 0;
+}
+
+int mkstemp(char *template)
+{
+       char *filename = mktemp(template);
+       if (filename == NULL)
+               return -1;
+       return open(filename, O_RDWR | O_CREAT, 0600);
+}
+
+int gettimeofday(struct timeval *tv, void *tz)
+{
+       SYSTEMTIME st;
+       struct tm tm;
+       GetSystemTime(&st);
+       tm.tm_year = st.wYear-1900;
+       tm.tm_mon = st.wMonth-1;
+       tm.tm_mday = st.wDay;
+       tm.tm_hour = st.wHour;
+       tm.tm_min = st.wMinute;
+       tm.tm_sec = st.wSecond;
+       tv->tv_sec = tm_to_time_t(&tm);
+       if (tv->tv_sec < 0)
+               return -1;
+       tv->tv_usec = st.wMilliseconds*1000;
+       return 0;
+}
+
+int pipe(int filedes[2])
+{
+       int fd;
+       HANDLE h[2], parent;
+
+       if (_pipe(filedes, 8192, 0) < 0)
+               return -1;
+
+       parent = GetCurrentProcess();
+
+       if (!DuplicateHandle (parent, (HANDLE)_get_osfhandle(filedes[0]),
+                       parent, &h[0], 0, FALSE, DUPLICATE_SAME_ACCESS)) {
+               close(filedes[0]);
+               close(filedes[1]);
+               return -1;
+       }
+       if (!DuplicateHandle (parent, (HANDLE)_get_osfhandle(filedes[1]),
+                       parent, &h[1], 0, FALSE, DUPLICATE_SAME_ACCESS)) {
+               close(filedes[0]);
+               close(filedes[1]);
+               CloseHandle(h[0]);
+               return -1;
+       }
+       fd = _open_osfhandle((int)h[0], O_NOINHERIT);
+       if (fd < 0) {
+               close(filedes[0]);
+               close(filedes[1]);
+               CloseHandle(h[0]);
+               CloseHandle(h[1]);
+               return -1;
+       }
+       close(filedes[0]);
+       filedes[0] = fd;
+       fd = _open_osfhandle((int)h[1], O_NOINHERIT);
+       if (fd < 0) {
+               close(filedes[0]);
+               close(filedes[1]);
+               CloseHandle(h[1]);
+               return -1;
+       }
+       close(filedes[1]);
+       filedes[1] = fd;
+       return 0;
+}
+
+int poll(struct pollfd *ufds, unsigned int nfds, int timeout)
+{
+       int i, pending;
+
+       if (timeout != -1)
+               return errno = EINVAL, error("poll timeout not supported");
+
+       /* When there is only one fd to wait for, then we pretend that
+        * input is available and let the actual wait happen when the
+        * caller invokes read().
+        */
+       if (nfds == 1) {
+               if (!(ufds[0].events & POLLIN))
+                       return errno = EINVAL, error("POLLIN not set");
+               ufds[0].revents = POLLIN;
+               return 0;
+       }
+
+repeat:
+       pending = 0;
+       for (i = 0; i < nfds; i++) {
+               DWORD avail = 0;
+               HANDLE h = (HANDLE) _get_osfhandle(ufds[i].fd);
+               if (h == INVALID_HANDLE_VALUE)
+                       return -1;      /* errno was set */
+
+               if (!(ufds[i].events & POLLIN))
+                       return errno = EINVAL, error("POLLIN not set");
+
+               /* this emulation works only for pipes */
+               if (!PeekNamedPipe(h, NULL, 0, NULL, &avail, NULL)) {
+                       int err = GetLastError();
+                       if (err == ERROR_BROKEN_PIPE) {
+                               ufds[i].revents = POLLHUP;
+                               pending++;
+                       } else {
+                               errno = EINVAL;
+                               return error("PeekNamedPipe failed,"
+                                       " GetLastError: %u", err);
+                       }
+               } else if (avail) {
+                       ufds[i].revents = POLLIN;
+                       pending++;
+               } else
+                       ufds[i].revents = 0;
+       }
+       if (!pending) {
+               /* The only times that we spin here is when the process
+                * that is connected through the pipes is waiting for
+                * its own input data to become available. But since
+                * the process (pack-objects) is itself CPU intensive,
+                * it will happily pick up the time slice that we are
+                * relinguishing here.
+                */
+               Sleep(0);
+               goto repeat;
+       }
+       return 0;
+}
+
+struct tm *gmtime_r(const time_t *timep, struct tm *result)
+{
+       /* gmtime() in MSVCRT.DLL is thread-safe, but not reentrant */
+       memcpy(result, gmtime(timep), sizeof(struct tm));
+       return result;
+}
+
+struct tm *localtime_r(const time_t *timep, struct tm *result)
+{
+       /* localtime() in MSVCRT.DLL is thread-safe, but not reentrant */
+       memcpy(result, localtime(timep), sizeof(struct tm));
+       return result;
+}
+
+#undef getcwd
+char *mingw_getcwd(char *pointer, int len)
+{
+       int i;
+       char *ret = getcwd(pointer, len);
+       if (!ret)
+               return ret;
+       for (i = 0; pointer[i]; i++)
+               if (pointer[i] == '\\')
+                       pointer[i] = '/';
+       return ret;
+}
+
+#undef getenv
+char *mingw_getenv(const char *name)
+{
+       char *result = getenv(name);
+       if (!result && !strcmp(name, "TMPDIR")) {
+               /* on Windows it is TMP and TEMP */
+               result = getenv("TMP");
+               if (!result)
+                       result = getenv("TEMP");
+       }
+       return result;
+}
+
+/*
+ * See http://msdn2.microsoft.com/en-us/library/17w5ykft(vs.71).aspx
+ * (Parsing C++ Command-Line Arguments)
+ */
+static const char *quote_arg(const char *arg)
+{
+       /* count chars to quote */
+       int len = 0, n = 0;
+       int force_quotes = 0;
+       char *q, *d;
+       const char *p = arg;
+       if (!*p) force_quotes = 1;
+       while (*p) {
+               if (isspace(*p) || *p == '*' || *p == '?' || *p == '{')
+                       force_quotes = 1;
+               else if (*p == '"')
+                       n++;
+               else if (*p == '\\') {
+                       int count = 0;
+                       while (*p == '\\') {
+                               count++;
+                               p++;
+                               len++;
+                       }
+                       if (*p == '"')
+                               n += count*2 + 1;
+                       continue;
+               }
+               len++;
+               p++;
+       }
+       if (!force_quotes && n == 0)
+               return arg;
+
+       /* insert \ where necessary */
+       d = q = xmalloc(len+n+3);
+       *d++ = '"';
+       while (*arg) {
+               if (*arg == '"')
+                       *d++ = '\\';
+               else if (*arg == '\\') {
+                       int count = 0;
+                       while (*arg == '\\') {
+                               count++;
+                               *d++ = *arg++;
+                       }
+                       if (*arg == '"') {
+                               while (count-- > 0)
+                                       *d++ = '\\';
+                               *d++ = '\\';
+                       }
+               }
+               *d++ = *arg++;
+       }
+       *d++ = '"';
+       *d++ = 0;
+       return q;
+}
+
+static const char *parse_interpreter(const char *cmd)
+{
+       static char buf[100];
+       char *p, *opt;
+       int n, fd;
+
+       /* don't even try a .exe */
+       n = strlen(cmd);
+       if (n >= 4 && !strcasecmp(cmd+n-4, ".exe"))
+               return NULL;
+
+       fd = open(cmd, O_RDONLY);
+       if (fd < 0)
+               return NULL;
+       n = read(fd, buf, sizeof(buf)-1);
+       close(fd);
+       if (n < 4)      /* at least '#!/x' and not error */
+               return NULL;
+
+       if (buf[0] != '#' || buf[1] != '!')
+               return NULL;
+       buf[n] = '\0';
+       p = strchr(buf, '\n');
+       if (!p)
+               return NULL;
+
+       *p = '\0';
+       if (!(p = strrchr(buf+2, '/')) && !(p = strrchr(buf+2, '\\')))
+               return NULL;
+       /* strip options */
+       if ((opt = strchr(p+1, ' ')))
+               *opt = '\0';
+       return p+1;
+}
+
+/*
+ * Splits the PATH into parts.
+ */
+static char **get_path_split(void)
+{
+       char *p, **path, *envpath = getenv("PATH");
+       int i, n = 0;
+
+       if (!envpath || !*envpath)
+               return NULL;
+
+       envpath = xstrdup(envpath);
+       p = envpath;
+       while (p) {
+               char *dir = p;
+               p = strchr(p, ';');
+               if (p) *p++ = '\0';
+               if (*dir) {     /* not earlier, catches series of ; */
+                       ++n;
+               }
+       }
+       if (!n)
+               return NULL;
+
+       path = xmalloc((n+1)*sizeof(char*));
+       p = envpath;
+       i = 0;
+       do {
+               if (*p)
+                       path[i++] = xstrdup(p);
+               p = p+strlen(p)+1;
+       } while (i < n);
+       path[i] = NULL;
+
+       free(envpath);
+
+       return path;
+}
+
+static void free_path_split(char **path)
+{
+       if (!path)
+               return;
+
+       char **p = path;
+       while (*p)
+               free(*p++);
+       free(path);
+}
+
+/*
+ * exe_only means that we only want to detect .exe files, but not scripts
+ * (which do not have an extension)
+ */
+static char *lookup_prog(const char *dir, const char *cmd, int isexe, int exe_only)
+{
+       char path[MAX_PATH];
+       snprintf(path, sizeof(path), "%s/%s.exe", dir, cmd);
+
+       if (!isexe && access(path, F_OK) == 0)
+               return xstrdup(path);
+       path[strlen(path)-4] = '\0';
+       if ((!exe_only || isexe) && access(path, F_OK) == 0)
+               return xstrdup(path);
+       return NULL;
+}
+
+/*
+ * Determines the absolute path of cmd using the the split path in path.
+ * If cmd contains a slash or backslash, no lookup is performed.
+ */
+static char *path_lookup(const char *cmd, char **path, int exe_only)
+{
+       char *prog = NULL;
+       int len = strlen(cmd);
+       int isexe = len >= 4 && !strcasecmp(cmd+len-4, ".exe");
+
+       if (strchr(cmd, '/') || strchr(cmd, '\\'))
+               prog = xstrdup(cmd);
+
+       while (!prog && *path)
+               prog = lookup_prog(*path++, cmd, isexe, exe_only);
+
+       return prog;
+}
+
+static int env_compare(const void *a, const void *b)
+{
+       char *const *ea = a;
+       char *const *eb = b;
+       return strcasecmp(*ea, *eb);
+}
+
+static pid_t mingw_spawnve(const char *cmd, const char **argv, char **env,
+                          int prepend_cmd)
+{
+       STARTUPINFO si;
+       PROCESS_INFORMATION pi;
+       struct strbuf envblk, args;
+       unsigned flags;
+       BOOL ret;
+
+       /* Determine whether or not we are associated to a console */
+       HANDLE cons = CreateFile("CONOUT$", GENERIC_WRITE,
+                       FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
+                       FILE_ATTRIBUTE_NORMAL, NULL);
+       if (cons == INVALID_HANDLE_VALUE) {
+               /* There is no console associated with this process.
+                * Since the child is a console process, Windows
+                * would normally create a console window. But
+                * since we'll be redirecting std streams, we do
+                * not need the console.
+                */
+               flags = CREATE_NO_WINDOW;
+       } else {
+               /* There is already a console. If we specified
+                * CREATE_NO_WINDOW here, too, Windows would
+                * disassociate the child from the console.
+                * Go figure!
+                */
+               flags = 0;
+               CloseHandle(cons);
+       }
+       memset(&si, 0, sizeof(si));
+       si.cb = sizeof(si);
+       si.dwFlags = STARTF_USESTDHANDLES;
+       si.hStdInput = (HANDLE) _get_osfhandle(0);
+       si.hStdOutput = (HANDLE) _get_osfhandle(1);
+       si.hStdError = (HANDLE) _get_osfhandle(2);
+
+       /* concatenate argv, quoting args as we go */
+       strbuf_init(&args, 0);
+       if (prepend_cmd) {
+               char *quoted = (char *)quote_arg(cmd);
+               strbuf_addstr(&args, quoted);
+               if (quoted != cmd)
+                       free(quoted);
+       }
+       for (; *argv; argv++) {
+               char *quoted = (char *)quote_arg(*argv);
+               if (*args.buf)
+                       strbuf_addch(&args, ' ');
+               strbuf_addstr(&args, quoted);
+               if (quoted != *argv)
+                       free(quoted);
+       }
+
+       if (env) {
+               int count = 0;
+               char **e, **sorted_env;
+
+               for (e = env; *e; e++)
+                       count++;
+
+               /* environment must be sorted */
+               sorted_env = xmalloc(sizeof(*sorted_env) * (count + 1));
+               memcpy(sorted_env, env, sizeof(*sorted_env) * (count + 1));
+               qsort(sorted_env, count, sizeof(*sorted_env), env_compare);
+
+               strbuf_init(&envblk, 0);
+               for (e = sorted_env; *e; e++) {
+                       strbuf_addstr(&envblk, *e);
+                       strbuf_addch(&envblk, '\0');
+               }
+               free(sorted_env);
+       }
+
+       memset(&pi, 0, sizeof(pi));
+       ret = CreateProcess(cmd, args.buf, NULL, NULL, TRUE, flags,
+               env ? envblk.buf : NULL, NULL, &si, &pi);
+
+       if (env)
+               strbuf_release(&envblk);
+       strbuf_release(&args);
+
+       if (!ret) {
+               errno = ENOENT;
+               return -1;
+       }
+       CloseHandle(pi.hThread);
+       return (pid_t)pi.hProcess;
+}
+
+pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env)
+{
+       pid_t pid;
+       char **path = get_path_split();
+       char *prog = path_lookup(cmd, path, 0);
+
+       if (!prog) {
+               errno = ENOENT;
+               pid = -1;
+       }
+       else {
+               const char *interpr = parse_interpreter(prog);
+
+               if (interpr) {
+                       const char *argv0 = argv[0];
+                       char *iprog = path_lookup(interpr, path, 1);
+                       argv[0] = prog;
+                       if (!iprog) {
+                               errno = ENOENT;
+                               pid = -1;
+                       }
+                       else {
+                               pid = mingw_spawnve(iprog, argv, env, 1);
+                               free(iprog);
+                       }
+                       argv[0] = argv0;
+               }
+               else
+                       pid = mingw_spawnve(prog, argv, env, 0);
+               free(prog);
+       }
+       free_path_split(path);
+       return pid;
+}
+
+static int try_shell_exec(const char *cmd, char *const *argv, char **env)
+{
+       const char *interpr = parse_interpreter(cmd);
+       char **path;
+       char *prog;
+       int pid = 0;
+
+       if (!interpr)
+               return 0;
+       path = get_path_split();
+       prog = path_lookup(interpr, path, 1);
+       if (prog) {
+               int argc = 0;
+               const char **argv2;
+               while (argv[argc]) argc++;
+               argv2 = xmalloc(sizeof(*argv) * (argc+1));
+               argv2[0] = (char *)cmd; /* full path to the script file */
+               memcpy(&argv2[1], &argv[1], sizeof(*argv) * argc);
+               pid = mingw_spawnve(prog, argv2, env, 1);
+               if (pid >= 0) {
+                       int status;
+                       if (waitpid(pid, &status, 0) < 0)
+                               status = 255;
+                       exit(status);
+               }
+               pid = 1;        /* indicate that we tried but failed */
+               free(prog);
+               free(argv2);
+       }
+       free_path_split(path);
+       return pid;
+}
+
+static void mingw_execve(const char *cmd, char *const *argv, char *const *env)
+{
+       /* check if git_command is a shell script */
+       if (!try_shell_exec(cmd, argv, (char **)env)) {
+               int pid, status;
+
+               pid = mingw_spawnve(cmd, (const char **)argv, (char **)env, 0);
+               if (pid < 0)
+                       return;
+               if (waitpid(pid, &status, 0) < 0)
+                       status = 255;
+               exit(status);
+       }
+}
+
+void mingw_execvp(const char *cmd, char *const *argv)
+{
+       char **path = get_path_split();
+       char *prog = path_lookup(cmd, path, 0);
+
+       if (prog) {
+               mingw_execve(prog, argv, environ);
+               free(prog);
+       } else
+               errno = ENOENT;
+
+       free_path_split(path);
+}
+
+char **copy_environ()
+{
+       char **env;
+       int i = 0;
+       while (environ[i])
+               i++;
+       env = xmalloc((i+1)*sizeof(*env));
+       for (i = 0; environ[i]; i++)
+               env[i] = xstrdup(environ[i]);
+       env[i] = NULL;
+       return env;
+}
+
+void free_environ(char **env)
+{
+       int i;
+       for (i = 0; env[i]; i++)
+               free(env[i]);
+       free(env);
+}
+
+static int lookup_env(char **env, const char *name, size_t nmln)
+{
+       int i;
+
+       for (i = 0; env[i]; i++) {
+               if (0 == strncmp(env[i], name, nmln)
+                   && '=' == env[i][nmln])
+                       /* matches */
+                       return i;
+       }
+       return -1;
+}
+
+/*
+ * If name contains '=', then sets the variable, otherwise it unsets it
+ */
+char **env_setenv(char **env, const char *name)
+{
+       char *eq = strchrnul(name, '=');
+       int i = lookup_env(env, name, eq-name);
+
+       if (i < 0) {
+               if (*eq) {
+                       for (i = 0; env[i]; i++)
+                               ;
+                       env = xrealloc(env, (i+2)*sizeof(*env));
+                       env[i] = xstrdup(name);
+                       env[i+1] = NULL;
+               }
+       }
+       else {
+               free(env[i]);
+               if (*eq)
+                       env[i] = xstrdup(name);
+               else
+                       for (; env[i]; i++)
+                               env[i] = env[i+1];
+       }
+       return env;
+}
+
+/* this is the first function to call into WS_32; initialize it */
+#undef gethostbyname
+struct hostent *mingw_gethostbyname(const char *host)
+{
+       WSADATA wsa;
+
+       if (WSAStartup(MAKEWORD(2,2), &wsa))
+               die("unable to initialize winsock subsystem, error %d",
+                       WSAGetLastError());
+       atexit((void(*)(void)) WSACleanup);
+       return gethostbyname(host);
+}
+
+int mingw_socket(int domain, int type, int protocol)
+{
+       int sockfd;
+       SOCKET s = WSASocket(domain, type, protocol, NULL, 0, 0);
+       if (s == INVALID_SOCKET) {
+               /*
+                * WSAGetLastError() values are regular BSD error codes
+                * biased by WSABASEERR.
+                * However, strerror() does not know about networking
+                * specific errors, which are values beginning at 38 or so.
+                * Therefore, we choose to leave the biased error code
+                * in errno so that _if_ someone looks up the code somewhere,
+                * then it is at least the number that are usually listed.
+                */
+               errno = WSAGetLastError();
+               return -1;
+       }
+       /* convert into a file descriptor */
+       if ((sockfd = _open_osfhandle(s, O_RDWR|O_BINARY)) < 0) {
+               closesocket(s);
+               return error("unable to make a socket file descriptor: %s",
+                       strerror(errno));
+       }
+       return sockfd;
+}
+
+#undef connect
+int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz)
+{
+       SOCKET s = (SOCKET)_get_osfhandle(sockfd);
+       return connect(s, sa, sz);
+}
+
+#undef rename
+int mingw_rename(const char *pold, const char *pnew)
+{
+       /*
+        * Try native rename() first to get errno right.
+        * It is based on MoveFile(), which cannot overwrite existing files.
+        */
+       if (!rename(pold, pnew))
+               return 0;
+       if (errno != EEXIST)
+               return -1;
+       if (MoveFileEx(pold, pnew, MOVEFILE_REPLACE_EXISTING))
+               return 0;
+       /* TODO: translate more errors */
+       if (GetLastError() == ERROR_ACCESS_DENIED) {
+               DWORD attrs = GetFileAttributes(pnew);
+               if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY)) {
+                       errno = EISDIR;
+                       return -1;
+               }
+       }
+       errno = EACCES;
+       return -1;
+}
+
+struct passwd *getpwuid(int uid)
+{
+       static char user_name[100];
+       static struct passwd p;
+
+       DWORD len = sizeof(user_name);
+       if (!GetUserName(user_name, &len))
+               return NULL;
+       p.pw_name = user_name;
+       p.pw_gecos = "unknown";
+       p.pw_dir = NULL;
+       return &p;
+}
+
+static HANDLE timer_event;
+static HANDLE timer_thread;
+static int timer_interval;
+static int one_shot;
+static sig_handler_t timer_fn = SIG_DFL;
+
+/* The timer works like this:
+ * The thread, ticktack(), is a trivial routine that most of the time
+ * only waits to receive the signal to terminate. The main thread tells
+ * the thread to terminate by setting the timer_event to the signalled
+ * state.
+ * But ticktack() interrupts the wait state after the timer's interval
+ * length to call the signal handler.
+ */
+
+static __stdcall unsigned ticktack(void *dummy)
+{
+       while (WaitForSingleObject(timer_event, timer_interval) == WAIT_TIMEOUT) {
+               if (timer_fn == SIG_DFL)
+                       die("Alarm");
+               if (timer_fn != SIG_IGN)
+                       timer_fn(SIGALRM);
+               if (one_shot)
+                       break;
+       }
+       return 0;
+}
+
+static int start_timer_thread(void)
+{
+       timer_event = CreateEvent(NULL, FALSE, FALSE, NULL);
+       if (timer_event) {
+               timer_thread = (HANDLE) _beginthreadex(NULL, 0, ticktack, NULL, 0, NULL);
+               if (!timer_thread )
+                       return errno = ENOMEM,
+                               error("cannot start timer thread");
+       } else
+               return errno = ENOMEM,
+                       error("cannot allocate resources for timer");
+       return 0;
+}
+
+static void stop_timer_thread(void)
+{
+       if (timer_event)
+               SetEvent(timer_event);  /* tell thread to terminate */
+       if (timer_thread) {
+               int rc = WaitForSingleObject(timer_thread, 1000);
+               if (rc == WAIT_TIMEOUT)
+                       error("timer thread did not terminate timely");
+               else if (rc != WAIT_OBJECT_0)
+                       error("waiting for timer thread failed: %lu",
+                             GetLastError());
+               CloseHandle(timer_thread);
+       }
+       if (timer_event)
+               CloseHandle(timer_event);
+       timer_event = NULL;
+       timer_thread = NULL;
+}
+
+static inline int is_timeval_eq(const struct timeval *i1, const struct timeval *i2)
+{
+       return i1->tv_sec == i2->tv_sec && i1->tv_usec == i2->tv_usec;
+}
+
+int setitimer(int type, struct itimerval *in, struct itimerval *out)
+{
+       static const struct timeval zero;
+       static int atexit_done;
+
+       if (out != NULL)
+               return errno = EINVAL,
+                       error("setitimer param 3 != NULL not implemented");
+       if (!is_timeval_eq(&in->it_interval, &zero) &&
+           !is_timeval_eq(&in->it_interval, &in->it_value))
+               return errno = EINVAL,
+                       error("setitimer: it_interval must be zero or eq it_value");
+
+       if (timer_thread)
+               stop_timer_thread();
+
+       if (is_timeval_eq(&in->it_value, &zero) &&
+           is_timeval_eq(&in->it_interval, &zero))
+               return 0;
+
+       timer_interval = in->it_value.tv_sec * 1000 + in->it_value.tv_usec / 1000;
+       one_shot = is_timeval_eq(&in->it_interval, &zero);
+       if (!atexit_done) {
+               atexit(stop_timer_thread);
+               atexit_done = 1;
+       }
+       return start_timer_thread();
+}
+
+int sigaction(int sig, struct sigaction *in, struct sigaction *out)
+{
+       if (sig != SIGALRM)
+               return errno = EINVAL,
+                       error("sigaction only implemented for SIGALRM");
+       if (out != NULL)
+               return errno = EINVAL,
+                       error("sigaction: param 3 != NULL not implemented");
+
+       timer_fn = in->sa_handler;
+       return 0;
+}
+
+#undef signal
+sig_handler_t mingw_signal(int sig, sig_handler_t handler)
+{
+       if (sig != SIGALRM)
+               return signal(sig, handler);
+       sig_handler_t old = timer_fn;
+       timer_fn = handler;
+       return old;
+}
diff --git a/compat/mingw.h b/compat/mingw.h
new file mode 100644 (file)
index 0000000..6bc049a
--- /dev/null
@@ -0,0 +1,211 @@
+#include <winsock2.h>
+
+/*
+ * things that are not available in header files
+ */
+
+typedef int pid_t;
+#define hstrerror strerror
+
+#define S_IFLNK    0120000 /* Symbolic link */
+#define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK)
+#define S_ISSOCK(x) 0
+#define S_IRGRP 0
+#define S_IWGRP 0
+#define S_IXGRP 0
+#define S_ISGID 0
+#define S_IROTH 0
+#define S_IXOTH 0
+
+#define WIFEXITED(x) ((unsigned)(x) < 259)     /* STILL_ACTIVE */
+#define WEXITSTATUS(x) ((x) & 0xff)
+#define WIFSIGNALED(x) ((unsigned)(x) > 259)
+
+#define SIGKILL 0
+#define SIGCHLD 0
+#define SIGPIPE 0
+#define SIGHUP 0
+#define SIGQUIT 0
+#define SIGALRM 100
+
+#define F_GETFD 1
+#define F_SETFD 2
+#define FD_CLOEXEC 0x1
+
+struct passwd {
+       char *pw_name;
+       char *pw_gecos;
+       char *pw_dir;
+};
+
+struct pollfd {
+       int fd;           /* file descriptor */
+       short events;     /* requested events */
+       short revents;    /* returned events */
+};
+#define POLLIN 1
+#define POLLHUP 2
+
+typedef void (__cdecl *sig_handler_t)(int);
+struct sigaction {
+       sig_handler_t sa_handler;
+       unsigned sa_flags;
+};
+#define sigemptyset(x) (void)0
+#define SA_RESTART 0
+
+struct itimerval {
+       struct timeval it_value, it_interval;
+};
+#define ITIMER_REAL 0
+
+/*
+ * trivial stubs
+ */
+
+static inline int readlink(const char *path, char *buf, size_t bufsiz)
+{ errno = ENOSYS; return -1; }
+static inline int symlink(const char *oldpath, const char *newpath)
+{ errno = ENOSYS; return -1; }
+static inline int link(const char *oldpath, const char *newpath)
+{ errno = ENOSYS; return -1; }
+static inline int fchmod(int fildes, mode_t mode)
+{ errno = ENOSYS; return -1; }
+static inline int fork(void)
+{ errno = ENOSYS; return -1; }
+static inline unsigned int alarm(unsigned int seconds)
+{ return 0; }
+static inline int fsync(int fd)
+{ return 0; }
+static inline int getppid(void)
+{ return 1; }
+static inline void sync(void)
+{}
+static inline int getuid()
+{ return 1; }
+static inline struct passwd *getpwnam(const char *name)
+{ return NULL; }
+static inline int fcntl(int fd, int cmd, long arg)
+{
+       if (cmd == F_GETFD || cmd == F_SETFD)
+               return 0;
+       errno = EINVAL;
+       return -1;
+}
+
+/*
+ * simple adaptors
+ */
+
+static inline int mingw_mkdir(const char *path, int mode)
+{
+       return mkdir(path);
+}
+#define mkdir mingw_mkdir
+
+static inline int mingw_unlink(const char *pathname)
+{
+       /* read-only files cannot be removed */
+       chmod(pathname, 0666);
+       return unlink(pathname);
+}
+#define unlink mingw_unlink
+
+static inline int waitpid(pid_t pid, unsigned *status, unsigned options)
+{
+       if (options == 0)
+               return _cwait(status, pid, 0);
+       errno = EINVAL;
+       return -1;
+}
+
+/*
+ * implementations of missing functions
+ */
+
+int pipe(int filedes[2]);
+unsigned int sleep (unsigned int seconds);
+int mkstemp(char *template);
+int gettimeofday(struct timeval *tv, void *tz);
+int poll(struct pollfd *ufds, unsigned int nfds, int timeout);
+struct tm *gmtime_r(const time_t *timep, struct tm *result);
+struct tm *localtime_r(const time_t *timep, struct tm *result);
+int getpagesize(void); /* defined in MinGW's libgcc.a */
+struct passwd *getpwuid(int uid);
+int setitimer(int type, struct itimerval *in, struct itimerval *out);
+int sigaction(int sig, struct sigaction *in, struct sigaction *out);
+
+/*
+ * replacements of existing functions
+ */
+
+int mingw_open (const char *filename, int oflags, ...);
+#define open mingw_open
+
+char *mingw_getcwd(char *pointer, int len);
+#define getcwd mingw_getcwd
+
+char *mingw_getenv(const char *name);
+#define getenv mingw_getenv
+
+struct hostent *mingw_gethostbyname(const char *host);
+#define gethostbyname mingw_gethostbyname
+
+int mingw_socket(int domain, int type, int protocol);
+#define socket mingw_socket
+
+int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz);
+#define connect mingw_connect
+
+int mingw_rename(const char*, const char*);
+#define rename mingw_rename
+
+/* Use mingw_lstat() instead of lstat()/stat() and
+ * mingw_fstat() instead of fstat() on Windows.
+ * struct stat is redefined because it lacks the st_blocks member.
+ */
+struct mingw_stat {
+       unsigned st_mode;
+       time_t st_mtime, st_atime, st_ctime;
+       unsigned st_dev, st_ino, st_uid, st_gid;
+       size_t st_size;
+       size_t st_blocks;
+};
+int mingw_lstat(const char *file_name, struct mingw_stat *buf);
+int mingw_fstat(int fd, struct mingw_stat *buf);
+#define fstat mingw_fstat
+#define lstat mingw_lstat
+#define stat mingw_stat
+static inline int mingw_stat(const char *file_name, struct mingw_stat *buf)
+{ return mingw_lstat(file_name, buf); }
+
+int mingw_utime(const char *file_name, const struct utimbuf *times);
+#define utime mingw_utime
+
+pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env);
+void mingw_execvp(const char *cmd, char *const *argv);
+#define execvp mingw_execvp
+
+static inline unsigned int git_ntohl(unsigned int x)
+{ return (unsigned int)ntohl(x); }
+#define ntohl git_ntohl
+
+sig_handler_t mingw_signal(int sig, sig_handler_t handler);
+#define signal mingw_signal
+
+/*
+ * git specific compatibility
+ */
+
+#define has_dos_drive_prefix(path) (isalpha(*(path)) && (path)[1] == ':')
+#define is_dir_sep(c) ((c) == '/' || (c) == '\\')
+#define PATH_SEP ';'
+#define PRIuMAX "I64u"
+
+/*
+ * helpers
+ */
+
+char **copy_environ(void);
+void free_environ(char **env);
+char **env_setenv(char **env, const char *name);
diff --git a/compat/regex.c b/compat/regex.c
new file mode 100644 (file)
index 0000000..87b33e4
--- /dev/null
@@ -0,0 +1,4927 @@
+/* Extended regular expression matching and search library,
+   version 0.12.
+   (Implements POSIX draft P10003.2/D11.2, except for
+   internationalization features.)
+
+   Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* AIX requires this to be the first thing in the file. */
+#if defined (_AIX) && !defined (REGEX_MALLOC)
+  #pragma alloca
+#endif
+
+#define _GNU_SOURCE
+
+/* We need this for `regex.h', and perhaps for the Emacs include files.  */
+#include <sys/types.h>
+
+/* We used to test for `BSTRING' here, but only GCC and Emacs define
+   `BSTRING', as far as I know, and neither of them use this code.  */
+#include <string.h>
+#ifndef bcmp
+#define bcmp(s1, s2, n)        memcmp ((s1), (s2), (n))
+#endif
+#ifndef bcopy
+#define bcopy(s, d, n) memcpy ((d), (s), (n))
+#endif
+#ifndef bzero
+#define bzero(s, n)    memset ((s), 0, (n))
+#endif
+
+#include <stdlib.h>
+
+
+/* Define the syntax stuff for \<, \>, etc.  */
+
+/* This must be nonzero for the wordchar and notwordchar pattern
+   commands in re_match_2.  */
+#ifndef Sword
+#define Sword 1
+#endif
+
+#ifdef SYNTAX_TABLE
+
+extern char *re_syntax_table;
+
+#else /* not SYNTAX_TABLE */
+
+/* How many characters in the character set.  */
+#define CHAR_SET_SIZE 256
+
+static char re_syntax_table[CHAR_SET_SIZE];
+
+static void
+init_syntax_once ()
+{
+   register int c;
+   static int done = 0;
+
+   if (done)
+     return;
+
+   bzero (re_syntax_table, sizeof re_syntax_table);
+
+   for (c = 'a'; c <= 'z'; c++)
+     re_syntax_table[c] = Sword;
+
+   for (c = 'A'; c <= 'Z'; c++)
+     re_syntax_table[c] = Sword;
+
+   for (c = '0'; c <= '9'; c++)
+     re_syntax_table[c] = Sword;
+
+   re_syntax_table['_'] = Sword;
+
+   done = 1;
+}
+
+#endif /* not SYNTAX_TABLE */
+
+#define SYNTAX(c) re_syntax_table[c]
+
+\f
+/* Get the interface, including the syntax bits.  */
+#include "regex.h"
+
+/* isalpha etc. are used for the character classes.  */
+#include <ctype.h>
+
+#ifndef isascii
+#define isascii(c) 1
+#endif
+
+#ifdef isblank
+#define ISBLANK(c) (isascii (c) && isblank (c))
+#else
+#define ISBLANK(c) ((c) == ' ' || (c) == '\t')
+#endif
+#ifdef isgraph
+#define ISGRAPH(c) (isascii (c) && isgraph (c))
+#else
+#define ISGRAPH(c) (isascii (c) && isprint (c) && !isspace (c))
+#endif
+
+#define ISPRINT(c) (isascii (c) && isprint (c))
+#define ISDIGIT(c) (isascii (c) && isdigit (c))
+#define ISALNUM(c) (isascii (c) && isalnum (c))
+#define ISALPHA(c) (isascii (c) && isalpha (c))
+#define ISCNTRL(c) (isascii (c) && iscntrl (c))
+#define ISLOWER(c) (isascii (c) && islower (c))
+#define ISPUNCT(c) (isascii (c) && ispunct (c))
+#define ISSPACE(c) (isascii (c) && isspace (c))
+#define ISUPPER(c) (isascii (c) && isupper (c))
+#define ISXDIGIT(c) (isascii (c) && isxdigit (c))
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/* We remove any previous definition of `SIGN_EXTEND_CHAR',
+   since ours (we hope) works properly with all combinations of
+   machines, compilers, `char' and `unsigned char' argument types.
+   (Per Bothner suggested the basic approach.)  */
+#undef SIGN_EXTEND_CHAR
+#if __STDC__
+#define SIGN_EXTEND_CHAR(c) ((signed char) (c))
+#else  /* not __STDC__ */
+/* As in Harbison and Steele.  */
+#define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128)
+#endif
+\f
+/* Should we use malloc or alloca?  If REGEX_MALLOC is not defined, we
+   use `alloca' instead of `malloc'.  This is because using malloc in
+   re_search* or re_match* could cause memory leaks when C-g is used in
+   Emacs; also, malloc is slower and causes storage fragmentation.  On
+   the other hand, malloc is more portable, and easier to debug.
+
+   Because we sometimes use alloca, some routines have to be macros,
+   not functions -- `alloca'-allocated space disappears at the end of the
+   function it is called in.  */
+
+#ifdef REGEX_MALLOC
+
+#define REGEX_ALLOCATE malloc
+#define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize)
+
+#else /* not REGEX_MALLOC  */
+
+/* Emacs already defines alloca, sometimes.  */
+#ifndef alloca
+
+/* Make alloca work the best possible way.  */
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* not __GNUC__ */
+#if HAVE_ALLOCA_H
+#include <alloca.h>
+#else /* not __GNUC__ or HAVE_ALLOCA_H */
+#ifndef _AIX /* Already did AIX, up at the top.  */
+char *alloca ();
+#endif /* not _AIX */
+#endif /* not HAVE_ALLOCA_H */
+#endif /* not __GNUC__ */
+
+#endif /* not alloca */
+
+#define REGEX_ALLOCATE alloca
+
+/* Assumes a `char *destination' variable.  */
+#define REGEX_REALLOCATE(source, osize, nsize)                         \
+  (destination = (char *) alloca (nsize),                              \
+   bcopy (source, destination, osize),                                 \
+   destination)
+
+#endif /* not REGEX_MALLOC */
+
+
+/* True if `size1' is non-NULL and PTR is pointing anywhere inside
+   `string1' or just past its end.  This works if PTR is NULL, which is
+   a good thing.  */
+#define FIRST_STRING_P(ptr)                                    \
+  (size1 && string1 <= (ptr) && (ptr) <= string1 + size1)
+
+/* (Re)Allocate N items of type T using malloc, or fail.  */
+#define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t)))
+#define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t)))
+#define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t)))
+
+#define BYTEWIDTH 8 /* In bits.  */
+
+#define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
+
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+typedef char boolean;
+#define false 0
+#define true 1
+\f
+/* These are the command codes that appear in compiled regular
+   expressions.  Some opcodes are followed by argument bytes.  A
+   command code can specify any interpretation whatsoever for its
+   arguments.  Zero bytes may appear in the compiled regular expression.
+
+   The value of `exactn' is needed in search.c (search_buffer) in Emacs.
+   So regex.h defines a symbol `RE_EXACTN_VALUE' to be 1; the value of
+   `exactn' we use here must also be 1.  */
+
+typedef enum
+{
+  no_op = 0,
+
+       /* Followed by one byte giving n, then by n literal bytes.  */
+  exactn = 1,
+
+       /* Matches any (more or less) character.  */
+  anychar,
+
+       /* Matches any one char belonging to specified set.  First
+          following byte is number of bitmap bytes.  Then come bytes
+          for a bitmap saying which chars are in.  Bits in each byte
+          are ordered low-bit-first.  A character is in the set if its
+          bit is 1.  A character too large to have a bit in the map is
+          automatically not in the set.  */
+  charset,
+
+       /* Same parameters as charset, but match any character that is
+          not one of those specified.  */
+  charset_not,
+
+       /* Start remembering the text that is matched, for storing in a
+          register.  Followed by one byte with the register number, in
+          the range 0 to one less than the pattern buffer's re_nsub
+          field.  Then followed by one byte with the number of groups
+          inner to this one.  (This last has to be part of the
+          start_memory only because we need it in the on_failure_jump
+          of re_match_2.)  */
+  start_memory,
+
+       /* Stop remembering the text that is matched and store it in a
+          memory register.  Followed by one byte with the register
+          number, in the range 0 to one less than `re_nsub' in the
+          pattern buffer, and one byte with the number of inner groups,
+          just like `start_memory'.  (We need the number of inner
+          groups here because we don't have any easy way of finding the
+          corresponding start_memory when we're at a stop_memory.)  */
+  stop_memory,
+
+       /* Match a duplicate of something remembered. Followed by one
+          byte containing the register number.  */
+  duplicate,
+
+       /* Fail unless at beginning of line.  */
+  begline,
+
+       /* Fail unless at end of line.  */
+  endline,
+
+       /* Succeeds if at beginning of buffer (if emacs) or at beginning
+          of string to be matched (if not).  */
+  begbuf,
+
+       /* Analogously, for end of buffer/string.  */
+  endbuf,
+
+       /* Followed by two byte relative address to which to jump.  */
+  jump,
+
+       /* Same as jump, but marks the end of an alternative.  */
+  jump_past_alt,
+
+       /* Followed by two-byte relative address of place to resume at
+          in case of failure.  */
+  on_failure_jump,
+
+       /* Like on_failure_jump, but pushes a placeholder instead of the
+          current string position when executed.  */
+  on_failure_keep_string_jump,
+
+       /* Throw away latest failure point and then jump to following
+          two-byte relative address.  */
+  pop_failure_jump,
+
+       /* Change to pop_failure_jump if know won't have to backtrack to
+          match; otherwise change to jump.  This is used to jump
+          back to the beginning of a repeat.  If what follows this jump
+          clearly won't match what the repeat does, such that we can be
+          sure that there is no use backtracking out of repetitions
+          already matched, then we change it to a pop_failure_jump.
+          Followed by two-byte address.  */
+  maybe_pop_jump,
+
+       /* Jump to following two-byte address, and push a dummy failure
+          point. This failure point will be thrown away if an attempt
+          is made to use it for a failure.  A `+' construct makes this
+          before the first repeat.  Also used as an intermediary kind
+          of jump when compiling an alternative.  */
+  dummy_failure_jump,
+
+       /* Push a dummy failure point and continue.  Used at the end of
+          alternatives.  */
+  push_dummy_failure,
+
+       /* Followed by two-byte relative address and two-byte number n.
+          After matching N times, jump to the address upon failure.  */
+  succeed_n,
+
+       /* Followed by two-byte relative address, and two-byte number n.
+          Jump to the address N times, then fail.  */
+  jump_n,
+
+       /* Set the following two-byte relative address to the
+          subsequent two-byte number.  The address *includes* the two
+          bytes of number.  */
+  set_number_at,
+
+  wordchar,    /* Matches any word-constituent character.  */
+  notwordchar, /* Matches any char that is not a word-constituent.  */
+
+  wordbeg,     /* Succeeds if at word beginning.  */
+  wordend,     /* Succeeds if at word end.  */
+
+  wordbound,   /* Succeeds if at a word boundary.  */
+  notwordbound /* Succeeds if not at a word boundary.  */
+
+#ifdef emacs
+  ,before_dot, /* Succeeds if before point.  */
+  at_dot,      /* Succeeds if at point.  */
+  after_dot,   /* Succeeds if after point.  */
+
+       /* Matches any character whose syntax is specified.  Followed by
+          a byte which contains a syntax code, e.g., Sword.  */
+  syntaxspec,
+
+       /* Matches any character whose syntax is not that specified.  */
+  notsyntaxspec
+#endif /* emacs */
+} re_opcode_t;
+\f
+/* Common operations on the compiled pattern.  */
+
+/* Store NUMBER in two contiguous bytes starting at DESTINATION.  */
+
+#define STORE_NUMBER(destination, number)                              \
+  do {                                                                 \
+    (destination)[0] = (number) & 0377;                                        \
+    (destination)[1] = (number) >> 8;                                  \
+  } while (0)
+
+/* Same as STORE_NUMBER, except increment DESTINATION to
+   the byte after where the number is stored.  Therefore, DESTINATION
+   must be an lvalue.  */
+
+#define STORE_NUMBER_AND_INCR(destination, number)                     \
+  do {                                                                 \
+    STORE_NUMBER (destination, number);                                        \
+    (destination) += 2;                                                        \
+  } while (0)
+
+/* Put into DESTINATION a number stored in two contiguous bytes starting
+   at SOURCE.  */
+
+#define EXTRACT_NUMBER(destination, source)                            \
+  do {                                                                 \
+    (destination) = *(source) & 0377;                                  \
+    (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8;          \
+  } while (0)
+
+#ifdef DEBUG
+static void
+extract_number (dest, source)
+    int *dest;
+    unsigned char *source;
+{
+  int temp = SIGN_EXTEND_CHAR (*(source + 1));
+  *dest = *source & 0377;
+  *dest += temp << 8;
+}
+
+#ifndef EXTRACT_MACROS /* To debug the macros.  */
+#undef EXTRACT_NUMBER
+#define EXTRACT_NUMBER(dest, src) extract_number (&dest, src)
+#endif /* not EXTRACT_MACROS */
+
+#endif /* DEBUG */
+
+/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number.
+   SOURCE must be an lvalue.  */
+
+#define EXTRACT_NUMBER_AND_INCR(destination, source)                   \
+  do {                                                                 \
+    EXTRACT_NUMBER (destination, source);                              \
+    (source) += 2;                                                     \
+  } while (0)
+
+#ifdef DEBUG
+static void
+extract_number_and_incr (destination, source)
+    int *destination;
+    unsigned char **source;
+{
+  extract_number (destination, *source);
+  *source += 2;
+}
+
+#ifndef EXTRACT_MACROS
+#undef EXTRACT_NUMBER_AND_INCR
+#define EXTRACT_NUMBER_AND_INCR(dest, src) \
+  extract_number_and_incr (&dest, &src)
+#endif /* not EXTRACT_MACROS */
+
+#endif /* DEBUG */
+\f
+/* If DEBUG is defined, Regex prints many voluminous messages about what
+   it is doing (if the variable `debug' is nonzero).  If linked with the
+   main program in `iregex.c', you can enter patterns and strings
+   interactively.  And if linked with the main program in `main.c' and
+   the other test files, you can run the already-written tests.  */
+
+#ifdef DEBUG
+
+/* We use standard I/O for debugging.  */
+#include <stdio.h>
+
+/* It is useful to test things that ``must'' be true when debugging.  */
+#include <assert.h>
+
+static int debug = 0;
+
+#define DEBUG_STATEMENT(e) e
+#define DEBUG_PRINT1(x) if (debug) printf (x)
+#define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2)
+#define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3)
+#define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4)
+#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e)                          \
+  if (debug) print_partial_compiled_pattern (s, e)
+#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)                 \
+  if (debug) print_double_string (w, s1, sz1, s2, sz2)
+
+
+extern void printchar ();
+
+/* Print the fastmap in human-readable form.  */
+
+void
+print_fastmap (fastmap)
+    char *fastmap;
+{
+  unsigned was_a_range = 0;
+  unsigned i = 0;
+
+  while (i < (1 << BYTEWIDTH))
+    {
+      if (fastmap[i++])
+       {
+         was_a_range = 0;
+         printchar (i - 1);
+         while (i < (1 << BYTEWIDTH)  &&  fastmap[i])
+           {
+             was_a_range = 1;
+             i++;
+           }
+         if (was_a_range)
+           {
+             printf ("-");
+             printchar (i - 1);
+           }
+       }
+    }
+  putchar ('\n');
+}
+
+
+/* Print a compiled pattern string in human-readable form, starting at
+   the START pointer into it and ending just before the pointer END.  */
+
+void
+print_partial_compiled_pattern (start, end)
+    unsigned char *start;
+    unsigned char *end;
+{
+  int mcnt, mcnt2;
+  unsigned char *p = start;
+  unsigned char *pend = end;
+
+  if (start == NULL)
+    {
+      printf ("(null)\n");
+      return;
+    }
+
+  /* Loop over pattern commands.  */
+  while (p < pend)
+    {
+      switch ((re_opcode_t) *p++)
+       {
+       case no_op:
+         printf ("/no_op");
+         break;
+
+       case exactn:
+         mcnt = *p++;
+         printf ("/exactn/%d", mcnt);
+         do
+           {
+             putchar ('/');
+             printchar (*p++);
+           }
+         while (--mcnt);
+         break;
+
+       case start_memory:
+         mcnt = *p++;
+         printf ("/start_memory/%d/%d", mcnt, *p++);
+         break;
+
+       case stop_memory:
+         mcnt = *p++;
+         printf ("/stop_memory/%d/%d", mcnt, *p++);
+         break;
+
+       case duplicate:
+         printf ("/duplicate/%d", *p++);
+         break;
+
+       case anychar:
+         printf ("/anychar");
+         break;
+
+       case charset:
+       case charset_not:
+         {
+           register int c;
+
+           printf ("/charset%s",
+                   (re_opcode_t) *(p - 1) == charset_not ? "_not" : "");
+
+           assert (p + *p < pend);
+
+           for (c = 0; c < *p; c++)
+             {
+               unsigned bit;
+               unsigned char map_byte = p[1 + c];
+
+               putchar ('/');
+
+               for (bit = 0; bit < BYTEWIDTH; bit++)
+                 if (map_byte & (1 << bit))
+                   printchar (c * BYTEWIDTH + bit);
+             }
+           p += 1 + *p;
+           break;
+         }
+
+       case begline:
+         printf ("/begline");
+         break;
+
+       case endline:
+         printf ("/endline");
+         break;
+
+       case on_failure_jump:
+         extract_number_and_incr (&mcnt, &p);
+         printf ("/on_failure_jump/0/%d", mcnt);
+         break;
+
+       case on_failure_keep_string_jump:
+         extract_number_and_incr (&mcnt, &p);
+         printf ("/on_failure_keep_string_jump/0/%d", mcnt);
+         break;
+
+       case dummy_failure_jump:
+         extract_number_and_incr (&mcnt, &p);
+         printf ("/dummy_failure_jump/0/%d", mcnt);
+         break;
+
+       case push_dummy_failure:
+         printf ("/push_dummy_failure");
+         break;
+
+       case maybe_pop_jump:
+         extract_number_and_incr (&mcnt, &p);
+         printf ("/maybe_pop_jump/0/%d", mcnt);
+         break;
+
+       case pop_failure_jump:
+         extract_number_and_incr (&mcnt, &p);
+         printf ("/pop_failure_jump/0/%d", mcnt);
+         break;
+
+       case jump_past_alt:
+         extract_number_and_incr (&mcnt, &p);
+         printf ("/jump_past_alt/0/%d", mcnt);
+         break;
+
+       case jump:
+         extract_number_and_incr (&mcnt, &p);
+         printf ("/jump/0/%d", mcnt);
+         break;
+
+       case succeed_n:
+         extract_number_and_incr (&mcnt, &p);
+         extract_number_and_incr (&mcnt2, &p);
+         printf ("/succeed_n/0/%d/0/%d", mcnt, mcnt2);
+         break;
+
+       case jump_n:
+         extract_number_and_incr (&mcnt, &p);
+         extract_number_and_incr (&mcnt2, &p);
+         printf ("/jump_n/0/%d/0/%d", mcnt, mcnt2);
+         break;
+
+       case set_number_at:
+         extract_number_and_incr (&mcnt, &p);
+         extract_number_and_incr (&mcnt2, &p);
+         printf ("/set_number_at/0/%d/0/%d", mcnt, mcnt2);
+         break;
+
+       case wordbound:
+         printf ("/wordbound");
+         break;
+
+       case notwordbound:
+         printf ("/notwordbound");
+         break;
+
+       case wordbeg:
+         printf ("/wordbeg");
+         break;
+
+       case wordend:
+         printf ("/wordend");
+
+#ifdef emacs
+       case before_dot:
+         printf ("/before_dot");
+         break;
+
+       case at_dot:
+         printf ("/at_dot");
+         break;
+
+       case after_dot:
+         printf ("/after_dot");
+         break;
+
+       case syntaxspec:
+         printf ("/syntaxspec");
+         mcnt = *p++;
+         printf ("/%d", mcnt);
+         break;
+
+       case notsyntaxspec:
+         printf ("/notsyntaxspec");
+         mcnt = *p++;
+         printf ("/%d", mcnt);
+         break;
+#endif /* emacs */
+
+       case wordchar:
+         printf ("/wordchar");
+         break;
+
+       case notwordchar:
+         printf ("/notwordchar");
+         break;
+
+       case begbuf:
+         printf ("/begbuf");
+         break;
+
+       case endbuf:
+         printf ("/endbuf");
+         break;
+
+       default:
+         printf ("?%d", *(p-1));
+       }
+    }
+  printf ("/\n");
+}
+
+
+void
+print_compiled_pattern (bufp)
+    struct re_pattern_buffer *bufp;
+{
+  unsigned char *buffer = bufp->buffer;
+
+  print_partial_compiled_pattern (buffer, buffer + bufp->used);
+  printf ("%d bytes used/%d bytes allocated.\n", bufp->used, bufp->allocated);
+
+  if (bufp->fastmap_accurate && bufp->fastmap)
+    {
+      printf ("fastmap: ");
+      print_fastmap (bufp->fastmap);
+    }
+
+  printf ("re_nsub: %d\t", bufp->re_nsub);
+  printf ("regs_alloc: %d\t", bufp->regs_allocated);
+  printf ("can_be_null: %d\t", bufp->can_be_null);
+  printf ("newline_anchor: %d\n", bufp->newline_anchor);
+  printf ("no_sub: %d\t", bufp->no_sub);
+  printf ("not_bol: %d\t", bufp->not_bol);
+  printf ("not_eol: %d\t", bufp->not_eol);
+  printf ("syntax: %d\n", bufp->syntax);
+  /* Perhaps we should print the translate table?  */
+}
+
+
+void
+print_double_string (where, string1, size1, string2, size2)
+    const char *where;
+    const char *string1;
+    const char *string2;
+    int size1;
+    int size2;
+{
+  unsigned this_char;
+
+  if (where == NULL)
+    printf ("(null)");
+  else
+    {
+      if (FIRST_STRING_P (where))
+       {
+         for (this_char = where - string1; this_char < size1; this_char++)
+           printchar (string1[this_char]);
+
+         where = string2;
+       }
+
+      for (this_char = where - string2; this_char < size2; this_char++)
+       printchar (string2[this_char]);
+    }
+}
+
+#else /* not DEBUG */
+
+#undef assert
+#define assert(e)
+
+#define DEBUG_STATEMENT(e)
+#define DEBUG_PRINT1(x)
+#define DEBUG_PRINT2(x1, x2)
+#define DEBUG_PRINT3(x1, x2, x3)
+#define DEBUG_PRINT4(x1, x2, x3, x4)
+#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e)
+#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)
+
+#endif /* not DEBUG */
+\f
+/* Set by `re_set_syntax' to the current regexp syntax to recognize.  Can
+   also be assigned to arbitrarily: each pattern buffer stores its own
+   syntax, so it can be changed between regex compilations.  */
+reg_syntax_t re_syntax_options = RE_SYNTAX_EMACS;
+
+
+/* Specify the precise syntax of regexps for compilation.  This provides
+   for compatibility for various utilities which historically have
+   different, incompatible syntaxes.
+
+   The argument SYNTAX is a bit mask comprised of the various bits
+   defined in regex.h.  We return the old syntax.  */
+
+reg_syntax_t
+re_set_syntax (syntax)
+    reg_syntax_t syntax;
+{
+  reg_syntax_t ret = re_syntax_options;
+
+  re_syntax_options = syntax;
+  return ret;
+}
+\f
+/* This table gives an error message for each of the error codes listed
+   in regex.h.  Obviously the order here has to be same as there.  */
+
+static const char *re_error_msg[] =
+  { NULL,                                      /* REG_NOERROR */
+    "No match",                                        /* REG_NOMATCH */
+    "Invalid regular expression",              /* REG_BADPAT */
+    "Invalid collation character",             /* REG_ECOLLATE */
+    "Invalid character class name",            /* REG_ECTYPE */
+    "Trailing backslash",                      /* REG_EESCAPE */
+    "Invalid back reference",                  /* REG_ESUBREG */
+    "Unmatched [ or [^",                       /* REG_EBRACK */
+    "Unmatched ( or \\(",                      /* REG_EPAREN */
+    "Unmatched \\{",                           /* REG_EBRACE */
+    "Invalid content of \\{\\}",               /* REG_BADBR */
+    "Invalid range end",                       /* REG_ERANGE */
+    "Memory exhausted",                                /* REG_ESPACE */
+    "Invalid preceding regular expression",    /* REG_BADRPT */
+    "Premature end of regular expression",     /* REG_EEND */
+    "Regular expression too big",              /* REG_ESIZE */
+    "Unmatched ) or \\)",                      /* REG_ERPAREN */
+  };
+\f
+/* Subroutine declarations and macros for regex_compile.  */
+
+static void store_op1 (), store_op2 ();
+static void insert_op1 (), insert_op2 ();
+static boolean at_begline_loc_p (), at_endline_loc_p ();
+static boolean group_in_compile_stack ();
+static reg_errcode_t compile_range ();
+
+/* Fetch the next character in the uncompiled pattern---translating it
+   if necessary.  Also cast from a signed character in the constant
+   string passed to us by the user to an unsigned char that we can use
+   as an array index (in, e.g., `translate').  */
+#define PATFETCH(c)                                                    \
+  do {if (p == pend) return REG_EEND;                                  \
+    c = (unsigned char) *p++;                                          \
+    if (translate) c = translate[c];                                   \
+  } while (0)
+
+/* Fetch the next character in the uncompiled pattern, with no
+   translation.  */
+#define PATFETCH_RAW(c)                                                        \
+  do {if (p == pend) return REG_EEND;                                  \
+    c = (unsigned char) *p++;                                          \
+  } while (0)
+
+/* Go backwards one character in the pattern.  */
+#define PATUNFETCH p--
+
+
+/* If `translate' is non-null, return translate[D], else just D.  We
+   cast the subscript to translate because some data is declared as
+   `char *', to avoid warnings when a string constant is passed.  But
+   when we use a character as a subscript we must make it unsigned.  */
+#define TRANSLATE(d) (translate ? translate[(unsigned char) (d)] : (d))
+
+
+/* Macros for outputting the compiled pattern into `buffer'.  */
+
+/* If the buffer isn't allocated when it comes in, use this.  */
+#define INIT_BUF_SIZE  32
+
+/* Make sure we have at least N more bytes of space in buffer.  */
+#define GET_BUFFER_SPACE(n)                                            \
+    while (b - bufp->buffer + (n) > bufp->allocated)                   \
+      EXTEND_BUFFER ()
+
+/* Make sure we have one more byte of buffer space and then add C to it.  */
+#define BUF_PUSH(c)                                                    \
+  do {                                                                 \
+    GET_BUFFER_SPACE (1);                                              \
+    *b++ = (unsigned char) (c);                                                \
+  } while (0)
+
+
+/* Ensure we have two more bytes of buffer space and then append C1 and C2.  */
+#define BUF_PUSH_2(c1, c2)                                             \
+  do {                                                                 \
+    GET_BUFFER_SPACE (2);                                              \
+    *b++ = (unsigned char) (c1);                                       \
+    *b++ = (unsigned char) (c2);                                       \
+  } while (0)
+
+
+/* As with BUF_PUSH_2, except for three bytes.  */
+#define BUF_PUSH_3(c1, c2, c3)                                         \
+  do {                                                                 \
+    GET_BUFFER_SPACE (3);                                              \
+    *b++ = (unsigned char) (c1);                                       \
+    *b++ = (unsigned char) (c2);                                       \
+    *b++ = (unsigned char) (c3);                                       \
+  } while (0)
+
+
+/* Store a jump with opcode OP at LOC to location TO.  We store a
+   relative address offset by the three bytes the jump itself occupies.  */
+#define STORE_JUMP(op, loc, to) \
+  store_op1 (op, loc, (to) - (loc) - 3)
+
+/* Likewise, for a two-argument jump.  */
+#define STORE_JUMP2(op, loc, to, arg) \
+  store_op2 (op, loc, (to) - (loc) - 3, arg)
+
+/* Like `STORE_JUMP', but for inserting.  Assume `b' is the buffer end.  */
+#define INSERT_JUMP(op, loc, to) \
+  insert_op1 (op, loc, (to) - (loc) - 3, b)
+
+/* Like `STORE_JUMP2', but for inserting.  Assume `b' is the buffer end.  */
+#define INSERT_JUMP2(op, loc, to, arg) \
+  insert_op2 (op, loc, (to) - (loc) - 3, arg, b)
+
+
+/* This is not an arbitrary limit: the arguments which represent offsets
+   into the pattern are two bytes long.  So if 2^16 bytes turns out to
+   be too small, many things would have to change.  */
+#define MAX_BUF_SIZE (1L << 16)
+
+
+/* Extend the buffer by twice its current size via realloc and
+   reset the pointers that pointed into the old block to point to the
+   correct places in the new one.  If extending the buffer results in it
+   being larger than MAX_BUF_SIZE, then flag memory exhausted.  */
+#define EXTEND_BUFFER()                                                        \
+  do {                                                                         \
+    unsigned char *old_buffer = bufp->buffer;                          \
+    if (bufp->allocated == MAX_BUF_SIZE)                               \
+      return REG_ESIZE;                                                        \
+    bufp->allocated <<= 1;                                             \
+    if (bufp->allocated > MAX_BUF_SIZE)                                        \
+      bufp->allocated = MAX_BUF_SIZE;                                  \
+    bufp->buffer = (unsigned char *) realloc (bufp->buffer, bufp->allocated);\
+    if (bufp->buffer == NULL)                                          \
+      return REG_ESPACE;                                               \
+    /* If the buffer moved, move all the pointers into it.  */         \
+    if (old_buffer != bufp->buffer)                                    \
+      {                                                                        \
+       b = (b - old_buffer) + bufp->buffer;                            \
+       begalt = (begalt - old_buffer) + bufp->buffer;                  \
+       if (fixup_alt_jump)                                             \
+         fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\
+       if (laststart)                                                  \
+         laststart = (laststart - old_buffer) + bufp->buffer;          \
+       if (pending_exact)                                              \
+         pending_exact = (pending_exact - old_buffer) + bufp->buffer;  \
+      }                                                                        \
+  } while (0)
+
+
+/* Since we have one byte reserved for the register number argument to
+   {start,stop}_memory, the maximum number of groups we can report
+   things about is what fits in that byte.  */
+#define MAX_REGNUM 255
+
+/* But patterns can have more than `MAX_REGNUM' registers.  We just
+   ignore the excess.  */
+typedef unsigned regnum_t;
+
+
+/* Macros for the compile stack.  */
+
+/* Since offsets can go either forwards or backwards, this type needs to
+   be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1.  */
+typedef int pattern_offset_t;
+
+typedef struct
+{
+  pattern_offset_t begalt_offset;
+  pattern_offset_t fixup_alt_jump;
+  pattern_offset_t inner_group_offset;
+  pattern_offset_t laststart_offset;
+  regnum_t regnum;
+} compile_stack_elt_t;
+
+
+typedef struct
+{
+  compile_stack_elt_t *stack;
+  unsigned size;
+  unsigned avail;                      /* Offset of next open position.  */
+} compile_stack_type;
+
+
+#define INIT_COMPILE_STACK_SIZE 32
+
+#define COMPILE_STACK_EMPTY  (compile_stack.avail == 0)
+#define COMPILE_STACK_FULL  (compile_stack.avail == compile_stack.size)
+
+/* The next available element.  */
+#define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail])
+
+
+/* Set the bit for character C in a list.  */
+#define SET_LIST_BIT(c)                               \
+  (b[((unsigned char) (c)) / BYTEWIDTH]               \
+   |= 1 << (((unsigned char) c) % BYTEWIDTH))
+
+
+/* Get the next unsigned number in the uncompiled pattern.  */
+#define GET_UNSIGNED_NUMBER(num)                                       \
+  { if (p != pend)                                                     \
+     {                                                                 \
+       PATFETCH (c);                                                   \
+       while (ISDIGIT (c))                                             \
+        {                                                              \
+          if (num < 0)                                                 \
+             num = 0;                                                  \
+          num = num * 10 + c - '0';                                    \
+          if (p == pend)                                               \
+             break;                                                    \
+          PATFETCH (c);                                                \
+        }                                                              \
+       }                                                               \
+    }
+
+#define CHAR_CLASS_MAX_LENGTH  6 /* Namely, `xdigit'.  */
+
+#define IS_CHAR_CLASS(string)                                          \
+   (STREQ (string, "alpha") || STREQ (string, "upper")                 \
+    || STREQ (string, "lower") || STREQ (string, "digit")              \
+    || STREQ (string, "alnum") || STREQ (string, "xdigit")             \
+    || STREQ (string, "space") || STREQ (string, "print")              \
+    || STREQ (string, "punct") || STREQ (string, "graph")              \
+    || STREQ (string, "cntrl") || STREQ (string, "blank"))
+\f
+/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX.
+   Returns one of error codes defined in `regex.h', or zero for success.
+
+   Assumes the `allocated' (and perhaps `buffer') and `translate'
+   fields are set in BUFP on entry.
+
+   If it succeeds, results are put in BUFP (if it returns an error, the
+   contents of BUFP are undefined):
+     `buffer' is the compiled pattern;
+     `syntax' is set to SYNTAX;
+     `used' is set to the length of the compiled pattern;
+     `fastmap_accurate' is zero;
+     `re_nsub' is the number of subexpressions in PATTERN;
+     `not_bol' and `not_eol' are zero;
+
+   The `fastmap' and `newline_anchor' fields are neither
+   examined nor set.  */
+
+static reg_errcode_t
+regex_compile (pattern, size, syntax, bufp)
+     const char *pattern;
+     int size;
+     reg_syntax_t syntax;
+     struct re_pattern_buffer *bufp;
+{
+  /* We fetch characters from PATTERN here.  Even though PATTERN is
+     `char *' (i.e., signed), we declare these variables as unsigned, so
+     they can be reliably used as array indices.  */
+  register unsigned char c, c1;
+
+  /* A random tempory spot in PATTERN.  */
+  const char *p1;
+
+  /* Points to the end of the buffer, where we should append.  */
+  register unsigned char *b;
+
+  /* Keeps track of unclosed groups.  */
+  compile_stack_type compile_stack;
+
+  /* Points to the current (ending) position in the pattern.  */
+  const char *p = pattern;
+  const char *pend = pattern + size;
+
+  /* How to translate the characters in the pattern.  */
+  char *translate = bufp->translate;
+
+  /* Address of the count-byte of the most recently inserted `exactn'
+     command.  This makes it possible to tell if a new exact-match
+     character can be added to that command or if the character requires
+     a new `exactn' command.  */
+  unsigned char *pending_exact = 0;
+
+  /* Address of start of the most recently finished expression.
+     This tells, e.g., postfix * where to find the start of its
+     operand.  Reset at the beginning of groups and alternatives.  */
+  unsigned char *laststart = 0;
+
+  /* Address of beginning of regexp, or inside of last group.  */
+  unsigned char *begalt;
+
+  /* Place in the uncompiled pattern (i.e., the {) to
+     which to go back if the interval is invalid.  */
+  const char *beg_interval;
+
+  /* Address of the place where a forward jump should go to the end of
+     the containing expression.  Each alternative of an `or' -- except the
+     last -- ends with a forward jump of this sort.  */
+  unsigned char *fixup_alt_jump = 0;
+
+  /* Counts open-groups as they are encountered.  Remembered for the
+     matching close-group on the compile stack, so the same register
+     number is put in the stop_memory as the start_memory.  */
+  regnum_t regnum = 0;
+
+#ifdef DEBUG
+  DEBUG_PRINT1 ("\nCompiling pattern: ");
+  if (debug)
+    {
+      unsigned debug_count;
+
+      for (debug_count = 0; debug_count < size; debug_count++)
+       printchar (pattern[debug_count]);
+      putchar ('\n');
+    }
+#endif /* DEBUG */
+
+  /* Initialize the compile stack.  */
+  compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t);
+  if (compile_stack.stack == NULL)
+    return REG_ESPACE;
+
+  compile_stack.size = INIT_COMPILE_STACK_SIZE;
+  compile_stack.avail = 0;
+
+  /* Initialize the pattern buffer.  */
+  bufp->syntax = syntax;
+  bufp->fastmap_accurate = 0;
+  bufp->not_bol = bufp->not_eol = 0;
+
+  /* Set `used' to zero, so that if we return an error, the pattern
+     printer (for debugging) will think there's no pattern.  We reset it
+     at the end.  */
+  bufp->used = 0;
+
+  /* Always count groups, whether or not bufp->no_sub is set.  */
+  bufp->re_nsub = 0;
+
+#if !defined (emacs) && !defined (SYNTAX_TABLE)
+  /* Initialize the syntax table.  */
+   init_syntax_once ();
+#endif
+
+  if (bufp->allocated == 0)
+    {
+      if (bufp->buffer)
+       { /* If zero allocated, but buffer is non-null, try to realloc
+            enough space.  This loses if buffer's address is bogus, but
+            that is the user's responsibility.  */
+         RETALLOC (bufp->buffer, INIT_BUF_SIZE, unsigned char);
+       }
+      else
+       { /* Caller did not allocate a buffer.  Do it for them.  */
+         bufp->buffer = TALLOC (INIT_BUF_SIZE, unsigned char);
+       }
+      if (!bufp->buffer) return REG_ESPACE;
+
+      bufp->allocated = INIT_BUF_SIZE;
+    }
+
+  begalt = b = bufp->buffer;
+
+  /* Loop through the uncompiled pattern until we're at the end.  */
+  while (p != pend)
+    {
+      PATFETCH (c);
+
+      switch (c)
+       {
+       case '^':
+         {
+           if (   /* If at start of pattern, it's an operator.  */
+                  p == pattern + 1
+                  /* If context independent, it's an operator.  */
+               || syntax & RE_CONTEXT_INDEP_ANCHORS
+                  /* Otherwise, depends on what's come before.  */
+               || at_begline_loc_p (pattern, p, syntax))
+             BUF_PUSH (begline);
+           else
+             goto normal_char;
+         }
+         break;
+
+
+       case '$':
+         {
+           if (   /* If at end of pattern, it's an operator.  */
+                  p == pend
+                  /* If context independent, it's an operator.  */
+               || syntax & RE_CONTEXT_INDEP_ANCHORS
+                  /* Otherwise, depends on what's next.  */
+               || at_endline_loc_p (p, pend, syntax))
+              BUF_PUSH (endline);
+            else
+              goto normal_char;
+          }
+          break;
+
+
+       case '+':
+       case '?':
+         if ((syntax & RE_BK_PLUS_QM)
+             || (syntax & RE_LIMITED_OPS))
+           goto normal_char;
+       handle_plus:
+       case '*':
+         /* If there is no previous pattern... */
+         if (!laststart)
+           {
+             if (syntax & RE_CONTEXT_INVALID_OPS)
+               return REG_BADRPT;
+             else if (!(syntax & RE_CONTEXT_INDEP_OPS))
+               goto normal_char;
+           }
+
+         {
+           /* Are we optimizing this jump?  */
+           boolean keep_string_p = false;
+
+           /* 1 means zero (many) matches is allowed.  */
+           char zero_times_ok = 0, many_times_ok = 0;
+
+           /* If there is a sequence of repetition chars, collapse it
+              down to just one (the right one).  We can't combine
+              interval operators with these because of, e.g., `a{2}*',
+              which should only match an even number of `a's.  */
+
+           for (;;)
+             {
+               zero_times_ok |= c != '+';
+               many_times_ok |= c != '?';
+
+               if (p == pend)
+                 break;
+
+               PATFETCH (c);
+
+               if (c == '*'
+                   || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?')))
+                 ;
+
+               else if (syntax & RE_BK_PLUS_QM  &&  c == '\\')
+                 {
+                   if (p == pend) return REG_EESCAPE;
+
+                   PATFETCH (c1);
+                   if (!(c1 == '+' || c1 == '?'))
+                     {
+                       PATUNFETCH;
+                       PATUNFETCH;
+                       break;
+                     }
+
+                   c = c1;
+                 }
+               else
+                 {
+                   PATUNFETCH;
+                   break;
+                 }
+
+               /* If we get here, we found another repeat character.  */
+              }
+
+           /* Star, etc. applied to an empty pattern is equivalent
+              to an empty pattern.  */
+           if (!laststart)
+             break;
+
+           /* Now we know whether or not zero matches is allowed
+              and also whether or not two or more matches is allowed.  */
+           if (many_times_ok)
+             { /* More than one repetition is allowed, so put in at the
+                  end a backward relative jump from `b' to before the next
+                  jump we're going to put in below (which jumps from
+                  laststart to after this jump).
+
+                  But if we are at the `*' in the exact sequence `.*\n',
+                  insert an unconditional jump backwards to the .,
+                  instead of the beginning of the loop.  This way we only
+                  push a failure point once, instead of every time
+                  through the loop.  */
+               assert (p - 1 > pattern);
+
+               /* Allocate the space for the jump.  */
+               GET_BUFFER_SPACE (3);
+
+               /* We know we are not at the first character of the pattern,
+                  because laststart was nonzero.  And we've already
+                  incremented `p', by the way, to be the character after
+                  the `*'.  Do we have to do something analogous here
+                  for null bytes, because of RE_DOT_NOT_NULL?  */
+               if (TRANSLATE (*(p - 2)) == TRANSLATE ('.')
+                   && zero_times_ok
+                   && p < pend && TRANSLATE (*p) == TRANSLATE ('\n')
+                   && !(syntax & RE_DOT_NEWLINE))
+                 { /* We have .*\n.  */
+                   STORE_JUMP (jump, b, laststart);
+                   keep_string_p = true;
+                 }
+               else
+                 /* Anything else.  */
+                 STORE_JUMP (maybe_pop_jump, b, laststart - 3);
+
+               /* We've added more stuff to the buffer.  */
+               b += 3;
+             }
+
+           /* On failure, jump from laststart to b + 3, which will be the
+              end of the buffer after this jump is inserted.  */
+           GET_BUFFER_SPACE (3);
+           INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump
+                                      : on_failure_jump,
+                        laststart, b + 3);
+           pending_exact = 0;
+           b += 3;
+
+           if (!zero_times_ok)
+             {
+               /* At least one repetition is required, so insert a
+                  `dummy_failure_jump' before the initial
+                  `on_failure_jump' instruction of the loop. This
+                  effects a skip over that instruction the first time
+                  we hit that loop.  */
+               GET_BUFFER_SPACE (3);
+               INSERT_JUMP (dummy_failure_jump, laststart, laststart + 6);
+               b += 3;
+             }
+           }
+         break;
+
+
+       case '.':
+         laststart = b;
+         BUF_PUSH (anychar);
+         break;
+
+
+       case '[':
+         {
+           boolean had_char_class = false;
+
+           if (p == pend) return REG_EBRACK;
+
+           /* Ensure that we have enough space to push a charset: the
+              opcode, the length count, and the bitset; 34 bytes in all.  */
+           GET_BUFFER_SPACE (34);
+
+           laststart = b;
+
+           /* We test `*p == '^' twice, instead of using an if
+              statement, so we only need one BUF_PUSH.  */
+           BUF_PUSH (*p == '^' ? charset_not : charset);
+           if (*p == '^')
+             p++;
+
+           /* Remember the first position in the bracket expression.  */
+           p1 = p;
+
+           /* Push the number of bytes in the bitmap.  */
+           BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH);
+
+           /* Clear the whole map.  */
+           bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH);
+
+           /* charset_not matches newline according to a syntax bit.  */
+           if ((re_opcode_t) b[-2] == charset_not
+               && (syntax & RE_HAT_LISTS_NOT_NEWLINE))
+             SET_LIST_BIT ('\n');
+
+           /* Read in characters and ranges, setting map bits.  */
+           for (;;)
+             {
+               if (p == pend) return REG_EBRACK;
+
+               PATFETCH (c);
+
+               /* \ might escape characters inside [...] and [^...].  */
+               if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\')
+                 {
+                   if (p == pend) return REG_EESCAPE;
+
+                   PATFETCH (c1);
+                   SET_LIST_BIT (c1);
+                   continue;
+                 }
+
+               /* Could be the end of the bracket expression.  If it's
+                  not (i.e., when the bracket expression is `[]' so
+                  far), the ']' character bit gets set way below.  */
+               if (c == ']' && p != p1 + 1)
+                 break;
+
+               /* Look ahead to see if it's a range when the last thing
+                  was a character class.  */
+               if (had_char_class && c == '-' && *p != ']')
+                 return REG_ERANGE;
+
+               /* Look ahead to see if it's a range when the last thing
+                  was a character: if this is a hyphen not at the
+                  beginning or the end of a list, then it's the range
+                  operator.  */
+               if (c == '-'
+                   && !(p - 2 >= pattern && p[-2] == '[')
+                   && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^')
+                   && *p != ']')
+                 {
+                   reg_errcode_t ret
+                     = compile_range (&p, pend, translate, syntax, b);
+                   if (ret != REG_NOERROR) return ret;
+                 }
+
+               else if (p[0] == '-' && p[1] != ']')
+                 { /* This handles ranges made up of characters only.  */
+                   reg_errcode_t ret;
+
+                   /* Move past the `-'.  */
+                   PATFETCH (c1);
+
+                   ret = compile_range (&p, pend, translate, syntax, b);
+                   if (ret != REG_NOERROR) return ret;
+                 }
+
+               /* See if we're at the beginning of a possible character
+                  class.  */
+
+               else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':')
+                 { /* Leave room for the null.  */
+                   char str[CHAR_CLASS_MAX_LENGTH + 1];
+
+                   PATFETCH (c);
+                   c1 = 0;
+
+                   /* If pattern is `[[:'.  */
+                   if (p == pend) return REG_EBRACK;
+
+                   for (;;)
+                     {
+                       PATFETCH (c);
+                       if (c == ':' || c == ']' || p == pend
+                           || c1 == CHAR_CLASS_MAX_LENGTH)
+                         break;
+                       str[c1++] = c;
+                     }
+                   str[c1] = '\0';
+
+                   /* If isn't a word bracketed by `[:' and:`]':
+                      undo the ending character, the letters, and leave
+                      the leading `:' and `[' (but set bits for them).  */
+                   if (c == ':' && *p == ']')
+                     {
+                       int ch;
+                       boolean is_alnum = STREQ (str, "alnum");
+                       boolean is_alpha = STREQ (str, "alpha");
+                       boolean is_blank = STREQ (str, "blank");
+                       boolean is_cntrl = STREQ (str, "cntrl");
+                       boolean is_digit = STREQ (str, "digit");
+                       boolean is_graph = STREQ (str, "graph");
+                       boolean is_lower = STREQ (str, "lower");
+                       boolean is_print = STREQ (str, "print");
+                       boolean is_punct = STREQ (str, "punct");
+                       boolean is_space = STREQ (str, "space");
+                       boolean is_upper = STREQ (str, "upper");
+                       boolean is_xdigit = STREQ (str, "xdigit");
+
+                       if (!IS_CHAR_CLASS (str)) return REG_ECTYPE;
+
+                       /* Throw away the ] at the end of the character
+                          class.  */
+                       PATFETCH (c);
+
+                       if (p == pend) return REG_EBRACK;
+
+                       for (ch = 0; ch < 1 << BYTEWIDTH; ch++)
+                         {
+                           if (   (is_alnum  && ISALNUM (ch))
+                               || (is_alpha  && ISALPHA (ch))
+                               || (is_blank  && ISBLANK (ch))
+                               || (is_cntrl  && ISCNTRL (ch))
+                               || (is_digit  && ISDIGIT (ch))
+                               || (is_graph  && ISGRAPH (ch))
+                               || (is_lower  && ISLOWER (ch))
+                               || (is_print  && ISPRINT (ch))
+                               || (is_punct  && ISPUNCT (ch))
+                               || (is_space  && ISSPACE (ch))
+                               || (is_upper  && ISUPPER (ch))
+                               || (is_xdigit && ISXDIGIT (ch)))
+                           SET_LIST_BIT (ch);
+                         }
+                       had_char_class = true;
+                     }
+                   else
+                     {
+                       c1++;
+                       while (c1--)
+                         PATUNFETCH;
+                       SET_LIST_BIT ('[');
+                       SET_LIST_BIT (':');
+                       had_char_class = false;
+                     }
+                 }
+               else
+                 {
+                   had_char_class = false;
+                   SET_LIST_BIT (c);
+                 }
+             }
+
+           /* Discard any (non)matching list bytes that are all 0 at the
+              end of the map.  Decrease the map-length byte too.  */
+           while ((int) b[-1] > 0 && b[b[-1] - 1] == 0)
+             b[-1]--;
+           b += b[-1];
+         }
+         break;
+
+
+       case '(':
+         if (syntax & RE_NO_BK_PARENS)
+           goto handle_open;
+         else
+           goto normal_char;
+
+
+       case ')':
+         if (syntax & RE_NO_BK_PARENS)
+           goto handle_close;
+         else
+           goto normal_char;
+
+
+       case '\n':
+         if (syntax & RE_NEWLINE_ALT)
+           goto handle_alt;
+         else
+           goto normal_char;
+
+
+       case '|':
+         if (syntax & RE_NO_BK_VBAR)
+           goto handle_alt;
+         else
+           goto normal_char;
+
+
+       case '{':
+          if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES)
+            goto handle_interval;
+          else
+            goto normal_char;
+
+
+       case '\\':
+         if (p == pend) return REG_EESCAPE;
+
+         /* Do not translate the character after the \, so that we can
+            distinguish, e.g., \B from \b, even if we normally would
+            translate, e.g., B to b.  */
+         PATFETCH_RAW (c);
+
+         switch (c)
+           {
+           case '(':
+             if (syntax & RE_NO_BK_PARENS)
+               goto normal_backslash;
+
+           handle_open:
+             bufp->re_nsub++;
+             regnum++;
+
+             if (COMPILE_STACK_FULL)
+               {
+                 RETALLOC (compile_stack.stack, compile_stack.size << 1,
+                           compile_stack_elt_t);
+                 if (compile_stack.stack == NULL) return REG_ESPACE;
+
+                 compile_stack.size <<= 1;
+               }
+
+             /* These are the values to restore when we hit end of this
+                group.  They are all relative offsets, so that if the
+                whole pattern moves because of realloc, they will still
+                be valid.  */
+             COMPILE_STACK_TOP.begalt_offset = begalt - bufp->buffer;
+             COMPILE_STACK_TOP.fixup_alt_jump
+               = fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0;
+             COMPILE_STACK_TOP.laststart_offset = b - bufp->buffer;
+             COMPILE_STACK_TOP.regnum = regnum;
+
+             /* We will eventually replace the 0 with the number of
+                groups inner to this one.  But do not push a
+                start_memory for groups beyond the last one we can
+                represent in the compiled pattern.  */
+             if (regnum <= MAX_REGNUM)
+               {
+                 COMPILE_STACK_TOP.inner_group_offset = b - bufp->buffer + 2;
+                 BUF_PUSH_3 (start_memory, regnum, 0);
+               }
+
+             compile_stack.avail++;
+
+             fixup_alt_jump = 0;
+             laststart = 0;
+             begalt = b;
+             /* If we've reached MAX_REGNUM groups, then this open
+                won't actually generate any code, so we'll have to
+                clear pending_exact explicitly.  */
+             pending_exact = 0;
+             break;
+
+
+           case ')':
+             if (syntax & RE_NO_BK_PARENS) goto normal_backslash;
+
+             if (COMPILE_STACK_EMPTY)
+             {
+               if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
+                 goto normal_backslash;
+               else
+                 return REG_ERPAREN;
+             }
+
+           handle_close:
+             if (fixup_alt_jump)
+               { /* Push a dummy failure point at the end of the
+                    alternative for a possible future
+                    `pop_failure_jump' to pop.  See comments at
+                    `push_dummy_failure' in `re_match_2'.  */
+                 BUF_PUSH (push_dummy_failure);
+
+                 /* We allocated space for this jump when we assigned
+                    to `fixup_alt_jump', in the `handle_alt' case below.  */
+                 STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1);
+               }
+
+             /* See similar code for backslashed left paren above.  */
+             if (COMPILE_STACK_EMPTY)
+             {
+               if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
+                 goto normal_char;
+               else
+                 return REG_ERPAREN;
+             }
+
+             /* Since we just checked for an empty stack above, this
+                ``can't happen''.  */
+             assert (compile_stack.avail != 0);
+             {
+               /* We don't just want to restore into `regnum', because
+                  later groups should continue to be numbered higher,
+                  as in `(ab)c(de)' -- the second group is #2.  */
+               regnum_t this_group_regnum;
+
+               compile_stack.avail--;
+               begalt = bufp->buffer + COMPILE_STACK_TOP.begalt_offset;
+               fixup_alt_jump
+                 = COMPILE_STACK_TOP.fixup_alt_jump
+                   ? bufp->buffer + COMPILE_STACK_TOP.fixup_alt_jump - 1
+                   : 0;
+               laststart = bufp->buffer + COMPILE_STACK_TOP.laststart_offset;
+               this_group_regnum = COMPILE_STACK_TOP.regnum;
+               /* If we've reached MAX_REGNUM groups, then this open
+                  won't actually generate any code, so we'll have to
+                  clear pending_exact explicitly.  */
+               pending_exact = 0;
+
+               /* We're at the end of the group, so now we know how many
+                  groups were inside this one.  */
+               if (this_group_regnum <= MAX_REGNUM)
+                 {
+                   unsigned char *inner_group_loc
+                     = bufp->buffer + COMPILE_STACK_TOP.inner_group_offset;
+
+                   *inner_group_loc = regnum - this_group_regnum;
+                   BUF_PUSH_3 (stop_memory, this_group_regnum,
+                               regnum - this_group_regnum);
+                 }
+             }
+             break;
+
+
+           case '|':                                   /* `\|'.  */
+             if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR)
+               goto normal_backslash;
+           handle_alt:
+             if (syntax & RE_LIMITED_OPS)
+               goto normal_char;
+
+             /* Insert before the previous alternative a jump which
+                jumps to this alternative if the former fails.  */
+             GET_BUFFER_SPACE (3);
+             INSERT_JUMP (on_failure_jump, begalt, b + 6);
+             pending_exact = 0;
+             b += 3;
+
+             /* The alternative before this one has a jump after it
+                which gets executed if it gets matched.  Adjust that
+                jump so it will jump to this alternative's analogous
+                jump (put in below, which in turn will jump to the next
+                (if any) alternative's such jump, etc.).  The last such
+                jump jumps to the correct final destination.  A picture:
+                         _____ _____
+                         |   | |   |
+                         |   v |   v
+                        a | b   | c
+
+                If we are at `b', then fixup_alt_jump right now points to a
+                three-byte space after `a'.  We'll put in the jump, set
+                fixup_alt_jump to right after `b', and leave behind three
+                bytes which we'll fill in when we get to after `c'.  */
+
+             if (fixup_alt_jump)
+               STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
+
+             /* Mark and leave space for a jump after this alternative,
+                to be filled in later either by next alternative or
+                when know we're at the end of a series of alternatives.  */
+             fixup_alt_jump = b;
+             GET_BUFFER_SPACE (3);
+             b += 3;
+
+             laststart = 0;
+             begalt = b;
+             break;
+
+
+           case '{':
+             /* If \{ is a literal.  */
+             if (!(syntax & RE_INTERVALS)
+                    /* If we're at `\{' and it's not the open-interval
+                       operator.  */
+                 || ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
+                 || (p - 2 == pattern  &&  p == pend))
+               goto normal_backslash;
+
+           handle_interval:
+             {
+               /* If got here, then the syntax allows intervals.  */
+
+               /* At least (most) this many matches must be made.  */
+               int lower_bound = -1, upper_bound = -1;
+
+               beg_interval = p - 1;
+
+               if (p == pend)
+                 {
+                   if (syntax & RE_NO_BK_BRACES)
+                     goto unfetch_interval;
+                   else
+                     return REG_EBRACE;
+                 }
+
+               GET_UNSIGNED_NUMBER (lower_bound);
+
+               if (c == ',')
+                 {
+                   GET_UNSIGNED_NUMBER (upper_bound);
+                   if (upper_bound < 0) upper_bound = RE_DUP_MAX;
+                 }
+               else
+                 /* Interval such as `{1}' => match exactly once. */
+                 upper_bound = lower_bound;
+
+               if (lower_bound < 0 || upper_bound > RE_DUP_MAX
+                   || lower_bound > upper_bound)
+                 {
+                   if (syntax & RE_NO_BK_BRACES)
+                     goto unfetch_interval;
+                   else
+                     return REG_BADBR;
+                 }
+
+               if (!(syntax & RE_NO_BK_BRACES))
+                 {
+                   if (c != '\\') return REG_EBRACE;
+
+                   PATFETCH (c);
+                 }
+
+               if (c != '}')
+                 {
+                   if (syntax & RE_NO_BK_BRACES)
+                     goto unfetch_interval;
+                   else
+                     return REG_BADBR;
+                 }
+
+               /* We just parsed a valid interval.  */
+
+               /* If it's invalid to have no preceding re.  */
+               if (!laststart)
+                 {
+                   if (syntax & RE_CONTEXT_INVALID_OPS)
+                     return REG_BADRPT;
+                   else if (syntax & RE_CONTEXT_INDEP_OPS)
+                     laststart = b;
+                   else
+                     goto unfetch_interval;
+                 }
+
+               /* If the upper bound is zero, don't want to succeed at
+                  all; jump from `laststart' to `b + 3', which will be
+                  the end of the buffer after we insert the jump.  */
+                if (upper_bound == 0)
+                  {
+                    GET_BUFFER_SPACE (3);
+                    INSERT_JUMP (jump, laststart, b + 3);
+                    b += 3;
+                  }
+
+                /* Otherwise, we have a nontrivial interval.  When
+                   we're all done, the pattern will look like:
+                     set_number_at <jump count> <upper bound>
+                     set_number_at <succeed_n count> <lower bound>
+                     succeed_n <after jump addr> <succed_n count>
+                     <body of loop>
+                     jump_n <succeed_n addr> <jump count>
+                   (The upper bound and `jump_n' are omitted if
+                   `upper_bound' is 1, though.)  */
+                else
+                  { /* If the upper bound is > 1, we need to insert
+                       more at the end of the loop.  */
+                    unsigned nbytes = 10 + (upper_bound > 1) * 10;
+
+                    GET_BUFFER_SPACE (nbytes);
+
+                    /* Initialize lower bound of the `succeed_n', even
+                       though it will be set during matching by its
+                       attendant `set_number_at' (inserted next),
+                       because `re_compile_fastmap' needs to know.
+                       Jump to the `jump_n' we might insert below.  */
+                    INSERT_JUMP2 (succeed_n, laststart,
+                                  b + 5 + (upper_bound > 1) * 5,
+                                  lower_bound);
+                    b += 5;
+
+                    /* Code to initialize the lower bound.  Insert
+                       before the `succeed_n'.  The `5' is the last two
+                       bytes of this `set_number_at', plus 3 bytes of
+                       the following `succeed_n'.  */
+                    insert_op2 (set_number_at, laststart, 5, lower_bound, b);
+                    b += 5;
+
+                    if (upper_bound > 1)
+                      { /* More than one repetition is allowed, so
+                           append a backward jump to the `succeed_n'
+                           that starts this interval.
+
+                           When we've reached this during matching,
+                           we'll have matched the interval once, so
+                           jump back only `upper_bound - 1' times.  */
+                        STORE_JUMP2 (jump_n, b, laststart + 5,
+                                     upper_bound - 1);
+                        b += 5;
+
+                        /* The location we want to set is the second
+                           parameter of the `jump_n'; that is `b-2' as
+                           an absolute address.  `laststart' will be
+                           the `set_number_at' we're about to insert;
+                           `laststart+3' the number to set, the source
+                           for the relative address.  But we are
+                           inserting into the middle of the pattern --
+                           so everything is getting moved up by 5.
+                           Conclusion: (b - 2) - (laststart + 3) + 5,
+                           i.e., b - laststart.
+
+                           We insert this at the beginning of the loop
+                           so that if we fail during matching, we'll
+                           reinitialize the bounds.  */
+                        insert_op2 (set_number_at, laststart, b - laststart,
+                                    upper_bound - 1, b);
+                        b += 5;
+                      }
+                  }
+               pending_exact = 0;
+               beg_interval = NULL;
+             }
+             break;
+
+           unfetch_interval:
+             /* If an invalid interval, match the characters as literals.  */
+              assert (beg_interval);
+              p = beg_interval;
+              beg_interval = NULL;
+
+              /* normal_char and normal_backslash need `c'.  */
+              PATFETCH (c);
+
+              if (!(syntax & RE_NO_BK_BRACES))
+                {
+                  if (p > pattern  &&  p[-1] == '\\')
+                    goto normal_backslash;
+                }
+              goto normal_char;
+
+#ifdef emacs
+           /* There is no way to specify the before_dot and after_dot
+              operators.  rms says this is ok.  --karl  */
+           case '=':
+             BUF_PUSH (at_dot);
+             break;
+
+           case 's':
+             laststart = b;
+             PATFETCH (c);
+             BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]);
+             break;
+
+           case 'S':
+             laststart = b;
+             PATFETCH (c);
+             BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]);
+             break;
+#endif /* emacs */
+
+
+           case 'w':
+             laststart = b;
+             BUF_PUSH (wordchar);
+             break;
+
+
+           case 'W':
+             laststart = b;
+             BUF_PUSH (notwordchar);
+             break;
+
+
+           case '<':
+             BUF_PUSH (wordbeg);
+             break;
+
+           case '>':
+             BUF_PUSH (wordend);
+             break;
+
+           case 'b':
+             BUF_PUSH (wordbound);
+             break;
+
+           case 'B':
+             BUF_PUSH (notwordbound);
+             break;
+
+           case '`':
+             BUF_PUSH (begbuf);
+             break;
+
+           case '\'':
+             BUF_PUSH (endbuf);
+             break;
+
+           case '1': case '2': case '3': case '4': case '5':
+           case '6': case '7': case '8': case '9':
+             if (syntax & RE_NO_BK_REFS)
+               goto normal_char;
+
+             c1 = c - '0';
+
+             if (c1 > regnum)
+               return REG_ESUBREG;
+
+             /* Can't back reference to a subexpression if inside of it.  */
+             if (group_in_compile_stack (compile_stack, c1))
+               goto normal_char;
+
+             laststart = b;
+             BUF_PUSH_2 (duplicate, c1);
+             break;
+
+
+           case '+':
+           case '?':
+             if (syntax & RE_BK_PLUS_QM)
+               goto handle_plus;
+             else
+               goto normal_backslash;
+
+           default:
+           normal_backslash:
+             /* You might think it would be useful for \ to mean
+                not to translate; but if we don't translate it
+                it will never match anything.  */
+             c = TRANSLATE (c);
+             goto normal_char;
+           }
+         break;
+
+
+       default:
+       /* Expects the character in `c'.  */
+       normal_char:
+             /* If no exactn currently being built.  */
+         if (!pending_exact
+
+             /* If last exactn not at current position.  */
+             || pending_exact + *pending_exact + 1 != b
+
+             /* We have only one byte following the exactn for the count.  */
+             || *pending_exact == (1 << BYTEWIDTH) - 1
+
+             /* If followed by a repetition operator.  */
+             || *p == '*' || *p == '^'
+             || ((syntax & RE_BK_PLUS_QM)
+                 ? *p == '\\' && (p[1] == '+' || p[1] == '?')
+                 : (*p == '+' || *p == '?'))
+             || ((syntax & RE_INTERVALS)
+                 && ((syntax & RE_NO_BK_BRACES)
+                     ? *p == '{'
+                     : (p[0] == '\\' && p[1] == '{'))))
+           {
+             /* Start building a new exactn.  */
+
+             laststart = b;
+
+             BUF_PUSH_2 (exactn, 0);
+             pending_exact = b - 1;
+           }
+
+         BUF_PUSH (c);
+         (*pending_exact)++;
+         break;
+       } /* switch (c) */
+    } /* while p != pend */
+
+
+  /* Through the pattern now.  */
+
+  if (fixup_alt_jump)
+    STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
+
+  if (!COMPILE_STACK_EMPTY)
+    return REG_EPAREN;
+
+  free (compile_stack.stack);
+
+  /* We have succeeded; set the length of the buffer.  */
+  bufp->used = b - bufp->buffer;
+
+#ifdef DEBUG
+  if (debug)
+    {
+      DEBUG_PRINT1 ("\nCompiled pattern: ");
+      print_compiled_pattern (bufp);
+    }
+#endif /* DEBUG */
+
+  return REG_NOERROR;
+} /* regex_compile */
+\f
+/* Subroutines for `regex_compile'.  */
+
+/* Store OP at LOC followed by two-byte integer parameter ARG.  */
+
+static void
+store_op1 (op, loc, arg)
+    re_opcode_t op;
+    unsigned char *loc;
+    int arg;
+{
+  *loc = (unsigned char) op;
+  STORE_NUMBER (loc + 1, arg);
+}
+
+
+/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2.  */
+
+static void
+store_op2 (op, loc, arg1, arg2)
+    re_opcode_t op;
+    unsigned char *loc;
+    int arg1, arg2;
+{
+  *loc = (unsigned char) op;
+  STORE_NUMBER (loc + 1, arg1);
+  STORE_NUMBER (loc + 3, arg2);
+}
+
+
+/* Copy the bytes from LOC to END to open up three bytes of space at LOC
+   for OP followed by two-byte integer parameter ARG.  */
+
+static void
+insert_op1 (op, loc, arg, end)
+    re_opcode_t op;
+    unsigned char *loc;
+    int arg;
+    unsigned char *end;
+{
+  register unsigned char *pfrom = end;
+  register unsigned char *pto = end + 3;
+
+  while (pfrom != loc)
+    *--pto = *--pfrom;
+
+  store_op1 (op, loc, arg);
+}
+
+
+/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2.  */
+
+static void
+insert_op2 (op, loc, arg1, arg2, end)
+    re_opcode_t op;
+    unsigned char *loc;
+    int arg1, arg2;
+    unsigned char *end;
+{
+  register unsigned char *pfrom = end;
+  register unsigned char *pto = end + 5;
+
+  while (pfrom != loc)
+    *--pto = *--pfrom;
+
+  store_op2 (op, loc, arg1, arg2);
+}
+
+
+/* P points to just after a ^ in PATTERN.  Return true if that ^ comes
+   after an alternative or a begin-subexpression.  We assume there is at
+   least one character before the ^.  */
+
+static boolean
+at_begline_loc_p (pattern, p, syntax)
+    const char *pattern, *p;
+    reg_syntax_t syntax;
+{
+  const char *prev = p - 2;
+  boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\';
+
+  return
+       /* After a subexpression?  */
+       (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash))
+       /* After an alternative?  */
+    || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash));
+}
+
+
+/* The dual of at_begline_loc_p.  This one is for $.  We assume there is
+   at least one character after the $, i.e., `P < PEND'.  */
+
+static boolean
+at_endline_loc_p (p, pend, syntax)
+    const char *p, *pend;
+    int syntax;
+{
+  const char *next = p;
+  boolean next_backslash = *next == '\\';
+  const char *next_next = p + 1 < pend ? p + 1 : NULL;
+
+  return
+       /* Before a subexpression?  */
+       (syntax & RE_NO_BK_PARENS ? *next == ')'
+       : next_backslash && next_next && *next_next == ')')
+       /* Before an alternative?  */
+    || (syntax & RE_NO_BK_VBAR ? *next == '|'
+       : next_backslash && next_next && *next_next == '|');
+}
+
+
+/* Returns true if REGNUM is in one of COMPILE_STACK's elements and
+   false if it's not.  */
+
+static boolean
+group_in_compile_stack (compile_stack, regnum)
+    compile_stack_type compile_stack;
+    regnum_t regnum;
+{
+  int this_element;
+
+  for (this_element = compile_stack.avail - 1;
+       this_element >= 0;
+       this_element--)
+    if (compile_stack.stack[this_element].regnum == regnum)
+      return true;
+
+  return false;
+}
+
+
+/* Read the ending character of a range (in a bracket expression) from the
+   uncompiled pattern *P_PTR (which ends at PEND).  We assume the
+   starting character is in `P[-2]'.  (`P[-1]' is the character `-'.)
+   Then we set the translation of all bits between the starting and
+   ending characters (inclusive) in the compiled pattern B.
+
+   Return an error code.
+
+   We use these short variable names so we can use the same macros as
+   `regex_compile' itself.  */
+
+static reg_errcode_t
+compile_range (p_ptr, pend, translate, syntax, b)
+    const char **p_ptr, *pend;
+    char *translate;
+    reg_syntax_t syntax;
+    unsigned char *b;
+{
+  unsigned this_char;
+
+  const char *p = *p_ptr;
+  int range_start, range_end;
+
+  if (p == pend)
+    return REG_ERANGE;
+
+  /* Even though the pattern is a signed `char *', we need to fetch
+     with unsigned char *'s; if the high bit of the pattern character
+     is set, the range endpoints will be negative if we fetch using a
+     signed char *.
+
+     We also want to fetch the endpoints without translating them; the
+     appropriate translation is done in the bit-setting loop below.  */
+  range_start = ((unsigned char *) p)[-2];
+  range_end   = ((unsigned char *) p)[0];
+
+  /* Have to increment the pointer into the pattern string, so the
+     caller isn't still at the ending character.  */
+  (*p_ptr)++;
+
+  /* If the start is after the end, the range is empty.  */
+  if (range_start > range_end)
+    return syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR;
+
+  /* Here we see why `this_char' has to be larger than an `unsigned
+     char' -- the range is inclusive, so if `range_end' == 0xff
+     (assuming 8-bit characters), we would otherwise go into an infinite
+     loop, since all characters <= 0xff.  */
+  for (this_char = range_start; this_char <= range_end; this_char++)
+    {
+      SET_LIST_BIT (TRANSLATE (this_char));
+    }
+
+  return REG_NOERROR;
+}
+\f
+/* Failure stack declarations and macros; both re_compile_fastmap and
+   re_match_2 use a failure stack.  These have to be macros because of
+   REGEX_ALLOCATE.  */
+
+
+/* Number of failure points for which to initially allocate space
+   when matching.  If this number is exceeded, we allocate more
+   space, so it is not a hard limit.  */
+#ifndef INIT_FAILURE_ALLOC
+#define INIT_FAILURE_ALLOC 5
+#endif
+
+/* Roughly the maximum number of failure points on the stack.  Would be
+   exactly that if always used MAX_FAILURE_SPACE each time we failed.
+   This is a variable only so users of regex can assign to it; we never
+   change it ourselves.  */
+int re_max_failures = 2000;
+
+typedef const unsigned char *fail_stack_elt_t;
+
+typedef struct
+{
+  fail_stack_elt_t *stack;
+  unsigned size;
+  unsigned avail;                      /* Offset of next open position.  */
+} fail_stack_type;
+
+#define FAIL_STACK_EMPTY()     (fail_stack.avail == 0)
+#define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0)
+#define FAIL_STACK_FULL()      (fail_stack.avail == fail_stack.size)
+#define FAIL_STACK_TOP()       (fail_stack.stack[fail_stack.avail])
+
+
+/* Initialize `fail_stack'.  Do `return -2' if the alloc fails.  */
+
+#define INIT_FAIL_STACK()                                              \
+  do {                                                                 \
+    fail_stack.stack = (fail_stack_elt_t *)                            \
+      REGEX_ALLOCATE (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t)); \
+                                                                       \
+    if (fail_stack.stack == NULL)                                      \
+      return -2;                                                       \
+                                                                       \
+    fail_stack.size = INIT_FAILURE_ALLOC;                              \
+    fail_stack.avail = 0;                                              \
+  } while (0)
+
+
+/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items.
+
+   Return 1 if succeeds, and 0 if either ran out of memory
+   allocating space for it or it was already too large.
+
+   REGEX_REALLOCATE requires `destination' be declared.   */
+
+#define DOUBLE_FAIL_STACK(fail_stack)                                  \
+  ((fail_stack).size > re_max_failures * MAX_FAILURE_ITEMS             \
+   ? 0                                                                 \
+   : ((fail_stack).stack = (fail_stack_elt_t *)                                \
+       REGEX_REALLOCATE ((fail_stack).stack,                           \
+         (fail_stack).size * sizeof (fail_stack_elt_t),                \
+         ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)),        \
+                                                                       \
+      (fail_stack).stack == NULL                                       \
+      ? 0                                                              \
+      : ((fail_stack).size <<= 1,                                      \
+        1)))
+
+
+/* Push PATTERN_OP on FAIL_STACK.
+
+   Return 1 if was able to do so and 0 if ran out of memory allocating
+   space to do so.  */
+#define PUSH_PATTERN_OP(pattern_op, fail_stack)                                \
+  ((FAIL_STACK_FULL ()                                                 \
+    && !DOUBLE_FAIL_STACK (fail_stack))                                        \
+    ? 0                                                                        \
+    : ((fail_stack).stack[(fail_stack).avail++] = pattern_op,          \
+       1))
+
+/* This pushes an item onto the failure stack.  Must be a four-byte
+   value.  Assumes the variable `fail_stack'.  Probably should only
+   be called from within `PUSH_FAILURE_POINT'.  */
+#define PUSH_FAILURE_ITEM(item)                                                \
+  fail_stack.stack[fail_stack.avail++] = (fail_stack_elt_t) item
+
+/* The complement operation.  Assumes `fail_stack' is nonempty.  */
+#define POP_FAILURE_ITEM() fail_stack.stack[--fail_stack.avail]
+
+/* Used to omit pushing failure point id's when we're not debugging.  */
+#ifdef DEBUG
+#define DEBUG_PUSH PUSH_FAILURE_ITEM
+#define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_ITEM ()
+#else
+#define DEBUG_PUSH(item)
+#define DEBUG_POP(item_addr)
+#endif
+
+
+/* Push the information about the state we will need
+   if we ever fail back to it.
+
+   Requires variables fail_stack, regstart, regend, reg_info, and
+   num_regs be declared.  DOUBLE_FAIL_STACK requires `destination' be
+   declared.
+
+   Does `return FAILURE_CODE' if runs out of memory.  */
+
+#define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code)  \
+  do {                                                                 \
+    char *destination;                                                 \
+    /* Must be int, so when we don't save any registers, the arithmetic        \
+       of 0 + -1 isn't done as unsigned.  */                           \
+    int this_reg;                                                      \
+                                                                       \
+    DEBUG_STATEMENT (failure_id++);                                    \
+    DEBUG_STATEMENT (nfailure_points_pushed++);                                \
+    DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id);          \
+    DEBUG_PRINT2 ("  Before push, next avail: %d\n", (fail_stack).avail);\
+    DEBUG_PRINT2 ("                     size: %d\n", (fail_stack).size);\
+                                                                       \
+    DEBUG_PRINT2 ("  slots needed: %d\n", NUM_FAILURE_ITEMS);          \
+    DEBUG_PRINT2 ("     available: %d\n", REMAINING_AVAIL_SLOTS);      \
+                                                                       \
+    /* Ensure we have enough space allocated for what we will push.  */        \
+    while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS)                  \
+      {                                                                        \
+       if (!DOUBLE_FAIL_STACK (fail_stack))                    \
+         return failure_code;                                          \
+                                                                       \
+       DEBUG_PRINT2 ("\n  Doubled stack; size now: %d\n",              \
+                      (fail_stack).size);                              \
+       DEBUG_PRINT2 ("  slots available: %d\n", REMAINING_AVAIL_SLOTS);\
+      }                                                                        \
+                                                                       \
+    /* Push the info, starting with the registers.  */                 \
+    DEBUG_PRINT1 ("\n");                                               \
+                                                                       \
+    for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \
+        this_reg++)                                                    \
+      {                                                                        \
+       DEBUG_PRINT2 ("  Pushing reg: %d\n", this_reg);                 \
+       DEBUG_STATEMENT (num_regs_pushed++);                            \
+                                                                       \
+       DEBUG_PRINT2 ("    start: 0x%x\n", regstart[this_reg]);         \
+       PUSH_FAILURE_ITEM (regstart[this_reg]);                         \
+                                                                       \
+       DEBUG_PRINT2 ("    end: 0x%x\n", regend[this_reg]);             \
+       PUSH_FAILURE_ITEM (regend[this_reg]);                           \
+                                                                       \
+       DEBUG_PRINT2 ("    info: 0x%x\n      ", reg_info[this_reg]);    \
+       DEBUG_PRINT2 (" match_null=%d",                                 \
+                     REG_MATCH_NULL_STRING_P (reg_info[this_reg]));    \
+       DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg]));    \
+       DEBUG_PRINT2 (" matched_something=%d",                          \
+                     MATCHED_SOMETHING (reg_info[this_reg]));          \
+       DEBUG_PRINT2 (" ever_matched=%d",                               \
+                     EVER_MATCHED_SOMETHING (reg_info[this_reg]));     \
+       DEBUG_PRINT1 ("\n");                                            \
+       PUSH_FAILURE_ITEM (reg_info[this_reg].word);                    \
+      }                                                                        \
+                                                                       \
+    DEBUG_PRINT2 ("  Pushing  low active reg: %d\n", lowest_active_reg);\
+    PUSH_FAILURE_ITEM (lowest_active_reg);                             \
+                                                                       \
+    DEBUG_PRINT2 ("  Pushing high active reg: %d\n", highest_active_reg);\
+    PUSH_FAILURE_ITEM (highest_active_reg);                            \
+                                                                       \
+    DEBUG_PRINT2 ("  Pushing pattern 0x%x: ", pattern_place);          \
+    DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend);          \
+    PUSH_FAILURE_ITEM (pattern_place);                                 \
+                                                                       \
+    DEBUG_PRINT2 ("  Pushing string 0x%x: `", string_place);           \
+    DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2,   \
+                                size2);                                \
+    DEBUG_PRINT1 ("'\n");                                              \
+    PUSH_FAILURE_ITEM (string_place);                                  \
+                                                                       \
+    DEBUG_PRINT2 ("  Pushing failure id: %u\n", failure_id);           \
+    DEBUG_PUSH (failure_id);                                           \
+  } while (0)
+
+/* This is the number of items that are pushed and popped on the stack
+   for each register.  */
+#define NUM_REG_ITEMS  3
+
+/* Individual items aside from the registers.  */
+#ifdef DEBUG
+#define NUM_NONREG_ITEMS 5 /* Includes failure point id.  */
+#else
+#define NUM_NONREG_ITEMS 4
+#endif
+
+/* We push at most this many items on the stack.  */
+#define MAX_FAILURE_ITEMS ((num_regs - 1) * NUM_REG_ITEMS + NUM_NONREG_ITEMS)
+
+/* We actually push this many items.  */
+#define NUM_FAILURE_ITEMS                                              \
+  ((highest_active_reg - lowest_active_reg + 1) * NUM_REG_ITEMS        \
+    + NUM_NONREG_ITEMS)
+
+/* How many items can still be added to the stack without overflowing it.  */
+#define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail)
+
+
+/* Pops what PUSH_FAIL_STACK pushes.
+
+   We restore into the parameters, all of which should be lvalues:
+     STR -- the saved data position.
+     PAT -- the saved pattern position.
+     LOW_REG, HIGH_REG -- the highest and lowest active registers.
+     REGSTART, REGEND -- arrays of string positions.
+     REG_INFO -- array of information about each subexpression.
+
+   Also assumes the variables `fail_stack' and (if debugging), `bufp',
+   `pend', `string1', `size1', `string2', and `size2'.  */
+
+#define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\
+{                                                                      \
+  DEBUG_STATEMENT (fail_stack_elt_t failure_id;)                       \
+  int this_reg;                                                                \
+  const unsigned char *string_temp;                                    \
+                                                                       \
+  assert (!FAIL_STACK_EMPTY ());                                       \
+                                                                       \
+  /* Remove failure points and point to how many regs pushed.  */      \
+  DEBUG_PRINT1 ("POP_FAILURE_POINT:\n");                               \
+  DEBUG_PRINT2 ("  Before pop, next avail: %d\n", fail_stack.avail);   \
+  DEBUG_PRINT2 ("                    size: %d\n", fail_stack.size);    \
+                                                                       \
+  assert (fail_stack.avail >= NUM_NONREG_ITEMS);                       \
+                                                                       \
+  DEBUG_POP (&failure_id);                                             \
+  DEBUG_PRINT2 ("  Popping failure id: %u\n", failure_id);             \
+                                                                       \
+  /* If the saved string location is NULL, it came from an             \
+     on_failure_keep_string_jump opcode, and we want to throw away the \
+     saved NULL, thus retaining our current position in the string.  */        \
+  string_temp = POP_FAILURE_ITEM ();                                   \
+  if (string_temp != NULL)                                             \
+    str = (const char *) string_temp;                                  \
+                                                                       \
+  DEBUG_PRINT2 ("  Popping string 0x%x: `", str);                      \
+  DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2);     \
+  DEBUG_PRINT1 ("'\n");                                                        \
+                                                                       \
+  pat = (unsigned char *) POP_FAILURE_ITEM ();                         \
+  DEBUG_PRINT2 ("  Popping pattern 0x%x: ", pat);                      \
+  DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend);                      \
+                                                                       \
+  /* Restore register info.  */                                                \
+  high_reg = (unsigned) POP_FAILURE_ITEM ();                           \
+  DEBUG_PRINT2 ("  Popping high active reg: %d\n", high_reg);          \
+                                                                       \
+  low_reg = (unsigned) POP_FAILURE_ITEM ();                            \
+  DEBUG_PRINT2 ("  Popping  low active reg: %d\n", low_reg);           \
+                                                                       \
+  for (this_reg = high_reg; this_reg >= low_reg; this_reg--)           \
+    {                                                                  \
+      DEBUG_PRINT2 ("    Popping reg: %d\n", this_reg);                        \
+                                                                       \
+      reg_info[this_reg].word = POP_FAILURE_ITEM ();                   \
+      DEBUG_PRINT2 ("      info: 0x%x\n", reg_info[this_reg]);         \
+                                                                       \
+      regend[this_reg] = (const char *) POP_FAILURE_ITEM ();           \
+      DEBUG_PRINT2 ("      end: 0x%x\n", regend[this_reg]);            \
+                                                                       \
+      regstart[this_reg] = (const char *) POP_FAILURE_ITEM ();         \
+      DEBUG_PRINT2 ("      start: 0x%x\n", regstart[this_reg]);                \
+    }                                                                  \
+                                                                       \
+  DEBUG_STATEMENT (nfailure_points_popped++);                          \
+} /* POP_FAILURE_POINT */
+\f
+/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in
+   BUFP.  A fastmap records which of the (1 << BYTEWIDTH) possible
+   characters can start a string that matches the pattern.  This fastmap
+   is used by re_search to skip quickly over impossible starting points.
+
+   The caller must supply the address of a (1 << BYTEWIDTH)-byte data
+   area as BUFP->fastmap.
+
+   We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in
+   the pattern buffer.
+
+   Returns 0 if we succeed, -2 if an internal error.   */
+
+int
+re_compile_fastmap (bufp)
+     struct re_pattern_buffer *bufp;
+{
+  int j, k;
+  fail_stack_type fail_stack;
+#ifndef REGEX_MALLOC
+  char *destination;
+#endif
+  /* We don't push any register information onto the failure stack.  */
+  unsigned num_regs = 0;
+
+  register char *fastmap = bufp->fastmap;
+  unsigned char *pattern = bufp->buffer;
+  unsigned long size = bufp->used;
+  const unsigned char *p = pattern;
+  register unsigned char *pend = pattern + size;
+
+  /* Assume that each path through the pattern can be null until
+     proven otherwise.  We set this false at the bottom of switch
+     statement, to which we get only if a particular path doesn't
+     match the empty string.  */
+  boolean path_can_be_null = true;
+
+  /* We aren't doing a `succeed_n' to begin with.  */
+  boolean succeed_n_p = false;
+
+  assert (fastmap != NULL && p != NULL);
+
+  INIT_FAIL_STACK ();
+  bzero (fastmap, 1 << BYTEWIDTH);  /* Assume nothing's valid.  */
+  bufp->fastmap_accurate = 1;      /* It will be when we're done.  */
+  bufp->can_be_null = 0;
+
+  while (p != pend || !FAIL_STACK_EMPTY ())
+    {
+      if (p == pend)
+       {
+         bufp->can_be_null |= path_can_be_null;
+
+         /* Reset for next path.  */
+         path_can_be_null = true;
+
+         p = fail_stack.stack[--fail_stack.avail];
+       }
+
+      /* We should never be about to go beyond the end of the pattern.  */
+      assert (p < pend);
+
+#ifdef SWITCH_ENUM_BUG
+      switch ((int) ((re_opcode_t) *p++))
+#else
+      switch ((re_opcode_t) *p++)
+#endif
+       {
+
+       /* I guess the idea here is to simply not bother with a fastmap
+          if a backreference is used, since it's too hard to figure out
+          the fastmap for the corresponding group.  Setting
+          `can_be_null' stops `re_search_2' from using the fastmap, so
+          that is all we do.  */
+       case duplicate:
+         bufp->can_be_null = 1;
+         return 0;
+
+
+      /* Following are the cases which match a character.  These end
+        with `break'.  */
+
+       case exactn:
+         fastmap[p[1]] = 1;
+         break;
+
+
+       case charset:
+         for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
+           if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))
+             fastmap[j] = 1;
+         break;
+
+
+       case charset_not:
+         /* Chars beyond end of map must be allowed.  */
+         for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++)
+           fastmap[j] = 1;
+
+         for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
+           if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))))
+             fastmap[j] = 1;
+         break;
+
+
+       case wordchar:
+         for (j = 0; j < (1 << BYTEWIDTH); j++)
+           if (SYNTAX (j) == Sword)
+             fastmap[j] = 1;
+         break;
+
+
+       case notwordchar:
+         for (j = 0; j < (1 << BYTEWIDTH); j++)
+           if (SYNTAX (j) != Sword)
+             fastmap[j] = 1;
+         break;
+
+
+       case anychar:
+         /* `.' matches anything ...  */
+         for (j = 0; j < (1 << BYTEWIDTH); j++)
+           fastmap[j] = 1;
+
+         /* ... except perhaps newline.  */
+         if (!(bufp->syntax & RE_DOT_NEWLINE))
+           fastmap['\n'] = 0;
+
+         /* Return if we have already set `can_be_null'; if we have,
+            then the fastmap is irrelevant.  Something's wrong here.  */
+         else if (bufp->can_be_null)
+           return 0;
+
+         /* Otherwise, have to check alternative paths.  */
+         break;
+
+
+#ifdef emacs
+       case syntaxspec:
+         k = *p++;
+         for (j = 0; j < (1 << BYTEWIDTH); j++)
+           if (SYNTAX (j) == (enum syntaxcode) k)
+             fastmap[j] = 1;
+         break;
+
+
+       case notsyntaxspec:
+         k = *p++;
+         for (j = 0; j < (1 << BYTEWIDTH); j++)
+           if (SYNTAX (j) != (enum syntaxcode) k)
+             fastmap[j] = 1;
+         break;
+
+
+      /* All cases after this match the empty string.  These end with
+        `continue'.  */
+
+
+       case before_dot:
+       case at_dot:
+       case after_dot:
+         continue;
+#endif /* not emacs */
+
+
+       case no_op:
+       case begline:
+       case endline:
+       case begbuf:
+       case endbuf:
+       case wordbound:
+       case notwordbound:
+       case wordbeg:
+       case wordend:
+       case push_dummy_failure:
+         continue;
+
+
+       case jump_n:
+       case pop_failure_jump:
+       case maybe_pop_jump:
+       case jump:
+       case jump_past_alt:
+       case dummy_failure_jump:
+         EXTRACT_NUMBER_AND_INCR (j, p);
+         p += j;
+         if (j > 0)
+           continue;
+
+         /* Jump backward implies we just went through the body of a
+            loop and matched nothing.  Opcode jumped to should be
+            `on_failure_jump' or `succeed_n'.  Just treat it like an
+            ordinary jump.  For a * loop, it has pushed its failure
+            point already; if so, discard that as redundant.  */
+         if ((re_opcode_t) *p != on_failure_jump
+             && (re_opcode_t) *p != succeed_n)
+           continue;
+
+         p++;
+         EXTRACT_NUMBER_AND_INCR (j, p);
+         p += j;
+
+         /* If what's on the stack is where we are now, pop it.  */
+         if (!FAIL_STACK_EMPTY ()
+             && fail_stack.stack[fail_stack.avail - 1] == p)
+           fail_stack.avail--;
+
+         continue;
+
+
+       case on_failure_jump:
+       case on_failure_keep_string_jump:
+       handle_on_failure_jump:
+         EXTRACT_NUMBER_AND_INCR (j, p);
+
+         /* For some patterns, e.g., `(a?)?', `p+j' here points to the
+            end of the pattern.  We don't want to push such a point,
+            since when we restore it above, entering the switch will
+            increment `p' past the end of the pattern.  We don't need
+            to push such a point since we obviously won't find any more
+            fastmap entries beyond `pend'.  Such a pattern can match
+            the null string, though.  */
+         if (p + j < pend)
+           {
+             if (!PUSH_PATTERN_OP (p + j, fail_stack))
+               return -2;
+           }
+         else
+           bufp->can_be_null = 1;
+
+         if (succeed_n_p)
+           {
+             EXTRACT_NUMBER_AND_INCR (k, p);   /* Skip the n.  */
+             succeed_n_p = false;
+           }
+
+         continue;
+
+
+       case succeed_n:
+         /* Get to the number of times to succeed.  */
+         p += 2;
+
+         /* Increment p past the n for when k != 0.  */
+         EXTRACT_NUMBER_AND_INCR (k, p);
+         if (k == 0)
+           {
+             p -= 4;
+             succeed_n_p = true;  /* Spaghetti code alert.  */
+             goto handle_on_failure_jump;
+           }
+         continue;
+
+
+       case set_number_at:
+         p += 4;
+         continue;
+
+
+       case start_memory:
+       case stop_memory:
+         p += 2;
+         continue;
+
+
+       default:
+         abort (); /* We have listed all the cases.  */
+       } /* switch *p++ */
+
+      /* Getting here means we have found the possible starting
+        characters for one path of the pattern -- and that the empty
+        string does not match.  We need not follow this path further.
+        Instead, look at the next alternative (remembered on the
+        stack), or quit if no more.  The test at the top of the loop
+        does these things.  */
+      path_can_be_null = false;
+      p = pend;
+    } /* while p */
+
+  /* Set `can_be_null' for the last path (also the first path, if the
+     pattern is empty).  */
+  bufp->can_be_null |= path_can_be_null;
+  return 0;
+} /* re_compile_fastmap */
+\f
+/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
+   ENDS.  Subsequent matches using PATTERN_BUFFER and REGS will use
+   this memory for recording register information.  STARTS and ENDS
+   must be allocated using the malloc library routine, and must each
+   be at least NUM_REGS * sizeof (regoff_t) bytes long.
+
+   If NUM_REGS == 0, then subsequent matches should allocate their own
+   register data.
+
+   Unless this function is called, the first search or match using
+   PATTERN_BUFFER will allocate its own register data, without
+   freeing the old data.  */
+
+void
+re_set_registers (bufp, regs, num_regs, starts, ends)
+    struct re_pattern_buffer *bufp;
+    struct re_registers *regs;
+    unsigned num_regs;
+    regoff_t *starts, *ends;
+{
+  if (num_regs)
+    {
+      bufp->regs_allocated = REGS_REALLOCATE;
+      regs->num_regs = num_regs;
+      regs->start = starts;
+      regs->end = ends;
+    }
+  else
+    {
+      bufp->regs_allocated = REGS_UNALLOCATED;
+      regs->num_regs = 0;
+      regs->start = regs->end = (regoff_t) 0;
+    }
+}
+\f
+/* Searching routines.  */
+
+/* Like re_search_2, below, but only one string is specified, and
+   doesn't let you say where to stop matching. */
+
+int
+re_search (bufp, string, size, startpos, range, regs)
+     struct re_pattern_buffer *bufp;
+     const char *string;
+     int size, startpos, range;
+     struct re_registers *regs;
+{
+  return re_search_2 (bufp, NULL, 0, string, size, startpos, range,
+                     regs, size);
+}
+
+
+/* Using the compiled pattern in BUFP->buffer, first tries to match the
+   virtual concatenation of STRING1 and STRING2, starting first at index
+   STARTPOS, then at STARTPOS + 1, and so on.
+
+   STRING1 and STRING2 have length SIZE1 and SIZE2, respectively.
+
+   RANGE is how far to scan while trying to match.  RANGE = 0 means try
+   only at STARTPOS; in general, the last start tried is STARTPOS +
+   RANGE.
+
+   In REGS, return the indices of the virtual concatenation of STRING1
+   and STRING2 that matched the entire BUFP->buffer and its contained
+   subexpressions.
+
+   Do not consider matching one past the index STOP in the virtual
+   concatenation of STRING1 and STRING2.
+
+   We return either the position in the strings at which the match was
+   found, -1 if no match, or -2 if error (such as failure
+   stack overflow).  */
+
+int
+re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop)
+     struct re_pattern_buffer *bufp;
+     const char *string1, *string2;
+     int size1, size2;
+     int startpos;
+     int range;
+     struct re_registers *regs;
+     int stop;
+{
+  int val;
+  register char *fastmap = bufp->fastmap;
+  register char *translate = bufp->translate;
+  int total_size = size1 + size2;
+  int endpos = startpos + range;
+
+  /* Check for out-of-range STARTPOS.  */
+  if (startpos < 0 || startpos > total_size)
+    return -1;
+
+  /* Fix up RANGE if it might eventually take us outside
+     the virtual concatenation of STRING1 and STRING2.  */
+  if (endpos < -1)
+    range = -1 - startpos;
+  else if (endpos > total_size)
+    range = total_size - startpos;
+
+  /* If the search isn't to be a backwards one, don't waste time in a
+     search for a pattern that must be anchored.  */
+  if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == begbuf && range > 0)
+    {
+      if (startpos > 0)
+       return -1;
+      else
+       range = 1;
+    }
+
+  /* Update the fastmap now if not correct already.  */
+  if (fastmap && !bufp->fastmap_accurate)
+    if (re_compile_fastmap (bufp) == -2)
+      return -2;
+
+  /* Loop through the string, looking for a place to start matching.  */
+  for (;;)
+    {
+      /* If a fastmap is supplied, skip quickly over characters that
+        cannot be the start of a match.  If the pattern can match the
+        null string, however, we don't need to skip characters; we want
+        the first null string.  */
+      if (fastmap && startpos < total_size && !bufp->can_be_null)
+       {
+         if (range > 0)        /* Searching forwards.  */
+           {
+             register const char *d;
+             register int lim = 0;
+             int irange = range;
+
+             if (startpos < size1 && startpos + range >= size1)
+               lim = range - (size1 - startpos);
+
+             d = (startpos >= size1 ? string2 - size1 : string1) + startpos;
+
+             /* Written out as an if-else to avoid testing `translate'
+                inside the loop.  */
+             if (translate)
+               while (range > lim
+                      && !fastmap[(unsigned char)
+                                  translate[(unsigned char) *d++]])
+                 range--;
+             else
+               while (range > lim && !fastmap[(unsigned char) *d++])
+                 range--;
+
+             startpos += irange - range;
+           }
+         else                          /* Searching backwards.  */
+           {
+             register char c = (size1 == 0 || startpos >= size1
+                                ? string2[startpos - size1]
+                                : string1[startpos]);
+
+             if (!fastmap[(unsigned char) TRANSLATE (c)])
+               goto advance;
+           }
+       }
+
+      /* If can't match the null string, and that's all we have left, fail.  */
+      if (range >= 0 && startpos == total_size && fastmap
+         && !bufp->can_be_null)
+       return -1;
+
+      val = re_match_2 (bufp, string1, size1, string2, size2,
+                       startpos, regs, stop);
+      if (val >= 0)
+       return startpos;
+
+      if (val == -2)
+       return -2;
+
+    advance:
+      if (!range)
+       break;
+      else if (range > 0)
+       {
+         range--;
+         startpos++;
+       }
+      else
+       {
+         range++;
+         startpos--;
+       }
+    }
+  return -1;
+} /* re_search_2 */
+\f
+/* Declarations and macros for re_match_2.  */
+
+static int bcmp_translate ();
+static boolean alt_match_null_string_p (),
+              common_op_match_null_string_p (),
+              group_match_null_string_p ();
+
+/* Structure for per-register (a.k.a. per-group) information.
+   This must not be longer than one word, because we push this value
+   onto the failure stack.  Other register information, such as the
+   starting and ending positions (which are addresses), and the list of
+   inner groups (which is a bits list) are maintained in separate
+   variables.
+
+   We are making a (strictly speaking) nonportable assumption here: that
+   the compiler will pack our bit fields into something that fits into
+   the type of `word', i.e., is something that fits into one item on the
+   failure stack.  */
+typedef union
+{
+  fail_stack_elt_t word;
+  struct
+  {
+      /* This field is one if this group can match the empty string,
+        zero if not.  If not yet determined,  `MATCH_NULL_UNSET_VALUE'.  */
+#define MATCH_NULL_UNSET_VALUE 3
+    unsigned match_null_string_p : 2;
+    unsigned is_active : 1;
+    unsigned matched_something : 1;
+    unsigned ever_matched_something : 1;
+  } bits;
+} register_info_type;
+
+#define REG_MATCH_NULL_STRING_P(R)  ((R).bits.match_null_string_p)
+#define IS_ACTIVE(R)  ((R).bits.is_active)
+#define MATCHED_SOMETHING(R)  ((R).bits.matched_something)
+#define EVER_MATCHED_SOMETHING(R)  ((R).bits.ever_matched_something)
+
+
+/* Call this when have matched a real character; it sets `matched' flags
+   for the subexpressions which we are currently inside.  Also records
+   that those subexprs have matched.  */
+#define SET_REGS_MATCHED()                                             \
+  do                                                                   \
+    {                                                                  \
+      unsigned r;                                                      \
+      for (r = lowest_active_reg; r <= highest_active_reg; r++)                \
+       {                                                               \
+         MATCHED_SOMETHING (reg_info[r])                               \
+           = EVER_MATCHED_SOMETHING (reg_info[r])                      \
+           = 1;                                                        \
+       }                                                               \
+    }                                                                  \
+  while (0)
+
+
+/* This converts PTR, a pointer into one of the search strings `string1'
+   and `string2' into an offset from the beginning of that string.  */
+#define POINTER_TO_OFFSET(ptr)                                         \
+  (FIRST_STRING_P (ptr) ? (ptr) - string1 : (ptr) - string2 + size1)
+
+/* Registers are set to a sentinel when they haven't yet matched.  */
+#define REG_UNSET_VALUE ((char *) -1)
+#define REG_UNSET(e) ((e) == REG_UNSET_VALUE)
+
+
+/* Macros for dealing with the split strings in re_match_2.  */
+
+#define MATCHING_IN_FIRST_STRING  (dend == end_match_1)
+
+/* Call before fetching a character with *d.  This switches over to
+   string2 if necessary.  */
+#define PREFETCH()                                                     \
+  while (d == dend)                                                    \
+    {                                                                  \
+      /* End of string2 => fail.  */                                   \
+      if (dend == end_match_2)                                                 \
+       goto fail;                                                      \
+      /* End of string1 => advance to string2.  */                     \
+      d = string2;                                                     \
+      dend = end_match_2;                                              \
+    }
+
+
+/* Test if at very beginning or at very end of the virtual concatenation
+   of `string1' and `string2'.  If only one string, it's `string2'.  */
+#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2)
+#define AT_STRINGS_END(d) ((d) == end2)
+
+
+/* Test if D points to a character which is word-constituent.  We have
+   two special cases to check for: if past the end of string1, look at
+   the first character in string2; and if before the beginning of
+   string2, look at the last character in string1.  */
+#define WORDCHAR_P(d)                                                  \
+  (SYNTAX ((d) == end1 ? *string2                                      \
+          : (d) == string2 - 1 ? *(end1 - 1) : *(d))                   \
+   == Sword)
+
+/* Test if the character before D and the one at D differ with respect
+   to being word-constituent.  */
+#define AT_WORD_BOUNDARY(d)                                            \
+  (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)                            \
+   || WORDCHAR_P (d - 1) != WORDCHAR_P (d))
+
+
+/* Free everything we malloc.  */
+#ifdef REGEX_MALLOC
+#define FREE_VAR(var) if (var) free (var); var = NULL
+#define FREE_VARIABLES()                                               \
+  do {                                                                 \
+    FREE_VAR (fail_stack.stack);                                       \
+    FREE_VAR (regstart);                                               \
+    FREE_VAR (regend);                                                 \
+    FREE_VAR (old_regstart);                                           \
+    FREE_VAR (old_regend);                                             \
+    FREE_VAR (best_regstart);                                          \
+    FREE_VAR (best_regend);                                            \
+    FREE_VAR (reg_info);                                               \
+    FREE_VAR (reg_dummy);                                              \
+    FREE_VAR (reg_info_dummy);                                         \
+  } while (0)
+#else /* not REGEX_MALLOC */
+/* Some MIPS systems (at least) want this to free alloca'd storage.  */
+#define FREE_VARIABLES() alloca (0)
+#endif /* not REGEX_MALLOC */
+
+
+/* These values must meet several constraints.  They must not be valid
+   register values; since we have a limit of 255 registers (because
+   we use only one byte in the pattern for the register number), we can
+   use numbers larger than 255.  They must differ by 1, because of
+   NUM_FAILURE_ITEMS above.  And the value for the lowest register must
+   be larger than the value for the highest register, so we do not try
+   to actually save any registers when none are active.  */
+#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH)
+#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1)
+\f
+/* Matching routines.  */
+
+#ifndef emacs   /* Emacs never uses this.  */
+/* re_match is like re_match_2 except it takes only a single string.  */
+
+int
+re_match (bufp, string, size, pos, regs)
+     struct re_pattern_buffer *bufp;
+     const char *string;
+     int size, pos;
+     struct re_registers *regs;
+ {
+  return re_match_2 (bufp, NULL, 0, string, size, pos, regs, size);
+}
+#endif /* not emacs */
+
+
+/* re_match_2 matches the compiled pattern in BUFP against the
+   the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1
+   and SIZE2, respectively).  We start matching at POS, and stop
+   matching at STOP.
+
+   If REGS is non-null and the `no_sub' field of BUFP is nonzero, we
+   store offsets for the substring each group matched in REGS.  See the
+   documentation for exactly how many groups we fill.
+
+   We return -1 if no match, -2 if an internal error (such as the
+   failure stack overflowing).  Otherwise, we return the length of the
+   matched substring.  */
+
+int
+re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
+     struct re_pattern_buffer *bufp;
+     const char *string1, *string2;
+     int size1, size2;
+     int pos;
+     struct re_registers *regs;
+     int stop;
+{
+  /* General temporaries.  */
+  int mcnt;
+  unsigned char *p1;
+
+  /* Just past the end of the corresponding string.  */
+  const char *end1, *end2;
+
+  /* Pointers into string1 and string2, just past the last characters in
+     each to consider matching.  */
+  const char *end_match_1, *end_match_2;
+
+  /* Where we are in the data, and the end of the current string.  */
+  const char *d, *dend;
+
+  /* Where we are in the pattern, and the end of the pattern.  */
+  unsigned char *p = bufp->buffer;
+  register unsigned char *pend = p + bufp->used;
+
+  /* We use this to map every character in the string.  */
+  char *translate = bufp->translate;
+
+  /* Failure point stack.  Each place that can handle a failure further
+     down the line pushes a failure point on this stack.  It consists of
+     restart, regend, and reg_info for all registers corresponding to
+     the subexpressions we're currently inside, plus the number of such
+     registers, and, finally, two char *'s.  The first char * is where
+     to resume scanning the pattern; the second one is where to resume
+     scanning the strings.  If the latter is zero, the failure point is
+     a ``dummy''; if a failure happens and the failure point is a dummy,
+     it gets discarded and the next next one is tried.  */
+  fail_stack_type fail_stack;
+#ifdef DEBUG
+  static unsigned failure_id = 0;
+  unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0;
+#endif
+
+  /* We fill all the registers internally, independent of what we
+     return, for use in backreferences.  The number here includes
+     an element for register zero.  */
+  unsigned num_regs = bufp->re_nsub + 1;
+
+  /* The currently active registers.  */
+  unsigned lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+  unsigned highest_active_reg = NO_HIGHEST_ACTIVE_REG;
+
+  /* Information on the contents of registers. These are pointers into
+     the input strings; they record just what was matched (on this
+     attempt) by a subexpression part of the pattern, that is, the
+     regnum-th regstart pointer points to where in the pattern we began
+     matching and the regnum-th regend points to right after where we
+     stopped matching the regnum-th subexpression.  (The zeroth register
+     keeps track of what the whole pattern matches.)  */
+  const char **regstart = NULL, **regend = NULL;
+
+  /* If a group that's operated upon by a repetition operator fails to
+     match anything, then the register for its start will need to be
+     restored because it will have been set to wherever in the string we
+     are when we last see its open-group operator.  Similarly for a
+     register's end.  */
+  const char **old_regstart = NULL, **old_regend = NULL;
+
+  /* The is_active field of reg_info helps us keep track of which (possibly
+     nested) subexpressions we are currently in. The matched_something
+     field of reg_info[reg_num] helps us tell whether or not we have
+     matched any of the pattern so far this time through the reg_num-th
+     subexpression.  These two fields get reset each time through any
+     loop their register is in.  */
+  register_info_type *reg_info = NULL;
+
+  /* The following record the register info as found in the above
+     variables when we find a match better than any we've seen before.
+     This happens as we backtrack through the failure points, which in
+     turn happens only if we have not yet matched the entire string. */
+  unsigned best_regs_set = false;
+  const char **best_regstart = NULL, **best_regend = NULL;
+
+  /* Logically, this is `best_regend[0]'.  But we don't want to have to
+     allocate space for that if we're not allocating space for anything
+     else (see below).  Also, we never need info about register 0 for
+     any of the other register vectors, and it seems rather a kludge to
+     treat `best_regend' differently than the rest.  So we keep track of
+     the end of the best match so far in a separate variable.  We
+     initialize this to NULL so that when we backtrack the first time
+     and need to test it, it's not garbage.  */
+  const char *match_end = NULL;
+
+  /* Used when we pop values we don't care about.  */
+  const char **reg_dummy = NULL;
+  register_info_type *reg_info_dummy = NULL;
+
+#ifdef DEBUG
+  /* Counts the total number of registers pushed.  */
+  unsigned num_regs_pushed = 0;
+#endif
+
+  DEBUG_PRINT1 ("\n\nEntering re_match_2.\n");
+
+  INIT_FAIL_STACK ();
+
+  /* Do not bother to initialize all the register variables if there are
+     no groups in the pattern, as it takes a fair amount of time.  If
+     there are groups, we include space for register 0 (the whole
+     pattern), even though we never use it, since it simplifies the
+     array indexing.  We should fix this.  */
+  if (bufp->re_nsub)
+    {
+      regstart = REGEX_TALLOC (num_regs, const char *);
+      regend = REGEX_TALLOC (num_regs, const char *);
+      old_regstart = REGEX_TALLOC (num_regs, const char *);
+      old_regend = REGEX_TALLOC (num_regs, const char *);
+      best_regstart = REGEX_TALLOC (num_regs, const char *);
+      best_regend = REGEX_TALLOC (num_regs, const char *);
+      reg_info = REGEX_TALLOC (num_regs, register_info_type);
+      reg_dummy = REGEX_TALLOC (num_regs, const char *);
+      reg_info_dummy = REGEX_TALLOC (num_regs, register_info_type);
+
+      if (!(regstart && regend && old_regstart && old_regend && reg_info
+           && best_regstart && best_regend && reg_dummy && reg_info_dummy))
+       {
+         FREE_VARIABLES ();
+         return -2;
+       }
+    }
+#ifdef REGEX_MALLOC
+  else
+    {
+      /* We must initialize all our variables to NULL, so that
+        `FREE_VARIABLES' doesn't try to free them.  */
+      regstart = regend = old_regstart = old_regend = best_regstart
+       = best_regend = reg_dummy = NULL;
+      reg_info = reg_info_dummy = (register_info_type *) NULL;
+    }
+#endif /* REGEX_MALLOC */
+
+  /* The starting position is bogus.  */
+  if (pos < 0 || pos > size1 + size2)
+    {
+      FREE_VARIABLES ();
+      return -1;
+    }
+
+  /* Initialize subexpression text positions to -1 to mark ones that no
+     start_memory/stop_memory has been seen for. Also initialize the
+     register information struct.  */
+  for (mcnt = 1; mcnt < num_regs; mcnt++)
+    {
+      regstart[mcnt] = regend[mcnt]
+       = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE;
+
+      REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE;
+      IS_ACTIVE (reg_info[mcnt]) = 0;
+      MATCHED_SOMETHING (reg_info[mcnt]) = 0;
+      EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0;
+    }
+
+  /* We move `string1' into `string2' if the latter's empty -- but not if
+     `string1' is null.  */
+  if (size2 == 0 && string1 != NULL)
+    {
+      string2 = string1;
+      size2 = size1;
+      string1 = 0;
+      size1 = 0;
+    }
+  end1 = string1 + size1;
+  end2 = string2 + size2;
+
+  /* Compute where to stop matching, within the two strings.  */
+  if (stop <= size1)
+    {
+      end_match_1 = string1 + stop;
+      end_match_2 = string2;
+    }
+  else
+    {
+      end_match_1 = end1;
+      end_match_2 = string2 + stop - size1;
+    }
+
+  /* `p' scans through the pattern as `d' scans through the data.
+     `dend' is the end of the input string that `d' points within.  `d'
+     is advanced into the following input string whenever necessary, but
+     this happens before fetching; therefore, at the beginning of the
+     loop, `d' can be pointing at the end of a string, but it cannot
+     equal `string2'.  */
+  if (size1 > 0 && pos <= size1)
+    {
+      d = string1 + pos;
+      dend = end_match_1;
+    }
+  else
+    {
+      d = string2 + pos - size1;
+      dend = end_match_2;
+    }
+
+  DEBUG_PRINT1 ("The compiled pattern is: ");
+  DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend);
+  DEBUG_PRINT1 ("The string to match is: `");
+  DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2);
+  DEBUG_PRINT1 ("'\n");
+
+  /* This loops over pattern commands.  It exits by returning from the
+     function if the match is complete, or it drops through if the match
+     fails at this starting point in the input data.  */
+  for (;;)
+    {
+      DEBUG_PRINT2 ("\n0x%x: ", p);
+
+      if (p == pend)
+       { /* End of pattern means we might have succeeded.  */
+         DEBUG_PRINT1 ("end of pattern ... ");
+
+         /* If we haven't matched the entire string, and we want the
+            longest match, try backtracking.  */
+         if (d != end_match_2)
+           {
+             DEBUG_PRINT1 ("backtracking.\n");
+
+             if (!FAIL_STACK_EMPTY ())
+               { /* More failure points to try.  */
+                 boolean same_str_p = (FIRST_STRING_P (match_end)
+                                       == MATCHING_IN_FIRST_STRING);
+
+                 /* If exceeds best match so far, save it.  */
+                 if (!best_regs_set
+                     || (same_str_p && d > match_end)
+                     || (!same_str_p && !MATCHING_IN_FIRST_STRING))
+                   {
+                     best_regs_set = true;
+                     match_end = d;
+
+                     DEBUG_PRINT1 ("\nSAVING match as best so far.\n");
+
+                     for (mcnt = 1; mcnt < num_regs; mcnt++)
+                       {
+                         best_regstart[mcnt] = regstart[mcnt];
+                         best_regend[mcnt] = regend[mcnt];
+                       }
+                   }
+                 goto fail;
+               }
+
+             /* If no failure points, don't restore garbage.  */
+             else if (best_regs_set)
+               {
+               restore_best_regs:
+                 /* Restore best match.  It may happen that `dend ==
+                    end_match_1' while the restored d is in string2.
+                    For example, the pattern `x.*y.*z' against the
+                    strings `x-' and `y-z-', if the two strings are
+                    not consecutive in memory.  */
+                 DEBUG_PRINT1 ("Restoring best registers.\n");
+
+                 d = match_end;
+                 dend = ((d >= string1 && d <= end1)
+                          ? end_match_1 : end_match_2);
+
+                 for (mcnt = 1; mcnt < num_regs; mcnt++)
+                   {
+                     regstart[mcnt] = best_regstart[mcnt];
+                     regend[mcnt] = best_regend[mcnt];
+                   }
+               }
+           } /* d != end_match_2 */
+
+         DEBUG_PRINT1 ("Accepting match.\n");
+
+         /* If caller wants register contents data back, do it.  */
+         if (regs && !bufp->no_sub)
+           {
+             /* Have the register data arrays been allocated?  */
+             if (bufp->regs_allocated == REGS_UNALLOCATED)
+               { /* No.  So allocate them with malloc.  We need one
+                    extra element beyond `num_regs' for the `-1' marker
+                    GNU code uses.  */
+                 regs->num_regs = MAX (RE_NREGS, num_regs + 1);
+                 regs->start = TALLOC (regs->num_regs, regoff_t);
+                 regs->end = TALLOC (regs->num_regs, regoff_t);
+                 if (regs->start == NULL || regs->end == NULL)
+                   return -2;
+                 bufp->regs_allocated = REGS_REALLOCATE;
+               }
+             else if (bufp->regs_allocated == REGS_REALLOCATE)
+               { /* Yes.  If we need more elements than were already
+                    allocated, reallocate them.  If we need fewer, just
+                    leave it alone.  */
+                 if (regs->num_regs < num_regs + 1)
+                   {
+                     regs->num_regs = num_regs + 1;
+                     RETALLOC (regs->start, regs->num_regs, regoff_t);
+                     RETALLOC (regs->end, regs->num_regs, regoff_t);
+                     if (regs->start == NULL || regs->end == NULL)
+                       return -2;
+                   }
+               }
+             else
+               assert (bufp->regs_allocated == REGS_FIXED);
+
+             /* Convert the pointer data in `regstart' and `regend' to
+                indices.  Register zero has to be set differently,
+                since we haven't kept track of any info for it.  */
+             if (regs->num_regs > 0)
+               {
+                 regs->start[0] = pos;
+                 regs->end[0] = (MATCHING_IN_FIRST_STRING ? d - string1
+                                 : d - string2 + size1);
+               }
+
+             /* Go through the first `min (num_regs, regs->num_regs)'
+                registers, since that is all we initialized.  */
+             for (mcnt = 1; mcnt < MIN (num_regs, regs->num_regs); mcnt++)
+               {
+                 if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt]))
+                   regs->start[mcnt] = regs->end[mcnt] = -1;
+                 else
+                   {
+                     regs->start[mcnt] = POINTER_TO_OFFSET (regstart[mcnt]);
+                     regs->end[mcnt] = POINTER_TO_OFFSET (regend[mcnt]);
+                   }
+               }
+
+             /* If the regs structure we return has more elements than
+                were in the pattern, set the extra elements to -1.  If
+                we (re)allocated the registers, this is the case,
+                because we always allocate enough to have at least one
+                -1 at the end.  */
+             for (mcnt = num_regs; mcnt < regs->num_regs; mcnt++)
+               regs->start[mcnt] = regs->end[mcnt] = -1;
+           } /* regs && !bufp->no_sub */
+
+         FREE_VARIABLES ();
+         DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n",
+                       nfailure_points_pushed, nfailure_points_popped,
+                       nfailure_points_pushed - nfailure_points_popped);
+         DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed);
+
+         mcnt = d - pos - (MATCHING_IN_FIRST_STRING
+                           ? string1
+                           : string2 - size1);
+
+         DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt);
+
+         return mcnt;
+       }
+
+      /* Otherwise match next pattern command.  */
+#ifdef SWITCH_ENUM_BUG
+      switch ((int) ((re_opcode_t) *p++))
+#else
+      switch ((re_opcode_t) *p++)
+#endif
+       {
+       /* Ignore these.  Used to ignore the n of succeed_n's which
+          currently have n == 0.  */
+       case no_op:
+         DEBUG_PRINT1 ("EXECUTING no_op.\n");
+         break;
+
+
+       /* Match the next n pattern characters exactly.  The following
+          byte in the pattern defines n, and the n bytes after that
+          are the characters to match.  */
+       case exactn:
+         mcnt = *p++;
+         DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt);
+
+         /* This is written out as an if-else so we don't waste time
+            testing `translate' inside the loop.  */
+         if (translate)
+           {
+             do
+               {
+                 PREFETCH ();
+                 if (translate[(unsigned char) *d++] != (char) *p++)
+                   goto fail;
+               }
+             while (--mcnt);
+           }
+         else
+           {
+             do
+               {
+                 PREFETCH ();
+                 if (*d++ != (char) *p++) goto fail;
+               }
+             while (--mcnt);
+           }
+         SET_REGS_MATCHED ();
+         break;
+
+
+       /* Match any character except possibly a newline or a null.  */
+       case anychar:
+         DEBUG_PRINT1 ("EXECUTING anychar.\n");
+
+         PREFETCH ();
+
+         if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n')
+             || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000'))
+           goto fail;
+
+         SET_REGS_MATCHED ();
+         DEBUG_PRINT2 ("  Matched `%d'.\n", *d);
+         d++;
+         break;
+
+
+       case charset:
+       case charset_not:
+         {
+           register unsigned char c;
+           boolean not = (re_opcode_t) *(p - 1) == charset_not;
+
+           DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : "");
+
+           PREFETCH ();
+           c = TRANSLATE (*d); /* The character to match.  */
+
+           /* Cast to `unsigned' instead of `unsigned char' in case the
+              bit list is a full 32 bytes long.  */
+           if (c < (unsigned) (*p * BYTEWIDTH)
+               && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
+             not = !not;
+
+           p += 1 + *p;
+
+           if (!not) goto fail;
+
+           SET_REGS_MATCHED ();
+           d++;
+           break;
+         }
+
+
+       /* The beginning of a group is represented by start_memory.
+          The arguments are the register number in the next byte, and the
+          number of groups inner to this one in the next.  The text
+          matched within the group is recorded (in the internal
+          registers data structure) under the register number.  */
+       case start_memory:
+         DEBUG_PRINT3 ("EXECUTING start_memory %d (%d):\n", *p, p[1]);
+
+         /* Find out if this group can match the empty string.  */
+         p1 = p;               /* To send to group_match_null_string_p.  */
+
+         if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE)
+           REG_MATCH_NULL_STRING_P (reg_info[*p])
+             = group_match_null_string_p (&p1, pend, reg_info);
+
+         /* Save the position in the string where we were the last time
+            we were at this open-group operator in case the group is
+            operated upon by a repetition operator, e.g., with `(a*)*b'
+            against `ab'; then we want to ignore where we are now in
+            the string in case this attempt to match fails.  */
+         old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
+                            ? REG_UNSET (regstart[*p]) ? d : regstart[*p]
+                            : regstart[*p];
+         DEBUG_PRINT2 ("  old_regstart: %d\n",
+                        POINTER_TO_OFFSET (old_regstart[*p]));
+
+         regstart[*p] = d;
+         DEBUG_PRINT2 ("  regstart: %d\n", POINTER_TO_OFFSET (regstart[*p]));
+
+         IS_ACTIVE (reg_info[*p]) = 1;
+         MATCHED_SOMETHING (reg_info[*p]) = 0;
+
+         /* This is the new highest active register.  */
+         highest_active_reg = *p;
+
+         /* If nothing was active before, this is the new lowest active
+            register.  */
+         if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
+           lowest_active_reg = *p;
+
+         /* Move past the register number and inner group count.  */
+         p += 2;
+         break;
+
+
+       /* The stop_memory opcode represents the end of a group.  Its
+          arguments are the same as start_memory's: the register
+          number, and the number of inner groups.  */
+       case stop_memory:
+         DEBUG_PRINT3 ("EXECUTING stop_memory %d (%d):\n", *p, p[1]);
+
+         /* We need to save the string position the last time we were at
+            this close-group operator in case the group is operated
+            upon by a repetition operator, e.g., with `((a*)*(b*)*)*'
+            against `aba'; then we want to ignore where we are now in
+            the string in case this attempt to match fails.  */
+         old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
+                          ? REG_UNSET (regend[*p]) ? d : regend[*p]
+                          : regend[*p];
+         DEBUG_PRINT2 ("      old_regend: %d\n",
+                        POINTER_TO_OFFSET (old_regend[*p]));
+
+         regend[*p] = d;
+         DEBUG_PRINT2 ("      regend: %d\n", POINTER_TO_OFFSET (regend[*p]));
+
+         /* This register isn't active anymore.  */
+         IS_ACTIVE (reg_info[*p]) = 0;
+
+         /* If this was the only register active, nothing is active
+            anymore.  */
+         if (lowest_active_reg == highest_active_reg)
+           {
+             lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+             highest_active_reg = NO_HIGHEST_ACTIVE_REG;
+           }
+         else
+           { /* We must scan for the new highest active register, since
+                it isn't necessarily one less than now: consider
+                (a(b)c(d(e)f)g).  When group 3 ends, after the f), the
+                new highest active register is 1.  */
+             unsigned char r = *p - 1;
+             while (r > 0 && !IS_ACTIVE (reg_info[r]))
+               r--;
+
+             /* If we end up at register zero, that means that we saved
+                the registers as the result of an `on_failure_jump', not
+                a `start_memory', and we jumped to past the innermost
+                `stop_memory'.  For example, in ((.)*) we save
+                registers 1 and 2 as a result of the *, but when we pop
+                back to the second ), we are at the stop_memory 1.
+                Thus, nothing is active.  */
+             if (r == 0)
+               {
+                 lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+                 highest_active_reg = NO_HIGHEST_ACTIVE_REG;
+               }
+             else
+               highest_active_reg = r;
+           }
+
+         /* If just failed to match something this time around with a
+            group that's operated on by a repetition operator, try to
+            force exit from the ``loop'', and restore the register
+            information for this group that we had before trying this
+            last match.  */
+         if ((!MATCHED_SOMETHING (reg_info[*p])
+              || (re_opcode_t) p[-3] == start_memory)
+             && (p + 2) < pend)
+           {
+             boolean is_a_jump_n = false;
+
+             p1 = p + 2;
+             mcnt = 0;
+             switch ((re_opcode_t) *p1++)
+               {
+                 case jump_n:
+                   is_a_jump_n = true;
+                 case pop_failure_jump:
+                 case maybe_pop_jump:
+                 case jump:
+                 case dummy_failure_jump:
+                   EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+                   if (is_a_jump_n)
+                     p1 += 2;
+                   break;
+
+                 default:
+                   /* do nothing */ ;
+               }
+             p1 += mcnt;
+
+             /* If the next operation is a jump backwards in the pattern
+                to an on_failure_jump right before the start_memory
+                corresponding to this stop_memory, exit from the loop
+                by forcing a failure after pushing on the stack the
+                on_failure_jump's jump in the pattern, and d.  */
+             if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump
+                 && (re_opcode_t) p1[3] == start_memory && p1[4] == *p)
+               {
+                 /* If this group ever matched anything, then restore
+                    what its registers were before trying this last
+                    failed match, e.g., with `(a*)*b' against `ab' for
+                    regstart[1], and, e.g., with `((a*)*(b*)*)*'
+                    against `aba' for regend[3].
+
+                    Also restore the registers for inner groups for,
+                    e.g., `((a*)(b*))*' against `aba' (register 3 would
+                    otherwise get trashed).  */
+
+                 if (EVER_MATCHED_SOMETHING (reg_info[*p]))
+                   {
+                     unsigned r;
+
+                     EVER_MATCHED_SOMETHING (reg_info[*p]) = 0;
+
+                     /* Restore this and inner groups' (if any) registers.  */
+                     for (r = *p; r < *p + *(p + 1); r++)
+                       {
+                         regstart[r] = old_regstart[r];
+
+                         /* xx why this test?  */
+                         if ((int) old_regend[r] >= (int) regstart[r])
+                           regend[r] = old_regend[r];
+                       }
+                   }
+                 p1++;
+                 EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+                 PUSH_FAILURE_POINT (p1 + mcnt, d, -2);
+
+                 goto fail;
+               }
+           }
+
+         /* Move past the register number and the inner group count.  */
+         p += 2;
+         break;
+
+
+       /* \<digit> has been turned into a `duplicate' command which is
+          followed by the numeric value of <digit> as the register number.  */
+       case duplicate:
+         {
+           register const char *d2, *dend2;
+           int regno = *p++;   /* Get which register to match against.  */
+           DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno);
+
+           /* Can't back reference a group which we've never matched.  */
+           if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno]))
+             goto fail;
+
+           /* Where in input to try to start matching.  */
+           d2 = regstart[regno];
+
+           /* Where to stop matching; if both the place to start and
+              the place to stop matching are in the same string, then
+              set to the place to stop, otherwise, for now have to use
+              the end of the first string.  */
+
+           dend2 = ((FIRST_STRING_P (regstart[regno])
+                     == FIRST_STRING_P (regend[regno]))
+                    ? regend[regno] : end_match_1);
+           for (;;)
+             {
+               /* If necessary, advance to next segment in register
+                  contents.  */
+               while (d2 == dend2)
+                 {
+                   if (dend2 == end_match_2) break;
+                   if (dend2 == regend[regno]) break;
+
+                   /* End of string1 => advance to string2. */
+                   d2 = string2;
+                   dend2 = regend[regno];
+                 }
+               /* At end of register contents => success */
+               if (d2 == dend2) break;
+
+               /* If necessary, advance to next segment in data.  */
+               PREFETCH ();
+
+               /* How many characters left in this segment to match.  */
+               mcnt = dend - d;
+
+               /* Want how many consecutive characters we can match in
+                  one shot, so, if necessary, adjust the count.  */
+               if (mcnt > dend2 - d2)
+                 mcnt = dend2 - d2;
+
+               /* Compare that many; failure if mismatch, else move
+                  past them.  */
+               if (translate
+                   ? bcmp_translate (d, d2, mcnt, translate)
+                   : bcmp (d, d2, mcnt))
+                 goto fail;
+               d += mcnt, d2 += mcnt;
+             }
+         }
+         break;
+
+
+       /* begline matches the empty string at the beginning of the string
+          (unless `not_bol' is set in `bufp'), and, if
+          `newline_anchor' is set, after newlines.  */
+       case begline:
+         DEBUG_PRINT1 ("EXECUTING begline.\n");
+
+         if (AT_STRINGS_BEG (d))
+           {
+             if (!bufp->not_bol) break;
+           }
+         else if (d[-1] == '\n' && bufp->newline_anchor)
+           {
+             break;
+           }
+         /* In all other cases, we fail.  */
+         goto fail;
+
+
+       /* endline is the dual of begline.  */
+       case endline:
+         DEBUG_PRINT1 ("EXECUTING endline.\n");
+
+         if (AT_STRINGS_END (d))
+           {
+             if (!bufp->not_eol) break;
+           }
+
+         /* We have to ``prefetch'' the next character.  */
+         else if ((d == end1 ? *string2 : *d) == '\n'
+                  && bufp->newline_anchor)
+           {
+             break;
+           }
+         goto fail;
+
+
+       /* Match at the very beginning of the data.  */
+       case begbuf:
+         DEBUG_PRINT1 ("EXECUTING begbuf.\n");
+         if (AT_STRINGS_BEG (d))
+           break;
+         goto fail;
+
+
+       /* Match at the very end of the data.  */
+       case endbuf:
+         DEBUG_PRINT1 ("EXECUTING endbuf.\n");
+         if (AT_STRINGS_END (d))
+           break;
+         goto fail;
+
+
+       /* on_failure_keep_string_jump is used to optimize `.*\n'.  It
+          pushes NULL as the value for the string on the stack.  Then
+          `pop_failure_point' will keep the current value for the
+          string, instead of restoring it.  To see why, consider
+          matching `foo\nbar' against `.*\n'.  The .* matches the foo;
+          then the . fails against the \n.  But the next thing we want
+          to do is match the \n against the \n; if we restored the
+          string value, we would be back at the foo.
+
+          Because this is used only in specific cases, we don't need to
+          check all the things that `on_failure_jump' does, to make
+          sure the right things get saved on the stack.  Hence we don't
+          share its code.  The only reason to push anything on the
+          stack at all is that otherwise we would have to change
+          `anychar's code to do something besides goto fail in this
+          case; that seems worse than this.  */
+       case on_failure_keep_string_jump:
+         DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump");
+
+         EXTRACT_NUMBER_AND_INCR (mcnt, p);
+         DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt);
+
+         PUSH_FAILURE_POINT (p + mcnt, NULL, -2);
+         break;
+
+
+       /* Uses of on_failure_jump:
+
+          Each alternative starts with an on_failure_jump that points
+          to the beginning of the next alternative.  Each alternative
+          except the last ends with a jump that in effect jumps past
+          the rest of the alternatives.  (They really jump to the
+          ending jump of the following alternative, because tensioning
+          these jumps is a hassle.)
+
+          Repeats start with an on_failure_jump that points past both
+          the repetition text and either the following jump or
+          pop_failure_jump back to this on_failure_jump.  */
+       case on_failure_jump:
+       on_failure:
+         DEBUG_PRINT1 ("EXECUTING on_failure_jump");
+
+         EXTRACT_NUMBER_AND_INCR (mcnt, p);
+         DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt);
+
+         /* If this on_failure_jump comes right before a group (i.e.,
+            the original * applied to a group), save the information
+            for that group and all inner ones, so that if we fail back
+            to this point, the group's information will be correct.
+            For example, in \(a*\)*\1, we need the preceding group,
+            and in \(\(a*\)b*\)\2, we need the inner group.  */
+
+         /* We can't use `p' to check ahead because we push
+            a failure point to `p + mcnt' after we do this.  */
+         p1 = p;
+
+         /* We need to skip no_op's before we look for the
+            start_memory in case this on_failure_jump is happening as
+            the result of a completed succeed_n, as in \(a\)\{1,3\}b\1
+            against aba.  */
+         while (p1 < pend && (re_opcode_t) *p1 == no_op)
+           p1++;
+
+         if (p1 < pend && (re_opcode_t) *p1 == start_memory)
+           {
+             /* We have a new highest active register now.  This will
+                get reset at the start_memory we are about to get to,
+                but we will have saved all the registers relevant to
+                this repetition op, as described above.  */
+             highest_active_reg = *(p1 + 1) + *(p1 + 2);
+             if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
+               lowest_active_reg = *(p1 + 1);
+           }
+
+         DEBUG_PRINT1 (":\n");
+         PUSH_FAILURE_POINT (p + mcnt, d, -2);
+         break;
+
+
+       /* A smart repeat ends with `maybe_pop_jump'.
+          We change it to either `pop_failure_jump' or `jump'.  */
+       case maybe_pop_jump:
+         EXTRACT_NUMBER_AND_INCR (mcnt, p);
+         DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt);
+         {
+           register unsigned char *p2 = p;
+
+           /* Compare the beginning of the repeat with what in the
+              pattern follows its end. If we can establish that there
+              is nothing that they would both match, i.e., that we
+              would have to backtrack because of (as in, e.g., `a*a')
+              then we can change to pop_failure_jump, because we'll
+              never have to backtrack.
+
+              This is not true in the case of alternatives: in
+              `(a|ab)*' we do need to backtrack to the `ab' alternative
+              (e.g., if the string was `ab').  But instead of trying to
+              detect that here, the alternative has put on a dummy
+              failure point which is what we will end up popping.  */
+
+           /* Skip over open/close-group commands.  */
+           while (p2 + 2 < pend
+                  && ((re_opcode_t) *p2 == stop_memory
+                      || (re_opcode_t) *p2 == start_memory))
+             p2 += 3;                  /* Skip over args, too.  */
+
+           /* If we're at the end of the pattern, we can change.  */
+           if (p2 == pend)
+             {
+               /* Consider what happens when matching ":\(.*\)"
+                  against ":/".  I don't really understand this code
+                  yet.  */
+               p[-3] = (unsigned char) pop_failure_jump;
+               DEBUG_PRINT1
+                 ("  End of pattern: change to `pop_failure_jump'.\n");
+             }
+
+           else if ((re_opcode_t) *p2 == exactn
+                    || (bufp->newline_anchor && (re_opcode_t) *p2 == endline))
+             {
+               register unsigned char c
+                 = *p2 == (unsigned char) endline ? '\n' : p2[2];
+               p1 = p + mcnt;
+
+               /* p1[0] ... p1[2] are the `on_failure_jump' corresponding
+                  to the `maybe_finalize_jump' of this case.  Examine what
+                  follows.  */
+               if ((re_opcode_t) p1[3] == exactn && p1[5] != c)
+                 {
+                   p[-3] = (unsigned char) pop_failure_jump;
+                   DEBUG_PRINT3 ("  %c != %c => pop_failure_jump.\n",
+                                 c, p1[5]);
+                 }
+
+               else if ((re_opcode_t) p1[3] == charset
+                        || (re_opcode_t) p1[3] == charset_not)
+                 {
+                   int not = (re_opcode_t) p1[3] == charset_not;
+
+                   if (c < (unsigned char) (p1[4] * BYTEWIDTH)
+                       && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
+                     not = !not;
+
+                   /* `not' is equal to 1 if c would match, which means
+                       that we can't change to pop_failure_jump.  */
+                   if (!not)
+                     {
+                       p[-3] = (unsigned char) pop_failure_jump;
+                       DEBUG_PRINT1 ("  No match => pop_failure_jump.\n");
+                     }
+                 }
+             }
+         }
+         p -= 2;               /* Point at relative address again.  */
+         if ((re_opcode_t) p[-1] != pop_failure_jump)
+           {
+             p[-1] = (unsigned char) jump;
+             DEBUG_PRINT1 ("  Match => jump.\n");
+             goto unconditional_jump;
+           }
+       /* Note fall through.  */
+
+
+       /* The end of a simple repeat has a pop_failure_jump back to
+          its matching on_failure_jump, where the latter will push a
+          failure point.  The pop_failure_jump takes off failure
+          points put on by this pop_failure_jump's matching
+          on_failure_jump; we got through the pattern to here from the
+          matching on_failure_jump, so didn't fail.  */
+       case pop_failure_jump:
+         {
+           /* We need to pass separate storage for the lowest and
+              highest registers, even though we don't care about the
+              actual values.  Otherwise, we will restore only one
+              register from the stack, since lowest will == highest in
+              `pop_failure_point'.  */
+           unsigned dummy_low_reg, dummy_high_reg;
+           unsigned char *pdummy;
+           const char *sdummy;
+
+           DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n");
+           POP_FAILURE_POINT (sdummy, pdummy,
+                              dummy_low_reg, dummy_high_reg,
+                              reg_dummy, reg_dummy, reg_info_dummy);
+         }
+         /* Note fall through.  */
+
+
+       /* Unconditionally jump (without popping any failure points).  */
+       case jump:
+       unconditional_jump:
+         EXTRACT_NUMBER_AND_INCR (mcnt, p);    /* Get the amount to jump.  */
+         DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt);
+         p += mcnt;                            /* Do the jump.  */
+         DEBUG_PRINT2 ("(to 0x%x).\n", p);
+         break;
+
+
+       /* We need this opcode so we can detect where alternatives end
+          in `group_match_null_string_p' et al.  */
+       case jump_past_alt:
+         DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n");
+         goto unconditional_jump;
+
+
+       /* Normally, the on_failure_jump pushes a failure point, which
+          then gets popped at pop_failure_jump.  We will end up at
+          pop_failure_jump, also, and with a pattern of, say, `a+', we
+          are skipping over the on_failure_jump, so we have to push
+          something meaningless for pop_failure_jump to pop.  */
+       case dummy_failure_jump:
+         DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n");
+         /* It doesn't matter what we push for the string here.  What
+            the code at `fail' tests is the value for the pattern.  */
+         PUSH_FAILURE_POINT (0, 0, -2);
+         goto unconditional_jump;
+
+
+       /* At the end of an alternative, we need to push a dummy failure
+          point in case we are followed by a `pop_failure_jump', because
+          we don't want the failure point for the alternative to be
+          popped.  For example, matching `(a|ab)*' against `aab'
+          requires that we match the `ab' alternative.  */
+       case push_dummy_failure:
+         DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n");
+         /* See comments just above at `dummy_failure_jump' about the
+            two zeroes.  */
+         PUSH_FAILURE_POINT (0, 0, -2);
+         break;
+
+       /* Have to succeed matching what follows at least n times.
+          After that, handle like `on_failure_jump'.  */
+       case succeed_n:
+         EXTRACT_NUMBER (mcnt, p + 2);
+         DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt);
+
+         assert (mcnt >= 0);
+         /* Originally, this is how many times we HAVE to succeed.  */
+         if (mcnt > 0)
+           {
+              mcnt--;
+              p += 2;
+              STORE_NUMBER_AND_INCR (p, mcnt);
+              DEBUG_PRINT3 ("  Setting 0x%x to %d.\n", p, mcnt);
+           }
+         else if (mcnt == 0)
+           {
+             DEBUG_PRINT2 ("  Setting two bytes from 0x%x to no_op.\n", p+2);
+             p[2] = (unsigned char) no_op;
+             p[3] = (unsigned char) no_op;
+             goto on_failure;
+           }
+         break;
+
+       case jump_n:
+         EXTRACT_NUMBER (mcnt, p + 2);
+         DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt);
+
+         /* Originally, this is how many times we CAN jump.  */
+         if (mcnt)
+           {
+              mcnt--;
+              STORE_NUMBER (p + 2, mcnt);
+              goto unconditional_jump;
+           }
+         /* If don't have to jump any more, skip over the rest of command.  */
+         else
+           p += 4;
+         break;
+
+       case set_number_at:
+         {
+           DEBUG_PRINT1 ("EXECUTING set_number_at.\n");
+
+           EXTRACT_NUMBER_AND_INCR (mcnt, p);
+           p1 = p + mcnt;
+           EXTRACT_NUMBER_AND_INCR (mcnt, p);
+           DEBUG_PRINT3 ("  Setting 0x%x to %d.\n", p1, mcnt);
+           STORE_NUMBER (p1, mcnt);
+           break;
+         }
+
+       case wordbound:
+         DEBUG_PRINT1 ("EXECUTING wordbound.\n");
+         if (AT_WORD_BOUNDARY (d))
+           break;
+         goto fail;
+
+       case notwordbound:
+         DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
+         if (AT_WORD_BOUNDARY (d))
+           goto fail;
+         break;
+
+       case wordbeg:
+         DEBUG_PRINT1 ("EXECUTING wordbeg.\n");
+         if (WORDCHAR_P (d) && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1)))
+           break;
+         goto fail;
+
+       case wordend:
+         DEBUG_PRINT1 ("EXECUTING wordend.\n");
+         if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1)
+             && (!WORDCHAR_P (d) || AT_STRINGS_END (d)))
+           break;
+         goto fail;
+
+#ifdef emacs
+#ifdef emacs19
+       case before_dot:
+         DEBUG_PRINT1 ("EXECUTING before_dot.\n");
+         if (PTR_CHAR_POS ((unsigned char *) d) >= point)
+           goto fail;
+         break;
+
+       case at_dot:
+         DEBUG_PRINT1 ("EXECUTING at_dot.\n");
+         if (PTR_CHAR_POS ((unsigned char *) d) != point)
+           goto fail;
+         break;
+
+       case after_dot:
+         DEBUG_PRINT1 ("EXECUTING after_dot.\n");
+         if (PTR_CHAR_POS ((unsigned char *) d) <= point)
+           goto fail;
+         break;
+#else /* not emacs19 */
+       case at_dot:
+         DEBUG_PRINT1 ("EXECUTING at_dot.\n");
+         if (PTR_CHAR_POS ((unsigned char *) d) + 1 != point)
+           goto fail;
+         break;
+#endif /* not emacs19 */
+
+       case syntaxspec:
+         DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt);
+         mcnt = *p++;
+         goto matchsyntax;
+
+       case wordchar:
+         DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n");
+         mcnt = (int) Sword;
+       matchsyntax:
+         PREFETCH ();
+         if (SYNTAX (*d++) != (enum syntaxcode) mcnt)
+           goto fail;
+         SET_REGS_MATCHED ();
+         break;
+
+       case notsyntaxspec:
+         DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt);
+         mcnt = *p++;
+         goto matchnotsyntax;
+
+       case notwordchar:
+         DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n");
+         mcnt = (int) Sword;
+       matchnotsyntax:
+         PREFETCH ();
+         if (SYNTAX (*d++) == (enum syntaxcode) mcnt)
+           goto fail;
+         SET_REGS_MATCHED ();
+         break;
+
+#else /* not emacs */
+       case wordchar:
+         DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n");
+         PREFETCH ();
+         if (!WORDCHAR_P (d))
+           goto fail;
+         SET_REGS_MATCHED ();
+         d++;
+         break;
+
+       case notwordchar:
+         DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n");
+         PREFETCH ();
+         if (WORDCHAR_P (d))
+           goto fail;
+         SET_REGS_MATCHED ();
+         d++;
+         break;
+#endif /* not emacs */
+
+       default:
+         abort ();
+       }
+      continue;  /* Successfully executed one pattern command; keep going.  */
+
+
+    /* We goto here if a matching operation fails. */
+    fail:
+      if (!FAIL_STACK_EMPTY ())
+       { /* A restart point is known.  Restore to that state.  */
+         DEBUG_PRINT1 ("\nFAIL:\n");
+         POP_FAILURE_POINT (d, p,
+                            lowest_active_reg, highest_active_reg,
+                            regstart, regend, reg_info);
+
+         /* If this failure point is a dummy, try the next one.  */
+         if (!p)
+           goto fail;
+
+         /* If we failed to the end of the pattern, don't examine *p.  */
+         assert (p <= pend);
+         if (p < pend)
+           {
+             boolean is_a_jump_n = false;
+
+             /* If failed to a backwards jump that's part of a repetition
+                loop, need to pop this failure point and use the next one.  */
+             switch ((re_opcode_t) *p)
+               {
+               case jump_n:
+                 is_a_jump_n = true;
+               case maybe_pop_jump:
+               case pop_failure_jump:
+               case jump:
+                 p1 = p + 1;
+                 EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+                 p1 += mcnt;
+
+                 if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n)
+                     || (!is_a_jump_n
+                         && (re_opcode_t) *p1 == on_failure_jump))
+                   goto fail;
+                 break;
+               default:
+                 /* do nothing */ ;
+               }
+           }
+
+         if (d >= string1 && d <= end1)
+           dend = end_match_1;
+       }
+      else
+       break;   /* Matching at this starting point really fails.  */
+    } /* for (;;) */
+
+  if (best_regs_set)
+    goto restore_best_regs;
+
+  FREE_VARIABLES ();
+
+  return -1;                           /* Failure to match.  */
+} /* re_match_2 */
+\f
+/* Subroutine definitions for re_match_2.  */
+
+
+/* We are passed P pointing to a register number after a start_memory.
+
+   Return true if the pattern up to the corresponding stop_memory can
+   match the empty string, and false otherwise.
+
+   If we find the matching stop_memory, sets P to point to one past its number.
+   Otherwise, sets P to an undefined byte less than or equal to END.
+
+   We don't handle duplicates properly (yet).  */
+
+static boolean
+group_match_null_string_p (p, end, reg_info)
+    unsigned char **p, *end;
+    register_info_type *reg_info;
+{
+  int mcnt;
+  /* Point to after the args to the start_memory.  */
+  unsigned char *p1 = *p + 2;
+
+  while (p1 < end)
+    {
+      /* Skip over opcodes that can match nothing, and return true or
+        false, as appropriate, when we get to one that can't, or to the
+        matching stop_memory.  */
+
+      switch ((re_opcode_t) *p1)
+       {
+       /* Could be either a loop or a series of alternatives.  */
+       case on_failure_jump:
+         p1++;
+         EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+
+         /* If the next operation is not a jump backwards in the
+            pattern.  */
+
+         if (mcnt >= 0)
+           {
+             /* Go through the on_failure_jumps of the alternatives,
+                seeing if any of the alternatives cannot match nothing.
+                The last alternative starts with only a jump,
+                whereas the rest start with on_failure_jump and end
+                with a jump, e.g., here is the pattern for `a|b|c':
+
+                /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6
+                /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3
+                /exactn/1/c
+
+                So, we have to first go through the first (n-1)
+                alternatives and then deal with the last one separately.  */
+
+
+             /* Deal with the first (n-1) alternatives, which start
+                with an on_failure_jump (see above) that jumps to right
+                past a jump_past_alt.  */
+
+             while ((re_opcode_t) p1[mcnt-3] == jump_past_alt)
+               {
+                 /* `mcnt' holds how many bytes long the alternative
+                    is, including the ending `jump_past_alt' and
+                    its number.  */
+
+                 if (!alt_match_null_string_p (p1, p1 + mcnt - 3,
+                                                     reg_info))
+                   return false;
+
+                 /* Move to right after this alternative, including the
+                    jump_past_alt.  */
+                 p1 += mcnt;
+
+                 /* Break if it's the beginning of an n-th alternative
+                    that doesn't begin with an on_failure_jump.  */
+                 if ((re_opcode_t) *p1 != on_failure_jump)
+                   break;
+
+                 /* Still have to check that it's not an n-th
+                    alternative that starts with an on_failure_jump.  */
+                 p1++;
+                 EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+                 if ((re_opcode_t) p1[mcnt-3] != jump_past_alt)
+                   {
+                     /* Get to the beginning of the n-th alternative.  */
+                     p1 -= 3;
+                     break;
+                   }
+               }
+
+             /* Deal with the last alternative: go back and get number
+                of the `jump_past_alt' just before it.  `mcnt' contains
+                the length of the alternative.  */
+             EXTRACT_NUMBER (mcnt, p1 - 2);
+
+             if (!alt_match_null_string_p (p1, p1 + mcnt, reg_info))
+               return false;
+
+             p1 += mcnt;       /* Get past the n-th alternative.  */
+           } /* if mcnt > 0 */
+         break;
+
+
+       case stop_memory:
+         assert (p1[1] == **p);
+         *p = p1 + 2;
+         return true;
+
+
+       default:
+         if (!common_op_match_null_string_p (&p1, end, reg_info))
+           return false;
+       }
+    } /* while p1 < end */
+
+  return false;
+} /* group_match_null_string_p */
+
+
+/* Similar to group_match_null_string_p, but doesn't deal with alternatives:
+   It expects P to be the first byte of a single alternative and END one
+   byte past the last. The alternative can contain groups.  */
+
+static boolean
+alt_match_null_string_p (p, end, reg_info)
+    unsigned char *p, *end;
+    register_info_type *reg_info;
+{
+  int mcnt;
+  unsigned char *p1 = p;
+
+  while (p1 < end)
+    {
+      /* Skip over opcodes that can match nothing, and break when we get
+        to one that can't.  */
+
+      switch ((re_opcode_t) *p1)
+       {
+       /* It's a loop.  */
+       case on_failure_jump:
+         p1++;
+         EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+         p1 += mcnt;
+         break;
+
+       default:
+         if (!common_op_match_null_string_p (&p1, end, reg_info))
+           return false;
+       }
+    }  /* while p1 < end */
+
+  return true;
+} /* alt_match_null_string_p */
+
+
+/* Deals with the ops common to group_match_null_string_p and
+   alt_match_null_string_p.
+
+   Sets P to one after the op and its arguments, if any.  */
+
+static boolean
+common_op_match_null_string_p (p, end, reg_info)
+    unsigned char **p, *end;
+    register_info_type *reg_info;
+{
+  int mcnt;
+  boolean ret;
+  int reg_no;
+  unsigned char *p1 = *p;
+
+  switch ((re_opcode_t) *p1++)
+    {
+    case no_op:
+    case begline:
+    case endline:
+    case begbuf:
+    case endbuf:
+    case wordbeg:
+    case wordend:
+    case wordbound:
+    case notwordbound:
+#ifdef emacs
+    case before_dot:
+    case at_dot:
+    case after_dot:
+#endif
+      break;
+
+    case start_memory:
+      reg_no = *p1;
+      assert (reg_no > 0 && reg_no <= MAX_REGNUM);
+      ret = group_match_null_string_p (&p1, end, reg_info);
+
+      /* Have to set this here in case we're checking a group which
+        contains a group and a back reference to it.  */
+
+      if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE)
+       REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret;
+
+      if (!ret)
+       return false;
+      break;
+
+    /* If this is an optimized succeed_n for zero times, make the jump.  */
+    case jump:
+      EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+      if (mcnt >= 0)
+       p1 += mcnt;
+      else
+       return false;
+      break;
+
+    case succeed_n:
+      /* Get to the number of times to succeed.  */
+      p1 += 2;
+      EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+
+      if (mcnt == 0)
+       {
+         p1 -= 4;
+         EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+         p1 += mcnt;
+       }
+      else
+       return false;
+      break;
+
+    case duplicate:
+      if (!REG_MATCH_NULL_STRING_P (reg_info[*p1]))
+       return false;
+      break;
+
+    case set_number_at:
+      p1 += 4;
+
+    default:
+      /* All other opcodes mean we cannot match the empty string.  */
+      return false;
+  }
+
+  *p = p1;
+  return true;
+} /* common_op_match_null_string_p */
+
+
+/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN
+   bytes; nonzero otherwise.  */
+
+static int
+bcmp_translate(
+     unsigned char *s1,
+     unsigned char *s2,
+     int len,
+     char *translate
+)
+{
+  register unsigned char *p1 = s1, *p2 = s2;
+  while (len)
+    {
+      if (translate[*p1++] != translate[*p2++]) return 1;
+      len--;
+    }
+  return 0;
+}
+\f
+/* Entry points for GNU code.  */
+
+/* re_compile_pattern is the GNU regular expression compiler: it
+   compiles PATTERN (of length SIZE) and puts the result in BUFP.
+   Returns 0 if the pattern was valid, otherwise an error string.
+
+   Assumes the `allocated' (and perhaps `buffer') and `translate' fields
+   are set in BUFP on entry.
+
+   We call regex_compile to do the actual compilation.  */
+
+const char *
+re_compile_pattern (pattern, length, bufp)
+     const char *pattern;
+     int length;
+     struct re_pattern_buffer *bufp;
+{
+  reg_errcode_t ret;
+
+  /* GNU code is written to assume at least RE_NREGS registers will be set
+     (and at least one extra will be -1).  */
+  bufp->regs_allocated = REGS_UNALLOCATED;
+
+  /* And GNU code determines whether or not to get register information
+     by passing null for the REGS argument to re_match, etc., not by
+     setting no_sub.  */
+  bufp->no_sub = 0;
+
+  /* Match anchors at newline.  */
+  bufp->newline_anchor = 1;
+
+  ret = regex_compile (pattern, length, re_syntax_options, bufp);
+
+  return re_error_msg[(int) ret];
+}
+\f
+/* Entry points compatible with 4.2 BSD regex library.  We don't define
+   them if this is an Emacs or POSIX compilation.  */
+
+#if !defined (emacs) && !defined (_POSIX_SOURCE)
+
+/* BSD has one and only one pattern buffer.  */
+static struct re_pattern_buffer re_comp_buf;
+
+char *
+re_comp (s)
+    const char *s;
+{
+  reg_errcode_t ret;
+
+  if (!s)
+    {
+      if (!re_comp_buf.buffer)
+       return "No previous regular expression";
+      return 0;
+    }
+
+  if (!re_comp_buf.buffer)
+    {
+      re_comp_buf.buffer = (unsigned char *) malloc (200);
+      if (re_comp_buf.buffer == NULL)
+       return "Memory exhausted";
+      re_comp_buf.allocated = 200;
+
+      re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH);
+      if (re_comp_buf.fastmap == NULL)
+       return "Memory exhausted";
+    }
+
+  /* Since `re_exec' always passes NULL for the `regs' argument, we
+     don't need to initialize the pattern buffer fields which affect it.  */
+
+  /* Match anchors at newlines.  */
+  re_comp_buf.newline_anchor = 1;
+
+  ret = regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf);
+
+  /* Yes, we're discarding `const' here.  */
+  return (char *) re_error_msg[(int) ret];
+}
+
+
+int
+re_exec (s)
+    const char *s;
+{
+  const int len = strlen (s);
+  return
+    0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0);
+}
+#endif /* not emacs and not _POSIX_SOURCE */
+\f
+/* POSIX.2 functions.  Don't define these for Emacs.  */
+
+#ifndef emacs
+
+/* regcomp takes a regular expression as a string and compiles it.
+
+   PREG is a regex_t *.  We do not expect any fields to be initialized,
+   since POSIX says we shouldn't.  Thus, we set
+
+     `buffer' to the compiled pattern;
+     `used' to the length of the compiled pattern;
+     `syntax' to RE_SYNTAX_POSIX_EXTENDED if the
+       REG_EXTENDED bit in CFLAGS is set; otherwise, to
+       RE_SYNTAX_POSIX_BASIC;
+     `newline_anchor' to REG_NEWLINE being set in CFLAGS;
+     `fastmap' and `fastmap_accurate' to zero;
+     `re_nsub' to the number of subexpressions in PATTERN.
+
+   PATTERN is the address of the pattern string.
+
+   CFLAGS is a series of bits which affect compilation.
+
+     If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we
+     use POSIX basic syntax.
+
+     If REG_NEWLINE is set, then . and [^...] don't match newline.
+     Also, regexec will try a match beginning after every newline.
+
+     If REG_ICASE is set, then we considers upper- and lowercase
+     versions of letters to be equivalent when matching.
+
+     If REG_NOSUB is set, then when PREG is passed to regexec, that
+     routine will report only success or failure, and nothing about the
+     registers.
+
+   It returns 0 if it succeeds, nonzero if it doesn't.  (See regex.h for
+   the return codes and their meanings.)  */
+
+int
+regcomp (preg, pattern, cflags)
+    regex_t *preg;
+    const char *pattern;
+    int cflags;
+{
+  reg_errcode_t ret;
+  unsigned syntax
+    = (cflags & REG_EXTENDED) ?
+      RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC;
+
+  /* regex_compile will allocate the space for the compiled pattern.  */
+  preg->buffer = 0;
+  preg->allocated = 0;
+
+  /* Don't bother to use a fastmap when searching.  This simplifies the
+     REG_NEWLINE case: if we used a fastmap, we'd have to put all the
+     characters after newlines into the fastmap.  This way, we just try
+     every character.  */
+  preg->fastmap = 0;
+
+  if (cflags & REG_ICASE)
+    {
+      unsigned i;
+
+      preg->translate = (char *) malloc (CHAR_SET_SIZE);
+      if (preg->translate == NULL)
+       return (int) REG_ESPACE;
+
+      /* Map uppercase characters to corresponding lowercase ones.  */
+      for (i = 0; i < CHAR_SET_SIZE; i++)
+       preg->translate[i] = ISUPPER (i) ? tolower (i) : i;
+    }
+  else
+    preg->translate = NULL;
+
+  /* If REG_NEWLINE is set, newlines are treated differently.  */
+  if (cflags & REG_NEWLINE)
+    { /* REG_NEWLINE implies neither . nor [^...] match newline.  */
+      syntax &= ~RE_DOT_NEWLINE;
+      syntax |= RE_HAT_LISTS_NOT_NEWLINE;
+      /* It also changes the matching behavior.  */
+      preg->newline_anchor = 1;
+    }
+  else
+    preg->newline_anchor = 0;
+
+  preg->no_sub = !!(cflags & REG_NOSUB);
+
+  /* POSIX says a null character in the pattern terminates it, so we
+     can use strlen here in compiling the pattern.  */
+  ret = regex_compile (pattern, strlen (pattern), syntax, preg);
+
+  /* POSIX doesn't distinguish between an unmatched open-group and an
+     unmatched close-group: both are REG_EPAREN.  */
+  if (ret == REG_ERPAREN) ret = REG_EPAREN;
+
+  return (int) ret;
+}
+
+
+/* regexec searches for a given pattern, specified by PREG, in the
+   string STRING.
+
+   If NMATCH is zero or REG_NOSUB was set in the cflags argument to
+   `regcomp', we ignore PMATCH.  Otherwise, we assume PMATCH has at
+   least NMATCH elements, and we set them to the offsets of the
+   corresponding matched substrings.
+
+   EFLAGS specifies `execution flags' which affect matching: if
+   REG_NOTBOL is set, then ^ does not match at the beginning of the
+   string; if REG_NOTEOL is set, then $ does not match at the end.
+
+   We return 0 if we find a match and REG_NOMATCH if not.  */
+
+int
+regexec (preg, string, nmatch, pmatch, eflags)
+    const regex_t *preg;
+    const char *string;
+    size_t nmatch;
+    regmatch_t pmatch[];
+    int eflags;
+{
+  int ret;
+  struct re_registers regs;
+  regex_t private_preg;
+  int len = strlen (string);
+  boolean want_reg_info = !preg->no_sub && nmatch > 0;
+
+  private_preg = *preg;
+
+  private_preg.not_bol = !!(eflags & REG_NOTBOL);
+  private_preg.not_eol = !!(eflags & REG_NOTEOL);
+
+  /* The user has told us exactly how many registers to return
+     information about, via `nmatch'.  We have to pass that on to the
+     matching routines.  */
+  private_preg.regs_allocated = REGS_FIXED;
+
+  if (want_reg_info)
+    {
+      regs.num_regs = nmatch;
+      regs.start = TALLOC (nmatch, regoff_t);
+      regs.end = TALLOC (nmatch, regoff_t);
+      if (regs.start == NULL || regs.end == NULL)
+       return (int) REG_NOMATCH;
+    }
+
+  /* Perform the searching operation.  */
+  ret = re_search (&private_preg, string, len,
+                  /* start: */ 0, /* range: */ len,
+                  want_reg_info ? &regs : (struct re_registers *) 0);
+
+  /* Copy the register information to the POSIX structure.  */
+  if (want_reg_info)
+    {
+      if (ret >= 0)
+       {
+         unsigned r;
+
+         for (r = 0; r < nmatch; r++)
+           {
+             pmatch[r].rm_so = regs.start[r];
+             pmatch[r].rm_eo = regs.end[r];
+           }
+       }
+
+      /* If we needed the temporary register info, free the space now.  */
+      free (regs.start);
+      free (regs.end);
+    }
+
+  /* We want zero return to mean success, unlike `re_search'.  */
+  return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH;
+}
+
+
+/* Returns a message corresponding to an error code, ERRCODE, returned
+   from either regcomp or regexec.   We don't use PREG here.  */
+
+size_t
+regerror (errcode, preg, errbuf, errbuf_size)
+    int errcode;
+    const regex_t *preg;
+    char *errbuf;
+    size_t errbuf_size;
+{
+  const char *msg;
+  size_t msg_size;
+
+  if (errcode < 0
+      || errcode >= (sizeof (re_error_msg) / sizeof (re_error_msg[0])))
+    /* Only error codes returned by the rest of the code should be passed
+       to this routine.  If we are given anything else, or if other regex
+       code generates an invalid error code, then the program has a bug.
+       Dump core so we can fix it.  */
+    abort ();
+
+  msg = re_error_msg[errcode];
+
+  /* POSIX doesn't require that we do anything in this case, but why
+     not be nice.  */
+  if (! msg)
+    msg = "Success";
+
+  msg_size = strlen (msg) + 1; /* Includes the null.  */
+
+  if (errbuf_size != 0)
+    {
+      if (msg_size > errbuf_size)
+       {
+         strncpy (errbuf, msg, errbuf_size - 1);
+         errbuf[errbuf_size - 1] = 0;
+       }
+      else
+       strcpy (errbuf, msg);
+    }
+
+  return msg_size;
+}
+
+
+/* Free dynamically allocated space used by PREG.  */
+
+void
+regfree (preg)
+    regex_t *preg;
+{
+  if (preg->buffer != NULL)
+    free (preg->buffer);
+  preg->buffer = NULL;
+
+  preg->allocated = 0;
+  preg->used = 0;
+
+  if (preg->fastmap != NULL)
+    free (preg->fastmap);
+  preg->fastmap = NULL;
+  preg->fastmap_accurate = 0;
+
+  if (preg->translate != NULL)
+    free (preg->translate);
+  preg->translate = NULL;
+}
+
+#endif /* not emacs  */
+\f
+/*
+Local variables:
+make-backup-files: t
+version-control: t
+trim-versions-without-asking: nil
+End:
+*/
diff --git a/compat/regex.h b/compat/regex.h
new file mode 100644 (file)
index 0000000..6eb64f1
--- /dev/null
@@ -0,0 +1,490 @@
+/* Definitions for data structures and routines for the regular
+   expression library, version 0.12.
+
+   Copyright (C) 1985, 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifndef __REGEXP_LIBRARY_H__
+#define __REGEXP_LIBRARY_H__
+
+/* POSIX says that <sys/types.h> must be included (by the caller) before
+   <regex.h>.  */
+
+#ifdef VMS
+/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it
+   should be there.  */
+#include <stddef.h>
+#endif
+
+
+/* The following bits are used to determine the regexp syntax we
+   recognize.  The set/not-set meanings are chosen so that Emacs syntax
+   remains the value 0.  The bits are given in alphabetical order, and
+   the definitions shifted by one from the previous bit; thus, when we
+   add or remove a bit, only one other definition need change.  */
+typedef unsigned reg_syntax_t;
+
+/* If this bit is not set, then \ inside a bracket expression is literal.
+   If set, then such a \ quotes the following character.  */
+#define RE_BACKSLASH_ESCAPE_IN_LISTS (1)
+
+/* If this bit is not set, then + and ? are operators, and \+ and \? are
+     literals.
+   If set, then \+ and \? are operators and + and ? are literals.  */
+#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)
+
+/* If this bit is set, then character classes are supported.  They are:
+     [:alpha:], [:upper:], [:lower:],  [:digit:], [:alnum:], [:xdigit:],
+     [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
+   If not set, then character classes are not supported.  */
+#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
+
+/* If this bit is set, then ^ and $ are always anchors (outside bracket
+     expressions, of course).
+   If this bit is not set, then it depends:
+       ^  is an anchor if it is at the beginning of a regular
+          expression or after an open-group or an alternation operator;
+       $  is an anchor if it is at the end of a regular expression, or
+          before a close-group or an alternation operator.
+
+   This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because
+   POSIX draft 11.2 says that * etc. in leading positions is undefined.
+   We already implemented a previous draft which made those constructs
+   invalid, though, so we haven't changed the code back.  */
+#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
+
+/* If this bit is set, then special characters are always special
+     regardless of where they are in the pattern.
+   If this bit is not set, then special characters are special only in
+     some contexts; otherwise they are ordinary.  Specifically,
+     * + ? and intervals are only special when not after the beginning,
+     open-group, or alternation operator.  */
+#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
+
+/* If this bit is set, then *, +, ?, and { cannot be first in an re or
+     immediately after an alternation or begin-group operator.  */
+#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
+
+/* If this bit is set, then . matches newline.
+   If not set, then it doesn't.  */
+#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
+
+/* If this bit is set, then . doesn't match NUL.
+   If not set, then it does.  */
+#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
+
+/* If this bit is set, nonmatching lists [^...] do not match newline.
+   If not set, they do.  */
+#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)
+
+/* If this bit is set, either \{...\} or {...} defines an
+     interval, depending on RE_NO_BK_BRACES.
+   If not set, \{, \}, {, and } are literals.  */
+#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
+
+/* If this bit is set, +, ? and | aren't recognized as operators.
+   If not set, they are.  */
+#define RE_LIMITED_OPS (RE_INTERVALS << 1)
+
+/* If this bit is set, newline is an alternation operator.
+   If not set, newline is literal.  */
+#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
+
+/* If this bit is set, then `{...}' defines an interval, and \{ and \}
+     are literals.
+  If not set, then `\{...\}' defines an interval.  */
+#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
+
+/* If this bit is set, (...) defines a group, and \( and \) are literals.
+   If not set, \(...\) defines a group, and ( and ) are literals.  */
+#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
+
+/* If this bit is set, then \<digit> matches <digit>.
+   If not set, then \<digit> is a back-reference.  */
+#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
+
+/* If this bit is set, then | is an alternation operator, and \| is literal.
+   If not set, then \| is an alternation operator, and | is literal.  */
+#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
+
+/* If this bit is set, then an ending range point collating higher
+     than the starting range point, as in [z-a], is invalid.
+   If not set, then when ending range point collates higher than the
+     starting range point, the range is ignored.  */
+#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
+
+/* If this bit is set, then an unmatched ) is ordinary.
+   If not set, then an unmatched ) is invalid.  */
+#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
+
+/* This global variable defines the particular regexp syntax to use (for
+   some interfaces).  When a regexp is compiled, the syntax used is
+   stored in the pattern buffer, so changing this does not affect
+   already-compiled regexps.  */
+extern reg_syntax_t re_syntax_options;
+\f
+/* Define combinations of the above bits for the standard possibilities.
+   (The [[[ comments delimit what gets put into the Texinfo file, so
+   don't delete them!)  */
+/* [[[begin syntaxes]]] */
+#define RE_SYNTAX_EMACS 0
+
+#define RE_SYNTAX_AWK                                                  \
+  (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL                      \
+   | RE_NO_BK_PARENS            | RE_NO_BK_REFS                                \
+   | RE_NO_BK_VBAR               | RE_NO_EMPTY_RANGES                  \
+   | RE_UNMATCHED_RIGHT_PAREN_ORD)
+
+#define RE_SYNTAX_POSIX_AWK                                            \
+  (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS)
+
+#define RE_SYNTAX_GREP                                                 \
+  (RE_BK_PLUS_QM              | RE_CHAR_CLASSES                                \
+   | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS                           \
+   | RE_NEWLINE_ALT)
+
+#define RE_SYNTAX_EGREP                                                        \
+  (RE_CHAR_CLASSES        | RE_CONTEXT_INDEP_ANCHORS                   \
+   | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE                   \
+   | RE_NEWLINE_ALT       | RE_NO_BK_PARENS                            \
+   | RE_NO_BK_VBAR)
+
+#define RE_SYNTAX_POSIX_EGREP                                          \
+  (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES)
+
+/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff.  */
+#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
+
+#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
+
+/* Syntax bits common to both basic and extended POSIX regex syntax.  */
+#define _RE_SYNTAX_POSIX_COMMON                                                \
+  (RE_CHAR_CLASSES | RE_DOT_NEWLINE      | RE_DOT_NOT_NULL             \
+   | RE_INTERVALS  | RE_NO_EMPTY_RANGES)
+
+#define RE_SYNTAX_POSIX_BASIC                                          \
+  (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM)
+
+/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
+   RE_LIMITED_OPS, i.e., \? \+ \| are not recognized.  Actually, this
+   isn't minimal, since other operators, such as \`, aren't disabled.  */
+#define RE_SYNTAX_POSIX_MINIMAL_BASIC                                  \
+  (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)
+
+#define RE_SYNTAX_POSIX_EXTENDED                                       \
+  (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS                  \
+   | RE_CONTEXT_INDEP_OPS  | RE_NO_BK_BRACES                           \
+   | RE_NO_BK_PARENS       | RE_NO_BK_VBAR                             \
+   | RE_UNMATCHED_RIGHT_PAREN_ORD)
+
+/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INVALID_OPS
+   replaces RE_CONTEXT_INDEP_OPS and RE_NO_BK_REFS is added.  */
+#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED                               \
+  (_RE_SYNTAX_POSIX_COMMON  | RE_CONTEXT_INDEP_ANCHORS                 \
+   | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES                          \
+   | RE_NO_BK_PARENS        | RE_NO_BK_REFS                            \
+   | RE_NO_BK_VBAR         | RE_UNMATCHED_RIGHT_PAREN_ORD)
+/* [[[end syntaxes]]] */
+\f
+/* Maximum number of duplicates an interval can allow.  Some systems
+   (erroneously) define this in other header files, but we want our
+   value, so remove any previous define.  */
+#ifdef RE_DUP_MAX
+#undef RE_DUP_MAX
+#endif
+#define RE_DUP_MAX ((1 << 15) - 1)
+
+
+/* POSIX `cflags' bits (i.e., information for `regcomp').  */
+
+/* If this bit is set, then use extended regular expression syntax.
+   If not set, then use basic regular expression syntax.  */
+#define REG_EXTENDED 1
+
+/* If this bit is set, then ignore case when matching.
+   If not set, then case is significant.  */
+#define REG_ICASE (REG_EXTENDED << 1)
+
+/* If this bit is set, then anchors do not match at newline
+     characters in the string.
+   If not set, then anchors do match at newlines.  */
+#define REG_NEWLINE (REG_ICASE << 1)
+
+/* If this bit is set, then report only success or fail in regexec.
+   If not set, then returns differ between not matching and errors.  */
+#define REG_NOSUB (REG_NEWLINE << 1)
+
+
+/* POSIX `eflags' bits (i.e., information for regexec).  */
+
+/* If this bit is set, then the beginning-of-line operator doesn't match
+     the beginning of the string (presumably because it's not the
+     beginning of a line).
+   If not set, then the beginning-of-line operator does match the
+     beginning of the string.  */
+#define REG_NOTBOL 1
+
+/* Like REG_NOTBOL, except for the end-of-line.  */
+#define REG_NOTEOL (1 << 1)
+
+
+/* If any error codes are removed, changed, or added, update the
+   `re_error_msg' table in regex.c.  */
+typedef enum
+{
+  REG_NOERROR = 0,     /* Success.  */
+  REG_NOMATCH,         /* Didn't find a match (for regexec).  */
+
+  /* POSIX regcomp return error codes.  (In the order listed in the
+     standard.)  */
+  REG_BADPAT,          /* Invalid pattern.  */
+  REG_ECOLLATE,                /* Not implemented.  */
+  REG_ECTYPE,          /* Invalid character class name.  */
+  REG_EESCAPE,         /* Trailing backslash.  */
+  REG_ESUBREG,         /* Invalid back reference.  */
+  REG_EBRACK,          /* Unmatched left bracket.  */
+  REG_EPAREN,          /* Parenthesis imbalance.  */
+  REG_EBRACE,          /* Unmatched \{.  */
+  REG_BADBR,           /* Invalid contents of \{\}.  */
+  REG_ERANGE,          /* Invalid range end.  */
+  REG_ESPACE,          /* Ran out of memory.  */
+  REG_BADRPT,          /* No preceding re for repetition op.  */
+
+  /* Error codes we've added.  */
+  REG_EEND,            /* Premature end.  */
+  REG_ESIZE,           /* Compiled pattern bigger than 2^16 bytes.  */
+  REG_ERPAREN          /* Unmatched ) or \); not returned from regcomp.  */
+} reg_errcode_t;
+\f
+/* This data structure represents a compiled pattern.  Before calling
+   the pattern compiler, the fields `buffer', `allocated', `fastmap',
+   `translate', and `no_sub' can be set.  After the pattern has been
+   compiled, the `re_nsub' field is available.  All other fields are
+   private to the regex routines.  */
+
+struct re_pattern_buffer
+{
+/* [[[begin pattern_buffer]]] */
+       /* Space that holds the compiled pattern.  It is declared as
+         `unsigned char *' because its elements are
+          sometimes used as array indexes.  */
+  unsigned char *buffer;
+
+       /* Number of bytes to which `buffer' points.  */
+  unsigned long allocated;
+
+       /* Number of bytes actually used in `buffer'.  */
+  unsigned long used;
+
+       /* Syntax setting with which the pattern was compiled.  */
+  reg_syntax_t syntax;
+
+       /* Pointer to a fastmap, if any, otherwise zero.  re_search uses
+          the fastmap, if there is one, to skip over impossible
+          starting points for matches.  */
+  char *fastmap;
+
+       /* Either a translate table to apply to all characters before
+          comparing them, or zero for no translation.  The translation
+          is applied to a pattern when it is compiled and to a string
+          when it is matched.  */
+  char *translate;
+
+       /* Number of subexpressions found by the compiler.  */
+  size_t re_nsub;
+
+       /* Zero if this pattern cannot match the empty string, one else.
+          Well, in truth it's used only in `re_search_2', to see
+          whether or not we should use the fastmap, so we don't set
+          this absolutely perfectly; see `re_compile_fastmap' (the
+          `duplicate' case).  */
+  unsigned can_be_null : 1;
+
+       /* If REGS_UNALLOCATED, allocate space in the `regs' structure
+            for `max (RE_NREGS, re_nsub + 1)' groups.
+          If REGS_REALLOCATE, reallocate space if necessary.
+          If REGS_FIXED, use what's there.  */
+#define REGS_UNALLOCATED 0
+#define REGS_REALLOCATE 1
+#define REGS_FIXED 2
+  unsigned regs_allocated : 2;
+
+       /* Set to zero when `regex_compile' compiles a pattern; set to one
+          by `re_compile_fastmap' if it updates the fastmap.  */
+  unsigned fastmap_accurate : 1;
+
+       /* If set, `re_match_2' does not return information about
+          subexpressions.  */
+  unsigned no_sub : 1;
+
+       /* If set, a beginning-of-line anchor doesn't match at the
+          beginning of the string.  */
+  unsigned not_bol : 1;
+
+       /* Similarly for an end-of-line anchor.  */
+  unsigned not_eol : 1;
+
+       /* If true, an anchor at a newline matches.  */
+  unsigned newline_anchor : 1;
+
+/* [[[end pattern_buffer]]] */
+};
+
+typedef struct re_pattern_buffer regex_t;
+
+
+/* search.c (search_buffer) in Emacs needs this one opcode value.  It is
+   defined both in `regex.c' and here.  */
+#define RE_EXACTN_VALUE 1
+\f
+/* Type for byte offsets within the string.  POSIX mandates this.  */
+typedef int regoff_t;
+
+
+/* This is the structure we store register match data in.  See
+   regex.texinfo for a full description of what registers match.  */
+struct re_registers
+{
+  unsigned num_regs;
+  regoff_t *start;
+  regoff_t *end;
+};
+
+
+/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
+   `re_match_2' returns information about at least this many registers
+   the first time a `regs' structure is passed.  */
+#ifndef RE_NREGS
+#define RE_NREGS 30
+#endif
+
+
+/* POSIX specification for registers.  Aside from the different names than
+   `re_registers', POSIX uses an array of structures, instead of a
+   structure of arrays.  */
+typedef struct
+{
+  regoff_t rm_so;  /* Byte offset from string's start to substring's start.  */
+  regoff_t rm_eo;  /* Byte offset from string's start to substring's end.  */
+} regmatch_t;
+\f
+/* Declarations for routines.  */
+
+/* To avoid duplicating every routine declaration -- once with a
+   prototype (if we are ANSI), and once without (if we aren't) -- we
+   use the following macro to declare argument types.  This
+   unfortunately clutters up the declarations a bit, but I think it's
+   worth it.  */
+
+#if __STDC__
+
+#define _RE_ARGS(args) args
+
+#else /* not __STDC__ */
+
+#define _RE_ARGS(args) ()
+
+#endif /* not __STDC__ */
+
+/* Sets the current default syntax to SYNTAX, and return the old syntax.
+   You can also simply assign to the `re_syntax_options' variable.  */
+extern reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax));
+
+/* Compile the regular expression PATTERN, with length LENGTH
+   and syntax given by the global `re_syntax_options', into the buffer
+   BUFFER.  Return NULL if successful, and an error string if not.  */
+extern const char *re_compile_pattern
+  _RE_ARGS ((const char *pattern, int length,
+            struct re_pattern_buffer *buffer));
+
+
+/* Compile a fastmap for the compiled pattern in BUFFER; used to
+   accelerate searches.  Return 0 if successful and -2 if was an
+   internal error.  */
+extern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer));
+
+
+/* Search in the string STRING (with length LENGTH) for the pattern
+   compiled into BUFFER.  Start searching at position START, for RANGE
+   characters.  Return the starting position of the match, -1 for no
+   match, or -2 for an internal error.  Also return register
+   information in REGS (if REGS and BUFFER->no_sub are nonzero).  */
+extern int re_search
+  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
+           int length, int start, int range, struct re_registers *regs));
+
+
+/* Like `re_search', but search in the concatenation of STRING1 and
+   STRING2.  Also, stop searching at index START + STOP.  */
+extern int re_search_2
+  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
+            int length1, const char *string2, int length2,
+            int start, int range, struct re_registers *regs, int stop));
+
+
+/* Like `re_search', but return how many characters in STRING the regexp
+   in BUFFER matched, starting at position START.  */
+extern int re_match
+  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
+            int length, int start, struct re_registers *regs));
+
+
+/* Relates to `re_match' as `re_search_2' relates to `re_search'.  */
+extern int re_match_2
+  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
+            int length1, const char *string2, int length2,
+            int start, struct re_registers *regs, int stop));
+
+
+/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
+   ENDS.  Subsequent matches using BUFFER and REGS will use this memory
+   for recording register information.  STARTS and ENDS must be
+   allocated with malloc, and must each be at least `NUM_REGS * sizeof
+   (regoff_t)' bytes long.
+
+   If NUM_REGS == 0, then subsequent matches should allocate their own
+   register data.
+
+   Unless this function is called, the first search or match using
+   PATTERN_BUFFER will allocate its own register data, without
+   freeing the old data.  */
+extern void re_set_registers
+  _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs,
+            unsigned num_regs, regoff_t *starts, regoff_t *ends));
+
+/* 4.2 bsd compatibility.  */
+extern char *re_comp _RE_ARGS ((const char *));
+extern int re_exec _RE_ARGS ((const char *));
+
+/* POSIX compatibility.  */
+extern int regcomp _RE_ARGS ((regex_t *preg, const char *pattern, int cflags));
+extern int regexec
+  _RE_ARGS ((const regex_t *preg, const char *string, size_t nmatch,
+            regmatch_t pmatch[], int eflags));
+extern size_t regerror
+  _RE_ARGS ((int errcode, const regex_t *preg, char *errbuf,
+            size_t errbuf_size));
+extern void regfree _RE_ARGS ((regex_t *preg));
+
+#endif /* not __REGEXP_LIBRARY_H__ */
+\f
+/*
+Local variables:
+make-backup-files: t
+version-control: t
+trim-versions-without-asking: nil
+End:
+*/
index dbfc2d6b6e2bc115e9976c231ae9d8fef7b2e086..580966e56a3455b9970b7eef33143c1e9c57d41c 100644 (file)
@@ -1,12 +1,25 @@
 #include "../git-compat-util.h"
 
+/*
+ * The size parameter specifies the available space, i.e. includes
+ * the trailing NUL byte; but Windows's vsnprintf expects the
+ * number of characters to write without the trailing NUL.
+ */
+#ifndef SNPRINTF_SIZE_CORR
+#define SNPRINTF_SIZE_CORR 0
+#endif
+
 #undef vsnprintf
 int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap)
 {
        char *s;
-       int ret;
+       int ret = -1;
 
-       ret = vsnprintf(str, maxsize, format, ap);
+       if (maxsize > 0) {
+               ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap);
+               /* Windows does not NUL-terminate if result fills buffer */
+               str[maxsize-1] = 0;
+       }
        if (ret != -1)
                return ret;
 
@@ -20,7 +33,7 @@ int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap)
                if (! str)
                        break;
                s = str;
-               ret = vsnprintf(str, maxsize, format, ap);
+               ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap);
        }
        free(s);
        return ret;
index c2f2bbb000cd003002c1bd346e6be6c9d3ef5c2d..2862cc45cbb1752153bb6050b4e6bd53f6660724 100644 (file)
--- a/config.c
+++ b/config.c
@@ -16,6 +16,8 @@ static int config_linenr;
 static int config_file_eof;
 static int zlib_compression_seen;
 
+const char *config_exclusive_filename = NULL;
+
 static int get_next_char(void)
 {
        int c;
@@ -332,7 +334,7 @@ int git_config_string(const char **dest, const char *var, const char *value)
        return 0;
 }
 
-int git_default_config(const char *var, const char *value, void *dummy)
+static int git_default_core_config(const char *var, const char *value)
 {
        /* This needs a better name */
        if (!strcmp(var, "core.filemode")) {
@@ -444,6 +446,33 @@ int git_default_config(const char *var, const char *value, void *dummy)
                return 0;
        }
 
+       if (!strcmp(var, "core.pager"))
+               return git_config_string(&pager_program, var, value);
+
+       if (!strcmp(var, "core.editor"))
+               return git_config_string(&editor_program, var, value);
+
+       if (!strcmp(var, "core.excludesfile"))
+               return git_config_string(&excludes_file, var, value);
+
+       if (!strcmp(var, "core.whitespace")) {
+               if (!value)
+                       return config_error_nonbool(var);
+               whitespace_rule_cfg = parse_whitespace_rule(value);
+               return 0;
+       }
+
+       if (!strcmp(var, "core.fsyncobjectfiles")) {
+               fsync_object_files = git_config_bool(var, value);
+               return 0;
+       }
+
+       /* Add other config variables here and to Documentation/config.txt. */
+       return 0;
+}
+
+static int git_default_user_config(const char *var, const char *value)
+{
        if (!strcmp(var, "user.name")) {
                if (!value)
                        return config_error_nonbool(var);
@@ -462,32 +491,24 @@ int git_default_config(const char *var, const char *value, void *dummy)
                return 0;
        }
 
+       /* Add other config variables here and to Documentation/config.txt. */
+       return 0;
+}
+
+static int git_default_i18n_config(const char *var, const char *value)
+{
        if (!strcmp(var, "i18n.commitencoding"))
                return git_config_string(&git_commit_encoding, var, value);
 
        if (!strcmp(var, "i18n.logoutputencoding"))
                return git_config_string(&git_log_output_encoding, var, value);
 
-       if (!strcmp(var, "pager.color") || !strcmp(var, "color.pager")) {
-               pager_use_color = git_config_bool(var,value);
-               return 0;
-       }
-
-       if (!strcmp(var, "core.pager"))
-               return git_config_string(&pager_program, var, value);
-
-       if (!strcmp(var, "core.editor"))
-               return git_config_string(&editor_program, var, value);
-
-       if (!strcmp(var, "core.excludesfile"))
-               return git_config_string(&excludes_file, var, value);
+       /* Add other config variables here and to Documentation/config.txt. */
+       return 0;
+}
 
-       if (!strcmp(var, "core.whitespace")) {
-               if (!value)
-                       return config_error_nonbool(var);
-               whitespace_rule_cfg = parse_whitespace_rule(value);
-               return 0;
-       }
+static int git_default_branch_config(const char *var, const char *value)
+{
        if (!strcmp(var, "branch.autosetupmerge")) {
                if (value && !strcasecmp(value, "always")) {
                        git_branch_track = BRANCH_TRACK_ALWAYS;
@@ -516,6 +537,29 @@ int git_default_config(const char *var, const char *value, void *dummy)
        return 0;
 }
 
+int git_default_config(const char *var, const char *value, void *dummy)
+{
+       if (!prefixcmp(var, "core."))
+               return git_default_core_config(var, value);
+
+       if (!prefixcmp(var, "user."))
+               return git_default_user_config(var, value);
+
+       if (!prefixcmp(var, "i18n."))
+               return git_default_i18n_config(var, value);
+
+       if (!prefixcmp(var, "branch."))
+               return git_default_branch_config(var, value);
+
+       if (!strcmp(var, "pager.color") || !strcmp(var, "color.pager")) {
+               pager_use_color = git_config_bool(var,value);
+               return 0;
+       }
+
+       /* Add other config variables here and to Documentation/config.txt. */
+       return 0;
+}
+
 int git_config_from_file(config_fn_t fn, const char *filename, void *data)
 {
        int ret;
@@ -549,7 +593,7 @@ const char *git_etc_gitconfig(void)
        return system_wide;
 }
 
-int git_env_bool(const char *k, int def)
+static int git_env_bool(const char *k, int def)
 {
        const char *v = getenv(k);
        return v ? git_config_bool(k, v) : def;
@@ -569,31 +613,28 @@ int git_config(config_fn_t fn, void *data)
 {
        int ret = 0;
        char *repo_config = NULL;
-       const char *home = NULL, *filename;
+       const char *home = NULL;
 
        /* $GIT_CONFIG makes git read _only_ the given config file,
         * $GIT_CONFIG_LOCAL will make it process it in addition to the
         * global config file, the same way it would the per-repository
         * config file otherwise. */
-       filename = getenv(CONFIG_ENVIRONMENT);
-       if (!filename) {
-               if (git_config_system() && !access(git_etc_gitconfig(), R_OK))
-                       ret += git_config_from_file(fn, git_etc_gitconfig(),
-                               data);
-               home = getenv("HOME");
-               filename = getenv(CONFIG_LOCAL_ENVIRONMENT);
-               if (!filename)
-                       filename = repo_config = xstrdup(git_path("config"));
-       }
+       if (config_exclusive_filename)
+               return git_config_from_file(fn, config_exclusive_filename, data);
+       if (git_config_system() && !access(git_etc_gitconfig(), R_OK))
+               ret += git_config_from_file(fn, git_etc_gitconfig(),
+                                           data);
 
+       home = getenv("HOME");
        if (git_config_global() && home) {
                char *user_config = xstrdup(mkpath("%s/.gitconfig", home));
                if (!access(user_config, R_OK))
-                       ret = git_config_from_file(fn, user_config, data);
+                       ret += git_config_from_file(fn, user_config, data);
                free(user_config);
        }
 
-       ret += git_config_from_file(fn, filename, data);
+       repo_config = xstrdup(git_path("config"));
+       ret += git_config_from_file(fn, repo_config, data);
        free(repo_config);
        return ret;
 }
@@ -831,13 +872,10 @@ int git_config_set_multivar(const char* key, const char* value,
        struct lock_file *lock = NULL;
        const char* last_dot = strrchr(key, '.');
 
-       config_filename = getenv(CONFIG_ENVIRONMENT);
-       if (!config_filename) {
-               config_filename = getenv(CONFIG_LOCAL_ENVIRONMENT);
-               if (!config_filename)
-                       config_filename  = git_path("config");
-       }
-       config_filename = xstrdup(config_filename);
+       if (config_exclusive_filename)
+               config_filename = xstrdup(config_exclusive_filename);
+       else
+               config_filename = xstrdup(git_path("config"));
 
        /*
         * Since "key" actually contains the section name and the real
@@ -1094,13 +1132,10 @@ int git_config_rename_section(const char *old_name, const char *new_name)
        int out_fd;
        char buf[1024];
 
-       config_filename = getenv(CONFIG_ENVIRONMENT);
-       if (!config_filename) {
-               config_filename = getenv(CONFIG_LOCAL_ENVIRONMENT);
-               if (!config_filename)
-                       config_filename  = git_path("config");
-       }
-       config_filename = xstrdup(config_filename);
+       if (config_exclusive_filename)
+               config_filename = xstrdup(config_exclusive_filename);
+       else
+               config_filename = xstrdup(git_path("config"));
        out_fd = hold_lock_file_for_update(lock, config_filename, 0);
        if (out_fd < 0) {
                ret = error("could not lock config file %s", config_filename);
index 7868dfd93a8dab01927c3f5907733baf556e9b59..b776149531025c85f5665d971e6e072f0cc64893 100644 (file)
@@ -11,7 +11,7 @@ TCLTK_PATH = @TCLTK_PATH@
 prefix = @prefix@
 exec_prefix = @exec_prefix@
 bindir = @bindir@
-#gitexecdir = @libexecdir@/git-core/
+gitexecdir = @libexecdir@/git-core/
 datarootdir = @datarootdir@
 template_dir = @datadir@/git-core/templates/
 
index e92af2973565197f2f001c45c6059f9a838fe289..574f42fa47ffa69328217eb25afee6f85db9595e 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -529,7 +529,7 @@ struct child_process *git_connect(int fd[2], const char *url_orig,
                end = host;
 
        path = strchr(end, c);
-       if (path) {
+       if (path && !has_dos_drive_prefix(end)) {
                if (c == ':') {
                        protocol = PROTO_SSH;
                        *path++ = '\0';
index 72f02f208fad95128d7e2fd3b55fdddd23bf2460..37f52d5395daf5791917aa4c4a3b1dc45114b69a 100755 (executable)
@@ -547,7 +547,7 @@ _git_bisect ()
 {
        __git_has_doubledash && return
 
-       local subcommands="start bad good reset visualize replay log"
+       local subcommands="start bad good skip reset visualize replay log run"
        local subcommand="$(__git_find_subcommand "$subcommands")"
        if [ -z "$subcommand" ]; then
                __gitcomp "$subcommands"
@@ -555,7 +555,7 @@ _git_bisect ()
        fi
 
        case "$subcommand" in
-       bad|good|reset)
+       bad|good|reset|skip)
                __gitcomp "$(__git_refs)"
                ;;
        *)
@@ -582,7 +582,7 @@ _git_branch ()
        --*)
                __gitcomp "
                        --color --no-color --verbose --abbrev= --no-abbrev
-                       --track --no-track
+                       --track --no-track --contains --merged --no-merged
                        "
                ;;
        *)
@@ -809,6 +809,9 @@ _git_log ()
                        --not --all
                        --left-right --cherry-pick
                        --graph
+                       --stat --numstat --shortstat
+                       --decorate --diff-filter=
+                       --color-words --walk-reflogs
                        "
                return
                ;;
@@ -933,6 +936,24 @@ _git_rebase ()
        __gitcomp "$(__git_refs)"
 }
 
+_git_send_email ()
+{
+       local cur="${COMP_WORDS[COMP_CWORD]}"
+       case "$cur" in
+       --*)
+               __gitcomp "--bcc --cc --cc-cmd --chain-reply-to --compose
+                       --dry-run --envelope-sender --from --identity
+                       --in-reply-to --no-chain-reply-to --no-signed-off-by-cc
+                       --no-suppress-from --no-thread --quiet
+                       --signed-off-by-cc --smtp-pass --smtp-server
+                       --smtp-server-port --smtp-ssl --smtp-user --subject
+                       --suppress-cc --suppress-from --thread --to"
+               return
+               ;;
+       esac
+       COMPREPLY=()
+}
+
 _git_config ()
 {
        local cur="${COMP_WORDS[COMP_CWORD]}"
@@ -1092,7 +1113,6 @@ _git_config ()
                pull.octopus
                pull.twohead
                repack.useDeltaBaseOffset
-               show.difftree
                showbranch.default
                tar.umask
                transfer.unpackLimit
@@ -1101,7 +1121,6 @@ _git_config ()
                user.name
                user.email
                user.signingkey
-               whatchanged.difftree
                branch. remote.
        "
 }
@@ -1194,8 +1213,19 @@ _git_show ()
 _git_stash ()
 {
        local subcommands='save list show apply clear drop pop create'
-       if [ -z "$(__git_find_subcommand "$subcommands")" ]; then
+       local subcommand="$(__git_find_subcommand "$subcommands")"
+       if [ -z "$subcommand" ]; then
                __gitcomp "$subcommands"
+       else
+               local cur="${COMP_WORDS[COMP_CWORD]}"
+               case "$subcommand,$cur" in
+               save,--*)
+                       __gitcomp "--keep-index"
+                       ;;
+               *)
+                       COMPREPLY=()
+                       ;;
+               esac
        fi
 }
 
@@ -1395,6 +1425,7 @@ _git ()
        rebase)      _git_rebase ;;
        remote)      _git_remote ;;
        reset)       _git_reset ;;
+       send-email)  _git_send_email ;;
        shortlog)    _git_shortlog ;;
        show)        _git_show ;;
        show-branch) _git_log ;;
@@ -1454,6 +1485,7 @@ complete -o default -o nospace -F _git_rebase git-rebase
 complete -o default -o nospace -F _git_config git-config
 complete -o default -o nospace -F _git_remote git-remote
 complete -o default -o nospace -F _git_reset git-reset
+complete -o default -o nospace -F _git_send_email git-send-email
 complete -o default -o nospace -F _git_shortlog git-shortlog
 complete -o default -o nospace -F _git_show git-show
 complete -o default -o nospace -F _git_stash git-stash
index b30ed734e7102b6a5d88c01364fa7d18db8f8bfe..36bd54c985080f8dd5558a3e7a4e19ede9fbab93 100755 (executable)
@@ -129,10 +129,7 @@ sub update_ls_remote {
        return if (($harder == 0) ||
                   (($harder == 1) && exists $info->{'LS_REMOTE'}));
 
-       my @ref = map {
-               s|^[0-9a-f]{40}\s+refs/heads/||;
-               $_;
-       } $git->command(qw(ls-remote --heads), $info->{'URL'});
+       my @ref = map { s|refs/heads/||; $_; } keys %{$git->remote_refs($info->{'URL'}, [ 'heads' ])};
        $info->{'LS_REMOTE'} = \@ref;
 }
 
index d8de9f6c255ca7e458eac62e7f14b3d664054587..87ca51e401cc7f00a2e75acdc205fc49ee54231b 100755 (executable)
@@ -687,6 +687,10 @@ class P4Submit(Command):
         else:
             return False
 
+        allowSubmit = gitConfig("git-p4.allowSubmit")
+        if len(allowSubmit) > 0 and not self.master in allowSubmit.split(","):
+            die("%s is not in git-p4.allowSubmit" % self.master)
+
         [upstream, settings] = findUpstreamBranchPoint()
         self.depotPath = settings['depot-paths'][0]
         if len(self.origin) == 0:
diff --git a/contrib/fast-import/import-zips.py b/contrib/fast-import/import-zips.py
new file mode 100755 (executable)
index 0000000..c674fa2
--- /dev/null
@@ -0,0 +1,72 @@
+#!/usr/bin/python
+
+## zip archive frontend for git-fast-import
+##
+## For example:
+##
+##  mkdir project; cd project; git init
+##  python import-zips.py *.zip
+##  git log --stat import-zips
+
+from os import popen, path
+from sys import argv, exit
+from time import mktime
+from zipfile import ZipFile
+
+if len(argv) < 2:
+       print 'Usage:', argv[0], '<zipfile>...'
+       exit(1)
+
+branch_ref = 'refs/heads/import-zips'
+committer_name = 'Z Ip Creator'
+committer_email = 'zip@example.com'
+
+fast_import = popen('git fast-import --quiet', 'w')
+def printlines(list):
+       for str in list:
+               fast_import.write(str + "\n")
+
+for zipfile in argv[1:]:
+       commit_time = 0
+       next_mark = 1
+       common_prefix = None
+       mark = dict()
+
+       zip = ZipFile(zipfile, 'r')
+       for name in zip.namelist():
+               if name.endswith('/'):
+                       continue
+               info = zip.getinfo(name)
+
+               if commit_time < info.date_time:
+                       commit_time = info.date_time
+               if common_prefix == None:
+                       common_prefix = name[:name.rfind('/') + 1]
+               else:
+                       while not name.startswith(common_prefix):
+                               common_prefix = name[:name.rfind('/') + 1]
+
+               mark[name] = ':' + str(next_mark)
+               next_mark += 1
+
+               printlines(('blob', 'mark ' + mark[name], \
+                                       'data ' + str(info.file_size)))
+               fast_import.write(zip.read(name) + "\n")
+
+       committer = committer_name + ' <' + committer_email + '> %d +0000' % \
+               mktime(commit_time + (0, 0, 0))
+
+       printlines(('commit ' + branch_ref, 'committer ' + committer, \
+               'data <<EOM', 'Imported from ' + zipfile + '.', 'EOM', \
+               '', 'deleteall'))
+
+       for name in mark.keys():
+               fast_import.write('M 100644 ' + mark[name] + ' ' +
+                       name[len(common_prefix):] + "\n")
+
+       printlines(('',  'tag ' + path.basename(zipfile), \
+               'from ' + branch_ref, 'tagger ' + committer, \
+               'data <<EOM', 'Package ' + zipfile, 'EOM', ''))
+
+if fast_import.close():
+       exit(1)
index f68ef725d42cdb1a6082574f9ef3a45d2346c296..7b03204ed18500756ba55818f0808b52db68d048 100755 (executable)
@@ -89,7 +89,7 @@ try:
         if o in ('-v', '--verbose'):
             verbose = True
     if len(args) != 1:
-        raise('params')
+        raise Exception('params')
 except:
     usage()
     sys.exit(1)
@@ -106,7 +106,10 @@ if state:
     else:
         print 'State does not exist, first run'
 
-tip = os.popen('hg tip --template "{rev}"').read()
+sock = os.popen('hg tip --template "{rev}"')
+tip = sock.read()
+if sock.close():
+    sys.exit(1)
 if verbose:
     print 'tip is', tip
 
@@ -149,7 +152,7 @@ for cset in range(1, int(tip) + 1):
 
 if not hgvers.has_key("0"):
     print 'creating repository'
-    os.system('git-init-db')
+    os.system('git init')
 
 # loop through every hg changeset
 for cset in range(int(tip) + 1):
@@ -191,10 +194,10 @@ for cset in range(int(tip) + 1):
     if cset != 0:
         if hgbranch[str(cset)] == "branch-" + str(cset):
             print 'creating new branch', hgbranch[str(cset)]
-            os.system('git-checkout -b %s %s' % (hgbranch[str(cset)], hgvers[parent]))
+            os.system('git checkout -b %s %s' % (hgbranch[str(cset)], hgvers[parent]))
         else:
             print 'checking out branch', hgbranch[str(cset)]
-            os.system('git-checkout %s' % hgbranch[str(cset)])
+            os.system('git checkout %s' % hgbranch[str(cset)])
 
     # merge
     if mparent:
@@ -203,7 +206,7 @@ for cset in range(int(tip) + 1):
         else:
             otherbranch = hgbranch[parent]
         print 'merging', otherbranch, 'into', hgbranch[str(cset)]
-        os.system(getgitenv(user, date) + 'git-merge --no-commit -s ours "" %s %s' % (hgbranch[str(cset)], otherbranch))
+        os.system(getgitenv(user, date) + 'git merge --no-commit -s ours "" %s %s' % (hgbranch[str(cset)], otherbranch))
 
     # remove everything except .git and .hg directories
     os.system('find . \( -path "./.hg" -o -path "./.git" \) -prune -o ! -name "." -print | xargs rm -rf')
@@ -212,9 +215,9 @@ for cset in range(int(tip) + 1):
     os.system('hg update -C %d' % cset)
 
     # add new files
-    os.system('git-ls-files -x .hg --others | git-update-index --add --stdin')
+    os.system('git ls-files -x .hg --others | git update-index --add --stdin')
     # delete removed files
-    os.system('git-ls-files -x .hg --deleted | git-update-index --remove --stdin')
+    os.system('git ls-files -x .hg --deleted | git update-index --remove --stdin')
 
     # commit
     os.system(getgitenv(user, date) + 'git commit --allow-empty -a -F %s' % filecomment)
@@ -222,20 +225,20 @@ for cset in range(int(tip) + 1):
 
     # tag
     if tag and tag != 'tip':
-        os.system(getgitenv(user, date) + 'git-tag %s' % tag)
+        os.system(getgitenv(user, date) + 'git tag %s' % tag)
 
     # delete branch if not used anymore...
     if mparent and len(hgchildren[str(cset)]):
         print "Deleting unused branch:", otherbranch
-        os.system('git-branch -d %s' % otherbranch)
+        os.system('git branch -d %s' % otherbranch)
 
     # retrieve and record the version
-    vvv = os.popen('git-show --quiet --pretty=format:%H').read()
+    vvv = os.popen('git show --quiet --pretty=format:%H').read()
     print 'record', cset, '->', vvv
     hgvers[str(cset)] = vvv
 
 if hgnewcsets >= opt_nrepack and opt_nrepack != -1:
-    os.system('git-repack -a -d')
+    os.system('git repack -a -d')
 
 # write the state for incrementals
 if state:
diff --git a/contrib/thunderbird-patch-inline/README b/contrib/thunderbird-patch-inline/README
new file mode 100644 (file)
index 0000000..39f96aa
--- /dev/null
@@ -0,0 +1,20 @@
+appp.sh is a script that is supposed to be used together with ExternalEditor
+for Mozilla Thundebird. It will let you include patches inline in e-mails
+in an easy way.
+
+Usage:
+- Generate the patch with git format-patch.
+- Start writing a new e-mail in Thunderbird.
+- Press the external editor button (or Ctrl-E) to run appp.sh
+- Select the previosly generated patch file.
+- Finish editing the e-mail.
+
+Any text that is entered into the message editor before appp.sh is called
+will be moved to the section between the --- and the diffstat.
+
+All S-O-B:s and Cc:s in the patch will be added to the CC list.
+
+To set it up, just install External Editor and tell it to use appp.sh as the
+editor.
+
+Zenity is a required dependency.
diff --git a/contrib/thunderbird-patch-inline/appp.sh b/contrib/thunderbird-patch-inline/appp.sh
new file mode 100755 (executable)
index 0000000..cc518f3
--- /dev/null
@@ -0,0 +1,55 @@
+#!/bin/bash
+# Copyright 2008 Lukas Sandström <luksan@gmail.com>
+#
+# AppendPatch - A script to be used together with ExternalEditor
+# for Mozilla Thunderbird to properly include pathes inline i e-mails.
+
+# ExternalEditor can be downloaded at http://globs.org/articles.php?lng=en&pg=2
+
+CONFFILE=~/.appprc
+
+SEP="-=-=-=-=-=-=-=-=-=# Don't remove this line #=-=-=-=-=-=-=-=-=-"
+if [ -e "$CONFFILE" ] ; then
+       LAST_DIR=`grep -m 1 "^LAST_DIR=" "${CONFFILE}"|sed -e 's/^LAST_DIR=//'`
+       cd "${LAST_DIR}"
+else
+       cd > /dev/null
+fi
+
+PATCH=$(zenity --file-selection)
+
+if [ "$?" != "0" ] ; then
+       #zenity --error --text "No patchfile given."
+       exit 1
+fi
+
+cd - > /dev/null
+
+SUBJECT=`sed -n -e '/^Subject: /p' "${PATCH}"`
+HEADERS=`sed -e '/^'"${SEP}"'$/,$d' $1`
+BODY=`sed -e "1,/${SEP}/d" $1`
+CMT_MSG=`sed -e '1,/^$/d' -e '/^---$/,$d' "${PATCH}"`
+DIFF=`sed -e '1,/^---$/d' "${PATCH}"`
+
+CCS=`echo -e "$CMT_MSG\n$HEADERS" | sed -n -e 's/^Cc: \(.*\)$/\1,/gp' \
+       -e 's/^Signed-off-by: \(.*\)/\1,/gp'`
+
+echo "$SUBJECT" > $1
+echo "Cc: $CCS" >> $1
+echo "$HEADERS" | sed -e '/^Subject: /d' -e '/^Cc: /d' >> $1
+echo "$SEP" >> $1
+
+echo "$CMT_MSG" >> $1
+echo "---" >> $1
+if [ "x${BODY}x" != "xx" ] ; then
+       echo >> $1
+       echo "$BODY" >> $1
+       echo >> $1
+fi
+echo "$DIFF" >> $1
+
+LAST_DIR=`dirname "${PATCH}"`
+
+grep -v "^LAST_DIR=" "${CONFFILE}" > "${CONFFILE}_"
+echo "LAST_DIR=${LAST_DIR}" >> "${CONFFILE}_"
+mv "${CONFFILE}_" "${CONFFILE}"
index 63cd12cd9c1909edbaab49aea066ff6fe03c3542..ce3a6f58f3c5c6bb88617510422c4053e0d545a2 100644 (file)
--- a/daemon.c
+++ b/daemon.c
@@ -694,23 +694,47 @@ static void kill_some_children(int signo, unsigned start, unsigned stop)
        }
 }
 
+static void check_dead_children(void)
+{
+       unsigned spawned, reaped, deleted;
+
+       spawned = children_spawned;
+       reaped = children_reaped;
+       deleted = children_deleted;
+
+       while (deleted < reaped) {
+               pid_t pid = dead_child[deleted % MAX_CHILDREN];
+               const char *dead = pid < 0 ? " (with error)" : "";
+
+               if (pid < 0)
+                       pid = -pid;
+
+               /* XXX: Custom logging, since we don't wanna getpid() */
+               if (verbose) {
+                       if (log_syslog)
+                               syslog(LOG_INFO, "[%d] Disconnected%s",
+                                               pid, dead);
+                       else
+                               fprintf(stderr, "[%d] Disconnected%s\n",
+                                               pid, dead);
+               }
+               remove_child(pid, deleted, spawned);
+               deleted++;
+       }
+       children_deleted = deleted;
+}
+
 static void check_max_connections(void)
 {
        for (;;) {
                int active;
-               unsigned spawned, reaped, deleted;
+               unsigned spawned, deleted;
+
+               check_dead_children();
 
                spawned = children_spawned;
-               reaped = children_reaped;
                deleted = children_deleted;
 
-               while (deleted < reaped) {
-                       pid_t pid = dead_child[deleted % MAX_CHILDREN];
-                       remove_child(pid, deleted, spawned);
-                       deleted++;
-               }
-               children_deleted = deleted;
-
                active = spawned - deleted;
                if (active <= max_connections)
                        break;
@@ -760,18 +784,10 @@ static void child_handler(int signo)
 
                if (pid > 0) {
                        unsigned reaped = children_reaped;
+                       if (!WIFEXITED(status) || WEXITSTATUS(status) > 0)
+                               pid = -pid;
                        dead_child[reaped % MAX_CHILDREN] = pid;
                        children_reaped = reaped + 1;
-                       /* XXX: Custom logging, since we don't wanna getpid() */
-                       if (verbose) {
-                               const char *dead = "";
-                               if (!WIFEXITED(status) || WEXITSTATUS(status) > 0)
-                                       dead = " (with error)";
-                               if (log_syslog)
-                                       syslog(LOG_INFO, "[%d] Disconnected%s", pid, dead);
-                               else
-                                       fprintf(stderr, "[%d] Disconnected%s\n", pid, dead);
-                       }
                        continue;
                }
                break;
@@ -928,8 +944,18 @@ static int service_loop(int socknum, int *socklist)
 
        for (;;) {
                int i;
+               int timeout;
 
-               if (poll(pfd, socknum, -1) < 0) {
+               /*
+                * This 1-sec timeout could lead to idly looping but it is
+                * here so that children culled in child_handler() are reported
+                * without too much delay.  We could probably set up a pipe
+                * to ourselves that we poll, and write to the fd from child_handler()
+                * to wake us up (and consume it when the poll() returns...
+                */
+               timeout = (children_spawned != children_deleted) ? 1000 : -1;
+               i = poll(pfd, socknum, timeout);
+               if (i < 0) {
                        if (errno != EINTR) {
                                error("poll failed, resuming: %s",
                                      strerror(errno));
@@ -937,6 +963,10 @@ static int service_loop(int socknum, int *socklist)
                        }
                        continue;
                }
+               if (i == 0) {
+                       check_dead_children();
+                       continue;
+               }
 
                for (i = 0; i < socknum; i++) {
                        if (pfd[i].revents & POLLIN) {
diff --git a/date.c b/date.c
index 1a4eb87b01d5dab0c4a0c455bbef3fda132415ee..35a52576c53e5e1406d40ed4402b8834a29b9f0e 100644 (file)
--- a/date.c
+++ b/date.c
@@ -6,7 +6,10 @@
 
 #include "cache.h"
 
-static time_t my_mktime(struct tm *tm)
+/*
+ * This is like mktime, but without normalization of tm_wday and tm_yday.
+ */
+time_t tm_to_time_t(const struct tm *tm)
 {
        static const int mdays[] = {
            0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
@@ -67,7 +70,7 @@ static int local_tzoffset(unsigned long time)
 
        t = time;
        localtime_r(&t, &tm);
-       t_local = my_mktime(&tm);
+       t_local = tm_to_time_t(&tm);
 
        if (t_local < t) {
                eastwest = -1;
@@ -322,7 +325,7 @@ static int is_date(int year, int month, int day, struct tm *now_tm, time_t now,
                if (!now_tm)
                        return 1;
 
-               specified = my_mktime(r);
+               specified = tm_to_time_t(r);
 
                /* Be it commit time or author time, it does not make
                 * sense to specify timestamp way into the future.  Make
@@ -572,7 +575,7 @@ int parse_date(const char *date, char *result, int maxlen)
        }
 
        /* mktime uses local timezone */
-       then = my_mktime(&tm);
+       then = tm_to_time_t(&tm);
        if (offset == -1)
                offset = (then - mktime(&tm)) / 60;
 
@@ -611,7 +614,7 @@ void datestamp(char *buf, int bufsize)
 
        time(&now);
 
-       offset = my_mktime(localtime(&now)) - now;
+       offset = tm_to_time_t(localtime(&now)) - now;
        offset /= 60;
 
        date_string(now, offset, buf, bufsize);
index 23f6b0040f1cda9a550e5b1d90589fa4a7f76eb5..d9668d2ef94c73e4a7a5602011ff13a9fd9d8c6a 100644 (file)
@@ -37,10 +37,7 @@ static void grow_decoration(struct decoration *n)
 {
        int i;
        int old_size = n->size;
-       struct object_decoration *old_hash;
-
-       old_size = n->size;
-       old_hash = n->hash;
+       struct object_decoration *old_hash = n->hash;
 
        n->size = (old_size + 1000) * 3 / 2;
        n->hash = xcalloc(n->size, sizeof(struct object_decoration));
diff --git a/diff.c b/diff.c
index 78c4d3a35a975d0ffef51dbe999d14938d0a90e3..6a39b393f3e276dd0e0352b5c05eec6989940854 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -531,9 +531,9 @@ static void emit_add_line(const char *reset, struct emit_callback *ecbdata, cons
        else {
                /* Emit just the prefix, then the rest. */
                emit_line(ecbdata->file, set, reset, line, ecbdata->nparents);
-               (void)check_and_emit_line(line + ecbdata->nparents,
-                   len - ecbdata->nparents, ecbdata->ws_rule,
-                   ecbdata->file, set, reset, ws);
+               ws_check_emit(line + ecbdata->nparents,
+                             len - ecbdata->nparents, ecbdata->ws_rule,
+                             ecbdata->file, set, reset, ws);
        }
 }
 
@@ -826,12 +826,12 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options)
        /* Sanity: give at least 5 columns to the graph,
         * but leave at least 10 columns for the name.
         */
-       if (width < name_width + 15) {
-               if (name_width <= 25)
-                       width = name_width + 15;
-               else
-                       name_width = width - 15;
-       }
+       if (width < 25)
+               width = 25;
+       if (name_width < 10)
+               name_width = 10;
+       else if (width < name_width + 15)
+               name_width = width - 15;
 
        /* Find the longest filename and max number of changes */
        reset = diff_get_color_opt(options, DIFF_RESET);
@@ -924,7 +924,8 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options)
                        total = add + del;
                }
                show_name(options->file, prefix, name, len, reset, set);
-               fprintf(options->file, "%5d ", added + deleted);
+               fprintf(options->file, "%5d%s", added + deleted,
+                               added + deleted ? " " : "");
                show_graph(options->file, '+', add, add_c, reset);
                show_graph(options->file, '-', del, del_c, reset);
                fprintf(options->file, "\n");
@@ -1131,42 +1132,85 @@ static void free_diffstat_info(struct diffstat_t *diffstat)
 struct checkdiff_t {
        struct xdiff_emit_state xm;
        const char *filename;
-       int lineno, color_diff;
+       int lineno;
+       struct diff_options *o;
        unsigned ws_rule;
        unsigned status;
-       FILE *file;
+       int trailing_blanks_start;
 };
 
+static int is_conflict_marker(const char *line, unsigned long len)
+{
+       char firstchar;
+       int cnt;
+
+       if (len < 8)
+               return 0;
+       firstchar = line[0];
+       switch (firstchar) {
+       case '=': case '>': case '<':
+               break;
+       default:
+               return 0;
+       }
+       for (cnt = 1; cnt < 7; cnt++)
+               if (line[cnt] != firstchar)
+                       return 0;
+       /* line[0] thru line[6] are same as firstchar */
+       if (firstchar == '=') {
+               /* divider between ours and theirs? */
+               if (len != 8 || line[7] != '\n')
+                       return 0;
+       } else if (len < 8 || !isspace(line[7])) {
+               /* not divider before ours nor after theirs */
+               return 0;
+       }
+       return 1;
+}
+
 static void checkdiff_consume(void *priv, char *line, unsigned long len)
 {
        struct checkdiff_t *data = priv;
-       const char *ws = diff_get_color(data->color_diff, DIFF_WHITESPACE);
-       const char *reset = diff_get_color(data->color_diff, DIFF_RESET);
-       const char *set = diff_get_color(data->color_diff, DIFF_FILE_NEW);
+       int color_diff = DIFF_OPT_TST(data->o, COLOR_DIFF);
+       const char *ws = diff_get_color(color_diff, DIFF_WHITESPACE);
+       const char *reset = diff_get_color(color_diff, DIFF_RESET);
+       const char *set = diff_get_color(color_diff, DIFF_FILE_NEW);
        char *err;
 
        if (line[0] == '+') {
                unsigned bad;
                data->lineno++;
-               bad = check_and_emit_line(line + 1, len - 1,
-                   data->ws_rule, NULL, NULL, NULL, NULL);
+               if (!ws_blank_line(line + 1, len - 1, data->ws_rule))
+                       data->trailing_blanks_start = 0;
+               else if (!data->trailing_blanks_start)
+                       data->trailing_blanks_start = data->lineno;
+               if (is_conflict_marker(line + 1, len - 1)) {
+                       data->status |= 1;
+                       fprintf(data->o->file,
+                               "%s:%d: leftover conflict marker\n",
+                               data->filename, data->lineno);
+               }
+               bad = ws_check(line + 1, len - 1, data->ws_rule);
                if (!bad)
                        return;
                data->status |= bad;
                err = whitespace_error_string(bad);
-               fprintf(data->file, "%s:%d: %s.\n", data->filename, data->lineno, err);
+               fprintf(data->o->file, "%s:%d: %s.\n",
+                       data->filename, data->lineno, err);
                free(err);
-               emit_line(data->file, set, reset, line, 1);
-               (void)check_and_emit_line(line + 1, len - 1, data->ws_rule,
-                   data->file, set, reset, ws);
-       } else if (line[0] == ' ')
+               emit_line(data->o->file, set, reset, line, 1);
+               ws_check_emit(line + 1, len - 1, data->ws_rule,
+                             data->o->file, set, reset, ws);
+       } else if (line[0] == ' ') {
                data->lineno++;
-       else if (line[0] == '@') {
+               data->trailing_blanks_start = 0;
+       } else if (line[0] == '@') {
                char *plus = strchr(line, '+');
                if (plus)
                        data->lineno = strtol(plus, NULL, 10) - 1;
                else
                        die("invalid diff");
+               data->trailing_blanks_start = 0;
        }
 }
 
@@ -1539,8 +1583,9 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
 
 static void builtin_checkdiff(const char *name_a, const char *name_b,
                              const char *attr_path,
-                            struct diff_filespec *one,
-                            struct diff_filespec *two, struct diff_options *o)
+                             struct diff_filespec *one,
+                             struct diff_filespec *two,
+                             struct diff_options *o)
 {
        mmfile_t mf1, mf2;
        struct checkdiff_t data;
@@ -1552,13 +1597,18 @@ static void builtin_checkdiff(const char *name_a, const char *name_b,
        data.xm.consume = checkdiff_consume;
        data.filename = name_b ? name_b : name_a;
        data.lineno = 0;
-       data.color_diff = DIFF_OPT_TST(o, COLOR_DIFF);
+       data.o = o;
        data.ws_rule = whitespace_rule(attr_path);
-       data.file = o->file;
 
        if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
                die("unable to read files to diff");
 
+       /*
+        * All the other codepaths check both sides, but not checking
+        * the "old" side here is deliberate.  We are checking the newly
+        * introduced changes, and as long as the "new" side is text, we
+        * can and should check what it introduces.
+        */
        if (diff_filespec_is_binary(two))
                goto free_and_return;
        else {
@@ -1572,6 +1622,12 @@ static void builtin_checkdiff(const char *name_a, const char *name_b,
                ecb.outf = xdiff_outf;
                ecb.priv = &data;
                xdi_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
+
+               if (data.trailing_blanks_start) {
+                       fprintf(o->file, "%s:%d: ends with blank lines.\n",
+                               data.filename, data.trailing_blanks_start);
+                       data.status = 1; /* report errors */
+               }
        }
  free_and_return:
        diff_free_filespec_data(one);
index 73feb2d03a917d1fbdc8d9397b42fd90e5916bca..4a88a17d54df19af51a4fe0596815badf32fce1f 100644 (file)
@@ -13,7 +13,6 @@ char git_default_email[MAX_GITNAME];
 char git_default_name[MAX_GITNAME];
 int user_ident_explicitly_given;
 int trust_executable_bit = 1;
-int quote_path_fully = 1;
 int has_symlinks = 1;
 int ignore_case;
 int assume_unchanged;
@@ -29,6 +28,7 @@ const char *apply_default_whitespace;
 int zlib_compression_level = Z_BEST_SPEED;
 int core_compression_level;
 int core_compression_seen;
+int fsync_object_files;
 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;
@@ -129,13 +129,6 @@ char *get_object_directory(void)
        return git_object_dir;
 }
 
-char *get_refs_directory(void)
-{
-       if (!git_refs_dir)
-               setup_git_env();
-       return git_refs_dir;
-}
-
 char *get_index_file(void)
 {
        if (!git_index_file)
index e189caca629262334541ea8313d2931b06e67adf..da04efe951e5b8dc4e7b72246212d8ebabc09ec6 100644 (file)
@@ -4,9 +4,42 @@
 #define MAX_ARGS       32
 
 extern char **environ;
-static const char *builtin_exec_path = GIT_EXEC_PATH;
 static const char *argv_exec_path;
 
+static const char *builtin_exec_path(void)
+{
+#ifndef __MINGW32__
+       return GIT_EXEC_PATH;
+#else
+       int len;
+       char *p, *q, *sl;
+       static char *ep;
+       if (ep)
+               return ep;
+
+       len = strlen(_pgmptr);
+       if (len < 2)
+               return ep = ".";
+
+       p = ep = xmalloc(len+1);
+       q = _pgmptr;
+       sl = NULL;
+       /* copy program name, turn '\\' into '/', skip last part */
+       while ((*p = *q)) {
+               if (*q == '\\' || *q == '/') {
+                       *p = '/';
+                       sl = p;
+               }
+               p++, q++;
+       }
+       if (sl)
+               *sl = '\0';
+       else
+               ep[0] = '.', ep[1] = '\0';
+       return ep;
+#endif
+}
+
 void git_set_argv_exec_path(const char *exec_path)
 {
        argv_exec_path = exec_path;
@@ -26,7 +59,7 @@ const char *git_exec_path(void)
                return env;
        }
 
-       return builtin_exec_path;
+       return builtin_exec_path();
 }
 
 static void add_path(struct strbuf *out, const char *path)
@@ -37,7 +70,7 @@ static void add_path(struct strbuf *out, const char *path)
                else
                        strbuf_addstr(out, make_absolute_path(path));
 
-               strbuf_addch(out, ':');
+               strbuf_addch(out, PATH_SEP);
        }
 }
 
@@ -50,7 +83,7 @@ void setup_path(const char *cmd_path)
 
        add_path(&new_path, argv_exec_path);
        add_path(&new_path, getenv(EXEC_PATH_ENVIRONMENT));
-       add_path(&new_path, builtin_exec_path);
+       add_path(&new_path, builtin_exec_path());
        add_path(&new_path, cmd_path);
 
        if (old_path)
@@ -65,32 +98,25 @@ void setup_path(const char *cmd_path)
 
 int execv_git_cmd(const char **argv)
 {
-       struct strbuf cmd;
-       const char *tmp;
-
-       strbuf_init(&cmd, 0);
-       strbuf_addf(&cmd, "git-%s", argv[0]);
+       int argc;
+       const char **nargv;
 
-       /*
-        * argv[0] must be the git command, but the argv array
-        * belongs to the caller, and may be reused in
-        * subsequent loop iterations. Save argv[0] and
-        * restore it on error.
-        */
-       tmp = argv[0];
-       argv[0] = cmd.buf;
+       for (argc = 0; argv[argc]; argc++)
+               ; /* just counting */
+       nargv = xmalloc(sizeof(*nargv) * (argc + 2));
 
-       trace_argv_printf(argv, "trace: exec:");
+       nargv[0] = "git";
+       for (argc = 0; argv[argc]; argc++)
+               nargv[argc + 1] = argv[argc];
+       nargv[argc + 1] = NULL;
+       trace_argv_printf(nargv, "trace: exec:");
 
        /* execvp() can only ever return if it fails */
-       execvp(cmd.buf, (char **)argv);
+       execvp("git", (char **)nargv);
 
        trace_printf("trace: exec failed: %s\n", strerror(errno));
 
-       argv[0] = tmp;
-
-       strbuf_release(&cmd);
-
+       free(nargv);
        return -1;
 }
 
index 903953e68e98535e754b5a5dd6ba22eb6074ef20..801d7c02513be636ac682b503de7b9b4121acee9 100755 (executable)
@@ -18,6 +18,18 @@ my ($fraginfo_color) =
        $diff_use_color ? (
                $repo->get_color('color.diff.frag', 'cyan'),
        ) : ();
+my ($diff_plain_color) =
+       $diff_use_color ? (
+               $repo->get_color('color.diff.plain', ''),
+       ) : ();
+my ($diff_old_color) =
+       $diff_use_color ? (
+               $repo->get_color('color.diff.old', 'red'),
+       ) : ();
+my ($diff_new_color) =
+       $diff_use_color ? (
+               $repo->get_color('color.diff.new', 'green'),
+       ) : ();
 
 my $normal_color = $repo->get_color("", "reset");
 
@@ -682,92 +694,104 @@ sub split_hunk {
        return @split;
 }
 
-sub find_last_o_ctx {
-       my ($it) = @_;
-       my $text = $it->{TEXT};
-       my ($o_ofs, $o_cnt) = parse_hunk_header($text->[0]);
-       my $i = @{$text};
-       my $last_o_ctx = $o_ofs + $o_cnt;
-       while (0 < --$i) {
-               my $line = $text->[$i];
-               if ($line =~ /^ /) {
-                       $last_o_ctx--;
-                       next;
-               }
-               last;
-       }
-       return $last_o_ctx;
+
+sub color_diff {
+       return map {
+               colored((/^@/  ? $fraginfo_color :
+                        /^\+/ ? $diff_new_color :
+                        /^-/  ? $diff_old_color :
+                        $diff_plain_color),
+                       $_);
+       } @_;
 }
 
-sub merge_hunk {
-       my ($prev, $this) = @_;
-       my ($o0_ofs, $o0_cnt, $n0_ofs, $n0_cnt) =
-           parse_hunk_header($prev->{TEXT}[0]);
-       my ($o1_ofs, $o1_cnt, $n1_ofs, $n1_cnt) =
-           parse_hunk_header($this->{TEXT}[0]);
-
-       my (@line, $i, $ofs, $o_cnt, $n_cnt);
-       $ofs = $o0_ofs;
-       $o_cnt = $n_cnt = 0;
-       for ($i = 1; $i < @{$prev->{TEXT}}; $i++) {
-               my $line = $prev->{TEXT}[$i];
-               if ($line =~ /^\+/) {
-                       $n_cnt++;
-                       push @line, $line;
-                       next;
-               }
+sub edit_hunk_manually {
+       my ($oldtext) = @_;
 
-               last if ($o1_ofs <= $ofs);
+       my $hunkfile = $repo->repo_path . "/addp-hunk-edit.diff";
+       my $fh;
+       open $fh, '>', $hunkfile
+               or die "failed to open hunk edit file for writing: " . $!;
+       print $fh "# Manual hunk edit mode -- see bottom for a quick guide\n";
+       print $fh @$oldtext;
+       print $fh <<EOF;
+# ---
+# To remove '-' lines, make them ' ' lines (context).
+# To remove '+' lines, delete them.
+# Lines starting with # will be removed.
+#
+# If the patch applies cleanly, the edited hunk will immediately be
+# marked for staging. If it does not apply cleanly, you will be given
+# an opportunity to edit again. If all lines of the hunk are removed,
+# then the edit is aborted and the hunk is left unchanged.
+EOF
+       close $fh;
 
-               $o_cnt++;
-               $ofs++;
-               if ($line =~ /^ /) {
-                       $n_cnt++;
-               }
-               push @line, $line;
+       my $editor = $ENV{GIT_EDITOR} || $repo->config("core.editor")
+               || $ENV{VISUAL} || $ENV{EDITOR} || "vi";
+       system('sh', '-c', $editor.' "$@"', $editor, $hunkfile);
+
+       open $fh, '<', $hunkfile
+               or die "failed to open hunk edit file for reading: " . $!;
+       my @newtext = grep { !/^#/ } <$fh>;
+       close $fh;
+       unlink $hunkfile;
+
+       # Abort if nothing remains
+       if (!grep { /\S/ } @newtext) {
+               return undef;
        }
 
-       for ($i = 1; $i < @{$this->{TEXT}}; $i++) {
-               my $line = $this->{TEXT}[$i];
-               if ($line =~ /^\+/) {
-                       $n_cnt++;
-                       push @line, $line;
-                       next;
-               }
-               $ofs++;
-               $o_cnt++;
-               if ($line =~ /^ /) {
-                       $n_cnt++;
-               }
-               push @line, $line;
+       # Reinsert the first hunk header if the user accidentally deleted it
+       if ($newtext[0] !~ /^@/) {
+               unshift @newtext, $oldtext->[0];
+       }
+       return \@newtext;
+}
+
+sub diff_applies {
+       my $fh;
+       open $fh, '| git apply --recount --cached --check';
+       for my $h (@_) {
+               print $fh @{$h->{TEXT}};
        }
-       my $head = ("@@ -$o0_ofs" .
-                   (($o_cnt != 1) ? ",$o_cnt" : '') .
-                   " +$n0_ofs" .
-                   (($n_cnt != 1) ? ",$n_cnt" : '') .
-                   " @@\n");
-       @{$prev->{TEXT}} = ($head, @line);
+       return close $fh;
 }
 
-sub coalesce_overlapping_hunks {
-       my (@in) = @_;
-       my @out = ();
+sub prompt_yesno {
+       my ($prompt) = @_;
+       while (1) {
+               print colored $prompt_color, $prompt;
+               my $line = <STDIN>;
+               return 0 if $line =~ /^n/i;
+               return 1 if $line =~ /^y/i;
+       }
+}
 
-       my ($last_o_ctx);
+sub edit_hunk_loop {
+       my ($head, $hunk, $ix) = @_;
+       my $text = $hunk->[$ix]->{TEXT};
 
-       for (grep { $_->{USE} } @in) {
-               my $text = $_->{TEXT};
-               my ($o_ofs) = parse_hunk_header($text->[0]);
-               if (defined $last_o_ctx &&
-                   $o_ofs <= $last_o_ctx) {
-                       merge_hunk($out[-1], $_);
+       while (1) {
+               $text = edit_hunk_manually($text);
+               if (!defined $text) {
+                       return undef;
+               }
+               my $newhunk = { TEXT => $text, USE => 1 };
+               if (diff_applies($head,
+                                @{$hunk}[0..$ix-1],
+                                $newhunk,
+                                @{$hunk}[$ix+1..$#{$hunk}])) {
+                       $newhunk->{DISPLAY} = [color_diff(@{$text})];
+                       return $newhunk;
                }
                else {
-                       push @out, $_;
+                       prompt_yesno(
+                               'Your edited hunk does not apply. Edit again '
+                               . '(saying "no" discards!) [y/n]? '
+                               ) or return undef;
                }
-               $last_o_ctx = find_last_o_ctx($out[-1]);
        }
-       return @out;
 }
 
 sub help_patch_cmd {
@@ -781,6 +805,7 @@ J - leave this hunk undecided, see next hunk
 k - leave this hunk undecided, see previous undecided hunk
 K - leave this hunk undecided, see previous hunk
 s - split the current hunk into smaller hunks
+e - manually edit the current hunk
 ? - print help
 EOF
 }
@@ -885,6 +910,7 @@ sub patch_update_file {
                if (hunk_splittable($hunk[$ix]{TEXT})) {
                        $other .= '/s';
                }
+               $other .= '/e';
                for (@{$hunk[$ix]{DISPLAY}}) {
                        print;
                }
@@ -949,6 +975,12 @@ sub patch_update_file {
                                $num = scalar @hunk;
                                next;
                        }
+                       elsif ($line =~ /^e/) {
+                               my $newhunk = edit_hunk_loop($head, \@hunk, $ix);
+                               if (defined $newhunk) {
+                                       splice @hunk, $ix, 1, $newhunk;
+                               }
+                       }
                        else {
                                help_patch_cmd($other);
                                next;
@@ -962,47 +994,21 @@ sub patch_update_file {
                }
        }
 
-       @hunk = coalesce_overlapping_hunks(@hunk);
-
        my $n_lofs = 0;
        my @result = ();
        if ($mode->{USE}) {
                push @result, @{$mode->{TEXT}};
        }
        for (@hunk) {
-               my $text = $_->{TEXT};
-               my ($o_ofs, $o_cnt, $n_ofs, $n_cnt) =
-                   parse_hunk_header($text->[0]);
-
-               if (!$_->{USE}) {
-                       # We would have added ($n_cnt - $o_cnt) lines
-                       # to the postimage if we were to use this hunk,
-                       # but we didn't.  So the line number that the next
-                       # hunk starts at would be shifted by that much.
-                       $n_lofs -= ($n_cnt - $o_cnt);
-                       next;
-               }
-               else {
-                       if ($n_lofs) {
-                               $n_ofs += $n_lofs;
-                               $text->[0] = ("@@ -$o_ofs" .
-                                             (($o_cnt != 1)
-                                              ? ",$o_cnt" : '') .
-                                             " +$n_ofs" .
-                                             (($n_cnt != 1)
-                                              ? ",$n_cnt" : '') .
-                                             " @@\n");
-                       }
-                       for (@$text) {
-                               push @result, $_;
-                       }
+               if ($_->{USE}) {
+                       push @result, @{$_->{TEXT}};
                }
        }
 
        if (@result) {
                my $fh;
 
-               open $fh, '| git apply --cached';
+               open $fh, '| git apply --cached --recount';
                for (@{$head->{TEXT}}, @result) {
                        print $fh $_;
                }
index 2c517ede590c5c3274b03d1c980f9a847cc7d643..4e73f93a1f1906db8212a1aa9236bdfa03ae1a00 100755 (executable)
--- a/git-am.sh
+++ b/git-am.sh
@@ -5,7 +5,7 @@
 SUBDIRECTORY_OK=Yes
 OPTIONS_KEEPDASHDASH=
 OPTIONS_SPEC="\
-git-am [options] <mbox>|<Maildir>...
+git-am [options] [<mbox>|<Maildir>...]
 git-am [options] --resolved
 git-am [options] --skip
 --
@@ -30,7 +30,8 @@ set_reflog_action am
 require_work_tree
 cd_to_toplevel
 
-git var GIT_COMMITTER_IDENT >/dev/null || exit
+git var GIT_COMMITTER_IDENT >/dev/null ||
+       die "You need to set your committer info first"
 
 stop_here () {
     echo "$1" >"$dotest/next"
index c04e8baa87f263b426de17556f63351ae254ae95..8c7e11473390c14956e43843c17a2d85a336a087 100644 (file)
 #include <sys/time.h>
 #include <time.h>
 #include <signal.h>
-#include <sys/wait.h>
 #include <fnmatch.h>
+#include <assert.h>
+#include <regex.h>
+#include <utime.h>
+#ifndef __MINGW32__
+#include <sys/wait.h>
 #include <sys/poll.h>
 #include <sys/socket.h>
 #include <sys/ioctl.h>
-#include <utime.h>
 #ifndef NO_SYS_SELECT_H
 #include <sys/select.h>
 #endif
-#include <assert.h>
-#include <regex.h>
 #include <netinet/in.h>
 #include <netinet/tcp.h>
 #include <arpa/inet.h>
 #include <grp.h>
 #define _ALL_SOURCE 1
 #endif
+#else  /* __MINGW32__ */
+/* pull in Windows compatibility stuff */
+#include "compat/mingw.h"
+#endif /* __MINGW32__ */
 
 #ifndef NO_ICONV
 #include <iconv.h>
 #define PRIuMAX "llu"
 #endif
 
+#ifndef PRIu32
+#define PRIu32 "u"
+#endif
+
+#ifndef PRIx32
+#define PRIx32 "x"
+#endif
+
+#ifndef PATH_SEP
+#define PATH_SEP ':'
+#endif
+
+#ifndef STRIP_EXTENSION
+#define STRIP_EXTENSION ""
+#endif
+
+#ifndef has_dos_drive_prefix
+#define has_dos_drive_prefix(path) 0
+#endif
+
+#ifndef is_dir_sep
+#define is_dir_sep(c) ((c) == '/')
+#endif
+
 #ifdef __GNUC__
 #define NORETURN __attribute__((__noreturn__))
 #else
@@ -126,6 +155,7 @@ extern void set_error_routine(void (*routine)(const char *err, va_list params));
 extern void set_warn_routine(void (*routine)(const char *warn, va_list params));
 
 extern int prefixcmp(const char *str, const char *prefix);
+extern time_t tm_to_time_t(const struct tm *tm);
 
 #ifdef NO_MMAP
 
@@ -163,6 +193,12 @@ extern int git_munmap(void *start, size_t length);
 #define pread git_pread
 extern ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);
 #endif
+/*
+ * Forward decl that will remind us if its twin in cache.h changes.
+ * This function is used in compat/pread.c.  But we can't include
+ * cache.h there.
+ */
+extern ssize_t read_in_full(int fd, void *buf, size_t count);
 
 #ifdef NO_SETENV
 #define setenv gitsetenv
@@ -240,161 +276,18 @@ static inline char *gitstrchrnul(const char *s, int c)
 
 extern void release_pack_memory(size_t, int);
 
-static inline char* xstrdup(const char *str)
-{
-       char *ret = strdup(str);
-       if (!ret) {
-               release_pack_memory(strlen(str) + 1, -1);
-               ret = strdup(str);
-               if (!ret)
-                       die("Out of memory, strdup failed");
-       }
-       return ret;
-}
-
-static inline void *xmalloc(size_t size)
-{
-       void *ret = malloc(size);
-       if (!ret && !size)
-               ret = malloc(1);
-       if (!ret) {
-               release_pack_memory(size, -1);
-               ret = malloc(size);
-               if (!ret && !size)
-                       ret = malloc(1);
-               if (!ret)
-                       die("Out of memory, malloc failed");
-       }
-#ifdef XMALLOC_POISON
-       memset(ret, 0xA5, size);
-#endif
-       return ret;
-}
-
-/*
- * xmemdupz() allocates (len + 1) bytes of memory, duplicates "len" bytes of
- * "data" to the allocated memory, zero terminates the allocated memory,
- * and returns a pointer to the allocated memory. If the allocation fails,
- * the program dies.
- */
-static inline void *xmemdupz(const void *data, size_t len)
-{
-       char *p = xmalloc(len + 1);
-       memcpy(p, data, len);
-       p[len] = '\0';
-       return p;
-}
-
-static inline char *xstrndup(const char *str, size_t len)
-{
-       char *p = memchr(str, '\0', len);
-       return xmemdupz(str, p ? p - str : len);
-}
-
-static inline void *xrealloc(void *ptr, size_t size)
-{
-       void *ret = realloc(ptr, size);
-       if (!ret && !size)
-               ret = realloc(ptr, 1);
-       if (!ret) {
-               release_pack_memory(size, -1);
-               ret = realloc(ptr, size);
-               if (!ret && !size)
-                       ret = realloc(ptr, 1);
-               if (!ret)
-                       die("Out of memory, realloc failed");
-       }
-       return ret;
-}
-
-static inline void *xcalloc(size_t nmemb, size_t size)
-{
-       void *ret = calloc(nmemb, size);
-       if (!ret && (!nmemb || !size))
-               ret = calloc(1, 1);
-       if (!ret) {
-               release_pack_memory(nmemb * size, -1);
-               ret = calloc(nmemb, size);
-               if (!ret && (!nmemb || !size))
-                       ret = calloc(1, 1);
-               if (!ret)
-                       die("Out of memory, calloc failed");
-       }
-       return ret;
-}
-
-static inline void *xmmap(void *start, size_t length,
-       int prot, int flags, int fd, off_t offset)
-{
-       void *ret = mmap(start, length, prot, flags, fd, offset);
-       if (ret == MAP_FAILED) {
-               if (!length)
-                       return NULL;
-               release_pack_memory(length, fd);
-               ret = mmap(start, length, prot, flags, fd, offset);
-               if (ret == MAP_FAILED)
-                       die("Out of memory? mmap failed: %s", strerror(errno));
-       }
-       return ret;
-}
-
-/*
- * xread() is the same a read(), but it automatically restarts read()
- * operations with a recoverable error (EAGAIN and EINTR). xread()
- * DOES NOT GUARANTEE that "len" bytes is read even if the data is available.
- */
-static inline ssize_t xread(int fd, void *buf, size_t len)
-{
-       ssize_t nr;
-       while (1) {
-               nr = read(fd, buf, len);
-               if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
-                       continue;
-               return nr;
-       }
-}
-
-/*
- * xwrite() is the same a write(), but it automatically restarts write()
- * operations with a recoverable error (EAGAIN and EINTR). xwrite() DOES NOT
- * GUARANTEE that "len" bytes is written even if the operation is successful.
- */
-static inline ssize_t xwrite(int fd, const void *buf, size_t len)
-{
-       ssize_t nr;
-       while (1) {
-               nr = write(fd, buf, len);
-               if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
-                       continue;
-               return nr;
-       }
-}
-
-static inline int xdup(int fd)
-{
-       int ret = dup(fd);
-       if (ret < 0)
-               die("dup failed: %s", strerror(errno));
-       return ret;
-}
-
-static inline FILE *xfdopen(int fd, const char *mode)
-{
-       FILE *stream = fdopen(fd, mode);
-       if (stream == NULL)
-               die("Out of memory? fdopen failed: %s", strerror(errno));
-       return stream;
-}
-
-static inline int xmkstemp(char *template)
-{
-       int fd;
-
-       fd = mkstemp(template);
-       if (fd < 0)
-               die("Unable to create temporary file: %s", strerror(errno));
-       return fd;
-}
+extern char *xstrdup(const char *str);
+extern void *xmalloc(size_t size);
+extern void *xmemdupz(const void *data, size_t len);
+extern char *xstrndup(const char *str, size_t len);
+extern void *xrealloc(void *ptr, size_t size);
+extern void *xcalloc(size_t nmemb, size_t size);
+extern void *xmmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
+extern ssize_t xread(int fd, void *buf, size_t len);
+extern ssize_t xwrite(int fd, const void *buf, size_t len);
+extern int xdup(int fd);
+extern FILE *xfdopen(int fd, const char *mode);
+extern int xmkstemp(char *template);
 
 static inline size_t xsize_t(off_t len)
 {
index e6e88902f1dd1f678eaa5d1dc2d62f8dcacef484..d89f156fd54fe5e51e00793b908ce220e6aa91c8 100755 (executable)
@@ -1774,6 +1774,11 @@ proc do_commit {} {
        commit_tree
 }
 
+proc next_diff {} {
+       global next_diff_p next_diff_w next_diff_i
+       show_diff $next_diff_p $next_diff_w $next_diff_i
+}
+
 proc toggle_or_diff {w x y} {
        global file_states file_lists current_diff_path ui_index ui_workdir
        global last_clicked selected_paths
@@ -1792,12 +1797,34 @@ proc toggle_or_diff {w x y} {
        $ui_index tag remove in_sel 0.0 end
        $ui_workdir tag remove in_sel 0.0 end
 
-       if {$col == 0} {
-               if {$current_diff_path eq $path} {
+       if {$col == 0 && $y > 1} {
+               set i [expr {$lno-1}]
+               set ll [expr {[llength $file_lists($w)]-1}]
+
+               if {$i == $ll && $i == 0} {
                        set after {reshow_diff;}
                } else {
-                       set after {}
+                       global next_diff_p next_diff_w next_diff_i
+
+                       set next_diff_w $w
+
+                       if {$i < $ll} {
+                               set i [expr {$i + 1}]
+                               set next_diff_i $i
+                       } else {
+                               set next_diff_i $i
+                               set i [expr {$i - 1}]
+                       }
+
+                       set next_diff_p [lindex $file_lists($w) $i]
+
+                       if {$next_diff_p ne {} && $current_diff_path ne {}} {
+                               set after {next_diff;}
+                       } else {
+                               set after {}
+                       }
                }
+
                if {$w eq $ui_index} {
                        update_indexinfo \
                                "Unstaging [short_path $path] from commit" \
@@ -2639,6 +2666,11 @@ $ctxm add command \
        -command {apply_hunk $cursorX $cursorY}
 set ui_diff_applyhunk [$ctxm index last]
 lappend diff_actions [list $ctxm entryconf $ui_diff_applyhunk -state]
+$ctxm add command \
+       -label [mc "Apply/Reverse Line"] \
+       -command {apply_line $cursorX $cursorY; do_rescan}
+set ui_diff_applyline [$ctxm index last]
+lappend diff_actions [list $ctxm entryconf $ui_diff_applyline -state]
 $ctxm add separator
 $ctxm add command \
        -label [mc "Show Less Context"] \
@@ -2687,8 +2719,10 @@ proc popup_diff_menu {ctxm x y X Y} {
        set ::cursorY $y
        if {$::ui_index eq $::current_diff_side} {
                set l [mc "Unstage Hunk From Commit"]
+               set t [mc "Unstage Line From Commit"]
        } else {
                set l [mc "Stage Hunk For Commit"]
+               set t [mc "Stage Line For Commit"]
        }
        if {$::is_3way_diff
                || $current_diff_path eq {}
@@ -2699,6 +2733,7 @@ proc popup_diff_menu {ctxm x y X Y} {
                set s normal
        }
        $ctxm entryconf $::ui_diff_applyhunk -state $s -label $l
+       $ctxm entryconf $::ui_diff_applyline -state $s -label $t
        tk_popup $ctxm $X $Y
 }
 bind_button3 $ui_diff [list popup_diff_menu $ctxm %x %y %X %Y]
index d04f6dbde2c468274770aa5543758186803e9ac5..96ba94906cf8037b58c2ba135654da840f9fff9a 100644 (file)
@@ -362,3 +362,90 @@ proc apply_hunk {x y} {
                set current_diff_path $current_diff_path
        }
 }
+
+proc apply_line {x y} {
+       global current_diff_path current_diff_header current_diff_side
+       global ui_diff ui_index file_states
+
+       if {$current_diff_path eq {} || $current_diff_header eq {}} return
+       if {![lock_index apply_hunk]} return
+
+       set apply_cmd {apply --cached --whitespace=nowarn}
+       set mi [lindex $file_states($current_diff_path) 0]
+       if {$current_diff_side eq $ui_index} {
+               set failed_msg [mc "Failed to unstage selected line."]
+               set to_context {+}
+               lappend apply_cmd --reverse
+               if {[string index $mi 0] ne {M}} {
+                       unlock_index
+                       return
+               }
+       } else {
+               set failed_msg [mc "Failed to stage selected line."]
+               set to_context {-}
+               if {[string index $mi 1] ne {M}} {
+                       unlock_index
+                       return
+               }
+       }
+
+       set the_l [$ui_diff index @$x,$y]
+
+       # operate only on change lines
+       set c1 [$ui_diff get "$the_l linestart"]
+       if {$c1 ne {+} && $c1 ne {-}} {
+               unlock_index
+               return
+       }
+       set sign $c1
+
+       set i_l [$ui_diff search -backwards -regexp ^@@ $the_l 0.0]
+       if {$i_l eq {}} {
+               unlock_index
+               return
+       }
+       # $i_l is now at the beginning of a line
+
+       # pick start line number from hunk header
+       set hh [$ui_diff get $i_l "$i_l + 1 lines"]
+       set hh [lindex [split $hh ,] 0]
+       set hln [lindex [split $hh -] 1]
+
+       set n 0
+       set i_l [$ui_diff index "$i_l + 1 lines"]
+       set patch {}
+       while {[$ui_diff compare $i_l < "end - 1 chars"] &&
+              [$ui_diff get $i_l "$i_l + 2 chars"] ne {@@}} {
+               set next_l [$ui_diff index "$i_l + 1 lines"]
+               set c1 [$ui_diff get $i_l]
+               if {[$ui_diff compare $i_l <= $the_l] &&
+                   [$ui_diff compare $the_l < $next_l]} {
+                       # the line to stage/unstage
+                       set ln [$ui_diff get $i_l $next_l]
+                       set patch "$patch$ln"
+               } elseif {$c1 ne {-} && $c1 ne {+}} {
+                       # context line
+                       set ln [$ui_diff get $i_l $next_l]
+                       set patch "$patch$ln"
+                       set n [expr $n+1]
+               } elseif {$c1 eq $to_context} {
+                       # turn change line into context line
+                       set ln [$ui_diff get "$i_l + 1 chars" $next_l]
+                       set patch "$patch $ln"
+                       set n [expr $n+1]
+               }
+               set i_l $next_l
+       }
+       set patch "@@ -$hln,$n +$hln,[eval expr $n $sign 1] @@\n$patch"
+
+       if {[catch {
+               set p [eval git_write $apply_cmd]
+               fconfigure $p -translation binary -encoding binary
+               puts -nonewline $p $current_diff_header
+               puts -nonewline $p $patch
+               close $p} err]} {
+               error_popup [append $failed_msg "\n\n$err"]
+       }
+
+       unlock_index
+}
diff --git a/git-merge-stupid.sh b/git-merge-stupid.sh
deleted file mode 100755 (executable)
index f612d47..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2005 Linus Torvalds
-#
-# Resolve two trees, 'stupid merge'.
-
-# The first parameters up to -- are merge bases; the rest are heads.
-bases= head= remotes= sep_seen=
-for arg
-do
-       case ",$sep_seen,$head,$arg," in
-       *,--,)
-               sep_seen=yes
-               ;;
-       ,yes,,*)
-               head=$arg
-               ;;
-       ,yes,*)
-               remotes="$remotes$arg "
-               ;;
-       *)
-               bases="$bases$arg "
-               ;;
-       esac
-done
-
-# Give up if we are given two or more remotes -- not handling octopus.
-case "$remotes" in
-?*' '?*)
-       exit 2 ;;
-esac
-
-# Find an optimum merge base if there are more than one candidates.
-case "$bases" in
-?*' '?*)
-       echo "Trying to find the optimum merge base."
-       G=.tmp-index$$
-       best=
-       best_cnt=-1
-       for c in $bases
-       do
-               rm -f $G
-               GIT_INDEX_FILE=$G git read-tree -m $c $head $remotes \
-                        2>/dev/null || continue
-               # Count the paths that are unmerged.
-               cnt=`GIT_INDEX_FILE=$G git ls-files --unmerged | wc -l`
-               if test $best_cnt -le 0 -o $cnt -le $best_cnt
-               then
-                       best=$c
-                       best_cnt=$cnt
-                       if test "$best_cnt" -eq 0
-                       then
-                               # Cannot do any better than all trivial merge.
-                               break
-                       fi
-               fi
-       done
-       rm -f $G
-       common="$best"
-       ;;
-*)
-       common="$bases"
-       ;;
-esac
-
-git update-index --refresh 2>/dev/null
-git read-tree -u -m $common $head $remotes || exit 2
-echo "Trying simple merge."
-if result_tree=$(git write-tree  2>/dev/null)
-then
-       exit 0
-else
-       echo "Simple merge failed, trying Automatic merge."
-       if git-merge-index -o git-merge-one-file -a
-       then
-               exit 0
-       else
-               exit 1
-       fi
-fi
index fcdec4a504acd5681e0695fb9657d6a1cd513ab0..94187c306ccb05d977f2bb35e81828130ab49a61 100755 (executable)
@@ -141,10 +141,10 @@ merge_file () {
     fi
 
     ext="$$$(expr "$MERGED" : '.*\(\.[^/]*\)$')"
-    BACKUP="$MERGED.BACKUP.$ext"
-    LOCAL="$MERGED.LOCAL.$ext"
-    REMOTE="$MERGED.REMOTE.$ext"
-    BASE="$MERGED.BASE.$ext"
+    BACKUP="./$MERGED.BACKUP.$ext"
+    LOCAL="./$MERGED.LOCAL.$ext"
+    REMOTE="./$MERGED.REMOTE.$ext"
+    BASE="./$MERGED.BASE.$ext"
 
     mv -- "$MERGED" "$BACKUP"
     cp -- "$BACKUP" "$MERGED"
@@ -183,29 +183,29 @@ merge_file () {
        kdiff3)
            if base_present ; then
                ("$merge_tool_path" --auto --L1 "$MERGED (Base)" --L2 "$MERGED (Local)" --L3 "$MERGED (Remote)" \
-                   -o "$MERGED" -- "$BASE" "$LOCAL" "$REMOTE" > /dev/null 2>&1)
+                   -o "$MERGED" "$BASE" "$LOCAL" "$REMOTE" > /dev/null 2>&1)
            else
                ("$merge_tool_path" --auto --L1 "$MERGED (Local)" --L2 "$MERGED (Remote)" \
-                   -o "$MERGED" -- "$LOCAL" "$REMOTE" > /dev/null 2>&1)
+                   -o "$MERGED" "$LOCAL" "$REMOTE" > /dev/null 2>&1)
            fi
            status=$?
            ;;
        tkdiff)
            if base_present ; then
-               "$merge_tool_path" -a "$BASE" -o "$MERGED" -- "$LOCAL" "$REMOTE"
+               "$merge_tool_path" -a "$BASE" -o "$MERGED" "$LOCAL" "$REMOTE"
            else
-               "$merge_tool_path" -o "$MERGED" -- "$LOCAL" "$REMOTE"
+               "$merge_tool_path" -o "$MERGED" "$LOCAL" "$REMOTE"
            fi
            status=$?
            ;;
        meld|vimdiff)
            touch "$BACKUP"
-           "$merge_tool_path" -- "$LOCAL" "$MERGED" "$REMOTE"
+           "$merge_tool_path" "$LOCAL" "$MERGED" "$REMOTE"
            check_unchanged
            ;;
        gvimdiff)
            touch "$BACKUP"
-           "$merge_tool_path" -f -- "$LOCAL" "$MERGED" "$REMOTE"
+           "$merge_tool_path" -f "$LOCAL" "$MERGED" "$REMOTE"
            check_unchanged
            ;;
        xxdiff)
@@ -215,13 +215,13 @@ merge_file () {
                    -R 'Accel.SaveAsMerged: "Ctrl-S"' \
                    -R 'Accel.Search: "Ctrl+F"' \
                    -R 'Accel.SearchForward: "Ctrl-G"' \
-                   --merged-file "$MERGED" -- "$LOCAL" "$BASE" "$REMOTE"
+                   --merged-file "$MERGED" "$LOCAL" "$BASE" "$REMOTE"
            else
                "$merge_tool_path" -X --show-merged-pane \
                    -R 'Accel.SaveAsMerged: "Ctrl-S"' \
                    -R 'Accel.Search: "Ctrl+F"' \
                    -R 'Accel.SearchForward: "Ctrl-G"' \
-                   --merged-file "$MERGED" -- "$LOCAL" "$REMOTE"
+                   --merged-file "$MERGED" "$LOCAL" "$REMOTE"
            fi
            check_unchanged
            ;;
index a64d9d57ab5943ac4e065866ce0ccd7de5364a9a..3d85486c88069b98cff72f84001bc1897ef85941 100755 (executable)
 # The original idea comes from Eric W. Biederman, in
 # http://article.gmane.org/gmane.comp.version-control.git/22407
 
-USAGE='(--continue | --abort | --skip | [--preserve-merges] [--verbose]
-       [--onto <branch>] <upstream> [<branch>])'
+OPTIONS_KEEPDASHDASH=
+OPTIONS_SPEC="\
+git-rebase [-i] [options] [--] <upstream> [<branch>]
+git-rebase [-i] (--continue | --abort | --skip)
+--
+ Available options are
+v,verbose          display a diffstat of what changed upstream
+onto=              rebase onto given branch instead of upstream
+p,preserve-merges  try to recreate merges instead of ignoring them
+s,strategy=        use the given merge strategy
+m,merge            always used (no-op)
+i,interactive      always used (no-op)
+ Actions:
+continue           continue rebasing process
+abort              abort rebasing process and restore original branch
+skip               skip current patch and continue rebasing process
+"
 
-OPTIONS_SPEC=
 . git-sh-setup
 require_work_tree
 
@@ -25,10 +39,8 @@ SQUASH_MSG="$DOTEST"/message-squash
 REWRITTEN="$DOTEST"/rewritten
 PRESERVE_MERGES=
 STRATEGY=
+ONTO=
 VERBOSE=
-test -d "$REWRITTEN" && PRESERVE_MERGES=t
-test -f "$DOTEST"/strategy && STRATEGY="$(cat "$DOTEST"/strategy)"
-test -f "$DOTEST"/verbose && VERBOSE=t
 
 GIT_CHERRY_PICK_HELP="  After resolving the conflicts,
 mark the corrected paths with 'git add <paths>', and
@@ -366,10 +378,27 @@ do_rest () {
        done
 }
 
+# check if no other options are set
+is_standalone () {
+       test $# -eq 2 -a "$2" = '--' &&
+       test -z "$ONTO" &&
+       test -z "$PRESERVE_MERGES" &&
+       test -z "$STRATEGY" &&
+       test -z "$VERBOSE"
+}
+
+get_saved_options () {
+       test -d "$REWRITTEN" && PRESERVE_MERGES=t
+       test -f "$DOTEST"/strategy && STRATEGY="$(cat "$DOTEST"/strategy)"
+       test -f "$DOTEST"/verbose && VERBOSE=t
+}
+
 while test $# != 0
 do
        case "$1" in
        --continue)
+               is_standalone "$@" || usage
+               get_saved_options
                comment_for_reflog continue
 
                test -d "$DOTEST" || die "No interactive rebase running"
@@ -402,6 +431,8 @@ do
                do_rest
                ;;
        --abort)
+               is_standalone "$@" || usage
+               get_saved_options
                comment_for_reflog abort
 
                git rerere clear
@@ -419,6 +450,8 @@ do
                exit
                ;;
        --skip)
+               is_standalone "$@" || usage
+               get_saved_options
                comment_for_reflog skip
 
                git rerere clear
@@ -426,7 +459,7 @@ do
 
                output git reset --hard && do_rest
                ;;
-       -s|--strategy)
+       -s)
                case "$#,$1" in
                *,*=*)
                        STRATEGY="-s "$(expr "z$1" : 'z-[^=]*=\(.*\)') ;;
@@ -437,25 +470,26 @@ do
                        shift ;;
                esac
                ;;
-       -m|--merge)
+       -m)
                # we use merge anyway
                ;;
-       -C*)
-               die "Interactive rebase uses merge, so $1 does not make sense"
-               ;;
-       -v|--verbose)
+       -v)
                VERBOSE=t
                ;;
-       -p|--preserve-merges)
+       -p)
                PRESERVE_MERGES=t
                ;;
-       -i|--interactive)
+       -i)
                # yeah, we know
                ;;
-       ''|-h)
-               usage
+       --onto)
+               shift
+               ONTO=$(git rev-parse --verify "$1") ||
+                       die "Does not point to a valid commit: $1"
                ;;
-       *)
+       --)
+               shift
+               test $# -eq 1 -o $# -eq 2 || usage
                test -d "$DOTEST" &&
                        die "Interactive rebase already started"
 
@@ -464,15 +498,6 @@ do
 
                comment_for_reflog start
 
-               ONTO=
-               case "$1" in
-               --onto)
-                       ONTO=$(git rev-parse --verify "$2") ||
-                               die "Does not point to a valid commit: $2"
-                       shift; shift
-                       ;;
-               esac
-
                require_clean_work_tree
 
                UPSTREAM=$(git rev-parse --verify "$1") || die "Invalid base"
index 072d1b40f7d71aa731c90e9af158a0fe5cf89fde..8c3bc134add87f38a764f24c63b9e09f562ad6b1 100755 (executable)
@@ -44,11 +44,7 @@ do
        shift
 done
 
-# Later we will default repack.UseDeltaBaseOffset to true
-default_dbo=false
-
-case "`git config --bool repack.usedeltabaseoffset ||
-       echo $default_dbo`" in
+case "`git config --bool repack.usedeltabaseoffset || echo true`" in
 true)
        extra="$extra --delta-base-offset" ;;
 esac
index 068f5e0fc7308db601141bc3e70475ec2145ef67..073a314c8043e0ff30afde65e012e356ff0d186f 100755 (executable)
@@ -26,7 +26,7 @@ merge_base=`git merge-base $baserev $headrev` ||
 die "fatal: No commits in common between $base and $head"
 
 url=$(get_remote_url "$url")
-branch=$(git peek-remote "$url" \
+branch=$(git ls-remote "$url" \
        | sed -n -e "/^$headrev refs.heads./{
                s/^.*   refs.heads.//
                p
index 0b04ba32f0399d338be587ac2d9ad4620705c9a1..6adb66947279e290d90be7da154f49e696894528 100755 (executable)
@@ -84,7 +84,10 @@ Options:
 
    --smtp-pass    The password for SMTP-AUTH.
 
-   --smtp-ssl     If set, connects to the SMTP server using SSL.
+   --smtp-encryption Specify 'tls' for STARTTLS encryption, or 'ssl' for SSL.
+                  Any other value disables the feature.
+
+   --smtp-ssl     Synonym for '--smtp-encryption=ssl'.  Deprecated.
 
    --suppress-cc  Suppress the specified category of auto-CC.  The category
                  can be one of 'author' for the patch author, 'self' to
@@ -184,7 +187,7 @@ my ($quiet, $dry_run) = (0, 0);
 
 # Variables with corresponding config settings
 my ($thread, $chain_reply_to, $suppress_from, $signed_off_cc, $cc_cmd);
-my ($smtp_server, $smtp_server_port, $smtp_authuser, $smtp_ssl);
+my ($smtp_server, $smtp_server_port, $smtp_authuser, $smtp_encryption);
 my ($identity, $aliasfiletype, @alias_files, @smtp_host_parts);
 my ($no_validate);
 my (@suppress_cc);
@@ -194,7 +197,6 @@ my %config_bool_settings = (
     "chainreplyto" => [\$chain_reply_to, 1],
     "suppressfrom" => [\$suppress_from, undef],
     "signedoffcc" => [\$signed_off_cc, undef],
-    "smtpssl" => [\$smtp_ssl, 0],
 );
 
 my %config_settings = (
@@ -249,7 +251,8 @@ my $rc = GetOptions("sender|from=s" => \$sender,
                    "smtp-server-port=s" => \$smtp_server_port,
                    "smtp-user=s" => \$smtp_authuser,
                    "smtp-pass:s" => \$smtp_authpass,
-                   "smtp-ssl!" => \$smtp_ssl,
+                   "smtp-ssl" => sub { $smtp_encryption = 'ssl' },
+                   "smtp-encryption=s" => \$smtp_encryption,
                    "identity=s" => \$identity,
                    "compose" => \$compose,
                    "quiet" => \$quiet,
@@ -289,6 +292,15 @@ sub read_config {
                        $$target = Git::config(@repo, "$prefix.$setting") unless (defined $$target);
                }
        }
+
+       if (!defined $smtp_encryption) {
+               my $enc = Git::config(@repo, "$prefix.smtpencryption");
+               if (defined $enc) {
+                       $smtp_encryption = $enc;
+               } elsif (Git::config_bool(@repo, "$prefix.smtpssl")) {
+                       $smtp_encryption = 'ssl';
+               }
+       }
 }
 
 # read configuration from [sendemail "$identity"], fall back on [sendemail]
@@ -301,6 +313,9 @@ foreach my $setting (values %config_bool_settings) {
        ${$setting->[0]} = $setting->[1] unless (defined (${$setting->[0]}));
 }
 
+# 'default' encryption is none -- this only prevents a warning
+$smtp_encryption = '' unless (defined $smtp_encryption);
+
 # Set CC suppressions
 my(%suppress_cc);
 if (@suppress_cc) {
@@ -393,7 +408,7 @@ for my $f (@ARGV) {
                push @files, grep { -f $_ } map { +$f . "/" . $_ }
                                sort readdir(DH);
 
-       } elsif (-f $f) {
+       } elsif (-f $f or -p $f) {
                push @files, $f;
 
        } else {
@@ -403,8 +418,10 @@ for my $f (@ARGV) {
 
 if (!$no_validate) {
        foreach my $f (@files) {
-               my $error = validate_patch($f);
-               $error and die "fatal: $f: $error\nwarning: no patches were sent\n";
+               unless (-p $f) {
+                       my $error = validate_patch($f);
+                       $error and die "fatal: $f: $error\nwarning: no patches were sent\n";
+               }
        }
 }
 
@@ -738,7 +755,7 @@ X-Mailer: git-send-email $gitversion
                        die "The required SMTP server is not properly defined."
                }
 
-               if ($smtp_ssl) {
+               if ($smtp_encryption eq 'ssl') {
                        $smtp_server_port ||= 465; # ssmtp
                        require Net::SMTP::SSL;
                        $smtp ||= Net::SMTP::SSL->new($smtp_server, Port => $smtp_server_port);
@@ -748,6 +765,21 @@ X-Mailer: git-send-email $gitversion
                        $smtp ||= Net::SMTP->new((defined $smtp_server_port)
                                                 ? "$smtp_server:$smtp_server_port"
                                                 : $smtp_server);
+                       if ($smtp_encryption eq 'tls') {
+                               require Net::SMTP::SSL;
+                               $smtp->command('STARTTLS');
+                               $smtp->response();
+                               if ($smtp->code == 220) {
+                                       $smtp = Net::SMTP::SSL->start_SSL($smtp)
+                                               or die "STARTTLS failed! ".$smtp->message;
+                                       $smtp_encryption = '';
+                                       # Send EHLO again to receive fresh
+                                       # supported commands
+                                       $smtp->hello();
+                               } else {
+                                       die "Server does not support STARTTLS! ".$smtp->message;
+                               }
+                       }
                }
 
                if (!$smtp) {
index a44b1c74a38d6310d7a1bde969cbbcb51f977188..9cceb21a82881b5f12e85769fcbfeb2146631d3c 100755 (executable)
@@ -142,3 +142,16 @@ then
        }
        : ${GIT_OBJECT_DIRECTORY="$GIT_DIR/objects"}
 fi
+
+# Fix some commands on Windows
+case $(uname -s) in
+*MINGW*)
+       # Windows has its own (incompatible) sort and find
+       sort () {
+               /usr/bin/sort "$@"
+       }
+       find () {
+               /usr/bin/find "$@"
+       }
+       ;;
+esac
index 4938ade589f2f7d1c69bd53f7bc7bc1bd33f488c..e4cb6c3e4bef5a714ff245624503a004d3c293e3 100755 (executable)
@@ -86,6 +86,13 @@ create_stash () {
 }
 
 save_stash () {
+       keep_index=
+       case "$1" in
+       --keep-index)
+               keep_index=t
+               shift
+       esac
+
        stash_msg="$1"
 
        if no_changes
@@ -104,6 +111,13 @@ save_stash () {
        git update-ref -m "$stash_msg" $ref_stash $w_commit ||
                die "Cannot save the current status"
        printf 'Saved working directory and index state "%s"\n' "$stash_msg"
+
+       git reset --hard
+
+       if test -n "$keep_index" && test -n $i_tree
+       then
+               git read-tree --reset -u $i_tree
+       fi
 }
 
 have_stash () {
@@ -153,7 +167,8 @@ apply_stash () {
                die "$*: no valid stashed state found"
 
        unstashed_index_tree=
-       if test -n "$unstash_index" && test "$b_tree" != "$i_tree"
+       if test -n "$unstash_index" && test "$b_tree" != "$i_tree" &&
+                       test "$c_tree" != "$i_tree"
        then
                git diff-tree --binary $s^2^..$s^2 | git apply --cached
                test $? -ne 0 &&
@@ -218,6 +233,23 @@ drop_stash () {
        git rev-parse --verify "$ref_stash@{0}" > /dev/null 2>&1 || clear_stash
 }
 
+apply_to_branch () {
+       have_stash || die 'Nothing to apply'
+
+       test -n "$1" || die 'No branch name specified'
+       branch=$1
+
+       if test -z "$2"
+       then
+               set x "$ref_stash@{0}"
+       fi
+       stash=$2
+
+       git-checkout -b $branch $stash^ &&
+       apply_stash --index $stash &&
+       drop_stash $stash
+}
+
 # Main command set
 case "$1" in
 list)
@@ -235,7 +267,7 @@ show)
        ;;
 save)
        shift
-       save_stash "$*" && git-reset --hard
+       save_stash "$*"
        ;;
 apply)
        shift
@@ -264,12 +296,15 @@ pop)
                drop_stash "$@"
        fi
        ;;
+branch)
+       shift
+       apply_to_branch "$@"
+       ;;
 *)
        if test $# -eq 0
        then
                save_stash &&
-               echo '(To restore them type "git stash apply")' &&
-               git-reset --hard
+               echo '(To restore them type "git stash apply")'
        else
                usage
        fi
index 099a7d7560879c284c9fb2fff68f4588baaaf49b..9228f56bee7fd82d530a6865f1f8669fd9b99d8f 100755 (executable)
@@ -5,7 +5,7 @@
 # Copyright (c) 2007 Lars Hjemli
 
 USAGE="[--quiet] [--cached] \
-[add <repo> [-b branch]|status|init|update [-i|--init]|summary [-n|--summary-limit <n>] [<commit>]] \
+[add <repo> [-b branch] <path>]|[status|init|update [-i|--init]|summary [-n|--summary-limit <n>] [<commit>]] \
 [--] [<path>...]"
 OPTIONS_SPEC=
 . git-sh-setup
@@ -27,18 +27,6 @@ say()
        fi
 }
 
-# NEEDSWORK: identical function exists in get_repo_base in clone.sh
-get_repo_base() {
-       (
-               cd "`/bin/pwd`" &&
-               cd "$1" || cd "$1.git" &&
-               {
-                       cd .git
-                       pwd
-               }
-       ) 2>/dev/null
-}
-
 # Resolve relative url by appending to parent's url
 resolve_relative_url ()
 {
@@ -115,7 +103,7 @@ module_clone()
 #
 # Add a new submodule to the working tree, .gitmodules and the index
 #
-# $@ = repo [path]
+# $@ = repo path
 #
 # optional branch is stored in global branch variable
 #
@@ -150,16 +138,27 @@ cmd_add()
        repo=$1
        path=$2
 
-       if test -z "$repo"; then
+       if test -z "$repo" -o -z "$path"; then
                usage
        fi
 
-       # Guess path from repo if not specified or strip trailing slashes
-       if test -z "$path"; then
-               path=$(echo "$repo" | sed -e 's|/*$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g')
-       else
-               path=$(echo "$path" | sed -e 's|/*$||')
-       fi
+       # assure repo is absolute or relative to parent
+       case "$repo" in
+       ./*|../*)
+               # dereference source url relative to parent's url
+               realrepo=$(resolve_relative_url "$repo") || exit
+               ;;
+       *:*|/*)
+               # absolute url
+               realrepo=$repo
+               ;;
+       *)
+               die "repo URL: '$repo' must be absolute or begin with ./|../"
+       ;;
+       esac
+
+       # strip trailing slashes from path
+       path=$(echo "$path" | sed -e 's|/*$||')
 
        git ls-files --error-unmatch "$path" > /dev/null 2>&1 &&
        die "'$path' already exists in the index"
@@ -173,21 +172,17 @@ cmd_add()
                else
                        die "'$path' already exists and is not a valid git repo"
                fi
-       else
+
                case "$repo" in
                ./*|../*)
-                       # dereference source url relative to parent's url
-                       realrepo=$(resolve_relative_url "$repo") || exit
-                       ;;
+                       url=$(resolve_relative_url "$repo") || exit
+                   ;;
                *)
-                       # Turn the source into an absolute path if
-                       # it is local
-                       if base=$(get_repo_base "$repo"); then
-                               repo="$base"
-                       fi
-                       realrepo=$repo
+                       url="$repo"
                        ;;
                esac
+               git config submodule."$path".url "$url"
+       else
 
                module_clone "$path" "$realrepo" || exit
                (unset GIT_DIR; cd "$path" && git checkout -q ${branch:+-b "$branch" "origin/$branch"}) ||
index a366c891dc9892550093f0bb760d5d2580eb11cd..3750e47c202ebdcb25e657eecd69ef5252d45221 100755 (executable)
@@ -537,13 +537,13 @@ sub cmd_find_rev {
                my $head = shift;
                $head ||= 'HEAD';
                my @refs;
-               my (undef, undef, undef, $gs) = working_head_info($head, \@refs);
+               my (undef, undef, $uuid, $gs) = working_head_info($head, \@refs);
                unless ($gs) {
                        die "Unable to determine upstream SVN information from ",
                            "$head history\n";
                }
                my $desired_revision = substr($revision_or_hash, 1);
-               $result = $gs->rev_map_get($desired_revision);
+               $result = $gs->rev_map_get($desired_revision, $uuid);
        } else {
                my (undef, $rev, undef) = cmt_metadata($revision_or_hash);
                $result = $rev;
@@ -1162,7 +1162,7 @@ sub working_head_info {
                if (defined $url && defined $rev) {
                        next if $max{$url} and $max{$url} < $rev;
                        if (my $gs = Git::SVN->find_by_url($url)) {
-                               my $c = $gs->rev_map_get($rev);
+                               my $c = $gs->rev_map_get($rev, $uuid);
                                if ($c && $c eq $hash) {
                                        close $fh; # break the pipe
                                        return ($url, $rev, $uuid, $gs);
@@ -1416,11 +1416,17 @@ sub fetch_all {
 
 sub read_all_remotes {
        my $r = {};
+       my $use_svm_props = eval { command_oneline(qw/config --bool
+           svn.useSvmProps/) };
+       $use_svm_props = $use_svm_props eq 'true' if $use_svm_props;
        foreach (grep { s/^svn-remote\.// } command(qw/config -l/)) {
                if (m!^(.+)\.fetch=\s*(.*)\s*:\s*refs/remotes/(.+)\s*$!) {
                        my ($remote, $local_ref, $remote_ref) = ($1, $2, $3);
                        $local_ref =~ s{^/}{};
                        $r->{$remote}->{fetch}->{$local_ref} = $remote_ref;
+                       $r->{$remote}->{svm} = {} if $use_svm_props;
+               } elsif (m!^(.+)\.usesvmprops=\s*(.*)\s*$!) {
+                       $r->{$1}->{svm} = {};
                } elsif (m!^(.+)\.url=\s*(.*)\s*$!) {
                        $r->{$1}->{url} = $2;
                } elsif (m!^(.+)\.(branches|tags)=
@@ -1437,6 +1443,23 @@ sub read_all_remotes {
                        }
                }
        }
+
+       map {
+               if (defined $r->{$_}->{svm}) {
+                       my $svm;
+                       eval {
+                               my $section = "svn-remote.$_";
+                               $svm = {
+                                       source => tmp_config('--get',
+                                           "$section.svm-source"),
+                                       replace => tmp_config('--get',
+                                           "$section.svm-replace"),
+                               }
+                       };
+                       $r->{$_}->{svm} = $svm;
+               }
+       } keys %$r;
+
        $r;
 }
 
@@ -1563,13 +1586,21 @@ sub find_by_url { # repos_root and, path are optional
                }
                my $p = $path;
                my $rwr = rewrite_root({repo_id => $repo_id});
+               my $svm = $remotes->{$repo_id}->{svm}
+                       if defined $remotes->{$repo_id}->{svm};
                unless (defined $p) {
                        $p = $full_url;
                        my $z = $u;
+                       my $prefix = '';
                        if ($rwr) {
                                $z = $rwr;
+                       } elsif (defined $svm) {
+                               $z = $svm->{source};
+                               $prefix = $svm->{replace};
+                               $prefix =~ s#^\Q$u\E(?:/|$)##;
+                               $prefix =~ s#/$##;
                        }
-                       $p =~ s#^\Q$z\E(?:/|$)## or next;
+                       $p =~ s#^\Q$z\E(?:/|$)#$prefix# or next;
                }
                foreach my $f (keys %$fetch) {
                        next if $f ne $p;
@@ -4619,7 +4650,7 @@ sub migrate_from_v1 {
        mkpath([$svn_dir]);
        print STDERR "Data from a previous version of git-svn exists, but\n\t",
                     "$svn_dir\n\t(required for this version ",
-                    "($::VERSION) of git-svn) does not. exist\n";
+                    "($::VERSION) of git-svn) does not exist.\n";
        my ($fh, $ctx) = command_output_pipe(qw/rev-parse --symbolic --all/);
        while (<$fh>) {
                my $x = $_;
diff --git a/git.c b/git.c
index 59f0fcc1f2278d3234a7e4a306db56c7cfcde9a2..7075533aa7243abacf100cb8a8987284d5d144de 100644 (file)
--- a/git.c
+++ b/git.c
@@ -9,6 +9,43 @@ const char git_usage_string[] =
 const char git_more_info_string[] =
        "See 'git help COMMAND' for more information on a specific command.";
 
+static int use_pager = -1;
+struct pager_config {
+       const char *cmd;
+       int val;
+};
+
+static int pager_command_config(const char *var, const char *value, void *data)
+{
+       struct pager_config *c = data;
+       if (!prefixcmp(var, "pager.") && !strcmp(var + 6, c->cmd))
+               c->val = git_config_bool(var, value);
+       return 0;
+}
+
+/* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */
+int check_pager_config(const char *cmd)
+{
+       struct pager_config c;
+       c.cmd = cmd;
+       c.val = -1;
+       git_config(pager_command_config, &c);
+       return c.val;
+}
+
+static void commit_pager_choice(void) {
+       switch (use_pager) {
+       case 0:
+               setenv("GIT_PAGER", "cat", 1);
+               break;
+       case 1:
+               setup_pager();
+               break;
+       default:
+               break;
+       }
+}
+
 static int handle_options(const char*** argv, int* argc, int* envchanged)
 {
        int handled = 0;
@@ -38,9 +75,9 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
                                exit(0);
                        }
                } else if (!strcmp(cmd, "-p") || !strcmp(cmd, "--paginate")) {
-                       setup_pager();
+                       use_pager = 1;
                } else if (!strcmp(cmd, "--no-pager")) {
-                       setenv("GIT_PAGER", "cat", 1);
+                       use_pager = 0;
                        if (envchanged)
                                *envchanged = 1;
                } else if (!strcmp(cmd, "--git-dir")) {
@@ -242,8 +279,13 @@ static int run_command(struct cmd_struct *p, int argc, const char **argv)
        prefix = NULL;
        if (p->option & RUN_SETUP)
                prefix = setup_git_directory();
-       if (p->option & USE_PAGER)
-               setup_pager();
+
+       if (use_pager == -1 && p->option & RUN_SETUP)
+               use_pager = check_pager_config(p->cmd);
+       if (use_pager == -1 && p->option & USE_PAGER)
+               use_pager = 1;
+       commit_pager_choice();
+
        if (p->option & NEED_WORK_TREE)
                setup_work_tree();
 
@@ -369,6 +411,16 @@ static void handle_internal_command(int argc, const char **argv)
                { "pack-refs", cmd_pack_refs, RUN_SETUP },
        };
        int i;
+       static const char ext[] = STRIP_EXTENSION;
+
+       if (sizeof(ext) > 1) {
+               i = strlen(argv[0]) - strlen(ext);
+               if (i > 0 && !strcmp(argv[0] + i, ext)) {
+                       char *argv0 = strdup(argv[0]);
+                       argv[0] = cmd = argv0;
+                       argv0[i] = '\0';
+               }
+       }
 
        /* Turn "git cmd --help" into "git help cmd" */
        if (argc > 1 && !strcmp(argv[1], "--help")) {
@@ -384,10 +436,40 @@ static void handle_internal_command(int argc, const char **argv)
        }
 }
 
+static void execv_dashed_external(const char **argv)
+{
+       struct strbuf cmd;
+       const char *tmp;
+
+       strbuf_init(&cmd, 0);
+       strbuf_addf(&cmd, "git-%s", argv[0]);
+
+       /*
+        * argv[0] must be the git command, but the argv array
+        * belongs to the caller, and may be reused in
+        * subsequent loop iterations. Save argv[0] and
+        * restore it on error.
+        */
+       tmp = argv[0];
+       argv[0] = cmd.buf;
+
+       trace_argv_printf(argv, "trace: exec:");
+
+       /* execvp() can only ever return if it fails */
+       execvp(cmd.buf, (char **)argv);
+
+       trace_printf("trace: exec failed: %s\n", strerror(errno));
+
+       argv[0] = tmp;
+
+       strbuf_release(&cmd);
+}
+
+
 int main(int argc, const char **argv)
 {
-       const char *cmd = argv[0] ? argv[0] : "git-help";
-       char *slash = strrchr(cmd, '/');
+       const char *cmd = argv[0] && *argv[0] ? argv[0] : "git-help";
+       char *slash = (char *)cmd + strlen(cmd);
        const char *cmd_path = NULL;
        int done_alias = 0;
 
@@ -396,7 +478,10 @@ int main(int argc, const char **argv)
         * name, and the dirname as the default exec_path
         * if we don't have anything better.
         */
-       if (slash) {
+       do
+               --slash;
+       while (cmd <= slash && !is_dir_sep(*slash));
+       if (cmd <= slash) {
                *slash++ = 0;
                cmd_path = cmd;
                cmd = slash;
@@ -423,6 +508,7 @@ int main(int argc, const char **argv)
        argv++;
        argc--;
        handle_options(&argv, &argc, NULL);
+       commit_pager_choice();
        if (argc > 0) {
                if (!prefixcmp(argv[0], "--"))
                        argv[0] += 2;
@@ -448,7 +534,7 @@ int main(int argc, const char **argv)
                handle_internal_command(argc, argv);
 
                /* .. then try the external ones */
-               execv_git_cmd(argv);
+               execv_dashed_external(argv);
 
                /* It could be an alias -- this works around the insanity
                 * of overriding "git log" with "git show" by having
index 3d7f3ef4afeccefd56330342715cb89e73b94775..c6492e5be2763eab81358424ff625a34a5ff2fba 100644 (file)
@@ -117,6 +117,7 @@ find $RPM_BUILD_ROOT -type f -name '*.bs' -empty -exec rm -f {} ';'
 find $RPM_BUILD_ROOT -type f -name perllocal.pod -exec rm -f {} ';'
 
 (find $RPM_BUILD_ROOT%{_bindir} -type f | grep -vE "archimport|svn|cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@)               > bin-man-doc-files
+(find $RPM_BUILD_ROOT%{_libexecdir}/git-core -type f | grep -vE "archimport|svn|cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@)               >> bin-man-doc-files
 (find $RPM_BUILD_ROOT%{perl_vendorlib} -type f | sed -e s@^$RPM_BUILD_ROOT@@) >> perl-files
 %if %{!?_without_docs:1}0
 (find $RPM_BUILD_ROOT%{_mandir} $RPM_BUILD_ROOT/Documentation -type f | grep -vE "archimport|svn|git-cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@ -e 's/$/*/' ) >> bin-man-doc-files
@@ -136,7 +137,7 @@ rm -rf $RPM_BUILD_ROOT
 
 %files svn
 %defattr(-,root,root)
-%{_bindir}/*svn*
+%{_libexecdir}/git-core/*svn*
 %doc Documentation/*svn*.txt
 %{!?_without_docs: %{_mandir}/man1/*svn*.1*}
 %{!?_without_docs: %doc Documentation/*svn*.html }
@@ -144,28 +145,28 @@ rm -rf $RPM_BUILD_ROOT
 %files cvs
 %defattr(-,root,root)
 %doc Documentation/*git-cvs*.txt
-%{_bindir}/*cvs*
+%{_libexecdir}/git-core/*cvs*
 %{!?_without_docs: %{_mandir}/man1/*cvs*.1*}
 %{!?_without_docs: %doc Documentation/*git-cvs*.html }
 
 %files arch
 %defattr(-,root,root)
 %doc Documentation/git-archimport.txt
-%{_bindir}/git-archimport
+%{_libexecdir}/git-core/git-archimport
 %{!?_without_docs: %{_mandir}/man1/git-archimport.1*}
 %{!?_without_docs: %doc Documentation/git-archimport.html }
 
 %files email
 %defattr(-,root,root)
 %doc Documentation/*email*.txt
-%{_bindir}/*email*
+%{_libexecdir}/git-core/*email*
 %{!?_without_docs: %{_mandir}/man1/*email*.1*}
 %{!?_without_docs: %doc Documentation/*email*.html }
 
 %files gui
 %defattr(-,root,root)
-%{_bindir}/git-gui
-%{_bindir}/git-citool
+%{_libexecdir}/git-core/git-gui
+%{_libexecdir}/git-core/git-citool
 %{_datadir}/git-gui/
 %{!?_without_docs: %{_mandir}/man1/git-gui.1*}
 %{!?_without_docs: %doc Documentation/git-gui.html}
index f7194dbef79f3b03cc3524469c4b504a195807b6..26967e201aca8ea1c799e6b21cad468484753779 100644 (file)
@@ -144,6 +144,12 @@ Gitweb repositories
   Spaces in both project path and project owner have to be encoded as either
   '%20' or '+'.
 
+  Other characters that have to be url-encoded, i.e. replaced by '%'
+  followed by two-digit character number in octal, are: other whitespace
+  characters (because they are field separator in a record), plus sign '+'
+  (because it can be used as replacement for spaces), and percent sign '%'
+  (which is used for encoding / escaping).
+
   You can generate the projects list index file using the project_index
   action (the 'TXT' link on projects list page) directly from gitweb.
 
index 356ab7b327eb0df99c0773d68375e155dbcea0be..6908036402ffe56c8b0cdcebdfb3dfacf84fb6f1 100644 (file)
@@ -156,10 +156,11 @@ not include variables usually directly set during build):
    set correctly for gitweb to find repositories.
  * $projects_list
    Source of projects list, either directory to scan, or text file
-   with list of repositories (in the "<URI-encoded repository path> SPC
-   <URI-encoded repository owner>" format).  Set to $GITWEB_LIST
-   during installation.  If empty, $projectroot is used to scan for
-   repositories.
+   with list of repositories (in the "<URI-encoded repository path> SP
+   <URI-encoded repository owner>" line format; actually there can be
+   any sequence of whitespace in place of space (SP)).  Set to
+   $GITWEB_LIST during installation.  If empty, $projectroot is used
+   to scan for repositories.
  * $my_url, $my_uri
    URL and absolute URL of gitweb script; you might need to set those
    variables if you are using 'pathinfo' feature: see also below.
@@ -214,6 +215,39 @@ not include variables usually directly set during build):
    ('-M'); set it to ('-C') or ('-C', '-C') to also detect copies, or
    set it to () if you don't want to have renames detection.
 
+
+Projects list file format
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Instead of having gitweb find repositories by scanning filesystem starting
+from $projectroot (or $projects_list, if it points to directory), you can
+provide list of projects by setting $projects_list to a text file with list
+of projects (and some additional info).  This file uses the following
+format:
+
+One record (for project / repository) per line, whitespace separated fields;
+does not support (at least for now) lines continuation (newline escaping).
+Leading and trailing whitespace are ignored, any run of whitespace can be
+used as field separator (rules for Perl's "split(' ', $line)").  Keyed by
+the first field, which is project name, i.e. path to repository GIT_DIR
+relative to $projectroot.  Fields use modified URI encoding, defined in
+RFC 3986, section 2.1 (Percent-Encoding), or rather "Query string encoding"
+(see http://en.wikipedia.org/wiki/Query_string#URL_encoding), the difference
+being that SP (' ') can be encoded as '+' (and therefore '+' has to be also
+percent-encoded).  Reserved characters are: '%' (used for encoding), '+'
+(can be used to encode SPACE), all whitespace characters as defined in Perl,
+including SP, TAB and LF, (used to separate fields in a record).
+
+Currently list of fields is
+ * <repository path>  - path to repository GIT_DIR, relative to $projectroot
+ * <repository owner> - displayed as repository owner, preferably full name,
+                        or email, or both
+
+You can additionally use $projects_list file to limit which repositories
+are visible, and together with $strict_export to limit access to
+repositories (see "Gitweb repositories" section in gitweb/INSTALL).
+
+
 Per-repository gitweb configuration
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -225,8 +259,8 @@ You can use the following files in repository:
  * README.html
    A .html file (HTML fragment) which is included on the gitweb project
    summary page inside <div> block element. You can use it for longer
-   description of a project, to provide links for example to projects
-   homepage, etc.
+   description of a project, to provide links (for example to project's
+   homepage), etc.
  * description (or gitweb.description)
    Short (shortened by default to 25 characters in the projects list page)
    single line description of a project (of a repository). Plain text file;
index 49b01d8c25b7a7d9c850b5484414bfcfa9bbf85b..90cd99bf916135e5c0a9e1bd7d5e9ff45555c489 100755 (executable)
@@ -386,7 +386,7 @@ $projects_list ||= $projectroot;
 our $action = $cgi->param('a');
 if (defined $action) {
        if ($action =~ m/[^0-9a-zA-Z\.\-_]/) {
-               die_error(undef, "Invalid action parameter");
+               die_error(400, "Invalid action parameter");
        }
 }
 
@@ -399,21 +399,21 @@ if (defined $project) {
            ($export_ok && !(-e "$projectroot/$project/$export_ok")) ||
            ($strict_export && !project_in_list($project))) {
                undef $project;
-               die_error(undef, "No such project");
+               die_error(404, "No such project");
        }
 }
 
 our $file_name = $cgi->param('f');
 if (defined $file_name) {
        if (!validate_pathname($file_name)) {
-               die_error(undef, "Invalid file parameter");
+               die_error(400, "Invalid file parameter");
        }
 }
 
 our $file_parent = $cgi->param('fp');
 if (defined $file_parent) {
        if (!validate_pathname($file_parent)) {
-               die_error(undef, "Invalid file parent parameter");
+               die_error(400, "Invalid file parent parameter");
        }
 }
 
@@ -421,21 +421,21 @@ if (defined $file_parent) {
 our $hash = $cgi->param('h');
 if (defined $hash) {
        if (!validate_refname($hash)) {
-               die_error(undef, "Invalid hash parameter");
+               die_error(400, "Invalid hash parameter");
        }
 }
 
 our $hash_parent = $cgi->param('hp');
 if (defined $hash_parent) {
        if (!validate_refname($hash_parent)) {
-               die_error(undef, "Invalid hash parent parameter");
+               die_error(400, "Invalid hash parent parameter");
        }
 }
 
 our $hash_base = $cgi->param('hb');
 if (defined $hash_base) {
        if (!validate_refname($hash_base)) {
-               die_error(undef, "Invalid hash base parameter");
+               die_error(400, "Invalid hash base parameter");
        }
 }
 
@@ -447,10 +447,10 @@ our @extra_options = $cgi->param('opt');
 if (defined @extra_options) {
        foreach my $opt (@extra_options) {
                if (not exists $allowed_options{$opt}) {
-                       die_error(undef, "Invalid option parameter");
+                       die_error(400, "Invalid option parameter");
                }
                if (not grep(/^$action$/, @{$allowed_options{$opt}})) {
-                       die_error(undef, "Invalid option parameter for this action");
+                       die_error(400, "Invalid option parameter for this action");
                }
        }
 }
@@ -458,7 +458,7 @@ if (defined @extra_options) {
 our $hash_parent_base = $cgi->param('hpb');
 if (defined $hash_parent_base) {
        if (!validate_refname($hash_parent_base)) {
-               die_error(undef, "Invalid hash parent base parameter");
+               die_error(400, "Invalid hash parent base parameter");
        }
 }
 
@@ -466,14 +466,14 @@ if (defined $hash_parent_base) {
 our $page = $cgi->param('pg');
 if (defined $page) {
        if ($page =~ m/[^0-9]/) {
-               die_error(undef, "Invalid page parameter");
+               die_error(400, "Invalid page parameter");
        }
 }
 
 our $searchtype = $cgi->param('st');
 if (defined $searchtype) {
        if ($searchtype =~ m/[^a-z]/) {
-               die_error(undef, "Invalid searchtype parameter");
+               die_error(400, "Invalid searchtype parameter");
        }
 }
 
@@ -483,7 +483,7 @@ our $searchtext = $cgi->param('s');
 our $search_regexp;
 if (defined $searchtext) {
        if (length($searchtext) < 2) {
-               die_error(undef, "At least two characters are required for search parameter");
+               die_error(403, "At least two characters are required for search parameter");
        }
        $search_regexp = $search_use_regexp ? $searchtext : quotemeta $searchtext;
 }
@@ -539,7 +539,7 @@ $git_dir = "$projectroot/$project" if $project;
 
 # dispatch
 my %actions = (
-       "blame" => \&git_blame2,
+       "blame" => \&git_blame,
        "blobdiff" => \&git_blobdiff,
        "blobdiff_plain" => \&git_blobdiff_plain,
        "blob" => \&git_blob,
@@ -580,11 +580,11 @@ if (!defined $action) {
        }
 }
 if (!defined($actions{$action})) {
-       die_error(undef, "Unknown action");
+       die_error(400, "Unknown action");
 }
 if ($action !~ m/^(opml|project_list|project_index)$/ &&
     !$project) {
-       die_error(undef, "Project needed");
+       die_error(400, "Project needed");
 }
 $actions{$action}->();
 exit;
@@ -1665,7 +1665,7 @@ sub git_get_hash_by_path {
        $path =~ s,/+$,,;
 
        open my $fd, "-|", git_cmd(), "ls-tree", $base, "--", $path
-               or die_error(undef, "Open git-ls-tree failed");
+               or die_error(500, "Open git-ls-tree failed");
        my $line = <$fd>;
        close $fd or return undef;
 
@@ -2127,7 +2127,7 @@ sub parse_commit {
                "--max-count=1",
                $commit_id,
                "--",
-               or die_error(undef, "Open git-rev-list failed");
+               or die_error(500, "Open git-rev-list failed");
        %co = parse_commit_text(<$fd>, 1);
        close $fd;
 
@@ -2152,7 +2152,7 @@ sub parse_commits {
                $commit_id,
                "--",
                ($filename ? ($filename) : ())
-               or die_error(undef, "Open git-rev-list failed");
+               or die_error(500, "Open git-rev-list failed");
        while (my $line = <$fd>) {
                my %co = parse_commit_text($line);
                push @cos, \%co;
@@ -2672,11 +2672,26 @@ sub git_footer_html {
              "</html>";
 }
 
+# die_error(<http_status_code>, <error_message>)
+# Example: die_error(404, 'Hash not found')
+# By convention, use the following status codes (as defined in RFC 2616):
+# 400: Invalid or missing CGI parameters, or
+#      requested object exists but has wrong type.
+# 403: Requested feature (like "pickaxe" or "snapshot") not enabled on
+#      this server or project.
+# 404: Requested object/revision/project doesn't exist.
+# 500: The server isn't configured properly, or
+#      an internal error occurred (e.g. failed assertions caused by bugs), or
+#      an unknown error occurred (e.g. the git binary died unexpectedly).
 sub die_error {
-       my $status = shift || "403 Forbidden";
-       my $error = shift || "Malformed query, file missing or permission denied";
-
-       git_header_html($status);
+       my $status = shift || 500;
+       my $error = shift || "Internal server error";
+
+       my %http_responses = (400 => '400 Bad Request',
+                             403 => '403 Forbidden',
+                             404 => '404 Not Found',
+                             500 => '500 Internal Server Error');
+       git_header_html($http_responses{$status});
        print <<EOF;
 <div class="page_body">
 <br /><br />
@@ -3520,21 +3535,24 @@ sub git_patchset_body {
 
 # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
 
-sub git_project_list_body {
-       my ($projlist, $order, $from, $to, $extra, $no_header) = @_;
-
-       my ($check_forks) = gitweb_check_feature('forks');
-
+# fills project list info (age, description, owner, forks) for each
+# project in the list, removing invalid projects from returned list
+# NOTE: modifies $projlist, but does not remove entries from it
+sub fill_project_list_info {
+       my ($projlist, $check_forks) = @_;
        my @projects;
+
+ PROJECT:
        foreach my $pr (@$projlist) {
-               my (@aa) = git_get_last_activity($pr->{'path'});
-               unless (@aa) {
-                       next;
+               my (@activity) = git_get_last_activity($pr->{'path'});
+               unless (@activity) {
+                       next PROJECT;
                }
-               ($pr->{'age'}, $pr->{'age_string'}) = @aa;
+               ($pr->{'age'}, $pr->{'age_string'}) = @activity;
                if (!defined $pr->{'descr'}) {
                        my $descr = git_get_project_description($pr->{'path'}) || "";
-                       $pr->{'descr_long'} = to_utf8($descr);
+                       $descr = to_utf8($descr);
+                       $pr->{'descr_long'} = $descr;
                        $pr->{'descr'} = chop_str($descr, $projects_list_description_width, 5);
                }
                if (!defined $pr->{'owner'}) {
@@ -3546,14 +3564,52 @@ sub git_project_list_body {
                            ($pname !~ /\/$/) &&
                            (-d "$projectroot/$pname")) {
                                $pr->{'forks'} = "-d $projectroot/$pname";
-                       }
-                       else {
+                       }       else {
                                $pr->{'forks'} = 0;
                        }
                }
                push @projects, $pr;
        }
 
+       return @projects;
+}
+
+# print 'sort by' <th> element, either sorting by $key if $name eq $order
+# (changing $list), or generating 'sort by $name' replay link otherwise
+sub print_sort_th {
+       my ($str_sort, $name, $order, $key, $header, $list) = @_;
+       $key    ||= $name;
+       $header ||= ucfirst($name);
+
+       if ($order eq $name) {
+               if ($str_sort) {
+                       @$list = sort {$a->{$key} cmp $b->{$key}} @$list;
+               } else {
+                       @$list = sort {$a->{$key} <=> $b->{$key}} @$list;
+               }
+               print "<th>$header</th>\n";
+       } else {
+               print "<th>" .
+                     $cgi->a({-href => href(-replay=>1, order=>$name),
+                              -class => "header"}, $header) .
+                     "</th>\n";
+       }
+}
+
+sub print_sort_th_str {
+       print_sort_th(1, @_);
+}
+
+sub print_sort_th_num {
+       print_sort_th(0, @_);
+}
+
+sub git_project_list_body {
+       my ($projlist, $order, $from, $to, $extra, $no_header) = @_;
+
+       my ($check_forks) = gitweb_check_feature('forks');
+       my @projects = fill_project_list_info($projlist, $check_forks);
+
        $order ||= $default_projects_order;
        $from = 0 unless defined $from;
        $to = $#projects if (!defined $to || $#projects < $to);
@@ -3564,43 +3620,15 @@ sub git_project_list_body {
                if ($check_forks) {
                        print "<th></th>\n";
                }
-               if ($order eq "project") {
-                       @projects = sort {$a->{'path'} cmp $b->{'path'}} @projects;
-                       print "<th>Project</th>\n";
-               } else {
-                       print "<th>" .
-                             $cgi->a({-href => href(project=>undef, order=>'project'),
-                                      -class => "header"}, "Project") .
-                             "</th>\n";
-               }
-               if ($order eq "descr") {
-                       @projects = sort {$a->{'descr'} cmp $b->{'descr'}} @projects;
-                       print "<th>Description</th>\n";
-               } else {
-                       print "<th>" .
-                             $cgi->a({-href => href(project=>undef, order=>'descr'),
-                                      -class => "header"}, "Description") .
-                             "</th>\n";
-               }
-               if ($order eq "owner") {
-                       @projects = sort {$a->{'owner'} cmp $b->{'owner'}} @projects;
-                       print "<th>Owner</th>\n";
-               } else {
-                       print "<th>" .
-                             $cgi->a({-href => href(project=>undef, order=>'owner'),
-                                      -class => "header"}, "Owner") .
-                             "</th>\n";
-               }
-               if ($order eq "age") {
-                       @projects = sort {$a->{'age'} <=> $b->{'age'}} @projects;
-                       print "<th>Last Change</th>\n";
-               } else {
-                       print "<th>" .
-                             $cgi->a({-href => href(project=>undef, order=>'age'),
-                                      -class => "header"}, "Last Change") .
-                             "</th>\n";
-               }
-               print "<th></th>\n" .
+               print_sort_th_str('project', $order, 'path',
+                                 'Project', \@projects);
+               print_sort_th_str('descr', $order, 'descr_long',
+                                 'Description', \@projects);
+               print_sort_th_str('owner', $order, 'owner',
+                                 'Owner', \@projects);
+               print_sort_th_num('age', $order, 'age',
+                                 'Last Change', \@projects);
+               print "<th></th>\n" . # for links
                      "</tr>\n";
        }
        my $alternate = 1;
@@ -3924,12 +3952,12 @@ sub git_search_grep_body {
 sub git_project_list {
        my $order = $cgi->param('o');
        if (defined $order && $order !~ m/none|project|descr|owner|age/) {
-               die_error(undef, "Unknown order parameter");
+               die_error(400, "Unknown order parameter");
        }
 
        my @list = git_get_projects_list();
        if (!@list) {
-               die_error(undef, "No projects found");
+               die_error(404, "No projects found");
        }
 
        git_header_html();
@@ -3947,12 +3975,12 @@ sub git_project_list {
 sub git_forks {
        my $order = $cgi->param('o');
        if (defined $order && $order !~ m/none|project|descr|owner|age/) {
-               die_error(undef, "Unknown order parameter");
+               die_error(400, "Unknown order parameter");
        }
 
        my @list = git_get_projects_list($project);
        if (!@list) {
-               die_error(undef, "No forks found");
+               die_error(404, "No forks found");
        }
 
        git_header_html();
@@ -4081,7 +4109,7 @@ sub git_tag {
        my %tag = parse_tag($hash);
 
        if (! %tag) {
-               die_error(undef, "Unknown tag object");
+               die_error(404, "Unknown tag object");
        }
 
        git_print_header_div('commit', esc_html($tag{'name'}), $hash);
@@ -4113,30 +4141,29 @@ sub git_tag {
        git_footer_html();
 }
 
-sub git_blame2 {
+sub git_blame {
        my $fd;
        my $ftype;
 
-       my ($have_blame) = gitweb_check_feature('blame');
-       if (!$have_blame) {
-               die_error('403 Permission denied', "Permission denied");
-       }
-       die_error('404 Not Found', "File name not defined") if (!$file_name);
+       gitweb_check_feature('blame')
+           or die_error(403, "Blame view not allowed");
+
+       die_error(400, "No file name given") unless $file_name;
        $hash_base ||= git_get_head_hash($project);
-       die_error(undef, "Couldn't find base commit") unless ($hash_base);
+       die_error(404, "Couldn't find base commit") unless ($hash_base);
        my %co = parse_commit($hash_base)
-               or die_error(undef, "Reading commit failed");
+               or die_error(404, "Commit not found");
        if (!defined $hash) {
                $hash = git_get_hash_by_path($hash_base, $file_name, "blob")
-                       or die_error(undef, "Error looking up file");
+                       or die_error(404, "Error looking up file");
        }
        $ftype = git_get_type($hash);
        if ($ftype !~ "blob") {
-               die_error('400 Bad Request', "Object is not a blob");
+               die_error(400, "Object is not a blob");
        }
        open ($fd, "-|", git_cmd(), "blame", '-p', '--',
              $file_name, $hash_base)
-               or die_error(undef, "Open git-blame failed");
+               or die_error(500, "Open git-blame failed");
        git_header_html();
        my $formats_nav =
                $cgi->a({-href => href(action=>"blob", -replay=>1)},
@@ -4198,7 +4225,7 @@ HTML
                        print "</td>\n";
                }
                open (my $dd, "-|", git_cmd(), "rev-parse", "$full_rev^")
-                       or die_error(undef, "Open git-rev-parse failed");
+                       or die_error(500, "Open git-rev-parse failed");
                my $parent_commit = <$dd>;
                close $dd;
                chomp($parent_commit);
@@ -4221,103 +4248,6 @@ HTML
        git_footer_html();
 }
 
-sub git_blame {
-       my $fd;
-
-       my ($have_blame) = gitweb_check_feature('blame');
-       if (!$have_blame) {
-               die_error('403 Permission denied', "Permission denied");
-       }
-       die_error('404 Not Found', "File name not defined") if (!$file_name);
-       $hash_base ||= git_get_head_hash($project);
-       die_error(undef, "Couldn't find base commit") unless ($hash_base);
-       my %co = parse_commit($hash_base)
-               or die_error(undef, "Reading commit failed");
-       if (!defined $hash) {
-               $hash = git_get_hash_by_path($hash_base, $file_name, "blob")
-                       or die_error(undef, "Error lookup file");
-       }
-       open ($fd, "-|", git_cmd(), "annotate", '-l', '-t', '-r', $file_name, $hash_base)
-               or die_error(undef, "Open git-annotate failed");
-       git_header_html();
-       my $formats_nav =
-               $cgi->a({-href => href(action=>"blob", hash=>$hash, hash_base=>$hash_base, file_name=>$file_name)},
-                       "blob") .
-               " | " .
-               $cgi->a({-href => href(action=>"history", hash=>$hash, hash_base=>$hash_base, file_name=>$file_name)},
-                       "history") .
-               " | " .
-               $cgi->a({-href => href(action=>"blame", file_name=>$file_name)},
-                       "HEAD");
-       git_print_page_nav('','', $hash_base,$co{'tree'},$hash_base, $formats_nav);
-       git_print_header_div('commit', esc_html($co{'title'}), $hash_base);
-       git_print_page_path($file_name, 'blob', $hash_base);
-       print "<div class=\"page_body\">\n";
-       print <<HTML;
-<table class="blame">
-  <tr>
-    <th>Commit</th>
-    <th>Age</th>
-    <th>Author</th>
-    <th>Line</th>
-    <th>Data</th>
-  </tr>
-HTML
-       my @line_class = (qw(light dark));
-       my $line_class_len = scalar (@line_class);
-       my $line_class_num = $#line_class;
-       while (my $line = <$fd>) {
-               my $long_rev;
-               my $short_rev;
-               my $author;
-               my $time;
-               my $lineno;
-               my $data;
-               my $age;
-               my $age_str;
-               my $age_class;
-
-               chomp $line;
-               $line_class_num = ($line_class_num + 1) % $line_class_len;
-
-               if ($line =~ m/^([0-9a-fA-F]{40})\t\(\s*([^\t]+)\t(\d+) [+-]\d\d\d\d\t(\d+)\)(.*)$/) {
-                       $long_rev = $1;
-                       $author   = $2;
-                       $time     = $3;
-                       $lineno   = $4;
-                       $data     = $5;
-               } else {
-                       print qq(  <tr><td colspan="5" class="error">Unable to parse: $line</td></tr>\n);
-                       next;
-               }
-               $short_rev  = substr ($long_rev, 0, 8);
-               $age        = time () - $time;
-               $age_str    = age_string ($age);
-               $age_str    =~ s/ /&nbsp;/g;
-               $age_class  = age_class($age);
-               $author     = esc_html ($author);
-               $author     =~ s/ /&nbsp;/g;
-
-               $data = untabify($data);
-               $data = esc_html ($data);
-
-               print <<HTML;
-  <tr class="$line_class[$line_class_num]">
-    <td class="sha1"><a href="${\href (action=>"commit", hash=>$long_rev)}" class="text">$short_rev..</a></td>
-    <td class="$age_class">$age_str</td>
-    <td>$author</td>
-    <td class="linenr"><a id="$lineno" href="#$lineno" class="linenr">$lineno</a></td>
-    <td class="pre">$data</td>
-  </tr>
-HTML
-       } # while (my $line = <$fd>)
-       print "</table>\n\n";
-       close $fd
-               or print "Reading blob failed.\n";
-       print "</div>";
-       git_footer_html();
-}
-
 sub git_tags {
        my $head = git_get_head_hash($project);
        git_header_html();
@@ -4352,9 +4282,9 @@ sub git_blob_plain {
                if (defined $file_name) {
                        my $base = $hash_base || git_get_head_hash($project);
                        $hash = git_get_hash_by_path($base, $file_name, "blob")
-                               or die_error(undef, "Error lookup file");
+                               or die_error(404, "Cannot find file");
                } else {
-                       die_error(undef, "No file name defined");
+                       die_error(400, "No file name defined");
                }
        } elsif ($hash =~ m/^[0-9a-fA-F]{40}$/) {
                # blobs defined by non-textual hash id's can be cached
@@ -4362,7 +4292,7 @@ sub git_blob_plain {
        }
 
        open my $fd, "-|", git_cmd(), "cat-file", "blob", $hash
-               or die_error(undef, "Open git-cat-file blob '$hash' failed");
+               or die_error(500, "Open git-cat-file blob '$hash' failed");
 
        # content-type (can include charset)
        $type = blob_contenttype($fd, $file_name, $type);
@@ -4394,9 +4324,9 @@ sub git_blob {
                if (defined $file_name) {
                        my $base = $hash_base || git_get_head_hash($project);
                        $hash = git_get_hash_by_path($base, $file_name, "blob")
-                               or die_error(undef, "Error lookup file");
+                               or die_error(404, "Cannot find file");
                } else {
-                       die_error(undef, "No file name defined");
+                       die_error(400, "No file name defined");
                }
        } elsif ($hash =~ m/^[0-9a-fA-F]{40}$/) {
                # blobs defined by non-textual hash id's can be cached
@@ -4405,7 +4335,7 @@ sub git_blob {
 
        my ($have_blame) = gitweb_check_feature('blame');
        open my $fd, "-|", git_cmd(), "cat-file", "blob", $hash
-               or die_error(undef, "Couldn't cat $file_name, $hash");
+               or die_error(500, "Couldn't cat $file_name, $hash");
        my $mimetype = blob_mimetype($fd, $file_name);
        if ($mimetype !~ m!^(?:text/|image/(?:gif|png|jpeg)$)! && -B $fd) {
                close $fd;
@@ -4486,9 +4416,9 @@ sub git_tree {
        }
        $/ = "\0";
        open my $fd, "-|", git_cmd(), "ls-tree", '-z', $hash
-               or die_error(undef, "Open git-ls-tree failed");
+               or die_error(500, "Open git-ls-tree failed");
        my @entries = map { chomp; $_ } <$fd>;
-       close $fd or die_error(undef, "Reading tree failed");
+       close $fd or die_error(404, "Reading tree failed");
        $/ = "\n";
 
        my $refs = git_get_references();
@@ -4578,16 +4508,16 @@ sub git_snapshot {
 
        my $format = $cgi->param('sf');
        if (!@supported_fmts) {
-               die_error('403 Permission denied', "Permission denied");
+               die_error(403, "Snapshots not allowed");
        }
        # default to first supported snapshot format
        $format ||= $supported_fmts[0];
        if ($format !~ m/^[a-z0-9]+$/) {
-               die_error(undef, "Invalid snapshot format parameter");
+               die_error(400, "Invalid snapshot format parameter");
        } elsif (!exists($known_snapshot_formats{$format})) {
-               die_error(undef, "Unknown snapshot format");
+               die_error(400, "Unknown snapshot format");
        } elsif (!grep($_ eq $format, @supported_fmts)) {
-               die_error(undef, "Unsupported snapshot format");
+               die_error(403, "Unsupported snapshot format");
        }
 
        if (!defined $hash) {
@@ -4615,7 +4545,7 @@ sub git_snapshot {
                -status => '200 OK');
 
        open my $fd, "-|", $cmd
-               or die_error(undef, "Execute git-archive failed");
+               or die_error(500, "Execute git-archive failed");
        binmode STDOUT, ':raw';
        print <$fd>;
        binmode STDOUT, ':utf8'; # as set at the beginning of gitweb.cgi
@@ -4683,10 +4613,8 @@ sub git_log {
 
 sub git_commit {
        $hash ||= $hash_base || "HEAD";
-       my %co = parse_commit($hash);
-       if (!%co) {
-               die_error(undef, "Unknown commit object");
-       }
+       my %co = parse_commit($hash)
+           or die_error(404, "Unknown commit object");
        my %ad = parse_date($co{'author_epoch'}, $co{'author_tz'});
        my %cd = parse_date($co{'committer_epoch'}, $co{'committer_tz'});
 
@@ -4726,9 +4654,9 @@ sub git_commit {
                @diff_opts,
                (@$parents <= 1 ? $parent : '-c'),
                $hash, "--"
-               or die_error(undef, "Open git-diff-tree failed");
+               or die_error(500, "Open git-diff-tree failed");
        @difftree = map { chomp; $_ } <$fd>;
-       close $fd or die_error(undef, "Reading git-diff-tree failed");
+       close $fd or die_error(404, "Reading git-diff-tree failed");
 
        # non-textual hash id's can be cached
        my $expires;
@@ -4821,33 +4749,33 @@ sub git_object {
 
                open my $fd, "-|", quote_command(
                        git_cmd(), 'cat-file', '-t', $object_id) . ' 2> /dev/null'
-                       or die_error('404 Not Found', "Object does not exist");
+                       or die_error(404, "Object does not exist");
                $type = <$fd>;
                chomp $type;
                close $fd
-                       or die_error('404 Not Found', "Object does not exist");
+                       or die_error(404, "Object does not exist");
 
        # - hash_base and file_name
        } elsif ($hash_base && defined $file_name) {
                $file_name =~ s,/+$,,;
 
                system(git_cmd(), "cat-file", '-e', $hash_base) == 0
-                       or die_error('404 Not Found', "Base object does not exist");
+                       or die_error(404, "Base object does not exist");
 
                # here errors should not hapen
                open my $fd, "-|", git_cmd(), "ls-tree", $hash_base, "--", $file_name
-                       or die_error(undef, "Open git-ls-tree failed");
+                       or die_error(500, "Open git-ls-tree failed");
                my $line = <$fd>;
                close $fd;
 
                #'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa  panic.c'
                unless ($line && $line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t/) {
-                       die_error('404 Not Found', "File or directory for given base does not exist");
+                       die_error(404, "File or directory for given base does not exist");
                }
                $type = $2;
                $hash = $3;
        } else {
-               die_error('404 Not Found', "Not enough information to find object");
+               die_error(400, "Not enough information to find object");
        }
 
        print $cgi->redirect(-uri => href(action=>$type, -full=>1,
@@ -4872,12 +4800,12 @@ sub git_blobdiff {
                        open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts,
                                $hash_parent_base, $hash_base,
                                "--", (defined $file_parent ? $file_parent : ()), $file_name
-                               or die_error(undef, "Open git-diff-tree failed");
+                               or die_error(500, "Open git-diff-tree failed");
                        @difftree = map { chomp; $_ } <$fd>;
                        close $fd
-                               or die_error(undef, "Reading git-diff-tree failed");
+                               or die_error(404, "Reading git-diff-tree failed");
                        @difftree
-                               or die_error('404 Not Found', "Blob diff not found");
+                               or die_error(404, "Blob diff not found");
 
                } elsif (defined $hash &&
                         $hash =~ /[0-9a-fA-F]{40}/) {
@@ -4886,23 +4814,23 @@ sub git_blobdiff {
                        # read filtered raw output
                        open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts,
                                $hash_parent_base, $hash_base, "--"
-                               or die_error(undef, "Open git-diff-tree failed");
+                               or die_error(500, "Open git-diff-tree failed");
                        @difftree =
                                # ':100644 100644 03b21826... 3b93d5e7... M     ls-files.c'
                                # $hash == to_id
                                grep { /^:[0-7]{6} [0-7]{6} [0-9a-fA-F]{40} $hash/ }
                                map { chomp; $_ } <$fd>;
                        close $fd
-                               or die_error(undef, "Reading git-diff-tree failed");
+                               or die_error(404, "Reading git-diff-tree failed");
                        @difftree
-                               or die_error('404 Not Found', "Blob diff not found");
+                               or die_error(404, "Blob diff not found");
 
                } else {
-                       die_error('404 Not Found', "Missing one of the blob diff parameters");
+                       die_error(400, "Missing one of the blob diff parameters");
                }
 
                if (@difftree > 1) {
-                       die_error('404 Not Found', "Ambiguous blob diff specification");
+                       die_error(400, "Ambiguous blob diff specification");
                }
 
                %diffinfo = parse_difftree_raw_line($difftree[0]);
@@ -4923,7 +4851,7 @@ sub git_blobdiff {
                        '-p', ($format eq 'html' ? "--full-index" : ()),
                        $hash_parent_base, $hash_base,
                        "--", (defined $file_parent ? $file_parent : ()), $file_name
-                       or die_error(undef, "Open git-diff-tree failed");
+                       or die_error(500, "Open git-diff-tree failed");
        }
 
        # old/legacy style URI
@@ -4959,9 +4887,9 @@ sub git_blobdiff {
                open $fd, "-|", git_cmd(), "diff", @diff_opts,
                        '-p', ($format eq 'html' ? "--full-index" : ()),
                        $hash_parent, $hash, "--"
-                       or die_error(undef, "Open git-diff failed");
+                       or die_error(500, "Open git-diff failed");
        } else  {
-               die_error('404 Not Found', "Missing one of the blob diff parameters")
+               die_error(400, "Missing one of the blob diff parameters")
                        unless %diffinfo;
        }
 
@@ -4994,7 +4922,7 @@ sub git_blobdiff {
                print "X-Git-Url: " . $cgi->self_url() . "\n\n";
 
        } else {
-               die_error(undef, "Unknown blobdiff format");
+               die_error(400, "Unknown blobdiff format");
        }
 
        # patch
@@ -5029,10 +4957,8 @@ sub git_blobdiff_plain {
 sub git_commitdiff {
        my $format = shift || 'html';
        $hash ||= $hash_base || "HEAD";
-       my %co = parse_commit($hash);
-       if (!%co) {
-               die_error(undef, "Unknown commit object");
-       }
+       my %co = parse_commit($hash)
+           or die_error(404, "Unknown commit object");
 
        # choose format for commitdiff for merge
        if (! defined $hash_parent && @{$co{'parents'}} > 1) {
@@ -5114,7 +5040,7 @@ sub git_commitdiff {
                open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts,
                        "--no-commit-id", "--patch-with-raw", "--full-index",
                        $hash_parent_param, $hash, "--"
-                       or die_error(undef, "Open git-diff-tree failed");
+                       or die_error(500, "Open git-diff-tree failed");
 
                while (my $line = <$fd>) {
                        chomp $line;
@@ -5126,10 +5052,10 @@ sub git_commitdiff {
        } elsif ($format eq 'plain') {
                open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts,
                        '-p', $hash_parent_param, $hash, "--"
-                       or die_error(undef, "Open git-diff-tree failed");
+                       or die_error(500, "Open git-diff-tree failed");
 
        } else {
-               die_error(undef, "Unknown commitdiff format");
+               die_error(400, "Unknown commitdiff format");
        }
 
        # non-textual hash id's can be cached
@@ -5212,19 +5138,15 @@ sub git_history {
                $page = 0;
        }
        my $ftype;
-       my %co = parse_commit($hash_base);
-       if (!%co) {
-               die_error(undef, "Unknown commit object");
-       }
+       my %co = parse_commit($hash_base)
+           or die_error(404, "Unknown commit object");
 
        my $refs = git_get_references();
        my $limit = sprintf("--max-count=%i", (100 * ($page+1)));
 
        my @commitlist = parse_commits($hash_base, 101, (100 * $page),
-                                      $file_name, "--full-history");
-       if (!@commitlist) {
-               die_error('404 Not Found', "No such file or directory on given branch");
-       }
+                                      $file_name, "--full-history")
+           or die_error(404, "No such file or directory on given branch");
 
        if (!defined $hash && defined $file_name) {
                # some commits could have deleted file in question,
@@ -5238,7 +5160,7 @@ sub git_history {
                $ftype = git_get_type($hash);
        }
        if (!defined $ftype) {
-               die_error(undef, "Unknown type of object");
+               die_error(500, "Unknown type of object");
        }
 
        my $paging_nav = '';
@@ -5276,19 +5198,16 @@ sub git_history {
 }
 
 sub git_search {
-       my ($have_search) = gitweb_check_feature('search');
-       if (!$have_search) {
-               die_error('403 Permission denied', "Permission denied");
-       }
+       gitweb_check_feature('search') or die_error(403, "Search is disabled");
        if (!defined $searchtext) {
-               die_error(undef, "Text field empty");
+               die_error(400, "Text field is empty");
        }
        if (!defined $hash) {
                $hash = git_get_head_hash($project);
        }
        my %co = parse_commit($hash);
        if (!%co) {
-               die_error(undef, "Unknown commit object");
+               die_error(404, "Unknown commit object");
        }
        if (!defined $page) {
                $page = 0;
@@ -5298,16 +5217,12 @@ sub git_search {
        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
-               my ($have_pickaxe) = gitweb_check_feature('pickaxe');
-               if (!$have_pickaxe) {
-                       die_error('403 Permission denied', "Permission denied");
-               }
+               gitweb_check_feature('pickaxe')
+                   or die_error(403, "Pickaxe is disabled");
        }
        if ($searchtype eq 'grep') {
-               my ($have_grep) = gitweb_check_feature('grep');
-               if (!$have_grep) {
-                       die_error('403 Permission denied', "Permission denied");
-               }
+               gitweb_check_feature('grep')
+                   or die_error(403, "Grep is disabled");
        }
 
        git_header_html();
@@ -5581,7 +5496,7 @@ sub git_feed {
        # Atom: http://www.atomenabled.org/developers/syndication/
        # RSS:  http://www.notestips.com/80256B3A007F2692/1/NAMO5P9UPQ
        if ($format ne 'rss' && $format ne 'atom') {
-               die_error(undef, "Unknown web feed format");
+               die_error(400, "Unknown web feed format");
        }
 
        # log/feed of current (HEAD) branch, log of given branch, history of file/directory
diff --git a/help.c b/help.c
index 8aff94c64a1204f8a359e522a554f29c8f0fdc20..ca9632b6c58267776086f48e87e2236ff1f6053f 100644 (file)
--- a/help.c
+++ b/help.c
@@ -391,6 +391,32 @@ static void pretty_print_string_list(struct cmdnames *cmds, int longest)
        }
 }
 
+static int is_executable(const char *name)
+{
+       struct stat st;
+
+       if (stat(name, &st) || /* stat, not lstat */
+           !S_ISREG(st.st_mode))
+               return 0;
+
+#ifdef __MINGW32__
+       /* cannot trust the executable bit, peek into the file instead */
+       char buf[3] = { 0 };
+       int n;
+       int fd = open(name, O_RDONLY);
+       st.st_mode &= ~S_IXUSR;
+       if (fd >= 0) {
+               n = read(fd, buf, 2);
+               if (n == 2)
+                       /* DOS executables start with "MZ" */
+                       if (!strcmp(buf, "#!") || !strcmp(buf, "MZ"))
+                               st.st_mode |= S_IXUSR;
+               close(fd);
+       }
+#endif
+       return st.st_mode & S_IXUSR;
+}
+
 static unsigned int list_commands_in_dir(struct cmdnames *cmds,
                                         const char *path)
 {
@@ -404,15 +430,12 @@ static unsigned int list_commands_in_dir(struct cmdnames *cmds,
                return 0;
 
        while ((de = readdir(dir)) != NULL) {
-               struct stat st;
                int entlen;
 
                if (prefixcmp(de->d_name, prefix))
                        continue;
 
-               if (stat(de->d_name, &st) || /* stat, not lstat */
-                   !S_ISREG(st.st_mode) ||
-                   !(st.st_mode & S_IXUSR))
+               if (!is_executable(de->d_name))
                        continue;
 
                entlen = strlen(de->d_name) - prefix_len;
@@ -447,7 +470,7 @@ static unsigned int load_command_list(void)
 
        path = paths = xstrdup(env_path);
        while (1) {
-               if ((colon = strchr(path, ':')))
+               if ((colon = strchr(path, PATH_SEP)))
                        *colon = 0;
 
                len = list_commands_in_dir(&other_cmds, path);
@@ -527,20 +550,26 @@ static int is_git_command(const char *s)
                is_in_cmdlist(&other_cmds, s);
 }
 
+static const char *prepend(const char *prefix, const char *cmd)
+{
+       size_t pre_len = strlen(prefix);
+       size_t cmd_len = strlen(cmd);
+       char *p = xmalloc(pre_len + cmd_len + 1);
+       memcpy(p, prefix, pre_len);
+       strcpy(p + pre_len, cmd);
+       return p;
+}
+
 static const char *cmd_to_page(const char *git_cmd)
 {
        if (!git_cmd)
                return "git";
        else if (!prefixcmp(git_cmd, "git"))
                return git_cmd;
-       else {
-               int page_len = strlen(git_cmd) + 4;
-               char *p = xmalloc(page_len + 1);
-               strcpy(p, "git-");
-               strcpy(p + 4, git_cmd);
-               p[page_len] = 0;
-               return p;
-       }
+       else if (is_git_command(git_cmd))
+               return prepend("git-", git_cmd);
+       else
+               return prepend("git", git_cmd);
 }
 
 static void setup_man_path(void)
index 665712a85de3fb4bba3a879753b60ece64a4243a..2cd068a6f1ef0199cc27a1564678c91b66237a9b 100644 (file)
@@ -783,7 +783,7 @@ static void finish_request(struct transfer_request *request)
                                        lst = &((*lst)->next);
                                *lst = (*lst)->next;
 
-                               if (!verify_pack(target, 0))
+                               if (!verify_pack(target))
                                        install_packed_git(target);
                                else
                                        remote->can_update_info_refs = 0;
index 99f397e32b673e289c2f9d298b1287a97cb7a49e..51c18f2685aa1bdb7e4ed471d0ec5d31c6684fda 100644 (file)
@@ -795,7 +795,7 @@ static int fetch_pack(struct walker *walker, struct alt_base *repo, unsigned cha
                lst = &((*lst)->next);
        *lst = (*lst)->next;
 
-       if (verify_pack(target, 0))
+       if (verify_pack(target))
                return -1;
        install_packed_git(target);
 
index 5ac91baf98615d7e494550155c1c4d7665ed2dcd..25db5db24b239409657510e8c2eeb3845b374bbf 100644 (file)
@@ -190,7 +190,8 @@ static void parse_pack_header(void)
        if (hdr->hdr_signature != htonl(PACK_SIGNATURE))
                die("pack signature mismatch");
        if (!pack_version_ok(hdr->hdr_version))
-               die("pack version %d unsupported", ntohl(hdr->hdr_version));
+               die("pack version %"PRIu32" unsupported",
+                       ntohl(hdr->hdr_version));
 
        nr_objects = ntohl(hdr->hdr_entries);
        use(sizeof(struct pack_header));
@@ -771,7 +772,8 @@ static int git_index_pack_config(const char *k, const char *v, void *cb)
        if (!strcmp(k, "pack.indexversion")) {
                pack_idx_default_version = git_config_int(k, v);
                if (pack_idx_default_version > 2)
-                       die("bad pack.indexversion=%d", pack_idx_default_version);
+                       die("bad pack.indexversion=%"PRIu32,
+                               pack_idx_default_version);
                return 0;
        }
        return git_default_config(k, v, cb);
index f4898732dd8cd8ad2d8599cb13e0d9d96dda753b..f596bf2db5e0a0065e6856b8caa3ded8a134f74d 100644 (file)
@@ -4,8 +4,9 @@
 
 struct idx_entry
 {
-       const unsigned char *sha1;
        off_t                offset;
+       const unsigned char *sha1;
+       unsigned int nr;
 };
 
 static int compare_entries(const void *e1, const void *e2)
@@ -19,6 +20,28 @@ static int compare_entries(const void *e1, const void *e2)
        return 0;
 }
 
+int check_pack_crc(struct packed_git *p, struct pack_window **w_curs,
+                  off_t offset, off_t len, unsigned int nr)
+{
+       const uint32_t *index_crc;
+       uint32_t data_crc = crc32(0, Z_NULL, 0);
+
+       do {
+               unsigned int avail;
+               void *data = use_pack(p, w_curs, offset, &avail);
+               if (avail > len)
+                       avail = len;
+               data_crc = crc32(data_crc, data, avail);
+               offset += avail;
+               len -= avail;
+       } while (len);
+
+       index_crc = p->index_data;
+       index_crc += 2 + 256 + p->num_objects * (20/4) + nr;
+
+       return data_crc != ntohl(*index_crc);
+}
+
 static int verify_packfile(struct packed_git *p,
                struct pack_window **w_curs)
 {
@@ -61,15 +84,15 @@ static int verify_packfile(struct packed_git *p,
         * we do not do scan-streaming check on the pack file.
         */
        nr_objects = p->num_objects;
-       entries = xmalloc(nr_objects * sizeof(*entries));
+       entries = xmalloc((nr_objects + 1) * sizeof(*entries));
+       entries[nr_objects].offset = pack_sig_ofs;
        /* first sort entries by pack offset, since unpacking them is more efficient that way */
        for (i = 0; i < nr_objects; i++) {
                entries[i].sha1 = nth_packed_object_sha1(p, i);
                if (!entries[i].sha1)
                        die("internal error pack-check nth-packed-object");
-               entries[i].offset = find_pack_entry_one(entries[i].sha1, p);
-               if (!entries[i].offset)
-                       die("internal error pack-check find-pack-entry-one");
+               entries[i].offset = nth_packed_object_offset(p, i);
+               entries[i].nr = i;
        }
        qsort(entries, nr_objects, sizeof(*entries), compare_entries);
 
@@ -78,6 +101,16 @@ static int verify_packfile(struct packed_git *p,
                enum object_type type;
                unsigned long size;
 
+               if (p->index_version > 1) {
+                       off_t offset = entries[i].offset;
+                       off_t len = entries[i+1].offset - offset;
+                       unsigned int nr = entries[i].nr;
+                       if (check_pack_crc(p, w_curs, offset, len, nr))
+                               err = error("index CRC mismatch for object %s "
+                                           "from %s at offset %"PRIuMAX"",
+                                           sha1_to_hex(entries[i].sha1),
+                                           p->pack_name, (uintmax_t)offset);
+               }
                data = unpack_entry(p, entries[i].offset, &type, &size);
                if (!data) {
                        err = error("cannot unpack %s from %s at offset %"PRIuMAX"",
@@ -98,63 +131,7 @@ static int verify_packfile(struct packed_git *p,
        return err;
 }
 
-
-#define MAX_CHAIN 50
-
-static void show_pack_info(struct packed_git *p)
-{
-       uint32_t nr_objects, i, chain_histogram[MAX_CHAIN+1];
-
-       nr_objects = p->num_objects;
-       memset(chain_histogram, 0, sizeof(chain_histogram));
-       init_pack_revindex();
-
-       for (i = 0; i < nr_objects; i++) {
-               const unsigned char *sha1;
-               unsigned char base_sha1[20];
-               const char *type;
-               unsigned long size;
-               unsigned long store_size;
-               off_t offset;
-               unsigned int delta_chain_length;
-
-               sha1 = nth_packed_object_sha1(p, i);
-               if (!sha1)
-                       die("internal error pack-check nth-packed-object");
-               offset = find_pack_entry_one(sha1, p);
-               if (!offset)
-                       die("internal error pack-check find-pack-entry-one");
-
-               type = packed_object_info_detail(p, offset, &size, &store_size,
-                                                &delta_chain_length,
-                                                base_sha1);
-               printf("%s ", sha1_to_hex(sha1));
-               if (!delta_chain_length)
-                       printf("%-6s %lu %lu %"PRIuMAX"\n",
-                              type, size, store_size, (uintmax_t)offset);
-               else {
-                       printf("%-6s %lu %lu %"PRIuMAX" %u %s\n",
-                              type, size, store_size, (uintmax_t)offset,
-                              delta_chain_length, sha1_to_hex(base_sha1));
-                       if (delta_chain_length <= MAX_CHAIN)
-                               chain_histogram[delta_chain_length]++;
-                       else
-                               chain_histogram[0]++;
-               }
-       }
-
-       for (i = 0; i <= MAX_CHAIN; i++) {
-               if (!chain_histogram[i])
-                       continue;
-               printf("chain length = %d: %d object%s\n", i,
-                      chain_histogram[i], chain_histogram[i] > 1 ? "s" : "");
-       }
-       if (chain_histogram[0])
-               printf("chain length > %d: %d object%s\n", MAX_CHAIN,
-                      chain_histogram[0], chain_histogram[0] > 1 ? "s" : "");
-}
-
-int verify_pack(struct packed_git *p, int verbose)
+int verify_pack(struct packed_git *p)
 {
        off_t index_size;
        const unsigned char *index_base;
@@ -180,14 +157,5 @@ int verify_pack(struct packed_git *p, int verbose)
        err |= verify_packfile(p, &w_curs);
        unuse_pack(&w_curs);
 
-       if (verbose) {
-               if (err)
-                       printf("%s: bad\n", p->pack_name);
-               else {
-                       show_pack_info(p);
-                       printf("%s: ok\n", p->pack_name);
-               }
-       }
-
        return err;
 }
diff --git a/pack-refs.c b/pack-refs.c
new file mode 100644 (file)
index 0000000..848d311
--- /dev/null
@@ -0,0 +1,117 @@
+#include "cache.h"
+#include "refs.h"
+#include "tag.h"
+#include "pack-refs.h"
+
+struct ref_to_prune {
+       struct ref_to_prune *next;
+       unsigned char sha1[20];
+       char name[FLEX_ARRAY];
+};
+
+struct pack_refs_cb_data {
+       unsigned int flags;
+       struct ref_to_prune *ref_to_prune;
+       FILE *refs_file;
+};
+
+static int do_not_prune(int flags)
+{
+       /* If it is already packed or if it is a symref,
+        * do not prune it.
+        */
+       return (flags & (REF_ISSYMREF|REF_ISPACKED));
+}
+
+static int handle_one_ref(const char *path, const unsigned char *sha1,
+                         int flags, void *cb_data)
+{
+       struct pack_refs_cb_data *cb = cb_data;
+       int is_tag_ref;
+
+       /* Do not pack the symbolic refs */
+       if ((flags & REF_ISSYMREF))
+               return 0;
+       is_tag_ref = !prefixcmp(path, "refs/tags/");
+
+       /* ALWAYS pack refs that were already packed or are tags */
+       if (!(cb->flags & PACK_REFS_ALL) && !is_tag_ref && !(flags & REF_ISPACKED))
+               return 0;
+
+       fprintf(cb->refs_file, "%s %s\n", sha1_to_hex(sha1), path);
+       if (is_tag_ref) {
+               struct object *o = parse_object(sha1);
+               if (o->type == OBJ_TAG) {
+                       o = deref_tag(o, path, 0);
+                       if (o)
+                               fprintf(cb->refs_file, "^%s\n",
+                                       sha1_to_hex(o->sha1));
+               }
+       }
+
+       if ((cb->flags & PACK_REFS_PRUNE) && !do_not_prune(flags)) {
+               int namelen = strlen(path) + 1;
+               struct ref_to_prune *n = xcalloc(1, sizeof(*n) + namelen);
+               hashcpy(n->sha1, sha1);
+               strcpy(n->name, path);
+               n->next = cb->ref_to_prune;
+               cb->ref_to_prune = n;
+       }
+       return 0;
+}
+
+/* make sure nobody touched the ref, and unlink */
+static void prune_ref(struct ref_to_prune *r)
+{
+       struct ref_lock *lock = lock_ref_sha1(r->name + 5, r->sha1);
+
+       if (lock) {
+               unlink(git_path("%s", r->name));
+               unlock_ref(lock);
+       }
+}
+
+static void prune_refs(struct ref_to_prune *r)
+{
+       while (r) {
+               prune_ref(r);
+               r = r->next;
+       }
+}
+
+static struct lock_file packed;
+
+int pack_refs(unsigned int flags)
+{
+       int fd;
+       struct pack_refs_cb_data cbdata;
+
+       memset(&cbdata, 0, sizeof(cbdata));
+       cbdata.flags = flags;
+
+       fd = hold_lock_file_for_update(&packed, git_path("packed-refs"), 1);
+       cbdata.refs_file = fdopen(fd, "w");
+       if (!cbdata.refs_file)
+               die("unable to create ref-pack file structure (%s)",
+                   strerror(errno));
+
+       /* perhaps other traits later as well */
+       fprintf(cbdata.refs_file, "# pack-refs with: peeled \n");
+
+       for_each_ref(handle_one_ref, &cbdata);
+       if (ferror(cbdata.refs_file))
+               die("failed to write ref-pack file");
+       if (fflush(cbdata.refs_file) || fsync(fd) || fclose(cbdata.refs_file))
+               die("failed to write ref-pack file (%s)", strerror(errno));
+       /*
+        * Since the lock file was fdopen()'ed and then fclose()'ed above,
+        * assign -1 to the lock file descriptor so that commit_lock_file()
+        * won't try to close() it.
+        */
+       packed.fd = -1;
+       if (commit_lock_file(&packed) < 0)
+               die("unable to overwrite old ref-pack file (%s)", strerror(errno));
+       if (cbdata.flags & PACK_REFS_PRUNE)
+               prune_refs(cbdata.ref_to_prune);
+       return 0;
+}
diff --git a/pack-refs.h b/pack-refs.h
new file mode 100644 (file)
index 0000000..518acfb
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef PACK_REFS_H
+#define PACK_REFS_H
+
+/*
+ * Flags for controlling behaviour of pack_refs()
+ * PACK_REFS_PRUNE: Prune loose refs after packing
+ * PACK_REFS_ALL:   Pack _all_ refs, not just tags and already packed refs
+ */
+#define PACK_REFS_PRUNE 0x0001
+#define PACK_REFS_ALL   0x0002
+
+/*
+ * Write a packed-refs file for the current repository.
+ * flags: Combination of the above PACK_REFS_* flags.
+ */
+int pack_refs(unsigned int flags);
+
+#endif /* PACK_REFS_H */
index a8aa2cd6caefe7d37febdf5c3426cec043492b19..cd300bdff5b524a4d509ba5276e9ef21f443013d 100644 (file)
@@ -40,7 +40,7 @@ static int pack_revindex_ix(struct packed_git *p)
        return -1 - i;
 }
 
-void init_pack_revindex(void)
+static void init_pack_revindex(void)
 {
        int num;
        struct packed_git *p;
@@ -118,9 +118,11 @@ struct revindex_entry *find_pack_revindex(struct packed_git *p, off_t ofs)
        struct pack_revindex *rix;
        struct revindex_entry *revindex;
 
+       if (!pack_revindex_hashsz)
+               init_pack_revindex();
        num = pack_revindex_ix(p);
        if (num < 0)
-               die("internal error: pack revindex uninitialized");
+               die("internal error: pack revindex fubar");
 
        rix = &pack_revindex[num];
        if (!rix->revindex)
index c3527a75655470b95ab4ba0900e9c1ad6a15a35f..36a514a6cf600e7e77794e50998a9d160e30c8e9 100644 (file)
@@ -6,7 +6,6 @@ struct revindex_entry {
        unsigned int nr;
 };
 
-void init_pack_revindex(void);
 struct revindex_entry *find_pack_revindex(struct packed_git *p, off_t ofs);
 
 #endif
index f52cabe83829289dee7e44673b59a02db38918a5..a8f02699366c87de960d7637e9f69c26c2241693 100644 (file)
@@ -2,7 +2,7 @@
 #include "pack.h"
 #include "csum-file.h"
 
-uint32_t pack_idx_default_version = 1;
+uint32_t pack_idx_default_version = 2;
 uint32_t pack_idx_off32_limit = 0x7fffffff;
 
 static int sha1_compare(const void *_a, const void *_b)
diff --git a/pack.h b/pack.h
index b31b37608d7f1901c74a20552770c306e633670c..76e6aa2aad06545e7c44fc2c1e117ea668356ccf 100644 (file)
--- a/pack.h
+++ b/pack.h
@@ -56,8 +56,8 @@ struct pack_idx_entry {
 };
 
 extern char *write_idx_file(char *index_name, struct pack_idx_entry **objects, int nr_objects, unsigned char *sha1);
-
-extern int verify_pack(struct packed_git *, int);
+extern int check_pack_crc(struct packed_git *p, struct pack_window **w_curs, off_t offset, off_t len, unsigned int nr);
+extern int verify_pack(struct packed_git *);
 extern void fixup_pack_header_footer(int, unsigned char *, const char *, uint32_t);
 extern char *index_pack_lockfile(int fd);
 
diff --git a/pager.c b/pager.c
index dbd941421bf90bb1c4b6ad26ba46869f57d15cd8..6b5c9e44b4ded338ddb344ae454d83a685b7569a 100644 (file)
--- a/pager.c
+++ b/pager.c
@@ -1,12 +1,13 @@
 #include "cache.h"
 
 /*
- * This is split up from the rest of git so that we might do
- * something different on Windows, for example.
+ * This is split up from the rest of git so that we can do
+ * something different on Windows.
  */
 
 static int spawned_pager;
 
+#ifndef __MINGW32__
 static void run_pager(const char *pager)
 {
        /*
@@ -22,11 +23,31 @@ static void run_pager(const char *pager)
        execlp(pager, pager, NULL);
        execl("/bin/sh", "sh", "-c", pager, NULL);
 }
+#else
+#include "run-command.h"
+
+static const char *pager_argv[] = { "sh", "-c", NULL, NULL };
+static struct child_process pager_process = {
+       .argv = pager_argv,
+       .in = -1
+};
+static void wait_for_pager(void)
+{
+       fflush(stdout);
+       fflush(stderr);
+       /* signal EOF to pager */
+       close(1);
+       close(2);
+       finish_command(&pager_process);
+}
+#endif
 
 void setup_pager(void)
 {
+#ifndef __MINGW32__
        pid_t pid;
        int fd[2];
+#endif
        const char *pager = getenv("GIT_PAGER");
 
        if (!isatty(1))
@@ -45,6 +66,7 @@ void setup_pager(void)
 
        spawned_pager = 1; /* means we are emitting to terminal */
 
+#ifndef __MINGW32__
        if (pipe(fd) < 0)
                return;
        pid = fork();
@@ -72,6 +94,20 @@ void setup_pager(void)
        run_pager(pager);
        die("unable to execute pager '%s'", pager);
        exit(255);
+#else
+       /* spawn the pager */
+       pager_argv[2] = pager;
+       if (start_command(&pager_process))
+               return;
+
+       /* original process continues, but writes to the pipe */
+       dup2(pager_process.in, 1);
+       dup2(pager_process.in, 2);
+       close(pager_process.in);
+
+       /* this makes sure that the parent terminates after the pager */
+       atexit(wait_for_pager);
+#endif
 }
 
 int pager_in_use(void)
index f8d52e21fe1f0bced3d4abf081f02000bbd7df62..469831d21b99e2ea6d5d0be51555d853d68a7682 100644 (file)
@@ -1,17 +1,11 @@
 #include "git-compat-util.h"
 #include "parse-options.h"
+#include "cache.h"
 
 #define OPT_SHORT 1
 #define OPT_UNSET 2
 
-struct optparse_t {
-       const char **argv;
-       const char **out;
-       int argc, cpidx;
-       const char *opt;
-};
-
-static inline const char *get_arg(struct optparse_t *p)
+static inline const char *get_arg(struct parse_opt_ctx_t *p)
 {
        if (p->opt) {
                const char *res = p->opt;
@@ -37,7 +31,7 @@ static int opterror(const struct option *opt, const char *reason, int flags)
        return error("option `%s' %s", opt->long_name, reason);
 }
 
-static int get_value(struct optparse_t *p,
+static int get_value(struct parse_opt_ctx_t *p,
                      const struct option *opt, int flags)
 {
        const char *s, *arg;
@@ -101,14 +95,14 @@ static int get_value(struct optparse_t *p,
 
        case OPTION_CALLBACK:
                if (unset)
-                       return (*opt->callback)(opt, NULL, 1);
+                       return (*opt->callback)(opt, NULL, 1) ? (-1) : 0;
                if (opt->flags & PARSE_OPT_NOARG)
-                       return (*opt->callback)(opt, NULL, 0);
+                       return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
                if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
-                       return (*opt->callback)(opt, NULL, 0);
+                       return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
                if (!arg)
                        return opterror(opt, "requires a value", flags);
-               return (*opt->callback)(opt, get_arg(p), 0);
+               return (*opt->callback)(opt, get_arg(p), 0) ? (-1) : 0;
 
        case OPTION_INTEGER:
                if (unset) {
@@ -131,7 +125,7 @@ static int get_value(struct optparse_t *p,
        }
 }
 
-static int parse_short_opt(struct optparse_t *p, const struct option *options)
+static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *options)
 {
        for (; options->type != OPTION_END; options++) {
                if (options->short_name == *p->opt) {
@@ -139,10 +133,10 @@ static int parse_short_opt(struct optparse_t *p, const struct option *options)
                        return get_value(p, options, OPT_SHORT);
                }
        }
-       return error("unknown switch `%c'", *p->opt);
+       return -2;
 }
 
-static int parse_long_opt(struct optparse_t *p, const char *arg,
+static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
                           const struct option *options)
 {
        const char *arg_end = strchr(arg, '=');
@@ -224,7 +218,7 @@ is_abbreviated:
                        abbrev_option->long_name);
        if (abbrev_option)
                return get_value(p, abbrev_option, abbrev_flags);
-       return error("unknown option `%s'", arg);
+       return -2;
 }
 
 void check_typos(const char *arg, const struct option *options)
@@ -247,73 +241,136 @@ void check_typos(const char *arg, const struct option *options)
        }
 }
 
-static NORETURN void usage_with_options_internal(const char * const *,
-                                                 const struct option *, int);
+void parse_options_start(struct parse_opt_ctx_t *ctx,
+                        int argc, const char **argv, int flags)
+{
+       memset(ctx, 0, sizeof(*ctx));
+       ctx->argc = argc - 1;
+       ctx->argv = argv + 1;
+       ctx->out  = argv;
+       ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0);
+       ctx->flags = flags;
+}
 
-int parse_options(int argc, const char **argv, const struct option *options,
-                  const char * const usagestr[], int flags)
+static int usage_with_options_internal(const char * const *,
+                                      const struct option *, int);
+
+int parse_options_step(struct parse_opt_ctx_t *ctx,
+                      const struct option *options,
+                      const char * const usagestr[])
 {
-       struct optparse_t args = { argv + 1, argv, argc - 1, 0, NULL };
+       /* we must reset ->opt, unknown short option leave it dangling */
+       ctx->opt = NULL;
 
-       for (; args.argc; args.argc--, args.argv++) {
-               const char *arg = args.argv[0];
+       for (; ctx->argc; ctx->argc--, ctx->argv++) {
+               const char *arg = ctx->argv[0];
 
                if (*arg != '-' || !arg[1]) {
-                       if (flags & PARSE_OPT_STOP_AT_NON_OPTION)
+                       if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION)
                                break;
-                       args.out[args.cpidx++] = args.argv[0];
+                       ctx->out[ctx->cpidx++] = ctx->argv[0];
                        continue;
                }
 
                if (arg[1] != '-') {
-                       args.opt = arg + 1;
-                       if (*args.opt == 'h')
-                               usage_with_options(usagestr, options);
-                       if (parse_short_opt(&args, options) < 0)
-                               usage_with_options(usagestr, options);
-                       if (args.opt)
+                       ctx->opt = arg + 1;
+                       if (*ctx->opt == 'h')
+                               return parse_options_usage(usagestr, options);
+                       switch (parse_short_opt(ctx, options)) {
+                       case -1:
+                               return parse_options_usage(usagestr, options);
+                       case -2:
+                               return PARSE_OPT_UNKNOWN;
+                       }
+                       if (ctx->opt)
                                check_typos(arg + 1, options);
-                       while (args.opt) {
-                               if (*args.opt == 'h')
-                                       usage_with_options(usagestr, options);
-                               if (parse_short_opt(&args, options) < 0)
-                                       usage_with_options(usagestr, options);
+                       while (ctx->opt) {
+                               if (*ctx->opt == 'h')
+                                       return parse_options_usage(usagestr, options);
+                               switch (parse_short_opt(ctx, options)) {
+                               case -1:
+                                       return parse_options_usage(usagestr, options);
+                               case -2:
+                                       /* fake a short option thing to hide the fact that we may have
+                                        * started to parse aggregated stuff
+                                        *
+                                        * This is leaky, too bad.
+                                        */
+                                       ctx->argv[0] = xstrdup(ctx->opt - 1);
+                                       *(char *)ctx->argv[0] = '-';
+                                       return PARSE_OPT_UNKNOWN;
+                               }
                        }
                        continue;
                }
 
                if (!arg[2]) { /* "--" */
-                       if (!(flags & PARSE_OPT_KEEP_DASHDASH)) {
-                               args.argc--;
-                               args.argv++;
+                       if (!(ctx->flags & PARSE_OPT_KEEP_DASHDASH)) {
+                               ctx->argc--;
+                               ctx->argv++;
                        }
                        break;
                }
 
                if (!strcmp(arg + 2, "help-all"))
-                       usage_with_options_internal(usagestr, options, 1);
+                       return usage_with_options_internal(usagestr, options, 1);
                if (!strcmp(arg + 2, "help"))
-                       usage_with_options(usagestr, options);
-               if (parse_long_opt(&args, arg + 2, options))
-                       usage_with_options(usagestr, options);
+                       return parse_options_usage(usagestr, options);
+               switch (parse_long_opt(ctx, arg + 2, options)) {
+               case -1:
+                       return parse_options_usage(usagestr, options);
+               case -2:
+                       return PARSE_OPT_UNKNOWN;
+               }
+       }
+       return PARSE_OPT_DONE;
+}
+
+int parse_options_end(struct parse_opt_ctx_t *ctx)
+{
+       memmove(ctx->out + ctx->cpidx, ctx->argv, ctx->argc * sizeof(*ctx->out));
+       ctx->out[ctx->cpidx + ctx->argc] = NULL;
+       return ctx->cpidx + ctx->argc;
+}
+
+int parse_options(int argc, const char **argv, const struct option *options,
+                 const char * const usagestr[], int flags)
+{
+       struct parse_opt_ctx_t ctx;
+
+       parse_options_start(&ctx, argc, argv, flags);
+       switch (parse_options_step(&ctx, options, usagestr)) {
+       case PARSE_OPT_HELP:
+               exit(129);
+       case PARSE_OPT_DONE:
+               break;
+       default: /* PARSE_OPT_UNKNOWN */
+               if (ctx.argv[0][1] == '-') {
+                       error("unknown option `%s'", ctx.argv[0] + 2);
+               } else {
+                       error("unknown switch `%c'", *ctx.opt);
+               }
+               usage_with_options(usagestr, options);
        }
 
-       memmove(args.out + args.cpidx, args.argv, args.argc * sizeof(*args.out));
-       args.out[args.cpidx + args.argc] = NULL;
-       return args.cpidx + args.argc;
+       return parse_options_end(&ctx);
 }
 
 #define USAGE_OPTS_WIDTH 24
 #define USAGE_GAP         2
 
-void usage_with_options_internal(const char * const *usagestr,
-                                 const struct option *opts, int full)
+int usage_with_options_internal(const char * const *usagestr,
+                               const struct option *opts, int full)
 {
        fprintf(stderr, "usage: %s\n", *usagestr++);
        while (*usagestr && **usagestr)
                fprintf(stderr, "   or: %s\n", *usagestr++);
-       while (*usagestr)
-               fprintf(stderr, "    %s\n", *usagestr++);
+       while (*usagestr) {
+               fprintf(stderr, "%s%s\n",
+                               **usagestr ? "    " : "",
+                               *usagestr);
+               usagestr++;
+       }
 
        if (opts->type != OPTION_GROUP)
                fputc('\n', stderr);
@@ -388,15 +445,23 @@ void usage_with_options_internal(const char * const *usagestr,
        }
        fputc('\n', stderr);
 
-       exit(129);
+       return PARSE_OPT_HELP;
 }
 
 void usage_with_options(const char * const *usagestr,
-                        const struct option *opts)
+                       const struct option *opts)
 {
        usage_with_options_internal(usagestr, opts, 0);
+       exit(129);
 }
 
+int parse_options_usage(const char * const *usagestr,
+                       const struct option *opts)
+{
+       return usage_with_options_internal(usagestr, opts, 0);
+}
+
+
 /*----- some often used options -----*/
 #include "cache.h"
 
index 4ee443dafe146f05d1fe2a46e7e39ca6fdd608f9..c5f0b4b4dabb5a40027c0cc588549904e0efcc6f 100644 (file)
@@ -20,6 +20,7 @@ enum parse_opt_type {
 enum parse_opt_flags {
        PARSE_OPT_KEEP_DASHDASH = 1,
        PARSE_OPT_STOP_AT_NON_OPTION = 2,
+       PARSE_OPT_KEEP_ARGV0 = 4,
 };
 
 enum parse_opt_option_flags {
@@ -111,6 +112,40 @@ extern int parse_options(int argc, const char **argv,
 extern NORETURN void usage_with_options(const char * const *usagestr,
                                         const struct option *options);
 
+/*----- incremantal advanced APIs -----*/
+
+enum {
+       PARSE_OPT_HELP = -1,
+       PARSE_OPT_DONE,
+       PARSE_OPT_UNKNOWN,
+};
+
+/*
+ * It's okay for the caller to consume argv/argc in the usual way.
+ * Other fields of that structure are private to parse-options and should not
+ * be modified in any way.
+ */
+struct parse_opt_ctx_t {
+       const char **argv;
+       const char **out;
+       int argc, cpidx;
+       const char *opt;
+       int flags;
+};
+
+extern int parse_options_usage(const char * const *usagestr,
+                              const struct option *opts);
+
+extern void parse_options_start(struct parse_opt_ctx_t *ctx,
+                               int argc, const char **argv, int flags);
+
+extern int parse_options_step(struct parse_opt_ctx_t *ctx,
+                             const struct option *options,
+                             const char * const usagestr[]);
+
+extern int parse_options_end(struct parse_opt_ctx_t *ctx);
+
+
 /*----- some often used options -----*/
 extern int parse_opt_abbrev_cb(const struct option *, const char *, int);
 extern int parse_opt_approxidate_cb(const struct option *, const char *, int);
diff --git a/path.c b/path.c
index 6e3df1849965be6a88fac89c007f9b5fe960f825..504eae061fe27e846f67f3e1c25d51e886420b62 100644 (file)
--- a/path.c
+++ b/path.c
@@ -272,7 +272,7 @@ int adjust_shared_perm(const char *path)
                int tweak = shared_repository;
                if (!(mode & S_IWUSR))
                        tweak &= ~0222;
-               mode = (mode & ~0777) | tweak;
+               mode |= tweak;
        } else {
                /* Preserve old PERM_UMASK behaviour */
                if (mode & S_IWUSR)
@@ -327,9 +327,6 @@ const char *make_nonrelative_path(const char *path)
        return buf;
 }
 
-/* We allow "recursive" symbolic links. Only within reason, though. */
-#define MAXDEPTH 5
-
 const char *make_relative_path(const char *abs, const char *base)
 {
        static char buf[PATH_MAX + 1];
@@ -347,66 +344,98 @@ const char *make_relative_path(const char *abs, const char *base)
        return buf;
 }
 
-const char *make_absolute_path(const char *path)
+/*
+ * path = absolute path
+ * buf = buffer of at least max(2, strlen(path)+1) bytes
+ * It is okay if buf == path, but they should not overlap otherwise.
+ *
+ * Performs the following normalizations on path, storing the result in buf:
+ * - Removes trailing slashes.
+ * - Removes empty components.
+ * - Removes "." components.
+ * - Removes ".." components, and the components the precede them.
+ * "" and paths that contain only slashes are normalized to "/".
+ * Returns the length of the output.
+ *
+ * Note that this function is purely textual.  It does not follow symlinks,
+ * verify the existence of the path, or make any system calls.
+ */
+int normalize_absolute_path(char *buf, const char *path)
 {
-       static char bufs[2][PATH_MAX + 1], *buf = bufs[0], *next_buf = bufs[1];
-       char cwd[1024] = "";
-       int buf_index = 1, len;
+       const char *comp_start = path, *comp_end = path;
+       char *dst = buf;
+       int comp_len;
+       assert(buf);
+       assert(path);
+
+       while (*comp_start) {
+               assert(*comp_start == '/');
+               while (*++comp_end && *comp_end != '/')
+                       ; /* nothing */
+               comp_len = comp_end - comp_start;
+
+               if (!strncmp("/",  comp_start, comp_len) ||
+                   !strncmp("/.", comp_start, comp_len))
+                       goto next;
+
+               if (!strncmp("/..", comp_start, comp_len)) {
+                       while (dst > buf && *--dst != '/')
+                               ; /* nothing */
+                       goto next;
+               }
 
-       int depth = MAXDEPTH;
-       char *last_elem = NULL;
-       struct stat st;
+               memcpy(dst, comp_start, comp_len);
+               dst += comp_len;
+       next:
+               comp_start = comp_end;
+       }
 
-       if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
-               die ("Too long path: %.*s", 60, path);
-
-       while (depth--) {
-               if (stat(buf, &st) || !S_ISDIR(st.st_mode)) {
-                       char *last_slash = strrchr(buf, '/');
-                       if (last_slash) {
-                               *last_slash = '\0';
-                               last_elem = xstrdup(last_slash + 1);
-                       } else {
-                               last_elem = xstrdup(buf);
-                               *buf = '\0';
-                       }
-               }
+       if (dst == buf)
+               *dst++ = '/';
+
+       *dst = '\0';
+       return dst - buf;
+}
 
-               if (*buf) {
-                       if (!*cwd && !getcwd(cwd, sizeof(cwd)))
-                               die ("Could not get current working directory");
+/*
+ * path = Canonical absolute path
+ * prefix_list = Colon-separated list of absolute paths
+ *
+ * Determines, for each path in parent_list, whether the "prefix" really
+ * is an ancestor directory of path.  Returns the length of the longest
+ * ancestor directory, excluding any trailing slashes, or -1 if no prefix
+ * is an ancestor.  (Note that this means 0 is returned if prefix_list is
+ * "/".) "/foo" is not considered an ancestor of "/foobar".  Directories
+ * are not considered to be their own ancestors.  path must be in a
+ * canonical form: empty components, or "." or ".." components are not
+ * allowed.  prefix_list may be null, which is like "".
+ */
+int longest_ancestor_length(const char *path, const char *prefix_list)
+{
+       char buf[PATH_MAX+1];
+       const char *ceil, *colon;
+       int len, max_len = -1;
 
-                       if (chdir(buf))
-                               die ("Could not switch to '%s'", buf);
-               }
-               if (!getcwd(buf, PATH_MAX))
-                       die ("Could not get current working directory");
-
-               if (last_elem) {
-                       int len = strlen(buf);
-                       if (len + strlen(last_elem) + 2 > PATH_MAX)
-                               die ("Too long path name: '%s/%s'",
-                                               buf, last_elem);
-                       buf[len] = '/';
-                       strcpy(buf + len + 1, last_elem);
-                       free(last_elem);
-                       last_elem = NULL;
-               }
+       if (prefix_list == NULL || !strcmp(path, "/"))
+               return -1;
 
-               if (!lstat(buf, &st) && S_ISLNK(st.st_mode)) {
-                       len = readlink(buf, next_buf, PATH_MAX);
-                       if (len < 0)
-                               die ("Invalid symlink: %s", buf);
-                       next_buf[len] = '\0';
-                       buf = next_buf;
-                       buf_index = 1 - buf_index;
-                       next_buf = bufs[buf_index];
-               } else
-                       break;
+       for (colon = ceil = prefix_list; *colon; ceil = colon+1) {
+               for (colon = ceil; *colon && *colon != ':'; colon++);
+               len = colon - ceil;
+               if (len == 0 || len > PATH_MAX || !is_absolute_path(ceil))
+                       continue;
+               strlcpy(buf, ceil, len+1);
+               len = normalize_absolute_path(buf, buf);
+               /* Strip "trailing slashes" from "/". */
+               if (len == 1)
+                       len = 0;
+
+               if (!strncmp(path, buf, len) &&
+                   path[len] == '/' &&
+                   len > max_len) {
+                       max_len = len;
+               }
        }
 
-       if (*cwd && chdir(cwd))
-               die ("Could not change back to '%s'", cwd);
-
-       return buf;
+       return max_len;
 }
index 97e61efaff240a60ecd25ba68d391e75ed7ce958..d99e7782002e01079b3866003cc8555b7e130e3f 100644 (file)
@@ -56,7 +56,8 @@ require Exporter;
 @EXPORT_OK = qw(command command_oneline command_noisy
                 command_output_pipe command_input_pipe command_close_pipe
                 command_bidi_pipe command_close_bidi_pipe
-                version exec_path hash_object git_cmd_try);
+                version exec_path hash_object git_cmd_try
+                remote_refs);
 
 
 =head1 DESCRIPTION
@@ -668,6 +669,59 @@ sub get_color {
        return $color;
 }
 
+=item remote_refs ( REPOSITORY [, GROUPS [, REFGLOBS ] ] )
+
+This function returns a hashref of refs stored in a given remote repository.
+The hash is in the format C<refname =\> hash>. For tags, the C<refname> entry
+contains the tag object while a C<refname^{}> entry gives the tagged objects.
+
+C<REPOSITORY> has the same meaning as the appropriate C<git-ls-remote>
+argument; either an URL or a remote name (if called on a repository instance).
+C<GROUPS> is an optional arrayref that can contain 'tags' to return all the
+tags and/or 'heads' to return all the heads. C<REFGLOB> is an optional array
+of strings containing a shell-like glob to further limit the refs returned in
+the hash; the meaning is again the same as the appropriate C<git-ls-remote>
+argument.
+
+This function may or may not be called on a repository instance. In the former
+case, remote names as defined in the repository are recognized as repository
+specifiers.
+
+=cut
+
+sub remote_refs {
+       my ($self, $repo, $groups, $refglobs) = _maybe_self(@_);
+       my @args;
+       if (ref $groups eq 'ARRAY') {
+               foreach (@$groups) {
+                       if ($_ eq 'heads') {
+                               push (@args, '--heads');
+                       } elsif ($_ eq 'tags') {
+                               push (@args, '--tags');
+                       } else {
+                               # Ignore unknown groups for future
+                               # compatibility
+                       }
+               }
+       }
+       push (@args, $repo);
+       if (ref $refglobs eq 'ARRAY') {
+               push (@args, @$refglobs);
+       }
+
+       my @self = $self ? ($self) : (); # Ultra trickery
+       my ($fh, $ctx) = Git::command_output_pipe(@self, 'ls-remote', @args);
+       my %refs;
+       while (<$fh>) {
+               chomp;
+               my ($hash, $ref) = split(/\t/, $_, 2);
+               $refs{$ref} = $hash;
+       }
+       Git::command_close_pipe(@self, $fh, $ctx);
+       return \%refs;
+}
+
+
 =item ident ( TYPE | IDENTSTR )
 
 =item ident_person ( TYPE | IDENTSTR | IDENTARRAY )
diff --git a/quote.c b/quote.c
index d5cf9d8f94f37fe8ff9f964998c7f0525617e5bc..6a520855d6c418ecb1384ef9571b122b134af1af 100644 (file)
--- a/quote.c
+++ b/quote.c
@@ -1,6 +1,8 @@
 #include "cache.h"
 #include "quote.h"
 
+int quote_path_fully = 1;
+
 /* Help to copy the thing properly quoted for the shell safety.
  * any single quote is replaced with '\'', any exclamation point
  * is replaced with '\!', and the whole thing is enclosed in a
index b26f2e3a41c870d1b73690e389dbd74a8b8a40a0..fa653b49fe3c865b7e9c3723136b5b2344f8f4ca 100644 (file)
@@ -370,7 +370,8 @@ static const char *unpack(void)
        hdr_err = parse_pack_header(&hdr);
        if (hdr_err)
                return hdr_err;
-       snprintf(hdr_arg, sizeof(hdr_arg), "--pack_header=%u,%u",
+       snprintf(hdr_arg, sizeof(hdr_arg),
+                       "--pack_header=%"PRIu32",%"PRIu32,
                        ntohl(hdr.hdr_version), ntohl(hdr.hdr_entries));
 
        if (ntohl(hdr.hdr_entries) < unpack_limit) {
diff --git a/refs.c b/refs.c
index c9bcf148b0e1cd659e645e0f793fc07ebc133426..39a3b23804d2da715c564459bf320be23d41c1bf 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -1412,6 +1412,10 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *
        tz = strtoul(tz_c, NULL, 10);
        if (get_sha1_hex(logdata, sha1))
                die("Log %s is corrupt.", logfile);
+       if (is_null_sha1(sha1)) {
+               if (get_sha1_hex(logdata + 41, sha1))
+                       die("Log %s is corrupt.", logfile);
+       }
        if (msg)
                *msg = ref_msg(logdata, logend);
        munmap(log_mapped, mapsz);
index ff2c8021678fee5ef12060d35c6eb1960e8792c7..df8bd72ba9b9728aeff0c34208a6492b7d0b692c 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -1,6 +1,9 @@
 #include "cache.h"
 #include "remote.h"
 #include "refs.h"
+#include "commit.h"
+#include "diff.h"
+#include "revision.h"
 
 static struct refspec s_tag_refspec = {
        0,
@@ -1222,3 +1225,117 @@ int resolve_remote_symref(struct ref *ref, struct ref *list)
                }
        return 1;
 }
+
+/*
+ * Return true if there is anything to report, otherwise false.
+ */
+int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs)
+{
+       unsigned char sha1[20];
+       struct commit *ours, *theirs;
+       char symmetric[84];
+       struct rev_info revs;
+       const char *rev_argv[10], *base;
+       int rev_argc;
+
+       /*
+        * Nothing to report unless we are marked to build on top of
+        * somebody else.
+        */
+       if (!branch ||
+           !branch->merge || !branch->merge[0] || !branch->merge[0]->dst)
+               return 0;
+
+       /*
+        * If what we used to build on no longer exists, there is
+        * nothing to report.
+        */
+       base = branch->merge[0]->dst;
+       if (!resolve_ref(base, sha1, 1, NULL))
+               return 0;
+       theirs = lookup_commit(sha1);
+       if (!theirs)
+               return 0;
+
+       if (!resolve_ref(branch->refname, sha1, 1, NULL))
+               return 0;
+       ours = lookup_commit(sha1);
+       if (!ours)
+               return 0;
+
+       /* are we the same? */
+       if (theirs == ours)
+               return 0;
+
+       /* Run "rev-list --left-right ours...theirs" internally... */
+       rev_argc = 0;
+       rev_argv[rev_argc++] = NULL;
+       rev_argv[rev_argc++] = "--left-right";
+       rev_argv[rev_argc++] = symmetric;
+       rev_argv[rev_argc++] = "--";
+       rev_argv[rev_argc] = NULL;
+
+       strcpy(symmetric, sha1_to_hex(ours->object.sha1));
+       strcpy(symmetric + 40, "...");
+       strcpy(symmetric + 43, sha1_to_hex(theirs->object.sha1));
+
+       init_revisions(&revs, NULL);
+       setup_revisions(rev_argc, rev_argv, &revs, NULL);
+       prepare_revision_walk(&revs);
+
+       /* ... and count the commits on each side. */
+       *num_ours = 0;
+       *num_theirs = 0;
+       while (1) {
+               struct commit *c = get_revision(&revs);
+               if (!c)
+                       break;
+               if (c->object.flags & SYMMETRIC_LEFT)
+                       (*num_ours)++;
+               else
+                       (*num_theirs)++;
+       }
+
+       /* clear object flags smudged by the above traversal */
+       clear_commit_marks(ours, ALL_REV_FLAGS);
+       clear_commit_marks(theirs, ALL_REV_FLAGS);
+       return 1;
+}
+
+/*
+ * Return true when there is anything to report, otherwise false.
+ */
+int format_tracking_info(struct branch *branch, struct strbuf *sb)
+{
+       int num_ours, num_theirs;
+       const char *base, *remote_msg;
+
+       if (!stat_tracking_info(branch, &num_ours, &num_theirs))
+               return 0;
+
+       base = branch->merge[0]->dst;
+       if (!prefixcmp(base, "refs/remotes/")) {
+               remote_msg = " remote";
+               base += strlen("refs/remotes/");
+       } else {
+               remote_msg = "";
+       }
+       if (!num_theirs)
+               strbuf_addf(sb, "Your branch is ahead of the tracked%s branch '%s' "
+                           "by %d commit%s.\n",
+                           remote_msg, base,
+                           num_ours, (num_ours == 1) ? "" : "s");
+       else if (!num_ours)
+               strbuf_addf(sb, "Your branch is behind the tracked%s branch '%s' "
+                           "by %d commit%s,\n"
+                           "and can be fast-forwarded.\n",
+                           remote_msg, base,
+                           num_theirs, (num_theirs == 1) ? "" : "s");
+       else
+               strbuf_addf(sb, "Your branch and the tracked%s branch '%s' "
+                           "have diverged,\nand respectively "
+                           "have %d and %d different commit(s) each.\n",
+                           remote_msg, base,
+                           num_ours, num_theirs);
+       return 1;
+}
index 8eed87ba5ab78eb4635632c21843590467d0d864..091b1d041f8a4d255f59bfc001e098e692dbc15c 100644 (file)
--- a/remote.h
+++ b/remote.h
@@ -129,4 +129,8 @@ enum match_refs_flags {
        MATCH_REFS_MIRROR       = (1 << 1),
 };
 
+/* Reporting of tracking info */
+int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs);
+int format_tracking_info(struct branch *branch, struct strbuf *sb);
+
 #endif
index fc667552592daa3c894d0df4e97469d1809dbf27..bbd563e6514f98ed5678314573fc4521b9fa0a95 100644 (file)
@@ -10,6 +10,7 @@
 #include "grep.h"
 #include "reflog-walk.h"
 #include "patch-ids.h"
+#include "decorate.h"
 
 volatile show_early_output_fn_t show_early_output;
 
@@ -910,6 +911,23 @@ int handle_revision_arg(const char *arg, struct rev_info *revs,
        return 0;
 }
 
+void read_revisions_from_stdin(struct rev_info *revs)
+{
+       char line[1000];
+
+       while (fgets(line, sizeof(line), stdin) != NULL) {
+               int len = strlen(line);
+               if (len && line[len - 1] == '\n')
+                       line[--len] = '\0';
+               if (!len)
+                       break;
+               if (line[0] == '-')
+                       die("options not supported in --stdin mode");
+               if (handle_revision_arg(line, revs, 0, 1))
+                       die("bad revision '%s'", line);
+       }
+}
+
 static void add_grep(struct rev_info *revs, const char *ptn, enum grep_pat_token what)
 {
        if (!revs->grep_filter) {
@@ -956,6 +974,226 @@ static void add_ignore_packed(struct rev_info *revs, const char *name)
        revs->ignore_packed[num] = NULL;
 }
 
+static int handle_revision_opt(struct rev_info *revs, int argc, const char **argv,
+                              int *unkc, const char **unkv)
+{
+       const char *arg = argv[0];
+
+       /* pseudo revision arguments */
+       if (!strcmp(arg, "--all") || !strcmp(arg, "--branches") ||
+           !strcmp(arg, "--tags") || !strcmp(arg, "--remotes") ||
+           !strcmp(arg, "--reflog") || !strcmp(arg, "--not") ||
+           !strcmp(arg, "--no-walk") || !strcmp(arg, "--do-walk"))
+       {
+               unkv[(*unkc)++] = arg;
+               return 0;
+       }
+
+       if (!prefixcmp(arg, "--max-count=")) {
+               revs->max_count = atoi(arg + 12);
+       } else if (!prefixcmp(arg, "--skip=")) {
+               revs->skip_count = atoi(arg + 7);
+       } else if ((*arg == '-') && isdigit(arg[1])) {
+       /* accept -<digit>, like traditional "head" */
+               revs->max_count = atoi(arg + 1);
+       } else if (!strcmp(arg, "-n")) {
+               if (argc <= 1)
+                       return error("-n requires an argument");
+               revs->max_count = atoi(argv[1]);
+               return 2;
+       } else if (!prefixcmp(arg, "-n")) {
+               revs->max_count = atoi(arg + 2);
+       } else if (!prefixcmp(arg, "--max-age=")) {
+               revs->max_age = atoi(arg + 10);
+       } else if (!prefixcmp(arg, "--since=")) {
+               revs->max_age = approxidate(arg + 8);
+       } else if (!prefixcmp(arg, "--after=")) {
+               revs->max_age = approxidate(arg + 8);
+       } else if (!prefixcmp(arg, "--min-age=")) {
+               revs->min_age = atoi(arg + 10);
+       } else if (!prefixcmp(arg, "--before=")) {
+               revs->min_age = approxidate(arg + 9);
+       } else if (!prefixcmp(arg, "--until=")) {
+               revs->min_age = approxidate(arg + 8);
+       } else if (!strcmp(arg, "--first-parent")) {
+               revs->first_parent_only = 1;
+       } else if (!strcmp(arg, "-g") || !strcmp(arg, "--walk-reflogs")) {
+               init_reflog_walk(&revs->reflog_info);
+       } else if (!strcmp(arg, "--default")) {
+               if (argc <= 1)
+                       return error("bad --default argument");
+               revs->def = argv[1];
+               return 2;
+       } else if (!strcmp(arg, "--merge")) {
+               revs->show_merge = 1;
+       } else if (!strcmp(arg, "--topo-order")) {
+               revs->lifo = 1;
+               revs->topo_order = 1;
+       } else if (!strcmp(arg, "--date-order")) {
+               revs->lifo = 0;
+               revs->topo_order = 1;
+       } else if (!prefixcmp(arg, "--early-output")) {
+               int count = 100;
+               switch (arg[14]) {
+               case '=':
+                       count = atoi(arg+15);
+                       /* Fallthrough */
+               case 0:
+                       revs->topo_order = 1;
+                      revs->early_output = count;
+               }
+       } else if (!strcmp(arg, "--parents")) {
+               revs->rewrite_parents = 1;
+               revs->print_parents = 1;
+       } else if (!strcmp(arg, "--dense")) {
+               revs->dense = 1;
+       } else if (!strcmp(arg, "--sparse")) {
+               revs->dense = 0;
+       } else if (!strcmp(arg, "--show-all")) {
+               revs->show_all = 1;
+       } else if (!strcmp(arg, "--remove-empty")) {
+               revs->remove_empty_trees = 1;
+       } else if (!strcmp(arg, "--no-merges")) {
+               revs->no_merges = 1;
+       } else if (!strcmp(arg, "--boundary")) {
+               revs->boundary = 1;
+       } else if (!strcmp(arg, "--left-right")) {
+               revs->left_right = 1;
+       } else if (!strcmp(arg, "--cherry-pick")) {
+               revs->cherry_pick = 1;
+               revs->limited = 1;
+       } else if (!strcmp(arg, "--objects")) {
+               revs->tag_objects = 1;
+               revs->tree_objects = 1;
+               revs->blob_objects = 1;
+       } else if (!strcmp(arg, "--objects-edge")) {
+               revs->tag_objects = 1;
+               revs->tree_objects = 1;
+               revs->blob_objects = 1;
+               revs->edge_hint = 1;
+       } else if (!strcmp(arg, "--unpacked")) {
+               revs->unpacked = 1;
+               free(revs->ignore_packed);
+               revs->ignore_packed = NULL;
+               revs->num_ignore_packed = 0;
+       } else if (!prefixcmp(arg, "--unpacked=")) {
+               revs->unpacked = 1;
+               add_ignore_packed(revs, arg+11);
+       } else if (!strcmp(arg, "-r")) {
+               revs->diff = 1;
+               DIFF_OPT_SET(&revs->diffopt, RECURSIVE);
+       } else if (!strcmp(arg, "-t")) {
+               revs->diff = 1;
+               DIFF_OPT_SET(&revs->diffopt, RECURSIVE);
+               DIFF_OPT_SET(&revs->diffopt, TREE_IN_RECURSIVE);
+       } else if (!strcmp(arg, "-m")) {
+               revs->ignore_merges = 0;
+       } else if (!strcmp(arg, "-c")) {
+               revs->diff = 1;
+               revs->dense_combined_merges = 0;
+               revs->combine_merges = 1;
+       } else if (!strcmp(arg, "--cc")) {
+               revs->diff = 1;
+               revs->dense_combined_merges = 1;
+               revs->combine_merges = 1;
+       } else if (!strcmp(arg, "-v")) {
+               revs->verbose_header = 1;
+       } else if (!strcmp(arg, "--pretty")) {
+               revs->verbose_header = 1;
+               get_commit_format(arg+8, revs);
+       } else if (!prefixcmp(arg, "--pretty=")) {
+               revs->verbose_header = 1;
+               get_commit_format(arg+9, revs);
+       } else if (!strcmp(arg, "--graph")) {
+               revs->topo_order = 1;
+               revs->rewrite_parents = 1;
+               revs->graph = graph_init(revs);
+       } else if (!strcmp(arg, "--root")) {
+               revs->show_root_diff = 1;
+       } else if (!strcmp(arg, "--no-commit-id")) {
+               revs->no_commit_id = 1;
+       } else if (!strcmp(arg, "--always")) {
+               revs->always_show_header = 1;
+       } else if (!strcmp(arg, "--no-abbrev")) {
+               revs->abbrev = 0;
+       } else if (!strcmp(arg, "--abbrev")) {
+               revs->abbrev = DEFAULT_ABBREV;
+       } else if (!prefixcmp(arg, "--abbrev=")) {
+               revs->abbrev = strtoul(arg + 9, NULL, 10);
+               if (revs->abbrev < MINIMUM_ABBREV)
+                       revs->abbrev = MINIMUM_ABBREV;
+               else if (revs->abbrev > 40)
+                       revs->abbrev = 40;
+       } else if (!strcmp(arg, "--abbrev-commit")) {
+               revs->abbrev_commit = 1;
+       } else if (!strcmp(arg, "--full-diff")) {
+               revs->diff = 1;
+               revs->full_diff = 1;
+       } else if (!strcmp(arg, "--full-history")) {
+               revs->simplify_history = 0;
+       } else if (!strcmp(arg, "--relative-date")) {
+               revs->date_mode = DATE_RELATIVE;
+       } else if (!strncmp(arg, "--date=", 7)) {
+               revs->date_mode = parse_date_format(arg + 7);
+       } else if (!strcmp(arg, "--log-size")) {
+               revs->show_log_size = 1;
+       }
+       /*
+        * Grepping the commit log
+        */
+       else if (!prefixcmp(arg, "--author=")) {
+               add_header_grep(revs, "author", arg+9);
+       } else if (!prefixcmp(arg, "--committer=")) {
+               add_header_grep(revs, "committer", arg+12);
+       } else if (!prefixcmp(arg, "--grep=")) {
+               add_message_grep(revs, arg+7);
+       } else if (!strcmp(arg, "--extended-regexp") || !strcmp(arg, "-E")) {
+               if (revs->grep_filter)
+                       revs->grep_filter->regflags |= REG_EXTENDED;
+       } else if (!strcmp(arg, "--regexp-ignore-case") || !strcmp(arg, "-i")) {
+               if (revs->grep_filter)
+                       revs->grep_filter->regflags |= REG_ICASE;
+       } else if (!strcmp(arg, "--fixed-strings") || !strcmp(arg, "-F")) {
+               if (revs->grep_filter)
+                       revs->grep_filter->fixed = 1;
+       } else if (!strcmp(arg, "--all-match")) {
+               if (revs->grep_filter)
+                       revs->grep_filter->all_match = 1;
+       } else if (!prefixcmp(arg, "--encoding=")) {
+               arg += 11;
+               if (strcmp(arg, "none"))
+                       git_log_output_encoding = xstrdup(arg);
+               else
+                       git_log_output_encoding = "";
+       } else if (!strcmp(arg, "--reverse")) {
+               revs->reverse ^= 1;
+       } else if (!strcmp(arg, "--children")) {
+               revs->children.name = "children";
+               revs->limited = 1;
+       } else {
+               int opts = diff_opt_parse(&revs->diffopt, argv, argc);
+               if (!opts)
+                       unkv[(*unkc)++] = arg;
+               return opts;
+       }
+
+       return 1;
+}
+
+void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ctx,
+                       const struct option *options,
+                       const char * const usagestr[])
+{
+       int n = handle_revision_opt(revs, ctx->argc, ctx->argv,
+                                   &ctx->cpidx, ctx->out);
+       if (n <= 0) {
+               error("unknown option `%s'", ctx->argv[0]);
+               usage_with_options(usagestr, options);
+       }
+       ctx->argv += n;
+       ctx->argc -= n;
+}
+
 /*
  * Parse revision information, filling in the "rev_info" structure,
  * and removing the used arguments from the argument list.
@@ -965,12 +1203,7 @@ static void add_ignore_packed(struct rev_info *revs, const char *name)
  */
 int setup_revisions(int argc, const char **argv, struct rev_info *revs, const char *def)
 {
-       int i, flags, seen_dashdash, show_merge;
-       const char **unrecognized = argv + 1;
-       int left = 1;
-       int all_match = 0;
-       int regflags = 0;
-       int fixed = 0;
+       int i, flags, left, seen_dashdash;
 
        /* First, search for "--" */
        seen_dashdash = 0;
@@ -986,58 +1219,13 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
                break;
        }
 
-       flags = show_merge = 0;
-       for (i = 1; i < argc; i++) {
+       /* Second, deal with arguments and options */
+       flags = 0;
+       for (left = i = 1; i < argc; i++) {
                const char *arg = argv[i];
                if (*arg == '-') {
                        int opts;
-                       if (!prefixcmp(arg, "--max-count=")) {
-                               revs->max_count = atoi(arg + 12);
-                               continue;
-                       }
-                       if (!prefixcmp(arg, "--skip=")) {
-                               revs->skip_count = atoi(arg + 7);
-                               continue;
-                       }
-                       /* accept -<digit>, like traditional "head" */
-                       if ((*arg == '-') && isdigit(arg[1])) {
-                               revs->max_count = atoi(arg + 1);
-                               continue;
-                       }
-                       if (!strcmp(arg, "-n")) {
-                               if (argc <= i + 1)
-                                       die("-n requires an argument");
-                               revs->max_count = atoi(argv[++i]);
-                               continue;
-                       }
-                       if (!prefixcmp(arg, "-n")) {
-                               revs->max_count = atoi(arg + 2);
-                               continue;
-                       }
-                       if (!prefixcmp(arg, "--max-age=")) {
-                               revs->max_age = atoi(arg + 10);
-                               continue;
-                       }
-                       if (!prefixcmp(arg, "--since=")) {
-                               revs->max_age = approxidate(arg + 8);
-                               continue;
-                       }
-                       if (!prefixcmp(arg, "--after=")) {
-                               revs->max_age = approxidate(arg + 8);
-                               continue;
-                       }
-                       if (!prefixcmp(arg, "--min-age=")) {
-                               revs->min_age = atoi(arg + 10);
-                               continue;
-                       }
-                       if (!prefixcmp(arg, "--before=")) {
-                               revs->min_age = approxidate(arg + 9);
-                               continue;
-                       }
-                       if (!prefixcmp(arg, "--until=")) {
-                               revs->min_age = approxidate(arg + 8);
-                               continue;
-                       }
+
                        if (!strcmp(arg, "--all")) {
                                handle_refs(revs, flags, for_each_ref);
                                continue;
@@ -1054,265 +1242,14 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
                                handle_refs(revs, flags, for_each_remote_ref);
                                continue;
                        }
-                       if (!strcmp(arg, "--first-parent")) {
-                               revs->first_parent_only = 1;
-                               continue;
-                       }
                        if (!strcmp(arg, "--reflog")) {
                                handle_reflog(revs, flags);
                                continue;
                        }
-                       if (!strcmp(arg, "-g") ||
-                                       !strcmp(arg, "--walk-reflogs")) {
-                               init_reflog_walk(&revs->reflog_info);
-                               continue;
-                       }
                        if (!strcmp(arg, "--not")) {
                                flags ^= UNINTERESTING;
                                continue;
                        }
-                       if (!strcmp(arg, "--default")) {
-                               if (++i >= argc)
-                                       die("bad --default argument");
-                               def = argv[i];
-                               continue;
-                       }
-                       if (!strcmp(arg, "--merge")) {
-                               show_merge = 1;
-                               continue;
-                       }
-                       if (!strcmp(arg, "--topo-order")) {
-                               revs->lifo = 1;
-                               revs->topo_order = 1;
-                               continue;
-                       }
-                       if (!strcmp(arg, "--date-order")) {
-                               revs->lifo = 0;
-                               revs->topo_order = 1;
-                               continue;
-                       }
-                       if (!prefixcmp(arg, "--early-output")) {
-                               int count = 100;
-                               switch (arg[14]) {
-                               case '=':
-                                       count = atoi(arg+15);
-                                       /* Fallthrough */
-                               case 0:
-                                       revs->topo_order = 1;
-                                       revs->early_output = count;
-                                       continue;
-                               }
-                       }
-                       if (!strcmp(arg, "--parents")) {
-                               revs->rewrite_parents = 1;
-                               revs->print_parents = 1;
-                               continue;
-                       }
-                       if (!strcmp(arg, "--dense")) {
-                               revs->dense = 1;
-                               continue;
-                       }
-                       if (!strcmp(arg, "--sparse")) {
-                               revs->dense = 0;
-                               continue;
-                       }
-                       if (!strcmp(arg, "--show-all")) {
-                               revs->show_all = 1;
-                               continue;
-                       }
-                       if (!strcmp(arg, "--remove-empty")) {
-                               revs->remove_empty_trees = 1;
-                               continue;
-                       }
-                       if (!strcmp(arg, "--no-merges")) {
-                               revs->no_merges = 1;
-                               continue;
-                       }
-                       if (!strcmp(arg, "--boundary")) {
-                               revs->boundary = 1;
-                               continue;
-                       }
-                       if (!strcmp(arg, "--left-right")) {
-                               revs->left_right = 1;
-                               continue;
-                       }
-                       if (!strcmp(arg, "--cherry-pick")) {
-                               revs->cherry_pick = 1;
-                               revs->limited = 1;
-                               continue;
-                       }
-                       if (!strcmp(arg, "--objects")) {
-                               revs->tag_objects = 1;
-                               revs->tree_objects = 1;
-                               revs->blob_objects = 1;
-                               continue;
-                       }
-                       if (!strcmp(arg, "--objects-edge")) {
-                               revs->tag_objects = 1;
-                               revs->tree_objects = 1;
-                               revs->blob_objects = 1;
-                               revs->edge_hint = 1;
-                               continue;
-                       }
-                       if (!strcmp(arg, "--unpacked")) {
-                               revs->unpacked = 1;
-                               free(revs->ignore_packed);
-                               revs->ignore_packed = NULL;
-                               revs->num_ignore_packed = 0;
-                               continue;
-                       }
-                       if (!prefixcmp(arg, "--unpacked=")) {
-                               revs->unpacked = 1;
-                               add_ignore_packed(revs, arg+11);
-                               continue;
-                       }
-                       if (!strcmp(arg, "-r")) {
-                               revs->diff = 1;
-                               DIFF_OPT_SET(&revs->diffopt, RECURSIVE);
-                               continue;
-                       }
-                       if (!strcmp(arg, "-t")) {
-                               revs->diff = 1;
-                               DIFF_OPT_SET(&revs->diffopt, RECURSIVE);
-                               DIFF_OPT_SET(&revs->diffopt, TREE_IN_RECURSIVE);
-                               continue;
-                       }
-                       if (!strcmp(arg, "-m")) {
-                               revs->ignore_merges = 0;
-                               continue;
-                       }
-                       if (!strcmp(arg, "-c")) {
-                               revs->diff = 1;
-                               revs->dense_combined_merges = 0;
-                               revs->combine_merges = 1;
-                               continue;
-                       }
-                       if (!strcmp(arg, "--cc")) {
-                               revs->diff = 1;
-                               revs->dense_combined_merges = 1;
-                               revs->combine_merges = 1;
-                               continue;
-                       }
-                       if (!strcmp(arg, "-v")) {
-                               revs->verbose_header = 1;
-                               continue;
-                       }
-                       if (!strcmp(arg, "--pretty")) {
-                               revs->verbose_header = 1;
-                               get_commit_format(arg+8, revs);
-                               continue;
-                       }
-                       if (!prefixcmp(arg, "--pretty=")) {
-                               revs->verbose_header = 1;
-                               get_commit_format(arg+9, revs);
-                               continue;
-                       }
-                       if (!strcmp(arg, "--graph")) {
-                               revs->topo_order = 1;
-                               revs->rewrite_parents = 1;
-                               revs->graph = graph_init(revs);
-                               continue;
-                       }
-                       if (!strcmp(arg, "--root")) {
-                               revs->show_root_diff = 1;
-                               continue;
-                       }
-                       if (!strcmp(arg, "--no-commit-id")) {
-                               revs->no_commit_id = 1;
-                               continue;
-                       }
-                       if (!strcmp(arg, "--always")) {
-                               revs->always_show_header = 1;
-                               continue;
-                       }
-                       if (!strcmp(arg, "--no-abbrev")) {
-                               revs->abbrev = 0;
-                               continue;
-                       }
-                       if (!strcmp(arg, "--abbrev")) {
-                               revs->abbrev = DEFAULT_ABBREV;
-                               continue;
-                       }
-                       if (!prefixcmp(arg, "--abbrev=")) {
-                               revs->abbrev = strtoul(arg + 9, NULL, 10);
-                               if (revs->abbrev < MINIMUM_ABBREV)
-                                       revs->abbrev = MINIMUM_ABBREV;
-                               else if (revs->abbrev > 40)
-                                       revs->abbrev = 40;
-                               continue;
-                       }
-                       if (!strcmp(arg, "--abbrev-commit")) {
-                               revs->abbrev_commit = 1;
-                               continue;
-                       }
-                       if (!strcmp(arg, "--full-diff")) {
-                               revs->diff = 1;
-                               revs->full_diff = 1;
-                               continue;
-                       }
-                       if (!strcmp(arg, "--full-history")) {
-                               revs->simplify_history = 0;
-                               continue;
-                       }
-                       if (!strcmp(arg, "--relative-date")) {
-                               revs->date_mode = DATE_RELATIVE;
-                               continue;
-                       }
-                       if (!strncmp(arg, "--date=", 7)) {
-                               revs->date_mode = parse_date_format(arg + 7);
-                               continue;
-                       }
-                       if (!strcmp(arg, "--log-size")) {
-                               revs->show_log_size = 1;
-                               continue;
-                       }
-
-                       /*
-                        * Grepping the commit log
-                        */
-                       if (!prefixcmp(arg, "--author=")) {
-                               add_header_grep(revs, "author", arg+9);
-                               continue;
-                       }
-                       if (!prefixcmp(arg, "--committer=")) {
-                               add_header_grep(revs, "committer", arg+12);
-                               continue;
-                       }
-                       if (!prefixcmp(arg, "--grep=")) {
-                               add_message_grep(revs, arg+7);
-                               continue;
-                       }
-                       if (!strcmp(arg, "--extended-regexp") ||
-                           !strcmp(arg, "-E")) {
-                               regflags |= REG_EXTENDED;
-                               continue;
-                       }
-                       if (!strcmp(arg, "--regexp-ignore-case") ||
-                           !strcmp(arg, "-i")) {
-                               regflags |= REG_ICASE;
-                               continue;
-                       }
-                       if (!strcmp(arg, "--fixed-strings") ||
-                           !strcmp(arg, "-F")) {
-                               fixed = 1;
-                               continue;
-                       }
-                       if (!strcmp(arg, "--all-match")) {
-                               all_match = 1;
-                               continue;
-                       }
-                       if (!prefixcmp(arg, "--encoding=")) {
-                               arg += 11;
-                               if (strcmp(arg, "none"))
-                                       git_log_output_encoding = xstrdup(arg);
-                               else
-                                       git_log_output_encoding = "";
-                               continue;
-                       }
-                       if (!strcmp(arg, "--reverse")) {
-                               revs->reverse ^= 1;
-                               continue;
-                       }
                        if (!strcmp(arg, "--no-walk")) {
                                revs->no_walk = 1;
                                continue;
@@ -1322,13 +1259,13 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
                                continue;
                        }
 
-                       opts = diff_opt_parse(&revs->diffopt, argv+i, argc-i);
+                       opts = handle_revision_opt(revs, argc - i, argv + i, &left, argv);
                        if (opts > 0) {
                                i += opts - 1;
                                continue;
                        }
-                       *unrecognized++ = arg;
-                       left++;
+                       if (opts < 0)
+                               exit(128);
                        continue;
                }
 
@@ -1352,21 +1289,18 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
                }
        }
 
-       if (revs->grep_filter) {
-               revs->grep_filter->regflags |= regflags;
-               revs->grep_filter->fixed = fixed;
-       }
-
-       if (show_merge)
+       if (revs->def == NULL)
+               revs->def = def;
+       if (revs->show_merge)
                prepare_show_merge(revs);
-       if (def && !revs->pending.nr) {
+       if (revs->def && !revs->pending.nr) {
                unsigned char sha1[20];
                struct object *object;
                unsigned mode;
-               if (get_sha1_with_mode(def, sha1, &mode))
-                       die("bad default revision '%s'", def);
-               object = get_reference(revs, def, sha1, 0);
-               add_pending_object_with_mode(revs, object, def, mode);
+               if (get_sha1_with_mode(revs->def, sha1, &mode))
+                       die("bad default revision '%s'", revs->def);
+               object = get_reference(revs, revs->def, sha1, 0);
+               add_pending_object_with_mode(revs, object, revs->def, mode);
        }
 
        /* Did the user ask for any diff output? Run the diff! */
@@ -1400,12 +1334,13 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
                die("diff_setup_done failed");
 
        if (revs->grep_filter) {
-               revs->grep_filter->all_match = all_match;
                compile_grep_patterns(revs->grep_filter);
        }
 
        if (revs->reverse && revs->reflog_info)
                die("cannot combine --reverse with --walk-reflogs");
+       if (revs->rewrite_parents && revs->children.name)
+               die("cannot combine --parents and --children");
 
        /*
         * Limitations on the graph functionality
@@ -1419,6 +1354,26 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
        return left;
 }
 
+static void add_child(struct rev_info *revs, struct commit *parent, struct commit *child)
+{
+       struct commit_list *l = xcalloc(1, sizeof(*l));
+
+       l->item = child;
+       l->next = add_decoration(&revs->children, &parent->object, l);
+}
+
+static void set_children(struct rev_info *revs)
+{
+       struct commit_list *l;
+       for (l = revs->commits; l; l = l->next) {
+               struct commit *commit = l->item;
+               struct commit_list *p;
+
+               for (p = commit->parents; p; p = p->next)
+                       add_child(revs, p->item, commit);
+       }
+}
+
 int prepare_revision_walk(struct rev_info *revs)
 {
        int nr = revs->pending.nr;
@@ -1447,6 +1402,8 @@ int prepare_revision_walk(struct rev_info *revs)
                        return -1;
        if (revs->topo_order)
                sort_in_topological_order(&revs->commits, revs->lifo);
+       if (revs->children.name)
+               set_children(revs);
        return 0;
 }
 
@@ -1524,6 +1481,11 @@ static int commit_match(struct commit *commit, struct rev_info *opt)
                           commit->buffer, strlen(commit->buffer));
 }
 
+static inline int want_ancestry(struct rev_info *revs)
+{
+       return (revs->rewrite_parents || revs->children.name);
+}
+
 enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit)
 {
        if (commit->object.flags & SHOWN)
@@ -1544,13 +1506,13 @@ enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit)
                /* Commit without changes? */
                if (commit->object.flags & TREESAME) {
                        /* drop merges unless we want parenthood */
-                       if (!revs->rewrite_parents)
+                       if (!want_ancestry(revs))
                                return commit_ignore;
                        /* non-merge - always ignore it */
                        if (!commit->parents || !commit->parents->next)
                                return commit_ignore;
                }
-               if (revs->rewrite_parents && rewrite_parents(revs, commit) < 0)
+               if (want_ancestry(revs) && rewrite_parents(revs, commit) < 0)
                        return commit_error;
        }
        return commit_show;
index abce5001f19a60bb15b519b26773b57c83563021..fa68c651424e406ce84c890a655a5e292a7e5af6 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef REVISION_H
 #define REVISION_H
 
+#include "parse-options.h"
+
 #define SEEN           (1u<<0)
 #define UNINTERESTING   (1u<<1)
 #define TREESAME       (1u<<2)
@@ -11,6 +13,7 @@
 #define ADDED          (1u<<7) /* Parents already parsed and added? */
 #define SYMMETRIC_LEFT (1u<<8)
 #define TOPOSORT       (1u<<9) /* In the active toposort list.. */
+#define ALL_REV_FLAGS  ((1u<<10)-1)
 
 struct rev_info;
 struct log_info;
@@ -25,6 +28,7 @@ struct rev_info {
 
        /* Basic information */
        const char *prefix;
+       const char *def;
        void *prune_data;
        unsigned int early_output;
 
@@ -65,6 +69,7 @@ struct rev_info {
 
        /* Format info */
        unsigned int    shown_one:1,
+                       show_merge:1,
                        abbrev_commit:1,
                        use_terminator:1,
                        missing_newline:1;
@@ -104,6 +109,7 @@ struct rev_info {
        struct diff_options pruning;
 
        struct reflog_walk_info *reflog_info;
+       struct decoration children;
 };
 
 #define REV_TREE_SAME          0
@@ -111,11 +117,16 @@ struct rev_info {
 #define REV_TREE_DIFFERENT     2
 
 /* revision.c */
+void read_revisions_from_stdin(struct rev_info *revs);
+
 typedef void (*show_early_output_fn_t)(struct rev_info *, struct commit_list *);
 volatile show_early_output_fn_t show_early_output;
 
 extern void init_revisions(struct rev_info *revs, const char *prefix);
 extern int setup_revisions(int argc, const char **argv, struct rev_info *revs, const char *def);
+extern void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ctx,
+                                const struct option *options,
+                                const char * const usagestr[]);
 extern int handle_revision_arg(const char *arg, struct rev_info *revs,int flags,int cant_be_filename);
 
 extern int prepare_revision_walk(struct rev_info *revs);
index 7068ec7e6d74af0cec233259b4b6e41a61ed5123..6e29fdf9e2968900d21ea48b992f292204621f19 100644 (file)
@@ -67,21 +67,8 @@ int start_command(struct child_process *cmd)
 
        trace_argv_printf(cmd->argv, "trace: run_command:");
 
+#ifndef __MINGW32__
        cmd->pid = fork();
-       if (cmd->pid < 0) {
-               if (need_in)
-                       close_pair(fdin);
-               else if (cmd->in)
-                       close(cmd->in);
-               if (need_out)
-                       close_pair(fdout);
-               else if (cmd->out)
-                       close(cmd->out);
-               if (need_err)
-                       close_pair(fderr);
-               return -ERR_RUN_COMMAND_FORK;
-       }
-
        if (!cmd->pid) {
                if (cmd->no_stdin)
                        dup_devnull(0);
@@ -130,6 +117,88 @@ int start_command(struct child_process *cmd)
                }
                die("exec %s failed.", cmd->argv[0]);
        }
+#else
+       int s0 = -1, s1 = -1, s2 = -1;  /* backups of stdin, stdout, stderr */
+       const char *sargv0 = cmd->argv[0];
+       char **env = environ;
+       struct strbuf git_cmd;
+
+       if (cmd->no_stdin) {
+               s0 = dup(0);
+               dup_devnull(0);
+       } else if (need_in) {
+               s0 = dup(0);
+               dup2(fdin[0], 0);
+       } else if (cmd->in) {
+               s0 = dup(0);
+               dup2(cmd->in, 0);
+       }
+
+       if (cmd->no_stderr) {
+               s2 = dup(2);
+               dup_devnull(2);
+       } else if (need_err) {
+               s2 = dup(2);
+               dup2(fderr[1], 2);
+       }
+
+       if (cmd->no_stdout) {
+               s1 = dup(1);
+               dup_devnull(1);
+       } else if (cmd->stdout_to_stderr) {
+               s1 = dup(1);
+               dup2(2, 1);
+       } else if (need_out) {
+               s1 = dup(1);
+               dup2(fdout[1], 1);
+       } else if (cmd->out > 1) {
+               s1 = dup(1);
+               dup2(cmd->out, 1);
+       }
+
+       if (cmd->dir)
+               die("chdir in start_command() not implemented");
+       if (cmd->env) {
+               env = copy_environ();
+               for (; *cmd->env; cmd->env++)
+                       env = env_setenv(env, *cmd->env);
+       }
+
+       if (cmd->git_cmd) {
+               strbuf_init(&git_cmd, 0);
+               strbuf_addf(&git_cmd, "git-%s", cmd->argv[0]);
+               cmd->argv[0] = git_cmd.buf;
+       }
+
+       cmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, env);
+
+       if (cmd->env)
+               free_environ(env);
+       if (cmd->git_cmd)
+               strbuf_release(&git_cmd);
+
+       cmd->argv[0] = sargv0;
+       if (s0 >= 0)
+               dup2(s0, 0), close(s0);
+       if (s1 >= 0)
+               dup2(s1, 1), close(s1);
+       if (s2 >= 0)
+               dup2(s2, 2), close(s2);
+#endif
+
+       if (cmd->pid < 0) {
+               if (need_in)
+                       close_pair(fdin);
+               else if (cmd->in)
+                       close(cmd->in);
+               if (need_out)
+                       close_pair(fdout);
+               else if (cmd->out)
+                       close(cmd->out);
+               if (need_err)
+                       close_pair(fderr);
+               return -ERR_RUN_COMMAND_FORK;
+       }
 
        if (need_in)
                close(fdin[0]);
@@ -221,13 +290,23 @@ int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const
        return run_command(&cmd);
 }
 
+#ifdef __MINGW32__
+static __stdcall unsigned run_thread(void *data)
+{
+       struct async *async = data;
+       return async->proc(async->fd_for_proc, async->data);
+}
+#endif
+
 int start_async(struct async *async)
 {
        int pipe_out[2];
 
        if (pipe(pipe_out) < 0)
                return error("cannot create pipe: %s", strerror(errno));
+       async->out = pipe_out[0];
 
+#ifndef __MINGW32__
        async->pid = fork();
        if (async->pid < 0) {
                error("fork (async) failed: %s", strerror(errno));
@@ -238,16 +317,33 @@ int start_async(struct async *async)
                close(pipe_out[0]);
                exit(!!async->proc(pipe_out[1], async->data));
        }
-       async->out = pipe_out[0];
        close(pipe_out[1]);
+#else
+       async->fd_for_proc = pipe_out[1];
+       async->tid = (HANDLE) _beginthreadex(NULL, 0, run_thread, async, 0, NULL);
+       if (!async->tid) {
+               error("cannot create thread: %s", strerror(errno));
+               close_pair(pipe_out);
+               return -1;
+       }
+#endif
        return 0;
 }
 
 int finish_async(struct async *async)
 {
+#ifndef __MINGW32__
        int ret = 0;
 
        if (wait_or_whine(async->pid))
                ret = error("waitpid (async) failed");
+#else
+       DWORD ret = 0;
+       if (WaitForSingleObject(async->tid, INFINITE) != WAIT_OBJECT_0)
+               ret = error("waiting for thread failed: %lu", GetLastError());
+       else if (!GetExitCodeThread(async->tid, &ret))
+               ret = error("cannot get thread exit code: %lu", GetLastError());
+       CloseHandle(async->tid);
+#endif
        return ret;
 }
index debe3074b5a01fb5a19e61f07ff66c250cdc4f82..5203a9ebb10b14bd06862abafed0ab73d7514a3d 100644 (file)
@@ -76,7 +76,12 @@ struct async {
        int (*proc)(int fd, void *data);
        void *data;
        int out;        /* caller reads from here and closes it */
+#ifndef __MINGW32__
        pid_t pid;
+#else
+       HANDLE tid;
+       int fd_for_proc;
+#endif
 };
 
 int start_async(struct async *async);
diff --git a/setup.c b/setup.c
index 3b111ea7cf5f68ecca085f5a56421ea190e1771a..6cf909463d4ad3681a2f35269db9dc944f4389c2 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -6,11 +6,17 @@ static int inside_work_tree = -1;
 
 static int sanitary_path_copy(char *dst, const char *src)
 {
-       char *dst0 = dst;
+       char *dst0;
 
-       if (*src == '/') {
+       if (has_dos_drive_prefix(src)) {
+               *dst++ = *src++;
+               *dst++ = *src++;
+       }
+       dst0 = dst;
+
+       if (is_dir_sep(*src)) {
                *dst++ = '/';
-               while (*src == '/')
+               while (is_dir_sep(*src))
                        src++;
        }
 
@@ -26,27 +32,24 @@ static int sanitary_path_copy(char *dst, const char *src)
                 * (4) "../"          -- strip one, eat slash and continue.
                 */
                if (c == '.') {
-                       switch (src[1]) {
-                       case '\0':
+                       if (!src[1]) {
                                /* (1) */
                                src++;
-                               break;
-                       case '/':
+                       } else if (is_dir_sep(src[1])) {
                                /* (2) */
                                src += 2;
-                               while (*src == '/')
+                               while (is_dir_sep(*src))
                                        src++;
                                continue;
-                       case '.':
-                               switch (src[2]) {
-                               case '\0':
+                       } else if (src[1] == '.') {
+                               if (!src[2]) {
                                        /* (3) */
                                        src += 2;
                                        goto up_one;
-                               case '/':
+                               } else if (is_dir_sep(src[2])) {
                                        /* (4) */
                                        src += 3;
-                                       while (*src == '/')
+                                       while (is_dir_sep(*src))
                                                src++;
                                        goto up_one;
                                }
@@ -54,11 +57,11 @@ static int sanitary_path_copy(char *dst, const char *src)
                }
 
                /* copy up to the next '/', and eat all '/' */
-               while ((c = *src++) != '\0' && c != '/')
+               while ((c = *src++) != '\0' && !is_dir_sep(c))
                        *dst++ = c;
-               if (c == '/') {
-                       *dst++ = c;
-                       while (c == '/')
+               if (is_dir_sep(c)) {
+                       *dst++ = '/';
+                       while (is_dir_sep(c))
                                c = *src++;
                        src--;
                } else if (!c)
@@ -77,7 +80,7 @@ static int sanitary_path_copy(char *dst, const char *src)
                        if (dst <= dst0)
                                break;
                        c = *dst--;
-                       if (c == '/') {
+                       if (c == '/') { /* MinGW: cannot be '\\' anymore */
                                dst += 2;
                                break;
                        }
@@ -126,10 +129,23 @@ const char *prefix_path(const char *prefix, int len, const char *path)
 const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
 {
        static char path[PATH_MAX];
+#ifndef __MINGW32__
        if (!pfx || !*pfx || is_absolute_path(arg))
                return arg;
        memcpy(path, pfx, pfx_len);
        strcpy(path + pfx_len, arg);
+#else
+       char *p;
+       /* don't add prefix to absolute paths, but still replace '\' by '/' */
+       if (is_absolute_path(arg))
+               pfx_len = 0;
+       else
+               memcpy(path, pfx, pfx_len);
+       strcpy(path + pfx_len, arg);
+       for (p = path + pfx_len; *p; p++)
+               if (*p == '\\')
+                       *p = '/';
+#endif
        return path;
 }
 
@@ -360,10 +376,11 @@ const char *read_gitfile_gently(const char *path)
 const char *setup_git_directory_gently(int *nongit_ok)
 {
        const char *work_tree_env = getenv(GIT_WORK_TREE_ENVIRONMENT);
+       const char *env_ceiling_dirs = getenv(CEILING_DIRECTORIES_ENVIRONMENT);
        static char cwd[PATH_MAX+1];
        const char *gitdirenv;
        const char *gitfile_dir;
-       int len, offset;
+       int len, offset, ceil_offset;
 
        /*
         * Let's assume that we are in a git repository.
@@ -415,6 +432,10 @@ const char *setup_git_directory_gently(int *nongit_ok)
        if (!getcwd(cwd, sizeof(cwd)-1))
                die("Unable to read current working directory");
 
+       ceil_offset = longest_ancestor_length(cwd, env_ceiling_dirs);
+       if (ceil_offset < 0 && has_dos_drive_prefix(cwd))
+               ceil_offset = 1;
+
        /*
         * Test in the following order (relative to the cwd):
         * - .git (file containing "gitdir: <path>")
@@ -444,18 +465,17 @@ const char *setup_git_directory_gently(int *nongit_ok)
                        check_repository_format_gently(nongit_ok);
                        return NULL;
                }
-               chdir("..");
-               do {
-                       if (!offset) {
-                               if (nongit_ok) {
-                                       if (chdir(cwd))
-                                               die("Cannot come back to cwd");
-                                       *nongit_ok = 1;
-                                       return NULL;
-                               }
-                               die("Not a git repository");
+               while (--offset > ceil_offset && cwd[offset] != '/');
+               if (offset <= ceil_offset) {
+                       if (nongit_ok) {
+                               if (chdir(cwd))
+                                       die("Cannot come back to cwd");
+                               *nongit_ok = 1;
+                               return NULL;
                        }
-               } while (cwd[--offset] != '/');
+                       die("Not a git repository");
+               }
+               chdir("..");
        }
 
        inside_git_dir = 0;
index d1c406081e29eab9843a5268b611af1a3e014227..e281c14f01d37ab7623998c2990914aca49a7a3b 100644 (file)
@@ -83,14 +83,18 @@ int get_sha1_hex(const char *hex, unsigned char *sha1)
        return 0;
 }
 
+static inline int offset_1st_component(const char *path)
+{
+       if (has_dos_drive_prefix(path))
+               return 2 + (path[2] == '/');
+       return *path == '/';
+}
+
 int safe_create_leading_directories(char *path)
 {
-       char *pos = path;
+       char *pos = path + offset_1st_component(path);
        struct stat st;
 
-       if (is_absolute_path(path))
-               pos++;
-
        while (pos) {
                pos = strchr(pos, '/');
                if (!pos)
@@ -401,7 +405,7 @@ void prepare_alt_odb(void)
        if (!alt) alt = "";
 
        alt_odb_tail = &alt_odb_list;
-       link_alt_odb_entries(alt, alt + strlen(alt), ':', NULL, 0);
+       link_alt_odb_entries(alt, alt + strlen(alt), PATH_SEP, NULL, 0);
 
        read_info_alternates(get_object_directory(), 0);
 }
@@ -480,7 +484,7 @@ static int check_packed_git_idx(const char *path,  struct packed_git *p)
                version = ntohl(hdr->idx_version);
                if (version < 2 || version > 2) {
                        munmap(idx_map, idx_size);
-                       return error("index file %s is version %d"
+                       return error("index file %s is version %"PRIu32
                                     " and is not supported by this binary"
                                     " (try upgrading GIT to a newer version)",
                                     path, version);
@@ -691,14 +695,14 @@ static int open_packed_git_1(struct packed_git *p)
        if (hdr.hdr_signature != htonl(PACK_SIGNATURE))
                return error("file %s is not a GIT packfile", p->pack_name);
        if (!pack_version_ok(hdr.hdr_version))
-               return error("packfile %s is version %u and not supported"
-                       " (try upgrading GIT to a newer version)",
+               return error("packfile %s is version %"PRIu32" and not"
+                       " supported (try upgrading GIT to a newer version)",
                        p->pack_name, ntohl(hdr.hdr_version));
 
        /* Verify the pack matches its index. */
        if (p->num_objects != ntohl(hdr.hdr_entries))
-               return error("packfile %s claims to have %u objects"
-                            " while index indicates %u objects",
+               return error("packfile %s claims to have %"PRIu32" objects"
+                            " while index indicates %"PRIu32" objects",
                             p->pack_name, ntohl(hdr.hdr_entries),
                             p->num_objects);
        if (lseek(p->pack_fd, p->pack_size - sizeof(sha1), SEEK_SET) == -1)
@@ -801,18 +805,28 @@ unsigned char* use_pack(struct packed_git *p,
        return win->base + offset;
 }
 
+static struct packed_git *alloc_packed_git(int extra)
+{
+       struct packed_git *p = xmalloc(sizeof(*p) + extra);
+       memset(p, 0, sizeof(*p));
+       p->pack_fd = -1;
+       return p;
+}
+
 struct packed_git *add_packed_git(const char *path, int path_len, int local)
 {
        struct stat st;
-       struct packed_git *p = xmalloc(sizeof(*p) + path_len + 2);
+       struct packed_git *p = alloc_packed_git(path_len + 2);
 
        /*
         * Make sure a corresponding .pack file exists and that
         * the index looks sane.
         */
        path_len -= strlen(".idx");
-       if (path_len < 1)
+       if (path_len < 1) {
+               free(p);
                return NULL;
+       }
        memcpy(p->pack_name, path, path_len);
        strcpy(p->pack_name + path_len, ".pack");
        if (stat(p->pack_name, &st) || !S_ISREG(st.st_mode)) {
@@ -823,14 +837,7 @@ struct packed_git *add_packed_git(const char *path, int path_len, int local)
        /* ok, it looks sane as far as we can check without
         * actually mapping the pack file.
         */
-       p->index_version = 0;
-       p->index_data = NULL;
-       p->index_size = 0;
-       p->num_objects = 0;
        p->pack_size = st.st_size;
-       p->next = NULL;
-       p->windows = NULL;
-       p->pack_fd = -1;
        p->pack_local = local;
        p->mtime = st.st_mtime;
        if (path_len < 40 || get_sha1_hex(path + path_len - 40, p->sha1))
@@ -842,19 +849,15 @@ struct packed_git *parse_pack_index(unsigned char *sha1)
 {
        const char *idx_path = sha1_pack_index_name(sha1);
        const char *path = sha1_pack_name(sha1);
-       struct packed_git *p = xmalloc(sizeof(*p) + strlen(path) + 2);
+       struct packed_git *p = alloc_packed_git(strlen(path) + 1);
 
+       strcpy(p->pack_name, path);
+       hashcpy(p->sha1, sha1);
        if (check_packed_git_idx(idx_path, p)) {
                free(p);
                return NULL;
        }
 
-       strcpy(p->pack_name, path);
-       p->pack_size = 0;
-       p->next = NULL;
-       p->windows = NULL;
-       p->pack_fd = -1;
-       hashcpy(p->sha1, sha1);
        return p;
 }
 
@@ -991,6 +994,30 @@ void reprepare_packed_git(void)
        prepare_packed_git();
 }
 
+static void mark_bad_packed_object(struct packed_git *p,
+                                  const unsigned char *sha1)
+{
+       unsigned i;
+       for (i = 0; i < p->num_bad_objects; i++)
+               if (!hashcmp(sha1, p->bad_object_sha1 + 20 * i))
+                       return;
+       p->bad_object_sha1 = xrealloc(p->bad_object_sha1, 20 * (p->num_bad_objects + 1));
+       hashcpy(p->bad_object_sha1 + 20 * p->num_bad_objects, sha1);
+       p->num_bad_objects++;
+}
+
+static int has_packed_and_bad(const unsigned char *sha1)
+{
+       struct packed_git *p;
+       unsigned i;
+
+       for (p = packed_git; p; p = p->next)
+               for (i = 0; i < p->num_bad_objects; i++)
+                       if (!hashcmp(sha1, p->bad_object_sha1 + 20 * i))
+                               return 1;
+       return 0;
+}
+
 int check_sha1_signature(const unsigned char *sha1, void *map, unsigned long size, const char *type)
 {
        unsigned char real_sha1[20];
@@ -1309,20 +1336,17 @@ static off_t get_delta_base(struct packed_git *p,
                while (c & 128) {
                        base_offset += 1;
                        if (!base_offset || MSB(base_offset, 7))
-                               die("offset value overflow for delta base object");
+                               return 0;  /* overflow */
                        c = base_info[used++];
                        base_offset = (base_offset << 7) + (c & 127);
                }
                base_offset = delta_obj_offset - base_offset;
                if (base_offset >= delta_obj_offset)
-                       die("delta base offset out of bound");
+                       return 0;  /* out of bound */
                *curpos += used;
        } else if (type == OBJ_REF_DELTA) {
                /* The base entry _must_ be in the same pack */
                base_offset = find_pack_entry_one(base_info, p);
-               if (!base_offset)
-                       die("failed to find delta-pack base object %s",
-                               sha1_to_hex(base_info));
                *curpos += 20;
        } else
                die("I am totally screwed");
@@ -1415,6 +1439,9 @@ const char *packed_object_info_detail(struct packed_git *p,
                        return typename(type);
                case OBJ_OFS_DELTA:
                        obj_offset = get_delta_base(p, &w_curs, &curpos, type, obj_offset);
+                       if (!obj_offset)
+                               die("pack %s contains bad delta base reference of type %s",
+                                   p->pack_name, typename(type));
                        if (*delta_chain_length == 0) {
                                revidx = find_pack_revindex(p, obj_offset);
                                hashcpy(base_sha1, nth_packed_object_sha1(p, revidx->nr));
@@ -1609,17 +1636,42 @@ static void *unpack_delta_entry(struct packed_git *p,
        off_t base_offset;
 
        base_offset = get_delta_base(p, w_curs, &curpos, *type, obj_offset);
+       if (!base_offset) {
+               error("failed to validate delta base reference "
+                     "at offset %"PRIuMAX" from %s",
+                     (uintmax_t)curpos, p->pack_name);
+               return NULL;
+       }
+       unuse_pack(w_curs);
        base = cache_or_unpack_entry(p, base_offset, &base_size, type, 0);
-       if (!base)
-               die("failed to read delta base object"
-                   " at %"PRIuMAX" from %s",
-                   (uintmax_t)base_offset, p->pack_name);
+       if (!base) {
+               /*
+                * We're probably in deep shit, but let's try to fetch
+                * the required base anyway from another pack or loose.
+                * This is costly but should happen only in the presence
+                * of a corrupted pack, and is better than failing outright.
+                */
+               struct revindex_entry *revidx = find_pack_revindex(p, base_offset);
+               const unsigned char *base_sha1 =
+                                       nth_packed_object_sha1(p, revidx->nr);
+               error("failed to read delta base object %s"
+                     " at offset %"PRIuMAX" from %s",
+                     sha1_to_hex(base_sha1), (uintmax_t)base_offset,
+                     p->pack_name);
+               mark_bad_packed_object(p, base_sha1);
+               base = read_object(base_sha1, type, &base_size);
+               if (!base)
+                       return NULL;
+       }
 
        delta_data = unpack_compressed_entry(p, w_curs, curpos, delta_size);
-       if (!delta_data)
-               die("failed to unpack compressed delta"
-                   " at %"PRIuMAX" from %s",
-                   (uintmax_t)curpos, p->pack_name);
+       if (!delta_data) {
+               error("failed to unpack compressed delta "
+                     "at offset %"PRIuMAX" from %s",
+                     (uintmax_t)curpos, p->pack_name);
+               free(base);
+               return NULL;
+       }
        result = patch_delta(base, base_size,
                             delta_data, delta_size,
                             sizep);
@@ -1651,7 +1703,9 @@ void *unpack_entry(struct packed_git *p, off_t obj_offset,
                data = unpack_compressed_entry(p, &w_curs, curpos, *sizep);
                break;
        default:
-               die("unknown object type %i in %s", *type, p->pack_name);
+               data = NULL;
+               error("unknown object type %i at offset %"PRIuMAX" in %s",
+                     *type, (uintmax_t)obj_offset, p->pack_name);
        }
        unuse_pack(&w_curs);
        return data;
@@ -1677,7 +1731,7 @@ const unsigned char *nth_packed_object_sha1(struct packed_git *p,
        }
 }
 
-static off_t nth_packed_object_offset(const struct packed_git *p, uint32_t n)
+off_t nth_packed_object_offset(const struct packed_git *p, uint32_t n)
 {
        const unsigned char *index = p->index_data;
        index += 4 * 256;
@@ -1728,7 +1782,7 @@ off_t find_pack_entry_one(const unsigned char *sha1,
        }
 
        if (debug_lookup)
-               printf("%02x%02x%02x... lo %u hi %u nr %u\n",
+               printf("%02x%02x%02x... lo %u hi %u nr %"PRIu32"\n",
                       sha1[0], sha1[1], sha1[2], lo, hi, p->num_objects);
 
        if (use_lookup < 0)
@@ -1797,6 +1851,13 @@ static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e, cons
                                goto next;
                }
 
+               if (p->num_bad_objects) {
+                       unsigned i;
+                       for (i = 0; i < p->num_bad_objects; i++)
+                               if (!hashcmp(sha1, p->bad_object_sha1 + 20 * i))
+                                       goto next;
+               }
+
                offset = find_pack_entry_one(sha1, p);
                if (offset) {
                        /*
@@ -1881,11 +1942,24 @@ static void *read_packed_sha1(const unsigned char *sha1,
                              enum object_type *type, unsigned long *size)
 {
        struct pack_entry e;
+       void *data;
 
        if (!find_pack_entry(sha1, &e, NULL))
                return NULL;
-       else
-               return cache_or_unpack_entry(e.p, e.offset, size, type, 1);
+       data = cache_or_unpack_entry(e.p, e.offset, size, type, 1);
+       if (!data) {
+               /*
+                * We're probably in deep shit, but let's try to fetch
+                * the required object anyway from another pack or loose.
+                * This should happen only in the presence of a corrupted
+                * pack, and is better than failing outright.
+                */
+               error("failed to read object %s at offset %"PRIuMAX" from %s",
+                     sha1_to_hex(sha1), (uintmax_t)e.offset, e.p->pack_name);
+               mark_bad_packed_object(e.p, sha1);
+               data = read_object(sha1, type, size);
+       }
+       return data;
 }
 
 /*
@@ -1948,8 +2022,8 @@ int pretend_sha1_file(void *buf, unsigned long len, enum object_type type,
        return 0;
 }
 
-void *read_sha1_file(const unsigned char *sha1, enum object_type *type,
-                    unsigned long *size)
+void *read_object(const unsigned char *sha1, enum object_type *type,
+                 unsigned long *size)
 {
        unsigned long mapsize;
        void *map, *buf;
@@ -1975,6 +2049,16 @@ void *read_sha1_file(const unsigned char *sha1, enum object_type *type,
        return read_packed_sha1(sha1, type, size);
 }
 
+void *read_sha1_file(const unsigned char *sha1, enum object_type *type,
+                    unsigned long *size)
+{
+       void *data = read_object(sha1, type, size);
+       /* legacy behavior is to die on corrupted objects */
+       if (!data && (has_loose_object(sha1) || has_packed_and_bad(sha1)))
+               die("object %s is corrupted", sha1_to_hex(sha1));
+       return data;
+}
+
 void *read_object_with_reference(const unsigned char *sha1,
                                 const char *required_type_name,
                                 unsigned long *size,
@@ -2092,7 +2176,8 @@ int hash_sha1_file(const void *buf, unsigned long len, const char *type,
 /* Finalize a file on disk, and close it. */
 static void close_sha1_file(int fd)
 {
-       /* For safe-mode, we could fsync_or_die(fd, "sha1 file") here */
+       if (fsync_object_files)
+               fsync_or_die(fd, "sha1 file");
        fchmod(fd, 0444);
        if (close(fd) != 0)
                die("unable to write sha1 file");
diff --git a/shell.c b/shell.c
index b27d01c9e4ca51dc3259994da47f4d9a6e8344c3..91ca7de0827642fd949f861fca6991415853b1ce 100644 (file)
--- a/shell.c
+++ b/shell.c
@@ -3,6 +3,14 @@
 #include "exec_cmd.h"
 #include "strbuf.h"
 
+/* Stubs for functions that make no sense for git-shell. These stubs
+ * are provided here to avoid linking in external redundant modules.
+ */
+void release_pack_memory(size_t need, int fd){}
+void trace_argv_printf(const char **argv, const char *fmt, ...){}
+void trace_printf(const char *fmt, ...){}
+
+
 static int do_generic_cmd(const char *me, char *arg)
 {
        const char *my_argv[4];
index 7253991fff9f6240ee6413986dfc66cfa3ff184e..45bb535773fd9c36f73502df9462f7de800009c8 100644 (file)
@@ -68,7 +68,8 @@ int main(int argc, char **argv)
                                                     ntohl(off64[1]);
                                off64_nr++;
                        }
-                       printf("%" PRIuMAX " %s (%08x)\n", (uintmax_t) offset,
+                       printf("%" PRIuMAX " %s (%08"PRIx32")\n",
+                              (uintmax_t) offset,
                               sha1_to_hex(entries[i].sha1),
                               ntohl(entries[i].crc));
                }
index ab6edbf19e80a5e07c85ff7cde05061fba349647..1b97c5465b7d9e4404e11668b44c5c507a302d4a 100644 (file)
@@ -1,2 +1 @@
-t[0-9][0-9][0-9][0-9]-*.sh -whitespace
 t[0-9][0-9][0-9][0-9]/* -whitespace
index 11ffd910c1b5022e0bd3aa217147269c8e9ac29e..b27e280083867ac03c4abc188f0f37291eb123a0 100644 (file)
@@ -1 +1,2 @@
 /trash directory
+/test-results
index c6a60ab165b504393d3ecd5db1ea9d241687be05..a778865ae7d015535763b856391ba751f2a9f87c 100644 (file)
@@ -14,18 +14,24 @@ SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
 T = $(wildcard t[0-9][0-9][0-9][0-9]-*.sh)
 TSVN = $(wildcard t91[0-9][0-9]-*.sh)
 
-all: $(T) clean
+all: pre-clean $(T) aggregate-results clean
 
 $(T):
        @echo "*** $@ ***"; GIT_CONFIG=.git/config '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS)
 
+pre-clean:
+       $(RM) -r test-results
+
 clean:
-       $(RM) -r 'trash directory'
+       $(RM) -r 'trash directory' test-results
+
+aggregate-results:
+       ./aggregate-results.sh test-results/t*-*
 
 # we can test NO_OPTIMIZE_COMMITS independently of LC_ALL
 full-svn-test:
        $(MAKE) $(TSVN) GIT_SVN_NO_OPTIMIZE_COMMITS=1 LC_ALL=C
        $(MAKE) $(TSVN) GIT_SVN_NO_OPTIMIZE_COMMITS=0 LC_ALL=en_US.UTF-8
 
-.PHONY: $(T) clean
+.PHONY: pre-clean $(T) aggregate-results clean
 .NOTPARALLEL:
index 70841a4645b2469d8263553a7ba41d4f953774f7..8f12d48fe8b4ffe4a4b37dcd16ce58e50837433f 100644 (file)
--- a/t/README
+++ b/t/README
@@ -54,6 +54,38 @@ You can pass --verbose (or -v), --debug (or -d), and --immediate
        This causes the test to immediately exit upon the first
        failed test.
 
+--long-tests::
+       This causes additional long-running tests to be run (where
+       available), for more exhaustive testing.
+
+
+Skipping Tests
+--------------
+
+In some environments, certain tests have no way of succeeding
+due to platform limitation, such as lack of 'unzip' program, or
+filesystem that do not allow arbitrary sequence of non-NUL bytes
+as pathnames.
+
+You should be able to say something like
+
+    $ GIT_SKIP_TESTS=t9200.8 sh ./t9200-git-cvsexport-commit.sh
+
+and even:
+
+    $ GIT_SKIP_TESTS='t[0-4]??? t91?? t9200.8' make
+
+to omit such tests.  The value of the environment variable is a
+SP separated list of patterns that tells which tests to skip,
+and either can match the "t[0-9]{4}" part to skip the whole
+test, or t[0-9]{4} followed by ".$number" to say which
+particular test to skip.
+
+Note that some tests in the existing test suite rely on previous
+test item, so you cannot arbitrarily disable one and expect the
+remainder of test to check what the test originally was intended
+to check.
+
 
 Naming Tests
 ------------
diff --git a/t/aggregate-results.sh b/t/aggregate-results.sh
new file mode 100755 (executable)
index 0000000..52e88e3
--- /dev/null
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+fixed=0
+success=0
+failed=0
+broken=0
+total=0
+
+for file
+do
+       while read type value
+       do
+               case $type in
+               '')
+                       continue ;;
+               fixed)
+                       fixed=$(($fixed + $value)) ;;
+               success)
+                       success=$(($success + $value)) ;;
+               failed)
+                       failed=$(($failed + $value)) ;;
+               broken)
+                       broken=$(( $broken + $value)) ;;
+               total)
+                       total=$(( $total + $value)) ;;
+               esac
+       done <"$file"
+done
+
+printf "%-8s%d\n" fixed $fixed
+printf "%-8s%d\n" success $success
+printf "%-8s%d\n" failed $failed
+printf "%-8s%d\n" broken $broken
+printf "%-8s%d\n" total $total
index a5c4436fd104e93ca74b11e11bc98238aaf83b29..dc473dfb53d5ffafee72738a55caf21732fa4fb1 100644 (file)
@@ -45,22 +45,22 @@ else
        error "Could not identify web server at '$LIB_HTTPD_PATH'"
 fi
 
-HTTPD_PARA="-d $HTTPD_ROOT_PATH -f $TEST_PATH/apache.conf"
+HTTPD_PARA=""
 
 prepare_httpd() {
-       mkdir -p $HTTPD_DOCUMENT_ROOT_PATH
+       mkdir -p "$HTTPD_DOCUMENT_ROOT_PATH"
 
-       ln -s $LIB_HTTPD_MODULE_PATH $HTTPD_ROOT_PATH/modules
+       ln -s "$LIB_HTTPD_MODULE_PATH" "$HTTPD_ROOT_PATH/modules"
 
        if test -n "$LIB_HTTPD_SSL"
        then
                HTTPD_URL=https://127.0.0.1:$LIB_HTTPD_PORT
 
                RANDFILE_PATH="$HTTPD_ROOT_PATH"/.rnd openssl req \
-                       -config $TEST_PATH/ssl.cnf \
+                       -config "$TEST_PATH/ssl.cnf" \
                        -new -x509 -nodes \
-                       -out $HTTPD_ROOT_PATH/httpd.pem \
-                       -keyout $HTTPD_ROOT_PATH/httpd.pem
+                       -out "$HTTPD_ROOT_PATH/httpd.pem" \
+                       -keyout "$HTTPD_ROOT_PATH/httpd.pem"
                GIT_SSL_NO_VERIFY=t
                export GIT_SSL_NO_VERIFY
                HTTPD_PARA="$HTTPD_PARA -DSSL"
@@ -86,12 +86,14 @@ start_httpd() {
 
        trap 'stop_httpd; die' exit
 
-       "$LIB_HTTPD_PATH" $HTTPD_PARA \
+       "$LIB_HTTPD_PATH" -d "$HTTPD_ROOT_PATH" \
+               -f "$TEST_PATH/apache.conf" $HTTPD_PARA \
                -c "Listen 127.0.0.1:$LIB_HTTPD_PORT" -k start
 }
 
 stop_httpd() {
        trap 'die' exit
 
-       "$LIB_HTTPD_PATH" $HTTPD_PARA -k stop
+       "$LIB_HTTPD_PATH" -d "$HTTPD_ROOT_PATH" \
+               -f "$TEST_PATH/apache.conf" -k stop
 }
index a4473462d10602a7cc57ee792d8e130a8207c38c..4717c2d33b70af6527f8951ec8a414e8caf87095 100644 (file)
@@ -1,3 +1,4 @@
+ServerName dummy
 PidFile httpd.pid
 DocumentRoot www
 ErrorLog error.log
index 690f80ab27fd9ff6d7e145a86eb22c6f87e3cd76..d7cbc5c6dae538fe8c053a2f3760502422615e2c 100755 (executable)
@@ -301,14 +301,14 @@ test_expect_success 'absolute path works as expected' '
        mkdir third &&
        dir="$(cd .git; pwd -P)" &&
        dir2=third/../second/other/.git &&
-       test "$dir" = "$(test-absolute-path $dir2)" &&
+       test "$dir" = "$(test-path-utils make_absolute_path $dir2)" &&
        file="$dir"/index &&
-       test "$file" = "$(test-absolute-path $dir2/index)" &&
+       test "$file" = "$(test-path-utils make_absolute_path $dir2/index)" &&
        basename=blub &&
-       test "$dir/$basename" = "$(cd .git && test-absolute-path "$basename")" &&
+       test "$dir/$basename" = "$(cd .git && test-path-utils make_absolute_path "$basename")" &&
        ln -s ../first/file .git/syml &&
        sym="$(cd first; pwd -P)"/file &&
-       test "$sym" = "$(test-absolute-path "$dir2/syml")"
+       test "$sym" = "$(test-path-utils make_absolute_path "$dir2/syml")"
 '
 
 test_expect_success 'very long name in the index handled sanely' '
index 9255c63c08f06399525ca098d0374ad7d197e0b7..63e1217e7162435c3da8ec7984b5f6a53b3a10e2 100755 (executable)
@@ -8,6 +8,7 @@ test_expect_success setup '
 
        >file &&
        git add file &&
+       test_tick &&
        git commit -m initial &&
        echo >file &&
        git add file
@@ -17,11 +18,11 @@ test_expect_success setup '
 test_expect_success 'write-tree should notice unwritable repository' '
 
        (
-               chmod a-w .git/objects
+               chmod a-w .git/objects .git/objects/?? &&
                test_must_fail git write-tree
        )
        status=$?
-       chmod 775 .git/objects
+       chmod 775 .git/objects .git/objects/??
        (exit $status)
 
 '
@@ -29,11 +30,11 @@ test_expect_success 'write-tree should notice unwritable repository' '
 test_expect_success 'commit should notice unwritable repository' '
 
        (
-               chmod a-w .git/objects
+               chmod a-w .git/objects .git/objects/?? &&
                test_must_fail git commit -m second
        )
        status=$?
-       chmod 775 .git/objects
+       chmod 775 .git/objects .git/objects/??
        (exit $status)
 
 '
@@ -41,12 +42,12 @@ test_expect_success 'commit should notice unwritable repository' '
 test_expect_success 'update-index should notice unwritable repository' '
 
        (
-               echo a >file &&
-               chmod a-w .git/objects
+               echo 6O >file &&
+               chmod a-w .git/objects .git/objects/?? &&
                test_must_fail git update-index file
        )
        status=$?
-       chmod 775 .git/objects
+       chmod 775 .git/objects .git/objects/??
        (exit $status)
 
 '
@@ -55,11 +56,11 @@ test_expect_success 'add should notice unwritable repository' '
 
        (
                echo b >file &&
-               chmod a-w .git/objects
+               chmod a-w .git/objects .git/objects/?? &&
                test_must_fail git add file
        )
        status=$?
-       chmod 775 .git/objects
+       chmod 775 .git/objects .git/objects/??
        (exit $status)
 
 '
diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
new file mode 100755 (executable)
index 0000000..6e7501f
--- /dev/null
@@ -0,0 +1,87 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 David Reiss
+#
+
+test_description='Test various path utilities'
+
+. ./test-lib.sh
+
+norm_abs() {
+       test_expect_success "normalize absolute" \
+       "test \$(test-path-utils normalize_absolute_path '$1') = '$2'"
+}
+
+ancestor() {
+       test_expect_success "longest ancestor" \
+       "test \$(test-path-utils longest_ancestor_length '$1' '$2') = '$3'"
+}
+
+norm_abs "" /
+norm_abs / /
+norm_abs // /
+norm_abs /// /
+norm_abs /. /
+norm_abs /./ /
+norm_abs /./.. /
+norm_abs /../. /
+norm_abs /./../.// /
+norm_abs /dir/.. /
+norm_abs /dir/sub/../.. /
+norm_abs /dir /dir
+norm_abs /dir// /dir
+norm_abs /./dir /dir
+norm_abs /dir/. /dir
+norm_abs /dir///./ /dir
+norm_abs /dir//sub/.. /dir
+norm_abs /dir/sub/../ /dir
+norm_abs //dir/sub/../. /dir
+norm_abs /dir/s1/../s2/ /dir/s2
+norm_abs /d1/s1///s2/..//../s3/ /d1/s3
+norm_abs /d1/s1//../s2/../../d2 /d2
+norm_abs /d1/.../d2 /d1/.../d2
+norm_abs /d1/..././../d2 /d1/d2
+
+ancestor / "" -1
+ancestor / / -1
+ancestor /foo "" -1
+ancestor /foo : -1
+ancestor /foo ::. -1
+ancestor /foo ::..:: -1
+ancestor /foo / 0
+ancestor /foo /fo -1
+ancestor /foo /foo -1
+ancestor /foo /foo/ -1
+ancestor /foo /bar -1
+ancestor /foo /bar/ -1
+ancestor /foo /foo/bar -1
+ancestor /foo /foo:/bar/ -1
+ancestor /foo /foo/:/bar/ -1
+ancestor /foo /foo::/bar/ -1
+ancestor /foo /:/foo:/bar/ 0
+ancestor /foo /foo:/:/bar/ 0
+ancestor /foo /:/bar/:/foo 0
+ancestor /foo/bar "" -1
+ancestor /foo/bar / 0
+ancestor /foo/bar /fo -1
+ancestor /foo/bar foo -1
+ancestor /foo/bar /foo 4
+ancestor /foo/bar /foo/ 4
+ancestor /foo/bar /foo/ba -1
+ancestor /foo/bar /:/fo 0
+ancestor /foo/bar /foo:/foo/ba 4
+ancestor /foo/bar /bar -1
+ancestor /foo/bar /bar/ -1
+ancestor /foo/bar /fo: -1
+ancestor /foo/bar :/fo -1
+ancestor /foo/bar /foo:/bar/ 4
+ancestor /foo/bar /:/foo:/bar/ 4
+ancestor /foo/bar /foo:/:/bar/ 4
+ancestor /foo/bar /:/bar/:/fo 0
+ancestor /foo/bar /:/bar/ 0
+ancestor /foo/bar :://foo/. 4
+ancestor /foo/bar :://foo/.:: 4
+ancestor /foo/bar //foo/./::/bar 4
+ancestor /foo/bar ::/bar -1
+
+test_done
index 6c78c8bc9b76828c258f524e73b40d7daff7c305..dc85e8b60a5c10e57047d1692e383f177e2c478d 100755 (executable)
@@ -17,6 +17,29 @@ test_expect_success 'shared = 0400 (faulty permission u-w)' '
        test $ret != "0"
 '
 
+for u in 002 022
+do
+       test_expect_success "shared=1 does not clear bits preset by umask $u" '
+               mkdir sub && (
+                       cd sub &&
+                       umask $u &&
+                       git init --shared=1 &&
+                       test 1 = "$(git config core.sharedrepository)"
+               ) &&
+               actual=$(ls -l sub/.git/HEAD)
+               case "$actual" in
+               -rw-rw-r--*)
+                       : happy
+                       ;;
+               *)
+                       echo Oops, .git/HEAD is not 0664 but $actual
+                       false
+                       ;;
+               esac
+       '
+       rm -rf sub
+done
+
 test_expect_success 'shared=all' '
        mkdir sub &&
        cd sub &&
index b8b7ab410354b01584092802365f4b53cd991b4a..ca99d37616aaaae9584ecfd1c5d74378c727d077 100755 (executable)
@@ -42,6 +42,14 @@ test_expect_success "delete $m" '
 '
 rm -f .git/$m
 
+test_expect_success "delete $m without oldvalue verification" "
+       git update-ref $m $A &&
+       test $A = \$(cat .git/$m) &&
+       git update-ref -d $m &&
+       ! test -f .git/$m
+"
+rm -f .git/$m
+
 test_expect_success \
        "fail to create $n" \
        "touch .git/$n_dir
@@ -147,7 +155,8 @@ rm -f .git/$m .git/logs/$m expect
 
 git update-ref $m $D
 cat >.git/logs/$m <<EOF
-$C $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150320 -0500
+0000000000000000000000000000000000000000 $C $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150320 -0500
+$C $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150350 -0500
 $A $B $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150380 -0500
 $F $Z $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150680 -0500
 $Z $E $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150980 -0500
@@ -178,6 +187,12 @@ test_expect_success \
        'Query "master@{May 26 2005 23:32:00}" (exactly history start)' \
        'rm -f o e
         git rev-parse --verify "master@{May 26 2005 23:32:00}" >o 2>e &&
+        test '"$C"' = $(cat o) &&
+        test "" = "$(cat e)"'
+test_expect_success \
+       'Query "master@{May 26 2005 23:32:30}" (first non-creation change)' \
+       'rm -f o e
+        git rev-parse --verify "master@{May 26 2005 23:32:30}" >o 2>e &&
         test '"$A"' = $(cat o) &&
         test "" = "$(cat e)"'
 test_expect_success \
index 3508d0a612487be824dfe62eaf2377bc05ae8c17..997002d4c40dd8e66e3be5a701e3d99bab1c57c4 100755 (executable)
@@ -5,7 +5,7 @@ test_description='test git rev-parse --parseopt'
 
 cat > expect.err <<EOF
 usage: some-command [options] <args>...
-    
+
     some-command does foo and bar!
 
     -h, --help            show the help
diff --git a/t/t1504-ceiling-dirs.sh b/t/t1504-ceiling-dirs.sh
new file mode 100755 (executable)
index 0000000..91b704a
--- /dev/null
@@ -0,0 +1,163 @@
+#!/bin/sh
+
+test_description='test GIT_CEILING_DIRECTORIES'
+. ./test-lib.sh
+
+test_prefix() {
+       test_expect_success "$1" \
+       "test '$2' = \"\$(git rev-parse --show-prefix)\""
+}
+
+test_fail() {
+       test_expect_code 128 "$1: prefix" \
+       "git rev-parse --show-prefix"
+}
+
+TRASH_ROOT="$(pwd)"
+ROOT_PARENT=$(dirname "$TRASH_ROOT")
+
+
+unset GIT_CEILING_DIRECTORIES
+test_prefix no_ceil ""
+
+export GIT_CEILING_DIRECTORIES
+
+GIT_CEILING_DIRECTORIES=""
+test_prefix ceil_empty ""
+
+GIT_CEILING_DIRECTORIES="$ROOT_PARENT"
+test_prefix ceil_at_parent ""
+
+GIT_CEILING_DIRECTORIES="$ROOT_PARENT/"
+test_prefix ceil_at_parent_slash ""
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT"
+test_prefix ceil_at_trash ""
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/"
+test_prefix ceil_at_trash_slash ""
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub"
+test_prefix ceil_at_sub ""
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/"
+test_prefix ceil_at_sub_slash ""
+
+
+mkdir -p sub/dir || exit 1
+cd sub/dir || exit 1
+
+unset GIT_CEILING_DIRECTORIES
+test_prefix subdir_no_ceil "sub/dir/"
+
+export GIT_CEILING_DIRECTORIES
+
+GIT_CEILING_DIRECTORIES=""
+test_prefix subdir_ceil_empty "sub/dir/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT"
+test_fail subdir_ceil_at_trash
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/"
+test_fail subdir_ceil_at_trash_slash
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub"
+test_fail subdir_ceil_at_sub
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/"
+test_fail subdir_ceil_at_sub_slash
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/dir"
+test_prefix subdir_ceil_at_subdir "sub/dir/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/dir/"
+test_prefix subdir_ceil_at_subdir_slash "sub/dir/"
+
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su"
+test_prefix subdir_ceil_at_su "sub/dir/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su/"
+test_prefix subdir_ceil_at_su_slash "sub/dir/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/di"
+test_prefix subdir_ceil_at_sub_di "sub/dir/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/di"
+test_prefix subdir_ceil_at_sub_di_slash "sub/dir/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/subdi"
+test_prefix subdir_ceil_at_subdi "sub/dir/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/subdi"
+test_prefix subdir_ceil_at_subdi_slash "sub/dir/"
+
+
+GIT_CEILING_DIRECTORIES="foo:$TRASH_ROOT/sub"
+test_fail second_of_two
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub:bar"
+test_fail first_of_two
+
+GIT_CEILING_DIRECTORIES="foo:$TRASH_ROOT/sub:bar"
+test_fail second_of_three
+
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub"
+GIT_DIR=../../.git
+export GIT_DIR
+test_prefix git_dir_specified ""
+unset GIT_DIR
+
+
+cd ../.. || exit 1
+mkdir -p s/d || exit 1
+cd s/d || exit 1
+
+unset GIT_CEILING_DIRECTORIES
+test_prefix sd_no_ceil "s/d/"
+
+export GIT_CEILING_DIRECTORIES
+
+GIT_CEILING_DIRECTORIES=""
+test_prefix sd_ceil_empty "s/d/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT"
+test_fail sd_ceil_at_trash
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/"
+test_fail sd_ceil_at_trash_slash
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s"
+test_fail sd_ceil_at_s
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/"
+test_fail sd_ceil_at_s_slash
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/d"
+test_prefix sd_ceil_at_sd "s/d/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/d/"
+test_prefix sd_ceil_at_sd_slash "s/d/"
+
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su"
+test_prefix sd_ceil_at_su "s/d/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su/"
+test_prefix sd_ceil_at_su_slash "s/d/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/di"
+test_prefix sd_ceil_at_s_di "s/d/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/di"
+test_prefix sd_ceil_at_s_di_slash "s/d/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sdi"
+test_prefix sd_ceil_at_sdi "s/d/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sdi"
+test_prefix sd_ceil_at_sdi_slash "s/d/"
+
+
+test_done
index b9e3dbd242cc92710d1c689ca5412619e46ee63f..092aa265733b0c6cbf75ac532c3c006457668bc8 100755 (executable)
@@ -96,6 +96,7 @@ chmod a+x fake-editor.sh
 
 test_expect_success 'no changes are a nop' '
        git rebase -i F &&
+       test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch2" &&
        test $(git rev-parse I) = $(git rev-parse HEAD)
 '
 
@@ -104,14 +105,26 @@ test_expect_success 'test the [branch] option' '
        git rm file6 &&
        git commit -m "stop here" &&
        git rebase -i F branch2 &&
+       test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch2" &&
+       test $(git rev-parse I) = $(git rev-parse branch2) &&
        test $(git rev-parse I) = $(git rev-parse HEAD)
 '
 
+test_expect_success 'test --onto <branch>' '
+       git checkout -b test-onto branch2 &&
+       git rebase -i --onto branch1 F &&
+       test "$(git symbolic-ref -q HEAD)" = "refs/heads/test-onto" &&
+       test $(git rev-parse HEAD^) = $(git rev-parse branch1) &&
+       test $(git rev-parse I) = $(git rev-parse branch2)
+'
+
 test_expect_success 'rebase on top of a non-conflicting commit' '
        git checkout branch1 &&
        git tag original-branch1 &&
        git rebase -i branch2 &&
        test file6 = $(git diff --name-only original-branch1) &&
+       test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch1" &&
+       test $(git rev-parse I) = $(git rev-parse branch2) &&
        test $(git rev-parse I) = $(git rev-parse HEAD~2)
 '
 
@@ -144,9 +157,12 @@ EOF
 
 test_expect_success 'stop on conflicting pick' '
        git tag new-branch1 &&
-       ! git rebase -i master &&
+       test_must_fail git rebase -i master &&
+       test "$(git rev-parse HEAD~3)" = "$(git rev-parse master)" &&
        test_cmp expect .git/.dotest-merge/patch &&
        test_cmp expect2 file1 &&
+       test "$(git-diff --name-status |
+               sed -n -e "/^U/s/^U[^a-z]*//p")" = file1 &&
        test 4 = $(grep -v "^#" < .git/.dotest-merge/done | wc -l) &&
        test 0 = $(grep -c "^[^#]" < .git/.dotest-merge/git-rebase-todo)
 '
@@ -154,6 +170,7 @@ test_expect_success 'stop on conflicting pick' '
 test_expect_success 'abort' '
        git rebase --abort &&
        test $(git rev-parse new-branch1) = $(git rev-parse HEAD) &&
+       test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch1" &&
        ! test -d .git/.dotest-merge
 '
 
@@ -194,7 +211,7 @@ test_expect_success 'preserve merges with -p' '
        git add unrelated-file &&
        test_tick &&
        git commit -m "unrelated" &&
-       git checkout -b to-be-rebased master &&
+       git checkout -b another-branch master &&
        echo B > file1 &&
        test_tick &&
        git commit -m J file1 &&
@@ -203,17 +220,33 @@ test_expect_success 'preserve merges with -p' '
        echo C > file1 &&
        test_tick &&
        git commit -m K file1 &&
+       echo D > file1 &&
+       test_tick &&
+       git commit -m L1 file1 &&
+       git checkout HEAD^ &&
+       echo 1 > unrelated-file &&
+       test_tick &&
+       git commit -m L2 unrelated-file &&
+       test_tick &&
+       git merge another-branch &&
+       echo E > file1 &&
+       test_tick &&
+       git commit -m M file1 &&
+       git checkout -b to-be-rebased &&
        test_tick &&
        git rebase -i -p --onto branch1 master &&
-       test $(git rev-parse HEAD^^2) = $(git rev-parse to-be-preserved) &&
-       test $(git rev-parse HEAD~3) = $(git rev-parse branch1) &&
-       test $(git show HEAD:file1) = C &&
-       test $(git show HEAD~2:file1) = B
+       test $(git rev-parse HEAD~6) = $(git rev-parse branch1) &&
+       test $(git rev-parse HEAD~4^2) = $(git rev-parse to-be-preserved) &&
+       test $(git rev-parse HEAD^^2^) = $(git rev-parse HEAD^^^) &&
+       test $(git show HEAD~5:file1) = B &&
+       test $(git show HEAD~3:file1) = C &&
+       test $(git show HEAD:file1) = E &&
+       test $(git show HEAD:unrelated-file) = 1
 '
 
 test_expect_success '--continue tries to commit' '
        test_tick &&
-       ! git rebase -i --onto new-branch1 HEAD^ &&
+       test_must_fail git rebase -i --onto new-branch1 HEAD^ &&
        echo resolved > file1 &&
        git add file1 &&
        FAKE_COMMIT_MESSAGE="chouette!" git rebase --continue &&
@@ -224,7 +257,7 @@ test_expect_success '--continue tries to commit' '
 test_expect_success 'verbose flag is heeded, even after --continue' '
        git reset --hard HEAD@{1} &&
        test_tick &&
-       ! git rebase -v -i --onto new-branch1 HEAD^ &&
+       test_must_fail git rebase -v -i --onto new-branch1 HEAD^ &&
        echo resolved > file1 &&
        git add file1 &&
        git rebase --continue > output &&
@@ -259,10 +292,14 @@ test_expect_success 'interrupted squash works as expected' '
                git commit -m $n
        done &&
        one=$(git rev-parse HEAD~3) &&
-       ! FAKE_LINES="1 squash 3 2" git rebase -i HEAD~3 &&
+       (
+               FAKE_LINES="1 squash 3 2" &&
+               export FAKE_LINES &&
+               test_must_fail git rebase -i HEAD~3
+       ) &&
        (echo one; echo two; echo four) > conflict &&
        git add conflict &&
-       ! git rebase --continue &&
+       test_must_fail git rebase --continue &&
        echo resolved > conflict &&
        git add conflict &&
        git rebase --continue &&
@@ -277,13 +314,17 @@ test_expect_success 'interrupted squash works as expected (case 2)' '
                git commit -m $n
        done &&
        one=$(git rev-parse HEAD~3) &&
-       ! FAKE_LINES="3 squash 1 2" git rebase -i HEAD~3 &&
+       (
+               FAKE_LINES="3 squash 1 2" &&
+               export FAKE_LINES &&
+               test_must_fail git rebase -i HEAD~3
+       ) &&
        (echo one; echo four) > conflict &&
        git add conflict &&
-       ! git rebase --continue &&
+       test_must_fail git rebase --continue &&
        (echo one; echo two; echo four) > conflict &&
        git add conflict &&
-       ! git rebase --continue &&
+       test_must_fail git rebase --continue &&
        echo resolved > conflict &&
        git add conflict &&
        git rebase --continue &&
@@ -331,7 +372,7 @@ test_expect_success 'rebase a commit violating pre-commit' '
        chmod a+x $PRE_COMMIT &&
        echo "monde! " >> file1 &&
        test_tick &&
-       ! git commit -m doesnt-verify file1 &&
+       test_must_fail git commit -m doesnt-verify file1 &&
        git commit -m doesnt-verify --no-verify file1 &&
        test_tick &&
        FAKE_LINES=2 git rebase -i HEAD~2
diff --git a/t/t3503-cherry-pick-root.sh b/t/t3503-cherry-pick-root.sh
new file mode 100755 (executable)
index 0000000..b0faa29
--- /dev/null
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+test_description='test cherry-picking a root commit'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+
+       echo first > file1 &&
+       git add file1 &&
+       test_tick &&
+       git commit -m "first" &&
+
+       git symbolic-ref HEAD refs/heads/second &&
+       rm .git/index file1 &&
+       echo second > file2 &&
+       git add file2 &&
+       test_tick &&
+       git commit -m "second"
+
+'
+
+test_expect_success 'cherry-pick a root commit' '
+
+       git cherry-pick master &&
+       test first = $(cat file1)
+
+'
+
+test_done
index fae64eae9f9ff9b34b935e8556df61d2093425cf..e95663d8e66d5b94e574a6b956625fccfd341a05 100755 (executable)
@@ -66,6 +66,73 @@ test_expect_success 'revert works (commit)' '
        grep "unchanged *+3/-0 file" output
 '
 
+cat >expected <<EOF
+EOF
+cat >fake_editor.sh <<EOF
+EOF
+chmod a+x fake_editor.sh
+test_set_editor "$(pwd)/fake_editor.sh"
+test_expect_success 'dummy edit works' '
+       (echo e; echo a) | git add -p &&
+       git diff > diff &&
+       test_cmp expected diff
+'
+
+cat >patch <<EOF
+@@ -1,1 +1,4 @@
+ this
++patch
+-doesn't
+ apply
+EOF
+echo "#!$SHELL_PATH" >fake_editor.sh
+cat >>fake_editor.sh <<\EOF
+mv -f "$1" oldpatch &&
+mv -f patch "$1"
+EOF
+chmod a+x fake_editor.sh
+test_set_editor "$(pwd)/fake_editor.sh"
+test_expect_success 'bad edit rejected' '
+       git reset &&
+       (echo e; echo n; echo d) | git add -p >output &&
+       grep "hunk does not apply" output
+'
+
+cat >patch <<EOF
+this patch
+is garbage
+EOF
+test_expect_success 'garbage edit rejected' '
+       git reset &&
+       (echo e; echo n; echo d) | git add -p >output &&
+       grep "hunk does not apply" output
+'
+
+cat >patch <<EOF
+@@ -1,0 +1,0 @@
+ baseline
++content
++newcontent
++lines
+EOF
+cat >expected <<EOF
+diff --git a/file b/file
+index b5dd6c9..f910ae9 100644
+--- a/file
++++ b/file
+@@ -1,4 +1,4 @@
+ baseline
+ content
+-newcontent
++more
+ lines
+EOF
+test_expect_success 'real edit works' '
+       (echo e; echo n; echo d) | git add -p &&
+       git diff >output &&
+       test_cmp expected output
+'
+
 if test "$(git config --bool core.filemode)" = false
 then
     say 'skipping filemode tests (filesystem does not properly support modes)'
index df1fd6f86f11b40667dfbd8132fef8da45d03d75..c851db8ca9373a890ede7c230710690d5b4b4165 100755 (executable)
@@ -241,11 +241,11 @@ check_verify_failure 'disallow spaces in tag email' \
 ############################################################
 # 17. disallow missing tag timestamp
 
-cat >tag.sig <<EOF
+tr '_' ' ' >tag.sig <<EOF
 object $head
 type commit
 tag mytag
-tagger T A Gger <tagger@example.com>  
+tagger T A Gger <tagger@example.com>__
 
 EOF
 
index 2d3ee3b78c66e4e964fffccaa1ae8252929c1732..8d4804b65818f7fc55f0c0736fde673ac7512a8a 100755 (executable)
@@ -41,7 +41,7 @@ test_expect_success 'apply needs clean working directory' '
        echo 4 > other-file &&
        git add other-file &&
        echo 5 > other-file &&
-       test_must_fail git stash apply
+       test_must_fail git stash apply
 '
 
 test_expect_success 'apply stashed changes' '
@@ -117,4 +117,64 @@ test_expect_success 'stash pop' '
        test 0 = $(git stash list | wc -l)
 '
 
+cat > expect << EOF
+diff --git a/file2 b/file2
+new file mode 100644
+index 0000000..1fe912c
+--- /dev/null
++++ b/file2
+@@ -0,0 +1 @@
++bar2
+EOF
+
+cat > expect1 << EOF
+diff --git a/file b/file
+index 257cc56..5716ca5 100644
+--- a/file
++++ b/file
+@@ -1 +1 @@
+-foo
++bar
+EOF
+
+cat > expect2 << EOF
+diff --git a/file b/file
+index 7601807..5716ca5 100644
+--- a/file
++++ b/file
+@@ -1 +1 @@
+-baz
++bar
+diff --git a/file2 b/file2
+new file mode 100644
+index 0000000..1fe912c
+--- /dev/null
++++ b/file2
+@@ -0,0 +1 @@
++bar2
+EOF
+
+test_expect_success 'stash branch' '
+       echo foo > file &&
+       git commit file -m first
+       echo bar > file &&
+       echo bar2 > file2 &&
+       git add file2 &&
+       git stash &&
+       echo baz > file &&
+       git commit file -m second &&
+       git stash branch stashbranch &&
+       test refs/heads/stashbranch = $(git symbolic-ref HEAD) &&
+       test $(git rev-parse HEAD) = $(git rev-parse master^) &&
+       git diff --cached > output &&
+       test_cmp output expect &&
+       git diff > output &&
+       test_cmp output expect1 &&
+       git add file &&
+       git commit -m alternate\ second &&
+       git diff master..stashbranch > output &&
+       test_cmp output expect2 &&
+       test 0 = $(git stash list | wc -l)
+'
+
 test_done
index 3583e68e92148a5145b82f93ec8a52fd4bb7f200..7fe853c20d1111e40371a3796d82bb8485f5ebcf 100755 (executable)
@@ -98,7 +98,7 @@ test_expect_success 'extra headers' '
        sed -e "/^$/q" patch2 > hdrs2 &&
        grep "^To: R. E. Cipient <rcipient@example.com>$" hdrs2 &&
        grep "^Cc: S. E. Cipient <scipient@example.com>$" hdrs2
-       
+
 '
 
 test_expect_success 'extra headers without newlines' '
@@ -109,7 +109,7 @@ test_expect_success 'extra headers without newlines' '
        sed -e "/^$/q" patch3 > hdrs3 &&
        grep "^To: R. E. Cipient <rcipient@example.com>$" hdrs3 &&
        grep "^Cc: S. E. Cipient <scipient@example.com>$" hdrs3
-       
+
 '
 
 test_expect_success 'extra headers with multiple To:s' '
@@ -170,7 +170,7 @@ test_expect_success 'thread cover-letter' '
        git checkout side &&
        git format-patch --cover-letter --thread -o patches/ master &&
        FIRST_MID=$(grep "Message-Id:" patches/0000-* | sed "s/^[^<]*\(<[^>]*>\).*$/\1/") &&
-       for i in patches/0001-* patches/0002-* patches/0003-* 
+       for i in patches/0001-* patches/0002-* patches/0003-*
        do
          grep "References: $FIRST_MID" $i &&
          grep "In-Reply-To: $FIRST_MID" $i || break
index ca0302f41b332df053baa72362099ba691f2ff97..0922c708f16fea490a85d16d5d4d366df0fb2088 100755 (executable)
@@ -62,16 +62,16 @@ EOF
 
 git update-index x
 
-cat << EOF > x
+tr '_' ' ' << EOF > x
        whitespace at beginning
 whitespace      change
 white space in the middle
-whitespace at end  
+whitespace at end__
 unchanged line
 CR at end
 EOF
 
-tr 'Q' '\015' << EOF > expect
+tr 'Q_' '\015 ' << EOF > expect
 diff --git a/x b/x
 index d99af23..8b32fb5 100644
 --- a/x
@@ -84,7 +84,7 @@ index d99af23..8b32fb5 100644
 +      whitespace at beginning
 +whitespace     change
 +white space in the middle
-+whitespace at end  
++whitespace at end__
  unchanged line
 -CR at endQ
 +CR at end
@@ -335,4 +335,10 @@ test_expect_success 'line numbers in --check output are correct' '
 
 '
 
+test_expect_success 'checkdiff detects trailing blank lines' '
+       echo "foo();" >x &&
+       echo "" >>x &&
+       git diff --check | grep "ends with blank"
+'
+
 test_done
index 0950250c9be7f7833b7542f5491a4dad8f5ef82e..f07035ab7ec72557be7a0cba9ea286bcbaa79da9 100755 (executable)
@@ -53,13 +53,13 @@ test_expect_success 'git diff --summary -M HEAD' '
 '
 
 cat >expect <<\EOF
- pathname.1 => "Rpathname\twith HT.0"            |    0 
- pathname.3 => "Rpathname\nwith LF.0"            |    0 
- "pathname\twith HT.3" => "Rpathname\nwith LF.1" |    0 
- pathname.2 => Rpathname with SP.0               |    0 
- "pathname\twith HT.2" => Rpathname with SP.1    |    0 
- pathname.0 => Rpathname.0                       |    0 
- "pathname\twith HT.0" => Rpathname.1            |    0 
+ pathname.1 => "Rpathname\twith HT.0"            |    0
+ pathname.3 => "Rpathname\nwith LF.0"            |    0
+ "pathname\twith HT.3" => "Rpathname\nwith LF.1" |    0
+ pathname.2 => Rpathname with SP.0               |    0
+ "pathname\twith HT.2" => Rpathname with SP.1    |    0
+ pathname.0 => Rpathname.0                       |    0
+ "pathname\twith HT.0" => Rpathname.1            |    0
  7 files changed, 0 insertions(+), 0 deletions(-)
 EOF
 test_expect_success 'git diff --stat -M HEAD' '
index 0d0fb87f5732e3ecbca8a195843070539353701e..60dd2014d5ae5d5e9e168b8b60278d90ef93cc53 100755 (executable)
@@ -113,4 +113,18 @@ test_expect_success 'check should test not just the last line' '
 
 '
 
+test_expect_success 'check detects leftover conflict markers' '
+       git reset --hard &&
+       git checkout HEAD^ &&
+       echo binary >>b &&
+       git commit -m "side" b &&
+       test_must_fail git merge master &&
+       git add b && (
+               git --no-pager diff --cached --check >test.out
+               test $? = 2
+       ) &&
+       test 3 = $(grep "conflict marker" test.out | wc -l) &&
+       git reset --hard
+'
+
 test_done
index 8073a5a1f23ebb76cb1273c80d1e031a03a03ed8..e0c67740a5ef85aaa3edc9a4514da72c92ce30ec 100755 (executable)
@@ -3,44 +3,38 @@
 # Copyright (c) 2005 Junio C Hamano
 #
 
-test_description='git apply --stat --summary test.
+test_description='git apply --stat --summary test, with --recount
 
 '
 . ./test-lib.sh
 
-test_expect_success \
-    'rename' \
-    'git apply --stat --summary <../t4100/t-apply-1.patch >current &&
-    test_cmp ../t4100/t-apply-1.expect current'
-
-test_expect_success \
-    'copy' \
-    'git apply --stat --summary <../t4100/t-apply-2.patch >current &&
-    test_cmp ../t4100/t-apply-2.expect current'
-
-test_expect_success \
-    'rewrite' \
-    'git apply --stat --summary <../t4100/t-apply-3.patch >current &&
-    test_cmp ../t4100/t-apply-3.expect current'
-
-test_expect_success \
-    'mode' \
-    'git apply --stat --summary <../t4100/t-apply-4.patch >current &&
-    test_cmp ../t4100/t-apply-4.expect current'
-
-test_expect_success \
-    'non git' \
-    'git apply --stat --summary <../t4100/t-apply-5.patch >current &&
-    test_cmp ../t4100/t-apply-5.expect current'
-
-test_expect_success \
-    'non git' \
-    'git apply --stat --summary <../t4100/t-apply-6.patch >current &&
-    test_cmp ../t4100/t-apply-6.expect current'
-
-test_expect_success \
-    'non git' \
-    'git apply --stat --summary <../t4100/t-apply-7.patch >current &&
-    test_cmp ../t4100/t-apply-7.expect current'
+UNC='s/^\(@@ -[1-9][0-9]*\),[0-9]* \(+[1-9][0-9]*\),[0-9]* @@/\1,999 \2,999 @@/'
+
+num=0
+while read title
+do
+       num=$(( $num + 1 ))
+       test_expect_success "$title" '
+               git apply --stat --summary \
+                       <"$TEST_DIRECTORY/t4100/t-apply-$num.patch" >current &&
+               test_cmp ../t4100/t-apply-$num.expect current
+       '
+
+       test_expect_success "$title with recount" '
+               sed -e "$UNC" <"$TEST_DIRECTORY/t4100/t-apply-$num.patch" |
+               git apply --recount --stat --summary >current &&
+               test_cmp ../t4100/t-apply-$num.expect current
+       '
+done <<\EOF
+rename
+copy
+rewrite
+mode
+non git (1)
+non git (2)
+non git (3)
+incomplete (1)
+incomplete (2)
+EOF
 
 test_done
diff --git a/t/t4100/t-apply-8.expect b/t/t4100/t-apply-8.expect
new file mode 100644 (file)
index 0000000..eef7f2e
--- /dev/null
@@ -0,0 +1,2 @@
+ t/t4100-apply-stat.sh |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/t/t4100/t-apply-8.patch b/t/t4100/t-apply-8.patch
new file mode 100644 (file)
index 0000000..5ca13e6
--- /dev/null
@@ -0,0 +1,11 @@
+diff --git a/t/t4100-apply-stat.sh b/t/t4100-apply-stat.sh
+index be837bb..0798c64 100755
+--- a/t/t4100-apply-stat.sh
++++ b/t/t4100-apply-stat.sh
+@@ -35,4 +35,4 @@ non git (2)
+ non git (3)
+ EOF
+-test_done
++test_done
+\ No newline at end of file
diff --git a/t/t4100/t-apply-9.expect b/t/t4100/t-apply-9.expect
new file mode 100644 (file)
index 0000000..eef7f2e
--- /dev/null
@@ -0,0 +1,2 @@
+ t/t4100-apply-stat.sh |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/t/t4100/t-apply-9.patch b/t/t4100/t-apply-9.patch
new file mode 100644 (file)
index 0000000..875d57d
--- /dev/null
@@ -0,0 +1,11 @@
+diff --git a/t/t4100-apply-stat.sh b/t/t4100-apply-stat.sh
+index 0798c64..be837bb 100755
+--- a/t/t4100-apply-stat.sh
++++ b/t/t4100-apply-stat.sh
+@@ -35,4 +35,4 @@ non git (2)
+ non git (3)
+ EOF
+-test_done
+\ No newline at end of file
++test_done
index bd40a218cd81fdcb4417cb693cfbf047bc0e64c7..ff5fdf35f99e4c50d1bd27eeacd816c37cc5bdfa 100755 (executable)
@@ -9,134 +9,10 @@ test_description='git apply test patches with multiple fragments.
 '
 . ./test-lib.sh
 
-# setup
-
-cat > patch1.patch <<\EOF
-diff --git a/main.c b/main.c
-new file mode 100644
---- /dev/null
-+++ b/main.c
-@@ -0,0 +1,23 @@
-+#include <stdio.h>
-+
-+int func(int num);
-+void print_int(int num);
-+
-+int main() {
-+      int i;
-+
-+      for (i = 0; i < 10; i++) {
-+              print_int(func(i));
-+      }
-+
-+      return 0;
-+}
-+
-+int func(int num) {
-+      return num * num;
-+}
-+
-+void print_int(int num) {
-+      printf("%d", num);
-+}
-+
-EOF
-cat > patch2.patch <<\EOF
-diff --git a/main.c b/main.c
---- a/main.c
-+++ b/main.c
-@@ -1,7 +1,9 @@
-+#include <stdlib.h>
- #include <stdio.h>
- int func(int num);
- void print_int(int num);
-+void print_ln();
- int main() {
-       int i;
-@@ -10,6 +12,8 @@
-               print_int(func(i));
-       }
-+      print_ln();
-+
-       return 0;
- }
-@@ -21,3 +25,7 @@
-       printf("%d", num);
- }
-+void print_ln() {
-+      printf("\n");
-+}
-+
-EOF
-cat > patch3.patch <<\EOF
-diff --git a/main.c b/main.c
---- a/main.c
-+++ b/main.c
-@@ -1,9 +1,7 @@
--#include <stdlib.h>
- #include <stdio.h>
- int func(int num);
- void print_int(int num);
--void print_ln();
- int main() {
-       int i;
-@@ -12,8 +10,6 @@
-               print_int(func(i));
-       }
--      print_ln();
--
-       return 0;
- }
-@@ -25,7 +21,3 @@
-       printf("%d", num);
- }
--void print_ln() {
--      printf("\n");
--}
--
-EOF
-cat > patch4.patch <<\EOF
-diff --git a/main.c b/main.c
---- a/main.c
-+++ b/main.c
-@@ -1,13 +1,14 @@
- #include <stdio.h>
- int func(int num);
--void print_int(int num);
-+int func2(int num);
- int main() {
-       int i;
-       for (i = 0; i < 10; i++) {
--              print_int(func(i));
-+              printf("%d", func(i));
-+              printf("%d", func3(i));
-       }
-       return 0;
-@@ -17,7 +18,7 @@
-       return num * num;
- }
--void print_int(int num) {
--      printf("%d", num);
-+int func2(int num) {
-+      return num * num * num;
- }
-EOF
+cp ../t4109/patch1.patch .
+cp ../t4109/patch2.patch .
+cp ../t4109/patch3.patch .
+cp ../t4109/patch4.patch .
 
 test_expect_success "S = git apply (1)" \
     'git apply patch1.patch patch2.patch'
diff --git a/t/t4109/patch1.patch b/t/t4109/patch1.patch
new file mode 100644 (file)
index 0000000..1d411fc
--- /dev/null
@@ -0,0 +1,28 @@
+diff --git a/main.c b/main.c
+new file mode 100644
+--- /dev/null
++++ b/main.c
+@@ -0,0 +1,23 @@
++#include <stdio.h>
++
++int func(int num);
++void print_int(int num);
++
++int main() {
++      int i;
++
++      for (i = 0; i < 10; i++) {
++              print_int(func(i));
++      }
++
++      return 0;
++}
++
++int func(int num) {
++      return num * num;
++}
++
++void print_int(int num) {
++      printf("%d", num);
++}
++
diff --git a/t/t4109/patch2.patch b/t/t4109/patch2.patch
new file mode 100644 (file)
index 0000000..8c6b06d
--- /dev/null
@@ -0,0 +1,30 @@
+diff --git a/main.c b/main.c
+--- a/main.c
++++ b/main.c
+@@ -1,7 +1,9 @@
++#include <stdlib.h>
+ #include <stdio.h>
+ int func(int num);
+ void print_int(int num);
++void print_ln();
+ int main() {
+       int i;
+@@ -10,6 +12,8 @@
+               print_int(func(i));
+       }
++      print_ln();
++
+       return 0;
+ }
+@@ -21,3 +25,7 @@
+       printf("%d", num);
+ }
++void print_ln() {
++      printf("\n");
++}
++
diff --git a/t/t4109/patch3.patch b/t/t4109/patch3.patch
new file mode 100644 (file)
index 0000000..d696c55
--- /dev/null
@@ -0,0 +1,31 @@
+cat > patch3.patch <<\EOF
+diff --git a/main.c b/main.c
+--- a/main.c
++++ b/main.c
+@@ -1,9 +1,7 @@
+-#include <stdlib.h>
+ #include <stdio.h>
+ int func(int num);
+ void print_int(int num);
+-void print_ln();
+ int main() {
+       int i;
+@@ -12,8 +10,6 @@
+               print_int(func(i));
+       }
+-      print_ln();
+-
+       return 0;
+ }
+@@ -25,7 +21,3 @@
+       printf("%d", num);
+ }
+-void print_ln() {
+-      printf("\n");
+-}
+-
diff --git a/t/t4109/patch4.patch b/t/t4109/patch4.patch
new file mode 100644 (file)
index 0000000..4b08590
--- /dev/null
@@ -0,0 +1,30 @@
+diff --git a/main.c b/main.c
+--- a/main.c
++++ b/main.c
+@@ -1,13 +1,14 @@
+ #include <stdio.h>
+ int func(int num);
+-void print_int(int num);
++int func2(int num);
+ int main() {
+       int i;
+       for (i = 0; i < 10; i++) {
+-              print_int(func(i));
++              printf("%d", func(i));
++              printf("%d", func3(i));
+       }
+       return 0;
+@@ -17,7 +18,7 @@
+       return num * num;
+ }
+-void print_int(int num) {
+-      printf("%d", num);
++int func2(int num) {
++      return num * num * num;
+ }
index 70a1859503c7ee6a5b1a6db19174c1c359eec13f..f9ad183758c28ff648890d1bd4bbd599562cd795 100755 (executable)
@@ -36,6 +36,9 @@ typedef struct __jmp_buf jmp_buf[1];
 
 #endif /* _SETJMP_H */
 EOF
+cat >klibc/README <<\EOF
+This is a simple readme file.
+EOF
 
 cat >patch <<\EOF
 diff --git a/klibc/arch/x86_64/include/klibc/archsetjmp.h b/include/arch/cris/klibc/archsetjmp.h
@@ -113,6 +116,23 @@ rename to include/arch/m32r/klibc/archsetjmp.h
 
 -#endif /* _SETJMP_H */
 +#endif /* _KLIBC_ARCHSETJMP_H */
+diff --git a/klibc/README b/klibc/README
+--- a/klibc/README
++++ b/klibc/README
+@@ -1,1 +1,4 @@
+ This is a simple readme file.
++And we add a few
++lines at the
++end of it.
+diff --git a/klibc/README b/klibc/arch/README
+copy from klibc/README
+copy to klibc/arch/README
+--- a/klibc/README
++++ b/klibc/arch/README
+@@ -1,1 +1,3 @@
+ This is a simple readme file.
++And we copy it to one level down, and
++add a few lines at the end of it.
 EOF
 
 find klibc -type f -print | xargs git update-index --add --
index b540f7295a1bb48bf044d297201b07aca9fb5005..3c73a783a7e908070308fb1f972f6b5d152e12a4 100755 (executable)
@@ -19,12 +19,12 @@ test_expect_success setup '
 '
 
 # Also handcraft GNU diff output; note this has trailing whitespace.
-cat >gpatch.file <<\EOF &&
+tr '_' ' ' >gpatch.file <<\EOF &&
 --- file1      2007-02-21 01:04:24.000000000 -0800
 +++ file1+     2007-02-21 01:07:44.000000000 -0800
 @@ -1 +1 @@
 -A
-+B 
++B_
 EOF
 
 sed -e 's|file1|sub/&|' gpatch.file >gpatch-sub.file &&
diff --git a/t/t4127-apply-same-fn.sh b/t/t4127-apply-same-fn.sh
new file mode 100755 (executable)
index 0000000..1f859dd
--- /dev/null
@@ -0,0 +1,90 @@
+#!/bin/sh
+
+test_description='apply same filename'
+
+. ./test-lib.sh
+
+modify () {
+       sed -e "$1" < "$2" > "$2".x &&
+       mv "$2".x "$2"
+}
+
+test_expect_success setup '
+       for i in a b c d e f g h i j k l m
+       do
+               echo $i
+       done >same_fn &&
+       cp same_fn other_fn &&
+       git add same_fn other_fn &&
+       git commit -m initial
+'
+test_expect_success 'apply same filename with independent changes' '
+       modify "s/^d/z/" same_fn &&
+       git diff > patch0 &&
+       git add same_fn &&
+       modify "s/^i/y/" same_fn &&
+       git diff >> patch0 &&
+       cp same_fn same_fn2 &&
+       git reset --hard &&
+       git-apply patch0 &&
+       diff same_fn same_fn2
+'
+
+test_expect_success 'apply same filename with overlapping changes' '
+       git reset --hard
+       modify "s/^d/z/" same_fn &&
+       git diff > patch0 &&
+       git add same_fn &&
+       modify "s/^e/y/" same_fn &&
+       git diff >> patch0 &&
+       cp same_fn same_fn2 &&
+       git reset --hard &&
+       git-apply patch0 &&
+       diff same_fn same_fn2
+'
+
+test_expect_success 'apply same new filename after rename' '
+       git reset --hard
+       git mv same_fn new_fn
+       modify "s/^d/z/" new_fn &&
+       git add new_fn &&
+       git diff -M --cached > patch1 &&
+       modify "s/^e/y/" new_fn &&
+       git diff >> patch1 &&
+       cp new_fn new_fn2 &&
+       git reset --hard &&
+       git apply --index patch1 &&
+       diff new_fn new_fn2
+'
+
+test_expect_success 'apply same old filename after rename -- should fail.' '
+       git reset --hard
+       git mv same_fn new_fn
+       modify "s/^d/z/" new_fn &&
+       git add new_fn &&
+       git diff -M --cached > patch1 &&
+       git mv new_fn same_fn
+       modify "s/^e/y/" same_fn &&
+       git diff >> patch1 &&
+       git reset --hard &&
+       test_must_fail git apply patch1
+'
+
+test_expect_success 'apply A->B (rename), C->A (rename), A->A -- should pass.' '
+       git reset --hard
+       git mv same_fn new_fn
+       modify "s/^d/z/" new_fn &&
+       git add new_fn &&
+       git diff -M --cached > patch1 &&
+       git commit -m "a rename" &&
+       git mv other_fn same_fn
+       modify "s/^e/y/" same_fn &&
+       git add same_fn &&
+       git diff -M --cached >> patch1 &&
+       modify "s/^g/x/" same_fn &&
+       git diff >> patch1 &&
+       git reset --hard HEAD^ &&
+       git apply patch1
+'
+
+test_done
diff --git a/t/t4128-apply-root.sh b/t/t4128-apply-root.sh
new file mode 100755 (executable)
index 0000000..2dd0c75
--- /dev/null
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+test_description='apply same filename'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+
+       mkdir -p some/sub/dir &&
+       echo Hello > some/sub/dir/file &&
+       git add some/sub/dir/file &&
+       git commit -m initial &&
+       git tag initial
+
+'
+
+cat > patch << EOF
+diff a/bla/blub/dir/file b/bla/blub/dir/file
+--- a/bla/blub/dir/file
++++ b/bla/blub/dir/file
+@@ -1,1 +1,1 @@
+-Hello
++Bello
+EOF
+
+test_expect_success 'apply --directory -p (1)' '
+
+       git apply --directory=some/sub -p3 --index patch &&
+       test Bello = $(git show :some/sub/dir/file) &&
+       test Bello = $(cat some/sub/dir/file)
+
+'
+
+test_expect_success 'apply --directory -p (2) ' '
+
+       git reset --hard initial &&
+       git apply --directory=some/sub/ -p3 --index patch &&
+       test Bello = $(git show :some/sub/dir/file) &&
+       test Bello = $(cat some/sub/dir/file)
+
+'
+
+test_done
index 722ae96cd5d320e3a8d5771e81d76165b3166b3e..bc982607d09bbdeb0d486eb282f5756a48ae5bcb 100755 (executable)
@@ -110,7 +110,7 @@ test_expect_success 'am applies patch correctly' '
 
 GIT_AUTHOR_NAME="Another Thor"
 GIT_AUTHOR_EMAIL="a.thor@example.com"
-GIT_COMMITTER_NAME="Co M Miter" 
+GIT_COMMITTER_NAME="Co M Miter"
 GIT_COMMITTER_EMAIL="c.miter@example.com"
 export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL
 
index 85d7e3edcd04be761167ca87cb39a1597908201e..a64727d5ad00cb222e3020b6702e4f89e212039c 100755 (executable)
@@ -193,9 +193,19 @@ test_expect_success 'resolution was recorded properly' '
        echo Bello > file3 &&
        git add file3 &&
        git commit -m version2 &&
-       ! git merge fifth &&
-       git diff-files -q &&
-       test Cello = "$(cat file3)"
+       git tag version2 &&
+       test_must_fail git merge fifth &&
+       test Cello = "$(cat file3)" &&
+       test 0 != $(git ls-files -u | wc -l)
+'
+
+test_expect_success 'rerere.autoupdate' '
+       git config rerere.autoupdate true
+       git reset --hard &&
+       git checkout version2 &&
+       test_must_fail git merge fifth &&
+       test 0 = $(git ls-files -u | wc -l)
+
 '
 
 test_done
index 9b0baac8db4b342206d37ab5eaff0b7a09d33967..3f1e25d921c2e90176d8487ae0519af2cbd1e17b 100755 (executable)
@@ -44,6 +44,11 @@ test_expect_success \
       echo text >file_with_long_path) &&
      (cd a && find .) | sort >a.lst'
 
+test_expect_success \
+    'add ignored file' \
+    'echo ignore me >a/ignored &&
+     echo ignored export-ignore >.gitattributes'
+
 test_expect_success \
     'add files to repository' \
     'find a -type f | xargs git update-index --add &&
@@ -53,6 +58,10 @@ test_expect_success \
      git update-ref HEAD $(TZ=GMT GIT_COMMITTER_DATE="2005-05-27 22:00:00" \
      git commit-tree $treeid </dev/null)'
 
+test_expect_success \
+    'remove ignored file' \
+    'rm a/ignored'
+
 test_expect_success \
     'git archive' \
     'git archive HEAD >b.tar'
index 09fd91767297a8c59edb08944740bbcf08f8a7c4..ecec5916346ce76936a807ebc769c3981fc0bf8c 100755 (executable)
@@ -162,4 +162,18 @@ test_expect_success \
     '[index v2] 5) pack-objects refuses to reuse corrupted data' \
     '! git pack-objects test-5 <obj-list'
 
+test_expect_success \
+    '[index v2] 6) verify-pack detects CRC mismatch' \
+    'rm -f .git/objects/pack/* &&
+     git-index-pack --index-version=2 --stdin < "test-1-${pack1}.pack" &&
+     git verify-pack ".git/objects/pack/pack-${pack1}.pack" &&
+     chmod +w ".git/objects/pack/pack-${pack1}.idx" &&
+     dd if=/dev/zero of=".git/objects/pack/pack-${pack1}.idx" conv=notrunc \
+        bs=1 count=4 seek=$((8 + 256 * 4 + `wc -l <obj-list` * 20 + 0)) &&
+     ( while read obj
+       do git cat-file -p $obj >/dev/null || exit 1
+       done <obj-list ) &&
+     err=$(! git verify-pack ".git/objects/pack/pack-${pack1}.pack" 2>&1) &&
+     echo "$err" | grep "CRC mismatch"'
+
 test_done
diff --git a/t/t5303-pack-corruption-resilience.sh b/t/t5303-pack-corruption-resilience.sh
new file mode 100755 (executable)
index 0000000..31b20b2
--- /dev/null
@@ -0,0 +1,194 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Nicolas Pitre
+#
+
+test_description='resilience to pack corruptions with redundant objects'
+. ./test-lib.sh
+
+# Note: the test objects are created with knowledge of their pack encoding
+# to ensure good code path coverage, and to facilitate direct alteration
+# later on.  The assumed characteristics are:
+#
+# 1) blob_2 is a delta with blob_1 for base and blob_3 is a delta with blob2
+#    for base, such that blob_3 delta depth is 2;
+#
+# 2) the bulk of object data is uncompressible so the text part remains
+#    visible;
+#
+# 3) object header is always 2 bytes.
+
+create_test_files() {
+    test-genrandom "foo" 2000 > file_1 &&
+    test-genrandom "foo" 1800 > file_2 &&
+    test-genrandom "foo" 1800 > file_3 &&
+    echo " base " >> file_1 &&
+    echo " delta1 " >> file_2 &&
+    echo " delta delta2 " >> file_3 &&
+    test-genrandom "bar" 150 >> file_2 &&
+    test-genrandom "baz" 100 >> file_3
+}
+
+create_new_pack() {
+    rm -rf .git &&
+    git init &&
+    blob_1=`git hash-object -t blob -w file_1` &&
+    blob_2=`git hash-object -t blob -w file_2` &&
+    blob_3=`git hash-object -t blob -w file_3` &&
+    pack=`printf "$blob_1\n$blob_2\n$blob_3\n" |
+          git pack-objects $@ .git/objects/pack/pack` &&
+    pack=".git/objects/pack/pack-${pack}" &&
+    git verify-pack -v ${pack}.pack
+}
+
+do_corrupt_object() {
+    ofs=`git show-index < ${pack}.idx | grep $1 | cut -f1 -d" "` &&
+    ofs=$(($ofs + $2)) &&
+    chmod +w ${pack}.pack &&
+    dd if=/dev/zero of=${pack}.pack count=1 bs=1 conv=notrunc seek=$ofs &&
+    test_must_fail git verify-pack ${pack}.pack
+}
+
+test_expect_success \
+    'initial setup validation' \
+    'create_test_files &&
+     create_new_pack &&
+     git prune-packed &&
+     git cat-file blob $blob_1 > /dev/null &&
+     git cat-file blob $blob_2 > /dev/null &&
+     git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    'create corruption in header of first object' \
+    'do_corrupt_object $blob_1 0 &&
+     test_must_fail git cat-file blob $blob_1 > /dev/null &&
+     test_must_fail git cat-file blob $blob_2 > /dev/null &&
+     test_must_fail git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    '... but having a loose copy allows for full recovery' \
+    'mv ${pack}.idx tmp &&
+     git hash-object -t blob -w file_1 &&
+     mv tmp ${pack}.idx &&
+     git cat-file blob $blob_1 > /dev/null &&
+     git cat-file blob $blob_2 > /dev/null &&
+     git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    '... and loose copy of first delta allows for partial recovery' \
+    'git prune-packed &&
+     test_must_fail git cat-file blob $blob_2 > /dev/null &&
+     mv ${pack}.idx tmp &&
+     git hash-object -t blob -w file_2 &&
+     mv tmp ${pack}.idx &&
+     test_must_fail git cat-file blob $blob_1 > /dev/null &&
+     git cat-file blob $blob_2 > /dev/null &&
+     git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    'create corruption in data of first object' \
+    'create_new_pack &&
+     git prune-packed &&
+     chmod +w ${pack}.pack &&
+     perl -i.bak -pe "s/ base /abcdef/" ${pack}.pack &&
+     test_must_fail git cat-file blob $blob_1 > /dev/null &&
+     test_must_fail git cat-file blob $blob_2 > /dev/null &&
+     test_must_fail git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    '... but having a loose copy allows for full recovery' \
+    'mv ${pack}.idx tmp &&
+     git hash-object -t blob -w file_1 &&
+     mv tmp ${pack}.idx &&
+     git cat-file blob $blob_1 > /dev/null &&
+     git cat-file blob $blob_2 > /dev/null &&
+     git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    '... and loose copy of second object allows for partial recovery' \
+    'git prune-packed &&
+     test_must_fail git cat-file blob $blob_2 > /dev/null &&
+     mv ${pack}.idx tmp &&
+     git hash-object -t blob -w file_2 &&
+     mv tmp ${pack}.idx &&
+     test_must_fail git cat-file blob $blob_1 > /dev/null &&
+     git cat-file blob $blob_2 > /dev/null &&
+     git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    'create corruption in header of first delta' \
+    'create_new_pack &&
+     git prune-packed &&
+     do_corrupt_object $blob_2 0 &&
+     git cat-file blob $blob_1 > /dev/null &&
+     test_must_fail git cat-file blob $blob_2 > /dev/null &&
+     test_must_fail git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    '... but having a loose copy allows for full recovery' \
+    'mv ${pack}.idx tmp &&
+     git hash-object -t blob -w file_2 &&
+     mv tmp ${pack}.idx &&
+     git cat-file blob $blob_1 > /dev/null &&
+     git cat-file blob $blob_2 > /dev/null &&
+     git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    'create corruption in data of first delta' \
+    'create_new_pack &&
+     git prune-packed &&
+     chmod +w ${pack}.pack &&
+     perl -i.bak -pe "s/ delta1 /abcdefgh/" ${pack}.pack &&
+     git cat-file blob $blob_1 > /dev/null &&
+     test_must_fail git cat-file blob $blob_2 > /dev/null &&
+     test_must_fail git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    '... but having a loose copy allows for full recovery' \
+    'mv ${pack}.idx tmp &&
+     git hash-object -t blob -w file_2 &&
+     mv tmp ${pack}.idx &&
+     git cat-file blob $blob_1 > /dev/null &&
+     git cat-file blob $blob_2 > /dev/null &&
+     git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    'corruption in delta base reference of first delta (OBJ_REF_DELTA)' \
+    'create_new_pack &&
+     git prune-packed &&
+     do_corrupt_object $blob_2 2 &&
+     git cat-file blob $blob_1 > /dev/null &&
+     test_must_fail git cat-file blob $blob_2 > /dev/null &&
+     test_must_fail git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    '... but having a loose copy allows for full recovery' \
+    'mv ${pack}.idx tmp &&
+     git hash-object -t blob -w file_2 &&
+     mv tmp ${pack}.idx &&
+     git cat-file blob $blob_1 > /dev/null &&
+     git cat-file blob $blob_2 > /dev/null &&
+     git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    'corruption in delta base reference of first delta (OBJ_OFS_DELTA)' \
+    'create_new_pack --delta-base-offset &&
+     git prune-packed &&
+     do_corrupt_object $blob_2 2 &&
+     git cat-file blob $blob_1 > /dev/null &&
+     test_must_fail git cat-file blob $blob_2 > /dev/null &&
+     test_must_fail git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    '... and a redundant pack allows for full recovery too' \
+    'mv ${pack}.idx tmp &&
+     git hash-object -t blob -w file_1 &&
+     git hash-object -t blob -w file_2 &&
+     printf "$blob_1\n$blob_2\n" | git pack-objects .git/objects/pack/pack &&
+     git prune-packed &&
+     mv tmp ${pack}.idx &&
+     git cat-file blob $blob_1 > /dev/null &&
+     git cat-file blob $blob_2 > /dev/null &&
+     git cat-file blob $blob_3 > /dev/null'
+
+test_done
index 3def75eeb29f0eeaa096ab4b9f4511a01a3ce3d8..8becbc3f38fde02371ebbcd9a39a320a1c00c290 100755 (executable)
@@ -142,9 +142,12 @@ do
                        set x $cmd; shift
                        git symbolic-ref HEAD refs/heads/$1 ; shift
                        rm -f .git/FETCH_HEAD
-                       rm -f .git/refs/heads/*
-                       rm -f .git/refs/remotes/rem/*
-                       rm -f .git/refs/tags/*
+                       git for-each-ref \
+                               refs/heads refs/remotes/rem refs/tags |
+                       while read val type refname
+                       do
+                               git update-ref -d "$refname" "$val"
+                       done
                        git fetch "$@" >/dev/null
                        cat .git/FETCH_HEAD
                } >"$actual_f" &&
index 7372439164d521df9c29d98b4507612013aba86b..21dbb557b7cfad412ba1796519a7a63a403c35bb 100755 (executable)
@@ -12,6 +12,13 @@ This test runs various sanity checks on http-push.'
 ROOT_PATH="$PWD"
 LIB_HTTPD_DAV=t
 
+if git http-push > /dev/null 2>&1 || [ $? -eq 128 ]
+then
+       say "skipping test, USE_CURL_MULTI is not defined"
+       test_done
+       exit
+fi
+
 . ../lib-httpd.sh
 
 if ! start_httpd >&3 2>&4
@@ -36,24 +43,25 @@ test_expect_success 'setup remote repository' '
        git --bare update-server-info &&
        chmod +x hooks/post-update &&
        cd - &&
-       mv test_repo.git $HTTPD_DOCUMENT_ROOT_PATH
+       mv test_repo.git "$HTTPD_DOCUMENT_ROOT_PATH"
 '
-       
+
 test_expect_success 'clone remote repository' '
        cd "$ROOT_PATH" &&
        git clone $HTTPD_URL/test_repo.git test_repo_clone
 '
 
-test_expect_success 'push to remote repository' '
+test_expect_failure 'push to remote repository' '
        cd "$ROOT_PATH"/test_repo_clone &&
        : >path2 &&
        git add path2 &&
        test_tick &&
        git commit -m path2 &&
-       git push
+       git push &&
+       [ -f "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/refs/heads/master" ]
 '
 
-test_expect_success 'create and delete remote branch' '
+test_expect_failure 'create and delete remote branch' '
        cd "$ROOT_PATH"/test_repo_clone &&
        git checkout -b dev &&
        : >path3 &&
index 88e96fb91b9fd54ddc6bd43de4996c1e70404a6f..c4af9ca0a7edf6230dc6ca8ec10848545971fce7 100755 (executable)
@@ -23,7 +23,7 @@ test_expect_success 'setup' '
 
        : > super-file &&
        git add super-file &&
-       git submodule add . sub &&
+       git submodule add "$(pwd)" sub &&
        git symbolic-ref HEAD refs/heads/super &&
        test_tick &&
        git commit -m super-initial &&
diff --git a/t/t6011-rev-list-with-bad-commit.sh b/t/t6011-rev-list-with-bad-commit.sh
new file mode 100755 (executable)
index 0000000..e51eb41
--- /dev/null
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+test_description='git rev-list should notice bad commits'
+
+. ./test-lib.sh
+
+# Note:
+# - compression level is set to zero to make "corruptions" easier to perform
+# - reflog is disabled to avoid extra references which would twart the test
+
+test_expect_success 'setup' \
+   '
+   git init &&
+   git config core.compression 0 &&
+   git config core.logallrefupdates false &&
+   echo "foo" > foo &&
+   git add foo &&
+   git commit -m "first commit" &&
+   echo "bar" > bar &&
+   git add bar &&
+   git commit -m "second commit" &&
+   echo "baz" > baz &&
+   git add baz &&
+   git commit -m "third commit" &&
+   echo "foo again" >> foo &&
+   git add foo &&
+   git commit -m "fourth commit" &&
+   git repack -a -f -d
+   '
+
+test_expect_success 'verify number of revisions' \
+   '
+   revs=$(git rev-list --all | wc -l) &&
+   test $revs -eq 4 &&
+   first_commit=$(git rev-parse HEAD~3)
+   '
+
+test_expect_success 'corrupt second commit object' \
+   '
+   perl -i.bak -pe "s/second commit/socond commit/" .git/objects/pack/*.pack &&
+   test_must_fail git fsck --full
+   '
+
+test_expect_success 'rev-list should fail' \
+   '
+   test_must_fail git rev-list --all > /dev/null
+   '
+
+test_expect_success 'git repack _MUST_ fail' \
+   '
+   test_must_fail git repack -a -f -d
+   '
+
+test_expect_success 'first commit is still available' \
+   '
+   git log $first_commit
+   '
+
+test_done
+
diff --git a/t/t6040-tracking-info.sh b/t/t6040-tracking-info.sh
new file mode 100755 (executable)
index 0000000..aac212e
--- /dev/null
@@ -0,0 +1,70 @@
+#!/bin/sh
+
+test_description='remote tracking stats'
+
+. ./test-lib.sh
+
+advance () {
+       echo "$1" >"$1" &&
+       git add "$1" &&
+       test_tick &&
+       git commit -m "$1"
+}
+
+test_expect_success setup '
+       for i in a b c;
+       do
+               advance $i || break
+       done &&
+       git clone . test &&
+       (
+               cd test &&
+               git checkout -b b1 origin &&
+               git reset --hard HEAD^ &&
+               advance d &&
+               git checkout -b b2 origin &&
+               git reset --hard b1 &&
+               git checkout -b b3 origin &&
+               git reset --hard HEAD^ &&
+               git checkout -b b4 origin &&
+               advance e &&
+               advance f
+       )
+'
+
+script='s/^..\(b.\)[    0-9a-f]*\[\([^]]*\)\].*/\1 \2/p'
+cat >expect <<\EOF
+b1 ahead 1, behind 1
+b2 ahead 1, behind 1
+b3 behind 1
+b4 ahead 2
+EOF
+
+test_expect_success 'branch -v' '
+       (
+               cd test &&
+               git branch -v
+       ) |
+       sed -n -e "$script" >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'checkout' '
+       (
+               cd test && git checkout b1
+       ) >actual &&
+       grep -e "have 1 and 1 different" actual
+'
+
+test_expect_success 'status' '
+       (
+               cd test &&
+               git checkout b1 >/dev/null &&
+               # reports nothing to commit
+               test_must_fail git status
+       ) >actual &&
+       grep -e "have 1 and 1 different" actual
+'
+
+
+test_done
index 91ea85d99bc9ba306a9616b67903863d4379634d..a3c8941c726d77fd993a3cfcd7fde4e9aa43da74 100755 (executable)
@@ -26,25 +26,78 @@ test_expect_success 'Create sample commit with known timestamp' '
        git tag -a -m "Tagging at $datestamp" testtag
 '
 
-test_expect_success 'Check atom names are valid' '
-       bad=
-       for token in \
-               refname objecttype objectsize objectname tree parent \
-               numparent object type author authorname authoremail \
-               authordate committer committername committeremail \
-               committerdate tag tagger taggername taggeremail \
-               taggerdate creator creatordate subject body contents
-       do
-               git for-each-ref --format="$token=%($token)" refs/heads || {
-                       bad=$token
-                       break
-               }
-       done
-       test -z "$bad"
+test_atom() {
+       case "$1" in
+               head) ref=refs/heads/master ;;
+                tag) ref=refs/tags/testtag ;;
+       esac
+       printf '%s\n' "$3" >expected
+       test_expect_${4:-success} "basic atom: $1 $2" "
+               git for-each-ref --format='%($2)' $ref >actual &&
+               test_cmp expected actual
+       "
+}
+
+test_atom head refname refs/heads/master
+test_atom head objecttype commit
+test_atom head objectsize 171
+test_atom head objectname 67a36f10722846e891fbada1ba48ed035de75581
+test_atom head tree 0e51c00fcb93dffc755546f27593d511e1bdb46f
+test_atom head parent ''
+test_atom head numparent 0
+test_atom head object ''
+test_atom head type ''
+test_atom head author 'A U Thor <author@example.com> 1151939924 +0200'
+test_atom head authorname 'A U Thor'
+test_atom head authoremail '<author@example.com>'
+test_atom head authordate 'Mon Jul 3 17:18:44 2006 +0200'
+test_atom head committer 'C O Mitter <committer@example.com> 1151939923 +0200'
+test_atom head committername 'C O Mitter'
+test_atom head committeremail '<committer@example.com>'
+test_atom head committerdate 'Mon Jul 3 17:18:43 2006 +0200'
+test_atom head tag ''
+test_atom head tagger ''
+test_atom head taggername ''
+test_atom head taggeremail ''
+test_atom head taggerdate ''
+test_atom head creator 'C O Mitter <committer@example.com> 1151939923 +0200'
+test_atom head creatordate 'Mon Jul 3 17:18:43 2006 +0200'
+test_atom head subject 'Initial'
+test_atom head body ''
+test_atom head contents 'Initial
+'
+
+test_atom tag refname refs/tags/testtag
+test_atom tag objecttype tag
+test_atom tag objectsize 154
+test_atom tag objectname 98b46b1d36e5b07909de1b3886224e3e81e87322
+test_atom tag tree ''
+test_atom tag parent ''
+test_atom tag numparent ''
+test_atom tag object '67a36f10722846e891fbada1ba48ed035de75581'
+test_atom tag type 'commit'
+test_atom tag author ''
+test_atom tag authorname ''
+test_atom tag authoremail ''
+test_atom tag authordate ''
+test_atom tag committer ''
+test_atom tag committername ''
+test_atom tag committeremail ''
+test_atom tag committerdate ''
+test_atom tag tag 'testtag'
+test_atom tag tagger 'C O Mitter <committer@example.com> 1151939925 +0200'
+test_atom tag taggername 'C O Mitter'
+test_atom tag taggeremail '<committer@example.com>'
+test_atom tag taggerdate 'Mon Jul 3 17:18:45 2006 +0200'
+test_atom tag creator 'C O Mitter <committer@example.com> 1151939925 +0200'
+test_atom tag creatordate 'Mon Jul 3 17:18:45 2006 +0200'
+test_atom tag subject 'Tagging at 1151939927'
+test_atom tag body ''
+test_atom tag contents 'Tagging at 1151939927
 '
 
 test_expect_success 'Check invalid atoms names are errors' '
-       ! git-for-each-ref --format="%(INVALID)" refs/heads
+       test_must_fail git-for-each-ref --format="%(INVALID)" refs/heads
 '
 
 test_expect_success 'Check format specifiers are ignored in naming date atoms' '
@@ -64,7 +117,7 @@ test_expect_success 'Check valid format specifiers for date fields' '
 '
 
 test_expect_success 'Check invalid format specifiers are errors' '
-       ! git-for-each-ref --format="%(authordate:INVALID)" refs/heads
+       test_must_fail git-for-each-ref --format="%(authordate:INVALID)" refs/heads
 '
 
 cat >expected <<\EOF
index 80a438d4d988baa54a25e5725665904c6c45f431..38a48b57c70a888838cfa114be843e1d4aea00d8 100755 (executable)
@@ -67,6 +67,104 @@ test_expect_success 'status (2)' '
 
 '
 
+cat >expect <<EOF
+# On branch master
+# Changes to be committed:
+#   (use "git reset HEAD <file>..." to unstage)
+#
+#      new file:   dir2/added
+#
+# Changed but not updated:
+#   (use "git add <file>..." to update what will be committed)
+#
+#      modified:   dir1/modified
+#
+# Untracked files not listed (use -u option to show untracked files)
+EOF
+test_expect_success 'status -uno' '
+       mkdir dir3 &&
+       : > dir3/untracked1 &&
+       : > dir3/untracked2 &&
+       git status -uno >output &&
+       test_cmp expect output
+'
+
+test_expect_success 'status (status.showUntrackedFiles no)' '
+       git config status.showuntrackedfiles no
+       git status >output &&
+       test_cmp expect output
+'
+
+cat >expect <<EOF
+# On branch master
+# Changes to be committed:
+#   (use "git reset HEAD <file>..." to unstage)
+#
+#      new file:   dir2/added
+#
+# Changed but not updated:
+#   (use "git add <file>..." to update what will be committed)
+#
+#      modified:   dir1/modified
+#
+# Untracked files:
+#   (use "git add <file>..." to include in what will be committed)
+#
+#      dir1/untracked
+#      dir2/modified
+#      dir2/untracked
+#      dir3/
+#      expect
+#      output
+#      untracked
+EOF
+test_expect_success 'status -unormal' '
+       git status -unormal >output &&
+       test_cmp expect output
+'
+
+test_expect_success 'status (status.showUntrackedFiles normal)' '
+       git config status.showuntrackedfiles normal
+       git status >output &&
+       test_cmp expect output
+'
+
+cat >expect <<EOF
+# On branch master
+# Changes to be committed:
+#   (use "git reset HEAD <file>..." to unstage)
+#
+#      new file:   dir2/added
+#
+# Changed but not updated:
+#   (use "git add <file>..." to update what will be committed)
+#
+#      modified:   dir1/modified
+#
+# Untracked files:
+#   (use "git add <file>..." to include in what will be committed)
+#
+#      dir1/untracked
+#      dir2/modified
+#      dir2/untracked
+#      dir3/untracked1
+#      dir3/untracked2
+#      expect
+#      output
+#      untracked
+EOF
+test_expect_success 'status -uall' '
+       git status -uall >output &&
+       test_cmp expect output
+'
+test_expect_success 'status (status.showUntrackedFiles all)' '
+       git config status.showuntrackedfiles all
+       git status >output &&
+       rm -rf dir3 &&
+       git config --unset status.showuntrackedfiles &&
+       test_cmp expect output
+'
+
 cat > expect << \EOF
 # On branch master
 # Changes to be committed:
index 6a5211f1873be6a8bb80404cda34751c46f26e86..31c340fd389ed2688bb94a29acbf892be6f0c564 100755 (executable)
@@ -4,6 +4,10 @@ test_description='git-repack works correctly'
 
 . ./test-lib.sh
 
+fsha1=
+csha1=
+tsha1=
+
 test_expect_success '-A option leaves unreachable objects unpacked' '
        echo content > file1 &&
        git add . &&
@@ -44,4 +48,34 @@ test_expect_success '-A option leaves unreachable objects unpacked' '
        git show $tsha1
 '
 
+compare_mtimes ()
+{
+       perl -e 'my $reference = shift;
+                foreach my $file (@ARGV) {
+                       exit(1) unless(-f $file && -M $file == -M $reference);
+                }
+                exit(0);
+               ' -- "$@"
+}
+
+test_expect_success 'unpacked objects receive timestamp of pack file' '
+       fsha1path=$(echo "$fsha1" | sed -e "s|\(..\)|\1/|") &&
+       fsha1path=".git/objects/$fsha1path" &&
+       csha1path=$(echo "$csha1" | sed -e "s|\(..\)|\1/|") &&
+       csha1path=".git/objects/$csha1path" &&
+       tsha1path=$(echo "$tsha1" | sed -e "s|\(..\)|\1/|") &&
+       tsha1path=".git/objects/$tsha1path" &&
+       git branch transient_branch $csha1 &&
+       git repack -a -d -l &&
+       test ! -f "$fsha1path" &&
+       test ! -f "$csha1path" &&
+       test ! -f "$tsha1path" &&
+       test 1 = $(ls -1 .git/objects/pack/pack-*.pack | wc -l) &&
+       packfile=$(ls .git/objects/pack/pack-*.pack) &&
+       git branch -D transient_branch &&
+       sleep 1 &&
+       git repack -A -l &&
+       compare_mtimes "$packfile" "$fsha1path" "$csha1path" "$tsha1path"
+'
+
 test_done
index 242cdf092acdbfc88858de1dbcfe3c817a67a4c2..3bc6164125f683d26213035ee9b1ea9199be5792 100755 (executable)
@@ -4,9 +4,9 @@
 #
 
 test_description='git-svn basic tests'
-GIT_SVN_LC_ALL=$LC_ALL
+GIT_SVN_LC_ALL=${LC_ALL:-$LANG}
 
-case "$LC_ALL" in
+case "$GIT_SVN_LC_ALL" in
 *.UTF-8)
        have_utf8=t
        ;;
@@ -17,7 +17,7 @@ esac
 
 . ./lib-git-svn.sh
 
-echo 'define NO_SVN_TESTS to skip git-svn tests'
+say 'define NO_SVN_TESTS to skip git-svn tests'
 
 test_expect_success \
     'initialize git-svn' '
@@ -183,7 +183,7 @@ then
                git-svn set-tree HEAD"
        unset LC_ALL
 else
-       echo "UTF-8 locale not set, test skipped ($GIT_SVN_LC_ALL)"
+       say "UTF-8 locale not set, test skipped ($GIT_SVN_LC_ALL)"
 fi
 
 name='test fetch functionality (svn => git) with alternate GIT_SVN_ID'
index a400dc796666e820c27dd6989ef9ee1b9922fad3..f8f4718c361fc16749fd82fe9bd797643a7a399b 100755 (executable)
@@ -20,8 +20,8 @@ test_expect_success '(supposedly) non-conflicting change from SVN' '
        test x"`sed -n -e 61p < file`" = x61 &&
        svn co "$svnrepo" tmp &&
        cd tmp &&
-               perl -i -p -e "s/^58$/5588/" file &&
-               perl -i -p -e "s/^61$/6611/" file &&
+               perl -i.bak -p -e "s/^58$/5588/" file &&
+               perl -i.bak -p -e "s/^61$/6611/" file &&
                poke file &&
                test x"`sed -n -e 58p < file`" = x5588 &&
                test x"`sed -n -e 61p < file`" = x6611 &&
@@ -40,8 +40,8 @@ test_expect_success 'some unrelated changes to git' "
 test_expect_success 'change file but in unrelated area' "
        test x\"\`sed -n -e 4p < file\`\" = x4 &&
        test x\"\`sed -n -e 7p < file\`\" = x7 &&
-       perl -i -p -e 's/^4\$/4444/' file &&
-       perl -i -p -e 's/^7\$/7777/' file &&
+       perl -i.bak -p -e 's/^4\$/4444/' file &&
+       perl -i.bak -p -e 's/^7\$/7777/' file &&
        test x\"\`sed -n -e 4p < file\`\" = x4444 &&
        test x\"\`sed -n -e 7p < file\`\" = x7777 &&
        git commit -m '4 => 4444, 7 => 7777' file &&
index 047659fde1049777e7fe12113ecb305377b1f8f9..04d2a65c087de78fa8126b68774673532497276e 100755 (executable)
@@ -49,4 +49,13 @@ test_expect_success 'verify metadata for /dir' "
           grep '^git-svn-id: $dir_url@1 $uuid$'
        "
 
+test_expect_success 'find commit based on SVN revision number' "
+        git-svn find-rev r12 |
+           grep `git rev-parse HEAD`
+        "
+
+test_expect_success 'empty rebase' "
+       git-svn rebase
+       "
+
 test_done
index 31c929b57368fe08f35301a75bff48e19b86a06d..8da8ce58eb1b29210a6ac95fdd3a3fcb547ca36f 100755 (executable)
@@ -7,12 +7,18 @@
 # I don't like the idea of taking a port and possibly leaving a
 # daemon running on a users system if the test fails.
 # Not all git users will need to interact with SVN.
-test -z "$SVNSERVE_PORT" && exit 0
 
 test_description='git-svn dcommit new files over svn:// test'
 
 . ./lib-git-svn.sh
 
+if test -z "$SVNSERVE_PORT"
+then
+       say 'skipping svnserve test. (set $SVNSERVE_PORT to enable)'
+       test_done
+       exit
+fi
+
 start_svnserve () {
        svnserve --listen-port $SVNSERVE_PORT \
                 --root "$rawsvnrepo" \
index f09bfb1117caa05981d65e45fe2a9cc4c7ca19f3..f1bc5ceef0453fcdf711afd6225a5f0cd5dc69e5 100755 (executable)
@@ -77,6 +77,29 @@ test_expect_success 'iso-8859-1' '
                 git fast-import &&
                 git cat-file commit i18n | grep "Áéí óú")
 
+'
+test_expect_success 'import/export-marks' '
+
+       git checkout -b marks master &&
+       git fast-export --export-marks=tmp-marks HEAD &&
+       test -s tmp-marks &&
+       test $(wc -l < tmp-marks) -eq 3 &&
+       test $(
+               git fast-export --import-marks=tmp-marks\
+               --export-marks=tmp-marks HEAD |
+               grep ^commit |
+               wc -l) \
+       -eq 0 &&
+       echo change > file &&
+       git commit -m "last commit" file &&
+       test $(
+               git fast-export --import-marks=tmp-marks \
+               --export-marks=tmp-marks HEAD |
+               grep ^commit\  |
+               wc -l) \
+       -eq 1 &&
+       test $(wc -l < tmp-marks) -eq 4
+
 '
 
 cat > signed-tag-import << EOF
diff --git a/t/t9700-perl-git.sh b/t/t9700-perl-git.sh
new file mode 100755 (executable)
index 0000000..9706ee5
--- /dev/null
@@ -0,0 +1,44 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Lea Wiemann
+#
+
+test_description='perl interface (Git.pm)'
+. ./test-lib.sh
+
+perl -MTest::More -e 0 2>/dev/null || {
+       say_color skip "Perl Test::More unavailable, skipping test"
+       test_done
+}
+
+# set up test repository
+
+test_expect_success \
+    'set up test repository' \
+    'echo "test file 1" > file1 &&
+     echo "test file 2" > file2 &&
+     mkdir directory1 &&
+     echo "in directory1" >> directory1/file &&
+     mkdir directory2 &&
+     echo "in directory2" >> directory2/file &&
+     git add . &&
+     git commit -m "first commit" &&
+
+     echo "changed file 1" > file1 &&
+     git commit -a -m "second commit" &&
+
+     git-config --add color.test.slot1 green &&
+     git-config --add test.string value &&
+     git-config --add test.dupstring value1 &&
+     git-config --add test.dupstring value2 &&
+     git-config --add test.booltrue true &&
+     git-config --add test.boolfalse no &&
+     git-config --add test.boolother other &&
+     git-config --add test.int 2k
+     '
+
+test_external_without_stderr \
+    'Perl API' \
+    perl ../t9700/test.pl
+
+test_done
diff --git a/t/t9700/test.pl b/t/t9700/test.pl
new file mode 100755 (executable)
index 0000000..4d23125
--- /dev/null
@@ -0,0 +1,100 @@
+#!/usr/bin/perl
+use lib (split(/:/, $ENV{GITPERLLIB}));
+
+use 5.006002;
+use warnings;
+use strict;
+
+use Test::More qw(no_plan);
+
+use Cwd;
+use File::Basename;
+use File::Temp;
+
+BEGIN { use_ok('Git') }
+
+# set up
+our $repo_dir = "trash directory";
+our $abs_repo_dir = Cwd->cwd;
+die "this must be run by calling the t/t97* shell script(s)\n"
+    if basename(Cwd->cwd) ne $repo_dir;
+ok(our $r = Git->repository(Directory => "."), "open repository");
+
+# config
+is($r->config("test.string"), "value", "config scalar: string");
+is_deeply([$r->config("test.dupstring")], ["value1", "value2"],
+         "config array: string");
+is($r->config("test.nonexistent"), undef, "config scalar: nonexistent");
+is_deeply([$r->config("test.nonexistent")], [], "config array: nonexistent");
+is($r->config_int("test.int"), 2048, "config_int: integer");
+is($r->config_int("test.nonexistent"), undef, "config_int: nonexistent");
+ok($r->config_bool("test.booltrue"), "config_bool: true");
+ok(!$r->config_bool("test.boolfalse"), "config_bool: false");
+our $ansi_green = "\x1b[32m";
+is($r->get_color("color.test.slot1", "red"), $ansi_green, "get_color");
+# Cannot test $r->get_colorbool("color.foo")) because we do not
+# control whether our STDOUT is a terminal.
+
+# Failure cases for config:
+# Save and restore STDERR; we will probably extract this into a
+# "dies_ok" method and possibly move the STDERR handling to Git.pm.
+open our $tmpstderr, ">&", STDERR or die "cannot save STDERR"; close STDERR;
+eval { $r->config("test.dupstring") };
+ok($@, "config: duplicate entry in scalar context fails");
+eval { $r->config_bool("test.boolother") };
+ok($@, "config_bool: non-boolean values fail");
+open STDERR, ">&", $tmpstderr or die "cannot restore STDERR";
+
+# ident
+like($r->ident("aUthor"), qr/^A U Thor <author\@example.com> [0-9]+ \+0000$/,
+     "ident scalar: author (type)");
+like($r->ident("cOmmitter"), qr/^C O Mitter <committer\@example.com> [0-9]+ \+0000$/,
+     "ident scalar: committer (type)");
+is($r->ident("invalid"), "invalid", "ident scalar: invalid ident string (no parsing)");
+my ($name, $email, $time_tz) = $r->ident('author');
+is_deeply([$name, $email], ["A U Thor", "author\@example.com"],
+        "ident array: author");
+like($time_tz, qr/[0-9]+ \+0000/, "ident array: author");
+is_deeply([$r->ident("Name <email> 123 +0000")], ["Name", "email", "123 +0000"],
+         "ident array: ident string");
+is_deeply([$r->ident("invalid")], [], "ident array: invalid ident string");
+
+# ident_person
+is($r->ident_person("aUthor"), "A U Thor <author\@example.com>",
+   "ident_person: author (type)");
+is($r->ident_person("Name <email> 123 +0000"), "Name <email>",
+   "ident_person: ident string");
+is($r->ident_person("Name", "email", "123 +0000"), "Name <email>",
+   "ident_person: array");
+
+# objects and hashes
+ok(our $file1hash = $r->command_oneline('rev-parse', "HEAD:file1"), "(get file hash)");
+our $tmpfile = File::Temp->new;
+is($r->cat_blob($file1hash, $tmpfile), 15, "cat_blob: size");
+our $blobcontents;
+{ local $/; seek $tmpfile, 0, 0; $blobcontents = <$tmpfile>; }
+is($blobcontents, "changed file 1\n", "cat_blob: data");
+seek $tmpfile, 0, 0;
+is(Git::hash_object("blob", $tmpfile), $file1hash, "hash_object: roundtrip");
+$tmpfile = File::Temp->new();
+print $tmpfile my $test_text = "test blob, to be inserted\n";
+like(our $newhash = $r->hash_and_insert_object($tmpfile), qr/[0-9a-fA-F]{40}/,
+     "hash_and_insert_object: returns hash");
+$tmpfile = File::Temp->new;
+is($r->cat_blob($newhash, $tmpfile), length $test_text, "cat_blob: roundtrip size");
+{ local $/; seek $tmpfile, 0, 0; $blobcontents = <$tmpfile>; }
+is($blobcontents, $test_text, "cat_blob: roundtrip data");
+
+# paths
+is($r->repo_path, "./.git", "repo_path");
+is($r->wc_path, $abs_repo_dir . "/", "wc_path");
+is($r->wc_subdir, "", "wc_subdir initial");
+$r->wc_chdir("directory1");
+is($r->wc_subdir, "directory1", "wc_subdir after wc_chdir");
+TODO: {
+       local $TODO = "commands do not work after wc_chdir";
+       # Failure output is active even in non-verbose mode and thus
+       # annoying.  Hence we skip these tests as long as they fail.
+       todo_skip 'config after wc_chdir', 1;
+       is($r->config("color.string"), "value", "config after wc_chdir");
+}
index c861141667eb03eb42f559cbe174c6a76dd704c9..8e2849b5ce915c3984894628e8e3ce990812ddfd 100644 (file)
@@ -35,6 +35,7 @@ unset GIT_WORK_TREE
 unset GIT_EXTERNAL_DIFF
 unset GIT_INDEX_FILE
 unset GIT_OBJECT_DIRECTORY
+unset GIT_CEILING_DIRECTORIES
 unset SHA1_FILE_DIRECTORIES
 unset SHA1_FILE_DIRECTORY
 GIT_MERGE_VERBOSITY=5
@@ -80,6 +81,8 @@ do
                debug=t; shift ;;
        -i|--i|--im|--imm|--imme|--immed|--immedi|--immedia|--immediat|--immediate)
                immediate=t; shift ;;
+       -l|--l|--lo|--lon|--long|--long-|--long-t|--long-te|--long-tes|--long-test|--long-tests)
+               export GIT_TEST_LONG=t; shift ;;
        -h|--h|--he|--hel|--help)
                help=t; shift ;;
        -v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose)
@@ -152,6 +155,7 @@ test_failure=0
 test_count=0
 test_fixed=0
 test_broken=0
+test_success=0
 
 die () {
        echo >&5 "FATAL: Unexpected exit with code $?"
@@ -193,6 +197,7 @@ test_tick () {
 
 test_ok_ () {
        test_count=$(expr "$test_count" + 1)
+       test_success=$(expr "$test_success" + 1)
        say_color "" "  ok $test_count: $@"
 }
 
@@ -302,6 +307,64 @@ test_expect_code () {
        echo >&3 ""
 }
 
+# test_external runs external test scripts that provide continuous
+# test output about their progress, and succeeds/fails on
+# zero/non-zero exit code.  It outputs the test output on stdout even
+# in non-verbose mode, and announces the external script with "* run
+# <n>: ..." before running it.  When providing relative paths, keep in
+# mind that all scripts run in "trash directory".
+# Usage: test_external description command arguments...
+# Example: test_external 'Perl API' perl ../path/to/test.pl
+test_external () {
+       test "$#" -eq 3 ||
+       error >&5 "bug in the test script: not 3 parameters to test_external"
+       descr="$1"
+       shift
+       if ! test_skip "$descr" "$@"
+       then
+               # Announce the script to reduce confusion about the
+               # test output that follows.
+               say_color "" " run $(expr "$test_count" + 1): $descr ($*)"
+               # Run command; redirect its stderr to &4 as in
+               # test_run_, but keep its stdout on our stdout even in
+               # non-verbose mode.
+               "$@" 2>&4
+               if [ "$?" = 0 ]
+               then
+                       test_ok_ "$descr"
+               else
+                       test_failure_ "$descr" "$@"
+               fi
+       fi
+}
+
+# Like test_external, but in addition tests that the command generated
+# no output on stderr.
+test_external_without_stderr () {
+       # The temporary file has no (and must have no) security
+       # implications.
+       tmp="$TMPDIR"; if [ -z "$tmp" ]; then tmp=/tmp; fi
+       stderr="$tmp/git-external-stderr.$$.tmp"
+       test_external "$@" 4> "$stderr"
+       [ -f "$stderr" ] || error "Internal error: $stderr disappeared."
+       descr="no stderr: $1"
+       shift
+       say >&3 "expecting no stderr from previous command"
+       if [ ! -s "$stderr" ]; then
+               rm "$stderr"
+               test_ok_ "$descr"
+       else
+               if [ "$verbose" = t ]; then
+                       output=`echo; echo Stderr is:; cat "$stderr"`
+               else
+                       output=
+               fi
+               # rm first in case test_failure exits.
+               rm "$stderr"
+               test_failure_ "$descr" "$@" "$output"
+       fi
+}
+
 # This is not among top-level (test_expect_success | test_expect_failure)
 # but is a prefix that can be used in the test script, like:
 #
@@ -345,7 +408,7 @@ test_create_repo () {
        repo="$1"
        mkdir "$repo"
        cd "$repo" || error "Cannot setup test environment"
-       "$GIT_EXEC_PATH/git" init "--template=$GIT_EXEC_PATH/templates/blt/" >/dev/null 2>&1 ||
+       "$GIT_EXEC_PATH/git" init "--template=$GIT_EXEC_PATH/templates/blt/" >&3 2>&4 ||
        error "cannot run git init -- have you built things yet?"
        mv .git/hooks .git/hooks-disabled
        cd "$owd"
@@ -353,6 +416,16 @@ test_create_repo () {
 
 test_done () {
        trap - exit
+       test_results_dir="$TEST_DIRECTORY/test-results"
+       mkdir -p "$test_results_dir"
+       test_results_path="$test_results_dir/${0%-*}-$$"
+
+       echo "total $test_count" >> $test_results_path
+       echo "success $test_success" >> $test_results_path
+       echo "fixed $test_fixed" >> $test_results_path
+       echo "broken $test_broken" >> $test_results_path
+       echo "failed $test_failure" >> $test_results_path
+       echo "" >> $test_results_path
 
        if test "$test_fixed" != 0
        then
@@ -387,7 +460,8 @@ test_done () {
 
 # Test the binaries we have just built.  The tests are kept in
 # t/ subdirectory and are run in 'trash directory' subdirectory.
-PATH=$(pwd)/..:$PATH
+TEST_DIRECTORY=$(pwd)
+PATH=$TEST_DIRECTORY/..:$PATH
 GIT_EXEC_PATH=$(pwd)/..
 GIT_TEMPLATE_DIR=$(pwd)/../templates/blt
 unset GIT_CONFIG
index bda9d13505f9dbec8a7864d14c52bbb4827b4f52..9f3f1fc352dea624bd36e55802de190ead0ad9dd 100644 (file)
@@ -8,12 +8,12 @@ INSTALL ?= install
 TAR ?= tar
 RM ?= rm -f
 prefix ?= $(HOME)
-template_dir ?= $(prefix)/share/git-core/templates
+template_instdir ?= $(prefix)/share/git-core/templates
 # DESTDIR=
 
 # Shell quote (do not use $(call) to accommodate ancient setups);
 DESTDIR_SQ = $(subst ','\'',$(DESTDIR))
-template_dir_SQ = $(subst ','\'',$(template_dir))
+template_instdir_SQ = $(subst ','\'',$(template_instdir))
 
 all: boilerplates.made custom
 
@@ -46,6 +46,6 @@ clean:
        $(RM) -r blt boilerplates.made
 
 install: all
-       $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(template_dir_SQ)'
+       $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(template_instdir_SQ)'
        (cd blt && $(TAR) cf - .) | \
-       (cd '$(DESTDIR_SQ)$(template_dir_SQ)' && umask 022 && $(TAR) xf -)
+       (cd '$(DESTDIR_SQ)$(template_instdir_SQ)' && umask 022 && $(TAR) xf -)
diff --git a/templates/hooks--applypatch-msg b/templates/hooks--applypatch-msg
deleted file mode 100644 (file)
index 02de1ef..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-#
-# An example hook script to check the commit log message taken by
-# applypatch from an e-mail message.
-#
-# The hook should exit with non-zero status after issuing an
-# appropriate message if it wants to stop the commit.  The hook is
-# allowed to edit the commit message file.
-#
-# To enable this hook, make this file executable.
-
-. git-sh-setup
-test -x "$GIT_DIR/hooks/commit-msg" &&
-       exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"}
-:
diff --git a/templates/hooks--applypatch-msg.sample b/templates/hooks--applypatch-msg.sample
new file mode 100755 (executable)
index 0000000..8b2a2fe
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message taken by
+# applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.  The hook is
+# allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "applypatch-msg".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/commit-msg" &&
+       exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"}
+:
diff --git a/templates/hooks--commit-msg b/templates/hooks--commit-msg
deleted file mode 100644 (file)
index 4ef86eb..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/sh
-#
-# An example hook script to check the commit log message.
-# Called by git-commit with one argument, the name of the file
-# that has the commit message.  The hook should exit with non-zero
-# status after issuing an appropriate message if it wants to stop the
-# commit.  The hook is allowed to edit the commit message file.
-#
-# To enable this hook, make this file executable.
-
-# Uncomment the below to add a Signed-off-by line to the message.
-# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
-# hook is more suited to it.
-#
-# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
-# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
-
-# This example catches duplicate Signed-off-by lines.
-
-test "" = "$(grep '^Signed-off-by: ' "$1" |
-        sort | uniq -c | sed -e '/^[   ]*1[    ]/d')" || {
-       echo >&2 Duplicate Signed-off-by lines.
-       exit 1
-}
diff --git a/templates/hooks--commit-msg.sample b/templates/hooks--commit-msg.sample
new file mode 100755 (executable)
index 0000000..6ef1d29
--- /dev/null
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message.
+# Called by git-commit with one argument, the name of the file
+# that has the commit message.  The hook should exit with non-zero
+# status after issuing an appropriate message if it wants to stop the
+# commit.  The hook is allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "commit-msg".
+
+# Uncomment the below to add a Signed-off-by line to the message.
+# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
+# hook is more suited to it.
+#
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
+
+# This example catches duplicate Signed-off-by lines.
+
+test "" = "$(grep '^Signed-off-by: ' "$1" |
+        sort | uniq -c | sed -e '/^[   ]*1[    ]/d')" || {
+       echo >&2 Duplicate Signed-off-by lines.
+       exit 1
+}
diff --git a/templates/hooks--post-commit b/templates/hooks--post-commit
deleted file mode 100644 (file)
index 8be6f34..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-#
-# An example hook script that is called after a successful
-# commit is made.
-#
-# To enable this hook, make this file executable.
-
-: Nothing
diff --git a/templates/hooks--post-commit.sample b/templates/hooks--post-commit.sample
new file mode 100755 (executable)
index 0000000..2266821
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# An example hook script that is called after a successful
+# commit is made.
+#
+# To enable this hook, rename this file to "post-commit".
+
+: Nothing
diff --git a/templates/hooks--post-receive b/templates/hooks--post-receive
deleted file mode 100644 (file)
index b70c8fd..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/sh
-#
-# An example hook script for the post-receive event
-#
-# This script is run after receive-pack has accepted a pack and the
-# repository has been updated.  It is passed arguments in through stdin
-# in the form
-#  <oldrev> <newrev> <refname>
-# For example:
-#  aa453216d1b3e49e7f6f98441fa56946ddcd6a20 68f7abf4e6f922807889f52bc043ecd31b79f814 refs/heads/master
-#
-# see contrib/hooks/ for an sample, or uncomment the next line (on debian)
-#
-
-
-#. /usr/share/doc/git-core/contrib/hooks/post-receive-email
diff --git a/templates/hooks--post-receive.sample b/templates/hooks--post-receive.sample
new file mode 100755 (executable)
index 0000000..18d2e0f
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# An example hook script for the "post-receive" event.
+#
+# The "post-receive" script is run after receive-pack has accepted a pack
+# and the repository has been updated.  It is passed arguments in through
+# stdin in the form
+#  <oldrev> <newrev> <refname>
+# For example:
+#  aa453216d1b3e49e7f6f98441fa56946ddcd6a20 68f7abf4e6f922807889f52bc043ecd31b79f814 refs/heads/master
+#
+# see contrib/hooks/ for an sample, or uncomment the next line and
+# rename the file to "post-receive".
+
+#. /usr/share/doc/git-core/contrib/hooks/post-receive-email
diff --git a/templates/hooks--post-update b/templates/hooks--post-update
deleted file mode 100644 (file)
index bcba893..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-#
-# An example hook script to prepare a packed repository for use over
-# dumb transports.
-#
-# To enable this hook, make this file executable by "chmod +x post-update".
-
-exec git-update-server-info
diff --git a/templates/hooks--post-update.sample b/templates/hooks--post-update.sample
new file mode 100755 (executable)
index 0000000..5323b56
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# An example hook script to prepare a packed repository for use over
+# dumb transports.
+#
+# To enable this hook, rename this file to "post-update".
+
+exec git-update-server-info
diff --git a/templates/hooks--pre-applypatch b/templates/hooks--pre-applypatch
deleted file mode 100644 (file)
index eeccc93..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/sh
-#
-# An example hook script to verify what is about to be committed
-# by applypatch from an e-mail message.
-#
-# The hook should exit with non-zero status after issuing an
-# appropriate message if it wants to stop the commit.
-#
-# To enable this hook, make this file executable.
-
-. git-sh-setup
-test -x "$GIT_DIR/hooks/pre-commit" &&
-       exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"}
-:
diff --git a/templates/hooks--pre-applypatch.sample b/templates/hooks--pre-applypatch.sample
new file mode 100755 (executable)
index 0000000..b1f187c
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed
+# by applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-applypatch".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/pre-commit" &&
+       exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"}
+:
diff --git a/templates/hooks--pre-commit b/templates/hooks--pre-commit
deleted file mode 100644 (file)
index b25dce6..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/bin/sh
-#
-# An example hook script to verify what is about to be committed.
-# Called by git-commit with no arguments.  The hook should
-# exit with non-zero status after issuing an appropriate message if
-# it wants to stop the commit.
-#
-# To enable this hook, make this file executable.
-
-# This is slightly modified from Andrew Morton's Perfect Patch.
-# Lines you introduce should not have trailing whitespace.
-# Also check for an indentation that has SP before a TAB.
-
-if git-rev-parse --verify HEAD 2>/dev/null
-then
-       git-diff-index -p -M --cached HEAD --
-else
-       # NEEDSWORK: we should produce a diff with an empty tree here
-       # if we want to do the same verification for the initial import.
-       :
-fi |
-perl -e '
-    my $found_bad = 0;
-    my $filename;
-    my $reported_filename = "";
-    my $lineno;
-    sub bad_line {
-       my ($why, $line) = @_;
-       if (!$found_bad) {
-           print STDERR "*\n";
-           print STDERR "* You have some suspicious patch lines:\n";
-           print STDERR "*\n";
-           $found_bad = 1;
-       }
-       if ($reported_filename ne $filename) {
-           print STDERR "* In $filename\n";
-           $reported_filename = $filename;
-       }
-       print STDERR "* $why (line $lineno)\n";
-       print STDERR "$filename:$lineno:$line\n";
-    }
-    while (<>) {
-       if (m|^diff --git a/(.*) b/\1$|) {
-           $filename = $1;
-           next;
-       }
-       if (/^@@ -\S+ \+(\d+)/) {
-           $lineno = $1 - 1;
-           next;
-       }
-       if (/^ /) {
-           $lineno++;
-           next;
-       }
-       if (s/^\+//) {
-           $lineno++;
-           chomp;
-           if (/\s$/) {
-               bad_line("trailing whitespace", $_);
-           }
-           if (/^\s* \t/) {
-               bad_line("indent SP followed by a TAB", $_);
-           }
-           if (/^([<>])\1{6} |^={7}$/) {
-               bad_line("unresolved merge conflict", $_);
-           }
-       }
-    }
-    exit($found_bad);
-'
diff --git a/templates/hooks--pre-commit.sample b/templates/hooks--pre-commit.sample
new file mode 100755 (executable)
index 0000000..0e49279
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed.
+# Called by git-commit with no arguments.  The hook should
+# exit with non-zero status after issuing an appropriate message if
+# it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-commit".
+
+if git-rev-parse --verify HEAD 2>/dev/null
+then
+       against=HEAD
+else
+       # Initial commit: diff against an empty tree object
+       against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+fi
+
+exec git diff-index --check --cached $against --
diff --git a/templates/hooks--pre-rebase b/templates/hooks--pre-rebase
deleted file mode 100644 (file)
index 981c454..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2006 Junio C Hamano
-#
-
-publish=next
-basebranch="$1"
-if test "$#" = 2
-then
-       topic="refs/heads/$2"
-else
-       topic=`git symbolic-ref HEAD`
-fi
-
-case "$basebranch,$topic" in
-master,refs/heads/??/*)
-       ;;
-*)
-       exit 0 ;# we do not interrupt others.
-       ;;
-esac
-
-# Now we are dealing with a topic branch being rebased
-# on top of master.  Is it OK to rebase it?
-
-# Is topic fully merged to master?
-not_in_master=`git-rev-list --pretty=oneline ^master "$topic"`
-if test -z "$not_in_master"
-then
-       echo >&2 "$topic is fully merged to master; better remove it."
-       exit 1 ;# we could allow it, but there is no point.
-fi
-
-# Is topic ever merged to next?  If so you should not be rebasing it.
-only_next_1=`git-rev-list ^master "^$topic" ${publish} | sort`
-only_next_2=`git-rev-list ^master           ${publish} | sort`
-if test "$only_next_1" = "$only_next_2"
-then
-       not_in_topic=`git-rev-list "^$topic" master`
-       if test -z "$not_in_topic"
-       then
-               echo >&2 "$topic is already up-to-date with master"
-               exit 1 ;# we could allow it, but there is no point.
-       else
-               exit 0
-       fi
-else
-       not_in_next=`git-rev-list --pretty=oneline ^${publish} "$topic"`
-       perl -e '
-               my $topic = $ARGV[0];
-               my $msg = "* $topic has commits already merged to public branch:\n";
-               my (%not_in_next) = map {
-                       /^([0-9a-f]+) /;
-                       ($1 => 1);
-               } split(/\n/, $ARGV[1]);
-               for my $elem (map {
-                               /^([0-9a-f]+) (.*)$/;
-                               [$1 => $2];
-                       } split(/\n/, $ARGV[2])) {
-                       if (!exists $not_in_next{$elem->[0]}) {
-                               if ($msg) {
-                                       print STDERR $msg;
-                                       undef $msg;
-                               }
-                               print STDERR " $elem->[1]\n";
-                       }
-               }
-       ' "$topic" "$not_in_next" "$not_in_master"
-       exit 1
-fi
-
-exit 0
-
-################################################################
-
-This sample hook safeguards topic branches that have been
-published from being rewound.
-
-The workflow assumed here is:
-
- * Once a topic branch forks from "master", "master" is never
-   merged into it again (either directly or indirectly).
-
- * Once a topic branch is fully cooked and merged into "master",
-   it is deleted.  If you need to build on top of it to correct
-   earlier mistakes, a new topic branch is created by forking at
-   the tip of the "master".  This is not strictly necessary, but
-   it makes it easier to keep your history simple.
-
- * Whenever you need to test or publish your changes to topic
-   branches, merge them into "next" branch.
-
-The script, being an example, hardcodes the publish branch name
-to be "next", but it is trivial to make it configurable via
-$GIT_DIR/config mechanism.
-
-With this workflow, you would want to know:
-
-(1) ... if a topic branch has ever been merged to "next".  Young
-    topic branches can have stupid mistakes you would rather
-    clean up before publishing, and things that have not been
-    merged into other branches can be easily rebased without
-    affecting other people.  But once it is published, you would
-    not want to rewind it.
-
-(2) ... if a topic branch has been fully merged to "master".
-    Then you can delete it.  More importantly, you should not
-    build on top of it -- other people may already want to
-    change things related to the topic as patches against your
-    "master", so if you need further changes, it is better to
-    fork the topic (perhaps with the same name) afresh from the
-    tip of "master".
-
-Let's look at this example:
-
-                  o---o---o---o---o---o---o---o---o---o "next"
-                 /       /           /           /
-                /   a---a---b A     /           /
-               /   /               /           /
-              /   /   c---c---c---c B         /
-             /   /   /             \         /
-            /   /   /   b---b C     \       /
-           /   /   /   /             \     /
-    ---o---o---o---o---o---o---o---o---o---o---o "master"
-
-
-A, B and C are topic branches.
-
- * A has one fix since it was merged up to "next".
-
- * B has finished.  It has been fully merged up to "master" and "next",
-   and is ready to be deleted.
-
- * C has not merged to "next" at all.
-
-We would want to allow C to be rebased, refuse A, and encourage
-B to be deleted.
-
-To compute (1):
-
-       git-rev-list ^master ^topic next
-       git-rev-list ^master        next
-
-       if these match, topic has not merged in next at all.
-
-To compute (2):
-
-       git-rev-list master..topic
-
-       if this is empty, it is fully merged to "master".
diff --git a/templates/hooks--pre-rebase.sample b/templates/hooks--pre-rebase.sample
new file mode 100755 (executable)
index 0000000..be1b06e
--- /dev/null
@@ -0,0 +1,169 @@
+#!/bin/sh
+#
+# Copyright (c) 2006, 2008 Junio C Hamano
+#
+# The "pre-rebase" hook is run just before "git-rebase" starts doing
+# its job, and can prevent the command from running by exiting with
+# non-zero status.
+#
+# The hook is called with the following parameters:
+#
+# $1 -- the upstream the series was forked from.
+# $2 -- the branch being rebased (or empty when rebasing the current branch).
+#
+# This sample shows how to prevent topic branches that are already
+# merged to 'next' branch from getting rebased, because allowing it
+# would result in rebasing already published history.
+
+publish=next
+basebranch="$1"
+if test "$#" = 2
+then
+       topic="refs/heads/$2"
+else
+       topic=`git symbolic-ref HEAD` ||
+       exit 0 ;# we do not interrupt rebasing detached HEAD
+fi
+
+case "$topic" in
+refs/heads/??/*)
+       ;;
+*)
+       exit 0 ;# we do not interrupt others.
+       ;;
+esac
+
+# Now we are dealing with a topic branch being rebased
+# on top of master.  Is it OK to rebase it?
+
+# Does the topic really exist?
+git show-ref -q "$topic" || {
+       echo >&2 "No such branch $topic"
+       exit 1
+}
+
+# Is topic fully merged to master?
+not_in_master=`git-rev-list --pretty=oneline ^master "$topic"`
+if test -z "$not_in_master"
+then
+       echo >&2 "$topic is fully merged to master; better remove it."
+       exit 1 ;# we could allow it, but there is no point.
+fi
+
+# Is topic ever merged to next?  If so you should not be rebasing it.
+only_next_1=`git-rev-list ^master "^$topic" ${publish} | sort`
+only_next_2=`git-rev-list ^master           ${publish} | sort`
+if test "$only_next_1" = "$only_next_2"
+then
+       not_in_topic=`git-rev-list "^$topic" master`
+       if test -z "$not_in_topic"
+       then
+               echo >&2 "$topic is already up-to-date with master"
+               exit 1 ;# we could allow it, but there is no point.
+       else
+               exit 0
+       fi
+else
+       not_in_next=`git-rev-list --pretty=oneline ^${publish} "$topic"`
+       perl -e '
+               my $topic = $ARGV[0];
+               my $msg = "* $topic has commits already merged to public branch:\n";
+               my (%not_in_next) = map {
+                       /^([0-9a-f]+) /;
+                       ($1 => 1);
+               } split(/\n/, $ARGV[1]);
+               for my $elem (map {
+                               /^([0-9a-f]+) (.*)$/;
+                               [$1 => $2];
+                       } split(/\n/, $ARGV[2])) {
+                       if (!exists $not_in_next{$elem->[0]}) {
+                               if ($msg) {
+                                       print STDERR $msg;
+                                       undef $msg;
+                               }
+                               print STDERR " $elem->[1]\n";
+                       }
+               }
+       ' "$topic" "$not_in_next" "$not_in_master"
+       exit 1
+fi
+
+exit 0
+
+################################################################
+
+This sample hook safeguards topic branches that have been
+published from being rewound.
+
+The workflow assumed here is:
+
+ * Once a topic branch forks from "master", "master" is never
+   merged into it again (either directly or indirectly).
+
+ * Once a topic branch is fully cooked and merged into "master",
+   it is deleted.  If you need to build on top of it to correct
+   earlier mistakes, a new topic branch is created by forking at
+   the tip of the "master".  This is not strictly necessary, but
+   it makes it easier to keep your history simple.
+
+ * Whenever you need to test or publish your changes to topic
+   branches, merge them into "next" branch.
+
+The script, being an example, hardcodes the publish branch name
+to be "next", but it is trivial to make it configurable via
+$GIT_DIR/config mechanism.
+
+With this workflow, you would want to know:
+
+(1) ... if a topic branch has ever been merged to "next".  Young
+    topic branches can have stupid mistakes you would rather
+    clean up before publishing, and things that have not been
+    merged into other branches can be easily rebased without
+    affecting other people.  But once it is published, you would
+    not want to rewind it.
+
+(2) ... if a topic branch has been fully merged to "master".
+    Then you can delete it.  More importantly, you should not
+    build on top of it -- other people may already want to
+    change things related to the topic as patches against your
+    "master", so if you need further changes, it is better to
+    fork the topic (perhaps with the same name) afresh from the
+    tip of "master".
+
+Let's look at this example:
+
+                  o---o---o---o---o---o---o---o---o---o "next"
+                 /       /           /           /
+                /   a---a---b A     /           /
+               /   /               /           /
+              /   /   c---c---c---c B         /
+             /   /   /             \         /
+            /   /   /   b---b C     \       /
+           /   /   /   /             \     /
+    ---o---o---o---o---o---o---o---o---o---o---o "master"
+
+
+A, B and C are topic branches.
+
+ * A has one fix since it was merged up to "next".
+
+ * B has finished.  It has been fully merged up to "master" and "next",
+   and is ready to be deleted.
+
+ * C has not merged to "next" at all.
+
+We would want to allow C to be rebased, refuse A, and encourage
+B to be deleted.
+
+To compute (1):
+
+       git-rev-list ^master ^topic next
+       git-rev-list ^master        next
+
+       if these match, topic has not merged in next at all.
+
+To compute (2):
+
+       git-rev-list master..topic
+
+       if this is empty, it is fully merged to "master".
diff --git a/templates/hooks--prepare-commit-msg b/templates/hooks--prepare-commit-msg
deleted file mode 100644 (file)
index d3c1da3..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/bin/sh
-#
-# An example hook script to prepare the commit log message.
-# Called by git-commit with the name of the file that has the
-# commit message, followed by the description of the commit
-# message's source.  The hook's purpose is to edit the commit
-# message file.  If the hook fails with a non-zero status,
-# the commit is aborted.
-#
-# To enable this hook, make this file executable.
-
-# This hook includes three examples.  The first comments out the
-# "Conflicts:" part of a merge commit.
-#
-# The second includes the output of "git diff --name-status -r"
-# into the message, just before the "git status" output.  It is
-# commented because it doesn't cope with --amend or with squashed
-# commits.
-#
-# The third example adds a Signed-off-by line to the message, that can
-# still be edited.  This is rarely a good idea.
-
-case "$2,$3" in
-  merge,)
-    perl -i -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;
-
-# ,|template,)
-#   perl -i -pe '
-#      print "\n" . `git diff --cached --name-status -r`
-#       if /^#/ && $first++ == 0' "$1" ;;
-
-  *) ;;
-esac
-
-# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
-# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
diff --git a/templates/hooks--prepare-commit-msg.sample b/templates/hooks--prepare-commit-msg.sample
new file mode 100755 (executable)
index 0000000..3652424
--- /dev/null
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# An example hook script to prepare the commit log message.
+# Called by git-commit with the name of the file that has the
+# commit message, followed by the description of the commit
+# message's source.  The hook's purpose is to edit the commit
+# message file.  If the hook fails with a non-zero status,
+# the commit is aborted.
+#
+# To enable this hook, rename this file to "prepare-commit-msg".
+
+# This hook includes three examples.  The first comments out the
+# "Conflicts:" part of a merge commit.
+#
+# The second includes the output of "git diff --name-status -r"
+# into the message, just before the "git status" output.  It is
+# commented because it doesn't cope with --amend or with squashed
+# commits.
+#
+# The third example adds a Signed-off-by line to the message, that can
+# still be edited.  This is rarely a good idea.
+
+case "$2,$3" in
+  merge,)
+    perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;
+
+# ,|template,)
+#   perl -i.bak -pe '
+#      print "\n" . `git diff --cached --name-status -r`
+#       if /^#/ && $first++ == 0' "$1" ;;
+
+  *) ;;
+esac
+
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
diff --git a/templates/hooks--update b/templates/hooks--update
deleted file mode 100644 (file)
index 4b69268..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-#!/bin/sh
-#
-# An example hook script to blocks unannotated tags from entering.
-# Called by git-receive-pack with arguments: refname sha1-old sha1-new
-#
-# To enable this hook, make this file executable by "chmod +x update".
-#
-# Config
-# ------
-# hooks.allowunannotated
-#   This boolean sets whether unannotated tags will be allowed into the
-#   repository.  By default they won't be.
-# hooks.allowdeletetag
-#   This boolean sets whether deleting tags will be allowed in the
-#   repository.  By default they won't be.
-# hooks.allowdeletebranch
-#   This boolean sets whether deleting branches will be allowed in the
-#   repository.  By default they won't be.
-#
-
-# --- Command line
-refname="$1"
-oldrev="$2"
-newrev="$3"
-
-# --- Safety check
-if [ -z "$GIT_DIR" ]; then
-       echo "Don't run this script from the command line." >&2
-       echo " (if you want, you could supply GIT_DIR then run" >&2
-       echo "  $0 <ref> <oldrev> <newrev>)" >&2
-       exit 1
-fi
-
-if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
-       echo "Usage: $0 <ref> <oldrev> <newrev>" >&2
-       exit 1
-fi
-
-# --- Config
-allowunannotated=$(git config --bool hooks.allowunannotated)
-allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
-allowdeletetag=$(git config --bool hooks.allowdeletetag)
-
-# check for no description
-projectdesc=$(sed -e '1q' "$GIT_DIR/description")
-if [ -z "$projectdesc" -o "$projectdesc" = "Unnamed repository; edit this file to name it for gitweb." ]; then
-       echo "*** Project description file hasn't been set" >&2
-       exit 1
-fi
-
-# --- Check types
-# if $newrev is 0000...0000, it's a commit to delete a ref.
-if [ "$newrev" = "0000000000000000000000000000000000000000" ]; then
-       newrev_type=delete
-else
-       newrev_type=$(git-cat-file -t $newrev)
-fi
-
-case "$refname","$newrev_type" in
-       refs/tags/*,commit)
-               # un-annotated tag
-               short_refname=${refname##refs/tags/}
-               if [ "$allowunannotated" != "true" ]; then
-                       echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
-                       echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
-                       exit 1
-               fi
-               ;;
-       refs/tags/*,delete)
-               # delete tag
-               if [ "$allowdeletetag" != "true" ]; then
-                       echo "*** Deleting a tag is not allowed in this repository" >&2
-                       exit 1
-               fi
-               ;;
-       refs/tags/*,tag)
-               # annotated tag
-               ;;
-       refs/heads/*,commit)
-               # branch
-               ;;
-       refs/heads/*,delete)
-               # delete branch
-               if [ "$allowdeletebranch" != "true" ]; then
-                       echo "*** Deleting a branch is not allowed in this repository" >&2
-                       exit 1
-               fi
-               ;;
-       refs/remotes/*,commit)
-               # tracking branch
-               ;;
-       refs/remotes/*,delete)
-               # delete tracking branch
-               if [ "$allowdeletebranch" != "true" ]; then
-                       echo "*** Deleting a tracking branch is not allowed in this repository" >&2
-                       exit 1
-               fi
-               ;;
-       *)
-               # Anything else (is there anything else?)
-               echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
-               exit 1
-               ;;
-esac
-
-# --- Finished
-exit 0
diff --git a/templates/hooks--update.sample b/templates/hooks--update.sample
new file mode 100755 (executable)
index 0000000..93c6055
--- /dev/null
@@ -0,0 +1,107 @@
+#!/bin/sh
+#
+# An example hook script to blocks unannotated tags from entering.
+# Called by git-receive-pack with arguments: refname sha1-old sha1-new
+#
+# To enable this hook, rename this file to "update".
+#
+# Config
+# ------
+# hooks.allowunannotated
+#   This boolean sets whether unannotated tags will be allowed into the
+#   repository.  By default they won't be.
+# hooks.allowdeletetag
+#   This boolean sets whether deleting tags will be allowed in the
+#   repository.  By default they won't be.
+# hooks.allowdeletebranch
+#   This boolean sets whether deleting branches will be allowed in the
+#   repository.  By default they won't be.
+#
+
+# --- Command line
+refname="$1"
+oldrev="$2"
+newrev="$3"
+
+# --- Safety check
+if [ -z "$GIT_DIR" ]; then
+       echo "Don't run this script from the command line." >&2
+       echo " (if you want, you could supply GIT_DIR then run" >&2
+       echo "  $0 <ref> <oldrev> <newrev>)" >&2
+       exit 1
+fi
+
+if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
+       echo "Usage: $0 <ref> <oldrev> <newrev>" >&2
+       exit 1
+fi
+
+# --- Config
+allowunannotated=$(git config --bool hooks.allowunannotated)
+allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
+allowdeletetag=$(git config --bool hooks.allowdeletetag)
+
+# check for no description
+projectdesc=$(sed -e '1q' "$GIT_DIR/description")
+if [ -z "$projectdesc" -o "$projectdesc" = "Unnamed repository; edit this file to name it for gitweb." ]; then
+       echo "*** Project description file hasn't been set" >&2
+       exit 1
+fi
+
+# --- Check types
+# if $newrev is 0000...0000, it's a commit to delete a ref.
+if [ "$newrev" = "0000000000000000000000000000000000000000" ]; then
+       newrev_type=delete
+else
+       newrev_type=$(git-cat-file -t $newrev)
+fi
+
+case "$refname","$newrev_type" in
+       refs/tags/*,commit)
+               # un-annotated tag
+               short_refname=${refname##refs/tags/}
+               if [ "$allowunannotated" != "true" ]; then
+                       echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
+                       echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
+                       exit 1
+               fi
+               ;;
+       refs/tags/*,delete)
+               # delete tag
+               if [ "$allowdeletetag" != "true" ]; then
+                       echo "*** Deleting a tag is not allowed in this repository" >&2
+                       exit 1
+               fi
+               ;;
+       refs/tags/*,tag)
+               # annotated tag
+               ;;
+       refs/heads/*,commit)
+               # branch
+               ;;
+       refs/heads/*,delete)
+               # delete branch
+               if [ "$allowdeletebranch" != "true" ]; then
+                       echo "*** Deleting a branch is not allowed in this repository" >&2
+                       exit 1
+               fi
+               ;;
+       refs/remotes/*,commit)
+               # tracking branch
+               ;;
+       refs/remotes/*,delete)
+               # delete tracking branch
+               if [ "$allowdeletebranch" != "true" ]; then
+                       echo "*** Deleting a tracking branch is not allowed in this repository" >&2
+                       exit 1
+               fi
+               ;;
+       *)
+               # Anything else (is there anything else?)
+               echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
+               exit 1
+               ;;
+esac
+
+# --- Finished
+exit 0
diff --git a/test-absolute-path.c b/test-absolute-path.c
deleted file mode 100644 (file)
index c959ea2..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#include "cache.h"
-
-int main(int argc, char **argv)
-{
-       while (argc > 1) {
-               puts(make_absolute_path(argv[1]));
-               argc--;
-               argv++;
-       }
-       return 0;
-}
diff --git a/test-path-utils.c b/test-path-utils.c
new file mode 100644 (file)
index 0000000..a0bcb0e
--- /dev/null
@@ -0,0 +1,26 @@
+#include "cache.h"
+
+int main(int argc, char **argv)
+{
+       if (argc == 3 && !strcmp(argv[1], "normalize_absolute_path")) {
+               char *buf = xmalloc(strlen(argv[2])+1);
+               int rv = normalize_absolute_path(buf, argv[2]);
+               assert(strlen(buf) == rv);
+               puts(buf);
+       }
+
+       if (argc >= 2 && !strcmp(argv[1], "make_absolute_path")) {
+               while (argc > 2) {
+                       puts(make_absolute_path(argv[2]));
+                       argc--;
+                       argv++;
+               }
+       }
+
+       if (argc == 4 && !strcmp(argv[1], "longest_ancestor_length")) {
+               int len = longest_ancestor_length(argv[2], argv[3]);
+               printf("%d\n", len);
+       }
+
+       return 0;
+}
index 6f549b336ba1f7c84f45bd13317949bae4f9c704..6eb65b873afc9dfd457e974b63d88350bb8dc913 100644 (file)
@@ -711,7 +711,8 @@ static int is_local(const char *url)
 {
        const char *colon = strchr(url, ':');
        const char *slash = strchr(url, '/');
-       return !colon || (slash && slash < colon);
+       return !colon || (slash && slash < colon) ||
+               has_dos_drive_prefix(url);
 }
 
 static int is_file(const char *url)
index b46dd365ea289c6d397dc6fc994b6ba4227886fc..9f82941f8b1e1cd65ebcd7675f7b7ba63c24acae 100644 (file)
@@ -135,6 +135,8 @@ static int do_rev_list(int fd, void *create_full_pack)
                die("revision walk setup failed");
        mark_edges_uninteresting(revs.commits, &revs, show_edge);
        traverse_commit_list(&revs, show_commit, show_object);
+       fflush(pack_pipe);
+       fclose(pack_pipe);
        return 0;
 }
 
diff --git a/wrapper.c b/wrapper.c
new file mode 100644 (file)
index 0000000..4e04f76
--- /dev/null
+++ b/wrapper.c
@@ -0,0 +1,160 @@
+/*
+ * Various trivial helper wrappers around standard functions
+ */
+#include "cache.h"
+
+char *xstrdup(const char *str)
+{
+       char *ret = strdup(str);
+       if (!ret) {
+               release_pack_memory(strlen(str) + 1, -1);
+               ret = strdup(str);
+               if (!ret)
+                       die("Out of memory, strdup failed");
+       }
+       return ret;
+}
+
+void *xmalloc(size_t size)
+{
+       void *ret = malloc(size);
+       if (!ret && !size)
+               ret = malloc(1);
+       if (!ret) {
+               release_pack_memory(size, -1);
+               ret = malloc(size);
+               if (!ret && !size)
+                       ret = malloc(1);
+               if (!ret)
+                       die("Out of memory, malloc failed");
+       }
+#ifdef XMALLOC_POISON
+       memset(ret, 0xA5, size);
+#endif
+       return ret;
+}
+
+/*
+ * xmemdupz() allocates (len + 1) bytes of memory, duplicates "len" bytes of
+ * "data" to the allocated memory, zero terminates the allocated memory,
+ * and returns a pointer to the allocated memory. If the allocation fails,
+ * the program dies.
+ */
+void *xmemdupz(const void *data, size_t len)
+{
+       char *p = xmalloc(len + 1);
+       memcpy(p, data, len);
+       p[len] = '\0';
+       return p;
+}
+
+char *xstrndup(const char *str, size_t len)
+{
+       char *p = memchr(str, '\0', len);
+       return xmemdupz(str, p ? p - str : len);
+}
+
+void *xrealloc(void *ptr, size_t size)
+{
+       void *ret = realloc(ptr, size);
+       if (!ret && !size)
+               ret = realloc(ptr, 1);
+       if (!ret) {
+               release_pack_memory(size, -1);
+               ret = realloc(ptr, size);
+               if (!ret && !size)
+                       ret = realloc(ptr, 1);
+               if (!ret)
+                       die("Out of memory, realloc failed");
+       }
+       return ret;
+}
+
+void *xcalloc(size_t nmemb, size_t size)
+{
+       void *ret = calloc(nmemb, size);
+       if (!ret && (!nmemb || !size))
+               ret = calloc(1, 1);
+       if (!ret) {
+               release_pack_memory(nmemb * size, -1);
+               ret = calloc(nmemb, size);
+               if (!ret && (!nmemb || !size))
+                       ret = calloc(1, 1);
+               if (!ret)
+                       die("Out of memory, calloc failed");
+       }
+       return ret;
+}
+
+void *xmmap(void *start, size_t length,
+       int prot, int flags, int fd, off_t offset)
+{
+       void *ret = mmap(start, length, prot, flags, fd, offset);
+       if (ret == MAP_FAILED) {
+               if (!length)
+                       return NULL;
+               release_pack_memory(length, fd);
+               ret = mmap(start, length, prot, flags, fd, offset);
+               if (ret == MAP_FAILED)
+                       die("Out of memory? mmap failed: %s", strerror(errno));
+       }
+       return ret;
+}
+
+/*
+ * xread() is the same a read(), but it automatically restarts read()
+ * operations with a recoverable error (EAGAIN and EINTR). xread()
+ * DOES NOT GUARANTEE that "len" bytes is read even if the data is available.
+ */
+ssize_t xread(int fd, void *buf, size_t len)
+{
+       ssize_t nr;
+       while (1) {
+               nr = read(fd, buf, len);
+               if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
+                       continue;
+               return nr;
+       }
+}
+
+/*
+ * xwrite() is the same a write(), but it automatically restarts write()
+ * operations with a recoverable error (EAGAIN and EINTR). xwrite() DOES NOT
+ * GUARANTEE that "len" bytes is written even if the operation is successful.
+ */
+ssize_t xwrite(int fd, const void *buf, size_t len)
+{
+       ssize_t nr;
+       while (1) {
+               nr = write(fd, buf, len);
+               if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
+                       continue;
+               return nr;
+       }
+}
+
+int xdup(int fd)
+{
+       int ret = dup(fd);
+       if (ret < 0)
+               die("dup failed: %s", strerror(errno));
+       return ret;
+}
+
+FILE *xfdopen(int fd, const char *mode)
+{
+       FILE *stream = fdopen(fd, mode);
+       if (stream == NULL)
+               die("Out of memory? fdopen failed: %s", strerror(errno));
+       return stream;
+}
+
+int xmkstemp(char *template)
+{
+       int fd;
+
+       fd = mkstemp(template);
+       if (fd < 0)
+               die("Unable to create temporary file: %s", strerror(errno));
+       return fd;
+}
index 630be4cb9414b1686a5ad86a4d5166f2828096f1..e4c8e225fd232dfd642aa13d7ae5b64b9827c915 100644 (file)
@@ -34,7 +34,12 @@ void maybe_flush_or_die(FILE *f, const char *desc)
                        return;
        }
        if (fflush(f)) {
-               if (errno == EPIPE)
+               /*
+                * On Windows, EPIPE is returned only by the first write()
+                * after the reading end has closed its handle; subsequent
+                * write()s return EINVAL.
+                */
+               if (errno == EPIPE || errno == EINVAL)
                        exit(0);
                die("write failure on %s: %s", desc, strerror(errno));
        }
diff --git a/ws.c b/ws.c
index ba7e834ca819b1d2ccce6cf125aa9f34efea8d5c..7a7ff130a34942506e6068105ac5946c9404bf18 100644 (file)
--- a/ws.c
+++ b/ws.c
@@ -117,9 +117,9 @@ char *whitespace_error_string(unsigned ws)
 }
 
 /* If stream is non-NULL, emits the line after checking. */
-unsigned check_and_emit_line(const char *line, int len, unsigned ws_rule,
-                            FILE *stream, const char *set,
-                            const char *reset, const char *ws)
+static unsigned ws_check_emit_1(const char *line, int len, unsigned ws_rule,
+                               FILE *stream, const char *set,
+                               const char *reset, const char *ws)
 {
        unsigned result = 0;
        int written = 0;
@@ -213,6 +213,33 @@ unsigned check_and_emit_line(const char *line, int len, unsigned ws_rule,
        return result;
 }
 
+void ws_check_emit(const char *line, int len, unsigned ws_rule,
+                  FILE *stream, const char *set,
+                  const char *reset, const char *ws)
+{
+       (void)ws_check_emit_1(line, len, ws_rule, stream, set, reset, ws);
+}
+
+unsigned ws_check(const char *line, int len, unsigned ws_rule)
+{
+       return ws_check_emit_1(line, len, ws_rule, NULL, NULL, NULL, NULL);
+}
+
+int ws_blank_line(const char *line, int len, unsigned ws_rule)
+{
+       /*
+        * We _might_ want to treat CR differently from other
+        * whitespace characters when ws_rule has WS_CR_AT_EOL, but
+        * for now we just use this stupid definition.
+        */
+       while (len-- > 0) {
+               if (!isspace(*line))
+                       return 0;
+               line++;
+       }
+       return 1;
+}
+
 /* Copy the line to the buffer while fixing whitespaces */
 int ws_fix_copy(char *dst, const char *src, int len, unsigned ws_rule, int *error_count)
 {
index 5b4d74c1f3f4c24aa23cf564a16592d188449da1..889e50f89fc24984f700d14f7033600fa9fdf642 100644 (file)
@@ -9,6 +9,7 @@
 #include "diffcore.h"
 #include "quote.h"
 #include "run-command.h"
+#include "remote.h"
 
 int wt_status_relative_paths = 1;
 int wt_status_use_color = -1;
@@ -27,6 +28,7 @@ static const char use_add_rm_msg[] =
 "use \"git add/rm <file>...\" to update what will be committed";
 static const char use_add_to_include_msg[] =
 "use \"git add <file>...\" to include in what will be committed";
+enum untracked_status_type show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
 
 static int parse_status_slot(const char *var, int offset)
 {
@@ -314,6 +316,25 @@ static void wt_status_print_verbose(struct wt_status *s)
        run_diff_index(&rev, 1);
 }
 
+static void wt_status_print_tracking(struct wt_status *s)
+{
+       struct strbuf sb = STRBUF_INIT;
+       const char *cp, *ep;
+       struct branch *branch;
+
+       assert(s->branch && !s->is_initial);
+       if (prefixcmp(s->branch, "refs/heads/"))
+               return;
+       branch = branch_get(s->branch + 11);
+       if (!format_tracking_info(branch, &sb))
+               return;
+
+       for (cp = sb.buf; (ep = strchr(cp, '\n')) != NULL; cp = ep + 1)
+               color_fprintf_ln(s->fp, color(WT_STATUS_HEADER),
+                                "# %.*s", (int)(ep - cp), cp);
+       color_fprintf_ln(s->fp, color(WT_STATUS_HEADER), "#");
+}
+
 void wt_status_print(struct wt_status *s)
 {
        unsigned char sha1[20];
@@ -332,6 +353,8 @@ void wt_status_print(struct wt_status *s)
                }
                color_fprintf(s->fp, color(WT_STATUS_HEADER), "# ");
                color_fprintf_ln(s->fp, branch_color, "%s%s", on_what, branch_name);
+               if (!s->is_initial)
+                       wt_status_print_tracking(s);
        }
 
        if (s->is_initial) {
@@ -347,7 +370,10 @@ void wt_status_print(struct wt_status *s)
        wt_status_print_changed(s);
        if (wt_status_submodule_summary)
                wt_status_print_submodule_summary(s);
-       wt_status_print_untracked(s);
+       if (show_untracked_files)
+               wt_status_print_untracked(s);
+       else if (s->commitable)
+                fprintf(s->fp, "# Untracked files not listed (use -u option to show untracked files)\n");
 
        if (s->verbose && !s->is_initial)
                wt_status_print_verbose(s);
@@ -362,6 +388,8 @@ void wt_status_print(struct wt_status *s)
                        printf("nothing added to commit but untracked files present (use \"git add\" to track)\n");
                else if (s->is_initial)
                        printf("nothing to commit (create/copy files and use \"git add\" to track)\n");
+               else if (!show_untracked_files)
+                       printf("nothing to commit (use -u to show untracked files)\n");
                else
                        printf("nothing to commit (working directory clean)\n");
        }
@@ -391,5 +419,18 @@ int git_status_config(const char *k, const char *v, void *cb)
                wt_status_relative_paths = git_config_bool(k, v);
                return 0;
        }
+       if (!strcmp(k, "status.showuntrackedfiles")) {
+               if (!v)
+                       return config_error_nonbool(k);
+               else if (!strcmp(v, "no"))
+                       show_untracked_files = SHOW_NO_UNTRACKED_FILES;
+               else if (!strcmp(v, "normal"))
+                       show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
+               else if (!strcmp(v, "all"))
+                       show_untracked_files = SHOW_ALL_UNTRACKED_FILES;
+               else
+                       return error("Invalid untracked files mode '%s'", v);
+               return 0;
+       }
        return git_color_default_config(k, v, cb);
 }
index 597c7ea988634409f920c86008f5ba70910722f9..78add09bd67c727babb61cd1eaa773bcd0c6e55e 100644 (file)
@@ -11,6 +11,13 @@ enum color_wt_status {
        WT_STATUS_NOBRANCH,
 };
 
+enum untracked_status_type {
+       SHOW_NO_UNTRACKED_FILES,
+       SHOW_NORMAL_UNTRACKED_FILES,
+       SHOW_ALL_UNTRACKED_FILES
+};
+extern enum untracked_status_type show_untracked_files;
+
 struct wt_status {
        int is_initial;
        char *branch;