Merge branch 'rh/maint-gitweb-highlight-ext' into maint
authorJunio C Hamano <gitster@pobox.com>
Wed, 28 Nov 2012 20:05:30 +0000 (12:05 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 28 Nov 2012 20:05:30 +0000 (12:05 -0800)
Syntax highlighting in "gitweb" was not quite working.

* rh/maint-gitweb-highlight-ext:
  gitweb.perl: fix %highlight_ext mappings

287 files changed:
.gitignore
.mailmap
Documentation/RelNotes/1.5.2.1.txt
Documentation/RelNotes/1.6.0.2.txt
Documentation/RelNotes/1.6.1.3.txt
Documentation/RelNotes/1.6.1.4.txt
Documentation/RelNotes/1.6.1.txt
Documentation/RelNotes/1.8.0.1.txt [new file with mode: 0644]
Documentation/RelNotes/1.8.0.txt [new file with mode: 0644]
Documentation/config.txt
Documentation/git-branch.txt
Documentation/git-cherry-pick.txt
Documentation/git-clone.txt
Documentation/git-commit.txt
Documentation/git-daemon.txt
Documentation/git-difftool.txt
Documentation/git-fast-import.txt
Documentation/git-grep.txt
Documentation/git-merge-base.txt
Documentation/git-merge.txt
Documentation/git-mergetool.txt
Documentation/git-p4.txt
Documentation/git-push.txt
Documentation/git-rebase.txt
Documentation/git-submodule.txt
Documentation/git.txt
Documentation/gitattributes.txt
Documentation/gitrepository-layout.txt
Documentation/merge-config.txt
Documentation/rev-list-options.txt
Documentation/revisions.txt
Documentation/technical/api-sha1-array.txt
Documentation/technical/api-string-list.txt
GIT-VERSION-GEN
Makefile
RelNotes
abspath.c
archive-zip.c
archive.c
bisect.c
builtin.h
builtin/add.c
builtin/apply.c
builtin/archive.c
builtin/bisect--helper.c
builtin/blame.c
builtin/branch.c
builtin/cat-file.c
builtin/check-attr.c
builtin/checkout-index.c
builtin/checkout.c
builtin/clean.c
builtin/clone.c
builtin/column.c
builtin/commit.c
builtin/config.c
builtin/count-objects.c
builtin/describe.c
builtin/fast-export.c
builtin/fetch-pack.c
builtin/fetch.c
builtin/fmt-merge-msg.c
builtin/for-each-ref.c
builtin/fsck.c
builtin/gc.c
builtin/grep.c
builtin/hash-object.c
builtin/help.c
builtin/index-pack.c
builtin/init-db.c
builtin/log.c
builtin/ls-files.c
builtin/ls-tree.c
builtin/mailinfo.c
builtin/merge-base.c
builtin/merge-file.c
builtin/merge.c
builtin/mktree.c
builtin/mv.c
builtin/name-rev.c
builtin/notes.c
builtin/pack-objects.c
builtin/pack-refs.c
builtin/prune-packed.c
builtin/prune.c
builtin/push.c
builtin/read-tree.c
builtin/receive-pack.c
builtin/remote.c
builtin/replace.c
builtin/rerere.c
builtin/reset.c
builtin/rev-parse.c
builtin/revert.c
builtin/rm.c
builtin/shortlog.c
builtin/show-branch.c
builtin/show-ref.c
builtin/symbolic-ref.c
builtin/tag.c
builtin/update-index.c
builtin/update-ref.c
builtin/update-server-info.c
builtin/verify-pack.c
builtin/verify-tag.c
builtin/write-tree.c
cache.h
commit.c
commit.h
compat/fnmatch/fnmatch.c
compat/mkdir.c [new file with mode: 0644]
compat/poll/poll.c [moved from compat/win32/poll.c with 97% similarity]
compat/poll/poll.h [moved from compat/win32/poll.h with 100% similarity]
config.c
config.mak.in
configure.ac
contrib/completion/git-completion.bash
contrib/credential/gnome-keyring/.gitignore [new file with mode: 0644]
contrib/credential/gnome-keyring/Makefile [new file with mode: 0644]
contrib/credential/gnome-keyring/git-credential-gnome-keyring.c [new file with mode: 0644]
contrib/credential/wincred/Makefile [new file with mode: 0644]
contrib/credential/wincred/git-credential-wincred.c [new file with mode: 0644]
contrib/examples/builtin-fetch--tool.c
daemon.c
diff.c
diff.h
diffcore-pickaxe.c
fast-import.c
fetch-pack.h
gettext.c
gettext.h
git-am.sh
git-compat-util.h
git-cvsimport.perl
git-difftool.perl
git-gui/GIT-VERSION-GEN
git-gui/git-gui.sh
git-gui/lib/commit.tcl
git-gui/lib/status_bar.tcl
git-gui/macosx/AppMain.tcl
git-gui/po/de.po
git-gui/po/fr.po
git-gui/po/git-gui.pot
git-gui/po/hu.po
git-gui/po/it.po
git-gui/po/ja.po
git-gui/po/nb.po
git-gui/po/pt_br.po
git-gui/po/ru.po
git-gui/po/sv.po
git-mergetool--lib.sh
git-p4.py
git-parse-remote.sh
git-pull.sh
git-rebase--interactive.sh
git-rebase.sh
git-submodule.sh
git-svn.perl
gitk-git/gitk
gitweb/gitweb.perl
graph.c
graph.h
grep.c
grep.h
http-push.c
http-walker.c
http.c
ident.c
mailmap.c
merge-recursive.c
mergetools/codecompare [new file with mode: 0644]
mergetools/defaults
mergetools/p4merge
notes.c
notes.h
parse-options.h
path.c
perl/Git/SVN.pm
perl/Git/SVN/Editor.pm
perl/Git/SVN/Fetcher.pm
perl/Git/SVN/GlobSpec.pm
perl/Git/SVN/Migration.pm
perl/Git/SVN/Ra.pm
perl/Git/SVN/Utils.pm
po/TEAMS
po/de.po
po/git.pot
po/sv.po
po/vi.po
po/zh_CN.po
pretty.c
read-cache.c
refs.c
remote-curl.c
rerere.c
rerere.h
revision.c
sequencer.c
sequencer.h
sha1-array.c
sha1-array.h
strbuf.c
strbuf.h
string-list.c
string-list.h
submodule.c
symlinks.c
t/Git-SVN/Utils/add_path_to_url.t [new file with mode: 0644]
t/Git-SVN/Utils/canonicalize_url.t [new file with mode: 0644]
t/Git-SVN/Utils/collapse_dotdot.t [new file with mode: 0644]
t/Git-SVN/Utils/join_paths.t [new file with mode: 0644]
t/lib-credential.sh
t/lib-git-p4.sh
t/perf/perf-lib.sh
t/t0000-basic.sh
t/t0006-date.sh
t/t0040-parse-options.sh
t/t0060-path-utils.sh
t/t0063-string-list.sh [new file with mode: 0755]
t/t1300-repo-config.sh
t/t1400-update-ref.sh
t/t1502-rev-parse-parseopt.sh
t/t2006-checkout-index-basic.sh
t/t2107-update-index-basic.sh
t/t3004-ls-files-basic.sh
t/t3200-branch.sh
t/t3300-funny-names.sh
t/t3404-rebase-interactive.sh
t/t3501-revert-cherry-pick.sh
t/t3505-cherry-pick-empty.sh
t/t3507-cherry-pick-conflict.sh
t/t3510-cherry-pick-sequence.sh
t/t3902-quoted.sh
t/t3903-stash.sh
t/t4006-diff-mode.sh
t/t4012-diff-binary.sh
t/t4014-format-patch.sh
t/t4016-diff-quote.sh
t/t4018-diff-funcname.sh
t/t4030-diff-textconv.sh
t/t4034-diff-words.sh
t/t4034/ada/expect [new file with mode: 0644]
t/t4034/ada/post [new file with mode: 0644]
t/t4034/ada/pre [new file with mode: 0644]
t/t4120-apply-popt.sh
t/t4133-apply-filenames.sh
t/t4200-rerere.sh
t/t4202-log.sh
t/t4205-log-pretty-formats.sh
t/t5300-pack-object.sh
t/t5400-send-pack.sh
t/t5500-fetch-pack.sh
t/t5505-remote.sh
t/t5530-upload-pack-error.sh
t/t5541-http-push.sh
t/t5551-http-fetch.sh
t/t6500-gc.sh
t/t7008-grep-binary.sh
t/t7508-status.sh
t/t7600-merge.sh
t/t7610-mergetool.sh
t/t7800-difftool.sh
t/t7810-grep.sh
t/t9107-git-svn-migrate.sh
t/t9118-git-svn-funky-branch-names.sh
t/t9154-git-svn-fancy-glob.sh
t/t9164-git-svn-dcommit-concurrent.sh [moved from t/t9164-git-svn-dcommit-concrrent.sh with 97% similarity]
t/t9165-git-svn-fetch-merge-branch-of-branch.sh [new file with mode: 0755]
t/t9166-git-svn-fetch-merge-branch-of-branch2.sh [new file with mode: 0755]
t/t9502-gitweb-standalone-parse-output.sh
t/t9801-git-p4-branch.sh
t/t9805-git-p4-skip-submit-edit.sh
t/t9807-git-p4-submit.sh
t/t9809-git-p4-client-view.sh
t/t9810-git-p4-rcs.sh
t/t9815-git-p4-submit-fail.sh [new file with mode: 0755]
t/t9902-completion.sh
t/test-lib-functions.sh
t/test-lib.sh
test-string-list.c [new file with mode: 0644]
trace.c
transport.c
transport.h
userdiff.c
utf8.c
wt-status.c
wt-status.h

index 68fe464..a188a82 100644 (file)
 /test-run-command
 /test-sha1
 /test-sigchain
+/test-string-list
 /test-subprocess
 /test-svn-fe
 /common-cmds.h
index 6303782..bcf4f87 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -18,6 +18,7 @@ David Kågedal <davidk@lysator.liu.se>
 David S. Miller <davem@davemloft.net>
 Deskin Miller <deskinm@umich.edu>
 Dirk Süsserott <newsletter@dirk.my1.cc>
+Erik Faye-Lund <kusmabite@gmail.com> <kusmabite@googlemail.com>
 Fredrik Kuivinen <freku045@student.liu.se>
 H. Peter Anvin <hpa@bonde.sc.orionmulti.com>
 H. Peter Anvin <hpa@tazenda.sc.orionmulti.com>
@@ -26,6 +27,9 @@ Horst H. von Brand <vonbrand@inf.utfsm.cl>
 İsmail Dönmez <ismail@pardus.org.tr>
 Jay Soffian <jaysoffian+git@gmail.com>
 Joachim Berdal Haga <cjhaga@fys.uio.no>
+Johannes Sixt <j6t@kdbg.org> <johannes.sixt@telecom.at>
+Johannes Sixt <j6t@kdbg.org> <j.sixt@viscovery.net>
+Johannes Sixt <j6t@kdbg.org> <J.Sixt@eudaptics.com>
 Jon Loeliger <jdl@freescale.com>
 Jon Seymour <jon@blackcubes.dyndns.org>
 Jonathan Nieder <jrnieder@uchicago.edu>
@@ -43,6 +47,7 @@ Lars Doelle <lars.doelle@on-line.de>
 Li Hong <leehong@pku.edu.cn>
 Lukas Sandström <lukass@etek.chalmers.se>
 Martin Langhoff <martin@laptop.org>
+Martin von Zweigbergk <martinvonz@gmail.com> <martin.von.zweigbergk@gmail.com>
 Michael Coleman <tutufan@gmail.com>
 Michael J Gruber <git@drmicha.warpmail.net> <michaeljgruber+gmane@fastmail.fm>
 Michael W. Olson <mwolson@gnu.org>
@@ -51,7 +56,10 @@ Nanako Shiraishi <nanako3@bluebottle.com>
 Nanako Shiraishi <nanako3@lavabit.com>
 Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
 <nico@fluxnic.net> <nico@cam.org>
+Peter Krefting <peter@softwolves.pp.se> <peter@svarten.intern.softwolves.pp.se>
+Peter Krefting <peter@softwolves.pp.se> <peter@softwolves.pp.se>
 Philippe Bruhat <book@cpan.org>
+Ralf Thielow <ralf.thielow@gmail.com> <ralf.thielow@googlemail.com>
 Ramsay Allan Jones <ramsay@ramsay1.demon.co.uk>
 René Scharfe <rene.scharfe@lsrfire.ath.cx>
 Robert Fitzsimons <robfitz@273k.net>
@@ -61,6 +69,7 @@ Sean Estabrooks <seanlkml@sympatico.ca>
 Shawn O. Pearce <spearce@spearce.org>
 Steven Grimm <koreth@midwinter.com>
 Theodore Ts'o <tytso@mit.edu>
+Thomas Rast <trast@inf.ethz.ch> <trast@student.ethz.ch>
 Tony Luck <tony.luck@intel.com>
 Uwe Kleine-König <Uwe_Zeisberger@digi.com>
 Uwe Kleine-König <Uwe.Kleine-Koenig@digi.com>
index ebf20e2..d41984d 100644 (file)
@@ -45,9 +45,3 @@ Fixes since v1.5.2
   - git-fastimport --import-marks was broken; fixed.
 
   - A lot of documentation updates, clarifications and fixes.
-
---
-exec >/var/tmp/1
-O=v1.5.2-65-g996e2d6
-echo O=`git describe refs/heads/maint`
-git shortlog --no-merges $O..refs/heads/maint
index e1e24b3..7d8fb85 100644 (file)
@@ -79,9 +79,3 @@ Fixes since v1.6.0.1
   packfile.
 
 Also contains many documentation updates.
-
---
-exec >/var/tmp/1
-O=v1.6.0.1-78-g3632cfc
-echo O=$(git describe maint)
-git shortlog --no-merges $O..maint
index 6f0bde1..cd08d81 100644 (file)
@@ -26,7 +26,3 @@ Fixes since v1.6.1.2
 * RPM binary package installed the html manpages in a wrong place.
 
 Also includes minor documentation fixes and updates.
-
-
---
-git shortlog --no-merges v1.6.1.2-33-gc789350..
index 0ce6316..ccbad79 100644 (file)
@@ -39,6 +39,3 @@ Fixes since v1.6.1.3
   This fix was first merged to 1.6.2.3.
 
 Also includes minor documentation fixes and updates.
-
---
-git shortlog --no-merges v1.6.1.3..
index adb7cca..7b152a6 100644 (file)
@@ -278,9 +278,3 @@ release, unless otherwise noted.
 
 * "gitweb" did not mark non-ASCII characters imported from external HTML fragments
   correctly.
-
---
-exec >/var/tmp/1
-O=v1.6.1-rc3-74-gf66bc5f
-echo O=$(git describe master)
-git shortlog --no-merges $O..master ^maint
diff --git a/Documentation/RelNotes/1.8.0.1.txt b/Documentation/RelNotes/1.8.0.1.txt
new file mode 100644 (file)
index 0000000..1f372fa
--- /dev/null
@@ -0,0 +1,64 @@
+Git v1.8.0.1 Release Notes
+==========================
+
+Fixes since v1.8.0
+------------------
+
+ * The configuration parser had an unnecessary hardcoded limit on
+   variable names that was not checked consistently.
+
+ * The "say" function in the test scaffolding incorrectly allowed
+   "echo" to interpret "\a" as if it were a C-string asking for a
+   BEL output.
+
+ * "git mergetool" feeds /dev/null as a common ancestor when dealing
+   with an add/add conflict, but p4merge backend cannot handle
+   it. Work it around by passing a temporary empty file.
+
+ * "git log -F -E --grep='<ere>'" failed to use the given <ere>
+   pattern as extended regular expression, and instead looked for the
+   string literally.
+
+ * "git grep -e pattern <tree>" asked the attribute system to read
+   "<tree>:.gitattributes" file in the working tree, which was
+   nonsense.
+
+ * A symbolic ref refs/heads/SYM was not correctly removed with "git
+   branch -d SYM"; the command removed the ref pointed by SYM
+   instead.
+
+ * Earlier we fixed documentation to hyphenate "remote-tracking branch"
+   to clarify that these are not a remote entity, but unhyphenated
+   spelling snuck in to a few places since then.
+
+ * "git pull --rebase" run while the HEAD is detached tried to find
+   the upstream branch of the detached HEAD (which by definition
+   does not exist) and emitted unnecessary error messages.
+
+ * The refs/replace hierarchy was not mentioned in the
+   repository-layout docs.
+
+ * Sometimes curl_multi_timeout() function suggested a wrong timeout
+   value when there is no file descriptors to wait on and the http
+   transport ended up sleeping for minutes in select(2) system call.
+   A workaround has been added for this.
+
+ * Various rfc2047 quoting issues around a non-ASCII name on the
+   From: line in the output from format-patch have been corrected.
+
+ * "git diff -G<pattern>" did not honor textconv filter when looking
+   for changes.
+
+ * Bash completion script (in contrib/) did not correctly complete a
+   lazy "git checkout $name_of_remote_tracking_branch_that_is_unique"
+   command line.
+
+ * RSS feed from "gitweb" had a xss hole in its title output.
+
+ * "git config --path $key" segfaulted on "[section] key" (a boolean
+   "true" spelled without "=", not "[section] key = true").
+
+ * "git checkout -b foo" while on an unborn branch did not say
+   "Switched to a new branch 'foo'" like other cases.
+
+Also contains other minor fixes and documentation updates.
diff --git a/Documentation/RelNotes/1.8.0.txt b/Documentation/RelNotes/1.8.0.txt
new file mode 100644 (file)
index 0000000..43883c1
--- /dev/null
@@ -0,0 +1,267 @@
+Git v1.8.0 Release Notes
+========================
+
+Backward compatibility notes
+----------------------------
+
+In the next major release (not *this* one), we will change the
+behavior of the "git push" command.
+
+When "git push [$there]" does not say what to push, we have used the
+traditional "matching" semantics so far (all your branches were sent
+to the remote as long as there already are branches of the same name
+over there).  We will use the "simple" semantics that pushes the
+current branch to the branch with the same name, only when the current
+branch is set to integrate with that remote branch.  There is a user
+preference configuration variable "push.default" to change this, and
+"git push" will warn about the upcoming change until you set this
+variable in this release.
+
+"git branch --set-upstream" is deprecated and may be removed in a
+relatively distant future.  "git branch [-u|--set-upstream-to]" has
+been introduced with a saner order of arguments.
+
+
+Updates since v1.7.12
+---------------------
+
+UI, Workflows & Features
+
+ * A credential helper for Win32 to allow access to the keychain of
+   the logged-in user has been added.
+
+ * An initial port to HP NonStop.
+
+ * A credential helper to allow access to the Gnome keyring has been
+   added.
+
+ * When "git am" sanitizes the "Subject:" line, we strip the prefix from
+   "Re: subject" and also from a less common "re: subject", but left
+   the even less common "RE: subject" intact.  Now we strip that too.
+
+ * It was tempting to say "git branch --set-upstream origin/master",
+   but that tells Git to arrange the local branch "origin/master" to
+   integrate with the currently checked out branch, which is highly
+   unlikely what the user meant.  The option is deprecated; use the
+   new "--set-upstream-to" (with a short-and-sweet "-u") option
+   instead.
+
+ * "git cherry-pick" learned the "--allow-empty-message" option to
+   allow it to replay a commit without any log message.
+
+ * After "git cherry-pick -s" gave control back to the user asking
+   help to resolve conflicts, concluding "git commit" used to need to
+   be run with "-s" if the user wants to sign it off; now the command
+   leaves the sign-off line in the log template.
+
+ * "git daemon" learned the "--access-hook" option to allow an
+   external command to decline service based on the client address,
+   repository path, etc.
+
+ * "git difftool --dir-diff" learned to use symbolic links to prepare
+   a temporary copy of the working tree when available.
+
+ * "git grep" learned to use a non-standard pattern type by default if
+   a configuration variable tells it to.
+
+ * Accumulated updates to "git gui" has been merged.
+
+ * "git log -g" learned the "--grep-reflog=<pattern>" option to limit
+   its output to commits with a reflog message that matches the given
+   pattern.
+
+ * "git merge-base" learned the "--is-ancestor A B" option to tell if A is
+   an ancestor of B.  The result is indicated by its exit status code.
+
+ * "git mergetool" now allows users to override the actual command used
+   with the mergetool.$name.cmd configuration variable even for built-in
+   mergetool backends.
+
+ * "git rebase -i" learned the "--edit-todo" option to open an editor
+   to edit the instruction sheet.
+
+
+Foreign Interface
+
+ * "git svn" has been updated to work with SVN 1.7.
+
+ * "git p4" learned the "--conflicts" option to specify what to do when
+   encountering a conflict during "p4 submit".
+
+
+Performance, Internal Implementation, etc.
+
+ * Git ships with a fall-back regexp implementation for platforms with
+   buggy regexp library, but it was easy for people to keep using their
+   platform regexp by mistake.  A new test has been added to check this.
+
+ * The "check-docs" build target has been updated and greatly
+   simplified.
+
+ * The test suite is run under MALLOC_CHECK_ when running with a glibc
+   that supports the feature.
+
+ * The documentation in the TeXinfo format was using indented output
+   for materials meant to be examples that are better typeset in
+   monospace.
+
+ * Compatibility wrapper around some mkdir(2) implementations that
+   reject parameters with trailing slash has been introduced.
+
+ * Compatibility wrapper for systems that lack usable setitimer() has
+   been added.
+
+ * The option parsing of "git checkout" had error checking, dwim and
+   defaulting missing options, all mixed in the code, and issuing an
+   appropriate error message with useful context was getting harder.
+   The code has been reorganized to allow giving a proper diagnosis
+   when the user says "git checkout -b -t foo bar" (e.g. "-t" is not a
+   good name for a branch).
+
+ * Many internal uses of a "git merge-base" equivalent were only to see
+   if one commit fast-forwards to the other, which did not need the
+   full set of merge bases to be computed. They have been updated to
+   use less expensive checks.
+
+ * The heuristics to detect and silently convert latin1 to utf8 when
+   we were told to use utf-8 in the log message has been transplanted
+   from "mailinfo" to "commit" and "commit-tree".
+
+ * Messages given by "git <subcommand> -h" from many subcommands have
+   been marked for translation.
+
+
+Also contains minor documentation updates and code clean-ups.
+
+
+Fixes since v1.7.12
+-------------------
+
+Unless otherwise noted, all the fixes since v1.7.12 in the
+maintenance track are contained in this release (see release notes
+to them for details).
+
+ * The attribute system may be asked for a path that itself or its
+   leading directories no longer exists in the working tree, and it is
+   fine if we cannot open .gitattribute file in such a case.  Failure
+   to open per-directory .gitattributes with error status other than
+   ENOENT and ENOTDIR should be diagnosed, but it wasn't.
+
+ * When looking for $HOME/.gitconfig etc., it is OK if we cannot read
+   them because they do not exist, but we did not diagnose existing
+   files that we cannot read.
+
+ * When "git am" is fed an input that has multiple "Content-type: ..."
+   header, it did not grok charset= attribute correctly.
+
+ * "git am" mishandled a patch attached as application/octet-stream
+   (e.g. not text/*); Content-Transfer-Encoding (e.g. base64) was not
+   honored correctly.
+
+ * "git blame MAKEFILE" run in a history that has "Makefile" but not
+   "MAKEFILE" should say "No such file MAKEFILE in HEAD", but got
+   confused on a case insensitive filesystem and failed to do so.
+
+ * Even during a conflicted merge, "git blame $path" always meant to
+   blame uncommitted changes to the "working tree" version; make it
+   more useful by showing cleanly merged parts as coming from the other
+   branch that is being merged.
+
+ * It was unclear in the documentation for "git blame" that it is
+   unnecessary for users to use the "--follow" option.
+
+ * Output from "git branch -v" contains "(no branch)" that could be
+   localized, but the code to align it along with the names of
+   branches was counting in bytes, not in display columns.
+
+ * "git cherry-pick A C B" used to replay changes in A and then B and
+   then C if these three commits had committer timestamps in that
+   order, which is not what the user who said "A C B" naturally
+   expects.
+
+ * A repository created with "git clone --single" had its fetch
+   refspecs set up just like a clone without "--single", leading the
+   subsequent "git fetch" to slurp all the other branches, defeating
+   the whole point of specifying "only this branch".
+
+ * Documentation talked about "first line of commit log" when it meant
+   the title of the commit.  The description was clarified by defining
+   how the title is decided and rewording the casual mention of "first
+   line" to "title".
+
+ * "git cvsimport" did not thoroughly cleanse tag names that it
+   inferred from the names of the tags it obtained from CVS, which
+   caused "git tag" to barf and stop the import in the middle.
+
+ * Earlier we made the diffstat summary line that shows the number of
+   lines added/deleted localizable, but it was found irritating having
+   to see them in various languages on a list whose discussion language
+   is English, and this change has been reverted.
+
+ * "git fetch --all", when passed "--no-tags", did not honor the
+   "--no-tags" option while fetching from individual remotes (the same
+   issue existed with "--tags", but the combination "--all --tags" makes
+   much less sense than "--all --no-tags").
+
+ * "git fetch" over http had an old workaround for an unlikely server
+   misconfiguration; it turns out that this hurts debuggability of the
+   configuration in general, and has been reverted.
+
+ * "git fetch" over http advertised that it supports "deflate", which
+   is much less common, and did not advertise the more common "gzip" on
+   its Accept-Encoding header.
+
+ * "git fetch" over the dumb-http revision walker could segfault when
+   curl's multi interface was used.
+
+ * "git gc --auto" notified the user that auto-packing has triggered
+    even under the "--quiet" option.
+
+ * After "gitk" showed the contents of a tag, neither "Reread
+   references" nor "Reload" updated what is shown as the
+   contents of it when the user overwrote the tag with "git tag -f".
+
+ * "git log --all-match --grep=A --grep=B" ought to show commits that
+   mention both A and B, but when these three options are used with
+   --author or --committer, it showed commits that mention either A or
+   B (or both) instead.
+
+ * The "-Xours" backend option to "git merge -s recursive" was ignored
+   for binary files.
+
+ * "git p4", when "--use-client-spec" and "--detect-branches" are used
+   together, misdetected branches.
+
+ * "git receive-pack" (the counterpart to "git push") did not give
+   progress output while processing objects it received to the puser
+   when run over the smart-http protocol.
+
+ * When you misspell the command name you give to the "exec" action in
+   the "git rebase -i" instruction sheet you were told that 'rebase' is not a
+   git subcommand from "git rebase --continue".
+
+ * The subcommand in "git remote" to remove a defined remote was
+   "rm" and the command did not take a fully-spelled "remove".
+
+ * The interactive prompt that "git send-email" gives was error prone. It
+   asked "What e-mail address do you want to use?" with the address it
+   guessed (correctly) the user would want to use in its prompt,
+   tempting the user to say "y". But the response was taken as "No,
+   please use 'y' as the e-mail address instead", which is most
+   certainly not what the user meant.
+
+ * "git show --format='%ci'" did not give the timestamp correctly for
+   commits created without human readable name on the "committer" line.
+
+ * "git show --quiet" ought to be a synonym for "git show -s", but
+   wasn't.
+
+ * "git submodule frotz" was not diagnosed as "frotz" being an unknown
+   subcommand to "git submodule"; the user instead got a complaint
+   that "git submodule status" was run with an unknown path "frotz".
+
+ * "git status" honored the ignore=dirty settings in .gitmodules but
+   "git commit" didn't.
+
+ * "gitweb" did not give the correct committer timezone in its feed
+   output due to a typo.
index 122e3c4..11f320b 100644 (file)
@@ -1211,8 +1211,16 @@ gitweb.snapshot::
 grep.lineNumber::
        If set to true, enable '-n' option by default.
 
+grep.patternType::
+       Set the default matching behavior. Using a value of 'basic', 'extended',
+       'fixed', or 'perl' will enable the '--basic-regexp', '--extended-regexp',
+       '--fixed-strings', or '--perl-regexp' option accordingly, while the
+       value 'default' will return to the default matching behavior.
+
 grep.extendedRegexp::
-       If set to true, enable '--extended-regexp' option by default.
+       If set to true, enable '--extended-regexp' option by default. This
+       option is ignored when the 'grep.patternType' option is set to a value
+       other than 'default'.
 
 gpg.program::
        Use this custom program instead of "gpg" found on $PATH when
index 4f44131..45a225e 100644 (file)
@@ -13,6 +13,8 @@ SYNOPSIS
        [--column[=<options>] | --no-column]
        [(--merged | --no-merged | --contains) [<commit>]] [<pattern>...]
 'git branch' [--set-upstream | --track | --no-track] [-l] [-f] <branchname> [<start-point>]
+'git branch' (--set-upstream-to=<upstream> | -u <upstream>) [<branchname>]
+'git branch' --unset-upstream [<branchname>]
 'git branch' (-m | -M) [<oldbranch>] <newbranch>
 'git branch' (-d | -D) [-r] <branchname>...
 'git branch' --edit-description [<branchname>]
@@ -48,7 +50,7 @@ branch so that 'git pull' will appropriately merge from
 the remote-tracking 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, and
-changed later using `git branch --set-upstream`.
+changed later using `git branch --set-upstream-to`.
 
 With a `-m` or `-M` option, <oldbranch> will be renamed to <newbranch>.
 If <oldbranch> had a corresponding reflog, it is renamed to match
@@ -175,6 +177,16 @@ start-point is either a local or remote-tracking branch.
        like `--track` would when creating the branch, except that where
        branch points to is not changed.
 
+-u <upstream>::
+--set-upstream-to=<upstream>::
+       Set up <branchname>'s tracking information so <upstream> is
+       considered <branchname>'s upstream branch. If no <branchname>
+       is specified, then it defaults to the current branch.
+
+--unset-upstream::
+       Remove the upstream information for <branchname>. If no branch
+       is specified it defaults to the current branch.
+
 --edit-description::
        Open an editor and edit the text to explain what the branch is
        for, to be used by various other commands (e.g. `request-pull`).
index 0e170a5..c205d23 100644 (file)
@@ -118,6 +118,11 @@ effect to your index in a row.
        previous commit are dropped.  To force the inclusion of those commits
        use `--keep-redundant-commits`.
 
+--allow-empty-message::
+       By default, cherry-picking a commit with an empty message will fail.
+       This option overrides that behaviour, allowing commits with empty
+       messages to be cherry picked.
+
 --keep-redundant-commits::
        If a commit being cherry picked duplicates a commit already in the
        current history, it will become empty.  By default these
index 6d98ef3..7fefdb0 100644 (file)
@@ -196,9 +196,9 @@ objects from the source repository into a pack in the cloned repository.
        `--no-single-branch` is given to fetch the histories near the
        tips of all branches.
        Further fetches into the resulting repository will only update the
-       remote tracking branch for the branch this option was used for the
+       remote-tracking branch for the branch this option was used for the
        initial cloning.  If the HEAD at the remote did not point at any
-       branch when `--single-branch` clone was made, no remote tracking
+       branch when `--single-branch` clone was made, no remote-tracking
        branch is created.
 
 --recursive::
index 9594ac8..15cec86 100644 (file)
@@ -184,6 +184,11 @@ OPTIONS
        commit log message unmodified.  This option lets you
        further edit the message taken from these sources.
 
+--no-edit::
+       Use the selected commit message without launching an editor.
+       For example, `git commit --amend --no-edit` amends a commit
+       without changing its commit message.
+
 --amend::
        Used to amend the tip of the current branch. Prepare the tree
        object you would want to replace the latest commit as usual
@@ -193,10 +198,6 @@ OPTIONS
        current tip -- if it was a merge, it will have the parents of
        the current tip as parents -- so the current top commit is
        discarded.
-
---no-post-rewrite::
-       Bypass the post-rewrite hook.
-
 +
 --
 It is a rough equivalent for:
@@ -213,6 +214,9 @@ You should understand the implications of rewriting history if you
 amend a commit that has already been published.  (See the "RECOVERING
 FROM UPSTREAM REBASE" section in linkgit:git-rebase[1].)
 
+--no-post-rewrite::
+       Bypass the post-rewrite hook.
+
 -i::
 --include::
        Before making a commit out of staged contents so far,
index e8f7577..7e5098a 100644 (file)
@@ -16,6 +16,7 @@ SYNOPSIS
             [--reuseaddr] [--detach] [--pid-file=<file>]
             [--enable=<service>] [--disable=<service>]
             [--allow-override=<service>] [--forbid-override=<service>]
+            [--access-hook=<path>]
             [--inetd | [--listen=<host_or_ipaddr>] [--port=<n>] [--user=<user> [--group=<group>]]
             [<directory>...]
 
@@ -171,6 +172,21 @@ the facility of inet daemon to achieve the same before spawning
        errors are not enabled, all errors report "access denied" to the
        client. The default is --no-informative-errors.
 
+--access-hook=<path>::
+       Every time a client connects, first run an external command
+       specified by the <path> with service name (e.g. "upload-pack"),
+       path to the repository, hostname (%H), canonical hostname
+       (%CH), ip address (%IP), and tcp port (%P) as its command line
+       arguments. The external command can decide to decline the
+       service by exiting with a non-zero status (or to allow it by
+       exiting with a zero status).  It can also look at the $REMOTE_ADDR
+       and $REMOTE_PORT environment variables to learn about the
+       requestor when making this decision.
++
+The external command can optionally write a single line to its
+standard output to be sent to the requestor as an error message when
+it declines the service.
+
 <directory>::
        A directory to add to the whitelist of allowed directories. Unless
        --strict-paths is specified this will also include subdirectories
index 31fc2e3..73ca702 100644 (file)
@@ -69,6 +69,14 @@ with custom merge tool commands and has the same value as `$MERGED`.
 --tool-help::
        Print a list of diff tools that may be used with `--tool`.
 
+--symlinks::
+--no-symlinks::
+       'git difftool''s default behavior is create symlinks to the
+       working tree when run in `--dir-diff` mode.
++
+       Specifying `--no-symlinks` instructs 'git difftool' to create
+       copies instead.  `--no-symlinks` is the default on Windows.
+
 -x <command>::
 --extcmd=<command>::
        Specify a custom command for viewing diffs.
index 6603a7a..959e4d3 100644 (file)
@@ -442,7 +442,9 @@ their syntax.
 ^^^^^^
 The `from` command is used to specify the commit to initialize
 this branch from.  This revision will be the first ancestor of the
-new commit.
+new commit.  The state of the tree built at this commit will begin
+with the state at the `from` commit, and be altered by the content
+modifications in this commit.
 
 Omitting the `from` command in the first commit of a new branch
 will cause fast-import to create that commit with no ancestor. This
@@ -492,7 +494,9 @@ existing value of the branch.
 
 `merge`
 ^^^^^^^
-Includes one additional ancestor commit.  If the `from` command is
+Includes one additional ancestor commit.  The additional ancestry
+link does not change the way the tree state is built at this commit.
+If the `from` command is
 omitted when creating a new branch, the first `merge` commit will be
 the first ancestor of the current commit, and the branch will start
 out with no files.  An unlimited number of `merge` commands per
index 3bec036..cfecf84 100644 (file)
@@ -42,8 +42,16 @@ CONFIGURATION
 grep.lineNumber::
        If set to true, enable '-n' option by default.
 
+grep.patternType::
+       Set the default matching behavior. Using a value of 'basic', 'extended',
+       'fixed', or 'perl' will enable the '--basic-regexp', '--extended-regexp',
+       '--fixed-strings', or '--perl-regexp' option accordingly, while the
+       value 'default' will return to the default matching behavior.
+
 grep.extendedRegexp::
-       If set to true, enable '--extended-regexp' option by default.
+       If set to true, enable '--extended-regexp' option by default. This
+       option is ignored when the 'grep.patternType' option is set to a value
+       other than 'default'.
 
 
 OPTIONS
index b295bf8..87842e3 100644 (file)
@@ -11,6 +11,7 @@ SYNOPSIS
 [verse]
 'git merge-base' [-a|--all] <commit> <commit>...
 'git merge-base' [-a|--all] --octopus <commit>...
+'git merge-base' --is-ancestor <commit> <commit>
 'git merge-base' --independent <commit>...
 
 DESCRIPTION
@@ -50,6 +51,12 @@ from linkgit:git-show-branch[1] when used with the `--merge-base` option.
        from any other.  This mimics the behavior of 'git show-branch
        --independent'.
 
+--is-ancestor::
+       Check if the first <commit> is an ancestor of the second <commit>,
+       and exit with status 0 if true, or with status 1 if not.
+       Errors are signaled by a non-zero status that is not 1.
+
+
 OPTIONS
 -------
 -a::
@@ -110,6 +117,27 @@ both '1' and '2' are merge-bases of A and B.  Neither one is better than
 the other (both are 'best' merge bases).  When the `--all` option is not given,
 it is unspecified which best one is output.
 
+A common idiom to check "fast-forward-ness" between two commits A
+and B is (or at least used to be) to compute the merge base between
+A and B, and check if it is the same as A, in which case, A is an
+ancestor of B.  You will see this idiom used often in older scripts.
+
+       A=$(git rev-parse --verify A)
+       if test "$A" = "$(git merge-base A B)"
+       then
+               ... A is an ancestor of B ...
+       fi
+
+In modern git, you can say this in a more direct way:
+
+       if git merge-base --is-ancestor A B
+       then
+               ... A is an ancestor of B ...
+       fi
+
+instead.
+
+
 See also
 --------
 linkgit:git-rev-list[1],
index 20f9228..d34ea3c 100644 (file)
@@ -99,7 +99,7 @@ commit or stash your changes before running 'git merge'.
        more than two parents (affectionately called an Octopus merge).
 +
 If no commit is given from the command line, and if `merge.defaultToUpstream`
-configuration variable is set, merge the remote tracking branches
+configuration variable is set, merge the remote-tracking branches
 that the current branch is configured to use as its upstream.
 See also the configuration section of this manual page.
 
index d7207bd..6b563c5 100644 (file)
@@ -64,6 +64,9 @@ variable `mergetool.<tool>.trustExitCode` can be set to `true`.
 Otherwise, 'git mergetool' will prompt the user to indicate the
 success of the resolution after the custom tool has exited.
 
+--tool-help::
+       Print a list of merge tools that may be used with `--tool`.
+
 -y::
 --no-prompt::
        Don't prompt before each invocation of the merge resolution
index 8228f33..beff622 100644 (file)
@@ -163,7 +163,7 @@ All commands except clone accept these options.
 --git-dir <dir>::
        Set the 'GIT_DIR' environment variable.  See linkgit:git[1].
 
---verbose::
+--verbose, -v::
        Provide more progress information.
 
 Sync options
@@ -269,6 +269,24 @@ These options can be used to modify 'git p4 submit' behavior.
        Export tags from git as p4 labels. Tags found in git are applied
        to the perforce working directory.
 
+--dry-run, -n::
+       Show just what commits would be submitted to p4; do not change
+       state in git or p4.
+
+--prepare-p4-only::
+       Apply a commit to the p4 workspace, opening, adding and deleting
+       files in p4 as for a normal submit operation.  Do not issue the
+       final "p4 submit", but instead print a message about how to
+       submit manually or revert.  This option always stops after the
+       first (oldest) commit.  Git tags are not exported to p4.
+
+--conflict=(ask|skip|quit)::
+       Conflicts can occur when applying a commit to p4.  When this
+       happens, the default behavior ("ask") is to prompt whether to
+       skip this commit and continue, or quit.  This option can be used
+       to bypass the prompt, causing conflicting commits to be automatically
+       skipped, or to quit trying to apply commits, without prompting.
+
 Rebase options
 ~~~~~~~~~~~~~~
 These options can be used to modify 'git p4 rebase' behavior.
@@ -519,6 +537,10 @@ git-p4.labelExportRegexp::
        Only p4 labels matching this regular expression will be exported. The
        default value is '[a-zA-Z0-9_\-.]+$'.
 
+git-p4.conflict::
+       Specify submit behavior when a conflict with p4 is found, as per
+       --conflict.  The default behavior is 'ask'.
+
 IMPLEMENTATION DETAILS
 ----------------------
 * Changesets from p4 are imported using git fast-import.
index cb97cc1..6d19d59 100644 (file)
@@ -37,7 +37,9 @@ OPTIONS[[OPTIONS]]
        `+`, followed by the source ref <src>, followed
        by a colon `:`, followed by the destination ref <dst>.
        It is used to specify with what <src> object the <dst> ref
-       in the remote repository is to be updated.
+       in the remote repository is to be updated.  If not specified,
+       the behavior of the command is controlled by the `push.default`
+       configuration variable.
 +
 The <src> is often the name of the branch you would want to push, but
 it can be any arbitrary "SHA-1 expression", such as `master~4` or
@@ -65,7 +67,8 @@ directs git to push "matching" branches: for every branch that exists on
 the local side, the remote side is updated if a branch of the same name
 already exists on the remote side.  This is the default operation mode
 if no explicit refspec is found (that is neither on the command line
-nor in any Push line of the corresponding remotes file---see below).
+nor in any Push line of the corresponding remotes file---see below) and
+no `push.default` configuration variable is set.
 
 --all::
        Instead of naming each ref to push, specifies that all
@@ -172,7 +175,7 @@ useful if you write an alias or script around 'git push'.
 
 --recurse-submodules=check|on-demand::
        Make sure all submodule commits used by the revisions to be
-       pushed are available on a remote tracking branch. If 'check' is
+       pushed are available on a remote-tracking branch. If 'check' is
        used git will verify that all submodule commits that changed in
        the revisions to be pushed are available on at least one remote
        of the submodule. If any commits are missing the push will be
@@ -283,7 +286,8 @@ leading to commit A.  The history looks like this:
 ----------------
 
 Further suppose that the other person already pushed changes leading to A
-back to the original repository you two obtained the original commit X.
+back to the original repository from which you two obtained the original
+commit X.
 
 The push done by the other person updated the branch that used to point at
 commit X to point at commit A.  It is a fast-forward.
@@ -357,7 +361,8 @@ Examples
        `git push origin :`.
 +
 The default behavior of this command when no <refspec> is given can be
-configured by setting the `push` option of the remote.
+configured by setting the `push` option of the remote, or the `push.default`
+configuration variable.
 +
 For example, to default to pushing only the current branch to `origin`
 use `git config remote.origin.push HEAD`.  Any valid <refspec> (like
index fd535b0..da067ec 100644 (file)
@@ -12,7 +12,7 @@ SYNOPSIS
        [<upstream>] [<branch>]
 'git rebase' [-i | --interactive] [options] [--exec <cmd>] [--onto <newbase>]
        --root [<branch>]
-'git rebase' --continue | --skip | --abort
+'git rebase' --continue | --skip | --abort | --edit-todo
 
 DESCRIPTION
 -----------
@@ -245,6 +245,9 @@ leave out at most one of A and B, in which case it defaults to HEAD.
 --skip::
        Restart the rebasing process by skipping the current patch.
 
+--edit-todo::
+       Edit the todo list during an interactive rebase.
+
 -m::
 --merge::
        Use merging strategies to rebase.  When the recursive (default) merge
index b4683bb..a65f38e 100644 (file)
@@ -9,7 +9,7 @@ git-submodule - Initialize, update or inspect submodules
 SYNOPSIS
 --------
 [verse]
-'git submodule' [--quiet] add [-b branch] [-f|--force]
+'git submodule' [--quiet] add [-b <branch>] [-f|--force]
              [--reference <repository>] [--] <repository> [<path>]
 'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]
 'git submodule' [--quiet] init [--] [<path>...]
index fbdd2a5..cbe0883 100644 (file)
@@ -43,6 +43,12 @@ unreleased) version of git, that is available from 'master'
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
+* link:v1.8.0.1/git.html[documentation for release 1.8.0.1]
+
+* release notes for
+  link:RelNotes/1.8.0.1.txt[1.8.0.1],
+  link:RelNotes/1.8.0.txt[1.8.0].
+
 * link:v1.7.12.4/git.html[documentation for release 1.7.12.4]
 
 * release notes for
index 52ab93d..ba02d4d 100644 (file)
@@ -516,6 +516,8 @@ configuration file (you still need to enable this with the
 attribute mechanism, via `.gitattributes`).  The following built in
 patterns are available:
 
+- `ada` suitable for source code in the Ada language.
+
 - `bibtex` suitable for files with BibTeX coded references.
 
 - `cpp` suitable for source code in the C and C++ languages.
index 5c891f1..9f62886 100644 (file)
@@ -93,6 +93,12 @@ refs/remotes/`name`::
        records tip-of-the-tree commit objects of branches copied
        from a remote repository.
 
+refs/replace/`<obj-sha1>`::
+       records the SHA1 of the object that replaces `<obj-sha1>`.
+       This is similar to info/grafts and is internally used and
+       maintained by linkgit:git-replace[1]. Such refs can be exchanged
+       between repositories while grafts are not.
+
 packed-refs::
        records the same information as refs/heads/, refs/tags/,
        and friends record in a more efficient way.  See
index 861bd6f..9bb4956 100644 (file)
@@ -9,11 +9,11 @@ merge.conflictstyle::
 merge.defaultToUpstream::
        If merge is called without any commit argument, merge the upstream
        branches configured for the current branch by using their last
-       observed values stored in their remote tracking branches.
+       observed values stored in their remote-tracking branches.
        The values of the `branch.<current branch>.merge` that name the
        branches at the remote named by `branch.<current branch>.remote`
        are consulted, and then they are mapped via `remote.<remote>.fetch`
-       to their corresponding remote tracking branches, and the tips of
+       to their corresponding remote-tracking branches, and the tips of
        these tracking branches are merged.
 
 merge.ff::
index 1fc2a18..ee49743 100644 (file)
@@ -51,6 +51,14 @@ endif::git-rev-list[]
        commits whose author matches any of the given patterns are
        chosen (similarly for multiple `--committer=<pattern>`).
 
+--grep-reflog=<pattern>::
+
+       Limit the commits output to ones with reflog entries that
+       match the specified pattern (regular expression). With
+       more than one `--grep-reflog`, commits whose reflog message
+       matches any of the given patterns are chosen.  It is an
+       error to use this option unless `--walk-reflogs` is in use.
+
 --grep=<pattern>::
 
        Limit the commits output to ones with log message that
@@ -58,6 +66,9 @@ endif::git-rev-list[]
        more than one `--grep=<pattern>`, commits whose message
        matches any of the given patterns are chosen (but see
        `--all-match`).
++
+When `--show-notes` is in effect, the message from the notes as
+if it is part of the log message.
 
 --all-match::
        Limit the commits output to ones that match all given --grep,
index 69d996b..991fcd8 100644 (file)
@@ -55,6 +55,8 @@ when you run `git cherry-pick`.
 +
 Note that any of the 'refs/*' cases above may come either from
 the '$GIT_DIR/refs' directory or from the '$GIT_DIR/packed-refs' file.
+While the ref name encoding is unspecified, UTF-8 is prefered as
+some output processing may assume ref names in UTF-8.
 
 '<refname>@\{<date>\}', e.g. 'master@\{yesterday\}', 'HEAD@\{5 minutes ago\}'::
   A ref followed by the suffix '@' with a date specification
index 4a4bae8..45d1c51 100644 (file)
@@ -25,9 +25,6 @@ Functions
        the array (but note that some operations below may lose this
        ordering).
 
-`sha1_array_sort`::
-       Sort the elements in the array.
-
 `sha1_array_lookup`::
        Perform a binary search of the array for a specific sha1.
        If found, returns the offset (in number of elements) of the
index 5a0c14f..94d7a2b 100644 (file)
@@ -1,8 +1,9 @@
 string-list API
 ===============
 
-The string_list API offers a data structure and functions to handle sorted
-and unsorted string lists.
+The string_list API offers a data structure and functions to handle
+sorted and unsorted string lists.  A "sorted" list is one whose
+entries are sorted by string value in `strcmp()` order.
 
 The 'string_list' struct used to be called 'path_list', but was renamed
 because it is not specific to paths.
@@ -20,8 +21,9 @@ If you need something advanced, you can manually malloc() the `items`
 member (you need this if you add things later) and you should set the
 `nr` and `alloc` members in that case, too.
 
-. Adds new items to the list, using `string_list_append` or
-  `string_list_insert`.
+. Adds new items to the list, using `string_list_append`,
+  `string_list_append_nodup`, `string_list_insert`,
+  `string_list_split`, and/or `string_list_split_in_place`.
 
 . Can check if a string is in the list using `string_list_has_string` or
   `unsorted_string_list_has_string` and get it from the list using
@@ -29,18 +31,23 @@ member (you need this if you add things later) and you should set the
 
 . Can sort an unsorted list using `sort_string_list`.
 
+. Can remove duplicate items from a sorted list using
+  `string_list_remove_duplicates`.
+
 . Can remove individual items of an unsorted list using
   `unsorted_string_list_delete_item`.
 
+. Can remove items not matching a criterion from a sorted or unsorted
+  list using `filter_string_list`.
+
 . Finally it should free the list using `string_list_clear`.
 
 Example:
 
 ----
-struct string_list list;
+struct string_list list = STRING_LIST_INIT_NODUP;
 int i;
 
-memset(&list, 0, sizeof(struct string_list));
 string_list_append(&list, "foo");
 string_list_append(&list, "bar");
 for (i = 0; i < list.nr; i++)
@@ -60,6 +67,22 @@ Functions
 
 * General ones (works with sorted and unsorted lists as well)
 
+`filter_string_list`::
+
+       Apply a function to each item in a list, retaining only the
+       items for which the function returns true.  If free_util is
+       true, call free() on the util members of any items that have
+       to be deleted.  Preserve the order of the items that are
+       retained.
+
+`string_list_longest_prefix`::
+
+       Return the longest string within a string_list that is a
+       prefix (in the sense of prefixcmp()) of the specified string,
+       or NULL if no such prefix exists.  This function does not
+       require the string_list to be sorted (it does a linear
+       search).
+
 `print_string_list`::
 
        Dump a string_list to stdout, useful mainly for debugging purposes. It
@@ -96,15 +119,32 @@ write `string_list_insert(...)->util = ...;`.
        Look up a given string in the string_list, returning the containing
        string_list_item. If the string is not found, NULL is returned.
 
+`string_list_remove_duplicates`::
+
+       Remove all but the first of consecutive entries that have the
+       same string value.  If free_util is true, call free() on the
+       util members of any items that have to be deleted.
+
 * Functions for unsorted lists only
 
 `string_list_append`::
 
-       Append a new string to the end of the string_list.
+       Append a new string to the end of the string_list.  If
+       `strdup_string` is set, then the string argument is copied;
+       otherwise the new `string_list_entry` refers to the input
+       string.
+
+`string_list_append_nodup`::
+
+       Append a new string to the end of the string_list.  The new
+       `string_list_entry` always refers to the input string, even if
+       `strdup_string` is set.  This function can be used to hand
+       ownership of a malloc()ed string to a `string_list` that has
+       `strdup_string` set.
 
 `sort_string_list`::
 
-       Make an unsorted list sorted.
+       Sort the list's entries by string value in `strcmp()` order.
 
 `unsorted_string_list_has_string`::
 
@@ -124,6 +164,25 @@ counterpart for sorted lists, which performs a binary search.
        is set. The third parameter controls if the `util` pointer of the
        items should be freed or not.
 
+`string_list_split`::
+`string_list_split_in_place`::
+
+       Split a string into substrings on a delimiter character and
+       append the substrings to a `string_list`.  If `maxsplit` is
+       non-negative, then split at most `maxsplit` times.  Return the
+       number of substrings appended to the list.
++
+`string_list_split` requires a `string_list` that has `strdup_strings`
+set to true; it leaves the input string untouched and makes copies of
+the substrings in newly-allocated memory.
+`string_list_split_in_place` requires a `string_list` that has
+`strdup_strings` set to false; it splits the input string in place,
+overwriting the delimiter characters with NULs and creating new
+string_list_items that point into the original string (the original
+string must therefore not be modified or freed while the `string_list`
+is in use).
+
+
 Data structures
 ---------------
 
index 7451390..d66e54f 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v1.7.12.4
+DEF_VER=v1.8.0.1
 
 LF='
 '
index 26b697d..6b73c14 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -90,6 +90,8 @@ all::
 #
 # Define NO_MKDTEMP if you don't have mkdtemp in the C library.
 #
+# Define MKDIR_WO_TRAILING_SLASH if your mkdir() can't deal with trailing slash.
+#
 # Define NO_MKSTEMPS if you don't have mkstemps in the C library.
 #
 # Define NO_STRTOK_R if you don't have strtok_r in the C library.
@@ -143,6 +145,12 @@ all::
 #
 # Define NEEDS_LIBICONV if linking with libc is not enough (Darwin).
 #
+# Define NEEDS_LIBINTL_BEFORE_LIBICONV if you need libintl before libiconv.
+#
+# Define NO_INTPTR_T if you don't have intptr_t nor uintptr_t.
+#
+# Define NO_UINTMAX_T if you don't have uintmax_t.
+#
 # Define NEEDS_SOCKET if linking with libc is not enough (SunOS,
 # Patrick Mauritz).
 #
@@ -152,11 +160,21 @@ all::
 #
 # Define NO_MMAP if you want to avoid mmap.
 #
+# Define NO_SYS_POLL_H if you don't have sys/poll.h.
+#
+# Define NO_POLL if you do not have or don't want to use poll().
+# This also implies NO_SYS_POLL_H.
+#
 # Define NO_PTHREADS if you do not have or do not want to use Pthreads.
 #
 # Define NO_PREAD if you have a problem with pread() system call (e.g.
 # cygwin1.dll before v1.5.22).
 #
+# Define NO_SETITIMER if you don't have setitimer()
+#
+# Define NO_STRUCT_ITIMERVAL if you don't have struct itimerval
+# This also implies NO_SETITIMER
+#
 # Define NO_THREAD_SAFE_PREAD if your pread() implementation is not
 # thread-safe. (e.g. compat/pread.c or cygwin)
 #
@@ -502,6 +520,7 @@ TEST_PROGRAMS_NEED_X += test-run-command
 TEST_PROGRAMS_NEED_X += test-scrap-cache-tree
 TEST_PROGRAMS_NEED_X += test-sha1
 TEST_PROGRAMS_NEED_X += test-sigchain
+TEST_PROGRAMS_NEED_X += test-string-list
 TEST_PROGRAMS_NEED_X += test-subprocess
 TEST_PROGRAMS_NEED_X += test-svn-fe
 
@@ -596,10 +615,10 @@ LIB_H += compat/bswap.h
 LIB_H += compat/cygwin.h
 LIB_H += compat/mingw.h
 LIB_H += compat/obstack.h
+LIB_H += compat/poll/poll.h
 LIB_H += compat/precompose_utf8.h
 LIB_H += compat/terminal.h
 LIB_H += compat/win32/dirent.h
-LIB_H += compat/win32/poll.h
 LIB_H += compat/win32/pthread.h
 LIB_H += compat/win32/syslog.h
 LIB_H += connected.h
@@ -1217,7 +1236,7 @@ ifeq ($(uname_S),Windows)
        NO_PREAD = YesPlease
        NEEDS_CRYPTO_WITH_SSL = YesPlease
        NO_LIBGEN_H = YesPlease
-       NO_SYS_POLL_H = YesPlease
+       NO_POLL = YesPlease
        NO_SYMLINK_HEAD = YesPlease
        NO_IPV6 = YesPlease
        NO_UNIX_SOCKETS = YesPlease
@@ -1258,7 +1277,7 @@ ifeq ($(uname_S),Windows)
        BASIC_CFLAGS = -nologo -I. -I../zlib -Icompat/vcbuild -Icompat/vcbuild/include -DWIN32 -D_CONSOLE -DHAVE_STRING_H -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE
        COMPAT_OBJS = compat/msvc.o compat/winansi.o \
                compat/win32/pthread.o compat/win32/syslog.o \
-               compat/win32/poll.o compat/win32/dirent.o
+               compat/win32/dirent.o
        COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DNOGDI -DHAVE_STRING_H -DHAVE_ALLOCA_H -Icompat -Icompat/regex -Icompat/win32 -DSTRIP_EXTENSION=\".exe\"
        BASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -SUBSYSTEM:CONSOLE -NODEFAULTLIB:MSVCRT.lib
        EXTLIBS = user32.lib advapi32.lib shell32.lib wininet.lib ws2_32.lib
@@ -1308,12 +1327,67 @@ ifeq ($(uname_S),Minix)
        NO_CURL =
        NO_EXPAT =
 endif
+ifeq ($(uname_S),NONSTOP_KERNEL)
+       # Needs some C99 features, "inline" is just one of them.
+       # INLINE='' would just replace one set of warnings with another and
+       # still not compile in c89 mode, due to non-const array initializations.
+       CC = cc -c99
+       # Disable all optimization, seems to result in bad code, with -O or -O2
+       # or even -O1 (default), /usr/local/libexec/git-core/git-pack-objects
+       # abends on "git push". Needs more investigation.
+       CFLAGS = -g -O0
+       # We'd want it to be here.
+       prefix = /usr/local
+       # Our's are in ${prefix}/bin (perl might also be in /usr/bin/perl).
+       PERL_PATH = ${prefix}/bin/perl
+       PYTHON_PATH = ${prefix}/bin/python
+
+       # As detected by './configure'.
+       # Missdetected, hence commented out, see below.
+       #NO_CURL = YesPlease
+       # Added manually, see above.
+       NEEDS_SSL_WITH_CURL = YesPlease
+       HAVE_LIBCHARSET_H = YesPlease
+       NEEDS_LIBICONV = YesPlease
+       NEEDS_LIBINTL_BEFORE_LIBICONV = YesPlease
+       NO_SYS_SELECT_H = UnfortunatelyYes
+       NO_D_TYPE_IN_DIRENT = YesPlease
+       NO_HSTRERROR = YesPlease
+       NO_STRCASESTR = YesPlease
+       NO_FNMATCH_CASEFOLD = YesPlease
+       NO_MEMMEM = YesPlease
+       NO_STRLCPY = YesPlease
+       NO_SETENV = YesPlease
+       NO_UNSETENV = YesPlease
+       NO_MKDTEMP = YesPlease
+       NO_MKSTEMPS = YesPlease
+       # Currently libiconv-1.9.1.
+       OLD_ICONV = UnfortunatelyYes
+       NO_REGEX = YesPlease
+       NO_PTHREADS = UnfortunatelyYes
+
+       # Not detected (nor checked for) by './configure'.
+       # We don't have SA_RESTART on NonStop, unfortunalety.
+       COMPAT_CFLAGS += -DSA_RESTART=0
+       # Apparently needed in compat/fnmatch/fnmatch.c.
+       COMPAT_CFLAGS += -DHAVE_STRING_H=1
+       NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
+       NO_NSEC = YesPlease
+       NO_PREAD = YesPlease
+       NO_MMAP = YesPlease
+       NO_POLL = YesPlease
+       NO_INTPTR_T = UnfortunatelyYes
+       # Bug report 10-120822-4477 submitted to HP NonStop development.
+       MKDIR_WO_TRAILING_SLASH = YesPlease
+       # RFE 10-120912-4693 submitted to HP NonStop development.
+       NO_SETITIMER = UnfortunatelyYes
+endif
 ifneq (,$(findstring MINGW,$(uname_S)))
        pathsep = ;
        NO_PREAD = YesPlease
        NEEDS_CRYPTO_WITH_SSL = YesPlease
        NO_LIBGEN_H = YesPlease
-       NO_SYS_POLL_H = YesPlease
+       NO_POLL = YesPlease
        NO_SYMLINK_HEAD = YesPlease
        NO_UNIX_SOCKETS = YesPlease
        NO_SETENV = YesPlease
@@ -1348,7 +1422,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
        COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
        COMPAT_OBJS += compat/mingw.o compat/winansi.o \
                compat/win32/pthread.o compat/win32/syslog.o \
-               compat/win32/poll.o compat/win32/dirent.o
+               compat/win32/dirent.o
        EXTLIBS += -lws2_32
        PTHREAD_LIBS =
        X = .exe
@@ -1490,7 +1564,7 @@ else
        REMOTE_CURL_NAMES = $(REMOTE_CURL_PRIMARY) $(REMOTE_CURL_ALIASES)
        PROGRAM_OBJS += http-fetch.o
        PROGRAMS += $(REMOTE_CURL_NAMES)
-       curl_check := $(shell (echo 070908; curl-config --vernum) | sort -r | sed -ne 2p)
+       curl_check := $(shell (echo 070908; curl-config --vernum) 2>/dev/null | sort -r | sed -ne 2p)
        ifeq "$(curl_check)" "070908"
                ifndef NO_EXPAT
                        PROGRAM_OBJS += http-push.o
@@ -1544,6 +1618,9 @@ ifdef NEEDS_LIBICONV
        else
                ICONV_LINK =
        endif
+       ifdef NEEDS_LIBINTL_BEFORE_LIBICONV
+               ICONV_LINK += -lintl
+       endif
        EXTLIBS += $(ICONV_LINK) -liconv
 endif
 ifdef NEEDS_LIBGEN
@@ -1602,6 +1679,11 @@ ifdef NO_GETTEXT
        BASIC_CFLAGS += -DNO_GETTEXT
        USE_GETTEXT_SCHEME ?= fallthrough
 endif
+ifdef NO_POLL
+       NO_SYS_POLL_H = YesPlease
+       COMPAT_CFLAGS += -DNO_POLL -Icompat/poll
+       COMPAT_OBJS += compat/poll/poll.o
+endif
 ifdef NO_STRCASESTR
        COMPAT_CFLAGS += -DNO_STRCASESTR
        COMPAT_OBJS += compat/strcasestr.o
@@ -1640,6 +1722,10 @@ ifdef NO_MKDTEMP
        COMPAT_CFLAGS += -DNO_MKDTEMP
        COMPAT_OBJS += compat/mkdtemp.o
 endif
+ifdef MKDIR_WO_TRAILING_SLASH
+       COMPAT_CFLAGS += -DMKDIR_WO_TRAILING_SLASH
+       COMPAT_OBJS += compat/mkdir.o
+endif
 ifdef NO_MKSTEMPS
        COMPAT_CFLAGS += -DNO_MKSTEMPS
 endif
@@ -1671,6 +1757,13 @@ endif
 ifdef OBJECT_CREATION_USES_RENAMES
        COMPAT_CFLAGS += -DOBJECT_CREATION_MODE=1
 endif
+ifdef NO_STRUCT_ITIMERVAL
+       COMPAT_CFLAGS += -DNO_STRUCT_ITIMERVAL
+       NO_SETITIMER=YesPlease
+endif
+ifdef NO_SETITIMER
+       COMPAT_CFLAGS += -DNO_SETITIMER
+endif
 ifdef NO_PREAD
        COMPAT_CFLAGS += -DNO_PREAD
        COMPAT_OBJS += compat/pread.o
@@ -1688,6 +1781,9 @@ endif
 ifdef NO_IPV6
        BASIC_CFLAGS += -DNO_IPV6
 endif
+ifdef NO_INTPTR_T
+       COMPAT_CFLAGS += -DNO_INTPTR_T
+endif
 ifdef NO_UINTMAX_T
        BASIC_CFLAGS += -Duintmax_t=uint32_t
 endif
@@ -2540,6 +2636,7 @@ bin-wrappers/%: wrap-for-bin.sh
 # with that.
 
 export NO_SVN_TESTS
+export TEST_NO_MALLOC_CHECK
 
 ### Testing rules
 
index b1456c3..ca734fb 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/1.7.12.4.txt
\ No newline at end of file
+Documentation/RelNotes/1.8.0.1.txt
\ No newline at end of file
index f04ac18..05f2d79 100644 (file)
--- a/abspath.c
+++ b/abspath.c
@@ -35,6 +35,9 @@ const char *real_path(const char *path)
        if (path == buf || path == next_buf)
                return path;
 
+       if (!*path)
+               die("The empty string is not a valid path");
+
        if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
                die ("Too long path: %.*s", 60, path);
 
@@ -42,8 +45,8 @@ const char *real_path(const char *path)
                if (!is_directory(buf)) {
                        char *last_slash = find_last_dir_sep(buf);
                        if (last_slash) {
-                               *last_slash = '\0';
                                last_elem = xstrdup(last_slash + 1);
+                               last_slash[1] = '\0';
                        } else {
                                last_elem = xstrdup(buf);
                                *buf = '\0';
@@ -123,7 +126,9 @@ const char *absolute_path(const char *path)
 {
        static char buf[PATH_MAX + 1];
 
-       if (is_absolute_path(path)) {
+       if (!*path) {
+               die("The empty string is not a valid path");
+       } else if (is_absolute_path(path)) {
                if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
                        die("Too long path: %.*s", 60, path);
        } else {
index f5af81f..55f66b4 100644 (file)
@@ -4,6 +4,7 @@
 #include "cache.h"
 #include "archive.h"
 #include "streaming.h"
+#include "utf8.h"
 
 static int zip_date;
 static int zip_time;
@@ -16,7 +17,8 @@ static unsigned int zip_dir_offset;
 static unsigned int zip_dir_entries;
 
 #define ZIP_DIRECTORY_MIN_SIZE (1024 * 1024)
-#define ZIP_STREAM (8)
+#define ZIP_STREAM     (1 <<  3)
+#define ZIP_UTF8       (1 << 11)
 
 struct zip_local_header {
        unsigned char magic[4];
@@ -74,6 +76,14 @@ struct zip_dir_trailer {
        unsigned char _end[1];
 };
 
+struct zip_extra_mtime {
+       unsigned char magic[2];
+       unsigned char extra_size[2];
+       unsigned char flags[1];
+       unsigned char mtime[4];
+       unsigned char _end[1];
+};
+
 /*
  * On ARM, padding is added at the end of the struct, so a simple
  * sizeof(struct ...) reports two bytes more than the payload size
@@ -83,6 +93,9 @@ struct zip_dir_trailer {
 #define ZIP_DATA_DESC_SIZE     offsetof(struct zip_data_desc, _end)
 #define ZIP_DIR_HEADER_SIZE    offsetof(struct zip_dir_header, _end)
 #define ZIP_DIR_TRAILER_SIZE   offsetof(struct zip_dir_trailer, _end)
+#define ZIP_EXTRA_MTIME_SIZE   offsetof(struct zip_extra_mtime, _end)
+#define ZIP_EXTRA_MTIME_PAYLOAD_SIZE \
+       (ZIP_EXTRA_MTIME_SIZE - offsetof(struct zip_extra_mtime, flags))
 
 static void copy_le16(unsigned char *dest, unsigned int n)
 {
@@ -164,6 +177,17 @@ static void set_zip_header_data_desc(struct zip_local_header *header,
        copy_le32(header->size, size);
 }
 
+static int has_only_ascii(const char *s)
+{
+       for (;;) {
+               int c = *s++;
+               if (c == '\0')
+                       return 1;
+               if (!isascii(c))
+                       return 0;
+       }
+}
+
 #define STREAM_BUFFER_SIZE (1024 * 16)
 
 static int write_zip_entry(struct archiver_args *args,
@@ -173,6 +197,7 @@ static int write_zip_entry(struct archiver_args *args,
 {
        struct zip_local_header header;
        struct zip_dir_header dirent;
+       struct zip_extra_mtime extra;
        unsigned long attr2;
        unsigned long compressed_size;
        unsigned long crc;
@@ -187,6 +212,13 @@ static int write_zip_entry(struct archiver_args *args,
 
        crc = crc32(0, NULL, 0);
 
+       if (!has_only_ascii(path)) {
+               if (is_utf8(path))
+                       flags |= ZIP_UTF8;
+               else
+                       warning("Path is not valid UTF-8: %s", path);
+       }
+
        if (pathlen > 0xffff) {
                return error("path too long (%d chars, SHA1: %s): %s",
                                (int)pathlen, sha1_to_hex(sha1), path);
@@ -246,8 +278,13 @@ static int write_zip_entry(struct archiver_args *args,
                }
        }
 
+       copy_le16(extra.magic, 0x5455);
+       copy_le16(extra.extra_size, ZIP_EXTRA_MTIME_PAYLOAD_SIZE);
+       extra.flags[0] = 1;     /* just mtime */
+       copy_le32(extra.mtime, args->time);
+
        /* make sure we have enough free space in the dictionary */
-       direntsize = ZIP_DIR_HEADER_SIZE + pathlen;
+       direntsize = ZIP_DIR_HEADER_SIZE + pathlen + ZIP_EXTRA_MTIME_SIZE;
        while (zip_dir_size < zip_dir_offset + direntsize) {
                zip_dir_size += ZIP_DIRECTORY_MIN_SIZE;
                zip_dir = xrealloc(zip_dir, zip_dir_size);
@@ -263,7 +300,7 @@ static int write_zip_entry(struct archiver_args *args,
        copy_le16(dirent.mdate, zip_date);
        set_zip_dir_data_desc(&dirent, size, compressed_size, crc);
        copy_le16(dirent.filename_length, pathlen);
-       copy_le16(dirent.extra_length, 0);
+       copy_le16(dirent.extra_length, ZIP_EXTRA_MTIME_SIZE);
        copy_le16(dirent.comment_length, 0);
        copy_le16(dirent.disk, 0);
        copy_le16(dirent.attr1, 0);
@@ -281,11 +318,13 @@ static int write_zip_entry(struct archiver_args *args,
        else
                set_zip_header_data_desc(&header, size, compressed_size, crc);
        copy_le16(header.filename_length, pathlen);
-       copy_le16(header.extra_length, 0);
+       copy_le16(header.extra_length, ZIP_EXTRA_MTIME_SIZE);
        write_or_die(1, &header, ZIP_LOCAL_HEADER_SIZE);
        zip_offset += ZIP_LOCAL_HEADER_SIZE;
        write_or_die(1, path, pathlen);
        zip_offset += pathlen;
+       write_or_die(1, &extra, ZIP_EXTRA_MTIME_SIZE);
+       zip_offset += ZIP_EXTRA_MTIME_SIZE;
        if (stream && method == 0) {
                unsigned char buf[STREAM_BUFFER_SIZE];
                ssize_t readlen;
@@ -382,6 +421,8 @@ static int write_zip_entry(struct archiver_args *args,
        zip_dir_offset += ZIP_DIR_HEADER_SIZE;
        memcpy(zip_dir + zip_dir_offset, path, pathlen);
        zip_dir_offset += pathlen;
+       memcpy(zip_dir + zip_dir_offset, &extra, ZIP_EXTRA_MTIME_SIZE);
+       zip_dir_offset += ZIP_EXTRA_MTIME_SIZE;
        zip_dir_entries++;
 
        return 0;
index a484433..4666404 100644 (file)
--- a/archive.c
+++ b/archive.c
@@ -7,10 +7,10 @@
 #include "unpack-trees.h"
 
 static char const * const archive_usage[] = {
-       "git archive [options] <tree-ish> [<path>...]",
-       "git archive --list",
-       "git archive --remote <repo> [--exec <cmd>] [options] <tree-ish> [<path>...]",
-       "git archive --remote <repo> [--exec <cmd>] --list",
+       N_("git archive [options] <tree-ish> [<path>...]"),
+       N_("git archive --list"),
+       N_("git archive --remote <repo> [--exec <cmd>] [options] <tree-ish> [<path>...]"),
+       N_("git archive --remote <repo> [--exec <cmd>] --list"),
        NULL
 };
 
@@ -319,16 +319,16 @@ static int parse_archive_args(int argc, const char **argv,
        int worktree_attributes = 0;
        struct option opts[] = {
                OPT_GROUP(""),
-               OPT_STRING(0, "format", &format, "fmt", "archive format"),
-               OPT_STRING(0, "prefix", &base, "prefix",
-                       "prepend prefix to each pathname in the archive"),
-               OPT_STRING('o', "output", &output, "file",
-                       "write the archive to this file"),
+               OPT_STRING(0, "format", &format, N_("fmt"), N_("archive format")),
+               OPT_STRING(0, "prefix", &base, N_("prefix"),
+                       N_("prepend prefix to each pathname in the archive")),
+               OPT_STRING('o', "output", &output, N_("file"),
+                       N_("write the archive to this file")),
                OPT_BOOL(0, "worktree-attributes", &worktree_attributes,
-                       "read .gitattributes in working directory"),
-               OPT__VERBOSE(&verbose, "report archived files on stderr"),
-               OPT__COMPR('0', &compression_level, "store only", 0),
-               OPT__COMPR('1', &compression_level, "compress faster", 1),
+                       N_("read .gitattributes in working directory")),
+               OPT__VERBOSE(&verbose, N_("report archived files on stderr")),
+               OPT__COMPR('0', &compression_level, N_("store only"), 0),
+               OPT__COMPR('1', &compression_level, N_("compress faster"), 1),
                OPT__COMPR_HIDDEN('2', &compression_level, 2),
                OPT__COMPR_HIDDEN('3', &compression_level, 3),
                OPT__COMPR_HIDDEN('4', &compression_level, 4),
@@ -336,15 +336,15 @@ static int parse_archive_args(int argc, const char **argv,
                OPT__COMPR_HIDDEN('6', &compression_level, 6),
                OPT__COMPR_HIDDEN('7', &compression_level, 7),
                OPT__COMPR_HIDDEN('8', &compression_level, 8),
-               OPT__COMPR('9', &compression_level, "compress better", 9),
+               OPT__COMPR('9', &compression_level, N_("compress better"), 9),
                OPT_GROUP(""),
                OPT_BOOL('l', "list", &list,
-                       "list supported archive formats"),
+                       N_("list supported archive formats")),
                OPT_GROUP(""),
-               OPT_STRING(0, "remote", &remote, "repo",
-                       "retrieve the archive from remote repository <repo>"),
-               OPT_STRING(0, "exec", &exec, "cmd",
-                       "path to the remote git-upload-archive command"),
+               OPT_STRING(0, "remote", &remote, N_("repo"),
+                       N_("retrieve the archive from remote repository <repo>")),
+               OPT_STRING(0, "exec", &exec, N_("command"),
+                       N_("path to the remote git-upload-archive command")),
                OPT_END()
        };
 
index 48acf73..1aad49b 100644 (file)
--- a/bisect.c
+++ b/bisect.c
@@ -833,7 +833,7 @@ static int check_ancestors(const char *prefix)
  */
 static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout)
 {
-       char *filename = xstrdup(git_path("BISECT_ANCESTORS_OK"));
+       char *filename = git_pathdup("BISECT_ANCESTORS_OK");
        struct stat st;
        int fd;
 
index 8e37752..95116b8 100644 (file)
--- a/builtin.h
+++ b/builtin.h
@@ -21,7 +21,6 @@ struct fmt_merge_msg_opts {
 
 extern int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
                         struct fmt_merge_msg_opts *);
-extern void commit_notes(struct notes_tree *t, const char *msg);
 
 struct notes_rewrite_cfg {
        struct notes_tree **trees;
@@ -33,7 +32,6 @@ struct notes_rewrite_cfg {
        int mode_from_env;
 };
 
-combine_notes_fn parse_combine_notes_fn(const char *v);
 struct notes_rewrite_cfg *init_copy_notes_for_rewrite(const char *cmd);
 int copy_note_for_rewrite(struct notes_rewrite_cfg *c,
                          const unsigned char *from_obj, const unsigned char *to_obj);
index 89dce56..e664100 100644 (file)
@@ -16,7 +16,7 @@
 #include "bulk-checkin.h"
 
 static const char * const builtin_add_usage[] = {
-       "git add [options] [--] <filepattern>...",
+       N_("git add [options] [--] <filepattern>..."),
        NULL
 };
 static int patch_interactive, add_interactive, edit_interactive;
@@ -260,7 +260,7 @@ int interactive_add(int argc, const char **argv, const char *prefix, int patch)
 
 static int edit_patch(int argc, const char **argv, const char *prefix)
 {
-       char *file = xstrdup(git_path("ADD_EDIT.patch"));
+       char *file = git_pathdup("ADD_EDIT.patch");
        const char *apply_argv[] = { "apply", "--recount", "--cached",
                NULL, NULL };
        struct child_process child;
@@ -303,6 +303,7 @@ static int edit_patch(int argc, const char **argv, const char *prefix)
                die (_("Could not apply '%s'"), file);
 
        unlink(file);
+       free(file);
        return 0;
 }
 
@@ -315,19 +316,19 @@ static int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0;
 static int ignore_add_errors, addremove, intent_to_add, ignore_missing = 0;
 
 static struct option builtin_add_options[] = {
-       OPT__DRY_RUN(&show_only, "dry run"),
-       OPT__VERBOSE(&verbose, "be verbose"),
+       OPT__DRY_RUN(&show_only, N_("dry run")),
+       OPT__VERBOSE(&verbose, N_("be verbose")),
        OPT_GROUP(""),
-       OPT_BOOLEAN('i', "interactive", &add_interactive, "interactive picking"),
-       OPT_BOOLEAN('p', "patch", &patch_interactive, "select hunks interactively"),
-       OPT_BOOLEAN('e', "edit", &edit_interactive, "edit current diff and apply"),
-       OPT__FORCE(&ignored_too, "allow adding otherwise ignored files"),
-       OPT_BOOLEAN('u', "update", &take_worktree_changes, "update tracked files"),
-       OPT_BOOLEAN('N', "intent-to-add", &intent_to_add, "record only the fact that the path will be added later"),
-       OPT_BOOLEAN('A', "all", &addremove, "add changes from all tracked and untracked files"),
-       OPT_BOOLEAN( 0 , "refresh", &refresh_only, "don't add, only refresh the index"),
-       OPT_BOOLEAN( 0 , "ignore-errors", &ignore_add_errors, "just skip files which cannot be added because of errors"),
-       OPT_BOOLEAN( 0 , "ignore-missing", &ignore_missing, "check if - even missing - files are ignored in dry run"),
+       OPT_BOOLEAN('i', "interactive", &add_interactive, N_("interactive picking")),
+       OPT_BOOLEAN('p', "patch", &patch_interactive, N_("select hunks interactively")),
+       OPT_BOOLEAN('e', "edit", &edit_interactive, N_("edit current diff and apply")),
+       OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files")),
+       OPT_BOOLEAN('u', "update", &take_worktree_changes, N_("update tracked files")),
+       OPT_BOOLEAN('N', "intent-to-add", &intent_to_add, N_("record only the fact that the path will be added later")),
+       OPT_BOOLEAN('A', "all", &addremove, N_("add changes from all tracked and untracked files")),
+       OPT_BOOLEAN( 0 , "refresh", &refresh_only, N_("don't add, only refresh the index")),
+       OPT_BOOLEAN( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
+       OPT_BOOLEAN( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
        OPT_END(),
 };
 
index ca8695a..156b3ce 100644 (file)
@@ -4314,7 +4314,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix_)
                OPT_NOOP_NOARG(0, "allow-binary-replacement"),
                OPT_NOOP_NOARG(0, "binary"),
                OPT_BOOLEAN(0, "numstat", &numstat,
-                       N_("shows number of added and deleted lines in decimal notation")),
+                       N_("show number of added and deleted lines in decimal notation")),
                OPT_BOOLEAN(0, "summary", &summary,
                        N_("instead of applying the patch, output a summary for the input")),
                OPT_BOOLEAN(0, "check", &check,
index 931956d..9a1cfd3 100644 (file)
@@ -88,12 +88,12 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
        const char *output = NULL;
        const char *remote = NULL;
        struct option local_opts[] = {
-               OPT_STRING('o', "output", &output, "file",
-                       "write the archive to this file"),
-               OPT_STRING(0, "remote", &remote, "repo",
-                       "retrieve the archive from remote repository <repo>"),
-               OPT_STRING(0, "exec", &exec, "cmd",
-                       "path to the remote git-upload-archive command"),
+               OPT_STRING('o', "output", &output, N_("file"),
+                       N_("write the archive to this file")),
+               OPT_STRING(0, "remote", &remote, N_("repo"),
+                       N_("retrieve the archive from remote repository <repo>")),
+               OPT_STRING(0, "exec", &exec, N_("command"),
+                       N_("path to the remote git-upload-archive command")),
                OPT_END()
        };
 
index 8d325a5..e3884e3 100644 (file)
@@ -4,7 +4,7 @@
 #include "bisect.h"
 
 static const char * const git_bisect_helper_usage[] = {
-       "git bisect--helper --next-all [--no-checkout]",
+       N_("git bisect--helper --next-all [--no-checkout]"),
        NULL
 };
 
@@ -14,9 +14,9 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
        int no_checkout = 0;
        struct option options[] = {
                OPT_BOOLEAN(0, "next-all", &next_all,
-                           "perform 'git bisect next'"),
+                           N_("perform 'git bisect next'")),
                OPT_BOOLEAN(0, "no-checkout", &no_checkout,
-                           "update BISECT_HEAD instead of checking out the current commit"),
+                           N_("update BISECT_HEAD instead of checking out the current commit")),
                OPT_END()
        };
 
index 409eb42..c27ef21 100644 (file)
 #include "utf8.h"
 #include "userdiff.h"
 
-static char blame_usage[] = "git blame [options] [rev-opts] [rev] [--] file";
+static char blame_usage[] = N_("git blame [options] [rev-opts] [rev] [--] file");
 
 static const char *blame_opt_usage[] = {
        blame_usage,
        "",
-       "[rev-opts] are documented in git-rev-list(1)",
+       N_("[rev-opts] are documented in git-rev-list(1)"),
        NULL
 };
 
@@ -2370,27 +2370,27 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
        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(0, "line-porcelain", &output_option, "Show porcelain format with per-line commit information", OUTPUT_PORCELAIN|OUTPUT_LINE_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('e', "show-email", &output_option, "Show author email instead of name (Default: off)", OUTPUT_SHOW_EMAIL),
-               OPT_BIT('w', NULL, &xdl_opts, "Ignore whitespace differences", XDF_IGNORE_WHITESPACE),
-               OPT_BIT(0, "minimal", &xdl_opts, "Spend extra cycles to find better match", XDF_NEED_MINIMAL),
-               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_BOOLEAN(0, "incremental", &incremental, N_("Show blame entries as we find them, incrementally")),
+               OPT_BOOLEAN('b', NULL, &blank_boundary, N_("Show blank SHA-1 for boundary commits (Default: off)")),
+               OPT_BOOLEAN(0, "root", &show_root, N_("Do not treat root commits as boundaries (Default: off)")),
+               OPT_BOOLEAN(0, "show-stats", &show_stats, N_("Show work cost statistics")),
+               OPT_BIT(0, "score-debug", &output_option, N_("Show output score for blame entries"), OUTPUT_SHOW_SCORE),
+               OPT_BIT('f', "show-name", &output_option, N_("Show original filename (Default: auto)"), OUTPUT_SHOW_NAME),
+               OPT_BIT('n', "show-number", &output_option, N_("Show original linenumber (Default: off)"), OUTPUT_SHOW_NUMBER),
+               OPT_BIT('p', "porcelain", &output_option, N_("Show in a format designed for machine consumption"), OUTPUT_PORCELAIN),
+               OPT_BIT(0, "line-porcelain", &output_option, N_("Show porcelain format with per-line commit information"), OUTPUT_PORCELAIN|OUTPUT_LINE_PORCELAIN),
+               OPT_BIT('c', NULL, &output_option, N_("Use the same output mode as git-annotate (Default: off)"), OUTPUT_ANNOTATE_COMPAT),
+               OPT_BIT('t', NULL, &output_option, N_("Show raw timestamp (Default: off)"), OUTPUT_RAW_TIMESTAMP),
+               OPT_BIT('l', NULL, &output_option, N_("Show long commit SHA1 (Default: off)"), OUTPUT_LONG_OBJECT_NAME),
+               OPT_BIT('s', NULL, &output_option, N_("Suppress author name and timestamp (Default: off)"), OUTPUT_NO_AUTHOR),
+               OPT_BIT('e', "show-email", &output_option, N_("Show author email instead of name (Default: off)"), OUTPUT_SHOW_EMAIL),
+               OPT_BIT('w', NULL, &xdl_opts, N_("Ignore whitespace differences"), XDF_IGNORE_WHITESPACE),
+               OPT_BIT(0, "minimal", &xdl_opts, N_("Spend extra cycles to find better match"), XDF_NEED_MINIMAL),
+               OPT_STRING('S', NULL, &revs_file, N_("file"), N_("Use revisions from <file> instead of calling git-rev-list")),
+               OPT_STRING(0, "contents", &contents_from, N_("file"), N_("Use <file>'s contents as the final image")),
+               { OPTION_CALLBACK, 'C', NULL, &opt, N_("score"), N_("Find line copies within and across files"), PARSE_OPT_OPTARG, blame_copy_callback },
+               { OPTION_CALLBACK, 'M', NULL, &opt, N_("score"), N_("Find line movements within and across files"), PARSE_OPT_OPTARG, blame_move_callback },
+               OPT_CALLBACK('L', NULL, &bottomtop, N_("n,m"), N_("Process only line range n,m, counting from 1"), blame_bottomtop_callback),
                OPT__ABBREV(&abbrev),
                OPT_END()
        };
index 0e060f2..1ec9c02 100644 (file)
 #include "revision.h"
 #include "string-list.h"
 #include "column.h"
+#include "utf8.h"
 
 static const char * const builtin_branch_usage[] = {
-       "git branch [options] [-r | -a] [--merged | --no-merged]",
-       "git branch [options] [-l] [-f] <branchname> [<start-point>]",
-       "git branch [options] [-r] (-d | -D) <branchname>...",
-       "git branch [options] (-m | -M) [<oldbranch>] <newbranch>",
+       N_("git branch [options] [-r | -a] [--merged | --no-merged]"),
+       N_("git branch [options] [-l] [-f] <branchname> [<start-point>]"),
+       N_("git branch [options] [-r] (-d | -D) <branchname>..."),
+       N_("git branch [options] (-m | -M) [<oldbranch>] <newbranch>"),
        NULL
 };
 
@@ -129,7 +130,7 @@ static int branch_merged(int kind, const char *name,
        if (!reference_rev)
                reference_rev = head_rev;
 
-       merged = in_merge_bases(rev, &reference_rev, 1);
+       merged = in_merge_bases(rev, reference_rev);
 
        /*
         * After the safety valve is fully redefined to "check with
@@ -139,7 +140,7 @@ static int branch_merged(int kind, const char *name,
         * a gentle reminder is in order.
         */
        if ((head_rev != reference_rev) &&
-           in_merge_bases(rev, &head_rev, 1) != merged) {
+           in_merge_bases(rev, head_rev) != merged) {
                if (merged)
                        warning(_("deleting branch '%s' that has been merged to\n"
                                "         '%s', but not yet merged to HEAD."),
@@ -153,10 +154,37 @@ static int branch_merged(int kind, const char *name,
        return merged;
 }
 
+static int check_branch_commit(const char *branchname, const char *refname,
+                              unsigned char *sha1, struct commit *head_rev,
+                              int kinds, int force)
+{
+       struct commit *rev = lookup_commit_reference(sha1);
+       if (!rev) {
+               error(_("Couldn't look up commit object for '%s'"), refname);
+               return -1;
+       }
+       if (!force && !branch_merged(kinds, branchname, rev, head_rev)) {
+               error(_("The branch '%s' is not fully merged.\n"
+                     "If you are sure you want to delete it, "
+                     "run 'git branch -D %s'."), branchname, branchname);
+               return -1;
+       }
+       return 0;
+}
+
+static void delete_branch_config(const char *branchname)
+{
+       struct strbuf buf = STRBUF_INIT;
+       strbuf_addf(&buf, "branch.%s", branchname);
+       if (git_config_rename_section(buf.buf, NULL) < 0)
+               warning(_("Update of config-file failed"));
+       strbuf_release(&buf);
+}
+
 static int delete_branches(int argc, const char **argv, int force, int kinds,
                           int quiet)
 {
-       struct commit *rev, *head_rev = NULL;
+       struct commit *head_rev = NULL;
        unsigned char sha1[20];
        char *name = NULL;
        const char *fmt;
@@ -186,6 +214,9 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
                        die(_("Couldn't look up commit object for HEAD"));
        }
        for (i = 0; i < argc; i++, strbuf_release(&bname)) {
+               const char *target;
+               int flags = 0;
+
                strbuf_branchname(&bname, argv[i]);
                if (kinds == REF_LOCAL_BRANCH && !strcmp(head, bname.buf)) {
                        error(_("Cannot delete the branch '%s' "
@@ -196,8 +227,10 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
 
                free(name);
 
-               name = xstrdup(mkpath(fmt, bname.buf));
-               if (read_ref(name, sha1)) {
+               name = mkpathdup(fmt, bname.buf);
+               target = resolve_ref_unsafe(name, sha1, 0, &flags);
+               if (!target ||
+                   (!(flags & REF_ISSYMREF) && is_null_sha1(sha1))) {
                        error(remote_branch
                              ? _("remote branch '%s' not found.")
                              : _("branch '%s' not found."), bname.buf);
@@ -205,40 +238,31 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
                        continue;
                }
 
-               rev = lookup_commit_reference(sha1);
-               if (!rev) {
-                       error(_("Couldn't look up commit object for '%s'"), name);
-                       ret = 1;
-                       continue;
-               }
-
-               if (!force && !branch_merged(kinds, bname.buf, rev, head_rev)) {
-                       error(_("The branch '%s' is not fully merged.\n"
-                             "If you are sure you want to delete it, "
-                             "run 'git branch -D %s'."), bname.buf, bname.buf);
+               if (!(flags & REF_ISSYMREF) &&
+                   check_branch_commit(bname.buf, name, sha1, head_rev, kinds,
+                                       force)) {
                        ret = 1;
                        continue;
                }
 
-               if (delete_ref(name, sha1, 0)) {
+               if (delete_ref(name, sha1, REF_NODEREF)) {
                        error(remote_branch
                              ? _("Error deleting remote branch '%s'")
                              : _("Error deleting branch '%s'"),
                              bname.buf);
                        ret = 1;
-               } else {
-                       struct strbuf buf = STRBUF_INIT;
-                       if (!quiet)
-                               printf(remote_branch
-                                      ? _("Deleted remote branch %s (was %s).\n")
-                                      : _("Deleted branch %s (was %s).\n"),
-                                      bname.buf,
-                                      find_unique_abbrev(sha1, DEFAULT_ABBREV));
-                       strbuf_addf(&buf, "branch.%s", bname.buf);
-                       if (git_config_rename_section(buf.buf, NULL) < 0)
-                               warning(_("Update of config-file failed"));
-                       strbuf_release(&buf);
+                       continue;
+               }
+               if (!quiet) {
+                       printf(remote_branch
+                              ? _("Deleted remote branch %s (was %s).\n")
+                              : _("Deleted branch %s (was %s).\n"),
+                              bname.buf,
+                              (flags & REF_ISSYMREF)
+                              ? target
+                              : find_unique_abbrev(sha1, DEFAULT_ABBREV));
                }
+               delete_branch_config(bname.buf);
        }
 
        free(name);
@@ -249,7 +273,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
 struct ref_item {
        char *name;
        char *dest;
-       unsigned int kind, len;
+       unsigned int kind, width;
        struct commit *commit;
 };
 
@@ -354,14 +378,14 @@ static int append_ref(const char *refname, const unsigned char *sha1, int flags,
        newitem->name = xstrdup(refname);
        newitem->kind = kind;
        newitem->commit = commit;
-       newitem->len = strlen(refname);
+       newitem->width = utf8_strwidth(refname);
        newitem->dest = resolve_symref(orig_refname, prefix);
        /* adjust for "remotes/" */
        if (newitem->kind == REF_REMOTE_BRANCH &&
            ref_list->kinds != REF_REMOTE_BRANCH)
-               newitem->len += 8;
-       if (newitem->len > ref_list->maxwidth)
-               ref_list->maxwidth = newitem->len;
+               newitem->width += 8;
+       if (newitem->width > ref_list->maxwidth)
+               ref_list->maxwidth = newitem->width;
 
        return 0;
 }
@@ -490,11 +514,12 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
        }
 
        strbuf_addf(&name, "%s%s", prefix, item->name);
-       if (verbose)
+       if (verbose) {
+               int utf8_compensation = strlen(name.buf) - utf8_strwidth(name.buf);
                strbuf_addf(&out, "%c %s%-*s%s", c, branch_get_color(color),
-                           maxwidth, name.buf,
+                           maxwidth + utf8_compensation, name.buf,
                            branch_get_color(BRANCH_COLOR_RESET));
-       else
+       else
                strbuf_addf(&out, "%c %s%s%s", c, branch_get_color(color),
                            name.buf, branch_get_color(BRANCH_COLOR_RESET));
 
@@ -519,8 +544,8 @@ static int calc_maxwidth(struct ref_list *refs)
        for (i = 0; i < refs->index; i++) {
                if (!matches_merge_filter(refs->list[i].commit))
                        continue;
-               if (refs->list[i].len > w)
-                       w = refs->list[i].len;
+               if (refs->list[i].width > w)
+                       w = refs->list[i].width;
        }
        return w;
 }
@@ -533,12 +558,12 @@ static void show_detached(struct ref_list *ref_list)
        if (head_commit && is_descendant_of(head_commit, ref_list->with_commit)) {
                struct ref_item item;
                item.name = xstrdup(_("(no branch)"));
-               item.len = strlen(item.name);
+               item.width = utf8_strwidth(item.name);
                item.kind = REF_LOCAL_BRANCH;
                item.dest = NULL;
                item.commit = head_commit;
-               if (item.len > ref_list->maxwidth)
-                       ref_list->maxwidth = item.len;
+               if (item.width > ref_list->maxwidth)
+                       ref_list->maxwidth = item.width;
                print_ref_item(&item, ref_list->maxwidth, ref_list->verbose, ref_list->abbrev, 1, "");
                free(item.name);
        }
@@ -712,62 +737,65 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
        int delete = 0, rename = 0, force_create = 0, list = 0;
        int verbose = 0, abbrev = -1, detached = 0;
        int reflog = 0, edit_description = 0;
-       int quiet = 0;
+       int quiet = 0, unset_upstream = 0;
+       const char *new_upstream = NULL;
        enum branch_track track;
        int kinds = REF_LOCAL_BRANCH;
        struct commit_list *with_commit = NULL;
 
        struct option options[] = {
-               OPT_GROUP("Generic options"),
+               OPT_GROUP(N_("Generic options")),
                OPT__VERBOSE(&verbose,
-                       "show hash and subject, give twice for upstream branch"),
-               OPT__QUIET(&quiet, "suppress informational messages"),
-               OPT_SET_INT('t', "track",  &track, "set up tracking mode (see git-pull(1))",
+                       N_("show hash and subject, give twice for upstream branch")),
+               OPT__QUIET(&quiet, N_("suppress informational messages")),
+               OPT_SET_INT('t', "track",  &track, N_("set up tracking mode (see git-pull(1))"),
                        BRANCH_TRACK_EXPLICIT),
-               OPT_SET_INT( 0, "set-upstream",  &track, "change upstream info",
+               OPT_SET_INT( 0, "set-upstream",  &track, N_("change upstream info"),
                        BRANCH_TRACK_OVERRIDE),
-               OPT__COLOR(&branch_use_color, "use colored output"),
-               OPT_SET_INT('r', "remotes",     &kinds, "act on remote-tracking branches",
+               OPT_STRING('u', "set-upstream-to", &new_upstream, "upstream", "change the upstream info"),
+               OPT_BOOLEAN(0, "unset-upstream", &unset_upstream, "Unset the upstream info"),
+               OPT__COLOR(&branch_use_color, N_("use colored output")),
+               OPT_SET_INT('r', "remotes",     &kinds, N_("act on remote-tracking branches"),
                        REF_REMOTE_BRANCH),
                {
-                       OPTION_CALLBACK, 0, "contains", &with_commit, "commit",
-                       "print only branches that contain the commit",
+                       OPTION_CALLBACK, 0, "contains", &with_commit, N_("commit"),
+                       N_("print only branches that contain the commit"),
                        PARSE_OPT_LASTARG_DEFAULT,
                        parse_opt_with_commit, (intptr_t)"HEAD",
                },
                {
-                       OPTION_CALLBACK, 0, "with", &with_commit, "commit",
-                       "print only branches that contain the commit",
+                       OPTION_CALLBACK, 0, "with", &with_commit, N_("commit"),
+                       N_("print only branches that contain the commit"),
                        PARSE_OPT_HIDDEN | PARSE_OPT_LASTARG_DEFAULT,
                        parse_opt_with_commit, (intptr_t) "HEAD",
                },
                OPT__ABBREV(&abbrev),
 
-               OPT_GROUP("Specific git-branch actions:"),
-               OPT_SET_INT('a', "all", &kinds, "list both remote-tracking and local branches",
+               OPT_GROUP(N_("Specific git-branch actions:")),
+               OPT_SET_INT('a', "all", &kinds, N_("list both remote-tracking and local branches"),
                        REF_REMOTE_BRANCH | REF_LOCAL_BRANCH),
-               OPT_BIT('d', "delete", &delete, "delete fully merged branch", 1),
-               OPT_BIT('D', NULL, &delete, "delete branch (even if not merged)", 2),
-               OPT_BIT('m', "move", &rename, "move/rename a branch and its reflog", 1),
-               OPT_BIT('M', NULL, &rename, "move/rename a branch, even if target exists", 2),
-               OPT_BOOLEAN(0, "list", &list, "list branch names"),
-               OPT_BOOLEAN('l', "create-reflog", &reflog, "create the branch's reflog"),
+               OPT_BIT('d', "delete", &delete, N_("delete fully merged branch"), 1),
+               OPT_BIT('D', NULL, &delete, N_("delete branch (even if not merged)"), 2),
+               OPT_BIT('m', "move", &rename, N_("move/rename a branch and its reflog"), 1),
+               OPT_BIT('M', NULL, &rename, N_("move/rename a branch, even if target exists"), 2),
+               OPT_BOOLEAN(0, "list", &list, N_("list branch names")),
+               OPT_BOOLEAN('l', "create-reflog", &reflog, N_("create the branch's reflog")),
                OPT_BOOLEAN(0, "edit-description", &edit_description,
-                           "edit the description for the branch"),
-               OPT__FORCE(&force_create, "force creation (when already exists)"),
+                           N_("edit the description for the branch")),
+               OPT__FORCE(&force_create, N_("force creation (when already exists)")),
                {
                        OPTION_CALLBACK, 0, "no-merged", &merge_filter_ref,
-                       "commit", "print only not merged branches",
+                       N_("commit"), N_("print only not merged branches"),
                        PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG,
                        opt_parse_merge_filter, (intptr_t) "HEAD",
                },
                {
                        OPTION_CALLBACK, 0, "merged", &merge_filter_ref,
-                       "commit", "print only merged branches",
+                       N_("commit"), N_("print only merged branches"),
                        PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG,
                        opt_parse_merge_filter, (intptr_t) "HEAD",
                },
-               OPT_COLUMN(0, "column", &colopts, "list branches in columns"),
+               OPT_COLUMN(0, "column", &colopts, N_("list branches in columns")),
                OPT_END(),
        };
 
@@ -794,10 +822,10 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
        argc = parse_options(argc, argv, prefix, options, builtin_branch_usage,
                             0);
 
-       if (!delete && !rename && !edit_description && argc == 0)
+       if (!delete && !rename && !edit_description && !new_upstream && !unset_upstream && argc == 0)
                list = 1;
 
-       if (!!delete + !!rename + !!force_create + !!list > 1)
+       if (!!delete + !!rename + !!force_create + !!list + !!new_upstream + !!unset_upstream > 1)
                usage_with_options(builtin_branch_usage, options);
 
        if (abbrev == -1)
@@ -852,11 +880,62 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
                        rename_branch(argv[0], argv[1], rename > 1);
                else
                        usage_with_options(builtin_branch_usage, options);
+       } else if (new_upstream) {
+               struct branch *branch = branch_get(argv[0]);
+
+               if (!ref_exists(branch->refname))
+                       die(_("branch '%s' does not exist"), branch->name);
+
+               /*
+                * create_branch takes care of setting up the tracking
+                * info and making sure new_upstream is correct
+                */
+               create_branch(head, branch->name, new_upstream, 0, 0, 0, quiet, BRANCH_TRACK_OVERRIDE);
+       } else if (unset_upstream) {
+               struct branch *branch = branch_get(argv[0]);
+               struct strbuf buf = STRBUF_INIT;
+
+               if (!branch_has_merge_config(branch)) {
+                       die(_("Branch '%s' has no upstream information"), branch->name);
+               }
+
+               strbuf_addf(&buf, "branch.%s.remote", branch->name);
+               git_config_set_multivar(buf.buf, NULL, NULL, 1);
+               strbuf_reset(&buf);
+               strbuf_addf(&buf, "branch.%s.merge", branch->name);
+               git_config_set_multivar(buf.buf, NULL, NULL, 1);
+               strbuf_release(&buf);
        } else if (argc > 0 && argc <= 2) {
+               struct branch *branch = branch_get(argv[0]);
+               int branch_existed = 0, remote_tracking = 0;
+               struct strbuf buf = STRBUF_INIT;
+
                if (kinds != REF_LOCAL_BRANCH)
                        die(_("-a and -r options to 'git branch' do not make sense with a branch name"));
+
+               if (track == BRANCH_TRACK_OVERRIDE)
+                       fprintf(stderr, _("The --set-upstream flag is deprecated and will be removed. Consider using --track or --set-upstream-to\n"));
+
+               strbuf_addf(&buf, "refs/remotes/%s", branch->name);
+               remote_tracking = ref_exists(buf.buf);
+               strbuf_release(&buf);
+
+               branch_existed = ref_exists(branch->refname);
                create_branch(head, argv[0], (argc == 2) ? argv[1] : head,
                              force_create, reflog, 0, quiet, track);
+
+               /*
+                * We only show the instructions if the user gave us
+                * one branch which doesn't exist locally, but is the
+                * name of a remote-tracking branch.
+                */
+               if (argc == 1 && track == BRANCH_TRACK_OVERRIDE &&
+                   !branch_existed && remote_tracking) {
+                       fprintf(stderr, _("\nIf you wanted to make '%s' track '%s', do this:\n\n"), head, branch->name);
+                       fprintf(stderr, _("    git branch -d %s\n"), branch->name);
+                       fprintf(stderr, _("    git branch --set-upstream-to %s\n"), branch->name);
+               }
+
        } else
                usage_with_options(builtin_branch_usage, options);
 
index 0eca2d7..00528dd 100644 (file)
@@ -244,8 +244,8 @@ static int batch_objects(int print_contents)
 }
 
 static const char * const cat_file_usage[] = {
-       "git cat-file (-t|-s|-e|-p|<type>|--textconv) <object>",
-       "git cat-file (--batch|--batch-check) < <list_of_objects>",
+       N_("git cat-file (-t|-s|-e|-p|<type>|--textconv) <object>"),
+       N_("git cat-file (--batch|--batch-check) < <list_of_objects>"),
        NULL
 };
 
@@ -263,19 +263,19 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
        const char *exp_type = NULL, *obj_name = NULL;
 
        const struct option options[] = {
-               OPT_GROUP("<type> can be one of: blob, tree, commit, tag"),
-               OPT_SET_INT('t', NULL, &opt, "show object type", 't'),
-               OPT_SET_INT('s', NULL, &opt, "show object size", 's'),
+               OPT_GROUP(N_("<type> can be one of: blob, tree, commit, tag")),
+               OPT_SET_INT('t', NULL, &opt, N_("show object type"), 't'),
+               OPT_SET_INT('s', NULL, &opt, N_("show object size"), 's'),
                OPT_SET_INT('e', NULL, &opt,
-                           "exit with zero when there's no error", 'e'),
-               OPT_SET_INT('p', NULL, &opt, "pretty-print object's content", 'p'),
+                           N_("exit with zero when there's no error"), 'e'),
+               OPT_SET_INT('p', NULL, &opt, N_("pretty-print object's content"), 'p'),
                OPT_SET_INT(0, "textconv", &opt,
-                           "for blob objects, run textconv on object's content", 'c'),
+                           N_("for blob objects, run textconv on object's content"), 'c'),
                OPT_SET_INT(0, "batch", &batch,
-                           "show info and content of objects fed from the standard input",
+                           N_("show info and content of objects fed from the standard input"),
                            BATCH),
                OPT_SET_INT(0, "batch-check", &batch,
-                           "show info about objects fed from the standard input",
+                           N_("show info about objects fed from the standard input"),
                            BATCH_CHECK),
                OPT_END()
        };
index 9000c2d..075d01d 100644 (file)
@@ -8,19 +8,19 @@ static int all_attrs;
 static int cached_attrs;
 static int stdin_paths;
 static const char * const check_attr_usage[] = {
-"git check-attr [-a | --all | attr...] [--] pathname...",
-"git check-attr --stdin [-z] [-a | --all | attr...] < <list-of-paths>",
+N_("git check-attr [-a | --all | attr...] [--] pathname..."),
+N_("git check-attr --stdin [-z] [-a | --all | attr...] < <list-of-paths>"),
 NULL
 };
 
 static int null_term_line;
 
 static const struct option check_attr_options[] = {
-       OPT_BOOLEAN('a', "all", &all_attrs, "report all attributes set on file"),
-       OPT_BOOLEAN(0,  "cached", &cached_attrs, "use .gitattributes only from the index"),
-       OPT_BOOLEAN(0 , "stdin", &stdin_paths, "read file names from stdin"),
+       OPT_BOOLEAN('a', "all", &all_attrs, N_("report all attributes set on file")),
+       OPT_BOOLEAN(0,  "cached", &cached_attrs, N_("use .gitattributes only from the index")),
+       OPT_BOOLEAN(0 , "stdin", &stdin_paths, N_("read file names from stdin")),
        OPT_BOOLEAN('z', NULL, &null_term_line,
-               "input paths are terminated by a null character"),
+               N_("input paths are terminated by a null character")),
        OPT_END()
 };
 
index c16d82b..b1feda7 100644 (file)
@@ -123,7 +123,7 @@ static void checkout_all(const char *prefix, int prefix_length)
 }
 
 static const char * const builtin_checkout_index_usage[] = {
-       "git checkout-index [options] [--] [<file>...]",
+       N_("git checkout-index [options] [--] [<file>...]"),
        NULL
 };
 
@@ -184,27 +184,27 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
        int force = 0, quiet = 0, not_new = 0;
        struct option builtin_checkout_index_options[] = {
                OPT_BOOLEAN('a', "all", &all,
-                       "checks out all files in the index"),
-               OPT__FORCE(&force, "forces overwrite of existing files"),
+                       N_("check out all files in the index")),
+               OPT__FORCE(&force, N_("force overwrite of existing files")),
                OPT__QUIET(&quiet,
-                       "no warning for existing files and files not in index"),
+                       N_("no warning for existing files and files not in index")),
                OPT_BOOLEAN('n', "no-create", &not_new,
-                       "don't checkout new files"),
+                       N_("don't checkout new files")),
                { OPTION_CALLBACK, 'u', "index", &newfd, NULL,
-                       "update stat information in the index file",
+                       N_("update stat information in the index file"),
                        PARSE_OPT_NOARG, option_parse_u },
                { OPTION_CALLBACK, 'z', NULL, NULL, NULL,
-                       "paths are separated with NUL character",
+                       N_("paths are separated with NUL character"),
                        PARSE_OPT_NOARG, option_parse_z },
                OPT_BOOLEAN(0, "stdin", &read_from_stdin,
-                       "read list of paths from the standard input"),
+                       N_("read list of paths from the standard input")),
                OPT_BOOLEAN(0, "temp", &to_tempfile,
-                       "write the content to temporary files"),
-               OPT_CALLBACK(0, "prefix", NULL, "string",
-                       "when creating files, prepend <string>",
+                       N_("write the content to temporary files")),
+               OPT_CALLBACK(0, "prefix", NULL, N_("string"),
+                       N_("when creating files, prepend <string>"),
                        option_parse_prefix),
                OPT_CALLBACK(0, "stage", NULL, NULL,
-                       "copy out the files from named stage",
+                       N_("copy out the files from named stage"),
                        option_parse_stage),
                OPT_END()
        };
index 7d922c6..a9c1b5a 100644 (file)
 #include "argv-array.h"
 
 static const char * const checkout_usage[] = {
-       "git checkout [options] <branch>",
-       "git checkout [options] [<branch>] -- <file>...",
+       N_("git checkout [options] <branch>"),
+       N_("git checkout [options] [<branch>] -- <file>..."),
        NULL,
 };
 
 struct checkout_opts {
+       int patch_mode;
        int quiet;
        int merge;
        int force;
        int force_detach;
        int writeout_stage;
-       int writeout_error;
        int overwrite_ignore;
 
-       /* not set by parse_options */
-       int branch_exists;
-
        const char *new_branch;
        const char *new_branch_force;
        const char *new_orphan_branch;
        int new_branch_log;
        enum branch_track track;
        struct diff_options diff_options;
+
+       int branch_exists;
+       const char *prefix;
+       const char **pathspec;
+       struct tree *source_tree;
 };
 
 static int post_checkout_hook(struct commit *old, struct commit *new,
@@ -215,8 +217,8 @@ static int checkout_merged(int pos, struct checkout *state)
        return status;
 }
 
-static int checkout_paths(struct tree *source_tree, const char **pathspec,
-                         const char *prefix, struct checkout_opts *opts)
+static int checkout_paths(const struct checkout_opts *opts,
+                         const char *revision)
 {
        int pos;
        struct checkout state;
@@ -228,37 +230,65 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec,
        int stage = opts->writeout_stage;
        int merge = opts->merge;
        int newfd;
-       struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file));
+       struct lock_file *lock_file;
+
+       if (opts->track != BRANCH_TRACK_UNSPECIFIED)
+               die(_("'%s' cannot be used with updating paths"), "--track");
+
+       if (opts->new_branch_log)
+               die(_("'%s' cannot be used with updating paths"), "-l");
+
+       if (opts->force && opts->patch_mode)
+               die(_("'%s' cannot be used with updating paths"), "-f");
+
+       if (opts->force_detach)
+               die(_("'%s' cannot be used with updating paths"), "--detach");
+
+       if (opts->merge && opts->patch_mode)
+               die(_("'%s' cannot be used with %s"), "--merge", "--patch");
+
+       if (opts->force && opts->merge)
+               die(_("'%s' cannot be used with %s"), "-f", "-m");
+
+       if (opts->new_branch)
+               die(_("Cannot update paths and switch to branch '%s' at the same time."),
+                   opts->new_branch);
+
+       if (opts->patch_mode)
+               return run_add_interactive(revision, "--patch=checkout",
+                                          opts->pathspec);
+
+       lock_file = xcalloc(1, sizeof(struct lock_file));
 
        newfd = hold_locked_index(lock_file, 1);
-       if (read_cache_preload(pathspec) < 0)
+       if (read_cache_preload(opts->pathspec) < 0)
                return error(_("corrupt index file"));
 
-       if (source_tree)
-               read_tree_some(source_tree, pathspec);
+       if (opts->source_tree)
+               read_tree_some(opts->source_tree, opts->pathspec);
 
-       for (pos = 0; pathspec[pos]; pos++)
+       for (pos = 0; opts->pathspec[pos]; pos++)
                ;
        ps_matched = xcalloc(1, pos);
 
        for (pos = 0; pos < active_nr; pos++) {
                struct cache_entry *ce = active_cache[pos];
-               if (source_tree && !(ce->ce_flags & CE_UPDATE))
+               if (opts->source_tree && !(ce->ce_flags & CE_UPDATE))
                        continue;
-               match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, ps_matched);
+               match_pathspec(opts->pathspec, ce->name, ce_namelen(ce), 0, ps_matched);
        }
 
-       if (report_path_error(ps_matched, pathspec, prefix))
+       if (report_path_error(ps_matched, opts->pathspec, opts->prefix))
                return 1;
 
        /* "checkout -m path" to recreate conflicted state */
        if (opts->merge)
-               unmerge_cache(pathspec);
+               unmerge_cache(opts->pathspec);
 
        /* Any unmerged paths? */
        for (pos = 0; pos < active_nr; pos++) {
                struct cache_entry *ce = active_cache[pos];
-               if (match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, NULL)) {
+               if (match_pathspec(opts->pathspec, ce->name, ce_namelen(ce), 0, NULL)) {
                        if (!ce_stage(ce))
                                continue;
                        if (opts->force) {
@@ -283,9 +313,9 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec,
        state.refresh_cache = 1;
        for (pos = 0; pos < active_nr; pos++) {
                struct cache_entry *ce = active_cache[pos];
-               if (source_tree && !(ce->ce_flags & CE_UPDATE))
+               if (opts->source_tree && !(ce->ce_flags & CE_UPDATE))
                        continue;
-               if (match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, NULL)) {
+               if (match_pathspec(opts->pathspec, ce->name, ce_namelen(ce), 0, NULL)) {
                        if (!ce_stage(ce)) {
                                errs |= checkout_entry(ce, &state, NULL);
                                continue;
@@ -309,7 +339,8 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec,
        return errs;
 }
 
-static void show_local_changes(struct object *head, struct diff_options *opts)
+static void show_local_changes(struct object *head,
+                              const struct diff_options *opts)
 {
        struct rev_info rev;
        /* I think we want full paths, even if we're in a subdirectory. */
@@ -331,7 +362,8 @@ static void describe_detached_head(const char *msg, struct commit *commit)
        strbuf_release(&sb);
 }
 
-static int reset_tree(struct tree *tree, struct checkout_opts *o, int worktree)
+static int reset_tree(struct tree *tree, const struct checkout_opts *o,
+                     int worktree, int *writeout_error)
 {
        struct unpack_trees_options opts;
        struct tree_desc tree_desc;
@@ -350,7 +382,7 @@ static int reset_tree(struct tree *tree, struct checkout_opts *o, int worktree)
        init_tree_desc(&tree_desc, tree->buffer, tree->size);
        switch (unpack_trees(1, &tree_desc, &opts)) {
        case -2:
-               o->writeout_error = 1;
+               *writeout_error = 1;
                /*
                 * We return 0 nevertheless, as the index is all right
                 * and more importantly we have made best efforts to
@@ -381,8 +413,10 @@ static void setup_branch_path(struct branch_info *branch)
        branch->path = strbuf_detach(&buf, NULL);
 }
 
-static int merge_working_tree(struct checkout_opts *opts,
-                             struct branch_info *old, struct branch_info *new)
+static int merge_working_tree(const struct checkout_opts *opts,
+                             struct branch_info *old,
+                             struct branch_info *new,
+                             int *writeout_error)
 {
        int ret;
        struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file));
@@ -393,7 +427,7 @@ static int merge_working_tree(struct checkout_opts *opts,
 
        resolve_undo_clear();
        if (opts->force) {
-               ret = reset_tree(new->commit->tree, opts, 1);
+               ret = reset_tree(new->commit->tree, opts, 1, writeout_error);
                if (ret)
                        return ret;
        } else {
@@ -479,7 +513,8 @@ static int merge_working_tree(struct checkout_opts *opts,
                        o.verbosity = 0;
                        work = write_tree_from_memory(&o);
 
-                       ret = reset_tree(new->commit->tree, opts, 1);
+                       ret = reset_tree(new->commit->tree, opts, 1,
+                                        writeout_error);
                        if (ret)
                                return ret;
                        o.ancestor = old->name;
@@ -487,7 +522,8 @@ static int merge_working_tree(struct checkout_opts *opts,
                        o.branch2 = "local";
                        merge_trees(&o, new->commit->tree, work,
                                old->commit->tree, &result);
-                       ret = reset_tree(new->commit->tree, opts, 0);
+                       ret = reset_tree(new->commit->tree, opts, 0,
+                                        writeout_error);
                        if (ret)
                                return ret;
                }
@@ -514,7 +550,7 @@ static void report_tracking(struct branch_info *new)
        strbuf_release(&sb);
 }
 
-static void update_refs_for_switch(struct checkout_opts *opts,
+static void update_refs_for_switch(const struct checkout_opts *opts,
                                   struct branch_info *old,
                                   struct branch_info *new)
 {
@@ -701,13 +737,14 @@ static void orphaned_commit_warning(struct commit *old, struct commit *new)
        free(refs.objects);
 }
 
-static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
+static int switch_branches(const struct checkout_opts *opts,
+                          struct branch_info *new)
 {
        int ret = 0;
        struct branch_info old;
        void *path_to_free;
        unsigned char rev[20];
-       int flag;
+       int flag, writeout_error = 0;
        memset(&old, 0, sizeof(old));
        old.path = path_to_free = resolve_refdup("HEAD", rev, 0, &flag);
        old.commit = lookup_commit_reference_gently(rev, 1);
@@ -725,7 +762,7 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
                parse_commit(new->commit);
        }
 
-       ret = merge_working_tree(opts, &old, new);
+       ret = merge_working_tree(opts, &old, new, &writeout_error);
        if (ret) {
                free(path_to_free);
                return ret;
@@ -738,7 +775,7 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
 
        ret = post_checkout_hook(old.commit, new->commit, 1);
        free(path_to_free);
-       return ret || opts->writeout_error;
+       return ret || writeout_error;
 }
 
 static int git_checkout_config(const char *var, const char *value, void *cb)
@@ -755,12 +792,6 @@ static int git_checkout_config(const char *var, const char *value, void *cb)
        return git_xmerge_config(var, value, NULL);
 }
 
-static int interactive_checkout(const char *revision, const char **pathspec,
-                               struct checkout_opts *opts)
-{
-       return run_add_interactive(revision, "--patch=checkout", pathspec);
-}
-
 struct tracking_name_data {
        const char *name;
        char *remote;
@@ -910,7 +941,7 @@ static int parse_branchname_arg(int argc, const char **argv,
        return argcount;
 }
 
-static int switch_unborn_to_new_branch(struct checkout_opts *opts)
+static int switch_unborn_to_new_branch(const struct checkout_opts *opts)
 {
        int status;
        struct strbuf branch_ref = STRBUF_INIT;
@@ -920,41 +951,86 @@ static int switch_unborn_to_new_branch(struct checkout_opts *opts)
        strbuf_addf(&branch_ref, "refs/heads/%s", opts->new_branch);
        status = create_symref("HEAD", branch_ref.buf, "checkout -b");
        strbuf_release(&branch_ref);
+       if (!opts->quiet)
+               fprintf(stderr, _("Switched to a new branch '%s'\n"),
+                       opts->new_branch);
        return status;
 }
 
+static int checkout_branch(struct checkout_opts *opts,
+                          struct branch_info *new)
+{
+       if (opts->pathspec)
+               die(_("paths cannot be used with switching branches"));
+
+       if (opts->patch_mode)
+               die(_("'%s' cannot be used with switching branches"),
+                   "--patch");
+
+       if (opts->writeout_stage)
+               die(_("'%s' cannot be used with switching branches"),
+                   "--ours/--theirs");
+
+       if (opts->force && opts->merge)
+               die(_("'%s' cannot be used with '%s'"), "-f", "-m");
+
+       if (opts->force_detach && opts->new_branch)
+               die(_("'%s' cannot be used with '%s'"),
+                   "--detach", "-b/-B/--orphan");
+
+       if (opts->new_orphan_branch) {
+               if (opts->track != BRANCH_TRACK_UNSPECIFIED)
+                       die(_("'%s' cannot be used with '%s'"), "--orphan", "-t");
+       } else if (opts->force_detach) {
+               if (opts->track != BRANCH_TRACK_UNSPECIFIED)
+                       die(_("'%s' cannot be used with '%s'"), "--detach", "-t");
+       } else if (opts->track == BRANCH_TRACK_UNSPECIFIED)
+               opts->track = git_branch_track;
+
+       if (new->name && !new->commit)
+               die(_("Cannot switch branch to a non-commit '%s'"),
+                   new->name);
+
+       if (!new->commit && opts->new_branch) {
+               unsigned char rev[20];
+               int flag;
+
+               if (!read_ref_full("HEAD", rev, 0, &flag) &&
+                   (flag & REF_ISSYMREF) && is_null_sha1(rev))
+                       return switch_unborn_to_new_branch(opts);
+       }
+       return switch_branches(opts, new);
+}
+
 int cmd_checkout(int argc, const char **argv, const char *prefix)
 {
        struct checkout_opts opts;
-       unsigned char rev[20];
        struct branch_info new;
-       struct tree *source_tree = NULL;
        char *conflict_style = NULL;
-       int patch_mode = 0;
        int dwim_new_local_branch = 1;
        struct option options[] = {
-               OPT__QUIET(&opts.quiet, "suppress progress reporting"),
-               OPT_STRING('b', NULL, &opts.new_branch, "branch",
-                          "create and checkout a new branch"),
-               OPT_STRING('B', NULL, &opts.new_branch_force, "branch",
-                          "create/reset and checkout a branch"),
-               OPT_BOOLEAN('l', NULL, &opts.new_branch_log, "create reflog for new branch"),
-               OPT_BOOLEAN(0, "detach", &opts.force_detach, "detach the HEAD at named commit"),
-               OPT_SET_INT('t', "track",  &opts.track, "set upstream info for new branch",
+               OPT__QUIET(&opts.quiet, N_("suppress progress reporting")),
+               OPT_STRING('b', NULL, &opts.new_branch, N_("branch"),
+                          N_("create and checkout a new branch")),
+               OPT_STRING('B', NULL, &opts.new_branch_force, N_("branch"),
+                          N_("create/reset and checkout a branch")),
+               OPT_BOOLEAN('l', NULL, &opts.new_branch_log, N_("create reflog for new branch")),
+               OPT_BOOLEAN(0, "detach", &opts.force_detach, N_("detach the HEAD at named commit")),
+               OPT_SET_INT('t', "track",  &opts.track, N_("set upstream info for new branch"),
                        BRANCH_TRACK_EXPLICIT),
-               OPT_STRING(0, "orphan", &opts.new_orphan_branch, "new branch", "new unparented branch"),
-               OPT_SET_INT('2', "ours", &opts.writeout_stage, "checkout our version for unmerged files",
+               OPT_STRING(0, "orphan", &opts.new_orphan_branch, N_("new branch"), N_("new unparented branch")),
+               OPT_SET_INT('2', "ours", &opts.writeout_stage, N_("checkout our version for unmerged files"),
                            2),
-               OPT_SET_INT('3', "theirs", &opts.writeout_stage, "checkout their version for unmerged files",
+               OPT_SET_INT('3', "theirs", &opts.writeout_stage, N_("checkout their version for unmerged files"),
                            3),
-               OPT__FORCE(&opts.force, "force checkout (throw away local modifications)"),
-               OPT_BOOLEAN('m', "merge", &opts.merge, "perform a 3-way merge with the new branch"),
-               OPT_BOOLEAN(0, "overwrite-ignore", &opts.overwrite_ignore, "update ignored files (default)"),
-               OPT_STRING(0, "conflict", &conflict_style, "style",
-                          "conflict style (merge or diff3)"),
-               OPT_BOOLEAN('p', "patch", &patch_mode, "select hunks interactively"),
+               OPT__FORCE(&opts.force, N_("force checkout (throw away local modifications)")),
+               OPT_BOOLEAN('m', "merge", &opts.merge, N_("perform a 3-way merge with the new branch")),
+               OPT_BOOLEAN(0, "overwrite-ignore", &opts.overwrite_ignore, N_("update ignored files (default)")),
+               OPT_STRING(0, "conflict", &conflict_style, N_("style"),
+                          N_("conflict style (merge or diff3)")),
+               OPT_BOOLEAN('p', "patch", &opts.patch_mode, N_("select hunks interactively")),
                { OPTION_BOOLEAN, 0, "guess", &dwim_new_local_branch, NULL,
-                 "second guess 'git checkout no-such-branch'",
+                 N_("second guess 'git checkout no-such-branch'"),
                  PARSE_OPT_NOARG | PARSE_OPT_HIDDEN },
                OPT_END(),
        };
@@ -962,6 +1038,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
        memset(&opts, 0, sizeof(opts));
        memset(&new, 0, sizeof(new));
        opts.overwrite_ignore = 1;
+       opts.prefix = prefix;
 
        gitmodules_config();
        git_config(git_checkout_config, &opts);
@@ -971,26 +1048,27 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
        argc = parse_options(argc, argv, prefix, options, checkout_usage,
                             PARSE_OPT_KEEP_DASHDASH);
 
-       /* we can assume from now on new_branch = !new_branch_force */
-       if (opts.new_branch && opts.new_branch_force)
-               die(_("-B cannot be used with -b"));
+       if (conflict_style) {
+               opts.merge = 1; /* implied */
+               git_xmerge_config("merge.conflictstyle", conflict_style, NULL);
+       }
+
+       if ((!!opts.new_branch + !!opts.new_branch_force + !!opts.new_orphan_branch) > 1)
+               die(_("-b, -B and --orphan are mutually exclusive"));
 
-       /* copy -B over to -b, so that we can just check the latter */
+       /*
+        * From here on, new_branch will contain the branch to be checked out,
+        * and new_branch_force and new_orphan_branch will tell us which one of
+        * -b/-B/--orphan is being used.
+        */
        if (opts.new_branch_force)
                opts.new_branch = opts.new_branch_force;
 
-       if (patch_mode && (opts.track > 0 || opts.new_branch
-                          || opts.new_branch_log || opts.merge || opts.force
-                          || opts.force_detach))
-               die (_("--patch is incompatible with all other options"));
-
-       if (opts.force_detach && (opts.new_branch || opts.new_orphan_branch))
-               die(_("--detach cannot be used with -b/-B/--orphan"));
-       if (opts.force_detach && 0 < opts.track)
-               die(_("--detach cannot be used with -t"));
+       if (opts.new_orphan_branch)
+               opts.new_branch = opts.new_orphan_branch;
 
-       /* --track without -b should DWIM */
-       if (0 < opts.track && !opts.new_branch) {
+       /* --track without -b/-B/--orphan should DWIM */
+       if (opts.track != BRANCH_TRACK_UNSPECIFIED && !opts.new_branch) {
                const char *argv0 = argv[0];
                if (!argc || !strcmp(argv0, "--"))
                        die (_("--track needs a branch name"));
@@ -1004,22 +1082,6 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
                opts.new_branch = argv0 + 1;
        }
 
-       if (opts.new_orphan_branch) {
-               if (opts.new_branch)
-                       die(_("--orphan and -b|-B are mutually exclusive"));
-               if (opts.track > 0)
-                       die(_("--orphan cannot be used with -t"));
-               opts.new_branch = opts.new_orphan_branch;
-       }
-
-       if (conflict_style) {
-               opts.merge = 1; /* implied */
-               git_xmerge_config("merge.conflictstyle", conflict_style, NULL);
-       }
-
-       if (opts.force && opts.merge)
-               die(_("git checkout: -f and -m are incompatible"));
-
        /*
         * Extract branch name from command line arguments, so
         * all that is left is pathspecs.
@@ -1034,73 +1096,56 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
         * remote branches, erroring out for invalid or ambiguous cases.
         */
        if (argc) {
+               unsigned char rev[20];
                int dwim_ok =
-                       !patch_mode &&
+                       !opts.patch_mode &&
                        dwim_new_local_branch &&
                        opts.track == BRANCH_TRACK_UNSPECIFIED &&
                        !opts.new_branch;
                int n = parse_branchname_arg(argc, argv, dwim_ok,
-                               &new, &source_tree, rev, &opts.new_branch);
+                                            &new, &opts.source_tree,
+                                            rev, &opts.new_branch);
                argv += n;
                argc -= n;
        }
 
-       if (opts.track == BRANCH_TRACK_UNSPECIFIED)
-               opts.track = git_branch_track;
-
        if (argc) {
-               const char **pathspec = get_pathspec(prefix, argv);
+               opts.pathspec = get_pathspec(prefix, argv);
 
-               if (!pathspec)
+               if (!opts.pathspec)
                        die(_("invalid path specification"));
 
-               if (patch_mode)
-                       return interactive_checkout(new.name, pathspec, &opts);
-
-               /* Checkout paths */
-               if (opts.new_branch) {
-                       if (argc == 1) {
-                               die(_("git checkout: updating paths is incompatible with switching branches.\nDid you intend to checkout '%s' which can not be resolved as commit?"), argv[0]);
-                       } else {
-                               die(_("git checkout: updating paths is incompatible with switching branches."));
-                       }
-               }
+               /*
+                * Try to give more helpful suggestion.
+                * new_branch && argc > 1 will be caught later.
+                */
+               if (opts.new_branch && argc == 1)
+                       die(_("Cannot update paths and switch to branch '%s' at the same time.\n"
+                             "Did you intend to checkout '%s' which can not be resolved as commit?"),
+                           opts.new_branch, argv[0]);
 
                if (opts.force_detach)
-                       die(_("git checkout: --detach does not take a path argument"));
+                       die(_("git checkout: --detach does not take a path argument '%s'"),
+                           argv[0]);
 
                if (1 < !!opts.writeout_stage + !!opts.force + !!opts.merge)
-                       die(_("git checkout: --ours/--theirs, --force and --merge are incompatible when\nchecking out of the index."));
-
-               return checkout_paths(source_tree, pathspec, prefix, &opts);
+                       die(_("git checkout: --ours/--theirs, --force and --merge are incompatible when\n"
+                             "checking out of the index."));
        }
 
-       if (patch_mode)
-               return interactive_checkout(new.name, NULL, &opts);
-
        if (opts.new_branch) {
                struct strbuf buf = STRBUF_INIT;
 
-               opts.branch_exists = validate_new_branchname(opts.new_branch, &buf,
-                                                            !!opts.new_branch_force,
-                                                            !!opts.new_branch_force);
+               opts.branch_exists =
+                       validate_new_branchname(opts.new_branch, &buf,
+                                               !!opts.new_branch_force,
+                                               !!opts.new_branch_force);
 
                strbuf_release(&buf);
        }
 
-       if (new.name && !new.commit) {
-               die(_("Cannot switch branch to a non-commit."));
-       }
-       if (opts.writeout_stage)
-               die(_("--ours/--theirs is incompatible with switching branches."));
-
-       if (!new.commit && opts.new_branch) {
-               unsigned char rev[20];
-               int flag;
-
-               if (!read_ref_full("HEAD", rev, 0, &flag) &&
-                   (flag & REF_ISSYMREF) && is_null_sha1(rev))
-                       return switch_unborn_to_new_branch(&opts);
-       }
-       return switch_branches(&opts, &new);
+       if (opts.patch_mode || opts.pathspec)
+               return checkout_paths(&opts, new.name);
+       else
+               return checkout_branch(&opts, &new);
 }
index 0c7b3d0..69c1cda 100644 (file)
@@ -16,7 +16,7 @@
 static int force = -1; /* unset */
 
 static const char *const builtin_clean_usage[] = {
-       "git clean [-d] [-f] [-n] [-q] [-e <pattern>] [-x | -X] [--] <paths>...",
+       N_("git clean [-d] [-f] [-n] [-q] [-e <pattern>] [-x | -X] [--] <paths>..."),
        NULL
 };
 
@@ -48,16 +48,16 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
        const char *qname;
        char *seen = NULL;
        struct option options[] = {
-               OPT__QUIET(&quiet, "do not print names of files removed"),
-               OPT__DRY_RUN(&show_only, "dry run"),
-               OPT__FORCE(&force, "force"),
+               OPT__QUIET(&quiet, N_("do not print names of files removed")),
+               OPT__DRY_RUN(&show_only, N_("dry run")),
+               OPT__FORCE(&force, N_("force")),
                OPT_BOOLEAN('d', NULL, &remove_directories,
-                               "remove whole directories"),
-               { OPTION_CALLBACK, 'e', "exclude", &exclude_list, "pattern",
-                 "add <pattern> to ignore rules", PARSE_OPT_NONEG, exclude_cb },
-               OPT_BOOLEAN('x', NULL, &ignored, "remove ignored files, too"),
+                               N_("remove whole directories")),
+               { OPTION_CALLBACK, 'e', "exclude", &exclude_list, N_("pattern"),
+                 N_("add <pattern> to ignore rules"), PARSE_OPT_NONEG, exclude_cb },
+               OPT_BOOLEAN('x', NULL, &ignored, N_("remove ignored files, too")),
                OPT_BOOLEAN('X', NULL, &ignored_only,
-                               "remove only ignored files"),
+                               N_("remove only ignored files")),
                OPT_END()
        };
 
index 0d663e3..ec2f75b 100644 (file)
@@ -33,7 +33,7 @@
  *
  */
 static const char * const builtin_clone_usage[] = {
-       "git clone [options] [--] <repo> [<dir>]",
+       N_("git clone [options] [--] <repo> [<dir>]"),
        NULL
 };
 
@@ -61,43 +61,43 @@ static int opt_parse_reference(const struct option *opt, const char *arg, int un
 static struct option builtin_clone_options[] = {
        OPT__VERBOSITY(&option_verbosity),
        OPT_BOOL(0, "progress", &option_progress,
-                "force progress reporting"),
+                N_("force progress reporting")),
        OPT_BOOLEAN('n', "no-checkout", &option_no_checkout,
-                   "don't create a checkout"),
-       OPT_BOOLEAN(0, "bare", &option_bare, "create a bare repository"),
+                   N_("don't create a checkout")),
+       OPT_BOOLEAN(0, "bare", &option_bare, N_("create a bare repository")),
        { OPTION_BOOLEAN, 0, "naked", &option_bare, NULL,
-               "create a bare repository",
+               N_("create a bare repository"),
                PARSE_OPT_NOARG | PARSE_OPT_HIDDEN },
        OPT_BOOLEAN(0, "mirror", &option_mirror,
-                   "create a mirror repository (implies bare)"),
+                   N_("create a mirror repository (implies bare)")),
        OPT_BOOL('l', "local", &option_local,
-               "to clone from a local repository"),
+               N_("to clone from a local repository")),
        OPT_BOOLEAN(0, "no-hardlinks", &option_no_hardlinks,
-                   "don't use local hardlinks, always copy"),
+                   N_("don't use local hardlinks, always copy")),
        OPT_BOOLEAN('s', "shared", &option_shared,
-                   "setup as shared repository"),
+                   N_("setup as shared repository")),
        OPT_BOOLEAN(0, "recursive", &option_recursive,
-                   "initialize submodules in the clone"),
+                   N_("initialize submodules in the clone")),
        OPT_BOOLEAN(0, "recurse-submodules", &option_recursive,
-                   "initialize submodules in the clone"),
-       OPT_STRING(0, "template", &option_template, "template-directory",
-                  "directory from which templates will be used"),
-       OPT_CALLBACK(0 , "reference", &option_reference, "repo",
-                    "reference repository", &opt_parse_reference),
-       OPT_STRING('o', "origin", &option_origin, "name",
-                  "use <name> instead of 'origin' to track upstream"),
-       OPT_STRING('b', "branch", &option_branch, "branch",
-                  "checkout <branch> instead of the remote's HEAD"),
-       OPT_STRING('u', "upload-pack", &option_upload_pack, "path",
-                  "path to git-upload-pack on the remote"),
-       OPT_STRING(0, "depth", &option_depth, "depth",
-                   "create a shallow clone of that depth"),
+                   N_("initialize submodules in the clone")),
+       OPT_STRING(0, "template", &option_template, N_("template-directory"),
+                  N_("directory from which templates will be used")),
+       OPT_CALLBACK(0 , "reference", &option_reference, N_("repo"),
+                    N_("reference repository"), &opt_parse_reference),
+       OPT_STRING('o', "origin", &option_origin, N_("name"),
+                  N_("use <name> instead of 'origin' to track upstream")),
+       OPT_STRING('b', "branch", &option_branch, N_("branch"),
+                  N_("checkout <branch> instead of the remote's HEAD")),
+       OPT_STRING('u', "upload-pack", &option_upload_pack, N_("path"),
+                  N_("path to git-upload-pack on the remote")),
+       OPT_STRING(0, "depth", &option_depth, N_("depth"),
+                   N_("create a shallow clone of that depth")),
        OPT_BOOL(0, "single-branch", &option_single_branch,
-                   "clone only one branch, HEAD or --branch"),
-       OPT_STRING(0, "separate-git-dir", &real_git_dir, "gitdir",
-                  "separate git dir from working tree"),
-       OPT_STRING_LIST('c', "config", &option_config, "key=value",
-                       "set config inside the new repository"),
+                   N_("clone only one branch, HEAD or --branch")),
+       OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
+                  N_("separate git dir from working tree")),
+       OPT_STRING_LIST('c', "config", &option_config, N_("key=value"),
+                       N_("set config inside the new repository")),
        OPT_END()
 };
 
