summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--.mailmap9
-rw-r--r--Documentation/CodingGuidelines8
-rw-r--r--Documentation/Makefile8
-rw-r--r--Documentation/RelNotes/1.5.2.1.txt6
-rw-r--r--Documentation/RelNotes/1.6.0.2.txt6
-rw-r--r--Documentation/RelNotes/1.6.1.3.txt4
-rw-r--r--Documentation/RelNotes/1.6.1.4.txt3
-rw-r--r--Documentation/RelNotes/1.6.1.txt6
-rw-r--r--Documentation/RelNotes/1.7.11.6.txt84
-rw-r--r--Documentation/RelNotes/1.7.11.7.txt46
-rw-r--r--Documentation/RelNotes/1.7.12.1.txt134
-rw-r--r--Documentation/RelNotes/1.7.12.2.txt40
-rw-r--r--Documentation/RelNotes/1.7.12.3.txt34
-rw-r--r--Documentation/RelNotes/1.7.12.4.txt23
-rw-r--r--Documentation/RelNotes/1.8.0.txt267
-rw-r--r--Documentation/asciidoc.conf4
-rw-r--r--Documentation/config.txt15
-rw-r--r--Documentation/diff-config.txt4
-rw-r--r--Documentation/fetch-options.txt3
-rw-r--r--Documentation/git-add.txt2
-rw-r--r--Documentation/git-blame.txt6
-rw-r--r--Documentation/git-branch.txt18
-rw-r--r--Documentation/git-checkout.txt18
-rw-r--r--Documentation/git-cherry-pick.txt5
-rw-r--r--Documentation/git-clean.txt4
-rw-r--r--Documentation/git-clone.txt15
-rw-r--r--Documentation/git-commit.txt6
-rw-r--r--Documentation/git-config.txt12
-rw-r--r--Documentation/git-credential-cache--daemon.txt2
-rw-r--r--Documentation/git-credential-cache.txt2
-rw-r--r--Documentation/git-credential-store.txt2
-rw-r--r--Documentation/git-daemon.txt16
-rw-r--r--Documentation/git-describe.txt4
-rw-r--r--Documentation/git-difftool.txt8
-rw-r--r--Documentation/git-fast-import.txt8
-rw-r--r--Documentation/git-filter-branch.txt22
-rw-r--r--Documentation/git-for-each-ref.txt7
-rw-r--r--Documentation/git-format-patch.txt11
-rw-r--r--Documentation/git-fsck.txt4
-rw-r--r--Documentation/git-grep.txt10
-rw-r--r--Documentation/git-log.txt6
-rw-r--r--Documentation/git-lost-found.txt3
-rw-r--r--Documentation/git-ls-remote.txt5
-rw-r--r--Documentation/git-merge-base.txt28
-rw-r--r--Documentation/git-mergetool.txt3
-rw-r--r--Documentation/git-p4.txt24
-rw-r--r--Documentation/git-pack-refs.txt19
-rw-r--r--Documentation/git-pull.txt1
-rw-r--r--Documentation/git-push.txt10
-rw-r--r--Documentation/git-rebase.txt5
-rw-r--r--Documentation/git-remote.txt3
-rw-r--r--Documentation/git-replace.txt5
-rw-r--r--Documentation/git-shortlog.txt3
-rw-r--r--Documentation/git-submodule.txt10
-rw-r--r--Documentation/git-tag.txt5
-rw-r--r--Documentation/git.txt78
-rw-r--r--Documentation/gitattributes.txt9
-rw-r--r--Documentation/gitcli.txt39
-rw-r--r--Documentation/gitcore-tutorial.txt9
-rw-r--r--Documentation/gitignore.txt36
-rw-r--r--Documentation/gittutorial.txt8
-rw-r--r--Documentation/merge-strategies.txt3
-rw-r--r--Documentation/pretty-formats.txt3
-rw-r--r--Documentation/pretty-options.txt4
-rw-r--r--Documentation/rev-list-options.txt78
-rw-r--r--Documentation/revisions.txt9
-rw-r--r--Documentation/technical/api-argv-array.txt4
-rw-r--r--Documentation/technical/api-sha1-array.txt3
-rw-r--r--Documentation/technical/api-string-list.txt75
-rw-r--r--Documentation/technical/pack-protocol.txt6
-rw-r--r--Documentation/urls.txt8
-rw-r--r--Documentation/user-manual.conf2
-rw-r--r--Documentation/user-manual.txt9
-rwxr-xr-xGIT-VERSION-GEN2
-rw-r--r--Makefile143
l---------RelNotes2
-rw-r--r--abspath.c9
-rw-r--r--archive-zip.c49
-rw-r--r--archive.c38
-rw-r--r--argv-array.c11
-rw-r--r--argv-array.h1
-rw-r--r--attr.c7
-rw-r--r--bisect.c2
-rw-r--r--builtin.h4
-rw-r--r--builtin/add.c29
-rw-r--r--builtin/apply.c71
-rw-r--r--builtin/archive.c12
-rw-r--r--builtin/bisect--helper.c6
-rw-r--r--builtin/blame.c153
-rw-r--r--builtin/branch.c150
-rw-r--r--builtin/cat-file.c22
-rw-r--r--builtin/check-attr.c12
-rw-r--r--builtin/checkout-index.c24
-rw-r--r--builtin/checkout.c315
-rw-r--r--builtin/clean.c18
-rw-r--r--builtin/clone.c125
-rw-r--r--builtin/column.c16
-rw-r--r--builtin/commit.c199
-rw-r--r--builtin/config.c68
-rw-r--r--builtin/count-objects.c4
-rw-r--r--builtin/describe.c28
-rw-r--r--builtin/diff.c11
-rw-r--r--builtin/fast-export.c28
-rw-r--r--builtin/fetch-pack.c189
-rw-r--r--builtin/fetch.c116
-rw-r--r--builtin/fmt-merge-msg.c16
-rw-r--r--builtin/for-each-ref.c22
-rw-r--r--builtin/fsck.c24
-rw-r--r--builtin/gc.c16
-rw-r--r--builtin/grep.c206
-rw-r--r--builtin/hash-object.c16
-rw-r--r--builtin/help.c10
-rw-r--r--builtin/index-pack.c21
-rw-r--r--builtin/init-db.c18
-rw-r--r--builtin/log.c106
-rw-r--r--builtin/ls-files.c54
-rw-r--r--builtin/ls-remote.c2
-rw-r--r--builtin/ls-tree.c22
-rw-r--r--builtin/mailinfo.c48
-rw-r--r--builtin/merge-base.c34
-rw-r--r--builtin/merge-file.c20
-rw-r--r--builtin/merge.c51
-rw-r--r--builtin/mktree.c8
-rw-r--r--builtin/mv.c10
-rw-r--r--builtin/name-rev.c22
-rw-r--r--builtin/notes.c127
-rw-r--r--builtin/pack-objects.c64
-rw-r--r--builtin/pack-refs.c6
-rw-r--r--builtin/prune-packed.c6
-rw-r--r--builtin/prune.c15
-rw-r--r--builtin/push.c63
-rw-r--r--builtin/read-tree.c38
-rw-r--r--builtin/receive-pack.c52
-rw-r--r--builtin/remote.c86
-rw-r--r--builtin/replace.c12
-rw-r--r--builtin/rerere.c4
-rw-r--r--builtin/reset.c20
-rw-r--r--builtin/rev-parse.c34
-rw-r--r--builtin/revert.c40
-rw-r--r--builtin/rm.c14
-rw-r--r--builtin/send-pack.c15
-rw-r--r--builtin/shortlog.c14
-rw-r--r--builtin/show-branch.c42
-rw-r--r--builtin/show-ref.c28
-rw-r--r--builtin/symbolic-ref.c8
-rw-r--r--builtin/tag.c56
-rw-r--r--builtin/update-index.c56
-rw-r--r--builtin/update-ref.c10
-rw-r--r--builtin/update-server-info.c4
-rw-r--r--builtin/verify-pack.c6
-rw-r--r--builtin/verify-tag.c4
-rw-r--r--builtin/write-tree.c10
-rw-r--r--cache.h11
-rw-r--r--combine-diff.c4
-rw-r--r--command-list.txt3
-rw-r--r--commit.c311
-rw-r--r--commit.h3
-rw-r--r--compat/mkdir.c24
-rw-r--r--compat/poll/poll.c (renamed from compat/win32/poll.c)14
-rw-r--r--compat/poll/poll.h (renamed from compat/win32/poll.h)0
-rw-r--r--compat/precompose_utf8.c44
-rw-r--r--config.c10
-rw-r--r--config.mak.in49
-rw-r--r--configure.ac159
-rw-r--r--connect.c45
-rw-r--r--contrib/ciabot/INSTALL54
-rw-r--r--contrib/ciabot/README3
-rwxr-xr-xcontrib/ciabot/ciabot.py179
-rwxr-xr-xcontrib/ciabot/ciabot.sh133
-rw-r--r--contrib/completion/git-completion.bash15
-rw-r--r--contrib/completion/git-prompt.sh7
-rw-r--r--contrib/credential/gnome-keyring/.gitignore1
-rw-r--r--contrib/credential/gnome-keyring/Makefile24
-rw-r--r--contrib/credential/gnome-keyring/git-credential-gnome-keyring.c445
-rw-r--r--contrib/credential/wincred/Makefile14
-rw-r--r--contrib/credential/wincred/git-credential-wincred.c357
-rw-r--r--contrib/examples/builtin-fetch--tool.c2
-rwxr-xr-xcontrib/git-jump/git-jump4
-rwxr-xr-xcontrib/hooks/post-receive-email2
-rw-r--r--daemon.c77
-rw-r--r--diff-lib.c20
-rw-r--r--diff-no-index.c5
-rw-r--r--diff.c42
-rw-r--r--diff.h8
-rw-r--r--diffcore-rename.c2
-rw-r--r--diffcore.h2
-rw-r--r--dir.c6
-rw-r--r--fast-import.c2
-rw-r--r--fetch-pack.h20
-rw-r--r--fsck.c8
-rw-r--r--gettext.c15
-rw-r--r--gettext.h7
-rwxr-xr-xgit-am.sh4
-rw-r--r--git-compat-util.h39
-rwxr-xr-xgit-cvsimport.perl33
-rwxr-xr-xgit-difftool.perl305
-rwxr-xr-xgit-gui/GIT-VERSION-GEN2
-rwxr-xr-xgit-gui/git-gui.sh36
-rw-r--r--git-gui/lib/commit.tcl3
-rw-r--r--git-gui/lib/status_bar.tcl1
-rw-r--r--git-gui/macosx/AppMain.tcl4
-rw-r--r--git-gui/po/de.po38
-rw-r--r--git-gui/po/fr.po2
-rw-r--r--git-gui/po/git-gui.pot2
-rw-r--r--git-gui/po/hu.po2
-rw-r--r--git-gui/po/it.po2
-rw-r--r--git-gui/po/ja.po2
-rw-r--r--git-gui/po/nb.po2
-rw-r--r--git-gui/po/pt_br.po2
-rw-r--r--git-gui/po/ru.po2
-rw-r--r--git-gui/po/sv.po2
-rw-r--r--git-mergetool--lib.sh42
-rwxr-xr-xgit-mergetool.sh581
-rwxr-xr-xgit-p4.py314
-rw-r--r--git-rebase--interactive.sh60
-rwxr-xr-xgit-rebase.sh13
-rwxr-xr-xgit-send-email.perl28
-rw-r--r--git-sh-setup.sh4
-rwxr-xr-xgit-stash.sh1
-rwxr-xr-xgit-submodule.sh45
-rwxr-xr-xgit-svn.perl92
-rwxr-xr-xgitk-git/gitk22
-rwxr-xr-xgitweb/gitweb.perl7
-rw-r--r--graph.c32
-rw-r--r--graph.h27
-rw-r--r--grep.c131
-rw-r--r--grep.h22
-rw-r--r--http-push.c3
-rw-r--r--http-walker.c4
-rw-r--r--http.c53
-rw-r--r--http.h2
-rw-r--r--ident.c10
-rw-r--r--ll-merge.c32
-rw-r--r--merge-recursive.c35
-rw-r--r--mergetools/codecompare25
-rw-r--r--mergetools/defaults28
-rw-r--r--notes-merge.c6
-rw-r--r--notes.c14
-rw-r--r--notes.h14
-rw-r--r--pager.c18
-rw-r--r--parse-options.h2
-rw-r--r--patch-ids.c3
-rw-r--r--path.c28
-rw-r--r--perl/Git/SVN.pm183
-rw-r--r--perl/Git/SVN/Editor.pm25
-rw-r--r--perl/Git/SVN/Fetcher.pm2
-rw-r--r--perl/Git/SVN/GlobSpec.pm4
-rw-r--r--perl/Git/SVN/Migration.pm6
-rw-r--r--perl/Git/SVN/Ra.pm94
-rw-r--r--perl/Git/SVN/Utils.pm175
-rw-r--r--po/TEAMS3
-rw-r--r--po/de.po736
-rw-r--r--po/git.pot4678
-rw-r--r--po/sv.po4901
-rw-r--r--po/vi.po6245
-rw-r--r--po/zh_CN.po4831
-rw-r--r--read-cache.c10
-rw-r--r--remote-curl.c50
-rw-r--r--rerere.c2
-rw-r--r--rerere.h1
-rw-r--r--revision.c78
-rw-r--r--revision.h6
-rw-r--r--run-command.c25
-rw-r--r--run-command.h1
-rw-r--r--sequencer.c76
-rw-r--r--sequencer.h8
-rw-r--r--setup.c8
-rw-r--r--sha1-array.c2
-rw-r--r--sha1-array.h1
-rw-r--r--sha1_file.c26
-rw-r--r--strbuf.c13
-rw-r--r--strbuf.h4
-rw-r--r--string-list.c127
-rw-r--r--string-list.h71
-rw-r--r--submodule.c46
-rw-r--r--submodule.h3
-rw-r--r--symlinks.c7
-rw-r--r--t/Git-SVN/Utils/add_path_to_url.t27
-rw-r--r--t/Git-SVN/Utils/canonicalize_url.t26
-rw-r--r--t/Git-SVN/Utils/collapse_dotdot.t23
-rw-r--r--t/Git-SVN/Utils/join_paths.t32
-rw-r--r--t/README9
-rwxr-xr-xt/lib-credential.sh4
-rw-r--r--t/lib-git-p4.sh24
-rw-r--r--t/lib-httpd.sh39
-rw-r--r--t/lib-httpd/apache.conf25
-rw-r--r--t/perf/.gitignore5
-rw-r--r--t/perf/perf-lib.sh3
-rwxr-xr-xt/t0000-basic.sh28
-rwxr-xr-xt/t0003-attributes.sh10
-rwxr-xr-xt/t0006-date.sh2
-rwxr-xr-xt/t0040-parse-options.sh34
-rwxr-xr-xt/t0050-filesystem.sh64
-rwxr-xr-xt/t0060-path-utils.sh59
-rwxr-xr-xt/t0063-string-list.sh121
-rwxr-xr-xt/t0070-fundamental.sh5
-rwxr-xr-xt/t1300-repo-config.sh2
-rwxr-xr-xt/t1450-fsck.sh30
-rwxr-xr-xt/t1502-rev-parse-parseopt.sh2
-rwxr-xr-xt/t1506-rev-parse-diagnosis.sh14
-rwxr-xr-xt/t2006-checkout-index-basic.sh4
-rwxr-xr-xt/t2107-update-index-basic.sh23
-rwxr-xr-xt/t3004-ls-files-basic.sh4
-rwxr-xr-xt/t3200-branch.sh74
-rwxr-xr-xt/t3300-funny-names.sh24
-rwxr-xr-xt/t3401-rebase-partial.sh18
-rwxr-xr-xt/t3404-rebase-interactive.sh29
-rwxr-xr-xt/t3501-revert-cherry-pick.sh4
-rwxr-xr-xt/t3505-cherry-pick-empty.sh5
-rwxr-xr-xt/t3507-cherry-pick-conflict.sh32
-rwxr-xr-xt/t3508-cherry-pick-many-commits.sh15
-rwxr-xr-xt/t3510-cherry-pick-sequence.sh6
-rwxr-xr-xt/t3902-quoted.sh31
-rwxr-xr-xt/t3903-stash.sh2
-rwxr-xr-xt/t3910-mac-os-precompose.sh281
-rwxr-xr-xt/t4006-diff-mode.sh8
-rwxr-xr-xt/t4012-diff-binary.sh4
-rwxr-xr-xt/t4016-diff-quote.sh20
-rwxr-xr-xt/t4018-diff-funcname.sh2
-rwxr-xr-xt/t4022-diff-rewrite.sh30
-rwxr-xr-xt/t4034-diff-words.sh1
-rw-r--r--t/t4034/ada/expect27
-rw-r--r--t/t4034/ada/post13
-rw-r--r--t/t4034/ada/pre13
-rwxr-xr-xt/t4054-diff-bogus-tree.sh83
-rwxr-xr-xt/t4055-diff-context.sh92
-rwxr-xr-xt/t4103-apply-binary.sh54
-rwxr-xr-xt/t4120-apply-popt.sh4
-rwxr-xr-xt/t4133-apply-filenames.sh4
-rwxr-xr-xt/t4200-rerere.sh4
-rwxr-xr-xt/t4202-log.sh19
-rwxr-xr-xt/t4205-log-pretty-formats.sh4
-rwxr-xr-xt/t5100-mailinfo.sh2
-rw-r--r--t/t5100/info00175
-rw-r--r--t/t5100/msg00172
-rw-r--r--t/t5100/patch00176
-rw-r--r--t/t5100/sample.mbox16
-rwxr-xr-xt/t5300-pack-object.sh4
-rwxr-xr-xt/t5400-send-pack.sh34
-rwxr-xr-xt/t5500-fetch-pack.sh47
-rwxr-xr-xt/t5504-fetch-receive-strict.sh2
-rwxr-xr-xt/t5505-remote.sh32
-rwxr-xr-xt/t5514-fetch-multiple.sh30
-rwxr-xr-xt/t5530-upload-pack-error.sh4
-rwxr-xr-xt/t5540-http-push.sh19
-rwxr-xr-xt/t5541-http-push.sh31
-rwxr-xr-xt/t5550-http-fetch.sh77
-rwxr-xr-xt/t5551-http-fetch.sh37
-rwxr-xr-xt/t5709-clone-refspec.sh156
-rwxr-xr-xt/t5800-remote-helpers.sh2
-rwxr-xr-xt/t6037-merge-ours-theirs.sh14
-rwxr-xr-xt/t6300-for-each-ref.sh10
-rwxr-xr-xt/t6500-gc.sh4
-rwxr-xr-xt/t7007-show.sh12
-rwxr-xr-xt/t7400-submodule-basic.sh28
-rwxr-xr-xt/t7406-submodule-update.sh28
-rwxr-xr-xt/t7508-status.sh2
-rwxr-xr-xt/t7600-merge.sh2
-rwxr-xr-xt/t7610-mergetool.sh51
-rwxr-xr-xt/t7800-difftool.sh11
-rwxr-xr-xt/t7810-grep.sh313
-rwxr-xr-xt/t8004-blame-with-conflicts.sh2
-rwxr-xr-xt/t9001-send-email.sh13
-rwxr-xr-xt/t9107-git-svn-migrate.sh6
-rwxr-xr-xt/t9118-git-svn-funky-branch-names.sh9
-rwxr-xr-xt/t9154-git-svn-fancy-glob.sh9
-rwxr-xr-xt/t9164-git-svn-dcommit-concurrent.sh (renamed from t/t9164-git-svn-dcommit-concrrent.sh)8
-rwxr-xr-xt/t9165-git-svn-fetch-merge-branch-of-branch.sh60
-rwxr-xr-xt/t9166-git-svn-fetch-merge-branch-of-branch2.sh53
-rwxr-xr-xt/t9801-git-p4-branch.sh77
-rwxr-xr-xt/t9805-git-p4-skip-submit-edit.sh2
-rwxr-xr-xt/t9807-git-p4-submit.sh65
-rwxr-xr-xt/t9809-git-p4-client-view.sh17
-rwxr-xr-xt/t9810-git-p4-rcs.sh50
-rwxr-xr-xt/t9815-git-p4-submit-fail.sh429
-rwxr-xr-xt/t9902-completion.sh60
-rw-r--r--t/test-lib-functions.sh90
-rw-r--r--t/test-lib.sh159
-rw-r--r--test-regex.c20
-rw-r--r--test-string-list.c123
-rw-r--r--trace.c2
-rw-r--r--transport.c12
-rw-r--r--transport.h1
-rw-r--r--tree-diff.c11
-rw-r--r--upload-pack.c7
-rw-r--r--userdiff.c9
-rw-r--r--version.c21
-rw-r--r--version.h1
-rw-r--r--wrapper.c13
-rw-r--r--wt-status.c52
-rw-r--r--wt-status.h2
392 files changed, 27847 insertions, 7624 deletions
diff --git a/.gitignore b/.gitignore
index 51294d6..f702415 100644
--- a/.gitignore
+++ b/.gitignore
@@ -190,10 +190,12 @@
/test-mktemp
/test-parse-options
/test-path-utils
+/test-regex
/test-revision-walking
/test-run-command
/test-sha1
/test-sigchain
+/test-string-list
/test-subprocess
/test-svn-fe
/common-cmds.h
diff --git a/.mailmap b/.mailmap
index 6303782..bcf4f87 100644
--- 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>
diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines
index 4557711..57da6aa 100644
--- a/Documentation/CodingGuidelines
+++ b/Documentation/CodingGuidelines
@@ -76,11 +76,19 @@ For shell scripts specifically (not exhaustive):
- We do not use Process Substitution <(list) or >(list).
+ - Do not write control structures on a single line with semicolon.
+ "then" should be on the next line for if statements, and "do"
+ should be on the next line for "while" and "for".
+
- We prefer "test" over "[ ... ]".
- We do not write the noiseword "function" in front of shell
functions.
+ - We prefer a space between the function name and the parentheses. The
+ opening "{" should also be on the same line.
+ E.g.: my_function () {
+
- As to use of grep, stick to a subset of BRE (namely, no \{m,n\},
[::], [==], nor [..]) for portability.
diff --git a/Documentation/Makefile b/Documentation/Makefile
index 063fa69..267dfe1 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -44,9 +44,10 @@ man5dir=$(mandir)/man5
man7dir=$(mandir)/man7
# DESTDIR=
-ASCIIDOC=asciidoc
+ASCIIDOC = asciidoc
ASCIIDOC_EXTRA =
MANPAGE_XSL = manpage-normal.xsl
+XMLTO = xmlto
XMLTO_EXTRA =
INSTALL?=install
RM ?= rm -f
@@ -245,7 +246,7 @@ manpage-base-url.xsl: manpage-base-url.xsl.in
%.1 %.5 %.7 : %.xml manpage-base-url.xsl
$(QUIET_XMLTO)$(RM) $@ && \
- xmlto -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $<
+ $(XMLTO) -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $<
%.xml : %.txt
$(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
@@ -344,4 +345,7 @@ require-htmlrepo::
quick-install-html: require-htmlrepo
'$(SHELL_PATH_SQ)' ./install-doc-quick.sh $(HTML_REPO) $(DESTDIR)$(htmldir)
+print-man1:
+ @for i in $(MAN1_TXT); do echo $$i; done
+
.PHONY: FORCE
diff --git a/Documentation/RelNotes/1.5.2.1.txt b/Documentation/RelNotes/1.5.2.1.txt
index ebf20e2..d41984d 100644
--- a/Documentation/RelNotes/1.5.2.1.txt
+++ b/Documentation/RelNotes/1.5.2.1.txt
@@ -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
diff --git a/Documentation/RelNotes/1.6.0.2.txt b/Documentation/RelNotes/1.6.0.2.txt
index e1e24b3..7d8fb85 100644
--- a/Documentation/RelNotes/1.6.0.2.txt
+++ b/Documentation/RelNotes/1.6.0.2.txt
@@ -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
diff --git a/Documentation/RelNotes/1.6.1.3.txt b/Documentation/RelNotes/1.6.1.3.txt
index 6f0bde1..cd08d81 100644
--- a/Documentation/RelNotes/1.6.1.3.txt
+++ b/Documentation/RelNotes/1.6.1.3.txt
@@ -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..
diff --git a/Documentation/RelNotes/1.6.1.4.txt b/Documentation/RelNotes/1.6.1.4.txt
index 0ce6316..ccbad79 100644
--- a/Documentation/RelNotes/1.6.1.4.txt
+++ b/Documentation/RelNotes/1.6.1.4.txt
@@ -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..
diff --git a/Documentation/RelNotes/1.6.1.txt b/Documentation/RelNotes/1.6.1.txt
index adb7cca..7b152a6 100644
--- a/Documentation/RelNotes/1.6.1.txt
+++ b/Documentation/RelNotes/1.6.1.txt
@@ -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.7.11.6.txt b/Documentation/RelNotes/1.7.11.6.txt
new file mode 100644
index 0000000..ba7d3c3
--- /dev/null
+++ b/Documentation/RelNotes/1.7.11.6.txt
@@ -0,0 +1,84 @@
+Git v1.7.11.6 Release Notes
+===========================
+
+Fixes since v1.7.11.5
+---------------------
+
+ * "ciabot" script (in contrib/) has been updated with extensive
+ documentation.
+
+ * "git foo" errored out with "Not a directory" when the user had a
+ non-directory on $PATH, and worse yet it masked an alias "foo" from
+ running.
+
+ * When the user exports a non-default IFS without HT, scripts that
+ rely on being able to parse "ls-files -s | while read a b c..."
+ started to fail. Protect them from such a misconfiguration.
+
+ * When the user gives an argument that can be taken as both a
+ revision name and a pathname without disambiguating with "--", we
+ used to give a help message "Use '--' to separate". The message
+ has been clarified to show where that '--' goes on the command
+ line.
+
+ * Documentation for the configuration file format had a confusing
+ example.
+
+ * Older parts of the documentation described as if having a regular
+ file in .git/refs/ hierarchy were the only way to have branches and
+ tags, which is not true for quite some time.
+
+ * It was generally understood that "--long-option"s to many of our
+ subcommands can be abbreviated to the unique prefix, but it was not
+ easy to find it described for new readers of the documentation set.
+
+ * The "--topo-order", "--date-order" (and the lack of either means
+ the default order) options to "rev-list" and "log" family of
+ commands were poorly described in the documentation.
+
+ * "git commit --amend" let the user edit the log message and then
+ died when the human-readable committer name was given
+ insufficiently by getpwent(3).
+
+ * The exit status code from "git config" was way overspecified while
+ being incorrect. The implementation has been updated to give the
+ documented status for a case that was documented, and introduce a
+ new code for "all other errors".
+
+ * The output from "git diff -B" for a file that ends with an
+ incomplete line did not put "\ No newline..." on a line of its own.
+
+ * "git diff" had a confusion between taking data from a path in the
+ working tree and taking data from an object that happens to have
+ name 0{40} recorded in a tree.
+
+ * The "--rebase" option to "git pull" can be abbreviated to "-r",
+ but we didn't document it.
+
+ * When "git push" triggered the automatic gc on the receiving end, a
+ message from "git prune" that said it was removing cruft leaked to
+ the standard output, breaking the communication protocol.
+
+ * The reflog entries left by "git rebase" and "git rebase -i" were
+ inconsistent (the interactive one gave an abbreviated object name).
+
+ * "git send-email" did not unquote encoded words that appear on the
+ header correctly, and lost "_" from strings.
+
+ * "git stash apply/pop" did not trigger "rerere" upon conflicts
+ unlike other mergy operations.
+
+ * "git submodule <cmd> path" did not error out when the path to the
+ submodule was misspelt.
+
+ * "git submodule update -f" did not update paths in the working tree
+ that has local changes.
+ (merge 01d4721 sz/submodule-force-update later to maint).
+
+ * "gitweb" when used with PATH_INFO failed to notice directories with
+ SP (and other characters that need URL-style quoting) in them.
+
+ * Fallback 'getpass' implementation made unportable use of stdio API.
+
+ * A utility shell function test_seq has been added as a replacement
+ for the 'seq' utility found on some platforms.
diff --git a/Documentation/RelNotes/1.7.11.7.txt b/Documentation/RelNotes/1.7.11.7.txt
new file mode 100644
index 0000000..e7e79d9
--- /dev/null
+++ b/Documentation/RelNotes/1.7.11.7.txt
@@ -0,0 +1,46 @@
+Git v1.7.11.7 Release Notes
+===========================
+
+Fixes since v1.7.11.6
+---------------------
+
+ * The synopsis said "checkout [-B branch]" to make it clear the
+ branch name is a parameter to the option, but the heading for the
+ option description was "-B::", not "-B branch::", making the
+ documentation misleading.
+
+ * 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. A new test has been added to check this.
+
+ * "git apply -p0" did not parse pathnames on "diff --git" line
+ correctly. This caused patches that had pathnames in no other
+ places to be mistakenly rejected (most notably, binary patch that
+ does not rename nor change mode). Textual patches, renames or mode
+ changes have preimage and postimage pathnames in different places
+ in a form that can be parsed unambiguously and did not suffer from
+ this problem.
+
+ * After "gitk" showed the contents of a tag, neither "Reread
+ references" nor "Reload" did not update what is shown as the
+ contents of it, when the user overwrote the tag with "git tag -f".
+
+ * "git for-each-ref" did not currectly support more than one --sort
+ option.
+
+ * "git log .." errored out saying it is both rev range and a path
+ when there is no disambiguating "--" is on the command line.
+ Update the command line parser to interpret ".." as a path in such
+ a case.
+
+ * Pushing to smart HTTP server with recent Git fails without having
+ the username in the URL to force authentication, if the server is
+ configured to allow GET anonymously, while requiring authentication
+ for POST.
+
+ * "git show --format='%ci'" did not give timestamp correctly for
+ commits created without human readable name on "committer" line.
+ (merge e27ddb6 jc/maint-ident-missing-human-name later to maint).
+
+ * "git show --quiet" ought to be a synonym for "git show -s", but
+ wasn't.
diff --git a/Documentation/RelNotes/1.7.12.1.txt b/Documentation/RelNotes/1.7.12.1.txt
new file mode 100644
index 0000000..b8f04af
--- /dev/null
+++ b/Documentation/RelNotes/1.7.12.1.txt
@@ -0,0 +1,134 @@
+Git 1.7.12.1 Release Notes
+==========================
+
+Fixes since v1.7.12
+-------------------
+
+ * "git apply -p0" did not parse pathnames on "diff --git" line
+ correctly. This caused patches that had pathnames in no other
+ places to be mistakenly rejected (most notably, binary patch that
+ does not rename nor change mode). Textual patches, renames or mode
+ changes have preimage and postimage pathnames in different places
+ in a form that can be parsed unambiguously and did not suffer from
+ this problem.
+
+ * "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.
+
+ * "git commit --amend" let the user edit the log message and then
+ died when the human-readable committer name was given
+ insufficiently by getpwent(3).
+
+ * Some capabilities were asked by fetch-pack even when upload-pack
+ did not advertise that they are available. fetch-pack has been
+ fixed not to do so.
+
+ * "git diff" had a confusion between taking data from a path in the
+ working tree and taking data from an object that happens to have
+ name 0{40} recorded in a tree.
+
+ * "git for-each-ref" did not correctly support more than one --sort
+ option.
+
+ * "git log .." errored out saying it is both rev range and a path
+ when there is no disambiguating "--" is on the command line.
+ Update the command line parser to interpret ".." as a path in such
+ a case.
+
+ * The "--topo-order", "--date-order" (and the lack of either means
+ the default order) options to "rev-list" and "log" family of
+ commands were poorly described in the documentation.
+
+ * "git prune" without "-v" used to warn about leftover temporary
+ files (which is an indication of an earlier aborted operation).
+
+ * Pushing to smart HTTP server with recent Git fails without having
+ the username in the URL to force authentication, if the server is
+ configured to allow GET anonymously, while requiring authentication
+ for POST.
+
+ * The reflog entries left by "git rebase" and "git rebase -i" were
+ inconsistent (the interactive one gave an abbreviated object name).
+
+ * When "git push" triggered the automatic gc on the receiving end, a
+ message from "git prune" that said it was removing cruft leaked to
+ the standard output, breaking the communication protocol.
+
+ * "git show --quiet" ought to be a synonym for "git show -s", but
+ wasn't.
+
+ * "git show --format='%ci'" did not give timestamp correctly for
+ commits created without human readable name on "committer" line.
+
+ * "git send-email" did not unquote encoded words that appear on the
+ header correctly, and lost "_" from strings.
+
+ * The interactive prompt "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.
+
+ * "gitweb" when used with PATH_INFO failed to notice directories with
+ SP (and other characters that need URL-style quoting) in them.
+
+ * When the user gives an argument that can be taken as both a
+ revision name and a pathname without disambiguating with "--", we
+ used to give a help message "Use '--' to separate". The message
+ has been clarified to show where that '--' goes on the command
+ line.
+
+ * When the user exports a non-default IFS without HT, scripts that
+ rely on being able to parse "ls-files -s | while read a b c..."
+ started to fail. Protect them from such a misconfiguration.
+
+ * 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.
+
+ * After "gitk" showed the contents of a tag, neither "Reread
+ references" nor "Reload" did not update what is shown as the
+ contents of it, when the user overwrote the tag with "git tag -f".
+
+ * "ciabot" script (in contrib/) has been updated with extensive
+ documentation.
+
+ * "git-jump" script (in contrib/) did not work well when
+ diff.noprefix or diff.mnemonicprefix is in effect.
+
+ * Older parts of the documentation described as if having a regular
+ file in .git/refs/ hierarchy were the only way to have branches and
+ tags, which is not true for quite some time.
+
+ * A utility shell function test_seq has been added as a replacement
+ for the 'seq' utility found on some platforms.
+
+ * Compatibility wrapper to learn the maximum number of file
+ descriptors we can open around sysconf(_SC_OPEN_MAX) and
+ getrlimit(RLIMIT_NO_FILE) has been introduced for portability.
+
+ * We used curl_easy_strerror() without checking version of cURL,
+ breaking the build for versions before curl 7.12.0.
+
+ * Code to work around MacOS X UTF-8 gotcha has been cleaned up.
+
+ * Fallback 'getpass' implementation made unportable use of stdio API.
+
+ * The "--rebase" option to "git pull" can be abbreviated to "-r",
+ but we didn't document it.
+
+ * It was generally understood that "--long-option"s to many of our
+ subcommands can be abbreviated to the unique prefix, but it was not
+ easy to find it described for new readers of the documentation set.
+
+ * The synopsis said "checkout [-B branch]" to make it clear the
+ branch name is a parameter to the option, but the heading for the
+ option description was "-B::", not "-B branch::", making the
+ documentation misleading.
+
+Also contains numerous documentation updates.
diff --git a/Documentation/RelNotes/1.7.12.2.txt b/Documentation/RelNotes/1.7.12.2.txt
new file mode 100644
index 0000000..6925574
--- /dev/null
+++ b/Documentation/RelNotes/1.7.12.2.txt
@@ -0,0 +1,40 @@
+Git 1.7.12.2 Release Notes
+==========================
+
+Fixes since v1.7.12.1
+---------------------
+
+ * When "git am" is fed an input that has multiple "Content-type: ..."
+ header, it did not grok charset= attribute correctly.
+
+ * 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.
+
+ * "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.
+
+ * "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 combination "--all --tags" makes
+ much less sense than "--all --no-tags").
+
+ * "git log/diff/format-patch --stat" showed the "N line(s) added"
+ comment in user's locale and caused careless submitters to send
+ patches with such a line in them to projects whose project language
+ is not their language, mildly irritating others. Localization to
+ the line has been disabled for now.
+
+ * "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 subcommand to remove the definition of a remote in "git remote"
+ was named "rm" even though all other subcommands were spelled out.
+ Introduce "git remote remove" to remove confusion, and keep "rm" as
+ a backward compatible synonym.
+
+Also contains a handful of documentation updates.
diff --git a/Documentation/RelNotes/1.7.12.3.txt b/Documentation/RelNotes/1.7.12.3.txt
new file mode 100644
index 0000000..ecda427
--- /dev/null
+++ b/Documentation/RelNotes/1.7.12.3.txt
@@ -0,0 +1,34 @@
+Git 1.7.12.3 Release Notes
+==========================
+
+Fixes since v1.7.12.2
+---------------------
+
+ * "git am" mishandled a patch attached as application/octet-stream
+ (e.g. not text/*); Content-Transfer-Encoding (e.g. base64) was not
+ honored correctly.
+
+ * It was unclear in the documentation for "git blame" that it is
+ unnecessary for users to use the "--follow" option.
+
+ * 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".
+
+ * "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 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.
+
+ * "git status" honored the ignore=dirty settings in .gitmodules but
+ "git commit" didn't.
+
+Also contains a handful of documentation updates.
diff --git a/Documentation/RelNotes/1.7.12.4.txt b/Documentation/RelNotes/1.7.12.4.txt
new file mode 100644
index 0000000..c6da3cc
--- /dev/null
+++ b/Documentation/RelNotes/1.7.12.4.txt
@@ -0,0 +1,23 @@
+Git 1.7.12.4 Release Notes
+==========================
+
+Fixes since v1.7.12.3
+---------------------
+
+ * "git fetch" over the dumb-http revision walker could segfault when
+ curl's multi interface was used.
+
+ * It was possible to give specific paths for "asciidoc" and other
+ tools in the documentation toolchain, but not for "xmlto".
+
+ * "gitweb" did not give the correct committer timezone in its feed
+ output due to a typo.
+
+ * The "-Xours" (and similarly -Xtheirs) backend option to "git
+ merge -s recursive" was ignored for binary files. Now it is
+ honored.
+
+ * The "binary" synthetic attribute made "diff" to treat the path as
+ binary, but not "merge".
+
+Also contains many documentation updates.
diff --git a/Documentation/RelNotes/1.8.0.txt b/Documentation/RelNotes/1.8.0.txt
new file mode 100644
index 0000000..43883c1
--- /dev/null
+++ b/Documentation/RelNotes/1.8.0.txt
@@ -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.
diff --git a/Documentation/asciidoc.conf b/Documentation/asciidoc.conf
index a26d245..1273a85 100644
--- a/Documentation/asciidoc.conf
+++ b/Documentation/asciidoc.conf
@@ -36,7 +36,7 @@ ifndef::git-asciidoc-no-roff[]
# v1.72 breaks with this because it replaces dots not in roff requests.
[listingblock]
<example><title>{title}</title>
-<literallayout>
+<literallayout class="monospaced">
ifdef::doctype-manpage[]
&#10;.ft C&#10;
endif::doctype-manpage[]
@@ -53,7 +53,7 @@ ifdef::doctype-manpage[]
# The following two small workarounds insert a simple paragraph after screen
[listingblock]
<example><title>{title}</title>
-<literallayout>
+<literallayout class="monospaced">
|
</literallayout><simpara></simpara>
{title#}</example>
diff --git a/Documentation/config.txt b/Documentation/config.txt
index a95e5a4..11f320b 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -559,8 +559,9 @@ core.whitespace::
* `space-before-tab` treats a space character that appears immediately
before a tab character in the initial indent part of the line as an
error (enabled by default).
-* `indent-with-non-tab` treats a line that is indented with 8 or more
- space characters as an error (not enabled by default).
+* `indent-with-non-tab` treats a line that is indented with space
+ characters instead of the equivalent tabs as an error (not enabled by
+ default).
* `tab-in-indent` treats a tab character in the initial indent part of
the line as an error (not enabled by default).
* `blank-at-eof` treats blank lines added at the end of file as an error
@@ -1210,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
diff --git a/Documentation/diff-config.txt b/Documentation/diff-config.txt
index 67a90a8..75ab8a5 100644
--- a/Documentation/diff-config.txt
+++ b/Documentation/diff-config.txt
@@ -56,6 +56,10 @@ diff.statGraphWidth::
Limit the width of the graph part in --stat output. If set, applies
to all commands generating --stat output except format-patch.
+diff.context::
+ Generate diffs with <n> lines of context instead of the default of
+ 3. This value is overridden by the -U option.
+
diff.external::
If this config variable is set, diff generation is not
performed using the internal diff machinery, but using the
diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index 39d326a..b4d6476 100644
--- a/Documentation/fetch-options.txt
+++ b/Documentation/fetch-options.txt
@@ -10,7 +10,8 @@
--depth=<depth>::
Deepen the history of a 'shallow' repository created by
`git clone` with `--depth=<depth>` option (see linkgit:git-clone[1])
- by the specified number of commits.
+ to the specified number of commits from the tip of each remote
+ branch history. Tags for the deepened commits are not fetched.
ifndef::git-pull[]
--dry-run::
diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt
index 9c1d395..fd9e36b 100644
--- a/Documentation/git-add.txt
+++ b/Documentation/git-add.txt
@@ -155,7 +155,7 @@ Configuration
The optional configuration variable `core.excludesfile` indicates a path to a
file containing patterns of file names to exclude from git-add, similar to
$GIT_DIR/info/exclude. Patterns in the exclude file are used in addition to
-those in info/exclude. See linkgit:gitrepository-layout[5].
+those in info/exclude. See linkgit:gitignore[5].
EXAMPLES
diff --git a/Documentation/git-blame.txt b/Documentation/git-blame.txt
index 7ee9236..e44173f 100644
--- a/Documentation/git-blame.txt
+++ b/Documentation/git-blame.txt
@@ -20,6 +20,12 @@ last modified the line. Optionally, start annotating from the given revision.
The command can also limit the range of lines annotated.
+The origin of lines is automatically followed across whole-file
+renames (currently there is no option to turn the rename-following
+off). To follow lines moved from one file to another, or to follow
+lines that were copied and pasted from another file, etc., see the
+`-C` and `-M` options.
+
The report does not tell you anything about lines which have been deleted or
replaced; you need to use a tool such as 'git diff' or the "pickaxe"
interface briefly mentioned in the following paragraph.
diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index 47235be..45a225e 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -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
@@ -129,11 +131,13 @@ This option is only applicable in non-verbose mode.
use `git branch --list <pattern>` to list matching branches.
-v::
+-vv::
--verbose::
When in list mode,
show sha1 and commit subject line for each head, along with
relationship to upstream branch (if any). If given twice, print
- the name of the upstream branch, as well.
+ the name of the upstream branch, as well (see also `git remote
+ show <remote>`).
-q::
--quiet::
@@ -173,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`).
diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index 63a2516..7958a47 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -84,11 +84,11 @@ entries; instead, unmerged entries are ignored.
When checking out paths from the index, check out stage #2
('ours') or #3 ('theirs') for unmerged paths.
--b::
+-b <new_branch>::
Create a new branch named <new_branch> and start it at
<start_point>; see linkgit:git-branch[1] for details.
--B::
+-B <new_branch>::
Creates the branch <new_branch> and start it at <start_point>;
if it already exists, then reset it to <start_point>. This is
equivalent to running "git branch" with "-f"; see
@@ -124,7 +124,7 @@ explicitly give a name with '-b' in such a case.
<commit> is not a branch name. See the "DETACHED HEAD" section
below for details.
---orphan::
+--orphan <new_branch>::
Create a new 'orphan' branch, named <new_branch>, started from
<start_point> and switch to it. The first commit made on this
new branch will have no parents and it will be the root of a new
@@ -367,6 +367,18 @@ $ git checkout hello.c <3>
<2> take a file out of another commit
<3> restore hello.c from the index
+
+If you want to check out _all_ C source files out of the index,
+you can say
++
+------------
+$ git checkout -- '*.c'
+------------
++
+Note the quotes around `*.c`. The file `hello.c` will also be
+checked out, even though it is no longer in the working tree,
+because the file globbing is used to match entries in the index
+(not in the working tree by the shell).
++
If you have an unfortunate branch that is named `hello.c`, this
step would be confused as an instruction to switch to that branch.
You should instead write:
diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt
index 0e170a5..c205d23 100644
--- a/Documentation/git-cherry-pick.txt
+++ b/Documentation/git-cherry-pick.txt
@@ -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
diff --git a/Documentation/git-clean.txt b/Documentation/git-clean.txt
index 79fb984..9f42c0d 100644
--- a/Documentation/git-clean.txt
+++ b/Documentation/git-clean.txt
@@ -63,6 +63,10 @@ OPTIONS
Remove only files ignored by git. This may be useful to rebuild
everything from scratch, but keep manually created files.
+SEE ALSO
+--------
+linkgit:gitignore[5]
+
GIT
---
Part of the linkgit:git[1] suite
diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index c1ddd4c..6d98ef3 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -29,7 +29,8 @@ currently active branch.
After the clone, a plain `git fetch` without arguments will update
all the remote-tracking branches, and a `git pull` without
arguments will in addition merge the remote master branch into the
-current master branch, if any.
+current master branch, if any (this is untrue when "--single-branch"
+is given; see below).
This default configuration is achieved by creating references to
the remote branch heads under `refs/remotes/origin` and
@@ -152,9 +153,10 @@ objects from the source repository into a pack in the cloned repository.
-b <name>::
Instead of pointing the newly created HEAD to the branch pointed
to by the cloned repository's HEAD, point to `<name>` branch
- instead. `--branch` can also take tags and treat them like
- detached HEAD. In a non-bare repository, this is the branch
- that will be checked out.
+ instead. In a non-bare repository, this is the branch that will
+ be checked out.
+ `--branch` can also take tags and detaches the HEAD at that commit
+ in the resulting repository.
--upload-pack <upload-pack>::
-u <upload-pack>::
@@ -193,6 +195,11 @@ objects from the source repository into a pack in the cloned repository.
clone with the `--depth` option, this is the default, unless
`--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
+ initial cloning. If the HEAD at the remote did not point at any
+ branch when `--single-branch` clone was made, no remote tracking
+ branch is created.
--recursive::
--recurse-submodules::
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index 4622297..9594ac8 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -389,8 +389,10 @@ DISCUSSION
Though not required, it's a good idea to begin the commit message
with a single short (less than 50 character) line summarizing the
change, followed by a blank line and then a more thorough description.
-Tools that turn commits into email, for example, use the first line
-on the Subject: line and the rest of the commit in the body.
+The text up to the first blank line in a commit message is treated
+as the commit title, and that title is used throughout git.
+For example, linkgit:git-format-patch[1] turns a commit into email, and it uses
+the title on the Subject line and the rest of the commit in the body.
include::i18n.txt[]
diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
index 2d6ef32..eaea079 100644
--- a/Documentation/git-config.txt
+++ b/Documentation/git-config.txt
@@ -54,16 +54,16 @@ configuration file by default, and options '--system', '--global',
'--file <filename>' can be used to tell the command to write to
that location (you can say '--local' but that is the default).
-This command will fail (with exit code ret) if:
+This command will fail with non-zero status upon error. Some exit
+codes are:
. The config file is invalid (ret=3),
. can not write to the config file (ret=4),
. no section or name was provided (ret=2),
. the section or key is invalid (ret=1),
. you try to unset an option which does not exist (ret=5),
-. you try to unset/set an option for which multiple lines match (ret=5),
-. you try to use an invalid regexp (ret=6), or
-. you use '--global' option without $HOME being properly set (ret=128).
+. you try to unset/set an option for which multiple lines match (ret=5), or
+. you try to use an invalid regexp (ret=6).
On success, the command returns the exit code 0.
@@ -267,7 +267,7 @@ Given a .git/config like this:
; Proxy settings
[core]
- gitproxy="proxy-command" for kernel.org
+ gitproxy=proxy-command for kernel.org
gitproxy=default-proxy ; for all the rest
you can set the filemode to true with
@@ -342,7 +342,7 @@ To actually match only values with an exclamation mark, you have to
To add a new proxy, without altering any of the existing ones, use
------------
-% git config core.gitproxy '"proxy-command" for example.com'
+% git config --add core.gitproxy '"proxy-command" for example.com'
------------
An example to use customized color from the configuration in your
diff --git a/Documentation/git-credential-cache--daemon.txt b/Documentation/git-credential-cache--daemon.txt
index 11edc5a..d15db42 100644
--- a/Documentation/git-credential-cache--daemon.txt
+++ b/Documentation/git-credential-cache--daemon.txt
@@ -3,7 +3,7 @@ git-credential-cache--daemon(1)
NAME
----
-git-credential-cache--daemon - temporarily store user credentials in memory
+git-credential-cache--daemon - Temporarily store user credentials in memory
SYNOPSIS
--------
diff --git a/Documentation/git-credential-cache.txt b/Documentation/git-credential-cache.txt
index f3d09c5..eeff5fa 100644
--- a/Documentation/git-credential-cache.txt
+++ b/Documentation/git-credential-cache.txt
@@ -3,7 +3,7 @@ git-credential-cache(1)
NAME
----
-git-credential-cache - helper to temporarily store passwords in memory
+git-credential-cache - Helper to temporarily store passwords in memory
SYNOPSIS
--------
diff --git a/Documentation/git-credential-store.txt b/Documentation/git-credential-store.txt
index 3109346..b27c03c 100644
--- a/Documentation/git-credential-store.txt
+++ b/Documentation/git-credential-store.txt
@@ -3,7 +3,7 @@ git-credential-store(1)
NAME
----
-git-credential-store - helper to store credentials on disk
+git-credential-store - Helper to store credentials on disk
SYNOPSIS
--------
diff --git a/Documentation/git-daemon.txt b/Documentation/git-daemon.txt
index e8f7577..7e5098a 100644
--- a/Documentation/git-daemon.txt
+++ b/Documentation/git-daemon.txt
@@ -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
diff --git a/Documentation/git-describe.txt b/Documentation/git-describe.txt
index 039cce2..72d6bb6 100644
--- a/Documentation/git-describe.txt
+++ b/Documentation/git-describe.txt
@@ -36,12 +36,12 @@ OPTIONS
--all::
Instead of using only the annotated tags, use any ref
- found in `.git/refs/`. This option enables matching
+ found in `refs/` namespace. This option enables matching
any known branch, remote-tracking branch, or lightweight tag.
--tags::
Instead of using only the annotated tags, use any tag
- found in `.git/refs/tags`. This option enables matching
+ found in `refs/tags` namespace. This option enables matching
a lightweight (non-annotated) tag.
--contains::
diff --git a/Documentation/git-difftool.txt b/Documentation/git-difftool.txt
index 31fc2e3..73ca702 100644
--- a/Documentation/git-difftool.txt
+++ b/Documentation/git-difftool.txt
@@ -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.
diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt
index 2620d28..6603a7a 100644
--- a/Documentation/git-fast-import.txt
+++ b/Documentation/git-fast-import.txt
@@ -39,6 +39,10 @@ OPTIONS
See ``Date Formats'' below for details about which formats
are supported, and their syntax.
+-- done::
+ Terminate with error if there is no 'done' command at the
+ end of the stream.
+
--force::
Force updating modified existing branches, even if doing
so would cause commits to be lost (as the new commit does
@@ -1047,7 +1051,9 @@ done::
Error out if the stream ends without a 'done' command.
Without this feature, errors causing the frontend to end
abruptly at a convenient point in the stream can go
- undetected.
+ undetected. This may occur, for example, if an import
+ front end dies in mid-operation without emitting SIGTERM
+ or SIGKILL at its subordinate git fast-import instance.
`option`
~~~~~~~~
diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt
index 81f5823..e2301f5 100644
--- a/Documentation/git-filter-branch.txt
+++ b/Documentation/git-filter-branch.txt
@@ -32,7 +32,8 @@ changes, which would normally have no effect. Nevertheless, this may be
useful in the future for compensating for some git bugs or such,
therefore such a usage is permitted.
-*NOTE*: This command honors `.git/info/grafts` and `.git/refs/replace/`.
+*NOTE*: This command honors `.git/info/grafts` file and refs in
+the `refs/replace/` namespace.
If you have any grafts or replacement refs defined, running this command
will make them permanent.
@@ -303,6 +304,11 @@ committed a merge between P1 and P2, it will be propagated properly
and all children of the merge will become merge commits with P1,P2
as their parents instead of the merge commit.
+*NOTE* the changes introduced by the commits, and which are not reverted
+by subsequent commits, will still be in the rewritten branch. If you want
+to throw out _changes_ together with the commits, you should use the
+interactive mode of 'git rebase'.
+
You can rewrite the commit log messages using `--msg-filter`. For
example, 'git svn-id' strings in a repository created by 'git svn' can
be removed this way:
@@ -313,11 +319,6 @@ git filter-branch --msg-filter '
'
-------------------------------------------------------
-To restrict rewriting to only part of the history, specify a revision
-range in addition to the new branch name. The new branch name will
-point to the top-most revision that a 'git rev-list' of this range
-will print.
-
If you need to add 'Acked-by' lines to, say, the last 10 commits (none
of which is a merge), use this command:
@@ -328,11 +329,10 @@ git filter-branch --msg-filter '
' HEAD~10..HEAD
--------------------------------------------------------
-*NOTE* the changes introduced by the commits, and which are not reverted
-by subsequent commits, will still be in the rewritten branch. If you want
-to throw out _changes_ together with the commits, you should use the
-interactive mode of 'git rebase'.
-
+To restrict rewriting to only part of the history, specify a revision
+range in addition to the new branch name. The new branch name will
+point to the top-most revision that a 'git rev-list' of this range
+will print.
Consider this history:
diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt
index c872b88..db55a4e 100644
--- a/Documentation/git-for-each-ref.txt
+++ b/Documentation/git-for-each-ref.txt
@@ -102,9 +102,10 @@ Fields that have name-email-date tuple as its value (`author`,
and `date` to extract the named component.
The complete message in a commit and tag object is `contents`.
-Its first line is `contents:subject`, the remaining lines
-are `contents:body` and the optional GPG signature
-is `contents:signature`.
+Its first line is `contents:subject`, where subject is the concatenation
+of all lines of the commit message up to the first blank line. The next
+line is 'contents:body', where body is all of the lines after the first
+blank line. Finally, the optional GPG signature is `contents:signature`.
For sorting purposes, fields with numeric values sort in numeric
order (`objectsize`, `authordate`, `committerdate`, `taggerdate`).
diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt
index 04c7346..6d43f56 100644
--- a/Documentation/git-format-patch.txt
+++ b/Documentation/git-format-patch.txt
@@ -58,10 +58,13 @@ output, unless the `--stdout` option is specified.
If `-o` is specified, output files are created in <dir>. Otherwise
they are created in the current working directory.
-By default, the subject of a single patch is "[PATCH] First Line" and
-the subject when multiple patches are output is "[PATCH n/m] First
-Line". To force 1/1 to be added for a single patch, use `-n`. To omit
-patch numbers from the subject, use `-N`.
+By default, the subject of a single patch is "[PATCH] " followed by
+the concatenation of lines from the commit message up to the first blank
+line (see the DISCUSSION section of linkgit:git-commit[1]).
+
+When multiple patches are output, the subject prefix will instead be
+"[PATCH n/m] ". To force 1/1 to be added for a single patch, use `-n`.
+To omit patch numbers from the subject, use `-N`.
If given `--thread`, `git-format-patch` will generate `In-Reply-To` and
`References` headers to make the second and subsequent patch mails appear
diff --git a/Documentation/git-fsck.txt b/Documentation/git-fsck.txt
index bbb25da..da348fc 100644
--- a/Documentation/git-fsck.txt
+++ b/Documentation/git-fsck.txt
@@ -23,8 +23,8 @@ OPTIONS
An object to treat as the head of an unreachability trace.
+
If no objects are given, 'git fsck' defaults to using the
-index file, all SHA1 references in .git/refs/*, and all reflogs (unless
---no-reflogs is given) as heads.
+index file, all SHA1 references in `refs` namespace, and all reflogs
+(unless --no-reflogs is given) as heads.
--unreachable::
Print out objects that exist but that aren't reachable from any
diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt
index 3bec036..cfecf84 100644
--- a/Documentation/git-grep.txt
+++ b/Documentation/git-grep.txt
@@ -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
diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt
index 1f90620..585dac4 100644
--- a/Documentation/git-log.txt
+++ b/Documentation/git-log.txt
@@ -24,10 +24,6 @@ each commit introduces are shown.
OPTIONS
-------
--<n>::
- Limits the number of commits to show.
- Note that this is a commit limiting option, see below.
-
<since>..<until>::
Show only commits between the named two commits. When
either <since> or <until> is omitted, it defaults to
@@ -137,6 +133,8 @@ Examples
This makes sense only when following a strict policy of merging all
topic branches when staying on a single integration branch.
+`git log -3`::
+ Limits the number of commits to show to 3.
Discussion
----------
diff --git a/Documentation/git-lost-found.txt b/Documentation/git-lost-found.txt
index c406a11..d549328 100644
--- a/Documentation/git-lost-found.txt
+++ b/Documentation/git-lost-found.txt
@@ -48,7 +48,8 @@ $ gitk $(cd .git/lost-found/commit && echo ??*)
------------
After making sure you know which the object is the tag you are looking
-for, you can reconnect it to your regular .git/refs hierarchy.
+for, you can reconnect it to your regular `refs` hierarchy by using
+the `update-ref` command.
------------
$ git cat-file -t 1ef2b196
diff --git a/Documentation/git-ls-remote.txt b/Documentation/git-ls-remote.txt
index 7a9b86a..774de5e 100644
--- a/Documentation/git-ls-remote.txt
+++ b/Documentation/git-ls-remote.txt
@@ -42,6 +42,11 @@ OPTIONS
it successfully talked with the remote repository, whether it
found any matching refs.
+--get-url::
+ Expand the URL of the given remote repository taking into account any
+ "url.<base>.insteadOf" config setting (See linkgit:git-config[1]) and
+ exit without talking to the remote.
+
<repository>::
Location of the repository. The shorthand defined in
$GIT_DIR/branches/ can be used. Use "." (dot) to list references in
diff --git a/Documentation/git-merge-base.txt b/Documentation/git-merge-base.txt
index b295bf8..87842e3 100644
--- a/Documentation/git-merge-base.txt
+++ b/Documentation/git-merge-base.txt
@@ -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],
diff --git a/Documentation/git-mergetool.txt b/Documentation/git-mergetool.txt
index d7207bd..6b563c5 100644
--- a/Documentation/git-mergetool.txt
+++ b/Documentation/git-mergetool.txt
@@ -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
diff --git a/Documentation/git-p4.txt b/Documentation/git-p4.txt
index 8228f33..beff622 100644
--- a/Documentation/git-p4.txt
+++ b/Documentation/git-p4.txt
@@ -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.
diff --git a/Documentation/git-pack-refs.txt b/Documentation/git-pack-refs.txt
index 10afd4e..f131677 100644
--- a/Documentation/git-pack-refs.txt
+++ b/Documentation/git-pack-refs.txt
@@ -14,7 +14,8 @@ DESCRIPTION
-----------
Traditionally, tips of branches and tags (collectively known as
-'refs') were stored one file per ref under `$GIT_DIR/refs`
+'refs') were stored one file per ref in a (sub)directory
+under `$GIT_DIR/refs`
directory. While many branch tips tend to be updated often,
most tags and some branch tips are never updated. When a
repository has hundreds or thousands of tags, this
@@ -22,13 +23,14 @@ one-file-per-ref format both wastes storage and hurts
performance.
This command is used to solve the storage and performance
-problem by stashing the refs in a single file,
+problem by storing the refs in a single file,
`$GIT_DIR/packed-refs`. When a ref is missing from the
-traditional `$GIT_DIR/refs` hierarchy, it is looked up in this
+traditional `$GIT_DIR/refs` directory hierarchy, it is looked
+up in this
file and used if found.
Subsequent updates to branches always create new files under
-`$GIT_DIR/refs` hierarchy.
+`$GIT_DIR/refs` directory hierarchy.
A recommended practice to deal with a repository with too many
refs is to pack its refs with `--all --prune` once, and
@@ -57,6 +59,15 @@ a repository with many branches of historical interests.
The command usually removes loose refs under `$GIT_DIR/refs`
hierarchy after packing them. This option tells it not to.
+
+BUGS
+----
+
+Older documentation written before the packed-refs mechanism was
+introduced may still say things like ".git/refs/heads/<branch> file
+exists" when it means "branch <branch> exists".
+
+
GIT
---
Part of the linkgit:git[1] suite
diff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt
index defb544..67fa5ee 100644
--- a/Documentation/git-pull.txt
+++ b/Documentation/git-pull.txt
@@ -101,6 +101,7 @@ include::merge-options.txt[]
:git-pull: 1
+-r::
--rebase::
Rebase the current branch on top of the upstream branch after
fetching. If there is a remote-tracking branch corresponding to
diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index cb97cc1..22d2580 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -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
@@ -357,7 +360,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
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index fd535b0..da067ec 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -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
diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt
index a308f4c..e8c396b 100644
--- a/Documentation/git-remote.txt
+++ b/Documentation/git-remote.txt
@@ -12,7 +12,7 @@ SYNOPSIS
'git remote' [-v | --verbose]
'git remote add' [-t <branch>] [-m <master>] [-f] [--tags|--no-tags] [--mirror=<fetch|push>] <name> <url>
'git remote rename' <old> <new>
-'git remote rm' <name>
+'git remote remove' <name>
'git remote set-head' <name> (-a | -d | <branch>)
'git remote set-branches' [--add] <name> <branch>...
'git remote set-url' [--push] <name> <newurl> [<oldurl>]
@@ -85,6 +85,7 @@ In case <old> and <new> are the same, and <old> is a file under
`$GIT_DIR/remotes` or `$GIT_DIR/branches`, the remote is converted to
the configuration file format.
+'remove'::
'rm'::
Remove the remote named <name>. All remote-tracking branches and
diff --git a/Documentation/git-replace.txt b/Documentation/git-replace.txt
index 17df525..51131d0 100644
--- a/Documentation/git-replace.txt
+++ b/Documentation/git-replace.txt
@@ -14,14 +14,13 @@ SYNOPSIS
DESCRIPTION
-----------
-Adds a 'replace' reference in `.git/refs/replace/`
+Adds a 'replace' reference in `refs/replace/` namespace.
The name of the 'replace' reference is the SHA1 of the object that is
replaced. The content of the 'replace' reference is the SHA1 of the
replacement object.
-Unless `-f` is given, the 'replace' reference must not yet exist in
-`.git/refs/replace/` directory.
+Unless `-f` is given, the 'replace' reference must not yet exist.
Replacement references will be used by default by all git commands
except those doing reachability traversal (prune, pack transfer and
diff --git a/Documentation/git-shortlog.txt b/Documentation/git-shortlog.txt
index 01d8417..afeb4cd 100644
--- a/Documentation/git-shortlog.txt
+++ b/Documentation/git-shortlog.txt
@@ -14,8 +14,7 @@ git log --pretty=short | 'git shortlog' [-h] [-n] [-s] [-e] [-w]
DESCRIPTION
-----------
Summarizes 'git log' output in a format suitable for inclusion
-in release announcements. Each commit will be grouped by author and
-the first line of the commit message will be shown.
+in release announcements. Each commit will be grouped by author and title.
Additionally, "[PATCH]" will be stripped from the commit description.
diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index fbbbcb2..b4683bb 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -112,7 +112,6 @@ status::
initialized, `+` if the currently checked out submodule commit
does not match the SHA-1 found in the index of the containing
repository and `U` if the submodule has merge conflicts.
- This command is the default command for 'git submodule'.
+
If `--recursive` is specified, this command will recurse into nested
submodules, and show their status as well.
@@ -149,6 +148,11 @@ submodule with the `--init` option.
+
If `--recursive` is specified, this command will recurse into the
registered submodules, and update any nested submodules within.
++
+If `--force` is specified, the submodule will be checked out (using
+`git checkout --force` if appropriate), even if the commit specified in the
+index of the containing repository already matches the commit checked out in
+the submodule.
summary::
Show commit summary between the given commit (defaults to HEAD) and
@@ -210,7 +214,9 @@ OPTIONS
This option is only valid for add and update commands.
When running add, allow adding an otherwise ignored submodule path.
When running update, throw away local changes in submodules when
- switching to a different commit.
+ switching to a different commit; and always run a checkout operation
+ in the submodule, even if the commit listed in the index of the
+ containing repository matches the commit checked out in the submodule.
--cached::
This option is only valid for status and summary commands. These
diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt
index e36a7c3..247534e 100644
--- a/Documentation/git-tag.txt
+++ b/Documentation/git-tag.txt
@@ -20,11 +20,10 @@ SYNOPSIS
DESCRIPTION
-----------
-Add a tag reference in `.git/refs/tags/`, unless `-d/-l/-v` is given
+Add a tag reference in `refs/tags/`, unless `-d/-l/-v` is given
to delete, list or verify tags.
-Unless `-f` is given, the tag to be created must not yet exist in the
-`.git/refs/tags/` directory.
+Unless `-f` is given, the named tag must not yet exist.
If one of `-a`, `-s`, or `-u <key-id>` is passed, the command
creates a 'tag' object, and requires a tag message. Unless
diff --git a/Documentation/git.txt b/Documentation/git.txt
index eb6b2c0..4a89a12 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -22,18 +22,17 @@ unusually rich command set that provides both high-level operations
and full access to internals.
See linkgit:gittutorial[7] to get started, then see
-link:everyday.html[Everyday Git] for a useful minimum set of commands, and
-"man git-commandname" for documentation of each command. CVS users may
-also want to read linkgit:gitcvs-migration[7]. See
-the link:user-manual.html[Git User's Manual] for a more in-depth
-introduction.
+link:everyday.html[Everyday Git] for a useful minimum set of
+commands. The link:user-manual.html[Git User's Manual] has a more
+in-depth introduction.
-The '<command>' is either a name of a Git command (see below) or an alias
-as defined in the configuration file (see linkgit:git-config[1]).
+After you mastered the basic concepts, you can come back to this
+page to learn what commands git offers. You can learn more about
+individual git commands with "git help command". linkgit:gitcli[7]
+manual page gives you an overview of the command line command syntax.
-Formatted and hyperlinked version of the latest git
-documentation can be viewed at
-`http://git-htmldocs.googlecode.com/git/git.html`.
+Formatted and hyperlinked version of the latest git documentation
+can be viewed at `http://git-htmldocs.googlecode.com/git/git.html`.
ifdef::stalenotes[]
[NOTE]
@@ -44,9 +43,25 @@ unreleased) version of git, that is available from 'master'
branch of the `git.git` repository.
Documentation for older releases are available here:
-* link:v1.7.11.5/git.html[documentation for release 1.7.11.5]
+* link:v1.8.0/git.html[documentation for release 1.8.0]
* release notes for
+ 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
+ link:RelNotes/1.7.12.4.txt[1.7.12.4],
+ link:RelNotes/1.7.12.3.txt[1.7.12.3],
+ link:RelNotes/1.7.12.2.txt[1.7.12.2],
+ link:RelNotes/1.7.12.1.txt[1.7.12.1],
+ link:RelNotes/1.7.12.txt[1.7.12].
+
+* link:v1.7.11.7/git.html[documentation for release 1.7.11.7]
+
+* release notes for
+ link:RelNotes/1.7.11.7.txt[1.7.11.7],
+ link:RelNotes/1.7.11.6.txt[1.7.11.6],
link:RelNotes/1.7.11.5.txt[1.7.11.5],
link:RelNotes/1.7.11.4.txt[1.7.11.4],
link:RelNotes/1.7.11.3.txt[1.7.11.3],
@@ -406,24 +421,6 @@ help ...`.
linkgit:git-replace[1] for more information.
-FURTHER DOCUMENTATION
----------------------
-
-See the references above to get started using git. The following is
-probably more detail than necessary for a first-time user.
-
-The link:user-manual.html#git-concepts[git concepts chapter of the
-user-manual] and linkgit:gitcore-tutorial[7] both provide
-introductions to the underlying git architecture.
-
-See linkgit:gitworkflows[7] for an overview of recommended workflows.
-
-See also the link:howto-index.html[howto] documents for some useful
-examples.
-
-The internals are documented in the
-link:technical/api-index.html[GIT API documentation].
-
GIT COMMANDS
------------
@@ -843,6 +840,29 @@ The index is also capable of storing multiple entries (called "stages")
for a given pathname. These stages are used to hold the various
unmerged version of a file when a merge is in progress.
+FURTHER DOCUMENTATION
+---------------------
+
+See the references in the "description" section to get started
+using git. The following is probably more detail than necessary
+for a first-time user.
+
+The link:user-manual.html#git-concepts[git concepts chapter of the
+user-manual] and linkgit:gitcore-tutorial[7] both provide
+introductions to the underlying git architecture.
+
+See linkgit:gitworkflows[7] for an overview of recommended workflows.
+
+See also the link:howto-index.html[howto] documents for some useful
+examples.
+
+The internals are documented in the
+link:technical/api-index.html[GIT API documentation].
+
+Users migrating from CVS may also want to
+read linkgit:gitcvs-migration[7].
+
+
Authors
-------
Git was started by Linus Torvalds, and is currently maintained by Junio
diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt
index e16f3e1..ba02d4d 100644
--- a/Documentation/gitattributes.txt
+++ b/Documentation/gitattributes.txt
@@ -66,6 +66,11 @@ is from the path in question, the lower its precedence). Finally
global and system-wide files are considered (they have the lowest
precedence).
+When the `.gitattributes` file is missing from the work tree, the
+path in the index is used as a fall-back. During checkout process,
+`.gitattributes` in the index is used and then the file in the
+working tree is used as a fall-back.
+
If you wish to affect only a single repository (i.e., to assign
attributes to files that are particular to
one user's workflow for that repository), then
@@ -511,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.
@@ -927,7 +934,7 @@ file at the toplevel (i.e. not in any subdirectory). The built-in
macro attribute "binary" is equivalent to:
------------
-[attr]binary -diff -text
+[attr]binary -diff -merge -text
------------
diff --git a/Documentation/gitcli.txt b/Documentation/gitcli.txt
index ea17f7a..3bc1500 100644
--- a/Documentation/gitcli.txt
+++ b/Documentation/gitcli.txt
@@ -37,11 +37,28 @@ arguments. Here are the rules:
file called HEAD in your work tree, `git diff HEAD` is ambiguous, and
you have to say either `git diff HEAD --` or `git diff -- HEAD` to
disambiguate.
-
++
When writing a script that is expected to handle random user-input, it is
a good practice to make it explicit which arguments are which by placing
disambiguating `--` at appropriate places.
+ * Many commands allow wildcards in paths, but you need to protect
+ them from getting globbed by the shell. These two mean different
+ things:
++
+--------------------------------
+$ git checkout -- *.c
+$ git checkout -- \*.c
+--------------------------------
++
+The former lets your shell expand the fileglob, and you are asking
+the dot-C files in your working tree to be overwritten with the version
+in the index. The latter passes the `*.c` to Git, and you are asking
+the paths in the index that match the pattern to be checked out to your
+working tree. After running `git add hello.c; rm hello.c`, you will _not_
+see `hello.c` in your working tree with the former, but with the latter
+you will.
+
Here are the rules regarding the "flags" that you should follow when you are
scripting git:
@@ -62,13 +79,21 @@ scripting git:
`git log -1 HEAD` but write `git log -1 HEAD --`; the former will not work
if you happen to have a file called `HEAD` in the work tree.
+ * many commands allow a long option "--option" to be abbreviated
+ only to their unique prefix (e.g. if there is no other option
+ whose name begins with "opt", you may be able to spell "--opt" to
+ invoke the "--option" flag), but you should fully spell them out
+ when writing your scripts; later versions of Git may introduce a
+ new option whose name shares the same prefix, e.g. "--optimize",
+ to make a short prefix that used to be unique no longer unique.
+
ENHANCED OPTION PARSER
----------------------
From the git 1.5.4 series and further, many git commands (not all of them at the
time of the writing though) come with an enhanced option parser.
-Here is an exhaustive list of the facilities provided by this option parser.
+Here is a list of the facilities provided by this option parser.
Magic Options
@@ -112,6 +137,16 @@ options. This means that you can for example use `git rm -rf` or
`git clean -fdx`.
+Abbreviating long options
+~~~~~~~~~~~~~~~~~~~~~~~~~
+Commands that support the enhanced option parser accepts unique
+prefix of a long option as if it is fully spelled out, but use this
+with a caution. For example, `git commit --amen` behaves as if you
+typed `git commit --amend`, but that is true only until a later version
+of Git introduces another option that shares the same prefix,
+e.g `git commit --amenity" option.
+
+
Separating argument from the option
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can write the mandatory option parameter to an option as a separate
diff --git a/Documentation/gitcore-tutorial.txt b/Documentation/gitcore-tutorial.txt
index 9d89336..5325c5a 100644
--- a/Documentation/gitcore-tutorial.txt
+++ b/Documentation/gitcore-tutorial.txt
@@ -956,12 +956,11 @@ $ git show-branch --topo-order --more=1 master mybranch
------------------------------------------------
The first two lines indicate that it is showing the two branches
-and the first line of the commit log message from their
-top-of-the-tree commits, you are currently on `master` branch
-(notice the asterisk `*` character), and the first column for
-the later output lines is used to show commits contained in the
+with the titles of their top-of-the-tree commits, you are currently on
+`master` branch (notice the asterisk `*` character), and the first
+column for the later output lines is used to show commits contained in the
`master` branch, and the second column for the `mybranch`
-branch. Three commits are shown along with their log messages.
+branch. Three commits are shown along with their titles.
All of them have non blank characters in the first column (`*`
shows an ordinary commit on the current branch, `-` is a merge commit), which
means they are now part of the `master` branch. Only the "Some
diff --git a/Documentation/gitignore.txt b/Documentation/gitignore.txt
index c1f692a..1b82fe1 100644
--- a/Documentation/gitignore.txt
+++ b/Documentation/gitignore.txt
@@ -41,18 +41,24 @@ precedence, the last matching pattern decides the outcome):
variable 'core.excludesfile'.
Which file to place a pattern in depends on how the pattern is meant to
-be used. Patterns which should be version-controlled and distributed to
-other repositories via clone (i.e., files that all developers will want
-to ignore) should go into a `.gitignore` file. Patterns which are
-specific to a particular repository but which do not need to be shared
-with other related repositories (e.g., auxiliary files that live inside
-the repository but are specific to one user's workflow) should go into
-the `$GIT_DIR/info/exclude` file. Patterns which a user wants git to
-ignore in all situations (e.g., backup or temporary files generated by
-the user's editor of choice) generally go into a file specified by
-`core.excludesfile` in the user's `~/.gitconfig`. Its default value is
-$XDG_CONFIG_HOME/git/ignore. If $XDG_CONFIG_HOME is either not set or empty,
-$HOME/.config/git/ignore is used instead.
+be used.
+
+ * Patterns which should be version-controlled and distributed to
+ other repositories via clone (i.e., files that all developers will want
+ to ignore) should go into a `.gitignore` file.
+
+ * Patterns which are
+ specific to a particular repository but which do not need to be shared
+ with other related repositories (e.g., auxiliary files that live inside
+ the repository but are specific to one user's workflow) should go into
+ the `$GIT_DIR/info/exclude` file.
+
+ * Patterns which a user wants git to
+ ignore in all situations (e.g., backup or temporary files generated by
+ the user's editor of choice) generally go into a file specified by
+ `core.excludesfile` in the user's `~/.gitconfig`. Its default value is
+ $XDG_CONFIG_HOME/git/ignore. If $XDG_CONFIG_HOME is either not set or
+ empty, $HOME/.config/git/ignore is used instead.
The underlying git plumbing tools, such as
'git ls-files' and 'git read-tree', read
@@ -68,11 +74,15 @@ PATTERN FORMAT
for readability.
- A line starting with # serves as a comment.
+ Put a backslash ("`\`") in front of the first hash for patterns
+ that begin with a hash.
- - An optional prefix '!' which negates the pattern; any
+ - An optional prefix "`!`" which negates the pattern; any
matching file excluded by a previous pattern will become
included again. If a negated pattern matches, this will
override lower precedence patterns sources.
+ Put a backslash ("`\`") in front of the first "`!`" for patterns
+ that begin with a literal "`!`", for example, "`\!important!.txt`".
- If the pattern ends with a slash, it is removed for the
purpose of the following description, but it would only find
diff --git a/Documentation/gittutorial.txt b/Documentation/gittutorial.txt
index dee0505..f1cb6f3 100644
--- a/Documentation/gittutorial.txt
+++ b/Documentation/gittutorial.txt
@@ -139,9 +139,11 @@ them to the index, and commit, all in one step.
A note on commit messages: Though not required, it's a good idea to
begin the commit message with a single short (less than 50 character)
line summarizing the change, followed by a blank line and then a more
-thorough description. Tools that turn commits into email, for
-example, use the first line on the Subject: line and the rest of the
-commit in the body.
+thorough description. The text up to the first blank line in a commit
+message is treated as the commit title, and that title is used
+throughout git. For example, linkgit:git-format-patch[1] turns a
+commit into email, and it uses the title on the Subject line and the
+rest of the commit in the body.
Git tracks content not files
----------------------------
diff --git a/Documentation/merge-strategies.txt b/Documentation/merge-strategies.txt
index 595a3cf..66db802 100644
--- a/Documentation/merge-strategies.txt
+++ b/Documentation/merge-strategies.txt
@@ -32,13 +32,14 @@ ours;;
This option forces conflicting hunks to be auto-resolved cleanly by
favoring 'our' version. Changes from the other tree that do not
conflict with our side are reflected to the merge result.
+ For a binary file, the entire contents are taken from our side.
+
This should not be confused with the 'ours' merge strategy, which does not
even look at what the other tree contains at all. It discards everything
the other tree did, declaring 'our' history contains all that happened in it.
theirs;;
- This is opposite of 'ours'.
+ This is the opposite of 'ours'.
patience;;
With this option, 'merge-recursive' spends a little extra time
diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index e3d8a83..d9edded 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -130,6 +130,9 @@ The placeholders are:
- '%b': body
- '%B': raw body (unwrapped subject and body)
- '%N': commit notes
+- '%GG': raw verification message from GPG for a signed commit
+- '%G?': show either "G" for Good or "B" for Bad for a signed commit
+- '%GS': show the name of the signer for a signed commit
- '%gD': reflog selector, e.g., `refs/stash@{1}`
- '%gd': shortened reflog selector, e.g., `stash@{1}`
- '%gn': reflog identity name
diff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt
index 2a3dc86..5e49942 100644
--- a/Documentation/pretty-options.txt
+++ b/Documentation/pretty-options.txt
@@ -66,3 +66,7 @@ being displayed. Examples: "--notes=foo" will show only notes from
--[no-]standard-notes::
These options are deprecated. Use the above --notes/--no-notes
options instead.
+
+--show-signature::
+ Check the validity of a signed commit object by passing the signature
+ to `gpg --verify` and show the output.
diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt
index d9b2b5b..ee49743 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -3,12 +3,20 @@ Commit Limiting
Besides specifying a range of commits that should be listed using the
special notations explained in the description, additional commit
-limiting may be applied. Note that they are applied before commit
-ordering and formatting options, such as '--reverse'.
+limiting may be applied.
+
+Using more options generally further limits the output (e.g.
+`--since=<date1>` limits to commits newer than `<date1>`, and using it
+with `--grep=<pattern>` further limits to commits whose log message
+has a line that matches `<pattern>`), unless otherwise noted.
+
+Note that these are applied before commit
+ordering and formatting options, such as `--reverse`.
--
--n 'number'::
+-<number>::
+-n <number>::
--max-count=<number>::
Limit the number of commits to output.
@@ -38,16 +46,33 @@ endif::git-rev-list[]
--committer=<pattern>::
Limit the commits output to ones with author/committer
- header lines that match the specified pattern (regular expression).
+ header lines that match the specified pattern (regular
+ expression). With more than one `--author=<pattern>`,
+ 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
- matches the specified pattern (regular expression).
+ matches the specified pattern (regular expression). With
+ 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,
- --author and --committer instead of ones that match at least one.
+ instead of ones that match at least one.
-i::
--regexp-ignore-case::
@@ -578,16 +603,33 @@ Commit Ordering
By default, the commits are shown in reverse chronological order.
---topo-order::
+--date-order::
+ Show no parents before all of its children are shown, but
+ otherwise show commits in the commit timestamp order.
- This option makes them appear in topological order (i.e.
- descendant commits are shown before their parents).
+--topo-order::
+ Show no parents before all of its children are shown, and
+ avoid showing commits on multiple lines of history
+ intermixed.
++
+For example, in a commit history like this:
++
+----------------------------------------------------------------
---date-order::
+ ---1----2----4----7
+ \ \
+ 3----5----6----8---
- This option is similar to '--topo-order' in the sense that no
- parent comes before all of its children, but otherwise things
- are still ordered in the commit timestamp order.
+----------------------------------------------------------------
++
+where the numbers denote the order of commit timestamps, `git
+rev-list` and friends with `--date-order` show the commits in the
+timestamp order: 8 7 6 5 4 3 2 1.
++
+With `--topo-order`, they would show 8 6 5 3 7 4 2 1 (or 8 7 4 2 6 5
+3 1); some older commits are shown before newer ones in order to
+avoid showing the commits from two parallel development track mixed
+together.
--reverse::
@@ -619,10 +661,14 @@ These options are mostly targeted for packing of git repositories.
Only useful with '--objects'; print the object IDs that are not
in packs.
---no-walk::
+--no-walk[=(sorted|unsorted)]::
- Only show the given revs, but do not traverse their ancestors.
- This has no effect if a range is specified.
+ Only show the given commits, but do not traverse their ancestors.
+ This has no effect if a range is specified. If the argument
+ "unsorted" is given, the commits are show in the order they were
+ given on the command line. Otherwise (if "sorted" or no argument
+ was given), the commits are show in reverse chronological order
+ by commit time.
--do-walk::
diff --git a/Documentation/revisions.txt b/Documentation/revisions.txt
index dc0070b..991fcd8 100644
--- a/Documentation/revisions.txt
+++ b/Documentation/revisions.txt
@@ -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
@@ -213,6 +215,13 @@ of 'r1' and 'r2' and is defined as
It is the set of commits that are reachable from either one of
'r1' or 'r2' but not from both.
+In these two shorthands, you can omit one end and let it default to HEAD.
+For example, 'origin..' is a shorthand for 'origin..HEAD' and asks "What
+did I do since I forked from the origin branch?" Similarly, '..origin'
+is a shorthand for 'HEAD..origin' and asks "What did the origin do since
+I forked from them?" Note that '..' would mean 'HEAD..HEAD' which is an
+empty range that is both reachable and unreachable from HEAD.
+
Two other shorthands for naming a set that is formed by a commit
and its parent commits exist. The 'r1{caret}@' notation means all
parents of 'r1'. 'r1{caret}!' includes commit 'r1' but excludes
diff --git a/Documentation/technical/api-argv-array.txt b/Documentation/technical/api-argv-array.txt
index 6b97d6d..a959517 100644
--- a/Documentation/technical/api-argv-array.txt
+++ b/Documentation/technical/api-argv-array.txt
@@ -46,6 +46,10 @@ Functions
Format a string and push it onto the end of the array. This is a
convenience wrapper combining `strbuf_addf` and `argv_array_push`.
+`argv_array_pop`::
+ Remove the final element from the array. If there are no
+ elements in the array, do nothing.
+
`argv_array_clear`::
Free all memory associated with the array and return it to the
initial, empty state.
diff --git a/Documentation/technical/api-sha1-array.txt b/Documentation/technical/api-sha1-array.txt
index 4a4bae8..45d1c51 100644
--- a/Documentation/technical/api-sha1-array.txt
+++ b/Documentation/technical/api-sha1-array.txt
@@ -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
diff --git a/Documentation/technical/api-string-list.txt b/Documentation/technical/api-string-list.txt
index 5a0c14f..94d7a2b 100644
--- a/Documentation/technical/api-string-list.txt
+++ b/Documentation/technical/api-string-list.txt
@@ -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
---------------
diff --git a/Documentation/technical/pack-protocol.txt b/Documentation/technical/pack-protocol.txt
index 49cdc57..d51e20f 100644
--- a/Documentation/technical/pack-protocol.txt
+++ b/Documentation/technical/pack-protocol.txt
@@ -259,8 +259,10 @@ a positive depth, this step is skipped.
----
If the client has requested a positive depth, the server will compute
-the set of commits which are no deeper than the desired depth, starting
-at the client's wants. The server writes 'shallow' lines for each
+the set of commits which are no deeper than the desired depth. The set
+of commits start at the client's wants.
+
+The server writes 'shallow' lines for each
commit whose parents will not be sent as a result. The server writes
an 'unshallow' line for each commit which the client has indicated is
shallow, but is no longer shallow at the currently requested depth
diff --git a/Documentation/urls.txt b/Documentation/urls.txt
index 2890194..1d15ee7 100644
--- a/Documentation/urls.txt
+++ b/Documentation/urls.txt
@@ -6,8 +6,12 @@ address of the remote server, and the path to the repository.
Depending on the transport protocol, some of this information may be
absent.
-Git natively supports ssh, git, http, https, ftp, ftps, and rsync
-protocols. The following syntaxes may be used with them:
+Git supports ssh, git, http, and https protocols (in addition, ftp,
+and ftps can be used for fetching and rsync can be used for fetching
+and pushing, but these are inefficient and deprecated; do not use
+them).
+
+The following syntaxes may be used with them:
- ssh://{startsb}user@{endsb}host.xz{startsb}:port{endsb}/path/to/repo.git/
- git://host.xz{startsb}:port{endsb}/path/to/repo.git/
diff --git a/Documentation/user-manual.conf b/Documentation/user-manual.conf
index 339b309..d87294d 100644
--- a/Documentation/user-manual.conf
+++ b/Documentation/user-manual.conf
@@ -14,7 +14,7 @@ ifdef::backend-docbook[]
# "unbreak" docbook-xsl v1.68 for manpages. v1.69 works with or without this.
[listingblock]
<example><title>{title}</title>
-<literallayout>
+<literallayout class="monospaced">
|
</literallayout>
{title#}</example>
diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt
index 03d95dc..85651b5 100644
--- a/Documentation/user-manual.txt
+++ b/Documentation/user-manual.txt
@@ -1136,9 +1136,12 @@ Creating good commit messages
Though not required, it's a good idea to begin the commit message
with a single short (less than 50 character) line summarizing the
change, followed by a blank line and then a more thorough
-description. Tools that turn commits into email, for example, use
-the first line on the Subject line and the rest of the commit in the
-body.
+description. The text up to the first blank line in a commit
+message is treated as the commit title, and that title is used
+throughout git. For example, linkgit:git-format-patch[1] turns a
+commit into email, and it uses the title on the Subject line and the
+rest of the commit in the body.
+
[[ignoring-files]]
Ignoring files
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index d7ad644..b09d264 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v1.7.12-rc3
+DEF_VER=v1.8.0
LF='
'
diff --git a/Makefile b/Makefile
index a6933df..40829a9 100644
--- 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)
#
@@ -497,11 +515,13 @@ TEST_PROGRAMS_NEED_X += test-mergesort
TEST_PROGRAMS_NEED_X += test-mktemp
TEST_PROGRAMS_NEED_X += test-parse-options
TEST_PROGRAMS_NEED_X += test-path-utils
+TEST_PROGRAMS_NEED_X += test-regex
TEST_PROGRAMS_NEED_X += test-revision-walking
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 +616,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 +1237,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 +1278,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 +1328,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 +1423,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
@@ -1544,6 +1619,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 +1680,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 +1723,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 +1758,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 +1782,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
@@ -2544,6 +2641,7 @@ bin-wrappers/%: wrap-for-bin.sh
# with that.
export NO_SVN_TESTS
+export TEST_NO_MALLOC_CHECK
### Testing rules
@@ -2810,8 +2908,13 @@ endif
### Check documentation
#
+ALL_COMMANDS = $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS)
+ALL_COMMANDS += git
+ALL_COMMANDS += gitk
+ALL_COMMANDS += gitweb
+ALL_COMMANDS += git-gui git-citool
check-docs::
- @(for v in $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git gitk; \
+ @(for v in $(ALL_COMMANDS); \
do \
case "$$v" in \
git-merge-octopus | git-merge-ours | git-merge-recursive | \
@@ -2833,35 +2936,13 @@ check-docs::
sed -e '/^#/d' \
-e 's/[ ].*//' \
-e 's/^/listed /' command-list.txt; \
- ls -1 Documentation/git*txt | \
+ $(MAKE) -C Documentation print-man1 | \
+ grep '\.txt$$' | \
sed -e 's|Documentation/|documented |' \
-e 's/\.txt//'; \
) | while read how cmd; \
do \
- case "$$how,$$cmd" in \
- *,git-citool | \
- *,git-gui | \
- *,git-help | \
- documented,gitattributes | \
- documented,gitignore | \
- documented,gitmodules | \
- documented,gitcli | \
- documented,git-tools | \
- documented,gitcore-tutorial | \
- documented,gitcvs-migration | \
- documented,gitdiffcore | \
- documented,gitglossary | \
- documented,githooks | \
- documented,gitrepository-layout | \
- documented,gitrevisions | \
- documented,gittutorial | \
- documented,gittutorial-2 | \
- documented,git-bisect-lk2009 | \
- documented,git-remote-helpers | \
- documented,gitworkflows | \
- sentinel,not,matching,is,ok ) continue ;; \
- esac; \
- case " $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git gitk " in \
+ case " $(ALL_COMMANDS) " in \
*" $$cmd "*) ;; \
*) echo "removed but $$how: $$cmd" ;; \
esac; \
diff --git a/RelNotes b/RelNotes
index 19bb2eb..2484b38 120000
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/1.7.12.txt \ No newline at end of file
+Documentation/RelNotes/1.8.0.txt \ No newline at end of file
diff --git a/abspath.c b/abspath.c
index f04ac18..05f2d79 100644
--- 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 {
diff --git a/archive-zip.c b/archive-zip.c
index f5af81f..55f66b4 100644
--- a/archive-zip.c
+++ b/archive-zip.c
@@ -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;
diff --git a/archive.c b/archive.c
index a484433..4666404 100644
--- 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()
};
diff --git a/argv-array.c b/argv-array.c
index aab50d6..9e960d5 100644
--- a/argv-array.c
+++ b/argv-array.c
@@ -49,12 +49,21 @@ void argv_array_pushl(struct argv_array *array, ...)
va_end(ap);
}
+void argv_array_pop(struct argv_array *array)
+{
+ if (!array->argc)
+ return;
+ free((char *)array->argv[array->argc - 1]);
+ array->argv[array->argc - 1] = NULL;
+ array->argc--;
+}
+
void argv_array_clear(struct argv_array *array)
{
if (array->argv != empty_argv) {
int i;
for (i = 0; i < array->argc; i++)
- free((char **)array->argv[i]);
+ free((char *)array->argv[i]);
free(array->argv);
}
argv_array_init(array);
diff --git a/argv-array.h b/argv-array.h
index b3ef351..40248d4 100644
--- a/argv-array.h
+++ b/argv-array.h
@@ -16,6 +16,7 @@ void argv_array_push(struct argv_array *, const char *);
__attribute__((format (printf,2,3)))
void argv_array_pushf(struct argv_array *, const char *fmt, ...);
void argv_array_pushl(struct argv_array *, ...);
+void argv_array_pop(struct argv_array *);
void argv_array_clear(struct argv_array *);
const char **argv_array_detach(struct argv_array *array, int *argc);
void argv_array_free_detached(const char **argv);
diff --git a/attr.c b/attr.c
index b52efb5..887a9ae 100644
--- a/attr.c
+++ b/attr.c
@@ -306,7 +306,7 @@ static void free_attr_elem(struct attr_stack *e)
}
static const char *builtin_attr[] = {
- "[attr]binary -diff -text",
+ "[attr]binary -diff -merge -text",
NULL,
};
@@ -352,8 +352,11 @@ static struct attr_stack *read_attr_from_file(const char *path, int macro_ok)
char buf[2048];
int lineno = 0;
- if (!fp)
+ if (!fp) {
+ if (errno != ENOENT && errno != ENOTDIR)
+ warn_on_inaccessible(path);
return NULL;
+ }
res = xcalloc(1, sizeof(*res));
while (fgets(buf, sizeof(buf), fp))
handle_attr_line(res, buf, path, ++lineno, macro_ok);
diff --git a/bisect.c b/bisect.c
index 48acf73..1aad49b 100644
--- 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;
diff --git a/builtin.h b/builtin.h
index ba6626b..95116b8 100644
--- 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);
@@ -43,7 +41,7 @@ extern int check_pager_config(const char *cmd);
struct diff_options;
extern void setup_diff_pager(struct diff_options *);
-extern int textconv_object(const char *path, unsigned mode, const unsigned char *sha1, char **buf, unsigned long *buf_size);
+extern int textconv_object(const char *path, unsigned mode, const unsigned char *sha1, int sha1_valid, char **buf, unsigned long *buf_size);
extern int cmd_add(int argc, const char **argv, const char *prefix);
extern int cmd_annotate(int argc, const char **argv, const char *prefix);
diff --git a/builtin/add.c b/builtin/add.c
index 89dce56..e664100 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -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(),
};
diff --git a/builtin/apply.c b/builtin/apply.c
index d453c83..156b3ce 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -188,7 +188,6 @@ struct patch {
int is_new, is_delete; /* -1 = unknown, 0 = false, 1 = true */
int rejected;
unsigned ws_rule;
- unsigned long deflate_origlen;
int lines_added, lines_deleted;
int score;
unsigned int is_toplevel_relative:1;
@@ -1096,15 +1095,23 @@ static int gitdiff_unrecognized(const char *line, struct patch *patch)
return -1;
}
-static const char *stop_at_slash(const char *line, int llen)
+/*
+ * Skip p_value leading components from "line"; as we do not accept
+ * absolute paths, return NULL in that case.
+ */
+static const char *skip_tree_prefix(const char *line, int llen)
{
- int nslash = p_value;
+ int nslash;
int i;
+ if (!p_value)
+ return (llen && line[0] == '/') ? NULL : line;
+
+ nslash = p_value;
for (i = 0; i < llen; i++) {
int ch = line[i];
if (ch == '/' && --nslash <= 0)
- return &line[i];
+ return (i == 0) ? NULL : &line[i + 1];
}
return NULL;
}
@@ -1134,12 +1141,11 @@ static char *git_header_name(const char *line, int llen)
if (unquote_c_style(&first, line, &second))
goto free_and_fail1;
- /* advance to the first slash */
- cp = stop_at_slash(first.buf, first.len);
- /* we do not accept absolute paths */
- if (!cp || cp == first.buf)
+ /* strip the a/b prefix including trailing slash */
+ cp = skip_tree_prefix(first.buf, first.len);
+ if (!cp)
goto free_and_fail1;
- strbuf_remove(&first, 0, cp + 1 - first.buf);
+ strbuf_remove(&first, 0, cp - first.buf);
/*
* second points at one past closing dq of name.
@@ -1153,22 +1159,21 @@ static char *git_header_name(const char *line, int llen)
if (*second == '"') {
if (unquote_c_style(&sp, second, NULL))
goto free_and_fail1;
- cp = stop_at_slash(sp.buf, sp.len);
- if (!cp || cp == sp.buf)
+ cp = skip_tree_prefix(sp.buf, sp.len);
+ if (!cp)
goto free_and_fail1;
/* They must match, otherwise ignore */
- if (strcmp(cp + 1, first.buf))
+ if (strcmp(cp, first.buf))
goto free_and_fail1;
strbuf_release(&sp);
return strbuf_detach(&first, NULL);
}
/* unquoted second */
- cp = stop_at_slash(second, line + llen - second);
- if (!cp || cp == second)
+ cp = skip_tree_prefix(second, line + llen - second);
+ if (!cp)
goto free_and_fail1;
- cp++;
- if (line + llen - cp != first.len + 1 ||
+ if (line + llen - cp != first.len ||
memcmp(first.buf, cp, first.len))
goto free_and_fail1;
return strbuf_detach(&first, NULL);
@@ -1180,10 +1185,9 @@ static char *git_header_name(const char *line, int llen)
}
/* unquoted first name */
- name = stop_at_slash(line, llen);
- if (!name || name == line)
+ name = skip_tree_prefix(line, llen);
+ if (!name)
return NULL;
- name++;
/*
* since the first name is unquoted, a dq if exists must be
@@ -1197,10 +1201,9 @@ static char *git_header_name(const char *line, int llen)
if (unquote_c_style(&sp, second, NULL))
goto free_and_fail2;
- np = stop_at_slash(sp.buf, sp.len);
- if (!np || np == sp.buf)
+ np = skip_tree_prefix(sp.buf, sp.len);
+ if (!np)
goto free_and_fail2;
- np++;
len = sp.buf + sp.len - np;
if (len < second - name &&
@@ -1232,13 +1235,27 @@ static char *git_header_name(const char *line, int llen)
case '\n':
return NULL;
case '\t': case ' ':
- second = stop_at_slash(name + len, line_len - len);
+ /*
+ * Is this the separator between the preimage
+ * and the postimage pathname? Again, we are
+ * only interested in the case where there is
+ * no rename, as this is only to set def_name
+ * and a rename patch has the names elsewhere
+ * in an unambiguous form.
+ */
+ if (!name[len + 1])
+ return NULL; /* no postimage name */
+ second = skip_tree_prefix(name + len + 1,
+ line_len - (len + 1));
if (!second)
return NULL;
- second++;
- if (second[len] == '\n' && !strncmp(name, second, len)) {
+ /*
+ * Does len bytes starting at "name" and "second"
+ * (that are separated by one HT or SP we just
+ * found) exactly match?
+ */
+ if (second[len] == '\n' && !strncmp(name, second, len))
return xmemdupz(name, len);
- }
}
}
}
@@ -4297,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,
diff --git a/builtin/archive.c b/builtin/archive.c
index 931956d..9a1cfd3 100644
--- a/builtin/archive.c
+++ b/builtin/archive.c
@@ -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()
};
diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c
index 8d325a5..e3884e3 100644
--- a/builtin/bisect--helper.c
+++ b/builtin/bisect--helper.c
@@ -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()
};
diff --git a/builtin/blame.c b/builtin/blame.c
index 0d50273..c27ef21 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -22,12 +22,12 @@
#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
};
@@ -110,6 +110,7 @@ static int diff_hunks(mmfile_t *file_a, mmfile_t *file_b, long ctxlen,
int textconv_object(const char *path,
unsigned mode,
const unsigned char *sha1,
+ int sha1_valid,
char **buf,
unsigned long *buf_size)
{
@@ -117,7 +118,7 @@ int textconv_object(const char *path,
struct userdiff_driver *textconv;
df = alloc_filespec(path);
- fill_filespec(df, sha1, mode);
+ fill_filespec(df, sha1, sha1_valid, mode);
textconv = get_textconv(df);
if (!textconv) {
free_filespec(df);
@@ -142,7 +143,7 @@ static void fill_origin_blob(struct diff_options *opt,
num_read_blob++;
if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV) &&
- textconv_object(o->path, o->mode, o->blob_sha1, &file->ptr, &file_size))
+ textconv_object(o->path, o->mode, o->blob_sha1, 1, &file->ptr, &file_size))
;
else
file->ptr = read_sha1_file(o->blob_sha1, &type, &file_size);
@@ -406,8 +407,7 @@ static struct origin *find_origin(struct scoreboard *sb,
paths[1] = NULL;
diff_tree_setup_paths(paths, &diff_opts);
- if (diff_setup_done(&diff_opts) < 0)
- die("diff-setup");
+ diff_setup_done(&diff_opts);
if (is_null_sha1(origin->commit->object.sha1))
do_diff_cache(parent->tree->object.sha1, &diff_opts);
@@ -493,8 +493,7 @@ static struct origin *find_rename(struct scoreboard *sb,
diff_opts.single_follow = origin->path;
paths[0] = NULL;
diff_tree_setup_paths(paths, &diff_opts);
- if (diff_setup_done(&diff_opts) < 0)
- die("diff-setup");
+ diff_setup_done(&diff_opts);
if (is_null_sha1(origin->commit->object.sha1))
do_diff_cache(parent->tree->object.sha1, &diff_opts);
@@ -1074,8 +1073,7 @@ static int find_copy_in_parent(struct scoreboard *sb,
paths[0] = NULL;
diff_tree_setup_paths(paths, &diff_opts);
- if (diff_setup_done(&diff_opts) < 0)
- die("diff-setup");
+ diff_setup_done(&diff_opts);
/* Try "find copies harder" on new path if requested;
* we do not want to use diffcore_rename() actually to
@@ -2071,6 +2069,55 @@ static int git_blame_config(const char *var, const char *value, void *cb)
return git_default_config(var, value, cb);
}
+static void verify_working_tree_path(struct commit *work_tree, const char *path)
+{
+ struct commit_list *parents;
+
+ for (parents = work_tree->parents; parents; parents = parents->next) {
+ const unsigned char *commit_sha1 = parents->item->object.sha1;
+ unsigned char blob_sha1[20];
+ unsigned mode;
+
+ if (!get_tree_entry(commit_sha1, path, blob_sha1, &mode) &&
+ sha1_object_info(blob_sha1, NULL) == OBJ_BLOB)
+ return;
+ }
+ die("no such path '%s' in HEAD", path);
+}
+
+static struct commit_list **append_parent(struct commit_list **tail, const unsigned char *sha1)
+{
+ struct commit *parent;
+
+ parent = lookup_commit_reference(sha1);
+ if (!parent)
+ die("no such commit %s", sha1_to_hex(sha1));
+ return &commit_list_insert(parent, tail)->next;
+}
+
+static void append_merge_parents(struct commit_list **tail)
+{
+ int merge_head;
+ const char *merge_head_file = git_path("MERGE_HEAD");
+ struct strbuf line = STRBUF_INIT;
+
+ merge_head = open(merge_head_file, O_RDONLY);
+ if (merge_head < 0) {
+ if (errno == ENOENT)
+ return;
+ die("cannot open '%s' for reading", merge_head_file);
+ }
+
+ while (!strbuf_getwholeline_fd(&line, merge_head, '\n')) {
+ unsigned char sha1[20];
+ if (line.len < 40 || get_sha1_hex(line.buf, sha1))
+ die("unknown line in '%s': %s", merge_head_file, line.buf);
+ tail = append_parent(tail, sha1);
+ }
+ close(merge_head);
+ strbuf_release(&line);
+}
+
/*
* Prepare a dummy commit that represents the work tree (or staged) item.
* Note that annotating work tree item never works in the reverse.
@@ -2081,6 +2128,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
{
struct commit *commit;
struct origin *origin;
+ struct commit_list **parent_tail, *parent;
unsigned char head_sha1[20];
struct strbuf buf = STRBUF_INIT;
const char *ident;
@@ -2088,20 +2136,38 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
int size, len;
struct cache_entry *ce;
unsigned mode;
-
- if (get_sha1("HEAD", head_sha1))
- die("No such ref: HEAD");
+ struct strbuf msg = STRBUF_INIT;
time(&now);
commit = xcalloc(1, sizeof(*commit));
- commit->parents = xcalloc(1, sizeof(*commit->parents));
- commit->parents->item = lookup_commit_reference(head_sha1);
commit->object.parsed = 1;
commit->date = now;
commit->object.type = OBJ_COMMIT;
+ parent_tail = &commit->parents;
+
+ if (!resolve_ref_unsafe("HEAD", head_sha1, 1, NULL))
+ die("no such ref: HEAD");
+
+ parent_tail = append_parent(parent_tail, head_sha1);
+ append_merge_parents(parent_tail);
+ verify_working_tree_path(commit, path);
origin = make_origin(commit, path);
+ ident = fmt_ident("Not Committed Yet", "not.committed.yet", NULL, 0);
+ strbuf_addstr(&msg, "tree 0000000000000000000000000000000000000000\n");
+ for (parent = commit->parents; parent; parent = parent->next)
+ strbuf_addf(&msg, "parent %s\n",
+ sha1_to_hex(parent->item->object.sha1));
+ strbuf_addf(&msg,
+ "author %s\n"
+ "committer %s\n\n"
+ "Version of %s from %s\n",
+ ident, ident, path,
+ (!contents_from ? path :
+ (!strcmp(contents_from, "-") ? "standard input" : contents_from)));
+ commit->buffer = strbuf_detach(&msg, NULL);
+
if (!contents_from || strcmp("-", contents_from)) {
struct stat st;
const char *read_from;
@@ -2123,7 +2189,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
switch (st.st_mode & S_IFMT) {
case S_IFREG:
if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV) &&
- textconv_object(read_from, mode, null_sha1, &buf_ptr, &buf_len))
+ textconv_object(read_from, mode, null_sha1, 0, &buf_ptr, &buf_len))
strbuf_attach(&buf, buf_ptr, buf_len, buf_len + 1);
else if (strbuf_read_file(&buf, read_from, st.st_size) != st.st_size)
die_errno("cannot open or read '%s'", read_from);
@@ -2138,7 +2204,6 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
}
else {
/* Reading from stdin */
- contents_from = "standard input";
mode = 0;
if (strbuf_read(&buf, 0, 0) < 0)
die_errno("failed to read from stdin");
@@ -2183,16 +2248,6 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
*/
cache_tree_invalidate_path(active_cache_tree, path);
- commit->buffer = xmalloc(400);
- ident = fmt_ident("Not Committed Yet", "not.committed.yet", NULL, 0);
- snprintf(commit->buffer, 400,
- "tree 0000000000000000000000000000000000000000\n"
- "parent %s\n"
- "author %s\n"
- "committer %s\n\n"
- "Version of %s from %s\n",
- sha1_to_hex(head_sha1),
- ident, ident, path, contents_from ? contents_from : path);
return commit;
}
@@ -2315,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()
};
@@ -2516,7 +2571,7 @@ parse_done:
die("no such path %s in %s", path, final_commit_name);
if (DIFF_OPT_TST(&sb.revs->diffopt, ALLOW_TEXTCONV) &&
- textconv_object(path, o->mode, o->blob_sha1, (char **) &sb.final_buf,
+ textconv_object(path, o->mode, o->blob_sha1, 1, (char **) &sb.final_buf,
&sb.final_buf_size))
;
else
diff --git a/builtin/branch.c b/builtin/branch.c
index 0e060f2..ffd2684 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -17,12 +17,13 @@
#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."),
@@ -196,7 +197,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
free(name);
- name = xstrdup(mkpath(fmt, bname.buf));
+ name = mkpathdup(fmt, bname.buf);
if (read_ref(name, sha1)) {
error(remote_branch
? _("remote branch '%s' not found.")
@@ -249,7 +250,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 +355,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 +491,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 +521,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 +535,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 +714,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 +799,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 +857,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);
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index af74e77..00528dd 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -146,7 +146,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name)
die("git cat-file --textconv %s: <object> must be <sha1:path>",
obj_name);
- if (!textconv_object(obj_context.path, obj_context.mode, sha1, &buf, &size))
+ if (!textconv_object(obj_context.path, obj_context.mode, sha1, 1, &buf, &size))
die("git cat-file --textconv: unable to run textconv on %s",
obj_name);
break;
@@ -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()
};
diff --git a/builtin/check-attr.c b/builtin/check-attr.c
index 44c421e..075d01d 100644
--- a/builtin/check-attr.c
+++ b/builtin/check-attr.c
@@ -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 [-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()
};
diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c
index c16d82b..b1feda7 100644
--- a/builtin/checkout-index.c
+++ b/builtin/checkout-index.c
@@ -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()
};
diff --git a/builtin/checkout.c b/builtin/checkout.c
index d812219..781295b 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -22,29 +22,31 @@
#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,15 +339,15 @@ 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. */
init_revisions(&rev, NULL);
rev.diffopt.flags = opts->flags;
rev.diffopt.output_format |= DIFF_FORMAT_NAME_STATUS;
- if (diff_setup_done(&rev.diffopt) < 0)
- die(_("diff_setup_done failed"));
+ diff_setup_done(&rev.diffopt);
add_pending_object(&rev, head, NULL);
run_diff_index(&rev, 0);
}
@@ -332,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;
@@ -351,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
@@ -382,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));
@@ -394,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 {
@@ -480,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;
@@ -488,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;
}
@@ -515,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)
{
@@ -702,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);
@@ -726,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;
@@ -739,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)
@@ -756,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;
@@ -911,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;
@@ -924,38 +954,80 @@ static int switch_unborn_to_new_branch(struct checkout_opts *opts)
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(),
};
@@ -963,6 +1035,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);
@@ -972,26 +1045,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"));
@@ -1005,22 +1079,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.
@@ -1035,73 +1093,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);
}
diff --git a/builtin/clean.c b/builtin/clean.c
index 0c7b3d0..69c1cda 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -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()
};
diff --git a/builtin/clone.c b/builtin/clone.c
index e314b0b..ec2f75b 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -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)))
@@ -610,6 +610,54 @@ static void write_config(struct string_list *config)
}
}
+static void write_refspec_config(const char* src_ref_prefix,
+ const struct ref* our_head_points_at,
+ const struct ref* remote_head_points_at, struct strbuf* branch_top)
+{
+ struct strbuf key = STRBUF_INIT;
+ struct strbuf value = STRBUF_INIT;
+
+ if (option_mirror || !option_bare) {
+ if (option_single_branch && !option_mirror) {
+ if (option_branch) {
+ if (strstr(our_head_points_at->name, "refs/tags/"))
+ strbuf_addf(&value, "+%s:%s", our_head_points_at->name,
+ our_head_points_at->name);
+ else
+ strbuf_addf(&value, "+%s:%s%s", our_head_points_at->name,
+ branch_top->buf, option_branch);
+ } else if (remote_head_points_at) {
+ strbuf_addf(&value, "+%s:%s%s", remote_head_points_at->name,
+ branch_top->buf,
+ skip_prefix(remote_head_points_at->name, "refs/heads/"));
+ }
+ /*
+ * otherwise, the next "git fetch" will
+ * simply fetch from HEAD without updating
+ * any remote tracking branch, which is what
+ * we want.
+ */
+ } else {
+ strbuf_addf(&value, "+%s*:%s*", src_ref_prefix, branch_top->buf);
+ }
+ /* Configure the remote */
+ if (value.len) {
+ strbuf_addf(&key, "remote.%s.fetch", option_origin);
+ git_config_set_multivar(key.buf, value.buf, "^$", 0);
+ strbuf_reset(&key);
+
+ if (option_mirror) {
+ strbuf_addf(&key, "remote.%s.mirror", option_origin);
+ git_config_set(key.buf, "true");
+ strbuf_reset(&key);
+ }
+ }
+ }
+
+ strbuf_release(&key);
+ strbuf_release(&value);
+}
+
int cmd_clone(int argc, const char **argv, const char *prefix)
{
int is_bundle = 0, is_local;
@@ -700,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) {
@@ -755,20 +803,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
}
strbuf_addf(&value, "+%s*:%s*", src_ref_prefix, branch_top.buf);
-
- if (option_mirror || !option_bare) {
- /* Configure the remote */
- strbuf_addf(&key, "remote.%s.fetch", option_origin);
- git_config_set_multivar(key.buf, value.buf, "^$", 0);
- strbuf_reset(&key);
-
- if (option_mirror) {
- strbuf_addf(&key, "remote.%s.mirror", option_origin);
- git_config_set(key.buf, "true");
- strbuf_reset(&key);
- }
- }
-
strbuf_addf(&key, "remote.%s.url", option_origin);
git_config_set(key.buf, repo);
strbuf_reset(&key);
@@ -853,6 +887,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
"refs/heads/master");
}
+ write_refspec_config(src_ref_prefix, our_head_points_at,
+ remote_head_points_at, &branch_top);
+
if (is_local)
clone_local(path, git_dir);
else if (refs && complete_refs_before_fetch)
diff --git a/builtin/column.c b/builtin/column.c
index 5ea798a..e125a55 100644
--- a/builtin/column.c
+++ b/builtin/column.c
@@ -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()
};
diff --git a/builtin/commit.c b/builtin/commit.c
index 20cef95..a17a5df 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -28,14 +28,15 @@
#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;
@@ -478,6 +477,20 @@ static void export_one(const char *var, const char *s, const char *e, int hack)
strbuf_release(&buf);
}
+static int sane_ident_split(struct ident_split *person)
+{
+ if (!person->name_begin || !person->name_end ||
+ person->name_begin == person->name_end)
+ return 0; /* no human readable name */
+ if (!person->mail_begin || !person->mail_end ||
+ person->mail_begin == person->mail_end)
+ return 0; /* no usable mail */
+ if (!person->date_begin || !person->date_end ||
+ !person->tz_begin || !person->tz_end)
+ return 0;
+ return 1;
+}
+
static void determine_author_info(struct strbuf *author_ident)
{
char *name, *email, *date;
@@ -530,54 +543,14 @@ static void determine_author_info(struct strbuf *author_ident)
if (force_date)
date = force_date;
strbuf_addstr(author_ident, fmt_ident(name, email, date, IDENT_STRICT));
- if (!split_ident_line(&author, author_ident->buf, author_ident->len)) {
+ if (!split_ident_line(&author, author_ident->buf, author_ident->len) &&
+ sane_ident_split(&author)) {
export_one("GIT_AUTHOR_NAME", author.name_begin, author.name_end, 0);
export_one("GIT_AUTHOR_EMAIL", author.mail_begin, author.mail_end, 0);
export_one("GIT_AUTHOR_DATE", author.date_begin, author.tz_end, '@');
}
}
-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, '>');
@@ -702,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)
@@ -1169,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(),
};
@@ -1369,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()
@@ -1437,6 +1419,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
usage_with_options(builtin_commit_usage, builtin_commit_options);
wt_status_prepare(&s);
+ gitmodules_config();
git_config(git_commit_config, &s);
determine_whence(&s);
s.colopts = 0;
diff --git a/builtin/config.c b/builtin/config.c
index 8cd08da..e1c33e0 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -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(),
};
@@ -160,7 +160,7 @@ static int show_config(const char *key_, const char *value_, void *cb)
static int get_value(const char *key_, const char *regex_)
{
- int ret = -1;
+ int ret = CONFIG_GENERIC_ERROR;
char *global = NULL, *xdg = NULL, *repo_config = NULL;
const char *system_wide = NULL, *local;
struct config_include_data inc = CONFIG_INCLUDE_INIT;
@@ -196,11 +196,14 @@ static int get_value(const char *key_, const char *regex_)
if (regcomp(key_regexp, key, REG_EXTENDED)) {
fprintf(stderr, "Invalid key pattern: %s\n", key_);
free(key);
+ ret = CONFIG_INVALID_PATTERN;
goto free_strings;
}
} else {
- if (git_config_parse_key(key_, &key, NULL))
+ if (git_config_parse_key(key_, &key, NULL)) {
+ ret = CONFIG_INVALID_KEY;
goto free_strings;
+ }
}
if (regex_) {
@@ -212,6 +215,7 @@ static int get_value(const char *key_, const char *regex_)
regexp = (regex_t*)xmalloc(sizeof(regex_t));
if (regcomp(regexp, regex_, REG_EXTENDED)) {
fprintf(stderr, "Invalid pattern: %s\n", regex_);
+ ret = CONFIG_INVALID_PATTERN;
goto free_strings;
}
}
@@ -396,8 +400,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)
*/
die("$HOME not set");
- if (access(user_config, R_OK) &&
- xdg_config && !access(xdg_config, R_OK))
+ if (access_or_warn(user_config, R_OK) &&
+ xdg_config && !access_or_warn(xdg_config, R_OK))
given_config_file = xdg_config;
else
given_config_file = user_config;
diff --git a/builtin/count-objects.c b/builtin/count-objects.c
index c37cb98..9afaa88 100644
--- a/builtin/count-objects.c
+++ b/builtin/count-objects.c
@@ -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(),
};
diff --git a/builtin/describe.c b/builtin/describe.c
index 9f63067..9fe11ed 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -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(),
};
diff --git a/builtin/diff.c b/builtin/diff.c
index da8f6aa..9650be2 100644
--- a/builtin/diff.c
+++ b/builtin/diff.c
@@ -29,6 +29,8 @@ static void stuff_change(struct diff_options *opt,
unsigned old_mode, unsigned new_mode,
const unsigned char *old_sha1,
const unsigned char *new_sha1,
+ int old_sha1_valid,
+ int new_sha1_valid,
const char *old_name,
const char *new_name)
{
@@ -54,8 +56,8 @@ static void stuff_change(struct diff_options *opt,
one = alloc_filespec(old_name);
two = alloc_filespec(new_name);
- fill_filespec(one, old_sha1, old_mode);
- fill_filespec(two, new_sha1, new_mode);
+ fill_filespec(one, old_sha1, old_sha1_valid, old_mode);
+ fill_filespec(two, new_sha1, new_sha1_valid, new_mode);
diff_queue(&diff_queued_diff, one, two);
}
@@ -84,6 +86,7 @@ static int builtin_diff_b_f(struct rev_info *revs,
stuff_change(&revs->diffopt,
blob[0].mode, canon_mode(st.st_mode),
blob[0].sha1, null_sha1,
+ 1, 0,
path, path);
diffcore_std(&revs->diffopt);
diff_flush(&revs->diffopt);
@@ -108,6 +111,7 @@ static int builtin_diff_blobs(struct rev_info *revs,
stuff_change(&revs->diffopt,
blob[0].mode, blob[1].mode,
blob[0].sha1, blob[1].sha1,
+ 1, 1,
blob[0].name, blob[1].name);
diffcore_std(&revs->diffopt);
diff_flush(&revs->diffopt);
@@ -298,8 +302,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
argc = setup_revisions(argc, argv, &rev, NULL);
if (!rev.diffopt.output_format) {
rev.diffopt.output_format = DIFF_FORMAT_PATCH;
- if (diff_setup_done(&rev.diffopt) < 0)
- die(_("diff_setup_done failed"));
+ diff_setup_done(&rev.diffopt);
}
DIFF_OPT_SET(&rev.diffopt, RECURSIVE);
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 9ab6db3..12220ad 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -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()
};
diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c
index 149db88..e644398 100644
--- a/builtin/fetch-pack.c
+++ b/builtin/fetch-pack.c
@@ -10,6 +10,7 @@
#include "remote.h"
#include "run-command.h"
#include "transport.h"
+#include "version.h"
static int transfer_unpack_limit = -1;
static int fetch_unpack_limit = -1;
@@ -18,6 +19,7 @@ static int prefer_ofs_delta = 1;
static int no_done;
static int fetch_fsck_objects = -1;
static int transfer_fsck_objects = -1;
+static int agent_supported;
static struct fetch_pack_args args = {
/* .uploadpack = */ "git-upload-pack",
};
@@ -327,6 +329,8 @@ static int find_common(int fd[2], unsigned char *result_sha1,
if (args.no_progress) strbuf_addstr(&c, " no-progress");
if (args.include_tag) strbuf_addstr(&c, " include-tag");
if (prefer_ofs_delta) strbuf_addstr(&c, " ofs-delta");
+ if (agent_supported) strbuf_addf(&c, " agent=%s",
+ git_user_agent_sanitized());
packet_buf_write(&req_buf, "want %s%s\n", remote_hex, c.buf);
strbuf_release(&c);
} else
@@ -521,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;
}
@@ -595,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;
@@ -646,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;
@@ -777,12 +768,13 @@ 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);
unsigned char sha1[20];
+ const char *agent_feature;
+ int agent_len;
sort_ref_list(&ref, ref_compare_name);
@@ -814,12 +806,26 @@ static struct ref *do_fetch_pack(int fd[2],
fprintf(stderr, "Server supports side-band\n");
use_sideband = 1;
}
+ if (!server_supports("thin-pack"))
+ args.use_thin_pack = 0;
+ if (!server_supports("no-progress"))
+ args.no_progress = 0;
+ if (!server_supports("include-tag"))
+ args.include_tag = 0;
if (server_supports("ofs-delta")) {
if (args.verbose)
fprintf(stderr, "Server supports ofs-delta\n");
} else
prefer_ofs_delta = 0;
- if (everything_local(&ref, nr_match, match)) {
+
+ if ((agent_feature = server_feature_value("agent", &agent_len))) {
+ agent_supported = 1;
+ if (args.verbose && agent_len)
+ fprintf(stderr, "Server version is %.*s\n",
+ agent_len, agent_feature);
+ }
+
+ if (everything_local(&ref, sought)) {
packet_flush(fd[1]);
goto all_done;
}
@@ -839,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) {
@@ -902,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;
@@ -980,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
@@ -995,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);
}
}
@@ -1022,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);
@@ -1030,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);
@@ -1054,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;
@@ -1078,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;
diff --git a/builtin/fetch.c b/builtin/fetch.c
index bb9a074..4b5a898 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -14,12 +14,13 @@
#include "transport.h"
#include "submodule.h"
#include "connected.h"
+#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
};
@@ -56,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()
};
@@ -255,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;
}
@@ -271,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;
}
@@ -282,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;
@@ -317,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));
@@ -357,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;
@@ -554,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);
}
@@ -841,38 +841,39 @@ static int add_remote_or_group(const char *name, struct string_list *list)
return 1;
}
-static void add_options_to_argv(int *argc, const char **argv)
+static void add_options_to_argv(struct argv_array *argv)
{
if (dry_run)
- argv[(*argc)++] = "--dry-run";
+ argv_array_push(argv, "--dry-run");
if (prune)
- argv[(*argc)++] = "--prune";
+ argv_array_push(argv, "--prune");
if (update_head_ok)
- argv[(*argc)++] = "--update-head-ok";
+ argv_array_push(argv, "--update-head-ok");
if (force)
- argv[(*argc)++] = "--force";
+ argv_array_push(argv, "--force");
if (keep)
- argv[(*argc)++] = "--keep";
+ argv_array_push(argv, "--keep");
if (recurse_submodules == RECURSE_SUBMODULES_ON)
- argv[(*argc)++] = "--recurse-submodules";
+ argv_array_push(argv, "--recurse-submodules");
else if (recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND)
- argv[(*argc)++] = "--recurse-submodules=on-demand";
+ argv_array_push(argv, "--recurse-submodules=on-demand");
+ if (tags == TAGS_SET)
+ argv_array_push(argv, "--tags");
+ else if (tags == TAGS_UNSET)
+ argv_array_push(argv, "--no-tags");
if (verbosity >= 2)
- argv[(*argc)++] = "-v";
+ argv_array_push(argv, "-v");
if (verbosity >= 1)
- argv[(*argc)++] = "-v";
+ argv_array_push(argv, "-v");
else if (verbosity < 0)
- argv[(*argc)++] = "-q";
+ argv_array_push(argv, "-q");
}
static int fetch_multiple(struct string_list *list)
{
int i, result = 0;
- const char *argv[12] = { "fetch", "--append" };
- int argc = 2;
-
- add_options_to_argv(&argc, argv);
+ struct argv_array argv = ARGV_ARRAY_INIT;
if (!append && !dry_run) {
int errcode = truncate_fetch_head();
@@ -880,18 +881,22 @@ static int fetch_multiple(struct string_list *list)
return errcode;
}
+ argv_array_pushl(&argv, "fetch", "--append", NULL);
+ add_options_to_argv(&argv);
+
for (i = 0; i < list->nr; i++) {
const char *name = list->items[i].string;
- argv[argc] = name;
- argv[argc + 1] = NULL;
+ argv_array_push(&argv, name);
if (verbosity >= 0)
printf(_("Fetching %s\n"), name);
- if (run_command_v_opt(argv, RUN_GIT_CMD)) {
+ if (run_command_v_opt(argv.argv, RUN_GIT_CMD)) {
error(_("Could not fetch %s"), name);
result = 1;
}
+ argv_array_pop(&argv);
}
+ argv_array_clear(&argv);
return result;
}
@@ -1007,13 +1012,14 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
}
if (!result && (recurse_submodules != RECURSE_SUBMODULES_OFF)) {
- const char *options[10];
- int num_options = 0;
- add_options_to_argv(&num_options, options);
- result = fetch_populated_submodules(num_options, options,
+ struct argv_array options = ARGV_ARRAY_INIT;
+
+ add_options_to_argv(&options);
+ result = fetch_populated_submodules(&options,
submodule_prefix,
recurse_submodules,
verbosity < 0);
+ argv_array_clear(&options);
}
/* All names were strdup()ed or strndup()ed */
diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
index 2c4d435..e2e27b2 100644
--- a/builtin/fmt-merge-msg.c
+++ b/builtin/fmt-merge-msg.c
@@ -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()
};
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index b01d76a..7f059c3 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -962,7 +962,9 @@ static int opt_parse_sort(const struct option *opt, const char *arg, int unset)
if (!arg) /* should --no-sort void the list ? */
return -1;
- *sort_tail = s = xcalloc(1, sizeof(*s));
+ s = xcalloc(1, sizeof(*s));
+ s->next = *sort_tail;
+ *sort_tail = s;
if (*arg == '-') {
s->reverse = 1;
@@ -974,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
};
@@ -989,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(),
};
diff --git a/builtin/fsck.c b/builtin/fsck.c
index a710227..bb9a2cd 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -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(),
};
diff --git a/builtin/gc.c b/builtin/gc.c
index 9b4232c..6be6c8d 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -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 "
diff --git a/builtin/grep.c b/builtin/grep.c
index 29adb0a..82530a6 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -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
};
@@ -209,6 +209,7 @@ static void start_threads(struct grep_opt *opt)
int err;
struct grep_opt *o = grep_opt_dup(opt);
o->output = strbuf_out;
+ o->debug = 0;
compile_grep_patterns(o);
err = pthread_create(&threads[i], NULL, run, o);
@@ -260,6 +261,53 @@ static int wait_all(void)
}
#endif
+static int parse_pattern_type_arg(const char *opt, const char *arg)
+{
+ if (!strcmp(arg, "default"))
+ return GREP_PATTERN_TYPE_UNSPECIFIED;
+ else if (!strcmp(arg, "basic"))
+ return GREP_PATTERN_TYPE_BRE;
+ else if (!strcmp(arg, "extended"))
+ return GREP_PATTERN_TYPE_ERE;
+ else if (!strcmp(arg, "fixed"))
+ return GREP_PATTERN_TYPE_FIXED;
+ else if (!strcmp(arg, "perl"))
+ return GREP_PATTERN_TYPE_PCRE;
+ die("bad %s argument: %s", opt, arg);
+}
+
+static void grep_pattern_type_options(const int pattern_type, struct grep_opt *opt)
+{
+ switch (pattern_type) {
+ case GREP_PATTERN_TYPE_UNSPECIFIED:
+ /* fall through */
+
+ case GREP_PATTERN_TYPE_BRE:
+ opt->fixed = 0;
+ opt->pcre = 0;
+ opt->regflags &= ~REG_EXTENDED;
+ break;
+
+ case GREP_PATTERN_TYPE_ERE:
+ opt->fixed = 0;
+ opt->pcre = 0;
+ opt->regflags |= REG_EXTENDED;
+ break;
+
+ case GREP_PATTERN_TYPE_FIXED:
+ opt->fixed = 1;
+ opt->pcre = 0;
+ opt->regflags &= ~REG_EXTENDED;
+ break;
+
+ case GREP_PATTERN_TYPE_PCRE:
+ opt->fixed = 0;
+ opt->pcre = 1;
+ opt->regflags &= ~REG_EXTENDED;
+ break;
+ }
+}
+
static int grep_config(const char *var, const char *value, void *cb)
{
struct grep_opt *opt = cb;
@@ -270,12 +318,17 @@ static int grep_config(const char *var, const char *value, void *cb)
if (!strcmp(var, "grep.extendedregexp")) {
if (git_config_bool(var, value))
- opt->regflags |= REG_EXTENDED;
+ opt->extended_regexp_option = 1;
else
- opt->regflags &= ~REG_EXTENDED;
+ opt->extended_regexp_option = 0;
return 0;
}
+ if (!strcmp(var, "grep.patterntype")) {
+ opt->pattern_type_option = parse_pattern_type_arg(var, value);
+ return 0;
+ }
+
if (!strcmp(var, "grep.linenumber")) {
opt->linenum = git_config_bool(var, value);
return 0;
@@ -669,95 +722,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, "",
@@ -769,16 +815,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,
+ 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()
};
@@ -799,6 +848,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
opt.header_tail = &opt.header_list;
opt.regflags = REG_NEWLINE;
opt.max_depth = -1;
+ opt.pattern_type_option = GREP_PATTERN_TYPE_UNSPECIFIED;
+ opt.extended_regexp_option = 0;
strcpy(opt.color_context, "");
strcpy(opt.color_filename, "");
@@ -824,28 +875,13 @@ 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 */
- }
+
+ if (pattern_type_arg != GREP_PATTERN_TYPE_UNSPECIFIED)
+ grep_pattern_type_options(pattern_type_arg, &opt);
+ else if (opt.pattern_type_option != GREP_PATTERN_TYPE_UNSPECIFIED)
+ grep_pattern_type_options(opt.pattern_type_option, &opt);
+ else if (opt.extended_regexp_option)
+ grep_pattern_type_options(GREP_PATTERN_TYPE_ERE, &opt);
if (use_index && !startup_info->have_repository)
/* die the same way as if we did it at the beginning */
diff --git a/builtin/hash-object.c b/builtin/hash-object.c
index 33911fd..8d184f1 100644
--- a/builtin/hash-object.c
+++ b/builtin/hash-object.c
@@ -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()
};
diff --git a/builtin/help.c b/builtin/help.c
index efea4f5..bd86253 100644
--- a/builtin/help.c
+++ b/builtin/help.c
@@ -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
};
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 953dd30..43d364b 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -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=")) {
diff --git a/builtin/init-db.c b/builtin/init-db.c
index 244fb7f..78aa387 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -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()
};
diff --git a/builtin/log.c b/builtin/log.c
index ecc2793..09cf43e 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -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()
};
@@ -109,9 +109,9 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |
PARSE_OPT_KEEP_DASHDASH);
- argc = setup_revisions(argc, argv, rev, opt);
if (quiet)
rev->diffopt.output_format |= DIFF_FORMAT_NO_OUTPUT;
+ argc = setup_revisions(argc, argv, rev, opt);
/* Any arguments at this point are not recognized */
if (argc > 1)
@@ -456,7 +456,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
init_revisions(&rev, prefix);
rev.diff = 1;
rev.always_show_header = 1;
- rev.no_walk = 1;
+ rev.no_walk = REVISION_WALK_NO_WALK_SORTED;
rev.diffopt.stat_width = -1; /* Scale to real terminal size */
memset(&opt, 0, sizeof(opt));
@@ -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"),
- OPT_STRING(0, "suffix", &fmt_patch_suffix, "sfx",
- "use <sfx> instead of '.patch'"),
+ N_("use simple number sequence for output file names")),
+ OPT_STRING(0, "suffix", &fmt_patch_suffix, N_("sfx"),
+ N_("use <sfx> instead of '.patch'")),
OPT_INTEGER(0, "start-number", &start_number,
- "start numbering patches at <n> instead of 1"),
- { OPTION_CALLBACK, 0, "subject-prefix", &rev, "prefix",
- "Use [<prefix>] instead of [PATCH]",
+ N_("start numbering patches at <n> instead of 1")),
+ { OPTION_CALLBACK, 0, "subject-prefix", &rev, N_("prefix"),
+ N_("Use [<prefix>] instead of [PATCH]"),
PARSE_OPT_NONEG, subject_prefix_callback },
{ OPTION_CALLBACK, 'o', "output-directory", &output_directory,
- "dir", "store resulting files in <dir>",
+ N_("dir"), N_("store resulting files in <dir>"),
PARSE_OPT_NONEG, output_directory_callback },
{ OPTION_CALLBACK, 'k', "keep-subject", &rev, NULL,
- "don't strip/add [PATCH]",
+ N_("don't strip/add [PATCH]"),
PARSE_OPT_NOARG | PARSE_OPT_NONEG, keep_callback },
OPT_BOOLEAN(0, "no-binary", &no_binary_diff,
- "don't output binary diffs"),
+ N_("don't output binary diffs")),
OPT_BOOLEAN(0, "ignore-if-in-upstream", &ignore_if_in_upstream,
- "don't include a patch matching a commit upstream"),
+ N_("don't include a patch matching a commit upstream")),
{ OPTION_BOOLEAN, 'p', "no-stat", &use_patch_format, NULL,
- "show patch format instead of default (patch + stat)",
+ N_("show patch format instead of default (patch + stat)"),
PARSE_OPT_NONEG | PARSE_OPT_NOARG },
- OPT_GROUP("Messaging"),
- { OPTION_CALLBACK, 0, "add-header", NULL, "header",
- "add email header", 0, header_callback },
- { OPTION_CALLBACK, 0, "to", NULL, "email", "add To: header",
+ OPT_GROUP(N_("Messaging")),
+ { OPTION_CALLBACK, 0, "add-header", NULL, N_("header"),
+ N_("add email header"), 0, header_callback },
+ { OPTION_CALLBACK, 0, "to", NULL, N_("email"), N_("add To: header"),
0, to_callback },
- { OPTION_CALLBACK, 0, "cc", NULL, "email", "add Cc: header",
+ { OPTION_CALLBACK, 0, "cc", NULL, N_("email"), N_("add Cc: header"),
0, cc_callback },
- OPT_STRING(0, "in-reply-to", &in_reply_to, "message-id",
- "make first mail a reply to <message-id>"),
- { OPTION_CALLBACK, 0, "attach", &rev, "boundary",
- "attach the patch", PARSE_OPT_OPTARG,
+ OPT_STRING(0, "in-reply-to", &in_reply_to, N_("message-id"),
+ N_("make first mail a reply to <message-id>")),
+ { OPTION_CALLBACK, 0, "attach", &rev, N_("boundary"),
+ N_("attach the patch"), PARSE_OPT_OPTARG,
attach_callback },
- { OPTION_CALLBACK, 0, "inline", &rev, "boundary",
- "inline the patch",
+ { OPTION_CALLBACK, 0, "inline", &rev, N_("boundary"),
+ N_("inline the patch"),
PARSE_OPT_OPTARG | PARSE_OPT_NONEG,
inline_callback },
- { OPTION_CALLBACK, 0, "thread", &thread, "style",
- "enable message threading, styles: shallow, deep",
+ { OPTION_CALLBACK, 0, "thread", &thread, N_("style"),
+ N_("enable message threading, styles: shallow, deep"),
PARSE_OPT_OPTARG, thread_callback },
- OPT_STRING(0, "signature", &signature, "signature",
- "add a signature"),
+ OPT_STRING(0, "signature", &signature, N_("signature"),
+ N_("add a signature")),
OPT_BOOLEAN(0, "quiet", &quiet,
- "don't print the patch filenames"),
+ N_("don't print the patch filenames")),
OPT_END()
};
@@ -1306,7 +1303,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
if (hashcmp(o[0].item->sha1, o[1].item->sha1) == 0)
return 0;
}
- get_patch_ids(&rev, &ids, prefix);
+ get_patch_ids(&rev, &ids);
}
if (!use_stdout)
@@ -1443,7 +1440,7 @@ static int add_pending_commit(const char *arg, struct rev_info *revs, int flags)
}
static const char * const cherry_usage[] = {
- "git cherry [-v] [<upstream> [<head> [<limit>]]]",
+ N_("git cherry [-v] [<upstream> [<head> [<limit>]]]"),
NULL
};
@@ -1477,7 +1474,7 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
struct option options[] = {
OPT__ABBREV(&abbrev),
- OPT__VERBOSE(&verbose, "be verbose"),
+ OPT__VERBOSE(&verbose, N_("be verbose")),
OPT_END()
};
@@ -1508,10 +1505,7 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
}
init_revisions(&revs, prefix);
- revs.diff = 1;
- revs.combine_merges = 0;
- revs.ignore_merges = 1;
- DIFF_OPT_SET(&revs.diffopt, RECURSIVE);
+ revs.max_parents = 1;
if (add_pending_commit(head, &revs, 0))
die(_("Unknown commit %s"), head);
@@ -1525,7 +1519,7 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
return 0;
}
- get_patch_ids(&revs, &ids, prefix);
+ get_patch_ids(&revs, &ids);
if (limit && add_pending_commit(limit, &revs, UNINTERESTING))
die(_("Unknown commit %s"), limit);
@@ -1534,10 +1528,6 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
if (prepare_revision_walk(&revs))
die(_("revision walk setup failed"));
while ((commit = get_revision(&revs)) != NULL) {
- /* ignore merges */
- if (commit->parents && commit->parents->next)
- continue;
-
commit_list_insert(commit, &list);
}
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 31b3f2d..b5434af 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -405,7 +405,7 @@ int report_path_error(const char *ps_matched, const char **pathspec, const char
}
static const char * const ls_files_usage[] = {
- "git ls-files [options] [<file>...]",
+ N_("git ls-files [options] [<file>...]"),
NULL
};
@@ -457,57 +457,57 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
struct dir_struct dir;
struct option builtin_ls_files_options[] = {
{ 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('t', NULL, &show_tag,
- "identify the file status with tags"),
+ N_("identify the file status with tags")),
OPT_BOOLEAN('v', NULL, &show_valid_bit,
- "use lowercase letters for 'assume unchanged' files"),
+ N_("use lowercase letters for 'assume unchanged' files")),
OPT_BOOLEAN('c', "cached", &show_cached,
- "show cached files in the output (default)"),
+ N_("show cached files in the output (default)")),
OPT_BOOLEAN('d', "deleted", &show_deleted,
- "show deleted files in the output"),
+ N_("show deleted files in the output")),
OPT_BOOLEAN('m', "modified", &show_modified,
- "show modified files in the output"),
+ N_("show modified files in the output")),
OPT_BOOLEAN('o', "others", &show_others,
- "show other files in the output"),
+ N_("show other files in the output")),
OPT_BIT('i', "ignored", &dir.flags,
- "show ignored files in the output",
+ N_("show ignored files in the output"),
DIR_SHOW_IGNORED),
OPT_BOOLEAN('s', "stage", &show_stage,
- "show staged contents' object name in the output"),
+ N_("show staged contents' object name in the output")),
OPT_BOOLEAN('k', "killed", &show_killed,
- "show files on the filesystem that need to be removed"),
+ N_("show files on the filesystem that need to be removed")),
OPT_BIT(0, "directory", &dir.flags,
- "show 'other' directories' name only",
+ N_("show 'other' directories' name only"),
DIR_SHOW_OTHER_DIRECTORIES),
OPT_NEGBIT(0, "empty-directory", &dir.flags,
- "don't show empty directories",
+ N_("don't show empty directories"),
DIR_HIDE_EMPTY_DIRECTORIES),
OPT_BOOLEAN('u', "unmerged", &show_unmerged,
- "show unmerged files in the output"),
+ N_("show unmerged files in the output")),
OPT_BOOLEAN(0, "resolve-undo", &show_resolve_undo,
- "show resolve-undo information"),
- { OPTION_CALLBACK, 'x', "exclude", &dir.exclude_list[EXC_CMDL], "pattern",
- "skip files matching pattern",
+ N_("show resolve-undo information")),
+ { OPTION_CALLBACK, 'x', "exclude", &dir.exclude_list[EXC_CMDL], N_("pattern"),
+ N_("skip files matching pattern"),
0, option_parse_exclude },
- { OPTION_CALLBACK, 'X', "exclude-from", &dir, "file",
- "exclude patterns are read from <file>",
+ { OPTION_CALLBACK, 'X', "exclude-from", &dir, N_("file"),
+ N_("exclude patterns are read from <file>"),
0, option_parse_exclude_from },
- OPT_STRING(0, "exclude-per-directory", &dir.exclude_per_dir, "file",
- "read additional per-directory exclude patterns in <file>"),
+ OPT_STRING(0, "exclude-per-directory", &dir.exclude_per_dir, N_("file"),
+ N_("read additional per-directory exclude patterns in <file>")),
{ OPTION_CALLBACK, 0, "exclude-standard", &dir, NULL,
- "add the standard git exclusions",
+ N_("add the standard git exclusions"),
PARSE_OPT_NOARG, option_parse_exclude_standard },
{ OPTION_SET_INT, 0, "full-name", &prefix_len, NULL,
- "make the output relative to the project top directory",
+ N_("make the output relative to the project top directory"),
PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL },
OPT_BOOLEAN(0, "error-unmatch", &error_unmatch,
- "if any <file> is not in the index, treat this as an error"),
- OPT_STRING(0, "with-tree", &with_tree, "tree-ish",
- "pretend that paths removed since <tree-ish> are still present"),
+ N_("if any <file> is not in the index, treat this as an error")),
+ OPT_STRING(0, "with-tree", &with_tree, N_("tree-ish"),
+ N_("pretend that paths removed since <tree-ish> are still present")),
OPT__ABBREV(&abbrev),
- OPT_BOOLEAN(0, "debug", &debug_mode, "show debugging data"),
+ OPT_BOOLEAN(0, "debug", &debug_mode, N_("show debugging data")),
OPT_END()
};
diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c
index 41c88a9..25e83cf 100644
--- a/builtin/ls-remote.c
+++ b/builtin/ls-remote.c
@@ -5,7 +5,7 @@
static const char ls_remote_usage[] =
"git ls-remote [--heads] [--tags] [-u <exec> | --upload-pack <exec>]\n"
-" [-q|--quiet] [--exit-code] [<repository> [<refs>...]]";
+" [-q|--quiet] [--exit-code] [--get-url] [<repository> [<refs>...]]";
/*
* Is there one among the list of patterns that match the tail part
diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c
index 6b666e1..235c17c 100644
--- a/builtin/ls-tree.c
+++ b/builtin/ls-tree.c
@@ -24,7 +24,7 @@ static int chomp_prefix;
static const char *ls_tree_prefix;
static const char * const ls_tree_usage[] = {
- "git ls-tree [<options>] <tree-ish> [<path>...]",
+ N_("git ls-tree [<options>] <tree-ish> [<path>...]"),
NULL
};
@@ -122,25 +122,25 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
struct tree *tree;
int i, full_tree = 0;
const struct option ls_tree_options[] = {
- OPT_BIT('d', NULL, &ls_options, "only show trees",
+ OPT_BIT('d', NULL, &ls_options, N_("only show trees"),
LS_TREE_ONLY),
- OPT_BIT('r', NULL, &ls_options, "recurse into subtrees",
+ OPT_BIT('r', NULL, &ls_options, N_("recurse into subtrees"),
LS_RECURSIVE),
- OPT_BIT('t', NULL, &ls_options, "show trees when recursing",
+ OPT_BIT('t', NULL, &ls_options, N_("show trees when recursing"),
LS_SHOW_TREES),
OPT_SET_INT('z', NULL, &line_termination,
- "terminate entries with NUL byte", 0),
- OPT_BIT('l', "long", &ls_options, "include object size",
+ N_("terminate entries with NUL byte"), 0),
+ OPT_BIT('l', "long", &ls_options, N_("include object size"),
LS_SHOW_SIZE),
- OPT_BIT(0, "name-only", &ls_options, "list only filenames",
+ OPT_BIT(0, "name-only", &ls_options, N_("list only filenames"),
LS_NAME_ONLY),
- OPT_BIT(0, "name-status", &ls_options, "list only filenames",
+ OPT_BIT(0, "name-status", &ls_options, N_("list only filenames"),
LS_NAME_ONLY),
OPT_SET_INT(0, "full-name", &chomp_prefix,
- "use full path names", 0),
+ N_("use full path names"), 0),
OPT_BOOLEAN(0, "full-tree", &full_tree,
- "list entire tree; not just current directory "
- "(implies --full-name)"),
+ N_("list entire tree; not just current directory "
+ "(implies --full-name)")),
OPT__ABBREV(&abbrev),
OPT_END()
};
diff --git a/builtin/mailinfo.c b/builtin/mailinfo.c
index eaf9e15..da23140 100644
--- a/builtin/mailinfo.c
+++ b/builtin/mailinfo.c
@@ -19,9 +19,6 @@ static struct strbuf email = STRBUF_INIT;
static enum {
TE_DONTCARE, TE_QP, TE_BASE64
} transfer_encoding;
-static enum {
- TYPE_TEXT, TYPE_OTHER
-} message_type;
static struct strbuf charset = STRBUF_INIT;
static int patch_lines;
@@ -160,10 +157,9 @@ static int slurp_attr(const char *line, const char *name, struct strbuf *attr)
const char *ends, *ap = strcasestr(line, name);
size_t sz;
- if (!ap) {
- strbuf_setlen(attr, 0);
+ strbuf_setlen(attr, 0);
+ if (!ap)
return 0;
- }
ap += strlen(name);
if (*ap == '"') {
ap++;
@@ -185,8 +181,6 @@ static void handle_content_type(struct strbuf *line)
struct strbuf *boundary = xmalloc(sizeof(struct strbuf));
strbuf_init(boundary, line->len);
- if (!strcasestr(line->buf, "text/"))
- message_type = TYPE_OTHER;
if (slurp_attr(line->buf, "boundary=", boundary)) {
strbuf_insert(boundary, 0, "--", 2);
if (++content_top > &content[MAX_BOUNDARIES]) {
@@ -232,7 +226,9 @@ static void cleanup_subject(struct strbuf *subject)
case 'r': case 'R':
if (subject->len <= at + 3)
break;
- if (!memcmp(subject->buf + at + 1, "e:", 2)) {
+ if ((subject->buf[at + 1] == 'e' ||
+ subject->buf[at + 1] == 'E') &&
+ subject->buf[at + 2] == ':') {
strbuf_remove(subject, at, 3);
continue;
}
@@ -481,36 +477,12 @@ static struct strbuf *decode_b_segment(const struct strbuf *b_seg)
return out;
}
-/*
- * When there is no known charset, guess.
- *
- * Right now we assume that if the target is UTF-8 (the default),
- * and it already looks like UTF-8 (which includes US-ASCII as its
- * subset, of course) then that is what it is and there is nothing
- * to do.
- *
- * Otherwise, we default to assuming it is Latin1 for historical
- * reasons.
- */
-static const char *guess_charset(const struct strbuf *line, const char *target_charset)
-{
- if (is_encoding_utf8(target_charset)) {
- if (is_utf8(line->buf))
- return NULL;
- }
- return "ISO8859-1";
-}
-
static void convert_to_utf8(struct strbuf *line, const char *charset)
{
char *out;
- if (!charset || !*charset) {
- charset = guess_charset(line, metainfo_charset);
- if (!charset)
- return;
- }
-
+ if (!charset || !*charset)
+ return;
if (!strcasecmp(metainfo_charset, charset))
return;
out = reencode_string(line->buf, metainfo_charset, charset);
@@ -680,7 +652,6 @@ again:
/* set some defaults */
transfer_encoding = TE_DONTCARE;
strbuf_reset(&charset);
- message_type = TYPE_TEXT;
/* slurp in this section's info */
while (read_one_header_line(&line, fin))
@@ -894,11 +865,6 @@ static void handle_body(void)
strbuf_insert(&line, 0, prev.buf, prev.len);
strbuf_reset(&prev);
- /* binary data most likely doesn't have newlines */
- if (message_type != TYPE_TEXT) {
- handle_filter(&line);
- break;
- }
/*
* This is a decoded line that may contain
* multiple new lines. Pass only one chunk
diff --git a/builtin/merge-base.c b/builtin/merge-base.c
index 4f30f1b..1bc7991 100644
--- a/builtin/merge-base.c
+++ b/builtin/merge-base.c
@@ -23,9 +23,10 @@ static int show_merge_base(struct commit **rev, int rev_nr, int show_all)
}
static const char * const merge_base_usage[] = {
- "git merge-base [-a|--all] <commit> <commit>...",
- "git merge-base [-a|--all] --octopus <commit>...",
- "git merge-base --independent <commit>...",
+ N_("git merge-base [-a|--all] <commit> <commit>..."),
+ N_("git merge-base [-a|--all] --octopus <commit>..."),
+ N_("git merge-base --independent <commit>..."),
+ N_("git merge-base --is-ancestor <commit> <commit>"),
NULL
};
@@ -70,6 +71,20 @@ static int handle_octopus(int count, const char **args, int reduce, int show_all
return 0;
}
+static int handle_is_ancestor(int argc, const char **argv)
+{
+ struct commit *one, *two;
+
+ if (argc != 2)
+ die("--is-ancestor takes exactly two commits");
+ one = get_commit_reference(argv[0]);
+ two = get_commit_reference(argv[1]);
+ if (in_merge_bases(one, two))
+ return 0;
+ else
+ return 1;
+}
+
int cmd_merge_base(int argc, const char **argv, const char *prefix)
{
struct commit **rev;
@@ -77,11 +92,14 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix)
int show_all = 0;
int octopus = 0;
int reduce = 0;
+ int is_ancestor = 0;
struct option options[] = {
- OPT_BOOLEAN('a', "all", &show_all, "output all common ancestors"),
- OPT_BOOLEAN(0, "octopus", &octopus, "find ancestors for a single n-way merge"),
- OPT_BOOLEAN(0, "independent", &reduce, "list revs not reachable from others"),
+ OPT_BOOLEAN('a', "all", &show_all, N_("output all common ancestors")),
+ OPT_BOOLEAN(0, "octopus", &octopus, N_("find ancestors for a single n-way merge")),
+ OPT_BOOLEAN(0, "independent", &reduce, N_("list revs not reachable from others")),
+ OPT_BOOLEAN(0, "is-ancestor", &is_ancestor,
+ N_("is the first one ancestor of the other?")),
OPT_END()
};
@@ -89,6 +107,10 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix)
argc = parse_options(argc, argv, prefix, options, merge_base_usage, 0);
if (!octopus && !reduce && argc < 2)
usage_with_options(merge_base_usage, options);
+ if (is_ancestor && (show_all | octopus | reduce))
+ die("--is-ancestor cannot be used with other options");
+ if (is_ancestor)
+ return handle_is_ancestor(argc, argv);
if (reduce && (show_all || octopus))
die("--independent cannot be used with other options");
diff --git a/builtin/merge-file.c b/builtin/merge-file.c
index 6f0efef..c0570f2 100644
--- a/builtin/merge-file.c
+++ b/builtin/merge-file.c
@@ -5,7 +5,7 @@
#include "parse-options.h"
static const char *const merge_file_usage[] = {
- "git merge-file [options] [-L name1 [-L orig [-L name2]]] file1 orig_file file2",
+ N_("git merge-file [options] [-L name1 [-L orig [-L name2]]] file1 orig_file file2"),
NULL
};
@@ -30,19 +30,19 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
int quiet = 0;
int prefixlen = 0;
struct option options[] = {
- OPT_BOOLEAN('p', "stdout", &to_stdout, "send results to standard output"),
- OPT_SET_INT(0, "diff3", &xmp.style, "use a diff3 based merge", XDL_MERGE_DIFF3),
- OPT_SET_INT(0, "ours", &xmp.favor, "for conflicts, use our version",
+ OPT_BOOLEAN('p', "stdout", &to_stdout, N_("send results to standard output")),
+ OPT_SET_INT(0, "diff3", &xmp.style, N_("use a diff3 based merge"), XDL_MERGE_DIFF3),
+ OPT_SET_INT(0, "ours", &xmp.favor, N_("for conflicts, use our version"),
XDL_MERGE_FAVOR_OURS),
- OPT_SET_INT(0, "theirs", &xmp.favor, "for conflicts, use their version",
+ OPT_SET_INT(0, "theirs", &xmp.favor, N_("for conflicts, use their version"),
XDL_MERGE_FAVOR_THEIRS),
- OPT_SET_INT(0, "union", &xmp.favor, "for conflicts, use a union version",
+ OPT_SET_INT(0, "union", &xmp.favor, N_("for conflicts, use a union version"),
XDL_MERGE_FAVOR_UNION),
OPT_INTEGER(0, "marker-size", &xmp.marker_size,
- "for conflicts, use this marker size"),
- OPT__QUIET(&quiet, "do not warn about conflicts"),
- OPT_CALLBACK('L', NULL, names, "name",
- "set labels for file1/orig_file/file2", &label_cb),
+ N_("for conflicts, use this marker size")),
+ OPT__QUIET(&quiet, N_("do not warn about conflicts")),
+ OPT_CALLBACK('L', NULL, names, N_("name"),
+ N_("set labels for file1/orig_file/file2"), &label_cb),
OPT_END(),
};
diff --git a/builtin/merge.c b/builtin/merge.c
index dd50a0c..0ec8f0d 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -40,9 +40,9 @@ struct strategy {
};
static const char * const builtin_merge_usage[] = {
- "git merge [options] [<commit>...]",
- "git merge [options] <msg> HEAD <commit>",
- "git merge --abort",
+ N_("git merge [options] [<commit>...]"),
+ N_("git merge [options] <msg> HEAD <commit>"),
+ N_("git merge --abort"),
NULL
};
@@ -180,39 +180,39 @@ static int option_parse_n(const struct option *opt,
static struct option builtin_merge_options[] = {
{ OPTION_CALLBACK, 'n', NULL, NULL, NULL,
- "do not show a diffstat at the end of the merge",
+ N_("do not show a diffstat at the end of the merge"),
PARSE_OPT_NOARG, option_parse_n },
OPT_BOOLEAN(0, "stat", &show_diffstat,
- "show a diffstat at the end of the merge"),
- OPT_BOOLEAN(0, "summary", &show_diffstat, "(synonym to --stat)"),
- { OPTION_INTEGER, 0, "log", &shortlog_len, "n",
- "add (at most <n>) entries from shortlog to merge commit message",
+ N_("show a diffstat at the end of the merge")),
+ OPT_BOOLEAN(0, "summary", &show_diffstat, N_("(synonym to --stat)")),
+ { OPTION_INTEGER, 0, "log", &shortlog_len, N_("n"),
+ N_("add (at most <n>) entries from shortlog to merge commit message"),
PARSE_OPT_OPTARG, NULL, DEFAULT_MERGE_LOG_LEN },
OPT_BOOLEAN(0, "squash", &squash,
- "create a single commit instead of doing a merge"),
+ N_("create a single commit instead of doing a merge")),
OPT_BOOLEAN(0, "commit", &option_commit,
- "perform a commit if the merge succeeds (default)"),
+ N_("perform a commit if the merge succeeds (default)")),
OPT_BOOL('e', "edit", &option_edit,
- "edit message before committing"),
+ N_("edit message before committing")),
OPT_BOOLEAN(0, "ff", &allow_fast_forward,
- "allow fast-forward (default)"),
+ N_("allow fast-forward (default)")),
OPT_BOOLEAN(0, "ff-only", &fast_forward_only,
- "abort if fast-forward is not possible"),
+ N_("abort if fast-forward is not possible")),
OPT_RERERE_AUTOUPDATE(&allow_rerere_auto),
- OPT_CALLBACK('s', "strategy", &use_strategies, "strategy",
- "merge strategy to use", option_parse_strategy),
- OPT_CALLBACK('X', "strategy-option", &xopts, "option=value",
- "option for selected merge strategy", option_parse_x),
- OPT_CALLBACK('m', "message", &merge_msg, "message",
- "merge commit message (for a non-fast-forward merge)",
+ OPT_CALLBACK('s', "strategy", &use_strategies, N_("strategy"),
+ N_("merge strategy to use"), option_parse_strategy),
+ OPT_CALLBACK('X', "strategy-option", &xopts, N_("option=value"),
+ N_("option for selected merge strategy"), option_parse_x),
+ OPT_CALLBACK('m', "message", &merge_msg, N_("message"),
+ N_("merge commit message (for a non-fast-forward merge)"),
option_parse_message),
OPT__VERBOSITY(&verbosity),
OPT_BOOLEAN(0, "abort", &abort_current_merge,
- "abort the current in-progress merge"),
- OPT_SET_INT(0, "progress", &show_progress, "force progress reporting", 1),
- { OPTION_STRING, 'S', "gpg-sign", &sign_commit, "key id",
- "GPG sign commit", PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
- OPT_BOOLEAN(0, "overwrite-ignore", &overwrite_ignore, "update ignored files (default)"),
+ N_("abort the current in-progress merge")),
+ OPT_SET_INT(0, "progress", &show_progress, N_("force progress reporting"), 1),
+ { OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key id"),
+ N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
+ OPT_BOOLEAN(0, "overwrite-ignore", &overwrite_ignore, N_("update ignored files (default)")),
OPT_END()
};
@@ -404,8 +404,7 @@ static void finish(struct commit *head_commit,
opts.output_format |=
DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
opts.detect_rename = DIFF_DETECT_RENAME;
- if (diff_setup_done(&opts) < 0)
- die(_("diff_setup_done failed"));
+ diff_setup_done(&opts);
diff_tree_sha1(head, new_head, "", &opts);
diffcore_std(&opts);
diff_flush(&opts);
diff --git a/builtin/mktree.c b/builtin/mktree.c
index 4ae1c41..f92ba40 100644
--- a/builtin/mktree.c
+++ b/builtin/mktree.c
@@ -64,7 +64,7 @@ static void write_tree(unsigned char *sha1)
}
static const char *mktree_usage[] = {
- "git mktree [-z] [--missing] [--batch]",
+ N_("git mktree [-z] [--missing] [--batch]"),
NULL
};
@@ -150,9 +150,9 @@ int cmd_mktree(int ac, const char **av, const char *prefix)
int got_eof = 0;
const struct option option[] = {
- OPT_SET_INT('z', NULL, &line_termination, "input is NUL terminated", '\0'),
- OPT_SET_INT( 0 , "missing", &allow_missing, "allow missing objects", 1),
- OPT_SET_INT( 0 , "batch", &is_batch_mode, "allow creation of more than one tree", 1),
+ OPT_SET_INT('z', NULL, &line_termination, N_("input is NUL terminated"), '\0'),
+ OPT_SET_INT( 0 , "missing", &allow_missing, N_("allow missing objects"), 1),
+ OPT_SET_INT( 0 , "batch", &is_batch_mode, N_("allow creation of more than one tree"), 1),
OPT_END()
};
diff --git a/builtin/mv.c b/builtin/mv.c
index 2a144b0..034fec9 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -11,7 +11,7 @@
#include "parse-options.h"
static const char * const builtin_mv_usage[] = {
- "git mv [options] <source>... <destination>",
+ N_("git mv [options] <source>... <destination>"),
NULL
};
@@ -59,10 +59,10 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
int i, newfd;
int verbose = 0, show_only = 0, force = 0, ignore_errors = 0;
struct option builtin_mv_options[] = {
- OPT__VERBOSE(&verbose, "be verbose"),
- OPT__DRY_RUN(&show_only, "dry run"),
- OPT__FORCE(&force, "force move/rename even if target exists"),
- OPT_BOOLEAN('k', NULL, &ignore_errors, "skip move/rename errors"),
+ OPT__VERBOSE(&verbose, N_("be verbose")),
+ OPT__DRY_RUN(&show_only, N_("dry run")),
+ OPT__FORCE(&force, N_("force move/rename even if target exists")),
+ OPT_BOOLEAN('k', NULL, &ignore_errors, N_("skip move/rename errors")),
OPT_END(),
};
const char **source, **destination, **dest_path;
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 1b37458..6238247 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -172,9 +172,9 @@ static void show_name(const struct object *obj,
}
static char const * const name_rev_usage[] = {
- "git name-rev [options] <commit>...",
- "git name-rev [options] --all",
- "git name-rev [options] --stdin",
+ N_("git name-rev [options] <commit>..."),
+ N_("git name-rev [options] --all"),
+ N_("git name-rev [options] --stdin"),
NULL
};
@@ -226,16 +226,16 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
int all = 0, transform_stdin = 0, allow_undefined = 1, always = 0;
struct name_ref_data data = { 0, 0, NULL };
struct option opts[] = {
- OPT_BOOLEAN(0, "name-only", &data.name_only, "print only names (no SHA-1)"),
- OPT_BOOLEAN(0, "tags", &data.tags_only, "only use tags to name the commits"),
- OPT_STRING(0, "refs", &data.ref_filter, "pattern",
- "only use refs matching <pattern>"),
+ OPT_BOOLEAN(0, "name-only", &data.name_only, N_("print only names (no SHA-1)")),
+ OPT_BOOLEAN(0, "tags", &data.tags_only, N_("only use tags to name the commits")),
+ OPT_STRING(0, "refs", &data.ref_filter, N_("pattern"),
+ N_("only use refs matching <pattern>")),
OPT_GROUP(""),
- OPT_BOOLEAN(0, "all", &all, "list all commits reachable from all refs"),
- OPT_BOOLEAN(0, "stdin", &transform_stdin, "read from stdin"),
- OPT_BOOLEAN(0, "undefined", &allow_undefined, "allow to print `undefined` names"),
+ OPT_BOOLEAN(0, "all", &all, N_("list all commits reachable from all refs")),
+ OPT_BOOLEAN(0, "stdin", &transform_stdin, N_("read from stdin")),
+ OPT_BOOLEAN(0, "undefined", &allow_undefined, N_("allow to print `undefined` names")),
OPT_BOOLEAN(0, "always", &always,
- "show abbreviated commit object as fallback"),
+ N_("show abbreviated commit object as fallback")),
OPT_END(),
};
diff --git a/builtin/notes.c b/builtin/notes.c
index 3644d14..453457a 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -19,72 +19,75 @@
#include "string-list.h"
#include "notes-merge.h"
+static void commit_notes(struct notes_tree *t, const char *msg);
+static combine_notes_fn parse_combine_notes_fn(const char *v);
+
static const char * const git_notes_usage[] = {
- "git notes [--ref <notes_ref>] [list [<object>]]",
- "git notes [--ref <notes_ref>] add [-f] [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]",
- "git notes [--ref <notes_ref>] copy [-f] <from-object> <to-object>",
- "git notes [--ref <notes_ref>] append [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]",
- "git notes [--ref <notes_ref>] edit [<object>]",
- "git notes [--ref <notes_ref>] show [<object>]",
- "git notes [--ref <notes_ref>] merge [-v | -q] [-s <strategy> ] <notes_ref>",
- "git notes merge --commit [-v | -q]",
- "git notes merge --abort [-v | -q]",
- "git notes [--ref <notes_ref>] remove [<object>...]",
- "git notes [--ref <notes_ref>] prune [-n | -v]",
- "git notes [--ref <notes_ref>] get-ref",
+ N_("git notes [--ref <notes_ref>] [list [<object>]]"),
+ N_("git notes [--ref <notes_ref>] add [-f] [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]"),
+ N_("git notes [--ref <notes_ref>] copy [-f] <from-object> <to-object>"),
+ N_("git notes [--ref <notes_ref>] append [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]"),
+ N_("git notes [--ref <notes_ref>] edit [<object>]"),
+ N_("git notes [--ref <notes_ref>] show [<object>]"),
+ N_("git notes [--ref <notes_ref>] merge [-v | -q] [-s <strategy> ] <notes_ref>"),
+ N_("git notes merge --commit [-v | -q]"),
+ N_("git notes merge --abort [-v | -q]"),
+ N_("git notes [--ref <notes_ref>] remove [<object>...]"),
+ N_("git notes [--ref <notes_ref>] prune [-n | -v]"),
+ N_("git notes [--ref <notes_ref>] get-ref"),
NULL
};
static const char * const git_notes_list_usage[] = {
- "git notes [list [<object>]]",
+ N_("git notes [list [<object>]]"),
NULL
};
static const char * const git_notes_add_usage[] = {
- "git notes add [<options>] [<object>]",
+ N_("git notes add [<options>] [<object>]"),
NULL
};
static const char * const git_notes_copy_usage[] = {
- "git notes copy [<options>] <from-object> <to-object>",
- "git notes copy --stdin [<from-object> <to-object>]...",
+ N_("git notes copy [<options>] <from-object> <to-object>"),
+ N_("git notes copy --stdin [<from-object> <to-object>]..."),
NULL
};
static const char * const git_notes_append_usage[] = {
- "git notes append [<options>] [<object>]",
+ N_("git notes append [<options>] [<object>]"),
NULL
};
static const char * const git_notes_edit_usage[] = {
- "git notes edit [<object>]",
+ N_("git notes edit [<object>]"),
NULL
};
static const char * const git_notes_show_usage[] = {
- "git notes show [<object>]",
+ N_("git notes show [<object>]"),
NULL
};
static const char * const git_notes_merge_usage[] = {
- "git notes merge [<options>] <notes_ref>",
- "git notes merge --commit [<options>]",
- "git notes merge --abort [<options>]",
+ N_("git notes merge [<options>] <notes_ref>"),
+ N_("git notes merge --commit [<options>]"),
+ N_("git notes merge --abort [<options>]"),
NULL
};
static const char * const git_notes_remove_usage[] = {
- "git notes remove [<object>]",
+ N_("git notes remove [<object>]"),
NULL
};
static const char * const git_notes_prune_usage[] = {
- "git notes prune [<options>]",
+ N_("git notes prune [<options>]"),
NULL
};
static const char * const git_notes_get_ref_usage[] = {
- "git notes get-ref",
+ N_("git notes get-ref"),
NULL
};
@@ -288,7 +291,7 @@ static int parse_reedit_arg(const struct option *opt, const char *arg, int unset
return parse_reuse_arg(opt, arg, unset);
}
-void commit_notes(struct notes_tree *t, const char *msg)
+static void commit_notes(struct notes_tree *t, const char *msg)
{
struct strbuf buf = STRBUF_INIT;
unsigned char commit_sha1[20];
@@ -312,7 +315,7 @@ void commit_notes(struct notes_tree *t, const char *msg)
strbuf_release(&buf);
}
-combine_notes_fn parse_combine_notes_fn(const char *v)
+static combine_notes_fn parse_combine_notes_fn(const char *v)
{
if (!strcasecmp(v, "overwrite"))
return combine_notes_overwrite;
@@ -531,19 +534,19 @@ static int add(int argc, const char **argv, const char *prefix)
const unsigned char *note;
struct msg_arg msg = { 0, 0, STRBUF_INIT };
struct option options[] = {
- { OPTION_CALLBACK, 'm', "message", &msg, "msg",
- "note contents as a string", PARSE_OPT_NONEG,
+ { OPTION_CALLBACK, 'm', "message", &msg, N_("message"),
+ N_("note contents as a string"), PARSE_OPT_NONEG,
parse_msg_arg},
- { OPTION_CALLBACK, 'F', "file", &msg, "file",
- "note contents in a file", PARSE_OPT_NONEG,
+ { OPTION_CALLBACK, 'F', "file", &msg, N_("file"),
+ N_("note contents in a file"), PARSE_OPT_NONEG,
parse_file_arg},
- { OPTION_CALLBACK, 'c', "reedit-message", &msg, "object",
- "reuse and edit specified note object", PARSE_OPT_NONEG,
+ { OPTION_CALLBACK, 'c', "reedit-message", &msg, N_("object"),
+ N_("reuse and edit specified note object"), PARSE_OPT_NONEG,
parse_reedit_arg},
- { OPTION_CALLBACK, 'C', "reuse-message", &msg, "object",
- "reuse specified note object", PARSE_OPT_NONEG,
+ { OPTION_CALLBACK, 'C', "reuse-message", &msg, N_("object"),
+ N_("reuse specified note object"), PARSE_OPT_NONEG,
parse_reuse_arg},
- OPT__FORCE(&force, "replace existing notes"),
+ OPT__FORCE(&force, N_("replace existing notes")),
OPT_END()
};
@@ -611,11 +614,11 @@ static int copy(int argc, const char **argv, const char *prefix)
struct notes_tree *t;
const char *rewrite_cmd = NULL;
struct option options[] = {
- OPT__FORCE(&force, "replace existing notes"),
- OPT_BOOLEAN(0, "stdin", &from_stdin, "read objects from stdin"),
- OPT_STRING(0, "for-rewrite", &rewrite_cmd, "command",
- "load rewriting config for <command> (implies "
- "--stdin)"),
+ OPT__FORCE(&force, N_("replace existing notes")),
+ OPT_BOOLEAN(0, "stdin", &from_stdin, N_("read objects from stdin")),
+ OPT_STRING(0, "for-rewrite", &rewrite_cmd, N_("command"),
+ N_("load rewriting config for <command> (implies "
+ "--stdin)")),
OPT_END()
};
@@ -688,17 +691,17 @@ static int append_edit(int argc, const char **argv, const char *prefix)
const char * const *usage;
struct msg_arg msg = { 0, 0, STRBUF_INIT };
struct option options[] = {
- { OPTION_CALLBACK, 'm', "message", &msg, "msg",
- "note contents as a string", PARSE_OPT_NONEG,
+ { OPTION_CALLBACK, 'm', "message", &msg, N_("message"),
+ N_("note contents as a string"), PARSE_OPT_NONEG,
parse_msg_arg},
- { OPTION_CALLBACK, 'F', "file", &msg, "file",
- "note contents in a file", PARSE_OPT_NONEG,
+ { OPTION_CALLBACK, 'F', "file", &msg, N_("file"),
+ N_("note contents in a file"), PARSE_OPT_NONEG,
parse_file_arg},
- { OPTION_CALLBACK, 'c', "reedit-message", &msg, "object",
- "reuse and edit specified note object", PARSE_OPT_NONEG,
+ { OPTION_CALLBACK, 'c', "reedit-message", &msg, N_("object"),
+ N_("reuse and edit specified note object"), PARSE_OPT_NONEG,
parse_reedit_arg},
- { OPTION_CALLBACK, 'C', "reuse-message", &msg, "object",
- "reuse specified note object", PARSE_OPT_NONEG,
+ { OPTION_CALLBACK, 'C', "reuse-message", &msg, N_("object"),
+ N_("reuse specified note object"), PARSE_OPT_NONEG,
parse_reuse_arg},
OPT_END()
};
@@ -861,19 +864,19 @@ static int merge(int argc, const char **argv, const char *prefix)
int verbosity = 0, result;
const char *strategy = NULL;
struct option options[] = {
- OPT_GROUP("General options"),
+ OPT_GROUP(N_("General options")),
OPT__VERBOSITY(&verbosity),
- OPT_GROUP("Merge options"),
- OPT_STRING('s', "strategy", &strategy, "strategy",
- "resolve notes conflicts using the given strategy "
- "(manual/ours/theirs/union/cat_sort_uniq)"),
- OPT_GROUP("Committing unmerged notes"),
+ OPT_GROUP(N_("Merge options")),
+ OPT_STRING('s', "strategy", &strategy, N_("strategy"),
+ N_("resolve notes conflicts using the given strategy "
+ "(manual/ours/theirs/union/cat_sort_uniq)")),
+ OPT_GROUP(N_("Committing unmerged notes")),
{ OPTION_BOOLEAN, 0, "commit", &do_commit, NULL,
- "finalize notes merge by committing unmerged notes",
+ N_("finalize notes merge by committing unmerged notes"),
PARSE_OPT_NOARG | PARSE_OPT_NONEG },
- OPT_GROUP("Aborting notes merge resolution"),
+ OPT_GROUP(N_("Aborting notes merge resolution")),
{ OPTION_BOOLEAN, 0, "abort", &do_abort, NULL,
- "abort notes merge",
+ N_("abort notes merge"),
PARSE_OPT_NOARG | PARSE_OPT_NONEG },
OPT_END()
};
@@ -980,10 +983,10 @@ static int remove_cmd(int argc, const char **argv, const char *prefix)
int from_stdin = 0;
struct option options[] = {
OPT_BIT(0, "ignore-missing", &flag,
- "attempt to remove non-existent note is not an error",
+ N_("attempt to remove non-existent note is not an error"),
IGNORE_MISSING),
OPT_BOOLEAN(0, "stdin", &from_stdin,
- "read object names from the standard input"),
+ N_("read object names from the standard input")),
OPT_END()
};
struct notes_tree *t;
@@ -1064,8 +1067,8 @@ int cmd_notes(int argc, const char **argv, const char *prefix)
int result;
const char *override_notes_ref = NULL;
struct option options[] = {
- OPT_STRING(0, "ref", &override_notes_ref, "notes_ref",
- "use notes from <notes_ref>"),
+ OPT_STRING(0, "ref", &override_notes_ref, N_("notes_ref"),
+ N_("use notes from <notes_ref>")),
OPT_END()
};
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 782e7d0..5e14064 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -20,8 +20,8 @@
#include "thread-utils.h"
static const char *pack_usage[] = {
- "git pack-objects --stdout [options...] [< ref-list | < object-list]",
- "git pack-objects [options...] base-name [< ref-list | < object-list]",
+ N_("git pack-objects --stdout [options...] [< ref-list | < object-list]"),
+ N_("git pack-objects [options...] base-name [< ref-list | < object-list]"),
NULL
};
@@ -2445,67 +2445,67 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
int rev_list_unpacked = 0, rev_list_all = 0, rev_list_reflog = 0;
struct option pack_objects_options[] = {
OPT_SET_INT('q', "quiet", &progress,
- "do not show progress meter", 0),
+ N_("do not show progress meter"), 0),
OPT_SET_INT(0, "progress", &progress,
- "show progress meter", 1),
+ N_("show progress meter"), 1),
OPT_SET_INT(0, "all-progress", &progress,
- "show progress meter during object writing phase", 2),
+ N_("show progress meter during object writing phase"), 2),
OPT_BOOL(0, "all-progress-implied",
&all_progress_implied,
- "similar to --all-progress when progress meter is shown"),
- { OPTION_CALLBACK, 0, "index-version", NULL, "version[,offset]",
- "write the pack index file in the specified idx format version",
+ N_("similar to --all-progress when progress meter is shown")),
+ { OPTION_CALLBACK, 0, "index-version", NULL, N_("version[,offset]"),
+ N_("write the pack index file in the specified idx format version"),
0, option_parse_index_version },
OPT_ULONG(0, "max-pack-size", &pack_size_limit,
- "maximum size of each output pack file"),
+ N_("maximum size of each output pack file")),
OPT_BOOL(0, "local", &local,
- "ignore borrowed objects from alternate object store"),
+ N_("ignore borrowed objects from alternate object store")),
OPT_BOOL(0, "incremental", &incremental,
- "ignore packed objects"),
+ N_("ignore packed objects")),
OPT_INTEGER(0, "window", &window,
- "limit pack window by objects"),
+ N_("limit pack window by objects")),
OPT_ULONG(0, "window-memory", &window_memory_limit,
- "limit pack window by memory in addition to object limit"),
+ N_("limit pack window by memory in addition to object limit")),
OPT_INTEGER(0, "depth", &depth,
- "maximum length of delta chain allowed in the resulting pack"),
+ N_("maximum length of delta chain allowed in the resulting pack")),
OPT_BOOL(0, "reuse-delta", &reuse_delta,
- "reuse existing deltas"),
+ N_("reuse existing deltas")),
OPT_BOOL(0, "reuse-object", &reuse_object,
- "reuse existing objects"),
+ N_("reuse existing objects")),
OPT_BOOL(0, "delta-base-offset", &allow_ofs_delta,
- "use OFS_DELTA objects"),
+ N_("use OFS_DELTA objects")),
OPT_INTEGER(0, "threads", &delta_search_threads,
- "use threads when searching for best delta matches"),
+ N_("use threads when searching for best delta matches")),
OPT_BOOL(0, "non-empty", &non_empty,
- "do not create an empty pack output"),
+ N_("do not create an empty pack output")),
OPT_BOOL(0, "revs", &use_internal_rev_list,
- "read revision arguments from standard input"),
+ N_("read revision arguments from standard input")),
{ OPTION_SET_INT, 0, "unpacked", &rev_list_unpacked, NULL,
- "limit the objects to those that are not yet packed",
+ N_("limit the objects to those that are not yet packed"),
PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1 },
{ OPTION_SET_INT, 0, "all", &rev_list_all, NULL,
- "include objects reachable from any reference",
+ N_("include objects reachable from any reference"),
PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1 },
{ OPTION_SET_INT, 0, "reflog", &rev_list_reflog, NULL,
- "include objects referred by reflog entries",
+ N_("include objects referred by reflog entries"),
PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1 },
OPT_BOOL(0, "stdout", &pack_to_stdout,
- "output pack to stdout"),
+ N_("output pack to stdout")),
OPT_BOOL(0, "include-tag", &include_tag,
- "include tag objects that refer to objects to be packed"),
+ N_("include tag objects that refer to objects to be packed")),
OPT_BOOL(0, "keep-unreachable", &keep_unreachable,
- "keep unreachable objects"),
- { OPTION_CALLBACK, 0, "unpack-unreachable", NULL, "time",
- "unpack unreachable objects newer than <time>",
+ N_("keep unreachable objects")),
+ { OPTION_CALLBACK, 0, "unpack-unreachable", NULL, N_("time"),
+ N_("unpack unreachable objects newer than <time>"),
PARSE_OPT_OPTARG, option_parse_unpack_unreachable },
OPT_BOOL(0, "thin", &thin,
- "create thin packs"),
+ N_("create thin packs")),
OPT_BOOL(0, "honor-pack-keep", &ignore_packed_keep,
- "ignore packs that have companion .keep file"),
+ N_("ignore packs that have companion .keep file")),
OPT_INTEGER(0, "compression", &pack_compression_level,
- "pack compression level"),
+ N_("pack compression level")),
OPT_SET_INT(0, "keep-true-parents", &grafts_replace_parents,
- "do not hide commits by grafts", 0),
+ N_("do not hide commits by grafts"), 0),
OPT_END(),
};
diff --git a/builtin/pack-refs.c b/builtin/pack-refs.c
index 39a9d89..b5a0f88 100644
--- a/builtin/pack-refs.c
+++ b/builtin/pack-refs.c
@@ -3,7 +3,7 @@
#include "pack-refs.h"
static char const * const pack_refs_usage[] = {
- "git pack-refs [options]",
+ N_("git pack-refs [options]"),
NULL
};
@@ -11,8 +11,8 @@ int cmd_pack_refs(int argc, const char **argv, const char *prefix)
{
unsigned int flags = PACK_REFS_PRUNE;
struct option opts[] = {
- OPT_BIT(0, "all", &flags, "pack everything", PACK_REFS_ALL),
- OPT_BIT(0, "prune", &flags, "prune loose refs (default)", PACK_REFS_PRUNE),
+ OPT_BIT(0, "all", &flags, N_("pack everything"), PACK_REFS_ALL),
+ OPT_BIT(0, "prune", &flags, N_("prune loose refs (default)"), PACK_REFS_PRUNE),
OPT_END(),
};
if (parse_options(argc, argv, prefix, opts, pack_refs_usage, 0))
diff --git a/builtin/prune-packed.c b/builtin/prune-packed.c
index b58a2e1..83382c1 100644
--- a/builtin/prune-packed.c
+++ b/builtin/prune-packed.c
@@ -4,7 +4,7 @@
#include "parse-options.h"
static const char * const prune_packed_usage[] = {
- "git prune-packed [-n|--dry-run] [-q|--quiet]",
+ N_("git prune-packed [-n|--dry-run] [-q|--quiet]"),
NULL
};
@@ -73,8 +73,8 @@ int cmd_prune_packed(int argc, const char **argv, const char *prefix)
{
int opts = isatty(2) ? VERBOSE : 0;
const struct option prune_packed_options[] = {
- OPT_BIT('n', "dry-run", &opts, "dry run", DRY_RUN),
- OPT_NEGBIT('q', "quiet", &opts, "be quiet", VERBOSE),
+ OPT_BIT('n', "dry-run", &opts, N_("dry run"), DRY_RUN),
+ OPT_NEGBIT('q', "quiet", &opts, N_("be quiet"), VERBOSE),
OPT_END()
};
diff --git a/builtin/prune.c b/builtin/prune.c
index b99b635..8cb8b91 100644
--- a/builtin/prune.c
+++ b/builtin/prune.c
@@ -9,7 +9,7 @@
#include "dir.h"
static const char * const prune_usage[] = {
- "git prune [-n] [-v] [--expire <time>] [--] [<head>...]",
+ N_("git prune [-n] [-v] [--expire <time>] [--] [<head>...]"),
NULL
};
static int show_only;
@@ -25,7 +25,8 @@ static int prune_tmp_object(const char *path, const char *filename)
return error("Could not stat '%s'", fullpath);
if (st.st_mtime > expire)
return 0;
- printf("Removing stale temporary file %s\n", fullpath);
+ if (show_only || verbose)
+ printf("Removing stale temporary file %s\n", fullpath);
if (!show_only)
unlink_or_warn(fullpath);
return 0;
@@ -128,11 +129,11 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
struct rev_info revs;
struct progress *progress = NULL;
const struct option options[] = {
- OPT__DRY_RUN(&show_only, "do not remove, show only"),
- OPT__VERBOSE(&verbose, "report pruned objects"),
- OPT_BOOL(0, "progress", &show_progress, "show progress"),
+ OPT__DRY_RUN(&show_only, N_("do not remove, show only")),
+ OPT__VERBOSE(&verbose, N_("report pruned objects")),
+ OPT_BOOL(0, "progress", &show_progress, N_("show progress")),
OPT_DATE(0, "expire", &expire,
- "expire objects older than <time>"),
+ N_("expire objects older than <time>")),
OPT_END()
};
char *s;
@@ -168,7 +169,7 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
prune_packed_objects(show_only);
remove_temporary_files(get_object_directory());
- s = xstrdup(mkpath("%s/pack", get_object_directory()));
+ s = mkpathdup("%s/pack", get_object_directory());
remove_temporary_files(s);
free(s);
return 0;
diff --git a/builtin/push.c b/builtin/push.c
index fdfcc6c..db9ba30 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -11,7 +11,7 @@
#include "submodule.h"
static const char * const push_usage[] = {
- "git push [<options>] [<repository> [<refspec>...]]",
+ N_("git push [<options>] [<repository> [<refspec>...]]"),
NULL,
};
@@ -147,12 +147,37 @@ static void setup_push_upstream(struct remote *remote, int simple)
add_refspec(refspec.buf);
}
+static char warn_unspecified_push_default_msg[] =
+N_("push.default is unset; its implicit value is changing in\n"
+ "Git 2.0 from 'matching' to 'simple'. To squelch this message\n"
+ "and maintain the current behavior after the default changes, use:\n"
+ "\n"
+ " git config --global push.default matching\n"
+ "\n"
+ "To squelch this message and adopt the new behavior now, use:\n"
+ "\n"
+ " git config --global push.default simple\n"
+ "\n"
+ "See 'git help config' and search for 'push.default' for further information.\n"
+ "(the 'simple' mode was introduced in Git 1.7.11. Use the similar mode\n"
+ "'current' instead of 'simple' if you sometimes use older versions of Git)");
+
+static void warn_unspecified_push_default_configuration(void)
+{
+ static int warn_once;
+
+ if (warn_once++)
+ return;
+ warning("%s\n", _(warn_unspecified_push_default_msg));
+}
+
static void setup_default_push_refspecs(struct remote *remote)
{
switch (push_default) {
default:
case PUSH_DEFAULT_UNSPECIFIED:
default_matching_used = 1;
+ warn_unspecified_push_default_configuration();
/* fallthru */
case PUSH_DEFAULT_MATCHING:
add_refspec(":");
@@ -186,8 +211,8 @@ static const char message_advice_pull_before_push[] =
static const char message_advice_use_upstream[] =
N_("Updates were rejected because a pushed branch tip is behind its remote\n"
"counterpart. If you did not intend to push that branch, you may want to\n"
- "specify branches to push or set the 'push.default' configuration\n"
- "variable to 'current' or 'upstream' to push only the current branch.");
+ "specify branches to push or set the 'push.default' configuration variable\n"
+ "to 'simple', 'current' or 'upstream' to push only the current branch.");
static const char message_advice_checkout_pull_push[] =
N_("Updates were rejected because a pushed branch tip is behind its remote\n"
@@ -354,25 +379,25 @@ int cmd_push(int argc, const char **argv, const char *prefix)
const char *repo = NULL; /* default repository */
struct option options[] = {
OPT__VERBOSITY(&verbosity),
- OPT_STRING( 0 , "repo", &repo, "repository", "repository"),
- OPT_BIT( 0 , "all", &flags, "push all refs", TRANSPORT_PUSH_ALL),
- OPT_BIT( 0 , "mirror", &flags, "mirror all refs",
+ OPT_STRING( 0 , "repo", &repo, N_("repository"), N_("repository")),
+ OPT_BIT( 0 , "all", &flags, N_("push all refs"), TRANSPORT_PUSH_ALL),
+ OPT_BIT( 0 , "mirror", &flags, N_("mirror all refs"),
(TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
- OPT_BOOLEAN( 0, "delete", &deleterefs, "delete refs"),
- OPT_BOOLEAN( 0 , "tags", &tags, "push tags (can't be used with --all or --mirror)"),
- OPT_BIT('n' , "dry-run", &flags, "dry run", TRANSPORT_PUSH_DRY_RUN),
- OPT_BIT( 0, "porcelain", &flags, "machine-readable output", TRANSPORT_PUSH_PORCELAIN),
- OPT_BIT('f', "force", &flags, "force updates", TRANSPORT_PUSH_FORCE),
- { OPTION_CALLBACK, 0, "recurse-submodules", &flags, "check",
- "controls recursive pushing of submodules",
+ OPT_BOOLEAN( 0, "delete", &deleterefs, N_("delete refs")),
+ OPT_BOOLEAN( 0 , "tags", &tags, N_("push tags (can't be used with --all or --mirror)")),
+ OPT_BIT('n' , "dry-run", &flags, N_("dry run"), TRANSPORT_PUSH_DRY_RUN),
+ OPT_BIT( 0, "porcelain", &flags, N_("machine-readable output"), TRANSPORT_PUSH_PORCELAIN),
+ OPT_BIT('f', "force", &flags, N_("force updates"), TRANSPORT_PUSH_FORCE),
+ { OPTION_CALLBACK, 0, "recurse-submodules", &flags, N_("check"),
+ N_("control recursive pushing of submodules"),
PARSE_OPT_OPTARG, option_parse_recurse_submodules },
- OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"),
- OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"),
- OPT_STRING( 0 , "exec", &receivepack, "receive-pack", "receive pack program"),
- OPT_BIT('u', "set-upstream", &flags, "set upstream for git pull/status",
+ OPT_BOOLEAN( 0 , "thin", &thin, N_("use thin pack")),
+ OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", N_("receive pack program")),
+ OPT_STRING( 0 , "exec", &receivepack, "receive-pack", N_("receive pack program")),
+ OPT_BIT('u', "set-upstream", &flags, N_("set upstream for git pull/status"),
TRANSPORT_PUSH_SET_UPSTREAM),
- OPT_BOOL(0, "progress", &progress, "force progress reporting"),
- OPT_BIT(0, "prune", &flags, "prune locally removed refs",
+ OPT_BOOL(0, "progress", &progress, N_("force progress reporting")),
+ OPT_BIT(0, "prune", &flags, N_("prune locally removed refs"),
TRANSPORT_PUSH_PRUNE),
OPT_END()
};
diff --git a/builtin/read-tree.c b/builtin/read-tree.c
index df6c4c8..042ac1b 100644
--- a/builtin/read-tree.c
+++ b/builtin/read-tree.c
@@ -33,7 +33,7 @@ static int list_tree(unsigned char *sha1)
}
static const char * const read_tree_usage[] = {
- "git read-tree [[-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>] [-u [--exclude-per-directory=<gitignore>] | -i]] [--no-sparse-checkout] [--index-output=<file>] (--empty | <tree-ish1> [<tree-ish2> [<tree-ish3>]])",
+ N_("git read-tree [[-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>] [-u [--exclude-per-directory=<gitignore>] | -i]] [--no-sparse-checkout] [--index-output=<file>] (--empty | <tree-ish1> [<tree-ish2> [<tree-ish3>]])"),
NULL
};
@@ -104,37 +104,37 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
struct unpack_trees_options opts;
int prefix_set = 0;
const struct option read_tree_options[] = {
- { OPTION_CALLBACK, 0, "index-output", NULL, "file",
- "write resulting index to <file>",
+ { OPTION_CALLBACK, 0, "index-output", NULL, N_("file"),
+ N_("write resulting index to <file>"),
PARSE_OPT_NONEG, index_output_cb },
OPT_SET_INT(0, "empty", &read_empty,
- "only empty the index", 1),
- OPT__VERBOSE(&opts.verbose_update, "be verbose"),
- OPT_GROUP("Merging"),
+ N_("only empty the index"), 1),
+ OPT__VERBOSE(&opts.verbose_update, N_("be verbose")),
+ OPT_GROUP(N_("Merging")),
OPT_SET_INT('m', NULL, &opts.merge,
- "perform a merge in addition to a read", 1),
+ N_("perform a merge in addition to a read"), 1),
OPT_SET_INT(0, "trivial", &opts.trivial_merges_only,
- "3-way merge if no file level merging required", 1),
+ N_("3-way merge if no file level merging required"), 1),
OPT_SET_INT(0, "aggressive", &opts.aggressive,
- "3-way merge in presence of adds and removes", 1),
+ N_("3-way merge in presence of adds and removes"), 1),
OPT_SET_INT(0, "reset", &opts.reset,
- "same as -m, but discard unmerged entries", 1),
- { OPTION_STRING, 0, "prefix", &opts.prefix, "<subdirectory>/",
- "read the tree into the index under <subdirectory>/",
+ N_("same as -m, but discard unmerged entries"), 1),
+ { OPTION_STRING, 0, "prefix", &opts.prefix, N_("<subdirectory>/"),
+ N_("read the tree into the index under <subdirectory>/"),
PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP },
OPT_SET_INT('u', NULL, &opts.update,
- "update working tree with merge result", 1),
+ N_("update working tree with merge result"), 1),
{ OPTION_CALLBACK, 0, "exclude-per-directory", &opts,
- "gitignore",
- "allow explicitly ignored files to be overwritten",
+ N_("gitignore"),
+ N_("allow explicitly ignored files to be overwritten"),
PARSE_OPT_NONEG, exclude_per_directory_cb },
OPT_SET_INT('i', NULL, &opts.index_only,
- "don't check the working tree after merging", 1),
- OPT__DRY_RUN(&opts.dry_run, "don't update the index or the work tree"),
+ N_("don't check the working tree after merging"), 1),
+ OPT__DRY_RUN(&opts.dry_run, N_("don't update the index or the work tree")),
OPT_SET_INT(0, "no-sparse-checkout", &opts.skip_sparse_checkout,
- "skip applying sparse checkout filter", 1),
+ N_("skip applying sparse checkout filter"), 1),
OPT_SET_INT(0, "debug-unpack", &opts.debug_unpack,
- "debug unpack-trees", 1),
+ N_("debug unpack-trees"), 1),
OPT_END()
};
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 0afb8b2..ff781fe 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -12,6 +12,7 @@
#include "string-list.h"
#include "sha1-array.h"
#include "connected.h"
+#include "version.h"
static const char receive_pack_usage[] = "git receive-pack <git-dir>";
@@ -121,10 +122,11 @@ static void show_ref(const char *path, const unsigned char *sha1)
if (sent_capabilities)
packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
else
- packet_write(1, "%s %s%c%s%s\n",
+ packet_write(1, "%s %s%c%s%s agent=%s\n",
sha1_to_hex(sha1), path, 0,
" report-status delete-refs side-band-64k quiet",
- prefer_ofs_delta ? " ofs-delta" : "");
+ prefer_ofs_delta ? " ofs-delta" : "",
+ git_user_agent_sanitized());
sent_capabilities = 1;
}
@@ -478,7 +480,6 @@ static const char *update(struct command *cmd)
!prefixcmp(name, "refs/heads/")) {
struct object *old_object, *new_object;
struct commit *old_commit, *new_commit;
- struct commit_list *bases, *ent;
old_object = parse_object(old_sha1);
new_object = parse_object(new_sha1);
@@ -491,12 +492,7 @@ static const char *update(struct command *cmd)
}
old_commit = (struct commit *)old_object;
new_commit = (struct commit *)new_object;
- bases = get_merge_bases(old_commit, new_commit, 1);
- for (ent = bases; ent; ent = ent->next)
- if (!hashcmp(old_sha1, ent->item->object.sha1))
- break;
- free_commit_list(bases);
- if (!ent) {
+ if (!in_merge_bases(old_commit, new_commit)) {
rp_error("denying non-fast-forward %s"
" (you should pull first)", name);
return "non-fast-forward";
@@ -699,7 +695,7 @@ static void execute_commands(struct command *commands, const char *unpacker_erro
if (unpacker_error) {
for (cmd = commands; cmd; cmd = cmd->next)
- cmd->error_string = "n/a (unpacker error)";
+ cmd->error_string = "unpacker error";
return;
}
@@ -799,7 +795,7 @@ static const char *parse_pack_header(struct pack_header *hdr)
static const char *pack_lockfile;
-static const char *unpack(void)
+static const char *unpack(int err_fd)
{
struct pack_header hdr;
const char *hdr_err;
@@ -819,6 +815,7 @@ static const char *unpack(void)
if (ntohl(hdr.hdr_entries) < unpack_limit) {
int code, i = 0;
+ struct child_process child;
const char *unpacker[5];
unpacker[i++] = "unpack-objects";
if (quiet)
@@ -827,7 +824,12 @@ static const char *unpack(void)
unpacker[i++] = "--strict";
unpacker[i++] = hdr_arg;
unpacker[i++] = NULL;
- code = run_command_v_opt(unpacker, RUN_GIT_CMD);
+ memset(&child, 0, sizeof(child));
+ child.argv = unpacker;
+ child.no_stdout = 1;
+ child.err = err_fd;
+ child.git_cmd = 1;
+ code = run_command(&child);
if (!code)
return NULL;
return "unpack-objects abnormal exit";
@@ -852,6 +854,7 @@ static const char *unpack(void)
memset(&ip, 0, sizeof(ip));
ip.argv = keeper;
ip.out = -1;
+ ip.err = err_fd;
ip.git_cmd = 1;
status = start_command(&ip);
if (status) {
@@ -868,6 +871,26 @@ static const char *unpack(void)
}
}
+static const char *unpack_with_sideband(void)
+{
+ struct async muxer;
+ const char *ret;
+
+ if (!use_sideband)
+ return unpack(0);
+
+ memset(&muxer, 0, sizeof(muxer));
+ muxer.proc = copy_to_sideband;
+ muxer.in = -1;
+ if (start_async(&muxer))
+ return NULL;
+
+ ret = unpack(muxer.in);
+
+ finish_async(&muxer);
+ return ret;
+}
+
static void report(struct command *commands, const char *unpack_status)
{
struct command *cmd;
@@ -965,7 +988,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
const char *unpack_status = NULL;
if (!delete_only(commands))
- unpack_status = unpack();
+ unpack_status = unpack_with_sideband();
execute_commands(commands, unpack_status);
if (pack_lockfile)
unlink_or_warn(pack_lockfile);
@@ -977,7 +1000,8 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
const char *argv_gc_auto[] = {
"gc", "--auto", "--quiet", NULL,
};
- run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
+ int opt = RUN_GIT_CMD | RUN_COMMAND_STDOUT_TO_STDERR;
+ run_command_v_opt(argv_gc_auto, opt);
}
if (auto_update_server_info)
update_server_info(0);
diff --git a/builtin/remote.c b/builtin/remote.c
index 920262d..a5a4b23 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -8,66 +8,66 @@
#include "refs.h"
static const char * const builtin_remote_usage[] = {
- "git remote [-v | --verbose]",
- "git remote add [-t <branch>] [-m <master>] [-f] [--tags|--no-tags] [--mirror=<fetch|push>] <name> <url>",
- "git remote rename <old> <new>",
- "git remote rm <name>",
- "git remote set-head <name> (-a | -d | <branch>)",
- "git remote [-v | --verbose] show [-n] <name>",
- "git remote prune [-n | --dry-run] <name>",
- "git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)...]",
- "git remote set-branches [--add] <name> <branch>...",
- "git remote set-url [--push] <name> <newurl> [<oldurl>]",
- "git remote set-url --add <name> <newurl>",
- "git remote set-url --delete <name> <url>",
+ N_("git remote [-v | --verbose]"),
+ N_("git remote add [-t <branch>] [-m <master>] [-f] [--tags|--no-tags] [--mirror=<fetch|push>] <name> <url>"),
+ N_("git remote rename <old> <new>"),
+ N_("git remote remove <name>"),
+ N_("git remote set-head <name> (-a | -d | <branch>)"),
+ N_("git remote [-v | --verbose] show [-n] <name>"),
+ N_("git remote prune [-n | --dry-run] <name>"),
+ N_("git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)...]"),
+ N_("git remote set-branches [--add] <name> <branch>..."),
+ N_("git remote set-url [--push] <name> <newurl> [<oldurl>]"),
+ N_("git remote set-url --add <name> <newurl>"),
+ N_("git remote set-url --delete <name> <url>"),
NULL
};
static const char * const builtin_remote_add_usage[] = {
- "git remote add [<options>] <name> <url>",
+ N_("git remote add [<options>] <name> <url>"),
NULL
};
static const char * const builtin_remote_rename_usage[] = {
- "git remote rename <old> <new>",
+ N_("git remote rename <old> <new>"),
NULL
};
static const char * const builtin_remote_rm_usage[] = {
- "git remote rm <name>",
+ N_("git remote remove <name>"),
NULL
};
static const char * const builtin_remote_sethead_usage[] = {
- "git remote set-head <name> (-a | -d | <branch>])",
+ N_("git remote set-head <name> (-a | -d | <branch>])"),
NULL
};
static const char * const builtin_remote_setbranches_usage[] = {
- "git remote set-branches <name> <branch>...",
- "git remote set-branches --add <name> <branch>...",
+ N_("git remote set-branches <name> <branch>..."),
+ N_("git remote set-branches --add <name> <branch>..."),
NULL
};
static const char * const builtin_remote_show_usage[] = {
- "git remote show [<options>] <name>",
+ N_("git remote show [<options>] <name>"),
NULL
};
static const char * const builtin_remote_prune_usage[] = {
- "git remote prune [<options>] <name>",
+ N_("git remote prune [<options>] <name>"),
NULL
};
static const char * const builtin_remote_update_usage[] = {
- "git remote update [<options>] [<group> | <remote>]...",
+ N_("git remote update [<options>] [<group> | <remote>]..."),
NULL
};
static const char * const builtin_remote_seturl_usage[] = {
- "git remote set-url [--push] <name> <newurl> [<oldurl>]",
- "git remote set-url --add <name> <newurl>",
- "git remote set-url --delete <name> <url>",
+ N_("git remote set-url [--push] <name> <newurl> [<oldurl>]"),
+ N_("git remote set-url --add <name> <newurl>"),
+ N_("git remote set-url --delete <name> <url>"),
NULL
};
@@ -160,17 +160,17 @@ static int add(int argc, const char **argv)
int i;
struct option options[] = {
- OPT_BOOLEAN('f', "fetch", &fetch, "fetch the remote branches"),
+ OPT_BOOLEAN('f', "fetch", &fetch, N_("fetch the remote branches")),
OPT_SET_INT(0, "tags", &fetch_tags,
- "import all tags and associated objects when fetching",
+ N_("import all tags and associated objects when fetching"),
TAGS_SET),
OPT_SET_INT(0, NULL, &fetch_tags,
- "or do not fetch any tag at all (--no-tags)", TAGS_UNSET),
- OPT_STRING_LIST('t', "track", &track, "branch",
- "branch(es) to track"),
- OPT_STRING('m', "master", &master, "branch", "master branch"),
- { OPTION_CALLBACK, 0, "mirror", &mirror, "push|fetch",
- "set up remote as a mirror to push to or fetch from",
+ N_("or do not fetch any tag at all (--no-tags)"), TAGS_UNSET),
+ OPT_STRING_LIST('t', "track", &track, N_("branch"),
+ N_("branch(es) to track")),
+ OPT_STRING('m', "master", &master, N_("branch"), N_("master branch")),
+ { OPTION_CALLBACK, 0, "mirror", &mirror, N_("push|fetch"),
+ N_("set up remote as a mirror to push to or fetch from"),
PARSE_OPT_OPTARG, parse_mirror_opt },
OPT_END()
};
@@ -1088,7 +1088,7 @@ static int show(int argc, const char **argv)
{
int no_query = 0, result = 0, query_flag = 0;
struct option options[] = {
- OPT_BOOLEAN('n', NULL, &no_query, "do not query remotes"),
+ OPT_BOOLEAN('n', NULL, &no_query, N_("do not query remotes")),
OPT_END()
};
struct ref_states states;
@@ -1196,9 +1196,9 @@ static int set_head(int argc, const char **argv)
struct option options[] = {
OPT_BOOLEAN('a', "auto", &opt_a,
- "set refs/remotes/<name>/HEAD according to remote"),
+ N_("set refs/remotes/<name>/HEAD according to remote")),
OPT_BOOLEAN('d', "delete", &opt_d,
- "delete refs/remotes/<name>/HEAD"),
+ N_("delete refs/remotes/<name>/HEAD")),
OPT_END()
};
argc = parse_options(argc, argv, NULL, options, builtin_remote_sethead_usage,
@@ -1250,7 +1250,7 @@ static int prune(int argc, const char **argv)
{
int dry_run = 0, result = 0;
struct option options[] = {
- OPT__DRY_RUN(&dry_run, "dry run"),
+ OPT__DRY_RUN(&dry_run, N_("dry run")),
OPT_END()
};
@@ -1318,7 +1318,7 @@ static int update(int argc, const char **argv)
int i, prune = 0;
struct option options[] = {
OPT_BOOLEAN('p', "prune", &prune,
- "prune remotes after fetching"),
+ N_("prune remotes after fetching")),
OPT_END()
};
const char **fetch_argv;
@@ -1404,7 +1404,7 @@ static int set_branches(int argc, const char **argv)
{
int add_mode = 0;
struct option options[] = {
- OPT_BOOLEAN('\0', "add", &add_mode, "add branch"),
+ OPT_BOOLEAN('\0', "add", &add_mode, N_("add branch")),
OPT_END()
};
@@ -1433,11 +1433,11 @@ static int set_url(int argc, const char **argv)
struct strbuf name_buf = STRBUF_INIT;
struct option options[] = {
OPT_BOOLEAN('\0', "push", &push_mode,
- "manipulate push URLs"),
+ N_("manipulate push URLs")),
OPT_BOOLEAN('\0', "add", &add_mode,
- "add URL"),
+ N_("add URL")),
OPT_BOOLEAN('\0', "delete", &delete_mode,
- "delete URLs"),
+ N_("delete URLs")),
OPT_END()
};
argc = parse_options(argc, argv, NULL, options, builtin_remote_seturl_usage,
@@ -1566,7 +1566,7 @@ static int show_all(void)
int cmd_remote(int argc, const char **argv, const char *prefix)
{
struct option options[] = {
- OPT__VERBOSE(&verbose, "be verbose; must be placed before a subcommand"),
+ OPT__VERBOSE(&verbose, N_("be verbose; must be placed before a subcommand")),
OPT_END()
};
int result;
@@ -1580,7 +1580,7 @@ int cmd_remote(int argc, const char **argv, const char *prefix)
result = add(argc, argv);
else if (!strcmp(argv[0], "rename"))
result = mv(argc, argv);
- else if (!strcmp(argv[0], "rm"))
+ else if (!strcmp(argv[0], "rm") || !strcmp(argv[0], "remove"))
result = rm(argc, argv);
else if (!strcmp(argv[0], "set-head"))
result = set_head(argc, argv);
diff --git a/builtin/replace.c b/builtin/replace.c
index 4a8970e..e3aaf70 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -14,9 +14,9 @@
#include "parse-options.h"
static const char * const git_replace_usage[] = {
- "git replace [-f] <object> <replacement>",
- "git replace -d <object>...",
- "git replace -l [<pattern>]",
+ N_("git replace [-f] <object> <replacement>"),
+ N_("git replace -d <object>..."),
+ N_("git replace -l [<pattern>]"),
NULL
};
@@ -115,9 +115,9 @@ int cmd_replace(int argc, const char **argv, const char *prefix)
{
int list = 0, delete = 0, force = 0;
struct option options[] = {
- OPT_BOOLEAN('l', NULL, &list, "list replace refs"),
- OPT_BOOLEAN('d', NULL, &delete, "delete replace refs"),
- OPT_BOOLEAN('f', NULL, &force, "replace the ref if it exists"),
+ OPT_BOOLEAN('l', NULL, &list, N_("list replace refs")),
+ OPT_BOOLEAN('d', NULL, &delete, N_("delete replace refs")),
+ OPT_BOOLEAN('f', NULL, &force, N_("replace the ref if it exists")),
OPT_END()
};
diff --git a/builtin/rerere.c b/builtin/rerere.c
index 08213c7..dc1708e 100644
--- a/builtin/rerere.c
+++ b/builtin/rerere.c
@@ -8,7 +8,7 @@
#include "xdiff-interface.h"
static const char * const rerere_usage[] = {
- "git rerere [clear | forget path... | status | remaining | diff | gc]",
+ N_("git rerere [clear | forget path... | status | remaining | diff | gc]"),
NULL,
};
@@ -53,7 +53,7 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)
struct option options[] = {
OPT_SET_INT(0, "rerere-autoupdate", &autoupdate,
- "register clean resolutions in index", 1),
+ N_("register clean resolutions in index"), 1),
OPT_END(),
};
diff --git a/builtin/reset.c b/builtin/reset.c
index 74442bd..915cc9f 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -22,9 +22,9 @@
#include "cache-tree.h"
static const char * const git_reset_usage[] = {
- "git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]",
- "git reset [-q] <commit> [--] <paths>...",
- "git reset --patch [<commit>] [--] [<paths>...]",
+ N_("git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]"),
+ N_("git reset [-q] <commit> [--] <paths>..."),
+ N_("git reset --patch [<commit>] [--] [<paths>...]"),
NULL
};
@@ -235,17 +235,17 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
struct commit *commit;
struct strbuf msg = STRBUF_INIT;
const struct option options[] = {
- OPT__QUIET(&quiet, "be quiet, only report errors"),
+ OPT__QUIET(&quiet, N_("be quiet, only report errors")),
OPT_SET_INT(0, "mixed", &reset_type,
- "reset HEAD and index", MIXED),
- OPT_SET_INT(0, "soft", &reset_type, "reset only HEAD", SOFT),
+ N_("reset HEAD and index"), MIXED),
+ OPT_SET_INT(0, "soft", &reset_type, N_("reset only HEAD"), SOFT),
OPT_SET_INT(0, "hard", &reset_type,
- "reset HEAD, index and working tree", HARD),
+ N_("reset HEAD, index and working tree"), HARD),
OPT_SET_INT(0, "merge", &reset_type,
- "reset HEAD, index and working tree", MERGE),
+ N_("reset HEAD, index and working tree"), MERGE),
OPT_SET_INT(0, "keep", &reset_type,
- "reset HEAD but keep local changes", KEEP),
- OPT_BOOLEAN('p', "patch", &patch_mode, "select hunks interactively"),
+ N_("reset HEAD but keep local changes"), KEEP),
+ OPT_BOOLEAN('p', "patch", &patch_mode, N_("select hunks interactively")),
OPT_END()
};
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index 32788a9..f267a1d 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -230,6 +230,7 @@ static int try_difference(const char *arg)
const char *next;
const char *this;
int symmetric;
+ static const char head_by_default[] = "HEAD";
if (!(dotdot = strstr(arg, "..")))
return 0;
@@ -241,9 +242,20 @@ static int try_difference(const char *arg)
next += symmetric;
if (!*next)
- next = "HEAD";
+ next = head_by_default;
if (dotdot == arg)
- this = "HEAD";
+ this = head_by_default;
+
+ if (this == head_by_default && next == head_by_default &&
+ !symmetric) {
+ /*
+ * Just ".."? That is not a range but the
+ * pathspec for the parent directory.
+ */
+ *dotdot = '.';
+ return 0;
+ }
+
if (!get_sha1_committish(this, sha1) && !get_sha1_committish(next, end)) {
show_rev(NORMAL, end, next);
show_rev(symmetric ? NORMAL : REVERSED, sha1, this);
@@ -324,15 +336,15 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
{
static int keep_dashdash = 0, stop_at_non_option = 0;
static char const * const parseopt_usage[] = {
- "git rev-parse --parseopt [options] -- [<args>...]",
+ N_("git rev-parse --parseopt [options] -- [<args>...]"),
NULL
};
static struct option parseopt_opts[] = {
OPT_BOOLEAN(0, "keep-dashdash", &keep_dashdash,
- "keep the `--` passed as an arg"),
+ N_("keep the `--` passed as an arg")),
OPT_BOOLEAN(0, "stop-at-non-option", &stop_at_non_option,
- "stop parsing after the "
- "first non-option argument"),
+ N_("stop parsing after the "
+ "first non-option argument")),
OPT_END(),
};
@@ -449,11 +461,11 @@ static void die_no_single_rev(int quiet)
}
static const char builtin_rev_parse_usage[] =
-"git rev-parse --parseopt [options] -- [<args>...]\n"
-" or: git rev-parse --sq-quote [<arg>...]\n"
-" or: git rev-parse [options] [<arg>...]\n"
-"\n"
-"Run \"git rev-parse --parseopt -h\" for more information on the first usage.";
+N_("git rev-parse --parseopt [options] -- [<args>...]\n"
+ " or: git rev-parse --sq-quote [<arg>...]\n"
+ " or: git rev-parse [options] [<arg>...]\n"
+ "\n"
+ "Run \"git rev-parse --parseopt -h\" for more information on the first usage.");
int cmd_rev_parse(int argc, const char **argv, const char *prefix)
{
diff --git a/builtin/revert.c b/builtin/revert.c
index 82d1bf8..c5e36b9 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -19,14 +19,14 @@
*/
static const char * const revert_usage[] = {
- "git revert [options] <commit-ish>",
- "git revert <subcommand>",
+ N_("git revert [options] <commit-ish>"),
+ N_("git revert <subcommand>"),
NULL
};
static const char * const cherry_pick_usage[] = {
- "git cherry-pick [options] <commit-ish>",
- "git cherry-pick <subcommand>",
+ N_("git cherry-pick [options] <commit-ish>"),
+ N_("git cherry-pick <subcommand>"),
NULL
};
@@ -100,18 +100,19 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts)
int contin = 0;
int rollback = 0;
struct option options[] = {
- OPT_BOOLEAN(0, "quit", &remove_state, "end revert or cherry-pick sequence"),
- OPT_BOOLEAN(0, "continue", &contin, "resume revert or cherry-pick sequence"),
- OPT_BOOLEAN(0, "abort", &rollback, "cancel revert or cherry-pick sequence"),
- OPT_BOOLEAN('n', "no-commit", &opts->no_commit, "don't automatically commit"),
- OPT_BOOLEAN('e', "edit", &opts->edit, "edit the commit message"),
+ OPT_BOOLEAN(0, "quit", &remove_state, N_("end revert or cherry-pick sequence")),
+ OPT_BOOLEAN(0, "continue", &contin, N_("resume revert or cherry-pick sequence")),
+ OPT_BOOLEAN(0, "abort", &rollback, N_("cancel revert or cherry-pick sequence")),
+ OPT_BOOLEAN('n', "no-commit", &opts->no_commit, N_("don't automatically commit")),
+ OPT_BOOLEAN('e', "edit", &opts->edit, N_("edit the commit message")),
OPT_NOOP_NOARG('r', NULL),
- OPT_BOOLEAN('s', "signoff", &opts->signoff, "add Signed-off-by:"),
- OPT_INTEGER('m', "mainline", &opts->mainline, "parent number"),
+ OPT_BOOLEAN('s', "signoff", &opts->signoff, N_("add Signed-off-by:")),
+ OPT_INTEGER('m', "mainline", &opts->mainline, N_("parent number")),
OPT_RERERE_AUTOUPDATE(&opts->allow_rerere_auto),
- OPT_STRING(0, "strategy", &opts->strategy, "strategy", "merge strategy"),
- OPT_CALLBACK('X', "strategy-option", &opts, "option",
- "option for merge strategy", option_parse_x),
+ OPT_STRING(0, "strategy", &opts->strategy, N_("strategy"), N_("merge strategy")),
+ OPT_CALLBACK('X', "strategy-option", &opts, N_("option"),
+ N_("option for merge strategy"), option_parse_x),
+ OPT_END(),
OPT_END(),
OPT_END(),
OPT_END(),
@@ -121,10 +122,11 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts)
if (opts->action == REPLAY_PICK) {
struct option cp_extra[] = {
- OPT_BOOLEAN('x', NULL, &opts->record_origin, "append commit name"),
- OPT_BOOLEAN(0, "ff", &opts->allow_ff, "allow fast-forward"),
- OPT_BOOLEAN(0, "allow-empty", &opts->allow_empty, "preserve initially empty commits"),
- OPT_BOOLEAN(0, "keep-redundant-commits", &opts->keep_redundant_commits, "keep redundant, empty commits"),
+ OPT_BOOLEAN('x', NULL, &opts->record_origin, N_("append commit name")),
+ OPT_BOOLEAN(0, "ff", &opts->allow_ff, N_("allow fast-forward")),
+ OPT_BOOLEAN(0, "allow-empty", &opts->allow_empty, N_("preserve initially empty commits")),
+ OPT_BOOLEAN(0, "allow-empty-message", &opts->allow_empty_message, N_("allow commits with empty messages")),
+ OPT_BOOLEAN(0, "keep-redundant-commits", &opts->keep_redundant_commits, N_("keep redundant, empty commits")),
OPT_END(),
};
if (parse_options_concat(options, ARRAY_SIZE(options), cp_extra))
@@ -193,7 +195,7 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts)
struct setup_revision_opt s_r_opt;
opts->revs = xmalloc(sizeof(*opts->revs));
init_revisions(opts->revs, NULL);
- opts->revs->no_walk = 1;
+ opts->revs->no_walk = REVISION_WALK_NO_WALK_UNSORTED;
if (argc < 2)
usage_with_options(usage_str, options);
memset(&s_r_opt, 0, sizeof(s_r_opt));
diff --git a/builtin/rm.c b/builtin/rm.c
index 90c8a50..b384c4c 100644
--- a/builtin/rm.c
+++ b/builtin/rm.c
@@ -11,7 +11,7 @@
#include "parse-options.h"
static const char * const builtin_rm_usage[] = {
- "git rm [options] [--] <file>...",
+ N_("git rm [options] [--] <file>..."),
NULL
};
@@ -130,13 +130,13 @@ static int show_only = 0, force = 0, index_only = 0, recursive = 0, quiet = 0;
static int ignore_unmatch = 0;
static struct option builtin_rm_options[] = {
- OPT__DRY_RUN(&show_only, "dry run"),
- OPT__QUIET(&quiet, "do not list removed files"),
- OPT_BOOLEAN( 0 , "cached", &index_only, "only remove from the index"),
- OPT__FORCE(&force, "override the up-to-date check"),
- OPT_BOOLEAN('r', NULL, &recursive, "allow recursive removal"),
+ OPT__DRY_RUN(&show_only, N_("dry run")),
+ OPT__QUIET(&quiet, N_("do not list removed files")),
+ OPT_BOOLEAN( 0 , "cached", &index_only, N_("only remove from the index")),
+ OPT__FORCE(&force, N_("override the up-to-date check")),
+ OPT_BOOLEAN('r', NULL, &recursive, N_("allow recursive removal")),
OPT_BOOLEAN( 0 , "ignore-unmatch", &ignore_unmatch,
- "exit with a zero status even if nothing matched"),
+ N_("exit with a zero status even if nothing matched")),
OPT_END(),
};
diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index d5d7105..7d05064 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -8,6 +8,7 @@
#include "send-pack.h"
#include "quote.h"
#include "transport.h"
+#include "version.h"
static const char send_pack_usage[] =
"git send-pack [--all | --mirror] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\n"
@@ -251,6 +252,7 @@ int send_pack(struct send_pack_args *args,
int status_report = 0;
int use_sideband = 0;
int quiet_supported = 0;
+ int agent_supported = 0;
unsigned cmds_sent = 0;
int ret;
struct async demux;
@@ -266,6 +268,8 @@ int send_pack(struct send_pack_args *args,
use_sideband = 1;
if (server_supports("quiet"))
quiet_supported = 1;
+ if (server_supports("agent"))
+ agent_supported = 1;
if (!remote_refs) {
fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
@@ -305,12 +309,17 @@ int send_pack(struct send_pack_args *args,
char *new_hex = sha1_to_hex(ref->new_sha1);
int quiet = quiet_supported && (args->quiet || !args->progress);
- if (!cmds_sent && (status_report || use_sideband || args->quiet)) {
- packet_buf_write(&req_buf, "%s %s %s%c%s%s%s",
+ if (!cmds_sent && (status_report || use_sideband ||
+ quiet || agent_supported)) {
+ packet_buf_write(&req_buf,
+ "%s %s %s%c%s%s%s%s%s",
old_hex, new_hex, ref->name, 0,
status_report ? " report-status" : "",
use_sideband ? " side-band-64k" : "",
- quiet ? " quiet" : "");
+ quiet ? " quiet" : "",
+ agent_supported ? " agent=" : "",
+ agent_supported ? git_user_agent_sanitized() : ""
+ );
}
else
packet_buf_write(&req_buf, "%s %s %s",
diff --git a/builtin/shortlog.c b/builtin/shortlog.c
index 37f3193..b316cf3 100644
--- a/builtin/shortlog.c
+++ b/builtin/shortlog.c
@@ -10,9 +10,9 @@
#include "parse-options.h"
static char const * const shortlog_usage[] = {
- "git shortlog [-n] [-s] [-e] [-w] [rev-opts] [--] [<commit-id>... ]",
+ N_("git shortlog [-n] [-s] [-e] [-w] [rev-opts] [--] [<commit-id>... ]"),
"",
- "[rev-opts] are documented in git-rev-list(1)",
+ N_("[rev-opts] are documented in git-rev-list(1)"),
NULL
};
@@ -250,13 +250,13 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix)
static const struct option options[] = {
OPT_BOOLEAN('n', "numbered", &log.sort_by_number,
- "sort output according to the number of commits per author"),
+ N_("sort output according to the number of commits per author")),
OPT_BOOLEAN('s', "summary", &log.summary,
- "Suppress commit descriptions, only provides commit count"),
+ N_("Suppress commit descriptions, only provides commit count")),
OPT_BOOLEAN('e', "email", &log.email,
- "Show the email address of each author"),
- { OPTION_CALLBACK, 'w', NULL, &log, "w[,i1[,i2]]",
- "Linewrap output", PARSE_OPT_OPTARG, &parse_wrap_args },
+ N_("Show the email address of each author")),
+ { OPTION_CALLBACK, 'w', NULL, &log, N_("w[,i1[,i2]]"),
+ N_("Linewrap output"), PARSE_OPT_OPTARG, &parse_wrap_args },
OPT_END(),
};
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index a59e088..d208fd6 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -6,8 +6,8 @@
#include "parse-options.h"
static const char* show_branch_usage[] = {
- "git show-branch [-a|--all] [-r|--remotes] [--topo-order | --date-order] [--current] [--color[=<when>] | --no-color] [--sparse] [--more=<n> | --list | --independent | --merge-base] [--no-name | --sha1-name] [--topics] [(<rev> | <glob>)...]",
- "git show-branch (-g|--reflog)[=<n>[,<base>]] [--list] [<ref>]",
+ N_("git show-branch [-a|--all] [-r|--remotes] [--topo-order | --date-order] [--current] [--color[=<when>] | --no-color] [--sparse] [--more=<n> | --list | --independent | --merge-base] [--no-name | --sha1-name] [--topics] [(<rev> | <glob>)...]"),
+ N_("git show-branch (-g|--reflog)[=<n>[,<base>]] [--list] [<ref>]"),
NULL
};
@@ -648,36 +648,36 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
const char *reflog_base = NULL;
struct option builtin_show_branch_options[] = {
OPT_BOOLEAN('a', "all", &all_heads,
- "show remote-tracking and local branches"),
+ N_("show remote-tracking and local branches")),
OPT_BOOLEAN('r', "remotes", &all_remotes,
- "show remote-tracking branches"),
+ N_("show remote-tracking branches")),
OPT__COLOR(&showbranch_use_color,
- "color '*!+-' corresponding to the branch"),
- { OPTION_INTEGER, 0, "more", &extra, "n",
- "show <n> more commits after the common ancestor",
+ N_("color '*!+-' corresponding to the branch")),
+ { OPTION_INTEGER, 0, "more", &extra, N_("n"),
+ N_("show <n> more commits after the common ancestor"),
PARSE_OPT_OPTARG, NULL, (intptr_t)1 },
- OPT_SET_INT(0, "list", &extra, "synonym to more=-1", -1),
- OPT_BOOLEAN(0, "no-name", &no_name, "suppress naming strings"),
+ OPT_SET_INT(0, "list", &extra, N_("synonym to more=-1"), -1),
+ OPT_BOOLEAN(0, "no-name", &no_name, N_("suppress naming strings")),
OPT_BOOLEAN(0, "current", &with_current_branch,
- "include the current branch"),
+ N_("include the current branch")),
OPT_BOOLEAN(0, "sha1-name", &sha1_name,
- "name commits with their object names"),
+ N_("name commits with their object names")),
OPT_BOOLEAN(0, "merge-base", &merge_base,
- "show possible merge bases"),
+ N_("show possible merge bases")),
OPT_BOOLEAN(0, "independent", &independent,
- "show refs unreachable from any other ref"),
+ N_("show refs unreachable from any other ref")),
OPT_BOOLEAN(0, "topo-order", &lifo,
- "show commits in topological order"),
+ N_("show commits in topological order")),
OPT_BOOLEAN(0, "topics", &topics,
- "show only commits not on the first branch"),
+ N_("show only commits not on the first branch")),
OPT_SET_INT(0, "sparse", &dense,
- "show merges reachable from only one tip", 0),
+ N_("show merges reachable from only one tip"), 0),
OPT_SET_INT(0, "date-order", &lifo,
- "show commits where no parent comes before its "
- "children", 0),
- { OPTION_CALLBACK, 'g', "reflog", &reflog_base, "<n>[,<base>]",
- "show <n> most recent ref-log entries starting at "
- "base",
+ N_("show commits where no parent comes before its "
+ "children"), 0),
+ { OPTION_CALLBACK, 'g', "reflog", &reflog_base, N_("<n>[,<base>]"),
+ N_("show <n> most recent ref-log entries starting at "
+ "base"),
PARSE_OPT_OPTARG | PARSE_OPT_LITERAL_ARGHELP,
parse_reflog_param },
OPT_END()
diff --git a/builtin/show-ref.c b/builtin/show-ref.c
index 3911661..4eb016d 100644
--- a/builtin/show-ref.c
+++ b/builtin/show-ref.c
@@ -7,8 +7,8 @@
#include "parse-options.h"
static const char * const show_ref_usage[] = {
- "git show-ref [-q|--quiet] [--verify] [--head] [-d|--dereference] [-s|--hash[=<n>]] [--abbrev[=<n>]] [--tags] [--heads] [--] [pattern*] ",
- "git show-ref --exclude-existing[=pattern] < ref-list",
+ N_("git show-ref [-q|--quiet] [--verify] [--head] [-d|--dereference] [-s|--hash[=<n>]] [--abbrev[=<n>]] [--tags] [--heads] [--] [pattern*] "),
+ N_("git show-ref --exclude-existing[=pattern] < ref-list"),
NULL
};
@@ -179,26 +179,26 @@ static int help_callback(const struct option *opt, const char *arg, int unset)
}
static const struct option show_ref_options[] = {
- OPT_BOOLEAN(0, "tags", &tags_only, "only show tags (can be combined with heads)"),
- OPT_BOOLEAN(0, "heads", &heads_only, "only show heads (can be combined with tags)"),
- OPT_BOOLEAN(0, "verify", &verify, "stricter reference checking, "
- "requires exact ref path"),
+ OPT_BOOLEAN(0, "tags", &tags_only, N_("only show tags (can be combined with heads)")),
+ OPT_BOOLEAN(0, "heads", &heads_only, N_("only show heads (can be combined with tags)")),
+ OPT_BOOLEAN(0, "verify", &verify, N_("stricter reference checking, "
+ "requires exact ref path")),
{ OPTION_BOOLEAN, 'h', NULL, &show_head, NULL,
- "show the HEAD reference",
+ N_("show the HEAD reference"),
PARSE_OPT_NOARG | PARSE_OPT_HIDDEN },
- OPT_BOOLEAN(0, "head", &show_head, "show the HEAD reference"),
+ OPT_BOOLEAN(0, "head", &show_head, N_("show the HEAD reference")),
OPT_BOOLEAN('d', "dereference", &deref_tags,
- "dereference tags into object IDs"),
- { OPTION_CALLBACK, 's', "hash", &abbrev, "n",
- "only show SHA1 hash using <n> digits",
+ N_("dereference tags into object IDs")),
+ { OPTION_CALLBACK, 's', "hash", &abbrev, N_("n"),
+ N_("only show SHA1 hash using <n> digits"),
PARSE_OPT_OPTARG, &hash_callback },
OPT__ABBREV(&abbrev),
OPT__QUIET(&quiet,
- "do not print results to stdout (useful with --verify)"),
+ N_("do not print results to stdout (useful with --verify)")),
{ OPTION_CALLBACK, 0, "exclude-existing", &exclude_existing_arg,
- "pattern", "show refs from stdin that aren't in local repository",
+ N_("pattern"), N_("show refs from stdin that aren't in local repository"),
PARSE_OPT_OPTARG | PARSE_OPT_NONEG, exclude_existing_callback },
- { OPTION_CALLBACK, 0, "help-all", NULL, NULL, "show usage",
+ { OPTION_CALLBACK, 0, "help-all", NULL, NULL, N_("show usage"),
PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, help_callback },
OPT_END()
};
diff --git a/builtin/symbolic-ref.c b/builtin/symbolic-ref.c
index 801d62e..9e92828 100644
--- a/builtin/symbolic-ref.c
+++ b/builtin/symbolic-ref.c
@@ -4,7 +4,7 @@
#include "parse-options.h"
static const char * const git_symbolic_ref_usage[] = {
- "git symbolic-ref [options] name [ref]",
+ N_("git symbolic-ref [options] name [ref]"),
NULL
};
@@ -35,9 +35,9 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
const char *msg = NULL;
struct option options[] = {
OPT__QUIET(&quiet,
- "suppress error message for non-symbolic (detached) refs"),
- OPT_BOOL(0, "short", &shorten, "shorten ref output"),
- OPT_STRING('m', NULL, &msg, "reason", "reason of the update"),
+ N_("suppress error message for non-symbolic (detached) refs")),
+ OPT_BOOL(0, "short", &shorten, N_("shorten ref output")),
+ OPT_STRING('m', NULL, &msg, N_("reason"), N_("reason of the update")),
OPT_END(),
};
diff --git a/builtin/tag.c b/builtin/tag.c
index 7b1be85..9c3e067 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -19,11 +19,11 @@
#include "column.h"
static const char * const git_tag_usage[] = {
- "git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]",
- "git tag -d <tagname>...",
- "git tag -l [-n[<num>]] [--contains <commit>] [--points-at <object>] "
- "\n\t\t[<pattern>...]",
- "git tag -v <tagname>...",
+ N_("git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]"),
+ N_("git tag -d <tagname>..."),
+ N_("git tag -l [-n[<num>]] [--contains <commit>] [--points-at <object>] "
+ "\n\t\t[<pattern>...]"),
+ N_("git tag -v <tagname>..."),
NULL
};
@@ -444,37 +444,37 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
struct msg_arg msg = { 0, STRBUF_INIT };
struct commit_list *with_commit = NULL;
struct option options[] = {
- OPT_BOOLEAN('l', "list", &list, "list tag names"),
- { OPTION_INTEGER, 'n', NULL, &lines, "n",
- "print <n> lines of each tag message",
+ OPT_BOOLEAN('l', "list", &list, N_("list tag names")),
+ { OPTION_INTEGER, 'n', NULL, &lines, N_("n"),
+ N_("print <n> lines of each tag message"),
PARSE_OPT_OPTARG, NULL, 1 },
- OPT_BOOLEAN('d', "delete", &delete, "delete tags"),
- OPT_BOOLEAN('v', "verify", &verify, "verify tags"),
+ OPT_BOOLEAN('d', "delete", &delete, N_("delete tags")),
+ OPT_BOOLEAN('v', "verify", &verify, N_("verify tags")),
- OPT_GROUP("Tag creation options"),
+ OPT_GROUP(N_("Tag creation options")),
OPT_BOOLEAN('a', "annotate", &annotate,
- "annotated tag, needs a message"),
- OPT_CALLBACK('m', "message", &msg, "message",
- "tag message", parse_msg_arg),
- OPT_FILENAME('F', "file", &msgfile, "read message from file"),
- OPT_BOOLEAN('s', "sign", &opt.sign, "annotated and GPG-signed tag"),
- OPT_STRING(0, "cleanup", &cleanup_arg, "mode",
- "how to strip spaces and #comments from message"),
- OPT_STRING('u', "local-user", &keyid, "key-id",
- "use another key to sign the tag"),
- OPT__FORCE(&force, "replace the tag if exists"),
- OPT_COLUMN(0, "column", &colopts, "show tag list in columns"),
-
- OPT_GROUP("Tag listing options"),
+ N_("annotated tag, needs a message")),
+ OPT_CALLBACK('m', "message", &msg, N_("message"),
+ N_("tag message"), parse_msg_arg),
+ OPT_FILENAME('F', "file", &msgfile, N_("read message from file")),
+ OPT_BOOLEAN('s', "sign", &opt.sign, N_("annotated and GPG-signed tag")),
+ OPT_STRING(0, "cleanup", &cleanup_arg, N_("mode"),
+ N_("how to strip spaces and #comments from message")),
+ OPT_STRING('u', "local-user", &keyid, N_("key id"),
+ N_("use another key to sign the tag")),
+ OPT__FORCE(&force, N_("replace the tag if exists")),
+ OPT_COLUMN(0, "column", &colopts, N_("show tag list in columns")),
+
+ OPT_GROUP(N_("Tag listing options")),
{
- OPTION_CALLBACK, 0, "contains", &with_commit, "commit",
- "print only tags that contain the commit",
+ OPTION_CALLBACK, 0, "contains", &with_commit, N_("commit"),
+ N_("print only tags that contain the commit"),
PARSE_OPT_LASTARG_DEFAULT,
parse_opt_with_commit, (intptr_t)"HEAD",
},
{
- OPTION_CALLBACK, 0, "points-at", NULL, "object",
- "print only tags of the object", 0, parse_opt_points_at
+ OPTION_CALLBACK, 0, "points-at", NULL, N_("object"),
+ N_("print only tags of the object"), 0, parse_opt_points_at
},
OPT_END()
};
diff --git a/builtin/update-index.c b/builtin/update-index.c
index 4ce341c..74986bf 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -398,7 +398,7 @@ static void read_index_info(int line_termination)
}
static const char * const update_index_usage[] = {
- "git update-index [options] [--] [<file>...]",
+ N_("git update-index [options] [--] [<file>...]"),
NULL
};
@@ -714,83 +714,83 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
int parseopt_state = PARSE_OPT_UNKNOWN;
struct option options[] = {
OPT_BIT('q', NULL, &refresh_args.flags,
- "continue refresh even when index needs update",
+ N_("continue refresh even when index needs update"),
REFRESH_QUIET),
OPT_BIT(0, "ignore-submodules", &refresh_args.flags,
- "refresh: ignore submodules",
+ N_("refresh: ignore submodules"),
REFRESH_IGNORE_SUBMODULES),
OPT_SET_INT(0, "add", &allow_add,
- "do not ignore new files", 1),
+ N_("do not ignore new files"), 1),
OPT_SET_INT(0, "replace", &allow_replace,
- "let files replace directories and vice-versa", 1),
+ N_("let files replace directories and vice-versa"), 1),
OPT_SET_INT(0, "remove", &allow_remove,
- "notice files missing from worktree", 1),
+ N_("notice files missing from worktree"), 1),
OPT_BIT(0, "unmerged", &refresh_args.flags,
- "refresh even if index contains unmerged entries",
+ N_("refresh even if index contains unmerged entries"),
REFRESH_UNMERGED),
{OPTION_CALLBACK, 0, "refresh", &refresh_args, NULL,
- "refresh stat information",
+ N_("refresh stat information"),
PARSE_OPT_NOARG | PARSE_OPT_NONEG,
refresh_callback},
{OPTION_CALLBACK, 0, "really-refresh", &refresh_args, NULL,
- "like --refresh, but ignore assume-unchanged setting",
+ N_("like --refresh, but ignore assume-unchanged setting"),
PARSE_OPT_NOARG | PARSE_OPT_NONEG,
really_refresh_callback},
{OPTION_LOWLEVEL_CALLBACK, 0, "cacheinfo", NULL,
- "<mode> <object> <path>",
- "add the specified entry to the index",
+ N_("<mode> <object> <path>"),
+ N_("add the specified entry to the index"),
PARSE_OPT_NOARG | /* disallow --cacheinfo=<mode> form */
PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
(parse_opt_cb *) cacheinfo_callback},
- {OPTION_CALLBACK, 0, "chmod", &set_executable_bit, "(+/-)x",
- "override the executable bit of the listed files",
+ {OPTION_CALLBACK, 0, "chmod", &set_executable_bit, N_("(+/-)x"),
+ N_("override the executable bit of the listed files"),
PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
chmod_callback},
{OPTION_SET_INT, 0, "assume-unchanged", &mark_valid_only, NULL,
- "mark files as \"not changing\"",
+ N_("mark files as \"not changing\""),
PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, MARK_FLAG},
{OPTION_SET_INT, 0, "no-assume-unchanged", &mark_valid_only, NULL,
- "clear assumed-unchanged bit",
+ N_("clear assumed-unchanged bit"),
PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, UNMARK_FLAG},
{OPTION_SET_INT, 0, "skip-worktree", &mark_skip_worktree_only, NULL,
- "mark files as \"index-only\"",
+ N_("mark files as \"index-only\""),
PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, MARK_FLAG},
{OPTION_SET_INT, 0, "no-skip-worktree", &mark_skip_worktree_only, NULL,
- "clear skip-worktree bit",
+ N_("clear skip-worktree bit"),
PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, UNMARK_FLAG},
OPT_SET_INT(0, "info-only", &info_only,
- "add to index only; do not add content to object database", 1),
+ N_("add to index only; do not add content to object database"), 1),
OPT_SET_INT(0, "force-remove", &force_remove,
- "remove named paths even if present in worktree", 1),
+ N_("remove named paths even if present in worktree"), 1),
OPT_SET_INT('z', NULL, &line_termination,
- "with --stdin: input lines are terminated by null bytes", '\0'),
+ N_("with --stdin: input lines are terminated by null bytes"), '\0'),
{OPTION_LOWLEVEL_CALLBACK, 0, "stdin", &read_from_stdin, NULL,
- "read list of paths to be updated from standard input",
+ N_("read list of paths to be updated from standard input"),
PARSE_OPT_NONEG | PARSE_OPT_NOARG,
(parse_opt_cb *) stdin_callback},
{OPTION_LOWLEVEL_CALLBACK, 0, "index-info", &line_termination, NULL,
- "add entries from standard input to the index",
+ N_("add entries from standard input to the index"),
PARSE_OPT_NONEG | PARSE_OPT_NOARG,
(parse_opt_cb *) stdin_cacheinfo_callback},
{OPTION_LOWLEVEL_CALLBACK, 0, "unresolve", &has_errors, NULL,
- "repopulate stages #2 and #3 for the listed paths",
+ N_("repopulate stages #2 and #3 for the listed paths"),
PARSE_OPT_NONEG | PARSE_OPT_NOARG,
(parse_opt_cb *) unresolve_callback},
{OPTION_LOWLEVEL_CALLBACK, 'g', "again", &has_errors, NULL,
- "only update entries that differ from HEAD",
+ N_("only update entries that differ from HEAD"),
PARSE_OPT_NONEG | PARSE_OPT_NOARG,
(parse_opt_cb *) reupdate_callback},
OPT_BIT(0, "ignore-missing", &refresh_args.flags,
- "ignore files missing from worktree",
+ N_("ignore files missing from worktree"),
REFRESH_IGNORE_MISSING),
OPT_SET_INT(0, "verbose", &verbose,
- "report actions to standard output", 1),
+ N_("report actions to standard output"), 1),
{OPTION_CALLBACK, 0, "clear-resolve-undo", NULL, NULL,
- "(for porcelains) forget saved unresolved conflicts",
+ N_("(for porcelains) forget saved unresolved conflicts"),
PARSE_OPT_NOARG | PARSE_OPT_NONEG,
resolve_undo_clear_callback},
OPT_INTEGER(0, "index-version", &preferred_index_format,
- "write index in this format"),
+ N_("write index in this format")),
OPT_END()
};
diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index 835c62a..51d2684 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -4,8 +4,8 @@
#include "parse-options.h"
static const char * const git_update_ref_usage[] = {
- "git update-ref [options] -d <refname> [<oldval>]",
- "git update-ref [options] <refname> <newval> [<oldval>]",
+ N_("git update-ref [options] -d <refname> [<oldval>]"),
+ N_("git update-ref [options] <refname> <newval> [<oldval>]"),
NULL
};
@@ -15,10 +15,10 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
unsigned char sha1[20], oldsha1[20];
int delete = 0, no_deref = 0, flags = 0;
struct option options[] = {
- OPT_STRING( 'm', NULL, &msg, "reason", "reason of the update"),
- OPT_BOOLEAN('d', NULL, &delete, "deletes the reference"),
+ OPT_STRING( 'm', NULL, &msg, N_("reason"), N_("reason of the update")),
+ OPT_BOOLEAN('d', NULL, &delete, N_("delete the reference")),
OPT_BOOLEAN( 0 , "no-deref", &no_deref,
- "update <refname> not the one it points to"),
+ N_("update <refname> not the one it points to")),
OPT_END(),
};
diff --git a/builtin/update-server-info.c b/builtin/update-server-info.c
index 0d63c44..6c8cc3e 100644
--- a/builtin/update-server-info.c
+++ b/builtin/update-server-info.c
@@ -3,7 +3,7 @@
#include "parse-options.h"
static const char * const update_server_info_usage[] = {
- "git update-server-info [--force]",
+ N_("git update-server-info [--force]"),
NULL
};
@@ -11,7 +11,7 @@ int cmd_update_server_info(int argc, const char **argv, const char *prefix)
{
int force = 0;
struct option options[] = {
- OPT__FORCE(&force, "update the info files from scratch"),
+ OPT__FORCE(&force, N_("update the info files from scratch")),
OPT_END()
};
diff --git a/builtin/verify-pack.c b/builtin/verify-pack.c
index e841b4a..66cd2df 100644
--- a/builtin/verify-pack.c
+++ b/builtin/verify-pack.c
@@ -53,7 +53,7 @@ static int verify_one_pack(const char *path, unsigned int flags)
}
static const char * const verify_pack_usage[] = {
- "git verify-pack [-v|--verbose] [-s|--stat-only] <pack>...",
+ N_("git verify-pack [-v|--verbose] [-s|--stat-only] <pack>..."),
NULL
};
@@ -63,9 +63,9 @@ int cmd_verify_pack(int argc, const char **argv, const char *prefix)
unsigned int flags = 0;
int i;
const struct option verify_pack_options[] = {
- OPT_BIT('v', "verbose", &flags, "verbose",
+ OPT_BIT('v', "verbose", &flags, N_("verbose"),
VERIFY_PACK_VERBOSE),
- OPT_BIT('s', "stat-only", &flags, "show statistics only",
+ OPT_BIT('s', "stat-only", &flags, N_("show statistics only"),
VERIFY_PACK_STAT_ONLY),
OPT_END()
};
diff --git a/builtin/verify-tag.c b/builtin/verify-tag.c
index 986789f..a8eee88 100644
--- a/builtin/verify-tag.c
+++ b/builtin/verify-tag.c
@@ -14,7 +14,7 @@
#include "gpg-interface.h"
static const char * const verify_tag_usage[] = {
- "git verify-tag [-v|--verbose] <tag>...",
+ N_("git verify-tag [-v|--verbose] <tag>..."),
NULL
};
@@ -70,7 +70,7 @@ int cmd_verify_tag(int argc, const char **argv, const char *prefix)
{
int i = 1, verbose = 0, had_error = 0;
const struct option verify_tag_options[] = {
- OPT__VERBOSE(&verbose, "print tag contents"),
+ OPT__VERBOSE(&verbose, N_("print tag contents")),
OPT_END()
};
diff --git a/builtin/write-tree.c b/builtin/write-tree.c
index b223af4..084c0df 100644
--- a/builtin/write-tree.c
+++ b/builtin/write-tree.c
@@ -10,7 +10,7 @@
#include "parse-options.h"
static const char * const write_tree_usage[] = {
- "git write-tree [--missing-ok] [--prefix=<prefix>/]",
+ N_("git write-tree [--missing-ok] [--prefix=<prefix>/]"),
NULL
};
@@ -21,13 +21,13 @@ int cmd_write_tree(int argc, const char **argv, const char *unused_prefix)
unsigned char sha1[20];
const char *me = "git-write-tree";
struct option write_tree_options[] = {
- OPT_BIT(0, "missing-ok", &flags, "allow missing objects",
+ OPT_BIT(0, "missing-ok", &flags, N_("allow missing objects"),
WRITE_TREE_MISSING_OK),
- { OPTION_STRING, 0, "prefix", &prefix, "<prefix>/",
- "write tree object for a subdirectory <prefix>" ,
+ { OPTION_STRING, 0, "prefix", &prefix, N_("<prefix>/"),
+ N_("write tree object for a subdirectory <prefix>") ,
PARSE_OPT_LITERAL_ARGHELP },
{ OPTION_BIT, 0, "ignore-cache-tree", &flags, NULL,
- "only useful for debugging",
+ N_("only useful for debugging"),
PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, NULL,
WRITE_TREE_IGNORE_CACHE_TREE },
OPT_END()
diff --git a/cache.h b/cache.h
index 67f28b4..a58df84 100644
--- a/cache.h
+++ b/cache.h
@@ -442,7 +442,6 @@ extern int discard_index(struct index_state *);
extern int unmerged_index(const struct index_state *);
extern int verify_path(const char *path);
extern struct cache_entry *index_name_exists(struct index_state *istate, const char *name, int namelen, int igncase);
-extern int index_name_stage_pos(const struct index_state *, const char *name, int namelen, int stage);
extern int index_name_pos(const struct index_state *, const char *name, int namelen);
#define ADD_CACHE_OK_TO_ADD 1 /* Ok to add */
#define ADD_CACHE_OK_TO_REPLACE 2 /* Ok to replace file/directory */
@@ -902,9 +901,7 @@ extern const char *git_author_info(int);
extern const char *git_committer_info(int);
extern const char *fmt_ident(const char *name, const char *email, const char *date_str, int);
extern const char *fmt_name(const char *name, const char *email);
-extern const char *ident_default_name(void);
extern const char *ident_default_email(void);
-extern const char *ident_default_date(void);
extern const char *git_editor(void);
extern const char *git_pager(int stdout_is_tty);
extern int git_ident_config(const char *, const char *, void *);
@@ -947,9 +944,7 @@ struct cache_def {
extern int has_symlink_leading_path(const char *name, int len);
extern int threaded_has_symlink_leading_path(struct cache_def *, const char *, int);
extern int check_leading_path(const char *name, int len);
-extern int threaded_check_leading_path(struct cache_def *cache, const char *name, int len);
extern int has_dirs_only_path(const char *name, int len, int prefix_len);
-extern int threaded_has_dirs_only_path(struct cache_def *cache, const char *name, int len, int prefix_len);
extern void schedule_dir_for_removal(const char *name, int len);
extern void remove_scheduled_dirs(void);
@@ -1038,7 +1033,9 @@ struct extra_have_objects {
};
extern struct ref **get_remote_heads(int in, struct ref **list, unsigned int flags, struct extra_have_objects *);
extern int server_supports(const char *feature);
-extern const char *parse_feature_request(const char *features, const char *feature);
+extern int parse_feature_request(const char *features, const char *feature);
+extern const char *server_feature_value(const char *feature, int *len_ret);
+extern const char *parse_feature_value(const char *feature_list, const char *feature, int *len_ret);
extern struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path);
@@ -1108,6 +1105,7 @@ extern int update_server_info(int);
#define CONFIG_NO_WRITE 4
#define CONFIG_NOTHING_SET 5
#define CONFIG_INVALID_PATTERN 6
+#define CONFIG_GENERIC_ERROR 7
typedef int (*config_fn_t)(const char *, const char *, void *);
extern int git_default_config(const char *, const char *, void *);
@@ -1205,7 +1203,6 @@ extern void alloc_report(void);
/* trace.c */
__attribute__((format (printf, 1, 2)))
extern void trace_printf(const char *format, ...);
-extern void trace_vprintf(const char *key, const char *format, va_list ap);
__attribute__((format (printf, 2, 3)))
extern void trace_argv_printf(const char **argv, const char *format, ...);
extern void trace_repo_setup(const char *prefix);
diff --git a/combine-diff.c b/combine-diff.c
index 9786680..bb1cc96 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -111,7 +111,7 @@ static char *grab_blob(const unsigned char *sha1, unsigned int mode,
return xcalloc(1, 1);
} else if (textconv) {
struct diff_filespec *df = alloc_filespec(path);
- fill_filespec(df, sha1, mode);
+ fill_filespec(df, sha1, 1, mode);
*size = fill_textconv(textconv, df, &blob);
free_filespec(df);
} else {
@@ -823,7 +823,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
&result_size, NULL, NULL);
} else if (textconv) {
struct diff_filespec *df = alloc_filespec(elem->path);
- fill_filespec(df, null_sha1, st.st_mode);
+ fill_filespec(df, null_sha1, 0, st.st_mode);
result_size = fill_textconv(textconv, df, &result);
free_filespec(df);
} else if (0 <= (fd = open(elem->path, O_RDONLY))) {
diff --git a/command-list.txt b/command-list.txt
index ec64cac..7e8cfec 100644
--- a/command-list.txt
+++ b/command-list.txt
@@ -26,6 +26,8 @@ git-commit-tree plumbingmanipulators
git-config ancillarymanipulators
git-count-objects ancillaryinterrogators
git-credential purehelpers
+git-credential-cache purehelpers
+git-credential-store purehelpers
git-cvsexportcommit foreignscminterface
git-cvsimport foreignscminterface
git-cvsserver foreignscminterface
@@ -114,6 +116,7 @@ git-show mainporcelain common
git-show-branch ancillaryinterrogators
git-show-index plumbinginterrogators
git-show-ref plumbinginterrogators
+git-sh-i18n purehelpers
git-sh-setup purehelpers
git-stash mainporcelain
git-status mainporcelain common
diff --git a/commit.c b/commit.c
index 42af4c1..213bc98 100644
--- a/commit.c
+++ b/commit.c
@@ -9,6 +9,8 @@
#include "gpg-interface.h"
#include "mergesort.h"
+static struct commit_extra_header *read_commit_extra_header_lines(const char *buf, size_t len, const char **);
+
int save_commit_buffer = 1;
const char *commit_type = "commit";
@@ -607,30 +609,17 @@ static struct commit *interesting(struct commit_list *list)
return NULL;
}
-static struct commit_list *merge_bases_many(struct commit *one, int n, struct commit **twos)
+/* all input commits in one and twos[] must have been parsed! */
+static struct commit_list *paint_down_to_common(struct commit *one, int n, struct commit **twos)
{
struct commit_list *list = NULL;
struct commit_list *result = NULL;
int i;
- for (i = 0; i < n; i++) {
- if (one == twos[i])
- /*
- * We do not mark this even with RESULT so we do not
- * have to clean it up.
- */
- return commit_list_insert(one, &result);
- }
-
- if (parse_commit(one))
- return NULL;
- for (i = 0; i < n; i++) {
- if (parse_commit(twos[i]))
- return NULL;
- }
-
one->object.flags |= PARENT1;
commit_list_insert_by_date(one, &list);
+ if (!n)
+ return list;
for (i = 0; i < n; i++) {
twos[i]->object.flags |= PARENT2;
commit_list_insert_by_date(twos[i], &list);
@@ -669,9 +658,34 @@ static struct commit_list *merge_bases_many(struct commit *one, int n, struct co
}
}
- /* Clean up the result to remove stale ones */
free_commit_list(list);
- list = result; result = NULL;
+ return result;
+}
+
+static struct commit_list *merge_bases_many(struct commit *one, int n, struct commit **twos)
+{
+ struct commit_list *list = NULL;
+ struct commit_list *result = NULL;
+ int i;
+
+ for (i = 0; i < n; i++) {
+ if (one == twos[i])
+ /*
+ * We do not mark this even with RESULT so we do not
+ * have to clean it up.
+ */
+ return commit_list_insert(one, &result);
+ }
+
+ if (parse_commit(one))
+ return NULL;
+ for (i = 0; i < n; i++) {
+ if (parse_commit(twos[i]))
+ return NULL;
+ }
+
+ list = paint_down_to_common(one, n, twos);
+
while (list) {
struct commit_list *next = list->next;
if (!(list->item->object.flags & STALE))
@@ -709,6 +723,62 @@ struct commit_list *get_octopus_merge_bases(struct commit_list *in)
return ret;
}
+static int remove_redundant(struct commit **array, int cnt)
+{
+ /*
+ * Some commit in the array may be an ancestor of
+ * another commit. Move such commit to the end of
+ * the array, and return the number of commits that
+ * are independent from each other.
+ */
+ struct commit **work;
+ unsigned char *redundant;
+ int *filled_index;
+ int i, j, filled;
+
+ work = xcalloc(cnt, sizeof(*work));
+ redundant = xcalloc(cnt, 1);
+ filled_index = xmalloc(sizeof(*filled_index) * (cnt - 1));
+
+ for (i = 0; i < cnt; i++)
+ parse_commit(array[i]);
+ for (i = 0; i < cnt; i++) {
+ struct commit_list *common;
+
+ if (redundant[i])
+ continue;
+ for (j = filled = 0; j < cnt; j++) {
+ if (i == j || redundant[j])
+ continue;
+ filled_index[filled] = j;
+ work[filled++] = array[j];
+ }
+ common = paint_down_to_common(array[i], filled, work);
+ if (array[i]->object.flags & PARENT2)
+ redundant[i] = 1;
+ for (j = 0; j < filled; j++)
+ if (work[j]->object.flags & PARENT1)
+ redundant[filled_index[j]] = 1;
+ clear_commit_marks(array[i], all_flags);
+ for (j = 0; j < filled; j++)
+ clear_commit_marks(work[j], all_flags);
+ free_commit_list(common);
+ }
+
+ /* Now collect the result */
+ memcpy(work, array, sizeof(*array) * cnt);
+ for (i = filled = 0; i < cnt; i++)
+ if (!redundant[i])
+ array[filled++] = work[i];
+ for (j = filled, i = 0; i < cnt; i++)
+ if (redundant[i])
+ array[j++] = work[i];
+ free(work);
+ free(redundant);
+ free(filled_index);
+ return filled;
+}
+
struct commit_list *get_merge_bases_many(struct commit *one,
int n,
struct commit **twos,
@@ -717,7 +787,7 @@ struct commit_list *get_merge_bases_many(struct commit *one,
struct commit_list *list;
struct commit **rslt;
struct commit_list *result;
- int cnt, i, j;
+ int cnt, i;
result = merge_bases_many(one, n, twos);
for (i = 0; i < n; i++) {
@@ -748,28 +818,11 @@ struct commit_list *get_merge_bases_many(struct commit *one,
clear_commit_marks(one, all_flags);
for (i = 0; i < n; i++)
clear_commit_marks(twos[i], all_flags);
- for (i = 0; i < cnt - 1; i++) {
- for (j = i+1; j < cnt; j++) {
- if (!rslt[i] || !rslt[j])
- continue;
- result = merge_bases_many(rslt[i], 1, &rslt[j]);
- clear_commit_marks(rslt[i], all_flags);
- clear_commit_marks(rslt[j], all_flags);
- for (list = result; list; list = list->next) {
- if (rslt[i] == list->item)
- rslt[i] = NULL;
- if (rslt[j] == list->item)
- rslt[j] = NULL;
- }
- }
- }
- /* Surviving ones in rslt[] are the independent results */
+ cnt = remove_redundant(rslt, cnt);
result = NULL;
- for (i = 0; i < cnt; i++) {
- if (rslt[i])
- commit_list_insert_by_date(rslt[i], &result);
- }
+ for (i = 0; i < cnt; i++)
+ commit_list_insert_by_date(rslt[i], &result);
free(rslt);
return result;
}
@@ -780,6 +833,9 @@ struct commit_list *get_merge_bases(struct commit *one, struct commit *two,
return get_merge_bases_many(one, 1, &two, cleanup);
}
+/*
+ * Is "commit" a decendant of one of the elements on the "with_commit" list?
+ */
int is_descendant_of(struct commit *commit, struct commit_list *with_commit)
{
if (!with_commit)
@@ -789,28 +845,28 @@ int is_descendant_of(struct commit *commit, struct commit_list *with_commit)
other = with_commit->item;
with_commit = with_commit->next;
- if (in_merge_bases(other, &commit, 1))
+ if (in_merge_bases(other, commit))
return 1;
}
return 0;
}
-int in_merge_bases(struct commit *commit, struct commit **reference, int num)
+/*
+ * Is "commit" an ancestor of (i.e. reachable from) the "reference"?
+ */
+int in_merge_bases(struct commit *commit, struct commit *reference)
{
- struct commit_list *bases, *b;
+ struct commit_list *bases;
int ret = 0;
- if (num == 1)
- bases = get_merge_bases(commit, *reference, 1);
- else
- die("not yet");
- for (b = bases; b; b = b->next) {
- if (!hashcmp(commit->object.sha1, b->item->object.sha1)) {
- ret = 1;
- break;
- }
- }
+ if (parse_commit(commit) || parse_commit(reference))
+ return ret;
+ bases = paint_down_to_common(commit, 1, &reference);
+ if (commit->object.flags & PARENT2)
+ ret = 1;
+ clear_commit_marks(commit, all_flags);
+ clear_commit_marks(reference, all_flags);
free_commit_list(bases);
return ret;
}
@@ -819,51 +875,31 @@ struct commit_list *reduce_heads(struct commit_list *heads)
{
struct commit_list *p;
struct commit_list *result = NULL, **tail = &result;
- struct commit **other;
- size_t num_head, num_other;
+ struct commit **array;
+ int num_head, i;
if (!heads)
return NULL;
- /* Avoid unnecessary reallocations */
- for (p = heads, num_head = 0; p; p = p->next)
- num_head++;
- other = xcalloc(sizeof(*other), num_head);
-
- /* For each commit, see if it can be reached by others */
- for (p = heads; p; p = p->next) {
- struct commit_list *q, *base;
-
- /* Do we already have this in the result? */
- for (q = result; q; q = q->next)
- if (p->item == q->item)
- break;
- if (q)
+ /* Uniquify */
+ for (p = heads; p; p = p->next)
+ p->item->object.flags &= ~STALE;
+ for (p = heads, num_head = 0; p; p = p->next) {
+ if (p->item->object.flags & STALE)
continue;
-
- num_other = 0;
- for (q = heads; q; q = q->next) {
- if (p->item == q->item)
- continue;
- other[num_other++] = q->item;
+ p->item->object.flags |= STALE;
+ num_head++;
+ }
+ array = xcalloc(sizeof(*array), num_head);
+ for (p = heads, i = 0; p; p = p->next) {
+ if (p->item->object.flags & STALE) {
+ array[i++] = p->item;
+ p->item->object.flags &= ~STALE;
}
- if (num_other)
- base = get_merge_bases_many(p->item, num_other, other, 1);
- else
- base = NULL;
- /*
- * If p->item does not have anything common with other
- * commits, there won't be any merge base. If it is
- * reachable from some of the others, p->item will be
- * the merge base. If its history is connected with
- * others, but p->item is not reachable by others, we
- * will get something other than p->item back.
- */
- if (!base || (base->item != p->item))
- tail = &(commit_list_insert(p->item, tail)->next);
- free_commit_list(base);
}
- free(other);
+ num_head = remove_redundant(array, num_head);
+ for (i = 0; i < num_head; i++)
+ tail = &commit_list_insert(array[i], tail)->next;
return result;
}
@@ -1044,8 +1080,9 @@ static int excluded_header_field(const char *field, size_t len, const char **exc
return 0;
}
-struct commit_extra_header *read_commit_extra_header_lines(const char *buffer, size_t size,
- const char **exclude)
+static struct commit_extra_header *read_commit_extra_header_lines(
+ const char *buffer, size_t size,
+ const char **exclude)
{
struct commit_extra_header *extra = NULL, **tail = &extra, *it = NULL;
const char *line, *next, *eof, *eob;
@@ -1112,8 +1149,92 @@ int commit_tree(const struct strbuf *msg, unsigned char *tree,
return result;
}
+static int find_invalid_utf8(const char *buf, int len)
+{
+ int offset = 0;
+
+ while (len) {
+ unsigned char c = *buf++;
+ int bytes, bad_offset;
+
+ len--;
+ offset++;
+
+ /* Simple US-ASCII? No worries. */
+ if (c < 0x80)
+ continue;
+
+ bad_offset = offset-1;
+
+ /*
+ * Count how many more high bits set: that's how
+ * many more bytes this sequence should have.
+ */
+ bytes = 0;
+ while (c & 0x40) {
+ c <<= 1;
+ bytes++;
+ }
+
+ /* Must be between 1 and 5 more bytes */
+ if (bytes < 1 || bytes > 5)
+ return bad_offset;
+
+ /* Do we *have* that many bytes? */
+ if (len < bytes)
+ return bad_offset;
+
+ offset += bytes;
+ len -= bytes;
+
+ /* And verify that they are good continuation bytes */
+ do {
+ if ((*buf++ & 0xc0) != 0x80)
+ return bad_offset;
+ } while (--bytes);
+
+ /* We could/should check the value and length here too */
+ }
+ return -1;
+}
+
+/*
+ * This verifies that the buffer is in proper utf8 format.
+ *
+ * If it isn't, it assumes any non-utf8 characters are Latin1,
+ * and does the conversion.
+ *
+ * Fixme: we should probably also disallow overlong forms and
+ * invalid characters. But we don't do that currently.
+ */
+static int verify_utf8(struct strbuf *buf)
+{
+ int ok = 1;
+ long pos = 0;
+
+ for (;;) {
+ int bad;
+ unsigned char c;
+ unsigned char replace[2];
+
+ bad = find_invalid_utf8(buf->buf + pos, buf->len - pos);
+ if (bad < 0)
+ return ok;
+ pos += bad;
+ ok = 0;
+ c = buf->buf[pos];
+ strbuf_remove(buf, pos, 1);
+
+ /* We know 'c' must be in the range 128-255 */
+ replace[0] = 0xc0 + (c >> 6);
+ replace[1] = 0x80 + (c & 0x3f);
+ strbuf_insert(buf, pos, replace, 2);
+ pos += 2;
+ }
+}
+
static const char commit_utf8_warn[] =
-"Warning: commit message does not conform to UTF-8.\n"
+"Warning: commit message did not conform to UTF-8.\n"
"You may want to amend it after fixing the message, or set the config\n"
"variable i18n.commitencoding to the encoding your project uses.\n";
@@ -1170,7 +1291,7 @@ int commit_tree_extended(const struct strbuf *msg, unsigned char *tree,
strbuf_addbuf(&buffer, msg);
/* And check the encoding */
- if (encoding_is_utf8 && !is_utf8(buffer.buf))
+ if (encoding_is_utf8 && !verify_utf8(&buffer))
fprintf(stderr, commit_utf8_warn);
if (sign_commit && do_sign_commit(&buffer, sign_commit))
diff --git a/commit.h b/commit.h
index d617fa3..9f21313 100644
--- a/commit.h
+++ b/commit.h
@@ -171,7 +171,7 @@ extern struct commit_list *get_shallow_commits(struct object_array *heads,
int depth, int shallow_flag, int not_shallow_flag);
int is_descendant_of(struct commit *, struct commit_list *);
-int in_merge_bases(struct commit *, struct commit **, int);
+int in_merge_bases(struct commit *, struct commit *);
extern int interactive_add(int argc, const char **argv, const char *prefix, int patch);
extern int run_add_interactive(const char *revision, const char *patch_mode,
@@ -204,7 +204,6 @@ extern int commit_tree_extended(const struct strbuf *msg, unsigned char *tree,
struct commit_extra_header *);
extern struct commit_extra_header *read_commit_extra_headers(struct commit *, const char **);
-extern struct commit_extra_header *read_commit_extra_header_lines(const char *buf, size_t len, const char **);
extern void free_commit_extra_headers(struct commit_extra_header *extra);
diff --git a/compat/mkdir.c b/compat/mkdir.c
new file mode 100644
index 0000000..9e253fb
--- /dev/null
+++ b/compat/mkdir.c
@@ -0,0 +1,24 @@
+#include "../git-compat-util.h"
+#undef mkdir
+
+/* for platforms that can't deal with a trailing '/' */
+int compat_mkdir_wo_trailing_slash(const char *dir, mode_t mode)
+{
+ int retval;
+ char *tmp_dir = NULL;
+ size_t len = strlen(dir);
+
+ if (len && dir[len-1] == '/') {
+ if ((tmp_dir = strdup(dir)) == NULL)
+ return -1;
+ tmp_dir[len-1] = '\0';
+ }
+ else
+ tmp_dir = (char *)dir;
+
+ retval = mkdir(tmp_dir, mode);
+ if (tmp_dir != dir)
+ free(tmp_dir);
+
+ return retval;
+}
diff --git a/compat/win32/poll.c b/compat/poll/poll.c
index 403eaa7..7d226ec 100644
--- a/compat/win32/poll.c
+++ b/compat/poll/poll.c
@@ -24,7 +24,9 @@
# pragma GCC diagnostic ignored "-Wtype-limits"
#endif
-#include <malloc.h>
+#if defined(WIN32)
+# include <malloc.h>
+#endif
#include <sys/types.h>
@@ -48,7 +50,9 @@
#else
# include <sys/time.h>
# include <sys/socket.h>
-# include <sys/select.h>
+# ifndef NO_SYS_SELECT_H
+# include <sys/select.h>
+# endif
# include <unistd.h>
#endif
@@ -302,6 +306,10 @@ compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
|| socket_errno == ECONNABORTED || socket_errno == ENETRESET)
happened |= POLLHUP;
+ /* some systems can't use recv() on non-socket, including HP NonStop */
+ else if (/* (r == -1) && */ socket_errno == ENOTSOCK)
+ happened |= (POLLIN | POLLRDNORM) & sought;
+
else
happened |= POLLERR;
}
@@ -349,7 +357,7 @@ poll (struct pollfd *pfd, nfds_t nfd, int timeout)
/* EFAULT is not necessary to implement, but let's do it in the
simplest case. */
- if (!pfd)
+ if (!pfd && nfd)
{
errno = EFAULT;
return -1;
diff --git a/compat/win32/poll.h b/compat/poll/poll.h
index b7aa59d..b7aa59d 100644
--- a/compat/win32/poll.h
+++ b/compat/poll/poll.h
diff --git a/compat/precompose_utf8.c b/compat/precompose_utf8.c
index d40d1b3..8cf5955 100644
--- a/compat/precompose_utf8.c
+++ b/compat/precompose_utf8.c
@@ -1,8 +1,7 @@
/*
* Converts filenames from decomposed unicode into precomposed unicode.
* Used on MacOS X.
-*/
-
+ */
#define PRECOMPOSE_UNICODE_C
@@ -11,25 +10,23 @@
#include "precompose_utf8.h"
typedef char *iconv_ibp;
-const static char *repo_encoding = "UTF-8";
-const static char *path_encoding = "UTF-8-MAC";
-
+static const char *repo_encoding = "UTF-8";
+static const char *path_encoding = "UTF-8-MAC";
-static size_t has_utf8(const char *s, size_t maxlen, size_t *strlen_c)
+static size_t has_non_ascii(const char *s, size_t maxlen, size_t *strlen_c)
{
- const uint8_t *utf8p = (const uint8_t*) s;
+ const uint8_t *ptr = (const uint8_t *)s;
size_t strlen_chars = 0;
size_t ret = 0;
- if ((!utf8p) || (!*utf8p)) {
+ if (!ptr || !*ptr)
return 0;
- }
- while((*utf8p) && maxlen) {
- if (*utf8p & 0x80)
+ while (*ptr && maxlen) {
+ if (*ptr & 0x80)
ret++;
strlen_chars++;
- utf8p++;
+ ptr++;
maxlen--;
}
if (strlen_c)
@@ -41,26 +38,24 @@ static size_t has_utf8(const char *s, size_t maxlen, size_t *strlen_c)
void probe_utf8_pathname_composition(char *path, int len)
{
- const static char *auml_nfc = "\xc3\xa4";
- const static char *auml_nfd = "\x61\xcc\x88";
+ static const char *auml_nfc = "\xc3\xa4";
+ static const char *auml_nfd = "\x61\xcc\x88";
int output_fd;
if (precomposed_unicode != -1)
return; /* We found it defined in the global config, respect it */
- path[len] = 0;
strcpy(path + len, auml_nfc);
output_fd = open(path, O_CREAT|O_EXCL|O_RDWR, 0600);
- if (output_fd >=0) {
+ if (output_fd >= 0) {
close(output_fd);
- path[len] = 0;
strcpy(path + len, auml_nfd);
/* Indicate to the user, that we can configure it to true */
- if (0 == access(path, R_OK))
+ if (!access(path, R_OK))
git_config_set("core.precomposeunicode", "false");
- /* To be backward compatible, set precomposed_unicode to 0 */
+ /* To be backward compatible, set precomposed_unicode to 0 */
precomposed_unicode = 0;
- path[len] = 0;
strcpy(path + len, auml_nfc);
- unlink(path);
+ if (unlink(path))
+ die_errno(_("failed to unlink '%s'"), path);
}
}
@@ -82,7 +77,7 @@ void precompose_argv(int argc, const char **argv)
while (i < argc) {
size_t namelen;
oldarg = argv[i];
- if (has_utf8(oldarg, (size_t)-1, &namelen)) {
+ if (has_non_ascii(oldarg, (size_t)-1, &namelen)) {
newarg = reencode_string_iconv(oldarg, namelen, ic_precompose);
if (newarg)
argv[i] = newarg;
@@ -135,7 +130,7 @@ struct dirent_prec_psx *precompose_utf8_readdir(PREC_DIR *prec_dir)
prec_dir->dirent_nfc->d_ino = res->d_ino;
prec_dir->dirent_nfc->d_type = res->d_type;
- if ((precomposed_unicode == 1) && has_utf8(res->d_name, (size_t)-1, NULL)) {
+ if ((precomposed_unicode == 1) && has_non_ascii(res->d_name, (size_t)-1, NULL)) {
if (prec_dir->ic_precompose == (iconv_t)-1) {
die("iconv_open(%s,%s) failed, but needed:\n"
" precomposed unicode is not supported.\n"
@@ -160,8 +155,7 @@ struct dirent_prec_psx *precompose_utf8_readdir(PREC_DIR *prec_dir)
namelenz = 0; /* trigger strlcpy */
}
}
- }
- else
+ } else
namelenz = 0;
if (!namelenz)
diff --git a/config.c b/config.c
index 2b706ea..08e47e2 100644
--- a/config.c
+++ b/config.c
@@ -60,7 +60,7 @@ static int handle_path_include(const char *path, struct config_include_data *inc
path = buf.buf;
}
- if (!access(path, R_OK)) {
+ if (!access_or_warn(path, R_OK)) {
if (++inc->depth > MAX_INCLUDE_DEPTH)
die(include_depth_advice, MAX_INCLUDE_DEPTH, path,
cf && cf->name ? cf->name : "the command line");
@@ -939,23 +939,23 @@ int git_config_early(config_fn_t fn, void *data, const char *repo_config)
home_config_paths(&user_config, &xdg_config, "config");
- if (git_config_system() && !access(git_etc_gitconfig(), R_OK)) {
+ if (git_config_system() && !access_or_warn(git_etc_gitconfig(), R_OK)) {
ret += git_config_from_file(fn, git_etc_gitconfig(),
data);
found += 1;
}
- if (xdg_config && !access(xdg_config, R_OK)) {
+ if (xdg_config && !access_or_warn(xdg_config, R_OK)) {
ret += git_config_from_file(fn, xdg_config, data);
found += 1;
}
- if (user_config && !access(user_config, R_OK)) {
+ if (user_config && !access_or_warn(user_config, R_OK)) {
ret += git_config_from_file(fn, user_config, data);
found += 1;
}
- if (repo_config && !access(repo_config, R_OK)) {
+ if (repo_config && !access_or_warn(repo_config, R_OK)) {
ret += git_config_from_file(fn, repo_config, data);
found += 1;
}
diff --git a/config.mak.in b/config.mak.in
index 802d342..69d4838 100644
--- a/config.mak.in
+++ b/config.mak.in
@@ -5,12 +5,10 @@ CC = @CC@
CFLAGS = @CFLAGS@
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
-CC_LD_DYNPATH = @CC_LD_DYNPATH@
AR = @AR@
TAR = @TAR@
DIFF = @DIFF@
#INSTALL = @INSTALL@ # needs install-sh or install.sh in sources
-TCLTK_PATH = @TCLTK_PATH@
prefix = @prefix@
exec_prefix = @exec_prefix@
@@ -27,50 +25,3 @@ VPATH = @srcdir@
export exec_prefix mandir
export srcdir VPATH
-
-NEEDS_SSL_WITH_CRYPTO=@NEEDS_SSL_WITH_CRYPTO@
-NO_OPENSSL=@NO_OPENSSL@
-NO_CURL=@NO_CURL@
-NO_EXPAT=@NO_EXPAT@
-NO_LIBGEN_H=@NO_LIBGEN_H@
-HAVE_PATHS_H=@HAVE_PATHS_H@
-HAVE_LIBCHARSET_H=@HAVE_LIBCHARSET_H@
-NO_GETTEXT=@NO_GETTEXT@
-LIBC_CONTAINS_LIBINTL=@LIBC_CONTAINS_LIBINTL@
-NEEDS_LIBICONV=@NEEDS_LIBICONV@
-NEEDS_SOCKET=@NEEDS_SOCKET@
-NEEDS_RESOLV=@NEEDS_RESOLV@
-NEEDS_LIBGEN=@NEEDS_LIBGEN@
-NO_SYS_SELECT_H=@NO_SYS_SELECT_H@
-NO_D_INO_IN_DIRENT=@NO_D_INO_IN_DIRENT@
-NO_D_TYPE_IN_DIRENT=@NO_D_TYPE_IN_DIRENT@
-NO_SOCKADDR_STORAGE=@NO_SOCKADDR_STORAGE@
-NO_IPV6=@NO_IPV6@
-NO_HSTRERROR=@NO_HSTRERROR@
-NO_STRCASESTR=@NO_STRCASESTR@
-NO_STRTOK_R=@NO_STRTOK_R@
-NO_FNMATCH=@NO_FNMATCH@
-NO_FNMATCH_CASEFOLD=@NO_FNMATCH_CASEFOLD@
-NO_MEMMEM=@NO_MEMMEM@
-NO_STRLCPY=@NO_STRLCPY@
-NO_UINTMAX_T=@NO_UINTMAX_T@
-NO_STRTOUMAX=@NO_STRTOUMAX@
-NO_SETENV=@NO_SETENV@
-NO_UNSETENV=@NO_UNSETENV@
-NO_MKDTEMP=@NO_MKDTEMP@
-NO_MKSTEMPS=@NO_MKSTEMPS@
-NO_INET_NTOP=@NO_INET_NTOP@
-NO_INET_PTON=@NO_INET_PTON@
-NO_ICONV=@NO_ICONV@
-OLD_ICONV=@OLD_ICONV@
-NO_REGEX=@NO_REGEX@
-USE_LIBPCRE=@USE_LIBPCRE@
-NO_DEFLATE_BOUND=@NO_DEFLATE_BOUND@
-INLINE=@INLINE@
-SOCKLEN_T=@SOCKLEN_T@
-FREAD_READS_DIRECTORIES=@FREAD_READS_DIRECTORIES@
-SNPRINTF_RETURNS_BOGUS=@SNPRINTF_RETURNS_BOGUS@
-NO_PTHREADS=@NO_PTHREADS@
-PTHREAD_CFLAGS=@PTHREAD_CFLAGS@
-PTHREAD_LIBS=@PTHREAD_LIBS@
-CHARSET_LIB=@CHARSET_LIB@
diff --git a/configure.ac b/configure.ac
index df7e376..c85888c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,8 +7,9 @@
# ------------------------
# Cause the line "VAR=VAL" to be eventually appended to ${config_file}.
AC_DEFUN([GIT_CONF_SUBST],
- [AC_REQUIRE([GIT_CONF_SUBST_INIT])
- config_appended_defs="$config_appended_defs${newline}$1=$2"])
+[AC_REQUIRE([GIT_CONF_SUBST_INIT])
+config_appended_defs="$config_appended_defs${newline}dnl
+$1=m4_if([$#],[1],[${$1}],[$2])"])
# GIT_CONF_SUBST_INIT
# -------------------
@@ -179,7 +180,7 @@ AC_ARG_WITH([lib],
else
lib=$withval
AC_MSG_NOTICE([Setting lib to '$lib'])
- GIT_CONF_SUBST([lib], [$withval])
+ GIT_CONF_SUBST([lib])
fi])
if test -z "$lib"; then
@@ -215,7 +216,7 @@ AC_ARG_ENABLE([jsmin],
[
JSMIN=$enableval;
AC_MSG_NOTICE([Setting JSMIN to '$JSMIN' to enable JavaScript minifying])
- GIT_CONF_SUBST([JSMIN], [$enableval])
+ GIT_CONF_SUBST([JSMIN])
])
# Define option to enable CSS minification
@@ -225,7 +226,7 @@ AC_ARG_ENABLE([cssmin],
[
CSSMIN=$enableval;
AC_MSG_NOTICE([Setting CSSMIN to '$CSSMIN' to enable CSS minifying])
- GIT_CONF_SUBST([CSSMIN], [$enableval])
+ GIT_CONF_SUBST([CSSMIN])
])
## Site configuration (override autodetection)
@@ -265,8 +266,10 @@ AS_HELP_STRING([], [ARG can be also prefix for libpcre library and hea
else
USE_LIBPCRE=YesPlease
LIBPCREDIR=$withval
- AC_MSG_NOTICE([Setting LIBPCREDIR to $withval])
- GIT_CONF_SUBST([LIBPCREDIR], [$withval])
+ AC_MSG_NOTICE([Setting LIBPCREDIR to $LIBPCREDIR])
+ dnl USE_LIBPCRE can still be modified below, so don't substitute
+ dnl it yet.
+ GIT_CONF_SUBST([LIBPCREDIR])
fi)
#
# Define NO_CURL if you do not have curl installed. git-http-pull and
@@ -386,9 +389,10 @@ AC_MSG_NOTICE([CHECKS for programs])
AC_PROG_CC([cc gcc])
AC_C_INLINE
case $ac_cv_c_inline in
- inline | yes | no) ;;
- *) AC_SUBST([INLINE], [$ac_cv_c_inline]) ;;
+ inline | yes | no) INLINE='';;
+ *) INLINE=$ac_cv_c_inline ;;
esac
+GIT_CONF_SUBST([INLINE])
# which switch to pass runtime path to dynamic libraries to the linker
AC_CACHE_CHECK([if linker supports -R], git_cv_ld_dashr, [
@@ -398,7 +402,7 @@ AC_CACHE_CHECK([if linker supports -R], git_cv_ld_dashr, [
LDFLAGS="${SAVE_LDFLAGS}"
])
if test "$git_cv_ld_dashr" = "yes"; then
- AC_SUBST(CC_LD_DYNPATH, [-R])
+ CC_LD_DYNPATH=-R
else
AC_CACHE_CHECK([if linker supports -Wl,-rpath,], git_cv_ld_wl_rpath, [
SAVE_LDFLAGS="${LDFLAGS}"
@@ -407,7 +411,7 @@ else
LDFLAGS="${SAVE_LDFLAGS}"
])
if test "$git_cv_ld_wl_rpath" = "yes"; then
- AC_SUBST(CC_LD_DYNPATH, [-Wl,-rpath,])
+ CC_LD_DYNPATH=-Wl,-rpath,
else
AC_CACHE_CHECK([if linker supports -rpath], git_cv_ld_rpath, [
SAVE_LDFLAGS="${LDFLAGS}"
@@ -416,32 +420,35 @@ else
LDFLAGS="${SAVE_LDFLAGS}"
])
if test "$git_cv_ld_rpath" = "yes"; then
- AC_SUBST(CC_LD_DYNPATH, [-rpath])
+ CC_LD_DYNPATH=-rpath
else
+ CC_LD_DYNPATH=
AC_MSG_WARN([linker does not support runtime path to dynamic libraries])
fi
fi
fi
+GIT_CONF_SUBST([CC_LD_DYNPATH])
#AC_PROG_INSTALL # needs install-sh or install.sh in sources
AC_CHECK_TOOLS(AR, [gar ar], :)
AC_CHECK_PROGS(TAR, [gtar tar])
AC_CHECK_PROGS(DIFF, [gnudiff gdiff diff])
# TCLTK_PATH will be set to some value if we want Tcl/Tk
# or will be empty otherwise.
-if test -z "$NO_TCLTK"; then
+if test -n "$NO_TCLTK"; then
+ TCLTK_PATH=
+else
if test "$with_tcltk" = ""; then
# No Tcl/Tk switches given. Do not check for Tcl/Tk, use bare 'wish'.
TCLTK_PATH=wish
- AC_SUBST(TCLTK_PATH)
elif test "$with_tcltk" = "yes"; then
# Tcl/Tk check requested.
AC_CHECK_PROGS(TCLTK_PATH, [wish], )
else
AC_MSG_RESULT([Using Tcl/Tk interpreter $with_tcltk])
TCLTK_PATH="$with_tcltk"
- AC_SUBST(TCLTK_PATH)
fi
fi
+GIT_CONF_SUBST([TCLTK_PATH])
AC_CHECK_PROGS(ASCIIDOC, [asciidoc])
if test -n "$ASCIIDOC"; then
AC_MSG_CHECKING([for asciidoc version])
@@ -468,13 +475,13 @@ GIT_STASH_FLAGS($OPENSSLDIR)
AC_CHECK_LIB([crypto], [SHA1_Init],
[NEEDS_SSL_WITH_CRYPTO=],
[AC_CHECK_LIB([ssl], [SHA1_Init],
- [NEEDS_SSL_WITH_CRYPTO=YesPlease],
- [NEEDS_SSL_WITH_CRYPTO= NO_OPENSSL=YesPlease])])
+ [NEEDS_SSL_WITH_CRYPTO=YesPlease NO_OPENSSL=],
+ [NEEDS_SSL_WITH_CRYPTO= NO_OPENSSL=YesPlease])])
GIT_UNSTASH_FLAGS($OPENSSLDIR)
-AC_SUBST(NEEDS_SSL_WITH_CRYPTO)
-AC_SUBST(NO_OPENSSL)
+GIT_CONF_SUBST([NEEDS_SSL_WITH_CRYPTO])
+GIT_CONF_SUBST([NO_OPENSSL])
#
# Define USE_LIBPCRE if you have and want to use libpcre. git-grep will be
@@ -491,7 +498,7 @@ AC_CHECK_LIB([pcre], [pcre_version],
GIT_UNSTASH_FLAGS($LIBPCREDIR)
-AC_SUBST(USE_LIBPCRE)
+GIT_CONF_SUBST([USE_LIBPCRE])
fi
@@ -508,7 +515,7 @@ AC_CHECK_LIB([curl], [curl_global_init],
GIT_UNSTASH_FLAGS($CURLDIR)
-AC_SUBST(NO_CURL)
+GIT_CONF_SUBST([NO_CURL])
#
# Define NO_EXPAT if you do not have expat installed. git-http-push is
@@ -522,7 +529,7 @@ AC_CHECK_LIB([expat], [XML_ParserCreate],
GIT_UNSTASH_FLAGS($EXPATDIR)
-AC_SUBST(NO_EXPAT)
+GIT_CONF_SUBST([NO_EXPAT])
#
# Define NEEDS_LIBICONV if linking with libc is not enough (Darwin and
@@ -568,8 +575,8 @@ LIBS="$old_LIBS"
GIT_UNSTASH_FLAGS($ICONVDIR)
-AC_SUBST(NEEDS_LIBICONV)
-AC_SUBST(NO_ICONV)
+GIT_CONF_SUBST([NEEDS_LIBICONV])
+GIT_CONF_SUBST([NO_ICONV])
if test -n "$NO_ICONV"; then
NEEDS_LIBICONV=
@@ -596,7 +603,7 @@ LIBS="$old_LIBS"
GIT_UNSTASH_FLAGS($ZLIB_PATH)
-AC_SUBST(NO_DEFLATE_BOUND)
+GIT_CONF_SUBST([NO_DEFLATE_BOUND])
#
# Define NEEDS_SOCKET if linking with libc is not enough (SunOS,
@@ -604,7 +611,7 @@ AC_SUBST(NO_DEFLATE_BOUND)
AC_CHECK_LIB([c], [socket],
[NEEDS_SOCKET=],
[NEEDS_SOCKET=YesPlease])
-AC_SUBST(NEEDS_SOCKET)
+GIT_CONF_SUBST([NEEDS_SOCKET])
test -n "$NEEDS_SOCKET" && LIBS="$LIBS -lsocket"
#
@@ -612,40 +619,43 @@ test -n "$NEEDS_SOCKET" && LIBS="$LIBS -lsocket"
# libresolv provides some of the functions we would normally get
# from libc.
NEEDS_RESOLV=
-AC_SUBST(NEEDS_RESOLV)
#
# Define NO_INET_NTOP if linking with -lresolv is not enough.
# Solaris 2.7 in particular hos inet_ntop in -lresolv.
NO_INET_NTOP=
-AC_SUBST(NO_INET_NTOP)
AC_CHECK_FUNC([inet_ntop],
- [],
+ [],
[AC_CHECK_LIB([resolv], [inet_ntop],
- [NEEDS_RESOLV=YesPlease],
+ [NEEDS_RESOLV=YesPlease],
[NO_INET_NTOP=YesPlease])
])
+GIT_CONF_SUBST([NO_INET_NTOP])
#
# Define NO_INET_PTON if linking with -lresolv is not enough.
# Solaris 2.7 in particular hos inet_pton in -lresolv.
NO_INET_PTON=
-AC_SUBST(NO_INET_PTON)
AC_CHECK_FUNC([inet_pton],
- [],
+ [],
[AC_CHECK_LIB([resolv], [inet_pton],
- [NEEDS_RESOLV=YesPlease],
+ [NEEDS_RESOLV=YesPlease],
[NO_INET_PTON=YesPlease])
])
+GIT_CONF_SUBST([NO_INET_PTON])
#
# Define NO_HSTRERROR if linking with -lresolv is not enough.
# Solaris 2.6 in particular has no hstrerror, even in -lresolv.
NO_HSTRERROR=
AC_CHECK_FUNC([hstrerror],
- [],
+ [],
[AC_CHECK_LIB([resolv], [hstrerror],
- [NEEDS_RESOLV=YesPlease],
+ [NEEDS_RESOLV=YesPlease],
[NO_HSTRERROR=YesPlease])
])
-AC_SUBST(NO_HSTRERROR)
+GIT_CONF_SUBST([NO_HSTRERROR])
+
+dnl This must go after all the possible places for its initialization,
+dnl in the AC_CHECK_FUNC invocations above.
+GIT_CONF_SUBST([NEEDS_RESOLV])
#
# If any of the above tests determined that -lresolv is needed at
# build-time, also set it here for remaining configure-time checks.
@@ -654,13 +664,13 @@ test -n "$NEEDS_RESOLV" && LIBS="$LIBS -lresolv"
AC_CHECK_LIB([c], [basename],
[NEEDS_LIBGEN=],
[NEEDS_LIBGEN=YesPlease])
-AC_SUBST(NEEDS_LIBGEN)
+GIT_CONF_SUBST([NEEDS_LIBGEN])
test -n "$NEEDS_LIBGEN" && LIBS="$LIBS -lgen"
AC_CHECK_LIB([c], [gettext],
[LIBC_CONTAINS_LIBINTL=YesPlease],
[LIBC_CONTAINS_LIBINTL=])
-AC_SUBST(LIBC_CONTAINS_LIBINTL)
+GIT_CONF_SUBST([LIBC_CONTAINS_LIBINTL])
#
# Define NO_GETTEXT if you don't want Git output to be translated.
@@ -668,7 +678,7 @@ AC_SUBST(LIBC_CONTAINS_LIBINTL)
AC_CHECK_HEADER([libintl.h],
[NO_GETTEXT=],
[NO_GETTEXT=YesPlease])
-AC_SUBST(NO_GETTEXT)
+GIT_CONF_SUBST([NO_GETTEXT])
if test -z "$NO_GETTEXT"; then
test -n "$LIBC_CONTAINS_LIBINTL" || LIBS="$LIBS -lintl"
@@ -681,19 +691,19 @@ AC_MSG_NOTICE([CHECKS for header files])
AC_CHECK_HEADER([sys/select.h],
[NO_SYS_SELECT_H=],
[NO_SYS_SELECT_H=UnfortunatelyYes])
-AC_SUBST(NO_SYS_SELECT_H)
+GIT_CONF_SUBST([NO_SYS_SELECT_H])
#
# Define NO_SYS_POLL_H if you don't have sys/poll.h
AC_CHECK_HEADER([sys/poll.h],
[NO_SYS_POLL_H=],
[NO_SYS_POLL_H=UnfortunatelyYes])
-AC_SUBST(NO_SYS_POLL_H)
+GIT_CONF_SUBST([NO_SYS_POLL_H])
#
# Define NO_INTTYPES_H if you don't have inttypes.h
AC_CHECK_HEADER([inttypes.h],
[NO_INTTYPES_H=],
[NO_INTTYPES_H=UnfortunatelyYes])
-AC_SUBST(NO_INTTYPES_H)
+GIT_CONF_SUBST([NO_INTTYPES_H])
#
# Define OLD_ICONV if your library has an old iconv(), where the second
# (input buffer pointer) parameter is declared with type (const char **).
@@ -716,23 +726,24 @@ AC_COMPILE_IFELSE([OLDICONVTEST_SRC],
GIT_UNSTASH_FLAGS($ICONVDIR)
-AC_SUBST(OLD_ICONV)
+GIT_CONF_SUBST([OLD_ICONV])
## Checks for typedefs, structures, and compiler characteristics.
AC_MSG_NOTICE([CHECKS for typedefs, structures, and compiler characteristics])
#
TYPE_SOCKLEN_T
case $ac_cv_type_socklen_t in
- yes) ;;
- *) AC_SUBST([SOCKLEN_T], [$git_cv_socklen_t_equiv]) ;;
+ yes) SOCKLEN_T='';;
+ *) SOCKLEN_T=$git_cv_socklen_t_equiv;;
esac
+GIT_CONF_SUBST([SOCKLEN_T])
# Define NO_D_INO_IN_DIRENT if you don't have d_ino in your struct dirent.
AC_CHECK_MEMBER(struct dirent.d_ino,
[NO_D_INO_IN_DIRENT=],
[NO_D_INO_IN_DIRENT=YesPlease],
[#include <dirent.h>])
-AC_SUBST(NO_D_INO_IN_DIRENT)
+GIT_CONF_SUBST([NO_D_INO_IN_DIRENT])
#
# Define NO_D_TYPE_IN_DIRENT if your platform defines DT_UNKNOWN but lacks
# d_type in struct dirent (latest Cygwin -- will be fixed soonish).
@@ -740,7 +751,7 @@ AC_CHECK_MEMBER(struct dirent.d_type,
[NO_D_TYPE_IN_DIRENT=],
[NO_D_TYPE_IN_DIRENT=YesPlease],
[#include <dirent.h>])
-AC_SUBST(NO_D_TYPE_IN_DIRENT)
+GIT_CONF_SUBST([NO_D_TYPE_IN_DIRENT])
#
# Define NO_SOCKADDR_STORAGE if your platform does not have struct
# sockaddr_storage.
@@ -750,7 +761,7 @@ AC_CHECK_TYPE(struct sockaddr_storage,
#include <sys/types.h>
#include <sys/socket.h>
])
-AC_SUBST(NO_SOCKADDR_STORAGE)
+GIT_CONF_SUBST([NO_SOCKADDR_STORAGE])
#
# Define NO_IPV6 if you lack IPv6 support and getaddrinfo().
AC_CHECK_TYPE([struct addrinfo],[
@@ -762,7 +773,7 @@ AC_CHECK_TYPE([struct addrinfo],[
#include <sys/socket.h>
#include <netdb.h>
])
-AC_SUBST(NO_IPV6)
+GIT_CONF_SUBST([NO_IPV6])
#
# Define NO_REGEX if you have no or inferior regex support in your C library.
AC_CACHE_CHECK([whether the platform regex can handle null bytes],
@@ -783,7 +794,7 @@ if test $ac_cv_c_excellent_regex = yes; then
else
NO_REGEX=YesPlease
fi
-AC_SUBST(NO_REGEX)
+GIT_CONF_SUBST([NO_REGEX])
#
# Define FREAD_READS_DIRECTORIES if your are on a system which succeeds
# when attempting to read from an fopen'ed directory.
@@ -803,7 +814,7 @@ if test $ac_cv_fread_reads_directories = yes; then
else
FREAD_READS_DIRECTORIES=
fi
-AC_SUBST(FREAD_READS_DIRECTORIES)
+GIT_CONF_SUBST([FREAD_READS_DIRECTORIES])
#
# Define SNPRINTF_RETURNS_BOGUS if your are on a system which snprintf()
# or vsnprintf() return -1 instead of number of characters which would
@@ -837,7 +848,7 @@ if test $ac_cv_snprintf_returns_bogus = yes; then
else
SNPRINTF_RETURNS_BOGUS=
fi
-AC_SUBST(SNPRINTF_RETURNS_BOGUS)
+GIT_CONF_SUBST([SNPRINTF_RETURNS_BOGUS])
## Checks for library functions.
@@ -848,47 +859,45 @@ AC_MSG_NOTICE([CHECKS for library functions])
AC_CHECK_HEADER([libgen.h],
[NO_LIBGEN_H=],
[NO_LIBGEN_H=YesPlease])
-AC_SUBST(NO_LIBGEN_H)
+GIT_CONF_SUBST([NO_LIBGEN_H])
#
# Define HAVE_PATHS_H if you have paths.h.
AC_CHECK_HEADER([paths.h],
[HAVE_PATHS_H=YesPlease],
[HAVE_PATHS_H=])
-AC_SUBST(HAVE_PATHS_H)
+GIT_CONF_SUBST([HAVE_PATHS_H])
#
# Define HAVE_LIBCHARSET_H if have libcharset.h
AC_CHECK_HEADER([libcharset.h],
[HAVE_LIBCHARSET_H=YesPlease],
[HAVE_LIBCHARSET_H=])
-AC_SUBST(HAVE_LIBCHARSET_H)
+GIT_CONF_SUBST([HAVE_LIBCHARSET_H])
# Define CHARSET_LIB if libiconv does not export the locale_charset symbol
# and libcharset does
CHARSET_LIB=
AC_CHECK_LIB([iconv], [locale_charset],
[],
[AC_CHECK_LIB([charset], [locale_charset],
- [CHARSET_LIB=-lcharset])
- ]
-)
-AC_SUBST(CHARSET_LIB)
+ [CHARSET_LIB=-lcharset])])
+GIT_CONF_SUBST([CHARSET_LIB])
#
# Define NO_STRCASESTR if you don't have strcasestr.
GIT_CHECK_FUNC(strcasestr,
[NO_STRCASESTR=],
[NO_STRCASESTR=YesPlease])
-AC_SUBST(NO_STRCASESTR)
+GIT_CONF_SUBST([NO_STRCASESTR])
#
# Define NO_STRTOK_R if you don't have strtok_r
GIT_CHECK_FUNC(strtok_r,
[NO_STRTOK_R=],
[NO_STRTOK_R=YesPlease])
-AC_SUBST(NO_STRTOK_R)
+GIT_CONF_SUBST([NO_STRTOK_R])
#
# Define NO_FNMATCH if you don't have fnmatch
GIT_CHECK_FUNC(fnmatch,
[NO_FNMATCH=],
[NO_FNMATCH=YesPlease])
-AC_SUBST(NO_FNMATCH)
+GIT_CONF_SUBST([NO_FNMATCH])
#
# Define NO_FNMATCH_CASEFOLD if your fnmatch function doesn't have the
# FNM_CASEFOLD GNU extension.
@@ -910,19 +919,19 @@ if test $ac_cv_c_excellent_fnmatch = yes; then
else
NO_FNMATCH_CASEFOLD=YesPlease
fi
-AC_SUBST(NO_FNMATCH_CASEFOLD)
+GIT_CONF_SUBST([NO_FNMATCH_CASEFOLD])
#
# Define NO_MEMMEM if you don't have memmem.
GIT_CHECK_FUNC(memmem,
[NO_MEMMEM=],
[NO_MEMMEM=YesPlease])
-AC_SUBST(NO_MEMMEM)
+GIT_CONF_SUBST([NO_MEMMEM])
#
# Define NO_STRLCPY if you don't have strlcpy.
GIT_CHECK_FUNC(strlcpy,
[NO_STRLCPY=],
[NO_STRLCPY=YesPlease])
-AC_SUBST(NO_STRLCPY)
+GIT_CONF_SUBST([NO_STRLCPY])
#
# Define NO_UINTMAX_T if your platform does not have uintmax_t
AC_CHECK_TYPE(uintmax_t,
@@ -930,43 +939,43 @@ AC_CHECK_TYPE(uintmax_t,
[NO_UINTMAX_T=YesPlease],[
#include <inttypes.h>
])
-AC_SUBST(NO_UINTMAX_T)
+GIT_CONF_SUBST([NO_UINTMAX_T])
#
# Define NO_STRTOUMAX if you don't have strtoumax in the C library.
GIT_CHECK_FUNC(strtoumax,
[NO_STRTOUMAX=],
[NO_STRTOUMAX=YesPlease])
-AC_SUBST(NO_STRTOUMAX)
+GIT_CONF_SUBST([NO_STRTOUMAX])
#
# Define NO_SETENV if you don't have setenv in the C library.
GIT_CHECK_FUNC(setenv,
[NO_SETENV=],
[NO_SETENV=YesPlease])
-AC_SUBST(NO_SETENV)
+GIT_CONF_SUBST([NO_SETENV])
#
# Define NO_UNSETENV if you don't have unsetenv in the C library.
GIT_CHECK_FUNC(unsetenv,
[NO_UNSETENV=],
[NO_UNSETENV=YesPlease])
-AC_SUBST(NO_UNSETENV)
+GIT_CONF_SUBST([NO_UNSETENV])
#
# Define NO_MKDTEMP if you don't have mkdtemp in the C library.
GIT_CHECK_FUNC(mkdtemp,
[NO_MKDTEMP=],
[NO_MKDTEMP=YesPlease])
-AC_SUBST(NO_MKDTEMP)
+GIT_CONF_SUBST([NO_MKDTEMP])
#
# Define NO_MKSTEMPS if you don't have mkstemps in the C library.
GIT_CHECK_FUNC(mkstemps,
[NO_MKSTEMPS=],
[NO_MKSTEMPS=YesPlease])
-AC_SUBST(NO_MKSTEMPS)
+GIT_CONF_SUBST([NO_MKSTEMPS])
#
# Define NO_INITGROUPS if you don't have initgroups in the C library.
GIT_CHECK_FUNC(initgroups,
[NO_INITGROUPS=],
[NO_INITGROUPS=YesPlease])
-AC_SUBST(NO_INITGROUPS)
+GIT_CONF_SUBST([NO_INITGROUPS])
#
#
# Define NO_MMAP if you want to avoid mmap.
@@ -1048,9 +1057,9 @@ fi
CFLAGS="$old_CFLAGS"
-AC_SUBST(PTHREAD_CFLAGS)
-AC_SUBST(PTHREAD_LIBS)
-AC_SUBST(NO_PTHREADS)
+GIT_CONF_SUBST([PTHREAD_CFLAGS])
+GIT_CONF_SUBST([PTHREAD_LIBS])
+GIT_CONF_SUBST([NO_PTHREADS])
## Output files
AC_CONFIG_FILES(["${config_file}":"${config_in}"])
diff --git a/connect.c b/connect.c
index 55a85ad..49e56ba 100644
--- a/connect.c
+++ b/connect.c
@@ -115,12 +115,7 @@ struct ref **get_remote_heads(int in, struct ref **list,
return list;
}
-int server_supports(const char *feature)
-{
- return !!parse_feature_request(server_capabilities, feature);
-}
-
-const char *parse_feature_request(const char *feature_list, const char *feature)
+const char *parse_feature_value(const char *feature_list, const char *feature, int *lenp)
{
int len;
@@ -132,14 +127,46 @@ const char *parse_feature_request(const char *feature_list, const char *feature)
const char *found = strstr(feature_list, feature);
if (!found)
return NULL;
- if ((feature_list == found || isspace(found[-1])) &&
- (!found[len] || isspace(found[len]) || found[len] == '='))
- return found;
+ if (feature_list == found || isspace(found[-1])) {
+ const char *value = found + len;
+ /* feature with no value (e.g., "thin-pack") */
+ if (!*value || isspace(*value)) {
+ if (lenp)
+ *lenp = 0;
+ return value;
+ }
+ /* feature with a value (e.g., "agent=git/1.2.3") */
+ else if (*value == '=') {
+ value++;
+ if (lenp)
+ *lenp = strcspn(value, " \t\n");
+ return value;
+ }
+ /*
+ * otherwise we matched a substring of another feature;
+ * keep looking
+ */
+ }
feature_list = found + 1;
}
return NULL;
}
+int parse_feature_request(const char *feature_list, const char *feature)
+{
+ return !!parse_feature_value(feature_list, feature, NULL);
+}
+
+const char *server_feature_value(const char *feature, int *len)
+{
+ return parse_feature_value(server_capabilities, feature, len);
+}
+
+int server_supports(const char *feature)
+{
+ return !!server_feature_value(feature, NULL);
+}
+
enum protocol {
PROTO_LOCAL = 1,
PROTO_SSH,
diff --git a/contrib/ciabot/INSTALL b/contrib/ciabot/INSTALL
new file mode 100644
index 0000000..7222961
--- /dev/null
+++ b/contrib/ciabot/INSTALL
@@ -0,0 +1,54 @@
+= Installation instructions =
+
+Two scripts are included. The Python one (ciabot.py) is faster and
+more capable; the shell one (ciabot.sh) is a fallback in case Python
+gives your git hosting site indigestion. (I know of no such sites.)
+
+It is no longer necessary to modify the script in order to put it
+in place; in fact, this is now discouraged. It is entirely
+configurable with the following git config variables:
+
+ciabot.project = name of the project
+ciabot.repo = name of the project repo for gitweb/cgit purposes
+ciabot.xmlrpc = if true, ship notifications via XML-RPC
+ciabot.revformat = format in which the revision is shown
+
+The revformat variable may have the following values
+raw -> full hex ID of commit
+short -> first 12 chars of hex ID
+describe -> describe relative to last tag, falling back to short
+
+ciabot.project defaults to the directory name of the repository toplevel.
+ciabot.repo defaults to ciabot.project lowercased.
+ciabot.xmlrpc defaults to True
+ciabot.revformat defaults to 'describe'.
+
+This means that in the normal case you need not do any configuration at all,
+however setting ciabot.project will allow the hook to run slightly faster.
+
+Once you've set these variables, try your script with -n to see the
+notification message dumped to stdout and verify that it looks sane.
+
+To live-test these scripts, your project needs to have been registered with
+the CIA site. Here are the steps:
+
+1. Open an IRC window on irc://freenode/commits or your registered
+ project IRC channel.
+
+2. Run ciabot.py and/or ciabot.sh from any directory under git
+ control.
+
+You should see a notification on the channel for your most recent commit.
+
+After verifying correct function, install one of these scripts either
+in a post-commit hook or in an update hook.
+
+In post-commit, run it without arguments. It will query for
+current HEAD and the latest commit ID to get the information it
+needs.
+
+In update, call it with a refname followed by a list of commits:
+You want to reverse the order git rev-list emits because it lists
+from most recent to oldest.
+
+/path/to/ciabot.py ${refname} $(git rev-list ${oldhead}..${newhead} | tac)
diff --git a/contrib/ciabot/README b/contrib/ciabot/README
index 3b916ac..2dfe1f9 100644
--- a/contrib/ciabot/README
+++ b/contrib/ciabot/README
@@ -8,5 +8,4 @@ You probably want the Python version; it's faster, more capable, and
better documented. The shell version is maintained only as a fallback
for use on hosting sites that don't permit Python hook scripts.
-You will find installation instructions for each script in its comment
-header.
+See the file INSTALL for installation instructions.
diff --git a/contrib/ciabot/ciabot.py b/contrib/ciabot/ciabot.py
index 9775dff..bd24395 100755
--- a/contrib/ciabot/ciabot.py
+++ b/contrib/ciabot/ciabot.py
@@ -10,44 +10,45 @@
# usage: ciabot.py [-V] [-n] [-p projectname] [refname [commits...]]
#
# This script is meant to be run either in a post-commit hook or in an
-# update hook. If there's nothing unusual about your hosting setup,
-# you can specify the project name with a -p option and avoid having
-# to modify this script. Try it with -n to see the notification mail
-# dumped to stdout and verify that it looks sane. With -V it dumps its
-# version and exits.
+# update hook. Try it with -n to see the notification mail dumped to
+# stdout and verify that it looks sane. With -V it dumps its version
+# and exits.
#
-# In post-commit, run it without arguments (other than possibly a -p
-# option). It will query for current HEAD and the latest commit ID to
-# get the information it needs.
+# In post-commit, run it without arguments. It will query for
+# current HEAD and the latest commit ID to get the information it
+# needs.
#
# In update, call it with a refname followed by a list of commits:
-# You want to reverse the order git rev-list emits becxause it lists
+# You want to reverse the order git rev-list emits because it lists
# from most recent to oldest.
#
# /path/to/ciabot.py ${refname} $(git rev-list ${oldhead}..${newhead} | tac)
#
-# Note: this script uses mail, not XML-RPC, in order to avoid stalling
-# until timeout when the CIA XML-RPC server is down.
+# Configuration variables affecting this script:
#
-
+# ciabot.project = name of the project
+# ciabot.repo = name of the project repo for gitweb/cgit purposes
+# ciabot.xmlrpc = if true (default), ship notifications via XML-RPC
+# ciabot.revformat = format in which the revision is shown
#
-# The project as known to CIA. You will either want to change this
-# or invoke the script with a -p option to set it.
+# ciabot.project defaults to the directory name of the repository toplevel.
+# ciabot.repo defaults to ciabot.project lowercased.
#
-project=None
-
+# This means that in the normal case you need not do any configuration at all,
+# but setting the project name will speed it up slightly.
#
-# You may not need to change these:
+# The revformat variable may have the following values
+# raw -> full hex ID of commit
+# short -> first 12 chars of hex ID
+# describe = -> describe relative to last tag, falling back to short
+# The default is 'describe'.
+#
+# Note: the CIA project now says only XML-RPC is reliable, so
+# we default to that.
#
-import os, sys, commands, socket, urllib
-
-# Name of the repository.
-# You can hardwire this to make the script faster.
-repo = os.path.basename(os.getcwd())
-# Fully-qualified domain name of this host.
-# You can hardwire this to make the script faster.
-host = socket.getfqdn()
+import os, sys, commands, socket, urllib
+from xml.sax.saxutils import escape
# Changeset URL prefix for your repo: when the commit ID is appended
# to this, it should point at a CGI that will display the commit
@@ -72,7 +73,7 @@ xml = '''\
<message>
<generator>
<name>CIA Python client for Git</name>
- <version>%(gitver)s</version>
+ <version>%(version)s</version>
<url>%(generator)s</url>
</generator>
<source>
@@ -98,19 +99,18 @@ xml = '''\
# No user-serviceable parts below this line:
#
-# Addresses for the e-mail. The from address is a dummy, since CIA
-# will never reply to this mail.
-fromaddr = "CIABOT-NOREPLY@" + host
-toaddr = "cia@cia.navi.cx"
+# Where to ship e-mail notifications.
+toaddr = "cia@cia.vc"
# Identify the generator script.
# Should only change when the script itself gets a new home and maintainer.
-generator="http://www.catb.org/~esr/ciabot.py"
+generator = "http://www.catb.org/~esr/ciabot.py"
+version = "3.6"
def do(command):
return commands.getstatusoutput(command)[1]
-def report(refname, merged):
+def report(refname, merged, xmlrpc=True):
"Generate a commit notification to be reported to CIA"
# Try to tinyfy a reference to a web view for this commit.
@@ -121,32 +121,27 @@ def report(refname, merged):
branch = os.path.basename(refname)
- # Compute a shortnane for the revision
- rev = do("git describe '"+ merged +"' 2>/dev/null") or merged[:12]
-
- # Extract the neta-information for the commit
- rawcommit = do("git cat-file commit " + merged)
+ # Compute a description for the revision
+ if revformat == 'raw':
+ rev = merged
+ elif revformat == 'short':
+ rev = ''
+ else: # revformat == 'describe'
+ rev = do("git describe %s 2>/dev/null" % merged)
+ if not rev:
+ rev = merged[:12]
+
+ # Extract the meta-information for the commit
files=do("git diff-tree -r --name-only '"+ merged +"' | sed -e '1d' -e 's-.*-<file>&</file>-'")
- inheader = True
- headers = {}
- logmsg = ""
- for line in rawcommit.split("\n"):
- if inheader:
- if line:
- fields = line.split()
- headers[fields[0]] = " ".join(fields[1:])
- else:
- inheader = False
- else:
- logmsg = line
- break
- (author, ts) = headers["author"].split(">")
+ metainfo = do("git log -1 '--pretty=format:%an <%ae>%n%at%n%s' " + merged)
+ (author, ts, logmsg) = metainfo.split("\n")
+ logmsg = escape(logmsg)
- # This discards the part of the authors addrsss after @.
- # Might be bnicece to ship the full email address, if not
+ # This discards the part of the author's address after @.
+ # Might be be nice to ship the full email address, if not
# for spammers' address harvesters - getting this wrong
# would make the freenode #commits channel into harvester heaven.
- author = author.replace("<", "").split("@")[0].split()[-1]
+ author = escape(author.replace("<", "").split("@")[0].split()[-1])
# This ignores the timezone. Not clear what to do with it...
ts = ts.strip().split()[0]
@@ -155,8 +150,7 @@ def report(refname, merged):
context.update(globals())
out = xml % context
-
- message = '''\
+ mail = '''\
Message-ID: <%(merged)s.%(author)s@%(project)s>
From: %(fromaddr)s
To: %(toaddr)s
@@ -165,34 +159,56 @@ Subject: DeliverXML
%(out)s''' % locals()
- return message
+ if xmlrpc:
+ return out
+ else:
+ return mail
if __name__ == "__main__":
import getopt
+ # Get all config variables
+ revformat = do("git config --get ciabot.revformat")
+ project = do("git config --get ciabot.project")
+ repo = do("git config --get ciabot.repo")
+ xmlrpc = do("git config --get ciabot.xmlrpc")
+ xmlrpc = not (xmlrpc and xmlrpc == "false")
+
+ host = socket.getfqdn()
+ fromaddr = "CIABOT-NOREPLY@" + host
+
try:
- (options, arguments) = getopt.getopt(sys.argv[1:], "np:V")
+ (options, arguments) = getopt.getopt(sys.argv[1:], "np:xV")
except getopt.GetoptError, msg:
print "ciabot.py: " + str(msg)
raise SystemExit, 1
- mailit = True
+ notify = True
for (switch, val) in options:
if switch == '-p':
project = val
elif switch == '-n':
- mailit = False
+ notify = False
+ elif switch == '-x':
+ xmlrpc = True
elif switch == '-V':
- print "ciabot.py: version 3.2"
+ print "ciabot.py: version", version
sys.exit(0)
- # Cough and die if user has not specified a project
+ # The project variable defaults to the name of the repository toplevel.
if not project:
- sys.stderr.write("ciabot.py: no project specified, bailing out.\n")
- sys.exit(1)
-
- # We'll need the git version number.
- gitver = do("git --version").split()[0]
+ here = os.getcwd()
+ while True:
+ if os.path.exists(os.path.join(here, ".git")):
+ project = os.path.basename(here)
+ break
+ elif here == '/':
+ sys.stderr.write("ciabot.py: no .git below root!\n")
+ sys.exit(1)
+ here = os.path.dirname(here)
+
+ if not repo:
+ repo = project.lower()
urlprefix = urlprefix % globals()
@@ -205,18 +221,29 @@ if __name__ == "__main__":
refname = arguments[0]
merges = arguments[1:]
- if mailit:
- import smtplib
- server = smtplib.SMTP('localhost')
+ if notify:
+ if xmlrpc:
+ import xmlrpclib
+ server = xmlrpclib.Server('http://cia.vc/RPC2');
+ else:
+ import smtplib
+ server = smtplib.SMTP('localhost')
for merged in merges:
- message = report(refname, merged)
- if mailit:
- server.sendmail(fromaddr, [toaddr], message)
- else:
+ message = report(refname, merged, xmlrpc)
+ if not notify:
print message
+ elif xmlrpc:
+ try:
+ # RPC server is flaky, this can fail due to timeout.
+ server.hub.deliver(message)
+ except socket.error, e:
+ sys.stderr.write("%s\n" % e)
+ else:
+ server.sendmail(fromaddr, [toaddr], message)
- if mailit:
- server.quit()
+ if notify:
+ if not xmlrpc:
+ server.quit()
#End
diff --git a/contrib/ciabot/ciabot.sh b/contrib/ciabot/ciabot.sh
index eb87bba..3fbbc53 100755
--- a/contrib/ciabot/ciabot.sh
+++ b/contrib/ciabot/ciabot.sh
@@ -3,6 +3,8 @@
# Copyright (c) 2006 Fernando J. Pereda <ferdy@gentoo.org>
# Copyright (c) 2008 Natanael Copa <natanael.copa@gmail.com>
# Copyright (c) 2010 Eric S. Raymond <esr@thyrsus.com>
+# Assistance and review by Petr Baudis, author of ciabot.pl,
+# is gratefully acknowledged.
#
# This is a version 3.x of ciabot.sh; use -V to find the exact
# version. Versions 1 and 2 were shipped in 2006 and 2008 and are not
@@ -11,6 +13,7 @@
# Note: This script should be considered obsolete.
# There is a faster, better-documented rewrite in Python: find it as ciabot.py
# Use this only if your hosting site forbids Python hooks.
+# It requires: git(1), hostname(1), cut(1), sendmail(1), and wget(1).
#
# Originally based on Git ciabot.pl by Petr Baudis.
# This script contains porcelain and porcelain byproducts.
@@ -18,15 +21,13 @@
# usage: ciabot.sh [-V] [-n] [-p projectname] [refname commit]
#
# This script is meant to be run either in a post-commit hook or in an
-# update hook. If there's nothing unusual about your hosting setup,
-# you can specify the project name with a -p option and avoid having
-# to modify this script. Try it with -n first to see the notification
-# mail dumped to stdout and verify that it looks sane. Use -V to dump
-# the version and exit.
+# update hook. Try it with -n to see the notification mail dumped to
+# stdout and verify that it looks sane. With -V it dumps its version
+# and exits.
#
-# In post-commit, run it without arguments (other than possibly a -p
-# option). It will query for current HEAD and the latest commit ID to
-# get the information it needs.
+# In post-commit, run it without arguments. It will query for
+# current HEAD and the latest commit ID to get the information it
+# needs.
#
# In update, you have to call it once per merged commit:
#
@@ -34,33 +35,76 @@
# oldhead=$2
# newhead=$3
# for merged in $(git rev-list ${oldhead}..${newhead} | tac) ; do
-# /path/to/ciabot.bash ${refname} ${merged}
+# /path/to/ciabot.sh ${refname} ${merged}
# done
#
-# The reason for the tac call ids that git rev-list emits commits from
+# The reason for the tac call is that git rev-list emits commits from
# most recent to least - better to ship notifactions from oldest to newest.
#
-# Note: this script uses mail, not XML-RPC, in order to avoid stalling
-# until timeout when the CIA XML-RPC server is down.
+# Configuration variables affecting this script:
#
-
+# ciabot.project = name of the project
+# ciabot.repo = name of the project repo for gitweb/cgit purposes
+# ciabot.revformat = format in which the revision is shown
#
-# The project as known to CIA. You will either want to change this
-# or set the project name with a -p option.
+# ciabot.project defaults to the directory name of the repository toplevel.
+# ciabot.repo defaults to ciabot.project lowercased.
#
-project=
-
+# This means that in the normal case you need not do any configuration at all,
+# but setting the project name will speed it up slightly.
#
-# You may not need to change these:
+# The revformat variable may have the following values
+# raw -> full hex ID of commit
+# short -> first 12 chars of hex ID
+# describe = -> describe relative to last tag, falling back to short
+# The default is 'describe'.
#
+# Note: the shell ancestors of this script used mail, not XML-RPC, in
+# order to avoid stalling until timeout when the CIA XML-RPC server is
+# down. It is unknown whether this is still an issue in 2010, but
+# XML-RPC would be annoying to do from sh in any case. (XML-RPC does
+# have the advantage that it guarantees notification of multiple commits
+# shpped from an update in their actual order.)
+#
+
+# The project as known to CIA. You can set this with a -p option,
+# or let it default to the directory name of the repo toplevel.
+project=$(git config --get ciabot.project)
+
+if [ -z $project ]
+then
+ here=`pwd`;
+ while :; do
+ if [ -d $here/.git ]
+ then
+ project=`basename $here`
+ break
+ elif [ $here = '/' ]
+ then
+ echo "ciabot.sh: no .git below root!"
+ exit 1
+ fi
+ here=`dirname $here`
+ done
+fi
-# Name of the repository.
-# You can hardwire this to make the script faster.
-repo="`basename ${PWD}`"
+# Name of the repo for gitweb/cgit purposes
+repo=$(git config --get ciabot.repo)
+[ -z $repo] && repo=$(echo "${project}" | tr '[A-Z]' '[a-z]')
-# Fully qualified domain name of the repo host.
-# You can hardwire this to make the script faster.
-host=`hostname --fqdn`
+# What revision format do we want in the summary?
+revformat=$(git config --get ciabot.revformat)
+
+# Fully qualified domain name of the repo host. You can hardwire this
+# to make the script faster. The -f option works under Linux and FreeBSD,
+# but not OpenBSD and NetBSD. But under OpenBSD and NetBSD,
+# hostname without options gives the FQDN.
+if hostname -f >/dev/null 2>&1
+then
+ hostname=`hostname -f`
+else
+ hostname=`hostname`
+fi
# Changeset URL prefix for your repo: when the commit ID is appended
# to this, it should point at a CGI that will display the commit
@@ -73,13 +117,14 @@ urlprefix="http://${host}/cgi-bin/cgit.cgi/${repo}/commit/?id="
# You probably will not need to change the following:
#
-# Identify the script. Should change only when the script itself
-# gets a new home and maintainer.
+# Identify the script. The 'generator' variable should change only
+# when the script itself gets a new home and maintainer.
generator="http://www.catb.org/~esr/ciabot/ciabot.sh"
+version=3.5
# Addresses for the e-mail
-from="CIABOT-NOREPLY@${host}"
-to="cia@cia.navi.cx"
+from="CIABOT-NOREPLY@${hostname}"
+to="cia@cia.vc"
# SMTP client to use - may need to edit the absolute pathname for your system
sendmail="sendmail -t -f ${from}"
@@ -97,7 +142,7 @@ do
case $opt in
p) project=$2; shift ; shift ;;
n) mode=dumpit; shift ;;
- V) echo "ciabot.sh: version 3.2"; exit 0; shift ;;
+ V) echo "ciabot.sh: version $version"; exit 0; shift ;;
esac
done
@@ -128,33 +173,29 @@ fi
refname=${refname##refs/heads/}
-gitver=$(git --version)
-gitver=${gitver##* }
-
-rev=$(git describe ${merged} 2>/dev/null)
-# ${merged:0:12} was the only bashism left in the 2008 version of this
-# script, according to checkbashisms. Replace it with ${merged} here
-# because it was just a fallback anyway, and it's worth accepting a
-# longer fallback for faster execution and removing the bash
-# dependency.
-[ -z ${rev} ] && rev=${merged}
+case $revformat in
+raw) rev=$merged ;;
+short) rev='' ;;
+*) rev=$(git describe ${merged} 2>/dev/null) ;;
+esac
+[ -z ${rev} ] && rev=$(echo "$merged" | cut -c 1-12)
-# This discards the part of the author's address after @.
+# We discard the part of the author's address after @.
# Might be nice to ship the full email address, if not
# for spammers' address harvesters - getting this wrong
# would make the freenode #commits channel into harvester heaven.
-rawcommit=$(git cat-file commit ${merged})
-author=$(echo "$rawcommit" | sed -n -e '/^author .*<\([^@]*\).*$/s--\1-p')
-logmessage=$(echo "$rawcommit" | sed -e '1,/^$/d' | head -n 1)
-logmessage=$(echo "$logmessage" | sed 's/\&/&amp\;/g; s/</&lt\;/g; s/>/&gt\;/g')
-ts=$(echo "$rawcommit" | sed -n -e '/^author .*> \([0-9]\+\).*$/s--\1-p')
+author=$(git log -1 '--pretty=format:%an <%ae>' $merged)
+author=$(echo "$author" | sed -n -e '/^.*<\([^@]*\).*$/s--\1-p')
+
+logmessage=$(git log -1 '--pretty=format:%s' $merged)
+ts=$(git log -1 '--pretty=format:%at' $merged)
files=$(git diff-tree -r --name-only ${merged} | sed -e '1d' -e 's-.*-<file>&</file>-')
out="
<message>
<generator>
<name>CIA Shell client for Git</name>
- <version>${gitver}</version>
+ <version>${version}</version>
<url>${generator}</url>
</generator>
<source>
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index ffedce7..be800e0 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -875,11 +875,15 @@ _git_branch ()
done
case "$cur" in
+ --set-upstream-to=*)
+ __gitcomp "$(__git_refs)" "" "${cur##--set-upstream-to=}"
+ ;;
--*)
__gitcomp "
--color --no-color --verbose --abbrev= --no-abbrev
--track --no-track --contains --merged --no-merged
- --set-upstream --edit-description --list
+ --set-upstream-to= --edit-description --list
+ --unset-upstream
"
;;
*)
@@ -1014,7 +1018,8 @@ _git_commit ()
--*)
__gitcomp "
--all --author= --signoff --verify --no-verify
- --edit --amend --include --only --interactive
+ --edit --no-edit
+ --amend --include --only --interactive
--dry-run --reuse-message= --reedit-message=
--reset-author --file= --message= --template=
--cleanup= --untracked-files --untracked-files=
@@ -1071,7 +1076,7 @@ _git_diff ()
}
__git_mergetools_common="diffuse ecmerge emerge kdiff3 meld opendiff
- tkdiff vimdiff gvimdiff xxdiff araxis p4merge bc3
+ tkdiff vimdiff gvimdiff xxdiff araxis p4merge bc3 codecompare
"
_git_difftool ()
@@ -2032,7 +2037,7 @@ _git_config ()
_git_remote ()
{
- local subcommands="add rename rm set-head set-branches set-url show prune update"
+ local subcommands="add rename remove set-head set-branches set-url show prune update"
local subcommand="$(__git_find_on_cmdline "$subcommands")"
if [ -z "$subcommand" ]; then
__gitcomp "$subcommands"
@@ -2040,7 +2045,7 @@ _git_remote ()
fi
case "$subcommand" in
- rename|rm|set-url|show|prune)
+ rename|remove|set-url|show|prune)
__gitcomp_nl "$(__git_remotes)"
;;
set-head|set-branches)
diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh
index 29b1ec9..bf20491 100644
--- a/contrib/completion/git-prompt.sh
+++ b/contrib/completion/git-prompt.sh
@@ -34,9 +34,10 @@
#
# If you would like to see the difference between HEAD and its upstream,
# set GIT_PS1_SHOWUPSTREAM="auto". A "<" indicates you are behind, ">"
-# indicates you are ahead, and "<>" indicates you have diverged. You
-# can further control behaviour by setting GIT_PS1_SHOWUPSTREAM to a
-# space-separated list of values:
+# indicates you are ahead, "<>" indicates you have diverged and "="
+# indicates that there is no difference. You can further control
+# behaviour by setting GIT_PS1_SHOWUPSTREAM to a space-separated list
+# of values:
#
# verbose show number of commits ahead/behind (+/-) upstream
# legacy don't use the '--count' option available in recent
diff --git a/contrib/credential/gnome-keyring/.gitignore b/contrib/credential/gnome-keyring/.gitignore
new file mode 100644
index 0000000..88d8fcd
--- /dev/null
+++ b/contrib/credential/gnome-keyring/.gitignore
@@ -0,0 +1 @@
+git-credential-gnome-keyring
diff --git a/contrib/credential/gnome-keyring/Makefile b/contrib/credential/gnome-keyring/Makefile
new file mode 100644
index 0000000..e6561d8
--- /dev/null
+++ b/contrib/credential/gnome-keyring/Makefile
@@ -0,0 +1,24 @@
+MAIN:=git-credential-gnome-keyring
+all:: $(MAIN)
+
+CC = gcc
+RM = rm -f
+CFLAGS = -g -O2 -Wall
+
+-include ../../../config.mak.autogen
+-include ../../../config.mak
+
+INCS:=$(shell pkg-config --cflags gnome-keyring-1)
+LIBS:=$(shell pkg-config --libs gnome-keyring-1)
+
+SRCS:=$(MAIN).c
+OBJS:=$(SRCS:.c=.o)
+
+%.o: %.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(INCS) -o $@ -c $<
+
+$(MAIN): $(OBJS)
+ $(CC) -o $@ $(LDFLAGS) $^ $(LIBS)
+
+clean:
+ @$(RM) $(MAIN) $(OBJS)
diff --git a/contrib/credential/gnome-keyring/git-credential-gnome-keyring.c b/contrib/credential/gnome-keyring/git-credential-gnome-keyring.c
new file mode 100644
index 0000000..41f61c5
--- /dev/null
+++ b/contrib/credential/gnome-keyring/git-credential-gnome-keyring.c
@@ -0,0 +1,445 @@
+/*
+ * Copyright (C) 2011 John Szakmeister <john@szakmeister.net>
+ * 2012 Philipp A. Hartmann <pah@qo.cx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * Credits:
+ * - GNOME Keyring API handling originally written by John Szakmeister
+ * - ported to credential helper API by Philipp A. Hartmann
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <gnome-keyring.h>
+
+/*
+ * This credential struct and API is simplified from git's credential.{h,c}
+ */
+struct credential
+{
+ char *protocol;
+ char *host;
+ unsigned short port;
+ char *path;
+ char *username;
+ char *password;
+};
+
+#define CREDENTIAL_INIT \
+ { NULL,NULL,0,NULL,NULL,NULL }
+
+void credential_init(struct credential *c);
+void credential_clear(struct credential *c);
+int credential_read(struct credential *c);
+void credential_write(const struct credential *c);
+
+typedef int (*credential_op_cb)(struct credential*);
+
+struct credential_operation
+{
+ char *name;
+ credential_op_cb op;
+};
+
+#define CREDENTIAL_OP_END \
+ { NULL,NULL }
+
+/*
+ * Table with operation callbacks is defined in concrete
+ * credential helper implementation and contains entries
+ * like { "get", function_to_get_credential } terminated
+ * by CREDENTIAL_OP_END.
+ */
+struct credential_operation const credential_helper_ops[];
+
+/* ---------------- common helper functions ----------------- */
+
+static inline void free_password(char *password)
+{
+ char *c = password;
+ if (!password)
+ return;
+
+ while (*c) *c++ = '\0';
+ free(password);
+}
+
+static inline void warning(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ fprintf(stderr, "warning: ");
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n" );
+ va_end(ap);
+}
+
+static inline void error(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ fprintf(stderr, "error: ");
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n" );
+ va_end(ap);
+}
+
+static inline void die(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap,fmt);
+ error(fmt, ap);
+ va_end(ap);
+ exit(EXIT_FAILURE);
+}
+
+static inline void die_errno(int err)
+{
+ error("%s", strerror(err));
+ exit(EXIT_FAILURE);
+}
+
+static inline char *xstrdup(const char *str)
+{
+ char *ret = strdup(str);
+ if (!ret)
+ die_errno(errno);
+
+ return ret;
+}
+
+/* ----------------- GNOME Keyring functions ----------------- */
+
+/* create a special keyring option string, if path is given */
+static char* keyring_object(struct credential *c)
+{
+ char* object = NULL;
+
+ if (!c->path)
+ return object;
+
+ object = (char*) malloc(strlen(c->host)+strlen(c->path)+8);
+ if(!object)
+ die_errno(errno);
+
+ if(c->port)
+ sprintf(object,"%s:%hd/%s",c->host,c->port,c->path);
+ else
+ sprintf(object,"%s/%s",c->host,c->path);
+
+ return object;
+}
+
+int keyring_get(struct credential *c)
+{
+ char* object = NULL;
+ GList *entries;
+ GnomeKeyringNetworkPasswordData *password_data;
+ GnomeKeyringResult result;
+
+ if (!c->protocol || !(c->host || c->path))
+ return EXIT_FAILURE;
+
+ object = keyring_object(c);
+
+ result = gnome_keyring_find_network_password_sync(
+ c->username,
+ NULL /* domain */,
+ c->host,
+ object,
+ c->protocol,
+ NULL /* authtype */,
+ c->port,
+ &entries);
+
+ free(object);
+
+ if (result == GNOME_KEYRING_RESULT_NO_MATCH)
+ return EXIT_SUCCESS;
+
+ if (result == GNOME_KEYRING_RESULT_CANCELLED)
+ return EXIT_SUCCESS;
+
+ if (result != GNOME_KEYRING_RESULT_OK) {
+ error("%s",gnome_keyring_result_to_message(result));
+ return EXIT_FAILURE;
+ }
+
+ /* pick the first one from the list */
+ password_data = (GnomeKeyringNetworkPasswordData *) entries->data;
+
+ free_password(c->password);
+ c->password = xstrdup(password_data->password);
+
+ if (!c->username)
+ c->username = xstrdup(password_data->user);
+
+ gnome_keyring_network_password_list_free(entries);
+
+ return EXIT_SUCCESS;
+}
+
+
+int keyring_store(struct credential *c)
+{
+ guint32 item_id;
+ char *object = NULL;
+
+ /*
+ * Sanity check that what we are storing is actually sensible.
+ * In particular, we can't make a URL without a protocol field.
+ * Without either a host or pathname (depending on the scheme),
+ * we have no primary key. And without a username and password,
+ * we are not actually storing a credential.
+ */
+ if (!c->protocol || !(c->host || c->path) ||
+ !c->username || !c->password)
+ return EXIT_FAILURE;
+
+ object = keyring_object(c);
+
+ gnome_keyring_set_network_password_sync(
+ GNOME_KEYRING_DEFAULT,
+ c->username,
+ NULL /* domain */,
+ c->host,
+ object,
+ c->protocol,
+ NULL /* authtype */,
+ c->port,
+ c->password,
+ &item_id);
+
+ free(object);
+ return EXIT_SUCCESS;
+}
+
+int keyring_erase(struct credential *c)
+{
+ char *object = NULL;
+ GList *entries;
+ GnomeKeyringNetworkPasswordData *password_data;
+ GnomeKeyringResult result;
+
+ /*
+ * Sanity check that we actually have something to match
+ * against. The input we get is a restrictive pattern,
+ * so technically a blank credential means "erase everything".
+ * But it is too easy to accidentally send this, since it is equivalent
+ * to empty input. So explicitly disallow it, and require that the
+ * pattern have some actual content to match.
+ */
+ if (!c->protocol && !c->host && !c->path && !c->username)
+ return EXIT_FAILURE;
+
+ object = keyring_object(c);
+
+ result = gnome_keyring_find_network_password_sync(
+ c->username,
+ NULL /* domain */,
+ c->host,
+ object,
+ c->protocol,
+ NULL /* authtype */,
+ c->port,
+ &entries);
+
+ free(object);
+
+ if (result == GNOME_KEYRING_RESULT_NO_MATCH)
+ return EXIT_SUCCESS;
+
+ if (result == GNOME_KEYRING_RESULT_CANCELLED)
+ return EXIT_SUCCESS;
+
+ if (result != GNOME_KEYRING_RESULT_OK)
+ {
+ error("%s",gnome_keyring_result_to_message(result));
+ return EXIT_FAILURE;
+ }
+
+ /* pick the first one from the list (delete all matches?) */
+ password_data = (GnomeKeyringNetworkPasswordData *) entries->data;
+
+ result = gnome_keyring_item_delete_sync(
+ password_data->keyring, password_data->item_id);
+
+ gnome_keyring_network_password_list_free(entries);
+
+ if (result != GNOME_KEYRING_RESULT_OK)
+ {
+ error("%s",gnome_keyring_result_to_message(result));
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+/*
+ * Table with helper operation callbacks, used by generic
+ * credential helper main function.
+ */
+struct credential_operation const credential_helper_ops[] =
+{
+ { "get", keyring_get },
+ { "store", keyring_store },
+ { "erase", keyring_erase },
+ CREDENTIAL_OP_END
+};
+
+/* ------------------ credential functions ------------------ */
+
+void credential_init(struct credential *c)
+{
+ memset(c, 0, sizeof(*c));
+}
+
+void credential_clear(struct credential *c)
+{
+ free(c->protocol);
+ free(c->host);
+ free(c->path);
+ free(c->username);
+ free_password(c->password);
+
+ credential_init(c);
+}
+
+int credential_read(struct credential *c)
+{
+ char buf[1024];
+ ssize_t line_len = 0;
+ char *key = buf;
+ char *value;
+
+ while (fgets(buf, sizeof(buf), stdin))
+ {
+ line_len = strlen(buf);
+
+ if(buf[line_len-1]=='\n')
+ buf[--line_len]='\0';
+
+ if(!line_len)
+ break;
+
+ value = strchr(buf,'=');
+ if(!value) {
+ warning("invalid credential line: %s", key);
+ return -1;
+ }
+ *value++ = '\0';
+
+ if (!strcmp(key, "protocol")) {
+ free(c->protocol);
+ c->protocol = xstrdup(value);
+ } else if (!strcmp(key, "host")) {
+ free(c->host);
+ c->host = xstrdup(value);
+ value = strrchr(c->host,':');
+ if (value) {
+ *value++ = '\0';
+ c->port = atoi(value);
+ }
+ } else if (!strcmp(key, "path")) {
+ free(c->path);
+ c->path = xstrdup(value);
+ } else if (!strcmp(key, "username")) {
+ free(c->username);
+ c->username = xstrdup(value);
+ } else if (!strcmp(key, "password")) {
+ free_password(c->password);
+ c->password = xstrdup(value);
+ while (*value) *value++ = '\0';
+ }
+ /*
+ * Ignore other lines; we don't know what they mean, but
+ * this future-proofs us when later versions of git do
+ * learn new lines, and the helpers are updated to match.
+ */
+ }
+ return 0;
+}
+
+void credential_write_item(FILE *fp, const char *key, const char *value)
+{
+ if (!value)
+ return;
+ fprintf(fp, "%s=%s\n", key, value);
+}
+
+void credential_write(const struct credential *c)
+{
+ /* only write username/password, if set */
+ credential_write_item(stdout, "username", c->username);
+ credential_write_item(stdout, "password", c->password);
+}
+
+static void usage(const char *name)
+{
+ struct credential_operation const *try_op = credential_helper_ops;
+ const char *basename = strrchr(name,'/');
+
+ basename = (basename) ? basename + 1 : name;
+ fprintf(stderr, "Usage: %s <", basename);
+ while(try_op->name) {
+ fprintf(stderr,"%s",(try_op++)->name);
+ if(try_op->name)
+ fprintf(stderr,"%s","|");
+ }
+ fprintf(stderr,"%s",">\n");
+}
+
+int main(int argc, char *argv[])
+{
+ int ret = EXIT_SUCCESS;
+
+ struct credential_operation const *try_op = credential_helper_ops;
+ struct credential cred = CREDENTIAL_INIT;
+
+ if (!argv[1]) {
+ usage(argv[0]);
+ goto out;
+ }
+
+ /* lookup operation callback */
+ while(try_op->name && strcmp(argv[1], try_op->name))
+ try_op++;
+
+ /* unsupported operation given -- ignore silently */
+ if(!try_op->name || !try_op->op)
+ goto out;
+
+ ret = credential_read(&cred);
+ if(ret)
+ goto out;
+
+ /* perform credential operation */
+ ret = (*try_op->op)(&cred);
+
+ credential_write(&cred);
+
+out:
+ credential_clear(&cred);
+ return ret;
+}
diff --git a/contrib/credential/wincred/Makefile b/contrib/credential/wincred/Makefile
new file mode 100644
index 0000000..bad45ca
--- /dev/null
+++ b/contrib/credential/wincred/Makefile
@@ -0,0 +1,14 @@
+all: git-credential-wincred.exe
+
+CC = gcc
+RM = rm -f
+CFLAGS = -O2 -Wall
+
+-include ../../../config.mak.autogen
+-include ../../../config.mak
+
+git-credential-wincred.exe : git-credential-wincred.c
+ $(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $@
+
+clean:
+ $(RM) git-credential-wincred.exe
diff --git a/contrib/credential/wincred/git-credential-wincred.c b/contrib/credential/wincred/git-credential-wincred.c
new file mode 100644
index 0000000..cbaec5f
--- /dev/null
+++ b/contrib/credential/wincred/git-credential-wincred.c
@@ -0,0 +1,357 @@
+/*
+ * A git credential helper that interface with Windows' Credential Manager
+ *
+ */
+#include <windows.h>
+#include <stdio.h>
+#include <io.h>
+#include <fcntl.h>
+
+/* common helpers */
+
+static void die(const char *err, ...)
+{
+ char msg[4096];
+ va_list params;
+ va_start(params, err);
+ vsnprintf(msg, sizeof(msg), err, params);
+ fprintf(stderr, "%s\n", msg);
+ va_end(params);
+ exit(1);
+}
+
+static void *xmalloc(size_t size)
+{
+ void *ret = malloc(size);
+ if (!ret && !size)
+ ret = malloc(1);
+ if (!ret)
+ die("Out of memory");
+ return ret;
+}
+
+static char *xstrdup(const char *str)
+{
+ char *ret = strdup(str);
+ if (!ret)
+ die("Out of memory");
+ return ret;
+}
+
+/* MinGW doesn't have wincred.h, so we need to define stuff */
+
+typedef struct _CREDENTIAL_ATTRIBUTEW {
+ LPWSTR Keyword;
+ DWORD Flags;
+ DWORD ValueSize;
+ LPBYTE Value;
+} CREDENTIAL_ATTRIBUTEW, *PCREDENTIAL_ATTRIBUTEW;
+
+typedef struct _CREDENTIALW {
+ DWORD Flags;
+ DWORD Type;
+ LPWSTR TargetName;
+ LPWSTR Comment;
+ FILETIME LastWritten;
+ DWORD CredentialBlobSize;
+ LPBYTE CredentialBlob;
+ DWORD Persist;
+ DWORD AttributeCount;
+ PCREDENTIAL_ATTRIBUTEW Attributes;
+ LPWSTR TargetAlias;
+ LPWSTR UserName;
+} CREDENTIALW, *PCREDENTIALW;
+
+#define CRED_TYPE_GENERIC 1
+#define CRED_PERSIST_LOCAL_MACHINE 2
+#define CRED_MAX_ATTRIBUTES 64
+
+typedef BOOL (WINAPI *CredWriteWT)(PCREDENTIALW, DWORD);
+typedef BOOL (WINAPI *CredUnPackAuthenticationBufferWT)(DWORD, PVOID, DWORD,
+ LPWSTR, DWORD *, LPWSTR, DWORD *, LPWSTR, DWORD *);
+typedef BOOL (WINAPI *CredEnumerateWT)(LPCWSTR, DWORD, DWORD *,
+ PCREDENTIALW **);
+typedef BOOL (WINAPI *CredPackAuthenticationBufferWT)(DWORD, LPWSTR, LPWSTR,
+ PBYTE, DWORD *);
+typedef VOID (WINAPI *CredFreeT)(PVOID);
+typedef BOOL (WINAPI *CredDeleteWT)(LPCWSTR, DWORD, DWORD);
+
+static HMODULE advapi, credui;
+static CredWriteWT CredWriteW;
+static CredUnPackAuthenticationBufferWT CredUnPackAuthenticationBufferW;
+static CredEnumerateWT CredEnumerateW;
+static CredPackAuthenticationBufferWT CredPackAuthenticationBufferW;
+static CredFreeT CredFree;
+static CredDeleteWT CredDeleteW;
+
+static void load_cred_funcs(void)
+{
+ /* load DLLs */
+ advapi = LoadLibrary("advapi32.dll");
+ credui = LoadLibrary("credui.dll");
+ if (!advapi || !credui)
+ die("failed to load DLLs");
+
+ /* get function pointers */
+ CredWriteW = (CredWriteWT)GetProcAddress(advapi, "CredWriteW");
+ CredUnPackAuthenticationBufferW = (CredUnPackAuthenticationBufferWT)
+ GetProcAddress(credui, "CredUnPackAuthenticationBufferW");
+ CredEnumerateW = (CredEnumerateWT)GetProcAddress(advapi,
+ "CredEnumerateW");
+ CredPackAuthenticationBufferW = (CredPackAuthenticationBufferWT)
+ GetProcAddress(credui, "CredPackAuthenticationBufferW");
+ CredFree = (CredFreeT)GetProcAddress(advapi, "CredFree");
+ CredDeleteW = (CredDeleteWT)GetProcAddress(advapi, "CredDeleteW");
+ if (!CredWriteW || !CredUnPackAuthenticationBufferW ||
+ !CredEnumerateW || !CredPackAuthenticationBufferW || !CredFree ||
+ !CredDeleteW)
+ die("failed to load functions");
+}
+
+static char target_buf[1024];
+static char *protocol, *host, *path, *username;
+static WCHAR *wusername, *password, *target;
+
+static void write_item(const char *what, WCHAR *wbuf)
+{
+ char *buf;
+ int len = WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, NULL, 0, NULL,
+ FALSE);
+ buf = xmalloc(len);
+
+ if (!WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, buf, len, NULL, FALSE))
+ die("WideCharToMultiByte failed!");
+
+ printf("%s=", what);
+ fwrite(buf, 1, len - 1, stdout);
+ putchar('\n');
+ free(buf);
+}
+
+static int match_attr(const CREDENTIALW *cred, const WCHAR *keyword,
+ const char *want)
+{
+ int i;
+ if (!want)
+ return 1;
+
+ for (i = 0; i < cred->AttributeCount; ++i)
+ if (!wcscmp(cred->Attributes[i].Keyword, keyword))
+ return !strcmp((const char *)cred->Attributes[i].Value,
+ want);
+
+ return 0; /* not found */
+}
+
+static int match_cred(const CREDENTIALW *cred)
+{
+ return (!wusername || !wcscmp(wusername, cred->UserName)) &&
+ match_attr(cred, L"git_protocol", protocol) &&
+ match_attr(cred, L"git_host", host) &&
+ match_attr(cred, L"git_path", path);
+}
+
+static void get_credential(void)
+{
+ WCHAR *user_buf, *pass_buf;
+ DWORD user_buf_size = 0, pass_buf_size = 0;
+ CREDENTIALW **creds, *cred = NULL;
+ DWORD num_creds;
+ int i;
+
+ if (!CredEnumerateW(L"git:*", 0, &num_creds, &creds))
+ return;
+
+ /* search for the first credential that matches username */
+ for (i = 0; i < num_creds; ++i)
+ if (match_cred(creds[i])) {
+ cred = creds[i];
+ break;
+ }
+ if (!cred)
+ return;
+
+ CredUnPackAuthenticationBufferW(0, cred->CredentialBlob,
+ cred->CredentialBlobSize, NULL, &user_buf_size, NULL, NULL,
+ NULL, &pass_buf_size);
+
+ user_buf = xmalloc(user_buf_size * sizeof(WCHAR));
+ pass_buf = xmalloc(pass_buf_size * sizeof(WCHAR));
+
+ if (!CredUnPackAuthenticationBufferW(0, cred->CredentialBlob,
+ cred->CredentialBlobSize, user_buf, &user_buf_size, NULL, NULL,
+ pass_buf, &pass_buf_size))
+ die("CredUnPackAuthenticationBuffer failed");
+
+ CredFree(creds);
+
+ /* zero-terminate (sizes include zero-termination) */
+ user_buf[user_buf_size - 1] = L'\0';
+ pass_buf[pass_buf_size - 1] = L'\0';
+
+ write_item("username", user_buf);
+ write_item("password", pass_buf);
+
+ free(user_buf);
+ free(pass_buf);
+}
+
+static void write_attr(CREDENTIAL_ATTRIBUTEW *attr, const WCHAR *keyword,
+ const char *value)
+{
+ attr->Keyword = (LPWSTR)keyword;
+ attr->Flags = 0;
+ attr->ValueSize = strlen(value) + 1; /* store zero-termination */
+ attr->Value = (LPBYTE)value;
+}
+
+static void store_credential(void)
+{
+ CREDENTIALW cred;
+ BYTE *auth_buf;
+ DWORD auth_buf_size = 0;
+ CREDENTIAL_ATTRIBUTEW attrs[CRED_MAX_ATTRIBUTES];
+
+ if (!wusername || !password)
+ return;
+
+ /* query buffer size */
+ CredPackAuthenticationBufferW(0, wusername, password,
+ NULL, &auth_buf_size);
+
+ auth_buf = xmalloc(auth_buf_size);
+
+ if (!CredPackAuthenticationBufferW(0, wusername, password,
+ auth_buf, &auth_buf_size))
+ die("CredPackAuthenticationBuffer failed");
+
+ cred.Flags = 0;
+ cred.Type = CRED_TYPE_GENERIC;
+ cred.TargetName = target;
+ cred.Comment = L"saved by git-credential-wincred";
+ cred.CredentialBlobSize = auth_buf_size;
+ cred.CredentialBlob = auth_buf;
+ cred.Persist = CRED_PERSIST_LOCAL_MACHINE;
+ cred.AttributeCount = 1;
+ cred.Attributes = attrs;
+ cred.TargetAlias = NULL;
+ cred.UserName = wusername;
+
+ write_attr(attrs, L"git_protocol", protocol);
+
+ if (host) {
+ write_attr(attrs + cred.AttributeCount, L"git_host", host);
+ cred.AttributeCount++;
+ }
+
+ if (path) {
+ write_attr(attrs + cred.AttributeCount, L"git_path", path);
+ cred.AttributeCount++;
+ }
+
+ if (!CredWriteW(&cred, 0))
+ die("CredWrite failed");
+}
+
+static void erase_credential(void)
+{
+ CREDENTIALW **creds;
+ DWORD num_creds;
+ int i;
+
+ if (!CredEnumerateW(L"git:*", 0, &num_creds, &creds))
+ return;
+
+ for (i = 0; i < num_creds; ++i) {
+ if (match_cred(creds[i]))
+ CredDeleteW(creds[i]->TargetName, creds[i]->Type, 0);
+ }
+
+ CredFree(creds);
+}
+
+static WCHAR *utf8_to_utf16_dup(const char *str)
+{
+ int wlen = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
+ WCHAR *wstr = xmalloc(sizeof(WCHAR) * wlen);
+ MultiByteToWideChar(CP_UTF8, 0, str, -1, wstr, wlen);
+ return wstr;
+}
+
+static void read_credential(void)
+{
+ char buf[1024];
+
+ while (fgets(buf, sizeof(buf), stdin)) {
+ char *v;
+
+ if (!strcmp(buf, "\n"))
+ break;
+ buf[strlen(buf)-1] = '\0';
+
+ v = strchr(buf, '=');
+ if (!v)
+ die("bad input: %s", buf);
+ *v++ = '\0';
+
+ if (!strcmp(buf, "protocol"))
+ protocol = xstrdup(v);
+ else if (!strcmp(buf, "host"))
+ host = xstrdup(v);
+ else if (!strcmp(buf, "path"))
+ path = xstrdup(v);
+ else if (!strcmp(buf, "username")) {
+ username = xstrdup(v);
+ wusername = utf8_to_utf16_dup(v);
+ } else if (!strcmp(buf, "password"))
+ password = utf8_to_utf16_dup(v);
+ else
+ die("unrecognized input");
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ const char *usage =
+ "Usage: git credential-wincred <get|store|erase>\n";
+
+ if (!argv[1])
+ die(usage);
+
+ /* git use binary pipes to avoid CRLF-issues */
+ _setmode(_fileno(stdin), _O_BINARY);
+ _setmode(_fileno(stdout), _O_BINARY);
+
+ read_credential();
+
+ load_cred_funcs();
+
+ if (!protocol || !(host || path))
+ return 0;
+
+ /* prepare 'target', the unique key for the credential */
+ strncat(target_buf, "git:", sizeof(target_buf));
+ strncat(target_buf, protocol, sizeof(target_buf));
+ strncat(target_buf, "://", sizeof(target_buf));
+ if (username) {
+ strncat(target_buf, username, sizeof(target_buf));
+ strncat(target_buf, "@", sizeof(target_buf));
+ }
+ if (host)
+ strncat(target_buf, host, sizeof(target_buf));
+ if (path) {
+ strncat(target_buf, "/", sizeof(target_buf));
+ strncat(target_buf, path, sizeof(target_buf));
+ }
+
+ target = utf8_to_utf16_dup(target_buf);
+
+ if (!strcmp(argv[1], "get"))
+ get_credential();
+ else if (!strcmp(argv[1], "store"))
+ store_credential();
+ else if (!strcmp(argv[1], "erase"))
+ erase_credential();
+ /* otherwise, ignore unknown action */
+ return 0;
+}
diff --git a/contrib/examples/builtin-fetch--tool.c b/contrib/examples/builtin-fetch--tool.c
index 0d54aa7..8bc8c75 100644
--- a/contrib/examples/builtin-fetch--tool.c
+++ b/contrib/examples/builtin-fetch--tool.c
@@ -96,7 +96,7 @@ static int update_local_ref(const char *name,
strcpy(oldh, find_unique_abbrev(current->object.sha1, DEFAULT_ABBREV));
strcpy(newh, find_unique_abbrev(sha1_new, DEFAULT_ABBREV));
- if (in_merge_bases(current, &updated, 1)) {
+ if (in_merge_bases(current, updated)) {
fprintf(stderr, "* %s: fast-forward to %s\n",
name, note);
fprintf(stderr, " old..new: %s..%s\n", oldh, newh);
diff --git a/contrib/git-jump/git-jump b/contrib/git-jump/git-jump
index a33674e..dc90cd6 100755
--- a/contrib/git-jump/git-jump
+++ b/contrib/git-jump/git-jump
@@ -21,9 +21,9 @@ open_editor() {
}
mode_diff() {
- git diff --relative "$@" |
+ git diff --no-prefix --relative "$@" |
perl -ne '
- if (m{^\+\+\+ b/(.*)}) { $file = $1; next }
+ if (m{^\+\+\+ (.*)}) { $file = $1; next }
defined($file) or next;
if (m/^@@ .*\+(\d+)/) { $line = $1; next }
defined($line) or next;
diff --git a/contrib/hooks/post-receive-email b/contrib/hooks/post-receive-email
index 01af9df..b2171a0 100755
--- a/contrib/hooks/post-receive-email
+++ b/contrib/hooks/post-receive-email
@@ -403,7 +403,7 @@ generate_update_branch_email()
echo " \\"
echo " O -- O -- O ($oldrev)"
echo ""
- echo "The removed revisions are not necessarilly gone - if another reference"
+ echo "The removed revisions are not necessarily gone - if another reference"
echo "still refers to them they will stay in the repository."
rewind_only=1
else
diff --git a/daemon.c b/daemon.c
index ab21e66..4602b46 100644
--- a/daemon.c
+++ b/daemon.c
@@ -30,6 +30,7 @@ static const char daemon_usage[] =
" [--interpolated-path=<path>]\n"
" [--reuseaddr] [--pid-file=<file>]\n"
" [--(enable|disable|allow-override|forbid-override)=<service>]\n"
+" [--access-hook=<path>]\n"
" [--inetd | [--listen=<host_or_ipaddr>] [--port=<n>]\n"
" [--detach] [--user=<user> [--group=<group>]]\n"
" [<directory>...]";
@@ -256,6 +257,71 @@ static int daemon_error(const char *dir, const char *msg)
return -1;
}
+static char *access_hook;
+
+static int run_access_hook(struct daemon_service *service, const char *dir, const char *path)
+{
+ struct child_process child;
+ struct strbuf buf = STRBUF_INIT;
+ const char *argv[8];
+ const char **arg = argv;
+ char *eol;
+ int seen_errors = 0;
+
+#define STRARG(x) ((x) ? (x) : "")
+ *arg++ = access_hook;
+ *arg++ = service->name;
+ *arg++ = path;
+ *arg++ = STRARG(hostname);
+ *arg++ = STRARG(canon_hostname);
+ *arg++ = STRARG(ip_address);
+ *arg++ = STRARG(tcp_port);
+ *arg = NULL;
+#undef STRARG
+
+ memset(&child, 0, sizeof(child));
+ child.use_shell = 1;
+ child.argv = argv;
+ child.no_stdin = 1;
+ child.no_stderr = 1;
+ child.out = -1;
+ if (start_command(&child)) {
+ logerror("daemon access hook '%s' failed to start",
+ access_hook);
+ goto error_return;
+ }
+ if (strbuf_read(&buf, child.out, 0) < 0) {
+ logerror("failed to read from pipe to daemon access hook '%s'",
+ access_hook);
+ strbuf_reset(&buf);
+ seen_errors = 1;
+ }
+ if (close(child.out) < 0) {
+ logerror("failed to close pipe to daemon access hook '%s'",
+ access_hook);
+ seen_errors = 1;
+ }
+ if (finish_command(&child))
+ seen_errors = 1;
+
+ if (!seen_errors) {
+ strbuf_release(&buf);
+ return 0;
+ }
+
+error_return:
+ strbuf_ltrim(&buf);
+ if (!buf.len)
+ strbuf_addstr(&buf, "service rejected");
+ eol = strchr(buf.buf, '\n');
+ if (eol)
+ *eol = '\0';
+ errno = EACCES;
+ daemon_error(dir, buf.buf);
+ strbuf_release(&buf);
+ return -1;
+}
+
static int run_service(char *dir, struct daemon_service *service)
{
const char *path;
@@ -304,6 +370,13 @@ static int run_service(char *dir, struct daemon_service *service)
}
/*
+ * Optionally, a hook can choose to deny access to the
+ * repository depending on the phase of the moon.
+ */
+ if (access_hook && run_access_hook(service, dir, path))
+ return -1;
+
+ /*
* We'll ignore SIGTERM from now on, we have a
* good client.
*/
@@ -1142,6 +1215,10 @@ int main(int argc, char **argv)
export_all_trees = 1;
continue;
}
+ if (!prefixcmp(arg, "--access-hook=")) {
+ access_hook = arg + 14;
+ continue;
+ }
if (!prefixcmp(arg, "--timeout=")) {
timeout = atoi(arg+10);
continue;
diff --git a/diff-lib.c b/diff-lib.c
index fc0dff3..f35de0f 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -206,7 +206,8 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
if (silent_on_removed)
continue;
diff_addremove(&revs->diffopt, '-', ce->ce_mode,
- ce->sha1, ce->name, 0);
+ ce->sha1, !is_null_sha1(ce->sha1),
+ ce->name, 0);
continue;
}
changed = match_stat_with_submodule(&revs->diffopt, ce, &st,
@@ -220,6 +221,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
newmode = ce_mode_from_stat(ce, st.st_mode);
diff_change(&revs->diffopt, oldmode, newmode,
ce->sha1, (changed ? null_sha1 : ce->sha1),
+ !is_null_sha1(ce->sha1), (changed ? 0 : !is_null_sha1(ce->sha1)),
ce->name, 0, dirty_submodule);
}
@@ -236,11 +238,12 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
static void diff_index_show_file(struct rev_info *revs,
const char *prefix,
struct cache_entry *ce,
- const unsigned char *sha1, unsigned int mode,
+ const unsigned char *sha1, int sha1_valid,
+ unsigned int mode,
unsigned dirty_submodule)
{
diff_addremove(&revs->diffopt, prefix[0], mode,
- sha1, ce->name, dirty_submodule);
+ sha1, sha1_valid, ce->name, dirty_submodule);
}
static int get_stat_data(struct cache_entry *ce,
@@ -295,7 +298,7 @@ static void show_new_file(struct rev_info *revs,
&dirty_submodule, &revs->diffopt) < 0)
return;
- diff_index_show_file(revs, "+", new, sha1, mode, dirty_submodule);
+ diff_index_show_file(revs, "+", new, sha1, !is_null_sha1(sha1), mode, dirty_submodule);
}
static int show_modified(struct rev_info *revs,
@@ -312,7 +315,7 @@ static int show_modified(struct rev_info *revs,
&dirty_submodule, &revs->diffopt) < 0) {
if (report_missing)
diff_index_show_file(revs, "-", old,
- old->sha1, old->ce_mode, 0);
+ old->sha1, 1, old->ce_mode, 0);
return -1;
}
@@ -347,7 +350,8 @@ static int show_modified(struct rev_info *revs,
return 0;
diff_change(&revs->diffopt, oldmode, mode,
- old->sha1, sha1, old->name, 0, dirty_submodule);
+ old->sha1, sha1, 1, !is_null_sha1(sha1),
+ old->name, 0, dirty_submodule);
return 0;
}
@@ -380,7 +384,7 @@ static void do_oneway_diff(struct unpack_trees_options *o,
struct diff_filepair *pair;
pair = diff_unmerge(&revs->diffopt, idx->name);
if (tree)
- fill_filespec(pair->one, tree->sha1, tree->ce_mode);
+ fill_filespec(pair->one, tree->sha1, 1, tree->ce_mode);
return;
}
@@ -396,7 +400,7 @@ static void do_oneway_diff(struct unpack_trees_options *o,
* Something removed from the tree?
*/
if (!idx) {
- diff_index_show_file(revs, "-", tree, tree->sha1, tree->ce_mode, 0);
+ diff_index_show_file(revs, "-", tree, tree->sha1, 1, tree->ce_mode, 0);
return;
}
diff --git a/diff-no-index.c b/diff-no-index.c
index 7d805a0..74da659 100644
--- a/diff-no-index.c
+++ b/diff-no-index.c
@@ -82,7 +82,7 @@ static struct diff_filespec *noindex_filespec(const char *name, int mode)
if (!name)
name = "/dev/null";
s = alloc_filespec(name);
- fill_filespec(s, null_sha1, mode);
+ fill_filespec(s, null_sha1, 0, mode);
if (name == file_from_standard_input)
populate_from_stdin(s);
return s;
@@ -258,8 +258,7 @@ void diff_no_index(struct rev_info *revs,
DIFF_OPT_SET(&revs->diffopt, NO_INDEX);
revs->max_count = -2;
- if (diff_setup_done(&revs->diffopt) < 0)
- die("diff_setup_done failed");
+ diff_setup_done(&revs->diffopt);
setup_diff_pager(&revs->diffopt);
DIFF_OPT_SET(&revs->diffopt, EXIT_WITH_STATUS);
diff --git a/diff.c b/diff.c
index 95706a5..86e5f2a 100644
--- a/diff.c
+++ b/diff.c
@@ -25,7 +25,8 @@
static int diff_detect_rename_default;
static int diff_rename_limit_default = 400;
static int diff_suppress_blank_empty;
-int diff_use_color_default = -1;
+static int diff_use_color_default = -1;
+static int diff_context_default = 3;
static const char *diff_word_regex_cfg;
static const char *external_diff_cmd_cfg;
int diff_auto_refresh_index = 1;
@@ -141,6 +142,12 @@ int git_diff_ui_config(const char *var, const char *value, void *cb)
diff_use_color_default = git_config_colorbool(var, value);
return 0;
}
+ if (!strcmp(var, "diff.context")) {
+ diff_context_default = git_config_int(var, value);
+ if (diff_context_default < 0)
+ return -1;
+ return 0;
+ }
if (!strcmp(var, "diff.renames")) {
diff_detect_rename_default = git_config_rename(var, value);
return 0;
@@ -574,6 +581,7 @@ static void emit_rewrite_lines(struct emit_callback *ecb,
if (!endp) {
const char *plain = diff_get_color(ecb->color_diff,
DIFF_PLAIN);
+ putc('\n', ecb->opt->file);
emit_line_0(ecb->opt, plain, reset, '\\',
nneof, strlen(nneof));
}
@@ -1397,11 +1405,11 @@ int print_stat_summary(FILE *fp, int files, int insertions, int deletions)
if (!files) {
assert(insertions == 0 && deletions == 0);
- return fprintf(fp, "%s\n", _(" 0 files changed"));
+ return fprintf(fp, "%s\n", " 0 files changed");
}
strbuf_addf(&sb,
- Q_(" %d file changed", " %d files changed", files),
+ (files == 1) ? " %d file changed" : " %d files changed",
files);
/*
@@ -1418,8 +1426,7 @@ int print_stat_summary(FILE *fp, int files, int insertions, int deletions)
* do not translate it.
*/
strbuf_addf(&sb,
- Q_(", %d insertion(+)", ", %d insertions(+)",
- insertions),
+ (insertions == 1) ? ", %d insertion(+)" : ", %d insertions(+)",
insertions);
}
@@ -1429,8 +1436,7 @@ int print_stat_summary(FILE *fp, int files, int insertions, int deletions)
* do not translate it.
*/
strbuf_addf(&sb,
- Q_(", %d deletion(-)", ", %d deletions(-)",
- deletions),
+ (deletions == 1) ? ", %d deletion(-)" : ", %d deletions(-)",
deletions);
}
strbuf_addch(&sb, '\n');
@@ -2541,12 +2547,12 @@ void free_filespec(struct diff_filespec *spec)
}
void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1,
- unsigned short mode)
+ int sha1_valid, unsigned short mode)
{
if (mode) {
spec->mode = canon_mode(mode);
hashcpy(spec->sha1, sha1);
- spec->sha1_valid = !is_null_sha1(sha1);
+ spec->sha1_valid = sha1_valid;
}
}
@@ -3171,7 +3177,7 @@ void diff_setup(struct diff_options *options)
options->break_opt = -1;
options->rename_limit = -1;
options->dirstat_permille = diff_dirstat_permille_default;
- options->context = 3;
+ options->context = diff_context_default;
DIFF_OPT_SET(options, RENAME_EMPTY);
options->change = diff_change;
@@ -3187,7 +3193,7 @@ void diff_setup(struct diff_options *options)
}
}
-int diff_setup_done(struct diff_options *options)
+void diff_setup_done(struct diff_options *options)
{
int count = 0;
@@ -3286,8 +3292,6 @@ int diff_setup_done(struct diff_options *options)
options->output_format = DIFF_FORMAT_NO_OUTPUT;
DIFF_OPT_SET(options, EXIT_WITH_STATUS);
}
-
- return 0;
}
static int opt_arg(const char *arg, int arg_short, const char *arg_long, int *val)
@@ -4693,6 +4697,7 @@ static int is_submodule_ignored(const char *path, struct diff_options *options)
void diff_addremove(struct diff_options *options,
int addremove, unsigned mode,
const unsigned char *sha1,
+ int sha1_valid,
const char *concatpath, unsigned dirty_submodule)
{
struct diff_filespec *one, *two;
@@ -4724,9 +4729,9 @@ void diff_addremove(struct diff_options *options,
two = alloc_filespec(concatpath);
if (addremove != '+')
- fill_filespec(one, sha1, mode);
+ fill_filespec(one, sha1, sha1_valid, mode);
if (addremove != '-') {
- fill_filespec(two, sha1, mode);
+ fill_filespec(two, sha1, sha1_valid, mode);
two->dirty_submodule = dirty_submodule;
}
@@ -4739,6 +4744,7 @@ void diff_change(struct diff_options *options,
unsigned old_mode, unsigned new_mode,
const unsigned char *old_sha1,
const unsigned char *new_sha1,
+ int old_sha1_valid, int new_sha1_valid,
const char *concatpath,
unsigned old_dirty_submodule, unsigned new_dirty_submodule)
{
@@ -4753,6 +4759,8 @@ void diff_change(struct diff_options *options,
const unsigned char *tmp_c;
tmp = old_mode; old_mode = new_mode; new_mode = tmp;
tmp_c = old_sha1; old_sha1 = new_sha1; new_sha1 = tmp_c;
+ tmp = old_sha1_valid; old_sha1_valid = new_sha1_valid;
+ new_sha1_valid = tmp;
tmp = old_dirty_submodule; old_dirty_submodule = new_dirty_submodule;
new_dirty_submodule = tmp;
}
@@ -4763,8 +4771,8 @@ void diff_change(struct diff_options *options,
one = alloc_filespec(concatpath);
two = alloc_filespec(concatpath);
- fill_filespec(one, old_sha1, old_mode);
- fill_filespec(two, new_sha1, new_mode);
+ fill_filespec(one, old_sha1, old_sha1_valid, old_mode);
+ fill_filespec(two, new_sha1, new_sha1_valid, new_mode);
one->dirty_submodule = old_dirty_submodule;
two->dirty_submodule = new_dirty_submodule;
diff --git a/diff.h b/diff.h
index e027650..a658f85 100644
--- a/diff.h
+++ b/diff.h
@@ -19,12 +19,14 @@ typedef void (*change_fn_t)(struct diff_options *options,
unsigned old_mode, unsigned new_mode,
const unsigned char *old_sha1,
const unsigned char *new_sha1,
+ int old_sha1_valid, int new_sha1_valid,
const char *fullpath,
unsigned old_dirty_submodule, unsigned new_dirty_submodule);
typedef void (*add_remove_fn_t)(struct diff_options *options,
int addremove, unsigned mode,
const unsigned char *sha1,
+ int sha1_valid,
const char *fullpath, unsigned dirty_submodule);
typedef void (*diff_format_fn_t)(struct diff_queue_struct *q,
@@ -214,12 +216,15 @@ extern void diff_addremove(struct diff_options *,
int addremove,
unsigned mode,
const unsigned char *sha1,
+ int sha1_valid,
const char *fullpath, unsigned dirty_submodule);
extern void diff_change(struct diff_options *,
unsigned mode1, unsigned mode2,
const unsigned char *sha1,
const unsigned char *sha2,
+ int sha1_valid,
+ int sha2_valid,
const char *fullpath,
unsigned dirty_submodule1, unsigned dirty_submodule2);
@@ -238,10 +243,9 @@ extern int parse_long_opt(const char *opt, const char **argv,
extern int git_diff_basic_config(const char *var, const char *value, void *cb);
extern int git_diff_ui_config(const char *var, const char *value, void *cb);
-extern int diff_use_color_default;
extern void diff_setup(struct diff_options *);
extern int diff_opt_parse(struct diff_options *, const char **, int);
-extern int diff_setup_done(struct diff_options *);
+extern void diff_setup_done(struct diff_options *);
#define DIFF_DETECT_RENAME 1
#define DIFF_DETECT_COPY 2
diff --git a/diffcore-rename.c b/diffcore-rename.c
index 216a7a4..512d0ac 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -48,7 +48,7 @@ static struct diff_rename_dst *locate_rename_dst(struct diff_filespec *two,
memmove(rename_dst + first + 1, rename_dst + first,
(rename_dst_nr - first - 1) * sizeof(*rename_dst));
rename_dst[first].two = alloc_filespec(two->path);
- fill_filespec(rename_dst[first].two, two->sha1, two->mode);
+ fill_filespec(rename_dst[first].two, two->sha1, two->sha1_valid, two->mode);
rename_dst[first].pair = NULL;
return &(rename_dst[first]);
}
diff --git a/diffcore.h b/diffcore.h
index be0739c..1c16c85 100644
--- a/diffcore.h
+++ b/diffcore.h
@@ -55,7 +55,7 @@ struct diff_filespec {
extern struct diff_filespec *alloc_filespec(const char *);
extern void free_filespec(struct diff_filespec *);
extern void fill_filespec(struct diff_filespec *, const unsigned char *,
- unsigned short);
+ int, unsigned short);
extern int diff_populate_filespec(struct diff_filespec *, int);
extern void diff_free_filespec_data(struct diff_filespec *);
diff --git a/dir.c b/dir.c
index 240bf0c..4868339 100644
--- a/dir.c
+++ b/dir.c
@@ -397,6 +397,8 @@ int add_excludes_from_file_to_list(const char *fname,
fd = open(fname, O_RDONLY);
if (fd < 0 || fstat(fd, &st) < 0) {
+ if (errno != ENOENT)
+ warn_on_inaccessible(fname);
if (0 <= fd)
close(fd);
if (!check_index ||
@@ -1311,9 +1313,9 @@ void setup_standard_excludes(struct dir_struct *dir)
home_config_paths(NULL, &xdg_path, "ignore");
excludes_file = xdg_path;
}
- if (!access(path, R_OK))
+ if (!access_or_warn(path, R_OK))
add_excludes_from_file(dir, path);
- if (excludes_file && !access(excludes_file, R_OK))
+ if (excludes_file && !access_or_warn(excludes_file, R_OK))
add_excludes_from_file(dir, excludes_file);
}
diff --git a/fast-import.c b/fast-import.c
index eed97c8..c2a814e 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -1691,7 +1691,7 @@ static int update_branch(struct branch *b)
return error("Branch %s is missing commits.", b->name);
}
- if (!in_merge_bases(old_cmit, &new_cmit, 1)) {
+ if (!in_merge_bases(old_cmit, new_cmit)) {
unlock_ref(lock);
warning("Not updating %s"
" (new tip %s does not contain %s)",
diff --git a/fetch-pack.h b/fetch-pack.h
index 7c2069c..cb14871 100644
--- a/fetch-pack.h
+++ b/fetch-pack.h
@@ -1,6 +1,8 @@
#ifndef FETCH_PACK_H
#define FETCH_PACK_H
+#include "string-list.h"
+
struct fetch_pack_args {
const char *uploadpack;
int unpacklimit;
@@ -17,12 +19,18 @@ struct fetch_pack_args {
stateless_rpc:1;
};
+/*
+ * sought contains the full names of remote references that should be
+ * updated from. On return, the names that were found on the remote
+ * will have been removed from the list. The util members of the
+ * string_list_items are used internally; they must be NULL on entry
+ * (and will be NULL on exit).
+ */
struct ref *fetch_pack(struct fetch_pack_args *args,
- int fd[], struct child_process *conn,
- const struct ref *ref,
- const char *dest,
- int nr_heads,
- char **heads,
- char **pack_lockfile);
+ int fd[], struct child_process *conn,
+ const struct ref *ref,
+ const char *dest,
+ struct string_list *sought,
+ char **pack_lockfile);
#endif
diff --git a/fsck.c b/fsck.c
index 4c63b2c..7395ef6 100644
--- a/fsck.c
+++ b/fsck.c
@@ -139,6 +139,7 @@ static int verify_ordered(unsigned mode1, const char *name1, unsigned mode2, con
static int fsck_tree(struct tree *item, int strict, fsck_error error_func)
{
int retval;
+ int has_null_sha1 = 0;
int has_full_path = 0;
int has_empty_name = 0;
int has_zero_pad = 0;
@@ -157,9 +158,12 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func)
while (desc.size) {
unsigned mode;
const char *name;
+ const unsigned char *sha1;
- tree_entry_extract(&desc, &name, &mode);
+ sha1 = tree_entry_extract(&desc, &name, &mode);
+ if (is_null_sha1(sha1))
+ has_null_sha1 = 1;
if (strchr(name, '/'))
has_full_path = 1;
if (!*name)
@@ -207,6 +211,8 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func)
}
retval = 0;
+ if (has_null_sha1)
+ retval += error_func(&item->object, FSCK_WARN, "contains entries pointing to null sha1");
if (has_full_path)
retval += error_func(&item->object, FSCK_WARN, "contains full pathnames");
if (has_empty_name)
diff --git a/gettext.c b/gettext.c
index f75bca7..71e9545 100644
--- a/gettext.c
+++ b/gettext.c
@@ -4,6 +4,8 @@
#include "git-compat-util.h"
#include "gettext.h"
+#include "strbuf.h"
+#include "utf8.h"
#ifndef NO_GETTEXT
# include <locale.h>
@@ -27,10 +29,9 @@ int use_gettext_poison(void)
#endif
#ifndef NO_GETTEXT
+static const char *charset;
static void init_gettext_charset(const char *domain)
{
- const char *charset;
-
/*
This trick arranges for messages to be emitted in the user's
requested encoding, but avoids setting LC_CTYPE from the
@@ -128,4 +129,14 @@ void git_setup_gettext(void)
init_gettext_charset("git");
textdomain("git");
}
+
+/* return the number of columns of string 's' in current locale */
+int gettext_width(const char *s)
+{
+ static int is_utf8 = -1;
+ if (is_utf8 == -1)
+ is_utf8 = !strcmp(charset, "UTF-8");
+
+ return is_utf8 ? utf8_strwidth(s) : strlen(s);
+}
#endif
diff --git a/gettext.h b/gettext.h
index 57ba8bb..7671d09 100644
--- a/gettext.h
+++ b/gettext.h
@@ -30,10 +30,15 @@
#ifndef NO_GETTEXT
extern void git_setup_gettext(void);
+extern int gettext_width(const char *s);
#else
static inline void git_setup_gettext(void)
{
}
+static inline int gettext_width(const char *s)
+{
+ return strlen(s);
+}
#endif
#ifdef GETTEXT_POISON
@@ -44,6 +49,8 @@ extern int use_gettext_poison(void);
static inline FORMAT_PRESERVING(1) const char *_(const char *msgid)
{
+ if (!*msgid)
+ return "";
return use_gettext_poison() ? "# GETTEXT POISON #" : gettext(msgid);
}
diff --git a/git-am.sh b/git-am.sh
index bd9620c..c682d34 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -855,8 +855,8 @@ did you forget to use 'git add'?"
eval_gettextln 'Patch failed at $msgnum $FIRSTLINE'
if test "$(git config --bool advice.amworkdir)" != false
then
- eval_gettextln "The copy of the patch that failed is found in:
- $dotest/patch"
+ eval_gettextln 'The copy of the patch that failed is found in:
+ $dotest/patch'
fi
stop_here_user_resolve $this
fi
diff --git a/git-compat-util.h b/git-compat-util.h
index 35b095e..2fbf1fd 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -74,7 +74,8 @@
# define _XOPEN_SOURCE 500
# endif
#elif !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__USLC__) && \
- !defined(_M_UNIX) && !defined(__sgi) && !defined(__DragonFly__)
+ !defined(_M_UNIX) && !defined(__sgi) && !defined(__DragonFly__) && \
+ !defined(__TANDEM)
#define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */
#define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */
#endif
@@ -98,6 +99,9 @@
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
+#ifdef __TANDEM /* or HAVE_STRINGS_H or !NO_STRINGS_H? */
+#include <strings.h> /* for strcasecmp() */
+#endif
#include <errno.h>
#include <limits.h>
#include <sys/param.h>
@@ -141,6 +145,17 @@
#else
#include <stdint.h>
#endif
+#ifdef NO_INTPTR_T
+/*
+ * On I16LP32, ILP32 and LP64 "long" is the save bet, however
+ * on LLP86, IL33LLP64 and P64 it needs to be "long long",
+ * while on IP16 and IP16L32 it is "int" (resp. "short")
+ * Size needs to match (or exceed) 'sizeof(void *)'.
+ * We can't take "long long" here as not everybody has it.
+ */
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+#endif
#if defined(__CYGWIN__)
#undef _XOPEN_SOURCE
#include <grp.h>
@@ -162,6 +177,22 @@
#define probe_utf8_pathname_composition(a,b)
#endif
+#ifdef MKDIR_WO_TRAILING_SLASH
+#define mkdir(a,b) compat_mkdir_wo_trailing_slash((a),(b))
+extern int compat_mkdir_wo_trailing_slash(const char*, mode_t);
+#endif
+
+#ifdef NO_STRUCT_ITIMERVAL
+struct itimerval {
+ struct timeval it_interval;
+ struct timeval it_value;
+}
+#endif
+
+#ifdef NO_SETITIMER
+#define setitimer(which,value,ovalue)
+#endif
+
#ifndef NO_LIBGEN_H
#include <libgen.h>
#else
@@ -604,6 +635,12 @@ int rmdir_or_warn(const char *path);
*/
int remove_or_warn(unsigned int mode, const char *path);
+/* Call access(2), but warn for any error besides ENOENT. */
+int access_or_warn(const char *path, int mode);
+
+/* Warn on an inaccessible file that ought to be accessible */
+void warn_on_inaccessible(const char *path);
+
/* Get the passwd entry for the UID of the current process. */
struct passwd *xgetpwuid_self(void);
diff --git a/git-cvsimport.perl b/git-cvsimport.perl
index 8d41610..8032f23 100755
--- a/git-cvsimport.perl
+++ b/git-cvsimport.perl
@@ -889,10 +889,37 @@ sub commit {
$xtag =~ s/\s+\*\*.*$//; # Remove stuff like ** INVALID ** and ** FUNKY **
$xtag =~ tr/_/\./ if ( $opt_u );
$xtag =~ s/[\/]/$opt_s/g;
- $xtag =~ s/\[//g;
- system('git' , 'tag', '-f', $xtag, $cid) == 0
- or die "Cannot create tag $xtag: $!\n";
+ # See refs.c for these rules.
+ # Tag cannot contain bad chars. (See bad_ref_char in refs.c.)
+ $xtag =~ s/[ ~\^:\\\*\?\[]//g;
+ # Other bad strings for tags:
+ # (See check_refname_component in refs.c.)
+ 1 while $xtag =~ s/
+ (?: \.\. # Tag cannot contain '..'.
+ | \@{ # Tag cannot contain '@{'.
+ | ^ - # Tag cannot begin with '-'.
+ | \.lock $ # Tag cannot end with '.lock'.
+ | ^ \. # Tag cannot begin...
+ | \. $ # ...or end with '.'
+ )//xg;
+ # Tag cannot be empty.
+ if ($xtag eq '') {
+ warn("warning: ignoring tag '$tag'",
+ " with invalid tagname\n");
+ return;
+ }
+
+ if (system('git' , 'tag', '-f', $xtag, $cid) != 0) {
+ # We did our best to sanitize the tag, but still failed
+ # for whatever reason. Bail out, and give the user
+ # enough information to understand if/how we should
+ # improve the translation in the future.
+ if ($tag ne $xtag) {
+ print "Translated '$tag' tag to '$xtag'\n";
+ }
+ die "Cannot create tag $xtag: $!\n";
+ }
print "Created tag '$xtag' on '$branch'\n" if $opt_v;
}
diff --git a/git-difftool.perl b/git-difftool.perl
index c079854..edd0493 100755
--- a/git-difftool.perl
+++ b/git-difftool.perl
@@ -18,17 +18,11 @@ use File::Copy;
use File::Compare;
use File::Find;
use File::stat;
-use File::Path qw(mkpath);
+use File::Path qw(mkpath rmtree);
use File::Temp qw(tempdir);
use Getopt::Long qw(:config pass_through);
use Git;
-my @tools;
-my @working_tree;
-my $rc;
-my $repo = Git->repository();
-my $repo_path = $repo->repo_path();
-
sub usage
{
my $exitcode = shift;
@@ -45,6 +39,8 @@ USAGE
sub find_worktree
{
+ my ($repo) = @_;
+
# Git->repository->wc_path() does not honor changes to the working
# tree location made by $ENV{GIT_WORK_TREE} or the 'core.worktree'
# config variable.
@@ -63,10 +59,9 @@ sub find_worktree
return $worktree;
}
-my $workdir = find_worktree();
-
sub filter_tool_scripts
{
+ my ($tools) = @_;
if (-d $_) {
if ($_ ne ".") {
# Ignore files in subdirectories
@@ -74,17 +69,17 @@ sub filter_tool_scripts
}
} else {
if ((-f $_) && ($_ ne "defaults")) {
- push(@tools, $_);
+ push(@$tools, $_);
}
}
}
sub print_tool_help
{
- my ($cmd, @found, @notfound);
+ my ($cmd, @found, @notfound, @tools);
my $gitpath = Git::exec_path();
- find(\&filter_tool_scripts, "$gitpath/mergetools");
+ find(sub { filter_tool_scripts(\@tools) }, "$gitpath/mergetools");
foreach my $tool (@tools) {
$cmd = "TOOL_MODE=diff";
@@ -98,34 +93,52 @@ sub print_tool_help
}
}
- print "'git difftool --tool=<tool>' may be set to one of the following:\n";
+ print << 'EOF';
+'git difftool --tool=<tool>' may be set to one of the following:
+EOF
print "\t$_\n" for (sort(@found));
- print "\nThe following tools are valid, but not currently available:\n";
+ print << 'EOF';
+
+The following tools are valid, but not currently available:
+EOF
print "\t$_\n" for (sort(@notfound));
- print "\nNOTE: Some of the tools listed above only work in a windowed\n";
- print "environment. If run in a terminal-only session, they will fail.\n";
+ print << 'EOF';
+NOTE: Some of the tools listed above only work in a windowed
+environment. If run in a terminal-only session, they will fail.
+EOF
exit(0);
}
+sub exit_cleanup
+{
+ my ($tmpdir, $status) = @_;
+ my $errno = $!;
+ rmtree($tmpdir);
+ if ($status and $errno) {
+ my ($package, $file, $line) = caller();
+ warn "$file line $line: $errno\n";
+ }
+ exit($status | ($status >> 8));
+}
+
sub setup_dir_diff
{
+ my ($repo, $workdir, $symlinks) = @_;
+
# Run the diff; exit immediately if no diff found
# 'Repository' and 'WorkingCopy' must be explicitly set to insure that
# if $GIT_DIR and $GIT_WORK_TREE are set in ENV, they are actually used
# by Git->repository->command*.
- my $diffrepo = Git->repository(Repository => $repo_path, WorkingCopy => $workdir);
- my $diffrtn = $diffrepo->command_oneline('diff', '--raw', '--no-abbrev', '-z', @ARGV);
- exit(0) if (length($diffrtn) == 0);
+ my $repo_path = $repo->repo_path();
+ my %repo_args = (Repository => $repo_path, WorkingCopy => $workdir);
+ my $diffrepo = Git->repository(%repo_args);
- # Setup temp directories
- my $tmpdir = tempdir('git-diffall.XXXXX', CLEANUP => 1, TMPDIR => 1);
- my $ldir = "$tmpdir/left";
- my $rdir = "$tmpdir/right";
- mkpath($ldir) or die $!;
- mkpath($rdir) or die $!;
+ my @gitargs = ('diff', '--raw', '--no-abbrev', '-z', @ARGV);
+ my $diffrtn = $diffrepo->command_oneline(@gitargs);
+ exit(0) unless defined($diffrtn);
# Build index info for left and right sides of the diff
my $submodule_mode = '160000';
@@ -136,16 +149,21 @@ sub setup_dir_diff
my $rindex = '';
my %submodule;
my %symlink;
+ my @working_tree = ();
my @rawdiff = split('\0', $diffrtn);
my $i = 0;
while ($i < $#rawdiff) {
if ($rawdiff[$i] =~ /^::/) {
- print "Combined diff formats ('-c' and '--cc') are not supported in directory diff mode.\n";
+ warn << 'EOF';
+Combined diff formats ('-c' and '--cc') are not supported in
+directory diff mode ('-d' and '--dir-diff').
+EOF
exit(1);
}
- my ($lmode, $rmode, $lsha1, $rsha1, $status) = split(' ', substr($rawdiff[$i], 1));
+ my ($lmode, $rmode, $lsha1, $rsha1, $status) =
+ split(' ', substr($rawdiff[$i], 1));
my $src_path = $rawdiff[$i + 1];
my $dst_path;
@@ -157,7 +175,7 @@ sub setup_dir_diff
$i += 2;
}
- if (($lmode eq $submodule_mode) or ($rmode eq $submodule_mode)) {
+ if ($lmode eq $submodule_mode or $rmode eq $submodule_mode) {
$submodule{$src_path}{left} = $lsha1;
if ($lsha1 ne $rsha1) {
$submodule{$dst_path}{right} = $rsha1;
@@ -168,14 +186,16 @@ sub setup_dir_diff
}
if ($lmode eq $symlink_mode) {
- $symlink{$src_path}{left} = $diffrepo->command_oneline('show', "$lsha1");
+ $symlink{$src_path}{left} =
+ $diffrepo->command_oneline('show', "$lsha1");
}
if ($rmode eq $symlink_mode) {
- $symlink{$dst_path}{right} = $diffrepo->command_oneline('show', "$rsha1");
+ $symlink{$dst_path}{right} =
+ $diffrepo->command_oneline('show', "$rsha1");
}
- if (($lmode ne $null_mode) and ($status !~ /^C/)) {
+ if ($lmode ne $null_mode and $status !~ /^C/) {
$lindex .= "$lmode $lsha1\t$src_path\0";
}
@@ -188,6 +208,13 @@ sub setup_dir_diff
}
}
+ # Setup temp directories
+ my $tmpdir = tempdir('git-difftool.XXXXX', CLEANUP => 0, TMPDIR => 1);
+ my $ldir = "$tmpdir/left";
+ my $rdir = "$tmpdir/right";
+ mkpath($ldir) or exit_cleanup($tmpdir, 1);
+ mkpath($rdir) or exit_cleanup($tmpdir, 1);
+
# If $GIT_DIR is not set prior to calling 'git update-index' and
# 'git checkout-index', then those commands will fail if difftool
# is called from a directory other than the repo root.
@@ -200,18 +227,22 @@ sub setup_dir_diff
# Populate the left and right directories based on each index file
my ($inpipe, $ctx);
$ENV{GIT_INDEX_FILE} = "$tmpdir/lindex";
- ($inpipe, $ctx) = $repo->command_input_pipe(qw/update-index -z --index-info/);
+ ($inpipe, $ctx) =
+ $repo->command_input_pipe(qw(update-index -z --index-info));
print($inpipe $lindex);
$repo->command_close_pipe($inpipe, $ctx);
- $rc = system('git', 'checkout-index', '--all', "--prefix=$ldir/");
- exit($rc | ($rc >> 8)) if ($rc != 0);
+
+ my $rc = system('git', 'checkout-index', '--all', "--prefix=$ldir/");
+ exit_cleanup($tmpdir, $rc) if $rc != 0;
$ENV{GIT_INDEX_FILE} = "$tmpdir/rindex";
- ($inpipe, $ctx) = $repo->command_input_pipe(qw/update-index -z --index-info/);
+ ($inpipe, $ctx) =
+ $repo->command_input_pipe(qw(update-index -z --index-info));
print($inpipe $rindex);
$repo->command_close_pipe($inpipe, $ctx);
+
$rc = system('git', 'checkout-index', '--all', "--prefix=$rdir/");
- exit($rc | ($rc >> 8)) if ($rc != 0);
+ exit_cleanup($tmpdir, $rc) if $rc != 0;
# If $GIT_DIR was explicitly set just for the update/checkout
# commands, then it should be unset before continuing.
@@ -223,37 +254,55 @@ sub setup_dir_diff
for my $file (@working_tree) {
my $dir = dirname($file);
unless (-d "$rdir/$dir") {
- mkpath("$rdir/$dir") or die $!;
+ mkpath("$rdir/$dir") or
+ exit_cleanup($tmpdir, 1);
+ }
+ if ($symlinks) {
+ symlink("$workdir/$file", "$rdir/$file") or
+ exit_cleanup($tmpdir, 1);
+ } else {
+ copy("$workdir/$file", "$rdir/$file") or
+ exit_cleanup($tmpdir, 1);
+
+ my $mode = stat("$workdir/$file")->mode;
+ chmod($mode, "$rdir/$file") or
+ exit_cleanup($tmpdir, 1);
}
- copy("$workdir/$file", "$rdir/$file") or die $!;
- chmod(stat("$workdir/$file")->mode, "$rdir/$file") or die $!;
}
# Changes to submodules require special treatment. This loop writes a
# temporary file to both the left and right directories to show the
# change in the recorded SHA1 for the submodule.
for my $path (keys %submodule) {
+ my $ok;
if (defined($submodule{$path}{left})) {
- write_to_file("$ldir/$path", "Subproject commit $submodule{$path}{left}");
+ $ok = write_to_file("$ldir/$path",
+ "Subproject commit $submodule{$path}{left}");
}
if (defined($submodule{$path}{right})) {
- write_to_file("$rdir/$path", "Subproject commit $submodule{$path}{right}");
+ $ok = write_to_file("$rdir/$path",
+ "Subproject commit $submodule{$path}{right}");
}
+ exit_cleanup($tmpdir, 1) if not $ok;
}
# Symbolic links require special treatment. The standard "git diff"
# shows only the link itself, not the contents of the link target.
# This loop replicates that behavior.
for my $path (keys %symlink) {
+ my $ok;
if (defined($symlink{$path}{left})) {
- write_to_file("$ldir/$path", $symlink{$path}{left});
+ $ok = write_to_file("$ldir/$path",
+ $symlink{$path}{left});
}
if (defined($symlink{$path}{right})) {
- write_to_file("$rdir/$path", $symlink{$path}{right});
+ $ok = write_to_file("$rdir/$path",
+ $symlink{$path}{right});
}
+ exit_cleanup($tmpdir, 1) if not $ok;
}
- return ($ldir, $rdir);
+ return ($ldir, $rdir, $tmpdir, @working_tree);
}
sub write_to_file
@@ -264,85 +313,141 @@ sub write_to_file
# Make sure the path to the file exists
my $dir = dirname($path);
unless (-d "$dir") {
- mkpath("$dir") or die $!;
+ mkpath("$dir") or return 0;
}
# If the file already exists in that location, delete it. This
# is required in the case of symbolic links.
- unlink("$path");
+ unlink($path);
- open(my $fh, '>', "$path") or die $!;
+ open(my $fh, '>', $path) or return 0;
print($fh $value);
close($fh);
-}
-# parse command-line options. all unrecognized options and arguments
-# are passed through to the 'git diff' command.
-my ($difftool_cmd, $dirdiff, $extcmd, $gui, $help, $prompt, $tool_help);
-GetOptions('g|gui!' => \$gui,
- 'd|dir-diff' => \$dirdiff,
- 'h' => \$help,
- 'prompt!' => \$prompt,
- 'y' => sub { $prompt = 0; },
- 't|tool:s' => \$difftool_cmd,
- 'tool-help' => \$tool_help,
- 'x|extcmd:s' => \$extcmd);
-
-if (defined($help)) {
- usage(0);
-}
-if (defined($tool_help)) {
- print_tool_help();
+ return 1;
}
-if (defined($difftool_cmd)) {
- if (length($difftool_cmd) > 0) {
- $ENV{GIT_DIFF_TOOL} = $difftool_cmd;
- } else {
- print "No <tool> given for --tool=<tool>\n";
- usage(1);
+
+sub main
+{
+ # parse command-line options. all unrecognized options and arguments
+ # are passed through to the 'git diff' command.
+ my %opts = (
+ difftool_cmd => undef,
+ dirdiff => undef,
+ extcmd => undef,
+ gui => undef,
+ help => undef,
+ prompt => undef,
+ symlinks => $^O ne 'cygwin' &&
+ $^O ne 'MSWin32' && $^O ne 'msys',
+ tool_help => undef,
+ );
+ GetOptions('g|gui!' => \$opts{gui},
+ 'd|dir-diff' => \$opts{dirdiff},
+ 'h' => \$opts{help},
+ 'prompt!' => \$opts{prompt},
+ 'y' => sub { $opts{prompt} = 0; },
+ 'symlinks' => \$opts{symlinks},
+ 'no-symlinks' => sub { $opts{symlinks} = 0; },
+ 't|tool:s' => \$opts{difftool_cmd},
+ 'tool-help' => \$opts{tool_help},
+ 'x|extcmd:s' => \$opts{extcmd});
+
+ if (defined($opts{help})) {
+ usage(0);
}
-}
-if (defined($extcmd)) {
- if (length($extcmd) > 0) {
- $ENV{GIT_DIFFTOOL_EXTCMD} = $extcmd;
- } else {
- print "No <cmd> given for --extcmd=<cmd>\n";
- usage(1);
+ if (defined($opts{tool_help})) {
+ print_tool_help();
}
-}
-if ($gui) {
- my $guitool = '';
- $guitool = Git::config('diff.guitool');
- if (length($guitool) > 0) {
- $ENV{GIT_DIFF_TOOL} = $guitool;
+ if (defined($opts{difftool_cmd})) {
+ if (length($opts{difftool_cmd}) > 0) {
+ $ENV{GIT_DIFF_TOOL} = $opts{difftool_cmd};
+ } else {
+ print "No <tool> given for --tool=<tool>\n";
+ usage(1);
+ }
+ }
+ if (defined($opts{extcmd})) {
+ if (length($opts{extcmd}) > 0) {
+ $ENV{GIT_DIFFTOOL_EXTCMD} = $opts{extcmd};
+ } else {
+ print "No <cmd> given for --extcmd=<cmd>\n";
+ usage(1);
+ }
+ }
+ if ($opts{gui}) {
+ my $guitool = Git::config('diff.guitool');
+ if (length($guitool) > 0) {
+ $ENV{GIT_DIFF_TOOL} = $guitool;
+ }
+ }
+
+ # In directory diff mode, 'git-difftool--helper' is called once
+ # to compare the a/b directories. In file diff mode, 'git diff'
+ # will invoke a separate instance of 'git-difftool--helper' for
+ # each file that changed.
+ if (defined($opts{dirdiff})) {
+ dir_diff($opts{extcmd}, $opts{symlinks});
+ } else {
+ file_diff($opts{prompt});
}
}
-# In directory diff mode, 'git-difftool--helper' is called once
-# to compare the a/b directories. In file diff mode, 'git diff'
-# will invoke a separate instance of 'git-difftool--helper' for
-# each file that changed.
-if (defined($dirdiff)) {
- my ($a, $b) = setup_dir_diff();
+sub dir_diff
+{
+ my ($extcmd, $symlinks) = @_;
+ my $rc;
+ my $error = 0;
+ my $repo = Git->repository();
+ my $workdir = find_worktree($repo);
+ my ($a, $b, $tmpdir, @worktree) =
+ setup_dir_diff($repo, $workdir, $symlinks);
+
if (defined($extcmd)) {
$rc = system($extcmd, $a, $b);
} else {
$ENV{GIT_DIFFTOOL_DIRDIFF} = 'true';
$rc = system('git', 'difftool--helper', $a, $b);
}
-
- exit($rc | ($rc >> 8)) if ($rc != 0);
-
# If the diff including working copy files and those
# files were modified during the diff, then the changes
- # should be copied back to the working tree
- for my $file (@working_tree) {
- if (-e "$b/$file" && compare("$b/$file", "$workdir/$file")) {
- copy("$b/$file", "$workdir/$file") or die $!;
- chmod(stat("$b/$file")->mode, "$workdir/$file") or die $!;
+ # should be copied back to the working tree.
+ # Do not copy back files when symlinks are used and the
+ # external tool did not replace the original link with a file.
+ for my $file (@worktree) {
+ next if $symlinks && -l "$b/$file";
+ next if ! -f "$b/$file";
+
+ my $diff = compare("$b/$file", "$workdir/$file");
+ if ($diff == 0) {
+ next;
+ } elsif ($diff == -1) {
+ my $errmsg = "warning: Could not compare ";
+ $errmsg += "'$b/$file' with '$workdir/$file'\n";
+ warn $errmsg;
+ $error = 1;
+ } elsif ($diff == 1) {
+ my $mode = stat("$b/$file")->mode;
+ copy("$b/$file", "$workdir/$file") or
+ exit_cleanup($tmpdir, 1);
+
+ chmod($mode, "$workdir/$file") or
+ exit_cleanup($tmpdir, 1);
}
}
-} else {
+ if ($error) {
+ warn "warning: Temporary files exist in '$tmpdir'.\n";
+ warn "warning: You may want to cleanup or recover these.\n";
+ exit(1);
+ } else {
+ exit_cleanup($tmpdir, $rc);
+ }
+}
+
+sub file_diff
+{
+ my ($prompt) = @_;
+
if (defined($prompt)) {
if ($prompt) {
$ENV{GIT_DIFFTOOL_PROMPT} = 'true';
@@ -362,3 +467,5 @@ if (defined($dirdiff)) {
my $rc = system('git', 'diff', @ARGV);
exit($rc | ($rc >> 8));
}
+
+main();
diff --git a/git-gui/GIT-VERSION-GEN b/git-gui/GIT-VERSION-GEN
index 6570943..49b62ea 100755
--- a/git-gui/GIT-VERSION-GEN
+++ b/git-gui/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=0.16.GITGUI
+DEF_VER=0.17.GITGUI
LF='
'
diff --git a/git-gui/git-gui.sh b/git-gui/git-gui.sh
index ba4e5c1..89f636f 100755
--- a/git-gui/git-gui.sh
+++ b/git-gui/git-gui.sh
@@ -154,6 +154,7 @@ set _trace [lsearch -exact $argv --trace]
if {$_trace >= 0} {
set argv [lreplace $argv $_trace $_trace]
set _trace 1
+ if {[tk windowingsystem] eq "win32"} { console show }
} else {
set _trace 0
}
@@ -1463,7 +1464,7 @@ proc rescan {after {honor_trustmtime 1}} {
(![$ui_comm edit modified]
|| [string trim [$ui_comm get 0.0 end]] eq {})} {
if {[string match amend* $commit_type]} {
- } elseif {[load_message GITGUI_MSG]} {
+ } elseif {[load_message GITGUI_MSG utf-8]} {
} elseif {[run_prepare_commit_msg_hook]} {
} elseif {[load_message MERGE_MSG]} {
} elseif {[load_message SQUASH_MSG]} {
@@ -1549,7 +1550,7 @@ proc rescan_stage2 {fd after} {
fileevent $fd_lo readable [list read_ls_others $fd_lo $after]
}
-proc load_message {file} {
+proc load_message {file {encoding {}}} {
global ui_comm
set f [gitdir $file]
@@ -1558,6 +1559,9 @@ proc load_message {file} {
return 0
}
fconfigure $fd -eofchar {}
+ if {$encoding ne {}} {
+ fconfigure $fd -encoding $encoding
+ }
set content [string trim [read $fd]]
close $fd
regsub -all -line {[ \r\t]+$} $content {} content
@@ -2266,6 +2270,7 @@ proc do_quit {{rc {1}}} {
&& $msg ne {}} {
catch {
set fd [open $save w]
+ fconfigure $fd -encoding utf-8
puts -nonewline $fd $msg
close $fd
}
@@ -2998,10 +3003,19 @@ blame {
set jump_spec {}
set is_path 0
foreach a $argv {
- if {$is_path || [file exists $_prefix$a]} {
+ if {[file exists $a]} {
+ if {$path ne {}} usage
+ set path [normalize_relpath $a]
+ break
+ } elseif {[file exists $_prefix$a]} {
if {$path ne {}} usage
set path [normalize_relpath $_prefix$a]
break
+ }
+
+ if {$is_path} {
+ if {$path ne {}} usage
+ break
} elseif {$a eq {--}} {
if {$path ne {}} {
if {$head ne {}} usage
@@ -3023,8 +3037,13 @@ blame {
unset is_path
if {$head ne {} && $path eq {}} {
- set path [normalize_relpath $_prefix$head]
- set head {}
+ if {[string index $head 0] eq {/}} {
+ set path [normalize_relpath $head]
+ set head {}
+ } else {
+ set path [normalize_relpath $_prefix$head]
+ set head {}
+ }
}
if {$head eq {}} {
@@ -3710,6 +3729,8 @@ bind $ui_diff <$M1B-Key-v> {break}
bind $ui_diff <$M1B-Key-V> {break}
bind $ui_diff <$M1B-Key-a> {%W tag add sel 0.0 end;break}
bind $ui_diff <$M1B-Key-A> {%W tag add sel 0.0 end;break}
+bind $ui_diff <$M1B-Key-j> {do_revert_selection;break}
+bind $ui_diff <$M1B-Key-J> {do_revert_selection;break}
bind $ui_diff <Key-Up> {catch {%W yview scroll -1 units};break}
bind $ui_diff <Key-Down> {catch {%W yview scroll 1 units};break}
bind $ui_diff <Key-Left> {catch {%W xview scroll -1 units};break}
@@ -3742,6 +3763,8 @@ bind . <$M1B-Key-s> do_signoff
bind . <$M1B-Key-S> do_signoff
bind . <$M1B-Key-t> do_add_selection
bind . <$M1B-Key-T> do_add_selection
+bind . <$M1B-Key-u> do_unstage_selection
+bind . <$M1B-Key-U> do_unstage_selection
bind . <$M1B-Key-j> do_revert_selection
bind . <$M1B-Key-J> do_revert_selection
bind . <$M1B-Key-i> do_add_all
@@ -3835,7 +3858,7 @@ if {[is_enabled transport]} {
}
if {[winfo exists $ui_comm]} {
- set GITGUI_BCK_exists [load_message GITGUI_BCK]
+ set GITGUI_BCK_exists [load_message GITGUI_BCK utf-8]
# -- If both our backup and message files exist use the
# newer of the two files to initialize the buffer.
@@ -3872,6 +3895,7 @@ if {[winfo exists $ui_comm]} {
} elseif {$m} {
catch {
set fd [open [gitdir GITGUI_BCK] w]
+ fconfigure $fd -encoding utf-8
puts -nonewline $fd $msg
close $fd
set GITGUI_BCK_exists 1
diff --git a/git-gui/lib/commit.tcl b/git-gui/lib/commit.tcl
index 0d81432..864b687 100644
--- a/git-gui/lib/commit.tcl
+++ b/git-gui/lib/commit.tcl
@@ -268,7 +268,7 @@ proc commit_commitmsg {curHEAD msg_p} {
&& [is_config_true gui.warndetachedcommit]} {
set msg [mc "You are about to commit on a detached head.\
This is a potentially dangerous thing to do because if you switch\
-to another branch you will loose your changes and it can be difficult\
+to another branch you will lose your changes and it can be difficult\
to retrieve them later from the reflog. You should probably cancel this\
commit and create a new branch to continue.\n\
\n\
@@ -409,6 +409,7 @@ A rescan will be automatically started now.
catch {file delete [gitdir MERGE_MSG]}
catch {file delete [gitdir SQUASH_MSG]}
catch {file delete [gitdir GITGUI_MSG]}
+ catch {file delete [gitdir CHERRY_PICK_HEAD]}
# -- Let rerere do its thing.
#
diff --git a/git-gui/lib/status_bar.tcl b/git-gui/lib/status_bar.tcl
index 95cb449..02111a1 100644
--- a/git-gui/lib/status_bar.tcl
+++ b/git-gui/lib/status_bar.tcl
@@ -77,6 +77,7 @@ method start {msg uds} {
method update {have total} {
set pdone 0
+ set cdone 0
if {$total > 0} {
set pdone [expr {100 * $have / $total}]
set cdone [expr {[winfo width $w_c] * $have / $total}]
diff --git a/git-gui/macosx/AppMain.tcl b/git-gui/macosx/AppMain.tcl
index ddbe633..738bdd0 100644
--- a/git-gui/macosx/AppMain.tcl
+++ b/git-gui/macosx/AppMain.tcl
@@ -12,7 +12,9 @@ if {[file tail [lindex $argv 0]] eq {gitk}} {
} else {
set argv0 [file join $gitexecdir [file tail [lindex $argv 0]]]
set AppMain_source [file join $gitguilib git-gui.tcl]
- if {[pwd] eq {/}} {
+ if {[info exists env(PWD)]} {
+ cd $env(PWD)
+ } elseif {[pwd] eq {/}} {
cd $env(HOME)
}
}
diff --git a/git-gui/po/de.po b/git-gui/po/de.po
index 44c5ddc..baebff2 100644
--- a/git-gui/po/de.po
+++ b/git-gui/po/de.po
@@ -72,7 +72,7 @@ msgstr ""
#: git-gui.sh:1154
msgid "Cannot use bare repository:"
-msgstr "Leeres Projektarchiv kann nicht benutzt werden:"
+msgstr "Bloßes Projektarchiv kann nicht benutzt werden:"
#: git-gui.sh:1162
msgid "No working directory"
@@ -88,7 +88,7 @@ msgstr "Nach geänderten Dateien suchen..."
#: git-gui.sh:1454
msgid "Calling prepare-commit-msg hook..."
-msgstr "Aufrufen der Eintragen-Vorbereiten-Kontrolle..."
+msgstr "Aufrufen der Eintragen-Vorbereiten-Kontrolle (»prepare-commit hook«)..."
#: git-gui.sh:1471
msgid "Commit declined by prepare-commit-msg hook."
@@ -188,7 +188,7 @@ msgstr "Zusammenführen"
#: git-gui.sh:2465 lib/choose_rev.tcl:557
msgid "Remote"
-msgstr "Andere Archive"
+msgstr "Externe Archive"
#: git-gui.sh:2468
msgid "Tools"
@@ -478,7 +478,7 @@ msgs