summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Documentation/Makefile32
-rw-r--r--Documentation/RelNotes-1.5.4.7.txt10
-rw-r--r--Documentation/RelNotes-1.5.5.6.txt10
-rw-r--r--Documentation/RelNotes-1.5.6.6.txt10
-rw-r--r--Documentation/RelNotes-1.6.0.3.txt36
-rw-r--r--Documentation/RelNotes-1.6.0.4.txt39
-rw-r--r--Documentation/RelNotes-1.6.0.5.txt56
-rw-r--r--Documentation/RelNotes-1.6.0.6.txt33
-rw-r--r--Documentation/RelNotes-1.6.1.1.txt49
-rw-r--r--Documentation/RelNotes-1.6.1.txt158
-rw-r--r--Documentation/RelNotes-1.6.2.txt65
-rw-r--r--Documentation/SubmittingPatches30
-rw-r--r--Documentation/asciidoc.conf23
-rw-r--r--Documentation/blame-options.txt7
-rwxr-xr-xDocumentation/cat-texi.perl8
-rw-r--r--Documentation/config.txt227
-rw-r--r--Documentation/diff-format.txt16
-rw-r--r--Documentation/diff-generate-patch.txt6
-rw-r--r--Documentation/diff-options.txt25
-rw-r--r--Documentation/git-add.txt13
-rw-r--r--Documentation/git-bisect.txt27
-rw-r--r--Documentation/git-check-attr.txt61
-rw-r--r--Documentation/git-checkout.txt5
-rw-r--r--Documentation/git-cherry-pick.txt13
-rw-r--r--Documentation/git-cherry.txt3
-rw-r--r--Documentation/git-clone.txt5
-rw-r--r--Documentation/git-commit.txt12
-rw-r--r--Documentation/git-config.txt2
-rw-r--r--Documentation/git-daemon.txt13
-rw-r--r--Documentation/git-describe.txt11
-rw-r--r--Documentation/git-diff-files.txt5
-rw-r--r--Documentation/git-diff-tree.txt4
-rw-r--r--Documentation/git-diff.txt1
-rw-r--r--Documentation/git-fast-export.txt8
-rw-r--r--Documentation/git-filter-branch.txt18
-rw-r--r--Documentation/git-format-patch.txt3
-rw-r--r--Documentation/git-fsck.txt3
-rw-r--r--Documentation/git-gui.txt19
-rw-r--r--Documentation/git-log.txt4
-rw-r--r--Documentation/git-ls-files.txt2
-rw-r--r--Documentation/git-ls-tree.txt10
-rw-r--r--Documentation/git-mailinfo.txt2
-rw-r--r--Documentation/git-merge-base.txt19
-rw-r--r--Documentation/git-merge-file.txt12
-rw-r--r--Documentation/git-merge-index.txt6
-rw-r--r--Documentation/git-merge-tree.txt6
-rw-r--r--Documentation/git-merge.txt34
-rw-r--r--Documentation/git-mergetool.txt19
-rw-r--r--Documentation/git-pack-objects.txt7
-rw-r--r--Documentation/git-push.txt4
-rw-r--r--Documentation/git-rebase.txt138
-rw-r--r--Documentation/git-receive-pack.txt4
-rw-r--r--Documentation/git-reflog.txt4
-rw-r--r--Documentation/git-remote.txt10
-rw-r--r--Documentation/git-repack.txt11
-rw-r--r--Documentation/git-reset.txt37
-rw-r--r--Documentation/git-revert.txt8
-rw-r--r--Documentation/git-send-email.txt29
-rw-r--r--Documentation/git-shortlog.txt40
-rw-r--r--Documentation/git-show-branch.txt4
-rw-r--r--Documentation/git-stage.txt19
-rw-r--r--Documentation/git-submodule.txt2
-rw-r--r--Documentation/git-svn.txt4
-rw-r--r--Documentation/git-tag.txt4
-rw-r--r--Documentation/git-update-index.txt8
-rw-r--r--Documentation/git.txt22
-rw-r--r--Documentation/gitattributes.txt93
-rw-r--r--Documentation/gitcore-tutorial.txt34
-rw-r--r--Documentation/gitglossary.txt6
-rw-r--r--Documentation/githooks.txt8
-rw-r--r--Documentation/gitk.txt9
-rw-r--r--Documentation/gitrepository-layout.txt3
-rw-r--r--Documentation/gittutorial-2.txt16
-rw-r--r--Documentation/gittutorial.txt14
-rw-r--r--Documentation/gitworkflows.txt364
-rw-r--r--Documentation/glossary-content.txt3
-rw-r--r--Documentation/howto/rebase-from-internal-branch.txt2
-rw-r--r--Documentation/howto/revert-a-faulty-merge.txt179
-rw-r--r--Documentation/i18n.txt10
-rw-r--r--Documentation/merge-config.txt18
-rw-r--r--Documentation/merge-options.txt10
-rw-r--r--Documentation/pretty-formats.txt6
-rw-r--r--Documentation/pretty-options.txt2
-rw-r--r--Documentation/rev-list-options.txt81
-rw-r--r--Documentation/technical/api-strbuf.txt18
-rw-r--r--Documentation/technical/racy-git.txt2
-rw-r--r--Documentation/urls-remotes.txt19
-rw-r--r--Documentation/user-manual.txt43
-rw-r--r--INSTALL8
-rw-r--r--Makefile70
-rw-r--r--README2
l---------RelNotes2
-rw-r--r--abspath.c2
-rw-r--r--archive.c2
-rw-r--r--branch.c5
-rw-r--r--builtin-add.c30
-rw-r--r--builtin-apply.c14
-rw-r--r--builtin-archive.c2
-rw-r--r--builtin-blame.c228
-rw-r--r--builtin-branch.c70
-rw-r--r--builtin-cat-file.c2
-rw-r--r--builtin-check-attr.c109
-rw-r--r--builtin-checkout-index.c152
-rw-r--r--builtin-checkout.c25
-rw-r--r--builtin-clone.c113
-rw-r--r--builtin-commit.c63
-rw-r--r--builtin-config.c2
-rw-r--r--builtin-describe.c8
-rw-r--r--builtin-diff-files.c4
-rw-r--r--builtin-diff.c19
-rw-r--r--builtin-fast-export.c28
-rw-r--r--builtin-fetch-pack.c6
-rw-r--r--builtin-fetch.c40
-rw-r--r--builtin-for-each-ref.c6
-rw-r--r--builtin-fsck.c48
-rw-r--r--builtin-gc.c20
-rw-r--r--builtin-grep.c15
-rw-r--r--builtin-init-db.c2
-rw-r--r--builtin-log.c53
-rw-r--r--builtin-ls-files.c37
-rw-r--r--builtin-ls-remote.c2
-rw-r--r--builtin-ls-tree.c7
-rw-r--r--builtin-mailinfo.c2
-rw-r--r--builtin-merge-file.c7
-rw-r--r--builtin-merge-recursive.c2
-rw-r--r--builtin-merge.c37
-rw-r--r--builtin-mv.c1
-rw-r--r--builtin-pack-objects.c112
-rw-r--r--builtin-read-tree.c2
-rw-r--r--builtin-receive-pack.c82
-rw-r--r--builtin-reflog.c4
-rw-r--r--builtin-remote.c223
-rw-r--r--builtin-rerere.c1
-rw-r--r--builtin-reset.c28
-rw-r--r--builtin-rev-list.c2
-rw-r--r--builtin-revert.c11
-rw-r--r--builtin-rm.c52
-rw-r--r--builtin-send-pack.c32
-rw-r--r--builtin-shortlog.c28
-rw-r--r--builtin-tag.c51
-rw-r--r--builtin-unpack-objects.c2
-rw-r--r--builtin-update-index.c2
-rw-r--r--builtin-update-ref.c8
-rw-r--r--builtin-write-tree.c2
-rw-r--r--bundle.c39
-rw-r--r--cache-tree.c10
-rw-r--r--cache.h95
-rw-r--r--combine-diff.c11
-rw-r--r--commit.h2
-rw-r--r--compat/cygwin.c20
-rw-r--r--compat/mingw.c23
-rw-r--r--config.c16
-rw-r--r--config.mak.in3
-rw-r--r--configure.ac61
-rw-r--r--connect.c12
-rwxr-xr-xcontrib/completion/git-completion.bash284
-rwxr-xr-xcontrib/difftool/git-difftool74
-rwxr-xr-xcontrib/difftool/git-difftool-helper240
-rw-r--r--contrib/difftool/git-difftool.txt104
-rw-r--r--contrib/emacs/git.el337
-rw-r--r--contrib/examples/README3
-rwxr-xr-xcontrib/examples/git-remote.perl2
-rwxr-xr-xcontrib/fast-import/git-p438
-rw-r--r--contrib/hooks/post-receive-email57
-rw-r--r--contrib/hooks/pre-auto-gc-battery3
-rwxr-xr-xcontrib/stats/packinfo.pl14
-rw-r--r--contrib/vim/README12
-rwxr-xr-xcontrib/workdir/git-new-workdir2
-rw-r--r--daemon.c165
-rw-r--r--diff-lib.c40
-rw-r--r--diff.c431
-rw-r--r--diff.h2
-rw-r--r--diffcore-rename.c2
-rw-r--r--diffcore.h10
-rw-r--r--environment.c7
-rw-r--r--fast-import.c55
-rw-r--r--fsck.c2
-rwxr-xr-xgenerate-cmdlist.sh2
-rwxr-xr-xgit-add--interactive.perl76
-rwxr-xr-xgit-am.sh15
-rwxr-xr-xgit-bisect.sh25
-rwxr-xr-xgit-cvsserver.perl20
-rwxr-xr-xgit-filter-branch.sh31
-rwxr-xr-xgit-gui/GIT-VERSION-GEN2
-rw-r--r--git-gui/Makefile2
-rwxr-xr-xgit-gui/git-gui--askpass59
-rwxr-xr-xgit-gui/git-gui.sh202
-rw-r--r--git-gui/lib/blame.tcl88
-rw-r--r--git-gui/lib/choose_repository.tcl22
-rw-r--r--git-gui/lib/commit.tcl7
-rw-r--r--git-gui/lib/diff.tcl31
-rw-r--r--git-gui/lib/index.tcl11
-rw-r--r--git-gui/lib/merge.tcl1
-rw-r--r--git-gui/lib/mergetool.tcl17
-rw-r--r--git-gui/lib/option.tcl12
-rw-r--r--git-gui/lib/remote.tcl188
-rw-r--r--git-gui/lib/remote_add.tcl191
-rw-r--r--git-gui/lib/remote_branch_delete.tcl6
-rw-r--r--git-gui/lib/search.tcl198
-rw-r--r--git-gui/lib/spellcheck.tcl3
-rw-r--r--git-gui/lib/sshkey.tcl126
-rw-r--r--git-gui/lib/tools.tcl159
-rw-r--r--git-gui/lib/tools_dlg.tcl421
-rw-r--r--git-gui/lib/transport.tcl45
-rw-r--r--git-gui/po/de.po488
-rw-r--r--git-gui/po/fr.po1124
-rw-r--r--git-gui/po/git-gui.pot1108
-rw-r--r--git-gui/po/hu.po1289
-rw-r--r--git-gui/po/it.po1163
-rw-r--r--git-gui/po/ja.po1126
-rw-r--r--git-gui/po/nb.po2484
-rw-r--r--git-gui/po/sv.po1194
-rwxr-xr-xgit-lost-found.sh2
-rwxr-xr-xgit-mergetool.sh111
-rwxr-xr-xgit-pull.sh22
-rwxr-xr-xgit-rebase--interactive.sh155
-rwxr-xr-xgit-rebase.sh42
-rwxr-xr-xgit-repack.sh14
-rwxr-xr-xgit-request-pull.sh6
-rwxr-xr-xgit-send-email.perl269
-rwxr-xr-xgit-sh-setup.sh23
-rwxr-xr-xgit-submodule.sh12
-rwxr-xr-xgit-svn.perl76
-rw-r--r--git.c65
-rw-r--r--git.spec.in1
-rw-r--r--gitk-git/gitk1822
-rw-r--r--gitk-git/po/de.po637
-rw-r--r--gitk-git/po/es.po507
-rw-r--r--gitk-git/po/it.po500
-rw-r--r--gitk-git/po/sv.po448
-rw-r--r--gitweb/INSTALL21
-rwxr-xr-xgitweb/gitweb.perl792
-rw-r--r--grep.c48
-rw-r--r--grep.h1
-rw-r--r--hash-object.c2
-rw-r--r--http-push.c54
-rw-r--r--http.c11
-rw-r--r--ident.c1
-rw-r--r--imap-send.c6
-rw-r--r--index-pack.c194
-rw-r--r--interpolate.c103
-rw-r--r--interpolate.h26
-rw-r--r--levenshtein.c39
-rw-r--r--ll-merge.c21
-rw-r--r--lockfile.c30
-rw-r--r--log-tree.c10
-rw-r--r--log-tree.h2
-rw-r--r--merge-file.c1
-rw-r--r--merge-recursive.c43
-rw-r--r--pack-redundant.c8
-rw-r--r--pack-refs.c3
-rw-r--r--pack-revindex.c3
-rw-r--r--pager.c3
-rw-r--r--parse-options.c22
-rw-r--r--parse-options.h6
-rw-r--r--path.c56
-rw-r--r--perl/Git.pm33
-rw-r--r--preload-index.c100
-rw-r--r--pretty.c140
-rw-r--r--read-cache.c150
-rw-r--r--refs.c64
-rw-r--r--remote.c69
-rw-r--r--remote.h11
-rw-r--r--rerere.c51
-rw-r--r--revision.c47
-rw-r--r--revision.h3
-rw-r--r--server-info.c2
-rw-r--r--setup.c5
-rw-r--r--sha1_file.c178
-rw-r--r--sha1_name.c6
-rw-r--r--strbuf.c58
-rw-r--r--strbuf.h6
-rw-r--r--t/lib-httpd/apache.conf2
-rwxr-xr-xt/t0003-attributes.sh17
-rwxr-xr-xt/t1001-read-tree-m-2way.sh51
-rwxr-xr-xt/t1005-read-tree-reset.sh60
-rwxr-xr-xt/t1301-shared-repo.sh13
-rwxr-xr-xt/t1400-update-ref.sh18
-rwxr-xr-xt/t2005-checkout-index-symlinks.sh2
-rwxr-xr-xt/t2011-checkout-invalid-head.sh22
-rwxr-xr-xt/t2102-update-index-symlinks.sh4
-rwxr-xr-xt/t2203-add-intent.sh28
-rwxr-xr-xt/t2300-cd-to-toplevel.sh37
-rwxr-xr-xt/t3001-ls-files-others-exclude.sh6
-rwxr-xr-xt/t3200-branch.sh12
-rwxr-xr-xt/t3210-pack-refs.sh7
-rwxr-xr-xt/t3404-rebase-interactive.sh32
-rwxr-xr-xt/t3409-rebase-hook.sh16
-rwxr-xr-xt/t3409-rebase-preserve-merges.sh95
-rwxr-xr-xt/t3410-rebase-preserve-dropped-merges.sh139
-rwxr-xr-xt/t3411-rebase-preserve-around-merges.sh135
-rwxr-xr-xt/t3501-revert-cherry-pick.sh2
-rwxr-xr-xt/t3600-rm.sh30
-rwxr-xr-xt/t4012-diff-binary.sh4
-rwxr-xr-xt/t4018-diff-funcname.sh11
-rwxr-xr-xt/t4020-diff-external.sh21
-rwxr-xr-xt/t4030-diff-textconv.sh126
-rwxr-xr-xt/t4031-diff-rewrite-binary.sh67
-rwxr-xr-xt/t4032-diff-inter-hunk-context.sh92
-rwxr-xr-xt/t4128-apply-root.sh2
-rwxr-xr-xt/t4129-apply-samemode.sh62
-rwxr-xr-xt/t4252-am-options.sh53
-rw-r--r--t/t4252/am-test-1-119
-rw-r--r--t/t4252/am-test-1-221
-rw-r--r--t/t4252/am-test-2-119
-rw-r--r--t/t4252/am-test-2-221
-rw-r--r--t/t4252/am-test-3-119
-rw-r--r--t/t4252/am-test-3-221
-rw-r--r--t/t4252/am-test-4-119
-rw-r--r--t/t4252/am-test-4-222
-rw-r--r--t/t4252/file-1-07
-rw-r--r--t/t4252/file-2-07
-rwxr-xr-xt/t5000-tar-tree.sh23
-rwxr-xr-xt/t5300-pack-object.sh6
-rwxr-xr-xt/t5302-pack-index.sh106
-rwxr-xr-xt/t5303-pack-corruption-resilience.sh96
-rwxr-xr-xt/t5400-send-pack.sh13
-rwxr-xr-xt/t5405-send-pack-rewind.sh2
-rwxr-xr-xt/t5505-remote.sh64
-rwxr-xr-xt/t5510-fetch.sh12
-rwxr-xr-xt/t5516-fetch-push.sh140
-rwxr-xr-xt/t5520-pull.sh12
-rwxr-xr-xt/t5521-pull-options.sh60
-rwxr-xr-xt/t5521-pull-symlink.sh78
-rwxr-xr-xt/t5540-http-push.sh24
-rwxr-xr-xt/t5702-clone-options.sh13
-rwxr-xr-xt/t5704-bundle.sh33
-rwxr-xr-xt/t6024-recursive-merge.sh23
-rwxr-xr-xt/t6025-merge-symlinks.sh4
-rwxr-xr-xt/t6030-bisect-porcelain.sh19
-rwxr-xr-xt/t6120-describe.sh14
-rwxr-xr-xt/t7001-mv.sh25
-rwxr-xr-xt/t7002-grep.sh7
-rwxr-xr-xt/t7003-filter-branch.sh8
-rwxr-xr-xt/t7004-tag.sh11
-rwxr-xr-xt/t7007-show.sh20
-rwxr-xr-xt/t7201-co.sh26
-rwxr-xr-xt/t7400-submodule-basic.sh25
-rwxr-xr-xt/t7500-commit.sh5
-rwxr-xr-xt/t7501-commit.sh20
-rwxr-xr-xt/t7502-commit.sh8
-rwxr-xr-xt/t7502-status.sh6
-rwxr-xr-xt/t7507-commit-verbose.sh73
-rwxr-xr-xt/t7600-merge.sh40
-rwxr-xr-xt/t7607-merge-overwrite.sh87
-rwxr-xr-xt/t7700-repack.sh73
-rwxr-xr-xt/t7701-repack-unpack-unreachable.sh18
-rwxr-xr-xt/t8005-blame-i18n.sh92
-rw-r--r--t/t8005/cp1251.txt2
-rw-r--r--t/t8005/sjis.txt2
-rw-r--r--t/t8005/utf8.txt2
-rwxr-xr-xt/t9001-send-email.sh21
-rwxr-xr-xt/t9100-git-svn-basic.sh9
-rwxr-xr-xt/t9104-git-svn-follow-parent.sh42
-rwxr-xr-xt/t9128-git-svn-cmd-branch.sh19
-rwxr-xr-xt/t9129-git-svn-i18n-commitencoding.sh84
-rwxr-xr-xt/t9130-git-svn-authors-file.sh94
-rwxr-xr-xt/t9300-fast-import.sh20
-rwxr-xr-xt/t9301-fast-export.sh28
-rwxr-xr-xt/t9400-git-cvsserver-server.sh2
-rwxr-xr-xt/t9500-gitweb-standalone-no-errors.sh10
-rw-r--r--t/test-lib.sh1
-rw-r--r--test-chmtime.c91
-rw-r--r--transport.c12
-rw-r--r--transport.h2
-rw-r--r--unpack-trees.c38
-rw-r--r--userdiff.c167
-rw-r--r--userdiff.h21
-rw-r--r--walker.c2
-rw-r--r--wt-status.c59
-rw-r--r--xdiff-interface.c50
-rw-r--r--xdiff-interface.h4
-rw-r--r--xdiff/xdiff.h2
-rw-r--r--xdiff/xdiffi.c4
-rw-r--r--xdiff/xemit.c6
-rw-r--r--xdiff/xemit.h3
-rw-r--r--xdiff/xprepare.c15
378 files changed, 22516 insertions, 6539 deletions
diff --git a/.gitignore b/.gitignore
index bbaf9de0bc..d9adce585a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -118,6 +118,7 @@ git-show
git-show-branch
git-show-index
git-show-ref
+git-stage
git-stash
git-status
git-stripspace
diff --git a/Documentation/Makefile b/Documentation/Makefile
index ded0e40b97..144ec32f12 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -6,7 +6,7 @@ MAN5_TXT=gitattributes.txt gitignore.txt gitmodules.txt githooks.txt \
gitrepository-layout.txt
MAN7_TXT=gitcli.txt gittutorial.txt gittutorial-2.txt \
gitcvs-migration.txt gitcore-tutorial.txt gitglossary.txt \
- gitdiffcore.txt
+ gitdiffcore.txt gitworkflows.txt
MAN_TXT = $(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT)
MAN_XML=$(patsubst %.txt,%.xml,$(MAN_TXT))
@@ -32,6 +32,7 @@ DOC_MAN7=$(patsubst %.txt,%.7,$(MAN7_TXT))
prefix?=$(HOME)
bindir?=$(prefix)/bin
htmldir?=$(prefix)/share/doc/git-doc
+pdfdir?=$(prefix)/share/doc/git-doc
mandir?=$(prefix)/share/man
man1dir=$(mandir)/man1
man5dir=$(mandir)/man5
@@ -50,6 +51,7 @@ infodir?=$(prefix)/share/info
MAKEINFO=makeinfo
INSTALL_INFO=install-info
DOCBOOK2X_TEXI=docbook2x-texi
+DBLATEX=dblatex
ifndef PERL_PATH
PERL_PATH = /usr/bin/perl
endif
@@ -87,7 +89,11 @@ man7: $(DOC_MAN7)
info: git.info gitman.info
-install: man
+pdf: user-manual.pdf
+
+install: install-man
+
+install-man: man
$(INSTALL) -d -m 755 $(DESTDIR)$(man1dir)
$(INSTALL) -d -m 755 $(DESTDIR)$(man5dir)
$(INSTALL) -d -m 755 $(DESTDIR)$(man7dir)
@@ -105,6 +111,10 @@ install-info: info
echo "No directory found in $(DESTDIR)$(infodir)" >&2 ; \
fi
+install-pdf: pdf
+ $(INSTALL) -d -m 755 $(DESTDIR)$(pdfdir)
+ $(INSTALL) -m 644 user-manual.pdf $(DESTDIR)$(pdfdir)
+
install-html: html
sh ./install-webdoc.sh $(DESTDIR)$(htmldir)
@@ -185,17 +195,23 @@ git.info: user-manual.texi
user-manual.texi: user-manual.xml
$(RM) $@+ $@
- $(DOCBOOK2X_TEXI) user-manual.xml --to-stdout | $(PERL_PATH) fix-texi.perl >$@+
+ $(DOCBOOK2X_TEXI) user-manual.xml --encoding=UTF-8 --to-stdout | \
+ $(PERL_PATH) fix-texi.perl >$@+
+ mv $@+ $@
+
+user-manual.pdf: user-manual.xml
+ $(RM) $@+ $@
+ $(DBLATEX) -o $@+ -p /etc/asciidoc/dblatex/asciidoc-dblatex.xsl -s /etc/asciidoc/dblatex/asciidoc-dblatex.sty $<
mv $@+ $@
gitman.texi: $(MAN_XML) cat-texi.perl
$(RM) $@+ $@
- ($(foreach xml,$(MAN_XML),$(DOCBOOK2X_TEXI) --to-stdout $(xml);)) | \
- $(PERL_PATH) cat-texi.perl $@ >$@+
+ ($(foreach xml,$(MAN_XML),$(DOCBOOK2X_TEXI) --encoding=UTF-8 \
+ --to-stdout $(xml);)) | $(PERL_PATH) cat-texi.perl $@ >$@+
mv $@+ $@
gitman.info: gitman.texi
- $(MAKEINFO) --no-split $*.texi
+ $(MAKEINFO) --no-split --no-validate $*.texi
$(patsubst %.txt,%.texi,$(MAN_TXT)): %.texi : %.xml
$(RM) $@+ $@
@@ -220,7 +236,9 @@ $(patsubst %.txt,%.html,$(wildcard howto/*.txt)): %.html : %.txt
install-webdoc : html
sh ./install-webdoc.sh $(WEBDOC_DEST)
-quick-install:
+quick-install: quick-install-man
+
+quick-install-man:
sh ./install-doc-quick.sh $(DOC_REF) $(DESTDIR)$(mandir)
quick-install-html:
diff --git a/Documentation/RelNotes-1.5.4.7.txt b/Documentation/RelNotes-1.5.4.7.txt
new file mode 100644
index 0000000000..9065a0e273
--- /dev/null
+++ b/Documentation/RelNotes-1.5.4.7.txt
@@ -0,0 +1,10 @@
+GIT v1.5.4.7 Release Notes
+==========================
+
+Fixes since 1.5.4.7
+-------------------
+
+ * Removed support for an obsolete gitweb request URI, whose
+ implementation ran "git diff" Porcelain, instead of using plumbing,
+ which would have run an external diff command specified in the
+ repository configuration as the gitweb user.
diff --git a/Documentation/RelNotes-1.5.5.6.txt b/Documentation/RelNotes-1.5.5.6.txt
new file mode 100644
index 0000000000..d5e85cb70e
--- /dev/null
+++ b/Documentation/RelNotes-1.5.5.6.txt
@@ -0,0 +1,10 @@
+GIT v1.5.5.6 Release Notes
+==========================
+
+Fixes since 1.5.5.5
+-------------------
+
+ * Removed support for an obsolete gitweb request URI, whose
+ implementation ran "git diff" Porcelain, instead of using plumbing,
+ which would have run an external diff command specified in the
+ repository configuration as the gitweb user.
diff --git a/Documentation/RelNotes-1.5.6.6.txt b/Documentation/RelNotes-1.5.6.6.txt
new file mode 100644
index 0000000000..79da23db5a
--- /dev/null
+++ b/Documentation/RelNotes-1.5.6.6.txt
@@ -0,0 +1,10 @@
+GIT v1.5.6.6 Release Notes
+==========================
+
+Fixes since 1.5.6.5
+-------------------
+
+ * Removed support for an obsolete gitweb request URI, whose
+ implementation ran "git diff" Porcelain, instead of using plumbing,
+ which would have run an external diff command specified in the
+ repository configuration as the gitweb user.
diff --git a/Documentation/RelNotes-1.6.0.3.txt b/Documentation/RelNotes-1.6.0.3.txt
index 6cf8ae4ea1..ae0577836a 100644
--- a/Documentation/RelNotes-1.6.0.3.txt
+++ b/Documentation/RelNotes-1.6.0.3.txt
@@ -16,12 +16,17 @@ Fixes since v1.6.0.2
* "git rebase -i" now honors the pre-rebase hook, just like the
other rebase implementations "git rebase" and "git rebase -m".
+* "git rebase -i" incorrectly aborted when there is no commit to replay.
+
* Behaviour of "git diff --quiet" was inconsistent with "diff --exit-code"
with the output redirected to /dev/null.
* "git diff --no-index" on binary files no longer outputs a bogus
"diff --git" header line.
+* "git diff" hunk header patterns with multiple elements separated by LF
+ were not used correctly.
+
* Hunk headers in "git diff" default to using extended regular
expressions, fixing some of the internal patterns on non-GNU
platforms.
@@ -29,6 +34,15 @@ Fixes since v1.6.0.2
* New config "diff.*.xfuncname" exposes extended regular expressions
for user specified hunk header patterns.
+* "git gc" when ejecting otherwise unreachable objects from packfiles into
+ loose form leaked memory.
+
+* "git index-pack" was recently broken and mishandled objects added by
+ thin-pack completion processing under memory pressure.
+
+* "git index-pack" was recently broken and misbehaved when run from inside
+ .git/objects/pack/ directory.
+
* "git stash apply sash@{1}" was fixed to error out. Prior versions
would have applied stash@{0} incorrectly.
@@ -42,6 +56,8 @@ Fixes since v1.6.0.2
* "git remote show -v" now displays all URLs of a remote.
+* "git checkout -b branch" was confused when branch already existed.
+
* "git checkout -q" once again suppresses the locally modified file list.
* "git clone -q", "git fetch -q" asks remote side to not send
@@ -56,9 +72,15 @@ Fixes since v1.6.0.2
* "git merge" once again removes directories after the last file has
been removed from it during the merge.
+* "git merge" did not allocate enough memory for the structure itself when
+ enumerating the parents of the resulting commit.
+
* "git blame -C -C" no longer segfaults while trying to pass blame if
it encounters a submodule reference.
+* "git rm" incorrectly claimed that you have local modifications when a
+ path was merely stat-dirty.
+
* "git svn" fixed to display an error message when 'set-tree' failed,
instead of a Perl compile error.
@@ -68,10 +90,16 @@ Fixes since v1.6.0.2
* The "git commit" error message when there are still unmerged
files present was clarified to match "git write-tree".
+* "git init" was confused when core.bare or core.sharedRepository are set
+ in system or user global configuration file by mistake. When --bare or
+ --shared is given from the command line, these now override such
+ settings made outside the repositories.
+
* Some segfaults due to uncaught NULL pointers were fixed in multiple
tools such as apply, reset, update-index.
-* Solaris builds now default to OLD_ICONV=1 to avoid compile warnings.
+* Solaris builds now default to OLD_ICONV=1 to avoid compile warnings;
+ Solaris 8 does not define NEEDS_LIBICONV by default.
* "Git.pm" tests relied on unnecessarily more recent version of Perl.
@@ -87,9 +115,3 @@ Fixes since v1.6.0.2
("git fetch") is still however supported.
Many other documentation updates.
-
---
-exec >/var/tmp/1
-O=v1.6.0.2-76-gd70b4a8
-echo O=$(git describe maint)
-git shortlog --no-merges $O..maint
diff --git a/Documentation/RelNotes-1.6.0.4.txt b/Documentation/RelNotes-1.6.0.4.txt
new file mode 100644
index 0000000000..d522661d31
--- /dev/null
+++ b/Documentation/RelNotes-1.6.0.4.txt
@@ -0,0 +1,39 @@
+GIT v1.6.0.4 Release Notes
+==========================
+
+Fixes since v1.6.0.3
+--------------------
+
+* 'git add -p' said "No changes" when only binary files were changed.
+
+* 'git archive' did not work correctly in bare repositories.
+
+* 'git checkout -t -b newbranch' when you are on detached HEAD was broken.
+
+* when we refuse to detect renames because there are too many new or
+ deleted files, 'git diff' did not say how many there are.
+
+* 'git push --mirror' tried and failed to push the stash; there is no
+ point in sending it to begin with.
+
+* 'git push' did not update the remote tracking reference if the corresponding
+ ref on the remote end happened to be already up to date.
+
+* 'git pull $there $branch:$current_branch' did not work when you were on
+ a branch yet to be born.
+
+* when giving up resolving a conflicted merge, 'git reset --hard' failed
+ to remove new paths from the working tree.
+
+* 'git send-email' had a small fd leak while scanning directory.
+
+* 'git status' incorrectly reported a submodule directory as an untracked
+ directory.
+
+* 'git svn' used deprecated 'git-foo' form of subcommand invocation.
+
+* 'git update-ref -d' to remove a reference did not honor --no-deref option.
+
+* Plugged small memleaks here and there.
+
+* Also contains many documentation updates.
diff --git a/Documentation/RelNotes-1.6.0.5.txt b/Documentation/RelNotes-1.6.0.5.txt
new file mode 100644
index 0000000000..a08bb96738
--- /dev/null
+++ b/Documentation/RelNotes-1.6.0.5.txt
@@ -0,0 +1,56 @@
+GIT v1.6.0.5 Release Notes
+==========================
+
+Fixes since v1.6.0.4
+--------------------
+
+* "git checkout" used to crash when your HEAD was pointing at a deleted
+ branch.
+
+* "git checkout" from an un-checked-out state did not allow switching out
+ of the current branch.
+
+* "git diff" always allowed GIT_EXTERNAL_DIFF and --no-ext-diff was no-op for
+ the command.
+
+* Giving 3 or more tree-ish to "git diff" is supposed to show the combined
+ diff from second and subsequent trees to the first one, but the order was
+ screwed up.
+
+* "git fast-export" did not export all tags.
+
+* "git ls-files --with-tree=<tree>" did not work with options other
+ than -c, most notably with -m.
+
+* "git pack-objects" did not make its best effort to honor --max-pack-size
+ option when a single first object already busted the given limit and
+ placed many objects in a single pack.
+
+* "git-p4" fast import frontend was too eager to trigger its keyword expansion
+ logic, even on a keyword-looking string that does not have closing '$' on the
+ same line.
+
+* "git push $there" when the remote $there is defined in $GIT_DIR/branches/$there
+ behaves more like what cg-push from Cogito used to work.
+
+* when giving up resolving a conflicted merge, "git reset --hard" failed
+ to remove new paths from the working tree.
+
+* "git tag" did not complain when given mutually incompatible set of options.
+
+* The message constructed in the internal editor was discarded when "git
+ tag -s" failed to sign the message, which was often caused by the user
+ not configuring GPG correctly.
+
+* "make check" cannot be run without sparse; people may have meant to say
+ "make test" instead, so suggest that.
+
+* Internal diff machinery had a corner case performance bug that choked on
+ a large file with many repeated contents.
+
+* "git repack" used to grab objects out of packs marked with .keep
+ into a new pack.
+
+* Many unsafe call to sprintf() style varargs functions are corrected.
+
+* Also contains quite a few documentation updates.
diff --git a/Documentation/RelNotes-1.6.0.6.txt b/Documentation/RelNotes-1.6.0.6.txt
new file mode 100644
index 0000000000..64ece1ffd5
--- /dev/null
+++ b/Documentation/RelNotes-1.6.0.6.txt
@@ -0,0 +1,33 @@
+GIT v1.6.0.6 Release Notes
+==========================
+
+Fixes since 1.6.0.5
+-------------------
+
+ * "git fsck" had a deep recursion that wasted stack space.
+
+ * "git fast-export" and "git fast-import" choked on an old style
+ annotated tag that lack the tagger information.
+
+ * "git mergetool -- file" did not correctly skip "--" marker that
+ signals the end of options list.
+
+ * "git show $tag" segfaulted when an annotated $tag pointed at a
+ nonexistent object.
+
+ * "git show 2>error" when the standard output is automatically redirected
+ to the pager redirected the standard error to the pager as well; there
+ was no need to.
+
+ * "git send-email" did not correctly handle list of addresses when
+ they had quoted comma (e.g. "Lastname, Givenname" <mail@addre.ss>).
+
+ * Logic to discover branch ancestry in "git svn" was unreliable when
+ the process to fetch history was interrupted.
+
+ * Removed support for an obsolete gitweb request URI, whose
+ implementation ran "git diff" Porcelain, instead of using plumbing,
+ which would have run an external diff command specified in the
+ repository configuration as the gitweb user.
+
+Also contains numerous documentation typofixes.
diff --git a/Documentation/RelNotes-1.6.1.1.txt b/Documentation/RelNotes-1.6.1.1.txt
new file mode 100644
index 0000000000..5cd1ca9cc6
--- /dev/null
+++ b/Documentation/RelNotes-1.6.1.1.txt
@@ -0,0 +1,49 @@
+GIT v1.6.1.1 Release Notes
+==========================
+
+Fixes since v1.6.1
+------------------
+
+* "git apply" took file modes from the patch text and updated the mode
+ bits of the target tree even when the patch was not about mode changes.
+
+* "git checkout $tree" did not trigger an error.
+
+* "git commit" tried to remove COMMIT_EDITMSG from the work tree by mistake.
+
+* "git describe --all" complained when a commit is described with a tag,
+ which was nonsense.
+
+* "git fsck branch" did not work as advertised; instead it behaved the same
+ way as "git fsck".
+
+* "git log --pretty=format:%s" did not handle a multi-line subject the
+ same way as built-in log listers (i.e. shortlog, --pretty=oneline, etc.)
+
+* "git daemon", and "git merge-file" are more careful when freopen fails
+ and barf, instead of going on and writing to unopened filehandle.
+
+* "git http-push" did not like some RFC 4918 compliant DAV server
+ responses.
+
+* "git merge -s recursive" mistakenly overwritten an untracked file in the
+ work tree upon delete/modify conflict.
+
+* "git merge -s recursive" didn't leave the index unmerged for entries with
+ rename/delete conflictd.
+
+* "git merge -s recursive" clobbered untracked files in the work tree.
+
+* "git mv -k" with more than one errorneous paths misbehaved.
+
+* "git rebase -i" issued an unnecessary error message upon a user error of
+ marking the first commit to be "squash"ed.
+
+Other documentation updates.
+
+---
+exec >/var/tmp/1
+O=v1.6.1-60-g78f111e
+echo O=$(git describe maint)
+git shortlog --no-merges $O..maint
+
diff --git a/Documentation/RelNotes-1.6.1.txt b/Documentation/RelNotes-1.6.1.txt
index 906932cfa1..adb7ccab0a 100644
--- a/Documentation/RelNotes-1.6.1.txt
+++ b/Documentation/RelNotes-1.6.1.txt
@@ -16,16 +16,28 @@ on.
* gitk can call out to git-gui to view "git blame" output; git-gui in turn
can run gitk from its blame view.
+* Various git-gui updates including updated translations.
+
+* Various gitweb updates from repo.or.cz installation.
+
+* Updates to emacs bindings.
+
(portability)
-* ...
+* A few test scripts used nonportable "grep" that did not work well on
+ some platforms, e.g. Solaris.
-(documentation)
+* Sample pre-auto-gc script has OS X support.
-* ...
+* Makefile has support for (ancient) FreeBSD 4.9.
(performance)
+* Many operations that are lstat(3) heavy can be told to pre-execute
+ necessary lstat(3) in parallel before their main operations, which
+ potentially gives much improved performance for cold-cache cases or in
+ environments with weak metadata caching (e.g. NFS).
+
* The underlying diff machinery to produce textual output has been
optimized, which would result in faster "git blame" processing.
@@ -35,6 +47,14 @@ on.
* Bash completion of refnames in a repository with massive number of
refs has been optimized.
+* Cygwin port uses native stat/lstat implementations when applicable,
+ which leads to improved performance.
+
+* "git push" pays attention to alternate repositories to avoid sending
+ unnecessary objects.
+
+* "git svn" can rebuild an out-of-date rev_map file.
+
(usability, bells and whistles)
* When you mistype a command name, git helpfully suggests what it guesses
@@ -42,35 +62,91 @@ on.
to a non-zero value to accept the suggestion when git can uniquely
guess.
+* The packfile machinery hopefully is more robust when dealing with
+ corrupt packs if redundant objects involved in the corruption are
+ available elsewhere.
+
+* "git add -N path..." adds the named paths as an empty blob, so that
+ subsequent "git diff" will show a diff as if they are creation events.
+
+* "git add" gained a built-in synonym for people who want to say "stage
+ changes" instead of "add contents to the staging area" which amounts
+ to the same thing.
+
+* "git apply" learned --include=paths option, similar to the existing
+ --exclude=paths option.
+
* "git bisect" is careful about a user mistake and suggests testing of
merge base first when good is not a strict ancestor of bad.
+* "git bisect skip" can take a range of commits.
+
+* "git blame" re-encodes the commit metainfo to UTF-8 from i18n.commitEncoding
+ by default.
+
+* "git check-attr --stdin" can check attributes for multiple paths.
+
* "git checkout --track origin/hack" used to be a syntax error. It now
DWIMs to create a corresponding local branch "hack", i.e. acts as if you
said "git checkout --track -b hack origin/hack".
+* "git checkout --ours/--theirs" can be used to check out one side of a
+ conflicting merge during conflict resolution.
+
+* "git checkout -m" can be used to recreate the initial conflicted state
+ during conflict resolution.
+
* "git cherry-pick" can also utilize rerere for conflict resolution.
+* "git clone" learned to be verbose with -v
+
* "git commit --author=$name" can look up author name from existing
commits.
+* output from "git commit" has been reworded in a more concise and yet
+ more informative way.
+
* "git count-objects" reports the on-disk footprint for packfiles and
their corresponding idx files.
* "git daemon" learned --max-connections=<count> option.
+* "git daemon" exports REMOTE_ADDR to record client address, so that
+ spawned programs can act differently on it.
+
+* "git describe --tags" favours closer lightweight tags than farther
+ annotated tags now.
+
* "git diff" learned to mimic --suppress-blank-empty from GNU diff via a
configuration option.
-* "git diff" learned to put more sensible hunk headers for Python and
- HTML contents.
+* "git diff" learned to put more sensible hunk headers for Python,
+ HTML and ObjC contents.
* "git diff" learned to vary the a/ vs b/ prefix depending on what are
being compared, controlled by diff.mnemonicprefix configuration.
+* "git diff" learned --dirstat-by-file to count changed files, not number
+ of lines, when summarizing the global picture.
+
+* "git diff" learned "textconv" filters --- a binary or hard-to-read
+ contents can be munged into human readable form and the difference
+ between the results of the conversion can be viewed (obviously this
+ cannot produce a patch that can be applied, so this is disabled in
+ format-patch among other things).
+
+* "--cached" option to "git diff has an easier to remember synonym "--staged",
+ to ask "what is the difference between the given commit and the
+ contents staged in the index?"
+
* "git for-each-ref" learned "refname:short" token that gives an
unambiguously abbreviated refname.
+* Auto-numbering of the subject lines is the default for "git
+ format-patch" now.
+
+* "git grep" learned to accept -z similar to GNU grep.
+
* "git help" learned to use GIT_MAN_VIEWER environment variable before
using "man" program.
@@ -85,6 +161,12 @@ on.
* "git log" learned --simplify-merges, a milder variant of --full-history;
"gitk --simplify-merges" is easier to view than with --full-history.
+* "git log" learned "--source" to show what ref each commit was reached
+ from.
+
+* "git log" also learned "--simplify-by-decoration" to show the
+ birds-eye-view of the topology of the history.
+
* "git log --pretty=format:" learned "%d" format element that inserts
names of tags that point at the commit.
@@ -94,38 +176,99 @@ on.
* "git merge -s $strategy" can use a custom built strategy if you have a
command "git-merge-$strategy" on your $PATH.
+* "git pull" (and "git fetch") can be told to operate "-v"erbosely or
+ "-q"uietly.
+
+* "git push" can be told to reject deletion of refs with receive.denyDeletes
+ configuration.
+
+* "git rebase" honours pre-rebase hook; use --no-verify to bypass it.
+
+* "git rebase -p" uses interactive rebase machinery now to preserve the merges.
+
* "git reflog expire branch" can be used in place of "git reflog expire
refs/heads/branch".
+* "git remote show $remote" lists remote branches one-per-line now.
+
+* "git send-email" can be given revision range instead of files and
+ maildirs on the command line, and automatically runs format-patch to
+ generate patches for the given revision range.
+
* "git submodule foreach" subcommand allows you to iterate over checked
out submodules.
* "git submodule sync" subcommands allows you to update the origin URL
recorded in submodule directories from the toplevel .gitmodules file.
+* "git svn branch" can create new branches on the other end.
+
+* "gitweb" can use more saner PATH_INFO based URL.
+
(internal)
* "git hash-object" learned to lie about the path being hashed, so that
correct gitattributes processing can be done while hashing contents
stored in a temporary file.
+* various callers of git-merge-recursive avoid forking it as an external
+ process.
+
+* Git class defined in "Git.pm" can be subclasses a bit more easily.
+
+* We used to link GNU regex library as a compatibility layer for some
+ platforms, but it turns out it is not necessary on most of them.
+
+* Some path handling routines used fixed number of buffers used alternately
+ but depending on the call depth, this arrangement led to hard to track
+ bugs. This issue is being addressed.
+
+
Fixes since v1.6.0
------------------
All of the fixes in v1.6.0.X maintenance series are included in this
release, unless otherwise noted.
+* Porcelains implemented as shell scripts were utterly confused when you
+ entered to a subdirectory of a work tree from sideways, following a
+ symbolic link (this may need to be backported to older releases later).
+
+* Tracking symbolic links would work better on filesystems whose lstat()
+ returns incorrect st_size value for them.
+
* "git add" and "git update-index" incorrectly allowed adding S/F when S
is a tracked symlink that points at a directory D that has a path F in
it (we still need to fix a similar nonsense when S is a submodule and F
is a path in it).
+* "git am" after stopping at a broken patch lost --whitespace, -C, -p and
+ --3way options given from the command line initially.
+
* "git diff --stdin" used to take two trees on a line and compared them,
but we dropped support for such a use case long time ago. This has
been resurrected.
* "git filter-branch" failed to rewrite a tag name with slashes in it.
+* "git http-push" did not understand URI scheme other than opaquelocktoken
+ when acquiring a lock from the server (this may need to be backported to
+ older releases later).
+
+* After "git rebase -p" stopped with conflicts while replaying a merge,
+ "git rebase --continue" did not work (may need to be backported to older
+ releases).
+
+* "git revert" records relative to which parent a revert was made when
+ reverting a merge. Together with new documentation that explains issues
+ around reverting a merge and merging from the updated branch later, this
+ hopefully will reduce user confusion (this may need to be backported to
+ older releases later).
+
+* "git rm --cached" used to allow an empty blob that was added earlier to
+ be removed without --force, even when the file in the work tree has
+ since been modified.
+
* "git push --tags --all $there" failed with generic usage message without
telling saying these two options are incompatible.
@@ -133,8 +276,11 @@ release, unless otherwise noted.
timestamp part, exposing internal implementation detail. Also these did
not work with --fixed-strings match at all.
+* "gitweb" did not mark non-ASCII characters imported from external HTML fragments
+ correctly.
+
--
exec >/var/tmp/1
-O=v1.6.0.2-295-g34a5d35
+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.6.2.txt b/Documentation/RelNotes-1.6.2.txt
new file mode 100644
index 0000000000..296804301f
--- /dev/null
+++ b/Documentation/RelNotes-1.6.2.txt
@@ -0,0 +1,65 @@
+GIT v1.6.2 Release Notes
+========================
+
+Updates since v1.6.1
+--------------------
+
+(subsystems)
+
+(portability)
+
+(performance)
+
+* pack-objects autodetects the number of CPUs available and uses threaded
+ version.
+
+(usability, bells and whistles)
+
+* "git-add -p" learned 'g'oto action to jump directly to a hunk.
+
+* git-cherry defaults to HEAD when the <upstream> argument is not given.
+
+* git-cvsserver can be told not to add extra "via git-CVS emulator" to the
+ commit log message it serves via gitcvs.commitmsgannotation configuration.
+
+* git-diff learned a new option --inter-hunk-context to coalesce close
+ hunks together and show context between them.
+
+* git-filter-branch learned --prune-empty option that discards commits
+ that do not change the contents.
+
+* git-ls-tree learned --full-tree option that shows the path in full
+ regardless of where in the work tree hierarchy the command was started.
+
+* git-mergetool learned -y(--no-prompt) option to disable prompting.
+
+* "git-reset --merge" is a new mode that works similar to the way
+ "git checkout" switches branches, taking the local changes while
+ switching to another commit.
+
+(internal)
+
+
+Fixes since v1.6.1
+------------------
+
+All of the fixes in v1.6.1.X maintenance series are included in this
+release, unless otherwise noted.
+
+* "git-add sub/file" when sub is a submodule incorrectly added the path to
+ the superproject.
+
+* git-bundle did not exclude annotated tags even when a range given from the
+ command line wanted to.
+
+* git-grep did not work correctly for index entries with assume-unchanged bit.
+
+* branch switching and merges had a silly bug that did not validate
+ the correct directory when making sure an existing subdirectory is
+ clean.
+
+--
+exec >/var/tmp/1
+O=v1.6.1-134-ge98c6a1
+echo O=$(git describe master)
+git shortlog --no-merges $O..master ^maint
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index a1e9100f9e..ba07c8c571 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -222,6 +222,9 @@ D-C-O. Indeed you are encouraged to do so. Do not forget to
place an in-body "From: " line at the beginning to properly attribute
the change to its true author (see (2) above).
+Also notice that a real name is used in the Signed-off-by: line. Please
+don't hide your real name.
+
Some people also put extra tags at the end.
"Acked-by:" says that the patch was reviewed by the person who
@@ -456,3 +459,30 @@ This should help you to submit patches inline using KMail.
5) Back in the compose window: add whatever other text you wish to the
message, complete the addressing and subject fields, and press send.
+
+
+Gmail
+-----
+
+Submitting properly formatted patches via Gmail is simple now that
+IMAP support is available. First, edit your ~/.gitconfig to specify your
+account settings:
+
+[imap]
+ folder = "[Gmail]/Drafts"
+ host = imaps://imap.gmail.com
+ user = user@gmail.com
+ pass = p4ssw0rd
+ port = 993
+ sslverify = false
+
+Next, ensure that your Gmail settings are correct. In "Settings" the
+"Use Unicode (UTF-8) encoding for outgoing messages" should be checked.
+
+Once your commits are ready to send to the mailing list, run the following
+command to send the patch emails to your Gmail Drafts folder.
+
+ $ git format-patch -M --stdout origin/master | git imap-send
+
+Go to your Gmail account, open the Drafts folder, find the patch email, fill
+in the To: and CC: fields and send away!
diff --git a/Documentation/asciidoc.conf b/Documentation/asciidoc.conf
index 40d43b78ee..1e735df3bb 100644
--- a/Documentation/asciidoc.conf
+++ b/Documentation/asciidoc.conf
@@ -7,6 +7,9 @@
# Show GIT link as: <command>(<section>); if section is defined, else just show
# the command.
+[macros]
+(?su)[\\]?(?P<name>linkgit):(?P<target>\S*?)\[(?P<attrlist>.*?)\]=
+
[attributes]
asterisk=&#42;
plus=&#43;
@@ -40,6 +43,26 @@ endif::doctype-manpage[]
</literallayout>
{title#}</example>
endif::docbook-xsl-172[]
+
+ifdef::docbook-xsl-172[]
+ifdef::doctype-manpage[]
+# The following two small workarounds insert a simple paragraph after screen
+[listingblock]
+<example><title>{title}</title>
+<screen>
+|
+</screen><simpara></simpara>
+{title#}</example>
+
+[verseblock]
+<formalpara{id? id="{id}"}><title>{title}</title><para>
+{title%}<literallayout{id? id="{id}"}>
+{title#}<literallayout>
+|
+</literallayout><simpara></simpara>
+{title#}</para></formalpara>
+endif::doctype-manpage[]
+endif::docbook-xsl-172[]
endif::backend-docbook[]
ifdef::doctype-manpage[]
diff --git a/Documentation/blame-options.txt b/Documentation/blame-options.txt
index 5428111d73..1ab1b96cf9 100644
--- a/Documentation/blame-options.txt
+++ b/Documentation/blame-options.txt
@@ -49,6 +49,13 @@ of lines before or after the line given by <start>.
Show the result incrementally in a format designed for
machine consumption.
+--encoding=<encoding>::
+ Specifies the encoding used to output author names
+ and commit summaries. Setting it to `none` makes blame
+ output unconverted data. For more information see the
+ discussion about encoding in the linkgit:git-log[1]
+ manual page.
+
--contents <file>::
When <rev> is not specified, the command annotates the
changes starting backwards from the working tree copy.
diff --git a/Documentation/cat-texi.perl b/Documentation/cat-texi.perl
index dbc133cd3c..828ec62554 100755
--- a/Documentation/cat-texi.perl
+++ b/Documentation/cat-texi.perl
@@ -18,8 +18,12 @@ close TMP;
printf '\input texinfo
@setfilename gitman.info
-@documentencoding us-ascii
-@node Top,,%s
+@documentencoding UTF-8
+@dircategory Development
+@direntry
+* Git Man Pages: (gitman). Manual pages for Git revision control system
+@end direntry
+@node Top,,, (dir)
@top Git Manual Pages
@documentlanguage en
@menu
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 5ba3ffa10f..6b3ac5aa90 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -124,7 +124,9 @@ core.ignoreCygwinFSTricks::
one hierarchy using Cygwin mount. If true, Git uses native Win32 API
whenever it is possible and falls back to Cygwin functions only to
handle symbol links. The native mode is more than twice faster than
- normal Cygwin l/stat() functions. True by default.
+ normal Cygwin l/stat() functions. True by default, unless core.filemode
+ is true, in which case ignoreCygwinFSTricks is ignored as Cygwin's
+ POSIX emulation is required to support core.filemode.
core.trustctime::
If false, the ctime differences between the index and the
@@ -411,6 +413,15 @@ data writes properly, but can be useful for filesystems that do not use
journalling (traditional UNIX filesystems) or that only journal metadata
and not file contents (OS X's HFS+, or Linux ext3 with "data=writeback").
+core.preloadindex::
+ Enable parallel index preload for operations like 'git diff'
++
+This can speed up operations like 'git diff' and 'git status' especially
+on filesystems like NFS that have weak caching semantics and thus
+relatively high IO latencies. With this set to 'true', git will do the
+index comparison to the filesystem data in parallel, allowing
+overlapping IO's.
+
alias.*::
Command aliases for the linkgit:git[1] command wrapper - e.g.
after defining "alias.last = cat-file commit HEAD", the invocation
@@ -570,9 +581,6 @@ color.status.<slot>::
to red). The values of these variables may be specified as in
color.branch.<slot>.
-commit.template::
- Specify a file to use as the template for new commit messages.
-
color.ui::
When set to `always`, always use colors in all git commands which
are capable of colored output. When false (or `never`), never. When
@@ -580,6 +588,9 @@ color.ui::
terminal. When more specific variables of color.* are set, they always
take precedence over this setting. Defaults to false.
+commit.template::
+ Specify a file to use as the template for new commit messages.
+
diff.autorefreshindex::
When using 'git-diff' to compare with work tree
files, do not consider stat-only change as changed.
@@ -590,10 +601,6 @@ diff.autorefreshindex::
affects only 'git-diff' Porcelain, and not lower level
'diff' commands, such as 'git-diff-files'.
-diff.suppress-blank-empty::
- A boolean to inhibit the standard behavior of printing a space
- before each empty output line. Defaults to false.
-
diff.external::
If this config variable is set, diff generation is not
performed using the internal diff machinery, but using the
@@ -628,6 +635,10 @@ diff.renames::
will enable basic rename detection. If set to "copies" or
"copy", it will detect copies, as well.
+diff.suppress-blank-empty::
+ A boolean to inhibit the standard behavior of printing a space
+ before each empty output line. Defaults to false.
+
fetch.unpackLimit::
If the number of objects fetched over the git native
transfer is below this
@@ -691,7 +702,9 @@ gc.packrefs::
gc.pruneexpire::
When 'git-gc' is run, it will call 'prune --expire 2.weeks.ago'.
- Override the grace period with this config variable.
+ Override the grace period with this config variable. The value
+ "now" may be used to disable this grace period and always prune
+ unreachable objects immediately.
gc.reflogexpire::
'git-reflog expire' removes reflog entries older than
@@ -712,17 +725,9 @@ gc.rerereunresolved::
kept for this many days when 'git-rerere gc' is run.
The default is 15 days. See linkgit:git-rerere[1].
-rerere.autoupdate::
- When set to true, `git-rerere` updates the index with the
- resulting contents after it cleanly resolves conflicts using
- previously recorded resolution. Defaults to false.
-
-rerere.enabled::
- Activate recording of resolved conflicts, so that identical
- conflict hunks can be resolved automatically, should they
- be encountered again. linkgit:git-rerere[1] command is by
- default enabled if you create `rr-cache` directory under
- `$GIT_DIR`, but can be disabled by setting this option to false.
+gitcvs.commitmsgannotation::
+ Append this string to each commit message. Set to empty string
+ to disable this feature. Defaults to "via git-CVS emulator".
gitcvs.enabled::
Whether the CVS server interface is enabled for this repository.
@@ -794,6 +799,14 @@ gui.diffcontext::
Specifies how many context lines should be used in calls to diff
made by the linkgit:git-gui[1]. The default is "5".
+gui.encoding::
+ Specifies the default encoding to use for displaying of
+ file contents in linkgit:git-gui[1] and linkgit:gitk[1].
+ It can be overridden by setting the 'encoding' attribute
+ for relevant files (see linkgit:gitattributes[5]).
+ If this option is not set, the tools default to the
+ locale encoding.
+
gui.matchtrackingbranch::
Determines if new branches created with linkgit:git-gui[1] should
default to tracking remote branches with matching names or
@@ -816,6 +829,73 @@ gui.spellingdictionary::
the linkgit:git-gui[1]. When set to "none" spell checking is turned
off.
+gui.fastcopyblame::
+ If true, 'git gui blame' uses '-C' instead of '-C -C' for original
+ location detection. It makes blame significantly faster on huge
+ repositories at the expense of less thorough copy detection.
+
+gui.copyblamethreshold::
+ Specifies the threshold to use in 'git gui blame' original location
+ detection, measured in alphanumeric characters. See the
+ linkgit:git-blame[1] manual for more information on copy detection.
+
+gui.blamehistoryctx::
+ Specifies the radius of history context in days to show in
+ linkgit:gitk[1] for the selected commit, when the `Show History
+ Context` menu item is invoked from 'git gui blame'. If this
+ variable is set to zero, the whole history is shown.
+
+guitool.<name>.cmd::
+ Specifies the shell command line to execute when the corresponding item
+ of the linkgit:git-gui[1] `Tools` menu is invoked. This option is
+ mandatory for every tool. The command is executed from the root of
+ the working directory, and in the environment it receives the name of
+ the tool as 'GIT_GUITOOL', the name of the currently selected file as
+ 'FILENAME', and the name of the current branch as 'CUR_BRANCH' (if
+ the head is detached, 'CUR_BRANCH' is empty).
+
+guitool.<name>.needsfile::
+ Run the tool only if a diff is selected in the GUI. It guarantees
+ that 'FILENAME' is not empty.
+
+guitool.<name>.noconsole::
+ Run the command silently, without creating a window to display its
+ output.
+
+guitool.<name>.norescan::
+ Don't rescan the working directory for changes after the tool
+ finishes execution.
+
+guitool.<name>.confirm::
+ Show a confirmation dialog before actually running the tool.
+
+guitool.<name>.argprompt::
+ Request a string argument from the user, and pass it to the tool
+ through the 'ARGS' environment variable. Since requesting an
+ argument implies confirmation, the 'confirm' option has no effect
+ if this is enabled. If the option is set to 'true', 'yes', or '1',
+ the dialog uses a built-in generic prompt; otherwise the exact
+ value of the variable is used.
+
+guitool.<name>.revprompt::
+ Request a single valid revision from the user, and set the
+ 'REVISION' environment variable. In other aspects this option
+ is similar to 'argprompt', and can be used together with it.
+
+guitool.<name>.revunmerged::
+ Show only unmerged branches in the 'revprompt' subdialog.
+ This is useful for tools similar to merge or rebase, but not
+ for things like checkout or reset.
+
+guitool.<name>.title::
+ Specifies the title to use for the prompt dialog. The default
+ is the tool name.
+
+guitool.<name>.prompt::
+ Specifies the general prompt string to display at the top of
+ the dialog, before subsections for 'argprompt' and 'revprompt'.
+ The default value includes the actual command.
+
help.browser::
Specify the browser that will be used to display help in the
'web' format. See linkgit:git-help[1].
@@ -891,6 +971,10 @@ i18n.logOutputEncoding::
Character encoding the commit messages are converted to when
running 'git-log' and friends.
+imap::
+ The configuration variables in the 'imap' section are described
+ in linkgit:git-imap-send[1].
+
instaweb.browser::
Specify the program that will be used to browse your working
repository in gitweb. See linkgit:git-instaweb[1].
@@ -926,8 +1010,6 @@ man.viewer::
Specify the programs that may be used to display help in the
'man' format. See linkgit:git-help[1].
-include::merge-config.txt[]
-
man.<tool>.cmd::
Specify the command to invoke the specified man viewer. The
specified command is evaluated in shell with the man page
@@ -937,13 +1019,7 @@ man.<tool>.path::
Override the path for the given tool that may be used to
display help in the 'man' format. See linkgit:git-help[1].
-merge.conflictstyle::
- Specify the style in which conflicted hunks are written out to
- working tree files upon merge. The default is "merge", which
- shows `<<<<<<<` conflict marker, change made by one side,
- `=======` marker, change made by the other side, and then
- `>>>>>>>` marker. An alternate style, "diff3", adds `|||||||`
- marker and the original text before `=======` marker.
+include::merge-config.txt[]
mergetool.<tool>.path::
Override the path for the given tool. This is useful in case
@@ -974,6 +1050,16 @@ mergetool.keepBackup::
is set to `false` then this file is not preserved. Defaults to
`true` (i.e. keep the backup files).
+mergetool.keepTemporaries::
+ When invoking a custom merge tool, git uses a set of temporary
+ files to pass to the tool. If the tool returns an error and this
+ variable is set to `true`, then these temporary files will be
+ preserved, otherwise they will be removed after the tool has
+ exited. Defaults to `false`.
+
+mergetool.prompt::
+ Prompt before each invocation of the merge resolution program.
+
pack.window::
The size of the window used by linkgit:git-pack-objects[1] when no
window size is given on the command line. Defaults to 10.
@@ -1053,6 +1139,41 @@ pull.octopus::
pull.twohead::
The default merge strategy to use when pulling a single branch.
+receive.fsckObjects::
+ If it is set to true, git-receive-pack will check all received
+ objects. It will abort in the case of a malformed object or a
+ broken link. The result of an abort are only dangling objects.
+ Defaults to false.
+
+receive.unpackLimit::
+ If the number of objects received in a push is below this
+ limit then the objects will be unpacked into loose object
+ files. However if the number of received objects equals or
+ exceeds this limit then the received pack will be stored as
+ a pack, after adding any missing delta bases. Storing the
+ pack from a push can make the push operation complete faster,
+ especially on slow filesystems. If not set, the value of
+ `transfer.unpackLimit` is used instead.
+
+receive.denyDeletes::
+ If set to true, git-receive-pack will deny a ref update that deletes
+ the ref. Use this to prevent such a ref deletion via a push.
+
+receive.denyCurrentBranch::
+ If set to true or "refuse", receive-pack will deny a ref update
+ to the currently checked out branch of a non-bare repository.
+ Such a push is potentially dangerous because it brings the HEAD
+ out of sync with the index and working tree. If set to "warn",
+ print a warning of such a push to stderr, but allow the push to
+ proceed. If set to false or "ignore", allow such pushes with no
+ message. Defaults to "warn".
+
+receive.denyNonFastForwards::
+ If set to true, git-receive-pack will deny a ref update which is
+ not a fast forward. Use this to prevent such an update via a push,
+ even if that push is forced. This configuration variable is
+ set when initializing a shared repository.
+
remote.<name>.url::
The URL of a remote repository. See linkgit:git-fetch[1] or
linkgit:git-push[1].
@@ -1102,6 +1223,18 @@ repack.usedeltabaseoffset::
"false" and repack. Access from old git versions over the
native protocol are unaffected by this option.
+rerere.autoupdate::
+ When set to true, `git-rerere` updates the index with the
+ resulting contents after it cleanly resolves conflicts using
+ previously recorded resolution. Defaults to false.
+
+rerere.enabled::
+ Activate recording of resolved conflicts, so that identical
+ conflict hunks can be resolved automatically, should they
+ be encountered again. linkgit:git-rerere[1] command is by
+ default enabled if you create `rr-cache` directory under
+ `$GIT_DIR`, but can be disabled by setting this option to false.
+
showbranch.default::
The default set of branches for linkgit:git-show-branch[1].
See linkgit:git-show-branch[1].
@@ -1138,6 +1271,11 @@ tar.umask::
archiving user's umask will be used instead. See umask(2) and
linkgit:git-archive[1].
+transfer.unpackLimit::
+ When `fetch.unpackLimit` or `receive.unpackLimit` are
+ not set, the value of this variable is used instead.
+ The default value is 100.
+
url.<base>.insteadOf::
Any URL that starts with this value will be rewritten to
start, instead, with <base>. In cases where some site serves a
@@ -1166,37 +1304,6 @@ user.signingkey::
unchanged to gpg's --local-user parameter, so you may specify a key
using any method that gpg supports.
-imap::
- The configuration variables in the 'imap' section are described
- in linkgit:git-imap-send[1].
-
-receive.fsckObjects::
- If it is set to true, git-receive-pack will check all received
- objects. It will abort in the case of a malformed object or a
- broken link. The result of an abort are only dangling objects.
- Defaults to false.
-
-receive.unpackLimit::
- If the number of objects received in a push is below this
- limit then the objects will be unpacked into loose object
- files. However if the number of received objects equals or
- exceeds this limit then the received pack will be stored as
- a pack, after adding any missing delta bases. Storing the
- pack from a push can make the push operation complete faster,
- especially on slow filesystems. If not set, the value of
- `transfer.unpackLimit` is used instead.
-
-receive.denyNonFastForwards::
- If set to true, git-receive-pack will deny a ref update which is
- not a fast forward. Use this to prevent such an update via a push,
- even if that push is forced. This configuration variable is
- set when initializing a shared repository.
-
-transfer.unpackLimit::
- When `fetch.unpackLimit` or `receive.unpackLimit` are
- not set, the value of this variable is used instead.
- The default value is 100.
-
web.browser::
Specify a web browser that may be used by some commands.
Currently only linkgit:git-instaweb[1] and linkgit:git-help[1]
diff --git a/Documentation/diff-format.txt b/Documentation/diff-format.txt
index 400cbb3b1c..1eeb1c7683 100644
--- a/Documentation/diff-format.txt
+++ b/Documentation/diff-format.txt
@@ -46,6 +46,22 @@ That is, from the left to the right:
. path for "dst"; only exists for C or R.
. an LF or a NUL when '-z' option is used, to terminate the record.
+Possible status letters are:
+
+- A: addition of a file
+- C: copy of a file into a new one
+- D: deletion of a file
+- M: modification of the contents or mode of a file
+- R: renaming of a file
+- T: change in the type of the file
+- U: file is unmerged (you must complete the merge before it can
+be committed)
+- X: "unknown" change type (most probably a bug, please report it)
+
+Status letters C and R are always followed by a score (denoting the
+percentage of similarity between the source and target of the move or
+copy), and are the only ones to be so.
+
<sha1> is shown as all 0's if a file is new on the filesystem
and it is out of sync with the index.
diff --git a/Documentation/diff-generate-patch.txt b/Documentation/diff-generate-patch.txt
index 517e1eba3c..0f25ba7e38 100644
--- a/Documentation/diff-generate-patch.txt
+++ b/Documentation/diff-generate-patch.txt
@@ -143,15 +143,15 @@ different from it.
A `-` character in the column N means that the line appears in
fileN but it does not appear in the result. A `+` character
-in the column N means that the line appears in the last file,
+in the column N means that the line appears in the result,
and fileN does not have that line (in other words, the line was
added, from the point of view of that parent).
In the above example output, the function signature was changed
from both files (hence two `-` removals from both file1 and
file2, plus `++` to mean one line that was added does not appear
-in either file1 nor file2). Also two other lines are the same
-from file1 but do not appear in file2 (hence prefixed with ` +`).
+in either file1 nor file2). Also eight other lines are the same
+from file1 but do not appear in file2 (hence prefixed with `{plus}`).
When shown by `git diff-tree -c`, it compares the parents of a
merge commit with the merge result (i.e. file1..fileN are the
diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
index 7788d4fa4a..43793d7500 100644
--- a/Documentation/diff-options.txt
+++ b/Documentation/diff-options.txt
@@ -19,16 +19,12 @@ endif::git-format-patch[]
ifndef::git-format-patch[]
-p::
+-u::
Generate patch (see section on generating patches).
{git-diff? This is the default.}
endif::git-format-patch[]
--u::
- Synonym for "-p".
-
-U<n>::
- Shorthand for "--unified=<n>".
-
--unified=<n>::
Generate diffs with <n> lines of context instead of
the usual three. Implies "-p".
@@ -120,7 +116,7 @@ endif::git-format-patch[]
--abbrev[=<n>]::
Instead of showing the full 40-byte hexadecimal object
name in diff-raw format output and diff-tree header
- lines, show only handful hexdigits prefix. This is
+ lines, show only a partial prefix. This is
independent of --full-index option above, which controls
the diff-patch output format. Non default number of
digits can be specified with --abbrev=<n>.
@@ -137,7 +133,8 @@ endif::git-format-patch[]
--diff-filter=[ACDMRTUXB*]::
Select only files that are Added (`A`), Copied (`C`),
Deleted (`D`), Modified (`M`), Renamed (`R`), have their
- type (mode) changed (`T`), are Unmerged (`U`), are
+ type (i.e. regular file, symlink, submodule, ...) changed (`T`),
+ are Unmerged (`U`), are
Unknown (`X`), or have had their pairing Broken (`B`).
Any combination of the filter characters may be used.
When `*` (All-or-none) is added to the combination, all
@@ -189,30 +186,28 @@ endif::git-format-patch[]
can name which subdirectory to make the output relative
to by giving a <path> as an argument.
+-a::
--text::
Treat all files as text.
--a::
- Shorthand for "--text".
-
--ignore-space-at-eol::
Ignore changes in whitespace at EOL.
+-b::
--ignore-space-change::
Ignore changes in amount of whitespace. This ignores whitespace
at line end, and considers all other sequences of one or
more whitespace characters to be equivalent.
--b::
- Shorthand for "--ignore-space-change".
-
+-w::
--ignore-all-space::
Ignore whitespace when comparing lines. This ignores
differences even if one line has whitespace where the other
line has none.
--w::
- Shorthand for "--ignore-all-space".
+--inter-hunk-context=<lines>::
+ Show the context between diff hunks, up to the specified number
+ of lines, thereby fusing hunks that are close to each other.
--exit-code::
Make the program exit with codes similar to diff(1).
diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt
index 2b6d6c8654..7c129cb24f 100644
--- a/Documentation/git-add.txt
+++ b/Documentation/git-add.txt
@@ -9,8 +9,8 @@ SYNOPSIS
--------
[verse]
'git add' [-n] [-v] [--force | -f] [--interactive | -i] [--patch | -p]
- [--all | [--update | -u]] [--refresh] [--ignore-errors] [--]
- <filepattern>...
+ [--all | [--update | -u]] [--intent-to-add | -N]
+ [--refresh] [--ignore-errors] [--] <filepattern>...
DESCRIPTION
-----------
@@ -92,6 +92,15 @@ OPTIONS
and add all untracked files that are not ignored by '.gitignore'
mechanism.
+
+-N::
+--intent-to-add::
+ Record only the fact that the path will be added later. An entry
+ for the path is placed in the index with no content. This is
+ useful for, among other things, showing the unstaged content of
+ such files with 'git diff' and committing them with 'git commit
+ -a'.
+
--refresh::
Don't add the file(s), but only refresh their stat()
information in the index.
diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt
index c7981efcd9..147ea38197 100644
--- a/Documentation/git-bisect.txt
+++ b/Documentation/git-bisect.txt
@@ -19,14 +19,14 @@ on the subcommand:
git bisect start [<bad> [<good>...]] [--] [<paths>...]
git bisect bad [<rev>]
git bisect good [<rev>...]
- git bisect skip [<rev>...]
+ git bisect skip [(<rev>|<range>)...]
git bisect reset [<branch>]
git bisect visualize
git bisect replay <logfile>
git bisect log
git bisect run <cmd>...
-This command uses 'git-rev-list --bisect' to help drive the
+This command uses 'git rev-list --bisect' to help drive the
binary search process to find which change introduced a bug, given an
old "good" commit object name and a later "bad" commit object name.
@@ -101,7 +101,7 @@ $ git bisect visualize
to see the currently remaining suspects in 'gitk'. `visualize` is a bit
too long to type and `view` is provided as a synonym.
-If 'DISPLAY' environment variable is not set, 'git-log' is used
+If 'DISPLAY' environment variable is not set, 'git log' is used
instead. You can even give command line options such as `-p` and
`--stat`.
@@ -164,6 +164,25 @@ But computing the commit to test may be slower afterwards and git may
eventually not be able to tell the first bad among a bad and one or
more "skip"ped commits.
+You can even skip a range of commits, instead of just one commit,
+using the "'<commit1>'..'<commit2>'" notation. For example:
+
+------------
+$ git bisect skip v2.5..v2.6
+------------
+
+would mean that no commit between `v2.5` excluded and `v2.6` included
+can be tested.
+
+Note that if you want to also skip the first commit of a range you can
+use something like:
+
+------------
+$ git bisect skip v2.5 v2.5..v2.6
+------------
+
+and the commit pointed to by `v2.5` will be skipped too.
+
Cutting down bisection by giving more parameters to bisect start
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -215,7 +234,7 @@ tweaks (e.g., s/#define DEBUG 0/#define DEBUG 1/ in a header file, or
work around other problem this bisection is not interested in")
applied to the revision being tested.
-To cope with such a situation, after the inner 'git-bisect' finds the
+To cope with such a situation, after the inner 'git bisect' finds the
next revision to test, with the "run" script, you can apply that tweak
before compiling, run the real test, and after the test decides if the
revision (possibly with the needed tweaks) passed the test, rewind the
diff --git a/Documentation/git-check-attr.txt b/Documentation/git-check-attr.txt
index 2b821f2a1d..8c2ac12f5d 100644
--- a/Documentation/git-check-attr.txt
+++ b/Documentation/git-check-attr.txt
@@ -3,12 +3,14 @@ git-check-attr(1)
NAME
----
-git-check-attr - Display gitattributes information.
+git-check-attr - Display gitattributes information
SYNOPSIS
--------
+[verse]
'git check-attr' attr... [--] pathname...
+'git check-attr' --stdin [-z] attr... < <list-of-paths>
DESCRIPTION
-----------
@@ -17,11 +19,68 @@ For every pathname, this command will list if each attr is 'unspecified',
OPTIONS
-------
+--stdin::
+ Read file names from stdin instead of from the command-line.
+
+-z::
+ Only meaningful with `--stdin`; paths are separated with
+ NUL character instead of LF.
+
\--::
Interpret all preceding arguments as attributes, and all following
arguments as path names. If not supplied, only the first argument will
be treated as an attribute.
+OUTPUT
+------
+
+The output is of the form:
+<path> COLON SP <attribute> COLON SP <info> LF
+
+Where <path> is the path of a file being queried, <attribute> is an attribute
+being queried and <info> can be either:
+
+'unspecified';; when the attribute is not defined for the path.
+'unset';; when the attribute is defined to false.
+'set';; when the attribute is defined to true.
+<value>;; when a value has been assigned to the attribute.
+
+EXAMPLES
+--------
+
+In the examples, the following '.gitattributes' file is used:
+---------------
+*.java diff=java -crlf myAttr
+NoMyAttr.java !myAttr
+README caveat=unspecified
+---------------
+
+* Listing a single attribute:
+---------------
+$ git check-attr diff org/example/MyClass.java
+org/example/MyClass.java: diff: java
+---------------
+
+* Listing multiple attributes for a file:
+---------------
+$ git check-attr crlf diff myAttr -- org/example/MyClass.java
+org/example/MyClass.java: crlf: unset
+org/example/MyClass.java: diff: java
+org/example/MyClass.java: myAttr: set
+---------------
+
+* Listing attribute for multiple files:
+---------------
+$ git check-attr myAttr -- org/example/MyClass.java org/example/NoMyAttr.java
+org/example/MyClass.java: myAttr: set
+org/example/NoMyAttr.java: myAttr: unspecified
+---------------
+
+* Not all values are equally unambiguous:
+---------------
+$ git check-attr caveat README
+README: caveat: unspecified
+---------------
SEE ALSO
--------
diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index 82e154de49..9cd51514db 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -27,7 +27,7 @@ the first namespace level.
When <paths> are given, this command does *not* switch
branches. It updates the named paths in the working tree from
-the index file, or from a named commit. In
+the index file, or from a named <tree-ish> (most often a commit). In
this case, the `-b` options is meaningless and giving
either of them results in an error. <tree-ish> argument can be
used to specify a specific tree-ish (i.e. commit, tag or tree)
@@ -88,7 +88,7 @@ This would tell us to use "hack" as the local branch when branching
off of "origin/hack" (or "remotes/origin/hack", or even
"refs/remotes/origin/hack"). If the given name has no slash, or the above
guessing results in an empty name, the guessing is aborted. You can
-exlicitly give a name with '-b' in such a case.
+explicitly give a name with '-b' in such a case.
--no-track::
Ignore the branch.autosetupmerge configuration variable.
@@ -232,7 +232,6 @@ the `-m` option, you would see something like this:
------------
$ git checkout -m mytopic
Auto-merging frotz
-merge: warning: conflicts during merge
ERROR: Merge conflict in frotz
fatal: merge program failed
------------
diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt
index 837fb08b79..b764130d26 100644
--- a/Documentation/git-cherry-pick.txt
+++ b/Documentation/git-cherry-pick.txt
@@ -55,13 +55,12 @@ OPTIONS
-n::
--no-commit::
- Usually the command automatically creates a commit with
- a commit log message stating which commit was
- cherry-picked. This flag applies the change necessary
- to cherry-pick the named commit to your working tree
- and the index, but does not make the commit. In addition,
- when this option is used, your index does not have to match
- the HEAD commit. The cherry-pick is done against the
+ Usually the command automatically creates a commit.
+ This flag applies the change necessary to cherry-pick
+ the named commit to your working tree and the index,
+ but does not make the commit. In addition, when this
+ option is used, your index does not have to match the
+ HEAD commit. The cherry-pick is done against the
beginning state of your index.
+
This is useful when cherry-picking more than one commits'
diff --git a/Documentation/git-cherry.txt b/Documentation/git-cherry.txt
index 74d14c4e7f..7deefdae8f 100644
--- a/Documentation/git-cherry.txt
+++ b/Documentation/git-cherry.txt
@@ -7,7 +7,7 @@ git-cherry - Find commits not merged upstream
SYNOPSIS
--------
-'git cherry' [-v] <upstream> [<head>] [<limit>]
+'git cherry' [-v] [<upstream> [<head> [<limit>]]]
DESCRIPTION
-----------
@@ -51,6 +51,7 @@ OPTIONS
<upstream>::
Upstream branch to compare against.
+ Defaults to the first tracked remote branch, if available.
<head>::
Working branch; defaults to HEAD.
diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index 0e14e732fd..95f08b9114 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -90,6 +90,11 @@ then the cloned repository will become corrupt.
Operate quietly. This flag is also passed to the `rsync'
command when given.
+--verbose::
+-v::
+ Display the progressbar, even in case the standard output is not
+ a terminal.
+
--no-checkout::
-n::
No checkout of HEAD is performed after the clone is complete.
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index eb05b0f49b..b5d81be7ec 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -29,7 +29,8 @@ The content to be added can be specified in several ways:
3. by listing files as arguments to the 'commit' command, in which
case the commit will ignore changes staged in the index, and instead
- record the current content of the listed files;
+ record the current content of the listed files (which must already
+ be known to git);
4. by using the -a switch with the 'commit' command to automatically
"add" changes from all known files (i.e. all files that are already
@@ -94,7 +95,8 @@ OPTIONS
-s::
--signoff::
- Add Signed-off-by line at the end of the commit message.
+ Add Signed-off-by line by the committer at the end of the commit
+ log message.
-n::
--no-verify::
@@ -144,6 +146,10 @@ It is a rough equivalent for:
------
but can be used to amend a merge commit.
--
++
+You should understand the implications of rewriting history if you
+amend a commit that has already been published. (See the "RECOVERING
+FROM UPSTREAM REBASE" section in linkgit:git-rebase[1].)
-i::
--include::
@@ -160,7 +166,7 @@ but can be used to amend a merge commit.
'git-commit' if any paths are given on the command line,
in which case this option can be omitted.
If this option is specified together with '--amend', then
- no paths need be specified, which can be used to amend
+ no paths need to be specified, which can be used to amend
the last commit without committing changes that have
already been staged.
diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
index 28e1861094..19a8917b83 100644
--- a/Documentation/git-config.txt
+++ b/Documentation/git-config.txt
@@ -279,7 +279,7 @@ If you want to know all the values for a multivar, do:
% git config --get-all core.gitproxy
------------
-If you like to live dangerous, you can replace *all* core.gitproxy by a
+If you like to live dangerously, you can replace *all* core.gitproxy by a
new one with
------------
diff --git a/Documentation/git-daemon.txt b/Documentation/git-daemon.txt
index b08a08cd95..36f00aed67 100644
--- a/Documentation/git-daemon.txt
+++ b/Documentation/git-daemon.txt
@@ -110,9 +110,9 @@ OPTIONS
--user-path::
--user-path=path::
- Allow ~user notation to be used in requests. When
+ Allow {tilde}user notation to be used in requests. When
specified with no parameter, requests to
- git://host/~alice/foo is taken as a request to access
+ git://host/{tilde}alice/foo is taken as a request to access
'foo' repository in the home directory of user `alice`.
If `--user-path=path` is specified, the same request is
taken as a request to access `path/foo` repository in
@@ -270,6 +270,15 @@ selectively enable/disable services per repository::
----------------------------------------------------------------
+ENVIRONMENT
+-----------
+'git-daemon' will set REMOTE_ADDR to the IP address of the client
+that connected to it, if the IP address is available. REMOTE_ADDR will
+be available in the environment of hooks called when
+services are performed.
+
+
+
Author
------
Written by Linus Torvalds <torvalds@osdl.org>, YOSHIFUJI Hideaki
diff --git a/Documentation/git-describe.txt b/Documentation/git-describe.txt
index c4dbc2ae34..a99b4ef943 100644
--- a/Documentation/git-describe.txt
+++ b/Documentation/git-describe.txt
@@ -18,6 +18,9 @@ shown. Otherwise, it suffixes the tag name with the number of
additional commits on top of the tagged object and the
abbreviated object name of the most recent commit.
+By default (without --all or --tags) `git describe` only shows
+annotated tags. For more information about creating annotated tags
+see the -a and -s options to linkgit:git-tag[1].
OPTIONS
-------
@@ -26,11 +29,13 @@ OPTIONS
--all::
Instead of using only the annotated tags, use any ref
- found in `.git/refs/`.
+ found in `.git/refs/`. This option enables matching
+ any known branch, remote branch, or lightweight tag.
--tags::
Instead of using only the annotated tags, use any tag
- found in `.git/refs/tags`.
+ found in `.git/refs/tags`. This option enables matching
+ a lightweight (non-annotated) tag.
--contains::
Instead of finding the tag that predates the commit, find
@@ -82,7 +87,7 @@ With something like git.git current tree, I get:
v1.0.4-14-g2414721
i.e. the current head of my "parent" branch is based on v1.0.4,
-but since it has a handful commits on top of that,
+but since it has a few commits on top of that,
describe has added the number of additional commits ("14") and
an abbreviated object name for the commit itself ("2414721")
at the end.
diff --git a/Documentation/git-diff-files.txt b/Documentation/git-diff-files.txt
index 5c8c1d95a8..c526141564 100644
--- a/Documentation/git-diff-files.txt
+++ b/Documentation/git-diff-files.txt
@@ -21,7 +21,10 @@ OPTIONS
-------
include::diff-options.txt[]
--1 -2 -3 or --base --ours --theirs, and -0::
+-1 --base::
+-2 --ours::
+-3 --theirs::
+-0::
Diff against the "base" version, "our branch" or "their
branch" respectively. With these options, diffs for
merged entries are not shown.
diff --git a/Documentation/git-diff-tree.txt b/Documentation/git-diff-tree.txt
index 5d48664e62..23b7abd3c6 100644
--- a/Documentation/git-diff-tree.txt
+++ b/Documentation/git-diff-tree.txt
@@ -43,7 +43,7 @@ include::diff-options.txt[]
show tree entry itself as well as subtrees. Implies -r.
--root::
- When '--root' is specified the initial commit will be showed as a big
+ When '--root' is specified the initial commit will be shown as a big
creation event. This is equivalent to a diff against the NULL tree.
--stdin::
@@ -63,7 +63,7 @@ and terminated by a newline) is printed before the difference. When
comparing commits, the ID of the first (or only) commit, followed by a
newline, is printed.
+
-The following flags further affects the behavior when comparing
+The following flags further affect the behavior when comparing
commits (but not trees).
-m::
diff --git a/Documentation/git-diff.txt b/Documentation/git-diff.txt
index c53eba557d..a2f192fb75 100644
--- a/Documentation/git-diff.txt
+++ b/Documentation/git-diff.txt
@@ -33,6 +33,7 @@ forced by --no-index.
commit relative to the named <commit>. Typically you
would want comparison with the latest commit, so if you
do not give <commit>, it defaults to HEAD.
+ --staged is a synonym of --cached.
'git diff' [--options] <commit> [--] [<path>...]::
diff --git a/Documentation/git-fast-export.txt b/Documentation/git-fast-export.txt
index b974e2115b..0c9eb567cb 100644
--- a/Documentation/git-fast-export.txt
+++ b/Documentation/git-fast-export.txt
@@ -15,7 +15,7 @@ DESCRIPTION
This program dumps the given revisions in a form suitable to be piped
into 'git-fast-import'.
-You can use it as a human readable bundle replacement (see
+You can use it as a human-readable bundle replacement (see
linkgit:git-bundle[1]), or as a kind of an interactive
'git-filter-branch'.
@@ -65,6 +65,12 @@ If the backend uses a similar \--import-marks file, this allows for
incremental bidirectional exporting of the repository by keeping the
marks the same across runs.
+--fake-missing-tagger::
+ Some old repositories have tags without a tagger. The
+ fast-import protocol was pretty strict about that, and did not
+ allow that. So fake a tagger to be able to fast-import the
+ output.
+
EXAMPLES
--------
diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt
index b0e710d5f9..451950bab6 100644
--- a/Documentation/git-filter-branch.txt
+++ b/Documentation/git-filter-branch.txt
@@ -36,7 +36,9 @@ the objects and will not converge with the original branch. You will not
be able to easily push and distribute the rewritten branch on top of the
original branch. Please do not use this command if you do not know the
full implications, and avoid using it anyway, if a simple single commit
-would suffice to fix your problem.
+would suffice to fix your problem. (See the "RECOVERING FROM UPSTREAM
+REBASE" section in linkgit:git-rebase[1] for further information about
+rewriting published history.)
Always verify that the rewritten version is correct: The original refs,
if different from the rewritten ones, will be stored in the namespace
@@ -120,6 +122,10 @@ You can use the 'map' convenience function in this filter, and other
convenience functions, too. For example, calling 'skip_commit "$@"'
will leave out the current commit (but not its changes! If you want
that, use 'git-rebase' instead).
++
+You can also use the 'git_commit_non_empty_tree "$@"' instead of
+'git commit-tree "$@"' if you don't wish to keep commits with a single parent
+and that makes no change to the tree.
--tag-name-filter <command>::
This is the filter for rewriting tag names. When passed,
@@ -149,6 +155,16 @@ to other tags will be rewritten to point to the underlying commit.
The result will contain that directory (and only that) as its
project root.
+--prune-empty::
+ Some kind of filters will generate empty commits, that left the tree
+ untouched. This switch allow git-filter-branch to ignore such
+ commits. Though, this switch only applies for commits that have one
+ and only one parent, it will hence keep merges points. Also, this
+ option is not compatible with the use of '--commit-filter'. Though you
+ just need to use the function 'git_commit_non_empty_tree "$@"' instead
+ of the 'git commit-tree "$@"' idiom in your commit filter to make that
+ happen.
+
--original <namespace>::
Use this option to set the namespace where the original commits
will be stored. The default value is 'refs/original'.
diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt
index ac36ce8717..11a7d77261 100644
--- a/Documentation/git-format-patch.txt
+++ b/Documentation/git-format-patch.txt
@@ -46,7 +46,8 @@ applies to that command line and you do not get "everything
since the beginning of the time". If you want to format
everything since project inception to one commit, say "git
format-patch \--root <commit>" to make it clear that it is the
-latter case.
+latter case. If you want to format a single commit, you can do
+this with "git format-patch -1 <commit>".
By default, each output file is numbered sequentially from 1, and uses the
first line of the commit message (massaged for pathname safety) as
diff --git a/Documentation/git-fsck.txt b/Documentation/git-fsck.txt
index d5a7647219..287c4fc5e0 100644
--- a/Documentation/git-fsck.txt
+++ b/Documentation/git-fsck.txt
@@ -79,7 +79,8 @@ that aren't readable from any of the specified head nodes.
So for example
- git fsck --unreachable HEAD $(cat .git/refs/heads/*)
+ git fsck --unreachable HEAD \
+ $(git for-each-ref --format="%(objectname)" refs/heads)
will do quite a _lot_ of verification on the tree. There are a few
extra validity tests to be added (make sure that tree objects are
diff --git a/Documentation/git-gui.txt b/Documentation/git-gui.txt
index 0e650f497b..d0bc98b852 100644
--- a/Documentation/git-gui.txt
+++ b/Documentation/git-gui.txt
@@ -65,9 +65,28 @@ git gui blame v0.99.8 Makefile::
example the file is read from the object database and not
the working directory.
+git gui blame --line=100 Makefile::
+
+ Loads annotations as described above and automatically
+ scrolls the view to center on line '100'.
+
git gui citool::
Make one commit and return to the shell when it is complete.
+ This command returns a non-zero exit code if the window was
+ closed in any way other than by making a commit.
+
+git gui citool --amend::
+
+ Automatically enter the 'Amend Last Commit' mode of
+ the interface.
+
+git gui citool --nocommit::
+
+ Behave as normal citool, but instead of making a commit
+ simply terminate with a zero exit code. It still checks
+ that the index does not contain any unmerged entries, so
+ you can use it as a GUI version of linkgit:git-mergetool[1]
git citool::
diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt
index 93a2a227c4..34cf4e5811 100644
--- a/Documentation/git-log.txt
+++ b/Documentation/git-log.txt
@@ -40,6 +40,10 @@ include::diff-options.txt[]
--decorate::
Print out the ref names of any commits that are shown.
+--source::
+ Print out the ref name given on the command line by which each
+ commit was reached.
+
--full-diff::
Without this flag, "git log -p <path>..." shows commits that
touch the specified paths, and diffs about the same specified
diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt
index 9f85d60b5f..057a021eb5 100644
--- a/Documentation/git-ls-files.txt
+++ b/Documentation/git-ls-files.txt
@@ -126,7 +126,7 @@ OPTIONS
--abbrev[=<n>]::
Instead of showing the full 40-byte hexadecimal object
- lines, show only handful hexdigits prefix.
+ lines, show only a partial prefix.
Non default number of digits can be specified with --abbrev=<n>.
\--::
diff --git a/Documentation/git-ls-tree.txt b/Documentation/git-ls-tree.txt
index 4c7262f1cd..f68e5c5c1a 100644
--- a/Documentation/git-ls-tree.txt
+++ b/Documentation/git-ls-tree.txt
@@ -10,7 +10,7 @@ SYNOPSIS
--------
[verse]
'git ls-tree' [-d] [-r] [-t] [-l] [-z]
- [--name-only] [--name-status] [--full-name] [--abbrev=[<n>]]
+ [--name-only] [--name-status] [--full-name] [--full-tree] [--abbrev=[<n>]]
<tree-ish> [paths...]
DESCRIPTION
@@ -30,6 +30,8 @@ in the current working directory. Note that:
'sub/dir' in 'HEAD'). You don't want to give a tree that is not at the
root level (e.g. 'git ls-tree -r HEAD:sub dir') in this case, as that
would result in asking for 'sub/sub/dir' in the 'HEAD' commit.
+ However, the current working directory can be ignored by passing
+ --full-tree option.
OPTIONS
-------
@@ -59,13 +61,17 @@ OPTIONS
--abbrev[=<n>]::
Instead of showing the full 40-byte hexadecimal object
- lines, show only handful hexdigits prefix.
+ lines, show only a partial prefix.
Non default number of digits can be specified with --abbrev=<n>.
--full-name::
Instead of showing the path names relative to the current working
directory, show the full path names.
+--full-tree::
+ Do not limit the listing to the current working directory.
+ Implies --full-name.
+
paths::
When paths are given, show them (note that this isn't really raw
pathnames, but rather a list of patterns to match). Otherwise
diff --git a/Documentation/git-mailinfo.txt b/Documentation/git-mailinfo.txt
index 31eccea5bc..8d95aaa304 100644
--- a/Documentation/git-mailinfo.txt
+++ b/Documentation/git-mailinfo.txt
@@ -13,7 +13,7 @@ SYNOPSIS
DESCRIPTION
-----------
-Reading a single e-mail message from the standard input, and
+Reads a single e-mail message from the standard input, and
writes the commit log message in <msg> file, and the patches in
<patch> file. The author name, e-mail and e-mail subject are
written out to the standard output to be used by 'git-am'
diff --git a/Documentation/git-merge-base.txt b/Documentation/git-merge-base.txt
index 2f0c5259e0..767486c770 100644
--- a/Documentation/git-merge-base.txt
+++ b/Documentation/git-merge-base.txt
@@ -16,15 +16,15 @@ DESCRIPTION
'git-merge-base' finds best common ancestor(s) between two commits to use
in a three-way merge. One common ancestor is 'better' than another common
ancestor if the latter is an ancestor of the former. A common ancestor
-that does not have any better common ancestor than it is a 'best common
+that does not have any better common ancestor is a 'best common
ancestor', i.e. a 'merge base'. Note that there can be more than one
-merge bases between two commits.
+merge base for a pair of commits.
-Among the two commits to compute their merge bases, one is specified by
+Among the two commits to compute the merge base from, one is specified by
the first commit argument on the command line; the other commit is a
(possibly hypothetical) commit that is a merge across all the remaining
-commits on the command line. As the most common special case, giving only
-two commits from the command line means computing the merge base between
+commits on the command line. As the most common special case, specifying only
+two commits on the command line means computing the merge base between
the given two commits.
OPTIONS
@@ -47,7 +47,7 @@ For example, with this topology:
the merge base between 'A' and 'B' is '1'.
Given three commits 'A', 'B' and 'C', `git merge-base A B C` will compute the
-merge base between 'A' and an hypothetical commit 'M', which is a merge
+merge base between 'A' and a hypothetical commit 'M', which is a merge
between 'B' and 'C'. For example, with this topology:
o---o---o---o---C
@@ -71,8 +71,7 @@ common ancestor between 'A' and 'M', but '1' is a better common ancestor,
because '2' is an ancestor of '1'. Hence, '2' is not a merge base.
When the history involves criss-cross merges, there can be more than one
-'best' common ancestors between two commits. For example, with this
-topology:
+'best' common ancestor for two commits. For example, with this topology:
---1---o---A
\ /
@@ -80,8 +79,8 @@ topology:
/ \
---2---o---o---B
-both '1' and '2' are merge-base of A and B. Neither one is better than
-the other (both are 'best' merge base). When `--all` option is not given,
+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.
Author
diff --git a/Documentation/git-merge-file.txt b/Documentation/git-merge-file.txt
index 024ec015a3..303537357b 100644
--- a/Documentation/git-merge-file.txt
+++ b/Documentation/git-merge-file.txt
@@ -15,17 +15,17 @@ SYNOPSIS
DESCRIPTION
-----------
-'git-file-merge' incorporates all changes that lead from the `<base-file>`
+'git-merge-file' incorporates all changes that lead from the `<base-file>`
to `<other-file>` into `<current-file>`. The result ordinarily goes into
`<current-file>`. 'git-merge-file' is useful for combining separate changes
to an original. Suppose `<base-file>` is the original, and both
-`<current-file>` and `<other-file>` are modifications of `<base-file>`.
-Then 'git-merge-file' combines both changes.
+`<current-file>` and `<other-file>` are modifications of `<base-file>`,
+then 'git-merge-file' combines both changes.
A conflict occurs if both `<current-file>` and `<other-file>` have changes
in a common segment of lines. If a conflict is found, 'git-merge-file'
-normally outputs a warning and brackets the conflict with <<<<<<< and
->>>>>>> lines. A typical conflict will look like this:
+normally outputs a warning and brackets the conflict with lines containing
+<<<<<<< and >>>>>>> markers. A typical conflict will look like this:
<<<<<<< A
lines in file A
@@ -60,7 +60,7 @@ OPTIONS
`<current-file>`.
-q::
- Quiet; do not warn about conflicts.
+ Quiet; do not warn about conflicts.
EXAMPLES
diff --git a/Documentation/git-merge-index.txt b/Documentation/git-merge-index.txt
index ff088c5c29..123e6d024a 100644
--- a/Documentation/git-merge-index.txt
+++ b/Documentation/git-merge-index.txt
@@ -29,11 +29,11 @@ OPTIONS
Instead of stopping at the first failed merge, do all of them
in one shot - continue with merging even when previous merges
returned errors, and only return the error code after all the
- merges are over.
+ merges.
-q::
- Do not complain about failed merge program (the merge program
- failure usually indicates conflicts during merge). This is for
+ Do not complain about a failed merge program (a merge program
+ failure usually indicates conflicts during the merge). This is for
porcelains which might want to emit custom messages.
If 'git-merge-index' is called with multiple <file>s (or -a) then it
diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt
index dbb0c18668..f869a7f00f 100644
--- a/Documentation/git-merge-tree.txt
+++ b/Documentation/git-merge-tree.txt
@@ -14,14 +14,14 @@ DESCRIPTION
-----------
Reads three treeish, and output trivial merge results and
conflicting stages to the standard output. This is similar to
-what three-way read-tree -m does, but instead of storing the
+what three-way 'git read-tree -m' does, but instead of storing the
results in the index, the command outputs the entries to the
standard output.
This is meant to be used by higher level scripts to compute
-merge results outside index, and stuff the results back into the
+merge results outside of the index, and stuff the results back into the
index. For this reason, the output from the command omits
-entries that match <branch1> tree.
+entries that match the <branch1> tree.
Author
------
diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt
index 1f30830d46..f7be5846a6 100644
--- a/Documentation/git-merge.txt
+++ b/Documentation/git-merge.txt
@@ -69,20 +69,20 @@ Three kinds of merge can happen:
simplest case, called "Already up-to-date."
* `HEAD` is already contained in the merged commit. This is the
- most common case especially when involved through 'git pull':
- you are tracking an upstream repository, committed no local
+ most common case especially when invoked from 'git pull':
+ you are tracking an upstream repository, have committed no local
changes and now you want to update to a newer upstream revision.
- Your `HEAD` (and the index) is updated to at point the merged
+ Your `HEAD` (and the index) is updated to point at the merged
commit, without creating an extra merge commit. This is
called "Fast-forward".
* Both the merged commit and `HEAD` are independent and must be
- tied together by a merge commit that has them both as its parents.
+ tied together by a merge commit that has both of them as its parents.
The rest of this section describes this "True merge" case.
The chosen merge strategy merges the two commits into a single
new source tree.
-When things cleanly merge, these things happen:
+When things merge cleanly, this is what happens:
1. The results are updated both in the index file and in your
working tree;
@@ -91,16 +91,16 @@ When things cleanly merge, these things happen:
4. The `HEAD` pointer gets advanced.
Because of 2., we require that the original state of the index
-file to match exactly the current `HEAD` commit; otherwise we
+file matches exactly the current `HEAD` commit; otherwise we
will write out your local changes already registered in your
index file along with the merge result, which is not good.
-Because 1. involves only the paths different between your
+Because 1. involves only those paths differing between your
branch and the remote branch you are pulling from during the
merge (which is typically a fraction of the whole tree), you can
have local modifications in your working tree as long as they do
not overlap with what the merge updates.
-When there are conflicts, these things happen:
+When there are conflicts, the following happens:
1. `HEAD` stays the same.
@@ -111,8 +111,8 @@ When there are conflicts, these things happen:
versions; stage1 stores the version from the common ancestor,
stage2 from `HEAD`, and stage3 from the remote branch (you
can inspect the stages with `git ls-files -u`). The working
- tree files have the result of "merge" program; i.e. 3-way
- merge result with familiar conflict markers `<<< === >>>`.
+ tree files contain the result of the "merge" program; i.e. 3-way
+ merge results with familiar conflict markers `<<< === >>>`.
4. No other changes are done. In particular, the local
modifications you had before you started merge will stay the
@@ -145,13 +145,13 @@ Git makes conflict resolution easy.
And here is another line that is cleanly resolved or unmodified.
------------
-The area a pair of conflicting changes happened is marked with markers
+The area where a pair of conflicting changes happened is marked with markers
"`<<<<<<<`", "`=======`", and "`>>>>>>>`". The part before the "`=======`"
-is typically your side, and the part after it is typically their side.
+is typically your side, and the part afterwards is typically their side.
-The default format does not show what the original said in the conflicted
-area. You cannot tell how many lines are deleted and replaced with the
-Barbie's remark by your side. The only thing you can tell is that your
+The default format does not show what the original said in the conflicting
+area. You cannot tell how many lines are deleted and replaced with
+Barbie's remark on your side. The only thing you can tell is that your
side wants to say it is hard and you'd prefer to go shopping, while the
other side wants to claim it is easy.
@@ -186,14 +186,14 @@ HOW TO RESOLVE CONFLICTS
After seeing a conflict, you can do two things:
- * Decide not to merge. The only clean-up you need are to reset
+ * Decide not to merge. The only clean-ups you need are to reset
the index file to the `HEAD` commit to reverse 2. and to clean
up working tree changes made by 2. and 3.; 'git-reset --hard' can
be used for this.
* Resolve the conflicts. Git will mark the conflicts in
the working tree. Edit the files into shape and
- 'git-add' to the index. 'git-commit' to seal the deal.
+ 'git-add' them to the index. Use 'git-commit' to seal the deal.
You can work through the conflict with a number of tools:
diff --git a/Documentation/git-mergetool.txt b/Documentation/git-mergetool.txt
index e0b2703b38..5d3c632872 100644
--- a/Documentation/git-mergetool.txt
+++ b/Documentation/git-mergetool.txt
@@ -7,7 +7,7 @@ git-mergetool - Run merge conflict resolution tools to resolve merge conflicts
SYNOPSIS
--------
-'git mergetool' [--tool=<tool>] [<file>]...
+'git mergetool' [--tool=<tool>] [-y|--no-prompt|--prompt] [<file>]...
DESCRIPTION
-----------
@@ -22,7 +22,8 @@ with merge conflicts.
OPTIONS
-------
--t or --tool=<tool>::
+-t <tool>::
+--tool=<tool>::
Use the merge resolution program specified by <tool>.
Valid merge tools are:
kdiff3, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff, ecmerge, and opendiff
@@ -38,7 +39,7 @@ can configure the absolute path to kdiff3 by setting
`mergetool.kdiff3.path`. Otherwise, 'git-mergetool' assumes the
tool is available in PATH.
+
-Instead of running one of the known merge tool programs
+Instead of running one of the known merge tool programs,
'git-mergetool' can be customized to run an alternative program
by specifying the command line to invoke in a configuration
variable `mergetool.<tool>.cmd`.
@@ -55,11 +56,21 @@ of the file to which the merge tool should write the result of the
merge resolution.
+
If the custom merge tool correctly indicates the success of a
-merge resolution with its exit code then the configuration
+merge resolution with its exit code, then the configuration
variable `mergetool.<tool>.trustExitCode` can be set to `true`.
Otherwise, 'git-mergetool' will prompt the user to indicate the
success of the resolution after the custom tool has exited.
+-y::
+--no-prompt::
+ Don't prompt before each invocation of the merge resolution
+ program.
+
+--prompt::
+ Prompt before each invocation of the merge resolution program.
+ This is the default behaviour; the option is provided to
+ override any configuration settings.
+
Author
------
Written by Theodore Y Ts'o <tytso@mit.edu>
diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt
index 8c354bd470..7d4c1a7556 100644
--- a/Documentation/git-pack-objects.txt
+++ b/Documentation/git-pack-objects.txt
@@ -109,6 +109,11 @@ base-name::
The default is unlimited, unless the config variable
`pack.packSizeLimit` is set.
+--honor-pack-keep::
+ This flag causes an object already in a local pack that
+ has a .keep file to be ignored, even if it appears in the
+ standard input.
+
--incremental::
This flag causes an object already in a pack ignored
even if it appears in the standard input.
@@ -116,7 +121,7 @@ base-name::
--local::
This flag is similar to `--incremental`; instead of
ignoring all packed objects, it only ignores objects
- that are packed and not in the local object store
+ that are packed and/or not in the local object store
(i.e. borrowed from an alternate).
--non-empty::
diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index 6150b1b959..3321966c6b 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -86,14 +86,12 @@ nor in any Push line of the corresponding remotes file---see below).
line.
--receive-pack=<git-receive-pack>::
+--exec=<git-receive-pack>::
Path to the 'git-receive-pack' program on the remote
end. Sometimes useful when pushing to a remote
repository over ssh, and you do not have the program in
a directory on the default $PATH.
---exec=<git-receive-pack>::
- Same as \--receive-pack=<git-receive-pack>.
-
-f::
--force::
Usually, the command refuses to update a remote ref that is
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 32f0f122e9..c8ad86a56f 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -9,7 +9,7 @@ SYNOPSIS
--------
[verse]
'git rebase' [-i | --interactive] [-v | --verbose] [-m | --merge]
- [-s <strategy> | --strategy=<strategy>]
+ [-s <strategy> | --strategy=<strategy>] [--no-verify]
[-C<n>] [ --whitespace=<option>] [-p | --preserve-merges]
[--onto <newbase>] <upstream> [<branch>]
'git rebase' --continue | --skip | --abort
@@ -232,6 +232,9 @@ OPTIONS
--verbose::
Display a diffstat of what changed upstream since the last rebase.
+--no-verify::
+ This option bypasses the pre-rebase hook. See also linkgit:githooks[5].
+
-C<n>::
Ensure at least <n> lines of surrounding context match before
and after each change. When fewer lines of surrounding
@@ -250,18 +253,16 @@ OPTIONS
-p::
--preserve-merges::
- Instead of ignoring merges, try to recreate them. This option
- only works in interactive mode.
+ Instead of ignoring merges, try to recreate them.
include::merge-strategies.txt[]
NOTES
-----
-When you rebase a branch, you are changing its history in a way that
-will cause problems for anyone who already has a copy of the branch
-in their repository and tries to pull updates from you. You should
-understand the implications of using 'git-rebase' on a repository that
-you share.
+
+You should understand the implications of using 'git-rebase' on a
+repository that you share. See also RECOVERING FROM UPSTREAM REBASE
+below.
When the git-rebase command is run, it will first execute a "pre-rebase"
hook if one exists. You can use this hook to do sanity checks and
@@ -396,6 +397,127 @@ consistent (they compile, pass the testsuite, etc.) you should use
after each commit, test, and amend the commit if fixes are necessary.
+RECOVERING FROM UPSTREAM REBASE
+-------------------------------
+
+Rebasing (or any other form of rewriting) a branch that others have
+based work on is a bad idea: anyone downstream of it is forced to
+manually fix their history. This section explains how to do the fix
+from the downstream's point of view. The real fix, however, would be
+to avoid rebasing the upstream in the first place.
+
+To illustrate, suppose you are in a situation where someone develops a
+'subsystem' branch, and you are working on a 'topic' that is dependent
+on this 'subsystem'. You might end up with a history like the
+following:
+
+------------
+ o---o---o---o---o---o---o---o---o master
+ \
+ o---o---o---o---o subsystem
+ \
+ *---*---* topic
+------------
+
+If 'subsystem' is rebased against 'master', the following happens:
+
+------------
+ o---o---o---o---o---o---o---o master
+ \ \
+ o---o---o---o---o o'--o'--o'--o'--o' subsystem
+ \
+ *---*---* topic
+------------
+
+If you now continue development as usual, and eventually merge 'topic'
+to 'subsystem', the commits from 'subsystem' will remain duplicated forever:
+
+------------
+ o---o---o---o---o---o---o---o master
+ \ \
+ o---o---o---o---o o'--o'--o'--o'--o'--M subsystem
+ \ /
+ *---*---*-..........-*--* topic
+------------
+
+Such duplicates are generally frowned upon because they clutter up
+history, making it harder to follow. To clean things up, you need to
+transplant the commits on 'topic' to the new 'subsystem' tip, i.e.,
+rebase 'topic'. This becomes a ripple effect: anyone downstream from
+'topic' is forced to rebase too, and so on!
+
+There are two kinds of fixes, discussed in the following subsections:
+
+Easy case: The changes are literally the same.::
+
+ This happens if the 'subsystem' rebase was a simple rebase and
+ had no conflicts.
+
+Hard case: The changes are not the same.::
+
+ This happens if the 'subsystem' rebase had conflicts, or used
+ `\--interactive` to omit, edit, or squash commits; or if the
+ upstream used one of `commit \--amend`, `reset`, or
+ `filter-branch`.
+
+
+The easy case
+~~~~~~~~~~~~~
+
+Only works if the changes (patch IDs based on the diff contents) on
+'subsystem' are literally the same before and after the rebase
+'subsystem' did.
+
+In that case, the fix is easy because 'git-rebase' knows to skip
+changes that are already present in the new upstream. So if you say
+(assuming you're on 'topic')
+------------
+ $ git rebase subsystem
+------------
+you will end up with the fixed history
+------------
+ o---o---o---o---o---o---o---o master
+ \
+ o'--o'--o'--o'--o' subsystem
+ \
+ *---*---* topic
+------------
+
+
+The hard case
+~~~~~~~~~~~~~
+
+Things get more complicated if the 'subsystem' changes do not exactly
+correspond to the ones before the rebase.
+
+NOTE: While an "easy case recovery" sometimes appears to be successful
+ even in the hard case, it may have unintended consequences. For
+ example, a commit that was removed via `git rebase
+ \--interactive` will be **resurrected**!
+
+The idea is to manually tell 'git-rebase' "where the old 'subsystem'
+ended and your 'topic' began", that is, what the old merge-base
+between them was. You will have to find a way to name the last commit
+of the old 'subsystem', for example:
+
+* With the 'subsystem' reflog: after 'git-fetch', the old tip of
+ 'subsystem' is at `subsystem@\{1}`. Subsequent fetches will
+ increase the number. (See linkgit:git-reflog[1].)
+
+* Relative to the tip of 'topic': knowing that your 'topic' has three
+ commits, the old tip of 'subsystem' must be `topic~3`.
+
+You can then transplant the old `subsystem..topic` to the new tip by
+saying (for the reflog case, and assuming you are on 'topic' already):
+------------
+ $ git rebase --onto subsystem subsystem@{1}
+------------
+
+The ripple effect of a "hard case" recovery is especially bad:
+'everyone' downstream from 'topic' will now have to perform a "hard
+case" recovery too!
+
+
Authors
------
Written by Junio C Hamano <gitster@pobox.com> and
diff --git a/Documentation/git-receive-pack.txt b/Documentation/git-receive-pack.txt
index 6b2f8c4de7..514f03c979 100644
--- a/Documentation/git-receive-pack.txt
+++ b/Documentation/git-receive-pack.txt
@@ -86,7 +86,7 @@ post-receive Hook
-----------------
After all refs were updated (or attempted to be updated), if any
ref update was successful, and if $GIT_DIR/hooks/post-receive
-file exists and is executable, it will be invoke once with no
+file exists and is executable, it will be invoked once with no
parameters. The standard input of the hook will be one line
for each successfully updated ref:
@@ -133,7 +133,7 @@ post-update Hook
----------------
After all other processing, if at least one ref was updated, and
if $GIT_DIR/hooks/post-update file exists and is executable, then
-post-update will called with the list of refs that have been updated.
+post-update will be called with the list of refs that have been updated.
This can be used to implement any repository wide cleanup tasks.
The exit code from this hook invocation is ignored; the only thing
diff --git a/Documentation/git-reflog.txt b/Documentation/git-reflog.txt
index d99236e14d..7f7a5445c7 100644
--- a/Documentation/git-reflog.txt
+++ b/Documentation/git-reflog.txt
@@ -28,7 +28,7 @@ updated. This command is to manage the information recorded in it.
The subcommand "expire" is used to prune older reflog entries.
Entries older than `expire` time, or entries older than
-`expire-unreachable` time and are not reachable from the current
+`expire-unreachable` time and not reachable from the current
tip, are removed from the reflog. This is typically not used
directly by the end users -- instead, see linkgit:git-gc[1].
@@ -71,7 +71,7 @@ them.
which in turn defaults to 90 days.
--expire-unreachable=<time>::
- Entries older than this time and are not reachable from
+ Entries older than this time and not reachable from
the current tip of the branch are pruned. Without the
option it is taken from configuration
`gc.reflogExpireUnreachable`, which in turn defaults to
diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt
index bb99810ec7..fad983e297 100644
--- a/Documentation/git-remote.txt
+++ b/Documentation/git-remote.txt
@@ -11,6 +11,7 @@ SYNOPSIS
[verse]
'git remote' [-v | --verbose]
'git remote add' [-t <branch>] [-m <master>] [-f] [--mirror] <name> <url>
+'git remote rename' <old> <new>
'git remote rm' <name>
'git remote show' [-n] <name>
'git remote prune' [-n | --dry-run] <name>
@@ -61,6 +62,15 @@ only makes sense in bare repositories. If a remote uses mirror
mode, furthermore, `git push` will always behave as if `\--mirror`
was passed.
+'rename'::
+
+Rename the remote named <old> to <new>. All remote tracking branches and
+configuration settings for the remote are updated.
++
+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.
+
'rm'::
Remove the remote named <name>. All remote tracking branches and
diff --git a/Documentation/git-repack.txt b/Documentation/git-repack.txt
index bbe1485a97..aaa8852629 100644
--- a/Documentation/git-repack.txt
+++ b/Documentation/git-repack.txt
@@ -38,12 +38,11 @@ OPTIONS
dangling.
-A::
- Same as `-a`, but any unreachable objects in a previous
- pack become loose, unpacked objects, instead of being
- left in the old pack. Unreachable objects are never
- intentionally added to a pack, even when repacking.
- When used with '-d', this option
- prevents unreachable objects from being immediately
+ Same as `-a`, unless '-d' is used. Then any unreachable
+ objects in a previous pack become loose, unpacked objects,
+ instead of being left in the old pack. Unreachable objects
+ are never intentionally added to a pack, even when repacking.
+ This option prevents unreachable objects from being immediately
deleted by way of being left in the old pack and then
removed. Instead, the loose unreachable objects
will be pruned according to normal expiry rules
diff --git a/Documentation/git-reset.txt b/Documentation/git-reset.txt
index 6abaeac28c..abb25d1c00 100644
--- a/Documentation/git-reset.txt
+++ b/Documentation/git-reset.txt
@@ -8,7 +8,7 @@ git-reset - Reset current HEAD to the specified state
SYNOPSIS
--------
[verse]
-'git reset' [--mixed | --soft | --hard] [-q] [<commit>]
+'git reset' [--mixed | --soft | --hard | --merge] [-q] [<commit>]
'git reset' [-q] [<commit>] [--] <paths>...
DESCRIPTION
@@ -45,6 +45,11 @@ OPTIONS
switched to. Any changes to tracked files in the working tree
since <commit> are lost.
+--merge::
+ Resets the index to match the tree recorded by the named commit,
+ and updates the files that are different between the named commit
+ and the current commit in the working tree.
+
-q::
Be quiet, only report errors.
@@ -82,7 +87,9 @@ $ git reset --hard HEAD~3 <1>
+
<1> The last three commits (HEAD, HEAD^, and HEAD~2) were bad
and you do not want to ever see them again. Do *not* do this if
-you have already given these commits to somebody else.
+you have already given these commits to somebody else. (See the
+"RECOVERING FROM UPSTREAM REBASE" section in linkgit:git-rebase[1] for
+the implications of doing so.)
Undo a commit, making it a topic branch::
+
@@ -128,7 +135,7 @@ Undo a merge or pull::
$ git pull <1>
Auto-merging nitfol
CONFLICT (content): Merge conflict in nitfol
-Automatic merge failed/prevented; fix up by hand
+Automatic merge failed; fix conflicts and then commit the result.
$ git reset --hard <2>
$ git pull . topic/branch <3>
Updating from 41223... to 13134...
@@ -150,6 +157,28 @@ tip of the current branch in ORIG_HEAD, so resetting hard to it
brings your index file and the working tree back to that state,
and resets the tip of the branch to that commit.
+Undo a merge or pull inside a dirty work tree::
++
+------------
+$ git pull <1>
+Auto-merging nitfol
+Merge made by recursive.
+ nitfol | 20 +++++----
+ ...
+$ git reset --merge ORIG_HEAD <2>
+------------
++
+<1> Even if you may have local modifications in your
+working tree, you can safely say "git pull" when you know
+that the change in the other branch does not overlap with
+them.
+<2> After inspecting the result of the merge, you may find
+that the change in the other branch is unsatisfactory. Running
+"git reset --hard ORIG_HEAD" will let you go back to where you
+were, but it will discard your local changes, which you do not
+want. "git reset --merge" keeps your local changes.
+
+
Interrupted workflow::
+
Suppose you are interrupted by an urgent fix request while you
@@ -175,6 +204,8 @@ $ git reset <3>
<3> At this point the index file still has all the WIP changes you
committed as 'snapshot WIP'. This updates the index to show your
WIP files as uncommitted.
++
+See also linkgit:git-stash[1].
Reset a single file in the index::
+
diff --git a/Documentation/git-revert.txt b/Documentation/git-revert.txt
index caa07298a6..5e1175800a 100644
--- a/Documentation/git-revert.txt
+++ b/Documentation/git-revert.txt
@@ -44,6 +44,14 @@ OPTIONS
option specifies the parent number (starting from 1) of
the mainline and allows revert to reverse the change
relative to the specified parent.
++
+Reverting a merge commit declares that you will never want the tree changes
+brought in by the merge. As a result, later merges will only bring in tree
+changes introduced by commits that are not ancestors of the previously
+reverted merge. This may or may not be what you want.
++
+See the link:howto/revert-a-faulty-merge.txt[revert-a-faulty-merge How-To] for
+more details.
--no-edit::
With this option, 'git-revert' will not start the commit
diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt
index 82f505686e..ff4aeff4e6 100644
--- a/Documentation/git-send-email.txt
+++ b/Documentation/git-send-email.txt
@@ -8,7 +8,7 @@ git-send-email - Send a collection of patches as emails
SYNOPSIS
--------
-'git send-email' [options] <file|directory> [... file|directory]
+'git send-email' [options] <file|directory|rev-list options>...
DESCRIPTION
@@ -34,12 +34,27 @@ The --bcc option must be repeated for each user you want on the bcc list.
--cc::
Specify a starting "Cc:" value for each email.
+ Default is the value of 'sendemail.cc'.
+
The --cc option must be repeated for each user you want on the cc list.
+--annotate::
+ Review each patch you're about to send in an editor. The setting
+ 'sendemail.multiedit' defines if this will spawn one editor per patch
+ or one for all of them at once.
+
--compose::
Use $GIT_EDITOR, core.editor, $VISUAL, or $EDITOR to edit an
introductory message for the patch series.
++
+When '--compose' is used, git send-email gets less interactive will use the
+values of the headers you set there. If the body of the email (what you type
+after the headers and a blank line) only contains blank (or GIT: prefixed)
+lines, the summary won't be sent, but git-send-email will still use the
+Headers values if you don't removed them.
++
+If it wasn't able to see a header in the summary it will ask you about it
+interactively after quitting your editor.
--from::
Specify the sender of the emails. This will default to
@@ -192,6 +207,12 @@ Administering
Default is the value of 'sendemail.validate'; if this is not set,
default to '--validate'.
+--[no-]format-patch::
+ When an argument may be understood either as a reference or as a file name,
+ choose to understand it as a format-patch argument ('--format-patch')
+ or as a file name ('--no-format-patch'). By default, when such a conflict
+ occurs, git send-email will fail.
+
CONFIGURATION
-------------
@@ -204,6 +225,12 @@ sendemail.aliasfiletype::
Format of the file(s) specified in sendemail.aliasesfile. Must be
one of 'mutt', 'mailrc', 'pine', or 'gnus'.
+sendemail.multiedit::
+ If true (default), a single editor instance will be spawned to edit
+ files you have to edit (patches when '--annotate' is used, and the
+ summary when '--compose' is used). If false, files will be edited one
+ after the other, spawning a new editor each time.
+
Author
------
diff --git a/Documentation/git-shortlog.txt b/Documentation/git-shortlog.txt
index 7ccf31ccc4..8f7c0e226d 100644
--- a/Documentation/git-shortlog.txt
+++ b/Documentation/git-shortlog.txt
@@ -48,15 +48,41 @@ OPTIONS
FILES
-----
-If the file `.mailmap` exists, it will be used for mapping author
-email addresses to a real author name. One mapping per line, first
-the author name followed by the email address enclosed by
-'<' and '>'. Use hash '#' for comments. Example:
+If a file `.mailmap` exists at the toplevel of the repository,
+it is used to map an author email address to a canonical real name. This
+can be used to coalesce together commits by the same person where their
+name was spelled differently (whether with the same email address or
+not).
+
+Each line in the file consists, in this order, of the canonical real name
+of an author, whitespace, and an email address (enclosed by '<' and '>')
+to map to the name. Use hash '#' for comments, either on their own line,
+or after the email address.
+
+A canonical name may appear in more than one line, associated with
+different email addresses, but it doesn't make sense for a given address
+to appear more than once (if that happens, a later line overrides the
+earlier ones).
+
+So, for example, if your history contains commits by two authors, Jane
+and Joe, whose names appear in the repository under several forms:
+
+------------
+Joe Developer <joe@example.com>
+Joe R. Developer <joe@example.com>
+Jane Doe <jane@example.com>
+Jane Doe <jane@laptop.(none)>
+Jane D. <jane@desktop.(none)>
+------------
+
+Then, supposing Joe wants his middle name initial used, and Jane prefers
+her family name fully spelled out, a proper `.mailmap` file would look like:
------------
-# Keep alphabetized
-Adam Morrow <adam@localhost.localdomain>
-Eve Jones <eve@laptop.(none)>
+# Note how we don't need an entry for <jane@laptop.(none)>, because the
+# real name of that author is correct already, and coalesced directly.
+Jane Doe <jane@desktop.(none)>
+Joe R. Developer <joe@random.com>
------------
Author
diff --git a/Documentation/git-show-branch.txt b/Documentation/git-show-branch.txt
index d3f258869f..8277577a6f 100644
--- a/Documentation/git-show-branch.txt
+++ b/Documentation/git-show-branch.txt
@@ -30,7 +30,7 @@ OPTIONS
-------
<rev>::
Arbitrary extended SHA1 expression (see linkgit:git-rev-parse[1])
- that typically names a branch HEAD or a tag.
+ that typically names a branch head or a tag.
<glob>::
A glob pattern that matches branch or tag names under
@@ -172,7 +172,7 @@ only the primary branches. In addition, if you happen to be on
your topic branch, it is shown as well.
------------
-$ git show-branch --reflog='10,1 hour ago' --list master
+$ git show-branch --reflog="10,1 hour ago" --list master
------------
shows 10 reflog entries going back from the tip as of 1 hour ago.
diff --git a/Documentation/git-stage.txt b/Documentation/git-stage.txt
new file mode 100644
index 0000000000..7f251a5865
--- /dev/null
+++ b/Documentation/git-stage.txt
@@ -0,0 +1,19 @@
+git-stage(1)
+==============
+
+NAME
+----
+git-stage - Add file contents to the staging area
+
+
+SYNOPSIS
+--------
+[verse]
+'git stage' args...
+
+
+DESCRIPTION
+-----------
+
+This is a synonym for linkgit:git-add[1]. Please refer to the
+documentation of that command.
diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index babaa9bc46..2f207fbbda 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -87,7 +87,7 @@ use by subsequent users cloning the superproject. If the URL is
given relative to the superproject's repository, the presumption
is the superproject and submodule repositories will be kept
together in the same relative location, and only the
-superproject's URL need be provided: git-submodule will correctly
+superproject's URL needs to be provided: git-submodule will correctly
locate the submodule using the relative URL in .gitmodules.
status::
diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index 84c8f3cde0..8d0c421b80 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -109,7 +109,7 @@ COMMANDS
This works similarly to `svn update` or 'git-pull' except that
it preserves linear history with 'git-rebase' instead of
-'git-merge' for ease of dcommiting with 'git-svn'.
+'git-merge' for ease of dcommitting with 'git-svn'.
This accepts all options that 'git-svn fetch' and 'git-rebase'
accept. However, '--fetch-all' only fetches from the current
@@ -544,6 +544,8 @@ have each person clone that repository with 'git-clone':
git remote add origin server:/pub/project
git config --add remote.origin.fetch '+refs/remotes/*:refs/remotes/*'
git fetch
+# Create a local branch from one of the branches just fetched
+ git checkout -b master FETCH_HEAD
# Initialize git-svn locally (be sure to use the same URL and -T/-b/-t options as were used on server)
git svn init http://svn.example.com/project
# Pull the latest changes from Subversion
diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt
index 046ab3542b..e44f543025 100644
--- a/Documentation/git-tag.txt
+++ b/Documentation/git-tag.txt
@@ -70,7 +70,7 @@ OPTIONS
-m <msg>::
Use the given tag message (instead of prompting).
- If multiple `-m` options are given, there values are
+ If multiple `-m` options are given, their values are
concatenated as separate paragraphs.
Implies `-a` if none of `-a`, `-s`, or `-u <key-id>`
is given.
@@ -207,7 +207,7 @@ determines who are interested in whose tags.
A one-shot pull is a sign that a commit history is now crossing
the boundary between one circle of people (e.g. "people who are
-primarily interested in networking part of the kernel") who may
+primarily interested in the networking part of the kernel") who may
have their own set of tags (e.g. "this is the third release
candidate from the networking group to be proposed for general
consumption with 2.6.21 release") to another circle of people
diff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.txt
index 1d9d81a702..25e0bbea86 100644
--- a/Documentation/git-update-index.txt
+++ b/Documentation/git-update-index.txt
@@ -55,7 +55,7 @@ OPTIONS
default behavior is to error out. This option makes
'git-update-index' continue anyway.
---ignore-submodules:
+--ignore-submodules::
Do not try to update submodules. This option is only respected
when passed before --refresh.
@@ -78,9 +78,9 @@ OPTIONS
--assume-unchanged::
--no-assume-unchanged::
- When these flags are specified, the object name recorded
+ When these flags are specified, the object names recorded
for the paths are not updated. Instead, these options
- sets and unsets the "assume unchanged" bit for the
+ set and unset the "assume unchanged" bit for the
paths. When the "assume unchanged" bit is on, git stops
checking the working tree files for possible
modifications, so you need to manually unset the bit to
@@ -122,7 +122,7 @@ you will need to handle the situation manually.
'git-update-index' refuses an attempt to add `path/file`.
Similarly if a file `path/file` exists, a file `path`
cannot be added. With --replace flag, existing entries
- that conflicts with the entry being added are
+ that conflict with the entry being added are
automatically removed with warning messages.
--stdin::
diff --git a/Documentation/git.txt b/Documentation/git.txt
index df420aeb33..17dc8b2019 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -43,16 +43,26 @@ unreleased) version of git, that is available from 'master'
branch of the `git.git` repository.
Documentation for older releases are available here:
-* link:v1.6.0.2/git.html[documentation for release 1.6.0.2]
+* link:v1.6.1/git.html[documentation for release 1.6.1]
* release notes for
+ link:RelNotes-1.6.1.txt[1.6.1].
+
+* link:v1.6.0.6/git.html[documentation for release 1.6.0.6]
+
+* release notes for
+ link:RelNotes-1.6.0.6.txt[1.6.0.6],
+ link:RelNotes-1.6.0.5.txt[1.6.0.5],
+ link:RelNotes-1.6.0.4.txt[1.6.0.4],
+ link:RelNotes-1.6.0.3.txt[1.6.0.3],
link:RelNotes-1.6.0.2.txt[1.6.0.2],
link:RelNotes-1.6.0.1.txt[1.6.0.1],
link:RelNotes-1.6.0.txt[1.6.0].
-* link:v1.5.6.5/git.html[documentation for release 1.5.6.5]
+* link:v1.5.6.6/git.html[documentation for release 1.5.6.6]
* release notes for
+ link:RelNotes-1.5.6.6.txt[1.5.6.6],
link:RelNotes-1.5.6.5.txt[1.5.6.5],
link:RelNotes-1.5.6.4.txt[1.5.6.4],
link:RelNotes-1.5.6.3.txt[1.5.6.3],
@@ -60,18 +70,22 @@ Documentation for older releases are available here:
link:RelNotes-1.5.6.1.txt[1.5.6.1],
link:RelNotes-1.5.6.txt[1.5.6].
-* link:v1.5.5.4/git.html[documentation for release 1.5.5.4]
+* link:v1.5.5.6/git.html[documentation for release 1.5.5.6]
* release notes for
+ link:RelNotes-1.5.5.6.txt[1.5.5.6],
+ link:RelNotes-1.5.5.5.txt[1.5.5.5],
link:RelNotes-1.5.5.4.txt[1.5.5.4],
link:RelNotes-1.5.5.3.txt[1.5.5.3],
link:RelNotes-1.5.5.2.txt[1.5.5.2],
link:RelNotes-1.5.5.1.txt[1.5.5.1],
link:RelNotes-1.5.5.txt[1.5.5].
-* link:v1.5.4.5/git.html[documentation for release 1.5.4.5]
+* link:v1.5.4.7/git.html[documentation for release 1.5.4.7]
* release notes for
+ link:RelNotes-1.5.4.7.txt[1.5.4.7],
+ link:RelNotes-1.5.4.6.txt[1.5.4.6],
link:RelNotes-1.5.4.5.txt[1.5.4.5],
link:RelNotes-1.5.4.4.txt[1.5.4.4],
link:RelNotes-1.5.4.3.txt[1.5.4.3],
diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt
index 26945593cb..8af22eccac 100644
--- a/Documentation/gitattributes.txt
+++ b/Documentation/gitattributes.txt
@@ -163,8 +163,8 @@ few exceptions. Even though...
`ident`
^^^^^^^
-When the attribute `ident` is set to a path, git replaces
-`$Id$` in the blob object with `$Id:`, followed by
+When the attribute `ident` is set for a path, git replaces
+`$Id$` in the blob object with `$Id:`, followed by the
40-character hexadecimal blob object name, followed by a dollar
sign `$` upon checkout. Any byte sequence that begins with
`$Id:` and ends with `$` in the worktree file is replaced
@@ -213,10 +213,15 @@ with `crlf`, and then `ident` and fed to `filter`.
Generating diff text
~~~~~~~~~~~~~~~~~~~~
-The attribute `diff` affects if 'git-diff' generates textual
-patch for the path or just says `Binary files differ`. It also
-can affect what line is shown on the hunk header `@@ -k,l +n,m @@`
-line.
+`diff`
+^^^^^^
+
+The attribute `diff` affects how 'git' generates diffs for particular
+files. It can tell git whether to generate a textual patch for the path
+or to treat the path as a binary file. It can also affect what line is
+shown on the hunk header `@@ -k,l +n,m @@` line, tell git to use an
+external command to generate the diff, or ask git to convert binary
+files to a text format before generating the diff.
Set::
@@ -227,7 +232,8 @@ Set::
Unset::
A path to which the `diff` attribute is unset will
- generate `Binary files differ`.
+ generate `Binary files differ` (or a binary patch, if
+ binary patches are enabled).
Unspecified::
@@ -238,21 +244,21 @@ Unspecified::
String::
- Diff is shown using the specified custom diff driver.
- The driver program is given its input using the same
- calling convention as used for GIT_EXTERNAL_DIFF
- program. This name is also used for custom hunk header
- selection.
+ Diff is shown using the specified diff driver. Each driver may
+ specify one or more options, as described in the following
+ section. The options for the diff driver "foo" are defined
+ by the configuration variables in the "diff.foo" section of the
+ git config file.
-Defining a custom diff driver
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Defining an external diff driver
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The definition of a diff driver is done in `gitconfig`, not
`gitattributes` file, so strictly speaking this manual page is a
wrong place to talk about it. However...
-To define a custom diff driver `jcdiff`, add a section to your
+To define an external diff driver `jcdiff`, add a section to your
`$GIT_DIR/config` file (or `$HOME/.gitconfig` file) like this:
----------------------------------------------------------------
@@ -328,9 +334,49 @@ patterns are available:
- `tex` suitable for source code for LaTeX documents.
+Performing text diffs of binary files
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Sometimes it is desirable to see the diff of a text-converted
+version of some binary files. For example, a word processor
+document can be converted to an ASCII text representation, and
+the diff of the text shown. Even though this conversion loses
+some information, the resulting diff is useful for human
+viewing (but cannot be applied directly).
+
+The `textconv` config option is used to define a program for
+performing such a conversion. The program should take a single
+argument, the name of a file to convert, and produce the
+resulting text on stdout.
+
+For example, to show the diff of the exif information of a
+file instead of the binary information (assuming you have the
+exif tool installed):
+
+------------------------
+[diff "jpg"]
+ textconv = exif
+------------------------
+
+NOTE: The text conversion is generally a one-way conversion;
+in this example, we lose the actual image contents and focus
+just on the text data. This means that diffs generated by
+textconv are _not_ suitable for applying. For this reason,
+only `git diff` and the `git log` family of commands (i.e.,
+log, whatchanged, show) will perform text conversion. `git
+format-patch` will never generate this output. If you want to
+send somebody a text-converted diff of a binary file (e.g.,
+because it quickly conveys the changes you have made), you
+should generate it separately and send it as a comment _in
+addition to_ the usual binary diff that you might send.
+
+
Performing a three-way merge
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+`merge`
+^^^^^^^
+
The attribute `merge` affects how three versions of a file is
merged when a file-level merge is necessary during `git merge`,
and other programs such as `git revert` and `git cherry-pick`.
@@ -489,6 +535,23 @@ in the file. E.g. the string `$Format:%H$` will be replaced by the
commit hash.
+Viewing files in GUI tools
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+`encoding`
+^^^^^^^^^^
+
+The value of this attribute specifies the character encoding that should
+be used by GUI tools (e.g. linkgit:gitk[1] and linkgit:git-gui[1]) to
+display the contents of the relevant file. Note that due to performance
+considerations linkgit:gitk[1] does not use this attribute unless you
+manually enable per-file encodings in its options.
+
+If this attribute is not set or has an invalid value, the value of the
+`gui.encoding` configuration variable is used instead
+(See linkgit:git-config[1]).
+
+
USING ATTRIBUTE MACROS
----------------------
diff --git a/Documentation/gitcore-tutorial.txt b/Documentation/gitcore-tutorial.txt
index a417e592ac..7ba5e589d7 100644
--- a/Documentation/gitcore-tutorial.txt
+++ b/Documentation/gitcore-tutorial.txt
@@ -899,7 +899,7 @@ file, which had no differences in the `mybranch` branch), and say:
----------------
Auto-merging hello
CONFLICT (content): Merge conflict in hello
- Automatic merge failed; fix up by hand
+ Automatic merge failed; fix conflicts and then commit the result.
----------------
It tells you that it did an "Automatic merge", which
@@ -993,14 +993,14 @@ would be different)
----------------
Updating from ae3a2da... to a80b4aa....
-Fast forward
+Fast forward (no commit created; -m option ignored)
example | 1 +
hello | 1 +
2 files changed, 2 insertions(+), 0 deletions(-)
----------------
-Because your branch did not contain anything more than what are
-already merged into the `master` branch, the merge operation did
+Because your branch did not contain anything more than what had
+already been merged into the `master` branch, the merge operation did
not actually do a merge. Instead, it just updated the top of
the tree of your branch to that of the `master` branch. This is
often called 'fast forward' merge.
@@ -1243,10 +1243,10 @@ $ git ls-files --stage
------------
In our example of only two files, we did not have unchanged
-files so only 'example' resulted in collapsing, but in real-life
-large projects, only small number of files change in one commit,
-and this 'collapsing' tends to trivially merge most of the paths
-fairly quickly, leaving only a handful the real changes in non-zero
+files so only 'example' resulted in collapsing. But in real-life
+large projects, when only a small number of files change in one commit,
+this 'collapsing' tends to trivially merge most of the paths
+fairly quickly, leaving only a handful of real changes in non-zero
stages.
To look at only non-zero stages, use `\--unmerged` flag:
@@ -1265,9 +1265,8 @@ file, using 3-way merge. This is done by giving
------------
$ git merge-index git-merge-one-file hello
-Auto-merging hello.
-merge: warning: conflicts during merge
-ERROR: Merge conflict in hello.
+Auto-merging hello
+ERROR: Merge conflict in hello
fatal: merge program failed
------------
@@ -1353,7 +1352,7 @@ $ GIT_DIR=my-git.git git init
------------
Make sure this directory is available for others you want your
-changes to be pulled by via the transport of your choice. Also
+changes to be pulled via the transport of your choice. Also
you need to make sure that you have the 'git-receive-pack'
program on the `$PATH`.
@@ -1447,7 +1446,7 @@ public repository you might want to repack & prune often, or
never.
If you run `git repack` again at this point, it will say
-"Nothing to pack". Once you continue your development and
+"Nothing new to pack.". Once you continue your development and
accumulate the changes, running `git repack` again will create a
new pack, that contains objects created since you packed your
repository the last time. We recommend that you pack your project
@@ -1512,7 +1511,7 @@ You can repack this private repository whenever you feel like.
6. Push your changes to the public repository, and announce it
to the public.
-7. Every once in a while, "git-repack" the public repository.
+7. Every once in a while, 'git-repack' the public repository.
Go back to step 5. and continue working.
@@ -1690,8 +1689,11 @@ to follow, not easier.
SEE ALSO
--------
-linkgit:gittutorial[7], linkgit:gittutorial-2[7],
-linkgit:everyday[7], linkgit:gitcvs-migration[7],
+linkgit:gittutorial[7],
+linkgit:gittutorial-2[7],
+linkgit:gitcvs-migration[7],
+linkgit:git-help[1],
+link:everyday.html[Everyday git],
link:user-manual.html[The Git User's Manual]
GIT
diff --git a/Documentation/gitglossary.txt b/Documentation/gitglossary.txt
index 565719ed5f..d77a45aed6 100644
--- a/Documentation/gitglossary.txt
+++ b/Documentation/gitglossary.txt
@@ -16,8 +16,10 @@ include::glossary-content.txt[]
SEE ALSO
--------
-linkgit:gittutorial[7], linkgit:gittutorial-2[7],
-linkgit:everyday[7], linkgit:gitcvs-migration[7],
+linkgit:gittutorial[7],
+linkgit:gittutorial-2[7],
+linkgit:gitcvs-migration[7],
+link:everyday.html[Everyday git],
link:user-manual.html[The Git User's Manual]
GIT
diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt
index 5faaaa5fed..1fd512bca2 100644
--- a/Documentation/githooks.txt
+++ b/Documentation/githooks.txt
@@ -15,11 +15,15 @@ DESCRIPTION
Hooks are little scripts you can place in `$GIT_DIR/hooks`
directory to trigger action at certain points. When
-'git-init' is run, a handful example hooks are copied in the
+'git-init' is run, a handful of example hooks are copied into the
`hooks` directory of the new repository, but by default they are
all disabled. To enable a hook, rename it by removing its `.sample`
suffix.
+NOTE: It is also a requirement for a given hook to be executable.
+However - in a freshly initialized repository - the `.sample` files are
+executable by default.
+
This document describes the currently defined hooks.
applypatch-msg
@@ -86,7 +90,7 @@ This hook is invoked by 'git-commit' right after preparing the
default log message, and before the editor is started.
It takes one to three parameters. The first is the name of the file
-that the commit log message. The second is the source of the commit
+that contains the commit log message. The second is the source of the commit
message, and can be: `message` (if a `-m` or `-F` option was
given); `template` (if a `-t` option was given or the
configuration option `commit.template` is set); `merge` (if the
diff --git a/Documentation/gitk.txt b/Documentation/gitk.txt
index ae29a00d59..4673a75a98 100644
--- a/Documentation/gitk.txt
+++ b/Documentation/gitk.txt
@@ -21,7 +21,7 @@ git repository.
OPTIONS
-------
-To control which revisions to shown, the command takes options applicable to
+To control which revisions to show, the command takes options applicable to
the 'git-rev-list' command (see linkgit:git-rev-list[1]).
This manual page describes only the most
frequently used options.
@@ -56,6 +56,11 @@ frequently used options.
Use this instead of explicitly specifying <revs> if the set of
commits to show may vary between refreshes.
+--select-commit=<ref>::
+
+ Automatically select the specified commit after loading the graph.
+ Default behavior is equivalent to specifying '--select-commit=HEAD'.
+
<revs>::
Limit the revisions to show. This can be either a single revision
@@ -75,7 +80,7 @@ Examples
--------
gitk v2.6.12.. include/scsi drivers/scsi::
- Show as the changes since version 'v2.6.12' that changed any
+ Show the changes since version 'v2.6.12' that changed any
file in the include/scsi or drivers/scsi subdirectories
gitk --since="2 weeks ago" \-- gitk::
diff --git a/Documentation/gitrepository-layout.txt b/Documentation/gitrepository-layout.txt
index a969b3fbc3..1befca98d4 100644
--- a/Documentation/gitrepository-layout.txt
+++ b/Documentation/gitrepository-layout.txt
@@ -134,7 +134,8 @@ hooks::
Hooks are customization scripts used by various git
commands. A handful of sample hooks are installed when
'git-init' is run, but all of them are disabled by
- default. To enable, they need to be made executable.
+ default. To enable, the `.sample` suffix has to be
+ removed from the filename by renaming.
Read linkgit:githooks[5] for more details about
each hook.
diff --git a/Documentation/gittutorial-2.txt b/Documentation/gittutorial-2.txt
index 660904686c..a057b50b2b 100644
--- a/Documentation/gittutorial-2.txt
+++ b/Documentation/gittutorial-2.txt
@@ -32,22 +32,27 @@ Initialized empty Git repository in .git/
$ echo 'hello world' > file.txt
$ git add .
$ git commit -a -m "initial commit"
-Created initial commit 54196cc2703dc165cbd373a65a4dcf22d50ae7f7
+[master (root-commit)] created 54196cc: "initial commit"
+ 1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 file.txt
$ echo 'hello world!' >file.txt
$ git commit -a -m "add emphasis"
-Created commit c4d59f390b9cfd4318117afde11d601c1085f241
+[master] created c4d59f3: "add emphasis"
+ 1 files changed, 1 insertions(+), 1 deletions(-)
------------------------------------------------
-What are the 40 digits of hex that git responded to the commit with?
+What are the 7 digits of hex that git responded to the commit with?
We saw in part one of the tutorial that commits have names like this.
It turns out that every object in the git history is stored under
-such a 40-digit hex name. That name is the SHA1 hash of the object's
+a 40-digit hex name. That name is the SHA1 hash of the object's
contents; among other things, this ensures that git will never store
the same data twice (since identical data is given an identical SHA1
name), and that the contents of a git object will never change (since
-that would change the object's name as well).
+that would change the object's name as well). The 7 char hex strings
+here are simply the abbreviation of such 40 character long strings.
+Abbreviations can be used everywhere where the 40 character strings
+can be used, so long as they are unambiguous.
It is expected that the content of the commit object you created while
following the example above generates a different SHA1 hash than
@@ -420,6 +425,7 @@ linkgit:gittutorial[7],
linkgit:gitcvs-migration[7],
linkgit:gitcore-tutorial[7],
linkgit:gitglossary[7],
+linkgit:git-help[1],
link:everyday.html[Everyday git],
link:user-manual.html[The Git User's Manual]
diff --git a/Documentation/gittutorial.txt b/Documentation/gittutorial.txt
index 384972cb9b..458fafdb2c 100644
--- a/Documentation/gittutorial.txt
+++ b/Documentation/gittutorial.txt
@@ -26,6 +26,15 @@ First, note that you can get documentation for a command such as
$ man git-log
------------------------------------------------
+or:
+
+------------------------------------------------
+$ git help log
+------------------------------------------------
+
+With the latter, you can use the manual viewer of your choice; see
+linkgit:git-help[1] for more information.
+
It is a good idea to introduce yourself to git with your name and
public email address before doing any operation. The easiest
way to do so is:
@@ -581,7 +590,7 @@ list. When the history has lines of development that diverged and
then merged back together, the order in which 'git-log' presents
those commits is meaningless.
-Most projects with multiple contributors (such as the linux kernel,
+Most projects with multiple contributors (such as the Linux kernel,
or git itself) have frequent merges, and 'gitk' does a better job of
visualizing their history. For example,
@@ -633,7 +642,7 @@ digressions that may be interesting at this point are:
* linkgit:git-format-patch[1], linkgit:git-am[1]: These convert
series of git commits into emailed patches, and vice versa,
- useful for projects such as the linux kernel which rely heavily
+ useful for projects such as the Linux kernel which rely heavily
on emailed patches.
* linkgit:git-bisect[1]: When there is a regression in your
@@ -653,6 +662,7 @@ linkgit:gittutorial-2[7],
linkgit:gitcvs-migration[7],
linkgit:gitcore-tutorial[7],
linkgit:gitglossary[7],
+linkgit:git-help[1],
link:everyday.html[Everyday git],
link:user-manual.html[The Git User's Manual]
diff --git a/Documentation/gitworkflows.txt b/Documentation/gitworkflows.txt
new file mode 100644
index 0000000000..2b021e3c15
--- /dev/null
+++ b/Documentation/gitworkflows.txt
@@ -0,0 +1,364 @@
+gitworkflows(7)
+===============
+
+NAME
+----
+gitworkflows - An overview of recommended workflows with git
+
+SYNOPSIS
+--------
+git *
+
+
+DESCRIPTION
+-----------
+
+This document attempts to write down and motivate some of the workflow
+elements used for `git.git` itself. Many ideas apply in general,
+though the full workflow is rarely required for smaller projects with
+fewer people involved.
+
+We formulate a set of 'rules' for quick reference, while the prose
+tries to motivate each of them. Do not always take them literally;
+you should value good reasons for your actions higher than manpages
+such as this one.
+
+
+SEPARATE CHANGES
+----------------
+
+As a general rule, you should try to split your changes into small
+logical steps, and commit each of them. They should be consistent,
+working independently of any later commits, pass the test suite, etc.
+This makes the review process much easier, and the history much more
+useful for later inspection and analysis, for example with
+linkgit:git-blame[1] and linkgit:git-bisect[1].
+
+To achieve this, try to split your work into small steps from the very
+beginning. It is always easier to squash a few commits together than
+to split one big commit into several. Don't be afraid of making too
+small or imperfect steps along the way. You can always go back later
+and edit the commits with `git rebase \--interactive` before you
+publish them. You can use `git stash save \--keep-index` to run the
+test suite independent of other uncommitted changes; see the EXAMPLES
+section of linkgit:git-stash[1].
+
+
+MANAGING BRANCHES
+-----------------
+
+There are two main tools that can be used to include changes from one
+branch on another: linkgit:git-merge[1] and
+linkgit:git-cherry-pick[1].
+
+Merges have many advantages, so we try to solve as many problems as
+possible with merges alone. Cherry-picking is still occasionally
+useful; see "Merging upwards" below for an example.
+
+Most importantly, merging works at the branch level, while
+cherry-picking works at the commit level. This means that a merge can
+carry over the changes from 1, 10, or 1000 commits with equal ease,
+which in turn means the workflow scales much better to a large number
+of contributors (and contributions). Merges are also easier to
+understand because a merge commit is a "promise" that all changes from
+all its parents are now included.
+
+There is a tradeoff of course: merges require a more careful branch
+management. The following subsections discuss the important points.
+
+
+Graduation
+~~~~~~~~~~
+
+As a given feature goes from experimental to stable, it also
+"graduates" between the corresponding branches of the software.
+`git.git` uses the following 'integration branches':
+
+* 'maint' tracks the commits that should go into the next "maintenance
+ release", i.e., update of the last released stable version;
+
+* 'master' tracks the commits that should go into the next release;
+
+* 'next' is intended as a testing branch for topics being tested for
+ stability for master.
+
+There is a fourth official branch that is used slightly differently:
+
+* 'pu' (proposed updates) is an integration branch for things that are
+ not quite ready for inclusion yet (see "Integration Branches"
+ below).
+
+Each of the four branches is usually a direct descendant of the one
+above it.
+
+Conceptually, the feature enters at an unstable branch (usually 'next'
+or 'pu'), and "graduates" to 'master' for the next release once it is
+considered stable enough.
+
+
+Merging upwards
+~~~~~~~~~~~~~~~
+
+The "downwards graduation" discussed above cannot be done by actually
+merging downwards, however, since that would merge 'all' changes on
+the unstable branch into the stable one. Hence the following:
+
+.Merge upwards
+[caption="Rule: "]
+=====================================
+Always commit your fixes to the oldest supported branch that require
+them. Then (periodically) merge the integration branches upwards into each
+other.
+=====================================
+
+This gives a very controlled flow of fixes. If you notice that you
+have applied a fix to e.g. 'master' that is also required in 'maint',
+you will need to cherry-pick it (using linkgit:git-cherry-pick[1])
+downwards. This will happen a few times and is nothing to worry about
+unless you do it very frequently.
+
+
+Topic branches
+~~~~~~~~~~~~~~
+
+Any nontrivial feature will require several patches to implement, and
+may get extra bugfixes or improvements during its lifetime.
+
+Committing everything directly on the integration branches leads to many
+problems: Bad commits cannot be undone, so they must be reverted one
+by one, which creates confusing histories and further error potential
+when you forget to revert part of a group of changes. Working in
+parallel mixes up the changes, creating further confusion.
+
+Use of "topic branches" solves these problems. The name is pretty
+self explanatory, with a caveat that comes from the "merge upwards"
+rule above:
+
+.Topic branches
+[caption="Rule: "]
+=====================================
+Make a side branch for every topic (feature, bugfix, ...). Fork it off
+at the oldest integration branch that you will eventually want to merge it
+into.
+=====================================
+
+Many things can then be done very naturally:
+
+* To get the feature/bugfix into an integration branch, simply merge
+ it. If the topic has evolved further in the meantime, merge again.
+ (Note that you do not necessarily have to merge it to the oldest
+ integration branch first. For example, you can first merge a bugfix
+ to 'next', give it some testing time, and merge to 'maint' when you
+ know it is stable.)
+
+* If you find you need new features from the branch 'other' to continue
+ working on your topic, merge 'other' to 'topic'. (However, do not
+ do this "just habitually", see below.)
+
+* If you find you forked off the wrong branch and want to move it
+ "back in time", use linkgit:git-rebase[1].
+
+Note that the last point clashes with the other two: a topic that has
+been merged elsewhere should not be rebased. See the section on
+RECOVERING FROM UPSTREAM REBASE in linkgit:git-rebase[1].
+
+We should point out that "habitually" (regularly for no real reason)
+merging an integration branch into your topics -- and by extension,
+merging anything upstream into anything downstream on a regular basis
+-- is frowned upon:
+
+.Merge to downstream only at well-defined points
+[caption="Rule: "]
+=====================================
+Do not merge to downstream except with a good reason: upstream API
+changes affect your branch; your branch no longer merges to upstream
+cleanly; etc.
+=====================================
+
+Otherwise, the topic that was merged to suddenly contains more than a
+single (well-separated) change. The many resulting small merges will
+greatly clutter up history. Anyone who later investigates the history
+of a file will have to find out whether that merge affected the topic
+in development. An upstream might even inadvertently be merged into a
+"more stable" branch. And so on.
+
+
+Throw-away integration
+~~~~~~~~~~~~~~~~~~~~~~
+
+If you followed the last paragraph, you will now have many small topic
+branches, and occasionally wonder how they interact. Perhaps the
+result of merging them does not even work? But on the other hand, we
+want to avoid merging them anywhere "stable" because such merges
+cannot easily be undone.
+
+The solution, of course, is to make a merge that we can undo: merge
+into a throw-away branch.
+
+.Throw-away integration branches
+[caption="Rule: "]
+=====================================
+To test the interaction of several topics, merge them into a
+throw-away branch. You must never base any work on such a branch!
+=====================================
+
+If you make it (very) clear that this branch is going to be deleted
+right after the testing, you can even publish this branch, for example
+to give the testers a chance to work with it, or other developers a
+chance to see if their in-progress work will be compatible. `git.git`
+has such an official throw-away integration branch called 'pu'.
+
+
+DISTRIBUTED WORKFLOWS
+---------------------
+
+After the last section, you should know how to manage topics. In
+general, you will not be the only person working on the project, so
+you will have to share your work.
+
+Roughly speaking, there are two important workflows: merge and patch.
+The important difference is that the merge workflow can propagate full
+history, including merges, while patches cannot. Both workflows can
+be used in parallel: in `git.git`, only subsystem maintainers use
+the merge workflow, while everyone else sends patches.
+
+Note that the maintainer(s) may impose restrictions, such as
+"Signed-off-by" requirements, that all commits/patches submitted for
+inclusion must adhere to. Consult your project's documentation for
+more information.
+
+
+Merge workflow
+~~~~~~~~~~~~~~
+
+The merge workflow works by copying branches between upstream and
+downstream. Upstream can merge contributions into the official
+history; downstream base their work on the official history.
+
+There are three main tools that can be used for this:
+
+* linkgit:git-push[1] copies your branches to a remote repository,
+ usually to one that can be read by all involved parties;
+
+* linkgit:git-fetch[1] that copies remote branches to your repository;
+ and
+
+* linkgit:git-pull[1] that does fetch and merge in one go.
+
+Note the last point. Do 'not' use 'git-pull' unless you actually want
+to merge the remote branch.
+
+Getting changes out is easy:
+
+.Push/pull: Publishing branches/topics
+[caption="Recipe: "]
+=====================================
+`git push <remote> <branch>` and tell everyone where they can fetch
+from.
+=====================================
+
+You will still have to tell people by other means, such as mail. (Git
+provides the linkgit:git-request-pull[1] to send preformatted pull
+requests to upstream maintainers to simplify this task.)
+
+If you just want to get the newest copies of the integration branches,
+staying up to date is easy too:
+
+.Push/pull: Staying up to date
+[caption="Recipe: "]
+=====================================
+Use `git fetch <remote>` or `git remote update` to stay up to date.
+=====================================
+
+Then simply fork your topic branches from the stable remotes as
+explained earlier.
+
+If you are a maintainer and would like to merge other people's topic
+branches to the integration branches, they will typically send a
+request to do so by mail. Such a request looks like
+
+-------------------------------------
+Please pull from
+ <url> <branch>
+-------------------------------------
+
+In that case, 'git-pull' can do the fetch and merge in one go, as
+follows.
+
+.Push/pull: Merging remote topics
+[caption="Recipe: "]
+=====================================
+`git pull <url> <branch>`
+=====================================
+
+Occasionally, the maintainer may get merge conflicts when he tries to
+pull changes from downstream. In this case, he can ask downstream to
+do the merge and resolve the conflicts themselves (perhaps they will
+know better how to resolve them). It is one of the rare cases where
+downstream 'should' merge from upstream.
+
+
+Patch workflow
+~~~~~~~~~~~~~~
+
+If you are a contributor that sends changes upstream in the form of
+emails, you should use topic branches as usual (see above). Then use
+linkgit:git-format-patch[1] to generate the corresponding emails
+(highly recommended over manually formatting them because it makes the
+maintainer's life easier).
+
+.format-patch/am: Publishing branches/topics
+[caption="Recipe: "]
+=====================================
+* `git format-patch -M upstream..topic` to turn them into preformatted
+ patch files
+* `git send-email --to=<recipient> <patches>`
+=====================================
+
+See the linkgit:git-format-patch[1] and linkgit:git-send-email[1]
+manpages for further usage notes.
+
+If the maintainer tells you that your patch no longer applies to the
+current upstream, you will have to rebase your topic (you cannot use a
+merge because you cannot format-patch merges):
+
+.format-patch/am: Keeping topics up to date
+[caption="Recipe: "]
+=====================================
+`git pull --rebase <url> <branch>`
+=====================================
+
+You can then fix the conflicts during the rebase. Presumably you have
+not published your topic other than by mail, so rebasing it is not a
+problem.
+
+If you receive such a patch series (as maintainer, or perhaps as a
+reader of the mailing list it was sent to), save the mails to files,
+create a new topic branch and use 'git-am' to import the commits:
+
+.format-patch/am: Importing patches
+[caption="Recipe: "]
+=====================================
+`git am < patch`
+=====================================
+
+One feature worth pointing out is the three-way merge, which can help
+if you get conflicts: `git am -3` will use index information contained
+in patches to figure out the merge base. See linkgit:git-am[1] for
+other options.
+
+
+SEE ALSO
+--------
+linkgit:gittutorial[7],
+linkgit:git-push[1],
+linkgit:git-pull[1],
+linkgit:git-merge[1],
+linkgit:git-rebase[1],
+linkgit:git-format-patch[1],
+linkgit:git-send-email[1],
+linkgit:git-am[1]
+
+GIT
+---
+Part of the linkgit:git[1] suite.
diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt
index 9b4a4f45e9..9afca755ed 100644
--- a/Documentation/glossary-content.txt
+++ b/Documentation/glossary-content.txt
@@ -183,7 +183,8 @@ to point at the new commit.
and potentially aborted, and allow for a post-notification after the
operation is done. The hook scripts are found in the
`$GIT_DIR/hooks/` directory, and are enabled by simply
- making them executable.
+ removing the `.sample` suffix from the filename. In earlier versions
+ of git you had to make them executable.
[[def_index]]index::
A collection of files with stat information, whose contents are stored
diff --git a/Documentation/howto/rebase-from-internal-branch.txt b/Documentation/howto/rebase-from-internal-branch.txt
index d214d4bf9d..74a1c0c4ba 100644
--- a/Documentation/howto/rebase-from-internal-branch.txt
+++ b/Documentation/howto/rebase-from-internal-branch.txt
@@ -27,7 +27,7 @@ the kind of task StGIT is designed to do.
I just have done a simpler one, this time using only the core
GIT tools.
-I had a handful commits that were ahead of master in pu, and I
+I had a handful of commits that were ahead of master in pu, and I
wanted to add some documentation bypassing my usual habit of
placing new things in pu first. At the beginning, the commit
ancestry graph looked like this:
diff --git a/Documentation/howto/revert-a-faulty-merge.txt b/Documentation/howto/revert-a-faulty-merge.txt
new file mode 100644
index 0000000000..39b1da440a
--- /dev/null
+++ b/Documentation/howto/revert-a-faulty-merge.txt
@@ -0,0 +1,179 @@
+Date: Fri, 19 Dec 2008 00:45:19 -0800
+From: Linus Torvalds <torvalds@linux-foundation.org>, Junio C Hamano <gitster@pobox.com>
+Subject: Re: Odd merge behaviour involving reverts
+Abstract: Sometimes a branch that was already merged to the mainline
+ is later found to be faulty. Linus and Junio give guidance on
+ recovering from such a premature merge and continuing development
+ after the offending branch is fixed.
+Message-ID: <7vocz8a6zk.fsf@gitster.siamese.dyndns.org>
+References: <alpine.LFD.2.00.0812181949450.14014@localhost.localdomain>
+
+Alan <alan@clueserver.org> said:
+
+ I have a master branch. We have a branch off of that that some
+ developers are doing work on. They claim it is ready. We merge it
+ into the master branch. It breaks something so we revert the merge.
+ They make changes to the code. they get it to a point where they say
+ it is ok and we merge again.
+
+ When examined, we find that code changes made before the revert are
+ not in the master branch, but code changes after are in the master
+ branch.
+
+and asked for help recovering from this situation.
+
+The history immediately after the "revert of the merge" would look like
+this:
+
+ ---o---o---o---M---x---x---W
+ /
+ ---A---B
+
+where A and B are on the side development that was not so good, M is the
+merge that brings these premature changes into the mainline, x are changes
+unrelated to what the side branch did and already made on the mainline,
+and W is the "revert of the merge M" (doesn't W look M upside down?).
+IOW, "diff W^..W" is similar to "diff -R M^..M".
+
+Such a "revert" of a merge can be made with:
+
+ $ git revert -m 1 M
+
+After the develpers of the side branch fixes their mistakes, the history
+may look like this:
+
+ ---o---o---o---M---x---x---W---x
+ /
+ ---A---B-------------------C---D
+
+where C and D are to fix what was broken in A and B, and you may already
+have some other changes on the mainline after W.
+
+If you merge the updated side branch (with D at its tip), none of the
+changes made in A nor B will be in the result, because they were reverted
+by W. That is what Alan saw.
+
+Linus explains the situation:
+
+ Reverting a regular commit just effectively undoes what that commit
+ did, and is fairly straightforward. But reverting a merge commit also
+ undoes the _data_ that the commit changed, but it does absolutely
+ nothing to the effects on _history_ that the merge had.
+
+ So the merge will still exist, and it will still be seen as joining
+ the two branches together, and future merges will see that merge as
+ the last shared state - and the revert that reverted the merge brought
+ in will not affect that at all.
+
+ So a "revert" undoes the data changes, but it's very much _not_ an
+ "undo" in the sense that it doesn't undo the effects of a commit on
+ the repository history.
+
+ So if you think of "revert" as "undo", then you're going to always
+ miss this part of reverts. Yes, it undoes the data, but no, it doesn't
+ undo history.
+
+In such a situation, you would want to first revert the previous revert,
+which would make the history look like this:
+
+ ---o---o---o---M---x---x---W---x---Y
+ /
+ ---A---B-------------------C---D
+
+where Y is the revert of W. Such a "revert of the revert" can be done
+with:
+
+ $ git revert W
+
+This history would (ignoring possible conflicts between what W and W..Y
+changed) be equivalent to not having W nor Y at all in the history:
+
+ ---o---o---o---M---x---x-------x----
+ /
+ ---A---B-------------------C---D
+
+and merging the side branch again will not have conflict arising from an
+earlier revert and revert of the revert.
+
+ ---o---o---o---M---x---x-------x-------*
+ / /
+ ---A---B-------------------C---D
+
+Of course the changes made in C and D still can conflict with what was
+done by any of the x, but that is just a normal merge conflict.
+
+On the other hand, if the developers of the side branch discarded their
+faulty A and B, and redone the changes on top of the updated mainline
+after the revert, the history would have looked like this:
+
+ ---o---o---o---M---x---x---W---x---x
+ / \
+ ---A---B A'--B'--C'
+
+If you reverted the revert in such a case as in the previous example:
+
+ ---o---o---o---M---x---x---W---x---x---Y---*
+ / \ /
+ ---A---B A'--B'--C'
+
+where Y is the revert of W, A' and B'are rerolled A and B, and there may
+also be a further fix-up C' on the side branch. "diff Y^..Y" is similar
+to "diff -R W^..W" (which in turn means it is similar to "diff M^..M"),
+and "diff A'^..C'" by definition would be similar but different from that,
+because it is a rerolled series of the earlier change. There will be a
+lot of overlapping changes that result in conflicts. So do not do "revert
+of revert" blindly without thinking..
+
+ ---o---o---o---M---x---x---W---x---x
+ / \
+ ---A---B A'--B'--C'
+
+In the history with rebased side branch, W (and M) are behind the merge
+base of the updated branch and the tip of the mainline, and they should
+merge without the past faulty merge and its revert getting in the way.
+
+To recap, these are two very different scenarios, and they want two very
+different resolution strategies:
+
+ - If the faulty side branch was fixed by adding corrections on top, then
+ doing a revert of the previous revert would be the right thing to do.
+
+ - If the faulty side branch whose effects were discarded by an earlier
+ revert of a merge was rebuilt from scratch (i.e. rebasing and fixing,
+ as you seem to have interpreted), then re-merging the result without
+ doing anything else fancy would be the right thing to do.
+
+However, there are things to keep in mind when reverting a merge (and
+reverting such a revert).
+
+For example, think about what reverting a merge (and then reverting the
+revert) does to bisectability. Ignore the fact that the revert of a revert
+is undoing it - just think of it as a "single commit that does a lot".
+Because that is what it does.
+
+When you have a problem you are chasing down, and you hit a "revert this
+merge", what you're hitting is essentially a single commit that contains
+all the changes (but obviously in reverse) of all the commits that got
+merged. So it's debugging hell, because now you don't have lots of small
+changes that you can try to pinpoint which _part_ of it changes.
+
+But does it all work? Sure it does. You can revert a merge, and from a
+purely technical angle, git did it very naturally and had no real
+troubles. It just considered it a change from "state before merge" to
+"state after merge", and that was it. Nothing complicated, nothing odd,
+nothing really dangerous. Git will do it without even thinking about it.
+
+So from a technical angle, there's nothing wrong with reverting a merge,
+but from a workflow angle it's something that you generally should try to
+avoid.
+
+If at all possible, for example, if you find a problem that got merged
+into the main tree, rather than revert the merge, try _really_ hard to
+bisect the problem down into the branch you merged, and just fix it, or
+try to revert the individual commit that caused it.
+
+Yes, it's more complex, and no, it's not always going to work (sometimes
+the answer is: "oops, I really shouldn't have merged it, because it wasn't
+ready yet, and I really need to undo _all_ of the merge"). So then you
+really should revert the merge, but when you want to re-do the merge, you
+now need to do it by reverting the revert.
diff --git a/Documentation/i18n.txt b/Documentation/i18n.txt
index d2970f8357..708da6ca31 100644
--- a/Documentation/i18n.txt
+++ b/Documentation/i18n.txt
@@ -7,11 +7,11 @@ At the core level, git is character encoding agnostic.
to be what lstat(2) and creat(2) accepts. There is no such
thing as pathname encoding translation.
- - The contents of the blob objects are uninterpreted sequence
+ - The contents of the blob objects are uninterpreted sequences
of bytes. There is no encoding translation at the core
level.
- - The commit log messages are uninterpreted sequence of non-NUL
+ - The commit log messages are uninterpreted sequences of non-NUL
bytes.
Although we encourage that the commit log messages are encoded
@@ -37,9 +37,9 @@ of `i18n.commitencoding` in its `encoding` header. This is to
help other people who look at them later. Lack of this header
implies that the commit log message is encoded in UTF-8.
-. 'git-log', 'git-show' and friends looks at the `encoding`
- header of a commit object, and tries to re-code the log
- message into UTF-8 unless otherwise specified. You can
+. 'git-log', 'git-show', 'git-blame' and friends look at the
+ `encoding` header of a commit object, and try to re-code the
+ log message into UTF-8 unless otherwise specified. You can
specify the desired output encoding with
`i18n.logoutputencoding` in `.git/config` file, like this:
+
diff --git a/Documentation/merge-config.txt b/Documentation/merge-config.txt
index c735788b0f..1ff08ff2cc 100644
--- a/Documentation/merge-config.txt
+++ b/Documentation/merge-config.txt
@@ -1,6 +1,10 @@
-merge.stat::
- Whether to print the diffstat between ORIG_HEAD and the merge result
- at the end of the merge. True by default.
+merge.conflictstyle::
+ Specify the style in which conflicted hunks are written out to
+ working tree files upon merge. The default is "merge", which
+ shows a `<<<<<<<` conflict marker, changes made by one side,
+ a `=======` marker, changes made by the other side, and then
+ a `>>>>>>>` marker. An alternate style, "diff3", adds a `|||||||`
+ marker and the original text before the `=======` marker.
merge.log::
Whether to include summaries of merged commits in newly created
@@ -11,6 +15,10 @@ merge.renameLimit::
during a merge; if not specified, defaults to the value of
diff.renameLimit.
+merge.stat::
+ Whether to print the diffstat between ORIG_HEAD and the merge result
+ at the end of the merge. True by default.
+
merge.tool::
Controls which merge resolution program is used by
linkgit:git-mergetool[1]. Valid built-in values are: "kdiff3",
@@ -24,10 +32,10 @@ merge.verbosity::
message if conflicts were detected. Level 1 outputs only
conflicts, 2 outputs conflicts and file changes. Level 5 and
above outputs debugging information. The default is level 2.
- Can be overridden by 'GIT_MERGE_VERBOSITY' environment variable.
+ Can be overridden by the 'GIT_MERGE_VERBOSITY' environment variable.
merge.<driver>.name::
- Defines a human readable name for a custom low-level
+ Defines a human-readable name for a custom low-level
merge driver. See linkgit:gitattributes[5] for details.
merge.<driver>.driver::
diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt
index 007909a82f..637b53f898 100644
--- a/Documentation/merge-options.txt
+++ b/Documentation/merge-options.txt
@@ -1,10 +1,18 @@
+-q::
+--quiet::
+ Operate quietly.
+
+-v::
+--verbose::
+ Be verbose.
+
--stat::
Show a diffstat at the end of the merge. The diffstat is also
controlled by the configuration option merge.stat.
-n::
--no-stat::
- Do not show diffstat at the end of the merge.
+ Do not show a diffstat at the end of the merge.
--summary::
--no-summary::
diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index f18d33e00b..0a8a948e6f 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -30,7 +30,7 @@ This is designed to be as compact as possible.
commit <sha1>
Author: <author>
- Date: <author date>
+ Date: <author date>
<title line>
@@ -49,9 +49,9 @@ This is designed to be as compact as possible.
* 'fuller'
commit <sha1>
- Author: <author>
+ Author: <author>
AuthorDate: <author date>
- Commit: <committer>
+ Commit: <committer>
CommitDate: <committer date>
<title line>
diff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt
index 6d66c74cc1..5f21efe407 100644
--- a/Documentation/pretty-options.txt
+++ b/Documentation/pretty-options.txt
@@ -10,7 +10,7 @@ configuration (see linkgit:git-config[1]).
--abbrev-commit::
Instead of showing the full 40-byte hexadecimal commit object
- name, show only handful hexdigits prefix. Non default number of
+ name, show only a partial prefix. Non default number of
digits can be specified with "--abbrev=<n>" (which also modifies
diff output, if it is displayed).
+
diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt
index 0ce916a188..b9f6e4d1b7 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -174,6 +174,10 @@ endif::git-rev-list[]
Limit the commits output to ones with log message that
matches the specified pattern (regular expression).
+--all-match::
+ Limit the commits output to ones that match all given --grep,
+ --author and --committer instead of ones that match at least one.
+
-i::
--regexp-ignore-case::
@@ -218,6 +222,21 @@ endif::git-rev-list[]
Pretend as if all the refs in `$GIT_DIR/refs/` are listed on the
command line as '<commit>'.
+--branches::
+
+ Pretend as if all the refs in `$GIT_DIR/refs/heads` are listed
+ on the command line as '<commit>'.
+
+--tags::
+
+ Pretend as if all the refs in `$GIT_DIR/refs/tags` are listed
+ on the command line as '<commit>'.
+
+--remotes::
+
+ Pretend as if all the refs in `$GIT_DIR/refs/remotes` are listed
+ on the command line as '<commit>'.
+
ifdef::git-rev-list[]
--stdin::
@@ -281,8 +300,52 @@ See also linkgit:git-reflog[1].
History Simplification
~~~~~~~~~~~~~~~~~~~~~~
-When optional paths are given, 'git-rev-list' simplifies commits with
-various strategies, according to the options you have selected.
+Sometimes you are only interested in parts of the history, for example the
+commits modifying a particular <path>. But there are two parts of
+'History Simplification', one part is selecting the commits and the other
+is how to do it, as there are various strategies to simplify the history.
+
+The following options select the commits to be shown:
+
+<paths>::
+
+ Commits modifying the given <paths> are selected.
+
+--simplify-by-decoration::
+
+ Commits that are referred by some branch or tag are selected.
+
+Note that extra commits can be shown to give a meaningful history.
+
+The following options affect the way the simplification is performed:
+
+Default mode::
+
+ Simplifies the history to the simplest history explaining the
+ final state of the tree. Simplest because it prunes some side
+ branches if the end result is the same (i.e. merging branches
+ with the same content)
+
+--full-history::
+
+ As the default mode but does not prune some history.
+
+--dense::
+
+ Only the selected commits are shown, plus some to have a
+ meaningful history.
+
+--sparse::
+
+ All commits in the simplified history are shown.
+
+--simplify-merges::
+
+ Additional option to '--full-history' to remove some needless
+ merges from the resulting history, as there are no selected
+ commits contributing to this merge.
+
+A more detailed explanation follows.
Suppose you specified `foo` as the <paths>. We shall call commits
that modify `foo` !TREESAME, and the rest TREESAME. (In a diff
@@ -452,6 +515,14 @@ Note the major differences in `N` and `P` over '\--full-history':
removed completely, because it had one parent and is TREESAME.
--
+The '\--simplify-by-decoration' option allows you to view only the
+big picture of the topology of the history, by omitting commits
+that are not referenced by tags. Commits are marked as !TREESAME
+(in other words, kept after history simplification rules described
+above) if (1) they are referenced by tags, or (2) they change the
+contents of the paths given on the command line. All other
+commits are marked as TREESAME (subject to be simplified away).
+
ifdef::git-rev-list[]
Bisection Helpers
~~~~~~~~~~~~~~~~~
@@ -462,14 +533,14 @@ Limit output to the one commit object which is roughly halfway between
the included and excluded commits. Thus, if
-----------------------------------------------------------------------
- $ git-rev-list --bisect foo ^bar ^baz
+ $ git rev-list --bisect foo ^bar ^baz
-----------------------------------------------------------------------
outputs 'midpoint', the output of the two commands
-----------------------------------------------------------------------
- $ git-rev-list foo ^midpoint
- $ git-rev-list midpoint ^bar ^baz
+ $ git rev-list foo ^midpoint
+ $ git rev-list midpoint ^bar ^baz
-----------------------------------------------------------------------
would be of roughly the same length. Finding the change which
diff --git a/Documentation/technical/api-strbuf.txt b/Documentation/technical/api-strbuf.txt
index a9668e5f2d..9a4e3ea92c 100644
--- a/Documentation/technical/api-strbuf.txt
+++ b/Documentation/technical/api-strbuf.txt
@@ -133,8 +133,10 @@ Functions
* Adding data to the buffer
-NOTE: All of these functions in this section will grow the buffer as
- necessary.
+NOTE: All of the functions in this section will grow the buffer as necessary.
+If they fail for some reason other than memory shortage and the buffer hadn't
+been allocated before (i.e. the `struct strbuf` was set to `STRBUF_INIT`),
+then they will free() it.
`strbuf_addch`::
@@ -205,6 +207,13 @@ In order to facilitate caching and to make it possible to give
parameters to the callback, `strbuf_expand()` passes a context pointer,
which can be used by the programmer of the callback as she sees fit.
+`strbuf_expand_dict_cb`::
+
+ Used as callback for `strbuf_expand()`, expects an array of
+ struct strbuf_expand_dict_entry as context, i.e. pairs of
+ placeholder and replacement string. The array needs to be
+ terminated by an entry with placeholder set to NULL.
+
`strbuf_addf`::
Add a formatted string to the buffer.
@@ -228,6 +237,11 @@ same behaviour as well.
Read the contents of a file, specified by its path. The third argument
can be used to give a hint about the file size, to avoid reallocs.
+`strbuf_readlink`::
+
+ Read the target of a symbolic link, specified by its path. The third
+ argument can be used to give a hint about the size, to avoid reallocs.
+
`strbuf_getline`::
Read a line from a FILE* pointer. The second argument specifies the line
diff --git a/Documentation/technical/racy-git.txt b/Documentation/technical/racy-git.txt
index 6bdf034b3a..48bb97f0b1 100644
--- a/Documentation/technical/racy-git.txt
+++ b/Documentation/technical/racy-git.txt
@@ -135,7 +135,7 @@ them, and give the same timestamp to the index file:
This will make all index entries racily clean. The linux-2.6
project, for example, there are over 20,000 files in the working
-tree. On my Athron 64X2 3800+, after the above:
+tree. On my Athlon 64 X2 3800+, after the above:
$ /usr/bin/time git diff-files
1.68user 0.54system 0:02.22elapsed 100%CPU (0avgtext+0avgdata 0maxresident)k
diff --git a/Documentation/urls-remotes.txt b/Documentation/urls-remotes.txt
index 504ae8a53b..41ec7774f4 100644
--- a/Documentation/urls-remotes.txt
+++ b/Documentation/urls-remotes.txt
@@ -68,13 +68,22 @@ This file should have the following format:
------------
`<url>` is required; `#<head>` is optional.
-When you do not provide a refspec on the command line,
-git will use the following refspec, where `<head>` defaults to `master`,
-and `<repository>` is the name of this file
-you provided in the command line.
+
+Depending on the operation, git will use one of the following
+refspecs, if you don't provide one on the command line.
+`<branch>` is the name of this file in `$GIT_DIR/branches` and
+`<head>` defaults to `master`.
+
+git fetch uses:
+
+------------
+ refs/heads/<head>:refs/heads/<branch>
+------------
+
+git push uses:
------------
- refs/heads/<head>:<repository>
+ HEAD:refs/heads/<head>
------------
diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt
index 08d1310bf5..19f571ae3b 100644
--- a/Documentation/user-manual.txt
+++ b/Documentation/user-manual.txt
@@ -13,17 +13,27 @@ to build and test a particular version of a software project, search for
regressions, and so on.
People needing to do actual development will also want to read
-<<Developing-with-git>> and <<sharing-development>>.
+<<Developing-With-git>> and <<sharing-development>>.
Further chapters cover more specialized topics.
Comprehensive reference documentation is available through the man
-pages. For a command such as "git clone <repo>", just use
+pages, or linkgit:git-help[1] command. For example, for the command
+"git clone <repo>", you can either use:
------------------------------------------------
$ man git-clone
------------------------------------------------
+or:
+
+------------------------------------------------
+$ git help clone
+------------------------------------------------
+
+With the latter, you can use the manual viewer of your choice; see
+linkgit:git-help[1] for more information.
+
See also <<git-quick-start>> for a brief overview of git commands,
without any explanation.
@@ -49,7 +59,7 @@ project in mind, here are some interesting examples:
------------------------------------------------
# git itself (approx. 10MB download):
$ git clone git://git.kernel.org/pub/scm/git/git.git
- # the linux kernel (approx. 150MB download):
+ # the Linux kernel (approx. 150MB download):
$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
------------------------------------------------
@@ -389,7 +399,7 @@ the order it uses to decide which to choose when there are multiple
references with the same shorthand name, see the "SPECIFYING
REVISIONS" section of linkgit:git-rev-parse[1].
-[[Updating-a-repository-with-git-fetch]]
+[[Updating-a-repository-With-git-fetch]]
Updating a repository with git-fetch
------------------------------------
@@ -536,7 +546,7 @@ $ git bisect skip
-------------------------------------------------
In this case, though, git may not eventually be able to tell the first
-bad one between some first skipped commits and a latter bad commit.
+bad one between some first skipped commits and a later bad commit.
There are also ways to automate the bisecting process if you have a
test script that can tell a good from a bad commit. See
@@ -945,7 +955,7 @@ echo "git diff --stat --summary -M v$last v$new > ../diffstat-$new"
and then he just cut-and-pastes the output commands after verifying that
they look OK.
-[[Finding-comments-with-given-content]]
+[[Finding-comments-With-given-Content]]
Finding commits referencing a file with given content
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -962,7 +972,7 @@ Figuring out why this works is left as an exercise to the (advanced)
student. The linkgit:git-log[1], linkgit:git-diff-tree[1], and
linkgit:git-hash-object[1] man pages may prove helpful.
-[[Developing-with-git]]
+[[Developing-With-git]]
Developing with git
===================
@@ -999,7 +1009,7 @@ $ git init
If you have some initial content (say, a tarball):
-------------------------------------------------
-$ tar -xzvf project.tar.gz
+$ tar xzvf project.tar.gz
$ cd project
$ git init
$ git add . # include everything below ./ in the first commit:
@@ -1330,7 +1340,7 @@ These will display all commits which exist only on HEAD or on
MERGE_HEAD, and which touch an unmerged file.
You may also use linkgit:git-mergetool[1], which lets you merge the
-unmerged files using external tools such as emacs or kdiff3.
+unmerged files using external tools such as Emacs or kdiff3.
Each time you resolve the conflicts in a file and update the index:
@@ -1665,7 +1675,7 @@ dangling objects can arise in other situations.
Sharing development with others
===============================
-[[getting-updates-with-git-pull]]
+[[getting-updates-With-git-pull]]
Getting updates with git-pull
-----------------------------
@@ -1673,7 +1683,7 @@ After you clone a repository and make a few changes of your own, you
may wish to check the original repository for updates and merge them
into your own work.
-We have already seen <<Updating-a-repository-with-git-fetch,how to
+We have already seen <<Updating-a-repository-With-git-fetch,how to
keep remote tracking branches up to date>> with linkgit:git-fetch[1],
and how to merge two branches. So you can merge in changes from the
original repository's master branch with:
@@ -1784,7 +1794,7 @@ Public git repositories
Another way to submit changes to a project is to tell the maintainer
of that project to pull the changes from your repository using
-linkgit:git-pull[1]. In the section "<<getting-updates-with-git-pull,
+linkgit:git-pull[1]. In the section "<<getting-updates-With-git-pull,
Getting updates with git-pull>>" we described this as a way to get
updates from the "main" repository, but it works just as well in the
other direction.
@@ -1994,7 +2004,7 @@ $ git push ssh://yourserver.com/~you/proj.git +master
Normally whenever a branch head in a public repository is modified, it
is modified to point to a descendant of the commit that it pointed to
before. By forcing a push in this situation, you break that convention.
-(See <<problems-with-rewriting-history>>.)
+(See <<problems-With-rewriting-history>>.)
Nevertheless, this is a common practice for people that need a simple
way to publish a work-in-progress patch series, and it is an acceptable
@@ -2563,7 +2573,7 @@ There are numerous other tools, such as StGIT, which exist for the
purpose of maintaining a patch series. These are outside of the scope of
this manual.
-[[problems-with-rewriting-history]]
+[[problems-With-rewriting-history]]
Problems with rewriting history
-------------------------------
@@ -4356,7 +4366,9 @@ $ git remote show example # get details
* remote example
URL: git://example.com/project.git
Tracked remote branches
- master next ...
+ master
+ next
+ ...
$ git fetch example # update branches from example
$ git branch -r # list all remote branches
-----------------------------------------------
@@ -4560,4 +4572,3 @@ Alternates, clone -reference, etc.
More on recovery from repository corruption. See:
http://marc.theaimsgroup.com/?l=git&m=117263864820799&w=2
http://marc.theaimsgroup.com/?l=git&m=117147855503798&w=2
- http://marc.theaimsgroup.com/?l=git&m=117147855503798&w=2
diff --git a/INSTALL b/INSTALL
index a4fd8624bc..ae7f7508f8 100644
--- a/INSTALL
+++ b/INSTALL
@@ -101,6 +101,9 @@ Issues of note:
Building and installing the info file additionally requires
makeinfo and docbook2X. Version 0.8.3 is known to work.
+ Building and installing the pdf file additionally requires
+ dblatex. Version 0.2.7 with asciidoc >= 8.2.7 is known to work.
+
The documentation is written for AsciiDoc 7, but "make
ASCIIDOC8=YesPlease doc" will let you format with AsciiDoc 8.
@@ -126,8 +129,9 @@ Issues of note:
http://www.kernel.org/pub/software/scm/git/docs/
- There are also "make quick-install-doc" and "make quick-install-html"
- which install preformatted man pages and html documentation.
+ There are also "make quick-install-doc", "make quick-install-man"
+ and "make quick-install-html" which install preformatted man pages
+ and html documentation.
This does not require asciidoc/xmlto, but it only works from within
a cloned checkout of git.git with these two extra branches, and will
not work for the maintainer for obvious chicken-and-egg reasons.
diff --git a/Makefile b/Makefile
index 308dc70b5d..2b873fa99f 100644
--- a/Makefile
+++ b/Makefile
@@ -90,6 +90,8 @@ all::
#
# Define NO_MMAP if you want to avoid mmap.
#
+# 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.
# cygwin.dll before v1.5.22).
#
@@ -164,6 +166,7 @@ uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not')
uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not')
uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not')
uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not')
+uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not')
# CFLAGS and LDFLAGS are for the users to override from the command line.
@@ -229,6 +232,7 @@ INSTALL = install
RPMBUILD = rpmbuild
TCL_PATH = tclsh
TCLTK_PATH = wish
+PTHREAD_LIBS = -lpthread
export TCL_PATH TCLTK_PATH
@@ -316,6 +320,7 @@ BUILT_INS += git-merge-subtree$X
BUILT_INS += git-peek-remote$X
BUILT_INS += git-repo-config$X
BUILT_INS += git-show$X
+BUILT_INS += git-stage$X
BUILT_INS += git-status$X
BUILT_INS += git-whatchanged$X
@@ -389,6 +394,7 @@ LIB_H += transport.h
LIB_H += tree.h
LIB_H += tree-walk.h
LIB_H += unpack-trees.h
+LIB_H += userdiff.h
LIB_H += utf8.h
LIB_H += wt-status.h
@@ -435,7 +441,6 @@ LIB_OBJS += grep.o
LIB_OBJS += hash.o
LIB_OBJS += help.o
LIB_OBJS += ident.o
-LIB_OBJS += interpolate.o
LIB_OBJS += levenshtein.o
LIB_OBJS += list-objects.o
LIB_OBJS += ll-merge.o
@@ -485,6 +490,7 @@ LIB_OBJS += tree-diff.o
LIB_OBJS += tree.o
LIB_OBJS += tree-walk.o
LIB_OBJS += unpack-trees.o
+LIB_OBJS += userdiff.o
LIB_OBJS += usage.o
LIB_OBJS += utf8.o
LIB_OBJS += walker.o
@@ -493,6 +499,7 @@ LIB_OBJS += write_or_die.o
LIB_OBJS += ws.o
LIB_OBJS += wt-status.o
LIB_OBJS += xdiff-interface.o
+LIB_OBJS += preload-index.o
BUILTIN_OBJS += builtin-add.o
BUILTIN_OBJS += builtin-annotate.o
@@ -638,8 +645,7 @@ ifeq ($(uname_S),Darwin)
endif
NO_STRLCPY = YesPlease
NO_MEMMEM = YesPlease
- COMPAT_CFLAGS += -Icompat/regex
- COMPAT_OBJS += compat/regex/regex.o
+ THREADED_DELTA_SEARCH = YesPlease
endif
ifeq ($(uname_S),SunOS)
NEEDS_SOCKET = YesPlease
@@ -690,8 +696,11 @@ ifeq ($(uname_S),FreeBSD)
BASIC_LDFLAGS += -L/usr/local/lib
DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease
THREADED_DELTA_SEARCH = YesPlease
- COMPAT_CFLAGS += -Icompat/regex
- COMPAT_OBJS += compat/regex/regex.o
+ ifeq ($(shell expr "$(uname_R)" : '4\.'),2)
+ PTHREAD_LIBS = -pthread
+ NO_UINTMAX_T = YesPlease
+ NO_STRTOUMAX = YesPlease
+ endif
endif
ifeq ($(uname_S),OpenBSD)
NO_STRCASESTR = YesPlease
@@ -718,8 +727,11 @@ ifeq ($(uname_S),AIX)
INTERNAL_QSORT = UnfortunatelyYes
NEEDS_LIBICONV=YesPlease
BASIC_CFLAGS += -D_LARGE_FILES
- COMPAT_CFLAGS += -Icompat/regex
- COMPAT_OBJS += compat/regex/regex.o
+ ifneq ($(shell expr "$(uname_V)" : '[1234]'),1)
+ THREADED_DELTA_SEARCH = YesPlease
+ else
+ NO_PTHREADS = YesPlease
+ endif
endif
ifeq ($(uname_S),GNU)
# GNU/Hurd
@@ -764,6 +776,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
NO_STRCASESTR = YesPlease
NO_STRLCPY = YesPlease
NO_MEMMEM = YesPlease
+ NO_PTHREADS = YesPlease
NEEDS_LIBICONV = YesPlease
OLD_ICONV = YesPlease
NO_C99_FORMAT = YesPlease
@@ -953,6 +966,9 @@ endif
ifdef NO_IPV6
BASIC_CFLAGS += -DNO_IPV6
endif
+ifdef NO_UINTMAX_T
+ BASIC_CFLAGS += -Duintmax_t=uint32_t
+endif
ifdef NO_SOCKADDR_STORAGE
ifdef NO_IPV6
BASIC_CFLAGS += -Dsockaddr_storage=sockaddr_in
@@ -1012,9 +1028,15 @@ ifdef INTERNAL_QSORT
COMPAT_OBJS += compat/qsort.o
endif
+ifdef NO_PTHREADS
+ THREADED_DELTA_SEARCH =
+ BASIC_CFLAGS += -DNO_PTHREADS
+else
+ EXTLIBS += $(PTHREAD_LIBS)
+endif
+
ifdef THREADED_DELTA_SEARCH
BASIC_CFLAGS += -DTHREADED_DELTA_SEARCH
- EXTLIBS += -lpthread
LIB_OBJS += thread-utils.o
endif
ifdef DIR_HAS_BSD_GROUP_SEMANTICS
@@ -1285,6 +1307,9 @@ html:
info:
$(MAKE) -C Documentation info
+pdf:
+ $(MAKE) -C Documentation pdf
+
TAGS:
$(RM) TAGS
$(FIND) . -name '*.[hcS]' -print | xargs etags -a
@@ -1331,7 +1356,14 @@ endif
### Testing rules
-TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-parse-options$X test-path-utils$X
+TEST_PROGRAMS += test-chmtime$X
+TEST_PROGRAMS += test-date$X
+TEST_PROGRAMS += test-delta$X
+TEST_PROGRAMS += test-genrandom$X
+TEST_PROGRAMS += test-match-trees$X
+TEST_PROGRAMS += test-parse-options$X
+TEST_PROGRAMS += test-path-utils$X
+TEST_PROGRAMS += test-sha1$X
all:: $(TEST_PROGRAMS)
@@ -1359,7 +1391,16 @@ check-sha1:: test-sha1$X
./test-sha1.sh
check: common-cmds.h
- for i in *.c; do sparse $(ALL_CFLAGS) $(SPARSE_FLAGS) $$i || exit; done
+ if sparse; \
+ then \
+ for i in *.c; \
+ do \
+ sparse $(ALL_CFLAGS) $(SPARSE_FLAGS) $$i || exit; \
+ done; \
+ else \
+ echo 2>&1 "Did you mean 'make test'?"; \
+ exit 1; \
+ fi
remove-dashes:
./fixup-builtins $(BUILT_INS) $(PROGRAMS) $(SCRIPTS)
@@ -1409,15 +1450,24 @@ endif
install-doc:
$(MAKE) -C Documentation install
+install-man:
+ $(MAKE) -C Documentation install-man
+
install-html:
$(MAKE) -C Documentation install-html
install-info:
$(MAKE) -C Documentation install-info
+install-pdf:
+ $(MAKE) -C Documentation install-pdf
+
quick-install-doc:
$(MAKE) -C Documentation quick-install
+quick-install-man:
+ $(MAKE) -C Documentation quick-install-man
+
quick-install-html:
$(MAKE) -C Documentation quick-install-html
diff --git a/README b/README
index 548142c327..5fa41b7a18 100644
--- a/README
+++ b/README
@@ -24,7 +24,7 @@ It was originally written by Linus Torvalds with help of a group of
hackers around the net. It is currently maintained by Junio C Hamano.
Please read the file INSTALL for installation instructions.
-See Documentation/tutorial.txt to get started, then see
+See Documentation/gittutorial.txt to get started, then see
Documentation/everyday.txt for a useful minimum set of commands,
and "man git-commandname" for documentation of each command.
CVS users may also want to read Documentation/cvs-migration.txt.
diff --git a/RelNotes b/RelNotes
index 3d420845b1..ecced08731 120000
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes-1.6.1.txt \ No newline at end of file
+Documentation/RelNotes-1.6.2.txt \ No newline at end of file
diff --git a/abspath.c b/abspath.c
index 8194ce1256..649f34f833 100644
--- a/abspath.c
+++ b/abspath.c
@@ -64,6 +64,8 @@ const char *make_absolute_path(const char *path)
len = readlink(buf, next_buf, PATH_MAX);
if (len < 0)
die ("Invalid symlink: %s", buf);
+ if (PATH_MAX <= len)
+ die("symbolic link too long: %s", buf);
next_buf[len] = '\0';
buf = next_buf;
buf_index = 1 - buf_index;
diff --git a/archive.c b/archive.c
index 849eed553e..9ac455d889 100644
--- a/archive.c
+++ b/archive.c
@@ -336,5 +336,7 @@ int write_archive(int argc, const char **argv, const char *prefix,
parse_treeish_arg(argv, &args, prefix);
parse_pathspec_arg(argv + 1, &args);
+ git_config(git_default_config, NULL);
+
return ar->write_archive(&args);
}
diff --git a/branch.c b/branch.c
index b1e59f2196..b1ac837f3d 100644
--- a/branch.c
+++ b/branch.c
@@ -129,7 +129,9 @@ void create_branch(const char *head,
die("Cannot setup tracking information; starting point is not a branch.");
break;
case 1:
- /* Unique completion -- good */
+ /* Unique completion -- good, only if it is a real ref */
+ if (track == BRANCH_TRACK_EXPLICIT && !strcmp(real_ref, "HEAD"))
+ die("Cannot setup tracking information; starting point is not a branch.");
break;
default:
die("Ambiguous object name: '%s'.", start_name);
@@ -168,5 +170,6 @@ void remove_branch_state(void)
unlink(git_path("MERGE_HEAD"));
unlink(git_path("MERGE_RR"));
unlink(git_path("MERGE_MSG"));
+ unlink(git_path("MERGE_MODE"));
unlink(git_path("SQUASH_MSG"));
}
diff --git a/builtin-add.c b/builtin-add.c
index ea4e77169a..ac98c8354d 100644
--- a/builtin-add.c
+++ b/builtin-add.c
@@ -23,7 +23,7 @@ static void fill_pathspec_matches(const char **pathspec, char *seen, int specs)
int num_unmatched = 0, i;
/*
- * Since we are walking the index as if we are warlking the directory,
+ * Since we are walking the index as if we were walking the directory,
* we have to mark the matched pathspec as seen; otherwise we will
* mistakenly think that the user gave a pathspec that did not match
* anything.
@@ -68,6 +68,33 @@ static void prune_directory(struct dir_struct *dir, const char **pathspec, int p
free(seen);
}
+static void treat_gitlinks(const char **pathspec)
+{
+ int i;
+
+ if (!pathspec || !*pathspec)
+ return;
+
+ for (i = 0; i < active_nr; i++) {
+ struct cache_entry *ce = active_cache[i];
+ if (S_ISGITLINK(ce->ce_mode)) {
+ int len = ce_namelen(ce), j;
+ for (j = 0; pathspec[j]; j++) {
+ int len2 = strlen(pathspec[j]);
+ if (len2 <= len || pathspec[j][len] != '/' ||
+ memcmp(ce->name, pathspec[j], len))
+ continue;
+ if (len2 == len + 1)
+ /* strip trailing slash */
+ pathspec[j] = xstrndup(ce->name, len);
+ else
+ die ("Path '%s' is in submodule '%.*s'",
+ pathspec[j], len, ce->name);
+ }
+ }
+ }
+}
+
static void fill_directory(struct dir_struct *dir, const char **pathspec,
int ignored_too)
{
@@ -261,6 +288,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
if (read_cache() < 0)
die("index file corrupt");
+ treat_gitlinks(pathspec);
if (add_new_files)
/* This picks up the paths that are not tracked */
diff --git a/builtin-apply.c b/builtin-apply.c
index cfd8fceb90..a8f75ed3ed 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -630,7 +630,7 @@ static int gitdiff_index(const char *line, struct patch *patch)
memcpy(patch->new_sha1_prefix, line, len);
patch->new_sha1_prefix[len] = 0;
if (*ptr == ' ')
- patch->new_mode = patch->old_mode = strtoul(ptr+1, NULL, 8);
+ patch->old_mode = strtoul(ptr+1, NULL, 8);
return 0;
}
@@ -1559,10 +1559,8 @@ static int read_old_data(struct stat *st, const char *path, struct strbuf *buf)
{
switch (st->st_mode & S_IFMT) {
case S_IFLNK:
- strbuf_grow(buf, st->st_size);
- if (readlink(path, buf->buf, st->st_size) != st->st_size)
- return -1;
- strbuf_setlen(buf, st->st_size);
+ if (strbuf_readlink(buf, path, st->st_size) < 0)
+ return error("unable to read symlink %s", path);
return 0;
case S_IFREG:
if (strbuf_read_file(buf, path, st->st_size) != st->st_size)
@@ -2449,6 +2447,8 @@ static int check_preimage(struct patch *patch, struct cache_entry **ce, struct s
if (st_mode != patch->old_mode)
fprintf(stderr, "warning: %s has type %o, expected %o\n",
old_name, st_mode, patch->old_mode);
+ if (!patch->new_mode)
+ patch->new_mode = st_mode;
return 0;
is_new:
@@ -2841,8 +2841,8 @@ static void create_one_file(char *path, unsigned mode, const char *buf, unsigned
unsigned int nr = getpid();
for (;;) {
- const char *newpath;
- newpath = mkpath("%s~%u", path, nr);
+ char newpath[PATH_MAX];
+ mksnpath(newpath, sizeof(newpath), "%s~%u", path, nr);
if (!try_create_file(newpath, mode, buf, size)) {
if (!rename(newpath, path))
return;
diff --git a/builtin-archive.c b/builtin-archive.c
index 432ce2acc6..5ceec433fd 100644
--- a/builtin-archive.c
+++ b/builtin-archive.c
@@ -111,8 +111,6 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
{
const char *remote = NULL;
- git_config(git_default_config, NULL);
-
remote = extract_remote_arg(&argc, argv);
if (remote)
return run_remote_archiver(remote, argc, argv);
diff --git a/builtin-blame.c b/builtin-blame.c
index 48cc0c175d..aae14ef8bb 100644
--- a/builtin-blame.c
+++ b/builtin-blame.c
@@ -443,131 +443,6 @@ static struct origin *find_rename(struct scoreboard *sb,
}
/*
- * Parsing of patch chunks...
- */
-struct chunk {
- /* line number in postimage; up to but not including this
- * line is the same as preimage
- */
- int same;
-
- /* preimage line number after this chunk */
- int p_next;
-
- /* postimage line number after this chunk */
- int t_next;
-};
-
-struct patch {
- struct chunk *chunks;
- int num;
-};
-
-struct blame_diff_state {
- struct patch *ret;
- unsigned hunk_post_context;
- unsigned hunk_in_pre_context : 1;
-};
-
-static void process_u_diff(void *state_, char *line, unsigned long len)
-{
- struct blame_diff_state *state = state_;
- struct chunk *chunk;
- int off1, off2, len1, len2, num;
-
- num = state->ret->num;
- if (len < 4 || line[0] != '@' || line[1] != '@') {
- if (state->hunk_in_pre_context && line[0] == ' ')
- state->ret->chunks[num - 1].same++;
- else {
- state->hunk_in_pre_context = 0;
- if (line[0] == ' ')
- state->hunk_post_context++;
- else
- state->hunk_post_context = 0;
- }
- return;
- }
-
- if (num && state->hunk_post_context) {
- chunk = &state->ret->chunks[num - 1];
- chunk->p_next -= state->hunk_post_context;
- chunk->t_next -= state->hunk_post_context;
- }
- state->ret->num = ++num;
- state->ret->chunks = xrealloc(state->ret->chunks,
- sizeof(struct chunk) * num);
- chunk = &state->ret->chunks[num - 1];
- if (parse_hunk_header(line, len, &off1, &len1, &off2, &len2)) {
- state->ret->num--;
- return;
- }
-
- /* Line numbers in patch output are one based. */
- off1--;
- off2--;
-
- chunk->same = len2 ? off2 : (off2 + 1);
-
- chunk->p_next = off1 + (len1 ? len1 : 1);
- chunk->t_next = chunk->same + len2;
- state->hunk_in_pre_context = 1;
- state->hunk_post_context = 0;
-}
-
-static struct patch *compare_buffer(mmfile_t *file_p, mmfile_t *file_o,
- int context)
-{
- struct blame_diff_state state;
- xpparam_t xpp;
- xdemitconf_t xecfg;
- xdemitcb_t ecb;
-
- xpp.flags = xdl_opts;
- memset(&xecfg, 0, sizeof(xecfg));
- xecfg.ctxlen = context;
- memset(&state, 0, sizeof(state));
- state.ret = xmalloc(sizeof(struct patch));
- state.ret->chunks = NULL;
- state.ret->num = 0;
-
- xdi_diff_outf(file_p, file_o, process_u_diff, &state, &xpp, &xecfg, &ecb);
-
- if (state.ret->num) {
- struct chunk *chunk;
- chunk = &state.ret->chunks[state.ret->num - 1];
- chunk->p_next -= state.hunk_post_context;
- chunk->t_next -= state.hunk_post_context;
- }
- return state.ret;
-}
-
-/*
- * Run diff between two origins and grab the patch output, so that
- * we can pass blame for lines origin is currently suspected for
- * to its parent.
- */
-static struct patch *get_patch(struct origin *parent, struct origin *origin)
-{
- mmfile_t file_p, file_o;
- struct patch *patch;
-
- fill_origin_blob(parent, &file_p);
- fill_origin_blob(origin, &file_o);
- if (!file_p.ptr || !file_o.ptr)
- return NULL;
- patch = compare_buffer(&file_p, &file_o, 0);
- num_get_patch++;
- return patch;
-}
-
-static void free_patch(struct patch *p)
-{
- free(p->chunks);
- free(p);
-}
-
-/*
* Link in a new blame entry to the scoreboard. Entries that cover the
* same line range have been removed from the scoreboard previously.
*/
@@ -813,6 +688,22 @@ static void blame_chunk(struct scoreboard *sb,
}
}
+struct blame_chunk_cb_data {
+ struct scoreboard *sb;
+ struct origin *target;
+ struct origin *parent;
+ long plno;
+ long tlno;
+};
+
+static void blame_chunk_cb(void *data, long same, long p_next, long t_next)
+{
+ struct blame_chunk_cb_data *d = data;
+ blame_chunk(d->sb, d->tlno, d->plno, same, d->target, d->parent);
+ d->plno = p_next;
+ d->tlno = t_next;
+}
+
/*
* We are looking at the origin 'target' and aiming to pass blame
* for the lines it is suspected to its parent. Run diff to find
@@ -822,26 +713,28 @@ static int pass_blame_to_parent(struct scoreboard *sb,
struct origin *target,
struct origin *parent)
{
- int i, last_in_target, plno, tlno;
- struct patch *patch;
+ int last_in_target;
+ mmfile_t file_p, file_o;
+ struct blame_chunk_cb_data d = { sb, target, parent, 0, 0 };
+ xpparam_t xpp;
+ xdemitconf_t xecfg;
last_in_target = find_last_in_target(sb, target);
if (last_in_target < 0)
return 1; /* nothing remains for this target */
- patch = get_patch(parent, target);
- plno = tlno = 0;
- for (i = 0; i < patch->num; i++) {
- struct chunk *chunk = &patch->chunks[i];
+ fill_origin_blob(parent, &file_p);
+ fill_origin_blob(target, &file_o);
+ num_get_patch++;
- blame_chunk(sb, tlno, plno, chunk->same, target, parent);
- plno = chunk->p_next;
- tlno = chunk->t_next;
- }
+ memset(&xpp, 0, sizeof(xpp));
+ xpp.flags = xdl_opts;
+ memset(&xecfg, 0, sizeof(xecfg));
+ xecfg.ctxlen = 0;
+ xdi_diff_hunks(&file_p, &file_o, blame_chunk_cb, &d, &xpp, &xecfg);
/* The rest (i.e. anything after tlno) are the same as the parent */
- blame_chunk(sb, tlno, plno, last_in_target, target, parent);
+ blame_chunk(sb, d.tlno, d.plno, last_in_target, target, parent);
- free_patch(patch);
return 0;
}
@@ -933,6 +826,23 @@ static void handle_split(struct scoreboard *sb,
}
}
+struct handle_split_cb_data {
+ struct scoreboard *sb;
+ struct blame_entry *ent;
+ struct origin *parent;
+ struct blame_entry *split;
+ long plno;
+ long tlno;
+};
+
+static void handle_split_cb(void *data, long same, long p_next, long t_next)
+{
+ struct handle_split_cb_data *d = data;
+ handle_split(d->sb, d->ent, d->tlno, d->plno, same, d->parent, d->split);
+ d->plno = p_next;
+ d->tlno = t_next;
+}
+
/*
* Find the lines from parent that are the same as ent so that
* we can pass blames to it. file_p has the blob contents for
@@ -947,8 +857,9 @@ static void find_copy_in_blob(struct scoreboard *sb,
const char *cp;
int cnt;
mmfile_t file_o;
- struct patch *patch;
- int i, plno, tlno;
+ struct handle_split_cb_data d = { sb, ent, parent, split, 0, 0 };
+ xpparam_t xpp;
+ xdemitconf_t xecfg;
/*
* Prepare mmfile that contains only the lines in ent.
@@ -963,24 +874,18 @@ static void find_copy_in_blob(struct scoreboard *sb,
}
file_o.size = cp - file_o.ptr;
- patch = compare_buffer(file_p, &file_o, 1);
-
/*
* file_o is a part of final image we are annotating.
* file_p partially may match that image.
*/
+ memset(&xpp, 0, sizeof(xpp));
+ xpp.flags = xdl_opts;
+ memset(&xecfg, 0, sizeof(xecfg));
+ xecfg.ctxlen = 1;
memset(split, 0, sizeof(struct blame_entry [3]));
- plno = tlno = 0;
- for (i = 0; i < patch->num; i++) {
- struct chunk *chunk = &patch->chunks[i];
-
- handle_split(sb, ent, tlno, plno, chunk->same, parent, split);
- plno = chunk->p_next;
- tlno = chunk->t_next;
- }
+ xdi_diff_hunks(file_p, &file_o, handle_split_cb, &d, &xpp, &xecfg);
/* remainder, if any, all match the preimage */
- handle_split(sb, ent, tlno, plno, ent->num_lines, parent, split);
- free_patch(patch);
+ handle_split(sb, ent, d.tlno, d.plno, ent->num_lines, parent, split);
}
/*
@@ -1431,7 +1336,7 @@ static void get_commit_info(struct commit *commit,
int detailed)
{
int len;
- char *tmp, *endp;
+ char *tmp, *endp, *reencoded, *message;
static char author_buf[1024];
static char committer_buf[1024];
static char summary_buf[1024];
@@ -1449,24 +1354,29 @@ static void get_commit_info(struct commit *commit,
die("Cannot read commit %s",
sha1_to_hex(commit->object.sha1));
}
+ reencoded = reencode_commit_message(commit, NULL);
+ message = reencoded ? reencoded : commit->buffer;
ret->author = author_buf;
- get_ac_line(commit->buffer, "\nauthor ",
+ get_ac_line(message, "\nauthor ",
sizeof(author_buf), author_buf, &ret->author_mail,
&ret->author_time, &ret->author_tz);
- if (!detailed)
+ if (!detailed) {
+ free(reencoded);
return;
+ }
ret->committer = committer_buf;
- get_ac_line(commit->buffer, "\ncommitter ",
+ get_ac_line(message, "\ncommitter ",
sizeof(committer_buf), committer_buf, &ret->committer_mail,
&ret->committer_time, &ret->committer_tz);
ret->summary = summary_buf;
- tmp = strstr(commit->buffer, "\n\n");
+ tmp = strstr(message, "\n\n");
if (!tmp) {
error_out:
sprintf(summary_buf, "(%s)", sha1_to_hex(commit->object.sha1));
+ free(reencoded);
return;
}
tmp += 2;
@@ -1478,6 +1388,7 @@ static void get_commit_info(struct commit *commit,
goto error_out;
memcpy(summary_buf, tmp, len);
summary_buf[len] = 0;
+ free(reencoded);
}
/*
@@ -2085,7 +1996,6 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
if (!contents_from || strcmp("-", contents_from)) {
struct stat st;
const char *read_from;
- unsigned long fin_size;
if (contents_from) {
if (stat(contents_from, &st) < 0)
@@ -2097,7 +2007,6 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
die("Cannot lstat %s", path);
read_from = path;
}
- fin_size = xsize_t(st.st_size);
mode = canon_mode(st.st_mode);
switch (st.st_mode & S_IFMT) {
case S_IFREG:
@@ -2105,9 +2014,8 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
die("cannot open or read %s", read_from);
break;
case S_IFLNK:
- if (readlink(read_from, buf.buf, buf.alloc) != fin_size)
+ if (strbuf_readlink(&buf, read_from, st.st_size) < 0)
die("cannot readlink %s", read_from);
- buf.len = fin_size;
break;
default:
die("unsupported file type %s", read_from);
diff --git a/builtin-branch.c b/builtin-branch.c
index 8d634ff571..02fa38fd3b 100644
--- a/builtin-branch.c
+++ b/builtin-branch.c
@@ -97,7 +97,6 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)
unsigned char sha1[20];
char *name = NULL;
const char *fmt, *remote;
- char section[PATH_MAX];
int i;
int ret = 0;
@@ -160,16 +159,18 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)
continue;
}
- if (delete_ref(name, sha1)) {
+ if (delete_ref(name, sha1, 0)) {
error("Error deleting %sbranch '%s'", remote,
argv[i]);
ret = 1;
} else {
- printf("Deleted %sbranch %s.\n", remote, argv[i]);
- snprintf(section, sizeof(section), "branch.%s",
- argv[i]);
- if (git_config_rename_section(section, NULL) < 0)
+ struct strbuf buf = STRBUF_INIT;
+ printf("Deleted %sbranch %s (%s).\n", remote, argv[i],
+ find_unique_abbrev(sha1, DEFAULT_ABBREV));
+ strbuf_addf(&buf, "branch.%s", argv[i]);
+ if (git_config_rename_section(buf.buf, NULL) < 0)
warning("Update of config-file failed");
+ strbuf_release(&buf);
}
}
@@ -279,7 +280,7 @@ static int ref_cmp(const void *r1, const void *r2)
return strcmp(c1->name, c2->name);
}
-static void fill_tracking_info(char *stat, const char *branch_name)
+static void fill_tracking_info(struct strbuf *stat, const char *branch_name)
{
int ours, theirs;
struct branch *branch = branch_get(branch_name);
@@ -287,11 +288,11 @@ static void fill_tracking_info(char *stat, const char *branch_name)
if (!stat_tracking_info(branch, &ours, &theirs) || (!ours && !theirs))
return;
if (!ours)
- sprintf(stat, "[behind %d] ", theirs);
+ strbuf_addf(stat, "[behind %d] ", theirs);
else if (!theirs)
- sprintf(stat, "[ahead %d] ", ours);
+ strbuf_addf(stat, "[ahead %d] ", ours);
else
- sprintf(stat, "[ahead %d, behind %d] ", ours, theirs);
+ strbuf_addf(stat, "[ahead %d, behind %d] ", ours, theirs);
}
static int matches_merge_filter(struct commit *commit)
@@ -334,11 +335,8 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
}
if (verbose) {
- struct strbuf subject = STRBUF_INIT;
+ struct strbuf subject = STRBUF_INIT, stat = STRBUF_INIT;
const char *sub = " **** invalid ref ****";
- char stat[128];
-
- stat[0] = '\0';
commit = item->commit;
if (commit && !parse_commit(commit)) {
@@ -348,13 +346,14 @@ static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
}
if (item->kind == REF_LOCAL_BRANCH)
- fill_tracking_info(stat, item->name);
+ fill_tracking_info(&stat, item->name);
printf("%c %s%-*s%s %s %s%s\n", c, branch_get_color(color),
maxwidth, item->name,
branch_get_color(COLOR_BRANCH_RESET),
find_unique_abbrev(item->commit->object.sha1, abbrev),
- stat, sub);
+ stat.buf, sub);
+ strbuf_release(&stat);
strbuf_release(&subject);
} else {
printf("%c %s%s%s\n", c, branch_get_color(color), item->name,
@@ -426,42 +425,45 @@ static void print_ref_list(int kinds, int detached, int verbose, int abbrev, str
static void rename_branch(const char *oldname, const char *newname, int force)
{
- char oldref[PATH_MAX], newref[PATH_MAX], logmsg[PATH_MAX*2 + 100];
+ struct strbuf oldref = STRBUF_INIT, newref = STRBUF_INIT, logmsg = STRBUF_INIT;
unsigned char sha1[20];
- char oldsection[PATH_MAX], newsection[PATH_MAX];
+ struct strbuf oldsection = STRBUF_INIT, newsection = STRBUF_INIT;
if (!oldname)
die("cannot rename the current branch while not on any.");
- if (snprintf(oldref, sizeof(oldref), "refs/heads/%s", oldname) > sizeof(oldref))
- die("Old branchname too long");
+ strbuf_addf(&oldref, "refs/heads/%s", oldname);
- if (check_ref_format(oldref))
- die("Invalid branch name: %s", oldref);
+ if (check_ref_format(oldref.buf))
+ die("Invalid branch name: %s", oldref.buf);
- if (snprintf(newref, sizeof(newref), "refs/heads/%s", newname) > sizeof(newref))
- die("New branchname too long");
+ strbuf_addf(&newref, "refs/heads/%s", newname);
- if (check_ref_format(newref))
- die("Invalid branch name: %s", newref);
+ if (check_ref_format(newref.buf))
+ die("Invalid branch name: %s", newref.buf);
- if (resolve_ref(newref, sha1, 1, NULL) && !force)
+ if (resolve_ref(newref.buf, sha1, 1, NULL) && !force)
die("A branch named '%s' already exists.", newname);
- snprintf(logmsg, sizeof(logmsg), "Branch: renamed %s to %s",
- oldref, newref);
+ strbuf_addf(&logmsg, "Branch: renamed %s to %s",
+ oldref.buf, newref.buf);
- if (rename_ref(oldref, newref, logmsg))
+ if (rename_ref(oldref.buf, newref.buf, logmsg.buf))
die("Branch rename failed");
+ strbuf_release(&logmsg);
/* no need to pass logmsg here as HEAD didn't really move */
- if (!strcmp(oldname, head) && create_symref("HEAD", newref, NULL))
+ if (!strcmp(oldname, head) && create_symref("HEAD", newref.buf, NULL))
die("Branch renamed to %s, but HEAD is not updated!", newname);
- snprintf(oldsection, sizeof(oldsection), "branch.%s", oldref + 11);
- snprintf(newsection, sizeof(newsection), "branch.%s", newref + 11);
- if (git_config_rename_section(oldsection, newsection) < 0)
+ strbuf_addf(&oldsection, "branch.%s", oldref.buf + 11);
+ strbuf_release(&oldref);
+ strbuf_addf(&newsection, "branch.%s", newref.buf + 11);
+ strbuf_release(&newref);
+ if (git_config_rename_section(oldsection.buf, newsection.buf) < 0)
die("Branch is renamed, but update of config-file failed");
+ strbuf_release(&oldsection);
+ strbuf_release(&newsection);
}
static int opt_parse_with_commit(const struct option *opt, const char *arg, int unset)
diff --git a/builtin-cat-file.c b/builtin-cat-file.c
index 30d00a6664..8fad19daed 100644
--- a/builtin-cat-file.c
+++ b/builtin-cat-file.c
@@ -137,7 +137,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name)
break;
default:
- die("git cat-file: unknown option: %s\n", exp_type);
+ die("git cat-file: unknown option: %s", exp_type);
}
if (!buf)
diff --git a/builtin-check-attr.c b/builtin-check-attr.c
index cb783fc77e..15a04b7179 100644
--- a/builtin-check-attr.c
+++ b/builtin-check-attr.c
@@ -2,21 +2,84 @@
#include "cache.h"
#include "attr.h"
#include "quote.h"
+#include "parse-options.h"
-static const char check_attr_usage[] =
-"git check-attr attr... [--] pathname...";
+static int stdin_paths;
+static const char * const check_attr_usage[] = {
+"git check-attr attr... [--] pathname...",
+"git check-attr --stdin attr... < <list-of-paths>",
+NULL
+};
+
+static int null_term_line;
+
+static const struct option check_attr_options[] = {
+ OPT_BOOLEAN(0 , "stdin", &stdin_paths, "read file names from stdin"),
+ OPT_BOOLEAN('z', NULL, &null_term_line,
+ "input paths are terminated by a null character"),
+ OPT_END()
+};
+
+static void check_attr(int cnt, struct git_attr_check *check,
+ const char** name, const char *file)
+{
+ int j;
+ if (git_checkattr(file, cnt, check))
+ die("git_checkattr died");
+ for (j = 0; j < cnt; j++) {
+ const char *value = check[j].value;
+
+ if (ATTR_TRUE(value))
+ value = "set";
+ else if (ATTR_FALSE(value))
+ value = "unset";
+ else if (ATTR_UNSET(value))
+ value = "unspecified";
+
+ quote_c_style(file, NULL, stdout, 0);
+ printf(": %s: %s\n", name[j], value);
+ }
+}
+
+static void check_attr_stdin_paths(int cnt, struct git_attr_check *check,
+ const char** name)
+{
+ struct strbuf buf, nbuf;
+ int line_termination = null_term_line ? 0 : '\n';
+
+ strbuf_init(&buf, 0);
+ strbuf_init(&nbuf, 0);
+ while (strbuf_getline(&buf, stdin, line_termination) != EOF) {
+ if (line_termination && buf.buf[0] == '"') {
+ strbuf_reset(&nbuf);
+ if (unquote_c_style(&nbuf, buf.buf, NULL))
+ die("line is badly quoted");
+ strbuf_swap(&buf, &nbuf);
+ }
+ check_attr(cnt, check, name, buf.buf);
+ maybe_flush_or_die(stdout, "attribute to stdout");
+ }
+ strbuf_release(&buf);
+ strbuf_release(&nbuf);
+}
int cmd_check_attr(int argc, const char **argv, const char *prefix)
{
struct git_attr_check *check;
int cnt, i, doubledash;
+ const char *errstr = NULL;
+
+ argc = parse_options(argc, argv, check_attr_options, check_attr_usage,
+ PARSE_OPT_KEEP_DASHDASH);
+ if (!argc)
+ usage_with_options(check_attr_usage, check_attr_options);
if (read_cache() < 0) {
die("invalid cache");
}
doubledash = -1;
- for (i = 1; doubledash < 0 && i < argc; i++) {
+ for (i = 0; doubledash < 0 && i < argc; i++) {
if (!strcmp(argv[i], "--"))
doubledash = i;
}
@@ -24,41 +87,37 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)
/* If there is no double dash, we handle only one attribute */
if (doubledash < 0) {
cnt = 1;
- doubledash = 1;
+ doubledash = 0;
} else
- cnt = doubledash - 1;
+ cnt = doubledash;
doubledash++;
- if (cnt <= 0 || argc < doubledash)
- usage(check_attr_usage);
+ if (cnt <= 0)
+ errstr = "No attribute specified";
+ else if (stdin_paths && doubledash < argc)
+ errstr = "Can't specify files with --stdin";
+ if (errstr) {
+ error("%s", errstr);
+ usage_with_options(check_attr_usage, check_attr_options);
+ }
+
check = xcalloc(cnt, sizeof(*check));
for (i = 0; i < cnt; i++) {
const char *name;
struct git_attr *a;
- name = argv[i + 1];
+ name = argv[i];
a = git_attr(name, strlen(name));
if (!a)
return error("%s: not a valid attribute name", name);
check[i].attr = a;
}
- for (i = doubledash; i < argc; i++) {
- int j;
- if (git_checkattr(argv[i], cnt, check))
- die("git_checkattr died");
- for (j = 0; j < cnt; j++) {
- const char *value = check[j].value;
-
- if (ATTR_TRUE(value))
- value = "set";
- else if (ATTR_FALSE(value))
- value = "unset";
- else if (ATTR_UNSET(value))
- value = "unspecified";
-
- quote_c_style(argv[i], NULL, stdout, 0);
- printf(": %s: %s\n", argv[j+1], value);
- }
+ if (stdin_paths)
+ check_attr_stdin_paths(cnt, check, argv);
+ else {
+ for (i = doubledash; i < argc; i++)
+ check_attr(cnt, check, argv, argv[i]);
+ maybe_flush_or_die(stdout, "attribute to stdout");
}
return 0;
}
diff --git a/builtin-checkout-index.c b/builtin-checkout-index.c
index 4ba27024c5..0d534bc023 100644
--- a/builtin-checkout-index.c
+++ b/builtin-checkout-index.c
@@ -40,6 +40,7 @@
#include "cache.h"
#include "quote.h"
#include "cache-tree.h"
+#include "parse-options.h"
#define CHECKOUT_ALL 4
static int line_termination = '\n';
@@ -153,11 +154,58 @@ static void checkout_all(const char *prefix, int prefix_length)
exit(128);
}
-static const char checkout_cache_usage[] =
-"git checkout-index [-u] [-q] [-a] [-f] [-n] [--stage=[123]|all] [--prefix=<string>] [--temp] [--] <file>...";
+static const char * const builtin_checkout_index_usage[] = {
+ "git checkout-index [options] [--] <file>...",
+ NULL
+};
static struct lock_file lock_file;
+static int option_parse_u(const struct option *opt,
+ const char *arg, int unset)
+{
+ int *newfd = opt->value;
+
+ state.refresh_cache = 1;
+ if (*newfd < 0)
+ *newfd = hold_locked_index(&lock_file, 1);
+ return 0;
+}
+
+static int option_parse_z(const struct option *opt,
+ const char *arg, int unset)
+{
+ if (unset)
+ line_termination = '\n';
+ else
+ line_termination = 0;
+ return 0;
+}
+
+static int option_parse_prefix(const struct option *opt,
+ const char *arg, int unset)
+{
+ state.base_dir = arg;
+ state.base_dir_len = strlen(arg);
+ return 0;
+}
+
+static int option_parse_stage(const struct option *opt,
+ const char *arg, int unset)
+{
+ if (!strcmp(arg, "all")) {
+ to_tempfile = 1;
+ checkout_stage = CHECKOUT_ALL;
+ } else {
+ int ch = arg[0];
+ if ('1' <= ch && ch <= '3')
+ checkout_stage = arg[0] - '0';
+ else
+ die("stage should be between 1 and 3 or all");
+ }
+ return 0;
+}
+
int cmd_checkout_index(int argc, const char **argv, const char *prefix)
{
int i;
@@ -165,6 +213,33 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
int all = 0;
int read_from_stdin = 0;
int prefix_length;
+ 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_BOOLEAN('f', "force", &force,
+ "forces overwrite of existing files"),
+ OPT__QUIET(&quiet),
+ OPT_BOOLEAN('n', "no-create", &not_new,
+ "don't checkout new files"),
+ { OPTION_CALLBACK, 'u', "index", &newfd, NULL,
+ "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",
+ PARSE_OPT_NOARG, option_parse_z },
+ OPT_BOOLEAN(0, "stdin", &read_from_stdin,
+ "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>",
+ option_parse_prefix),
+ OPT_CALLBACK(0, "stage", NULL, NULL,
+ "copy out the files from named stage",
+ option_parse_stage),
+ OPT_END()
+ };
git_config(git_default_config, NULL);
state.base_dir = "";
@@ -174,72 +249,11 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
die("invalid cache");
}
- for (i = 1; i < argc; i++) {
- const char *arg = argv[i];
-
- if (!strcmp(arg, "--")) {
- i++;
- break;
- }
- if (!strcmp(arg, "-a") || !strcmp(arg, "--all")) {
- all = 1;
- continue;
- }
- if (!strcmp(arg, "-f") || !strcmp(arg, "--force")) {
- state.force = 1;
- continue;
- }
- if (!strcmp(arg, "-q") || !strcmp(arg, "--quiet")) {
- state.quiet = 1;
- continue;
- }
- if (!strcmp(arg, "-n") || !strcmp(arg, "--no-create")) {
- state.not_new = 1;
- continue;
- }
- if (!strcmp(arg, "-u") || !strcmp(arg, "--index")) {
- state.refresh_cache = 1;
- if (newfd < 0)
- newfd = hold_locked_index(&lock_file, 1);
- continue;
- }
- if (!strcmp(arg, "-z")) {
- line_termination = 0;
- continue;
- }
- if (!strcmp(arg, "--stdin")) {
- if (i != argc - 1)
- die("--stdin must be at the end");
- read_from_stdin = 1;
- i++; /* do not consider arg as a file name */
- break;
- }
- if (!strcmp(arg, "--temp")) {
- to_tempfile = 1;
- continue;
- }
- if (!prefixcmp(arg, "--prefix=")) {
- state.base_dir = arg+9;
- state.base_dir_len = strlen(state.base_dir);
- continue;
- }
- if (!prefixcmp(arg, "--stage=")) {
- if (!strcmp(arg + 8, "all")) {
- to_tempfile = 1;
- checkout_stage = CHECKOUT_ALL;
- } else {
- int ch = arg[8];
- if ('1' <= ch && ch <= '3')
- checkout_stage = arg[8] - '0';
- else
- die("stage should be between 1 and 3 or all");
- }
- continue;
- }
- if (arg[0] == '-')
- usage(checkout_cache_usage);
- break;
- }
+ argc = parse_options(argc, argv, builtin_checkout_index_options,
+ builtin_checkout_index_usage, 0);
+ state.force = force;
+ state.quiet = quiet;
+ state.not_new = not_new;
if (state.base_dir_len || to_tempfile) {
/* when --prefix is specified we do not
@@ -253,7 +267,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
}
/* Check out named files first */
- for ( ; i < argc; i++) {
+ for (i = 0; i < argc; i++) {
const char *arg = argv[i];
const char *p;
diff --git a/builtin-checkout.c b/builtin-checkout.c
index ad04a184a2..b5dd9c07b4 100644
--- a/builtin-checkout.c
+++ b/builtin-checkout.c
@@ -47,7 +47,7 @@ static int post_checkout_hook(struct commit *old, struct commit *new,
memset(&proc, 0, sizeof(proc));
argv[0] = name;
- argv[1] = xstrdup(sha1_to_hex(old->object.sha1));
+ argv[1] = xstrdup(sha1_to_hex(old ? old->object.sha1 : null_sha1));
argv[2] = xstrdup(sha1_to_hex(new->object.sha1));
argv[3] = changed ? "1" : "0";
argv[4] = NULL;
@@ -228,7 +228,8 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec,
struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file));
newfd = hold_locked_index(lock_file, 1);
- read_cache();
+ if (read_cache() < 0)
+ return error("corrupt index file");
if (source_tree)
read_tree_some(source_tree, pathspec);
@@ -371,7 +372,9 @@ static int merge_working_tree(struct checkout_opts *opts,
int ret;
struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file));
int newfd = hold_locked_index(lock_file, 1);
- read_cache();
+
+ if (read_cache() < 0)
+ return error("corrupt index file");
if (opts->force) {
ret = reset_tree(new->commit->tree, opts, 1);
@@ -397,8 +400,7 @@ static int merge_working_tree(struct checkout_opts *opts,
}
/* 2-way merge to the new branch */
- topts.initial_checkout = (!active_nr &&
- (old->commit == new->commit));
+ topts.initial_checkout = is_cache_unborn();
topts.update = 1;
topts.merge = 1;
topts.gently = opts->merge;
@@ -492,10 +494,10 @@ static void update_refs_for_switch(struct checkout_opts *opts,
}
old_desc = old->name;
- if (!old_desc)
+ if (!old_desc && old->commit)
old_desc = sha1_to_hex(old->commit->object.sha1);
strbuf_addf(&msg, "checkout: moving from %s to %s",
- old_desc, new->name);
+ old_desc ? old_desc : "(invalid)", new->name);
if (new->path) {
create_symref("HEAD", new->path, msg.buf);
@@ -551,10 +553,10 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
* a new commit, we want to mention the old commit once more
* to remind the user that it might be lost.
*/
- if (!opts->quiet && !old.path && new->commit != old.commit)
+ if (!opts->quiet && !old.path && old.commit && new->commit != old.commit)
describe_detached_head("Previous HEAD position was", old.commit);
- if (!old.commit) {
+ if (!old.commit && !opts->force) {
if (!opts->quiet) {
fprintf(stderr, "warning: You appear to be on a branch yet to be born.\n");
fprintf(stderr, "warning: Forcing checkout of %s.\n", new->name);
@@ -635,9 +637,6 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
git_xmerge_config("merge.conflictstyle", conflict_style, NULL);
}
- if (!opts.new_branch && (opts.track != git_branch_track))
- die("git checkout: --track and --no-track require -b");
-
if (opts.force && opts.merge)
die("git checkout: -f and -m are incompatible");
@@ -682,8 +681,8 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
argv++;
argc--;
+ new.name = arg;
if ((new.commit = lookup_commit_reference_gently(rev, 1))) {
- new.name = arg;
setup_branch_path(&new);
if (resolve_ref(new.path, rev, 1, NULL))
new.commit = lookup_commit_reference(rev);
diff --git a/builtin-clone.c b/builtin-clone.c
index 1ddc14b9c7..f1a1a0c365 100644
--- a/builtin-clone.c
+++ b/builtin-clone.c
@@ -38,9 +38,11 @@ static int option_local, option_no_hardlinks, option_shared;
static char *option_template, *option_reference, *option_depth;
static char *option_origin = NULL;
static char *option_upload_pack = "git-upload-pack";
+static int option_verbose;
static struct option builtin_clone_options[] = {
OPT__QUIET(&option_quiet),
+ OPT__VERBOSE(&option_verbose),
OPT_BOOLEAN('n', "no-checkout", &option_no_checkout,
"don't create a checkout"),
OPT_BOOLEAN(0, "bare", &option_bare, "create a bare repository"),
@@ -132,9 +134,9 @@ static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)
}
if (is_bare) {
- char *result = xmalloc(end - start + 5);
- sprintf(result, "%.*s.git", (int)(end - start), start);
- return result;
+ struct strbuf result = STRBUF_INIT;
+ strbuf_addf(&result, "%.*s.git", (int)(end - start), start);
+ return strbuf_detach(&result, 0);
}
return xstrndup(start, end - start);
@@ -181,36 +183,38 @@ static void setup_reference(const char *repo)
free(ref_git_copy);
}
-static void copy_or_link_directory(char *src, char *dest)
+static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest)
{
struct dirent *de;
struct stat buf;
int src_len, dest_len;
DIR *dir;
- dir = opendir(src);
+ dir = opendir(src->buf);
if (!dir)
- die("failed to open %s\n", src);
+ die("failed to open %s", src->buf);
- if (mkdir(dest, 0777)) {
+ if (mkdir(dest->buf, 0777)) {
if (errno != EEXIST)
- die("failed to create directory %s\n", dest);
- else if (stat(dest, &buf))
- die("failed to stat %s\n", dest);
+ die("failed to create directory %s", dest->buf);
+ else if (stat(dest->buf, &buf))
+ die("failed to stat %s", dest->buf);
else if (!S_ISDIR(buf.st_mode))
- die("%s exists and is not a directory\n", dest);
+ die("%s exists and is not a directory", dest->buf);
}
- src_len = strlen(src);
- src[src_len] = '/';
- dest_len = strlen(dest);
- dest[dest_len] = '/';
+ strbuf_addch(src, '/');
+ src_len = src->len;
+ strbuf_addch(dest, '/');
+ dest_len = dest->len;
while ((de = readdir(dir)) != NULL) {
- strcpy(src + src_len + 1, de->d_name);
- strcpy(dest + dest_len + 1, de->d_name);
- if (stat(src, &buf)) {
- warning ("failed to stat %s\n", src);
+ strbuf_setlen(src, src_len);
+ strbuf_addstr(src, de->d_name);
+ strbuf_setlen(dest, dest_len);
+ strbuf_addstr(dest, de->d_name);
+ if (stat(src->buf, &buf)) {
+ warning ("failed to stat %s\n", src->buf);
continue;
}
if (S_ISDIR(buf.st_mode)) {
@@ -219,17 +223,17 @@ static void copy_or_link_directory(char *src, char *dest)
continue;
}
- if (unlink(dest) && errno != ENOENT)
- die("failed to unlink %s\n", dest);
+ if (unlink(dest->buf) && errno != ENOENT)
+ die("failed to unlink %s", dest->buf);
if (!option_no_hardlinks) {
- if (!link(src, dest))
+ if (!link(src->buf, dest->buf))
continue;
if (option_local)
- die("failed to create link %s\n", dest);
+ die("failed to create link %s", dest->buf);
option_no_hardlinks = 1;
}
- if (copy_file(dest, src, 0666))
- die("failed to copy file to %s\n", dest);
+ if (copy_file(dest->buf, src->buf, 0666))
+ die("failed to copy file to %s", dest->buf);
}
closedir(dir);
}
@@ -238,17 +242,19 @@ static const struct ref *clone_local(const char *src_repo,
const char *dest_repo)
{
const struct ref *ret;
- char src[PATH_MAX];
- char dest[PATH_MAX];
+ struct strbuf src = STRBUF_INIT;
+ struct strbuf dest = STRBUF_INIT;
struct remote *remote;
struct transport *transport;
if (option_shared)
add_to_alternates_file(src_repo);
else {
- snprintf(src, PATH_MAX, "%s/objects", src_repo);
- snprintf(dest, PATH_MAX, "%s/objects", dest_repo);
- copy_or_link_directory(src, dest);
+ strbuf_addf(&src, "%s/objects", src_repo);
+ strbuf_addf(&dest, "%s/objects", dest_repo);
+ copy_or_link_directory(&src, &dest);
+ strbuf_release(&src);
+ strbuf_release(&dest);
}
remote = remote_get(src_repo);
@@ -352,8 +358,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
const char *repo_name, *repo, *work_tree, *git_dir;
char *path, *dir;
const struct ref *refs, *head_points_at, *remote_head, *mapped_refs;
- char branch_top[256], key[256], value[256];
- struct strbuf reflog_msg = STRBUF_INIT;
+ struct strbuf key = STRBUF_INIT, value = STRBUF_INIT;
+ struct strbuf branch_top = STRBUF_INIT, reflog_msg = STRBUF_INIT;
struct transport *transport = NULL;
char *src_ref_prefix = "refs/heads/";
@@ -457,35 +463,36 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
if (option_bare) {
if (option_mirror)
src_ref_prefix = "refs/";
- strcpy(branch_top, src_ref_prefix);
+ strbuf_addstr(&branch_top, src_ref_prefix);
git_config_set("core.bare", "true");
} else {
- snprintf(branch_top, sizeof(branch_top),
- "refs/remotes/%s/", option_origin);
+ strbuf_addf(&branch_top, "refs/remotes/%s/", option_origin);
}
if (option_mirror || !option_bare) {
/* Configure the remote */
if (option_mirror) {
- snprintf(key, sizeof(key),
- "remote.%s.mirror", option_origin);
- git_config_set(key, "true");
+ strbuf_addf(&key, "remote.%s.mirror", option_origin);
+ git_config_set(key.buf, "true");
+ strbuf_reset(&key);
}
- snprintf(key, sizeof(key), "remote.%s.url", option_origin);
- git_config_set(key, repo);
+ strbuf_addf(&key, "remote.%s.url", option_origin);
+ git_config_set(key.buf, repo);
+ strbuf_reset(&key);
- snprintf(key, sizeof(key), "remote.%s.fetch", option_origin);
- snprintf(value, sizeof(value),
- "+%s*:%s*", src_ref_prefix, branch_top);
- git_config_set_multivar(key, value, "^$", 0);
+ strbuf_addf(&key, "remote.%s.fetch", option_origin);
+ strbuf_addf(&value, "+%s*:%s*", src_ref_prefix, branch_top.buf);
+ git_config_set_multivar(key.buf, value.buf, "^$", 0);
+ strbuf_reset(&key);
+ strbuf_reset(&value);
}
refspec.force = 0;
refspec.pattern = 1;
refspec.src = src_ref_prefix;
- refspec.dst = branch_top;
+ refspec.dst = branch_top.buf;
if (path && !is_bundle)
refs = clone_local(path, git_dir);
@@ -504,6 +511,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
if (option_quiet)
transport->verbose = -1;
+ else if (option_verbose)
+ transport->progress = 1;
if (option_upload_pack)
transport_set_option(transport, TRANS_OPT_UPLOADPACK,
@@ -537,7 +546,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
head_points_at->old_sha1,
NULL, 0, DIE_ON_ERR);
- strbuf_addstr(&head_ref, branch_top);
+ strbuf_addstr(&head_ref, branch_top.buf);
strbuf_addstr(&head_ref, "HEAD");
/* Remote branch link */
@@ -545,10 +554,11 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
head_points_at->peer_ref->name,
reflog_msg.buf);
- snprintf(key, sizeof(key), "branch.%s.remote", head);
- git_config_set(key, option_origin);
- snprintf(key, sizeof(key), "branch.%s.merge", head);
- git_config_set(key, head_points_at->name);
+ strbuf_addf(&key, "branch.%s.remote", head);
+ git_config_set(key.buf, option_origin);
+ strbuf_reset(&key);
+ strbuf_addf(&key, "branch.%s.merge", head);
+ git_config_set(key.buf, head_points_at->name);
}
} else if (remote_head) {
/* Source had detached HEAD pointing somewhere. */
@@ -598,6 +608,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
}
strbuf_release(&reflog_msg);
+ strbuf_release(&branch_top);
+ strbuf_release(&key);
+ strbuf_release(&value);
junk_pid = 0;
return 0;
}
diff --git a/builtin-commit.c b/builtin-commit.c
index a2755dc3be..2f0b00a174 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -225,18 +225,18 @@ static char *prepare_index(int argc, const char **argv, const char *prefix)
if (interactive) {
interactive_add(argc, argv, prefix);
- if (read_cache() < 0)
+ if (read_cache_preload(NULL) < 0)
die("index file corrupt");
commit_style = COMMIT_AS_IS;
return get_index_file();
}
- if (read_cache() < 0)
- die("index file corrupt");
-
if (*argv)
pathspec = get_pathspec(prefix, argv);
+ if (read_cache_preload(pathspec) < 0)
+ die("index file corrupt");
+
/*
* Non partial, non as-is commit.
*
@@ -320,7 +320,9 @@ static char *prepare_index(int argc, const char **argv, const char *prefix)
die("unable to write new_index file");
fd = hold_lock_file_for_update(&false_lock,
- git_path("next-index-%"PRIuMAX, (uintmax_t) getpid()), 1);
+ git_path("next-index-%"PRIuMAX,
+ (uintmax_t) getpid()),
+ LOCK_DIE_ON_ERROR);
create_base_index();
add_remove_files(&partial);
@@ -622,7 +624,6 @@ static int prepare_to_commit(const char *index_file, const char *prefix)
if (!commitable && !in_merge && !allow_empty &&
!(amend && is_a_merge(head_sha1))) {
run_status(stdout, index_file, prefix, 0);
- unlink(commit_editmsg);
return 0;
}
@@ -637,7 +638,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix)
active_cache_tree = cache_tree();
if (cache_tree_update(active_cache_tree,
active_cache, active_nr, 0, 0) < 0) {
- error("Error building trees; the index is unmerged?");
+ error("Error building trees");
return 0;
}
@@ -864,6 +865,9 @@ int cmd_status(int argc, const char **argv, const char *prefix)
if (wt_status_use_color == -1)
wt_status_use_color = git_use_color_default;
+ if (diff_use_color_default == -1)
+ diff_use_color_default = git_use_color_default;
+
argc = parse_and_validate_options(argc, argv, builtin_status_usage, prefix);
index_file = prepare_index(argc, argv, prefix);
@@ -879,6 +883,9 @@ static void print_summary(const char *prefix, const unsigned char *sha1)
{
struct rev_info rev;
struct commit *commit;
+ static const char *format = "format:%h: \"%s\"";
+ unsigned char junk_sha1[20];
+ const char *head = resolve_ref("HEAD", junk_sha1, 0, NULL);
commit = lookup_commit(sha1);
if (!commit)
@@ -896,18 +903,24 @@ static void print_summary(const char *prefix, const unsigned char *sha1)
rev.verbose_header = 1;
rev.show_root_diff = 1;
- get_commit_format("format:%h: %s", &rev);
+ get_commit_format(format, &rev);
rev.always_show_header = 0;
rev.diffopt.detect_rename = 1;
rev.diffopt.rename_limit = 100;
rev.diffopt.break_opt = 0;
diff_setup_done(&rev.diffopt);
- printf("Created %scommit ", initial_commit ? "initial " : "");
+ printf("[%s%s]: created ",
+ !prefixcmp(head, "refs/heads/") ?
+ head + 11 :
+ !strcmp(head, "HEAD") ?
+ "detached HEAD" :
+ head,
+ initial_commit ? " (root-commit)" : "");
if (!log_tree_commit(&rev, commit)) {
struct strbuf buf = STRBUF_INIT;
- format_commit_message(commit, "%h: %s", &buf, DATE_NORMAL);
+ format_commit_message(commit, format + 7, &buf, DATE_NORMAL);
printf("%s\n", buf.buf);
strbuf_release(&buf);
}
@@ -921,11 +934,6 @@ static int git_commit_config(const char *k, const char *v, void *cb)
return git_status_config(k, v, cb);
}
-static const char commit_utf8_warn[] =
-"Warning: commit message does 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";
-
int cmd_commit(int argc, const char **argv, const char *prefix)
{
struct strbuf sb = STRBUF_INIT;
@@ -934,9 +942,14 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
unsigned char commit_sha1[20];
struct ref_lock *ref_lock;
struct commit_list *parents = NULL, **pptr = &parents;
+ struct stat statbuf;
+ int allow_fast_forward = 1;
git_config(git_commit_config, NULL);
+ if (wt_status_use_color == -1)
+ wt_status_use_color = git_use_color_default;
+
argc = parse_and_validate_options(argc, argv, builtin_commit_usage, prefix);
index_file = prepare_index(argc, argv, prefix);
@@ -980,22 +993,33 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
}
fclose(fp);
strbuf_release(&m);
+ if (!stat(git_path("MERGE_MODE"), &statbuf)) {
+ if (strbuf_read_file(&sb, git_path("MERGE_MODE"), 0) < 0)
+ die("could not read MERGE_MODE: %s",
+ strerror(errno));
+ if (!strcmp(sb.buf, "no-ff"))
+ allow_fast_forward = 0;
+ }
+ if (allow_fast_forward)
+ parents = reduce_heads(parents);
} else {
reflog_msg = "commit";
pptr = &commit_list_insert(lookup_commit(head_sha1), pptr)->next;
}
- parents = reduce_heads(parents);
/* Finally, get the commit message */
+ strbuf_reset(&sb);
if (strbuf_read_file(&sb, git_path(commit_editmsg), 0) < 0) {
rollback_index_files();
die("could not read commit message");
}
/* Truncate the message just before the diff, if any. */
- p = strstr(sb.buf, "\ndiff --git a/");
- if (p != NULL)
- strbuf_setlen(&sb, p - sb.buf + 1);
+ if (verbose) {
+ p = strstr(sb.buf, "\ndiff --git ");
+ if (p != NULL)
+ strbuf_setlen(&sb, p - sb.buf + 1);
+ }
if (cleanup_mode != CLEANUP_NONE)
stripspace(&sb, cleanup_mode == CLEANUP_ALL);
@@ -1035,6 +1059,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
unlink(git_path("MERGE_HEAD"));
unlink(git_path("MERGE_MSG"));
+ unlink(git_path("MERGE_MODE"));
unlink(git_path("SQUASH_MSG"));
if (commit_index_files())
diff --git a/builtin-config.c b/builtin-config.c
index 91fdc4985d..f71016204b 100644
--- a/builtin-config.c
+++ b/builtin-config.c
@@ -84,7 +84,7 @@ static int get_value(const char* key_, const char* regex_)
local = config_exclusive_filename;
if (!local) {
const char *home = getenv("HOME");
- local = repo_config = xstrdup(git_path("config"));
+ local = repo_config = git_pathdup("config");
if (git_config_global() && home)
global = xstrdup(mkpath("%s/.gitconfig", home));
if (git_config_system())
diff --git a/builtin-describe.c b/builtin-describe.c
index ec404c839b..3a007ed1ca 100644
--- a/builtin-describe.c
+++ b/builtin-describe.c
@@ -15,8 +15,8 @@ static const char * const describe_usage[] = {
};
static int debug; /* Display lots of verbose info */
-static int all; /* Default to annotated tags only */
-static int tags; /* But allow any tags if --tags is specified */
+static int all; /* Any valid ref can be used */
+static int tags; /* Allow lightweight tags */
static int longformat;
static int abbrev = DEFAULT_ABBREV;
static int max_candidates = 10;
@@ -112,8 +112,6 @@ static int compare_pt(const void *a_, const void *b_)
{
struct possible_tag *a = (struct possible_tag *)a_;
struct possible_tag *b = (struct possible_tag *)b_;
- if (a->name->prio != b->name->prio)
- return b->name->prio - a->name->prio;
if (a->depth != b->depth)
return a->depth - b->depth;
if (a->found_order != b->found_order)
@@ -160,7 +158,7 @@ static void display_name(struct commit_name *n)
n->tag = lookup_tag(n->sha1);
if (!n->tag || parse_tag(n->tag) || !n->tag->tag)
die("annotated tag %s not available", n->path);
- if (strcmp(n->tag->tag, n->path))
+ if (strcmp(n->tag->tag, all ? n->path + 5 : n->path))
warning("tag '%s' is really '%s' here", n->tag->tag, n->path);
}
diff --git a/builtin-diff-files.c b/builtin-diff-files.c
index 2b578c714d..5b64011de8 100644
--- a/builtin-diff-files.c
+++ b/builtin-diff-files.c
@@ -59,8 +59,8 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix)
(rev.diffopt.output_format & DIFF_FORMAT_PATCH))
rev.combine_merges = rev.dense_combined_merges = 1;
- if (read_cache() < 0) {
- perror("read_cache");
+ if (read_cache_preload(rev.diffopt.paths) < 0) {
+ perror("read_cache_preload");
return -1;
}
result = run_diff_files(&rev, options);
diff --git a/builtin-diff.c b/builtin-diff.c
index 9c8c295732..d75d69bf57 100644
--- a/builtin-diff.c
+++ b/builtin-diff.c
@@ -118,7 +118,7 @@ static int builtin_diff_index(struct rev_info *revs,
int cached = 0;
while (1 < argc) {
const char *arg = argv[1];
- if (!strcmp(arg, "--cached"))
+ if (!strcmp(arg, "--cached") || !strcmp(arg, "--staged"))
cached = 1;
else
usage(builtin_diff_usage);
@@ -134,8 +134,8 @@ static int builtin_diff_index(struct rev_info *revs,
revs->max_count != -1 || revs->min_age != -1 ||
revs->max_age != -1)
usage(builtin_diff_usage);
- if (read_cache() < 0) {
- perror("read_cache");
+ if (read_cache_preload(revs->diffopt.paths) < 0) {
+ perror("read_cache_preload");
return -1;
}
return run_diff_index(revs, cached);
@@ -234,8 +234,8 @@ static int builtin_diff_files(struct rev_info *revs, int argc, const char **argv
revs->combine_merges = revs->dense_combined_merges = 1;
setup_work_tree();
- if (read_cache() < 0) {
- perror("read_cache");
+ if (read_cache_preload(revs->diffopt.paths) < 0) {
+ perror("read_cache_preload");
return -1;
}
result = run_diff_files(revs, options);
@@ -290,6 +290,10 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
/* Otherwise, we are doing the usual "git" diff */
rev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index;
+ /* Default to let external and textconv be used */
+ DIFF_OPT_SET(&rev.diffopt, ALLOW_EXTERNAL);
+ DIFF_OPT_SET(&rev.diffopt, ALLOW_TEXTCONV);
+
if (nongit)
die("Not a git repository");
argc = setup_revisions(argc, argv, &rev, NULL);
@@ -298,7 +302,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
if (diff_setup_done(&rev.diffopt) < 0)
die("diff_setup_done failed");
}
- DIFF_OPT_SET(&rev.diffopt, ALLOW_EXTERNAL);
+
DIFF_OPT_SET(&rev.diffopt, RECURSIVE);
/*
@@ -319,7 +323,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
const char *arg = argv[i];
if (!strcmp(arg, "--"))
break;
- else if (!strcmp(arg, "--cached")) {
+ else if (!strcmp(arg, "--cached") ||
+ !strcmp(arg, "--staged")) {
add_head_to_pending(&rev);
if (!rev.pending.nr)
die("No HEAD commit to compare with (yet)");
diff --git a/builtin-fast-export.c b/builtin-fast-export.c
index 7c93eb878d..e9ee2c79ac 100644
--- a/builtin-fast-export.c
+++ b/builtin-fast-export.c
@@ -24,6 +24,7 @@ static const char *fast_export_usage[] = {
static int progress;
static enum { VERBATIM, WARN, STRIP, ABORT } signed_tag_mode = ABORT;
+static int fake_missing_tagger;
static int parse_opt_signed_tag_mode(const struct option *opt,
const char *arg, int unset)
@@ -297,10 +298,17 @@ static void handle_tag(const char *name, struct tag *tag)
message_size = strlen(message);
}
tagger = memmem(buf, message ? message - buf : size, "\ntagger ", 8);
- if (!tagger)
- die ("No tagger for tag %s", sha1_to_hex(tag->object.sha1));
- tagger++;
- tagger_end = strchrnul(tagger, '\n');
+ if (!tagger) {
+ if (fake_missing_tagger)
+ tagger = "tagger Unspecified Tagger "
+ "<unspecified-tagger> 0 +0000";
+ else
+ tagger = "";
+ tagger_end = tagger + strlen(tagger);
+ } else {
+ tagger++;
+ tagger_end = strchrnul(tagger, '\n');
+ }
/* handle signed tags */
if (message) {
@@ -326,9 +334,10 @@ static void handle_tag(const char *name, struct tag *tag)
if (!prefixcmp(name, "refs/tags/"))
name += 10;
- printf("tag %s\nfrom :%d\n%.*s\ndata %d\n%.*s\n",
+ printf("tag %s\nfrom :%d\n%.*s%sdata %d\n%.*s\n",
name, get_object_mark(tag->tagged),
(int)(tagger_end - tagger), tagger,
+ tagger == tagger_end ? "" : "\n",
(int)message_size, (int)message_size, message ? message : "");
}
@@ -354,7 +363,7 @@ static void get_tags_and_duplicates(struct object_array *pending,
case OBJ_TAG:
tag = (struct tag *)e->item;
while (tag && tag->object.type == OBJ_TAG) {
- string_list_insert(full_name, extra_refs)->util = tag;
+ string_list_append(full_name, extra_refs)->util = tag;
tag = (struct tag *)tag->tagged;
}
if (!tag)
@@ -374,7 +383,7 @@ static void get_tags_and_duplicates(struct object_array *pending,
}
if (commit->util)
/* more than one name for the same object */
- string_list_insert(full_name, extra_refs)->util = commit;
+ string_list_append(full_name, extra_refs)->util = commit;
else
commit->util = full_name;
}
@@ -483,9 +492,14 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
"Dump marks to this file"),
OPT_STRING(0, "import-marks", &import_filename, "FILE",
"Import marks from this file"),
+ OPT_BOOLEAN(0, "fake-missing-tagger", &fake_missing_tagger,
+ "Fake a tagger when tags lack one"),
OPT_END()
};
+ if (argc == 1)
+ usage_with_options (fast_export_usage, options);
+
/* we handle encodings */
git_config(git_default_config, NULL);
diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c
index fa3c936493..67fb80ec48 100644
--- a/builtin-fetch-pack.c
+++ b/builtin-fetch-pack.c
@@ -780,7 +780,8 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args,
struct ref *ref_cpy;
fetch_pack_setup();
- memcpy(&args, my_args, sizeof(args));
+ if (&args != my_args)
+ memcpy(&args, my_args, sizeof(args));
if (args.depth > 0) {
if (stat(git_path("shallow"), &st))
st.st_mtime = 0;
@@ -813,7 +814,8 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args,
)
die("shallow file was changed during fetch");
- fd = hold_lock_file_for_update(&lock, shallow, 1);
+ fd = hold_lock_file_for_update(&lock, shallow,
+ LOCK_DIE_ON_ERROR);
if (!write_shallow_commits(fd, 0)) {
unlink(shallow);
rollback_lock_file(&lock);
diff --git a/builtin-fetch.c b/builtin-fetch.c
index ee93d3a93d..de6f3074b1 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -22,7 +22,7 @@ enum {
TAGS_SET = 2
};
-static int append, force, keep, update_head_ok, verbose, quiet;
+static int append, force, keep, update_head_ok, verbosity;
static int tags = TAGS_DEFAULT;
static const char *depth;
static const char *upload_pack;
@@ -30,8 +30,7 @@ static struct strbuf default_rla = STRBUF_INIT;
static struct transport *transport;
static struct option builtin_fetch_options[] = {
- OPT__QUIET(&quiet),
- OPT__VERBOSE(&verbose),
+ OPT__VERBOSITY(&verbosity),
OPT_BOOLEAN('a', "append", &append,
"append to .git/FETCH_HEAD instead of overwriting"),
OPT_STRING(0, "upload-pack", &upload_pack, "PATH",
@@ -192,7 +191,6 @@ static int s_update_ref(const char *action,
static int update_local_ref(struct ref *ref,
const char *remote,
- int verbose,
char *display)
{
struct commit *current = NULL, *updated;
@@ -210,7 +208,7 @@ static int update_local_ref(struct ref *ref,
die("object %s not found", sha1_to_hex(ref->new_sha1));
if (!hashcmp(ref->old_sha1, ref->new_sha1)) {
- if (verbose)
+ if (verbosity > 0)
sprintf(display, "= %-*s %-*s -> %s", SUMMARY_WIDTH,
"[up to date]", REFCOL_WIDTH, remote,
pretty_ref);
@@ -366,18 +364,19 @@ static int store_updated_refs(const char *url, const char *remote_name,
note);
if (ref)
- rc |= update_local_ref(ref, what, verbose, note);
+ rc |= update_local_ref(ref, what, note);
else
sprintf(note, "* %-*s %-*s -> FETCH_HEAD",
SUMMARY_WIDTH, *kind ? kind : "branch",
REFCOL_WIDTH, *what ? what : "HEAD");
if (*note) {
- if (!shown_url) {
+ if (verbosity >= 0 && !shown_url) {
fprintf(stderr, "From %.*s\n",
url_len, url);
shown_url = 1;
}
- fprintf(stderr, " %s\n", note);
+ if (verbosity >= 0)
+ fprintf(stderr, " %s\n", note);
}
}
fclose(fp);
@@ -521,8 +520,8 @@ static void find_non_local_tags(struct transport *transport,
will_fetch(head, ref->old_sha1))) {
string_list_insert(ref_name, &new_refs);
- rm = alloc_ref_from_str(ref_name);
- rm->peer_ref = alloc_ref_from_str(ref_name);
+ rm = alloc_ref(ref_name);
+ rm->peer_ref = alloc_ref(ref_name);
hashcpy(rm->old_sha1, ref_sha1);
**tail = rm;
@@ -534,6 +533,19 @@ static void find_non_local_tags(struct transport *transport,
string_list_clear(&new_refs, 0);
}
+static void check_not_current_branch(struct ref *ref_map)
+{
+ struct branch *current_branch = branch_get(NULL);
+
+ if (is_bare_repository() || !current_branch)
+ return;
+
+ for (; ref_map; ref_map = ref_map->next)
+ if (ref_map->peer_ref && !strcmp(current_branch->refname,
+ ref_map->peer_ref->name))
+ die("Refusing to fetch into current branch");
+}
+
static int do_fetch(struct transport *transport,
struct refspec *refs, int ref_count)
{
@@ -558,6 +570,8 @@ static int do_fetch(struct transport *transport,
}
ref_map = get_ref_map(transport, refs, ref_count, tags, &autotags);
+ if (!update_head_ok)
+ check_not_current_branch(ref_map);
for (rm = ref_map; rm; rm = rm->next) {
if (rm->peer_ref)
@@ -593,7 +607,7 @@ static void set_option(const char *name, const char *value)
{
int r = transport_set_option(transport, name, value);
if (r < 0)
- die("Option \"%s\" value \"%s\" is not valid for %s\n",
+ die("Option \"%s\" value \"%s\" is not valid for %s",
name, value, transport->url);
if (r > 0)
warning("Option \"%s\" is ignored for %s\n",
@@ -622,9 +636,9 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
remote = remote_get(argv[0]);
transport = transport_get(remote, remote->url[0]);
- if (verbose >= 2)
+ if (verbosity >= 2)
transport->verbose = 1;
- if (quiet)
+ if (verbosity < 0)
transport->verbose = -1;
if (upload_pack)
set_option(TRANS_OPT_UPLOADPACK, upload_pack);
diff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c
index fa6c1ed752..e46b7adc97 100644
--- a/builtin-for-each-ref.c
+++ b/builtin-for-each-ref.c
@@ -620,14 +620,16 @@ static char *get_short_ref(struct refinfo *ref)
for (j = 0; j < i; j++) {
const char *rule = ref_rev_parse_rules[j];
unsigned char short_objectname[20];
+ char refname[PATH_MAX];
/*
* the short name is ambiguous, if it resolves
* (with this previous rule) to a valid ref
* read_ref() returns 0 on success
*/
- if (!read_ref(mkpath(rule, short_name_len, short_name),
- short_objectname))
+ mksnpath(refname, sizeof(refname),
+ rule, short_name_len, short_name);
+ if (!read_ref(refname, short_objectname))
break;
}
diff --git a/builtin-fsck.c b/builtin-fsck.c
index d3f3de9446..5c4c77adaa 100644
--- a/builtin-fsck.c
+++ b/builtin-fsck.c
@@ -64,11 +64,11 @@ static int fsck_error_func(struct object *obj, int type, const char *err, ...)
return (type == FSCK_WARN) ? 0 : 1;
}
+static struct object_array pending;
+
static int mark_object(struct object *obj, int type, void *data)
{
- struct tree *tree = NULL;
struct object *parent = data;
- int result;
if (!obj) {
printf("broken link from %7s %s\n",
@@ -96,6 +96,20 @@ static int mark_object(struct object *obj, int type, void *data)
return 1;
}
+ add_object_array(obj, (void *) parent, &pending);
+ return 0;
+}
+
+static void mark_object_reachable(struct object *obj)
+{
+ mark_object(obj, OBJ_ANY, 0);
+}
+
+static int traverse_one_object(struct object *obj, struct object *parent)
+{
+ int result;
+ struct tree *tree = NULL;
+
if (obj->type == OBJ_TREE) {
obj->parsed = 0;
tree = (struct tree *)obj;
@@ -107,15 +121,22 @@ static int mark_object(struct object *obj, int type, void *data)
free(tree->buffer);
tree->buffer = NULL;
}
- if (result < 0)
- result = 1;
-
return result;
}
-static void mark_object_reachable(struct object *obj)
+static int traverse_reachable(void)
{
- mark_object(obj, OBJ_ANY, 0);
+ int result = 0;
+ while (pending.nr) {
+ struct object_array_entry *entry;
+ struct object *obj, *parent;
+
+ entry = pending.objects + --pending.nr;
+ obj = entry->item;
+ parent = (struct object *) entry->name;
+ result |= traverse_one_object(obj, parent);
+ }
+ return !!result;
}
static int mark_used(struct object *obj, int type, void *data)
@@ -201,12 +222,16 @@ static void check_unreachable_object(struct object *obj)
char *buf = read_sha1_file(obj->sha1,
&type, &size);
if (buf) {
- fwrite(buf, size, 1, f);
+ if (fwrite(buf, size, 1, f) != 1)
+ die("Could not write %s: %s",
+ filename, strerror(errno));
free(buf);
}
} else
fprintf(f, "%s\n", sha1_to_hex(obj->sha1));
- fclose(f);
+ if (fclose(f))
+ die("Could not finish %s: %s",
+ filename, strerror(errno));
}
return;
}
@@ -233,6 +258,9 @@ static void check_connectivity(void)
{
int i, max;
+ /* Traverse the pending reachable objects */
+ traverse_reachable();
+
/* Look up all the requirements, warn about missing objects.. */
max = get_max_object_index();
if (verbose)
@@ -600,7 +628,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
}
heads = 0;
- for (i = 1; i < argc; i++) {
+ for (i = 0; i < argc; i++) {
const char *arg = argv[i];
if (!get_sha1(arg, head_sha1)) {
struct object *obj = lookup_object(head_sha1);
diff --git a/builtin-gc.c b/builtin-gc.c
index 7af65bb31b..f8eae4adb4 100644
--- a/builtin-gc.c
+++ b/builtin-gc.c
@@ -131,19 +131,9 @@ static int too_many_packs(void)
prepare_packed_git();
for (cnt = 0, p = packed_git; p; p = p->next) {
- char path[PATH_MAX];
- size_t len;
- int keep;
-
if (!p->pack_local)
continue;
- len = strlen(p->pack_name);
- if (PATH_MAX <= len + 1)
- continue; /* oops, give up */
- memcpy(path, p->pack_name, len-5);
- memcpy(path + len - 5, ".keep", 6);
- keep = access(p->pack_name, F_OK) && (errno == ENOENT);
- if (keep)
+ if (p->pack_keep)
continue;
/*
* Perhaps check the size of the pack and count only
@@ -198,7 +188,9 @@ static int need_to_gc(void)
* there is no need.
*/
if (too_many_packs())
- append_option(argv_repack, "-A", MAX_ADD);
+ append_option(argv_repack,
+ !strcmp(prune_expire, "now") ? "-a" : "-A",
+ MAX_ADD);
else if (!too_many_loose_objects())
return 0;
@@ -253,7 +245,9 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
"run \"git gc\" manually. See "
"\"git help gc\" for more information.\n");
} else
- append_option(argv_repack, "-A", MAX_ADD);
+ append_option(argv_repack,
+ !strcmp(prune_expire, "now") ? "-a" : "-A",
+ MAX_ADD);
if (pack_refs && run_command_v_opt(argv_pack_refs, RUN_GIT_CMD))
return error(FAILED_RUN, argv_pack_refs[0]);
diff --git a/builtin-grep.c b/builtin-grep.c
index 624f86e287..bebf15cd6f 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -20,6 +20,8 @@
#endif
#endif
+static int builtin_grep;
+
/*
* git grep pathspecs are somewhat different from diff-tree pathspecs;
* pathname wildcards are allowed.
@@ -389,7 +391,7 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
* we grep through the checked-out files. It tends to
* be a lot more optimized
*/
- if (!cached) {
+ if (!cached && !builtin_grep) {
hit = external_grep(opt, paths, cached);
if (hit >= 0)
return hit;
@@ -402,7 +404,12 @@ static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
continue;
if (!pathspec_matches(paths, ce->name))
continue;
- if (cached) {
+ /*
+ * If CE_VALID is on, we assume worktree file and its cache entry
+ * are identical, even if worktree file has been modified, so use
+ * cache version instead
+ */
+ if (cached || (ce->ce_flags & CE_VALID)) {
if (ce_stage(ce))
continue;
hit |= grep_sha1(opt, ce->sha1, ce->name, 0);
@@ -545,6 +552,10 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
cached = 1;
continue;
}
+ if (!strcmp("--no-ext-grep", arg)) {
+ builtin_grep = 1;
+ continue;
+ }
if (!strcmp("-a", arg) ||
!strcmp("--text", arg)) {
opt.binary = GREP_BINARY_TEXT;
diff --git a/builtin-init-db.c b/builtin-init-db.c
index d30c3fe2ca..ee3911f8ee 100644
--- a/builtin-init-db.c
+++ b/builtin-init-db.c
@@ -29,7 +29,7 @@ static void safe_create_dir(const char *dir, int share)
}
}
else if (share && adjust_shared_perm(dir))
- die("Could not make %s writable by group\n", dir);
+ die("Could not make %s writable by group", dir);
}
static void copy_templates_1(char *path, int baselen,
diff --git a/builtin-log.c b/builtin-log.c
index a0944f70a4..c1e2c6a4c5 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -16,6 +16,7 @@
#include "patch-ids.h"
#include "run-command.h"
#include "shortlog.h"
+#include "remote.h"
/* Set a default date-time format for git log ("log.date" config variable) */
static const char *default_date_mode = NULL;
@@ -28,7 +29,6 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
struct rev_info *rev)
{
int i;
- int decorate = 0;
rev->abbrev = DEFAULT_ABBREV;
rev->commit_format = CMIT_FMT_DEFAULT;
@@ -38,6 +38,7 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
DIFF_OPT_SET(&rev->diffopt, RECURSIVE);
rev->show_root_diff = default_show_root;
rev->subject_prefix = fmt_patch_subject_prefix;
+ DIFF_OPT_SET(&rev->diffopt, ALLOW_TEXTCONV);
if (default_date_mode)
rev->date_mode = parse_date_format(default_date_mode);
@@ -55,7 +56,9 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
const char *arg = argv[i];
if (!strcmp(arg, "--decorate")) {
load_ref_decorations();
- decorate = 1;
+ rev->show_decorations = 1;
+ } else if (!strcmp(arg, "--source")) {
+ rev->show_source = 1;
} else
die("unrecognized argument: %s", arg);
}
@@ -247,22 +250,13 @@ int cmd_whatchanged(int argc, const char **argv, const char *prefix)
static void show_tagger(char *buf, int len, struct rev_info *rev)
{
- char *email_end, *p;
- unsigned long date;
- int tz;
+ struct strbuf out = STRBUF_INIT;
- email_end = memchr(buf, '>', len);
- if (!email_end)
- return;
- p = ++email_end;
- while (isspace(*p))
- p++;
- date = strtoul(p, &p, 10);
- while (isspace(*p))
- p++;
- tz = (int)strtol(p, NULL, 10);
- printf("Tagger: %.*s\nDate: %s\n", (int)(email_end - buf), buf,
- show_date(date, tz, rev->date_mode));
+ pp_user_info("Tagger", rev->commit_format, &out, buf, rev->date_mode,
+ git_log_output_encoding ?
+ git_log_output_encoding: git_commit_encoding);
+ printf("%s\n", out.buf);
+ strbuf_release(&out);
}
static int show_object(const unsigned char *sha1, int show_tag_object,
@@ -338,7 +332,13 @@ int cmd_show(int argc, const char **argv, const char *prefix)
t->tag,
diff_get_color_opt(&rev.diffopt, DIFF_RESET));
ret = show_object(o->sha1, 1, &rev);
- objects[i].item = parse_object(t->tagged->sha1);
+ if (ret)
+ break;
+ o = parse_object(t->tagged->sha1);
+ if (!o)
+ ret = error("Could not read object %s",
+ sha1_to_hex(t->tagged->sha1));
+ objects[i].item = o;
i--;
break;
}
@@ -816,7 +816,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
committer = git_committer_info(IDENT_ERROR_ON_NO_NAME);
endpos = strchr(committer, '>');
if (!endpos)
- die("bogus committer info %s\n", committer);
+ die("bogus committer info %s", committer);
add_signoff = xmemdupz(committer, endpos - committer + 1);
}
else if (!strcmp(argv[i], "--attach")) {
@@ -1062,13 +1062,14 @@ static int add_pending_commit(const char *arg, struct rev_info *revs, int flags)
}
static const char cherry_usage[] =
-"git cherry [-v] <upstream> [<head>] [<limit>]";
+"git cherry [-v] [<upstream> [<head> [<limit>]]]";
int cmd_cherry(int argc, const char **argv, const char *prefix)
{
struct rev_info revs;
struct patch_ids ids;
struct commit *commit;
struct commit_list *list = NULL;
+ struct branch *current_branch;
const char *upstream;
const char *head = "HEAD";
const char *limit = NULL;
@@ -1091,7 +1092,17 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
upstream = argv[1];
break;
default:
- usage(cherry_usage);
+ current_branch = branch_get(NULL);
+ if (!current_branch || !current_branch->merge
+ || !current_branch->merge[0]
+ || !current_branch->merge[0]->dst) {
+ fprintf(stderr, "Could not find a tracked"
+ " remote branch, please"
+ " specify <upstream> manually.\n");
+ usage(cherry_usage);
+ }
+
+ upstream = current_branch->merge[0]->dst;
}
init_revisions(&revs, prefix);
diff --git a/builtin-ls-files.c b/builtin-ls-files.c
index 068f424696..f72eb85475 100644
--- a/builtin-ls-files.c
+++ b/builtin-ls-files.c
@@ -91,39 +91,10 @@ static void show_other_files(struct dir_struct *dir)
{
int i;
-
- /*
- * Skip matching and unmerged entries for the paths,
- * since we want just "others".
- *
- * (Matching entries are normally pruned during
- * the directory tree walk, but will show up for
- * gitlinks because we don't necessarily have
- * dir->show_other_directories set to suppress
- * them).
- */
for (i = 0; i < dir->nr; i++) {
struct dir_entry *ent = dir->entries[i];
- int len, pos;
- struct cache_entry *ce;
-
- /*
- * Remove the '/' at the end that directory
- * walking adds for directory entries.
- */
- len = ent->len;
- if (len && ent->name[len-1] == '/')
- len--;
- pos = cache_name_pos(ent->name, len);
- if (0 <= pos)
- continue; /* exact match */
- pos = -pos - 1;
- if (pos < active_nr) {
- ce = active_cache[pos];
- if (ce_namelen(ce) == len &&
- !memcmp(ce->name, ent->name, len))
- continue; /* Yup, this one exists unmerged */
- }
+ if (!cache_name_is_other(ent->name, ent->len))
+ continue;
show_dir_entry(tag_other, ent);
}
}
@@ -256,6 +227,8 @@ static void show_files(struct dir_struct *dir, const char *prefix)
int dtype = ce_to_dtype(ce);
if (excluded(dir, ce->name, &dtype) != dir->show_ignored)
continue;
+ if (ce->ce_flags & CE_UPDATE)
+ continue;
err = lstat(ce->name, &st);
if (show_deleted && err)
show_ce_entry(tag_removed, ce);
@@ -358,7 +331,7 @@ void overlay_tree_on_cache(const char *tree_name, const char *prefix)
if (prefix) {
static const char *(matchbuf[2]);
matchbuf[0] = prefix;
- matchbuf [1] = NULL;
+ matchbuf[1] = NULL;
match = matchbuf;
} else
match = NULL;
diff --git a/builtin-ls-remote.c b/builtin-ls-remote.c
index c21b841e7c..78a88f7476 100644
--- a/builtin-ls-remote.c
+++ b/builtin-ls-remote.c
@@ -4,7 +4,7 @@
#include "remote.h"
static const char ls_remote_usage[] =
-"git ls-remote [--upload-pack=<git-upload-pack>] [<host>:]<directory>";
+"git ls-remote [--heads] [--tags] [-u <exec> | --upload-pack <exec>] <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 cb61717685..5b63e6eada 100644
--- a/builtin-ls-tree.c
+++ b/builtin-ls-tree.c
@@ -23,7 +23,7 @@ static int chomp_prefix;
static const char *ls_tree_prefix;
static const char ls_tree_usage[] =
- "git ls-tree [-d] [-r] [-t] [-l] [-z] [--name-only] [--name-status] [--full-name] [--abbrev[=<n>]] <tree-ish> [path...]";
+ "git ls-tree [-d] [-r] [-t] [-l] [-z] [--name-only] [--name-status] [--full-name] [--full-tree] [--abbrev[=<n>]] <tree-ish> [path...]";
static int show_recursive(const char *base, int baselen, const char *pathname)
{
@@ -156,6 +156,11 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
chomp_prefix = 0;
break;
}
+ if (!strcmp(argv[1]+2, "full-tree")) {
+ ls_tree_prefix = prefix = NULL;
+ chomp_prefix = 0;
+ break;
+ }
if (!prefixcmp(argv[1]+2, "abbrev=")) {
abbrev = strtoul(argv[1]+9, NULL, 10);
if (abbrev && abbrev < MINIMUM_ABBREV)
diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c
index e890f7a6d1..f7c8c08b32 100644
--- a/builtin-mailinfo.c
+++ b/builtin-mailinfo.c
@@ -494,7 +494,7 @@ static void convert_to_utf8(struct strbuf *line, const char *charset)
return;
out = reencode_string(line->buf, metainfo_charset, charset);
if (!out)
- die("cannot convert from %s to %s\n",
+ die("cannot convert from %s to %s",
charset, metainfo_charset);
strbuf_attach(line, out, strlen(out), strlen(out));
}
diff --git a/builtin-merge-file.c b/builtin-merge-file.c
index 9d4e874809..96edb97a83 100644
--- a/builtin-merge-file.c
+++ b/builtin-merge-file.c
@@ -51,8 +51,11 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
argc = parse_options(argc, argv, options, merge_file_usage, 0);
if (argc != 3)
usage_with_options(merge_file_usage, options);
- if (quiet)
- freopen("/dev/null", "w", stderr);
+ if (quiet) {
+ if (!freopen("/dev/null", "w", stderr))
+ return error("failed to redirect stderr to /dev/null: "
+ "%s\n", strerror(errno));
+ }
for (i = 0; i < 3; i++) {
if (!names[i])
diff --git a/builtin-merge-recursive.c b/builtin-merge-recursive.c
index 6b534c1a66..703045bfc8 100644
--- a/builtin-merge-recursive.c
+++ b/builtin-merge-recursive.c
@@ -33,7 +33,7 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix)
}
if (argc < 4)
- die("Usage: %s <base>... -- <head> <remote> ...\n", argv[0]);
+ die("Usage: %s <base>... -- <head> <remote> ...", argv[0]);
for (i = 1; i < argc; ++i) {
if (!strcmp(argv[i], "--"))
diff --git a/builtin-merge.c b/builtin-merge.c
index 5e2b7f12c3..cf869751b4 100644
--- a/builtin-merge.c
+++ b/builtin-merge.c
@@ -50,6 +50,7 @@ static unsigned char head[20], stash[20];
static struct strategy **use_strategies;
static size_t use_strategies_nr, use_strategies_alloc;
static const char *branch;
+static int verbosity;
static struct strategy all_strategy[] = {
{ "recursive", DEFAULT_TWOHEAD | NO_TRIVIAL },
@@ -171,6 +172,7 @@ static struct option builtin_merge_options[] = {
OPT_CALLBACK('m', "message", &merge_msg, "message",
"message to be used for the merge commit (if any)",
option_parse_message),
+ OPT__VERBOSITY(&verbosity),
OPT_END()
};
@@ -179,6 +181,7 @@ static void drop_save(void)
{
unlink(git_path("MERGE_HEAD"));
unlink(git_path("MERGE_MSG"));
+ unlink(git_path("MERGE_MODE"));
}
static void save_state(void)
@@ -249,7 +252,8 @@ static void restore_state(void)
/* This is called when no merge was necessary. */
static void finish_up_to_date(const char *msg)
{
- printf("%s%s\n", squash ? " (nothing to squash)" : "", msg);
+ if (verbosity >= 0)
+ printf("%s%s\n", squash ? " (nothing to squash)" : "", msg);
drop_save();
}
@@ -289,8 +293,10 @@ static void squash_message(void)
pretty_print_commit(rev.commit_format, commit, &out, rev.abbrev,
NULL, NULL, rev.date_mode, 0);
}
- write(fd, out.buf, out.len);
- close(fd);
+ if (write(fd, out.buf, out.len) < 0)
+ die("Writing SQUASH_MSG: %s", strerror(errno));
+ if (close(fd))
+ die("Finishing SQUASH_MSG: %s", strerror(errno));
strbuf_release(&out);
}
@@ -330,14 +336,15 @@ static void finish(const unsigned char *new_head, const char *msg)
if (!msg)
strbuf_addstr(&reflog_message, getenv("GIT_REFLOG_ACTION"));
else {
- printf("%s\n", msg);
+ if (verbosity >= 0)
+ printf("%s\n", msg);
strbuf_addf(&reflog_message, "%s: %s",
getenv("GIT_REFLOG_ACTION"), msg);
}
if (squash) {
squash_message();
} else {
- if (!merge_msg.len)
+ if (verbosity >= 0 && !merge_msg.len)
printf("No merge message -- not updating HEAD\n");
else {
const char *argv_gc_auto[] = { "gc", "--auto", NULL };
@@ -871,6 +878,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
argc = parse_options(argc, argv, builtin_merge_options,
builtin_merge_usage, 0);
+ if (verbosity < 0)
+ show_diffstat = 0;
if (squash) {
if (!allow_fast_forward)
@@ -1012,10 +1021,11 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
strcpy(hex, find_unique_abbrev(head, DEFAULT_ABBREV));
- printf("Updating %s..%s\n",
- hex,
- find_unique_abbrev(remoteheads->item->object.sha1,
- DEFAULT_ABBREV));
+ if (verbosity >= 0)
+ printf("Updating %s..%s\n",
+ hex,
+ find_unique_abbrev(remoteheads->item->object.sha1,
+ DEFAULT_ABBREV));
strbuf_addstr(&msg, "Fast forward");
if (have_message)
strbuf_addstr(&msg,
@@ -1210,6 +1220,15 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
merge_msg.len)
die("Could not write to %s", git_path("MERGE_MSG"));
close(fd);
+ fd = open(git_path("MERGE_MODE"), O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if (fd < 0)
+ die("Could open %s for writing", git_path("MERGE_MODE"));
+ strbuf_reset(&buf);
+ if (!allow_fast_forward)
+ strbuf_addf(&buf, "no-ff");
+ if (write_in_full(fd, buf.buf, buf.len) != buf.len)
+ die("Could not write to %s", git_path("MERGE_MODE"));
+ close(fd);
}
if (merge_was_ok) {
diff --git a/builtin-mv.c b/builtin-mv.c
index 4f65b5ae9b..bce9959293 100644
--- a/builtin-mv.c
+++ b/builtin-mv.c
@@ -192,6 +192,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
memmove(destination + i,
destination + i + 1,
(argc - i) * sizeof(char *));
+ i--;
}
} else
die ("%s, source=%s, destination=%s",
diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
index 59c30d1caa..e8515348be 100644
--- a/builtin-pack-objects.c
+++ b/builtin-pack-objects.c
@@ -71,13 +71,14 @@ static int reuse_delta = 1, reuse_object = 1;
static int keep_unreachable, unpack_unreachable, include_tag;
static int local;
static int incremental;
+static int ignore_packed_keep;
static int allow_ofs_delta;
static const char *base_name;
static int progress = 1;
static int window = 10;
static uint32_t pack_size_limit, pack_size_limit_cfg;
static int depth = 50;
-static int delta_search_threads = 1;
+static int delta_search_threads;
static int pack_to_stdout;
static int num_preferred_base;
static struct progress *progress_state;
@@ -245,8 +246,16 @@ static unsigned long write_object(struct sha1file *f,
type = entry->type;
/* write limit if limited packsize and not first object */
- limit = pack_size_limit && nr_written ?
- pack_size_limit - write_offset : 0;
+ if (!pack_size_limit || !nr_written)
+ limit = 0;
+ else if (pack_size_limit <= write_offset)
+ /*
+ * the earlier object did not fit the limit; avoid
+ * mistaking this with unlimited (i.e. limit = 0).
+ */
+ limit = 1;
+ else
+ limit = pack_size_limit - write_offset;
if (!entry->delta)
usable_delta = 0; /* no delta */
@@ -277,6 +286,7 @@ static unsigned long write_object(struct sha1file *f,
*/
if (!to_reuse) {
+ no_reuse:
if (!usable_delta) {
buf = read_sha1_file(entry->idx.sha1, &type, &size);
if (!buf)
@@ -358,46 +368,60 @@ static unsigned long write_object(struct sha1file *f,
struct revindex_entry *revidx;
off_t offset;
- if (entry->delta) {
+ if (entry->delta)
type = (allow_ofs_delta && entry->delta->idx.offset) ?
OBJ_OFS_DELTA : OBJ_REF_DELTA;
- reused_delta++;
- }
hdrlen = encode_header(type, entry->size, header);
+
offset = entry->in_pack_offset;
revidx = find_pack_revindex(p, offset);
datalen = revidx[1].offset - offset;
if (!pack_to_stdout && p->index_version > 1 &&
- check_pack_crc(p, &w_curs, offset, datalen, revidx->nr))
- die("bad packed object CRC for %s", sha1_to_hex(entry->idx.sha1));
+ check_pack_crc(p, &w_curs, offset, datalen, revidx->nr)) {
+ error("bad packed object CRC for %s", sha1_to_hex(entry->idx.sha1));
+ unuse_pack(&w_curs);
+ goto no_reuse;
+ }
+
offset += entry->in_pack_header_size;
datalen -= entry->in_pack_header_size;
+ if (!pack_to_stdout && p->index_version == 1 &&
+ check_pack_inflate(p, &w_curs, offset, datalen, entry->size)) {
+ error("corrupt packed object for %s", sha1_to_hex(entry->idx.sha1));
+ unuse_pack(&w_curs);
+ goto no_reuse;
+ }
+
if (type == OBJ_OFS_DELTA) {
off_t ofs = entry->idx.offset - entry->delta->idx.offset;
unsigned pos = sizeof(dheader) - 1;
dheader[pos] = ofs & 127;
while (ofs >>= 7)
dheader[--pos] = 128 | (--ofs & 127);
- if (limit && hdrlen + sizeof(dheader) - pos + datalen + 20 >= limit)
+ if (limit && hdrlen + sizeof(dheader) - pos + datalen + 20 >= limit) {
+ unuse_pack(&w_curs);
return 0;
+ }
sha1write(f, header, hdrlen);
sha1write(f, dheader + pos, sizeof(dheader) - pos);
hdrlen += sizeof(dheader) - pos;
+ reused_delta++;
} else if (type == OBJ_REF_DELTA) {
- if (limit && hdrlen + 20 + datalen + 20 >= limit)
+ if (limit && hdrlen + 20 + datalen + 20 >= limit) {
+ unuse_pack(&w_curs);
return 0;
+ }
sha1write(f, header, hdrlen);
sha1write(f, entry->delta->idx.sha1, 20);
hdrlen += 20;
+ reused_delta++;
} else {
- if (limit && hdrlen + datalen + 20 >= limit)
+ if (limit && hdrlen + datalen + 20 >= limit) {
+ unuse_pack(&w_curs);
return 0;
+ }
sha1write(f, header, hdrlen);
}
-
- if (!pack_to_stdout && p->index_version == 1 &&
- check_pack_inflate(p, &w_curs, offset, datalen, entry->size))
- die("corrupt packed object for %s", sha1_to_hex(entry->idx.sha1));
copy_pack_data(f, p, &w_curs, offset, datalen);
unuse_pack(&w_curs);
reused++;
@@ -511,6 +535,7 @@ static void write_pack_file(void)
snprintf(tmpname, sizeof(tmpname), "%s-%s.pack",
base_name, sha1_to_hex(sha1));
+ free_pack_by_name(tmpname);
if (adjust_perm(pack_tmp_name, mode))
die("unable to make temporary pack file readable: %s",
strerror(errno));
@@ -690,6 +715,9 @@ static int add_object_entry(const unsigned char *sha1, enum object_type type,
return 0;
}
+ if (!exclude && local && has_loose_object_nonlocal(sha1))
+ return 0;
+
for (p = packed_git; p; p = p->next) {
off_t offset = find_pack_entry_one(sha1, p);
if (offset) {
@@ -703,6 +731,8 @@ static int add_object_entry(const unsigned char *sha1, enum object_type type,
return 0;
if (local && !p->pack_local)
return 0;
+ if (ignore_packed_keep && p->pack_local && p->pack_keep)
+ return 0;
}
}
@@ -1002,9 +1032,11 @@ static void check_object(struct object_entry *entry)
* We want in_pack_type even if we do not reuse delta
* since non-delta representations could still be reused.
*/
- used = unpack_object_header_gently(buf, avail,
+ used = unpack_object_header_buffer(buf, avail,
&entry->in_pack_type,
&entry->size);
+ if (used == 0)
+ goto give_up;
/*
* Determine if this is a delta and if so whether we can
@@ -1016,6 +1048,8 @@ static void check_object(struct object_entry *entry)
/* Not a delta hence we've already got all we need. */
entry->type = entry->in_pack_type;
entry->in_pack_header_size = used;
+ if (entry->type < OBJ_COMMIT || entry->type > OBJ_BLOB)
+ goto give_up;
unuse_pack(&w_curs);
return;
case OBJ_REF_DELTA:
@@ -1032,19 +1066,25 @@ static void check_object(struct object_entry *entry)
ofs = c & 127;
while (c & 128) {
ofs += 1;
- if (!ofs || MSB(ofs, 7))
- die("delta base offset overflow in pack for %s",
- sha1_to_hex(entry->idx.sha1));
+ if (!ofs || MSB(ofs, 7)) {
+ error("delta base offset overflow in pack for %s",
+ sha1_to_hex(entry->idx.sha1));
+ goto give_up;
+ }
c = buf[used_0++];
ofs = (ofs << 7) + (c & 127);
}
- if (ofs >= entry->in_pack_offset)
- die("delta base offset out of bound for %s",
- sha1_to_hex(entry->idx.sha1));
ofs = entry->in_pack_offset - ofs;
+ if (ofs <= 0 || ofs >= entry->in_pack_offset) {
+ error("delta base offset out of bound for %s",
+ sha1_to_hex(entry->idx.sha1));
+ goto give_up;
+ }
if (reuse_delta && !entry->preferred_base) {
struct revindex_entry *revidx;
revidx = find_pack_revindex(p, ofs);
+ if (!revidx)
+ goto give_up;
base_ref = nth_packed_object_sha1(p, revidx->nr);
}
entry->in_pack_header_size = used + used_0;
@@ -1064,6 +1104,7 @@ static void check_object(struct object_entry *entry)
*/
entry->type = entry->in_pack_type;
entry->delta = base_entry;
+ entry->delta_size = entry->size;
entry->delta_sibling = base_entry->delta_child;
base_entry->delta_child = entry;
unuse_pack(&w_curs);
@@ -1078,6 +1119,8 @@ static void check_object(struct object_entry *entry)
*/
entry->size = get_size_from_delta(p, &w_curs,
entry->in_pack_offset + entry->in_pack_header_size);
+ if (entry->size == 0)
+ goto give_up;
unuse_pack(&w_curs);
return;
}
@@ -1087,6 +1130,7 @@ static void check_object(struct object_entry *entry)
* with sha1_object_info() to find about the object type
* at this point...
*/
+ give_up:
unuse_pack(&w_curs);
}
@@ -1375,7 +1419,7 @@ static void find_deltas(struct object_entry **list, unsigned *list_size,
array = xcalloc(window, sizeof(struct unpacked));
for (;;) {
- struct object_entry *entry = *list++;
+ struct object_entry *entry;
struct unpacked *n = array + idx;
int j, max_depth, best_base = -1;
@@ -1384,6 +1428,7 @@ static void find_deltas(struct object_entry **list, unsigned *list_size,
progress_unlock();
break;
}
+ entry = *list++;
(*list_size)--;
if (!entry->preferred_base) {
(*processed)++;
@@ -1567,11 +1612,18 @@ static void ll_find_deltas(struct object_entry **list, unsigned list_size,
find_deltas(list, &list_size, window, depth, processed);
return;
}
+ if (progress > pack_to_stdout)
+ fprintf(stderr, "Delta compression using %d threads.\n",
+ delta_search_threads);
/* Partition the work amongst work threads. */
for (i = 0; i < delta_search_threads; i++) {
unsigned sub_size = list_size / (delta_search_threads - i);
+ /* don't use too small segments or no deltas will be found */
+ if (sub_size < 2*window && i+1 < delta_search_threads)
+ sub_size = 0;
+
p[i].window = window;
p[i].depth = depth;
p[i].processed = processed;
@@ -1697,6 +1749,16 @@ static void prepare_pack(int window, int depth)
get_object_details();
+ /*
+ * If we're locally repacking then we need to be doubly careful
+ * from now on in order to make sure no stealth corruption gets
+ * propagated to the new pack. Clients receiving streamed packs
+ * should validate everything they get anyway so no need to incur
+ * the additional cost here in that case.
+ */
+ if (!pack_to_stdout)
+ do_check_packed_object_crc = 1;
+
if (!nr_objects || !window || !depth)
return;
@@ -2047,6 +2109,10 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
incremental = 1;
continue;
}
+ if (!strcmp("--honor-pack-keep", arg)) {
+ ignore_packed_keep = 1;
+ continue;
+ }
if (!prefixcmp(arg, "--compression=")) {
char *end;
int level = strtoul(arg+14, &end, 0);
diff --git a/builtin-read-tree.c b/builtin-read-tree.c
index 0706c95818..38fef34d3f 100644
--- a/builtin-read-tree.c
+++ b/builtin-read-tree.c
@@ -206,7 +206,7 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
break;
case 2:
opts.fn = twoway_merge;
- opts.initial_checkout = !active_nr;
+ opts.initial_checkout = is_cache_unborn();
break;
case 3:
default:
diff --git a/builtin-receive-pack.c b/builtin-receive-pack.c
index 45e3cd90fd..db67c3162c 100644
--- a/builtin-receive-pack.c
+++ b/builtin-receive-pack.c
@@ -11,7 +11,15 @@
static const char receive_pack_usage[] = "git-receive-pack <git-dir>";
+enum deny_action {
+ DENY_IGNORE,
+ DENY_WARN,
+ DENY_REFUSE,
+};
+
+static int deny_deletes = 0;
static int deny_non_fast_forwards = 0;
+static enum deny_action deny_current_branch = DENY_WARN;
static int receive_fsck_objects;
static int receive_unpack_limit = -1;
static int transfer_unpack_limit = -1;
@@ -21,8 +29,28 @@ static int report_status;
static char capabilities[] = " report-status delete-refs ";
static int capabilities_sent;
+static enum deny_action parse_deny_action(const char *var, const char *value)
+{
+ if (value) {
+ if (!strcasecmp(value, "ignore"))
+ return DENY_IGNORE;
+ if (!strcasecmp(value, "warn"))
+ return DENY_WARN;
+ if (!strcasecmp(value, "refuse"))
+ return DENY_REFUSE;
+ }
+ if (git_config_bool(var, value))
+ return DENY_REFUSE;
+ return DENY_IGNORE;
+}
+
static int receive_pack_config(const char *var, const char *value, void *cb)
{
+ if (strcmp(var, "receive.denydeletes") == 0) {
+ deny_deletes = git_config_bool(var, value);
+ return 0;
+ }
+
if (strcmp(var, "receive.denynonfastforwards") == 0) {
deny_non_fast_forwards = git_config_bool(var, value);
return 0;
@@ -43,6 +71,11 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
return 0;
}
+ if (!strcmp(var, "receive.denycurrentbranch")) {
+ deny_current_branch = parse_deny_action(var, value);
+ return 0;
+ }
+
return git_default_config(var, value, cb);
}
@@ -167,6 +200,20 @@ static int run_update_hook(struct command *cmd)
return hook_status(run_command(&proc), update_hook);
}
+static int is_ref_checked_out(const char *ref)
+{
+ unsigned char sha1[20];
+ const char *head;
+
+ if (is_bare_repository())
+ return 0;
+
+ head = resolve_ref("HEAD", sha1, 0, NULL);
+ if (!head)
+ return 0;
+ return !strcmp(head, ref);
+}
+
static const char *update(struct command *cmd)
{
const char *name = cmd->ref_name;
@@ -180,11 +227,35 @@ static const char *update(struct command *cmd)
return "funny refname";
}
+ switch (deny_current_branch) {
+ case DENY_IGNORE:
+ break;
+ case DENY_WARN:
+ if (!is_ref_checked_out(name))
+ break;
+ warning("updating the currently checked out branch; this may"
+ " cause confusion,\n"
+ "as the index and working tree do not reflect changes"
+ " that are now in HEAD.");
+ break;
+ case DENY_REFUSE:
+ if (!is_ref_checked_out(name))
+ break;
+ error("refusing to update checked out branch: %s", name);
+ return "branch is currently checked out";
+ }
+
if (!is_null_sha1(new_sha1) && !has_sha1_file(new_sha1)) {
error("unpack should have generated %s, "
"but I can't find it!", sha1_to_hex(new_sha1));
return "bad pack";
}
+ if (deny_deletes && is_null_sha1(new_sha1) &&
+ !is_null_sha1(old_sha1) &&
+ !prefixcmp(name, "refs/heads/")) {
+ error("denying ref deletion for %s", name);
+ return "deletion prohibited";
+ }
if (deny_non_fast_forwards && !is_null_sha1(new_sha1) &&
!is_null_sha1(old_sha1) &&
!prefixcmp(name, "refs/heads/")) {
@@ -224,7 +295,7 @@ static const char *update(struct command *cmd)
warning ("Allowing deletion of corrupt ref.");
old_sha1 = NULL;
}
- if (delete_ref(name, old_sha1)) {
+ if (delete_ref(name, old_sha1, 0)) {
error("failed to delete %s", name);
return "failed to delete";
}
@@ -466,12 +537,17 @@ static int delete_only(struct command *cmd)
static int add_refs_from_alternate(struct alternate_object_database *e, void *unused)
{
- char *other = xstrdup(make_absolute_path(e->base));
- size_t len = strlen(other);
+ char *other;
+ size_t len;
struct remote *remote;
struct transport *transport;
const struct ref *extra;
+ e->name[-1] = '\0';
+ other = xstrdup(make_absolute_path(e->base));
+ e->name[-1] = '/';
+ len = strlen(other);
+
while (other[len-1] == '/')
other[--len] = '\0';
if (len < 8 || memcmp(other + len - 8, "/objects", 8))
diff --git a/builtin-reflog.c b/builtin-reflog.c
index 6b3667ef0e..d95f515f2e 100644
--- a/builtin-reflog.c
+++ b/builtin-reflog.c
@@ -277,11 +277,11 @@ static int expire_reflog(const char *ref, const unsigned char *sha1, int unused,
lock = lock_any_ref_for_update(ref, sha1, 0);
if (!lock)
return error("cannot lock ref '%s'", ref);
- log_file = xstrdup(git_path("logs/%s", ref));
+ log_file = git_pathdup("logs/%s", ref);
if (!file_exists(log_file))
goto finish;
if (!cmd->dry_run) {
- newlog_path = xstrdup(git_path("logs/%s.lock", ref));
+ newlog_path = git_pathdup("logs/%s.lock", ref);
cb.newlog = fopen(newlog_path, "w");
}
diff --git a/builtin-remote.c b/builtin-remote.c
index 6b3325dfa9..abc8dd8389 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -8,12 +8,13 @@
#include "refs.h"
static const char * const builtin_remote_usage[] = {
- "git remote",
- "git remote add <name> <url>",
+ "git remote [-v | --verbose]",
+ "git remote add [-t <branch>] [-m <master>] [-f] [--mirror] <name> <url>",
+ "git remote rename <old> <new>",
"git remote rm <name>",
- "git remote show <name>",
- "git remote prune <name>",
- "git remote update [group]",
+ "git remote show [-n] <name>",
+ "git remote prune [-n | --dry-run] <name>",
+ "git remote [-v | --verbose] update [group]",
NULL
};
@@ -41,7 +42,11 @@ static int opt_parse_track(const struct option *opt, const char *arg, int not)
static int fetch_remote(const char *name)
{
- const char *argv[] = { "fetch", name, NULL };
+ const char *argv[] = { "fetch", name, NULL, NULL };
+ if (verbose) {
+ argv[1] = "-v";
+ argv[2] = name;
+ }
printf("Updating %s\n", name);
if (run_command_v_opt(argv, RUN_GIT_CMD))
return error("Could not fetch %s", name);
@@ -320,7 +325,7 @@ static int add_branch_for_removal(const char *refname,
/* make sure that symrefs are deleted */
if (flags & REF_ISSYMREF)
- return unlink(git_path(refname));
+ return unlink(git_path("%s", refname));
item = string_list_append(refname, branches->branches);
item->util = xmalloc(20);
@@ -329,6 +334,191 @@ static int add_branch_for_removal(const char *refname,
return 0;
}
+struct rename_info {
+ const char *old;
+ const char *new;
+ struct string_list *remote_branches;
+};
+
+static int read_remote_branches(const char *refname,
+ const unsigned char *sha1, int flags, void *cb_data)
+{
+ struct rename_info *rename = cb_data;
+ struct strbuf buf = STRBUF_INIT;
+ struct string_list_item *item;
+ int flag;
+ unsigned char orig_sha1[20];
+ const char *symref;
+
+ strbuf_addf(&buf, "refs/remotes/%s", rename->old);
+ if(!prefixcmp(refname, buf.buf)) {
+ item = string_list_append(xstrdup(refname), rename->remote_branches);
+ symref = resolve_ref(refname, orig_sha1, 1, &flag);
+ if (flag & REF_ISSYMREF)
+ item->util = xstrdup(symref);
+ else
+ item->util = NULL;
+ }
+
+ return 0;
+}
+
+static int migrate_file(struct remote *remote)
+{
+ struct strbuf buf = STRBUF_INIT;
+ int i;
+ char *path = NULL;
+
+ strbuf_addf(&buf, "remote.%s.url", remote->name);
+ for (i = 0; i < remote->url_nr; i++)
+ if (git_config_set_multivar(buf.buf, remote->url[i], "^$", 0))
+ return error("Could not append '%s' to '%s'",
+ remote->url[i], buf.buf);
+ strbuf_reset(&buf);
+ strbuf_addf(&buf, "remote.%s.push", remote->name);
+ for (i = 0; i < remote->push_refspec_nr; i++)
+ if (git_config_set_multivar(buf.buf, remote->push_refspec[i], "^$", 0))
+ return error("Could not append '%s' to '%s'",
+ remote->push_refspec[i], buf.buf);
+ strbuf_reset(&buf);
+ strbuf_addf(&buf, "remote.%s.fetch", remote->name);
+ for (i = 0; i < remote->fetch_refspec_nr; i++)
+ if (git_config_set_multivar(buf.buf, remote->fetch_refspec[i], "^$", 0))
+ return error("Could not append '%s' to '%s'",
+ remote->fetch_refspec[i], buf.buf);
+ if (remote->origin == REMOTE_REMOTES)
+ path = git_path("remotes/%s", remote->name);
+ else if (remote->origin == REMOTE_BRANCHES)
+ path = git_path("branches/%s", remote->name);
+ if (path && unlink(path))
+ warning("failed to remove '%s'", path);
+ return 0;
+}
+
+static int mv(int argc, const char **argv)
+{
+ struct option options[] = {
+ OPT_END()
+ };
+ struct remote *oldremote, *newremote;
+ struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT, buf3 = STRBUF_INIT;
+ struct string_list remote_branches = { NULL, 0, 0, 0 };
+ struct rename_info rename;
+ int i;
+
+ if (argc != 3)
+ usage_with_options(builtin_remote_usage, options);
+
+ rename.old = argv[1];
+ rename.new = argv[2];
+ rename.remote_branches = &remote_branches;
+
+ oldremote = remote_get(rename.old);
+ if (!oldremote)
+ die("No such remote: %s", rename.old);
+
+ if (!strcmp(rename.old, rename.new) && oldremote->origin != REMOTE_CONFIG)
+ return migrate_file(oldremote);
+
+ newremote = remote_get(rename.new);
+ if (newremote && (newremote->url_nr > 1 || newremote->fetch_refspec_nr))
+ die("remote %s already exists.", rename.new);
+
+ strbuf_addf(&buf, "refs/heads/test:refs/remotes/%s/test", rename.new);
+ if (!valid_fetch_refspec(buf.buf))
+ die("'%s' is not a valid remote name", rename.new);
+
+ strbuf_reset(&buf);
+ strbuf_addf(&buf, "remote.%s", rename.old);
+ strbuf_addf(&buf2, "remote.%s", rename.new);
+ if (git_config_rename_section(buf.buf, buf2.buf) < 1)
+ return error("Could not rename config section '%s' to '%s'",
+ buf.buf, buf2.buf);
+
+ strbuf_reset(&buf);
+ strbuf_addf(&buf, "remote.%s.fetch", rename.new);
+ if (git_config_set_multivar(buf.buf, NULL, NULL, 1))
+ return error("Could not remove config section '%s'", buf.buf);
+ for (i = 0; i < oldremote->fetch_refspec_nr; i++) {
+ char *ptr;
+
+ strbuf_reset(&buf2);
+ strbuf_addstr(&buf2, oldremote->fetch_refspec[i]);
+ ptr = strstr(buf2.buf, rename.old);
+ if (ptr)
+ strbuf_splice(&buf2, ptr-buf2.buf, strlen(rename.old),
+ rename.new, strlen(rename.new));
+ if (git_config_set_multivar(buf.buf, buf2.buf, "^$", 0))
+ return error("Could not append '%s'", buf.buf);
+ }
+
+ read_branches();
+ for (i = 0; i < branch_list.nr; i++) {
+ struct string_list_item *item = branch_list.items + i;
+ struct branch_info *info = item->util;
+ if (info->remote && !strcmp(info->remote, rename.old)) {
+ strbuf_reset(&buf);
+ strbuf_addf(&buf, "branch.%s.remote", item->string);
+ if (git_config_set(buf.buf, rename.new)) {
+ return error("Could not set '%s'", buf.buf);
+ }
+ }
+ }
+
+ /*
+ * First remove symrefs, then rename the rest, finally create
+ * the new symrefs.
+ */
+ for_each_ref(read_remote_branches, &rename);
+ for (i = 0; i < remote_branches.nr; i++) {
+ struct string_list_item *item = remote_branches.items + i;
+ int flag = 0;
+ unsigned char sha1[20];
+ const char *symref;
+
+ symref = resolve_ref(item->string, sha1, 1, &flag);
+ if (!(flag & REF_ISSYMREF))
+ continue;
+ if (delete_ref(item->string, NULL, REF_NODEREF))
+ die("deleting '%s' failed", item->string);
+ }
+ for (i = 0; i < remote_branches.nr; i++) {
+ struct string_list_item *item = remote_branches.items + i;
+
+ if (item->util)
+ continue;
+ strbuf_reset(&buf);
+ strbuf_addstr(&buf, item->string);
+ strbuf_splice(&buf, strlen("refs/remotes/"), strlen(rename.old),
+ rename.new, strlen(rename.new));
+ strbuf_reset(&buf2);
+ strbuf_addf(&buf2, "remote: renamed %s to %s",
+ item->string, buf.buf);
+ if (rename_ref(item->string, buf.buf, buf2.buf))
+ die("renaming '%s' failed", item->string);
+ }
+ for (i = 0; i < remote_branches.nr; i++) {
+ struct string_list_item *item = remote_branches.items + i;
+
+ if (!item->util)
+ continue;
+ strbuf_reset(&buf);
+ strbuf_addstr(&buf, item->string);
+ strbuf_splice(&buf, strlen("refs/remotes/"), strlen(rename.old),
+ rename.new, strlen(rename.new));
+ strbuf_reset(&buf2);
+ strbuf_addstr(&buf2, item->util);
+ strbuf_splice(&buf2, strlen("refs/remotes/"), strlen(rename.old),
+ rename.new, strlen(rename.new));
+ strbuf_reset(&buf3);
+ strbuf_addf(&buf3, "remote: renamed %s to %s",
+ item->string, buf.buf);
+ if (create_symref(buf.buf, buf2.buf, buf3.buf))
+ die("creating '%s' failed", buf.buf);
+ }
+ return 0;
+}
+
static int remove_branches(struct string_list *branches)
{
int i, result = 0;
@@ -337,7 +527,7 @@ static int remove_branches(struct string_list *branches)
const char *refname = item->string;
unsigned char *sha1 = item->util;
- if (delete_ref(refname, sha1))
+ if (delete_ref(refname, sha1, 0))
result |= error("Could not remove branch %s", refname);
}
return result;
@@ -412,10 +602,9 @@ static void show_list(const char *title, struct string_list *list,
return;
printf(title, list->nr > 1 ? "es" : "", extra_arg);
- printf("\n ");
- for (i = 0; i < list->nr; i++)
- printf("%s%s", i ? " " : "", list->items[i].string);
printf("\n");
+ for (i = 0; i < list->nr; i++)
+ printf(" %s\n", list->items[i].string);
}
static int get_remote_ref_states(const char *name,
@@ -511,17 +700,17 @@ static int show(int argc, const char **argv)
show_list(" Tracked remote branch%s", &states.tracked, "");
if (states.remote->push_refspec_nr) {
- printf(" Local branch%s pushed with 'git push'\n ",
+ printf(" Local branch%s pushed with 'git push'\n",
states.remote->push_refspec_nr > 1 ?
"es" : "");
for (i = 0; i < states.remote->push_refspec_nr; i++) {
struct refspec *spec = states.remote->push + i;
- printf(" %s%s%s%s", spec->force ? "+" : "",
+ printf(" %s%s%s%s\n",
+ spec->force ? "+" : "",
abbrev_branch(spec->src),
spec->dst ? ":" : "",
spec->dst ? abbrev_branch(spec->dst) : "");
}
- printf("\n");
}
/* NEEDSWORK: free remote */
@@ -566,7 +755,7 @@ static int prune(int argc, const char **argv)
const char *refname = states.stale.items[i].util;
if (!dry_run)
- result |= delete_ref(refname, NULL);
+ result |= delete_ref(refname, NULL, 0);
printf(" * [%s] %s\n", dry_run ? "would prune" : "pruned",
abbrev_ref(refname, "refs/remotes/"));
@@ -585,7 +774,7 @@ static int get_one_remote_for_update(struct remote *remote, void *priv)
{
struct string_list *list = priv;
if (!remote->skip_default_update)
- string_list_append(xstrdup(remote->name), list);
+ string_list_append(remote->name, list);
return 0;
}
@@ -696,6 +885,8 @@ int cmd_remote(int argc, const char **argv, const char *prefix)
result = show_all();
else if (!strcmp(argv[0], "add"))
result = add(argc, argv);
+ else if (!strcmp(argv[0], "rename"))
+ result = mv(argc, argv);
else if (!strcmp(argv[0], "rm"))
result = rm(argc, argv);
else if (!strcmp(argv[0], "show"))
diff --git a/builtin-rerere.c b/builtin-rerere.c
index dd4573fe8d..d4dec6b715 100644
--- a/builtin-rerere.c
+++ b/builtin-rerere.c
@@ -98,6 +98,7 @@ static int diff_two(const char *file1, const char *label1,
printf("--- a/%s\n+++ b/%s\n", label1, label2);
fflush(stdout);
+ memset(&xpp, 0, sizeof(xpp));
xpp.flags = XDF_NEED_MINIMAL;
memset(&xecfg, 0, sizeof(xecfg));
xecfg.ctxlen = 3;
diff --git a/builtin-reset.c b/builtin-reset.c
index 16e6bb20f1..c0cb915c26 100644
--- a/builtin-reset.c
+++ b/builtin-reset.c
@@ -20,11 +20,14 @@
#include "parse-options.h"
static const char * const git_reset_usage[] = {
- "git reset [--mixed | --soft | --hard] [-q] [<commit>]",
+ "git reset [--mixed | --soft | --hard | --merge] [-q] [<commit>]",
"git reset [--mixed] <commit> [--] <paths>...",
NULL
};
+enum reset_type { MIXED, SOFT, HARD, MERGE, NONE };
+static const char *reset_type_names[] = { "mixed", "soft", "hard", "merge", NULL };
+
static char *args_to_str(const char **argv)
{
char *buf = NULL;
@@ -49,7 +52,7 @@ static inline int is_merge(void)
return !access(git_path("MERGE_HEAD"), F_OK);
}
-static int reset_index_file(const unsigned char *sha1, int is_hard_reset, int quiet)
+static int reset_index_file(const unsigned char *sha1, int reset_type, int quiet)
{
int i = 0;
const char *args[6];
@@ -57,9 +60,17 @@ static int reset_index_file(const unsigned char *sha1, int is_hard_reset, int qu
args[i++] = "read-tree";
if (!quiet)
args[i++] = "-v";
- args[i++] = "--reset";
- if (is_hard_reset)
+ switch (reset_type) {
+ case MERGE:
args[i++] = "-u";
+ args[i++] = "-m";
+ break;
+ case HARD:
+ args[i++] = "-u";
+ /* fallthrough */
+ default:
+ args[i++] = "--reset";
+ }
args[i++] = sha1_to_hex(sha1);
args[i] = NULL;
@@ -169,9 +180,6 @@ static void prepend_reflog_action(const char *action, char *buf, size_t size)
warning("Reflog action message too long: %.*s...", 50, buf);
}
-enum reset_type { MIXED, SOFT, HARD, NONE };
-static const char *reset_type_names[] = { "mixed", "soft", "hard", NULL };
-
int cmd_reset(int argc, const char **argv, const char *prefix)
{
int i = 0, reset_type = NONE, update_ref_status = 0, quiet = 0;
@@ -186,6 +194,8 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
OPT_SET_INT(0, "soft", &reset_type, "reset only HEAD", SOFT),
OPT_SET_INT(0, "hard", &reset_type,
"reset HEAD, index and working tree", HARD),
+ OPT_SET_INT(0, "merge", &reset_type,
+ "reset HEAD, index and working tree", MERGE),
OPT_BOOLEAN('q', NULL, &quiet,
"disable showing new HEAD in hard reset and progress message"),
OPT_END()
@@ -266,7 +276,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
if (is_merge() || read_cache() < 0 || unmerged_cache())
die("Cannot do a soft reset in the middle of a merge.");
}
- else if (reset_index_file(sha1, (reset_type == HARD), quiet))
+ else if (reset_index_file(sha1, reset_type, quiet))
die("Could not reset index file to revision '%s'.", rev);
/* Any resets update HEAD to the head being switched to,
@@ -279,7 +289,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
update_ref(msg, "ORIG_HEAD", orig, old_orig, 0, MSG_ON_ERR);
}
else if (old_orig)
- delete_ref("ORIG_HEAD", old_orig);
+ delete_ref("ORIG_HEAD", old_orig, 0);
prepend_reflog_action("updating HEAD", msg, sizeof(msg));
update_ref_status = update_ref(msg, "HEAD", sha1, orig, 0, MSG_ON_ERR);
diff --git a/builtin-rev-list.c b/builtin-rev-list.c
index 06cdeb7ebe..857742a14f 100644
--- a/builtin-rev-list.c
+++ b/builtin-rev-list.c
@@ -100,7 +100,7 @@ static void show_commit(struct commit *commit)
children = children->next;
}
}
- show_decorations(commit);
+ show_decorations(&revs, commit);
if (revs.commit_format == CMIT_FMT_ONELINE)
putchar(' ');
else
diff --git a/builtin-revert.c b/builtin-revert.c
index 8486539740..d48313c745 100644
--- a/builtin-revert.c
+++ b/builtin-revert.c
@@ -251,7 +251,7 @@ static int revert_or_cherry_pick(int argc, const char **argv)
int i, index_fd, clean;
char *oneline, *reencoded_message = NULL;
const char *message, *encoding;
- const char *defmsg = xstrdup(git_path("MERGE_MSG"));
+ char *defmsg = git_pathdup("MERGE_MSG");
struct merge_options o;
struct tree *result, *next_tree, *base_tree, *head_tree;
static struct lock_file index_lock;
@@ -329,7 +329,8 @@ static int revert_or_cherry_pick(int argc, const char **argv)
* reverse of it if we are revert.
*/
- msg_fd = hold_lock_file_for_update(&msg_file, defmsg, 1);
+ msg_fd = hold_lock_file_for_update(&msg_file, defmsg,
+ LOCK_DIE_ON_ERROR);
encoding = get_encoding(message);
if (!encoding)
@@ -351,6 +352,11 @@ static int revert_or_cherry_pick(int argc, const char **argv)
add_to_msg(oneline_body + 1);
add_to_msg("\"\n\nThis reverts commit ");
add_to_msg(sha1_to_hex(commit->object.sha1));
+
+ if (commit->parents->next) {
+ add_to_msg(", reversing\nchanges made to ");
+ add_to_msg(sha1_to_hex(parent->object.sha1));
+ }
add_to_msg(".\n");
} else {
base = parent;
@@ -431,6 +437,7 @@ static int revert_or_cherry_pick(int argc, const char **argv)
return execv_git_cmd(args);
}
free(reencoded_message);
+ free(defmsg);
return 0;
}
diff --git a/builtin-rm.c b/builtin-rm.c
index e06640cf8d..c11f455858 100644
--- a/builtin-rm.c
+++ b/builtin-rm.c
@@ -31,7 +31,8 @@ static void add_list(const char *name)
static int check_local_mod(unsigned char *head, int index_only)
{
- /* items in list are already sorted in the cache order,
+ /*
+ * Items in list are already sorted in the cache order,
* so we could do this a lot more efficiently by using
* tree_desc based traversal if we wanted to, but I am
* lazy, and who cares if removal of files is a tad
@@ -71,24 +72,55 @@ static int check_local_mod(unsigned char *head, int index_only)
*/
continue;
}
+
+ /*
+ * "rm" of a path that has changes need to be treated
+ * carefully not to allow losing local changes
+ * accidentally. A local change could be (1) file in
+ * work tree is different since the index; and/or (2)
+ * the user staged a content that is different from
+ * the current commit in the index.
+ *
+ * In such a case, you would need to --force the
+ * removal. However, "rm --cached" (remove only from
+ * the index) is safe if the index matches the file in
+ * the work tree or the HEAD commit, as it means that
+ * the content being removed is available elsewhere.
+ */
+
+ /*
+ * Is the index different from the file in the work tree?
+ */
if (ce_match_stat(ce, &st, 0))
local_changes = 1;
+
+ /*
+ * Is the index different from the HEAD commit? By
+ * definition, before the very initial commit,
+ * anything staged in the index is treated by the same
+ * way as changed from the HEAD.
+ */
if (no_head
|| get_tree_entry(head, name, sha1, &mode)
|| ce->ce_mode != create_ce_mode(mode)
|| hashcmp(ce->sha1, sha1))
staged_changes = 1;
- if (local_changes && staged_changes)
- errs = error("'%s' has staged content different "
- "from both the file and the HEAD\n"
- "(use -f to force removal)", name);
+ /*
+ * If the index does not match the file in the work
+ * tree and if it does not match the HEAD commit
+ * either, (1) "git rm" without --cached definitely
+ * will lose information; (2) "git rm --cached" will
+ * lose information unless it is about removing an
+ * "intent to add" entry.
+ */
+ if (local_changes && staged_changes) {
+ if (!index_only || !(ce->ce_flags & CE_INTENT_TO_ADD))
+ errs = error("'%s' has staged content different "
+ "from both the file and the HEAD\n"
+ "(use -f to force removal)", name);
+ }
else if (!index_only) {
- /* It's not dangerous to "git rm --cached" a
- * file if the index matches the file or the
- * HEAD, since it means the deleted content is
- * still available somewhere.
- */
if (staged_changes)
errs = error("'%s' has changes staged in the index\n"
"(use --cached to keep the file, "
diff --git a/builtin-send-pack.c b/builtin-send-pack.c
index 910db92b62..a9fdbf9d45 100644
--- a/builtin-send-pack.c
+++ b/builtin-send-pack.c
@@ -140,7 +140,13 @@ static struct ref *remote_refs, **remote_tail;
static int one_local_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
{
struct ref *ref;
- int len = strlen(refname) + 1;
+ int len;
+
+ /* we already know it starts with refs/ to get here */
+ if (check_ref_format(refname + 5))
+ return 0;
+
+ len = strlen(refname) + 1;
ref = xcalloc(1, sizeof(*ref) + len);
hashcpy(ref->new_sha1, sha1);
memcpy(ref->name, refname, len);
@@ -224,7 +230,7 @@ static void update_tracking_ref(struct remote *remote, struct ref *ref)
{
struct refspec rs;
- if (ref->status != REF_STATUS_OK)
+ if (ref->status != REF_STATUS_OK && ref->status != REF_STATUS_UPTODATE)
return;
rs.src = ref->name;
@@ -234,7 +240,7 @@ static void update_tracking_ref(struct remote *remote, struct ref *ref)
if (args.verbose)
fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst);
if (ref->deletion) {
- delete_ref(rs.dst, NULL);
+ delete_ref(rs.dst, NULL, 0);
} else
update_ref("update by push", rs.dst,
ref->new_sha1, NULL, 0, 0);
@@ -429,24 +435,19 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
*/
new_refs = 0;
for (ref = remote_refs; ref; ref = ref->next) {
- const unsigned char *new_sha1;
-
- if (!ref->peer_ref) {
- if (!args.send_mirror)
- continue;
- new_sha1 = null_sha1;
- }
- else
- new_sha1 = ref->peer_ref->new_sha1;
+ if (ref->peer_ref)
+ hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
+ else if (!args.send_mirror)
+ continue;
- ref->deletion = is_null_sha1(new_sha1);
+ ref->deletion = is_null_sha1(ref->new_sha1);
if (ref->deletion && !allow_deleting_refs) {
ref->status = REF_STATUS_REJECT_NODELETE;
continue;
}
if (!ref->deletion &&
- !hashcmp(ref->old_sha1, new_sha1)) {
+ !hashcmp(ref->old_sha1, ref->new_sha1)) {
ref->status = REF_STATUS_UPTODATE;
continue;
}
@@ -474,14 +475,13 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
!ref->deletion &&
!is_null_sha1(ref->old_sha1) &&
(!has_sha1_file(ref->old_sha1)
- || !ref_newer(new_sha1, ref->old_sha1));
+ || !ref_newer(ref->new_sha1, ref->old_sha1));
if (ref->nonfastforward && !ref->force && !args.force_update) {
ref->status = REF_STATUS_REJECT_NONFASTFORWARD;
continue;
}
- hashcpy(ref->new_sha1, new_sha1);
if (!ref->deletion)
new_refs++;
diff --git a/builtin-shortlog.c b/builtin-shortlog.c
index d03f14fdad..5f9f3f09b1 100644
--- a/builtin-shortlog.c
+++ b/builtin-shortlog.c
@@ -29,6 +29,9 @@ static int compare_by_number(const void *a1, const void *a2)
return -1;
}
+const char *format_subject(struct strbuf *sb, const char *msg,
+ const char *line_separator);
+
static void insert_one_record(struct shortlog *log,
const char *author,
const char *oneline)
@@ -36,11 +39,11 @@ static void insert_one_record(struct shortlog *log,
const char *dot3 = log->common_repo_prefix;
char *buffer, *p;
struct string_list_item *item;
- struct string_list *onelines;
char namebuf[1024];
size_t len;
const char *eol;
const char *boemail, *eoemail;
+ struct strbuf subject = STRBUF_INIT;
boemail = strchr(author, '<');
if (!boemail)
@@ -68,12 +71,9 @@ static void insert_one_record(struct shortlog *log,
snprintf(namebuf + len, room, " %.*s", maillen, boemail);
}
- buffer = xstrdup(namebuf);
- item = string_list_insert(buffer, &log->list);
+ item = string_list_insert(namebuf, &log->list);
if (item->util == NULL)
item->util = xcalloc(1, sizeof(struct string_list));
- else
- free(buffer);
/* Skip any leading whitespace, including any blank lines. */
while (*oneline && isspace(*oneline))
@@ -89,9 +89,8 @@ static void insert_one_record(struct shortlog *log,
while (*oneline && isspace(*oneline) && *oneline != '\n')
oneline++;
len = eol - oneline;
- while (len && isspace(oneline[len-1]))
- len--;
- buffer = xmemdupz(oneline, len);
+ format_subject(&subject, oneline, " ");
+ buffer = strbuf_detach(&subject, NULL);
if (dot3) {
int dot3len = strlen(dot3);
@@ -104,16 +103,7 @@ static void insert_one_record(struct shortlog *log,
}
}
- onelines = item->util;
- if (onelines->nr >= onelines->alloc) {
- onelines->alloc = alloc_nr(onelines->nr);
- onelines->items = xrealloc(onelines->items,
- onelines->alloc
- * sizeof(struct string_list_item));
- }
-
- onelines->items[onelines->nr].util = NULL;
- onelines->items[onelines->nr++].string = buffer;
+ string_list_append(buffer, item->util);
}
static void read_from_stdin(struct shortlog *log)
@@ -323,7 +313,7 @@ void shortlog_output(struct shortlog *log)
}
onelines->strdup_strings = 1;
- string_list_clear(onelines, 1);
+ string_list_clear(onelines, 0);
free(onelines);
log->list.items[i].util = NULL;
}
diff --git a/builtin-tag.c b/builtin-tag.c
index b13fa34d8c..a398499891 100644
--- a/builtin-tag.c
+++ b/builtin-tag.c
@@ -125,7 +125,7 @@ static int for_each_tag_name(const char **argv, each_tag_name_fn fn)
static int delete_tag(const char *name, const char *ref,
const unsigned char *sha1)
{
- if (delete_ref(ref, sha1))
+ if (delete_ref(ref, sha1, 0))
return 1;
printf("Deleted tag '%s'\n", name);
return 0;
@@ -253,6 +253,15 @@ static void write_tag_body(int fd, const unsigned char *sha1)
free(buf);
}
+static int build_tag_object(struct strbuf *buf, int sign, unsigned char *result)
+{
+ if (sign && do_sign(buf) < 0)
+ return error("unable to sign the tag");
+ if (write_sha1_file(buf->buf, buf->len, tag_type, result) < 0)
+ return error("unable to write tag file");
+ return 0;
+}
+
static void create_tag(const unsigned char *object, const char *tag,
struct strbuf *buf, int message, int sign,
unsigned char *prev, unsigned char *result)
@@ -260,6 +269,7 @@ static void create_tag(const unsigned char *object, const char *tag,
enum object_type type;
char header_buf[1024];
int header_len;
+ char *path = NULL;
type = sha1_object_info(object, NULL);
if (type <= OBJ_NONE)
@@ -279,11 +289,10 @@ static void create_tag(const unsigned char *object, const char *tag,
die("tag header too big.");
if (!message) {
- char *path;
int fd;
/* write the template message before editing: */
- path = xstrdup(git_path("TAG_EDITMSG"));
+ path = git_pathdup("TAG_EDITMSG");
fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
if (fd < 0)
die("could not create file '%s': %s",
@@ -300,9 +309,6 @@ static void create_tag(const unsigned char *object, const char *tag,
"Please supply the message using either -m or -F option.\n");
exit(1);
}
-
- unlink(path);
- free(path);
}
stripspace(buf, 1);
@@ -312,10 +318,16 @@ static void create_tag(const unsigned char *object, const char *tag,
strbuf_insert(buf, 0, header_buf, header_len);
- if (sign && do_sign(buf) < 0)
- die("unable to sign the tag");
- if (write_sha1_file(buf->buf, buf->len, tag_type, result) < 0)
- die("unable to write tag file");
+ if (build_tag_object(buf, sign, result) < 0) {
+ if (path)
+ fprintf(stderr, "The tag message has been left in %s\n",
+ path);
+ exit(128);
+ }
+ if (path) {
+ unlink(path);
+ free(path);
+ }
}
struct msg_arg {
@@ -344,7 +356,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
const char *object_ref, *tag;
struct ref_lock *lock;
- int annotate = 0, sign = 0, force = 0, lines = 0,
+ int annotate = 0, sign = 0, force = 0, lines = -1,
list = 0, delete = 0, verify = 0;
const char *msgfile = NULL, *keyid = NULL;
struct msg_arg msg = { 0, STRBUF_INIT };
@@ -380,9 +392,19 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
}
if (sign)
annotate = 1;
+ if (argc == 0 && !(delete || verify))
+ list = 1;
+ if ((annotate || msg.given || msgfile || force) &&
+ (list || delete || verify))
+ usage_with_options(git_tag_usage, options);
+
+ if (list + delete + verify > 1)
+ usage_with_options(git_tag_usage, options);
if (list)
- return list_tags(argv[0], lines);
+ return list_tags(argv[0], lines == -1 ? 0 : lines);
+ if (lines != -1)
+ die("-n option is only allowed with -l.");
if (delete)
return for_each_tag_name(argv, delete_tag);
if (verify)
@@ -406,11 +428,6 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
}
}
- if (argc == 0) {
- if (annotate)
- usage_with_options(git_tag_usage, options);
- return list_tags(NULL, lines);
- }
tag = argv[0];
object_ref = argc == 2 ? argv[1] : "HEAD";
diff --git a/builtin-unpack-objects.c b/builtin-unpack-objects.c
index 9f4bdd3296..47ed610677 100644
--- a/builtin-unpack-objects.c
+++ b/builtin-unpack-objects.c
@@ -370,6 +370,8 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
base_offset = (base_offset << 7) + (c & 127);
}
base_offset = obj_list[nr].offset - base_offset;
+ if (base_offset <= 0 || base_offset >= obj_list[nr].offset)
+ die("offset value out of bound for delta base object");
delta_data = get_data(delta_size);
if (dry_run || !delta_data) {
diff --git a/builtin-update-index.c b/builtin-update-index.c
index 65d5775107..5604977505 100644
--- a/builtin-update-index.c
+++ b/builtin-update-index.c
@@ -486,7 +486,7 @@ static int unresolve_one(const char *path)
static void read_head_pointers(void)
{
if (read_ref("HEAD", head_sha1))
- die("No HEAD -- no initial commit yet?\n");
+ die("No HEAD -- no initial commit yet?");
if (read_ref("MERGE_HEAD", merge_head_sha1)) {
fprintf(stderr, "Not in the middle of a merge.\n");
exit(0);
diff --git a/builtin-update-ref.c b/builtin-update-ref.c
index 56a0b1b39c..378dc1b7a6 100644
--- a/builtin-update-ref.c
+++ b/builtin-update-ref.c
@@ -13,7 +13,7 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
{
const char *refname, *oldval, *msg=NULL;
unsigned char sha1[20], oldsha1[20];
- int delete = 0, no_deref = 0;
+ 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"),
@@ -47,9 +47,11 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
if (oldval && *oldval && get_sha1(oldval, oldsha1))
die("%s: not a valid old SHA1", oldval);
+ if (no_deref)
+ flags = REF_NODEREF;
if (delete)
- return delete_ref(refname, oldval ? oldsha1 : NULL);
+ return delete_ref(refname, oldval ? oldsha1 : NULL, flags);
else
return update_ref(msg, refname, sha1, oldval ? oldsha1 : NULL,
- no_deref ? REF_NODEREF : 0, DIE_ON_ERR);
+ flags, DIE_ON_ERR);
}
diff --git a/builtin-write-tree.c b/builtin-write-tree.c
index 52a3c015ff..9d640508dd 100644
--- a/builtin-write-tree.c
+++ b/builtin-write-tree.c
@@ -42,7 +42,7 @@ int cmd_write_tree(int argc, const char **argv, const char *unused_prefix)
die("%s: error reading the index", me);
break;
case WRITE_TREE_UNMERGED_INDEX:
- die("%s: error building trees; the index is unmerged?", me);
+ die("%s: error building trees", me);
break;
case WRITE_TREE_PREFIX_ERROR:
die("%s: prefix %s not found", me, prefix);
diff --git a/bundle.c b/bundle.c
index 00b2aabefc..4977962eb5 100644
--- a/bundle.c
+++ b/bundle.c
@@ -114,7 +114,7 @@ int verify_bundle(struct bundle_header *header, int verbose)
continue;
}
if (++ret == 1)
- error(message);
+ error("%s", message);
error("%s %s", sha1_to_hex(e->sha1), e->name);
}
if (revs.pending.nr != p->nr)
@@ -139,7 +139,7 @@ int verify_bundle(struct bundle_header *header, int verbose)
for (i = 0; i < req_nr; i++)
if (!(refs.objects[i].item->flags & SHOWN)) {
if (++ret == 1)
- error(message);
+ error("%s", message);
error("%s %s", sha1_to_hex(refs.objects[i].item->sha1),
refs.objects[i].name);
}
@@ -167,6 +167,32 @@ int list_bundle_refs(struct bundle_header *header, int argc, const char **argv)
return list_refs(&header->references, argc, argv);
}
+static int is_tag_in_date_range(struct object *tag, struct rev_info *revs)
+{
+ unsigned long size;
+ enum object_type type;
+ char *buf, *line, *lineend;
+ unsigned long date;
+
+ if (revs->max_age == -1 && revs->min_age == -1)
+ return 1;
+
+ buf = read_sha1_file(tag->sha1, &type, &size);
+ if (!buf)
+ return 1;
+ line = memmem(buf, size, "\ntagger ", 8);
+ if (!line++)
+ return 1;
+ lineend = memchr(line, buf + size - line, '\n');
+ line = memchr(line, lineend ? lineend - line : buf + size - line, '>');
+ if (!line++)
+ return 1;
+ date = strtoul(line, NULL, 10);
+ free(buf);
+ return (revs->max_age == -1 || revs->max_age < date) &&
+ (revs->min_age == -1 || revs->min_age > date);
+}
+
int create_bundle(struct bundle_header *header, const char *path,
int argc, const char **argv)
{
@@ -186,7 +212,8 @@ int create_bundle(struct bundle_header *header, const char *path,
if (bundle_to_stdout)
bundle_fd = 1;
else
- bundle_fd = hold_lock_file_for_update(&lock, path, 1);
+ bundle_fd = hold_lock_file_for_update(&lock, path,
+ LOCK_DIE_ON_ERROR);
/* write signature */
write_or_die(bundle_fd, bundle_signature, strlen(bundle_signature));
@@ -254,6 +281,12 @@ int create_bundle(struct bundle_header *header, const char *path,
flag = 0;
display_ref = (flag & REF_ISSYMREF) ? e->name : ref;
+ if (e->item->type == OBJ_TAG &&
+ !is_tag_in_date_range(e->item, &revs)) {
+ e->item->flags |= UNINTERESTING;
+ continue;
+ }
+
/*
* Make sure the refs we wrote out is correct; --max-count and
* other limiting options could have prevented all the tips
diff --git a/cache-tree.c b/cache-tree.c
index 5f8ee87bb1..3d8f218a5f 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -155,13 +155,17 @@ static int verify_cache(struct cache_entry **cache,
funny = 0;
for (i = 0; i < entries; i++) {
struct cache_entry *ce = cache[i];
- if (ce_stage(ce)) {
+ if (ce_stage(ce) || (ce->ce_flags & CE_INTENT_TO_ADD)) {
if (10 < ++funny) {
fprintf(stderr, "...\n");
break;
}
- fprintf(stderr, "%s: unmerged (%s)\n",
- ce->name, sha1_to_hex(ce->sha1));
+ if (ce_stage(ce))
+ fprintf(stderr, "%s: unmerged (%s)\n",
+ ce->name, sha1_to_hex(ce->sha1));
+ else
+ fprintf(stderr, "%s: not added yet\n",
+ ce->name);
}
}
if (funny)
diff --git a/cache.h b/cache.h
index 991544cf0b..8e1af2669b 100644
--- a/cache.h
+++ b/cache.h
@@ -115,6 +115,26 @@ struct ondisk_cache_entry {
char name[FLEX_ARRAY]; /* more */
};
+/*
+ * This struct is used when CE_EXTENDED bit is 1
+ * The struct must match ondisk_cache_entry exactly from
+ * ctime till flags
+ */
+struct ondisk_cache_entry_extended {
+ struct cache_time ctime;
+ struct cache_time mtime;
+ unsigned int dev;
+ unsigned int ino;
+ unsigned int mode;
+ unsigned int uid;
+ unsigned int gid;
+ unsigned int size;
+ unsigned char sha1[20];
+ unsigned short flags;
+ unsigned short flags2;
+ char name[FLEX_ARRAY]; /* more */
+};
+
struct cache_entry {
unsigned int ce_ctime;
unsigned int ce_mtime;
@@ -136,7 +156,15 @@ struct cache_entry {
#define CE_VALID (0x8000)
#define CE_STAGESHIFT 12
-/* In-memory only */
+/*
+ * Range 0xFFFF0000 in ce_flags is divided into
+ * two parts: in-memory flags and on-disk ones.
+ * Flags in CE_EXTENDED_FLAGS will get saved on-disk
+ * if you want to save a new flag, add it in
+ * CE_EXTENDED_FLAGS
+ *
+ * In-memory only flags
+ */
#define CE_UPDATE (0x10000)
#define CE_REMOVE (0x20000)
#define CE_UPTODATE (0x40000)
@@ -146,6 +174,25 @@ struct cache_entry {
#define CE_UNHASHED (0x200000)
/*
+ * Extended on-disk flags
+ */
+#define CE_INTENT_TO_ADD 0x20000000
+/* CE_EXTENDED2 is for future extension */
+#define CE_EXTENDED2 0x80000000
+
+#define CE_EXTENDED_FLAGS (CE_INTENT_TO_ADD)
+
+/*
+ * Safeguard to avoid saving wrong flags:
+ * - CE_EXTENDED2 won't get saved until its semantic is known
+ * - Bits in 0x0000FFFF have been saved in ce_flags already
+ * - Bits in 0x003F0000 are currently in-memory flags
+ */
+#if CE_EXTENDED_FLAGS & 0x803FFFFF
+#error "CE_EXTENDED_FLAGS out of range"
+#endif
+
+/*
* Copy the sha1 and stat state of a cache entry from one to
* another. But we never change the name, or the hash state!
*/
@@ -177,7 +224,9 @@ static inline size_t ce_namelen(const struct cache_entry *ce)
}
#define ce_size(ce) cache_entry_size(ce_namelen(ce))
-#define ondisk_ce_size(ce) ondisk_cache_entry_size(ce_namelen(ce))
+#define ondisk_ce_size(ce) (((ce)->ce_flags & CE_EXTENDED) ? \
+ ondisk_cache_entry_extended_size(ce_namelen(ce)) : \
+ ondisk_cache_entry_size(ce_namelen(ce)))
#define ce_stage(ce) ((CE_STAGEMASK & (ce)->ce_flags) >> CE_STAGESHIFT)
#define ce_uptodate(ce) ((ce)->ce_flags & CE_UPTODATE)
#define ce_mark_uptodate(ce) ((ce)->ce_flags |= CE_UPTODATE)
@@ -220,8 +269,10 @@ static inline int ce_to_dtype(const struct cache_entry *ce)
(S_ISREG(mode) ? (S_IFREG | ce_permissions(mode)) : \
S_ISLNK(mode) ? S_IFLNK : S_ISDIR(mode) ? S_IFDIR : S_IFGITLINK)
-#define cache_entry_size(len) ((offsetof(struct cache_entry,name) + (len) + 8) & ~7)
-#define ondisk_cache_entry_size(len) ((offsetof(struct ondisk_cache_entry,name) + (len) + 8) & ~7)
+#define flexible_size(STRUCT,len) ((offsetof(struct STRUCT,name) + (len) + 8) & ~7)
+#define cache_entry_size(len) flexible_size(cache_entry,len)
+#define ondisk_cache_entry_size(len) flexible_size(ondisk_cache_entry,len)
+#define ondisk_cache_entry_extended_size(len) flexible_size(ondisk_cache_entry_extended,len)
struct index_state {
struct cache_entry **cache;
@@ -262,6 +313,8 @@ static inline void remove_name_hash(struct cache_entry *ce)
#define read_cache() read_index(&the_index)
#define read_cache_from(path) read_index_from(&the_index, (path))
+#define read_cache_preload(pathspec) read_index_preload(&the_index, (pathspec))
+#define is_cache_unborn() is_index_unborn(&the_index)
#define read_cache_unmerged() read_index_unmerged(&the_index)
#define write_cache(newfd, cache, entries) write_index(&the_index, (newfd))
#define discard_cache() discard_index(&the_index)
@@ -277,6 +330,7 @@ static inline void remove_name_hash(struct cache_entry *ce)
#define ce_match_stat(ce, st, options) ie_match_stat(&the_index, (ce), (st), (options))
#define ce_modified(ce, st, options) ie_modified(&the_index, (ce), (st), (options))
#define cache_name_exists(name, namelen, igncase) index_name_exists(&the_index, (name), (namelen), (igncase))
+#define cache_name_is_other(name, namelen) index_name_is_other(&the_index, (name), (namelen))
#endif
enum object_type {
@@ -366,7 +420,9 @@ extern int init_db(const char *template_dir, unsigned int flags);
/* Initialize and use the cache information */
extern int read_index(struct index_state *);
+extern int read_index_preload(struct index_state *, const char **pathspec);
extern int read_index_from(struct index_state *, const char *path);
+extern int is_index_unborn(struct index_state *);
extern int read_index_unmerged(struct index_state *);
extern int write_index(const struct index_state *, int newfd);
extern int discard_index(struct index_state *);
@@ -393,6 +449,7 @@ extern int add_to_index(struct index_state *, const char *path, struct stat *, i
extern int add_file_to_index(struct index_state *, const char *path, int flags);
extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, int refresh);
extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);
+extern int index_name_is_other(const struct index_state *, const char *, int);
/* do stat comparison even if CE_VALID is true */
#define CE_MATCH_IGNORE_VALID 01
@@ -421,6 +478,8 @@ struct lock_file {
char on_list;
char filename[PATH_MAX];
};
+#define LOCK_DIE_ON_ERROR 1
+#define LOCK_NODEREF 2
extern int hold_lock_file_for_update(struct lock_file *, const char *path, int);
extern int hold_lock_file_for_append(struct lock_file *, const char *path, int);
extern int commit_lock_file(struct lock_file *);
@@ -430,7 +489,7 @@ extern int commit_locked_index(struct lock_file *);
extern void set_alternate_index_output(const char *);
extern int close_lock_file(struct lock_file *);
extern void rollback_lock_file(struct lock_file *);
-extern int delete_ref(const char *, const unsigned char *sha1);
+extern int delete_ref(const char *, const unsigned char *sha1, int delopt);
/* Environment bits from configuration mechanism */
extern int trust_executable_bit;
@@ -452,6 +511,7 @@ extern size_t packed_git_limit;
extern size_t delta_base_cache_limit;
extern int auto_crlf;
extern int fsync_object_files;
+extern int core_preload_index;
enum safe_crlf {
SAFE_CRLF_FALSE = 0,
@@ -491,6 +551,13 @@ extern int check_repository_format(void);
#define DATA_CHANGED 0x0020
#define TYPE_CHANGED 0x0040
+extern char *mksnpath(char *buf, size_t n, const char *fmt, ...)
+ __attribute__((format (printf, 3, 4)));
+extern char *git_snpath(char *buf, size_t n, const char *fmt, ...)
+ __attribute__((format (printf, 3, 4)));
+extern char *git_pathdup(const char *fmt, ...)
+ __attribute__((format (printf, 1, 2)));
+
/* Return a statically allocated filename matching the sha1 signature */
extern char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
extern char *git_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
@@ -515,6 +582,13 @@ static inline void hashclr(unsigned char *hash)
{
memset(hash, 0, 20);
}
+extern int is_empty_blob_sha1(const unsigned char *sha1);
+
+#define EMPTY_TREE_SHA1_HEX \
+ "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
+#define EMPTY_TREE_SHA1_BIN \
+ "\x4b\x82\x5d\xc6\x42\xcb\x6e\xb9\xa0\x60" \
+ "\xe5\x4b\xf8\xd6\x92\x88\xfb\xee\x49\x04"
int git_mkstemp(char *path, size_t n, const char *template);
@@ -557,8 +631,8 @@ extern int write_sha1_file(void *buf, unsigned long len, const char *type, unsig
extern int pretend_sha1_file(void *, unsigned long, enum object_type, unsigned char *);
extern int force_object_loose(const unsigned char *sha1, time_t mtime);
-/* just like read_sha1_file(), but non fatal in presence of bad objects */
-extern void *read_object(const unsigned char *sha1, enum object_type *type, unsigned long *size);
+/* global flag to enable extra checks when accessing packed objects */
+extern int do_check_packed_object_crc;
extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned long size, const char *type);
@@ -566,6 +640,7 @@ extern int move_temp_to_file(const char *tmpfile, const char *filename);
extern int has_sha1_pack(const unsigned char *sha1, const char **ignore);
extern int has_sha1_file(const unsigned char *sha1);
+extern int has_loose_object_nonlocal(const unsigned char *sha1);
extern int has_pack_file(const unsigned char *sha1);
extern int has_pack_index(const unsigned char *sha1);
@@ -674,7 +749,8 @@ extern struct packed_git {
int index_version;
time_t mtime;
int pack_fd;
- int pack_local;
+ unsigned pack_local:1,
+ pack_keep:1;
unsigned char sha1[20];
/* something like ".git/objects/pack/xxxxx.pack" */
char pack_name[FLEX_ARRAY]; /* more */
@@ -741,12 +817,13 @@ extern int open_pack_index(struct packed_git *);
extern unsigned char* use_pack(struct packed_git *, struct pack_window **, off_t, unsigned int *);
extern void close_pack_windows(struct packed_git *);
extern void unuse_pack(struct pack_window **);
+extern void free_pack_by_name(const char *);
extern struct packed_git *add_packed_git(const char *, int, int);
extern const unsigned char *nth_packed_object_sha1(struct packed_git *, uint32_t);
extern off_t nth_packed_object_offset(const struct packed_git *, uint32_t);
extern off_t find_pack_entry_one(const unsigned char *, struct packed_git *);
extern void *unpack_entry(struct packed_git *, off_t, enum object_type *, unsigned long *);
-extern unsigned long unpack_object_header_gently(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep);
+extern unsigned long unpack_object_header_buffer(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep);
extern unsigned long get_size_from_delta(struct packed_git *, struct pack_window **, off_t);
extern const char *packed_object_info_detail(struct packed_git *, off_t, unsigned long *, unsigned long *, unsigned int *, unsigned char *);
extern int matches_pack_name(struct packed_git *p, const char *name);
diff --git a/combine-diff.c b/combine-diff.c
index 5aa1104d34..bccc018ab2 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -213,6 +213,7 @@ static void combine_diff(const unsigned char *parent, mmfile_t *result_file,
parent_file.ptr = grab_blob(parent, &sz);
parent_file.size = sz;
+ memset(&xpp, 0, sizeof(xpp));
xpp.flags = XDF_NEED_MINIMAL;
memset(&xecfg, 0, sizeof(xecfg));
memset(&state, 0, sizeof(state));
@@ -702,15 +703,15 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
goto deleted_file;
if (S_ISLNK(st.st_mode)) {
- size_t len = xsize_t(st.st_size);
- result_size = len;
- result = xmalloc(len + 1);
- if (result_size != readlink(elem->path, result, len)) {
+ struct strbuf buf = STRBUF_INIT;
+
+ if (strbuf_readlink(&buf, elem->path, st.st_size) < 0) {
error("readlink(%s): %s", elem->path,
strerror(errno));
return;
}
- result[len] = 0;
+ result_size = buf.len;
+ result = strbuf_detach(&buf, NULL);
elem->mode = canon_mode(st.st_mode);
}
else if (0 <= (fd = open(elem->path, O_RDONLY)) &&
diff --git a/commit.h b/commit.h
index 4c05864fb4..3a7b06a828 100644
--- a/commit.h
+++ b/commit.h
@@ -65,6 +65,8 @@ enum cmit_fmt {
extern int non_ascii(int);
struct rev_info; /* in revision.h, it circularly uses enum cmit_fmt */
+extern char *reencode_commit_message(const struct commit *commit,
+ const char **encoding_p);
extern void get_commit_format(const char *arg, struct rev_info *);
extern void format_commit_message(const struct commit *commit,
const void *format, struct strbuf *sb,
diff --git a/compat/cygwin.c b/compat/cygwin.c
index 423ff20b0e..ebac148392 100644
--- a/compat/cygwin.c
+++ b/compat/cygwin.c
@@ -91,13 +91,24 @@ static int cygwin_stat(const char *path, struct stat *buf)
* functions should be used. The choice is determined by core.ignorecygwinfstricks.
* Reading this option is not always possible immediately as git_dir may be
* not be set yet. So until it is set, use cygwin lstat/stat functions.
+ * However, if core.filemode is set, we must use the Cygwin posix
+ * stat/lstat as the Windows stat fuctions do not determine posix filemode.
+ *
+ * Note that git_cygwin_config() does NOT call git_default_config() and this
+ * is deliberate. Many commands read from config to establish initial
+ * values in variables and later tweak them from elsewhere (e.g. command line).
+ * init_stat() is called lazily on demand, typically much late in the program,
+ * and calling git_default_config() from here would break such variables.
*/
static int native_stat = 1;
+static int core_filemode;
static int git_cygwin_config(const char *var, const char *value, void *cb)
{
if (!strcmp(var, "core.ignorecygwinfstricks"))
native_stat = git_config_bool(var, value);
+ else if (!strcmp(var, "core.filemode"))
+ core_filemode = git_config_bool(var, value);
return 0;
}
@@ -105,8 +116,13 @@ static int init_stat(void)
{
if (have_git_dir()) {
git_config(git_cygwin_config, NULL);
- cygwin_stat_fn = native_stat ? cygwin_stat : stat;
- cygwin_lstat_fn = native_stat ? cygwin_lstat : lstat;
+ if (!core_filemode && native_stat) {
+ cygwin_stat_fn = cygwin_stat;
+ cygwin_lstat_fn = cygwin_lstat;
+ } else {
+ cygwin_stat_fn = stat;
+ cygwin_lstat_fn = lstat;
+ }
return 0;
}
return 1;
diff --git a/compat/mingw.c b/compat/mingw.c
index 09858f6c59..3dbe6a77ff 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -536,12 +536,16 @@ static pid_t mingw_spawnve(const char *cmd, const char **argv, char **env,
* would normally create a console window. But
* since we'll be redirecting std streams, we do
* not need the console.
+ * It is necessary to use DETACHED_PROCESS
+ * instead of CREATE_NO_WINDOW to make ssh
+ * recognize that it has no console.
*/
- flags = CREATE_NO_WINDOW;
+ flags = DETACHED_PROCESS;
} else {
/* There is already a console. If we specified
- * CREATE_NO_WINDOW here, too, Windows would
+ * DETACHED_PROCESS here, too, Windows would
* disassociate the child from the console.
+ * The same is true for CREATE_NO_WINDOW.
* Go figure!
*/
flags = 0;
@@ -815,6 +819,8 @@ int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz)
#undef rename
int mingw_rename(const char *pold, const char *pnew)
{
+ DWORD attrs;
+
/*
* Try native rename() first to get errno right.
* It is based on MoveFile(), which cannot overwrite existing files.
@@ -826,12 +832,19 @@ int mingw_rename(const char *pold, const char *pnew)
if (MoveFileEx(pold, pnew, MOVEFILE_REPLACE_EXISTING))
return 0;
/* TODO: translate more errors */
- if (GetLastError() == ERROR_ACCESS_DENIED) {
- DWORD attrs = GetFileAttributes(pnew);
- if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY)) {
+ if (GetLastError() == ERROR_ACCESS_DENIED &&
+ (attrs = GetFileAttributes(pnew)) != INVALID_FILE_ATTRIBUTES) {
+ if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
errno = EISDIR;
return -1;
}
+ if ((attrs & FILE_ATTRIBUTE_READONLY) &&
+ SetFileAttributes(pnew, attrs & ~FILE_ATTRIBUTE_READONLY)) {
+ if (MoveFileEx(pold, pnew, MOVEFILE_REPLACE_EXISTING))
+ return 0;
+ /* revert file attributes on failure */
+ SetFileAttributes(pnew, attrs);
+ }
}
errno = EACCES;
return -1;
diff --git a/config.c b/config.c
index b8d289d217..790405a213 100644
--- a/config.c
+++ b/config.c
@@ -490,6 +490,11 @@ static int git_default_core_config(const char *var, const char *value)
return 0;
}
+ if (!strcmp(var, "core.preloadindex")) {
+ core_preload_index = git_config_bool(var, value);
+ return 0;
+ }
+
/* Add other config variables here and to Documentation/config.txt. */
return 0;
}
@@ -631,10 +636,7 @@ int git_config(config_fn_t fn, void *data)
char *repo_config = NULL;
const char *home = NULL;
- /* $GIT_CONFIG makes git read _only_ the given config file,
- * $GIT_CONFIG_LOCAL will make it process it in addition to the
- * global config file, the same way it would the per-repository
- * config file otherwise. */
+ /* Setting $GIT_CONFIG makes git read _only_ the given config file. */
if (config_exclusive_filename)
return git_config_from_file(fn, config_exclusive_filename, data);
if (git_config_system() && !access(git_etc_gitconfig(), R_OK))
@@ -649,7 +651,7 @@ int git_config(config_fn_t fn, void *data)
free(user_config);
}
- repo_config = xstrdup(git_path("config"));
+ repo_config = git_pathdup("config");
ret += git_config_from_file(fn, repo_config, data);
free(repo_config);
return ret;
@@ -889,7 +891,7 @@ int git_config_set_multivar(const char* key, const char* value,
if (config_exclusive_filename)
config_filename = xstrdup(config_exclusive_filename);
else
- config_filename = xstrdup(git_path("config"));
+ config_filename = git_pathdup("config");
/*
* Since "key" actually contains the section name and the real
@@ -1149,7 +1151,7 @@ int git_config_rename_section(const char *old_name, const char *new_name)
if (config_exclusive_filename)
config_filename = xstrdup(config_exclusive_filename);
else
- config_filename = xstrdup(git_path("config"));
+ config_filename = git_pathdup("config");
out_fd = hold_lock_file_for_update(lock, config_filename, 0);
if (out_fd < 0) {
ret = error("could not lock config file %s", config_filename);
diff --git a/config.mak.in b/config.mak.in
index 17e9861c06..14dfb21fa5 100644
--- a/config.mak.in
+++ b/config.mak.in
@@ -41,6 +41,7 @@ NO_C99_FORMAT=@NO_C99_FORMAT@
NO_STRCASESTR=@NO_STRCASESTR@
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@
@@ -50,3 +51,5 @@ OLD_ICONV=@OLD_ICONV@
NO_DEFLATE_BOUND=@NO_DEFLATE_BOUND@
FREAD_READS_DIRECTORIES=@FREAD_READS_DIRECTORIES@
SNPRINTF_RETURNS_BOGUS=@SNPRINTF_RETURNS_BOGUS@
+NO_PTHREADS=@NO_PTHREADS@
+PTHREAD_LIBS=@PTHREAD_LIBS@
diff --git a/configure.ac b/configure.ac
index 27bab00a45..0a5fc8c6f6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -65,7 +65,17 @@ else \
fi \
])# GIT_PARSE_WITH
-
+dnl
+dnl GIT_CHECK_FUNC(FUNCTION, IFTRUE, IFFALSE)
+dnl -----------------------------------------
+dnl Similar to AC_CHECK_FUNC, but on systems that do not generate
+dnl warnings for missing prototypes (e.g. FreeBSD when compiling without
+dnl -Wall), it does not work. By looking for function definition in
+dnl libraries, this problem can be worked around.
+AC_DEFUN([GIT_CHECK_FUNC],[AC_CHECK_FUNC([$1],[
+ AC_SEARCH_LIBS([$1],,
+ [$2],[$3])
+],[$3])])
## Site configuration related to programs (before tests)
## --with-PACKAGE[=ARG] and --without-PACKAGE
#
@@ -117,7 +127,7 @@ else
SAVE_LDFLAGS="${LDFLAGS}"
LDFLAGS="${SAVE_LDFLAGS} -Wl,-rpath,/"
AC_LINK_IFELSE(AC_LANG_PROGRAM([], []), [ld_wl_rpath=yes], [ld_wl_rpath=no])
- LDFLAGS="${SAVE_LD_FLAGS}"
+ LDFLAGS="${SAVE_LDFLAGS}"
])
if test "$ld_wl_rpath" = "yes"; then
AC_SUBST(CC_LD_DYNPATH, [-Wl,-rpath,])
@@ -126,7 +136,7 @@ else
SAVE_LDFLAGS="${LDFLAGS}"
LDFLAGS="${SAVE_LDFLAGS} -rpath /"
AC_LINK_IFELSE(AC_LANG_PROGRAM([], []), [ld_rpath=yes], [ld_rpath=no])
- LDFLAGS="${SAVE_LD_FLAGS}"
+ LDFLAGS="${SAVE_LDFLAGS}"
])
if test "$ld_rpath" = "yes"; then
AC_SUBST(CC_LD_DYNPATH, [-rpath])
@@ -325,7 +335,7 @@ AC_SUBST(NO_SOCKADDR_STORAGE)
#
# Define NO_IPV6 if you lack IPv6 support and getaddrinfo().
AC_CHECK_TYPE([struct addrinfo],[
- AC_CHECK_FUNC([getaddrinfo],
+ GIT_CHECK_FUNC([getaddrinfo],
[NO_IPV6=],
[NO_IPV6=YesPlease])
],[NO_IPV6=YesPlease],[
@@ -419,43 +429,51 @@ AC_SUBST(SNPRINTF_RETURNS_BOGUS)
AC_MSG_NOTICE([CHECKS for library functions])
#
# Define NO_STRCASESTR if you don't have strcasestr.
-AC_CHECK_FUNC(strcasestr,
+GIT_CHECK_FUNC(strcasestr,
[NO_STRCASESTR=],
[NO_STRCASESTR=YesPlease])
AC_SUBST(NO_STRCASESTR)
#
# Define NO_MEMMEM if you don't have memmem.
-AC_CHECK_FUNC(memmem,
+GIT_CHECK_FUNC(memmem,
[NO_MEMMEM=],
[NO_MEMMEM=YesPlease])
AC_SUBST(NO_MEMMEM)
#
# Define NO_STRLCPY if you don't have strlcpy.
-AC_CHECK_FUNC(strlcpy,
+GIT_CHECK_FUNC(strlcpy,
[NO_STRLCPY=],
[NO_STRLCPY=YesPlease])
AC_SUBST(NO_STRLCPY)
#
+# Define NO_UINTMAX_T if your platform does not have uintmax_t
+AC_CHECK_TYPE(uintmax_t,
+[NO_UINTMAX_T=],
+[NO_UINTMAX_T=YesPlease],[
+#include <inttypes.h>
+])
+AC_SUBST(NO_UINTMAX_T)
+#
# Define NO_STRTOUMAX if you don't have strtoumax in the C library.
-AC_CHECK_FUNC(strtoumax,
+GIT_CHECK_FUNC(strtoumax,
[NO_STRTOUMAX=],
[NO_STRTOUMAX=YesPlease])
AC_SUBST(NO_STRTOUMAX)
#
# Define NO_SETENV if you don't have setenv in the C library.
-AC_CHECK_FUNC(setenv,
+GIT_CHECK_FUNC(setenv,
[NO_SETENV=],
[NO_SETENV=YesPlease])
AC_SUBST(NO_SETENV)
#
# Define NO_UNSETENV if you don't have unsetenv in the C library.
-AC_CHECK_FUNC(unsetenv,
+GIT_CHECK_FUNC(unsetenv,
[NO_UNSETENV=],
[NO_UNSETENV=YesPlease])
AC_SUBST(NO_UNSETENV)
#
# Define NO_MKDTEMP if you don't have mkdtemp in the C library.
-AC_CHECK_FUNC(mkdtemp,
+GIT_CHECK_FUNC(mkdtemp,
[NO_MKDTEMP=],
[NO_MKDTEMP=YesPlease])
AC_SUBST(NO_MKDTEMP)
@@ -471,6 +489,27 @@ AC_SUBST(NO_MKDTEMP)
#
# Define NO_SYMLINK_HEAD if you never want .git/HEAD to be a symbolic link.
# Enable it on Windows. By default, symrefs are still used.
+#
+# Define NO_PTHREADS if we do not have pthreads
+#
+# Define PTHREAD_LIBS to the linker flag used for Pthread support.
+AC_LANG_CONFTEST([AC_LANG_PROGRAM(
+ [[#include <pthread.h>]],
+ [[pthread_mutex_t test_mutex;]]
+)])
+${CC} -pthread conftest.c -o conftest.o > /dev/null 2>&1
+if test $? -eq 0;then
+ PTHREAD_LIBS="-pthread"
+else
+ ${CC} -lpthread conftest.c -o conftest.o > /dev/null 2>&1
+ if test $? -eq 0;then
+ PTHREAD_LIBS="-lpthread"
+ else
+ NO_PTHREADS=UnfortunatelyYes
+ fi
+fi
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(NO_PTHREADS)
## Site configuration (override autodetection)
## --with-PACKAGE[=ARG] and --without-PACKAGE
diff --git a/connect.c b/connect.c
index 67d2cd86a8..2f23ab3b87 100644
--- a/connect.c
+++ b/connect.c
@@ -70,6 +70,9 @@ struct ref **get_remote_heads(int in, struct ref **list,
if (buffer[len-1] == '\n')
buffer[--len] = 0;
+ if (len > 4 && !prefixcmp(buffer, "ERR "))
+ die("remote error: %s", buffer + 4);
+
if (len < 42 || get_sha1_hex(buffer, old_sha1) || buffer[40] != ' ')
die("protocol error: expected sha/ref, got '%s'", buffer);
name = buffer + 41;
@@ -90,9 +93,8 @@ struct ref **get_remote_heads(int in, struct ref **list,
continue;
if (nr_match && !path_match(name, nr_match, match))
continue;
- ref = alloc_ref(name_len + 1);
+ ref = alloc_ref(buffer + 41);
hashcpy(ref->old_sha1, old_sha1);
- memcpy(ref->name, buffer + 41, name_len + 1);
*list = ref;
list = &ref->next;
}
@@ -313,7 +315,7 @@ static int git_tcp_connect_sock(char *host, int flags)
/* Not numeric */
struct servent *se = getservbyname(port,"tcp");
if ( !se )
- die("Unknown port %s\n", port);
+ die("Unknown port %s", port);
nport = se->s_port;
}
@@ -478,8 +480,8 @@ char *get_port(char *host)
char *p = strchr(host, ':');
if (p) {
- strtol(p+1, &end, 10);
- if (*end == '\0') {
+ long port = strtol(p + 1, &end, 10);
+ if (end != p + 1 && *end == '\0' && 0 <= port && port < 65536) {
*p = '\0';
return p+1;
}
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index d192927c20..ec701e8069 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1,3 +1,4 @@
+#!bash
#
# bash completion support for core Git.
#
@@ -50,9 +51,11 @@ case "$COMP_WORDBREAKS" in
*) COMP_WORDBREAKS="$COMP_WORDBREAKS:"
esac
+# __gitdir accepts 0 or 1 arguments (i.e., location)
+# returns location of .git repo
__gitdir ()
{
- if [ -z "$1" ]; then
+ if [ -z "${1-}" ]; then
if [ -n "$__git_dir" ]; then
echo "$__git_dir"
elif [ -d .git ]; then
@@ -67,6 +70,8 @@ __gitdir ()
fi
}
+# __git_ps1 accepts 0 or 1 arguments (i.e., format string)
+# returns text to add to bash PS1 prompt (includes branch name)
__git_ps1 ()
{
local g="$(git rev-parse --git-dir 2>/dev/null)"
@@ -111,7 +116,7 @@ __git_ps1 ()
fi
fi
- if [ -n "$1" ]; then
+ if [ -n "${1-}" ]; then
printf "$1" "${b##refs/heads/}$r"
else
printf " (%s)" "${b##refs/heads/}$r"
@@ -119,6 +124,7 @@ __git_ps1 ()
fi
}
+# __gitcomp_1 requires 2 arguments
__gitcomp_1 ()
{
local c IFS=' '$'\t'$'\n'
@@ -131,6 +137,8 @@ __gitcomp_1 ()
done
}
+# __gitcomp accepts 1, 2, 3, or 4 arguments
+# generates completion reply with compgen
__gitcomp ()
{
local cur="${COMP_WORDS[COMP_CWORD]}"
@@ -143,22 +151,23 @@ __gitcomp ()
;;
*)
local IFS=$'\n'
- COMPREPLY=($(compgen -P "$2" \
- -W "$(__gitcomp_1 "$1" "$4")" \
+ COMPREPLY=($(compgen -P "${2-}" \
+ -W "$(__gitcomp_1 "${1-}" "${4-}")" \
-- "$cur"))
;;
esac
}
+# __git_heads accepts 0 or 1 arguments (to pass to __gitdir)
__git_heads ()
{
- local cmd i is_hash=y dir="$(__gitdir "$1")"
+ local cmd i is_hash=y dir="$(__gitdir "${1-}")"
if [ -d "$dir" ]; then
git --git-dir="$dir" for-each-ref --format='%(refname:short)' \
refs/heads
return
fi
- for i in $(git ls-remote "$1" 2>/dev/null); do
+ for i in $(git ls-remote "${1-}" 2>/dev/null); do
case "$is_hash,$i" in
y,*) is_hash=n ;;
n,*^{}) is_hash=y ;;
@@ -168,15 +177,16 @@ __git_heads ()
done
}
+# __git_tags accepts 0 or 1 arguments (to pass to __gitdir)
__git_tags ()
{
- local cmd i is_hash=y dir="$(__gitdir "$1")"
+ local cmd i is_hash=y dir="$(__gitdir "${1-}")"
if [ -d "$dir" ]; then
git --git-dir="$dir" for-each-ref --format='%(refname:short)' \
refs/tags
return
fi
- for i in $(git ls-remote "$1" 2>/dev/null); do
+ for i in $(git ls-remote "${1-}" 2>/dev/null); do
case "$is_hash,$i" in
y,*) is_hash=n ;;
n,*^{}) is_hash=y ;;
@@ -186,13 +196,25 @@ __git_tags ()
done
}
+# __git_refs accepts 0 or 1 arguments (to pass to __gitdir)
__git_refs ()
{
- local cmd i is_hash=y dir="$(__gitdir "$1")"
+ local i is_hash=y dir="$(__gitdir "${1-}")"
+ local cur="${COMP_WORDS[COMP_CWORD]}" format refs
if [ -d "$dir" ]; then
- if [ -e "$dir/HEAD" ]; then echo HEAD; fi
- git --git-dir="$dir" for-each-ref --format='%(refname:short)' \
- refs/tags refs/heads refs/remotes
+ case "$cur" in
+ refs|refs/*)
+ format="refname"
+ refs="${cur%/*}"
+ ;;
+ *)
+ if [ -e "$dir/HEAD" ]; then echo HEAD; fi
+ format="refname:short"
+ refs="refs/tags refs/heads refs/remotes"
+ ;;
+ esac
+ git --git-dir="$dir" for-each-ref --format="%($format)" \
+ $refs
return
fi
for i in $(git ls-remote "$dir" 2>/dev/null); do
@@ -207,6 +229,7 @@ __git_refs ()
done
}
+# __git_refs2 requires 1 argument (to pass to __git_refs)
__git_refs2 ()
{
local i
@@ -215,6 +238,7 @@ __git_refs2 ()
done
}
+# __git_refs_remotes requires 1 argument (to pass to ls-remote)
__git_refs_remotes ()
{
local cmd i is_hash=y
@@ -459,6 +483,7 @@ __git_aliases ()
done
}
+# __git_aliased_command requires 1 argument
__git_aliased_command ()
{
local word cmdline=$(git --git-dir="$(__gitdir)" \
@@ -471,6 +496,7 @@ __git_aliased_command ()
done
}
+# __git_find_subcommand requires 1 argument
__git_find_subcommand ()
{
local word subcommand c=1
@@ -552,7 +578,7 @@ _git_add ()
--*)
__gitcomp "
--interactive --refresh --patch --update --dry-run
- --ignore-errors
+ --ignore-errors --intent-to-add
"
return
esac
@@ -617,7 +643,6 @@ _git_branch ()
done
case "${COMP_WORDS[COMP_CWORD]}" in
- --*=*) COMPREPLY=() ;;
--*)
__gitcomp "
--color --no-color --verbose --abbrev= --no-abbrev
@@ -636,21 +661,12 @@ _git_branch ()
_git_bundle ()
{
- local mycword="$COMP_CWORD"
- case "${COMP_WORDS[0]}" in
- git)
- local cmd="${COMP_WORDS[2]}"
- mycword="$((mycword-1))"
- ;;
- git-bundle*)
- local cmd="${COMP_WORDS[1]}"
- ;;
- esac
- case "$mycword" in
- 1)
+ local cmd="${COMP_WORDS[2]}"
+ case "$COMP_CWORD" in
+ 2)
__gitcomp "create list-heads verify unbundle"
;;
- 2)
+ 3)
# looking for a file
;;
*)
@@ -774,6 +790,7 @@ _git_diff ()
--no-ext-diff
--no-prefix --src-prefix= --dst-prefix=
--base --ours --theirs
+ --inter-hunk-context=
"
return
;;
@@ -798,12 +815,7 @@ _git_fetch ()
__gitcomp "$(__git_refs)" "$pfx" "${cur#*:}"
;;
*)
- local remote
- case "${COMP_WORDS[0]}" in
- git-fetch) remote="${COMP_WORDS[1]}" ;;
- git) remote="${COMP_WORDS[2]}" ;;
- esac
- __gitcomp "$(__git_refs2 "$remote")"
+ __gitcomp "$(__git_refs2 "${COMP_WORDS[2]}")"
;;
esac
fi
@@ -826,6 +838,8 @@ _git_format_patch ()
--not --all
--cover-letter
--no-prefix --src-prefix= --dst-prefix=
+ --inline --suffix= --ignore-if-in-upstream
+ --subject-prefix=
"
return
;;
@@ -881,6 +895,7 @@ _git_help ()
attributes cli core-tutorial cvs-migration
diffcore gitk glossary hooks ignore modules
repository-layout tutorial tutorial-2
+ workflows
"
}
@@ -932,6 +947,8 @@ _git_ls_tree ()
__git_complete_file
}
+__git_log_pretty_formats="oneline short medium full fuller email raw format:"
+
_git_log ()
{
__git_has_doubledash && return
@@ -939,8 +956,7 @@ _git_log ()
local cur="${COMP_WORDS[COMP_CWORD]}"
case "$cur" in
--pretty=*)
- __gitcomp "
- oneline short medium full fuller email raw
+ __gitcomp "$__git_log_pretty_formats
" "" "${cur##--pretty=}"
return
;;
@@ -969,6 +985,7 @@ _git_log ()
--color-words --walk-reflogs
--parents --children --full-history
--merge
+ --inter-hunk-context=
"
return
;;
@@ -1046,12 +1063,7 @@ _git_pull ()
if [ "$COMP_CWORD" = 2 ]; then
__gitcomp "$(__git_remotes)"
else
- local remote
- case "${COMP_WORDS[0]}" in
- git-pull) remote="${COMP_WORDS[1]}" ;;
- git) remote="${COMP_WORDS[2]}" ;;
- esac
- __gitcomp "$(__git_refs "$remote")"
+ __gitcomp "$(__git_refs "${COMP_WORDS[2]}")"
fi
}
@@ -1064,19 +1076,13 @@ _git_push ()
else
case "$cur" in
*:*)
- local remote
- case "${COMP_WORDS[0]}" in
- git-push) remote="${COMP_WORDS[1]}" ;;
- git) remote="${COMP_WORDS[2]}" ;;
- esac
-
local pfx=""
case "$COMP_WORDBREAKS" in
*:*) : great ;;
*) pfx="${cur%%:*}:" ;;
esac
- __gitcomp "$(__git_refs "$remote")" "$pfx" "${cur#*:}"
+ __gitcomp "$(__git_refs "${COMP_WORDS[2]}")" "$pfx" "${cur#*:}"
;;
+*)
__gitcomp "$(__git_refs)" + "${cur#+}"
@@ -1168,7 +1174,7 @@ _git_config ()
;;
color.*.*)
__gitcomp "
- black red green yellow blue magenta cyan white
+ normal black red green yellow blue magenta cyan white
bold dim ul blink reverse
"
return
@@ -1192,7 +1198,7 @@ _git_config ()
branch.*.*)
local pfx="${cur%.*}."
cur="${cur##*.}"
- __gitcomp "remote merge" "$pfx" "$cur"
+ __gitcomp "remote merge mergeoptions" "$pfx" "$cur"
return
;;
branch.*)
@@ -1205,7 +1211,7 @@ _git_config ()
local pfx="${cur%.*}."
cur="${cur##*.}"
__gitcomp "
- url fetch push skipDefaultUpdate
+ url proxy fetch push mirror skipDefaultUpdate
receivepack uploadpack tagopt
" "$pfx" "$cur"
return
@@ -1219,85 +1225,161 @@ _git_config ()
esac
__gitcomp "
apply.whitespace
- core.fileMode
- core.gitProxy
- core.ignoreStat
- core.preferSymlinkRefs
- core.logAllRefUpdates
- core.loosecompression
- core.repositoryFormatVersion
- core.sharedRepository
- core.warnAmbiguousRefs
- core.compression
- core.packedGitWindowSize
- core.packedGitLimit
+ branch.autosetupmerge
+ branch.autosetuprebase
clean.requireForce
color.branch
color.branch.current
color.branch.local
- color.branch.remote
color.branch.plain
+ color.branch.remote
color.diff
- color.diff.plain
- color.diff.meta
+ color.diff.commit
color.diff.frag
- color.diff.old
+ color.diff.meta
color.diff.new
- color.diff.commit
+ color.diff.old
+ color.diff.plain
color.diff.whitespace
+ color.interactive
+ color.interactive.header
+ color.interactive.help
+ color.interactive.prompt
color.pager
color.status
- color.status.header
color.status.added
color.status.changed
+ color.status.header
+ color.status.nobranch
color.status.untracked
+ color.status.updated
+ color.ui
+ commit.template
+ core.autocrlf
+ core.bare
+ core.compression
+ core.deltaBaseCacheLimit
+ core.editor
+ core.excludesfile
+ core.fileMode
+ core.fsyncobjectfiles
+ core.gitProxy
+ core.ignoreCygwinFSTricks
+ core.ignoreStat
+ core.logAllRefUpdates
+ core.loosecompression
+ core.packedGitLimit
+ core.packedGitWindowSize
+ core.pager
+ core.preferSymlinkRefs
+ core.preloadindex
+ core.quotepath
+ core.repositoryFormatVersion
+ core.safecrlf
+ core.sharedRepository
+ core.symlinks
+ core.trustctime
+ core.warnAmbiguousRefs
+ core.whitespace
+ core.worktree
+ diff.autorefreshindex
+ diff.external
+ diff.mnemonicprefix
diff.renameLimit
+ diff.renameLimit.
diff.renames
fetch.unpackLimit
format.headers
- format.subjectprefix
- gitcvs.enabled
- gitcvs.logfile
- gitcvs.allbinary
- gitcvs.dbname gitcvs.dbdriver gitcvs.dbuser gitcvs.dbpass
- gitcvs.dbtablenameprefix
+ format.numbered
+ format.pretty
+ format.suffix
+ gc.aggressiveWindow
+ gc.auto
+ gc.autopacklimit
gc.packrefs
+ gc.pruneexpire
gc.reflogexpire
gc.reflogexpireunreachable
gc.rerereresolved
gc.rerereunresolved
- http.sslVerify
- http.sslCert
- http.sslKey
- http.sslCAInfo
- http.sslCAPath
- http.maxRequests
+ gitcvs.allbinary
+ gitcvs.dbTableNamePrefix
+ gitcvs.dbdriver
+ gitcvs.dbname
+ gitcvs.dbpass
+ gitcvs.dbuser
+ gitcvs.enabled
+ gitcvs.logfile
+ gitcvs.usecrlfattr
+ gui.blamehistoryctx
+ gui.commitmsgwidth
+ gui.copyblamethreshold
+ gui.diffcontext
+ gui.encoding
+ gui.fastcopyblame
+ gui.matchtrackingbranch
+ gui.newbranchtemplate
+ gui.pruneduringfetch
+ gui.spellingdictionary
+ gui.trustmtime
+ help.autocorrect
+ help.browser
+ help.format
http.lowSpeedLimit
http.lowSpeedTime
+ http.maxRequests
http.noEPSV
+ http.proxy
+ http.sslCAInfo
+ http.sslCAPath
+ http.sslCert
+ http.sslKey
+ http.sslVerify
i18n.commitEncoding
i18n.logOutputEncoding
+ instaweb.browser
+ instaweb.httpd
+ instaweb.local
+ instaweb.modulepath
+ instaweb.port
+ log.date
log.showroot
+ man.viewer
+ merge.conflictstyle
+ merge.log
+ merge.renameLimit
+ merge.stat
merge.tool
- merge.summary
merge.verbosity
- pack.window
- pack.depth
- pack.windowMemory
+ mergetool.keepBackup
pack.compression
- pack.deltaCacheSize
pack.deltaCacheLimit
+ pack.deltaCacheSize
+ pack.depth
+ pack.indexVersion
+ pack.packSizeLimit
+ pack.threads
+ pack.window
+ pack.windowMemory
pull.octopus
pull.twohead
- repack.useDeltaBaseOffset
+ receive.denyCurrentBranch
+ receive.denyDeletes
+ receive.denyNonFastForwards
+ receive.fsckObjects
+ receive.unpackLimit
+ repack.usedeltabaseoffset
+ rerere.autoupdate
+ rerere.enabled
showbranch.default
+ status.relativePaths
+ status.showUntrackedFiles
tar.umask
transfer.unpackLimit
- receive.unpackLimit
- receive.denyNonFastForwards
- user.name
user.email
+ user.name
user.signingkey
+ web.browser
branch. remote.
"
}
@@ -1340,7 +1422,7 @@ _git_reset ()
local cur="${COMP_WORDS[COMP_CWORD]}"
case "$cur" in
--*)
- __gitcomp "--mixed --hard --soft"
+ __gitcomp "--merge --mixed --hard --soft"
return
;;
esac
@@ -1356,7 +1438,7 @@ _git_revert ()
return
;;
esac
- COMPREPLY=()
+ __gitcomp "$(__git_refs)"
}
_git_rm ()
@@ -1397,11 +1479,12 @@ _git_shortlog ()
_git_show ()
{
+ __git_has_doubledash && return
+
local cur="${COMP_WORDS[COMP_CWORD]}"
case "$cur" in
--pretty=*)
- __gitcomp "
- oneline short medium full fuller email raw
+ __gitcomp "$__git_log_pretty_formats
" "" "${cur##--pretty=}"
return
;;
@@ -1576,7 +1659,7 @@ _git_tag ()
-m|-F)
COMPREPLY=()
;;
- -*|tag|git-tag)
+ -*|tag)
if [ $f = 1 ]; then
__gitcomp "$(__git_tags)"
else
@@ -1607,7 +1690,6 @@ _git ()
if [ -z "$command" ]; then
case "${COMP_WORDS[COMP_CWORD]}" in
- --*=*) COMPREPLY=() ;;
--*) __gitcomp "
--paginate
--no-pager
@@ -1671,6 +1753,7 @@ _git ()
show) _git_show ;;
show-branch) _git_show_branch ;;
stash) _git_stash ;;
+ stage) _git_add ;;
submodule) _git_submodule ;;
svn) _git_svn ;;
tag) _git_tag ;;
@@ -1698,13 +1781,16 @@ _gitk ()
__git_complete_revlist
}
-complete -o default -o nospace -F _git git
-complete -o default -o nospace -F _gitk gitk
+complete -o bashdefault -o default -o nospace -F _git git 2>/dev/null \
+ || complete -o default -o nospace -F _git git
+complete -o bashdefault -o default -o nospace -F _gitk gitk 2>/dev/null \
+ || complete -o default -o nospace -F _gitk gitk
# The following are necessary only for Cygwin, and only are needed
# when the user has tab-completed the executable name and consequently
# included the '.exe' suffix.
#
if [ Cygwin = "$(uname -o 2>/dev/null)" ]; then
-complete -o default -o nospace -F _git git.exe
+complete -o bashdefault -o default -o nospace -F _git git.exe 2>/dev/null \
+ || complete -o default -o nospace -F _git git.exe
fi
diff --git a/contrib/difftool/git-difftool b/contrib/difftool/git-difftool
new file mode 100755
index 0000000000..1fc087c5fc
--- /dev/null
+++ b/contrib/difftool/git-difftool
@@ -0,0 +1,74 @@
+#!/usr/bin/env perl
+# Copyright (c) 2009 David Aguilar
+#
+# This is a wrapper around the GIT_EXTERNAL_DIFF-compatible
+# git-difftool-helper script. This script exports
+# GIT_EXTERNAL_DIFF and GIT_PAGER for use by git, and
+# GIT_NO_PROMPT and GIT_MERGE_TOOL for use by git-difftool-helper.
+# Any arguments that are unknown to this script are forwarded to 'git diff'.
+
+use strict;
+use warnings;
+use Cwd qw(abs_path);
+use File::Basename qw(dirname);
+
+my $DIR = abs_path(dirname($0));
+
+
+sub usage
+{
+ print << 'USAGE';
+
+usage: git difftool [--no-prompt] [--tool=tool] ["git diff" options]
+USAGE
+ exit 1;
+}
+
+sub setup_environment
+{
+ $ENV{PATH} = "$DIR:$ENV{PATH}";
+ $ENV{GIT_PAGER} = '';
+ $ENV{GIT_EXTERNAL_DIFF} = 'git-difftool-helper';
+}
+
+sub exe
+{
+ my $exe = shift;
+ return defined $ENV{COMSPEC} ? "$exe.exe" : $exe;
+}
+
+sub generate_command
+{
+ my @command = (exe('git'), 'diff');
+ my $skip_next = 0;
+ my $idx = -1;
+ for my $arg (@ARGV) {
+ $idx++;
+ if ($skip_next) {
+ $skip_next = 0;
+ next;
+ }
+ if ($arg eq '-t' or $arg eq '--tool') {
+ usage() if $#ARGV <= $idx;
+ $ENV{GIT_MERGE_TOOL} = $ARGV[$idx + 1];
+ $skip_next = 1;
+ next;
+ }
+ if ($arg =~ /^--tool=/) {
+ $ENV{GIT_MERGE_TOOL} = substr($arg, 7);
+ next;
+ }
+ if ($arg eq '--no-prompt') {
+ $ENV{GIT_DIFFTOOL_NO_PROMPT} = 'true';
+ next;
+ }
+ if ($arg eq '-h' or $arg eq '--help') {
+ usage();
+ }
+ push @command, $arg;
+ }
+ return @command
+}
+
+setup_environment();
+exec(generate_command());
diff --git a/contrib/difftool/git-difftool-helper b/contrib/difftool/git-difftool-helper
new file mode 100755
index 0000000000..0b266e3603
--- /dev/null
+++ b/contrib/difftool/git-difftool-helper
@@ -0,0 +1,240 @@
+#!/bin/sh
+# git-difftool-helper is a GIT_EXTERNAL_DIFF-compatible diff tool launcher.
+# It supports kdiff3, tkdiff, xxdiff, meld, opendiff, emerge, ecmerge,
+# vimdiff, gvimdiff, and custom user-configurable tools.
+# This script is typically launched by using the 'git difftool'
+# convenience command.
+#
+# Copyright (c) 2009 David Aguilar
+
+# Set GIT_DIFFTOOL_NO_PROMPT to bypass the per-file prompt.
+should_prompt () {
+ ! test -n "$GIT_DIFFTOOL_NO_PROMPT"
+}
+
+# Should we keep the backup .orig file?
+keep_backup_mode="$(git config --bool merge.keepBackup || echo true)"
+keep_backup () {
+ test "$keep_backup_mode" = "true"
+}
+
+# This function manages the backup .orig file.
+# A backup $MERGED.orig file is created if changes are detected.
+cleanup_temp_files () {
+ if test -n "$MERGED"; then
+ if keep_backup && test "$MERGED" -nt "$BACKUP"; then
+ test -f "$BACKUP" && mv -- "$BACKUP" "$MERGED.orig"
+ else
+ rm -f -- "$BACKUP"
+ fi
+ fi
+}
+
+# This is called when users Ctrl-C out of git-difftool-helper
+sigint_handler () {
+ echo
+ cleanup_temp_files
+ exit 1
+}
+
+# This function prepares temporary files and launches the appropriate
+# merge tool.
+launch_merge_tool () {
+ # Merged is the filename as it appears in the work tree
+ # Local is the contents of a/filename
+ # Remote is the contents of b/filename
+ # Custom merge tool commands might use $BASE so we provide it
+ MERGED="$1"
+ LOCAL="$2"
+ REMOTE="$3"
+ BASE="$1"
+ ext="$$$(expr "$MERGED" : '.*\(\.[^/]*\)$')"
+ BACKUP="$MERGED.BACKUP.$ext"
+
+ # Create and ensure that we clean up $BACKUP
+ test -f "$MERGED" && cp -- "$MERGED" "$BACKUP"
+ trap sigint_handler SIGINT
+
+ # $LOCAL and $REMOTE are temporary files so prompt
+ # the user with the real $MERGED name before launching $merge_tool.
+ if should_prompt; then
+ printf "\nViewing: '$MERGED'\n"
+ printf "Hit return to launch '%s': " "$merge_tool"
+ read ans
+ fi
+
+ # Run the appropriate merge tool command
+ case "$merge_tool" in
+ kdiff3)
+ basename=$(basename "$MERGED")
+ "$merge_tool_path" --auto \
+ --L1 "$basename (A)" \
+ --L2 "$basename (B)" \
+ -o "$MERGED" "$LOCAL" "$REMOTE" \
+ > /dev/null 2>&1
+ ;;
+
+ tkdiff)
+ "$merge_tool_path" -o "$MERGED" "$LOCAL" "$REMOTE"
+ ;;
+
+ meld|vimdiff)
+ "$merge_tool_path" "$LOCAL" "$REMOTE"
+ ;;
+
+ gvimdiff)
+ "$merge_tool_path" -f "$LOCAL" "$REMOTE"
+ ;;
+
+ xxdiff)
+ "$merge_tool_path" \
+ -X \
+ -R 'Accel.SaveAsMerged: "Ctrl-S"' \
+ -R 'Accel.Search: "Ctrl+F"' \
+ -R 'Accel.SearchForward: "Ctrl-G"' \
+ --merged-file "$MERGED" \
+ "$LOCAL" "$REMOTE"
+ ;;
+
+ opendiff)
+ "$merge_tool_path" "$LOCAL" "$REMOTE" \
+ -merge "$MERGED" | cat
+ ;;
+
+ ecmerge)
+ "$merge_tool_path" "$LOCAL" "$REMOTE" \
+ --default --mode=merge2 --to="$MERGED"
+ ;;
+
+ emerge)
+ "$merge_tool_path" -f emerge-files-command \
+ "$LOCAL" "$REMOTE" "$(basename "$MERGED")"
+ ;;
+
+ *)
+ if test -n "$merge_tool_cmd"; then
+ ( eval $merge_tool_cmd )
+ fi
+ ;;
+ esac
+
+ cleanup_temp_files
+}
+
+# Verifies that mergetool.<tool>.cmd exists
+valid_custom_tool() {
+ merge_tool_cmd="$(git config mergetool.$1.cmd)"
+ test -n "$merge_tool_cmd"
+}
+
+# Verifies that the chosen merge tool is properly setup.
+# Built-in merge tools are always valid.
+valid_tool() {
+ case "$1" in
+ kdiff3 | tkdiff | xxdiff | meld | opendiff | emerge | vimdiff | gvimdiff | ecmerge)
+ ;; # happy
+ *)
+ if ! valid_custom_tool "$1"
+ then
+ return 1
+ fi
+ ;;
+ esac
+}
+
+# Sets up the merge_tool_path variable.
+# This handles the mergetool.<tool>.path configuration.
+init_merge_tool_path() {
+ merge_tool_path=$(git config mergetool."$1".path)
+ if test -z "$merge_tool_path"; then
+ case "$1" in
+ emerge)
+ merge_tool_path=emacs
+ ;;
+ *)
+ merge_tool_path="$1"
+ ;;
+ esac
+ fi
+}
+
+# Allow the GIT_MERGE_TOOL variable to provide a default value
+test -n "$GIT_MERGE_TOOL" && merge_tool="$GIT_MERGE_TOOL"
+
+# If not merge tool was specified then use the merge.tool
+# configuration variable. If that's invalid then reset merge_tool.
+if test -z "$merge_tool"; then
+ merge_tool=$(git config merge.tool)
+ if test -n "$merge_tool" && ! valid_tool "$merge_tool"; then
+ echo >&2 "git config option merge.tool set to unknown tool: $merge_tool"
+ echo >&2 "Resetting to default..."
+ unset merge_tool
+ fi
+fi
+
+# Try to guess an appropriate merge tool if no tool has been set.
+if test -z "$merge_tool"; then
+
+ # We have a $DISPLAY so try some common UNIX merge tools
+ if test -n "$DISPLAY"; then
+ merge_tool_candidates="kdiff3 tkdiff xxdiff meld gvimdiff"
+ # If gnome then prefer meld
+ if test -n "$GNOME_DESKTOP_SESSION_ID"; then
+ merge_tool_candidates="meld $merge_tool_candidates"
+ fi
+ # If KDE then prefer kdiff3
+ if test "$KDE_FULL_SESSION" = "true"; then
+ merge_tool_candidates="kdiff3 $merge_tool_candidates"
+ fi
+ fi
+
+ # $EDITOR is emacs so add emerge as a candidate
+ if echo "${VISUAL:-$EDITOR}" | grep 'emacs' > /dev/null 2>&1; then
+ merge_tool_candidates="$merge_tool_candidates emerge"
+ fi
+
+ # $EDITOR is vim so add vimdiff as a candidate
+ if echo "${VISUAL:-$EDITOR}" | grep 'vim' > /dev/null 2>&1; then
+ merge_tool_candidates="$merge_tool_candidates vimdiff"
+ fi
+
+ merge_tool_candidates="$merge_tool_candidates opendiff emerge vimdiff"
+ echo "merge tool candidates: $merge_tool_candidates"
+
+ # Loop over each candidate and stop when a valid merge tool is found.
+ for i in $merge_tool_candidates
+ do
+ init_merge_tool_path $i
+ if type "$merge_tool_path" > /dev/null 2>&1; then
+ merge_tool=$i
+ break
+ fi
+ done
+
+ if test -z "$merge_tool" ; then
+ echo "No known merge resolution program available."
+ exit 1
+ fi
+
+else
+ # A merge tool has been set, so verify that it's valid.
+ if ! valid_tool "$merge_tool"; then
+ echo >&2 "Unknown merge tool $merge_tool"
+ exit 1
+ fi
+
+ init_merge_tool_path "$merge_tool"
+
+ if test -z "$merge_tool_cmd" && ! type "$merge_tool_path" > /dev/null 2>&1; then
+ echo "The merge tool $merge_tool is not available as '$merge_tool_path'"
+ exit 1
+ fi
+fi
+
+
+# Launch the merge tool on each path provided by 'git diff'
+while test $# -gt 6
+do
+ launch_merge_tool "$1" "$2" "$5"
+ shift 7
+done
diff --git a/contrib/difftool/git-difftool.txt b/contrib/difftool/git-difftool.txt
new file mode 100644
index 0000000000..3940c7057c
--- /dev/null
+++ b/contrib/difftool/git-difftool.txt
@@ -0,0 +1,104 @@
+git-difftool(1)
+===============
+
+NAME
+----
+git-difftool - compare changes using common merge tools
+
+SYNOPSIS
+--------
+'git difftool' [--tool=<tool>] [--no-prompt] ['git diff' options]
+
+DESCRIPTION
+-----------
+'git difftool' is a git command that allows you to compare and edit files
+between revisions using common merge tools. At its most basic level,
+'git difftool' does what 'git mergetool' does but its use is for non-merge
+situations such as when preparing commits or comparing changes against
+the index.
+
+'git difftool' is a frontend to 'git diff' and accepts the same
+arguments and options.
+
+See linkgit:git-diff[7] for the full list of supported options.
+
+OPTIONS
+-------
+-t <tool>::
+--tool=<tool>::
+ Use the merge resolution program specified by <tool>.
+ Valid merge tools are:
+ kdiff3, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff, ecmerge, and opendiff
++
+If a merge resolution program is not specified, 'git difftool'
+will use the configuration variable `merge.tool`. If the
+configuration variable `merge.tool` is not set, 'git difftool'
+will pick a suitable default.
++
+You can explicitly provide a full path to the tool by setting the
+configuration variable `mergetool.<tool>.path`. For example, you
+can configure the absolute path to kdiff3 by setting
+`mergetool.kdiff3.path`. Otherwise, 'git difftool' assumes the
+tool is available in PATH.
++
+Instead of running one of the known merge tool programs,
+'git difftool' can be customized to run an alternative program
+by specifying the command line to invoke in a configuration
+variable `mergetool.<tool>.cmd`.
++
+When 'git difftool' is invoked with this tool (either through the
+`-t` or `--tool` option or the `merge.tool` configuration variable)
+the configured command line will be invoked with the following
+variables available: `$LOCAL` is set to the name of the temporary
+file containing the contents of the diff pre-image and `$REMOTE`
+is set to the name of the temporary file containing the contents
+of the diff post-image. `$BASE` is provided for compatibility
+with custom merge tool commands and has the same value as `$LOCAL`.
+
+--no-prompt::
+ Do not prompt before launching a merge tool.
+
+CONFIG VARIABLES
+----------------
+merge.tool::
+ The default merge tool to use.
++
+See the `--tool=<tool>` option above for more details.
+
+merge.keepBackup::
+ The original, unedited file content can be saved to a file with
+ a `.orig` extension. Defaults to `true` (i.e. keep the backup files).
+
+mergetool.<tool>.path::
+ Override the path for the given tool. This is useful in case
+ your tool is not in the PATH.
+
+mergetool.<tool>.cmd::
+ Specify the command to invoke the specified merge tool.
++
+See the `--tool=<tool>` option above for more details.
+
+
+SEE ALSO
+--------
+linkgit:git-diff[7]::
+ Show changes between commits, commit and working tree, etc
+
+linkgit:git-mergetool[1]::
+ Run merge conflict resolution tools to resolve merge conflicts
+
+linkgit:git-config[7]::
+ Get and set repository or global options
+
+
+AUTHOR
+------
+Written by David Aguilar <davvid@gmail.com>.
+
+Documentation
+--------------
+Documentation by David Aguilar and the git-list <git@vger.kernel.org>.
+
+GIT
+---
+Part of the linkgit:git[1] suite
diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el
index c1cf1cbcc0..09e8bae3a4 100644
--- a/contrib/emacs/git.el
+++ b/contrib/emacs/git.el
@@ -173,7 +173,7 @@ if there is already one that displays the same directory."
(defconst git-log-msg-separator "--- log message follows this line ---")
(defvar git-log-edit-font-lock-keywords
- `(("^\\(Author:\\|Date:\\|Parent:\\|Signed-off-by:\\)\\(.*\\)$"
+ `(("^\\(Author:\\|Date:\\|Merge:\\|Signed-off-by:\\)\\(.*\\)$"
(1 font-lock-keyword-face)
(2 font-lock-function-name-face))
(,(concat "^\\(" (regexp-quote git-log-msg-separator) "\\)$")
@@ -183,11 +183,9 @@ if there is already one that displays the same directory."
"Build a list of NAME=VALUE strings from a list of environment strings."
(mapcar (lambda (entry) (concat (car entry) "=" (cdr entry))) env))
-(defun git-call-process-env (buffer env &rest args)
+(defun git-call-process (buffer &rest args)
"Wrapper for call-process that sets environment strings."
- (let ((process-environment (append (git-get-env-strings env)
- process-environment)))
- (apply #'call-process "git" nil buffer nil args)))
+ (apply #'call-process "git" nil buffer nil args))
(defun git-call-process-display-error (&rest args)
"Wrapper for call-process that displays error messages."
@@ -197,17 +195,26 @@ if there is already one that displays the same directory."
(let ((default-directory dir)
(buffer-read-only nil))
(erase-buffer)
- (eq 0 (apply 'call-process "git" nil (list buffer t) nil args))))))
+ (eq 0 (apply #'git-call-process (list buffer t) args))))))
(unless ok (display-message-or-buffer buffer))
ok))
-(defun git-call-process-env-string (env &rest args)
- "Wrapper for call-process that sets environment strings,
-and returns the process output as a string, or nil if the git failed."
+(defun git-call-process-string (&rest args)
+ "Wrapper for call-process that returns the process output as a string,
+or nil if the git command failed."
(with-temp-buffer
- (and (eq 0 (apply #' git-call-process-env t env args))
+ (and (eq 0 (apply #'git-call-process t args))
(buffer-string))))
+(defun git-call-process-string-display-error (&rest args)
+ "Wrapper for call-process that displays error message and returns
+the process output as a string, or nil if the git command failed."
+ (with-temp-buffer
+ (if (eq 0 (apply #'git-call-process (list t t) args))
+ (buffer-string)
+ (display-message-or-buffer (current-buffer))
+ nil)))
+
(defun git-run-process-region (buffer start end program args)
"Run a git process with a buffer region as input."
(let ((output-buffer (current-buffer))
@@ -226,7 +233,7 @@ and returns the process output as a string, or nil if the git failed."
(let ((default-directory dir)
(buffer-read-only nil))
(erase-buffer)
- (apply #'git-call-process-env buffer nil args)))
+ (apply #'git-call-process buffer args)))
(message "Running git %s...done" (car args))
buffer))
@@ -327,7 +334,7 @@ and returns the process output as a string, or nil if the git failed."
(let ((cdup (with-output-to-string
(with-current-buffer standard-output
(cd dir)
- (unless (eq 0 (call-process "git" nil t nil "rev-parse" "--show-cdup"))
+ (unless (eq 0 (git-call-process t "rev-parse" "--show-cdup"))
(error "cannot find top-level git tree for %s." dir))))))
(expand-file-name (concat (file-name-as-directory dir)
(car (split-string cdup "\n"))))))
@@ -348,8 +355,8 @@ and returns the process output as a string, or nil if the git failed."
(sort-lines nil (point-min) (point-max))
(save-buffer))
(when created
- (git-call-process-env nil nil "update-index" "--add" "--" (file-relative-name ignore-name)))
- (git-update-status-files (list (file-relative-name ignore-name)) 'unknown)))
+ (git-call-process nil "update-index" "--add" "--" (file-relative-name ignore-name)))
+ (git-update-status-files (list (file-relative-name ignore-name)))))
; propertize definition for XEmacs, stolen from erc-compat
(eval-when-compile
@@ -367,38 +374,41 @@ and returns the process output as a string, or nil if the git failed."
(defun git-rev-parse (rev)
"Parse a revision name and return its SHA1."
(git-get-string-sha1
- (git-call-process-env-string nil "rev-parse" rev)))
+ (git-call-process-string "rev-parse" rev)))
(defun git-config (key)
"Retrieve the value associated to KEY in the git repository config file."
- (let ((str (git-call-process-env-string nil "config" key)))
+ (let ((str (git-call-process-string "config" key)))
(and str (car (split-string str "\n")))))
(defun git-symbolic-ref (ref)
"Wrapper for the git-symbolic-ref command."
- (let ((str (git-call-process-env-string nil "symbolic-ref" ref)))
+ (let ((str (git-call-process-string "symbolic-ref" ref)))
(and str (car (split-string str "\n")))))
(defun git-update-ref (ref newval &optional oldval reason)
"Update a reference by calling git-update-ref."
(let ((args (and oldval (list oldval))))
- (push newval args)
+ (when newval (push newval args))
(push ref args)
(when reason
(push reason args)
(push "-m" args))
+ (unless newval (push "-d" args))
(apply 'git-call-process-display-error "update-ref" args)))
(defun git-read-tree (tree &optional index-file)
"Read a tree into the index file."
- (apply #'git-call-process-env nil
- (if index-file `(("GIT_INDEX_FILE" . ,index-file)) nil)
- "read-tree" (if tree (list tree))))
+ (let ((process-environment
+ (append (and index-file (list (concat "GIT_INDEX_FILE=" index-file))) process-environment)))
+ (apply 'git-call-process-display-error "read-tree" (if tree (list tree)))))
(defun git-write-tree (&optional index-file)
"Call git-write-tree and return the resulting tree SHA1 as a string."
- (git-get-string-sha1
- (git-call-process-env-string (and index-file `(("GIT_INDEX_FILE" . ,index-file))) "write-tree")))
+ (let ((process-environment
+ (append (and index-file (list (concat "GIT_INDEX_FILE=" index-file))) process-environment)))
+ (git-get-string-sha1
+ (git-call-process-string-display-error "write-tree"))))
(defun git-commit-tree (buffer tree head)
"Call git-commit-tree with buffer as input and return the resulting commit SHA1."
@@ -424,11 +434,11 @@ and returns the process output as a string, or nil if the git failed."
(when (re-search-forward "^Date: +\\(.*\\)$" nil t)
(setq author-date (match-string 1)))
(goto-char (point-min))
- (while (re-search-forward "^Parent: +\\([0-9a-f]+\\)" nil t)
- (unless (string-equal head (match-string 1))
- (setq subject "commit (merge): ")
+ (when (re-search-forward "^Merge: +\\(.*\\)" nil t)
+ (setq subject "commit (merge): ")
+ (dolist (parent (split-string (match-string 1) " +" t))
(push "-p" args)
- (push (match-string 1) args))))
+ (push parent args))))
(setq log-start (point-min)))
(setq log-end (point-max))
(goto-char log-start)
@@ -452,7 +462,7 @@ and returns the process output as a string, or nil if the git failed."
(defun git-empty-db-p ()
"Check if the git db is empty (no commit done yet)."
- (not (eq 0 (call-process "git" nil nil nil "rev-parse" "--verify" "HEAD"))))
+ (not (eq 0 (git-call-process nil "rev-parse" "--verify" "HEAD"))))
(defun git-get-merge-heads ()
"Retrieve the merge heads from the MERGE_HEAD file if present."
@@ -468,7 +478,7 @@ and returns the process output as a string, or nil if the git failed."
(defun git-get-commit-description (commit)
"Get a one-line description of COMMIT."
(let ((coding-system-for-read (git-get-logoutput-coding-system)))
- (let ((descr (git-call-process-env-string nil "log" "--max-count=1" "--pretty=oneline" commit)))
+ (let ((descr (git-call-process-string "log" "--max-count=1" "--pretty=oneline" commit)))
(if (and descr (string-match "\\`\\([0-9a-f]\\{40\\}\\) *\\(.*\\)$" descr))
(concat (substring (match-string 1 descr) 0 10) " - " (match-string 2 descr))
descr))))
@@ -487,14 +497,11 @@ and returns the process output as a string, or nil if the git failed."
old-perm new-perm ;; permission flags
rename-state ;; rename or copy state
orig-name ;; original name for renames or copies
+ needs-update ;; whether file needs to be updated
needs-refresh) ;; whether file needs to be refreshed
(defvar git-status nil)
-(defun git-clear-status (status)
- "Remove everything from the status list."
- (ewoc-filter status (lambda (info) nil)))
-
(defun git-set-fileinfo-state (info state)
"Set the state of a file info."
(unless (eq (git-fileinfo->state info) state)
@@ -502,6 +509,7 @@ and returns the process output as a string, or nil if the git failed."
(git-fileinfo->new-perm info) (git-fileinfo->old-perm info)
(git-fileinfo->rename-state info) nil
(git-fileinfo->orig-name info) nil
+ (git-fileinfo->needs-update info) nil
(git-fileinfo->needs-refresh info) t)))
(defun git-status-filenames-map (status func files &rest args)
@@ -511,10 +519,11 @@ and returns the process output as a string, or nil if the git failed."
(let ((file (pop files))
(node (ewoc-nth status 0)))
(while (and file node)
- (let ((info (ewoc-data node)))
- (if (string-lessp (git-fileinfo->name info) file)
+ (let* ((info (ewoc-data node))
+ (name (git-fileinfo->name info)))
+ (if (string-lessp name file)
(setq node (ewoc-next status node))
- (if (string-equal (git-fileinfo->name info) file)
+ (if (string-equal name file)
(apply func info args))
(setq file (pop files))))))))
@@ -612,39 +621,52 @@ and returns the process output as a string, or nil if the git failed."
(git-file-type-as-string old-perm new-perm)
(git-rename-as-string info)))))
-(defun git-insert-info-list (status infolist)
- "Insert a list of file infos in the status buffer, replacing existing ones if any."
- (setq infolist (sort infolist
- (lambda (info1 info2)
- (string-lessp (git-fileinfo->name info1)
- (git-fileinfo->name info2)))))
- (let ((info (pop infolist))
- (node (ewoc-nth status 0)))
+(defun git-update-node-fileinfo (node info)
+ "Update the fileinfo of the specified node. The names are assumed to match already."
+ (let ((data (ewoc-data node)))
+ (setf
+ ;; preserve the marked flag
+ (git-fileinfo->marked info) (git-fileinfo->marked data)
+ (git-fileinfo->needs-update data) nil)
+ (when (not (equal info data))
+ (setf (git-fileinfo->needs-refresh info) t
+ (ewoc-data node) info))))
+
+(defun git-insert-info-list (status infolist files)
+ "Insert a sorted list of file infos in the status buffer, replacing existing ones if any."
+ (let* ((info (pop infolist))
+ (node (ewoc-nth status 0))
+ (name (and info (git-fileinfo->name info)))
+ remaining)
(while info
- (cond ((not node)
- (setq node (ewoc-enter-last status info))
- (setq info (pop infolist)))
- ((string-lessp (git-fileinfo->name (ewoc-data node))
- (git-fileinfo->name info))
- (setq node (ewoc-next status node)))
- ((string-equal (git-fileinfo->name (ewoc-data node))
- (git-fileinfo->name info))
- ;; preserve the marked flag
- (setf (git-fileinfo->marked info) (git-fileinfo->marked (ewoc-data node)))
- (setf (git-fileinfo->needs-refresh info) t)
- (setf (ewoc-data node) info)
- (setq info (pop infolist)))
- (t
- (setq node (ewoc-enter-before status node info))
- (setq info (pop infolist)))))))
+ (let ((nodename (and node (git-fileinfo->name (ewoc-data node)))))
+ (while (and files (string-lessp (car files) name))
+ (push (pop files) remaining))
+ (when (and files (string-equal (car files) name))
+ (setq files (cdr files)))
+ (cond ((not nodename)
+ (setq node (ewoc-enter-last status info))
+ (setq info (pop infolist))
+ (setq name (and info (git-fileinfo->name info))))
+ ((string-lessp nodename name)
+ (setq node (ewoc-next status node)))
+ ((string-equal nodename name)
+ ;; preserve the marked flag
+ (git-update-node-fileinfo node info)
+ (setq info (pop infolist))
+ (setq name (and info (git-fileinfo->name info))))
+ (t
+ (setq node (ewoc-enter-before status node info))
+ (setq info (pop infolist))
+ (setq name (and info (git-fileinfo->name info)))))))
+ (nconc (nreverse remaining) files)))
(defun git-run-diff-index (status files)
"Run git-diff-index on FILES and parse the results into STATUS.
Return the list of files that haven't been handled."
- (let ((remaining (copy-sequence files))
- infolist)
+ (let (infolist)
(with-temp-buffer
- (apply #'git-call-process-env t nil "diff-index" "-z" "-M" "HEAD" "--" files)
+ (apply #'git-call-process t "diff-index" "-z" "-M" "HEAD" "--" files)
(goto-char (point-min))
(while (re-search-forward
":\\([0-7]\\{6\\}\\) \\([0-7]\\{6\\}\\) [0-9a-f]\\{40\\} [0-9a-f]\\{40\\} \\(\\([ADMUT]\\)\0\\([^\0]+\\)\\|\\([CR]\\)[0-9]*\0\\([^\0]+\\)\0\\([^\0]+\\)\\)\0"
@@ -659,11 +681,12 @@ Return the list of files that haven't been handled."
(push (git-create-fileinfo 'added new-name old-perm new-perm 'copy name) infolist)
(push (git-create-fileinfo 'deleted name 0 0 'rename new-name) infolist)
(push (git-create-fileinfo 'added new-name old-perm new-perm 'rename name) infolist))
- (push (git-create-fileinfo (git-state-code state) name old-perm new-perm) infolist))
- (setq remaining (delete name remaining))
- (when new-name (setq remaining (delete new-name remaining))))))
- (git-insert-info-list status infolist)
- remaining))
+ (push (git-create-fileinfo (git-state-code state) name old-perm new-perm) infolist)))))
+ (setq infolist (sort (nreverse infolist)
+ (lambda (info1 info2)
+ (string-lessp (git-fileinfo->name info1)
+ (git-fileinfo->name info2)))))
+ (git-insert-info-list status infolist files)))
(defun git-find-status-file (status file)
"Find a given file in the status ewoc and return its node."
@@ -677,38 +700,35 @@ Return the list of files that haven't been handled."
Return the list of files that haven't been handled."
(let (infolist)
(with-temp-buffer
- (apply #'git-call-process-env t nil "ls-files" "-z" (append options (list "--") files))
+ (apply #'git-call-process t "ls-files" "-z" (append options (list "--") files))
(goto-char (point-min))
(while (re-search-forward "\\([^\0]*?\\)\\(/?\\)\0" nil t 1)
(let ((name (match-string 1)))
(push (git-create-fileinfo default-state name 0
(if (string-equal "/" (match-string 2)) (lsh ?\110 9) 0))
- infolist)
- (setq files (delete name files)))))
- (git-insert-info-list status infolist)
- files))
+ infolist))))
+ (setq infolist (nreverse infolist)) ;; assume it is sorted already
+ (git-insert-info-list status infolist files)))
(defun git-run-ls-files-cached (status files default-state)
"Run git-ls-files -c on FILES and parse the results into STATUS.
Return the list of files that haven't been handled."
- (let ((remaining (copy-sequence files))
- infolist)
+ (let (infolist)
(with-temp-buffer
- (apply #'git-call-process-env t nil "ls-files" "-z" "-s" "-c" "--" files)
+ (apply #'git-call-process t "ls-files" "-z" "-s" "-c" "--" files)
(goto-char (point-min))
(while (re-search-forward "\\([0-7]\\{6\\}\\) [0-9a-f]\\{40\\} 0\t\\([^\0]+\\)\0" nil t)
(let* ((new-perm (string-to-number (match-string 1) 8))
(old-perm (if (eq default-state 'added) 0 new-perm))
(name (match-string 2)))
- (push (git-create-fileinfo default-state name old-perm new-perm) infolist)
- (setq remaining (delete name remaining)))))
- (git-insert-info-list status infolist)
- remaining))
+ (push (git-create-fileinfo default-state name old-perm new-perm) infolist))))
+ (setq infolist (nreverse infolist)) ;; assume it is sorted already
+ (git-insert-info-list status infolist files)))
(defun git-run-ls-unmerged (status files)
"Run git-ls-files -u on FILES and parse the results into STATUS."
(with-temp-buffer
- (apply #'git-call-process-env t nil "ls-files" "-z" "-u" "--" files)
+ (apply #'git-call-process t "ls-files" "-z" "-u" "--" files)
(goto-char (point-min))
(let (unmerged-files)
(while (re-search-forward "[0-7]\\{6\\} [0-9a-f]\\{40\\} [123]\t\\([^\0]+\\)\0" nil t)
@@ -732,11 +752,17 @@ Return the list of files that haven't been handled."
(concat "--exclude-per-directory=" git-per-dir-ignore-file)
(append options (mapcar (lambda (f) (concat "--exclude-from=" f)) exclude-files)))))
-(defun git-update-status-files (files &optional default-state)
+(defun git-update-status-files (&optional files mark-files)
"Update the status of FILES from the index."
(unless git-status (error "Not in git-status buffer."))
- (when (or git-show-uptodate files)
- (git-run-ls-files-cached git-status files 'uptodate))
+ ;; set the needs-update flag on existing files
+ (if (setq files (sort files #'string-lessp))
+ (git-status-filenames-map
+ git-status (lambda (info) (setf (git-fileinfo->needs-update info) t)) files)
+ (ewoc-map (lambda (info) (setf (git-fileinfo->needs-update info) t) nil) git-status)
+ (git-call-process nil "update-index" "--refresh")
+ (when git-show-uptodate
+ (git-run-ls-files-cached git-status nil 'uptodate)))
(let* ((remaining-files
(if (git-empty-db-p) ; we need some special handling for an empty db
(git-run-ls-files-cached git-status files 'added)
@@ -746,13 +772,17 @@ Return the list of files that haven't been handled."
(setq remaining-files (git-run-ls-files-with-excludes git-status remaining-files 'unknown "-o")))
(when (or remaining-files (and git-show-ignored (not files)))
(setq remaining-files (git-run-ls-files-with-excludes git-status remaining-files 'ignored "-o" "-i")))
- (git-set-filenames-state git-status remaining-files default-state)
+ (unless files
+ (setq remaining-files (git-get-filenames (ewoc-collect git-status #'git-fileinfo->needs-update))))
+ (when remaining-files
+ (setq remaining-files (git-run-ls-files-cached git-status remaining-files 'uptodate)))
+ (git-set-filenames-state git-status remaining-files nil)
+ (when mark-files (git-mark-files git-status files))
(git-refresh-files)
(git-refresh-ewoc-hf git-status)))
(defun git-mark-files (status files)
"Mark all the specified FILES, and unmark the others."
- (setq files (sort files #'string-lessp))
(let ((file (and files (pop files)))
(node (ewoc-nth status 0)))
(while node
@@ -824,19 +854,18 @@ Return the list of files that haven't been handled."
(defun git-update-index (index-file files)
"Run git-update-index on a list of files."
- (let ((env (and index-file `(("GIT_INDEX_FILE" . ,index-file))))
+ (let ((process-environment (append (and index-file (list (concat "GIT_INDEX_FILE=" index-file)))
+ process-environment))
added deleted modified)
(dolist (info files)
(case (git-fileinfo->state info)
('added (push info added))
('deleted (push info deleted))
('modified (push info modified))))
- (when added
- (apply #'git-call-process-env nil env "update-index" "--add" "--" (git-get-filenames added)))
- (when deleted
- (apply #'git-call-process-env nil env "update-index" "--remove" "--" (git-get-filenames deleted)))
- (when modified
- (apply #'git-call-process-env nil env "update-index" "--" (git-get-filenames modified)))))
+ (and
+ (or (not added) (apply #'git-call-process-display-error "update-index" "--add" "--" (git-get-filenames added)))
+ (or (not deleted) (apply #'git-call-process-display-error "update-index" "--remove" "--" (git-get-filenames deleted)))
+ (or (not modified) (apply #'git-call-process-display-error "update-index" "--" (git-get-filenames modified))))))
(defun git-run-pre-commit-hook ()
"Run the pre-commit hook if any."
@@ -862,33 +891,30 @@ Return the list of files that haven't been handled."
(message "You cannot commit unmerged files, resolve them first.")
(unwind-protect
(let ((files (git-marked-files-state 'added 'deleted 'modified))
- head head-tree)
+ head tree head-tree)
(unless (git-empty-db-p)
(setq head (git-rev-parse "HEAD")
head-tree (git-rev-parse "HEAD^{tree}")))
- (if files
- (progn
- (message "Running git commit...")
- (git-read-tree head-tree index-file)
- (git-update-index nil files) ;update both the default index
- (git-update-index index-file files) ;and the temporary one
- (let ((tree (git-write-tree index-file)))
- (if (or (not (string-equal tree head-tree))
- (yes-or-no-p "The tree was not modified, do you really want to perform an empty commit? "))
- (let ((commit (git-commit-tree buffer tree head)))
- (when commit
- (condition-case nil (delete-file ".git/MERGE_HEAD") (error nil))
- (condition-case nil (delete-file ".git/MERGE_MSG") (error nil))
- (with-current-buffer buffer (erase-buffer))
- (git-update-status-files (git-get-filenames files) 'uptodate)
- (git-call-process-env nil nil "rerere")
- (git-call-process-env nil nil "gc" "--auto")
- (git-refresh-files)
- (git-refresh-ewoc-hf git-status)
- (message "Committed %s." commit)
- (git-run-hook "post-commit" nil)))
- (message "Commit aborted."))))
- (message "No files to commit.")))
+ (message "Running git commit...")
+ (when
+ (and
+ (git-read-tree head-tree index-file)
+ (git-update-index nil files) ;update both the default index
+ (git-update-index index-file files) ;and the temporary one
+ (setq tree (git-write-tree index-file)))
+ (if (or (not (string-equal tree head-tree))
+ (yes-or-no-p "The tree was not modified, do you really want to perform an empty commit? "))
+ (let ((commit (git-commit-tree buffer tree head)))
+ (when commit
+ (condition-case nil (delete-file ".git/MERGE_HEAD") (error nil))
+ (condition-case nil (delete-file ".git/MERGE_MSG") (error nil))
+ (with-current-buffer buffer (erase-buffer))
+ (git-update-status-files (git-get-filenames files))
+ (git-call-process nil "rerere")
+ (git-call-process nil "gc" "--auto")
+ (message "Committed %s." commit)
+ (git-run-hook "post-commit" nil)))
+ (message "Commit aborted."))))
(delete-file index-file))))))
@@ -990,6 +1016,11 @@ Return the list of files that haven't been handled."
(setq node (ewoc-prev git-status node)))
(ewoc-goto-node git-status last)))
+(defun git-insert-file (file)
+ "Insert file(s) into the git-status buffer."
+ (interactive "fInsert file: ")
+ (git-update-status-files (list (file-relative-name file))))
+
(defun git-add-file ()
"Add marked file(s) to the index cache."
(interactive)
@@ -998,7 +1029,7 @@ Return the list of files that haven't been handled."
(unless files
(push (file-relative-name (read-file-name "File to add: " nil nil t)) files))
(when (apply 'git-call-process-display-error "update-index" "--add" "--" files)
- (git-update-status-files files 'uptodate)
+ (git-update-status-files files)
(git-success-message "Added" files))))
(defun git-ignore-file ()
@@ -1008,7 +1039,7 @@ Return the list of files that haven't been handled."
(unless files
(push (file-relative-name (read-file-name "File to ignore: " nil nil t)) files))
(dolist (f files) (git-append-to-ignore f))
- (git-update-status-files files 'ignored)
+ (git-update-status-files files)
(git-success-message "Ignored" files)))
(defun git-remove-file ()
@@ -1026,7 +1057,7 @@ Return the list of files that haven't been handled."
(delete-directory name)
(delete-file name))))
(when (apply 'git-call-process-display-error "update-index" "--remove" "--" files)
- (git-update-status-files files nil)
+ (git-update-status-files files)
(git-success-message "Removed" files)))
(message "Aborting"))))
@@ -1054,7 +1085,7 @@ Return the list of files that haven't been handled."
(apply 'git-call-process-display-error "update-index" "--force-remove" "--" added))
(or (not modified)
(apply 'git-call-process-display-error "checkout" "HEAD" modified)))))
- (git-update-status-files (append added modified) 'uptodate)
+ (git-update-status-files (append added modified))
(when ok
(dolist (file modified)
(let ((buffer (get-file-buffer file)))
@@ -1067,7 +1098,7 @@ Return the list of files that haven't been handled."
(let ((files (git-get-filenames (git-marked-files-state 'unmerged))))
(when files
(when (apply 'git-call-process-display-error "update-index" "--" files)
- (git-update-status-files files 'uptodate)
+ (git-update-status-files files)
(git-success-message "Resolved" files)))))
(defun git-remove-handled ()
@@ -1225,11 +1256,10 @@ Return the list of files that haven't been handled."
(goto-char (point-max))
(insert sign-off "\n"))))
-(defun git-setup-log-buffer (buffer &optional author-name author-email subject date msg)
+(defun git-setup-log-buffer (buffer &optional merge-heads author-name author-email subject date msg)
"Setup the log buffer for a commit."
(unless git-status (error "Not in git-status buffer."))
- (let ((merge-heads (git-get-merge-heads))
- (dir default-directory)
+ (let ((dir default-directory)
(committer-name (git-get-committer-name))
(committer-email (git-get-committer-email))
(sign-off git-append-signed-off-by))
@@ -1243,9 +1273,8 @@ Return the list of files that haven't been handled."
(or author-email committer-email)
(if date (format "Date: %s\n" date) "")
(if merge-heads
- (format "Parent: %s\n%s\n"
- (git-rev-parse "HEAD")
- (mapconcat (lambda (str) (concat "Parent: " str)) merge-heads "\n"))
+ (format "Merge: %s\n"
+ (mapconcat 'identity merge-heads " "))
""))
'face 'git-header-face)
(propertize git-log-msg-separator 'face 'git-separator-face)
@@ -1285,7 +1314,7 @@ Return the list of files that haven't been handled."
(goto-char (point-min))
(when (re-search-forward "^Date: \\(.*\\)$" nil t)
(setq date (match-string 1)))))
- (git-setup-log-buffer buffer author-name author-email subject date))
+ (git-setup-log-buffer buffer (git-get-merge-heads) author-name author-email subject date))
(if (boundp 'log-edit-diff-function)
(log-edit 'git-do-commit nil '((log-edit-listfun . git-log-edit-files)
(log-edit-diff-function . git-log-edit-diff)) buffer)
@@ -1296,11 +1325,13 @@ Return the list of files that haven't been handled."
(defun git-setup-commit-buffer (commit)
"Setup the commit buffer with the contents of COMMIT."
- (let (author-name author-email subject date msg)
+ (let (parents author-name author-email subject date msg)
(with-temp-buffer
(let ((coding-system (git-get-logoutput-coding-system)))
- (git-call-process-env t nil "log" "-1" "--pretty=medium" commit)
+ (git-call-process t "log" "-1" "--pretty=medium" "--abbrev=40" commit)
(goto-char (point-min))
+ (when (re-search-forward "^Merge: *\\(.*\\)$" nil t)
+ (setq parents (cdr (split-string (match-string 1) " +"))))
(when (re-search-forward "^Author: *\\(.*\\) <\\(.*\\)>$" nil t)
(setq author-name (match-string 1))
(setq author-email (match-string 2)))
@@ -1312,14 +1343,14 @@ Return the list of files that haven't been handled."
(setq subject (pop msg))
(while (and msg (zerop (length (car msg))) (pop msg)))))
(git-setup-log-buffer (get-buffer-create "*git-commit*")
- author-name author-email subject date
+ parents author-name author-email subject date
(mapconcat #'identity msg "\n"))))
(defun git-get-commit-files (commit)
"Retrieve the list of files modified by COMMIT."
(let (files)
(with-temp-buffer
- (git-call-process-env t nil "diff-tree" "-r" "-z" "--name-only" "--no-commit-id" commit)
+ (git-call-process t "diff-tree" "-m" "-r" "-z" "--name-only" "--no-commit-id" "--root" commit)
(goto-char (point-min))
(while (re-search-forward "\\([^\0]*\\)\0" nil t 1)
(push (match-string 1) files)))
@@ -1333,10 +1364,11 @@ amended version of it."
(when (git-empty-db-p) (error "No commit to amend."))
(let* ((commit (git-rev-parse "HEAD"))
(files (git-get-commit-files commit)))
- (when (git-call-process-display-error "reset" "--soft" "HEAD^")
- (git-update-status-files (copy-sequence files) 'uptodate)
- (git-mark-files git-status files)
- (git-refresh-files)
+ (when (if (git-rev-parse "HEAD^")
+ (git-call-process-display-error "reset" "--soft" "HEAD^")
+ (and (git-update-ref "ORIG_HEAD" commit)
+ (git-update-ref "HEAD" nil commit)))
+ (git-update-status-files files t)
(git-setup-commit-buffer commit)
(git-commit-file))))
@@ -1377,27 +1409,10 @@ amended version of it."
(defun git-refresh-status ()
"Refresh the git status buffer."
(interactive)
- (let* ((status git-status)
- (pos (ewoc-locate status))
- (marked-files (git-get-filenames (ewoc-collect status (lambda (info) (git-fileinfo->marked info)))))
- (cur-name (and pos (git-fileinfo->name (ewoc-data pos)))))
- (unless status (error "Not in git-status buffer."))
- (message "Refreshing git status...")
- (git-call-process-env nil nil "update-index" "--refresh")
- (git-clear-status status)
- (git-update-status-files nil)
- ; restore file marks
- (when marked-files
- (git-status-filenames-map status
- (lambda (info)
- (setf (git-fileinfo->marked info) t)
- (setf (git-fileinfo->needs-refresh info) t))
- marked-files)
- (git-refresh-files))
- ; move point to the current file name if any
- (message "Refreshing git status...done")
- (let ((node (and cur-name (git-find-status-file status cur-name))))
- (when node (ewoc-goto-node status node)))))
+ (unless git-status (error "Not in git-status buffer."))
+ (message "Refreshing git status...")
+ (git-update-status-files)
+ (message "Refreshing git status...done"))
(defun git-status-quit ()
"Quit git-status mode."
@@ -1434,6 +1449,7 @@ amended version of it."
(define-key map "\r" 'git-find-file)
(define-key map "g" 'git-refresh-status)
(define-key map "i" 'git-ignore-file)
+ (define-key map "I" 'git-insert-file)
(define-key map "l" 'git-log-file)
(define-key map "m" 'git-mark-file)
(define-key map "M" 'git-mark-all)
@@ -1490,6 +1506,7 @@ amended version of it."
["Revert File" git-revert-file t]
["Ignore File" git-ignore-file t]
["Remove File" git-remove-file t]
+ ["Insert File" git-insert-file t]
"--------"
["Find File" git-find-file t]
["View File" git-view-file t]
@@ -1576,8 +1593,8 @@ Meant to be used in `after-save-hook'."
(let ((filename (file-relative-name file dir)))
; skip files located inside the .git directory
(unless (string-match "^\\.git/" filename)
- (git-call-process-env nil nil "add" "--refresh" "--" filename)
- (git-update-status-files (list filename) 'uptodate)))))))
+ (git-call-process nil "add" "--refresh" "--" filename)
+ (git-update-status-files (list filename))))))))
(defun git-help ()
"Display help for Git mode."
diff --git a/contrib/examples/README b/contrib/examples/README
new file mode 100644
index 0000000000..6946f3dd2a
--- /dev/null
+++ b/contrib/examples/README
@@ -0,0 +1,3 @@
+These are original scripted implementations, kept primarily for their
+reference value to any aspiring plumbing users who want to learn how
+pieces can be fit together.
diff --git a/contrib/examples/git-remote.perl b/contrib/examples/git-remote.perl
index 36bd54c985..b17952a785 100755
--- a/contrib/examples/git-remote.perl
+++ b/contrib/examples/git-remote.perl
@@ -309,7 +309,7 @@ sub update_remote {
}
}
} else {
- print STDERR "Remote group $name does not exists.\n";
+ print STDERR "Remote group $name does not exist.\n";
exit(1);
}
for (@remotes) {
diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4
index 2216cacba7..a85a7b2a58 100755
--- a/contrib/fast-import/git-p4
+++ b/contrib/fast-import/git-p4
@@ -245,7 +245,22 @@ def p4Cmd(cmd):
def p4Where(depotPath):
if not depotPath.endswith("/"):
depotPath += "/"
- output = p4Cmd("where %s..." % depotPath)
+ depotPath = depotPath + "..."
+ outputList = p4CmdList("where %s" % depotPath)
+ output = None
+ for entry in outputList:
+ if "depotFile" in entry:
+ if entry["depotFile"] == depotPath:
+ output = entry
+ break
+ elif "data" in entry:
+ data = entry.get("data")
+ space = data.find(" ")
+ if data[:space] == depotPath:
+ output = entry
+ break
+ if output == None:
+ return ""
if output["code"] == "error":
return ""
clientPath = ""
@@ -316,8 +331,11 @@ def gitBranchExists(branch):
stderr=subprocess.PIPE, stdout=subprocess.PIPE);
return proc.wait() == 0;
+_gitConfig = {}
def gitConfig(key):
- return read_pipe("git config %s" % key, ignore_error=True).strip()
+ if not _gitConfig.has_key(key):
+ _gitConfig[key] = read_pipe("git config %s" % key, ignore_error=True).strip()
+ return _gitConfig[key]
def p4BranchesInGit(branchesAreInRemotes = True):
branches = {}
@@ -946,7 +964,7 @@ class P4Sync(Command):
if includeFile:
filesForCommit.append(f)
- if f['action'] != 'delete':
+ if f['action'] not in ('delete', 'purge'):
filesToRead.append(f)
filedata = []
@@ -965,11 +983,11 @@ class P4Sync(Command):
while j < len(filedata):
stat = filedata[j]
j += 1
- text = [];
+ text = ''
while j < len(filedata) and filedata[j]['code'] in ('text', 'unicode', 'binary'):
- text.append(filedata[j]['data'])
+ text += filedata[j]['data']
+ del filedata[j]['data']
j += 1
- text = ''.join(text)
if not stat.has_key('depotFile'):
sys.stderr.write("p4 print fails with: %s\n" % repr(stat))
@@ -978,7 +996,7 @@ class P4Sync(Command):
if stat['type'] in ('text+ko', 'unicode+ko', 'binary+ko'):
text = re.sub(r'(?i)\$(Id|Header):[^$]*\$',r'$\1$', text)
elif stat['type'] in ('text+k', 'ktext', 'kxtext', 'unicode+k', 'binary+k'):
- text = re.sub(r'\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$]*\$',r'$\1$', text)
+ text = re.sub(r'\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$\n]*\$',r'$\1$', text)
contents[stat['depotFile']] = text
@@ -1038,7 +1056,7 @@ class P4Sync(Command):
continue
relPath = self.stripRepoPath(file['path'], branchPrefixes)
- if file["action"] == "delete":
+ if file["action"] in ("delete", "purge"):
self.gitStream.write("D %s\n" % relPath)
else:
data = file['data']
@@ -1077,7 +1095,7 @@ class P4Sync(Command):
cleanedFiles = {}
for info in files:
- if info["action"] == "delete":
+ if info["action"] in ("delete", "purge"):
continue
cleanedFiles[info["depotFile"]] = info["rev"]
@@ -1400,7 +1418,7 @@ class P4Sync(Command):
if change > newestRevision:
newestRevision = change
- if info["action"] == "delete":
+ if info["action"] in ("delete", "purge"):
# don't increase the file cnt, otherwise details["depotFile123"] will have gaps!
#fileCnt = fileCnt + 1
continue
diff --git a/contrib/hooks/post-receive-email b/contrib/hooks/post-receive-email
index 41368950d6..28a3c0e46e 100644
--- a/contrib/hooks/post-receive-email
+++ b/contrib/hooks/post-receive-email
@@ -38,6 +38,12 @@
# hooks.emailprefix
# All emails have their subjects prefixed with this prefix, or "[SCM]"
# if emailprefix is unset, to aid filtering
+# hooks.showrev
+# The shell command used to format each revision in the email, with
+# "%s" replaced with the commit id. Defaults to "git rev-list -1
+# --pretty %s", displaying the commit id, author, date and log
+# message. To list full patches separated by a blank line, you
+# could set this to "git show -C %s; echo".
#
# Notes
# -----
@@ -224,13 +230,7 @@ generate_create_branch_email()
echo ""
echo $LOGBEGIN
- # This shows all log entries that are not already covered by
- # another ref - i.e. commits that are now accessible from this
- # ref that were previously not accessible
- # (see generate_update_branch_email for the explanation of this
- # command)
- git rev-parse --not --branches | grep -v $(git rev-parse $refname) |
- git rev-list --pretty --stdin $newrev
+ show_new_revisions
echo $LOGEND
}
@@ -390,8 +390,7 @@ generate_update_branch_email()
echo ""
echo $LOGBEGIN
- git rev-parse --not --branches | grep -v $(git rev-parse $refname) |
- git rev-list --pretty --stdin $oldrev..$newrev
+ show_new_revisions
# XXX: Need a way of detecting whether git rev-list actually
# outputted anything, so that we can issue a "no new
@@ -591,6 +590,45 @@ generate_delete_general_email()
echo $LOGEND
}
+
+# --------------- Miscellaneous utilities
+
+#
+# Show new revisions as the user would like to see them in the email.
+#
+show_new_revisions()
+{
+ # This shows all log entries that are not already covered by
+ # another ref - i.e. commits that are now accessible from this
+ # ref that were previously not accessible
+ # (see generate_update_branch_email for the explanation of this
+ # command)
+
+ # Revision range passed to rev-list differs for new vs. updated
+ # branches.
+ if [ "$change_type" = create ]
+ then
+ # Show all revisions exclusive to this (new) branch.
+ revspec=$newrev
+ else
+ # Branch update; show revisions not part of $oldrev.
+ revspec=$oldrev..$newrev
+ fi
+
+ git rev-parse --not --branches | grep -v $(git rev-parse $refname) |
+ if [ -z "$custom_showrev" ]
+ then
+ git rev-list --pretty --stdin $revspec
+ else
+ git rev-list --stdin $revspec |
+ while read onerev
+ do
+ eval $(printf "$custom_showrev" $onerev)
+ done
+ fi
+}
+
+
send_mail()
{
if [ -n "$envelopesender" ]; then
@@ -627,6 +665,7 @@ recipients=$(git config hooks.mailinglist)
announcerecipients=$(git config hooks.announcelist)
envelopesender=$(git config hooks.envelopesender)
emailprefix=$(git config hooks.emailprefix || echo '[SCM] ')
+custom_showrev=$(git config hooks.showrev)
# --- Main loop
# Allow dual mode: run from the command line just like the update hook, or
diff --git a/contrib/hooks/pre-auto-gc-battery b/contrib/hooks/pre-auto-gc-battery
index b0a8caae9e..1f914c94aa 100644
--- a/contrib/hooks/pre-auto-gc-battery
+++ b/contrib/hooks/pre-auto-gc-battery
@@ -30,6 +30,9 @@ then
elif grep -q '0x01$' /proc/apm 2>/dev/null
then
exit 0
+elif grep -q "AC Power \+: 1" /proc/pmu/info 2>/dev/null
+then
+ exit 0
elif test -x /usr/bin/pmset && /usr/bin/pmset -g batt |
grep -q "Currently drawing from 'AC Power'"
then
diff --git a/contrib/stats/packinfo.pl b/contrib/stats/packinfo.pl
index f4a7b62cd9..be188c0f11 100755
--- a/contrib/stats/packinfo.pl
+++ b/contrib/stats/packinfo.pl
@@ -1,9 +1,9 @@
#!/usr/bin/perl
#
# This tool will print vaguely pretty information about a pack. It
-# expects the output of "git-verify-pack -v" as input on stdin.
+# expects the output of "git verify-pack -v" as input on stdin.
#
-# $ git-verify-pack -v | packinfo.pl
+# $ git verify-pack -v | packinfo.pl
#
# This prints some full-pack statistics; currently "all sizes", "all
# path sizes", "tree sizes", "tree path sizes", and "depths".
@@ -20,7 +20,7 @@
#
# When run as:
#
-# $ git-verify-pack -v | packinfo.pl -tree
+# $ git verify-pack -v | packinfo.pl -tree
#
# the trees of objects are output along with the stats. This looks
# like:
@@ -43,7 +43,7 @@
#
# When run as:
#
-# $ git-verify-pack -v | packinfo.pl -tree -filenames
+# $ git verify-pack -v | packinfo.pl -tree -filenames
#
# it adds filenames to the tree. Getting this information is slow:
#
@@ -58,7 +58,7 @@
#
# When run as:
#
-# $ git-verify-pack -v | packinfo.pl -dump
+# $ git verify-pack -v | packinfo.pl -dump
#
# it prints out "sha1 size pathsize depth" for each sha1 in lexical
# order.
@@ -106,7 +106,7 @@ while (<STDIN>) {
}
if ($filenames && ($tree || $dump)) {
- open(NAMES, "git-name-rev --all|");
+ open(NAMES, "git name-rev --all|");
while (<NAMES>) {
if (/^(\S+)\s+(.*)$/) {
my ($sha1, $name) = ($1, $2);
@@ -117,7 +117,7 @@ if ($filenames && ($tree || $dump)) {
for my $commit (@commits) {
my $name = $names{$commit};
- open(TREE, "git-ls-tree -t -r $commit|");
+ open(TREE, "git ls-tree -t -r $commit|");
print STDERR "Plumbing tree $name\n";
while (<TREE>) {
if (/^(\S+)\s+(\S+)\s+(\S+)\s+(.*)$/) {
diff --git a/contrib/vim/README b/contrib/vim/README
index c487346eba..fca1e17251 100644
--- a/contrib/vim/README
+++ b/contrib/vim/README
@@ -5,11 +5,13 @@ automatically.
If you have an older version of vim, you can get the latest syntax
files from the vim project:
- http://vim.svn.sourceforge.net/viewvc/vim/trunk/runtime/syntax/git.vim
- http://vim.svn.sourceforge.net/viewvc/vim/trunk/runtime/syntax/gitcommit.vim
- http://vim.svn.sourceforge.net/viewvc/vim/trunk/runtime/syntax/gitconfig.vim
- http://vim.svn.sourceforge.net/viewvc/vim/trunk/runtime/syntax/gitrebase.vim
- http://vim.svn.sourceforge.net/viewvc/vim/trunk/runtime/syntax/gitsendemail.vim
+ http://ftp.vim.org/pub/vim/runtime/syntax/git.vim
+ http://ftp.vim.org/pub/vim/runtime/syntax/gitcommit.vim
+ http://ftp.vim.org/pub/vim/runtime/syntax/gitconfig.vim
+ http://ftp.vim.org/pub/vim/runtime/syntax/gitrebase.vim
+ http://ftp.vim.org/pub/vim/runtime/syntax/gitsendemail.vim
+
+These files are also available via FTP at the same location.
To install:
diff --git a/contrib/workdir/git-new-workdir b/contrib/workdir/git-new-workdir
index 7959eab902..993cacf324 100755
--- a/contrib/workdir/git-new-workdir
+++ b/contrib/workdir/git-new-workdir
@@ -22,7 +22,7 @@ branch=$3
# want to make sure that what is pointed to has a .git directory ...
git_dir=$(cd "$orig_git" 2>/dev/null &&
git rev-parse --git-dir 2>/dev/null) ||
- die "\"$orig_git\" is not a git repository!"
+ die "Not a git repository: \"$orig_git\""
case "$git_dir" in
.git)
diff --git a/daemon.c b/daemon.c
index 3e5582d289..540700ee84 100644
--- a/daemon.c
+++ b/daemon.c
@@ -1,7 +1,6 @@
#include "cache.h"
#include "pkt-line.h"
#include "exec_cmd.h"
-#include "interpolate.h"
#include <syslog.h>
@@ -54,26 +53,10 @@ static const char *user_path;
static unsigned int timeout;
static unsigned int init_timeout;
-/*
- * Static table for now. Ugh.
- * Feel free to make dynamic as needed.
- */
-#define INTERP_SLOT_HOST (0)
-#define INTERP_SLOT_CANON_HOST (1)
-#define INTERP_SLOT_IP (2)
-#define INTERP_SLOT_PORT (3)
-#define INTERP_SLOT_DIR (4)
-#define INTERP_SLOT_PERCENT (5)
-
-static struct interp interp_table[] = {
- { "%H", 0},
- { "%CH", 0},
- { "%IP", 0},
- { "%P", 0},
- { "%D", 0},
- { "%%", 0},
-};
-
+static char *hostname;
+static char *canon_hostname;
+static char *ip_address;
+static char *tcp_port;
static void logreport(int priority, const char *err, va_list params)
{
@@ -163,15 +146,14 @@ static int avoid_alias(char *p)
}
}
-static char *path_ok(struct interp *itable)
+static char *path_ok(char *directory)
{
static char rpath[PATH_MAX];
static char interp_path[PATH_MAX];
- int retried_path = 0;
char *path;
char *dir;
- dir = itable[INTERP_SLOT_DIR].value;
+ dir = directory;
if (avoid_alias(dir)) {
logerror("'%s': aliased", dir);
@@ -201,14 +183,27 @@ static char *path_ok(struct interp *itable)
}
}
else if (interpolated_path && saw_extended_args) {
+ struct strbuf expanded_path = STRBUF_INIT;
+ struct strbuf_expand_dict_entry dict[] = {
+ { "H", hostname },
+ { "CH", canon_hostname },
+ { "IP", ip_address },
+ { "P", tcp_port },
+ { "D", directory },
+ { "%", "%" },
+ { NULL }
+ };
+
if (*dir != '/') {
/* Allow only absolute */
logerror("'%s': Non-absolute path denied (interpolated-path active)", dir);
return NULL;
}
- interpolate(interp_path, PATH_MAX, interpolated_path,
- interp_table, ARRAY_SIZE(interp_table));
+ strbuf_expand(&expanded_path, interpolated_path,
+ strbuf_expand_dict_cb, &dict);
+ strlcpy(interp_path, expanded_path.buf, PATH_MAX);
+ strbuf_release(&expanded_path);
loginfo("Interpolated dir '%s'", interp_path);
dir = interp_path;
@@ -223,22 +218,15 @@ static char *path_ok(struct interp *itable)
dir = rpath;
}
- do {
- path = enter_repo(dir, strict_paths);
- if (path)
- break;
-
+ path = enter_repo(dir, strict_paths);
+ if (!path && base_path && base_path_relaxed) {
/*
* if we fail and base_path_relaxed is enabled, try without
* prefixing the base path
*/
- if (base_path && base_path_relaxed && !retried_path) {
- dir = itable[INTERP_SLOT_DIR].value;
- retried_path = 1;
- continue;
- }
- break;
- } while (1);
+ dir = directory;
+ path = enter_repo(dir, strict_paths);
+ }
if (!path) {
logerror("'%s': unable to chdir or not a git archive", dir);
@@ -299,14 +287,12 @@ static int git_daemon_config(const char *var, const char *value, void *cb)
return 0;
}
-static int run_service(struct interp *itable, struct daemon_service *service)
+static int run_service(char *dir, struct daemon_service *service)
{
const char *path;
int enabled = service->enabled;
- loginfo("Request %s for '%s'",
- service->name,
- itable[INTERP_SLOT_DIR].value);
+ loginfo("Request %s for '%s'", service->name, dir);
if (!enabled && !service->overridable) {
logerror("'%s': service not enabled.", service->name);
@@ -314,7 +300,7 @@ static int run_service(struct interp *itable, struct daemon_service *service)
return -1;
}
- if (!(path = path_ok(itable)))
+ if (!(path = path_ok(dir)))
return -1;
/*
@@ -411,11 +397,18 @@ static void make_service_overridable(const char *name, int ena)
die("No such service %s", name);
}
+static char *xstrdup_tolower(const char *str)
+{
+ char *p, *dup = xstrdup(str);
+ for (p = dup; *p; p++)
+ *p = tolower(*p);
+ return dup;
+}
+
/*
* Separate the "extra args" information as supplied by the client connection.
- * Any resulting data is squirreled away in the given interpolation table.
*/
-static void parse_extra_args(struct interp *table, char *extra_args, int buflen)
+static void parse_extra_args(char *extra_args, int buflen)
{
char *val;
int vallen;
@@ -433,35 +426,23 @@ static void parse_extra_args(struct interp *table, char *extra_args, int buflen)
if (port) {
*port = 0;
port++;
- interp_set_entry(table, INTERP_SLOT_PORT, port);
+ free(tcp_port);
+ tcp_port = xstrdup(port);
}
- interp_set_entry(table, INTERP_SLOT_HOST, host);
+ free(hostname);
+ hostname = xstrdup_tolower(host);
}
/* On to the next one */
extra_args = val + vallen;
}
}
-}
-
-static void fill_in_extra_table_entries(struct interp *itable)
-{
- char *hp;
-
- /*
- * Replace literal host with lowercase-ized hostname.
- */
- hp = interp_table[INTERP_SLOT_HOST].value;
- if (!hp)
- return;
- for ( ; *hp; hp++)
- *hp = tolower(*hp);
/*
* Locate canonical hostname and its IP address.
*/
+ if (hostname) {
#ifndef NO_IPV6
- {
struct addrinfo hints;
struct addrinfo *ai, *ai0;
int gai;
@@ -470,30 +451,28 @@ static void fill_in_extra_table_entries(struct interp *itable)
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME;
- gai = getaddrinfo(interp_table[INTERP_SLOT_HOST].value, 0, &hints, &ai0);
+ gai = getaddrinfo(hostname, 0, &hints, &ai0);
if (!gai) {
for (ai = ai0; ai; ai = ai->ai_next) {
struct sockaddr_in *sin_addr = (void *)ai->ai_addr;
inet_ntop(AF_INET, &sin_addr->sin_addr,
addrbuf, sizeof(addrbuf));
- interp_set_entry(interp_table,
- INTERP_SLOT_CANON_HOST, ai->ai_canonname);
- interp_set_entry(interp_table,
- INTERP_SLOT_IP, addrbuf);
+ free(canon_hostname);
+ canon_hostname = xstrdup(ai->ai_canonname);
+ free(ip_address);
+ ip_address = xstrdup(addrbuf);
break;
}
freeaddrinfo(ai0);
}
- }
#else
- {
struct hostent *hent;
struct sockaddr_in sa;
char **ap;
static char addrbuf[HOST_NAME_MAX + 1];
- hent = gethostbyname(interp_table[INTERP_SLOT_HOST].value);
+ hent = gethostbyname(hostname);
ap = hent->h_addr_list;
memset(&sa, 0, sizeof sa);
@@ -504,10 +483,12 @@ static void fill_in_extra_table_entries(struct interp *itable)
inet_ntop(hent->h_addrtype, &sa.sin_addr,
addrbuf, sizeof(addrbuf));
- interp_set_entry(interp_table, INTERP_SLOT_CANON_HOST, hent->h_name);
- interp_set_entry(interp_table, INTERP_SLOT_IP, addrbuf);
- }
+ free(canon_hostname);
+ canon_hostname = xstrdup(hent->h_name);
+ free(ip_address);
+ ip_address = xstrdup(addrbuf);
#endif
+ }
}
@@ -537,6 +518,10 @@ static int execute(struct sockaddr *addr)
#endif
}
loginfo("Connection from %s:%d", addrbuf, port);
+ setenv("REMOTE_ADDR", addrbuf, 1);
+ }
+ else {
+ unsetenv("REMOTE_ADDR");
}
alarm(init_timeout ? init_timeout : timeout);
@@ -553,16 +538,14 @@ static int execute(struct sockaddr *addr)
pktlen--;
}
- /*
- * Initialize the path interpolation table for this connection.
- */
- interp_clear_table(interp_table, ARRAY_SIZE(interp_table));
- interp_set_entry(interp_table, INTERP_SLOT_PERCENT, "%");
+ free(hostname);
+ free(canon_hostname);
+ free(ip_address);
+ free(tcp_port);
+ hostname = canon_hostname = ip_address = tcp_port = NULL;
- if (len != pktlen) {
- parse_extra_args(interp_table, line + len + 1, pktlen - len - 1);
- fill_in_extra_table_entries(interp_table);
- }
+ if (len != pktlen)
+ parse_extra_args(line + len + 1, pktlen - len - 1);
for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
struct daemon_service *s = &(daemon_service[i]);
@@ -574,9 +557,7 @@ static int execute(struct sockaddr *addr)
* Note: The directory here is probably context sensitive,
* and might depend on the actual service being performed.
*/
- interp_set_entry(interp_table,
- INTERP_SLOT_DIR, line + namelen + 5);
- return run_service(interp_table, s);
+ return run_service(line + namelen + 5, s);
}
}
@@ -735,7 +716,7 @@ static int socksetup(char *listen_addr, int listen_port, int **socklist_p)
gai = getaddrinfo(listen_addr, pbuf, &hints, &ai0);
if (gai)
- die("getaddrinfo() failed: %s\n", gai_strerror(gai));
+ die("getaddrinfo() failed: %s", gai_strerror(gai));
for (ai = ai0; ai; ai = ai->ai_next) {
int sockfd;
@@ -960,12 +941,8 @@ int main(int argc, char **argv)
char *arg = argv[i];
if (!prefixcmp(arg, "--listen=")) {
- char *p = arg + 9;
- char *ph = listen_addr = xmalloc(strlen(arg + 9) + 1);
- while (*p)
- *ph++ = tolower(*p++);
- *ph = 0;
- continue;
+ listen_addr = xstrdup_tolower(arg + 9);
+ continue;
}
if (!prefixcmp(arg, "--port=")) {
char *end;
@@ -1125,7 +1102,9 @@ int main(int argc, char **argv)
struct sockaddr *peer = (struct sockaddr *)&ss;
socklen_t slen = sizeof(ss);
- freopen("/dev/null", "w", stderr);
+ if (!freopen("/dev/null", "w", stderr))
+ die("failed to redirect stderr to /dev/null: %s",
+ strerror(errno));
if (getpeername(0, peer, &slen))
peer = NULL;
diff --git a/diff-lib.c b/diff-lib.c
index ae96c64ca2..a41e1ec07c 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -61,14 +61,12 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
int silent_on_removed = option & DIFF_SILENT_ON_REMOVED;
unsigned ce_option = ((option & DIFF_RACY_IS_MODIFIED)
? CE_MATCH_RACY_IS_DIRTY : 0);
- char symcache[PATH_MAX];
diff_set_mnemonic_prefix(&revs->diffopt, "i/", "w/");
if (diff_unmerged_stage < 0)
diff_unmerged_stage = 2;
entries = active_nr;
- symcache[0] = '\0';
for (i = 0; i < entries; i++) {
struct stat st;
unsigned int oldmode, newmode;
@@ -198,11 +196,6 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
* diff-index
*/
-struct oneway_unpack_data {
- struct rev_info *revs;
- char symcache[PATH_MAX];
-};
-
/* A file entry went away or appeared */
static void diff_index_show_file(struct rev_info *revs,
const char *prefix,
@@ -216,8 +209,7 @@ static void diff_index_show_file(struct rev_info *revs,
static int get_stat_data(struct cache_entry *ce,
const unsigned char **sha1p,
unsigned int *modep,
- int cached, int match_missing,
- struct oneway_unpack_data *cbdata)
+ int cached, int match_missing)
{
const unsigned char *sha1 = ce->sha1;
unsigned int mode = ce->ce_mode;
@@ -248,25 +240,24 @@ static int get_stat_data(struct cache_entry *ce,
return 0;
}
-static void show_new_file(struct oneway_unpack_data *cbdata,
+static void show_new_file(struct rev_info *revs,
struct cache_entry *new,
int cached, int match_missing)
{
const unsigned char *sha1;
unsigned int mode;
- struct rev_info *revs = cbdata->revs;
/*
* New file in the index: it might actually be different in
* the working copy.
*/
- if (get_stat_data(new, &sha1, &mode, cached, match_missing, cbdata) < 0)
+ if (get_stat_data(new, &sha1, &mode, cached, match_missing) < 0)
return;
diff_index_show_file(revs, "+", new, sha1, mode);
}
-static int show_modified(struct oneway_unpack_data *cbdata,
+static int show_modified(struct rev_info *revs,
struct cache_entry *old,
struct cache_entry *new,
int report_missing,
@@ -274,9 +265,8 @@ static int show_modified(struct oneway_unpack_data *cbdata,
{
unsigned int mode, oldmode;
const unsigned char *sha1;
- struct rev_info *revs = cbdata->revs;
- if (get_stat_data(new, &sha1, &mode, cached, match_missing, cbdata) < 0) {
+ if (get_stat_data(new, &sha1, &mode, cached, match_missing) < 0) {
if (report_missing)
diff_index_show_file(revs, "-", old,
old->sha1, old->ce_mode);
@@ -344,8 +334,7 @@ static void do_oneway_diff(struct unpack_trees_options *o,
struct cache_entry *idx,
struct cache_entry *tree)
{
- struct oneway_unpack_data *cbdata = o->unpack_data;
- struct rev_info *revs = cbdata->revs;
+ struct rev_info *revs = o->unpack_data;
int match_missing, cached;
/*
@@ -368,7 +357,7 @@ static void do_oneway_diff(struct unpack_trees_options *o,
* Something added to the tree?
*/
if (!tree) {
- show_new_file(cbdata, idx, cached, match_missing);
+ show_new_file(revs, idx, cached, match_missing);
return;
}
@@ -381,7 +370,7 @@ static void do_oneway_diff(struct unpack_trees_options *o,
}
/* Show difference between old and new */
- show_modified(cbdata, tree, idx, 1, cached, match_missing);
+ show_modified(revs, tree, idx, 1, cached, match_missing);
}
static inline void skip_same_name(struct cache_entry *ce, struct unpack_trees_options *o)
@@ -418,8 +407,7 @@ static int oneway_diff(struct cache_entry **src, struct unpack_trees_options *o)
{
struct cache_entry *idx = src[0];
struct cache_entry *tree = src[1];
- struct oneway_unpack_data *cbdata = o->unpack_data;
- struct rev_info *revs = cbdata->revs;
+ struct rev_info *revs = o->unpack_data;
if (idx && ce_stage(idx))
skip_same_name(idx, o);
@@ -446,7 +434,6 @@ int run_diff_index(struct rev_info *revs, int cached)
const char *tree_name;
struct unpack_trees_options opts;
struct tree_desc t;
- struct oneway_unpack_data unpack_cb;
mark_merge_entries();
@@ -456,14 +443,12 @@ int run_diff_index(struct rev_info *revs, int cached)
if (!tree)
return error("bad tree object %s", tree_name);
- unpack_cb.revs = revs;
- unpack_cb.symcache[0] = '\0';
memset(&opts, 0, sizeof(opts));
opts.head_idx = 1;
opts.index_only = cached;
opts.merge = 1;
opts.fn = oneway_diff;
- opts.unpack_data = &unpack_cb;
+ opts.unpack_data = revs;
opts.src_index = &the_index;
opts.dst_index = NULL;
@@ -486,7 +471,6 @@ int do_diff_cache(const unsigned char *tree_sha1, struct diff_options *opt)
struct cache_entry *last = NULL;
struct unpack_trees_options opts;
struct tree_desc t;
- struct oneway_unpack_data unpack_cb;
/*
* This is used by git-blame to run diff-cache internally;
@@ -515,14 +499,12 @@ int do_diff_cache(const unsigned char *tree_sha1, struct diff_options *opt)
if (!tree)
die("bad tree object %s", sha1_to_hex(tree_sha1));
- unpack_cb.revs = &revs;
- unpack_cb.symcache[0] = '\0';
memset(&opts, 0, sizeof(opts));
opts.head_idx = 1;
opts.index_only = 1;
opts.merge = 1;
opts.fn = oneway_diff;
- opts.unpack_data = &unpack_cb;
+ opts.unpack_data = &revs;
opts.src_index = &the_index;
opts.dst_index = &the_index;
diff --git a/diff.c b/diff.c
index 1c6be897b2..d23548292a 100644
--- a/diff.c
+++ b/diff.c
@@ -11,6 +11,7 @@
#include "attr.h"
#include "run-command.h"
#include "utf8.h"
+#include "userdiff.h"
#ifdef NO_FAST_WORKING_DIRECTORY
#define FAST_WORKING_DIRECTORY 0
@@ -37,6 +38,9 @@ static char diff_colors[][COLOR_MAXLEN] = {
"\033[41m", /* WHITESPACE (red background) */
};
+static void diff_filespec_load_driver(struct diff_filespec *one);
+static char *run_textconv(const char *, struct diff_filespec *, size_t *);
+
static int parse_diff_color_slot(const char *var, int ofs)
{
if (!strcasecmp(var+ofs, "plain"))
@@ -56,80 +60,6 @@ static int parse_diff_color_slot(const char *var, int ofs)
die("bad config variable '%s'", var);
}
-static struct ll_diff_driver {
- const char *name;
- struct ll_diff_driver *next;
- const char *cmd;
-} *user_diff, **user_diff_tail;
-
-/*
- * Currently there is only "diff.<drivername>.command" variable;
- * because there are "diff.color.<slot>" variables, we are parsing
- * this in a bit convoluted way to allow low level diff driver
- * called "color".
- */
-static int parse_lldiff_command(const char *var, const char *ep, const char *value)
-{
- const char *name;
- int namelen;
- struct ll_diff_driver *drv;
-
- name = var + 5;
- namelen = ep - name;
- for (drv = user_diff; drv; drv = drv->next)
- if (!strncmp(drv->name, name, namelen) && !drv->name[namelen])
- break;
- if (!drv) {
- drv = xcalloc(1, sizeof(struct ll_diff_driver));
- drv->name = xmemdupz(name, namelen);
- if (!user_diff_tail)
- user_diff_tail = &user_diff;
- *user_diff_tail = drv;
- user_diff_tail = &(drv->next);
- }
-
- return git_config_string(&(drv->cmd), var, value);
-}
-
-/*
- * 'diff.<what>.funcname' attribute can be specified in the configuration
- * to define a customized regexp to find the beginning of a function to
- * be used for hunk header lines of "diff -p" style output.
- */
-struct funcname_pattern_entry {
- char *name;
- char *pattern;
- int cflags;
-};
-static struct funcname_pattern_list {
- struct funcname_pattern_list *next;
- struct funcname_pattern_entry e;
-} *funcname_pattern_list;
-
-static int parse_funcname_pattern(const char *var, const char *ep, const char *value, int cflags)
-{
- const char *name;
- int namelen;
- struct funcname_pattern_list *pp;
-
- name = var + 5; /* "diff." */
- namelen = ep - name;
-
- for (pp = funcname_pattern_list; pp; pp = pp->next)
- if (!strncmp(pp->e.name, name, namelen) && !pp->e.name[namelen])
- break;
- if (!pp) {
- pp = xcalloc(1, sizeof(*pp));
- pp->e.name = xmemdupz(name, namelen);
- pp->next = funcname_pattern_list;
- funcname_pattern_list = pp;
- }
- free(pp->e.pattern);
- pp->e.pattern = xstrdup(value);
- pp->e.cflags = cflags;
- return 0;
-}
-
/*
* These are to give UI layer defaults.
* The core-level commands such as git-diff-files should
@@ -162,12 +92,6 @@ int git_diff_ui_config(const char *var, const char *value, void *cb)
}
if (!strcmp(var, "diff.external"))
return git_config_string(&external_diff_cmd_cfg, var, value);
- if (!prefixcmp(var, "diff.")) {
- const char *ep = strrchr(var, '.');
-
- if (ep != var + 4 && !strcmp(ep, ".command"))
- return parse_lldiff_command(var, ep, value);
- }
return git_diff_basic_config(var, value, cb);
}
@@ -179,6 +103,12 @@ int git_diff_basic_config(const char *var, const char *value, void *cb)
return 0;
}
+ switch (userdiff_config(var, value)) {
+ case 0: break;
+ case -1: return -1;
+ default: return 0;
+ }
+
if (!prefixcmp(var, "diff.color.") || !prefixcmp(var, "color.diff.")) {
int slot = parse_diff_color_slot(var, 11);
if (!value)
@@ -193,23 +123,6 @@ int git_diff_basic_config(const char *var, const char *value, void *cb)
return 0;
}
- if (!prefixcmp(var, "diff.")) {
- const char *ep = strrchr(var, '.');
- if (ep != var + 4) {
- if (!strcmp(ep, ".funcname")) {
- if (!value)
- return config_error_nonbool(var);
- return parse_funcname_pattern(var, ep, value,
- 0);
- } else if (!strcmp(ep, ".xfuncname")) {
- if (!value)
- return config_error_nonbool(var);
- return parse_funcname_pattern(var, ep, value,
- REG_EXTENDED);
- }
- }
- }
-
return git_color_default_config(var, value, cb);
}
@@ -316,6 +229,8 @@ static void emit_rewrite_diff(const char *name_a,
const char *name_b,
struct diff_filespec *one,
struct diff_filespec *two,
+ const char *textconv_one,
+ const char *textconv_two,
struct diff_options *o)
{
int lc_a, lc_b;
@@ -328,6 +243,8 @@ static void emit_rewrite_diff(const char *name_a,
const char *reset = diff_get_color(color_diff, DIFF_RESET);
static struct strbuf a_name = STRBUF_INIT, b_name = STRBUF_INIT;
const char *a_prefix, *b_prefix;
+ const char *data_one, *data_two;
+ size_t size_one, size_two;
if (diff_mnemonic_prefix && DIFF_OPT_TST(o, REVERSE_DIFF)) {
a_prefix = o->b_prefix;
@@ -349,8 +266,27 @@ static void emit_rewrite_diff(const char *name_a,
diff_populate_filespec(one, 0);
diff_populate_filespec(two, 0);
- lc_a = count_lines(one->data, one->size);
- lc_b = count_lines(two->data, two->size);
+ if (textconv_one) {
+ data_one = run_textconv(textconv_one, one, &size_one);
+ if (!data_one)
+ die("unable to read files to diff");
+ }
+ else {
+ data_one = one->data;
+ size_one = one->size;
+ }
+ if (textconv_two) {
+ data_two = run_textconv(textconv_two, two, &size_two);
+ if (!data_two)
+ die("unable to read files to diff");
+ }
+ else {
+ data_two = two->data;
+ size_two = two->size;
+ }
+
+ lc_a = count_lines(data_one, size_one);
+ lc_b = count_lines(data_two, size_two);
fprintf(o->file,
"%s--- %s%s%s\n%s+++ %s%s%s\n%s@@ -",
metainfo, a_name.buf, name_a_tab, reset,
@@ -360,9 +296,9 @@ static void emit_rewrite_diff(const char *name_a,
print_line_count(o->file, lc_b);
fprintf(o->file, " @@%s\n", reset);
if (lc_a)
- copy_file_with_prefix(o->file, '-', one->data, one->size, old, reset);
+ copy_file_with_prefix(o->file, '-', data_one, size_one, old, reset);
if (lc_b)
- copy_file_with_prefix(o->file, '+', two->data, two->size, new, reset);
+ copy_file_with_prefix(o->file, '+', data_two, size_two, new, reset);
}
static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one)
@@ -374,6 +310,7 @@ static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one)
}
else if (diff_populate_filespec(one, 0))
return -1;
+
mf->ptr = one->data;
mf->size = one->size;
return 0;
@@ -470,6 +407,7 @@ static void diff_words_show(struct diff_words_data *diff_words)
mmfile_t minus, plus;
int i;
+ memset(&xpp, 0, sizeof(xpp));
memset(&xecfg, 0, sizeof(xecfg));
minus.size = diff_words->minus.text.size;
minus.ptr = xmalloc(minus.size);
@@ -1352,136 +1290,37 @@ static void emit_binary_diff(FILE *file, mmfile_t *one, mmfile_t *two)
emit_binary_diff_body(file, two, one);
}
-static void setup_diff_attr_check(struct git_attr_check *check)
-{
- static struct git_attr *attr_diff;
-
- if (!attr_diff) {
- attr_diff = git_attr("diff", 4);
- }
- check[0].attr = attr_diff;
-}
-
-static void diff_filespec_check_attr(struct diff_filespec *one)
+static void diff_filespec_load_driver(struct diff_filespec *one)
{
- struct git_attr_check attr_diff_check;
- int check_from_data = 0;
-
- if (one->checked_attr)
- return;
-
- setup_diff_attr_check(&attr_diff_check);
- one->is_binary = 0;
- one->funcname_pattern_ident = NULL;
-
- if (!git_checkattr(one->path, 1, &attr_diff_check)) {
- const char *value;
-
- /* binaryness */
- value = attr_diff_check.value;
- if (ATTR_TRUE(value))
- ;
- else if (ATTR_FALSE(value))
- one->is_binary = 1;
- else
- check_from_data = 1;
-
- /* funcname pattern ident */
- if (ATTR_TRUE(value) || ATTR_FALSE(value) || ATTR_UNSET(value))
- ;
- else
- one->funcname_pattern_ident = value;
- }
-
- if (check_from_data) {
- if (!one->data && DIFF_FILE_VALID(one))
- diff_populate_filespec(one, 0);
-
- if (one->data)
- one->is_binary = buffer_is_binary(one->data, one->size);
- }
+ if (!one->driver)
+ one->driver = userdiff_find_by_path(one->path);
+ if (!one->driver)
+ one->driver = userdiff_find_by_name("default");
}
int diff_filespec_is_binary(struct diff_filespec *one)
{
- diff_filespec_check_attr(one);
+ if (one->is_binary == -1) {
+ diff_filespec_load_driver(one);
+ if (one->driver->binary != -1)
+ one->is_binary = one->driver->binary;
+ else {
+ if (!one->data && DIFF_FILE_VALID(one))
+ diff_populate_filespec(one, 0);
+ if (one->data)
+ one->is_binary = buffer_is_binary(one->data,
+ one->size);
+ if (one->is_binary == -1)
+ one->is_binary = 0;
+ }
+ }
return one->is_binary;
}
-static const struct funcname_pattern_entry *funcname_pattern(const char *ident)
-{
- struct funcname_pattern_list *pp;
-
- for (pp = funcname_pattern_list; pp; pp = pp->next)
- if (!strcmp(ident, pp->e.name))
- return &pp->e;
- return NULL;
-}
-
-static const struct funcname_pattern_entry builtin_funcname_pattern[] = {
- { "bibtex", "(@[a-zA-Z]{1,}[ \t]*\\{{0,1}[ \t]*[^ \t\"@',\\#}{~%]*).*$",
- REG_EXTENDED },
- { "html", "^[ \t]*(<[Hh][1-6][ \t].*>.*)$", REG_EXTENDED },
- { "java",
- "!^[ \t]*(catch|do|for|if|instanceof|new|return|switch|throw|while)\n"
- "^[ \t]*(([ \t]*[A-Za-z_][A-Za-z_0-9]*){2,}[ \t]*\\([^;]*)$",
- REG_EXTENDED },
- { "objc",
- /* Negate C statements that can look like functions */
- "!^[ \t]*(do|for|if|else|return|switch|while)\n"
- /* Objective-C methods */
- "^[ \t]*([-+][ \t]*\\([ \t]*[A-Za-z_][A-Za-z_0-9* \t]*\\)[ \t]*[A-Za-z_].*)$\n"
- /* C functions */
- "^[ \t]*(([ \t]*[A-Za-z_][A-Za-z_0-9]*){2,}[ \t]*\\([^;]*)$\n"
- /* Objective-C class/protocol definitions */
- "^(@(implementation|interface|protocol)[ \t].*)$",
- REG_EXTENDED },
- { "pascal",
- "^((procedure|function|constructor|destructor|interface|"
- "implementation|initialization|finalization)[ \t]*.*)$"
- "\n"
- "^(.*=[ \t]*(class|record).*)$",
- REG_EXTENDED },
- { "php", "^[\t ]*((function|class).*)", REG_EXTENDED },
- { "python", "^[ \t]*((class|def)[ \t].*)$", REG_EXTENDED },
- { "ruby", "^[ \t]*((class|module|def)[ \t].*)$",
- REG_EXTENDED },
- { "tex",
- "^(\\\\((sub)*section|chapter|part)\\*{0,1}\\{.*)$",
- REG_EXTENDED },
-};
-
-static const struct funcname_pattern_entry *diff_funcname_pattern(struct diff_filespec *one)
+static const struct userdiff_funcname *diff_funcname_pattern(struct diff_filespec *one)
{
- const char *ident;
- const struct funcname_pattern_entry *pe;
- int i;
-
- diff_filespec_check_attr(one);
- ident = one->funcname_pattern_ident;
-
- if (!ident)
- /*
- * If the config file has "funcname.default" defined, that
- * regexp is used; otherwise NULL is returned and xemit uses
- * the built-in default.
- */
- return funcname_pattern("default");
-
- /* Look up custom "funcname.$ident" regexp from config. */
- pe = funcname_pattern(ident);
- if (pe)
- return pe;
-
- /*
- * And define built-in fallback patterns here. Note that
- * these can be overridden by the user's config settings.
- */
- for (i = 0; i < ARRAY_SIZE(builtin_funcname_pattern); i++)
- if (!strcmp(ident, builtin_funcname_pattern[i].name))
- return &builtin_funcname_pattern[i];
-
- return NULL;
+ diff_filespec_load_driver(one);
+ return one->driver->funcname.pattern ? &one->driver->funcname : NULL;
}
void diff_set_mnemonic_prefix(struct diff_options *options, const char *a, const char *b)
@@ -1492,6 +1331,16 @@ void diff_set_mnemonic_prefix(struct diff_options *options, const char *a, const
options->b_prefix = b;
}
+static const char *get_textconv(struct diff_filespec *one)
+{
+ if (!DIFF_FILE_VALID(one))
+ return NULL;
+ if (!S_ISREG(one->mode))
+ return NULL;
+ diff_filespec_load_driver(one);
+ return one->driver->textconv;
+}
+
static void builtin_diff(const char *name_a,
const char *name_b,
struct diff_filespec *one,
@@ -1506,6 +1355,12 @@ static void builtin_diff(const char *name_a,
const char *set = diff_get_color_opt(o, DIFF_METAINFO);
const char *reset = diff_get_color_opt(o, DIFF_RESET);
const char *a_prefix, *b_prefix;
+ const char *textconv_one = NULL, *textconv_two = NULL;
+
+ if (DIFF_OPT_TST(o, ALLOW_TEXTCONV)) {
+ textconv_one = get_textconv(one);
+ textconv_two = get_textconv(two);
+ }
diff_set_mnemonic_prefix(o, "a/", "b/");
if (DIFF_OPT_TST(o, REVERSE_DIFF)) {
@@ -1549,8 +1404,11 @@ static void builtin_diff(const char *name_a,
*/
if ((one->mode ^ two->mode) & S_IFMT)
goto free_ab_and_return;
- if (complete_rewrite) {
- emit_rewrite_diff(name_a, name_b, one, two, o);
+ if (complete_rewrite &&
+ (textconv_one || !diff_filespec_is_binary(one)) &&
+ (textconv_two || !diff_filespec_is_binary(two))) {
+ emit_rewrite_diff(name_a, name_b, one, two,
+ textconv_one, textconv_two, o);
o->found_changes = 1;
goto free_ab_and_return;
}
@@ -1560,7 +1418,8 @@ static void builtin_diff(const char *name_a,
die("unable to read files to diff");
if (!DIFF_OPT_TST(o, TEXT) &&
- (diff_filespec_is_binary(one) || diff_filespec_is_binary(two))) {
+ ( (diff_filespec_is_binary(one) && !textconv_one) ||
+ (diff_filespec_is_binary(two) && !textconv_two) )) {
/* Quite common confusing case */
if (mf1.size == mf2.size &&
!memcmp(mf1.ptr, mf2.ptr, mf1.size))
@@ -1579,12 +1438,28 @@ static void builtin_diff(const char *name_a,
xdemitconf_t xecfg;
xdemitcb_t ecb;
struct emit_callback ecbdata;
- const struct funcname_pattern_entry *pe;
+ const struct userdiff_funcname *pe;
+
+ if (textconv_one) {
+ size_t size;
+ mf1.ptr = run_textconv(textconv_one, one, &size);
+ if (!mf1.ptr)
+ die("unable to read files to diff");
+ mf1.size = size;
+ }
+ if (textconv_two) {
+ size_t size;
+ mf2.ptr = run_textconv(textconv_two, two, &size);
+ if (!mf2.ptr)
+ die("unable to read files to diff");
+ mf2.size = size;
+ }
pe = diff_funcname_pattern(one);
if (!pe)
pe = diff_funcname_pattern(two);
+ memset(&xpp, 0, sizeof(xpp));
memset(&xecfg, 0, sizeof(xecfg));
memset(&ecbdata, 0, sizeof(ecbdata));
ecbdata.label_path = lbl;
@@ -1594,6 +1469,7 @@ static void builtin_diff(const char *name_a,
ecbdata.file = o->file;
xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
xecfg.ctxlen = o->context;
+ xecfg.interhunkctxlen = o->interhunkcontext;
xecfg.flags = XDL_EMIT_FUNCNAMES;
if (pe)
xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags);
@@ -1612,6 +1488,10 @@ static void builtin_diff(const char *name_a,
&xpp, &xecfg, &ecb);
if (DIFF_OPT_TST(o, COLOR_DIFF_WORDS))
free_diff_words_data(&ecbdata);
+ if (textconv_one)
+ free(mf1.ptr);
+ if (textconv_two)
+ free(mf2.ptr);
}
free_ab_and_return:
@@ -1658,6 +1538,7 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
xdemitconf_t xecfg;
xdemitcb_t ecb;
+ memset(&xpp, 0, sizeof(xpp));
memset(&xecfg, 0, sizeof(xecfg));
xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
xdi_diff_outf(&mf1, &mf2, diffstat_consume, diffstat,
@@ -1704,6 +1585,7 @@ static void builtin_checkdiff(const char *name_a, const char *name_b,
xdemitconf_t xecfg;
xdemitcb_t ecb;
+ memset(&xpp, 0, sizeof(xpp));
memset(&xecfg, 0, sizeof(xecfg));
xecfg.ctxlen = 1; /* at least one context line */
xpp.flags = XDF_NEED_MINIMAL;
@@ -1733,6 +1615,7 @@ struct diff_filespec *alloc_filespec(const char *path)
spec->path = (char *)(spec + 1);
memcpy(spec->path, path, namelen+1);
spec->count = 1;
+ spec->is_binary = -1;
return spec;
}
@@ -1891,19 +1774,18 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)
s->size = xsize_t(st.st_size);
if (!s->size)
goto empty;
- if (size_only)
- return 0;
if (S_ISLNK(st.st_mode)) {
- int ret;
- s->data = xmalloc(s->size);
- s->should_free = 1;
- ret = readlink(s->path, s->data, s->size);
- if (ret < 0) {
- free(s->data);
+ struct strbuf sb = STRBUF_INIT;
+
+ if (strbuf_readlink(&sb, s->path, s->size))
goto err_empty;
- }
+ s->size = sb.len;
+ s->data = strbuf_detach(&sb, NULL);
+ s->should_free = 1;
return 0;
}
+ if (size_only)
+ return 0;
fd = open(s->path, O_RDONLY);
if (fd < 0)
goto err_empty;
@@ -2001,13 +1883,12 @@ static void prepare_temp_file(const char *name,
if (S_ISLNK(st.st_mode)) {
int ret;
char buf[PATH_MAX + 1]; /* ought to be SYMLINK_MAX */
- size_t sz = xsize_t(st.st_size);
- if (sizeof(buf) <= st.st_size)
- die("symlink too long: %s", name);
- ret = readlink(name, buf, sz);
+ ret = readlink(name, buf, sizeof(buf));
if (ret < 0)
die("readlink(%s)", name);
- prep_temp_blob(temp, buf, sz,
+ if (ret == sizeof(buf))
+ die("symlink too long: %s", name);
+ prep_temp_blob(temp, buf, ret,
(one->sha1_valid ?
one->sha1 : null_sha1),
(one->sha1_valid ?
@@ -2117,29 +1998,6 @@ static void run_external_diff(const char *pgm,
}
}
-static const char *external_diff_attr(const char *name)
-{
- struct git_attr_check attr_diff_check;
-
- if (!name)
- return NULL;
-
- setup_diff_attr_check(&attr_diff_check);
- if (!git_checkattr(name, 1, &attr_diff_check)) {
- const char *value = attr_diff_check.value;
- if (!ATTR_TRUE(value) &&
- !ATTR_FALSE(value) &&
- !ATTR_UNSET(value)) {
- struct ll_diff_driver *drv;
-
- for (drv = user_diff; drv; drv = drv->next)
- if (!strcmp(drv->name, value))
- return drv->cmd;
- }
- }
- return NULL;
-}
-
static void run_diff_cmd(const char *pgm,
const char *name,
const char *other,
@@ -2153,9 +2011,9 @@ static void run_diff_cmd(const char *pgm,
if (!DIFF_OPT_TST(o, ALLOW_EXTERNAL))
pgm = NULL;
else {
- const char *cmd = external_diff_attr(attr_path);
- if (cmd)
- pgm = cmd;
+ struct userdiff_driver *drv = userdiff_find_by_path(attr_path);
+ if (drv && drv->external)
+ pgm = drv->external;
}
if (pgm) {
@@ -2182,7 +2040,7 @@ static void diff_fill_sha1_info(struct diff_filespec *one)
if (lstat(one->path, &st) < 0)
die("stat %s", one->path);
if (index_path(one->sha1, one->path, &st, 0))
- die("cannot hash %s\n", one->path);
+ die("cannot hash %s", one->path);
}
}
else
@@ -2644,6 +2502,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
DIFF_OPT_SET(options, ALLOW_EXTERNAL);
else if (!strcmp(arg, "--no-ext-diff"))
DIFF_OPT_CLR(options, ALLOW_EXTERNAL);
+ else if (!strcmp(arg, "--textconv"))
+ DIFF_OPT_SET(options, ALLOW_TEXTCONV);
+ else if (!strcmp(arg, "--no-textconv"))
+ DIFF_OPT_CLR(options, ALLOW_TEXTCONV);
else if (!strcmp(arg, "--ignore-submodules"))
DIFF_OPT_SET(options, IGNORE_SUBMODULES);
@@ -2677,6 +2539,9 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
options->b_prefix = arg + 13;
else if (!strcmp(arg, "--no-prefix"))
options->a_prefix = options->b_prefix = "";
+ else if (opt_arg(arg, '\0', "inter-hunk-context",
+ &options->interhunkcontext))
+ ;
else if (!prefixcmp(arg, "--output=")) {
options->file = fopen(arg + strlen("--output="), "w");
options->close_file = 1;
@@ -3149,6 +3014,7 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1)
struct diff_filepair *p = q->queue[i];
int len1, len2;
+ memset(&xpp, 0, sizeof(xpp));
memset(&xecfg, 0, sizeof(xecfg));
if (p->status == 0)
return error("internal diff status error");
@@ -3578,3 +3444,34 @@ void diff_unmerge(struct diff_options *options,
fill_filespec(one, sha1, mode);
diff_queue(&diff_queued_diff, one, two)->is_unmerged = 1;
}
+
+static char *run_textconv(const char *pgm, struct diff_filespec *spec,
+ size_t *outsize)
+{
+ struct diff_tempfile temp;
+ const char *argv[3];
+ const char **arg = argv;
+ struct child_process child;
+ struct strbuf buf = STRBUF_INIT;
+
+ prepare_temp_file(spec->path, &temp, spec);
+ *arg++ = pgm;
+ *arg++ = temp.name;
+ *arg = NULL;
+
+ memset(&child, 0, sizeof(child));
+ child.argv = argv;
+ child.out = -1;
+ if (start_command(&child) != 0 ||
+ strbuf_read(&buf, child.out, 0) < 0 ||
+ finish_command(&child) != 0) {
+ if (temp.name == temp.tmp_path)
+ unlink(temp.name);
+ error("error running textconv command '%s'", pgm);
+ return NULL;
+ }
+ if (temp.name == temp.tmp_path)
+ unlink(temp.name);
+
+ return strbuf_detach(&buf, outsize);
+}
diff --git a/diff.h b/diff.h
index a49d865bd9..4d5a32781d 100644
--- a/diff.h
+++ b/diff.h
@@ -65,6 +65,7 @@ typedef void (*diff_format_fn_t)(struct diff_queue_struct *q,
#define DIFF_OPT_IGNORE_SUBMODULES (1 << 18)
#define DIFF_OPT_DIRSTAT_CUMULATIVE (1 << 19)
#define DIFF_OPT_DIRSTAT_BY_FILE (1 << 20)
+#define DIFF_OPT_ALLOW_TEXTCONV (1 << 21)
#define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag)
#define DIFF_OPT_SET(opts, flag) ((opts)->flags |= DIFF_OPT_##flag)
#define DIFF_OPT_CLR(opts, flag) ((opts)->flags &= ~DIFF_OPT_##flag)
@@ -77,6 +78,7 @@ struct diff_options {
const char *a_prefix, *b_prefix;
unsigned flags;
int context;
+ int interhunkcontext;
int break_opt;
int detect_rename;
int skip_stat_unmatch;
diff --git a/diffcore-rename.c b/diffcore-rename.c
index 1b2ebb4001..168a95b541 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -493,7 +493,7 @@ void diffcore_rename(struct diff_options *options)
if ((num_create > rename_limit && num_src > rename_limit) ||
(num_create * num_src > rename_limit * rename_limit)) {
if (options->warn_on_too_large_rename)
- warning("too many files, skipping inexact rename detection");
+ warning("too many files (created: %d deleted: %d), skipping inexact rename detection", num_create, num_src);
goto cleanup;
}
diff --git a/diffcore.h b/diffcore.h
index 8ae35785fd..5b634585e8 100644
--- a/diffcore.h
+++ b/diffcore.h
@@ -22,6 +22,8 @@
#define MINIMUM_BREAK_SIZE 400 /* do not break a file smaller than this */
+struct userdiff_driver;
+
struct diff_filespec {
unsigned char sha1[20];
char *path;
@@ -40,8 +42,10 @@ struct diff_filespec {
#define DIFF_FILE_VALID(spec) (((spec)->mode) != 0)
unsigned should_free : 1; /* data should be free()'ed */
unsigned should_munmap : 1; /* data should be munmap()'ed */
- unsigned checked_attr : 1;
- unsigned is_binary : 1; /* data should be considered "binary" */
+
+ struct userdiff_driver *driver;
+ /* data should be considered "binary"; -1 means "don't know yet" */
+ int is_binary;
};
extern struct diff_filespec *alloc_filespec(const char *);
@@ -58,7 +62,7 @@ struct diff_filepair {
struct diff_filespec *one;
struct diff_filespec *two;
unsigned short int score;
- char status; /* M C R N D U (see Documentation/diff-format.txt) */
+ char status; /* M C R A D U etc. (see Documentation/diff-format.txt or DIFF_STATUS_* in diff.h) */
unsigned broken_pair : 1;
unsigned renamed_pair : 1;
unsigned is_unmerged : 1;
diff --git a/environment.c b/environment.c
index 0693cd9a42..e278bce0ea 100644
--- a/environment.c
+++ b/environment.c
@@ -43,6 +43,9 @@ unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;
enum rebase_setup_type autorebase = AUTOREBASE_NEVER;
+/* Parallel index stat data preload? */
+int core_preload_index = 0;
+
/* This is set by setup_git_dir_gently() and/or git_default_config() */
char *git_work_tree_cfg;
static char *work_tree;
@@ -71,7 +74,7 @@ static void setup_git_env(void)
}
git_graft_file = getenv(GRAFT_ENVIRONMENT);
if (!git_graft_file)
- git_graft_file = xstrdup(git_path("info/grafts"));
+ git_graft_file = git_pathdup("info/grafts");
}
int is_bare_repository(void)
@@ -118,7 +121,7 @@ const char *get_git_work_tree(void)
work_tree = git_work_tree_cfg;
/* make_absolute_path also normalizes the path */
if (work_tree && !is_absolute_path(work_tree))
- work_tree = xstrdup(make_absolute_path(git_path(work_tree)));
+ work_tree = xstrdup(make_absolute_path(git_path("%s", work_tree)));
} else if (work_tree)
work_tree = xstrdup(make_absolute_path(work_tree));
git_work_tree_initialized = 1;
diff --git a/fast-import.c b/fast-import.c
index 3c035a5788..f0e08aca70 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -43,7 +43,7 @@ Format of STDIN stream:
new_tag ::= 'tag' sp tag_str lf
'from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf
- 'tagger' sp name '<' email '>' when lf
+ ('tagger' sp name '<' email '>' when lf)?
tag_msg;
tag_msg ::= data;
@@ -554,6 +554,10 @@ static void *pool_alloc(size_t len)
struct mem_pool *p;
void *r;
+ /* round up to a 'uintmax_t' alignment */
+ if (len & (sizeof(uintmax_t) - 1))
+ len += sizeof(uintmax_t) - (len & (sizeof(uintmax_t) - 1));
+
for (p = mem_pool; p; p = p->next_pool)
if ((p->end - p->next_free >= len))
break;
@@ -572,9 +576,6 @@ static void *pool_alloc(size_t len)
}
r = p->next_free;
- /* round out to a 'uintmax_t' alignment */
- if (len & (sizeof(uintmax_t) - 1))
- len += sizeof(uintmax_t) - (len & (sizeof(uintmax_t) - 1));
p->next_free += len;
return r;
}
@@ -982,8 +983,10 @@ static void end_packfile(void)
pack_id++;
}
- else
+ else {
+ close(old_p->pack_fd);
unlink(old_p->pack_name);
+ }
free(old_p);
/* We can't carry a delta across packfiles. */
@@ -1745,9 +1748,12 @@ static int validate_raw_date(const char *src, char *result, int maxlen)
{
const char *orig_src = src;
char *endp, sign;
+ unsigned long date;
+
+ errno = 0;
- strtoul(src, &endp, 10);
- if (endp == src || *endp != ' ')
+ date = strtoul(src, &endp, 10);
+ if (errno || endp == src || *endp != ' ')
return -1;
src = endp + 1;
@@ -1755,8 +1761,8 @@ static int validate_raw_date(const char *src, char *result, int maxlen)
return -1;
sign = *src;
- strtoul(src + 1, &endp, 10);
- if (endp == src || *endp || (endp - orig_src) >= maxlen)
+ date = strtoul(src + 1, &endp, 10);
+ if (errno || endp == src || *endp || (endp - orig_src) >= maxlen)
return -1;
strcpy(result, orig_src);
@@ -1866,12 +1872,13 @@ static void file_change_m(struct branch *b)
if (!p)
die("Corrupt mode: %s", command_buf.buf);
switch (mode) {
+ case 0644:
+ case 0755:
+ mode |= S_IFREG;
case S_IFREG | 0644:
case S_IFREG | 0755:
case S_IFLNK:
case S_IFGITLINK:
- case 0644:
- case 0755:
/* ok */
break;
default:
@@ -1938,7 +1945,7 @@ static void file_change_m(struct branch *b)
typename(type), command_buf.buf);
}
- tree_content_set(&b->branch_tree, p, sha1, S_IFREG | mode, NULL);
+ tree_content_set(&b->branch_tree, p, sha1, mode, NULL);
}
static void file_change_d(struct branch *b)
@@ -2262,23 +2269,27 @@ static void parse_new_tag(void)
read_next_command();
/* tagger ... */
- if (prefixcmp(command_buf.buf, "tagger "))
- die("Expected tagger command, got %s", command_buf.buf);
- tagger = parse_ident(command_buf.buf + 7);
+ if (!prefixcmp(command_buf.buf, "tagger ")) {
+ tagger = parse_ident(command_buf.buf + 7);
+ read_next_command();
+ } else
+ tagger = NULL;
/* tag payload/message */
- read_next_command();
parse_data(&msg);
/* build the tag object */
strbuf_reset(&new_data);
+
strbuf_addf(&new_data,
- "object %s\n"
- "type %s\n"
- "tag %s\n"
- "tagger %s\n"
- "\n",
- sha1_to_hex(sha1), commit_type, t->name, tagger);
+ "object %s\n"
+ "type %s\n"
+ "tag %s\n",
+ sha1_to_hex(sha1), commit_type, t->name);
+ if (tagger)
+ strbuf_addf(&new_data,
+ "tagger %s\n", tagger);
+ strbuf_addch(&new_data, '\n');
strbuf_addbuf(&new_data, &msg);
free(tagger);
diff --git a/fsck.c b/fsck.c
index 0cf5f012bd..97f76c5815 100644
--- a/fsck.c
+++ b/fsck.c
@@ -326,7 +326,7 @@ int fsck_error_function(struct object *obj, int type, const char *fmt, ...)
die("this should not happen, your snprintf is broken");
}
- error(sb.buf);
+ error("%s", sb.buf);
strbuf_release(&sb);
return 1;
}
diff --git a/generate-cmdlist.sh b/generate-cmdlist.sh
index a2913c2a2c..75c68d948f 100755
--- a/generate-cmdlist.sh
+++ b/generate-cmdlist.sh
@@ -14,7 +14,7 @@ sort |
while read cmd
do
sed -n '
- /NAME/,/git-'"$cmd"'/H
+ /^NAME/,/git-'"$cmd"'/H
${
x
s/.*git-'"$cmd"' - \(.*\)/ {"'"$cmd"'", "\1"},/
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index da768ee7ac..ca60356d00 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -800,6 +800,7 @@ y - stage this hunk
n - do not stage this hunk
a - stage this and all the remaining hunks in the file
d - do not stage this hunk nor any of the remaining hunks in the file
+g - select a hunk to go to
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
k - leave this hunk undecided, see previous undecided hunk
@@ -811,11 +812,16 @@ EOF
}
sub patch_update_cmd {
- my @mods = grep { !($_->{BINARY}) } list_modified('file-only');
+ my @all_mods = list_modified('file-only');
+ my @mods = grep { !($_->{BINARY}) } @all_mods;
my @them;
if (!@mods) {
- print STDERR "No changes.\n";
+ if (@all_mods) {
+ print STDERR "Only binary files changed.\n";
+ } else {
+ print STDERR "No changes.\n";
+ }
return 0;
}
if ($patch_mode) {
@@ -831,6 +837,47 @@ sub patch_update_cmd {
}
}
+# Generate a one line summary of a hunk.
+sub summarize_hunk {
+ my $rhunk = shift;
+ my $summary = $rhunk->{TEXT}[0];
+
+ # Keep the line numbers, discard extra context.
+ $summary =~ s/@@(.*?)@@.*/$1 /s;
+ $summary .= " " x (20 - length $summary);
+
+ # Add some user context.
+ for my $line (@{$rhunk->{TEXT}}) {
+ if ($line =~ m/^[+-].*\w/) {
+ $summary .= $line;
+ last;
+ }
+ }
+
+ chomp $summary;
+ return substr($summary, 0, 80) . "\n";
+}
+
+
+# Print a one-line summary of each hunk in the array ref in
+# the first argument, starting wih the index in the 2nd.
+sub display_hunks {
+ my ($hunks, $i) = @_;
+ my $ctr = 0;
+ $i ||= 0;
+ for (; $i < @$hunks && $ctr < 20; $i++, $ctr++) {
+ my $status = " ";
+ if (defined $hunks->[$i]{USE}) {
+ $status = $hunks->[$i]{USE} ? "+" : "-";
+ }
+ printf "%s%2d: %s",
+ $status,
+ $i + 1,
+ summarize_hunk($hunks->[$i]);
+ }
+ return $i;
+}
+
sub patch_update_file {
my ($ix, $num);
my $path = shift;
@@ -899,6 +946,9 @@ sub patch_update_file {
if ($ix < $num - 1) {
$other .= '/J';
}
+ if ($num > 1) {
+ $other .= '/g';
+ }
for ($i = 0; $i < $num; $i++) {
if (!defined $hunk[$i]{USE}) {
$undecided = 1;
@@ -932,6 +982,28 @@ sub patch_update_file {
}
next;
}
+ elsif ($other =~ /g/ && $line =~ /^g(.*)/) {
+ my $response = $1;
+ my $no = $ix > 10 ? $ix - 10 : 0;
+ while ($response eq '') {
+ my $extra = "";
+ $no = display_hunks(\@hunk, $no);
+ if ($no < $num) {
+ $extra = " (<ret> to see more)";
+ }
+ print "go to which hunk$extra? ";
+ $response = <STDIN>;
+ chomp $response;
+ }
+ if ($response !~ /^\s*\d+\s*$/) {
+ print STDERR "Invalid number: '$response'\n";
+ } elsif (0 < $response && $response <= $num) {
+ $ix = $response - 1;
+ } else {
+ print STDERR "Sorry, only $num hunks available.\n";
+ }
+ next;
+ }
elsif ($line =~ /^d/i) {
while ($ix < $num) {
if (!defined $hunk[$ix]{USE}) {
diff --git a/git-am.sh b/git-am.sh
index aa602618e6..4b157fe5d5 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -247,10 +247,11 @@ else
exit 1
}
- # -s, -u, -k and --whitespace flags are kept for the
- # resuming session after a patch failure.
- # -3 and -i can and must be given when resuming.
- echo " $ws" >"$dotest/whitespace"
+ # -s, -u, -k, --whitespace, -3, -C and -p flags are kept
+ # for the resuming session after a patch failure.
+ # -i can and must be given when resuming.
+ echo " $git_apply_opt" >"$dotest/apply-opt"
+ echo "$threeway" >"$dotest/threeway"
echo "$sign" >"$dotest/sign"
echo "$utf8" >"$dotest/utf8"
echo "$keep" >"$dotest/keep"
@@ -283,7 +284,11 @@ if test "$(cat "$dotest/keep")" = t
then
keep=-k
fi
-ws=`cat "$dotest/whitespace"`
+if test "$(cat "$dotest/threeway")" = t
+then
+ threeway=t
+fi
+git_apply_opt=$(cat "$dotest/apply-opt")
if test "$(cat "$dotest/sign")" = t
then
SIGNOFF=`git var GIT_COMMITTER_IDENT | sed -e '
diff --git a/git-bisect.sh b/git-bisect.sh
index 79de7017e8..85db4ba400 100755
--- a/git-bisect.sh
+++ b/git-bisect.sh
@@ -9,7 +9,7 @@ git bisect bad [<rev>]
mark <rev> a known-bad revision.
git bisect good [<rev>...]
mark <rev>... known-good revisions.
-git bisect skip [<rev>...]
+git bisect skip [(<rev>|<range>)...]
mark <rev>... untestable revisions.
git bisect next
find next bisection to test and check it out.
@@ -191,6 +191,21 @@ check_expected_revs() {
done
}
+bisect_skip() {
+ all=''
+ for arg in "$@"
+ do
+ case "$arg" in
+ *..*)
+ revs=$(git rev-list "$arg") || die "Bad rev input: $arg" ;;
+ *)
+ revs=$(sq "$arg") ;;
+ esac
+ all="$all $revs"
+ done
+ eval bisect_state 'skip' $all
+}
+
bisect_state() {
bisect_autostart
state=$1
@@ -455,7 +470,7 @@ bisect_next() {
good=$(git for-each-ref --format='^%(objectname)' \
"refs/bisect/good-*" | tr '\012' ' ') &&
skip=$(git for-each-ref --format='%(objectname)' \
- "refs/bisect/skip-*" | tr '\012' ' ') &&
+ "refs/bisect/skip-*" | tr '\012' ' ') || exit
# Maybe some merge bases must be tested first
check_good_are_ancestors_of_bad "$bad" "$good" "$skip"
@@ -493,7 +508,7 @@ bisect_visualize() {
if test $# = 0
then
- case "${DISPLAY+set}${MSYSTEM+set}${SECURITYSESSIONID+set}" in
+ case "${DISPLAY+set}${SESSIONNAME+set}${MSYSTEM+set}${SECURITYSESSIONID+set}" in
'') set git log ;;
set*) set gitk ;;
esac
@@ -630,8 +645,10 @@ case "$#" in
git bisect -h ;;
start)
bisect_start "$@" ;;
- bad|good|skip)
+ bad|good)
bisect_state "$cmd" "$@" ;;
+ skip)
+ bisect_skip "$@" ;;
next)
# Not sure we want "next" at the UI level anymore.
bisect_next "$@" ;;
diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index b0a805c688..fef7faf339 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -1358,7 +1358,13 @@ sub req_ci
# write our commit message out if we have one ...
my ( $msg_fh, $msg_filename ) = tempfile( DIR => $TEMP_DIR );
print $msg_fh $state->{opt}{m};# if ( exists ( $state->{opt}{m} ) );
- print $msg_fh "\n\nvia git-CVS emulator\n";
+ if ( defined ( $cfg->{gitcvs}{commitmsgannotation} ) ) {
+ if ($cfg->{gitcvs}{commitmsgannotation} !~ /^\s*$/ ) {
+ print $msg_fh "\n\n".$cfg->{gitcvs}{commitmsgannotation}."\n"
+ }
+ } else {
+ print $msg_fh "\n\nvia git-CVS emulator\n";
+ }
close $msg_fh;
my $commithash = `git-commit-tree $treehash -p $parenthash < $msg_filename`;
@@ -2527,12 +2533,18 @@ sub open_blob_or_die
return $fh;
}
-# Generate a CVS author name from Git author information, by taking
-# the first eight characters of the user part of the email address.
+# Generate a CVS author name from Git author information, by taking the local
+# part of the email address and replacing characters not in the Portable
+# Filename Character Set (see IEEE Std 1003.1-2001, 3.276) by underscores. CVS
+# Login names are Unix login names, which should be restricted to this
+# character set.
sub cvs_author
{
my $author_line = shift;
- (my $author) = $author_line =~ /<([^>@]{1,8})/;
+ (my $author) = $author_line =~ /<([^@>]*)/;
+
+ $author =~ s/[^-a-zA-Z0-9_.]/_/g;
+ $author =~ s/^-/_/;
$author;
}
diff --git a/git-filter-branch.sh b/git-filter-branch.sh
index 81392add0b..eb62f719b0 100755
--- a/git-filter-branch.sh
+++ b/git-filter-branch.sh
@@ -40,6 +40,16 @@ skip_commit()
done;
}
+# if you run 'git_commit_non_empty_tree "$@"' in a commit filter,
+# it will skip commits that leave the tree untouched, commit the other.
+git_commit_non_empty_tree()
+{
+ if test $# = 3 && test "$1" = $(git rev-parse "$3^{tree}"); then
+ map "$3"
+ else
+ git commit-tree "$@"
+ fi
+}
# override die(): this version puts in an extra line break, so that
# the progress is still visible
@@ -109,11 +119,12 @@ filter_tree=
filter_index=
filter_parent=
filter_msg=cat
-filter_commit='git commit-tree "$@"'
+filter_commit=
filter_tag_name=
filter_subdir=
orig_namespace=refs/original/
force=
+prune_empty=
while :
do
case "$1" in
@@ -126,6 +137,11 @@ do
force=t
continue
;;
+ --prune-empty)
+ shift
+ prune_empty=t
+ continue
+ ;;
-*)
;;
*)
@@ -176,6 +192,17 @@ do
esac
done
+case "$prune_empty,$filter_commit" in
+,)
+ filter_commit='git commit-tree "$@"';;
+t,)
+ filter_commit="$functions;"' git_commit_non_empty_tree "$@"';;
+,*)
+ ;;
+*)
+ die "Cannot set --prune-empty and --filter-commit at the same time"
+esac
+
case "$force" in
t)
rm -rf "$tempdir"
@@ -256,7 +283,7 @@ while read commit parents; do
*)
# The commit may not have the subdirectory at all
err=$(git read-tree -i -m $commit:"$filter_subdir" 2>&1) || {
- if ! git rev-parse --verify $commit:"$filter_subdir" 2>/dev/null
+ if ! git rev-parse -q --verify $commit:"$filter_subdir"
then
rm -f "$GIT_INDEX_FILE"
else
diff --git a/git-gui/GIT-VERSION-GEN b/git-gui/GIT-VERSION-GEN
index 4e709ebe77..b3f937eace 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.11.GITGUI
+DEF_VER=0.12.GITGUI
LF='
'
diff --git a/git-gui/Makefile b/git-gui/Makefile
index 55765c8a3a..3ad8a21b30 100644
--- a/git-gui/Makefile
+++ b/git-gui/Makefile
@@ -285,6 +285,7 @@ all:: $(GITGUI_MAIN) lib/tclIndex $(ALL_MSGFILES)
install: all
$(QUIET)$(INSTALL_D0)'$(DESTDIR_SQ)$(gitexecdir_SQ)' $(INSTALL_D1)
$(QUIET)$(INSTALL_X0)git-gui $(INSTALL_X1) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
+ $(QUIET)$(INSTALL_X0)git-gui--askpass $(INSTALL_X1) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
$(QUIET)$(foreach p,$(GITGUI_BUILT_INS), $(INSTALL_L0)'$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' $(INSTALL_L1)'$(DESTDIR_SQ)$(gitexecdir_SQ)/git-gui' $(INSTALL_L2)'$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' $(INSTALL_L3) &&) true
ifdef GITGUI_WINDOWS_WRAPPER
$(QUIET)$(INSTALL_R0)git-gui.tcl $(INSTALL_R1) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
@@ -302,6 +303,7 @@ endif
uninstall:
$(QUIET)$(CLEAN_DST) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
$(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/git-gui $(REMOVE_F1)
+ $(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/git-gui--askpass $(REMOVE_F1)
$(QUIET)$(foreach p,$(GITGUI_BUILT_INS), $(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/$p $(REMOVE_F1) &&) true
ifdef GITGUI_WINDOWS_WRAPPER
$(QUIET)$(REMOVE_F0)'$(DESTDIR_SQ)$(gitexecdir_SQ)'/git-gui.tcl $(REMOVE_F1)
diff --git a/git-gui/git-gui--askpass b/git-gui/git-gui--askpass
new file mode 100755
index 0000000000..12e117ecb1
--- /dev/null
+++ b/git-gui/git-gui--askpass
@@ -0,0 +1,59 @@
+#!/bin/sh
+# Tcl ignores the next line -*- tcl -*- \
+exec wish "$0" -- "$@"
+
+# This is a trivial implementation of an SSH_ASKPASS handler.
+# Git-gui uses this script if none are already configured.
+
+set answer {}
+set yesno 0
+set rc 255
+
+if {$argc < 1} {
+ set prompt "Enter your OpenSSH passphrase:"
+} else {
+ set prompt [join $argv " "]
+ if {[regexp -nocase {\(yes\/no\)\?\s*$} $prompt]} {
+ set yesno 1
+ }
+}
+
+message .m -text $prompt -justify center -aspect 4000
+pack .m -side top -fill x -padx 20 -pady 20 -expand 1
+
+entry .e -textvariable answer -width 50
+pack .e -side top -fill x -padx 10 -pady 10
+
+if {!$yesno} {
+ .e configure -show "*"
+}
+
+frame .b
+button .b.ok -text OK -command finish
+button .b.cancel -text Cancel -command {destroy .}
+
+pack .b.ok -side left -expand 1
+pack .b.cancel -side right -expand 1
+pack .b -side bottom -fill x -padx 10 -pady 10
+
+bind . <Visibility> {focus -force .e}
+bind . <Key-Return> finish
+bind . <Key-Escape> {destroy .}
+bind . <Destroy> {exit $rc}
+
+proc finish {} {
+ if {$::yesno} {
+ if {$::answer ne "yes" && $::answer ne "no"} {
+ tk_messageBox -icon error -title "Error" -type ok \
+ -message "Only 'yes' or 'no' input allowed."
+ return
+ }
+ }
+
+ set ::rc 0
+ puts $::answer
+ destroy .
+}
+
+wm title . "OpenSSH"
+tk::PlaceWindow .
diff --git a/git-gui/git-gui.sh b/git-gui/git-gui.sh
index 4085e8fea5..e018e076f8 100755
--- a/git-gui/git-gui.sh
+++ b/git-gui/git-gui.sh
@@ -591,6 +591,34 @@ bind . <Visibility> {
if {[is_Windows]} {
wm iconbitmap . -default $oguilib/git-gui.ico
+ set ::tk::AlwaysShowSelection 1
+
+ # Spoof an X11 display for SSH
+ if {![info exists env(DISPLAY)]} {
+ set env(DISPLAY) :9999
+ }
+} else {
+ catch {
+ image create photo gitlogo -width 16 -height 16
+
+ gitlogo put #33CC33 -to 7 0 9 2
+ gitlogo put #33CC33 -to 4 2 12 4
+ gitlogo put #33CC33 -to 7 4 9 6
+ gitlogo put #CC3333 -to 4 6 12 8
+ gitlogo put gray26 -to 4 9 6 10
+ gitlogo put gray26 -to 3 10 6 12
+ gitlogo put gray26 -to 8 9 13 11
+ gitlogo put gray26 -to 8 11 10 12
+ gitlogo put gray26 -to 11 11 13 14
+ gitlogo put gray26 -to 3 12 5 14
+ gitlogo put gray26 -to 5 13
+ gitlogo put gray26 -to 10 13
+ gitlogo put gray26 -to 4 14 12 15
+ gitlogo put gray26 -to 5 15 11 16
+ gitlogo redither
+
+ wm iconphoto . -default gitlogo
+ }
}
######################################################################
@@ -912,19 +940,25 @@ git-version proc _parse_config {arr_name args} {
}
proc load_config {include_global} {
- global repo_config global_config default_config
+ global repo_config global_config system_config default_config
if {$include_global} {
+ _parse_config system_config --system
_parse_config global_config --global
}
_parse_config repo_config
foreach name [array names default_config] {
+ if {[catch {set v $system_config($name)}]} {
+ set system_config($name) $default_config($name)
+ }
+ }
+ foreach name [array names system_config] {
if {[catch {set v $global_config($name)}]} {
- set global_config($name) $default_config($name)
+ set global_config($name) $system_config($name)
}
if {[catch {set v $repo_config($name)}]} {
- set repo_config($name) $default_config($name)
+ set repo_config($name) $system_config($name)
}
}
}
@@ -993,8 +1027,20 @@ citool {
######################################################################
##
+## execution environment
+
+set have_tk85 [expr {[package vcompare $tk_version "8.5"] >= 0}]
+
+# Suggest our implementation of askpass, if none is set
+if {![info exists env(SSH_ASKPASS)]} {
+ set env(SSH_ASKPASS) [gitexec git-gui--askpass]
+}
+
+######################################################################
+##
## repository setup
+set picked 0
if {[catch {
set _gitdir $env(GIT_DIR)
set _prefix {}
@@ -1006,6 +1052,7 @@ if {[catch {
load_config 1
apply_config
choose_repository::pick
+ set picked 1
}
if {![file isdirectory $_gitdir] && [is_Cygwin]} {
catch {set _gitdir [exec cygpath --windows $_gitdir]}
@@ -1444,10 +1491,8 @@ proc rescan_done {fd buf after} {
prune_selection
unlock_index
display_all_files
- if {$current_diff_path ne {}} reshow_diff
- if {$current_diff_path eq {}} select_first_diff
-
- uplevel #0 $after
+ if {$current_diff_path ne {}} { reshow_diff $after }
+ if {$current_diff_path eq {}} { select_first_diff $after }
}
proc prune_selection {} {
@@ -1869,6 +1914,19 @@ proc do_gitk {revs} {
}
}
+proc do_explore {} {
+ set explorer {}
+ if {[is_Cygwin] || [is_Windows]} {
+ set explorer "explorer.exe"
+ } elseif {[is_MacOSX]} {
+ set explorer "open"
+ } else {
+ # freedesktop.org-conforming system is our best shot
+ set explorer "xdg-open"
+ }
+ eval exec $explorer [file dirname [gitdir]] &
+}
+
set is_quitting 0
set ret_code 1
@@ -1946,16 +2004,16 @@ proc do_rescan {} {
}
proc ui_do_rescan {} {
- rescan {force_first_diff; ui_ready}
+ rescan {force_first_diff ui_ready}
}
proc do_commit {} {
commit_tree
}
-proc next_diff {} {
+proc next_diff {{after {}}} {
global next_diff_p next_diff_w next_diff_i
- show_diff $next_diff_p $next_diff_w {}
+ show_diff $next_diff_p $next_diff_w {} {} $after
}
proc find_anchor_pos {lst name} {
@@ -2040,25 +2098,42 @@ proc next_diff_after_action {w path {lno {}} {mmask {}}} {
}
}
-proc select_first_diff {} {
+proc select_first_diff {after} {
global ui_workdir
if {[find_next_diff $ui_workdir {} 1 {^_?U}] ||
[find_next_diff $ui_workdir {} 1 {[^O]$}]} {
- next_diff
+ next_diff $after
+ } else {
+ uplevel #0 $after
}
}
-proc force_first_diff {} {
- global current_diff_path
+proc force_first_diff {after} {
+ global ui_workdir current_diff_path file_states
if {[info exists file_states($current_diff_path)]} {
set state [lindex $file_states($current_diff_path) 0]
+ } else {
+ set state {OO}
+ }
- if {[string index $state 1] ne {O}} return
+ set reselect 0
+ if {[string first {U} $state] >= 0} {
+ # Already a conflict, do nothing
+ } elseif {[find_next_diff $ui_workdir $current_diff_path {} {^_?U}]} {
+ set reselect 1
+ } elseif {[string index $state 1] ne {O}} {
+ # Already a diff & no conflicts, do nothing
+ } elseif {[find_next_diff $ui_workdir $current_diff_path {} {[^O]$}]} {
+ set reselect 1
}
- select_first_diff
+ if {$reselect} {
+ next_diff $after
+ } else {
+ uplevel #0 $after
+ }
}
proc toggle_or_diff {w x y} {
@@ -2090,7 +2165,9 @@ proc toggle_or_diff {w x y} {
if {$col == 0 && $y > 1} {
# Conflicts need special handling
if {[string first {U} $state] >= 0} {
- merge_stage_workdir $path $w $lno
+ # $w must always be $ui_workdir, but...
+ if {$w ne $ui_workdir} { set lno {} }
+ merge_stage_workdir $path $lno
return
}
@@ -2212,6 +2289,9 @@ if {[is_enabled transport]} {
.mbar add cascade -label [mc Merge] -menu .mbar.merge
.mbar add cascade -label [mc Remote] -menu .mbar.remote
}
+if {[is_enabled multicommit] || [is_enabled singlecommit]} {
+ .mbar add cascade -label [mc Tools] -menu .mbar.tools
+}
. configure -menu .mbar
# -- Repository Menu
@@ -2219,6 +2299,11 @@ if {[is_enabled transport]} {
menu .mbar.repository
.mbar.repository add command \
+ -label [mc "Explore Working Copy"] \
+ -command {do_explore}
+.mbar.repository add separator
+
+.mbar.repository add command \
-label [mc "Browse Current Branch's Files"] \
-command {browser::new $current_branch}
set ui_browse_current [.mbar.repository index last]
@@ -2413,7 +2498,7 @@ if {[is_enabled multicommit] || [is_enabled singlecommit]} {
.mbar.commit add separator
- if {![is_enabled nocommit]} {
+ if {![is_enabled nocommitmsg]} {
.mbar.commit add command -label [mc "Sign Off"] \
-command do_signoff \
-accelerator $M1T-S
@@ -2447,11 +2532,15 @@ if {[is_enabled transport]} {
menu .mbar.remote
.mbar.remote add command \
+ -label [mc "Add..."] \
+ -command remote_add::dialog \
+ -accelerator $M1T-A
+ .mbar.remote add command \
-label [mc "Push..."] \
-command do_push_anywhere \
-accelerator $M1T-P
.mbar.remote add command \
- -label [mc "Delete..."] \
+ -label [mc "Delete Branch..."] \
-command remote_branch_delete::dialog
}
@@ -2477,6 +2566,20 @@ if {[is_MacOSX]} {
-command do_options
}
+# -- Tools Menu
+#
+if {[is_enabled multicommit] || [is_enabled singlecommit]} {
+ set tools_menubar .mbar.tools
+ menu $tools_menubar
+ $tools_menubar add separator
+ $tools_menubar add command -label [mc "Add..."] -command tools_add::dialog
+ $tools_menubar add command -label [mc "Remove..."] -command tools_remove::dialog
+ set tools_tailcnt 3
+ if {[array names repo_config guitool.*.cmd] ne {}} {
+ tools_populate_all
+ }
+}
+
# -- Help Menu
#
.mbar add cascade -label [mc Help] -menu .mbar.help
@@ -2487,8 +2590,7 @@ if {![is_MacOSX]} {
-command do_about
}
-set browser {}
-catch {set browser $repo_config(instaweb.browser)}
+
set doc_path [file dirname [gitexec]]
set doc_path [file join $doc_path Documentation index.html]
@@ -2496,34 +2598,23 @@ if {[is_Cygwin]} {
set doc_path [exec cygpath --mixed $doc_path]
}
-if {$browser eq {}} {
- if {[is_MacOSX]} {
- set browser open
- } elseif {[is_Cygwin]} {
- set program_files [file dirname [exec cygpath --windir]]
- set program_files [file join $program_files {Program Files}]
- set firefox [file join $program_files {Mozilla Firefox} firefox.exe]
- set ie [file join $program_files {Internet Explorer} IEXPLORE.EXE]
- if {[file exists $firefox]} {
- set browser $firefox
- } elseif {[file exists $ie]} {
- set browser $ie
- }
- unset program_files firefox ie
- }
-}
-
if {[file isfile $doc_path]} {
set doc_url "file:$doc_path"
} else {
set doc_url {http://www.kernel.org/pub/software/scm/git/docs/}
}
-if {$browser ne {}} {
- .mbar.help add command -label [mc "Online Documentation"] \
- -command [list exec $browser $doc_url &]
+proc start_browser {url} {
+ git "web--browse" $url
}
-unset browser doc_path doc_url
+
+.mbar.help add command -label [mc "Online Documentation"] \
+ -command [list start_browser $doc_url]
+
+.mbar.help add command -label [mc "Show SSH Key"] \
+ -command do_ssh_key
+
+unset doc_path doc_url
# -- Standard bindings
#
@@ -2539,6 +2630,20 @@ proc usage {} {
exit 1
}
+proc normalize_relpath {path} {
+ set elements {}
+ foreach item [file split $path] {
+ if {$item eq {.}} continue
+ if {$item eq {..} && [llength $elements] > 0
+ && [lindex $elements end] ne {..}} {
+ set elements [lrange $elements 0 end-1]
+ continue
+ }
+ lappend elements $item
+ }
+ return [eval file join $elements]
+}
+
# -- Not a normal commit type invocation? Do that instead!
#
switch -- $subcommand {
@@ -2557,7 +2662,7 @@ blame {
foreach a $argv {
if {$is_path || [file exists $_prefix$a]} {
if {$path ne {}} usage
- set path $_prefix$a
+ set path [normalize_relpath $_prefix$a]
break
} elseif {$a eq {--}} {
if {$path ne {}} {
@@ -2580,7 +2685,7 @@ blame {
unset is_path
if {$head ne {} && $path eq {}} {
- set path $_prefix$head
+ set path [normalize_relpath $_prefix$head]
set head {}
}
@@ -2743,7 +2848,7 @@ pack .vpane.lower.commarea.buttons.incall -side top -fill x
lappend disable_on_lock \
{.vpane.lower.commarea.buttons.incall conf -state}
-if {![is_enabled nocommit]} {
+if {![is_enabled nocommitmsg]} {
button .vpane.lower.commarea.buttons.signoff -text [mc "Sign Off"] \
-command do_signoff
pack .vpane.lower.commarea.buttons.signoff -side top -fill x
@@ -3224,7 +3329,6 @@ by %s:
{^GIT_PAGER$} -
{^GIT_TRACE$} -
{^GIT_CONFIG$} -
- {^GIT_CONFIG_LOCAL$} -
{^GIT_(AUTHOR|COMMITTER)_DATE$} {
append msg " - $name\n"
incr ignored_env
@@ -3261,8 +3365,7 @@ if {[is_enabled transport]} {
load_all_remotes
set n [.mbar.remote index end]
- populate_push_menu
- populate_fetch_menu
+ populate_remotes_menu
set n [expr {[.mbar.remote index end] - $n}]
if {$n > 0} {
if {[.mbar.remote type 0] eq "tearoff"} { incr n }
@@ -3369,3 +3472,6 @@ if {[is_enabled multicommit]} {
if {[is_enabled retcode]} {
bind . <Destroy> {+terminate_me %W}
}
+if {$picked && [is_config_true gui.autoexplore]} {
+ do_explore
+}
diff --git a/git-gui/lib/blame.tcl b/git-gui/lib/blame.tcl
index eb61374d2d..1f3b08f9ef 100644
--- a/git-gui/lib/blame.tcl
+++ b/git-gui/lib/blame.tcl
@@ -21,9 +21,11 @@ field w_amov ; # text column: annotations + move tracking
field w_asim ; # text column: annotations (simple computation)
field w_file ; # text column: actual file data
field w_cviewer ; # pane showing commit message
+field finder ; # find mini-dialog frame
field status ; # status mega-widget instance
field old_height ; # last known height of $w.file_pane
+
# Tk UI colors
#
variable active_color #c0edc5
@@ -59,7 +61,7 @@ field tooltip_timer {} ; # Current timer event for our tooltip
field tooltip_commit {} ; # Commit(s) in tooltip
constructor new {i_commit i_path i_jump} {
- global cursor_ptr
+ global cursor_ptr M1B M1T have_tk85
variable active_color
variable group_colors
@@ -69,6 +71,8 @@ constructor new {i_commit i_path i_jump} {
make_toplevel top w
wm title $top [append "[appname] ([reponame]): " [mc "File Viewer"]]
+ set font_w [font measure font_diff "0"]
+
frame $w.header -background gold
label $w.header.commit_l \
-text [mc "Commit:"] \
@@ -114,9 +118,9 @@ constructor new {i_commit i_path i_jump} {
pack $w_path -fill x -side right
pack $w.header.path_l -side right
- panedwindow $w.file_pane -orient vertical
- frame $w.file_pane.out
- frame $w.file_pane.cm
+ panedwindow $w.file_pane -orient vertical -borderwidth 0 -sashwidth 3
+ frame $w.file_pane.out -relief flat -borderwidth 1
+ frame $w.file_pane.cm -relief sunken -borderwidth 1
$w.file_pane add $w.file_pane.out \
-sticky nsew \
-minsize 100 \
@@ -197,6 +201,11 @@ constructor new {i_commit i_path i_jump} {
-width 80 \
-xscrollcommand [list $w.file_pane.out.sbx set] \
-font font_diff
+ if {$have_tk85} {
+ $w_file configure -inactiveselectbackground darkblue
+ }
+ $w_file tag conf found \
+ -background yellow
set w_columns [list $w_amov $w_asim $w_line $w_file]
@@ -217,6 +226,11 @@ constructor new {i_commit i_path i_jump} {
-weight 1
grid rowconfigure $w.file_pane.out 0 -weight 1
+ set finder [::searchbar::new \
+ $w.file_pane.out.ff $w_file \
+ -column [expr {[llength $w_columns] - 1}] \
+ ]
+
set w_cviewer $w.file_pane.cm.t
text $w_cviewer \
-background white \
@@ -257,6 +271,10 @@ constructor new {i_commit i_path i_jump} {
-label [mc "Copy Commit"] \
-command [cb _copycommit]
$w.ctxm add separator
+ $w.ctxm add command \
+ -label [mc "Find Text..."] \
+ -accelerator F7 \
+ -command [list searchbar::show $finder]
menu $w.ctxm.enc
build_encoding_menu $w.ctxm.enc [cb _setencoding]
$w.ctxm add cascade \
@@ -278,9 +296,15 @@ constructor new {i_commit i_path i_jump} {
$i tag conf color$g -background [lindex $group_colors $g]
}
+ if {$i eq $w_file} {
+ $w_file tag raise found
+ }
+ $i tag raise sel
+
$i conf -cursor $cursor_ptr
- $i conf -yscrollcommand [list many2scrollbar \
- $w_columns yview $w.file_pane.out.sby]
+ $i conf -yscrollcommand \
+ "[list ::searchbar::scrolled $finder]
+ [list many2scrollbar $w_columns yview $w.file_pane.out.sby]"
bind $i <Button-1> "
[cb _hide_tooltip]
[cb _click $i @%x,%y]
@@ -297,7 +321,7 @@ constructor new {i_commit i_path i_jump} {
tk_popup $w.ctxm %X %Y
"
bind $i <Shift-Tab> "[list focus $w_cviewer];break"
- bind $i <Tab> "[list focus $w_cviewer];break"
+ bind $i <Tab> "[cb _focus_search $w_cviewer];break"
}
foreach i [concat $w_columns $w_cviewer] {
@@ -313,10 +337,15 @@ constructor new {i_commit i_path i_jump} {
bind $i <Control-Key-f> {catch {%W yview scroll 1 pages};break}
}
- bind $w_cviewer <Shift-Tab> "[list focus $w_file];break"
+ bind $w_cviewer <Shift-Tab> "[cb _focus_search $w_file];break"
bind $w_cviewer <Tab> "[list focus $w_file];break"
- bind $w_cviewer <Button-1> [list focus $w_cviewer]
- bind $w_file <Visibility> [list focus $w_file]
+ bind $w_cviewer <Button-1> [list focus $w_cviewer]
+ bind $w_file <Visibility> [cb _focus_search $w_file]
+ bind $top <F7> [list searchbar::show $finder]
+ bind $top <Escape> [list searchbar::hide $finder]
+ bind $top <F3> [list searchbar::find_next $finder]
+ bind $top <Shift-F3> [list searchbar::find_prev $finder]
+ catch { bind $top <Shift-Key-XF86_Switch_VT_3> [list searchbar::find_prev $finder] }
grid configure $w.header -sticky ew
grid configure $w.file_pane -sticky nsew
@@ -328,9 +357,14 @@ constructor new {i_commit i_path i_jump} {
set req_w [winfo reqwidth $top]
set req_h [winfo reqheight $top]
- set scr_h [expr {[winfo screenheight $top] - 100}]
- if {$req_w < 600} {set req_w 600}
+ set scr_w [expr {[winfo screenwidth $top] - 40}]
+ set scr_h [expr {[winfo screenheight $top] - 120}]
+ set opt_w [expr {$font_w * (80 + 5*3 + 3)}]
+ if {$req_w < $opt_w} {set req_w $opt_w}
+ if {$req_w > $scr_w} {set req_w $scr_w}
+ set opt_h [expr {$req_w*4/3}]
if {$req_h < $scr_h} {set req_h $scr_h}
+ if {$req_h > $opt_h} {set req_h $opt_h}
set g "${req_w}x${req_h}"
wm geometry $top $g
update
@@ -338,16 +372,31 @@ constructor new {i_commit i_path i_jump} {
set old_height [winfo height $w.file_pane]
$w.file_pane sash place 0 \
[lindex [$w.file_pane sash coord 0] 0] \
- [expr {int($old_height * 0.70)}]
+ [expr {int($old_height * 0.80)}]
bind $w.file_pane <Configure> \
"if {{$w.file_pane} eq {%W}} {[cb _resize %h]}"
wm protocol $top WM_DELETE_WINDOW "destroy $top"
- bind $top <Destroy> [cb _kill]
+ bind $top <Destroy> [cb _handle_destroy %W]
_load $this $i_jump
}
+method _focus_search {win} {
+ if {[searchbar::visible $finder]} {
+ focus [searchbar::editor $finder]
+ } else {
+ focus $win
+ }
+}
+
+method _handle_destroy {win} {
+ if {$win eq $w} {
+ _kill $this
+ delete_this
+ }
+}
+
method _kill {} {
if {$current_fd ne {}} {
kill_file_process $current_fd
@@ -510,7 +559,7 @@ method _read_file {fd jump} {
} ifdeleted { catch {close $fd} }
method _exec_blame {cur_w cur_d options cur_s} {
- lappend options --incremental
+ lappend options --incremental --encoding=utf-8
if {$commit eq {}} {
lappend options --contents $path
} else {
@@ -866,6 +915,10 @@ method _showcommit {cur_w lno} {
foreach i $w_columns {
$i tag conf g$cmit -background $active_color
$i tag raise g$cmit
+ if {$i eq $w_file} {
+ $w_file tag raise found
+ }
+ $i tag raise sel
}
set author_name {}
@@ -887,9 +940,8 @@ method _showcommit {cur_w lno} {
catch {
set fd [git_read cat-file commit $cmit]
fconfigure $fd -encoding binary -translation lf
- if {[catch {set enc $repo_config(i18n.commitencoding)}]} {
- set enc utf-8
- }
+ # By default commits are assumed to be in utf-8
+ set enc utf-8
while {[gets $fd line] > 0} {
if {[string match {encoding *} $line]} {
set enc [string tolower [string range $line 9 end]]
diff --git a/git-gui/lib/choose_repository.tcl b/git-gui/lib/choose_repository.tcl
index 3180786158..f9ff62a3b2 100644
--- a/git-gui/lib/choose_repository.tcl
+++ b/git-gui/lib/choose_repository.tcl
@@ -43,12 +43,18 @@ constructor pick {} {
$w.mbar.apple add command \
-label [mc "About %s" [appname]] \
-command do_about
+ $w.mbar.apple add command \
+ -label [mc "Show SSH Key"] \
+ -command do_ssh_key
} else {
$w.mbar add cascade -label [mc Help] -menu $w.mbar.help
menu $w.mbar.help
$w.mbar.help add command \
-label [mc "About %s" [appname]] \
-command do_about
+ $w.mbar.help add command \
+ -label [mc "Show SSH Key"] \
+ -command do_ssh_key
}
wm protocol $top WM_DELETE_WINDOW exit
@@ -381,7 +387,8 @@ method _do_new {} {
label $w_body.where.l -text [mc "Directory:"]
entry $w_body.where.t \
-textvariable @local_path \
- -font font_diff \
+ -borderwidth 1 \
+ -relief sunken \
-width 50
button $w_body.where.b \
-text [mc "Browse"] \
@@ -463,20 +470,22 @@ method _do_clone {} {
frame $w_body.args
pack $args -fill both
- label $args.origin_l -text [mc "URL:"]
+ label $args.origin_l -text [mc "Source Location:"]
entry $args.origin_t \
-textvariable @origin_url \
- -font font_diff \
+ -borderwidth 1 \
+ -relief sunken \
-width 50
button $args.origin_b \
-text [mc "Browse"] \
-command [cb _open_origin]
grid $args.origin_l $args.origin_t $args.origin_b -sticky ew
- label $args.where_l -text [mc "Directory:"]
+ label $args.where_l -text [mc "Target Directory:"]
entry $args.where_t \
-textvariable @local_path \
- -font font_diff \
+ -borderwidth 1 \
+ -relief sunken \
-width 50
button $args.where_b \
-text [mc "Browse"] \
@@ -979,7 +988,8 @@ method _do_open {} {
label $w_body.where.l -text [mc "Repository:"]
entry $w_body.where.t \
-textvariable @local_path \
- -font font_diff \
+ -borderwidth 1 \
+ -relief sunken \
-width 50
button $w_body.where.b \
-text [mc "Browse"] \
diff --git a/git-gui/lib/commit.tcl b/git-gui/lib/commit.tcl
index 334514996a..9cc8410595 100644
--- a/git-gui/lib/commit.tcl
+++ b/git-gui/lib/commit.tcl
@@ -27,9 +27,8 @@ You are currently in the middle of a merge that has not been fully completed. Y
if {[catch {
set fd [git_read cat-file commit $curHEAD]
fconfigure $fd -encoding binary -translation lf
- if {[catch {set enc $repo_config(i18n.commitencoding)}]} {
- set enc utf-8
- }
+ # By default commits are assumed to be in utf-8
+ set enc utf-8
while {[gets $fd line] > 0} {
if {[string match {parent *} $line]} {
lappend parents [string range $line 7 end]
@@ -208,7 +207,7 @@ A good commit message has the following format:
if {$use_enc ne {}} {
fconfigure $msg_wt -encoding $use_enc
} else {
- puts stderr [mc "warning: Tcl does not support encoding '%s'." $enc]
+ error_popup [mc "warning: Tcl does not support encoding '%s'." $enc]
fconfigure $msg_wt -encoding utf-8
}
puts $msg_wt $msg
diff --git a/git-gui/lib/diff.tcl b/git-gui/lib/diff.tcl
index abe502d971..bbbf15c875 100644
--- a/git-gui/lib/diff.tcl
+++ b/git-gui/lib/diff.tcl
@@ -16,7 +16,7 @@ proc clear_diff {} {
$ui_workdir tag remove in_diff 0.0 end
}
-proc reshow_diff {} {
+proc reshow_diff {{after {}}} {
global file_states file_lists
global current_diff_path current_diff_side
global ui_diff
@@ -30,13 +30,13 @@ proc reshow_diff {} {
|| [lsearch -sorted -exact $file_lists($current_diff_side) $p] == -1} {
if {[find_next_diff $current_diff_side $p {} {[^O]}]} {
- next_diff
+ next_diff $after
} else {
clear_diff
}
} else {
set save_pos [lindex [$ui_diff yview] 0]
- show_diff $p $current_diff_side {} $save_pos
+ show_diff $p $current_diff_side {} $save_pos $after
}
}
@@ -117,22 +117,22 @@ proc show_unmerged_diff {cont_info} {
if {$merge_stages(2) eq {}} {
set is_conflict_diff 1
lappend current_diff_queue \
- [list "LOCAL: deleted\nREMOTE:\n" d======= \
+ [list [mc "LOCAL: deleted\nREMOTE:\n"] d======= \
[list ":1:$current_diff_path" ":3:$current_diff_path"]]
} elseif {$merge_stages(3) eq {}} {
set is_conflict_diff 1
lappend current_diff_queue \
- [list "REMOTE: deleted\nLOCAL:\n" d======= \
+ [list [mc "REMOTE: deleted\nLOCAL:\n"] d======= \
[list ":1:$current_diff_path" ":2:$current_diff_path"]]
} elseif {[lindex $merge_stages(1) 0] eq {120000}
|| [lindex $merge_stages(2) 0] eq {120000}
|| [lindex $merge_stages(3) 0] eq {120000}} {
set is_conflict_diff 1
lappend current_diff_queue \
- [list "LOCAL:\n" d======= \
+ [list [mc "LOCAL:\n"] d======= \
[list ":1:$current_diff_path" ":2:$current_diff_path"]]
lappend current_diff_queue \
- [list "REMOTE:\n" d======= \
+ [list [mc "REMOTE:\n"] d======= \
[list ":1:$current_diff_path" ":3:$current_diff_path"]]
} else {
start_show_diff $cont_info
@@ -164,7 +164,7 @@ proc show_other_diff {path w m cont_info} {
# - Git won't give us the diff, there's nothing to compare to!
#
if {$m eq {_O}} {
- set max_sz [expr {128 * 1024}]
+ set max_sz 100000
set type unknown
if {[catch {
set type [file type $path]
@@ -218,17 +218,17 @@ proc show_other_diff {path w m cont_info} {
d_@
} else {
if {$sz > $max_sz} {
- $ui_diff insert end \
-"* Untracked file is $sz bytes.
-* Showing only first $max_sz bytes.
-" d_@
+ $ui_diff insert end [mc \
+"* Untracked file is %d bytes.
+* Showing only first %d bytes.
+" $sz $max_sz] d_@
}
$ui_diff insert end $content
if {$sz > $max_sz} {
- $ui_diff insert end "
-* Untracked file clipped here by [appname].
+ $ui_diff insert end [mc "
+* Untracked file clipped here by %s.
* To see the entire file, use an external editor.
-" d_@
+" [appname]] d_@
}
}
$ui_diff conf -state disabled
@@ -377,7 +377,6 @@ proc read_diff {fd cont_info} {
{+} {
if {[regexp {^\+([<>]{7} |={7})} $line _g op]} {
set is_conflict_diff 1
- set line [string replace $line 0 0 { }]
set tags d$op
} else {
set tags d_+
diff --git a/git-gui/lib/index.tcl b/git-gui/lib/index.tcl
index b045219a1c..d33896a0ce 100644
--- a/git-gui/lib/index.tcl
+++ b/git-gui/lib/index.tcl
@@ -298,11 +298,18 @@ proc add_helper {txt paths} {
set after {}
foreach path $paths {
switch -glob -- [lindex $file_states($path) 0] {
+ _U -
+ U? {
+ if {$path eq $current_diff_path} {
+ unlock_index
+ merge_stage_workdir $path
+ return
+ }
+ }
_O -
?M -
?D -
- ?T -
- U? {
+ ?T {
lappend pathList $path
if {$path eq $current_diff_path} {
set after {reshow_diff;}
diff --git a/git-gui/lib/merge.tcl b/git-gui/lib/merge.tcl
index 5c01875b05..283e4915e9 100644
--- a/git-gui/lib/merge.tcl
+++ b/git-gui/lib/merge.tcl
@@ -40,6 +40,7 @@ The rescan will be automatically started now.
_O {
continue; # and pray it works!
}
+ _U -
U? {
error_popup [mc "You are in the middle of a conflicted merge.
diff --git a/git-gui/lib/mergetool.tcl b/git-gui/lib/mergetool.tcl
index 6ab5701d93..eb2b4b56a4 100644
--- a/git-gui/lib/mergetool.tcl
+++ b/git-gui/lib/mergetool.tcl
@@ -23,13 +23,14 @@ This operation can be undone only by restarting the merge." \
}
}
-proc merge_stage_workdir {path w lno} {
+proc merge_stage_workdir {path {lno {}}} {
global current_diff_path diff_active
+ global current_diff_side ui_workdir
if {$diff_active} return
- if {$path ne $current_diff_path} {
- show_diff $path $w $lno {} [list do_merge_stage_workdir $path]
+ if {$path ne $current_diff_path || $ui_workdir ne $current_diff_side} {
+ show_diff $path $ui_workdir $lno {} [list do_merge_stage_workdir $path]
} else {
do_merge_stage_workdir $path
}
@@ -375,14 +376,6 @@ proc merge_tool_finish {fd} {
}
}
- # Check the modification time of the target file
- if {!$failed && [file mtime $mtool_target] eq $mtool_mtime} {
- if {[ask_popup [mc "File %s unchanged, still accept as resolved?" \
- [short_path $mtool_target]]] ne {yes}} {
- set failed 1
- }
- }
-
# Finish
if {$failed} {
file rename -force -- $backup $mtool_target
@@ -395,6 +388,6 @@ proc merge_tool_finish {fd} {
delete_temp_files $mtool_tmpfiles
- merge_add_resolution $mtool_target
+ reshow_diff
}
}
diff --git a/git-gui/lib/option.tcl b/git-gui/lib/option.tcl
index c80c939878..1d55b49c9b 100644
--- a/git-gui/lib/option.tcl
+++ b/git-gui/lib/option.tcl
@@ -25,7 +25,7 @@ proc config_check_encodings {} {
proc save_config {} {
global default_config font_descs
- global repo_config global_config
+ global repo_config global_config system_config
global repo_config_new global_config_new
global ui_comm_spell
@@ -49,7 +49,7 @@ proc save_config {} {
foreach name [array names default_config] {
set value $global_config_new($name)
if {$value ne $global_config($name)} {
- if {$value eq $default_config($name)} {
+ if {$value eq $system_config($name)} {
catch {git config --global --unset $name}
} else {
regsub -all "\[{}\]" $value {"} value
@@ -284,17 +284,17 @@ proc do_options {} {
}
proc do_restore_defaults {} {
- global font_descs default_config repo_config
+ global font_descs default_config repo_config system_config
global repo_config_new global_config_new
foreach name [array names default_config] {
- set repo_config_new($name) $default_config($name)
- set global_config_new($name) $default_config($name)
+ set repo_config_new($name) $system_config($name)
+ set global_config_new($name) $system_config($name)
}
foreach option $font_descs {
set name [lindex $option 0]
- set repo_config(gui.$name) $default_config(gui.$name)
+ set repo_config(gui.$name) $system_config(gui.$name)
}
apply_config
diff --git a/git-gui/lib/remote.tcl b/git-gui/lib/remote.tcl
index 0e86ddac09..b92b429cf7 100644
--- a/git-gui/lib/remote.tcl
+++ b/git-gui/lib/remote.tcl
@@ -132,91 +132,145 @@ proc load_all_remotes {} {
set all_remotes [lsort -unique $all_remotes]
}
-proc populate_fetch_menu {} {
- global all_remotes repo_config
-
+proc add_fetch_entry {r} {
+ global repo_config
set remote_m .mbar.remote
set fetch_m $remote_m.fetch
set prune_m $remote_m.prune
-
- foreach r $all_remotes {
- set enable 0
- if {![catch {set a $repo_config(remote.$r.url)}]} {
- if {![catch {set a $repo_config(remote.$r.fetch)}]} {
- set enable 1
- }
- } else {
- catch {
- set fd [open [gitdir remotes $r] r]
- while {[gets $fd n] >= 0} {
- if {[regexp {^Pull:[ \t]*([^:]+):} $n]} {
- set enable 1
- break
- }
+ set remove_m $remote_m.remove
+ set enable 0
+ if {![catch {set a $repo_config(remote.$r.url)}]} {
+ if {![catch {set a $repo_config(remote.$r.fetch)}]} {
+ set enable 1
+ }
+ } else {
+ catch {
+ set fd [open [gitdir remotes $r] r]
+ while {[gets $fd n] >= 0} {
+ if {[regexp {^Pull:[ \t]*([^:]+):} $n]} {
+ set enable 1
+ break
}
- close $fd
}
+ close $fd
}
+ }
- if {$enable} {
- if {![winfo exists $fetch_m]} {
- menu $prune_m
- $remote_m insert 0 cascade \
- -label [mc "Prune from"] \
- -menu $prune_m
-
- menu $fetch_m
- $remote_m insert 0 cascade \
- -label [mc "Fetch from"] \
- -menu $fetch_m
- }
+ if {$enable} {
+ if {![winfo exists $fetch_m]} {
+ menu $remove_m
+ $remote_m insert 0 cascade \
+ -label [mc "Remove Remote"] \
+ -menu $remove_m
+
+ menu $prune_m
+ $remote_m insert 0 cascade \
+ -label [mc "Prune from"] \
+ -menu $prune_m
- $fetch_m add command \
- -label $r \
- -command [list fetch_from $r]
- $prune_m add command \
- -label $r \
- -command [list prune_from $r]
+ menu $fetch_m
+ $remote_m insert 0 cascade \
+ -label [mc "Fetch from"] \
+ -menu $fetch_m
}
+
+ $fetch_m add command \
+ -label $r \
+ -command [list fetch_from $r]
+ $prune_m add command \
+ -label $r \
+ -command [list prune_from $r]
+ $remove_m add command \
+ -label $r \
+ -command [list remove_remote $r]
}
}
-proc populate_push_menu {} {
- global all_remotes repo_config
-
+proc add_push_entry {r} {
+ global repo_config
set remote_m .mbar.remote
set push_m $remote_m.push
-
- foreach r $all_remotes {
- set enable 0
- if {![catch {set a $repo_config(remote.$r.url)}]} {
- if {![catch {set a $repo_config(remote.$r.push)}]} {
- set enable 1
- }
- } else {
- catch {
- set fd [open [gitdir remotes $r] r]
- while {[gets $fd n] >= 0} {
- if {[regexp {^Push:[ \t]*([^:]+):} $n]} {
- set enable 1
- break
- }
+ set enable 0
+ if {![catch {set a $repo_config(remote.$r.url)}]} {
+ if {![catch {set a $repo_config(remote.$r.push)}]} {
+ set enable 1
+ }
+ } else {
+ catch {
+ set fd [open [gitdir remotes $r] r]
+ while {[gets $fd n] >= 0} {
+ if {[regexp {^Push:[ \t]*([^:]+):} $n]} {
+ set enable 1
+ break
}
- close $fd
}
+ close $fd
}
+ }
- if {$enable} {
- if {![winfo exists $push_m]} {
- menu $push_m
- $remote_m insert 0 cascade \
- -label [mc "Push to"] \
- -menu $push_m
- }
-
- $push_m add command \
- -label $r \
- -command [list push_to $r]
+ if {$enable} {
+ if {![winfo exists $push_m]} {
+ menu $push_m
+ $remote_m insert 0 cascade \
+ -label [mc "Push to"] \
+ -menu $push_m
}
+
+ $push_m add command \
+ -label $r \
+ -command [list push_to $r]
+ }
+}
+
+proc populate_remotes_menu {} {
+ global all_remotes
+
+ foreach r $all_remotes {
+ add_fetch_entry $r
+ add_push_entry $r
+ }
+}
+
+proc add_single_remote {name location} {
+ global all_remotes repo_config
+ lappend all_remotes $name
+
+ git remote add $name $location
+
+ # XXX: Better re-read the config so that we will never get out
+ # of sync with git remote implementation?
+ set repo_config(remote.$name.url) $location
+ set repo_config(remote.$name.fetch) "+refs/heads/*:refs/remotes/$name/*"
+
+ add_fetch_entry $name
+ add_push_entry $name
+}
+
+proc delete_from_menu {menu name} {
+ if {[winfo exists $menu]} {
+ $menu delete $name
}
}
+
+proc remove_remote {name} {
+ global all_remotes repo_config
+
+ git remote rm $name
+
+ catch {
+ # Missing values are ok
+ unset repo_config(remote.$name.url)
+ unset repo_config(remote.$name.fetch)
+ unset repo_config(remote.$name.push)
+ }
+
+ set i [lsearch -exact all_remotes $name]
+ lreplace all_remotes $i $i
+
+ set remote_m .mbar.remote
+ delete_from_menu $remote_m.fetch $name
+ delete_from_menu $remote_m.prune $name
+ delete_from_menu $remote_m.remove $name
+ # Not all remotes are in the push menu
+ catch { delete_from_menu $remote_m.push $name }
+}
diff --git a/git-gui/lib/remote_add.tcl b/git-gui/lib/remote_add.tcl
new file mode 100644
index 0000000000..fb29422aa7
--- /dev/null
+++ b/git-gui/lib/remote_add.tcl
@@ -0,0 +1,191 @@
+# git-gui remote adding support
+# Copyright (C) 2008 Petr Baudis
+
+class remote_add {
+
+field w ; # widget path
+field w_name ; # new remote name widget
+field w_loc ; # new remote location widget
+
+field name {}; # name of the remote the user has chosen
+field location {}; # location of the remote the user has chosen
+
+field opt_action fetch; # action to do after registering the remote locally
+
+constructor dialog {} {
+ global repo_config
+
+ make_toplevel top w
+ wm title $top [append "[appname] ([reponame]): " [mc "Add Remote"]]
+ if {$top ne {.}} {
+ wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
+ }
+
+ label $w.header -text [mc "Add New Remote"] -font font_uibold
+ pack $w.header -side top -fill x
+
+ frame $w.buttons
+ button $w.buttons.create -text [mc Add] \
+ -default active \
+ -command [cb _add]
+ pack $w.buttons.create -side right
+ button $w.buttons.cancel -text [mc Cancel] \
+ -command [list destroy $w]
+ pack $w.buttons.cancel -side right -padx 5
+ pack $w.buttons -side bottom -fill x -pady 10 -padx 10
+
+ labelframe $w.desc -text [mc "Remote Details"]
+
+ label $w.desc.name_l -text [mc "Name:"]
+ set w_name $w.desc.name_t
+ entry $w_name \
+ -borderwidth 1 \
+ -relief sunken \
+ -width 40 \
+ -textvariable @name \
+ -validate key \
+ -validatecommand [cb _validate_name %d %S]
+ grid $w.desc.name_l $w_name -sticky we -padx {0 5}
+
+ label $w.desc.loc_l -text [mc "Location:"]
+ set w_loc $w.desc.loc_t
+ entry $w_loc \
+ -borderwidth 1 \
+ -relief sunken \
+ -width 40 \
+ -textvariable @location
+ grid $w.desc.loc_l $w_loc -sticky we -padx {0 5}
+
+ grid columnconfigure $w.desc 1 -weight 1
+ pack $w.desc -anchor nw -fill x -pady 5 -padx 5
+
+ labelframe $w.action -text [mc "Further Action"]
+
+ radiobutton $w.action.fetch \
+ -text [mc "Fetch Immediately"] \
+ -value fetch \
+ -variable @opt_action
+ pack $w.action.fetch -anchor nw
+
+ radiobutton $w.action.push \
+ -text [mc "Initialize Remote Repository and Push"] \
+ -value push \
+ -variable @opt_action
+ pack $w.action.push -anchor nw
+
+ radiobutton $w.action.none \
+ -text [mc "Do Nothing Else Now"] \
+ -value none \
+ -variable @opt_action
+ pack $w.action.none -anchor nw
+
+ grid columnconfigure $w.action 1 -weight 1
+ pack $w.action -anchor nw -fill x -pady 5 -padx 5
+
+ bind $w <Visibility> [cb _visible]
+ bind $w <Key-Escape> [list destroy $w]
+ bind $w <Key-Return> [cb _add]\;break
+ tkwait window $w
+}
+
+method _add {} {
+ global repo_config env
+ global M1B
+
+ if {$name eq {}} {
+ tk_messageBox \
+ -icon error \
+ -type ok \
+ -title [wm title $w] \
+ -parent $w \
+ -message [mc "Please supply a remote name."]
+ focus $w_name
+ return
+ }
+
+ # XXX: We abuse check-ref-format here, but
+ # that should be ok.
+ if {[catch {git check-ref-format "remotes/$name"}]} {
+ tk_messageBox \
+ -icon error \
+ -type ok \
+ -title [wm title $w] \
+ -parent $w \
+ -message [mc "'%s' is not an acceptable remote name." $name]
+ focus $w_name
+ return
+ }
+
+ if {[catch {add_single_remote $name $location}]} {
+ tk_messageBox \
+ -icon error \
+ -type ok \
+ -title [wm title $w] \
+ -parent $w \
+ -message [mc "Failed to add remote '%s' of location '%s'." $name $location]
+ focus $w_name
+ return
+ }
+
+ switch -- $opt_action {
+ fetch {
+ set c [console::new \
+ [mc "fetch %s" $name] \
+ [mc "Fetching the %s" $name]]
+ console::exec $c [list git fetch $name]
+ }
+ push {
+ set cmds [list]
+
+ # Parse the location
+ if { [regexp {(?:git\+)?ssh://([^/]+)(/.+)} $location xx host path]
+ || [regexp {([^:][^:]+):(.+)} $location xx host path]} {
+ set ssh ssh
+ if {[info exists env(GIT_SSH)]} {
+ set ssh $env(GIT_SSH)
+ }
+ lappend cmds [list exec $ssh $host mkdir -p $location && git --git-dir=$path init --bare]
+ } elseif { ! [regexp {://} $location xx] } {
+ lappend cmds [list exec mkdir -p $location]
+ lappend cmds [list exec git --git-dir=$location init --bare]
+ } else {
+ tk_messageBox \
+ -icon error \
+ -type ok \
+ -title [wm title $w] \
+ -parent $w \
+ -message [mc "Do not know how to initialize repository at location '%s'." $location]
+ destroy $w
+ return
+ }
+
+ set c [console::new \
+ [mc "push %s" $name] \
+ [mc "Setting up the %s (at %s)" $name $location]]
+
+ lappend cmds [list exec git push -v --all $name]
+ console::chain $c $cmds
+ }
+ none {
+ }
+ }
+
+ destroy $w
+}
+
+method _validate_name {d S} {
+ if {$d == 1} {
+ if {[regexp {[~^:?*\[\0- ]} $S]} {
+ return 0
+ }
+ }
+ return 1
+}
+
+method _visible {} {
+ grab $w
+ $w_name icursor end
+ focus $w_name
+}
+
+}
diff --git a/git-gui/lib/remote_branch_delete.tcl b/git-gui/lib/remote_branch_delete.tcl
index c7b8148698..89eb0f70f2 100644
--- a/git-gui/lib/remote_branch_delete.tcl
+++ b/git-gui/lib/remote_branch_delete.tcl
@@ -26,12 +26,12 @@ constructor dialog {} {
global all_remotes M1B
make_toplevel top w
- wm title $top [append "[appname] ([reponame]): " [mc "Delete Remote Branch"]]
+ wm title $top [append "[appname] ([reponame]): " [mc "Delete Branch Remotely"]]
if {$top ne {.}} {
wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
}
- label $w.header -text [mc "Delete Remote Branch"] -font font_uibold
+ label $w.header -text [mc "Delete Branch Remotely"] -font font_uibold
pack $w.header -side top -fill x
frame $w.buttons
@@ -63,7 +63,7 @@ constructor dialog {} {
set urltype url
}
radiobutton $w.dest.url_r \
- -text [mc "Arbitrary URL:"] \
+ -text [mc "Arbitrary Location:"] \
-value url \
-variable @urltype
entry $w.dest.url_t \
diff --git a/git-gui/lib/search.tcl b/git-gui/lib/search.tcl
new file mode 100644
index 0000000000..b371e9a30a
--- /dev/null
+++ b/git-gui/lib/search.tcl
@@ -0,0 +1,198 @@
+# incremental search panel
+# based on code from gitk, Copyright (C) Paul Mackerras
+
+class searchbar {
+
+field w
+field ctext
+
+field searchstring {}
+field casesensitive 1
+field searchdirn -forwards
+
+field smarktop
+field smarkbot
+
+constructor new {i_w i_text args} {
+ set w $i_w
+ set ctext $i_text
+
+ frame $w
+ label $w.l -text [mc Find:]
+ entry $w.ent -textvariable ${__this}::searchstring -background lightgreen
+ button $w.bn -text [mc Next] -command [cb find_next]
+ button $w.bp -text [mc Prev] -command [cb find_prev]
+ checkbutton $w.cs -text [mc Case-Sensitive] \
+ -variable ${__this}::casesensitive -command [cb _incrsearch]
+ pack $w.l -side left
+ pack $w.cs -side right
+ pack $w.bp -side right
+ pack $w.bn -side right
+ pack $w.ent -side left -expand 1 -fill x
+
+ eval grid conf $w -sticky we $args
+ grid remove $w
+
+ trace add variable searchstring write [cb _incrsearch_cb]
+
+ bind $w <Destroy> [list delete_this $this]
+ return $this
+}
+
+method show {} {
+ if {![visible $this]} {
+ grid $w
+ }
+ focus -force $w.ent
+}
+
+method hide {} {
+ if {[visible $this]} {
+ focus $ctext
+ grid remove $w
+ }
+}
+
+method visible {} {
+ return [winfo ismapped $w]
+}
+
+method editor {} {
+ return $w.ent
+}
+
+method _get_new_anchor {} {
+ # use start of selection if it is visible,
+ # or the bounds of the visible area
+ set top [$ctext index @0,0]
+ set bottom [$ctext index @0,[winfo height $ctext]]
+ set sel [$ctext tag ranges sel]
+ if {$sel ne {}} {
+ set spos [lindex $sel 0]
+ if {[lindex $spos 0] >= [lindex $top 0] &&
+ [lindex $spos 0] <= [lindex $bottom 0]} {
+ return $spos
+ }
+ }
+ if {$searchdirn eq "-forwards"} {
+ return $top
+ } else {
+ return $bottom
+ }
+}
+
+method _get_wrap_anchor {dir} {
+ if {$dir eq "-forwards"} {
+ return 1.0
+ } else {
+ return end
+ }
+}
+
+method _do_search {start {mlenvar {}} {dir {}} {endbound {}}} {
+ set cmd [list $ctext search]
+ if {$mlenvar ne {}} {
+ upvar $mlenvar mlen
+ lappend cmd -count mlen
+ }
+ if {!$casesensitive} {
+ lappend cmd -nocase
+ }
+ if {$dir eq {}} {
+ set dir $searchdirn
+ }
+ lappend cmd $dir -- $searchstring
+ if {$endbound ne {}} {
+ set here [eval $cmd [list $start] [list $endbound]]
+ } else {
+ set here [eval $cmd [list $start]]
+ if {$here eq {}} {
+ set here [eval $cmd [_get_wrap_anchor $this $dir]]
+ }
+ }
+ return $here
+}
+
+method _incrsearch_cb {name ix op} {
+ after idle [cb _incrsearch]
+}
+
+method _incrsearch {} {
+ $ctext tag remove found 1.0 end
+ if {[catch {$ctext index anchor}]} {
+ $ctext mark set anchor [_get_new_anchor $this]
+ }
+ if {$searchstring ne {}} {
+ set here [_do_search $this anchor mlen]
+ if {$here ne {}} {
+ $ctext see $here
+ $ctext tag remove sel 1.0 end
+ $ctext tag add sel $here "$here + $mlen c"
+ $w.ent configure -background lightgreen
+ _set_marks $this 1
+ } else {
+ $w.ent configure -background lightpink
+ }
+ }
+}
+
+method find_prev {} {
+ find_next $this -backwards
+}
+
+method find_next {{dir -forwards}} {
+ focus $w.ent
+ $w.ent icursor end
+ set searchdirn $dir
+ $ctext mark unset anchor
+ if {$searchstring ne {}} {
+ set start [_get_new_anchor $this]
+ if {$dir eq "-forwards"} {
+ set start "$start + 1c"
+ }
+ set match [_do_search $this $start mlen]
+ $ctext tag remove sel 1.0 end
+ if {$match ne {}} {
+ $ctext see $match
+ $ctext tag add sel $match "$match + $mlen c"
+ }
+ }
+}
+
+method _mark_range {first last} {
+ set mend $first.0
+ while {1} {
+ set match [_do_search $this $mend mlen -forwards $last.end]
+ if {$match eq {}} break
+ set mend "$match + $mlen c"
+ $ctext tag add found $match $mend
+ }
+}
+
+method _set_marks {doall} {
+ set topline [lindex [split [$ctext index @0,0] .] 0]
+ set botline [lindex [split [$ctext index @0,[winfo height $ctext]] .] 0]
+ if {$doall || $botline < $smarktop || $topline > $smarkbot} {
+ # no overlap with previous
+ _mark_range $this $topline $botline
+ set smarktop $topline
+ set smarkbot $botline
+ } else {
+ if {$topline < $smarktop} {
+ _mark_range $this $topline [expr {$smarktop-1}]
+ set smarktop $topline
+ }
+ if {$botline > $smarkbot} {
+ _mark_range $this [expr {$smarkbot+1}] $botline
+ set smarkbot $botline
+ }
+ }
+}
+
+method scrolled {} {
+ if {$searchstring ne {}} {
+ after idle [cb _set_marks 0]
+ }
+}
+
+} \ No newline at end of file
diff --git a/git-gui/lib/spellcheck.tcl b/git-gui/lib/spellcheck.tcl
index 78f344f08f..e6120303e9 100644
--- a/git-gui/lib/spellcheck.tcl
+++ b/git-gui/lib/spellcheck.tcl
@@ -80,7 +80,7 @@ method _connect {pipe_fd} {
error_popup [strcat [mc "Unrecognized spell checker"] ":\n\n$s_version"]
return
}
- set s_version [string range $s_version 5 end]
+ set s_version [string range [string trim $s_version] 5 end]
regexp \
{International Ispell Version .* \(but really (Aspell .*?)\)$} \
$s_version _junk s_version
@@ -314,6 +314,7 @@ method _run {} {
method _read {} {
while {[gets $s_fd line] >= 0} {
set lineno [lindex $s_pending 0 0]
+ set line [string trim $line]
if {$s_clear} {
$w_text tag remove misspelled "$lineno.0" "$lineno.end"
diff --git a/git-gui/lib/sshkey.tcl b/git-gui/lib/sshkey.tcl
new file mode 100644
index 0000000000..82a1a80ff4
--- /dev/null
+++ b/git-gui/lib/sshkey.tcl
@@ -0,0 +1,126 @@
+# git-gui about git-gui dialog
+# Copyright (C) 2006, 2007 Shawn Pearce
+
+proc find_ssh_key {} {
+ foreach name {~/.ssh/id_dsa.pub ~/.ssh/id_rsa.pub ~/.ssh/identity.pub} {
+ if {[file exists $name]} {
+ set fh [open $name r]
+ set cont [read $fh]
+ close $fh
+ return [list $name $cont]
+ }
+ }
+
+ return {}
+}
+
+proc do_ssh_key {} {
+ global sshkey_title have_tk85 sshkey_fd
+
+ set w .sshkey_dialog
+ if {[winfo exists $w]} {
+ raise $w
+ return
+ }
+
+ toplevel $w
+ wm transient $w .
+
+ set finfo [find_ssh_key]
+ if {$finfo eq {}} {
+ set sshkey_title [mc "No keys found."]
+ set gen_state normal
+ } else {
+ set sshkey_title [mc "Found a public key in: %s" [lindex $finfo 0]]
+ set gen_state disabled
+ }
+
+ frame $w.header -relief flat
+ label $w.header.lbl -textvariable sshkey_title -anchor w
+ button $w.header.gen -text [mc "Generate Key"] \
+ -command [list make_ssh_key $w] -state $gen_state
+ pack $w.header.lbl -side left -expand 1 -fill x
+ pack $w.header.gen -side right
+ pack $w.header -fill x -pady 5 -padx 5
+
+ text $w.contents -width 60 -height 10 -wrap char -relief sunken
+ pack $w.contents -fill both -expand 1
+ if {$have_tk85} {
+ $w.contents configure -inactiveselectbackground darkblue
+ }
+
+ frame $w.buttons
+ button $w.buttons.close -text [mc Close] \
+ -default active -command [list destroy $w]
+ pack $w.buttons.close -side right
+ button $w.buttons.copy -text [mc "Copy To Clipboard"] \
+ -command [list tk_textCopy $w.contents]
+ pack $w.buttons.copy -side left
+ pack $w.buttons -side bottom -fill x -pady 5 -padx 5
+
+ if {$finfo ne {}} {
+ $w.contents insert end [lindex $finfo 1] sel
+ }
+ $w.contents configure -state disabled
+
+ bind $w <Visibility> "grab $w; focus $w.buttons.close"
+ bind $w <Key-Escape> "destroy $w"
+ bind $w <Key-Return> "destroy $w"
+ bind $w <Destroy> kill_sshkey
+ wm title $w [mc "Your OpenSSH Public Key"]
+ tk::PlaceWindow $w widget .
+ tkwait window $w
+}
+
+proc make_ssh_key {w} {
+ global sshkey_title sshkey_output sshkey_fd
+
+ set sshkey_title [mc "Generating..."]
+ $w.header.gen configure -state disabled
+
+ set cmdline [list sh -c {echo | ssh-keygen -q -t rsa -f ~/.ssh/id_rsa 2>&1}]
+
+ if {[catch { set sshkey_fd [_open_stdout_stderr $cmdline] } err]} {
+ error_popup [mc "Could not start ssh-keygen:\n\n%s" $err]
+ return
+ }
+
+ set sshkey_output {}
+ fconfigure $sshkey_fd -blocking 0
+ fileevent $sshkey_fd readable [list read_sshkey_output $sshkey_fd $w]
+}
+
+proc kill_sshkey {} {
+ global sshkey_fd
+ if {![info exists sshkey_fd]} return
+ catch { kill_file_process $sshkey_fd }
+ catch { close $sshkey_fd }
+}
+
+proc read_sshkey_output {fd w} {
+ global sshkey_fd sshkey_output sshkey_title
+
+ set sshkey_output "$sshkey_output[read $fd]"
+ if {![eof $fd]} return
+
+ fconfigure $fd -blocking 1
+ unset sshkey_fd
+
+ $w.contents configure -state normal
+ if {[catch {close $fd} err]} {
+ set sshkey_title [mc "Generation failed."]
+ $w.contents insert end $err
+ $w.contents insert end "\n"
+ $w.contents insert end $sshkey_output
+ } else {
+ set finfo [find_ssh_key]
+ if {$finfo eq {}} {
+ set sshkey_title [mc "Generation succeded, but no keys found."]
+ $w.contents insert end $sshkey_output
+ } else {
+ set sshkey_title [mc "Your key is in: %s" [lindex $finfo 0]]
+ $w.contents insert end [lindex $finfo 1] sel
+ }
+ }
+ $w.contents configure -state disable
+}
diff --git a/git-gui/lib/tools.tcl b/git-gui/lib/tools.tcl
new file mode 100644
index 0000000000..6ae63b6c7c
--- /dev/null
+++ b/git-gui/lib/tools.tcl
@@ -0,0 +1,159 @@
+# git-gui Tools menu implementation
+
+proc tools_list {} {
+ global repo_config
+
+ set names {}
+ foreach item [array names repo_config guitool.*.cmd] {
+ lappend names [string range $item 8 end-4]
+ }
+ return [lsort $names]
+}
+
+proc tools_populate_all {} {
+ global tools_menubar tools_menutbl
+ global tools_tailcnt
+
+ set mbar_end [$tools_menubar index end]
+ set mbar_base [expr {$mbar_end - $tools_tailcnt}]
+ if {$mbar_base >= 0} {
+ $tools_menubar delete 0 $mbar_base
+ }
+
+ array unset tools_menutbl
+
+ foreach fullname [tools_list] {
+ tools_populate_one $fullname
+ }
+}
+
+proc tools_create_item {parent args} {
+ global tools_menubar tools_tailcnt
+ if {$parent eq $tools_menubar} {
+ set pos [expr {[$parent index end]-$tools_tailcnt+1}]
+ eval [list $parent insert $pos] $args
+ } else {
+ eval [list $parent add] $args
+ }
+}
+
+proc tools_populate_one {fullname} {
+ global tools_menubar tools_menutbl tools_id
+
+ if {![info exists tools_id]} {
+ set tools_id 0
+ }
+
+ set names [split $fullname '/']
+ set parent $tools_menubar
+ for {set i 0} {$i < [llength $names]-1} {incr i} {
+ set subname [join [lrange $names 0 $i] '/']
+ if {[info exists tools_menutbl($subname)]} {
+ set parent $tools_menutbl($subname)
+ } else {
+ set subid $parent.t$tools_id
+ tools_create_item $parent cascade \
+ -label [lindex $names $i] -menu $subid
+ menu $subid
+ set tools_menutbl($subname) $subid
+ set parent $subid
+ incr tools_id
+ }
+ }
+
+ tools_create_item $parent command \
+ -label [lindex $names end] \
+ -command [list tools_exec $fullname]
+}
+
+proc tools_exec {fullname} {
+ global repo_config env current_diff_path
+ global current_branch is_detached
+
+ if {[is_config_true "guitool.$fullname.needsfile"]} {
+ if {$current_diff_path eq {}} {
+ error_popup [mc "Running %s requires a selected file." $fullname]
+ return
+ }
+ }
+
+ catch { unset env(ARGS) }
+ catch { unset env(REVISION) }
+
+ if {[get_config "guitool.$fullname.revprompt"] ne {} ||
+ [get_config "guitool.$fullname.argprompt"] ne {}} {
+ set dlg [tools_askdlg::dialog $fullname]
+ if {![tools_askdlg::execute $dlg]} {
+ return
+ }
+ } elseif {[is_config_true "guitool.$fullname.confirm"]} {
+ if {[ask_popup [mc "Are you sure you want to run %s?" $fullname]] ne {yes}} {
+ return
+ }
+ }
+
+ set env(GIT_GUITOOL) $fullname
+ set env(FILENAME) $current_diff_path
+ if {$is_detached} {
+ set env(CUR_BRANCH) ""
+ } else {
+ set env(CUR_BRANCH) $current_branch
+ }
+
+ set cmdline $repo_config(guitool.$fullname.cmd)
+ if {[is_config_true "guitool.$fullname.noconsole"]} {
+ tools_run_silent [list sh -c $cmdline] \
+ [list tools_complete $fullname {}]
+ } else {
+ regsub {/} $fullname { / } title
+ set w [console::new \
+ [mc "Tool: %s" $title] \
+ [mc "Running: %s" $cmdline]]
+ console::exec $w [list sh -c $cmdline] \
+ [list tools_complete $fullname $w]
+ }
+
+ unset env(GIT_GUITOOL)
+ unset env(FILENAME)
+ unset env(CUR_BRANCH)
+ catch { unset env(ARGS) }
+ catch { unset env(REVISION) }
+}
+
+proc tools_run_silent {cmd after} {
+ lappend cmd 2>@1
+ set fd [_open_stdout_stderr $cmd]
+
+ fconfigure $fd -blocking 0 -translation binary
+ fileevent $fd readable [list tools_consume_input $fd $after]
+}
+
+proc tools_consume_input {fd after} {
+ read $fd
+ if {[eof $fd]} {
+ fconfigure $fd -blocking 1
+ if {[catch {close $fd}]} {
+ uplevel #0 $after 0
+ } else {
+ uplevel #0 $after 1
+ }
+ }
+}
+
+proc tools_complete {fullname w {ok 1}} {
+ if {$w ne {}} {
+ console::done $w $ok
+ }
+
+ if {$ok} {
+ set msg [mc "Tool completed succesfully: %s" $fullname]
+ } else {
+ set msg [mc "Tool failed: %s" $fullname]
+ }
+
+ if {[is_config_true "guitool.$fullname.norescan"]} {
+ ui_status $msg
+ } else {
+ rescan [list ui_status $msg]
+ }
+}
diff --git a/git-gui/lib/tools_dlg.tcl b/git-gui/lib/tools_dlg.tcl
new file mode 100644
index 0000000000..5f7f08e239
--- /dev/null
+++ b/git-gui/lib/tools_dlg.tcl
@@ -0,0 +1,421 @@
+# git-gui Tools menu dialogs
+
+class tools_add {
+
+field w ; # widget path
+field w_name ; # new remote name widget
+field w_cmd ; # new remote location widget
+
+field name {}; # name of the tool
+field command {}; # command to execute
+field add_global 0; # add to the --global config
+field no_console 0; # disable using the console
+field needs_file 0; # ensure filename is set
+field confirm 0; # ask for confirmation
+field ask_branch 0; # ask for a revision
+field ask_args 0; # ask for additional args
+
+constructor dialog {} {
+ global repo_config
+
+ make_toplevel top w
+ wm title $top [append "[appname] ([reponame]): " [mc "Add Tool"]]
+ if {$top ne {.}} {
+ wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
+ wm transient $top .
+ }
+
+ label $w.header -text [mc "Add New Tool Command"] -font font_uibold
+ pack $w.header -side top -fill x
+
+ frame $w.buttons
+ checkbutton $w.buttons.global \
+ -text [mc "Add globally"] \
+ -variable @add_global
+ pack $w.buttons.global -side left -padx 5
+ button $w.buttons.create -text [mc Add] \
+ -default active \
+ -command [cb _add]
+ pack $w.buttons.create -side right
+ button $w.buttons.cancel -text [mc Cancel] \
+ -command [list destroy $w]
+ pack $w.buttons.cancel -side right -padx 5
+ pack $w.buttons -side bottom -fill x -pady 10 -padx 10
+
+ labelframe $w.desc -text [mc "Tool Details"]
+
+ label $w.desc.name_cmnt -anchor w\
+ -text [mc "Use '/' separators to create a submenu tree:"]
+ grid x $w.desc.name_cmnt -sticky we -padx {0 5} -pady {0 2}
+ label $w.desc.name_l -text [mc "Name:"]
+ set w_name $w.desc.name_t
+ entry $w_name \
+ -borderwidth 1 \
+ -relief sunken \
+ -width 40 \
+ -textvariable @name \
+ -validate key \
+ -validatecommand [cb _validate_name %d %S]
+ grid $w.desc.name_l $w_name -sticky we -padx {0 5}
+
+ label $w.desc.cmd_l -text [mc "Command:"]
+ set w_cmd $w.desc.cmd_t
+ entry $w_cmd \
+ -borderwidth 1 \
+ -relief sunken \
+ -width 40 \
+ -textvariable @command
+ grid $w.desc.cmd_l $w_cmd -sticky we -padx {0 5} -pady {0 3}
+
+ grid columnconfigure $w.desc 1 -weight 1
+ pack $w.desc -anchor nw -fill x -pady 5 -padx 5
+
+ checkbutton $w.confirm \
+ -text [mc "Show a dialog before running"] \
+ -variable @confirm -command [cb _check_enable_dlg]
+
+ labelframe $w.dlg -labelwidget $w.confirm
+
+ checkbutton $w.dlg.askbranch \
+ -text [mc "Ask the user to select a revision (sets \$REVISION)"] \
+ -variable @ask_branch -state disabled
+ pack $w.dlg.askbranch -anchor w -padx 15
+
+ checkbutton $w.dlg.askargs \
+ -text [mc "Ask the user for additional arguments (sets \$ARGS)"] \
+ -variable @ask_args -state disabled
+ pack $w.dlg.askargs -anchor w -padx 15
+
+ pack $w.dlg -anchor nw -fill x -pady {0 8} -padx 5
+
+ checkbutton $w.noconsole \
+ -text [mc "Don't show the command output window"] \
+ -variable @no_console
+ pack $w.noconsole -anchor w -padx 5
+
+ checkbutton $w.needsfile \
+ -text [mc "Run only if a diff is selected (\$FILENAME not empty)"] \
+ -variable @needs_file
+ pack $w.needsfile -anchor w -padx 5
+
+ bind $w <Visibility> [cb _visible]
+ bind $w <Key-Escape> [list destroy $w]
+ bind $w <Key-Return> [cb _add]\;break
+ tkwait window $w
+}
+
+method _check_enable_dlg {} {
+ if {$confirm} {
+ $w.dlg.askbranch configure -state normal
+ $w.dlg.askargs configure -state normal
+ } else {
+ $w.dlg.askbranch configure -state disabled
+ $w.dlg.askargs configure -state disabled
+ }
+}
+
+method _add {} {
+ global repo_config
+
+ if {$name eq {}} {
+ error_popup [mc "Please supply a name for the tool."]
+ focus $w_name
+ return
+ }
+
+ set item "guitool.$name.cmd"
+
+ if {[info exists repo_config($item)]} {
+ error_popup [mc "Tool '%s' already exists." $name]
+ focus $w_name
+ return
+ }
+
+ set cmd [list git config]
+ if {$add_global} { lappend cmd --global }
+ set items {}
+ if {$no_console} { lappend items "guitool.$name.noconsole" }
+ if {$needs_file} { lappend items "guitool.$name.needsfile" }
+ if {$confirm} {
+ if {$ask_args} { lappend items "guitool.$name.argprompt" }
+ if {$ask_branch} { lappend items "guitool.$name.revprompt" }
+ if {!$ask_args && !$ask_branch} {
+ lappend items "guitool.$name.confirm"
+ }
+ }
+
+ if {[catch {
+ eval $cmd [list $item $command]
+ foreach citem $items { eval $cmd [list $citem yes] }
+ } err]} {
+ error_popup [mc "Could not add tool:\n%s" $err]
+ } else {
+ set repo_config($item) $command
+ foreach citem $items { set repo_config($citem) yes }
+
+ tools_populate_all
+ }
+
+ destroy $w
+}
+
+method _validate_name {d S} {
+ if {$d == 1} {
+ if {[regexp {[~?*&\[\0\"\\\{]} $S]} {
+ return 0
+ }
+ }
+ return 1
+}
+
+method _visible {} {
+ grab $w
+ $w_name icursor end
+ focus $w_name
+}
+
+}
+
+class tools_remove {
+
+field w ; # widget path
+field w_names ; # name list
+
+constructor dialog {} {
+ global repo_config global_config system_config
+
+ load_config 1
+
+ make_toplevel top w
+ wm title $top [append "[appname] ([reponame]): " [mc "Remove Tool"]]
+ if {$top ne {.}} {
+ wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
+ wm transient $top .
+ }
+
+ label $w.header -text [mc "Remove Tool Commands"] -font font_uibold
+ pack $w.header -side top -fill x
+
+ frame $w.buttons
+ button $w.buttons.create -text [mc Remove] \
+ -default active \
+ -command [cb _remove]
+ pack $w.buttons.create -side right
+ button $w.buttons.cancel -text [mc Cancel] \
+ -command [list destroy $w]
+ pack $w.buttons.cancel -side right -padx 5
+ pack $w.buttons -side bottom -fill x -pady 10 -padx 10
+
+ frame $w.list
+ set w_names $w.list.l
+ listbox $w_names \
+ -height 10 \
+ -width 30 \
+ -selectmode extended \
+ -exportselection false \
+ -yscrollcommand [list $w.list.sby set]
+ scrollbar $w.list.sby -command [list $w.list.l yview]
+ pack $w.list.sby -side right -fill y
+ pack $w.list.l -side left -fill both -expand 1
+ pack $w.list -fill both -expand 1 -pady 5 -padx 5
+
+ set local_cnt 0
+ foreach fullname [tools_list] {
+ # Cannot delete system tools
+ if {[info exists system_config(guitool.$fullname.cmd)]} continue
+
+ $w_names insert end $fullname
+ if {![info exists global_config(guitool.$fullname.cmd)]} {
+ $w_names itemconfigure end -foreground blue
+ incr local_cnt
+ }
+ }
+
+ if {$local_cnt > 0} {
+ label $w.colorlbl -foreground blue \
+ -text [mc "(Blue denotes repository-local tools)"]
+ pack $w.colorlbl -fill x -pady 5 -padx 5
+ }
+
+ bind $w <Visibility> [cb _visible]
+ bind $w <Key-Escape> [list destroy $w]
+ bind $w <Key-Return> [cb _remove]\;break
+ tkwait window $w
+}
+
+method _remove {} {
+ foreach i [$w_names curselection] {
+ set name [$w_names get $i]
+
+ catch { git config --remove-section guitool.$name }
+ catch { git config --global --remove-section guitool.$name }
+ }
+
+ load_config 0
+ tools_populate_all
+
+ destroy $w
+}
+
+method _visible {} {
+ grab $w
+ focus $w_names
+}
+
+}
+
+class tools_askdlg {
+
+field w ; # widget path
+field w_rev {}; # revision browser
+field w_args {}; # arguments
+
+field is_ask_args 0; # has arguments field
+field is_ask_revs 0; # has revision browser
+
+field is_ok 0; # ok to start
+field argstr {}; # arguments
+
+constructor dialog {fullname} {
+ global M1B
+
+ set title [get_config "guitool.$fullname.title"]
+ if {$title eq {}} {
+ regsub {/} $fullname { / } title
+ }
+
+ make_toplevel top w -autodelete 0
+ wm title $top [append "[appname] ([reponame]): " $title]
+ if {$top ne {.}} {
+ wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
+ wm transient $top .
+ }
+
+ set prompt [get_config "guitool.$fullname.prompt"]
+ if {$prompt eq {}} {
+ set command [get_config "guitool.$fullname.cmd"]
+ set prompt [mc "Run Command: %s" $command]
+ }
+
+ label $w.header -text $prompt -font font_uibold
+ pack $w.header -side top -fill x
+
+ set argprompt [get_config "guitool.$fullname.argprompt"]
+ set revprompt [get_config "guitool.$fullname.revprompt"]
+
+ set is_ask_args [expr {$argprompt ne {}}]
+ set is_ask_revs [expr {$revprompt ne {}}]
+
+ if {$is_ask_args} {
+ if {$argprompt eq {yes} || $argprompt eq {true} || $argprompt eq {1}} {
+ set argprompt [mc "Arguments"]
+ }
+
+ labelframe $w.arg -text $argprompt
+
+ set w_args $w.arg.txt
+ entry $w_args \
+ -borderwidth 1 \
+ -relief sunken \
+ -width 40 \
+ -textvariable @argstr
+ pack $w_args -padx 5 -pady 5 -fill both
+ pack $w.arg -anchor nw -fill both -pady 5 -padx 5
+ }
+
+ if {$is_ask_revs} {
+ if {$revprompt eq {yes} || $revprompt eq {true} || $revprompt eq {1}} {
+ set revprompt [mc "Revision"]
+ }
+
+ if {[is_config_true "guitool.$fullname.revunmerged"]} {
+ set w_rev [::choose_rev::new_unmerged $w.rev $revprompt]
+ } else {
+ set w_rev [::choose_rev::new $w.rev $revprompt]
+ }
+
+ pack $w.rev -anchor nw -fill both -expand 1 -pady 5 -padx 5
+ }
+
+ frame $w.buttons
+ if {$is_ask_revs} {
+ button $w.buttons.visualize \
+ -text [mc Visualize] \
+ -command [cb _visualize]
+ pack $w.buttons.visualize -side left
+ }
+ button $w.buttons.ok \
+ -text [mc OK] \
+ -command [cb _start]
+ pack $w.buttons.ok -side right
+ button $w.buttons.cancel \
+ -text [mc "Cancel"] \
+ -command [cb _cancel]
+ pack $w.buttons.cancel -side right -padx 5
+ pack $w.buttons -side bottom -fill x -pady 10 -padx 10
+
+ bind $w <$M1B-Key-Return> [cb _start]
+ bind $w <Key-Return> [cb _start]
+ bind $w <Key-Escape> [cb _cancel]
+ wm protocol $w WM_DELETE_WINDOW [cb _cancel]
+
+ bind $w <Visibility> [cb _visible]
+ return $this
+}
+
+method execute {} {
+ tkwait window $w
+ set rv $is_ok
+ delete_this
+ return $rv
+}
+
+method _visible {} {
+ grab $w
+ if {$is_ask_args} {
+ focus $w_args
+ } elseif {$is_ask_revs} {
+ $w_rev focus_filter
+ }
+}
+
+method _cancel {} {
+ wm protocol $w WM_DELETE_WINDOW {}
+ destroy $w
+}
+
+method _rev {} {
+ if {[catch {$w_rev commit_or_die}]} {
+ return {}
+ }
+ return [$w_rev get]
+}
+
+method _visualize {} {
+ global current_branch
+ set rev [_rev $this]
+ if {$rev ne {}} {
+ do_gitk [list --left-right "$current_branch...$rev"]
+ }
+}
+
+method _start {} {
+ global env
+
+ if {$is_ask_revs} {
+ set name [_rev $this]
+ if {$name eq {}} {
+ return
+ }
+ set env(REVISION) $name
+ }
+
+ if {$is_ask_args} {
+ set env(ARGS) $argstr
+ }
+
+ set is_ok 1
+ _cancel $this
+}
+
+}
diff --git a/git-gui/lib/transport.tcl b/git-gui/lib/transport.tcl
index 8e6a9d0a60..b18d9c7a1b 100644
--- a/git-gui/lib/transport.tcl
+++ b/git-gui/lib/transport.tcl
@@ -33,10 +33,15 @@ proc push_to {remote} {
proc start_push_anywhere_action {w} {
global push_urltype push_remote push_url push_thin push_tags
global push_force
+ global repo_config
+ set is_mirror 0
set r_url {}
switch -- $push_urltype {
- remote {set r_url $push_remote}
+ remote {
+ set r_url $push_remote
+ catch {set is_mirror $repo_config(remote.$push_remote.mirror)}
+ }
url {set r_url $push_url}
}
if {$r_url eq {}} return
@@ -53,23 +58,29 @@ proc start_push_anywhere_action {w} {
lappend cmd --tags
}
lappend cmd $r_url
- set cnt 0
- foreach i [$w.source.l curselection] {
- set b [$w.source.l get $i]
- lappend cmd "refs/heads/$b:refs/heads/$b"
- incr cnt
- }
- if {$cnt == 0} {
- return
- } elseif {$cnt == 1} {
- set unit branch
+ if {$is_mirror} {
+ set cons [console::new \
+ [mc "push %s" $r_url] \
+ [mc "Mirroring to %s" $r_url]]
} else {
- set unit branches
- }
+ set cnt 0
+ foreach i [$w.source.l curselection] {
+ set b [$w.source.l get $i]
+ lappend cmd "refs/heads/$b:refs/heads/$b"
+ incr cnt
+ }
+ if {$cnt == 0} {
+ return
+ } elseif {$cnt == 1} {
+ set unit branch
+ } else {
+ set unit branches
+ }
- set cons [console::new \
- [mc "push %s" $r_url] \
- [mc "Pushing %s %s to %s" $cnt $unit $r_url]]
+ set cons [console::new \
+ [mc "push %s" $r_url] \
+ [mc "Pushing %s %s to %s" $cnt $unit $r_url]]
+ }
console::exec $cons $cmd
destroy $w
}
@@ -135,7 +146,7 @@ proc do_push_anywhere {} {
set push_urltype url
}
radiobutton $w.dest.url_r \
- -text [mc "Arbitrary URL:"] \
+ -text [mc "Arbitrary Location:"] \
-value url \
-variable push_urltype
entry $w.dest.url_t \
diff --git a/git-gui/po/de.po b/git-gui/po/de.po
index 793cca1e79..a6f730b4eb 100644
--- a/git-gui/po/de.po
+++ b/git-gui/po/de.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: git-gui\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-09-13 10:20+0200\n"
-"PO-Revision-Date: 2008-09-13 10:24+0200\n"
+"POT-Creation-Date: 2008-12-06 20:51+0100\n"
+"PO-Revision-Date: 2008-12-06 21:22+0100\n"
"Last-Translator: Christian Stimming <stimming@tuhh.de>\n"
"Language-Team: German\n"
"MIME-Version: 1.0\n"
@@ -86,7 +86,15 @@ msgstr "Dateistatus aktualisieren..."
msgid "Scanning for modified files ..."
msgstr "Nach geänderten Dateien suchen..."
-#: git-gui.sh:1324 lib/browser.tcl:246
+#: git-gui.sh:1367
+msgid "Calling prepare-commit-msg hook..."
+msgstr "Aufrufen der Eintragen-Vorbereiten-Kontrolle..."
+
+#: git-gui.sh:1384
+msgid "Commit declined by prepare-commit-msg hook."
+msgstr "Eintragen abgelehnt durch Eintragen-Vorbereiten-Kontrolle (»prepare-commit hook«)."
+
+#: git-gui.sh:1542 lib/browser.tcl:246
msgid "Ready."
msgstr "Bereit."
@@ -170,7 +178,15 @@ msgstr "Zusammenführen"
msgid "Remote"
msgstr "Andere Archive"
-#: git-gui.sh:1879
+#: git-gui.sh:2293
+msgid "Tools"
+msgstr "Werkzeuge"
+
+#: git-gui.sh:2302
+msgid "Explore Working Copy"
+msgstr "Arbeitskopie im Dateimanager"
+
+#: git-gui.sh:2247
msgid "Browse Current Branch's Files"
msgstr "Aktuellen Zweig durchblättern"
@@ -267,7 +283,15 @@ msgstr "Löschen..."
msgid "Reset..."
msgstr "Zurücksetzen..."
-#: git-gui.sh:2002 git-gui.sh:2389
+#: git-gui.sh:2372
+msgid "Done"
+msgstr "Fertig"
+
+#: git-gui.sh:2374
+msgid "Commit@@verb"
+msgstr "Eintragen"
+
+#: git-gui.sh:2383 git-gui.sh:2786
msgid "New Commit"
msgstr "Neue Version"
@@ -307,11 +331,7 @@ msgstr "Mehr Zeilen anzeigen"
msgid "Sign Off"
msgstr "Abzeichnen"
-#: git-gui.sh:2053 git-gui.sh:2372
-msgid "Commit@@verb"
-msgstr "Eintragen"
-
-#: git-gui.sh:2064
+#: git-gui.sh:2458
msgid "Local Merge..."
msgstr "Lokales Zusammenführen..."
@@ -319,11 +339,19 @@ msgstr "Lokales Zusammenführen..."
msgid "Abort Merge..."
msgstr "Zusammenführen abbrechen..."
-#: git-gui.sh:2081
+#: git-gui.sh:2475
+msgid "Add..."
+msgstr "Hinzufügen..."
+
+#: git-gui.sh:2479
msgid "Push..."
msgstr "Versenden..."
-#: git-gui.sh:2197 git-gui.sh:2219 lib/about.tcl:14
+#: git-gui.sh:2483
+msgid "Delete Branch..."
+msgstr "Zweig löschen..."
+
+#: git-gui.sh:2493 git-gui.sh:2515 lib/about.tcl:14
#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50
#, tcl-format
msgid "About %s"
@@ -337,7 +365,11 @@ msgstr "Einstellungen..."
msgid "Options..."
msgstr "Optionen..."
-#: git-gui.sh:2113 lib/choose_repository.tcl:47
+#: git-gui.sh:2576
+msgid "Remove..."
+msgstr "Entfernen..."
+
+#: git-gui.sh:2585 lib/choose_repository.tcl:50
msgid "Help"
msgstr "Hilfe"
@@ -345,7 +377,11 @@ msgstr "Hilfe"
msgid "Online Documentation"
msgstr "Online-Dokumentation"
-#: git-gui.sh:2238
+#: git-gui.sh:2614 lib/choose_repository.tcl:47 lib/choose_repository.tcl:56
+msgid "Show SSH Key"
+msgstr "SSH-Schlüssel anzeigen"
+
+#: git-gui.sh:2707
#, tcl-format
msgid "fatal: cannot stat path %s: No such file or directory"
msgstr ""
@@ -416,7 +452,11 @@ msgstr "Schriftgröße verkleinern"
msgid "Increase Font Size"
msgstr "Schriftgröße vergrößern"
-#: git-gui.sh:2870
+#: git-gui.sh:3033 lib/blame.tcl:281
+msgid "Encoding"
+msgstr "Zeichenkodierung"
+
+#: git-gui.sh:3044
msgid "Apply/Reverse Hunk"
msgstr "Kontext anwenden/umkehren"
@@ -440,11 +480,7 @@ msgstr "Lokale Version benutzen"
msgid "Revert To Base"
msgstr "Ursprüngliche Version benutzen"
-#: git-gui.sh:2906
-msgid "Stage Working Copy"
-msgstr "Arbeitskopie bereitstellen"
-
-#: git-gui.sh:2925
+#: git-gui.sh:3091
msgid "Unstage Hunk From Commit"
msgstr "Kontext aus Bereitstellung herausnehmen"
@@ -522,7 +558,11 @@ msgstr "Version:"
msgid "Copy Commit"
msgstr "Version kopieren"
-#: lib/blame.tcl:260
+#: lib/blame.tcl:275
+msgid "Find Text..."
+msgstr "Text suchen..."
+
+#: lib/blame.tcl:284
msgid "Do Full Copy Detection"
msgstr "Volle Kopie-Erkennung"
@@ -583,7 +623,11 @@ msgstr "Eintragender:"
msgid "Original File:"
msgstr "Ursprüngliche Datei:"
-#: lib/blame.tcl:990
+#: lib/blame.tcl:1021
+msgid "Cannot find HEAD commit:"
+msgstr "Zweigspitze (»HEAD«) kann nicht gefunden werden:"
+
+#: lib/blame.tcl:1076
msgid "Cannot find parent commit:"
msgstr "Elternversion kann nicht gefunden werden:"
@@ -1018,7 +1062,7 @@ msgstr "Zuletzt benutztes Projektarchiv öffnen:"
msgid "Failed to create repository %s:"
msgstr "Projektarchiv »%s« konnte nicht erstellt werden:"
-#: lib/choose_repository.tcl:381 lib/choose_repository.tcl:478
+#: lib/choose_repository.tcl:387
msgid "Directory:"
msgstr "Verzeichnis:"
@@ -1027,12 +1071,12 @@ msgstr "Verzeichnis:"
msgid "Git Repository"
msgstr "Git Projektarchiv"
-#: lib/choose_repository.tcl:437
+#: lib/choose_repository.tcl:442
#, tcl-format
msgid "Directory %s already exists."
msgstr "Verzeichnis »%s« existiert bereits."
-#: lib/choose_repository.tcl:441
+#: lib/choose_repository.tcl:446
#, tcl-format
msgid "File %s already exists."
msgstr "Datei »%s« existiert bereits."
@@ -1041,11 +1085,15 @@ msgstr "Datei »%s« existiert bereits."
msgid "Clone"
msgstr "Klonen"
-#: lib/choose_repository.tcl:468
-msgid "URL:"
-msgstr "URL:"
+#: lib/choose_repository.tcl:473
+msgid "Source Location:"
+msgstr "Herkunft:"
-#: lib/choose_repository.tcl:489
+#: lib/choose_repository.tcl:484
+msgid "Target Directory:"
+msgstr "Zielverzeichnis:"
+
+#: lib/choose_repository.tcl:490
msgid "Clone Type:"
msgstr "Art des Klonens:"
@@ -1525,7 +1573,31 @@ msgstr ""
msgid "Loading diff of %s..."
msgstr "Vergleich von »%s« laden..."
-#: lib/diff.tcl:114 lib/diff.tcl:184
+#: lib/diff.tcl:120
+msgid ""
+"LOCAL: deleted\n"
+"REMOTE:\n"
+msgstr ""
+"LOKAL: gelöscht\n"
+"ANDERES:\n"
+
+#: lib/diff.tcl:125
+msgid ""
+"REMOTE: deleted\n"
+"LOCAL:\n"
+msgstr ""
+"ANDERES: gelöscht\n"
+"LOKAL:\n"
+
+#: lib/diff.tcl:132
+msgid "LOCAL:\n"
+msgstr "LOKAL:\n"
+
+#: lib/diff.tcl:135
+msgid "REMOTE:\n"
+msgstr "ANDERES:\n"
+
+#: lib/diff.tcl:197 lib/diff.tcl:296
#, tcl-format
msgid "Unable to display %s"
msgstr "Datei »%s« kann nicht angezeigt werden"
@@ -1542,7 +1614,27 @@ msgstr "Git-Projektarchiv (Unterprojekt)"
msgid "* Binary file (not showing content)."
msgstr "* Binärdatei (Inhalt wird nicht angezeigt)"
-#: lib/diff.tcl:313
+#: lib/diff.tcl:222
+#, tcl-format
+msgid ""
+"* Untracked file is %d bytes.\n"
+"* Showing only first %d bytes.\n"
+msgstr ""
+"* Datei nicht unter Versionskontrolle, Dateigröße %d Bytes.\n"
+"* Nur erste %d Bytes werden angezeigt.\n"
+
+#: lib/diff.tcl:228
+#, tcl-format
+msgid ""
+"\n"
+"* Untracked file clipped here by %s.\n"
+"* To see the entire file, use an external editor.\n"
+msgstr ""
+"\n"
+"* Datei nicht unter Versionskontrolle, hier abgeschnitten durch %s.\n"
+"* Zum Ansehen der vollständigen Datei externen Editor benutzen.\n"
+
+#: lib/diff.tcl:436
msgid "Failed to unstage selected hunk."
msgstr ""
"Fehler beim Herausnehmen des gewählten Kontexts aus der Bereitstellung."
@@ -1559,6 +1651,19 @@ msgstr "Fehler beim Herausnehmen der gewählten Zeile aus der Bereitstellung."
msgid "Failed to stage selected line."
msgstr "Fehler beim Bereitstellen der gewählten Zeile."
+#: lib/encoding.tcl:443
+msgid "Default"
+msgstr "Voreinstellung"
+
+#: lib/encoding.tcl:448
+#, tcl-format
+msgid "System (%s)"
+msgstr "Systemweit (%s)"
+
+#: lib/encoding.tcl:459 lib/encoding.tcl:465
+msgid "Other"
+msgstr "Andere"
+
#: lib/error.tcl:20 lib/error.tcl:114
msgid "error"
msgstr "Fehler"
@@ -1811,7 +1916,12 @@ msgstr ""
"Diese Operation kann nur rückgängig gemacht werden, wenn die\n"
"Zusammenführung erneut gestartet wird."
-#: lib/mergetool.tcl:32
+#: lib/mergetool.tcl:45
+#, tcl-format
+msgid "File %s seems to have unresolved conflicts, still stage?"
+msgstr "Datei »%s« hat nicht aufgelöste Konflikte. Trotzdem bereitstellen?"
+
+#: lib/mergetool.tcl:60
#, tcl-format
msgid "Adding resolution for %s"
msgstr "Auflösung hinzugefügt für %s"
@@ -1868,12 +1978,17 @@ msgstr "Zusammenführungswerkzeug starten..."
msgid "Merge tool failed."
msgstr "Zusammenführungswerkzeug fehlgeschlagen."
-#: lib/mergetool.tcl:353
+#: lib/option.tcl:11
+#, tcl-format
+msgid "Invalid global encoding '%s'"
+msgstr "Ungültige globale Zeichenkodierung »%s«"
+
+#: lib/option.tcl:19
#, tcl-format
-msgid "File %s unchanged, still accept as resolved?"
-msgstr "Datei »%s« unverändert. Trotzdem Konflikt als gelöst akzeptieren?"
+msgid "Invalid repo encoding '%s'"
+msgstr "Ungültige Archiv-Zeichenkodierung »%s«"
-#: lib/option.tcl:95
+#: lib/option.tcl:117
msgid "Restore Defaults"
msgstr "Voreinstellungen wiederherstellen"
@@ -1950,7 +2065,15 @@ msgstr "Textbreite der Versionsbeschreibung"
msgid "New Branch Name Template"
msgstr "Namensvorschlag für neue Zweige"
-#: lib/option.tcl:192
+#: lib/option.tcl:155
+msgid "Default File Contents Encoding"
+msgstr "Voreingestellte Zeichenkodierung"
+
+#: lib/option.tcl:203
+msgid "Change"
+msgstr "Ändern"
+
+#: lib/option.tcl:230
msgid "Spelling Dictionary:"
msgstr "Wörterbuch Rechtschreibprüfung:"
@@ -1975,9 +2098,86 @@ msgstr "Einstellungen"
msgid "Failed to completely save options:"
msgstr "Optionen konnten nicht gespeichert werden:"
+#: lib/remote_add.tcl:19
+msgid "Add Remote"
+msgstr "Anderes Archiv hinzufügen"
+
+#: lib/remote_add.tcl:24
+msgid "Add New Remote"
+msgstr "Neues anderes Archiv hinzufügen"
+
+#: lib/remote_add.tcl:28
+msgid "Add"
+msgstr "Hinzufügen"
+
+#: lib/remote_add.tcl:37
+msgid "Remote Details"
+msgstr "Einzelheiten des anderen Archivs"
+
+#: lib/remote_add.tcl:50
+msgid "Location:"
+msgstr "Adresse:"
+
+#: lib/remote_add.tcl:62
+msgid "Further Action"
+msgstr "Weitere Aktion jetzt"
+
+#: lib/remote_add.tcl:65
+msgid "Fetch Immediately"
+msgstr "Gleich anfordern"
+
+#: lib/remote_add.tcl:71
+msgid "Initialize Remote Repository and Push"
+msgstr "Anderes Archiv initialisieren und dahin versenden"
+
+#: lib/remote_add.tcl:77
+msgid "Do Nothing Else Now"
+msgstr "Nichts tun"
+
+#: lib/remote_add.tcl:101
+msgid "Please supply a remote name."
+msgstr "Bitte geben Sie einen Namen des anderen Archivs an."
+
+#: lib/remote_add.tcl:114
+#, tcl-format
+msgid "'%s' is not an acceptable remote name."
+msgstr "»%s« ist kein zulässiger Name eines anderen Archivs."
+
+#: lib/remote_add.tcl:125
+#, tcl-format
+msgid "Failed to add remote '%s' of location '%s'."
+msgstr "Fehler beim Hinzufügen des anderen Archivs »%s« aus Herkunftsort »%s«."
+
+#: lib/remote_add.tcl:133 lib/transport.tcl:6
+#, tcl-format
+msgid "fetch %s"
+msgstr "»%s« anfordern"
+
+#: lib/remote_add.tcl:134
+#, tcl-format
+msgid "Fetching the %s"
+msgstr "»%s« anfordern"
+
+#: lib/remote_add.tcl:157
+#, tcl-format
+msgid "Do not know how to initialize repository at location '%s'."
+msgstr ""
+"Initialisieren eines anderen Archivs an Adresse »%s« ist nicht möglich."
+
+#: lib/remote_add.tcl:163 lib/transport.tcl:25 lib/transport.tcl:63
+#: lib/transport.tcl:81
+#, tcl-format
+msgid "push %s"
+msgstr "»%s« versenden..."
+
+#: lib/remote_add.tcl:164
+#, tcl-format
+msgid "Setting up the %s (at %s)"
+msgstr "Einrichten von »%s« an »%s«"
+
#: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34
-msgid "Delete Remote Branch"
-msgstr "Zweig in anderem Projektarchiv löschen"
+msgid "Delete Branch Remotely"
+msgstr "Zweig in anderem Archiv löschen"
#: lib/remote_branch_delete.tcl:47
msgid "From Repository"
@@ -1988,8 +2188,8 @@ msgid "Remote:"
msgstr "Anderes Archiv:"
#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:138
-msgid "Arbitrary URL:"
-msgstr "Archiv-URL:"
+msgid "Arbitrary Location:"
+msgstr "Adresse:"
#: lib/remote_branch_delete.tcl:84
msgid "Branches"
@@ -2061,7 +2261,11 @@ msgstr "Kein Projektarchiv ausgewählt."
msgid "Scanning %s..."
msgstr "»%s« laden..."
-#: lib/remote.tcl:165
+#: lib/remote.tcl:163
+msgid "Remove Remote"
+msgstr "Anderes Archiv entfernen"
+
+#: lib/remote.tcl:168
msgid "Prune from"
msgstr "Aufräumen von"
@@ -2073,6 +2277,22 @@ msgstr "Anfordern von"
msgid "Push to"
msgstr "Versenden nach"
+#: lib/search.tcl:21
+msgid "Find:"
+msgstr "Suchen:"
+
+#: lib/search.tcl:22
+msgid "Next"
+msgstr "Nächster"
+
+#: lib/search.tcl:23
+msgid "Prev"
+msgstr "Voriger"
+
+#: lib/search.tcl:25
+msgid "Case-Sensitive"
+msgstr "Groß-/Kleinschreibung unterscheiden"
+
#: lib/shortcut.tcl:20 lib/shortcut.tcl:61
msgid "Cannot write shortcut:"
msgstr "Fehler beim Schreiben der Verknüpfung:"
@@ -2118,15 +2338,181 @@ msgstr "Unerwartetes EOF vom Rechtschreibprüfungsprogramm"
msgid "Spell Checker Failed"
msgstr "Rechtschreibprüfung fehlgeschlagen"
+#: lib/sshkey.tcl:31
+msgid "No keys found."
+msgstr "Keine Schlüssel gefunden."
+
+#: lib/sshkey.tcl:34
+#, tcl-format
+msgid "Found a public key in: %s"
+msgstr "Öffentlicher Schlüssel gefunden in: %s"
+
+#: lib/sshkey.tcl:40
+msgid "Generate Key"
+msgstr "Schlüssel erzeugen"
+
+#: lib/sshkey.tcl:56
+msgid "Copy To Clipboard"
+msgstr "In Zwischenablage kopieren"
+
+#: lib/sshkey.tcl:70
+msgid "Your OpenSSH Public Key"
+msgstr "Ihr OpenSSH öffenlicher Schlüssel"
+
+#: lib/sshkey.tcl:78
+msgid "Generating..."
+msgstr "Erzeugen..."
+
+#: lib/sshkey.tcl:84
+#, tcl-format
+msgid ""
+"Could not start ssh-keygen:\n"
+"\n"
+"%s"
+msgstr ""
+"Konnte »ssh-keygen« nicht starten:\n"
+"\n"
+"%s"
+
+#: lib/sshkey.tcl:111
+msgid "Generation failed."
+msgstr "Schlüsselerzeugung fehlgeschlagen."
+
+#: lib/sshkey.tcl:118
+msgid "Generation succeded, but no keys found."
+msgstr "Schlüsselerzeugung erfolgreich, aber keine Schlüssel gefunden."
+
+#: lib/sshkey.tcl:121
+#, tcl-format
+msgid "Your key is in: %s"
+msgstr "Ihr Schlüssel ist abgelegt in: %s"
+
#: lib/status_bar.tcl:83
#, tcl-format
msgid "%s ... %*i of %*i %s (%3i%%)"
msgstr "%s ... %*i von %*i %s (%3i%%)"
-#: lib/transport.tcl:6
+#: lib/tools_dlg.tcl:22
+msgid "Add Tool"
+msgstr "Werkzeug hinzufügen"
+
+#: lib/tools_dlg.tcl:28
+msgid "Add New Tool Command"
+msgstr "Neues Kommando für Werkzeug hinzufügen"
+
+#: lib/tools_dlg.tcl:33
+msgid "Add globally"
+msgstr "Global hinzufügen"
+
+#: lib/tools_dlg.tcl:45
+msgid "Tool Details"
+msgstr "Einzelheiten des Werkzeugs"
+
+#: lib/tools_dlg.tcl:48
+msgid "Use '/' separators to create a submenu tree:"
+msgstr "Benutzen Sie einen Schrägstrich »/«, um Untermenüs zu erstellen:"
+
+#: lib/tools_dlg.tcl:61
+msgid "Command:"
+msgstr "Kommando:"
+
+#: lib/tools_dlg.tcl:74
+msgid "Show a dialog before running"
+msgstr "Bestätigungsfrage vor Starten anzeigen"
+
+#: lib/tools_dlg.tcl:80
+msgid "Ask the user to select a revision (sets $REVISION)"
+msgstr "Benutzer nach Version fragen (setzt $REVISION)"
+
+#: lib/tools_dlg.tcl:85
+msgid "Ask the user for additional arguments (sets $ARGS)"
+msgstr "Benutzer nach zusätzlichen Argumenten fragen (setzt $ARGS)"
+
+#: lib/tools_dlg.tcl:92
+msgid "Don't show the command output window"
+msgstr "Kein Ausgabefenster zeigen"
+
+#: lib/tools_dlg.tcl:97
+msgid "Run only if a diff is selected ($FILENAME not empty)"
+msgstr "Nur starten, wenn ein Vergleich gewählt ist ($FILENAME ist nicht leer)"
+
+#: lib/tools_dlg.tcl:121
+msgid "Please supply a name for the tool."
+msgstr "Bitte geben Sie einen Werkzeugnamen an."
+
+#: lib/tools_dlg.tcl:129
#, tcl-format
-msgid "fetch %s"
-msgstr "»%s« anfordern"
+msgid "Tool '%s' already exists."
+msgstr "Werkzeug »%s« existiert bereits."
+
+#: lib/tools_dlg.tcl:151
+#, tcl-format
+msgid ""
+"Could not add tool:\n"
+"%s"
+msgstr ""
+"Werkzeug konnte nicht hinzugefügt werden:\n"
+"\n"
+"%s"
+
+#: lib/tools_dlg.tcl:190
+msgid "Remove Tool"
+msgstr "Werkzeug entfernen"
+
+#: lib/tools_dlg.tcl:196
+msgid "Remove Tool Commands"
+msgstr "Werkzeugkommandos entfernen"
+
+#: lib/tools_dlg.tcl:200
+msgid "Remove"
+msgstr "Entfernen"
+
+#: lib/tools_dlg.tcl:236
+msgid "(Blue denotes repository-local tools)"
+msgstr "(Werkzeuge für lokales Archiv werden in Blau angezeigt)"
+
+#: lib/tools_dlg.tcl:297
+#, tcl-format
+msgid "Run Command: %s"
+msgstr "Kommando aufrufen: %s"
+
+#: lib/tools_dlg.tcl:311
+msgid "Arguments"
+msgstr "Argumente"
+
+#: lib/tools_dlg.tcl:348
+msgid "OK"
+msgstr "Ok"
+
+#: lib/tools.tcl:75
+#, tcl-format
+msgid "Running %s requires a selected file."
+msgstr "Um »%s« zu starten, muss eine Datei ausgewählt sein."
+
+#: lib/tools.tcl:90
+#, tcl-format
+msgid "Are you sure you want to run %s?"
+msgstr "Wollen Sie %s wirklich starten?"
+
+#: lib/tools.tcl:110
+#, tcl-format
+msgid "Tool: %s"
+msgstr "Werkzeug: %s"
+
+#: lib/tools.tcl:111
+#, tcl-format
+msgid "Running: %s"
+msgstr "Starten: %s"
+
+#: lib/tools.tcl:149
+#, tcl-format
+msgid "Tool completed succesfully: %s"
+msgstr "Werkzeug erfolgreich abgeschlossen: %s"
+
+#: lib/tools.tcl:151
+#, tcl-format
+msgid "Tool failed: %s"
+msgstr "Werkzeug fehlgeschlagen: %s"
#: lib/transport.tcl:7
#, tcl-format
@@ -2143,17 +2529,17 @@ msgstr "Aufräumen von »%s«"
msgid "Pruning tracking branches deleted from %s"
msgstr "Übernahmezweige aufräumen und entfernen, die in »%s« gelöscht wurden"
-#: lib/transport.tcl:25 lib/transport.tcl:71
-#, tcl-format
-msgid "push %s"
-msgstr "»%s« versenden..."
-
#: lib/transport.tcl:26
#, tcl-format
msgid "Pushing changes to %s"
msgstr "Änderungen nach »%s« versenden"
-#: lib/transport.tcl:72
+#: lib/transport.tcl:64
+#, tcl-format
+msgid "Mirroring to %s"
+msgstr "Spiegeln nach %s"
+
+#: lib/transport.tcl:82
#, tcl-format
msgid "Pushing %s %s to %s"
msgstr "%s %s nach %s versenden"
diff --git a/git-gui/po/fr.po b/git-gui/po/fr.po
index 26b866f551..45773ab3d8 100644
--- a/git-gui/po/fr.po
+++ b/git-gui/po/fr.po
@@ -1,4 +1,4 @@
-# translation of fr.po to Français
+# translation of fr.po to French
# Translation of git-gui to French.
# Copyright (C) 2008 Shawn Pearce, et al.
# This file is distributed under the same license as the git package.
@@ -9,43 +9,43 @@ msgid ""
msgstr ""
"Project-Id-Version: fr\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-08-02 14:45-0700\n"
-"PO-Revision-Date: 2008-08-11 17:12-0400\n"
-"Last-Translator: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com>\n"
-"Language-Team: Français <fr@li.org>\n"
+"POT-Creation-Date: 2008-11-16 13:56-0800\n"
+"PO-Revision-Date: 2008-11-20 10:20+0100\n"
+"Last-Translator: Christian Couder <chriscool@tuxfamily.org>\n"
+"Language-Team: French\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: KBabel 1.11.4\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-#: git-gui.sh:41 git-gui.sh:688 git-gui.sh:702 git-gui.sh:715 git-gui.sh:798
-#: git-gui.sh:817
+#: git-gui.sh:41 git-gui.sh:737 git-gui.sh:751 git-gui.sh:764 git-gui.sh:847
+#: git-gui.sh:866
msgid "git-gui: fatal error"
msgstr "git-gui: erreur fatale"
-#: git-gui.sh:644
+#: git-gui.sh:689
#, tcl-format
msgid "Invalid font specified in %s:"
msgstr "Police invalide spécifiée dans %s :"
-#: git-gui.sh:674
+#: git-gui.sh:723
msgid "Main Font"
msgstr "Police principale"
-#: git-gui.sh:675
+#: git-gui.sh:724
msgid "Diff/Console Font"
msgstr "Police diff/console"
-#: git-gui.sh:689
+#: git-gui.sh:738
msgid "Cannot find git in PATH."
msgstr "Impossible de trouver git dans PATH."
-#: git-gui.sh:716
+#: git-gui.sh:765
msgid "Cannot parse Git version string:"
msgstr "Impossible de parser la version de Git :"
-#: git-gui.sh:734
+#: git-gui.sh:783
#, tcl-format
msgid ""
"Git version cannot be determined.\n"
@@ -64,381 +64,446 @@ msgstr ""
"\n"
"Peut'on considérer que '%s' est en version 1.5.0 ?\n"
-#: git-gui.sh:972
+#: git-gui.sh:1062
msgid "Git directory not found:"
msgstr "Impossible de trouver le répertoire git :"
-#: git-gui.sh:979
+#: git-gui.sh:1069
msgid "Cannot move to top of working directory:"
msgstr "Impossible d'aller à la racine du répertoire de travail :"
-#: git-gui.sh:986
+#: git-gui.sh:1076
msgid "Cannot use funny .git directory:"
msgstr "Impossible d'utiliser le répertoire .git:"
-#: git-gui.sh:991
+#: git-gui.sh:1081
msgid "No working directory"
msgstr "Aucun répertoire de travail"
-#: git-gui.sh:1138 lib/checkout_op.tcl:305
+#: git-gui.sh:1247 lib/checkout_op.tcl:305
msgid "Refreshing file status..."
msgstr "Rafraichissement du status des fichiers..."
-#: git-gui.sh:1194
+#: git-gui.sh:1303
msgid "Scanning for modified files ..."
msgstr "Recherche de fichiers modifiés..."
-#: git-gui.sh:1369 lib/browser.tcl:246
+#: git-gui.sh:1367
+msgid "Calling prepare-commit-msg hook..."
+msgstr "Lancement de l'action de préparation du message de commit..."
+
+#: git-gui.sh:1384
+msgid "Commit declined by prepare-commit-msg hook."
+msgstr "Commit refusé par l'action de préparation du message de commit."
+
+#: git-gui.sh:1542 lib/browser.tcl:246
msgid "Ready."
msgstr "Prêt."
-#: git-gui.sh:1635
+#: git-gui.sh:1819
msgid "Unmodified"
msgstr "Non modifié"
-#: git-gui.sh:1637
+#: git-gui.sh:1821
msgid "Modified, not staged"
msgstr "Modifié, pas indexé"
-#: git-gui.sh:1638 git-gui.sh:1643
+#: git-gui.sh:1822 git-gui.sh:1830
msgid "Staged for commit"
msgstr "Indexé"
-#: git-gui.sh:1639 git-gui.sh:1644
+#: git-gui.sh:1823 git-gui.sh:1831
msgid "Portions staged for commit"
msgstr "Portions indexées"
-#: git-gui.sh:1640 git-gui.sh:1645
+#: git-gui.sh:1824 git-gui.sh:1832
msgid "Staged for commit, missing"
msgstr "Indexés, manquant"
-#: git-gui.sh:1642
+#: git-gui.sh:1826
+msgid "File type changed, not staged"
+msgstr "Le type de fichier a changé, non indexé"
+
+#: git-gui.sh:1827
+msgid "File type changed, staged"
+msgstr "Le type de fichier a changé, indexé"
+
+#: git-gui.sh:1829
msgid "Untracked, not staged"
msgstr "Non versionné, non indexé"
-#: git-gui.sh:1647
+#: git-gui.sh:1834
msgid "Missing"
msgstr "Manquant"
-#: git-gui.sh:1648
+#: git-gui.sh:1835
msgid "Staged for removal"
msgstr "Indexé pour suppression"
-#: git-gui.sh:1649
+#: git-gui.sh:1836
msgid "Staged for removal, still present"
msgstr "Indexé pour suppression, toujours présent"
-#: git-gui.sh:1651 git-gui.sh:1652 git-gui.sh:1653 git-gui.sh:1654
+#: git-gui.sh:1838 git-gui.sh:1839 git-gui.sh:1840 git-gui.sh:1841
+#: git-gui.sh:1842 git-gui.sh:1843
msgid "Requires merge resolution"
msgstr "Nécessite la résolution d'une fusion"
-#: git-gui.sh:1689
+#: git-gui.sh:1878
msgid "Starting gitk... please wait..."
msgstr "Lancement de gitk... un instant..."
-#: git-gui.sh:1698
+#: git-gui.sh:1887
msgid "Couldn't find gitk in PATH"
msgstr "Impossible de trouver gitk dans PATH."
-#: git-gui.sh:1948 lib/choose_repository.tcl:36
+#: git-gui.sh:2280 lib/choose_repository.tcl:36
msgid "Repository"
msgstr "Dépôt"
-#: git-gui.sh:1949
+#: git-gui.sh:2281
msgid "Edit"
msgstr "Edition"
-#: git-gui.sh:1951 lib/choose_rev.tcl:561
+#: git-gui.sh:2283 lib/choose_rev.tcl:561
msgid "Branch"
msgstr "Branche"
-#: git-gui.sh:1954 lib/choose_rev.tcl:548
+#: git-gui.sh:2286 lib/choose_rev.tcl:548
msgid "Commit@@noun"
msgstr "Commit"
-#: git-gui.sh:1957 lib/merge.tcl:120 lib/merge.tcl:149 lib/merge.tcl:167
+#: git-gui.sh:2289 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168
msgid "Merge"
msgstr "Fusionner"
-#: git-gui.sh:1958 lib/choose_rev.tcl:557
+#: git-gui.sh:2290 lib/choose_rev.tcl:557
msgid "Remote"
msgstr "Dépôt distant"
-#: git-gui.sh:1967
+#: git-gui.sh:2293
+msgid "Tools"
+msgstr "Outils"
+
+#: git-gui.sh:2302
+msgid "Explore Working Copy"
+msgstr "Explorer la copie de travail"
+
+#: git-gui.sh:2307
msgid "Browse Current Branch's Files"
msgstr "Naviguer dans la branche courante"
-#: git-gui.sh:1971
+#: git-gui.sh:2311
msgid "Browse Branch Files..."
msgstr "Naviguer dans la branche..."
-#: git-gui.sh:1976
+#: git-gui.sh:2316
msgid "Visualize Current Branch's History"
msgstr "Visualiser historique branche courante"
-#: git-gui.sh:1980
+#: git-gui.sh:2320
msgid "Visualize All Branch History"
msgstr "Voir l'historique de toutes les branches"
-#: git-gui.sh:1987
+#: git-gui.sh:2327
#, tcl-format
msgid "Browse %s's Files"
msgstr "Naviguer l'arborescence de %s"
-#: git-gui.sh:1989
+#: git-gui.sh:2329
#, tcl-format
msgid "Visualize %s's History"
msgstr "Voir l'historique de la branche: %s"
-#: git-gui.sh:1994 lib/database.tcl:27 lib/database.tcl:67
+#: git-gui.sh:2334 lib/database.tcl:27 lib/database.tcl:67
msgid "Database Statistics"
msgstr "Statistiques du dépôt"
-#: git-gui.sh:1997 lib/database.tcl:34
+#: git-gui.sh:2337 lib/database.tcl:34
msgid "Compress Database"
msgstr "Comprimer le dépôt"
-#: git-gui.sh:2000
+#: git-gui.sh:2340
msgid "Verify Database"
msgstr "Vérifier le dépôt"
-#: git-gui.sh:2007 git-gui.sh:2011 git-gui.sh:2015 lib/shortcut.tcl:7
+#: git-gui.sh:2347 git-gui.sh:2351 git-gui.sh:2355 lib/shortcut.tcl:7
#: lib/shortcut.tcl:39 lib/shortcut.tcl:71
msgid "Create Desktop Icon"
msgstr "Créer icône sur bureau"
-#: git-gui.sh:2023 lib/choose_repository.tcl:177 lib/choose_repository.tcl:185
+#: git-gui.sh:2363 lib/choose_repository.tcl:183 lib/choose_repository.tcl:191
msgid "Quit"
msgstr "Quitter"
-#: git-gui.sh:2031
+#: git-gui.sh:2371
msgid "Undo"
msgstr "Défaire"
-#: git-gui.sh:2034
+#: git-gui.sh:2374
msgid "Redo"
msgstr "Refaire"
-#: git-gui.sh:2038 git-gui.sh:2545
+#: git-gui.sh:2378 git-gui.sh:2923
msgid "Cut"
msgstr "Couper"
-#: git-gui.sh:2041 git-gui.sh:2548 git-gui.sh:2622 git-gui.sh:2715
+#: git-gui.sh:2381 git-gui.sh:2926 git-gui.sh:3000 git-gui.sh:3082
#: lib/console.tcl:69
msgid "Copy"
msgstr "Copier"
-#: git-gui.sh:2044 git-gui.sh:2551
+#: git-gui.sh:2384 git-gui.sh:2929
msgid "Paste"
msgstr "Coller"
-#: git-gui.sh:2047 git-gui.sh:2554 lib/branch_delete.tcl:26
+#: git-gui.sh:2387 git-gui.sh:2932 lib/branch_delete.tcl:26
#: lib/remote_branch_delete.tcl:38
msgid "Delete"
msgstr "Supprimer"
-#: git-gui.sh:2051 git-gui.sh:2558 git-gui.sh:2719 lib/console.tcl:71
+#: git-gui.sh:2391 git-gui.sh:2936 git-gui.sh:3086 lib/console.tcl:71
msgid "Select All"
msgstr "Tout sélectionner"
-#: git-gui.sh:2060
+#: git-gui.sh:2400
msgid "Create..."
msgstr "Créer..."
-#: git-gui.sh:2066
+#: git-gui.sh:2406
msgid "Checkout..."
msgstr "Charger (checkout)..."
-#: git-gui.sh:2072
+#: git-gui.sh:2412
msgid "Rename..."
msgstr "Renommer..."
-#: git-gui.sh:2077 git-gui.sh:2187
+#: git-gui.sh:2417
msgid "Delete..."
msgstr "Supprimer..."
-#: git-gui.sh:2082
+#: git-gui.sh:2422
msgid "Reset..."
msgstr "Réinitialiser..."
-#: git-gui.sh:2094 git-gui.sh:2491
+#: git-gui.sh:2432
+msgid "Done"
+msgstr "Effectué"
+
+#: git-gui.sh:2434
+msgid "Commit@@verb"
+msgstr "Commiter@@verb"
+
+#: git-gui.sh:2443 git-gui.sh:2864
msgid "New Commit"
msgstr "Nouveau commit"
-#: git-gui.sh:2102 git-gui.sh:2498
+#: git-gui.sh:2451 git-gui.sh:2871
msgid "Amend Last Commit"
msgstr "Corriger dernier commit"
-#: git-gui.sh:2111 git-gui.sh:2458 lib/remote_branch_delete.tcl:99
+#: git-gui.sh:2461 git-gui.sh:2825 lib/remote_branch_delete.tcl:99
msgid "Rescan"
msgstr "Recharger modifs."
-#: git-gui.sh:2117
+#: git-gui.sh:2467
msgid "Stage To Commit"
msgstr "Indexer"
-#: git-gui.sh:2123
+#: git-gui.sh:2473
msgid "Stage Changed Files To Commit"
msgstr "Indexer toutes modifications"
-#: git-gui.sh:2129
+#: git-gui.sh:2479
msgid "Unstage From Commit"
msgstr "Désindexer"
-#: git-gui.sh:2134 lib/index.tcl:395
+#: git-gui.sh:2484 lib/index.tcl:410
msgid "Revert Changes"
msgstr "Annuler les modifications (revert)"
-#: git-gui.sh:2141 git-gui.sh:2702
+#: git-gui.sh:2491 git-gui.sh:3069
msgid "Show Less Context"
msgstr "Montrer moins de contexte"
-#: git-gui.sh:2145 git-gui.sh:2706
+#: git-gui.sh:2495 git-gui.sh:3073
msgid "Show More Context"
msgstr "Montrer plus de contexte"
-#: git-gui.sh:2151 git-gui.sh:2470 git-gui.sh:2569
+#: git-gui.sh:2502 git-gui.sh:2838 git-gui.sh:2947
msgid "Sign Off"
msgstr "Signer"
-#: git-gui.sh:2155 git-gui.sh:2474
-msgid "Commit@@verb"
-msgstr "Commiter"
-
-#: git-gui.sh:2166
+#: git-gui.sh:2518
msgid "Local Merge..."
msgstr "Fusion locale..."
-#: git-gui.sh:2171
+#: git-gui.sh:2523
msgid "Abort Merge..."
msgstr "Abandonner fusion..."
-#: git-gui.sh:2183
+#: git-gui.sh:2535 git-gui.sh:2575
+msgid "Add..."
+msgstr "Ajouter..."
+
+#: git-gui.sh:2539
msgid "Push..."
msgstr "Pousser..."
-#: git-gui.sh:2197 git-gui.sh:2219 lib/about.tcl:14
-#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50
+#: git-gui.sh:2543
+msgid "Delete Branch..."
+msgstr "Supprimer branche..."
+
+#: git-gui.sh:2553 git-gui.sh:2589 lib/about.tcl:14
+#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:53
#, tcl-format
msgid "About %s"
msgstr "À propos de %s"
-#: git-gui.sh:2201
+#: git-gui.sh:2557
msgid "Preferences..."
msgstr "Préférences..."
-#: git-gui.sh:2209 git-gui.sh:2740
+#: git-gui.sh:2565 git-gui.sh:3115
msgid "Options..."
msgstr "Options..."
-#: git-gui.sh:2215 lib/choose_repository.tcl:47
+#: git-gui.sh:2576
+msgid "Remove..."
+msgstr "Supprimer..."
+
+#: git-gui.sh:2585 lib/choose_repository.tcl:50
msgid "Help"
msgstr "Aide"
-#: git-gui.sh:2256
+#: git-gui.sh:2611
msgid "Online Documentation"
msgstr "Documentation en ligne"
-#: git-gui.sh:2340
+#: git-gui.sh:2614 lib/choose_repository.tcl:47 lib/choose_repository.tcl:56
+msgid "Show SSH Key"
+msgstr "Montrer clé SSH"
+
+#: git-gui.sh:2707
#, tcl-format
msgid "fatal: cannot stat path %s: No such file or directory"
msgstr ""
"erreur fatale : pas d'infos sur le chemin %s : Fichier ou répertoire "
"inexistant"
-#: git-gui.sh:2373
+#: git-gui.sh:2740
msgid "Current Branch:"
msgstr "Branche courante :"
-#: git-gui.sh:2394
+#: git-gui.sh:2761
msgid "Staged Changes (Will Commit)"
msgstr "Modifs. indexées (pour commit)"
-#: git-gui.sh:2414
+#: git-gui.sh:2781
msgid "Unstaged Changes"
msgstr "Modifs. non indexées"
-#: git-gui.sh:2464
+#: git-gui.sh:2831
msgid "Stage Changed"
msgstr "Indexer modifs."
-#: git-gui.sh:2480 lib/transport.tcl:93 lib/transport.tcl:182
+#: git-gui.sh:2850 lib/transport.tcl:93 lib/transport.tcl:182
msgid "Push"
msgstr "Pousser"
-#: git-gui.sh:2510
+#: git-gui.sh:2885
msgid "Initial Commit Message:"
msgstr "Message de commit initial :"
-#: git-gui.sh:2511
+#: git-gui.sh:2886
msgid "Amended Commit Message:"
msgstr "Message de commit corrigé :"
-#: git-gui.sh:2512
+#: git-gui.sh:2887
msgid "Amended Initial Commit Message:"
msgstr "Message de commit initial corrigé :"
-#: git-gui.sh:2513
+#: git-gui.sh:2888
msgid "Amended Merge Commit Message:"
msgstr "Message de commit de fusion corrigé :"
-#: git-gui.sh:2514
+#: git-gui.sh:2889
msgid "Merge Commit Message:"
msgstr "Message de commit de fusion :"
-#: git-gui.sh:2515
+#: git-gui.sh:2890
msgid "Commit Message:"
msgstr "Message de commit :"
-#: git-gui.sh:2561 git-gui.sh:2723 lib/console.tcl:73
+#: git-gui.sh:2939 git-gui.sh:3090 lib/console.tcl:73
msgid "Copy All"
msgstr "Copier tout"
-#: git-gui.sh:2585 lib/blame.tcl:100
+#: git-gui.sh:2963 lib/blame.tcl:104
msgid "File:"
msgstr "Fichier :"
-#: git-gui.sh:2691
-msgid "Apply/Reverse Hunk"
-msgstr "Appliquer/Inverser section"
-
-#: git-gui.sh:2696
-msgid "Apply/Reverse Line"
-msgstr "Appliquer/Inverser la ligne"
-
-#: git-gui.sh:2711
+#: git-gui.sh:3078
msgid "Refresh"
msgstr "Rafraichir"
-#: git-gui.sh:2732
+#: git-gui.sh:3099
msgid "Decrease Font Size"
msgstr "Diminuer la police"
-#: git-gui.sh:2736
+#: git-gui.sh:3103
msgid "Increase Font Size"
msgstr "Agrandir la police"
-#: git-gui.sh:2747
+#: git-gui.sh:3111 lib/blame.tcl:281
+msgid "Encoding"
+msgstr "Encodage"
+
+#: git-gui.sh:3122
+msgid "Apply/Reverse Hunk"
+msgstr "Appliquer/Inverser section"
+
+#: git-gui.sh:3127
+msgid "Apply/Reverse Line"
+msgstr "Appliquer/Inverser la ligne"
+
+#: git-gui.sh:3137
+msgid "Run Merge Tool"
+msgstr "Lancer outil de merge"
+
+#: git-gui.sh:3142
+msgid "Use Remote Version"
+msgstr "Utiliser la version distante"
+
+#: git-gui.sh:3146
+msgid "Use Local Version"
+msgstr "Utiliser la version locale"
+
+#: git-gui.sh:3150
+msgid "Revert To Base"
+msgstr "Revenir à la version de base"
+
+#: git-gui.sh:3169
msgid "Unstage Hunk From Commit"
msgstr "Désindexer la section"
-#: git-gui.sh:2748
+#: git-gui.sh:3170
msgid "Unstage Line From Commit"
msgstr "Désindexer la ligne"
-#: git-gui.sh:2750
+#: git-gui.sh:3172
msgid "Stage Hunk For Commit"
msgstr "Indexer la section"
-#: git-gui.sh:2751
+#: git-gui.sh:3173
msgid "Stage Line For Commit"
msgstr "Indexer la ligne"
-#: git-gui.sh:2771
+#: git-gui.sh:3196
msgid "Initializing..."
msgstr "Initialisation..."
-#: git-gui.sh:2876
+#: git-gui.sh:3301
#, tcl-format
msgid ""
"Possible environment issues exist.\n"
@@ -455,7 +520,7 @@ msgstr ""
"sous-processus de Git lancés par %s\n"
"\n"
-#: git-gui.sh:2906
+#: git-gui.sh:3331
msgid ""
"\n"
"This is due to a known issue with the\n"
@@ -465,7 +530,7 @@ msgstr ""
"Ceci est du à un problème connu avec\n"
"le binaire Tcl distribué par Cygwin."
-#: git-gui.sh:2911
+#: git-gui.sh:3336
#, tcl-format
msgid ""
"\n"
@@ -486,80 +551,108 @@ msgstr ""
msgid "git-gui - a graphical user interface for Git."
msgstr "git-gui - une interface graphique utilisateur pour Git"
-#: lib/blame.tcl:70
+#: lib/blame.tcl:72
msgid "File Viewer"
msgstr "Visionneur de fichier"
-#: lib/blame.tcl:74
+#: lib/blame.tcl:78
msgid "Commit:"
msgstr "Commit :"
-#: lib/blame.tcl:257
+#: lib/blame.tcl:271
msgid "Copy Commit"
msgstr "Copier commit"
-#: lib/blame.tcl:260
+#: lib/blame.tcl:275
+msgid "Find Text..."
+msgstr "Chercher texte..."
+
+#: lib/blame.tcl:284
msgid "Do Full Copy Detection"
msgstr "Lancer la détection approfondie des copies"
-#: lib/blame.tcl:388
+#: lib/blame.tcl:288
+msgid "Show History Context"
+msgstr "Montrer l'historique"
+
+#: lib/blame.tcl:291
+msgid "Blame Parent Commit"
+msgstr "Blâmer le commit parent"
+
+#: lib/blame.tcl:450
#, tcl-format
msgid "Reading %s..."
msgstr "Lecture de %s..."
-#: lib/blame.tcl:492
+#: lib/blame.tcl:557
msgid "Loading copy/move tracking annotations..."
msgstr "Chargement des annotations de suivi des copies/déplacements..."
-#: lib/blame.tcl:512
+#: lib/blame.tcl:577
msgid "lines annotated"
msgstr "lignes annotées"
-#: lib/blame.tcl:704
+#: lib/blame.tcl:769
msgid "Loading original location annotations..."
msgstr "Chargement des annotations d'emplacement original"
-#: lib/blame.tcl:707
+#: lib/blame.tcl:772
msgid "Annotation complete."
msgstr "Annotation terminée."
-#: lib/blame.tcl:737
+#: lib/blame.tcl:802
msgid "Busy"
msgstr "Occupé"
-#: lib/blame.tcl:738
+#: lib/blame.tcl:803
msgid "Annotation process is already running."
msgstr "Annotation en cours d'exécution."
-#: lib/blame.tcl:777
+#: lib/blame.tcl:842
msgid "Running thorough copy detection..."
msgstr "Recherche de copie approfondie en cours..."
-#: lib/blame.tcl:827
+#: lib/blame.tcl:910
msgid "Loading annotation..."
msgstr "Chargement des annotations..."
-#: lib/blame.tcl:883
+#: lib/blame.tcl:964
msgid "Author:"
msgstr "Auteur :"
-#: lib/blame.tcl:887
+#: lib/blame.tcl:968
msgid "Committer:"
msgstr "Commiteur :"
-#: lib/blame.tcl:892
+#: lib/blame.tcl:973
msgid "Original File:"
msgstr "Fichier original :"
-#: lib/blame.tcl:1006
+#: lib/blame.tcl:1021
+msgid "Cannot find HEAD commit:"
+msgstr "Impossible de trouver le commit HEAD:"
+
+#: lib/blame.tcl:1076
+msgid "Cannot find parent commit:"
+msgstr "Impossible de trouver le commit parent:"
+
+#: lib/blame.tcl:1091
+msgid "Unable to display parent"
+msgstr "Impossible d'afficher le parent"
+
+#: lib/blame.tcl:1092 lib/diff.tcl:297
+msgid "Error loading diff:"
+msgstr "Erreur lors du chargement des différences :"
+
+#: lib/blame.tcl:1232
msgid "Originally By:"
msgstr "A l'origine par :"
-#: lib/blame.tcl:1012
+#: lib/blame.tcl:1238
msgid "In File:"
msgstr "Dans le fichier :"
-#: lib/blame.tcl:1017
+#: lib/blame.tcl:1243
msgid "Copied Or Moved Here By:"
msgstr "Copié ou déplacé ici par :"
@@ -573,16 +666,18 @@ msgstr "Charger (checkout)"
#: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35
#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:282
-#: lib/checkout_op.tcl:544 lib/choose_font.tcl:43 lib/merge.tcl:171
-#: lib/option.tcl:103 lib/remote_branch_delete.tcl:42 lib/transport.tcl:97
+#: lib/checkout_op.tcl:544 lib/choose_font.tcl:43 lib/merge.tcl:172
+#: lib/option.tcl:125 lib/remote_add.tcl:32 lib/remote_branch_delete.tcl:42
+#: lib/tools_dlg.tcl:40 lib/tools_dlg.tcl:204 lib/tools_dlg.tcl:352
+#: lib/transport.tcl:97
msgid "Cancel"
msgstr "Annuler"
-#: lib/branch_checkout.tcl:32 lib/browser.tcl:287
+#: lib/branch_checkout.tcl:32 lib/browser.tcl:287 lib/tools_dlg.tcl:328
msgid "Revision"
msgstr "Révision"
-#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:244
+#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:280
msgid "Options"
msgstr "Options"
@@ -602,7 +697,7 @@ msgstr "Créer branche"
msgid "Create New Branch"
msgstr "Créer nouvelle branche"
-#: lib/branch_create.tcl:31 lib/choose_repository.tcl:371
+#: lib/branch_create.tcl:31 lib/choose_repository.tcl:377
msgid "Create"
msgstr "Créer"
@@ -610,7 +705,7 @@ msgstr "Créer"
msgid "Branch Name"
msgstr "Nom de branche"
-#: lib/branch_create.tcl:43
+#: lib/branch_create.tcl:43 lib/remote_add.tcl:39 lib/tools_dlg.tcl:50
msgid "Name:"
msgstr "Nom :"
@@ -755,9 +850,9 @@ msgstr "[Jusqu'au parent]"
msgid "Browse Branch Files"
msgstr "Naviguer dans les fichiers de le branche"
-#: lib/browser.tcl:278 lib/choose_repository.tcl:387
-#: lib/choose_repository.tcl:472 lib/choose_repository.tcl:482
-#: lib/choose_repository.tcl:985
+#: lib/browser.tcl:278 lib/choose_repository.tcl:394
+#: lib/choose_repository.tcl:480 lib/choose_repository.tcl:491
+#: lib/choose_repository.tcl:995
msgid "Browse"
msgstr "Naviguer"
@@ -772,6 +867,7 @@ msgid "fatal: Cannot resolve %s"
msgstr "erreur fatale : Impossible de résoudre %s"
#: lib/checkout_op.tcl:145 lib/console.tcl:81 lib/database.tcl:31
+#: lib/sshkey.tcl:53
msgid "Close"
msgstr "Fermer"
@@ -884,7 +980,7 @@ msgstr "Récupérer les commits perdus ne sera peut être pas facile."
msgid "Reset '%s'?"
msgstr "Réinitialiser '%s' ?"
-#: lib/checkout_op.tcl:532 lib/merge.tcl:163
+#: lib/checkout_op.tcl:532 lib/merge.tcl:164 lib/tools_dlg.tcl:343
msgid "Visualize"
msgstr "Visualiser"
@@ -934,225 +1030,229 @@ msgstr ""
msgid "Git Gui"
msgstr "Git Gui"
-#: lib/choose_repository.tcl:81 lib/choose_repository.tcl:376
+#: lib/choose_repository.tcl:87 lib/choose_repository.tcl:382
msgid "Create New Repository"
msgstr "Créer nouveau dépôt"
-#: lib/choose_repository.tcl:87
+#: lib/choose_repository.tcl:93
msgid "New..."
msgstr "Nouveau..."
-#: lib/choose_repository.tcl:94 lib/choose_repository.tcl:458
+#: lib/choose_repository.tcl:100 lib/choose_repository.tcl:465
msgid "Clone Existing Repository"
msgstr "Cloner dépôt existant"
-#: lib/choose_repository.tcl:100
+#: lib/choose_repository.tcl:106
msgid "Clone..."
msgstr "Cloner..."
-#: lib/choose_repository.tcl:107 lib/choose_repository.tcl:974
+#: lib/choose_repository.tcl:113 lib/choose_repository.tcl:983
msgid "Open Existing Repository"
msgstr "Ouvrir dépôt existant"
-#: lib/choose_repository.tcl:113
+#: lib/choose_repository.tcl:119
msgid "Open..."
msgstr "Ouvrir..."
-#: lib/choose_repository.tcl:126
+#: lib/choose_repository.tcl:132
msgid "Recent Repositories"
msgstr "Dépôt récemment utilisés"
-#: lib/choose_repository.tcl:132
+#: lib/choose_repository.tcl:138
msgid "Open Recent Repository:"
msgstr "Ouvrir dépôt récent :"
-#: lib/choose_repository.tcl:296 lib/choose_repository.tcl:303
-#: lib/choose_repository.tcl:310
+#: lib/choose_repository.tcl:302 lib/choose_repository.tcl:309
+#: lib/choose_repository.tcl:316
#, tcl-format
msgid "Failed to create repository %s:"
msgstr "La création du dépôt %s a échouée :"
-#: lib/choose_repository.tcl:381 lib/choose_repository.tcl:476
+#: lib/choose_repository.tcl:387
msgid "Directory:"
msgstr "Répertoire :"
-#: lib/choose_repository.tcl:410 lib/choose_repository.tcl:535
-#: lib/choose_repository.tcl:1007
+#: lib/choose_repository.tcl:417 lib/choose_repository.tcl:544
+#: lib/choose_repository.tcl:1017
msgid "Git Repository"
msgstr "Dépôt Git"
-#: lib/choose_repository.tcl:435
+#: lib/choose_repository.tcl:442
#, tcl-format
msgid "Directory %s already exists."
msgstr "Le répertoire %s existe déjà."
-#: lib/choose_repository.tcl:439
+#: lib/choose_repository.tcl:446
#, tcl-format
msgid "File %s already exists."
msgstr "Le fichier %s existe déjà."
-#: lib/choose_repository.tcl:453
+#: lib/choose_repository.tcl:460
msgid "Clone"
msgstr "Cloner"
-#: lib/choose_repository.tcl:466
-msgid "URL:"
-msgstr "URL :"
+#: lib/choose_repository.tcl:473
+msgid "Source Location:"
+msgstr "Emplacement source:"
-#: lib/choose_repository.tcl:487
+#: lib/choose_repository.tcl:484
+msgid "Target Directory:"
+msgstr "Répertoire cible:"
+
+#: lib/choose_repository.tcl:496
msgid "Clone Type:"
msgstr "Type de clonage :"
-#: lib/choose_repository.tcl:493
+#: lib/choose_repository.tcl:502
msgid "Standard (Fast, Semi-Redundant, Hardlinks)"
msgstr "Standard (rapide, semi-redondant, liens durs)"
-#: lib/choose_repository.tcl:499
+#: lib/choose_repository.tcl:508
msgid "Full Copy (Slower, Redundant Backup)"
msgstr "Copy complète (plus lent, sauvegarde redondante)"
-#: lib/choose_repository.tcl:505
+#: lib/choose_repository.tcl:514
msgid "Shared (Fastest, Not Recommended, No Backup)"
msgstr "Partagé (le plus rapide, non recommandé, pas de sauvegarde)"
-#: lib/choose_repository.tcl:541 lib/choose_repository.tcl:588
-#: lib/choose_repository.tcl:734 lib/choose_repository.tcl:804
-#: lib/choose_repository.tcl:1013 lib/choose_repository.tcl:1021
+#: lib/choose_repository.tcl:550 lib/choose_repository.tcl:597
+#: lib/choose_repository.tcl:743 lib/choose_repository.tcl:813
+#: lib/choose_repository.tcl:1023 lib/choose_repository.tcl:1031
#, tcl-format
msgid "Not a Git repository: %s"
msgstr "'%s' n'est pas un dépôt Git."
-#: lib/choose_repository.tcl:577
+#: lib/choose_repository.tcl:586
msgid "Standard only available for local repository."
msgstr "Standard n'est disponible que pour un dépôt local."
-#: lib/choose_repository.tcl:581
+#: lib/choose_repository.tcl:590
msgid "Shared only available for local repository."
msgstr "Partagé n'est disponible que pour un dépôt local."
-#: lib/choose_repository.tcl:602
+#: lib/choose_repository.tcl:611
#, tcl-format
msgid "Location %s already exists."
msgstr "L'emplacement %s existe déjà."
-#: lib/choose_repository.tcl:613
+#: lib/choose_repository.tcl:622
msgid "Failed to configure origin"
msgstr "La configuration de l'origine a échouée."
-#: lib/choose_repository.tcl:625
+#: lib/choose_repository.tcl:634
msgid "Counting objects"
msgstr "Décompte des objets"
-#: lib/choose_repository.tcl:626
+#: lib/choose_repository.tcl:635
msgid "buckets"
msgstr "paniers"
-#: lib/choose_repository.tcl:650
+#: lib/choose_repository.tcl:659
#, tcl-format
msgid "Unable to copy objects/info/alternates: %s"
msgstr "Impossible de copier 'objects/info/alternates' : %s"
-#: lib/choose_repository.tcl:686
+#: lib/choose_repository.tcl:695
#, tcl-format
msgid "Nothing to clone from %s."
msgstr "Il n'y a rien à cloner depuis %s."
-#: lib/choose_repository.tcl:688 lib/choose_repository.tcl:902
-#: lib/choose_repository.tcl:914
+#: lib/choose_repository.tcl:697 lib/choose_repository.tcl:911
+#: lib/choose_repository.tcl:923
msgid "The 'master' branch has not been initialized."
msgstr "La branche 'master' n'a pas été initialisée."
-#: lib/choose_repository.tcl:701
+#: lib/choose_repository.tcl:710
msgid "Hardlinks are unavailable. Falling back to copying."
msgstr "Les liens durs ne sont pas supportés. Une copie sera effectuée à la place."
-#: lib/choose_repository.tcl:713
+#: lib/choose_repository.tcl:722
#, tcl-format
msgid "Cloning from %s"
msgstr "Clonage depuis %s"
-#: lib/choose_repository.tcl:744
+#: lib/choose_repository.tcl:753
msgid "Copying objects"
msgstr "Copie des objets"
-#: lib/choose_repository.tcl:745
+#: lib/choose_repository.tcl:754
msgid "KiB"
msgstr "KiB"
-#: lib/choose_repository.tcl:769
+#: lib/choose_repository.tcl:778
#, tcl-format
msgid "Unable to copy object: %s"
msgstr "Impossible de copier l'objet : %s"
-#: lib/choose_repository.tcl:779
+#: lib/choose_repository.tcl:788
msgid "Linking objects"
msgstr "Liaison des objets"
-#: lib/choose_repository.tcl:780
+#: lib/choose_repository.tcl:789
msgid "objects"
msgstr "objets"
-#: lib/choose_repository.tcl:788
+#: lib/choose_repository.tcl:797
#, tcl-format
msgid "Unable to hardlink object: %s"
msgstr "Impossible créer un lien dur pour l'objet : %s"
-#: lib/choose_repository.tcl:843
+#: lib/choose_repository.tcl:852
msgid "Cannot fetch branches and objects. See console output for details."
msgstr ""
"Impossible de récupérer les branches et objets. Voir la sortie console pour "
"plus de détails."
-#: lib/choose_repository.tcl:854
+#: lib/choose_repository.tcl:863
msgid "Cannot fetch tags. See console output for details."
msgstr ""
"Impossible de récupérer les marques (tags). Voir la sortie console pour plus "
"de détails."
-#: lib/choose_repository.tcl:878
+#: lib/choose_repository.tcl:887
msgid "Cannot determine HEAD. See console output for details."
msgstr "Impossible de déterminer HEAD. Voir la sortie console pour plus de détails."
-#: lib/choose_repository.tcl:887
+#: lib/choose_repository.tcl:896
#, tcl-format
msgid "Unable to cleanup %s"
msgstr "Impossible de nettoyer %s"
-#: lib/choose_repository.tcl:893
+#: lib/choose_repository.tcl:902
msgid "Clone failed."
msgstr "Le clonage a échoué."
-#: lib/choose_repository.tcl:900
+#: lib/choose_repository.tcl:909
msgid "No default branch obtained."
msgstr "Aucune branche par défaut n'a été obtenue."
-#: lib/choose_repository.tcl:911
+#: lib/choose_repository.tcl:920
#, tcl-format
msgid "Cannot resolve %s as a commit."
msgstr "Impossible de résoudre %s comme commit."
-#: lib/choose_repository.tcl:923
+#: lib/choose_repository.tcl:932
msgid "Creating working directory"
msgstr "Création du répertoire de travail"
-#: lib/choose_repository.tcl:924 lib/index.tcl:65 lib/index.tcl:127
-#: lib/index.tcl:193
+#: lib/choose_repository.tcl:933 lib/index.tcl:65 lib/index.tcl:128
+#: lib/index.tcl:196
msgid "files"
msgstr "fichiers"
-#: lib/choose_repository.tcl:953
+#: lib/choose_repository.tcl:962
msgid "Initial file checkout failed."
msgstr "Chargement initial du fichier échoué."
-#: lib/choose_repository.tcl:969
+#: lib/choose_repository.tcl:978
msgid "Open"
msgstr "Ouvrir"
-#: lib/choose_repository.tcl:979
+#: lib/choose_repository.tcl:988
msgid "Repository:"
msgstr "Dépôt :"
-#: lib/choose_repository.tcl:1027
+#: lib/choose_repository.tcl:1037
#, tcl-format
msgid "Failed to open repository %s:"
msgstr "Impossible d'ouvrir le dépôt %s :"
@@ -1254,7 +1354,7 @@ msgstr ""
"\n"
"Cela va être fait tout de suite automatiquement.\n"
-#: lib/commit.tcl:154
+#: lib/commit.tcl:156
#, tcl-format
msgid ""
"Unmerged files cannot be committed.\n"
@@ -1267,7 +1367,7 @@ msgstr ""
"Le fichier %s a des conflicts de fusion. Vous devez les résoudre et pré-"
"commiter le fichier avant de pouvoir commiter.\n"
-#: lib/commit.tcl:162
+#: lib/commit.tcl:164
#, tcl-format
msgid ""
"Unknown file state %s detected.\n"
@@ -1278,7 +1378,7 @@ msgstr ""
"\n"
"Le fichier %s ne peut pas être commité par ce programme.\n"
-#: lib/commit.tcl:170
+#: lib/commit.tcl:172
msgid ""
"No changes to commit.\n"
"\n"
@@ -1288,7 +1388,7 @@ msgstr ""
"\n"
"Vous devez indexer au moins 1 fichier avant de pouvoir commiter.\n"
-#: lib/commit.tcl:183
+#: lib/commit.tcl:187
msgid ""
"Please supply a commit message.\n"
"\n"
@@ -1306,45 +1406,45 @@ msgstr ""
"- Deuxième ligne : rien.\n"
"- Lignes suivantes : Décrire pourquoi ces modifications sont bonnes.\n"
-#: lib/commit.tcl:207
+#: lib/commit.tcl:211
#, tcl-format
msgid "warning: Tcl does not support encoding '%s'."
msgstr "attention : Tcl ne supporte pas l'encodage '%s'."
-#: lib/commit.tcl:221
+#: lib/commit.tcl:227
msgid "Calling pre-commit hook..."
msgstr "Lancement de l'action d'avant-commit..."
-#: lib/commit.tcl:236
+#: lib/commit.tcl:242
msgid "Commit declined by pre-commit hook."
msgstr "Commit refusé par l'action d'avant-commit."
-#: lib/commit.tcl:259
+#: lib/commit.tcl:265
msgid "Calling commit-msg hook..."
msgstr "Lancement de l'action \"message de commit\"..."
-#: lib/commit.tcl:274
+#: lib/commit.tcl:280
msgid "Commit declined by commit-msg hook."
msgstr "Commit refusé par l'action \"message de commit\"."
-#: lib/commit.tcl:287
+#: lib/commit.tcl:293
msgid "Committing changes..."
msgstr "Commit des modifications..."
-#: lib/commit.tcl:303
+#: lib/commit.tcl:309
msgid "write-tree failed:"
msgstr "write-tree a échoué :"
-#: lib/commit.tcl:304 lib/commit.tcl:348 lib/commit.tcl:368
+#: lib/commit.tcl:310 lib/commit.tcl:354 lib/commit.tcl:374
msgid "Commit failed."
msgstr "Le commit a échoué."
-#: lib/commit.tcl:321
+#: lib/commit.tcl:327
#, tcl-format
msgid "Commit %s appears to be corrupt"
msgstr "Le commit %s semble être corrompu"
-#: lib/commit.tcl:326
+#: lib/commit.tcl:332
msgid ""
"No changes to commit.\n"
"\n"
@@ -1359,19 +1459,19 @@ msgstr ""
"\n"
"Une resynchronisation va être lancée tout de suite automatiquement.\n"
-#: lib/commit.tcl:333
+#: lib/commit.tcl:339
msgid "No changes to commit."
msgstr "Pas de modifications à commiter."
-#: lib/commit.tcl:347
+#: lib/commit.tcl:353
msgid "commit-tree failed:"
msgstr "commit-tree a échoué :"
-#: lib/commit.tcl:367
+#: lib/commit.tcl:373
msgid "update-ref failed:"
msgstr "update-ref a échoué"
-#: lib/commit.tcl:454
+#: lib/commit.tcl:461
#, tcl-format
msgid "Created commit %s: %s"
msgstr "Commit créé %s : %s"
@@ -1448,7 +1548,7 @@ msgstr ""
msgid "Invalid date from Git: %s"
msgstr "Date invalide de Git : %s"
-#: lib/diff.tcl:44
+#: lib/diff.tcl:59
#, tcl-format
msgid ""
"No differences detected.\n"
@@ -1471,48 +1571,101 @@ msgstr ""
"Une resynchronisation va être lancée automatiquement pour trouver d'autres "
"fichiers qui pourraient se trouver dans le même état."
-#: lib/diff.tcl:83
+#: lib/diff.tcl:99
#, tcl-format
msgid "Loading diff of %s..."
msgstr "Chargement des différences de %s..."
-#: lib/diff.tcl:116 lib/diff.tcl:190
+#: lib/diff.tcl:120
+msgid ""
+"LOCAL: deleted\n"
+"REMOTE:\n"
+msgstr ""
+"LOCAL: supprimé\n"
+"DISTANT:\n"
+
+#: lib/diff.tcl:125
+msgid ""
+"REMOTE: deleted\n"
+"LOCAL:\n"
+msgstr ""
+"DISTANT: supprimé\n"
+"LOCAL:\n"
+
+#: lib/diff.tcl:132
+msgid "LOCAL:\n"
+msgstr "LOCAL:\n"
+
+#: lib/diff.tcl:135
+msgid "REMOTE:\n"
+msgstr "DISTANT:\n"
+
+#: lib/diff.tcl:197 lib/diff.tcl:296
#, tcl-format
msgid "Unable to display %s"
msgstr "Impossible d'afficher %s"
-#: lib/diff.tcl:117
+#: lib/diff.tcl:198
msgid "Error loading file:"
msgstr "Erreur lors du chargement du fichier :"
-#: lib/diff.tcl:124
+#: lib/diff.tcl:205
msgid "Git Repository (subproject)"
msgstr "Dépôt Git (sous projet)"
-#: lib/diff.tcl:136
+#: lib/diff.tcl:217
msgid "* Binary file (not showing content)."
msgstr "* Fichier binaire (pas d'apperçu du contenu)."
-#: lib/diff.tcl:191
-msgid "Error loading diff:"
-msgstr "Erreur lors du chargement des différences :"
+#: lib/diff.tcl:222
+#, tcl-format
+msgid ""
+"* Untracked file is %d bytes.\n"
+"* Showing only first %d bytes.\n"
+msgstr ""
+"* Le fichier non suivi fait %d octets.\n"
+"* On montre seulement les premiers %d octets.\n"
-#: lib/diff.tcl:313
+#: lib/diff.tcl:228
+#, tcl-format
+msgid ""
+"\n"
+"* Untracked file clipped here by %s.\n"
+"* To see the entire file, use an external editor.\n"
+msgstr ""
+"\n"
+"* Fichier suivi raccourcis ici de %s.\n"
+"* Pour voir le fichier entier, utiliser un éditeur externe.\n"
+
+#: lib/diff.tcl:436
msgid "Failed to unstage selected hunk."
msgstr "Échec lors de la désindexation de la section sélectionnée."
-#: lib/diff.tcl:320
+#: lib/diff.tcl:443
msgid "Failed to stage selected hunk."
msgstr "Échec lors de l'indexation de la section."
-#: lib/diff.tcl:386
+#: lib/diff.tcl:509
msgid "Failed to unstage selected line."
msgstr "Échec lors de la désindexation de la ligne sélectionnée."
-#: lib/diff.tcl:394
+#: lib/diff.tcl:517
msgid "Failed to stage selected line."
msgstr "Échec lors de l'indexation de la ligne."
+#: lib/encoding.tcl:443
+msgid "Default"
+msgstr "Défaut"
+
+#: lib/encoding.tcl:448
+#, tcl-format
+msgid "System (%s)"
+msgstr "Système (%s)"
+
+#: lib/encoding.tcl:459 lib/encoding.tcl:465
+msgid "Other"
+msgstr "Autre"
+
#: lib/error.tcl:20 lib/error.tcl:114
msgid "error"
msgstr "erreur"
@@ -1549,40 +1702,49 @@ msgstr "Continuer"
msgid "Unlock Index"
msgstr "Déverouiller l'index"
-#: lib/index.tcl:282
+#: lib/index.tcl:287
#, tcl-format
msgid "Unstaging %s from commit"
msgstr "Désindexation de: %s"
-#: lib/index.tcl:313
+#: lib/index.tcl:326
msgid "Ready to commit."
msgstr "Prêt à être commité."
-#: lib/index.tcl:326
+#: lib/index.tcl:339
#, tcl-format
msgid "Adding %s"
msgstr "Ajout de %s"
-#: lib/index.tcl:381
+#: lib/index.tcl:396
#, tcl-format
msgid "Revert changes in file %s?"
msgstr "Annuler les modifications dans le fichier %s ? "
-#: lib/index.tcl:383
+#: lib/index.tcl:398
#, tcl-format
msgid "Revert changes in these %i files?"
msgstr "Annuler les modifications dans ces %i fichiers ?"
-#: lib/index.tcl:391
+#: lib/index.tcl:406
msgid "Any unstaged changes will be permanently lost by the revert."
msgstr ""
"Toutes les modifications non-indexées seront définitivement perdues par "
"l'annulation."
-#: lib/index.tcl:394
+#: lib/index.tcl:409
msgid "Do Nothing"
msgstr "Ne rien faire"
+#: lib/index.tcl:427
+msgid "Reverting selected files"
+msgstr "Annuler modifications dans fichiers selectionnés"
+
+#: lib/index.tcl:431
+#, tcl-format
+msgid "Reverting %s"
+msgstr "Annulation des modifications dans %s"
+
#: lib/merge.tcl:13
msgid ""
"Cannot merge while amending.\n"
@@ -1612,7 +1774,7 @@ msgstr ""
"\n"
"Cela va être fait tout de suite automatiquement\n"
-#: lib/merge.tcl:44
+#: lib/merge.tcl:45
#, tcl-format
msgid ""
"You are in the middle of a conflicted merge.\n"
@@ -1630,7 +1792,7 @@ msgstr ""
"terminer la fusion courante. Seulement à ce moment là sera-t-il possible "
"d'effectuer une nouvelle fusion.\n"
-#: lib/merge.tcl:54
+#: lib/merge.tcl:55
#, tcl-format
msgid ""
"You are in the middle of a change.\n"
@@ -1648,34 +1810,34 @@ msgstr ""
"faisait comme cela, vous éviterez de devoir éventuellement abandonner une "
"fusion ayant échouée.\n"
-#: lib/merge.tcl:106
+#: lib/merge.tcl:107
#, tcl-format
msgid "%s of %s"
msgstr "%s de %s"
-#: lib/merge.tcl:119
+#: lib/merge.tcl:120
#, tcl-format
msgid "Merging %s and %s..."
msgstr "Fusion de %s et %s..."
-#: lib/merge.tcl:130
+#: lib/merge.tcl:131
msgid "Merge completed successfully."
msgstr "La fusion s'est faite avec succès."
-#: lib/merge.tcl:132
+#: lib/merge.tcl:133
msgid "Merge failed. Conflict resolution is required."
msgstr "La fusion a echouée. Il est nécessaire de résoudre les conflicts."
-#: lib/merge.tcl:157
+#: lib/merge.tcl:158
#, tcl-format
msgid "Merge Into %s"
msgstr "Fusion dans %s"
-#: lib/merge.tcl:176
+#: lib/merge.tcl:177
msgid "Revision To Merge"
msgstr "Révision à fusionner"
-#: lib/merge.tcl:211
+#: lib/merge.tcl:212
msgid ""
"Cannot abort while amending.\n"
"\n"
@@ -1685,7 +1847,7 @@ msgstr ""
"\n"
"Vous devez finir de corriger ce commit.\n"
-#: lib/merge.tcl:221
+#: lib/merge.tcl:222
msgid ""
"Abort merge?\n"
"\n"
@@ -1700,7 +1862,7 @@ msgstr ""
"\n"
"Abandonner quand même la fusion courante ?"
-#: lib/merge.tcl:227
+#: lib/merge.tcl:228
msgid ""
"Reset changes?\n"
"\n"
@@ -1715,131 +1877,323 @@ msgstr ""
"\n"
"Réinitialiser quand même les modifications courantes ?"
-#: lib/merge.tcl:238
+#: lib/merge.tcl:239
msgid "Aborting"
msgstr "Abandon"
-#: lib/merge.tcl:238
+#: lib/merge.tcl:239
msgid "files reset"
msgstr "fichiers réinitialisés"
-#: lib/merge.tcl:266
+#: lib/merge.tcl:267
msgid "Abort failed."
msgstr "L'abandon a échoué."
-#: lib/merge.tcl:268
+#: lib/merge.tcl:269
msgid "Abort completed. Ready."
msgstr "Abandon teminé. Prêt."
-#: lib/option.tcl:95
+#: lib/mergetool.tcl:8
+msgid "Force resolution to the base version?"
+msgstr "Forcer la résolution à la version de base ?"
+
+#: lib/mergetool.tcl:9
+msgid "Force resolution to this branch?"
+msgstr "Forcer la résolution à cette branche ?"
+
+#: lib/mergetool.tcl:10
+msgid "Force resolution to the other branch?"
+msgstr "Forcer la résolution à l'autre branche ?"
+
+#: lib/mergetool.tcl:14
+#, tcl-format
+msgid ""
+"Note that the diff shows only conflicting changes.\n"
+"\n"
+"%s will be overwritten.\n"
+"\n"
+"This operation can be undone only by restarting the merge."
+msgstr ""
+"Noter que le diff ne montre que les modifications en conflict.\n"
+"\n"
+"%s sera écrasé.\n"
+"\n"
+"Cette opération ne peut être défaite qu'en relançant la fusion."
+
+#: lib/mergetool.tcl:45
+#, tcl-format
+msgid "File %s seems to have unresolved conflicts, still stage?"
+msgstr "Le fichier %s semble avoir des conflicts non résolus, indéxer quand même ?"
+
+#: lib/mergetool.tcl:60
+#, tcl-format
+msgid "Adding resolution for %s"
+msgstr "Ajouter une résolution pour %s"
+
+#: lib/mergetool.tcl:141
+msgid "Cannot resolve deletion or link conflicts using a tool"
+msgstr "Impossible de résoudre la suppression ou de relier des conflicts en utilisant un outil"
+
+#: lib/mergetool.tcl:146
+msgid "Conflict file does not exist"
+msgstr "Le fichier en conflict n'existe pas."
+
+#: lib/mergetool.tcl:264
+#, tcl-format
+msgid "Not a GUI merge tool: '%s'"
+msgstr "'%s' n'est pas un outil graphique pour fusionner des fichiers."
+
+#: lib/mergetool.tcl:268
+#, tcl-format
+msgid "Unsupported merge tool '%s'"
+msgstr "Outil de fusion '%s' non supporté"
+
+#: lib/mergetool.tcl:303
+msgid "Merge tool is already running, terminate it?"
+msgstr "L'outil de fusion tourne déjà, faut-il le terminer ?"
+
+#: lib/mergetool.tcl:323
+#, tcl-format
+msgid ""
+"Error retrieving versions:\n"
+"%s"
+msgstr ""
+"Erreur lors de la récupération des versions:\n"
+"%s"
+
+#: lib/mergetool.tcl:343
+#, tcl-format
+msgid ""
+"Could not start the merge tool:\n"
+"\n"
+"%s"
+msgstr ""
+"Impossible de lancer l'outil de fusion:\n"
+"\n"
+"%s"
+
+#: lib/mergetool.tcl:347
+msgid "Running merge tool..."
+msgstr "Lancement de l'outil de fusion..."
+
+#: lib/mergetool.tcl:375 lib/mergetool.tcl:383
+msgid "Merge tool failed."
+msgstr "L'outil de fusion a échoué."
+
+#: lib/option.tcl:11
+#, tcl-format
+msgid "Invalid global encoding '%s'"
+msgstr "Encodage global invalide '%s'"
+
+#: lib/option.tcl:19
+#, tcl-format
+msgid "Invalid repo encoding '%s'"
+msgstr "Encodage de dépôt invalide '%s'"
+
+#: lib/option.tcl:117
msgid "Restore Defaults"
msgstr "Remettre les valeurs par défaut"
-#: lib/option.tcl:99
+#: lib/option.tcl:121
msgid "Save"
msgstr "Sauvegarder"
-#: lib/option.tcl:109
+#: lib/option.tcl:131
#, tcl-format
msgid "%s Repository"
msgstr "Dépôt: %s"
-#: lib/option.tcl:110
+#: lib/option.tcl:132
msgid "Global (All Repositories)"
msgstr "Globales (tous les dépôts)"
-#: lib/option.tcl:116
+#: lib/option.tcl:138
msgid "User Name"
msgstr "Nom d'utilisateur"
-#: lib/option.tcl:117
+#: lib/option.tcl:139
msgid "Email Address"
msgstr "Adresse email"
-#: lib/option.tcl:119
+#: lib/option.tcl:141
msgid "Summarize Merge Commits"
msgstr "Résumer les commits de fusion"
-#: lib/option.tcl:120
+#: lib/option.tcl:142
msgid "Merge Verbosity"
msgstr "Fusion bavarde"
-#: lib/option.tcl:121
+#: lib/option.tcl:143
msgid "Show Diffstat After Merge"
msgstr "Montrer statistiques de diff après fusion"
-#: lib/option.tcl:123
+#: lib/option.tcl:144
+msgid "Use Merge Tool"
+msgstr "Utiliser outil de fusion"
+
+#: lib/option.tcl:146
msgid "Trust File Modification Timestamps"
msgstr "Faire confiance aux dates de modification de fichiers "
-#: lib/option.tcl:124
+#: lib/option.tcl:147
msgid "Prune Tracking Branches During Fetch"
msgstr "Purger les branches de suivi pendant la récupération"
-#: lib/option.tcl:125
+#: lib/option.tcl:148
msgid "Match Tracking Branches"
msgstr "Faire correspondre les branches de suivi"
-#: lib/option.tcl:126
+#: lib/option.tcl:149
msgid "Blame Copy Only On Changed Files"
msgstr "Annoter les copies seulement sur fichiers modifiés"
-#: lib/option.tcl:127
+#: lib/option.tcl:150
msgid "Minimum Letters To Blame Copy On"
msgstr "Minimum de caratères pour annoter une copie"
-#: lib/option.tcl:128
+#: lib/option.tcl:151
+msgid "Blame History Context Radius (days)"
+msgstr "Distance de blâme dans l'historique (jours)"
+
+#: lib/option.tcl:152
msgid "Number of Diff Context Lines"
msgstr "Nombre de lignes de contexte dans les diffs"
-#: lib/option.tcl:129
+#: lib/option.tcl:153
msgid "Commit Message Text Width"
msgstr "Largeur du texte de message de commit"
-#: lib/option.tcl:130
+#: lib/option.tcl:154
msgid "New Branch Name Template"
msgstr "Nouveau modèle de nom de branche"
-#: lib/option.tcl:194
+#: lib/option.tcl:155
+msgid "Default File Contents Encoding"
+msgstr "Encodage du contenu des fichiers par défaut"
+
+#: lib/option.tcl:203
+msgid "Change"
+msgstr "Modifier"
+
+#: lib/option.tcl:230
msgid "Spelling Dictionary:"
msgstr "Dictionnaire d'orthographe :"
-#: lib/option.tcl:218
+#: lib/option.tcl:254
msgid "Change Font"
msgstr "Modifier les polices"
-#: lib/option.tcl:222
+#: lib/option.tcl:258
#, tcl-format
msgid "Choose %s"
msgstr "Choisir %s"
-#: lib/option.tcl:228
+#: lib/option.tcl:264
msgid "pt."
msgstr "pt."
-#: lib/option.tcl:242
+#: lib/option.tcl:278
msgid "Preferences"
msgstr "Préférences"
-#: lib/option.tcl:277
+#: lib/option.tcl:314
msgid "Failed to completely save options:"
msgstr "La sauvegarde complète des options a échouée :"
-#: lib/remote.tcl:165
+#: lib/remote.tcl:163
+msgid "Remove Remote"
+msgstr "Supprimer dépôt distant"
+
+#: lib/remote.tcl:168
msgid "Prune from"
msgstr "Purger de"
-#: lib/remote.tcl:170
+#: lib/remote.tcl:173
msgid "Fetch from"
msgstr "Récupérer de"
-#: lib/remote.tcl:213
+#: lib/remote.tcl:215
msgid "Push to"
msgstr "Pousser vers"
+#: lib/remote_add.tcl:19
+msgid "Add Remote"
+msgstr "Ajouter dépôt distant"
+
+#: lib/remote_add.tcl:24
+msgid "Add New Remote"
+msgstr "Ajouter nouveau dépôt distant"
+
+#: lib/remote_add.tcl:28 lib/tools_dlg.tcl:36
+msgid "Add"
+msgstr "Ajouter"
+
+#: lib/remote_add.tcl:37
+msgid "Remote Details"
+msgstr "Détails des dépôts distants"
+
+#: lib/remote_add.tcl:50
+msgid "Location:"
+msgstr "Emplacement:"
+
+#: lib/remote_add.tcl:62
+msgid "Further Action"
+msgstr "Action supplémentaire"
+
+#: lib/remote_add.tcl:65
+msgid "Fetch Immediately"
+msgstr "Récupérer immédiatement"
+
+#: lib/remote_add.tcl:71
+msgid "Initialize Remote Repository and Push"
+msgstr "Initialiser dépôt distant et pousser"
+
+#: lib/remote_add.tcl:77
+msgid "Do Nothing Else Now"
+msgstr "Ne rien faire d'autre maintenant"
+
+#: lib/remote_add.tcl:101
+msgid "Please supply a remote name."
+msgstr "Merci de fournir un nom de dépôt distant."
+
+#: lib/remote_add.tcl:114
+#, tcl-format
+msgid "'%s' is not an acceptable remote name."
+msgstr "'%s' n'est pas un nom de dépôt distant acceptable."
+
+#: lib/remote_add.tcl:125
+#, tcl-format
+msgid "Failed to add remote '%s' of location '%s'."
+msgstr "Échec de l'ajout du dépôt distant '%s' à l'emplacement '%s'."
+
+#: lib/remote_add.tcl:133 lib/transport.tcl:6
+#, tcl-format
+msgid "fetch %s"
+msgstr "récupérer %s"
+
+#: lib/remote_add.tcl:134
+#, tcl-format
+msgid "Fetching the %s"
+msgstr "Récupération de %s"
+
+#: lib/remote_add.tcl:157
+#, tcl-format
+msgid "Do not know how to initialize repository at location '%s'."
+msgstr "Pas de méthode connue pour initialiser le dépôt à l'emplacement '%s'."
+
+#: lib/remote_add.tcl:163 lib/transport.tcl:25 lib/transport.tcl:71
+#, tcl-format
+msgid "push %s"
+msgstr "pousser %s"
+
+#: lib/remote_add.tcl:164
+#, tcl-format
+msgid "Setting up the %s (at %s)"
+msgstr "Mise en place de %s (à %s)"
+
#: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34
-msgid "Delete Remote Branch"
-msgstr "Supprimer branche distante"
+msgid "Delete Branch Remotely"
+msgstr "Supprimer branche à distance"
#: lib/remote_branch_delete.tcl:47
msgid "From Repository"
@@ -1850,8 +2204,8 @@ msgid "Remote:"
msgstr "Branche distante :"
#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:138
-msgid "Arbitrary URL:"
-msgstr "URL arbitraire :"
+msgid "Arbitrary Location:"
+msgstr "Emplacement arbitraire :"
#: lib/remote_branch_delete.tcl:84
msgid "Branches"
@@ -1921,6 +2275,22 @@ msgstr "Aucun dépôt n'est sélectionné."
msgid "Scanning %s..."
msgstr "Synchronisation de %s..."
+#: lib/search.tcl:21
+msgid "Find:"
+msgstr "Chercher :"
+
+#: lib/search.tcl:23
+msgid "Next"
+msgstr "Suivant"
+
+#: lib/search.tcl:24
+msgid "Prev"
+msgstr "Précédant"
+
+#: lib/search.tcl:25
+msgid "Case-Sensitive"
+msgstr "Sensible à la casse"
+
#: lib/shortcut.tcl:20 lib/shortcut.tcl:61
msgid "Cannot write shortcut:"
msgstr "Impossible d'écrire le raccourcis :"
@@ -1958,23 +2328,188 @@ msgstr "Vérificateur d'orthographe non reconnu"
msgid "No Suggestions"
msgstr "Aucune suggestion"
-#: lib/spellcheck.tcl:387
+#: lib/spellcheck.tcl:388
msgid "Unexpected EOF from spell checker"
msgstr "EOF inattendue envoyée par le vérificateur d'orthographe"
-#: lib/spellcheck.tcl:391
+#: lib/spellcheck.tcl:392
msgid "Spell Checker Failed"
msgstr "Le vérificateur d'orthographe a échoué"
+#: lib/sshkey.tcl:31
+msgid "No keys found."
+msgstr "Aucune clé trouvée."
+
+#: lib/sshkey.tcl:34
+#, tcl-format
+msgid "Found a public key in: %s"
+msgstr "Clé publique trouvée dans : %s"
+
+#: lib/sshkey.tcl:40
+msgid "Generate Key"
+msgstr "Générer une clé"
+
+#: lib/sshkey.tcl:56
+msgid "Copy To Clipboard"
+msgstr "Copier dans le presse papier"
+
+#: lib/sshkey.tcl:70
+msgid "Your OpenSSH Public Key"
+msgstr "Votre clé publique Open SSH"
+
+#: lib/sshkey.tcl:78
+msgid "Generating..."
+msgstr "Génération..."
+
+#: lib/sshkey.tcl:84
+#, tcl-format
+msgid ""
+"Could not start ssh-keygen:\n"
+"\n"
+"%s"
+msgstr ""
+"Impossible de lancer ssh-keygen:\n"
+"\n"
+"%s"
+
+#: lib/sshkey.tcl:111
+msgid "Generation failed."
+msgstr "La génération a échoué."
+
+#: lib/sshkey.tcl:118
+msgid "Generation succeded, but no keys found."
+msgstr "La génération a réussi, mais aucune clé n'a été trouvée."
+
+#: lib/sshkey.tcl:121
+#, tcl-format
+msgid "Your key is in: %s"
+msgstr "Votre clé est dans : %s"
+
#: lib/status_bar.tcl:83
#, tcl-format
msgid "%s ... %*i of %*i %s (%3i%%)"
msgstr "%s ... %*i de %*i %s (%3i%%)"
-#: lib/transport.tcl:6
+#: lib/tools.tcl:75
#, tcl-format
-msgid "fetch %s"
-msgstr "récupérer %s"
+msgid "Running %s requires a selected file."
+msgstr "Lancer %s nécessite qu'un fichier soit sélectionné."
+
+#: lib/tools.tcl:90
+#, tcl-format
+msgid "Are you sure you want to run %s?"
+msgstr "Êtes vous sûr de vouloir lancer %s ?"
+
+#: lib/tools.tcl:110
+#, tcl-format
+msgid "Tool: %s"
+msgstr "Outil : %s"
+
+#: lib/tools.tcl:111
+#, tcl-format
+msgid "Running: %s"
+msgstr "Lancement de : %s"
+
+#: lib/tools.tcl:149
+#, tcl-format
+msgid "Tool completed succesfully: %s"
+msgstr "L'outil a terminé avec succès : %s"
+
+#: lib/tools.tcl:151
+#, tcl-format
+msgid "Tool failed: %s"
+msgstr "L'outil a échoué : %s"
+
+#: lib/tools_dlg.tcl:22
+msgid "Add Tool"
+msgstr "Ajouter outil"
+
+#: lib/tools_dlg.tcl:28
+msgid "Add New Tool Command"
+msgstr "Ajouter nouvelle commande d'outil"
+
+#: lib/tools_dlg.tcl:33
+msgid "Add globally"
+msgstr "Ajouter globalement"
+
+#: lib/tools_dlg.tcl:45
+msgid "Tool Details"
+msgstr "Détails sur l'outil"
+
+#: lib/tools_dlg.tcl:48
+msgid "Use '/' separators to create a submenu tree:"
+msgstr "Utiliser les séparateurs '/' pour créer un arbre de sous menus :"
+
+#: lib/tools_dlg.tcl:61
+msgid "Command:"
+msgstr "Commande :"
+
+#: lib/tools_dlg.tcl:74
+msgid "Show a dialog before running"
+msgstr "Montrer une boîte de dialogue avant le lancement"
+
+#: lib/tools_dlg.tcl:80
+msgid "Ask the user to select a revision (sets $REVISION)"
+msgstr "Demander à l'utilisateur de sélectionner une révision (change $REVISION)"
+
+#: lib/tools_dlg.tcl:85
+msgid "Ask the user for additional arguments (sets $ARGS)"
+msgstr "Demander à l'utilisateur des arguments supplémentaires (change $ARGS)"
+
+#: lib/tools_dlg.tcl:92
+msgid "Don't show the command output window"
+msgstr "Ne pas montrer la fenêtre de sortie des commandes"
+
+#: lib/tools_dlg.tcl:97
+msgid "Run only if a diff is selected ($FILENAME not empty)"
+msgstr "Lancer seulement si un diff est selectionné ($FILENAME non vide)"
+
+#: lib/tools_dlg.tcl:121
+msgid "Please supply a name for the tool."
+msgstr "Merci de fournir un nom pour l'outil."
+
+#: lib/tools_dlg.tcl:129
+#, tcl-format
+msgid "Tool '%s' already exists."
+msgstr "L'outil '%s' existe déjà."
+
+#: lib/tools_dlg.tcl:151
+#, tcl-format
+msgid ""
+"Could not add tool:\n"
+"%s"
+msgstr ""
+"Impossible d'ajouter l'outil:\n"
+"%s"
+
+#: lib/tools_dlg.tcl:190
+msgid "Remove Tool"
+msgstr "Supprimer l'outil"
+
+#: lib/tools_dlg.tcl:196
+msgid "Remove Tool Commands"
+msgstr "Supprimer des commandes d'outil"
+
+#: lib/tools_dlg.tcl:200
+msgid "Remove"
+msgstr "Supprimer"
+
+#: lib/tools_dlg.tcl:236
+msgid "(Blue denotes repository-local tools)"
+msgstr "(Le bleu indique des outils locaux au dépôt)"
+
+#: lib/tools_dlg.tcl:297
+#, tcl-format
+msgid "Run Command: %s"
+msgstr "Lancer commande : %s"
+
+#: lib/tools_dlg.tcl:311
+msgid "Arguments"
+msgstr "Arguments"
+
+#: lib/tools_dlg.tcl:348
+msgid "OK"
+msgstr "OK"
#: lib/transport.tcl:7
#, tcl-format
@@ -1991,11 +2526,6 @@ msgstr "purger à distance %s"
msgid "Pruning tracking branches deleted from %s"
msgstr "Nettoyer les branches de suivi supprimées de %s"
-#: lib/transport.tcl:25 lib/transport.tcl:71
-#, tcl-format
-msgid "push %s"
-msgstr "pousser %s"
-
#: lib/transport.tcl:26
#, tcl-format
msgid "Pushing changes to %s"
diff --git a/git-gui/po/git-gui.pot b/git-gui/po/git-gui.pot
index e295000e77..15aea0dc64 100644
--- a/git-gui/po/git-gui.pot
+++ b/git-gui/po/git-gui.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-08-02 14:45-0700\n"
+"POT-Creation-Date: 2008-12-08 08:31-0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -16,33 +16,33 @@ msgstr ""
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
-#: git-gui.sh:41 git-gui.sh:688 git-gui.sh:702 git-gui.sh:715 git-gui.sh:798
-#: git-gui.sh:817
+#: git-gui.sh:41 git-gui.sh:737 git-gui.sh:751 git-gui.sh:764 git-gui.sh:847
+#: git-gui.sh:866
msgid "git-gui: fatal error"
msgstr ""
-#: git-gui.sh:644
+#: git-gui.sh:689
#, tcl-format
msgid "Invalid font specified in %s:"
msgstr ""
-#: git-gui.sh:674
+#: git-gui.sh:723
msgid "Main Font"
msgstr ""
-#: git-gui.sh:675
+#: git-gui.sh:724
msgid "Diff/Console Font"
msgstr ""
-#: git-gui.sh:689
+#: git-gui.sh:738
msgid "Cannot find git in PATH."
msgstr ""
-#: git-gui.sh:716
+#: git-gui.sh:765
msgid "Cannot parse Git version string:"
msgstr ""
-#: git-gui.sh:734
+#: git-gui.sh:783
#, tcl-format
msgid ""
"Git version cannot be determined.\n"
@@ -54,379 +54,444 @@ msgid ""
"Assume '%s' is version 1.5.0?\n"
msgstr ""
-#: git-gui.sh:972
+#: git-gui.sh:1062
msgid "Git directory not found:"
msgstr ""
-#: git-gui.sh:979
+#: git-gui.sh:1069
msgid "Cannot move to top of working directory:"
msgstr ""
-#: git-gui.sh:986
+#: git-gui.sh:1076
msgid "Cannot use funny .git directory:"
msgstr ""
-#: git-gui.sh:991
+#: git-gui.sh:1081
msgid "No working directory"
msgstr ""
-#: git-gui.sh:1138 lib/checkout_op.tcl:305
+#: git-gui.sh:1247 lib/checkout_op.tcl:305
msgid "Refreshing file status..."
msgstr ""
-#: git-gui.sh:1194
+#: git-gui.sh:1303
msgid "Scanning for modified files ..."
msgstr ""
-#: git-gui.sh:1369 lib/browser.tcl:246
+#: git-gui.sh:1367
+msgid "Calling prepare-commit-msg hook..."
+msgstr ""
+
+#: git-gui.sh:1384
+msgid "Commit declined by prepare-commit-msg hook."
+msgstr ""
+
+#: git-gui.sh:1542 lib/browser.tcl:246
msgid "Ready."
msgstr ""
-#: git-gui.sh:1635
+#: git-gui.sh:1819
msgid "Unmodified"
msgstr ""
-#: git-gui.sh:1637
+#: git-gui.sh:1821
msgid "Modified, not staged"
msgstr ""
-#: git-gui.sh:1638 git-gui.sh:1643
+#: git-gui.sh:1822 git-gui.sh:1830
msgid "Staged for commit"
msgstr ""
-#: git-gui.sh:1639 git-gui.sh:1644
+#: git-gui.sh:1823 git-gui.sh:1831
msgid "Portions staged for commit"
msgstr ""
-#: git-gui.sh:1640 git-gui.sh:1645
+#: git-gui.sh:1824 git-gui.sh:1832
msgid "Staged for commit, missing"
msgstr ""
-#: git-gui.sh:1642
+#: git-gui.sh:1826
+msgid "File type changed, not staged"
+msgstr ""
+
+#: git-gui.sh:1827
+msgid "File type changed, staged"
+msgstr ""
+
+#: git-gui.sh:1829
msgid "Untracked, not staged"
msgstr ""
-#: git-gui.sh:1647
+#: git-gui.sh:1834
msgid "Missing"
msgstr ""
-#: git-gui.sh:1648
+#: git-gui.sh:1835
msgid "Staged for removal"
msgstr ""
-#: git-gui.sh:1649
+#: git-gui.sh:1836
msgid "Staged for removal, still present"
msgstr ""
-#: git-gui.sh:1651 git-gui.sh:1652 git-gui.sh:1653 git-gui.sh:1654
+#: git-gui.sh:1838 git-gui.sh:1839 git-gui.sh:1840 git-gui.sh:1841
+#: git-gui.sh:1842 git-gui.sh:1843
msgid "Requires merge resolution"
msgstr ""
-#: git-gui.sh:1689
+#: git-gui.sh:1878
msgid "Starting gitk... please wait..."
msgstr ""
-#: git-gui.sh:1698
+#: git-gui.sh:1887
msgid "Couldn't find gitk in PATH"
msgstr ""
-#: git-gui.sh:1948 lib/choose_repository.tcl:36
+#: git-gui.sh:2280 lib/choose_repository.tcl:36
msgid "Repository"
msgstr ""
-#: git-gui.sh:1949
+#: git-gui.sh:2281
msgid "Edit"
msgstr ""
-#: git-gui.sh:1951 lib/choose_rev.tcl:561
+#: git-gui.sh:2283 lib/choose_rev.tcl:561
msgid "Branch"
msgstr ""
-#: git-gui.sh:1954 lib/choose_rev.tcl:548
+#: git-gui.sh:2286 lib/choose_rev.tcl:548
msgid "Commit@@noun"
msgstr ""
-#: git-gui.sh:1957 lib/merge.tcl:120 lib/merge.tcl:149 lib/merge.tcl:167
+#: git-gui.sh:2289 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168
msgid "Merge"
msgstr ""
-#: git-gui.sh:1958 lib/choose_rev.tcl:557
+#: git-gui.sh:2290 lib/choose_rev.tcl:557
msgid "Remote"
msgstr ""
-#: git-gui.sh:1967
+#: git-gui.sh:2293
+msgid "Tools"
+msgstr ""
+
+#: git-gui.sh:2302
+msgid "Explore Working Copy"
+msgstr ""
+
+#: git-gui.sh:2307
msgid "Browse Current Branch's Files"
msgstr ""
-#: git-gui.sh:1971
+#: git-gui.sh:2311
msgid "Browse Branch Files..."
msgstr ""
-#: git-gui.sh:1976
+#: git-gui.sh:2316
msgid "Visualize Current Branch's History"
msgstr ""
-#: git-gui.sh:1980
+#: git-gui.sh:2320
msgid "Visualize All Branch History"
msgstr ""
-#: git-gui.sh:1987
+#: git-gui.sh:2327
#, tcl-format
msgid "Browse %s's Files"
msgstr ""
-#: git-gui.sh:1989
+#: git-gui.sh:2329
#, tcl-format
msgid "Visualize %s's History"
msgstr ""
-#: git-gui.sh:1994 lib/database.tcl:27 lib/database.tcl:67
+#: git-gui.sh:2334 lib/database.tcl:27 lib/database.tcl:67
msgid "Database Statistics"
msgstr ""
-#: git-gui.sh:1997 lib/database.tcl:34
+#: git-gui.sh:2337 lib/database.tcl:34
msgid "Compress Database"
msgstr ""
-#: git-gui.sh:2000
+#: git-gui.sh:2340
msgid "Verify Database"
msgstr ""
-#: git-gui.sh:2007 git-gui.sh:2011 git-gui.sh:2015 lib/shortcut.tcl:7
+#: git-gui.sh:2347 git-gui.sh:2351 git-gui.sh:2355 lib/shortcut.tcl:7
#: lib/shortcut.tcl:39 lib/shortcut.tcl:71
msgid "Create Desktop Icon"
msgstr ""
-#: git-gui.sh:2023 lib/choose_repository.tcl:177 lib/choose_repository.tcl:185
+#: git-gui.sh:2363 lib/choose_repository.tcl:183 lib/choose_repository.tcl:191
msgid "Quit"
msgstr ""
-#: git-gui.sh:2031
+#: git-gui.sh:2371
msgid "Undo"
msgstr ""
-#: git-gui.sh:2034
+#: git-gui.sh:2374
msgid "Redo"
msgstr ""
-#: git-gui.sh:2038 git-gui.sh:2545
+#: git-gui.sh:2378 git-gui.sh:2937
msgid "Cut"
msgstr ""
-#: git-gui.sh:2041 git-gui.sh:2548 git-gui.sh:2622 git-gui.sh:2715
+#: git-gui.sh:2381 git-gui.sh:2940 git-gui.sh:3014 git-gui.sh:3096
#: lib/console.tcl:69
msgid "Copy"
msgstr ""
-#: git-gui.sh:2044 git-gui.sh:2551
+#: git-gui.sh:2384 git-gui.sh:2943
msgid "Paste"
msgstr ""
-#: git-gui.sh:2047 git-gui.sh:2554 lib/branch_delete.tcl:26
+#: git-gui.sh:2387 git-gui.sh:2946 lib/branch_delete.tcl:26
#: lib/remote_branch_delete.tcl:38
msgid "Delete"
msgstr ""
-#: git-gui.sh:2051 git-gui.sh:2558 git-gui.sh:2719 lib/console.tcl:71
+#: git-gui.sh:2391 git-gui.sh:2950 git-gui.sh:3100 lib/console.tcl:71
msgid "Select All"
msgstr ""
-#: git-gui.sh:2060
+#: git-gui.sh:2400
msgid "Create..."
msgstr ""
-#: git-gui.sh:2066
+#: git-gui.sh:2406
msgid "Checkout..."
msgstr ""
-#: git-gui.sh:2072
+#: git-gui.sh:2412
msgid "Rename..."
msgstr ""
-#: git-gui.sh:2077 git-gui.sh:2187
+#: git-gui.sh:2417
msgid "Delete..."
msgstr ""
-#: git-gui.sh:2082
+#: git-gui.sh:2422
msgid "Reset..."
msgstr ""
-#: git-gui.sh:2094 git-gui.sh:2491
+#: git-gui.sh:2432
+msgid "Done"
+msgstr ""
+
+#: git-gui.sh:2434
+msgid "Commit@@verb"
+msgstr ""
+
+#: git-gui.sh:2443 git-gui.sh:2878
msgid "New Commit"
msgstr ""
-#: git-gui.sh:2102 git-gui.sh:2498
+#: git-gui.sh:2451 git-gui.sh:2885
msgid "Amend Last Commit"
msgstr ""
-#: git-gui.sh:2111 git-gui.sh:2458 lib/remote_branch_delete.tcl:99
+#: git-gui.sh:2461 git-gui.sh:2839 lib/remote_branch_delete.tcl:99
msgid "Rescan"
msgstr ""
-#: git-gui.sh:2117
+#: git-gui.sh:2467
msgid "Stage To Commit"
msgstr ""
-#: git-gui.sh:2123
+#: git-gui.sh:2473
msgid "Stage Changed Files To Commit"
msgstr ""
-#: git-gui.sh:2129
+#: git-gui.sh:2479
msgid "Unstage From Commit"
msgstr ""
-#: git-gui.sh:2134 lib/index.tcl:395
+#: git-gui.sh:2484 lib/index.tcl:410
msgid "Revert Changes"
msgstr ""
-#: git-gui.sh:2141 git-gui.sh:2702
+#: git-gui.sh:2491 git-gui.sh:3083
msgid "Show Less Context"
msgstr ""
-#: git-gui.sh:2145 git-gui.sh:2706
+#: git-gui.sh:2495 git-gui.sh:3087
msgid "Show More Context"
msgstr ""
-#: git-gui.sh:2151 git-gui.sh:2470 git-gui.sh:2569
+#: git-gui.sh:2502 git-gui.sh:2852 git-gui.sh:2961
msgid "Sign Off"
msgstr ""
-#: git-gui.sh:2155 git-gui.sh:2474
-msgid "Commit@@verb"
-msgstr ""
-
-#: git-gui.sh:2166
+#: git-gui.sh:2518
msgid "Local Merge..."
msgstr ""
-#: git-gui.sh:2171
+#: git-gui.sh:2523
msgid "Abort Merge..."
msgstr ""
-#: git-gui.sh:2183
+#: git-gui.sh:2535 git-gui.sh:2575
+msgid "Add..."
+msgstr ""
+
+#: git-gui.sh:2539
msgid "Push..."
msgstr ""
-#: git-gui.sh:2197 git-gui.sh:2219 lib/about.tcl:14
-#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50
+#: git-gui.sh:2543
+msgid "Delete Branch..."
+msgstr ""
+
+#: git-gui.sh:2553 git-gui.sh:2589 lib/about.tcl:14
+#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:53
#, tcl-format
msgid "About %s"
msgstr ""
-#: git-gui.sh:2201
+#: git-gui.sh:2557
msgid "Preferences..."
msgstr ""
-#: git-gui.sh:2209 git-gui.sh:2740
+#: git-gui.sh:2565 git-gui.sh:3129
msgid "Options..."
msgstr ""
-#: git-gui.sh:2215 lib/choose_repository.tcl:47
+#: git-gui.sh:2576
+msgid "Remove..."
+msgstr ""
+
+#: git-gui.sh:2585 lib/choose_repository.tcl:50
msgid "Help"
msgstr ""
-#: git-gui.sh:2256
+#: git-gui.sh:2611
msgid "Online Documentation"
msgstr ""
-#: git-gui.sh:2340
+#: git-gui.sh:2614 lib/choose_repository.tcl:47 lib/choose_repository.tcl:56
+msgid "Show SSH Key"
+msgstr ""
+
+#: git-gui.sh:2721
#, tcl-format
msgid "fatal: cannot stat path %s: No such file or directory"
msgstr ""
-#: git-gui.sh:2373
+#: git-gui.sh:2754
msgid "Current Branch:"
msgstr ""
-#: git-gui.sh:2394
+#: git-gui.sh:2775
msgid "Staged Changes (Will Commit)"
msgstr ""
-#: git-gui.sh:2414
+#: git-gui.sh:2795
msgid "Unstaged Changes"
msgstr ""
-#: git-gui.sh:2464
+#: git-gui.sh:2845
msgid "Stage Changed"
msgstr ""
-#: git-gui.sh:2480 lib/transport.tcl:93 lib/transport.tcl:182
+#: git-gui.sh:2864 lib/transport.tcl:104 lib/transport.tcl:193
msgid "Push"
msgstr ""
-#: git-gui.sh:2510
+#: git-gui.sh:2899
msgid "Initial Commit Message:"
msgstr ""
-#: git-gui.sh:2511
+#: git-gui.sh:2900
msgid "Amended Commit Message:"
msgstr ""
-#: git-gui.sh:2512
+#: git-gui.sh:2901
msgid "Amended Initial Commit Message:"
msgstr ""
-#: git-gui.sh:2513
+#: git-gui.sh:2902
msgid "Amended Merge Commit Message:"
msgstr ""
-#: git-gui.sh:2514
+#: git-gui.sh:2903
msgid "Merge Commit Message:"
msgstr ""
-#: git-gui.sh:2515
+#: git-gui.sh:2904
msgid "Commit Message:"
msgstr ""
-#: git-gui.sh:2561 git-gui.sh:2723 lib/console.tcl:73
+#: git-gui.sh:2953 git-gui.sh:3104 lib/console.tcl:73
msgid "Copy All"
msgstr ""
-#: git-gui.sh:2585 lib/blame.tcl:100
+#: git-gui.sh:2977 lib/blame.tcl:104
msgid "File:"
msgstr ""
-#: git-gui.sh:2691
+#: git-gui.sh:3092
+msgid "Refresh"
+msgstr ""
+
+#: git-gui.sh:3113
+msgid "Decrease Font Size"
+msgstr ""
+
+#: git-gui.sh:3117
+msgid "Increase Font Size"
+msgstr ""
+
+#: git-gui.sh:3125 lib/blame.tcl:281
+msgid "Encoding"
+msgstr ""
+
+#: git-gui.sh:3136
msgid "Apply/Reverse Hunk"
msgstr ""
-#: git-gui.sh:2696
+#: git-gui.sh:3141
msgid "Apply/Reverse Line"
msgstr ""
-#: git-gui.sh:2711
-msgid "Refresh"
+#: git-gui.sh:3151
+msgid "Run Merge Tool"
msgstr ""
-#: git-gui.sh:2732
-msgid "Decrease Font Size"
+#: git-gui.sh:3156
+msgid "Use Remote Version"
msgstr ""
-#: git-gui.sh:2736
-msgid "Increase Font Size"
+#: git-gui.sh:3160
+msgid "Use Local Version"
+msgstr ""
+
+#: git-gui.sh:3164
+msgid "Revert To Base"
msgstr ""
-#: git-gui.sh:2747
+#: git-gui.sh:3183
msgid "Unstage Hunk From Commit"
msgstr ""
-#: git-gui.sh:2748
+#: git-gui.sh:3184
msgid "Unstage Line From Commit"
msgstr ""
-#: git-gui.sh:2750
+#: git-gui.sh:3186
msgid "Stage Hunk For Commit"
msgstr ""
-#: git-gui.sh:2751
+#: git-gui.sh:3187
msgid "Stage Line For Commit"
msgstr ""
-#: git-gui.sh:2771
+#: git-gui.sh:3210
msgid "Initializing..."
msgstr ""
-#: git-gui.sh:2876
+#: git-gui.sh:3315
#, tcl-format
msgid ""
"Possible environment issues exist.\n"
@@ -437,14 +502,14 @@ msgid ""
"\n"
msgstr ""
-#: git-gui.sh:2906
+#: git-gui.sh:3345
msgid ""
"\n"
"This is due to a known issue with the\n"
"Tcl binary distributed by Cygwin."
msgstr ""
-#: git-gui.sh:2911
+#: git-gui.sh:3350
#, tcl-format
msgid ""
"\n"
@@ -459,80 +524,108 @@ msgstr ""
msgid "git-gui - a graphical user interface for Git."
msgstr ""
-#: lib/blame.tcl:70
+#: lib/blame.tcl:72
msgid "File Viewer"
msgstr ""
-#: lib/blame.tcl:74
+#: lib/blame.tcl:78
msgid "Commit:"
msgstr ""
-#: lib/blame.tcl:257
+#: lib/blame.tcl:271
msgid "Copy Commit"
msgstr ""
-#: lib/blame.tcl:260
+#: lib/blame.tcl:275
+msgid "Find Text..."
+msgstr ""
+
+#: lib/blame.tcl:284
msgid "Do Full Copy Detection"
msgstr ""
-#: lib/blame.tcl:388
+#: lib/blame.tcl:288
+msgid "Show History Context"
+msgstr ""
+
+#: lib/blame.tcl:291
+msgid "Blame Parent Commit"
+msgstr ""
+
+#: lib/blame.tcl:450
#, tcl-format
msgid "Reading %s..."
msgstr ""
-#: lib/blame.tcl:492
+#: lib/blame.tcl:557
msgid "Loading copy/move tracking annotations..."
msgstr ""
-#: lib/blame.tcl:512
+#: lib/blame.tcl:577
msgid "lines annotated"
msgstr ""
-#: lib/blame.tcl:704
+#: lib/blame.tcl:769
msgid "Loading original location annotations..."
msgstr ""
-#: lib/blame.tcl:707
+#: lib/blame.tcl:772
msgid "Annotation complete."
msgstr ""
-#: lib/blame.tcl:737
+#: lib/blame.tcl:802
msgid "Busy"
msgstr ""
-#: lib/blame.tcl:738
+#: lib/blame.tcl:803
msgid "Annotation process is already running."
msgstr ""
-#: lib/blame.tcl:777
+#: lib/blame.tcl:842
msgid "Running thorough copy detection..."
msgstr ""
-#: lib/blame.tcl:827
+#: lib/blame.tcl:910
msgid "Loading annotation..."
msgstr ""
-#: lib/blame.tcl:883
+#: lib/blame.tcl:963
msgid "Author:"
msgstr ""
-#: lib/blame.tcl:887
+#: lib/blame.tcl:967
msgid "Committer:"
msgstr ""
-#: lib/blame.tcl:892
+#: lib/blame.tcl:972
msgid "Original File:"
msgstr ""
-#: lib/blame.tcl:1006
+#: lib/blame.tcl:1020
+msgid "Cannot find HEAD commit:"
+msgstr ""
+
+#: lib/blame.tcl:1075
+msgid "Cannot find parent commit:"
+msgstr ""
+
+#: lib/blame.tcl:1090
+msgid "Unable to display parent"
+msgstr ""
+
+#: lib/blame.tcl:1091 lib/diff.tcl:297
+msgid "Error loading diff:"
+msgstr ""
+
+#: lib/blame.tcl:1231
msgid "Originally By:"
msgstr ""
-#: lib/blame.tcl:1012
+#: lib/blame.tcl:1237
msgid "In File:"
msgstr ""
-#: lib/blame.tcl:1017
+#: lib/blame.tcl:1242
msgid "Copied Or Moved Here By:"
msgstr ""
@@ -546,16 +639,18 @@ msgstr ""
#: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35
#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:282
-#: lib/checkout_op.tcl:544 lib/choose_font.tcl:43 lib/merge.tcl:171
-#: lib/option.tcl:103 lib/remote_branch_delete.tcl:42 lib/transport.tcl:97
+#: lib/checkout_op.tcl:544 lib/choose_font.tcl:43 lib/merge.tcl:172
+#: lib/option.tcl:125 lib/remote_add.tcl:32 lib/remote_branch_delete.tcl:42
+#: lib/tools_dlg.tcl:40 lib/tools_dlg.tcl:204 lib/tools_dlg.tcl:352
+#: lib/transport.tcl:108
msgid "Cancel"
msgstr ""
-#: lib/branch_checkout.tcl:32 lib/browser.tcl:287
+#: lib/branch_checkout.tcl:32 lib/browser.tcl:287 lib/tools_dlg.tcl:328
msgid "Revision"
msgstr ""
-#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:244
+#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:280
msgid "Options"
msgstr ""
@@ -575,7 +670,7 @@ msgstr ""
msgid "Create New Branch"
msgstr ""
-#: lib/branch_create.tcl:31 lib/choose_repository.tcl:371
+#: lib/branch_create.tcl:31 lib/choose_repository.tcl:377
msgid "Create"
msgstr ""
@@ -583,7 +678,7 @@ msgstr ""
msgid "Branch Name"
msgstr ""
-#: lib/branch_create.tcl:43
+#: lib/branch_create.tcl:43 lib/remote_add.tcl:39 lib/tools_dlg.tcl:50
msgid "Name:"
msgstr ""
@@ -723,9 +818,9 @@ msgstr ""
msgid "Browse Branch Files"
msgstr ""
-#: lib/browser.tcl:278 lib/choose_repository.tcl:387
-#: lib/choose_repository.tcl:472 lib/choose_repository.tcl:482
-#: lib/choose_repository.tcl:985
+#: lib/browser.tcl:278 lib/choose_repository.tcl:394
+#: lib/choose_repository.tcl:480 lib/choose_repository.tcl:491
+#: lib/choose_repository.tcl:995
msgid "Browse"
msgstr ""
@@ -740,6 +835,7 @@ msgid "fatal: Cannot resolve %s"
msgstr ""
#: lib/checkout_op.tcl:145 lib/console.tcl:81 lib/database.tcl:31
+#: lib/sshkey.tcl:53
msgid "Close"
msgstr ""
@@ -836,7 +932,7 @@ msgstr ""
msgid "Reset '%s'?"
msgstr ""
-#: lib/checkout_op.tcl:532 lib/merge.tcl:163
+#: lib/checkout_op.tcl:532 lib/merge.tcl:164 lib/tools_dlg.tcl:343
msgid "Visualize"
msgstr ""
@@ -877,221 +973,225 @@ msgstr ""
msgid "Git Gui"
msgstr ""
-#: lib/choose_repository.tcl:81 lib/choose_repository.tcl:376
+#: lib/choose_repository.tcl:87 lib/choose_repository.tcl:382
msgid "Create New Repository"
msgstr ""
-#: lib/choose_repository.tcl:87
+#: lib/choose_repository.tcl:93
msgid "New..."
msgstr ""
-#: lib/choose_repository.tcl:94 lib/choose_repository.tcl:458
+#: lib/choose_repository.tcl:100 lib/choose_repository.tcl:465
msgid "Clone Existing Repository"
msgstr ""
-#: lib/choose_repository.tcl:100
+#: lib/choose_repository.tcl:106
msgid "Clone..."
msgstr ""
-#: lib/choose_repository.tcl:107 lib/choose_repository.tcl:974
+#: lib/choose_repository.tcl:113 lib/choose_repository.tcl:983
msgid "Open Existing Repository"
msgstr ""
-#: lib/choose_repository.tcl:113
+#: lib/choose_repository.tcl:119
msgid "Open..."
msgstr ""
-#: lib/choose_repository.tcl:126
+#: lib/choose_repository.tcl:132
msgid "Recent Repositories"
msgstr ""
-#: lib/choose_repository.tcl:132
+#: lib/choose_repository.tcl:138
msgid "Open Recent Repository:"
msgstr ""
-#: lib/choose_repository.tcl:296 lib/choose_repository.tcl:303
-#: lib/choose_repository.tcl:310
+#: lib/choose_repository.tcl:302 lib/choose_repository.tcl:309
+#: lib/choose_repository.tcl:316
#, tcl-format
msgid "Failed to create repository %s:"
msgstr ""
-#: lib/choose_repository.tcl:381 lib/choose_repository.tcl:476
+#: lib/choose_repository.tcl:387
msgid "Directory:"
msgstr ""
-#: lib/choose_repository.tcl:410 lib/choose_repository.tcl:535
-#: lib/choose_repository.tcl:1007
+#: lib/choose_repository.tcl:417 lib/choose_repository.tcl:544
+#: lib/choose_repository.tcl:1017
msgid "Git Repository"
msgstr ""
-#: lib/choose_repository.tcl:435
+#: lib/choose_repository.tcl:442
#, tcl-format
msgid "Directory %s already exists."
msgstr ""
-#: lib/choose_repository.tcl:439
+#: lib/choose_repository.tcl:446
#, tcl-format
msgid "File %s already exists."
msgstr ""
-#: lib/choose_repository.tcl:453
+#: lib/choose_repository.tcl:460
msgid "Clone"
msgstr ""
-#: lib/choose_repository.tcl:466
-msgid "URL:"
+#: lib/choose_repository.tcl:473
+msgid "Source Location:"
msgstr ""
-#: lib/choose_repository.tcl:487
+#: lib/choose_repository.tcl:484
+msgid "Target Directory:"
+msgstr ""
+
+#: lib/choose_repository.tcl:496
msgid "Clone Type:"
msgstr ""
-#: lib/choose_repository.tcl:493
+#: lib/choose_repository.tcl:502
msgid "Standard (Fast, Semi-Redundant, Hardlinks)"
msgstr ""
-#: lib/choose_repository.tcl:499
+#: lib/choose_repository.tcl:508
msgid "Full Copy (Slower, Redundant Backup)"
msgstr ""
-#: lib/choose_repository.tcl:505
+#: lib/choose_repository.tcl:514
msgid "Shared (Fastest, Not Recommended, No Backup)"
msgstr ""
-#: lib/choose_repository.tcl:541 lib/choose_repository.tcl:588
-#: lib/choose_repository.tcl:734 lib/choose_repository.tcl:804
-#: lib/choose_repository.tcl:1013 lib/choose_repository.tcl:1021
+#: lib/choose_repository.tcl:550 lib/choose_repository.tcl:597
+#: lib/choose_repository.tcl:743 lib/choose_repository.tcl:813
+#: lib/choose_repository.tcl:1023 lib/choose_repository.tcl:1031
#, tcl-format
msgid "Not a Git repository: %s"
msgstr ""
-#: lib/choose_repository.tcl:577
+#: lib/choose_repository.tcl:586
msgid "Standard only available for local repository."
msgstr ""
-#: lib/choose_repository.tcl:581
+#: lib/choose_repository.tcl:590
msgid "Shared only available for local repository."
msgstr ""
-#: lib/choose_repository.tcl:602
+#: lib/choose_repository.tcl:611
#, tcl-format
msgid "Location %s already exists."
msgstr ""
-#: lib/choose_repository.tcl:613
+#: lib/choose_repository.tcl:622
msgid "Failed to configure origin"
msgstr ""
-#: lib/choose_repository.tcl:625
+#: lib/choose_repository.tcl:634
msgid "Counting objects"
msgstr ""
-#: lib/choose_repository.tcl:626
+#: lib/choose_repository.tcl:635
msgid "buckets"
msgstr ""
-#: lib/choose_repository.tcl:650
+#: lib/choose_repository.tcl:659
#, tcl-format
msgid "Unable to copy objects/info/alternates: %s"
msgstr ""
-#: lib/choose_repository.tcl:686
+#: lib/choose_repository.tcl:695
#, tcl-format
msgid "Nothing to clone from %s."
msgstr ""
-#: lib/choose_repository.tcl:688 lib/choose_repository.tcl:902
-#: lib/choose_repository.tcl:914
+#: lib/choose_repository.tcl:697 lib/choose_repository.tcl:911
+#: lib/choose_repository.tcl:923
msgid "The 'master' branch has not been initialized."
msgstr ""
-#: lib/choose_repository.tcl:701
+#: lib/choose_repository.tcl:710
msgid "Hardlinks are unavailable. Falling back to copying."
msgstr ""
-#: lib/choose_repository.tcl:713
+#: lib/choose_repository.tcl:722
#, tcl-format
msgid "Cloning from %s"
msgstr ""
-#: lib/choose_repository.tcl:744
+#: lib/choose_repository.tcl:753
msgid "Copying objects"
msgstr ""
-#: lib/choose_repository.tcl:745
+#: lib/choose_repository.tcl:754
msgid "KiB"
msgstr ""
-#: lib/choose_repository.tcl:769
+#: lib/choose_repository.tcl:778
#, tcl-format
msgid "Unable to copy object: %s"
msgstr ""
-#: lib/choose_repository.tcl:779
+#: lib/choose_repository.tcl:788
msgid "Linking objects"
msgstr ""
-#: lib/choose_repository.tcl:780
+#: lib/choose_repository.tcl:789
msgid "objects"
msgstr ""
-#: lib/choose_repository.tcl:788
+#: lib/choose_repository.tcl:797
#, tcl-format
msgid "Unable to hardlink object: %s"
msgstr ""
-#: lib/choose_repository.tcl:843
+#: lib/choose_repository.tcl:852
msgid "Cannot fetch branches and objects. See console output for details."
msgstr ""
-#: lib/choose_repository.tcl:854
+#: lib/choose_repository.tcl:863
msgid "Cannot fetch tags. See console output for details."
msgstr ""
-#: lib/choose_repository.tcl:878
+#: lib/choose_repository.tcl:887
msgid "Cannot determine HEAD. See console output for details."
msgstr ""
-#: lib/choose_repository.tcl:887
+#: lib/choose_repository.tcl:896
#, tcl-format
msgid "Unable to cleanup %s"
msgstr ""
-#: lib/choose_repository.tcl:893
+#: lib/choose_repository.tcl:902
msgid "Clone failed."
msgstr ""
-#: lib/choose_repository.tcl:900
+#: lib/choose_repository.tcl:909
msgid "No default branch obtained."
msgstr ""
-#: lib/choose_repository.tcl:911
+#: lib/choose_repository.tcl:920
#, tcl-format
msgid "Cannot resolve %s as a commit."
msgstr ""
-#: lib/choose_repository.tcl:923
+#: lib/choose_repository.tcl:932
msgid "Creating working directory"
msgstr ""
-#: lib/choose_repository.tcl:924 lib/index.tcl:65 lib/index.tcl:127
-#: lib/index.tcl:193
+#: lib/choose_repository.tcl:933 lib/index.tcl:65 lib/index.tcl:128
+#: lib/index.tcl:196
msgid "files"
msgstr ""
-#: lib/choose_repository.tcl:953
+#: lib/choose_repository.tcl:962
msgid "Initial file checkout failed."
msgstr ""
-#: lib/choose_repository.tcl:969
+#: lib/choose_repository.tcl:978
msgid "Open"
msgstr ""
-#: lib/choose_repository.tcl:979
+#: lib/choose_repository.tcl:988
msgid "Repository:"
msgstr ""
-#: lib/choose_repository.tcl:1027
+#: lib/choose_repository.tcl:1037
#, tcl-format
msgid "Failed to open repository %s:"
msgstr ""
@@ -1154,19 +1254,19 @@ msgid ""
"current merge activity.\n"
msgstr ""
-#: lib/commit.tcl:49
+#: lib/commit.tcl:48
msgid "Error loading commit data for amend:"
msgstr ""
-#: lib/commit.tcl:76
+#: lib/commit.tcl:75
msgid "Unable to obtain your identity:"
msgstr ""
-#: lib/commit.tcl:81
+#: lib/commit.tcl:80
msgid "Invalid GIT_COMMITTER_IDENT:"
msgstr ""
-#: lib/commit.tcl:133
+#: lib/commit.tcl:132
msgid ""
"Last scanned state does not match repository state.\n"
"\n"
@@ -1176,7 +1276,7 @@ msgid ""
"The rescan will be automatically started now.\n"
msgstr ""
-#: lib/commit.tcl:154
+#: lib/commit.tcl:155
#, tcl-format
msgid ""
"Unmerged files cannot be committed.\n"
@@ -1185,7 +1285,7 @@ msgid ""
"before committing.\n"
msgstr ""
-#: lib/commit.tcl:162
+#: lib/commit.tcl:163
#, tcl-format
msgid ""
"Unknown file state %s detected.\n"
@@ -1193,14 +1293,14 @@ msgid ""
"File %s cannot be committed by this program.\n"
msgstr ""
-#: lib/commit.tcl:170
+#: lib/commit.tcl:171
msgid ""
"No changes to commit.\n"
"\n"
"You must stage at least 1 file before you can commit.\n"
msgstr ""
-#: lib/commit.tcl:183
+#: lib/commit.tcl:186
msgid ""
"Please supply a commit message.\n"
"\n"
@@ -1211,45 +1311,45 @@ msgid ""
"- Remaining lines: Describe why this change is good.\n"
msgstr ""
-#: lib/commit.tcl:207
+#: lib/commit.tcl:210
#, tcl-format
msgid "warning: Tcl does not support encoding '%s'."
msgstr ""
-#: lib/commit.tcl:221
+#: lib/commit.tcl:226
msgid "Calling pre-commit hook..."
msgstr ""
-#: lib/commit.tcl:236
+#: lib/commit.tcl:241
msgid "Commit declined by pre-commit hook."
msgstr ""
-#: lib/commit.tcl:259
+#: lib/commit.tcl:264
msgid "Calling commit-msg hook..."
msgstr ""
-#: lib/commit.tcl:274
+#: lib/commit.tcl:279
msgid "Commit declined by commit-msg hook."
msgstr ""
-#: lib/commit.tcl:287
+#: lib/commit.tcl:292
msgid "Committing changes..."
msgstr ""
-#: lib/commit.tcl:303
+#: lib/commit.tcl:308
msgid "write-tree failed:"
msgstr ""
-#: lib/commit.tcl:304 lib/commit.tcl:348 lib/commit.tcl:368
+#: lib/commit.tcl:309 lib/commit.tcl:353 lib/commit.tcl:373
msgid "Commit failed."
msgstr ""
-#: lib/commit.tcl:321
+#: lib/commit.tcl:326
#, tcl-format
msgid "Commit %s appears to be corrupt"
msgstr ""
-#: lib/commit.tcl:326
+#: lib/commit.tcl:331
msgid ""
"No changes to commit.\n"
"\n"
@@ -1258,19 +1358,19 @@ msgid ""
"A rescan will be automatically started now.\n"
msgstr ""
-#: lib/commit.tcl:333
+#: lib/commit.tcl:338
msgid "No changes to commit."
msgstr ""
-#: lib/commit.tcl:347
+#: lib/commit.tcl:352
msgid "commit-tree failed:"
msgstr ""
-#: lib/commit.tcl:367
+#: lib/commit.tcl:372
msgid "update-ref failed:"
msgstr ""
-#: lib/commit.tcl:454
+#: lib/commit.tcl:460
#, tcl-format
msgid "Created commit %s: %s"
msgstr ""
@@ -1339,7 +1439,7 @@ msgstr ""
msgid "Invalid date from Git: %s"
msgstr ""
-#: lib/diff.tcl:44
+#: lib/diff.tcl:59
#, tcl-format
msgid ""
"No differences detected.\n"
@@ -1353,48 +1453,92 @@ msgid ""
"the same state."
msgstr ""
-#: lib/diff.tcl:83
+#: lib/diff.tcl:99
#, tcl-format
msgid "Loading diff of %s..."
msgstr ""
-#: lib/diff.tcl:116 lib/diff.tcl:190
+#: lib/diff.tcl:120
+msgid ""
+"LOCAL: deleted\n"
+"REMOTE:\n"
+msgstr ""
+
+#: lib/diff.tcl:125
+msgid ""
+"REMOTE: deleted\n"
+"LOCAL:\n"
+msgstr ""
+
+#: lib/diff.tcl:132
+msgid "LOCAL:\n"
+msgstr ""
+
+#: lib/diff.tcl:135
+msgid "REMOTE:\n"
+msgstr ""
+
+#: lib/diff.tcl:197 lib/diff.tcl:296
#, tcl-format
msgid "Unable to display %s"
msgstr ""
-#: lib/diff.tcl:117
+#: lib/diff.tcl:198
msgid "Error loading file:"
msgstr ""
-#: lib/diff.tcl:124
+#: lib/diff.tcl:205
msgid "Git Repository (subproject)"
msgstr ""
-#: lib/diff.tcl:136
+#: lib/diff.tcl:217
msgid "* Binary file (not showing content)."
msgstr ""
-#: lib/diff.tcl:191
-msgid "Error loading diff:"
+#: lib/diff.tcl:222
+#, tcl-format
+msgid ""
+"* Untracked file is %d bytes.\n"
+"* Showing only first %d bytes.\n"
+msgstr ""
+
+#: lib/diff.tcl:228
+#, tcl-format
+msgid ""
+"\n"
+"* Untracked file clipped here by %s.\n"
+"* To see the entire file, use an external editor.\n"
msgstr ""
-#: lib/diff.tcl:313
+#: lib/diff.tcl:436
msgid "Failed to unstage selected hunk."
msgstr ""
-#: lib/diff.tcl:320
+#: lib/diff.tcl:443
msgid "Failed to stage selected hunk."
msgstr ""
-#: lib/diff.tcl:386
+#: lib/diff.tcl:509
msgid "Failed to unstage selected line."
msgstr ""
-#: lib/diff.tcl:394
+#: lib/diff.tcl:517
msgid "Failed to stage selected line."
msgstr ""
+#: lib/encoding.tcl:443
+msgid "Default"
+msgstr ""
+
+#: lib/encoding.tcl:448
+#, tcl-format
+msgid "System (%s)"
+msgstr ""
+
+#: lib/encoding.tcl:459 lib/encoding.tcl:465
+msgid "Other"
+msgstr ""
+
#: lib/error.tcl:20 lib/error.tcl:114
msgid "error"
msgstr ""
@@ -1429,38 +1573,47 @@ msgstr ""
msgid "Unlock Index"
msgstr ""
-#: lib/index.tcl:282
+#: lib/index.tcl:287
#, tcl-format
msgid "Unstaging %s from commit"
msgstr ""
-#: lib/index.tcl:313
+#: lib/index.tcl:326
msgid "Ready to commit."
msgstr ""
-#: lib/index.tcl:326
+#: lib/index.tcl:339
#, tcl-format
msgid "Adding %s"
msgstr ""
-#: lib/index.tcl:381
+#: lib/index.tcl:396
#, tcl-format
msgid "Revert changes in file %s?"
msgstr ""
-#: lib/index.tcl:383
+#: lib/index.tcl:398
#, tcl-format
msgid "Revert changes in these %i files?"
msgstr ""
-#: lib/index.tcl:391
+#: lib/index.tcl:406
msgid "Any unstaged changes will be permanently lost by the revert."
msgstr ""
-#: lib/index.tcl:394
+#: lib/index.tcl:409
msgid "Do Nothing"
msgstr ""
+#: lib/index.tcl:427
+msgid "Reverting selected files"
+msgstr ""
+
+#: lib/index.tcl:431
+#, tcl-format
+msgid "Reverting %s"
+msgstr ""
+
#: lib/merge.tcl:13
msgid ""
"Cannot merge while amending.\n"
@@ -1478,7 +1631,7 @@ msgid ""
"The rescan will be automatically started now.\n"
msgstr ""
-#: lib/merge.tcl:44
+#: lib/merge.tcl:45
#, tcl-format
msgid ""
"You are in the middle of a conflicted merge.\n"
@@ -1489,7 +1642,7 @@ msgid ""
"merge. Only then can you begin another merge.\n"
msgstr ""
-#: lib/merge.tcl:54
+#: lib/merge.tcl:55
#, tcl-format
msgid ""
"You are in the middle of a change.\n"
@@ -1500,41 +1653,41 @@ msgid ""
"will help you abort a failed merge, should the need arise.\n"
msgstr ""
-#: lib/merge.tcl:106
+#: lib/merge.tcl:107
#, tcl-format
msgid "%s of %s"
msgstr ""
-#: lib/merge.tcl:119
+#: lib/merge.tcl:120
#, tcl-format
msgid "Merging %s and %s..."
msgstr ""
-#: lib/merge.tcl:130
+#: lib/merge.tcl:131
msgid "Merge completed successfully."
msgstr ""
-#: lib/merge.tcl:132
+#: lib/merge.tcl:133
msgid "Merge failed. Conflict resolution is required."
msgstr ""
-#: lib/merge.tcl:157
+#: lib/merge.tcl:158
#, tcl-format
msgid "Merge Into %s"
msgstr ""
-#: lib/merge.tcl:176
+#: lib/merge.tcl:177
msgid "Revision To Merge"
msgstr ""
-#: lib/merge.tcl:211
+#: lib/merge.tcl:212
msgid ""
"Cannot abort while amending.\n"
"\n"
"You must finish amending this commit.\n"
msgstr ""
-#: lib/merge.tcl:221
+#: lib/merge.tcl:222
msgid ""
"Abort merge?\n"
"\n"
@@ -1543,7 +1696,7 @@ msgid ""
"Continue with aborting the current merge?"
msgstr ""
-#: lib/merge.tcl:227
+#: lib/merge.tcl:228
msgid ""
"Reset changes?\n"
"\n"
@@ -1552,142 +1705,325 @@ msgid ""
"Continue with resetting the current changes?"
msgstr ""
-#: lib/merge.tcl:238
+#: lib/merge.tcl:239
msgid "Aborting"
msgstr ""
-#: lib/merge.tcl:238
+#: lib/merge.tcl:239
msgid "files reset"
msgstr ""
-#: lib/merge.tcl:266
+#: lib/merge.tcl:267
msgid "Abort failed."
msgstr ""
-#: lib/merge.tcl:268
+#: lib/merge.tcl:269
msgid "Abort completed. Ready."
msgstr ""
-#: lib/option.tcl:95
+#: lib/mergetool.tcl:8
+msgid "Force resolution to the base version?"
+msgstr ""
+
+#: lib/mergetool.tcl:9
+msgid "Force resolution to this branch?"
+msgstr ""
+
+#: lib/mergetool.tcl:10
+msgid "Force resolution to the other branch?"
+msgstr ""
+
+#: lib/mergetool.tcl:14
+#, tcl-format
+msgid ""
+"Note that the diff shows only conflicting changes.\n"
+"\n"
+"%s will be overwritten.\n"
+"\n"
+"This operation can be undone only by restarting the merge."
+msgstr ""
+
+#: lib/mergetool.tcl:45
+#, tcl-format
+msgid "File %s seems to have unresolved conflicts, still stage?"
+msgstr ""
+
+#: lib/mergetool.tcl:60
+#, tcl-format
+msgid "Adding resolution for %s"
+msgstr ""
+
+#: lib/mergetool.tcl:141
+msgid "Cannot resolve deletion or link conflicts using a tool"
+msgstr ""
+
+#: lib/mergetool.tcl:146
+msgid "Conflict file does not exist"
+msgstr ""
+
+#: lib/mergetool.tcl:264
+#, tcl-format
+msgid "Not a GUI merge tool: '%s'"
+msgstr ""
+
+#: lib/mergetool.tcl:268
+#, tcl-format
+msgid "Unsupported merge tool '%s'"
+msgstr ""
+
+#: lib/mergetool.tcl:303
+msgid "Merge tool is already running, terminate it?"
+msgstr ""
+
+#: lib/mergetool.tcl:323
+#, tcl-format
+msgid ""
+"Error retrieving versions:\n"
+"%s"
+msgstr ""
+
+#: lib/mergetool.tcl:343
+#, tcl-format
+msgid ""
+"Could not start the merge tool:\n"
+"\n"
+"%s"
+msgstr ""
+
+#: lib/mergetool.tcl:347
+msgid "Running merge tool..."
+msgstr ""
+
+#: lib/mergetool.tcl:375 lib/mergetool.tcl:383
+msgid "Merge tool failed."
+msgstr ""
+
+#: lib/option.tcl:11
+#, tcl-format
+msgid "Invalid global encoding '%s'"
+msgstr ""
+
+#: lib/option.tcl:19
+#, tcl-format
+msgid "Invalid repo encoding '%s'"
+msgstr ""
+
+#: lib/option.tcl:117
msgid "Restore Defaults"
msgstr ""
-#: lib/option.tcl:99
+#: lib/option.tcl:121
msgid "Save"
msgstr ""
-#: lib/option.tcl:109
+#: lib/option.tcl:131
#, tcl-format
msgid "%s Repository"
msgstr ""
-#: lib/option.tcl:110
+#: lib/option.tcl:132
msgid "Global (All Repositories)"
msgstr ""
-#: lib/option.tcl:116
+#: lib/option.tcl:138
msgid "User Name"
msgstr ""
-#: lib/option.tcl:117
+#: lib/option.tcl:139
msgid "Email Address"
msgstr ""
-#: lib/option.tcl:119
+#: lib/option.tcl:141
msgid "Summarize Merge Commits"
msgstr ""
-#: lib/option.tcl:120
+#: lib/option.tcl:142
msgid "Merge Verbosity"
msgstr ""
-#: lib/option.tcl:121
+#: lib/option.tcl:143
msgid "Show Diffstat After Merge"
msgstr ""
-#: lib/option.tcl:123
+#: lib/option.tcl:144
+msgid "Use Merge Tool"
+msgstr ""
+
+#: lib/option.tcl:146
msgid "Trust File Modification Timestamps"
msgstr ""
-#: lib/option.tcl:124
+#: lib/option.tcl:147
msgid "Prune Tracking Branches During Fetch"
msgstr ""
-#: lib/option.tcl:125
+#: lib/option.tcl:148
msgid "Match Tracking Branches"
msgstr ""
-#: lib/option.tcl:126
+#: lib/option.tcl:149
msgid "Blame Copy Only On Changed Files"
msgstr ""
-#: lib/option.tcl:127
+#: lib/option.tcl:150
msgid "Minimum Letters To Blame Copy On"
msgstr ""
-#: lib/option.tcl:128
+#: lib/option.tcl:151
+msgid "Blame History Context Radius (days)"
+msgstr ""
+
+#: lib/option.tcl:152
msgid "Number of Diff Context Lines"
msgstr ""
-#: lib/option.tcl:129
+#: lib/option.tcl:153
msgid "Commit Message Text Width"
msgstr ""
-#: lib/option.tcl:130
+#: lib/option.tcl:154
msgid "New Branch Name Template"
msgstr ""
-#: lib/option.tcl:194
+#: lib/option.tcl:155
+msgid "Default File Contents Encoding"
+msgstr ""
+
+#: lib/option.tcl:203
+msgid "Change"
+msgstr ""
+
+#: lib/option.tcl:230
msgid "Spelling Dictionary:"
msgstr ""
-#: lib/option.tcl:218
+#: lib/option.tcl:254
msgid "Change Font"
msgstr ""
-#: lib/option.tcl:222
+#: lib/option.tcl:258
#, tcl-format
msgid "Choose %s"
msgstr ""
-#: lib/option.tcl:228
+#: lib/option.tcl:264
msgid "pt."
msgstr ""
-#: lib/option.tcl:242
+#: lib/option.tcl:278
msgid "Preferences"
msgstr ""
-#: lib/option.tcl:277
+#: lib/option.tcl:314
msgid "Failed to completely save options:"
msgstr ""
-#: lib/remote.tcl:165
+#: lib/remote.tcl:163
+msgid "Remove Remote"
+msgstr ""
+
+#: lib/remote.tcl:168
msgid "Prune from"
msgstr ""
-#: lib/remote.tcl:170
+#: lib/remote.tcl:173
msgid "Fetch from"
msgstr ""
-#: lib/remote.tcl:213
+#: lib/remote.tcl:215
msgid "Push to"
msgstr ""
+#: lib/remote_add.tcl:19
+msgid "Add Remote"
+msgstr ""
+
+#: lib/remote_add.tcl:24
+msgid "Add New Remote"
+msgstr ""
+
+#: lib/remote_add.tcl:28 lib/tools_dlg.tcl:36
+msgid "Add"
+msgstr ""
+
+#: lib/remote_add.tcl:37
+msgid "Remote Details"
+msgstr ""
+
+#: lib/remote_add.tcl:50
+msgid "Location:"
+msgstr ""
+
+#: lib/remote_add.tcl:62
+msgid "Further Action"
+msgstr ""
+
+#: lib/remote_add.tcl:65
+msgid "Fetch Immediately"
+msgstr ""
+
+#: lib/remote_add.tcl:71
+msgid "Initialize Remote Repository and Push"
+msgstr ""
+
+#: lib/remote_add.tcl:77
+msgid "Do Nothing Else Now"
+msgstr ""
+
+#: lib/remote_add.tcl:101
+msgid "Please supply a remote name."
+msgstr ""
+
+#: lib/remote_add.tcl:114
+#, tcl-format
+msgid "'%s' is not an acceptable remote name."
+msgstr ""
+
+#: lib/remote_add.tcl:125
+#, tcl-format
+msgid "Failed to add remote '%s' of location '%s'."
+msgstr ""
+
+#: lib/remote_add.tcl:133 lib/transport.tcl:6
+#, tcl-format
+msgid "fetch %s"
+msgstr ""
+
+#: lib/remote_add.tcl:134
+#, tcl-format
+msgid "Fetching the %s"
+msgstr ""
+
+#: lib/remote_add.tcl:157
+#, tcl-format
+msgid "Do not know how to initialize repository at location '%s'."
+msgstr ""
+
+#: lib/remote_add.tcl:163 lib/transport.tcl:25 lib/transport.tcl:63
+#: lib/transport.tcl:81
+#, tcl-format
+msgid "push %s"
+msgstr ""
+
+#: lib/remote_add.tcl:164
+#, tcl-format
+msgid "Setting up the %s (at %s)"
+msgstr ""
+
#: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34
-msgid "Delete Remote Branch"
+msgid "Delete Branch Remotely"
msgstr ""
#: lib/remote_branch_delete.tcl:47
msgid "From Repository"
msgstr ""
-#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:123
+#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:134
msgid "Remote:"
msgstr ""
-#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:138
-msgid "Arbitrary URL:"
+#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:149
+msgid "Arbitrary Location:"
msgstr ""
#: lib/remote_branch_delete.tcl:84
@@ -1750,6 +2086,22 @@ msgstr ""
msgid "Scanning %s..."
msgstr ""
+#: lib/search.tcl:21
+msgid "Find:"
+msgstr ""
+
+#: lib/search.tcl:23
+msgid "Next"
+msgstr ""
+
+#: lib/search.tcl:24
+msgid "Prev"
+msgstr ""
+
+#: lib/search.tcl:25
+msgid "Case-Sensitive"
+msgstr ""
+
#: lib/shortcut.tcl:20 lib/shortcut.tcl:61
msgid "Cannot write shortcut:"
msgstr ""
@@ -1787,22 +2139,182 @@ msgstr ""
msgid "No Suggestions"
msgstr ""
-#: lib/spellcheck.tcl:387
+#: lib/spellcheck.tcl:388
msgid "Unexpected EOF from spell checker"
msgstr ""
-#: lib/spellcheck.tcl:391
+#: lib/spellcheck.tcl:392
msgid "Spell Checker Failed"
msgstr ""
+#: lib/sshkey.tcl:31
+msgid "No keys found."
+msgstr ""
+
+#: lib/sshkey.tcl:34
+#, tcl-format
+msgid "Found a public key in: %s"
+msgstr ""
+
+#: lib/sshkey.tcl:40
+msgid "Generate Key"
+msgstr ""
+
+#: lib/sshkey.tcl:56
+msgid "Copy To Clipboard"
+msgstr ""
+
+#: lib/sshkey.tcl:70
+msgid "Your OpenSSH Public Key"
+msgstr ""
+
+#: lib/sshkey.tcl:78
+msgid "Generating..."
+msgstr ""
+
+#: lib/sshkey.tcl:84
+#, tcl-format
+msgid ""
+"Could not start ssh-keygen:\n"
+"\n"
+"%s"
+msgstr ""
+
+#: lib/sshkey.tcl:111
+msgid "Generation failed."
+msgstr ""
+
+#: lib/sshkey.tcl:118
+msgid "Generation succeded, but no keys found."
+msgstr ""
+
+#: lib/sshkey.tcl:121
+#, tcl-format
+msgid "Your key is in: %s"
+msgstr ""
+
#: lib/status_bar.tcl:83
#, tcl-format
msgid "%s ... %*i of %*i %s (%3i%%)"
msgstr ""
-#: lib/transport.tcl:6
+#: lib/tools.tcl:75
#, tcl-format
-msgid "fetch %s"
+msgid "Running %s requires a selected file."
+msgstr ""
+
+#: lib/tools.tcl:90
+#, tcl-format
+msgid "Are you sure you want to run %s?"
+msgstr ""
+
+#: lib/tools.tcl:110
+#, tcl-format
+msgid "Tool: %s"
+msgstr ""
+
+#: lib/tools.tcl:111
+#, tcl-format
+msgid "Running: %s"
+msgstr ""
+
+#: lib/tools.tcl:149
+#, tcl-format
+msgid "Tool completed succesfully: %s"
+msgstr ""
+
+#: lib/tools.tcl:151
+#, tcl-format
+msgid "Tool failed: %s"
+msgstr ""
+
+#: lib/tools_dlg.tcl:22
+msgid "Add Tool"
+msgstr ""
+
+#: lib/tools_dlg.tcl:28
+msgid "Add New Tool Command"
+msgstr ""
+
+#: lib/tools_dlg.tcl:33
+msgid "Add globally"
+msgstr ""
+
+#: lib/tools_dlg.tcl:45
+msgid "Tool Details"
+msgstr ""
+
+#: lib/tools_dlg.tcl:48
+msgid "Use '/' separators to create a submenu tree:"
+msgstr ""
+
+#: lib/tools_dlg.tcl:61
+msgid "Command:"
+msgstr ""
+
+#: lib/tools_dlg.tcl:74
+msgid "Show a dialog before running"
+msgstr ""
+
+#: lib/tools_dlg.tcl:80
+msgid "Ask the user to select a revision (sets $REVISION)"
+msgstr ""
+
+#: lib/tools_dlg.tcl:85
+msgid "Ask the user for additional arguments (sets $ARGS)"
+msgstr ""
+
+#: lib/tools_dlg.tcl:92
+msgid "Don't show the command output window"
+msgstr ""
+
+#: lib/tools_dlg.tcl:97
+msgid "Run only if a diff is selected ($FILENAME not empty)"
+msgstr ""
+
+#: lib/tools_dlg.tcl:121
+msgid "Please supply a name for the tool."
+msgstr ""
+
+#: lib/tools_dlg.tcl:129
+#, tcl-format
+msgid "Tool '%s' already exists."
+msgstr ""
+
+#: lib/tools_dlg.tcl:151
+#, tcl-format
+msgid ""
+"Could not add tool:\n"
+"%s"
+msgstr ""
+
+#: lib/tools_dlg.tcl:190
+msgid "Remove Tool"
+msgstr ""
+
+#: lib/tools_dlg.tcl:196
+msgid "Remove Tool Commands"
+msgstr ""
+
+#: lib/tools_dlg.tcl:200
+msgid "Remove"
+msgstr ""
+
+#: lib/tools_dlg.tcl:236
+msgid "(Blue denotes repository-local tools)"
+msgstr ""
+
+#: lib/tools_dlg.tcl:297
+#, tcl-format
+msgid "Run Command: %s"
+msgstr ""
+
+#: lib/tools_dlg.tcl:311
+msgid "Arguments"
+msgstr ""
+
+#: lib/tools_dlg.tcl:348
+msgid "OK"
msgstr ""
#: lib/transport.tcl:7
@@ -1820,45 +2332,45 @@ msgstr ""
msgid "Pruning tracking branches deleted from %s"
msgstr ""
-#: lib/transport.tcl:25 lib/transport.tcl:71
+#: lib/transport.tcl:26
#, tcl-format
-msgid "push %s"
+msgid "Pushing changes to %s"
msgstr ""
-#: lib/transport.tcl:26
+#: lib/transport.tcl:64
#, tcl-format
-msgid "Pushing changes to %s"
+msgid "Mirroring to %s"
msgstr ""
-#: lib/transport.tcl:72
+#: lib/transport.tcl:82
#, tcl-format
msgid "Pushing %s %s to %s"
msgstr ""
-#: lib/transport.tcl:89
+#: lib/transport.tcl:100
msgid "Push Branches"
msgstr ""
-#: lib/transport.tcl:103
+#: lib/transport.tcl:114
msgid "Source Branches"
msgstr ""
-#: lib/transport.tcl:120
+#: lib/transport.tcl:131
msgid "Destination Repository"
msgstr ""
-#: lib/transport.tcl:158
+#: lib/transport.tcl:169
msgid "Transfer Options"
msgstr ""
-#: lib/transport.tcl:160
+#: lib/transport.tcl:171
msgid "Force overwrite existing branch (may discard changes)"
msgstr ""
-#: lib/transport.tcl:164
+#: lib/transport.tcl:175
msgid "Use thin pack (for slow network connections)"
msgstr ""
-#: lib/transport.tcl:168
+#: lib/transport.tcl:179
msgid "Include tags"
msgstr ""
diff --git a/git-gui/po/hu.po b/git-gui/po/hu.po
index 28760ed978..f761b64152 100644
--- a/git-gui/po/hu.po
+++ b/git-gui/po/hu.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: git-gui-i 18n\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-03-14 07:18+0100\n"
-"PO-Revision-Date: 2008-03-14 17:24+0100\n"
+"POT-Creation-Date: 2008-12-08 08:31-0800\n"
+"PO-Revision-Date: 2008-12-10 15:00+0100\n"
"Last-Translator: Miklos Vajna <vmiklos@frugalware.org>\n"
"Language-Team: Hungarian\n"
"MIME-Version: 1.0\n"
@@ -16,33 +16,33 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: git-gui.sh:41 git-gui.sh:634 git-gui.sh:648 git-gui.sh:661 git-gui.sh:744
-#: git-gui.sh:763
+#: git-gui.sh:41 git-gui.sh:737 git-gui.sh:751 git-gui.sh:764 git-gui.sh:847
+#: git-gui.sh:866
msgid "git-gui: fatal error"
msgstr "git-gui: végzetes hiba"
-#: git-gui.sh:593
+#: git-gui.sh:689
#, tcl-format
msgid "Invalid font specified in %s:"
msgstr "Érvénytelen font lett megadva itt: %s:"
-#: git-gui.sh:620
+#: git-gui.sh:723
msgid "Main Font"
msgstr "Fő betűtípus"
-#: git-gui.sh:621
+#: git-gui.sh:724
msgid "Diff/Console Font"
msgstr "Diff/konzol betűtípus"
-#: git-gui.sh:635
+#: git-gui.sh:738
msgid "Cannot find git in PATH."
msgstr "A git nem található a PATH-ban."
-#: git-gui.sh:662
+#: git-gui.sh:765
msgid "Cannot parse Git version string:"
msgstr "Nem értelmezhető a Git verzió sztring:"
-#: git-gui.sh:680
+#: git-gui.sh:783
#, tcl-format
msgid ""
"Git version cannot be determined.\n"
@@ -61,379 +61,445 @@ msgstr ""
"\n"
"Feltételezhetjük, hogy a(z) '%s' verziója legalább 1.5.0?\n"
-#: git-gui.sh:918
+#: git-gui.sh:1062
msgid "Git directory not found:"
msgstr "A Git könyvtár nem található:"
-#: git-gui.sh:925
+#: git-gui.sh:1069
msgid "Cannot move to top of working directory:"
msgstr "Nem lehet a munkakönyvtár tetejére lépni:"
-#: git-gui.sh:932
+#: git-gui.sh:1076
msgid "Cannot use funny .git directory:"
msgstr "Nem használható vicces .git könyvtár:"
-#: git-gui.sh:937
+#: git-gui.sh:1081
msgid "No working directory"
msgstr "Nincs munkakönyvtár"
-#: git-gui.sh:1084 lib/checkout_op.tcl:283
+#: git-gui.sh:1247 lib/checkout_op.tcl:305
msgid "Refreshing file status..."
msgstr "A fájlok státuszának frissítése..."
-#: git-gui.sh:1149
+#: git-gui.sh:1303
msgid "Scanning for modified files ..."
msgstr "Módosított fájlok keresése ..."
-#: git-gui.sh:1324 lib/browser.tcl:246
+#: git-gui.sh:1367
+msgid "Calling prepare-commit-msg hook..."
+msgstr "A prepare-commit-msg hurok meghívása..."
+
+#: git-gui.sh:1384
+msgid "Commit declined by prepare-commit-msg hook."
+msgstr "A commitot megakadályozta a prepare-commit-msg hurok."
+
+#: git-gui.sh:1542 lib/browser.tcl:246
msgid "Ready."
msgstr "Kész."
-#: git-gui.sh:1590
+#: git-gui.sh:1819
msgid "Unmodified"
msgstr "Nem módosított"
-#: git-gui.sh:1592
+#: git-gui.sh:1821
msgid "Modified, not staged"
msgstr "Módosított, de nem kiválasztott"
-#: git-gui.sh:1593 git-gui.sh:1598
+#: git-gui.sh:1822 git-gui.sh:1830
msgid "Staged for commit"
msgstr "Kiválasztva commitolásra"
-#: git-gui.sh:1594 git-gui.sh:1599
+#: git-gui.sh:1823 git-gui.sh:1831
msgid "Portions staged for commit"
msgstr "Részek kiválasztva commitolásra"
-#: git-gui.sh:1595 git-gui.sh:1600
+#: git-gui.sh:1824 git-gui.sh:1832
msgid "Staged for commit, missing"
msgstr "Kiválasztva commitolásra, hiányzó"
-#: git-gui.sh:1597
+#: git-gui.sh:1826
+msgid "File type changed, not staged"
+msgstr "Fájl típus megváltozott, nem kiválasztott"
+
+#: git-gui.sh:1827
+msgid "File type changed, staged"
+msgstr "A fájltípus megváltozott, kiválasztott"
+
+#: git-gui.sh:1829
msgid "Untracked, not staged"
msgstr "Nem követett, nem kiválasztott"
-#: git-gui.sh:1602
+#: git-gui.sh:1834
msgid "Missing"
msgstr "Hiányzó"
-#: git-gui.sh:1603
+#: git-gui.sh:1835
msgid "Staged for removal"
msgstr "Kiválasztva eltávolításra"
-#: git-gui.sh:1604
+#: git-gui.sh:1836
msgid "Staged for removal, still present"
msgstr "Kiválasztva eltávolításra, jelenleg is elérhető"
-#: git-gui.sh:1606 git-gui.sh:1607 git-gui.sh:1608 git-gui.sh:1609
+#: git-gui.sh:1838 git-gui.sh:1839 git-gui.sh:1840 git-gui.sh:1841
+#: git-gui.sh:1842 git-gui.sh:1843
msgid "Requires merge resolution"
msgstr "Merge feloldás szükséges"
-#: git-gui.sh:1644
+#: git-gui.sh:1878
msgid "Starting gitk... please wait..."
msgstr "A gitk indítása... várjunk..."
-#: git-gui.sh:1653
-#, tcl-format
-msgid ""
-"Unable to start gitk:\n"
-"\n"
-"%s does not exist"
-msgstr ""
-"A gitk indítása sikertelen:\n"
-"\n"
-"A(z) %s nem létezik"
+#: git-gui.sh:1887
+msgid "Couldn't find gitk in PATH"
+msgstr "A gitk nem található a PATH-ban."
-#: git-gui.sh:1860 lib/choose_repository.tcl:36
+#: git-gui.sh:2280 lib/choose_repository.tcl:36
msgid "Repository"
msgstr "Repó"
-#: git-gui.sh:1861
+#: git-gui.sh:2281
msgid "Edit"
msgstr "Szerkesztés"
-#: git-gui.sh:1863 lib/choose_rev.tcl:561
+#: git-gui.sh:2283 lib/choose_rev.tcl:561
msgid "Branch"
msgstr "Branch"
-#: git-gui.sh:1866 lib/choose_rev.tcl:548
+#: git-gui.sh:2286 lib/choose_rev.tcl:548
msgid "Commit@@noun"
msgstr "Commit@@főnév"
-#: git-gui.sh:1869 lib/merge.tcl:120 lib/merge.tcl:149 lib/merge.tcl:167
+#: git-gui.sh:2289 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168
msgid "Merge"
msgstr "Merge"
-#: git-gui.sh:1870 lib/choose_rev.tcl:557
+#: git-gui.sh:2290 lib/choose_rev.tcl:557
msgid "Remote"
msgstr "Távoli"
-#: git-gui.sh:1879
+#: git-gui.sh:2293
+msgid "Tools"
+msgstr "Eszközök"
+
+#: git-gui.sh:2302
+msgid "Explore Working Copy"
+msgstr "Munkamásolat felfedezése"
+
+#: git-gui.sh:2307
msgid "Browse Current Branch's Files"
msgstr "A jelenlegi branch fájljainak böngészése"
-#: git-gui.sh:1883
+#: git-gui.sh:2311
msgid "Browse Branch Files..."
msgstr "A branch fájljainak böngészése..."
-#: git-gui.sh:1888
+#: git-gui.sh:2316
msgid "Visualize Current Branch's History"
msgstr "A jelenlegi branch történetének vizualizálása"
-#: git-gui.sh:1892
+#: git-gui.sh:2320
msgid "Visualize All Branch History"
msgstr "Az összes branch történetének vizualizálása"
-#: git-gui.sh:1899
+#: git-gui.sh:2327
#, tcl-format
msgid "Browse %s's Files"
msgstr "A(z) %s branch fájljainak böngészése"
-#: git-gui.sh:1901
+#: git-gui.sh:2329
#, tcl-format
msgid "Visualize %s's History"
msgstr "A(z) %s branch történetének vizualizálása"
-#: git-gui.sh:1906 lib/database.tcl:27 lib/database.tcl:67
+#: git-gui.sh:2334 lib/database.tcl:27 lib/database.tcl:67
msgid "Database Statistics"
msgstr "Adatbázis statisztikák"
-#: git-gui.sh:1909 lib/database.tcl:34
+#: git-gui.sh:2337 lib/database.tcl:34
msgid "Compress Database"
msgstr "Adatbázis tömörítése"
-#: git-gui.sh:1912
+#: git-gui.sh:2340
msgid "Verify Database"
msgstr "Adatbázis ellenőrzése"
-#: git-gui.sh:1919 git-gui.sh:1923 git-gui.sh:1927 lib/shortcut.tcl:7
+#: git-gui.sh:2347 git-gui.sh:2351 git-gui.sh:2355 lib/shortcut.tcl:7
#: lib/shortcut.tcl:39 lib/shortcut.tcl:71
msgid "Create Desktop Icon"
msgstr "Asztal ikon létrehozása"
-#: git-gui.sh:1932 lib/choose_repository.tcl:177 lib/choose_repository.tcl:185
+#: git-gui.sh:2363 lib/choose_repository.tcl:183 lib/choose_repository.tcl:191
msgid "Quit"
msgstr "Kilépés"
-#: git-gui.sh:1939
+#: git-gui.sh:2371
msgid "Undo"
msgstr "Visszavonás"
-#: git-gui.sh:1942
+#: git-gui.sh:2374
msgid "Redo"
msgstr "Mégis"
-#: git-gui.sh:1946 git-gui.sh:2443
+#: git-gui.sh:2378 git-gui.sh:2937
msgid "Cut"
msgstr "Kivágás"
-#: git-gui.sh:1949 git-gui.sh:2446 git-gui.sh:2520 git-gui.sh:2614
+#: git-gui.sh:2381 git-gui.sh:2940 git-gui.sh:3014 git-gui.sh:3096
#: lib/console.tcl:69
msgid "Copy"
msgstr "Másolás"
-#: git-gui.sh:1952 git-gui.sh:2449
+#: git-gui.sh:2384 git-gui.sh:2943
msgid "Paste"
msgstr "Beillesztés"
-#: git-gui.sh:1955 git-gui.sh:2452 lib/branch_delete.tcl:26
+#: git-gui.sh:2387 git-gui.sh:2946 lib/branch_delete.tcl:26
#: lib/remote_branch_delete.tcl:38
msgid "Delete"
msgstr "Törlés"
-#: git-gui.sh:1959 git-gui.sh:2456 git-gui.sh:2618 lib/console.tcl:71
+#: git-gui.sh:2391 git-gui.sh:2950 git-gui.sh:3100 lib/console.tcl:71
msgid "Select All"
msgstr "Mindent kiválaszt"
-#: git-gui.sh:1968
+#: git-gui.sh:2400
msgid "Create..."
msgstr "Létrehozás..."
-#: git-gui.sh:1974
+#: git-gui.sh:2406
msgid "Checkout..."
msgstr "Checkout..."
-#: git-gui.sh:1980
+#: git-gui.sh:2412
msgid "Rename..."
msgstr "Ãtnevezés..."
-#: git-gui.sh:1985 git-gui.sh:2085
+#: git-gui.sh:2417
msgid "Delete..."
msgstr "Törlés..."
-#: git-gui.sh:1990
+#: git-gui.sh:2422
msgid "Reset..."
msgstr "Visszaállítás..."
-#: git-gui.sh:2002 git-gui.sh:2389
+#: git-gui.sh:2432
+msgid "Done"
+msgstr "Kész"
+
+#: git-gui.sh:2434
+msgid "Commit@@verb"
+msgstr "Commit@@ige"
+
+#: git-gui.sh:2443 git-gui.sh:2878
msgid "New Commit"
msgstr "Új commit"
-#: git-gui.sh:2010 git-gui.sh:2396
+#: git-gui.sh:2451 git-gui.sh:2885
msgid "Amend Last Commit"
msgstr "Utolsó commit javítása"
-#: git-gui.sh:2019 git-gui.sh:2356 lib/remote_branch_delete.tcl:99
+#: git-gui.sh:2461 git-gui.sh:2839 lib/remote_branch_delete.tcl:99
msgid "Rescan"
msgstr "Keresés újra"
-#: git-gui.sh:2025
+#: git-gui.sh:2467
msgid "Stage To Commit"
msgstr "Kiválasztás commitolásra"
-#: git-gui.sh:2031
+#: git-gui.sh:2473
msgid "Stage Changed Files To Commit"
msgstr "Módosított fájlok kiválasztása commitolásra"
-#: git-gui.sh:2037
+#: git-gui.sh:2479
msgid "Unstage From Commit"
msgstr "Commitba való kiválasztás visszavonása"
-#: git-gui.sh:2042 lib/index.tcl:395
+#: git-gui.sh:2484 lib/index.tcl:410
msgid "Revert Changes"
msgstr "Változtatások visszaállítása"
-#: git-gui.sh:2049 git-gui.sh:2368 git-gui.sh:2467
+#: git-gui.sh:2491 git-gui.sh:3083
+msgid "Show Less Context"
+msgstr "Kevesebb környezet mutatása"
+
+#: git-gui.sh:2495 git-gui.sh:3087
+msgid "Show More Context"
+msgstr "Több környezet mutatása"
+
+#: git-gui.sh:2502 git-gui.sh:2852 git-gui.sh:2961
msgid "Sign Off"
msgstr "Aláír"
-#: git-gui.sh:2053 git-gui.sh:2372
-msgid "Commit@@verb"
-msgstr "Commit@@ige"
-
-#: git-gui.sh:2064
+#: git-gui.sh:2518
msgid "Local Merge..."
msgstr "Helyi merge..."
-#: git-gui.sh:2069
+#: git-gui.sh:2523
msgid "Abort Merge..."
msgstr "Merge megszakítása..."
-#: git-gui.sh:2081
+#: git-gui.sh:2535 git-gui.sh:2575
+msgid "Add..."
+msgstr "Hozzáadás..."
+
+#: git-gui.sh:2539
msgid "Push..."
msgstr "Push..."
-#: git-gui.sh:2092 lib/choose_repository.tcl:41
-msgid "Apple"
-msgstr "Apple"
+#: git-gui.sh:2543
+msgid "Delete Branch..."
+msgstr "Branch törlése..."
-#: git-gui.sh:2095 git-gui.sh:2117 lib/about.tcl:14
-#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50
+#: git-gui.sh:2553 git-gui.sh:2589 lib/about.tcl:14
+#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:53
#, tcl-format
msgid "About %s"
msgstr "Névjegy: %s"
-#: git-gui.sh:2099
+#: git-gui.sh:2557
msgid "Preferences..."
msgstr "Beállítások..."
-#: git-gui.sh:2107 git-gui.sh:2639
+#: git-gui.sh:2565 git-gui.sh:3129
msgid "Options..."
msgstr "Opciók..."
-#: git-gui.sh:2113 lib/choose_repository.tcl:47
+#: git-gui.sh:2576
+msgid "Remove..."
+msgstr "Eltávolítás..."
+
+#: git-gui.sh:2585 lib/choose_repository.tcl:50
msgid "Help"
msgstr "Segítség"
-#: git-gui.sh:2154
+#: git-gui.sh:2611
msgid "Online Documentation"
msgstr "Online dokumentáció"
-#: git-gui.sh:2238
+#: git-gui.sh:2614 lib/choose_repository.tcl:47 lib/choose_repository.tcl:56
+msgid "Show SSH Key"
+msgstr "SSH kulcs mutatása"
+
+#: git-gui.sh:2721
#, tcl-format
msgid "fatal: cannot stat path %s: No such file or directory"
msgstr ""
"végzetes hiba: nem érhető el a(z) %s útvonal: Nincs ilyen fájl vagy könyvtár"
-#: git-gui.sh:2271
+#: git-gui.sh:2754
msgid "Current Branch:"
msgstr "Jelenlegi branch:"
-#: git-gui.sh:2292
+#: git-gui.sh:2775
msgid "Staged Changes (Will Commit)"
msgstr "Kiválasztott változtatások (commitolva lesz)"
-#: git-gui.sh:2312
+#: git-gui.sh:2795
msgid "Unstaged Changes"
msgstr "Kiválasztatlan változtatások"
-#: git-gui.sh:2362
+#: git-gui.sh:2845
msgid "Stage Changed"
msgstr "Változtatások kiválasztása"
-#: git-gui.sh:2378 lib/transport.tcl:93 lib/transport.tcl:182
+#: git-gui.sh:2864 lib/transport.tcl:104 lib/transport.tcl:193
msgid "Push"
msgstr "Push"
-#: git-gui.sh:2408
+#: git-gui.sh:2899
msgid "Initial Commit Message:"
msgstr "Kezdeti commit üzenet:"
-#: git-gui.sh:2409
+#: git-gui.sh:2900
msgid "Amended Commit Message:"
msgstr "Javító commit üzenet:"
-#: git-gui.sh:2410
+#: git-gui.sh:2901
msgid "Amended Initial Commit Message:"
msgstr "Kezdeti javító commit üzenet:"
-#: git-gui.sh:2411
+#: git-gui.sh:2902
msgid "Amended Merge Commit Message:"
msgstr "Javító merge commit üzenet:"
-#: git-gui.sh:2412
+#: git-gui.sh:2903
msgid "Merge Commit Message:"
msgstr "Merge commit üzenet:"
-#: git-gui.sh:2413
+#: git-gui.sh:2904
msgid "Commit Message:"
msgstr "Commit üzenet:"
-#: git-gui.sh:2459 git-gui.sh:2622 lib/console.tcl:73
+#: git-gui.sh:2953 git-gui.sh:3104 lib/console.tcl:73
msgid "Copy All"
msgstr "Összes másolása"
-#: git-gui.sh:2483 lib/blame.tcl:107
+#: git-gui.sh:2977 lib/blame.tcl:104
msgid "File:"
msgstr "Fájl:"
-#: git-gui.sh:2589
-msgid "Apply/Reverse Hunk"
-msgstr "Hunk alkalmazása/visszaállítása"
-
-#: git-gui.sh:2595
-msgid "Show Less Context"
-msgstr "Kevesebb környezet mutatása"
-
-#: git-gui.sh:2602
-msgid "Show More Context"
-msgstr "Több környezet mutatása"
-
-#: git-gui.sh:2610
+#: git-gui.sh:3092
msgid "Refresh"
msgstr "Frissítés"
-#: git-gui.sh:2631
+#: git-gui.sh:3113
msgid "Decrease Font Size"
msgstr "Font méret csökkentése"
-#: git-gui.sh:2635
+#: git-gui.sh:3117
msgid "Increase Font Size"
msgstr "Fönt méret növelése"
-#: git-gui.sh:2646
+#: git-gui.sh:3125 lib/blame.tcl:281
+msgid "Encoding"
+msgstr "Kódolás"
+
+#: git-gui.sh:3136
+msgid "Apply/Reverse Hunk"
+msgstr "Hunk alkalmazása/visszaállítása"
+
+#: git-gui.sh:3141
+msgid "Apply/Reverse Line"
+msgstr "Sor alkalmazása/visszaállítása"
+
+#: git-gui.sh:3151
+msgid "Run Merge Tool"
+msgstr "Merge eszköz futtatása"
+
+#: git-gui.sh:3156
+msgid "Use Remote Version"
+msgstr "Távoli verzió használata"
+
+#: git-gui.sh:3160
+msgid "Use Local Version"
+msgstr "Helyi verzió használata"
+
+#: git-gui.sh:3164
+msgid "Revert To Base"
+msgstr "Visszaállítás az alaphoz"
+
+#: git-gui.sh:3183
msgid "Unstage Hunk From Commit"
msgstr "Hunk törlése commitból"
-#: git-gui.sh:2648
+#: git-gui.sh:3184
+msgid "Unstage Line From Commit"
+msgstr "A sor kiválasztásának törlése"
+
+#: git-gui.sh:3186
msgid "Stage Hunk For Commit"
msgstr "Hunk kiválasztása commitba"
-#: git-gui.sh:2667
+#: git-gui.sh:3187
+msgid "Stage Line For Commit"
+msgstr "Sor kiválasztása commitba"
+
+#: git-gui.sh:3210
msgid "Initializing..."
msgstr "Inicializálás..."
-#: git-gui.sh:2762
+#: git-gui.sh:3315
#, tcl-format
msgid ""
"Possible environment issues exist.\n"
@@ -450,7 +516,7 @@ msgstr ""
"indított folyamatok által:\n"
"\n"
-#: git-gui.sh:2792
+#: git-gui.sh:3345
msgid ""
"\n"
"This is due to a known issue with the\n"
@@ -460,7 +526,7 @@ msgstr ""
"Ez a Cygwin által terjesztett Tcl binárisban\n"
"lévő ismert hiba miatt van."
-#: git-gui.sh:2797
+#: git-gui.sh:3350
#, tcl-format
msgid ""
"\n"
@@ -481,64 +547,108 @@ msgstr ""
msgid "git-gui - a graphical user interface for Git."
msgstr "git-gui - egy grafikus felület a Githez."
-#: lib/blame.tcl:77
+#: lib/blame.tcl:72
msgid "File Viewer"
msgstr "Fájl néző"
-#: lib/blame.tcl:81
+#: lib/blame.tcl:78
msgid "Commit:"
msgstr "Commit:"
-#: lib/blame.tcl:264
+#: lib/blame.tcl:271
msgid "Copy Commit"
msgstr "Commit másolása"
-#: lib/blame.tcl:384
+#: lib/blame.tcl:275
+msgid "Find Text..."
+msgstr "Szöveg keresése..."
+
+#: lib/blame.tcl:284
+msgid "Do Full Copy Detection"
+msgstr "Teljes másolat-érzékelés bekapcsolása"
+
+#: lib/blame.tcl:288
+msgid "Show History Context"
+msgstr "Történeti környezet mutatása"
+
+#: lib/blame.tcl:291
+msgid "Blame Parent Commit"
+msgstr "Szülő commit vizsgálata"
+
+#: lib/blame.tcl:450
#, tcl-format
msgid "Reading %s..."
msgstr "A(z) %s olvasása..."
-#: lib/blame.tcl:488
+#: lib/blame.tcl:557
msgid "Loading copy/move tracking annotations..."
msgstr "A másolást/átnevezést követő annotációk betöltése..."
-#: lib/blame.tcl:508
+#: lib/blame.tcl:577
msgid "lines annotated"
msgstr "sor annotálva"
-#: lib/blame.tcl:689
+#: lib/blame.tcl:769
msgid "Loading original location annotations..."
msgstr "Az eredeti hely annotációk betöltése..."
-#: lib/blame.tcl:692
+#: lib/blame.tcl:772
msgid "Annotation complete."
msgstr "Az annotáció kész."
-#: lib/blame.tcl:746
+#: lib/blame.tcl:802
+msgid "Busy"
+msgstr "Elfoglalt"
+
+#: lib/blame.tcl:803
+msgid "Annotation process is already running."
+msgstr "Az annotációs folyamat már fut."
+
+#: lib/blame.tcl:842
+msgid "Running thorough copy detection..."
+msgstr "Futtatás másolás-érzékelésen keresztül..."
+
+#: lib/blame.tcl:910
msgid "Loading annotation..."
msgstr "Az annotáció betöltése..."
-#: lib/blame.tcl:802
+#: lib/blame.tcl:963
msgid "Author:"
msgstr "Szerző:"
-#: lib/blame.tcl:806
+#: lib/blame.tcl:967
msgid "Committer:"
msgstr "Commiter:"
-#: lib/blame.tcl:811
+#: lib/blame.tcl:972
msgid "Original File:"
msgstr "Eredeti fájl:"
-#: lib/blame.tcl:925
+#: lib/blame.tcl:1020
+msgid "Cannot find HEAD commit:"
+msgstr "Nem található a HEAD commit:"
+
+#: lib/blame.tcl:1075
+msgid "Cannot find parent commit:"
+msgstr "Nem található a szülő commit:"
+
+#: lib/blame.tcl:1090
+msgid "Unable to display parent"
+msgstr "Nem lehet megjeleníteni a szülőt"
+
+#: lib/blame.tcl:1091 lib/diff.tcl:297
+msgid "Error loading diff:"
+msgstr "Hiba a diff betöltése közben:"
+
+#: lib/blame.tcl:1231
msgid "Originally By:"
msgstr "Eredeti szerző:"
-#: lib/blame.tcl:931
+#: lib/blame.tcl:1237
msgid "In File:"
msgstr "Ebben a fájlban:"
-#: lib/blame.tcl:936
+#: lib/blame.tcl:1242
msgid "Copied Or Moved Here By:"
msgstr "Ide másolta vagy helyezte:"
@@ -552,16 +662,18 @@ msgstr "Checkout"
#: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35
#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:282
-#: lib/checkout_op.tcl:522 lib/choose_font.tcl:43 lib/merge.tcl:171
-#: lib/option.tcl:103 lib/remote_branch_delete.tcl:42 lib/transport.tcl:97
+#: lib/checkout_op.tcl:544 lib/choose_font.tcl:43 lib/merge.tcl:172
+#: lib/option.tcl:125 lib/remote_add.tcl:32 lib/remote_branch_delete.tcl:42
+#: lib/tools_dlg.tcl:40 lib/tools_dlg.tcl:204 lib/tools_dlg.tcl:352
+#: lib/transport.tcl:108
msgid "Cancel"
msgstr "Mégsem"
-#: lib/branch_checkout.tcl:32 lib/browser.tcl:287
+#: lib/branch_checkout.tcl:32 lib/browser.tcl:287 lib/tools_dlg.tcl:328
msgid "Revision"
msgstr "Revízió"
-#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:242
+#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:280
msgid "Options"
msgstr "Opciók"
@@ -581,7 +693,7 @@ msgstr "Branch létrehozása"
msgid "Create New Branch"
msgstr "Új branch létrehozása"
-#: lib/branch_create.tcl:31 lib/choose_repository.tcl:371
+#: lib/branch_create.tcl:31 lib/choose_repository.tcl:377
msgid "Create"
msgstr "Létrehozás"
@@ -589,7 +701,7 @@ msgstr "Létrehozás"
msgid "Branch Name"
msgstr "Branch neve"
-#: lib/branch_create.tcl:43
+#: lib/branch_create.tcl:43 lib/remote_add.tcl:39 lib/tools_dlg.tcl:50
msgid "Name:"
msgstr "Név:"
@@ -613,7 +725,7 @@ msgstr "Nem"
msgid "Fast Forward Only"
msgstr "Csak fast forward"
-#: lib/branch_create.tcl:85 lib/checkout_op.tcl:514
+#: lib/branch_create.tcl:85 lib/checkout_op.tcl:536
msgid "Reset"
msgstr "Visszaállítás"
@@ -703,7 +815,7 @@ msgstr "Új név:"
msgid "Please select a branch to rename."
msgstr "Válasszunk ki egy átnevezendő branchet."
-#: lib/branch_rename.tcl:96 lib/checkout_op.tcl:179
+#: lib/branch_rename.tcl:96 lib/checkout_op.tcl:201
#, tcl-format
msgid "Branch '%s' already exists."
msgstr "A(z) '%s' branch már létezik."
@@ -734,32 +846,39 @@ msgstr "[Fel a szülőhöz]"
msgid "Browse Branch Files"
msgstr "A branch fájljainak böngészése"
-#: lib/browser.tcl:278 lib/choose_repository.tcl:387
-#: lib/choose_repository.tcl:474 lib/choose_repository.tcl:484
-#: lib/choose_repository.tcl:987
+#: lib/browser.tcl:278 lib/choose_repository.tcl:394
+#: lib/choose_repository.tcl:480 lib/choose_repository.tcl:491
+#: lib/choose_repository.tcl:995
msgid "Browse"
msgstr "Böngészés"
-#: lib/checkout_op.tcl:79
+#: lib/checkout_op.tcl:84
#, tcl-format
msgid "Fetching %s from %s"
msgstr "A(z) %s letöltése innen: %s"
-#: lib/checkout_op.tcl:127
+#: lib/checkout_op.tcl:132
#, tcl-format
msgid "fatal: Cannot resolve %s"
msgstr "végzetes: Nem lehet feloldani a következőt: %s"
-#: lib/checkout_op.tcl:140 lib/console.tcl:81 lib/database.tcl:31
+#: lib/checkout_op.tcl:145 lib/console.tcl:81 lib/database.tcl:31
+#: lib/sshkey.tcl:53
msgid "Close"
msgstr "Bezárás"
-#: lib/checkout_op.tcl:169
+#: lib/checkout_op.tcl:174
#, tcl-format
msgid "Branch '%s' does not exist."
msgstr "A(z) '%s' branch nem létezik."
-#: lib/checkout_op.tcl:206
+#: lib/checkout_op.tcl:193
+#, tcl-format
+msgid "Failed to configure simplified git-pull for '%s'."
+msgstr ""
+"Nem sikerült beállítani az egyszerűsített git-pull-t a(z) '%s' számára."
+
+#: lib/checkout_op.tcl:228
#, tcl-format
msgid ""
"Branch '%s' already exists.\n"
@@ -772,21 +891,21 @@ msgstr ""
"Nem lehet fast-forwardolni a következőhöz: %s.\n"
"Egy merge szükséges."
-#: lib/checkout_op.tcl:220
+#: lib/checkout_op.tcl:242
#, tcl-format
msgid "Merge strategy '%s' not supported."
msgstr "A(z) '%s' merge strategy nem támogatott."
-#: lib/checkout_op.tcl:239
+#: lib/checkout_op.tcl:261
#, tcl-format
msgid "Failed to update '%s'."
msgstr "Nem sikerült frissíteni a következőt: '%s'."
-#: lib/checkout_op.tcl:251
+#: lib/checkout_op.tcl:273
msgid "Staging area (index) is already locked."
msgstr "A kiválasztási terület (index) már zárolva van."
-#: lib/checkout_op.tcl:266
+#: lib/checkout_op.tcl:288
msgid ""
"Last scanned state does not match repository state.\n"
"\n"
@@ -803,30 +922,30 @@ msgstr ""
"\n"
"Az újrakeresés most automatikusan el fog indulni.\n"
-#: lib/checkout_op.tcl:322
+#: lib/checkout_op.tcl:344
#, tcl-format
msgid "Updating working directory to '%s'..."
msgstr "A munkkönyvtár frissiítése a következőre: '%s'..."
-#: lib/checkout_op.tcl:323
+#: lib/checkout_op.tcl:345
msgid "files checked out"
msgstr "fájl frissítve"
-#: lib/checkout_op.tcl:353
+#: lib/checkout_op.tcl:375
#, tcl-format
msgid "Aborted checkout of '%s' (file level merging is required)."
msgstr "A(z) '%s' checkoutja megszakítva (fájlszintű merge-ölés szükséges)."
-#: lib/checkout_op.tcl:354
+#: lib/checkout_op.tcl:376
msgid "File level merge required."
msgstr "Fájlszintű merge-ölés szükséges."
-#: lib/checkout_op.tcl:358
+#: lib/checkout_op.tcl:380
#, tcl-format
msgid "Staying on branch '%s'."
msgstr "Jelenleg a(z) '%s' branchen."
-#: lib/checkout_op.tcl:429
+#: lib/checkout_op.tcl:451
msgid ""
"You are no longer on a local branch.\n"
"\n"
@@ -838,31 +957,31 @@ msgstr ""
"Ha egy branchen szeretnénk lenni, hozzunk létre egyet az 'Ez a leválasztott "
"checkout'-ból."
-#: lib/checkout_op.tcl:446 lib/checkout_op.tcl:450
+#: lib/checkout_op.tcl:468 lib/checkout_op.tcl:472
#, tcl-format
msgid "Checked out '%s'."
msgstr "'%s' kifejtve."
-#: lib/checkout_op.tcl:478
+#: lib/checkout_op.tcl:500
#, tcl-format
msgid "Resetting '%s' to '%s' will lose the following commits:"
msgstr ""
"A(z) '%s' -> '%s' visszaállítás a következő commitok elvesztését jelenti:"
-#: lib/checkout_op.tcl:500
+#: lib/checkout_op.tcl:522
msgid "Recovering lost commits may not be easy."
msgstr "Az elveszett commitok helyreállítása nem biztos, hogy egyszerű."
-#: lib/checkout_op.tcl:505
+#: lib/checkout_op.tcl:527
#, tcl-format
msgid "Reset '%s'?"
msgstr "Visszaállítjuk a következőt: '%s'?"
-#: lib/checkout_op.tcl:510 lib/merge.tcl:163
+#: lib/checkout_op.tcl:532 lib/merge.tcl:164 lib/tools_dlg.tcl:343
msgid "Visualize"
msgstr "Vizualizálás"
-#: lib/checkout_op.tcl:578
+#: lib/checkout_op.tcl:600
#, tcl-format
msgid ""
"Failed to set current branch.\n"
@@ -907,223 +1026,227 @@ msgstr ""
msgid "Git Gui"
msgstr "Git Gui"
-#: lib/choose_repository.tcl:81 lib/choose_repository.tcl:376
+#: lib/choose_repository.tcl:87 lib/choose_repository.tcl:382
msgid "Create New Repository"
msgstr "Új repó létrehozása"
-#: lib/choose_repository.tcl:87
+#: lib/choose_repository.tcl:93
msgid "New..."
msgstr "Új..."
-#: lib/choose_repository.tcl:94 lib/choose_repository.tcl:460
+#: lib/choose_repository.tcl:100 lib/choose_repository.tcl:465
msgid "Clone Existing Repository"
msgstr "Létező repó másolása"
-#: lib/choose_repository.tcl:100
+#: lib/choose_repository.tcl:106
msgid "Clone..."
msgstr "Másolás..."
-#: lib/choose_repository.tcl:107 lib/choose_repository.tcl:976
+#: lib/choose_repository.tcl:113 lib/choose_repository.tcl:983
msgid "Open Existing Repository"
msgstr "Létező könyvtár megnyitása"
-#: lib/choose_repository.tcl:113
+#: lib/choose_repository.tcl:119
msgid "Open..."
msgstr "Meggyitás..."
-#: lib/choose_repository.tcl:126
+#: lib/choose_repository.tcl:132
msgid "Recent Repositories"
msgstr "Legutóbbi repók"
-#: lib/choose_repository.tcl:132
+#: lib/choose_repository.tcl:138
msgid "Open Recent Repository:"
msgstr "Legutóbbi repók megnyitása:"
-#: lib/choose_repository.tcl:296 lib/choose_repository.tcl:303
-#: lib/choose_repository.tcl:310
+#: lib/choose_repository.tcl:302 lib/choose_repository.tcl:309
+#: lib/choose_repository.tcl:316
#, tcl-format
msgid "Failed to create repository %s:"
msgstr "Nem sikerült letrehozni a(z) %s repót:"
-#: lib/choose_repository.tcl:381 lib/choose_repository.tcl:478
+#: lib/choose_repository.tcl:387
msgid "Directory:"
msgstr "Könyvtár:"
-#: lib/choose_repository.tcl:412 lib/choose_repository.tcl:537
-#: lib/choose_repository.tcl:1011
+#: lib/choose_repository.tcl:417 lib/choose_repository.tcl:544
+#: lib/choose_repository.tcl:1017
msgid "Git Repository"
msgstr "Git repó"
-#: lib/choose_repository.tcl:437
+#: lib/choose_repository.tcl:442
#, tcl-format
msgid "Directory %s already exists."
msgstr "A(z) '%s' könyvtár már létezik."
-#: lib/choose_repository.tcl:441
+#: lib/choose_repository.tcl:446
#, tcl-format
msgid "File %s already exists."
msgstr "A(z) '%s' fájl már létezik."
-#: lib/choose_repository.tcl:455
+#: lib/choose_repository.tcl:460
msgid "Clone"
msgstr "Bezárás"
-#: lib/choose_repository.tcl:468
-msgid "URL:"
-msgstr "URL:"
+#: lib/choose_repository.tcl:473
+msgid "Source Location:"
+msgstr "Forrás helye:"
+
+#: lib/choose_repository.tcl:484
+msgid "Target Directory:"
+msgstr "Cél könyvtár:"
-#: lib/choose_repository.tcl:489
+#: lib/choose_repository.tcl:496
msgid "Clone Type:"
msgstr "Másolás típusa:"
-#: lib/choose_repository.tcl:495
+#: lib/choose_repository.tcl:502
msgid "Standard (Fast, Semi-Redundant, Hardlinks)"
msgstr "Ãltalános (Gyors, félig-redundáns, hardlinkek)"
-#: lib/choose_repository.tcl:501
+#: lib/choose_repository.tcl:508
msgid "Full Copy (Slower, Redundant Backup)"
msgstr "Teljes másolás (Lassabb, redundáns biztonsági mentés)"
-#: lib/choose_repository.tcl:507
+#: lib/choose_repository.tcl:514
msgid "Shared (Fastest, Not Recommended, No Backup)"
msgstr "Megosztott (Leggyorsabb, nem ajánlott, nincs mentés)"
-#: lib/choose_repository.tcl:543 lib/choose_repository.tcl:590
-#: lib/choose_repository.tcl:736 lib/choose_repository.tcl:806
-#: lib/choose_repository.tcl:1017 lib/choose_repository.tcl:1025
+#: lib/choose_repository.tcl:550 lib/choose_repository.tcl:597
+#: lib/choose_repository.tcl:743 lib/choose_repository.tcl:813
+#: lib/choose_repository.tcl:1023 lib/choose_repository.tcl:1031
#, tcl-format
msgid "Not a Git repository: %s"
msgstr "Nem Git repó: %s"
-#: lib/choose_repository.tcl:579
+#: lib/choose_repository.tcl:586
msgid "Standard only available for local repository."
msgstr "A standard csak helyi repókra érhető el."
-#: lib/choose_repository.tcl:583
+#: lib/choose_repository.tcl:590
msgid "Shared only available for local repository."
msgstr "A megosztott csak helyi repókra érhető el."
-#: lib/choose_repository.tcl:604
+#: lib/choose_repository.tcl:611
#, tcl-format
msgid "Location %s already exists."
msgstr "A(z) '%s' hely már létezik."
-#: lib/choose_repository.tcl:615
+#: lib/choose_repository.tcl:622
msgid "Failed to configure origin"
msgstr "Nem sikerült beállítani az origint"
-#: lib/choose_repository.tcl:627
+#: lib/choose_repository.tcl:634
msgid "Counting objects"
msgstr "Objektumok számolása"
-#: lib/choose_repository.tcl:628
+#: lib/choose_repository.tcl:635
msgid "buckets"
msgstr "vödrök"
-#: lib/choose_repository.tcl:652
+#: lib/choose_repository.tcl:659
#, tcl-format
msgid "Unable to copy objects/info/alternates: %s"
msgstr "Nem sikerült másolni az objects/info/alternates-t: %s"
-#: lib/choose_repository.tcl:688
+#: lib/choose_repository.tcl:695
#, tcl-format
msgid "Nothing to clone from %s."
msgstr "Semmi másolni való nincs innen: %s"
-#: lib/choose_repository.tcl:690 lib/choose_repository.tcl:904
-#: lib/choose_repository.tcl:916
+#: lib/choose_repository.tcl:697 lib/choose_repository.tcl:911
+#: lib/choose_repository.tcl:923
msgid "The 'master' branch has not been initialized."
msgstr "A 'master' branch nincs inicializálva."
-#: lib/choose_repository.tcl:703
+#: lib/choose_repository.tcl:710
msgid "Hardlinks are unavailable. Falling back to copying."
msgstr "Nem érhetőek el hardlinkek. Másolás használata."
-#: lib/choose_repository.tcl:715
+#: lib/choose_repository.tcl:722
#, tcl-format
msgid "Cloning from %s"
msgstr "Másolás innen: %s"
-#: lib/choose_repository.tcl:746
+#: lib/choose_repository.tcl:753
msgid "Copying objects"
msgstr "Objektumok másolása"
-#: lib/choose_repository.tcl:747
+#: lib/choose_repository.tcl:754
msgid "KiB"
msgstr "KiB"
-#: lib/choose_repository.tcl:771
+#: lib/choose_repository.tcl:778
#, tcl-format
msgid "Unable to copy object: %s"
msgstr "Nem sikerült másolni az objektumot: %s"
-#: lib/choose_repository.tcl:781
+#: lib/choose_repository.tcl:788
msgid "Linking objects"
msgstr "Objektumok összefűzése"
-#: lib/choose_repository.tcl:782
+#: lib/choose_repository.tcl:789
msgid "objects"
msgstr "objektum"
-#: lib/choose_repository.tcl:790
+#: lib/choose_repository.tcl:797
#, tcl-format
msgid "Unable to hardlink object: %s"
msgstr "Nem sikerült hardlinkelni az objektumot: %s"
-#: lib/choose_repository.tcl:845
+#: lib/choose_repository.tcl:852
msgid "Cannot fetch branches and objects. See console output for details."
msgstr ""
"Nem sikerült letölteni a branch-eket és az objektumokat. Bővebben a "
"konzolos kimenetben."
-#: lib/choose_repository.tcl:856
+#: lib/choose_repository.tcl:863
msgid "Cannot fetch tags. See console output for details."
msgstr "Nem sikerült letölteni a tageket. Bővebben a konzolos kimenetben."
-#: lib/choose_repository.tcl:880
+#: lib/choose_repository.tcl:887
msgid "Cannot determine HEAD. See console output for details."
msgstr "Nem sikerült megállapítani a HEAD-et. Bővebben a konzolos kimenetben."
-#: lib/choose_repository.tcl:889
+#: lib/choose_repository.tcl:896
#, tcl-format
msgid "Unable to cleanup %s"
msgstr "Nem sikerült tiszítani: %s."
-#: lib/choose_repository.tcl:895
+#: lib/choose_repository.tcl:902
msgid "Clone failed."
msgstr "A másolás nem sikerült."
-#: lib/choose_repository.tcl:902
+#: lib/choose_repository.tcl:909
msgid "No default branch obtained."
msgstr "Nincs alapértelmezett branch."
-#: lib/choose_repository.tcl:913
+#: lib/choose_repository.tcl:920
#, tcl-format
msgid "Cannot resolve %s as a commit."
msgstr "Nem sikerült felöldani a(z) %s objektumot commitként."
-#: lib/choose_repository.tcl:925
+#: lib/choose_repository.tcl:932
msgid "Creating working directory"
msgstr "Munkakönyvtár létrehozása"
-#: lib/choose_repository.tcl:926 lib/index.tcl:65 lib/index.tcl:127
-#: lib/index.tcl:193
+#: lib/choose_repository.tcl:933 lib/index.tcl:65 lib/index.tcl:128
+#: lib/index.tcl:196
msgid "files"
msgstr "fájl"
-#: lib/choose_repository.tcl:955
+#: lib/choose_repository.tcl:962
msgid "Initial file checkout failed."
msgstr "A kezdeti fájl-kibontás sikertelen."
-#: lib/choose_repository.tcl:971
+#: lib/choose_repository.tcl:978
msgid "Open"
msgstr "Megnyitás"
-#: lib/choose_repository.tcl:981
+#: lib/choose_repository.tcl:988
msgid "Repository:"
msgstr "Repó:"
-#: lib/choose_repository.tcl:1031
+#: lib/choose_repository.tcl:1037
#, tcl-format
msgid "Failed to open repository %s:"
msgstr "Nem sikerült megnyitni a(z) %s repót:"
@@ -1194,19 +1317,19 @@ msgstr ""
"A jelenlegi merge még nem teljesen fejeződött be. Csak akkor javíthat egy "
"előbbi commitot, hogyha megszakítja a jelenlegi merge folyamatot.\n"
-#: lib/commit.tcl:49
+#: lib/commit.tcl:48
msgid "Error loading commit data for amend:"
msgstr "Hiba a javítandó commit adat betöltése közben:"
-#: lib/commit.tcl:76
+#: lib/commit.tcl:75
msgid "Unable to obtain your identity:"
msgstr "Nem sikerült megállapítani az azonosítót:"
-#: lib/commit.tcl:81
+#: lib/commit.tcl:80
msgid "Invalid GIT_COMMITTER_IDENT:"
msgstr "Érvénytelen GIT_COMMITTER_IDENT:"
-#: lib/commit.tcl:133
+#: lib/commit.tcl:132
msgid ""
"Last scanned state does not match repository state.\n"
"\n"
@@ -1223,7 +1346,7 @@ msgstr ""
"\n"
"Az újrakeresés most automatikusan el fog indulni.\n"
-#: lib/commit.tcl:154
+#: lib/commit.tcl:155
#, tcl-format
msgid ""
"Unmerged files cannot be committed.\n"
@@ -1236,7 +1359,7 @@ msgstr ""
"A(z) %s fájlban ütközések vannak. Egyszer azokat ki kell javítani, majd "
"hozzá ki kell választani a fájlt mielőtt commitolni lehetne.\n"
-#: lib/commit.tcl:162
+#: lib/commit.tcl:163
#, tcl-format
msgid ""
"Unknown file state %s detected.\n"
@@ -1247,7 +1370,7 @@ msgstr ""
"\n"
"A(z) %s fájlt nem tudja ez a program commitolni.\n"
-#: lib/commit.tcl:170
+#: lib/commit.tcl:171
msgid ""
"No changes to commit.\n"
"\n"
@@ -1257,7 +1380,7 @@ msgstr ""
"\n"
"Legalább egy fájl ki kell választani, hogy commitolni lehessen.\n"
-#: lib/commit.tcl:183
+#: lib/commit.tcl:186
msgid ""
"Please supply a commit message.\n"
"\n"
@@ -1275,45 +1398,45 @@ msgstr ""
"- Második sor: Üres\n"
"- A többi sor: Leírja, hogy miért jó ez a változtatás.\n"
-#: lib/commit.tcl:207
+#: lib/commit.tcl:210
#, tcl-format
msgid "warning: Tcl does not support encoding '%s'."
msgstr "figyelmeztetés: a Tcl nem támogatja a(z) '%s' kódolást."
-#: lib/commit.tcl:221
+#: lib/commit.tcl:226
msgid "Calling pre-commit hook..."
msgstr "A pre-commit hurok meghívása..."
-#: lib/commit.tcl:236
+#: lib/commit.tcl:241
msgid "Commit declined by pre-commit hook."
msgstr "A commitot megakadályozta a pre-commit hurok. "
-#: lib/commit.tcl:259
+#: lib/commit.tcl:264
msgid "Calling commit-msg hook..."
msgstr "A commit-msg hurok meghívása..."
-#: lib/commit.tcl:274
+#: lib/commit.tcl:279
msgid "Commit declined by commit-msg hook."
msgstr "A commiot megakadályozta a commit-msg hurok."
-#: lib/commit.tcl:287
+#: lib/commit.tcl:292
msgid "Committing changes..."
msgstr "A változtatások commitolása..."
-#: lib/commit.tcl:303
+#: lib/commit.tcl:308
msgid "write-tree failed:"
msgstr "a write-tree sikertelen:"
-#: lib/commit.tcl:304 lib/commit.tcl:348 lib/commit.tcl:368
+#: lib/commit.tcl:309 lib/commit.tcl:353 lib/commit.tcl:373
msgid "Commit failed."
msgstr "A commit nem sikerült."
-#: lib/commit.tcl:321
+#: lib/commit.tcl:326
#, tcl-format
msgid "Commit %s appears to be corrupt"
msgstr "A(z) %s commit sérültnek tűnik"
-#: lib/commit.tcl:326
+#: lib/commit.tcl:331
msgid ""
"No changes to commit.\n"
"\n"
@@ -1327,19 +1450,19 @@ msgstr ""
"\n"
"Az újrakeresés most automatikusan el fog indulni.\n"
-#: lib/commit.tcl:333
+#: lib/commit.tcl:338
msgid "No changes to commit."
msgstr "Nincs commitolandó változtatás."
-#: lib/commit.tcl:347
+#: lib/commit.tcl:352
msgid "commit-tree failed:"
msgstr "a commit-tree sikertelen:"
-#: lib/commit.tcl:367
+#: lib/commit.tcl:372
msgid "update-ref failed:"
msgstr "az update-ref sikertelen:"
-#: lib/commit.tcl:454
+#: lib/commit.tcl:460
#, tcl-format
msgid "Created commit %s: %s"
msgstr "Létrejött a %s commit: %s"
@@ -1414,7 +1537,7 @@ msgstr ""
msgid "Invalid date from Git: %s"
msgstr "Érvénytelen dátum a Git-től: %s"
-#: lib/diff.tcl:42
+#: lib/diff.tcl:59
#, tcl-format
msgid ""
"No differences detected.\n"
@@ -1436,40 +1559,101 @@ msgstr ""
"\n"
"Egy újrakeresés fog indulni a hasonló állapotú fájlok megtalálása érdekében."
-#: lib/diff.tcl:81
+#: lib/diff.tcl:99
#, tcl-format
msgid "Loading diff of %s..."
msgstr "A(z) %s diff-jének betöltése..."
-#: lib/diff.tcl:114 lib/diff.tcl:184
+#: lib/diff.tcl:120
+msgid ""
+"LOCAL: deleted\n"
+"REMOTE:\n"
+msgstr ""
+"HELYI: törölve\n"
+"TÃVOLI:\n"
+
+#: lib/diff.tcl:125
+msgid ""
+"REMOTE: deleted\n"
+"LOCAL:\n"
+msgstr ""
+"TÃVOLI: törölve\n"
+"HELYI:\n"
+
+#: lib/diff.tcl:132
+msgid "LOCAL:\n"
+msgstr "HELYI:\n"
+
+#: lib/diff.tcl:135
+msgid "REMOTE:\n"
+msgstr "TÃVOLI:\n"
+
+#: lib/diff.tcl:197 lib/diff.tcl:296
#, tcl-format
msgid "Unable to display %s"
msgstr "Nem lehet megjeleníteni a következőt: %s"
-#: lib/diff.tcl:115
+#: lib/diff.tcl:198
msgid "Error loading file:"
msgstr "Hiba a fájl betöltése közben:"
-#: lib/diff.tcl:122
+#: lib/diff.tcl:205
msgid "Git Repository (subproject)"
msgstr "Git repó (alprojekt)"
-#: lib/diff.tcl:134
+#: lib/diff.tcl:217
msgid "* Binary file (not showing content)."
msgstr "* Bináris fájl (tartalom elrejtése)."
-#: lib/diff.tcl:185
-msgid "Error loading diff:"
-msgstr "Hiba a diff betöltése közben:"
+#: lib/diff.tcl:222
+#, tcl-format
+msgid ""
+"* Untracked file is %d bytes.\n"
+"* Showing only first %d bytes.\n"
+msgstr ""
+"* Nem követett fájl %d bájttal.\n"
+"* Csak az első %d bájt mutatása.\n"
+
+#: lib/diff.tcl:228
+#, tcl-format
+msgid ""
+"\n"
+"* Untracked file clipped here by %s.\n"
+"* To see the entire file, use an external editor.\n"
+msgstr ""
+"\n"
+"* Nem követett fájlt levágta a(z) %s.\n"
+"* A teljes tartalom megjelenítéséhez használjunk külső szövegszerkesztőt.\n"
-#: lib/diff.tcl:303
+#: lib/diff.tcl:436
msgid "Failed to unstage selected hunk."
msgstr "Nem visszavonni a hunk kiválasztását."
-#: lib/diff.tcl:310
+#: lib/diff.tcl:443
msgid "Failed to stage selected hunk."
msgstr "Nem sikerült kiválasztani a hunkot."
+#: lib/diff.tcl:509
+msgid "Failed to unstage selected line."
+msgstr "Nem sikerült visszavonni a sor kiválasztását."
+
+#: lib/diff.tcl:517
+msgid "Failed to stage selected line."
+msgstr "Nem sikerült kiválasztani a sort."
+
+#: lib/encoding.tcl:443
+msgid "Default"
+msgstr "Alapértelmezés"
+
+#: lib/encoding.tcl:448
+#, tcl-format
+msgid "System (%s)"
+msgstr "Rendszer (%s)"
+
+#: lib/encoding.tcl:459 lib/encoding.tcl:465
+msgid "Other"
+msgstr "Más"
+
#: lib/error.tcl:20 lib/error.tcl:114
msgid "error"
msgstr "hiba"
@@ -1506,40 +1690,49 @@ msgstr "Folytatás"
msgid "Unlock Index"
msgstr "Index zárolásának feloldása"
-#: lib/index.tcl:282
+#: lib/index.tcl:287
#, tcl-format
msgid "Unstaging %s from commit"
msgstr "A(z) %s commitba való kiválasztásának visszavonása"
-#: lib/index.tcl:313
+#: lib/index.tcl:326
msgid "Ready to commit."
msgstr "Commitolásra kész."
-#: lib/index.tcl:326
+#: lib/index.tcl:339
#, tcl-format
msgid "Adding %s"
msgstr "A(z) %s hozzáadása..."
-#: lib/index.tcl:381
+#: lib/index.tcl:396
#, tcl-format
msgid "Revert changes in file %s?"
msgstr "Visszaállítja a változtatásokat a(z) %s fájlban?"
-#: lib/index.tcl:383
+#: lib/index.tcl:398
#, tcl-format
msgid "Revert changes in these %i files?"
msgstr "Visszaállítja a változtatásokat ebben e %i fájlban?"
-#: lib/index.tcl:391
+#: lib/index.tcl:406
msgid "Any unstaged changes will be permanently lost by the revert."
msgstr ""
"Minden nem kiválasztott változtatás el fog veszni ezáltal a visszaállítás "
"által."
-#: lib/index.tcl:394
+#: lib/index.tcl:409
msgid "Do Nothing"
msgstr "Ne csináljunk semmit"
+#: lib/index.tcl:427
+msgid "Reverting selected files"
+msgstr "A kiválasztott fájlok visszaállítása"
+
+#: lib/index.tcl:431
+#, tcl-format
+msgid "Reverting %s"
+msgstr "%s visszaállítása"
+
#: lib/merge.tcl:13
msgid ""
"Cannot merge while amending.\n"
@@ -1568,7 +1761,7 @@ msgstr ""
"\n"
"Az újrakeresés most automatikusan el fog indulni.\n"
-#: lib/merge.tcl:44
+#: lib/merge.tcl:45
#, tcl-format
msgid ""
"You are in the middle of a conflicted merge.\n"
@@ -1585,7 +1778,7 @@ msgstr ""
"Fel kell oldanunk őket, kiválasztani a fájlt, és commitolni hogy befejezzük "
"a jelenlegi merge-t. Csak ezután kezdhetünk el egy újabbat.\n"
-#: lib/merge.tcl:54
+#: lib/merge.tcl:55
#, tcl-format
msgid ""
"You are in the middle of a change.\n"
@@ -1602,34 +1795,34 @@ msgstr ""
"Először be kell fejeznünk a jelenlegi commitot, hogy elkezdhessünk egy merge-"
"t. Ez segíteni fog, hogy félbeszakíthassunk egy merge-t.\n"
-#: lib/merge.tcl:106
+#: lib/merge.tcl:107
#, tcl-format
msgid "%s of %s"
msgstr "%s / %s"
-#: lib/merge.tcl:119
+#: lib/merge.tcl:120
#, tcl-format
msgid "Merging %s and %s..."
msgstr "A(z) %s és a(z) %s merge-ölése..."
-#: lib/merge.tcl:130
+#: lib/merge.tcl:131
msgid "Merge completed successfully."
msgstr "A merge sikeresen befejeződött."
-#: lib/merge.tcl:132
+#: lib/merge.tcl:133
msgid "Merge failed. Conflict resolution is required."
msgstr "A merge sikertelen. Fel kell oldanunk az ütközéseket."
-#: lib/merge.tcl:157
+#: lib/merge.tcl:158
#, tcl-format
msgid "Merge Into %s"
msgstr "Merge-ölés a következőbe: %s"
-#: lib/merge.tcl:176
+#: lib/merge.tcl:177
msgid "Revision To Merge"
msgstr "Merge-ölni szándékozott revízió"
-#: lib/merge.tcl:211
+#: lib/merge.tcl:212
msgid ""
"Cannot abort while amending.\n"
"\n"
@@ -1639,7 +1832,7 @@ msgstr ""
"\n"
"Be kell fejeznünk ennek a commitnak a javítását.\n"
-#: lib/merge.tcl:221
+#: lib/merge.tcl:222
msgid ""
"Abort merge?\n"
"\n"
@@ -1654,7 +1847,7 @@ msgstr ""
"\n"
"Folytatjuk a jelenlegi merge megszakítását?"
-#: lib/merge.tcl:227
+#: lib/merge.tcl:228
msgid ""
"Reset changes?\n"
"\n"
@@ -1669,123 +1862,338 @@ msgstr ""
"\n"
"Folytatjuk a jelenlegi módosítások visszavonását?"
-#: lib/merge.tcl:238
+#: lib/merge.tcl:239
msgid "Aborting"
msgstr "Félbeszakítás"
-#: lib/merge.tcl:238
+#: lib/merge.tcl:239
msgid "files reset"
msgstr "fájl visszaállítva"
-#: lib/merge.tcl:265
+#: lib/merge.tcl:267
msgid "Abort failed."
msgstr "A félbeszakítás nem sikerült."
-#: lib/merge.tcl:267
+#: lib/merge.tcl:269
msgid "Abort completed. Ready."
msgstr "A megkeszakítás befejeződött. Kész."
-#: lib/option.tcl:95
+#: lib/mergetool.tcl:8
+msgid "Force resolution to the base version?"
+msgstr "Feloldás erőltetése az alap verzióhoz?"
+
+#: lib/mergetool.tcl:9
+msgid "Force resolution to this branch?"
+msgstr "Feloldás erőltetése ehhez a branch-hez?"
+
+#: lib/mergetool.tcl:10
+msgid "Force resolution to the other branch?"
+msgstr "Feloldás erőltetése a másik branch-hez?"
+
+#: lib/mergetool.tcl:14
+#, tcl-format
+msgid ""
+"Note that the diff shows only conflicting changes.\n"
+"\n"
+"%s will be overwritten.\n"
+"\n"
+"This operation can be undone only by restarting the merge."
+msgstr ""
+"Megjegyzés: csak az ütköző különbségek látszanak.\n"
+"\n"
+"A(z) %s felül lesz írva.\n"
+"\n"
+"Ez a művelet csak a merge újraindításával lesz visszavonható."
+
+#: lib/mergetool.tcl:45
+#, tcl-format
+msgid "File %s seems to have unresolved conflicts, still stage?"
+msgstr ""
+"A(z) %s fájl nem feloldott ütközéseket tartalmaz, mégis legyen kiválasztva?"
+
+#: lib/mergetool.tcl:60
+#, tcl-format
+msgid "Adding resolution for %s"
+msgstr "Feloldás hozzáadása a(z) %s számára"
+
+#: lib/mergetool.tcl:141
+msgid "Cannot resolve deletion or link conflicts using a tool"
+msgstr "Nem lehet feloldani törlési vagy link ütközést egy eszközzel"
+
+#: lib/mergetool.tcl:146
+msgid "Conflict file does not exist"
+msgstr "A konfiklus-fájl nem létezik."
+
+#: lib/mergetool.tcl:264
+#, tcl-format
+msgid "Not a GUI merge tool: '%s'"
+msgstr "Nem GUI merge eszköz: %s"
+
+#: lib/mergetool.tcl:268
+#, tcl-format
+msgid "Unsupported merge tool '%s'"
+msgstr "A(z) '%s' merge eszköz nem támogatott"
+
+#: lib/mergetool.tcl:303
+msgid "Merge tool is already running, terminate it?"
+msgstr "A merge eszköz már fut, le legyen állítva?"
+
+#: lib/mergetool.tcl:323
+#, tcl-format
+msgid ""
+"Error retrieving versions:\n"
+"%s"
+msgstr ""
+"Hiba a verziók kinyerése közben:\n"
+"%s"
+
+#: lib/mergetool.tcl:343
+#, tcl-format
+msgid ""
+"Could not start the merge tool:\n"
+"\n"
+"%s"
+msgstr ""
+"A merge eszköz indítása sikertelen:\n"
+"\n"
+"%s"
+
+#: lib/mergetool.tcl:347
+msgid "Running merge tool..."
+msgstr "A merge eszköz futtatása..."
+
+#: lib/mergetool.tcl:375 lib/mergetool.tcl:383
+msgid "Merge tool failed."
+msgstr "A merge eszköz nem sikerült."
+
+#: lib/option.tcl:11
+#, tcl-format
+msgid "Invalid global encoding '%s'"
+msgstr "Érvénytelen globális kódolás '%s'"
+
+#: lib/option.tcl:19
+#, tcl-format
+msgid "Invalid repo encoding '%s'"
+msgstr "Érvénytelen repó kódolás '%s'"
+
+#: lib/option.tcl:117
msgid "Restore Defaults"
msgstr "Alapértelmezés visszaállítása"
-#: lib/option.tcl:99
+#: lib/option.tcl:121
msgid "Save"
msgstr "Mentés"
-#: lib/option.tcl:109
+#: lib/option.tcl:131
#, tcl-format
msgid "%s Repository"
msgstr "%s Repó"
-#: lib/option.tcl:110
+#: lib/option.tcl:132
msgid "Global (All Repositories)"
msgstr "Globális (minden repó)"
-#: lib/option.tcl:116
+#: lib/option.tcl:138
msgid "User Name"
msgstr "Felhasználónév"
-#: lib/option.tcl:117
+#: lib/option.tcl:139
msgid "Email Address"
msgstr "Email cím"
-#: lib/option.tcl:119
+#: lib/option.tcl:141
msgid "Summarize Merge Commits"
msgstr "A merge commitok összegzése"
-#: lib/option.tcl:120
+#: lib/option.tcl:142
msgid "Merge Verbosity"
msgstr "Merge beszédesség"
-#: lib/option.tcl:121
+#: lib/option.tcl:143
msgid "Show Diffstat After Merge"
msgstr "Diffstat mutatása merge után"
-#: lib/option.tcl:123
+#: lib/option.tcl:144
+msgid "Use Merge Tool"
+msgstr "Merge eszköz használata"
+
+#: lib/option.tcl:146
msgid "Trust File Modification Timestamps"
msgstr "A fájl módosítási dátumok megbízhatóak"
-#: lib/option.tcl:124
+#: lib/option.tcl:147
msgid "Prune Tracking Branches During Fetch"
msgstr "A követő branchek eltávolítása letöltés alatt"
-#: lib/option.tcl:125
+#: lib/option.tcl:148
msgid "Match Tracking Branches"
msgstr "A követő branchek egyeztetése"
-#: lib/option.tcl:126
+#: lib/option.tcl:149
+msgid "Blame Copy Only On Changed Files"
+msgstr "A blame másolás bekapcsolása csak megváltozott fájlokra"
+
+#: lib/option.tcl:150
+msgid "Minimum Letters To Blame Copy On"
+msgstr "Minimum betűszám blame másolás-érzékeléshez"
+
+#: lib/option.tcl:151
+msgid "Blame History Context Radius (days)"
+msgstr "Blame történet környezet sugár (napokban)"
+
+#: lib/option.tcl:152
msgid "Number of Diff Context Lines"
msgstr "A diff környezeti sorok száma"
-#: lib/option.tcl:127
+#: lib/option.tcl:153
msgid "Commit Message Text Width"
msgstr "Commit üzenet szövegének szélessége"
-#: lib/option.tcl:128
+#: lib/option.tcl:154
msgid "New Branch Name Template"
msgstr "Új branch név sablon"
-#: lib/option.tcl:192
+#: lib/option.tcl:155
+msgid "Default File Contents Encoding"
+msgstr "Alapértelmezett fájltartalom-kódolás"
+
+#: lib/option.tcl:203
+msgid "Change"
+msgstr "Megváltoztatás"
+
+#: lib/option.tcl:230
msgid "Spelling Dictionary:"
msgstr "Helyesírás-ellenőrző szótár:"
-#: lib/option.tcl:216
+#: lib/option.tcl:254
msgid "Change Font"
msgstr "Betűtípus megváltoztatása"
-#: lib/option.tcl:220
+#: lib/option.tcl:258
#, tcl-format
msgid "Choose %s"
msgstr "%s választása"
-#: lib/option.tcl:226
+#: lib/option.tcl:264
msgid "pt."
msgstr "pt."
-#: lib/option.tcl:240
+#: lib/option.tcl:278
msgid "Preferences"
msgstr "Beállítások"
-#: lib/option.tcl:275
+#: lib/option.tcl:314
msgid "Failed to completely save options:"
msgstr "Nem sikerült teljesen elmenteni a beállításokat:"
+#: lib/remote.tcl:163
+msgid "Remove Remote"
+msgstr "Remote eltávolítása"
+
+#: lib/remote.tcl:168
+msgid "Prune from"
+msgstr "Törlés innen"
+
+# tcl-format
+#: lib/remote.tcl:173
+msgid "Fetch from"
+msgstr "Letöltés innen"
+
+#: lib/remote.tcl:215
+msgid "Push to"
+msgstr "Push ide"
+
+#: lib/remote_add.tcl:19
+msgid "Add Remote"
+msgstr "Remote hozzáadása"
+
+#: lib/remote_add.tcl:24
+msgid "Add New Remote"
+msgstr "Új remote hozzáadása"
+
+#: lib/remote_add.tcl:28 lib/tools_dlg.tcl:36
+msgid "Add"
+msgstr "Hozzáadás"
+
+#: lib/remote_add.tcl:37
+msgid "Remote Details"
+msgstr "Remote részletei"
+
+#: lib/remote_add.tcl:50
+msgid "Location:"
+msgstr "Hely:"
+
+#: lib/remote_add.tcl:62
+msgid "Further Action"
+msgstr "Következő művelet"
+
+#: lib/remote_add.tcl:65
+msgid "Fetch Immediately"
+msgstr "Letöltés most"
+
+#: lib/remote_add.tcl:71
+msgid "Initialize Remote Repository and Push"
+msgstr "Távoli repó inicializálása és push"
+
+#: lib/remote_add.tcl:77
+msgid "Do Nothing Else Now"
+msgstr "Ne csináljunk semmit"
+
+#: lib/remote_add.tcl:101
+msgid "Please supply a remote name."
+msgstr "Adjunk megy egy remote nevet."
+
+#: lib/remote_add.tcl:114
+#, tcl-format
+msgid "'%s' is not an acceptable remote name."
+msgstr "A(z) '%s' nem egy elfogadható remote név."
+
+#: lib/remote_add.tcl:125
+#, tcl-format
+msgid "Failed to add remote '%s' of location '%s'."
+msgstr "Nem sikerült a(t) '%s' remote hozzáadása innen: '%s'."
+
+#: lib/remote_add.tcl:133 lib/transport.tcl:6
+#, tcl-format
+msgid "fetch %s"
+msgstr "a(z) %s letöltése"
+
+#: lib/remote_add.tcl:134
+#, tcl-format
+msgid "Fetching the %s"
+msgstr "A(z) %s letöltése"
+
+#: lib/remote_add.tcl:157
+#, tcl-format
+msgid "Do not know how to initialize repository at location '%s'."
+msgstr "Nem tudni, hogy hogy kell a(z) '%s' helyen repót inicializálni."
+
+#: lib/remote_add.tcl:163 lib/transport.tcl:25 lib/transport.tcl:63
+#: lib/transport.tcl:81
+#, tcl-format
+msgid "push %s"
+msgstr "%s push-olása"
+
+#: lib/remote_add.tcl:164
+#, tcl-format
+msgid "Setting up the %s (at %s)"
+msgstr "A(z) %s beállítása itt: %s"
+
#: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34
-msgid "Delete Remote Branch"
-msgstr "Távoli branch törlése"
+msgid "Delete Branch Remotely"
+msgstr "Távoli Branch törlése"
#: lib/remote_branch_delete.tcl:47
msgid "From Repository"
msgstr "Forrás repó"
-#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:123
+#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:134
msgid "Remote:"
msgstr "Távoli:"
-#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:138
-msgid "Arbitrary URL:"
-msgstr "Tetszőleges URL:"
+#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:149
+msgid "Arbitrary Location:"
+msgstr "Önkényes hely:"
#: lib/remote_branch_delete.tcl:84
msgid "Branches"
@@ -1854,18 +2262,21 @@ msgstr "Nincs kiválasztott repó."
msgid "Scanning %s..."
msgstr "Keresés itt: %s..."
-#: lib/remote.tcl:165
-msgid "Prune from"
-msgstr "Törlés innen"
+#: lib/search.tcl:21
+msgid "Find:"
+msgstr "Keresés:"
-# tcl-format
-#: lib/remote.tcl:170
-msgid "Fetch from"
-msgstr "Letöltés innen"
+#: lib/search.tcl:23
+msgid "Next"
+msgstr "Következő"
-#: lib/remote.tcl:213
-msgid "Push to"
-msgstr "Push ide"
+#: lib/search.tcl:24
+msgid "Prev"
+msgstr "Előző"
+
+#: lib/search.tcl:25
+msgid "Case-Sensitive"
+msgstr "Kisbetű-nagybetű számít"
#: lib/shortcut.tcl:20 lib/shortcut.tcl:61
msgid "Cannot write shortcut:"
@@ -1900,27 +2311,194 @@ msgstr "A helyesírás-ellenőrő indítása sikertelen"
msgid "Unrecognized spell checker"
msgstr "Ismeretlen helyesírás-ellenőrző"
-#: lib/spellcheck.tcl:180
+#: lib/spellcheck.tcl:186
msgid "No Suggestions"
msgstr "Nincs javaslat"
-#: lib/spellcheck.tcl:381
+#: lib/spellcheck.tcl:388
msgid "Unexpected EOF from spell checker"
msgstr "Nem várt EOF a helyesírás-ellenőrzőtől"
-#: lib/spellcheck.tcl:385
+#: lib/spellcheck.tcl:392
msgid "Spell Checker Failed"
msgstr "A helyesírás-ellenőrzés sikertelen"
+#: lib/sshkey.tcl:31
+msgid "No keys found."
+msgstr "Nincsenek kulcsok."
+
+#: lib/sshkey.tcl:34
+#, tcl-format
+msgid "Found a public key in: %s"
+msgstr "Nyilvános kulcs található ebben: %s"
+
+#: lib/sshkey.tcl:40
+msgid "Generate Key"
+msgstr "Kulcs generálása"
+
+#: lib/sshkey.tcl:56
+msgid "Copy To Clipboard"
+msgstr "Másolás vágólapra"
+
+#: lib/sshkey.tcl:70
+msgid "Your OpenSSH Public Key"
+msgstr "Az OpenSSH publikus kulcsunk"
+
+#: lib/sshkey.tcl:78
+msgid "Generating..."
+msgstr "Generálás..."
+
+#: lib/sshkey.tcl:84
+#, tcl-format
+msgid ""
+"Could not start ssh-keygen:\n"
+"\n"
+"%s"
+msgstr ""
+"Az ssh-keygen indítása sikertelen:\n"
+"\n"
+"%s"
+
+#: lib/sshkey.tcl:111
+msgid "Generation failed."
+msgstr "A generálás nem sikerült."
+
+#: lib/sshkey.tcl:118
+msgid "Generation succeded, but no keys found."
+msgstr "A generálás sikeres, de egy kulcs se található."
+
+#: lib/sshkey.tcl:121
+#, tcl-format
+msgid "Your key is in: %s"
+msgstr "A kulcsunk itt van: %s"
+
#: lib/status_bar.tcl:83
#, tcl-format
msgid "%s ... %*i of %*i %s (%3i%%)"
msgstr "%s ... %*i / %*i %s (%3i%%)"
-#: lib/transport.tcl:6
+#: lib/tools.tcl:75
#, tcl-format
-msgid "fetch %s"
-msgstr "a(z) %s letöltése"
+msgid "Running %s requires a selected file."
+msgstr "A(z) %s futtatása egy kiválasztott fájlt igényel."
+
+#: lib/tools.tcl:90
+#, tcl-format
+msgid "Are you sure you want to run %s?"
+msgstr "Biztos benne, hogy futtatni kívánja: %s?"
+
+#: lib/tools.tcl:110
+#, tcl-format
+msgid "Tool: %s"
+msgstr "Eszköz: %s"
+
+#: lib/tools.tcl:111
+#, tcl-format
+msgid "Running: %s"
+msgstr "Futtatás: %s..."
+
+#: lib/tools.tcl:149
+#, tcl-format
+msgid "Tool completed succesfully: %s"
+msgstr "Az eszköz sikeresen befejeződött: %s"
+
+#: lib/tools.tcl:151
+#, tcl-format
+msgid "Tool failed: %s"
+msgstr "Az eszköz sikertelen: %s"
+
+#: lib/tools_dlg.tcl:22
+msgid "Add Tool"
+msgstr "Eszköz hozzáadása"
+
+#: lib/tools_dlg.tcl:28
+msgid "Add New Tool Command"
+msgstr "Új eszköz-parancs hozzáadása"
+
+#: lib/tools_dlg.tcl:33
+msgid "Add globally"
+msgstr "Globális hozzáadás"
+
+#: lib/tools_dlg.tcl:45
+msgid "Tool Details"
+msgstr "Eszköz részletei"
+
+#: lib/tools_dlg.tcl:48
+msgid "Use '/' separators to create a submenu tree:"
+msgstr "Használjunk '/' szeparátorokat almenü-fa létrehozásához:"
+
+#: lib/tools_dlg.tcl:61
+msgid "Command:"
+msgstr "Parancs:"
+
+#: lib/tools_dlg.tcl:74
+msgid "Show a dialog before running"
+msgstr "Parancsablak mutatása futtatás előtt"
+
+#: lib/tools_dlg.tcl:80
+msgid "Ask the user to select a revision (sets $REVISION)"
+msgstr ""
+"Megkéri a felhasználót, hogy válasszon ki egy revíziót (a $REVISION-t "
+"állítja)"
+
+#: lib/tools_dlg.tcl:85
+msgid "Ask the user for additional arguments (sets $ARGS)"
+msgstr "Megkérdezi a felhasználót további argumentumokért (a $ARGS-ot állítja)"
+
+#: lib/tools_dlg.tcl:92
+msgid "Don't show the command output window"
+msgstr "Ne mutassa a parancs kimeneti ablakát"
+
+#: lib/tools_dlg.tcl:97
+msgid "Run only if a diff is selected ($FILENAME not empty)"
+msgstr "Futtatás csak ha egy diff ki van választva (a $FILENAME nem üres)"
+
+#: lib/tools_dlg.tcl:121
+msgid "Please supply a name for the tool."
+msgstr "Adjunk meg egy eszköz nevet."
+
+#: lib/tools_dlg.tcl:129
+#, tcl-format
+msgid "Tool '%s' already exists."
+msgstr "A(z) '%s' eszköz már létezik."
+
+#: lib/tools_dlg.tcl:151
+#, tcl-format
+msgid ""
+"Could not add tool:\n"
+"%s"
+msgstr ""
+"Az eszköz nem hozzáadható:\n"
+"%s"
+
+#: lib/tools_dlg.tcl:190
+msgid "Remove Tool"
+msgstr "Eszköz eltávolítása"
+
+#: lib/tools_dlg.tcl:196
+msgid "Remove Tool Commands"
+msgstr "Eszköz parancsok eltávolítása"
+
+#: lib/tools_dlg.tcl:200
+msgid "Remove"
+msgstr "Eltávolítás"
+
+#: lib/tools_dlg.tcl:236
+msgid "(Blue denotes repository-local tools)"
+msgstr "(Kék jelzi a repó-specifikus eszközöket)"
+
+#: lib/tools_dlg.tcl:297
+#, tcl-format
+msgid "Run Command: %s"
+msgstr "Parancs futtatása: %s"
+
+#: lib/tools_dlg.tcl:311
+msgid "Arguments"
+msgstr "Argumentumok"
+
+#: lib/tools_dlg.tcl:348
+msgid "OK"
+msgstr "OK"
#: lib/transport.tcl:7
#, tcl-format
@@ -1937,72 +2515,81 @@ msgstr "a(z) %s távoli törlése"
msgid "Pruning tracking branches deleted from %s"
msgstr "A %s repóból törölt követő branchek törlése"
-#: lib/transport.tcl:25 lib/transport.tcl:71
-#, tcl-format
-msgid "push %s"
-msgstr "%s push-olása"
-
#: lib/transport.tcl:26
#, tcl-format
msgid "Pushing changes to %s"
msgstr "Változások pusholása ide: %s"
-#: lib/transport.tcl:72
+#: lib/transport.tcl:64
+#, tcl-format
+msgid "Mirroring to %s"
+msgstr "Tükrözés a következő helyre: %s"
+
+#: lib/transport.tcl:82
#, tcl-format
msgid "Pushing %s %s to %s"
msgstr "Pusholás: %s %s, ide: %s"
-#: lib/transport.tcl:89
+#: lib/transport.tcl:100
msgid "Push Branches"
msgstr "Branchek pusholása"
-#: lib/transport.tcl:103
+#: lib/transport.tcl:114
msgid "Source Branches"
msgstr "Forrás branchek"
-#: lib/transport.tcl:120
+#: lib/transport.tcl:131
msgid "Destination Repository"
msgstr "Cél repó"
-#: lib/transport.tcl:158
+#: lib/transport.tcl:169
msgid "Transfer Options"
msgstr "Ãtviteli opciók"
-#: lib/transport.tcl:160
+#: lib/transport.tcl:171
msgid "Force overwrite existing branch (may discard changes)"
msgstr ""
"Létező branch felülírásának erőltetése (lehet, hogy el fog dobni "
"változtatásokat)"
-#: lib/transport.tcl:164
+#: lib/transport.tcl:175
msgid "Use thin pack (for slow network connections)"
msgstr "Vékony csomagok használata (lassú hálózati kapcsolatok számára)"
-#: lib/transport.tcl:168
+#: lib/transport.tcl:179
msgid "Include tags"
msgstr "Tageket is"
+#~ msgid ""
+#~ "Unable to start gitk:\n"
+#~ "\n"
+#~ "%s does not exist"
+#~ msgstr ""
+#~ "A gitk indítása sikertelen:\n"
+#~ "\n"
+#~ "A(z) %s nem létezik"
+
+#~ msgid "Apple"
+#~ msgstr "Apple"
+
+#~ msgid "URL:"
+#~ msgstr "URL:"
+
+#~ msgid "Delete Remote Branch"
+#~ msgstr "Távoli branch törlése"
+
#~ msgid "Not connected to aspell"
#~ msgstr "Nincs kapcsolat az aspellhez"
-#~ msgid "Cannot find the git directory:"
-#~ msgstr "Nem található a git könyvtár:"
-
#~ msgid "Unstaged Changes (Will Not Be Committed)"
#~ msgstr "Nem kiválasztott változtatások (nem lesz commitolva)"
#~ msgid "Push to %s..."
#~ msgstr "Pusholás ide: %s..."
-#~ msgid "Add To Commit"
-#~ msgstr "Hozzáadás a commithoz"
-
#~ msgid "Add Existing To Commit"
#~ msgstr "Hozzáadás létező commithoz"
-#~ msgid "Running miga..."
-#~ msgstr "A miga futtatása..."
-
#~ msgid "Add Existing"
#~ msgstr "Létező hozzáadása"
diff --git a/git-gui/po/it.po b/git-gui/po/it.po
index 3db4fb68c5..294e595887 100644
--- a/git-gui/po/it.po
+++ b/git-gui/po/it.po
@@ -9,41 +9,41 @@ msgid ""
msgstr ""
"Project-Id-Version: git-gui\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-08-02 14:45-0700\n"
-"PO-Revision-Date: 2008-08-03 16:04+0200\n"
+"POT-Creation-Date: 2008-12-08 08:31-0800\n"
+"PO-Revision-Date: 2008-12-09 13:04+0100\n"
"Last-Translator: Michele Ballabio <barra_cuda@katamail.com>\n"
"Language-Team: Italian <tp@lists.linux.it>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: git-gui.sh:41 git-gui.sh:688 git-gui.sh:702 git-gui.sh:715 git-gui.sh:798
-#: git-gui.sh:817
+#: git-gui.sh:41 git-gui.sh:737 git-gui.sh:751 git-gui.sh:764 git-gui.sh:847
+#: git-gui.sh:866
msgid "git-gui: fatal error"
msgstr "git-gui: errore grave"
-#: git-gui.sh:644
+#: git-gui.sh:689
#, tcl-format
msgid "Invalid font specified in %s:"
msgstr "Caratteri non validi specificati in %s:"
-#: git-gui.sh:674
+#: git-gui.sh:723
msgid "Main Font"
msgstr "Caratteri principali"
-#: git-gui.sh:675
+#: git-gui.sh:724
msgid "Diff/Console Font"
msgstr "Caratteri per confronti e terminale"
-#: git-gui.sh:689
+#: git-gui.sh:738
msgid "Cannot find git in PATH."
msgstr "Impossibile trovare git nel PATH"
-#: git-gui.sh:716
+#: git-gui.sh:765
msgid "Cannot parse Git version string:"
msgstr "Impossibile determinare la versione di Git:"
-#: git-gui.sh:734
+#: git-gui.sh:783
#, tcl-format
msgid ""
"Git version cannot be determined.\n"
@@ -62,381 +62,446 @@ msgstr ""
"\n"
"Assumere che '%s' sia alla versione 1.5.0?\n"
-#: git-gui.sh:972
+#: git-gui.sh:1062
msgid "Git directory not found:"
msgstr "Non trovo la directory di git: "
-#: git-gui.sh:979
+#: git-gui.sh:1069
msgid "Cannot move to top of working directory:"
msgstr "Impossibile spostarsi sulla directory principale del progetto:"
-#: git-gui.sh:986
+#: git-gui.sh:1076
msgid "Cannot use funny .git directory:"
msgstr "Impossibile usare una .git directory strana:"
-#: git-gui.sh:991
+#: git-gui.sh:1081
msgid "No working directory"
msgstr "Nessuna directory di lavoro"
-#: git-gui.sh:1138 lib/checkout_op.tcl:305
+#: git-gui.sh:1247 lib/checkout_op.tcl:305
msgid "Refreshing file status..."
msgstr "Controllo dello stato dei file in corso..."
-#: git-gui.sh:1194
+#: git-gui.sh:1303
msgid "Scanning for modified files ..."
msgstr "Ricerca di file modificati in corso..."
-#: git-gui.sh:1369 lib/browser.tcl:246
+#: git-gui.sh:1367
+msgid "Calling prepare-commit-msg hook..."
+msgstr "Avvio prepare-commit-msg hook..."
+
+#: git-gui.sh:1384
+msgid "Commit declined by prepare-commit-msg hook."
+msgstr "Revisione rifiutata dal prepare-commit-msg hook."
+
+#: git-gui.sh:1542 lib/browser.tcl:246
msgid "Ready."
msgstr "Pronto."
-#: git-gui.sh:1635
+#: git-gui.sh:1819
msgid "Unmodified"
msgstr "Non modificato"
-#: git-gui.sh:1637
+#: git-gui.sh:1821
msgid "Modified, not staged"
msgstr "Modificato, non preparato per una nuova revisione"
-#: git-gui.sh:1638 git-gui.sh:1643
+#: git-gui.sh:1822 git-gui.sh:1830
msgid "Staged for commit"
msgstr "Preparato per una nuova revisione"
-#: git-gui.sh:1639 git-gui.sh:1644
+#: git-gui.sh:1823 git-gui.sh:1831
msgid "Portions staged for commit"
msgstr "Parti preparate per una nuova revisione"
-#: git-gui.sh:1640 git-gui.sh:1645
+#: git-gui.sh:1824 git-gui.sh:1832
msgid "Staged for commit, missing"
msgstr "Preparato per una nuova revisione, mancante"
-#: git-gui.sh:1642
+#: git-gui.sh:1826
+msgid "File type changed, not staged"
+msgstr "Tipo di file modificato, non preparato per una nuova revisione"
+
+#: git-gui.sh:1827
+msgid "File type changed, staged"
+msgstr "Tipo di file modificato, preparato per una nuova revisione"
+
+#: git-gui.sh:1829
msgid "Untracked, not staged"
msgstr "Non tracciato, non preparato per una nuova revisione"
-#: git-gui.sh:1647
+#: git-gui.sh:1834
msgid "Missing"
msgstr "Mancante"
-#: git-gui.sh:1648
+#: git-gui.sh:1835
msgid "Staged for removal"
msgstr "Preparato per la rimozione"
-#: git-gui.sh:1649
+#: git-gui.sh:1836
msgid "Staged for removal, still present"
msgstr "Preparato alla rimozione, ancora presente"
-#: git-gui.sh:1651 git-gui.sh:1652 git-gui.sh:1653 git-gui.sh:1654
+#: git-gui.sh:1838 git-gui.sh:1839 git-gui.sh:1840 git-gui.sh:1841
+#: git-gui.sh:1842 git-gui.sh:1843
msgid "Requires merge resolution"
msgstr "Richiede risoluzione dei conflitti"
-#: git-gui.sh:1689
+#: git-gui.sh:1878
msgid "Starting gitk... please wait..."
msgstr "Avvio di gitk... attendere..."
-#: git-gui.sh:1698
+#: git-gui.sh:1887
msgid "Couldn't find gitk in PATH"
msgstr "Impossibile trovare gitk nel PATH"
-#: git-gui.sh:1948 lib/choose_repository.tcl:36
+#: git-gui.sh:2280 lib/choose_repository.tcl:36
msgid "Repository"
msgstr "Archivio"
-#: git-gui.sh:1949
+#: git-gui.sh:2281
msgid "Edit"
msgstr "Modifica"
-#: git-gui.sh:1951 lib/choose_rev.tcl:561
+#: git-gui.sh:2283 lib/choose_rev.tcl:561
msgid "Branch"
msgstr "Ramo"
-#: git-gui.sh:1954 lib/choose_rev.tcl:548
+#: git-gui.sh:2286 lib/choose_rev.tcl:548
msgid "Commit@@noun"
msgstr "Revisione"
-#: git-gui.sh:1957 lib/merge.tcl:120 lib/merge.tcl:149 lib/merge.tcl:167
+#: git-gui.sh:2289 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168
msgid "Merge"
msgstr "Fusione (Merge)"
-#: git-gui.sh:1958 lib/choose_rev.tcl:557
+#: git-gui.sh:2290 lib/choose_rev.tcl:557
msgid "Remote"
msgstr "Remoto"
-#: git-gui.sh:1967
+#: git-gui.sh:2293
+msgid "Tools"
+msgstr "Strumenti"
+
+#: git-gui.sh:2302
+msgid "Explore Working Copy"
+msgstr "Esplora copia di lavoro"
+
+#: git-gui.sh:2307
msgid "Browse Current Branch's Files"
msgstr "Esplora i file del ramo attuale"
-#: git-gui.sh:1971
+#: git-gui.sh:2311
msgid "Browse Branch Files..."
msgstr "Esplora i file del ramo..."
-#: git-gui.sh:1976
+#: git-gui.sh:2316
msgid "Visualize Current Branch's History"
msgstr "Visualizza la cronologia del ramo attuale"
-#: git-gui.sh:1980
+#: git-gui.sh:2320
msgid "Visualize All Branch History"
msgstr "Visualizza la cronologia di tutti i rami"
-#: git-gui.sh:1987
+#: git-gui.sh:2327
#, tcl-format
msgid "Browse %s's Files"
msgstr "Esplora i file di %s"
-#: git-gui.sh:1989
+#: git-gui.sh:2329
#, tcl-format
msgid "Visualize %s's History"
msgstr "Visualizza la cronologia di %s"
-#: git-gui.sh:1994 lib/database.tcl:27 lib/database.tcl:67
+#: git-gui.sh:2334 lib/database.tcl:27 lib/database.tcl:67
msgid "Database Statistics"
msgstr "Statistiche dell'archivio"
-#: git-gui.sh:1997 lib/database.tcl:34
+#: git-gui.sh:2337 lib/database.tcl:34
msgid "Compress Database"
msgstr "Comprimi l'archivio"
-#: git-gui.sh:2000
+#: git-gui.sh:2340
msgid "Verify Database"
msgstr "Verifica l'archivio"
-#: git-gui.sh:2007 git-gui.sh:2011 git-gui.sh:2015 lib/shortcut.tcl:7
+#: git-gui.sh:2347 git-gui.sh:2351 git-gui.sh:2355 lib/shortcut.tcl:7
#: lib/shortcut.tcl:39 lib/shortcut.tcl:71
msgid "Create Desktop Icon"
msgstr "Crea icona desktop"
-#: git-gui.sh:2023 lib/choose_repository.tcl:177 lib/choose_repository.tcl:185
+#: git-gui.sh:2363 lib/choose_repository.tcl:183 lib/choose_repository.tcl:191
msgid "Quit"
msgstr "Esci"
-#: git-gui.sh:2031
+#: git-gui.sh:2371
msgid "Undo"
msgstr "Annulla"
-#: git-gui.sh:2034
+#: git-gui.sh:2374
msgid "Redo"
msgstr "Ripeti"
-#: git-gui.sh:2038 git-gui.sh:2545
+#: git-gui.sh:2378 git-gui.sh:2937
msgid "Cut"
msgstr "Taglia"
-#: git-gui.sh:2041 git-gui.sh:2548 git-gui.sh:2622 git-gui.sh:2715
+#: git-gui.sh:2381 git-gui.sh:2940 git-gui.sh:3014 git-gui.sh:3096
#: lib/console.tcl:69
msgid "Copy"
msgstr "Copia"
-#: git-gui.sh:2044 git-gui.sh:2551
+#: git-gui.sh:2384 git-gui.sh:2943
msgid "Paste"
msgstr "Incolla"
-#: git-gui.sh:2047 git-gui.sh:2554 lib/branch_delete.tcl:26
+#: git-gui.sh:2387 git-gui.sh:2946 lib/branch_delete.tcl:26
#: lib/remote_branch_delete.tcl:38
msgid "Delete"
msgstr "Elimina"
-#: git-gui.sh:2051 git-gui.sh:2558 git-gui.sh:2719 lib/console.tcl:71
+#: git-gui.sh:2391 git-gui.sh:2950 git-gui.sh:3100 lib/console.tcl:71
msgid "Select All"
msgstr "Seleziona tutto"
-#: git-gui.sh:2060
+#: git-gui.sh:2400
msgid "Create..."
msgstr "Crea..."
-#: git-gui.sh:2066
+#: git-gui.sh:2406
msgid "Checkout..."
msgstr "Attiva..."
-#: git-gui.sh:2072
+#: git-gui.sh:2412
msgid "Rename..."
msgstr "Rinomina"
-#: git-gui.sh:2077 git-gui.sh:2187
+#: git-gui.sh:2417
msgid "Delete..."
msgstr "Elimina..."
-#: git-gui.sh:2082
+#: git-gui.sh:2422
msgid "Reset..."
msgstr "Ripristina..."
-#: git-gui.sh:2094 git-gui.sh:2491
+#: git-gui.sh:2432
+msgid "Done"
+msgstr "Fatto"
+
+#: git-gui.sh:2434
+msgid "Commit@@verb"
+msgstr "Nuova revisione"
+
+#: git-gui.sh:2443 git-gui.sh:2878
msgid "New Commit"
msgstr "Nuova revisione"
-#: git-gui.sh:2102 git-gui.sh:2498
+#: git-gui.sh:2451 git-gui.sh:2885
msgid "Amend Last Commit"
msgstr "Correggi l'ultima revisione"
-#: git-gui.sh:2111 git-gui.sh:2458 lib/remote_branch_delete.tcl:99
+#: git-gui.sh:2461 git-gui.sh:2839 lib/remote_branch_delete.tcl:99
msgid "Rescan"
msgstr "Analizza nuovamente"
-#: git-gui.sh:2117
+#: git-gui.sh:2467
msgid "Stage To Commit"
msgstr "Prepara per una nuova revisione"
-#: git-gui.sh:2123
+#: git-gui.sh:2473
msgid "Stage Changed Files To Commit"
msgstr "Prepara i file modificati per una nuova revisione"
-#: git-gui.sh:2129
+#: git-gui.sh:2479
msgid "Unstage From Commit"
msgstr "Annulla preparazione"
-#: git-gui.sh:2134 lib/index.tcl:395
+#: git-gui.sh:2484 lib/index.tcl:410
msgid "Revert Changes"
msgstr "Annulla modifiche"
-#: git-gui.sh:2141 git-gui.sh:2702
+#: git-gui.sh:2491 git-gui.sh:3083
msgid "Show Less Context"
msgstr "Mostra meno contesto"
-#: git-gui.sh:2145 git-gui.sh:2706
+#: git-gui.sh:2495 git-gui.sh:3087
msgid "Show More Context"
msgstr "Mostra più contesto"
-#: git-gui.sh:2151 git-gui.sh:2470 git-gui.sh:2569
+#: git-gui.sh:2502 git-gui.sh:2852 git-gui.sh:2961
msgid "Sign Off"
msgstr "Sign Off"
-#: git-gui.sh:2155 git-gui.sh:2474
-msgid "Commit@@verb"
-msgstr "Nuova revisione"
-
-#: git-gui.sh:2166
+#: git-gui.sh:2518
msgid "Local Merge..."
msgstr "Fusione locale..."
-#: git-gui.sh:2171
+#: git-gui.sh:2523
msgid "Abort Merge..."
msgstr "Interrompi fusione..."
-#: git-gui.sh:2183
+#: git-gui.sh:2535 git-gui.sh:2575
+msgid "Add..."
+msgstr "Aggiungi..."
+
+#: git-gui.sh:2539
msgid "Push..."
msgstr "Propaga..."
-#: git-gui.sh:2197 git-gui.sh:2219 lib/about.tcl:14
-#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50
+#: git-gui.sh:2543
+msgid "Delete Branch..."
+msgstr "Elimina ramo..."
+
+#: git-gui.sh:2553 git-gui.sh:2589 lib/about.tcl:14
+#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:53
#, tcl-format
msgid "About %s"
msgstr "Informazioni su %s"
-#: git-gui.sh:2201
+#: git-gui.sh:2557
msgid "Preferences..."
msgstr "Preferenze..."
-#: git-gui.sh:2209 git-gui.sh:2740
+#: git-gui.sh:2565 git-gui.sh:3129
msgid "Options..."
msgstr "Opzioni..."
-#: git-gui.sh:2215 lib/choose_repository.tcl:47
+#: git-gui.sh:2576
+msgid "Remove..."
+msgstr "Rimuovi..."
+
+#: git-gui.sh:2585 lib/choose_repository.tcl:50
msgid "Help"
msgstr "Aiuto"
-#: git-gui.sh:2256
+#: git-gui.sh:2611
msgid "Online Documentation"
msgstr "Documentazione sul web"
-#: git-gui.sh:2340
+#: git-gui.sh:2614 lib/choose_repository.tcl:47 lib/choose_repository.tcl:56
+msgid "Show SSH Key"
+msgstr "Mostra chave SSH"
+
+#: git-gui.sh:2721
#, tcl-format
msgid "fatal: cannot stat path %s: No such file or directory"
msgstr ""
"errore grave: impossibile effettuare lo stat del path %s: file o directory "
"non trovata"
-#: git-gui.sh:2373
+#: git-gui.sh:2754
msgid "Current Branch:"
msgstr "Ramo attuale:"
-#: git-gui.sh:2394
+#: git-gui.sh:2775
msgid "Staged Changes (Will Commit)"
msgstr "Modifiche preparate (saranno nella nuova revisione)"
-#: git-gui.sh:2414
+#: git-gui.sh:2795
msgid "Unstaged Changes"
msgstr "Modifiche non preparate"
-#: git-gui.sh:2464
+#: git-gui.sh:2845
msgid "Stage Changed"
msgstr "Prepara modificati"
-#: git-gui.sh:2480 lib/transport.tcl:93 lib/transport.tcl:182
+#: git-gui.sh:2864 lib/transport.tcl:104 lib/transport.tcl:193
msgid "Push"
msgstr "Propaga (Push)"
-#: git-gui.sh:2510
+#: git-gui.sh:2899
msgid "Initial Commit Message:"
msgstr "Messaggio di revisione iniziale:"
-#: git-gui.sh:2511
+#: git-gui.sh:2900
msgid "Amended Commit Message:"
msgstr "Messaggio di revisione corretto:"
-#: git-gui.sh:2512
+#: git-gui.sh:2901
msgid "Amended Initial Commit Message:"
msgstr "Messaggio iniziale di revisione corretto:"
-#: git-gui.sh:2513
+#: git-gui.sh:2902
msgid "Amended Merge Commit Message:"
msgstr "Messaggio di fusione corretto:"
-#: git-gui.sh:2514
+#: git-gui.sh:2903
msgid "Merge Commit Message:"
msgstr "Messaggio di fusione:"
-#: git-gui.sh:2515
+#: git-gui.sh:2904
msgid "Commit Message:"
msgstr "Messaggio di revisione:"
-#: git-gui.sh:2561 git-gui.sh:2723 lib/console.tcl:73
+#: git-gui.sh:2953 git-gui.sh:3104 lib/console.tcl:73
msgid "Copy All"
msgstr "Copia tutto"
-#: git-gui.sh:2585 lib/blame.tcl:100
+#: git-gui.sh:2977 lib/blame.tcl:104
msgid "File:"
msgstr "File:"
-#: git-gui.sh:2691
-msgid "Apply/Reverse Hunk"
-msgstr "Applica/Inverti sezione"
-
-#: git-gui.sh:2696
-msgid "Apply/Reverse Line"
-msgstr "Applica/Inverti riga"
-
-#: git-gui.sh:2711
+#: git-gui.sh:3092
msgid "Refresh"
msgstr "Rinfresca"
-#: git-gui.sh:2732
+#: git-gui.sh:3113
msgid "Decrease Font Size"
msgstr "Diminuisci dimensione caratteri"
-#: git-gui.sh:2736
+#: git-gui.sh:3117
msgid "Increase Font Size"
msgstr "Aumenta dimensione caratteri"
-#: git-gui.sh:2747
+#: git-gui.sh:3125 lib/blame.tcl:281
+msgid "Encoding"
+msgstr "Codifica"
+
+#: git-gui.sh:3136
+msgid "Apply/Reverse Hunk"
+msgstr "Applica/Inverti sezione"
+
+#: git-gui.sh:3141
+msgid "Apply/Reverse Line"
+msgstr "Applica/Inverti riga"
+
+#: git-gui.sh:3151
+msgid "Run Merge Tool"
+msgstr "Avvia programma esterno per la risoluzione dei conflitti"
+
+#: git-gui.sh:3156
+msgid "Use Remote Version"
+msgstr "Usa versione remota"
+
+#: git-gui.sh:3160
+msgid "Use Local Version"
+msgstr "Usa versione locale"
+
+#: git-gui.sh:3164
+msgid "Revert To Base"
+msgstr "Ritorna alla revisione comune"
+
+#: git-gui.sh:3183
msgid "Unstage Hunk From Commit"
msgstr "Annulla preparazione della sezione per una nuova revisione"
-#: git-gui.sh:2748
+#: git-gui.sh:3184
msgid "Unstage Line From Commit"
msgstr "Annulla preparazione della linea per una nuova revisione"
-#: git-gui.sh:2750
+#: git-gui.sh:3186
msgid "Stage Hunk For Commit"
msgstr "Prepara sezione per una nuova revisione"
-#: git-gui.sh:2751
+#: git-gui.sh:3187
msgid "Stage Line For Commit"
msgstr "Prepara linea per una nuova revisione"
-#: git-gui.sh:2771
+#: git-gui.sh:3210
msgid "Initializing..."
msgstr "Inizializzazione..."
-#: git-gui.sh:2876
+#: git-gui.sh:3315
#, tcl-format
msgid ""
"Possible environment issues exist.\n"
@@ -453,7 +518,7 @@ msgstr ""
"da %s:\n"
"\n"
-#: git-gui.sh:2906
+#: git-gui.sh:3345
msgid ""
"\n"
"This is due to a known issue with the\n"
@@ -463,7 +528,7 @@ msgstr ""
"Ciò è dovuto a un problema conosciuto\n"
"causato dall'eseguibile Tcl distribuito da Cygwin."
-#: git-gui.sh:2911
+#: git-gui.sh:3350
#, tcl-format
msgid ""
"\n"
@@ -483,80 +548,108 @@ msgstr ""
msgid "git-gui - a graphical user interface for Git."
msgstr "git-gui - un'interfaccia grafica per Git."
-#: lib/blame.tcl:70
+#: lib/blame.tcl:72
msgid "File Viewer"
msgstr "Mostra file"
-#: lib/blame.tcl:74
+#: lib/blame.tcl:78
msgid "Commit:"
msgstr "Revisione:"
-#: lib/blame.tcl:257
+#: lib/blame.tcl:271
msgid "Copy Commit"
msgstr "Copia revisione"
-#: lib/blame.tcl:260
+#: lib/blame.tcl:275
+msgid "Find Text..."
+msgstr "Trova testo..."
+
+#: lib/blame.tcl:284
msgid "Do Full Copy Detection"
msgstr "Ricerca accurata delle copie"
-#: lib/blame.tcl:388
+#: lib/blame.tcl:288
+msgid "Show History Context"
+msgstr "Mostra contesto nella cronologia"
+
+#: lib/blame.tcl:291
+msgid "Blame Parent Commit"
+msgstr "Annota la revisione precedente"
+
+#: lib/blame.tcl:450
#, tcl-format
msgid "Reading %s..."
msgstr "Lettura di %s..."
-#: lib/blame.tcl:492
+#: lib/blame.tcl:557
msgid "Loading copy/move tracking annotations..."
msgstr "Caricamento annotazioni per copie/spostamenti..."
-#: lib/blame.tcl:512
+#: lib/blame.tcl:577
msgid "lines annotated"
msgstr "linee annotate"
-#: lib/blame.tcl:704
+#: lib/blame.tcl:769
msgid "Loading original location annotations..."
msgstr "Caricamento annotazioni per posizione originaria..."
-#: lib/blame.tcl:707
+#: lib/blame.tcl:772
msgid "Annotation complete."
msgstr "Annotazione completata."
-#: lib/blame.tcl:737
+#: lib/blame.tcl:802
msgid "Busy"
msgstr "Occupato"
-#: lib/blame.tcl:738
+#: lib/blame.tcl:803
msgid "Annotation process is already running."
msgstr "Il processo di annotazione è già in corso."
-#: lib/blame.tcl:777
+#: lib/blame.tcl:842
msgid "Running thorough copy detection..."
msgstr "Ricerca accurata delle copie in corso..."
-#: lib/blame.tcl:827
+#: lib/blame.tcl:910
msgid "Loading annotation..."
msgstr "Caricamento annotazioni..."
-#: lib/blame.tcl:883
+#: lib/blame.tcl:963
msgid "Author:"
msgstr "Autore:"
-#: lib/blame.tcl:887
+#: lib/blame.tcl:967
msgid "Committer:"
msgstr "Revisione creata da:"
-#: lib/blame.tcl:892
+#: lib/blame.tcl:972
msgid "Original File:"
msgstr "File originario:"
-#: lib/blame.tcl:1006
+#: lib/blame.tcl:1020
+msgid "Cannot find HEAD commit:"
+msgstr "Impossibile trovare la revisione HEAD:"
+
+#: lib/blame.tcl:1075
+msgid "Cannot find parent commit:"
+msgstr "Impossibile trovare la revisione precedente:"
+
+#: lib/blame.tcl:1090
+msgid "Unable to display parent"
+msgstr "Impossibile visualizzare la revisione precedente"
+
+#: lib/blame.tcl:1091 lib/diff.tcl:297
+msgid "Error loading diff:"
+msgstr "Errore nel caricamento delle differenze:"
+
+#: lib/blame.tcl:1231
msgid "Originally By:"
msgstr "In origine da:"
-#: lib/blame.tcl:1012
+#: lib/blame.tcl:1237
msgid "In File:"
msgstr "Nel file:"
-#: lib/blame.tcl:1017
+#: lib/blame.tcl:1242
msgid "Copied Or Moved Here By:"
msgstr "Copiato o spostato qui da:"
@@ -570,16 +663,18 @@ msgstr "Attiva"
#: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35
#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:282
-#: lib/checkout_op.tcl:544 lib/choose_font.tcl:43 lib/merge.tcl:171
-#: lib/option.tcl:103 lib/remote_branch_delete.tcl:42 lib/transport.tcl:97
+#: lib/checkout_op.tcl:544 lib/choose_font.tcl:43 lib/merge.tcl:172
+#: lib/option.tcl:125 lib/remote_add.tcl:32 lib/remote_branch_delete.tcl:42
+#: lib/tools_dlg.tcl:40 lib/tools_dlg.tcl:204 lib/tools_dlg.tcl:352
+#: lib/transport.tcl:108
msgid "Cancel"
msgstr "Annulla"
-#: lib/branch_checkout.tcl:32 lib/browser.tcl:287
+#: lib/branch_checkout.tcl:32 lib/browser.tcl:287 lib/tools_dlg.tcl:328
msgid "Revision"
msgstr "Revisione"
-#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:244
+#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:280
msgid "Options"
msgstr "Opzioni"
@@ -599,7 +694,7 @@ msgstr "Crea ramo"
msgid "Create New Branch"
msgstr "Crea nuovo ramo"
-#: lib/branch_create.tcl:31 lib/choose_repository.tcl:371
+#: lib/branch_create.tcl:31 lib/choose_repository.tcl:377
msgid "Create"
msgstr "Crea"
@@ -607,7 +702,7 @@ msgstr "Crea"
msgid "Branch Name"
msgstr "Nome del ramo"
-#: lib/branch_create.tcl:43
+#: lib/branch_create.tcl:43 lib/remote_add.tcl:39 lib/tools_dlg.tcl:50
msgid "Name:"
msgstr "Nome:"
@@ -753,9 +848,9 @@ msgstr "[Directory superiore]"
msgid "Browse Branch Files"
msgstr "Esplora i file del ramo"
-#: lib/browser.tcl:278 lib/choose_repository.tcl:387
-#: lib/choose_repository.tcl:472 lib/choose_repository.tcl:482
-#: lib/choose_repository.tcl:985
+#: lib/browser.tcl:278 lib/choose_repository.tcl:394
+#: lib/choose_repository.tcl:480 lib/choose_repository.tcl:491
+#: lib/choose_repository.tcl:995
msgid "Browse"
msgstr "Esplora"
@@ -770,6 +865,7 @@ msgid "fatal: Cannot resolve %s"
msgstr "errore grave: impossibile risolvere %s"
#: lib/checkout_op.tcl:145 lib/console.tcl:81 lib/database.tcl:31
+#: lib/sshkey.tcl:53
msgid "Close"
msgstr "Chiudi"
@@ -883,7 +979,7 @@ msgstr "Ricomporre le revisioni perdute potrebbe non essere semplice."
msgid "Reset '%s'?"
msgstr "Ripristinare '%s'?"
-#: lib/checkout_op.tcl:532 lib/merge.tcl:163
+#: lib/checkout_op.tcl:532 lib/merge.tcl:164 lib/tools_dlg.tcl:343
msgid "Visualize"
msgstr "Visualizza"
@@ -933,226 +1029,230 @@ msgstr ""
msgid "Git Gui"
msgstr "Git Gui"
-#: lib/choose_repository.tcl:81 lib/choose_repository.tcl:376
+#: lib/choose_repository.tcl:87 lib/choose_repository.tcl:382
msgid "Create New Repository"
msgstr "Crea nuovo archivio"
-#: lib/choose_repository.tcl:87
+#: lib/choose_repository.tcl:93
msgid "New..."
msgstr "Nuovo..."
-#: lib/choose_repository.tcl:94 lib/choose_repository.tcl:458
+#: lib/choose_repository.tcl:100 lib/choose_repository.tcl:465
msgid "Clone Existing Repository"
msgstr "Clona archivio esistente"
-#: lib/choose_repository.tcl:100
+#: lib/choose_repository.tcl:106
msgid "Clone..."
msgstr "Clona..."
-#: lib/choose_repository.tcl:107 lib/choose_repository.tcl:974
+#: lib/choose_repository.tcl:113 lib/choose_repository.tcl:983
msgid "Open Existing Repository"
msgstr "Apri archivio esistente"
-#: lib/choose_repository.tcl:113
+#: lib/choose_repository.tcl:119
msgid "Open..."
msgstr "Apri..."
-#: lib/choose_repository.tcl:126
+#: lib/choose_repository.tcl:132
msgid "Recent Repositories"
msgstr "Archivi recenti"
-#: lib/choose_repository.tcl:132
+#: lib/choose_repository.tcl:138
msgid "Open Recent Repository:"
msgstr "Apri archivio recente:"
-#: lib/choose_repository.tcl:296 lib/choose_repository.tcl:303
-#: lib/choose_repository.tcl:310
+#: lib/choose_repository.tcl:302 lib/choose_repository.tcl:309
+#: lib/choose_repository.tcl:316
#, tcl-format
msgid "Failed to create repository %s:"
msgstr "Impossibile creare l'archivio %s:"
-#: lib/choose_repository.tcl:381 lib/choose_repository.tcl:476
+#: lib/choose_repository.tcl:387
msgid "Directory:"
msgstr "Directory:"
-#: lib/choose_repository.tcl:410 lib/choose_repository.tcl:535
-#: lib/choose_repository.tcl:1007
+#: lib/choose_repository.tcl:417 lib/choose_repository.tcl:544
+#: lib/choose_repository.tcl:1017
msgid "Git Repository"
msgstr "Archivio Git"
-#: lib/choose_repository.tcl:435
+#: lib/choose_repository.tcl:442
#, tcl-format
msgid "Directory %s already exists."
msgstr "La directory %s esiste già."
-#: lib/choose_repository.tcl:439
+#: lib/choose_repository.tcl:446
#, tcl-format
msgid "File %s already exists."
msgstr "Il file %s esiste già."
-#: lib/choose_repository.tcl:453
+#: lib/choose_repository.tcl:460
msgid "Clone"
msgstr "Clona"
-#: lib/choose_repository.tcl:466
-msgid "URL:"
-msgstr "URL:"
+#: lib/choose_repository.tcl:473
+msgid "Source Location:"
+msgstr "Posizione sorgente:"
-#: lib/choose_repository.tcl:487
+#: lib/choose_repository.tcl:484
+msgid "Target Directory:"
+msgstr "Directory di destinazione:"
+
+#: lib/choose_repository.tcl:496
msgid "Clone Type:"
msgstr "Tipo di clone:"
-#: lib/choose_repository.tcl:493
+#: lib/choose_repository.tcl:502
msgid "Standard (Fast, Semi-Redundant, Hardlinks)"
msgstr "Standard (veloce, semi-ridondante, con hardlink)"
-#: lib/choose_repository.tcl:499
+#: lib/choose_repository.tcl:508
msgid "Full Copy (Slower, Redundant Backup)"
msgstr "Copia completa (più lento, backup ridondante)"
-#: lib/choose_repository.tcl:505
+#: lib/choose_repository.tcl:514
msgid "Shared (Fastest, Not Recommended, No Backup)"
msgstr "Shared (il più veloce, non raccomandato, nessun backup)"
-#: lib/choose_repository.tcl:541 lib/choose_repository.tcl:588
-#: lib/choose_repository.tcl:734 lib/choose_repository.tcl:804
-#: lib/choose_repository.tcl:1013 lib/choose_repository.tcl:1021
+#: lib/choose_repository.tcl:550 lib/choose_repository.tcl:597
+#: lib/choose_repository.tcl:743 lib/choose_repository.tcl:813
+#: lib/choose_repository.tcl:1023 lib/choose_repository.tcl:1031
#, tcl-format
msgid "Not a Git repository: %s"
msgstr "%s non è un archivio Git."
-#: lib/choose_repository.tcl:577
+#: lib/choose_repository.tcl:586
msgid "Standard only available for local repository."
msgstr "Standard è disponibile solo per archivi locali."
-#: lib/choose_repository.tcl:581
+#: lib/choose_repository.tcl:590
msgid "Shared only available for local repository."
msgstr "Shared è disponibile solo per archivi locali."
-#: lib/choose_repository.tcl:602
+#: lib/choose_repository.tcl:611
#, tcl-format
msgid "Location %s already exists."
msgstr "Il file/directory %s esiste già."
-#: lib/choose_repository.tcl:613
+#: lib/choose_repository.tcl:622
msgid "Failed to configure origin"
msgstr "Impossibile configurare origin"
-#: lib/choose_repository.tcl:625
+#: lib/choose_repository.tcl:634
msgid "Counting objects"
msgstr "Calcolo oggetti"
-#: lib/choose_repository.tcl:626
+#: lib/choose_repository.tcl:635
msgid "buckets"
msgstr ""
-#: lib/choose_repository.tcl:650
+#: lib/choose_repository.tcl:659
#, tcl-format
msgid "Unable to copy objects/info/alternates: %s"
msgstr "Impossibile copiare oggetti/info/alternate: %s"
-#: lib/choose_repository.tcl:686
+#: lib/choose_repository.tcl:695
#, tcl-format
msgid "Nothing to clone from %s."
msgstr "Niente da clonare da %s."
-#: lib/choose_repository.tcl:688 lib/choose_repository.tcl:902
-#: lib/choose_repository.tcl:914
+#: lib/choose_repository.tcl:697 lib/choose_repository.tcl:911
+#: lib/choose_repository.tcl:923
msgid "The 'master' branch has not been initialized."
msgstr "Il ramo 'master' non è stato inizializzato."
-#: lib/choose_repository.tcl:701
+#: lib/choose_repository.tcl:710
msgid "Hardlinks are unavailable. Falling back to copying."
msgstr "Impossibile utilizzare gli hardlink. Si ricorrerà alla copia."
-#: lib/choose_repository.tcl:713
+#: lib/choose_repository.tcl:722
#, tcl-format
msgid "Cloning from %s"
msgstr "Clonazione da %s"
-#: lib/choose_repository.tcl:744
+#: lib/choose_repository.tcl:753
msgid "Copying objects"
msgstr "Copia degli oggetti"
-#: lib/choose_repository.tcl:745
+#: lib/choose_repository.tcl:754
msgid "KiB"
msgstr "KiB"
-#: lib/choose_repository.tcl:769
+#: lib/choose_repository.tcl:778
#, tcl-format
msgid "Unable to copy object: %s"
msgstr "Impossibile copiare oggetto: %s"
-#: lib/choose_repository.tcl:779
+#: lib/choose_repository.tcl:788
msgid "Linking objects"
msgstr "Collegamento oggetti"
-#: lib/choose_repository.tcl:780
+#: lib/choose_repository.tcl:789
msgid "objects"
msgstr "oggetti"
-#: lib/choose_repository.tcl:788
+#: lib/choose_repository.tcl:797
#, tcl-format
msgid "Unable to hardlink object: %s"
msgstr "Hardlink impossibile sull'oggetto: %s"
-#: lib/choose_repository.tcl:843
+#: lib/choose_repository.tcl:852
msgid "Cannot fetch branches and objects. See console output for details."
msgstr ""
"Impossibile recuperare rami e oggetti. Controllare i dettagli forniti dalla "
"console."
-#: lib/choose_repository.tcl:854
+#: lib/choose_repository.tcl:863
msgid "Cannot fetch tags. See console output for details."
msgstr ""
"Impossibile recuperare le etichette. Controllare i dettagli forniti dalla "
"console."
-#: lib/choose_repository.tcl:878
+#: lib/choose_repository.tcl:887
msgid "Cannot determine HEAD. See console output for details."
msgstr ""
"Impossibile determinare HEAD. Controllare i dettagli forniti dalla console."
-#: lib/choose_repository.tcl:887
+#: lib/choose_repository.tcl:896
#, tcl-format
msgid "Unable to cleanup %s"
msgstr "Impossibile ripulire %s"
-#: lib/choose_repository.tcl:893
+#: lib/choose_repository.tcl:902
msgid "Clone failed."
msgstr "Clonazione non riuscita."
-#: lib/choose_repository.tcl:900
+#: lib/choose_repository.tcl:909
msgid "No default branch obtained."
msgstr "Non è stato trovato un ramo predefinito."
-#: lib/choose_repository.tcl:911
+#: lib/choose_repository.tcl:920
#, tcl-format
msgid "Cannot resolve %s as a commit."
msgstr "Impossibile risolvere %s come una revisione."
-#: lib/choose_repository.tcl:923
+#: lib/choose_repository.tcl:932
msgid "Creating working directory"
msgstr "Creazione directory di lavoro"
-#: lib/choose_repository.tcl:924 lib/index.tcl:65 lib/index.tcl:127
-#: lib/index.tcl:193
+#: lib/choose_repository.tcl:933 lib/index.tcl:65 lib/index.tcl:128
+#: lib/index.tcl:196
msgid "files"
msgstr "file"
-#: lib/choose_repository.tcl:953
+#: lib/choose_repository.tcl:962
msgid "Initial file checkout failed."
msgstr "Attivazione iniziale non riuscita."
-#: lib/choose_repository.tcl:969
+#: lib/choose_repository.tcl:978
msgid "Open"
msgstr "Apri"
-#: lib/choose_repository.tcl:979
+#: lib/choose_repository.tcl:988
msgid "Repository:"
msgstr "Archivio:"
-#: lib/choose_repository.tcl:1027
+#: lib/choose_repository.tcl:1037
#, tcl-format
msgid "Failed to open repository %s:"
msgstr "Impossibile accedere all'archivio %s:"
@@ -1224,19 +1324,19 @@ msgstr ""
"completata. Non puoi correggere la revisione precedente a meno che prima tu "
"non interrompa l'operazione di fusione in corso.\n"
-#: lib/commit.tcl:49
+#: lib/commit.tcl:48
msgid "Error loading commit data for amend:"
msgstr "Errore durante il caricamento dei dati della revisione da correggere:"
-#: lib/commit.tcl:76
+#: lib/commit.tcl:75
msgid "Unable to obtain your identity:"
msgstr "Impossibile ottenere la tua identità:"
-#: lib/commit.tcl:81
+#: lib/commit.tcl:80
msgid "Invalid GIT_COMMITTER_IDENT:"
msgstr "GIT_COMMITTER_IDENT non valida:"
-#: lib/commit.tcl:133
+#: lib/commit.tcl:132
msgid ""
"Last scanned state does not match repository state.\n"
"\n"
@@ -1253,7 +1353,7 @@ msgstr ""
"\n"
"La nuova analisi comincerà ora.\n"
-#: lib/commit.tcl:154
+#: lib/commit.tcl:155
#, tcl-format
msgid ""
"Unmerged files cannot be committed.\n"
@@ -1266,7 +1366,7 @@ msgstr ""
"Il file %s presenta dei conflitti. Devi risolverli e preparare il file per "
"creare una nuova revisione prima di effettuare questa azione.\n"
-#: lib/commit.tcl:162
+#: lib/commit.tcl:163
#, tcl-format
msgid ""
"Unknown file state %s detected.\n"
@@ -1277,7 +1377,7 @@ msgstr ""
"\n"
"Questo programma non può creare una revisione contenente il file %s.\n"
-#: lib/commit.tcl:170
+#: lib/commit.tcl:171
msgid ""
"No changes to commit.\n"
"\n"
@@ -1288,7 +1388,7 @@ msgstr ""
"Devi preparare per una nuova revisione almeno 1 file prima di effettuare "
"questa operazione.\n"
-#: lib/commit.tcl:183
+#: lib/commit.tcl:186
msgid ""
"Please supply a commit message.\n"
"\n"
@@ -1306,45 +1406,45 @@ msgstr ""
"- Seconda linea: vuota.\n"
"- Terza linea: spiega a cosa serve la tua modifica.\n"
-#: lib/commit.tcl:207
+#: lib/commit.tcl:210
#, tcl-format
msgid "warning: Tcl does not support encoding '%s'."
msgstr "attenzione: Tcl non supporta la codifica '%s'."
-#: lib/commit.tcl:221
+#: lib/commit.tcl:226
msgid "Calling pre-commit hook..."
msgstr "Avvio pre-commit hook..."
-#: lib/commit.tcl:236
+#: lib/commit.tcl:241
msgid "Commit declined by pre-commit hook."
msgstr "Revisione rifiutata dal pre-commit hook."
-#: lib/commit.tcl:259
+#: lib/commit.tcl:264
msgid "Calling commit-msg hook..."
msgstr "Avvio commit-msg hook..."
-#: lib/commit.tcl:274
+#: lib/commit.tcl:279
msgid "Commit declined by commit-msg hook."
msgstr "Revisione rifiutata dal commit-msg hook."
-#: lib/commit.tcl:287
+#: lib/commit.tcl:292
msgid "Committing changes..."
msgstr "Archiviazione modifiche..."
-#: lib/commit.tcl:303
+#: lib/commit.tcl:308
msgid "write-tree failed:"
msgstr "write-tree non riuscito:"
-#: lib/commit.tcl:304 lib/commit.tcl:348 lib/commit.tcl:368
+#: lib/commit.tcl:309 lib/commit.tcl:353 lib/commit.tcl:373
msgid "Commit failed."
msgstr "Impossibile creare una nuova revisione."
-#: lib/commit.tcl:321
+#: lib/commit.tcl:326
#, tcl-format
msgid "Commit %s appears to be corrupt"
msgstr "La revisione %s sembra essere danneggiata"
-#: lib/commit.tcl:326
+#: lib/commit.tcl:331
msgid ""
"No changes to commit.\n"
"\n"
@@ -1358,19 +1458,19 @@ msgstr ""
"\n"
"Si procederà subito ad una nuova analisi.\n"
-#: lib/commit.tcl:333
+#: lib/commit.tcl:338
msgid "No changes to commit."
msgstr "Nessuna modifica per la nuova revisione."
-#: lib/commit.tcl:347
+#: lib/commit.tcl:352
msgid "commit-tree failed:"
msgstr "commit-tree non riuscito:"
-#: lib/commit.tcl:367
+#: lib/commit.tcl:372
msgid "update-ref failed:"
msgstr "update-ref non riuscito:"
-#: lib/commit.tcl:454
+#: lib/commit.tcl:460
#, tcl-format
msgid "Created commit %s: %s"
msgstr "Creata revisione %s: %s"
@@ -1445,7 +1545,7 @@ msgstr ""
msgid "Invalid date from Git: %s"
msgstr "Git ha restituito una data non valida: %s"
-#: lib/diff.tcl:44
+#: lib/diff.tcl:59
#, tcl-format
msgid ""
"No differences detected.\n"
@@ -1468,48 +1568,101 @@ msgstr ""
"Si procederà automaticamente ad una nuova analisi per trovare altri file che "
"potrebbero avere lo stesso stato."
-#: lib/diff.tcl:83
+#: lib/diff.tcl:99
#, tcl-format
msgid "Loading diff of %s..."
msgstr "Caricamento delle differenze di %s..."
-#: lib/diff.tcl:116 lib/diff.tcl:190
+#: lib/diff.tcl:120
+msgid ""
+"LOCAL: deleted\n"
+"REMOTE:\n"
+msgstr ""
+"LOCALE: cancellato\n"
+"REMOTO:\n"
+
+#: lib/diff.tcl:125
+msgid ""
+"REMOTE: deleted\n"
+"LOCAL:\n"
+msgstr ""
+"REMOTO: cancellato\n"
+"LOCALE:\n"
+
+#: lib/diff.tcl:132
+msgid "LOCAL:\n"
+msgstr "LOCALE:\n"
+
+#: lib/diff.tcl:135
+msgid "REMOTE:\n"
+msgstr "REMOTO:\n"
+
+#: lib/diff.tcl:197 lib/diff.tcl:296
#, tcl-format
msgid "Unable to display %s"
msgstr "Impossibile visualizzare %s"
-#: lib/diff.tcl:117
+#: lib/diff.tcl:198
msgid "Error loading file:"
msgstr "Errore nel caricamento del file:"
-#: lib/diff.tcl:124
+#: lib/diff.tcl:205
msgid "Git Repository (subproject)"
msgstr "Archivio Git (sottoprogetto)"
-#: lib/diff.tcl:136
+#: lib/diff.tcl:217
msgid "* Binary file (not showing content)."
msgstr "* File binario (il contenuto non sarà mostrato)."
-#: lib/diff.tcl:191
-msgid "Error loading diff:"
-msgstr "Errore nel caricamento delle differenze:"
+#: lib/diff.tcl:222
+#, tcl-format
+msgid ""
+"* Untracked file is %d bytes.\n"
+"* Showing only first %d bytes.\n"
+msgstr ""
+"* Il file non tracciato è di %d byte.\n"
+"* Saranno visualizzati solo i primi %d byte.\n"
+
+#: lib/diff.tcl:228
+#, tcl-format
+msgid ""
+"\n"
+"* Untracked file clipped here by %s.\n"
+"* To see the entire file, use an external editor.\n"
+msgstr ""
+"\n"
+"* %s non visualizza completamente questo file non tracciato.\n"
+"* Per visualizzare il file completo, usare un programma esterno.\n"
-#: lib/diff.tcl:313
+#: lib/diff.tcl:436
msgid "Failed to unstage selected hunk."
msgstr "Impossibile rimuovere la sezione scelta dalla nuova revisione."
-#: lib/diff.tcl:320
+#: lib/diff.tcl:443
msgid "Failed to stage selected hunk."
msgstr "Impossibile preparare la sezione scelta per una nuova revisione."
-#: lib/diff.tcl:386
+#: lib/diff.tcl:509
msgid "Failed to unstage selected line."
msgstr "Impossibile rimuovere la riga scelta dalla nuova revisione."
-#: lib/diff.tcl:394
+#: lib/diff.tcl:517
msgid "Failed to stage selected line."
msgstr "Impossibile preparare la riga scelta per una nuova revisione."
+#: lib/encoding.tcl:443
+msgid "Default"
+msgstr "Predefinito"
+
+#: lib/encoding.tcl:448
+#, tcl-format
+msgid "System (%s)"
+msgstr "Codifica di sistema (%s)"
+
+#: lib/encoding.tcl:459 lib/encoding.tcl:465
+msgid "Other"
+msgstr "Altro"
+
#: lib/error.tcl:20 lib/error.tcl:114
msgid "error"
msgstr "errore"
@@ -1547,40 +1700,49 @@ msgstr "Continua"
msgid "Unlock Index"
msgstr "Sblocca l'accesso all'indice"
-#: lib/index.tcl:282
+#: lib/index.tcl:287
#, tcl-format
msgid "Unstaging %s from commit"
msgstr "%s non farà parte della prossima revisione"
-#: lib/index.tcl:313
+#: lib/index.tcl:326
msgid "Ready to commit."
msgstr "Pronto per creare una nuova revisione."
-#: lib/index.tcl:326
+#: lib/index.tcl:339
#, tcl-format
msgid "Adding %s"
msgstr "Aggiunta di %s in corso"
-#: lib/index.tcl:381
+#: lib/index.tcl:396
#, tcl-format
msgid "Revert changes in file %s?"
msgstr "Annullare le modifiche nel file %s?"
-#: lib/index.tcl:383
+#: lib/index.tcl:398
#, tcl-format
msgid "Revert changes in these %i files?"
msgstr "Annullare le modifiche in questi %i file?"
-#: lib/index.tcl:391
+#: lib/index.tcl:406
msgid "Any unstaged changes will be permanently lost by the revert."
msgstr ""
"Tutte le modifiche non preparate per una nuova revisione saranno perse per "
"sempre."
-#: lib/index.tcl:394
+#: lib/index.tcl:409
msgid "Do Nothing"
msgstr "Non fare niente"
+#: lib/index.tcl:427
+msgid "Reverting selected files"
+msgstr "Annullo le modifiche nei file selezionati"
+
+#: lib/index.tcl:431
+#, tcl-format
+msgid "Reverting %s"
+msgstr "Annullo le modifiche in %s"
+
#: lib/merge.tcl:13
msgid ""
"Cannot merge while amending.\n"
@@ -1608,7 +1770,7 @@ msgstr ""
"\n"
"La nuova analisi comincerà ora.\n"
-#: lib/merge.tcl:44
+#: lib/merge.tcl:45
#, tcl-format
msgid ""
"You are in the middle of a conflicted merge.\n"
@@ -1626,7 +1788,7 @@ msgstr ""
"infine crearla per completare la fusione attuale. Solo a questo punto potrai "
"iniziare un'altra fusione.\n"
-#: lib/merge.tcl:54
+#: lib/merge.tcl:55
#, tcl-format
msgid ""
"You are in the middle of a change.\n"
@@ -1644,34 +1806,34 @@ msgstr ""
"una fusione. In questo modo sarà più facile interrompere una fusione non "
"riuscita, nel caso ce ne fosse bisogno.\n"
-#: lib/merge.tcl:106
+#: lib/merge.tcl:107
#, tcl-format
msgid "%s of %s"
msgstr "%s di %s"
-#: lib/merge.tcl:119
+#: lib/merge.tcl:120
#, tcl-format
msgid "Merging %s and %s..."
msgstr "Fusione di %s e %s in corso..."
-#: lib/merge.tcl:130
+#: lib/merge.tcl:131
msgid "Merge completed successfully."
msgstr "Fusione completata con successo."
-#: lib/merge.tcl:132
+#: lib/merge.tcl:133
msgid "Merge failed. Conflict resolution is required."
msgstr "Fusione non riuscita. Bisogna risolvere i conflitti."
-#: lib/merge.tcl:157
+#: lib/merge.tcl:158
#, tcl-format
msgid "Merge Into %s"
msgstr "Fusione in %s"
-#: lib/merge.tcl:176
+#: lib/merge.tcl:177
msgid "Revision To Merge"
msgstr "Revisione da fondere"
-#: lib/merge.tcl:211
+#: lib/merge.tcl:212
msgid ""
"Cannot abort while amending.\n"
"\n"
@@ -1681,7 +1843,7 @@ msgstr ""
"\n"
"Bisogna finire di correggere questa revisione.\n"
-#: lib/merge.tcl:221
+#: lib/merge.tcl:222
msgid ""
"Abort merge?\n"
"\n"
@@ -1696,7 +1858,7 @@ msgstr ""
"\n"
"Continuare con l'interruzione della fusione attuale?"
-#: lib/merge.tcl:227
+#: lib/merge.tcl:228
msgid ""
"Reset changes?\n"
"\n"
@@ -1704,151 +1866,352 @@ msgid ""
"\n"
"Continue with resetting the current changes?"
msgstr ""
-"Ripristinare la revisione corrente e annullare le modifiche?\n"
+"Ripristinare la revisione attuale e annullare le modifiche?\n"
"\n"
"L'annullamento delle modifiche causerà la perdita di *TUTTE* le modifiche "
"non ancora presenti nell'archivio.\n"
"\n"
"Continuare con l'annullamento delle modifiche attuali?"
-#: lib/merge.tcl:238
+#: lib/merge.tcl:239
msgid "Aborting"
msgstr "Interruzione"
-#: lib/merge.tcl:238
+#: lib/merge.tcl:239
msgid "files reset"
msgstr "ripristino file"
-#: lib/merge.tcl:266
+#: lib/merge.tcl:267
msgid "Abort failed."
msgstr "Interruzione non riuscita."
-#: lib/merge.tcl:268
+#: lib/merge.tcl:269
msgid "Abort completed. Ready."
msgstr "Interruzione completata. Pronto."
-#: lib/option.tcl:95
+#: lib/mergetool.tcl:8
+msgid "Force resolution to the base version?"
+msgstr "Imporre la risoluzione alla revisione comune?"
+
+#: lib/mergetool.tcl:9
+msgid "Force resolution to this branch?"
+msgstr "Imporre la risoluzione al ramo attuale?"
+
+#: lib/mergetool.tcl:10
+msgid "Force resolution to the other branch?"
+msgstr "Imporre la risoluzione all'altro ramo?"
+
+#: lib/mergetool.tcl:14
+#, tcl-format
+msgid ""
+"Note that the diff shows only conflicting changes.\n"
+"\n"
+"%s will be overwritten.\n"
+"\n"
+"This operation can be undone only by restarting the merge."
+msgstr ""
+"Si stanno mostrando solo le modifiche con conflitti.\n"
+"\n"
+"%s sarà sovrascritto.\n"
+"\n"
+"Questa operazione può essere modificata solo ricominciando la fusione."
+
+#: lib/mergetool.tcl:45
+#, tcl-format
+msgid "File %s seems to have unresolved conflicts, still stage?"
+msgstr ""
+"Il file %s sembra contenere conflitti non risolti, preparare per la prossima "
+"revisione?"
+
+#: lib/mergetool.tcl:60
+#, tcl-format
+msgid "Adding resolution for %s"
+msgstr ""
+"La risoluzione dei conflitti per %s è preparata per la prossima revisione"
+
+#: lib/mergetool.tcl:141
+msgid "Cannot resolve deletion or link conflicts using a tool"
+msgstr ""
+"Non è possibile risolvere i conflitti per cancellazioni o link con un "
+"programma esterno"
+
+#: lib/mergetool.tcl:146
+msgid "Conflict file does not exist"
+msgstr "Non esiste un file con conflitti."
+
+#: lib/mergetool.tcl:264
+#, tcl-format
+msgid "Not a GUI merge tool: '%s'"
+msgstr "'%s' non è una GUI per la risoluzione dei conflitti."
+
+#: lib/mergetool.tcl:268
+#, tcl-format
+msgid "Unsupported merge tool '%s'"
+msgstr "Il programma '%s' non è supportato"
+
+#: lib/mergetool.tcl:303
+msgid "Merge tool is already running, terminate it?"
+msgstr "La risoluzione dei conflitti è già avviata, terminarla?"
+
+#: lib/mergetool.tcl:323
+#, tcl-format
+msgid ""
+"Error retrieving versions:\n"
+"%s"
+msgstr ""
+"Errore: revisione non trovata:\n"
+"%s"
+
+#: lib/mergetool.tcl:343
+#, tcl-format
+msgid ""
+"Could not start the merge tool:\n"
+"\n"
+"%s"
+msgstr ""
+"Impossibile avviare la risoluzione dei conflitti:\n"
+"\n"
+"%s"
+
+#: lib/mergetool.tcl:347
+msgid "Running merge tool..."
+msgstr "Avvio del programma per la risoluzione dei conflitti in corso..."
+
+#: lib/mergetool.tcl:375 lib/mergetool.tcl:383
+msgid "Merge tool failed."
+msgstr "Risoluzione dei conflitti non riuscita."
+
+#: lib/option.tcl:11
+#, tcl-format
+msgid "Invalid global encoding '%s'"
+msgstr ""
+"La codifica dei caratteri '%s' specificata per tutti gli archivi non è valida"
+
+#: lib/option.tcl:19
+#, tcl-format
+msgid "Invalid repo encoding '%s'"
+msgstr ""
+"La codifica dei caratteri '%s' specificata per l'archivio attuale non è "
+"valida"
+
+#: lib/option.tcl:117
msgid "Restore Defaults"
msgstr "Ripristina valori predefiniti"
-#: lib/option.tcl:99
+#: lib/option.tcl:121
msgid "Save"
msgstr "Salva"
-#: lib/option.tcl:109
+#: lib/option.tcl:131
#, tcl-format
msgid "%s Repository"
msgstr "Archivio di %s"
-#: lib/option.tcl:110
+#: lib/option.tcl:132
msgid "Global (All Repositories)"
msgstr "Tutti gli archivi"
-#: lib/option.tcl:116
+#: lib/option.tcl:138
msgid "User Name"
msgstr "Nome utente"
-#: lib/option.tcl:117
+#: lib/option.tcl:139
msgid "Email Address"
msgstr "Indirizzo Email"
-#: lib/option.tcl:119
+#: lib/option.tcl:141
msgid "Summarize Merge Commits"
msgstr "Riepilogo nelle revisioni di fusione"
-#: lib/option.tcl:120
+#: lib/option.tcl:142
msgid "Merge Verbosity"
msgstr "Prolissità della fusione"
-#: lib/option.tcl:121
+#: lib/option.tcl:143
msgid "Show Diffstat After Merge"
msgstr "Mostra statistiche delle differenze dopo la fusione"
-#: lib/option.tcl:123
+#: lib/option.tcl:144
+msgid "Use Merge Tool"
+msgstr "Programma da utilizzare per la risoluzione dei conflitti"
+
+#: lib/option.tcl:146
msgid "Trust File Modification Timestamps"
msgstr "Fidati delle date di modifica dei file"
-#: lib/option.tcl:124
+#: lib/option.tcl:147
msgid "Prune Tracking Branches During Fetch"
msgstr ""
"Effettua potatura dei duplicati locali di rami remoti durante il recupero"
-#: lib/option.tcl:125
+#: lib/option.tcl:148
msgid "Match Tracking Branches"
msgstr "Appaia duplicati locali di rami remoti"
-#: lib/option.tcl:126
+#: lib/option.tcl:149
msgid "Blame Copy Only On Changed Files"
msgstr "Ricerca copie solo nei file modificati"
-#: lib/option.tcl:127
+#: lib/option.tcl:150
msgid "Minimum Letters To Blame Copy On"
msgstr "Numero minimo di lettere che attivano la ricerca delle copie"
-#: lib/option.tcl:128
+#: lib/option.tcl:151
+msgid "Blame History Context Radius (days)"
+msgstr "Giorni di contesto nella cronologia delle annotazioni"
+
+#: lib/option.tcl:152
msgid "Number of Diff Context Lines"
msgstr "Numero di linee di contesto nelle differenze"
-#: lib/option.tcl:129
+#: lib/option.tcl:153
msgid "Commit Message Text Width"
msgstr "Larghezza del messaggio di revisione"
-#: lib/option.tcl:130
+#: lib/option.tcl:154
msgid "New Branch Name Template"
msgstr "Modello per il nome di un nuovo ramo"
-#: lib/option.tcl:194
+#: lib/option.tcl:155
+msgid "Default File Contents Encoding"
+msgstr "Codifica predefinita per il contenuto dei file"
+
+#: lib/option.tcl:203
+msgid "Change"
+msgstr "Cambia"
+
+#: lib/option.tcl:230
msgid "Spelling Dictionary:"
msgstr "Lingua dizionario:"
-#: lib/option.tcl:218
+#: lib/option.tcl:254
msgid "Change Font"
msgstr "Cambia caratteri"
-#: lib/option.tcl:222
+#: lib/option.tcl:258
#, tcl-format
msgid "Choose %s"
msgstr "Scegli %s"
-#: lib/option.tcl:228
+#: lib/option.tcl:264
msgid "pt."
msgstr "pt."
-#: lib/option.tcl:242
+#: lib/option.tcl:278
msgid "Preferences"
msgstr "Preferenze"
-#: lib/option.tcl:277
+#: lib/option.tcl:314
msgid "Failed to completely save options:"
msgstr "Impossibile salvare completamente le opzioni:"
-#: lib/remote.tcl:165
+#: lib/remote.tcl:163
+msgid "Remove Remote"
+msgstr "Rimuovi archivio remoto"
+
+#: lib/remote.tcl:168
msgid "Prune from"
msgstr "Effettua potatura da"
-#: lib/remote.tcl:170
+#: lib/remote.tcl:173
msgid "Fetch from"
msgstr "Recupera da"
-#: lib/remote.tcl:213
+#: lib/remote.tcl:215
msgid "Push to"
msgstr "Propaga verso"
+#: lib/remote_add.tcl:19
+msgid "Add Remote"
+msgstr "Aggiungi archivio remoto"
+
+#: lib/remote_add.tcl:24
+msgid "Add New Remote"
+msgstr "Aggiungi nuovo archivio remoto"
+
+#: lib/remote_add.tcl:28 lib/tools_dlg.tcl:36
+msgid "Add"
+msgstr "Aggiungi"
+
+#: lib/remote_add.tcl:37
+msgid "Remote Details"
+msgstr "Dettagli sull'archivio remoto"
+
+#: lib/remote_add.tcl:50
+msgid "Location:"
+msgstr "Posizione:"
+
+#: lib/remote_add.tcl:62
+msgid "Further Action"
+msgstr "Altra azione"
+
+#: lib/remote_add.tcl:65
+msgid "Fetch Immediately"
+msgstr "Recupera subito"
+
+#: lib/remote_add.tcl:71
+msgid "Initialize Remote Repository and Push"
+msgstr "Inizializza l'archivio remoto e propaga"
+
+#: lib/remote_add.tcl:77
+msgid "Do Nothing Else Now"
+msgstr "Non fare altro"
+
+#: lib/remote_add.tcl:101
+msgid "Please supply a remote name."
+msgstr "Inserire un nome per l'archivio remoto."
+
+#: lib/remote_add.tcl:114
+#, tcl-format
+msgid "'%s' is not an acceptable remote name."
+msgstr "'%s' non è utilizzabile come nome di archivio remoto."
+
+#: lib/remote_add.tcl:125
+#, tcl-format
+msgid "Failed to add remote '%s' of location '%s'."
+msgstr "Impossibile aggiungere l'archivio remoto '%s' posto in '%s'."
+
+#: lib/remote_add.tcl:133 lib/transport.tcl:6
+#, tcl-format
+msgid "fetch %s"
+msgstr "recupera da %s"
+
+#: lib/remote_add.tcl:134
+#, tcl-format
+msgid "Fetching the %s"
+msgstr "Recupero %s"
+
+#: lib/remote_add.tcl:157
+#, tcl-format
+msgid "Do not know how to initialize repository at location '%s'."
+msgstr "Impossibile inizializzare l'archivio posto in '%s'."
+
+#: lib/remote_add.tcl:163 lib/transport.tcl:25 lib/transport.tcl:63
+#: lib/transport.tcl:81
+#, tcl-format
+msgid "push %s"
+msgstr "propaga verso %s"
+
+#: lib/remote_add.tcl:164
+#, tcl-format
+msgid "Setting up the %s (at %s)"
+msgstr "Imposto %s (in %s)"
+
#: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34
-msgid "Delete Remote Branch"
-msgstr "Cancella ramo remoto"
+msgid "Delete Branch Remotely"
+msgstr "Elimina ramo remoto"
#: lib/remote_branch_delete.tcl:47
msgid "From Repository"
msgstr "Da archivio"
-#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:123
+#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:134
msgid "Remote:"
msgstr "Remoto:"
-#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:138
-msgid "Arbitrary URL:"
-msgstr "URL specifico:"
+#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:149
+msgid "Arbitrary Location:"
+msgstr "Posizione specifica:"
#: lib/remote_branch_delete.tcl:84
msgid "Branches"
@@ -1918,6 +2281,22 @@ msgstr "Nessun archivio selezionato."
msgid "Scanning %s..."
msgstr "Analisi in corso %s..."
+#: lib/search.tcl:21
+msgid "Find:"
+msgstr "Trova:"
+
+#: lib/search.tcl:23
+msgid "Next"
+msgstr "Succ"
+
+#: lib/search.tcl:24
+msgid "Prev"
+msgstr "Prec"
+
+#: lib/search.tcl:25
+msgid "Case-Sensitive"
+msgstr "Distingui maiuscole"
+
#: lib/shortcut.tcl:20 lib/shortcut.tcl:61
msgid "Cannot write shortcut:"
msgstr "Impossibile scrivere shortcut:"
@@ -1955,23 +2334,189 @@ msgstr "Correttore ortografico non riconosciuto"
msgid "No Suggestions"
msgstr "Nessun suggerimento"
-#: lib/spellcheck.tcl:387
+#: lib/spellcheck.tcl:388
msgid "Unexpected EOF from spell checker"
msgstr "Il correttore ortografico ha mandato un EOF inaspettato"
-#: lib/spellcheck.tcl:391
+#: lib/spellcheck.tcl:392
msgid "Spell Checker Failed"
msgstr "Errore nel correttore ortografico"
+#: lib/sshkey.tcl:31
+msgid "No keys found."
+msgstr "Chiavi non trovate."
+
+#: lib/sshkey.tcl:34
+#, tcl-format
+msgid "Found a public key in: %s"
+msgstr "Chiave pubblica trovata in: %s"
+
+#: lib/sshkey.tcl:40
+msgid "Generate Key"
+msgstr "Crea chiave"
+
+#: lib/sshkey.tcl:56
+msgid "Copy To Clipboard"
+msgstr "Copia negli appunti"
+
+#: lib/sshkey.tcl:70
+msgid "Your OpenSSH Public Key"
+msgstr "La tua chiave pubblica OpenSSH"
+
+#: lib/sshkey.tcl:78
+msgid "Generating..."
+msgstr "Creazione chiave in corso..."
+
+#: lib/sshkey.tcl:84
+#, tcl-format
+msgid ""
+"Could not start ssh-keygen:\n"
+"\n"
+"%s"
+msgstr ""
+"Impossibile avviare ssh-keygen:\n"
+"\n"
+"%s"
+
+#: lib/sshkey.tcl:111
+msgid "Generation failed."
+msgstr "Errore durante la creazione della chiave."
+
+#: lib/sshkey.tcl:118
+msgid "Generation succeded, but no keys found."
+msgstr "La chiave è stata creata con successo, ma non è stata trovata."
+
+#: lib/sshkey.tcl:121
+#, tcl-format
+msgid "Your key is in: %s"
+msgstr "La chiave è in: %s"
+
#: lib/status_bar.tcl:83
#, tcl-format
msgid "%s ... %*i of %*i %s (%3i%%)"
msgstr "%1$s ... %6$s: %2$*i di %4$*i (%7$3i%%)"
-#: lib/transport.tcl:6
+#: lib/tools.tcl:75
#, tcl-format
-msgid "fetch %s"
-msgstr "recupera da %s"
+msgid "Running %s requires a selected file."
+msgstr "Bisogna selezionare un file prima di eseguire %s."
+
+#: lib/tools.tcl:90
+#, tcl-format
+msgid "Are you sure you want to run %s?"
+msgstr "Vuoi davvero eseguire %s?"
+
+#: lib/tools.tcl:110
+#, tcl-format
+msgid "Tool: %s"
+msgstr "Strumento: %s"
+
+#: lib/tools.tcl:111
+#, tcl-format
+msgid "Running: %s"
+msgstr "Eseguo: %s"
+
+#: lib/tools.tcl:149
+#, tcl-format
+msgid "Tool completed succesfully: %s"
+msgstr "Il programma esterno è terminato con successo: %s"
+
+#: lib/tools.tcl:151
+#, tcl-format
+msgid "Tool failed: %s"
+msgstr "Il programma esterno ha riportato un errore: %s"
+
+#: lib/tools_dlg.tcl:22
+msgid "Add Tool"
+msgstr "Aggiungi strumento"
+
+#: lib/tools_dlg.tcl:28
+msgid "Add New Tool Command"
+msgstr "Aggiungi un nuovo comando"
+
+#: lib/tools_dlg.tcl:33
+msgid "Add globally"
+msgstr "Aggiungi per tutti gli archivi"
+
+#: lib/tools_dlg.tcl:45
+msgid "Tool Details"
+msgstr "Dettagli sullo strumento"
+
+#: lib/tools_dlg.tcl:48
+msgid "Use '/' separators to create a submenu tree:"
+msgstr "Utilizza il separatore '/' per creare un albero di sottomenu:"
+
+#: lib/tools_dlg.tcl:61
+msgid "Command:"
+msgstr "Comando:"
+
+#: lib/tools_dlg.tcl:74
+msgid "Show a dialog before running"
+msgstr "Mostra una finestra di dialogo prima dell'avvio"
+
+#: lib/tools_dlg.tcl:80
+msgid "Ask the user to select a revision (sets $REVISION)"
+msgstr "Chiedi all'utente di scegliere una revisione (imposta $REVISION)"
+
+#: lib/tools_dlg.tcl:85
+msgid "Ask the user for additional arguments (sets $ARGS)"
+msgstr "Chiedi all'utente di fornire argomenti aggiuntivi (imposta $ARGS)"
+
+#: lib/tools_dlg.tcl:92
+msgid "Don't show the command output window"
+msgstr "Non mostrare la finestra di comando"
+
+#: lib/tools_dlg.tcl:97
+msgid "Run only if a diff is selected ($FILENAME not empty)"
+msgstr "Avvia solo se è selezionata una differenza ($FILENAME non è vuoto)"
+
+#: lib/tools_dlg.tcl:121
+msgid "Please supply a name for the tool."
+msgstr "Bisogna dare un nome allo strumento."
+
+#: lib/tools_dlg.tcl:129
+#, tcl-format
+msgid "Tool '%s' already exists."
+msgstr "Lo strumento '%s' esiste già."
+
+#: lib/tools_dlg.tcl:151
+#, tcl-format
+msgid ""
+"Could not add tool:\n"
+"%s"
+msgstr ""
+"Impossibile aggiungere lo strumento:\n"
+"\n"
+"%s"
+
+#: lib/tools_dlg.tcl:190
+msgid "Remove Tool"
+msgstr "Rimuovi strumento"
+
+#: lib/tools_dlg.tcl:196
+msgid "Remove Tool Commands"
+msgstr "Rimuovi i comandi dello strumento"
+
+#: lib/tools_dlg.tcl:200
+msgid "Remove"
+msgstr "Rimuovi"
+
+#: lib/tools_dlg.tcl:236
+msgid "(Blue denotes repository-local tools)"
+msgstr "(Il colore blu indica strumenti per l'archivio locale)"
+
+#: lib/tools_dlg.tcl:297
+#, tcl-format
+msgid "Run Command: %s"
+msgstr "Avvia il comando: %s"
+
+#: lib/tools_dlg.tcl:311
+msgid "Arguments"
+msgstr "Argomenti"
+
+#: lib/tools_dlg.tcl:348
+msgid "OK"
+msgstr "OK"
#: lib/transport.tcl:7
#, tcl-format
@@ -1988,45 +2533,45 @@ msgstr "potatura remota di %s"
msgid "Pruning tracking branches deleted from %s"
msgstr "Effettua potatura dei duplicati locali di rami remoti cancellati da %s"
-#: lib/transport.tcl:25 lib/transport.tcl:71
-#, tcl-format
-msgid "push %s"
-msgstr "propaga verso %s"
-
#: lib/transport.tcl:26
#, tcl-format
msgid "Pushing changes to %s"
msgstr "Propagazione modifiche a %s"
-#: lib/transport.tcl:72
+#: lib/transport.tcl:64
+#, tcl-format
+msgid "Mirroring to %s"
+msgstr "Mirroring verso %s"
+
+#: lib/transport.tcl:82
#, tcl-format
msgid "Pushing %s %s to %s"
msgstr "Propagazione %s %s a %s"
-#: lib/transport.tcl:89
+#: lib/transport.tcl:100
msgid "Push Branches"
msgstr "Propaga rami"
-#: lib/transport.tcl:103
+#: lib/transport.tcl:114
msgid "Source Branches"
msgstr "Rami di origine"
-#: lib/transport.tcl:120
+#: lib/transport.tcl:131
msgid "Destination Repository"
msgstr "Archivio di destinazione"
-#: lib/transport.tcl:158
+#: lib/transport.tcl:169
msgid "Transfer Options"
msgstr "Opzioni di trasferimento"
-#: lib/transport.tcl:160
+#: lib/transport.tcl:171
msgid "Force overwrite existing branch (may discard changes)"
msgstr "Sovrascrivi ramo esistente (alcune modifiche potrebbero essere perse)"
-#: lib/transport.tcl:164
+#: lib/transport.tcl:175
msgid "Use thin pack (for slow network connections)"
msgstr "Utilizza 'thin pack' (per connessioni lente)"
-#: lib/transport.tcl:168
+#: lib/transport.tcl:179
msgid "Include tags"
msgstr "Includi etichette"
diff --git a/git-gui/po/ja.po b/git-gui/po/ja.po
index 5db44a4ada..09d60bef74 100644
--- a/git-gui/po/ja.po
+++ b/git-gui/po/ja.po
@@ -8,41 +8,41 @@ msgid ""
msgstr ""
"Project-Id-Version: git-gui\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-08-02 14:45-0700\n"
-"PO-Revision-Date: 2008-08-03 17:00+0900\n"
+"POT-Creation-Date: 2008-12-08 08:31-0800\n"
+"PO-Revision-Date: 2008-12-09 06:27+0900\n"
"Last-Translator: ã—らã„ã— ãªãªã“ <nanako3@lavabit.com>\n"
"Language-Team: Japanese\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: git-gui.sh:41 git-gui.sh:688 git-gui.sh:702 git-gui.sh:715 git-gui.sh:798
-#: git-gui.sh:817
+#: git-gui.sh:41 git-gui.sh:737 git-gui.sh:751 git-gui.sh:764 git-gui.sh:847
+#: git-gui.sh:866
msgid "git-gui: fatal error"
msgstr "git-gui: 致命的ãªã‚¨ãƒ©ãƒ¼"
-#: git-gui.sh:644
+#: git-gui.sh:689
#, tcl-format
msgid "Invalid font specified in %s:"
msgstr "%s ã«ç„¡åŠ¹ãªãƒ•ã‚©ãƒ³ãƒˆãŒæŒ‡å®šã•ã‚Œã¦ã„ã¾ã™:"
-#: git-gui.sh:674
+#: git-gui.sh:723
msgid "Main Font"
msgstr "主フォント"
-#: git-gui.sh:675
+#: git-gui.sh:724
msgid "Diff/Console Font"
msgstr "diff/コンソール・フォント"
-#: git-gui.sh:689
+#: git-gui.sh:738
msgid "Cannot find git in PATH."
msgstr "PATH 中㫠git ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
-#: git-gui.sh:716
+#: git-gui.sh:765
msgid "Cannot parse Git version string:"
msgstr "Git ãƒãƒ¼ã‚¸ãƒ§ãƒ³åãŒç†è§£ã§ãã¾ã›ã‚“:"
-#: git-gui.sh:734
+#: git-gui.sh:783
#, tcl-format
msgid ""
"Git version cannot be determined.\n"
@@ -61,381 +61,446 @@ msgstr ""
"\n"
"'%s' ã¯ãƒãƒ¼ã‚¸ãƒ§ãƒ³ 1.5.0 ã¨æ€ã£ã¦è‰¯ã„ã§ã™ã‹ï¼Ÿ\n"
-#: git-gui.sh:972
+#: git-gui.sh:1062
msgid "Git directory not found:"
msgstr "Git ディレクトリãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“:"
-#: git-gui.sh:979
+#: git-gui.sh:1069
msgid "Cannot move to top of working directory:"
msgstr "作業ディレクトリã®æœ€ä¸Šä½ã«ç§»å‹•ã§ãã¾ã›ã‚“"
-#: git-gui.sh:986
+#: git-gui.sh:1076
msgid "Cannot use funny .git directory:"
msgstr "変㪠.git ディレクトリã¯ä½¿ãˆã¾ã›ã‚“"
-#: git-gui.sh:991
+#: git-gui.sh:1081
msgid "No working directory"
msgstr "作業ディレクトリãŒã‚ã‚Šã¾ã›ã‚“"
-#: git-gui.sh:1138 lib/checkout_op.tcl:305
+#: git-gui.sh:1247 lib/checkout_op.tcl:305
msgid "Refreshing file status..."
msgstr "ファイル状態を更新ã—ã¦ã„ã¾ã™â€¦"
-#: git-gui.sh:1194
+#: git-gui.sh:1303
msgid "Scanning for modified files ..."
msgstr "変更ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã‚’スキャンã—ã¦ã„ã¾ã™â€¦"
-#: git-gui.sh:1369 lib/browser.tcl:246
+#: git-gui.sh:1367
+msgid "Calling prepare-commit-msg hook..."
+msgstr "prepare-commit-msg フックを実行中・・・"
+
+#: git-gui.sh:1384
+msgid "Commit declined by prepare-commit-msg hook."
+msgstr "prepare-commit-msg フックãŒã‚³ãƒŸãƒƒãƒˆã‚’æ‹’å¦ã—ã¾ã—ãŸ"
+
+#: git-gui.sh:1542 lib/browser.tcl:246
msgid "Ready."
msgstr "準備完了"
-#: git-gui.sh:1635
+#: git-gui.sh:1819
msgid "Unmodified"
msgstr "変更無ã—"
-#: git-gui.sh:1637
+#: git-gui.sh:1821
msgid "Modified, not staged"
msgstr "変更ã‚ã‚Šã€ã‚³ãƒŸãƒƒãƒˆæœªäºˆå®š"
-#: git-gui.sh:1638 git-gui.sh:1643
+#: git-gui.sh:1822 git-gui.sh:1830
msgid "Staged for commit"
msgstr "コミット予定済"
-#: git-gui.sh:1639 git-gui.sh:1644
+#: git-gui.sh:1823 git-gui.sh:1831
msgid "Portions staged for commit"
msgstr "部分的ã«ã‚³ãƒŸãƒƒãƒˆäºˆå®šæ¸ˆ"
-#: git-gui.sh:1640 git-gui.sh:1645
+#: git-gui.sh:1824 git-gui.sh:1832
msgid "Staged for commit, missing"
msgstr "コミット予定済ã€ãƒ•ã‚¡ã‚¤ãƒ«ç„¡ã—"
-#: git-gui.sh:1642
+#: git-gui.sh:1826
+msgid "File type changed, not staged"
+msgstr "ファイル型変更ã€ã‚³ãƒŸãƒƒãƒˆæœªäºˆå®š"
+
+#: git-gui.sh:1827
+msgid "File type changed, staged"
+msgstr "ファイル型変更ã€ã‚³ãƒŸãƒƒãƒˆäºˆå®šæ¸ˆ"
+
+#: git-gui.sh:1829
msgid "Untracked, not staged"
msgstr "管ç†å¤–ã€ã‚³ãƒŸãƒƒãƒˆæœªäºˆå®š"
-#: git-gui.sh:1647
+#: git-gui.sh:1834
msgid "Missing"
msgstr "ファイル無ã—"
-#: git-gui.sh:1648
+#: git-gui.sh:1835
msgid "Staged for removal"
msgstr "削除予定済"
-#: git-gui.sh:1649
+#: git-gui.sh:1836
msgid "Staged for removal, still present"
msgstr "削除予定済ã€ãƒ•ã‚¡ã‚¤ãƒ«æœªå‰Šé™¤"
-#: git-gui.sh:1651 git-gui.sh:1652 git-gui.sh:1653 git-gui.sh:1654
+#: git-gui.sh:1838 git-gui.sh:1839 git-gui.sh:1840 git-gui.sh:1841
+#: git-gui.sh:1842 git-gui.sh:1843
msgid "Requires merge resolution"
msgstr "è¦ãƒžãƒ¼ã‚¸è§£æ±º"
-#: git-gui.sh:1689
+#: git-gui.sh:1878
msgid "Starting gitk... please wait..."
msgstr "gitk を起動中…ãŠå¾…ã¡ä¸‹ã•ã„…"
-#: git-gui.sh:1698
+#: git-gui.sh:1887
msgid "Couldn't find gitk in PATH"
msgstr "PATH 中㫠gitk ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
-#: git-gui.sh:1948 lib/choose_repository.tcl:36
+#: git-gui.sh:2280 lib/choose_repository.tcl:36
msgid "Repository"
msgstr "リãƒã‚¸ãƒˆãƒª"
-#: git-gui.sh:1949
+#: git-gui.sh:2281
msgid "Edit"
msgstr "編集"
-#: git-gui.sh:1951 lib/choose_rev.tcl:561
+#: git-gui.sh:2283 lib/choose_rev.tcl:561
msgid "Branch"
msgstr "ブランãƒ"
-#: git-gui.sh:1954 lib/choose_rev.tcl:548
+#: git-gui.sh:2286 lib/choose_rev.tcl:548
msgid "Commit@@noun"
msgstr "コミット"
-#: git-gui.sh:1957 lib/merge.tcl:120 lib/merge.tcl:149 lib/merge.tcl:167
+#: git-gui.sh:2289 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168
msgid "Merge"
msgstr "マージ"
-#: git-gui.sh:1958 lib/choose_rev.tcl:557
+#: git-gui.sh:2290 lib/choose_rev.tcl:557
msgid "Remote"
msgstr "リモート"
-#: git-gui.sh:1967
+#: git-gui.sh:2293
+msgid "Tools"
+msgstr "ツール"
+
+#: git-gui.sh:2302
+msgid "Explore Working Copy"
+msgstr "ワーキングコピーをブラウズ"
+
+#: git-gui.sh:2307
msgid "Browse Current Branch's Files"
msgstr "ç¾åœ¨ã®ãƒ–ランãƒã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’見る"
-#: git-gui.sh:1971
+#: git-gui.sh:2311
msgid "Browse Branch Files..."
msgstr "ブランãƒã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’見る…"
-#: git-gui.sh:1976
+#: git-gui.sh:2316
msgid "Visualize Current Branch's History"
msgstr "ç¾åœ¨ã®ãƒ–ランãƒã®å±¥æ­´ã‚’見る"
-#: git-gui.sh:1980
+#: git-gui.sh:2320
msgid "Visualize All Branch History"
msgstr "å…¨ã¦ã®ãƒ–ランãƒã®å±¥æ­´ã‚’見る"
-#: git-gui.sh:1987
+#: git-gui.sh:2327
#, tcl-format
msgid "Browse %s's Files"
msgstr "ブランム%s ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’見る"
-#: git-gui.sh:1989
+#: git-gui.sh:2329
#, tcl-format
msgid "Visualize %s's History"
msgstr "ブランム%s ã®å±¥æ­´ã‚’見る"
-#: git-gui.sh:1994 lib/database.tcl:27 lib/database.tcl:67
+#: git-gui.sh:2334 lib/database.tcl:27 lib/database.tcl:67
msgid "Database Statistics"
msgstr "データベース統計"
-#: git-gui.sh:1997 lib/database.tcl:34
+#: git-gui.sh:2337 lib/database.tcl:34
msgid "Compress Database"
msgstr "データベース圧縮"
-#: git-gui.sh:2000
+#: git-gui.sh:2340
msgid "Verify Database"
msgstr "データベース検証"
-#: git-gui.sh:2007 git-gui.sh:2011 git-gui.sh:2015 lib/shortcut.tcl:7
+#: git-gui.sh:2347 git-gui.sh:2351 git-gui.sh:2355 lib/shortcut.tcl:7
#: lib/shortcut.tcl:39 lib/shortcut.tcl:71
msgid "Create Desktop Icon"
msgstr "デスクトップ・アイコンを作る"
-#: git-gui.sh:2023 lib/choose_repository.tcl:177 lib/choose_repository.tcl:185
+#: git-gui.sh:2363 lib/choose_repository.tcl:183 lib/choose_repository.tcl:191
msgid "Quit"
msgstr "終了"
-#: git-gui.sh:2031
+#: git-gui.sh:2371
msgid "Undo"
msgstr "å…ƒã«æˆ»ã™"
-#: git-gui.sh:2034
+#: git-gui.sh:2374
msgid "Redo"
msgstr "ã‚„ã‚Šç›´ã—"
-#: git-gui.sh:2038 git-gui.sh:2545
+#: git-gui.sh:2378 git-gui.sh:2923
msgid "Cut"
msgstr "切りå–ã‚Š"
-#: git-gui.sh:2041 git-gui.sh:2548 git-gui.sh:2622 git-gui.sh:2715
+#: git-gui.sh:2381 git-gui.sh:2926 git-gui.sh:3000 git-gui.sh:3082
#: lib/console.tcl:69
msgid "Copy"
msgstr "コピー"
-#: git-gui.sh:2044 git-gui.sh:2551
+#: git-gui.sh:2384 git-gui.sh:2929
msgid "Paste"
msgstr "貼り付ã‘"
-#: git-gui.sh:2047 git-gui.sh:2554 lib/branch_delete.tcl:26
+#: git-gui.sh:2387 git-gui.sh:2932 lib/branch_delete.tcl:26
#: lib/remote_branch_delete.tcl:38
msgid "Delete"
msgstr "削除"
-#: git-gui.sh:2051 git-gui.sh:2558 git-gui.sh:2719 lib/console.tcl:71
+#: git-gui.sh:2391 git-gui.sh:2936 git-gui.sh:3086 lib/console.tcl:71
msgid "Select All"
msgstr "å…¨ã¦é¸æŠž"
-#: git-gui.sh:2060
+#: git-gui.sh:2400
msgid "Create..."
msgstr "作æˆâ€¦"
-#: git-gui.sh:2066
+#: git-gui.sh:2406
msgid "Checkout..."
msgstr "ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆ"
-#: git-gui.sh:2072
+#: git-gui.sh:2412
msgid "Rename..."
msgstr "åå‰å¤‰æ›´â€¦"
-#: git-gui.sh:2077 git-gui.sh:2187
+#: git-gui.sh:2417
msgid "Delete..."
msgstr "削除…"
-#: git-gui.sh:2082
+#: git-gui.sh:2422
msgid "Reset..."
msgstr "リセット…"
-#: git-gui.sh:2094 git-gui.sh:2491
+#: git-gui.sh:2432
+msgid "Done"
+msgstr "完了"
+
+#: git-gui.sh:2434
+msgid "Commit@@verb"
+msgstr "コミット"
+
+#: git-gui.sh:2443 git-gui.sh:2864
msgid "New Commit"
msgstr "æ–°è¦ã‚³ãƒŸãƒƒãƒˆ"
-#: git-gui.sh:2102 git-gui.sh:2498
+#: git-gui.sh:2451 git-gui.sh:2871
msgid "Amend Last Commit"
msgstr "最新コミットを訂正"
-#: git-gui.sh:2111 git-gui.sh:2458 lib/remote_branch_delete.tcl:99
+#: git-gui.sh:2461 git-gui.sh:2825 lib/remote_branch_delete.tcl:99
msgid "Rescan"
msgstr "å†ã‚¹ã‚­ãƒ£ãƒ³"
-#: git-gui.sh:2117
+#: git-gui.sh:2467
msgid "Stage To Commit"
msgstr "コミット予定ã™ã‚‹"
-#: git-gui.sh:2123
+#: git-gui.sh:2473
msgid "Stage Changed Files To Commit"
msgstr "変更ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã‚’コミット予定"
-#: git-gui.sh:2129
+#: git-gui.sh:2479
msgid "Unstage From Commit"
msgstr "コミットã‹ã‚‰é™ã‚ã™"
-#: git-gui.sh:2134 lib/index.tcl:395
+#: git-gui.sh:2484 lib/index.tcl:410
msgid "Revert Changes"
msgstr "変更を元ã«æˆ»ã™"
-#: git-gui.sh:2141 git-gui.sh:2702
+#: git-gui.sh:2491 git-gui.sh:3069
msgid "Show Less Context"
msgstr "文脈を少ãªã"
-#: git-gui.sh:2145 git-gui.sh:2706
+#: git-gui.sh:2495 git-gui.sh:3073
msgid "Show More Context"
msgstr "文脈を多ã"
-#: git-gui.sh:2151 git-gui.sh:2470 git-gui.sh:2569
+#: git-gui.sh:2502 git-gui.sh:2838 git-gui.sh:2947
msgid "Sign Off"
msgstr "ç½²å"
-#: git-gui.sh:2155 git-gui.sh:2474
-msgid "Commit@@verb"
-msgstr "コミット"
-
-#: git-gui.sh:2166
+#: git-gui.sh:2518
msgid "Local Merge..."
msgstr "ローカル・マージ…"
-#: git-gui.sh:2171
+#: git-gui.sh:2523
msgid "Abort Merge..."
msgstr "マージ中止…"
-#: git-gui.sh:2183
+#: git-gui.sh:2535 git-gui.sh:2575
+msgid "Add..."
+msgstr "追加"
+
+#: git-gui.sh:2539
msgid "Push..."
msgstr "プッシュ…"
-#: git-gui.sh:2197 git-gui.sh:2219 lib/about.tcl:14
-#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50
+#: git-gui.sh:2543
+msgid "Delete Branch..."
+msgstr "ブランãƒå‰Šé™¤..."
+
+#: git-gui.sh:2553 git-gui.sh:2589 lib/about.tcl:14
+#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:53
#, tcl-format
msgid "About %s"
msgstr "%s ã«ã¤ã„ã¦"
-#: git-gui.sh:2201
+#: git-gui.sh:2557
msgid "Preferences..."
msgstr "設定…"
-#: git-gui.sh:2209 git-gui.sh:2740
+#: git-gui.sh:2565 git-gui.sh:3115
msgid "Options..."
msgstr "オプション…"
-#: git-gui.sh:2215 lib/choose_repository.tcl:47
+#: git-gui.sh:2576
+msgid "Remove..."
+msgstr "削除..."
+
+#: git-gui.sh:2585 lib/choose_repository.tcl:50
msgid "Help"
msgstr "ヘルプ"
-#: git-gui.sh:2256
+#: git-gui.sh:2611
msgid "Online Documentation"
msgstr "オンライン・ドキュメント"
-#: git-gui.sh:2340
+#: git-gui.sh:2614 lib/choose_repository.tcl:47 lib/choose_repository.tcl:56
+msgid "Show SSH Key"
+msgstr "SSH キーを表示"
+
+#: git-gui.sh:2707
#, tcl-format
msgid "fatal: cannot stat path %s: No such file or directory"
msgstr ""
"致命的: パス %s ㌠stat ã§ãã¾ã›ã‚“。ãã®ã‚ˆã†ãªãƒ•ã‚¡ã‚¤ãƒ«ã‚„ディレクトリã¯ã‚ã‚Šã¾"
"ã›ã‚“"
-#: git-gui.sh:2373
+#: git-gui.sh:2740
msgid "Current Branch:"
msgstr "ç¾åœ¨ã®ãƒ–ランãƒ"
-#: git-gui.sh:2394
+#: git-gui.sh:2761
msgid "Staged Changes (Will Commit)"
msgstr "ステージングã•ã‚ŒãŸï¼ˆã‚³ãƒŸãƒƒãƒˆäºˆå®šæ¸ˆã®ï¼‰å¤‰æ›´"
-#: git-gui.sh:2414
+#: git-gui.sh:2781
msgid "Unstaged Changes"
msgstr "コミット予定ã«å…¥ã£ã¦ã„ãªã„変更"
-#: git-gui.sh:2464
+#: git-gui.sh:2831
msgid "Stage Changed"
msgstr "変更をコミット予定ã«å…¥ã‚Œã‚‹"
-#: git-gui.sh:2480 lib/transport.tcl:93 lib/transport.tcl:182
+#: git-gui.sh:2850 lib/transport.tcl:93 lib/transport.tcl:182
msgid "Push"
msgstr "プッシュ"
-#: git-gui.sh:2510
+#: git-gui.sh:2885
msgid "Initial Commit Message:"
msgstr "最åˆã®ã‚³ãƒŸãƒƒãƒˆãƒ¡ãƒƒã‚»ãƒ¼ã‚¸:"
-#: git-gui.sh:2511
+#: git-gui.sh:2886
msgid "Amended Commit Message:"
msgstr "訂正ã—ãŸã‚³ãƒŸãƒƒãƒˆãƒ¡ãƒƒã‚»ãƒ¼ã‚¸:"
-#: git-gui.sh:2512
+#: git-gui.sh:2887
msgid "Amended Initial Commit Message:"
msgstr "訂正ã—ãŸæœ€åˆã®ã‚³ãƒŸãƒƒãƒˆãƒ¡ãƒƒã‚»ãƒ¼ã‚¸:"
-#: git-gui.sh:2513
+#: git-gui.sh:2888
msgid "Amended Merge Commit Message:"
msgstr "訂正ã—ãŸãƒžãƒ¼ã‚¸ã‚³ãƒŸãƒƒãƒˆãƒ¡ãƒƒã‚»ãƒ¼ã‚¸:"
-#: git-gui.sh:2514
+#: git-gui.sh:2889
msgid "Merge Commit Message:"
msgstr "マージコミットメッセージ:"
-#: git-gui.sh:2515
+#: git-gui.sh:2890
msgid "Commit Message:"
msgstr "コミットメッセージ:"
-#: git-gui.sh:2561 git-gui.sh:2723 lib/console.tcl:73
+#: git-gui.sh:2939 git-gui.sh:3090 lib/console.tcl:73
msgid "Copy All"
msgstr "å…¨ã¦ã‚³ãƒ”ー"
-#: git-gui.sh:2585 lib/blame.tcl:100
+#: git-gui.sh:2963 lib/blame.tcl:104
msgid "File:"
msgstr "ファイル:"
-#: git-gui.sh:2691
-msgid "Apply/Reverse Hunk"
-msgstr "パッãƒã‚’é©ç”¨/å–り消ã™"
-
-#: git-gui.sh:2696
-msgid "Apply/Reverse Line"
-msgstr "パッãƒè¡Œã‚’é©ç”¨/å–り消ã™"
-
-#: git-gui.sh:2711
+#: git-gui.sh:3078
msgid "Refresh"
msgstr "å†èª­ã¿è¾¼ã¿"
-#: git-gui.sh:2732
+#: git-gui.sh:3099
msgid "Decrease Font Size"
msgstr "フォントをå°ã•ã"
-#: git-gui.sh:2736
+#: git-gui.sh:3103
msgid "Increase Font Size"
msgstr "フォントを大ãã"
-#: git-gui.sh:2747
+#: git-gui.sh:3111 lib/blame.tcl:281
+msgid "Encoding"
+msgstr "エンコーディング"
+
+#: git-gui.sh:3122
+msgid "Apply/Reverse Hunk"
+msgstr "パッãƒã‚’é©ç”¨/å–り消ã™"
+
+#: git-gui.sh:3127
+msgid "Apply/Reverse Line"
+msgstr "パッãƒè¡Œã‚’é©ç”¨/å–り消ã™"
+
+#: git-gui.sh:3137
+msgid "Run Merge Tool"
+msgstr "マージツールを起動"
+
+#: git-gui.sh:3142
+msgid "Use Remote Version"
+msgstr "リモートã®æ–¹ã‚’採用"
+
+#: git-gui.sh:3146
+msgid "Use Local Version"
+msgstr "ローカルã®æ–¹ã‚’採用"
+
+#: git-gui.sh:3150
+msgid "Revert To Base"
+msgstr "ベース版を採用"
+
+#: git-gui.sh:3169
msgid "Unstage Hunk From Commit"
msgstr "パッãƒã‚’コミット予定ã‹ã‚‰å¤–ã™"
-#: git-gui.sh:2748
+#: git-gui.sh:3170
msgid "Unstage Line From Commit"
msgstr "コミット予定ã‹ã‚‰è¡Œã‚’外ã™"
-#: git-gui.sh:2750
+#: git-gui.sh:3172
msgid "Stage Hunk For Commit"
msgstr "パッãƒã‚’コミット予定ã«åŠ ãˆã‚‹"
-#: git-gui.sh:2751
+#: git-gui.sh:3173
msgid "Stage Line For Commit"
msgstr "パッãƒè¡Œã‚’コミット予定ã«åŠ ãˆã‚‹"
-#: git-gui.sh:2771
+#: git-gui.sh:3196
msgid "Initializing..."
msgstr "åˆæœŸåŒ–ã—ã¦ã„ã¾ã™â€¦"
-#: git-gui.sh:2876
+#: git-gui.sh:3301
#, tcl-format
msgid ""
"Possible environment issues exist.\n"
@@ -450,7 +515,7 @@ msgstr ""
"以下ã®ç’°å¢ƒå¤‰æ•°ã¯ %s ãŒèµ·å‹•ã™ã‚‹ Git サブプロセスã«ã‚ˆã£ã¦ç„¡è¦–ã•ã‚Œã‚‹ã§ã—ょã†:\n"
"\n"
-#: git-gui.sh:2906
+#: git-gui.sh:3331
msgid ""
"\n"
"This is due to a known issue with the\n"
@@ -460,7 +525,7 @@ msgstr ""
"ã“れ㯠Cygwin ã§é…布ã•ã‚Œã¦ã„ã‚‹ Tcl ãƒã‚¤ãƒŠãƒªã«\n"
"é–¢ã—ã¦ã®æ—¢çŸ¥ã®å•é¡Œã«ã‚ˆã‚Šã¾ã™"
-#: git-gui.sh:2911
+#: git-gui.sh:3336
#, tcl-format
msgid ""
"\n"
@@ -479,80 +544,108 @@ msgstr ""
msgid "git-gui - a graphical user interface for Git."
msgstr "Git ã®ã‚°ãƒ©ãƒ•ã‚£ã‚«ãƒ«UI git-gui"
-#: lib/blame.tcl:70
+#: lib/blame.tcl:72
msgid "File Viewer"
msgstr "ファイルピューワ"
-#: lib/blame.tcl:74
+#: lib/blame.tcl:78
msgid "Commit:"
msgstr "コミット:"
-#: lib/blame.tcl:257
+#: lib/blame.tcl:271
msgid "Copy Commit"
msgstr "コミットをコピー"
-#: lib/blame.tcl:260
+#: lib/blame.tcl:275
+msgid "Find Text..."
+msgstr "テキストを検索"
+
+#: lib/blame.tcl:284
msgid "Do Full Copy Detection"
msgstr "コピー検知"
-#: lib/blame.tcl:388
+#: lib/blame.tcl:288
+msgid "Show History Context"
+msgstr "文脈を見ã›ã‚‹"
+
+#: lib/blame.tcl:291
+msgid "Blame Parent Commit"
+msgstr "親コミットを註釈"
+
+#: lib/blame.tcl:450
#, tcl-format
msgid "Reading %s..."
msgstr "%s を読んã§ã„ã¾ã™â€¦"
-#: lib/blame.tcl:492
+#: lib/blame.tcl:557
msgid "Loading copy/move tracking annotations..."
msgstr "コピー・移動追跡データを読んã§ã„ã¾ã™â€¦"
-#: lib/blame.tcl:512
+#: lib/blame.tcl:577
msgid "lines annotated"
msgstr "行を注釈ã—ã¾ã—ãŸ"
-#: lib/blame.tcl:704
+#: lib/blame.tcl:769
msgid "Loading original location annotations..."
msgstr "å…ƒä½ç½®è¡Œã®æ³¨é‡ˆãƒ‡ãƒ¼ã‚¿ã‚’読んã§ã„ã¾ã™â€¦"
-#: lib/blame.tcl:707
+#: lib/blame.tcl:772
msgid "Annotation complete."
msgstr "注釈完了ã—ã¾ã—ãŸ"
-#: lib/blame.tcl:737
+#: lib/blame.tcl:802
msgid "Busy"
msgstr "実行中"
-#: lib/blame.tcl:738
+#: lib/blame.tcl:803
msgid "Annotation process is already running."
msgstr "ã™ã§ã« blame プロセスを実行中ã§ã™ã€‚"
-#: lib/blame.tcl:777
+#: lib/blame.tcl:842
msgid "Running thorough copy detection..."
msgstr "コピー検知を実行中…"
-#: lib/blame.tcl:827
+#: lib/blame.tcl:910
msgid "Loading annotation..."
msgstr "注釈を読ã¿è¾¼ã‚“ã§ã„ã¾ã™â€¦"
-#: lib/blame.tcl:883
+#: lib/blame.tcl:964
msgid "Author:"
msgstr "作者:"
-#: lib/blame.tcl:887
+#: lib/blame.tcl:968
msgid "Committer:"
msgstr "コミット者:"
-#: lib/blame.tcl:892
+#: lib/blame.tcl:973
msgid "Original File:"
msgstr "元ファイル"
-#: lib/blame.tcl:1006
+#: lib/blame.tcl:1021
+msgid "Cannot find HEAD commit:"
+msgstr "HEAD コミットãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
+
+#: lib/blame.tcl:1076
+msgid "Cannot find parent commit:"
+msgstr "親コミットãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“:"
+
+#: lib/blame.tcl:1091
+msgid "Unable to display parent"
+msgstr "親を表示ã§ãã¾ã›ã‚“"
+
+#: lib/blame.tcl:1092 lib/diff.tcl:297
+msgid "Error loading diff:"
+msgstr "diff を読む際ã®ã‚¨ãƒ©ãƒ¼ã§ã™:"
+
+#: lib/blame.tcl:1232
msgid "Originally By:"
msgstr "原作者:"
-#: lib/blame.tcl:1012
+#: lib/blame.tcl:1238
msgid "In File:"
msgstr "ファイル:"
-#: lib/blame.tcl:1017
+#: lib/blame.tcl:1243
msgid "Copied Or Moved Here By:"
msgstr "複写・移動者:"
@@ -566,16 +659,18 @@ msgstr "ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆ"
#: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35
#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:282
-#: lib/checkout_op.tcl:544 lib/choose_font.tcl:43 lib/merge.tcl:171
-#: lib/option.tcl:103 lib/remote_branch_delete.tcl:42 lib/transport.tcl:97
+#: lib/checkout_op.tcl:544 lib/choose_font.tcl:43 lib/merge.tcl:172
+#: lib/option.tcl:125 lib/remote_add.tcl:32 lib/remote_branch_delete.tcl:42
+#: lib/tools_dlg.tcl:40 lib/tools_dlg.tcl:204 lib/tools_dlg.tcl:352
+#: lib/transport.tcl:97
msgid "Cancel"
msgstr "中止"
-#: lib/branch_checkout.tcl:32 lib/browser.tcl:287
+#: lib/branch_checkout.tcl:32 lib/browser.tcl:287 lib/tools_dlg.tcl:328
msgid "Revision"
msgstr "リビジョン"
-#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:244
+#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:280
msgid "Options"
msgstr "オプション"
@@ -595,7 +690,7 @@ msgstr "ブランãƒã‚’作æˆ"
msgid "Create New Branch"
msgstr "ブランãƒã‚’æ–°è¦ä½œæˆ"
-#: lib/branch_create.tcl:31 lib/choose_repository.tcl:371
+#: lib/branch_create.tcl:31 lib/choose_repository.tcl:377
msgid "Create"
msgstr "作æˆ"
@@ -603,7 +698,7 @@ msgstr "作æˆ"
msgid "Branch Name"
msgstr "ブランãƒå"
-#: lib/branch_create.tcl:43
+#: lib/branch_create.tcl:43 lib/remote_add.tcl:39 lib/tools_dlg.tcl:50
msgid "Name:"
msgstr "åå‰:"
@@ -748,9 +843,9 @@ msgstr "[上ä½ãƒ•ã‚©ãƒ«ãƒ€ã¸]"
msgid "Browse Branch Files"
msgstr "ç¾åœ¨ã®ãƒ–ランãƒã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’見る"
-#: lib/browser.tcl:278 lib/choose_repository.tcl:387
-#: lib/choose_repository.tcl:472 lib/choose_repository.tcl:482
-#: lib/choose_repository.tcl:985
+#: lib/browser.tcl:278 lib/choose_repository.tcl:394
+#: lib/choose_repository.tcl:480 lib/choose_repository.tcl:491
+#: lib/choose_repository.tcl:995
msgid "Browse"
msgstr "ブラウズ"
@@ -765,6 +860,7 @@ msgid "fatal: Cannot resolve %s"
msgstr "致命的エラー: %s を解決ã§ãã¾ã›ã‚“"
#: lib/checkout_op.tcl:145 lib/console.tcl:81 lib/database.tcl:31
+#: lib/sshkey.tcl:53
msgid "Close"
msgstr "é–‰ã˜ã‚‹"
@@ -875,7 +971,7 @@ msgstr "失ãªã‚ã‚ŒãŸã‚³ãƒŸãƒƒãƒˆã‚’回復ã™ã‚‹ã®ã¯ç°¡å˜ã§ã¯ã‚ã‚Šã¾ã›
msgid "Reset '%s'?"
msgstr "'%s' をリセットã—ã¾ã™ã‹ï¼Ÿ"
-#: lib/checkout_op.tcl:532 lib/merge.tcl:163
+#: lib/checkout_op.tcl:532 lib/merge.tcl:164 lib/tools_dlg.tcl:343
msgid "Visualize"
msgstr "å¯è¦–化"
@@ -923,221 +1019,225 @@ msgstr ""
msgid "Git Gui"
msgstr "Git GUI"
-#: lib/choose_repository.tcl:81 lib/choose_repository.tcl:376
+#: lib/choose_repository.tcl:87 lib/choose_repository.tcl:382
msgid "Create New Repository"
msgstr "æ–°ã—ã„リãƒã‚¸ãƒˆãƒªã‚’作る"
-#: lib/choose_repository.tcl:87
+#: lib/choose_repository.tcl:93
msgid "New..."
msgstr "æ–°è¦â€¦"
-#: lib/choose_repository.tcl:94 lib/choose_repository.tcl:458
+#: lib/choose_repository.tcl:100 lib/choose_repository.tcl:465
msgid "Clone Existing Repository"
msgstr "既存リãƒã‚¸ãƒˆãƒªã‚’複製ã™ã‚‹"
-#: lib/choose_repository.tcl:100
+#: lib/choose_repository.tcl:106
msgid "Clone..."
msgstr "複製…"
-#: lib/choose_repository.tcl:107 lib/choose_repository.tcl:974
+#: lib/choose_repository.tcl:113 lib/choose_repository.tcl:983
msgid "Open Existing Repository"
msgstr "既存リãƒã‚¸ãƒˆãƒªã‚’é–‹ã"
-#: lib/choose_repository.tcl:113
+#: lib/choose_repository.tcl:119
msgid "Open..."
msgstr "é–‹ã…"
-#: lib/choose_repository.tcl:126
+#: lib/choose_repository.tcl:132
msgid "Recent Repositories"
msgstr "最近使ã£ãŸãƒªãƒã‚¸ãƒˆãƒª"
-#: lib/choose_repository.tcl:132
+#: lib/choose_repository.tcl:138
msgid "Open Recent Repository:"
msgstr "最近使ã£ãŸãƒªãƒã‚¸ãƒˆãƒªã‚’é–‹ã"
-#: lib/choose_repository.tcl:296 lib/choose_repository.tcl:303
-#: lib/choose_repository.tcl:310
+#: lib/choose_repository.tcl:302 lib/choose_repository.tcl:309
+#: lib/choose_repository.tcl:316
#, tcl-format
msgid "Failed to create repository %s:"
msgstr "リãƒã‚¸ãƒˆãƒª %s を作製ã§ãã¾ã›ã‚“:"
-#: lib/choose_repository.tcl:381 lib/choose_repository.tcl:476
+#: lib/choose_repository.tcl:387
msgid "Directory:"
msgstr "ディレクトリ:"
-#: lib/choose_repository.tcl:410 lib/choose_repository.tcl:535
-#: lib/choose_repository.tcl:1007
+#: lib/choose_repository.tcl:417 lib/choose_repository.tcl:544
+#: lib/choose_repository.tcl:1017
msgid "Git Repository"
msgstr "GIT リãƒã‚¸ãƒˆãƒª"
-#: lib/choose_repository.tcl:435
+#: lib/choose_repository.tcl:442
#, tcl-format
msgid "Directory %s already exists."
msgstr "ディレクトリ '%s' ã¯æ—¢ã«å­˜åœ¨ã—ã¾ã™ã€‚"
-#: lib/choose_repository.tcl:439
+#: lib/choose_repository.tcl:446
#, tcl-format
msgid "File %s already exists."
msgstr "ファイル '%s' ã¯æ—¢ã«å­˜åœ¨ã—ã¾ã™ã€‚"
-#: lib/choose_repository.tcl:453
+#: lib/choose_repository.tcl:460
msgid "Clone"
msgstr "複製"
-#: lib/choose_repository.tcl:466
-msgid "URL:"
-msgstr "URL:"
+#: lib/choose_repository.tcl:473
+msgid "Source Location:"
+msgstr "ソースã®ä½ç½®"
-#: lib/choose_repository.tcl:487
+#: lib/choose_repository.tcl:484
+msgid "Target Directory:"
+msgstr "先ディレクトリ:"
+
+#: lib/choose_repository.tcl:496
msgid "Clone Type:"
msgstr "複製方å¼:"
-#: lib/choose_repository.tcl:493
+#: lib/choose_repository.tcl:502
msgid "Standard (Fast, Semi-Redundant, Hardlinks)"
msgstr "標準(高速・中冗長度・ãƒãƒ¼ãƒ‰ãƒªãƒ³ã‚¯)"
-#: lib/choose_repository.tcl:499
+#: lib/choose_repository.tcl:508
msgid "Full Copy (Slower, Redundant Backup)"
msgstr "全複写(低速・冗長ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—)"
-#: lib/choose_repository.tcl:505
+#: lib/choose_repository.tcl:514
msgid "Shared (Fastest, Not Recommended, No Backup)"
msgstr "共有(最高速・éžæŽ¨å¥¨ãƒ»ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—ç„¡ã—)"
-#: lib/choose_repository.tcl:541 lib/choose_repository.tcl:588
-#: lib/choose_repository.tcl:734 lib/choose_repository.tcl:804
-#: lib/choose_repository.tcl:1013 lib/choose_repository.tcl:1021
+#: lib/choose_repository.tcl:550 lib/choose_repository.tcl:597
+#: lib/choose_repository.tcl:743 lib/choose_repository.tcl:813
+#: lib/choose_repository.tcl:1023 lib/choose_repository.tcl:1031
#, tcl-format
msgid "Not a Git repository: %s"
msgstr "Git リãƒã‚¸ãƒˆãƒªã§ã¯ã‚ã‚Šã¾ã›ã‚“: %s"
-#: lib/choose_repository.tcl:577
+#: lib/choose_repository.tcl:586
msgid "Standard only available for local repository."
msgstr "標準方å¼ã¯åŒä¸€è¨ˆç®—機上ã®ãƒªãƒã‚¸ãƒˆãƒªã«ã®ã¿ä½¿ãˆã¾ã™ã€‚"
-#: lib/choose_repository.tcl:581
+#: lib/choose_repository.tcl:590
msgid "Shared only available for local repository."
msgstr "共有方å¼ã¯åŒä¸€è¨ˆç®—機上ã®ãƒªãƒã‚¸ãƒˆãƒªã«ã®ã¿ä½¿ãˆã¾ã™ã€‚"
-#: lib/choose_repository.tcl:602
+#: lib/choose_repository.tcl:611
#, tcl-format
msgid "Location %s already exists."
msgstr "'%s' ã¯æ—¢ã«å­˜åœ¨ã—ã¾ã™ã€‚"
-#: lib/choose_repository.tcl:613
+#: lib/choose_repository.tcl:622
msgid "Failed to configure origin"
msgstr "origin を設定ã§ãã¾ã›ã‚“ã§ã—ãŸ"
-#: lib/choose_repository.tcl:625
+#: lib/choose_repository.tcl:634
msgid "Counting objects"
msgstr "オブジェクトを数ãˆã¦ã„ã¾ã™"
-#: lib/choose_repository.tcl:626
+#: lib/choose_repository.tcl:635
msgid "buckets"
msgstr "ãƒã‚±ãƒ„"
-#: lib/choose_repository.tcl:650
+#: lib/choose_repository.tcl:659
#, tcl-format
msgid "Unable to copy objects/info/alternates: %s"
msgstr "objects/info/alternates を複写ã§ãã¾ã›ã‚“: %s"
-#: lib/choose_repository.tcl:686
+#: lib/choose_repository.tcl:695
#, tcl-format
msgid "Nothing to clone from %s."
msgstr "%s ã‹ã‚‰è¤‡è£½ã™ã‚‹å†…容ã¯ã‚ã‚Šã¾ã›ã‚“"
-#: lib/choose_repository.tcl:688 lib/choose_repository.tcl:902
-#: lib/choose_repository.tcl:914
+#: lib/choose_repository.tcl:697 lib/choose_repository.tcl:911
+#: lib/choose_repository.tcl:923
msgid "The 'master' branch has not been initialized."
msgstr "'master' ブランãƒãŒåˆæœŸåŒ–ã•ã‚Œã¦ã„ã¾ã›ã‚“"
-#: lib/choose_repository.tcl:701
+#: lib/choose_repository.tcl:710
msgid "Hardlinks are unavailable. Falling back to copying."
msgstr "ãƒãƒ¼ãƒ‰ãƒªãƒ³ã‚¯ãŒä½œã‚Œãªã„ã®ã§ã€ã‚³ãƒ”ーã—ã¾ã™"
-#: lib/choose_repository.tcl:713
+#: lib/choose_repository.tcl:722
#, tcl-format
msgid "Cloning from %s"
msgstr "%s ã‹ã‚‰è¤‡è£½ã—ã¦ã„ã¾ã™"
-#: lib/choose_repository.tcl:744
+#: lib/choose_repository.tcl:753
msgid "Copying objects"
msgstr "オブジェクトを複写ã—ã¦ã„ã¾ã™"
-#: lib/choose_repository.tcl:745
+#: lib/choose_repository.tcl:754
msgid "KiB"
msgstr "KiB"
-#: lib/choose_repository.tcl:769
+#: lib/choose_repository.tcl:778
#, tcl-format
msgid "Unable to copy object: %s"
msgstr "オブジェクトを複写ã§ãã¾ã›ã‚“: %s"
-#: lib/choose_repository.tcl:779
+#: lib/choose_repository.tcl:788
msgid "Linking objects"
msgstr "オブジェクトを連çµã—ã¦ã„ã¾ã™"
-#: lib/choose_repository.tcl:780
+#: lib/choose_repository.tcl:789
msgid "objects"
msgstr "オブジェクト"
-#: lib/choose_repository.tcl:788
+#: lib/choose_repository.tcl:797
#, tcl-format
msgid "Unable to hardlink object: %s"
msgstr "オブジェクトをãƒãƒ¼ãƒ‰ãƒªãƒ³ã‚¯ã§ãã¾ã›ã‚“: %s"
-#: lib/choose_repository.tcl:843
+#: lib/choose_repository.tcl:852
msgid "Cannot fetch branches and objects. See console output for details."
msgstr "ブランãƒã‚„オブジェクトをå–å¾—ã§ãã¾ã›ã‚“。コンソール出力を見ã¦ä¸‹ã•ã„"
-#: lib/choose_repository.tcl:854
+#: lib/choose_repository.tcl:863
msgid "Cannot fetch tags. See console output for details."
msgstr "ã‚¿ã‚°ã‚’å–å¾—ã§ãã¾ã›ã‚“。コンソール出力を見ã¦ä¸‹ã•ã„"
-#: lib/choose_repository.tcl:878
+#: lib/choose_repository.tcl:887
msgid "Cannot determine HEAD. See console output for details."
msgstr "HEAD を確定ã§ãã¾ã›ã‚“。コンソール出力を見ã¦ä¸‹ã•ã„"
-#: lib/choose_repository.tcl:887
+#: lib/choose_repository.tcl:896
#, tcl-format
msgid "Unable to cleanup %s"
msgstr "%s を掃除ã§ãã¾ã›ã‚“"
-#: lib/choose_repository.tcl:893
+#: lib/choose_repository.tcl:902
msgid "Clone failed."
msgstr "複写ã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
-#: lib/choose_repository.tcl:900
+#: lib/choose_repository.tcl:909
msgid "No default branch obtained."
msgstr "デフォールト・ブランãƒãŒå–å¾—ã•ã‚Œã¾ã›ã‚“ã§ã—ãŸ"
-#: lib/choose_repository.tcl:911
+#: lib/choose_repository.tcl:920
#, tcl-format
msgid "Cannot resolve %s as a commit."
msgstr "%s をコミットã¨ã—ã¦è§£é‡ˆã§ãã¾ã›ã‚“"
-#: lib/choose_repository.tcl:923
+#: lib/choose_repository.tcl:932
msgid "Creating working directory"
msgstr "作業ディレクトリを作æˆã—ã¦ã„ã¾ã™"
-#: lib/choose_repository.tcl:924 lib/index.tcl:65 lib/index.tcl:127
-#: lib/index.tcl:193
+#: lib/choose_repository.tcl:933 lib/index.tcl:65 lib/index.tcl:128
+#: lib/index.tcl:196
msgid "files"
msgstr "ファイル"
-#: lib/choose_repository.tcl:953
+#: lib/choose_repository.tcl:962
msgid "Initial file checkout failed."
msgstr "åˆæœŸãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆã«å¤±æ•—ã—ã¾ã—ãŸ"
-#: lib/choose_repository.tcl:969
+#: lib/choose_repository.tcl:978
msgid "Open"
msgstr "é–‹ã"
-#: lib/choose_repository.tcl:979
+#: lib/choose_repository.tcl:988
msgid "Repository:"
msgstr "リãƒã‚¸ãƒˆãƒª:"
-#: lib/choose_repository.tcl:1027
+#: lib/choose_repository.tcl:1037
#, tcl-format
msgid "Failed to open repository %s:"
msgstr "リãƒã‚¸ãƒˆãƒª %s ã‚’é–‹ã‘ã¾ã›ã‚“:"
@@ -1236,7 +1336,7 @@ msgstr ""
"\n"
"自動的ã«å†ã‚¹ã‚­ãƒ£ãƒ³ã‚’開始ã—ã¾ã™ã€‚\n"
-#: lib/commit.tcl:154
+#: lib/commit.tcl:156
#, tcl-format
msgid ""
"Unmerged files cannot be committed.\n"
@@ -1249,7 +1349,7 @@ msgstr ""
"ファイル %s ã«ã¯ãƒžãƒ¼ã‚¸è¡çªãŒæ®‹ã£ã¦ã„ã¾ã™ã€‚ã¾ãšè§£æ±ºã—ã¦ã‚³ãƒŸãƒƒãƒˆäºˆå®šã«åŠ ãˆã‚‹å¿…"
"è¦ãŒã‚ã‚Šã¾ã™ã€‚\n"
-#: lib/commit.tcl:162
+#: lib/commit.tcl:164
#, tcl-format
msgid ""
"Unknown file state %s detected.\n"
@@ -1260,7 +1360,7 @@ msgstr ""
"\n"
"ファイル %s ã¯æœ¬ãƒ—ログラムã§ã¯ã‚³ãƒŸãƒƒãƒˆã§ãã¾ã›ã‚“。\n"
-#: lib/commit.tcl:170
+#: lib/commit.tcl:172
msgid ""
"No changes to commit.\n"
"\n"
@@ -1270,7 +1370,7 @@ msgstr ""
"\n"
"最低一ã¤ã®å¤‰æ›´ã‚’コミット予定ã«åŠ ãˆã¦ã‹ã‚‰ã‚³ãƒŸãƒƒãƒˆã—ã¦ä¸‹ã•ã„。\n"
-#: lib/commit.tcl:183
+#: lib/commit.tcl:187
msgid ""
"Please supply a commit message.\n"
"\n"
@@ -1288,45 +1388,45 @@ msgstr ""
"- 第2行: 空白\n"
"- 残りã®è¡Œ: ãªãœã€ã“ã®å¤‰æ›´ãŒè‰¯ã„変更ã‹ã€ã®èª¬æ˜Žã€‚\n"
-#: lib/commit.tcl:207
+#: lib/commit.tcl:211
#, tcl-format
msgid "warning: Tcl does not support encoding '%s'."
msgstr "警告: Tcl ã¯ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‡ã‚£ãƒ³ã‚° '%s' をサãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã›ã‚“"
-#: lib/commit.tcl:221
+#: lib/commit.tcl:227
msgid "Calling pre-commit hook..."
msgstr "コミットå‰ãƒ•ãƒƒã‚¯ã‚’実行中・・・"
-#: lib/commit.tcl:236
+#: lib/commit.tcl:242
msgid "Commit declined by pre-commit hook."
msgstr "コミットå‰ãƒ•ãƒƒã‚¯ãŒã‚³ãƒŸãƒƒãƒˆã‚’æ‹’å¦ã—ã¾ã—ãŸ"
-#: lib/commit.tcl:259
+#: lib/commit.tcl:265
msgid "Calling commit-msg hook..."
msgstr "コミット・メッセージ・フックを実行中・・・"
-#: lib/commit.tcl:274
+#: lib/commit.tcl:280
msgid "Commit declined by commit-msg hook."
msgstr "コミット・メッセージ・フックãŒã‚³ãƒŸãƒƒãƒˆã‚’æ‹’å¦ã—ã¾ã—ãŸ"
-#: lib/commit.tcl:287
+#: lib/commit.tcl:293
msgid "Committing changes..."
msgstr "変更点をコミット中・・・"
-#: lib/commit.tcl:303
+#: lib/commit.tcl:309
msgid "write-tree failed:"
msgstr "write-tree ãŒå¤±æ•—ã—ã¾ã—ãŸ:"
-#: lib/commit.tcl:304 lib/commit.tcl:348 lib/commit.tcl:368
+#: lib/commit.tcl:310 lib/commit.tcl:354 lib/commit.tcl:374
msgid "Commit failed."
msgstr "コミットã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
-#: lib/commit.tcl:321
+#: lib/commit.tcl:327
#, tcl-format
msgid "Commit %s appears to be corrupt"
msgstr "コミット %s ã¯å£Šã‚Œã¦ã„ã¾ã™"
-#: lib/commit.tcl:326
+#: lib/commit.tcl:332
msgid ""
"No changes to commit.\n"
"\n"
@@ -1340,19 +1440,19 @@ msgstr ""
"\n"
"自動的ã«å†ã‚¹ã‚­ãƒ£ãƒ³ã‚’開始ã—ã¾ã™ã€‚\n"
-#: lib/commit.tcl:333
+#: lib/commit.tcl:339
msgid "No changes to commit."
msgstr "コミットã™ã‚‹å¤‰æ›´ãŒã‚ã‚Šã¾ã›ã‚“。"
-#: lib/commit.tcl:347
+#: lib/commit.tcl:353
msgid "commit-tree failed:"
msgstr "commit-tree ãŒå¤±æ•—ã—ã¾ã—ãŸ:"
-#: lib/commit.tcl:367
+#: lib/commit.tcl:373
msgid "update-ref failed:"
msgstr "update-ref ãŒå¤±æ•—ã—ã¾ã—ãŸ:"
-#: lib/commit.tcl:454
+#: lib/commit.tcl:461
#, tcl-format
msgid "Created commit %s: %s"
msgstr "コミット %s を作æˆã—ã¾ã—ãŸ: %s"
@@ -1427,7 +1527,7 @@ msgstr ""
msgid "Invalid date from Git: %s"
msgstr "Git ã‹ã‚‰å‡ºãŸç„¡åŠ¹ãªæ—¥ä»˜: %s"
-#: lib/diff.tcl:44
+#: lib/diff.tcl:59
#, tcl-format
msgid ""
"No differences detected.\n"
@@ -1449,48 +1549,102 @@ msgstr ""
"\n"
"åŒæ§˜ãªçŠ¶æ…‹ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’探ã™ãŸã‚ã«ã€è‡ªå‹•çš„ã«å†ã‚¹ã‚­ãƒ£ãƒ³ã‚’開始ã—ã¾ã™ã€‚"
-#: lib/diff.tcl:83
+#: lib/diff.tcl:99
#, tcl-format
msgid "Loading diff of %s..."
msgstr "%s ã®å¤‰æ›´ç‚¹ã‚’ロード中…"
-#: lib/diff.tcl:116 lib/diff.tcl:190
+#: lib/diff.tcl:120
+msgid ""
+"LOCAL: deleted\n"
+"REMOTE:\n"
+msgstr ""
+"LOCAL: 削除\n"
+"Remote:\n"
+
+#: lib/diff.tcl:125
+msgid ""
+"REMOTE: deleted\n"
+"LOCAL:\n"
+msgstr ""
+"REMOTE: 削除\n"
+"LOCAL:\n"
+
+#: lib/diff.tcl:132
+msgid "LOCAL:\n"
+msgstr "LOCAL:\n"
+
+#: lib/diff.tcl:135
+msgid "REMOTE:\n"
+msgstr "REMOTE\n"
+
+#: lib/diff.tcl:197 lib/diff.tcl:296
#, tcl-format
msgid "Unable to display %s"
msgstr "%s を表示ã§ãã¾ã›ã‚“"
-#: lib/diff.tcl:117
+#: lib/diff.tcl:198
msgid "Error loading file:"
msgstr "ファイルを読む際ã®ã‚¨ãƒ©ãƒ¼ã§ã™:"
-#: lib/diff.tcl:124
+#: lib/diff.tcl:205
msgid "Git Repository (subproject)"
msgstr "Git リãƒã‚¸ãƒˆãƒª(サブプロジェクト)"
-#: lib/diff.tcl:136
+#: lib/diff.tcl:217
msgid "* Binary file (not showing content)."
msgstr "* ãƒã‚¤ãƒŠãƒªãƒ•ã‚¡ã‚¤ãƒ«(内容ã¯è¡¨ç¤ºã—ã¾ã›ã‚“)"
-#: lib/diff.tcl:191
-msgid "Error loading diff:"
-msgstr "diff を読む際ã®ã‚¨ãƒ©ãƒ¼ã§ã™:"
+#: lib/diff.tcl:222
+#, tcl-format
+msgid ""
+"* Untracked file is %d bytes.\n"
+"* Showing only first %d bytes.\n"
+msgstr ""
+"* 管ç†å¤–ã®ãƒ•ã‚¡ã‚¤ãƒ«ã®å¤§ãã•ã¯ %d ãƒã‚¤ãƒˆã§ã™ã€‚\n"
+"* 最åˆã® %d ãƒã‚¤ãƒˆã ã‘表示ã—ã¦ã„ã¾ã™ã€‚\n"
+
+#: lib/diff.tcl:228
+#, tcl-format
+msgid ""
+"\n"
+"* Untracked file clipped here by %s.\n"
+"* To see the entire file, use an external editor.\n"
+msgstr ""
+"\n"
+"\n"
+"* %s ã¯ç®¡ç†å¤–ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ã“ã“ã§åˆ‡ã‚ŠãŠã¨ã—ã¾ã—ãŸã€‚\n"
+"* 全体を見るã«ã¯å¤–部エディタを使ã£ã¦ãã ã•ã„。\n"
-#: lib/diff.tcl:313
+#: lib/diff.tcl:436
msgid "Failed to unstage selected hunk."
msgstr "é¸æŠžã•ã‚ŒãŸãƒ‘ッãƒã‚’コミット予定ã‹ã‚‰å¤–ã›ã¾ã›ã‚“。"
-#: lib/diff.tcl:320
+#: lib/diff.tcl:443
msgid "Failed to stage selected hunk."
msgstr "é¸æŠžã•ã‚ŒãŸãƒ‘ッãƒã‚’コミット予定ã«åŠ ãˆã‚‰ã‚Œã¾ã›ã‚“。"
-#: lib/diff.tcl:386
+#: lib/diff.tcl:509
msgid "Failed to unstage selected line."
msgstr "é¸æŠžã•ã‚ŒãŸãƒ‘ッãƒè¡Œã‚’コミット予定ã‹ã‚‰å¤–ã›ã¾ã›ã‚“。"
-#: lib/diff.tcl:394
+#: lib/diff.tcl:517
msgid "Failed to stage selected line."
msgstr "é¸æŠžã•ã‚ŒãŸãƒ‘ッãƒè¡Œã‚’コミット予定ã«åŠ ãˆã‚‰ã‚Œã¾ã›ã‚“。"
+#: lib/encoding.tcl:443
+msgid "Default"
+msgstr "デフォールト"
+
+#: lib/encoding.tcl:448
+#, tcl-format
+msgid "System (%s)"
+msgstr "システム (%s)"
+
+#: lib/encoding.tcl:459 lib/encoding.tcl:465
+msgid "Other"
+msgstr "ãã®ä»–"
+
#: lib/error.tcl:20 lib/error.tcl:114
msgid "error"
msgstr "エラー"
@@ -1527,38 +1681,47 @@ msgstr "続行"
msgid "Unlock Index"
msgstr "インデックスã®ãƒ­ãƒƒã‚¯è§£é™¤"
-#: lib/index.tcl:282
+#: lib/index.tcl:287
#, tcl-format
msgid "Unstaging %s from commit"
msgstr "コミットã‹ã‚‰ '%s' ã‚’é™ã‚ã™"
-#: lib/index.tcl:313
+#: lib/index.tcl:326
msgid "Ready to commit."
msgstr "コミット準備完了"
-#: lib/index.tcl:326
+#: lib/index.tcl:339
#, tcl-format
msgid "Adding %s"
msgstr "コミット㫠%s を加ãˆã¦ã„ã¾ã™"
-#: lib/index.tcl:381
+#: lib/index.tcl:396
#, tcl-format
msgid "Revert changes in file %s?"
msgstr "ファイル %s ã«ã—ãŸå¤‰æ›´ã‚’å…ƒã«æˆ»ã—ã¾ã™ã‹ï¼Ÿ"
-#: lib/index.tcl:383
+#: lib/index.tcl:398
#, tcl-format
msgid "Revert changes in these %i files?"
msgstr "ã“れら %i 個ã®ãƒ•ã‚¡ã‚¤ãƒ«ã«ã—ãŸå¤‰æ›´ã‚’å…ƒã«æˆ»ã—ã¾ã™ã‹ï¼Ÿ"
-#: lib/index.tcl:391
+#: lib/index.tcl:406
msgid "Any unstaged changes will be permanently lost by the revert."
msgstr "変更を元ã«æˆ»ã™ã¨ã‚³ãƒŸãƒƒãƒˆäºˆå®šã—ã¦ã„ãªã„変更ã¯å…¨ã¦å¤±ã‚ã‚Œã¾ã™ã€‚"
-#: lib/index.tcl:394
+#: lib/index.tcl:409
msgid "Do Nothing"
msgstr "何もã—ãªã„"
+#: lib/index.tcl:427
+msgid "Reverting selected files"
+msgstr "é¸æŠžã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã«ã—ãŸå¤‰æ›´ã‚’å…ƒã«æˆ»ã—ã¾ã™"
+
+#: lib/index.tcl:431
+#, tcl-format
+msgid "Reverting %s"
+msgstr "%s ã«ã—ãŸå¤‰æ›´ã‚’å…ƒã«æˆ»ã—ã¾ã™"
+
#: lib/merge.tcl:13
msgid ""
"Cannot merge while amending.\n"
@@ -1585,7 +1748,7 @@ msgstr ""
"\n"
"自動的ã«å†ã‚¹ã‚­ãƒ£ãƒ³ã‚’開始ã—ã¾ã™ã€‚\n"
-#: lib/merge.tcl:44
+#: lib/merge.tcl:45
#, tcl-format
msgid ""
"You are in the middle of a conflicted merge.\n"
@@ -1602,7 +1765,7 @@ msgstr ""
"ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã®è¡çªã‚’解決ã—ã€ã‚³ãƒŸãƒƒãƒˆäºˆå®šã«åŠ ãˆã¦ã€ã‚³ãƒŸãƒƒãƒˆã™ã‚‹ã“ã¨ã§ãƒžãƒ¼ã‚¸ã‚’"
"完了ã—ã¾ã™ã€‚ãã†ã‚„ã£ã¦å§‹ã‚ã¦ã€æ–°ãŸãªãƒžãƒ¼ã‚¸ã‚’開始ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚\n"
-#: lib/merge.tcl:54
+#: lib/merge.tcl:55
#, tcl-format
msgid ""
"You are in the middle of a change.\n"
@@ -1619,34 +1782,34 @@ msgstr ""
"ç¾åœ¨ã®ã‚³ãƒŸãƒƒãƒˆã‚’完了ã—ã¦ã‹ã‚‰ãƒžãƒ¼ã‚¸ã‚’開始ã—ã¦ä¸‹ã•ã„。ãã†ã™ã‚‹æ–¹ãŒãƒžãƒ¼ã‚¸ã«å¤±æ•—"
"ã—ãŸã¨ãã®å›žå¾©ãŒæ¥½ã§ã™ã€‚\n"
-#: lib/merge.tcl:106
+#: lib/merge.tcl:107
#, tcl-format
msgid "%s of %s"
msgstr "%s ã® %s ブランãƒ"
-#: lib/merge.tcl:119
+#: lib/merge.tcl:120
#, tcl-format
msgid "Merging %s and %s..."
msgstr "%s 㨠%s をマージ中・・・"
-#: lib/merge.tcl:130
+#: lib/merge.tcl:131
msgid "Merge completed successfully."
msgstr "マージãŒå®Œäº†ã—ã¾ã—ãŸ"
-#: lib/merge.tcl:132
+#: lib/merge.tcl:133
msgid "Merge failed. Conflict resolution is required."
msgstr "マージãŒå¤±æ•—ã—ã¾ã—ãŸã€‚è¡çªã®è§£æ±ºãŒå¿…è¦ã§ã™ã€‚"
-#: lib/merge.tcl:157
+#: lib/merge.tcl:158
#, tcl-format
msgid "Merge Into %s"
msgstr "%s ã«ãƒžãƒ¼ã‚¸"
-#: lib/merge.tcl:176
+#: lib/merge.tcl:177
msgid "Revision To Merge"
msgstr "マージã™ã‚‹ãƒªãƒ“ジョン"
-#: lib/merge.tcl:211
+#: lib/merge.tcl:212
msgid ""
"Cannot abort while amending.\n"
"\n"
@@ -1656,7 +1819,7 @@ msgstr ""
"\n"
"ã¾ãšä»Šã®ã‚³ãƒŸãƒƒãƒˆè¨‚正を完了ã•ã›ã¦ä¸‹ã•ã„。\n"
-#: lib/merge.tcl:221
+#: lib/merge.tcl:222
msgid ""
"Abort merge?\n"
"\n"
@@ -1670,7 +1833,7 @@ msgstr ""
"\n"
"マージを中断ã—ã¦ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
-#: lib/merge.tcl:227
+#: lib/merge.tcl:228
msgid ""
"Reset changes?\n"
"\n"
@@ -1684,131 +1847,323 @@ msgstr ""
"\n"
"リセットã—ã¦ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
-#: lib/merge.tcl:238
+#: lib/merge.tcl:239
msgid "Aborting"
msgstr "中断ã—ã¦ã„ã¾ã™"
-#: lib/merge.tcl:238
+#: lib/merge.tcl:239
msgid "files reset"
msgstr "リセットã—ãŸãƒ•ã‚¡ã‚¤ãƒ«"
-#: lib/merge.tcl:266
+#: lib/merge.tcl:267
msgid "Abort failed."
msgstr "中断ã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
-#: lib/merge.tcl:268
+#: lib/merge.tcl:269
msgid "Abort completed. Ready."
msgstr "中断完了。"
-#: lib/option.tcl:95
+#: lib/mergetool.tcl:8
+msgid "Force resolution to the base version?"
+msgstr "共通ã®ç‰ˆã‚’使ã„ã¾ã™ã‹?"
+
+#: lib/mergetool.tcl:9
+msgid "Force resolution to this branch?"
+msgstr "自分ã®å´ã®ç‰ˆã‚’使ã„ã¾ã™ã‹?"
+
+#: lib/mergetool.tcl:10
+msgid "Force resolution to the other branch?"
+msgstr "相手制ã®ç‰ˆã‚’使ã„ã¾ã™ã‹?"
+
+#: lib/mergetool.tcl:14
+#, tcl-format
+msgid ""
+"Note that the diff shows only conflicting changes.\n"
+"\n"
+"%s will be overwritten.\n"
+"\n"
+"This operation can be undone only by restarting the merge."
+msgstr ""
+"競åˆã™ã‚‹å¤‰æ›´ç‚¹ã ã‘ãŒè¡¨ç¤ºã•ã‚Œã¦ã„ã‚‹ã“ã¨ã«æ³¨æ„ã—ã¦ãã ã•ã„。\n"
+"\n"
+"%s ã¯ä¸Šæ›¸ãã•ã‚Œã¾ã™ã€‚\n"
+"\n"
+"ã‚„ã‚Šç›´ã™ã«ã¯ãƒžãƒ¼ã‚¸å…¨ä½“ã‚’ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
+
+#: lib/mergetool.tcl:45
+#, tcl-format
+msgid "File %s seems to have unresolved conflicts, still stage?"
+msgstr "ファイル %s ã«ã¯è§£æ±ºã—ã¦ã„ãªã„競åˆéƒ¨åˆ†ãŒã¾ã ã‚るよã†ã§ã™ãŒã€ã„ã„ã§ã™ã‹?"
+
+#: lib/mergetool.tcl:60
+#, tcl-format
+msgid "Adding resolution for %s"
+msgstr "%s ã¸ã®è§£æ±ºã‚’ステージã—ã¾ã™"
+
+#: lib/mergetool.tcl:141
+msgid "Cannot resolve deletion or link conflicts using a tool"
+msgstr "ツールã§ã¯å‰Šé™¤ã‚„リンク競åˆã¯æ‰±ãˆã¾ã›ã‚“"
+
+#: lib/mergetool.tcl:146
+msgid "Conflict file does not exist"
+msgstr "競åˆãƒ•ã‚¡ã‚¤ãƒ«ã¯å­˜åœ¨ã—ã¾ã›ã‚“。"
+
+#: lib/mergetool.tcl:264
+#, tcl-format
+msgid "Not a GUI merge tool: '%s'"
+msgstr "GUI マージツールã§ã¯ã‚ã‚Šã¾ã›ã‚“: %s"
+
+#: lib/mergetool.tcl:268
+#, tcl-format
+msgid "Unsupported merge tool '%s'"
+msgstr "マージツール '%s' ã¯ã‚µãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã›ã‚“"
+
+#: lib/mergetool.tcl:303
+msgid "Merge tool is already running, terminate it?"
+msgstr "マージツールã¯ã™ã§ã«èµ·å‹•ã—ã¦ã„ã¾ã™ã€‚終了ã—ã¾ã™ã‹?"
+
+#: lib/mergetool.tcl:323
+#, tcl-format
+msgid ""
+"Error retrieving versions:\n"
+"%s"
+msgstr ""
+"版ã®å–り出ã—時ã«ã‚¨ãƒ©ãƒ¼ãŒå‡ºã¾ã—ãŸ:\n"
+"%s"
+
+#: lib/mergetool.tcl:343
+#, tcl-format
+msgid ""
+"Could not start the merge tool:\n"
+"\n"
+"%s"
+msgstr ""
+"マージツールãŒèµ·å‹•ã§ãã¾ã›ã‚“:\n"
+"\n"
+"%s"
+
+#: lib/mergetool.tcl:347
+msgid "Running merge tool..."
+msgstr "マージツールを実行ã—ã¦ã„ã¾ã™..."
+
+#: lib/mergetool.tcl:375 lib/mergetool.tcl:383
+msgid "Merge tool failed."
+msgstr "マージツールãŒå¤±æ•—ã—ã¾ã—ãŸã€‚"
+
+#: lib/option.tcl:11
+#, tcl-format
+msgid "Invalid global encoding '%s'"
+msgstr "全体エンコーディング㫠無効㪠%s ãŒæŒ‡å®šã•ã‚Œã¦ã„ã¾ã™"
+
+#: lib/option.tcl:19
+#, tcl-format
+msgid "Invalid repo encoding '%s'"
+msgstr "リãƒã‚¸ãƒˆãƒªã‚¨ãƒ³ã‚³ãƒ¼ãƒ‡ã‚£ãƒ³ã‚°ã« 無効㪠%s ãŒæŒ‡å®šã•ã‚Œã¦ã„ã¾ã™"
+
+#: lib/option.tcl:117
msgid "Restore Defaults"
msgstr "既定値ã«æˆ»ã™"
-#: lib/option.tcl:99
+#: lib/option.tcl:121
msgid "Save"
msgstr "ä¿å­˜"
-#: lib/option.tcl:109
+#: lib/option.tcl:131
#, tcl-format
msgid "%s Repository"
msgstr "%s リãƒã‚¸ãƒˆãƒª"
-#: lib/option.tcl:110
+#: lib/option.tcl:132
msgid "Global (All Repositories)"
msgstr "大域(全ã¦ã®ãƒªãƒã‚¸ãƒˆãƒªï¼‰"
-#: lib/option.tcl:116
+#: lib/option.tcl:138
msgid "User Name"
msgstr "ユーザå"
-#: lib/option.tcl:117
+#: lib/option.tcl:139
msgid "Email Address"
msgstr "é›»å­ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹"
-#: lib/option.tcl:119
+#: lib/option.tcl:141
msgid "Summarize Merge Commits"
msgstr "マージコミットã®è¦ç´„"
-#: lib/option.tcl:120
+#: lib/option.tcl:142
msgid "Merge Verbosity"
msgstr "マージã®å†—長度"
-#: lib/option.tcl:121
+#: lib/option.tcl:143
msgid "Show Diffstat After Merge"
msgstr "マージ後㫠diffstat を表示"
-#: lib/option.tcl:123
+#: lib/option.tcl:144
+msgid "Use Merge Tool"
+msgstr "マージツールを使用"
+
+#: lib/option.tcl:146
msgid "Trust File Modification Timestamps"
msgstr "ファイル変更時刻を信頼ã™ã‚‹"
-#: lib/option.tcl:124
+#: lib/option.tcl:147
msgid "Prune Tracking Branches During Fetch"
msgstr "フェッãƒä¸­ã«ãƒˆãƒ©ãƒƒã‚­ãƒ³ã‚°ãƒ–ランãƒã‚’刈る"
-#: lib/option.tcl:125
+#: lib/option.tcl:148
msgid "Match Tracking Branches"
msgstr "トラッキングブランãƒã‚’åˆã‚ã›ã‚‹"
-#: lib/option.tcl:126
+#: lib/option.tcl:149
msgid "Blame Copy Only On Changed Files"
msgstr "変更ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã®ã¿ã‚³ãƒ”ー検知を行ãªã†"
-#: lib/option.tcl:127
+#: lib/option.tcl:150
msgid "Minimum Letters To Blame Copy On"
msgstr "コピーを検知ã™ã‚‹æœ€å°‘文字数"
-#: lib/option.tcl:128
+#: lib/option.tcl:151
+msgid "Blame History Context Radius (days)"
+msgstr "註釈ã™ã‚‹å±¥æ­´åŠå¾„(日数)"
+
+#: lib/option.tcl:152
msgid "Number of Diff Context Lines"
msgstr "diff ã®æ–‡è„ˆè¡Œæ•°"
-#: lib/option.tcl:129
+#: lib/option.tcl:153
msgid "Commit Message Text Width"
msgstr "コミットメッセージã®ãƒ†ã‚­ã‚¹ãƒˆå¹…"
-#: lib/option.tcl:130
+#: lib/option.tcl:154
msgid "New Branch Name Template"
msgstr "æ–°ã—ã„ブランãƒåã®ãƒ†ãƒ³ãƒ—レート"
-#: lib/option.tcl:194
+#: lib/option.tcl:155
+msgid "Default File Contents Encoding"
+msgstr "ファイル内容ã®ãƒ‡ãƒ•ã‚©ãƒ¼ãƒ«ãƒˆã‚¨ãƒ³ã‚³ãƒ¼ãƒ‡ã‚£ãƒ³ã‚°"
+
+#: lib/option.tcl:203
+msgid "Change"
+msgstr "変更"
+
+#: lib/option.tcl:230
msgid "Spelling Dictionary:"
msgstr "スペルãƒã‚§ãƒƒã‚¯è¾žæ›¸"
-#: lib/option.tcl:218
+#: lib/option.tcl:254
msgid "Change Font"
msgstr "フォントを変更"
-#: lib/option.tcl:222
+#: lib/option.tcl:258
#, tcl-format
msgid "Choose %s"
msgstr "%s ã‚’é¸æŠž"
-#: lib/option.tcl:228
+#: lib/option.tcl:264
msgid "pt."
msgstr "ãƒã‚¤ãƒ³ãƒˆ"
-#: lib/option.tcl:242
+#: lib/option.tcl:278
msgid "Preferences"
msgstr "設定"
-#: lib/option.tcl:277
+#: lib/option.tcl:314
msgid "Failed to completely save options:"
msgstr "完全ã«ã‚ªãƒ—ションをä¿å­˜ã§ãã¾ã›ã‚“:"
-#: lib/remote.tcl:165
+#: lib/remote.tcl:163
+msgid "Remove Remote"
+msgstr "リモートを削除"
+
+#: lib/remote.tcl:168
msgid "Prune from"
msgstr "ã‹ã‚‰åˆˆè¾¼ã‚€â€¦"
-#: lib/remote.tcl:170
+#: lib/remote.tcl:173
msgid "Fetch from"
msgstr "å–å¾—å…ƒ"
-#: lib/remote.tcl:213
+#: lib/remote.tcl:215
msgid "Push to"
msgstr "プッシュ先"
+#: lib/remote_add.tcl:19
+msgid "Add Remote"
+msgstr "リモートを追加"
+
+#: lib/remote_add.tcl:24
+msgid "Add New Remote"
+msgstr "リモートを新è¦ã«è¿½åŠ "
+
+#: lib/remote_add.tcl:28 lib/tools_dlg.tcl:36
+msgid "Add"
+msgstr "追加"
+
+#: lib/remote_add.tcl:37
+msgid "Remote Details"
+msgstr "リモートã®è©³ç´°"
+
+#: lib/remote_add.tcl:50
+msgid "Location:"
+msgstr "場所:"
+
+#: lib/remote_add.tcl:62
+msgid "Further Action"
+msgstr "ãã®ä»–ã®å‹•ä½œ"
+
+#: lib/remote_add.tcl:65
+msgid "Fetch Immediately"
+msgstr "å³åº§ã«å–å¾—"
+
+#: lib/remote_add.tcl:71
+msgid "Initialize Remote Repository and Push"
+msgstr "リモートレãƒã‚¸ãƒˆãƒªã‚’åˆæœŸåŒ–ã—ã¦ãƒ—ッシュ"
+
+#: lib/remote_add.tcl:77
+msgid "Do Nothing Else Now"
+msgstr "何もã—ãªã„"
+
+#: lib/remote_add.tcl:101
+msgid "Please supply a remote name."
+msgstr "リモートåを指定ã—ã¦ä¸‹ã•ã„。"
+
+#: lib/remote_add.tcl:114
+#, tcl-format
+msgid "'%s' is not an acceptable remote name."
+msgstr "'%s' ã¯ãƒªãƒ¢ãƒ¼ãƒˆåã«ä½¿ãˆã¾ã›ã‚“。"
+
+#: lib/remote_add.tcl:125
+#, tcl-format
+msgid "Failed to add remote '%s' of location '%s'."
+msgstr "場所 '%2$s' ã®ãƒªãƒ¢ãƒ¼ãƒˆ '%1$s'ã®åå‰å¤‰æ›´ã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
+
+#: lib/remote_add.tcl:133 lib/transport.tcl:6
+#, tcl-format
+msgid "fetch %s"
+msgstr "%s ã‚’å–å¾—"
+
+#: lib/remote_add.tcl:134
+#, tcl-format
+msgid "Fetching the %s"
+msgstr "%s ã‹ã‚‰ãƒ•ã‚§ãƒƒãƒã—ã¦ã„ã¾ã™"
+
+#: lib/remote_add.tcl:157
+#, tcl-format
+msgid "Do not know how to initialize repository at location '%s'."
+msgstr "リãƒã‚¸ãƒˆãƒª '%s' ã‚’åˆæœŸåŒ–ã§ãã¾ã›ã‚“。"
+
+#: lib/remote_add.tcl:163 lib/transport.tcl:25 lib/transport.tcl:71
+#, tcl-format
+msgid "push %s"
+msgstr "%s をプッシュ"
+
+#: lib/remote_add.tcl:164
+#, tcl-format
+msgid "Setting up the %s (at %s)"
+msgstr "%2$s ã«ã‚ã‚‹ %1$s をセットアップã—ã¾ã™"
+
#: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34
-msgid "Delete Remote Branch"
-msgstr "リモート・ブランãƒã‚’削除"
+msgid "Delete Branch Remotely"
+msgstr "é éš”ã§ãƒ–ランãƒå‰Šé™¤"
#: lib/remote_branch_delete.tcl:47
msgid "From Repository"
@@ -1819,8 +2174,8 @@ msgid "Remote:"
msgstr "リモート:"
#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:138
-msgid "Arbitrary URL:"
-msgstr "ä»»æ„ã® URL:"
+msgid "Arbitrary Location:"
+msgstr "ä»»æ„ã®ä½ç½®:"
#: lib/remote_branch_delete.tcl:84
msgid "Branches"
@@ -1890,6 +2245,22 @@ msgstr "リãƒã‚¸ãƒˆãƒªãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã›ã‚“。"
msgid "Scanning %s..."
msgstr "%s をスキャンã—ã¦ã„ã¾ã™â€¦"
+#: lib/search.tcl:21
+msgid "Find:"
+msgstr "検索:"
+
+#: lib/search.tcl:23
+msgid "Next"
+msgstr "次"
+
+#: lib/search.tcl:24
+msgid "Prev"
+msgstr "å‰"
+
+#: lib/search.tcl:25
+msgid "Case-Sensitive"
+msgstr "大文字å°æ–‡å­—を区別"
+
#: lib/shortcut.tcl:20 lib/shortcut.tcl:61
msgid "Cannot write shortcut:"
msgstr "ショートカットãŒæ›¸ã‘ã¾ã›ã‚“:"
@@ -1927,23 +2298,188 @@ msgstr "スペルãƒã‚§ãƒƒã‚«ãƒ¼ãŒåˆ¤åˆ¥ã§ãã¾ã›ã‚“"
msgid "No Suggestions"
msgstr "æ案ãªã—"
-#: lib/spellcheck.tcl:387
+#: lib/spellcheck.tcl:388
msgid "Unexpected EOF from spell checker"
msgstr "スペルãƒã‚§ãƒƒã‚«ãƒ¼ãŒäºˆæƒ³å¤–ã® EOF ã‚’è¿”ã—ã¾ã—ãŸ"
-#: lib/spellcheck.tcl:391
+#: lib/spellcheck.tcl:392
msgid "Spell Checker Failed"
msgstr "スペルãƒã‚§ãƒƒã‚¯å¤±æ•—"
+#: lib/sshkey.tcl:31
+msgid "No keys found."
+msgstr "キーãŒã‚ã‚Šã¾ã›ã‚“。"
+
+#: lib/sshkey.tcl:34
+#, tcl-format
+msgid "Found a public key in: %s"
+msgstr "公開éµãŒã‚ã‚Šã¾ã—ãŸ: %s"
+
+#: lib/sshkey.tcl:40
+msgid "Generate Key"
+msgstr "éµã‚’生æˆ"
+
+#: lib/sshkey.tcl:56
+msgid "Copy To Clipboard"
+msgstr "クリップボードã«ã‚³ãƒ”ー"
+
+#: lib/sshkey.tcl:70
+msgid "Your OpenSSH Public Key"
+msgstr "ã‚ãªãŸã® OpenSSH 公開éµ"
+
+#: lib/sshkey.tcl:78
+msgid "Generating..."
+msgstr "生æˆä¸­..."
+
+#: lib/sshkey.tcl:84
+#, tcl-format
+msgid ""
+"Could not start ssh-keygen:\n"
+"\n"
+"%s"
+msgstr ""
+"ssh-keygen ã‚’èµ·å‹•ã§ãã¾ã›ã‚“:\n"
+"\n"
+"%s"
+
+#: lib/sshkey.tcl:111
+msgid "Generation failed."
+msgstr "生æˆã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
+
+#: lib/sshkey.tcl:118
+msgid "Generation succeded, but no keys found."
+msgstr "生æˆã«ã¯æˆåŠŸã—ã¾ã—ãŸãŒã€éµãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。"
+
+#: lib/sshkey.tcl:121
+#, tcl-format
+msgid "Your key is in: %s"
+msgstr "ã‚ãªãŸã®éµã¯ %s ã«ã‚ã‚Šã¾ã™"
+
#: lib/status_bar.tcl:83
#, tcl-format
msgid "%s ... %*i of %*i %s (%3i%%)"
msgstr "%1$s ... %4$*i %6$s 中㮠%2$*i (%7$3i%%)"
-#: lib/transport.tcl:6
+#: lib/tools.tcl:75
#, tcl-format
-msgid "fetch %s"
-msgstr "%s ã‚’å–å¾—"
+msgid "Running %s requires a selected file."
+msgstr "ファイルをé¸æŠžã—ã¦ã‹ã‚‰ %s ã‚’èµ·å‹•ã—ã¦ãã ã•ã„。"
+
+#: lib/tools.tcl:90
+#, tcl-format
+msgid "Are you sure you want to run %s?"
+msgstr "本当㫠%s ã‚’èµ·å‹•ã—ã¾ã™ã‹?"
+
+#: lib/tools.tcl:110
+#, tcl-format
+msgid "Tool: %s"
+msgstr "ツール: %s"
+
+#: lib/tools.tcl:111
+#, tcl-format
+msgid "Running: %s"
+msgstr "実行中: %s"
+
+#: lib/tools.tcl:149
+#, tcl-format
+msgid "Tool completed succesfully: %s"
+msgstr "ツールãŒå®Œäº†ã—ã¾ã—ãŸ: %s"
+
+#: lib/tools.tcl:151
+#, tcl-format
+msgid "Tool failed: %s"
+msgstr "ツールãŒå¤±æ•—ã—ã¾ã—ãŸ: %s"
+
+#: lib/tools_dlg.tcl:22
+msgid "Add Tool"
+msgstr "ツールã®è¿½åŠ "
+
+#: lib/tools_dlg.tcl:28
+msgid "Add New Tool Command"
+msgstr "æ–°è¦ãƒ„ールコマンドã®è¿½åŠ "
+
+#: lib/tools_dlg.tcl:33
+msgid "Add globally"
+msgstr "全体ã«è¿½åŠ "
+
+#: lib/tools_dlg.tcl:45
+msgid "Tool Details"
+msgstr "ツールã®è©³ç´°"
+
+#: lib/tools_dlg.tcl:48
+msgid "Use '/' separators to create a submenu tree:"
+msgstr "'/' ã§ã‚µãƒ–メニューを区切りã¾ã™:"
+
+#: lib/tools_dlg.tcl:61
+msgid "Command:"
+msgstr "コマンド:"
+
+#: lib/tools_dlg.tcl:74
+msgid "Show a dialog before running"
+msgstr "èµ·å‹•ã™ã‚‹å‰ã«ãƒ€ã‚¤ã‚¢ãƒ­ã‚°ã‚’表示"
+
+#: lib/tools_dlg.tcl:80
+msgid "Ask the user to select a revision (sets $REVISION)"
+msgstr "ユーザã«ã‚³ãƒŸãƒƒãƒˆã‚’一ã¤é¸ã°ã›ã‚‹ ($REVISION ã«ã‚»ãƒƒãƒˆã—ã¾ã™)"
+
+#: lib/tools_dlg.tcl:85
+msgid "Ask the user for additional arguments (sets $ARGS)"
+msgstr "ユーザã«ä»–ã®å¼•æ•°ã‚’追加ã•ã›ã‚‹ ($ARGS ã«ã‚»ãƒƒãƒˆã—ã¾ã™)"
+
+#: lib/tools_dlg.tcl:92
+msgid "Don't show the command output window"
+msgstr "コマンドã‹ã‚‰ã®å‡ºåŠ›ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã‚’見ã›ãªã„"
+
+#: lib/tools_dlg.tcl:97
+msgid "Run only if a diff is selected ($FILENAME not empty)"
+msgstr "パッãƒãŒé¸ã°ã‚Œã¦ã„ã‚‹ã¨ãã ã‘å‹•ã‹ã™($FILENAME ãŒç©ºã§ãªã„)"
+
+#: lib/tools_dlg.tcl:121
+msgid "Please supply a name for the tool."
+msgstr "ツールåを指定ã—ã¦ä¸‹ã•ã„。"
+
+#: lib/tools_dlg.tcl:129
+#, tcl-format
+msgid "Tool '%s' already exists."
+msgstr "ツール '%s' ã¯æ—¢ã«å­˜åœ¨ã—ã¾ã™ã€‚"
+
+#: lib/tools_dlg.tcl:151
+#, tcl-format
+msgid ""
+"Could not add tool:\n"
+"%s"
+msgstr ""
+"ツールを追加ã§ãã¾ã›ã‚“:\n"
+"%s"
+
+#: lib/tools_dlg.tcl:190
+msgid "Remove Tool"
+msgstr "ツールã®å‰Šé™¤"
+
+#: lib/tools_dlg.tcl:196
+msgid "Remove Tool Commands"
+msgstr "ツールコマンドã®å‰Šé™¤"
+
+#: lib/tools_dlg.tcl:200
+msgid "Remove"
+msgstr "削除"
+
+#: lib/tools_dlg.tcl:236
+msgid "(Blue denotes repository-local tools)"
+msgstr "(é’色ã¯ãƒ­ãƒ¼ã‚«ãƒ«ãƒ¬ãƒã‚¸ãƒˆãƒªã®ãƒ„ールã§ã™)"
+
+#: lib/tools_dlg.tcl:297
+#, tcl-format
+msgid "Run Command: %s"
+msgstr "コマンドを起動: %s"
+
+#: lib/tools_dlg.tcl:311
+msgid "Arguments"
+msgstr "引数"
+
+#: lib/tools_dlg.tcl:348
+msgid "OK"
+msgstr "OK"
#: lib/transport.tcl:7
#, tcl-format
@@ -1960,17 +2496,17 @@ msgstr "é éš”刈込 %s"
msgid "Pruning tracking branches deleted from %s"
msgstr "%s ã‹ã‚‰å‰Šé™¤ã•ã‚ŒãŸãƒˆãƒ©ãƒƒã‚­ãƒ³ã‚°ãƒ»ãƒ–ランãƒã‚’刈ã£ã¦ã„ã¾ã™"
-#: lib/transport.tcl:25 lib/transport.tcl:71
-#, tcl-format
-msgid "push %s"
-msgstr "%s をプッシュ"
-
#: lib/transport.tcl:26
#, tcl-format
msgid "Pushing changes to %s"
msgstr "%s ã¸å¤‰æ›´ã‚’プッシュã—ã¦ã„ã¾ã™"
-#: lib/transport.tcl:72
+#: lib/transport.tcl:64
+#, tcl-format
+msgid "Mirroring to %s"
+msgstr "%s ã¸ãƒŸãƒ©ãƒ¼ã—ã¦ã„ã¾ã™"
+
+#: lib/transport.tcl:82
#, tcl-format
msgid "Pushing %s %s to %s"
msgstr "%3$s 㸠%1$s %2$s をプッシュã—ã¦ã„ã¾ã™"
diff --git a/git-gui/po/nb.po b/git-gui/po/nb.po
new file mode 100644
index 0000000000..1c5137d84c
--- /dev/null
+++ b/git-gui/po/nb.po
@@ -0,0 +1,2484 @@
+# Norwegian (Bokmål) translation of git-gui.
+# Copyright (C) 2007-2008 Shawn Pearce, et al.
+# This file is distributed under the same license as the git-gui package.
+#
+# Fredrik Skolmli <fredrik@frsk.net>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: nb\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2008-11-16 13:56-0800\n"
+"PO-Revision-Date: 2008-12-03 16:05+0100\n"
+"Last-Translator: Fredrik Skolmli <fredrik@frsk.net>\n"
+"Language-Team: Norwegian Bokmål\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: git-gui.sh:41 git-gui.sh:737 git-gui.sh:751 git-gui.sh:764 git-gui.sh:847
+#: git-gui.sh:866
+msgid "git-gui: fatal error"
+msgstr "git-gui: Kritisk feil"
+
+#: git-gui.sh:689
+#, tcl-format
+msgid "Invalid font specified in %s:"
+msgstr "Ugyldig font spesifisert i %s:"
+
+#: git-gui.sh:723
+msgid "Main Font"
+msgstr "Hovedskrifttype"
+
+#: git-gui.sh:724
+msgid "Diff/Console Font"
+msgstr "Diff-/Konsollskrifttype"
+
+#: git-gui.sh:738
+msgid "Cannot find git in PATH."
+msgstr "Kan ikke finne git i PATH"
+
+#: git-gui.sh:765
+msgid "Cannot parse Git version string:"
+msgstr "Kan ikke tyde Git's oppgitte versjon:"
+
+#: git-gui.sh:783
+#, tcl-format
+msgid ""
+"Git version cannot be determined.\n"
+"\n"
+"%s claims it is version '%s'.\n"
+"\n"
+"%s requires at least Git 1.5.0 or later.\n"
+"\n"
+"Assume '%s' is version 1.5.0?\n"
+msgstr ""
+"Kan ikke avgjøre hvilken Git-versjon du har.\n"
+"\n"
+"%s sier versjonen er '%s'.\n"
+"\n"
+"%s krever Git versjon 1.5.0 eller nyere.\n"
+"\n"
+"Anta at '%s' er versjon 1.5.0?\n"
+
+#: git-gui.sh:1062
+msgid "Git directory not found:"
+msgstr "Git-katalog ikke funnet:"
+
+#: git-gui.sh:1069
+msgid "Cannot move to top of working directory:"
+msgstr "Kan ikke gå til toppen av arbeidskatalogen:"
+
+#: git-gui.sh:1076
+msgid "Cannot use funny .git directory:"
+msgstr ""
+
+#: git-gui.sh:1081
+msgid "No working directory"
+msgstr "Ingen arbeidskatalog"
+
+#: git-gui.sh:1247 lib/checkout_op.tcl:305
+msgid "Refreshing file status..."
+msgstr "Oppdaterer filstatus..."
+
+#: git-gui.sh:1303
+msgid "Scanning for modified files ..."
+msgstr "Søker etter endrede filer..."
+
+#: git-gui.sh:1367
+msgid "Calling prepare-commit-msg hook..."
+msgstr ""
+
+#: git-gui.sh:1384
+msgid "Commit declined by prepare-commit-msg hook."
+msgstr ""
+
+#: git-gui.sh:1542 lib/browser.tcl:246
+msgid "Ready."
+msgstr "Klar."
+
+#: git-gui.sh:1819
+msgid "Unmodified"
+msgstr "Uendret"
+
+#: git-gui.sh:1821
+msgid "Modified, not staged"
+msgstr "Endret, ikke køet"
+
+#: git-gui.sh:1822 git-gui.sh:1830
+msgid "Staged for commit"
+msgstr "Køet for innsjekking"
+
+#: git-gui.sh:1823 git-gui.sh:1831
+msgid "Portions staged for commit"
+msgstr "Delvis køet for innsjekking"
+
+#: git-gui.sh:1824 git-gui.sh:1832
+msgid "Staged for commit, missing"
+msgstr "Klar for innsjekking, fraværende"
+
+#: git-gui.sh:1826
+msgid "File type changed, not staged"
+msgstr "Filtype endret, ikke køet"
+
+#: git-gui.sh:1827
+msgid "File type changed, staged"
+msgstr "Filtype endret, køet"
+
+#: git-gui.sh:1829
+msgid "Untracked, not staged"
+msgstr "Usporet, ikke køet"
+
+#: git-gui.sh:1834
+msgid "Missing"
+msgstr "Fraværende"
+
+#: git-gui.sh:1835
+msgid "Staged for removal"
+msgstr "Køet for fjerning"
+
+#: git-gui.sh:1836
+msgid "Staged for removal, still present"
+msgstr "Køet for fjerning, fortsatt tilstede"
+
+#: git-gui.sh:1838 git-gui.sh:1839 git-gui.sh:1840 git-gui.sh:1841
+#: git-gui.sh:1842 git-gui.sh:1843
+msgid "Requires merge resolution"
+msgstr "Sammenslåingen krever konflikthåndtering"
+
+#: git-gui.sh:1878
+msgid "Starting gitk... please wait..."
+msgstr "Starter gitk... Vennligst vent..."
+
+#: git-gui.sh:1887
+msgid "Couldn't find gitk in PATH"
+msgstr "Kunne ikke finne gitk i PATH"
+
+#: git-gui.sh:2280 lib/choose_repository.tcl:36
+msgid "Repository"
+msgstr "Arkiv"
+
+#: git-gui.sh:2281
+msgid "Edit"
+msgstr "Redigere"
+
+#: git-gui.sh:2283 lib/choose_rev.tcl:561
+msgid "Branch"
+msgstr "Gren"
+
+#: git-gui.sh:2286 lib/choose_rev.tcl:548
+msgid "Commit@@noun"
+msgstr "Innsjekking"
+
+#: git-gui.sh:2289 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168
+msgid "Merge"
+msgstr "Sammenslåing"
+
+#: git-gui.sh:2290 lib/choose_rev.tcl:557
+msgid "Remote"
+msgstr "Fjernarkiv"
+
+#: git-gui.sh:2293
+msgid "Tools"
+msgstr "Verktøy"
+
+#: git-gui.sh:2302
+msgid "Explore Working Copy"
+msgstr "Utforsk arbeidskopien"
+
+#: git-gui.sh:2307
+msgid "Browse Current Branch's Files"
+msgstr "Utforsk denne grens filer"
+
+#: git-gui.sh:2311
+msgid "Browse Branch Files..."
+msgstr "Bla igjennom filer på gren..."
+
+#: git-gui.sh:2316
+msgid "Visualize Current Branch's History"
+msgstr "Visualiser denne grens historikk"
+
+#: git-gui.sh:2320
+msgid "Visualize All Branch History"
+msgstr "Visualiser alle greners historikk"
+
+#: git-gui.sh:2327
+#, tcl-format
+msgid "Browse %s's Files"
+msgstr "Bla i filene til %s"
+
+#: git-gui.sh:2329
+#, tcl-format
+msgid "Visualize %s's History"
+msgstr "Visualiser historien til %s"
+
+#: git-gui.sh:2334 lib/database.tcl:27 lib/database.tcl:67
+msgid "Database Statistics"
+msgstr "Databasestatistikk"
+
+#: git-gui.sh:2337 lib/database.tcl:34
+msgid "Compress Database"
+msgstr "Kompress databasen"
+
+#: git-gui.sh:2340
+msgid "Verify Database"
+msgstr "Verifiser databasen"
+
+#: git-gui.sh:2347 git-gui.sh:2351 git-gui.sh:2355 lib/shortcut.tcl:7
+#: lib/shortcut.tcl:39 lib/shortcut.tcl:71
+msgid "Create Desktop Icon"
+msgstr "Lag skrivebordsikon"
+
+#: git-gui.sh:2363 lib/choose_repository.tcl:183 lib/choose_repository.tcl:191
+msgid "Quit"
+msgstr "Avslutt"
+
+#: git-gui.sh:2371
+msgid "Undo"
+msgstr "Angre"
+
+#: git-gui.sh:2374
+msgid "Redo"
+msgstr "Gjør om"
+
+#: git-gui.sh:2378 git-gui.sh:2923
+msgid "Cut"
+msgstr "Klipp ut"
+
+#: git-gui.sh:2381 git-gui.sh:2926 git-gui.sh:3000 git-gui.sh:3082
+#: lib/console.tcl:69
+msgid "Copy"
+msgstr "Kopier"
+
+#: git-gui.sh:2384 git-gui.sh:2929
+msgid "Paste"
+msgstr "Lim inn"
+
+#: git-gui.sh:2387 git-gui.sh:2932 lib/branch_delete.tcl:26
+#: lib/remote_branch_delete.tcl:38
+msgid "Delete"
+msgstr "Slett"
+
+#: git-gui.sh:2391 git-gui.sh:2936 git-gui.sh:3086 lib/console.tcl:71
+msgid "Select All"
+msgstr "Velg alle"
+
+#: git-gui.sh:2400
+msgid "Create..."
+msgstr "Opprett..."
+
+#: git-gui.sh:2406
+msgid "Checkout..."
+msgstr "Sjekk ut..."
+
+#: git-gui.sh:2412
+msgid "Rename..."
+msgstr "Endre navn..."
+
+#: git-gui.sh:2417
+msgid "Delete..."
+msgstr "Slett..."
+
+#: git-gui.sh:2422
+msgid "Reset..."
+msgstr "Tilbakestill..."
+
+#: git-gui.sh:2432
+msgid "Done"
+msgstr "Ferdig"
+
+#: git-gui.sh:2434
+msgid "Commit@@verb"
+msgstr "Sjekk inn"
+
+#: git-gui.sh:2443 git-gui.sh:2864
+msgid "New Commit"
+msgstr "Ny innsjekking"
+
+#: git-gui.sh:2451 git-gui.sh:2871
+msgid "Amend Last Commit"
+msgstr "Legg til forrige innsjekking"
+
+#: git-gui.sh:2461 git-gui.sh:2825 lib/remote_branch_delete.tcl:99
+msgid "Rescan"
+msgstr "Søk på ny"
+
+#: git-gui.sh:2467
+msgid "Stage To Commit"
+msgstr "Legg til i innsjekkingskøen"
+
+#: git-gui.sh:2473
+msgid "Stage Changed Files To Commit"
+msgstr "Legg til endrede filer i innsjekkingskøen"
+
+#: git-gui.sh:2479
+msgid "Unstage From Commit"
+msgstr "Fjern fra innsjekkingskøen"
+
+#: git-gui.sh:2484 lib/index.tcl:410
+msgid "Revert Changes"
+msgstr "Tilbakestill endringer"
+
+#: git-gui.sh:2491 git-gui.sh:3069
+msgid "Show Less Context"
+msgstr "Vis mindre innhold"
+
+#: git-gui.sh:2495 git-gui.sh:3073
+msgid "Show More Context"
+msgstr "Vis mer innhold"
+
+#: git-gui.sh:2502 git-gui.sh:2838 git-gui.sh:2947
+msgid "Sign Off"
+msgstr "Signér"
+
+#: git-gui.sh:2518
+msgid "Local Merge..."
+msgstr "Lokal sammenslåing..."
+
+#: git-gui.sh:2523
+msgid "Abort Merge..."
+msgstr "Avbryt sammenslåing..."
+
+#: git-gui.sh:2535 git-gui.sh:2575
+msgid "Add..."
+msgstr "Legg til..."
+
+#: git-gui.sh:2539
+msgid "Push..."
+msgstr "Send..."
+
+#: git-gui.sh:2543
+msgid "Delete Branch..."
+msgstr "Fjern gren..."
+
+#: git-gui.sh:2553 git-gui.sh:2589 lib/about.tcl:14
+#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:53
+#, tcl-format
+msgid "About %s"
+msgstr "Om %s"
+
+#: git-gui.sh:2557
+msgid "Preferences..."
+msgstr "Innstillinger..."
+
+#: git-gui.sh:2565 git-gui.sh:3115
+msgid "Options..."
+msgstr "Alternativer..."
+
+#: git-gui.sh:2576
+msgid "Remove..."
+msgstr "Fjern..."
+
+#: git-gui.sh:2585 lib/choose_repository.tcl:50
+msgid "Help"
+msgstr "Hjelp"
+
+#: git-gui.sh:2611
+msgid "Online Documentation"
+msgstr "Online dokumentasjon"
+
+#: git-gui.sh:2614 lib/choose_repository.tcl:47 lib/choose_repository.tcl:56
+msgid "Show SSH Key"
+msgstr "Vis SSH-nøkkel"
+
+#: git-gui.sh:2707
+#, tcl-format
+msgid "fatal: cannot stat path %s: No such file or directory"
+msgstr ""
+"kritisk: kunne ikke finne status for sti %s: Ingen slik fil eller katalog"
+
+#: git-gui.sh:2740
+msgid "Current Branch:"
+msgstr "Nåværende gren:"
+
+#: git-gui.sh:2761
+msgid "Staged Changes (Will Commit)"
+msgstr "Køede endringer (til innsjekking)"
+
+#: git-gui.sh:2781
+msgid "Unstaged Changes"
+msgstr "Ukøede endringer"
+
+#: git-gui.sh:2831
+msgid "Stage Changed"
+msgstr "Kø endret"
+
+#: git-gui.sh:2850 lib/transport.tcl:93 lib/transport.tcl:182
+msgid "Push"
+msgstr "Send"
+
+#: git-gui.sh:2885
+msgid "Initial Commit Message:"
+msgstr "Innledende innsjekkingsmelding:"
+
+#: git-gui.sh:2886
+msgid "Amended Commit Message:"
+msgstr "Utdypt innsjekkingsmelding"
+
+#: git-gui.sh:2887
+msgid "Amended Initial Commit Message:"
+msgstr "Utdypt innledende innsjekkingsmelding:"
+
+#: git-gui.sh:2888
+msgid "Amended Merge Commit Message:"
+msgstr "Utdypt innsjekkingsmelding for sammenslåing:"
+
+#: git-gui.sh:2889
+msgid "Merge Commit Message:"
+msgstr "Revisjonsmelding for sammenslåing:"
+
+#: git-gui.sh:2890
+msgid "Commit Message:"
+msgstr "Revisjonsmelding:"
+
+#: git-gui.sh:2939 git-gui.sh:3090 lib/console.tcl:73
+msgid "Copy All"
+msgstr "Kopier alle"
+
+#: git-gui.sh:2963 lib/blame.tcl:104
+msgid "File:"
+msgstr "Fil:"
+
+#: git-gui.sh:3078
+msgid "Refresh"
+msgstr "Oppdater"
+
+#: git-gui.sh:3099
+msgid "Decrease Font Size"
+msgstr "Gjør teksten mindre"
+
+#: git-gui.sh:3103
+msgid "Increase Font Size"
+msgstr "Gjør teksten større"
+
+#: git-gui.sh:3111 lib/blame.tcl:281
+msgid "Encoding"
+msgstr "Tekstkoding"
+
+#: git-gui.sh:3122
+msgid "Apply/Reverse Hunk"
+msgstr "Bruk/tilbakestill del"
+
+#: git-gui.sh:3127
+msgid "Apply/Reverse Line"
+msgstr "Bruk/tilbakestill linje"
+
+#: git-gui.sh:3137
+msgid "Run Merge Tool"
+msgstr "Start sammenslåingsprosess"
+
+#: git-gui.sh:3142
+msgid "Use Remote Version"
+msgstr "Bruk versjon fra fjernarkiv"
+
+#: git-gui.sh:3146
+msgid "Use Local Version"
+msgstr "Bruk lokal versjon"
+
+#: git-gui.sh:3150
+msgid "Revert To Base"
+msgstr "Tilbakestill til baseversjonen"
+
+#: git-gui.sh:3169
+msgid "Unstage Hunk From Commit"
+msgstr "Fjern delen fra innsjekkingskøen"
+
+#: git-gui.sh:3170
+msgid "Unstage Line From Commit"
+msgstr "Fjern linjen fra innsjekkingskøen"
+
+#: git-gui.sh:3172
+msgid "Stage Hunk For Commit"
+msgstr "Legg del i innsjekkingskøen"
+
+#: git-gui.sh:3173
+msgid "Stage Line For Commit"
+msgstr "Legg til linje i innsjekkingskøen"
+
+#: git-gui.sh:3196
+msgid "Initializing..."
+msgstr "Initsialiserer..."
+
+#: git-gui.sh:3301
+#, tcl-format
+msgid ""
+"Possible environment issues exist.\n"
+"\n"
+"The following environment variables are probably\n"
+"going to be ignored by any Git subprocess run\n"
+"by %s:\n"
+"\n"
+msgstr ""
+
+#: git-gui.sh:3331
+msgid ""
+"\n"
+"This is due to a known issue with the\n"
+"Tcl binary distributed by Cygwin."
+msgstr ""
+
+#: git-gui.sh:3336
+#, tcl-format
+msgid ""
+"\n"
+"\n"
+"A good replacement for %s\n"
+"is placing values for the user.name and\n"
+"user.email settings into your personal\n"
+"~/.gitconfig file.\n"
+msgstr ""
+
+#: lib/about.tcl:26
+msgid "git-gui - a graphical user interface for Git."
+msgstr "git-gui - Et grafisk brukergrensesnitt for Git."
+
+#: lib/blame.tcl:72
+msgid "File Viewer"
+msgstr "Filviser"
+
+#: lib/blame.tcl:78
+msgid "Commit:"
+msgstr "Innsjekking:"
+
+#: lib/blame.tcl:271
+msgid "Copy Commit"
+msgstr "Kopier innsjekking"
+
+#: lib/blame.tcl:275
+msgid "Find Text..."
+msgstr "Søk etter tekst..."
+
+#: lib/blame.tcl:284
+msgid "Do Full Copy Detection"
+msgstr "Gjennomfør full deteksjon av kopieringer"
+
+#: lib/blame.tcl:288
+msgid "Show History Context"
+msgstr "Vis historikkens innhold"
+
+#: lib/blame.tcl:291
+msgid "Blame Parent Commit"
+msgstr ""
+
+#: lib/blame.tcl:450
+#, tcl-format
+msgid "Reading %s..."
+msgstr "Leser %s..."
+
+#: lib/blame.tcl:557
+msgid "Loading copy/move tracking annotations..."
+msgstr ""
+
+#: lib/blame.tcl:577
+msgid "lines annotated"
+msgstr ""
+
+#: lib/blame.tcl:769
+msgid "Loading original location annotations..."
+msgstr ""
+
+#: lib/blame.tcl:772
+msgid "Annotation complete."
+msgstr ""
+
+#: lib/blame.tcl:802
+msgid "Busy"
+msgstr "Opptatt"
+
+#: lib/blame.tcl:803
+msgid "Annotation process is already running."
+msgstr ""
+
+#: lib/blame.tcl:842
+msgid "Running thorough copy detection..."
+msgstr "Kjører kopidetektering..."
+
+#: lib/blame.tcl:910
+msgid "Loading annotation..."
+msgstr ""
+
+#: lib/blame.tcl:964
+msgid "Author:"
+msgstr "Forfatter:"
+
+#: lib/blame.tcl:968
+msgid "Committer:"
+msgstr "Innsjekker:"
+
+#: lib/blame.tcl:973
+msgid "Original File:"
+msgstr "Opprinnelig fil:"
+
+#: lib/blame.tcl:1021
+msgid "Cannot find HEAD commit:"
+msgstr "Finner ikke HEAD's innsjekking:"
+
+#: lib/blame.tcl:1076
+msgid "Cannot find parent commit:"
+msgstr "Kan ikke finne innsjekkingens forelder:"
+
+#: lib/blame.tcl:1091
+msgid "Unable to display parent"
+msgstr "Kan ikke vise forelder"
+
+#: lib/blame.tcl:1092 lib/diff.tcl:297
+msgid "Error loading diff:"
+msgstr "Feil ved innlasting av forskjell:"
+
+#: lib/blame.tcl:1232
+msgid "Originally By:"
+msgstr "Opprinnelig av:"
+
+#: lib/blame.tcl:1238
+msgid "In File:"
+msgstr "I fil:"
+
+#: lib/blame.tcl:1243
+msgid "Copied Or Moved Here By:"
+msgstr "Kopiert eller flyttet hit av:"
+
+#: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19
+msgid "Checkout Branch"
+msgstr "Sjekk ut gren"
+
+#: lib/branch_checkout.tcl:23
+msgid "Checkout"
+msgstr "Utsjekking"
+
+#: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35
+#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:282
+#: lib/checkout_op.tcl:544 lib/choose_font.tcl:43 lib/merge.tcl:172
+#: lib/option.tcl:125 lib/remote_add.tcl:32 lib/remote_branch_delete.tcl:42
+#: lib/tools_dlg.tcl:40 lib/tools_dlg.tcl:204 lib/tools_dlg.tcl:352
+#: lib/transport.tcl:97
+msgid "Cancel"
+msgstr "Avbryt"
+
+#: lib/branch_checkout.tcl:32 lib/browser.tcl:287 lib/tools_dlg.tcl:328
+msgid "Revision"
+msgstr "Revisjon"
+
+#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:280
+msgid "Options"
+msgstr "Valg"
+
+#: lib/branch_checkout.tcl:39 lib/branch_create.tcl:92
+msgid "Fetch Tracking Branch"
+msgstr "Hent sporet gren"
+
+#: lib/branch_checkout.tcl:44
+msgid "Detach From Local Branch"
+msgstr "Koble bort lokal gren"
+
+#: lib/branch_create.tcl:22
+msgid "Create Branch"
+msgstr "Opprett gren"
+
+#: lib/branch_create.tcl:27
+msgid "Create New Branch"
+msgstr "Opprett ny gren"
+
+#: lib/branch_create.tcl:31 lib/choose_repository.tcl:377
+msgid "Create"
+msgstr "Opprett"
+
+#: lib/branch_create.tcl:40
+msgid "Branch Name"
+msgstr "Navn på gren"
+
+#: lib/branch_create.tcl:43 lib/remote_add.tcl:39 lib/tools_dlg.tcl:50
+msgid "Name:"
+msgstr "Navn:"
+
+#: lib/branch_create.tcl:58
+msgid "Match Tracking Branch Name"
+msgstr "Bruk navn på sporet gren"
+
+#: lib/branch_create.tcl:66
+msgid "Starting Revision"
+msgstr "Starter revisjon"
+
+#: lib/branch_create.tcl:72
+msgid "Update Existing Branch:"
+msgstr "Oppdater eksisterende gren:"
+
+#: lib/branch_create.tcl:75
+msgid "No"
+msgstr "Nei"
+
+#: lib/branch_create.tcl:80
+msgid "Fast Forward Only"
+msgstr "Kun hurtigfremspoling"
+
+#: lib/branch_create.tcl:85 lib/checkout_op.tcl:536
+msgid "Reset"
+msgstr "Tilbakestill"
+
+#: lib/branch_create.tcl:97
+msgid "Checkout After Creation"
+msgstr "Sjekk ut etter oppretting"
+
+#: lib/branch_create.tcl:131
+msgid "Please select a tracking branch."
+msgstr "Velg en gren som skal følges."
+
+#: lib/branch_create.tcl:140
+#, tcl-format
+msgid "Tracking branch %s is not a branch in the remote repository."
+msgstr "Den fulgte grenen %s er ikke en gren i fjernarkivet."
+
+#: lib/branch_create.tcl:153 lib/branch_rename.tcl:86
+msgid "Please supply a branch name."
+msgstr "Angi et navn for grenen."
+
+#: lib/branch_create.tcl:164 lib/branch_rename.tcl:106
+#, tcl-format
+msgid "'%s' is not an acceptable branch name."
+msgstr "'%s' kan ikke brukes som navn på en gren."
+
+#: lib/branch_delete.tcl:15
+msgid "Delete Branch"
+msgstr "Fjern gren"
+
+#: lib/branch_delete.tcl:20
+msgid "Delete Local Branch"
+msgstr "Fjern lokal gren"
+
+#: lib/branch_delete.tcl:37
+msgid "Local Branches"
+msgstr "Lokale grener"
+
+#: lib/branch_delete.tcl:52
+msgid "Delete Only If Merged Into"
+msgstr "Fjern kun ved sammenslåing"
+
+#: lib/branch_delete.tcl:54
+msgid "Always (Do not perform merge test.)"
+msgstr "Alltid (Ikke utfør sammenslåingstest.)"
+
+#: lib/branch_delete.tcl:103
+#, tcl-format
+msgid "The following branches are not completely merged into %s:"
+msgstr "Følgende grener er ikke fullstendig slått sammen med %s:"
+
+#: lib/branch_delete.tcl:115
+msgid ""
+"Recovering deleted branches is difficult. \n"
+"\n"
+" Delete the selected branches?"
+msgstr ""
+"Gjenoppretting av fjernede grener er vanskelig. \n"
+"\n"
+" Fjern valgte grener?"
+
+#: lib/branch_delete.tcl:141
+#, tcl-format
+msgid ""
+"Failed to delete branches:\n"
+"%s"
+msgstr ""
+"Kunne ikke fjerne grener:\n"
+"%s"
+
+#: lib/branch_rename.tcl:14 lib/branch_rename.tcl:22
+msgid "Rename Branch"
+msgstr "Gi gren nytt navn"
+
+#: lib/branch_rename.tcl:26
+msgid "Rename"
+msgstr "Endre navn"
+
+#: lib/branch_rename.tcl:36
+msgid "Branch:"
+msgstr "Gren:"
+
+#: lib/branch_rename.tcl:39
+msgid "New Name:"
+msgstr "Nytt navn:"
+
+#: lib/branch_rename.tcl:75
+msgid "Please select a branch to rename."
+msgstr "Vennligst velg grenen du vil endre navn på."
+
+#: lib/branch_rename.tcl:96 lib/checkout_op.tcl:201
+#, tcl-format
+msgid "Branch '%s' already exists."
+msgstr "Grenen '%s' eksisterer allerede."
+
+#: lib/branch_rename.tcl:117
+#, tcl-format
+msgid "Failed to rename '%s'."
+msgstr "Kunne ikke endre navnet '%s'."
+
+#: lib/browser.tcl:17
+msgid "Starting..."
+msgstr "Starter..."
+
+#: lib/browser.tcl:26
+msgid "File Browser"
+msgstr "Utforsker"
+
+#: lib/browser.tcl:126 lib/browser.tcl:143
+#, tcl-format
+msgid "Loading %s..."
+msgstr "Laster %s..."
+
+#: lib/browser.tcl:187
+msgid "[Up To Parent]"
+msgstr "[Opp til forelder]"
+
+#: lib/browser.tcl:267 lib/browser.tcl:273
+msgid "Browse Branch Files"
+msgstr "Bla igjennom grenens filer"
+
+#: lib/browser.tcl:278 lib/choose_repository.tcl:394
+#: lib/choose_repository.tcl:480 lib/choose_repository.tcl:491
+#: lib/choose_repository.tcl:995
+msgid "Browse"
+msgstr "Bla igjennom"
+
+#: lib/checkout_op.tcl:84
+#, tcl-format
+msgid "Fetching %s from %s"
+msgstr "Henter %s fra %s"
+
+#: lib/checkout_op.tcl:132
+#, tcl-format
+msgid "fatal: Cannot resolve %s"
+msgstr "kritisk: Kan ikke åpne %s"
+
+#: lib/checkout_op.tcl:145 lib/console.tcl:81 lib/database.tcl:31
+#: lib/sshkey.tcl:53
+msgid "Close"
+msgstr "Lukk"
+
+#: lib/checkout_op.tcl:174
+#, tcl-format
+msgid "Branch '%s' does not exist."
+msgstr "Grenen '%s' eksisterer ikke."
+
+#: lib/checkout_op.tcl:193
+#, tcl-format
+msgid "Failed to configure simplified git-pull for '%s'."
+msgstr "Kunne ikke konfigurere forenklet git-pull for '%s'."
+
+#: lib/checkout_op.tcl:228
+#, tcl-format
+msgid ""
+"Branch '%s' already exists.\n"
+"\n"
+"It cannot fast-forward to %s.\n"
+"A merge is required."
+msgstr ""
+"Grenen '%s' eksisterer allerede.\n"
+"\n"
+"Den kan ikke hurtigfremspoles til %s.\n"
+"En sammenslåing er påkrevd."
+
+#: lib/checkout_op.tcl:242
+#, tcl-format
+msgid "Merge strategy '%s' not supported."
+msgstr "Sammenslåingsstrategien '%s' er ikke støttet."
+
+#: lib/checkout_op.tcl:261
+#, tcl-format
+msgid "Failed to update '%s'."
+msgstr "Kunne ikke oppdatere '%s'."
+
+#: lib/checkout_op.tcl:273
+msgid "Staging area (index) is already locked."
+msgstr "Køområdet (index) er allerede låst."
+
+#: lib/checkout_op.tcl:288
+msgid ""
+"Last scanned state does not match repository state.\n"
+"\n"
+"Another Git program has modified this repository since the last scan. A "
+"rescan must be performed before the current branch can be changed.\n"
+"\n"
+"The rescan will be automatically started now.\n"
+msgstr ""
+
+#: lib/checkout_op.tcl:344
+#, tcl-format
+msgid "Updating working directory to '%s'..."
+msgstr "Oppdaterer arbeidskatalogen til '%s'..."
+
+#: lib/checkout_op.tcl:345
+msgid "files checked out"
+msgstr "filer sjekket ut"
+
+#: lib/checkout_op.tcl:375
+#, tcl-format
+msgid "Aborted checkout of '%s' (file level merging is required)."
+msgstr "Avbrøt utsjekkingen av '%s' (sammenslåing på filnivå kreves)."
+
+#: lib/checkout_op.tcl:376
+msgid "File level merge required."
+msgstr "Sammenslåing på filnivå kreves"
+
+#: lib/checkout_op.tcl:380
+#, tcl-format
+msgid "Staying on branch '%s'."
+msgstr "Blir stående på grenen '%s'."
+
+#: lib/checkout_op.tcl:451
+msgid ""
+"You are no longer on a local branch.\n"
+"\n"
+"If you wanted to be on a branch, create one now starting from 'This Detached "
+"Checkout'."
+msgstr ""
+
+#: lib/checkout_op.tcl:468 lib/checkout_op.tcl:472
+#, tcl-format
+msgid "Checked out '%s'."
+msgstr "Sjekket ut '%s'."
+
+#: lib/checkout_op.tcl:500
+#, tcl-format
+msgid "Resetting '%s' to '%s' will lose the following commits:"
+msgstr ""
+"Tilbakestilling av '%s' til '%s' vil medføre tap av følgende innsjekkinger:"
+
+#: lib/checkout_op.tcl:522
+msgid "Recovering lost commits may not be easy."
+msgstr ""
+"Det vil kanskje ikke være så enkelt å gjenopprette en tapt innsjekking."
+
+#: lib/checkout_op.tcl:527
+#, tcl-format
+msgid "Reset '%s'?"
+msgstr "Tilbakestill '%s'?"
+
+#: lib/checkout_op.tcl:532 lib/merge.tcl:164 lib/tools_dlg.tcl:343
+msgid "Visualize"
+msgstr "Visualiser"
+
+#: lib/checkout_op.tcl:600
+#, tcl-format
+msgid ""
+"Failed to set current branch.\n"
+"\n"
+"This working directory is only partially switched. We successfully updated "
+"your files, but failed to update an internal Git file.\n"
+"\n"
+"This should not have occurred. %s will now close and give up."
+msgstr ""
+
+#: lib/choose_font.tcl:39
+msgid "Select"
+msgstr "Velg"
+
+#: lib/choose_font.tcl:53
+msgid "Font Family"
+msgstr "Skrifttype-familie"
+
+#: lib/choose_font.tcl:74
+msgid "Font Size"
+msgstr "Skriftstørrelse"
+
+#: lib/choose_font.tcl:91
+msgid "Font Example"
+msgstr "Skrifteksempel"
+
+#: lib/choose_font.tcl:103
+msgid ""
+"This is example text.\n"
+"If you like this text, it can be your font."
+msgstr ""
+"Dette er en eksempeltekst.\n"
+"Hvis du liker hvordan teksten ser ut, kan du velge dette som din skrifttype."
+
+#: lib/choose_repository.tcl:28
+msgid "Git Gui"
+msgstr "Git Gui"
+
+#: lib/choose_repository.tcl:87 lib/choose_repository.tcl:382
+msgid "Create New Repository"
+msgstr "Opprett nytt arkiv"
+
+#: lib/choose_repository.tcl:93
+msgid "New..."
+msgstr "Ny..."
+
+#: lib/choose_repository.tcl:100 lib/choose_repository.tcl:465
+msgid "Clone Existing Repository"
+msgstr "Klon eksistererende arkiv"
+
+#: lib/choose_repository.tcl:106
+msgid "Clone..."
+msgstr "Klon..."
+
+#: lib/choose_repository.tcl:113 lib/choose_repository.tcl:983
+msgid "Open Existing Repository"
+msgstr "Ã…pne eksistererende arkiv"
+
+#: lib/choose_repository.tcl:119
+msgid "Open..."
+msgstr "Ã…pne..."
+
+#: lib/choose_repository.tcl:132
+msgid "Recent Repositories"
+msgstr "Nylig brukte arkiv"
+
+#: lib/choose_repository.tcl:138
+msgid "Open Recent Repository:"
+msgstr "Ã…pne nylig brukt arkiv:"
+
+#: lib/choose_repository.tcl:302 lib/choose_repository.tcl:309
+#: lib/choose_repository.tcl:316
+#, tcl-format
+msgid "Failed to create repository %s:"
+msgstr "Kunne ikke opprette arkivet %s:"
+
+#: lib/choose_repository.tcl:387
+msgid "Directory:"
+msgstr "Mappe:"
+
+#: lib/choose_repository.tcl:417 lib/choose_repository.tcl:544
+#: lib/choose_repository.tcl:1017
+msgid "Git Repository"
+msgstr "Git arkiv"
+
+#: lib/choose_repository.tcl:442
+#, tcl-format
+msgid "Directory %s already exists."
+msgstr "Mappen %s eksisterer allerede."
+
+#: lib/choose_repository.tcl:446
+#, tcl-format
+msgid "File %s already exists."
+msgstr "Filen %s eksisterer allerede."
+
+#: lib/choose_repository.tcl:460
+msgid "Clone"
+msgstr "Klon"
+
+#: lib/choose_repository.tcl:473
+msgid "Source Location:"
+msgstr "Kildeplassering:"
+
+#: lib/choose_repository.tcl:484
+msgid "Target Directory:"
+msgstr "Destinasjonsmappe:"
+
+#: lib/choose_repository.tcl:496
+msgid "Clone Type:"
+msgstr "Klontype:"
+
+#: lib/choose_repository.tcl:502
+msgid "Standard (Fast, Semi-Redundant, Hardlinks)"
+msgstr "Standard (rask, delvis redundant, hardlinker)"
+
+#: lib/choose_repository.tcl:508
+msgid "Full Copy (Slower, Redundant Backup)"
+msgstr "Full kopi (tregere, redundant sikkerhetskopi)"
+
+#: lib/choose_repository.tcl:514
+msgid "Shared (Fastest, Not Recommended, No Backup)"
+msgstr "Delt (raskest, ikke anbefalt, ingen sikkerhetskopiering)"
+
+#: lib/choose_repository.tcl:550 lib/choose_repository.tcl:597
+#: lib/choose_repository.tcl:743 lib/choose_repository.tcl:813
+#: lib/choose_repository.tcl:1023 lib/choose_repository.tcl:1031
+#, tcl-format
+msgid "Not a Git repository: %s"
+msgstr "Ikke et Git-arkiv: %s"
+
+#: lib/choose_repository.tcl:586
+msgid "Standard only available for local repository."
+msgstr "Standard er kun tilgjengelig for lokalt arkiv."
+
+#: lib/choose_repository.tcl:590
+msgid "Shared only available for local repository."
+msgstr "Delt er kun tilgjengelig for lokalt arkiv."
+
+#: lib/choose_repository.tcl:611
+#, tcl-format
+msgid "Location %s already exists."
+msgstr "Stedet %s eksisterer allerede."
+
+#: lib/choose_repository.tcl:622
+msgid "Failed to configure origin"
+msgstr "Kunne ikke konfigurere kildeoppføring"
+
+#: lib/choose_repository.tcl:634
+msgid "Counting objects"
+msgstr "Teller objekter"
+
+#: lib/choose_repository.tcl:635
+msgid "buckets"
+msgstr "bøtter"
+
+#: lib/choose_repository.tcl:659
+#, tcl-format
+msgid "Unable to copy objects/info/alternates: %s"
+msgstr "Kunne ikke kopiere objekter/informasjon/alternativt: %s"
+
+#: lib/choose_repository.tcl:695
+#, tcl-format
+msgid "Nothing to clone from %s."
+msgstr "Ingenting å klone fra %s."
+
+#: lib/choose_repository.tcl:697 lib/choose_repository.tcl:911
+#: lib/choose_repository.tcl:923
+msgid "The 'master' branch has not been initialized."
+msgstr "Grenen 'master' har ikke blitt initsialisert."
+
+#: lib/choose_repository.tcl:710
+msgid "Hardlinks are unavailable. Falling back to copying."
+msgstr "Harde linker er utilgjengelig. GÃ¥r tilbake til kopiering."
+
+#: lib/choose_repository.tcl:722
+#, tcl-format
+msgid "Cloning from %s"
+msgstr "Kloner fra %s"
+
+#: lib/choose_repository.tcl:753
+msgid "Copying objects"
+msgstr "Kopierer objekter"
+
+#: lib/choose_repository.tcl:754
+msgid "KiB"
+msgstr "kB"
+
+#: lib/choose_repository.tcl:778
+#, tcl-format
+msgid "Unable to copy object: %s"
+msgstr "Kunne ikke kopiere objekt: %s"
+
+#: lib/choose_repository.tcl:788
+msgid "Linking objects"
+msgstr "Lenker objekter"
+
+#: lib/choose_repository.tcl:789
+msgid "objects"
+msgstr "objekter"
+
+#: lib/choose_repository.tcl:797
+#, tcl-format
+msgid "Unable to hardlink object: %s"
+msgstr "Kunne ikke opprette hardlink med objektet: %s"
+
+#: lib/choose_repository.tcl:852
+msgid "Cannot fetch branches and objects. See console output for details."
+msgstr "Kunne ikke hente grener og objekter. Se utdata i konsoll for detaljer."
+
+#: lib/choose_repository.tcl:863
+msgid "Cannot fetch tags. See console output for details."
+msgstr "Kunne ikke hente tagger. Se utdata i konsoll for detaljer."
+
+#: lib/choose_repository.tcl:887
+msgid "Cannot determine HEAD. See console output for details."
+msgstr "Kan ikke bestemme HEAD. Se utdata i konsoll for detaljer."
+
+#: lib/choose_repository.tcl:896
+#, tcl-format
+msgid "Unable to cleanup %s"
+msgstr "Kunne ikke rydde opp %s"
+
+#: lib/choose_repository.tcl:902
+msgid "Clone failed."
+msgstr "Kloning feilet."
+
+#: lib/choose_repository.tcl:909
+msgid "No default branch obtained."
+msgstr "Ingen standardgren hentet."
+
+#: lib/choose_repository.tcl:920
+#, tcl-format
+msgid "Cannot resolve %s as a commit."
+msgstr "Kan ikke finne %s som en innsjekking."
+
+#: lib/choose_repository.tcl:932
+msgid "Creating working directory"
+msgstr "Oppretter arbeidskatalog"
+
+#: lib/choose_repository.tcl:933 lib/index.tcl:65 lib/index.tcl:128
+#: lib/index.tcl:196
+msgid "files"
+msgstr "filer"
+
+#: lib/choose_repository.tcl:962
+msgid "Initial file checkout failed."
+msgstr "Initsialiserende utsjekking feilet."
+
+#: lib/choose_repository.tcl:978
+msgid "Open"
+msgstr "Ã…pne"
+
+#: lib/choose_repository.tcl:988
+msgid "Repository:"
+msgstr "Arkiv:"
+
+#: lib/choose_repository.tcl:1037
+#, tcl-format
+msgid "Failed to open repository %s:"
+msgstr "Kunne ikke åpne arkivet %s:"
+
+#: lib/choose_rev.tcl:53
+msgid "This Detached Checkout"
+msgstr "Denne frakoblede utsjekkingen"
+
+#: lib/choose_rev.tcl:60
+msgid "Revision Expression:"
+msgstr "Revisjonsuttrykk:"
+
+#: lib/choose_rev.tcl:74
+msgid "Local Branch"
+msgstr "Lokal gren"
+
+#: lib/choose_rev.tcl:79
+msgid "Tracking Branch"
+msgstr "Sporet gren"
+
+#: lib/choose_rev.tcl:84 lib/choose_rev.tcl:538
+msgid "Tag"
+msgstr "Tag"
+
+#: lib/choose_rev.tcl:317
+#, tcl-format
+msgid "Invalid revision: %s"
+msgstr "Ugyldig revisjon: %s"
+
+#: lib/choose_rev.tcl:338
+msgid "No revision selected."
+msgstr "Ingen revisjoner valgt."
+
+#: lib/choose_rev.tcl:346
+msgid "Revision expression is empty."
+msgstr "Revisjonsuttrykk er tomt."
+
+#: lib/choose_rev.tcl:531
+msgid "Updated"
+msgstr "Oppdatert"
+
+#: lib/choose_rev.tcl:559
+msgid "URL"
+msgstr "URL"
+
+#: lib/commit.tcl:9
+msgid ""
+"There is nothing to amend.\n"
+"\n"
+"You are about to create the initial commit. There is no commit before this "
+"to amend.\n"
+msgstr ""
+"Det er ingenting å legge til.\n"
+"\n"
+"Du er i ferd med å lage den initsialiserende revisjonen. Det er ingen "
+"tidligere revisjoner å tilføye.\n"
+
+#: lib/commit.tcl:18
+msgid ""
+"Cannot amend while merging.\n"
+"\n"
+"You are currently in the middle of a merge that has not been fully "
+"completed. You cannot amend the prior commit unless you first abort the "
+"current merge activity.\n"
+msgstr ""
+"Kan ikke tilføye under sammenslåing.\n"
+"\n"
+"Du er for øyeblikket under en pågående sammenslåing som ikke er fullført. Du "
+"kan ikke tilføye en tidligere revisjon med mindre du først avbryter denne "
+"sammenslåingen.\n"
+
+#: lib/commit.tcl:49
+msgid "Error loading commit data for amend:"
+msgstr "Feil ved innhenting av revisjonsdata for tilføying:"
+
+#: lib/commit.tcl:76
+msgid "Unable to obtain your identity:"
+msgstr "Kunne ikke avgjøre din identitet:"
+
+#: lib/commit.tcl:81
+msgid "Invalid GIT_COMMITTER_IDENT:"
+msgstr "Ugyldig GIT_COMMITTER_IDENT:"
+
+#: lib/commit.tcl:133
+msgid ""
+"Last scanned state does not match repository state.\n"
+"\n"
+"Another Git program has modified this repository since the last scan. A "
+"rescan must be performed before another commit can be created.\n"
+"\n"
+"The rescan will be automatically started now.\n"
+msgstr ""
+
+#: lib/commit.tcl:156
+#, tcl-format
+msgid ""
+"Unmerged files cannot be committed.\n"
+"\n"
+"File %s has merge conflicts. You must resolve them and stage the file "
+"before committing.\n"
+msgstr ""
+
+#: lib/commit.tcl:164
+#, tcl-format
+msgid ""
+"Unknown file state %s detected.\n"
+"\n"
+"File %s cannot be committed by this program.\n"
+msgstr ""
+"Ukjent filstatus %s er funnet.\n"
+"\n"
+"Filen %s kan ikke sjekkes inn av dette programmet.\n"
+
+#: lib/commit.tcl:172
+msgid ""
+"No changes to commit.\n"
+"\n"
+"You must stage at least 1 file before you can commit.\n"
+msgstr ""
+"Ingen endringer å sjekke inn.\n"
+"\n"
+"Du må køe minst en fil før du kan sjekke inn noe.\n"
+
+#: lib/commit.tcl:187
+msgid ""
+"Please supply a commit message.\n"
+"\n"
+"A good commit message has the following format:\n"
+"\n"
+"- First line: Describe in one sentence what you did.\n"
+"- Second line: Blank\n"
+"- Remaining lines: Describe why this change is good.\n"
+msgstr ""
+"Vennligst angi en revisjonsmelding.\n"
+"\n"
+"En god melding har følgende format:\n"
+"\n"
+"- Første linje: En beskrivelse av hva du har gjort i én setning.\n"
+"- Andre linje: Blank\n"
+"- Resterende linjer: Forklar hvorfor denne endringen er bra.\n"
+
+#: lib/commit.tcl:211
+#, tcl-format
+msgid "warning: Tcl does not support encoding '%s'."
+msgstr "advarsel: Tcl støtter ikke denne tegnkodingen '%s'."
+
+#: lib/commit.tcl:227
+msgid "Calling pre-commit hook..."
+msgstr ""
+
+#: lib/commit.tcl:242
+msgid "Commit declined by pre-commit hook."
+msgstr ""
+
+#: lib/commit.tcl:265
+msgid "Calling commit-msg hook..."
+msgstr ""
+
+#: lib/commit.tcl:280
+msgid "Commit declined by commit-msg hook."
+msgstr ""
+
+#: lib/commit.tcl:293
+msgid "Committing changes..."
+msgstr "Sjekker inn endringer..."
+
+#: lib/commit.tcl:309
+msgid "write-tree failed:"
+msgstr "Skriving til tre feilet:"
+
+#: lib/commit.tcl:310 lib/commit.tcl:354 lib/commit.tcl:374
+msgid "Commit failed."
+msgstr "Innsjekking feilet."
+
+#: lib/commit.tcl:327
+#, tcl-format
+msgid "Commit %s appears to be corrupt"
+msgstr "Revisjon %s ser ut til å være korrupt"
+
+#: lib/commit.tcl:332
+msgid ""
+"No changes to commit.\n"
+"\n"
+"No files were modified by this commit and it was not a merge commit.\n"
+"\n"
+"A rescan will be automatically started now.\n"
+msgstr ""
+"Ingen endringer til innsjekking.\n"
+"\n"
+"Ingen filer ble endret av denne revisjonen, og det var ikke en revisjon fra "
+"en sammenslåing.\n"
+"\n"
+"Et nytt søk vil bli startet automatisk.\n"
+
+#: lib/commit.tcl:339
+msgid "No changes to commit."
+msgstr "Ingen endringer til innsekking."
+
+#: lib/commit.tcl:353
+msgid "commit-tree failed:"
+msgstr "commit-tree feilet:"
+
+#: lib/commit.tcl:373
+msgid "update-ref failed:"
+msgstr "update-ref feilet:"
+
+#: lib/commit.tcl:461
+#, tcl-format
+msgid "Created commit %s: %s"
+msgstr "Opprettet innsjekking %s: %s"
+
+#: lib/console.tcl:59
+msgid "Working... please wait..."
+msgstr "Jobber... Vennligst vent..."
+
+#: lib/console.tcl:186
+msgid "Success"
+msgstr "Suksess"
+
+#: lib/console.tcl:200
+msgid "Error: Command Failed"
+msgstr "Feil: Kommandoen feilet"
+
+#: lib/database.tcl:43
+msgid "Number of loose objects"
+msgstr "Antall løse objekter"
+
+#: lib/database.tcl:44
+msgid "Disk space used by loose objects"
+msgstr "Diskplass brukt av løse objekter"
+
+#: lib/database.tcl:45
+msgid "Number of packed objects"
+msgstr "Antall pakkede objekter"
+
+#: lib/database.tcl:46
+msgid "Number of packs"
+msgstr "Antall pakker"
+
+#: lib/database.tcl:47
+msgid "Disk space used by packed objects"
+msgstr "Diskplass brukt av pakkede objekter"
+
+#: lib/database.tcl:48
+msgid "Packed objects waiting for pruning"
+msgstr "Pakkede objekter som avventer fjerning"
+
+#: lib/database.tcl:49
+msgid "Garbage files"
+msgstr "Avfallsfiler"
+
+#: lib/database.tcl:72
+msgid "Compressing the object database"
+msgstr "Komprimerer objektdatabasen"
+
+#: lib/database.tcl:83
+msgid "Verifying the object database with fsck-objects"
+msgstr "Verifiserer objektdatabasen med fsck-objects"
+
+#: lib/database.tcl:108
+#, tcl-format
+msgid ""
+"This repository currently has approximately %i loose objects.\n"
+"\n"
+"To maintain optimal performance it is strongly recommended that you compress "
+"the database when more than %i loose objects exist.\n"
+"\n"
+"Compress the database now?"
+msgstr ""
+"Dette arkivet inneholder omtrent %i 'løse' objekter.\n"
+"\n"
+"For å sikre en optimal ytelse er det sterkt anbefalt at du komprimerer "
+"databasen når det er flere enn %i 'løse' objekter i den.\n"
+"\n"
+"Komprimere databasen nå?"
+
+#: lib/date.tcl:25
+#, tcl-format
+msgid "Invalid date from Git: %s"
+msgstr "Ugyldig dato fra Git: %s"
+
+#: lib/diff.tcl:59
+#, tcl-format
+msgid ""
+"No differences detected.\n"
+"\n"
+"%s has no changes.\n"
+"\n"
+"The modification date of this file was updated by another application, but "
+"the content within the file was not changed.\n"
+"\n"
+"A rescan will be automatically started to find other files which may have "
+"the same state."
+msgstr ""
+"Ingen forandringer funnet.\n"
+"\n"
+"%s har ingen endringer.\n"
+"\n"
+"Tidsstempelet for endring på denne filen ble oppdatert av en annen "
+" applikasjon, men innholdet er uendret.\n"
+"\n"
+"En gjennomsøking vil nå starte automatisk for å se om andre filer har "
+"status."
+
+#: lib/diff.tcl:99
+#, tcl-format
+msgid "Loading diff of %s..."
+msgstr "Laster inn forskjellene av %s..."
+
+#: lib/diff.tcl:120
+msgid ""
+"LOCAL: deleted\n"
+"REMOTE:\n"
+msgstr "LOKAL: slettet\n"
+"FJERN:\n"
+
+#: lib/diff.tcl:125
+msgid ""
+"REMOTE: deleted\n"
+"LOCAL:\n"
+msgstr "FJERN: slettet\n"
+"LOKAL:\n"
+
+#: lib/diff.tcl:132
+msgid "LOCAL:\n"
+msgstr "LOKAL:\n"
+
+#: lib/diff.tcl:135
+msgid "REMOTE:\n"
+msgstr "FJERN:\n"
+
+#: lib/diff.tcl:197 lib/diff.tcl:296
+#, tcl-format
+msgid "Unable to display %s"
+msgstr "Kan ikke vise %s"
+
+#: lib/diff.tcl:198
+msgid "Error loading file:"
+msgstr "Feil ved lesing av fil: %s"
+
+#: lib/diff.tcl:205
+msgid "Git Repository (subproject)"
+msgstr "Git-arkiv (underprosjekt)"
+
+#: lib/diff.tcl:217
+msgid "* Binary file (not showing content)."
+msgstr "* Binærfil (viser ikke innhold)"
+
+#: lib/diff.tcl:222
+#, tcl-format
+msgid ""
+"* Untracked file is %d bytes.\n"
+"* Showing only first %d bytes.\n"
+msgstr ""
+"* Usporet fil er %d bytes.\n"
+"* Viser bare %d første bytes.\n"
+
+#: lib/diff.tcl:228
+#, tcl-format
+msgid ""
+"\n"
+"* Untracked file clipped here by %s.\n"
+"* To see the entire file, use an external editor.\n"
+msgstr ""
+"\n"
+"* Usporede filer klippet her av %s.\n"
+"* For å se hele filen, bruk et eksternt redigeringsverktøy.\n"
+
+#: lib/diff.tcl:436
+msgid "Failed to unstage selected hunk."
+msgstr "Kunne ikke fjerne den valgte delen fra innsjekkingskøen."
+
+#: lib/diff.tcl:443
+msgid "Failed to stage selected hunk."
+msgstr "Kunne ikke legge til den valgte delen i innsjekkingskøen."
+
+#: lib/diff.tcl:509
+msgid "Failed to unstage selected line."
+msgstr "Kunne ikke fjerne den valgte linjen fra innsjekkingskøen."
+
+#: lib/diff.tcl:517
+msgid "Failed to stage selected line."
+msgstr "Kunne ikke legge til den valgte linjen i innsjekkingskøen."
+
+#: lib/encoding.tcl:443
+msgid "Default"
+msgstr "Standard"
+
+#: lib/encoding.tcl:448
+#, tcl-format
+msgid "System (%s)"
+msgstr "Systemets (%s)"
+
+#: lib/encoding.tcl:459 lib/encoding.tcl:465
+msgid "Other"
+msgstr "Andre"
+
+#: lib/error.tcl:20 lib/error.tcl:114
+msgid "error"
+msgstr "feil"
+
+#: lib/error.tcl:36
+msgid "warning"
+msgstr "advarsel"
+
+#: lib/error.tcl:94
+msgid "You must correct the above errors before committing."
+msgstr "Du må rette de ovenstående feilene før innsjekking."
+
+#: lib/index.tcl:6
+msgid "Unable to unlock the index."
+msgstr "Kunne ikke låse opp indexen."
+
+#: lib/index.tcl:15
+msgid "Index Error"
+msgstr "Feil på index"
+
+#: lib/index.tcl:21
+msgid ""
+"Updating the Git index failed. A rescan will be automatically started to "
+"resynchronize git-gui."
+msgstr ""
+"Oppdatering av Git's index mislyktes. Et nytt søk vil bli startet for å "
+"resynkronisere git-gui."
+
+#: lib/index.tcl:27
+msgid "Continue"
+msgstr "Fortsett"
+
+#: lib/index.tcl:31
+msgid "Unlock Index"
+msgstr "LÃ¥s opp index"
+
+#: lib/index.tcl:287
+#, tcl-format
+msgid "Unstaging %s from commit"
+msgstr "Fjerner %s fra innsjekkingskøen"
+
+#: lib/index.tcl:326
+msgid "Ready to commit."
+msgstr "Klar til innsjekking."
+
+#: lib/index.tcl:339
+#, tcl-format
+msgid "Adding %s"
+msgstr "Legger til %s"
+
+#: lib/index.tcl:396
+#, tcl-format
+msgid "Revert changes in file %s?"
+msgstr "Reverter endringene i filen %s?"
+
+#: lib/index.tcl:398
+#, tcl-format
+msgid "Revert changes in these %i files?"
+msgstr "Reverter endringene i disse %i filene?"
+
+#: lib/index.tcl:406
+msgid "Any unstaged changes will be permanently lost by the revert."
+msgstr "Endringer som ikke ligger i innsjekkingskøen vil bli tapt av denne "
+"reverteringen"
+
+#: lib/index.tcl:409
+msgid "Do Nothing"
+msgstr "Ikke gjør noe"
+
+#: lib/index.tcl:427
+msgid "Reverting selected files"
+msgstr "Reverterer valgte filer"
+
+#: lib/index.tcl:431
+#, tcl-format
+msgid "Reverting %s"
+msgstr "Reverterer %s"
+
+#: lib/merge.tcl:13
+msgid ""
+"Cannot merge while amending.\n"
+"\n"
+"You must finish amending this commit before starting any type of merge.\n"
+msgstr ""
+"Kunne ikke slå sammen under utvidelse.\n"
+"\n"
+"Du må først fullføre utvidelsen av denne revisjonen før du kan starte en "
+"sammenslåing.\n"
+
+#: lib/merge.tcl:27
+msgid ""
+"Last scanned state does not match repository state.\n"
+"\n"
+"Another Git program has modified this repository since the last scan. A "
+"rescan must be performed before a merge can be performed.\n"
+"\n"
+"The rescan will be automatically started now.\n"
+msgstr ""
+
+#: lib/merge.tcl:45
+#, tcl-format
+msgid ""
+"You are in the middle of a conflicted merge.\n"
+"\n"
+"File %s has merge conflicts.\n"
+"\n"
+"You must resolve them, stage the file, and commit to complete the current "
+"merge. Only then can you begin another merge.\n"
+msgstr ""
+
+#: lib/merge.tcl:55
+#, tcl-format
+msgid ""
+"You are in the middle of a change.\n"
+"\n"
+"File %s is modified.\n"
+"\n"
+"You should complete the current commit before starting a merge. Doing so "
+"will help you abort a failed merge, should the need arise.\n"
+msgstr ""
+
+#: lib/merge.tcl:107
+#, tcl-format
+msgid "%s of %s"
+msgstr "%s av %s"
+
+#: lib/merge.tcl:120
+#, tcl-format
+msgid "Merging %s and %s..."
+msgstr "Slår sammen %s og %s"
+
+#: lib/merge.tcl:131
+msgid "Merge completed successfully."
+msgstr "Vellykket sammenslåing fullført."
+
+#: lib/merge.tcl:133
+msgid "Merge failed. Conflict resolution is required."
+msgstr "Sammenslåing feilet. Håndtering av konflikten kreves."
+
+#: lib/merge.tcl:158
+#, tcl-format
+msgid "Merge Into %s"
+msgstr "Slå sammen inn i %s"
+
+#: lib/merge.tcl:177
+msgid "Revision To Merge"
+msgstr "Revisjon til sammenslåing"
+
+#: lib/merge.tcl:212
+msgid ""
+"Cannot abort while amending.\n"
+"\n"
+"You must finish amending this commit.\n"
+msgstr ""
+"Kan ikke avbryte under utvidelse av revisjon.\n"
+"\n"
+"Du må fullføre utvidelsen av denne revisjonen.\n"
+
+#: lib/merge.tcl:222
+msgid ""
+"Abort merge?\n"
+"\n"
+"Aborting the current merge will cause *ALL* uncommitted changes to be lost.\n"
+"\n"
+"Continue with aborting the current merge?"
+msgstr ""
+"Avbryt sammenslåing?\n"
+"\n"
+"Avbryting av pågående sammenslåing vil føre til at *alle* endringer som ikke "
+" er sjekket inn, vil gå tapt.\n"
+"\n"
+"Fortsette med å avbryte den pågående sammenslåingen?"
+
+#: lib/merge.tcl:228
+msgid ""
+"Reset changes?\n"
+"\n"
+"Resetting the changes will cause *ALL* uncommitted changes to be lost.\n"
+"\n"
+"Continue with resetting the current changes?"
+msgstr ""
+"Nullstill endringer?\n"
+"\n"
+"Nullstilling av endringer vil føre til at *alle* endringer som ikke er "
+"sjekket inn går tapt.\n"
+"\n"
+"Fortsette med nullstilling av endringer?"
+
+#: lib/merge.tcl:239
+msgid "Aborting"
+msgstr "Avbryter"
+
+#: lib/merge.tcl:239
+msgid "files reset"
+msgstr "filer tilbakestilt"
+
+#: lib/merge.tcl:267
+msgid "Abort failed."
+msgstr "Avbryting feilet."
+
+#: lib/merge.tcl:269
+msgid "Abort completed. Ready."
+msgstr "Avbryting fullført. Klar."
+
+#: lib/mergetool.tcl:8
+msgid "Force resolution to the base version?"
+msgstr "Tving håndtering til opprinnelig versjon?"
+
+#: lib/mergetool.tcl:9
+msgid "Force resolution to this branch?"
+msgstr "Tving håndtering i denne grenen?"
+
+#: lib/mergetool.tcl:10
+msgid "Force resolution to the other branch?"
+msgstr "Tving håndtering i den andre grenen?"
+
+#: lib/mergetool.tcl:14
+#, tcl-format
+msgid ""
+"Note that the diff shows only conflicting changes.\n"
+"\n"
+"%s will be overwritten.\n"
+"\n"
+"This operation can be undone only by restarting the merge."
+msgstr ""
+"Merk deg at endringsvisningen kun viser motstridende endringer.\n"
+"\n"
+"%s vil bli overskrevet.\n"
+"\n"
+"Denne operasjonen kan kun bli angret ved å starte sammenslåingen på ny."
+
+#: lib/mergetool.tcl:45
+#, tcl-format
+msgid "File %s seems to have unresolved conflicts, still stage?"
+msgstr "Filen %s ser ut til å ha uløste konflikter, skal filen likevel køes?"
+
+#: lib/mergetool.tcl:60
+#, tcl-format
+msgid "Adding resolution for %s"
+msgstr "Legger til løsninge på konflikt for %s"
+
+#: lib/mergetool.tcl:141
+msgid "Cannot resolve deletion or link conflicts using a tool"
+msgstr ""
+
+#: lib/mergetool.tcl:146
+msgid "Conflict file does not exist"
+msgstr "Konfliktfil eksisterer ikke"
+
+#: lib/mergetool.tcl:264
+#, tcl-format
+msgid "Not a GUI merge tool: '%s'"
+msgstr ""
+
+#: lib/mergetool.tcl:268
+#, tcl-format
+msgid "Unsupported merge tool '%s'"
+msgstr ""
+
+#: lib/mergetool.tcl:303
+msgid "Merge tool is already running, terminate it?"
+msgstr ""
+
+#: lib/mergetool.tcl:323
+#, tcl-format
+msgid ""
+"Error retrieving versions:\n"
+"%s"
+msgstr ""
+"Kunne ikke hente versjoner:\n"
+"%s"
+
+#: lib/mergetool.tcl:343
+#, tcl-format
+msgid ""
+"Could not start the merge tool:\n"
+"\n"
+"%s"
+msgstr ""
+
+#: lib/mergetool.tcl:347
+msgid "Running merge tool..."
+msgstr ""
+
+#: lib/mergetool.tcl:375 lib/mergetool.tcl:383
+msgid "Merge tool failed."
+msgstr ""
+
+#: lib/option.tcl:11
+#, tcl-format
+msgid "Invalid global encoding '%s'"
+msgstr ""
+
+#: lib/option.tcl:19
+#, tcl-format
+msgid "Invalid repo encoding '%s'"
+msgstr ""
+
+#: lib/option.tcl:117
+msgid "Restore Defaults"
+msgstr "Gjennopprett standardverdier"
+
+#: lib/option.tcl:121
+msgid "Save"
+msgstr "Lagre"
+
+#: lib/option.tcl:131
+#, tcl-format
+msgid "%s Repository"
+msgstr "%s arkiv"
+
+#: lib/option.tcl:132
+msgid "Global (All Repositories)"
+msgstr "Globalt (alle arkiv)"
+
+#: lib/option.tcl:138
+msgid "User Name"
+msgstr "Navn"
+
+#: lib/option.tcl:139
+msgid "Email Address"
+msgstr "Epost-adresse"
+
+#: lib/option.tcl:141
+msgid "Summarize Merge Commits"
+msgstr "Oppsummer innsjekkinger fra sammenslåinger"
+
+#: lib/option.tcl:142
+msgid "Merge Verbosity"
+msgstr "Detaljenivå på sammenslåing"
+
+#: lib/option.tcl:143
+msgid "Show Diffstat After Merge"
+msgstr "Vis endringsstatistikk etter sammenslåing"
+
+#: lib/option.tcl:144
+msgid "Use Merge Tool"
+msgstr "Bruk sammenslåingsverktøy"
+
+#: lib/option.tcl:146
+msgid "Trust File Modification Timestamps"
+msgstr "Stol på filers tid for endring"
+
+#: lib/option.tcl:147
+msgid "Prune Tracking Branches During Fetch"
+msgstr ""
+
+#: lib/option.tcl:148
+msgid "Match Tracking Branches"
+msgstr ""
+
+#: lib/option.tcl:149
+msgid "Blame Copy Only On Changed Files"
+msgstr ""
+
+#: lib/option.tcl:150
+msgid "Minimum Letters To Blame Copy On"
+msgstr ""
+
+#: lib/option.tcl:151
+msgid "Blame History Context Radius (days)"
+msgstr ""
+
+#: lib/option.tcl:152
+msgid "Number of Diff Context Lines"
+msgstr "Antall linjer sammenhengende endringer"
+
+#: lib/option.tcl:153
+msgid "Commit Message Text Width"
+msgstr "Tekstbredde for vindu til innsjekkingsmeldinger"
+
+#: lib/option.tcl:154
+msgid "New Branch Name Template"
+msgstr "Mal for navn på nye grener"
+
+#: lib/option.tcl:155
+msgid "Default File Contents Encoding"
+msgstr "Standard tekstenkoding for innhold i filer"
+
+#: lib/option.tcl:203
+msgid "Change"
+msgstr "Endre"
+
+#: lib/option.tcl:230
+msgid "Spelling Dictionary:"
+msgstr "Stavebokordlister:"
+
+#: lib/option.tcl:254
+msgid "Change Font"
+msgstr "Endre skrifttype"
+
+#: lib/option.tcl:258
+#, tcl-format
+msgid "Choose %s"
+msgstr "Velg %s"
+
+#: lib/option.tcl:264
+msgid "pt."
+msgstr "pt."
+
+#: lib/option.tcl:278
+msgid "Preferences"
+msgstr "Egenskaper"
+
+#: lib/option.tcl:314
+msgid "Failed to completely save options:"
+msgstr "Kunne ikke lagre alternativ:"
+
+#: lib/remote.tcl:163
+msgid "Remove Remote"
+msgstr "Fjern fjernarkiv"
+
+#: lib/remote.tcl:168
+msgid "Prune from"
+msgstr "Fjern fra"
+
+#: lib/remote.tcl:173
+msgid "Fetch from"
+msgstr "Hent fra"
+
+#: lib/remote.tcl:215
+msgid "Push to"
+msgstr "Send til"
+
+#: lib/remote_add.tcl:19
+msgid "Add Remote"
+msgstr "Legg til fjernarkiv"
+
+#: lib/remote_add.tcl:24
+msgid "Add New Remote"
+msgstr "Legg til nytt fjernarkiv"
+
+#: lib/remote_add.tcl:28 lib/tools_dlg.tcl:36
+msgid "Add"
+msgstr "Legg til"
+
+#: lib/remote_add.tcl:37
+msgid "Remote Details"
+msgstr "Detaljer for fjernarkiv"
+
+#: lib/remote_add.tcl:50
+msgid "Location:"
+msgstr "Lokasjon:"
+
+#: lib/remote_add.tcl:62
+msgid "Further Action"
+msgstr "Videre handling"
+
+#: lib/remote_add.tcl:65
+msgid "Fetch Immediately"
+msgstr "Hent umiddelbart"
+
+#: lib/remote_add.tcl:71
+msgid "Initialize Remote Repository and Push"
+msgstr "Initsialiser og send til fjernarkiv"
+
+#: lib/remote_add.tcl:77
+msgid "Do Nothing Else Now"
+msgstr "Ikke gjør mer nå"
+
+#: lib/remote_add.tcl:101
+msgid "Please supply a remote name."
+msgstr "Vennligst angi et navn for fjernarkivet."
+
+#: lib/remote_add.tcl:114
+#, tcl-format
+msgid "'%s' is not an acceptable remote name."
+msgstr "'%s' er ikke et tillatt navn for et fjernarkiv."
+
+#: lib/remote_add.tcl:125
+#, tcl-format
+msgid "Failed to add remote '%s' of location '%s'."
+msgstr "Kunne ikke legge til fjernarkivet '%s' på '%s'."
+
+#: lib/remote_add.tcl:133 lib/transport.tcl:6
+#, tcl-format
+msgid "fetch %s"
+msgstr "hent %s"
+
+#: lib/remote_add.tcl:134
+#, tcl-format
+msgid "Fetching the %s"
+msgstr "Henter %s"
+
+#: lib/remote_add.tcl:157
+#, tcl-format
+msgid "Do not know how to initialize repository at location '%s'."
+msgstr "Vet ikke hvordan arkiv på '%s' skal opprettes."
+
+#: lib/remote_add.tcl:163 lib/transport.tcl:25 lib/transport.tcl:71
+#, tcl-format
+msgid "push %s"
+msgstr "send %s"
+
+#: lib/remote_add.tcl:164
+#, tcl-format
+msgid "Setting up the %s (at %s)"
+msgstr "Initsialiserer %s (på %s)"
+
+#: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34
+msgid "Delete Branch Remotely"
+msgstr "Fjern gren fra fjernarkiv"
+
+#: lib/remote_branch_delete.tcl:47
+msgid "From Repository"
+msgstr "Fra arkiv"
+
+#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:123
+msgid "Remote:"
+msgstr "Fjernarkiv:"
+
+#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:138
+msgid "Arbitrary Location:"
+msgstr "Vilkårlig lokasjon:"
+
+#: lib/remote_branch_delete.tcl:84
+msgid "Branches"
+msgstr "Grener"
+
+#: lib/remote_branch_delete.tcl:109
+msgid "Delete Only If"
+msgstr "Slett kun hvis"
+
+#: lib/remote_branch_delete.tcl:111
+msgid "Merged Into:"
+msgstr "Slått sammen i:"
+
+#: lib/remote_branch_delete.tcl:119
+msgid "Always (Do not perform merge checks)"
+msgstr "Alltid (Ikke utfør sammenslåingskontroll)"
+
+#: lib/remote_branch_delete.tcl:152
+msgid "A branch is required for 'Merged Into'."
+msgstr "En gren kreves for 'sammenslåing i'."
+
+#: lib/remote_branch_delete.tcl:184
+#, tcl-format
+msgid ""
+"The following branches are not completely merged into %s:\n"
+"\n"
+" - %s"
+msgstr ""
+"Følgende grener er ikke fullestendig sammenslått med %s:\n"
+"\n"
+" - %s"
+
+#: lib/remote_branch_delete.tcl:189
+#, tcl-format
+msgid ""
+"One or more of the merge tests failed because you have not fetched the "
+"necessary commits. Try fetching from %s first."
+msgstr ""
+"En eller flere av testene som blir kjørt under sammenslåing feilet fordi du"
+"ikke har hentet inn de nødvendige innsjekkingene. Prøv å hent disse fra %s"
+"først"
+
+#: lib/remote_branch_delete.tcl:207
+msgid "Please select one or more branches to delete."
+msgstr "Velg en eller flere grener som skal fjernes."
+
+#: lib/remote_branch_delete.tcl:216
+msgid ""
+"Recovering deleted branches is difficult.\n"
+"\n"
+"Delete the selected branches?"
+msgstr ""
+"Gjenoppretting av fjernede grener er vanskelig.\n"
+"\n"
+"Fjern den merkede grenen?"
+
+#: lib/remote_branch_delete.tcl:226
+#, tcl-format
+msgid "Deleting branches from %s"
+msgstr "Fjerner grenene fra %s"
+
+#: lib/remote_branch_delete.tcl:286
+msgid "No repository selected."
+msgstr "Ingen arkiv valgt."
+
+#: lib/remote_branch_delete.tcl:291
+#, tcl-format
+msgid "Scanning %s..."
+msgstr "Søker %s..."
+
+#: lib/search.tcl:21
+msgid "Find:"
+msgstr "Finn:"
+
+#: lib/search.tcl:23
+msgid "Next"
+msgstr "Neste"
+
+#: lib/search.tcl:24
+msgid "Prev"
+msgstr "Forrige"
+
+#: lib/search.tcl:25
+msgid "Case-Sensitive"
+msgstr "Skiller på store og små bokstaver"
+
+#: lib/shortcut.tcl:20 lib/shortcut.tcl:61
+msgid "Cannot write shortcut:"
+msgstr "Kan ikke opprette snarvei:"
+
+#: lib/shortcut.tcl:136
+msgid "Cannot write icon:"
+msgstr "Kan ikke opprette ikon:"
+
+#: lib/spellcheck.tcl:57
+msgid "Unsupported spell checker"
+msgstr "Stavekontrolleren er ikke støttet"
+
+#: lib/spellcheck.tcl:65
+msgid "Spell checking is unavailable"
+msgstr "Stavekontroll er ikke tilgjengelig"
+
+#: lib/spellcheck.tcl:68
+msgid "Invalid spell checking configuration"
+msgstr "Ugyldig stavekontroll-konfigurasjon"
+
+#: lib/spellcheck.tcl:70
+#, tcl-format
+msgid "Reverting dictionary to %s."
+msgstr "Reverterer ordbok til %s."
+
+#: lib/spellcheck.tcl:73
+msgid "Spell checker silently failed on startup"
+msgstr "Stavekontrollen feilet stille under oppstart"
+
+#: lib/spellcheck.tcl:80
+msgid "Unrecognized spell checker"
+msgstr "Stavekontrolleren er ukjent"
+
+#: lib/spellcheck.tcl:186
+msgid "No Suggestions"
+msgstr "Ingen forslag"
+
+#: lib/spellcheck.tcl:388
+msgid "Unexpected EOF from spell checker"
+msgstr "Uventet slutt på filen fra stavekontrollen"
+
+#: lib/spellcheck.tcl:392
+msgid "Spell Checker Failed"
+msgstr "Stavekontroll mislyktes"
+
+#: lib/sshkey.tcl:31
+msgid "No keys found."
+msgstr "Ingen nøkler funnet."
+
+#: lib/sshkey.tcl:34
+#, tcl-format
+msgid "Found a public key in: %s"
+msgstr "Funnet en offentlig nøkkel i: %s"
+
+#: lib/sshkey.tcl:40
+msgid "Generate Key"
+msgstr "Generer nøkkel"
+
+#: lib/sshkey.tcl:56
+msgid "Copy To Clipboard"
+msgstr "Kopier til utklippstavlen"
+
+#: lib/sshkey.tcl:70
+msgid "Your OpenSSH Public Key"
+msgstr "Din offentlige OpenSSH-nøkkel"
+
+#: lib/sshkey.tcl:78
+msgid "Generating..."
+msgstr "Genererer..."
+
+#: lib/sshkey.tcl:84
+#, tcl-format
+msgid ""
+"Could not start ssh-keygen:\n"
+"\n"
+"%s"
+msgstr ""
+"Kunne ikke starte ssh-keygen:\n"
+"\n"
+"%s"
+
+#: lib/sshkey.tcl:111
+msgid "Generation failed."
+msgstr "Generering feilet."
+
+#: lib/sshkey.tcl:118
+msgid "Generation succeded, but no keys found."
+msgstr "Generering vellykket, men ingen nøkler er funnet."
+
+#: lib/sshkey.tcl:121
+#, tcl-format
+msgid "Your key is in: %s"
+msgstr "Nøkkelen din ligger i: %s"
+
+#: lib/status_bar.tcl:83
+#, tcl-format
+msgid "%s ... %*i of %*i %s (%3i%%)"
+msgstr "%s ... %*i av %*i %s (%3i%%)"
+
+#: lib/tools.tcl:75
+#, tcl-format
+msgid "Running %s requires a selected file."
+msgstr "Å kjøre %s krever at en fil er valgt"
+
+#: lib/tools.tcl:90
+#, tcl-format
+msgid "Are you sure you want to run %s?"
+msgstr "Er du sikker på at du vil kjøre %s?"
+
+#: lib/tools.tcl:110
+#, tcl-format
+msgid "Tool: %s"
+msgstr "Verktøy: %s"
+
+#: lib/tools.tcl:111
+#, tcl-format
+msgid "Running: %s"
+msgstr "Kjører: %s"
+
+#: lib/tools.tcl:149
+#, tcl-format
+msgid "Tool completed succesfully: %s"
+msgstr "Verktøyet ble fullført med suksess: %s"
+
+#: lib/tools.tcl:151
+#, tcl-format
+msgid "Tool failed: %s"
+msgstr "Verktøy feilet: %s"
+
+#: lib/tools_dlg.tcl:22
+msgid "Add Tool"
+msgstr "Legg til verktøy"
+
+#: lib/tools_dlg.tcl:28
+msgid "Add New Tool Command"
+msgstr "Legg til ny verktøykommando"
+
+#: lib/tools_dlg.tcl:33
+msgid "Add globally"
+msgstr "Legg til globalt"
+
+#: lib/tools_dlg.tcl:45
+msgid "Tool Details"
+msgstr "Verktøydetaljer"
+
+#: lib/tools_dlg.tcl:48
+msgid "Use '/' separators to create a submenu tree:"
+msgstr "Bruk '/'-separator for å lage undermenyer:"
+
+#: lib/tools_dlg.tcl:61
+msgid "Command:"
+msgstr "Kommando:"
+
+#: lib/tools_dlg.tcl:74
+msgid "Show a dialog before running"
+msgstr "Vis en dialog før start"
+
+#: lib/tools_dlg.tcl:80
+msgid "Ask the user to select a revision (sets $REVISION)"
+msgstr "Spør brukeren om å velge en revisjon (setter $REVISION)"
+
+#: lib/tools_dlg.tcl:85
+msgid "Ask the user for additional arguments (sets $ARGS)"
+msgstr "Spør brukeren for ytterligere paramtere (setter $ARGS)"
+
+#: lib/tools_dlg.tcl:92
+msgid "Don't show the command output window"
+msgstr "Ikke vis kommandoens utdata i vinduet"
+
+#: lib/tools_dlg.tcl:97
+msgid "Run only if a diff is selected ($FILENAME not empty)"
+msgstr "Kjør kun om forskjellene er markert ($FILENAME er ikke tom)"
+
+#: lib/tools_dlg.tcl:121
+msgid "Please supply a name for the tool."
+msgstr "Vennligst angi et navn for dette verktøyet."
+
+#: lib/tools_dlg.tcl:129
+#, tcl-format
+msgid "Tool '%s' already exists."
+msgstr "Verktøyet '%s' eksisterer allerede."
+
+#: lib/tools_dlg.tcl:151
+#, tcl-format
+msgid ""
+"Could not add tool:\n"
+"%s"
+msgstr ""
+"Kunne ikke legge til verktøyet:\n"
+"%s"
+
+#: lib/tools_dlg.tcl:190
+msgid "Remove Tool"
+msgstr "Fjern verktøyet"
+
+#: lib/tools_dlg.tcl:196
+msgid "Remove Tool Commands"
+msgstr "Fjern verktøyskommandoen"
+
+#: lib/tools_dlg.tcl:200
+msgid "Remove"
+msgstr "Fjern"
+
+#: lib/tools_dlg.tcl:236
+msgid "(Blue denotes repository-local tools)"
+msgstr "(Blue angir lokale verktøy til arkivet)"
+
+#: lib/tools_dlg.tcl:297
+#, tcl-format
+msgid "Run Command: %s"
+msgstr "Kjør kommando: %s"
+
+#: lib/tools_dlg.tcl:311
+msgid "Arguments"
+msgstr "Argumenter"
+
+#: lib/tools_dlg.tcl:348
+msgid "OK"
+msgstr "OK"
+
+#: lib/transport.tcl:7
+#, tcl-format
+msgid "Fetching new changes from %s"
+msgstr "Henter nye endringer fra %s"
+
+#: lib/transport.tcl:18
+#, tcl-format
+msgid "remote prune %s"
+msgstr "slett fjernarkiv %s"
+
+#: lib/transport.tcl:19
+#, tcl-format
+msgid "Pruning tracking branches deleted from %s"
+msgstr "Fjrner sporing av grener slettet fra %s"
+
+#: lib/transport.tcl:26
+#, tcl-format
+msgid "Pushing changes to %s"
+msgstr "Sender endringer til %s"
+
+#: lib/transport.tcl:72
+#, tcl-format
+msgid "Pushing %s %s to %s"
+msgstr "Sender %s %s til %s"
+
+#: lib/transport.tcl:89
+msgid "Push Branches"
+msgstr "Send grener"
+
+#: lib/transport.tcl:103
+msgid "Source Branches"
+msgstr "Kildegrener"
+
+#: lib/transport.tcl:120
+msgid "Destination Repository"
+msgstr "Destinasjonsarkiv"
+
+#: lib/transport.tcl:158
+msgid "Transfer Options"
+msgstr "Overføringsalternativer"
+
+#: lib/transport.tcl:160
+msgid "Force overwrite existing branch (may discard changes)"
+msgstr "Tving overskrivning av eksisterende gren (kan forkaste endringer)"
+
+#: lib/transport.tcl:164
+msgid "Use thin pack (for slow network connections)"
+msgstr "Bruk tynne pakker (for tregere nettverkstilkoblinger)"
+
+#: lib/transport.tcl:168
+msgid "Include tags"
+msgstr "Inkluder tagger"
diff --git a/git-gui/po/sv.po b/git-gui/po/sv.po
index 0196ba8cef..167654c709 100644
--- a/git-gui/po/sv.po
+++ b/git-gui/po/sv.po
@@ -1,48 +1,48 @@
# Swedish translation of git-gui.
-# Copyright (C) 2007 Shawn Pearce, et al.
+# Copyright (C) 2007-2008 Shawn Pearce, et al.
# This file is distributed under the same license as the git-gui package.
#
-# Peter Karlsson <peter@softwolves.pp.se>, 2007-2008.
+# Peter Krefting <peter@softwolves.pp.se>, 2007-2008.
# Mikael Magnusson <mikachu@gmail.com>, 2008.
msgid ""
msgstr ""
"Project-Id-Version: sv\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-08-03 01:34+0200\n"
-"PO-Revision-Date: 2008-08-03 01:45+0200\n"
-"Last-Translator: Mikael Magnusson <mikachu@gmail.com>\n"
+"POT-Creation-Date: 2008-12-08 08:31-0800\n"
+"PO-Revision-Date: 2008-12-10 09:49+0100\n"
+"Last-Translator: Peter Krefting <peter@softwolves.pp.se>\n"
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: git-gui.sh:41 git-gui.sh:688 git-gui.sh:702 git-gui.sh:715 git-gui.sh:798
-#: git-gui.sh:817
+#: git-gui.sh:41 git-gui.sh:737 git-gui.sh:751 git-gui.sh:764 git-gui.sh:847
+#: git-gui.sh:866
msgid "git-gui: fatal error"
msgstr "git-gui: ödesdigert fel"
-#: git-gui.sh:644
+#: git-gui.sh:689
#, tcl-format
msgid "Invalid font specified in %s:"
msgstr "Ogiltigt teckensnitt angivet i %s:"
-#: git-gui.sh:674
+#: git-gui.sh:723
msgid "Main Font"
msgstr "Huvudteckensnitt"
-#: git-gui.sh:675
+#: git-gui.sh:724
msgid "Diff/Console Font"
msgstr "Diff/konsolteckensnitt"
-#: git-gui.sh:689
+#: git-gui.sh:738
msgid "Cannot find git in PATH."
msgstr "Hittar inte git i PATH."
-#: git-gui.sh:716
+#: git-gui.sh:765
msgid "Cannot parse Git version string:"
msgstr "Kan inte tolka versionssträng från Git:"
-#: git-gui.sh:734
+#: git-gui.sh:783
#, tcl-format
msgid ""
"Git version cannot be determined.\n"
@@ -61,380 +61,449 @@ msgstr ""
"\n"
"Anta att \"%s\" är version 1.5.0?\n"
-#: git-gui.sh:972
+#: git-gui.sh:1062
msgid "Git directory not found:"
msgstr "Git-katalogen hittades inte:"
-#: git-gui.sh:979
+#: git-gui.sh:1069
msgid "Cannot move to top of working directory:"
msgstr "Kan inte gå till början på arbetskatalogen:"
-#: git-gui.sh:986
+#: git-gui.sh:1076
msgid "Cannot use funny .git directory:"
msgstr "Kan inte använda underlig .git-katalog:"
-#: git-gui.sh:991
+#: git-gui.sh:1081
msgid "No working directory"
msgstr "Ingen arbetskatalog"
-#: git-gui.sh:1138 lib/checkout_op.tcl:305
+#: git-gui.sh:1247 lib/checkout_op.tcl:305
msgid "Refreshing file status..."
msgstr "Uppdaterar filstatus..."
-#: git-gui.sh:1194
+#: git-gui.sh:1303
msgid "Scanning for modified files ..."
msgstr "Söker efter ändrade filer..."
-#: git-gui.sh:1369 lib/browser.tcl:246
+#: git-gui.sh:1367
+msgid "Calling prepare-commit-msg hook..."
+msgstr ""
+"Anropar kroken för förberedelse av incheckningsmeddelande (prepare-commit-"
+"msg)..."
+
+#: git-gui.sh:1384
+msgid "Commit declined by prepare-commit-msg hook."
+msgstr ""
+"Incheckningen avvisades av kroken för förberedelse av incheckningsmeddelande "
+"(prepare-commit-msg)."
+
+#: git-gui.sh:1542 lib/browser.tcl:246
msgid "Ready."
msgstr "Klar."
-#: git-gui.sh:1635
+#: git-gui.sh:1819
msgid "Unmodified"
msgstr "Oförändrade"
-#: git-gui.sh:1637
+#: git-gui.sh:1821
msgid "Modified, not staged"
msgstr "Förändrade, ej köade"
-#: git-gui.sh:1638 git-gui.sh:1643
+#: git-gui.sh:1822 git-gui.sh:1830
msgid "Staged for commit"
msgstr "Köade för incheckning"
-#: git-gui.sh:1639 git-gui.sh:1644
+#: git-gui.sh:1823 git-gui.sh:1831
msgid "Portions staged for commit"
msgstr "Delar köade för incheckning"
-#: git-gui.sh:1640 git-gui.sh:1645
+#: git-gui.sh:1824 git-gui.sh:1832
msgid "Staged for commit, missing"
msgstr "Köade för incheckning, saknade"
-#: git-gui.sh:1642
+#: git-gui.sh:1826
+msgid "File type changed, not staged"
+msgstr "Filtyp ändrad, ej köade"
+
+#: git-gui.sh:1827
+msgid "File type changed, staged"
+msgstr "Filtyp ändrad, köade"
+
+#: git-gui.sh:1829
msgid "Untracked, not staged"
msgstr "Ej spårade, ej köade"
-#: git-gui.sh:1647
+#: git-gui.sh:1834
msgid "Missing"
msgstr "Saknade"
-#: git-gui.sh:1648
+#: git-gui.sh:1835
msgid "Staged for removal"
msgstr "Köade för borttagning"
-#: git-gui.sh:1649
+#: git-gui.sh:1836
msgid "Staged for removal, still present"
msgstr "Köade för borttagning, fortfarande närvarande"
-#: git-gui.sh:1651 git-gui.sh:1652 git-gui.sh:1653 git-gui.sh:1654
+#: git-gui.sh:1838 git-gui.sh:1839 git-gui.sh:1840 git-gui.sh:1841
+#: git-gui.sh:1842 git-gui.sh:1843
msgid "Requires merge resolution"
msgstr "Kräver konflikthantering efter sammanslagning"
-#: git-gui.sh:1689
+#: git-gui.sh:1878
msgid "Starting gitk... please wait..."
msgstr "Startar gitk... vänta..."
-#: git-gui.sh:1698
+#: git-gui.sh:1887
msgid "Couldn't find gitk in PATH"
msgstr "Hittar inte gitk i PATH."
-#: git-gui.sh:1948 lib/choose_repository.tcl:36
+#: git-gui.sh:2280 lib/choose_repository.tcl:36
msgid "Repository"
msgstr "Arkiv"
-#: git-gui.sh:1949
+#: git-gui.sh:2281
msgid "Edit"
msgstr "Redigera"
-#: git-gui.sh:1951 lib/choose_rev.tcl:561
+#: git-gui.sh:2283 lib/choose_rev.tcl:561
msgid "Branch"
msgstr "Gren"
-#: git-gui.sh:1954 lib/choose_rev.tcl:548
+#: git-gui.sh:2286 lib/choose_rev.tcl:548
msgid "Commit@@noun"
msgstr "Incheckning"
-#: git-gui.sh:1957 lib/merge.tcl:120 lib/merge.tcl:149 lib/merge.tcl:167
+#: git-gui.sh:2289 lib/merge.tcl:121 lib/merge.tcl:150 lib/merge.tcl:168
msgid "Merge"
msgstr "Slå ihop"
-#: git-gui.sh:1958 lib/choose_rev.tcl:557
+#: git-gui.sh:2290 lib/choose_rev.tcl:557
msgid "Remote"
-msgstr "Fjärr"
+msgstr "Fjärrarkiv"
-#: git-gui.sh:1967
+#: git-gui.sh:2293
+msgid "Tools"
+msgstr "Verktyg"
+
+#: git-gui.sh:2302
+msgid "Explore Working Copy"
+msgstr "Utforska arbetskopia"
+
+#: git-gui.sh:2307
msgid "Browse Current Branch's Files"
msgstr "Bläddra i grenens filer"
-#: git-gui.sh:1971
+#: git-gui.sh:2311
msgid "Browse Branch Files..."
msgstr "Bläddra filer på gren..."
-#: git-gui.sh:1976
+#: git-gui.sh:2316
msgid "Visualize Current Branch's History"
msgstr "Visualisera grenens historik"
-#: git-gui.sh:1980
+#: git-gui.sh:2320
msgid "Visualize All Branch History"
msgstr "Visualisera alla grenars historik"
-#: git-gui.sh:1987
+#: git-gui.sh:2327
#, tcl-format
msgid "Browse %s's Files"
msgstr "Bläddra i filer för %s"
-#: git-gui.sh:1989
+#: git-gui.sh:2329
#, tcl-format
msgid "Visualize %s's History"
msgstr "Visualisera historik för %s"
-#: git-gui.sh:1994 lib/database.tcl:27 lib/database.tcl:67
+#: git-gui.sh:2334 lib/database.tcl:27 lib/database.tcl:67
msgid "Database Statistics"
msgstr "Databasstatistik"
-#: git-gui.sh:1997 lib/database.tcl:34
+#: git-gui.sh:2337 lib/database.tcl:34
msgid "Compress Database"
msgstr "Komprimera databas"
-#: git-gui.sh:2000
+#: git-gui.sh:2340
msgid "Verify Database"
msgstr "Verifiera databas"
-#: git-gui.sh:2007 git-gui.sh:2011 git-gui.sh:2015 lib/shortcut.tcl:7
+#: git-gui.sh:2347 git-gui.sh:2351 git-gui.sh:2355 lib/shortcut.tcl:7
#: lib/shortcut.tcl:39 lib/shortcut.tcl:71
msgid "Create Desktop Icon"
msgstr "Skapa skrivbordsikon"
-#: git-gui.sh:2023 lib/choose_repository.tcl:177 lib/choose_repository.tcl:185
+#: git-gui.sh:2363 lib/choose_repository.tcl:183 lib/choose_repository.tcl:191
msgid "Quit"
msgstr "Avsluta"
-#: git-gui.sh:2031
+#: git-gui.sh:2371
msgid "Undo"
msgstr "Ã…ngra"
-#: git-gui.sh:2034
+#: git-gui.sh:2374
msgid "Redo"
msgstr "Gör om"
-#: git-gui.sh:2038 git-gui.sh:2545
+#: git-gui.sh:2378 git-gui.sh:2937
msgid "Cut"
msgstr "Klipp ut"
-#: git-gui.sh:2041 git-gui.sh:2548 git-gui.sh:2622 git-gui.sh:2715
+#: git-gui.sh:2381 git-gui.sh:2940 git-gui.sh:3014 git-gui.sh:3096
#: lib/console.tcl:69
msgid "Copy"
msgstr "Kopiera"
-#: git-gui.sh:2044 git-gui.sh:2551
+#: git-gui.sh:2384 git-gui.sh:2943
msgid "Paste"
msgstr "Klistra in"
-#: git-gui.sh:2047 git-gui.sh:2554 lib/branch_delete.tcl:26
+#: git-gui.sh:2387 git-gui.sh:2946 lib/branch_delete.tcl:26
#: lib/remote_branch_delete.tcl:38
msgid "Delete"
msgstr "Ta bort"
-#: git-gui.sh:2051 git-gui.sh:2558 git-gui.sh:2719 lib/console.tcl:71
+#: git-gui.sh:2391 git-gui.sh:2950 git-gui.sh:3100 lib/console.tcl:71
msgid "Select All"
msgstr "Markera alla"
-#: git-gui.sh:2060
+#: git-gui.sh:2400
msgid "Create..."
msgstr "Skapa..."
-#: git-gui.sh:2066
+#: git-gui.sh:2406
msgid "Checkout..."
msgstr "Checka ut..."
-#: git-gui.sh:2072
+#: git-gui.sh:2412
msgid "Rename..."
msgstr "Byt namn..."
-#: git-gui.sh:2077 git-gui.sh:2187
+#: git-gui.sh:2417
msgid "Delete..."
msgstr "Ta bort..."
-#: git-gui.sh:2082
+#: git-gui.sh:2422
msgid "Reset..."
msgstr "Återställ..."
-#: git-gui.sh:2094 git-gui.sh:2491
+#: git-gui.sh:2432
+msgid "Done"
+msgstr "Färdig"
+
+#: git-gui.sh:2434
+msgid "Commit@@verb"
+msgstr "Checka in"
+
+#: git-gui.sh:2443 git-gui.sh:2878
msgid "New Commit"
msgstr "Ny incheckning"
-#: git-gui.sh:2102 git-gui.sh:2498
+#: git-gui.sh:2451 git-gui.sh:2885
msgid "Amend Last Commit"
msgstr "Lägg till föregående incheckning"
-#: git-gui.sh:2111 git-gui.sh:2458 lib/remote_branch_delete.tcl:99
+#: git-gui.sh:2461 git-gui.sh:2839 lib/remote_branch_delete.tcl:99
msgid "Rescan"
msgstr "Sök på nytt"
-#: git-gui.sh:2117
+#: git-gui.sh:2467
msgid "Stage To Commit"
msgstr "Köa för incheckning"
-#: git-gui.sh:2123
+#: git-gui.sh:2473
msgid "Stage Changed Files To Commit"
msgstr "Köa ändrade filer för incheckning"
-#: git-gui.sh:2129
+#: git-gui.sh:2479
msgid "Unstage From Commit"
msgstr "Ta bort från incheckningskö"
-#: git-gui.sh:2134 lib/index.tcl:395
+#: git-gui.sh:2484 lib/index.tcl:410
msgid "Revert Changes"
msgstr "Återställ ändringar"
-#: git-gui.sh:2141 git-gui.sh:2702
+#: git-gui.sh:2491 git-gui.sh:3083
msgid "Show Less Context"
msgstr "Visa mindre sammanhang"
-#: git-gui.sh:2145 git-gui.sh:2706
+#: git-gui.sh:2495 git-gui.sh:3087
msgid "Show More Context"
msgstr "Visa mer sammanhang"
-#: git-gui.sh:2151 git-gui.sh:2470 git-gui.sh:2569
+#: git-gui.sh:2502 git-gui.sh:2852 git-gui.sh:2961
msgid "Sign Off"
msgstr "Skriv under"
-#: git-gui.sh:2155 git-gui.sh:2474
-msgid "Commit@@verb"
-msgstr "Checka in"
-
-#: git-gui.sh:2166
+#: git-gui.sh:2518
msgid "Local Merge..."
msgstr "Lokal sammanslagning..."
-#: git-gui.sh:2171
+#: git-gui.sh:2523
msgid "Abort Merge..."
msgstr "Avbryt sammanslagning..."
-#: git-gui.sh:2183
+#: git-gui.sh:2535 git-gui.sh:2575
+msgid "Add..."
+msgstr "Lägg till..."
+
+#: git-gui.sh:2539
msgid "Push..."
msgstr "Sänd..."
-#: git-gui.sh:2197 git-gui.sh:2219 lib/about.tcl:14
-#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50
+#: git-gui.sh:2543
+msgid "Delete Branch..."
+msgstr "Ta bort gren..."
+
+#: git-gui.sh:2553 git-gui.sh:2589 lib/about.tcl:14
+#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:53
#, tcl-format
msgid "About %s"
msgstr "Om %s"
-#: git-gui.sh:2201
+#: git-gui.sh:2557
msgid "Preferences..."
msgstr "Inställningar..."
-#: git-gui.sh:2209 git-gui.sh:2740
+#: git-gui.sh:2565 git-gui.sh:3129
msgid "Options..."
msgstr "Alternativ..."
-#: git-gui.sh:2215 lib/choose_repository.tcl:47
+#: git-gui.sh:2576
+msgid "Remove..."
+msgstr "Ta bort..."
+
+#: git-gui.sh:2585 lib/choose_repository.tcl:50
msgid "Help"
msgstr "Hjälp"
-#: git-gui.sh:2256
+#: git-gui.sh:2611
msgid "Online Documentation"
msgstr "Webbdokumentation"
-#: git-gui.sh:2340
+#: git-gui.sh:2614 lib/choose_repository.tcl:47 lib/choose_repository.tcl:56
+msgid "Show SSH Key"
+msgstr "Visa SSH-nyckel"
+
+#: git-gui.sh:2721
#, tcl-format
msgid "fatal: cannot stat path %s: No such file or directory"
msgstr ""
"ödesdigert: kunde inte ta status på sökvägen %s: Fil eller katalog saknas"
-#: git-gui.sh:2373
+#: git-gui.sh:2754
msgid "Current Branch:"
msgstr "Aktuell gren:"
-#: git-gui.sh:2394
+#: git-gui.sh:2775
msgid "Staged Changes (Will Commit)"
msgstr "Köade ändringar (kommer att checkas in)"
-#: git-gui.sh:2414
+#: git-gui.sh:2795
msgid "Unstaged Changes"
msgstr "Oköade ändringar"
-#: git-gui.sh:2464
+#: git-gui.sh:2845
msgid "Stage Changed"
msgstr "Köa ändrade"
-#: git-gui.sh:2480 lib/transport.tcl:93 lib/transport.tcl:182
+#: git-gui.sh:2864 lib/transport.tcl:104 lib/transport.tcl:193
msgid "Push"
msgstr "Sänd"
-#: git-gui.sh:2510
+#: git-gui.sh:2899
msgid "Initial Commit Message:"
msgstr "Inledande incheckningsmeddelande:"
-#: git-gui.sh:2511
+#: git-gui.sh:2900
msgid "Amended Commit Message:"
msgstr "Utökat incheckningsmeddelande:"
-#: git-gui.sh:2512
+#: git-gui.sh:2901
msgid "Amended Initial Commit Message:"
msgstr "Utökat inledande incheckningsmeddelande:"
-#: git-gui.sh:2513
+#: git-gui.sh:2902
msgid "Amended Merge Commit Message:"
msgstr "Utökat incheckningsmeddelande för sammanslagning:"
-#: git-gui.sh:2514
+#: git-gui.sh:2903
msgid "Merge Commit Message:"
msgstr "Incheckningsmeddelande för sammanslagning:"
-#: git-gui.sh:2515
+#: git-gui.sh:2904
msgid "Commit Message:"
msgstr "Incheckningsmeddelande:"
-#: git-gui.sh:2561 git-gui.sh:2723 lib/console.tcl:73
+#: git-gui.sh:2953 git-gui.sh:3104 lib/console.tcl:73
msgid "Copy All"
msgstr "Kopiera alla"
-#: git-gui.sh:2585 lib/blame.tcl:100
+#: git-gui.sh:2977 lib/blame.tcl:104
msgid "File:"
msgstr "Fil:"
-#: git-gui.sh:2691
-msgid "Apply/Reverse Hunk"
-msgstr "Använd/återställ del"
-
-#: git-gui.sh:2696
-msgid "Apply/Reverse Line"
-msgstr "Använd/återställ rad"
-
-#: git-gui.sh:2711
+#: git-gui.sh:3092
msgid "Refresh"
msgstr "Uppdatera"
-#: git-gui.sh:2732
+#: git-gui.sh:3113
msgid "Decrease Font Size"
msgstr "Minska teckensnittsstorlek"
-#: git-gui.sh:2736
+#: git-gui.sh:3117
msgid "Increase Font Size"
msgstr "Öka teckensnittsstorlek"
-#: git-gui.sh:2747
+#: git-gui.sh:3125 lib/blame.tcl:281
+msgid "Encoding"
+msgstr "Teckenkodning"
+
+#: git-gui.sh:3136
+msgid "Apply/Reverse Hunk"
+msgstr "Använd/återställ del"
+
+#: git-gui.sh:3141
+msgid "Apply/Reverse Line"
+msgstr "Använd/återställ rad"
+
+#: git-gui.sh:3151
+msgid "Run Merge Tool"
+msgstr "Starta verktyg för sammanslagning"
+
+#: git-gui.sh:3156
+msgid "Use Remote Version"
+msgstr "Använd versionen från fjärrarkivet"
+
+#: git-gui.sh:3160
+msgid "Use Local Version"
+msgstr "Använd lokala versionen"
+
+#: git-gui.sh:3164
+msgid "Revert To Base"
+msgstr "Återställ till basversionen"
+
+#: git-gui.sh:3183
msgid "Unstage Hunk From Commit"
msgstr "Ta bort del ur incheckningskö"
-#: git-gui.sh:2748
+#: git-gui.sh:3184
msgid "Unstage Line From Commit"
msgstr "Ta bort rad ur incheckningskö"
-#: git-gui.sh:2750
+#: git-gui.sh:3186
msgid "Stage Hunk For Commit"
msgstr "Ställ del i incheckningskö"
-#: git-gui.sh:2751
+#: git-gui.sh:3187
msgid "Stage Line For Commit"
msgstr "Ställ rad i incheckningskö"
-#: git-gui.sh:2771
+#: git-gui.sh:3210
msgid "Initializing..."
msgstr "Initierar..."
-#: git-gui.sh:2876
+#: git-gui.sh:3315
#, tcl-format
msgid ""
"Possible environment issues exist.\n"
@@ -451,7 +520,7 @@ msgstr ""
"av %s:\n"
"\n"
-#: git-gui.sh:2906
+#: git-gui.sh:3345
msgid ""
"\n"
"This is due to a known issue with the\n"
@@ -461,7 +530,7 @@ msgstr ""
"Detta beror på ett känt problem med\n"
"Tcl-binären som följer med Cygwin."
-#: git-gui.sh:2911
+#: git-gui.sh:3350
#, tcl-format
msgid ""
"\n"
@@ -482,80 +551,108 @@ msgstr ""
msgid "git-gui - a graphical user interface for Git."
msgstr "git-gui - ett grafiskt användargränssnitt för Git."
-#: lib/blame.tcl:70
+#: lib/blame.tcl:72
msgid "File Viewer"
msgstr "Filvisare"
-#: lib/blame.tcl:74
+#: lib/blame.tcl:78
msgid "Commit:"
msgstr "Incheckning:"
-#: lib/blame.tcl:257
+#: lib/blame.tcl:271
msgid "Copy Commit"
msgstr "Kopiera incheckning"
-#: lib/blame.tcl:260
+#: lib/blame.tcl:275
+msgid "Find Text..."
+msgstr "Sök text..."
+
+#: lib/blame.tcl:284
msgid "Do Full Copy Detection"
msgstr "Gör full kopieringsigenkänning"
-#: lib/blame.tcl:388
+#: lib/blame.tcl:288
+msgid "Show History Context"
+msgstr "Visa historiksammanhang"
+
+#: lib/blame.tcl:291
+msgid "Blame Parent Commit"
+msgstr "Klandra föräldraincheckning"
+
+#: lib/blame.tcl:450
#, tcl-format
msgid "Reading %s..."
msgstr "Läser %s..."
-#: lib/blame.tcl:492
+#: lib/blame.tcl:557
msgid "Loading copy/move tracking annotations..."
msgstr "Läser annoteringar för kopiering/flyttning..."
-#: lib/blame.tcl:512
+#: lib/blame.tcl:577
msgid "lines annotated"
msgstr "rader annoterade"
-#: lib/blame.tcl:704
+#: lib/blame.tcl:769
msgid "Loading original location annotations..."
msgstr "Läser in annotering av originalplacering..."
-#: lib/blame.tcl:707
+#: lib/blame.tcl:772
msgid "Annotation complete."
msgstr "Annotering fullbordad."
-#: lib/blame.tcl:737
+#: lib/blame.tcl:802
msgid "Busy"
msgstr "Upptagen"
-#: lib/blame.tcl:738
+#: lib/blame.tcl:803
msgid "Annotation process is already running."
msgstr "Annoteringsprocess körs redan."
-#: lib/blame.tcl:777
+#: lib/blame.tcl:842
msgid "Running thorough copy detection..."
msgstr "Kör grundlig kopieringsigenkänning..."
-#: lib/blame.tcl:827
+#: lib/blame.tcl:910
msgid "Loading annotation..."
msgstr "Läser in annotering..."
-#: lib/blame.tcl:883
+#: lib/blame.tcl:963
msgid "Author:"
msgstr "Författare:"
-#: lib/blame.tcl:887
+#: lib/blame.tcl:967
msgid "Committer:"
msgstr "Incheckare:"
-#: lib/blame.tcl:892
+#: lib/blame.tcl:972
msgid "Original File:"
msgstr "Ursprunglig fil:"
-#: lib/blame.tcl:1006
+#: lib/blame.tcl:1020
+msgid "Cannot find HEAD commit:"
+msgstr "Hittar inte incheckning för HEAD:"
+
+#: lib/blame.tcl:1075
+msgid "Cannot find parent commit:"
+msgstr "Hittar inte föräldraincheckning:"
+
+#: lib/blame.tcl:1090
+msgid "Unable to display parent"
+msgstr "Kan inte visa förälder"
+
+#: lib/blame.tcl:1091 lib/diff.tcl:297
+msgid "Error loading diff:"
+msgstr "Fel vid inläsning av differens:"
+
+#: lib/blame.tcl:1231
msgid "Originally By:"
msgstr "Ursprungligen av:"
-#: lib/blame.tcl:1012
+#: lib/blame.tcl:1237
msgid "In File:"
msgstr "I filen:"
-#: lib/blame.tcl:1017
+#: lib/blame.tcl:1242
msgid "Copied Or Moved Here By:"
msgstr "Kopierad eller flyttad hit av:"
@@ -569,16 +666,18 @@ msgstr "Checka ut"
#: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35
#: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:282
-#: lib/checkout_op.tcl:544 lib/choose_font.tcl:43 lib/merge.tcl:171
-#: lib/option.tcl:103 lib/remote_branch_delete.tcl:42 lib/transport.tcl:97
+#: lib/checkout_op.tcl:544 lib/choose_font.tcl:43 lib/merge.tcl:172
+#: lib/option.tcl:125 lib/remote_add.tcl:32 lib/remote_branch_delete.tcl:42
+#: lib/tools_dlg.tcl:40 lib/tools_dlg.tcl:204 lib/tools_dlg.tcl:352
+#: lib/transport.tcl:108
msgid "Cancel"
msgstr "Avbryt"
-#: lib/branch_checkout.tcl:32 lib/browser.tcl:287
+#: lib/branch_checkout.tcl:32 lib/browser.tcl:287 lib/tools_dlg.tcl:328
msgid "Revision"
msgstr "Revision"
-#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:244
+#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:280
msgid "Options"
msgstr "Alternativ"
@@ -598,7 +697,7 @@ msgstr "Skapa gren"
msgid "Create New Branch"
msgstr "Skapa ny gren"
-#: lib/branch_create.tcl:31 lib/choose_repository.tcl:371
+#: lib/branch_create.tcl:31 lib/choose_repository.tcl:377
msgid "Create"
msgstr "Skapa"
@@ -606,7 +705,7 @@ msgstr "Skapa"
msgid "Branch Name"
msgstr "Namn på gren"
-#: lib/branch_create.tcl:43
+#: lib/branch_create.tcl:43 lib/remote_add.tcl:39 lib/tools_dlg.tcl:50
msgid "Name:"
msgstr "Namn:"
@@ -751,9 +850,9 @@ msgstr "[Upp till förälder]"
msgid "Browse Branch Files"
msgstr "Bläddra filer på grenen"
-#: lib/browser.tcl:278 lib/choose_repository.tcl:387
-#: lib/choose_repository.tcl:472 lib/choose_repository.tcl:482
-#: lib/choose_repository.tcl:985
+#: lib/browser.tcl:278 lib/choose_repository.tcl:394
+#: lib/choose_repository.tcl:480 lib/choose_repository.tcl:491
+#: lib/choose_repository.tcl:995
msgid "Browse"
msgstr "Bläddra"
@@ -768,6 +867,7 @@ msgid "fatal: Cannot resolve %s"
msgstr "ödesdigert: Kunde inte slå upp %s"
#: lib/checkout_op.tcl:145 lib/console.tcl:81 lib/database.tcl:31
+#: lib/sshkey.tcl:53
msgid "Close"
msgstr "Stäng"
@@ -879,7 +979,7 @@ msgstr "Det kanske inte är så enkelt att återskapa förlorade incheckningar."
msgid "Reset '%s'?"
msgstr "Återställa \"%s\"?"
-#: lib/checkout_op.tcl:532 lib/merge.tcl:163
+#: lib/checkout_op.tcl:532 lib/merge.tcl:164 lib/tools_dlg.tcl:343
msgid "Visualize"
msgstr "Visualisera"
@@ -928,221 +1028,225 @@ msgstr ""
msgid "Git Gui"
msgstr "Git Gui"
-#: lib/choose_repository.tcl:81 lib/choose_repository.tcl:376
+#: lib/choose_repository.tcl:87 lib/choose_repository.tcl:382
msgid "Create New Repository"
msgstr "Skapa nytt arkiv"
-#: lib/choose_repository.tcl:87
+#: lib/choose_repository.tcl:93
msgid "New..."
msgstr "Nytt..."
-#: lib/choose_repository.tcl:94 lib/choose_repository.tcl:458
+#: lib/choose_repository.tcl:100 lib/choose_repository.tcl:465
msgid "Clone Existing Repository"
msgstr "Klona befintligt arkiv"
-#: lib/choose_repository.tcl:100
+#: lib/choose_repository.tcl:106
msgid "Clone..."
msgstr "Klona..."
-#: lib/choose_repository.tcl:107 lib/choose_repository.tcl:974
+#: lib/choose_repository.tcl:113 lib/choose_repository.tcl:983
msgid "Open Existing Repository"
msgstr "Öppna befintligt arkiv"
-#: lib/choose_repository.tcl:113
+#: lib/choose_repository.tcl:119
msgid "Open..."
msgstr "Öppna..."
-#: lib/choose_repository.tcl:126
+#: lib/choose_repository.tcl:132
msgid "Recent Repositories"
msgstr "Senaste arkiven"
-#: lib/choose_repository.tcl:132
+#: lib/choose_repository.tcl:138
msgid "Open Recent Repository:"
msgstr "Öppna tidigare arkiv:"
-#: lib/choose_repository.tcl:296 lib/choose_repository.tcl:303
-#: lib/choose_repository.tcl:310
+#: lib/choose_repository.tcl:302 lib/choose_repository.tcl:309
+#: lib/choose_repository.tcl:316
#, tcl-format
msgid "Failed to create repository %s:"
msgstr "Kunde inte skapa arkivet %s:"
-#: lib/choose_repository.tcl:381 lib/choose_repository.tcl:476
+#: lib/choose_repository.tcl:387
msgid "Directory:"
msgstr "Katalog:"
-#: lib/choose_repository.tcl:410 lib/choose_repository.tcl:535
-#: lib/choose_repository.tcl:1007
+#: lib/choose_repository.tcl:417 lib/choose_repository.tcl:544
+#: lib/choose_repository.tcl:1017
msgid "Git Repository"
msgstr "Gitarkiv"
-#: lib/choose_repository.tcl:435
+#: lib/choose_repository.tcl:442
#, tcl-format
msgid "Directory %s already exists."
msgstr "Katalogen %s finns redan."
-#: lib/choose_repository.tcl:439
+#: lib/choose_repository.tcl:446
#, tcl-format
msgid "File %s already exists."
msgstr "Filen %s finns redan."
-#: lib/choose_repository.tcl:453
+#: lib/choose_repository.tcl:460
msgid "Clone"
msgstr "Klona"
-#: lib/choose_repository.tcl:466
-msgid "URL:"
-msgstr "Webbadress:"
+#: lib/choose_repository.tcl:473
+msgid "Source Location:"
+msgstr "Plats för källkod:"
-#: lib/choose_repository.tcl:487
+#: lib/choose_repository.tcl:484
+msgid "Target Directory:"
+msgstr "MÃ¥lkatalog:"
+
+#: lib/choose_repository.tcl:496
msgid "Clone Type:"
msgstr "Typ av klon:"
-#: lib/choose_repository.tcl:493
+#: lib/choose_repository.tcl:502
msgid "Standard (Fast, Semi-Redundant, Hardlinks)"
msgstr "Standard (snabb, semiredundant, hårda länkar)"
-#: lib/choose_repository.tcl:499
+#: lib/choose_repository.tcl:508
msgid "Full Copy (Slower, Redundant Backup)"
msgstr "Full kopia (långsammare, redundant säkerhetskopia)"
-#: lib/choose_repository.tcl:505
+#: lib/choose_repository.tcl:514
msgid "Shared (Fastest, Not Recommended, No Backup)"
msgstr "Delad (snabbast, rekommenderas ej, ingen säkerhetskopia)"
-#: lib/choose_repository.tcl:541 lib/choose_repository.tcl:588
-#: lib/choose_repository.tcl:734 lib/choose_repository.tcl:804
-#: lib/choose_repository.tcl:1013 lib/choose_repository.tcl:1021
+#: lib/choose_repository.tcl:550 lib/choose_repository.tcl:597
+#: lib/choose_repository.tcl:743 lib/choose_repository.tcl:813
+#: lib/choose_repository.tcl:1023 lib/choose_repository.tcl:1031
#, tcl-format
msgid "Not a Git repository: %s"
msgstr "Inte ett Gitarkiv: %s"
-#: lib/choose_repository.tcl:577
+#: lib/choose_repository.tcl:586
msgid "Standard only available for local repository."
msgstr "Standard är endast tillgängligt för lokala arkiv."
-#: lib/choose_repository.tcl:581
+#: lib/choose_repository.tcl:590
msgid "Shared only available for local repository."
msgstr "Delat är endast tillgängligt för lokala arkiv."
-#: lib/choose_repository.tcl:602
+#: lib/choose_repository.tcl:611
#, tcl-format
msgid "Location %s already exists."
msgstr "Platsen %s finns redan."
-#: lib/choose_repository.tcl:613
+#: lib/choose_repository.tcl:622
msgid "Failed to configure origin"
msgstr "Kunde inte konfigurera ursprung"
-#: lib/choose_repository.tcl:625
+#: lib/choose_repository.tcl:634
msgid "Counting objects"
msgstr "Räknar objekt"
-#: lib/choose_repository.tcl:626
+#: lib/choose_repository.tcl:635
msgid "buckets"
msgstr "hinkar"
-#: lib/choose_repository.tcl:650
+#: lib/choose_repository.tcl:659
#, tcl-format
msgid "Unable to copy objects/info/alternates: %s"
msgstr "Kunde inte kopiera objekt/info/alternativ: %s"
-#: lib/choose_repository.tcl:686
+#: lib/choose_repository.tcl:695
#, tcl-format
msgid "Nothing to clone from %s."
msgstr "Ingenting att klona från %s."
-#: lib/choose_repository.tcl:688 lib/choose_repository.tcl:902
-#: lib/choose_repository.tcl:914
+#: lib/choose_repository.tcl:697 lib/choose_repository.tcl:911
+#: lib/choose_repository.tcl:923
msgid "The 'master' branch has not been initialized."
msgstr "Grenen \"master\" har inte initierats."
-#: lib/choose_repository.tcl:701
+#: lib/choose_repository.tcl:710
msgid "Hardlinks are unavailable. Falling back to copying."
msgstr "Hårda länkar är inte tillgängliga. Faller tillbaka på kopiering."
-#: lib/choose_repository.tcl:713
+#: lib/choose_repository.tcl:722
#, tcl-format
msgid "Cloning from %s"
msgstr "Klonar från %s"
-#: lib/choose_repository.tcl:744
+#: lib/choose_repository.tcl:753
msgid "Copying objects"
msgstr "Kopierar objekt"
-#: lib/choose_repository.tcl:745
+#: lib/choose_repository.tcl:754
msgid "KiB"
msgstr "KiB"
-#: lib/choose_repository.tcl:769
+#: lib/choose_repository.tcl:778
#, tcl-format
msgid "Unable to copy object: %s"
msgstr "Kunde inte kopiera objekt: %s"
-#: lib/choose_repository.tcl:779
+#: lib/choose_repository.tcl:788
msgid "Linking objects"
msgstr "Länkar objekt"
-#: lib/choose_repository.tcl:780
+#: lib/choose_repository.tcl:789
msgid "objects"
msgstr "objekt"
-#: lib/choose_repository.tcl:788
+#: lib/choose_repository.tcl:797
#, tcl-format
msgid "Unable to hardlink object: %s"
msgstr "Kunde inte hårdlänka objekt: %s"
-#: lib/choose_repository.tcl:843
+#: lib/choose_repository.tcl:852
msgid "Cannot fetch branches and objects. See console output for details."
msgstr "Kunde inte hämta grenar och objekt. Se konsolutdata för detaljer."
-#: lib/choose_repository.tcl:854
+#: lib/choose_repository.tcl:863
msgid "Cannot fetch tags. See console output for details."
msgstr "Kunde inte hämta taggar. Se konsolutdata för detaljer."
-#: lib/choose_repository.tcl:878
+#: lib/choose_repository.tcl:887
msgid "Cannot determine HEAD. See console output for details."
msgstr "Kunde inte avgöra HEAD. Se konsolutdata för detaljer."
-#: lib/choose_repository.tcl:887
+#: lib/choose_repository.tcl:896
#, tcl-format
msgid "Unable to cleanup %s"
msgstr "Kunde inte städa upp %s"
-#: lib/choose_repository.tcl:893
+#: lib/choose_repository.tcl:902
msgid "Clone failed."
msgstr "Kloning misslyckades."
-#: lib/choose_repository.tcl:900
+#: lib/choose_repository.tcl:909
msgid "No default branch obtained."
msgstr "Hämtade ingen standardgren."
-#: lib/choose_repository.tcl:911
+#: lib/choose_repository.tcl:920
#, tcl-format
msgid "Cannot resolve %s as a commit."
msgstr "Kunde inte slå upp %s till någon incheckning."
-#: lib/choose_repository.tcl:923
+#: lib/choose_repository.tcl:932
msgid "Creating working directory"
msgstr "Skapar arbetskatalog"
-#: lib/choose_repository.tcl:924 lib/index.tcl:65 lib/index.tcl:127
-#: lib/index.tcl:193
+#: lib/choose_repository.tcl:933 lib/index.tcl:65 lib/index.tcl:128
+#: lib/index.tcl:196
msgid "files"
msgstr "filer"
-#: lib/choose_repository.tcl:953
+#: lib/choose_repository.tcl:962
msgid "Initial file checkout failed."
msgstr "Inledande filutcheckning misslyckades."
-#: lib/choose_repository.tcl:969
+#: lib/choose_repository.tcl:978
msgid "Open"
msgstr "Öppna"
-#: lib/choose_repository.tcl:979
+#: lib/choose_repository.tcl:988
msgid "Repository:"
msgstr "Arkiv:"
-#: lib/choose_repository.tcl:1027
+#: lib/choose_repository.tcl:1037
#, tcl-format
msgid "Failed to open repository %s:"
msgstr "Kunde inte öppna arkivet %s:"
@@ -1214,19 +1318,19 @@ msgstr ""
"utöka tidigare incheckningar om du inte först avbryter den pågående "
"sammanslagningen.\n"
-#: lib/commit.tcl:49
+#: lib/commit.tcl:48
msgid "Error loading commit data for amend:"
msgstr "Fel vid inläsning av incheckningsdata för utökning:"
-#: lib/commit.tcl:76
+#: lib/commit.tcl:75
msgid "Unable to obtain your identity:"
msgstr "Kunde inte hämta din identitet:"
-#: lib/commit.tcl:81
+#: lib/commit.tcl:80
msgid "Invalid GIT_COMMITTER_IDENT:"
msgstr "Felaktig GIT_COMMITTER_IDENT:"
-#: lib/commit.tcl:133
+#: lib/commit.tcl:132
msgid ""
"Last scanned state does not match repository state.\n"
"\n"
@@ -1242,7 +1346,7 @@ msgstr ""
"\n"
"Sökningen kommer att startas automatiskt nu.\n"
-#: lib/commit.tcl:154
+#: lib/commit.tcl:155
#, tcl-format
msgid ""
"Unmerged files cannot be committed.\n"
@@ -1255,7 +1359,7 @@ msgstr ""
"Filen %s har sammanslagningskonflikter. Du måste lösa dem och köa filen "
"innan du checkar in den.\n"
-#: lib/commit.tcl:162
+#: lib/commit.tcl:163
#, tcl-format
msgid ""
"Unknown file state %s detected.\n"
@@ -1266,7 +1370,7 @@ msgstr ""
"\n"
"Filen %s kan inte checkas in av programmet.\n"
-#: lib/commit.tcl:170
+#: lib/commit.tcl:171
msgid ""
"No changes to commit.\n"
"\n"
@@ -1276,7 +1380,7 @@ msgstr ""
"\n"
"Du måste köa åtminstone en fil innan du kan checka in.\n"
-#: lib/commit.tcl:183
+#: lib/commit.tcl:186
msgid ""
"Please supply a commit message.\n"
"\n"
@@ -1294,45 +1398,45 @@ msgstr ""
"- Andra raden: Tom\n"
"- Följande rader: Beskriv varför det här är en bra ändring.\n"
-#: lib/commit.tcl:207
+#: lib/commit.tcl:210
#, tcl-format
msgid "warning: Tcl does not support encoding '%s'."
msgstr "varning: Tcl stöder inte teckenkodningen \"%s\"."
-#: lib/commit.tcl:221
+#: lib/commit.tcl:226
msgid "Calling pre-commit hook..."
-msgstr "Anropar krok före incheckning..."
+msgstr "Anropar kroken före incheckning (pre-commit)..."
-#: lib/commit.tcl:236
+#: lib/commit.tcl:241
msgid "Commit declined by pre-commit hook."
-msgstr "Incheckningen avvisades av krok före incheckning."
+msgstr "Incheckningen avvisades av kroken före incheckning (pre-commit)."
-#: lib/commit.tcl:259
+#: lib/commit.tcl:264
msgid "Calling commit-msg hook..."
-msgstr "Anropar krok för incheckningsmeddelande..."
+msgstr "Anropar kroken för incheckningsmeddelande (commit-msg)..."
-#: lib/commit.tcl:274
+#: lib/commit.tcl:279
msgid "Commit declined by commit-msg hook."
-msgstr "Incheckning avvisad av krok för incheckningsmeddelande."
+msgstr "Incheckning avvisad av kroken för incheckningsmeddelande (commit-msg)."
-#: lib/commit.tcl:287
+#: lib/commit.tcl:292
msgid "Committing changes..."
msgstr "Checkar in ändringar..."
-#: lib/commit.tcl:303
+#: lib/commit.tcl:308
msgid "write-tree failed:"
msgstr "write-tree misslyckades:"
-#: lib/commit.tcl:304 lib/commit.tcl:348 lib/commit.tcl:368
+#: lib/commit.tcl:309 lib/commit.tcl:353 lib/commit.tcl:373
msgid "Commit failed."
msgstr "Incheckningen misslyckades."
-#: lib/commit.tcl:321
+#: lib/commit.tcl:326
#, tcl-format
msgid "Commit %s appears to be corrupt"
msgstr "Incheckningen %s verkar vara trasig"
-#: lib/commit.tcl:326
+#: lib/commit.tcl:331
msgid ""
"No changes to commit.\n"
"\n"
@@ -1346,19 +1450,19 @@ msgstr ""
"\n"
"En sökning kommer att startas automatiskt nu.\n"
-#: lib/commit.tcl:333
+#: lib/commit.tcl:338
msgid "No changes to commit."
msgstr "Inga ändringar att checka in."
-#: lib/commit.tcl:347
+#: lib/commit.tcl:352
msgid "commit-tree failed:"
msgstr "commit-tree misslyckades:"
-#: lib/commit.tcl:367
+#: lib/commit.tcl:372
msgid "update-ref failed:"
msgstr "update-ref misslyckades:"
-#: lib/commit.tcl:454
+#: lib/commit.tcl:460
#, tcl-format
msgid "Created commit %s: %s"
msgstr "Skapade incheckningen %s: %s"
@@ -1433,7 +1537,7 @@ msgstr ""
msgid "Invalid date from Git: %s"
msgstr "Ogiltigt datum från Git: %s"
-#: lib/diff.tcl:44
+#: lib/diff.tcl:59
#, tcl-format
msgid ""
"No differences detected.\n"
@@ -1456,48 +1560,101 @@ msgstr ""
"En sökning kommer automatiskt att startas för att hitta andra filer som kan "
"vara i samma tillstånd."
-#: lib/diff.tcl:83
+#: lib/diff.tcl:99
#, tcl-format
msgid "Loading diff of %s..."
msgstr "Läser differens för %s..."
-#: lib/diff.tcl:116 lib/diff.tcl:190
+#: lib/diff.tcl:120
+msgid ""
+"LOCAL: deleted\n"
+"REMOTE:\n"
+msgstr ""
+"LOKAL: borttagen\n"
+"FJÄRR:\n"
+
+#: lib/diff.tcl:125
+msgid ""
+"REMOTE: deleted\n"
+"LOCAL:\n"
+msgstr ""
+"FJÄRR: borttagen\n"
+"LOKAL:\n"
+
+#: lib/diff.tcl:132
+msgid "LOCAL:\n"
+msgstr "LOKAL:\n"
+
+#: lib/diff.tcl:135
+msgid "REMOTE:\n"
+msgstr "FJÄRR:\n"
+
+#: lib/diff.tcl:197 lib/diff.tcl:296
#, tcl-format
msgid "Unable to display %s"
msgstr "Kan inte visa %s"
-#: lib/diff.tcl:117
+#: lib/diff.tcl:198
msgid "Error loading file:"
msgstr "Fel vid läsning av fil:"
-#: lib/diff.tcl:124
+#: lib/diff.tcl:205
msgid "Git Repository (subproject)"
msgstr "Gitarkiv (underprojekt)"
-#: lib/diff.tcl:136
+#: lib/diff.tcl:217
msgid "* Binary file (not showing content)."
msgstr "* Binärfil (visar inte innehållet)."
-#: lib/diff.tcl:191
-msgid "Error loading diff:"
-msgstr "Fel vid inläsning av differens:"
+#: lib/diff.tcl:222
+#, tcl-format
+msgid ""
+"* Untracked file is %d bytes.\n"
+"* Showing only first %d bytes.\n"
+msgstr ""
+"* Den ospårade filen är %d byte.\n"
+"* Visar endast inledande %d byte.\n"
+
+#: lib/diff.tcl:228
+#, tcl-format
+msgid ""
+"\n"
+"* Untracked file clipped here by %s.\n"
+"* To see the entire file, use an external editor.\n"
+msgstr ""
+"\n"
+"* Den ospårade filen klipptes här av %s.\n"
+"* För att se hela filen, använd ett externt redigeringsprogram.\n"
-#: lib/diff.tcl:313
+#: lib/diff.tcl:436
msgid "Failed to unstage selected hunk."
msgstr "Kunde inte ta bort den valda delen från kön."
-#: lib/diff.tcl:320
+#: lib/diff.tcl:443
msgid "Failed to stage selected hunk."
msgstr "Kunde inte lägga till den valda delen till kön."
-#: lib/diff.tcl:386
+#: lib/diff.tcl:509
msgid "Failed to unstage selected line."
msgstr "Kunde inte ta bort den valda raden från kön."
-#: lib/diff.tcl:394
+#: lib/diff.tcl:517
msgid "Failed to stage selected line."
msgstr "Kunde inte lägga till den valda raden till kön."
+#: lib/encoding.tcl:443
+msgid "Default"
+msgstr "Standard"
+
+#: lib/encoding.tcl:448
+#, tcl-format
+msgid "System (%s)"
+msgstr "Systemets (%s)"
+
+#: lib/encoding.tcl:459 lib/encoding.tcl:465
+msgid "Other"
+msgstr "Annan"
+
#: lib/error.tcl:20 lib/error.tcl:114
msgid "error"
msgstr "fel"
@@ -1534,39 +1691,48 @@ msgstr "Forstätt"
msgid "Unlock Index"
msgstr "LÃ¥s upp index"
-#: lib/index.tcl:282
+#: lib/index.tcl:287
#, tcl-format
msgid "Unstaging %s from commit"
msgstr "Tar bort %s för incheckningskön"
-#: lib/index.tcl:313
+#: lib/index.tcl:326
msgid "Ready to commit."
msgstr "Redo att checka in."
-#: lib/index.tcl:326
+#: lib/index.tcl:339
#, tcl-format
msgid "Adding %s"
msgstr "Lägger till %s"
-#: lib/index.tcl:381
+#: lib/index.tcl:396
#, tcl-format
msgid "Revert changes in file %s?"
msgstr "Återställ ändringarna i filen %s?"
-#: lib/index.tcl:383
+#: lib/index.tcl:398
#, tcl-format
msgid "Revert changes in these %i files?"
msgstr "Återställ ändringarna i dessa %i filer?"
-#: lib/index.tcl:391
+#: lib/index.tcl:406
msgid "Any unstaged changes will be permanently lost by the revert."
msgstr ""
"Alla oköade ändringar kommer permanent gå förlorade vid återställningen."
-#: lib/index.tcl:394
+#: lib/index.tcl:409
msgid "Do Nothing"
msgstr "Gör ingenting"
+#: lib/index.tcl:427
+msgid "Reverting selected files"
+msgstr "Återställer valda filer"
+
+#: lib/index.tcl:431
+#, tcl-format
+msgid "Reverting %s"
+msgstr "Återställer %s"
+
#: lib/merge.tcl:13
msgid ""
"Cannot merge while amending.\n"
@@ -1594,7 +1760,7 @@ msgstr ""
"\n"
"Sökningen kommer att startas automatiskt nu.\n"
-#: lib/merge.tcl:44
+#: lib/merge.tcl:45
#, tcl-format
msgid ""
"You are in the middle of a conflicted merge.\n"
@@ -1611,7 +1777,7 @@ msgstr ""
"Du måste lösa dem, köa filen och checka in för att fullborda den aktuella "
"sammanslagningen. När du gjort det kan du påbörja en ny sammanslagning.\n"
-#: lib/merge.tcl:54
+#: lib/merge.tcl:55
#, tcl-format
msgid ""
"You are in the middle of a change.\n"
@@ -1629,34 +1795,34 @@ msgstr ""
"sammanslagning. Om du gör det blir det enklare att avbryta en misslyckad "
"sammanslagning, om det skulle vara nödvändigt.\n"
-#: lib/merge.tcl:106
+#: lib/merge.tcl:107
#, tcl-format
msgid "%s of %s"
msgstr "%s av %s"
-#: lib/merge.tcl:119
+#: lib/merge.tcl:120
#, tcl-format
msgid "Merging %s and %s..."
msgstr "Slår ihop %s och %s..."
-#: lib/merge.tcl:130
+#: lib/merge.tcl:131
msgid "Merge completed successfully."
msgstr "Sammanslagningen avslutades framgångsrikt."
-#: lib/merge.tcl:132
+#: lib/merge.tcl:133
msgid "Merge failed. Conflict resolution is required."
msgstr "Sammanslagningen misslyckades. Du måste lösa konflikterna."
-#: lib/merge.tcl:157
+#: lib/merge.tcl:158
#, tcl-format
msgid "Merge Into %s"
msgstr "Slå ihop i %s"
-#: lib/merge.tcl:176
+#: lib/merge.tcl:177
msgid "Revision To Merge"
msgstr "Revisioner att slå ihop"
-#: lib/merge.tcl:211
+#: lib/merge.tcl:212
msgid ""
"Cannot abort while amending.\n"
"\n"
@@ -1666,7 +1832,7 @@ msgstr ""
"\n"
"Du måste göra dig färdig med att utöka incheckningen.\n"
-#: lib/merge.tcl:221
+#: lib/merge.tcl:222
msgid ""
"Abort merge?\n"
"\n"
@@ -1681,7 +1847,7 @@ msgstr ""
"\n"
"GÃ¥ vidare med att avbryta den aktuella sammanslagningen?"
-#: lib/merge.tcl:227
+#: lib/merge.tcl:228
msgid ""
"Reset changes?\n"
"\n"
@@ -1696,131 +1862,336 @@ msgstr ""
"\n"
"Gå vidare med att återställa de aktuella ändringarna?"
-#: lib/merge.tcl:238
+#: lib/merge.tcl:239
msgid "Aborting"
msgstr "Avbryter"
-#: lib/merge.tcl:238
+#: lib/merge.tcl:239
msgid "files reset"
msgstr "filer återställda"
-#: lib/merge.tcl:266
+#: lib/merge.tcl:267
msgid "Abort failed."
msgstr "Misslyckades avbryta."
-#: lib/merge.tcl:268
+#: lib/merge.tcl:269
msgid "Abort completed. Ready."
msgstr "Avbrytning fullbordad. Redo."
-#: lib/option.tcl:95
+#: lib/mergetool.tcl:8
+msgid "Force resolution to the base version?"
+msgstr "Tvinga lösning att använda basversionen?"
+
+#: lib/mergetool.tcl:9
+msgid "Force resolution to this branch?"
+msgstr "Tvinga lösning att använda den aktuella grenen?"
+
+#: lib/mergetool.tcl:10
+msgid "Force resolution to the other branch?"
+msgstr "Tvinga lösning att använda den andra grenen?"
+
+#: lib/mergetool.tcl:14
+#, tcl-format
+msgid ""
+"Note that the diff shows only conflicting changes.\n"
+"\n"
+"%s will be overwritten.\n"
+"\n"
+"This operation can be undone only by restarting the merge."
+msgstr ""
+"Observera att diffen endast visar de ändringar som står i konflikt.\n"
+"\n"
+"%s kommer att skrivas över.\n"
+"\n"
+"Du måste starta om sammanslagningen för att göra den här operationen ogjord."
+
+#: lib/mergetool.tcl:45
+#, tcl-format
+msgid "File %s seems to have unresolved conflicts, still stage?"
+msgstr "Filen %s verkar innehålla olösta konflikter. Vill du köa ändå?"
+
+#: lib/mergetool.tcl:60
+#, tcl-format
+msgid "Adding resolution for %s"
+msgstr "Lägger till lösning för %s"
+
+#: lib/mergetool.tcl:141
+msgid "Cannot resolve deletion or link conflicts using a tool"
+msgstr "Kan inte lösa borttagnings- eller länkkonflikter med ett verktyg"
+
+#: lib/mergetool.tcl:146
+msgid "Conflict file does not exist"
+msgstr "Konfliktfil existerar inte"
+
+#: lib/mergetool.tcl:264
+#, tcl-format
+msgid "Not a GUI merge tool: '%s'"
+msgstr "Inte ett grafiskt verktyg för sammanslagning: %s"
+
+#: lib/mergetool.tcl:268
+#, tcl-format
+msgid "Unsupported merge tool '%s'"
+msgstr "Verktyget \"%s\" för sammanslagning stöds inte"
+
+#: lib/mergetool.tcl:303
+msgid "Merge tool is already running, terminate it?"
+msgstr "Verktyget för sammanslagning körs redan. Vill du avsluta det?"
+
+#: lib/mergetool.tcl:323
+#, tcl-format
+msgid ""
+"Error retrieving versions:\n"
+"%s"
+msgstr ""
+"Fel vid hämtning av versioner:\n"
+"%s"
+
+#: lib/mergetool.tcl:343
+#, tcl-format
+msgid ""
+"Could not start the merge tool:\n"
+"\n"
+"%s"
+msgstr ""
+"Kunde inte starta verktyg för sammanslagning:\n"
+"\n"
+"%s"
+
+#: lib/mergetool.tcl:347
+msgid "Running merge tool..."
+msgstr "Kör verktyg för sammanslagning..."
+
+#: lib/mergetool.tcl:375 lib/mergetool.tcl:383
+msgid "Merge tool failed."
+msgstr "Verktyget för sammanslagning misslyckades."
+
+#: lib/option.tcl:11
+#, tcl-format
+msgid "Invalid global encoding '%s'"
+msgstr "Den globala teckenkodningen \"%s\" är ogiltig"
+
+#: lib/option.tcl:19
+#, tcl-format
+msgid "Invalid repo encoding '%s'"
+msgstr "Arkivets teckenkodning \"%s\" är ogiltig"
+
+#: lib/option.tcl:117
msgid "Restore Defaults"
msgstr "Återställ standardvärden"
-#: lib/option.tcl:99
+#: lib/option.tcl:121
msgid "Save"
msgstr "Spara"
-#: lib/option.tcl:109
+#: lib/option.tcl:131
#, tcl-format
msgid "%s Repository"
msgstr "Arkivet %s"
-#: lib/option.tcl:110
+#: lib/option.tcl:132
msgid "Global (All Repositories)"
msgstr "Globalt (alla arkiv)"
-#: lib/option.tcl:116
+#: lib/option.tcl:138
msgid "User Name"
msgstr "Användarnamn"
-#: lib/option.tcl:117
+#: lib/option.tcl:139
msgid "Email Address"
msgstr "E-postadress"
-#: lib/option.tcl:119
+#: lib/option.tcl:141
msgid "Summarize Merge Commits"
msgstr "Summera sammanslagningsincheckningar"
-#: lib/option.tcl:120
+#: lib/option.tcl:142
msgid "Merge Verbosity"
msgstr "Pratsamhet för sammanslagningar"
-#: lib/option.tcl:121
+#: lib/option.tcl:143
msgid "Show Diffstat After Merge"
msgstr "Visa diffstatistik efter sammanslagning"
-#: lib/option.tcl:123
+#: lib/option.tcl:144
+msgid "Use Merge Tool"
+msgstr "Använd verktyg för sammanslagning"
+
+#: lib/option.tcl:146
msgid "Trust File Modification Timestamps"
msgstr "Lita på filändringstidsstämplar"
-#: lib/option.tcl:124
+#: lib/option.tcl:147
msgid "Prune Tracking Branches During Fetch"
msgstr "Städa spårade grenar vid hämtning"
-#: lib/option.tcl:125
+#: lib/option.tcl:148
msgid "Match Tracking Branches"
msgstr "Matcha spårade grenar"
-#: lib/option.tcl:126
+#: lib/option.tcl:149
msgid "Blame Copy Only On Changed Files"
msgstr "Klandra kopiering bara i ändrade filer"
-#: lib/option.tcl:127
+#: lib/option.tcl:150
msgid "Minimum Letters To Blame Copy On"
msgstr "Minsta antal tecken att klandra kopiering för"
-#: lib/option.tcl:128
+#: lib/option.tcl:151
+msgid "Blame History Context Radius (days)"
+msgstr "Historikradie för klandring (dagar)"
+
+#: lib/option.tcl:152
msgid "Number of Diff Context Lines"
msgstr "Antal rader sammanhang i differenser"
-#: lib/option.tcl:129
+#: lib/option.tcl:153
msgid "Commit Message Text Width"
msgstr "Textbredd för incheckningsmeddelande"
-#: lib/option.tcl:130
+#: lib/option.tcl:154
msgid "New Branch Name Template"
msgstr "Mall för namn på nya grenar"
-#: lib/option.tcl:194
+#: lib/option.tcl:155
+msgid "Default File Contents Encoding"
+msgstr "Standardteckenkodning för filinnehåll"
+
+#: lib/option.tcl:203
+msgid "Change"
+msgstr "Ändra"
+
+#: lib/option.tcl:230
msgid "Spelling Dictionary:"
msgstr "Stavningsordlista:"
-#: lib/option.tcl:218
+#: lib/option.tcl:254
msgid "Change Font"
msgstr "Byt teckensnitt"
-#: lib/option.tcl:222
+#: lib/option.tcl:258
#, tcl-format
msgid "Choose %s"
msgstr "Välj %s"
-#: lib/option.tcl:228
+#: lib/option.tcl:264
msgid "pt."
msgstr "p."
-#: lib/option.tcl:242
+#: lib/option.tcl:278
msgid "Preferences"
msgstr "Inställningar"
-#: lib/option.tcl:277
+#: lib/option.tcl:314
msgid "Failed to completely save options:"
msgstr "Misslyckades med att helt spara alternativ:"
+#: lib/remote.tcl:163
+msgid "Remove Remote"
+msgstr "Ta bort fjärrarkiv"
+
+#: lib/remote.tcl:168
+msgid "Prune from"
+msgstr "Ta bort från"
+
+#: lib/remote.tcl:173
+msgid "Fetch from"
+msgstr "Hämta från"
+
+#: lib/remote.tcl:215
+msgid "Push to"
+msgstr "Sänd till"
+
+#: lib/remote_add.tcl:19
+msgid "Add Remote"
+msgstr "Lägg till fjärrarkiv"
+
+#: lib/remote_add.tcl:24
+msgid "Add New Remote"
+msgstr "Lägg till nytt fjärrarkiv"
+
+#: lib/remote_add.tcl:28 lib/tools_dlg.tcl:36
+msgid "Add"
+msgstr "Lägg till"
+
+#: lib/remote_add.tcl:37
+msgid "Remote Details"
+msgstr "Detaljer för fjärrarkiv"
+
+#: lib/remote_add.tcl:50
+msgid "Location:"
+msgstr "Plats:"
+
+#: lib/remote_add.tcl:62
+msgid "Further Action"
+msgstr "Ytterligare åtgärd"
+
+#: lib/remote_add.tcl:65
+msgid "Fetch Immediately"
+msgstr "Hämta omedelbart"
+
+#: lib/remote_add.tcl:71
+msgid "Initialize Remote Repository and Push"
+msgstr "Initiera fjärrarkiv och sänd till"
+
+#: lib/remote_add.tcl:77
+msgid "Do Nothing Else Now"
+msgstr "Gör ingent mer nu"
+
+#: lib/remote_add.tcl:101
+msgid "Please supply a remote name."
+msgstr "Ange ett namn för fjärrarkivet."
+
+#: lib/remote_add.tcl:114
+#, tcl-format
+msgid "'%s' is not an acceptable remote name."
+msgstr "\"%s\" kan inte användas som namn på fjärrarkivet."
+
+#: lib/remote_add.tcl:125
+#, tcl-format
+msgid "Failed to add remote '%s' of location '%s'."
+msgstr "Kunde inte lägga till fjärrarkivet \"%s\" på platsen \"%s\"."
+
+#: lib/remote_add.tcl:133 lib/transport.tcl:6
+#, tcl-format
+msgid "fetch %s"
+msgstr "hämta %s"
+
+#: lib/remote_add.tcl:134
+#, tcl-format
+msgid "Fetching the %s"
+msgstr "Hämtar %s"
+
+#: lib/remote_add.tcl:157
+#, tcl-format
+msgid "Do not know how to initialize repository at location '%s'."
+msgstr "Vet inte hur arkivet på platsen \"%s\" skall initieras."
+
+#: lib/remote_add.tcl:163 lib/transport.tcl:25 lib/transport.tcl:63
+#: lib/transport.tcl:81
+#, tcl-format
+msgid "push %s"
+msgstr "sänd %s"
+
+#: lib/remote_add.tcl:164
+#, tcl-format
+msgid "Setting up the %s (at %s)"
+msgstr "Konfigurerar %s (på %s)"
+
#: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34
-msgid "Delete Remote Branch"
-msgstr "Ta bort fjärrgren"
+msgid "Delete Branch Remotely"
+msgstr "Ta bort gren från fjärrarkiv"
#: lib/remote_branch_delete.tcl:47
msgid "From Repository"
msgstr "Från arkiv"
-#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:123
+#: lib/remote_branch_delete.tcl:50 lib/transport.tcl:134
msgid "Remote:"
-msgstr "Fjärr:"
+msgstr "Fjärrarkiv:"
-#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:138
-msgid "Arbitrary URL:"
-msgstr "Godtycklig webbadress:"
+#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:149
+msgid "Arbitrary Location:"
+msgstr "Godtycklig plats:"
#: lib/remote_branch_delete.tcl:84
msgid "Branches"
@@ -1890,17 +2261,21 @@ msgstr "Inget arkiv markerat."
msgid "Scanning %s..."
msgstr "Söker %s..."
-#: lib/remote.tcl:165
-msgid "Prune from"
-msgstr "Ta bort från"
+#: lib/search.tcl:21
+msgid "Find:"
+msgstr "Sök:"
-#: lib/remote.tcl:170
-msgid "Fetch from"
-msgstr "Hämta från"
+#: lib/search.tcl:23
+msgid "Next"
+msgstr "Nästa"
-#: lib/remote.tcl:213
-msgid "Push to"
-msgstr "Sänd till"
+#: lib/search.tcl:24
+msgid "Prev"
+msgstr "Föreg"
+
+#: lib/search.tcl:25
+msgid "Case-Sensitive"
+msgstr "Skilj på VERSALER/gemener"
#: lib/shortcut.tcl:20 lib/shortcut.tcl:61
msgid "Cannot write shortcut:"
@@ -1939,23 +2314,188 @@ msgstr "Stavningskontrollprogrammet känns inte igen"
msgid "No Suggestions"
msgstr "Inga förslag"
-#: lib/spellcheck.tcl:387
+#: lib/spellcheck.tcl:388
msgid "Unexpected EOF from spell checker"
msgstr "Oväntat filslut från stavningskontroll"
-#: lib/spellcheck.tcl:391
+#: lib/spellcheck.tcl:392
msgid "Spell Checker Failed"
msgstr "Stavningskontroll misslyckades"
+#: lib/sshkey.tcl:31
+msgid "No keys found."
+msgstr "Inga nycklar hittades."
+
+#: lib/sshkey.tcl:34
+#, tcl-format
+msgid "Found a public key in: %s"
+msgstr "Hittade öppen nyckel i: %s"
+
+#: lib/sshkey.tcl:40
+msgid "Generate Key"
+msgstr "Skapa nyckel"
+
+#: lib/sshkey.tcl:56
+msgid "Copy To Clipboard"
+msgstr "Kopiera till Urklipp"
+
+#: lib/sshkey.tcl:70
+msgid "Your OpenSSH Public Key"
+msgstr "Din öppna OpenSSH-nyckel"
+
+#: lib/sshkey.tcl:78
+msgid "Generating..."
+msgstr "Skapar..."
+
+#: lib/sshkey.tcl:84
+#, tcl-format
+msgid ""
+"Could not start ssh-keygen:\n"
+"\n"
+"%s"
+msgstr ""
+"Kunde inte starta ssh-keygen:\n"
+"\n"
+"%s"
+
+#: lib/sshkey.tcl:111
+msgid "Generation failed."
+msgstr "Misslyckades med att skapa."
+
+#: lib/sshkey.tcl:118
+msgid "Generation succeded, but no keys found."
+msgstr "Lyckades skapa nyckeln, men hittar inte någon nyckel."
+
+#: lib/sshkey.tcl:121
+#, tcl-format
+msgid "Your key is in: %s"
+msgstr "Din nyckel finns i: %s"
+
#: lib/status_bar.tcl:83
#, tcl-format
msgid "%s ... %*i of %*i %s (%3i%%)"
msgstr "%s... %*i av %*i %s (%3i%%)"
-#: lib/transport.tcl:6
+#: lib/tools.tcl:75
#, tcl-format
-msgid "fetch %s"
-msgstr "hämta %s"
+msgid "Running %s requires a selected file."
+msgstr "För att starta %s måste du välja en fil."
+
+#: lib/tools.tcl:90
+#, tcl-format
+msgid "Are you sure you want to run %s?"
+msgstr "Är du säker på att du vill starta %s?"
+
+#: lib/tools.tcl:110
+#, tcl-format
+msgid "Tool: %s"
+msgstr "Verktyg: %s"
+
+#: lib/tools.tcl:111
+#, tcl-format
+msgid "Running: %s"
+msgstr "Exekverar: %s"
+
+#: lib/tools.tcl:149
+#, tcl-format
+msgid "Tool completed succesfully: %s"
+msgstr "Verktyget avslutades framgångsrikt: %s"
+
+#: lib/tools.tcl:151
+#, tcl-format
+msgid "Tool failed: %s"
+msgstr "Verktyget misslyckades: %s"
+
+#: lib/tools_dlg.tcl:22
+msgid "Add Tool"
+msgstr "Lägg till verktyg"
+
+#: lib/tools_dlg.tcl:28
+msgid "Add New Tool Command"
+msgstr "Lägg till nytt verktygskommando"
+
+#: lib/tools_dlg.tcl:33
+msgid "Add globally"
+msgstr "Lägg till globalt"
+
+#: lib/tools_dlg.tcl:45
+msgid "Tool Details"
+msgstr "Detaljer för verktyg"
+
+#: lib/tools_dlg.tcl:48
+msgid "Use '/' separators to create a submenu tree:"
+msgstr "Använd \"/\"-avdelare för att skapa ett undermenyträd:"
+
+#: lib/tools_dlg.tcl:61
+msgid "Command:"
+msgstr "Kommando:"
+
+#: lib/tools_dlg.tcl:74
+msgid "Show a dialog before running"
+msgstr "Visa dialog innan programmet startas"
+
+#: lib/tools_dlg.tcl:80
+msgid "Ask the user to select a revision (sets $REVISION)"
+msgstr "Be användaren välja en version (sätter $REVISION)"
+
+#: lib/tools_dlg.tcl:85
+msgid "Ask the user for additional arguments (sets $ARGS)"
+msgstr "Be användaren om ytterligare parametrar (sätter $ARGS)"
+
+#: lib/tools_dlg.tcl:92
+msgid "Don't show the command output window"
+msgstr "Visa inte kommandots utdatafönster"
+
+#: lib/tools_dlg.tcl:97
+msgid "Run only if a diff is selected ($FILENAME not empty)"
+msgstr "Kör endast om en diff har markerats ($FILENAME är inte tomt)"
+
+#: lib/tools_dlg.tcl:121
+msgid "Please supply a name for the tool."
+msgstr "Ange ett namn för verktyget."
+
+#: lib/tools_dlg.tcl:129
+#, tcl-format
+msgid "Tool '%s' already exists."
+msgstr "Verktyget \"%s\" finns redan."
+
+#: lib/tools_dlg.tcl:151
+#, tcl-format
+msgid ""
+"Could not add tool:\n"
+"%s"
+msgstr ""
+"Kunde inte lägga till verktyget:\n"
+"%s"
+
+#: lib/tools_dlg.tcl:190
+msgid "Remove Tool"
+msgstr "Ta bort verktyg"
+
+#: lib/tools_dlg.tcl:196
+msgid "Remove Tool Commands"
+msgstr "Ta bort verktygskommandon"
+
+#: lib/tools_dlg.tcl:200
+msgid "Remove"
+msgstr "Ta bort"
+
+#: lib/tools_dlg.tcl:236
+msgid "(Blue denotes repository-local tools)"
+msgstr "(Blått anger verktyg lokala för arkivet)"
+
+#: lib/tools_dlg.tcl:297
+#, tcl-format
+msgid "Run Command: %s"
+msgstr "Kör kommandot: %s"
+
+#: lib/tools_dlg.tcl:311
+msgid "Arguments"
+msgstr "Argument"
+
+#: lib/tools_dlg.tcl:348
+msgid "OK"
+msgstr "OK"
#: lib/transport.tcl:7
#, tcl-format
@@ -1972,49 +2512,55 @@ msgstr "fjärrborttagning %s"
msgid "Pruning tracking branches deleted from %s"
msgstr "Tar bort spårande grenar som tagits bort från %s"
-#: lib/transport.tcl:25 lib/transport.tcl:71
-#, tcl-format
-msgid "push %s"
-msgstr "sänd %s"
-
#: lib/transport.tcl:26
#, tcl-format
msgid "Pushing changes to %s"
msgstr "Sänder ändringar till %s"
-#: lib/transport.tcl:72
+#: lib/transport.tcl:64
+#, tcl-format
+msgid "Mirroring to %s"
+msgstr "Speglar till %s"
+
+#: lib/transport.tcl:82
#, tcl-format
msgid "Pushing %s %s to %s"
msgstr "Sänder %s %s till %s"
-#: lib/transport.tcl:89
+#: lib/transport.tcl:100
msgid "Push Branches"
-msgstr "Sänder grenar"
+msgstr "Sänd grenar"
-#: lib/transport.tcl:103
+#: lib/transport.tcl:114
msgid "Source Branches"
msgstr "Källgrenar"
-#: lib/transport.tcl:120
+#: lib/transport.tcl:131
msgid "Destination Repository"
msgstr "Destinationsarkiv"
-#: lib/transport.tcl:158
+#: lib/transport.tcl:169
msgid "Transfer Options"
msgstr "Överföringsalternativ"
-#: lib/transport.tcl:160
+#: lib/transport.tcl:171
msgid "Force overwrite existing branch (may discard changes)"
msgstr "Tvinga överskrivning av befintlig gren (kan kasta bort ändringar)"
-#: lib/transport.tcl:164
+#: lib/transport.tcl:175
msgid "Use thin pack (for slow network connections)"
msgstr "Använd tunt paket (för långsamma nätverksanslutningar)"
-#: lib/transport.tcl:168
+#: lib/transport.tcl:179
msgid "Include tags"
msgstr "Ta med taggar"
+#~ msgid "URL:"
+#~ msgstr "Webbadress:"
+
+#~ msgid "Delete Remote Branch"
+#~ msgstr "Ta bort fjärrgren"
+
#~ msgid ""
#~ "Unable to start gitk:\n"
#~ "\n"
diff --git a/git-lost-found.sh b/git-lost-found.sh
index 9cedaf80ce..0b3e8c7a86 100755
--- a/git-lost-found.sh
+++ b/git-lost-found.sh
@@ -20,7 +20,7 @@ while read dangling type sha1
do
case "$dangling" in
dangling)
- if git rev-parse --verify "$sha1^0" >/dev/null 2>/dev/null
+ if git rev-parse -q --verify "$sha1^0" >/dev/null
then
dir="$laf/commit"
git show-branch "$sha1"
diff --git a/git-mergetool.sh b/git-mergetool.sh
index 94187c306c..b2d53752ae 100755
--- a/git-mergetool.sh
+++ b/git-mergetool.sh
@@ -8,7 +8,7 @@
# at the discretion of Junio C Hamano.
#
-USAGE='[--tool=tool] [file to merge] ...'
+USAGE='[--tool=tool] [-y|--no-prompt|--prompt] [file to merge] ...'
SUBDIRECTORY_OK=Yes
OPTIONS_SPEC=
. git-sh-setup
@@ -70,16 +70,16 @@ resolve_symlink_merge () {
git checkout-index -f --stage=2 -- "$MERGED"
git add -- "$MERGED"
cleanup_temp_files --save-backup
- return
+ return 0
;;
[rR]*)
git checkout-index -f --stage=3 -- "$MERGED"
git add -- "$MERGED"
cleanup_temp_files --save-backup
- return
+ return 0
;;
[aA]*)
- exit 1
+ return 1
;;
esac
done
@@ -97,15 +97,15 @@ resolve_deleted_merge () {
[mMcC]*)
git add -- "$MERGED"
cleanup_temp_files --save-backup
- return
+ return 0
;;
[dD]*)
git rm -- "$MERGED" > /dev/null
cleanup_temp_files
- return
+ return 0
;;
[aA]*)
- exit 1
+ return 1
;;
esac
done
@@ -137,7 +137,7 @@ merge_file () {
else
echo "$MERGED: file does not need merging"
fi
- exit 1
+ return 1
fi
ext="$$$(expr "$MERGED" : '.*\(\.[^/]*\)$')"
@@ -176,8 +176,10 @@ merge_file () {
echo "Normal merge conflict for '$MERGED':"
describe_file "$local_mode" "local" "$LOCAL"
describe_file "$remote_mode" "remote" "$REMOTE"
- printf "Hit return to start merge resolution tool (%s): " "$merge_tool"
- read ans
+ if "$prompt" = true; then
+ printf "Hit return to start merge resolution tool (%s): " "$merge_tool"
+ read ans
+ fi
case "$merge_tool" in
kdiff3)
@@ -267,7 +269,12 @@ merge_file () {
if test "$status" -ne 0; then
echo "merge of $MERGED failed" 1>&2
mv -- "$BACKUP" "$MERGED"
- exit 1
+
+ if test "$merge_keep_temporaries" = "false"; then
+ cleanup_temp_files
+ fi
+
+ return 1
fi
if test "$merge_keep_backup" = "true"; then
@@ -278,8 +285,11 @@ merge_file () {
git add -- "$MERGED"
cleanup_temp_files
+ return 0
}
+prompt=$(git config --bool mergetool.prompt || echo true)
+
while test $# != 0
do
case "$1" in
@@ -295,7 +305,14 @@ do
shift ;;
esac
;;
+ -y|--no-prompt)
+ prompt=false
+ ;;
+ --prompt)
+ prompt=true
+ ;;
--)
+ shift
break
;;
-*)
@@ -340,6 +357,22 @@ init_merge_tool_path() {
fi
}
+prompt_after_failed_merge() {
+ while true; do
+ printf "Continue merging other unresolved paths (y/n) ? "
+ read ans
+ case "$ans" in
+
+ [yY]*)
+ return 0
+ ;;
+
+ [nN]*)
+ return 1
+ ;;
+ esac
+ done
+}
if test -z "$merge_tool"; then
merge_tool=`git config merge.tool`
@@ -388,6 +421,7 @@ else
init_merge_tool_path "$merge_tool"
merge_keep_backup="$(git config --bool merge.keepBackup || echo true)"
+ merge_keep_temporaries="$(git config --bool mergetool.keepTemporaries || echo false)"
if test -z "$merge_tool_cmd" && ! type "$merge_tool_path" > /dev/null 2>&1; then
echo "The merge tool $merge_tool is not available as '$merge_tool_path'"
@@ -399,27 +433,44 @@ else
fi
fi
+last_status=0
+rollup_status=0
if test $# -eq 0 ; then
- files=`git ls-files -u | sed -e 's/^[^ ]* //' | sort -u`
- if test -z "$files" ; then
- echo "No files need merging"
- exit 0
+ files=`git ls-files -u | sed -e 's/^[^ ]* //' | sort -u`
+ if test -z "$files" ; then
+ echo "No files need merging"
+ exit 0
+ fi
+ echo Merging the files: "$files"
+ git ls-files -u |
+ sed -e 's/^[^ ]* //' |
+ sort -u |
+ while IFS= read i
+ do
+ if test $last_status -ne 0; then
+ prompt_after_failed_merge < /dev/tty || exit 1
fi
- echo Merging the files: "$files"
- git ls-files -u |
- sed -e 's/^[^ ]* //' |
- sort -u |
- while IFS= read i
- do
- printf "\n"
- merge_file "$i" < /dev/tty > /dev/tty
- done
+ printf "\n"
+ merge_file "$i" < /dev/tty > /dev/tty
+ last_status=$?
+ if test $last_status -ne 0; then
+ rollup_status=1
+ fi
+ done
else
- while test $# -gt 0; do
- printf "\n"
- merge_file "$1"
- shift
- done
+ while test $# -gt 0; do
+ if test $last_status -ne 0; then
+ prompt_after_failed_merge || exit 1
+ fi
+ printf "\n"
+ merge_file "$1"
+ last_status=$?
+ if test $last_status -ne 0; then
+ rollup_status=1
+ fi
+ shift
+ done
fi
-exit 0
+
+exit $rollup_status
diff --git a/git-pull.sh b/git-pull.sh
index 75c36100a2..2c7f432dc0 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -16,13 +16,17 @@ cd_to_toplevel
test -z "$(git ls-files -u)" ||
die "You are in the middle of a conflicted merge."
-strategy_args= no_stat= no_commit= squash= no_ff= log_arg=
+strategy_args= no_stat= no_commit= squash= no_ff= log_arg= verbosity=
curr_branch=$(git symbolic-ref -q HEAD)
curr_branch_short=$(echo "$curr_branch" | sed "s|refs/heads/||")
rebase=$(git config --bool branch.$curr_branch_short.rebase)
while :
do
case "$1" in
+ -q|--quiet)
+ verbosity="$verbosity -q" ;;
+ -v|--verbose)
+ verbosity="$verbosity -v" ;;
-n|--no-stat|--no-summary)
no_stat=-n ;;
--stat|--summary)
@@ -117,14 +121,14 @@ test true = "$rebase" && {
test -z "$origin" && origin=$(get_default_remote)
reflist="$(get_remote_refs_for_fetch "$@" 2>/dev/null |
sed "s|refs/heads/\(.*\):|\1|")" &&
- oldremoteref="$(git rev-parse --verify \
- "refs/remotes/$origin/$reflist" 2>/dev/null)"
+ oldremoteref="$(git rev-parse -q --verify \
+ "refs/remotes/$origin/$reflist")"
}
-orig_head=$(git rev-parse --verify HEAD 2>/dev/null)
-git fetch --update-head-ok "$@" || exit 1
+orig_head=$(git rev-parse -q --verify HEAD)
+git fetch $verbosity --update-head-ok "$@" || exit 1
-curr_head=$(git rev-parse --verify HEAD 2>/dev/null)
-if test "$curr_head" != "$orig_head"
+curr_head=$(git rev-parse -q --verify HEAD)
+if test -n "$orig_head" && test "$curr_head" != "$orig_head"
then
# The fetch involved updating the current branch.
@@ -172,7 +176,7 @@ esac
if test -z "$orig_head"
then
- git update-ref -m "initial pull" HEAD $merge_head "" &&
+ git update-ref -m "initial pull" HEAD $merge_head "$curr_head" &&
git read-tree --reset -u HEAD || exit 1
exit
fi
@@ -182,4 +186,4 @@ test true = "$rebase" &&
exec git-rebase $strategy_args --onto $merge_head \
${oldremoteref:-$merge_head}
exec git-merge $no_stat $no_commit $squash $no_ff $log_arg $strategy_args \
- "$merge_name" HEAD $merge_head
+ "$merge_name" HEAD $merge_head $verbosity
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 124cb5846b..8ed2244819 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -26,6 +26,7 @@ i,interactive always used (no-op)
continue continue rebasing process
abort abort rebasing process and restore original branch
skip skip current patch and continue rebasing process
+no-verify override pre-rebase hook from stopping the operation
"
. git-sh-setup
@@ -37,10 +38,12 @@ DONE="$DOTEST"/done
MSG="$DOTEST"/message
SQUASH_MSG="$DOTEST"/message-squash
REWRITTEN="$DOTEST"/rewritten
+DROPPED="$DOTEST"/dropped
PRESERVE_MERGES=
STRATEGY=
ONTO=
VERBOSE=
+OK_TO_SKIP_PRE_REBASE=
GIT_CHERRY_PICK_HELP=" After resolving the conflicts,
mark the corrected paths with 'git add <paths>', and
@@ -66,7 +69,8 @@ output () {
}
run_pre_rebase_hook () {
- if test -x "$GIT_DIR/hooks/pre-rebase"
+ if test -z "$OK_TO_SKIP_PRE_REBASE" &&
+ test -x "$GIT_DIR/hooks/pre-rebase"
then
"$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || {
echo >&2 "The pre-rebase hook refused to rebase."
@@ -111,9 +115,18 @@ mark_action_done () {
}
make_patch () {
- parent_sha1=$(git rev-parse --verify "$1"^) ||
- die "Cannot get patch for $1^"
- git diff-tree -p "$parent_sha1".."$1" > "$DOTEST"/patch
+ sha1_and_parents="$(git rev-list --parents -1 "$1")"
+ case "$sha1_and_parents" in
+ ?*' '?*' '?*)
+ git diff --cc $sha1_and_parents
+ ;;
+ ?*' '?*)
+ git diff-tree -p "$1^!"
+ ;;
+ *)
+ echo "Root commit"
+ ;;
+ esac > "$DOTEST"/patch
test -f "$DOTEST"/message ||
git cat-file commit "$1" | sed "1,/^$/d" > "$DOTEST"/message
test -f "$DOTEST"/author-script ||
@@ -169,21 +182,39 @@ pick_one_preserving_merges () {
if test -f "$DOTEST"/current-commit
then
- current_commit=$(cat "$DOTEST"/current-commit) &&
- git rev-parse HEAD > "$REWRITTEN"/$current_commit &&
- rm "$DOTEST"/current-commit ||
- die "Cannot write current commit's replacement sha1"
+ if test "$fast_forward" = t
+ then
+ cat "$DOTEST"/current-commit | while read current_commit
+ do
+ git rev-parse HEAD > "$REWRITTEN"/$current_commit
+ done
+ rm "$DOTEST"/current-commit ||
+ die "Cannot write current commit's replacement sha1"
+ fi
fi
- echo $sha1 > "$DOTEST"/current-commit
+ echo $sha1 >> "$DOTEST"/current-commit
# rewrite parents; if none were rewritten, we can fast-forward.
new_parents=
- for p in $(git rev-list --parents -1 $sha1 | cut -d' ' -f2-)
+ pend=" $(git rev-list --parents -1 $sha1 | cut -d' ' -f2-)"
+ while [ "$pend" != "" ]
do
+ p=$(expr "$pend" : ' \([^ ]*\)')
+ pend="${pend# $p}"
+
if test -f "$REWRITTEN"/$p
then
new_p=$(cat "$REWRITTEN"/$p)
+
+ # If the todo reordered commits, and our parent is marked for
+ # rewriting, but hasn't been gotten to yet, assume the user meant to
+ # drop it on top of the current HEAD
+ if test -z "$new_p"
+ then
+ new_p=$(git rev-parse HEAD)
+ fi
+
test $p != $new_p && fast_forward=f
case "$new_parents" in
*$new_p*)
@@ -193,7 +224,13 @@ pick_one_preserving_merges () {
;;
esac
else
- new_parents="$new_parents $p"
+ if test -f "$DROPPED"/$p
+ then
+ fast_forward=f
+ pend=" $(cat "$DROPPED"/$p)$pend"
+ else
+ new_parents="$new_parents $p"
+ fi
fi
done
case $fast_forward in
@@ -203,15 +240,19 @@ pick_one_preserving_merges () {
die "Cannot fast forward to $sha1"
;;
f)
- test "a$1" = a-n && die "Refusing to squash a merge: $sha1"
-
first_parent=$(expr "$new_parents" : ' \([^ ]*\)')
- # detach HEAD to current parent
- output git checkout $first_parent 2> /dev/null ||
- die "Cannot move HEAD to $first_parent"
+
+ if [ "$1" != "-n" ]
+ then
+ # detach HEAD to current parent
+ output git checkout $first_parent 2> /dev/null ||
+ die "Cannot move HEAD to $first_parent"
+ fi
case "$new_parents" in
' '*' '*)
+ test "a$1" = a-n && die "Refusing to squash a merge: $sha1"
+
# redo merge
author_script=$(get_author_ident_from_commit $sha1)
eval "$author_script"
@@ -224,9 +265,8 @@ pick_one_preserving_merges () {
output git merge $STRATEGY -m "$msg" \
$new_parents
then
- git rerere
printf "%s\n" "$msg" > "$GIT_DIR"/MERGE_MSG
- die Error redoing merge $sha1
+ die_with_patch $sha1 "Error redoing merge $sha1"
fi
;;
*)
@@ -309,7 +349,7 @@ do_next () {
squash|s)
comment_for_reflog squash
- has_action "$DONE" ||
+ test -f "$DONE" && has_action "$DONE" ||
die "Cannot 'squash' without a previous commit"
mark_action_done
@@ -365,20 +405,7 @@ do_next () {
HEADNAME=$(cat "$DOTEST"/head-name) &&
OLDHEAD=$(cat "$DOTEST"/head) &&
SHORTONTO=$(git rev-parse --short $(cat "$DOTEST"/onto)) &&
- if test -d "$REWRITTEN"
- then
- test -f "$DOTEST"/current-commit &&
- current_commit=$(cat "$DOTEST"/current-commit) &&
- git rev-parse HEAD > "$REWRITTEN"/$current_commit
- if test -f "$REWRITTEN"/$OLDHEAD
- then
- NEWHEAD=$(cat "$REWRITTEN"/$OLDHEAD)
- else
- NEWHEAD=$OLDHEAD
- fi
- else
- NEWHEAD=$(git rev-parse HEAD)
- fi &&
+ NEWHEAD=$(git rev-parse HEAD) &&
case $HEADNAME in
refs/*)
message="$GIT_REFLOG_ACTION: $HEADNAME onto $SHORTONTO)" &&
@@ -421,6 +448,11 @@ get_saved_options () {
while test $# != 0
do
case "$1" in
+ --no-verify)
+ OK_TO_SKIP_PRE_REBASE=yes
+ ;;
+ --verify)
+ ;;
--continue)
is_standalone "$@" || usage
get_saved_options
@@ -572,18 +604,69 @@ first and then run 'git rebase --continue' again."
echo $ONTO > "$REWRITTEN"/$c ||
die "Could not init rewritten commits"
done
+ # No cherry-pick because our first pass is to determine
+ # parents to rewrite and skipping dropped commits would
+ # prematurely end our probe
MERGES_OPTION=
+ first_after_upstream="$(git rev-list --reverse --first-parent $UPSTREAM..$HEAD | head -n 1)"
else
- MERGES_OPTION=--no-merges
+ MERGES_OPTION="--no-merges --cherry-pick"
fi
SHORTUPSTREAM=$(git rev-parse --short $UPSTREAM)
SHORTHEAD=$(git rev-parse --short $HEAD)
SHORTONTO=$(git rev-parse --short $ONTO)
git rev-list $MERGES_OPTION --pretty=oneline --abbrev-commit \
- --abbrev=7 --reverse --left-right --cherry-pick \
+ --abbrev=7 --reverse --left-right --topo-order \
$UPSTREAM...$HEAD | \
- sed -n "s/^>/pick /p" > "$TODO"
+ sed -n "s/^>//p" | while read shortsha1 rest
+ do
+ if test t != "$PRESERVE_MERGES"
+ then
+ echo "pick $shortsha1 $rest" >> "$TODO"
+ else
+ sha1=$(git rev-parse $shortsha1)
+ preserve=t
+ for p in $(git rev-list --parents -1 $sha1 | cut -d' ' -f2-)
+ do
+ if test -f "$REWRITTEN"/$p -a \( $p != $UPSTREAM -o $sha1 = $first_after_upstream \)
+ then
+ preserve=f
+ fi
+ done
+ if test f = "$preserve"
+ then
+ touch "$REWRITTEN"/$sha1
+ echo "pick $shortsha1 $rest" >> "$TODO"
+ fi
+ fi
+ done
+
+ # Watch for commits that been dropped by --cherry-pick
+ if test t = "$PRESERVE_MERGES"
+ then
+ mkdir "$DROPPED"
+ # Save all non-cherry-picked changes
+ git rev-list $UPSTREAM...$HEAD --left-right --cherry-pick | \
+ sed -n "s/^>//p" > "$DOTEST"/not-cherry-picks
+ # Now all commits and note which ones are missing in
+ # not-cherry-picks and hence being dropped
+ git rev-list $UPSTREAM..$HEAD |
+ while read rev
+ do
+ if test -f "$REWRITTEN"/$rev -a "$(grep "$rev" "$DOTEST"/not-cherry-picks)" = ""
+ then
+ # Use -f2 because if rev-list is telling us this commit is
+ # not worthwhile, we don't want to track its multiple heads,
+ # just the history of its first-parent for others that will
+ # be rebasing on top of it
+ git rev-list --parents -1 $rev | cut -d' ' -f2 > "$DROPPED"/$rev
+ short=$(git rev-list -1 --abbrev-commit --abbrev=7 $rev)
+ grep -v "^[a-z][a-z]* $short" <"$TODO" > "${TODO}2" ; mv "${TODO}2" "$TODO"
+ rm "$REWRITTEN"/$rev
+ fi
+ done
+ fi
test -s "$TODO" || echo noop >> "$TODO"
cat >> "$TODO" << EOF
diff --git a/git-rebase.sh b/git-rebase.sh
index a30d40c005..ebd4df3a0e 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -34,6 +34,7 @@ set_reflog_action rebase
require_work_tree
cd_to_toplevel
+OK_TO_SKIP_PRE_REBASE=
RESOLVEMSG="
When you have resolved this problem run \"git rebase --continue\".
If you would prefer to skip this patch, instead run \"git rebase --skip\".
@@ -138,14 +139,31 @@ finish_rb_merge () {
}
is_interactive () {
- test -f "$dotest"/interactive ||
- while :; do case $#,"$1" in 0,|*,-i|*,--interactive) break ;; esac
+ while test $# != 0
+ do
+ case "$1" in
+ -i|--interactive)
+ interactive_rebase=explicit
+ break
+ ;;
+ -p|--preserve-merges)
+ interactive_rebase=implied
+ ;;
+ esac
shift
- done && test -n "$1"
+ done
+
+ if [ "$interactive_rebase" = implied ]; then
+ GIT_EDITOR=:
+ export GIT_EDITOR
+ fi
+
+ test -n "$interactive_rebase" || test -f "$dotest"/interactive
}
run_pre_rebase_hook () {
- if test -x "$GIT_DIR/hooks/pre-rebase"
+ if test -z "$OK_TO_SKIP_PRE_REBASE" &&
+ test -x "$GIT_DIR/hooks/pre-rebase"
then
"$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || {
echo >&2 "The pre-rebase hook refused to rebase."
@@ -170,6 +188,9 @@ fi
while test $# != 0
do
case "$1" in
+ --no-verify)
+ OK_TO_SKIP_PRE_REBASE=yes
+ ;;
--continue)
test -d "$dotest" -o -d "$GIT_DIR"/rebase-apply ||
die "No rebase in progress?"
@@ -311,11 +332,14 @@ else
fi
# The tree must be really really clean.
-git update-index --ignore-submodules --refresh || exit
+if ! git update-index --ignore-submodules --refresh; then
+ echo >&2 "cannot rebase: you have unstaged changes"
+ exit 1
+fi
diff=$(git diff-index --cached --name-status -r --ignore-submodules HEAD --)
case "$diff" in
-?*) echo "cannot rebase: your index is not up-to-date"
- echo "$diff"
+?*) echo >&2 "cannot rebase: your index contains uncommitted changes"
+ echo >&2 "$diff"
exit 1
;;
esac
@@ -344,10 +368,10 @@ case "$#" in
switch_to="$2"
if git show-ref --verify --quiet -- "refs/heads/$2" &&
- branch=$(git rev-parse --verify "refs/heads/$2" 2>/dev/null)
+ branch=$(git rev-parse -q --verify "refs/heads/$2")
then
head_name="refs/heads/$2"
- elif branch=$(git rev-parse --verify "$2" 2>/dev/null)
+ elif branch=$(git rev-parse -q --verify "$2")
then
head_name="detached HEAD"
else
diff --git a/git-repack.sh b/git-repack.sh
index d39eb6cea6..458a497af8 100755
--- a/git-repack.sh
+++ b/git-repack.sh
@@ -71,19 +71,17 @@ case ",$all_into_one," in
existing="$existing $e"
fi
done
- fi
- if test -z "$args"
- then
- args='--unpacked --incremental'
- elif test -n "$unpack_unreachable"
- then
- args="$args $unpack_unreachable"
+ if test -n "$args" -a -n "$unpack_unreachable" -a \
+ -n "$remove_redundant"
+ then
+ args="$args $unpack_unreachable"
+ fi
fi
;;
esac
args="$args $local $quiet $no_reuse$extra"
-names=$(git pack-objects --non-empty --all --reflog $args </dev/null "$PACKTMP") ||
+names=$(git pack-objects --honor-pack-keep --non-empty --all --reflog $args </dev/null "$PACKTMP") ||
exit 1
if [ -z "$names" ]; then
if test -z "$quiet"; then
diff --git a/git-request-pull.sh b/git-request-pull.sh
index 073a314c80..a2cf5b8215 100755
--- a/git-request-pull.sh
+++ b/git-request-pull.sh
@@ -4,9 +4,9 @@
# This file is licensed under the GPL v2, or a later version
# at the discretion of Linus Torvalds.
-USAGE='<commit> <url> [<head>]'
-LONG_USAGE='Summarizes the changes since <commit> to the standard output,
-and includes <url> in the message generated.'
+USAGE='<start> <url> [<end>]'
+LONG_USAGE='Summarizes the changes between two commits to the standard output,
+and includes the given URL in the generated summary.'
SUBDIRECTORY_OK='Yes'
OPTIONS_SPEC=
. git-sh-setup
diff --git a/git-send-email.perl b/git-send-email.perl
index bdbfac6625..77ca8fe880 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -20,10 +20,15 @@ use strict;
use warnings;
use Term::ReadLine;
use Getopt::Long;
+use Text::ParseWords;
use Data::Dumper;
use Term::ANSIColor;
+use File::Temp qw/ tempdir /;
+use Error qw(:try);
use Git;
+Getopt::Long::Configure qw/ pass_through /;
+
package FakeTerm;
sub new {
my ($class, $reason) = @_;
@@ -38,7 +43,7 @@ package main;
sub usage {
print <<EOT;
-git send-email [options] <file | directory>...
+git send-email [options] <file | directory | rev-list options >
Composing:
--from <str> * Email From:
@@ -47,6 +52,7 @@ git send-email [options] <file | directory>...
--bcc <str> * Email Bcc:
--subject <str> * Email "Subject:"
--in-reply-to <str> * Email "In-Reply-To:"
+ --annotate * Review each patch that will be sent in an editor.
--compose * Open an editor for introduction.
Sending:
@@ -73,6 +79,8 @@ git send-email [options] <file | directory>...
--quiet * Output one line of info per email.
--dry-run * Don't actually send the emails.
--[no-]validate * Perform patch sanity checks. Default on.
+ --[no-]format-patch * understand any non optional arguments as
+ `git format-patch` ones.
EOT
exit(1);
@@ -124,12 +132,10 @@ my $auth;
sub unique_email_list(@);
sub cleanup_compose_files();
-# Constants (essentially)
-my $compose_filename = ".msg.$$";
-
# Variables we fill in automatically, or via prompting:
my (@to,@cc,@initial_cc,@bcclist,@xh,
- $initial_reply_to,$initial_subject,@files,$author,$sender,$smtp_authpass,$compose,$time);
+ $initial_reply_to,$initial_subject,@files,
+ $author,$sender,$smtp_authpass,$annotate,$compose,$time);
my $envelope_sender;
@@ -149,6 +155,27 @@ if ($@) {
# Behavior modification variables
my ($quiet, $dry_run) = (0, 0);
+my $format_patch;
+my $compose_filename = $repo->repo_path() . "/.gitsendemail.msg.$$";
+
+# Handle interactive edition of files.
+my $multiedit;
+my $editor = $ENV{GIT_EDITOR} || Git::config(@repo, "core.editor") || $ENV{VISUAL} || $ENV{EDITOR} || "vi";
+sub do_edit {
+ if (defined($multiedit) && !$multiedit) {
+ map {
+ system('sh', '-c', $editor.' "$@"', $editor, $_);
+ if (($? & 127) || ($? >> 8)) {
+ die("the editor exited uncleanly, aborting everything");
+ }
+ } @_;
+ } else {
+ system('sh', '-c', $editor.' "$@"', $editor, @_);
+ if (($? & 127) || ($? >> 8)) {
+ die("the editor exited uncleanly, aborting everything");
+ }
+ }
+}
# Variables with corresponding config settings
my ($thread, $chain_reply_to, $suppress_from, $signed_off_by_cc, $cc_cmd);
@@ -179,6 +206,7 @@ my %config_settings = (
"aliasesfile" => \@alias_files,
"suppresscc" => \@suppress_cc,
"envelopesender" => \$envelope_sender,
+ "multiedit" => \$multiedit,
);
# Handle Uncouth Termination
@@ -221,6 +249,7 @@ my $rc = GetOptions("sender|from=s" => \$sender,
"smtp-ssl" => sub { $smtp_encryption = 'ssl' },
"smtp-encryption=s" => \$smtp_encryption,
"identity=s" => \$identity,
+ "annotate" => \$annotate,
"compose" => \$compose,
"quiet" => \$quiet,
"cc-cmd=s" => \$cc_cmd,
@@ -231,6 +260,7 @@ my $rc = GetOptions("sender|from=s" => \$sender,
"envelope-sender=s" => \$envelope_sender,
"thread!" => \$thread,
"validate!" => \$validate,
+ "format-patch!" => \$format_patch,
);
unless ($rc) {
@@ -330,6 +360,10 @@ foreach my $entry (@bcclist) {
die "Comma in --bcclist entry: $entry'\n" unless $entry !~ m/,/;
}
+sub split_addrs {
+ return quotewords('\s*,\s*', 1, @_);
+}
+
my %aliases;
my %parse_alias = (
# multiline formats can be supported in the future
@@ -338,17 +372,20 @@ my %parse_alias = (
my ($alias, $addr) = ($1, $2);
$addr =~ s/#.*$//; # mutt allows # comments
# commas delimit multiple addresses
- $aliases{$alias} = [ split(/\s*,\s*/, $addr) ];
+ $aliases{$alias} = [ split_addrs($addr) ];
}}},
mailrc => sub { my $fh = shift; while (<$fh>) {
if (/^alias\s+(\S+)\s+(.*)$/) {
# spaces delimit multiple addresses
$aliases{$1} = [ split(/\s+/, $2) ];
}}},
- pine => sub { my $fh = shift; while (<$fh>) {
- if (/^(\S+)\t.*\t(.*)$/) {
- $aliases{$1} = [ split(/\s*,\s*/, $2) ];
- }}},
+ pine => sub { my $fh = shift; my $f='\t[^\t]*';
+ for (my $x = ''; defined($x); $x = $_) {
+ chomp $x;
+ $x .= $1 while(defined($_ = <$fh>) && /^ +(.*)$/);
+ $x =~ /^(\S+)$f\t\(?([^\t]+?)\)?(:?$f){0,2}$/ or next;
+ $aliases{$1} = [ split_addrs($2) ];
+ }},
gnus => sub { my $fh = shift; while (<$fh>) {
if (/\(define-mail-alias\s+"(\S+?)"\s+"(\S+?)"\)/) {
$aliases{$1} = [ $2 ];
@@ -365,24 +402,52 @@ if (@alias_files and $aliasfiletype and defined $parse_alias{$aliasfiletype}) {
($sender) = expand_aliases($sender) if defined $sender;
+# returns 1 if the conflict must be solved using it as a format-patch argument
+sub check_file_rev_conflict($) {
+ my $f = shift;
+ try {
+ $repo->command('rev-parse', '--verify', '--quiet', $f);
+ if (defined($format_patch)) {
+ print "foo\n";
+ return $format_patch;
+ }
+ die(<<EOF);
+File '$f' exists but it could also be the range of commits
+to produce patches for. Please disambiguate by...
+
+ * Saying "./$f" if you mean a file; or
+ * Giving --format-patch option if you mean a range.
+EOF
+ } catch Git::Error::Command with {
+ return 0;
+ }
+}
+
# Now that all the defaults are set, process the rest of the command line
# arguments and collect up the files that need to be processed.
-for my $f (@ARGV) {
- if (-d $f) {
+my @rev_list_opts;
+while (defined(my $f = shift @ARGV)) {
+ if ($f eq "--") {
+ push @rev_list_opts, "--", @ARGV;
+ @ARGV = ();
+ } elsif (-d $f and !check_file_rev_conflict($f)) {
opendir(DH,$f)
or die "Failed to opendir $f: $!";
push @files, grep { -f $_ } map { +$f . "/" . $_ }
sort readdir(DH);
-
- } elsif (-f $f or -p $f) {
+ closedir(DH);
+ } elsif ((-f $f or -p $f) and !check_file_rev_conflict($f)) {
push @files, $f;
-
} else {
- print STDERR "Skipping $f - not found.\n";
+ push @rev_list_opts, $f;
}
}
+if (@rev_list_opts) {
+ push @files, $repo->command('format-patch', '-o', tempdir(CLEANUP => 1), @rev_list_opts);
+}
+
if ($validate) {
foreach my $f (@files) {
unless (-p $f) {
@@ -401,6 +466,108 @@ if (@files) {
usage();
}
+sub get_patch_subject($) {
+ my $fn = shift;
+ open (my $fh, '<', $fn);
+ while (my $line = <$fh>) {
+ next unless ($line =~ /^Subject: (.*)$/);
+ close $fh;
+ return "GIT: $1\n";
+ }
+ close $fh;
+ die "No subject line in $fn ?";
+}
+
+if ($compose) {
+ # Note that this does not need to be secure, but we will make a small
+ # effort to have it be unique
+ open(C,">",$compose_filename)
+ or die "Failed to open for writing $compose_filename: $!";
+
+
+ my $tpl_sender = $sender || $repoauthor || $repocommitter || '';
+ my $tpl_subject = $initial_subject || '';
+ my $tpl_reply_to = $initial_reply_to || '';
+
+ print C <<EOT;
+From $tpl_sender # This line is ignored.
+GIT: Lines beginning in "GIT: " will be removed.
+GIT: Consider including an overall diffstat or table of contents
+GIT: for the patch you are writing.
+GIT:
+GIT: Clear the body content if you don't wish to send a summary.
+From: $tpl_sender
+Subject: $tpl_subject
+In-Reply-To: $tpl_reply_to
+
+EOT
+ for my $f (@files) {
+ print C get_patch_subject($f);
+ }
+ close(C);
+
+ my $editor = $ENV{GIT_EDITOR} || Git::config(@repo, "core.editor") || $ENV{VISUAL} || $ENV{EDITOR} || "vi";
+
+ if ($annotate) {
+ do_edit($compose_filename, @files);
+ } else {
+ do_edit($compose_filename);
+ }
+
+ open(C2,">",$compose_filename . ".final")
+ or die "Failed to open $compose_filename.final : " . $!;
+
+ open(C,"<",$compose_filename)
+ or die "Failed to open $compose_filename : " . $!;
+
+ my $need_8bit_cte = file_has_nonascii($compose_filename);
+ my $in_body = 0;
+ my $summary_empty = 1;
+ while(<C>) {
+ next if m/^GIT: /;
+ if ($in_body) {
+ $summary_empty = 0 unless (/^\n$/);
+ } elsif (/^\n$/) {
+ $in_body = 1;
+ if ($need_8bit_cte) {
+ print C2 "MIME-Version: 1.0\n",
+ "Content-Type: text/plain; ",
+ "charset=utf-8\n",
+ "Content-Transfer-Encoding: 8bit\n";
+ }
+ } elsif (/^MIME-Version:/i) {
+ $need_8bit_cte = 0;
+ } elsif (/^Subject:\s*(.+)\s*$/i) {
+ $initial_subject = $1;
+ my $subject = $initial_subject;
+ $_ = "Subject: " .
+ ($subject =~ /[^[:ascii:]]/ ?
+ quote_rfc2047($subject) :
+ $subject) .
+ "\n";
+ } elsif (/^In-Reply-To:\s*(.+)\s*$/i) {
+ $initial_reply_to = $1;
+ next;
+ } elsif (/^From:\s*(.+)\s*$/i) {
+ $sender = $1;
+ next;
+ } elsif (/^(?:To|Cc|Bcc):/i) {
+ print "To/Cc/Bcc fields are not interpreted yet, they have been ignored\n";
+ next;
+ }
+ print C2 $_;
+ }
+ close(C);
+ close(C2);
+
+ if ($summary_empty) {
+ print "Summary email is empty, skipping it\n";
+ $compose = -1;
+ }
+} elsif ($annotate) {
+ do_edit(@files);
+}
+
my $prompting = 0;
if (!defined $sender) {
$sender = $repoauthor || $repocommitter || '';
@@ -426,7 +593,7 @@ if (!@to) {
}
my $to = $_;
- push @to, split /,\s*/, $to;
+ push @to, split_addrs($to);
$prompting++;
}
@@ -445,17 +612,6 @@ sub expand_aliases {
@initial_cc = expand_aliases(@initial_cc);
@bcclist = expand_aliases(@bcclist);
-if (!defined $initial_subject && $compose) {
- while (1) {
- $_ = $term->readline("What subject should the initial email start with? ", $initial_subject);
- last if defined $_;
- print "\n";
- }
-
- $initial_subject = $_;
- $prompting++;
-}
-
if ($thread && !defined $initial_reply_to && $prompting) {
while (1) {
$_= $term->readline("Message-ID to be used as In-Reply-To for the first email? ", $initial_reply_to);
@@ -482,59 +638,6 @@ if (!defined $smtp_server) {
}
if ($compose) {
- # Note that this does not need to be secure, but we will make a small
- # effort to have it be unique
- open(C,">",$compose_filename)
- or die "Failed to open for writing $compose_filename: $!";
- print C "From $sender # This line is ignored.\n";
- printf C "Subject: %s\n\n", $initial_subject;
- printf C <<EOT;
-GIT: Please enter your email below.
-GIT: Lines beginning in "GIT: " will be removed.
-GIT: Consider including an overall diffstat or table of contents
-GIT: for the patch you are writing.
-
-EOT
- close(C);
-
- my $editor = $ENV{GIT_EDITOR} || Git::config(@repo, "core.editor") || $ENV{VISUAL} || $ENV{EDITOR} || "vi";
- system('sh', '-c', $editor.' "$@"', $editor, $compose_filename);
-
- open(C2,">",$compose_filename . ".final")
- or die "Failed to open $compose_filename.final : " . $!;
-
- open(C,"<",$compose_filename)
- or die "Failed to open $compose_filename : " . $!;
-
- my $need_8bit_cte = file_has_nonascii($compose_filename);
- my $in_body = 0;
- while(<C>) {
- next if m/^GIT: /;
- if (!$in_body && /^\n$/) {
- $in_body = 1;
- if ($need_8bit_cte) {
- print C2 "MIME-Version: 1.0\n",
- "Content-Type: text/plain; ",
- "charset=utf-8\n",
- "Content-Transfer-Encoding: 8bit\n";
- }
- }
- if (!$in_body && /^MIME-Version:/i) {
- $need_8bit_cte = 0;
- }
- if (!$in_body && /^Subject: ?(.*)/i) {
- my $subject = $1;
- $_ = "Subject: " .
- ($subject =~ /[^[:ascii:]]/ ?
- quote_rfc2047($subject) :
- $subject) .
- "\n";
- }
- print C2 $_;
- }
- close(C);
- close(C2);
-
while (1) {
$_ = $term->readline("Send this email? (y|n) ");
last if defined $_;
@@ -546,7 +649,9 @@ EOT
exit(0);
}
- @files = ($compose_filename . ".final", @files);
+ if ($compose > 0) {
+ @files = ($compose_filename . ".final", @files);
+ }
}
# Variables we set as part of the loop over files
diff --git a/git-sh-setup.sh b/git-sh-setup.sh
index dbdf209ec0..2142308bcc 100755
--- a/git-sh-setup.sh
+++ b/git-sh-setup.sh
@@ -85,8 +85,27 @@ cd_to_toplevel () {
cdup=$(git rev-parse --show-cdup)
if test ! -z "$cdup"
then
- cd "$cdup" || {
- echo >&2 "Cannot chdir to $cdup, the toplevel of the working tree"
+ case "$cdup" in
+ /*)
+ # Not quite the same as if we did "cd -P '$cdup'" when
+ # $cdup contains ".." after symlink path components.
+ # Don't fix that case at least until Git switches to
+ # "cd -P" across the board.
+ phys="$cdup"
+ ;;
+ ..|../*|*/..|*/../*)
+ # Interpret $cdup relative to the physical, not logical, cwd.
+ # Probably /bin/pwd is more portable than passing -P to cd or pwd.
+ phys="$(unset PWD; /bin/pwd)/$cdup"
+ ;;
+ *)
+ # There's no "..", so no need to make things absolute.
+ phys="$cdup"
+ ;;
+ esac
+
+ cd "$phys" || {
+ echo >&2 "Cannot chdir to $phys, the toplevel of the working tree"
exit 1
}
fi
diff --git a/git-submodule.sh b/git-submodule.sh
index 65178ae8e3..2f47e065fe 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -323,7 +323,7 @@ cmd_update()
# Only mention uninitialized submodules when its
# path have been specified
test "$#" != "0" &&
- say "Submodule path '$path' not initialized"
+ say "Submodule path '$path' not initialized" &&
say "Maybe you want to use 'update --init'?"
continue
fi
@@ -413,7 +413,7 @@ cmd_summary() {
test $summary_limit = 0 && return
- if rev=$(git rev-parse --verify "$1^0" 2>/dev/null)
+ if rev=$(git rev-parse -q --verify "$1^0")
then
head=$rev
shift
@@ -424,7 +424,7 @@ cmd_summary() {
cd_to_toplevel
# Get modified modules cared by user
modules=$(git diff-index $cached --raw $head -- "$@" |
- grep -e '^:160000' -e '^:[0-7]* 160000' |
+ egrep '^:([0-7]* )?160000' |
while read mod_src mod_dst sha1_src sha1_dst status name
do
# Always show modules deleted or type-changed (blob<->module)
@@ -438,7 +438,7 @@ cmd_summary() {
test -z "$modules" && return
git diff-index $cached --raw $head -- $modules |
- grep -e '^:160000' -e '^:[0-7]* 160000' |
+ egrep '^:([0-7]* )?160000' |
cut -c2- |
while read mod_src mod_dst sha1_src sha1_dst status name
do
@@ -464,11 +464,11 @@ cmd_summary() {
missing_dst=
test $mod_src = 160000 &&
- ! GIT_DIR="$name/.git" git-rev-parse --verify $sha1_src^0 >/dev/null 2>&1 &&
+ ! GIT_DIR="$name/.git" git-rev-parse -q --verify $sha1_src^0 >/dev/null &&
missing_src=t
test $mod_dst = 160000 &&
- ! GIT_DIR="$name/.git" git-rev-parse --verify $sha1_dst^0 >/dev/null 2>&1 &&
+ ! GIT_DIR="$name/.git" git-rev-parse -q --verify $sha1_dst^0 >/dev/null &&
missing_dst=t
total_commits=
diff --git a/git-svn.perl b/git-svn.perl
index ef6d773df1..ad01e182df 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -223,11 +223,13 @@ unless ($cmd && $cmd =~ /(?:clone|init|multi-init)$/) {
"but it is not a directory\n";
}
my $git_dir = delete $ENV{GIT_DIR};
- chomp(my $cdup = command_oneline(qw/rev-parse --show-cdup/));
- unless (length $cdup) {
- die "Already at toplevel, but $git_dir ",
- "not found '$cdup'\n";
- }
+ my $cdup = undef;
+ git_cmd_try {
+ $cdup = command_oneline(qw/rev-parse --show-cdup/);
+ $git_dir = '.' unless ($cdup);
+ chomp $cdup if ($cdup);
+ $cdup = "." unless ($cdup && length $cdup);
+ } "Already at toplevel, but $git_dir not found\n";
chdir $cdup or die "Unable to chdir up to '$cdup'\n";
unless (-d $git_dir) {
die "$git_dir still not found after going to ",
@@ -556,7 +558,7 @@ sub cmd_branch {
my ($src, $rev, undef, $gs) = working_head_info($head);
- my $remote = Git::SVN::read_all_remotes()->{svn};
+ my $remote = Git::SVN::read_all_remotes()->{$gs->{repo_id}};
my $glob = $remote->{ $_tag ? 'tags' : 'branches' };
my ($lft, $rgt) = @{ $glob->{path} }{qw/left right/};
my $dst = join '/', $remote->{url}, $lft, $branch_name, ($rgt || ());
@@ -852,7 +854,7 @@ sub escape_uri_only {
my ($uri) = @_;
my @tmp;
foreach (split m{/}, $uri) {
- s/([^\w.%+-]|%(?![a-fA-F0-9]{2}))/sprintf("%%%02X",ord($1))/eg;
+ s/([^~\w.%+-]|%(?![a-fA-F0-9]{2}))/sprintf("%%%02X",ord($1))/eg;
push @tmp, $_;
}
join('/', @tmp);
@@ -1136,9 +1138,19 @@ sub get_commit_entry {
system($editor, $commit_editmsg);
}
rename $commit_editmsg, $commit_msg or croak $!;
- open $log_fh, '<', $commit_msg or croak $!;
- { local $/; chomp($log_entry{log} = <$log_fh>); }
- close $log_fh or croak $!;
+ {
+ # SVN requires messages to be UTF-8 when entering the repo
+ local $/;
+ open $log_fh, '<', $commit_msg or croak $!;
+ binmode $log_fh;
+ chomp($log_entry{log} = <$log_fh>);
+
+ if (my $enc = Git::config('i18n.commitencoding')) {
+ require Encode;
+ Encode::from_to($log_entry{log}, $enc, 'UTF-8');
+ }
+ close $log_fh or croak $!;
+ }
unlink $commit_msg;
\%log_entry;
}
@@ -1191,7 +1203,7 @@ sub read_repo_config {
my $v = $opts->{$o};
my ($key) = ($o =~ /^([a-zA-Z\-]+)/);
$key =~ s/-//g;
- my $arg = 'git-config';
+ my $arg = 'git config';
$arg .= ' --int' if ($o =~ /[:=]i$/);
$arg .= ' --bool' if ($o !~ /[:=][sfi]$/);
if (ref $v eq 'ARRAY') {
@@ -2267,12 +2279,20 @@ sub do_git_commit {
}
die "Tree is not a valid sha1: $tree\n" if $tree !~ /^$::sha1$/o;
- my @exec = ('git-commit-tree', $tree);
+ my @exec = ('git', 'commit-tree', $tree);
foreach ($self->get_commit_parents($log_entry)) {
push @exec, '-p', $_;
}
defined(my $pid = open3(my $msg_fh, my $out_fh, '>&STDERR', @exec))
or croak $!;
+ binmode $msg_fh;
+
+ # we always get UTF-8 from SVN, but we may want our commits in
+ # a different encoding.
+ if (my $enc = Git::config('i18n.commitencoding')) {
+ require Encode;
+ Encode::from_to($log_entry->{log}, 'UTF-8', $enc);
+ }
print $msg_fh $log_entry->{log} or croak $!;
restore_commit_header_env($old_env);
unless ($self->no_metadata) {
@@ -2383,12 +2403,20 @@ sub find_parent_branch {
$gs = Git::SVN->init($u, $p, $repo_id, $ref_id, 1);
}
my ($r0, $parent) = $gs->find_rev_before($r, 1);
- if (!defined $r0 || !defined $parent) {
- my ($base, $head) = parse_revision_argument(0, $r);
- if ($base <= $r) {
+ {
+ my ($base, $head);
+ if (!defined $r0 || !defined $parent) {
+ ($base, $head) = parse_revision_argument(0, $r);
+ } else {
+ if ($r0 < $r) {
+ $gs->ra->get_log([$gs->{path}], $r0 + 1, $r, 1,
+ 0, 1, sub { $base = $_[1] - 1 });
+ }
+ }
+ if (defined $base && $base <= $r) {
$gs->fetch($base, $r);
}
- ($r0, $parent) = $gs->last_rev_commit;
+ ($r0, $parent) = $gs->find_rev_before($r, 1);
}
if (defined $r0 && defined $parent) {
print STDERR "Found branch parent: ($self->{ref_id}) $parent\n";
@@ -3312,11 +3340,11 @@ sub change_file_prop {
sub apply_textdelta {
my ($self, $fb, $exp) = @_;
- my $fh = Git::temp_acquire('svn_delta');
+ my $fh = $::_repository->temp_acquire('svn_delta');
# $fh gets auto-closed() by SVN::TxDelta::apply(),
# (but $base does not,) so dup() it for reading in close_file
open my $dup, '<&', $fh or croak $!;
- my $base = Git::temp_acquire('git_blob');
+ my $base = $::_repository->temp_acquire('git_blob');
if ($fb->{blob}) {
print $base 'link ' if ($fb->{mode_a} == 120000);
my $size = $::_repository->cat_blob($fb->{blob}, $base);
@@ -3357,7 +3385,8 @@ sub close_file {
warn "$path has mode 120000",
" but is not a link\n";
} else {
- my $tmp_fh = Git::temp_acquire('svn_hash');
+ my $tmp_fh = $::_repository->temp_acquire(
+ 'svn_hash');
my $res;
while ($res = sysread($fh, my $str, 1024)) {
my $out = syswrite($tmp_fh, $str, $res);
@@ -3537,7 +3566,7 @@ sub repo_path {
sub url_path {
my ($self, $path) = @_;
if ($self->{url} =~ m#^https?://#) {
- $path =~ s/([^a-zA-Z0-9_.-])/uc sprintf("%%%02x",ord($1))/eg;
+ $path =~ s/([^~a-zA-Z0-9_.-])/uc sprintf("%%%02x",ord($1))/eg;
}
$self->{url} . '/' . $self->repo_path($path);
}
@@ -3745,7 +3774,7 @@ sub change_file_prop {
sub _chg_file_get_blob ($$$$) {
my ($self, $fbat, $m, $which) = @_;
- my $fh = Git::temp_acquire("git_blob_$which");
+ my $fh = $::_repository->temp_acquire("git_blob_$which");
if ($m->{"mode_$which"} =~ /^120/) {
print $fh 'link ' or croak $!;
$self->change_file_prop($fbat,'svn:special','*');
@@ -3890,7 +3919,7 @@ sub escape_uri_only {
my ($uri) = @_;
my @tmp;
foreach (split m{/}, $uri) {
- s/([^\w.%+-]|%(?![a-fA-F0-9]{2}))/sprintf("%%%02X",ord($1))/eg;
+ s/([^~\w.%+-]|%(?![a-fA-F0-9]{2}))/sprintf("%%%02X",ord($1))/eg;
push @tmp, $_;
}
join('/', @tmp);
@@ -4986,8 +5015,7 @@ sub minimize_connections {
}
}
if (@emptied) {
- my $file = $ENV{GIT_CONFIG} || $ENV{GIT_CONFIG_LOCAL} ||
- "$ENV{GIT_DIR}/config";
+ my $file = $ENV{GIT_CONFIG} || "$ENV{GIT_DIR}/config";
print STDERR <<EOF;
The following [svn-remote] sections in your config file ($file) are empty
and can be safely removed:
diff --git a/git.c b/git.c
index 89feb0b6dc..ecc8fad09a 100644
--- a/git.c
+++ b/git.c
@@ -158,7 +158,7 @@ static int handle_alias(int *argcp, const char ***argv)
if (ret >= 0 && WIFEXITED(ret) &&
WEXITSTATUS(ret) != 127)
exit(WEXITSTATUS(ret));
- die("Failed to run '%s' when expanding alias '%s'\n",
+ die("Failed to run '%s' when expanding alias '%s'",
alias_string + 1, alias_command);
}
count = split_cmdline(alias_string, &new_argv);
@@ -195,8 +195,8 @@ static int handle_alias(int *argcp, const char ***argv)
ret = 1;
}
- if (subdir)
- chdir(subdir);
+ if (subdir && chdir(subdir))
+ die("Cannot change to %s: %s", subdir, strerror(errno));
errno = saved_errno;
@@ -266,6 +266,7 @@ static void handle_internal_command(int argc, const char **argv)
const char *cmd = argv[0];
static struct cmd_struct commands[] = {
{ "add", cmd_add, RUN_SETUP | NEED_WORK_TREE },
+ { "stage", cmd_add, RUN_SETUP | NEED_WORK_TREE },
{ "annotate", cmd_annotate, RUN_SETUP },
{ "apply", cmd_apply },
{ "archive", cmd_archive },
@@ -415,21 +416,42 @@ static void execv_dashed_external(const char **argv)
strbuf_release(&cmd);
}
+static int run_argv(int *argcp, const char ***argv)
+{
+ int done_alias = 0;
+
+ while (1) {
+ /* See if it's an internal command */
+ handle_internal_command(*argcp, *argv);
+
+ /* .. then try the external ones */
+ execv_dashed_external(*argv);
+
+ /* It could be an alias -- this works around the insanity
+ * of overriding "git log" with "git show" by having
+ * alias.log = show
+ */
+ if (done_alias || !handle_alias(argcp, argv))
+ break;
+ done_alias = 1;
+ }
+
+ return done_alias;
+}
+
int main(int argc, const char **argv)
{
const char *cmd = argv[0] && *argv[0] ? argv[0] : "git-help";
char *slash = (char *)cmd + strlen(cmd);
- int done_alias = 0;
/*
* Take the basename of argv[0] as the command
* name, and the dirname as the default exec_path
* if we don't have anything better.
*/
- do
- --slash;
- while (cmd <= slash && !is_dir_sep(*slash));
+ while (cmd <= slash && !is_dir_sep(*slash))
+ slash--;
if (cmd <= slash) {
*slash++ = 0;
git_set_argv0_path(cmd);
@@ -479,31 +501,22 @@ int main(int argc, const char **argv)
setup_path();
while (1) {
- /* See if it's an internal command */
- handle_internal_command(argc, argv);
-
- /* .. then try the external ones */
- execv_dashed_external(argv);
-
- /* It could be an alias -- this works around the insanity
- * of overriding "git log" with "git show" by having
- * alias.log = show
- */
- if (done_alias || !handle_alias(&argc, &argv))
+ static int done_help = 0;
+ static int was_alias = 0;
+ was_alias = run_argv(&argc, &argv);
+ if (errno != ENOENT)
break;
- done_alias = 1;
- }
-
- if (errno == ENOENT) {
- if (done_alias) {
+ if (was_alias) {
fprintf(stderr, "Expansion of alias '%s' failed; "
"'%s' is not a git-command\n",
cmd, argv[0]);
exit(1);
}
- argv[0] = help_unknown_cmd(cmd);
- handle_internal_command(argc, argv);
- execv_dashed_external(argv);
+ if (!done_help) {
+ cmd = argv[0] = help_unknown_cmd(cmd);
+ done_help = 1;
+ } else
+ break;
}
fprintf(stderr, "Failed to run command '%s': %s\n",
diff --git a/git.spec.in b/git.spec.in
index 6733b6f555..069ace050d 100644
--- a/git.spec.in
+++ b/git.spec.in
@@ -168,6 +168,7 @@ rm -rf $RPM_BUILD_ROOT
%defattr(-,root,root)
%{_libexecdir}/git-core/git-gui
%{_libexecdir}/git-core/git-citool
+%{_libexecdir}/git-core/git-gui--askpass
%{_datadir}/git-gui/
%{!?_without_docs: %{_mandir}/man1/git-gui.1*}
%{!?_without_docs: %doc Documentation/git-gui.html}
diff --git a/gitk-git/gitk b/gitk-git/gitk
index 2eaa2ae7d6..dc2a439618 100644
--- a/gitk-git/gitk
+++ b/gitk-git/gitk
@@ -155,18 +155,16 @@ proc parseviewargs {n arglist} {
set origargs [lreplace $origargs $i $i]
incr i -1
}
- # These request or affect diff output, which we don't want.
- # Some could be used to set our defaults for diff display.
"-[puabwcrRBMC]" -
"--no-renames" - "--full-index" - "--binary" - "--abbrev=*" -
"--find-copies-harder" - "-l*" - "--ext-diff" - "--no-ext-diff" -
"--src-prefix=*" - "--dst-prefix=*" - "--no-prefix" -
"-O*" - "--text" - "--full-diff" - "--ignore-space-at-eol" -
"--ignore-space-change" - "-U*" - "--unified=*" {
+ # These request or affect diff output, which we don't want.
+ # Some could be used to set our defaults for diff display.
lappend diffargs $arg
}
- # These cause our parsing of git log's output to fail, or else
- # they're options we want to set ourselves, so ignore them.
"--raw" - "--patch-with-raw" - "--patch-with-stat" -
"--name-only" - "--name-status" - "--color" - "--color-words" -
"--log-size" - "--pretty=*" - "--decorate" - "--abbrev-commit" -
@@ -174,36 +172,34 @@ proc parseviewargs {n arglist} {
"--no-color" - "-g" - "--walk-reflogs" - "--no-walk" -
"--timestamp" - "relative-date" - "--date=*" - "--stdin" -
"--objects" - "--objects-edge" - "--reverse" {
+ # These cause our parsing of git log's output to fail, or else
+ # they're options we want to set ourselves, so ignore them.
}
- # These are harmless, and some are even useful
"--stat=*" - "--numstat" - "--shortstat" - "--summary" -
"--check" - "--exit-code" - "--quiet" - "--topo-order" -
"--full-history" - "--dense" - "--sparse" -
"--follow" - "--left-right" - "--encoding=*" {
+ # These are harmless, and some are even useful
lappend glflags $arg
}
- # These mean that we get a subset of the commits
"--diff-filter=*" - "--no-merges" - "--unpacked" -
"--max-count=*" - "--skip=*" - "--since=*" - "--after=*" -
"--until=*" - "--before=*" - "--max-age=*" - "--min-age=*" -
"--author=*" - "--committer=*" - "--grep=*" - "-[iE]" -
"--remove-empty" - "--first-parent" - "--cherry-pick" -
- "-S*" - "--pickaxe-all" - "--pickaxe-regex" - {
+ "-S*" - "--pickaxe-all" - "--pickaxe-regex" {
+ # These mean that we get a subset of the commits
set filtered 1
lappend glflags $arg
}
- # This appears to be the only one that has a value as a
- # separate word following it
"-n" {
+ # This appears to be the only one that has a value as a
+ # separate word following it
set filtered 1
set nextisval 1
lappend glflags $arg
}
- "--not" {
- set notflag [expr {!$notflag}]
- lappend revargs $arg
- }
- "--all" {
+ "--not" - "--all" {
lappend revargs $arg
}
"--merge" {
@@ -211,8 +207,8 @@ proc parseviewargs {n arglist} {
# git rev-parse doesn't understand --merge
lappend revargs --gitk-symmetric-diff-marker MERGE_HEAD...HEAD
}
- # Other flag arguments including -<n>
"-*" {
+ # Other flag arguments including -<n>
if {[string is digit -strict [string range $arg 1 end]]} {
set filtered 1
} else {
@@ -222,8 +218,8 @@ proc parseviewargs {n arglist} {
}
lappend glflags $arg
}
- # Non-flag arguments specify commits or ranges of commits
default {
+ # Non-flag arguments specify commits or ranges of commits
if {[string match "*...*" $arg]} {
lappend revargs --gitk-symmetric-diff-marker
}
@@ -269,7 +265,7 @@ proc parseviewrevs {view revs} {
lappend badrev $line
}
}
- error_popup "Error parsing revisions: $err"
+ error_popup "[mc "Error parsing revisions:"] $err"
return {}
}
set ret {}
@@ -307,9 +303,9 @@ proc start_rev_list {view} {
global startmsecs commitidx viewcomplete curview
global tclencoding
global viewargs viewargscmd viewfiles vfilelimit
- global showlocalchanges commitinterest
+ global showlocalchanges
global viewactive viewinstances vmergeonly
- global mainheadid
+ global mainheadid viewmainheadid viewmainheadid_orig
global vcanopt vflags vrevs vorigargs
set startmsecs [clock clicks -milliseconds]
@@ -324,7 +320,7 @@ proc start_rev_list {view} {
if {[catch {
set str [exec sh -c $viewargscmd($view)]
} err]} {
- error_popup "Error executing --argscmd command: $err"
+ error_popup "[mc "Error executing --argscmd command:"] $err"
return 0
}
set args [concat $args [split $str "\n"]]
@@ -367,8 +363,13 @@ proc start_rev_list {view} {
}
set i [reg_instance $fd]
set viewinstances($view) [list $i]
- if {$showlocalchanges && $mainheadid ne {}} {
- lappend commitinterest($mainheadid) {dodiffindex}
+ set viewmainheadid($view) $mainheadid
+ set viewmainheadid_orig($view) $mainheadid
+ if {$files ne {} && $mainheadid ne {}} {
+ get_viewmainhead $view
+ }
+ if {$showlocalchanges && $viewmainheadid($view) ne {}} {
+ interestedin $viewmainheadid($view) dodiffindex
}
fconfigure $fd -blocking 0 -translation lf -eofchar {}
if {$tclencoding != {}} {
@@ -446,22 +447,26 @@ proc updatecommits {} {
global curview vcanopt vorigargs vfilelimit viewinstances
global viewactive viewcomplete tclencoding
global startmsecs showneartags showlocalchanges
- global mainheadid pending_select
+ global mainheadid viewmainheadid viewmainheadid_orig pending_select
global isworktree
global varcid vposids vnegids vflags vrevs
set isworktree [expr {[exec git rev-parse --is-inside-work-tree] == "true"}]
- set oldmainid $mainheadid
rereadrefs
- if {$showlocalchanges} {
- if {$mainheadid ne $oldmainid} {
+ set view $curview
+ if {$mainheadid ne $viewmainheadid_orig($view)} {
+ if {$showlocalchanges} {
dohidelocalchanges
}
- if {[commitinview $mainheadid $curview]} {
- dodiffindex
+ set viewmainheadid($view) $mainheadid
+ set viewmainheadid_orig($view) $mainheadid
+ if {$vfilelimit($view) ne {}} {
+ get_viewmainhead $view
}
}
- set view $curview
+ if {$showlocalchanges} {
+ doshowlocalchanges
+ }
if {$vcanopt($view)} {
set oldpos $vposids($view)
set oldneg $vnegids($view)
@@ -500,7 +505,7 @@ proc updatecommits {} {
set fd [open [concat | git log --no-color -z --pretty=raw --parents \
--boundary $args "--" $vfilelimit($view)] r]
} err]} {
- error_popup "Error executing git log: $err"
+ error_popup "[mc "Error executing git log:"] $err"
return
}
if {$viewactive($view) == 0} {
@@ -1231,7 +1236,7 @@ proc commitonrow {row} {
proc closevarcs {v} {
global varctok varccommits varcid parents children
- global cmitlisted commitidx commitinterest vtokmod
+ global cmitlisted commitidx vtokmod
set missing_parents 0
set scripts {}
@@ -1256,12 +1261,7 @@ proc closevarcs {v} {
}
lappend varccommits($v,$b) $p
incr commitidx($v)
- if {[info exists commitinterest($p)]} {
- foreach script $commitinterest($p) {
- lappend scripts [string map [list "%I" $p] $script]
- }
- unset commitinterest($id)
- }
+ set scripts [check_interest $p $scripts]
}
}
if {$missing_parents > 0} {
@@ -1297,8 +1297,41 @@ proc rewrite_commit {v id rwid} {
}
}
+# Mechanism for registering a command to be executed when we come
+# across a particular commit. To handle the case when only the
+# prefix of the commit is known, the commitinterest array is now
+# indexed by the first 4 characters of the ID. Each element is a
+# list of id, cmd pairs.
+proc interestedin {id cmd} {
+ global commitinterest
+
+ lappend commitinterest([string range $id 0 3]) $id $cmd
+}
+
+proc check_interest {id scripts} {
+ global commitinterest
+
+ set prefix [string range $id 0 3]
+ if {[info exists commitinterest($prefix)]} {
+ set newlist {}
+ foreach {i script} $commitinterest($prefix) {
+ if {[string match "$i*" $id]} {
+ lappend scripts [string map [list "%I" $id "%P" $i] $script]
+ } else {
+ lappend newlist $i $script
+ }
+ }
+ if {$newlist ne {}} {
+ set commitinterest($prefix) $newlist
+ } else {
+ unset commitinterest($prefix)
+ }
+ }
+ return $scripts
+}
+
proc getcommitlines {fd inst view updating} {
- global cmitlisted commitinterest leftover
+ global cmitlisted leftover
global commitidx commitdata vdatemode
global parents children curview hlview
global idpending ordertok
@@ -1474,12 +1507,7 @@ proc getcommitlines {fd inst view updating} {
incr i
}
- if {[info exists commitinterest($id)]} {
- foreach script $commitinterest($id) {
- lappend scripts [string map [list "%I" $id] $script]
- }
- unset commitinterest($id)
- }
+ set scripts [check_interest $id $scripts]
set gotsome 1
}
if {$gotsome} {
@@ -1532,9 +1560,27 @@ proc chewcommits {} {
return 0
}
+proc do_readcommit {id} {
+ global tclencoding
+
+ # Invoke git-log to handle automatic encoding conversion
+ set fd [open [concat | git log --no-color --pretty=raw -1 $id] r]
+ # Read the results using i18n.logoutputencoding
+ fconfigure $fd -translation lf -eofchar {}
+ if {$tclencoding != {}} {
+ fconfigure $fd -encoding $tclencoding
+ }
+ set contents [read $fd]
+ close $fd
+ # Remove the heading line
+ regsub {^commit [0-9a-f]+\n} $contents {} contents
+
+ return $contents
+}
+
proc readcommit {id} {
- if {[catch {set contents [exec git cat-file commit $id]}]} return
- parsecommit $id $contents 0
+ if {[catch {set contents [do_readcommit $id]}]} return
+ parsecommit $id $contents 1
}
proc parsecommit {id contents listed} {
@@ -1555,13 +1601,14 @@ proc parsecommit {id contents listed} {
set header [string range $contents 0 [expr {$hdrend - 1}]]
set comment [string range $contents [expr {$hdrend + 2}] end]
foreach line [split $header "\n"] {
+ set line [split $line " "]
set tag [lindex $line 0]
if {$tag == "author"} {
set audate [lindex $line end-1]
- set auname [lrange $line 1 end-2]
+ set auname [join [lrange $line 1 end-2] " "]
} elseif {$tag == "committer"} {
set comdate [lindex $line end-1]
- set comname [lrange $line 1 end-2]
+ set comname [join [lrange $line 1 end-2] " "]
}
}
set headline {}
@@ -1608,6 +1655,19 @@ proc getcommit {id} {
return 1
}
+# Expand an abbreviated commit ID to a list of full 40-char IDs that match
+# and are present in the current view.
+# This is fairly slow...
+proc longid {prefix} {
+ global varcid curview
+
+ set ids {}
+ foreach match [array names varcid "$curview,$prefix*"] {
+ lappend ids [lindex [split $match ","] 1]
+ }
+ return $ids
+}
+
proc readrefs {} {
global tagids idtags headids idheads tagobjid
global otherrefids idotherrefs mainhead mainheadid
@@ -1703,6 +1763,24 @@ proc removehead {id name} {
unset headids($name)
}
+proc make_transient {window origin} {
+ global have_tk85
+
+ # In MacOS Tk 8.4 transient appears to work by setting
+ # overrideredirect, which is utterly useless, since the
+ # windows get no border, and are not even kept above
+ # the parent.
+ if {!$have_tk85 && [tk windowingsystem] eq {aqua}} return
+
+ wm transient $window $origin
+
+ # Windows fails to place transient windows normally, so
+ # schedule a callback to center them on the parent.
+ if {[tk windowingsystem] eq {win32}} {
+ after idle [list tk::PlaceWindow $window widget $origin]
+ }
+}
+
proc show_error {w top msg} {
message $w.m -text $msg -justify center -aspect 400
pack $w.m -side top -fill x -padx 20 -pady 20
@@ -1710,22 +1788,24 @@ proc show_error {w top msg} {
pack $w.ok -side bottom -fill x
bind $top <Visibility> "grab $top; focus $top"
bind $top <Key-Return> "destroy $top"
+ bind $top <Key-space> "destroy $top"
+ bind $top <Key-Escape> "destroy $top"
tkwait window $top
}
-proc error_popup msg {
+proc error_popup {msg {owner .}} {
set w .error
toplevel $w
- wm transient $w .
+ make_transient $w $owner
show_error $w $w $msg
}
-proc confirm_popup msg {
+proc confirm_popup {msg {owner .}} {
global confirm_ok
set confirm_ok 0
set w .confirm
toplevel $w
- wm transient $w .
+ make_transient $w $owner
message $w.m -text $msg -justify center -aspect 400
pack $w.m -side top -fill x -padx 20 -pady 20
button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
@@ -1733,6 +1813,9 @@ proc confirm_popup msg {
button $w.cancel -text [mc Cancel] -command "destroy $w"
pack $w.cancel -side right -fill x
bind $w <Visibility> "grab $w; focus $w"
+ bind $w <Key-Return> "set confirm_ok 1; destroy $w"
+ bind $w <Key-space> "set confirm_ok 1; destroy $w"
+ bind $w <Key-Escape> "destroy $w"
tkwait window $w
return $confirm_ok
}
@@ -1750,6 +1833,60 @@ proc setoptions {} {
option add *Entry.font uifont startupFile
}
+# Make a menu and submenus.
+# m is the window name for the menu, items is the list of menu items to add.
+# Each item is a list {mc label type description options...}
+# mc is ignored; it's so we can put mc there to alert xgettext
+# label is the string that appears in the menu
+# type is cascade, command or radiobutton (should add checkbutton)
+# description depends on type; it's the sublist for cascade, the
+# command to invoke for command, or {variable value} for radiobutton
+proc makemenu {m items} {
+ menu $m
+ if {[tk windowingsystem] eq {aqua}} {
+ set Meta1 Cmd
+ } else {
+ set Meta1 Ctrl
+ }
+ foreach i $items {
+ set name [mc [lindex $i 1]]
+ set type [lindex $i 2]
+ set thing [lindex $i 3]
+ set params [list $type]
+ if {$name ne {}} {
+ set u [string first "&" [string map {&& x} $name]]
+ lappend params -label [string map {&& & & {}} $name]
+ if {$u >= 0} {
+ lappend params -underline $u
+ }
+ }
+ switch -- $type {
+ "cascade" {
+ set submenu [string tolower [string map {& ""} [lindex $i 1]]]
+ lappend params -menu $m.$submenu
+ }
+ "command" {
+ lappend params -command $thing
+ }
+ "radiobutton" {
+ lappend params -variable [lindex $thing 0] \
+ -value [lindex $thing 1]
+ }
+ }
+ set tail [lrange $i 4 end]
+ regsub -all {\yMeta1\y} $tail $Meta1 tail
+ eval $m add $params $tail
+ if {$type eq "cascade"} {
+ makemenu $m.$submenu $thing
+ }
+ }
+}
+
+# translate string and remove ampersands
+proc mca {str} {
+ return [string map {&& & & {}} [mc $str]]
+}
+
proc makewindow {} {
global canv canv2 canv3 linespc charspc ctext cflist cscroll
global tabstop
@@ -1767,33 +1904,34 @@ proc makewindow {} {
global rprogitem rprogcoord rownumsel numcommits
global have_tk85
- menu .bar
- .bar add cascade -label [mc "File"] -menu .bar.file
- menu .bar.file
- .bar.file add command -label [mc "Update"] -command updatecommits
- .bar.file add command -label [mc "Reload"] -command reloadcommits
- .bar.file add command -label [mc "Reread references"] -command rereadrefs
- .bar.file add command -label [mc "List references"] -command showrefs
- .bar.file add command -label [mc "Quit"] -command doquit
- menu .bar.edit
- .bar add cascade -label [mc "Edit"] -menu .bar.edit
- .bar.edit add command -label [mc "Preferences"] -command doprefs
-
- menu .bar.view
- .bar add cascade -label [mc "View"] -menu .bar.view
- .bar.view add command -label [mc "New view..."] -command {newview 0}
- .bar.view add command -label [mc "Edit view..."] -command editview \
- -state disabled
- .bar.view add command -label [mc "Delete view"] -command delview -state disabled
- .bar.view add separator
- .bar.view add radiobutton -label [mc "All files"] -command {showview 0} \
- -variable selectedview -value 0
-
- menu .bar.help
- .bar add cascade -label [mc "Help"] -menu .bar.help
- .bar.help add command -label [mc "About gitk"] -command about
- .bar.help add command -label [mc "Key bindings"] -command keys
- .bar.help configure
+ # The "mc" arguments here are purely so that xgettext
+ # sees the following string as needing to be translated
+ makemenu .bar {
+ {mc "File" cascade {
+ {mc "Update" command updatecommits -accelerator F5}
+ {mc "Reload" command reloadcommits -accelerator Meta1-F5}
+ {mc "Reread references" command rereadrefs}
+ {mc "List references" command showrefs -accelerator F2}
+ {xx "" separator}
+ {mc "Start git gui" command {exec git gui &}}
+ {xx "" separator}
+ {mc "Quit" command doquit -accelerator Meta1-Q}
+ }}
+ {mc "Edit" cascade {
+ {mc "Preferences" command doprefs}
+ }}
+ {mc "View" cascade {
+ {mc "New view..." command {newview 0} -accelerator Shift-F4}
+ {mc "Edit view..." command editview -state disabled -accelerator F4}
+ {mc "Delete view" command delview -state disabled}
+ {xx "" separator}
+ {mc "All files" radiobutton {selectedview 0} -command {showview 0}}
+ }}
+ {mc "Help" cascade {
+ {mc "About gitk" command about}
+ {mc "Key bindings" command keys}
+ }}
+ }
. configure -menu .bar
# the gui has upper and lower half, parts of a paned window.
@@ -2017,7 +2155,7 @@ proc makewindow {} {
$ctext tag conf filesep -font textfontbold -back "#aaaaaa"
$ctext tag conf hunksep -fore [lindex $diffcolors 2]
$ctext tag conf d0 -fore [lindex $diffcolors 0]
- $ctext tag conf d1 -fore [lindex $diffcolors 1]
+ $ctext tag conf dresult -fore [lindex $diffcolors 1]
$ctext tag conf m0 -fore red
$ctext tag conf m1 -fore blue
$ctext tag conf m2 -fore green
@@ -2142,11 +2280,16 @@ proc makewindow {} {
bindkey b prevfile
bindkey d "$ctext yview scroll 18 units"
bindkey u "$ctext yview scroll -18 units"
- bindkey / {dofind 1 1}
+ bindkey / {focus $fstring}
bindkey <Key-Return> {dofind 1 1}
bindkey ? {dofind -1 1}
bindkey f nextfile
- bindkey <F5> updatecommits
+ bind . <F5> updatecommits
+ bind . <$M1B-F5> reloadcommits
+ bind . <F2> showrefs
+ bind . <Shift-F4> {newview 0}
+ catch { bind . <Shift-Key-XF86_Switch_VT_4> {newview 0} }
+ bind . <F4> edit_or_newview
bind . <$M1B-q> doquit
bind . <$M1B-f> {dofind 1 1}
bind . <$M1B-g> {dofind 1 0}
@@ -2161,61 +2304,64 @@ proc makewindow {} {
bind . <Destroy> {stop_backends}
bind . <Button-1> "click %W"
bind $fstring <Key-Return> {dofind 1 1}
- bind $sha1entry <Key-Return> gotocommit
+ bind $sha1entry <Key-Return> {gotocommit; break}
bind $sha1entry <<PasteSelection>> clearsha1
bind $cflist <1> {sel_flist %W %x %y; break}
bind $cflist <B1-Motion> {sel_flist %W %x %y; break}
bind $cflist <ButtonRelease-1> {treeclick %W %x %y}
- bind $cflist <Button-3> {pop_flist_menu %W %X %Y %x %y}
+ global ctxbut
+ bind $cflist $ctxbut {pop_flist_menu %W %X %Y %x %y}
+ bind $ctext $ctxbut {pop_diff_menu %W %X %Y %x %y}
set maincursor [. cget -cursor]
set textcursor [$ctext cget -cursor]
set curtextcursor $textcursor
set rowctxmenu .rowctxmenu
- menu $rowctxmenu -tearoff 0
- $rowctxmenu add command -label [mc "Diff this -> selected"] \
- -command {diffvssel 0}
- $rowctxmenu add command -label [mc "Diff selected -> this"] \
- -command {diffvssel 1}
- $rowctxmenu add command -label [mc "Make patch"] -command mkpatch
- $rowctxmenu add command -label [mc "Create tag"] -command mktag
- $rowctxmenu add command -label [mc "Write commit to file"] -command writecommit
- $rowctxmenu add command -label [mc "Create new branch"] -command mkbranch
- $rowctxmenu add command -label [mc "Cherry-pick this commit"] \
- -command cherrypick
- $rowctxmenu add command -label [mc "Reset HEAD branch to here"] \
- -command resethead
+ makemenu $rowctxmenu {
+ {mc "Diff this -> selected" command {diffvssel 0}}
+ {mc "Diff selected -> this" command {diffvssel 1}}
+ {mc "Make patch" command mkpatch}
+ {mc "Create tag" command mktag}
+ {mc "Write commit to file" command writecommit}
+ {mc "Create new branch" command mkbranch}
+ {mc "Cherry-pick this commit" command cherrypick}
+ {mc "Reset HEAD branch to here" command resethead}
+ }
+ $rowctxmenu configure -tearoff 0
set fakerowmenu .fakerowmenu
- menu $fakerowmenu -tearoff 0
- $fakerowmenu add command -label [mc "Diff this -> selected"] \
- -command {diffvssel 0}
- $fakerowmenu add command -label [mc "Diff selected -> this"] \
- -command {diffvssel 1}
- $fakerowmenu add command -label [mc "Make patch"] -command mkpatch
-# $fakerowmenu add command -label [mc "Commit"] -command {mkcommit 0}
-# $fakerowmenu add command -label [mc "Commit all"] -command {mkcommit 1}
-# $fakerowmenu add command -label [mc "Revert local changes"] -command revertlocal
+ makemenu $fakerowmenu {
+ {mc "Diff this -> selected" command {diffvssel 0}}
+ {mc "Diff selected -> this" command {diffvssel 1}}
+ {mc "Make patch" command mkpatch}
+ }
+ $fakerowmenu configure -tearoff 0
set headctxmenu .headctxmenu
- menu $headctxmenu -tearoff 0
- $headctxmenu add command -label [mc "Check out this branch"] \
- -command cobranch
- $headctxmenu add command -label [mc "Remove this branch"] \
- -command rmbranch
+ makemenu $headctxmenu {
+ {mc "Check out this branch" command cobranch}
+ {mc "Remove this branch" command rmbranch}
+ }
+ $headctxmenu configure -tearoff 0
global flist_menu
set flist_menu .flistctxmenu
- menu $flist_menu -tearoff 0
- $flist_menu add command -label [mc "Highlight this too"] \
- -command {flist_hl 0}
- $flist_menu add command -label [mc "Highlight this only"] \
- -command {flist_hl 1}
- $flist_menu add command -label [mc "External diff"] \
- -command {external_diff}
- $flist_menu add command -label [mc "Blame parent commit"] \
- -command {external_blame 1}
+ makemenu $flist_menu {
+ {mc "Highlight this too" command {flist_hl 0}}
+ {mc "Highlight this only" command {flist_hl 1}}
+ {mc "External diff" command {external_diff}}
+ {mc "Blame parent commit" command {external_blame 1}}
+ }
+ $flist_menu configure -tearoff 0
+
+ global diff_menu
+ set diff_menu .diffctxmenu
+ makemenu $diff_menu {
+ {mc "Show origin of this line" command show_line_source}
+ {mc "Run git gui blame on this line" command {external_blame_diff}}
+ }
+ $diff_menu configure -tearoff 0
}
# Windows sends all mouse wheel events to the current focused window, not
@@ -2331,7 +2477,7 @@ proc savestuff {w} {
global viewname viewfiles viewargs viewargscmd viewperm nextviewnum
global cmitmode wrapcomment datetimeformat limitdiffs
global colors bgcolor fgcolor diffcolors diffcontext selectbgcolor
- global autoselect extdifftool
+ global autoselect extdifftool perfile_attrs markbgcolor
if {$stuffsaved} return
if {![winfo viewable .]} return
@@ -2355,9 +2501,11 @@ proc savestuff {w} {
puts $f [list set fgcolor $fgcolor]
puts $f [list set colors $colors]
puts $f [list set diffcolors $diffcolors]
+ puts $f [list set markbgcolor $markbgcolor]
puts $f [list set diffcontext $diffcontext]
puts $f [list set selectbgcolor $selectbgcolor]
puts $f [list set extdifftool $extdifftool]
+ puts $f [list set perfile_attrs $perfile_attrs]
puts $f "set geometry(main) [wm geometry .]"
puts $f "set geometry(topwidth) [winfo width .tf]"
@@ -2455,6 +2603,7 @@ proc about {} {
}
toplevel $w
wm title $w [mc "About gitk"]
+ make_transient $w .
message $w.m -text [mc "
Gitk - a commit viewer for git
@@ -2483,6 +2632,7 @@ proc keys {} {
}
toplevel $w
wm title $w [mc "Gitk key bindings"]
+ make_transient $w .
message $w.m -text "
[mc "Gitk key bindings:"]
@@ -2511,7 +2661,7 @@ proc keys {} {
[mc "<%s-F> Find" $M1T]
[mc "<%s-G> Move to next find hit" $M1T]
[mc "<Return> Move to next find hit"]
-[mc "/ Move to next find hit, or redo find"]
+[mc "/ Focus the search box"]
[mc "? Move to previous find hit"]
[mc "f Scroll diff view to next file"]
[mc "<%s-S> Search for next hit in diff view" $M1T]
@@ -2525,6 +2675,7 @@ proc keys {} {
-justify left -bg white -border 2 -relief groove
pack $w.m -side top -fill both -padx 2 -pady 2
button $w.ok -text [mc "Close"] -command "destroy $w" -default active
+ bind $w <Key-Escape> [list destroy $w]
pack $w.ok -side bottom
bind $w <Visibility> "focus $w.ok"
bind $w <Key-Escape> "destroy $w"
@@ -2705,7 +2856,7 @@ proc treeopendir {w dir} {
$w insert e:$ix $e [highlight_tag $de]
}
}
- $w mark gravity e:$ix left
+ $w mark gravity e:$ix right
$w conf -state disabled
set treediropen($dir) 1
set top [lindex [split [$w index @0,0] .] 0]
@@ -2746,9 +2897,15 @@ proc treeclick {w x y} {
}
proc setfilelist {id} {
- global treefilelist cflist
+ global treefilelist cflist jump_to_here
treeview $cflist $treefilelist($id) 0
+ if {$jump_to_here ne {}} {
+ set f [lindex $jump_to_here 0]
+ if {[lsearch -exact $treefilelist($id) $f] >= 0} {
+ showfile $f
+ }
+ }
}
image create bitmap tri-rt -background black -foreground blue -data {
@@ -2917,6 +3074,38 @@ proc pop_flist_menu {w X Y x y} {
tk_popup $flist_menu $X $Y
}
+proc find_ctext_fileinfo {line} {
+ global ctext_file_names ctext_file_lines
+
+ set ok [bsearch $ctext_file_lines $line]
+ set tline [lindex $ctext_file_lines $ok]
+
+ if {$ok >= [llength $ctext_file_lines] || $line < $tline} {
+ return {}
+ } else {
+ return [list [lindex $ctext_file_names $ok] $tline]
+ }
+}
+
+proc pop_diff_menu {w X Y x y} {
+ global ctext diff_menu flist_menu_file
+ global diff_menu_txtpos diff_menu_line
+ global diff_menu_filebase
+
+ set diff_menu_txtpos [split [$w index "@$x,$y"] "."]
+ set diff_menu_line [lindex $diff_menu_txtpos 0]
+ # don't pop up the menu on hunk-separator or file-separator lines
+ if {[lsearch -glob [$ctext tag names $diff_menu_line.0] "*sep"] >= 0} {
+ return
+ }
+ stopfinding
+ set f [find_ctext_fileinfo $diff_menu_line]
+ if {$f eq {}} return
+ set flist_menu_file [lindex $f 0]
+ set diff_menu_filebase [lindex $f 1]
+ tk_popup $diff_menu $X $Y
+}
+
proc flist_hl {only} {
global flist_menu_file findstring gdttype
@@ -2936,7 +3125,7 @@ proc save_file_from_commit {filename output what} {
if {[string match "fatal: bad revision *" $err]} {
return $nullfile
}
- error_popup "Error getting \"$filename\" from $what: $err"
+ error_popup "[mc "Error getting \"%s\" from %s:" $filename $what] $err"
return {}
}
return $output
@@ -2993,7 +3182,7 @@ proc external_diff {} {
set gitktmpdir [file join [file dirname $gitdir] \
[format ".gitk-tmp.%s" [pid]]]
if {[catch {file mkdir $gitktmpdir} err]} {
- error_popup "Error creating temporary directory $gitktmpdir: $err"
+ error_popup "[mc "Error creating temporary directory %s:" $gitktmpdir] $err"
unset gitktmpdir
return
}
@@ -3002,7 +3191,7 @@ proc external_diff {} {
incr diffnum
set diffdir [file join $gitktmpdir $diffnum]
if {[catch {file mkdir $diffdir} err]} {
- error_popup "Error creating temporary directory $diffdir: $err"
+ error_popup "[mc "Error creating temporary directory %s:" $diffdir] $err"
return
}
@@ -3015,7 +3204,7 @@ proc external_diff {} {
[list $difffromfile $difftofile]]
if {[catch {set fl [open $cmd r]} err]} {
file delete -force $diffdir
- error_popup [mc "$extdifftool: command failed: $err"]
+ error_popup "$extdifftool: [mc "command failed:"] $err"
} else {
fconfigure $fl -blocking 0
filerun $fl [list delete_at_eof $fl $diffdir]
@@ -3023,8 +3212,134 @@ proc external_diff {} {
}
}
-proc external_blame {parent_idx} {
- global flist_menu_file
+proc find_hunk_blamespec {base line} {
+ global ctext
+
+ # Find and parse the hunk header
+ set s_lix [$ctext search -backwards -regexp ^@@ "$line.0 lineend" $base.0]
+ if {$s_lix eq {}} return
+
+ set s_line [$ctext get $s_lix "$s_lix + 1 lines"]
+ if {![regexp {^@@@*(( -\d+(,\d+)?)+) \+(\d+)(,\d+)? @@} $s_line \
+ s_line old_specs osz osz1 new_line nsz]} {
+ return
+ }
+
+ # base lines for the parents
+ set base_lines [list $new_line]
+ foreach old_spec [lrange [split $old_specs " "] 1 end] {
+ if {![regexp -- {-(\d+)(,\d+)?} $old_spec \
+ old_spec old_line osz]} {
+ return
+ }
+ lappend base_lines $old_line
+ }
+
+ # Now scan the lines to determine offset within the hunk
+ set max_parent [expr {[llength $base_lines]-2}]
+ set dline 0
+ set s_lno [lindex [split $s_lix "."] 0]
+
+ # Determine if the line is removed
+ set chunk [$ctext get $line.0 "$line.1 + $max_parent chars"]
+ if {[string match {[-+ ]*} $chunk]} {
+ set removed_idx [string first "-" $chunk]
+ # Choose a parent index
+ if {$removed_idx >= 0} {
+ set parent $removed_idx
+ } else {
+ set unchanged_idx [string first " " $chunk]
+ if {$unchanged_idx >= 0} {
+ set parent $unchanged_idx
+ } else {
+ # blame the current commit
+ set parent -1
+ }
+ }
+ # then count other lines that belong to it
+ for {set i $line} {[incr i -1] > $s_lno} {} {
+ set chunk [$ctext get $i.0 "$i.1 + $max_parent chars"]
+ # Determine if the line is removed
+ set removed_idx [string first "-" $chunk]
+ if {$parent >= 0} {
+ set code [string index $chunk $parent]
+ if {$code eq "-" || ($removed_idx < 0 && $code ne "+")} {
+ incr dline
+ }
+ } else {
+ if {$removed_idx < 0} {
+ incr dline
+ }
+ }
+ }
+ incr parent
+ } else {
+ set parent 0
+ }
+
+ incr dline [lindex $base_lines $parent]
+ return [list $parent $dline]
+}
+
+proc external_blame_diff {} {
+ global currentid cmitmode
+ global diff_menu_txtpos diff_menu_line
+ global diff_menu_filebase flist_menu_file
+
+ if {$cmitmode eq "tree"} {
+ set parent_idx 0
+ set line [expr {$diff_menu_line - $diff_menu_filebase}]
+ } else {
+ set hinfo [find_hunk_blamespec $diff_menu_filebase $diff_menu_line]
+ if {$hinfo ne {}} {
+ set parent_idx [lindex $hinfo 0]
+ set line [lindex $hinfo 1]
+ } else {
+ set parent_idx 0
+ set line 0
+ }
+ }
+
+ external_blame $parent_idx $line
+}
+
+# Find the SHA1 ID of the blob for file $fname in the index
+# at stage 0 or 2
+proc index_sha1 {fname} {
+ set f [open [list | git ls-files -s $fname] r]
+ while {[gets $f line] >= 0} {
+ set info [lindex [split $line "\t"] 0]
+ set stage [lindex $info 2]
+ if {$stage eq "0" || $stage eq "2"} {
+ close $f
+ return [lindex $info 1]
+ }
+ }
+ close $f
+ return {}
+}
+
+# Turn an absolute path into one relative to the current directory
+proc make_relative {f} {
+ set elts [file split $f]
+ set here [file split [pwd]]
+ set ei 0
+ set hi 0
+ set res {}
+ foreach d $here {
+ if {$ei < $hi || $ei >= [llength $elts] || [lindex $elts $ei] ne $d} {
+ lappend res ".."
+ } else {
+ incr ei
+ }
+ incr hi
+ }
+ set elts [concat $res [lrange $elts $ei end]]
+ return [eval file join $elts]
+}
+
+proc external_blame {parent_idx {line {}}} {
+ global flist_menu_file gitdir
global nullid nullid2
global parentlist selectedline currentid
@@ -3039,17 +3354,159 @@ proc external_blame {parent_idx} {
return
}
- if {[catch {exec git gui blame $base_commit $flist_menu_file &} err]} {
- error_popup [mc "git gui blame: command failed: $err"]
+ set cmdline [list git gui blame]
+ if {$line ne {} && $line > 1} {
+ lappend cmdline "--line=$line"
+ }
+ set f [file join [file dirname $gitdir] $flist_menu_file]
+ # Unfortunately it seems git gui blame doesn't like
+ # being given an absolute path...
+ set f [make_relative $f]
+ lappend cmdline $base_commit $f
+ puts "cmdline={$cmdline}"
+ if {[catch {eval exec $cmdline &} err]} {
+ error_popup "[mc "git gui blame: command failed:"] $err"
}
}
+proc show_line_source {} {
+ global cmitmode currentid parents curview blamestuff blameinst
+ global diff_menu_line diff_menu_filebase flist_menu_file
+ global nullid nullid2 gitdir
+
+ set from_index {}
+ if {$cmitmode eq "tree"} {
+ set id $currentid
+ set line [expr {$diff_menu_line - $diff_menu_filebase}]
+ } else {
+ set h [find_hunk_blamespec $diff_menu_filebase $diff_menu_line]
+ if {$h eq {}} return
+ set pi [lindex $h 0]
+ if {$pi == 0} {
+ mark_ctext_line $diff_menu_line
+ return
+ }
+ incr pi -1
+ if {$currentid eq $nullid} {
+ if {$pi > 0} {
+ # must be a merge in progress...
+ if {[catch {
+ # get the last line from .git/MERGE_HEAD
+ set f [open [file join $gitdir MERGE_HEAD] r]
+ set id [lindex [split [read $f] "\n"] end-1]
+ close $f
+ } err]} {
+ error_popup [mc "Couldn't read merge head: %s" $err]
+ return
+ }
+ } elseif {$parents($curview,$currentid) eq $nullid2} {
+ # need to do the blame from the index
+ if {[catch {
+ set from_index [index_sha1 $flist_menu_file]
+ } err]} {
+ error_popup [mc "Error reading index: %s" $err]
+ return
+ }
+ } else {
+ set id $parents($curview,$currentid)
+ }
+ } else {
+ set id [lindex $parents($curview,$currentid) $pi]
+ }
+ set line [lindex $h 1]
+ }
+ set blameargs {}
+ if {$from_index ne {}} {
+ lappend blameargs | git cat-file blob $from_index
+ }
+ lappend blameargs | git blame -p -L$line,+1
+ if {$from_index ne {}} {
+ lappend blameargs --contents -
+ } else {
+ lappend blameargs $id
+ }
+ lappend blameargs -- [file join [file dirname $gitdir] $flist_menu_file]
+ if {[catch {
+ set f [open $blameargs r]
+ } err]} {
+ error_popup [mc "Couldn't start git blame: %s" $err]
+ return
+ }
+ nowbusy blaming [mc "Searching"]
+ fconfigure $f -blocking 0
+ set i [reg_instance $f]
+ set blamestuff($i) {}
+ set blameinst $i
+ filerun $f [list read_line_source $f $i]
+}
+
+proc stopblaming {} {
+ global blameinst
+
+ if {[info exists blameinst]} {
+ stop_instance $blameinst
+ unset blameinst
+ notbusy blaming
+ }
+}
+
+proc read_line_source {fd inst} {
+ global blamestuff curview commfd blameinst nullid nullid2
+
+ while {[gets $fd line] >= 0} {
+ lappend blamestuff($inst) $line
+ }
+ if {![eof $fd]} {
+ return 1
+ }
+ unset commfd($inst)
+ unset blameinst
+ notbusy blaming
+ fconfigure $fd -blocking 1
+ if {[catch {close $fd} err]} {
+ error_popup [mc "Error running git blame: %s" $err]
+ return 0
+ }
+
+ set fname {}
+ set line [split [lindex $blamestuff($inst) 0] " "]
+ set id [lindex $line 0]
+ set lnum [lindex $line 1]
+ if {[string length $id] == 40 && [string is xdigit $id] &&
+ [string is digit -strict $lnum]} {
+ # look for "filename" line
+ foreach l $blamestuff($inst) {
+ if {[string match "filename *" $l]} {
+ set fname [string range $l 9 end]
+ break
+ }
+ }
+ }
+ if {$fname ne {}} {
+ # all looks good, select it
+ if {$id eq $nullid} {
+ # blame uses all-zeroes to mean not committed,
+ # which would mean a change in the index
+ set id $nullid2
+ }
+ if {[commitinview $id $curview]} {
+ selectline [rowofcommit $id] 1 [list $fname $lnum]
+ } else {
+ error_popup [mc "That line comes from commit %s, \
+ which is not in this view" [shortids $id]]
+ }
+ } else {
+ puts "oops couldn't parse git blame output"
+ }
+ return 0
+}
+
# delete $dir when we see eof on $f (presumably because the child has exited)
proc delete_at_eof {f dir} {
while {[gets $f line] >= 0} {}
if {[eof $f]} {
if {[catch {close $f} err]} {
- error_popup "External diff viewer failed: $err"
+ error_popup "[mc "External diff viewer failed:"] $err"
}
file delete -force $dir
return 0
@@ -3154,8 +3611,8 @@ proc shellsplit {str} {
# Code to implement multiple views
proc newview {ishighlight} {
- global nextviewnum newviewname newviewperm newishighlight
- global newviewargs revtreeargs viewargscmd newviewargscmd curview
+ global nextviewnum newviewname newishighlight
+ global revtreeargs viewargscmd newviewopts curview
set newishighlight $ishighlight
set top .gitkview
@@ -3164,58 +3621,183 @@ proc newview {ishighlight} {
return
}
set newviewname($nextviewnum) "[mc "View"] $nextviewnum"
- set newviewperm($nextviewnum) 0
- set newviewargs($nextviewnum) [shellarglist $revtreeargs]
- set newviewargscmd($nextviewnum) $viewargscmd($curview)
+ set newviewopts($nextviewnum,perm) 0
+ set newviewopts($nextviewnum,cmd) $viewargscmd($curview)
+ decode_view_opts $nextviewnum $revtreeargs
vieweditor $top $nextviewnum [mc "Gitk view definition"]
}
+set known_view_options {
+ {perm b . {} {mc "Remember this view"}}
+ {args t50= + {} {mc "Commits to include (arguments to git log):"}}
+ {all b * "--all" {mc "Use all refs"}}
+ {dorder b . {"--date-order" "-d"} {mc "Strictly sort by date"}}
+ {lright b . "--left-right" {mc "Mark branch sides"}}
+ {since t15 + {"--since=*" "--after=*"} {mc "Since date:"}}
+ {until t15 . {"--until=*" "--before=*"} {mc "Until date:"}}
+ {limit t10 + "--max-count=*" {mc "Max count:"}}
+ {skip t10 . "--skip=*" {mc "Skip:"}}
+ {first b . "--first-parent" {mc "Limit to first parent"}}
+ {cmd t50= + {} {mc "Command to generate more commits to include:"}}
+ }
+
+proc encode_view_opts {n} {
+ global known_view_options newviewopts
+
+ set rargs [list]
+ foreach opt $known_view_options {
+ set patterns [lindex $opt 3]
+ if {$patterns eq {}} continue
+ set pattern [lindex $patterns 0]
+
+ set val $newviewopts($n,[lindex $opt 0])
+
+ if {[lindex $opt 1] eq "b"} {
+ if {$val} {
+ lappend rargs $pattern
+ }
+ } else {
+ set val [string trim $val]
+ if {$val ne {}} {
+ set pfix [string range $pattern 0 end-1]
+ lappend rargs $pfix$val
+ }
+ }
+ }
+ return [concat $rargs [shellsplit $newviewopts($n,args)]]
+}
+
+proc decode_view_opts {n view_args} {
+ global known_view_options newviewopts
+
+ foreach opt $known_view_options {
+ if {[lindex $opt 1] eq "b"} {
+ set val 0
+ } else {
+ set val {}
+ }
+ set newviewopts($n,[lindex $opt 0]) $val
+ }
+ set oargs [list]
+ foreach arg $view_args {
+ if {[regexp -- {^-([0-9]+)$} $arg arg cnt]
+ && ![info exists found(limit)]} {
+ set newviewopts($n,limit) $cnt
+ set found(limit) 1
+ continue
+ }
+ catch { unset val }
+ foreach opt $known_view_options {
+ set id [lindex $opt 0]
+ if {[info exists found($id)]} continue
+ foreach pattern [lindex $opt 3] {
+ if {![string match $pattern $arg]} continue
+ if {[lindex $opt 1] ne "b"} {
+ set size [string length $pattern]
+ set val [string range $arg [expr {$size-1}] end]
+ } else {
+ set val 1
+ }
+ set newviewopts($n,$id) $val
+ set found($id) 1
+ break
+ }
+ if {[info exists val]} break
+ }
+ if {[info exists val]} continue
+ lappend oargs $arg
+ }
+ set newviewopts($n,args) [shellarglist $oargs]
+}
+
+proc edit_or_newview {} {
+ global curview
+
+ if {$curview > 0} {
+ editview
+ } else {
+ newview 0
+ }
+}
+
proc editview {} {
global curview
- global viewname viewperm newviewname newviewperm
- global viewargs newviewargs viewargscmd newviewargscmd
+ global viewname viewperm newviewname newviewopts
+ global viewargs viewargscmd
set top .gitkvedit-$curview
if {[winfo exists $top]} {
raise $top
return
}
- set newviewname($curview) $viewname($curview)
- set newviewperm($curview) $viewperm($curview)
- set newviewargs($curview) [shellarglist $viewargs($curview)]
- set newviewargscmd($curview) $viewargscmd($curview)
+ set newviewname($curview) $viewname($curview)
+ set newviewopts($curview,perm) $viewperm($curview)
+ set newviewopts($curview,cmd) $viewargscmd($curview)
+ decode_view_opts $curview $viewargs($curview)
vieweditor $top $curview "Gitk: edit view $viewname($curview)"
}
proc vieweditor {top n title} {
- global newviewname newviewperm viewfiles bgcolor
+ global newviewname newviewopts viewfiles bgcolor
+ global known_view_options
toplevel $top
wm title $top $title
+ make_transient $top .
+
+ # View name
+ frame $top.nfr
label $top.nl -text [mc "Name"]
entry $top.name -width 20 -textvariable newviewname($n)
- grid $top.nl $top.name -sticky w -pady 5
- checkbutton $top.perm -text [mc "Remember this view"] \
- -variable newviewperm($n)
- grid $top.perm - -pady 5 -sticky w
- message $top.al -aspect 1000 \
- -text [mc "Commits to include (arguments to git log):"]
- grid $top.al - -sticky w -pady 5
- entry $top.args -width 50 -textvariable newviewargs($n) \
- -background $bgcolor
- grid $top.args - -sticky ew -padx 5
-
- message $top.ac -aspect 1000 \
- -text [mc "Command to generate more commits to include:"]
- grid $top.ac - -sticky w -pady 5
- entry $top.argscmd -width 50 -textvariable newviewargscmd($n) \
- -background white
- grid $top.argscmd - -sticky ew -padx 5
-
- message $top.l -aspect 1000 \
+ pack $top.nfr -in $top -fill x -pady 5 -padx 3
+ pack $top.nl -in $top.nfr -side left -padx {0 30}
+ pack $top.name -in $top.nfr -side left
+
+ # View options
+ set cframe $top.nfr
+ set cexpand 0
+ set cnt 0
+ foreach opt $known_view_options {
+ set id [lindex $opt 0]
+ set type [lindex $opt 1]
+ set flags [lindex $opt 2]
+ set title [eval [lindex $opt 4]]
+ set lxpad 0
+
+ if {$flags eq "+" || $flags eq "*"} {
+ set cframe $top.fr$cnt
+ incr cnt
+ frame $cframe
+ pack $cframe -in $top -fill x -pady 3 -padx 3
+ set cexpand [expr {$flags eq "*"}]
+ } else {
+ set lxpad 5
+ }
+
+ if {$type eq "b"} {
+ checkbutton $cframe.c_$id -text $title -variable newviewopts($n,$id)
+ pack $cframe.c_$id -in $cframe -side left \
+ -padx [list $lxpad 0] -expand $cexpand -anchor w
+ } elseif {[regexp {^t(\d+)$} $type type sz]} {
+ message $cframe.l_$id -aspect 1500 -text $title
+ entry $cframe.e_$id -width $sz -background $bgcolor \
+ -textvariable newviewopts($n,$id)
+ pack $cframe.l_$id -in $cframe -side left -padx [list $lxpad 0]
+ pack $cframe.e_$id -in $cframe -side left -expand 1 -fill x
+ } elseif {[regexp {^t(\d+)=$} $type type sz]} {
+ message $cframe.l_$id -aspect 1500 -text $title
+ entry $cframe.e_$id -width $sz -background $bgcolor \
+ -textvariable newviewopts($n,$id)
+ pack $cframe.l_$id -in $cframe -side top -pady [list 3 0] -anchor w
+ pack $cframe.e_$id -in $cframe -side top -fill x
+ }
+ }
+
+ # Path list
+ message $top.l -aspect 1500 \
-text [mc "Enter files and directories to include, one per line:"]
- grid $top.l - -sticky w
- text $top.t -width 40 -height 10 -background $bgcolor -font uifont
+ pack $top.l -in $top -side top -pady [list 7 0] -anchor w -padx 3
+ text $top.t -width 40 -height 5 -background $bgcolor -font uifont
if {[info exists viewfiles($n)]} {
foreach f $viewfiles($n) {
$top.t insert end $f
@@ -3224,14 +3806,19 @@ proc vieweditor {top n title} {
$top.t delete {end - 1c} end
$top.t mark set insert 0.0
}
- grid $top.t - -sticky ew -padx 5
+ pack $top.t -in $top -side top -pady [list 0 5] -fill both -expand 1 -padx 3
frame $top.buts
button $top.buts.ok -text [mc "OK"] -command [list newviewok $top $n]
+ button $top.buts.apply -text [mc "Apply (F5)"] -command [list newviewok $top $n 1]
button $top.buts.can -text [mc "Cancel"] -command [list destroy $top]
- grid $top.buts.ok $top.buts.can
+ bind $top <Control-Return> [list newviewok $top $n]
+ bind $top <F5> [list newviewok $top $n 1]
+ bind $top <Escape> [list destroy $top]
+ grid $top.buts.ok $top.buts.apply $top.buts.can
grid columnconfigure $top.buts 0 -weight 1 -uniform a
grid columnconfigure $top.buts 1 -weight 1 -uniform a
- grid $top.buts - -pady 10 -sticky ew
+ grid columnconfigure $top.buts 2 -weight 1 -uniform a
+ pack $top.buts -in $top -side top -fill x
focus $top.t
}
@@ -3252,17 +3839,15 @@ proc allviewmenus {n op args} {
# doviewmenu $viewhlmenu 1 [list addvhighlight $n] $op $args
}
-proc newviewok {top n} {
+proc newviewok {top n {apply 0}} {
global nextviewnum newviewperm newviewname newishighlight
global viewname viewfiles viewperm selectedview curview
- global viewargs newviewargs viewargscmd newviewargscmd viewhlmenu
+ global viewargs viewargscmd newviewopts viewhlmenu
if {[catch {
- set newargs [shellsplit $newviewargs($n)]
+ set newargs [encode_view_opts $n]
} err]} {
- error_popup "[mc "Error in commit selection arguments:"] $err"
- wm raise $top
- focus $top
+ error_popup "[mc "Error in commit selection arguments:"] $err" $top
return
}
set files {}
@@ -3276,10 +3861,10 @@ proc newviewok {top n} {
# creating a new view
incr nextviewnum
set viewname($n) $newviewname($n)
- set viewperm($n) $newviewperm($n)
+ set viewperm($n) $newviewopts($n,perm)
set viewfiles($n) $files
set viewargs($n) $newargs
- set viewargscmd($n) $newviewargscmd($n)
+ set viewargscmd($n) $newviewopts($n,cmd)
addviewmenu $n
if {!$newishighlight} {
run showview $n
@@ -3288,7 +3873,7 @@ proc newviewok {top n} {
}
} else {
# editing an existing view
- set viewperm($n) $newviewperm($n)
+ set viewperm($n) $newviewopts($n,perm)
if {$newviewname($n) ne $viewname($n)} {
set viewname($n) $newviewname($n)
doviewmenu .bar.view 5 [list showview $n] \
@@ -3297,15 +3882,16 @@ proc newviewok {top n} {
# entryconf [list -label $viewname($n) -value $viewname($n)]
}
if {$files ne $viewfiles($n) || $newargs ne $viewargs($n) || \
- $newviewargscmd($n) ne $viewargscmd($n)} {
+ $newviewopts($n,cmd) ne $viewargscmd($n)} {
set viewfiles($n) $files
set viewargs($n) $newargs
- set viewargscmd($n) $newviewargscmd($n)
+ set viewargscmd($n) $newviewopts($n,cmd)
if {$curview == $n} {
run reloadcommits
}
}
}
+ if {$apply} return
catch {destroy $top}
}
@@ -3374,8 +3960,8 @@ proc showview {n} {
set curview $n
set selectedview $n
- .bar.view entryconf [mc "Edit view..."] -state [expr {$n == 0? "disabled": "normal"}]
- .bar.view entryconf [mc "Delete view"] -state [expr {$n == 0? "disabled": "normal"}]
+ .bar.view entryconf [mca "Edit view..."] -state [expr {$n == 0? "disabled": "normal"}]
+ .bar.view entryconf [mca "Delete view"] -state [expr {$n == 0? "disabled": "normal"}]
run refill_reflist
if {![info exists viewcomplete($n)]} {
@@ -3456,28 +4042,31 @@ proc ishighlighted {id} {
return 0
}
-proc bolden {row font} {
- global canv linehtag selectedline boldrows
+proc bolden {id font} {
+ global canv linehtag currentid boldids need_redisplay
- lappend boldrows $row
- $canv itemconf $linehtag($row) -font $font
- if {$row == $selectedline} {
+ # need_redisplay = 1 means the display is stale and about to be redrawn
+ if {$need_redisplay} return
+ lappend boldids $id
+ $canv itemconf $linehtag($id) -font $font
+ if {[info exists currentid] && $id eq $currentid} {
$canv delete secsel
- set t [eval $canv create rect [$canv bbox $linehtag($row)] \
+ set t [eval $canv create rect [$canv bbox $linehtag($id)] \
-outline {{}} -tags secsel \
-fill [$canv cget -selectbackground]]
$canv lower $t
}
}
-proc bolden_name {row font} {
- global canv2 linentag selectedline boldnamerows
+proc bolden_name {id font} {
+ global canv2 linentag currentid boldnameids need_redisplay
- lappend boldnamerows $row
- $canv2 itemconf $linentag($row) -font $font
- if {$row == $selectedline} {
+ if {$need_redisplay} return
+ lappend boldnameids $id
+ $canv2 itemconf $linentag($id) -font $font
+ if {[info exists currentid] && $id eq $currentid} {
$canv2 delete secsel
- set t [eval $canv2 create rect [$canv2 bbox $linentag($row)] \
+ set t [eval $canv2 create rect [$canv2 bbox $linentag($id)] \
-outline {{}} -tags secsel \
-fill [$canv2 cget -selectbackground]]
$canv2 lower $t
@@ -3485,17 +4074,17 @@ proc bolden_name {row font} {
}
proc unbolden {} {
- global boldrows
+ global boldids
set stillbold {}
- foreach row $boldrows {
- if {![ishighlighted [commitonrow $row]]} {
- bolden $row mainfont
+ foreach id $boldids {
+ if {![ishighlighted $id]} {
+ bolden $id mainfont
} else {
- lappend stillbold $row
+ lappend stillbold $id
}
}
- set boldrows $stillbold
+ set boldids $stillbold
}
proc addvhighlight {n} {
@@ -3536,7 +4125,7 @@ proc vhighlightmore {} {
set row [rowofcommit $id]
if {$r0 <= $row && $row <= $r1} {
if {![highlighted $row]} {
- bolden $row mainfontbold
+ bolden $id mainfontbold
}
set vhighlights($id) 1
}
@@ -3551,7 +4140,7 @@ proc askvhighlight {row id} {
if {[commitinview $id $hlview]} {
if {[info exists iddrawn($id)] && ![ishighlighted $id]} {
- bolden $row mainfontbold
+ bolden $id mainfontbold
}
set vhighlights($id) 1
} else {
@@ -3561,7 +4150,7 @@ proc askvhighlight {row id} {
proc hfiles_change {} {
global highlight_files filehighlight fhighlights fh_serial
- global highlight_paths gdttype
+ global highlight_paths
if {[info exists filehighlight]} {
# delete previous highlights
@@ -3619,15 +4208,15 @@ proc find_change {name ix op} {
}
proc findcom_change args {
- global nhighlights boldnamerows
+ global nhighlights boldnameids
global findpattern findtype findstring gdttype
stopfinding
# delete previous highlights, if any
- foreach row $boldnamerows {
- bolden_name $row mainfont
+ foreach id $boldnameids {
+ bolden_name $id mainfont
}
- set boldnamerows {}
+ set boldnameids {}
catch {unset nhighlights}
unbolden
unmarkmatches
@@ -3716,9 +4305,8 @@ proc readfhighlight {} {
set fhl_list [lrange $fhl_list [expr {$i+1}] end]
if {$line eq {}} continue
if {![commitinview $line $curview]} continue
- set row [rowofcommit $line]
if {[info exists iddrawn($line)] && ![ishighlighted $line]} {
- bolden $row mainfontbold
+ bolden $line mainfontbold
}
set fhighlights($line) 1
}
@@ -3770,9 +4358,9 @@ proc askfindhighlight {row id} {
}
if {$isbold && [info exists iddrawn($id)]} {
if {![ishighlighted $id]} {
- bolden $row mainfontbold
+ bolden $id mainfontbold
if {$isbold > 1} {
- bolden_name $row mainfontbold
+ bolden_name $id mainfontbold
}
}
if {$markingmatches} {
@@ -3792,15 +4380,15 @@ proc markrowmatches {row id} {
if {$findloc eq [mc "All fields"] || $findloc eq [mc "Headline"]} {
set m [findmatches $headline]
if {$m ne {}} {
- markmatches $canv $row $headline $linehtag($row) $m \
- [$canv itemcget $linehtag($row) -font] $row
+ markmatches $canv $row $headline $linehtag($id) $m \
+ [$canv itemcget $linehtag($id) -font] $row
}
}
if {$findloc eq [mc "All fields"] || $findloc eq [mc "Author"]} {
set m [findmatches $author]
if {$m ne {}} {
- markmatches $canv2 $row $author $linentag($row) $m \
- [$canv2 itemcget $linentag($row) -font] $row
+ markmatches $canv2 $row $author $linentag($id) $m \
+ [$canv2 itemcget $linentag($id) -font] $row
}
}
}
@@ -3925,7 +4513,7 @@ proc askrelhighlight {row id} {
}
if {[info exists iddrawn($id)]} {
if {$isbold && ![ishighlighted $id]} {
- bolden $row mainfontbold
+ bolden $id mainfontbold
}
}
set rhighlights($id) $isbold
@@ -4079,7 +4667,7 @@ proc visiblerows {} {
proc layoutmore {} {
global commitidx viewcomplete curview
global numcommits pending_select curview
- global lastscrollset lastscrollrows commitinterest
+ global lastscrollset lastscrollrows
if {$lastscrollrows < 100 || $viewcomplete($curview) ||
[clock clicks -milliseconds] - $lastscrollset > 500} {
@@ -4093,14 +4681,56 @@ proc layoutmore {} {
drawvisible
}
+# With path limiting, we mightn't get the actual HEAD commit,
+# so ask git rev-list what is the first ancestor of HEAD that
+# touches a file in the path limit.
+proc get_viewmainhead {view} {
+ global viewmainheadid vfilelimit viewinstances mainheadid
+
+ catch {
+ set rfd [open [concat | git rev-list -1 $mainheadid \
+ -- $vfilelimit($view)] r]
+ set j [reg_instance $rfd]
+ lappend viewinstances($view) $j
+ fconfigure $rfd -blocking 0
+ filerun $rfd [list getviewhead $rfd $j $view]
+ set viewmainheadid($curview) {}
+ }
+}
+
+# git rev-list should give us just 1 line to use as viewmainheadid($view)
+proc getviewhead {fd inst view} {
+ global viewmainheadid commfd curview viewinstances showlocalchanges
+
+ set id {}
+ if {[gets $fd line] < 0} {
+ if {![eof $fd]} {
+ return 1
+ }
+ } elseif {[string length $line] == 40 && [string is xdigit $line]} {
+ set id $line
+ }
+ set viewmainheadid($view) $id
+ close $fd
+ unset commfd($inst)
+ set i [lsearch -exact $viewinstances($view) $inst]
+ if {$i >= 0} {
+ set viewinstances($view) [lreplace $viewinstances($view) $i $i]
+ }
+ if {$showlocalchanges && $id ne {} && $view == $curview} {
+ doshowlocalchanges
+ }
+ return 0
+}
+
proc doshowlocalchanges {} {
- global curview mainheadid
+ global curview viewmainheadid
- if {$mainheadid eq {}} return
- if {[commitinview $mainheadid $curview]} {
+ if {$viewmainheadid($curview) eq {}} return
+ if {[commitinview $viewmainheadid($curview) $curview]} {
dodiffindex
} else {
- lappend commitinterest($mainheadid) {dodiffindex}
+ interestedin $viewmainheadid($curview) dodiffindex
}
}
@@ -4118,19 +4748,24 @@ proc dohidelocalchanges {} {
# spawn off a process to do git diff-index --cached HEAD
proc dodiffindex {} {
- global lserial showlocalchanges
+ global lserial showlocalchanges vfilelimit curview
global isworktree
if {!$showlocalchanges || !$isworktree} return
incr lserial
- set fd [open "|git diff-index --cached HEAD" r]
+ set cmd "|git diff-index --cached HEAD"
+ if {$vfilelimit($curview) ne {}} {
+ set cmd [concat $cmd -- $vfilelimit($curview)]
+ }
+ set fd [open $cmd r]
fconfigure $fd -blocking 0
set i [reg_instance $fd]
filerun $fd [list readdiffindex $fd $lserial $i]
}
proc readdiffindex {fd serial inst} {
- global mainheadid nullid nullid2 curview commitinfo commitdata lserial
+ global viewmainheadid nullid nullid2 curview commitinfo commitdata lserial
+ global vfilelimit
set isdiff 1
if {[gets $fd line] < 0} {
@@ -4147,7 +4782,11 @@ proc readdiffindex {fd serial inst} {
}
# now see if there are any local changes not checked in to the index
- set fd [open "|git diff-files" r]
+ set cmd "|git diff-files"
+ if {$vfilelimit($curview) ne {}} {
+ set cmd [concat $cmd -- $vfilelimit($curview)]
+ }
+ set fd [open $cmd r]
fconfigure $fd -blocking 0
set i [reg_instance $fd]
filerun $fd [list readdifffiles $fd $serial $i]
@@ -4160,15 +4799,18 @@ proc readdiffindex {fd serial inst} {
if {[commitinview $nullid $curview]} {
removefakerow $nullid
}
- insertfakerow $nullid2 $mainheadid
+ insertfakerow $nullid2 $viewmainheadid($curview)
} elseif {!$isdiff && [commitinview $nullid2 $curview]} {
+ if {[commitinview $nullid $curview]} {
+ removefakerow $nullid
+ }
removefakerow $nullid2
}
return 0
}
proc readdifffiles {fd serial inst} {
- global mainheadid nullid nullid2 curview
+ global viewmainheadid nullid nullid2 curview
global commitinfo commitdata lserial
set isdiff 1
@@ -4193,7 +4835,7 @@ proc readdifffiles {fd serial inst} {
if {[commitinview $nullid2 $curview]} {
set p $nullid2
} else {
- set p $mainheadid
+ set p $viewmainheadid($curview)
}
insertfakerow $nullid $p
} elseif {!$isdiff && [commitinview $nullid $curview]} {
@@ -4918,8 +5560,8 @@ proc drawcmittext {id row col} {
global cmitlisted commitinfo rowidlist parentlist
global rowtextx idpos idtags idheads idotherrefs
global linehtag linentag linedtag selectedline
- global canvxmax boldrows boldnamerows fgcolor
- global mainheadid nullid nullid2 circleitem circlecolors
+ global canvxmax boldids boldnameids fgcolor
+ global mainheadid nullid nullid2 circleitem circlecolors ctxbut
# listed is 0 for boundary, 1 for normal, 2 for negative, 3 for left, 4 for right
set listed $cmitlisted($curview,$id)
@@ -4983,22 +5625,22 @@ proc drawcmittext {id row col} {
set nfont mainfont
set isbold [ishighlighted $id]
if {$isbold > 0} {
- lappend boldrows $row
+ lappend boldids $id
set font mainfontbold
if {$isbold > 1} {
- lappend boldnamerows $row
+ lappend boldnameids $id
set nfont mainfontbold
}
}
- set linehtag($row) [$canv create text $xt $y -anchor w -fill $fgcolor \
- -text $headline -font $font -tags text]
- $canv bind $linehtag($row) <Button-3> "rowmenu %X %Y $id"
- set linentag($row) [$canv2 create text 3 $y -anchor w -fill $fgcolor \
- -text $name -font $nfont -tags text]
- set linedtag($row) [$canv3 create text 3 $y -anchor w -fill $fgcolor \
- -text $date -font mainfont -tags text]
+ set linehtag($id) [$canv create text $xt $y -anchor w -fill $fgcolor \
+ -text $headline -font $font -tags text]
+ $canv bind $linehtag($id) $ctxbut "rowmenu %X %Y $id"
+ set linentag($id) [$canv2 create text 3 $y -anchor w -fill $fgcolor \
+ -text $name -font $nfont -tags text]
+ set linedtag($id) [$canv3 create text 3 $y -anchor w -fill $fgcolor \
+ -text $date -font mainfont -tags text]
if {$selectedline == $row} {
- make_secsel $row
+ make_secsel $id
}
set xr [expr {$xt + [font measure $font $headline]}]
if {$xr > $canvxmax} {
@@ -5206,7 +5848,7 @@ proc drawvisible {} {
proc clear_display {} {
global iddrawn linesegs need_redisplay nrows_drawn
global vhighlights fhighlights nhighlights rhighlights
- global linehtag linentag linedtag boldrows boldnamerows
+ global linehtag linentag linedtag boldids boldnameids
allcanvs delete all
catch {unset iddrawn}
@@ -5214,8 +5856,8 @@ proc clear_display {} {
catch {unset linehtag}
catch {unset linentag}
catch {unset linedtag}
- set boldrows {}
- set boldnamerows {}
+ set boldids {}
+ set boldnameids {}
catch {unset vhighlights}
catch {unset fhighlights}
catch {unset nhighlights}
@@ -5334,7 +5976,7 @@ proc bindline {t id} {
proc drawtags {id x xt y1} {
global idtags idheads idotherrefs mainhead
global linespc lthickness
- global canv rowtextx curview fgcolor bgcolor
+ global canv rowtextx curview fgcolor bgcolor ctxbut
set marks {}
set ntags 0
@@ -5412,7 +6054,7 @@ proc drawtags {id x xt y1} {
if {$ntags >= 0} {
$canv bind $t <1> [list showtag $tag 1]
} elseif {$nheads >= 0} {
- $canv bind $t <Button-3> [list headmenu %X %Y $id $tag]
+ $canv bind $t $ctxbut [list headmenu %X %Y $id $tag]
}
}
return $xt
@@ -5536,6 +6178,7 @@ proc stopfinding {} {
set fprogcoord 0
adjustprogress
}
+ stopblaming
}
proc findmore {} {
@@ -5672,10 +6315,11 @@ proc findmore {} {
proc findselectline {l} {
global findloc commentend ctext findcurline markingmatches gdttype
- set markingmatches 1
+ set markingmatches [expr {$gdttype eq [mc "containing:"]}]
set findcurline $l
selectline $l 1
- if {$findloc == [mc "All fields"] || $findloc == [mc "Comments"]} {
+ if {$markingmatches &&
+ ($findloc eq [mc "All fields"] || $findloc eq [mc "Comments"])} {
# highlight the matches in the comments
set f [$ctext get 1.0 $commentend]
set matches [findmatches $f]
@@ -5755,11 +6399,11 @@ proc commit_descriptor {p} {
# append some text to the ctext widget, and make any SHA1 ID
# that we know about be a clickable link.
proc appendwithlinks {text tags} {
- global ctext linknum curview pendinglinks
+ global ctext linknum curview
set start [$ctext index "end - 1c"]
$ctext insert end $text $tags
- set links [regexp -indices -all -inline {[0-9a-f]{40}} $text]
+ set links [regexp -indices -all -inline {\m[0-9a-f]{6,40}\M} $text]
foreach l $links {
set s [lindex $l 0]
set e [lindex $l 1]
@@ -5773,16 +6417,27 @@ proc appendwithlinks {text tags} {
}
proc setlink {id lk} {
- global curview ctext pendinglinks commitinterest
+ global curview ctext pendinglinks
- if {[commitinview $id $curview]} {
+ set known 0
+ if {[string length $id] < 40} {
+ set matches [longid $id]
+ if {[llength $matches] > 0} {
+ if {[llength $matches] > 1} return
+ set known 1
+ set id [lindex $matches 0]
+ }
+ } else {
+ set known [commitinview $id $curview]
+ }
+ if {$known} {
$ctext tag conf $lk -foreground blue -underline 1
- $ctext tag bind $lk <1> [list selectline [rowofcommit $id] 1]
+ $ctext tag bind $lk <1> [list selbyid $id]
$ctext tag bind $lk <Enter> {linkcursor %W 1}
$ctext tag bind $lk <Leave> {linkcursor %W -1}
} else {
lappend pendinglinks($id) $lk
- lappend commitinterest($id) {makelink %I}
+ interestedin $id {makelink %P}
}
}
@@ -5911,25 +6566,25 @@ proc dispnexttag {} {
}
}
-proc make_secsel {l} {
+proc make_secsel {id} {
global linehtag linentag linedtag canv canv2 canv3
- if {![info exists linehtag($l)]} return
+ if {![info exists linehtag($id)]} return
$canv delete secsel
- set t [eval $canv create rect [$canv bbox $linehtag($l)] -outline {{}} \
+ set t [eval $canv create rect [$canv bbox $linehtag($id)] -outline {{}} \
-tags secsel -fill [$canv cget -selectbackground]]
$canv lower $t
$canv2 delete secsel
- set t [eval $canv2 create rect [$canv2 bbox $linentag($l)] -outline {{}} \
+ set t [eval $canv2 create rect [$canv2 bbox $linentag($id)] -outline {{}} \
-tags secsel -fill [$canv2 cget -selectbackground]]
$canv2 lower $t
$canv3 delete secsel
- set t [eval $canv3 create rect [$canv3 bbox $linedtag($l)] -outline {{}} \
+ set t [eval $canv3 create rect [$canv3 bbox $linedtag($id)] -outline {{}} \
-tags secsel -fill [$canv3 cget -selectbackground]]
$canv3 lower $t
}
-proc selectline {l isnew} {
+proc selectline {l isnew {desired_loc {}}} {
global canv ctext commitinfo selectedline
global canvy0 linespc parents children curview
global currentid sha1entry
@@ -5937,7 +6592,7 @@ proc selectline {l isnew} {
global mergemax numcommits pending_select
global cmitmode showneartags allcommits
global targetrow targetid lastscrollrows
- global autoselect
+ global autoselect jump_to_here
catch {unset pending_select}
$canv delete hover
@@ -5990,7 +6645,7 @@ proc selectline {l isnew} {
drawvisible
}
- make_secsel $l
+ make_secsel $id
if {$isnew} {
addtohistory [list selbyid $id]
@@ -6076,6 +6731,7 @@ proc selectline {l isnew} {
$ctext conf -state disabled
set commentend [$ctext index "end - 1c"]
+ set jump_to_here $desired_loc
init_flist [mc "Comments"]
if {$cmitmode eq "tree"} {
gettree $id
@@ -6228,7 +6884,7 @@ proc gettree {id} {
set treepending $id
set treefilelist($id) {}
set treeidlist($id) {}
- fconfigure $gtf -blocking 0
+ fconfigure $gtf -blocking 0 -encoding binary
filerun $gtf [list gettreeline $gtf $id]
}
} else {
@@ -6250,11 +6906,12 @@ proc gettreeline {gtf id} {
set line [string range $line 0 [expr {$i-1}]]
if {$diffids ne $nullid2 && [lindex $line 1] ne "blob"} continue
set sha1 [lindex $line 2]
- if {[string index $fname 0] eq "\""} {
- set fname [lindex $fname 0]
- }
lappend treeidlist($id) $sha1
}
+ if {[string index $fname 0] eq "\""} {
+ set fname [lindex $fname 0]
+ }
+ set fname [encoding convertfrom $fname]
lappend treefilelist($id) $fname
}
if {![eof $gtf]} {
@@ -6276,6 +6933,7 @@ proc gettreeline {gtf id} {
proc showfile {f} {
global treefilelist treeidlist diffids nullid nullid2
+ global ctext_file_names ctext_file_lines
global ctext commentend
set i [lsearch -exact $treefilelist($diffids) $f]
@@ -6295,10 +6953,12 @@ proc showfile {f} {
return
}
}
- fconfigure $bf -blocking 0
+ fconfigure $bf -blocking 0 -encoding [get_path_encoding $f]
filerun $bf [list getblobline $bf $diffids]
$ctext config -state normal
clear_ctext $commentend
+ lappend ctext_file_names $f
+ lappend ctext_file_lines [lindex [split $commentend "."] 0]
$ctext insert end "\n"
$ctext insert end "$f\n" filesep
$ctext config -state disabled
@@ -6319,109 +6979,43 @@ proc getblobline {bf id} {
$ctext insert end "$line\n"
}
if {[eof $bf]} {
+ global jump_to_here ctext_file_names commentend
+
# delete last newline
$ctext delete "end - 2c" "end - 1c"
close $bf
+ if {$jump_to_here ne {} &&
+ [lindex $jump_to_here 0] eq [lindex $ctext_file_names 0]} {
+ set lnum [expr {[lindex $jump_to_here 1] +
+ [lindex [split $commentend .] 0]}]
+ mark_ctext_line $lnum
+ }
return 0
}
$ctext config -state disabled
return [expr {$nl >= 1000? 2: 1}]
}
+proc mark_ctext_line {lnum} {
+ global ctext markbgcolor
+
+ $ctext tag delete omark
+ $ctext tag add omark $lnum.0 "$lnum.0 + 1 line"
+ $ctext tag conf omark -background $markbgcolor
+ $ctext see $lnum.0
+}
+
proc mergediff {id} {
- global diffmergeid mdifffd
- global diffids
- global parents
- global diffcontext
- global limitdiffs vfilelimit curview
+ global diffmergeid
+ global diffids treediffs
+ global parents curview
set diffmergeid $id
set diffids $id
- # this doesn't seem to actually affect anything...
- set cmd [concat | git diff-tree --no-commit-id --cc -U$diffcontext $id]
- if {$limitdiffs && $vfilelimit($curview) ne {}} {
- set cmd [concat $cmd -- $vfilelimit($curview)]
- }
- if {[catch {set mdf [open $cmd r]} err]} {
- error_popup "[mc "Error getting merge diffs:"] $err"
- return
- }
- fconfigure $mdf -blocking 0
- set mdifffd($id) $mdf
+ set treediffs($id) {}
set np [llength $parents($curview,$id)]
settabs $np
- filerun $mdf [list getmergediffline $mdf $id $np]
-}
-
-proc getmergediffline {mdf id np} {
- global diffmergeid ctext cflist mergemax
- global difffilestart mdifffd
-
- $ctext conf -state normal
- set nr 0
- while {[incr nr] <= 1000 && [gets $mdf line] >= 0} {
- if {![info exists diffmergeid] || $id != $diffmergeid
- || $mdf != $mdifffd($id)} {
- close $mdf
- return 0
- }
- if {[regexp {^diff --cc (.*)} $line match fname]} {
- # start of a new file
- $ctext insert end "\n"
- set here [$ctext index "end - 1c"]
- lappend difffilestart $here
- add_flist [list $fname]
- set l [expr {(78 - [string length $fname]) / 2}]
- set pad [string range "----------------------------------------" 1 $l]
- $ctext insert end "$pad $fname $pad\n" filesep
- } elseif {[regexp {^@@} $line]} {
- $ctext insert end "$line\n" hunksep
- } elseif {[regexp {^[0-9a-f]{40}$} $line] || [regexp {^index} $line]} {
- # do nothing
- } else {
- # parse the prefix - one ' ', '-' or '+' for each parent
- set spaces {}
- set minuses {}
- set pluses {}
- set isbad 0
- for {set j 0} {$j < $np} {incr j} {
- set c [string range $line $j $j]
- if {$c == " "} {
- lappend spaces $j
- } elseif {$c == "-"} {
- lappend minuses $j
- } elseif {$c == "+"} {
- lappend pluses $j
- } else {
- set isbad 1
- break
- }
- }
- set tags {}
- set num {}
- if {!$isbad && $minuses ne {} && $pluses eq {}} {
- # line doesn't appear in result, parents in $minuses have the line
- set num [lindex $minuses 0]
- } elseif {!$isbad && $pluses ne {} && $minuses eq {}} {
- # line appears in result, parents in $pluses don't have the line
- lappend tags mresult
- set num [lindex $spaces 0]
- }
- if {$num ne {}} {
- if {$num >= $mergemax} {
- set num "max"
- }
- lappend tags m$num
- }
- $ctext insert end "$line\n" $tags
- }
- }
- $ctext conf -state disabled
- if {[eof $mdf]} {
- close $mdf
- return 0
- }
- return [expr {$nr >= 1000? 2: 1}]
+ getblobdiffs $id
}
proc startdiff {ids} {
@@ -6513,27 +7107,44 @@ proc gettreediffs {ids} {
set treepending $ids
set treediff {}
- fconfigure $gdtf -blocking 0
+ fconfigure $gdtf -blocking 0 -encoding binary
filerun $gdtf [list gettreediffline $gdtf $ids]
}
proc gettreediffline {gdtf ids} {
global treediff treediffs treepending diffids diffmergeid
- global cmitmode vfilelimit curview limitdiffs
+ global cmitmode vfilelimit curview limitdiffs perfile_attrs
set nr 0
- while {[incr nr] <= 1000 && [gets $gdtf line] >= 0} {
+ set sublist {}
+ set max 1000
+ if {$perfile_attrs} {
+ # cache_gitattr is slow, and even slower on win32 where we
+ # have to invoke it for only about 30 paths at a time
+ set max 500
+ if {[tk windowingsystem] == "win32"} {
+ set max 120
+ }
+ }
+ while {[incr nr] <= $max && [gets $gdtf line] >= 0} {
set i [string first "\t" $line]
if {$i >= 0} {
set file [string range $line [expr {$i+1}] end]
if {[string index $file 0] eq "\""} {
set file [lindex $file 0]
}
- lappend treediff $file
+ set file [encoding convertfrom $file]
+ if {$file ne [lindex $treediff end]} {
+ lappend treediff $file
+ lappend sublist $file
+ }
}
}
+ if {$perfile_attrs} {
+ cache_gitattr encoding $sublist
+ }
if {![eof $gdtf]} {
- return [expr {$nr >= 1000? 2: 1}]
+ return [expr {$nr >= $max? 2: 1}]
}
close $gdtf
if {$limitdiffs && $vfilelimit($curview) ne {}} {
@@ -6548,7 +7159,7 @@ proc gettreediffline {gdtf ids} {
set treediffs($ids) $treediff
}
unset treepending
- if {$cmitmode eq "tree"} {
+ if {$cmitmode eq "tree" && [llength $diffids] == 1} {
gettree $diffids
} elseif {$ids != $diffids} {
if {![info exists diffmergeid]} {
@@ -6586,8 +7197,9 @@ proc getblobdiffs {ids} {
global diffcontext
global ignorespace
global limitdiffs vfilelimit curview
+ global diffencoding targetline diffnparents
- set cmd [diffcmd $ids "-p -C --no-commit-id -U$diffcontext"]
+ set cmd [diffcmd $ids "-p -C --cc --no-commit-id -U$diffcontext"]
if {$ignorespace} {
append cmd " -w"
}
@@ -6595,11 +7207,14 @@ proc getblobdiffs {ids} {
set cmd [concat $cmd -- $vfilelimit($curview)]
}
if {[catch {set bdf [open $cmd r]} err]} {
- puts "error getting diffs: $err"
+ error_popup [mc "Error getting diffs: %s" $err]
return
}
+ set targetline {}
+ set diffnparents 0
set diffinhdr 0
- fconfigure $bdf -blocking 0
+ set diffencoding [get_path_encoding {}]
+ fconfigure $bdf -blocking 0 -encoding binary
set blobdifffd($ids) $bdf
filerun $bdf [list getblobdiffline $bdf $diffids]
}
@@ -6618,21 +7233,32 @@ proc setinlist {var i val} {
}
proc makediffhdr {fname ids} {
- global ctext curdiffstart treediffs
+ global ctext curdiffstart treediffs diffencoding
+ global ctext_file_names jump_to_here targetline diffline
+ set fname [encoding convertfrom $fname]
+ set diffencoding [get_path_encoding $fname]
set i [lsearch -exact $treediffs($ids) $fname]
if {$i >= 0} {
setinlist difffilestart $i $curdiffstart
}
+ lset ctext_file_names end $fname
set l [expr {(78 - [string length $fname]) / 2}]
set pad [string range "----------------------------------------" 1 $l]
$ctext insert $curdiffstart "$pad $fname $pad" filesep
+ set targetline {}
+ if {$jump_to_here ne {} && [lindex $jump_to_here 0] eq $fname} {
+ set targetline [lindex $jump_to_here 1]
+ }
+ set diffline 0
}
proc getblobdiffline {bdf ids} {
global diffids blobdifffd ctext curdiffstart
global diffnexthead diffnextnote difffilestart
- global diffinhdr treediffs
+ global ctext_file_names ctext_file_lines
+ global diffinhdr treediffs mergemax diffnparents
+ global diffencoding jump_to_here targetline diffline
set nr 0
$ctext conf -state normal
@@ -6641,40 +7267,74 @@ proc getblobdiffline {bdf ids} {
close $bdf
return 0
}
- if {![string compare -length 11 "diff --git " $line]} {
- # trim off "diff --git "
- set line [string range $line 11 end]
- set diffinhdr 1
+ if {![string compare -length 5 "diff " $line]} {
+ if {![regexp {^diff (--cc|--git) } $line m type]} {
+ set line [encoding convertfrom $line]
+ $ctext insert end "$line\n" hunksep
+ continue
+ }
# start of a new file
+ set diffinhdr 1
$ctext insert end "\n"
set curdiffstart [$ctext index "end - 1c"]
+ lappend ctext_file_names ""
+ lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
$ctext insert end "\n" filesep
- # If the name hasn't changed the length will be odd,
- # the middle char will be a space, and the two bits either
- # side will be a/name and b/name, or "a/name" and "b/name".
- # If the name has changed we'll get "rename from" and
- # "rename to" or "copy from" and "copy to" lines following this,
- # and we'll use them to get the filenames.
- # This complexity is necessary because spaces in the filename(s)
- # don't get escaped.
- set l [string length $line]
- set i [expr {$l / 2}]
- if {!(($l & 1) && [string index $line $i] eq " " &&
- [string range $line 2 [expr {$i - 1}]] eq \
- [string range $line [expr {$i + 3}] end])} {
- continue
- }
- # unescape if quoted and chop off the a/ from the front
- if {[string index $line 0] eq "\""} {
- set fname [string range [lindex $line 0] 2 end]
+
+ if {$type eq "--cc"} {
+ # start of a new file in a merge diff
+ set fname [string range $line 10 end]
+ if {[lsearch -exact $treediffs($ids) $fname] < 0} {
+ lappend treediffs($ids) $fname
+ add_flist [list $fname]
+ }
+
} else {
- set fname [string range $line 2 [expr {$i - 1}]]
+ set line [string range $line 11 end]
+ # If the name hasn't changed the length will be odd,
+ # the middle char will be a space, and the two bits either
+ # side will be a/name and b/name, or "a/name" and "b/name".
+ # If the name has changed we'll get "rename from" and
+ # "rename to" or "copy from" and "copy to" lines following
+ # this, and we'll use them to get the filenames.
+ # This complexity is necessary because spaces in the
+ # filename(s) don't get escaped.
+ set l [string length $line]
+ set i [expr {$l / 2}]
+ if {!(($l & 1) && [string index $line $i] eq " " &&
+ [string range $line 2 [expr {$i - 1}]] eq \
+ [string range $line [expr {$i + 3}] end])} {
+ continue
+ }
+ # unescape if quoted and chop off the a/ from the front
+ if {[string index $line 0] eq "\""} {
+ set fname [string range [lindex $line 0] 2 end]
+ } else {
+ set fname [string range $line 2 [expr {$i - 1}]]
+ }
}
makediffhdr $fname $ids
- } elseif {[regexp {^@@ -([0-9]+)(,[0-9]+)? \+([0-9]+)(,[0-9]+)? @@(.*)} \
- $line match f1l f1c f2l f2c rest]} {
+ } elseif {![string compare -length 16 "* Unmerged path " $line]} {
+ set fname [encoding convertfrom [string range $line 16 end]]
+ $ctext insert end "\n"
+ set curdiffstart [$ctext index "end - 1c"]
+ lappend ctext_file_names $fname
+ lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
+ $ctext insert end "$line\n" filesep
+ set i [lsearch -exact $treediffs($ids) $fname]
+ if {$i >= 0} {
+ setinlist difffilestart $i $curdiffstart
+ }
+
+ } elseif {![string compare -length 2 "@@" $line]} {
+ regexp {^@@+} $line ats
+ set line [encoding convertfrom $diffencoding $line]
$ctext insert end "$line\n" hunksep
+ if {[regexp { \+(\d+),\d+ @@} $line m nl]} {
+ set diffline $nl
+ }
+ set diffnparents [expr {[string length $ats] - 1}]
set diffinhdr 0
} elseif {$diffinhdr} {
@@ -6683,6 +7343,7 @@ proc getblobdiffline {bdf ids} {
if {[string index $fname 0] eq "\""} {
set fname [lindex $fname 0]
}
+ set fname [encoding convertfrom $fname]
set i [lsearch -exact $treediffs($ids) $fname]
if {$i >= 0} {
setinlist difffilestart $i $curdiffstart
@@ -6704,12 +7365,44 @@ proc getblobdiffline {bdf ids} {
$ctext insert end "$line\n" filesep
} else {
- set x [string range $line 0 0]
- if {$x == "-" || $x == "+"} {
- set tag [expr {$x == "+"}]
- $ctext insert end "$line\n" d$tag
- } elseif {$x == " "} {
- $ctext insert end "$line\n"
+ set line [encoding convertfrom $diffencoding $line]
+ # parse the prefix - one ' ', '-' or '+' for each parent
+ set prefix [string range $line 0 [expr {$diffnparents - 1}]]
+ set tag [expr {$diffnparents > 1? "m": "d"}]
+ if {[string trim $prefix " -+"] eq {}} {
+ # prefix only has " ", "-" and "+" in it: normal diff line
+ set num [string first "-" $prefix]
+ if {$num >= 0} {
+ # removed line, first parent with line is $num
+ if {$num >= $mergemax} {
+ set num "max"
+ }
+ $ctext insert end "$line\n" $tag$num
+ } else {
+ set tags {}
+ if {[string first "+" $prefix] >= 0} {
+ # added line
+ lappend tags ${tag}result
+ if {$diffnparents > 1} {
+ set num [string first " " $prefix]
+ if {$num >= 0} {
+ if {$num >= $mergemax} {
+ set num "max"
+ }
+ lappend tags m$num
+ }
+ }
+ }
+ if {$targetline ne {}} {
+ if {$diffline == $targetline} {
+ set seehere [$ctext index "end - 1 chars"]
+ set targetline {}
+ } else {
+ incr diffline
+ }
+ }
+ $ctext insert end "$line\n" $tags
+ }
} else {
# "\ No newline at end of file",
# or something else we don't recognize
@@ -6717,6 +7410,9 @@ proc getblobdiffline {bdf ids} {
}
}
}
+ if {[info exists seehere]} {
+ mark_ctext_line [lindex [split $seehere .] 0]
+ }
$ctext conf -state disabled
if {[eof $bdf]} {
close $bdf
@@ -6729,7 +7425,7 @@ proc changediffdisp {} {
global ctext diffelide
$ctext tag conf d0 -elide [lindex $diffelide 0]
- $ctext tag conf d1 -elide [lindex $diffelide 1]
+ $ctext tag conf dresult -elide [lindex $diffelide 1]
}
proc highlightfile {loc cline} {
@@ -6777,6 +7473,7 @@ proc nextfile {} {
proc clear_ctext {{first 1.0}} {
global ctext smarktop smarkbot
+ global ctext_file_names ctext_file_lines
global pendinglinks
set l [lindex [split $first .] 0]
@@ -6790,6 +7487,8 @@ proc clear_ctext {{first 1.0}} {
if {$first eq "1.0"} {
catch {unset pendinglinks}
}
+ set ctext_file_names {}
+ set ctext_file_lines {}
}
proc settabs {{firstab {}}} {
@@ -7065,13 +7764,13 @@ proc gotocommit {} {
} else {
set id [string tolower $sha1string]
if {[regexp {^[0-9a-f]{4,39}$} $id]} {
- set matches [array names varcid "$curview,$id*"]
+ set matches [longid $id]
if {$matches ne {}} {
if {[llength $matches] > 1} {
error_popup [mc "Short SHA1 id %s is ambiguous" $id]
return
}
- set id [lindex [split [lindex $matches 0] ","] 1]
+ set id [lindex $matches 0]
}
}
}
@@ -7281,16 +7980,16 @@ proc rowmenu {x y id} {
if {$id ne $nullid && $id ne $nullid2} {
set menu $rowctxmenu
if {$mainhead ne {}} {
- $menu entryconfigure 7 -label [mc "Reset %s branch to here" $mainhead]
+ $menu entryconfigure 7 -label [mc "Reset %s branch to here" $mainhead] -state normal
} else {
$menu entryconfigure 7 -label [mc "Detached head: can't reset" $mainhead] -state disabled
}
} else {
set menu $fakerowmenu
}
- $menu entryconfigure [mc "Diff this -> selected"] -state $state
- $menu entryconfigure [mc "Diff selected -> this"] -state $state
- $menu entryconfigure [mc "Make patch"] -state $state
+ $menu entryconfigure [mca "Diff this -> selected"] -state $state
+ $menu entryconfigure [mca "Diff selected -> this"] -state $state
+ $menu entryconfigure [mca "Make patch"] -state $state
tk_popup $menu $x $y
}
@@ -7344,6 +8043,7 @@ proc mkpatch {} {
set patchtop $top
catch {destroy $top}
toplevel $top
+ make_transient $top .
label $top.title -text [mc "Generate patch"]
grid $top.title - -pady 10
label $top.from -text [mc "From:"]
@@ -7374,6 +8074,8 @@ proc mkpatch {} {
frame $top.buts
button $top.buts.gen -text [mc "Generate"] -command mkpatchgo
button $top.buts.can -text [mc "Cancel"] -command mkpatchcan
+ bind $top <Key-Return> mkpatchgo
+ bind $top <Key-Escape> mkpatchcan
grid $top.buts.gen $top.buts.can
grid columnconfigure $top.buts 0 -weight 1 -uniform a
grid columnconfigure $top.buts 1 -weight 1 -uniform a
@@ -7408,7 +8110,7 @@ proc mkpatchgo {} {
set cmd [lrange $cmd 1 end]
lappend cmd >$fname &
if {[catch {eval exec $cmd} err]} {
- error_popup "[mc "Error creating patch:"] $err"
+ error_popup "[mc "Error creating patch:"] $err" $patchtop
}
catch {destroy $patchtop}
unset patchtop
@@ -7428,6 +8130,7 @@ proc mktag {} {
set mktagtop $top
catch {destroy $top}
toplevel $top
+ make_transient $top .
label $top.title -text [mc "Create tag"]
grid $top.title - -pady 10
label $top.id -text [mc "ID:"]
@@ -7445,6 +8148,8 @@ proc mktag {} {
frame $top.buts
button $top.buts.gen -text [mc "Create"] -command mktaggo
button $top.buts.can -text [mc "Cancel"] -command mktagcan
+ bind $top <Key-Return> mktaggo
+ bind $top <Key-Escape> mktagcan
grid $top.buts.gen $top.buts.can
grid columnconfigure $top.buts 0 -weight 1 -uniform a
grid columnconfigure $top.buts 1 -weight 1 -uniform a
@@ -7458,18 +8163,18 @@ proc domktag {} {
set id [$mktagtop.sha1 get]
set tag [$mktagtop.tag get]
if {$tag == {}} {
- error_popup [mc "No tag name specified"]
- return
+ error_popup [mc "No tag name specified"] $mktagtop
+ return 0
}
if {[info exists tagids($tag)]} {
- error_popup [mc "Tag \"%s\" already exists" $tag]
- return
+ error_popup [mc "Tag \"%s\" already exists" $tag] $mktagtop
+ return 0
}
if {[catch {
exec git tag $tag $id
} err]} {
- error_popup "[mc "Error creating tag:"] $err"
- return
+ error_popup "[mc "Error creating tag:"] $err" $mktagtop
+ return 0
}
set tagids($tag) $id
@@ -7478,6 +8183,7 @@ proc domktag {} {
addedtag $id
dispneartags 0
run refill_reflist
+ return 1
}
proc redrawtags {id} {
@@ -7495,16 +8201,16 @@ proc redrawtags {id} {
$canv itemconf $circleitem($row) -fill $ofill
$canv delete tag.$id
set xt [eval drawtags $id $idpos($id)]
- $canv coords $linehtag($row) $xt [lindex $idpos($id) 2]
- set text [$canv itemcget $linehtag($row) -text]
- set font [$canv itemcget $linehtag($row) -font]
+ $canv coords $linehtag($id) $xt [lindex $idpos($id) 2]
+ set text [$canv itemcget $linehtag($id) -text]
+ set font [$canv itemcget $linehtag($id) -font]
set xr [expr {$xt + [font measure $font $text]}]
if {$xr > $canvxmax} {
set canvxmax $xr
setcanvscroll
}
if {[info exists currentid] && $currentid == $id} {
- make_secsel $row
+ make_secsel $id
}
}
@@ -7516,7 +8222,7 @@ proc mktagcan {} {
}
proc mktaggo {} {
- domktag
+ if {![domktag]} return
mktagcan
}
@@ -7527,6 +8233,7 @@ proc writecommit {} {
set wrcomtop $top
catch {destroy $top}
toplevel $top
+ make_transient $top .
label $top.title -text [mc "Write commit to file"]
grid $top.title - -pady 10
label $top.id -text [mc "ID:"]
@@ -7548,6 +8255,8 @@ proc writecommit {} {
frame $top.buts
button $top.buts.gen -text [mc "Write"] -command wrcomgo
button $top.buts.can -text [mc "Cancel"] -command wrcomcan
+ bind $top <Key-Return> wrcomgo
+ bind $top <Key-Escape> wrcomcan
grid $top.buts.gen $top.buts.can
grid columnconfigure $top.buts 0 -weight 1 -uniform a
grid columnconfigure $top.buts 1 -weight 1 -uniform a
@@ -7562,7 +8271,7 @@ proc wrcomgo {} {
set cmd "echo $id | [$wrcomtop.cmd get]"
set fname [$wrcomtop.fname get]
if {[catch {exec sh -c $cmd >$fname &} err]} {
- error_popup "[mc "Error writing commit:"] $err"
+ error_popup "[mc "Error writing commit:"] $err" $wrcomtop
}
catch {destroy $wrcomtop}
unset wrcomtop
@@ -7581,6 +8290,7 @@ proc mkbranch {} {
set top .makebranch
catch {destroy $top}
toplevel $top
+ make_transient $top .
label $top.title -text [mc "Create new branch"]
grid $top.title - -pady 10
label $top.id -text [mc "ID:"]
@@ -7594,6 +8304,8 @@ proc mkbranch {} {
frame $top.buts
button $top.buts.go -text [mc "Create"] -command [list mkbrgo $top]
button $top.buts.can -text [mc "Cancel"] -command "catch {destroy $top}"
+ bind $top <Key-Return> [list mkbrgo $top]
+ bind $top <Key-Escape> "catch {destroy $top}"
grid $top.buts.go $top.buts.can
grid columnconfigure $top.buts 0 -weight 1 -uniform a
grid columnconfigure $top.buts 1 -weight 1 -uniform a
@@ -7606,29 +8318,73 @@ proc mkbrgo {top} {
set name [$top.name get]
set id [$top.sha1 get]
+ set cmdargs {}
+ set old_id {}
if {$name eq {}} {
- error_popup [mc "Please specify a name for the new branch"]
+ error_popup [mc "Please specify a name for the new branch"] $top
return
}
+ if {[info exists headids($name)]} {
+ if {![confirm_popup [mc \
+ "Branch '%s' already exists. Overwrite?" $name] $top]} {
+ return
+ }
+ set old_id $headids($name)
+ lappend cmdargs -f
+ }
catch {destroy $top}
+ lappend cmdargs $name $id
nowbusy newbranch
update
if {[catch {
- exec git branch $name $id
+ eval exec git branch $cmdargs
} err]} {
notbusy newbranch
error_popup $err
} else {
- set headids($name) $id
- lappend idheads($id) $name
- addedhead $id $name
notbusy newbranch
- redrawtags $id
+ if {$old_id ne {}} {
+ movehead $id $name
+ movedhead $id $name
+ redrawtags $old_id
+ redrawtags $id
+ } else {
+ set headids($name) $id
+ lappend idheads($id) $name
+ addedhead $id $name
+ redrawtags $id
+ }
dispneartags 0
run refill_reflist
}
}
+proc exec_citool {tool_args {baseid {}}} {
+ global commitinfo env
+
+ set save_env [array get env GIT_AUTHOR_*]
+
+ if {$baseid ne {}} {
+ if {![info exists commitinfo($baseid)]} {
+ getcommit $baseid
+ }
+ set author [lindex $commitinfo($baseid) 1]
+ set date [lindex $commitinfo($baseid) 2]
+ if {[regexp {^\s*(\S.*\S|\S)\s*<(.*)>\s*$} \
+ $author author name email]
+ && $date ne {}} {
+ set env(GIT_AUTHOR_NAME) $name
+ set env(GIT_AUTHOR_EMAIL) $email
+ set env(GIT_AUTHOR_DATE) $date
+ }
+ }
+
+ eval exec git citool $tool_args &
+
+ array unset env GIT_AUTHOR_*
+ array set env $save_env
+}
+
proc cherrypick {} {
global rowmenuid curview
global mainhead mainheadid
@@ -7647,7 +8403,26 @@ proc cherrypick {} {
# no error occurs, and exec takes that as an indication of error...
if {[catch {exec sh -c "git cherry-pick -r $rowmenuid 2>&1"} err]} {
notbusy cherrypick
- error_popup $err
+ if {[regexp -line \
+ {Entry '(.*)' (would be overwritten by merge|not uptodate)} \
+ $err msg fname]} {
+ error_popup [mc "Cherry-pick failed because of local changes\
+ to file '%s'.\nPlease commit, reset or stash\
+ your changes and try again." $fname]
+ } elseif {[regexp -line \
+ {^(CONFLICT \(.*\):|Automatic cherry-pick failed)} \
+ $err]} {
+ if {[confirm_popup [mc "Cherry-pick failed because of merge\
+ conflict.\nDo you wish to run git citool to\
+ resolve it?"]]} {
+ # Force citool to read MERGE_MSG
+ file delete [file join [gitdir] "GITGUI_MSG"]
+ exec_citool {} $rowmenuid
+ }
+ } else {
+ error_popup $err
+ }
+ run updatecommits
return
}
set newhead [exec git rev-parse HEAD]
@@ -7658,6 +8433,7 @@ proc cherrypick {} {
}
addnewchild $newhead $oldhead
if {[commitinview $oldhead $curview]} {
+ # XXX this isn't right if we have a path limit...
insertrow $newhead $oldhead $curview
if {$mainhead ne {}} {
movehead $newhead $mainhead
@@ -7677,7 +8453,7 @@ proc resethead {} {
set confirm_ok 0
set w ".confirmreset"
toplevel $w
- wm transient $w .
+ make_transient $w .
wm title $w [mc "Confirm reset"]
message $w.m -text \
[mc "Reset branch %s to %s?" $mainhead [string range $rowmenuid 0 7]] \
@@ -7700,6 +8476,7 @@ proc resethead {} {
button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
pack $w.ok -side left -fill x -padx 20 -pady 20
button $w.cancel -text [mc Cancel] -command "destroy $w"
+ bind $w <Key-Escape> [list destroy $w]
pack $w.cancel -side right -fill x -padx 20 -pady 20
bind $w <Visibility> "grab $w; focus $w"
tkwait window $w
@@ -7764,7 +8541,7 @@ proc headmenu {x y id head} {
proc cobranch {} {
global headmenuid headmenuhead headids
- global showlocalchanges mainheadid
+ global showlocalchanges
# check the tree is clean first??
nowbusy checkout [mc "Checking out"]
@@ -7785,6 +8562,7 @@ proc cobranch {} {
proc readcheckoutstat {fd newhead newheadid} {
global mainhead mainheadid headids showlocalchanges progresscoords
+ global viewmainheadid curview
if {[gets $fd line] >= 0} {
if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
@@ -7802,6 +8580,7 @@ proc readcheckoutstat {fd newhead newheadid} {
set oldmainid $mainheadid
set mainhead $newhead
set mainheadid $newheadid
+ set viewmainheadid($curview) $newheadid
redrawtags $oldmainid
redrawtags $newheadid
selbyid $newheadid
@@ -7856,6 +8635,7 @@ proc showrefs {} {
}
toplevel $top
wm title $top [mc "Tags and heads: %s" [file tail [pwd]]]
+ make_transient $top .
text $top.list -background $bgcolor -foreground $fgcolor \
-selectbackground $selectbgcolor -font mainfont \
-xscrollcommand "$top.xsb set" -yscrollcommand "$top.ysb set" \
@@ -7877,6 +8657,7 @@ proc showrefs {} {
pack $top.f.l -side left
grid $top.f - -sticky ew -pady 2
button $top.close -command [list destroy $top] -text [mc "Close"]
+ bind $top <Key-Escape> [list destroy $top]
grid $top.close -
grid columnconfigure $top 0 -weight 1
grid rowconfigure $top 0 -weight 1
@@ -7918,7 +8699,7 @@ proc reflistfilter_change {n1 n2 op} {
proc refill_reflist {} {
global reflist reflistfilter showrefstop headids tagids otherrefids
- global curview commitinterest
+ global curview
if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
set refs {}
@@ -7927,7 +8708,7 @@ proc refill_reflist {} {
if {[commitinview $headids($n) $curview]} {
lappend refs [list $n H]
} else {
- set commitinterest($headids($n)) {run refill_reflist}
+ interestedin $headids($n) {run refill_reflist}
}
}
}
@@ -7936,7 +8717,7 @@ proc refill_reflist {} {
if {[commitinview $tagids($n) $curview]} {
lappend refs [list $n T]
} else {
- set commitinterest($tagids($n)) {run refill_reflist}
+ interestedin $tagids($n) {run refill_reflist}
}
}
}
@@ -7945,7 +8726,7 @@ proc refill_reflist {} {
if {[commitinview $otherrefids($n) $curview]} {
lappend refs [list $n o]
} else {
- set commitinterest($otherrefids($n)) {run refill_reflist}
+ interestedin $otherrefids($n) {run refill_reflist}
}
}
}
@@ -9182,6 +9963,7 @@ proc mkfontdisp {font top which} {
proc choosefont {font which} {
global fontparam fontlist fonttop fontattr
+ global prefstop
set fontparam(which) $which
set fontparam(font) $font
@@ -9195,6 +9977,7 @@ proc choosefont {font which} {
font create sample
eval font config sample [font actual $font]
toplevel $top
+ make_transient $top $prefstop
wm title $top [mc "Gitk font chooser"]
label $top.l -textvariable fontparam(which)
pack $top.l -side top
@@ -9228,6 +10011,8 @@ proc choosefont {font which} {
frame $top.buts
button $top.buts.ok -text [mc "OK"] -command fontok -default active
button $top.buts.can -text [mc "Cancel"] -command fontcan -default normal
+ bind $top <Key-Return> fontok
+ bind $top <Key-Escape> fontcan
grid $top.buts.ok $top.buts.can
grid columnconfigure $top.buts 0 -weight 1 -uniform a
grid columnconfigure $top.buts 1 -weight 1 -uniform a
@@ -9294,8 +10079,8 @@ proc chg_fontparam {v sub op} {
proc doprefs {} {
global maxwidth maxgraphpct
global oldprefs prefstop showneartags showlocalchanges
- global bgcolor fgcolor ctext diffcolors selectbgcolor
- global tabstop limitdiffs autoselect extdifftool
+ global bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
+ global tabstop limitdiffs autoselect extdifftool perfile_attrs
set top .gitkprefs
set prefstop $top
@@ -9304,11 +10089,12 @@ proc doprefs {} {
return
}
foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
- limitdiffs tabstop} {
+ limitdiffs tabstop perfile_attrs} {
set oldprefs($v) [set $v]
}
toplevel $top
wm title $top [mc "Gitk preferences"]
+ make_transient $top .
label $top.ldisp -text [mc "Commit list display options"]
grid $top.ldisp - -sticky w -pady 10
label $top.spacer -text " "
@@ -9320,15 +10106,11 @@ proc doprefs {} {
-font optionfont
spinbox $top.maxpct -from 1 -to 100 -width 4 -textvariable maxgraphpct
grid x $top.maxpctl $top.maxpct -sticky w
- frame $top.showlocal
- label $top.showlocal.l -text [mc "Show local changes"] -font optionfont
- checkbutton $top.showlocal.b -variable showlocalchanges
- pack $top.showlocal.b $top.showlocal.l -side left
+ checkbutton $top.showlocal -text [mc "Show local changes"] \
+ -font optionfont -variable showlocalchanges
grid x $top.showlocal -sticky w
- frame $top.autoselect
- label $top.autoselect.l -text [mc "Auto-select SHA1"] -font optionfont
- checkbutton $top.autoselect.b -variable autoselect
- pack $top.autoselect.b $top.autoselect.l -side left
+ checkbutton $top.autoselect -text [mc "Auto-select SHA1"] \
+ -font optionfont -variable autoselect
grid x $top.autoselect -sticky w
label $top.ddisp -text [mc "Diff display options"]
@@ -9336,16 +10118,15 @@ proc doprefs {} {
label $top.tabstopl -text [mc "Tab spacing"] -font optionfont
spinbox $top.tabstop -from 1 -to 20 -width 4 -textvariable tabstop
grid x $top.tabstopl $top.tabstop -sticky w
- frame $top.ntag
- label $top.ntag.l -text [mc "Display nearby tags"] -font optionfont
- checkbutton $top.ntag.b -variable showneartags
- pack $top.ntag.b $top.ntag.l -side left
+ checkbutton $top.ntag -text [mc "Display nearby tags"] \
+ -font optionfont -variable showneartags
grid x $top.ntag -sticky w
- frame $top.ldiff
- label $top.ldiff.l -text [mc "Limit diffs to listed paths"] -font optionfont
- checkbutton $top.ldiff.b -variable limitdiffs
- pack $top.ldiff.b $top.ldiff.l -side left
+ checkbutton $top.ldiff -text [mc "Limit diffs to listed paths"] \
+ -font optionfont -variable limitdiffs
grid x $top.ldiff -sticky w
+ checkbutton $top.lattr -text [mc "Support per-file encodings"] \
+ -font optionfont -variable perfile_attrs
+ grid x $top.lattr -sticky w
entry $top.extdifft -textvariable extdifftool
frame $top.extdifff
@@ -9360,31 +10141,37 @@ proc doprefs {} {
grid $top.cdisp - -sticky w -pady 10
label $top.bg -padx 40 -relief sunk -background $bgcolor
button $top.bgbut -text [mc "Background"] -font optionfont \
- -command [list choosecolor bgcolor {} $top.bg background setbg]
+ -command [list choosecolor bgcolor {} $top.bg [mc "background"] setbg]
grid x $top.bgbut $top.bg -sticky w
label $top.fg -padx 40 -relief sunk -background $fgcolor
button $top.fgbut -text [mc "Foreground"] -font optionfont \
- -command [list choosecolor fgcolor {} $top.fg foreground setfg]
+ -command [list choosecolor fgcolor {} $top.fg [mc "foreground"] setfg]
grid x $top.fgbut $top.fg -sticky w
label $top.diffold -padx 40 -relief sunk -background [lindex $diffcolors 0]
button $top.diffoldbut -text [mc "Diff: old lines"] -font optionfont \
- -command [list choosecolor diffcolors 0 $top.diffold "diff old lines" \
+ -command [list choosecolor diffcolors 0 $top.diffold [mc "diff old lines"] \
[list $ctext tag conf d0 -foreground]]
grid x $top.diffoldbut $top.diffold -sticky w
label $top.diffnew -padx 40 -relief sunk -background [lindex $diffcolors 1]
button $top.diffnewbut -text [mc "Diff: new lines"] -font optionfont \
- -command [list choosecolor diffcolors 1 $top.diffnew "diff new lines" \
- [list $ctext tag conf d1 -foreground]]
+ -command [list choosecolor diffcolors 1 $top.diffnew [mc "diff new lines"] \
+ [list $ctext tag conf dresult -foreground]]
grid x $top.diffnewbut $top.diffnew -sticky w
label $top.hunksep -padx 40 -relief sunk -background [lindex $diffcolors 2]
button $top.hunksepbut -text [mc "Diff: hunk header"] -font optionfont \
-command [list choosecolor diffcolors 2 $top.hunksep \
- "diff hunk header" \
+ [mc "diff hunk header"] \
[list $ctext tag conf hunksep -foreground]]
grid x $top.hunksepbut $top.hunksep -sticky w
+ label $top.markbgsep -padx 40 -relief sunk -background $markbgcolor
+ button $top.markbgbut -text [mc "Marked line bg"] -font optionfont \
+ -command [list choosecolor markbgcolor {} $top.markbgsep \
+ [mc "marked line background"] \
+ [list $ctext tag conf omark -background]]
+ grid x $top.markbgbut $top.markbgsep -sticky w
label $top.selbgsep -padx 40 -relief sunk -background $selectbgcolor
button $top.selbgbut -text [mc "Select bg"] -font optionfont \
- -command [list choosecolor selectbgcolor {} $top.selbgsep background setselbg]
+ -command [list choosecolor selectbgcolor {} $top.selbgsep [mc "background"] setselbg]
grid x $top.selbgbut $top.selbgsep -sticky w
label $top.cfont -text [mc "Fonts: press to choose"]
@@ -9396,6 +10183,8 @@ proc doprefs {} {
frame $top.buts
button $top.buts.ok -text [mc "OK"] -command prefsok -default active
button $top.buts.can -text [mc "Cancel"] -command prefscan -default normal
+ bind $top <Key-Return> prefsok
+ bind $top <Key-Escape> prefscan
grid $top.buts.ok $top.buts.can
grid columnconfigure $top.buts 0 -weight 1 -uniform a
grid columnconfigure $top.buts 1 -weight 1 -uniform a
@@ -9455,7 +10244,7 @@ proc prefscan {} {
global oldprefs prefstop
foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
- limitdiffs tabstop} {
+ limitdiffs tabstop perfile_attrs} {
global $v
set $v $oldprefs($v)
}
@@ -9468,7 +10257,7 @@ proc prefsok {} {
global maxwidth maxgraphpct
global oldprefs prefstop showneartags showlocalchanges
global fontpref mainfont textfont uifont
- global limitdiffs treediffs
+ global limitdiffs treediffs perfile_attrs
catch {destroy $prefstop}
unset prefstop
@@ -9501,8 +10290,10 @@ proc prefsok {} {
dohidelocalchanges
}
}
- if {$limitdiffs != $oldprefs(limitdiffs)} {
- # treediffs elements are limited by path
+ if {$limitdiffs != $oldprefs(limitdiffs) ||
+ ($perfile_attrs && !$oldprefs(perfile_attrs))} {
+ # treediffs elements are limited by path;
+ # won't have encodings cached if perfile_attrs was just turned on
catch {unset treediffs}
}
if {$fontchanged || $maxwidth != $oldprefs(maxwidth)
@@ -9726,7 +10517,7 @@ set encoding_aliases {
{ ISO-8859-16 iso-ir-226 ISO_8859-16:2001 ISO_8859-16 latin10 l10 }
{ GBK CP936 MS936 windows-936 }
{ JIS_Encoding csJISEncoding }
- { Shift_JIS MS_Kanji csShiftJIS }
+ { Shift_JIS MS_Kanji csShiftJIS ShiftJIS Shift-JIS }
{ Extended_UNIX_Code_Packed_Format_for_Japanese csEUCPkdFmtJapanese
EUC-JP }
{ Extended_UNIX_Code_Fixed_Width_for_Japanese csEUCFixWidJapanese }
@@ -9761,14 +10552,17 @@ set encoding_aliases {
}
proc tcl_encoding {enc} {
- global encoding_aliases
+ global encoding_aliases tcl_encoding_cache
+ if {[info exists tcl_encoding_cache($enc)]} {
+ return $tcl_encoding_cache($enc)
+ }
set names [encoding names]
set lcnames [string tolower $names]
set enc [string tolower $enc]
set i [lsearch -exact $lcnames $enc]
if {$i < 0} {
# look for "isonnn" instead of "iso-nnn" or "iso_nnn"
- if {[regsub {^iso[-_]} $enc iso encx]} {
+ if {[regsub {^(iso|cp|ibm|jis)[-_]} $enc {\1} encx]} {
set i [lsearch -exact $lcnames $encx]
}
}
@@ -9780,7 +10574,7 @@ proc tcl_encoding {enc} {
foreach e $ll {
set i [lsearch -exact $lcnames $e]
if {$i < 0} {
- if {[regsub {^iso[-_]} $e iso ex]} {
+ if {[regsub {^(iso|cp|ibm|jis)[-_]} $e {\1} ex]} {
set i [lsearch -exact $lcnames $ex]
}
}
@@ -9789,10 +10583,70 @@ proc tcl_encoding {enc} {
break
}
}
+ set tclenc {}
if {$i >= 0} {
- return [lindex $names $i]
+ set tclenc [lindex $names $i]
}
- return {}
+ set tcl_encoding_cache($enc) $tclenc
+ return $tclenc
+}
+
+proc gitattr {path attr default} {
+ global path_attr_cache
+ if {[info exists path_attr_cache($attr,$path)]} {
+ set r $path_attr_cache($attr,$path)
+ } else {
+ set r "unspecified"
+ if {![catch {set line [exec git check-attr $attr -- $path]}]} {
+ regexp "(.*): encoding: (.*)" $line m f r
+ }
+ set path_attr_cache($attr,$path) $r
+ }
+ if {$r eq "unspecified"} {
+ return $default
+ }
+ return $r
+}
+
+proc cache_gitattr {attr pathlist} {
+ global path_attr_cache
+ set newlist {}
+ foreach path $pathlist {
+ if {![info exists path_attr_cache($attr,$path)]} {
+ lappend newlist $path
+ }
+ }
+ set lim 1000
+ if {[tk windowingsystem] == "win32"} {
+ # windows has a 32k limit on the arguments to a command...
+ set lim 30
+ }
+ while {$newlist ne {}} {
+ set head [lrange $newlist 0 [expr {$lim - 1}]]
+ set newlist [lrange $newlist $lim end]
+ if {![catch {set rlist [eval exec git check-attr $attr -- $head]}]} {
+ foreach row [split $rlist "\n"] {
+ if {[regexp "(.*): encoding: (.*)" $row m path value]} {
+ if {[string index $path 0] eq "\""} {
+ set path [encoding convertfrom [lindex $path 0]]
+ }
+ set path_attr_cache($attr,$path) $value
+ }
+ }
+ }
+ }
+}
+
+proc get_path_encoding {path} {
+ global gui_encoding perfile_attrs
+ set tcl_enc $gui_encoding
+ if {$path ne {} && $perfile_attrs} {
+ set enc2 [tcl_encoding [gitattr $path encoding $tcl_enc]]
+ if {$enc2 ne {}} {
+ set tcl_enc $enc2
+ }
+ }
+ return $tcl_enc
}
# First check that Tcl/Tk is recent enough
@@ -9809,6 +10663,9 @@ set gitencoding {}
catch {
set gitencoding [exec git config --get i18n.commitencoding]
}
+catch {
+ set gitencoding [exec git config --get i18n.logoutputencoding]
+}
if {$gitencoding == ""} {
set gitencoding "utf-8"
}
@@ -9817,6 +10674,19 @@ if {$tclencoding == {}} {
puts stderr "Warning: encoding $gitencoding is not supported by Tcl/Tk"
}
+set gui_encoding [encoding system]
+catch {
+ set enc [exec git config --get gui.encoding]
+ if {$enc ne {}} {
+ set tclenc [tcl_encoding $enc]
+ if {$tclenc ne {}} {
+ set gui_encoding $tclenc
+ } else {
+ puts stderr "Warning: encoding $enc is not supported by Tcl/Tk"
+ }
+ }
+}
+
set mainfont {Helvetica 9}
set textfont {Courier 9}
set uifont {Helvetica 9 bold}
@@ -9838,6 +10708,7 @@ set showlocalchanges 1
set limitdiffs 1
set datetimeformat "%Y-%m-%d %H:%M:%S"
set autoselect 1
+set perfile_attrs 0
set extdifftool "meld"
@@ -9848,9 +10719,17 @@ set diffcolors {red "#00a000" blue}
set diffcontext 3
set ignorespace 0
set selectbgcolor gray85
+set markbgcolor "#e0e0ff"
set circlecolors {white blue gray blue blue}
+# button for popping up context menus
+if {[tk windowingsystem] eq "aqua"} {
+ set ctxbut <Button-2>
+} else {
+ set ctxbut <Button-3>
+}
+
## For msgcat loading, first locate the installation location.
if { [info exists ::env(GITK_MSGSDIR)] } {
## Msgsdir was manually set in the environment.
@@ -9971,8 +10850,8 @@ set nhl_names {}
set highlight_paths {}
set findpattern {}
set searchdirn -forwards
-set boldrows {}
-set boldnamerows {}
+set boldids {}
+set boldnameids {}
set diffelide {0 0}
set markingmatches 0
set linkentercount 0
@@ -10019,8 +10898,8 @@ if {$cmdline_files ne {} || $revtreeargs ne {} || $revtreeargscmd ne {}} {
set viewperm(1) 0
set vdatemode(1) 0
addviewmenu 1
- .bar.view entryconf [mc "Edit view..."] -state normal
- .bar.view entryconf [mc "Delete view"] -state normal
+ .bar.view entryconf [mca "Edit view..."] -state normal
+ .bar.view entryconf [mca "Delete view"] -state normal
}
if {[info exists permviews]} {
@@ -10035,4 +10914,9 @@ if {[info exists permviews]} {
addviewmenu $n
}
}
+
+if {[tk windowingsystem] eq "win32"} {
+ focus -force .
+}
+
getcommits {}
diff --git a/gitk-git/po/de.po b/gitk-git/po/de.po
index 04ee570995..825dc98f74 100644
--- a/gitk-git/po/de.po
+++ b/gitk-git/po/de.po
@@ -7,25 +7,33 @@ msgid ""
msgstr ""
"Project-Id-Version: git-gui\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-05-24 22:32+0200\n"
-"PO-Revision-Date: 2008-05-24 22:40+0200\n"
+"POT-Creation-Date: 2008-12-06 20:40+0100\n"
+"PO-Revision-Date: 2008-12-06 20:45+0100\n"
"Last-Translator: Christian Stimming <stimming@tuhh.de>\n"
"Language-Team: German\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: gitk:102
+#: gitk:113
msgid "Couldn't get list of unmerged files:"
msgstr "Liste der nicht-zusammengeführten Dateien nicht gefunden:"
-#: gitk:329
+#: gitk:272
+msgid "Error parsing revisions:"
+msgstr "Fehler beim Laden der Versionen:"
+
+#: gitk:327
+msgid "Error executing --argscmd command:"
+msgstr "Fehler beim --argscmd Kommando:"
+
+#: gitk:340
msgid "No files selected: --merge specified but no files are unmerged."
msgstr ""
"Keine Dateien ausgewählt: --merge angegeben, es existieren aber keine nicht-"
"zusammengeführten Dateien."
-#: gitk:332
+#: gitk:343
msgid ""
"No files selected: --merge specified but no unmerged files are within file "
"limit."
@@ -33,257 +41,273 @@ msgstr ""
"Keine Dateien ausgewähle: --merge angegeben, aber keine nicht-"
"zusammengeführten Dateien sind in der Dateiauswahl."
-#: gitk:354
+#: gitk:365 gitk:503
msgid "Error executing git log:"
msgstr "Fehler beim Ausführen von git-log:"
-#: gitk:369
+#: gitk:378
msgid "Reading"
msgstr "Lesen"
-#: gitk:151 gitk:2191
+#: gitk:438 gitk:3462
msgid "Reading commits..."
msgstr "Versionen lesen..."
-#: gitk:275
-msgid "Can't parse git log output:"
-msgstr "Ausgabe von git-log kann nicht erkannt werden:"
-
-#: gitk:386 gitk:2195
+#: gitk:441 gitk:1528 gitk:3465
msgid "No commits selected"
msgstr "Keine Versionen ausgewählt."
-#: gitk:500
+#: gitk:1399
+msgid "Can't parse git log output:"
+msgstr "Ausgabe von git-log kann nicht erkannt werden:"
+
+#: gitk:1605
msgid "No commit information available"
msgstr "Keine Versionsinformation verfügbar"
-#: gitk:599 gitk:621 gitk:1955 gitk:6424 gitk:7924 gitk:8083
+#: gitk:1709 gitk:1731 gitk:3259 gitk:7764 gitk:9293 gitk:9466
msgid "OK"
msgstr "Ok"
-#: gitk:623 gitk:1956 gitk:6108 gitk:6179 gitk:6276 gitk:6322 gitk:6426
-#: gitk:7925 gitk:8084
+#: gitk:1733 gitk:3260 gitk:7439 gitk:7510 gitk:7613 gitk:7660 gitk:7766
+#: gitk:9294 gitk:9467
msgid "Cancel"
msgstr "Abbrechen"
-#: gitk:661
-msgid "File"
-msgstr "Datei"
-
-#: gitk:663
+#: gitk:1811
msgid "Update"
msgstr "Aktualisieren"
-#: gitk:1722
+#: gitk:1812
msgid "Reload"
msgstr "Neu laden"
-#: gitk:1723
+#: gitk:1813
msgid "Reread references"
msgstr "Zweige neu laden"
-#: gitk:665
+#: gitk:1814
msgid "List references"
msgstr "Zweige/Markierungen auflisten"
-#: gitk:666
+#: gitk:1915
+msgid "Start git gui"
+msgstr "»git gui« starten"
+
+#: gitk:1917
msgid "Quit"
msgstr "Beenden"
-#: gitk:668
-msgid "Edit"
-msgstr "Bearbeiten"
+#: gitk:1810
+msgid "File"
+msgstr "Datei"
-#: gitk:669
+#: gitk:1818
msgid "Preferences"
msgstr "Einstellungen"
-#: gitk:672 gitk:1892
-msgid "View"
-msgstr "Ansicht"
+#: gitk:1817
+msgid "Edit"
+msgstr "Bearbeiten"
-#: gitk:673
+#: gitk:1821
msgid "New view..."
msgstr "Neue Ansicht..."
-#: gitk:674 gitk:2133 gitk:8723
+#: gitk:1822
msgid "Edit view..."
msgstr "Ansicht bearbeiten..."
-#: gitk:676 gitk:2134 gitk:8724
+#: gitk:1823
msgid "Delete view"
msgstr "Ansicht löschen"
-#: gitk:678
+#: gitk:1825
msgid "All files"
msgstr "Alle Dateien"
-#: gitk:682
-msgid "Help"
-msgstr "Hilfe"
+#: gitk:1820 gitk:3196
+msgid "View"
+msgstr "Ansicht"
-#: gitk:683 gitk:1317
+#: gitk:1828 gitk:2487
msgid "About gitk"
msgstr "Ãœber gitk"
-#: gitk:684
+#: gitk:1829
msgid "Key bindings"
msgstr "Tastenkürzel"
-#: gitk:741
+#: gitk:1827
+msgid "Help"
+msgstr "Hilfe"
+
+#: gitk:1887
msgid "SHA1 ID: "
msgstr "SHA1:"
-#: gitk:1831
+#: gitk:1918
msgid "Row"
msgstr "Zeile"
-#: gitk:1862
+#: gitk:1949
msgid "Find"
msgstr "Suche"
-#: gitk:792
+#: gitk:1950
msgid "next"
msgstr "nächste"
-#: gitk:793
+#: gitk:1951
msgid "prev"
msgstr "vorige"
-#: gitk:794
+#: gitk:1952
msgid "commit"
msgstr "Version nach"
-#: gitk:797 gitk:799 gitk:2356 gitk:2379 gitk:2403 gitk:4306 gitk:4369
+#: gitk:1955 gitk:1957 gitk:3617 gitk:3640 gitk:3664 gitk:5550 gitk:5621
msgid "containing:"
msgstr "Beschreibung:"
-#: gitk:800 gitk:1778 gitk:1783 gitk:2431
+#: gitk:1958 gitk:2954 gitk:2959 gitk:3692
msgid "touching paths:"
msgstr "Dateien:"
-#: gitk:801 gitk:2436
+#: gitk:1959 gitk:3697
msgid "adding/removing string:"
msgstr "Änderungen:"
-#: gitk:810 gitk:812
+#: gitk:1968 gitk:1970
msgid "Exact"
msgstr "Exakt"
-#: gitk:812 gitk:2514 gitk:4274
+#: gitk:1970 gitk:3773 gitk:5518
msgid "IgnCase"
msgstr "Kein Groß/Klein"
-#: gitk:812 gitk:2405 gitk:2512 gitk:4270
+#: gitk:1970 gitk:3666 gitk:3771 gitk:5514
msgid "Regexp"
msgstr "Regexp"
-#: gitk:814 gitk:815 gitk:2533 gitk:2563 gitk:2570 gitk:4380 gitk:4436
+#: gitk:1972 gitk:1973 gitk:3792 gitk:3822 gitk:3829 gitk:5641 gitk:5708
msgid "All fields"
msgstr "Alle Felder"
-#: gitk:815 gitk:2531 gitk:2563 gitk:4336
+#: gitk:1973 gitk:3790 gitk:3822 gitk:5580
msgid "Headline"
msgstr "Ãœberschrift"
-#: gitk:816 gitk:2531 gitk:4336 gitk:4436 gitk:4827
+#: gitk:1974 gitk:3790 gitk:5580 gitk:5708 gitk:6109
msgid "Comments"
msgstr "Beschreibung"
-#: gitk:816 gitk:2531 gitk:2535 gitk:2570 gitk:4336 gitk:4763 gitk:5957
-#: gitk:5972
+#: gitk:1974 gitk:3790 gitk:3794 gitk:3829 gitk:5580 gitk:6045 gitk:7285
+#: gitk:7300
msgid "Author"
msgstr "Autor"
-#: gitk:816 gitk:2531 gitk:4336 gitk:4765
+#: gitk:1974 gitk:3790 gitk:5580 gitk:6047
msgid "Committer"
msgstr "Eintragender"
-#: gitk:845
+#: gitk:2003
msgid "Search"
msgstr "Suche"
-#: gitk:852
+#: gitk:2010
msgid "Diff"
msgstr "Vergleich"
-#: gitk:854
+#: gitk:2012
msgid "Old version"
msgstr "Alte Version"
-#: gitk:856
+#: gitk:2014
msgid "New version"
msgstr "Neue Version"
-#: gitk:858
+#: gitk:2016
msgid "Lines of context"
msgstr "Kontextzeilen"
-#: gitk:868
+#: gitk:2026
msgid "Ignore space change"
msgstr "Leerzeichenänderungen ignorieren"
-#: gitk:926
+#: gitk:2084
msgid "Patch"
msgstr "Patch"
-#: gitk:928
+#: gitk:2086
msgid "Tree"
msgstr "Baum"
-#: gitk:1053 gitk:1068 gitk:6023
+#: gitk:2213 gitk:2226
msgid "Diff this -> selected"
msgstr "Vergleich diese -> gewählte"
-#: gitk:1055 gitk:1070 gitk:6024
+#: gitk:2214 gitk:2227
msgid "Diff selected -> this"
msgstr "Vergleich gewählte -> diese"
-#: gitk:1057 gitk:1072 gitk:6025
+#: gitk:2215 gitk:2228
msgid "Make patch"
msgstr "Patch erstellen"
-#: gitk:1058 gitk:6163
+#: gitk:2216 gitk:7494
msgid "Create tag"
msgstr "Markierung erstellen"
-#: gitk:1059 gitk:6256
+#: gitk:2217 gitk:7593
msgid "Write commit to file"
msgstr "Version in Datei schreiben"
-#: gitk:1060 gitk:6310
+#: gitk:2218 gitk:7647
msgid "Create new branch"
msgstr "Neuen Zweig erstellen"
-#: gitk:1061
+#: gitk:2219
msgid "Cherry-pick this commit"
msgstr "Diese Version pflücken"
-#: gitk:1063
+#: gitk:2220
msgid "Reset HEAD branch to here"
msgstr "HEAD-Zweig auf diese Version zurücksetzen"
-#: gitk:1079
+#: gitk:2234
msgid "Check out this branch"
msgstr "Auf diesen Zweig umstellen"
-#: gitk:1081
+#: gitk:2235
msgid "Remove this branch"
msgstr "Zweig löschen"
-#: gitk:1087
+#: gitk:2242
msgid "Highlight this too"
msgstr "Diesen auch hervorheben"
-#: gitk:1089
+#: gitk:2243
msgid "Highlight this only"
msgstr "Nur diesen hervorheben"
-#: gitk:2162
+#: gitk:2244
msgid "External diff"
msgstr "Externer Vergleich"
-#: gitk:2403
+#: gitk:2255
+msgid "Blame parent commit"
+msgstr "Annotieren der Elternversion"
+
+#: gitk:2360
+msgid "Show origin of this line"
+msgstr "Herkunft dieser Zeile anzeigen"
+
+#: gitk:2361
+msgid "Run git gui blame on this line"
+msgstr "Annotieren (»git gui blame«) von dieser Zeile"
+
+#: gitk:2606
msgid ""
"\n"
"Gitk - a commit viewer for git\n"
@@ -297,431 +321,546 @@ msgstr ""
"\n"
"Copyright © 2005-2008 Paul Mackerras\n"
"\n"
-"Benutzung und Weiterverbreitung gemäß den Bedingungen der GNU General Public License"
+"Benutzung und Weiterverbreitung gemäß den Bedingungen der GNU General Public "
+"License"
-#: gitk:1326 gitk:1387 gitk:6582
+#: gitk:2496 gitk:2557 gitk:7943
msgid "Close"
msgstr "Schließen"
-#: gitk:1345
+#: gitk:2515
msgid "Gitk key bindings"
msgstr "Gitk Tastaturbelegung"
-#: gitk:1347
+#: gitk:2517
msgid "Gitk key bindings:"
msgstr "Gitk Tastaturbelegung:"
-#: gitk:1349
+#: gitk:2519
#, tcl-format
msgid "<%s-Q>\t\tQuit"
msgstr "<%s-Q>\t\tBeenden"
-#: gitk:1350
+#: gitk:2520
msgid "<Home>\t\tMove to first commit"
msgstr "<Pos1>\t\tZur neuesten Version springen"
-#: gitk:1351
+#: gitk:2521
msgid "<End>\t\tMove to last commit"
msgstr "<Ende>\t\tZur ältesten Version springen"
-#: gitk:1352
+#: gitk:2522
msgid "<Up>, p, i\tMove up one commit"
msgstr "<Hoch>, p, i\tNächste neuere Version"
-#: gitk:1353
+#: gitk:2523
msgid "<Down>, n, k\tMove down one commit"
msgstr "<Runter>, n, k\tNächste ältere Version"
-#: gitk:1354
+#: gitk:2524
msgid "<Left>, z, j\tGo back in history list"
msgstr "<Links>, z, j\tEine Version zurückgehen"
-#: gitk:1355
+#: gitk:2525
msgid "<Right>, x, l\tGo forward in history list"
msgstr "<Rechts>, x, l\tEine Version weitergehen"
-#: gitk:1356
+#: gitk:2526
msgid "<PageUp>\tMove up one page in commit list"
msgstr "<BildHoch>\tEine Seite nach oben blättern"
-#: gitk:1357
+#: gitk:2527
msgid "<PageDown>\tMove down one page in commit list"
msgstr "<BildRunter>\tEine Seite nach unten blättern"
-#: gitk:1358
+#: gitk:2528
#, tcl-format
msgid "<%s-Home>\tScroll to top of commit list"
msgstr "<%s-Pos1>\tZum oberen Ende der Versionsliste blättern"
-#: gitk:1359
+#: gitk:2529
#, tcl-format
msgid "<%s-End>\tScroll to bottom of commit list"
msgstr "<%s-Ende>\tZum unteren Ende der Versionsliste blättern"
-#: gitk:1360
+#: gitk:2530
#, tcl-format
msgid "<%s-Up>\tScroll commit list up one line"
msgstr "<%s-Hoch>\tVersionsliste eine Zeile nach oben blättern"
-#: gitk:1361
+#: gitk:2531
#, tcl-format
msgid "<%s-Down>\tScroll commit list down one line"
msgstr "<%s-Runter>\tVersionsliste eine Zeile nach unten blättern"
-#: gitk:1362
+#: gitk:2532
#, tcl-format
msgid "<%s-PageUp>\tScroll commit list up one page"
msgstr "<%s-BildHoch>\tVersionsliste eine Seite hoch blättern"
-#: gitk:1363
+#: gitk:2533
#, tcl-format
msgid "<%s-PageDown>\tScroll commit list down one page"
msgstr "<%s-BildRunter>\tVersionsliste eine Seite nach unten blättern"
-#: gitk:1364
+#: gitk:2534
msgid "<Shift-Up>\tFind backwards (upwards, later commits)"
msgstr "<Umschalt-Hoch>\tRückwärts suchen (nach oben; neuere Versionen)"
-#: gitk:1365
+#: gitk:2535
msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)"
msgstr "<Umschalt-Runter> Suchen (nach unten; ältere Versionen)"
-#: gitk:1366
+#: gitk:2536
msgid "<Delete>, b\tScroll diff view up one page"
msgstr "<Entf>, b\t\tVergleich eine Seite nach oben blättern"
-#: gitk:1367
+#: gitk:2537
msgid "<Backspace>\tScroll diff view up one page"
msgstr "<Löschtaste>\tVergleich eine Seite nach oben blättern"
-#: gitk:1368
+#: gitk:2538
msgid "<Space>\t\tScroll diff view down one page"
msgstr "<Leertaste>\tVergleich eine Seite nach unten blättern"
-#: gitk:1369
+#: gitk:2539
msgid "u\t\tScroll diff view up 18 lines"
msgstr "u\t\tVergleich um 18 Zeilen nach oben (»up«) blättern"
-#: gitk:1370
+#: gitk:2540
msgid "d\t\tScroll diff view down 18 lines"
msgstr "d\t\tVergleich um 18 Zeilen nach unten (»down«) blättern"
-#: gitk:1371
+#: gitk:2541
#, tcl-format
msgid "<%s-F>\t\tFind"
msgstr "<%s-F>\t\tSuchen"
-#: gitk:1372
+#: gitk:2542
#, tcl-format
msgid "<%s-G>\t\tMove to next find hit"
msgstr "<%s-G>\t\tWeitersuchen"
-#: gitk:1373
+#: gitk:2543
msgid "<Return>\tMove to next find hit"
msgstr "<Eingabetaste>\tWeitersuchen"
-#: gitk:1374
+#: gitk:2544
msgid "/\t\tMove to next find hit, or redo find"
msgstr "/\t\tWeitersuchen oder neue Suche beginnen"
-#: gitk:1375
+#: gitk:2545
msgid "?\t\tMove to previous find hit"
msgstr "?\t\tRückwärts weitersuchen"
-#: gitk:1376
+#: gitk:2546
msgid "f\t\tScroll diff view to next file"
msgstr "f\t\tVergleich zur nächsten Datei (»file«) blättern"
-#: gitk:1377
+#: gitk:2547
#, tcl-format
msgid "<%s-S>\t\tSearch for next hit in diff view"
msgstr "<%s-S>\t\tWeitersuchen im Vergleich"
-#: gitk:1378
+#: gitk:2548
#, tcl-format
msgid "<%s-R>\t\tSearch for previous hit in diff view"
msgstr "<%s-R>\t\tRückwärts weitersuchen im Vergleich"
-#: gitk:1379
+#: gitk:2549
#, tcl-format
msgid "<%s-KP+>\tIncrease font size"
msgstr "<%s-Nummerblock-Plus>\tSchriftgröße vergrößern"
-#: gitk:1380
+#: gitk:2550
#, tcl-format
msgid "<%s-plus>\tIncrease font size"
msgstr "<%s-Plus>\tSchriftgröße vergrößern"
-#: gitk:1381
+#: gitk:2551
#, tcl-format
msgid "<%s-KP->\tDecrease font size"
msgstr "<%s-Nummernblock-> Schriftgröße verkleinern"
-#: gitk:1382
+#: gitk:2552
#, tcl-format
msgid "<%s-minus>\tDecrease font size"
msgstr "<%s-Minus>\tSchriftgröße verkleinern"
-#: gitk:1383
+#: gitk:2553
msgid "<F5>\t\tUpdate"
msgstr "<F5>\t\tAktualisieren"
-#: gitk:1896
+#: gitk:2979
+#, tcl-format
+msgid "Error getting \"%s\" from %s:"
+msgstr "Fehler beim Holen von »%s« von »%s«:"
+
+#: gitk:3036 gitk:3045
+#, tcl-format
+msgid "Error creating temporary directory %s:"
+msgstr "Fehler beim Erzeugen eines temporären Verzeichnisses »%s«:"
+
+#: gitk:3058
+msgid "command failed:"
+msgstr "Kommando fehlgeschlagen:"
+
+#: gitk:3078
+msgid "No such commit"
+msgstr "Version nicht gefunden"
+
+#: gitk:3083
+msgid "git gui blame: command failed:"
+msgstr "git gui blame: Kommando fehlgeschlagen:"
+
+#: gitk:3398
+#, tcl-format
+msgid "Couldn't read merge head: %s"
+msgstr "Zusammenführungs-Spitze konnte nicht gelesen werden: %s"
+
+#: gitk:3406
+#, tcl-format
+msgid "Error reading index: %s"
+msgstr "Fehler beim Lesen der Bereitstellung (»index«): %s"
+
+#: gitk:3431
+#, tcl-format
+msgid "Couldn't start git blame: %s"
+msgstr "»git blame« konnte nicht gestartet werden: %s"
+
+#: gitk:3434 gitk:6160
+msgid "Searching"
+msgstr "Suchen"
+
+#: gitk:3466
+#, tcl-format
+msgid "Error running git blame: %s"
+msgstr "Fehler beim Ausführen von »git blame«: %s"
+
+#: gitk:3494
+#, tcl-format
+msgid "That line comes from commit %s, which is not in this view"
+msgstr ""
+"Diese Zeile stammt aus Version %s, welche nicht in dieser Ansicht gezeigt "
+"wird."
+
+#: gitk:3508
+msgid "External diff viewer failed:"
+msgstr "Externes Vergleich-(Diff-)Programm fehlgeschlagen:"
+
+#: gitk:3210
msgid "Gitk view definition"
msgstr "Gitk Ansichten"
-#: gitk:1921
-msgid "Name"
-msgstr "Name"
-
-#: gitk:1924
+#: gitk:3630
msgid "Remember this view"
msgstr "Diese Ansicht speichern"
-#: gitk:3126
+#: gitk:3232
msgid "Commits to include (arguments to git log):"
msgstr "Versionen anzeigen (Argumente von git-log):"
-#: gitk:3133
+#: gitk:3632
+msgid "Use all refs"
+msgstr "Alle Zweige verwenden"
+
+#: gitk:3633
+msgid "Strictly sort by date"
+msgstr "Streng nach Datum sortieren"
+
+#: gitk:3634
+msgid "Mark branch sides"
+msgstr "Zweig-Seiten markieren"
+
+#: gitk:3635
+msgid "Since date:"
+msgstr "Von Datum:"
+
+#: gitk:3636
+msgid "Until date:"
+msgstr "Bis Datum:"
+
+#: gitk:3637
+msgid "Max count:"
+msgstr "Max. Anzahl:"
+
+#: gitk:3638
+msgid "Skip:"
+msgstr "Ãœberspringen:"
+
+#: gitk:3639
+msgid "Limit to first parent"
+msgstr "Auf erste Elternversion beschränken"
+
+#: gitk:3640
msgid "Command to generate more commits to include:"
msgstr "Versionsliste durch folgendes Kommando erzeugen lassen:"
-#: gitk:1942
+#: gitk:3749
+msgid "Name"
+msgstr "Name"
+
+#: gitk:3797
msgid "Enter files and directories to include, one per line:"
msgstr "Folgende Dateien und Verzeichnisse anzeigen (eine pro Zeile):"
-#: gitk:1989
+#: gitk:3811
+msgid "Apply (F5)"
+msgstr "Anwenden (F5)"
+
+#: gitk:3849
msgid "Error in commit selection arguments:"
msgstr "Fehler in den ausgewählten Versionen:"
-#: gitk:2043 gitk:2127 gitk:2583 gitk:2597 gitk:3781 gitk:8689 gitk:8690
+#: gitk:3347 gitk:3399 gitk:3842 gitk:3856 gitk:5060 gitk:10141 gitk:10142
msgid "None"
msgstr "Keine"
-#: gitk:2531 gitk:4336 gitk:5959 gitk:5974
+#: gitk:3790 gitk:5580 gitk:7287 gitk:7302
msgid "Date"
msgstr "Datum"
-#: gitk:2531 gitk:4336
+#: gitk:3790 gitk:5580
msgid "CDate"
msgstr "Eintragedatum"
-#: gitk:2680 gitk:2685
+#: gitk:3939 gitk:3944
msgid "Descendant"
msgstr "Abkömmling"
-#: gitk:2681
+#: gitk:3940
msgid "Not descendant"
msgstr "Nicht Abkömmling"
-#: gitk:2688 gitk:2693
+#: gitk:3947 gitk:3952
msgid "Ancestor"
msgstr "Vorgänger"
-#: gitk:2689
+#: gitk:3948
msgid "Not ancestor"
msgstr "Nicht Vorgänger"
-#: gitk:2924
+#: gitk:4187
msgid "Local changes checked in to index but not committed"
msgstr "Lokale Änderungen bereitgestellt, aber nicht eingetragen"
-#: gitk:2954
+#: gitk:4220
msgid "Local uncommitted changes, not checked in to index"
msgstr "Lokale Änderungen, nicht bereitgestellt"
-#: gitk:4305
-msgid "Searching"
-msgstr "Suchen"
-
-#: gitk:4767
+#: gitk:6673
msgid "Tags:"
msgstr "Markierungen:"
-#: gitk:4784 gitk:4790 gitk:5952
+#: gitk:6066 gitk:6072 gitk:7280
msgid "Parent"
msgstr "Eltern"
-#: gitk:4795
+#: gitk:6077
msgid "Child"
msgstr "Kind"
-#: gitk:4804
+#: gitk:6086
msgid "Branch"
msgstr "Zweig"
-#: gitk:4807
+#: gitk:6089
msgid "Follows"
msgstr "Folgt auf"
-#: gitk:4810
+#: gitk:6092
msgid "Precedes"
msgstr "Vorgänger von"
-#: gitk:5094
-msgid "Error getting merge diffs:"
-msgstr "Fehler beim Laden des Vergleichs:"
+#: gitk:7209
+#, tcl-format
+msgid "Error getting diffs: %s"
+msgstr "Fehler beim Laden des Vergleichs: %s"
-#: gitk:5779
+#: gitk:7748
msgid "Goto:"
msgstr "Gehe zu:"
-#: gitk:5781
+#: gitk:7115
msgid "SHA1 ID:"
msgstr "SHA1-Hashwert:"
-#: gitk:5806
+#: gitk:7134
#, tcl-format
msgid "Short SHA1 id %s is ambiguous"
msgstr "Kurzer SHA1-Hashwert »%s« ist mehrdeutig"
-#: gitk:5818
+#: gitk:7146
#, tcl-format
msgid "SHA1 id %s is not known"
msgstr "SHA1-Hashwert »%s« unbekannt"
-#: gitk:5820
+#: gitk:7148
#, tcl-format
msgid "Tag/Head %s is not known"
msgstr "Markierung/Zweig »%s« ist unbekannt"
-#: gitk:5962
+#: gitk:7290
msgid "Children"
msgstr "Kinder"
-#: gitk:6019
+#: gitk:7347
#, tcl-format
msgid "Reset %s branch to here"
msgstr "Zweig »%s« hierher zurücksetzen"
-#: gitk:7204
+#: gitk:7349
msgid "Detached head: can't reset"
msgstr "Zweigspitze ist abgetrennt: Zurücksetzen nicht möglich"
-#: gitk:7236
+#: gitk:7381
msgid "Top"
msgstr "Oben"
-#: gitk:6051
+#: gitk:7382
msgid "From"
msgstr "Von"
-#: gitk:6056
+#: gitk:7387
msgid "To"
msgstr "bis"
-#: gitk:6079
+#: gitk:7410
msgid "Generate patch"
msgstr "Patch erstellen"
-#: gitk:6081
+#: gitk:7412
msgid "From:"
msgstr "Von:"
-#: gitk:6090
+#: gitk:7421
msgid "To:"
msgstr "bis:"
-#: gitk:6099
+#: gitk:7430
msgid "Reverse"
msgstr "Umgekehrt"
-#: gitk:6101 gitk:6270
+#: gitk:7432 gitk:7607
msgid "Output file:"
msgstr "Ausgabedatei:"
-#: gitk:6107
+#: gitk:7438
msgid "Generate"
msgstr "Erzeugen"
-#: gitk:6143
+#: gitk:7474
msgid "Error creating patch:"
msgstr "Fehler beim Patch erzeugen:"
-#: gitk:6165 gitk:6258 gitk:6312
+#: gitk:7496 gitk:7595 gitk:7649
msgid "ID:"
msgstr "ID:"
-#: gitk:6174
+#: gitk:7505
msgid "Tag name:"
msgstr "Markierungsname:"
-#: gitk:6178 gitk:6321
+#: gitk:7509 gitk:7659
msgid "Create"
msgstr "Erstellen"
-#: gitk:6193
+#: gitk:7524
msgid "No tag name specified"
msgstr "Kein Markierungsname angegeben"
-#: gitk:6197
+#: gitk:7528
#, tcl-format
msgid "Tag \"%s\" already exists"
msgstr "Markierung »%s« existiert bereits."
-#: gitk:6203
+#: gitk:7534
msgid "Error creating tag:"
msgstr "Fehler bei Markierung erstellen:"
-#: gitk:6267
+#: gitk:7604
msgid "Command:"
msgstr "Kommando:"
-#: gitk:6275
+#: gitk:7612
msgid "Write"
msgstr "Schreiben"
-#: gitk:6291
+#: gitk:7628
msgid "Error writing commit:"
msgstr "Fehler beim Schreiben der Version:"
-#: gitk:6317
+#: gitk:7654
msgid "Name:"
msgstr "Name:"
-#: gitk:6336
+#: gitk:7674
msgid "Please specify a name for the new branch"
msgstr "Bitte geben Sie einen Namen für den neuen Zweig an."
-#: gitk:6365
+#: gitk:8328
+#, tcl-format
+msgid "Branch '%s' already exists. Overwrite?"
+msgstr "Zweig »%s« existiert bereits. Soll er überschrieben werden?"
+
+#: gitk:8394
#, tcl-format
msgid "Commit %s is already included in branch %s -- really re-apply it?"
msgstr ""
"Version »%s« ist bereits im Zweig »%s« enthalten -- trotzdem erneut "
"eintragen?"
-#: gitk:6370
+#: gitk:7718
msgid "Cherry-picking"
msgstr "Version pflücken"
-#: gitk:6382
+#: gitk:8408
+#, tcl-format
+msgid ""
+"Cherry-pick failed because of local changes to file '%s'.\n"
+"Please commit, reset or stash your changes and try again."
+msgstr ""
+"Pflücken fehlgeschlagen, da noch lokale Änderungen in Datei »%s«\n"
+"vorliegen. Bitte diese Änderungen eintragen, zurücksetzen oder\n"
+"zwischenspeichern (»git stash») und dann erneut versuchen."
+
+#: gitk:8414
+msgid ""
+"Cherry-pick failed because of merge conflict.\n"
+"Do you wish to run git citool to resolve it?"
+msgstr ""
+"Pflücken fehlgeschlagen, da ein Zusammenführungs-Konflikt aufgetreten\n"
+"ist. Soll das »git citool« (Zusammenführungs-Werkzeug) aufgerufen\n"
+"werden, um diesen Konflikt aufzulösen?"
+
+#: gitk:8430
msgid "No changes committed"
msgstr "Keine Änderungen eingetragen"
-#: gitk:6405
+#: gitk:7745
msgid "Confirm reset"
msgstr "Zurücksetzen bestätigen"
-#: gitk:6407
+#: gitk:7747
#, tcl-format
msgid "Reset branch %s to %s?"
msgstr "Zweig »%s« auf »%s« zurücksetzen?"
-#: gitk:6411
+#: gitk:7751
msgid "Reset type:"
msgstr "Art des Zurücksetzens:"
-#: gitk:6415
+#: gitk:7755
msgid "Soft: Leave working tree and index untouched"
msgstr "Harmlos: Arbeitskopie und Bereitstellung unverändert"
-#: gitk:6418
+#: gitk:7758
msgid "Mixed: Leave working tree untouched, reset index"
msgstr ""
"Gemischt: Arbeitskopie unverändert,\n"
"Bereitstellung zurückgesetzt"
-#: gitk:6421
+#: gitk:7761
msgid ""
"Hard: Reset working tree and index\n"
"(discard ALL local changes)"
@@ -729,21 +868,21 @@ msgstr ""
"Hart: Arbeitskopie und Bereitstellung\n"
"(Alle lokalen Änderungen werden gelöscht)"
-#: gitk:6437
+#: gitk:7777
msgid "Resetting"
msgstr "Zurücksetzen"
-#: gitk:6494
+#: gitk:7834
msgid "Checking out"
msgstr "Umstellen"
-#: gitk:6524
+#: gitk:7885
msgid "Cannot delete the currently checked-out branch"
msgstr ""
"Der Zweig, auf den die Arbeitskopie momentan umgestellt ist, kann nicht "
"gelöscht werden."
-#: gitk:6530
+#: gitk:7891
#, tcl-format
msgid ""
"The commits on branch %s aren't on any other branch.\n"
@@ -752,16 +891,16 @@ msgstr ""
"Die Versionen auf Zweig »%s« existieren auf keinem anderen Zweig.\n"
"Zweig »%s« trotzdem löschen?"
-#: gitk:6561
+#: gitk:7922
#, tcl-format
msgid "Tags and heads: %s"
msgstr "Markierungen und Zweige: %s"
-#: gitk:6575
+#: gitk:7936
msgid "Filter"
msgstr "Filtern"
-#: gitk:6869
+#: gitk:8230
msgid ""
"Error reading commit topology information; branch and preceding/following "
"tag information will be incomplete."
@@ -769,125 +908,157 @@ msgstr ""
"Fehler beim Lesen der Strukturinformationen; Zweige und Vorgänger/Nachfolger "
"Informationen werden unvollständig sein."
-#: gitk:7853
+#: gitk:9216
msgid "Tag"
msgstr "Markierung"
-#: gitk:7853
+#: gitk:9216
msgid "Id"
msgstr "Id"
-#: gitk:7893
+#: gitk:9262
msgid "Gitk font chooser"
msgstr "Gitk Schriften wählen"
-#: gitk:7910
+#: gitk:9279
msgid "B"
msgstr "F"
-#: gitk:7913
+#: gitk:9282
msgid "I"
msgstr "K"
-#: gitk:8006
+#: gitk:9375
msgid "Gitk preferences"
msgstr "Gitk Einstellungen"
-#: gitk:8007
+#: gitk:9376
msgid "Commit list display options"
msgstr "Anzeige Versionsliste"
-#: gitk:8010
+#: gitk:9379
msgid "Maximum graph width (lines)"
msgstr "Maximale Graphenbreite (Zeilen)"
-#: gitk:8014
+#: gitk:9383
#, tcl-format
msgid "Maximum graph width (% of pane)"
msgstr "Maximale Graphenbreite (% des Fensters)"
-#: gitk:8019
+#: gitk:9388
msgid "Show local changes"
msgstr "Lokale Änderungen anzeigen"
-#: gitk:8024
+#: gitk:9393
msgid "Auto-select SHA1"
msgstr "SHA1-Hashwert automatisch markieren"
-#: gitk:8029
+#: gitk:9398
msgid "Diff display options"
msgstr "Anzeige Vergleich"
-#: gitk:8031
+#: gitk:9400
msgid "Tab spacing"
msgstr "Tabulatorbreite"
-#: gitk:8035
+#: gitk:9404
msgid "Display nearby tags"
msgstr "Naheliegende Ãœberschriften anzeigen"
-#: gitk:8040
+#: gitk:9409
msgid "Limit diffs to listed paths"
msgstr "Vergleich nur für angezeigte Pfade"
-#: gitk:9264
+#: gitk:9414
+msgid "Support per-file encodings"
+msgstr "Zeichenkodierung pro Datei ermitteln"
+
+#: gitk:9421
msgid "External diff tool"
msgstr "Externes Vergleich-(Diff-)Programm"
-#: gitk:9266
+#: gitk:9423
msgid "Choose..."
msgstr "Wählen..."
-#: gitk:9271
+#: gitk:9428
msgid "Colors: press to choose"
msgstr "Farben: Klicken zum Wählen"
-#: gitk:8048
+#: gitk:9431
msgid "Background"
msgstr "Hintergrund"
-#: gitk:8052
+#: gitk:10153 gitk:10183
+msgid "background"
+msgstr "Hintergrund"
+
+#: gitk:10156
msgid "Foreground"
msgstr "Vordergrund"
-#: gitk:8056
+#: gitk:10157
+msgid "foreground"
+msgstr "Vordergrund"
+
+#: gitk:10160
msgid "Diff: old lines"
msgstr "Vergleich: Alte Zeilen"
-#: gitk:8061
+#: gitk:10161
+msgid "diff old lines"
+msgstr "Vergleich - Alte Zeilen"
+
+#: gitk:10165
msgid "Diff: new lines"
msgstr "Vergleich: Neue Zeilen"
-#: gitk:8066
+#: gitk:10166
+msgid "diff new lines"
+msgstr "Vergleich - Neue Zeilen"
+
+#: gitk:10170
msgid "Diff: hunk header"
msgstr "Vergleich: Änderungstitel"
-#: gitk:8072
+#: gitk:10172
+msgid "diff hunk header"
+msgstr "Vergleich - Änderungstitel"
+
+#: gitk:10176
+msgid "Marked line bg"
+msgstr "Markierte Zeile Hintergrund"
+
+#: gitk:10178
+msgid "marked line background"
+msgstr "markierte Zeile Hintergrund"
+
+#: gitk:10182
msgid "Select bg"
msgstr "Hintergrundfarbe Auswählen"
-#: gitk:8076
+#: gitk:9459
msgid "Fonts: press to choose"
msgstr "Schriftart: Klicken zum Wählen"
-#: gitk:8078
+#: gitk:9461
msgid "Main font"
msgstr "Programmschriftart"
-#: gitk:8079
+#: gitk:9462
msgid "Diff display font"
msgstr "Vergleich"
-#: gitk:8080
+#: gitk:9463
msgid "User interface font"
msgstr "Beschriftungen"
-#: gitk:8096
+#: gitk:9488
#, tcl-format
msgid "Gitk: choose color for %s"
msgstr "Gitk: Farbe wählen für %s"
-#: gitk:8477
+#: gitk:9934
msgid ""
"Sorry, gitk cannot run with this version of Tcl/Tk.\n"
" Gitk requires at least Tcl/Tk 8.4."
@@ -895,24 +1066,24 @@ msgstr ""
"Gitk läuft nicht mit dieser Version von Tcl/Tk.\n"
"Gitk benötigt mindestens Tcl/Tk 8.4."
-#: gitk:8566
+#: gitk:10047
msgid "Cannot find a git repository here."
msgstr "Kein Git-Projektarchiv gefunden."
-#: gitk:8570
+#: gitk:10051
#, tcl-format
msgid "Cannot find the git directory \"%s\"."
msgstr "Git-Verzeichnis »%s« wurde nicht gefunden."
-#: gitk:8613
+#: gitk:10098
#, tcl-format
msgid "Ambiguous argument '%s': both revision and filename"
msgstr "Mehrdeutige Angabe »%s«: Sowohl Version als auch Dateiname existiert."
-#: gitk:8625
+#: gitk:10110
msgid "Bad arguments to gitk:"
msgstr "Falsche Kommandozeilen-Parameter für gitk:"
-#: gitk:9915
+#: gitk:10170
msgid "Command line"
msgstr "Kommandozeile"
diff --git a/gitk-git/po/es.po b/gitk-git/po/es.po
index 2cb1486247..0e19b5eae2 100644
--- a/gitk-git/po/es.po
+++ b/gitk-git/po/es.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitk\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-03-13 17:29+0100\n"
+"POT-Creation-Date: 2008-10-18 22:03+1100\n"
"PO-Revision-Date: 2008-03-25 11:20+0100\n"
"Last-Translator: Santiago Gala <santiago.gala@gmail.com>\n"
"Language-Team: Spanish\n"
@@ -16,676 +16,702 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: gitk:111
-msgid "Error executing git rev-list:"
-msgstr "Error al ejecutar git rev-list:"
+#: gitk:113
+msgid "Couldn't get list of unmerged files:"
+msgstr "Imposible obtener la lista de archivos pendientes de fusión:"
-#: gitk:124
+#: gitk:340
+msgid "No files selected: --merge specified but no files are unmerged."
+msgstr ""
+"No hay archivos seleccionados: se seleccionó la opción --merge pero no hay "
+"archivos pendientes de fusión."
+
+#: gitk:343
+msgid ""
+"No files selected: --merge specified but no unmerged files are within file "
+"limit."
+msgstr ""
+"No hay archivos seleccionados: se seleccionó la opción --merge pero los "
+"archivos especificados no necesitan fusión."
+
+#: gitk:378
msgid "Reading"
msgstr "Leyendo"
-#: gitk:151 gitk:2191
+#: gitk:438 gitk:3462
msgid "Reading commits..."
msgstr "Leyendo revisiones..."
-#: gitk:275
-msgid "Can't parse git log output:"
-msgstr "Error analizando la salida de git log:"
-
-#: gitk:386 gitk:2195
+#: gitk:441 gitk:1528 gitk:3465
msgid "No commits selected"
msgstr "No se seleccionaron revisiones"
-#: gitk:500
+#: gitk:1399
+msgid "Can't parse git log output:"
+msgstr "Error analizando la salida de git log:"
+
+#: gitk:1605
msgid "No commit information available"
msgstr "Falta información sobre las revisiones"
-#: gitk:599 gitk:621 gitk:1955 gitk:6423 gitk:7923 gitk:8082
+#: gitk:1709 gitk:1731 gitk:3259 gitk:7764 gitk:9293 gitk:9466
msgid "OK"
msgstr "Aceptar"
-#: gitk:623 gitk:1956 gitk:6107 gitk:6178 gitk:6275 gitk:6321 gitk:6425
-#: gitk:7924 gitk:8083
+#: gitk:1733 gitk:3260 gitk:7439 gitk:7510 gitk:7613 gitk:7660 gitk:7766
+#: gitk:9294 gitk:9467
msgid "Cancel"
msgstr "Cancelar"
-#: gitk:661
-msgid "File"
-msgstr "Archivo"
-
-#: gitk:663
+#: gitk:1811
msgid "Update"
msgstr "Actualizar"
-#: gitk:664
+#: gitk:1813
msgid "Reread references"
msgstr "Releer referencias"
-#: gitk:665
+#: gitk:1814
msgid "List references"
msgstr "Lista de referencias"
-#: gitk:666
+#: gitk:1815
msgid "Quit"
msgstr "Salir"
-#: gitk:668
-msgid "Edit"
-msgstr "Editar"
+#: gitk:1810
+msgid "File"
+msgstr "Archivo"
-#: gitk:669
+#: gitk:1818
msgid "Preferences"
msgstr "Preferencias"
-#: gitk:672 gitk:1892
-msgid "View"
-msgstr "Vista"
+#: gitk:1817
+msgid "Edit"
+msgstr "Editar"
-#: gitk:673
+#: gitk:1821
msgid "New view..."
msgstr "Nueva vista..."
-#: gitk:674 gitk:2133 gitk:8722
+#: gitk:1822
msgid "Edit view..."
msgstr "Modificar vista..."
-#: gitk:676 gitk:2134 gitk:8723
+#: gitk:1823
msgid "Delete view"
msgstr "Eliminar vista"
-#: gitk:678
+#: gitk:1825
msgid "All files"
msgstr "Todos los archivos"
-#: gitk:682
-msgid "Help"
-msgstr "Ayuda"
+#: gitk:1820 gitk:3196
+msgid "View"
+msgstr "Vista"
-#: gitk:683 gitk:1317
+#: gitk:1828 gitk:2487
msgid "About gitk"
msgstr "Acerca de gitk"
-#: gitk:684
+#: gitk:1829
msgid "Key bindings"
msgstr "Combinaciones de teclas"
-#: gitk:741
+#: gitk:1827
+msgid "Help"
+msgstr "Ayuda"
+
+#: gitk:1887
msgid "SHA1 ID: "
msgstr "SHA1 ID: "
-#: gitk:791
+#: gitk:1918
+msgid "Row"
+msgstr ""
+
+#: gitk:1949
msgid "Find"
msgstr "Buscar"
-#: gitk:792
+#: gitk:1950
msgid "next"
msgstr "<<"
-#: gitk:793
+#: gitk:1951
msgid "prev"
msgstr ">>"
-#: gitk:794
+#: gitk:1952
msgid "commit"
msgstr "revisión"
-#: gitk:797 gitk:799 gitk:2356 gitk:2379 gitk:2403 gitk:4306 gitk:4369
+#: gitk:1955 gitk:1957 gitk:3617 gitk:3640 gitk:3664 gitk:5550 gitk:5621
msgid "containing:"
msgstr "que contiene:"
-#: gitk:800 gitk:1778 gitk:1783 gitk:2431
+#: gitk:1958 gitk:2954 gitk:2959 gitk:3692
msgid "touching paths:"
msgstr "que modifica la ruta:"
-#: gitk:801 gitk:2436
+#: gitk:1959 gitk:3697
msgid "adding/removing string:"
msgstr "que añade/elimina cadena:"
-#: gitk:810 gitk:812
+#: gitk:1968 gitk:1970
msgid "Exact"
msgstr "Exacto"
-#: gitk:812 gitk:2514 gitk:4274
+#: gitk:1970 gitk:3773 gitk:5518
msgid "IgnCase"
msgstr "NoMayús"
-#: gitk:812 gitk:2405 gitk:2512 gitk:4270
+#: gitk:1970 gitk:3666 gitk:3771 gitk:5514
msgid "Regexp"
msgstr "Regex"
-#: gitk:814 gitk:815 gitk:2533 gitk:2563 gitk:2570 gitk:4380 gitk:4436
+#: gitk:1972 gitk:1973 gitk:3792 gitk:3822 gitk:3829 gitk:5641 gitk:5708
msgid "All fields"
msgstr "Todos los campos"
-#: gitk:815 gitk:2531 gitk:2563 gitk:4336
+#: gitk:1973 gitk:3790 gitk:3822 gitk:5580
msgid "Headline"
msgstr "Título"
-#: gitk:816 gitk:2531 gitk:4336 gitk:4436 gitk:4827
+#: gitk:1974 gitk:3790 gitk:5580 gitk:5708 gitk:6109
msgid "Comments"
msgstr "Comentarios"
-#: gitk:816 gitk:2531 gitk:2535 gitk:2570 gitk:4336 gitk:4763 gitk:5956
-#: gitk:5971
+#: gitk:1974 gitk:3790 gitk:3794 gitk:3829 gitk:5580 gitk:6045 gitk:7285
+#: gitk:7300
msgid "Author"
msgstr "Autor"
-#: gitk:816 gitk:2531 gitk:4336 gitk:4765
+#: gitk:1974 gitk:3790 gitk:5580 gitk:6047
msgid "Committer"
msgstr ""
-#: gitk:845
+#: gitk:2003
msgid "Search"
msgstr "Buscar"
-#: gitk:852
+#: gitk:2010
msgid "Diff"
msgstr "Diferencia"
-#: gitk:854
+#: gitk:2012
msgid "Old version"
msgstr "Versión antigua"
-#: gitk:856
+#: gitk:2014
msgid "New version"
msgstr "Versión nueva"
-#: gitk:858
+#: gitk:2016
msgid "Lines of context"
msgstr "Líneas de contexto"
-#: gitk:868
+#: gitk:2026
msgid "Ignore space change"
msgstr "Ignora cambios de espaciado"
-#: gitk:926
+#: gitk:2084
msgid "Patch"
msgstr "Parche"
-#: gitk:928
+#: gitk:2086
msgid "Tree"
msgstr "Ãrbol"
-#: gitk:1053 gitk:1068 gitk:6022
+#: gitk:2213 gitk:2226
msgid "Diff this -> selected"
msgstr "Diferencia de esta -> seleccionada"
-#: gitk:1055 gitk:1070 gitk:6023
+#: gitk:2214 gitk:2227
msgid "Diff selected -> this"
msgstr "Diferencia de seleccionada -> esta"
-#: gitk:1057 gitk:1072 gitk:6024
+#: gitk:2215 gitk:2228
msgid "Make patch"
msgstr "Crear patch"
-#: gitk:1058 gitk:6162
+#: gitk:2216 gitk:7494
msgid "Create tag"
msgstr "Crear etiqueta"
-#: gitk:1059 gitk:6255
+#: gitk:2217 gitk:7593
msgid "Write commit to file"
msgstr "Escribir revisiones a archivo"
-#: gitk:1060 gitk:6309
+#: gitk:2218 gitk:7647
msgid "Create new branch"
msgstr "Crear nueva rama"
-#: gitk:1061
+#: gitk:2219
msgid "Cherry-pick this commit"
msgstr "Añadir esta revisión a la rama actual (cherry-pick)"
-#: gitk:1063
+#: gitk:2220
msgid "Reset HEAD branch to here"
msgstr "Traer la rama HEAD aquí"
-#: gitk:1079
+#: gitk:2234
msgid "Check out this branch"
msgstr "Cambiar a esta rama"
-#: gitk:1081
+#: gitk:2235
msgid "Remove this branch"
msgstr "Eliminar esta rama"
-#: gitk:1087
+#: gitk:2242
msgid "Highlight this too"
msgstr "Seleccionar también"
-#: gitk:1089
+#: gitk:2243
msgid "Highlight this only"
msgstr "Seleccionar sólo"
-#: gitk:1318
+#: gitk:2245
+msgid "Blame parent commit"
+msgstr ""
+
+#: gitk:2488
msgid ""
"\n"
"Gitk - a commit viewer for git\n"
"\n"
-"Copyright © 2005-2006 Paul Mackerras\n"
+"Copyright © 2005-2008 Paul Mackerras\n"
"\n"
"Use and redistribute under the terms of the GNU General Public License"
msgstr ""
"\n"
"Gitk - un visualizador de revisiones para git\n"
"\n"
-"Copyright © 2005-2006 Paul Mackerras\n"
+"Copyright © 2005-2008 Paul Mackerras\n"
"\n"
-"Uso y redistribución permitidos según los términos de la Licencia Pública General de "
-"GNU (GNU GPL)"
+"Uso y redistribución permitidos según los términos de la Licencia Pública "
+"General de GNU (GNU GPL)"
-#: gitk:1326 gitk:1387 gitk:6581
+#: gitk:2496 gitk:2557 gitk:7943
msgid "Close"
msgstr "Cerrar"
-#: gitk:1345
+#: gitk:2515
msgid "Gitk key bindings"
msgstr "Combinaciones de tecla de Gitk"
-#: gitk:1347
+#: gitk:2517
msgid "Gitk key bindings:"
msgstr "Combinaciones de tecla de Gitk:"
-#: gitk:1349
+#: gitk:2519
#, tcl-format
msgid "<%s-Q>\t\tQuit"
msgstr "<%s-Q>\t\tSalir"
-#: gitk:1350
+#: gitk:2520
msgid "<Home>\t\tMove to first commit"
msgstr "<Home>\t\tIr a la primera revisión"
-#: gitk:1351
+#: gitk:2521
msgid "<End>\t\tMove to last commit"
msgstr "<End>\t\tIr a la última revisión"
-#: gitk:1352
+#: gitk:2522
msgid "<Up>, p, i\tMove up one commit"
msgstr "<Up>, p, i\tSubir una revisión"
-#: gitk:1353
+#: gitk:2523
msgid "<Down>, n, k\tMove down one commit"
msgstr "<Down>, n, k\tBajar una revisión"
-#: gitk:1354
+#: gitk:2524
msgid "<Left>, z, j\tGo back in history list"
msgstr "<Left>, z, j\tRetroceder en la historia"
-#: gitk:1355
+#: gitk:2525
msgid "<Right>, x, l\tGo forward in history list"
msgstr "<Right>, x, l\tAvanzar en la historia"
-#: gitk:1356
+#: gitk:2526
msgid "<PageUp>\tMove up one page in commit list"
msgstr "<PageUp>\tSubir una página en la lista de revisiones"
-#: gitk:1357
+#: gitk:2527
msgid "<PageDown>\tMove down one page in commit list"
msgstr "<PageDown>\tBajar una página en la lista de revisiones"
-#: gitk:1358
+#: gitk:2528
#, tcl-format
msgid "<%s-Home>\tScroll to top of commit list"
msgstr "<%s-Home>\tDesplazarse al inicio de la lista de revisiones"
-#: gitk:1359
+#: gitk:2529
#, tcl-format
msgid "<%s-End>\tScroll to bottom of commit list"
msgstr "<%s-End>\tDesplazarse al final de la lista de revisiones"
-#: gitk:1360
+#: gitk:2530
#, tcl-format
msgid "<%s-Up>\tScroll commit list up one line"
msgstr "<%s-Up>\tDesplazar una línea hacia arriba la lista de revisiones"
-#: gitk:1361
+#: gitk:2531
#, tcl-format
msgid "<%s-Down>\tScroll commit list down one line"
msgstr "<%s-Down>\tDesplazar una línea hacia abajo la lista de revisiones"
-#: gitk:1362
+#: gitk:2532
#, tcl-format
msgid "<%s-PageUp>\tScroll commit list up one page"
msgstr "<%s-PageUp>\tDesplazar una página hacia arriba la lista de revisiones"
-#: gitk:1363
+#: gitk:2533
#, tcl-format
msgid "<%s-PageDown>\tScroll commit list down one page"
msgstr "<%s-PageDown>\tDesplazar una página hacia abajo la lista de revisiones"
-#: gitk:1364
+#: gitk:2534
msgid "<Shift-Up>\tFind backwards (upwards, later commits)"
msgstr "<Shift-Up>\tBuscar hacia atrás (arriba, revisiones siguientes)"
-#: gitk:1365
+#: gitk:2535
msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)"
msgstr "<Shift-Down>\tBuscar hacia adelante (abajo, revisiones anteriores)"
-#: gitk:1366
+#: gitk:2536
msgid "<Delete>, b\tScroll diff view up one page"
msgstr "<Delete>, b\tDesplaza hacia arriba una página la vista de diferencias"
-#: gitk:1367
+#: gitk:2537
msgid "<Backspace>\tScroll diff view up one page"
msgstr "<Backspace>\tDesplaza hacia arriba una página la vista de diferencias"
-#: gitk:1368
+#: gitk:2538
msgid "<Space>\t\tScroll diff view down one page"
msgstr "<Space>\t\tDesplaza hacia abajo una página la vista de diferencias"
-#: gitk:1369
+#: gitk:2539
msgid "u\t\tScroll diff view up 18 lines"
msgstr "u\t\tDesplaza hacia arriba 18 líneas la vista de diferencias"
-#: gitk:1370
+#: gitk:2540
msgid "d\t\tScroll diff view down 18 lines"
msgstr "d\t\tDesplaza hacia abajo 18 líneas la vista de diferencias"
-#: gitk:1371
+#: gitk:2541
#, tcl-format
msgid "<%s-F>\t\tFind"
msgstr "<%s-F>\t\tBuscar"
-#: gitk:1372
+#: gitk:2542
#, tcl-format
msgid "<%s-G>\t\tMove to next find hit"
msgstr "<%s-G>\t\tBuscar el siguiente"
-#: gitk:1373
+#: gitk:2543
msgid "<Return>\tMove to next find hit"
msgstr "<Return>\tBuscar el siguiente"
-#: gitk:1374
+#: gitk:2544
msgid "/\t\tMove to next find hit, or redo find"
msgstr "/\t\tBuscar el siguiente, o reiniciar la búsqueda"
-#: gitk:1375
+#: gitk:2545
msgid "?\t\tMove to previous find hit"
msgstr "?\t\tBuscar el anterior"
-#: gitk:1376
+#: gitk:2546
msgid "f\t\tScroll diff view to next file"
msgstr "f\t\tDesplazar la vista de diferencias al archivo siguiente"
-#: gitk:1377
+#: gitk:2547
#, tcl-format
msgid "<%s-S>\t\tSearch for next hit in diff view"
msgstr "<%s-S>\t\tBuscar siguiente en la vista de diferencias"
-#: gitk:1378
+#: gitk:2548
#, tcl-format
msgid "<%s-R>\t\tSearch for previous hit in diff view"
msgstr "<%s-R>\t\tBuscar anterior en la vista de diferencias"
-#: gitk:1379
+#: gitk:2549
#, tcl-format
msgid "<%s-KP+>\tIncrease font size"
msgstr "<%s-KP+>\tAumentar tamaño del texto"
-#: gitk:1380
+#: gitk:2550
#, tcl-format
msgid "<%s-plus>\tIncrease font size"
msgstr "<%s-plus>\tAumentar tamaño del texto"
-#: gitk:1381
+#: gitk:2551
#, tcl-format
msgid "<%s-KP->\tDecrease font size"
msgstr "<%s-KP->\tDisminuir tamaño del texto"
-#: gitk:1382
+#: gitk:2552
#, tcl-format
msgid "<%s-minus>\tDecrease font size"
msgstr "<%s-minus>\tDisminuir tamaño del texto"
-#: gitk:1383
+#: gitk:2553
msgid "<F5>\t\tUpdate"
msgstr "<F5>\t\tActualizar"
-#: gitk:1896
+#: gitk:3200
msgid "Gitk view definition"
msgstr "Definición de vistas de Gitk"
-#: gitk:1921
+#: gitk:3225
msgid "Name"
msgstr "Nombre"
-#: gitk:1924
+#: gitk:3228
msgid "Remember this view"
msgstr "Recordar esta vista"
-#: gitk:1928
-msgid "Commits to include (arguments to git rev-list):"
-msgstr "Revisiones a incluir (argumentos a git rev-list):"
+#: gitk:3232
+msgid "Commits to include (arguments to git log):"
+msgstr "Revisiones a incluir (argumentos a git log):"
-#: gitk:1935
+#: gitk:3239
msgid "Command to generate more commits to include:"
msgstr "Comando que genera más revisiones a incluir:"
-#: gitk:1942
+#: gitk:3246
msgid "Enter files and directories to include, one per line:"
msgstr "Introducir archivos y directorios a incluir, uno por línea:"
-#: gitk:1989
+#: gitk:3293
msgid "Error in commit selection arguments:"
msgstr "Error en los argumentos de selección de las revisiones:"
-#: gitk:2043 gitk:2127 gitk:2583 gitk:2597 gitk:3781 gitk:8688 gitk:8689
+#: gitk:3347 gitk:3399 gitk:3842 gitk:3856 gitk:5060 gitk:10141 gitk:10142
msgid "None"
msgstr "Ninguno"
-#: gitk:2531 gitk:4336 gitk:5958 gitk:5973
+#: gitk:3790 gitk:5580 gitk:7287 gitk:7302
msgid "Date"
msgstr "Fecha"
-#: gitk:2531 gitk:4336
+#: gitk:3790 gitk:5580
msgid "CDate"
msgstr "Fecha de creación"
-#: gitk:2680 gitk:2685
+#: gitk:3939 gitk:3944
msgid "Descendant"
msgstr "Descendiente"
-#: gitk:2681
+#: gitk:3940
msgid "Not descendant"
msgstr "No descendiente"
-#: gitk:2688 gitk:2693
+#: gitk:3947 gitk:3952
msgid "Ancestor"
msgstr "Antepasado"
-#: gitk:2689
+#: gitk:3948
msgid "Not ancestor"
msgstr "No antepasado"
-#: gitk:2924
+#: gitk:4187
msgid "Local changes checked in to index but not committed"
msgstr "Cambios locales añadidos al índice pero sin completar revisión"
-#: gitk:2954
+#: gitk:4220
msgid "Local uncommitted changes, not checked in to index"
msgstr "Cambios locales sin añadir al índice"
-#: gitk:4305
+#: gitk:5549
msgid "Searching"
msgstr "Buscando"
-#: gitk:4767
+#: gitk:6049
msgid "Tags:"
msgstr "Etiquetas:"
-#: gitk:4784 gitk:4790 gitk:5951
+#: gitk:6066 gitk:6072 gitk:7280
msgid "Parent"
msgstr "Padre"
-#: gitk:4795
+#: gitk:6077
msgid "Child"
msgstr "Hija"
-#: gitk:4804
+#: gitk:6086
msgid "Branch"
msgstr "Rama"
-#: gitk:4807
+#: gitk:6089
msgid "Follows"
msgstr "Sigue-a"
-#: gitk:4810
+#: gitk:6092
msgid "Precedes"
msgstr "Precede-a"
-#: gitk:5093
+#: gitk:6378
msgid "Error getting merge diffs:"
msgstr "Error al leer las diferencias de fusión:"
-#: gitk:5778
+#: gitk:7113
msgid "Goto:"
msgstr "Ir a:"
-#: gitk:5780
+#: gitk:7115
msgid "SHA1 ID:"
msgstr "SHA1 ID:"
-#: gitk:5805
+#: gitk:7134
#, tcl-format
msgid "Short SHA1 id %s is ambiguous"
msgstr "La id SHA1 abreviada %s es ambigua"
-#: gitk:5817
+#: gitk:7146
#, tcl-format
msgid "SHA1 id %s is not known"
msgstr "La id SHA1 %s es desconocida"
-#: gitk:5819
+#: gitk:7148
#, tcl-format
msgid "Tag/Head %s is not known"
msgstr "La etiqueta/rama %s es deconocida"
-#: gitk:5961
+#: gitk:7290
msgid "Children"
msgstr "Hijas"
-#: gitk:6018
+#: gitk:7347
#, tcl-format
msgid "Reset %s branch to here"
msgstr "Poner la rama %s en esta revisión"
-#: gitk:6049
+#: gitk:7349
+msgid "Detached head: can't reset"
+msgstr ""
+
+#: gitk:7381
msgid "Top"
msgstr "Origen"
-#: gitk:6050
+#: gitk:7382
msgid "From"
msgstr "De"
-#: gitk:6055
+#: gitk:7387
msgid "To"
msgstr "A"
-#: gitk:6078
+#: gitk:7410
msgid "Generate patch"
msgstr "Generar parche"
-#: gitk:6080
+#: gitk:7412
msgid "From:"
msgstr "De:"
-#: gitk:6089
+#: gitk:7421
msgid "To:"
msgstr "Para:"
-#: gitk:6098
+#: gitk:7430
msgid "Reverse"
msgstr "Invertir"
-#: gitk:6100 gitk:6269
+#: gitk:7432 gitk:7607
msgid "Output file:"
msgstr "Escribir a archivo:"
-#: gitk:6106
+#: gitk:7438
msgid "Generate"
msgstr "Generar"
-#: gitk:6142
+#: gitk:7474
msgid "Error creating patch:"
msgstr "Error en la creación del parche:"
-#: gitk:6164 gitk:6257 gitk:6311
+#: gitk:7496 gitk:7595 gitk:7649
msgid "ID:"
msgstr "ID:"
-#: gitk:6173
+#: gitk:7505
msgid "Tag name:"
msgstr "Nombre de etiqueta:"
-#: gitk:6177 gitk:6320
+#: gitk:7509 gitk:7659
msgid "Create"
msgstr "Crear"
-#: gitk:6192
+#: gitk:7524
msgid "No tag name specified"
msgstr "No se ha especificado etiqueta"
-#: gitk:6196
+#: gitk:7528
#, tcl-format
msgid "Tag \"%s\" already exists"
msgstr "La etiqueta \"%s\" ya existe"
-#: gitk:6202
+#: gitk:7534
msgid "Error creating tag:"
msgstr "Error al crear la etiqueta:"
-#: gitk:6266
+#: gitk:7604
msgid "Command:"
msgstr "Comando:"
-#: gitk:6274
+#: gitk:7612
msgid "Write"
msgstr "Escribir"
-#: gitk:6290
+#: gitk:7628
msgid "Error writing commit:"
msgstr "Error al escribir revisión:"
-#: gitk:6316
+#: gitk:7654
msgid "Name:"
msgstr "Nombre:"
-#: gitk:6335
+#: gitk:7674
msgid "Please specify a name for the new branch"
msgstr "Especifique un nombre para la nueva rama"
-#: gitk:6364
+#: gitk:7703
#, tcl-format
msgid "Commit %s is already included in branch %s -- really re-apply it?"
msgstr "La revisión %s ya está incluida en la rama %s -- ¿Volver a aplicarla?"
-#: gitk:6369
+#: gitk:7708
msgid "Cherry-picking"
msgstr "Eligiendo revisiones (cherry-picking)"
-#: gitk:6381
+#: gitk:7720
msgid "No changes committed"
msgstr "No se han guardado cambios"
-#: gitk:6404
+#: gitk:7745
msgid "Confirm reset"
msgstr "Confirmar git reset"
-#: gitk:6406
+#: gitk:7747
#, tcl-format
msgid "Reset branch %s to %s?"
msgstr "¿Reponer la rama %s a %s?"
-#: gitk:6410
+#: gitk:7751
msgid "Reset type:"
msgstr "Tipo de reposición:"
-#: gitk:6414
+#: gitk:7755
msgid "Soft: Leave working tree and index untouched"
msgstr "Suave: No altera la copia de trabajo ni el índice"
-#: gitk:6417
+#: gitk:7758
msgid "Mixed: Leave working tree untouched, reset index"
msgstr "Mixta: Actualiza el índice, no altera la copia de trabajo"
-#: gitk:6420
+#: gitk:7761
msgid ""
"Hard: Reset working tree and index\n"
"(discard ALL local changes)"
@@ -693,19 +719,19 @@ msgstr ""
"Dura: Actualiza el índice y la copia de trabajo\n"
"(abandona TODAS las modificaciones locales)"
-#: gitk:6436
+#: gitk:7777
msgid "Resetting"
msgstr "Reponiendo"
-#: gitk:6493
+#: gitk:7834
msgid "Checking out"
msgstr "Creando copia de trabajo"
-#: gitk:6523
+#: gitk:7885
msgid "Cannot delete the currently checked-out branch"
msgstr "No se puede borrar la rama actual"
-#: gitk:6529
+#: gitk:7891
#, tcl-format
msgid ""
"The commits on branch %s aren't on any other branch.\n"
@@ -714,134 +740,146 @@ msgstr ""
"Las revisiones de la rama %s no están presentes en otras ramas.\n"
"¿Borrar la rama %s?"
-#: gitk:6560
+#: gitk:7922
#, tcl-format
msgid "Tags and heads: %s"
msgstr "Etiquetas y ramas: %s"
-#: gitk:6574
+#: gitk:7936
msgid "Filter"
msgstr "Filtro"
-#: gitk:6868
+#: gitk:8230
msgid ""
"Error reading commit topology information; branch and preceding/following "
"tag information will be incomplete."
msgstr ""
-"Error al leer la topología de revisiones: la información sobre "
-"las ramas y etiquetas precedentes y siguientes será incompleta."
+"Error al leer la topología de revisiones: la información sobre las ramas y "
+"etiquetas precedentes y siguientes será incompleta."
-#: gitk:7852
+#: gitk:9216
msgid "Tag"
msgstr "Etiqueta"
-#: gitk:7852
+#: gitk:9216
msgid "Id"
msgstr "Id"
-#: gitk:7892
+#: gitk:9262
msgid "Gitk font chooser"
msgstr "Selector de tipografías gitk"
-#: gitk:7909
+#: gitk:9279
msgid "B"
msgstr "B"
-#: gitk:7912
+#: gitk:9282
msgid "I"
msgstr "I"
-#: gitk:8005
+#: gitk:9375
msgid "Gitk preferences"
msgstr "Preferencias de gitk"
-#: gitk:8006
+#: gitk:9376
msgid "Commit list display options"
msgstr "Opciones de visualización de la lista de revisiones"
-#: gitk:8009
+#: gitk:9379
msgid "Maximum graph width (lines)"
msgstr "Ancho máximo del gráfico (en líneas)"
-#: gitk:8013
+#: gitk:9383
#, tcl-format
msgid "Maximum graph width (% of pane)"
msgstr "Ancho máximo del gráfico (en % del panel)"
-#: gitk:8018
+#: gitk:9388
msgid "Show local changes"
msgstr "Mostrar cambios locales"
-#: gitk:8023
+#: gitk:9393
msgid "Auto-select SHA1"
msgstr "Seleccionar automáticamente SHA1 hash"
-#: gitk:8028
+#: gitk:9398
msgid "Diff display options"
msgstr "Opciones de visualización de diferencias"
-#: gitk:8030
+#: gitk:9400
msgid "Tab spacing"
msgstr "Espaciado de tabulador"
-#: gitk:8034
+#: gitk:9404
msgid "Display nearby tags"
msgstr "Mostrar etiquetas cercanas"
-#: gitk:8039
+#: gitk:9409
msgid "Limit diffs to listed paths"
msgstr "Limitar las diferencias a las rutas seleccionadas"
-#: gitk:8044
+#: gitk:9414
+msgid "Support per-file encodings"
+msgstr ""
+
+#: gitk:9421
+msgid "External diff tool"
+msgstr ""
+
+#: gitk:9423
+msgid "Choose..."
+msgstr ""
+
+#: gitk:9428
msgid "Colors: press to choose"
msgstr "Colores: pulse para seleccionar"
-#: gitk:8047
+#: gitk:9431
msgid "Background"
msgstr "Fondo"
-#: gitk:8051
+#: gitk:9435
msgid "Foreground"
msgstr "Primer plano"
-#: gitk:8055
+#: gitk:9439
msgid "Diff: old lines"
msgstr "Diff: líneas viejas"
-#: gitk:8060
+#: gitk:9444
msgid "Diff: new lines"
msgstr "Diff: líneas nuevas"
-#: gitk:8065
+#: gitk:9449
msgid "Diff: hunk header"
msgstr "Diff: cabecera de fragmento"
-#: gitk:8071
+#: gitk:9455
msgid "Select bg"
msgstr "Color de fondo de la selección"
-#: gitk:8075
+#: gitk:9459
msgid "Fonts: press to choose"
msgstr "Tipografías: pulse para elegir"
-#: gitk:8077
+#: gitk:9461
msgid "Main font"
msgstr "Tipografía principal"
-#: gitk:8078
+#: gitk:9462
msgid "Diff display font"
msgstr "Tipografía para diferencias"
-#: gitk:8079
+#: gitk:9463
msgid "User interface font"
msgstr "Tipografía para interfaz de usuario"
-#: gitk:8095
+#: gitk:9488
#, tcl-format
msgid "Gitk: choose color for %s"
msgstr "Gitk: elegir color para %s"
-#: gitk:8476
+#: gitk:9934
msgid ""
"Sorry, gitk cannot run with this version of Tcl/Tk.\n"
" Gitk requires at least Tcl/Tk 8.4."
@@ -849,42 +887,25 @@ msgstr ""
"Esta versión de Tcl/Tk es demasiado antigua.\n"
" Gitk requiere Tcl/Tk versión 8.4 o superior."
-#: gitk:8565
+#: gitk:10047
msgid "Cannot find a git repository here."
msgstr "No hay un repositorio git aquí."
-#: gitk:8569
+#: gitk:10051
#, tcl-format
msgid "Cannot find the git directory \"%s\"."
msgstr "No hay directorio git \"%s\"."
-#: gitk:8612
+#: gitk:10098
#, tcl-format
msgid "Ambiguous argument '%s': both revision and filename"
-msgstr "Argumento ambiguo: '%s' es tanto una revisión como un nombre de archivo"
+msgstr ""
+"Argumento ambiguo: '%s' es tanto una revisión como un nombre de archivo"
-#: gitk:8624
+#: gitk:10110
msgid "Bad arguments to gitk:"
msgstr "Argumentos incorrectos a Gitk:"
-#: gitk:8636
-msgid "Couldn't get list of unmerged files:"
-msgstr "Imposible obtener la lista de archivos pendientes de fusión:"
-
-#: gitk:8652
-msgid "No files selected: --merge specified but no files are unmerged."
-msgstr ""
-"No hay archivos seleccionados: se seleccionó la opción --merge pero no hay "
-"archivos pendientes de fusión."
-
-#: gitk:8655
-msgid ""
-"No files selected: --merge specified but no unmerged files are within file "
-"limit."
-msgstr ""
-"No hay archivos seleccionados: se seleccionó la opción --merge pero los archivos "
-"especificados no necesitan fusión."
-
-#: gitk:8716
+#: gitk:10170
msgid "Command line"
msgstr "Línea de comandos"
diff --git a/gitk-git/po/it.po b/gitk-git/po/it.po
index d0f4c2e19a..e89c95702c 100644
--- a/gitk-git/po/it.po
+++ b/gitk-git/po/it.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitk\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-03-13 17:29+0100\n"
+"POT-Creation-Date: 2008-10-18 22:03+1100\n"
"PO-Revision-Date: 2008-03-13 17:34+0100\n"
"Last-Translator: Michele Ballabio <barra_cuda@katamail.com>\n"
"Language-Team: Italian\n"
@@ -16,676 +16,706 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: gitk:111
-msgid "Error executing git rev-list:"
-msgstr "Errore nell'esecuzione di git rev-list:"
+#: gitk:113
+msgid "Couldn't get list of unmerged files:"
+msgstr "Impossibile ottenere l'elenco dei file in attesa di fusione:"
+
+#: gitk:340
+msgid "No files selected: --merge specified but no files are unmerged."
+msgstr ""
+"Nessun file selezionato: è stata specificata l'opzione --merge ma non ci "
+"sono file in attesa di fusione."
+
+#: gitk:343
+msgid ""
+"No files selected: --merge specified but no unmerged files are within file "
+"limit."
+msgstr ""
+"Nessun file selezionato: è stata specificata l'opzione --merge ma i file "
+"specificati non sono in attesa di fusione."
-#: gitk:124
+#: gitk:365 gitk:503
+msgid "Error executing git log:"
+msgstr "Errore nell'esecuzione di git log:"
+
+#: gitk:378
msgid "Reading"
msgstr "Lettura in corso"
-#: gitk:151 gitk:2191
+#: gitk:438 gitk:3462
msgid "Reading commits..."
msgstr "Lettura delle revisioni in corso..."
-#: gitk:275
-msgid "Can't parse git log output:"
-msgstr "Impossibile elaborare i dati di git log:"
-
-#: gitk:386 gitk:2195
+#: gitk:441 gitk:1528 gitk:3465
msgid "No commits selected"
msgstr "Nessuna revisione selezionata"
-#: gitk:500
+#: gitk:1399
+msgid "Can't parse git log output:"
+msgstr "Impossibile elaborare i dati di git log:"
+
+#: gitk:1605
msgid "No commit information available"
msgstr "Nessuna informazione disponibile sulle revisioni"
-#: gitk:599 gitk:621 gitk:1955 gitk:6423 gitk:7923 gitk:8082
+#: gitk:1709 gitk:1731 gitk:3259 gitk:7764 gitk:9293 gitk:9466
msgid "OK"
msgstr "OK"
-#: gitk:623 gitk:1956 gitk:6107 gitk:6178 gitk:6275 gitk:6321 gitk:6425
-#: gitk:7924 gitk:8083
+#: gitk:1733 gitk:3260 gitk:7439 gitk:7510 gitk:7613 gitk:7660 gitk:7766
+#: gitk:9294 gitk:9467
msgid "Cancel"
msgstr "Annulla"
-#: gitk:661
-msgid "File"
-msgstr "File"
-
-#: gitk:663
+#: gitk:1811
msgid "Update"
msgstr "Aggiorna"
-#: gitk:664
+#: gitk:1813
msgid "Reread references"
msgstr "Rileggi riferimenti"
-#: gitk:665
+#: gitk:1814
msgid "List references"
msgstr "Elenca riferimenti"
-#: gitk:666
+#: gitk:1815
msgid "Quit"
msgstr "Esci"
-#: gitk:668
-msgid "Edit"
-msgstr "Modifica"
+#: gitk:1810
+msgid "File"
+msgstr "File"
-#: gitk:669
+#: gitk:1818
msgid "Preferences"
msgstr "Preferenze"
-#: gitk:672 gitk:1892
-msgid "View"
-msgstr "Vista"
+#: gitk:1817
+msgid "Edit"
+msgstr "Modifica"
-#: gitk:673
+#: gitk:1821
msgid "New view..."
msgstr "Nuova vista..."
-#: gitk:674 gitk:2133 gitk:8722
+#: gitk:1822
msgid "Edit view..."
msgstr "Modifica vista..."
-#: gitk:676 gitk:2134 gitk:8723
+#: gitk:1823
msgid "Delete view"
msgstr "Elimina vista"
-#: gitk:678
+#: gitk:1825
msgid "All files"
msgstr "Tutti i file"
-#: gitk:682
-msgid "Help"
-msgstr "Aiuto"
+#: gitk:1820 gitk:3196
+msgid "View"
+msgstr "Vista"
-#: gitk:683 gitk:1317
+#: gitk:1828 gitk:2487
msgid "About gitk"
msgstr "Informazioni su gitk"
-#: gitk:684
+#: gitk:1829
msgid "Key bindings"
msgstr "Scorciatoie da tastiera"
-#: gitk:741
+#: gitk:1827
+msgid "Help"
+msgstr "Aiuto"
+
+#: gitk:1887
msgid "SHA1 ID: "
msgstr "SHA1 ID: "
-#: gitk:791
+#: gitk:1918
+msgid "Row"
+msgstr ""
+
+#: gitk:1949
msgid "Find"
msgstr "Trova"
-#: gitk:792
+#: gitk:1950
msgid "next"
msgstr "succ"
-#: gitk:793
+#: gitk:1951
msgid "prev"
msgstr "prec"
-#: gitk:794
+#: gitk:1952
msgid "commit"
msgstr "revisione"
-#: gitk:797 gitk:799 gitk:2356 gitk:2379 gitk:2403 gitk:4306 gitk:4369
+#: gitk:1955 gitk:1957 gitk:3617 gitk:3640 gitk:3664 gitk:5550 gitk:5621
msgid "containing:"
msgstr "contenente:"
-#: gitk:800 gitk:1778 gitk:1783 gitk:2431
+#: gitk:1958 gitk:2954 gitk:2959 gitk:3692
msgid "touching paths:"
msgstr "che riguarda i percorsi:"
-#: gitk:801 gitk:2436
+#: gitk:1959 gitk:3697
msgid "adding/removing string:"
msgstr "che aggiunge/rimuove la stringa:"
-#: gitk:810 gitk:812
+#: gitk:1968 gitk:1970
msgid "Exact"
msgstr "Esatto"
-#: gitk:812 gitk:2514 gitk:4274
+#: gitk:1970 gitk:3773 gitk:5518
msgid "IgnCase"
msgstr ""
-#: gitk:812 gitk:2405 gitk:2512 gitk:4270
+#: gitk:1970 gitk:3666 gitk:3771 gitk:5514
msgid "Regexp"
msgstr ""
-#: gitk:814 gitk:815 gitk:2533 gitk:2563 gitk:2570 gitk:4380 gitk:4436
+#: gitk:1972 gitk:1973 gitk:3792 gitk:3822 gitk:3829 gitk:5641 gitk:5708
msgid "All fields"
msgstr "Tutti i campi"
-#: gitk:815 gitk:2531 gitk:2563 gitk:4336
+#: gitk:1973 gitk:3790 gitk:3822 gitk:5580
msgid "Headline"
msgstr "Titolo"
-#: gitk:816 gitk:2531 gitk:4336 gitk:4436 gitk:4827
+#: gitk:1974 gitk:3790 gitk:5580 gitk:5708 gitk:6109
msgid "Comments"
msgstr "Commenti"
-#: gitk:816 gitk:2531 gitk:2535 gitk:2570 gitk:4336 gitk:4763 gitk:5956
-#: gitk:5971
+#: gitk:1974 gitk:3790 gitk:3794 gitk:3829 gitk:5580 gitk:6045 gitk:7285
+#: gitk:7300
msgid "Author"
msgstr "Autore"
-#: gitk:816 gitk:2531 gitk:4336 gitk:4765
+#: gitk:1974 gitk:3790 gitk:5580 gitk:6047
msgid "Committer"
msgstr "Revisione creata da"
-#: gitk:845
+#: gitk:2003
msgid "Search"
msgstr "Cerca"
-#: gitk:852
+#: gitk:2010
msgid "Diff"
msgstr ""
-#: gitk:854
+#: gitk:2012
msgid "Old version"
msgstr "Vecchia versione"
-#: gitk:856
+#: gitk:2014
msgid "New version"
msgstr "Nuova versione"
-#: gitk:858
+#: gitk:2016
msgid "Lines of context"
msgstr "Linee di contesto"
-#: gitk:868
+#: gitk:2026
msgid "Ignore space change"
msgstr "Ignora modifiche agli spazi"
-#: gitk:926
+#: gitk:2084
msgid "Patch"
msgstr "Modifiche"
-#: gitk:928
+#: gitk:2086
msgid "Tree"
msgstr "Directory"
-#: gitk:1053 gitk:1068 gitk:6022
+#: gitk:2213 gitk:2226
msgid "Diff this -> selected"
msgstr "Diff questo -> selezionato"
-#: gitk:1055 gitk:1070 gitk:6023
+#: gitk:2214 gitk:2227
msgid "Diff selected -> this"
msgstr "Diff selezionato -> questo"
-#: gitk:1057 gitk:1072 gitk:6024
+#: gitk:2215 gitk:2228
msgid "Make patch"
msgstr "Crea patch"
-#: gitk:1058 gitk:6162
+#: gitk:2216 gitk:7494
msgid "Create tag"
msgstr "Crea etichetta"
-#: gitk:1059 gitk:6255
+#: gitk:2217 gitk:7593
msgid "Write commit to file"
msgstr "Scrivi revisione in un file"
-#: gitk:1060 gitk:6309
+#: gitk:2218 gitk:7647
msgid "Create new branch"
msgstr "Crea un nuovo ramo"
-#: gitk:1061
+#: gitk:2219
msgid "Cherry-pick this commit"
msgstr "Porta questa revisione in cima al ramo attuale"
-#: gitk:1063
+#: gitk:2220
msgid "Reset HEAD branch to here"
msgstr "Aggiorna il ramo HEAD a questa revisione"
-#: gitk:1079
+#: gitk:2234
msgid "Check out this branch"
msgstr "Attiva questo ramo"
-#: gitk:1081
+#: gitk:2235
msgid "Remove this branch"
msgstr "Elimina questo ramo"
-#: gitk:1087
+#: gitk:2242
msgid "Highlight this too"
msgstr "Evidenzia anche questo"
-#: gitk:1089
+#: gitk:2243
msgid "Highlight this only"
msgstr "Evidenzia solo questo"
-#: gitk:1318
+#: gitk:2245
+msgid "Blame parent commit"
+msgstr ""
+
+#: gitk:2488
msgid ""
"\n"
"Gitk - a commit viewer for git\n"
"\n"
-"Copyright © 2005-2006 Paul Mackerras\n"
+"Copyright © 2005-2008 Paul Mackerras\n"
"\n"
"Use and redistribute under the terms of the GNU General Public License"
msgstr ""
"\n"
"Gitk - un visualizzatore di revisioni per git\n"
"\n"
-"Copyright © 2005-2006 Paul Mackerras\n"
+"Copyright © 2005-2008 Paul Mackerras\n"
"\n"
"Utilizzo e redistribuzione permessi sotto i termini della GNU General Public "
"License"
-#: gitk:1326 gitk:1387 gitk:6581
+#: gitk:2496 gitk:2557 gitk:7943
msgid "Close"
msgstr "Chiudi"
-#: gitk:1345
+#: gitk:2515
msgid "Gitk key bindings"
msgstr "Scorciatoie da tastiera di Gitk"
-#: gitk:1347
+#: gitk:2517
msgid "Gitk key bindings:"
msgstr "Scorciatoie da tastiera di Gitk:"
-#: gitk:1349
+#: gitk:2519
#, tcl-format
msgid "<%s-Q>\t\tQuit"
msgstr "<%s-Q>\t\tEsci"
-#: gitk:1350
+#: gitk:2520
msgid "<Home>\t\tMove to first commit"
msgstr "<Home>\t\tVai alla prima revisione"
-#: gitk:1351
+#: gitk:2521
msgid "<End>\t\tMove to last commit"
msgstr "<End>\t\tVai all'ultima revisione"
-#: gitk:1352
+#: gitk:2522
msgid "<Up>, p, i\tMove up one commit"
msgstr "<Up>, p, i\tVai più in alto di una revisione"
-#: gitk:1353
+#: gitk:2523
msgid "<Down>, n, k\tMove down one commit"
msgstr "<Down>, n, k\tVai più in basso di una revisione"
-#: gitk:1354
+#: gitk:2524
msgid "<Left>, z, j\tGo back in history list"
msgstr "<Left>, z, j\tTorna indietro nella cronologia"
-#: gitk:1355
+#: gitk:2525
msgid "<Right>, x, l\tGo forward in history list"
msgstr "<Right>, x, l\tVai avanti nella cronologia"
-#: gitk:1356
+#: gitk:2526
msgid "<PageUp>\tMove up one page in commit list"
msgstr "<PageUp>\tVai più in alto di una pagina nella lista delle revisioni"
-#: gitk:1357
+#: gitk:2527
msgid "<PageDown>\tMove down one page in commit list"
msgstr "<PageDown>\tVai più in basso di una pagina nella lista delle revisioni"
-#: gitk:1358
+#: gitk:2528
#, tcl-format
msgid "<%s-Home>\tScroll to top of commit list"
msgstr "<%s-Home>\tScorri alla cima della lista delle revisioni"
-#: gitk:1359
+#: gitk:2529
#, tcl-format
msgid "<%s-End>\tScroll to bottom of commit list"
msgstr "<%s-End>\tScorri alla fine della lista delle revisioni"
-#: gitk:1360
+#: gitk:2530
#, tcl-format
msgid "<%s-Up>\tScroll commit list up one line"
msgstr "<%s-Up>\tScorri la lista delle revisioni in alto di una riga"
-#: gitk:1361
+#: gitk:2531
#, tcl-format
msgid "<%s-Down>\tScroll commit list down one line"
msgstr "<%s-Down>\tScorri la lista delle revisioni in basso di una riga"
-#: gitk:1362
+#: gitk:2532
#, tcl-format
msgid "<%s-PageUp>\tScroll commit list up one page"
msgstr "<%s-PageUp>\tScorri la lista delle revisioni in alto di una pagina"
-#: gitk:1363
+#: gitk:2533
#, tcl-format
msgid "<%s-PageDown>\tScroll commit list down one page"
msgstr "<%s-PageDown>\tScorri la lista delle revisioni in basso di una pagina"
-#: gitk:1364
+#: gitk:2534
msgid "<Shift-Up>\tFind backwards (upwards, later commits)"
msgstr "<Shift-Up>\tTrova all'indietro (verso l'alto, revisioni successive)"
-#: gitk:1365
+#: gitk:2535
msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)"
msgstr "<Shift-Down>\tTrova in avanti (verso il basso, revisioni precedenti)"
-#: gitk:1366
+#: gitk:2536
msgid "<Delete>, b\tScroll diff view up one page"
msgstr "<Delete>, b\tScorri la vista delle differenze in alto di una pagina"
-#: gitk:1367
+#: gitk:2537
msgid "<Backspace>\tScroll diff view up one page"
msgstr "<Backspace>\tScorri la vista delle differenze in alto di una pagina"
-#: gitk:1368
+#: gitk:2538
msgid "<Space>\t\tScroll diff view down one page"
msgstr "<Space>\t\tScorri la vista delle differenze in basso di una pagina"
-#: gitk:1369
+#: gitk:2539
msgid "u\t\tScroll diff view up 18 lines"
msgstr "u\t\tScorri la vista delle differenze in alto di 18 linee"
-#: gitk:1370
+#: gitk:2540
msgid "d\t\tScroll diff view down 18 lines"
msgstr "d\t\tScorri la vista delle differenze in basso di 18 linee"
-#: gitk:1371
+#: gitk:2541
#, tcl-format
msgid "<%s-F>\t\tFind"
msgstr "<%s-F>\t\tTrova"
-#: gitk:1372
+#: gitk:2542
#, tcl-format
msgid "<%s-G>\t\tMove to next find hit"
msgstr "<%s-G>\t\tTrova in avanti"
-#: gitk:1373
+#: gitk:2543
msgid "<Return>\tMove to next find hit"
msgstr "<Return>\tTrova in avanti"
-#: gitk:1374
+#: gitk:2544
msgid "/\t\tMove to next find hit, or redo find"
msgstr "/\t\tTrova in avanti, o cerca di nuovo"
-#: gitk:1375
+#: gitk:2545
msgid "?\t\tMove to previous find hit"
msgstr "?\t\tTrova all'indietro"
-#: gitk:1376
+#: gitk:2546
msgid "f\t\tScroll diff view to next file"
msgstr "f\t\tScorri la vista delle differenze al file successivo"
-#: gitk:1377
+#: gitk:2547
#, tcl-format
msgid "<%s-S>\t\tSearch for next hit in diff view"
msgstr "<%s-S>\t\tCerca in avanti nella vista delle differenze"
-#: gitk:1378
+#: gitk:2548
#, tcl-format
msgid "<%s-R>\t\tSearch for previous hit in diff view"
msgstr "<%s-R>\t\tCerca all'indietro nella vista delle differenze"
-#: gitk:1379
+#: gitk:2549
#, tcl-format
msgid "<%s-KP+>\tIncrease font size"
msgstr "<%s-KP+>\tAumenta grandezza carattere"
-#: gitk:1380
+#: gitk:2550
#, tcl-format
msgid "<%s-plus>\tIncrease font size"
msgstr "<%s-plus>\tAumenta grandezza carattere"
-#: gitk:1381
+#: gitk:2551
#, tcl-format
msgid "<%s-KP->\tDecrease font size"
msgstr "<%s-KP->\tDiminuisci grandezza carattere"
-#: gitk:1382
+#: gitk:2552
#, tcl-format
msgid "<%s-minus>\tDecrease font size"
msgstr "<%s-minus>\tDiminuisci grandezza carattere"
-#: gitk:1383
+#: gitk:2553
msgid "<F5>\t\tUpdate"
msgstr "<F5>\t\tAggiorna"
-#: gitk:1896
+#: gitk:3200
msgid "Gitk view definition"
msgstr "Scelta vista Gitk"
-#: gitk:1921
+#: gitk:3225
msgid "Name"
msgstr "Nome"
-#: gitk:1924
+#: gitk:3228
msgid "Remember this view"
msgstr "Ricorda questa vista"
-#: gitk:1928
-msgid "Commits to include (arguments to git rev-list):"
-msgstr "Revisioni da includere (argomenti di git rev-list):"
+#: gitk:3232
+msgid "Commits to include (arguments to git log):"
+msgstr "Revisioni da includere (argomenti di git log):"
-#: gitk:1935
+#: gitk:3239
msgid "Command to generate more commits to include:"
msgstr "Comando che genera altre revisioni da visualizzare:"
-#: gitk:1942
+#: gitk:3246
msgid "Enter files and directories to include, one per line:"
msgstr "Inserire file e directory da includere, uno per riga:"
-#: gitk:1989
+#: gitk:3293
msgid "Error in commit selection arguments:"
msgstr "Errore negli argomenti di selezione delle revisioni:"
-#: gitk:2043 gitk:2127 gitk:2583 gitk:2597 gitk:3781 gitk:8688 gitk:8689
+#: gitk:3347 gitk:3399 gitk:3842 gitk:3856 gitk:5060 gitk:10141 gitk:10142
msgid "None"
msgstr "Nessuno"
-#: gitk:2531 gitk:4336 gitk:5958 gitk:5973
+#: gitk:3790 gitk:5580 gitk:7287 gitk:7302
msgid "Date"
msgstr "Data"
-#: gitk:2531 gitk:4336
+#: gitk:3790 gitk:5580
msgid "CDate"
msgstr ""
-#: gitk:2680 gitk:2685
+#: gitk:3939 gitk:3944
msgid "Descendant"
msgstr "Discendente"
-#: gitk:2681
+#: gitk:3940
msgid "Not descendant"
msgstr "Non discendente"
-#: gitk:2688 gitk:2693
+#: gitk:3947 gitk:3952
msgid "Ancestor"
msgstr "Ascendente"
-#: gitk:2689
+#: gitk:3948
msgid "Not ancestor"
msgstr "Non ascendente"
-#: gitk:2924
+#: gitk:4187
msgid "Local changes checked in to index but not committed"
msgstr "Modifiche locali presenti nell'indice ma non nell'archivio"
-#: gitk:2954
+#: gitk:4220
msgid "Local uncommitted changes, not checked in to index"
msgstr "Modifiche locali non presenti né nell'archivio né nell'indice"
-#: gitk:4305
+#: gitk:5549
msgid "Searching"
msgstr "Ricerca in corso"
-#: gitk:4767
+#: gitk:6049
msgid "Tags:"
msgstr "Etichette:"
-#: gitk:4784 gitk:4790 gitk:5951
+#: gitk:6066 gitk:6072 gitk:7280
msgid "Parent"
msgstr "Genitore"
-#: gitk:4795
+#: gitk:6077
msgid "Child"
msgstr "Figlio"
-#: gitk:4804
+#: gitk:6086
msgid "Branch"
msgstr "Ramo"
-#: gitk:4807
+#: gitk:6089
msgid "Follows"
msgstr "Segue"
-#: gitk:4810
+#: gitk:6092
msgid "Precedes"
msgstr "Precede"
-#: gitk:5093
+#: gitk:6378
msgid "Error getting merge diffs:"
msgstr "Errore nella lettura delle differenze di fusione:"
-#: gitk:5778
+#: gitk:7113
msgid "Goto:"
msgstr "Vai a:"
-#: gitk:5780
+#: gitk:7115
msgid "SHA1 ID:"
msgstr "SHA1 ID:"
-#: gitk:5805
+#: gitk:7134
#, tcl-format
msgid "Short SHA1 id %s is ambiguous"
msgstr "La SHA1 id abbreviata %s è ambigua"
-#: gitk:5817
+#: gitk:7146
#, tcl-format
msgid "SHA1 id %s is not known"
msgstr "La SHA1 id %s è sconosciuta"
-#: gitk:5819
+#: gitk:7148
#, tcl-format
msgid "Tag/Head %s is not known"
msgstr "L'etichetta/ramo %s è sconosciuto"
-#: gitk:5961
+#: gitk:7290
msgid "Children"
msgstr "Figli"
-#: gitk:6018
+#: gitk:7347
#, tcl-format
msgid "Reset %s branch to here"
msgstr "Aggiorna il ramo %s a questa revisione"
-#: gitk:6049
+#: gitk:7349
+msgid "Detached head: can't reset"
+msgstr ""
+
+#: gitk:7381
msgid "Top"
msgstr "Inizio"
-#: gitk:6050
+#: gitk:7382
msgid "From"
msgstr "Da"
-#: gitk:6055
+#: gitk:7387
msgid "To"
msgstr "A"
-#: gitk:6078
+#: gitk:7410
msgid "Generate patch"
msgstr "Genera patch"
-#: gitk:6080
+#: gitk:7412
msgid "From:"
msgstr "Da:"
-#: gitk:6089
+#: gitk:7421
msgid "To:"
msgstr "A:"
-#: gitk:6098
+#: gitk:7430
msgid "Reverse"
msgstr "Inverti"
-#: gitk:6100 gitk:6269
+#: gitk:7432 gitk:7607
msgid "Output file:"
msgstr "Scrivi sul file:"
-#: gitk:6106
+#: gitk:7438
msgid "Generate"
msgstr "Genera"
-#: gitk:6142
+#: gitk:7474
msgid "Error creating patch:"
msgstr "Errore nella creazione della patch:"
-#: gitk:6164 gitk:6257 gitk:6311
+#: gitk:7496 gitk:7595 gitk:7649
msgid "ID:"
msgstr "ID:"
-#: gitk:6173
+#: gitk:7505
msgid "Tag name:"
msgstr "Nome etichetta:"
-#: gitk:6177 gitk:6320
+#: gitk:7509 gitk:7659
msgid "Create"
msgstr "Crea"
-#: gitk:6192
+#: gitk:7524
msgid "No tag name specified"
msgstr "Nessuna etichetta specificata"
-#: gitk:6196
+#: gitk:7528
#, tcl-format
msgid "Tag \"%s\" already exists"
msgstr "L'etichetta \"%s\" esiste già"
-#: gitk:6202
+#: gitk:7534
msgid "Error creating tag:"
msgstr "Errore nella creazione dell'etichetta:"
-#: gitk:6266
+#: gitk:7604
msgid "Command:"
msgstr "Comando:"
-#: gitk:6274
+#: gitk:7612
msgid "Write"
msgstr "Scrivi"
-#: gitk:6290
+#: gitk:7628
msgid "Error writing commit:"
msgstr "Errore nella scrittura della revisione:"
-#: gitk:6316
+#: gitk:7654
msgid "Name:"
msgstr "Nome:"
-#: gitk:6335
+#: gitk:7674
msgid "Please specify a name for the new branch"
msgstr "Specificare un nome per il nuovo ramo"
-#: gitk:6364
+#: gitk:7703
#, tcl-format
msgid "Commit %s is already included in branch %s -- really re-apply it?"
msgstr "La revisione %s è già inclusa nel ramo %s -- applicarla di nuovo?"
-#: gitk:6369
+#: gitk:7708
msgid "Cherry-picking"
msgstr ""
-#: gitk:6381
+#: gitk:7720
msgid "No changes committed"
msgstr "Nessuna modifica archiviata"
-#: gitk:6404
+#: gitk:7745
msgid "Confirm reset"
msgstr "Conferma git reset"
-#: gitk:6406
+#: gitk:7747
#, tcl-format
msgid "Reset branch %s to %s?"
msgstr "Aggiornare il ramo %s a %s?"
-#: gitk:6410
+#: gitk:7751
msgid "Reset type:"
msgstr "Tipo di aggiornamento:"
-#: gitk:6414
+#: gitk:7755
msgid "Soft: Leave working tree and index untouched"
msgstr "Soft: Lascia la direcory di lavoro e l'indice come sono"
-#: gitk:6417
+#: gitk:7758
msgid "Mixed: Leave working tree untouched, reset index"
msgstr "Mixed: Lascia la directory di lavoro come è, aggiorna l'indice"
-#: gitk:6420
+#: gitk:7761
msgid ""
"Hard: Reset working tree and index\n"
"(discard ALL local changes)"
@@ -693,19 +723,19 @@ msgstr ""
"Hard: Aggiorna la directory di lavoro e l'indice\n"
"(abbandona TUTTE le modifiche locali)"
-#: gitk:6436
+#: gitk:7777
msgid "Resetting"
msgstr "git reset in corso"
-#: gitk:6493
+#: gitk:7834
msgid "Checking out"
msgstr "Attivazione in corso"
-#: gitk:6523
+#: gitk:7885
msgid "Cannot delete the currently checked-out branch"
msgstr "Impossibile cancellare il ramo attualmente attivo"
-#: gitk:6529
+#: gitk:7891
#, tcl-format
msgid ""
"The commits on branch %s aren't on any other branch.\n"
@@ -714,16 +744,16 @@ msgstr ""
"Le revisioni nel ramo %s non sono presenti su altri rami.\n"
"Cancellare il ramo %s?"
-#: gitk:6560
+#: gitk:7922
#, tcl-format
msgid "Tags and heads: %s"
msgstr "Etichette e rami: %s"
-#: gitk:6574
+#: gitk:7936
msgid "Filter"
msgstr "Filtro"
-#: gitk:6868
+#: gitk:8230
msgid ""
"Error reading commit topology information; branch and preceding/following "
"tag information will be incomplete."
@@ -731,117 +761,129 @@ msgstr ""
"Errore nella lettura della topologia delle revisioni: le informazioni sul "
"ramo e le etichette precedenti e seguenti saranno incomplete."
-#: gitk:7852
+#: gitk:9216
msgid "Tag"
msgstr "Etichetta"
-#: gitk:7852
+#: gitk:9216
msgid "Id"
msgstr "Id"
-#: gitk:7892
+#: gitk:9262
msgid "Gitk font chooser"
msgstr "Scelta caratteri gitk"
-#: gitk:7909
+#: gitk:9279
msgid "B"
msgstr "B"
-#: gitk:7912
+#: gitk:9282
msgid "I"
msgstr "I"
-#: gitk:8005
+#: gitk:9375
msgid "Gitk preferences"
msgstr "Preferenze gitk"
-#: gitk:8006
+#: gitk:9376
msgid "Commit list display options"
msgstr "Opzioni visualizzazione dell'elenco revisioni"
-#: gitk:8009
+#: gitk:9379
msgid "Maximum graph width (lines)"
msgstr "Larghezza massima del grafico (in linee)"
-#: gitk:8013
+#: gitk:9383
#, tcl-format
msgid "Maximum graph width (% of pane)"
msgstr "Larghezza massima del grafico (% del pannello)"
-#: gitk:8018
+#: gitk:9388
msgid "Show local changes"
msgstr "Mostra modifiche locali"
-#: gitk:8023
+#: gitk:9393
msgid "Auto-select SHA1"
msgstr "Seleziona automaticamente SHA1 hash"
-#: gitk:8028
+#: gitk:9398
msgid "Diff display options"
msgstr "Opzioni di visualizzazione delle differenze"
-#: gitk:8030
+#: gitk:9400
msgid "Tab spacing"
msgstr "Spaziatura tabulazioni"
-#: gitk:8034
+#: gitk:9404
msgid "Display nearby tags"
msgstr "Mostra etichette vicine"
-#: gitk:8039
+#: gitk:9409
msgid "Limit diffs to listed paths"
msgstr "Limita le differenze ai percorsi elencati"
-#: gitk:8044
+#: gitk:9414
+msgid "Support per-file encodings"
+msgstr ""
+
+#: gitk:9421
+msgid "External diff tool"
+msgstr ""
+
+#: gitk:9423
+msgid "Choose..."
+msgstr ""
+
+#: gitk:9428
msgid "Colors: press to choose"
msgstr "Colori: premere per scegliere"
-#: gitk:8047
+#: gitk:9431
msgid "Background"
msgstr "Sfondo"
-#: gitk:8051
+#: gitk:9435
msgid "Foreground"
msgstr "Primo piano"
-#: gitk:8055
+#: gitk:9439
msgid "Diff: old lines"
msgstr "Diff: vecchie linee"
-#: gitk:8060
+#: gitk:9444
msgid "Diff: new lines"
msgstr "Diff: nuove linee"
-#: gitk:8065
+#: gitk:9449
msgid "Diff: hunk header"
msgstr "Diff: intestazione della sezione"
-#: gitk:8071
+#: gitk:9455
msgid "Select bg"
msgstr "Sfondo selezione"
-#: gitk:8075
+#: gitk:9459
msgid "Fonts: press to choose"
msgstr "Carattere: premere per scegliere"
-#: gitk:8077
+#: gitk:9461
msgid "Main font"
msgstr "Carattere principale"
-#: gitk:8078
+#: gitk:9462
msgid "Diff display font"
msgstr "Carattere per differenze"
-#: gitk:8079
+#: gitk:9463
msgid "User interface font"
msgstr "Carattere per interfaccia utente"
-#: gitk:8095
+#: gitk:9488
#, tcl-format
msgid "Gitk: choose color for %s"
msgstr "Gitk: scegliere un colore per %s"
-#: gitk:8476
+#: gitk:9934
msgid ""
"Sorry, gitk cannot run with this version of Tcl/Tk.\n"
" Gitk requires at least Tcl/Tk 8.4."
@@ -849,42 +891,24 @@ msgstr ""
"Questa versione di Tcl/Tk non può avviare gitk.\n"
" Gitk richiede Tcl/Tk versione 8.4 o superiore."
-#: gitk:8565
+#: gitk:10047
msgid "Cannot find a git repository here."
msgstr "Archivio git non trovato."
-#: gitk:8569
+#: gitk:10051
#, tcl-format
msgid "Cannot find the git directory \"%s\"."
msgstr "Directory git \"%s\" non trovata."
-#: gitk:8612
+#: gitk:10098
#, tcl-format
msgid "Ambiguous argument '%s': both revision and filename"
msgstr "Argomento ambiguo: '%s' è sia revisione che nome di file"
-#: gitk:8624
+#: gitk:10110
msgid "Bad arguments to gitk:"
msgstr "Gitk: argomenti errati:"
-#: gitk:8636
-msgid "Couldn't get list of unmerged files:"
-msgstr "Impossibile ottenere l'elenco dei file in attesa di fusione:"
-
-#: gitk:8652
-msgid "No files selected: --merge specified but no files are unmerged."
-msgstr ""
-"Nessun file selezionato: è stata specificata l'opzione --merge ma non ci "
-"sono file in attesa di fusione."
-
-#: gitk:8655
-msgid ""
-"No files selected: --merge specified but no unmerged files are within file "
-"limit."
-msgstr ""
-"Nessun file selezionato: è stata specificata l'opzione --merge ma i file "
-"specificati non sono in attesa di fusione."
-
-#: gitk:8716
+#: gitk:10170
msgid "Command line"
msgstr "Linea di comando"
diff --git a/gitk-git/po/sv.po b/gitk-git/po/sv.po
index e1ecfb7586..947b53f6b0 100644
--- a/gitk-git/po/sv.po
+++ b/gitk-git/po/sv.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: sv\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-08-03 18:58+0200\n"
+"POT-Creation-Date: 2008-10-18 22:03+1100\n"
"PO-Revision-Date: 2008-08-03 19:03+0200\n"
"Last-Translator: Mikael Magnusson <mikachu@gmail.com>\n"
"Language-Team: Swedish <sv@li.org>\n"
@@ -16,17 +16,17 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: gitk:102
+#: gitk:113
msgid "Couldn't get list of unmerged files:"
msgstr "Kunde inta hämta lista över ej sammanslagna filer:"
-#: gitk:329
+#: gitk:340
msgid "No files selected: --merge specified but no files are unmerged."
msgstr ""
"Inga filer valdes: --merge angavs men det finns inga filer som inte har "
"slagits samman."
-#: gitk:332
+#: gitk:343
msgid ""
"No files selected: --merge specified but no unmerged files are within file "
"limit."
@@ -34,257 +34,261 @@ msgstr ""
"Inga filer valdes: --merge angavs men det finns inga filer inom "
"filbegränsningen."
-#: gitk:354
+#: gitk:365 gitk:503
msgid "Error executing git log:"
msgstr "Fel vid körning av git log:"
-#: gitk:369
+#: gitk:378
msgid "Reading"
msgstr "Läser"
-#: gitk:400 gitk:3356
+#: gitk:438 gitk:3462
msgid "Reading commits..."
msgstr "Läser incheckningar..."
-#: gitk:403 gitk:1480 gitk:3359
+#: gitk:441 gitk:1528 gitk:3465
msgid "No commits selected"
msgstr "Inga incheckningar markerade"
-#: gitk:1358
+#: gitk:1399
msgid "Can't parse git log output:"
msgstr "Kan inte tolka utdata från git log:"
-#: gitk:1557
+#: gitk:1605
msgid "No commit information available"
msgstr "Ingen incheckningsinformation är tillgänglig"
-#: gitk:1654 gitk:1676 gitk:3150 gitk:7620 gitk:9149 gitk:9317
+#: gitk:1709 gitk:1731 gitk:3259 gitk:7764 gitk:9293 gitk:9466
msgid "OK"
msgstr "OK"
-#: gitk:1678 gitk:3151 gitk:7296 gitk:7367 gitk:7470 gitk:7516 gitk:7622
-#: gitk:9150 gitk:9318
+#: gitk:1733 gitk:3260 gitk:7439 gitk:7510 gitk:7613 gitk:7660 gitk:7766
+#: gitk:9294 gitk:9467
msgid "Cancel"
msgstr "Avbryt"
-#: gitk:1716
-msgid "File"
-msgstr "Arkiv"
-
-#: gitk:1718
+#: gitk:1811
msgid "Update"
msgstr "Uppdatera"
-#: gitk:1719
+#: gitk:1812
msgid "Reload"
msgstr "Ladda om"
-#: gitk:1720
+#: gitk:1813
msgid "Reread references"
msgstr "Läs om referenser"
-#: gitk:1721
+#: gitk:1814
msgid "List references"
msgstr "Visa referenser"
-#: gitk:1722
+#: gitk:1815
msgid "Quit"
msgstr "Avsluta"
-#: gitk:1724
-msgid "Edit"
-msgstr "Redigera"
+#: gitk:1810
+msgid "File"
+msgstr "Arkiv"
-#: gitk:1725
+#: gitk:1818
msgid "Preferences"
msgstr "Inställningar"
-#: gitk:1728 gitk:3087
-msgid "View"
-msgstr "Visa"
+#: gitk:1817
+msgid "Edit"
+msgstr "Redigera"
-#: gitk:1729
+#: gitk:1821
msgid "New view..."
msgstr "Ny vy..."
-#: gitk:1730 gitk:3298 gitk:9932
+#: gitk:1822
msgid "Edit view..."
msgstr "Ändra vy..."
-#: gitk:1732 gitk:3299 gitk:9933
+#: gitk:1823
msgid "Delete view"
msgstr "Ta bort vy"
-#: gitk:1734
+#: gitk:1825
msgid "All files"
msgstr "Alla filer"
-#: gitk:1738
-msgid "Help"
-msgstr "Hjälp"
+#: gitk:1820 gitk:3196
+msgid "View"
+msgstr "Visa"
-#: gitk:1739 gitk:2399
+#: gitk:1828 gitk:2487
msgid "About gitk"
msgstr "Om gitk"
-#: gitk:1740
+#: gitk:1829
msgid "Key bindings"
msgstr "Tangentbordsbindningar"
-#: gitk:1797
+#: gitk:1827
+msgid "Help"
+msgstr "Hjälp"
+
+#: gitk:1887
msgid "SHA1 ID: "
msgstr "SHA1-id: "
-#: gitk:1828
+#: gitk:1918
msgid "Row"
msgstr "Rad"
-#: gitk:1859
+#: gitk:1949
msgid "Find"
msgstr "Sök"
-#: gitk:1860
+#: gitk:1950
msgid "next"
msgstr "nästa"
-#: gitk:1861
+#: gitk:1951
msgid "prev"
msgstr "föreg"
-#: gitk:1862
+#: gitk:1952
msgid "commit"
msgstr "incheckning"
-#: gitk:1865 gitk:1867 gitk:3511 gitk:3534 gitk:3558 gitk:5441 gitk:5512
+#: gitk:1955 gitk:1957 gitk:3617 gitk:3640 gitk:3664 gitk:5550 gitk:5621
msgid "containing:"
msgstr "som innehåller:"
-#: gitk:1868 gitk:2866 gitk:2871 gitk:3586
+#: gitk:1958 gitk:2954 gitk:2959 gitk:3692
msgid "touching paths:"
msgstr "som rör sökväg:"
-#: gitk:1869 gitk:3591
+#: gitk:1959 gitk:3697
msgid "adding/removing string:"
msgstr "som lägger/till tar bort sträng:"
-#: gitk:1878 gitk:1880
+#: gitk:1968 gitk:1970
msgid "Exact"
msgstr "Exakt"
-#: gitk:1880 gitk:3667 gitk:5409
+#: gitk:1970 gitk:3773 gitk:5518
msgid "IgnCase"
msgstr "IgnVersaler"
-#: gitk:1880 gitk:3560 gitk:3665 gitk:5405
+#: gitk:1970 gitk:3666 gitk:3771 gitk:5514
msgid "Regexp"
msgstr "Reg.uttr."
-#: gitk:1882 gitk:1883 gitk:3686 gitk:3716 gitk:3723 gitk:5532 gitk:5599
+#: gitk:1972 gitk:1973 gitk:3792 gitk:3822 gitk:3829 gitk:5641 gitk:5708
msgid "All fields"
msgstr "Alla fält"
-#: gitk:1883 gitk:3684 gitk:3716 gitk:5471
+#: gitk:1973 gitk:3790 gitk:3822 gitk:5580
msgid "Headline"
msgstr "Rubrik"
-#: gitk:1884 gitk:3684 gitk:5471 gitk:5599 gitk:6000
+#: gitk:1974 gitk:3790 gitk:5580 gitk:5708 gitk:6109
msgid "Comments"
msgstr "Kommentarer"
-#: gitk:1884 gitk:3684 gitk:3688 gitk:3723 gitk:5471 gitk:5936 gitk:7142
-#: gitk:7157
+#: gitk:1974 gitk:3790 gitk:3794 gitk:3829 gitk:5580 gitk:6045 gitk:7285
+#: gitk:7300
msgid "Author"
msgstr "Författare"
-#: gitk:1884 gitk:3684 gitk:5471 gitk:5938
+#: gitk:1974 gitk:3790 gitk:5580 gitk:6047
msgid "Committer"
msgstr "Incheckare"
-#: gitk:1913
+#: gitk:2003
msgid "Search"
msgstr "Sök"
-#: gitk:1920
+#: gitk:2010
msgid "Diff"
msgstr "Diff"
-#: gitk:1922
+#: gitk:2012
msgid "Old version"
msgstr "Gammal version"
-#: gitk:1924
+#: gitk:2014
msgid "New version"
msgstr "Ny version"
-#: gitk:1926
+#: gitk:2016
msgid "Lines of context"
msgstr "Rader sammanhang"
-#: gitk:1936
+#: gitk:2026
msgid "Ignore space change"
msgstr "Ignorera ändringar i blanksteg"
-#: gitk:1994
+#: gitk:2084
msgid "Patch"
msgstr "Patch"
-#: gitk:1996
+#: gitk:2086
msgid "Tree"
msgstr "Träd"
-#: gitk:2121 gitk:2136 gitk:7211
+#: gitk:2213 gitk:2226
msgid "Diff this -> selected"
msgstr "Diff denna -> markerad"
-#: gitk:2123 gitk:2138 gitk:7212
+#: gitk:2214 gitk:2227
msgid "Diff selected -> this"
msgstr "Diff markerad -> denna"
-#: gitk:2125 gitk:2140 gitk:7213
+#: gitk:2215 gitk:2228
msgid "Make patch"
msgstr "Skapa patch"
-#: gitk:2126 gitk:7351
+#: gitk:2216 gitk:7494
msgid "Create tag"
msgstr "Skapa tagg"
-#: gitk:2127 gitk:7450
+#: gitk:2217 gitk:7593
msgid "Write commit to file"
msgstr "Skriv incheckning till fil"
-#: gitk:2128 gitk:7504
+#: gitk:2218 gitk:7647
msgid "Create new branch"
msgstr "Skapa ny gren"
-#: gitk:2129
+#: gitk:2219
msgid "Cherry-pick this commit"
msgstr "Plocka denna incheckning"
-#: gitk:2131
+#: gitk:2220
msgid "Reset HEAD branch to here"
msgstr "Återställ HEAD-grenen hit"
-#: gitk:2147
+#: gitk:2234
msgid "Check out this branch"
msgstr "Checka ut denna gren"
-#: gitk:2149
+#: gitk:2235
msgid "Remove this branch"
msgstr "Ta bort denna gren"
-#: gitk:2155
+#: gitk:2242
msgid "Highlight this too"
msgstr "Markera även detta"
-#: gitk:2157
+#: gitk:2243
msgid "Highlight this only"
msgstr "Markera bara detta"
-#: gitk:2159
+#: gitk:2244
msgid "External diff"
msgstr "Extern diff"
-#: gitk:2400
+#: gitk:2245
+msgid "Blame parent commit"
+msgstr ""
+
+#: gitk:2488
msgid ""
"\n"
"Gitk - a commit viewer for git\n"
@@ -300,427 +304,427 @@ msgstr ""
"\n"
"Använd och vidareförmedla enligt villkoren i GNU General Public License"
-#: gitk:2408 gitk:2469 gitk:7799
+#: gitk:2496 gitk:2557 gitk:7943
msgid "Close"
msgstr "Stäng"
-#: gitk:2427
+#: gitk:2515
msgid "Gitk key bindings"
msgstr "Tangentbordsbindningar för Gitk"
-#: gitk:2429
+#: gitk:2517
msgid "Gitk key bindings:"
msgstr "Tangentbordsbindningar för Gitk:"
-#: gitk:2431
+#: gitk:2519
#, tcl-format
msgid "<%s-Q>\t\tQuit"
msgstr "<%s-Q>\t\tAvsluta"
-#: gitk:2432
+#: gitk:2520
msgid "<Home>\t\tMove to first commit"
msgstr "<Home>\t\tGå till första incheckning"
-#: gitk:2433
+#: gitk:2521
msgid "<End>\t\tMove to last commit"
msgstr "<End>\t\tGÃ¥ till sista incheckning"
-#: gitk:2434
+#: gitk:2522
msgid "<Up>, p, i\tMove up one commit"
msgstr "<Upp>, p, i\tGÃ¥ en incheckning upp"
-#: gitk:2435
+#: gitk:2523
msgid "<Down>, n, k\tMove down one commit"
msgstr "<Ned>, n, k\tGÃ¥ en incheckning ned"
-#: gitk:2436
+#: gitk:2524
msgid "<Left>, z, j\tGo back in history list"
msgstr "<Vänster>, z, j\tGå bakåt i historiken"
-#: gitk:2437
+#: gitk:2525
msgid "<Right>, x, l\tGo forward in history list"
msgstr "<Höger>, x, l\tGå framåt i historiken"
-#: gitk:2438
+#: gitk:2526
msgid "<PageUp>\tMove up one page in commit list"
msgstr "<PageUp>\tGÃ¥ upp en sida i incheckningslistan"
-#: gitk:2439
+#: gitk:2527
msgid "<PageDown>\tMove down one page in commit list"
msgstr "<PageDown>\tGÃ¥ ned en sida i incheckningslistan"
-#: gitk:2440
+#: gitk:2528
#, tcl-format
msgid "<%s-Home>\tScroll to top of commit list"
msgstr "<%s-Home>\tRulla till början av incheckningslistan"
-#: gitk:2441
+#: gitk:2529
#, tcl-format
msgid "<%s-End>\tScroll to bottom of commit list"
msgstr "<%s-End>\tRulla till slutet av incheckningslistan"
-#: gitk:2442
+#: gitk:2530
#, tcl-format
msgid "<%s-Up>\tScroll commit list up one line"
msgstr "<%s-Upp>\tRulla incheckningslistan upp ett steg"
-#: gitk:2443
+#: gitk:2531
#, tcl-format
msgid "<%s-Down>\tScroll commit list down one line"
msgstr "<%s-Ned>\tRulla incheckningslistan ned ett steg"
-#: gitk:2444
+#: gitk:2532
#, tcl-format
msgid "<%s-PageUp>\tScroll commit list up one page"
msgstr "<%s-PageUp>\tRulla incheckningslistan upp en sida"
-#: gitk:2445
+#: gitk:2533
#, tcl-format
msgid "<%s-PageDown>\tScroll commit list down one page"
msgstr "<%s-PageDown>\tRulla incheckningslistan ned en sida"
-#: gitk:2446
+#: gitk:2534
msgid "<Shift-Up>\tFind backwards (upwards, later commits)"
msgstr "<Skift-Upp>\tSök bakåt (uppåt, senare incheckningar)"
-#: gitk:2447
+#: gitk:2535
msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)"
msgstr "<Skift-Ned>\tSök framåt (nedåt, tidigare incheckningar)"
-#: gitk:2448
+#: gitk:2536
msgid "<Delete>, b\tScroll diff view up one page"
msgstr "<Delete>, b\tRulla diffvisningen upp en sida"
-#: gitk:2449
+#: gitk:2537
msgid "<Backspace>\tScroll diff view up one page"
msgstr "<Baksteg>\tRulla diffvisningen upp en sida"
-#: gitk:2450
+#: gitk:2538
msgid "<Space>\t\tScroll diff view down one page"
msgstr "<Blanksteg>\tRulla diffvisningen ned en sida"
-#: gitk:2451
+#: gitk:2539
msgid "u\t\tScroll diff view up 18 lines"
msgstr "u\t\tRulla diffvisningen upp 18 rader"
-#: gitk:2452
+#: gitk:2540
msgid "d\t\tScroll diff view down 18 lines"
msgstr "d\t\tRulla diffvisningen ned 18 rader"
-#: gitk:2453
+#: gitk:2541
#, tcl-format
msgid "<%s-F>\t\tFind"
msgstr "<%s-F>\t\tSök"
-#: gitk:2454
+#: gitk:2542
#, tcl-format
msgid "<%s-G>\t\tMove to next find hit"
msgstr "<%s-G>\t\tGå till nästa sökträff"
-#: gitk:2455
+#: gitk:2543
msgid "<Return>\tMove to next find hit"
msgstr "<Return>\t\tGå till nästa sökträff"
-#: gitk:2456
+#: gitk:2544
msgid "/\t\tMove to next find hit, or redo find"
msgstr "/\t\tGå till nästa sökträff, eller sök på nytt"
-#: gitk:2457
+#: gitk:2545
msgid "?\t\tMove to previous find hit"
msgstr "?\t\tGå till föregående sökträff"
-#: gitk:2458
+#: gitk:2546
msgid "f\t\tScroll diff view to next file"
msgstr "f\t\tRulla diffvisningen till nästa fil"
-#: gitk:2459
+#: gitk:2547
#, tcl-format
msgid "<%s-S>\t\tSearch for next hit in diff view"
msgstr "<%s-S>\t\tGå till nästa sökträff i diffvisningen"
-#: gitk:2460
+#: gitk:2548
#, tcl-format
msgid "<%s-R>\t\tSearch for previous hit in diff view"
msgstr "<%s-R>\t\tGå till föregående sökträff i diffvisningen"
-#: gitk:2461
+#: gitk:2549
#, tcl-format
msgid "<%s-KP+>\tIncrease font size"
msgstr "<%s-Num+>\tÖka teckenstorlek"
-#: gitk:2462
+#: gitk:2550
#, tcl-format
msgid "<%s-plus>\tIncrease font size"
msgstr "<%s-plus>\tÖka teckenstorlek"
-#: gitk:2463
+#: gitk:2551
#, tcl-format
msgid "<%s-KP->\tDecrease font size"
msgstr "<%s-Num->\tMinska teckenstorlek"
-#: gitk:2464
+#: gitk:2552
#, tcl-format
msgid "<%s-minus>\tDecrease font size"
msgstr "<%s-minus>\tMinska teckenstorlek"
-#: gitk:2465
+#: gitk:2553
msgid "<F5>\t\tUpdate"
msgstr "<F5>\t\tUppdatera"
-#: gitk:3091
+#: gitk:3200
msgid "Gitk view definition"
msgstr "Definition av Gitk-vy"
-#: gitk:3116
+#: gitk:3225
msgid "Name"
msgstr "Namn"
-#: gitk:3119
+#: gitk:3228
msgid "Remember this view"
msgstr "Spara denna vy"
-#: gitk:3123
+#: gitk:3232
msgid "Commits to include (arguments to git log):"
msgstr "Incheckningar att ta med (argument till git log):"
-#: gitk:3130
+#: gitk:3239
msgid "Command to generate more commits to include:"
msgstr "Kommando för att generera fler incheckningar att ta med:"
-#: gitk:3137
+#: gitk:3246
msgid "Enter files and directories to include, one per line:"
msgstr "Ange filer och kataloger att ta med, en per rad:"
-#: gitk:3184
+#: gitk:3293
msgid "Error in commit selection arguments:"
msgstr "Fel i argument för val av incheckningar:"
-#: gitk:3238 gitk:3290 gitk:3736 gitk:3750 gitk:4951 gitk:9896 gitk:9897
+#: gitk:3347 gitk:3399 gitk:3842 gitk:3856 gitk:5060 gitk:10141 gitk:10142
msgid "None"
msgstr "Inget"
-#: gitk:3684 gitk:5471 gitk:7144 gitk:7159
+#: gitk:3790 gitk:5580 gitk:7287 gitk:7302
msgid "Date"
msgstr "Datum"
-#: gitk:3684 gitk:5471
+#: gitk:3790 gitk:5580
msgid "CDate"
msgstr "Skapat datum"
-#: gitk:3833 gitk:3838
+#: gitk:3939 gitk:3944
msgid "Descendant"
msgstr "Avkomling"
-#: gitk:3834
+#: gitk:3940
msgid "Not descendant"
msgstr "Inte avkomling"
-#: gitk:3841 gitk:3846
+#: gitk:3947 gitk:3952
msgid "Ancestor"
msgstr "Förfader"
-#: gitk:3842
+#: gitk:3948
msgid "Not ancestor"
msgstr "Inte förfader"
-#: gitk:4078
+#: gitk:4187
msgid "Local changes checked in to index but not committed"
msgstr "Lokala ändringar sparade i indexet men inte incheckade"
-#: gitk:4111
+#: gitk:4220
msgid "Local uncommitted changes, not checked in to index"
msgstr "Lokala ändringar, ej sparade i indexet"
-#: gitk:5440
+#: gitk:5549
msgid "Searching"
msgstr "Söker"
-#: gitk:5940
+#: gitk:6049
msgid "Tags:"
msgstr "Taggar:"
-#: gitk:5957 gitk:5963 gitk:7137
+#: gitk:6066 gitk:6072 gitk:7280
msgid "Parent"
msgstr "Förälder"
-#: gitk:5968
+#: gitk:6077
msgid "Child"
msgstr "Barn"
-#: gitk:5977
+#: gitk:6086
msgid "Branch"
msgstr "Gren"
-#: gitk:5980
+#: gitk:6089
msgid "Follows"
msgstr "Följer"
-#: gitk:5983
+#: gitk:6092
msgid "Precedes"
msgstr "Föregår"
-#: gitk:6267
+#: gitk:6378
msgid "Error getting merge diffs:"
msgstr "Fel vid hämtning av sammanslagningsdiff:"
-#: gitk:6970
+#: gitk:7113
msgid "Goto:"
msgstr "GÃ¥ till:"
-#: gitk:6972
+#: gitk:7115
msgid "SHA1 ID:"
msgstr "SHA1-id:"
-#: gitk:6991
+#: gitk:7134
#, tcl-format
msgid "Short SHA1 id %s is ambiguous"
msgstr "Förkortat SHA1-id %s är tvetydigt"
-#: gitk:7003
+#: gitk:7146
#, tcl-format
msgid "SHA1 id %s is not known"
msgstr "SHA-id:t %s är inte känt"
-#: gitk:7005
+#: gitk:7148
#, tcl-format
msgid "Tag/Head %s is not known"
msgstr "Tagg/huvud %s är okänt"
-#: gitk:7147
+#: gitk:7290
msgid "Children"
msgstr "Barn"
-#: gitk:7204
+#: gitk:7347
#, tcl-format
msgid "Reset %s branch to here"
msgstr "Återställ grenen %s hit"
-#: gitk:7206
+#: gitk:7349
msgid "Detached head: can't reset"
msgstr "Frånkopplad head: kan inte återställa"
-#: gitk:7238
+#: gitk:7381
msgid "Top"
msgstr "Topp"
-#: gitk:7239
+#: gitk:7382
msgid "From"
msgstr "Från"
-#: gitk:7244
+#: gitk:7387
msgid "To"
msgstr "Till"
-#: gitk:7267
+#: gitk:7410
msgid "Generate patch"
msgstr "Generera patch"
-#: gitk:7269
+#: gitk:7412
msgid "From:"
msgstr "Från:"
-#: gitk:7278
+#: gitk:7421
msgid "To:"
msgstr "Till:"
-#: gitk:7287
+#: gitk:7430
msgid "Reverse"
msgstr "Vänd"
-#: gitk:7289 gitk:7464
+#: gitk:7432 gitk:7607
msgid "Output file:"
msgstr "Utdatafil:"
-#: gitk:7295
+#: gitk:7438
msgid "Generate"
msgstr "Generera"
-#: gitk:7331
+#: gitk:7474
msgid "Error creating patch:"
msgstr "Fel vid generering av patch:"
-#: gitk:7353 gitk:7452 gitk:7506
+#: gitk:7496 gitk:7595 gitk:7649
msgid "ID:"
msgstr "Id:"
-#: gitk:7362
+#: gitk:7505
msgid "Tag name:"
msgstr "Taggnamn:"
-#: gitk:7366 gitk:7515
+#: gitk:7509 gitk:7659
msgid "Create"
msgstr "Skapa"
-#: gitk:7381
+#: gitk:7524
msgid "No tag name specified"
msgstr "Inget taggnamn angavs"
-#: gitk:7385
+#: gitk:7528
#, tcl-format
msgid "Tag \"%s\" already exists"
msgstr "Taggen \"%s\" finns redan"
-#: gitk:7391
+#: gitk:7534
msgid "Error creating tag:"
msgstr "Fel vid skapande av tagg:"
-#: gitk:7461
+#: gitk:7604
msgid "Command:"
msgstr "Kommando:"
-#: gitk:7469
+#: gitk:7612
msgid "Write"
msgstr "Skriv"
-#: gitk:7485
+#: gitk:7628
msgid "Error writing commit:"
msgstr "Fel vid skrivning av incheckning:"
-#: gitk:7511
+#: gitk:7654
msgid "Name:"
msgstr "Namn:"
-#: gitk:7530
+#: gitk:7674
msgid "Please specify a name for the new branch"
msgstr "Ange ett namn för den nya grenen"
-#: gitk:7559
+#: gitk:7703
#, tcl-format
msgid "Commit %s is already included in branch %s -- really re-apply it?"
msgstr ""
"Incheckningen %s finns redan på grenen %s -- skall den verkligen appliceras "
"på nytt?"
-#: gitk:7564
+#: gitk:7708
msgid "Cherry-picking"
msgstr "Plockar"
-#: gitk:7576
+#: gitk:7720
msgid "No changes committed"
msgstr "Inga ändringar incheckade"
-#: gitk:7601
+#: gitk:7745
msgid "Confirm reset"
msgstr "Bekräfta återställning"
-#: gitk:7603
+#: gitk:7747
#, tcl-format
msgid "Reset branch %s to %s?"
msgstr "Återställa grenen %s till %s?"
-#: gitk:7607
+#: gitk:7751
msgid "Reset type:"
msgstr "Typ av återställning:"
-#: gitk:7611
+#: gitk:7755
msgid "Soft: Leave working tree and index untouched"
msgstr "Mjuk: Rör inte utcheckning och index"
-#: gitk:7614
+#: gitk:7758
msgid "Mixed: Leave working tree untouched, reset index"
msgstr "Blandad: Rör inte utcheckning, återställ index"
-#: gitk:7617
+#: gitk:7761
msgid ""
"Hard: Reset working tree and index\n"
"(discard ALL local changes)"
@@ -728,19 +732,19 @@ msgstr ""
"Hård: Återställ utcheckning och index\n"
"(förkastar ALLA lokala ändringar)"
-#: gitk:7633
+#: gitk:7777
msgid "Resetting"
msgstr "Återställer"
-#: gitk:7690
+#: gitk:7834
msgid "Checking out"
msgstr "Checkar ut"
-#: gitk:7741
+#: gitk:7885
msgid "Cannot delete the currently checked-out branch"
msgstr "Kan inte ta bort den just nu utcheckade grenen"
-#: gitk:7747
+#: gitk:7891
#, tcl-format
msgid ""
"The commits on branch %s aren't on any other branch.\n"
@@ -749,16 +753,16 @@ msgstr ""
"Incheckningarna på grenen %s existerar inte på någon annan gren.\n"
"Vill du verkligen ta bort grenen %s?"
-#: gitk:7778
+#: gitk:7922
#, tcl-format
msgid "Tags and heads: %s"
msgstr "Taggar och huvuden: %s"
-#: gitk:7792
+#: gitk:7936
msgid "Filter"
msgstr "Filter"
-#: gitk:8086
+#: gitk:8230
msgid ""
"Error reading commit topology information; branch and preceding/following "
"tag information will be incomplete."
@@ -766,125 +770,129 @@ msgstr ""
"Fel vid läsning av information om incheckningstopologi; information om "
"grenar och föregående/senare taggar kommer inte vara komplett."
-#: gitk:9072
+#: gitk:9216
msgid "Tag"
msgstr "Tagg"
-#: gitk:9072
+#: gitk:9216
msgid "Id"
msgstr "Id"
-#: gitk:9118
+#: gitk:9262
msgid "Gitk font chooser"
msgstr "Teckensnittsväljare för Gitk"
-#: gitk:9135
+#: gitk:9279
msgid "B"
msgstr "F"
-#: gitk:9138
+#: gitk:9282
msgid "I"
msgstr "K"
-#: gitk:9231
+#: gitk:9375
msgid "Gitk preferences"
msgstr "Inställningar för Gitk"
-#: gitk:9232
+#: gitk:9376
msgid "Commit list display options"
msgstr "Alternativ för incheckningslistvy"
-#: gitk:9235
+#: gitk:9379
msgid "Maximum graph width (lines)"
msgstr "Maximal grafbredd (rader)"
-#: gitk:9239
+#: gitk:9383
#, tcl-format
msgid "Maximum graph width (% of pane)"
msgstr "Maximal grafbredd (% av ruta)"
-#: gitk:9244
+#: gitk:9388
msgid "Show local changes"
msgstr "Visa lokala ändringar"
-#: gitk:9249
+#: gitk:9393
msgid "Auto-select SHA1"
msgstr "Välj SHA1 automatiskt"
-#: gitk:9254
+#: gitk:9398
msgid "Diff display options"
msgstr "Alternativ för diffvy"
-#: gitk:9256
+#: gitk:9400
msgid "Tab spacing"
msgstr "Blanksteg för tabulatortecken"
-#: gitk:9260
+#: gitk:9404
msgid "Display nearby tags"
msgstr "Visa närliggande taggar"
-#: gitk:9265
+#: gitk:9409
msgid "Limit diffs to listed paths"
msgstr "Begränsa diff till listade sökvägar"
-#: gitk:9272
+#: gitk:9414
+msgid "Support per-file encodings"
+msgstr ""
+
+#: gitk:9421
msgid "External diff tool"
msgstr "Externt diff-verktyg"
-#: gitk:9274
+#: gitk:9423
msgid "Choose..."
msgstr "Välj..."
-#: gitk:9279
+#: gitk:9428
msgid "Colors: press to choose"
msgstr "Färger: tryck för att välja"
-#: gitk:9282
+#: gitk:9431
msgid "Background"
msgstr "Bakgrund"
-#: gitk:9286
+#: gitk:9435
msgid "Foreground"
msgstr "Förgrund"
-#: gitk:9290
+#: gitk:9439
msgid "Diff: old lines"
msgstr "Diff: gamla rader"
-#: gitk:9295
+#: gitk:9444
msgid "Diff: new lines"
msgstr "Diff: nya rader"
-#: gitk:9300
+#: gitk:9449
msgid "Diff: hunk header"
msgstr "Diff: delhuvud"
-#: gitk:9306
+#: gitk:9455
msgid "Select bg"
msgstr "Markerad bakgrund"
-#: gitk:9310
+#: gitk:9459
msgid "Fonts: press to choose"
msgstr "Teckensnitt: tryck för att välja"
-#: gitk:9312
+#: gitk:9461
msgid "Main font"
msgstr "Huvudteckensnitt"
-#: gitk:9313
+#: gitk:9462
msgid "Diff display font"
msgstr "Teckensnitt för diffvisning"
-#: gitk:9314
+#: gitk:9463
msgid "User interface font"
msgstr "Teckensnitt för användargränssnitt"
-#: gitk:9339
+#: gitk:9488
#, tcl-format
msgid "Gitk: choose color for %s"
msgstr "Gitk: välj färg för %s"
-#: gitk:9720
+#: gitk:9934
msgid ""
"Sorry, gitk cannot run with this version of Tcl/Tk.\n"
" Gitk requires at least Tcl/Tk 8.4."
@@ -892,24 +900,24 @@ msgstr ""
"Gitk kan tyvärr inte köra med denna version av Tcl/Tk.\n"
" Gitk kräver åtminstone Tcl/Tk 8.4."
-#: gitk:9812
+#: gitk:10047
msgid "Cannot find a git repository here."
msgstr "Hittar inget gitk-arkiv här."
-#: gitk:9816
+#: gitk:10051
#, tcl-format
msgid "Cannot find the git directory \"%s\"."
msgstr "Hittar inte git-katalogen \"%s\"."
-#: gitk:9853
+#: gitk:10098
#, tcl-format
msgid "Ambiguous argument '%s': both revision and filename"
msgstr "Tvetydigt argument \"%s\": både revision och filnamn"
-#: gitk:9865
+#: gitk:10110
msgid "Bad arguments to gitk:"
msgstr "Felaktiga argument till gitk:"
-#: gitk:9925
+#: gitk:10170
msgid "Command line"
msgstr "Kommandorad"
diff --git a/gitweb/INSTALL b/gitweb/INSTALL
index 26967e201a..18c9ce35e8 100644
--- a/gitweb/INSTALL
+++ b/gitweb/INSTALL
@@ -166,6 +166,27 @@ Gitweb repositories
shows repositories only if this file exists in its object database
(if directory has the magic file named $export_ok).
+- Finally, it is possible to specify an arbitrary perl subroutine that
+ will be called for each project to determine if it can be exported.
+ The subroutine receives an absolute path to the project as its only
+ parameter.
+
+ For example, if you use mod_perl to run the script, and have dumb
+ http protocol authentication configured for your repositories, you
+ can use the following hook to allow access only if the user is
+ authorized to read the files:
+
+ $export_auth_hook = sub {
+ use Apache2::SubRequest ();
+ use Apache2::Const -compile => qw(HTTP_OK);
+ my $path = "$_[0]/HEAD";
+ my $r = Apache2::RequestUtil->request;
+ my $sub = $r->lookup_file($path);
+ return $sub->filename eq $path
+ && $sub->status == Apache2::Const::HTTP_OK;
+ };
+
+
Generating projects list using gitweb
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 11168006cf..0ac84d1adf 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -29,7 +29,9 @@ our $my_uri = $cgi->url(-absolute => 1);
# if we're called with PATH_INFO, we have to strip that
# from the URL to find our real URL
-if (my $path_info = $ENV{"PATH_INFO"}) {
+# we make $path_info global because it's also used later on
+our $path_info = $ENV{"PATH_INFO"};
+if ($path_info) {
$my_url =~ s,\Q$path_info\E$,,;
$my_uri =~ s,\Q$path_info\E$,,;
}
@@ -93,6 +95,11 @@ our $default_projects_order = "project";
# (only effective if this variable evaluates to true)
our $export_ok = "++GITWEB_EXPORT_OK++";
+# show repository only if this subroutine returns true
+# when given the path to the project, for example:
+# sub { return -e "$_[0]/git-daemon-export-ok"; }
+our $export_auth_hook = undef;
+
# only allow viewing of repositories also shown on the overview page
our $strict_export = "++GITWEB_STRICT_EXPORT++";
@@ -183,7 +190,9 @@ our %feature = (
# if there is no 'sub' key (no feature-sub), then feature cannot be
# overriden
#
- # use gitweb_check_feature(<feature>) to check if <feature> is enabled
+ # use gitweb_get_feature(<feature>) to retrieve the <feature> value
+ # (an array) or gitweb_check_feature(<feature>) to check if <feature>
+ # is enabled
# Enable the 'blame' blob view, showing the last commit that modified
# each line in the file. This can be very CPU-intensive.
@@ -194,7 +203,7 @@ our %feature = (
# $feature{'blame'}{'override'} = 1;
# and in project config gitweb.blame = 0|1;
'blame' => {
- 'sub' => \&feature_blame,
+ 'sub' => sub { feature_bool('blame', @_) },
'override' => 0,
'default' => [0]},
@@ -232,6 +241,7 @@ our %feature = (
# $feature{'grep'}{'override'} = 1;
# and in project config gitweb.grep = 0|1;
'grep' => {
+ 'sub' => sub { feature_bool('grep', @_) },
'override' => 0,
'default' => [1]},
@@ -245,7 +255,7 @@ our %feature = (
# $feature{'pickaxe'}{'override'} = 1;
# and in project config gitweb.pickaxe = 0|1;
'pickaxe' => {
- 'sub' => \&feature_pickaxe,
+ 'sub' => sub { feature_bool('pickaxe', @_) },
'override' => 0,
'default' => [1]},
@@ -290,10 +300,10 @@ our %feature = (
# The 'default' value consists of a list of triplets in the form
# (label, link, position) where position is the label after which
- # to inster the link and link is a format string where %n expands
+ # to insert the link and link is a format string where %n expands
# to the project name, %f to the project path within the filesystem,
# %h to the current hash (h gitweb parameter) and %b to the current
- # hash base (hb gitweb parameter).
+ # hash base (hb gitweb parameter); %% expands to %.
# To enable system wide have in $GITWEB_CONFIG e.g.
# $feature{'actions'}{'default'} = [('graphiclog',
@@ -322,7 +332,7 @@ our %feature = (
'default' => [0]},
);
-sub gitweb_check_feature {
+sub gitweb_get_feature {
my ($name) = @_;
return unless exists $feature{$name};
my ($sub, $override, @defaults) = (
@@ -337,16 +347,33 @@ sub gitweb_check_feature {
return $sub->(@defaults);
}
-sub feature_blame {
- my ($val) = git_get_project_config('blame', '--bool');
+# A wrapper to check if a given feature is enabled.
+# With this, you can say
+#
+# my $bool_feat = gitweb_check_feature('bool_feat');
+# gitweb_check_feature('bool_feat') or somecode;
+#
+# instead of
+#
+# my ($bool_feat) = gitweb_get_feature('bool_feat');
+# (gitweb_get_feature('bool_feat'))[0] or somecode;
+#
+sub gitweb_check_feature {
+ return (gitweb_get_feature(@_))[0];
+}
+
+
+sub feature_bool {
+ my $key = shift;
+ my ($val) = git_get_project_config($key, '--bool');
if ($val eq 'true') {
- return 1;
+ return (1);
} elsif ($val eq 'false') {
- return 0;
+ return (0);
}
- return $_[0];
+ return ($_[0]);
}
sub feature_snapshot {
@@ -361,30 +388,6 @@ sub feature_snapshot {
return @fmts;
}
-sub feature_grep {
- my ($val) = git_get_project_config('grep', '--bool');
-
- if ($val eq 'true') {
- return (1);
- } elsif ($val eq 'false') {
- return (0);
- }
-
- return ($_[0]);
-}
-
-sub feature_pickaxe {
- my ($val) = git_get_project_config('pickaxe', '--bool');
-
- if ($val eq 'true') {
- return (1);
- } elsif ($val eq 'false') {
- return (0);
- }
-
- return ($_[0]);
-}
-
# checking HEAD file with -e is fragile if the repository was
# initialized long time ago (i.e. symlink HEAD) and was pack-ref'ed
# and then pruned.
@@ -398,7 +401,8 @@ sub check_head_link {
sub check_export_ok {
my ($dir) = @_;
return (check_head_link($dir) &&
- (!$export_ok || -e "$dir/$export_ok"));
+ (!$export_ok || -e "$dir/$export_ok") &&
+ (!$export_auth_hook || $export_auth_hook->($dir)));
}
# process alternate names for backward compatibility
@@ -428,34 +432,258 @@ $projects_list ||= $projectroot;
# ======================================================================
# input validation and dispatch
-our $action = $cgi->param('a');
+
+# input parameters can be collected from a variety of sources (presently, CGI
+# and PATH_INFO), so we define an %input_params hash that collects them all
+# together during validation: this allows subsequent uses (e.g. href()) to be
+# agnostic of the parameter origin
+
+our %input_params = ();
+
+# input parameters are stored with the long parameter name as key. This will
+# also be used in the href subroutine to convert parameters to their CGI
+# equivalent, and since the href() usage is the most frequent one, we store
+# the name -> CGI key mapping here, instead of the reverse.
+#
+# XXX: Warning: If you touch this, check the search form for updating,
+# too.
+
+our @cgi_param_mapping = (
+ project => "p",
+ action => "a",
+ file_name => "f",
+ file_parent => "fp",
+ hash => "h",
+ hash_parent => "hp",
+ hash_base => "hb",
+ hash_parent_base => "hpb",
+ page => "pg",
+ order => "o",
+ searchtext => "s",
+ searchtype => "st",
+ snapshot_format => "sf",
+ extra_options => "opt",
+ search_use_regexp => "sr",
+);
+our %cgi_param_mapping = @cgi_param_mapping;
+
+# we will also need to know the possible actions, for validation
+our %actions = (
+ "blame" => \&git_blame,
+ "blobdiff" => \&git_blobdiff,
+ "blobdiff_plain" => \&git_blobdiff_plain,
+ "blob" => \&git_blob,
+ "blob_plain" => \&git_blob_plain,
+ "commitdiff" => \&git_commitdiff,
+ "commitdiff_plain" => \&git_commitdiff_plain,
+ "commit" => \&git_commit,
+ "forks" => \&git_forks,
+ "heads" => \&git_heads,
+ "history" => \&git_history,
+ "log" => \&git_log,
+ "rss" => \&git_rss,
+ "atom" => \&git_atom,
+ "search" => \&git_search,
+ "search_help" => \&git_search_help,
+ "shortlog" => \&git_shortlog,
+ "summary" => \&git_summary,
+ "tag" => \&git_tag,
+ "tags" => \&git_tags,
+ "tree" => \&git_tree,
+ "snapshot" => \&git_snapshot,
+ "object" => \&git_object,
+ # those below don't need $project
+ "opml" => \&git_opml,
+ "project_list" => \&git_project_list,
+ "project_index" => \&git_project_index,
+);
+
+# finally, we have the hash of allowed extra_options for the commands that
+# allow them
+our %allowed_options = (
+ "--no-merges" => [ qw(rss atom log shortlog history) ],
+);
+
+# fill %input_params with the CGI parameters. All values except for 'opt'
+# should be single values, but opt can be an array. We should probably
+# build an array of parameters that can be multi-valued, but since for the time
+# being it's only this one, we just single it out
+while (my ($name, $symbol) = each %cgi_param_mapping) {
+ if ($symbol eq 'opt') {
+ $input_params{$name} = [ $cgi->param($symbol) ];
+ } else {
+ $input_params{$name} = $cgi->param($symbol);
+ }
+}
+
+# now read PATH_INFO and update the parameter list for missing parameters
+sub evaluate_path_info {
+ return if defined $input_params{'project'};
+ return if !$path_info;
+ $path_info =~ s,^/+,,;
+ return if !$path_info;
+
+ # find which part of PATH_INFO is project
+ my $project = $path_info;
+ $project =~ s,/+$,,;
+ while ($project && !check_head_link("$projectroot/$project")) {
+ $project =~ s,/*[^/]*$,,;
+ }
+ return unless $project;
+ $input_params{'project'} = $project;
+
+ # do not change any parameters if an action is given using the query string
+ return if $input_params{'action'};
+ $path_info =~ s,^\Q$project\E/*,,;
+
+ # next, check if we have an action
+ my $action = $path_info;
+ $action =~ s,/.*$,,;
+ if (exists $actions{$action}) {
+ $path_info =~ s,^$action/*,,;
+ $input_params{'action'} = $action;
+ }
+
+ # list of actions that want hash_base instead of hash, but can have no
+ # pathname (f) parameter
+ my @wants_base = (
+ 'tree',
+ 'history',
+ );
+
+ # we want to catch
+ # [$hash_parent_base[:$file_parent]..]$hash_parent[:$file_name]
+ my ($parentrefname, $parentpathname, $refname, $pathname) =
+ ($path_info =~ /^(?:(.+?)(?::(.+))?\.\.)?(.+?)(?::(.+))?$/);
+
+ # first, analyze the 'current' part
+ if (defined $pathname) {
+ # we got "branch:filename" or "branch:dir/"
+ # we could use git_get_type(branch:pathname), but:
+ # - it needs $git_dir
+ # - it does a git() call
+ # - the convention of terminating directories with a slash
+ # makes it superfluous
+ # - embedding the action in the PATH_INFO would make it even
+ # more superfluous
+ $pathname =~ s,^/+,,;
+ if (!$pathname || substr($pathname, -1) eq "/") {
+ $input_params{'action'} ||= "tree";
+ $pathname =~ s,/$,,;
+ } else {
+ # the default action depends on whether we had parent info
+ # or not
+ if ($parentrefname) {
+ $input_params{'action'} ||= "blobdiff_plain";
+ } else {
+ $input_params{'action'} ||= "blob_plain";
+ }
+ }
+ $input_params{'hash_base'} ||= $refname;
+ $input_params{'file_name'} ||= $pathname;
+ } elsif (defined $refname) {
+ # we got "branch". In this case we have to choose if we have to
+ # set hash or hash_base.
+ #
+ # Most of the actions without a pathname only want hash to be
+ # set, except for the ones specified in @wants_base that want
+ # hash_base instead. It should also be noted that hand-crafted
+ # links having 'history' as an action and no pathname or hash
+ # set will fail, but that happens regardless of PATH_INFO.
+ $input_params{'action'} ||= "shortlog";
+ if (grep { $_ eq $input_params{'action'} } @wants_base) {
+ $input_params{'hash_base'} ||= $refname;
+ } else {
+ $input_params{'hash'} ||= $refname;
+ }
+ }
+
+ # next, handle the 'parent' part, if present
+ if (defined $parentrefname) {
+ # a missing pathspec defaults to the 'current' filename, allowing e.g.
+ # someproject/blobdiff/oldrev..newrev:/filename
+ if ($parentpathname) {
+ $parentpathname =~ s,^/+,,;
+ $parentpathname =~ s,/$,,;
+ $input_params{'file_parent'} ||= $parentpathname;
+ } else {
+ $input_params{'file_parent'} ||= $input_params{'file_name'};
+ }
+ # we assume that hash_parent_base is wanted if a path was specified,
+ # or if the action wants hash_base instead of hash
+ if (defined $input_params{'file_parent'} ||
+ grep { $_ eq $input_params{'action'} } @wants_base) {
+ $input_params{'hash_parent_base'} ||= $parentrefname;
+ } else {
+ $input_params{'hash_parent'} ||= $parentrefname;
+ }
+ }
+
+ # for the snapshot action, we allow URLs in the form
+ # $project/snapshot/$hash.ext
+ # where .ext determines the snapshot and gets removed from the
+ # passed $refname to provide the $hash.
+ #
+ # To be able to tell that $refname includes the format extension, we
+ # require the following two conditions to be satisfied:
+ # - the hash input parameter MUST have been set from the $refname part
+ # of the URL (i.e. they must be equal)
+ # - the snapshot format MUST NOT have been defined already (e.g. from
+ # CGI parameter sf)
+ # It's also useless to try any matching unless $refname has a dot,
+ # so we check for that too
+ if (defined $input_params{'action'} &&
+ $input_params{'action'} eq 'snapshot' &&
+ defined $refname && index($refname, '.') != -1 &&
+ $refname eq $input_params{'hash'} &&
+ !defined $input_params{'snapshot_format'}) {
+ # We loop over the known snapshot formats, checking for
+ # extensions. Allowed extensions are both the defined suffix
+ # (which includes the initial dot already) and the snapshot
+ # format key itself, with a prepended dot
+ while (my ($fmt, %opt) = each %known_snapshot_formats) {
+ my $hash = $refname;
+ my $sfx;
+ $hash =~ s/(\Q$opt{'suffix'}\E|\Q.$fmt\E)$//;
+ next unless $sfx = $1;
+ # a valid suffix was found, so set the snapshot format
+ # and reset the hash parameter
+ $input_params{'snapshot_format'} = $fmt;
+ $input_params{'hash'} = $hash;
+ # we also set the format suffix to the one requested
+ # in the URL: this way a request for e.g. .tgz returns
+ # a .tgz instead of a .tar.gz
+ $known_snapshot_formats{$fmt}{'suffix'} = $sfx;
+ last;
+ }
+ }
+}
+evaluate_path_info();
+
+our $action = $input_params{'action'};
if (defined $action) {
- if ($action =~ m/[^0-9a-zA-Z\.\-_]/) {
+ if (!validate_action($action)) {
die_error(400, "Invalid action parameter");
}
}
# parameters which are pathnames
-our $project = $cgi->param('p');
+our $project = $input_params{'project'};
if (defined $project) {
- if (!validate_pathname($project) ||
- !(-d "$projectroot/$project") ||
- !check_head_link("$projectroot/$project") ||
- ($export_ok && !(-e "$projectroot/$project/$export_ok")) ||
- ($strict_export && !project_in_list($project))) {
+ if (!validate_project($project)) {
undef $project;
die_error(404, "No such project");
}
}
-our $file_name = $cgi->param('f');
+our $file_name = $input_params{'file_name'};
if (defined $file_name) {
if (!validate_pathname($file_name)) {
die_error(400, "Invalid file parameter");
}
}
-our $file_parent = $cgi->param('fp');
+our $file_parent = $input_params{'file_parent'};
if (defined $file_parent) {
if (!validate_pathname($file_parent)) {
die_error(400, "Invalid file parent parameter");
@@ -463,44 +691,41 @@ if (defined $file_parent) {
}
# parameters which are refnames
-our $hash = $cgi->param('h');
+our $hash = $input_params{'hash'};
if (defined $hash) {
if (!validate_refname($hash)) {
die_error(400, "Invalid hash parameter");
}
}
-our $hash_parent = $cgi->param('hp');
+our $hash_parent = $input_params{'hash_parent'};
if (defined $hash_parent) {
if (!validate_refname($hash_parent)) {
die_error(400, "Invalid hash parent parameter");
}
}
-our $hash_base = $cgi->param('hb');
+our $hash_base = $input_params{'hash_base'};
if (defined $hash_base) {
if (!validate_refname($hash_base)) {
die_error(400, "Invalid hash base parameter");
}
}
-my %allowed_options = (
- "--no-merges" => [ qw(rss atom log shortlog history) ],
-);
-
-our @extra_options = $cgi->param('opt');
-if (defined @extra_options) {
- foreach my $opt (@extra_options) {
- if (not exists $allowed_options{$opt}) {
- die_error(400, "Invalid option parameter");
- }
- if (not grep(/^$action$/, @{$allowed_options{$opt}})) {
- die_error(400, "Invalid option parameter for this action");
- }
+our @extra_options = @{$input_params{'extra_options'}};
+# @extra_options is always defined, since it can only be (currently) set from
+# CGI, and $cgi->param() returns the empty array in array context if the param
+# is not set
+foreach my $opt (@extra_options) {
+ if (not exists $allowed_options{$opt}) {
+ die_error(400, "Invalid option parameter");
+ }
+ if (not grep(/^$action$/, @{$allowed_options{$opt}})) {
+ die_error(400, "Invalid option parameter for this action");
}
}
-our $hash_parent_base = $cgi->param('hpb');
+our $hash_parent_base = $input_params{'hash_parent_base'};
if (defined $hash_parent_base) {
if (!validate_refname($hash_parent_base)) {
die_error(400, "Invalid hash parent base parameter");
@@ -508,23 +733,23 @@ if (defined $hash_parent_base) {
}
# other parameters
-our $page = $cgi->param('pg');
+our $page = $input_params{'page'};
if (defined $page) {
if ($page =~ m/[^0-9]/) {
die_error(400, "Invalid page parameter");
}
}
-our $searchtype = $cgi->param('st');
+our $searchtype = $input_params{'searchtype'};
if (defined $searchtype) {
if ($searchtype =~ m/[^a-z]/) {
die_error(400, "Invalid searchtype parameter");
}
}
-our $search_use_regexp = $cgi->param('sr');
+our $search_use_regexp = $input_params{'search_use_regexp'};
-our $searchtext = $cgi->param('s');
+our $searchtext = $input_params{'searchtext'};
our $search_regexp;
if (defined $searchtext) {
if (length($searchtext) < 2) {
@@ -533,86 +758,15 @@ if (defined $searchtext) {
$search_regexp = $search_use_regexp ? $searchtext : quotemeta $searchtext;
}
-# now read PATH_INFO and use it as alternative to parameters
-sub evaluate_path_info {
- return if defined $project;
- my $path_info = $ENV{"PATH_INFO"};
- return if !$path_info;
- $path_info =~ s,^/+,,;
- return if !$path_info;
- # find which part of PATH_INFO is project
- $project = $path_info;
- $project =~ s,/+$,,;
- while ($project && !check_head_link("$projectroot/$project")) {
- $project =~ s,/*[^/]*$,,;
- }
- # validate project
- $project = validate_pathname($project);
- if (!$project ||
- ($export_ok && !-e "$projectroot/$project/$export_ok") ||
- ($strict_export && !project_in_list($project))) {
- undef $project;
- return;
- }
- # do not change any parameters if an action is given using the query string
- return if $action;
- $path_info =~ s,^\Q$project\E/*,,;
- my ($refname, $pathname) = split(/:/, $path_info, 2);
- if (defined $pathname) {
- # we got "project.git/branch:filename" or "project.git/branch:dir/"
- # we could use git_get_type(branch:pathname), but it needs $git_dir
- $pathname =~ s,^/+,,;
- if (!$pathname || substr($pathname, -1) eq "/") {
- $action ||= "tree";
- $pathname =~ s,/$,,;
- } else {
- $action ||= "blob_plain";
- }
- $hash_base ||= validate_refname($refname);
- $file_name ||= validate_pathname($pathname);
- } elsif (defined $refname) {
- # we got "project.git/branch"
- $action ||= "shortlog";
- $hash ||= validate_refname($refname);
- }
-}
-evaluate_path_info();
-
# path to the current git repository
our $git_dir;
$git_dir = "$projectroot/$project" if $project;
-# dispatch
-my %actions = (
- "blame" => \&git_blame,
- "blobdiff" => \&git_blobdiff,
- "blobdiff_plain" => \&git_blobdiff_plain,
- "blob" => \&git_blob,
- "blob_plain" => \&git_blob_plain,
- "commitdiff" => \&git_commitdiff,
- "commitdiff_plain" => \&git_commitdiff_plain,
- "commit" => \&git_commit,
- "forks" => \&git_forks,
- "heads" => \&git_heads,
- "history" => \&git_history,
- "log" => \&git_log,
- "rss" => \&git_rss,
- "atom" => \&git_atom,
- "search" => \&git_search,
- "search_help" => \&git_search_help,
- "shortlog" => \&git_shortlog,
- "summary" => \&git_summary,
- "tag" => \&git_tag,
- "tags" => \&git_tags,
- "tree" => \&git_tree,
- "snapshot" => \&git_snapshot,
- "object" => \&git_object,
- # those below don't need $project
- "opml" => \&git_opml,
- "project_list" => \&git_project_list,
- "project_index" => \&git_project_index,
-);
+# list of supported snapshot formats
+our @snapshot_fmts = gitweb_get_feature('snapshot');
+@snapshot_fmts = filter_snapshot_fmts(@snapshot_fmts);
+# dispatch
if (!defined $action) {
if (defined $hash) {
$action = git_get_type($hash);
@@ -642,55 +796,96 @@ sub href (%) {
# default is to use -absolute url() i.e. $my_uri
my $href = $params{-full} ? $my_url : $my_uri;
- # XXX: Warning: If you touch this, check the search form for updating,
- # too.
-
- my @mapping = (
- project => "p",
- action => "a",
- file_name => "f",
- file_parent => "fp",
- hash => "h",
- hash_parent => "hp",
- hash_base => "hb",
- hash_parent_base => "hpb",
- page => "pg",
- order => "o",
- searchtext => "s",
- searchtype => "st",
- snapshot_format => "sf",
- extra_options => "opt",
- search_use_regexp => "sr",
- );
- my %mapping = @mapping;
-
$params{'project'} = $project unless exists $params{'project'};
if ($params{-replay}) {
- while (my ($name, $symbol) = each %mapping) {
+ while (my ($name, $symbol) = each %cgi_param_mapping) {
if (!exists $params{$name}) {
- # to allow for multivalued params we use arrayref form
- $params{$name} = [ $cgi->param($symbol) ];
+ $params{$name} = $input_params{$name};
}
}
}
- my ($use_pathinfo) = gitweb_check_feature('pathinfo');
+ my $use_pathinfo = gitweb_check_feature('pathinfo');
if ($use_pathinfo) {
- # use PATH_INFO for project name
+ # try to put as many parameters as possible in PATH_INFO:
+ # - project name
+ # - action
+ # - hash_parent or hash_parent_base:/file_parent
+ # - hash or hash_base:/filename
+ # - the snapshot_format as an appropriate suffix
+
+ # When the script is the root DirectoryIndex for the domain,
+ # $href here would be something like http://gitweb.example.com/
+ # Thus, we strip any trailing / from $href, to spare us double
+ # slashes in the final URL
+ $href =~ s,/$,,;
+
+ # Then add the project name, if present
$href .= "/".esc_url($params{'project'}) if defined $params{'project'};
delete $params{'project'};
- # Summary just uses the project path URL
- if (defined $params{'action'} && $params{'action'} eq 'summary') {
+ # since we destructively absorb parameters, we keep this
+ # boolean that remembers if we're handling a snapshot
+ my $is_snapshot = $params{'action'} eq 'snapshot';
+
+ # Summary just uses the project path URL, any other action is
+ # added to the URL
+ if (defined $params{'action'}) {
+ $href .= "/".esc_url($params{'action'}) unless $params{'action'} eq 'summary';
delete $params{'action'};
}
+
+ # Next, we put hash_parent_base:/file_parent..hash_base:/file_name,
+ # stripping nonexistent or useless pieces
+ $href .= "/" if ($params{'hash_base'} || $params{'hash_parent_base'}
+ || $params{'hash_parent'} || $params{'hash'});
+ if (defined $params{'hash_base'}) {
+ if (defined $params{'hash_parent_base'}) {
+ $href .= esc_url($params{'hash_parent_base'});
+ # skip the file_parent if it's the same as the file_name
+ delete $params{'file_parent'} if $params{'file_parent'} eq $params{'file_name'};
+ if (defined $params{'file_parent'} && $params{'file_parent'} !~ /\.\./) {
+ $href .= ":/".esc_url($params{'file_parent'});
+ delete $params{'file_parent'};
+ }
+ $href .= "..";
+ delete $params{'hash_parent'};
+ delete $params{'hash_parent_base'};
+ } elsif (defined $params{'hash_parent'}) {
+ $href .= esc_url($params{'hash_parent'}). "..";
+ delete $params{'hash_parent'};
+ }
+
+ $href .= esc_url($params{'hash_base'});
+ if (defined $params{'file_name'} && $params{'file_name'} !~ /\.\./) {
+ $href .= ":/".esc_url($params{'file_name'});
+ delete $params{'file_name'};
+ }
+ delete $params{'hash'};
+ delete $params{'hash_base'};
+ } elsif (defined $params{'hash'}) {
+ $href .= esc_url($params{'hash'});
+ delete $params{'hash'};
+ }
+
+ # If the action was a snapshot, we can absorb the
+ # snapshot_format parameter too
+ if ($is_snapshot) {
+ my $fmt = $params{'snapshot_format'};
+ # snapshot_format should always be defined when href()
+ # is called, but just in case some code forgets, we
+ # fall back to the default
+ $fmt ||= $snapshot_fmts[0];
+ $href .= $known_snapshot_formats{$fmt}{'suffix'};
+ delete $params{'snapshot_format'};
+ }
}
# now encode the parameters explicitly
my @result = ();
- for (my $i = 0; $i < @mapping; $i += 2) {
- my ($name, $symbol) = ($mapping[$i], $mapping[$i+1]);
+ for (my $i = 0; $i < @cgi_param_mapping; $i += 2) {
+ my ($name, $symbol) = ($cgi_param_mapping[$i], $cgi_param_mapping[$i+1]);
if (defined $params{$name}) {
if (ref($params{$name}) eq "ARRAY") {
foreach my $par (@{$params{$name}}) {
@@ -710,6 +905,24 @@ sub href (%) {
## ======================================================================
## validation, quoting/unquoting and escaping
+sub validate_action {
+ my $input = shift || return undef;
+ return undef unless exists $actions{$input};
+ return $input;
+}
+
+sub validate_project {
+ my $input = shift || return undef;
+ if (!validate_pathname($input) ||
+ !(-d "$projectroot/$input") ||
+ !check_export_ok("$projectroot/$input") ||
+ ($strict_export && !project_in_list($input))) {
+ return undef;
+ } else {
+ return $input;
+ }
+}
+
sub validate_pathname {
my $input = shift || return undef;
@@ -1495,8 +1708,6 @@ sub format_diff_line {
# linked. Pass the hash of the tree/commit to snapshot.
sub format_snapshot_links {
my ($hash) = @_;
- my @snapshot_fmts = gitweb_check_feature('snapshot');
- @snapshot_fmts = filter_snapshot_fmts(@snapshot_fmts);
my $num_fmts = @snapshot_fmts;
if ($num_fmts > 1) {
# A parenthesized list of links bearing format names.
@@ -1805,7 +2016,10 @@ sub git_get_project_ctags {
my $ctags = {};
$git_dir = "$projectroot/$path";
- foreach (<$git_dir/ctags/*>) {
+ unless (opendir D, "$git_dir/ctags") {
+ return $ctags;
+ }
+ foreach (grep { -f $_ } map { "$git_dir/ctags/$_" } readdir(D)) {
open CT, $_ or next;
my $val = <CT>;
chomp $val;
@@ -1813,6 +2027,7 @@ sub git_get_project_ctags {
my $ctag = $_; $ctag =~ s#.*/##;
$ctags->{$ctag} = $val;
}
+ closedir D;
$ctags;
}
@@ -1882,7 +2097,7 @@ sub git_get_projects_list {
$filter ||= '';
$filter =~ s/\.git$//;
- my ($check_forks) = gitweb_check_feature('forks');
+ my $check_forks = gitweb_check_feature('forks');
if (-d $projects_list) {
# search in directory
@@ -1909,8 +2124,9 @@ sub git_get_projects_list {
my $subdir = substr($File::Find::name, $pfxlen + 1);
# we check related file in $projectroot
- if (check_export_ok("$projectroot/$filter/$subdir")) {
- push @list, { path => ($filter ? "$filter/" : '') . $subdir };
+ my $path = ($filter ? "$filter/" : '') . $subdir;
+ if (check_export_ok("$projectroot/$path")) {
+ push @list, { path => $path };
$File::Find::prune = 1;
}
},
@@ -2521,6 +2737,15 @@ sub get_file_owner {
return to_utf8($owner);
}
+# assume that file exists
+sub insert_file {
+ my $filename = shift;
+
+ open my $fd, '<', $filename;
+ print map { to_utf8($_) } <$fd>;
+ close $fd;
+}
+
## ......................................................................
## mimetype related functions
@@ -2709,9 +2934,7 @@ EOF
"<body>\n";
if (-f $site_header) {
- open (my $fd, $site_header);
- print <$fd>;
- close $fd;
+ insert_file($site_header);
}
print "<div class=\"page_header\">\n" .
@@ -2728,7 +2951,7 @@ EOF
}
print "</div>\n";
- my ($have_search) = gitweb_check_feature('search');
+ my $have_search = gitweb_check_feature('search');
if (defined $project && $have_search) {
if (!defined $searchtext) {
$searchtext = "";
@@ -2742,7 +2965,7 @@ EOF
$search_hash = "HEAD";
}
my $action = $my_uri;
- my ($use_pathinfo) = gitweb_check_feature('pathinfo');
+ my $use_pathinfo = gitweb_check_feature('pathinfo');
if ($use_pathinfo) {
$action .= "/".esc_url($project);
}
@@ -2798,9 +3021,7 @@ sub git_footer_html {
print "</div>\n"; # class="page_footer"
if (-f $site_footer) {
- open (my $fd, $site_footer);
- print <$fd>;
- close $fd;
+ insert_file($site_footer);
}
print "</body>\n" .
@@ -2865,15 +3086,20 @@ sub git_print_page_nav {
$arg{'tree'}{'hash'} = $treehead if defined $treehead;
$arg{'tree'}{'hash_base'} = $treebase if defined $treebase;
- my @actions = gitweb_check_feature('actions');
+ my @actions = gitweb_get_feature('actions');
+ my %repl = (
+ '%' => '%',
+ 'n' => $project, # project name
+ 'f' => $git_dir, # project path within filesystem
+ 'h' => $treehead || '', # current hash ('h' parameter)
+ 'b' => $treebase || '', # hash base ('hb' parameter)
+ );
while (@actions) {
- my ($label, $link, $pos) = (shift(@actions), shift(@actions), shift(@actions));
+ my ($label, $link, $pos) = splice(@actions,0,3);
+ # insert
@navs = map { $_ eq $pos ? ($_, $label) : $_ } @navs;
# munch munch
- $link =~ s#%n#$project#g;
- $link =~ s#%f#$git_dir#g;
- $treehead ? $link =~ s#%h#$treehead#g : $link =~ s#%h##g;
- $treebase ? $link =~ s#%b#$treebase#g : $link =~ s#%b##g;
+ $link =~ s/%([%nfhb])/$repl{$1}/g;
$arg{$label}{'_href'} = $link;
}
@@ -3230,7 +3456,7 @@ sub is_patch_split {
sub git_difftree_body {
my ($difftree, $hash, @parents) = @_;
my ($parent) = $parents[0];
- my ($have_blame) = gitweb_check_feature('blame');
+ my $have_blame = gitweb_check_feature('blame');
print "<div class=\"list_head\">\n";
if ($#{$difftree} > 10) {
print(($#{$difftree} + 1) . " files changed:\n");
@@ -3744,7 +3970,7 @@ sub git_project_list_body {
# actually uses global variable $project
my ($projlist, $order, $from, $to, $extra, $no_header) = @_;
- my ($check_forks) = gitweb_check_feature('forks');
+ my $check_forks = gitweb_check_feature('forks');
my @projects = fill_project_list_info($projlist, $check_forks);
$order ||= $default_projects_order;
@@ -4121,7 +4347,7 @@ sub git_search_grep_body {
## actions
sub git_project_list {
- my $order = $cgi->param('o');
+ my $order = $input_params{'order'};
if (defined $order && $order !~ m/none|project|descr|owner|age/) {
die_error(400, "Unknown order parameter");
}
@@ -4134,9 +4360,7 @@ sub git_project_list {
git_header_html();
if (-f $home_text) {
print "<div class=\"index_include\">\n";
- open (my $fd, $home_text);
- print <$fd>;
- close $fd;
+ insert_file($home_text);
print "</div>\n";
}
print $cgi->startform(-method => "get") .
@@ -4149,7 +4373,7 @@ sub git_project_list {
}
sub git_forks {
- my $order = $cgi->param('o');
+ my $order = $input_params{'order'};
if (defined $order && $order !~ m/none|project|descr|owner|age/) {
die_error(400, "Unknown order parameter");
}
@@ -4204,7 +4428,7 @@ sub git_summary {
my @taglist = git_get_tags_list(16);
my @headlist = git_get_heads_list(16);
my @forklist;
- my ($check_forks) = gitweb_check_feature('forks');
+ my $check_forks = gitweb_check_feature('forks');
if ($check_forks) {
@forklist = git_get_projects_list($project);
@@ -4233,7 +4457,7 @@ sub git_summary {
}
# Tag cloud
- my $show_ctags = (gitweb_check_feature('ctags'))[0];
+ my $show_ctags = gitweb_check_feature('ctags');
if ($show_ctags) {
my $ctags = git_get_project_ctags($project);
my $cloud = git_populate_project_tagcloud($ctags);
@@ -4248,13 +4472,10 @@ sub git_summary {
print "</table>\n";
if (-s "$projectroot/$project/README.html") {
- if (open my $fd, "$projectroot/$project/README.html") {
- print "<div class=\"title\">readme</div>\n" .
- "<div class=\"readme\">\n";
- print $_ while (<$fd>);
- print "\n</div>\n"; # class="readme"
- close $fd;
- }
+ print "<div class=\"title\">readme</div>\n" .
+ "<div class=\"readme\">\n";
+ insert_file("$projectroot/$project/README.html");
+ print "\n</div>\n"; # class="readme"
}
# we need to request one more than 16 (0..15) to check if
@@ -4332,28 +4553,33 @@ sub git_tag {
}
sub git_blame {
- my $fd;
- my $ftype;
-
+ # permissions
gitweb_check_feature('blame')
- or die_error(403, "Blame view not allowed");
+ or die_error(403, "Blame view not allowed");
+ # error checking
die_error(400, "No file name given") unless $file_name;
$hash_base ||= git_get_head_hash($project);
- die_error(404, "Couldn't find base commit") unless ($hash_base);
+ die_error(404, "Couldn't find base commit") unless $hash_base;
my %co = parse_commit($hash_base)
or die_error(404, "Commit not found");
+ my $ftype = "blob";
if (!defined $hash) {
$hash = git_get_hash_by_path($hash_base, $file_name, "blob")
or die_error(404, "Error looking up file");
+ } else {
+ $ftype = git_get_type($hash);
+ if ($ftype !~ "blob") {
+ die_error(400, "Object is not a blob");
+ }
}
- $ftype = git_get_type($hash);
- if ($ftype !~ "blob") {
- die_error(400, "Object is not a blob");
- }
- open ($fd, "-|", git_cmd(), "blame", '-p', '--',
- $file_name, $hash_base)
+
+ # run git-blame --porcelain
+ open my $fd, "-|", git_cmd(), "blame", '-p',
+ $hash_base, '--', $file_name
or die_error(500, "Open git-blame failed");
+
+ # page header
git_header_html();
my $formats_nav =
$cgi->a({-href => href(action=>"blob", -replay=>1)},
@@ -4367,42 +4593,46 @@ sub git_blame {
git_print_page_nav('','', $hash_base,$co{'tree'},$hash_base, $formats_nav);
git_print_header_div('commit', esc_html($co{'title'}), $hash_base);
git_print_page_path($file_name, $ftype, $hash_base);
- my @rev_color = (qw(light2 dark2));
+
+ # page body
+ my @rev_color = qw(light2 dark2);
my $num_colors = scalar(@rev_color);
my $current_color = 0;
- my $last_rev;
+ my %metainfo = ();
+
print <<HTML;
<div class="page_body">
<table class="blame">
<tr><th>Commit</th><th>Line</th><th>Data</th></tr>
HTML
- my %metainfo = ();
- while (1) {
- $_ = <$fd>;
- last unless defined $_;
+ LINE:
+ while (my $line = <$fd>) {
+ chomp $line;
+ # the header: <SHA-1> <src lineno> <dst lineno> [<lines in group>]
+ # no <lines in group> for subsequent lines in group of lines
my ($full_rev, $orig_lineno, $lineno, $group_size) =
- /^([0-9a-f]{40}) (\d+) (\d+)(?: (\d+))?$/;
+ ($line =~ /^([0-9a-f]{40}) (\d+) (\d+)(?: (\d+))?$/);
if (!exists $metainfo{$full_rev}) {
$metainfo{$full_rev} = {};
}
my $meta = $metainfo{$full_rev};
- while (<$fd>) {
- last if (s/^\t//);
- if (/^(\S+) (.*)$/) {
+ my $data;
+ while ($data = <$fd>) {
+ chomp $data;
+ last if ($data =~ s/^\t//); # contents of line
+ if ($data =~ /^(\S+) (.*)$/) {
$meta->{$1} = $2;
}
}
- my $data = $_;
- chomp $data;
- my $rev = substr($full_rev, 0, 8);
+ my $short_rev = substr($full_rev, 0, 8);
my $author = $meta->{'author'};
- my %date = parse_date($meta->{'author-time'},
- $meta->{'author-tz'});
+ my %date =
+ parse_date($meta->{'author-time'}, $meta->{'author-tz'});
my $date = $date{'iso-tz'};
if ($group_size) {
- $current_color = ++$current_color % $num_colors;
+ $current_color = ($current_color + 1) % $num_colors;
}
- print "<tr class=\"$rev_color[$current_color]\">\n";
+ print "<tr id=\"l$lineno\" class=\"$rev_color[$current_color]\">\n";
if ($group_size) {
print "<td class=\"sha1\"";
print " title=\"". esc_html($author) . ", $date\"";
@@ -4411,20 +4641,25 @@ HTML
print $cgi->a({-href => href(action=>"commit",
hash=>$full_rev,
file_name=>$file_name)},
- esc_html($rev));
+ esc_html($short_rev));
print "</td>\n";
}
- open (my $dd, "-|", git_cmd(), "rev-parse", "$full_rev^")
- or die_error(500, "Open git-rev-parse failed");
- my $parent_commit = <$dd>;
- close $dd;
- chomp($parent_commit);
+ my $parent_commit;
+ if (!exists $meta->{'parent'}) {
+ open (my $dd, "-|", git_cmd(), "rev-parse", "$full_rev^")
+ or die_error(500, "Open git-rev-parse failed");
+ $parent_commit = <$dd>;
+ close $dd;
+ chomp($parent_commit);
+ $meta->{'parent'} = $parent_commit;
+ } else {
+ $parent_commit = $meta->{'parent'};
+ }
my $blamed = href(action => 'blame',
file_name => $meta->{'filename'},
hash_base => $parent_commit);
print "<td class=\"linenr\">";
print $cgi->a({ -href => "$blamed#l$orig_lineno",
- -id => "l$lineno",
-class => "linenr" },
esc_html($lineno));
print "</td>";
@@ -4435,6 +4670,8 @@ HTML
print "</div>";
close $fd
or print "Reading blob failed\n";
+
+ # page footer
git_footer_html();
}
@@ -4523,7 +4760,7 @@ sub git_blob {
$expires = "+1d";
}
- my ($have_blame) = gitweb_check_feature('blame');
+ my $have_blame = gitweb_check_feature('blame');
open my $fd, "-|", git_cmd(), "cat-file", "blob", $hash
or die_error(500, "Couldn't cat $file_name, $hash");
my $mimetype = blob_mimetype($fd, $file_name);
@@ -4616,7 +4853,7 @@ sub git_tree {
my $ref = format_ref_marker($refs, $hash_base);
git_header_html();
my $basedir = '';
- my ($have_blame) = gitweb_check_feature('blame');
+ my $have_blame = gitweb_check_feature('blame');
if (defined $hash_base && (my %co = parse_commit($hash_base))) {
my @views_nav = ();
if (defined $file_name) {
@@ -4694,20 +4931,17 @@ sub git_tree {
}
sub git_snapshot {
- my @supported_fmts = gitweb_check_feature('snapshot');
- @supported_fmts = filter_snapshot_fmts(@supported_fmts);
-
- my $format = $cgi->param('sf');
- if (!@supported_fmts) {
+ my $format = $input_params{'snapshot_format'};
+ if (!@snapshot_fmts) {
die_error(403, "Snapshots not allowed");
}
# default to first supported snapshot format
- $format ||= $supported_fmts[0];
+ $format ||= $snapshot_fmts[0];
if ($format !~ m/^[a-z0-9]+$/) {
die_error(400, "Invalid snapshot format parameter");
} elsif (!exists($known_snapshot_formats{$format})) {
die_error(400, "Unknown snapshot format");
- } elsif (!grep($_ eq $format, @supported_fmts)) {
+ } elsif (!grep($_ eq $format, @snapshot_fmts)) {
die_error(403, "Unsupported snapshot format");
}
@@ -5045,43 +5279,9 @@ sub git_blobdiff {
or die_error(500, "Open git-diff-tree failed");
}
- # old/legacy style URI
- if (!%diffinfo && # if new style URI failed
- defined $hash && defined $hash_parent) {
- # fake git-diff-tree raw output
- $diffinfo{'from_mode'} = $diffinfo{'to_mode'} = "blob";
- $diffinfo{'from_id'} = $hash_parent;
- $diffinfo{'to_id'} = $hash;
- if (defined $file_name) {
- if (defined $file_parent) {
- $diffinfo{'status'} = '2';
- $diffinfo{'from_file'} = $file_parent;
- $diffinfo{'to_file'} = $file_name;
- } else { # assume not renamed
- $diffinfo{'status'} = '1';
- $diffinfo{'from_file'} = $file_name;
- $diffinfo{'to_file'} = $file_name;
- }
- } else { # no filename given
- $diffinfo{'status'} = '2';
- $diffinfo{'from_file'} = $hash_parent;
- $diffinfo{'to_file'} = $hash;
- }
-
- # non-textual hash id's can be cached
- if ($hash =~ m/^[0-9a-fA-F]{40}$/ &&
- $hash_parent =~ m/^[0-9a-fA-F]{40}$/) {
- $expires = '+1d';
- }
-
- # open patch output
- open $fd, "-|", git_cmd(), "diff", @diff_opts,
- '-p', ($format eq 'html' ? "--full-index" : ()),
- $hash_parent, $hash, "--"
- or die_error(500, "Open git-diff failed");
- } else {
- die_error(400, "Missing one of the blob diff parameters")
- unless %diffinfo;
+ # old/legacy style URI -- not generated anymore since 1.4.3.
+ if (!%diffinfo) {
+ die_error('404 Not Found', "Missing one of the blob diff parameters")
}
# header
@@ -5617,7 +5817,7 @@ insensitive).</p>
<dt><b>commit</b></dt>
<dd>The commit messages and authorship information will be scanned for the given pattern.</dd>
EOT
- my ($have_grep) = gitweb_check_feature('grep');
+ my $have_grep = gitweb_check_feature('grep');
if ($have_grep) {
print <<EOT;
<dt><b>grep</b></dt>
@@ -5634,7 +5834,7 @@ EOT
<dt><b>committer</b></dt>
<dd>Name and e-mail of the committer and date of commit will be scanned for the given pattern.</dd>
EOT
- my ($have_pickaxe) = gitweb_check_feature('pickaxe');
+ my $have_pickaxe = gitweb_check_feature('pickaxe');
if ($have_pickaxe) {
print <<EOT;
<dt><b>pickaxe</b></dt>
@@ -5686,7 +5886,7 @@ sub git_shortlog {
sub git_feed {
my $format = shift || 'atom';
- my ($have_blame) = gitweb_check_feature('blame');
+ my $have_blame = gitweb_check_feature('blame');
# Atom: http://www.atomenabled.org/developers/syndication/
# RSS: http://www.notestips.com/80256B3A007F2692/1/NAMO5P9UPQ
@@ -5939,8 +6139,8 @@ XML
}
my $path = esc_html(chop_str($proj{'path'}, 25, 5));
- my $rss = "$my_url?p=$proj{'path'};a=rss";
- my $html = "$my_url?p=$proj{'path'};a=summary";
+ my $rss = href('project' => $proj{'path'}, 'action' => 'rss', -full => 1);
+ my $html = href('project' => $proj{'path'}, 'action' => 'summary', -full => 1);
print "<outline type=\"rss\" text=\"$path\" title=\"$path\" xmlUrl=\"$rss\" htmlUrl=\"$html\"/>\n";
}
print <<XML;
diff --git a/grep.c b/grep.c
index e2c190a7f6..6485760ff3 100644
--- a/grep.c
+++ b/grep.c
@@ -28,9 +28,31 @@ void append_grep_pattern(struct grep_opt *opt, const char *pat,
p->next = NULL;
}
+static int isregexspecial(int c)
+{
+ return isspecial(c) || c == '$' || c == '(' || c == ')' || c == '+' ||
+ c == '.' || c == '^' || c == '{' || c == '|';
+}
+
+static int is_fixed(const char *s)
+{
+ while (!isregexspecial(*s))
+ s++;
+ return !*s;
+}
+
static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
{
- int err = regcomp(&p->regexp, p->pattern, opt->regflags);
+ int err;
+
+ if (opt->fixed || is_fixed(p->pattern))
+ p->fixed = 1;
+ if (opt->regflags & REG_ICASE)
+ p->fixed = 0;
+ if (p->fixed)
+ return;
+
+ err = regcomp(&p->regexp, p->pattern, opt->regflags);
if (err) {
char errbuf[1024];
char where[1024];
@@ -159,8 +181,7 @@ void compile_grep_patterns(struct grep_opt *opt)
case GREP_PATTERN: /* atom */
case GREP_PATTERN_HEAD:
case GREP_PATTERN_BODY:
- if (!opt->fixed)
- compile_regexp(p, opt);
+ compile_regexp(p, opt);
break;
default:
opt->extended = 1;
@@ -294,7 +315,6 @@ static struct {
static int match_one_pattern(struct grep_opt *opt, struct grep_pat *p, char *bol, char *eol, enum grep_context ctx)
{
int hit = 0;
- int at_true_bol = 1;
int saved_ch = 0;
regmatch_t pmatch[10];
@@ -315,7 +335,7 @@ static int match_one_pattern(struct grep_opt *opt, struct grep_pat *p, char *bol
}
again:
- if (!opt->fixed) {
+ if (!p->fixed) {
regex_t *exp = &p->regexp;
hit = !regexec(exp, bol, ARRAY_SIZE(pmatch),
pmatch, 0);
@@ -337,7 +357,7 @@ static int match_one_pattern(struct grep_opt *opt, struct grep_pat *p, char *bol
* either end of the line, or at word boundary
* (i.e. the next char must not be a word char).
*/
- if ( ((pmatch[0].rm_so == 0 && at_true_bol) ||
+ if ( ((pmatch[0].rm_so == 0) ||
!word_char(bol[pmatch[0].rm_so-1])) &&
((pmatch[0].rm_eo == (eol-bol)) ||
!word_char(bol[pmatch[0].rm_eo])) )
@@ -349,10 +369,14 @@ static int match_one_pattern(struct grep_opt *opt, struct grep_pat *p, char *bol
/* There could be more than one match on the
* line, and the first match might not be
* strict word match. But later ones could be!
+ * Forward to the next possible start, i.e. the
+ * next position following a non-word char.
*/
bol = pmatch[0].rm_so + bol + 1;
- at_true_bol = 0;
- goto again;
+ while (word_char(bol[-1]) && bol < eol)
+ bol++;
+ if (bol < eol)
+ goto again;
}
}
if (p->token == GREP_PATTERN_HEAD && saved_ch)
@@ -395,7 +419,7 @@ static int match_expr_eval(struct grep_opt *o,
h |= match_expr_eval(o, x->u.binary.right, bol, eol, ctx, 1);
break;
default:
- die("Unexpected node type (internal error) %d\n", x->node);
+ die("Unexpected node type (internal error) %d", x->node);
}
if (collect_hits)
x->hit |= h;
@@ -514,7 +538,7 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
if (from <= last_shown)
from = last_shown + 1;
if (last_shown && from != last_shown + 1)
- printf(hunk_mark);
+ fputs(hunk_mark, stdout);
while (from < lno) {
pcl = &prev[lno-from-1];
show_line(opt, pcl->bol, pcl->eol,
@@ -524,7 +548,7 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
last_shown = lno-1;
}
if (last_shown && lno != last_shown + 1)
- printf(hunk_mark);
+ fputs(hunk_mark, stdout);
if (!opt->count)
show_line(opt, bol, eol, name, lno, ':');
last_shown = last_hit = lno;
@@ -535,7 +559,7 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
* we need to show this line.
*/
if (last_shown && lno != last_shown + 1)
- printf(hunk_mark);
+ fputs(hunk_mark, stdout);
show_line(opt, bol, eol, name, lno, '-');
last_shown = lno;
}
diff --git a/grep.h b/grep.h
index 45a222d904..5102ce335d 100644
--- a/grep.h
+++ b/grep.h
@@ -30,6 +30,7 @@ struct grep_pat {
const char *pattern;
enum grep_header_field field;
regex_t regexp;
+ unsigned fixed:1;
};
enum grep_expr_node {
diff --git a/hash-object.c b/hash-object.c
index 20937ff94c..846e91a231 100644
--- a/hash-object.c
+++ b/hash-object.c
@@ -110,7 +110,7 @@ int main(int argc, const char **argv)
}
if (errstr) {
- error (errstr);
+ error("%s", errstr);
usage_with_options(hash_object_usage, hash_object_options);
}
diff --git a/http-push.c b/http-push.c
index 42f4d78e54..6ad853e2d0 100644
--- a/http-push.c
+++ b/http-push.c
@@ -87,6 +87,7 @@ static struct object_list *objects;
struct repo
{
char *url;
+ char *path;
int path_len;
int has_info_refs;
int can_update_info_refs;
@@ -595,7 +596,7 @@ static int refresh_lock(struct remote_lock *lock)
lock->refreshing = 1;
if_header = xmalloc(strlen(lock->token) + 25);
- sprintf(if_header, "If: (<opaquelocktoken:%s>)", lock->token);
+ sprintf(if_header, "If: (<%s>)", lock->token);
sprintf(timeout_header, "Timeout: Second-%ld", lock->timeout);
dav_headers = curl_slist_append(dav_headers, if_header);
dav_headers = curl_slist_append(dav_headers, timeout_header);
@@ -1120,10 +1121,8 @@ static void handle_new_lock_ctx(struct xml_ctx *ctx, int tag_closed)
lock->timeout =
strtol(ctx->cdata + 7, NULL, 10);
} else if (!strcmp(ctx->name, DAV_ACTIVELOCK_TOKEN)) {
- if (!prefixcmp(ctx->cdata, "opaquelocktoken:")) {
- lock->token = xmalloc(strlen(ctx->cdata) - 15);
- strcpy(lock->token, ctx->cdata + 16);
- }
+ lock->token = xmalloc(strlen(ctx->cdata) + 1);
+ strcpy(lock->token, ctx->cdata);
}
}
}
@@ -1202,7 +1201,8 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
/* Make sure leading directories exist for the remote ref */
ep = strchr(url + strlen(remote->url) + 1, '/');
while (ep) {
- *ep = 0;
+ char saved_character = ep[1];
+ ep[1] = '\0';
slot = get_active_slot();
slot->results = &results;
curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
@@ -1224,7 +1224,7 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
free(url);
return NULL;
}
- *ep = '/';
+ ep[1] = saved_character;
ep = strchr(ep + 1, '/');
}
@@ -1308,7 +1308,7 @@ static int unlock_remote(struct remote_lock *lock)
int rc = 0;
lock_token_header = xmalloc(strlen(lock->token) + 31);
- sprintf(lock_token_header, "Lock-Token: <opaquelocktoken:%s>",
+ sprintf(lock_token_header, "Lock-Token: <%s>",
lock->token);
dav_headers = curl_slist_append(dav_headers, lock_token_header);
@@ -1426,9 +1426,17 @@ static void handle_remote_ls_ctx(struct xml_ctx *ctx, int tag_closed)
ls->userFunc(ls);
}
} else if (!strcmp(ctx->name, DAV_PROPFIND_NAME) && ctx->cdata) {
- ls->dentry_name = xmalloc(strlen(ctx->cdata) -
- remote->path_len + 1);
- strcpy(ls->dentry_name, ctx->cdata + remote->path_len);
+ char *path = ctx->cdata;
+ if (*ctx->cdata == 'h') {
+ path = strstr(path, "//");
+ if (path) {
+ path = strchr(path+2, '/');
+ }
+ }
+ if (path) {
+ path += remote->path_len;
+ ls->dentry_name = xstrdup(path);
+ }
} else if (!strcmp(ctx->name, DAV_PROPFIND_COLLECTION)) {
ls->dentry_flags |= IS_DIR;
}
@@ -1439,6 +1447,12 @@ static void handle_remote_ls_ctx(struct xml_ctx *ctx, int tag_closed)
}
}
+/*
+ * NEEDSWORK: remote_ls() ignores info/refs on the remote side. But it
+ * should _only_ heed the information from that file, instead of trying to
+ * determine the refs from the remote file system (badly: it does not even
+ * know about packed-refs).
+ */
static void remote_ls(const char *path, int flags,
void (*userFunc)(struct remote_ls_ctx *ls),
void *userData)
@@ -1722,7 +1736,7 @@ static int update_remote(unsigned char *sha1, struct remote_lock *lock)
struct curl_slist *dav_headers = NULL;
if_header = xmalloc(strlen(lock->token) + 25);
- sprintf(if_header, "If: (<opaquelocktoken:%s>)", lock->token);
+ sprintf(if_header, "If: (<%s>)", lock->token);
dav_headers = curl_slist_append(dav_headers, if_header);
strbuf_addf(&out_buffer.buf, "%s\n", sha1_to_hex(sha1));
@@ -1780,7 +1794,7 @@ static void one_remote_ref(char *refname)
struct ref *ref;
struct object *obj;
- ref = alloc_ref_from_str(refname);
+ ref = alloc_ref(refname);
if (http_fetch_ref(remote->url, ref) != 0) {
fprintf(stderr,
@@ -1887,7 +1901,7 @@ static void add_remote_info_ref(struct remote_ls_ctx *ls)
char *ref_info;
struct ref *ref;
- ref = alloc_ref_from_str(ls->dentry_name);
+ ref = alloc_ref(ls->dentry_name);
if (http_fetch_ref(remote->url, ref) != 0) {
fprintf(stderr,
@@ -1941,7 +1955,7 @@ static void update_remote_info_refs(struct remote_lock *lock)
add_remote_info_ref, &buffer.buf);
if (!aborted) {
if_header = xmalloc(strlen(lock->token) + 25);
- sprintf(if_header, "If: (<opaquelocktoken:%s>)", lock->token);
+ sprintf(if_header, "If: (<%s>)", lock->token);
dav_headers = curl_slist_append(dav_headers, if_header);
slot = get_active_slot();
@@ -2208,10 +2222,11 @@ int main(int argc, char **argv)
if (!remote->url) {
char *path = strstr(arg, "//");
remote->url = arg;
+ remote->path_len = strlen(arg);
if (path) {
- path = strchr(path+2, '/');
- if (path)
- remote->path_len = strlen(path);
+ remote->path = strchr(path+2, '/');
+ if (remote->path)
+ remote->path_len = strlen(remote->path);
}
continue;
}
@@ -2240,8 +2255,9 @@ int main(int argc, char **argv)
rewritten_url = xmalloc(strlen(remote->url)+2);
strcpy(rewritten_url, remote->url);
strcat(rewritten_url, "/");
+ remote->path = rewritten_url + (remote->path - remote->url);
+ remote->path_len++;
remote->url = rewritten_url;
- ++remote->path_len;
}
/* Verify DAV compliance/lock support */
diff --git a/http.c b/http.c
index ed59b79709..ee58799ca8 100644
--- a/http.c
+++ b/http.c
@@ -24,7 +24,7 @@ static const char *ssl_cainfo = NULL;
static long curl_low_speed_limit = -1;
static long curl_low_speed_time = -1;
static int curl_ftp_no_epsv = 0;
-static char *curl_http_proxy = NULL;
+static const char *curl_http_proxy = NULL;
static struct curl_slist *pragma_header;
@@ -149,11 +149,8 @@ static int http_options(const char *var, const char *value, void *cb)
return 0;
}
if (!strcmp("http.proxy", var)) {
- if (curl_http_proxy == NULL) {
- if (!value)
- return config_error_nonbool(var);
- curl_http_proxy = xstrdup(value);
- }
+ if (curl_http_proxy == NULL)
+ return git_config_string(&curl_http_proxy, var, value);
return 0;
}
@@ -309,7 +306,7 @@ void http_cleanup(void)
pragma_header = NULL;
if (curl_http_proxy) {
- free(curl_http_proxy);
+ free((void *)curl_http_proxy);
curl_http_proxy = NULL;
}
}
diff --git a/ident.c b/ident.c
index 09cf0c95c9..99f1c85ea5 100644
--- a/ident.c
+++ b/ident.c
@@ -121,6 +121,7 @@ static int crud(unsigned char c)
c == '<' ||
c == '>' ||
c == '"' ||
+ c == '\\' ||
c == '\'';
}
diff --git a/imap-send.c b/imap-send.c
index 3703dbd1af..c3fa0df855 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -115,9 +115,9 @@ static int nfvasprintf(char **strp, const char *fmt, va_list ap)
len = vsnprintf(tmp, sizeof(tmp), fmt, ap);
if (len < 0)
- die("Fatal: Out of memory\n");
+ die("Fatal: Out of memory");
if (len >= sizeof(tmp))
- die("imap command overflow !\n");
+ die("imap command overflow!");
*strp = xmemdupz(tmp, len);
return len;
}
@@ -482,7 +482,7 @@ static int nfsnprintf(char *buf, int blen, const char *fmt, ...)
va_start(va, fmt);
if (blen <= 0 || (unsigned)(ret = vsnprintf(buf, blen, fmt, va)) >= (unsigned)blen)
- die("Fatal: buffer too small. Please report a bug.\n");
+ die("Fatal: buffer too small. Please report a bug.");
va_end(va);
return ret;
}
diff --git a/index-pack.c b/index-pack.c
index d3a4d31b4e..2931511e8c 100644
--- a/index-pack.c
+++ b/index-pack.c
@@ -178,7 +178,7 @@ static char *open_pack_file(char *pack_name)
} else
output_fd = open(pack_name, O_CREAT|O_EXCL|O_RDWR, 0600);
if (output_fd < 0)
- die("unable to create %s: %s\n", pack_name, strerror(errno));
+ die("unable to create %s: %s", pack_name, strerror(errno));
pack_fd = output_fd;
} else {
input_fd = open(pack_name, O_RDONLY);
@@ -221,17 +221,23 @@ static void bad_object(unsigned long offset, const char *format, ...)
die("pack has bad object at offset %lu: %s", offset, buf);
}
+static void free_base_data(struct base_data *c)
+{
+ if (c->data) {
+ free(c->data);
+ c->data = NULL;
+ base_cache_used -= c->size;
+ }
+}
+
static void prune_base_data(struct base_data *retain)
{
struct base_data *b = base_cache;
for (b = base_cache;
base_cache_used > delta_base_cache_limit && b;
b = b->child) {
- if (b->data && b != retain) {
- free(b->data);
- b->data = NULL;
- base_cache_used -= b->size;
- }
+ if (b->data && b != retain)
+ free_base_data(b);
}
}
@@ -244,7 +250,8 @@ static void link_base_data(struct base_data *base, struct base_data *c)
c->base = base;
c->child = NULL;
- base_cache_used += c->size;
+ if (c->data)
+ base_cache_used += c->size;
prune_base_data(c);
}
@@ -255,10 +262,7 @@ static void unlink_base_data(struct base_data *c)
base->child = NULL;
else
base_cache = NULL;
- if (c->data) {
- free(c->data);
- base_cache_used -= c->size;
- }
+ free_base_data(c);
}
static void *unpack_entry_data(unsigned long offset, unsigned long size)
@@ -334,7 +338,7 @@ static void *unpack_raw_entry(struct object_entry *obj, union delta_base *delta_
base_offset = (base_offset << 7) + (c & 127);
}
delta_base->offset = obj->idx.offset - base_offset;
- if (delta_base->offset >= obj->idx.offset)
+ if (delta_base->offset <= 0 || delta_base->offset >= obj->idx.offset)
bad_object(obj->idx.offset, "delta base offset is out of bound");
break;
case OBJ_COMMIT:
@@ -408,22 +412,24 @@ static int find_delta(const union delta_base *base)
return -first-1;
}
-static int find_delta_children(const union delta_base *base,
- int *first_index, int *last_index)
+static void find_delta_children(const union delta_base *base,
+ int *first_index, int *last_index)
{
int first = find_delta(base);
int last = first;
int end = nr_deltas - 1;
- if (first < 0)
- return -1;
+ if (first < 0) {
+ *first_index = 0;
+ *last_index = -1;
+ return;
+ }
while (first > 0 && !memcmp(&deltas[first - 1].base, base, UNION_BASE_SZ))
--first;
while (last < end && !memcmp(&deltas[last + 1].base, base, UNION_BASE_SZ))
++last;
*first_index = first;
*last_index = last;
- return 0;
}
static void sha1_object(const void *data, unsigned long size,
@@ -494,8 +500,10 @@ static void *get_base_data(struct base_data *c)
free(raw);
if (!c->data)
bad_object(obj->idx.offset, "failed to apply delta");
- } else
+ } else {
c->data = get_data_from_pack(obj);
+ c->size = obj->size;
+ }
base_cache_used += c->size;
prune_base_data(c);
@@ -504,49 +512,74 @@ static void *get_base_data(struct base_data *c)
}
static void resolve_delta(struct object_entry *delta_obj,
- struct base_data *base_obj, enum object_type type)
+ struct base_data *base, struct base_data *result)
{
- void *delta_data;
- unsigned long delta_size;
- union delta_base delta_base;
- int j, first, last;
- struct base_data result;
+ void *base_data, *delta_data;
- delta_obj->real_type = type;
+ delta_obj->real_type = base->obj->real_type;
delta_data = get_data_from_pack(delta_obj);
- delta_size = delta_obj->size;
- result.data = patch_delta(get_base_data(base_obj), base_obj->size,
- delta_data, delta_size,
- &result.size);
+ base_data = get_base_data(base);
+ result->obj = delta_obj;
+ result->data = patch_delta(base_data, base->size,
+ delta_data, delta_obj->size, &result->size);
free(delta_data);
- if (!result.data)
+ if (!result->data)
bad_object(delta_obj->idx.offset, "failed to apply delta");
- sha1_object(result.data, result.size, type, delta_obj->idx.sha1);
+ sha1_object(result->data, result->size, delta_obj->real_type,
+ delta_obj->idx.sha1);
nr_resolved_deltas++;
+}
- result.obj = delta_obj;
- link_base_data(base_obj, &result);
+static void find_unresolved_deltas(struct base_data *base,
+ struct base_data *prev_base)
+{
+ int i, ref_first, ref_last, ofs_first, ofs_last;
+
+ /*
+ * This is a recursive function. Those brackets should help reducing
+ * stack usage by limiting the scope of the delta_base union.
+ */
+ {
+ union delta_base base_spec;
+
+ hashcpy(base_spec.sha1, base->obj->idx.sha1);
+ find_delta_children(&base_spec, &ref_first, &ref_last);
+
+ memset(&base_spec, 0, sizeof(base_spec));
+ base_spec.offset = base->obj->idx.offset;
+ find_delta_children(&base_spec, &ofs_first, &ofs_last);
+ }
+
+ if (ref_last == -1 && ofs_last == -1) {
+ free(base->data);
+ return;
+ }
+
+ link_base_data(prev_base, base);
- hashcpy(delta_base.sha1, delta_obj->idx.sha1);
- if (!find_delta_children(&delta_base, &first, &last)) {
- for (j = first; j <= last; j++) {
- struct object_entry *child = objects + deltas[j].obj_no;
- if (child->real_type == OBJ_REF_DELTA)
- resolve_delta(child, &result, type);
+ for (i = ref_first; i <= ref_last; i++) {
+ struct object_entry *child = objects + deltas[i].obj_no;
+ if (child->real_type == OBJ_REF_DELTA) {
+ struct base_data result;
+ resolve_delta(child, base, &result);
+ if (i == ref_last && ofs_last == -1)
+ free_base_data(base);
+ find_unresolved_deltas(&result, base);
}
}
- memset(&delta_base, 0, sizeof(delta_base));
- delta_base.offset = delta_obj->idx.offset;
- if (!find_delta_children(&delta_base, &first, &last)) {
- for (j = first; j <= last; j++) {
- struct object_entry *child = objects + deltas[j].obj_no;
- if (child->real_type == OBJ_OFS_DELTA)
- resolve_delta(child, &result, type);
+ for (i = ofs_first; i <= ofs_last; i++) {
+ struct object_entry *child = objects + deltas[i].obj_no;
+ if (child->real_type == OBJ_OFS_DELTA) {
+ struct base_data result;
+ resolve_delta(child, base, &result);
+ if (i == ofs_last)
+ free_base_data(base);
+ find_unresolved_deltas(&result, base);
}
}
- unlink_base_data(&result);
+ unlink_base_data(base);
}
static int compare_delta_entry(const void *a, const void *b)
@@ -622,37 +655,13 @@ static void parse_pack_objects(unsigned char *sha1)
progress = start_progress("Resolving deltas", nr_deltas);
for (i = 0; i < nr_objects; i++) {
struct object_entry *obj = &objects[i];
- union delta_base base;
- int j, ref, ref_first, ref_last, ofs, ofs_first, ofs_last;
struct base_data base_obj;
if (obj->type == OBJ_REF_DELTA || obj->type == OBJ_OFS_DELTA)
continue;
- hashcpy(base.sha1, obj->idx.sha1);
- ref = !find_delta_children(&base, &ref_first, &ref_last);
- memset(&base, 0, sizeof(base));
- base.offset = obj->idx.offset;
- ofs = !find_delta_children(&base, &ofs_first, &ofs_last);
- if (!ref && !ofs)
- continue;
- base_obj.data = get_data_from_pack(obj);
- base_obj.size = obj->size;
base_obj.obj = obj;
- link_base_data(NULL, &base_obj);
-
- if (ref)
- for (j = ref_first; j <= ref_last; j++) {
- struct object_entry *child = objects + deltas[j].obj_no;
- if (child->real_type == OBJ_REF_DELTA)
- resolve_delta(child, &base_obj, obj->type);
- }
- if (ofs)
- for (j = ofs_first; j <= ofs_last; j++) {
- struct object_entry *child = objects + deltas[j].obj_no;
- if (child->real_type == OBJ_OFS_DELTA)
- resolve_delta(child, &base_obj, obj->type);
- }
- unlink_base_data(&base_obj);
+ base_obj.data = NULL;
+ find_unresolved_deltas(&base_obj, NULL);
display_progress(progress, nr_resolved_deltas);
}
}
@@ -745,7 +754,6 @@ static void fix_unresolved_deltas(struct sha1file *f, int nr_unresolved)
for (i = 0; i < n; i++) {
struct delta_entry *d = sorted_by_pos[i];
enum object_type type;
- int j, first, last;
struct base_data base_obj;
if (objects[d->obj_no].real_type != OBJ_REF_DELTA)
@@ -759,16 +767,7 @@ static void fix_unresolved_deltas(struct sha1file *f, int nr_unresolved)
die("local object %s is corrupt", sha1_to_hex(d->base.sha1));
base_obj.obj = append_obj_to_pack(f, d->base.sha1,
base_obj.data, base_obj.size, type);
- link_base_data(NULL, &base_obj);
-
- find_delta_children(&d->base, &first, &last);
- for (j = first; j <= last; j++) {
- struct object_entry *child = objects + deltas[j].obj_no;
- if (child->real_type == OBJ_REF_DELTA)
- resolve_delta(child, &base_obj, type);
- }
-
- unlink_base_data(&base_obj);
+ find_unresolved_deltas(&base_obj, NULL);
display_progress(progress, nr_resolved_deltas);
}
free(sorted_by_pos);
@@ -790,7 +789,6 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
err = close(output_fd);
if (err)
die("error while closing pack file: %s", strerror(errno));
- chmod(curr_pack_name, 0444);
}
if (keep_msg) {
@@ -824,8 +822,9 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
if (move_temp_to_file(curr_pack_name, final_pack_name))
die("cannot store pack file");
}
+ if (from_stdin)
+ chmod(final_pack_name, 0444);
- chmod(curr_index_name, 0444);
if (final_index_name != curr_index_name) {
if (!final_index_name) {
snprintf(name, sizeof(name), "%s/pack/pack-%s.idx",
@@ -835,6 +834,7 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
if (move_temp_to_file(curr_index_name, final_index_name))
die("cannot store index file");
}
+ chmod(final_index_name, 0444);
if (!from_stdin) {
printf("%s\n", sha1_to_hex(sha1));
@@ -879,10 +879,26 @@ int main(int argc, char **argv)
char *index_name_buf = NULL, *keep_name_buf = NULL;
struct pack_idx_entry **idx_objects;
unsigned char pack_sha1[20];
- int nongit = 0;
- setup_git_directory_gently(&nongit);
- git_config(git_index_pack_config, NULL);
+ /*
+ * We wish to read the repository's config file if any, and
+ * for that it is necessary to call setup_git_directory_gently().
+ * However if the cwd was inside .git/objects/pack/ then we need
+ * to go back there or all the pack name arguments will be wrong.
+ * And in that case we cannot rely on any prefix returned by
+ * setup_git_directory_gently() either.
+ */
+ {
+ char cwd[PATH_MAX+1];
+ int nongit;
+
+ if (!getcwd(cwd, sizeof(cwd)-1))
+ die("Unable to get current working directory");
+ setup_git_directory_gently(&nongit);
+ git_config(git_index_pack_config, NULL);
+ if (chdir(cwd))
+ die("Cannot come back to cwd");
+ }
for (i = 1; i < argc; i++) {
char *arg = argv[i];
diff --git a/interpolate.c b/interpolate.c
deleted file mode 100644
index 7f03bd99c5..0000000000
--- a/interpolate.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright 2006 Jon Loeliger
- */
-
-#include "git-compat-util.h"
-#include "interpolate.h"
-
-
-void interp_set_entry(struct interp *table, int slot, const char *value)
-{
- char *oldval = table[slot].value;
- char *newval = NULL;
-
- free(oldval);
-
- if (value)
- newval = xstrdup(value);
-
- table[slot].value = newval;
-}
-
-
-void interp_clear_table(struct interp *table, int ninterps)
-{
- int i;
-
- for (i = 0; i < ninterps; i++) {
- interp_set_entry(table, i, NULL);
- }
-}
-
-
-/*
- * Convert a NUL-terminated string in buffer orig
- * into the supplied buffer, result, whose length is reslen,
- * performing substitutions on %-named sub-strings from
- * the table, interps, with ninterps entries.
- *
- * Example interps:
- * {
- * { "%H", "example.org"},
- * { "%port", "123"},
- * { "%%", "%"},
- * }
- *
- * Returns the length of the substituted string (not including the final \0).
- * Like with snprintf, if the result is >= reslen, then it overflowed.
- */
-
-unsigned long interpolate(char *result, unsigned long reslen,
- const char *orig,
- const struct interp *interps, int ninterps)
-{
- const char *src = orig;
- char *dest = result;
- unsigned long newlen = 0;
- const char *name, *value;
- unsigned long namelen, valuelen;
- int i;
- char c;
-
- while ((c = *src)) {
- if (c == '%') {
- /* Try to match an interpolation string. */
- for (i = 0; i < ninterps; i++) {
- name = interps[i].name;
- namelen = strlen(name);
- if (strncmp(src, name, namelen) == 0)
- break;
- }
-
- /* Check for valid interpolation. */
- if (i < ninterps) {
- value = interps[i].value;
- if (!value) {
- src += namelen;
- continue;
- }
-
- valuelen = strlen(value);
- if (newlen + valuelen < reslen) {
- /* Substitute. */
- memcpy(dest, value, valuelen);
- dest += valuelen;
- }
- newlen += valuelen;
- src += namelen;
- continue;
- }
- }
- /* Straight copy one non-interpolation character. */
- if (newlen + 1 < reslen)
- *dest++ = *src;
- src++;
- newlen++;
- }
-
- /* XXX: the previous loop always keep room for the ending NUL,
- we just need to check if there was room for a NUL in the first place */
- if (reslen > 0)
- *dest = '\0';
- return newlen;
-}
diff --git a/interpolate.h b/interpolate.h
deleted file mode 100644
index 77407e67dc..0000000000
--- a/interpolate.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2006 Jon Loeliger
- */
-
-#ifndef INTERPOLATE_H
-#define INTERPOLATE_H
-
-/*
- * Convert a NUL-terminated string in buffer orig,
- * performing substitutions on %-named sub-strings from
- * the interpretation table.
- */
-
-struct interp {
- const char *name;
- char *value;
-};
-
-extern void interp_set_entry(struct interp *table, int slot, const char *value);
-extern void interp_clear_table(struct interp *table, int ninterps);
-
-extern unsigned long interpolate(char *result, unsigned long reslen,
- const char *orig,
- const struct interp *interps, int ninterps);
-
-#endif /* INTERPOLATE_H */
diff --git a/levenshtein.c b/levenshtein.c
index db52f2c205..a32f4cdc45 100644
--- a/levenshtein.c
+++ b/levenshtein.c
@@ -1,6 +1,43 @@
#include "cache.h"
#include "levenshtein.h"
+/*
+ * This function implements the Damerau-Levenshtein algorithm to
+ * calculate a distance between strings.
+ *
+ * Basically, it says how many letters need to be swapped, substituted,
+ * deleted from, or added to string1, at least, to get string2.
+ *
+ * The idea is to build a distance matrix for the substrings of both
+ * strings. To avoid a large space complexity, only the last three rows
+ * are kept in memory (if swaps had the same or higher cost as one deletion
+ * plus one insertion, only two rows would be needed).
+ *
+ * At any stage, "i + 1" denotes the length of the current substring of
+ * string1 that the distance is calculated for.
+ *
+ * row2 holds the current row, row1 the previous row (i.e. for the substring
+ * of string1 of length "i"), and row0 the row before that.
+ *
+ * In other words, at the start of the big loop, row2[j + 1] contains the
+ * Damerau-Levenshtein distance between the substring of string1 of length
+ * "i" and the substring of string2 of length "j + 1".
+ *
+ * All the big loop does is determine the partial minimum-cost paths.
+ *
+ * It does so by calculating the costs of the path ending in characters
+ * i (in string1) and j (in string2), respectively, given that the last
+ * operation is a substition, a swap, a deletion, or an insertion.
+ *
+ * This implementation allows the costs to be weighted:
+ *
+ * - w (as in "sWap")
+ * - s (as in "Substitution")
+ * - a (for insertion, AKA "Add")
+ * - d (as in "Deletion")
+ *
+ * Note that this algorithm calculates a distance _iff_ d == a.
+ */
int levenshtein(const char *string1, const char *string2,
int w, int s, int a, int d)
{
@@ -25,7 +62,7 @@ int levenshtein(const char *string1, const char *string2,
row2[j + 1] > row0[j - 1] + w)
row2[j + 1] = row0[j - 1] + w;
/* deletion */
- if (j + 1 < len2 && row2[j + 1] > row1[j + 1] + d)
+ if (row2[j + 1] > row1[j + 1] + d)
row2[j + 1] = row1[j + 1] + d;
/* insertion */
if (row2[j + 1] > row2[j] + a)
diff --git a/ll-merge.c b/ll-merge.c
index 4a716146f6..fa2ca5250c 100644
--- a/ll-merge.c
+++ b/ll-merge.c
@@ -8,7 +8,6 @@
#include "attr.h"
#include "xdiff-interface.h"
#include "run-command.h"
-#include "interpolate.h"
#include "ll-merge.h"
struct ll_merge_driver;
@@ -169,11 +168,12 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
int virtual_ancestor)
{
char temp[3][50];
- char cmdbuf[2048];
- struct interp table[] = {
- { "%O" },
- { "%A" },
- { "%B" },
+ struct strbuf cmd = STRBUF_INIT;
+ struct strbuf_expand_dict_entry dict[] = {
+ { "O", temp[0] },
+ { "A", temp[1] },
+ { "B", temp[2] },
+ { NULL }
};
struct child_process child;
const char *args[20];
@@ -189,17 +189,13 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
create_temp(src1, temp[1]);
create_temp(src2, temp[2]);
- interp_set_entry(table, 0, temp[0]);
- interp_set_entry(table, 1, temp[1]);
- interp_set_entry(table, 2, temp[2]);
-
- interpolate(cmdbuf, sizeof(cmdbuf), fn->cmdline, table, 3);
+ strbuf_expand(&cmd, fn->cmdline, strbuf_expand_dict_cb, &dict);
memset(&child, 0, sizeof(child));
child.argv = args;
args[0] = "sh";
args[1] = "-c";
- args[2] = cmdbuf;
+ args[2] = cmd.buf;
args[3] = NULL;
status = run_command(&child);
@@ -224,6 +220,7 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
bad:
for (i = 0; i < 3; i++)
unlink(temp[i]);
+ strbuf_release(&cmd);
return status;
}
diff --git a/lockfile.c b/lockfile.c
index 4023797b00..8589155532 100644
--- a/lockfile.c
+++ b/lockfile.c
@@ -121,15 +121,17 @@ static char *resolve_symlink(char *p, size_t s)
}
-static int lock_file(struct lock_file *lk, const char *path)
+static int lock_file(struct lock_file *lk, const char *path, int flags)
{
- if (strlen(path) >= sizeof(lk->filename)) return -1;
+ if (strlen(path) >= sizeof(lk->filename))
+ return -1;
strcpy(lk->filename, path);
/*
* subtract 5 from size to make sure there's room for adding
* ".lock" for the lock file name
*/
- resolve_symlink(lk->filename, sizeof(lk->filename)-5);
+ if (!(flags & LOCK_NODEREF))
+ resolve_symlink(lk->filename, sizeof(lk->filename)-5);
strcat(lk->filename, ".lock");
lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);
if (0 <= lk->fd) {
@@ -138,6 +140,7 @@ static int lock_file(struct lock_file *lk, const char *path)
signal(SIGHUP, remove_lock_file_on_signal);
signal(SIGTERM, remove_lock_file_on_signal);
signal(SIGQUIT, remove_lock_file_on_signal);
+ signal(SIGPIPE, remove_lock_file_on_signal);
atexit(remove_lock_file);
}
lk->owner = getpid();
@@ -155,21 +158,21 @@ static int lock_file(struct lock_file *lk, const char *path)
return lk->fd;
}
-int hold_lock_file_for_update(struct lock_file *lk, const char *path, int die_on_error)
+int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags)
{
- int fd = lock_file(lk, path);
- if (fd < 0 && die_on_error)
+ int fd = lock_file(lk, path, flags);
+ if (fd < 0 && (flags & LOCK_DIE_ON_ERROR))
die("unable to create '%s.lock': %s", path, strerror(errno));
return fd;
}
-int hold_lock_file_for_append(struct lock_file *lk, const char *path, int die_on_error)
+int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
{
int fd, orig_fd;
- fd = lock_file(lk, path);
+ fd = lock_file(lk, path, flags);
if (fd < 0) {
- if (die_on_error)
+ if (flags & LOCK_DIE_ON_ERROR)
die("unable to create '%s.lock': %s", path, strerror(errno));
return fd;
}
@@ -177,13 +180,13 @@ int hold_lock_file_for_append(struct lock_file *lk, const char *path, int die_on
orig_fd = open(path, O_RDONLY);
if (orig_fd < 0) {
if (errno != ENOENT) {
- if (die_on_error)
+ if (flags & LOCK_DIE_ON_ERROR)
die("cannot open '%s' for copying", path);
close(fd);
return error("cannot open '%s' for copying", path);
}
} else if (copy_fd(orig_fd, fd)) {
- if (die_on_error)
+ if (flags & LOCK_DIE_ON_ERROR)
exit(128);
close(fd);
return -1;
@@ -215,7 +218,10 @@ int commit_lock_file(struct lock_file *lk)
int hold_locked_index(struct lock_file *lk, int die_on_error)
{
- return hold_lock_file_for_update(lk, get_index_file(), die_on_error);
+ return hold_lock_file_for_update(lk, get_index_file(),
+ die_on_error
+ ? LOCK_DIE_ON_ERROR
+ : 0);
}
void set_alternate_index_output(const char *name)
diff --git a/log-tree.c b/log-tree.c
index cec3c06136..194ddb13da 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -52,11 +52,15 @@ static void show_parents(struct commit *commit, int abbrev)
}
}
-void show_decorations(struct commit *commit)
+void show_decorations(struct rev_info *opt, struct commit *commit)
{
const char *prefix;
struct name_decoration *decoration;
+ if (opt->show_source && commit->util)
+ printf("\t%s", (char *) commit->util);
+ if (!opt->show_decorations)
+ return;
decoration = lookup_decoration(&name_decoration, &commit->object);
if (!decoration)
return;
@@ -279,7 +283,7 @@ void show_log(struct rev_info *opt)
fputs(diff_unique_abbrev(commit->object.sha1, abbrev_commit), stdout);
if (opt->print_parents)
show_parents(commit, abbrev_commit);
- show_decorations(commit);
+ show_decorations(opt, commit);
if (opt->graph && !graph_is_commit_finished(opt->graph)) {
putchar('\n');
graph_show_remainder(opt->graph);
@@ -352,7 +356,7 @@ void show_log(struct rev_info *opt)
printf(" (from %s)",
diff_unique_abbrev(parent->object.sha1,
abbrev_commit));
- show_decorations(commit);
+ show_decorations(opt, commit);
printf("%s", diff_get_color_opt(&opt->diffopt, DIFF_RESET));
if (opt->commit_format == CMIT_FMT_ONELINE) {
putchar(' ');
diff --git a/log-tree.h b/log-tree.h
index 3c8127bb7c..f2a90084ae 100644
--- a/log-tree.h
+++ b/log-tree.h
@@ -12,7 +12,7 @@ int log_tree_diff_flush(struct rev_info *);
int log_tree_commit(struct rev_info *, struct commit *);
int log_tree_opt_parse(struct rev_info *, const char **, int);
void show_log(struct rev_info *opt);
-void show_decorations(struct commit *commit);
+void show_decorations(struct rev_info *opt, struct commit *commit);
void log_write_email_headers(struct rev_info *opt, const char *name,
const char **subject_p,
const char **extra_headers_p,
diff --git a/merge-file.c b/merge-file.c
index 2a939c9dd8..3120a95f78 100644
--- a/merge-file.c
+++ b/merge-file.c
@@ -61,6 +61,7 @@ static int generate_common_file(mmfile_t *res, mmfile_t *f1, mmfile_t *f2)
xdemitconf_t xecfg;
xdemitcb_t ecb;
+ memset(&xpp, 0, sizeof(xpp));
xpp.flags = XDF_NEED_MINIMAL;
memset(&xecfg, 0, sizeof(xecfg));
xecfg.ctxlen = 3;
diff --git a/merge-recursive.c b/merge-recursive.c
index 245232a408..b97026bd5c 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -16,7 +16,6 @@
#include "string-list.h"
#include "xdiff-interface.h"
#include "ll-merge.h"
-#include "interpolate.h"
#include "attr.h"
#include "merge-recursive.h"
#include "dir.h"
@@ -448,6 +447,30 @@ static void flush_buffer(int fd, const char *buf, unsigned long size)
}
}
+static int would_lose_untracked(const char *path)
+{
+ int pos = cache_name_pos(path, strlen(path));
+
+ if (pos < 0)
+ pos = -1 - pos;
+ while (pos < active_nr &&
+ !strcmp(path, active_cache[pos]->name)) {
+ /*
+ * If stage #0, it is definitely tracked.
+ * If it has stage #2 then it was tracked
+ * before this merge started. All other
+ * cases the path was not tracked.
+ */
+ switch (ce_stage(active_cache[pos])) {
+ case 0:
+ case 2:
+ return 0;
+ }
+ pos++;
+ }
+ return file_exists(path);
+}
+
static int make_room_for_path(const char *path)
{
int status;
@@ -463,6 +486,14 @@ static int make_room_for_path(const char *path)
die(msg, path, "");
}
+ /*
+ * Do not unlink a file in the work tree if we are not
+ * tracking it.
+ */
+ if (would_lose_untracked(path))
+ return error("refusing to lose untracked file at '%s'",
+ path);
+
/* Successful unlink is good.. */
if (!unlink(path))
return 0;
@@ -526,7 +557,8 @@ static void update_file_flags(struct merge_options *o,
char *lnk = xmemdupz(buf, size);
safe_create_leading_directories_const(path);
unlink(path);
- symlink(lnk, path);
+ if (symlink(lnk, path))
+ die("failed to symlink %s: %s", path, strerror(errno));
free(lnk);
} else
die("do not know what to do with %06o %s '%s'",
@@ -902,6 +934,11 @@ static int process_renames(struct merge_options *o,
ren1_src, ren1_dst, branch1,
branch2);
update_file(o, 0, ren1->pair->two->sha1, ren1->pair->two->mode, ren1_dst);
+ update_stages(ren1_dst, NULL,
+ branch1 == o->branch1 ?
+ ren1->pair->two : NULL,
+ branch1 == o->branch1 ?
+ NULL : ren1->pair->two, 1);
} else if (!sha_eq(dst_other.sha1, null_sha1)) {
const char *new_path;
clean_merge = 0;
@@ -1332,7 +1369,7 @@ static int merge_recursive_config(const char *var, const char *value, void *cb)
o->merge_rename_limit = git_config_int(var, value);
return 0;
}
- return git_default_config(var, value, cb);
+ return git_xmerge_config(var, value, cb);
}
void init_merge_options(struct merge_options *o)
diff --git a/pack-redundant.c b/pack-redundant.c
index 25b81a445c..e93eb966e2 100644
--- a/pack-redundant.c
+++ b/pack-redundant.c
@@ -463,7 +463,7 @@ static void minimize(struct pack_list **min)
pll_free(perm_all);
}
if (perm_ok == NULL)
- die("Internal error: No complete sets found!\n");
+ die("Internal error: No complete sets found!");
/* find the permutation with the smallest size */
perm = perm_ok;
@@ -573,14 +573,14 @@ static struct pack_list * add_pack_file(char *filename)
struct packed_git *p = packed_git;
if (strlen(filename) < 40)
- die("Bad pack filename: %s\n", filename);
+ die("Bad pack filename: %s", filename);
while (p) {
if (strstr(p->pack_name, filename))
return add_pack(p);
p = p->next;
}
- die("Filename %s not found in packed_git\n", filename);
+ die("Filename %s not found in packed_git", filename);
}
static void load_all(void)
@@ -636,7 +636,7 @@ int main(int argc, char **argv)
add_pack_file(*(argv + i++));
if (local_packs == NULL)
- die("Zero packs found!\n");
+ die("Zero packs found!");
load_all_objects();
diff --git a/pack-refs.c b/pack-refs.c
index 848d311c2b..2c76fb181f 100644
--- a/pack-refs.c
+++ b/pack-refs.c
@@ -89,7 +89,8 @@ int pack_refs(unsigned int flags)
memset(&cbdata, 0, sizeof(cbdata));
cbdata.flags = flags;
- fd = hold_lock_file_for_update(&packed, git_path("packed-refs"), 1);
+ fd = hold_lock_file_for_update(&packed, git_path("packed-refs"),
+ LOCK_DIE_ON_ERROR);
cbdata.refs_file = fdopen(fd, "w");
if (!cbdata.refs_file)
die("unable to create ref-pack file structure (%s)",
diff --git a/pack-revindex.c b/pack-revindex.c
index 6096b6224a..1de53c8934 100644
--- a/pack-revindex.c
+++ b/pack-revindex.c
@@ -140,7 +140,8 @@ struct revindex_entry *find_pack_revindex(struct packed_git *p, off_t ofs)
else
lo = mi + 1;
} while (lo < hi);
- die("internal error: pack revindex corrupt");
+ error("bad offset for revindex");
+ return NULL;
}
void discard_revindex(void)
diff --git a/pager.c b/pager.c
index aa0966c9c5..f19ddbc87d 100644
--- a/pager.c
+++ b/pager.c
@@ -70,7 +70,8 @@ void setup_pager(void)
/* original process continues, but writes to the pipe */
dup2(pager_process.in, 1);
- dup2(pager_process.in, 2);
+ if (isatty(2))
+ dup2(pager_process.in, 2);
close(pager_process.in);
/* this makes sure that the parent terminates after the pager */
diff --git a/parse-options.c b/parse-options.c
index fd08bb425c..9eb55cc8b5 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -484,6 +484,28 @@ int parse_opt_approxidate_cb(const struct option *opt, const char *arg,
return 0;
}
+int parse_opt_verbosity_cb(const struct option *opt, const char *arg,
+ int unset)
+{
+ int *target = opt->value;
+
+ if (unset)
+ /* --no-quiet, --no-verbose */
+ *target = 0;
+ else if (opt->short_name == 'v') {
+ if (*target >= 0)
+ (*target)++;
+ else
+ *target = 1;
+ } else {
+ if (*target <= 0)
+ (*target)--;
+ else
+ *target = -1;
+ }
+ return 0;
+}
+
/*
* This should really be OPTION_FILENAME type as a part of
* parse_options that take prefix to do this while parsing.
diff --git a/parse-options.h b/parse-options.h
index 5199950c00..034162ec69 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -150,9 +150,15 @@ extern int parse_options_end(struct parse_opt_ctx_t *ctx);
/*----- some often used options -----*/
extern int parse_opt_abbrev_cb(const struct option *, const char *, int);
extern int parse_opt_approxidate_cb(const struct option *, const char *, int);
+extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
#define OPT__VERBOSE(var) OPT_BOOLEAN('v', "verbose", (var), "be verbose")
#define OPT__QUIET(var) OPT_BOOLEAN('q', "quiet", (var), "be quiet")
+#define OPT__VERBOSITY(var) \
+ { OPTION_CALLBACK, 'v', "verbose", (var), NULL, "be more verbose", \
+ PARSE_OPT_NOARG, &parse_opt_verbosity_cb, 0 }, \
+ { OPTION_CALLBACK, 'q', "quiet", (var), NULL, "be more quiet", \
+ PARSE_OPT_NOARG, &parse_opt_verbosity_cb, 0 }
#define OPT__DRY_RUN(var) OPT_BOOLEAN('n', "dry-run", (var), "dry run")
#define OPT__ABBREV(var) \
{ OPTION_CALLBACK, 0, "abbrev", (var), "n", \
diff --git a/path.c b/path.c
index 76e8872622..a074aea649 100644
--- a/path.c
+++ b/path.c
@@ -32,6 +32,60 @@ static char *cleanup_path(char *path)
return path;
}
+char *mksnpath(char *buf, size_t n, const char *fmt, ...)
+{
+ va_list args;
+ unsigned len;
+
+ va_start(args, fmt);
+ len = vsnprintf(buf, n, fmt, args);
+ va_end(args);
+ if (len >= n) {
+ strlcpy(buf, bad_path, n);
+ return buf;
+ }
+ return cleanup_path(buf);
+}
+
+static char *git_vsnpath(char *buf, size_t n, const char *fmt, va_list args)
+{
+ const char *git_dir = get_git_dir();
+ size_t len;
+
+ len = strlen(git_dir);
+ if (n < len + 1)
+ goto bad;
+ memcpy(buf, git_dir, len);
+ if (len && !is_dir_sep(git_dir[len-1]))
+ buf[len++] = '/';
+ len += vsnprintf(buf + len, n - len, fmt, args);
+ if (len >= n)
+ goto bad;
+ return cleanup_path(buf);
+bad:
+ strlcpy(buf, bad_path, n);
+ return buf;
+}
+
+char *git_snpath(char *buf, size_t n, const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ (void)git_vsnpath(buf, n, fmt, args);
+ va_end(args);
+ return buf;
+}
+
+char *git_pathdup(const char *fmt, ...)
+{
+ char path[PATH_MAX];
+ va_list args;
+ va_start(args, fmt);
+ (void)git_vsnpath(path, sizeof(path), fmt, args);
+ va_end(args);
+ return xstrdup(path);
+}
+
char *mkpath(const char *fmt, ...)
{
va_list args;
@@ -348,7 +402,7 @@ int normalize_absolute_path(char *buf, const char *path)
goto next;
}
- memcpy(dst, comp_start, comp_len);
+ memmove(dst, comp_start, comp_len);
dst += comp_len;
next:
comp_start = comp_end;
diff --git a/perl/Git.pm b/perl/Git.pm
index 6aab712e6a..7d7f2b1d36 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -166,11 +166,12 @@ sub repository {
}
}
- if (not defined $opts{Repository} and not defined $opts{WorkingCopy}) {
- $opts{Directory} ||= '.';
+ if (not defined $opts{Repository} and not defined $opts{WorkingCopy}
+ and not defined $opts{Directory}) {
+ $opts{Directory} = '.';
}
- if ($opts{Directory}) {
+ if (defined $opts{Directory}) {
-d $opts{Directory} or throw Error::Simple("Directory not found: $!");
my $search = Git->repository(WorkingCopy => $opts{Directory});
@@ -204,14 +205,14 @@ sub repository {
unless (-d "$dir/refs" and -d "$dir/objects" and -e "$dir/HEAD") {
# Mimick git-rev-parse --git-dir error message:
- throw Error::Simple('fatal: Not a git repository');
+ throw Error::Simple("fatal: Not a git repository: $dir");
}
my $search = Git->repository(Repository => $dir);
try {
$search->command('symbolic-ref', 'HEAD');
} catch Git::Error::Command with {
# Mimick git-rev-parse --git-dir error message:
- throw Error::Simple('fatal: Not a git repository');
+ throw Error::Simple("fatal: Not a git repository: $dir");
}
$opts{Repository} = abs_path($dir);
@@ -961,9 +962,7 @@ issue.
=cut
sub temp_acquire {
- my ($self, $name) = _maybe_self(@_);
-
- my $temp_fd = _temp_cache($name);
+ my $temp_fd = _temp_cache(@_);
$TEMP_FILES{$temp_fd}{locked} = 1;
$temp_fd;
@@ -1005,15 +1004,15 @@ sub temp_release {
}
sub _temp_cache {
- my ($name) = @_;
+ my ($self, $name) = _maybe_self(@_);
_verify_require();
my $temp_fd = \$TEMP_FILEMAP{$name};
if (defined $$temp_fd and $$temp_fd->opened) {
if ($TEMP_FILES{$$temp_fd}{locked}) {
- throw Error::Simple("Temp file with moniker '",
- $name, "' already in use");
+ throw Error::Simple("Temp file with moniker '" .
+ $name . "' already in use");
}
} else {
if (defined $$temp_fd) {
@@ -1022,9 +1021,16 @@ sub _temp_cache {
"' was closed. Opening replacement.";
}
my $fname;
+
+ my $tmpdir;
+ if (defined $self) {
+ $tmpdir = $self->repo_path();
+ }
+
($$temp_fd, $fname) = File::Temp->tempfile(
- 'Git_XXXXXX', UNLINK => 1
+ 'Git_XXXXXX', UNLINK => 1, DIR => $tmpdir,
) or throw Error::Simple("couldn't open new temp file");
+
$$temp_fd->autoflush;
binmode $$temp_fd;
$TEMP_FILES{$$temp_fd}{fname} = $fname;
@@ -1203,8 +1209,7 @@ either version 2, or (at your option) any later version.
# the method was called upon an instance and (undef, @args) if
# it was called directly.
sub _maybe_self {
- # This breaks inheritance. Oh well.
- ref $_[0] eq 'Git' ? @_ : (undef, @_);
+ UNIVERSAL::isa($_[0], 'Git') ? @_ : (undef, @_);
}
# Check if the command id is something reasonable.
diff --git a/preload-index.c b/preload-index.c
new file mode 100644
index 0000000000..88edc5f8a9
--- /dev/null
+++ b/preload-index.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2008 Linus Torvalds
+ */
+#include "cache.h"
+
+#ifdef NO_PTHREADS
+static void preload_index(struct index_state *index, const char **pathspec)
+{
+ ; /* nothing */
+}
+#else
+
+#include <pthread.h>
+
+/*
+ * Mostly randomly chosen maximum thread counts: we
+ * cap the parallelism to 20 threads, and we want
+ * to have at least 500 lstat's per thread for it to
+ * be worth starting a thread.
+ */
+#define MAX_PARALLEL (20)
+#define THREAD_COST (500)
+
+struct thread_data {
+ pthread_t pthread;
+ struct index_state *index;
+ const char **pathspec;
+ int offset, nr;
+};
+
+static void *preload_thread(void *_data)
+{
+ int nr;
+ struct thread_data *p = _data;
+ struct index_state *index = p->index;
+ struct cache_entry **cep = index->cache + p->offset;
+
+ nr = p->nr;
+ if (nr + p->offset > index->cache_nr)
+ nr = index->cache_nr - p->offset;
+
+ do {
+ struct cache_entry *ce = *cep++;
+ struct stat st;
+
+ if (ce_stage(ce))
+ continue;
+ if (ce_uptodate(ce))
+ continue;
+ if (!ce_path_match(ce, p->pathspec))
+ continue;
+ if (lstat(ce->name, &st))
+ continue;
+ if (ie_match_stat(index, ce, &st, CE_MATCH_RACY_IS_DIRTY))
+ continue;
+ ce_mark_uptodate(ce);
+ } while (--nr > 0);
+ return NULL;
+}
+
+static void preload_index(struct index_state *index, const char **pathspec)
+{
+ int threads, i, work, offset;
+ struct thread_data data[MAX_PARALLEL];
+
+ if (!core_preload_index)
+ return;
+
+ threads = index->cache_nr / THREAD_COST;
+ if (threads < 2)
+ return;
+ if (threads > MAX_PARALLEL)
+ threads = MAX_PARALLEL;
+ offset = 0;
+ work = (index->cache_nr + threads - 1) / threads;
+ for (i = 0; i < threads; i++) {
+ struct thread_data *p = data+i;
+ p->index = index;
+ p->pathspec = pathspec;
+ p->offset = offset;
+ p->nr = work;
+ offset += work;
+ if (pthread_create(&p->pthread, NULL, preload_thread, p))
+ die("unable to create threaded lstat");
+ }
+ for (i = 0; i < threads; i++) {
+ struct thread_data *p = data+i;
+ if (pthread_join(p->pthread, NULL))
+ die("unable to join threaded lstat");
+ }
+}
+#endif
+
+int read_index_preload(struct index_state *index, const char **pathspec)
+{
+ int retval = read_index(index);
+
+ preload_index(index, pathspec);
+ return retval;
+}
diff --git a/pretty.c b/pretty.c
index 1e79943339..421d9c5bca 100644
--- a/pretty.c
+++ b/pretty.c
@@ -181,6 +181,20 @@ static int is_empty_line(const char *line, int *len_p)
return !len;
}
+static const char *skip_empty_lines(const char *msg)
+{
+ for (;;) {
+ int linelen = get_one_line(msg);
+ int ll = linelen;
+ if (!linelen)
+ break;
+ if (!is_empty_line(msg, &ll))
+ break;
+ msg += linelen;
+ }
+ return msg;
+}
+
static void add_merge_info(enum cmit_fmt fmt, struct strbuf *sb,
const struct commit *commit, int abbrev)
{
@@ -410,13 +424,15 @@ struct chunk {
struct format_commit_context {
const struct commit *commit;
enum date_mode dmode;
+ unsigned commit_header_parsed:1;
+ unsigned commit_message_parsed:1;
/* These offsets are relative to the start of the commit message. */
- int commit_header_parsed;
- struct chunk subject;
struct chunk author;
struct chunk committer;
struct chunk encoding;
+ size_t message_off;
+ size_t subject_off;
size_t body_off;
/* The following ones are relative to the result struct strbuf. */
@@ -446,23 +462,14 @@ static void parse_commit_header(struct format_commit_context *context)
{
const char *msg = context->commit->buffer;
int i;
- enum { HEADER, SUBJECT, BODY } state;
- for (i = 0, state = HEADER; msg[i] && state < BODY; i++) {
+ for (i = 0; msg[i]; i++) {
int eol;
for (eol = i; msg[eol] && msg[eol] != '\n'; eol++)
; /* do nothing */
- if (state == SUBJECT) {
- context->subject.off = i;
- context->subject.len = eol - i;
- i = eol;
- }
if (i == eol) {
- state++;
- /* strip empty lines */
- while (msg[eol] == '\n' && msg[eol + 1] == '\n')
- eol++;
+ break;
} else if (!prefixcmp(msg + i, "author ")) {
context->author.off = i + 7;
context->author.len = eol - i - 7;
@@ -474,13 +481,50 @@ static void parse_commit_header(struct format_commit_context *context)
context->encoding.len = eol - i - 9;
}
i = eol;
- if (!msg[i])
- break;
}
- context->body_off = i;
+ context->message_off = i;
context->commit_header_parsed = 1;
}
+const char *format_subject(struct strbuf *sb, const char *msg,
+ const char *line_separator)
+{
+ int first = 1;
+
+ for (;;) {
+ const char *line = msg;
+ int linelen = get_one_line(line);
+
+ msg += linelen;
+ if (!linelen || is_empty_line(line, &linelen))
+ break;
+
+ if (!sb)
+ continue;
+ strbuf_grow(sb, linelen + 2);
+ if (!first)
+ strbuf_addstr(sb, line_separator);
+ strbuf_add(sb, line, linelen);
+ first = 0;
+ }
+ return msg;
+}
+
+static void parse_commit_message(struct format_commit_context *c)
+{
+ const char *msg = c->commit->buffer + c->message_off;
+ const char *start = c->commit->buffer;
+
+ msg = skip_empty_lines(msg);
+ c->subject_off = msg - start;
+
+ msg = format_subject(NULL, msg, NULL);
+ msg = skip_empty_lines(msg);
+ c->body_off = msg - start;
+
+ c->commit_message_parsed = 1;
+}
+
static void format_decoration(struct strbuf *sb, const struct commit *commit)
{
struct name_decoration *d;
@@ -600,9 +644,6 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
parse_commit_header(c);
switch (placeholder[0]) {
- case 's': /* subject */
- strbuf_add(sb, msg + c->subject.off, c->subject.len);
- return 1;
case 'a': /* author ... */
return format_person_part(sb, placeholder[1],
msg + c->author.off, c->author.len,
@@ -614,6 +655,16 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
case 'e': /* encoding */
strbuf_add(sb, msg + c->encoding.off, c->encoding.len);
return 1;
+ }
+
+ /* Now we need to parse the commit message. */
+ if (!c->commit_message_parsed)
+ parse_commit_message(c);
+
+ switch (placeholder[0]) {
+ case 's': /* subject */
+ format_subject(sb, msg + c->subject_off, " ");
+ return 1;
case 'b': /* body */
strbuf_addstr(sb, msg + c->body_off);
return 1;
@@ -704,27 +755,11 @@ void pp_title_line(enum cmit_fmt fmt,
const char *encoding,
int need_8bit_cte)
{
+ const char *line_separator = (fmt == CMIT_FMT_EMAIL) ? "\n " : " ";
struct strbuf title;
strbuf_init(&title, 80);
-
- for (;;) {
- const char *line = *msg_p;
- int linelen = get_one_line(line);
-
- *msg_p += linelen;
- if (!linelen || is_empty_line(line, &linelen))
- break;
-
- strbuf_grow(&title, linelen + 2);
- if (title.len) {
- if (fmt == CMIT_FMT_EMAIL) {
- strbuf_addch(&title, '\n');
- }
- strbuf_addch(&title, ' ');
- }
- strbuf_add(&title, line, linelen);
- }
+ *msg_p = format_subject(&title, *msg_p, line_separator);
strbuf_grow(sb, title.len + 1024);
if (subject) {
@@ -783,6 +818,20 @@ void pp_remainder(enum cmit_fmt fmt,
}
}
+char *reencode_commit_message(const struct commit *commit, const char **encoding_p)
+{
+ const char *encoding;
+
+ encoding = (git_log_output_encoding
+ ? git_log_output_encoding
+ : git_commit_encoding);
+ if (!encoding)
+ encoding = "utf-8";
+ if (encoding_p)
+ *encoding_p = encoding;
+ return logmsg_reencode(commit, encoding);
+}
+
void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,
struct strbuf *sb, int abbrev,
const char *subject, const char *after_subject,
@@ -799,12 +848,7 @@ void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,
return;
}
- encoding = (git_log_output_encoding
- ? git_log_output_encoding
- : git_commit_encoding);
- if (!encoding)
- encoding = "utf-8";
- reencoded = logmsg_reencode(commit, encoding);
+ reencoded = reencode_commit_message(commit, &encoding);
if (reencoded) {
msg = reencoded;
}
@@ -841,15 +885,7 @@ void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,
}
/* Skip excess blank lines at the beginning of body, if any... */
- for (;;) {
- int linelen = get_one_line(msg);
- int ll = linelen;
- if (!linelen)
- break;
- if (!is_empty_line(msg, &ll))
- break;
- msg += linelen;
- }
+ msg = skip_empty_lines(msg);
/* These formats treat the title line specially. */
if (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL)
diff --git a/read-cache.c b/read-cache.c
index c229fd4d0d..b1475ffa09 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -99,27 +99,21 @@ static int ce_compare_data(struct cache_entry *ce, struct stat *st)
static int ce_compare_link(struct cache_entry *ce, size_t expected_size)
{
int match = -1;
- char *target;
void *buffer;
unsigned long size;
enum object_type type;
- int len;
+ struct strbuf sb = STRBUF_INIT;
- target = xmalloc(expected_size);
- len = readlink(ce->name, target, expected_size);
- if (len != expected_size) {
- free(target);
+ if (strbuf_readlink(&sb, ce->name, expected_size))
return -1;
- }
+
buffer = read_sha1_file(ce->sha1, &type, &size);
- if (!buffer) {
- free(target);
- return -1;
+ if (buffer) {
+ if (size == sb.len)
+ match = memcmp(buffer, sb.buf, size);
+ free(buffer);
}
- if (size == expected_size)
- match = memcmp(buffer, target, size);
- free(buffer);
- free(target);
+ strbuf_release(&sb);
return match;
}
@@ -160,7 +154,7 @@ static int ce_modified_check_fs(struct cache_entry *ce, struct stat *st)
return 0;
}
-static int is_empty_blob_sha1(const unsigned char *sha1)
+int is_empty_blob_sha1(const unsigned char *sha1)
{
static const unsigned char empty_blob_sha1[20] = {
0xe6,0x9d,0xe2,0x9b,0xb2,0xd1,0xd6,0x43,0x4b,0x8b,
@@ -257,6 +251,14 @@ int ie_match_stat(const struct index_state *istate,
if (!ignore_valid && (ce->ce_flags & CE_VALID))
return 0;
+ /*
+ * Intent-to-add entries have not been added, so the index entry
+ * by definition never matches what is in the work tree until it
+ * actually gets added.
+ */
+ if (ce->ce_flags & CE_INTENT_TO_ADD)
+ return DATA_CHANGED | TYPE_CHANGED | MODE_CHANGED;
+
changed = ce_match_stat_basic(ce, st);
/*
@@ -546,6 +548,8 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
ce->ce_flags = namelen;
if (!intent_only)
fill_stat_cache_info(ce, st);
+ else
+ ce->ce_flags |= CE_INTENT_TO_ADD;
if (trust_executable_bit && has_symlinks)
ce->ce_mode = create_ce_mode(st_mode);
@@ -1098,7 +1102,7 @@ static int verify_hdr(struct cache_header *hdr, unsigned long size)
if (hdr->hdr_signature != htonl(CACHE_SIGNATURE))
return error("bad signature");
- if (hdr->hdr_version != htonl(2))
+ if (hdr->hdr_version != htonl(2) && hdr->hdr_version != htonl(3))
return error("bad index version");
git_SHA1_Init(&c);
git_SHA1_Update(&c, hdr, size - 20);
@@ -1133,6 +1137,7 @@ int read_index(struct index_state *istate)
static void convert_from_disk(struct ondisk_cache_entry *ondisk, struct cache_entry *ce)
{
size_t len;
+ const char *name;
ce->ce_ctime = ntohl(ondisk->ctime.sec);
ce->ce_mtime = ntohl(ondisk->mtime.sec);
@@ -1145,19 +1150,31 @@ static void convert_from_disk(struct ondisk_cache_entry *ondisk, struct cache_en
/* On-disk flags are just 16 bits */
ce->ce_flags = ntohs(ondisk->flags);
- /* For future extension: we do not understand this entry yet */
- if (ce->ce_flags & CE_EXTENDED)
- die("Unknown index entry format");
hashcpy(ce->sha1, ondisk->sha1);
len = ce->ce_flags & CE_NAMEMASK;
+
+ if (ce->ce_flags & CE_EXTENDED) {
+ struct ondisk_cache_entry_extended *ondisk2;
+ int extended_flags;
+ ondisk2 = (struct ondisk_cache_entry_extended *)ondisk;
+ extended_flags = ntohs(ondisk2->flags2) << 16;
+ /* We do not yet understand any bit out of CE_EXTENDED_FLAGS */
+ if (extended_flags & ~CE_EXTENDED_FLAGS)
+ die("Unknown index entry format %08x", extended_flags);
+ ce->ce_flags |= extended_flags;
+ name = ondisk2->name;
+ }
+ else
+ name = ondisk->name;
+
if (len == CE_NAMEMASK)
- len = strlen(ondisk->name);
+ len = strlen(name);
/*
* NEEDSWORK: If the original index is crafted, this copy could
* go unchecked.
*/
- memcpy(ce->name, ondisk->name, len + 1);
+ memcpy(ce->name, name, len + 1);
}
static inline size_t estimate_cache_size(size_t ondisk_size, unsigned int entries)
@@ -1269,6 +1286,11 @@ unmap:
die("index file corrupt");
}
+int is_index_unborn(struct index_state *istate)
+{
+ return (!istate->cache_nr && !istate->alloc && !istate->timestamp);
+}
+
int discard_index(struct index_state *istate)
{
istate->cache_nr = 0;
@@ -1417,6 +1439,7 @@ static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce)
{
int size = ondisk_ce_size(ce);
struct ondisk_cache_entry *ondisk = xcalloc(1, size);
+ char *name;
ondisk->ctime.sec = htonl(ce->ce_ctime);
ondisk->ctime.nsec = 0;
@@ -1430,7 +1453,15 @@ static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce)
ondisk->size = htonl(ce->ce_size);
hashcpy(ondisk->sha1, ce->sha1);
ondisk->flags = htons(ce->ce_flags);
- memcpy(ondisk->name, ce->name, ce_namelen(ce));
+ if (ce->ce_flags & CE_EXTENDED) {
+ struct ondisk_cache_entry_extended *ondisk2;
+ ondisk2 = (struct ondisk_cache_entry_extended *)ondisk;
+ ondisk2->flags2 = htons((ce->ce_flags & CE_EXTENDED_FLAGS) >> 16);
+ name = ondisk2->name;
+ }
+ else
+ name = ondisk->name;
+ memcpy(name, ce->name, ce_namelen(ce));
return ce_write(c, fd, ondisk, size);
}
@@ -1439,16 +1470,25 @@ int write_index(const struct index_state *istate, int newfd)
{
git_SHA_CTX c;
struct cache_header hdr;
- int i, err, removed;
+ int i, err, removed, extended;
struct cache_entry **cache = istate->cache;
int entries = istate->cache_nr;
- for (i = removed = 0; i < entries; i++)
+ for (i = removed = extended = 0; i < entries; i++) {
if (cache[i]->ce_flags & CE_REMOVE)
removed++;
+ /* reduce extended entries if possible */
+ cache[i]->ce_flags &= ~CE_EXTENDED;
+ if (cache[i]->ce_flags & CE_EXTENDED_FLAGS) {
+ extended++;
+ cache[i]->ce_flags |= CE_EXTENDED;
+ }
+ }
+
hdr.hdr_signature = htonl(CACHE_SIGNATURE);
- hdr.hdr_version = htonl(2);
+ /* for extended format, increase version so older git won't try to read it */
+ hdr.hdr_version = htonl(extended ? 3 : 2);
hdr.hdr_entries = htonl(entries - removed);
git_SHA1_Init(&c);
@@ -1481,7 +1521,7 @@ int write_index(const struct index_state *istate, int newfd)
/*
* Read the index file that is potentially unmerged into given
- * index_state, dropping any unmerged entries. Returns true is
+ * index_state, dropping any unmerged entries. Returns true if
* the index is unmerged. Callers who want to refuse to work
* from an unmerged state can call this and check its return value,
* instead of calling read_cache().
@@ -1489,25 +1529,30 @@ int write_index(const struct index_state *istate, int newfd)
int read_index_unmerged(struct index_state *istate)
{
int i;
- struct cache_entry **dst;
- struct cache_entry *last = NULL;
+ int unmerged = 0;
read_index(istate);
- dst = istate->cache;
for (i = 0; i < istate->cache_nr; i++) {
struct cache_entry *ce = istate->cache[i];
- if (ce_stage(ce)) {
- remove_name_hash(ce);
- if (last && !strcmp(ce->name, last->name))
- continue;
- cache_tree_invalidate_path(istate->cache_tree, ce->name);
- last = ce;
+ struct cache_entry *new_ce;
+ int size, len;
+
+ if (!ce_stage(ce))
continue;
- }
- *dst++ = ce;
+ unmerged = 1;
+ len = strlen(ce->name);
+ size = cache_entry_size(len);
+ new_ce = xcalloc(1, size);
+ hashcpy(new_ce->sha1, ce->sha1);
+ memcpy(new_ce->name, ce->name, len);
+ new_ce->ce_flags = create_ce_flags(len, 0);
+ new_ce->ce_mode = ce->ce_mode;
+ if (add_index_entry(istate, new_ce, 0))
+ return error("%s: cannot drop to stage #0",
+ ce->name);
+ i = index_name_pos(istate, new_ce->name, len);
}
- istate->cache_nr = dst - istate->cache;
- return !!last;
+ return unmerged;
}
struct update_callback_data
@@ -1565,3 +1610,30 @@ int add_files_to_cache(const char *prefix, const char **pathspec, int flags)
return !!data.add_errors;
}
+/*
+ * Returns 1 if the path is an "other" path with respect to
+ * the index; that is, the path is not mentioned in the index at all,
+ * either as a file, a directory with some files in the index,
+ * or as an unmerged entry.
+ *
+ * We helpfully remove a trailing "/" from directories so that
+ * the output of read_directory can be used as-is.
+ */
+int index_name_is_other(const struct index_state *istate, const char *name,
+ int namelen)
+{
+ int pos;
+ if (namelen && name[namelen - 1] == '/')
+ namelen--;
+ pos = index_name_pos(istate, name, namelen);
+ if (0 <= pos)
+ return 0; /* exact match */
+ pos = -pos - 1;
+ if (pos < istate->cache_nr) {
+ struct cache_entry *ce = istate->cache[pos];
+ if (ce_namelen(ce) == namelen &&
+ !memcmp(ce->name, name, namelen))
+ return 0; /* Yup, this one exists unmerged */
+ }
+ return 1;
+}
diff --git a/refs.c b/refs.c
index b6807505e2..33ced65a78 100644
--- a/refs.c
+++ b/refs.c
@@ -413,7 +413,7 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
*flag = 0;
for (;;) {
- const char *path = git_path("%s", ref);
+ char path[PATH_MAX];
struct stat st;
char *buf;
int fd;
@@ -421,6 +421,7 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
if (--depth < 0)
return NULL;
+ git_snpath(path, sizeof(path), "%s", ref);
/* Special case: non-existing file. */
if (lstat(path, &st) < 0) {
struct ref_list *list = get_packed_refs();
@@ -794,10 +795,10 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char
char *ref_file;
const char *orig_ref = ref;
struct ref_lock *lock;
- struct stat st;
int last_errno = 0;
- int type;
+ int type, lflags;
int mustexist = (old_sha1 && !is_null_sha1(old_sha1));
+ int missing = 0;
lock = xcalloc(1, sizeof(struct ref_lock));
lock->lock_fd = -1;
@@ -825,23 +826,27 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char
orig_ref, strerror(errno));
goto error_return;
}
+ missing = is_null_sha1(lock->old_sha1);
/* When the ref did not exist and we are creating it,
* make sure there is no existing ref that is packed
* whose name begins with our refname, nor a ref whose
* name is a proper prefix of our refname.
*/
- if (is_null_sha1(lock->old_sha1) &&
+ if (missing &&
!is_refname_available(ref, NULL, get_packed_refs(), 0))
goto error_return;
lock->lk = xcalloc(1, sizeof(struct lock_file));
- if (flags & REF_NODEREF)
+ lflags = LOCK_DIE_ON_ERROR;
+ if (flags & REF_NODEREF) {
ref = orig_ref;
+ lflags |= LOCK_NODEREF;
+ }
lock->ref_name = xstrdup(ref);
lock->orig_ref_name = xstrdup(orig_ref);
ref_file = git_path("%s", ref);
- if (lstat(ref_file, &st) && errno == ENOENT)
+ if (missing)
lock->force_write = 1;
if ((flags & REF_NODEREF) && (type & REF_ISSYMREF))
lock->force_write = 1;
@@ -851,8 +856,8 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char
error("unable to create directory for %s", ref_file);
goto error_return;
}
- lock->lock_fd = hold_lock_file_for_update(lock->lk, ref_file, 1);
+ lock->lock_fd = hold_lock_file_for_update(lock->lk, ref_file, lflags);
return old_sha1 ? verify_lock(lock, old_sha1, mustexist) : lock;
error_return:
@@ -918,25 +923,33 @@ static int repack_without_ref(const char *refname)
return commit_lock_file(&packlock);
}
-int delete_ref(const char *refname, const unsigned char *sha1)
+int delete_ref(const char *refname, const unsigned char *sha1, int delopt)
{
struct ref_lock *lock;
- int err, i, ret = 0, flag = 0;
+ int err, i = 0, ret = 0, flag = 0;
lock = lock_ref_sha1_basic(refname, sha1, 0, &flag);
if (!lock)
return 1;
- if (!(flag & REF_ISPACKED)) {
+ if (!(flag & REF_ISPACKED) || flag & REF_ISSYMREF) {
/* loose */
- i = strlen(lock->lk->filename) - 5; /* .lock */
- lock->lk->filename[i] = 0;
- err = unlink(lock->lk->filename);
+ const char *path;
+
+ if (!(delopt & REF_NODEREF)) {
+ i = strlen(lock->lk->filename) - 5; /* .lock */
+ lock->lk->filename[i] = 0;
+ path = lock->lk->filename;
+ } else {
+ path = git_path("%s", refname);
+ }
+ err = unlink(path);
if (err && errno != ENOENT) {
ret = 1;
error("unlink(%s) failed: %s",
- lock->lk->filename, strerror(errno));
+ path, strerror(errno));
}
- lock->lk->filename[i] = '.';
+ if (!(delopt & REF_NODEREF))
+ lock->lk->filename[i] = '.';
}
/* removing the loose one could have resurrected an earlier
* packed one. Also, if it was not loose we need to repack
@@ -961,11 +974,16 @@ int rename_ref(const char *oldref, const char *newref, const char *logmsg)
struct ref_lock *lock;
struct stat loginfo;
int log = !lstat(git_path("logs/%s", oldref), &loginfo);
+ const char *symref = NULL;
- if (S_ISLNK(loginfo.st_mode))
+ if (log && S_ISLNK(loginfo.st_mode))
return error("reflog for %s is a symlink", oldref);
- if (!resolve_ref(oldref, orig_sha1, 1, &flag))
+ symref = resolve_ref(oldref, orig_sha1, 1, &flag);
+ if (flag & REF_ISSYMREF)
+ return error("refname %s is a symbolic ref, renaming it is not supported",
+ oldref);
+ if (!symref)
return error("refname %s not found", oldref);
if (!is_refname_available(newref, oldref, get_packed_refs(), 0))
@@ -985,12 +1003,12 @@ int rename_ref(const char *oldref, const char *newref, const char *logmsg)
return error("unable to move logfile logs/%s to tmp-renamed-log: %s",
oldref, strerror(errno));
- if (delete_ref(oldref, orig_sha1)) {
+ if (delete_ref(oldref, orig_sha1, REF_NODEREF)) {
error("unable to delete old %s", oldref);
goto rollback;
}
- if (resolve_ref(newref, sha1, 1, &flag) && delete_ref(newref, sha1)) {
+ if (resolve_ref(newref, sha1, 1, &flag) && delete_ref(newref, sha1, REF_NODEREF)) {
if (errno==EISDIR) {
if (remove_empty_directories(git_path("%s", newref))) {
error("Directory not empty: %s", newref);
@@ -1033,7 +1051,6 @@ int rename_ref(const char *oldref, const char *newref, const char *logmsg)
error("unable to lock %s for update", newref);
goto rollback;
}
-
lock->force_write = 1;
hashcpy(lock->old_sha1, orig_sha1);
if (write_ref_sha1(lock, orig_sha1, logmsg)) {
@@ -1127,13 +1144,14 @@ static int log_ref_write(const char *ref_name, const unsigned char *old_sha1,
int logfd, written, oflags = O_APPEND | O_WRONLY;
unsigned maxlen, len;
int msglen;
- char *log_file, *logrec;
+ char log_file[PATH_MAX];
+ char *logrec;
const char *committer;
if (log_all_ref_updates < 0)
log_all_ref_updates = !is_bare_repository();
- log_file = git_path("logs/%s", ref_name);
+ git_snpath(log_file, sizeof(log_file), "logs/%s", ref_name);
if (log_all_ref_updates &&
(!prefixcmp(ref_name, "refs/heads/") ||
@@ -1262,7 +1280,7 @@ int create_symref(const char *ref_target, const char *refs_heads_master,
const char *lockpath;
char ref[1000];
int fd, len, written;
- char *git_HEAD = xstrdup(git_path("%s", ref_target));
+ char *git_HEAD = git_pathdup("%s", ref_target);
unsigned char old_sha1[20], new_sha1[20];
if (logmsg && read_ref(ref_target, old_sha1))
diff --git a/remote.c b/remote.c
index d5efadd93d..570e11286e 100644
--- a/remote.c
+++ b/remote.c
@@ -201,6 +201,7 @@ static void read_remotes_file(struct remote *remote)
if (!f)
return;
+ remote->origin = REMOTE_REMOTES;
while (fgets(buffer, BUF_SIZE, f)) {
int value_list;
char *s, *p;
@@ -261,6 +262,7 @@ static void read_branches_file(struct remote *remote)
s++;
if (!*s)
return;
+ remote->origin = REMOTE_BRANCHES;
p = s + strlen(s);
while (isspace(p[-1]))
*--p = 0;
@@ -297,6 +299,17 @@ static void read_branches_file(struct remote *remote)
}
add_url_alias(remote, p);
add_fetch_refspec(remote, strbuf_detach(&branch, 0));
+ /*
+ * Cogito compatible push: push current HEAD to remote #branch
+ * (master if missing)
+ */
+ strbuf_init(&branch, 0);
+ strbuf_addstr(&branch, "HEAD");
+ if (frag)
+ strbuf_addf(&branch, ":refs/heads/%s", frag);
+ else
+ strbuf_addstr(&branch, ":refs/heads/master");
+ add_push_refspec(remote, strbuf_detach(&branch, 0));
remote->fetch_tags = 1; /* always auto-follow */
}
@@ -341,14 +354,16 @@ static int handle_config(const char *key, const char *value, void *cb)
if (prefixcmp(key, "remote."))
return 0;
name = key + 7;
+ if (*name == '/') {
+ warning("Config remote shorthand cannot begin with '/': %s",
+ name);
+ return 0;
+ }
subkey = strrchr(name, '.');
if (!subkey)
return error("Config with no key for remote %s", name);
- if (*subkey == '/') {
- warning("Config remote shorthand cannot begin with '/': %s", name);
- return 0;
- }
remote = make_remote(name, subkey - name);
+ remote->origin = REMOTE_CONFIG;
if (!strcmp(subkey, ".mirror"))
remote->mirror = git_config_bool(key, value);
else if (!strcmp(subkey, ".skipdefaultupdate"))
@@ -748,17 +763,19 @@ int remote_find_tracking(struct remote *remote, struct refspec *refspec)
return -1;
}
-struct ref *alloc_ref(unsigned namelen)
+static struct ref *alloc_ref_with_prefix(const char *prefix, size_t prefixlen,
+ const char *name)
{
- struct ref *ret = xcalloc(1, sizeof(struct ref) + namelen);
- return ret;
+ size_t len = strlen(name);
+ struct ref *ref = xcalloc(1, sizeof(struct ref) + prefixlen + len + 1);
+ memcpy(ref->name, prefix, prefixlen);
+ memcpy(ref->name + prefixlen, name, len);
+ return ref;
}
-struct ref *alloc_ref_from_str(const char* str)
+struct ref *alloc_ref(const char *name)
{
- struct ref *ret = alloc_ref(strlen(str) + 1);
- strcpy(ret->name, str);
- return ret;
+ return alloc_ref_with_prefix("", 0, name);
}
static struct ref *copy_ref(const struct ref *ref)
@@ -869,21 +886,20 @@ static struct ref *try_explicit_object_name(const char *name)
struct ref *ref;
if (!*name) {
- ref = alloc_ref(20);
- strcpy(ref->name, "(delete)");
+ ref = alloc_ref("(delete)");
hashclr(ref->new_sha1);
return ref;
}
if (get_sha1(name, sha1))
return NULL;
- ref = alloc_ref_from_str(name);
+ ref = alloc_ref(name);
hashcpy(ref->new_sha1, sha1);
return ref;
}
static struct ref *make_linked_ref(const char *name, struct ref ***tail)
{
- struct ref *ret = alloc_ref_from_str(name);
+ struct ref *ret = alloc_ref(name);
tail_link_ref(ret, tail);
return ret;
}
@@ -1151,10 +1167,8 @@ static struct ref *get_expanded_map(const struct ref *remote_refs,
struct ref *cpy = copy_ref(ref);
match = ref->name + remote_prefix_len;
- cpy->peer_ref = alloc_ref(local_prefix_len +
- strlen(match) + 1);
- sprintf(cpy->peer_ref->name, "%s%s",
- refspec->dst, match);
+ cpy->peer_ref = alloc_ref_with_prefix(refspec->dst,
+ local_prefix_len, match);
if (refspec->force)
cpy->peer_ref->force = 1;
*tail = cpy;
@@ -1187,25 +1201,18 @@ struct ref *get_remote_ref(const struct ref *remote_refs, const char *name)
static struct ref *get_local_ref(const char *name)
{
- struct ref *ret;
if (!name)
return NULL;
- if (!prefixcmp(name, "refs/")) {
- return alloc_ref_from_str(name);
- }
+ if (!prefixcmp(name, "refs/"))
+ return alloc_ref(name);
if (!prefixcmp(name, "heads/") ||
!prefixcmp(name, "tags/") ||
- !prefixcmp(name, "remotes/")) {
- ret = alloc_ref(strlen(name) + 6);
- sprintf(ret->name, "refs/%s", name);
- return ret;
- }
+ !prefixcmp(name, "remotes/"))
+ return alloc_ref_with_prefix("refs/", 5, name);
- ret = alloc_ref(strlen(name) + 12);
- sprintf(ret->name, "refs/heads/%s", name);
- return ret;
+ return alloc_ref_with_prefix("refs/heads/", 11, name);
}
int get_fetch_map(const struct ref *remote_refs,
diff --git a/remote.h b/remote.h
index c6163ff5b1..a46a5be131 100644
--- a/remote.h
+++ b/remote.h
@@ -1,8 +1,15 @@
#ifndef REMOTE_H
#define REMOTE_H
+enum {
+ REMOTE_CONFIG,
+ REMOTE_REMOTES,
+ REMOTE_BRANCHES
+};
+
struct remote {
const char *name;
+ int origin;
const char **url;
int url_nr;
@@ -55,9 +62,7 @@ struct refspec {
extern const struct refspec *tag_refspec;
-struct ref *alloc_ref(unsigned namelen);
-
-struct ref *alloc_ref_from_str(const char* str);
+struct ref *alloc_ref(const char *name);
struct ref *copy_ref_list(const struct ref *ref);
diff --git a/rerere.c b/rerere.c
index 5bb5316cda..718fb526dd 100644
--- a/rerere.c
+++ b/rerere.c
@@ -70,6 +70,19 @@ static int write_rr(struct string_list *rr, int out_fd)
return 0;
}
+static void ferr_write(const void *p, size_t count, FILE *fp, int *err)
+{
+ if (!count || *err)
+ return;
+ if (fwrite(p, count, 1, fp) != 1)
+ *err = errno;
+}
+
+static inline void ferr_puts(const char *s, FILE *fp, int *err)
+{
+ ferr_write(s, strlen(s), fp, err);
+}
+
static int handle_file(const char *path,
unsigned char *sha1, const char *output)
{
@@ -82,6 +95,7 @@ static int handle_file(const char *path,
struct strbuf one = STRBUF_INIT, two = STRBUF_INIT;
FILE *f = fopen(path, "r");
FILE *out = NULL;
+ int wrerror = 0;
if (!f)
return error("Could not open %s", path);
@@ -118,11 +132,11 @@ static int handle_file(const char *path,
hunk_no++;
hunk = RR_CONTEXT;
if (out) {
- fputs("<<<<<<<\n", out);
- fwrite(one.buf, one.len, 1, out);
- fputs("=======\n", out);
- fwrite(two.buf, two.len, 1, out);
- fputs(">>>>>>>\n", out);
+ ferr_puts("<<<<<<<\n", out, &wrerror);
+ ferr_write(one.buf, one.len, out, &wrerror);
+ ferr_puts("=======\n", out, &wrerror);
+ ferr_write(two.buf, two.len, out, &wrerror);
+ ferr_puts(">>>>>>>\n", out, &wrerror);
}
if (sha1) {
git_SHA1_Update(&ctx, one.buf ? one.buf : "",
@@ -139,7 +153,7 @@ static int handle_file(const char *path,
else if (hunk == RR_SIDE_2)
strbuf_addstr(&two, buf);
else if (out)
- fputs(buf, out);
+ ferr_puts(buf, out, &wrerror);
continue;
bad:
hunk = 99; /* force error exit */
@@ -149,8 +163,12 @@ static int handle_file(const char *path,
strbuf_release(&two);
fclose(f);
- if (out)
- fclose(out);
+ if (wrerror)
+ error("There were errors while writing %s (%s)",
+ path, strerror(wrerror));
+ if (out && fclose(out))
+ wrerror = error("Failed to flush %s: %s",
+ path, strerror(errno));
if (sha1)
git_SHA1_Final(sha1, &ctx);
if (hunk != RR_CONTEXT) {
@@ -158,6 +176,8 @@ static int handle_file(const char *path,
unlink(output);
return error("Could not parse conflict hunks in %s", path);
}
+ if (wrerror)
+ return -1;
return hunk_no;
}
@@ -200,9 +220,13 @@ static int merge(const char *name, const char *path)
if (!ret) {
FILE *f = fopen(path, "w");
if (!f)
- return error("Could not write to %s", path);
- fwrite(result.ptr, result.size, 1, f);
- fclose(f);
+ return error("Could not open %s: %s", path,
+ strerror(errno));
+ if (fwrite(result.ptr, result.size, 1, f) != 1)
+ error("Could not write %s: %s", path, strerror(errno));
+ if (fclose(f))
+ return error("Writing %s failed: %s", path,
+ strerror(errno));
}
free(cur.ptr);
@@ -351,8 +375,9 @@ int setup_rerere(struct string_list *merge_rr)
if (!is_rerere_enabled())
return -1;
- merge_rr_path = xstrdup(git_path("MERGE_RR"));
- fd = hold_lock_file_for_update(&write_lock, merge_rr_path, 1);
+ merge_rr_path = git_pathdup("MERGE_RR");
+ fd = hold_lock_file_for_update(&write_lock, merge_rr_path,
+ LOCK_DIE_ON_ERROR);
read_rr(merge_rr);
return fd;
}
diff --git a/revision.c b/revision.c
index 2f646deab0..db60f06c98 100644
--- a/revision.c
+++ b/revision.c
@@ -11,6 +11,7 @@
#include "reflog-walk.h"
#include "patch-ids.h"
#include "decorate.h"
+#include "log-tree.h"
volatile show_early_output_fn_t show_early_output;
@@ -199,6 +200,8 @@ static struct commit *handle_commit(struct rev_info *revs, struct object *object
mark_parents_uninteresting(commit);
revs->limited = 1;
}
+ if (revs->show_source && !commit->util)
+ commit->util = (void *) name;
return commit;
}
@@ -292,10 +295,31 @@ static void file_change(struct diff_options *options,
DIFF_OPT_SET(options, HAS_CHANGES);
}
-static int rev_compare_tree(struct rev_info *revs, struct tree *t1, struct tree *t2)
+static int rev_compare_tree(struct rev_info *revs, struct commit *parent, struct commit *commit)
{
+ struct tree *t1 = parent->tree;
+ struct tree *t2 = commit->tree;
+
if (!t1)
return REV_TREE_NEW;
+
+ if (revs->simplify_by_decoration) {
+ /*
+ * If we are simplifying by decoration, then the commit
+ * is worth showing if it has a tag pointing at it.
+ */
+ if (lookup_decoration(&name_decoration, &commit->object))
+ return REV_TREE_DIFFERENT;
+ /*
+ * A commit that is not pointed by a tag is uninteresting
+ * if we are not limited by path. This means that you will
+ * see the usual "commits that touch the paths" plus any
+ * tagged commit by specifying both --simplify-by-decoration
+ * and pathspec.
+ */
+ if (!revs->prune_data)
+ return REV_TREE_SAME;
+ }
if (!t2)
return REV_TREE_DIFFERENT;
tree_difference = REV_TREE_SAME;
@@ -306,12 +330,13 @@ static int rev_compare_tree(struct rev_info *revs, struct tree *t1, struct tree
return tree_difference;
}
-static int rev_same_tree_as_empty(struct rev_info *revs, struct tree *t1)
+static int rev_same_tree_as_empty(struct rev_info *revs, struct commit *commit)
{
int retval;
void *tree;
unsigned long size;
struct tree_desc empty, real;
+ struct tree *t1 = commit->tree;
if (!t1)
return 0;
@@ -345,7 +370,7 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
return;
if (!commit->parents) {
- if (rev_same_tree_as_empty(revs, commit->tree))
+ if (rev_same_tree_as_empty(revs, commit))
commit->object.flags |= TREESAME;
return;
}
@@ -365,7 +390,7 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
die("cannot simplify commit %s (because of %s)",
sha1_to_hex(commit->object.sha1),
sha1_to_hex(p->object.sha1));
- switch (rev_compare_tree(revs, p->tree, commit->tree)) {
+ switch (rev_compare_tree(revs, p, commit)) {
case REV_TREE_SAME:
tree_same = 1;
if (!revs->simplify_history || (p->object.flags & UNINTERESTING)) {
@@ -385,7 +410,7 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
case REV_TREE_NEW:
if (revs->remove_empty_trees &&
- rev_same_tree_as_empty(revs, p->tree)) {
+ rev_same_tree_as_empty(revs, p)) {
/* We are adding all the specified
* paths from this parent, so the
* history beyond this parent is not
@@ -484,6 +509,8 @@ static int add_parents_to_list(struct rev_info *revs, struct commit *commit,
if (parse_commit(p) < 0)
return -1;
+ if (revs->show_source && !p->util)
+ p->util = commit->util;
p->object.flags |= left_flag;
if (!(p->object.flags & SEEN)) {
p->object.flags |= SEEN;
@@ -968,7 +995,7 @@ static void add_ignore_packed(struct rev_info *revs, const char *name)
int num = ++revs->num_ignore_packed;
revs->ignore_packed = xrealloc(revs->ignore_packed,
- sizeof(const char **) * (num + 1));
+ sizeof(const char *) * (num + 1));
revs->ignore_packed[num-1] = name;
revs->ignore_packed[num] = NULL;
}
@@ -1033,6 +1060,14 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
revs->rewrite_parents = 1;
revs->simplify_history = 0;
revs->limited = 1;
+ } else if (!strcmp(arg, "--simplify-by-decoration")) {
+ revs->simplify_merges = 1;
+ revs->rewrite_parents = 1;
+ revs->simplify_history = 0;
+ revs->simplify_by_decoration = 1;
+ revs->limited = 1;
+ revs->prune = 1;
+ load_ref_decorations();
} else if (!strcmp(arg, "--date-order")) {
revs->lifo = 0;
revs->topo_order = 1;
diff --git a/revision.h b/revision.h
index 2fdb2dd0ff..7cf848771b 100644
--- a/revision.h
+++ b/revision.h
@@ -43,6 +43,7 @@ struct rev_info {
lifo:1,
topo_order:1,
simplify_merges:1,
+ simplify_by_decoration:1,
tag_objects:1,
tree_objects:1,
blob_objects:1,
@@ -53,6 +54,8 @@ struct rev_info {
left_right:1,
rewrite_parents:1,
print_parents:1,
+ show_source:1,
+ show_decorations:1,
reverse:1,
reverse_output_stage:1,
cherry_pick:1,
diff --git a/server-info.c b/server-info.c
index c1c073b2f0..66b0d9d878 100644
--- a/server-info.c
+++ b/server-info.c
@@ -25,7 +25,7 @@ static int add_info_ref(const char *path, const unsigned char *sha1, int flag, v
static int update_info_refs(int force)
{
- char *path0 = xstrdup(git_path("info/refs"));
+ char *path0 = git_pathdup("info/refs");
int len = strlen(path0);
char *path1 = xmalloc(len + 2);
diff --git a/setup.c b/setup.c
index 78a8041ff0..6b277b6a11 100644
--- a/setup.c
+++ b/setup.c
@@ -468,9 +468,10 @@ const char *setup_git_directory_gently(int *nongit_ok)
*nongit_ok = 1;
return NULL;
}
- die("Not a git repository");
+ die("Not a git repository (or any of the parent directories): %s", DEFAULT_GIT_DIR_ENVIRONMENT);
}
- chdir("..");
+ if (chdir(".."))
+ die("Cannot change to %s/..: %s", cwd, strerror(errno));
}
inside_git_dir = 0;
diff --git a/sha1_file.c b/sha1_file.c
index 3fbb0820a0..f08493f039 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -388,7 +388,7 @@ static void read_info_alternates(const char * relative_base, int depth)
void add_to_alternates_file(const char *reference)
{
struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));
- int fd = hold_lock_file_for_append(lock, git_path("objects/info/alternates"), 1);
+ int fd = hold_lock_file_for_append(lock, git_path("objects/info/alternates"), LOCK_DIE_ON_ERROR);
char *alt = mkpath("%s/objects\n", reference);
write_or_die(fd, alt, strlen(alt));
if (commit_lock_file(lock))
@@ -423,23 +423,30 @@ void prepare_alt_odb(void)
read_info_alternates(get_object_directory(), 0);
}
-static int has_loose_object(const unsigned char *sha1)
+static int has_loose_object_local(const unsigned char *sha1)
{
char *name = sha1_file_name(sha1);
- struct alternate_object_database *alt;
+ return !access(name, F_OK);
+}
- if (!access(name, F_OK))
- return 1;
+int has_loose_object_nonlocal(const unsigned char *sha1)
+{
+ struct alternate_object_database *alt;
prepare_alt_odb();
for (alt = alt_odb_list; alt; alt = alt->next) {
- name = alt->name;
- fill_sha1_path(name, sha1);
+ fill_sha1_path(alt->name, sha1);
if (!access(alt->base, F_OK))
return 1;
}
return 0;
}
+static int has_loose_object(const unsigned char *sha1)
+{
+ return has_loose_object_local(sha1) ||
+ has_loose_object_nonlocal(sha1);
+}
+
static unsigned int pack_used_ctr;
static unsigned int pack_mmap_calls;
static unsigned int peak_pack_open_windows;
@@ -666,6 +673,37 @@ void unuse_pack(struct pack_window **w_cursor)
}
/*
+ * This is used by git-repack in case a newly created pack happens to
+ * contain the same set of objects as an existing one. In that case
+ * the resulting file might be different even if its name would be the
+ * same. It is best to close any reference to the old pack before it is
+ * replaced on disk. Of course no index pointers nor windows for given pack
+ * must subsist at this point. If ever objects from this pack are requested
+ * again, the new version of the pack will be reinitialized through
+ * reprepare_packed_git().
+ */
+void free_pack_by_name(const char *pack_name)
+{
+ struct packed_git *p, **pp = &packed_git;
+
+ while (*pp) {
+ p = *pp;
+ if (strcmp(pack_name, p->pack_name) == 0) {
+ close_pack_windows(p);
+ if (p->pack_fd != -1)
+ close(p->pack_fd);
+ if (p->index_data)
+ munmap((void *)p->index_data, p->index_size);
+ free(p->bad_object_sha1);
+ *pp = p->next;
+ free(p);
+ return;
+ }
+ pp = &p->next;
+ }
+}
+
+/*
* Do not call this directly as this leaks p->pack_fd on error return;
* call open_packed_git() instead.
*/
@@ -841,6 +879,11 @@ struct packed_git *add_packed_git(const char *path, int path_len, int local)
return NULL;
}
memcpy(p->pack_name, path, path_len);
+
+ strcpy(p->pack_name + path_len, ".keep");
+ if (!access(p->pack_name, F_OK))
+ p->pack_keep = 1;
+
strcpy(p->pack_name + path_len, ".pack");
if (stat(p->pack_name, &st) || !S_ISREG(st.st_mode)) {
free(p);
@@ -1110,7 +1153,8 @@ static int legacy_loose_object(unsigned char *map)
return 0;
}
-unsigned long unpack_object_header_gently(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep)
+unsigned long unpack_object_header_buffer(const unsigned char *buf,
+ unsigned long len, enum object_type *type, unsigned long *sizep)
{
unsigned shift;
unsigned char c;
@@ -1122,10 +1166,10 @@ unsigned long unpack_object_header_gently(const unsigned char *buf, unsigned lon
size = c & 15;
shift = 4;
while (c & 0x80) {
- if (len <= used)
- return 0;
- if (sizeof(long) * 8 <= shift)
+ if (len <= used || sizeof(long) * 8 <= shift) {
+ error("bad object header");
return 0;
+ }
c = buf[used++];
size += (c & 0x7f) << shift;
shift += 7;
@@ -1164,7 +1208,7 @@ static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned lon
* really worth it and we don't write it any longer. But we
* can still read it.
*/
- used = unpack_object_header_gently(map, mapsize, &type, &size);
+ used = unpack_object_header_buffer(map, mapsize, &type, &size);
if (!used || !valid_loose_object_type[type])
return -1;
map += used;
@@ -1313,8 +1357,10 @@ unsigned long get_size_from_delta(struct packed_git *p,
} while ((st == Z_OK || st == Z_BUF_ERROR) &&
stream.total_out < sizeof(delta_head));
inflateEnd(&stream);
- if ((st != Z_STREAM_END) && stream.total_out != sizeof(delta_head))
- die("delta data unpack-initial failed");
+ if ((st != Z_STREAM_END) && stream.total_out != sizeof(delta_head)) {
+ error("delta data unpack-initial failed");
+ return 0;
+ }
/* Examine the initial part of the delta to figure out
* the result size.
@@ -1355,7 +1401,7 @@ static off_t get_delta_base(struct packed_git *p,
base_offset = (base_offset << 7) + (c & 127);
}
base_offset = delta_obj_offset - base_offset;
- if (base_offset >= delta_obj_offset)
+ if (base_offset <= 0 || base_offset >= delta_obj_offset)
return 0; /* out of bound */
*curpos += used;
} else if (type == OBJ_REF_DELTA) {
@@ -1381,15 +1427,32 @@ static int packed_delta_info(struct packed_git *p,
off_t base_offset;
base_offset = get_delta_base(p, w_curs, &curpos, type, obj_offset);
+ if (!base_offset)
+ return OBJ_BAD;
type = packed_object_info(p, base_offset, NULL);
+ if (type <= OBJ_NONE) {
+ struct revindex_entry *revidx;
+ const unsigned char *base_sha1;
+ revidx = find_pack_revindex(p, base_offset);
+ if (!revidx)
+ return OBJ_BAD;
+ base_sha1 = nth_packed_object_sha1(p, revidx->nr);
+ mark_bad_packed_object(p, base_sha1);
+ type = sha1_object_info(base_sha1, NULL);
+ if (type <= OBJ_NONE)
+ return OBJ_BAD;
+ }
/* We choose to only get the type of the base object and
* ignore potentially corrupt pack file that expects the delta
* based on a base with a wrong size. This saves tons of
* inflate() calls.
*/
- if (sizep)
+ if (sizep) {
*sizep = get_size_from_delta(p, w_curs, curpos);
+ if (*sizep == 0)
+ type = OBJ_BAD;
+ }
return type;
}
@@ -1411,10 +1474,11 @@ static int unpack_object_header(struct packed_git *p,
* insane, so we know won't exceed what we have been given.
*/
base = use_pack(p, w_curs, *curpos, &left);
- used = unpack_object_header_gently(base, left, &type, sizep);
- if (!used)
- die("object offset outside of pack file");
- *curpos += used;
+ used = unpack_object_header_buffer(base, left, &type, sizep);
+ if (!used) {
+ type = OBJ_BAD;
+ } else
+ *curpos += used;
return type;
}
@@ -1498,8 +1562,9 @@ static int packed_object_info(struct packed_git *p, off_t obj_offset,
*sizep = size;
break;
default:
- die("pack %s contains unknown object type %d",
- p->pack_name, type);
+ error("unknown object type %i at offset %"PRIuMAX" in %s",
+ type, (uintmax_t)obj_offset, p->pack_name);
+ type = OBJ_BAD;
}
unuse_pack(&w_curs);
return type;
@@ -1635,6 +1700,9 @@ static void add_delta_base_cache(struct packed_git *p, off_t base_offset,
delta_base_cache_lru.prev = &ent->lru;
}
+static void *read_object(const unsigned char *sha1, enum object_type *type,
+ unsigned long *size);
+
static void *unpack_delta_entry(struct packed_git *p,
struct pack_window **w_curs,
off_t curpos,
@@ -1663,9 +1731,12 @@ static void *unpack_delta_entry(struct packed_git *p,
* This is costly but should happen only in the presence
* of a corrupted pack, and is better than failing outright.
*/
- struct revindex_entry *revidx = find_pack_revindex(p, base_offset);
- const unsigned char *base_sha1 =
- nth_packed_object_sha1(p, revidx->nr);
+ struct revindex_entry *revidx;
+ const unsigned char *base_sha1;
+ revidx = find_pack_revindex(p, base_offset);
+ if (!revidx)
+ return NULL;
+ base_sha1 = nth_packed_object_sha1(p, revidx->nr);
error("failed to read delta base object %s"
" at offset %"PRIuMAX" from %s",
sha1_to_hex(base_sha1), (uintmax_t)base_offset,
@@ -1694,6 +1765,8 @@ static void *unpack_delta_entry(struct packed_git *p,
return result;
}
+int do_check_packed_object_crc;
+
void *unpack_entry(struct packed_git *p, off_t obj_offset,
enum object_type *type, unsigned long *sizep)
{
@@ -1701,6 +1774,20 @@ void *unpack_entry(struct packed_git *p, off_t obj_offset,
off_t curpos = obj_offset;
void *data;
+ if (do_check_packed_object_crc && p->index_version > 1) {
+ struct revindex_entry *revidx = find_pack_revindex(p, obj_offset);
+ unsigned long len = revidx[1].offset - obj_offset;
+ if (check_pack_crc(p, &w_curs, obj_offset, len, revidx->nr)) {
+ const unsigned char *sha1 =
+ nth_packed_object_sha1(p, revidx->nr);
+ error("bad packed object CRC for %s",
+ sha1_to_hex(sha1));
+ mark_bad_packed_object(p, sha1);
+ unuse_pack(&w_curs);
+ return NULL;
+ }
+ }
+
*type = unpack_object_header(p, &w_curs, &curpos, sizep);
switch (*type) {
case OBJ_OFS_DELTA:
@@ -1954,7 +2041,14 @@ int sha1_object_info(const unsigned char *sha1, unsigned long *sizep)
if (!find_pack_entry(sha1, &e, NULL))
return status;
}
- return packed_object_info(e.p, e.offset, sizep);
+
+ status = packed_object_info(e.p, e.offset, sizep);
+ if (status < 0) {
+ mark_bad_packed_object(e.p, sha1);
+ status = sha1_object_info(sha1, sizep);
+ }
+
+ return status;
}
static void *read_packed_sha1(const unsigned char *sha1,
@@ -1996,9 +2090,7 @@ static struct cached_object {
static int cached_object_nr, cached_object_alloc;
static struct cached_object empty_tree = {
- /* empty tree sha1: 4b825dc642cb6eb9a060e54bf8d69288fbee4904 */
- "\x4b\x82\x5d\xc6\x42\xcb\x6e\xb9\xa0\x60"
- "\xe5\x4b\xf8\xd6\x92\x88\xfb\xee\x49\x04",
+ EMPTY_TREE_SHA1_BIN,
OBJ_TREE,
"",
0
@@ -2041,8 +2133,8 @@ int pretend_sha1_file(void *buf, unsigned long len, enum object_type type,
return 0;
}
-void *read_object(const unsigned char *sha1, enum object_type *type,
- unsigned long *size)
+static void *read_object(const unsigned char *sha1, enum object_type *type,
+ unsigned long *size)
{
unsigned long mapsize;
void *map, *buf;
@@ -2231,7 +2323,7 @@ static int create_tmpfile(char *buffer, size_t bufsiz, const char *filename)
memcpy(buffer, filename, dirlen);
strcpy(buffer + dirlen, "tmp_obj_XXXXXX");
fd = mkstemp(buffer);
- if (fd < 0 && dirlen) {
+ if (fd < 0 && dirlen && errno == ENOENT) {
/* Make sure the directory exists */
memcpy(buffer, filename, dirlen);
buffer[dirlen-1] = 0;
@@ -2257,7 +2349,7 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
filename = sha1_file_name(sha1);
fd = create_tmpfile(tmpfile, sizeof(tmpfile), filename);
if (fd < 0) {
- if (errno == EPERM)
+ if (errno == EACCES)
return error("insufficient permission for adding an object to repository database %s\n", get_object_directory());
else
return error("unable to create temporary sha1 filename %s: %s\n", tmpfile, strerror(errno));
@@ -2333,6 +2425,7 @@ int force_object_loose(const unsigned char *sha1, time_t mtime)
enum object_type type;
char hdr[32];
int hdrlen;
+ int ret;
if (has_loose_object(sha1))
return 0;
@@ -2340,7 +2433,10 @@ int force_object_loose(const unsigned char *sha1, time_t mtime)
if (!buf)
return error("cannot read sha1_file for %s", sha1_to_hex(sha1));
hdrlen = sprintf(hdr, "%s %lu", typename(type), len) + 1;
- return write_loose_object(sha1, hdr, hdrlen, buf, len, mtime);
+ ret = write_loose_object(sha1, hdr, hdrlen, buf, len, mtime);
+ free(buf);
+
+ return ret;
}
int has_pack_index(const unsigned char *sha1)
@@ -2430,8 +2526,7 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object,
int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object)
{
int fd;
- char *target;
- size_t len;
+ struct strbuf sb = STRBUF_INIT;
switch (st->st_mode & S_IFMT) {
case S_IFREG:
@@ -2444,20 +2539,17 @@ int index_path(unsigned char *sha1, const char *path, struct stat *st, int write
path);
break;
case S_IFLNK:
- len = xsize_t(st->st_size);
- target = xmalloc(len + 1);
- if (readlink(path, target, len + 1) != st->st_size) {
+ if (strbuf_readlink(&sb, path, st->st_size)) {
char *errstr = strerror(errno);
- free(target);
return error("readlink(\"%s\"): %s", path,
errstr);
}
if (!write_object)
- hash_sha1_file(target, len, blob_type, sha1);
- else if (write_sha1_file(target, len, blob_type, sha1))
+ hash_sha1_file(sb.buf, sb.len, blob_type, sha1);
+ else if (write_sha1_file(sb.buf, sb.len, blob_type, sha1))
return error("%s: failed to insert into database",
path);
- free(target);
+ strbuf_release(&sb);
break;
case S_IFDIR:
return resolve_gitlink_ref(path, "HEAD", sha1);
diff --git a/sha1_name.c b/sha1_name.c
index 41b680915d..159c2ab84f 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -245,11 +245,13 @@ int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
*ref = NULL;
for (p = ref_rev_parse_rules; *p; p++) {
+ char fullref[PATH_MAX];
unsigned char sha1_from_ref[20];
unsigned char *this_result;
this_result = refs_found ? sha1_from_ref : sha1;
- r = resolve_ref(mkpath(*p, len, str), this_result, 1, NULL);
+ mksnpath(fullref, sizeof(fullref), *p, len, str);
+ r = resolve_ref(fullref, this_result, 1, NULL);
if (r) {
if (!refs_found++)
*ref = xstrdup(r);
@@ -272,7 +274,7 @@ int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
char path[PATH_MAX];
const char *ref, *it;
- strcpy(path, mkpath(*p, len, str));
+ mksnpath(path, sizeof(path), *p, len, str);
ref = resolve_ref(path, hash, 1, NULL);
if (!ref)
continue;
diff --git a/strbuf.c b/strbuf.c
index 720737d856..6ed06840b8 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -237,21 +237,40 @@ void strbuf_expand(struct strbuf *sb, const char *format, expand_fn_t fn,
}
}
+size_t strbuf_expand_dict_cb(struct strbuf *sb, const char *placeholder,
+ void *context)
+{
+ struct strbuf_expand_dict_entry *e = context;
+ size_t len;
+
+ for (; e->placeholder && (len = strlen(e->placeholder)); e++) {
+ if (!strncmp(placeholder, e->placeholder, len)) {
+ if (e->value)
+ strbuf_addstr(sb, e->value);
+ return len;
+ }
+ }
+ return 0;
+}
+
size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f)
{
size_t res;
+ size_t oldalloc = sb->alloc;
strbuf_grow(sb, size);
res = fread(sb->buf + sb->len, 1, size, f);
- if (res > 0) {
+ if (res > 0)
strbuf_setlen(sb, sb->len + res);
- }
+ else if (res < 0 && oldalloc == 0)
+ strbuf_release(sb);
return res;
}
ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
{
size_t oldlen = sb->len;
+ size_t oldalloc = sb->alloc;
strbuf_grow(sb, hint ? hint : 8192);
for (;;) {
@@ -259,7 +278,10 @@ ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
cnt = xread(fd, sb->buf + sb->len, sb->alloc - sb->len - 1);
if (cnt < 0) {
- strbuf_setlen(sb, oldlen);
+ if (oldalloc == 0)
+ strbuf_release(sb);
+ else
+ strbuf_setlen(sb, oldlen);
return -1;
}
if (!cnt)
@@ -272,6 +294,36 @@ ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
return sb->len - oldlen;
}
+#define STRBUF_MAXLINK (2*PATH_MAX)
+
+int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint)
+{
+ size_t oldalloc = sb->alloc;
+
+ if (hint < 32)
+ hint = 32;
+
+ while (hint < STRBUF_MAXLINK) {
+ int len;
+
+ strbuf_grow(sb, hint);
+ len = readlink(path, sb->buf, hint);
+ if (len < 0) {
+ if (errno != ERANGE)
+ break;
+ } else if (len < hint) {
+ strbuf_setlen(sb, len);
+ return 0;
+ }
+
+ /* .. the buffer was too small - try again */
+ hint *= 2;
+ }
+ if (oldalloc == 0)
+ strbuf_release(sb);
+ return -1;
+}
+
int strbuf_getline(struct strbuf *sb, FILE *fp, int term)
{
int ch;
diff --git a/strbuf.h b/strbuf.h
index eba7ba423a..89bd36e15a 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -111,6 +111,11 @@ extern void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len);
typedef size_t (*expand_fn_t) (struct strbuf *sb, const char *placeholder, void *context);
extern void strbuf_expand(struct strbuf *sb, const char *format, expand_fn_t fn, void *context);
+struct strbuf_expand_dict_entry {
+ const char *placeholder;
+ const char *value;
+};
+extern size_t strbuf_expand_dict_cb(struct strbuf *sb, const char *placeholder, void *context);
__attribute__((format(printf,2,3)))
extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...);
@@ -119,6 +124,7 @@ extern size_t strbuf_fread(struct strbuf *, size_t, FILE *);
/* XXX: if read fails, any partial read is undone */
extern ssize_t strbuf_read(struct strbuf *, int fd, size_t hint);
extern int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint);
+extern int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint);
extern int strbuf_getline(struct strbuf *, FILE *, int);
diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf
index 4717c2d33b..fdb19a50f1 100644
--- a/t/lib-httpd/apache.conf
+++ b/t/lib-httpd/apache.conf
@@ -1,6 +1,8 @@
ServerName dummy
PidFile httpd.pid
DocumentRoot www
+LogFormat "%h %l %u %t \"%r\" %>s %b" common
+CustomLog access.log common
ErrorLog error.log
<IfDefine SSL>
diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh
index 3d8e06a20f..1c77192eb3 100755
--- a/t/t0003-attributes.sh
+++ b/t/t0003-attributes.sh
@@ -47,6 +47,23 @@ test_expect_success 'attribute test' '
'
+test_expect_success 'attribute test: read paths from stdin' '
+
+ cat <<EOF > expect
+f: test: f
+a/f: test: f
+a/c/f: test: f
+a/g: test: a/g
+a/b/g: test: a/b/g
+b/g: test: unspecified
+a/b/h: test: a/b/h
+a/b/d/g: test: a/b/d/*
+EOF
+
+ sed -e "s/:.*//" < expect | git check-attr --stdin test > actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'root subdir attribute test' '
attr_check a/i a/i &&
diff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh
index 4b44e131b2..271bc4e17f 100755
--- a/t/t1001-read-tree-m-2way.sh
+++ b/t/t1001-read-tree-m-2way.sh
@@ -341,4 +341,55 @@ test_expect_success \
check_cache_at DF/DF dirty &&
:'
+test_expect_success \
+ 'a/b (untracked) vs a case setup.' \
+ 'rm -f .git/index &&
+ : >a &&
+ git update-index --add a &&
+ treeM=`git write-tree` &&
+ echo treeM $treeM &&
+ git ls-tree $treeM &&
+ git ls-files --stage >treeM.out &&
+
+ rm -f a &&
+ git update-index --remove a &&
+ mkdir a &&
+ : >a/b &&
+ treeH=`git write-tree` &&
+ echo treeH $treeH &&
+ git ls-tree $treeH'
+
+test_expect_success \
+ 'a/b (untracked) vs a, plus c/d case test.' \
+ '! git read-tree -u -m "$treeH" "$treeM" &&
+ git ls-files --stage &&
+ test -f a/b'
+
+test_expect_success \
+ 'a/b vs a, plus c/d case setup.' \
+ 'rm -f .git/index &&
+ rm -fr a &&
+ : >a &&
+ mkdir c &&
+ : >c/d &&
+ git update-index --add a c/d &&
+ treeM=`git write-tree` &&
+ echo treeM $treeM &&
+ git ls-tree $treeM &&
+ git ls-files --stage >treeM.out &&
+
+ rm -f a &&
+ mkdir a
+ : >a/b &&
+ git update-index --add --remove a a/b &&
+ treeH=`git write-tree` &&
+ echo treeH $treeH &&
+ git ls-tree $treeH'
+
+test_expect_success \
+ 'a/b vs a, plus c/d case test.' \
+ 'git read-tree -u -m "$treeH" "$treeM" &&
+ git ls-files --stage | tee >treeMcheck.out &&
+ test_cmp treeM.out treeMcheck.out'
+
test_done
diff --git a/t/t1005-read-tree-reset.sh b/t/t1005-read-tree-reset.sh
index b0d31f5a9b..849911683a 100755
--- a/t/t1005-read-tree-reset.sh
+++ b/t/t1005-read-tree-reset.sh
@@ -27,4 +27,64 @@ test_expect_success 'reset should work' '
test_cmp expect actual
'
+test_expect_success 'reset should remove remnants from a failed merge' '
+ git read-tree --reset -u HEAD &&
+ git ls-files -s >expect &&
+ sha1=$(git rev-parse :new) &&
+ (
+ echo "100644 $sha1 1 old"
+ echo "100644 $sha1 3 old"
+ ) | git update-index --index-info &&
+ >old &&
+ git ls-files -s &&
+ git read-tree --reset -u HEAD &&
+ git ls-files -s >actual &&
+ ! test -f old
+'
+
+test_expect_success 'Porcelain reset should remove remnants too' '
+ git read-tree --reset -u HEAD &&
+ git ls-files -s >expect &&
+ sha1=$(git rev-parse :new) &&
+ (
+ echo "100644 $sha1 1 old"
+ echo "100644 $sha1 3 old"
+ ) | git update-index --index-info &&
+ >old &&
+ git ls-files -s &&
+ git reset --hard &&
+ git ls-files -s >actual &&
+ ! test -f old
+'
+
+test_expect_success 'Porcelain checkout -f should remove remnants too' '
+ git read-tree --reset -u HEAD &&
+ git ls-files -s >expect &&
+ sha1=$(git rev-parse :new) &&
+ (
+ echo "100644 $sha1 1 old"
+ echo "100644 $sha1 3 old"
+ ) | git update-index --index-info &&
+ >old &&
+ git ls-files -s &&
+ git checkout -f &&
+ git ls-files -s >actual &&
+ ! test -f old
+'
+
+test_expect_success 'Porcelain checkout -f HEAD should remove remnants too' '
+ git read-tree --reset -u HEAD &&
+ git ls-files -s >expect &&
+ sha1=$(git rev-parse :new) &&
+ (
+ echo "100644 $sha1 1 old"
+ echo "100644 $sha1 3 old"
+ ) | git update-index --index-info &&
+ >old &&
+ git ls-files -s &&
+ git checkout -f HEAD &&
+ git ls-files -s >actual &&
+ ! test -f old
+'
+
test_done
diff --git a/t/t1301-shared-repo.sh b/t/t1301-shared-repo.sh
index dc85e8b60a..653362ba22 100755
--- a/t/t1301-shared-repo.sh
+++ b/t/t1301-shared-repo.sh
@@ -7,6 +7,9 @@ test_description='Test shared repository initialization'
. ./test-lib.sh
+# Remove a default ACL from the test dir if possible.
+setfacl -k . 2>/dev/null
+
# User must have read permissions to the repo -> failure on --shared=0400
test_expect_success 'shared = 0400 (faulty permission u-w)' '
mkdir sub && (
@@ -17,6 +20,10 @@ test_expect_success 'shared = 0400 (faulty permission u-w)' '
test $ret != "0"
'
+modebits () {
+ ls -l "$1" | sed -e 's|^\(..........\).*|\1|'
+}
+
for u in 002 022
do
test_expect_success "shared=1 does not clear bits preset by umask $u" '
@@ -82,8 +89,7 @@ do
rm -f .git/info/refs &&
git update-server-info &&
- actual="$(ls -l .git/info/refs)" &&
- actual=${actual%% *} &&
+ actual="$(modebits .git/info/refs)" &&
test "x$actual" = "x-$y" || {
ls -lt .git/info
false
@@ -95,8 +101,7 @@ do
rm -f .git/info/refs &&
git update-server-info &&
- actual="$(ls -l .git/info/refs)" &&
- actual=${actual%% *} &&
+ actual="$(modebits .git/info/refs)" &&
test "x$actual" = "x-$x" || {
ls -lt .git/info
false
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index 04c2b164bc..bd589268fc 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -75,6 +75,24 @@ test_expect_success "delete $m (by HEAD)" '
'
rm -f .git/$m
+cp -f .git/HEAD .git/HEAD.orig
+test_expect_success "delete symref without dereference" '
+ git update-ref --no-deref -d HEAD &&
+ ! test -f .git/HEAD
+'
+cp -f .git/HEAD.orig .git/HEAD
+
+test_expect_success "delete symref without dereference when the referred ref is packed" '
+ echo foo >foo.c &&
+ git add foo.c &&
+ git commit -m foo &&
+ git pack-refs --all &&
+ git update-ref --no-deref -d HEAD &&
+ ! test -f .git/HEAD
+'
+cp -f .git/HEAD.orig .git/HEAD
+git update-ref -d $m
+
test_expect_success '(not) create HEAD with old sha1' "
test_must_fail git update-ref HEAD $A $B
"
diff --git a/t/t2005-checkout-index-symlinks.sh b/t/t2005-checkout-index-symlinks.sh
index ed12c4d782..9fa5610474 100755
--- a/t/t2005-checkout-index-symlinks.sh
+++ b/t/t2005-checkout-index-symlinks.sh
@@ -13,7 +13,7 @@ file if core.symlinks is false.'
test_expect_success \
'preparation' '
git config core.symlinks false &&
-l=$(echo -n file | git hash-object -t blob -w --stdin) &&
+l=$(printf file | git hash-object -t blob -w --stdin) &&
echo "120000 $l symlink" | git update-index --index-info'
test_expect_success \
diff --git a/t/t2011-checkout-invalid-head.sh b/t/t2011-checkout-invalid-head.sh
new file mode 100755
index 0000000000..15ebdc26eb
--- /dev/null
+++ b/t/t2011-checkout-invalid-head.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+test_description='checkout switching away from an invalid branch'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ echo hello >world &&
+ git add world &&
+ git commit -m initial
+'
+
+test_expect_success 'checkout should not start branch from a tree' '
+ test_must_fail git checkout -b newbranch master^{tree}
+'
+
+test_expect_success 'checkout master from invalid HEAD' '
+ echo 0000000000000000000000000000000000000000 >.git/HEAD &&
+ git checkout master --
+'
+
+test_done
diff --git a/t/t2102-update-index-symlinks.sh b/t/t2102-update-index-symlinks.sh
index f195aefe3a..1ed44ee503 100755
--- a/t/t2102-update-index-symlinks.sh
+++ b/t/t2102-update-index-symlinks.sh
@@ -13,12 +13,12 @@ even if a plain file is in the working tree if core.symlinks is false.'
test_expect_success \
'preparation' '
git config core.symlinks false &&
-l=$(echo -n file | git hash-object -t blob -w --stdin) &&
+l=$(printf file | git hash-object -t blob -w --stdin) &&
echo "120000 $l symlink" | git update-index --index-info'
test_expect_success \
'modify the symbolic link' '
-echo -n new-file > symlink &&
+printf new-file > symlink &&
git update-index symlink'
test_expect_success \
diff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh
index d4de35ea06..58a329961e 100755
--- a/t/t2203-add-intent.sh
+++ b/t/t2203-add-intent.sh
@@ -32,5 +32,33 @@ test_expect_success 'intent to add does not clobber existing paths' '
! grep "$empty" actual
'
+test_expect_success 'cannot commit with i-t-a entry' '
+ test_tick &&
+ git commit -a -m initial &&
+ git reset --hard &&
+
+ echo xyzzy >rezrov &&
+ echo frotz >nitfol &&
+ git add rezrov &&
+ git add -N nitfol &&
+ test_must_fail git commit
+'
+
+test_expect_success 'can commit with an unrelated i-t-a entry in index' '
+ git reset --hard &&
+ echo xyzzy >rezrov &&
+ echo frotz >nitfol &&
+ git add rezrov &&
+ git add -N nitfol &&
+ git commit -m partial rezrov
+'
+
+test_expect_success 'can "commit -a" with an i-t-a entry' '
+ git reset --hard &&
+ : >nitfol &&
+ git add -N nitfol &&
+ git commit -a -m all
+'
+
test_done
diff --git a/t/t2300-cd-to-toplevel.sh b/t/t2300-cd-to-toplevel.sh
new file mode 100755
index 0000000000..e42cbfe6c6
--- /dev/null
+++ b/t/t2300-cd-to-toplevel.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+test_description='cd_to_toplevel'
+
+. ./test-lib.sh
+
+test_cd_to_toplevel () {
+ test_expect_success "$2" '
+ (
+ cd '"'$1'"' &&
+ . git-sh-setup &&
+ cd_to_toplevel &&
+ [ "$(unset PWD; /bin/pwd)" = "$TOPLEVEL" ]
+ )
+ '
+}
+
+TOPLEVEL="$(unset PWD; /bin/pwd)/repo"
+mkdir -p repo/sub/dir
+mv .git repo/
+SUBDIRECTORY_OK=1
+
+test_cd_to_toplevel repo 'at physical root'
+
+test_cd_to_toplevel repo/sub/dir 'at physical subdir'
+
+ln -s repo symrepo
+test_cd_to_toplevel symrepo 'at symbolic root'
+
+ln -s repo/sub/dir subdir-link
+test_cd_to_toplevel subdir-link 'at symbolic subdir'
+
+cd repo
+ln -s sub/dir internal-link
+test_cd_to_toplevel internal-link 'at internal symbolic subdir'
+
+test_done
diff --git a/t/t3001-ls-files-others-exclude.sh b/t/t3001-ls-files-others-exclude.sh
index 8666946b02..85aef12a11 100755
--- a/t/t3001-ls-files-others-exclude.sh
+++ b/t/t3001-ls-files-others-exclude.sh
@@ -140,4 +140,10 @@ test_expect_success 'trailing slash in exclude forces directory match (2)' '
'
+test_expect_success 'negated exclude matches can override previous ones' '
+
+ git ls-files --others --exclude="a.*" --exclude="!a.1" >output &&
+ grep "^a.1" output
+'
+
test_done
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 2147eacc50..61a2010f5b 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -112,6 +112,15 @@ test_expect_success 'config information was renamed, too' \
"test $(git config branch.s.dummy) = Hello &&
test_must_fail git config branch.s/s/dummy"
+test_expect_success 'renaming a symref is not allowed' \
+'
+ git symbolic-ref refs/heads/master2 refs/heads/master &&
+ test_must_fail git branch -m master2 master3 &&
+ git symbolic-ref refs/heads/master2 &&
+ test -f .git/refs/heads/master &&
+ ! test -f .git/refs/heads/master3
+'
+
test_expect_success \
'git branch -m u v should fail when the reflog for u is a symlink' '
git branch -l u &&
@@ -185,7 +194,8 @@ test_expect_success 'test deleting branch deletes branch config' \
test_expect_success 'test deleting branch without config' \
'git branch my7 s &&
- test "$(git branch -d my7 2>&1)" = "Deleted branch my7."'
+ sha1=$(git rev-parse my7 | cut -c 1-7) &&
+ test "$(git branch -d my7 2>&1)" = "Deleted branch my7 ($sha1)."'
test_expect_success 'test --track without .fetch entries' \
'git branch --track my8 &&
diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh
index 087ef75061..413019acaf 100755
--- a/t/t3210-pack-refs.sh
+++ b/t/t3210-pack-refs.sh
@@ -96,6 +96,13 @@ test_expect_success \
git branch -d n/o/p &&
git branch n'
+test_expect_success \
+ 'see if up-to-date packed refs are preserved' \
+ 'git branch q &&
+ git pack-refs --all --prune &&
+ git update-ref refs/heads/q refs/heads/q &&
+ ! test -f .git/refs/heads/q'
+
test_expect_success 'pack, prune and repack' '
git tag foo &&
git pack-refs --all --prune &&
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 7d10a27f1d..2cc8e7abe1 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -373,6 +373,38 @@ test_expect_success '--continue tries to commit, even for "edit"' '
test $parent = $(git rev-parse HEAD^)
'
+test_expect_success 'aborted --continue does not squash commits after "edit"' '
+ old=$(git rev-parse HEAD) &&
+ test_tick &&
+ FAKE_LINES="edit 1" git rebase -i HEAD^ &&
+ echo "edited again" > file7 &&
+ git add file7 &&
+ (
+ FAKE_COMMIT_MESSAGE=" " &&
+ export FAKE_COMMIT_MESSAGE &&
+ test_must_fail git rebase --continue
+ ) &&
+ test $old = $(git rev-parse HEAD) &&
+ git rebase --abort
+'
+
+test_expect_success 'auto-amend only edited commits after "edit"' '
+ test_tick &&
+ FAKE_LINES="edit 1" git rebase -i HEAD^ &&
+ echo "edited again" > file7 &&
+ git add file7 &&
+ FAKE_COMMIT_MESSAGE="edited file7 again" git commit &&
+ echo "and again" > file7 &&
+ git add file7 &&
+ test_tick &&
+ (
+ FAKE_COMMIT_MESSAGE="and again" &&
+ export FAKE_COMMIT_MESSAGE &&
+ test_must_fail git rebase --continue
+ ) &&
+ git rebase --abort
+'
+
test_expect_success 'rebase a detached HEAD' '
grandparent=$(git rev-parse HEAD~2) &&
git checkout $(git rev-parse HEAD) &&
diff --git a/t/t3409-rebase-hook.sh b/t/t3409-rebase-hook.sh
index bc93dda8fd..1f1b850677 100755
--- a/t/t3409-rebase-hook.sh
+++ b/t/t3409-rebase-hook.sh
@@ -123,4 +123,20 @@ test_expect_success 'pre-rebase hook stops rebase (2)' '
test 0 = $(git rev-list HEAD...side | wc -l)
'
+test_expect_success 'rebase --no-verify overrides pre-rebase (1)' '
+ git checkout test &&
+ git reset --hard side &&
+ git rebase --no-verify master &&
+ test "z$(git symbolic-ref HEAD)" = zrefs/heads/test &&
+ test "z$(cat git)" = zworld
+'
+
+test_expect_success 'rebase --no-verify overrides pre-rebase (2)' '
+ git checkout test &&
+ git reset --hard side &&
+ EDITOR=true git rebase --no-verify -i master &&
+ test "z$(git symbolic-ref HEAD)" = zrefs/heads/test &&
+ test "z$(cat git)" = zworld
+'
+
test_done
diff --git a/t/t3409-rebase-preserve-merges.sh b/t/t3409-rebase-preserve-merges.sh
new file mode 100755
index 0000000000..e6c832780f
--- /dev/null
+++ b/t/t3409-rebase-preserve-merges.sh
@@ -0,0 +1,95 @@
+#!/bin/sh
+#
+# Copyright(C) 2008 Stephen Habermann & Andreas Ericsson
+#
+test_description='git rebase -p should preserve merges
+
+Run "git rebase -p" and check that merges are properly carried along
+'
+. ./test-lib.sh
+
+GIT_AUTHOR_EMAIL=bogus_email_address
+export GIT_AUTHOR_EMAIL
+
+# Clone 1 (trivial merge):
+#
+# A1--A2 <-- origin/master
+# \ \
+# B1--M <-- topic
+# \
+# B2 <-- origin/topic
+#
+# Clone 2 (conflicting merge):
+#
+# A1--A2--B3 <-- origin/master
+# \ \
+# B1------M <-- topic
+# \
+# B2 <-- origin/topic
+#
+# In both cases, 'topic' is rebased onto 'origin/topic'.
+
+test_expect_success 'setup for merge-preserving rebase' \
+ 'echo First > A &&
+ git add A &&
+ git-commit -m "Add A1" &&
+ git checkout -b topic &&
+ echo Second > B &&
+ git add B &&
+ git-commit -m "Add B1" &&
+ git checkout -f master &&
+ echo Third >> A &&
+ git-commit -a -m "Modify A2" &&
+
+ git clone ./. clone1 &&
+ cd clone1 &&
+ git checkout -b topic origin/topic &&
+ git merge origin/master &&
+ cd .. &&
+
+ echo Fifth > B &&
+ git add B &&
+ git commit -m "Add different B" &&
+
+ git clone ./. clone2 &&
+ cd clone2 &&
+ git checkout -b topic origin/topic &&
+ test_must_fail git merge origin/master &&
+ echo Resolved > B &&
+ git add B &&
+ git commit -m "Merge origin/master into topic" &&
+ cd .. &&
+
+ git checkout topic &&
+ echo Fourth >> B &&
+ git commit -a -m "Modify B2"
+'
+
+test_expect_success 'rebase -p fakes interactive rebase' '
+ (
+ cd clone1 &&
+ git fetch &&
+ git rebase -p origin/topic &&
+ test 1 = $(git rev-list --all --pretty=oneline | grep "Modify A" | wc -l) &&
+ test 1 = $(git rev-list --all --pretty=oneline | grep "Merge commit" | wc -l)
+ )
+'
+
+test_expect_success '--continue works after a conflict' '
+ (
+ cd clone2 &&
+ git fetch &&
+ test_must_fail git rebase -p origin/topic &&
+ test 2 = $(git ls-files B | wc -l) &&
+ echo Resolved again > B &&
+ test_must_fail git rebase --continue &&
+ grep "^@@@ " .git/rebase-merge/patch &&
+ git add B &&
+ git rebase --continue &&
+ test 1 = $(git rev-list --all --pretty=oneline | grep "Modify A" | wc -l) &&
+ test 1 = $(git rev-list --all --pretty=oneline | grep "Add different" | wc -l) &&
+ test 1 = $(git rev-list --all --pretty=oneline | grep "Merge origin" | wc -l)
+ )
+'
+
+test_done
diff --git a/t/t3410-rebase-preserve-dropped-merges.sh b/t/t3410-rebase-preserve-dropped-merges.sh
new file mode 100755
index 0000000000..5816415aaf
--- /dev/null
+++ b/t/t3410-rebase-preserve-dropped-merges.sh
@@ -0,0 +1,139 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Stephen Haberman
+#
+
+test_description='git rebase preserve merges
+
+This test runs git rebase with preserve merges and ensures commits
+dropped by the --cherry-pick flag have their childrens parents
+rewritten.
+'
+. ./test-lib.sh
+
+# set up two branches like this:
+#
+# A - B - C - D - E
+# \
+# F - G - H
+# \
+# I
+#
+# where B, D and G touch the same file.
+
+test_expect_success 'setup' '
+ : > file1 &&
+ git add file1 &&
+ test_tick &&
+ git commit -m A &&
+ git tag A &&
+ echo 1 > file1 &&
+ test_tick &&
+ git commit -m B file1 &&
+ : > file2 &&
+ git add file2 &&
+ test_tick &&
+ git commit -m C &&
+ echo 2 > file1 &&
+ test_tick &&
+ git commit -m D file1 &&
+ : > file3 &&
+ git add file3 &&
+ test_tick &&
+ git commit -m E &&
+ git tag E &&
+ git checkout -b branch1 A &&
+ : > file4 &&
+ git add file4 &&
+ test_tick &&
+ git commit -m F &&
+ git tag F &&
+ echo 3 > file1 &&
+ test_tick &&
+ git commit -m G file1 &&
+ git tag G &&
+ : > file5 &&
+ git add file5 &&
+ test_tick &&
+ git commit -m H &&
+ git tag H &&
+ git checkout -b branch2 F &&
+ : > file6 &&
+ git add file6 &&
+ test_tick &&
+ git commit -m I &&
+ git tag I
+'
+
+# A - B - C - D - E
+# \ \ \
+# F - G - H -- L \ --> L
+# \ | \
+# I -- G2 -- J -- K I -- K
+# G2 = same changes as G
+test_expect_success 'skip same-resolution merges with -p' '
+ git checkout branch1 &&
+ ! git merge E &&
+ echo 23 > file1 &&
+ git add file1 &&
+ git commit -m L &&
+ git checkout branch2 &&
+ echo 3 > file1 &&
+ git commit -a -m G2 &&
+ ! git merge E &&
+ echo 23 > file1 &&
+ git add file1 &&
+ git commit -m J &&
+ echo file7 > file7 &&
+ git add file7 &&
+ git commit -m K &&
+ GIT_EDITOR=: git rebase -i -p branch1 &&
+ test $(git rev-parse branch2^^) = $(git rev-parse branch1) &&
+ test "23" = "$(cat file1)" &&
+ test "" = "$(cat file6)" &&
+ test "file7" = "$(cat file7)" &&
+
+ git checkout branch1 &&
+ git reset --hard H &&
+ git checkout branch2 &&
+ git reset --hard I
+'
+
+# A - B - C - D - E
+# \ \ \
+# F - G - H -- L \ --> L
+# \ | \
+# I -- G2 -- J -- K I -- G2 -- K
+# G2 = different changes as G
+test_expect_success 'keep different-resolution merges with -p' '
+ git checkout branch1 &&
+ ! git merge E &&
+ echo 23 > file1 &&
+ git add file1 &&
+ git commit -m L &&
+ git checkout branch2 &&
+ echo 4 > file1 &&
+ git commit -a -m G2 &&
+ ! git merge E &&
+ echo 24 > file1 &&
+ git add file1 &&
+ git commit -m J &&
+ echo file7 > file7 &&
+ git add file7 &&
+ git commit -m K &&
+ ! GIT_EDITOR=: git rebase -i -p branch1 &&
+ echo 234 > file1 &&
+ git add file1 &&
+ GIT_EDITOR=: git rebase --continue &&
+ test $(git rev-parse branch2^^^) = $(git rev-parse branch1) &&
+ test "234" = "$(cat file1)" &&
+ test "" = "$(cat file6)" &&
+ test "file7" = "$(cat file7)" &&
+
+ git checkout branch1 &&
+ git reset --hard H &&
+ git checkout branch2 &&
+ git reset --hard I
+'
+
+test_done
diff --git a/t/t3411-rebase-preserve-around-merges.sh b/t/t3411-rebase-preserve-around-merges.sh
new file mode 100755
index 0000000000..aacfaae843
--- /dev/null
+++ b/t/t3411-rebase-preserve-around-merges.sh
@@ -0,0 +1,135 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Stephen Haberman
+#
+
+test_description='git rebase preserve merges
+
+This test runs git rebase with and tries to squash a commit from after a merge
+to before the merge.
+'
+. ./test-lib.sh
+
+# Copy/paste from t3404-rebase-interactive.sh
+echo "#!$SHELL_PATH" >fake-editor.sh
+cat >> fake-editor.sh <<\EOF
+case "$1" in
+*/COMMIT_EDITMSG)
+ test -z "$FAKE_COMMIT_MESSAGE" || echo "$FAKE_COMMIT_MESSAGE" > "$1"
+ test -z "$FAKE_COMMIT_AMEND" || echo "$FAKE_COMMIT_AMEND" >> "$1"
+ exit
+ ;;
+esac
+test -z "$EXPECT_COUNT" ||
+ test "$EXPECT_COUNT" = $(sed -e '/^#/d' -e '/^$/d' < "$1" | wc -l) ||
+ exit
+test -z "$FAKE_LINES" && exit
+grep -v '^#' < "$1" > "$1".tmp
+rm -f "$1"
+cat "$1".tmp
+action=pick
+for line in $FAKE_LINES; do
+ case $line in
+ squash|edit)
+ action="$line";;
+ *)
+ echo sed -n "${line}s/^pick/$action/p"
+ sed -n "${line}p" < "$1".tmp
+ sed -n "${line}s/^pick/$action/p" < "$1".tmp >> "$1"
+ action=pick;;
+ esac
+done
+EOF
+
+test_set_editor "$(pwd)/fake-editor.sh"
+chmod a+x fake-editor.sh
+
+# set up two branches like this:
+#
+# A1 - B1 - D1 - E1 - F1
+# \ /
+# -- C1 --
+
+test_expect_success 'setup' '
+ touch a &&
+ touch b &&
+ git add a &&
+ git commit -m A1 &&
+ git tag A1
+ git add b &&
+ git commit -m B1 &&
+ git tag B1 &&
+ git checkout -b branch &&
+ touch c &&
+ git add c &&
+ git commit -m C1 &&
+ git checkout master &&
+ touch d &&
+ git add d &&
+ git commit -m D1 &&
+ git merge branch &&
+ touch f &&
+ git add f &&
+ git commit -m F1 &&
+ git tag F1
+'
+
+# Should result in:
+#
+# A1 - B1 - D2 - E2
+# \ /
+# -- C1 --
+#
+test_expect_success 'squash F1 into D1' '
+ FAKE_LINES="1 squash 3 2" git rebase -i -p B1 &&
+ test "$(git rev-parse HEAD^2)" = "$(git rev-parse branch)" &&
+ test "$(git rev-parse HEAD~2)" = "$(git rev-parse B1)" &&
+ git tag E2
+'
+
+# Start with:
+#
+# A1 - B1 - D2 - E2
+# \
+# G1 ---- L1 ---- M1
+# \ /
+# H1 -- J1 -- K1
+# \ /
+# -- I1 --
+#
+# And rebase G1..M1 onto E2
+
+test_expect_success 'rebase two levels of merge' '
+ git checkout -b branch2 A1 &&
+ touch g &&
+ git add g &&
+ git commit -m G1 &&
+ git checkout -b branch3 &&
+ touch h
+ git add h &&
+ git commit -m H1 &&
+ git checkout -b branch4 &&
+ touch i &&
+ git add i &&
+ git commit -m I1 &&
+ git tag I1 &&
+ git checkout branch3 &&
+ touch j &&
+ git add j &&
+ git commit -m J1 &&
+ git merge I1 --no-commit &&
+ git commit -m K1 &&
+ git tag K1 &&
+ git checkout branch2 &&
+ touch l &&
+ git add l &&
+ git commit -m L1 &&
+ git merge K1 --no-commit &&
+ git commit -m M1 &&
+ GIT_EDITOR=: git rebase -i -p E2 &&
+ test "$(git rev-parse HEAD~3)" = "$(git rev-parse E2)" &&
+ test "$(git rev-parse HEAD~2)" = "$(git rev-parse HEAD^2^2~2)" &&
+ test "$(git rev-parse HEAD^2^1^1)" = "$(git rev-parse HEAD^2^2^1)"
+'
+
+test_done
diff --git a/t/t3501-revert-cherry-pick.sh b/t/t3501-revert-cherry-pick.sh
index 6da212825a..bb4cf00d78 100755
--- a/t/t3501-revert-cherry-pick.sh
+++ b/t/t3501-revert-cherry-pick.sh
@@ -45,6 +45,7 @@ test_expect_success 'cherry-pick after renaming branch' '
git checkout rename2 &&
git cherry-pick added &&
+ test $(git rev-parse HEAD^) = $(git rev-parse rename2) &&
test -f opos &&
grep "Add extra line at the end" opos
@@ -54,6 +55,7 @@ test_expect_success 'revert after renaming branch' '
git checkout rename1 &&
git revert added &&
+ test $(git rev-parse HEAD^) = $(git rev-parse rename1) &&
test -f spoo &&
! grep "Add extra line at the end" spoo
diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh
index 66aca99fd3..95542e9cfe 100755
--- a/t/t3600-rm.sh
+++ b/t/t3600-rm.sh
@@ -187,6 +187,19 @@ test_expect_success 'but with -f it should work.' '
test_must_fail git ls-files --error-unmatch baz
'
+test_expect_success 'refuse to remove cached empty file with modifications' '
+ >empty &&
+ git add empty &&
+ echo content >empty &&
+ test_must_fail git rm --cached empty
+'
+
+test_expect_success 'remove intent-to-add file without --force' '
+ echo content >intent-to-add &&
+ git add -N intent-to-add
+ git rm --cached intent-to-add
+'
+
test_expect_success 'Recursive test setup' '
mkdir -p frotz &&
echo qfwfq >frotz/nitfol &&
@@ -238,4 +251,21 @@ test_expect_success 'refresh index before checking if it is up-to-date' '
'
+test_expect_success 'choking "git rm" should not let it die with cruft' '
+ git reset -q --hard &&
+ H=0000000000000000000000000000000000000000 &&
+ i=0 &&
+ while test $i -lt 12000
+ do
+ echo "100644 $H 0 some-file-$i"
+ i=$(( $i + 1 ))
+ done | git update-index --index-info &&
+ git rm -n "some-file-*" | :;
+ test -f .git/index.lock
+ status=$?
+ rm -f .git/index.lock
+ git reset -q --hard
+ test "$status" != 0
+'
+
test_done
diff --git a/t/t4012-diff-binary.sh b/t/t4012-diff-binary.sh
index 421f4bba3f..3cf5b5c4ea 100755
--- a/t/t4012-diff-binary.sh
+++ b/t/t4012-diff-binary.sh
@@ -25,11 +25,11 @@ cat > expected <<\EOF
EOF
test_expect_success 'diff without --binary' \
'git diff | git apply --stat --summary >current &&
- cmp current expected'
+ test_cmp expected current'
test_expect_success 'diff with --binary' \
'git diff --binary | git apply --stat --summary >current &&
- cmp current expected'
+ test_cmp expected current'
# apply needs to be able to skip the binary material correctly
# in order to report the line number of a corrupt patch.
diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh
index 520e095c59..be541348c6 100755
--- a/t/t4018-diff-funcname.sh
+++ b/t/t4018-diff-funcname.sh
@@ -32,7 +32,7 @@ EOF
sed 's/beer\\/beer,\\/' < Beer.java > Beer-correct.java
-builtin_patterns="bibtex html java pascal php python ruby tex"
+builtin_patterns="bibtex html java objc pascal php python ruby tex"
for p in $builtin_patterns
do
test_expect_success "builtin $p pattern compiles" '
@@ -65,7 +65,14 @@ test_expect_success 'custom pattern' '
test_expect_success 'last regexp must not be negated' '
git config diff.java.funcname "!static" &&
- test_must_fail git diff --no-index Beer.java Beer-correct.java
+ git diff --no-index Beer.java Beer-correct.java 2>&1 |
+ grep "fatal: Last expression must not be negated:"
+'
+
+test_expect_success 'pattern which matches to end of line' '
+ git config diff.java.funcname "Beer$" &&
+ git diff --no-index Beer.java Beer-correct.java |
+ grep "^@@.*@@ Beer"
'
test_expect_success 'alternation in pattern' '
diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh
index dfe3fbc74b..caea292f15 100755
--- a/t/t4020-diff-external.sh
+++ b/t/t4020-diff-external.sh
@@ -43,6 +43,13 @@ test_expect_success 'GIT_EXTERNAL_DIFF environment should apply only to diff' '
'
+test_expect_success 'GIT_EXTERNAL_DIFF environment and --no-ext-diff' '
+
+ GIT_EXTERNAL_DIFF=echo git diff --no-ext-diff |
+ grep "^diff --git a/file b/file"
+
+'
+
test_expect_success 'diff attribute' '
git config diff.parrot.command echo &&
@@ -68,6 +75,13 @@ test_expect_success 'diff attribute should apply only to diff' '
'
+test_expect_success 'diff attribute and --no-ext-diff' '
+
+ git diff --no-ext-diff |
+ grep "^diff --git a/file b/file"
+
+'
+
test_expect_success 'diff attribute' '
git config --unset diff.parrot.command &&
@@ -94,6 +108,13 @@ test_expect_success 'diff attribute should apply only to diff' '
'
+test_expect_success 'diff attribute and --no-ext-diff' '
+
+ git diff --no-ext-diff |
+ grep "^diff --git a/file b/file"
+
+'
+
test_expect_success 'no diff with -diff' '
echo >.gitattributes "file -diff" &&
git diff | grep Binary
diff --git a/t/t4030-diff-textconv.sh b/t/t4030-diff-textconv.sh
new file mode 100755
index 0000000000..2f27a0ba9e
--- /dev/null
+++ b/t/t4030-diff-textconv.sh
@@ -0,0 +1,126 @@
+#!/bin/sh
+
+test_description='diff.*.textconv tests'
+. ./test-lib.sh
+
+find_diff() {
+ sed '1,/^index /d' | sed '/^-- $/,$d'
+}
+
+cat >expect.binary <<'EOF'
+Binary files a/file and b/file differ
+EOF
+
+cat >expect.text <<'EOF'
+--- a/file
++++ b/file
+@@ -1 +1,2 @@
+ 0
++1
+EOF
+
+cat >hexdump <<'EOF'
+#!/bin/sh
+perl -e '$/ = undef; $_ = <>; s/./ord($&)/ge; print $_' < "$1"
+EOF
+chmod +x hexdump
+
+test_expect_success 'setup binary file with history' '
+ printf "\\0\\n" >file &&
+ git add file &&
+ git commit -m one &&
+ printf "\\01\\n" >>file &&
+ git add file &&
+ git commit -m two
+'
+
+test_expect_success 'file is considered binary by porcelain' '
+ git diff HEAD^ HEAD >diff &&
+ find_diff <diff >actual &&
+ test_cmp expect.binary actual
+'
+
+test_expect_success 'file is considered binary by plumbing' '
+ git diff-tree -p HEAD^ HEAD >diff &&
+ find_diff <diff >actual &&
+ test_cmp expect.binary actual
+'
+
+test_expect_success 'setup textconv filters' '
+ echo file diff=foo >.gitattributes &&
+ git config diff.foo.textconv "$PWD"/hexdump &&
+ git config diff.fail.textconv false
+'
+
+test_expect_success 'diff produces text' '
+ git diff HEAD^ HEAD >diff &&
+ find_diff <diff >actual &&
+ test_cmp expect.text actual
+'
+
+test_expect_success 'diff-tree produces binary' '
+ git diff-tree -p HEAD^ HEAD >diff &&
+ find_diff <diff >actual &&
+ test_cmp expect.binary actual
+'
+
+test_expect_success 'log produces text' '
+ git log -1 -p >log &&
+ find_diff <log >actual &&
+ test_cmp expect.text actual
+'
+
+test_expect_success 'format-patch produces binary' '
+ git format-patch --no-binary --stdout HEAD^ >patch &&
+ find_diff <patch >actual &&
+ test_cmp expect.binary actual
+'
+
+test_expect_success 'status -v produces text' '
+ git reset --soft HEAD^ &&
+ git status -v >diff &&
+ find_diff <diff >actual &&
+ test_cmp expect.text actual &&
+ git reset --soft HEAD@{1}
+'
+
+cat >expect.stat <<'EOF'
+ file | Bin 2 -> 4 bytes
+ 1 files changed, 0 insertions(+), 0 deletions(-)
+EOF
+test_expect_success 'diffstat does not run textconv' '
+ echo file diff=fail >.gitattributes &&
+ git diff --stat HEAD^ HEAD >actual &&
+ test_cmp expect.stat actual
+'
+# restore working setup
+echo file diff=foo >.gitattributes
+
+cat >expect.typechange <<'EOF'
+--- a/file
++++ /dev/null
+@@ -1,2 +0,0 @@
+-0
+-1
+diff --git a/file b/file
+new file mode 120000
+index ad8b3d2..67be421
+--- /dev/null
++++ b/file
+@@ -0,0 +1 @@
++frotz
+\ No newline at end of file
+EOF
+# make a symlink the hard way that works on symlink-challenged file systems
+test_expect_success 'textconv does not act on symlinks' '
+ printf frotz > file &&
+ git add file &&
+ git ls-files -s | sed -e s/100644/120000/ |
+ git update-index --index-info &&
+ git commit -m typechange &&
+ git show >diff &&
+ find_diff <diff >actual &&
+ test_cmp expect.typechange actual
+'
+
+test_done
diff --git a/t/t4031-diff-rewrite-binary.sh b/t/t4031-diff-rewrite-binary.sh
new file mode 100755
index 0000000000..a894c60622
--- /dev/null
+++ b/t/t4031-diff-rewrite-binary.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+test_description='rewrite diff on binary file'
+
+. ./test-lib.sh
+
+# We must be large enough to meet the MINIMUM_BREAK_SIZE
+# requirement.
+make_file() {
+ # common first line to help identify rewrite versus regular diff
+ printf "=\n" >file
+ for i in 1 2 3 4 5 6 7 8 9 10
+ do
+ for j in 1 2 3 4 5 6 7 8 9
+ do
+ for k in 1 2 3 4 5
+ do
+ printf "$1\n"
+ done
+ done
+ done >>file
+}
+
+test_expect_success 'create binary file with changes' '
+ make_file "\\0" &&
+ git add file &&
+ make_file "\\01"
+'
+
+test_expect_success 'vanilla diff is binary' '
+ git diff >diff &&
+ grep "Binary files a/file and b/file differ" diff
+'
+
+test_expect_success 'rewrite diff is binary' '
+ git diff -B >diff &&
+ grep "dissimilarity index" diff &&
+ grep "Binary files a/file and b/file differ" diff
+'
+
+test_expect_success 'rewrite diff can show binary patch' '
+ git diff -B --binary >diff &&
+ grep "dissimilarity index" diff &&
+ grep "GIT binary patch" diff
+'
+
+{
+ echo "#!$SHELL_PATH"
+ cat <<'EOF'
+perl -e '$/ = undef; $_ = <>; s/./ord($&)/ge; print $_' < "$1"
+EOF
+} >dump
+chmod +x dump
+
+test_expect_success 'setup textconv' '
+ echo file diff=foo >.gitattributes &&
+ git config diff.foo.textconv "$PWD"/dump
+'
+
+test_expect_success 'rewrite diff respects textconv' '
+ git diff -B >diff &&
+ grep "dissimilarity index" diff &&
+ grep "^-61" diff &&
+ grep "^-0" diff
+'
+
+test_done
diff --git a/t/t4032-diff-inter-hunk-context.sh b/t/t4032-diff-inter-hunk-context.sh
new file mode 100755
index 0000000000..e4e3e28fc7
--- /dev/null
+++ b/t/t4032-diff-inter-hunk-context.sh
@@ -0,0 +1,92 @@
+#!/bin/sh
+
+test_description='diff hunk fusing'
+
+. ./test-lib.sh
+
+f() {
+ echo $1
+ i=1
+ while test $i -le $2
+ do
+ echo $i
+ i=$(expr $i + 1)
+ done
+ echo $3
+}
+
+t() {
+ case $# in
+ 4) hunks=$4; cmd="diff -U$3";;
+ 5) hunks=$5; cmd="diff -U$3 --inter-hunk-context=$4";;
+ esac
+ label="$cmd, $1 common $2"
+ file=f$1
+ expected=expected.$file.$3.$hunks
+
+ if ! test -f $file
+ then
+ f A $1 B >$file
+ git add $file
+ git commit -q -m. $file
+ f X $1 Y >$file
+ fi
+
+ test_expect_success "$label: count hunks ($hunks)" "
+ test $(git $cmd $file | grep '^@@ ' | wc -l) = $hunks
+ "
+
+ test -f $expected &&
+ test_expect_success "$label: check output" "
+ git $cmd $file | grep -v '^index ' >actual &&
+ test_cmp $expected actual
+ "
+}
+
+cat <<EOF >expected.f1.0.1 || exit 1
+diff --git a/f1 b/f1
+--- a/f1
++++ b/f1
+@@ -1,3 +1,3 @@
+-A
++X
+ 1
+-B
++Y
+EOF
+
+cat <<EOF >expected.f1.0.2 || exit 1
+diff --git a/f1 b/f1
+--- a/f1
++++ b/f1
+@@ -1 +1 @@
+-A
++X
+@@ -3 +3 @@ A
+-B
++Y
+EOF
+
+# common lines ctx intrctx hunks
+t 1 line 0 2
+t 1 line 0 0 2
+t 1 line 0 1 1
+t 1 line 0 2 1
+t 1 line 1 1
+
+t 2 lines 0 2
+t 2 lines 0 0 2
+t 2 lines 0 1 2
+t 2 lines 0 2 1
+t 2 lines 1 1
+
+t 3 lines 1 2
+t 3 lines 1 0 2
+t 3 lines 1 1 1
+t 3 lines 1 2 1
+
+t 9 lines 3 2
+t 9 lines 3 2 2
+t 9 lines 3 3 1
+
+test_done
diff --git a/t/t4128-apply-root.sh b/t/t4128-apply-root.sh
index bc7a8a8689..8f6aea48d8 100755
--- a/t/t4128-apply-root.sh
+++ b/t/t4128-apply-root.sh
@@ -72,7 +72,7 @@ test_expect_success 'apply --directory (delete file)' '
echo content >some/sub/dir/delfile &&
git add some/sub/dir/delfile &&
git apply --directory=some/sub/dir/ --index patch &&
- ! git ls-files | grep delfile
+ ! (git ls-files | grep delfile)
'
cat > patch << 'EOF'
diff --git a/t/t4129-apply-samemode.sh b/t/t4129-apply-samemode.sh
new file mode 100755
index 0000000000..adfcbb5a3b
--- /dev/null
+++ b/t/t4129-apply-samemode.sh
@@ -0,0 +1,62 @@
+#!/bin/sh
+
+test_description='applying patch with mode bits'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ echo original >file &&
+ git add file &&
+ test_tick &&
+ git commit -m initial &&
+ git tag initial &&
+ echo modified >file &&
+ git diff --stat -p >patch-0.txt &&
+ chmod +x file &&
+ git diff --stat -p >patch-1.txt
+'
+
+test_expect_success 'same mode (no index)' '
+ git reset --hard &&
+ chmod +x file &&
+ git apply patch-0.txt &&
+ test -x file
+'
+
+test_expect_success 'same mode (with index)' '
+ git reset --hard &&
+ chmod +x file &&
+ git add file &&
+ git apply --index patch-0.txt &&
+ test -x file &&
+ git diff --exit-code
+'
+
+test_expect_success 'same mode (index only)' '
+ git reset --hard &&
+ chmod +x file &&
+ git add file &&
+ git apply --cached patch-0.txt &&
+ git ls-files -s file | grep "^100755"
+'
+
+test_expect_success 'mode update (no index)' '
+ git reset --hard &&
+ git apply patch-1.txt &&
+ test -x file
+'
+
+test_expect_success 'mode update (with index)' '
+ git reset --hard &&
+ git apply --index patch-1.txt &&
+ test -x file &&
+ git diff --exit-code
+'
+
+test_expect_success 'mode update (index only)' '
+ git reset --hard &&
+ git apply --cached patch-1.txt &&
+ git ls-files -s file | grep "^100755"
+'
+
+test_done
diff --git a/t/t4252-am-options.sh b/t/t4252-am-options.sh
new file mode 100755
index 0000000000..3ab9e8e6e3
--- /dev/null
+++ b/t/t4252-am-options.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+test_description='git am not losing options'
+. ./test-lib.sh
+
+tm="$TEST_DIRECTORY/t4252"
+
+test_expect_success setup '
+ cp "$tm/file-1-0" file-1 &&
+ cp "$tm/file-2-0" file-2 &&
+ git add file-1 file-2 &&
+ test_tick &&
+ git commit -m initial &&
+ git tag initial
+'
+
+test_expect_success 'interrupted am --whitespace=fix' '
+ rm -rf .git/rebase-apply &&
+ git reset --hard initial &&
+ test_must_fail git am --whitespace=fix "$tm"/am-test-1-? &&
+ git am --skip &&
+ grep 3 file-1 &&
+ grep "^Six$" file-2
+'
+
+test_expect_success 'interrupted am -C1' '
+ rm -rf .git/rebase-apply &&
+ git reset --hard initial &&
+ test_must_fail git am -C1 "$tm"/am-test-2-? &&
+ git am --skip &&
+ grep 3 file-1 &&
+ grep "^Three$" file-2
+'
+
+test_expect_success 'interrupted am -p2' '
+ rm -rf .git/rebase-apply &&
+ git reset --hard initial &&
+ test_must_fail git am -p2 "$tm"/am-test-3-? &&
+ git am --skip &&
+ grep 3 file-1 &&
+ grep "^Three$" file-2
+'
+
+test_expect_success 'interrupted am -C1 -p2' '
+ rm -rf .git/rebase-apply &&
+ git reset --hard initial &&
+ test_must_fail git am -p2 -C1 "$tm"/am-test-4-? &&
+ git am --skip &&
+ grep 3 file-1 &&
+ grep "^Three$" file-2
+'
+
+test_done
diff --git a/t/t4252/am-test-1-1 b/t/t4252/am-test-1-1
new file mode 100644
index 0000000000..b0c09dc965
--- /dev/null
+++ b/t/t4252/am-test-1-1
@@ -0,0 +1,19 @@
+From: A U Thor <au.thor@example.com>
+Date: Thu Dec 4 16:00:00 2008 -0800
+Subject: Three
+
+Application of this should be rejected because the first line in the
+context does not match.
+
+diff --git i/file-1 w/file-1
+index 06e567b..10f8342 100644
+--- i/file-1
++++ w/file-1
+@@ -1,6 +1,6 @@
+ One
+ 2
+-3
++Three
+ 4
+ 5
+ 6
diff --git a/t/t4252/am-test-1-2 b/t/t4252/am-test-1-2
new file mode 100644
index 0000000000..1b874ae115
--- /dev/null
+++ b/t/t4252/am-test-1-2
@@ -0,0 +1,21 @@
+From: A U Thor <au.thor@example.com>
+Date: Thu Dec 4 16:00:00 2008 -0800
+Subject: Six
+
+Applying this patch with --whitespace=fix should lose
+the trailing whitespace after "Six".
+
+diff --git i/file-2 w/file-2
+index 06e567b..b6f3a16 100644
+--- i/file-2
++++ w/file-2
+@@ -1,7 +1,7 @@
+ 1
+ 2
+-3
++Three
+ 4
+ 5
+-6
++Six
+ 7
diff --git a/t/t4252/am-test-2-1 b/t/t4252/am-test-2-1
new file mode 100644
index 0000000000..feda94a0cc
--- /dev/null
+++ b/t/t4252/am-test-2-1
@@ -0,0 +1,19 @@
+From: A U Thor <au.thor@example.com>
+Date: Thu Dec 4 16:00:00 2008 -0800
+Subject: Three
+
+Application of this should be rejected even with -C1 because the
+preimage line in the context does not match.
+
+diff --git i/file-1 w/file-1
+index 06e567b..10f8342 100644
+--- i/file-1
++++ w/file-1
+@@ -1,6 +1,6 @@
+ 1
+ 2
+-Tres
++Three
+ 4
+ 5
+ 6
diff --git a/t/t4252/am-test-2-2 b/t/t4252/am-test-2-2
new file mode 100644
index 0000000000..2ac6600976
--- /dev/null
+++ b/t/t4252/am-test-2-2
@@ -0,0 +1,21 @@
+From: A U Thor <au.thor@example.com>
+Date: Thu Dec 4 16:00:00 2008 -0800
+Subject: Six
+
+Applying this patch with -C1 should be successful even though
+the first line in the context does not match.
+
+diff --git i/file-2 w/file-2
+index 06e567b..b6f3a16 100644
+--- i/file-2
++++ w/file-2
+@@ -1,7 +1,7 @@
+ One
+ 2
+-3
++Three
+ 4
+ 5
+-6
++Six
+ 7
diff --git a/t/t4252/am-test-3-1 b/t/t4252/am-test-3-1
new file mode 100644
index 0000000000..608e5abba4
--- /dev/null
+++ b/t/t4252/am-test-3-1
@@ -0,0 +1,19 @@
+From: A U Thor <au.thor@example.com>
+Date: Thu Dec 4 16:00:00 2008 -0800
+Subject: Three
+
+Application of this should be rejected even with -p2 because the
+preimage line in the context does not match.
+
+diff --git i/junk/file-1 w/junk/file-1
+index 06e567b..10f8342 100644
+--- i/junk/file-1
++++ w/junk/file-1
+@@ -1,6 +1,6 @@
+ 1
+ 2
+-Tres
++Three
+ 4
+ 5
+ 6
diff --git a/t/t4252/am-test-3-2 b/t/t4252/am-test-3-2
new file mode 100644
index 0000000000..0081b96f2a
--- /dev/null
+++ b/t/t4252/am-test-3-2
@@ -0,0 +1,21 @@
+From: A U Thor <au.thor@example.com>
+Date: Thu Dec 4 16:00:00 2008 -0800
+Subject: Six
+
+Applying this patch with -p2 should be successful even though
+the patch is against a wrong level.
+
+diff --git i/junk/file-2 w/junk/file-2
+index 06e567b..b6f3a16 100644
+--- i/junk/file-2
++++ w/junk/file-2
+@@ -1,7 +1,7 @@
+ 1
+ 2
+-3
++Three
+ 4
+ 5
+-6
++Six
+ 7
diff --git a/t/t4252/am-test-4-1 b/t/t4252/am-test-4-1
new file mode 100644
index 0000000000..e48cd6cbde
--- /dev/null
+++ b/t/t4252/am-test-4-1
@@ -0,0 +1,19 @@
+From: A U Thor <au.thor@example.com>
+Date: Thu Dec 4 16:00:00 2008 -0800
+Subject: Three
+
+Application of this should be rejected even with -C1 -p2 because
+the preimage line in the context does not match.
+
+diff --git i/junk/file-1 w/junk/file-1
+index 06e567b..10f8342 100644
+--- i/junk/file-1
++++ w/junk/file-1
+@@ -1,6 +1,6 @@
+ 1
+ 2
+-Tres
++Three
+ 4
+ 5
+ 6
diff --git a/t/t4252/am-test-4-2 b/t/t4252/am-test-4-2
new file mode 100644
index 0000000000..0e69bfa55b
--- /dev/null
+++ b/t/t4252/am-test-4-2
@@ -0,0 +1,22 @@
+From: A U Thor <au.thor@example.com>
+Date: Thu Dec 4 16:00:00 2008 -0800
+Subject: Six
+
+Applying this patch with -C1 -p2 should be successful even though
+the patch is against a wrong level and the first context line does
+not match.
+
+diff --git i/junk/file-2 w/junk/file-2
+index 06e567b..b6f3a16 100644
+--- i/junk/file-2
++++ w/junk/file-2
+@@ -1,7 +1,7 @@
+ One
+ 2
+-3
++Three
+ 4
+ 5
+-6
++Six
+ 7
diff --git a/t/t4252/file-1-0 b/t/t4252/file-1-0
new file mode 100644
index 0000000000..06e567b11d
--- /dev/null
+++ b/t/t4252/file-1-0
@@ -0,0 +1,7 @@
+1
+2
+3
+4
+5
+6
+7
diff --git a/t/t4252/file-2-0 b/t/t4252/file-2-0
new file mode 100644
index 0000000000..06e567b11d
--- /dev/null
+++ b/t/t4252/file-2-0
@@ -0,0 +1,7 @@
+1
+2
+3
+4
+5
+6
+7
diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh
index e395ff4e34..c942c8be85 100755
--- a/t/t5000-tar-tree.sh
+++ b/t/t5000-tar-tree.sh
@@ -58,6 +58,11 @@ test_expect_success \
git commit-tree $treeid </dev/null)'
test_expect_success \
+ 'create bare clone' \
+ 'git clone --bare . bare.git &&
+ cp .gitattributes bare.git/info/attributes'
+
+test_expect_success \
'remove ignored file' \
'rm a/ignored'
@@ -74,10 +79,18 @@ test_expect_success \
'diff b.tar b2.tar'
test_expect_success \
+ 'git archive in a bare repo' \
+ '(cd bare.git && git archive HEAD) >b3.tar'
+
+test_expect_success \
+ 'git archive vs. the same in a bare repo' \
+ 'test_cmp b.tar b3.tar'
+
+test_expect_success \
'validate file modification time' \
'mkdir extract &&
"$TAR" xf b.tar -C extract a/a &&
- perl -e '\''print((stat("extract/a/a"))[9], "\n")'\'' >b.mtime &&
+ test-chmtime -v +0 extract/a/a |cut -f 1 >b.mtime &&
echo "1117231200" >expected.mtime &&
diff expected.mtime b.mtime'
@@ -151,6 +164,14 @@ test_expect_success \
'git archive --format=zip' \
'git archive --format=zip HEAD >d.zip'
+test_expect_success \
+ 'git archive --format=zip in a bare repo' \
+ '(cd bare.git && git archive --format=zip HEAD) >d1.zip'
+
+test_expect_success \
+ 'git archive --format=zip vs. the same in a bare repo' \
+ 'test_cmp d.zip d1.zip'
+
$UNZIP -v >/dev/null 2>&1
if [ $? -eq 127 ]; then
echo "Skipping ZIP tests, because unzip was not found"
diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh
index b335c6b42d..04522857ab 100755
--- a/t/t5300-pack-object.sh
+++ b/t/t5300-pack-object.sh
@@ -376,4 +376,10 @@ test_expect_success 'index-pack with --strict' '
)
'
+test_expect_success 'tolerate absurdly small packsizelimit' '
+ git config pack.packSizeLimit 2 &&
+ packname_9=$(git pack-objects test-9 <obj-list) &&
+ test $(wc -l <obj-list) = $(ls test-9-*.pack | wc -l)
+'
+
test_done
diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh
index 6424db1f28..e6f70d474f 100755
--- a/t/t5302-pack-index.sh
+++ b/t/t5302-pack-index.sh
@@ -10,14 +10,20 @@ test_expect_success \
'setup' \
'rm -rf .git
git init &&
+ git config pack.threads 1 &&
i=1 &&
- while test $i -le 100
+ while test $i -le 100
do
- i=`printf '%03i' $i`
- echo $i >file_$i &&
- test-genrandom "$i" 8192 >>file_$i &&
- git update-index --add file_$i &&
- i=`expr $i + 1` || return 1
+ iii=`printf '%03i' $i`
+ test-genrandom "bar" 200 > wide_delta_$iii &&
+ test-genrandom "baz $iii" 50 >> wide_delta_$iii &&
+ test-genrandom "foo"$i 100 > deep_delta_$iii &&
+ test-genrandom "foo"`expr $i + 1` 100 >> deep_delta_$iii &&
+ test-genrandom "foo"`expr $i + 2` 100 >> deep_delta_$iii &&
+ echo $iii >file_$iii &&
+ test-genrandom "$iii" 8192 >>file_$iii &&
+ git update-index --add file_$iii deep_delta_$iii wide_delta_$iii &&
+ i=`expr $i + 1` || return 1
done &&
{ echo 101 && test-genrandom 100 8192; } >file_101 &&
git update-index --add file_101 &&
@@ -92,6 +98,31 @@ test_expect_success \
'64-bit offsets: index-pack result should match pack-objects one' \
'cmp "test-3-${pack3}.idx" "3.idx"'
+# returns the object number for given object in given pack index
+index_obj_nr()
+{
+ idx_file=$1
+ object_sha1=$2
+ nr=0
+ git show-index < $idx_file |
+ while read offs sha1 extra
+ do
+ nr=$(($nr + 1))
+ test "$sha1" = "$object_sha1" || continue
+ echo "$(($nr - 1))"
+ break
+ done
+}
+
+# returns the pack offset for given object as found in given pack index
+index_obj_offset()
+{
+ idx_file=$1
+ object_sha1=$2
+ git show-index < $idx_file | grep $object_sha1 |
+ ( read offs extra && echo "$offs" )
+}
+
test_expect_success \
'[index v1] 1) stream pack to repository' \
'git index-pack --index-version=1 --stdin < "test-1-${pack1}.pack" &&
@@ -102,19 +133,22 @@ test_expect_success \
test_expect_success \
'[index v1] 2) create a stealth corruption in a delta base reference' \
- '# this test assumes a delta smaller than 16 bytes at the end of the pack
- git show-index <1.idx | sort -n | sed -ne \$p | (
- read delta_offs delta_sha1 &&
- git cat-file blob "$delta_sha1" > blob_1 &&
- chmod +w ".git/objects/pack/pack-${pack1}.pack" &&
- dd of=".git/objects/pack/pack-${pack1}.pack" seek=$(($delta_offs + 1)) \
- if=".git/objects/pack/pack-${pack1}.idx" skip=$((256 * 4 + 4)) \
- bs=1 count=20 conv=notrunc &&
- git cat-file blob "$delta_sha1" > blob_2 )'
+ '# This test assumes file_101 is a delta smaller than 16 bytes.
+ # It should be against file_100 but we substitute its base for file_099
+ sha1_101=`git hash-object file_101` &&
+ sha1_099=`git hash-object file_099` &&
+ offs_101=`index_obj_offset 1.idx $sha1_101` &&
+ nr_099=`index_obj_nr 1.idx $sha1_099` &&
+ chmod +w ".git/objects/pack/pack-${pack1}.pack" &&
+ dd of=".git/objects/pack/pack-${pack1}.pack" seek=$(($offs_101 + 1)) \
+ if=".git/objects/pack/pack-${pack1}.idx" \
+ skip=$((4 + 256 * 4 + $nr_099 * 24)) \
+ bs=1 count=20 conv=notrunc &&
+ git cat-file blob $sha1_101 > file_101_foo1'
test_expect_success \
'[index v1] 3) corrupted delta happily returned wrong data' \
- '! cmp blob_1 blob_2'
+ 'test -f file_101_foo1 && ! cmp file_101 file_101_foo1'
test_expect_success \
'[index v1] 4) confirm that the pack is actually corrupted' \
@@ -140,19 +174,22 @@ test_expect_success \
test_expect_success \
'[index v2] 2) create a stealth corruption in a delta base reference' \
- '# this test assumes a delta smaller than 16 bytes at the end of the pack
- git show-index <1.idx | sort -n | sed -ne \$p | (
- read delta_offs delta_sha1 delta_crc &&
- git cat-file blob "$delta_sha1" > blob_3 &&
- chmod +w ".git/objects/pack/pack-${pack1}.pack" &&
- dd of=".git/objects/pack/pack-${pack1}.pack" seek=$(($delta_offs + 1)) \
- if=".git/objects/pack/pack-${pack1}.idx" skip=$((8 + 256 * 4)) \
- bs=1 count=20 conv=notrunc &&
- git cat-file blob "$delta_sha1" > blob_4 )'
+ '# This test assumes file_101 is a delta smaller than 16 bytes.
+ # It should be against file_100 but we substitute its base for file_099
+ sha1_101=`git hash-object file_101` &&
+ sha1_099=`git hash-object file_099` &&
+ offs_101=`index_obj_offset 1.idx $sha1_101` &&
+ nr_099=`index_obj_nr 1.idx $sha1_099` &&
+ chmod +w ".git/objects/pack/pack-${pack1}.pack" &&
+ dd of=".git/objects/pack/pack-${pack1}.pack" seek=$(($offs_101 + 1)) \
+ if=".git/objects/pack/pack-${pack1}.idx" \
+ skip=$((8 + 256 * 4 + $nr_099 * 20)) \
+ bs=1 count=20 conv=notrunc &&
+ git cat-file blob $sha1_101 > file_101_foo2'
test_expect_success \
'[index v2] 3) corrupted delta happily returned wrong data' \
- '! cmp blob_3 blob_4'
+ 'test -f file_101_foo2 && ! cmp file_101 file_101_foo2'
test_expect_success \
'[index v2] 4) confirm that the pack is actually corrupted' \
@@ -160,16 +197,19 @@ test_expect_success \
test_expect_success \
'[index v2] 5) pack-objects refuses to reuse corrupted data' \
- 'test_must_fail git pack-objects test-5 <obj-list'
+ 'test_must_fail git pack-objects test-5 <obj-list &&
+ test_must_fail git pack-objects --no-reuse-object test-6 <obj-list'
test_expect_success \
'[index v2] 6) verify-pack detects CRC mismatch' \
'rm -f .git/objects/pack/* &&
git index-pack --index-version=2 --stdin < "test-1-${pack1}.pack" &&
git verify-pack ".git/objects/pack/pack-${pack1}.pack" &&
+ obj=`git hash-object file_001` &&
+ nr=`index_obj_nr ".git/objects/pack/pack-${pack1}.idx" $obj` &&
chmod +w ".git/objects/pack/pack-${pack1}.idx" &&
dd if=/dev/zero of=".git/objects/pack/pack-${pack1}.idx" conv=notrunc \
- bs=1 count=4 seek=$((8 + 256 * 4 + `wc -l <obj-list` * 20 + 0)) &&
+ bs=1 count=4 seek=$((8 + 256 * 4 + `wc -l <obj-list` * 20 + $nr * 4)) &&
( while read obj
do git cat-file -p $obj >/dev/null || exit 1
done <obj-list ) &&
@@ -177,4 +217,14 @@ test_expect_success \
".git/objects/pack/pack-${pack1}.pack" 2>&1) &&
echo "$err" | grep "CRC mismatch"'
+test_expect_success 'running index-pack in the object store' '
+ rm -f .git/objects/pack/* &&
+ cp test-1-${pack1}.pack .git/objects/pack/pack-${pack1}.pack &&
+ (
+ cd .git/objects/pack
+ git index-pack pack-${pack1}.pack
+ ) &&
+ test -f .git/objects/pack/pack-${pack1}.idx
+'
+
test_done
diff --git a/t/t5303-pack-corruption-resilience.sh b/t/t5303-pack-corruption-resilience.sh
index 31b20b21d2..d4e30fc43c 100755
--- a/t/t5303-pack-corruption-resilience.sh
+++ b/t/t5303-pack-corruption-resilience.sh
@@ -41,11 +41,17 @@ create_new_pack() {
git verify-pack -v ${pack}.pack
}
+do_repack() {
+ pack=`printf "$blob_1\n$blob_2\n$blob_3\n" |
+ git pack-objects $@ .git/objects/pack/pack` &&
+ pack=".git/objects/pack/pack-${pack}"
+}
+
do_corrupt_object() {
ofs=`git show-index < ${pack}.idx | grep $1 | cut -f1 -d" "` &&
ofs=$(($ofs + $2)) &&
chmod +w ${pack}.pack &&
- dd if=/dev/zero of=${pack}.pack count=1 bs=1 conv=notrunc seek=$ofs &&
+ dd of=${pack}.pack count=1 bs=1 conv=notrunc seek=$ofs &&
test_must_fail git verify-pack ${pack}.pack
}
@@ -60,7 +66,7 @@ test_expect_success \
test_expect_success \
'create corruption in header of first object' \
- 'do_corrupt_object $blob_1 0 &&
+ 'do_corrupt_object $blob_1 0 < /dev/zero &&
test_must_fail git cat-file blob $blob_1 > /dev/null &&
test_must_fail git cat-file blob $blob_2 > /dev/null &&
test_must_fail git cat-file blob $blob_3 > /dev/null'
@@ -119,7 +125,7 @@ test_expect_success \
'create corruption in header of first delta' \
'create_new_pack &&
git prune-packed &&
- do_corrupt_object $blob_2 0 &&
+ do_corrupt_object $blob_2 0 < /dev/zero &&
git cat-file blob $blob_1 > /dev/null &&
test_must_fail git cat-file blob $blob_2 > /dev/null &&
test_must_fail git cat-file blob $blob_3 > /dev/null'
@@ -134,6 +140,15 @@ test_expect_success \
git cat-file blob $blob_3 > /dev/null'
test_expect_success \
+ '... and then a repack "clears" the corruption' \
+ 'do_repack &&
+ git prune-packed &&
+ git verify-pack ${pack}.pack &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
'create corruption in data of first delta' \
'create_new_pack &&
git prune-packed &&
@@ -153,10 +168,19 @@ test_expect_success \
git cat-file blob $blob_3 > /dev/null'
test_expect_success \
+ '... and then a repack "clears" the corruption' \
+ 'do_repack &&
+ git prune-packed &&
+ git verify-pack ${pack}.pack &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
'corruption in delta base reference of first delta (OBJ_REF_DELTA)' \
'create_new_pack &&
git prune-packed &&
- do_corrupt_object $blob_2 2 &&
+ do_corrupt_object $blob_2 2 < /dev/zero &&
git cat-file blob $blob_1 > /dev/null &&
test_must_fail git cat-file blob $blob_2 > /dev/null &&
test_must_fail git cat-file blob $blob_3 > /dev/null'
@@ -171,17 +195,75 @@ test_expect_success \
git cat-file blob $blob_3 > /dev/null'
test_expect_success \
- 'corruption in delta base reference of first delta (OBJ_OFS_DELTA)' \
+ '... and then a repack "clears" the corruption' \
+ 'do_repack &&
+ git prune-packed &&
+ git verify-pack ${pack}.pack &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ 'corruption #0 in delta base reference of first delta (OBJ_OFS_DELTA)' \
'create_new_pack --delta-base-offset &&
git prune-packed &&
- do_corrupt_object $blob_2 2 &&
+ do_corrupt_object $blob_2 2 < /dev/zero &&
git cat-file blob $blob_1 > /dev/null &&
test_must_fail git cat-file blob $blob_2 > /dev/null &&
test_must_fail git cat-file blob $blob_3 > /dev/null'
test_expect_success \
- '... and a redundant pack allows for full recovery too' \
+ '... but having a loose copy allows for full recovery' \
'mv ${pack}.idx tmp &&
+ git hash-object -t blob -w file_2 &&
+ mv tmp ${pack}.idx &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ '... and then a repack "clears" the corruption' \
+ 'do_repack --delta-base-offset &&
+ git prune-packed &&
+ git verify-pack ${pack}.pack &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ 'corruption #1 in delta base reference of first delta (OBJ_OFS_DELTA)' \
+ 'create_new_pack --delta-base-offset &&
+ git prune-packed &&
+ printf "\001" | do_corrupt_object $blob_2 2 &&
+ git cat-file blob $blob_1 > /dev/null &&
+ test_must_fail git cat-file blob $blob_2 > /dev/null &&
+ test_must_fail git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ '... but having a loose copy allows for full recovery' \
+ 'mv ${pack}.idx tmp &&
+ git hash-object -t blob -w file_2 &&
+ mv tmp ${pack}.idx &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ '... and then a repack "clears" the corruption' \
+ 'do_repack --delta-base-offset &&
+ git prune-packed &&
+ git verify-pack ${pack}.pack &&
+ git cat-file blob $blob_1 > /dev/null &&
+ git cat-file blob $blob_2 > /dev/null &&
+ git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+ '... and a redundant pack allows for full recovery too' \
+ 'do_corrupt_object $blob_2 2 < /dev/zero &&
+ git cat-file blob $blob_1 > /dev/null &&
+ test_must_fail git cat-file blob $blob_2 > /dev/null &&
+ test_must_fail git cat-file blob $blob_3 > /dev/null &&
+ mv ${pack}.idx tmp &&
git hash-object -t blob -w file_1 &&
git hash-object -t blob -w file_2 &&
printf "$blob_1\n$blob_2\n" | git pack-objects .git/objects/pack/pack &&
diff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh
index 544771d8fa..b21317d685 100755
--- a/t/t5400-send-pack.sh
+++ b/t/t5400-send-pack.sh
@@ -99,11 +99,22 @@ test_expect_success \
! test -f victim/.git/refs/heads/extra
'
-unset GIT_CONFIG GIT_CONFIG_LOCAL
+unset GIT_CONFIG
HOME=`pwd`/no-such-directory
export HOME ;# this way we force the victim/.git/config to be used.
test_expect_success \
+ 'pushing a delete should be denied with denyDeletes' '
+ cd victim &&
+ git config receive.denyDeletes true &&
+ git branch extra master &&
+ cd .. &&
+ test -f victim/.git/refs/heads/extra &&
+ test_must_fail git send-pack ./victim/.git/ :extra master
+'
+rm -f victim/.git/refs/heads/extra
+
+test_expect_success \
'pushing with --force should be denied with denyNonFastforwards' '
cd victim &&
git config receive.denyNonFastforwards true &&
diff --git a/t/t5405-send-pack-rewind.sh b/t/t5405-send-pack-rewind.sh
index 86abc62271..cb9aacc7bc 100755
--- a/t/t5405-send-pack-rewind.sh
+++ b/t/t5405-send-pack-rewind.sh
@@ -12,7 +12,7 @@ test_expect_success setup '
mkdir another && (
cd another &&
git init &&
- git fetch .. master:master
+ git fetch --update-head-ok .. master:master
) &&
>file2 && git add file2 && test_tick &&
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index c4496635df..1f59960d90 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -28,7 +28,7 @@ tokens_match () {
}
check_remote_track () {
- actual=$(git remote show "$1" | sed -n -e '$p') &&
+ actual=$(git remote show "$1" | sed -e '1,/Tracked/d') &&
shift &&
tokens_match "$*" "$actual"
}
@@ -115,9 +115,11 @@ cat > test/expect << EOF
New remote branch (next fetch will store in remotes/origin)
master
Tracked remote branches
- side master
+ side
+ master
Local branches pushed with 'git push'
- master:upstream +refs/tags/lastbackup
+ master:upstream
+ +refs/tags/lastbackup
EOF
test_expect_success 'show' '
@@ -144,9 +146,11 @@ cat > test/expect << EOF
Remote branch merged with 'git pull' while on branch master
master
Tracked remote branches
- master side
+ master
+ side
Local branches pushed with 'git push'
- master:upstream +refs/tags/lastbackup
+ master:upstream
+ +refs/tags/lastbackup
EOF
test_expect_success 'show -n' '
@@ -188,7 +192,7 @@ test_expect_success 'prune --dry-run' '
test_expect_success 'add --mirror && prune' '
(mkdir mirror &&
cd mirror &&
- git init &&
+ git init --bare &&
git remote add --mirror -f origin ../one) &&
(cd one &&
git branch -m side2 side) &&
@@ -324,4 +328,52 @@ test_expect_success 'reject adding remote with an invalid name' '
'
+# The first three test if the tracking branches are properly renamed,
+# the last two ones check if the config is updated.
+
+test_expect_success 'rename a remote' '
+
+ git clone one four &&
+ (cd four &&
+ git remote rename origin upstream &&
+ rmdir .git/refs/remotes/origin &&
+ test "$(git symbolic-ref refs/remotes/upstream/HEAD)" = "refs/remotes/upstream/master" &&
+ test "$(git rev-parse upstream/master)" = "$(git rev-parse master)" &&
+ test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/remotes/upstream/*" &&
+ test "$(git config branch.master.remote)" = "upstream")
+
+'
+
+cat > remotes_origin << EOF
+URL: $(pwd)/one
+Push: refs/heads/master:refs/heads/upstream
+Pull: refs/heads/master:refs/heads/origin
+EOF
+
+test_expect_success 'migrate a remote from named file in $GIT_DIR/remotes' '
+ git clone one five &&
+ origin_url=$(pwd)/one &&
+ (cd five &&
+ git remote rm origin &&
+ mkdir -p .git/remotes &&
+ cat ../remotes_origin > .git/remotes/origin &&
+ git remote rename origin origin &&
+ ! test -f .git/remotes/origin &&
+ test "$(git config remote.origin.url)" = "$origin_url" &&
+ test "$(git config remote.origin.push)" = "refs/heads/master:refs/heads/upstream" &&
+ test "$(git config remote.origin.fetch)" = "refs/heads/master:refs/heads/origin")
+'
+
+test_expect_success 'migrate a remote from named file in $GIT_DIR/branches' '
+ git clone one six &&
+ origin_url=$(pwd)/one &&
+ (cd six &&
+ git remote rm origin &&
+ echo "$origin_url" > .git/branches/origin &&
+ git remote rename origin origin &&
+ ! test -f .git/branches/origin &&
+ test "$(git config remote.origin.url)" = "$origin_url" &&
+ test "$(git config remote.origin.fetch)" = "refs/heads/master:refs/heads/origin")
+'
+
test_done
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index 9aae4965da..9e679b402d 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -323,4 +323,16 @@ test_expect_success 'auto tag following fetches minimum' '
)
'
+test_expect_success 'refuse to fetch into the current branch' '
+
+ test_must_fail git fetch . side:master
+
+'
+
+test_expect_success 'fetch into the current branch with --update-head-ok' '
+
+ git fetch --update-head-ok . side:master
+
+'
+
test_done
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index f0030ad00e..4426df9226 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -39,6 +39,11 @@ mk_test () {
)
}
+mk_child() {
+ rm -rf "$1" &&
+ git clone testrepo "$1"
+}
+
check_push_result () {
(
cd testrepo &&
@@ -425,29 +430,47 @@ test_expect_success 'push with dry-run' '
test_expect_success 'push updates local refs' '
- rm -rf parent child &&
- mkdir parent &&
- (cd parent && git init &&
- echo one >foo && git add foo && git commit -m one) &&
- git clone parent child &&
+ mk_test heads/master &&
+ mk_child child &&
(cd child &&
- echo two >foo && git commit -a -m two &&
+ git pull .. master &&
+ git push &&
+ test $(git rev-parse master) = $(git rev-parse remotes/origin/master))
+
+'
+
+test_expect_success 'push updates up-to-date local refs' '
+
+ mk_test heads/master &&
+ mk_child child1 &&
+ mk_child child2 &&
+ (cd child1 && git pull .. master && git push) &&
+ (cd child2 &&
+ git pull ../child1 master &&
git push &&
test $(git rev-parse master) = $(git rev-parse remotes/origin/master))
'
+test_expect_success 'push preserves up-to-date packed refs' '
+
+ mk_test heads/master &&
+ mk_child child &&
+ (cd child &&
+ git push &&
+ ! test -f .git/refs/remotes/origin/master)
+
+'
+
test_expect_success 'push does not update local refs on failure' '
- rm -rf parent child &&
- mkdir parent &&
- (cd parent && git init &&
- echo one >foo && git add foo && git commit -m one &&
- echo exit 1 >.git/hooks/pre-receive &&
- chmod +x .git/hooks/pre-receive) &&
- git clone parent child &&
+ mk_test heads/master &&
+ mk_child child &&
+ mkdir testrepo/.git/hooks &&
+ echo exit 1 >testrepo/.git/hooks/pre-receive &&
+ chmod +x testrepo/.git/hooks/pre-receive &&
(cd child &&
- echo two >foo && git commit -a -m two &&
+ git pull .. master
test_must_fail git push &&
test $(git rev-parse master) != \
$(git rev-parse remotes/origin/master))
@@ -456,11 +479,98 @@ test_expect_success 'push does not update local refs on failure' '
test_expect_success 'allow deleting an invalid remote ref' '
- pwd &&
+ mk_test heads/master &&
rm -f testrepo/.git/objects/??/* &&
git push testrepo :refs/heads/master &&
(cd testrepo && test_must_fail git rev-parse --verify refs/heads/master)
'
+test_expect_success 'warn on push to HEAD of non-bare repository' '
+ mk_test heads/master
+ (cd testrepo &&
+ git checkout master &&
+ git config receive.denyCurrentBranch warn) &&
+ git push testrepo master 2>stderr &&
+ grep "warning.*this may cause confusion" stderr
+'
+
+test_expect_success 'deny push to HEAD of non-bare repository' '
+ mk_test heads/master
+ (cd testrepo &&
+ git checkout master &&
+ git config receive.denyCurrentBranch true) &&
+ test_must_fail git push testrepo master
+'
+
+test_expect_success 'allow push to HEAD of bare repository (bare)' '
+ mk_test heads/master
+ (cd testrepo &&
+ git checkout master &&
+ git config receive.denyCurrentBranch true &&
+ git config core.bare true) &&
+ git push testrepo master 2>stderr &&
+ ! grep "warning.*this may cause confusion" stderr
+'
+
+test_expect_success 'allow push to HEAD of non-bare repository (config)' '
+ mk_test heads/master
+ (cd testrepo &&
+ git checkout master &&
+ git config receive.denyCurrentBranch false
+ ) &&
+ git push testrepo master 2>stderr &&
+ ! grep "warning.*this may cause confusion" stderr
+'
+
+test_expect_success 'fetch with branches' '
+ mk_empty &&
+ git branch second $the_first_commit &&
+ git checkout second &&
+ echo ".." > testrepo/.git/branches/branch1 &&
+ (cd testrepo &&
+ git fetch branch1 &&
+ r=$(git show-ref -s --verify refs/heads/branch1) &&
+ test "z$r" = "z$the_commit" &&
+ test 1 = $(git for-each-ref refs/heads | wc -l)
+ ) &&
+ git checkout master
+'
+
+test_expect_success 'fetch with branches containing #' '
+ mk_empty &&
+ echo "..#second" > testrepo/.git/branches/branch2 &&
+ (cd testrepo &&
+ git fetch branch2 &&
+ r=$(git show-ref -s --verify refs/heads/branch2) &&
+ test "z$r" = "z$the_first_commit" &&
+ test 1 = $(git for-each-ref refs/heads | wc -l)
+ ) &&
+ git checkout master
+'
+
+test_expect_success 'push with branches' '
+ mk_empty &&
+ git checkout second &&
+ echo "testrepo" > .git/branches/branch1 &&
+ git push branch1 &&
+ (cd testrepo &&
+ r=$(git show-ref -s --verify refs/heads/master) &&
+ test "z$r" = "z$the_first_commit" &&
+ test 1 = $(git for-each-ref refs/heads | wc -l)
+ )
+'
+
+test_expect_success 'push with branches containing #' '
+ mk_empty &&
+ echo "testrepo#branch3" > .git/branches/branch2 &&
+ git push branch2 &&
+ (cd testrepo &&
+ r=$(git show-ref -s --verify refs/heads/branch3) &&
+ test "z$r" = "z$the_first_commit" &&
+ test 1 = $(git for-each-ref refs/heads | wc -l)
+ ) &&
+ git checkout master
+'
+
test_done
diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh
index 997b2db827..725771fac1 100755
--- a/t/t5520-pull.sh
+++ b/t/t5520-pull.sh
@@ -29,6 +29,18 @@ test_expect_success 'checking the results' '
diff file cloned/file
'
+test_expect_success 'pulling into void using master:master' '
+ mkdir cloned-uho &&
+ (
+ cd cloned-uho &&
+ git init &&
+ git pull .. master:master
+ ) &&
+ test -f file &&
+ test -f cloned-uho/file &&
+ test_cmp file cloned-uho/file
+'
+
test_expect_success 'test . as a remote' '
git branch copy master &&
diff --git a/t/t5521-pull-options.sh b/t/t5521-pull-options.sh
new file mode 100755
index 0000000000..83e2e8ab80
--- /dev/null
+++ b/t/t5521-pull-options.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+test_description='pull options'
+
+. ./test-lib.sh
+
+D=`pwd`
+
+test_expect_success 'setup' '
+ mkdir parent &&
+ (cd parent && git init &&
+ echo one >file && git add file &&
+ git commit -m one)
+'
+
+cd "$D"
+
+test_expect_success 'git pull -q' '
+ mkdir clonedq &&
+ cd clonedq &&
+ git pull -q "$D/parent" >out 2>err &&
+ test ! -s out
+'
+
+cd "$D"
+
+test_expect_success 'git pull' '
+ mkdir cloned &&
+ cd cloned &&
+ git pull "$D/parent" >out 2>err &&
+ test -s out
+'
+cd "$D"
+
+test_expect_success 'git pull -v' '
+ mkdir clonedv &&
+ cd clonedv &&
+ git pull -v "$D/parent" >out 2>err &&
+ test -s out
+'
+
+cd "$D"
+
+test_expect_success 'git pull -v -q' '
+ mkdir clonedvq &&
+ cd clonedvq &&
+ git pull -v -q "$D/parent" >out 2>err &&
+ test ! -s out
+'
+
+cd "$D"
+
+test_expect_success 'git pull -q -v' '
+ mkdir clonedqv &&
+ cd clonedqv &&
+ git pull -q -v "$D/parent" >out 2>err &&
+ test -s out
+'
+
+test_done
diff --git a/t/t5521-pull-symlink.sh b/t/t5521-pull-symlink.sh
new file mode 100755
index 0000000000..5672b51e2e
--- /dev/null
+++ b/t/t5521-pull-symlink.sh
@@ -0,0 +1,78 @@
+#!/bin/sh
+
+test_description='pulling from symlinked subdir'
+
+. ./test-lib.sh
+
+# The scenario we are building:
+#
+# trash\ directory/
+# clone-repo/
+# subdir/
+# bar
+# subdir-link -> clone-repo/subdir/
+#
+# The working directory is subdir-link.
+
+mkdir subdir
+echo file >subdir/file
+git add subdir/file
+git commit -q -m file
+git clone -q . clone-repo
+ln -s clone-repo/subdir/ subdir-link
+
+
+# Demonstrate that things work if we just avoid the symlink
+#
+test_expect_success 'pulling from real subdir' '
+ (
+ echo real >subdir/file &&
+ git commit -m real subdir/file &&
+ cd clone-repo/subdir/ &&
+ git pull &&
+ test real = $(cat file)
+ )
+'
+
+# From subdir-link, pulling should work as it does from
+# clone-repo/subdir/.
+#
+# Instead, the error pull gave was:
+#
+# fatal: 'origin': unable to chdir or not a git archive
+# fatal: The remote end hung up unexpectedly
+#
+# because git would find the .git/config for the "trash directory"
+# repo, not for the clone-repo repo. The "trash directory" repo
+# had no entry for origin. Git found the wrong .git because
+# git rev-parse --show-cdup printed a path relative to
+# clone-repo/subdir/, not subdir-link/. Git rev-parse --show-cdup
+# used the correct .git, but when the git pull shell script did
+# "cd `git rev-parse --show-cdup`", it ended up in the wrong
+# directory. A POSIX shell's "cd" works a little differently
+# than chdir() in C; "cd -P" is much closer to chdir().
+#
+test_expect_success 'pulling from symlinked subdir' '
+ (
+ echo link >subdir/file &&
+ git commit -m link subdir/file &&
+ cd subdir-link/ &&
+ git pull &&
+ test link = $(cat file)
+ )
+'
+
+# Prove that the remote end really is a repo, and other commands
+# work fine in this context. It's just that "git pull" breaks.
+#
+test_expect_success 'pushing from symlinked subdir' '
+ (
+ cd subdir-link/ &&
+ echo push >file &&
+ git commit -m push ./file &&
+ git push
+ ) &&
+ test push = $(git show HEAD:subdir/file)
+'
+
+test_done
diff --git a/t/t5540-http-push.sh b/t/t5540-http-push.sh
index da9588645c..c236b5e83b 100755
--- a/t/t5540-http-push.sh
+++ b/t/t5540-http-push.sh
@@ -51,17 +51,29 @@ test_expect_success 'clone remote repository' '
git clone $HTTPD_URL/test_repo.git test_repo_clone
'
-test_expect_failure 'push to remote repository' '
+test_expect_failure 'push to remote repository with packed refs' '
cd "$ROOT_PATH"/test_repo_clone &&
: >path2 &&
git add path2 &&
test_tick &&
git commit -m path2 &&
+ HEAD=$(git rev-parse --verify HEAD) &&
git push &&
- [ -f "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/refs/heads/master" ]
+ (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
+ test $HEAD = $(git rev-parse --verify HEAD))
'
-test_expect_failure 'create and delete remote branch' '
+test_expect_success ' push to remote repository with unpacked refs' '
+ (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
+ rm packed-refs &&
+ git update-ref refs/heads/master \
+ 0c973ae9bd51902a28466f3850b543fa66a6aaf4) &&
+ git push &&
+ (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
+ test $HEAD = $(git rev-parse --verify HEAD))
+'
+
+test_expect_success 'create and delete remote branch' '
cd "$ROOT_PATH"/test_repo_clone &&
git checkout -b dev &&
: >path3 &&
@@ -76,6 +88,12 @@ test_expect_failure 'create and delete remote branch' '
test_must_fail git show-ref --verify refs/remotes/origin/dev
'
+test_expect_success 'MKCOL sends directory names with trailing slashes' '
+
+ ! grep "\"MKCOL.*[^/] HTTP/[^ ]*\"" < "$HTTPD_ROOT_PATH"/access.log
+
+'
+
stop_httpd
test_done
diff --git a/t/t5702-clone-options.sh b/t/t5702-clone-options.sh
index 328e4d9a33..27825f5f31 100755
--- a/t/t5702-clone-options.sh
+++ b/t/t5702-clone-options.sh
@@ -19,4 +19,17 @@ test_expect_success 'clone -o' '
'
+test_expect_success 'redirected clone' '
+
+ git clone "file://$(pwd)/parent" clone-redirected >out 2>err &&
+ test ! -s err
+
+'
+test_expect_success 'redirected clone -v' '
+
+ git clone -v "file://$(pwd)/parent" clone-redirected-v >out 2>err &&
+ test -s err
+
+'
+
test_done
diff --git a/t/t5704-bundle.sh b/t/t5704-bundle.sh
new file mode 100755
index 0000000000..a8f4419e61
--- /dev/null
+++ b/t/t5704-bundle.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+test_description='some bundle related tests'
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+
+ : > file &&
+ git add file &&
+ test_tick &&
+ git commit -m initial &&
+ test_tick &&
+ git tag -m tag tag &&
+ : > file2 &&
+ git add file2 &&
+ : > file3 &&
+ test_tick &&
+ git commit -m second &&
+ git add file3 &&
+ test_tick &&
+ git commit -m third
+
+'
+
+test_expect_success 'tags can be excluded by rev-list options' '
+
+ git bundle create bundle --all --since=7.Apr.2005.15:16:00.-0700 &&
+ git ls-remote bundle > output &&
+ ! grep tag output
+
+'
+
+test_done
diff --git a/t/t6024-recursive-merge.sh b/t/t6024-recursive-merge.sh
index 802d0d06eb..129fa3000c 100755
--- a/t/t6024-recursive-merge.sh
+++ b/t/t6024-recursive-merge.sh
@@ -97,4 +97,27 @@ test_expect_success 'refuse to merge binary files' '
merge.err
'
+test_expect_success 'mark rename/delete as unmerged' '
+
+ git reset --hard &&
+ git checkout -b delete &&
+ git rm a1 &&
+ test_tick &&
+ git commit -m delete &&
+ git checkout -b rename HEAD^ &&
+ git mv a1 a2
+ test_tick &&
+ git commit -m rename &&
+ test_must_fail git merge delete &&
+ test 1 = $(git ls-files --unmerged | wc -l) &&
+ git rev-parse --verify :2:a2 &&
+ test_must_fail git rev-parse --verify :3:a2 &&
+ git checkout -f delete &&
+ test_must_fail git merge rename &&
+ test 1 = $(git ls-files --unmerged | wc -l) &&
+ test_must_fail git rev-parse --verify :2:a2 &&
+ git rev-parse --verify :3:a2
+
+'
+
test_done
diff --git a/t/t6025-merge-symlinks.sh b/t/t6025-merge-symlinks.sh
index 53892a555c..433c4de08f 100755
--- a/t/t6025-merge-symlinks.sh
+++ b/t/t6025-merge-symlinks.sh
@@ -18,11 +18,11 @@ git add file &&
git commit -m initial &&
git branch b-symlink &&
git branch b-file &&
-l=$(echo -n file | git hash-object -t blob -w --stdin) &&
+l=$(printf file | git hash-object -t blob -w --stdin) &&
echo "120000 $l symlink" | git update-index --index-info &&
git commit -m master &&
git checkout b-symlink &&
-l=$(echo -n file-different | git hash-object -t blob -w --stdin) &&
+l=$(printf file-different | git hash-object -t blob -w --stdin) &&
echo "120000 $l symlink" | git update-index --index-info &&
git commit -m b-symlink &&
git checkout b-file &&
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index 85fa39cf0b..dd7eac84ea 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh
@@ -313,8 +313,25 @@ test_expect_success 'bisect run & skip: find first bad' '
grep "$HASH6 is first bad commit" my_bisect_log.txt
'
-test_expect_success 'bisect starting with a detached HEAD' '
+test_expect_success 'bisect skip only one range' '
+ git bisect reset &&
+ git bisect start $HASH7 $HASH1 &&
+ git bisect skip $HASH1..$HASH5 &&
+ test "$HASH6" = "$(git rev-parse --verify HEAD)" &&
+ test_must_fail git bisect bad > my_bisect_log.txt &&
+ grep "first bad commit could be any of" my_bisect_log.txt
+'
+test_expect_success 'bisect skip many ranges' '
+ git bisect start $HASH7 $HASH1 &&
+ test "$HASH4" = "$(git rev-parse --verify HEAD)" &&
+ git bisect skip $HASH2 $HASH2.. ..$HASH5 &&
+ test "$HASH6" = "$(git rev-parse --verify HEAD)" &&
+ test_must_fail git bisect bad > my_bisect_log.txt &&
+ grep "first bad commit could be any of" my_bisect_log.txt
+'
+
+test_expect_success 'bisect starting with a detached HEAD' '
git bisect reset &&
git checkout master^ &&
HEAD=$(git rev-parse --verify HEAD) &&
diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh
index 16cc635813..8c7e081c53 100755
--- a/t/t6120-describe.sh
+++ b/t/t6120-describe.sh
@@ -91,15 +91,21 @@ check_describe D-* HEAD^^
check_describe A-* HEAD^^2
check_describe B HEAD^^2^
-check_describe A-* --tags HEAD
-check_describe A-* --tags HEAD^
-check_describe D-* --tags HEAD^^
-check_describe A-* --tags HEAD^^2
+check_describe c-* --tags HEAD
+check_describe c-* --tags HEAD^
+check_describe e-* --tags HEAD^^
+check_describe c-* --tags HEAD^^2
check_describe B --tags HEAD^^2^
check_describe B-0-* --long HEAD^^2^
check_describe A-3-* --long HEAD^^2
+: >err.expect
+check_describe A --all A^0
+test_expect_success 'no warning was displayed for A' '
+ test_cmp err.expect err.actual
+'
+
test_expect_success 'rename tag A to Q locally' '
mv .git/refs/tags/A .git/refs/tags/Q
'
diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh
index 575ef5beb2..ef2e78f9df 100755
--- a/t/t7001-mv.sh
+++ b/t/t7001-mv.sh
@@ -39,6 +39,31 @@ test_expect_success \
grep "^R100..*path1/COPYING..*path0/COPYING"'
test_expect_success \
+ 'checking -k on non-existing file' \
+ 'git mv -k idontexist path0'
+
+test_expect_success \
+ 'checking -k on untracked file' \
+ 'touch untracked1 &&
+ git mv -k untracked1 path0 &&
+ test -f untracked1 &&
+ test ! -f path0/untracked1'
+
+test_expect_success \
+ 'checking -k on multiple untracked files' \
+ 'touch untracked2 &&
+ git mv -k untracked1 untracked2 path0 &&
+ test -f untracked1 &&
+ test -f untracked2 &&
+ test ! -f path0/untracked1
+ test ! -f path0/untracked2'
+
+# clean up the mess in case bad things happen
+rm -f idontexist untracked1 untracked2 \
+ path0/idontexist path0/untracked1 path0/untracked2 \
+ .git/index.lock
+
+test_expect_success \
'adding another file' \
'cp "$TEST_DIRECTORY"/../README path0/README &&
git add path0/README &&
diff --git a/t/t7002-grep.sh b/t/t7002-grep.sh
index 18fe6f2d57..c4938544d4 100755
--- a/t/t7002-grep.sh
+++ b/t/t7002-grep.sh
@@ -161,7 +161,14 @@ test_expect_success 'log grep (6)' '
git log --author=-0700 --pretty=tformat:%s >actual &&
>expect &&
test_cmp expect actual
+'
+test_expect_success 'grep with CE_VALID file' '
+ git update-index --assume-unchanged t/t &&
+ rm t/t &&
+ test "$(git grep --no-ext-grep t)" = "t/t:test" &&
+ git update-index --no-assume-unchanged t/t &&
+ git checkout t/t
'
test_done
diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh
index b0a9d7d536..8537bf9160 100755
--- a/t/t7003-filter-branch.sh
+++ b/t/t7003-filter-branch.sh
@@ -262,4 +262,12 @@ test_expect_success 'Tag name filtering allows slashes in tag names' '
test_cmp expect actual
'
+test_expect_success 'Prune empty commits' '
+ git rev-list HEAD > expect &&
+ make_commit to_remove &&
+ git filter-branch -f --index-filter "git update-index --remove to_remove" --prune-empty HEAD &&
+ git rev-list HEAD > actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index f0edbf1a76..f377fea4bb 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -1090,4 +1090,15 @@ test_expect_success 'filename for the message is relative to cwd' '
git cat-file tag tag-from-subdir-2 | grep "in sub directory"
'
+# mixing modes and options:
+
+test_expect_success 'mixing incompatibles modes and options is forbidden' '
+ test_must_fail git tag -a
+ test_must_fail git tag -l -v
+ test_must_fail git tag -n 100
+ test_must_fail git tag -l -m msg
+ test_must_fail git tag -l -F some file
+ test_must_fail git tag -v -s
+'
+
test_done
diff --git a/t/t7007-show.sh b/t/t7007-show.sh
new file mode 100755
index 0000000000..cce222f052
--- /dev/null
+++ b/t/t7007-show.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+test_description='git show'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ echo hello world >foo &&
+ H=$(git hash-object -w foo) &&
+ git tag -a foo-tag -m "Tags $H" $H &&
+ HH=$(expr "$H" : "\(..\)") &&
+ H38=$(expr "$H" : "..\(.*\)") &&
+ rm -f .git/objects/$HH/$H38
+'
+
+test_expect_success 'showing a tag that point at a missing object' '
+ test_must_fail git --no-pager show foo-tag
+'
+
+test_done
diff --git a/t/t7201-co.sh b/t/t7201-co.sh
index 82769b89fc..0e21632f19 100755
--- a/t/t7201-co.sh
+++ b/t/t7201-co.sh
@@ -330,12 +330,26 @@ test_expect_success \
test "$(git config branch.track2.merge)"
git config branch.autosetupmerge false'
-test_expect_success \
- 'checkout w/--track from non-branch HEAD fails' '
- git checkout -b delete-me master &&
- rm .git/refs/heads/delete-me &&
- test refs/heads/delete-me = "$(git symbolic-ref HEAD)" &&
- test_must_fail git checkout --track -b track'
+test_expect_success 'checkout w/--track from non-branch HEAD fails' '
+ git checkout master^0 &&
+ test_must_fail git symbolic-ref HEAD &&
+ test_must_fail git checkout --track -b track &&
+ test_must_fail git rev-parse --verify track &&
+ test_must_fail git symbolic-ref HEAD &&
+ test "z$(git rev-parse master^0)" = "z$(git rev-parse HEAD)"
+'
+
+test_expect_success 'detach a symbolic link HEAD' '
+ git checkout master &&
+ git config --bool core.prefersymlinkrefs yes &&
+ git checkout side &&
+ git checkout master &&
+ it=$(git symbolic-ref HEAD) &&
+ test "z$it" = zrefs/heads/master &&
+ here=$(git rev-parse --verify refs/heads/master) &&
+ git checkout side^ &&
+ test "z$(git rev-parse --verify refs/heads/master)" = "z$here"
+'
test_expect_success \
'checkout with --track fakes a sensible -b <name>' '
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index be73f7b60a..2ec7ac6a51 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -209,4 +209,29 @@ test_expect_success 'update --init' '
'
+test_expect_success 'do not add files from a submodule' '
+
+ git reset --hard &&
+ test_must_fail git add init/a
+
+'
+
+test_expect_success 'gracefully add submodule with a trailing slash' '
+
+ git reset --hard &&
+ git commit -m "commit subproject" init &&
+ (cd init &&
+ echo b > a) &&
+ git add init/ &&
+ git diff --exit-code --cached init &&
+ commit=$(cd init &&
+ git commit -m update a >/dev/null &&
+ git rev-parse HEAD) &&
+ git add init/ &&
+ test_must_fail git diff --exit-code --cached init &&
+ test $commit = $(git ls-files --stage |
+ sed -n "s/^160000 \([^ ]*\).*/\1/p")
+
+'
+
test_done
diff --git a/t/t7500-commit.sh b/t/t7500-commit.sh
index 6e18a96319..5998baf27b 100755
--- a/t/t7500-commit.sh
+++ b/t/t7500-commit.sh
@@ -149,10 +149,7 @@ EOF
test_expect_success '--signoff' '
echo "yet another content *narf*" >> foo &&
- echo "zort" | (
- test_set_editor "$TEST_DIRECTORY"/t7500/add-content &&
- git commit -s -F - foo
- ) &&
+ echo "zort" | git commit -s -F - foo &&
git cat-file commit HEAD | sed "1,/^$/d" > output &&
test_cmp expect output
'
diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh
index 63bfc6d8b3..b4e2b4db84 100755
--- a/t/t7501-commit.sh
+++ b/t/t7501-commit.sh
@@ -127,6 +127,26 @@ test_expect_success \
"showing committed revisions" \
"git rev-list HEAD >current"
+cat >editor <<\EOF
+#!/bin/sh
+sed -e "s/good/bad/g" < "$1" > "$1-"
+mv "$1-" "$1"
+EOF
+chmod 755 editor
+
+cat >msg <<EOF
+A good commit message.
+EOF
+
+test_expect_success \
+ 'editor not invoked if -F is given' '
+ echo "moo" >file &&
+ VISUAL=./editor git commit -a -F msg &&
+ git show -s --pretty=format:"%s" | grep -q good &&
+ echo "quack" >file &&
+ echo "Another good message." | VISUAL=./editor git commit -a -F - &&
+ git show -s --pretty=format:"%s" | grep -q good
+ '
# We could just check the head sha1, but checking each commit makes it
# easier to isolate bugs.
diff --git a/t/t7502-commit.sh b/t/t7502-commit.sh
index 3eb9faedcf..ad42c78d7c 100755
--- a/t/t7502-commit.sh
+++ b/t/t7502-commit.sh
@@ -89,6 +89,14 @@ test_expect_success 'verbose' '
'
+test_expect_success 'verbose respects diff config' '
+
+ git config color.diff always &&
+ git status -v >actual &&
+ grep "\[1mdiff --git" actual &&
+ git config --unset color.diff
+'
+
test_expect_success 'cleanup commit messages (verbatim,-t)' '
echo >>negative &&
diff --git a/t/t7502-status.sh b/t/t7502-status.sh
index 1905fb34cd..93f875f500 100755
--- a/t/t7502-status.sh
+++ b/t/t7502-status.sh
@@ -292,6 +292,12 @@ test_expect_success 'status submodule summary is disabled by default' '
test_cmp expect output
'
+# we expect the same as the previous test
+test_expect_success 'status --untracked-files=all does not show submodule' '
+ git status --untracked-files=all >output &&
+ test_cmp expect output
+'
+
head=$(cd sm && git rev-parse --short=7 --verify HEAD)
cat >expect <<EOF
diff --git a/t/t7507-commit-verbose.sh b/t/t7507-commit-verbose.sh
new file mode 100755
index 0000000000..da5bd3b5a5
--- /dev/null
+++ b/t/t7507-commit-verbose.sh
@@ -0,0 +1,73 @@
+#!/bin/sh
+
+test_description='verbose commit template'
+. ./test-lib.sh
+
+cat >check-for-diff <<EOF
+#!$SHELL_PATH
+exec grep '^diff --git' "\$1"
+EOF
+chmod +x check-for-diff
+test_set_editor "$PWD/check-for-diff"
+
+cat >message <<'EOF'
+subject
+
+body
+EOF
+
+test_expect_success 'setup' '
+ echo content >file &&
+ git add file &&
+ git commit -F message
+'
+
+test_expect_success 'initial commit shows verbose diff' '
+ git commit --amend -v
+'
+
+test_expect_success 'second commit' '
+ echo content modified >file &&
+ git add file &&
+ git commit -F message
+'
+
+check_message() {
+ git log -1 --pretty=format:%s%n%n%b >actual &&
+ test_cmp "$1" actual
+}
+
+test_expect_success 'verbose diff is stripped out' '
+ git commit --amend -v &&
+ check_message message
+'
+
+test_expect_success 'verbose diff is stripped out (mnemonicprefix)' '
+ git config diff.mnemonicprefix true &&
+ git commit --amend -v &&
+ check_message message
+'
+
+cat >diff <<'EOF'
+This is an example commit message that contains a diff.
+
+diff --git c/file i/file
+new file mode 100644
+index 0000000..f95c11d
+--- /dev/null
++++ i/file
+@@ -0,0 +1 @@
++this is some content
+EOF
+
+test_expect_success 'diff in message is retained without -v' '
+ git commit --amend -F diff &&
+ check_message diff
+'
+
+test_expect_failure 'diff in message is retained with -v' '
+ git commit --amend -F diff -v &&
+ check_message diff
+'
+
+test_done
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index 7313ac278c..e5b210bc96 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -518,6 +518,46 @@ test_expect_success 'refresh the index before merging' '
git merge c3
'
+cat >expected <<EOF
+Merge branch 'c5' (early part)
+EOF
+
+test_expect_success 'merge early part of c2' '
+ git reset --hard c3 &&
+ echo c4 > c4.c &&
+ git add c4.c &&
+ git commit -m c4 &&
+ git tag c4 &&
+ echo c5 > c5.c &&
+ git add c5.c &&
+ git commit -m c5 &&
+ git tag c5 &&
+ git reset --hard c3 &&
+ echo c6 > c6.c &&
+ git add c6.c &&
+ git commit -m c6 &&
+ git tag c6 &&
+ git merge c5~1 &&
+ git show -s --pretty=format:%s HEAD > actual &&
+ test_cmp actual expected
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge --no-ff --no-commit && commit' '
+ git reset --hard c0 &&
+ git merge --no-ff --no-commit c1 &&
+ EDITOR=: git commit &&
+ verify_parents $c0 $c1
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'amending no-ff merge commit' '
+ EDITOR=: git commit --amend &&
+ verify_parents $c0 $c1
+'
+
test_debug 'gitk --all'
test_done
diff --git a/t/t7607-merge-overwrite.sh b/t/t7607-merge-overwrite.sh
new file mode 100755
index 0000000000..49f4e1599a
--- /dev/null
+++ b/t/t7607-merge-overwrite.sh
@@ -0,0 +1,87 @@
+#!/bin/sh
+
+test_description='git-merge
+
+Do not overwrite changes.'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ echo c0 > c0.c &&
+ git add c0.c &&
+ git commit -m c0 &&
+ git tag c0 &&
+ echo c1 > c1.c &&
+ git add c1.c &&
+ git commit -m c1 &&
+ git tag c1 &&
+ git reset --hard c0 &&
+ echo c2 > c2.c &&
+ git add c2.c &&
+ git commit -m c2 &&
+ git tag c2 &&
+ git reset --hard c1 &&
+ echo "c1 a" > c1.c &&
+ git add c1.c &&
+ git commit -m "c1 a" &&
+ git tag c1a &&
+ echo "VERY IMPORTANT CHANGES" > important
+'
+
+test_expect_success 'will not overwrite untracked file' '
+ git reset --hard c1 &&
+ cat important > c2.c &&
+ ! git merge c2 &&
+ test_cmp important c2.c
+'
+
+test_expect_success 'will not overwrite new file' '
+ git reset --hard c1 &&
+ cat important > c2.c &&
+ git add c2.c &&
+ ! git merge c2 &&
+ test_cmp important c2.c
+'
+
+test_expect_success 'will not overwrite staged changes' '
+ git reset --hard c1 &&
+ cat important > c2.c &&
+ git add c2.c &&
+ rm c2.c &&
+ ! git merge c2 &&
+ git checkout c2.c &&
+ test_cmp important c2.c
+'
+
+test_expect_success 'will not overwrite removed file' '
+ git reset --hard c1 &&
+ git rm c1.c &&
+ git commit -m "rm c1.c" &&
+ cat important > c1.c &&
+ ! git merge c1a &&
+ test_cmp important c1.c
+'
+
+test_expect_success 'will not overwrite re-added file' '
+ git reset --hard c1 &&
+ git rm c1.c &&
+ git commit -m "rm c1.c" &&
+ cat important > c1.c &&
+ git add c1.c &&
+ ! git merge c1a &&
+ test_cmp important c1.c
+'
+
+test_expect_success 'will not overwrite removed file with staged changes' '
+ git reset --hard c1 &&
+ git rm c1.c &&
+ git commit -m "rm c1.c" &&
+ cat important > c1.c &&
+ git add c1.c &&
+ rm c1.c &&
+ ! git merge c1a &&
+ git checkout c1.c &&
+ test_cmp important c1.c
+'
+
+test_done
diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh
new file mode 100755
index 0000000000..3f602ea7de
--- /dev/null
+++ b/t/t7700-repack.sh
@@ -0,0 +1,73 @@
+#!/bin/sh
+
+test_description='git repack works correctly'
+
+. ./test-lib.sh
+
+test_expect_success 'objects in packs marked .keep are not repacked' '
+ echo content1 > file1 &&
+ echo content2 > file2 &&
+ git add . &&
+ git commit -m initial_commit &&
+ # Create two packs
+ # The first pack will contain all of the objects except one
+ git rev-list --objects --all | grep -v file2 |
+ git pack-objects pack > /dev/null &&
+ # The second pack will contain the excluded object
+ packsha1=$(git rev-list --objects --all | grep file2 |
+ git pack-objects pack) &&
+ touch -r pack-$packsha1.pack pack-$packsha1.keep &&
+ objsha1=$(git verify-pack -v pack-$packsha1.idx | head -n 1 |
+ sed -e "s/^\([0-9a-f]\{40\}\).*/\1/") &&
+ mv pack-* .git/objects/pack/ &&
+ git repack -A -d -l &&
+ git prune-packed &&
+ for p in .git/objects/pack/*.idx; do
+ idx=$(basename $p)
+ test "pack-$packsha1.idx" = "$idx" && continue
+ if git verify-pack -v $p | egrep "^$objsha1"; then
+ found_duplicate_object=1
+ echo "DUPLICATE OBJECT FOUND"
+ break
+ fi
+ done &&
+ test -z "$found_duplicate_object"
+'
+
+test_expect_success 'loose objects in alternate ODB are not repacked' '
+ mkdir alt_objects &&
+ echo `pwd`/alt_objects > .git/objects/info/alternates &&
+ echo content3 > file3 &&
+ objsha1=$(GIT_OBJECT_DIRECTORY=alt_objects git hash-object -w file3) &&
+ git add file3 &&
+ git commit -m commit_file3 &&
+ git repack -a -d -l &&
+ git prune-packed &&
+ for p in .git/objects/pack/*.idx; do
+ if git verify-pack -v $p | egrep "^$objsha1"; then
+ found_duplicate_object=1
+ echo "DUPLICATE OBJECT FOUND"
+ break
+ fi
+ done &&
+ test -z "$found_duplicate_object"
+'
+
+test_expect_success 'packed obs in alt ODB are repacked even when local repo is packless' '
+ mkdir alt_objects/pack
+ mv .git/objects/pack/* alt_objects/pack &&
+ git repack -a &&
+ myidx=$(ls -1 .git/objects/pack/*.idx) &&
+ test -f "$myidx" &&
+ for p in alt_objects/pack/*.idx; do
+ git verify-pack -v $p | sed -n -e "/^[0-9a-f]\{40\}/p"
+ done | while read sha1 rest; do
+ if ! ( git verify-pack -v $myidx | grep "^$sha1" ); then
+ echo "Missing object in local pack: $sha1"
+ return 1
+ fi
+ done
+'
+
+test_done
+
diff --git a/t/t7701-repack-unpack-unreachable.sh b/t/t7701-repack-unpack-unreachable.sh
index b48046e261..63a8225ae5 100755
--- a/t/t7701-repack-unpack-unreachable.sh
+++ b/t/t7701-repack-unpack-unreachable.sh
@@ -8,7 +8,7 @@ fsha1=
csha1=
tsha1=
-test_expect_success '-A option leaves unreachable objects unpacked' '
+test_expect_success '-A with -d option leaves unreachable objects unpacked' '
echo content > file1 &&
git add . &&
git commit -m initial_commit &&
@@ -58,7 +58,7 @@ compare_mtimes ()
' -- "$@"
}
-test_expect_success 'unpacked objects receive timestamp of pack file' '
+test_expect_success '-A without -d option leaves unreachable objects packed' '
fsha1path=$(echo "$fsha1" | sed -e "s|\(..\)|\1/|") &&
fsha1path=".git/objects/$fsha1path" &&
csha1path=$(echo "$csha1" | sed -e "s|\(..\)|\1/|") &&
@@ -75,7 +75,19 @@ test_expect_success 'unpacked objects receive timestamp of pack file' '
git branch -D transient_branch &&
sleep 1 &&
git repack -A -l &&
- compare_mtimes "$packfile" "$fsha1path" "$csha1path" "$tsha1path"
+ test ! -f "$fsha1path" &&
+ test ! -f "$csha1path" &&
+ test ! -f "$tsha1path" &&
+ git show $fsha1 &&
+ git show $csha1 &&
+ git show $tsha1
+'
+
+test_expect_success 'unpacked objects receive timestamp of pack file' '
+ tmppack=".git/objects/pack/tmp_pack" &&
+ ln "$packfile" "$tmppack" &&
+ git repack -A -l -d &&
+ compare_mtimes "$tmppack" "$fsha1path" "$csha1path" "$tsha1path"
'
test_done
diff --git a/t/t8005-blame-i18n.sh b/t/t8005-blame-i18n.sh
new file mode 100755
index 0000000000..4470a92bb2
--- /dev/null
+++ b/t/t8005-blame-i18n.sh
@@ -0,0 +1,92 @@
+#!/bin/sh
+
+test_description='git blame encoding conversion'
+. ./test-lib.sh
+
+. "$TEST_DIRECTORY"/t8005/utf8.txt
+. "$TEST_DIRECTORY"/t8005/cp1251.txt
+. "$TEST_DIRECTORY"/t8005/sjis.txt
+
+test_expect_success 'setup the repository' '
+ # Create the file
+ echo "UTF-8 LINE" > file &&
+ git add file &&
+ git commit --author "$UTF8_NAME <utf8@localhost>" -m "$UTF8_MSG" &&
+
+ echo "CP1251 LINE" >> file &&
+ git add file &&
+ git config i18n.commitencoding cp1251 &&
+ git commit --author "$CP1251_NAME <cp1251@localhost>" -m "$CP1251_MSG" &&
+
+ echo "SJIS LINE" >> file &&
+ git add file &&
+ git config i18n.commitencoding shift-jis &&
+ git commit --author "$SJIS_NAME <sjis@localhost>" -m "$SJIS_MSG"
+'
+
+cat >expected <<EOF
+author $SJIS_NAME
+summary $SJIS_MSG
+author $SJIS_NAME
+summary $SJIS_MSG
+author $SJIS_NAME
+summary $SJIS_MSG
+EOF
+
+test_expect_success \
+ 'blame respects i18n.commitencoding' '
+ git blame --incremental file | \
+ grep "^\(author\|summary\) " > actual &&
+ test_cmp actual expected
+'
+
+cat >expected <<EOF
+author $CP1251_NAME
+summary $CP1251_MSG
+author $CP1251_NAME
+summary $CP1251_MSG
+author $CP1251_NAME
+summary $CP1251_MSG
+EOF
+
+test_expect_success \
+ 'blame respects i18n.logoutputencoding' '
+ git config i18n.logoutputencoding cp1251 &&
+ git blame --incremental file | \
+ grep "^\(author\|summary\) " > actual &&
+ test_cmp actual expected
+'
+
+cat >expected <<EOF
+author $UTF8_NAME
+summary $UTF8_MSG
+author $UTF8_NAME
+summary $UTF8_MSG
+author $UTF8_NAME
+summary $UTF8_MSG
+EOF
+
+test_expect_success \
+ 'blame respects --encoding=utf-8' '
+ git blame --incremental --encoding=utf-8 file | \
+ grep "^\(author\|summary\) " > actual &&
+ test_cmp actual expected
+'
+
+cat >expected <<EOF
+author $SJIS_NAME
+summary $SJIS_MSG
+author $CP1251_NAME
+summary $CP1251_MSG
+author $UTF8_NAME
+summary $UTF8_MSG
+EOF
+
+test_expect_success \
+ 'blame respects --encoding=none' '
+ git blame --incremental --encoding=none file | \
+ grep "^\(author\|summary\) " > actual &&
+ test_cmp actual expected
+'
+
+test_done
diff --git a/t/t8005/cp1251.txt b/t/t8005/cp1251.txt
new file mode 100644
index 0000000000..ce41e98b81
--- /dev/null
+++ b/t/t8005/cp1251.txt
@@ -0,0 +1,2 @@
+CP1251_NAME="Èâàí Ïåòðîâè÷ Ñèäîðîâ"
+CP1251_MSG="Òåñòîâîå ñîîáùåíèå"
diff --git a/t/t8005/sjis.txt b/t/t8005/sjis.txt
new file mode 100644
index 0000000000..2ccfbad207
--- /dev/null
+++ b/t/t8005/sjis.txt
@@ -0,0 +1,2 @@
+SJIS_NAME="„I„r„p„~ „P„u„„„‚„€„r„y„‰ „R„y„t„€„‚„€„r"
+SJIS_MSG="„S„u„ƒ„„„€„r„€„u „ƒ„€„€„q„‹„u„~„y„u"
diff --git a/t/t8005/utf8.txt b/t/t8005/utf8.txt
new file mode 100644
index 0000000000..f46cfc56d8
--- /dev/null
+++ b/t/t8005/utf8.txt
@@ -0,0 +1,2 @@
+UTF8_NAME="Иван Петрович Сидоров"
+UTF8_MSG="ТеÑтовое Ñообщение"
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index 561ae7d0a6..cb3d183770 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -292,4 +292,25 @@ test_expect_success '--compose adds MIME for utf8 subject' '
grep "^Subject: =?utf-8?q?utf8-s=C3=BCbj=C3=ABct?=" msgtxt1
'
+test_expect_success 'detects ambiguous reference/file conflict' '
+ echo master > master &&
+ git add master &&
+ git commit -m"add master" &&
+ test_must_fail git send-email --dry-run master 2>errors &&
+ grep disambiguate errors
+'
+
+test_expect_success 'feed two files' '
+ rm -fr outdir &&
+ git format-patch -2 -o outdir &&
+ GIT_SEND_EMAIL_NOTTY=1 git send-email \
+ --dry-run \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ outdir/000?-*.patch 2>errors >out &&
+ grep "^Subject: " out >subjects &&
+ test "z$(sed -n -e 1p subjects)" = "zSubject: [PATCH 1/2] Second." &&
+ test "z$(sed -n -e 2p subjects)" = "zSubject: [PATCH 2/2] add master"
+'
+
test_done
diff --git a/t/t9100-git-svn-basic.sh b/t/t9100-git-svn-basic.sh
index 9b238c329b..bb921af56a 100755
--- a/t/t9100-git-svn-basic.sh
+++ b/t/t9100-git-svn-basic.sh
@@ -265,4 +265,13 @@ test_expect_success 'able to set-tree to a subdirectory' "
test -z \"\`git diff refs/heads/my-bar refs/remotes/bar\`\"
"
+test_expect_success 'git-svn works in a bare repository' '
+ mkdir bare-repo &&
+ ( cd bare-repo &&
+ git init --bare &&
+ GIT_DIR=. git svn init "$svnrepo" &&
+ git svn fetch ) &&
+ rm -rf bare-repo
+ '
+
test_done
diff --git a/t/t9104-git-svn-follow-parent.sh b/t/t9104-git-svn-follow-parent.sh
index 0a091e048e..ab9fa32220 100755
--- a/t/t9104-git-svn-follow-parent.sh
+++ b/t/t9104-git-svn-follow-parent.sh
@@ -149,6 +149,48 @@ test_expect_success "track initial change if it was only made to parent" '
"`git rev-parse r9270-d~1`"
'
+test_expect_success "follow-parent is atomic" '
+ (
+ cd wc &&
+ svn up &&
+ svn mkdir stunk &&
+ echo "trunk stunk" > stunk/readme &&
+ svn add stunk/readme &&
+ svn ci -m "trunk stunk" &&
+ echo "stunk like junk" >> stunk/readme &&
+ svn ci -m "really stunk" &&
+ echo "stink stank stunk" >> stunk/readme &&
+ svn ci -m "even the grinch agrees"
+ ) &&
+ svn copy -m "stunk flunked" "$svnrepo"/stunk "$svnrepo"/flunk &&
+ { svn cp -m "early stunk flunked too" \
+ "$svnrepo"/stunk@17 "$svnrepo"/flunked ||
+ svn cp -m "early stunk flunked too" \
+ -r17 "$svnrepo"/stunk "$svnrepo"/flunked; } &&
+ git svn init --minimize-url -i stunk "$svnrepo"/stunk &&
+ git svn fetch -i stunk &&
+ git update-ref refs/remotes/flunk@18 refs/remotes/stunk~2 &&
+ git update-ref -d refs/remotes/stunk &&
+ git config --unset svn-remote.svn.fetch stunk &&
+ mkdir -p "$GIT_DIR"/svn/flunk@18 &&
+ rev_map=$(cd "$GIT_DIR"/svn/stunk && ls .rev_map*) &&
+ dd if="$GIT_DIR"/svn/stunk/$rev_map \
+ of="$GIT_DIR"/svn/flunk@18/$rev_map bs=24 count=1 &&
+ rm -rf "$GIT_DIR"/svn/stunk &&
+ git svn init --minimize-url -i flunk "$svnrepo"/flunk &&
+ git svn fetch -i flunk &&
+ git svn init --minimize-url -i stunk "$svnrepo"/stunk &&
+ git svn fetch -i stunk &&
+ git svn init --minimize-url -i flunked "$svnrepo"/flunked &&
+ git svn fetch -i flunked
+ test "`git rev-parse --verify refs/remotes/flunk@18`" \
+ = "`git rev-parse --verify refs/remotes/stunk`" &&
+ test "`git rev-parse --verify refs/remotes/flunk~1`" \
+ = "`git rev-parse --verify refs/remotes/stunk`" &&
+ test "`git rev-parse --verify refs/remotes/flunked~1`" \
+ = "`git rev-parse --verify refs/remotes/stunk~1`"
+ '
+
test_expect_success "track multi-parent paths" '
svn cp -m "resurrect /glob" "$svnrepo"/r9270 "$svnrepo"/glob &&
git svn multi-fetch &&
diff --git a/t/t9128-git-svn-cmd-branch.sh b/t/t9128-git-svn-cmd-branch.sh
index 47c4d4d938..252daa7e1a 100755
--- a/t/t9128-git-svn-cmd-branch.sh
+++ b/t/t9128-git-svn-cmd-branch.sh
@@ -56,4 +56,23 @@ test_expect_success 'git svn branch tests' '
test_must_fail git svn tag tag1
'
+test_expect_success 'branch uses correct svn-remote' '
+ (svn co "$svnrepo" svn &&
+ cd svn &&
+ mkdir mirror &&
+ svn add mirror &&
+ svn copy trunk mirror/ &&
+ svn copy tags mirror/ &&
+ svn copy branches mirror/ &&
+ svn ci -m "made mirror" ) &&
+ rm -rf svn &&
+ git svn init -s -R mirror --prefix=mirror/ "$svnrepo"/mirror &&
+ git svn fetch -R mirror &&
+ git checkout mirror/trunk &&
+ base=$(git rev-parse HEAD:) &&
+ git svn branch -m "branch in mirror" d &&
+ test $base = $(git rev-parse remotes/mirror/d:) &&
+ test_must_fail git rev-parse remotes/d
+'
+
test_done
diff --git a/t/t9129-git-svn-i18n-commitencoding.sh b/t/t9129-git-svn-i18n-commitencoding.sh
new file mode 100755
index 0000000000..8a9dde44d5
--- /dev/null
+++ b/t/t9129-git-svn-i18n-commitencoding.sh
@@ -0,0 +1,84 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Eric Wong
+
+test_description='git svn honors i18n.commitEncoding in config'
+
+. ./lib-git-svn.sh
+
+compare_git_head_with () {
+ nr=`wc -l < "$1"`
+ a=7
+ b=$(($a + $nr - 1))
+ git cat-file commit HEAD | sed -ne "$a,${b}p" >current &&
+ test_cmp current "$1"
+}
+
+compare_svn_head_with () {
+ LC_ALL=en_US.UTF-8 svn log --limit 1 `git svn info --url` | \
+ sed -e 1,3d -e "/^-\{1,\}\$/d" >current &&
+ test_cmp current "$1"
+}
+
+for H in ISO-8859-1 EUCJP ISO-2022-JP
+do
+ test_expect_success "$H setup" '
+ mkdir $H &&
+ svn import -m "$H test" $H "$svnrepo"/$H &&
+ git svn clone "$svnrepo"/$H $H
+ '
+done
+
+for H in ISO-8859-1 EUCJP ISO-2022-JP
+do
+ test_expect_success "$H commit on git side" '
+ (
+ cd $H &&
+ git config i18n.commitencoding $H &&
+ git checkout -b t refs/remotes/git-svn &&
+ echo $H >F &&
+ git add F &&
+ git commit -a -F "$TEST_DIRECTORY"/t3900/$H.txt &&
+ E=$(git cat-file commit HEAD | sed -ne "s/^encoding //p") &&
+ test "z$E" = "z$H"
+ compare_git_head_with "$TEST_DIRECTORY"/t3900/$H.txt
+ )
+ '
+done
+
+for H in ISO-8859-1 EUCJP ISO-2022-JP
+do
+ test_expect_success "$H dcommit to svn" '
+ (
+ cd $H &&
+ git svn dcommit &&
+ git cat-file commit HEAD | grep git-svn-id: &&
+ E=$(git cat-file commit HEAD | sed -ne "s/^encoding //p") &&
+ test "z$E" = "z$H" &&
+ compare_git_head_with "$TEST_DIRECTORY"/t3900/$H.txt
+ )
+ '
+done
+
+if locale -a |grep -q en_US.utf8; then
+ test_expect_success 'ISO-8859-1 should match UTF-8 in svn' '
+ (
+ cd ISO-8859-1 &&
+ compare_svn_head_with "$TEST_DIRECTORY"/t3900/1-UTF-8.txt
+ )
+ '
+
+ for H in EUCJP ISO-2022-JP
+ do
+ test_expect_success '$H should match UTF-8 in svn' '
+ (
+ cd $H &&
+ compare_svn_head_with "$TEST_DIRECTORY"/t3900/2-UTF-8.txt
+ )
+ '
+ done
+else
+ say "UTF-8 locale not available, test skipped"
+fi
+
+test_done
diff --git a/t/t9130-git-svn-authors-file.sh b/t/t9130-git-svn-authors-file.sh
new file mode 100755
index 0000000000..b8fb277562
--- /dev/null
+++ b/t/t9130-git-svn-authors-file.sh
@@ -0,0 +1,94 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Eric Wong
+#
+
+test_description='git svn authors file tests'
+
+. ./lib-git-svn.sh
+
+cat > svn-authors <<EOF
+aa = AAAAAAA AAAAAAA <aa@example.com>
+bb = BBBBBBB BBBBBBB <bb@example.com>
+EOF
+
+test_expect_success 'setup svnrepo' '
+ for i in aa bb cc dd
+ do
+ svn mkdir -m $i --username $i "$svnrepo"/$i
+ done
+ '
+
+test_expect_success 'start import with incomplete authors file' '
+ ! git svn clone --authors-file=svn-authors "$svnrepo" x
+ '
+
+test_expect_success 'imported 2 revisions successfully' '
+ (
+ cd x
+ test "`git rev-list refs/remotes/git-svn | wc -l`" -eq 2 &&
+ git rev-list -1 --pretty=raw refs/remotes/git-svn | \
+ grep "^author BBBBBBB BBBBBBB <bb@example\.com> " &&
+ git rev-list -1 --pretty=raw refs/remotes/git-svn~1 | \
+ grep "^author AAAAAAA AAAAAAA <aa@example\.com> "
+ )
+ '
+
+cat >> svn-authors <<EOF
+cc = CCCCCCC CCCCCCC <cc@example.com>
+dd = DDDDDDD DDDDDDD <dd@example.com>
+EOF
+
+test_expect_success 'continues to import once authors have been added' '
+ (
+ cd x
+ git svn fetch --authors-file=../svn-authors &&
+ test "`git rev-list refs/remotes/git-svn | wc -l`" -eq 4 &&
+ git rev-list -1 --pretty=raw refs/remotes/git-svn | \
+ grep "^author DDDDDDD DDDDDDD <dd@example\.com> " &&
+ git rev-list -1 --pretty=raw refs/remotes/git-svn~1 | \
+ grep "^author CCCCCCC CCCCCCC <cc@example\.com> "
+ )
+ '
+
+test_expect_success 'authors-file against globs' '
+ svn mkdir -m globs --username aa \
+ "$svnrepo"/aa/trunk "$svnrepo"/aa/branches "$svnrepo"/aa/tags &&
+ git svn clone --authors-file=svn-authors -s "$svnrepo"/aa aa-work &&
+ for i in bb ee cc
+ do
+ branch="aa/branches/$i"
+ svn mkdir -m "$branch" --username $i "$svnrepo/$branch"
+ done
+ '
+
+test_expect_success 'fetch fails on ee' '
+ ( cd aa-work && ! git svn fetch --authors-file=../svn-authors )
+ '
+
+tmp_config_get () {
+ GIT_CONFIG=.git/svn/.metadata git config --get "$1"
+}
+
+test_expect_success 'failure happened without negative side effects' '
+ (
+ cd aa-work &&
+ test 6 -eq "`tmp_config_get svn-remote.svn.branches-maxRev`" &&
+ test 6 -eq "`tmp_config_get svn-remote.svn.tags-maxRev`"
+ )
+ '
+
+cat >> svn-authors <<EOF
+ee = EEEEEEE EEEEEEE <ee@example.com>
+EOF
+
+test_expect_success 'fetch continues after authors-file is fixed' '
+ (
+ cd aa-work &&
+ git svn fetch --authors-file=../svn-authors &&
+ test 8 -eq "`tmp_config_get svn-remote.svn.branches-maxRev`" &&
+ test 8 -eq "`tmp_config_get svn-remote.svn.tags-maxRev`"
+ )
+ '
+
+test_done
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index 328444a306..821be7ce8d 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -56,6 +56,12 @@ M 644 :2 file2
M 644 :3 file3
M 755 :4 file4
+tag series-A
+from :5
+data <<EOF
+An annotated tag without a tagger
+EOF
+
INPUT_END
test_expect_success \
'A: create pack from stdin' \
@@ -102,6 +108,18 @@ test_expect_success \
'git cat-file blob master:file4 >actual && test_cmp expect actual'
cat >expect <<EOF
+object $(git rev-parse refs/heads/master)
+type commit
+tag series-A
+
+An annotated tag without a tagger
+EOF
+test_expect_success 'A: verify tag/series-A' '
+ git cat-file tag tags/series-A >actual &&
+ test_cmp expect actual
+'
+
+cat >expect <<EOF
:2 `git rev-parse --verify master:file2`
:3 `git rev-parse --verify master:file3`
:4 `git rev-parse --verify master:file4`
@@ -983,7 +1001,7 @@ test_expect_success \
git checkout subuse1 &&
rm -rf sub && mkdir sub && cd sub &&
git init &&
- git fetch .. refs/heads/sub:refs/heads/master &&
+ git fetch --update-head-ok .. refs/heads/sub:refs/heads/master &&
git checkout master &&
cd .. &&
git submodule init &&
diff --git a/t/t9301-fast-export.sh b/t/t9301-fast-export.sh
index 6ddd7c19fd..9985721055 100755
--- a/t/t9301-fast-export.sh
+++ b/t/t9301-fast-export.sh
@@ -231,4 +231,32 @@ test_expect_success 'fast-export -C -C | fast-import' '
'
+test_expect_success 'fast-export | fast-import when master is tagged' '
+
+ git tag -m msg last &&
+ git fast-export -C -C --signed-tags=strip --all > output &&
+ test $(grep -c "^tag " output) = 3
+
+'
+
+cat > tag-content << EOF
+object $(git rev-parse HEAD)
+type commit
+tag rosten
+EOF
+
+test_expect_success 'cope with tagger-less tags' '
+
+ TAG=$(git hash-object -t tag -w tag-content) &&
+ git update-ref refs/tags/sonnenschein $TAG &&
+ git fast-export -C -C --signed-tags=strip --all > output &&
+ test $(grep -c "^tag " output) = 4 &&
+ ! grep "Unspecified Tagger" output &&
+ git fast-export -C -C --signed-tags=strip --all \
+ --fake-missing-tagger > output &&
+ test $(grep -c "^tag " output) = 4 &&
+ grep "Unspecified Tagger" output
+
+'
+
test_done
diff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh
index c1850d2923..6a37f71d11 100755
--- a/t/t9400-git-cvsserver-server.sh
+++ b/t/t9400-git-cvsserver-server.sh
@@ -424,7 +424,7 @@ cd "$WORKDIR"
test_expect_success 'cvs update (-p)' '
touch really-empty &&
echo Line 1 > no-lf &&
- echo -n Line 2 >> no-lf &&
+ printf "Line 2" >> no-lf &&
git add really-empty no-lf &&
git commit -q -m "Update -p test" &&
git push gitcvs.git >/dev/null &&
diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh
index 64c4cce58b..43cd6eecba 100755
--- a/t/t9500-gitweb-standalone-no-errors.sh
+++ b/t/t9500-gitweb-standalone-no-errors.sh
@@ -673,4 +673,14 @@ test_expect_success \
gitweb_run "p=.git;a=tree"'
test_debug 'cat gitweb.log'
+# ----------------------------------------------------------------------
+# non-ASCII in README.html
+
+test_expect_success \
+ 'README.html with non-ASCII characters (utf-8)' \
+ 'echo "<b>UTF-8 example:</b><br />" > .git/README.html &&
+ cat "$TEST_DIRECTORY"/t3900/1-UTF-8.txt >> .git/README.html &&
+ gitweb_run "p=.git;a=summary"'
+test_debug 'cat gitweb.log'
+
test_done
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 8936173ee2..22ed448d56 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -471,7 +471,6 @@ PATH=$TEST_DIRECTORY/..:$PATH
GIT_EXEC_PATH=$(pwd)/..
GIT_TEMPLATE_DIR=$(pwd)/../templates/blt
unset GIT_CONFIG
-unset GIT_CONFIG_LOCAL
GIT_CONFIG_NOSYSTEM=1
GIT_CONFIG_NOGLOBAL=1
export PATH GIT_EXEC_PATH GIT_TEMPLATE_DIR GIT_CONFIG_NOSYSTEM GIT_CONFIG_NOGLOBAL
diff --git a/test-chmtime.c b/test-chmtime.c
index 90da448ebe..d5358cbaac 100644
--- a/test-chmtime.c
+++ b/test-chmtime.c
@@ -1,39 +1,83 @@
+/*
+ * This program can either change modification time of the given
+ * file(s) or just print it. The program does not change atime nor
+ * ctime (their values are explicitely preserved).
+ *
+ * The mtime can be changed to an absolute value:
+ *
+ * test-chmtime =<seconds> file...
+ *
+ * Relative to the current time as returned by time(3):
+ *
+ * test-chmtime =+<seconds> (or =-<seconds>) file...
+ *
+ * Or relative to the current mtime of the file:
+ *
+ * test-chmtime <seconds> file...
+ * test-chmtime +<seconds> (or -<seconds>) file...
+ *
+ * Examples:
+ *
+ * To just print the mtime use --verbose and set the file mtime offset to 0:
+ *
+ * test-chmtime -v +0 file
+ *
+ * To set the mtime to current time:
+ *
+ * test-chmtime =+0 file
+ *
+ */
#include "git-compat-util.h"
#include <utime.h>
-static const char usage_str[] = "(+|=|=+|=-|-)<seconds> <file>...";
+static const char usage_str[] = "-v|--verbose (+|=|=+|=-|-)<seconds> <file>...";
-int main(int argc, const char *argv[])
+static int timespec_arg(const char *arg, long int *set_time, int *set_eq)
{
- int i;
- int set_eq;
- long int set_time;
char *test;
- const char *timespec;
-
- if (argc < 3)
- goto usage;
-
- timespec = argv[1];
- set_eq = (*timespec == '=') ? 1 : 0;
- if (set_eq) {
+ const char *timespec = arg;
+ *set_eq = (*timespec == '=') ? 1 : 0;
+ if (*set_eq) {
timespec++;
if (*timespec == '+') {
- set_eq = 2; /* relative "in the future" */
+ *set_eq = 2; /* relative "in the future" */
timespec++;
}
}
- set_time = strtol(timespec, &test, 10);
+ *set_time = strtol(timespec, &test, 10);
if (*test) {
- fprintf(stderr, "Not a base-10 integer: %s\n", argv[1] + 1);
- goto usage;
+ fprintf(stderr, "Not a base-10 integer: %s\n", arg + 1);
+ return 0;
}
- if ((set_eq && set_time < 0) || set_eq == 2) {
+ if ((*set_eq && *set_time < 0) || *set_eq == 2) {
time_t now = time(NULL);
- set_time += now;
+ *set_time += now;
}
+ return 1;
+}
+
+int main(int argc, const char *argv[])
+{
+ static int verbose;
- for (i = 2; i < argc; i++) {
+ int i = 1;
+ /* no mtime change by default */
+ int set_eq = 0;
+ long int set_time = 0;
+
+ if (argc < 3)
+ goto usage;
+
+ if (strcmp(argv[i], "--verbose") == 0 || strcmp(argv[i], "-v") == 0) {
+ verbose = 1;
+ ++i;
+ }
+ if (timespec_arg(argv[i], &set_time, &set_eq))
+ ++i;
+ else
+ goto usage;
+
+ for (; i < argc; i++) {
struct stat sb;
struct utimbuf utb;
@@ -46,7 +90,12 @@ int main(int argc, const char *argv[])
utb.actime = sb.st_atime;
utb.modtime = set_eq ? set_time : sb.st_mtime + set_time;
- if (utime(argv[i], &utb) < 0) {
+ if (verbose) {
+ uintmax_t mtime = utb.modtime < 0 ? 0: utb.modtime;
+ printf("%"PRIuMAX"\t%s\n", mtime, argv[i]);
+ }
+
+ if (utb.modtime != sb.st_mtime && utime(argv[i], &utb) < 0) {
fprintf(stderr, "Failed to modify time on %s: %s\n",
argv[i], strerror(errno));
return -1;
diff --git a/transport.c b/transport.c
index 5110c56c4e..56831c57c5 100644
--- a/transport.c
+++ b/transport.c
@@ -75,7 +75,7 @@ static int read_loose_refs(struct strbuf *path, int name_offset,
if (fd < 0)
continue;
- next = alloc_ref(path->len - name_offset + 1);
+ next = alloc_ref(path->buf + name_offset);
if (read_in_full(fd, buffer, 40) != 40 ||
get_sha1_hex(buffer, next->old_sha1)) {
close(fd);
@@ -83,7 +83,6 @@ static int read_loose_refs(struct strbuf *path, int name_offset,
continue;
}
close(fd);
- strcpy(next->name, path->buf + name_offset);
(*tail)->next = next;
*tail = next;
}
@@ -127,14 +126,13 @@ static void insert_packed_refs(const char *packed_refs, struct ref **list)
(*list)->next->name)) > 0)
list = &(*list)->next;
if (!(*list)->next || cmp < 0) {
- struct ref *next = alloc_ref(len - 40);
+ struct ref *next = alloc_ref(buffer + 41);
buffer[40] = '\0';
if (get_sha1_hex(buffer, next->old_sha1)) {
warning ("invalid SHA-1: %s", buffer);
free(next);
continue;
}
- strcpy(next->name, buffer + 41);
next->next = (*list)->next;
(*list)->next = next;
list = &(*list)->next;
@@ -501,7 +499,7 @@ static struct ref *get_refs_via_curl(struct transport *transport)
strbuf_release(&buffer);
- ref = alloc_ref_from_str("HEAD");
+ ref = alloc_ref("HEAD");
if (!walker->fetch_ref(walker, ref) &&
!resolve_remote_symref(ref, refs)) {
ref->next = refs;
@@ -542,7 +540,7 @@ static struct ref *get_refs_from_bundle(struct transport *transport)
die ("Could not read bundle '%s'.", transport->url);
for (i = 0; i < data->header.references.nr; i++) {
struct ref_list_entry *e = data->header.references.list + i;
- struct ref *ref = alloc_ref_from_str(e->name);
+ struct ref *ref = alloc_ref(e->name);
hashcpy(ref->old_sha1, e->sha1);
ref->next = result;
result = ref;
@@ -644,7 +642,7 @@ static int fetch_refs_via_pack(struct transport *transport,
args.include_tag = data->followtags;
args.verbose = (transport->verbose > 0);
args.quiet = (transport->verbose < 0);
- args.no_progress = args.quiet || !isatty(1);
+ args.no_progress = args.quiet || (!transport->progress && !isatty(1));
args.depth = data->depth;
for (i = 0; i < nr_heads; i++)
diff --git a/transport.h b/transport.h
index d0b52053ff..6bbc1a8264 100644
--- a/transport.h
+++ b/transport.h
@@ -25,6 +25,8 @@ struct transport {
int (*disconnect)(struct transport *connection);
char *pack_lockfile;
signed verbose : 2;
+ /* Force progress even if the output is not a tty */
+ unsigned progress : 1;
};
#define TRANSPORT_PUSH_ALL 1
diff --git a/unpack-trees.c b/unpack-trees.c
index e59d144d28..15c9ef592b 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -352,7 +352,7 @@ static int unpack_failed(struct unpack_trees_options *o, const char *message)
discard_index(&o->result);
if (!o->gently) {
if (message)
- return error(message);
+ return error("%s", message);
return -1;
}
return -1;
@@ -382,7 +382,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
o->merge_size = len;
if (!dfc)
- dfc = xcalloc(1, sizeof(struct cache_entry) + 1);
+ dfc = xcalloc(1, cache_entry_size(0));
o->df_conflict_entry = dfc;
if (len) {
@@ -494,7 +494,7 @@ static int verify_clean_subdirectory(struct cache_entry *ce, const char *action,
* anything in the existing directory there.
*/
int namelen;
- int pos, i;
+ int i;
struct dir_struct d;
char *pathbuf;
int cnt = 0;
@@ -515,24 +515,20 @@ static int verify_clean_subdirectory(struct cache_entry *ce, const char *action,
* in that directory.
*/
namelen = strlen(ce->name);
- pos = index_name_pos(o->src_index, ce->name, namelen);
- if (0 <= pos)
- return cnt; /* we have it as nondirectory */
- pos = -pos - 1;
- for (i = pos; i < o->src_index->cache_nr; i++) {
- struct cache_entry *ce = o->src_index->cache[i];
- int len = ce_namelen(ce);
+ for (i = o->pos; i < o->src_index->cache_nr; i++) {
+ struct cache_entry *ce2 = o->src_index->cache[i];
+ int len = ce_namelen(ce2);
if (len < namelen ||
- strncmp(ce->name, ce->name, namelen) ||
- ce->name[namelen] != '/')
+ strncmp(ce->name, ce2->name, namelen) ||
+ ce2->name[namelen] != '/')
break;
/*
- * ce->name is an entry in the subdirectory.
+ * ce2->name is an entry in the subdirectory.
*/
- if (!ce_stage(ce)) {
- if (verify_uptodate(ce, o))
+ if (!ce_stage(ce2)) {
+ if (verify_uptodate(ce2, o))
return -1;
- add_entry(o, ce, CE_REMOVE, 0);
+ add_entry(o, ce2, CE_REMOVE, 0);
}
cnt++;
}
@@ -588,7 +584,7 @@ static int verify_absent(struct cache_entry *ce, const char *action,
return 0;
if (!lstat(ce->name, &st)) {
- int cnt;
+ int ret;
int dtype = ce_to_dtype(ce);
struct cache_entry *result;
@@ -616,13 +612,15 @@ static int verify_absent(struct cache_entry *ce, const char *action,
* files that are in "foo/" we would lose
* it.
*/
- cnt = verify_clean_subdirectory(ce, action, o);
+ ret = verify_clean_subdirectory(ce, action, o);
+ if (ret < 0)
+ return ret;
/*
* If this removed entries from the index,
* what that means is:
*
- * (1) the caller unpack_trees_rec() saw path/foo
+ * (1) the caller unpack_callback() saw path/foo
* in the index, and it has not removed it because
* it thinks it is handling 'path' as blob with
* D/F conflict;
@@ -635,7 +633,7 @@ static int verify_absent(struct cache_entry *ce, const char *action,
* We need to increment it by the number of
* deleted entries here.
*/
- o->pos += cnt;
+ o->pos += ret;
return 0;
}
diff --git a/userdiff.c b/userdiff.c
new file mode 100644
index 0000000000..3681062ebf
--- /dev/null
+++ b/userdiff.c
@@ -0,0 +1,167 @@
+#include "userdiff.h"
+#include "cache.h"
+#include "attr.h"
+
+static struct userdiff_driver *drivers;
+static int ndrivers;
+static int drivers_alloc;
+
+#define FUNCNAME(name, pattern) \
+ { name, NULL, -1, { pattern, REG_EXTENDED } }
+static struct userdiff_driver builtin_drivers[] = {
+FUNCNAME("html", "^[ \t]*(<[Hh][1-6][ \t].*>.*)$"),
+FUNCNAME("java",
+ "!^[ \t]*(catch|do|for|if|instanceof|new|return|switch|throw|while)\n"
+ "^[ \t]*(([ \t]*[A-Za-z_][A-Za-z_0-9]*){2,}[ \t]*\\([^;]*)$"),
+FUNCNAME("objc",
+ /* Negate C statements that can look like functions */
+ "!^[ \t]*(do|for|if|else|return|switch|while)\n"
+ /* Objective-C methods */
+ "^[ \t]*([-+][ \t]*\\([ \t]*[A-Za-z_][A-Za-z_0-9* \t]*\\)[ \t]*[A-Za-z_].*)$\n"
+ /* C functions */
+ "^[ \t]*(([ \t]*[A-Za-z_][A-Za-z_0-9]*){2,}[ \t]*\\([^;]*)$\n"
+ /* Objective-C class/protocol definitions */
+ "^(@(implementation|interface|protocol)[ \t].*)$"),
+FUNCNAME("pascal",
+ "^((procedure|function|constructor|destructor|interface|"
+ "implementation|initialization|finalization)[ \t]*.*)$"
+ "\n"
+ "^(.*=[ \t]*(class|record).*)$"),
+FUNCNAME("php", "^[\t ]*((function|class).*)"),
+FUNCNAME("python", "^[ \t]*((class|def)[ \t].*)$"),
+FUNCNAME("ruby", "^[ \t]*((class|module|def)[ \t].*)$"),
+FUNCNAME("bibtex", "(@[a-zA-Z]{1,}[ \t]*\\{{0,1}[ \t]*[^ \t\"@',\\#}{~%]*).*$"),
+FUNCNAME("tex", "^(\\\\((sub)*section|chapter|part)\\*{0,1}\\{.*)$"),
+{ "default", NULL, -1, { NULL, 0 } },
+};
+#undef FUNCNAME
+
+static struct userdiff_driver driver_true = {
+ "diff=true",
+ NULL,
+ 0,
+ { NULL, 0 }
+};
+
+static struct userdiff_driver driver_false = {
+ "!diff",
+ NULL,
+ 1,
+ { NULL, 0 }
+};
+
+static struct userdiff_driver *userdiff_find_by_namelen(const char *k, int len)
+{
+ int i;
+ for (i = 0; i < ndrivers; i++) {
+ struct userdiff_driver *drv = drivers + i;
+ if (!strncmp(drv->name, k, len) && !drv->name[len])
+ return drv;
+ }
+ for (i = 0; i < ARRAY_SIZE(builtin_drivers); i++) {
+ struct userdiff_driver *drv = builtin_drivers + i;
+ if (!strncmp(drv->name, k, len) && !drv->name[len])
+ return drv;
+ }
+ return NULL;
+}
+
+static struct userdiff_driver *parse_driver(const char *var,
+ const char *value, const char *type)
+{
+ struct userdiff_driver *drv;
+ const char *dot;
+ const char *name;
+ int namelen;
+
+ if (prefixcmp(var, "diff."))
+ return NULL;
+ dot = strrchr(var, '.');
+ if (dot == var + 4)
+ return NULL;
+ if (strcmp(type, dot+1))
+ return NULL;
+
+ name = var + 5;
+ namelen = dot - name;
+ drv = userdiff_find_by_namelen(name, namelen);
+ if (!drv) {
+ ALLOC_GROW(drivers, ndrivers+1, drivers_alloc);
+ drv = &drivers[ndrivers++];
+ memset(drv, 0, sizeof(*drv));
+ drv->name = xmemdupz(name, namelen);
+ drv->binary = -1;
+ }
+ return drv;
+}
+
+static int parse_funcname(struct userdiff_funcname *f, const char *k,
+ const char *v, int cflags)
+{
+ if (git_config_string(&f->pattern, k, v) < 0)
+ return -1;
+ f->cflags = cflags;
+ return 1;
+}
+
+static int parse_string(const char **d, const char *k, const char *v)
+{
+ if (git_config_string(d, k, v) < 0)
+ return -1;
+ return 1;
+}
+
+static int parse_tristate(int *b, const char *k, const char *v)
+{
+ if (v && !strcasecmp(v, "auto"))
+ *b = -1;
+ else
+ *b = git_config_bool(k, v);
+ return 1;
+}
+
+int userdiff_config(const char *k, const char *v)
+{
+ struct userdiff_driver *drv;
+
+ if ((drv = parse_driver(k, v, "funcname")))
+ return parse_funcname(&drv->funcname, k, v, 0);
+ if ((drv = parse_driver(k, v, "xfuncname")))
+ return parse_funcname(&drv->funcname, k, v, REG_EXTENDED);
+ if ((drv = parse_driver(k, v, "binary")))
+ return parse_tristate(&drv->binary, k, v);
+ if ((drv = parse_driver(k, v, "command")))
+ return parse_string(&drv->external, k, v);
+ if ((drv = parse_driver(k, v, "textconv")))
+ return parse_string(&drv->textconv, k, v);
+
+ return 0;
+}
+
+struct userdiff_driver *userdiff_find_by_name(const char *name) {
+ int len = strlen(name);
+ return userdiff_find_by_namelen(name, len);
+}
+
+struct userdiff_driver *userdiff_find_by_path(const char *path)
+{
+ static struct git_attr *attr;
+ struct git_attr_check check;
+
+ if (!attr)
+ attr = git_attr("diff", 4);
+ check.attr = attr;
+
+ if (!path)
+ return NULL;
+ if (git_checkattr(path, 1, &check))
+ return NULL;
+
+ if (ATTR_TRUE(check.value))
+ return &driver_true;
+ if (ATTR_FALSE(check.value))
+ return &driver_false;
+ if (ATTR_UNSET(check.value))
+ return NULL;
+ return userdiff_find_by_name(check.value);
+}
diff --git a/userdiff.h b/userdiff.h
new file mode 100644
index 0000000000..ba2945770b
--- /dev/null
+++ b/userdiff.h
@@ -0,0 +1,21 @@
+#ifndef USERDIFF_H
+#define USERDIFF_H
+
+struct userdiff_funcname {
+ const char *pattern;
+ int cflags;
+};
+
+struct userdiff_driver {
+ const char *name;
+ const char *external;
+ int binary;
+ struct userdiff_funcname funcname;
+ const char *textconv;
+};
+
+int userdiff_config(const char *k, const char *v);
+struct userdiff_driver *userdiff_find_by_name(const char *name);
+struct userdiff_driver *userdiff_find_by_path(const char *path);
+
+#endif /* USERDIFF */
diff --git a/walker.c b/walker.c
index 6b4cf70c6a..679adab6a0 100644
--- a/walker.c
+++ b/walker.c
@@ -191,7 +191,7 @@ static int interpret_target(struct walker *walker, char *target, unsigned char *
if (!get_sha1_hex(target, sha1))
return 0;
if (!check_ref_format(target)) {
- struct ref *ref = alloc_ref_from_str(target);
+ struct ref *ref = alloc_ref(target);
if (!walker->fetch_ref(walker, ref)) {
hashcpy(sha1, ref->old_sha1);
free(ref);
diff --git a/wt-status.c b/wt-status.c
index d2eac36aea..96ff2f8f56 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -185,31 +185,12 @@ static void wt_status_print_changed_cb(struct diff_queue_struct *q,
wt_status_print_trailer(s);
}
-static void wt_status_print_initial(struct wt_status *s)
-{
- int i;
- struct strbuf buf = STRBUF_INIT;
-
- if (active_nr) {
- s->commitable = 1;
- wt_status_print_cached_header(s);
- }
- for (i = 0; i < active_nr; i++) {
- color_fprintf(s->fp, color(WT_STATUS_HEADER), "#\t");
- color_fprintf_ln(s->fp, color(WT_STATUS_UPDATED), "new file: %s",
- quote_path(active_cache[i]->name, -1,
- &buf, s->prefix));
- }
- if (active_nr)
- wt_status_print_trailer(s);
- strbuf_release(&buf);
-}
-
static void wt_status_print_updated(struct wt_status *s)
{
struct rev_info rev;
init_revisions(&rev, NULL);
- setup_revisions(0, NULL, &rev, s->reference);
+ setup_revisions(0, NULL, &rev,
+ s->is_initial ? EMPTY_TREE_SHA1_HEX : s->reference);
rev.diffopt.output_format |= DIFF_FORMAT_CALLBACK;
rev.diffopt.format_callback = wt_status_print_updated_cb;
rev.diffopt.format_callback_data = s;
@@ -277,20 +258,9 @@ static void wt_status_print_untracked(struct wt_status *s)
read_directory(&dir, ".", "", 0, NULL);
for(i = 0; i < dir.nr; i++) {
- /* check for matching entry, which is unmerged; lifted from
- * builtin-ls-files:show_other_files */
struct dir_entry *ent = dir.entries[i];
- int pos = cache_name_pos(ent->name, ent->len);
- struct cache_entry *ce;
- if (0 <= pos)
- die("bug in wt_status_print_untracked");
- pos = -pos - 1;
- if (pos < active_nr) {
- ce = active_cache[pos];
- if (ce_namelen(ce) == ent->len &&
- !memcmp(ce->name, ent->name, ent->len))
- continue;
- }
+ if (!cache_name_is_other(ent->name, ent->len))
+ continue;
if (!shown_header) {
s->workdir_untracked = 1;
wt_status_print_untracked_header(s);
@@ -309,11 +279,21 @@ static void wt_status_print_verbose(struct wt_status *s)
struct rev_info rev;
init_revisions(&rev, NULL);
- setup_revisions(0, NULL, &rev, s->reference);
+ DIFF_OPT_SET(&rev.diffopt, ALLOW_TEXTCONV);
+ setup_revisions(0, NULL, &rev,
+ s->is_initial ? EMPTY_TREE_SHA1_HEX : s->reference);
rev.diffopt.output_format |= DIFF_FORMAT_PATCH;
rev.diffopt.detect_rename = 1;
rev.diffopt.file = s->fp;
rev.diffopt.close_file = 0;
+ /*
+ * If we're not going to stdout, then we definitely don't
+ * want color, since we are going to the commit message
+ * file (and even the "auto" setting won't work, since it
+ * will have checked isatty on stdout).
+ */
+ if (s->fp != stdout)
+ DIFF_OPT_CLR(&rev.diffopt, COLOR_DIFF);
run_diff_index(&rev, 1);
}
@@ -362,12 +342,9 @@ void wt_status_print(struct wt_status *s)
color_fprintf_ln(s->fp, color(WT_STATUS_HEADER), "#");
color_fprintf_ln(s->fp, color(WT_STATUS_HEADER), "# Initial commit");
color_fprintf_ln(s->fp, color(WT_STATUS_HEADER), "#");
- wt_status_print_initial(s);
- }
- else {
- wt_status_print_updated(s);
}
+ wt_status_print_updated(s);
wt_status_print_changed(s);
if (wt_status_submodule_summary)
wt_status_print_submodule_summary(s);
@@ -376,7 +353,7 @@ void wt_status_print(struct wt_status *s)
else if (s->commitable)
fprintf(s->fp, "# Untracked files not listed (use -u option to show untracked files)\n");
- if (s->verbose && !s->is_initial)
+ if (s->verbose)
wt_status_print_verbose(s);
if (!s->commitable) {
if (s->amend)
@@ -433,5 +410,5 @@ int git_status_config(const char *k, const char *v, void *cb)
return error("Invalid untracked files mode '%s'", v);
return 0;
}
- return git_color_default_config(k, v, cb);
+ return git_diff_ui_config(k, v, cb);
}
diff --git a/xdiff-interface.c b/xdiff-interface.c
index f3f6db3297..d782f06d99 100644
--- a/xdiff-interface.c
+++ b/xdiff-interface.c
@@ -1,6 +1,9 @@
#include "cache.h"
#include "xdiff-interface.h"
-#include "strbuf.h"
+#include "xdiff/xtypes.h"
+#include "xdiff/xdiffi.h"
+#include "xdiff/xemit.h"
+#include "xdiff/xmacros.h"
struct xdiff_emit_state {
xdiff_emit_consume_fn consume;
@@ -153,6 +156,50 @@ int xdi_diff_outf(mmfile_t *mf1, mmfile_t *mf2,
return ret;
}
+struct xdiff_emit_hunk_state {
+ xdiff_emit_hunk_consume_fn consume;
+ void *consume_callback_data;
+};
+
+static int process_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
+ xdemitconf_t const *xecfg)
+{
+ long s1, s2, same, p_next, t_next;
+ xdchange_t *xch, *xche;
+ struct xdiff_emit_hunk_state *state = ecb->priv;
+ xdiff_emit_hunk_consume_fn fn = state->consume;
+ void *consume_callback_data = state->consume_callback_data;
+
+ for (xch = xscr; xch; xch = xche->next) {
+ xche = xdl_get_hunk(xch, xecfg);
+
+ s1 = XDL_MAX(xch->i1 - xecfg->ctxlen, 0);
+ s2 = XDL_MAX(xch->i2 - xecfg->ctxlen, 0);
+ same = s2 + XDL_MAX(xch->i1 - s1, 0);
+ p_next = xche->i1 + xche->chg1;
+ t_next = xche->i2 + xche->chg2;
+
+ fn(consume_callback_data, same, p_next, t_next);
+ }
+ return 0;
+}
+
+int xdi_diff_hunks(mmfile_t *mf1, mmfile_t *mf2,
+ xdiff_emit_hunk_consume_fn fn, void *consume_callback_data,
+ xpparam_t const *xpp, xdemitconf_t *xecfg)
+{
+ struct xdiff_emit_hunk_state state;
+ xdemitcb_t ecb;
+
+ memset(&state, 0, sizeof(state));
+ memset(&ecb, 0, sizeof(ecb));
+ state.consume = fn;
+ state.consume_callback_data = consume_callback_data;
+ xecfg->emit_func = (void (*)())process_diff;
+ ecb.priv = &state;
+ return xdi_diff(mf1, mf2, xpp, xecfg, &ecb);
+}
+
int read_mmfile(mmfile_t *ptr, const char *filename)
{
struct stat st;
@@ -281,4 +328,3 @@ int git_xmerge_config(const char *var, const char *value, void *cb)
}
return git_default_config(var, value, cb);
}
-
diff --git a/xdiff-interface.h b/xdiff-interface.h
index eaf9cd3498..7352b9a9c2 100644
--- a/xdiff-interface.h
+++ b/xdiff-interface.h
@@ -4,12 +4,16 @@
#include "xdiff/xdiff.h"
typedef void (*xdiff_emit_consume_fn)(void *, char *, unsigned long);
+typedef void (*xdiff_emit_hunk_consume_fn)(void *, long, long, long);
int xdi_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdemitconf_t const *xecfg, xdemitcb_t *ecb);
int xdi_diff_outf(mmfile_t *mf1, mmfile_t *mf2,
xdiff_emit_consume_fn fn, void *consume_callback_data,
xpparam_t const *xpp,
xdemitconf_t const *xecfg, xdemitcb_t *xecb);
+int xdi_diff_hunks(mmfile_t *mf1, mmfile_t *mf2,
+ xdiff_emit_hunk_consume_fn fn, void *consume_callback_data,
+ xpparam_t const *xpp, xdemitconf_t *xecfg);
int parse_hunk_header(char *line, int len,
int *ob, int *on,
int *nb, int *nn);
diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h
index deebe02cd3..361f802319 100644
--- a/xdiff/xdiff.h
+++ b/xdiff/xdiff.h
@@ -84,9 +84,11 @@ typedef long (*find_func_t)(const char *line, long line_len, char *buffer, long
typedef struct s_xdemitconf {
long ctxlen;
+ long interhunkctxlen;
unsigned long flags;
find_func_t find_func;
void *find_func_priv;
+ void (*emit_func)();
} xdemitconf_t;
typedef struct s_bdiffparam {
diff --git a/xdiff/xdiffi.c b/xdiff/xdiffi.c
index 1bad8462fb..9d0324a38c 100644
--- a/xdiff/xdiffi.c
+++ b/xdiff/xdiffi.c
@@ -538,6 +538,8 @@ int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
xdemitconf_t const *xecfg, xdemitcb_t *ecb) {
xdchange_t *xscr;
xdfenv_t xe;
+ emit_func_t ef = xecfg->emit_func ?
+ (emit_func_t)xecfg->emit_func : xdl_emit_diff;
if (xdl_do_diff(mf1, mf2, xpp, &xe) < 0) {
@@ -551,7 +553,7 @@ int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
return -1;
}
if (xscr) {
- if (xdl_emit_diff(&xe, xscr, ecb, xecfg) < 0) {
+ if (ef(&xe, xscr, ecb, xecfg) < 0) {
xdl_free_script(xscr);
xdl_free_env(&xe);
diff --git a/xdiff/xemit.c b/xdiff/xemit.c
index d3d9c845c6..05bfa41f10 100644
--- a/xdiff/xemit.c
+++ b/xdiff/xemit.c
@@ -27,7 +27,6 @@
static long xdl_get_rec(xdfile_t *xdf, long ri, char const **rec);
static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t *ecb);
-static xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg);
@@ -58,11 +57,12 @@ static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t *
* Starting at the passed change atom, find the latest change atom to be included
* inside the differential hunk according to the specified configuration.
*/
-static xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg) {
+xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg) {
xdchange_t *xch, *xchp;
+ long max_common = 2 * xecfg->ctxlen + xecfg->interhunkctxlen;
for (xchp = xscr, xch = xscr->next; xch; xchp = xch, xch = xch->next)
- if (xch->i1 - (xchp->i1 + xchp->chg1) > 2 * xecfg->ctxlen)
+ if (xch->i1 - (xchp->i1 + xchp->chg1) > max_common)
break;
return xchp;
diff --git a/xdiff/xemit.h b/xdiff/xemit.h
index 440a7390fa..c2e2e83027 100644
--- a/xdiff/xemit.h
+++ b/xdiff/xemit.h
@@ -24,7 +24,10 @@
#define XEMIT_H
+typedef int (*emit_func_t)(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
+ xdemitconf_t const *xecfg);
+xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg);
int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
xdemitconf_t const *xecfg);
diff --git a/xdiff/xprepare.c b/xdiff/xprepare.c
index e87ab57c65..a43aa72cd0 100644
--- a/xdiff/xprepare.c
+++ b/xdiff/xprepare.c
@@ -23,10 +23,9 @@
#include "xinclude.h"
-
#define XDL_KPDIS_RUN 4
#define XDL_MAX_EQLIMIT 1024
-
+#define XDL_SIMSCAN_WINDOW 100
typedef struct s_xdlclass {
@@ -313,6 +312,18 @@ static int xdl_clean_mmatch(char const *dis, long i, long s, long e) {
long r, rdis0, rpdis0, rdis1, rpdis1;
/*
+ * Limits the window the is examined during the similar-lines
+ * scan. The loops below stops when dis[i - r] == 1 (line that
+ * has no match), but there are corner cases where the loop
+ * proceed all the way to the extremities by causing huge
+ * performance penalties in case of big files.
+ */
+ if (i - s > XDL_SIMSCAN_WINDOW)
+ s = i - XDL_SIMSCAN_WINDOW;
+ if (e - i > XDL_SIMSCAN_WINDOW)
+ e = i + XDL_SIMSCAN_WINDOW;
+
+ /*
* Scans the lines before 'i' to find a run of lines that either
* have no match (dis[j] == 0) or have multiple matches (dis[j] > 1).
* Note that we always call this function with dis[i] > 1, so the