@@ -236,7 +236,7 @@ static int add_one_reference(struct string_list_item *item, void *cb_data)
        /* Beware: real_path() and mkpath() return static buffer */
        ref_git = xstrdup(real_path(item->string));
        if (is_directory(mkpath("%s/.git/objects", ref_git))) {
-               char *ref_git_git = xstrdup(mkpath("%s/.git", ref_git));
+               char *ref_git_git = mkpathdup("%s/.git", ref_git);
                free(ref_git);
                ref_git = ref_git_git;
        } else if (!is_directory(mkpath("%s/objects", ref_git)))
@@ -748,7 +748,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
                git_dir = xstrdup(dir);
        else {
                work_tree = dir;
-               git_dir = xstrdup(mkpath("%s/.git", dir));
+               git_dir = mkpathdup("%s/.git", dir);
        }
 
        if (!option_bare) {
index 5ea798a..e125a55 100644 (file)
@@ -6,7 +6,7 @@
 #include "column.h"
 
 static const char * const builtin_column_usage[] = {
-       "git column [options]",
+       N_("git column [options]"),
        NULL
 };
 static unsigned int colopts;
@@ -23,13 +23,13 @@ int cmd_column(int argc, const char **argv, const char *prefix)
        struct column_options copts;
        const char *command = NULL, *real_command = NULL;
        struct option options[] = {
-               OPT_STRING(0, "command", &real_command, "name", "lookup config vars"),
-               OPT_COLUMN(0, "mode", &colopts, "layout to use"),
-               OPT_INTEGER(0, "raw-mode", &colopts, "layout to use"),
-               OPT_INTEGER(0, "width", &copts.width, "Maximum width"),
-               OPT_STRING(0, "indent", &copts.indent, "string", "Padding space on left border"),
-               OPT_INTEGER(0, "nl", &copts.nl, "Padding space on right border"),
-               OPT_INTEGER(0, "padding", &copts.padding, "Padding space between columns"),
+               OPT_STRING(0, "command", &real_command, N_("name"), N_("lookup config vars")),
+               OPT_COLUMN(0, "mode", &colopts, N_("layout to use")),
+               OPT_INTEGER(0, "raw-mode", &colopts, N_("layout to use")),
+               OPT_INTEGER(0, "width", &copts.width, N_("Maximum width")),
+               OPT_STRING(0, "indent", &copts.indent, N_("string"), N_("Padding space on left border")),
+               OPT_INTEGER(0, "nl", &copts.nl, N_("Padding space on right border")),
+               OPT_INTEGER(0, "padding", &copts.padding, N_("Padding space between columns")),
                OPT_END()
        };
 
index 7a83cae..a17a5df 100644 (file)
 #include "submodule.h"
 #include "gpg-interface.h"
 #include "column.h"
+#include "sequencer.h"
 
 static const char * const builtin_commit_usage[] = {
-       "git commit [options] [--] <filepattern>...",
+       N_("git commit [options] [--] <filepattern>..."),
        NULL
 };
 
 static const char * const builtin_status_usage[] = {
-       "git status [options] [--] <filepattern>...",
+       N_("git status [options] [--] <filepattern>..."),
        NULL
 };
 
@@ -466,8 +467,6 @@ static int is_a_merge(const struct commit *current_head)
        return !!(current_head->parents && current_head->parents->next);
 }
 
-static const char sign_off_header[] = "Signed-off-by: ";
-
 static void export_one(const char *var, const char *s, const char *e, int hack)
 {
        struct strbuf buf = STRBUF_INIT;
@@ -552,47 +551,6 @@ static void determine_author_info(struct strbuf *author_ident)
        }
 }
 
-static int ends_rfc2822_footer(struct strbuf *sb)
-{
-       int ch;
-       int hit = 0;
-       int i, j, k;
-       int len = sb->len;
-       int first = 1;
-       const char *buf = sb->buf;
-
-       for (i = len - 1; i > 0; i--) {
-               if (hit && buf[i] == '\n')
-                       break;
-               hit = (buf[i] == '\n');
-       }
-
-       while (i < len - 1 && buf[i] == '\n')
-               i++;
-
-       for (; i < len; i = k) {
-               for (k = i; k < len && buf[k] != '\n'; k++)
-                       ; /* do nothing */
-               k++;
-
-               if ((buf[k] == ' ' || buf[k] == '\t') && !first)
-                       continue;
-
-               first = 0;
-
-               for (j = 0; i + j < len; j++) {
-                       ch = buf[i + j];
-                       if (ch == ':')
-                               break;
-                       if (isalnum(ch) ||
-                           (ch == '-'))
-                               continue;
-                       return 0;
-               }
-       }
-       return 1;
-}
-
 static char *cut_ident_timestamp_part(char *string)
 {
        char *ket = strrchr(string, '>');
@@ -717,21 +675,30 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
                stripspace(&sb, 0);
 
        if (signoff) {
-               struct strbuf sob = STRBUF_INIT;
-               int i;
-
-               strbuf_addstr(&sob, sign_off_header);
-               strbuf_addstr(&sob, fmt_name(getenv("GIT_COMMITTER_NAME"),
-                                            getenv("GIT_COMMITTER_EMAIL")));
-               strbuf_addch(&sob, '\n');
-               for (i = sb.len - 1; i > 0 && sb.buf[i - 1] != '\n'; i--)
-                       ; /* do nothing */
-               if (prefixcmp(sb.buf + i, sob.buf)) {
-                       if (!i || !ends_rfc2822_footer(&sb))
-                               strbuf_addch(&sb, '\n');
-                       strbuf_addbuf(&sb, &sob);
+               /*
+                * See if we have a Conflicts: block at the end. If yes, count
+                * its size, so we can ignore it.
+                */
+               int ignore_footer = 0;
+               int i, eol, previous = 0;
+               const char *nl;
+
+               for (i = 0; i < sb.len; i++) {
+                       nl = memchr(sb.buf + i, '\n', sb.len - i);
+                       if (nl)
+                               eol = nl - sb.buf;
+                       else
+                               eol = sb.len;
+                       if (!prefixcmp(sb.buf + previous, "\nConflicts:\n")) {
+                               ignore_footer = sb.len - previous;
+                               break;
+                       }
+                       while (i < eol)
+                               i++;
+                       previous = eol;
                }
-               strbuf_release(&sob);
+
+               append_signoff(&sb, ignore_footer);
        }
 
        if (fwrite(sb.buf, 1, sb.len, s->fp) < sb.len)
@@ -1184,26 +1151,26 @@ int cmd_status(int argc, const char **argv, const char *prefix)
        int fd;
        unsigned char sha1[20];
        static struct option builtin_status_options[] = {
-               OPT__VERBOSE(&verbose, "be verbose"),
+               OPT__VERBOSE(&verbose, N_("be verbose")),
                OPT_SET_INT('s', "short", &status_format,
-                           "show status concisely", STATUS_FORMAT_SHORT),
+                           N_("show status concisely"), STATUS_FORMAT_SHORT),
                OPT_BOOLEAN('b', "branch", &s.show_branch,
-                           "show branch information"),
+                           N_("show branch information")),
                OPT_SET_INT(0, "porcelain", &status_format,
-                           "machine-readable output",
+                           N_("machine-readable output"),
                            STATUS_FORMAT_PORCELAIN),
                OPT_BOOLEAN('z', "null", &s.null_termination,
-                           "terminate entries with NUL"),
+                           N_("terminate entries with NUL")),
                { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg,
-                 "mode",
-                 "show untracked files, optional modes: all, normal, no. (Default: all)",
+                 N_("mode"),
+                 N_("show untracked files, optional modes: all, normal, no. (Default: all)"),
                  PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
                OPT_BOOLEAN(0, "ignored", &show_ignored_in_status,
-                           "show ignored files"),
-               { OPTION_STRING, 0, "ignore-submodules", &ignore_submodule_arg, "when",
-                 "ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)",
+                           N_("show ignored files")),
+               { OPTION_STRING, 0, "ignore-submodules", &ignore_submodule_arg, N_("when"),
+                 N_("ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)"),
                  PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
-               OPT_COLUMN(0, "column", &s.colopts, "list untracked files in columns"),
+               OPT_COLUMN(0, "column", &s.colopts, N_("list untracked files in columns")),
                OPT_END(),
        };
 
@@ -1384,53 +1351,53 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
 {
        static struct wt_status s;
        static struct option builtin_commit_options[] = {
-               OPT__QUIET(&quiet, "suppress summary after successful commit"),
-               OPT__VERBOSE(&verbose, "show diff in commit message template"),
-
-               OPT_GROUP("Commit message options"),
-               OPT_FILENAME('F', "file", &logfile, "read message from file"),
-               OPT_STRING(0, "author", &force_author, "author", "override author for commit"),
-               OPT_STRING(0, "date", &force_date, "date", "override date for commit"),
-               OPT_CALLBACK('m', "message", &message, "message", "commit message", opt_parse_m),
-               OPT_STRING('c', "reedit-message", &edit_message, "commit", "reuse and edit message from specified commit"),
-               OPT_STRING('C', "reuse-message", &use_message, "commit", "reuse message from specified commit"),
-               OPT_STRING(0, "fixup", &fixup_message, "commit", "use autosquash formatted message to fixup specified commit"),
-               OPT_STRING(0, "squash", &squash_message, "commit", "use autosquash formatted message to squash specified commit"),
-               OPT_BOOLEAN(0, "reset-author", &renew_authorship, "the commit is authored by me now (used with -C/-c/--amend)"),
-               OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
-               OPT_FILENAME('t', "template", &template_file, "use specified template file"),
-               OPT_BOOL('e', "edit", &edit_flag, "force edit of commit"),
-               OPT_STRING(0, "cleanup", &cleanup_arg, "default", "how to strip spaces and #comments from message"),
-               OPT_BOOLEAN(0, "status", &include_status, "include status in commit message template"),
-               { OPTION_STRING, 'S', "gpg-sign", &sign_commit, "key id",
-                 "GPG sign commit", PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
+               OPT__QUIET(&quiet, N_("suppress summary after successful commit")),
+               OPT__VERBOSE(&verbose, N_("show diff in commit message template")),
+
+               OPT_GROUP(N_("Commit message options")),
+               OPT_FILENAME('F', "file", &logfile, N_("read message from file")),
+               OPT_STRING(0, "author", &force_author, N_("author"), N_("override author for commit")),
+               OPT_STRING(0, "date", &force_date, N_("date"), N_("override date for commit")),
+               OPT_CALLBACK('m', "message", &message, N_("message"), N_("commit message"), opt_parse_m),
+               OPT_STRING('c', "reedit-message", &edit_message, N_("commit"), N_("reuse and edit message from specified commit")),
+               OPT_STRING('C', "reuse-message", &use_message, N_("commit"), N_("reuse message from specified commit")),
+               OPT_STRING(0, "fixup", &fixup_message, N_("commit"), N_("use autosquash formatted message to fixup specified commit")),
+               OPT_STRING(0, "squash", &squash_message, N_("commit"), N_("use autosquash formatted message to squash specified commit")),
+               OPT_BOOLEAN(0, "reset-author", &renew_authorship, N_("the commit is authored by me now (used with -C/-c/--amend)")),
+               OPT_BOOLEAN('s', "signoff", &signoff, N_("add Signed-off-by:")),
+               OPT_FILENAME('t', "template", &template_file, N_("use specified template file")),
+               OPT_BOOL('e', "edit", &edit_flag, N_("force edit of commit")),
+               OPT_STRING(0, "cleanup", &cleanup_arg, N_("default"), N_("how to strip spaces and #comments from message")),
+               OPT_BOOLEAN(0, "status", &include_status, N_("include status in commit message template")),
+               { OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key id"),
+                 N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
                /* end commit message options */
 
-               OPT_GROUP("Commit contents options"),
-               OPT_BOOLEAN('a', "all", &all, "commit all changed files"),
-               OPT_BOOLEAN('i', "include", &also, "add specified files to index for commit"),
-               OPT_BOOLEAN(0, "interactive", &interactive, "interactively add files"),
-               OPT_BOOLEAN('p', "patch", &patch_interactive, "interactively add changes"),
-               OPT_BOOLEAN('o', "only", &only, "commit only specified files"),
-               OPT_BOOLEAN('n', "no-verify", &no_verify, "bypass pre-commit hook"),
-               OPT_BOOLEAN(0, "dry-run", &dry_run, "show what would be committed"),
-               OPT_SET_INT(0, "short", &status_format, "show status concisely",
+               OPT_GROUP(N_("Commit contents options")),
+               OPT_BOOLEAN('a', "all", &all, N_("commit all changed files")),
+               OPT_BOOLEAN('i', "include", &also, N_("add specified files to index for commit")),
+               OPT_BOOLEAN(0, "interactive", &interactive, N_("interactively add files")),
+               OPT_BOOLEAN('p', "patch", &patch_interactive, N_("interactively add changes")),
+               OPT_BOOLEAN('o', "only", &only, N_("commit only specified files")),
+               OPT_BOOLEAN('n', "no-verify", &no_verify, N_("bypass pre-commit hook")),
+               OPT_BOOLEAN(0, "dry-run", &dry_run, N_("show what would be committed")),
+               OPT_SET_INT(0, "short", &status_format, N_("show status concisely"),
                            STATUS_FORMAT_SHORT),
-               OPT_BOOLEAN(0, "branch", &s.show_branch, "show branch information"),
+               OPT_BOOLEAN(0, "branch", &s.show_branch, N_("show branch information")),
                OPT_SET_INT(0, "porcelain", &status_format,
-                           "machine-readable output", STATUS_FORMAT_PORCELAIN),
+                           N_("machine-readable output"), STATUS_FORMAT_PORCELAIN),
                OPT_BOOLEAN('z', "null", &s.null_termination,
-                           "terminate entries with NUL"),
-               OPT_BOOLEAN(0, "amend", &amend, "amend previous commit"),
-               OPT_BOOLEAN(0, "no-post-rewrite", &no_post_rewrite, "bypass post-rewrite hook"),
-               { 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" },
+                           N_("terminate entries with NUL")),
+               OPT_BOOLEAN(0, "amend", &amend, N_("amend previous commit")),
+               OPT_BOOLEAN(0, "no-post-rewrite", &no_post_rewrite, N_("bypass post-rewrite hook")),
+               { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, N_("mode"), N_("show untracked files, optional modes: all, normal, no. (Default: all)"), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
                /* end commit contents options */
 
                { OPTION_BOOLEAN, 0, "allow-empty", &allow_empty, NULL,
-                 "ok to record an empty change",
+                 N_("ok to record an empty change"),
                  PARSE_OPT_NOARG | PARSE_OPT_HIDDEN },
                { OPTION_BOOLEAN, 0, "allow-empty-message", &allow_empty_message, NULL,
-                 "ok to record a change with an empty message",
+                 N_("ok to record a change with an empty message"),
                  PARSE_OPT_NOARG | PARSE_OPT_HIDDEN },
 
                OPT_END()
index 442ccc2..505bbc7 100644 (file)
@@ -4,7 +4,7 @@
 #include "parse-options.h"
 
 static const char *const builtin_config_usage[] = {
-       "git config [options]",
+       N_("git config [options]"),
        NULL
 };
 
@@ -49,33 +49,33 @@ static int respect_includes = -1;
 #define TYPE_PATH (1<<3)
 
 static struct option builtin_config_options[] = {
-       OPT_GROUP("Config file location"),
-       OPT_BOOLEAN(0, "global", &use_global_config, "use global config file"),
-       OPT_BOOLEAN(0, "system", &use_system_config, "use system config file"),
-       OPT_BOOLEAN(0, "local", &use_local_config, "use repository config file"),
-       OPT_STRING('f', "file", &given_config_file, "file", "use given config file"),
-       OPT_GROUP("Action"),
-       OPT_BIT(0, "get", &actions, "get value: name [value-regex]", ACTION_GET),
-       OPT_BIT(0, "get-all", &actions, "get all values: key [value-regex]", ACTION_GET_ALL),
-       OPT_BIT(0, "get-regexp", &actions, "get values for regexp: name-regex [value-regex]", ACTION_GET_REGEXP),
-       OPT_BIT(0, "replace-all", &actions, "replace all matching variables: name value [value_regex]", ACTION_REPLACE_ALL),
-       OPT_BIT(0, "add", &actions, "adds a new variable: name value", ACTION_ADD),
-       OPT_BIT(0, "unset", &actions, "removes a variable: name [value-regex]", ACTION_UNSET),
-       OPT_BIT(0, "unset-all", &actions, "removes all matches: name [value-regex]", ACTION_UNSET_ALL),
-       OPT_BIT(0, "rename-section", &actions, "rename section: old-name new-name", ACTION_RENAME_SECTION),
-       OPT_BIT(0, "remove-section", &actions, "remove a section: name", ACTION_REMOVE_SECTION),
-       OPT_BIT('l', "list", &actions, "list all", ACTION_LIST),
-       OPT_BIT('e', "edit", &actions, "opens an editor", ACTION_EDIT),
-       OPT_STRING(0, "get-color", &get_color_slot, "slot", "find the color configured: [default]"),
-       OPT_STRING(0, "get-colorbool", &get_colorbool_slot, "slot", "find the color setting: [stdout-is-tty]"),
-       OPT_GROUP("Type"),
-       OPT_BIT(0, "bool", &types, "value is \"true\" or \"false\"", TYPE_BOOL),
-       OPT_BIT(0, "int", &types, "value is decimal number", TYPE_INT),
-       OPT_BIT(0, "bool-or-int", &types, "value is --bool or --int", TYPE_BOOL_OR_INT),
-       OPT_BIT(0, "path", &types, "value is a path (file or directory name)", TYPE_PATH),
-       OPT_GROUP("Other"),
-       OPT_BOOLEAN('z', "null", &end_null, "terminate values with NUL byte"),
-       OPT_BOOL(0, "includes", &respect_includes, "respect include directives on lookup"),
+       OPT_GROUP(N_("Config file location")),
+       OPT_BOOLEAN(0, "global", &use_global_config, N_("use global config file")),
+       OPT_BOOLEAN(0, "system", &use_system_config, N_("use system config file")),
+       OPT_BOOLEAN(0, "local", &use_local_config, N_("use repository config file")),
+       OPT_STRING('f', "file", &given_config_file, N_("file"), N_("use given config file")),
+       OPT_GROUP(N_("Action")),
+       OPT_BIT(0, "get", &actions, N_("get value: name [value-regex]"), ACTION_GET),
+       OPT_BIT(0, "get-all", &actions, N_("get all values: key [value-regex]"), ACTION_GET_ALL),
+       OPT_BIT(0, "get-regexp", &actions, N_("get values for regexp: name-regex [value-regex]"), ACTION_GET_REGEXP),
+       OPT_BIT(0, "replace-all", &actions, N_("replace all matching variables: name value [value_regex]"), ACTION_REPLACE_ALL),
+       OPT_BIT(0, "add", &actions, N_("add a new variable: name value"), ACTION_ADD),
+       OPT_BIT(0, "unset", &actions, N_("remove a variable: name [value-regex]"), ACTION_UNSET),
+       OPT_BIT(0, "unset-all", &actions, N_("remove all matches: name [value-regex]"), ACTION_UNSET_ALL),
+       OPT_BIT(0, "rename-section", &actions, N_("rename section: old-name new-name"), ACTION_RENAME_SECTION),
+       OPT_BIT(0, "remove-section", &actions, N_("remove a section: name"), ACTION_REMOVE_SECTION),
+       OPT_BIT('l', "list", &actions, N_("list all"), ACTION_LIST),
+       OPT_BIT('e', "edit", &actions, N_("open an editor"), ACTION_EDIT),
+       OPT_STRING(0, "get-color", &get_color_slot, N_("slot"), N_("find the color configured: [default]")),
+       OPT_STRING(0, "get-colorbool", &get_colorbool_slot, N_("slot"), N_("find the color setting: [stdout-is-tty]")),
+       OPT_GROUP(N_("Type")),
+       OPT_BIT(0, "bool", &types, N_("value is \"true\" or \"false\""), TYPE_BOOL),
+       OPT_BIT(0, "int", &types, N_("value is decimal number"), TYPE_INT),
+       OPT_BIT(0, "bool-or-int", &types, N_("value is --bool or --int"), TYPE_BOOL_OR_INT),
+       OPT_BIT(0, "path", &types, N_("value is a path (file or directory name)"), TYPE_PATH),
+       OPT_GROUP(N_("Other")),
+       OPT_BOOLEAN('z', "null", &end_null, N_("terminate values with NUL byte")),
+       OPT_BOOL(0, "includes", &respect_includes, N_("respect include directives on lookup")),
        OPT_END(),
 };
 
@@ -129,7 +129,8 @@ static int show_config(const char *key_, const char *value_, void *cb)
                else
                        sprintf(value, "%d", v);
        } else if (types == TYPE_PATH) {
-               git_config_pathname(&vptr, key_, value_);
+               if (git_config_pathname(&vptr, key_, value_) < 0)
+                       return -1;
                must_free_vptr = 1;
        } else if (value_) {
                vptr = value_;
index c37cb98..9afaa88 100644 (file)
@@ -66,7 +66,7 @@ static void count_objects(DIR *d, char *path, int len, int verbose,
 }
 
 static char const * const count_objects_usage[] = {
-       "git count-objects [-v]",
+       N_("git count-objects [-v]"),
        NULL
 };
 
@@ -79,7 +79,7 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)
        unsigned long loose = 0, packed = 0, packed_loose = 0, garbage = 0;
        off_t loose_size = 0;
        struct option opts[] = {
-               OPT__VERBOSE(&verbose, "be verbose"),
+               OPT__VERBOSE(&verbose, N_("be verbose")),
                OPT_END(),
        };
 
index 9f63067..9fe11ed 100644 (file)
@@ -12,8 +12,8 @@
 #define MAX_TAGS       (FLAG_BITS - 1)
 
 static const char * const describe_usage[] = {
-       "git describe [options] <committish>*",
-       "git describe [options] --dirty",
+       N_("git describe [options] <committish>*"),
+       N_("git describe [options] --dirty"),
        NULL
 };
 
@@ -400,22 +400,22 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
 {
        int contains = 0;
        struct option options[] = {
-               OPT_BOOLEAN(0, "contains",   &contains, "find the tag that comes after the commit"),
-               OPT_BOOLEAN(0, "debug",      &debug, "debug search strategy on stderr"),
-               OPT_BOOLEAN(0, "all",        &all, "use any ref in .git/refs"),
-               OPT_BOOLEAN(0, "tags",       &tags, "use any tag in .git/refs/tags"),
-               OPT_BOOLEAN(0, "long",       &longformat, "always use long format"),
+               OPT_BOOLEAN(0, "contains",   &contains, N_("find the tag that comes after the commit")),
+               OPT_BOOLEAN(0, "debug",      &debug, N_("debug search strategy on stderr")),
+               OPT_BOOLEAN(0, "all",        &all, N_("use any ref in .git/refs")),
+               OPT_BOOLEAN(0, "tags",       &tags, N_("use any tag in .git/refs/tags")),
+               OPT_BOOLEAN(0, "long",       &longformat, N_("always use long format")),
                OPT__ABBREV(&abbrev),
                OPT_SET_INT(0, "exact-match", &max_candidates,
-                           "only output exact matches", 0),
+                           N_("only output exact matches"), 0),
                OPT_INTEGER(0, "candidates", &max_candidates,
-                           "consider <n> most recent tags (default: 10)"),
-               OPT_STRING(0, "match",       &pattern, "pattern",
-                          "only consider tags matching <pattern>"),
+                           N_("consider <n> most recent tags (default: 10)")),
+               OPT_STRING(0, "match",       &pattern, N_("pattern"),
+                          N_("only consider tags matching <pattern>")),
                OPT_BOOLEAN(0, "always",     &always,
-                          "show abbreviated commit object as fallback"),
-               {OPTION_STRING, 0, "dirty",  &dirty, "mark",
-                          "append <mark> on dirty working tree (default: \"-dirty\")",
+                          N_("show abbreviated commit object as fallback")),
+               {OPTION_STRING, 0, "dirty",  &dirty, N_("mark"),
+                          N_("append <mark> on dirty working tree (default: \"-dirty\")"),
                 PARSE_OPT_OPTARG, NULL, (intptr_t) "-dirty"},
                OPT_END(),
        };
index 9ab6db3..12220ad 100644 (file)
@@ -19,7 +19,7 @@
 #include "quote.h"
 
 static const char *fast_export_usage[] = {
-       "git fast-export [rev-list-opts]",
+       N_("git fast-export [rev-list-opts]"),
        NULL
 };
 
@@ -632,24 +632,24 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
        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",
+                           N_("show progress after <n> objects")),
+               OPT_CALLBACK(0, "signed-tags", &signed_tag_mode, N_("mode"),
+                            N_("select handling of signed tags"),
                             parse_opt_signed_tag_mode),
-               OPT_CALLBACK(0, "tag-of-filtered-object", &tag_of_filtered_mode, "mode",
-                            "select handling of tags that tag filtered objects",
+               OPT_CALLBACK(0, "tag-of-filtered-object", &tag_of_filtered_mode, N_("mode"),
+                            N_("select handling of tags that tag filtered objects"),
                             parse_opt_tag_of_filtered_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_STRING(0, "export-marks", &export_filename, N_("file"),
+                            N_("Dump marks to this file")),
+               OPT_STRING(0, "import-marks", &import_filename, N_("file"),
+                            N_("Import marks from this file")),
                OPT_BOOLEAN(0, "fake-missing-tagger", &fake_missing_tagger,
-                            "Fake a tagger when tags lack one"),
+                            N_("Fake a tagger when tags lack one")),
                OPT_BOOLEAN(0, "full-tree", &full_tree,
-                            "Output full tree for each commit"),
+                            N_("Output full tree for each commit")),
                OPT_BOOLEAN(0, "use-done-feature", &use_done_feature,
-                            "Use the done feature to terminate the stream"),
-               OPT_BOOL(0, "no-data", &no_data, "Skip output of blob data"),
+                            N_("Use the done feature to terminate the stream")),
+               OPT_BOOL(0, "no-data", &no_data, N_("Skip output of blob data")),
                OPT_END()
        };
 
index fdda36f..e644398 100644 (file)
@@ -525,72 +525,59 @@ static void mark_recent_complete_commits(unsigned long cutoff)
        }
 }
 
-static void filter_refs(struct ref **refs, int nr_match, char **match)
+static int non_matching_ref(struct string_list_item *item, void *unused)
+{
+       if (item->util) {
+               item->util = NULL;
+               return 0;
+       }
+       else
+               return 1;
+}
+
+static void filter_refs(struct ref **refs, struct string_list *sought)
 {
-       struct ref **return_refs;
        struct ref *newlist = NULL;
        struct ref **newtail = &newlist;
        struct ref *ref, *next;
-       struct ref *fastarray[32];
-       int match_pos;
-
-       if (nr_match && !args.fetch_all) {
-               if (ARRAY_SIZE(fastarray) < nr_match)
-                       return_refs = xcalloc(nr_match, sizeof(struct ref *));
-               else {
-                       return_refs = fastarray;
-                       memset(return_refs, 0, sizeof(struct ref *) * nr_match);
-               }
-       }
-       else
-               return_refs = NULL;
+       int sought_pos;
 
-       match_pos = 0;
+       sought_pos = 0;
        for (ref = *refs; ref; ref = next) {
+               int keep = 0;
                next = ref->next;
                if (!memcmp(ref->name, "refs/", 5) &&
                    check_refname_format(ref->name + 5, 0))
                        ; /* trash */
-               else if (args.fetch_all &&
-                        (!args.depth || prefixcmp(ref->name, "refs/tags/") )) {
-                       *newtail = ref;
-                       ref->next = NULL;
-                       newtail = &ref->next;
-                       continue;
-               }
                else {
-                       int cmp = -1;
-                       while (match_pos < nr_match) {
-                               cmp = strcmp(ref->name, match[match_pos]);
-                               if (cmp < 0) /* definitely do not have it */
-                                       break;
-                               else if (cmp == 0) { /* definitely have it */
-                                       match[match_pos][0] = '\0';
-                                       return_refs[match_pos] = ref;
+                       while (sought_pos < sought->nr) {
+                               int cmp = strcmp(ref->name, sought->items[sought_pos].string);
+                               if (cmp < 0)
+                                       break; /* definitely do not have it */
+                               else if (cmp == 0) {
+                                       keep = 1; /* definitely have it */
+                                       sought->items[sought_pos++].util = "matched";
                                        break;
                                }
-                               else /* might have it; keep looking */
-                                       match_pos++;
+                               else
+                                       sought_pos++; /* might have it; keep looking */
                        }
-                       if (!cmp)
-                               continue; /* we will link it later */
                }
-               free(ref);
-       }
 
-       if (!args.fetch_all) {
-               int i;
-               for (i = 0; i < nr_match; i++) {
-                       ref = return_refs[i];
-                       if (ref) {
-                               *newtail = ref;
-                               ref->next = NULL;
-                               newtail = &ref->next;
-                       }
+               if (! keep && args.fetch_all &&
+                   (!args.depth || prefixcmp(ref->name, "refs/tags/")))
+                       keep = 1;
+
+               if (keep) {
+                       *newtail = ref;
+                       ref->next = NULL;
+                       newtail = &ref->next;
+               } else {
+                       free(ref);
                }
-               if (return_refs != fastarray)
-                       free(return_refs);
        }
+
+       filter_string_list(sought, 0, non_matching_ref, NULL);
        *refs = newlist;
 }
 
@@ -599,7 +586,7 @@ static void mark_alternate_complete(const struct ref *ref, void *unused)
        mark_complete(NULL, ref->old_sha1, 0, NULL);
 }
 
-static int everything_local(struct ref **refs, int nr_match, char **match)
+static int everything_local(struct ref **refs, struct string_list *sought)
 {
        struct ref *ref;
        int retval;
@@ -650,7 +637,7 @@ static int everything_local(struct ref **refs, int nr_match, char **match)
                }
        }
 
-       filter_refs(refs, nr_match, match);
+       filter_refs(refs, sought);
 
        for (retval = 1, ref = *refs; ref ; ref = ref->next) {
                const unsigned char *remote = ref->old_sha1;
@@ -781,8 +768,7 @@ static int get_pack(int xd[2], char **pack_lockfile)
 
 static struct ref *do_fetch_pack(int fd[2],
                const struct ref *orig_ref,
-               int nr_match,
-               char **match,
+               struct string_list *sought,
                char **pack_lockfile)
 {
        struct ref *ref = copy_ref_list(orig_ref);
@@ -839,7 +825,7 @@ static struct ref *do_fetch_pack(int fd[2],
                                agent_len, agent_feature);
        }
 
-       if (everything_local(&ref, nr_match, match)) {
+       if (everything_local(&ref, sought)) {
                packet_flush(fd[1]);
                goto all_done;
        }
@@ -859,19 +845,6 @@ static struct ref *do_fetch_pack(int fd[2],
        return ref;
 }
 
-static int remove_duplicates(int nr_heads, char **heads)
-{
-       int src, dst;
-
-       if (!nr_heads)
-               return 0;
-
-       for (src = dst = 1; src < nr_heads; src++)
-               if (strcmp(heads[src], heads[dst-1]))
-                       heads[dst++] = heads[src];
-       return dst;
-}
-
 static int fetch_pack_config(const char *var, const char *value, void *cb)
 {
        if (strcmp(var, "fetch.unpacklimit") == 0) {
@@ -922,8 +895,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
        int i, ret;
        struct ref *ref = NULL;
        const char *dest = NULL;
-       int alloc_heads = 0, nr_heads = 0;
-       char **heads = NULL;
+       struct string_list sought = STRING_LIST_INIT_DUP;
        int fd[2];
        char *pack_lockfile = NULL;
        char **pack_lockfile_ptr = NULL;
@@ -1000,9 +972,8 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
         * Copy refs from cmdline to growable list, then append any
         * refs from the standard input:
         */
-       ALLOC_GROW(heads, argc - i, alloc_heads);
        for (; i < argc; i++)
-               heads[nr_heads++] = xstrdup(argv[i]);
+               string_list_append(&sought, xstrdup(argv[i]));
        if (args.stdin_refs) {
                if (args.stateless_rpc) {
                        /* in stateless RPC mode we use pkt-line to read
@@ -1015,17 +986,14 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
                                        break;
                                if (line[n-1] == '\n')
                                        n--;
-                               ALLOC_GROW(heads, nr_heads + 1, alloc_heads);
-                               heads[nr_heads++] = xmemdupz(line, n);
+                               string_list_append(&sought, xmemdupz(line, n));
                        }
                }
                else {
                        /* read from stdin one ref per line, until EOF */
                        struct strbuf line = STRBUF_INIT;
-                       while (strbuf_getline(&line, stdin, '\n') != EOF) {
-                               ALLOC_GROW(heads, nr_heads + 1, alloc_heads);
-                               heads[nr_heads++] = strbuf_detach(&line, NULL);
-                       }
+                       while (strbuf_getline(&line, stdin, '\n') != EOF)
+                               string_list_append(&sought, strbuf_detach(&line, NULL));
                        strbuf_release(&line);
                }
        }
@@ -1042,7 +1010,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
        get_remote_heads(fd[0], &ref, 0, NULL);
 
        ref = fetch_pack(&args, fd, conn, ref, dest,
-               nr_heads, heads, pack_lockfile_ptr);
+                        &sought, pack_lockfile_ptr);
        if (pack_lockfile) {
                printf("lock %s\n", pack_lockfile);
                fflush(stdout);
@@ -1050,21 +1018,18 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
        close(fd[0]);
        close(fd[1]);
        if (finish_connect(conn))
-               ref = NULL;
-       ret = !ref;
-
-       if (!ret && nr_heads) {
-               /* If the heads to pull were given, we should have
-                * consumed all of them by matching the remote.
-                * Otherwise, 'git fetch remote no-such-ref' would
-                * silently succeed without issuing an error.
-                */
-               for (i = 0; i < nr_heads; i++)
-                       if (heads[i] && heads[i][0]) {
-                               error("no such remote ref %s", heads[i]);
-                               ret = 1;
-                       }
-       }
+               return 1;
+
+       ret = !ref || sought.nr;
+
+       /*
+        * If the heads to pull were given, we should have consumed
+        * all of them by matching the remote.  Otherwise, 'git fetch
+        * remote no-such-ref' would silently succeed without issuing
+        * an error.
+        */
+       for (i = 0; i < sought.nr; i++)
+               error("no such remote ref %s", sought.items[i].string);
        while (ref) {
                printf("%s %s\n",
                       sha1_to_hex(ref->old_sha1), ref->name);
@@ -1074,18 +1039,12 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
        return ret;
 }
 
-static int compare_heads(const void *a, const void *b)
-{
-       return strcmp(*(const char **)a, *(const char **)b);
-}
-
 struct ref *fetch_pack(struct fetch_pack_args *my_args,
                       int fd[], struct child_process *conn,
                       const struct ref *ref,
-               const char *dest,
-               int nr_heads,
-               char **heads,
-               char **pack_lockfile)
+                      const char *dest,
+                      struct string_list *sought,
+                      char **pack_lockfile)
 {
        struct stat st;
        struct ref *ref_cpy;
@@ -1098,16 +1057,16 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args,
                        st.st_mtime = 0;
        }
 
-       if (heads && nr_heads) {
-               qsort(heads, nr_heads, sizeof(*heads), compare_heads);
-               nr_heads = remove_duplicates(nr_heads, heads);
+       if (sought->nr) {
+               sort_string_list(sought);
+               string_list_remove_duplicates(sought, 0);
        }
 
        if (!ref) {
                packet_flush(fd[1]);
                die("no matching remote head");
        }
-       ref_cpy = do_fetch_pack(fd, ref, nr_heads, heads, pack_lockfile);
+       ref_cpy = do_fetch_pack(fd, ref, sought, pack_lockfile);
 
        if (args.depth > 0) {
                struct cache_time mtime;
index f483352..4b5a898 100644 (file)
 #include "argv-array.h"
 
 static const char * const builtin_fetch_usage[] = {
-       "git fetch [<options>] [<repository> [<refspec>...]]",
-       "git fetch [<options>] <group>",
-       "git fetch --multiple [<options>] [(<repository> | <group>)...]",
-       "git fetch --all [<options>]",
+       N_("git fetch [<options>] [<repository> [<refspec>...]]"),
+       N_("git fetch [<options>] <group>"),
+       N_("git fetch --multiple [<options>] [(<repository> | <group>)...]"),
+       N_("git fetch --all [<options>]"),
        NULL
 };
 
@@ -57,36 +57,36 @@ static int option_parse_recurse_submodules(const struct option *opt,
 static struct option builtin_fetch_options[] = {
        OPT__VERBOSITY(&verbosity),
        OPT_BOOLEAN(0, "all", &all,
-                   "fetch from all remotes"),
+                   N_("fetch from all remotes")),
        OPT_BOOLEAN('a', "append", &append,
-                   "append to .git/FETCH_HEAD instead of overwriting"),
-       OPT_STRING(0, "upload-pack", &upload_pack, "path",
-                  "path to upload pack on remote end"),
-       OPT__FORCE(&force, "force overwrite of local branch"),
+                   N_("append to .git/FETCH_HEAD instead of overwriting")),
+       OPT_STRING(0, "upload-pack", &upload_pack, N_("path"),
+                  N_("path to upload pack on remote end")),
+       OPT__FORCE(&force, N_("force overwrite of local branch")),
        OPT_BOOLEAN('m', "multiple", &multiple,
-                   "fetch from multiple remotes"),
+                   N_("fetch from multiple remotes")),
        OPT_SET_INT('t', "tags", &tags,
-                   "fetch all tags and associated objects", TAGS_SET),
+                   N_("fetch all tags and associated objects"), TAGS_SET),
        OPT_SET_INT('n', NULL, &tags,
-                   "do not fetch all tags (--no-tags)", TAGS_UNSET),
+                   N_("do not fetch all tags (--no-tags)"), TAGS_UNSET),
        OPT_BOOLEAN('p', "prune", &prune,
-                   "prune remote-tracking branches no longer on remote"),
-       { OPTION_CALLBACK, 0, "recurse-submodules", NULL, "on-demand",
-                   "control recursive fetching of submodules",
+                   N_("prune remote-tracking branches no longer on remote")),
+       { OPTION_CALLBACK, 0, "recurse-submodules", NULL, N_("on-demand"),
+                   N_("control recursive fetching of submodules"),
                    PARSE_OPT_OPTARG, option_parse_recurse_submodules },
        OPT_BOOLEAN(0, "dry-run", &dry_run,
-                   "dry run"),
-       OPT_BOOLEAN('k', "keep", &keep, "keep downloaded pack"),
+                   N_("dry run")),
+       OPT_BOOLEAN('k', "keep", &keep, N_("keep downloaded pack")),
        OPT_BOOLEAN('u', "update-head-ok", &update_head_ok,
-                   "allow updating of HEAD ref"),
-       OPT_BOOL(0, "progress", &progress, "force progress reporting"),
-       OPT_STRING(0, "depth", &depth, "depth",
-                  "deepen history of shallow clone"),
-       { OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, "dir",
-                  "prepend this to submodule path output", PARSE_OPT_HIDDEN },
+                   N_("allow updating of HEAD ref")),
+       OPT_BOOL(0, "progress", &progress, N_("force progress reporting")),
+       OPT_STRING(0, "depth", &depth, N_("depth"),
+                  N_("deepen history of shallow clone")),
+       { OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, N_("dir"),
+                  N_("prepend this to submodule path output"), PARSE_OPT_HIDDEN },
        { OPTION_STRING, 0, "recurse-submodules-default",
                   &recurse_submodules_default, NULL,
-                  "default mode for recursion", PARSE_OPT_HIDDEN },
+                  N_("default mode for recursion"), PARSE_OPT_HIDDEN },
        OPT_END()
 };
 
@@ -256,9 +256,8 @@ static int update_local_ref(struct ref *ref,
        if (!hashcmp(ref->old_sha1, ref->new_sha1)) {
                if (verbosity > 0)
                        strbuf_addf(display, "= %-*s %-*s -> %s",
-                                   TRANSPORT_SUMMARY_WIDTH,
-                                   _("[up to date]"), REFCOL_WIDTH,
-                                   remote, pretty_ref);
+                                   TRANSPORT_SUMMARY(_("[up to date]")),
+                                   REFCOL_WIDTH, remote, pretty_ref);
                return 0;
        }
 
@@ -272,7 +271,7 @@ static int update_local_ref(struct ref *ref,
                 */
                strbuf_addf(display,
                            _("! %-*s %-*s -> %s  (can't fetch in current branch)"),
-                           TRANSPORT_SUMMARY_WIDTH, _("[rejected]"),
+                           TRANSPORT_SUMMARY(_("[rejected]")),
                            REFCOL_WIDTH, remote, pretty_ref);
                return 1;
        }
@@ -283,7 +282,7 @@ static int update_local_ref(struct ref *ref,
                r = s_update_ref("updating tag", ref, 0);
                strbuf_addf(display, "%c %-*s %-*s -> %s%s",
                            r ? '!' : '-',
-                           TRANSPORT_SUMMARY_WIDTH, _("[tag update]"),
+                           TRANSPORT_SUMMARY(_("[tag update]")),
                            REFCOL_WIDTH, remote, pretty_ref,
                            r ? _("  (unable to update local ref)") : "");
                return r;
@@ -318,13 +317,13 @@ static int update_local_ref(struct ref *ref,
                r = s_update_ref(msg, ref, 0);
                strbuf_addf(display, "%c %-*s %-*s -> %s%s",
                            r ? '!' : '*',
-                           TRANSPORT_SUMMARY_WIDTH, what,
+                           TRANSPORT_SUMMARY(what),
                            REFCOL_WIDTH, remote, pretty_ref,
                            r ? _("  (unable to update local ref)") : "");
                return r;
        }
 
-       if (in_merge_bases(current, &updated, 1)) {
+       if (in_merge_bases(current, updated)) {
                char quickref[83];
                int r;
                strcpy(quickref, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV));
@@ -358,7 +357,7 @@ static int update_local_ref(struct ref *ref,
                return r;
        } else {
                strbuf_addf(display, "! %-*s %-*s -> %s  %s",
-                           TRANSPORT_SUMMARY_WIDTH, _("[rejected]"),
+                           TRANSPORT_SUMMARY(_("[rejected]")),
                            REFCOL_WIDTH, remote, pretty_ref,
                            _("(non-fast-forward)"));
                return 1;
@@ -555,7 +554,7 @@ static int prune_refs(struct refspec *refs, int ref_count, struct ref *ref_map)
                        result |= delete_ref(ref->name, NULL, 0);
                if (verbosity >= 0) {
                        fprintf(stderr, " x %-*s %-*s -> %s\n",
-                               TRANSPORT_SUMMARY_WIDTH, _("[deleted]"),
+                               TRANSPORT_SUMMARY(_("[deleted]")),
                                REFCOL_WIDTH, _("(none)"), prettify_refname(ref->name));
                        warn_dangling_symref(stderr, dangling_msg, ref->name);
                }
index 2c4d435..e2e27b2 100644 (file)
@@ -10,7 +10,7 @@
 #include "gpg-interface.h"
 
 static const char * const fmt_merge_msg_usage[] = {
-       "git fmt-merge-msg [-m <message>] [--log[=<n>]|--no-log] [--file <file>]",
+       N_("git fmt-merge-msg [-m <message>] [--log[=<n>]|--no-log] [--file <file>]"),
        NULL
 };
 
@@ -650,16 +650,16 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
        const char *message = NULL;
        int shortlog_len = -1;
        struct option options[] = {
-               { OPTION_INTEGER, 0, "log", &shortlog_len, "n",
-                 "populate log with at most <n> entries from shortlog",
+               { OPTION_INTEGER, 0, "log", &shortlog_len, N_("n"),
+                 N_("populate log with at most <n> entries from shortlog"),
                  PARSE_OPT_OPTARG, NULL, DEFAULT_MERGE_LOG_LEN },
-               { OPTION_INTEGER, 0, "summary", &shortlog_len, "n",
-                 "alias for --log (deprecated)",
+               { OPTION_INTEGER, 0, "summary", &shortlog_len, N_("n"),
+                 N_("alias for --log (deprecated)"),
                  PARSE_OPT_OPTARG | PARSE_OPT_HIDDEN, NULL,
                  DEFAULT_MERGE_LOG_LEN },
-               OPT_STRING('m', "message", &message, "text",
-                       "use <text> as start of message"),
-               OPT_FILENAME('F', "file", &inpath, "file to read from"),
+               OPT_STRING('m', "message", &message, N_("text"),
+                       N_("use <text> as start of message")),
+               OPT_FILENAME('F', "file", &inpath, N_("file to read from")),
                OPT_END()
        };
 
index 0c5294e..7f059c3 100644 (file)
@@ -976,7 +976,7 @@ static int opt_parse_sort(const struct option *opt, const char *arg, int unset)
 }
 
 static char const * const for_each_ref_usage[] = {
-       "git for-each-ref [options] [<pattern>]",
+       N_("git for-each-ref [options] [<pattern>]"),
        NULL
 };
 
@@ -991,19 +991,19 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
 
        struct option opts[] = {
                OPT_BIT('s', "shell", &quote_style,
-                       "quote placeholders suitably for shells", QUOTE_SHELL),
+                       N_("quote placeholders suitably for shells"), QUOTE_SHELL),
                OPT_BIT('p', "perl",  &quote_style,
-                       "quote placeholders suitably for perl", QUOTE_PERL),
+                       N_("quote placeholders suitably for perl"), QUOTE_PERL),
                OPT_BIT(0 , "python", &quote_style,
-                       "quote placeholders suitably for python", QUOTE_PYTHON),
+                       N_("quote placeholders suitably for python"), QUOTE_PYTHON),
                OPT_BIT(0 , "tcl",  &quote_style,
-                       "quote placeholders suitably for tcl", QUOTE_TCL),
+                       N_("quote placeholders suitably for tcl"), QUOTE_TCL),
 
                OPT_GROUP(""),
-               OPT_INTEGER( 0 , "count", &maxcount, "show only <n> matched refs"),
-               OPT_STRING(  0 , "format", &format, "format", "format to use for the output"),
-               OPT_CALLBACK(0 , "sort", sort_tail, "key",
-                           "field name to sort on", &opt_parse_sort),
+               OPT_INTEGER( 0 , "count", &maxcount, N_("show only <n> matched refs")),
+               OPT_STRING(  0 , "format", &format, N_("format"), N_("format to use for the output")),
+               OPT_CALLBACK(0 , "sort", sort_tail, N_("key"),
+                           N_("field name to sort on"), &opt_parse_sort),
                OPT_END(),
        };
 
index a710227..bb9a2cd 100644 (file)
@@ -605,23 +605,23 @@ static int fsck_cache_tree(struct cache_tree *it)
 }
 
 static char const * const fsck_usage[] = {
-       "git fsck [options] [<object>...]",
+       N_("git fsck [options] [<object>...]"),
        NULL
 };
 
 static struct option fsck_opts[] = {
-       OPT__VERBOSE(&verbose, "be verbose"),
-       OPT_BOOLEAN(0, "unreachable", &show_unreachable, "show unreachable objects"),
-       OPT_BOOL(0, "dangling", &show_dangling, "show dangling objects"),
-       OPT_BOOLEAN(0, "tags", &show_tags, "report tags"),
-       OPT_BOOLEAN(0, "root", &show_root, "report root nodes"),
-       OPT_BOOLEAN(0, "cache", &keep_cache_objects, "make index objects head nodes"),
-       OPT_BOOLEAN(0, "reflogs", &include_reflogs, "make reflogs head nodes (default)"),
-       OPT_BOOLEAN(0, "full", &check_full, "also consider packs and alternate objects"),
-       OPT_BOOLEAN(0, "strict", &check_strict, "enable more strict checking"),
+       OPT__VERBOSE(&verbose, N_("be verbose")),
+       OPT_BOOLEAN(0, "unreachable", &show_unreachable, N_("show unreachable objects")),
+       OPT_BOOL(0, "dangling", &show_dangling, N_("show dangling objects")),
+       OPT_BOOLEAN(0, "tags", &show_tags, N_("report tags")),
+       OPT_BOOLEAN(0, "root", &show_root, N_("report root nodes")),
+       OPT_BOOLEAN(0, "cache", &keep_cache_objects, N_("make index objects head nodes")),
+       OPT_BOOLEAN(0, "reflogs", &include_reflogs, N_("make reflogs head nodes (default)")),
+       OPT_BOOLEAN(0, "full", &check_full, N_("also consider packs and alternate objects")),
+       OPT_BOOLEAN(0, "strict", &check_strict, N_("enable more strict checking")),
        OPT_BOOLEAN(0, "lost-found", &write_lost_and_found,
-                               "write dangling objects in .git/lost-found"),
-       OPT_BOOL(0, "progress", &show_progress, "show progress"),
+                               N_("write dangling objects in .git/lost-found")),
+       OPT_BOOL(0, "progress", &show_progress, N_("show progress")),
        OPT_END(),
 };
 
index 9b4232c..6be6c8d 100644 (file)
@@ -19,7 +19,7 @@
 #define FAILED_RUN "failed to run %s"
 
 static const char * const builtin_gc_usage[] = {
-       "git gc [options]",
+       N_("git gc [options]"),
        NULL
 };
 
@@ -174,12 +174,12 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
        int quiet = 0;
 
        struct option builtin_gc_options[] = {
-               OPT__QUIET(&quiet, "suppress progress reporting"),
-               { OPTION_STRING, 0, "prune", &prune_expire, "date",
-                       "prune unreferenced objects",
+               OPT__QUIET(&quiet, N_("suppress progress reporting")),
+               { OPTION_STRING, 0, "prune", &prune_expire, N_("date"),
+                       N_("prune unreferenced objects"),
                        PARSE_OPT_OPTARG, NULL, (intptr_t)prune_expire },
-               OPT_BOOLEAN(0, "aggressive", &aggressive, "be more thorough (increased runtime)"),
-               OPT_BOOLEAN(0, "auto", &auto_gc, "enable auto-gc mode"),
+               OPT_BOOLEAN(0, "aggressive", &aggressive, N_("be more thorough (increased runtime)")),
+               OPT_BOOLEAN(0, "auto", &auto_gc, N_("enable auto-gc mode")),
                OPT_END()
        };
 
@@ -217,9 +217,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
                 */
                if (!need_to_gc())
                        return 0;
-               if (quiet)
-                       fprintf(stderr, _("Auto packing the repository for optimum performance.\n"));
-               else
+               if (!quiet)
                        fprintf(stderr,
                                        _("Auto packing the repository for optimum performance. You may also\n"
                                        "run \"git gc\" manually. See "
index 0654e0b..0e1b6c8 100644 (file)
@@ -19,7 +19,7 @@
 #include "dir.h"
 
 static char const * const grep_usage[] = {
-       "git grep [options] [-e] <pattern> [<rev>...] [[--] <path>...]",
+       N_("git grep [options] [-e] <pattern> [<rev>...] [[--] <path>...]"),
        NULL
 };
 
@@ -86,7 +86,7 @@ static pthread_cond_t cond_result;
 static int skip_first_line;
 
 static void add_work(struct grep_opt *opt, enum grep_source_type type,
-                    const char *name, const void *id)
+                    const char *name, const char *path, const void *id)
 {
        grep_lock();
 
@@ -94,7 +94,7 @@ static void add_work(struct grep_opt *opt, enum grep_source_type type,
                pthread_cond_wait(&cond_write, &grep_mutex);
        }
 
-       grep_source_init(&todo[todo_end].source, type, name, id);
+       grep_source_init(&todo[todo_end].source, type, name, path, id);
        if (opt->binary != GREP_BINARY_TEXT)
                grep_source_load_driver(&todo[todo_end].source);
        todo[todo_end].done = 0;
@@ -261,51 +261,12 @@ static int wait_all(void)
 }
 #endif
 
-static int grep_config(const char *var, const char *value, void *cb)
+static int grep_cmd_config(const char *var, const char *value, void *cb)
 {
-       struct grep_opt *opt = cb;
-       char *color = NULL;
-
-       if (userdiff_config(var, value) < 0)
-               return -1;
-
-       if (!strcmp(var, "grep.extendedregexp")) {
-               if (git_config_bool(var, value))
-                       opt->regflags |= REG_EXTENDED;
-               else
-                       opt->regflags &= ~REG_EXTENDED;
-               return 0;
-       }
-
-       if (!strcmp(var, "grep.linenumber")) {
-               opt->linenum = git_config_bool(var, value);
-               return 0;
-       }
-
-       if (!strcmp(var, "color.grep"))
-               opt->color = git_config_colorbool(var, value);
-       else if (!strcmp(var, "color.grep.context"))
-               color = opt->color_context;
-       else if (!strcmp(var, "color.grep.filename"))
-               color = opt->color_filename;
-       else if (!strcmp(var, "color.grep.function"))
-               color = opt->color_function;
-       else if (!strcmp(var, "color.grep.linenumber"))
-               color = opt->color_lineno;
-       else if (!strcmp(var, "color.grep.match"))
-               color = opt->color_match;
-       else if (!strcmp(var, "color.grep.selected"))
-               color = opt->color_selected;
-       else if (!strcmp(var, "color.grep.separator"))
-               color = opt->color_sep;
-       else
-               return git_color_default_config(var, value, cb);
-       if (color) {
-               if (!value)
-                       return config_error_nonbool(var);
-               color_parse(value, var, color);
-       }
-       return 0;
+       int st = grep_config(var, value, cb);
+       if (git_color_default_config(var, value, cb) < 0)
+               st = -1;
+       return st;
 }
 
 static void *lock_and_read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size)
@@ -319,7 +280,8 @@ static void *lock_and_read_sha1_file(const unsigned char *sha1, enum object_type
 }
 
 static int grep_sha1(struct grep_opt *opt, const unsigned char *sha1,
-                    const char *filename, int tree_name_len)
+                    const char *filename, int tree_name_len,
+                    const char *path)
 {
        struct strbuf pathbuf = STRBUF_INIT;
 
@@ -333,7 +295,7 @@ static int grep_sha1(struct grep_opt *opt, const unsigned char *sha1,
 
 #ifndef NO_PTHREADS
        if (use_threads) {
-               add_work(opt, GREP_SOURCE_SHA1, pathbuf.buf, sha1);
+               add_work(opt, GREP_SOURCE_SHA1, pathbuf.buf, path, sha1);
                strbuf_release(&pathbuf);
                return 0;
        } else
@@ -342,7 +304,7 @@ static int grep_sha1(struct grep_opt *opt, const unsigned char *sha1,
                struct grep_source gs;
                int hit;
 
-               grep_source_init(&gs, GREP_SOURCE_SHA1, pathbuf.buf, sha1);
+               grep_source_init(&gs, GREP_SOURCE_SHA1, pathbuf.buf, path, sha1);
                strbuf_release(&pathbuf);
                hit = grep_source(opt, &gs);
 
@@ -362,7 +324,7 @@ static int grep_file(struct grep_opt *opt, const char *filename)
 
 #ifndef NO_PTHREADS
        if (use_threads) {
-               add_work(opt, GREP_SOURCE_FILE, buf.buf, filename);
+               add_work(opt, GREP_SOURCE_FILE, buf.buf, filename, filename);
                strbuf_release(&buf);
                return 0;
        } else
@@ -371,7 +333,7 @@ static int grep_file(struct grep_opt *opt, const char *filename)
                struct grep_source gs;
                int hit;
 
-               grep_source_init(&gs, GREP_SOURCE_FILE, buf.buf, filename);
+               grep_source_init(&gs, GREP_SOURCE_FILE, buf.buf, filename, filename);
                strbuf_release(&buf);
                hit = grep_source(opt, &gs);
 
@@ -427,7 +389,7 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int
                if (cached || (ce->ce_flags & CE_VALID) || ce_skip_worktree(ce)) {
                        if (ce_stage(ce))
                                continue;
-                       hit |= grep_sha1(opt, ce->sha1, ce->name, 0);
+                       hit |= grep_sha1(opt, ce->sha1, ce->name, 0, ce->name);
                }
                else
                        hit |= grep_file(opt, ce->name);
@@ -445,7 +407,8 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int
 }
 
 static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
-                    struct tree_desc *tree, struct strbuf *base, int tn_len)
+                    struct tree_desc *tree, struct strbuf *base, int tn_len,
+                    int check_attr)
 {
        int hit = 0;
        enum interesting match = entry_not_interesting;
@@ -466,7 +429,8 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
                strbuf_add(base, entry.path, te_len);
 
                if (S_ISREG(entry.mode)) {
-                       hit |= grep_sha1(opt, entry.sha1, base->buf, tn_len);
+                       hit |= grep_sha1(opt, entry.sha1, base->buf, tn_len,
+                                        check_attr ? base->buf + tn_len : NULL);
                }
                else if (S_ISDIR(entry.mode)) {
                        enum object_type type;
@@ -481,7 +445,8 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
 
                        strbuf_addch(base, '/');
                        init_tree_desc(&sub, data, size);
-                       hit |= grep_tree(opt, pathspec, &sub, base, tn_len);
+                       hit |= grep_tree(opt, pathspec, &sub, base, tn_len,
+                                        check_attr);
                        free(data);
                }
                strbuf_setlen(base, old_baselen);
@@ -496,7 +461,7 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
                       struct object *obj, const char *name)
 {
        if (obj->type == OBJ_BLOB)
-               return grep_sha1(opt, obj->sha1, name, 0);
+               return grep_sha1(opt, obj->sha1, name, 0, NULL);
        if (obj->type == OBJ_COMMIT || obj->type == OBJ_TREE) {
                struct tree_desc tree;
                void *data;
@@ -519,7 +484,8 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
                        strbuf_addch(&base, ':');
                }
                init_tree_desc(&tree, data, size);
-               hit = grep_tree(opt, pathspec, &tree, &base, base.len);
+               hit = grep_tree(opt, pathspec, &tree, &base, base.len,
+                               obj->type == OBJ_COMMIT);
                strbuf_release(&base);
                free(data);
                return hit;
@@ -670,95 +636,88 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
        int i;
        int dummy;
        int use_index = 1;
-       enum {
-               pattern_type_unspecified = 0,
-               pattern_type_bre,
-               pattern_type_ere,
-               pattern_type_fixed,
-               pattern_type_pcre,
-       };
-       int pattern_type = pattern_type_unspecified;
+       int pattern_type_arg = GREP_PATTERN_TYPE_UNSPECIFIED;
 
        struct option options[] = {
                OPT_BOOLEAN(0, "cached", &cached,
-                       "search in index instead of in the work tree"),
+                       N_("search in index instead of in the work tree")),
                OPT_NEGBIT(0, "no-index", &use_index,
-                        "finds in contents not managed by git", 1),
+                        N_("find in contents not managed by git"), 1),
                OPT_BOOLEAN(0, "untracked", &untracked,
-                       "search in both tracked and untracked files"),
+                       N_("search in both tracked and untracked files")),
                OPT_SET_INT(0, "exclude-standard", &opt_exclude,
-                           "search also in ignored files", 1),
+                           N_("search also in ignored files"), 1),
                OPT_GROUP(""),
                OPT_BOOLEAN('v', "invert-match", &opt.invert,
-                       "show non-matching lines"),
+                       N_("show non-matching lines")),
                OPT_BOOLEAN('i', "ignore-case", &opt.ignore_case,
-                       "case insensitive matching"),
+                       N_("case insensitive matching")),
                OPT_BOOLEAN('w', "word-regexp", &opt.word_regexp,
-                       "match patterns only at word boundaries"),
+                       N_("match patterns only at word boundaries")),
                OPT_SET_INT('a', "text", &opt.binary,
-                       "process binary files as text", GREP_BINARY_TEXT),
+                       N_("process binary files as text"), GREP_BINARY_TEXT),
                OPT_SET_INT('I', NULL, &opt.binary,
-                       "don't match patterns in binary files",
+                       N_("don't match patterns in binary files"),
                        GREP_BINARY_NOMATCH),
-               { OPTION_INTEGER, 0, "max-depth", &opt.max_depth, "depth",
-                       "descend at most <depth> levels", PARSE_OPT_NONEG,
+               { OPTION_INTEGER, 0, "max-depth", &opt.max_depth, N_("depth"),
+                       N_("descend at most <depth> levels"), PARSE_OPT_NONEG,
                        NULL, 1 },
                OPT_GROUP(""),
-               OPT_SET_INT('E', "extended-regexp", &pattern_type,
-                           "use extended POSIX regular expressions",
-                           pattern_type_ere),
-               OPT_SET_INT('G', "basic-regexp", &pattern_type,
-                           "use basic POSIX regular expressions (default)",
-                           pattern_type_bre),
-               OPT_SET_INT('F', "fixed-strings", &pattern_type,
-                           "interpret patterns as fixed strings",
-                           pattern_type_fixed),
-               OPT_SET_INT('P', "perl-regexp", &pattern_type,
-                           "use Perl-compatible regular expressions",
-                           pattern_type_pcre),
+               OPT_SET_INT('E', "extended-regexp", &pattern_type_arg,
+                           N_("use extended POSIX regular expressions"),
+                           GREP_PATTERN_TYPE_ERE),
+               OPT_SET_INT('G', "basic-regexp", &pattern_type_arg,
+                           N_("use basic POSIX regular expressions (default)"),
+                           GREP_PATTERN_TYPE_BRE),
+               OPT_SET_INT('F', "fixed-strings", &pattern_type_arg,
+                           N_("interpret patterns as fixed strings"),
+                           GREP_PATTERN_TYPE_FIXED),
+               OPT_SET_INT('P', "perl-regexp", &pattern_type_arg,
+                           N_("use Perl-compatible regular expressions"),
+                           GREP_PATTERN_TYPE_PCRE),
                OPT_GROUP(""),
-               OPT_BOOLEAN('n', "line-number", &opt.linenum, "show line numbers"),
-               OPT_NEGBIT('h', NULL, &opt.pathname, "don't show filenames", 1),
-               OPT_BIT('H', NULL, &opt.pathname, "show filenames", 1),
+               OPT_BOOLEAN('n', "line-number", &opt.linenum, N_("show line numbers")),
+               OPT_NEGBIT('h', NULL, &opt.pathname, N_("don't show filenames"), 1),
+               OPT_BIT('H', NULL, &opt.pathname, N_("show filenames"), 1),
                OPT_NEGBIT(0, "full-name", &opt.relative,
-                       "show filenames relative to top directory", 1),
+                       N_("show filenames relative to top directory"), 1),
                OPT_BOOLEAN('l', "files-with-matches", &opt.name_only,
-                       "show only filenames instead of matching lines"),
+                       N_("show only filenames instead of matching lines")),
                OPT_BOOLEAN(0, "name-only", &opt.name_only,
-                       "synonym for --files-with-matches"),
+                       N_("synonym for --files-with-matches")),
                OPT_BOOLEAN('L', "files-without-match",
                        &opt.unmatch_name_only,
-                       "show only the names of files without match"),
+                       N_("show only the names of files without match")),
                OPT_BOOLEAN('z', "null", &opt.null_following_name,
-                       "print NUL after filenames"),
+                       N_("print NUL after filenames")),
                OPT_BOOLEAN('c', "count", &opt.count,
-                       "show the number of matches instead of matching lines"),
-               OPT__COLOR(&opt.color, "highlight matches"),
+                       N_("show the number of matches instead of matching lines")),
+               OPT__COLOR(&opt.color, N_("highlight matches")),
                OPT_BOOLEAN(0, "break", &opt.file_break,
-                       "print empty line between matches from different files"),
+                       N_("print empty line between matches from different files")),
                OPT_BOOLEAN(0, "heading", &opt.heading,
-                       "show filename only once above matches from same file"),
+                       N_("show filename only once above matches from same file")),
                OPT_GROUP(""),
-               OPT_CALLBACK('C', "context", &opt, "n",
-                       "show <n> context lines before and after matches",
+               OPT_CALLBACK('C', "context", &opt, N_("n"),
+                       N_("show <n> context lines before and after matches"),
                        context_callback),
                OPT_INTEGER('B', "before-context", &opt.pre_context,
-                       "show <n> context lines before matches"),
+                       N_("show <n> context lines before matches")),
                OPT_INTEGER('A', "after-context", &opt.post_context,
-                       "show <n> context lines after matches"),
-               OPT_NUMBER_CALLBACK(&opt, "shortcut for -C NUM",
+                       N_("show <n> context lines after matches")),
+               OPT_NUMBER_CALLBACK(&opt, N_("shortcut for -C NUM"),
                        context_callback),
                OPT_BOOLEAN('p', "show-function", &opt.funcname,
-                       "show a line with the function name before matches"),
+                       N_("show a line with the function name before matches")),
                OPT_BOOLEAN('W', "function-context", &opt.funcbody,
-                       "show the surrounding function"),
+                       N_("show the surrounding function")),
                OPT_GROUP(""),
-               OPT_CALLBACK('f', NULL, &opt, "file",
-                       "read patterns from file", file_callback),
-               { OPTION_CALLBACK, 'e', NULL, &opt, "pattern",
-                       "match <pattern>", PARSE_OPT_NONEG, pattern_callback },
+               OPT_CALLBACK('f', NULL, &opt, N_("file"),
+                       N_("read patterns from file"), file_callback),
+               { OPTION_CALLBACK, 'e', NULL, &opt, N_("pattern"),
+                       N_("match <pattern>"), PARSE_OPT_NONEG, pattern_callback },
                { OPTION_CALLBACK, 0, "and", &opt, NULL,
-                 "combine patterns specified with -e",
+                 N_("combine patterns specified with -e"),
                  PARSE_OPT_NOARG | PARSE_OPT_NONEG, and_callback },
                OPT_BOOLEAN(0, "or", &dummy, ""),
                { OPTION_CALLBACK, 0, "not", &opt, NULL, "",
@@ -770,19 +729,19 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                  PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
                  close_callback },
                OPT__QUIET(&opt.status_only,
-                          "indicate hit with exit status without output"),
+                          N_("indicate hit with exit status without output")),
                OPT_BOOLEAN(0, "all-match", &opt.all_match,
-                       "show only matches from files that match all patterns"),
+                       N_("show only matches from files that match all patterns")),
                { OPTION_SET_INT, 0, "debug", &opt.debug, NULL,
-                 "show parse tree for grep expression",
+                 N_("show parse tree for grep expression"),
                  PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, 1 },
                OPT_GROUP(""),
                { OPTION_STRING, 'O', "open-files-in-pager", &show_in_pager,
-                       "pager", "show matching files in the pager",
+                       N_("pager"), N_("show matching files in the pager"),
                        PARSE_OPT_OPTARG, NULL, (intptr_t)default_pager },
                OPT_BOOLEAN(0, "ext-grep", &external_grep_allowed__ignored,
-                           "allow calling of grep(1) (ignored by this build)"),
-               { OPTION_CALLBACK, 0, "help-all", &options, NULL, "show usage",
+                           N_("allow calling of grep(1) (ignored by this build)")),
+               { OPTION_CALLBACK, 0, "help-all", &options, NULL, N_("show usage"),
                  PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, help_callback },
                OPT_END()
        };
@@ -794,25 +753,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
        if (argc == 2 && !strcmp(argv[1], "-h"))
                usage_with_options(grep_usage, options);
 
-       memset(&opt, 0, sizeof(opt));
-       opt.prefix = prefix;
-       opt.prefix_length = (prefix && *prefix) ? strlen(prefix) : 0;
-       opt.relative = 1;
-       opt.pathname = 1;
-       opt.pattern_tail = &opt.pattern_list;
-       opt.header_tail = &opt.header_list;
-       opt.regflags = REG_NEWLINE;
-       opt.max_depth = -1;
-
-       strcpy(opt.color_context, "");
-       strcpy(opt.color_filename, "");
-       strcpy(opt.color_function, "");
-       strcpy(opt.color_lineno, "");
-       strcpy(opt.color_match, GIT_COLOR_BOLD_RED);
-       strcpy(opt.color_selected, "");
-       strcpy(opt.color_sep, GIT_COLOR_CYAN);
-       opt.color = -1;
-       git_config(grep_config, &opt);
+       init_grep_defaults();
+       git_config(grep_cmd_config, NULL);
+       grep_init(&opt, prefix);
 
        /*
         * If there is no -- then the paths must exist in the working
@@ -828,28 +771,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                             PARSE_OPT_KEEP_DASHDASH |
                             PARSE_OPT_STOP_AT_NON_OPTION |
                             PARSE_OPT_NO_INTERNAL_HELP);
-       switch (pattern_type) {
-       case pattern_type_fixed:
-               opt.fixed = 1;
-               opt.pcre = 0;
-               break;
-       case pattern_type_bre:
-               opt.fixed = 0;
-               opt.pcre = 0;
-               opt.regflags &= ~REG_EXTENDED;
-               break;
-       case pattern_type_ere:
-               opt.fixed = 0;
-               opt.pcre = 0;
-               opt.regflags |= REG_EXTENDED;
-               break;
-       case pattern_type_pcre:
-               opt.fixed = 0;
-               opt.pcre = 1;
-               break;
-       default:
-               break; /* nothing */
-       }
+       grep_commit_pattern_type(pattern_type_arg, &opt);
 
        if (use_index && !startup_info->have_repository)
                /* die the same way as if we did it at the beginning */
index 33911fd..8d184f1 100644 (file)
@@ -57,8 +57,8 @@ static void hash_stdin_paths(const char *type, int write_objects)
 }
 
 static const char * const hash_object_usage[] = {
-       "git hash-object [-t <type>] [-w] [--path=<file>|--no-filters] [--stdin] [--] <file>...",
-       "git hash-object  --stdin-paths < <list-of-paths>",
+       N_("git hash-object [-t <type>] [-w] [--path=<file>|--no-filters] [--stdin] [--] <file>..."),
+       N_("git hash-object  --stdin-paths < <list-of-paths>"),
        NULL
 };
 
@@ -69,12 +69,12 @@ static int stdin_paths;
 static const char *vpath;
 
 static const struct option hash_object_options[] = {
-       OPT_STRING('t', NULL, &type, "type", "object type"),
-       OPT_BOOLEAN('w', NULL, &write_object, "write the object into the object database"),
-       OPT_BOOLEAN( 0 , "stdin", &hashstdin, "read the object from stdin"),
-       OPT_BOOLEAN( 0 , "stdin-paths", &stdin_paths, "read file names from stdin"),
-       OPT_BOOLEAN( 0 , "no-filters", &no_filters, "store file as is without filters"),
-       OPT_STRING( 0 , "path", &vpath, "file", "process file as it were from this path"),
+       OPT_STRING('t', NULL, &type, N_("type"), N_("object type")),
+       OPT_BOOLEAN('w', NULL, &write_object, N_("write the object into the object database")),
+       OPT_BOOLEAN( 0 , "stdin", &hashstdin, N_("read the object from stdin")),
+       OPT_BOOLEAN( 0 , "stdin-paths", &stdin_paths, N_("read file names from stdin")),
+       OPT_BOOLEAN( 0 , "no-filters", &no_filters, N_("store file as is without filters")),
+       OPT_STRING( 0 , "path", &vpath, N_("file"), N_("process file as it were from this path")),
        OPT_END()
 };
 
index efea4f5..bd86253 100644 (file)
@@ -40,17 +40,17 @@ static int show_all = 0;
 static unsigned int colopts;
 static enum help_format help_format = HELP_FORMAT_NONE;
 static struct option builtin_help_options[] = {
-       OPT_BOOLEAN('a', "all", &show_all, "print all available commands"),
-       OPT_SET_INT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN),
-       OPT_SET_INT('w', "web", &help_format, "show manual in web browser",
+       OPT_BOOLEAN('a', "all", &show_all, N_("print all available commands")),
+       OPT_SET_INT('m', "man", &help_format, N_("show man page"), HELP_FORMAT_MAN),
+       OPT_SET_INT('w', "web", &help_format, N_("show manual in web browser"),
                        HELP_FORMAT_WEB),
-       OPT_SET_INT('i', "info", &help_format, "show info page",
+       OPT_SET_INT('i', "info", &help_format, N_("show info page"),
                        HELP_FORMAT_INFO),
        OPT_END(),
 };
 
 static const char * const builtin_help_usage[] = {
-       "git help [--all] [--man|--web|--info] [command]",
+       N_("git help [--all] [--man|--web|--info] [command]"),
        NULL
 };
 
index 953dd30..43d364b 100644 (file)
@@ -291,7 +291,7 @@ 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 %"PRIu32" unsupported",
+               die(_("pack version %"PRIu32" unsupported"),
                        ntohl(hdr->hdr_version));
 
        nr_objects = ntohl(hdr->hdr_entries);
@@ -1061,7 +1061,8 @@ static void resolve_deltas(void)
                        int ret = pthread_create(&thread_data[i].thread, NULL,
                                                 threaded_second_pass, thread_data + i);
                        if (ret)
-                               die("unable to create thread: %s", strerror(ret));
+                               die(_("unable to create thread: %s"),
+                                   strerror(ret));
                }
                for (i = 0; i < nr_threads; i++)
                        pthread_join(thread_data[i].thread, NULL);
@@ -1108,7 +1109,7 @@ static void conclude_pack(int fix_thin_pack, const char *curr_pack, unsigned cha
                                   * sizeof(*objects));
                f = sha1fd(output_fd, curr_pack);
                fix_unresolved_deltas(f, nr_unresolved);
-               sprintf(msg, "completed with %d local objects",
+               sprintf(msg, _("completed with %d local objects"),
                        nr_objects - nr_objects_initial);
                stop_progress_msg(&progress, msg);
                sha1close(f, tail_sha1, 0);
@@ -1117,8 +1118,8 @@ static void conclude_pack(int fix_thin_pack, const char *curr_pack, unsigned cha
                                         curr_pack, nr_objects,
                                         read_sha1, consumed_bytes-20);
                if (hashcmp(read_sha1, tail_sha1) != 0)
-                       die("Unexpected tail checksum for %s "
-                           "(disk corruption?)", curr_pack);
+                       die(_("Unexpected tail checksum for %s "
+                             "(disk corruption?)"), curr_pack);
        }
        if (nr_deltas != nr_resolved_deltas)
                die(Q_("pack has %d unresolved delta",
@@ -1327,17 +1328,17 @@ static int git_index_pack_config(const char *k, const char *v, void *cb)
        if (!strcmp(k, "pack.indexversion")) {
                opts->version = git_config_int(k, v);
                if (opts->version > 2)
-                       die("bad pack.indexversion=%"PRIu32, opts->version);
+                       die(_("bad pack.indexversion=%"PRIu32), opts->version);
                return 0;
        }
        if (!strcmp(k, "pack.threads")) {
                nr_threads = git_config_int(k, v);
                if (nr_threads < 0)
-                       die("invalid number of threads specified (%d)",
+                       die(_("invalid number of threads specified (%d)"),
                            nr_threads);
 #ifdef NO_PTHREADS
                if (nr_threads != 1)
-                       warning("no threads support, ignoring %s", k);
+                       warning(_("no threads support, ignoring %s"), k);
                nr_threads = 1;
 #endif
                return 0;
@@ -1510,8 +1511,8 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
                                        usage(index_pack_usage);
 #ifdef NO_PTHREADS
                                if (nr_threads != 1)
-                                       warning("no threads support, "
-                                               "ignoring %s", arg);
+                                       warning(_("no threads support, "
+                                                 "ignoring %s"), arg);
                                nr_threads = 1;
 #endif
                        } else if (!prefixcmp(arg, "--pack_header=")) {
index 244fb7f..78aa387 100644 (file)
@@ -464,7 +464,7 @@ static int shared_callback(const struct option *opt, const char *arg, int unset)
 }
 
 static const char *const init_db_usage[] = {
-       "git init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]] [directory]",
+       N_("git init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]] [directory]"),
        NULL
 };
 
@@ -482,17 +482,17 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
        const char *template_dir = NULL;
        unsigned int flags = 0;
        const struct option init_db_options[] = {
-               OPT_STRING(0, "template", &template_dir, "template-directory",
-                               "directory from which templates will be used"),
+               OPT_STRING(0, "template", &template_dir, N_("template-directory"),
+                               N_("directory from which templates will be used")),
                OPT_SET_INT(0, "bare", &is_bare_repository_cfg,
-                               "create a bare repository", 1),
+                               N_("create a bare repository"), 1),
                { OPTION_CALLBACK, 0, "shared", &init_shared_repository,
-                       "permissions",
-                       "specify that the git repository is to be shared amongst several users",
+                       N_("permissions"),
+                       N_("specify that the git repository is to be shared amongst several users"),
                        PARSE_OPT_OPTARG | PARSE_OPT_NONEG, shared_callback, 0},
-               OPT_BIT('q', "quiet", &flags, "be quiet", INIT_DB_QUIET),
-               OPT_STRING(0, "separate-git-dir", &real_git_dir, "gitdir",
-                          "separate git dir from working tree"),
+               OPT_BIT('q', "quiet", &flags, N_("be quiet"), INIT_DB_QUIET),
+               OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
+                          N_("separate git dir from working tree")),
                OPT_END()
        };
 
index dff7921..09cf43e 100644 (file)
@@ -34,8 +34,8 @@ static const char *fmt_patch_subject_prefix = "PATCH";
 static const char *fmt_pretty;
 
 static const char * const builtin_log_usage[] = {
-       "git log [<options>] [<since>..<until>] [[--] <path>...]\n"
-       "   or: git show [options] <object>...",
+       N_("git log [<options>] [<since>..<until>] [[--] <path>...]\n")
+       N_("   or: git show [options] <object>..."),
        NULL
 };
 
@@ -97,9 +97,9 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
        int quiet = 0, source = 0;
 
        const struct option builtin_log_options[] = {
-               OPT_BOOLEAN(0, "quiet", &quiet, "suppress diff output"),
-               OPT_BOOLEAN(0, "source", &source, "show source"),
-               { OPTION_CALLBACK, 0, "decorate", NULL, NULL, "decorate options",
+               OPT_BOOLEAN(0, "quiet", &quiet, N_("suppress diff output")),
+               OPT_BOOLEAN(0, "source", &source, N_("show source")),
+               { OPTION_CALLBACK, 0, "decorate", NULL, NULL, N_("decorate options"),
                  PARSE_OPT_OPTARG, decorate_callback},
                OPT_END()
        };
@@ -696,7 +696,7 @@ static int reopen_stdout(struct commit *commit, const char *subject,
        return 0;
 }
 
-static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids, const char *prefix)
+static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids)
 {
        struct rev_info check_rev;
        struct commit *commit;
@@ -717,7 +717,8 @@ static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids, const cha
        init_patch_ids(ids);
 
        /* given a range a..b get all patch ids for b..a */
-       init_revisions(&check_rev, prefix);
+       init_revisions(&check_rev, rev->prefix);
+       check_rev.max_parents = 1;
        o1->flags ^= UNINTERESTING;
        o2->flags ^= UNINTERESTING;
        add_pending_object(&check_rev, o1, "o1");
@@ -726,10 +727,6 @@ static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids, const cha
                die(_("revision walk setup failed"));
 
        while ((commit = get_revision(&check_rev)) != NULL) {
-               /* ignore merges */
-               if (commit->parents && commit->parents->next)
-                       continue;
-
                add_commit_patch_id(commit, ids);
        }
 
@@ -890,7 +887,7 @@ static const char *set_outdir(const char *prefix, const char *output_directory)
 }
 
 static const char * const builtin_format_patch_usage[] = {
-       "git format-patch [options] [<since> | <revision range>]",
+       N_("git format-patch [options] [<since> | <revision range>]"),
        NULL
 };
 
@@ -1063,61 +1060,61 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
        char *branch_name = NULL;
        const struct option builtin_format_patch_options[] = {
                { OPTION_CALLBACK, 'n', "numbered", &numbered, NULL,
-                           "use [PATCH n/m] even with a single patch",
+                           N_("use [PATCH n/m] even with a single patch"),
                            PARSE_OPT_NOARG, numbered_callback },
                { OPTION_CALLBACK, 'N', "no-numbered", &numbered, NULL,
-                           "use [PATCH] even with multiple patches",
+                           N_("use [PATCH] even with multiple patches"),
                            PARSE_OPT_NOARG, no_numbered_callback },
-               OPT_BOOLEAN('s', "signoff", &do_signoff, "add Signed-off-by:"),
+               OPT_BOOLEAN('s', "signoff", &do_signoff, N_("add Signed-off-by:")),
                OPT_BOOLEAN(0, "stdout", &use_stdout,
-                           "print patches to standard out"),
+                           N_("print patches to standard out")),
                OPT_BOOLEAN(0, "cover-letter", &cover_letter,
-                           "generate a cover letter"),
+                           N_("generate a cover letter")),
                OPT_BOOLEAN(0, "numbered-files", &numbered_files,
-                           "use simple number sequence for output file names"),
-