summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/Makefile6
-rw-r--r--Documentation/RelNotes-1.6.1.4.txt25
-rw-r--r--Documentation/RelNotes-1.6.2.5.txt21
-rw-r--r--Documentation/RelNotes-1.6.3.1.txt10
-rw-r--r--Documentation/RelNotes-1.6.3.2.txt61
-rw-r--r--Documentation/RelNotes-1.6.3.txt16
-rw-r--r--Documentation/RelNotes-1.6.4.txt93
-rw-r--r--Documentation/SubmittingPatches14
-rw-r--r--Documentation/config.txt87
-rw-r--r--Documentation/git-add.txt11
-rw-r--r--Documentation/git-am.txt28
-rw-r--r--Documentation/git-apply.txt2
-rw-r--r--Documentation/git-branch.txt1
-rw-r--r--Documentation/git-cat-file.txt4
-rw-r--r--Documentation/git-check-ref-format.txt6
-rw-r--r--Documentation/git-clean.txt13
-rw-r--r--Documentation/git-clone.txt2
-rw-r--r--Documentation/git-config.txt5
-rw-r--r--Documentation/git-difftool.txt2
-rw-r--r--Documentation/git-format-patch.txt42
-rw-r--r--Documentation/git-ls-tree.txt4
-rw-r--r--Documentation/git-mergetool.txt2
-rw-r--r--Documentation/git-mktree.txt19
-rw-r--r--Documentation/git-rebase.txt3
-rw-r--r--Documentation/git-repack.txt7
-rw-r--r--Documentation/git-rev-parse.txt37
-rw-r--r--Documentation/git-send-email.txt40
-rw-r--r--Documentation/git-show-branch.txt26
-rw-r--r--Documentation/git-stash.txt34
-rw-r--r--Documentation/git-submodule.txt14
-rw-r--r--Documentation/git-svn.txt8
-rw-r--r--Documentation/git-update-server-info.txt6
-rw-r--r--Documentation/git.txt14
-rw-r--r--Documentation/gittutorial.txt4
-rw-r--r--Documentation/merge-config.txt2
-rw-r--r--Documentation/merge-options.txt3
-rw-r--r--Documentation/technical/api-builtin.txt2
-rw-r--r--Documentation/technical/api-parse-options.txt23
-rw-r--r--Documentation/user-manual.txt4
-rwxr-xr-xGIT-VERSION-GEN2
-rw-r--r--Makefile101
l---------RelNotes2
-rw-r--r--alias.c10
-rw-r--r--alloc.c2
-rw-r--r--archive-tar.c2
-rw-r--r--archive.c2
-rw-r--r--attr.c4
-rw-r--r--bisect.c437
-rw-r--r--bisect.h9
-rw-r--r--builtin-add.c63
-rw-r--r--builtin-apply.c35
-rw-r--r--builtin-archive.c3
-rw-r--r--builtin-bisect--helper.c17
-rw-r--r--builtin-blame.c36
-rw-r--r--builtin-branch.c5
-rw-r--r--builtin-cat-file.c6
-rw-r--r--builtin-check-attr.c4
-rw-r--r--builtin-checkout-index.c6
-rw-r--r--builtin-checkout.c31
-rw-r--r--builtin-clean.c3
-rw-r--r--builtin-clone.c39
-rw-r--r--builtin-commit.c9
-rw-r--r--builtin-config.c5
-rw-r--r--builtin-count-objects.c2
-rw-r--r--builtin-describe.c6
-rw-r--r--builtin-fast-export.c2
-rw-r--r--builtin-fetch-pack.c21
-rw-r--r--builtin-fetch.c32
-rw-r--r--builtin-fmt-merge-msg.c5
-rw-r--r--builtin-for-each-ref.c9
-rw-r--r--builtin-fsck.c2
-rw-r--r--builtin-gc.c3
-rw-r--r--builtin-grep.c418
-rw-r--r--builtin-help.c27
-rw-r--r--builtin-log.c268
-rw-r--r--builtin-ls-files.c4
-rw-r--r--builtin-mailinfo.c10
-rw-r--r--builtin-merge-base.c2
-rw-r--r--builtin-merge-file.c2
-rw-r--r--builtin-merge-recursive.c5
-rw-r--r--builtin-merge.c6
-rw-r--r--builtin-mktree.c190
-rw-r--r--builtin-mv.c3
-rw-r--r--builtin-name-rev.c2
-rw-r--r--builtin-pack-refs.c2
-rw-r--r--builtin-prune-packed.c5
-rw-r--r--builtin-prune.c6
-rw-r--r--builtin-push.c2
-rw-r--r--builtin-receive-pack.c34
-rw-r--r--builtin-remote.c38
-rw-r--r--builtin-rerere.c2
-rw-r--r--builtin-reset.c2
-rw-r--r--builtin-rev-list.c63
-rw-r--r--builtin-rev-parse.c19
-rw-r--r--builtin-revert.c6
-rw-r--r--builtin-rm.c3
-rw-r--r--builtin-send-pack.c21
-rw-r--r--builtin-shortlog.c2
-rw-r--r--builtin-show-branch.c167
-rw-r--r--builtin-symbolic-ref.c3
-rw-r--r--builtin-tag.c7
-rw-r--r--builtin-update-index.c6
-rw-r--r--builtin-update-ref.c3
-rw-r--r--builtin-verify-tag.c2
-rw-r--r--builtin.h1
-rw-r--r--bundle.c2
-rw-r--r--cache.h11
-rw-r--r--combine-diff.c38
-rw-r--r--commit.c20
-rw-r--r--commit.h2
-rw-r--r--compat/basename.c15
-rw-r--r--compat/mingw.c21
-rw-r--r--compat/mingw.h4
-rw-r--r--compat/mkstemps.c70
-rw-r--r--config.c42
-rw-r--r--config.mak.in3
-rw-r--r--configure.ac22
-rw-r--r--connect.c20
-rwxr-xr-xcontrib/completion/git-completion.bash265
-rw-r--r--contrib/convert-objects/convert-objects.c6
-rwxr-xr-x[-rw-r--r--]contrib/hooks/post-receive-email4
-rw-r--r--ctype.c2
-rw-r--r--daemon.c38
-rw-r--r--date.c4
-rw-r--r--decorate.c8
-rw-r--r--diff-lib.c2
-rw-r--r--diff-no-index.c2
-rw-r--r--diff.c45
-rw-r--r--dir.c10
-rw-r--r--entry.c2
-rw-r--r--environment.c4
-rw-r--r--fast-import.c18
-rwxr-xr-xgit-add--interactive.perl95
-rwxr-xr-xgit-am.sh6
-rwxr-xr-xgit-bisect.sh180
-rw-r--r--git-compat-util.h38
-rwxr-xr-xgit-cvsexportcommit.perl49
-rwxr-xr-xgit-difftool.perl6
-rw-r--r--git-gui/Makefile7
-rwxr-xr-xgit-gui/git-gui.sh78
-rw-r--r--git-gui/lib/branch_delete.tcl4
-rw-r--r--git-gui/lib/checkout_op.tcl43
-rw-r--r--git-gui/lib/choose_repository.tcl33
-rw-r--r--git-gui/lib/commit.tcl35
-rw-r--r--git-gui/lib/diff.tcl9
-rw-r--r--git-gui/lib/mergetool.tcl4
-rw-r--r--git-gui/lib/remote_branch_delete.tcl4
-rw-r--r--git-gui/lib/shortcut.tcl2
-rw-r--r--git-gui/lib/tools.tcl2
-rw-r--r--git-gui/po/de.po12
-rw-r--r--git-gui/po/fr.po202
-rw-r--r--git-gui/po/git-gui.pot9
-rw-r--r--git-gui/po/hu.po12
-rw-r--r--git-gui/po/it.po12
-rw-r--r--git-gui/po/ja.po12
-rw-r--r--git-gui/po/nb.po12
-rw-r--r--git-gui/po/ru.po1390
-rw-r--r--git-gui/po/sv.po12
-rw-r--r--git-gui/po/zh_cn.po10
-rw-r--r--git-gui/windows/git-gui.sh7
-rwxr-xr-xgit-merge-one-file.sh11
-rw-r--r--git-mergetool--lib.sh31
-rwxr-xr-xgit-rebase--interactive.sh2
-rwxr-xr-xgit-send-email.perl37
-rwxr-xr-xgit-sh-setup.sh28
-rwxr-xr-xgit-stash.sh4
-rwxr-xr-xgit-submodule.sh38
-rwxr-xr-xgit-svn.perl60
-rw-r--r--git.c9
-rw-r--r--gitk-git/gitk321
-rw-r--r--gitk-git/po/ru.po1085
-rwxr-xr-xgitweb/gitweb.perl99
-rw-r--r--graph.c62
-rw-r--r--grep.c22
-rw-r--r--grep.h28
-rw-r--r--hash-object.c3
-rw-r--r--http-push.c50
-rw-r--r--http-walker.c14
-rw-r--r--imap-send.c54
-rw-r--r--ll-merge.c13
-rw-r--r--lockfile.c6
-rw-r--r--log-tree.c1
-rw-r--r--merge-index.c42
-rw-r--r--merge-recursive.c19
-rw-r--r--mktree.c131
-rw-r--r--object.c11
-rw-r--r--pack-refs.c2
-rw-r--r--parse-options.c160
-rw-r--r--parse-options.h32
-rw-r--r--path.c16
-rw-r--r--perl/Git.pm4
-rw-r--r--pretty.c4
-rw-r--r--progress.c8
-rw-r--r--reflog-walk.c2
-rw-r--r--refs.c25
-rw-r--r--refs.h2
-rw-r--r--remote.c23
-rw-r--r--remote.h2
-rw-r--r--rerere.c2
-rw-r--r--revision.c33
-rw-r--r--revision.h5
-rw-r--r--run-command.c2
-rw-r--r--send-pack.h1
-rw-r--r--server-info.c6
-rw-r--r--sha1_file.c15
-rw-r--r--symlinks.c6
-rw-r--r--t/annotate-tests.sh5
-rw-r--r--t/lib-git-svn.sh15
-rw-r--r--t/lib-httpd.sh6
-rwxr-xr-xt/t0040-parse-options.sh75
-rwxr-xr-xt/t1010-mktree.sh71
-rwxr-xr-xt/t2014-switch.sh28
-rwxr-xr-xt/t3031-merge-criscross.sh95
-rwxr-xr-xt/t3400-rebase.sh31
-rwxr-xr-xt/t3700-add.sh12
-rwxr-xr-xt/t3701-add-interactive.sh38
-rwxr-xr-xt/t3702-add-edit.sh121
-rwxr-xr-xt/t3900-i18n-commit.sh46
-rw-r--r--t/t3900/ISO8859-1.txt (renamed from t/t3900/ISO-8859-1.txt)0
-rw-r--r--t/t3900/eucJP.txt (renamed from t/t3900/EUCJP.txt)0
-rwxr-xr-xt/t3901-i18n-patch.sh40
-rw-r--r--t/t4013/diff.log_--decorate_--all6
-rwxr-xr-xt/t4014-format-patch.sh11
-rwxr-xr-xt/t4018-diff-funcname.sh2
-rwxr-xr-xt/t4020-diff-external.sh9
-rwxr-xr-xt/t4021-format-patch-numbered.sh13
-rwxr-xr-xt/t4027-diff-submodule.sh39
-rwxr-xr-xt/t4029-diff-trailing-space.sh2
-rwxr-xr-xt/t4118-apply-empty-context.sh4
-rwxr-xr-xt/t4131-apply-fake-ancestor.sh42
-rwxr-xr-xt/t4200-rerere.sh4
-rwxr-xr-xt/t4202-log.sh8
-rw-r--r--t/t5100/rfc2047-samples.mbox32
-rw-r--r--t/t5100/sample.mbox8
-rwxr-xr-xt/t5500-fetch-pack.sh276
-rwxr-xr-xt/t5505-remote.sh10
-rwxr-xr-xt/t5701-clone-local.sh4
-rwxr-xr-xt/t6023-merge-file.sh6
-rwxr-xr-xt/t6030-bisect-porcelain.sh13
-rwxr-xr-xt/t6040-tracking-info.sh14
-rwxr-xr-xt/t6200-fmt-merge-msg.sh32
-rwxr-xr-xt/t7002-grep.sh13
-rwxr-xr-xt/t7201-co.sh8
-rwxr-xr-xt/t7405-submodule-merge.sh6
-rwxr-xr-xt/t7406-submodule-reference.sh81
-rwxr-xr-xt/t7500-commit.sh10
-rwxr-xr-xt/t7700-repack.sh2
-rwxr-xr-xt/t7800-difftool.sh5
-rwxr-xr-xt/t8003-blame.sh15
-rwxr-xr-xt/t8005-blame-i18n.sh40
-rw-r--r--t/t8005/cp1251.txt2
-rw-r--r--t/t8005/iso8859-5.txt2
-rwxr-xr-xt/t9001-send-email.sh10
-rwxr-xr-xt/t9100-git-svn-basic.sh14
-rwxr-xr-xt/t9101-git-svn-props.sh38
-rwxr-xr-xt/t9102-git-svn-deep-rmdir.sh4
-rwxr-xr-xt/t9103-git-svn-tracked-directory-removed.sh8
-rwxr-xr-xt/t9104-git-svn-follow-parent.sh40
-rwxr-xr-xt/t9105-git-svn-commit-diff.sh8
-rwxr-xr-xt/t9106-git-svn-commit-diff-clobber.sh14
-rwxr-xr-xt/t9107-git-svn-migrate.sh2
-rwxr-xr-xt/t9108-git-svn-glob.sh26
-rwxr-xr-xt/t9109-git-svn-multi-glob.sh44
-rwxr-xr-xt/t9113-git-svn-dcommit-new-file.sh2
-rwxr-xr-xt/t9114-git-svn-dcommit-merge.sh6
-rwxr-xr-xt/t9116-git-svn-log.sh2
-rwxr-xr-xt/t9117-git-svn-init-clone.sh2
-rwxr-xr-xt/t9118-git-svn-funky-branch-names.sh8
-rwxr-xr-xt/t9119-git-svn-info.sh30
-rwxr-xr-xt/t9120-git-svn-clone-with-percent-escapes.sh19
-rwxr-xr-xt/t9122-git-svn-author.sh12
-rwxr-xr-xt/t9123-git-svn-rebuild-with-rewriteroot.sh2
-rwxr-xr-xt/t9124-git-svn-dcommit-auto-props.sh30
-rwxr-xr-xt/t9125-git-svn-multi-glob-branch-names.sh6
-rwxr-xr-xt/t9127-git-svn-partial-rebuild.sh14
-rwxr-xr-xt/t9128-git-svn-cmd-branch.sh18
-rwxr-xr-xt/t9129-git-svn-i18n-commitencoding.sh12
-rwxr-xr-xt/t9130-git-svn-authors-file.sh6
-rwxr-xr-xt/t9133-git-svn-nested-git-repo.sh32
-rwxr-xr-xt/t9134-git-svn-ignore-paths.sh32
-rwxr-xr-xt/t9137-git-svn-dcommit-clobber-series.sh8
-rwxr-xr-xt/t9138-git-svn-authors-prog.sh69
-rwxr-xr-xt/t9139-git-svn-non-utf8-commitencoding.sh47
-rwxr-xr-xt/t9200-git-cvsexportcommit.sh18
-rwxr-xr-xt/t9301-fast-export.sh2
-rwxr-xr-xt/t9500-gitweb-standalone-no-errors.sh2
-rwxr-xr-xt/t9700-perl-git.sh4
-rwxr-xr-xt/t9700/test.pl23
-rw-r--r--t/test-lib.sh23
-rwxr-xr-xtemplates/hooks--pre-commit.sample27
-rwxr-xr-xtemplates/hooks--update.sample10
-rw-r--r--test-genrandom.c2
-rw-r--r--test-parse-options.c17
-rw-r--r--transport.c60
-rw-r--r--transport.h1
-rw-r--r--unpack-trees.c2
-rw-r--r--utf8.c2
-rw-r--r--wrapper.c16
-rw-r--r--wt-status.c2
-rw-r--r--xdiff/xmerge.c31
300 files changed, 7703 insertions, 2849 deletions
diff --git a/Documentation/Makefile b/Documentation/Makefile
index e18242a..7a8037f 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -240,7 +240,7 @@ $(MAN_HTML): %.html : %.txt
mv $@+ $@
user-manual.xml: user-manual.txt user-manual.conf
- $(QUIET_ASCIIDOC)$(ASCIIDOC) -b docbook -d book $<
+ $(QUIET_ASCIIDOC)$(ASCIIDOC) $(ASCIIDOC_EXTRA) -b docbook -d book $<
technical/api-index.txt: technical/api-index-skel.txt \
technical/api-index.sh $(patsubst %,%.txt,$(API_DOCS))
@@ -293,13 +293,13 @@ howto-index.txt: howto-index.sh $(wildcard howto/*.txt)
mv $@+ $@
$(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt
- $(QUIET_ASCIIDOC)$(ASCIIDOC) -b xhtml11 $*.txt
+ $(QUIET_ASCIIDOC)$(ASCIIDOC) $(ASCIIDOC_EXTRA) -b xhtml11 $*.txt
WEBDOC_DEST = /pub/software/scm/git/docs
$(patsubst %.txt,%.html,$(wildcard howto/*.txt)): %.html : %.txt
$(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
- sed -e '1,/^$$/d' $< | $(ASCIIDOC) -b xhtml11 - >$@+ && \
+ sed -e '1,/^$$/d' $< | $(ASCIIDOC) $(ASCIIDOC_EXTRA) -b xhtml11 - >$@+ && \
mv $@+ $@
install-webdoc : html
diff --git a/Documentation/RelNotes-1.6.1.4.txt b/Documentation/RelNotes-1.6.1.4.txt
index a9f1a6b..0ce6316 100644
--- a/Documentation/RelNotes-1.6.1.4.txt
+++ b/Documentation/RelNotes-1.6.1.4.txt
@@ -4,15 +4,40 @@ GIT v1.6.1.4 Release Notes
Fixes since v1.6.1.3
--------------------
+* .gitignore learned to handle backslash as a quoting mechanism for
+ comment introduction character "#".
+ This fix was first merged to 1.6.2.1.
+
* "git fast-export" produced wrong output with some parents missing from
commits, when the history is clock-skewed.
* "git fast-import" sometimes failed to read back objects it just wrote
out and aborted, because it failed to flush stale cached data.
+* "git-ls-tree" and "git-diff-tree" used a pathspec correctly when
+ deciding to descend into a subdirectory but they did not match the
+ individual paths correctly. This caused pathspecs "abc/d ab" to match
+ "abc/0" ("abc/d" made them decide to descend into the directory "abc/",
+ and then "ab" incorrectly matched "abc/0" when it shouldn't).
+ This fix was first merged to 1.6.2.3.
+
+* import-zips script (in contrib) did not compute the common directory
+ prefix correctly.
+ This fix was first merged to 1.6.2.2.
+
+* "git init" segfaulted when given an overlong template location via
+ the --template= option.
+ This fix was first merged to 1.6.2.4.
+
* "git repack" did not error out when necessary object was missing in the
repository.
+* git-repack (invoked from git-gc) did not work as nicely as it should in
+ a repository that borrows objects from neighbours via alternates
+ mechanism especially when some packs are marked with the ".keep" flag
+ to prevent them from being repacked.
+ This fix was first merged to 1.6.2.3.
+
Also includes minor documentation fixes and updates.
--
diff --git a/Documentation/RelNotes-1.6.2.5.txt b/Documentation/RelNotes-1.6.2.5.txt
new file mode 100644
index 0000000..b23f9e9
--- /dev/null
+++ b/Documentation/RelNotes-1.6.2.5.txt
@@ -0,0 +1,21 @@
+GIT v1.6.2.5 Release Notes
+==========================
+
+Fixes since v1.6.2.4
+--------------------
+
+* "git apply" mishandled if you fed a git generated patch that renames
+ file A to B and file B to A at the same time.
+
+* "git diff -c -p" (and "diff --cc") did not expect to see submodule
+ differences and instead refused to work.
+
+* "git grep -e '('" segfaulted, instead of diagnosing a mismatched
+ parentheses error.
+
+* "git fetch" generated packs with offset-delta encoding when both ends of
+ the connection are capable of producing one; this cannot be read by
+ ancient git and the user should be able to disable this by setting
+ repack.usedeltabaseoffset configuration to false.
+
+
diff --git a/Documentation/RelNotes-1.6.3.1.txt b/Documentation/RelNotes-1.6.3.1.txt
new file mode 100644
index 0000000..2400b72
--- /dev/null
+++ b/Documentation/RelNotes-1.6.3.1.txt
@@ -0,0 +1,10 @@
+GIT v1.6.3.1 Release Notes
+==========================
+
+Fixes since v1.6.3
+------------------
+
+* "git checkout -b new-branch" with a staged change in the index
+ incorrectly primed the in-index cache-tree, resulting a wrong tree
+ object to be written out of the index. This is a grave regression
+ since the last 1.6.2.X maintenance release.
diff --git a/Documentation/RelNotes-1.6.3.2.txt b/Documentation/RelNotes-1.6.3.2.txt
new file mode 100644
index 0000000..b2f3f02
--- /dev/null
+++ b/Documentation/RelNotes-1.6.3.2.txt
@@ -0,0 +1,61 @@
+GIT v1.6.3.2 Release Notes
+==========================
+
+Fixes since v1.6.3.1
+--------------------
+
+ * A few codepaths picked up the first few bytes from an sha1[] by
+ casting the (char *) pointer to (int *); GCC 4.4 did not like this,
+ and aborted compilation.
+
+ * Some unlink(2) failures went undiagnosed.
+
+ * The "recursive" merge strategy misbehaved when faced rename/delete
+ conflicts while coming up with an intermediate merge base.
+
+ * The low-level merge algorithm did not handle a degenerate case of
+ merging a file with itself using itself as the common ancestor
+ gracefully. It should produce the file itself, but instead
+ produced an empty result.
+
+ * GIT_TRACE mechanism segfaulted when tracing a shell-quoted aliases.
+
+ * OpenBSD also uses st_ctimspec in "struct stat", instead of "st_ctim".
+
+ * With NO_CROSS_DIRECTORY_HARDLINKS, "make install" can be told not to
+ create hardlinks between $(gitexecdir)/git-$builtin_commands and
+ $(bindir)/git.
+
+ * command completion code in bash did not reliably detect that we are
+ in a bare repository.
+
+ * "git add ." in an empty directory complained that pathspec "." did not
+ match anything, which may be technically correct, but not useful. We
+ silently make it a no-op now.
+
+ * "git add -p" (and "patch" action in "git add -i") was broken when
+ the first hunk that adds a line at the top was split into two and
+ both halves are marked to be used.
+
+ * "git blame path" misbehaved at the commit where path became file
+ from a directory with some files in it.
+
+ * "git for-each-ref" had a segfaulting bug when dealing with a tag object
+ created by an ancient git.
+
+ * "git format-patch -k" still added patch numbers if format.numbered
+ configuration was set.
+
+ * "git grep --color ''" did not terminate. The command also had
+ subtle bugs with its -w option.
+
+ * http-push had a small use-after-free bug.
+
+ * "git push" was converting OFS_DELTA pack representation into less
+ efficient REF_DELTA representation unconditionally upon transfer,
+ making the transferred data unnecessarily larger.
+
+ * "git remote show origin" segfaulted when origin was still empty.
+
+Many other general usability updates around help text, diagnostic messages
+and documentation are included as well.
diff --git a/Documentation/RelNotes-1.6.3.txt b/Documentation/RelNotes-1.6.3.txt
index efce29d..418c685 100644
--- a/Documentation/RelNotes-1.6.3.txt
+++ b/Documentation/RelNotes-1.6.3.txt
@@ -37,6 +37,12 @@ Updates since v1.6.2
* various git-svn updates.
+* git-gui updates, including an update to Russian translation, and a
+ fix to an infinite loop when showing an empty diff.
+
+* gitk updates, including an update to Russian translation and improved Windows
+ support.
+
(performance)
* many uses of lstat(2) in the codepath for "git checkout" have been
@@ -152,6 +158,10 @@ Updates since v1.6.2
knobs you can tweak to work around issues with various versions of the
docbook-xsl package. See comments in Documentation/Makefile for details.
+* Support for building and testing a subset of git on a system without a
+ working perl has been improved.
+
+
Fixes since v1.6.2
------------------
@@ -170,9 +180,3 @@ v1.6.2.X series.
* git-gc spent excessive amount of time to decide if an object appears
in a locally existing pack (if needed, backport by merging 69e020a).
-
----
-exec >/var/tmp/1
-O=v1.6.3-rc1-1-gea10b60
-echo O=$(git describe master)
-git shortlog --no-merges $O..master ^maint
diff --git a/Documentation/RelNotes-1.6.4.txt b/Documentation/RelNotes-1.6.4.txt
new file mode 100644
index 0000000..af68297
--- /dev/null
+++ b/Documentation/RelNotes-1.6.4.txt
@@ -0,0 +1,93 @@
+GIT v1.6.4 Release Notes
+========================
+
+With the next major release, "git push" into a branch that is
+currently checked out will be refused by default. You can choose
+what should happen upon such a push by setting the configuration
+variable receive.denyCurrentBranch in the receiving repository.
+
+To ease the transition plan, the receiving repository of such a
+push running this release will issue a big warning when the
+configuration variable is missing. Please refer to:
+
+ http://git.or.cz/gitwiki/GitFaq#non-bare
+ http://thread.gmane.org/gmane.comp.version-control.git/107758/focus=108007
+
+for more details on the reason why this change is needed and the
+transition plan.
+
+For a similar reason, "git push $there :$killed" to delete the branch
+$killed in a remote repository $there, if $killed branch is the current
+branch pointed at by its HEAD, gets a large warning. You can choose what
+should happen upon such a push by setting the configuration variable
+receive.denyDeleteCurrent in the receiving repository.
+
+When the user does not tell "git push" what to push, it has always
+pushed matching refs. For some people it is unexpected, and a new
+configuration variable push.default has been introduced to allow
+changing a different default behaviour. To advertise the new feature,
+a big warning is issued if this is not configured and a git push without
+arguments is attempted.
+
+
+Updates since v1.6.3
+--------------------
+
+(subsystems)
+
+ * gitweb Perl style clean-up.
+
+ * git-svn updates, including a new --authors-prog option to map author
+ names by invoking an external program.
+
+(portability)
+
+ * We feed iconv with "UTF-8" instead of "utf8"; the former is
+ understood more widely.
+
+(performance)
+
+(usability, bells and whistles)
+
+ * "git add --edit" lets users edit the whole patch text to fine-tune what
+ is added to the index.
+
+ * "git log --graph" draws graphs more compactly by using horizonal lines
+ when able.
+
+ * "git log --decorate" shows shorter refnames by stripping well-known
+ refs/* prefix.
+
+ * "git send-email" understands quoted aliases in .mailrc files (might
+ have to be backported to 1.6.3.X).
+
+ * "git send-email" can fetch the sender address from the configuration
+ variable "sendmail.from" (and "sendmail.<identity>.from").
+
+ * "git show-branch" can color its output.
+
+ * "add" and "update" subcommands to "git submodule" learned --reference
+ option to use local clone with references.
+
+(developers)
+
+ * A major part of the "git bisect" wrapper has moved to C.
+
+Fixes since v1.6.3
+------------------
+
+All of the fixes in v1.6.3.X maintenance series are included in this
+release, unless otherwise noted.
+
+Here are fixes that this release has, but have not been backported to
+v1.6.3.X series.
+
+ * The way Git.pm sets up a Repository object was not friendly to callers
+ that chdir around. It now internally records the repository location
+ as an absolute path when autodetected.
+
+---
+exec >/var/tmp/1
+echo O=$(git describe master)
+O=v1.6.3.1-168-g23807fa
+git shortlog --no-merges $O..master ^maint
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 8d818a2..76fc84d 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -6,9 +6,13 @@ Checklist (and a short version for the impatient):
- check for unnecessary whitespace with "git diff --check"
before committing
- do not check in commented out code or unneeded files
- - provide a meaningful commit message
- the first line of the commit message should be a short
description and should skip the full stop
+ - the body should provide a meaningful commit message, which:
+ - uses the imperative, present tense: "change",
+ not "changed" or "changes".
+ - includes motivation for the change, and contrasts
+ its implementation with previous behaviour
- if you want your work included in git.git, add a
"Signed-off-by: Your Name <you@example.com>" line to the
commit message (or just use the option "-s" when
@@ -62,6 +66,14 @@ Describe the technical detail of the change(s).
If your description starts to get too long, that's a sign that you
probably need to split up your commit to finer grained pieces.
+That being said, patches which plainly describe the things that
+help reviewers check the patch, and future maintainers understand
+the code, are the most beautiful patches. Descriptions that summarise
+the point in the subject well, and describe the motivation for the
+change, the approach taken by the change, and if relevant how this
+differs substantially from the prior version, can be found on Usenet
+archives back into the late 80's. Consider it like good Netiquette,
+but for code.
Oh, another thing. I am picky about whitespaces. Make sure your
changes do not trigger errors with the sample pre-commit hook shipped
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 35056e1..3a86d1f 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -2,15 +2,15 @@ CONFIGURATION FILE
------------------
The git configuration file contains a number of variables that affect
-the git command's behavior. `.git/config` file for each repository
-is used to store the information for that repository, and
-`$HOME/.gitconfig` is used to store per user information to give
-fallback values for `.git/config` file. The file `/etc/gitconfig`
-can be used to store system-wide defaults.
-
-They can be used by both the git plumbing
-and the porcelains. The variables are divided into sections, where
-in the fully qualified variable name the variable itself is the last
+the git command's behavior. The `.git/config` file in each repository
+is used to store the configuration for that repository, and
+`$HOME/.gitconfig` is used to store a per-user configuration as
+fallback values for the `.git/config` file. The file `/etc/gitconfig`
+can be used to store a system-wide default configuration.
+
+The configuration variables are used by both the git plumbing
+and the porcelains. The variables are divided into sections, wherein
+the fully qualified variable name of the variable itself is the last
dot-separated segment and the section name is everything before the last
dot. The variable names are case-insensitive and only alphanumeric
characters are allowed. Some variables may appear multiple times.
@@ -26,28 +26,28 @@ The file consists of sections and variables. A section begins with
the name of the section in square brackets and continues until the next
section begins. Section names are not case sensitive. Only alphanumeric
characters, `-` and `.` are allowed in section names. Each variable
-must belong to some section, which means that there must be section
-header before first setting of a variable.
+must belong to some section, which means that there must be a section
+header before the first setting of a variable.
Sections can be further divided into subsections. To begin a subsection
put its name in double quotes, separated by space from the section name,
-in the section header, like in example below:
+in the section header, like in the example below:
--------
[section "subsection"]
--------
-Subsection names can contain any characters except newline (doublequote
-`"` and backslash have to be escaped as `\"` and `\\`,
-respectively) and are case sensitive. Section header cannot span multiple
+Subsection names are case sensitive and can contain any characters except
+newline (doublequote `"` and backslash have to be escaped as `\"` and `\\`,
+respectively). Section headers cannot span multiple
lines. Variables may belong directly to a section or to a given subsection.
You can have `[section]` if you have `[section "subsection"]`, but you
don't need to.
-There is also (case insensitive) alternative `[section.subsection]` syntax.
-In this syntax subsection names follow the same restrictions as for section
-name.
+There is also a case insensitive alternative `[section.subsection]` syntax.
+In this syntax, subsection names follow the same restrictions as for section
+names.
All the other lines are recognized as setting variables, in the form
'name = value'. If there is no equal sign on the line, the entire line
@@ -66,10 +66,10 @@ converting value to the canonical form using '--bool' type specifier;
'git-config' will ensure that the output is "true" or "false".
String values may be entirely or partially enclosed in double quotes.
-You need to enclose variable value in double quotes if you want to
-preserve leading or trailing whitespace, or if variable value contains
-beginning of comment characters (if it contains '#' or ';').
-Double quote `"` and backslash `\` characters in variable value must
+You need to enclose variable values in double quotes if you want to
+preserve leading or trailing whitespace, or if the variable value contains
+comment characters (i.e. it contains '#' or ';').
+Double quote `"` and backslash `\` characters in variable values must
be escaped: use `\"` for `"` and `\\` for `\`.
The following escape sequences (beside `\"` and `\\`) are recognized:
@@ -77,10 +77,10 @@ The following escape sequences (beside `\"` and `\\`) are recognized:
and `\b` for backspace (BS). No other char escape sequence, nor octal
char sequences are valid.
-Variable value ending in a `\` is continued on the next line in the
+Variable values ending in a `\` are continued on the next line in the
customary UNIX fashion.
-Some variables may require special value format.
+Some variables may require a special value format.
Example
~~~~~~~
@@ -429,6 +429,20 @@ 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.
+core.createObject::
+ You can set this to 'link', in which case a hardlink followed by
+ a delete of the source are used to make sure that object creation
+ will not overwrite existing objects.
++
+On some file system/operating system combinations, this is unreliable.
+Set this config setting to 'rename' there; However, This will remove the
+check that makes sure that existing object files will not get overwritten.
+
+add.ignore-errors::
+ Tells 'git-add' to continue adding files when some files cannot be
+ added due to indexing errors. Equivalent to the '--ignore-errors'
+ option of linkgit:git-add[1].
+
alias.*::
Command aliases for the linkgit:git[1] command wrapper - e.g.
after defining "alias.last = cat-file commit HEAD", the invocation
@@ -595,6 +609,12 @@ color.pager::
A boolean to enable/disable colored output when the pager is in
use (default is true).
+color.showbranch::
+ A boolean to enable/disable color in the output of
+ linkgit:git-show-branch[1]. May be set to `always`,
+ `false` (or `never`) or `auto` (or `true`), in which case colors are used
+ only when the output is to a terminal. Defaults to false.
+
color.status::
A boolean to enable/disable color in the output of
linkgit:git-status[1]. May be set to `always`,
@@ -707,6 +727,13 @@ fetch.unpackLimit::
especially on slow filesystems. If not set, the value of
`transfer.unpackLimit` is used instead.
+format.attach::
+ Enable multipart/mixed attachments as the default for
+ 'format-patch'. The value can also be a double quoted string
+ which will enable attachments as the default and set the
+ value as the boundary. See the --attach option in
+ linkgit:git-format-patch[1].
+
format.numbered::
A boolean which can enable or disable sequence numbers in patch
subjects. It defaults to "auto" which enables it only if there
@@ -718,6 +745,14 @@ format.headers::
Additional email headers to include in a patch to be submitted
by mail. See linkgit:git-format-patch[1].
+format.cc::
+ Additional "Cc:" headers to include in a patch to be submitted
+ by mail. See the --cc option in linkgit:git-format-patch[1].
+
+format.subjectprefix::
+ The default for format-patch is to output files with the '[PATCH]'
+ subject prefix. Use this variable to change that prefix.
+
format.suffix::
The default for format-patch is to output files with the suffix
`.patch`. Use this variable to change that suffix (make sure to
@@ -730,11 +765,11 @@ format.pretty::
format.thread::
The default threading style for 'git-format-patch'. Can be
- either a boolean value, `shallow` or `deep`. 'Shallow'
+ either a boolean value, `shallow` or `deep`. `shallow`
threading makes every mail a reply to the head of the series,
where the head is chosen from the cover letter, the
`\--in-reply-to`, and the first patch mail, in this order.
- 'Deep' threading makes every mail a reply to the previous one.
+ `deep` threading makes every mail a reply to the previous one.
A true boolean value is the same as `shallow`, and a false
value disables threading.
diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt
index d938b42..ab1943c 100644
--- a/Documentation/git-add.txt
+++ b/Documentation/git-add.txt
@@ -9,7 +9,7 @@ SYNOPSIS
--------
[verse]
'git add' [-n] [-v] [--force | -f] [--interactive | -i] [--patch | -p]
- [--all | [--update | -u]] [--intent-to-add | -N]
+ [--edit | -e] [--all | [--update | -u]] [--intent-to-add | -N]
[--refresh] [--ignore-errors] [--] <filepattern>...
DESCRIPTION
@@ -76,6 +76,15 @@ OPTIONS
bypassed and the 'patch' subcommand is invoked using each of
the specified filepatterns before exiting.
+-e, \--edit::
+ Open the diff vs. the index in an editor and let the user
+ edit it. After the editor was closed, adjust the hunk headers
+ and apply the patch to the index.
++
+*NOTE*: Obviously, if you change anything else than the first character
+on lines beginning with a space or a minus, the patch will no longer
+apply.
+
-u::
--update::
Update only files that git already knows about, staging modified
diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt
index 1e71dd5..6d92cbe 100644
--- a/Documentation/git-am.txt
+++ b/Documentation/git-am.txt
@@ -32,7 +32,7 @@ OPTIONS
-s::
--signoff::
- Add `Signed-off-by:` line to the commit message, using
+ Add a `Signed-off-by:` line to the commit message, using
the committer identity of yourself.
-k::
@@ -79,14 +79,14 @@ default. You can use `--no-utf8` to override this.
message as the commit author date, and uses the time of
commit creation as the committer date. This allows the
user to lie about the committer date by using the same
- timestamp as the author date.
+ value as the author date.
--ignore-date::
By default the command records the date from the e-mail
message as the commit author date, and uses the time of
commit creation as the committer date. This allows the
- user to lie about author timestamp by using the same
- timestamp as the committer date.
+ user to lie about the author date by using the same
+ value as the committer date.
--skip::
Skip the current patch. This is only meaningful when
@@ -115,21 +115,21 @@ DISCUSSION
----------
The commit author name is taken from the "From: " line of the
-message, and commit author time is taken from the "Date: " line
+message, and commit author date is taken from the "Date: " line
of the message. The "Subject: " line is used as the title of
the commit, after stripping common prefix "[PATCH <anything>]".
-It is supposed to describe what the commit is about concisely as
-a one line text.
+The "Subject: " line is supposed to concisely describe what the
+commit is about in one line of text.
-The body of the message (the rest of the message after the blank line
-that terminates the RFC2822 headers) can begin with "Subject: " and
-"From: " lines that are different from those of the mail header,
-to override the values of these fields.
+"From: " and "Subject: " lines starting the body (the rest of the
+message after the blank line terminating the RFC2822 headers)
+override the respective commit author name and title values taken
+from the headers.
The commit message is formed by the title taken from the
"Subject: ", a blank line and the body of the message up to
-where the patch begins. Excess whitespace characters at the end of the
-lines are automatically stripped.
+where the patch begins. Excess whitespace at the end of each
+line is automatically stripped.
The patch is expected to be inline, directly following the
message. Any line that is of the form:
@@ -141,7 +141,7 @@ message. Any line that is of the form:
is taken as the beginning of a patch, and the commit log message
is terminated before the first occurrence of such a line.
-When initially invoking it, you give it the names of the mailboxes
+When initially invoking `git am`, you give it the names of the mailboxes
to process. Upon seeing the first patch that does not apply, it
aborts in the middle. You can recover from this in one of two ways:
diff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt
index 9e5baa2..735374d 100644
--- a/Documentation/git-apply.txt
+++ b/Documentation/git-apply.txt
@@ -3,7 +3,7 @@ git-apply(1)
NAME
----
-git-apply - Apply a patch on a git index file and a working tree
+git-apply - Apply a patch on a git index file and/or a working tree
SYNOPSIS
diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index cbd4275..ae201de 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -111,6 +111,7 @@ OPTIONS
--no-abbrev::
Display the full sha1s in the output listing rather than abbreviating them.
+-t::
--track::
When creating a new branch, set up configuration to mark the
start-point branch as "upstream" from the new branch. This
diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt
index b191276..58c8d65 100644
--- a/Documentation/git-cat-file.txt
+++ b/Documentation/git-cat-file.txt
@@ -9,8 +9,8 @@ git-cat-file - Provide content or type and size information for repository objec
SYNOPSIS
--------
[verse]
-'git cat-file' [-t | -s | -e | -p | <type>] <object>
-'git cat-file' [--batch | --batch-check] < <list-of-objects>
+'git cat-file' (-t | -s | -e | -p | <type>) <object>
+'git cat-file' (--batch | --batch-check) < <list-of-objects>
DESCRIPTION
-----------
diff --git a/Documentation/git-check-ref-format.txt b/Documentation/git-check-ref-format.txt
index c1ce268..0b7982e 100644
--- a/Documentation/git-check-ref-format.txt
+++ b/Documentation/git-check-ref-format.txt
@@ -25,6 +25,10 @@ imposes the following rules on how references are named:
grouping, but no slash-separated component can begin with a
dot `.`.
+. They must contain at least one `/`. This enforces the presence of a
+ category like `heads/`, `tags/` etc. but the actual names are not
+ restricted.
+
. They cannot have two consecutive dots `..` anywhere.
. They cannot have ASCII control characters (i.e. bytes whose
@@ -38,6 +42,8 @@ imposes the following rules on how references are named:
. They cannot contain a sequence `@{`.
+- They cannot contain a `\\`.
+
These rules make it easy for shell script based tools to parse
reference names, pathname expansion by the shell when a reference name is used
unquoted (by mistake), and also avoids ambiguities in certain
diff --git a/Documentation/git-clean.txt b/Documentation/git-clean.txt
index 8a11450..be894af 100644
--- a/Documentation/git-clean.txt
+++ b/Documentation/git-clean.txt
@@ -12,14 +12,17 @@ SYNOPSIS
DESCRIPTION
-----------
-Removes files unknown to git. This allows to clean the working tree
-from files that are not under version control. If the '-x' option is
-specified, ignored files are also removed, allowing to remove all
-build products.
+
+Cleans the working tree by recursively removing files that are not
+under version control, starting from the current directory.
+
+Normally, only files unknown to git are removed, but if the '-x'
+option is specified, ignored files are also removed. This can, for
+example, be useful to remove all build products.
+
If any optional `<path>...` arguments are given, only those paths
are affected.
-
OPTIONS
-------
-d::
diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index 4072f40..b14de6c 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -149,7 +149,7 @@ then the cloned repository will become corrupt.
part of the source repository is used if no directory is
explicitly given ("repo" for "/path/to/repo.git" and "foo"
for "host.xz:foo/.git"). Cloning into an existing directory
- is not allowed.
+ is only allowed if the directory is empty.
:git-clone: 1
include::urls.txt[]
diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
index 7131ee3..f68b198 100644
--- a/Documentation/git-config.txt
+++ b/Documentation/git-config.txt
@@ -69,7 +69,8 @@ OPTIONS
--add::
Adds a new line to the option without altering any existing
- values. This is the same as providing '^$' as the value_regex.
+ values. This is the same as providing '^$' as the value_regex
+ in `--replace-all`.
--get::
Get the value for a given key (optionally filtered by a regex
@@ -155,7 +156,7 @@ See also <<FILES>>.
When the color setting for `name` is undefined, the command uses
`color.ui` as fallback.
---get-color name default::
+--get-color name [default]::
Find the color configured for `name` (e.g. `color.diff.new`) and
output it as the ANSI color escape sequence to the standard
diff --git a/Documentation/git-difftool.txt b/Documentation/git-difftool.txt
index 15b247b..96a6c51 100644
--- a/Documentation/git-difftool.txt
+++ b/Documentation/git-difftool.txt
@@ -31,7 +31,7 @@ OPTIONS
Use the diff tool specified by <tool>.
Valid merge tools are:
kdiff3, kompare, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff,
- ecmerge, diffuse and opendiff
+ ecmerge, diffuse, opendiff and araxis.
+
If a diff tool is not specified, 'git-difftool'
will use the configuration variable `diff.tool`. If the
diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt
index 5eddca9..6f1fc80 100644
--- a/Documentation/git-format-patch.txt
+++ b/Documentation/git-format-patch.txt
@@ -9,10 +9,10 @@ git-format-patch - Prepare patches for e-mail submission
SYNOPSIS
--------
[verse]
-'git format-patch' [-k] [-o <dir> | --stdout] [--thread]
- [--attach[=<boundary>] | --inline[=<boundary>] |
- [--no-attach]]
- [-s | --signoff] [<common diff options>]
+'git format-patch' [-k] [(-o|--output-directory) <dir> | --stdout]
+ [--thread[=<style>]]
+ [(--attach|--inline)[=<boundary>] | --no-attach]
+ [-s | --signoff]
[-n | --numbered | -N | --no-numbered]
[--start-number <n>] [--numbered-files]
[--in-reply-to=Message-Id] [--suffix=.<sfx>]
@@ -20,6 +20,7 @@ SYNOPSIS
[--subject-prefix=Subject-Prefix]
[--cc=<email>]
[--cover-letter]
+ [<common diff options>]
[ <since> | <revision range> ]
DESCRIPTION
@@ -128,9 +129,9 @@ include::diff-options.txt[]
the Message-Id header to reference.
+
The optional <style> argument can be either `shallow` or `deep`.
-'Shallow' threading makes every mail a reply to the head of the
+'shallow' threading makes every mail a reply to the head of the
series, where the head is chosen from the cover letter, the
-`\--in-reply-to`, and the first patch mail, in this order. 'Deep'
+`\--in-reply-to`, and the first patch mail, in this order. 'deep'
threading makes every mail a reply to the previous one. If not
specified, defaults to the 'format.thread' configuration, or `shallow`
if that is not set.
@@ -170,18 +171,17 @@ if that is not set.
--suffix=.<sfx>::
Instead of using `.patch` as the suffix for generated
filenames, use specified suffix. A common alternative is
- `--suffix=.txt`.
+ `--suffix=.txt`. Leaving this empty will remove the `.patch`
+ suffix.
+
-Note that you would need to include the leading dot `.` if you
-want a filename like `0001-description-of-my-change.patch`, and
-the first letter does not have to be a dot. Leaving it empty would
-not add any suffix.
+Note that the leading character does not have to be a dot; for example,
+you can use `--suffix=-patch` to get `0001-description-of-my-change-patch`.
--no-binary::
- Don't output contents of changes in binary files, just take note
- that they differ. Note that this disable the patch to be properly
- applied. By default the contents of changes in those files are
- encoded in the patch.
+ Do not output contents of changes in binary files, instead
+ display a notice that those files changed. Patches generated
+ using this option cannot be applied properly, but they are
+ still useful for code review.
--root::
Treat the revision argument as a <revision range>, even if it
@@ -192,10 +192,10 @@ not add any suffix.
CONFIGURATION
-------------
-You can specify extra mail header lines to be added to each message
-in the repository configuration, new defaults for the subject prefix
-and file suffix, control attachments, and number patches when outputting
-more than one.
+You can specify extra mail header lines to be added to each message,
+defaults for the subject prefix and file suffix, number patches when
+outputting more than one patch, add "Cc:" headers, configure attachments,
+and sign off patches with configuration variables.
------------
[format]
@@ -243,8 +243,8 @@ $ git format-patch -M -B origin
+
Additionally, it detects and handles renames and complete rewrites
intelligently to produce a renaming patch. A renaming patch reduces
-the amount of text output, and generally makes it easier to review it.
-Note that the "patch" program does not understand renaming patches, so
+the amount of text output, and generally makes it easier to review.
+Note that non-git "patch" programs won't understand renaming patches, so
use it only when you know the recipient uses git to apply your patch.
* Extract three topmost commits from the current branch and format them
diff --git a/Documentation/git-ls-tree.txt b/Documentation/git-ls-tree.txt
index f68e5c5..c3fdccb 100644
--- a/Documentation/git-ls-tree.txt
+++ b/Documentation/git-ls-tree.txt
@@ -82,8 +82,10 @@ Output Format
-------------
<mode> SP <type> SP <object> TAB <file>
-When the `-z` option is not used, TAB, LF, and backslash characters
+Unless the `-z` option is used, TAB, LF, and backslash characters
in pathnames are represented as `\t`, `\n`, and `\\`, respectively.
+This output format is compatible with what '--index-info --stdin' of
+'git update-index' expects.
When the `-l` option is used, format changes to
diff --git a/Documentation/git-mergetool.txt b/Documentation/git-mergetool.txt
index ff9700d..68ed6c0 100644
--- a/Documentation/git-mergetool.txt
+++ b/Documentation/git-mergetool.txt
@@ -27,7 +27,7 @@ OPTIONS
Use the merge resolution program specified by <tool>.
Valid merge tools are:
kdiff3, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff, ecmerge,
- diffuse, tortoisemerge and opendiff
+ diffuse, tortoisemerge, opendiff and araxis.
+
If a merge resolution program is not specified, 'git-mergetool'
will use the configuration variable `merge.tool`. If the
diff --git a/Documentation/git-mktree.txt b/Documentation/git-mktree.txt
index af19f06..81e3326 100644
--- a/Documentation/git-mktree.txt
+++ b/Documentation/git-mktree.txt
@@ -8,12 +8,13 @@ git-mktree - Build a tree-object from ls-tree formatted text
SYNOPSIS
--------
-'git mktree' [-z]
+'git mktree' [-z] [--missing] [--batch]
DESCRIPTION
-----------
-Reads standard input in non-recursive `ls-tree` output format,
-and creates a tree object. The object name of the tree object
+Reads standard input in non-recursive `ls-tree` output format, and creates
+a tree object. The order of the tree entries is normalised by mktree so
+pre-sorting the input is not required. The object name of the tree object
built is written to the standard output.
OPTIONS
@@ -21,6 +22,18 @@ OPTIONS
-z::
Read the NUL-terminated `ls-tree -z` output instead.
+--missing::
+ Allow missing objects. The default behaviour (without this option)
+ is to verify that each tree entry's sha1 identifies an existing
+ object. This option has no effect on the treatment of gitlink entries
+ (aka "submodules") which are always allowed to be missing.
+
+--batch::
+ Allow building of more than one tree object before exiting. Each
+ tree is separated by as single blank line. The final new-line is
+ optional. Note - if the '-z' option is used, lines are terminated
+ with NUL.
+
Author
------
Written by Junio C Hamano <gitster@pobox.com>
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 3d5a066..26f3b7b 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -231,8 +231,7 @@ OPTIONS
-s <strategy>::
--strategy=<strategy>::
- Use the given merge strategy; can be supplied more than
- once to specify them in the order they should be tried.
+ Use the given merge strategy.
If there is no `-s` option, a built-in list of strategies
is used instead ('git-merge-recursive' when merging a single
head, 'git-merge-octopus' otherwise). This implies --merge.
diff --git a/Documentation/git-repack.txt b/Documentation/git-repack.txt
index aaa8852..c9257a1 100644
--- a/Documentation/git-repack.txt
+++ b/Documentation/git-repack.txt
@@ -31,11 +31,14 @@ OPTIONS
Instead of incrementally packing the unpacked objects,
pack everything referenced into a single pack.
Especially useful when packing a repository that is used
- for private development and there is no need to worry
- about people fetching via dumb protocols from it. Use
+ for private development. Use
with '-d'. This will clean up the objects that `git prune`
leaves behind, but `git fsck --full` shows as
dangling.
++
+Note that users fetching over dumb protocols will have to fetch the
+whole new pack in order to get any contained object, no matter how many
+other objects in that pack they already have locally.
-A::
Same as `-a`, unless '-d' is used. Then any unreachable
diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt
index fba30b1..4bbdd05 100644
--- a/Documentation/git-rev-parse.txt
+++ b/Documentation/git-rev-parse.txt
@@ -26,10 +26,15 @@ OPTIONS
--parseopt::
Use 'git-rev-parse' in option parsing mode (see PARSEOPT section below).
---keep-dash-dash::
+--keep-dashdash::
Only meaningful in `--parseopt` mode. Tells the option parser to echo
out the first `--` met instead of skipping it.
+--sq-quote::
+ Use 'git-rev-parse' in shell quoting mode (see SQ-QUOTE
+ section below). In contrast to the `--sq` option below, this
+ mode does only quoting. Nothing else is done to command input.
+
--revs-only::
Do not output flags and parameters not meant for
'git-rev-list' command.
@@ -64,7 +69,8 @@ OPTIONS
properly quoted for consumption by shell. Useful when
you expect your parameter to contain whitespaces and
newlines (e.g. when using pickaxe `-S` with
- 'git-diff-\*').
+ 'git-diff-\*'). In contrast to the `--sq-quote` option,
+ the command input is still interpreted as usual.
--not::
When showing object names, prefix them with '{caret}' and
@@ -406,6 +412,33 @@ C? option C with an optional argument"
eval `echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?`
------------
+SQ-QUOTE
+--------
+
+In `--sq-quote` mode, 'git-rev-parse' echoes on the standard output a
+single line suitable for `sh(1)` `eval`. This line is made by
+normalizing the arguments following `--sq-quote`. Nothing other than
+quoting the arguments is done.
+
+If you want command input to still be interpreted as usual by
+'git-rev-parse' before the output is shell quoted, see the `--sq`
+option.
+
+Example
+~~~~~~~
+
+------------
+$ cat >your-git-script.sh <<\EOF
+#!/bin/sh
+args=$(git rev-parse --sq-quote "$@") # quote user-supplied arguments
+command="git frotz -n24 $args" # and use it inside a handcrafted
+ # command line
+eval "$command"
+EOF
+
+$ sh your-git-script.sh "a b'c"
+------------
+
EXAMPLES
--------
diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt
index 794224b..e7cb0e6 100644
--- a/Documentation/git-send-email.txt
+++ b/Documentation/git-send-email.txt
@@ -14,6 +14,10 @@ SYNOPSIS
DESCRIPTION
-----------
Takes the patches given on the command line and emails them out.
+Patches can be specified as files, directories (which will send all
+files in the directory), or directly as a revision list. In the
+last case, any format accepted by linkgit:git-format-patch[1] can
+be passed to git send-email.
The header of the email is configurable by command line options. If not
specified on the command line, the user will be prompted with a ReadLine
@@ -39,6 +43,10 @@ OPTIONS
Composing
~~~~~~~~~
+--annotate::
+ Review and edit each patch you're about to send. See the
+ CONFIGURATION section for 'sendemail.multiedit'.
+
--bcc=<address>::
Specify a "Bcc:" value for each email. Default is the value of
'sendemail.bcc'.
@@ -51,11 +59,6 @@ The --bcc option must be repeated for each user you want on the bcc list.
+
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.
@@ -67,11 +70,16 @@ In-Reply-To headers specified in the message. If the body of the message
and In-Reply-To headers will be used unless they are removed.
+
Missing From or In-Reply-To headers will be prompted for.
++
+See the CONFIGURATION section for 'sendemail.multiedit'.
--from=<address>::
- Specify the sender of the emails. This will default to
- the value GIT_COMMITTER_IDENT, as returned by "git var -l".
- The user will still be prompted to confirm this entry.
+ Specify the sender of the emails. If not specified on the command line,
+ the value of the 'sendemail.from' configuration option is used. If
+ neither the command line option nor 'sendemail.from' are set, then the
+ user will be prompted for the value. The default for the prompt will be
+ the value of GIT_AUTHOR_IDENT, or GIT_COMMITTER_IDENT if that is not
+ set, as returned by "git var -l".
--in-reply-to=<identifier>::
Specify the contents of the first In-Reply-To header.
@@ -135,7 +143,9 @@ user is prompted for a password while the input is masked for privacy.
--smtp-server-port=<port>::
Specifies a port different from the default port (SMTP
servers typically listen to smtp port 25 and ssmtp port
- 465). This can be set with 'sendemail.smtpserverport'.
+ 465); symbolic port names (e.g. "submission" instead of 465)
+ are also accepted. The port can also be set with the
+ 'sendemail.smtpserverport' configuration variable.
--smtp-ssl::
Legacy alias for '--smtp-encryption ssl'.
@@ -230,6 +240,12 @@ have been specified, in which case default to 'compose'.
--dry-run::
Do everything except actually send the emails.
+--[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.
+
--quiet::
Make git-send-email less verbose. One line per email should be
all that is output.
@@ -246,12 +262,6 @@ have been specified, in which case default to 'compose'.
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
-------------
diff --git a/Documentation/git-show-branch.txt b/Documentation/git-show-branch.txt
index 7e9ff37..89ec536 100644
--- a/Documentation/git-show-branch.txt
+++ b/Documentation/git-show-branch.txt
@@ -8,9 +8,11 @@ git-show-branch - Show branches and their commits
SYNOPSIS
--------
[verse]
-'git show-branch' [--all] [--remotes] [--topo-order] [--current]
+'git show-branch' [--all] [--remotes] [--topo-order | --date-order]
+ [--current] [--color | --no-color]
[--more=<n> | --list | --independent | --merge-base]
- [--no-name | --sha1-name] [--topics] [<rev> | <glob>]...
+ [--no-name | --sha1-name] [--topics]
+ [<rev> | <glob>]...
'git show-branch' (-g|--reflog)[=<n>[,<base>]] [--list] [<ref>]
DESCRIPTION
@@ -57,6 +59,11 @@ OPTIONS
appear in topological order (i.e., descendant commits
are shown before their parents).
+--date-order::
+ This option is similar to '--topo-order' in the sense that no
+ parent comes before all of its children, but otherwise commits
+ are ordered according to their commit date.
+
--sparse::
By default, the output omits merges that are reachable
from only one tip being shown. This option makes them
@@ -107,6 +114,14 @@ OPTIONS
When no explicit <ref> parameter is given, it defaults to the
current branch (or `HEAD` if it is detached).
+--color::
+ Color the status sign (one of these: `*` `!` `+` `-`) of each commit
+ corresponding to the branch it's in.
+
+--no-color::
+ Turn off colored output, even when the configuration file gives the
+ default to color output.
+
Note that --more, --list, --independent and --merge-base options
are mutually exclusive.
@@ -148,9 +163,10 @@ $ git show-branch master fixes mhf
------------------------------------------------
These three branches all forked from a common commit, [master],
-whose commit message is "Add 'git show-branch'. "fixes" branch
-adds one commit 'Introduce "reset type"'. "mhf" branch has many
-other commits. The current branch is "master".
+whose commit message is "Add \'git show-branch\'". The "fixes"
+branch adds one commit "Introduce "reset type" flag to "git reset"".
+The "mhf" branch adds many other commits. The current branch
+is "master".
EXAMPLE
diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt
index 051f94d..a42d4c8 100644
--- a/Documentation/git-stash.txt
+++ b/Documentation/git-stash.txt
@@ -9,8 +9,8 @@ SYNOPSIS
--------
[verse]
'git stash' list [<options>]
-'git stash' (show | drop | pop ) [<stash>]
-'git stash' apply [--index] [<stash>]
+'git stash' ( show | drop ) [<stash>]
+'git stash' ( pop | apply ) [--index] [<stash>]
'git stash' branch <branchname> [<stash>]
'git stash' [save [--keep-index] [<message>]]
'git stash' clear
@@ -75,19 +75,27 @@ show [<stash>]::
it will accept any format known to 'git-diff' (e.g., `git stash show
-p stash@\{1}` to view the second most recent stash in patch form).
-apply [--index] [<stash>]::
+pop [<stash>]::
- Restore the changes recorded in the stash on top of the current
- working tree state. When no `<stash>` is given, applies the latest
- one. The working directory must match the index.
+ Remove a single stashed state from the stash list and apply it
+ on top of the current working tree state, i.e., do the inverse
+ operation of `git stash save`. The working directory must
+ match the index.
+
-This operation can fail with conflicts; you need to resolve them
-by hand in the working tree.
+Applying the state can fail with conflicts; in this case, it is not
+removed from the stash list. You need to resolve the conflicts by hand
+and call `git stash drop` manually afterwards.
+
If the `--index` option is used, then tries to reinstate not only the working
tree's changes, but also the index's ones. However, this can fail, when you
have conflicts (which are stored in the index, where you therefore can no
longer apply the changes as they were originally).
++
+When no `<stash>` is given, `stash@\{0}` is assumed.
+
+apply [--index] [<stash>]::
+
+ Like `pop`, but do not remove the state from the stash list.
branch <branchname> [<stash>]::
@@ -112,12 +120,6 @@ drop [<stash>]::
Remove a single stashed state from the stash list. When no `<stash>`
is given, it removes the latest one. i.e. `stash@\{0}`
-pop [<stash>]::
-
- Remove a single stashed state from the stash list and apply on top
- of the current working tree state. When no `<stash>` is given,
- `stash@\{0}` is assumed. See also `apply`.
-
create::
Create a stash (which is a regular commit object) and return its
@@ -163,7 +165,7 @@ $ git pull
file foobar not up to date, cannot merge.
$ git stash
$ git pull
-$ git stash apply
+$ git stash pop
----------------------------------------------------------------
Interrupted workflow::
@@ -192,7 +194,7 @@ You can use 'git-stash' to simplify the above, like this:
$ git stash
$ edit emergency fix
$ git commit -a -m "Fix in a hurry"
-$ git stash apply
+$ git stash pop
# ... continue hacking ...
----------------------------------------------------------------
diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index f993469..cd8e861 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -9,10 +9,12 @@ git-submodule - Initialize, update or inspect submodules
SYNOPSIS
--------
[verse]
-'git submodule' [--quiet] add [-b branch] [--] <repository> <path>
+'git submodule' [--quiet] add [-b branch]
+ [--reference <repository>] [--] <repository> <path>
'git submodule' [--quiet] status [--cached] [--] [<path>...]
'git submodule' [--quiet] init [--] [<path>...]
-'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--rebase] [--] [<path>...]
+'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--rebase]
+ [--reference <repository>] [--] [<path>...]
'git submodule' [--quiet] summary [--summary-limit <n>] [commit] [--] [<path>...]
'git submodule' [--quiet] foreach <command>
'git submodule' [--quiet] sync [--] [<path>...]
@@ -187,6 +189,14 @@ OPTIONS
If the key `submodule.$name.update` is set to `rebase`, this option is
implicit.
+--reference <repository>::
+ This option is only valid for add and update commands. These
+ commands sometimes need to clone a remote repository. In this case,
+ this option will be passed to the linkgit:git-clone[1] command.
++
+*NOTE*: Do *not* use this option unless you have read the note
+for linkgit:git-clone[1]'s --reference and --shared options carefully.
+
<path>...::
Paths to submodule(s). When specified this will restrict the command
to only operate on the submodules found at the specified paths.
diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index 1c40894..ca3fc3d 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -398,6 +398,14 @@ after the authors-file is modified should continue operation.
config key: svn.authorsfile
+--authors-prog=<filename>::
+
+If this option is specified, for each SVN committer name that does not
+exist in the authors file, the given file is executed with the committer
+name as the first argument. The program is expected to return a single
+line of the form "Name <email>", which will be treated as if included in
+the authors file.
+
-q::
--quiet::
Make 'git-svn' less verbose. Specify a second time to make it
diff --git a/Documentation/git-update-server-info.txt b/Documentation/git-update-server-info.txt
index 35d27b0..035cc30 100644
--- a/Documentation/git-update-server-info.txt
+++ b/Documentation/git-update-server-info.txt
@@ -39,12 +39,6 @@ what they are for:
* info/refs
-BUGS
-----
-When you remove an existing ref, the command fails to update
-info/refs file unless `--force` flag is given.
-
-
Author
------
Written by Junio C Hamano <gitster@pobox.com>
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 470fdc5..56d4770 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -43,9 +43,16 @@ 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.2.3/git.html[documentation for release 1.6.2.3]
+* link:v1.6.3.2/git.html[documentation for release 1.6.3.2]
* release notes for
+ link:RelNotes-1.6.3.2.txt[1.6.3.2],
+ link:RelNotes-1.6.3.1.txt[1.6.3.1],
+ link:RelNotes-1.6.3.txt[1.6.3].
+
+* release notes for
+ link:RelNotes-1.6.2.5.txt[1.6.2.5],
+ link:RelNotes-1.6.2.4.txt[1.6.2.4],
link:RelNotes-1.6.2.3.txt[1.6.2.3],
link:RelNotes-1.6.2.2.txt[1.6.2.2],
link:RelNotes-1.6.2.1.txt[1.6.2.1],
@@ -225,6 +232,8 @@ The link:user-manual.html#git-concepts[git concepts chapter of the
user-manual] and linkgit:gitcore-tutorial[7] both provide
introductions to the underlying git architecture.
+See linkgit:gitworkflows[7] for an overview of recommended workflows.
+
See also the link:howto-index.html[howto] documents for some useful
examples.
@@ -642,7 +651,8 @@ SEE ALSO
linkgit:gittutorial[7], linkgit:gittutorial-2[7],
link:everyday.html[Everyday Git], linkgit:gitcvs-migration[7],
linkgit:gitglossary[7], linkgit:gitcore-tutorial[7],
-linkgit:gitcli[7], link:user-manual.html[The Git User's Manual]
+linkgit:gitcli[7], link:user-manual.html[The Git User's Manual],
+linkgit:gitworkflows[7]
GIT
---
diff --git a/Documentation/gittutorial.txt b/Documentation/gittutorial.txt
index c5d5596..c7fa949 100644
--- a/Documentation/gittutorial.txt
+++ b/Documentation/gittutorial.txt
@@ -650,6 +650,9 @@ digressions that may be interesting at this point are:
smart enough to perform a close-to-optimal search even in the
case of complex non-linear history with lots of merged branches.
+ * linkgit:gitworkflows[7]: Gives an overview of recommended
+ workflows.
+
* link:everyday.html[Everyday GIT with 20 Commands Or So]
* linkgit:gitcvs-migration[7]: Git for CVS users.
@@ -661,6 +664,7 @@ linkgit:gitcvs-migration[7],
linkgit:gitcore-tutorial[7],
linkgit:gitglossary[7],
linkgit:git-help[1],
+linkgit:gitworkflows[7],
link:everyday.html[Everyday git],
link:user-manual.html[The Git User's Manual]
diff --git a/Documentation/merge-config.txt b/Documentation/merge-config.txt
index 4832bc7..c0f96e7 100644
--- a/Documentation/merge-config.txt
+++ b/Documentation/merge-config.txt
@@ -23,7 +23,7 @@ merge.tool::
Controls which merge resolution program is used by
linkgit:git-mergetool[1]. Valid built-in values are: "kdiff3",
"tkdiff", "meld", "xxdiff", "emerge", "vimdiff", "gvimdiff",
- "diffuse", "ecmerge", "tortoisemerge", and
+ "diffuse", "ecmerge", "tortoisemerge", "araxis", and
"opendiff". Any other value is treated is custom merge tool
and there must be a corresponding mergetool.<tool>.cmd option.
diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt
index 637b53f..adadf8e 100644
--- a/Documentation/merge-options.txt
+++ b/Documentation/merge-options.txt
@@ -39,7 +39,8 @@
--squash::
Produce the working tree and index state as if a real
- merge happened, but do not actually make a commit or
+ merge happened (except for the merge information),
+ but do not actually make a commit or
move the `HEAD`, nor record `$GIT_DIR/MERGE_HEAD` to
cause the next `git commit` command to create a merge
commit. This allows you to create a single commit on
diff --git a/Documentation/technical/api-builtin.txt b/Documentation/technical/api-builtin.txt
index 7ede1e6..5cb2b05 100644
--- a/Documentation/technical/api-builtin.txt
+++ b/Documentation/technical/api-builtin.txt
@@ -37,7 +37,7 @@ where options is the bitwise-or of:
Make sure there is a work tree, i.e. the command cannot act
on bare repositories.
- This makes only sense when `RUN_SETUP` is also set.
+ This only makes sense when `RUN_SETUP` is also set.
. Add `builtin-foo.o` to `BUILTIN_OBJS` in `Makefile`.
diff --git a/Documentation/technical/api-parse-options.txt b/Documentation/technical/api-parse-options.txt
index e66ca9f..50f9e9a 100644
--- a/Documentation/technical/api-parse-options.txt
+++ b/Documentation/technical/api-parse-options.txt
@@ -60,13 +60,13 @@ Steps to parse options
. in `cmd_foo(int argc, const char **argv, const char *prefix)`
call
- argc = parse_options(argc, argv, builtin_foo_options, builtin_foo_usage, flags);
+ argc = parse_options(argc, argv, prefix, builtin_foo_options, builtin_foo_usage, flags);
+
`parse_options()` will filter out the processed options of `argv[]` and leave the
non-option arguments in `argv[]`.
`argc` is updated appropriately because of the assignment.
+
-You can also pass NULL instead of a usage array as fourth parameter of
+You can also pass NULL instead of a usage array as the fifth parameter of
parse_options(), to avoid displaying a help screen with usage info and
option list. This should only be done if necessary, e.g. to implement
a limited parser for only a subset of the options that needs to be run
@@ -137,6 +137,10 @@ There are some macros to easily define options:
Introduce a boolean option.
If used, `int_var` is bitwise-ored with `mask`.
+`OPT_NEGBIT(short, long, &int_var, description, mask)`::
+ Introduce a boolean option.
+ If used, `int_var` is bitwise-anded with the inverted `mask`.
+
`OPT_SET_INT(short, long, &int_var, description, integer)`::
Introduce a boolean option.
If used, set `int_var` to `integer`.
@@ -163,9 +167,22 @@ There are some macros to easily define options:
and the result will be put into `var`.
See 'Option Callbacks' below for a more elaborate description.
+`OPT_FILENAME(short, long, &var, description)`::
+ Introduce an option with a filename argument.
+ The filename will be prefixed by passing the filename along with
+ the prefix argument of `parse_options()` to `prefix_filename()`.
+
`OPT_ARGUMENT(long, description)`::
Introduce a long-option argument that will be kept in `argv[]`.
+`OPT_NUMBER_CALLBACK(&var, description, func_ptr)`::
+ Recognize numerical options like -123 and feed the integer as
+ if it was an argument to the function given by `func_ptr`.
+ The result will be put into `var`. There can be only one such
+ option definition. It cannot be negated and it takes no
+ arguments. Short options that happen to be digits take
+ precedence over it.
+
The last element of the array must be `OPT_END()`.
@@ -198,7 +215,7 @@ The function must be defined in this form:
The callback mechanism is as follows:
-* Inside `funct`, the only interesting member of the structure
+* Inside `func`, the only interesting member of the structure
given by `opt` is the void pointer `opt->value`.
`\*opt->value` will be the value that is saved into `var`, if you
use `OPT_CALLBACK()`.
diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt
index dbbeb7e..0b88a51 100644
--- a/Documentation/user-manual.txt
+++ b/Documentation/user-manual.txt
@@ -1520,10 +1520,10 @@ $ git commit -a -m "blorpl: typofix"
------------------------------------------------
After that, you can go back to what you were working on with
-`git stash apply`:
+`git stash pop`:
------------------------------------------------
-$ git stash apply
+$ git stash pop
------------------------------------------------
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index 97fc1e0..39cde78 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v1.6.2.GIT
+DEF_VER=v1.6.3.GIT
LF='
'
diff --git a/Makefile b/Makefile
index 49f36f5..735ab07 100644
--- a/Makefile
+++ b/Makefile
@@ -3,6 +3,11 @@ all::
# Define V=1 to have a more verbose compile.
#
+# Define SHELL_PATH to a POSIX shell if your /bin/sh is broken.
+#
+# Define SANE_TOOL_PATH to a colon-separated list of paths to prepend
+# to PATH if your tools in /usr/bin are broken.
+#
# Define SNPRINTF_RETURNS_BOGUS if your are on a system which snprintf()
# or vsnprintf() return -1 instead of number of characters which would
# have been written to the final string if enough space had been available.
@@ -52,6 +57,10 @@ all::
#
# Define NO_MKDTEMP if you don't have mkdtemp in the C library.
#
+# Define NO_MKSTEMPS if you don't have mkstemps in the C library.
+#
+# Define NO_LIBGEN_H if you don't have libgen.h.
+#
# Define NO_SYS_SELECT_H if you don't have sys/select.h.
#
# Define NO_SYMLINK_HEAD if you never want .git/HEAD to be a symbolic link.
@@ -91,6 +100,10 @@ all::
# Define NEEDS_SOCKET if linking with libc is not enough (SunOS,
# Patrick Mauritz).
#
+# Define NEEDS_RESOLV if linking with -lnsl and/or -lsocket is not enough.
+# Notably on Solaris hstrerror resides in libresolv and on Solaris 7
+# inet_ntop and inet_pton additionally reside there.
+#
# Define NO_MMAP if you want to avoid mmap.
#
# Define NO_PTHREADS if you do not have or do not want to use Pthreads.
@@ -171,6 +184,13 @@ all::
# Define UNRELIABLE_FSTAT if your system's fstat does not return the same
# information on a not yet closed file that lstat would return for the same
# file after it was closed.
+#
+# Define OBJECT_CREATION_USES_RENAMES if your operating systems has problems
+# when hardlinking a file to another name and unlinking the original file right
+# away (some NTFS drivers seem to zero the contents in that scenario).
+#
+# Define NO_CROSS_DIRECTORY_HARDLINKS if you plan to distribute the installed
+# programs as a tar, where bin/ and libexec/ might be on different file systems.
GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
@$(SHELL_PATH) ./GIT-VERSION-GEN
@@ -221,6 +241,7 @@ ETC_GITCONFIG = etc/gitconfig
endif
lib = lib
# DESTDIR=
+pathsep = :
# default configuration for gitweb
GITWEB_CONFIG = gitweb_config.perl
@@ -328,7 +349,6 @@ PROGRAMS += git-index-pack$X
PROGRAMS += git-merge-index$X
PROGRAMS += git-merge-tree$X
PROGRAMS += git-mktag$X
-PROGRAMS += git-mktree$X
PROGRAMS += git-pack-redundant$X
PROGRAMS += git-patch-id$X
PROGRAMS += git-shell$X
@@ -361,9 +381,6 @@ ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
# what 'all' will build but not install in gitexecdir
OTHER_PROGRAMS = git$X
-ifndef NO_PERL
-OTHER_PROGRAMS += gitweb/gitweb.cgi
-endif
# Set paths to tools early so that they can be used for version tests.
ifndef SHELL_PATH
@@ -585,6 +602,7 @@ BUILTIN_OBJS += builtin-merge-base.o
BUILTIN_OBJS += builtin-merge-file.o
BUILTIN_OBJS += builtin-merge-ours.o
BUILTIN_OBJS += builtin-merge-recursive.o
+BUILTIN_OBJS += builtin-mktree.o
BUILTIN_OBJS += builtin-mv.o
BUILTIN_OBJS += builtin-name-rev.o
BUILTIN_OBJS += builtin-pack-objects.o
@@ -631,10 +649,12 @@ EXTLIBS =
ifeq ($(uname_S),Linux)
NO_STRLCPY = YesPlease
+ NO_MKSTEMPS = YesPlease
THREADED_DELTA_SEARCH = YesPlease
endif
ifeq ($(uname_S),GNU/kFreeBSD)
NO_STRLCPY = YesPlease
+ NO_MKSTEMPS = YesPlease
THREADED_DELTA_SEARCH = YesPlease
endif
ifeq ($(uname_S),UnixWare)
@@ -646,6 +666,7 @@ ifeq ($(uname_S),UnixWare)
SHELL_PATH = /usr/local/bin/bash
NO_IPV6 = YesPlease
NO_HSTRERROR = YesPlease
+ NO_MKSTEMPS = YesPlease
BASIC_CFLAGS += -Kthread
BASIC_CFLAGS += -I/usr/local/include
BASIC_LDFLAGS += -L/usr/local/lib
@@ -669,6 +690,7 @@ ifeq ($(uname_S),SCO_SV)
SHELL_PATH = /usr/bin/bash
NO_IPV6 = YesPlease
NO_HSTRERROR = YesPlease
+ NO_MKSTEMPS = YesPlease
BASIC_CFLAGS += -I/usr/local/include
BASIC_LDFLAGS += -L/usr/local/lib
NO_STRCASESTR = YesPlease
@@ -693,11 +715,21 @@ ifeq ($(uname_S),SunOS)
NEEDS_SOCKET = YesPlease
NEEDS_NSL = YesPlease
SHELL_PATH = /bin/bash
+ SANE_TOOL_PATH = /usr/xpg6/bin:/usr/xpg4/bin
NO_STRCASESTR = YesPlease
NO_MEMMEM = YesPlease
- NO_HSTRERROR = YesPlease
NO_MKDTEMP = YesPlease
- OLD_ICONV = UnfortunatelyYes
+ NO_MKSTEMPS = YesPlease
+ ifeq ($(uname_R),5.7)
+ NEEDS_RESOLV = YesPlease
+ NO_IPV6 = YesPlease
+ NO_SOCKADDR_STORAGE = YesPlease
+ NO_UNSETENV = YesPlease
+ NO_SETENV = YesPlease
+ NO_STRLCPY = YesPlease
+ NO_C99_FORMAT = YesPlease
+ NO_STRTOUMAX = YesPlease
+ endif
ifeq ($(uname_R),5.8)
NO_UNSETENV = YesPlease
NO_SETENV = YesPlease
@@ -710,15 +742,19 @@ ifeq ($(uname_S),SunOS)
NO_C99_FORMAT = YesPlease
NO_STRTOUMAX = YesPlease
endif
- INSTALL = ginstall
+ ifdef NO_IPV6
+ NEEDS_RESOLV = YesPlease
+ endif
+ INSTALL = /usr/ucb/install
TAR = gtar
- BASIC_CFLAGS += -D__EXTENSIONS__
+ BASIC_CFLAGS += -D__EXTENSIONS__ -D__sun__
endif
ifeq ($(uname_O),Cygwin)
NO_D_TYPE_IN_DIRENT = YesPlease
NO_D_INO_IN_DIRENT = YesPlease
NO_STRCASESTR = YesPlease
NO_MEMMEM = YesPlease
+ NO_MKSTEMPS = YesPlease
NO_SYMLINK_HEAD = YesPlease
NEEDS_LIBICONV = YesPlease
NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes
@@ -748,6 +784,7 @@ endif
ifeq ($(uname_S),OpenBSD)
NO_STRCASESTR = YesPlease
NO_MEMMEM = YesPlease
+ USE_ST_TIMESPEC = YesPlease
NEEDS_LIBICONV = YesPlease
BASIC_CFLAGS += -I/usr/local/include
BASIC_LDFLAGS += -L/usr/local/lib
@@ -760,11 +797,14 @@ ifeq ($(uname_S),NetBSD)
BASIC_CFLAGS += -I/usr/pkg/include
BASIC_LDFLAGS += -L/usr/pkg/lib $(CC_LD_DYNPATH)/usr/pkg/lib
THREADED_DELTA_SEARCH = YesPlease
+ USE_ST_TIMESPEC = YesPlease
+ NO_MKSTEMPS = YesPlease
endif
ifeq ($(uname_S),AIX)
NO_STRCASESTR=YesPlease
NO_MEMMEM = YesPlease
NO_MKDTEMP = YesPlease
+ NO_MKSTEMPS = YesPlease
NO_STRLCPY = YesPlease
NO_NSEC = YesPlease
FREAD_READS_DIRECTORIES = UnfortunatelyYes
@@ -780,12 +820,14 @@ endif
ifeq ($(uname_S),GNU)
# GNU/Hurd
NO_STRLCPY=YesPlease
+ NO_MKSTEMPS = YesPlease
endif
ifeq ($(uname_S),IRIX64)
NO_IPV6=YesPlease
NO_SETENV=YesPlease
NO_STRCASESTR=YesPlease
NO_MEMMEM = YesPlease
+ NO_MKSTEMPS = YesPlease
NO_STRLCPY = YesPlease
NO_SOCKADDR_STORAGE=YesPlease
SHELL_PATH=/usr/gnu/bin/bash
@@ -798,6 +840,7 @@ ifeq ($(uname_S),HP-UX)
NO_SETENV=YesPlease
NO_STRCASESTR=YesPlease
NO_MEMMEM = YesPlease
+ NO_MKSTEMPS = YesPlease
NO_STRLCPY = YesPlease
NO_MKDTEMP = YesPlease
NO_UNSETENV = YesPlease
@@ -810,9 +853,11 @@ ifneq (,$(findstring CYGWIN,$(uname_S)))
UNRELIABLE_FSTAT = UnfortunatelyYes
endif
ifneq (,$(findstring MINGW,$(uname_S)))
+ pathsep = ;
NO_PREAD = YesPlease
NO_OPENSSL = YesPlease
NO_CURL = YesPlease
+ NO_LIBGEN_H = YesPlease
NO_SYMLINK_HEAD = YesPlease
NO_IPV6 = YesPlease
NO_SETENV = YesPlease
@@ -826,6 +871,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
NO_C99_FORMAT = YesPlease
NO_STRTOUMAX = YesPlease
NO_MKDTEMP = YesPlease
+ NO_MKSTEMPS = YesPlease
SNPRINTF_RETURNS_BOGUS = YesPlease
NO_SVN_TESTS = YesPlease
NO_PERL_MAKEMAKER = YesPlease
@@ -835,6 +881,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
NO_NSEC = YesPlease
USE_WIN32_MMAP = YesPlease
UNRELIABLE_FSTAT = UnfortunatelyYes
+ OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo
COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/regex -Icompat/fnmatch
COMPAT_CFLAGS += -DSNPRINTF_SIZE_CORR=1
COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
@@ -844,11 +891,20 @@ ifneq (,$(findstring MINGW,$(uname_S)))
endif
ifneq (,$(findstring arm,$(uname_M)))
ARM_SHA1 = YesPlease
+ NO_MKSTEMPS = YesPlease
endif
-include config.mak.autogen
-include config.mak
+ifdef SANE_TOOL_PATH
+SANE_TOOL_PATH_SQ = $(subst ','\'',$(SANE_TOOL_PATH))
+BROKEN_PATH_FIX = 's|^\# @@BROKEN_PATH_FIX@@$$|git_broken_path_fix $(SANE_TOOL_PATH_SQ)|'
+PATH := $(SANE_TOOL_PATH):${PATH}
+else
+BROKEN_PATH_FIX = '/^\# @@BROKEN_PATH_FIX@@$$/d'
+endif
+
ifeq ($(uname_S),Darwin)
ifndef NO_FINK
ifeq ($(shell test -d /sw/lib && echo y),y)
@@ -875,6 +931,11 @@ ifndef CC_LD_DYNPATH
endif
endif
+ifdef NO_LIBGEN_H
+ COMPAT_CFLAGS += -DNO_LIBGEN_H
+ COMPAT_OBJS += compat/basename.o
+endif
+
ifdef NO_CURL
BASIC_CFLAGS += -DNO_CURL
else
@@ -947,6 +1008,9 @@ endif
ifdef NEEDS_NSL
EXTLIBS += -lnsl
endif
+ifdef NEEDS_RESOLV
+ EXTLIBS += -lresolv
+endif
ifdef NO_D_TYPE_IN_DIRENT
BASIC_CFLAGS += -DNO_D_TYPE_IN_DIRENT
endif
@@ -1002,6 +1066,10 @@ ifdef NO_MKDTEMP
COMPAT_CFLAGS += -DNO_MKDTEMP
COMPAT_OBJS += compat/mkdtemp.o
endif
+ifdef NO_MKSTEMPS
+ COMPAT_CFLAGS += -DNO_MKSTEMPS
+ COMPAT_OBJS += compat/mkstemps.o
+endif
ifdef NO_UNSETENV
COMPAT_CFLAGS += -DNO_UNSETENV
COMPAT_OBJS += compat/unsetenv.o
@@ -1018,6 +1086,9 @@ else
COMPAT_OBJS += compat/win32mmap.o
endif
endif
+ifdef OBJECT_CREATION_USES_RENAMES
+ COMPAT_CFLAGS += -DOBJECT_CREATION_MODE=1
+endif
ifdef NO_PREAD
COMPAT_CFLAGS += -DNO_PREAD
COMPAT_OBJS += compat/pread.o
@@ -1242,9 +1313,9 @@ $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
$(QUIET_GEN)$(RM) $@ $@+ && \
sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
-e 's|@SHELL_PATH@|$(SHELL_PATH_SQ)|' \
- -e 's|@@PERL@@|$(PERL_PATH_SQ)|g' \
-e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
-e 's/@@NO_CURL@@/$(NO_CURL)/g' \
+ -e $(BROKEN_PATH_FIX) \
$@.sh >$@+ && \
chmod +x $@+ && \
mv $@+ $@
@@ -1261,7 +1332,7 @@ $(patsubst %.perl,%,$(SCRIPT_PERL)): % : %.perl
sed -e '1{' \
-e ' s|#!.*perl|#!$(PERL_PATH_SQ)|' \
-e ' h' \
- -e ' s=.*=use lib (split(/:/, $$ENV{GITPERLLIB} || "@@INSTLIBDIR@@"));=' \
+ -e ' s=.*=use lib (split(/$(pathsep)/, $$ENV{GITPERLLIB} || "@@INSTLIBDIR@@"));=' \
-e ' H' \
-e ' x' \
-e '}' \
@@ -1271,6 +1342,7 @@ $(patsubst %.perl,%,$(SCRIPT_PERL)): % : %.perl
chmod +x $@+ && \
mv $@+ $@
+OTHER_PROGRAMS += gitweb/gitweb.cgi
gitweb/gitweb.cgi: gitweb/gitweb.perl
$(QUIET_GEN)$(RM) $@ $@+ && \
sed -e '1s|#!.*perl|#!$(PERL_PATH_SQ)|' \
@@ -1483,6 +1555,8 @@ test-delta$X: diff-delta.o patch-delta.o
test-parse-options$X: parse-options.o
+test-parse-options.o: parse-options.h
+
.PRECIOUS: $(patsubst test-%$X,test-%.o,$(TEST_PROGRAMS))
test-%$X: test-%.o $(GITLIBS)
@@ -1529,17 +1603,20 @@ install: all
$(INSTALL) $(ALL_PROGRAMS) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
$(INSTALL) git$X git-upload-pack$X git-receive-pack$X git-upload-archive$X git-shell$X git-cvsserver '$(DESTDIR_SQ)$(bindir_SQ)'
$(MAKE) -C templates DESTDIR='$(DESTDIR_SQ)' install
+ifndef NO_PERL
$(MAKE) -C perl prefix='$(prefix_SQ)' DESTDIR='$(DESTDIR_SQ)' install
+endif
ifndef NO_TCLTK
$(MAKE) -C gitk-git install
$(MAKE) -C git-gui gitexecdir='$(gitexec_instdir_SQ)' install
endif
ifneq (,$X)
- $(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), $(RM) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p';)
+ $(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), test '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p' -ef '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p$X' || $(RM) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p';)
endif
bindir=$$(cd '$(DESTDIR_SQ)$(bindir_SQ)' && pwd) && \
execdir=$$(cd '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' && pwd) && \
{ $(RM) "$$execdir/git-add$X" && \
+ test -z "$(NO_CROSS_DIRECTORY_HARDLINKS)" && \
ln "$$bindir/git$X" "$$execdir/git-add$X" 2>/dev/null || \
cp "$$bindir/git$X" "$$execdir/git-add$X"; } && \
{ for p in $(filter-out git-add$X,$(BUILT_INS)); do \
@@ -1547,7 +1624,7 @@ endif
ln "$$execdir/git-add$X" "$$execdir/$$p" 2>/dev/null || \
ln -s "git-add$X" "$$execdir/$$p" 2>/dev/null || \
cp "$$execdir/git-add$X" "$$execdir/$$p" || exit; \
- done } && \
+ done; } && \
./check_bindir "z$$bindir" "z$$execdir" "$$bindir/git-add$X"
install-doc:
diff --git a/RelNotes b/RelNotes
index dd8bc4b..f8e49a5 120000
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes-1.6.3.txt \ No newline at end of file
+Documentation/RelNotes-1.6.4.txt \ No newline at end of file
diff --git a/alias.c b/alias.c
index ccb1108..372b7d8 100644
--- a/alias.c
+++ b/alias.c
@@ -27,7 +27,7 @@ int split_cmdline(char *cmdline, const char ***argv)
int src, dst, count = 0, size = 16;
char quoted = 0;
- *argv = xmalloc(sizeof(char*) * size);
+ *argv = xmalloc(sizeof(char *) * size);
/* split alias_string */
(*argv)[count++] = cmdline;
@@ -38,10 +38,7 @@ int split_cmdline(char *cmdline, const char ***argv)
while (cmdline[++src]
&& isspace(cmdline[src]))
; /* skip */
- if (count >= size) {
- size += 16;
- *argv = xrealloc(*argv, sizeof(char*) * size);
- }
+ ALLOC_GROW(*argv, count+1, size);
(*argv)[count++] = cmdline + dst;
} else if (!quoted && (c == '\'' || c == '"')) {
quoted = c;
@@ -72,6 +69,9 @@ int split_cmdline(char *cmdline, const char ***argv)
return error("unclosed quote");
}
+ ALLOC_GROW(*argv, count+1, size);
+ (*argv)[count] = NULL;
+
return count;
}
diff --git a/alloc.c b/alloc.c
index 216c23a..6ef6753 100644
--- a/alloc.c
+++ b/alloc.c
@@ -57,7 +57,7 @@ DEFINE_ALLOCATOR(object, union any_object)
#define SZ_FMT "%zu"
#endif
-static void report(const char* name, unsigned int count, size_t size)
+static void report(const char *name, unsigned int count, size_t size)
{
fprintf(stderr, "%10s: %8u (" SZ_FMT " kB)\n", name, count, size);
}
diff --git a/archive-tar.c b/archive-tar.c
index ba890eb..cee06ce 100644
--- a/archive-tar.c
+++ b/archive-tar.c
@@ -180,7 +180,7 @@ static int write_tar_entry(struct archiver_args *args,
sprintf(header.mode, "%07o", mode & 07777);
sprintf(header.size, "%011lo", S_ISREG(mode) ? size : 0);
- sprintf(header.mtime, "%011lo", args->time);
+ sprintf(header.mtime, "%011lo", (unsigned long) args->time);
sprintf(header.uid, "%07o", 0);
sprintf(header.gid, "%07o", 0);
diff --git a/archive.c b/archive.c
index b2b90d3..0bca9ca 100644
--- a/archive.c
+++ b/archive.c
@@ -309,7 +309,7 @@ static int parse_archive_args(int argc, const char **argv,
OPT_END()
};
- argc = parse_options(argc, argv, opts, archive_usage, 0);
+ argc = parse_options(argc, argv, NULL, opts, archive_usage, 0);
if (remote)
die("Unexpected option --remote");
diff --git a/attr.c b/attr.c
index f1ca4f5..98eb636 100644
--- a/attr.c
+++ b/attr.c
@@ -224,7 +224,7 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
if (is_macro)
res->u.attr = git_attr(name, namelen);
else {
- res->u.pattern = (char*)&(res->state[num_attr]);
+ res->u.pattern = (char *)&(res->state[num_attr]);
memcpy(res->u.pattern, name, namelen);
res->u.pattern[namelen] = 0;
}
@@ -275,7 +275,7 @@ static void free_attr_elem(struct attr_stack *e)
setto == ATTR__UNKNOWN)
;
else
- free((char*) setto);
+ free((char *) setto);
}
free(a);
}
diff --git a/bisect.c b/bisect.c
index 58f7e6f..c43c120 100644
--- a/bisect.c
+++ b/bisect.c
@@ -6,15 +6,30 @@
#include "list-objects.h"
#include "quote.h"
#include "sha1-lookup.h"
+#include "run-command.h"
#include "bisect.h"
-static unsigned char (*skipped_sha1)[20];
-static int skipped_sha1_nr;
-static int skipped_sha1_alloc;
+struct sha1_array {
+ unsigned char (*sha1)[20];
+ int sha1_nr;
+ int sha1_alloc;
+ int sorted;
+};
+
+static struct sha1_array good_revs;
+static struct sha1_array skipped_revs;
+
+static const unsigned char *current_bad_sha1;
+
+struct argv_array {
+ const char **argv;
+ int argv_nr;
+ int argv_alloc;
+};
-static const char **rev_argv;
-static int rev_argv_nr;
-static int rev_argv_alloc;
+static const char *argv_diff_tree[] = {"diff-tree", "--pretty", NULL, NULL};
+static const char *argv_checkout[] = {"checkout", "-q", NULL, "--", NULL};
+static const char *argv_show_branch[] = {"show-branch", NULL, NULL};
/* bits #0-15 in revision.h */
@@ -398,23 +413,37 @@ struct commit_list *find_bisection(struct commit_list *list,
return best;
}
+static void argv_array_push(struct argv_array *array, const char *string)
+{
+ ALLOC_GROW(array->argv, array->argv_nr + 1, array->argv_alloc);
+ array->argv[array->argv_nr++] = string;
+}
+
+static void argv_array_push_sha1(struct argv_array *array,
+ const unsigned char *sha1,
+ const char *format)
+{
+ struct strbuf buf = STRBUF_INIT;
+ strbuf_addf(&buf, format, sha1_to_hex(sha1));
+ argv_array_push(array, strbuf_detach(&buf, NULL));
+}
+
+static void sha1_array_push(struct sha1_array *array,
+ const unsigned char *sha1)
+{
+ ALLOC_GROW(array->sha1, array->sha1_nr + 1, array->sha1_alloc);
+ hashcpy(array->sha1[array->sha1_nr++], sha1);
+}
+
static int register_ref(const char *refname, const unsigned char *sha1,
int flags, void *cb_data)
{
if (!strcmp(refname, "bad")) {
- ALLOC_GROW(rev_argv, rev_argv_nr + 1, rev_argv_alloc);
- rev_argv[rev_argv_nr++] = xstrdup(sha1_to_hex(sha1));
+ current_bad_sha1 = sha1;
} else if (!prefixcmp(refname, "good-")) {
- const char *hex = sha1_to_hex(sha1);
- char *good = xmalloc(strlen(hex) + 2);
- *good = '^';
- memcpy(good + 1, hex, strlen(hex) + 1);
- ALLOC_GROW(rev_argv, rev_argv_nr + 1, rev_argv_alloc);
- rev_argv[rev_argv_nr++] = good;
+ sha1_array_push(&good_revs, sha1);
} else if (!prefixcmp(refname, "skip-")) {
- ALLOC_GROW(skipped_sha1, skipped_sha1_nr + 1,
- skipped_sha1_alloc);
- hashcpy(skipped_sha1[skipped_sha1_nr++], sha1);
+ sha1_array_push(&skipped_revs, sha1);
}
return 0;
@@ -425,7 +454,7 @@ static int read_bisect_refs(void)
return for_each_ref_in("refs/bisect/", register_ref, NULL);
}
-void read_bisect_paths(void)
+void read_bisect_paths(struct argv_array *array)
{
struct strbuf str = STRBUF_INIT;
const char *filename = git_path("BISECT_NAMES");
@@ -440,8 +469,8 @@ void read_bisect_paths(void)
strbuf_trim(&str);
quoted = strbuf_detach(&str, NULL);
- res = sq_dequote_to_argv(quoted, &rev_argv,
- &rev_argv_nr, &rev_argv_alloc);
+ res = sq_dequote_to_argv(quoted, &array->argv,
+ &array->argv_nr, &array->argv_alloc);
if (res)
die("Badly quoted content in file '%s': %s",
filename, quoted);
@@ -451,26 +480,45 @@ void read_bisect_paths(void)
fclose(fp);
}
-static int skipcmp(const void *a, const void *b)
+static int array_cmp(const void *a, const void *b)
{
return hashcmp(a, b);
}
-static void prepare_skipped(void)
+static void sort_sha1_array(struct sha1_array *array)
{
- qsort(skipped_sha1, skipped_sha1_nr, sizeof(*skipped_sha1), skipcmp);
+ qsort(array->sha1, array->sha1_nr, sizeof(*array->sha1), array_cmp);
+
+ array->sorted = 1;
}
-static const unsigned char *skipped_sha1_access(size_t index, void *table)
+static const unsigned char *sha1_access(size_t index, void *table)
{
- unsigned char (*skipped)[20] = table;
- return skipped[index];
+ unsigned char (*array)[20] = table;
+ return array[index];
}
-static int lookup_skipped(unsigned char *sha1)
+static int lookup_sha1_array(struct sha1_array *array,
+ const unsigned char *sha1)
{
- return sha1_pos(sha1, skipped_sha1, skipped_sha1_nr,
- skipped_sha1_access);
+ if (!array->sorted)
+ sort_sha1_array(array);
+
+ return sha1_pos(sha1, array->sha1, array->sha1_nr, sha1_access);
+}
+
+static char *join_sha1_array_hex(struct sha1_array *array, char delim)
+{
+ struct strbuf joined_hexs = STRBUF_INIT;
+ int i;
+
+ for (i = 0; i < array->sha1_nr; i++) {
+ strbuf_addstr(&joined_hexs, sha1_to_hex(array->sha1[i]));
+ if (i + 1 < array->sha1_nr)
+ strbuf_addch(&joined_hexs, delim);
+ }
+
+ return strbuf_detach(&joined_hexs, NULL);
}
struct commit_list *filter_skipped(struct commit_list *list,
@@ -481,15 +529,14 @@ struct commit_list *filter_skipped(struct commit_list *list,
*tried = NULL;
- if (!skipped_sha1_nr)
+ if (!skipped_revs.sha1_nr)
return list;
- prepare_skipped();
-
while (list) {
struct commit_list *next = list->next;
list->next = NULL;
- if (0 <= lookup_skipped(list->item->object.sha1)) {
+ if (0 <= lookup_sha1_array(&skipped_revs,
+ list->item->object.sha1)) {
/* Move current to tried list */
*tried = list;
tried = &list->next;
@@ -506,51 +553,323 @@ struct commit_list *filter_skipped(struct commit_list *list,
return filtered;
}
-static void bisect_rev_setup(struct rev_info *revs, const char *prefix)
+static void bisect_rev_setup(struct rev_info *revs, const char *prefix,
+ const char *bad_format, const char *good_format,
+ int read_paths)
{
+ struct argv_array rev_argv = { NULL, 0, 0 };
+ int i;
+
init_revisions(revs, prefix);
revs->abbrev = 0;
revs->commit_format = CMIT_FMT_UNSPECIFIED;
- /* argv[0] will be ignored by setup_revisions */
- ALLOC_GROW(rev_argv, rev_argv_nr + 1, rev_argv_alloc);
- rev_argv[rev_argv_nr++] = xstrdup("bisect_rev_setup");
+ /* rev_argv.argv[0] will be ignored by setup_revisions */
+ argv_array_push(&rev_argv, xstrdup("bisect_rev_setup"));
+ argv_array_push_sha1(&rev_argv, current_bad_sha1, bad_format);
+ for (i = 0; i < good_revs.sha1_nr; i++)
+ argv_array_push_sha1(&rev_argv, good_revs.sha1[i],
+ good_format);
+ argv_array_push(&rev_argv, xstrdup("--"));
+ if (read_paths)
+ read_bisect_paths(&rev_argv);
+ argv_array_push(&rev_argv, NULL);
+
+ setup_revisions(rev_argv.argv_nr, rev_argv.argv, revs, NULL);
+}
- if (read_bisect_refs())
- die("reading bisect refs failed");
+static void bisect_common(struct rev_info *revs)
+{
+ if (prepare_revision_walk(revs))
+ die("revision walk setup failed");
+ if (revs->tree_objects)
+ mark_edges_uninteresting(revs->commits, revs, NULL);
+}
+
+static void exit_if_skipped_commits(struct commit_list *tried,
+ const unsigned char *bad)
+{
+ if (!tried)
+ return;
+
+ printf("There are only 'skip'ped commits left to test.\n"
+ "The first bad commit could be any of:\n");
+ print_commit_list(tried, "%s\n", "%s\n");
+ if (bad)
+ printf("%s\n", sha1_to_hex(bad));
+ printf("We cannot bisect more!\n");
+ exit(2);
+}
+
+static int is_expected_rev(const unsigned char *sha1)
+{
+ const char *filename = git_path("BISECT_EXPECTED_REV");
+ struct stat st;
+ struct strbuf str = STRBUF_INIT;
+ FILE *fp;
+ int res = 0;
+
+ if (stat(filename, &st) || !S_ISREG(st.st_mode))
+ return 0;
+
+ fp = fopen(filename, "r");
+ if (!fp)
+ return 0;
+
+ if (strbuf_getline(&str, fp, '\n') != EOF)
+ res = !strcmp(str.buf, sha1_to_hex(sha1));
+
+ strbuf_release(&str);
+ fclose(fp);
+
+ return res;
+}
+
+static void mark_expected_rev(char *bisect_rev_hex)
+{
+ int len = strlen(bisect_rev_hex);
+ const char *filename = git_path("BISECT_EXPECTED_REV");
+ int fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0600);
+
+ if (fd < 0)
+ die("could not create file '%s': %s",
+ filename, strerror(errno));
- ALLOC_GROW(rev_argv, rev_argv_nr + 1, rev_argv_alloc);
- rev_argv[rev_argv_nr++] = xstrdup("--");
+ bisect_rev_hex[len] = '\n';
+ write_or_die(fd, bisect_rev_hex, len + 1);
+ bisect_rev_hex[len] = '\0';
- read_bisect_paths();
+ if (close(fd) < 0)
+ die("closing file %s: %s", filename, strerror(errno));
+}
+
+static int bisect_checkout(char *bisect_rev_hex)
+{
+ int res;
- ALLOC_GROW(rev_argv, rev_argv_nr + 1, rev_argv_alloc);
- rev_argv[rev_argv_nr++] = NULL;
+ mark_expected_rev(bisect_rev_hex);
- setup_revisions(rev_argv_nr, rev_argv, revs, NULL);
+ argv_checkout[2] = bisect_rev_hex;
+ res = run_command_v_opt(argv_checkout, RUN_GIT_CMD);
+ if (res)
+ exit(res);
- revs->limited = 1;
+ argv_show_branch[1] = bisect_rev_hex;
+ return run_command_v_opt(argv_show_branch, RUN_GIT_CMD);
}
-int bisect_next_vars(const char *prefix)
+static struct commit *get_commit_reference(const unsigned char *sha1)
+{
+ struct commit *r = lookup_commit_reference(sha1);
+ if (!r)
+ die("Not a valid commit name %s", sha1_to_hex(sha1));
+ return r;
+}
+
+static struct commit **get_bad_and_good_commits(int *rev_nr)
+{
+ int len = 1 + good_revs.sha1_nr;
+ struct commit **rev = xmalloc(len * sizeof(*rev));
+ int i, n = 0;
+
+ rev[n++] = get_commit_reference(current_bad_sha1);
+ for (i = 0; i < good_revs.sha1_nr; i++)
+ rev[n++] = get_commit_reference(good_revs.sha1[i]);
+ *rev_nr = n;
+
+ return rev;
+}
+
+static void handle_bad_merge_base(void)
+{
+ if (is_expected_rev(current_bad_sha1)) {
+ char *bad_hex = sha1_to_hex(current_bad_sha1);
+ char *good_hex = join_sha1_array_hex(&good_revs, ' ');
+
+ fprintf(stderr, "The merge base %s is bad.\n"
+ "This means the bug has been fixed "
+ "between %s and [%s].\n",
+ bad_hex, bad_hex, good_hex);
+
+ exit(3);
+ }
+
+ fprintf(stderr, "Some good revs are not ancestor of the bad rev.\n"
+ "git bisect cannot work properly in this case.\n"
+ "Maybe you mistake good and bad revs?\n");
+ exit(1);
+}
+
+void handle_skipped_merge_base(const unsigned char *mb)
+{
+ char *mb_hex = sha1_to_hex(mb);
+ char *bad_hex = sha1_to_hex(current_bad_sha1);
+ char *good_hex = join_sha1_array_hex(&good_revs, ' ');
+
+ fprintf(stderr, "Warning: the merge base between %s and [%s] "
+ "must be skipped.\n"
+ "So we cannot be sure the first bad commit is "
+ "between %s and %s.\n"
+ "We continue anyway.\n",
+ bad_hex, good_hex, mb_hex, bad_hex);
+ free(good_hex);
+}
+
+/*
+ * "check_merge_bases" checks that merge bases are not "bad".
+ *
+ * - If one is "bad", it means the user assumed something wrong
+ * and we must exit with a non 0 error code.
+ * - If one is "good", that's good, we have nothing to do.
+ * - If one is "skipped", we can't know but we should warn.
+ * - If we don't know, we should check it out and ask the user to test.
+ */
+static void check_merge_bases(void)
+{
+ struct commit_list *result;
+ int rev_nr;
+ struct commit **rev = get_bad_and_good_commits(&rev_nr);
+
+ result = get_merge_bases_many(rev[0], rev_nr - 1, rev + 1, 0);
+
+ for (; result; result = result->next) {
+ const unsigned char *mb = result->item->object.sha1;
+ if (!hashcmp(mb, current_bad_sha1)) {
+ handle_bad_merge_base();
+ } else if (0 <= lookup_sha1_array(&good_revs, mb)) {
+ continue;
+ } else if (0 <= lookup_sha1_array(&skipped_revs, mb)) {
+ handle_skipped_merge_base(mb);
+ } else {
+ printf("Bisecting: a merge base must be tested\n");
+ exit(bisect_checkout(sha1_to_hex(mb)));
+ }
+ }
+
+ free(rev);
+ free_commit_list(result);
+}
+
+static int check_ancestors(const char *prefix)
{
struct rev_info revs;
- struct rev_list_info info;
- int reaches = 0, all = 0;
+ struct object_array pending_copy;
+ int i, res;
- memset(&info, 0, sizeof(info));
- info.revs = &revs;
- info.bisect_show_flags = BISECT_SHOW_TRIED | BISECT_SHOW_STRINGED;
+ bisect_rev_setup(&revs, prefix, "^%s", "%s", 0);
- bisect_rev_setup(&revs, prefix);
+ /* Save pending objects, so they can be cleaned up later. */
+ memset(&pending_copy, 0, sizeof(pending_copy));
+ for (i = 0; i < revs.pending.nr; i++)
+ add_object_array(revs.pending.objects[i].item,
+ revs.pending.objects[i].name,
+ &pending_copy);
- if (prepare_revision_walk(&revs))
- die("revision walk setup failed");
- if (revs.tree_objects)
- mark_edges_uninteresting(revs.commits, &revs, NULL);
+ bisect_common(&revs);
+ res = (revs.commits != NULL);
+
+ /* Clean up objects used, as they will be reused. */
+ for (i = 0; i < pending_copy.nr; i++) {
+ struct object *o = pending_copy.objects[i].item;
+ unparse_commit((struct commit *)o);
+ }
+
+ return res;
+}
+
+/*
+ * "check_good_are_ancestors_of_bad" checks that all "good" revs are
+ * ancestor of the "bad" rev.
+ *
+ * If that's not the case, we need to check the merge bases.
+ * If a merge base must be tested by the user, its source code will be
+ * checked out to be tested by the user and we will exit.
+ */
+static void check_good_are_ancestors_of_bad(const char *prefix)
+{
+ const char *filename = git_path("BISECT_ANCESTORS_OK");
+ struct stat st;
+ int fd;
+
+ if (!current_bad_sha1)
+ die("a bad revision is needed");
+
+ /* Check if file BISECT_ANCESTORS_OK exists. */
+ if (!stat(filename, &st) && S_ISREG(st.st_mode))
+ return;
+
+ /* Bisecting with no good rev is ok. */
+ if (good_revs.sha1_nr == 0)
+ return;
+
+ /* Check if all good revs are ancestor of the bad rev. */
+ if (check_ancestors(prefix))
+ check_merge_bases();
+
+ /* Create file BISECT_ANCESTORS_OK. */
+ fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0600);
+ if (fd < 0)
+ warning("could not create file '%s': %s",
+ filename, strerror(errno));
+ else
+ close(fd);
+}
+
+/*
+ * We use the convention that exiting with an exit code 10 means that
+ * the bisection process finished successfully.
+ * In this case the calling shell script should exit 0.
+ */
+int bisect_next_all(const char *prefix)
+{
+ struct rev_info revs;
+ struct commit_list *tried;
+ int reaches = 0, all = 0, nr;
+ const unsigned char *bisect_rev;
+ char bisect_rev_hex[41];
+
+ if (read_bisect_refs())
+ die("reading bisect refs failed");
+
+ check_good_are_ancestors_of_bad(prefix);
+
+ bisect_rev_setup(&revs, prefix, "%s", "^%s", 1);
+ revs.limited = 1;
+
+ bisect_common(&revs);
revs.commits = find_bisection(revs.commits, &reaches, &all,
- !!skipped_sha1_nr);
+ !!skipped_revs.sha1_nr);
+ revs.commits = filter_skipped(revs.commits, &tried, 0);
+
+ if (!revs.commits) {
+ /*
+ * We should exit here only if the "bad"
+ * commit is also a "skip" commit.
+ */
+ exit_if_skipped_commits(tried, NULL);
+
+ printf("%s was both good and bad\n",
+ sha1_to_hex(current_bad_sha1));
+ exit(1);
+ }
- return show_bisect_vars(&info, reaches, all);
+ bisect_rev = revs.commits->item->object.sha1;
+ memcpy(bisect_rev_hex, sha1_to_hex(bisect_rev), 41);
+
+ if (!hashcmp(bisect_rev, current_bad_sha1)) {
+ exit_if_skipped_commits(tried, current_bad_sha1);
+ printf("%s is first bad commit\n", bisect_rev_hex);
+ argv_diff_tree[2] = bisect_rev_hex;
+ run_command_v_opt(argv_diff_tree, RUN_GIT_CMD);
+ /* This means the bisection process succeeded. */
+ exit(10);
+ }
+
+ nr = all - reaches - 1;
+ printf("Bisecting: %d revisions left to test after this "
+ "(roughly %d steps)\n", nr, estimate_bisect_steps(all));
+
+ return bisect_checkout(bisect_rev_hex);
}
+
diff --git a/bisect.h b/bisect.h
index fdba913..fb744fd 100644
--- a/bisect.h
+++ b/bisect.h
@@ -9,10 +9,13 @@ extern struct commit_list *filter_skipped(struct commit_list *list,
struct commit_list **tried,
int show_all);
+extern void print_commit_list(struct commit_list *list,
+ const char *format_cur,
+ const char *format_last);
+
/* bisect_show_flags flags in struct rev_list_info */
#define BISECT_SHOW_ALL (1<<0)
#define BISECT_SHOW_TRIED (1<<1)
-#define BISECT_SHOW_STRINGED (1<<2)
struct rev_list_info {
struct rev_info *revs;
@@ -24,6 +27,8 @@ struct rev_list_info {
extern int show_bisect_vars(struct rev_list_info *info, int reaches, int all);
-extern int bisect_next_vars(const char *prefix);
+extern int bisect_next_all(const char *prefix);
+
+extern int estimate_bisect_steps(int all);
#endif
diff --git a/builtin-add.c b/builtin-add.c
index cb67d2c..c1b229a 100644
--- a/builtin-add.c
+++ b/builtin-add.c
@@ -10,12 +10,14 @@
#include "cache-tree.h"
#include "run-command.h"
#include "parse-options.h"
+#include "diff.h"
+#include "revision.h"
static const char * const builtin_add_usage[] = {
"git add [options] [--] <filepattern>...",
NULL
};
-static int patch_interactive, add_interactive;
+static int patch_interactive, add_interactive, edit_interactive;
static int take_worktree_changes;
static void fill_pathspec_matches(const char **pathspec, char *seen, int specs)
@@ -61,7 +63,7 @@ static void prune_directory(struct dir_struct *dir, const char **pathspec, int p
fill_pathspec_matches(pathspec, seen, specs);
for (i = 0; i < specs; i++) {
- if (!seen[i] && !file_exists(pathspec[i]))
+ if (!seen[i] && pathspec[i][0] && !file_exists(pathspec[i]))
die("pathspec '%s' did not match any files",
pathspec[i]);
}
@@ -187,6 +189,51 @@ int interactive_add(int argc, const char **argv, const char *prefix)
return status;
}
+int edit_patch(int argc, const char **argv, const char *prefix)
+{
+ char *file = xstrdup(git_path("ADD_EDIT.patch"));
+ const char *apply_argv[] = { "apply", "--recount", "--cached",
+ file, NULL };
+ struct child_process child;
+ struct rev_info rev;
+ int out;
+ struct stat st;
+
+ git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
+
+ if (read_cache() < 0)
+ die ("Could not read the index");
+
+ init_revisions(&rev, prefix);
+ rev.diffopt.context = 7;
+
+ argc = setup_revisions(argc, argv, &rev, NULL);
+ rev.diffopt.output_format = DIFF_FORMAT_PATCH;
+ out = open(file, O_CREAT | O_WRONLY, 0644);
+ if (out < 0)
+ die ("Could not open '%s' for writing.", file);
+ rev.diffopt.file = fdopen(out, "w");
+ rev.diffopt.close_file = 1;
+ if (run_diff_files(&rev, 0))
+ die ("Could not write patch");
+
+ launch_editor(file, NULL, NULL);
+
+ if (stat(file, &st))
+ die("Could not stat '%s'", file);
+ if (!st.st_size)
+ die("Empty patch. Aborted.");
+
+ memset(&child, 0, sizeof(child));
+ child.git_cmd = 1;
+ child.argv = apply_argv;
+ if (run_command(&child))
+ die ("Could not apply '%s'", file);
+
+ unlink(file);
+ return 0;
+}
+
static struct lock_file lock_file;
static const char ignore_error[] =
@@ -201,6 +248,7 @@ static struct option builtin_add_options[] = {
OPT_GROUP(""),
OPT_BOOLEAN('i', "interactive", &add_interactive, "interactive picking"),
OPT_BOOLEAN('p', "patch", &patch_interactive, "interactive patching"),
+ OPT_BOOLEAN('e', "edit", &edit_interactive, "edit current diff and apply"),
OPT_BOOLEAN('f', "force", &ignored_too, "allow adding otherwise ignored files"),
OPT_BOOLEAN('u', "update", &take_worktree_changes, "update tracked files"),
OPT_BOOLEAN('N', "intent-to-add", &intent_to_add, "record only the fact that the path will be added later"),
@@ -250,15 +298,20 @@ int cmd_add(int argc, const char **argv, const char *prefix)
int add_new_files;
int require_pathspec;
- argc = parse_options(argc, argv, builtin_add_options,
- builtin_add_usage, 0);
+ argc = parse_options(argc, argv, prefix, builtin_add_options,
+ builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
if (patch_interactive)
add_interactive = 1;
if (add_interactive)
- exit(interactive_add(argc, argv, prefix));
+ exit(interactive_add(argc - 1, argv + 1, prefix));
git_config(add_config, NULL);
+ if (edit_interactive)
+ return(edit_patch(argc, argv, prefix));
+ argc--;
+ argv++;
+
if (addremove && take_worktree_changes)
die("-A and -u are mutually incompatible");
if ((addremove || take_worktree_changes) && !argc) {
diff --git a/builtin-apply.c b/builtin-apply.c
index 7b404ef..94ba2bd 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -320,6 +320,20 @@ static int name_terminate(const char *name, int namelen, int c, int terminate)
return 1;
}
+/* remove double slashes to make --index work with such filenames */
+static char *squash_slash(char *name)
+{
+ int i = 0, j = 0;
+
+ while (name[i]) {
+ if ((name[j++] = name[i++]) == '/')
+ while (name[i] == '/')
+ i++;
+ }
+ name[j] = '\0';
+ return name;
+}
+
static char *find_name(const char *line, char *def, int p_value, int terminate)
{
int len;
@@ -349,7 +363,7 @@ static char *find_name(const char *line, char *def, int p_value, int terminate)
free(def);
if (root)
strbuf_insert(&name, 0, root, root_len);
- return strbuf_detach(&name, NULL);
+ return squash_slash(strbuf_detach(&name, NULL));
}
}
strbuf_release(&name);
@@ -369,10 +383,10 @@ static char *find_name(const char *line, char *def, int p_value, int terminate)
start = line;
}
if (!start)
- return def;
+ return squash_slash(def);
len = line - start;
if (!len)
- return def;
+ return squash_slash(def);
/*
* Generally we prefer the shorter name, especially
@@ -383,7 +397,7 @@ static char *find_name(const char *line, char *def, int p_value, int terminate)
if (def) {
int deflen = strlen(def);
if (deflen < len && !strncmp(start, def, deflen))
- return def;
+ return squash_slash(def);
free(def);
}
@@ -392,10 +406,10 @@ static char *find_name(const char *line, char *def, int p_value, int terminate)
strcpy(ret, root);
memcpy(ret + root_len, start, len);
ret[root_len + len] = '\0';
- return ret;
+ return squash_slash(ret);
}
- return xmemdupz(start, len);
+ return squash_slash(xmemdupz(start, len));
}
static int count_slashes(const char *cp)
@@ -2781,7 +2795,7 @@ static void remove_file(struct patch *patch, int rmdir_empty)
if (rmdir(patch->old_name))
warning("unable to remove submodule %s",
patch->old_name);
- } else if (!unlink(patch->old_name) && rmdir_empty) {
+ } else if (!unlink_or_warn(patch->old_name) && rmdir_empty) {
remove_path(patch->old_name);
}
}
@@ -2891,7 +2905,7 @@ static void create_one_file(char *path, unsigned mode, const char *buf, unsigned
if (!try_create_file(newpath, mode, buf, size)) {
if (!rename(newpath, path))
return;
- unlink(newpath);
+ unlink_or_warn(newpath);
break;
}
if (errno != EEXIST)
@@ -3278,7 +3292,7 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
"apply a patch without touching the working tree"),
OPT_BOOLEAN(0, "apply", &force_apply,
"also apply the patch (use with --stat/--summary/--check)"),
- OPT_STRING(0, "build-fake-ancestor", &fake_ancestor, "file",
+ OPT_FILENAME(0, "build-fake-ancestor", &fake_ancestor,
"build a temporary index based on embedded index information"),
{ OPTION_CALLBACK, 'z', NULL, NULL, NULL,
"paths are separated with NUL character",
@@ -3313,8 +3327,9 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
if (apply_default_whitespace)
parse_whitespace_option(apply_default_whitespace);
- argc = parse_options(argc, argv, builtin_apply_options,
+ argc = parse_options(argc, argv, prefix, builtin_apply_options,
apply_usage, 0);
+
if (apply_with_reject)
apply = apply_verbosely = 1;
if (!force_apply && (diffstat || numstat || summary || check || fake_ancestor))
diff --git a/builtin-archive.c b/builtin-archive.c
index ab50ceb..3c5a5a7 100644
--- a/builtin-archive.c
+++ b/builtin-archive.c
@@ -80,7 +80,8 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
OPT_END()
};
- argc = parse_options(argc, argv, local_opts, NULL, PARSE_OPT_KEEP_ALL);
+ argc = parse_options(argc, argv, prefix, local_opts, NULL,
+ PARSE_OPT_KEEP_ALL);
if (output)
create_output_file(output);
diff --git a/builtin-bisect--helper.c b/builtin-bisect--helper.c
index 8fe7787..5b22639 100644
--- a/builtin-bisect--helper.c
+++ b/builtin-bisect--helper.c
@@ -4,24 +4,25 @@
#include "bisect.h"
static const char * const git_bisect_helper_usage[] = {
- "git bisect--helper --next-vars",
+ "git bisect--helper --next-all",
NULL
};
int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
{
- int next_vars = 0;
+ int next_all = 0;
struct option options[] = {
- OPT_BOOLEAN(0, "next-vars", &next_vars,
- "output next bisect step variables"),
+ OPT_BOOLEAN(0, "next-all", &next_all,
+ "perform 'git bisect next'"),
OPT_END()
};
- argc = parse_options(argc, argv, options, git_bisect_helper_usage, 0);
+ argc = parse_options(argc, argv, prefix, options,
+ git_bisect_helper_usage, 0);
- if (!next_vars)
+ if (!next_all)
usage_with_options(git_bisect_helper_usage, options);
- /* next-vars */
- return bisect_next_vars(prefix);
+ /* next-all */
+ return bisect_next_all(prefix);
}
diff --git a/builtin-blame.c b/builtin-blame.c
index 83141fc..0c2d29a 100644
--- a/builtin-blame.c
+++ b/builtin-blame.c
@@ -362,18 +362,28 @@ static struct origin *find_origin(struct scoreboard *sb,
"", &diff_opts);
diffcore_std(&diff_opts);
- /* It is either one entry that says "modified", or "created",
- * or nothing.
- */
if (!diff_queued_diff.nr) {
/* The path is the same as parent */
porigin = get_origin(sb, parent, origin->path);
hashcpy(porigin->blob_sha1, origin->blob_sha1);
- }
- else if (diff_queued_diff.nr != 1)
- die("internal error in blame::find_origin");
- else {
- struct diff_filepair *p = diff_queued_diff.queue[0];
+ } else {
+ /*
+ * Since origin->path is a pathspec, if the parent
+ * commit had it as a directory, we will see a whole
+ * bunch of deletion of files in the directory that we
+ * do not care about.
+ */
+ int i;
+ struct diff_filepair *p = NULL;
+ for (i = 0; i < diff_queued_diff.nr; i++) {
+ const char *name;
+ p = diff_queued_diff.queue[i];
+ name = p->one->path ? p->one->path : p->two->path;
+ if (!strcmp(name, origin->path))
+ break;
+ }
+ if (!p)
+ die("internal error in blame::find_origin");
switch (p->status) {
default:
die("internal error in blame::find_origin (%c)",
@@ -873,7 +883,7 @@ static void find_copy_in_blob(struct scoreboard *sb,
* Prepare mmfile that contains only the lines in ent.
*/
cp = nth_line(sb, ent->lno);
- file_o.ptr = (char*) cp;
+ file_o.ptr = (char *) cp;
cnt = ent->num_lines;
while (cnt && cp < sb->final_buf + sb->final_buf_size) {
@@ -1704,7 +1714,7 @@ static int prepare_lines(struct scoreboard *sb)
while (len--) {
if (bol) {
sb->lineno = xrealloc(sb->lineno,
- sizeof(int* ) * (num + 1));
+ sizeof(int *) * (num + 1));
sb->lineno[num] = buf - sb->final_buf;
bol = 0;
}
@@ -1714,7 +1724,7 @@ static int prepare_lines(struct scoreboard *sb)
}
}
sb->lineno = xrealloc(sb->lineno,
- sizeof(int* ) * (num + incomplete + 1));
+ sizeof(int *) * (num + incomplete + 1));
sb->lineno[num + incomplete] = buf - sb->final_buf;
sb->num_lines = num + incomplete;
return sb->num_lines;
@@ -1889,7 +1899,7 @@ static const char *parse_loc(const char *spec,
return spec;
/* it could be a regexp of form /.../ */
- for (term = (char*) spec + 1; *term && *term != '/'; term++) {
+ for (term = (char *) spec + 1; *term && *term != '/'; term++) {
if (*term == '\\')
term++;
}
@@ -2229,7 +2239,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
save_commit_buffer = 0;
dashdash_pos = 0;
- parse_options_start(&ctx, argc, argv, PARSE_OPT_KEEP_DASHDASH |
+ parse_options_start(&ctx, argc, argv, prefix, PARSE_OPT_KEEP_DASHDASH |
PARSE_OPT_KEEP_ARGV0);
for (;;) {
switch (parse_options_step(&ctx, options, blame_opt_usage)) {
diff --git a/builtin-branch.c b/builtin-branch.c
index 91098ca..5687d60 100644
--- a/builtin-branch.c
+++ b/builtin-branch.c
@@ -547,7 +547,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
struct option options[] = {
OPT_GROUP("Generic options"),
OPT__VERBOSE(&verbose),
- OPT_SET_INT( 0 , "track", &track, "set up tracking mode (see git-pull(1))",
+ OPT_SET_INT('t', "track", &track, "set up tracking mode (see git-pull(1))",
BRANCH_TRACK_EXPLICIT),
OPT_BOOLEAN( 0 , "color", &branch_use_color, "use colored output"),
OPT_SET_INT('r', NULL, &kinds, "act on remote-tracking branches",
@@ -610,7 +610,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
}
hashcpy(merge_filter_ref, head_sha1);
- argc = parse_options(argc, argv, options, builtin_branch_usage, 0);
+ argc = parse_options(argc, argv, prefix, options, builtin_branch_usage,
+ 0);
if (!!delete + !!rename + !!force_create > 1)
usage_with_options(builtin_branch_usage, options);
diff --git a/builtin-cat-file.c b/builtin-cat-file.c
index 8fad19d..5906842 100644
--- a/builtin-cat-file.c
+++ b/builtin-cat-file.c
@@ -201,8 +201,8 @@ static int batch_objects(int print_contents)
}
static const char * const cat_file_usage[] = {
- "git cat-file [-t|-s|-e|-p|<type>] <sha1>",
- "git cat-file [--batch|--batch-check] < <list_of_sha1s>",
+ "git cat-file (-t|-s|-e|-p|<type>) <object>",
+ "git cat-file (--batch|--batch-check) < <list_of_objects>",
NULL
};
@@ -231,7 +231,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
if (argc != 3 && argc != 2)
usage_with_options(cat_file_usage, options);
- argc = parse_options(argc, argv, options, cat_file_usage, 0);
+ argc = parse_options(argc, argv, prefix, options, cat_file_usage, 0);
if (opt) {
if (argc == 1)
diff --git a/builtin-check-attr.c b/builtin-check-attr.c
index 15a04b7..8bd0430 100644
--- a/builtin-check-attr.c
+++ b/builtin-check-attr.c
@@ -69,8 +69,8 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)
int cnt, i, doubledash;
const char *errstr = NULL;
- argc = parse_options(argc, argv, check_attr_options, check_attr_usage,
- PARSE_OPT_KEEP_DASHDASH);
+ argc = parse_options(argc, argv, prefix, check_attr_options,
+ check_attr_usage, PARSE_OPT_KEEP_DASHDASH);
if (!argc)
usage_with_options(check_attr_usage, check_attr_options);
diff --git a/builtin-checkout-index.c b/builtin-checkout-index.c
index 0d534bc..a7a5ee1 100644
--- a/builtin-checkout-index.c
+++ b/builtin-checkout-index.c
@@ -124,7 +124,7 @@ static int checkout_file(const char *name, int prefix_length)
static void checkout_all(const char *prefix, int prefix_length)
{
int i, errs = 0;
- struct cache_entry* last_ce = NULL;
+ struct cache_entry *last_ce = NULL;
for (i = 0; i < active_nr ; i++) {
struct cache_entry *ce = active_cache[i];
@@ -249,7 +249,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
die("invalid cache");
}
- argc = parse_options(argc, argv, builtin_checkout_index_options,
+ argc = parse_options(argc, argv, prefix, builtin_checkout_index_options,
builtin_checkout_index_usage, 0);
state.force = force;
state.quiet = quiet;
@@ -278,7 +278,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
p = prefix_path(prefix, prefix_length, arg);
checkout_file(p, prefix_length);
if (p < arg || p > arg + strlen(arg))
- free((char*)p);
+ free((char *)p);
}
if (read_from_stdin) {
diff --git a/builtin-checkout.c b/builtin-checkout.c
index 15f0c32..8a9a474 100644
--- a/builtin-checkout.c
+++ b/builtin-checkout.c
@@ -216,7 +216,7 @@ 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);
- if (read_cache() < 0)
+ if (read_cache_preload(pathspec) < 0)
return error("corrupt index file");
if (source_tree)
@@ -365,17 +365,14 @@ 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);
- int reprime_cache_tree = 0;
- if (read_cache() < 0)
+ if (read_cache_preload(NULL) < 0)
return error("corrupt index file");
- cache_tree_free(&active_cache_tree);
if (opts->force) {
ret = reset_tree(new->commit->tree, opts, 1);
if (ret)
return ret;
- reprime_cache_tree = 1;
} else {
struct tree_desc trees[2];
struct tree *tree;
@@ -411,9 +408,7 @@ static int merge_working_tree(struct checkout_opts *opts,
init_tree_desc(&trees[1], tree->buffer, tree->size);
ret = unpack_trees(2, trees, &topts);
- if (ret != -1) {
- reprime_cache_tree = 1;
- } else {
+ if (ret == -1) {
/*
* Unpack couldn't do a trivial merge; either
* give up or do a real merge, depending on
@@ -457,8 +452,6 @@ static int merge_working_tree(struct checkout_opts *opts,
}
}
- if (reprime_cache_tree)
- prime_cache_tree(&active_cache_tree, new->commit->tree);
if (write_cache(newfd, active_cache, active_nr) ||
commit_locked_index(lock_file))
die("unable to write new index file");
@@ -548,14 +541,6 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
parse_commit(new->commit);
}
- /*
- * If we were on a detached HEAD, but we are now moving to
- * 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 && old.commit && new->commit != old.commit)
- describe_detached_head("Previous HEAD position was", old.commit);
-
if (!old.commit && !opts->force) {
if (!opts->quiet) {
warning("You appear to be on a branch yet to be born.");
@@ -568,6 +553,14 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
if (ret)
return ret;
+ /*
+ * If we were on a detached HEAD, but have now moved to
+ * 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 && old.commit && new->commit != old.commit)
+ describe_detached_head("Previous HEAD position was", old.commit);
+
update_refs_for_switch(opts, &old, new);
ret = post_checkout_hook(old.commit, new->commit, 1);
@@ -612,7 +605,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
opts.track = BRANCH_TRACK_UNSPECIFIED;
- argc = parse_options(argc, argv, options, checkout_usage,
+ argc = parse_options(argc, argv, prefix, options, checkout_usage,
PARSE_OPT_KEEP_DASHDASH);
/* --track without -b should DWIM */
diff --git a/builtin-clean.c b/builtin-clean.c
index c5ad33d..1c1b6d2 100644
--- a/builtin-clean.c
+++ b/builtin-clean.c
@@ -56,7 +56,8 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
else
config_set = 1;
- argc = parse_options(argc, argv, options, builtin_clean_usage, 0);
+ argc = parse_options(argc, argv, prefix, options, builtin_clean_usage,
+ 0);
memset(&dir, 0, sizeof(dir));
if (ignored_only)
diff --git a/builtin-clone.c b/builtin-clone.c
index 880373f..5c46496 100644
--- a/builtin-clone.c
+++ b/builtin-clone.c
@@ -104,11 +104,12 @@ static char *get_repo_path(const char *repo, int *is_bundle)
static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)
{
const char *end = repo + strlen(repo), *start;
+ char *dir;
/*
- * Strip trailing slashes and /.git
+ * Strip trailing spaces, slashes and /.git
*/
- while (repo < end && is_dir_sep(end[-1]))
+ while (repo < end && (is_dir_sep(end[-1]) || isspace(end[-1])))
end--;
if (end - repo > 5 && is_dir_sep(end[-5]) &&
!strncmp(end - 4, ".git", 4)) {
@@ -140,10 +141,33 @@ static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)
if (is_bare) {
struct strbuf result = STRBUF_INIT;
strbuf_addf(&result, "%.*s.git", (int)(end - start), start);
- return strbuf_detach(&result, 0);
+ dir = strbuf_detach(&result, 0);
+ } else
+ dir = xstrndup(start, end - start);
+ /*
+ * Replace sequences of 'control' characters and whitespace
+ * with one ascii space, remove leading and trailing spaces.
+ */
+ if (*dir) {
+ char *out = dir;
+ int prev_space = 1 /* strip leading whitespace */;
+ for (end = dir; *end; ++end) {
+ char ch = *end;
+ if ((unsigned char)ch < '\x20')
+ ch = '\x20';
+ if (isspace(ch)) {
+ if (prev_space)
+ continue;
+ prev_space = 1;
+ } else
+ prev_space = 0;
+ *out++ = ch;
+ }
+ *out = '\0';
+ if (out > dir && prev_space)
+ out[-1] = '\0';
}
-
- return xstrndup(start, end - start);
+ return dir;
}
static void strip_trailing_slashes(char *dir)
@@ -228,7 +252,8 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest)
}
if (unlink(dest->buf) && errno != ENOENT)
- die("failed to unlink %s", dest->buf);
+ die("failed to unlink %s: %s",
+ dest->buf, strerror(errno));
if (!option_no_hardlinks) {
if (!link(src->buf, dest->buf))
continue;
@@ -335,7 +360,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
junk_pid = getpid();
- argc = parse_options(argc, argv, builtin_clone_options,
+ argc = parse_options(argc, argv, prefix, builtin_clone_options,
builtin_clone_usage, 0);
if (argc == 0)
diff --git a/builtin-commit.c b/builtin-commit.c
index 81371b1..41e222d 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -88,13 +88,13 @@ static struct option builtin_commit_options[] = {
OPT__VERBOSE(&verbose),
OPT_GROUP("Commit message options"),
- OPT_STRING('F', "file", &logfile, "FILE", "read log from file"),
+ OPT_FILENAME('F', "file", &logfile, "read log from file"),
OPT_STRING(0, "author", &force_author, "AUTHOR", "override author for commit"),
OPT_CALLBACK('m', "message", &message, "MESSAGE", "specify commit message", opt_parse_m),
OPT_STRING('c', "reedit-message", &edit_message, "COMMIT", "reuse and edit message from specified commit "),
OPT_STRING('C', "reuse-message", &use_message, "COMMIT", "reuse message from specified commit"),
OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
- OPT_STRING('t', "template", &template_file, "FILE", "use specified template file"),
+ OPT_FILENAME('t', "template", &template_file, "use specified template file"),
OPT_BOOLEAN('e', "edit", &edit_flag, "force edit of commit"),
OPT_GROUP("Commit contents options"),
@@ -697,9 +697,8 @@ static int parse_and_validate_options(int argc, const char *argv[],
{
int f = 0;
- argc = parse_options(argc, argv, builtin_commit_options, usage, 0);
- logfile = parse_options_fix_filename(prefix, logfile);
- template_file = parse_options_fix_filename(prefix, template_file);
+ argc = parse_options(argc, argv, prefix, builtin_commit_options, usage,
+ 0);
if (force_author && !strchr(force_author, '>'))
force_author = find_author_by_nickname(force_author);
diff --git a/builtin-config.c b/builtin-config.c
index d8da72c..60915f9 100644
--- a/builtin-config.c
+++ b/builtin-config.c
@@ -316,7 +316,8 @@ int cmd_config(int argc, const char **argv, const char *unused_prefix)
config_exclusive_filename = getenv(CONFIG_ENVIRONMENT);
- argc = parse_options(argc, argv, builtin_config_options, builtin_config_usage,
+ argc = parse_options(argc, argv, prefix, builtin_config_options,
+ builtin_config_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
if (use_global_config + use_system_config + !!given_config_file > 1) {
@@ -390,6 +391,8 @@ int cmd_config(int argc, const char **argv, const char *unused_prefix)
}
else if (actions == ACTION_EDIT) {
check_argc(argc, 0, 0);
+ if (!config_exclusive_filename && nongit)
+ die("not in a git directory");
git_config(git_default_config, NULL);
launch_editor(config_exclusive_filename ?
config_exclusive_filename : git_path("config"),
diff --git a/builtin-count-objects.c b/builtin-count-objects.c
index b814fe5..1b0b6c8 100644
--- a/builtin-count-objects.c
+++ b/builtin-count-objects.c
@@ -83,7 +83,7 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)
OPT_END(),
};
- argc = parse_options(argc, argv, opts, count_objects_usage, 0);
+ argc = parse_options(argc, argv, prefix, opts, count_objects_usage, 0);
/* we do not take arguments other than flags for now */
if (argc)
usage_with_options(count_objects_usage, opts);
diff --git a/builtin-describe.c b/builtin-describe.c
index 3a007ed..7a66298 100644
--- a/builtin-describe.c
+++ b/builtin-describe.c
@@ -322,7 +322,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
OPT_END(),
};
- argc = parse_options(argc, argv, options, describe_usage, 0);
+ argc = parse_options(argc, argv, prefix, options, describe_usage, 0);
if (max_candidates < 0)
max_candidates = 0;
else if (max_candidates > MAX_TAGS)
@@ -334,7 +334,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
die("--long is incompatible with --abbrev=0");
if (contains) {
- const char **args = xmalloc((7 + argc) * sizeof(char*));
+ const char **args = xmalloc((7 + argc) * sizeof(char *));
int i = 0;
args[i++] = "name-rev";
args[i++] = "--name-only";
@@ -349,7 +349,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
args[i++] = s;
}
}
- memcpy(args + i, argv, argc * sizeof(char*));
+ memcpy(args + i, argv, argc * sizeof(char *));
args[i + argc] = NULL;
return cmd_name_rev(i + argc, args, prefix);
}
diff --git a/builtin-fast-export.c b/builtin-fast-export.c
index 6731713..6cef810 100644
--- a/builtin-fast-export.c
+++ b/builtin-fast-export.c
@@ -515,7 +515,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
init_revisions(&revs, prefix);
argc = setup_revisions(argc, argv, &revs, NULL);
- argc = parse_options(argc, argv, options, fast_export_usage, 0);
+ argc = parse_options(argc, argv, prefix, options, fast_export_usage, 0);
if (argc > 1)
usage_with_options (fast_export_usage, options);
diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c
index 5d134be..629735f 100644
--- a/builtin-fetch-pack.c
+++ b/builtin-fetch-pack.c
@@ -13,6 +13,7 @@
static int transfer_unpack_limit = -1;
static int fetch_unpack_limit = -1;
static int unpack_limit = 100;
+static int prefer_ofs_delta = 1;
static struct fetch_pack_args args = {
/* .uploadpack = */ "git-upload-pack",
};
@@ -111,7 +112,7 @@ static void mark_common(struct commit *commit,
Get the next rev to send, ignoring the common.
*/
-static const unsigned char* get_rev(void)
+static const unsigned char *get_rev(void)
{
struct commit *commit = NULL;
@@ -200,7 +201,7 @@ static int find_common(int fd[2], unsigned char *result_sha1,
(args.use_thin_pack ? " thin-pack" : ""),
(args.no_progress ? " no-progress" : ""),
(args.include_tag ? " include-tag" : ""),
- " ofs-delta");
+ (prefer_ofs_delta ? " ofs-delta" : ""));
else
packet_write(fd[1], "want %s\n", sha1_to_hex(remote));
fetching++;
@@ -482,7 +483,9 @@ static int sideband_demux(int fd, void *data)
{
int *xd = data;
- return recv_sideband("fetch-pack", xd[0], fd);
+ int ret = recv_sideband("fetch-pack", xd[0], fd);
+ close(fd);
+ return ret;
}
static int get_pack(int xd[2], char **pack_lockfile)
@@ -596,6 +599,11 @@ static struct ref *do_fetch_pack(int fd[2],
fprintf(stderr, "Server supports side-band\n");
use_sideband = 1;
}
+ if (server_supports("ofs-delta")) {
+ if (args.verbose)
+ fprintf(stderr, "Server supports ofs-delta\n");
+ } else
+ prefer_ofs_delta = 0;
if (everything_local(&ref, nr_match, match)) {
packet_flush(fd[1]);
goto all_done;
@@ -648,6 +656,11 @@ static int fetch_pack_config(const char *var, const char *value, void *cb)
return 0;
}
+ if (strcmp(var, "repack.usedeltabaseoffset") == 0) {
+ prefer_ofs_delta = git_config_bool(var, value);
+ return 0;
+ }
+
return git_default_config(var, value, cb);
}
@@ -814,7 +827,7 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args,
fd = hold_lock_file_for_update(&lock, shallow,
LOCK_DIE_ON_ERROR);
if (!write_shallow_commits(fd, 0)) {
- unlink(shallow);
+ unlink_or_warn(shallow);
rollback_lock_file(&lock);
} else {
commit_lock_file(&lock);
diff --git a/builtin-fetch.c b/builtin-fetch.c
index 3c998ea..cd5eb9a 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -167,6 +167,9 @@ static struct ref *get_ref_map(struct transport *transport,
return ref_map;
}
+#define STORE_REF_ERROR_OTHER 1
+#define STORE_REF_ERROR_DF_CONFLICT 2
+
static int s_update_ref(const char *action,
struct ref *ref,
int check_old)
@@ -181,9 +184,11 @@ static int s_update_ref(const char *action,
lock = lock_any_ref_for_update(ref->name,
check_old ? ref->old_sha1 : NULL, 0);
if (!lock)
- return 2;
+ return errno == ENOTDIR ? STORE_REF_ERROR_DF_CONFLICT :
+ STORE_REF_ERROR_OTHER;
if (write_ref_sha1(lock, ref->new_sha1, msg) < 0)
- return 2;
+ return errno == ENOTDIR ? STORE_REF_ERROR_DF_CONFLICT :
+ STORE_REF_ERROR_OTHER;
return 0;
}
@@ -197,7 +202,7 @@ static int update_local_ref(struct ref *ref,
struct commit *current = NULL, *updated;
enum object_type type;
struct branch *current_branch = branch_get(NULL);
- const char *pretty_ref = prettify_ref(ref);
+ const char *pretty_ref = prettify_refname(ref->name);
*display = 0;
type = sha1_object_info(ref->new_sha1, NULL);
@@ -289,7 +294,7 @@ static int update_local_ref(struct ref *ref,
}
}
-static int store_updated_refs(const char *url, const char *remote_name,
+static int store_updated_refs(const char *raw_url, const char *remote_name,
struct ref *ref_map)
{
FILE *fp;
@@ -298,11 +303,13 @@ static int store_updated_refs(const char *url, const char *remote_name,
char note[1024];
const char *what, *kind;
struct ref *rm;
- char *filename = git_path("FETCH_HEAD");
+ char *url, *filename = git_path("FETCH_HEAD");
fp = fopen(filename, "a");
if (!fp)
return error("cannot open %s: %s\n", filename, strerror(errno));
+
+ url = transport_anonymize_url(raw_url);
for (rm = ref_map; rm; rm = rm->next) {
struct ref *ref = NULL;
@@ -353,12 +360,18 @@ static int store_updated_refs(const char *url, const char *remote_name,
kind);
note_len += sprintf(note + note_len, "'%s' of ", what);
}
- note_len += sprintf(note + note_len, "%.*s", url_len, url);
- fprintf(fp, "%s\t%s\t%s\n",
+ note[note_len] = '\0';
+ fprintf(fp, "%s\t%s\t%s",
sha1_to_hex(commit ? commit->object.sha1 :
rm->old_sha1),
rm->merge ? "" : "not-for-merge",
note);
+ for (i = 0; i < url_len; ++i)
+ if ('\n' == url[i])
+ fputs("\\n", fp);
+ else
+ fputc(url[i], fp);
+ fputc('\n', fp);
if (ref)
rc |= update_local_ref(ref, what, note);
@@ -376,8 +389,9 @@ static int store_updated_refs(const char *url, const char *remote_name,
fprintf(stderr, " %s\n", note);
}
}
+ free(url);
fclose(fp);
- if (rc & 2)
+ if (rc & STORE_REF_ERROR_DF_CONFLICT)
error("some local refs could not be updated; try running\n"
" 'git remote prune %s' to remove any old, conflicting "
"branches", remote_name);
@@ -625,7 +639,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
for (i = 1; i < argc; i++)
strbuf_addf(&default_rla, " %s", argv[i]);
- argc = parse_options(argc, argv,
+ argc = parse_options(argc, argv, prefix,
builtin_fetch_options, builtin_fetch_usage, 0);
if (argc == 0)
diff --git a/builtin-fmt-merge-msg.c b/builtin-fmt-merge-msg.c
index a788369..fbf9582 100644
--- a/builtin-fmt-merge-msg.c
+++ b/builtin-fmt-merge-msg.c
@@ -351,7 +351,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
struct option options[] = {
OPT_BOOLEAN(0, "log", &merge_summary, "populate log with the shortlog"),
OPT_BOOLEAN(0, "summary", &merge_summary, "alias for --log"),
- OPT_STRING('F', "file", &inpath, "file", "file to read from"),
+ OPT_FILENAME('F', "file", &inpath, "file to read from"),
OPT_END()
};
@@ -360,7 +360,8 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
int ret;
git_config(fmt_merge_msg_config, NULL);
- argc = parse_options(argc, argv, options, fmt_merge_msg_usage, 0);
+ argc = parse_options(argc, argv, prefix, options, fmt_merge_msg_usage,
+ 0);
if (argc > 0)
usage_with_options(fmt_merge_msg_usage, options);
diff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c
index 91e8f95..784733b 100644
--- a/builtin-for-each-ref.c
+++ b/builtin-for-each-ref.c
@@ -339,8 +339,11 @@ static const char *copy_name(const char *buf)
static const char *copy_email(const char *buf)
{
const char *email = strchr(buf, '<');
- const char *eoemail = strchr(email, '>');
- if (!email || !eoemail)
+ const char *eoemail;
+ if (!email)
+ return "";
+ eoemail = strchr(email, '>');
+ if (!eoemail)
return "";
return xmemdupz(email, eoemail + 1 - email);
}
@@ -902,7 +905,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
OPT_END(),
};
- parse_options(argc, argv, opts, for_each_ref_usage, 0);
+ parse_options(argc, argv, prefix, opts, for_each_ref_usage, 0);
if (maxcount < 0) {
error("invalid --count argument: `%d'", maxcount);
usage_with_options(for_each_ref_usage, opts);
diff --git a/builtin-fsck.c b/builtin-fsck.c
index 6436bc2..7da706c 100644
--- a/builtin-fsck.c
+++ b/builtin-fsck.c
@@ -590,7 +590,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
errors_found = 0;
- argc = parse_options(argc, argv, fsck_opts, fsck_usage, 0);
+ argc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0);
if (write_lost_and_found) {
check_full = 1;
include_reflogs = 0;
diff --git a/builtin-gc.c b/builtin-gc.c
index fc556ed..7d3e9cc 100644
--- a/builtin-gc.c
+++ b/builtin-gc.c
@@ -194,7 +194,8 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
if (pack_refs < 0)
pack_refs = !is_bare_repository();
- argc = parse_options(argc, argv, builtin_gc_options, builtin_gc_usage, 0);
+ argc = parse_options(argc, argv, prefix, builtin_gc_options,
+ builtin_gc_usage, 0);
if (argc > 0)
usage_with_options(builtin_gc_usage, builtin_gc_options);
diff --git a/builtin-grep.c b/builtin-grep.c
index f88a912..73fc922 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -10,6 +10,7 @@
#include "tag.h"
#include "tree-walk.h"
#include "builtin.h"
+#include "parse-options.h"
#include "grep.h"
#ifndef NO_EXTERNAL_GREP
@@ -20,7 +21,10 @@
#endif
#endif
-static int builtin_grep;
+static char const * const grep_usage[] = {
+ "git grep [options] [-e] <pattern> [<rev>...] [[--] path...]",
+ NULL
+};
static int grep_config(const char *var, const char *value, void *cb)
{
@@ -432,7 +436,8 @@ static int external_grep(struct grep_opt *opt, const char **paths, int cached)
}
#endif
-static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
+static int grep_cache(struct grep_opt *opt, const char **paths, int cached,
+ int external_grep_allowed)
{
int hit = 0;
int nr;
@@ -444,7 +449,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 && !builtin_grep) {
+ if (!cached && external_grep_allowed) {
hit = external_grep(opt, paths, cached);
if (hit >= 0)
return hit;
@@ -560,25 +565,182 @@ static int grep_object(struct grep_opt *opt, const char **paths,
die("unable to grep from object of type %s", typename(obj->type));
}
-static const char builtin_grep_usage[] =
-"git grep <option>* [-e] <pattern> <rev>* [[--] <path>...]";
+static int context_callback(const struct option *opt, const char *arg,
+ int unset)
+{
+ struct grep_opt *grep_opt = opt->value;
+ int value;
+ const char *endp;
+
+ if (unset) {
+ grep_opt->pre_context = grep_opt->post_context = 0;
+ return 0;
+ }
+ value = strtol(arg, (char **)&endp, 10);
+ if (*endp) {
+ return error("switch `%c' expects a numerical value",
+ opt->short_name);
+ }
+ grep_opt->pre_context = grep_opt->post_context = value;
+ return 0;
+}
+
+static int file_callback(const struct option *opt, const char *arg, int unset)
+{
+ struct grep_opt *grep_opt = opt->value;
+ FILE *patterns;
+ int lno = 0;
+ struct strbuf sb;
+
+ patterns = fopen(arg, "r");
+ if (!patterns)
+ die("'%s': %s", arg, strerror(errno));
+ while (strbuf_getline(&sb, patterns, '\n') == 0) {
+ /* ignore empty line like grep does */
+ if (sb.len == 0)
+ continue;
+ append_grep_pattern(grep_opt, strbuf_detach(&sb, NULL), arg,
+ ++lno, GREP_PATTERN);
+ }
+ fclose(patterns);
+ strbuf_release(&sb);
+ return 0;
+}
+
+static int not_callback(const struct option *opt, const char *arg, int unset)
+{
+ struct grep_opt *grep_opt = opt->value;
+ append_grep_pattern(grep_opt, "--not", "command line", 0, GREP_NOT);
+ return 0;
+}
+
+static int and_callback(const struct option *opt, const char *arg, int unset)
+{
+ struct grep_opt *grep_opt = opt->value;
+ append_grep_pattern(grep_opt, "--and", "command line", 0, GREP_AND);
+ return 0;
+}
+
+static int open_callback(const struct option *opt, const char *arg, int unset)
+{
+ struct grep_opt *grep_opt = opt->value;
+ append_grep_pattern(grep_opt, "(", "command line", 0, GREP_OPEN_PAREN);
+ return 0;
+}
+
+static int close_callback(const struct option *opt, const char *arg, int unset)
+{
+ struct grep_opt *grep_opt = opt->value;
+ append_grep_pattern(grep_opt, ")", "command line", 0, GREP_CLOSE_PAREN);
+ return 0;
+}
-static const char emsg_invalid_context_len[] =
-"%s: invalid context length argument";
-static const char emsg_missing_context_len[] =
-"missing context length argument";
-static const char emsg_missing_argument[] =
-"option requires an argument -%s";
+static int pattern_callback(const struct option *opt, const char *arg,
+ int unset)
+{
+ struct grep_opt *grep_opt = opt->value;
+ append_grep_pattern(grep_opt, arg, "-e option", 0, GREP_PATTERN);
+ return 0;
+}
+
+static int help_callback(const struct option *opt, const char *arg, int unset)
+{
+ return -1;
+}
int cmd_grep(int argc, const char **argv, const char *prefix)
{
int hit = 0;
int cached = 0;
+ int external_grep_allowed = 1;
int seen_dashdash = 0;
struct grep_opt opt;
struct object_array list = { 0, 0, NULL };
const char **paths = NULL;
int i;
+ int dummy;
+ struct option options[] = {
+ OPT_BOOLEAN(0, "cached", &cached,
+ "search in index instead of in the work tree"),
+ OPT_GROUP(""),
+ OPT_BOOLEAN('v', "invert-match", &opt.invert,
+ "show non-matching lines"),
+ OPT_BIT('i', "ignore-case", &opt.regflags,
+ "case insensitive matching", REG_ICASE),
+ OPT_BOOLEAN('w', "word-regexp", &opt.word_regexp,
+ "match patterns only at word boundaries"),
+ OPT_SET_INT('a', "text", &opt.binary,
+ "process binary files as text", GREP_BINARY_TEXT),
+ OPT_SET_INT('I', NULL, &opt.binary,
+ "don't match patterns in binary files",
+ GREP_BINARY_NOMATCH),
+ OPT_GROUP(""),
+ OPT_BIT('E', "extended-regexp", &opt.regflags,
+ "use extended POSIX regular expressions", REG_EXTENDED),
+ OPT_NEGBIT('G', "basic-regexp", &opt.regflags,
+ "use basic POSIX regular expressions (default)",
+ REG_EXTENDED),
+ OPT_BOOLEAN('F', "fixed-strings", &opt.fixed,
+ "interpret patterns as fixed strings"),
+ OPT_GROUP(""),
+ OPT_BOOLEAN('n', NULL, &opt.linenum, "show line numbers"),
+ OPT_NEGBIT('h', NULL, &opt.pathname, "don't show filenames", 1),
+ OPT_BIT('H', NULL, &opt.pathname, "show filenames", 1),
+ OPT_NEGBIT(0, "full-name", &opt.relative,
+ "show filenames relative to top directory", 1),
+ OPT_BOOLEAN('l', "files-with-matches", &opt.name_only,
+ "show only filenames instead of matching lines"),
+ OPT_BOOLEAN(0, "name-only", &opt.name_only,
+ "synonym for --files-with-matches"),
+ OPT_BOOLEAN('L', "files-without-match",
+ &opt.unmatch_name_only,
+ "show only the names of files without match"),
+ OPT_BOOLEAN('z', "null", &opt.null_following_name,
+ "print NUL after filenames"),
+ OPT_BOOLEAN('c', "count", &opt.count,
+ "show the number of matches instead of matching lines"),
+ OPT_SET_INT(0, "color", &opt.color, "highlight matches", 1),
+ OPT_GROUP(""),
+ OPT_CALLBACK('C', NULL, &opt, "n",
+ "show <n> context lines before and after matches",
+ context_callback),
+ OPT_INTEGER('B', NULL, &opt.pre_context,
+ "show <n> context lines before matches"),
+ OPT_INTEGER('A', NULL, &opt.post_context,
+ "show <n> context lines after matches"),
+ OPT_NUMBER_CALLBACK(&opt, "shortcut for -C NUM",
+ context_callback),
+ OPT_GROUP(""),
+ OPT_CALLBACK('f', NULL, &opt, "file",
+ "read patterns from file", file_callback),
+ { OPTION_CALLBACK, 'e', NULL, &opt, "pattern",
+ "match <pattern>", PARSE_OPT_NONEG, pattern_callback },
+ { OPTION_CALLBACK, 0, "and", &opt, NULL,
+ "combine patterns specified with -e",
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG, and_callback },
+ OPT_BOOLEAN(0, "or", &dummy, ""),
+ { OPTION_CALLBACK, 0, "not", &opt, NULL, "",
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG, not_callback },
+ { OPTION_CALLBACK, '(', NULL, &opt, NULL, "",
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
+ open_callback },
+ { OPTION_CALLBACK, ')', NULL, &opt, NULL, "",
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
+ close_callback },
+ OPT_BOOLEAN(0, "all-match", &opt.all_match,
+ "show only matches from files that match all patterns"),
+ OPT_GROUP(""),
+#if NO_EXTERNAL_GREP
+ OPT_BOOLEAN(0, "ext-grep", &external_grep_allowed,
+ "allow calling of grep(1) (ignored by this build)"),
+#else
+ OPT_BOOLEAN(0, "ext-grep", &external_grep_allowed,
+ "allow calling of grep(1) (default)"),
+#endif
+ { OPTION_CALLBACK, 0, "help-all", &options, NULL, "show usage",
+ PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, help_callback },
+ OPT_END()
+ };
memset(&opt, 0, sizeof(opt));
opt.prefix_length = (prefix && *prefix) ? strlen(prefix) : 0;
@@ -603,227 +765,21 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
* unrecognized non option is the beginning of the refs list
* that continues up to the -- (if exists), and then paths.
*/
-
- while (1 < argc) {
- const char *arg = argv[1];
- argc--; argv++;
- if (!strcmp("--cached", arg)) {
- 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;
- continue;
- }
- if (!strcmp("-i", arg) ||
- !strcmp("--ignore-case", arg)) {
- opt.regflags |= REG_ICASE;
- continue;
- }
- if (!strcmp("-I", arg)) {
- opt.binary = GREP_BINARY_NOMATCH;
- continue;
- }
- if (!strcmp("-v", arg) ||
- !strcmp("--invert-match", arg)) {
- opt.invert = 1;
- continue;
- }
- if (!strcmp("-E", arg) ||
- !strcmp("--extended-regexp", arg)) {
- opt.regflags |= REG_EXTENDED;
- continue;
- }
- if (!strcmp("-F", arg) ||
- !strcmp("--fixed-strings", arg)) {
- opt.fixed = 1;
- continue;
- }
- if (!strcmp("-G", arg) ||
- !strcmp("--basic-regexp", arg)) {
- opt.regflags &= ~REG_EXTENDED;
- continue;
- }
- if (!strcmp("-n", arg)) {
- opt.linenum = 1;
- continue;
- }
- if (!strcmp("-h", arg)) {
- opt.pathname = 0;
- continue;
- }
- if (!strcmp("-H", arg)) {
- opt.pathname = 1;
- continue;
- }
- if (!strcmp("-l", arg) ||
- !strcmp("--name-only", arg) ||
- !strcmp("--files-with-matches", arg)) {
- opt.name_only = 1;
- continue;
- }
- if (!strcmp("-L", arg) ||
- !strcmp("--files-without-match", arg)) {
- opt.unmatch_name_only = 1;
- continue;
- }
- if (!strcmp("-z", arg) ||
- !strcmp("--null", arg)) {
- opt.null_following_name = 1;
- continue;
- }
- if (!strcmp("-c", arg) ||
- !strcmp("--count", arg)) {
- opt.count = 1;
- continue;
- }
- if (!strcmp("-w", arg) ||
- !strcmp("--word-regexp", arg)) {
- opt.word_regexp = 1;
- continue;
- }
- if (!prefixcmp(arg, "-A") ||
- !prefixcmp(arg, "-B") ||
- !prefixcmp(arg, "-C") ||
- (arg[0] == '-' && '1' <= arg[1] && arg[1] <= '9')) {
- unsigned num;
- const char *scan;
- switch (arg[1]) {
- case 'A': case 'B': case 'C':
- if (!arg[2]) {
- if (argc <= 1)
- die(emsg_missing_context_len);
- scan = *++argv;
- argc--;
- }
- else
- scan = arg + 2;
- break;
- default:
- scan = arg + 1;
- break;
- }
- if (strtoul_ui(scan, 10, &num))
- die(emsg_invalid_context_len, scan);
- switch (arg[1]) {
- case 'A':
- opt.post_context = num;
- break;
- default:
- case 'C':
- opt.post_context = num;
- case 'B':
- opt.pre_context = num;
- break;
- }
- continue;
- }
- if (!strcmp("-f", arg)) {
- FILE *patterns;
- int lno = 0;
- char buf[1024];
- if (argc <= 1)
- die(emsg_missing_argument, arg);
- patterns = fopen(argv[1], "r");
- if (!patterns)
- die("'%s': %s", argv[1], strerror(errno));
- while (fgets(buf, sizeof(buf), patterns)) {
- int len = strlen(buf);
- if (len && buf[len-1] == '\n')
- buf[len-1] = 0;
- /* ignore empty line like grep does */
- if (!buf[0])
- continue;
- append_grep_pattern(&opt, xstrdup(buf),
- argv[1], ++lno,
- GREP_PATTERN);
- }
- fclose(patterns);
- argv++;
- argc--;
- continue;
- }
- if (!strcmp("--not", arg)) {
- append_grep_pattern(&opt, arg, "command line", 0,
- GREP_NOT);
- continue;
- }
- if (!strcmp("--and", arg)) {
- append_grep_pattern(&opt, arg, "command line", 0,
- GREP_AND);
- continue;
- }
- if (!strcmp("--or", arg))
- continue; /* no-op */
- if (!strcmp("(", arg)) {
- append_grep_pattern(&opt, arg, "command line", 0,
- GREP_OPEN_PAREN);
- continue;
- }
- if (!strcmp(")", arg)) {
- append_grep_pattern(&opt, arg, "command line", 0,
- GREP_CLOSE_PAREN);
- continue;
- }
- if (!strcmp("--all-match", arg)) {
- opt.all_match = 1;
- continue;
- }
- if (!strcmp("-e", arg)) {
- if (1 < argc) {
- append_grep_pattern(&opt, argv[1],
- "-e option", 0,
- GREP_PATTERN);
- argv++;
- argc--;
- continue;
- }
- die(emsg_missing_argument, arg);
- }
- if (!strcmp("--full-name", arg)) {
- opt.relative = 0;
- continue;
- }
- if (!strcmp("--color", arg)) {
- opt.color = 1;
- continue;
- }
- if (!strcmp("--no-color", arg)) {
- opt.color = 0;
- continue;
- }
- if (!strcmp("--", arg)) {
- /* later processing wants to have this at argv[1] */
- argv--;
- argc++;
- break;
- }
- if (*arg == '-')
- usage(builtin_grep_usage);
-
- /* First unrecognized non-option token */
- if (!opt.pattern_list) {
- append_grep_pattern(&opt, arg, "command line", 0,
- GREP_PATTERN);
- break;
- }
- else {
- /* We are looking at the first path or rev;
- * it is found at argv[1] after leaving the
- * loop.
- */
- argc++; argv--;
- break;
- }
+ argc = parse_options(argc, argv, prefix, options, grep_usage,
+ PARSE_OPT_KEEP_DASHDASH |
+ PARSE_OPT_STOP_AT_NON_OPTION |
+ PARSE_OPT_NO_INTERNAL_HELP);
+
+ /* First unrecognized non-option token */
+ if (argc > 0 && !opt.pattern_list) {
+ append_grep_pattern(&opt, argv[0], "command line", 0,
+ GREP_PATTERN);
+ argv++;
+ argc--;
}
if (opt.color && !opt.color_external)
- builtin_grep = 1;
+ external_grep_allowed = 0;
if (!opt.pattern_list)
die("no pattern given.");
if ((opt.regflags != REG_NEWLINE) && opt.fixed)
@@ -831,7 +787,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
compile_grep_patterns(&opt);
/* Check revs and then paths */
- for (i = 1; i < argc; i++) {
+ for (i = 0; i < argc; i++) {
const char *arg = argv[i];
unsigned char sha1[20];
/* Is it a rev? */
@@ -874,7 +830,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
if (!list.nr) {
if (!cached)
setup_work_tree();
- return !grep_cache(&opt, paths, cached);
+ return !grep_cache(&opt, paths, cached, external_grep_allowed);
}
if (cached)
diff --git a/builtin-help.c b/builtin-help.c
index 9b57a74..6e53b23 100644
--- a/builtin-help.c
+++ b/builtin-help.c
@@ -80,10 +80,9 @@ static int check_emacsclient_version(void)
ec_process.argv = argv_ec;
ec_process.err = -1;
ec_process.stdout_to_stderr = 1;
- if (start_command(&ec_process)) {
- fprintf(stderr, "Failed to start emacsclient.\n");
- return -1;
- }
+ if (start_command(&ec_process))
+ return error("Failed to start emacsclient.");
+
strbuf_read(&buffer, ec_process.err, 20);
close(ec_process.err);
@@ -94,27 +93,24 @@ static int check_emacsclient_version(void)
finish_command(&ec_process);
if (prefixcmp(buffer.buf, "emacsclient")) {
- fprintf(stderr, "Failed to parse emacsclient version.\n");
strbuf_release(&buffer);
- return -1;
+ return error("Failed to parse emacsclient version.");
}
strbuf_remove(&buffer, 0, strlen("emacsclient"));
version = atoi(buffer.buf);
if (version < 22) {
- fprintf(stderr,
- "emacsclient version '%d' too old (< 22).\n",
- version);
strbuf_release(&buffer);
- return -1;
+ return error("emacsclient version '%d' too old (< 22).",
+ version);
}
strbuf_release(&buffer);
return 0;
}
-static void exec_woman_emacs(const char* path, const char *page)
+static void exec_woman_emacs(const char *path, const char *page)
{
if (!check_emacsclient_version()) {
/* This works only with emacsclient version >= 22. */
@@ -128,7 +124,7 @@ static void exec_woman_emacs(const char* path, const char *page)
}
}
-static void exec_man_konqueror(const char* path, const char *page)
+static void exec_man_konqueror(const char *path, const char *page)
{
const char *display = getenv("DISPLAY");
if (display && *display) {
@@ -156,7 +152,7 @@ static void exec_man_konqueror(const char* path, const char *page)
}
}
-static void exec_man_man(const char* path, const char *page)
+static void exec_man_man(const char *path, const char *page)
{
if (!path)
path = "man";
@@ -236,7 +232,7 @@ static int add_man_viewer_info(const char *var, const char *value)
const char *subkey = strrchr(name, '.');
if (!subkey)
- return error("Config with no key for man viewer: %s", name);
+ return 0;
if (!strcmp(subkey, ".path")) {
if (!value)
@@ -249,7 +245,6 @@ static int add_man_viewer_info(const char *var, const char *value)
return add_man_viewer_cmd(name, subkey - name, value);
}
- warning("'%s': unsupported man viewer sub key.", subkey);
return 0;
}
@@ -424,7 +419,7 @@ int cmd_help(int argc, const char **argv, const char *prefix)
setup_git_directory_gently(&nongit);
git_config(git_help_config, NULL);
- argc = parse_options(argc, argv, builtin_help_options,
+ argc = parse_options(argc, argv, prefix, builtin_help_options,
builtin_help_usage, 0);
if (show_all) {
diff --git a/builtin-log.c b/builtin-log.c
index 5eaec5d..0d34050 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -18,6 +18,7 @@
#include "shortlog.h"
#include "remote.h"
#include "string-list.h"
+#include "parse-options.h"
/* Set a default date-time format for git log ("log.date" config variable) */
static const char *default_date_mode = NULL;
@@ -619,7 +620,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
struct shortlog log;
struct strbuf sb = STRBUF_INIT;
int i;
- const char *encoding = "utf-8";
+ const char *encoding = "UTF-8";
struct diff_options opts;
int need_8bit_cte = 0;
struct commit *commit = NULL;
@@ -740,17 +741,119 @@ static const char *set_outdir(const char *prefix, const char *output_directory)
output_directory));
}
+static const char * const builtin_format_patch_usage[] = {
+ "git format-patch [options] [<since> | <revision range>]",
+ NULL
+};
+
+static int keep_subject = 0;
+
+static int keep_callback(const struct option *opt, const char *arg, int unset)
+{
+ ((struct rev_info *)opt->value)->total = -1;
+ keep_subject = 1;
+ return 0;
+}
+
+static int subject_prefix = 0;
+
+static int subject_prefix_callback(const struct option *opt, const char *arg,
+ int unset)
+{
+ subject_prefix = 1;
+ ((struct rev_info *)opt->value)->subject_prefix = arg;
+ return 0;
+}
+
+static int numbered_cmdline_opt = 0;
+
+static int numbered_callback(const struct option *opt, const char *arg,
+ int unset)
+{
+ *(int *)opt->value = numbered_cmdline_opt = unset ? 0 : 1;
+ if (unset)
+ auto_number = 0;
+ return 0;
+}
+
+static int no_numbered_callback(const struct option *opt, const char *arg,
+ int unset)
+{
+ return numbered_callback(opt, arg, 1);
+}
+
+static int output_directory_callback(const struct option *opt, const char *arg,
+ int unset)
+{
+ const char **dir = (const char **)opt->value;
+ if (*dir)
+ die("Two output directories?");
+ *dir = arg;
+ return 0;
+}
+
+static int thread_callback(const struct option *opt, const char *arg, int unset)
+{
+ int *thread = (int *)opt->value;
+ if (unset)
+ *thread = 0;
+ else if (!arg || !strcmp(arg, "shallow"))
+ *thread = THREAD_SHALLOW;
+ else if (!strcmp(arg, "deep"))
+ *thread = THREAD_DEEP;
+ else
+ return 1;
+ return 0;
+}
+
+static int attach_callback(const struct option *opt, const char *arg, int unset)
+{
+ struct rev_info *rev = (struct rev_info *)opt->value;
+ if (unset)
+ rev->mime_boundary = NULL;
+ else if (arg)
+ rev->mime_boundary = arg;
+ else
+ rev->mime_boundary = git_version_string;
+ rev->no_inline = unset ? 0 : 1;
+ return 0;
+}
+
+static int inline_callback(const struct option *opt, const char *arg, int unset)
+{
+ struct rev_info *rev = (struct rev_info *)opt->value;
+ if (unset)
+ rev->mime_boundary = NULL;
+ else if (arg)
+ rev->mime_boundary = arg;
+ else
+ rev->mime_boundary = git_version_string;
+ rev->no_inline = 0;
+ return 0;
+}
+
+static int header_callback(const struct option *opt, const char *arg, int unset)
+{
+ add_header(arg);
+ return 0;
+}
+
+static int cc_callback(const struct option *opt, const char *arg, int unset)
+{
+ ALLOC_GROW(extra_cc, extra_cc_nr + 1, extra_cc_alloc);
+ extra_cc[extra_cc_nr++] = xstrdup(arg);
+ return 0;
+}
+
int cmd_format_patch(int argc, const char **argv, const char *prefix)
{
struct commit *commit;
struct commit **list = NULL;
struct rev_info rev;
- int nr = 0, total, i, j;
+ int nr = 0, total, i;
int use_stdout = 0;
int start_number = -1;
- int keep_subject = 0;
int numbered_files = 0; /* _just_ numbers */
- int subject_prefix = 0;
int ignore_if_in_upstream = 0;
int cover_letter = 0;
int boundary_count = 0;
@@ -760,6 +863,57 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
struct patch_ids ids;
char *add_signoff = NULL;
struct strbuf buf = STRBUF_INIT;
+ const struct option builtin_format_patch_options[] = {
+ { OPTION_CALLBACK, 'n', "numbered", &numbered, NULL,
+ "use [PATCH n/m] even with a single patch",
+ PARSE_OPT_NOARG, numbered_callback },
+ { OPTION_CALLBACK, 'N', "no-numbered", &numbered, NULL,
+ "use [PATCH] even with multiple patches",
+ PARSE_OPT_NOARG, no_numbered_callback },
+ OPT_BOOLEAN('s', "signoff", &do_signoff, "add Signed-off-by:"),
+ OPT_BOOLEAN(0, "stdout", &use_stdout,
+ "print patches to standard out"),
+ OPT_BOOLEAN(0, "cover-letter", &cover_letter,
+ "generate a cover letter"),
+ OPT_BOOLEAN(0, "numbered-files", &numbered_files,
+ "use simple number sequence for output file names"),
+ OPT_STRING(0, "suffix", &fmt_patch_suffix, "sfx",
+ "use <sfx> instead of '.patch'"),
+ OPT_INTEGER(0, "start-number", &start_number,
+ "start numbering patches at <n> instead of 1"),
+ { OPTION_CALLBACK, 0, "subject-prefix", &rev, "prefix",
+ "Use [<prefix>] instead of [PATCH]",
+ PARSE_OPT_NONEG, subject_prefix_callback },
+ { OPTION_CALLBACK, 'o', "output-directory", &output_directory,
+ "dir", "store resulting files in <dir>",
+ PARSE_OPT_NONEG, output_directory_callback },
+ { OPTION_CALLBACK, 'k', "keep-subject", &rev, NULL,
+ "don't strip/add [PATCH]",
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG, keep_callback },
+ OPT_BOOLEAN(0, "no-binary", &no_binary_diff,
+ "don't output binary diffs"),
+ OPT_BOOLEAN(0, "ignore-if-in-upstream", &ignore_if_in_upstream,
+ "don't include a patch matching a commit upstream"),
+ OPT_GROUP("Messaging"),
+ { OPTION_CALLBACK, 0, "add-header", NULL, "header",
+ "add email header", PARSE_OPT_NONEG,
+ header_callback },
+ { OPTION_CALLBACK, 0, "cc", NULL, "email", "add Cc: header",
+ PARSE_OPT_NONEG, cc_callback },
+ OPT_STRING(0, "in-reply-to", &in_reply_to, "message-id",
+ "make first mail a reply to <message-id>"),
+ { OPTION_CALLBACK, 0, "attach", &rev, "boundary",
+ "attach the patch", PARSE_OPT_OPTARG,
+ attach_callback },
+ { OPTION_CALLBACK, 0, "inline", &rev, "boundary",
+ "inline the patch",
+ PARSE_OPT_OPTARG | PARSE_OPT_NONEG,
+ inline_callback },
+ { OPTION_CALLBACK, 0, "thread", &thread, "style",
+ "enable message threading, styles: shallow, deep",
+ PARSE_OPT_OPTARG, thread_callback },
+ OPT_END()
+ };
git_config(git_format_config, NULL);
init_revisions(&rev, prefix);
@@ -782,100 +936,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
* like "git format-patch -o a123 HEAD^.." may fail; a123 is
* possibly a valid SHA1.
*/
- for (i = 1, j = 1; i < argc; i++) {
- if (!strcmp(argv[i], "--stdout"))
- use_stdout = 1;
- else if (!strcmp(argv[i], "-n") ||
- !strcmp(argv[i], "--numbered"))
- numbered = 1;
- else if (!strcmp(argv[i], "-N") ||
- !strcmp(argv[i], "--no-numbered")) {
- numbered = 0;
- auto_number = 0;
- }
- else if (!prefixcmp(argv[i], "--start-number="))
- start_number = strtol(argv[i] + 15, NULL, 10);
- else if (!strcmp(argv[i], "--numbered-files"))
- numbered_files = 1;
- else if (!strcmp(argv[i], "--start-number")) {
- i++;
- if (i == argc)
- die("Need a number for --start-number");
- start_number = strtol(argv[i], NULL, 10);
- }
- else if (!prefixcmp(argv[i], "--cc=")) {
- ALLOC_GROW(extra_cc, extra_cc_nr + 1, extra_cc_alloc);
- extra_cc[extra_cc_nr++] = xstrdup(argv[i] + 5);
- }
- else if (!strcmp(argv[i], "-k") ||
- !strcmp(argv[i], "--keep-subject")) {
- keep_subject = 1;
- rev.total = -1;
- }
- else if (!strcmp(argv[i], "--output-directory") ||
- !strcmp(argv[i], "-o")) {
- i++;
- if (argc <= i)
- die("Which directory?");
- if (output_directory)
- die("Two output directories?");
- output_directory = argv[i];
- }
- else if (!strcmp(argv[i], "--signoff") ||
- !strcmp(argv[i], "-s")) {
- do_signoff = 1;
- }
- else if (!strcmp(argv[i], "--attach")) {
- rev.mime_boundary = git_version_string;
- rev.no_inline = 1;
- }
- else if (!prefixcmp(argv[i], "--attach=")) {
- rev.mime_boundary = argv[i] + 9;
- rev.no_inline = 1;
- }
- else if (!strcmp(argv[i], "--no-attach")) {
- rev.mime_boundary = NULL;
- rev.no_inline = 0;
- }
- else if (!strcmp(argv[i], "--inline")) {
- rev.mime_boundary = git_version_string;
- rev.no_inline = 0;
- }
- else if (!prefixcmp(argv[i], "--inline=")) {
- rev.mime_boundary = argv[i] + 9;
- rev.no_inline = 0;
- }
- else if (!strcmp(argv[i], "--ignore-if-in-upstream"))
- ignore_if_in_upstream = 1;
- else if (!strcmp(argv[i], "--thread")
- || !strcmp(argv[i], "--thread=shallow"))
- thread = THREAD_SHALLOW;
- else if (!strcmp(argv[i], "--thread=deep"))
- thread = THREAD_DEEP;
- else if (!strcmp(argv[i], "--no-thread"))
- thread = 0;
- else if (!prefixcmp(argv[i], "--in-reply-to="))
- in_reply_to = argv[i] + 14;
- else if (!strcmp(argv[i], "--in-reply-to")) {
- i++;
- if (i == argc)
- die("Need a Message-Id for --in-reply-to");
- in_reply_to = argv[i];
- } else if (!prefixcmp(argv[i], "--subject-prefix=")) {
- subject_prefix = 1;
- rev.subject_prefix = argv[i] + 17;
- } else if (!prefixcmp(argv[i], "--suffix="))
- fmt_patch_suffix = argv[i] + 9;
- else if (!strcmp(argv[i], "--cover-letter"))
- cover_letter = 1;
- else if (!strcmp(argv[i], "--no-binary"))
- no_binary_diff = 1;
- else if (!prefixcmp(argv[i], "--add-header="))
- add_header(argv[i] + 13);
- else
- argv[j++] = argv[i];
- }
- argc = j;
+ argc = parse_options(argc, argv, prefix, builtin_format_patch_options,
+ builtin_format_patch_usage,
+ PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN);
if (do_signoff) {
const char *committer;
@@ -918,6 +981,15 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
if (start_number < 0)
start_number = 1;
+
+ /*
+ * If numbered is set solely due to format.numbered in config,
+ * and it would conflict with --keep-subject (-k) from the
+ * command line, reset "numbered".
+ */
+ if (numbered && keep_subject && !numbered_cmdline_opt)
+ numbered = 0;
+
if (numbered && keep_subject)
die ("-n and -k are mutually exclusive.");
if (keep_subject && subject_prefix)
diff --git a/builtin-ls-files.c b/builtin-ls-files.c
index da2daf4..2312866 100644
--- a/builtin-ls-files.c
+++ b/builtin-ls-files.c
@@ -454,7 +454,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
OPT_BIT(0, "directory", &dir.flags,
"show 'other' directories' name only",
DIR_SHOW_OTHER_DIRECTORIES),
- OPT_BIT(0, "no-empty-directory", &dir.flags,
+ OPT_NEGBIT(0, "empty-directory", &dir.flags,
"don't show empty directories",
DIR_HIDE_EMPTY_DIRECTORIES),
OPT_BOOLEAN('u', "unmerged", &show_unmerged,
@@ -486,7 +486,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
prefix_offset = strlen(prefix);
git_config(git_default_config, NULL);
- argc = parse_options(argc, argv, builtin_ls_files_options,
+ argc = parse_options(argc, argv, prefix, builtin_ls_files_options,
ls_files_usage, 0);
if (show_tag || show_valid_bit) {
tag_cached = "H ";
diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c
index 1eeeb4d..92637ac 100644
--- a/builtin-mailinfo.c
+++ b/builtin-mailinfo.c
@@ -193,8 +193,7 @@ static void handle_content_type(struct strbuf *line)
*content_top = boundary;
boundary = NULL;
}
- if (slurp_attr(line->buf, "charset=", &charset))
- strbuf_tolower(&charset);
+ slurp_attr(line->buf, "charset=", &charset);
if (boundary) {
strbuf_release(boundary);
@@ -481,7 +480,7 @@ static const char *guess_charset(const struct strbuf *line, const char *target_c
if (is_utf8(line->buf))
return NULL;
}
- return "latin1";
+ return "ISO8859-1";
}
static void convert_to_utf8(struct strbuf *line, const char *charset)
@@ -494,7 +493,7 @@ static void convert_to_utf8(struct strbuf *line, const char *charset)
return;
}
- if (!strcmp(metainfo_charset, charset))
+ if (!strcasecmp(metainfo_charset, charset))
return;
out = reencode_string(line->buf, metainfo_charset, charset);
if (!out)
@@ -550,7 +549,6 @@ static int decode_header_bq(struct strbuf *it)
if (cp + 3 - it->buf > it->len)
goto decode_header_bq_out;
strbuf_add(&charset_q, ep, cp - ep);
- strbuf_tolower(&charset_q);
encoding = cp[1];
if (!encoding || cp[2] != '?')
@@ -944,7 +942,7 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix)
*/
git_config(git_default_config, NULL);
- def_charset = (git_commit_encoding ? git_commit_encoding : "utf-8");
+ def_charset = (git_commit_encoding ? git_commit_encoding : "UTF-8");
metainfo_charset = def_charset;
while (1 < argc && argv[1][0] == '-') {
diff --git a/builtin-merge-base.c b/builtin-merge-base.c
index 03fc1c2..a6ec2f7 100644
--- a/builtin-merge-base.c
+++ b/builtin-merge-base.c
@@ -53,7 +53,7 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix)
};
git_config(git_default_config, NULL);
- argc = parse_options(argc, argv, options, merge_base_usage, 0);
+ argc = parse_options(argc, argv, prefix, options, merge_base_usage, 0);
if (argc < 2)
usage_with_options(merge_base_usage, options);
rev = xmalloc(argc * sizeof(*rev));
diff --git a/builtin-merge-file.c b/builtin-merge-file.c
index 96edb97..afd2ea7 100644
--- a/builtin-merge-file.c
+++ b/builtin-merge-file.c
@@ -48,7 +48,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
merge_style = git_xmerge_style;
}
- argc = parse_options(argc, argv, options, merge_file_usage, 0);
+ argc = parse_options(argc, argv, prefix, options, merge_file_usage, 0);
if (argc != 3)
usage_with_options(merge_file_usage, options);
if (quiet) {
diff --git a/builtin-merge-recursive.c b/builtin-merge-recursive.c
index 703045b..d26a96e 100644
--- a/builtin-merge-recursive.c
+++ b/builtin-merge-recursive.c
@@ -45,8 +45,9 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix)
bases[bases_count++] = sha;
}
else
- warning("Cannot handle more than %zu bases. "
- "Ignoring %s.", ARRAY_SIZE(bases)-1, argv[i]);
+ warning("Cannot handle more than %d bases. "
+ "Ignoring %s.",
+ (int)ARRAY_SIZE(bases)-1, argv[i]);
}
if (argc - i != 3) /* "--" "<head>" "<remote>" */
die("Not handling anything other than two heads merge.");
diff --git a/builtin-merge.c b/builtin-merge.c
index 6a51823..8d101ef 100644
--- a/builtin-merge.c
+++ b/builtin-merge.c
@@ -462,7 +462,7 @@ static int git_merge_config(const char *k, const char *v, void *cb)
argv = xrealloc(argv, sizeof(*argv) * (argc + 2));
memmove(argv + 1, argv, sizeof(*argv) * (argc + 1));
argc++;
- parse_options(argc, argv, builtin_merge_options,
+ parse_options(argc, argv, NULL, builtin_merge_options,
builtin_merge_usage, 0);
free(buf);
}
@@ -764,7 +764,7 @@ static int suggest_conflicts(void)
fp = fopen(git_path("MERGE_MSG"), "a");
if (!fp)
- die("Could open %s for writing", git_path("MERGE_MSG"));
+ die("Could not open %s for writing", git_path("MERGE_MSG"));
fprintf(fp, "\nConflicts:\n");
for (pos = 0; pos < active_nr; pos++) {
struct cache_entry *ce = active_cache[pos];
@@ -855,7 +855,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
if (diff_use_color_default == -1)
diff_use_color_default = git_use_color_default;
- argc = parse_options(argc, argv, builtin_merge_options,
+ argc = parse_options(argc, argv, prefix, builtin_merge_options,
builtin_merge_usage, 0);
if (verbosity < 0)
show_diffstat = 0;
diff --git a/builtin-mktree.c b/builtin-mktree.c
new file mode 100644
index 0000000..098395f
--- /dev/null
+++ b/builtin-mktree.c
@@ -0,0 +1,190 @@
+/*
+ * GIT - the stupid content tracker
+ *
+ * Copyright (c) Junio C Hamano, 2006, 2009
+ */
+#include "builtin.h"
+#include "quote.h"
+#include "tree.h"
+#include "parse-options.h"
+
+static struct treeent {
+ unsigned mode;
+ unsigned char sha1[20];
+ int len;
+ char name[FLEX_ARRAY];
+} **entries;
+static int alloc, used;
+
+static void append_to_tree(unsigned mode, unsigned char *sha1, char *path)
+{
+ struct treeent *ent;
+ int len = strlen(path);
+ if (strchr(path, '/'))
+ die("path %s contains slash", path);
+
+ if (alloc <= used) {
+ alloc = alloc_nr(used);
+ entries = xrealloc(entries, sizeof(*entries) * alloc);
+ }
+ ent = entries[used++] = xmalloc(sizeof(**entries) + len + 1);
+ ent->mode = mode;
+ ent->len = len;
+ hashcpy(ent->sha1, sha1);
+ memcpy(ent->name, path, len+1);
+}
+
+static int ent_compare(const void *a_, const void *b_)
+{
+ struct treeent *a = *(struct treeent **)a_;
+ struct treeent *b = *(struct treeent **)b_;
+ return base_name_compare(a->name, a->len, a->mode,
+ b->name, b->len, b->mode);
+}
+
+static void write_tree(unsigned char *sha1)
+{
+ struct strbuf buf;
+ size_t size;
+ int i;
+
+ qsort(entries, used, sizeof(*entries), ent_compare);
+ for (size = i = 0; i < used; i++)
+ size += 32 + entries[i]->len;
+
+ strbuf_init(&buf, size);
+ for (i = 0; i < used; i++) {
+ struct treeent *ent = entries[i];
+ strbuf_addf(&buf, "%o %s%c", ent->mode, ent->name, '\0');
+ strbuf_add(&buf, ent->sha1, 20);
+ }
+
+ write_sha1_file(buf.buf, buf.len, tree_type, sha1);
+}
+
+static const char *mktree_usage[] = {
+ "git mktree [-z] [--missing] [--batch]",
+ NULL
+};
+
+static void mktree_line(char *buf, size_t len, int line_termination, int allow_missing)
+{
+ char *ptr, *ntr;
+ unsigned mode;
+ enum object_type mode_type; /* object type derived from mode */
+ enum object_type obj_type; /* object type derived from sha */
+ char *path;
+ unsigned char sha1[20];
+
+ ptr = buf;
+ /*
+ * Read non-recursive ls-tree output format:
+ * mode SP type SP sha1 TAB name
+ */
+ mode = strtoul(ptr, &ntr, 8);
+ if (ptr == ntr || !ntr || *ntr != ' ')
+ die("input format error: %s", buf);
+ ptr = ntr + 1; /* type */
+ ntr = strchr(ptr, ' ');
+ if (!ntr || buf + len <= ntr + 40 ||
+ ntr[41] != '\t' ||
+ get_sha1_hex(ntr + 1, sha1))
+ die("input format error: %s", buf);
+
+ /* It is perfectly normal if we do not have a commit from a submodule */
+ if (S_ISGITLINK(mode))
+ allow_missing = 1;
+
+
+ *ntr++ = 0; /* now at the beginning of SHA1 */
+
+ path = ntr + 41; /* at the beginning of name */
+ if (line_termination && path[0] == '"') {
+ struct strbuf p_uq = STRBUF_INIT;
+ if (unquote_c_style(&p_uq, path, NULL))
+ die("invalid quoting");
+ path = strbuf_detach(&p_uq, NULL);
+ }
+
+ /*
+ * Object type is redundantly derivable three ways.
+ * These should all agree.
+ */
+ mode_type = object_type(mode);
+ if (mode_type != type_from_string(ptr)) {
+ die("entry '%s' object type (%s) doesn't match mode type (%s)",
+ path, ptr, typename(mode_type));
+ }
+
+ /* Check the type of object identified by sha1 */
+ obj_type = sha1_object_info(sha1, NULL);
+ if (obj_type < 0) {
+ if (allow_missing) {
+ ; /* no problem - missing objects are presumed to be of the right type */
+ } else {
+ die("entry '%s' object %s is unavailable", path, sha1_to_hex(sha1));
+ }
+ } else {
+ if (obj_type != mode_type) {
+ /*
+ * The object exists but is of the wrong type.
+ * This is a problem regardless of allow_missing
+ * because the new tree entry will never be correct.
+ */
+ die("entry '%s' object %s is a %s but specified type was (%s)",
+ path, sha1_to_hex(sha1), typename(obj_type), typename(mode_type));
+ }
+ }
+
+ append_to_tree(mode, sha1, path);
+}
+
+int cmd_mktree(int ac, const char **av, const char *prefix)
+{
+ struct strbuf sb = STRBUF_INIT;
+ unsigned char sha1[20];
+ int line_termination = '\n';
+ int allow_missing = 0;
+ int is_batch_mode = 0;
+ int got_eof = 0;
+
+ const struct option option[] = {
+ OPT_SET_INT('z', NULL, &line_termination, "input is NUL terminated", '\0'),
+ OPT_SET_INT( 0 , "missing", &allow_missing, "allow missing objects", 1),
+ OPT_SET_INT( 0 , "batch", &is_batch_mode, "allow creation of more than one tree", 1),
+ OPT_END()
+ };
+
+ ac = parse_options(ac, av, prefix, option, mktree_usage, 0);
+
+ while (!got_eof) {
+ while (1) {
+ if (strbuf_getline(&sb, stdin, line_termination) == EOF) {
+ got_eof = 1;
+ break;
+ }
+ if (sb.buf[0] == '\0') {
+ /* empty lines denote tree boundaries in batch mode */
+ if (is_batch_mode)
+ break;
+ die("input format error: (blank line only valid in batch mode)");
+ }
+ mktree_line(sb.buf, sb.len, line_termination, allow_missing);
+ }
+ if (is_batch_mode && got_eof && used < 1) {
+ /*
+ * Execution gets here if the last tree entry is terminated with a
+ * new-line. The final new-line has been made optional to be
+ * consistent with the original non-batch behaviour of mktree.
+ */
+ ; /* skip creating an empty tree */
+ } else {
+ write_tree(sha1);
+ puts(sha1_to_hex(sha1));
+ fflush(stdout);
+ }
+ used=0; /* reset tree entry buffer for re-use in batch mode */
+ }
+ strbuf_release(&sb);
+ exit(0);
+}
diff --git a/builtin-mv.c b/builtin-mv.c
index 01270fe..8b81d4b 100644
--- a/builtin-mv.c
+++ b/builtin-mv.c
@@ -72,7 +72,8 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
if (read_cache() < 0)
die("index file corrupt");
- argc = parse_options(argc, argv, builtin_mv_options, builtin_mv_usage, 0);
+ argc = parse_options(argc, argv, prefix, builtin_mv_options,
+ builtin_mv_usage, 0);
if (--argc < 1)
usage_with_options(builtin_mv_usage, builtin_mv_options);
diff --git a/builtin-name-rev.c b/builtin-name-rev.c
index 08c8aab..06a38ac 100644
--- a/builtin-name-rev.c
+++ b/builtin-name-rev.c
@@ -238,7 +238,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
};
git_config(git_default_config, NULL);
- argc = parse_options(argc, argv, opts, name_rev_usage, 0);
+ argc = parse_options(argc, argv, prefix, opts, name_rev_usage, 0);
if (!!all + !!transform_stdin + !!argc > 1) {
error("Specify either a list, or --all, not both!");
usage_with_options(name_rev_usage, opts);
diff --git a/builtin-pack-refs.c b/builtin-pack-refs.c
index 34246df..091860b 100644
--- a/builtin-pack-refs.c
+++ b/builtin-pack-refs.c
@@ -15,7 +15,7 @@ int cmd_pack_refs(int argc, const char **argv, const char *prefix)
OPT_BIT(0, "prune", &flags, "prune loose refs (default)", PACK_REFS_PRUNE),
OPT_END(),
};
- if (parse_options(argc, argv, opts, pack_refs_usage, 0))
+ if (parse_options(argc, argv, prefix, opts, pack_refs_usage, 0))
usage_with_options(pack_refs_usage, opts);
return pack_refs(flags);
}
diff --git a/builtin-prune-packed.c b/builtin-prune-packed.c
index 2d5b2cd..00590b1 100644
--- a/builtin-prune-packed.c
+++ b/builtin-prune-packed.c
@@ -28,8 +28,8 @@ static void prune_dir(int i, DIR *dir, char *pathname, int len, int opts)
memcpy(pathname + len, de->d_name, 38);
if (opts & DRY_RUN)
printf("rm -f %s\n", pathname);
- else if (unlink(pathname) < 0)
- error("unable to unlink %s", pathname);
+ else
+ unlink_or_warn(pathname);
display_progress(progress, i + 1);
}
pathname[len] = 0;
@@ -55,6 +55,7 @@ void prune_packed_objects(int opts)
for (i = 0; i < 256; i++) {
DIR *d;
+ display_progress(progress, i + 1);
sprintf(pathname + len, "%02x/", i);
d = opendir(pathname);
if (!d)
diff --git a/builtin-prune.c b/builtin-prune.c
index 545e9c1..0ed9cce 100644
--- a/builtin-prune.c
+++ b/builtin-prune.c
@@ -27,7 +27,7 @@ static int prune_tmp_object(const char *path, const char *filename)
}
printf("Removing stale temporary file %s\n", fullpath);
if (!show_only)
- unlink(fullpath);
+ unlink_or_warn(fullpath);
return 0;
}
@@ -47,7 +47,7 @@ static int prune_object(char *path, const char *filename, const unsigned char *s
(type > 0) ? typename(type) : "unknown");
}
if (!show_only)
- unlink(fullpath);
+ unlink_or_warn(fullpath);
return 0;
}
@@ -142,7 +142,7 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
save_commit_buffer = 0;
init_revisions(&revs, prefix);
- argc = parse_options(argc, argv, options, prune_usage, 0);
+ argc = parse_options(argc, argv, prefix, options, prune_usage, 0);
while (argc--) {
unsigned char sha1[20];
const char *name = *argv++;
diff --git a/builtin-push.c b/builtin-push.c
index 2eabcd3..c869974 100644
--- a/builtin-push.c
+++ b/builtin-push.c
@@ -198,7 +198,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
OPT_END()
};
- argc = parse_options(argc, argv, options, push_usage, 0);
+ argc = parse_options(argc, argv, prefix, options, push_usage, 0);
if (tags)
add_refspec("refs/tags/*");
diff --git a/builtin-receive-pack.c b/builtin-receive-pack.c
index a970b39..33d345d 100644
--- a/builtin-receive-pack.c
+++ b/builtin-receive-pack.c
@@ -27,10 +27,9 @@ static int receive_unpack_limit = -1;
static int transfer_unpack_limit = -1;
static int unpack_limit = 100;
static int report_status;
+static int prefer_ofs_delta = 1;
static const char *head_name;
-
-static char capabilities[] = " report-status delete-refs ";
-static int capabilities_sent;
+static char *capabilities_to_send;
static enum deny_action parse_deny_action(const char *var, const char *value)
{
@@ -84,24 +83,29 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
return 0;
}
+ if (strcmp(var, "repack.usedeltabaseoffset") == 0) {
+ prefer_ofs_delta = git_config_bool(var, value);
+ return 0;
+ }
+
return git_default_config(var, value, cb);
}
static int show_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
{
- if (capabilities_sent)
+ if (!capabilities_to_send)
packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
else
packet_write(1, "%s %s%c%s\n",
- sha1_to_hex(sha1), path, 0, capabilities);
- capabilities_sent = 1;
+ sha1_to_hex(sha1), path, 0, capabilities_to_send);
+ capabilities_to_send = NULL;
return 0;
}
static void write_head_info(void)
{
for_each_ref(show_ref, NULL);
- if (!capabilities_sent)
+ if (capabilities_to_send)
show_ref("capabilities^{}", null_sha1, 0, NULL);
}
@@ -188,7 +192,6 @@ static int run_receive_hook(const char *hook_name)
static int run_update_hook(struct command *cmd)
{
static const char update_hook[] = "hooks/update";
- struct child_process proc;
const char *argv[5];
if (access(update_hook, X_OK) < 0)
@@ -200,12 +203,9 @@ static int run_update_hook(struct command *cmd)
argv[3] = sha1_to_hex(cmd->new_sha1);
argv[4] = NULL;
- memset(&proc, 0, sizeof(proc));
- proc.argv = argv;
- proc.no_stdin = 1;
- proc.stdout_to_stderr = 1;
-
- return hook_status(run_command(&proc), update_hook);
+ return hook_status(run_command_v_opt(argv, RUN_COMMAND_NO_STDIN |
+ RUN_COMMAND_STDOUT_TO_STDERR),
+ update_hook);
}
static int is_ref_checked_out(const char *ref)
@@ -687,6 +687,10 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
else if (0 <= receive_unpack_limit)
unpack_limit = receive_unpack_limit;
+ capabilities_to_send = (prefer_ofs_delta) ?
+ " report-status delete-refs ofs-delta " :
+ " report-status delete-refs ";
+
add_alternate_refs();
write_head_info();
clear_extra_refs();
@@ -702,7 +706,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
unpack_status = unpack();
execute_commands(unpack_status);
if (pack_lockfile)
- unlink(pack_lockfile);
+ unlink_or_warn(pack_lockfile);
if (report_status)
report(unpack_status);
run_receive_hook(post_receive_hook);
diff --git a/builtin-remote.c b/builtin-remote.c
index 2ed752c..dfc0b9e 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -79,7 +79,8 @@ static int add(int argc, const char **argv)
OPT_END()
};
- argc = parse_options(argc, argv, options, builtin_remote_usage, 0);
+ argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
+ 0);
if (argc < 2)
usage_with_options(builtin_remote_usage, options);
@@ -294,17 +295,14 @@ static int get_push_ref_states(const struct ref *remote_refs,
struct ref_states *states)
{
struct remote *remote = states->remote;
- struct ref *ref, *local_refs, *push_map, **push_tail;
+ struct ref *ref, *local_refs, *push_map;
if (remote->mirror)
return 0;
local_refs = get_local_heads();
- ref = push_map = copy_ref_list(remote_refs);
- while (ref->next)
- ref = ref->next;
- push_tail = &ref->next;
+ push_map = copy_ref_list(remote_refs);
- match_refs(local_refs, push_map, &push_tail, remote->push_refspec_nr,
+ match_refs(local_refs, &push_map, remote->push_refspec_nr,
remote->push_refspec, MATCH_REFS_NONE);
states->push.strdup_strings = 1;
@@ -525,8 +523,8 @@ static int migrate_file(struct remote *remote)
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);
+ if (path)
+ unlink_or_warn(path);
return 0;
}
@@ -986,7 +984,8 @@ static int show(int argc, const char **argv)
struct string_list info_list = { NULL, 0, 0, 0 };
struct show_info info;
- argc = parse_options(argc, argv, options, builtin_remote_usage, 0);
+ argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
+ 0);
if (argc < 1)
return show_all();
@@ -1003,9 +1002,12 @@ static int show(int argc, const char **argv)
get_remote_ref_states(*argv, &states, query_flag);
- printf("* remote %s\n URL: %s\n", *argv,
- states.remote->url_nr > 0 ?
- states.remote->url[0] : "(no URL)");
+ printf("* remote %s\n", *argv);
+ if (states.remote->url_nr) {
+ for (i=0; i < states.remote->url_nr; i++)
+ printf(" URL: %s\n", states.remote->url[i]);
+ } else
+ printf(" URL: %s\n", "(no URL)");
if (no_query)
printf(" HEAD branch: (not queried)\n");
else if (!states.heads.nr)
@@ -1076,7 +1078,8 @@ static int set_head(int argc, const char **argv)
"delete refs/remotes/<name>/HEAD"),
OPT_END()
};
- argc = parse_options(argc, argv, options, builtin_remote_usage, 0);
+ argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
+ 0);
if (argc)
strbuf_addf(&buf, "refs/remotes/%s/HEAD", argv[0]);
@@ -1130,7 +1133,8 @@ static int prune(int argc, const char **argv)
OPT_END()
};
- argc = parse_options(argc, argv, options, builtin_remote_usage, 0);
+ argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
+ 0);
if (argc < 1)
usage_with_options(builtin_remote_usage, options);
@@ -1220,7 +1224,7 @@ static int update(int argc, const char **argv)
OPT_END()
};
- argc = parse_options(argc, argv, options, builtin_remote_usage,
+ argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
PARSE_OPT_KEEP_ARGV0);
if (argc < 2) {
argc = 2;
@@ -1306,7 +1310,7 @@ int cmd_remote(int argc, const char **argv, const char *prefix)
};
int result;
- argc = parse_options(argc, argv, options, builtin_remote_usage,
+ argc = parse_options(argc, argv, prefix, options, builtin_remote_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
if (argc < 1)
diff --git a/builtin-rerere.c b/builtin-rerere.c
index 020af73..adfb7b5 100644
--- a/builtin-rerere.c
+++ b/builtin-rerere.c
@@ -116,7 +116,7 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)
if (!has_rerere_resolution(name))
unlink_rr_item(name);
}
- unlink(git_path("rr-cache/MERGE_RR"));
+ unlink_or_warn(git_path("rr-cache/MERGE_RR"));
} else if (!strcmp(argv[1], "gc"))
garbage_collect(&merge_rr);
else if (!strcmp(argv[1], "status"))
diff --git a/builtin-reset.c b/builtin-reset.c
index 7e7ebab..5fa1789 100644
--- a/builtin-reset.c
+++ b/builtin-reset.c
@@ -203,7 +203,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
git_config(git_default_config, NULL);
- argc = parse_options(argc, argv, options, git_reset_usage,
+ argc = parse_options(argc, argv, prefix, options, git_reset_usage,
PARSE_OPT_KEEP_DASHDASH);
reflog_action = args_to_str(argv);
setenv("GIT_REFLOG_ACTION", reflog_action, 0);
diff --git a/builtin-rev-list.c b/builtin-rev-list.c
index 38a8f23..31ea5f4 100644
--- a/builtin-rev-list.c
+++ b/builtin-rev-list.c
@@ -211,7 +211,7 @@ static inline int exp2i(int n)
*
* and P(2^n + x) < 0.5 means 2^n < 3x
*/
-static int estimate_bisect_steps(int all)
+int estimate_bisect_steps(int all)
{
int n, x, e;
@@ -225,20 +225,37 @@ static int estimate_bisect_steps(int all)
return (e < 3 * x) ? n : n - 1;
}
-static void show_tried_revs(struct commit_list *tried, int stringed)
+void print_commit_list(struct commit_list *list,
+ const char *format_cur,
+ const char *format_last)
{
- printf("bisect_tried='");
- for (;tried; tried = tried->next) {
- char *format = tried->next ? "%s|" : "%s";
- printf(format, sha1_to_hex(tried->item->object.sha1));
+ for ( ; list; list = list->next) {
+ const char *format = list->next ? format_cur : format_last;
+ printf(format, sha1_to_hex(list->item->object.sha1));
}
- printf(stringed ? "' &&\n" : "'\n");
+}
+
+static void show_tried_revs(struct commit_list *tried)
+{
+ printf("bisect_tried='");
+ print_commit_list(tried, "%s|", "%s");
+ printf("'\n");
+}
+
+static void print_var_str(const char *var, const char *val)
+{
+ printf("%s='%s'\n", var, val);
+}
+
+static void print_var_int(const char *var, int val)
+{
+ printf("%s=%d\n", var, val);
}
int show_bisect_vars(struct rev_list_info *info, int reaches, int all)
{
int cnt, flags = info->bisect_show_flags;
- char hex[41] = "", *format;
+ char hex[41] = "";
struct commit_list *tried;
struct rev_info *revs = info->revs;
@@ -269,28 +286,14 @@ int show_bisect_vars(struct rev_list_info *info, int reaches, int all)
}
if (flags & BISECT_SHOW_TRIED)
- show_tried_revs(tried, flags & BISECT_SHOW_STRINGED);
- format = (flags & BISECT_SHOW_STRINGED) ?
- "bisect_rev=%s &&\n"
- "bisect_nr=%d &&\n"
- "bisect_good=%d &&\n"
- "bisect_bad=%d &&\n"
- "bisect_all=%d &&\n"
- "bisect_steps=%d\n"
- :
- "bisect_rev=%s\n"
- "bisect_nr=%d\n"
- "bisect_good=%d\n"
- "bisect_bad=%d\n"
- "bisect_all=%d\n"
- "bisect_steps=%d\n";
- printf(format,
- hex,
- cnt - 1,
- all - reaches - 1,
- reaches - 1,
- all,
- estimate_bisect_steps(all));
+ show_tried_revs(tried);
+
+ print_var_str("bisect_rev", hex);
+ print_var_int("bisect_nr", cnt - 1);
+ print_var_int("bisect_good", all - reaches - 1);
+ print_var_int("bisect_bad", reaches - 1);
+ print_var_int("bisect_all", all);
+ print_var_int("bisect_steps", estimate_bisect_steps(all));
return 0;
}
diff --git a/builtin-rev-parse.c b/builtin-rev-parse.c
index 22c6d6a..112d622 100644
--- a/builtin-rev-parse.c
+++ b/builtin-rev-parse.c
@@ -318,7 +318,7 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
int onb = 0, osz = 0, unb = 0, usz = 0;
strbuf_addstr(&parsed, "set --");
- argc = parse_options(argc, argv, parseopt_opts, parseopt_usage,
+ argc = parse_options(argc, argv, prefix, parseopt_opts, parseopt_usage,
PARSE_OPT_KEEP_DASHDASH);
if (argc < 1 || strcmp(argv[0], "--"))
usage_with_options(parseopt_usage, parseopt_opts);
@@ -393,7 +393,7 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
/* put an OPT_END() */
ALLOC_GROW(opts, onb + 1, osz);
memset(opts + onb, 0, sizeof(opts[onb]));
- argc = parse_options(argc, argv, opts, usage,
+ argc = parse_options(argc, argv, prefix, opts, usage,
keep_dashdash ? PARSE_OPT_KEEP_DASHDASH : 0);
strbuf_addf(&parsed, " --");
@@ -402,6 +402,18 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
return 0;
}
+static int cmd_sq_quote(int argc, const char **argv)
+{
+ struct strbuf buf = STRBUF_INIT;
+
+ if (argc)
+ sq_quote_argv(&buf, argv, 0);
+ printf("%s\n", buf.buf);
+ strbuf_release(&buf);
+
+ return 0;
+}
+
static void die_no_single_rev(int quiet)
{
if (quiet)
@@ -419,6 +431,9 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
if (argc > 1 && !strcmp("--parseopt", argv[1]))
return cmd_parseopt(argc - 1, argv + 1, prefix);
+ if (argc > 1 && !strcmp("--sq-quote", argv[1]))
+ return cmd_sq_quote(argc - 2, argv + 2);
+
prefix = setup_git_directory();
git_config(git_default_config, NULL);
for (i = 1; i < argc; i++) {
diff --git a/builtin-revert.c b/builtin-revert.c
index 3f2614e..c87115a 100644
--- a/builtin-revert.c
+++ b/builtin-revert.c
@@ -60,7 +60,7 @@ static void parse_args(int argc, const char **argv)
OPT_END(),
};
- if (parse_options(argc, argv, options, usage_str, 0) != 1)
+ if (parse_options(argc, argv, NULL, options, usage_str, 0) != 1)
usage_with_options(usage_str, options);
arg = argv[0];
@@ -323,9 +323,9 @@ static int revert_or_cherry_pick(int argc, const char **argv)
encoding = get_encoding(message);
if (!encoding)
- encoding = "utf-8";
+ encoding = "UTF-8";
if (!git_commit_encoding)
- git_commit_encoding = "utf-8";
+ git_commit_encoding = "UTF-8";
if ((reencoded_message = reencode_string(message,
git_commit_encoding, encoding)))
message = reencoded_message;
diff --git a/builtin-rm.c b/builtin-rm.c
index 269d608..0cc4912 100644
--- a/builtin-rm.c
+++ b/builtin-rm.c
@@ -157,7 +157,8 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
git_config(git_default_config, NULL);
- argc = parse_options(argc, argv, builtin_rm_options, builtin_rm_usage, 0);
+ argc = parse_options(argc, argv, prefix, builtin_rm_options,
+ builtin_rm_usage, 0);
if (!argc)
usage_with_options(builtin_rm_usage, builtin_rm_options);
diff --git a/builtin-send-pack.c b/builtin-send-pack.c
index d5a1c48..c375a3d 100644
--- a/builtin-send-pack.c
+++ b/builtin-send-pack.c
@@ -43,12 +43,16 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext
"--stdout",
NULL,
NULL,
+ NULL,
};
struct child_process po;
int i;
+ i = 4;
if (args->use_thin_pack)
- argv[4] = "--thin";
+ argv[i++] = "--thin";
+ if (args->use_ofs_delta)
+ argv[i++] = "--delta-base-offset";
memset(&po, 0, sizeof(po));
po.argv = argv;
po.in = -1;
@@ -174,9 +178,9 @@ static void print_ref_status(char flag, const char *summary, struct ref *to, str
{
fprintf(stderr, " %c %-*s ", flag, SUMMARY_WIDTH, summary);
if (from)
- fprintf(stderr, "%s -> %s", prettify_ref(from), prettify_ref(to));
+ fprintf(stderr, "%s -> %s", prettify_refname(from->name), prettify_refname(to->name));
else
- fputs(prettify_ref(to), stderr);
+ fputs(prettify_refname(to->name), stderr);
if (msg) {
fputs(" (", stderr);
fputs(msg, stderr);
@@ -315,6 +319,8 @@ int send_pack(struct send_pack_args *args,
ask_for_status_report = 1;
if (server_supports("delete-refs"))
allow_deleting_refs = 1;
+ if (server_supports("ofs-delta"))
+ args->use_ofs_delta = 1;
if (!remote_refs) {
fprintf(stderr, "No refs in common and none specified; doing nothing.\n"
@@ -467,7 +473,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
int fd[2];
struct child_process *conn;
struct extra_have_objects extra_have;
- struct ref *remote_refs, **remote_tail, *local_refs;
+ struct ref *remote_refs, *local_refs;
int ret;
int send_all = 0;
const char *receivepack = "git-receive-pack";
@@ -561,13 +567,8 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
flags |= MATCH_REFS_MIRROR;
/* match them up */
- remote_tail = &remote_refs;
- while (*remote_tail)
- remote_tail = &((*remote_tail)->next);
- if (match_refs(local_refs, remote_refs, &remote_tail,
- nr_refspecs, refspecs, flags)) {
+ if (match_refs(local_refs, &remote_refs, nr_refspecs, refspecs, flags))
return -1;
- }
ret = send_pack(&args, fd, conn, remote_refs, &extra_have);
diff --git a/builtin-shortlog.c b/builtin-shortlog.c
index b28091b..6a3812e 100644
--- a/builtin-shortlog.c
+++ b/builtin-shortlog.c
@@ -263,7 +263,7 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix)
git_config(git_default_config, NULL);
shortlog_init(&log);
init_revisions(&rev, prefix);
- parse_options_start(&ctx, argc, argv, PARSE_OPT_KEEP_DASHDASH |
+ parse_options_start(&ctx, argc, argv, prefix, PARSE_OPT_KEEP_DASHDASH |
PARSE_OPT_KEEP_ARGV0);
for (;;) {
diff --git a/builtin-show-branch.c b/builtin-show-branch.c
index 828e6f8..01bea3b 100644
--- a/builtin-show-branch.c
+++ b/builtin-show-branch.c
@@ -2,11 +2,26 @@
#include "commit.h"
#include "refs.h"
#include "builtin.h"
+#include "color.h"
+#include "parse-options.h"
-static const char show_branch_usage[] =
-"git show-branch [--sparse] [--current] [--all] [--remotes] [--topo-order] [--more=count | --list | --independent | --merge-base ] [--topics] [<refs>...] | --reflog[=n[,b]] <branch>";
-static const char show_branch_usage_reflog[] =
-"--reflog is incompatible with --all, --remotes, --independent or --merge-base";
+static const char* show_branch_usage[] = {
+ "git show-branch [--sparse] [--current] [--all] [--remotes] [--topo-order] [--more=count | --list | --independent | --merge-base] [--topics] [--color] [<refs>...]",
+ "--reflog[=n[,b]] [--list] [--color] <branch>",
+ NULL
+};
+
+static int showbranch_use_color = -1;
+static char column_colors[][COLOR_MAXLEN] = {
+ GIT_COLOR_RED,
+ GIT_COLOR_GREEN,
+ GIT_COLOR_YELLOW,
+ GIT_COLOR_BLUE,
+ GIT_COLOR_MAGENTA,
+ GIT_COLOR_CYAN,
+};
+
+#define COLUMN_COLORS_MAX (ARRAY_SIZE(column_colors))
static int default_num;
static int default_alloc;
@@ -19,6 +34,20 @@ static const char **default_arg;
#define DEFAULT_REFLOG 4
+static const char *get_color_code(int idx)
+{
+ if (showbranch_use_color)
+ return column_colors[idx];
+ return "";
+}
+
+static const char *get_color_reset_code(void)
+{
+ if (showbranch_use_color)
+ return GIT_COLOR_RESET;
+ return "";
+}
+
static struct commit *interesting(struct commit_list *list)
{
while (list) {
@@ -545,7 +574,12 @@ static int git_show_branch_config(const char *var, const char *value, void *cb)
return 0;
}
- return git_default_config(var, value, cb);
+ if (!strcmp(var, "color.showbranch")) {
+ showbranch_use_color = git_config_colorbool(var, value, -1);
+ return 0;
+ }
+
+ return git_color_default_config(var, value, cb);
}
static int omit_in_dense(struct commit *commit, struct commit **rev, int n)
@@ -569,18 +603,25 @@ static int omit_in_dense(struct commit *commit, struct commit **rev, int n)
return 0;
}
-static void parse_reflog_param(const char *arg, int *cnt, const char **base)
+static int reflog = 0;
+
+static int parse_reflog_param(const struct option *opt, const char *arg,
+ int unset)
{
char *ep;
- *cnt = strtoul(arg, &ep, 10);
+ const char **base = (const char **)opt->value;
+ if (!arg)
+ arg = "";
+ reflog = strtoul(arg, &ep, 10);
if (*ep == ',')
*base = ep + 1;
else if (*ep)
- die("unrecognized reflog param '%s'", arg + 9);
+ return error("unrecognized reflog param '%s'", arg);
else
*base = NULL;
- if (*cnt <= 0)
- *cnt = DEFAULT_REFLOG;
+ if (reflog <= 0)
+ reflog = DEFAULT_REFLOG;
+ return 0;
}
int cmd_show_branch(int ac, const char **av, const char *prefix)
@@ -606,70 +647,67 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
int head_at = -1;
int topics = 0;
int dense = 1;
- int reflog = 0;
const char *reflog_base = NULL;
+ struct option builtin_show_branch_options[] = {
+ OPT_BOOLEAN('a', "all", &all_heads,
+ "show remote-tracking and local branches"),
+ OPT_BOOLEAN('r', "remotes", &all_remotes,
+ "show remote-tracking branches"),
+ OPT_BOOLEAN(0, "color", &showbranch_use_color,
+ "color '*!+-' corresponding to the branch"),
+ { OPTION_INTEGER, 0, "more", &extra, "n",
+ "show <n> more commits after the common ancestor",
+ PARSE_OPT_OPTARG, NULL, (intptr_t)1 },
+ OPT_SET_INT(0, "list", &extra, "synonym to more=-1", -1),
+ OPT_BOOLEAN(0, "no-name", &no_name, "suppress naming strings"),
+ OPT_BOOLEAN(0, "current", &with_current_branch,
+ "include the current branch"),
+ OPT_BOOLEAN(0, "sha1-name", &sha1_name,
+ "name commits with their object names"),
+ OPT_BOOLEAN(0, "merge-base", &merge_base,
+ "act like git merge-base -a"),
+ OPT_BOOLEAN(0, "independent", &independent,
+ "show refs unreachable from any other ref"),
+ OPT_BOOLEAN(0, "topo-order", &lifo,
+ "show commits in topological order"),
+ OPT_BOOLEAN(0, "topics", &topics,
+ "show only commits not on the first branch"),
+ OPT_SET_INT(0, "sparse", &dense,
+ "show merges reachable from only one tip", 0),
+ OPT_SET_INT(0, "date-order", &lifo,
+ "show commits where no parent comes before its "
+ "children", 0),
+ { OPTION_CALLBACK, 'g', "reflog", &reflog_base, "<n>[,<base>]",
+ "show <n> most recent ref-log entries starting at "
+ "base",
+ PARSE_OPT_OPTARG | PARSE_OPT_LITERAL_ARGHELP,
+ parse_reflog_param },
+ OPT_END()
+ };
git_config(git_show_branch_config, NULL);
+ if (showbranch_use_color == -1)
+ showbranch_use_color = git_use_color_default;
+
/* If nothing is specified, try the default first */
if (ac == 1 && default_num) {
ac = default_num + 1;
av = default_arg - 1; /* ick; we would not address av[0] */
}
- while (1 < ac && av[1][0] == '-') {
- const char *arg = av[1];
- if (!strcmp(arg, "--")) {
- ac--; av++;
- break;
- }
- else if (!strcmp(arg, "--all") || !strcmp(arg, "-a"))
- all_heads = all_remotes = 1;
- else if (!strcmp(arg, "--remotes") || !strcmp(arg, "-r"))
- all_remotes = 1;
- else if (!strcmp(arg, "--more"))
- extra = 1;
- else if (!strcmp(arg, "--list"))
- extra = -1;
- else if (!strcmp(arg, "--no-name"))
- no_name = 1;
- else if (!strcmp(arg, "--current"))
- with_current_branch = 1;
- else if (!strcmp(arg, "--sha1-name"))
- sha1_name = 1;
- else if (!prefixcmp(arg, "--more="))
- extra = atoi(arg + 7);
- else if (!strcmp(arg, "--merge-base"))
- merge_base = 1;
- else if (!strcmp(arg, "--independent"))
- independent = 1;
- else if (!strcmp(arg, "--topo-order"))
- lifo = 1;
- else if (!strcmp(arg, "--topics"))
- topics = 1;
- else if (!strcmp(arg, "--sparse"))
- dense = 0;
- else if (!strcmp(arg, "--date-order"))
- lifo = 0;
- else if (!strcmp(arg, "--reflog") || !strcmp(arg, "-g")) {
- reflog = DEFAULT_REFLOG;
- }
- else if (!prefixcmp(arg, "--reflog="))
- parse_reflog_param(arg + 9, &reflog, &reflog_base);
- else if (!prefixcmp(arg, "-g="))
- parse_reflog_param(arg + 3, &reflog, &reflog_base);
- else
- usage(show_branch_usage);
- ac--; av++;
- }
- ac--; av++;
+ ac = parse_options(ac, av, prefix, builtin_show_branch_options,
+ show_branch_usage, PARSE_OPT_STOP_AT_NON_OPTION);
+ if (all_heads)
+ all_remotes = 1;
if (extra || reflog) {
/* "listing" mode is incompatible with
* independent nor merge-base modes.
*/
if (independent || merge_base)
- usage(show_branch_usage);
+ usage_with_options(show_branch_usage,
+ builtin_show_branch_options);
if (reflog && ((0 < extra) || all_heads || all_remotes))
/*
* Asking for --more in reflog mode does not
@@ -677,7 +715,8 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
*
* Also --all and --remotes do not make sense either.
*/
- usage(show_branch_usage_reflog);
+ die("--reflog is incompatible with --all, --remotes, "
+ "--independent or --merge-base");
}
/* If nothing is specified, show all branches by default */
@@ -843,8 +882,10 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
else {
for (j = 0; j < i; j++)
putchar(' ');
- printf("%c [%s] ",
- is_head ? '*' : '!', ref_name[i]);
+ printf("%s%c%s [%s] ",
+ get_color_code(i % COLUMN_COLORS_MAX),
+ is_head ? '*' : '!',
+ get_color_reset_code(), ref_name[i]);
}
if (!reflog) {
@@ -903,7 +944,9 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
mark = '*';
else
mark = '+';
- putchar(mark);
+ printf("%s%c%s",
+ get_color_code(i % COLUMN_COLORS_MAX),
+ mark, get_color_reset_code());
}
putchar(' ');
}
diff --git a/builtin-symbolic-ref.c b/builtin-symbolic-ref.c
index 6ae6bcc..ca855a5 100644
--- a/builtin-symbolic-ref.c
+++ b/builtin-symbolic-ref.c
@@ -36,7 +36,8 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
};
git_config(git_default_config, NULL);
- argc = parse_options(argc, argv, options, git_symbolic_ref_usage, 0);
+ argc = parse_options(argc, argv, prefix, options,
+ git_symbolic_ref_usage, 0);
if (msg &&!*msg)
die("Refusing to perform update with empty message");
switch (argc) {
diff --git a/builtin-tag.c b/builtin-tag.c
index 01e7374..dc3db62 100644
--- a/builtin-tag.c
+++ b/builtin-tag.c
@@ -338,7 +338,7 @@ static void create_tag(const unsigned char *object, const char *tag,
exit(128);
}
if (path) {
- unlink(path);
+ unlink_or_warn(path);
free(path);
}
}
@@ -387,7 +387,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
"annotated tag, needs a message"),
OPT_CALLBACK('m', NULL, &msg, "msg",
"message for the tag", parse_msg_arg),
- OPT_STRING('F', NULL, &msgfile, "file", "message in a file"),
+ OPT_FILENAME('F', NULL, &msgfile, "message in a file"),
OPT_BOOLEAN('s', NULL, &sign, "annotated and GPG-signed tag"),
OPT_STRING('u', NULL, &keyid, "key-id",
"use another key to sign the tag"),
@@ -405,8 +405,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
git_config(git_tag_config, NULL);
- argc = parse_options(argc, argv, options, git_tag_usage, 0);
- msgfile = parse_options_fix_filename(prefix, msgfile);
+ argc = parse_options(argc, argv, prefix, options, git_tag_usage, 0);
if (keyid) {
sign = 1;
diff --git a/builtin-update-index.c b/builtin-update-index.c
index 1fde893..92beaaf 100644
--- a/builtin-update-index.c
+++ b/builtin-update-index.c
@@ -292,7 +292,7 @@ static void update_one(const char *path, const char *prefix, int prefix_length)
report("add '%s'", path);
free_return:
if (p < path || p > path + strlen(path))
- free((char*)p);
+ free((char *)p);
}
static void read_index_info(int line_termination)
@@ -509,7 +509,7 @@ static int do_unresolve(int ac, const char **av,
const char *p = prefix_path(prefix, prefix_length, arg);
err |= unresolve_one(p);
if (p < arg || p > arg + strlen(arg))
- free((char*)p);
+ free((char *)p);
}
return err;
}
@@ -712,7 +712,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
if (set_executable_bit)
chmod_path(set_executable_bit, p);
if (p < path || p > path + strlen(path))
- free((char*)p);
+ free((char *)p);
}
if (read_from_stdin) {
struct strbuf buf = STRBUF_INIT, nbuf = STRBUF_INIT;
diff --git a/builtin-update-ref.c b/builtin-update-ref.c
index 378dc1b..76ba1d5 100644
--- a/builtin-update-ref.c
+++ b/builtin-update-ref.c
@@ -23,7 +23,8 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
};
git_config(git_default_config, NULL);
- argc = parse_options(argc, argv, options, git_update_ref_usage, 0);
+ argc = parse_options(argc, argv, prefix, options, git_update_ref_usage,
+ 0);
if (msg && !*msg)
die("Refusing to perform update with empty message.");
diff --git a/builtin-verify-tag.c b/builtin-verify-tag.c
index 729a159..7f7fda4 100644
--- a/builtin-verify-tag.c
+++ b/builtin-verify-tag.c
@@ -55,7 +55,7 @@ static int run_gpg_verify(const char *buf, unsigned long size, int verbose)
close(gpg.in);
ret = finish_command(&gpg);
- unlink(path);
+ unlink_or_warn(path);
return ret;
}
diff --git a/builtin.h b/builtin.h
index 425ff8e..20427d2 100644
--- a/builtin.h
+++ b/builtin.h
@@ -72,6 +72,7 @@ extern int cmd_merge_base(int argc, const char **argv, const char *prefix);
extern int cmd_merge_ours(int argc, const char **argv, const char *prefix);
extern int cmd_merge_file(int argc, const char **argv, const char *prefix);
extern int cmd_merge_recursive(int argc, const char **argv, const char *prefix);
+extern int cmd_mktree(int argc, const char **argv, const char *prefix);
extern int cmd_mv(int argc, const char **argv, const char *prefix);
extern int cmd_name_rev(int argc, const char **argv, const char *prefix);
extern int cmd_pack_objects(int argc, const char **argv, const char *prefix);
diff --git a/bundle.c b/bundle.c
index d0dd818..e4b2aa9 100644
--- a/bundle.c
+++ b/bundle.c
@@ -98,7 +98,7 @@ int verify_bundle(struct bundle_header *header, int verbose)
*/
struct ref_list *p = &header->prerequisites;
struct rev_info revs;
- const char *argv[] = {NULL, "--all"};
+ const char *argv[] = {NULL, "--all", NULL};
struct object_array refs;
struct commit *commit;
int i, ret = 0, req_nr;
diff --git a/cache.h b/cache.h
index ab1294d..871c984 100644
--- a/cache.h
+++ b/cache.h
@@ -554,6 +554,13 @@ extern enum branch_track git_branch_track;
extern enum rebase_setup_type autorebase;
extern enum push_default_type push_default;
+enum object_creation_mode {
+ OBJECT_CREATION_USES_HARDLINKS = 0,
+ OBJECT_CREATION_USES_RENAMES = 1,
+};
+
+extern enum object_creation_mode object_creation_mode;
+
#define GIT_REPO_VERSION 0
extern int repository_format_version;
extern int check_repository_format(void);
@@ -607,6 +614,8 @@ extern int is_empty_blob_sha1(const unsigned char *sha1);
int git_mkstemp(char *path, size_t n, const char *template);
+int git_mkstemps(char *path, size_t n, const char *template, int suffix_len);
+
/*
* NOTE NOTE NOTE!!
*
@@ -839,7 +848,7 @@ extern struct packed_git *find_sha1_pack(const unsigned char *sha1,
extern void pack_report(void);
extern int open_pack_index(struct packed_git *);
-extern unsigned char* use_pack(struct packed_git *, struct pack_window **, off_t, unsigned int *);
+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 *);
diff --git a/combine-diff.c b/combine-diff.c
index 066ce84..60d0367 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -6,6 +6,7 @@
#include "quote.h"
#include "xdiff-interface.h"
#include "log-tree.h"
+#include "refs.h"
static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr, int n, int num_parent)
{
@@ -23,7 +24,7 @@ static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr,
path = q->queue[i]->two->path;
len = strlen(path);
p = xmalloc(combine_diff_path_size(num_parent, len));
- p->path = (char*) &(p->parent[num_parent]);
+ p->path = (char *) &(p->parent[num_parent]);
memcpy(p->path, path, len);
p->path[len] = 0;
p->len = len;
@@ -90,18 +91,24 @@ struct sline {
unsigned long *p_lno;
};
-static char *grab_blob(const unsigned char *sha1, unsigned long *size)
+static char *grab_blob(const unsigned char *sha1, unsigned int mode, unsigned long *size)
{
char *blob;
enum object_type type;
- if (is_null_sha1(sha1)) {
+
+ if (S_ISGITLINK(mode)) {
+ blob = xmalloc(100);
+ *size = snprintf(blob, 100,
+ "Subproject commit %s\n", sha1_to_hex(sha1));
+ } else if (is_null_sha1(sha1)) {
/* deleted blob */
*size = 0;
return xcalloc(1, 1);
+ } else {
+ blob = read_sha1_file(sha1, &type, size);
+ if (type != OBJ_BLOB)
+ die("object '%s' is not a blob!", sha1_to_hex(sha1));
}
- blob = read_sha1_file(sha1, &type, size);
- if (type != OBJ_BLOB)
- die("object '%s' is not a blob!", sha1_to_hex(sha1));
return blob;
}
@@ -195,7 +202,8 @@ static void consume_line(void *state_, char *line, unsigned long len)
}
}
-static void combine_diff(const unsigned char *parent, mmfile_t *result_file,
+static void combine_diff(const unsigned char *parent, unsigned int mode,
+ mmfile_t *result_file,
struct sline *sline, unsigned int cnt, int n,
int num_parent)
{
@@ -211,7 +219,7 @@ static void combine_diff(const unsigned char *parent, mmfile_t *result_file,
if (!cnt)
return; /* result deleted */
- parent_file.ptr = grab_blob(parent, &sz);
+ parent_file.ptr = grab_blob(parent, mode, &sz);
parent_file.size = sz;
memset(&xpp, 0, sizeof(xpp));
xpp.flags = XDF_NEED_MINIMAL;
@@ -692,7 +700,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
/* Read the result of merge first */
if (!working_tree_file)
- result = grab_blob(elem->sha1, &result_size);
+ result = grab_blob(elem->sha1, elem->mode, &result_size);
else {
/* Used by diff-tree to read from the working tree */
struct stat st;
@@ -712,6 +720,12 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
result_size = buf.len;
result = strbuf_detach(&buf, NULL);
elem->mode = canon_mode(st.st_mode);
+ } else if (S_ISDIR(st.st_mode)) {
+ unsigned char sha1[20];
+ if (resolve_gitlink_ref(elem->path, "HEAD", sha1) < 0)
+ result = grab_blob(elem->sha1, elem->mode, &result_size);
+ else
+ result = grab_blob(sha1, elem->mode, &result_size);
} else if (0 <= (fd = open(elem->path, O_RDONLY))) {
size_t len = xsize_t(st.st_size);
ssize_t done;
@@ -804,7 +818,9 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
}
}
if (i <= j)
- combine_diff(elem->parent[i].sha1, &result_file, sline,
+ combine_diff(elem->parent[i].sha1,
+ elem->parent[i].mode,
+ &result_file, sline,
cnt, i, num_parent);
if (elem->parent[i].mode != elem->mode)
mode_differs = 1;
@@ -1047,7 +1063,7 @@ void diff_tree_combined_merge(const unsigned char *sha1,
for (parents = commit->parents, num_parent = 0;
parents;
parents = parents->next, num_parent++)
- hashcpy((unsigned char*)(parent + num_parent),
+ hashcpy((unsigned char *)(parent + num_parent),
parents->item->object.sha1);
diff_tree_combined(sha1, parent, num_parent, dense, rev);
}
diff --git a/commit.c b/commit.c
index aa3b35b..8f6b703 100644
--- a/commit.c
+++ b/commit.c
@@ -316,6 +316,26 @@ int parse_commit(struct commit *item)
return ret;
}
+static void unparse_commit_list(struct commit_list *list)
+{
+ for (; list; list = list->next)
+ unparse_commit(list->item);
+}
+
+void unparse_commit(struct commit *item)
+{
+ item->object.flags = 0;
+ item->object.used = 0;
+ if (item->object.parsed) {
+ item->object.parsed = 0;
+ if (item->parents) {
+ unparse_commit_list(item->parents);
+ free_commit_list(item->parents);
+ item->parents = NULL;
+ }
+ }
+}
+
struct commit_list *commit_list_insert(struct commit *item, struct commit_list **list_p)
{
struct commit_list *new_list = xmalloc(sizeof(struct commit_list));
diff --git a/commit.h b/commit.h
index ba9f638..f3eaf1d 100644
--- a/commit.h
+++ b/commit.h
@@ -40,6 +40,8 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size);
int parse_commit(struct commit *item);
+void unparse_commit(struct commit *item);
+
struct commit_list * commit_list_insert(struct commit *item, struct commit_list **list_p);
unsigned commit_list_count(const struct commit_list *l);
struct commit_list * insert_by_date(struct commit *item, struct commit_list **list);
diff --git a/compat/basename.c b/compat/basename.c
new file mode 100644
index 0000000..d8f8a3c
--- /dev/null
+++ b/compat/basename.c
@@ -0,0 +1,15 @@
+#include "../git-compat-util.h"
+
+/* Adapted from libiberty's basename.c. */
+char *gitbasename (char *path)
+{
+ const char *base;
+ /* Skip over the disk name in MSDOS pathnames. */
+ if (has_dos_drive_prefix(path))
+ path += 2;
+ for (base = path; *path; path++) {
+ if (is_dir_sep(*path))
+ base = path + 1;
+ }
+ return (char *)base;
+}
diff --git a/compat/mingw.c b/compat/mingw.c
index 2a04701..e190fdd 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -525,8 +525,8 @@ static const char *parse_interpreter(const char *cmd)
if (buf[0] != '#' || buf[1] != '!')
return NULL;
buf[n] = '\0';
- p = strchr(buf, '\n');
- if (!p)
+ p = buf + strcspn(buf, "\r\n");
+ if (!*p)
return NULL;
*p = '\0';
@@ -562,7 +562,7 @@ static char **get_path_split(void)
if (!n)
return NULL;
- path = xmalloc((n+1)*sizeof(char*));
+ path = xmalloc((n+1)*sizeof(char *));
p = envpath;
i = 0;
do {
@@ -1156,3 +1156,18 @@ int link(const char *oldpath, const char *newpath)
}
return 0;
}
+
+char *getpass(const char *prompt)
+{
+ struct strbuf buf = STRBUF_INIT;
+
+ fputs(prompt, stderr);
+ for (;;) {
+ char c = _getch();
+ if (c == '\r' || c == '\n')
+ break;
+ strbuf_addch(&buf, c);
+ }
+ fputs("\n", stderr);
+ return strbuf_detach(&buf, NULL);
+}
diff --git a/compat/mingw.h b/compat/mingw.h
index 762eb14..4c50f5b 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -38,6 +38,8 @@ struct passwd {
char *pw_dir;
};
+extern char *getpass(const char *prompt);
+
struct pollfd {
int fd; /* file descriptor */
short events; /* requested events */
@@ -109,7 +111,7 @@ static inline int mingw_unlink(const char *pathname)
}
#define unlink mingw_unlink
-static inline int waitpid(pid_t pid, unsigned *status, unsigned options)
+static inline int waitpid(pid_t pid, int *status, unsigned options)
{
if (options == 0)
return _cwait(status, pid, 0);
diff --git a/compat/mkstemps.c b/compat/mkstemps.c
new file mode 100644
index 0000000..14179c8
--- /dev/null
+++ b/compat/mkstemps.c
@@ -0,0 +1,70 @@
+#include "../git-compat-util.h"
+
+/* Adapted from libiberty's mkstemp.c. */
+
+#undef TMP_MAX
+#define TMP_MAX 16384
+
+int gitmkstemps(char *pattern, int suffix_len)
+{
+ static const char letters[] =
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789";
+ static const int num_letters = 62;
+ uint64_t value;
+ struct timeval tv;
+ char *template;
+ size_t len;
+ int fd, count;
+
+ len = strlen(pattern);
+
+ if (len < 6 + suffix_len) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (strncmp(&pattern[len - 6 - suffix_len], "XXXXXX", 6)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /*
+ * Replace pattern's XXXXXX characters with randomness.
+ * Try TMP_MAX different filenames.
+ */
+ gettimeofday(&tv, NULL);
+ value = ((size_t)(tv.tv_usec << 16)) ^ tv.tv_sec ^ getpid();
+ template = &pattern[len - 6 - suffix_len];
+ for (count = 0; count < TMP_MAX; ++count) {
+ uint64_t v = value;
+ /* Fill in the random bits. */
+ template[0] = letters[v % num_letters]; v /= num_letters;
+ template[1] = letters[v % num_letters]; v /= num_letters;
+ template[2] = letters[v % num_letters]; v /= num_letters;
+ template[3] = letters[v % num_letters]; v /= num_letters;
+ template[4] = letters[v % num_letters]; v /= num_letters;
+ template[5] = letters[v % num_letters]; v /= num_letters;
+
+ fd = open(pattern, O_CREAT | O_EXCL | O_RDWR, 0600);
+ if (fd > 0)
+ return fd;
+ /*
+ * Fatal error (EPERM, ENOSPC etc).
+ * It doesn't make sense to loop.
+ */
+ if (errno != EEXIST)
+ break;
+ /*
+ * This is a random value. It is only necessary that
+ * the next TMP_MAX values generated by adding 7777 to
+ * VALUE are different with (module 2^32).
+ */
+ value += 7777;
+ }
+ /* We return the null string if we can't find a unique file name. */
+ pattern[0] = '\0';
+ errno = EINVAL;
+ return -1;
+}
diff --git a/config.c b/config.c
index 8c1ae59..1682273 100644
--- a/config.c
+++ b/config.c
@@ -495,6 +495,16 @@ static int git_default_core_config(const char *var, const char *value)
return 0;
}
+ if (!strcmp(var, "core.createobject")) {
+ if (!strcmp(value, "rename"))
+ object_creation_mode = OBJECT_CREATION_USES_RENAMES;
+ else if (!strcmp(value, "link"))
+ object_creation_mode = OBJECT_CREATION_USES_HARDLINKS;
+ else
+ die("Invalid mode for object creation: %s", value);
+ return 0;
+ }
+
/* Add other config variables here and to Documentation/config.txt. */
return 0;
}
@@ -714,16 +724,16 @@ int git_config(config_fn_t fn, void *data)
static struct {
int baselen;
- char* key;
+ char *key;
int do_not_match;
- regex_t* value_regex;
+ regex_t *value_regex;
int multi_replace;
size_t offset[MAX_MATCHES];
enum { START, SECTION_SEEN, SECTION_END_SEEN, KEY_SEEN } state;
int seen;
} store;
-static int matches(const char* key, const char* value)
+static int matches(const char *key, const char *value)
{
return !strcmp(key, store.key) &&
(store.value_regex == NULL ||
@@ -731,7 +741,7 @@ static int matches(const char* key, const char* value)
!regexec(store.value_regex, value, 0, NULL, 0)));
}
-static int store_aux(const char* key, const char* value, void *cb)
+static int store_aux(const char *key, const char *value, void *cb)
{
const char *ep;
size_t section_len;
@@ -800,7 +810,7 @@ static int write_error(const char *filename)
return 4;
}
-static int store_write_section(int fd, const char* key)
+static int store_write_section(int fd, const char *key)
{
const char *dot;
int i, success;
@@ -825,7 +835,7 @@ static int store_write_section(int fd, const char* key)
return success;
}
-static int store_write_pair(int fd, const char* key, const char* value)
+static int store_write_pair(int fd, const char *key, const char *value)
{
int i, success;
int length = strlen(key + store.baselen + 1);
@@ -873,8 +883,8 @@ static int store_write_pair(int fd, const char* key, const char* value)
return success;
}
-static ssize_t find_beginning_of_line(const char* contents, size_t size,
- size_t offset_, int* found_bracket)
+static ssize_t find_beginning_of_line(const char *contents, size_t size,
+ size_t offset_, int *found_bracket)
{
size_t equal_offset = size, bracket_offset = size;
ssize_t offset;
@@ -899,7 +909,7 @@ contline:
return offset;
}
-int git_config_set(const char* key, const char* value)
+int git_config_set(const char *key, const char *value)
{
return git_config_set_multivar(key, value, NULL, 0);
}
@@ -927,15 +937,15 @@ int git_config_set(const char* key, const char* value)
* - the config file is removed and the lock file rename()d to it.
*
*/
-int git_config_set_multivar(const char* key, const char* value,
- const char* value_regex, int multi_replace)
+int git_config_set_multivar(const char *key, const char *value,
+ const char *value_regex, int multi_replace)
{
int i, dot;
int fd = -1, in_fd;
int ret;
- char* config_filename;
+ char *config_filename;
struct lock_file *lock = NULL;
- const char* last_dot = strrchr(key, '.');
+ const char *last_dot = strrchr(key, '.');
if (config_exclusive_filename)
config_filename = xstrdup(config_exclusive_filename);
@@ -991,7 +1001,7 @@ int git_config_set_multivar(const char* key, const char* value,
lock = xcalloc(sizeof(struct lock_file), 1);
fd = hold_lock_file_for_update(lock, config_filename, 0);
if (fd < 0) {
- error("could not lock config file %s", config_filename);
+ error("could not lock config file %s: %s", config_filename, strerror(errno));
free(store.key);
ret = -1;
goto out_free;
@@ -1016,13 +1026,13 @@ int git_config_set_multivar(const char* key, const char* value,
goto out_free;
}
- store.key = (char*)key;
+ store.key = (char *)key;
if (!store_write_section(fd, key) ||
!store_write_pair(fd, key, value))
goto write_err_out;
} else {
struct stat st;
- char* contents;
+ char *contents;
size_t contents_sz, copy_begin, copy_end;
int i, new_line = 0;
diff --git a/config.mak.in b/config.mak.in
index 7cce0c1..dd60451 100644
--- a/config.mak.in
+++ b/config.mak.in
@@ -30,8 +30,10 @@ NEEDS_SSL_WITH_CRYPTO=@NEEDS_SSL_WITH_CRYPTO@
NO_OPENSSL=@NO_OPENSSL@
NO_CURL=@NO_CURL@
NO_EXPAT=@NO_EXPAT@
+NO_LIBGEN_H=@NO_LIBGEN_H@
NEEDS_LIBICONV=@NEEDS_LIBICONV@
NEEDS_SOCKET=@NEEDS_SOCKET@
+NEEDS_RESOLV=@NEEDS_RESOLV@
NO_SYS_SELECT_H=@NO_SYS_SELECT_H@
NO_D_INO_IN_DIRENT=@NO_D_INO_IN_DIRENT@
NO_D_TYPE_IN_DIRENT=@NO_D_TYPE_IN_DIRENT@
@@ -46,6 +48,7 @@ NO_STRTOUMAX=@NO_STRTOUMAX@
NO_SETENV=@NO_SETENV@
NO_UNSETENV=@NO_UNSETENV@
NO_MKDTEMP=@NO_MKDTEMP@
+NO_MKSTEMPS=@NO_MKSTEMPS@
NO_ICONV=@NO_ICONV@
OLD_ICONV=@OLD_ICONV@
NO_DEFLATE_BOUND=@NO_DEFLATE_BOUND@
diff --git a/configure.ac b/configure.ac
index 4e728bc..7937e60 100644
--- a/configure.ac
+++ b/configure.ac
@@ -467,6 +467,15 @@ AC_CHECK_LIB([c], [socket],
AC_SUBST(NEEDS_SOCKET)
test -n "$NEEDS_SOCKET" && LIBS="$LIBS -lsocket"
+#
+# Define NEEDS_RESOLV if linking with -lnsl and/or -lsocket is not enough.
+# Notably on Solaris hstrerror resides in libresolv and on Solaris 7
+# inet_ntop and inet_pton additionally reside there.
+AC_CHECK_LIB([resolv], [hstrerror],
+[NEEDS_RESOLV=],
+[NEEDS_RESOLV=YesPlease])
+AC_SUBST(NEEDS_RESOLV)
+test -n "$NEEDS_RESOLV" && LIBS="$LIBS -lresolv"
## Checks for header files.
AC_MSG_NOTICE([CHECKS for header files])
@@ -627,6 +636,12 @@ AC_SUBST(SNPRINTF_RETURNS_BOGUS)
## (in default C library and libraries checked by AC_CHECK_LIB)
AC_MSG_NOTICE([CHECKS for library functions])
#
+# Define NO_LIBGEN_H if you don't have libgen.h.
+AC_CHECK_HEADER([libgen.h],
+[NO_LIBGEN_H=],
+[NO_LIBGEN_H=YesPlease])
+AC_SUBST(NO_LIBGEN_H)
+#
# Define NO_STRCASESTR if you don't have strcasestr.
GIT_CHECK_FUNC(strcasestr,
[NO_STRCASESTR=],
@@ -677,6 +692,13 @@ GIT_CHECK_FUNC(mkdtemp,
[NO_MKDTEMP=YesPlease])
AC_SUBST(NO_MKDTEMP)
#
+# Define NO_MKSTEMPS if you don't have mkstemps in the C library.
+GIT_CHECK_FUNC(mkstemps,
+[NO_MKSTEMPS=],
+[NO_MKSTEMPS=YesPlease])
+AC_SUBST(NO_MKSTEMPS)
+#
+#
# Define NO_MMAP if you want to avoid mmap.
#
# Define NO_ICONV if your libc does not properly support iconv.
diff --git a/connect.c b/connect.c
index 7636bf9..958c831 100644
--- a/connect.c
+++ b/connect.c
@@ -177,18 +177,11 @@ static enum protocol get_protocol(const char *name)
static const char *ai_name(const struct addrinfo *ai)
{
- static char addr[INET_ADDRSTRLEN];
- if ( AF_INET == ai->ai_family ) {
- struct sockaddr_in *in;
- in = (struct sockaddr_in *)ai->ai_addr;
- inet_ntop(ai->ai_family, &in->sin_addr, addr, sizeof(addr));
- } else if ( AF_INET6 == ai->ai_family ) {
- struct sockaddr_in6 *in;
- in = (struct sockaddr_in6 *)ai->ai_addr;
- inet_ntop(ai->ai_family, &in->sin6_addr, addr, sizeof(addr));
- } else {
+ static char addr[NI_MAXHOST];
+ if (getnameinfo(ai->ai_addr, ai->ai_addrlen, addr, sizeof(addr), NULL, 0,
+ NI_NUMERICHOST) != 0)
strcpy(addr, "(unknown)");
- }
+
return addr;
}
@@ -586,7 +579,10 @@ struct child_process *git_connect(int fd[2], const char *url_orig,
git_tcp_connect(fd, host, flags);
/*
* Separate original protocol components prog and path
- * from extended components with a NUL byte.
+ * from extended host header with a NUL byte.
+ *
+ * Note: Do not add any other headers here! Doing so
+ * will cause older git-daemon servers to crash.
*/
packet_write(fd[1],
"%s %s%chost=%s%c",
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 1a90cb8..80ab4e4 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -40,6 +40,10 @@
# with the bash.showDirtyState variable, which defaults to true
# once GIT_PS1_SHOWDIRTYSTATE is enabled.
#
+# You can also see if currently something is stashed, by setting
+# GIT_PS1_SHOWSTASHSTATE to a nonempty value. If something is stashed,
+# then a '$' will be shown next to the branch name.
+#
# To submit patches:
#
# *) Read Documentation/SubmittingPatches
@@ -84,43 +88,54 @@ __git_ps1 ()
if [ -n "$g" ]; then
local r
local b
- if [ -d "$g/rebase-apply" ]; then
- if [ -f "$g/rebase-apply/rebasing" ]; then
- r="|REBASE"
- elif [ -f "$g/rebase-apply/applying" ]; then
- r="|AM"
- else
- r="|AM/REBASE"
- fi
- b="$(git symbolic-ref HEAD 2>/dev/null)"
- elif [ -f "$g/rebase-merge/interactive" ]; then
+ if [ -f "$g/rebase-merge/interactive" ]; then
r="|REBASE-i"
b="$(cat "$g/rebase-merge/head-name")"
elif [ -d "$g/rebase-merge" ]; then
r="|REBASE-m"
b="$(cat "$g/rebase-merge/head-name")"
- elif [ -f "$g/MERGE_HEAD" ]; then
- r="|MERGING"
- b="$(git symbolic-ref HEAD 2>/dev/null)"
else
- if [ -f "$g/BISECT_LOG" ]; then
- r="|BISECTING"
- fi
- if ! b="$(git symbolic-ref HEAD 2>/dev/null)"; then
- if ! b="$(git describe --exact-match HEAD 2>/dev/null)"; then
- if [ -r "$g/HEAD" ]; then
- b="$(cut -c1-7 "$g/HEAD")..."
- fi
+ if [ -d "$g/rebase-apply" ]; then
+ if [ -f "$g/rebase-apply/rebasing" ]; then
+ r="|REBASE"
+ elif [ -f "$g/rebase-apply/applying" ]; then
+ r="|AM"
+ else
+ r="|AM/REBASE"
fi
+ elif [ -f "$g/MERGE_HEAD" ]; then
+ r="|MERGING"
+ elif [ -f "$g/BISECT_LOG" ]; then
+ r="|BISECTING"
fi
+
+ b="$(git symbolic-ref HEAD 2>/dev/null)" || {
+
+ b="$(
+ case "${GIT_PS1_DESCRIBE_STYLE-}" in
+ (contains)
+ git describe --contains HEAD ;;
+ (branch)
+ git describe --contains --all HEAD ;;
+ (describe)
+ git describe HEAD ;;
+ (* | default)
+ git describe --exact-match HEAD ;;
+ esac 2>/dev/null)" ||
+
+ b="$(cut -c1-7 "$g/HEAD" 2>/dev/null)..." ||
+ b="unknown"
+ b="($b)"
+ }
fi
local w
local i
+ local s
local c
if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then
- if [ "true" = "$(git config --bool core.bare 2>/dev/null)" ]; then
+ if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then
c="BARE:"
else
b="GIT_DIR!"
@@ -138,14 +153,15 @@ __git_ps1 ()
fi
fi
fi
+ if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ]; then
+ git rev-parse --verify refs/stash >/dev/null 2>&1 && s="$"
+ fi
fi
- if [ -n "$b" ]; then
- if [ -n "${1-}" ]; then
- printf "$1" "$c${b##refs/heads/}$w$i$r"
- else
- printf " (%s)" "$c${b##refs/heads/}$w$i$r"
- fi
+ if [ -n "${1-}" ]; then
+ printf "$1" "$c${b##refs/heads/}$w$i$s$r"
+ else
+ printf " (%s)" "$c${b##refs/heads/}$w$i$s$r"
fi
fi
}
@@ -911,7 +927,7 @@ _git_diff ()
}
__git_mergetools_common="diffuse ecmerge emerge kdiff3 meld opendiff
- tkdiff vimdiff gvimdiff xxdiff
+ tkdiff vimdiff gvimdiff xxdiff araxis
"
_git_difftool ()
@@ -1116,6 +1132,7 @@ __git_log_shortlog_options="
"
__git_log_pretty_formats="oneline short medium full fuller email raw format:"
+__git_log_date_formats="relative iso8601 rfc2822 short local default raw"
_git_log ()
{
@@ -1139,9 +1156,7 @@ _git_log ()
return
;;
--date=*)
- __gitcomp "
- relative iso8601 rfc2822 short local default
- " "" "${cur##--date=}"
+ __gitcomp "$__git_log_date_formats" "" "${cur##--date=}"
return
;;
--*)
@@ -1283,18 +1298,39 @@ _git_rebase ()
__gitcomp "$(__git_refs)"
}
+__git_send_email_confirm_options="always never auto cc compose"
+__git_send_email_suppresscc_options="author self cc ccbody sob cccmd body all"
+
_git_send_email ()
{
local cur="${COMP_WORDS[COMP_CWORD]}"
case "$cur" in
+ --confirm=*)
+ __gitcomp "
+ $__git_send_email_confirm_options
+ " "" "${cur##--confirm=}"
+ return
+ ;;
+ --suppress-cc=*)
+ __gitcomp "
+ $__git_send_email_suppresscc_options
+ " "" "${cur##--suppress-cc=}"
+
+ return
+ ;;
+ --smtp-encryption=*)
+ __gitcomp "ssl tls" "" "${cur##--smtp-encryption=}"
+ return
+ ;;
--*)
__gitcomp "--annotate --bcc --cc --cc-cmd --chain-reply-to
- --compose --dry-run --envelope-sender --from --identity
+ --compose --confirm= --dry-run --envelope-sender
+ --from --identity
--in-reply-to --no-chain-reply-to --no-signed-off-by-cc
--no-suppress-from --no-thread --quiet
--signed-off-by-cc --smtp-pass --smtp-server
- --smtp-server-port --smtp-ssl --smtp-user --subject
- --suppress-cc --suppress-from --thread --to
+ --smtp-server-port --smtp-encryption= --smtp-user
+ --subject --suppress-cc= --suppress-from --thread --to
--validate --no-validate"
return
;;
@@ -1302,6 +1338,35 @@ _git_send_email ()
COMPREPLY=()
}
+__git_config_get_set_variables ()
+{
+ local prevword word config_file= c=$COMP_CWORD
+ while [ $c -gt 1 ]; do
+ word="${COMP_WORDS[c]}"
+ case "$word" in
+ --global|--system|--file=*)
+ config_file="$word"
+ break
+ ;;
+ -f|--file)
+ config_file="$word $prevword"
+ break
+ ;;
+ esac
+ prevword=$word
+ c=$((--c))
+ done
+
+ for i in $(git --git-dir="$(__gitdir)" config $config_file --list \
+ 2>/dev/null); do
+ case "$i" in
+ *.*)
+ echo "${i/=*/}"
+ ;;
+ esac
+ done
+}
+
_git_config ()
{
local cur="${COMP_WORDS[COMP_CWORD]}"
@@ -1333,7 +1398,8 @@ _git_config ()
__gitcomp "$(__git_merge_strategies)"
return
;;
- color.branch|color.diff|color.interactive|color.status|color.ui)
+ color.branch|color.diff|color.interactive|\
+ color.showbranch|color.status|color.ui)
__gitcomp "always never auto"
return
;;
@@ -1348,6 +1414,30 @@ _git_config ()
"
return
;;
+ help.format)
+ __gitcomp "man info web html"
+ return
+ ;;
+ log.date)
+ __gitcomp "$__git_log_date_formats"
+ return
+ ;;
+ sendemail.aliasesfiletype)
+ __gitcomp "mutt mailrc pine elm gnus"
+ return
+ ;;
+ sendemail.confirm)
+ __gitcomp "$__git_send_email_confirm_options"
+ return
+ ;;
+ sendemail.suppresscc)
+ __gitcomp "$__git_send_email_suppresscc_options"
+ return
+ ;;
+ --get|--get-all|--unset|--unset-all)
+ __gitcomp "$(__git_config_get_set_variables)"
+ return
+ ;;
*.*)
COMPREPLY=()
return
@@ -1376,6 +1466,39 @@ _git_config ()
__gitcomp "$(__git_heads)" "$pfx" "$cur" "."
return
;;
+ guitool.*.*)
+ local pfx="${cur%.*}."
+ cur="${cur##*.}"
+ __gitcomp "
+ argprompt cmd confirm needsfile noconsole norescan
+ prompt revprompt revunmerged title
+ " "$pfx" "$cur"
+ return
+ ;;
+ difftool.*.*)
+ local pfx="${cur%.*}."
+ cur="${cur##*.}"
+ __gitcomp "cmd path" "$pfx" "$cur"
+ return
+ ;;
+ man.*.*)
+ local pfx="${cur%.*}."
+ cur="${cur##*.}"
+ __gitcomp "cmd path" "$pfx" "$cur"
+ return
+ ;;
+ mergetool.*.*)
+ local pfx="${cur%.*}."
+ cur="${cur##*.}"
+ __gitcomp "cmd path trustExitCode" "$pfx" "$cur"
+ return
+ ;;
+ pager.*)
+ local pfx="${cur%.*}."
+ cur="${cur#*.}"
+ __gitcomp "$(__git_all_commands)" "$pfx" "$cur"
+ return
+ ;;
remote.*.*)
local pfx="${cur%.*}."
cur="${cur##*.}"
@@ -1391,8 +1514,15 @@ _git_config ()
__gitcomp "$(__git_remotes)" "$pfx" "$cur" "."
return
;;
+ url.*.*)
+ local pfx="${cur%.*}."
+ cur="${cur##*.}"
+ __gitcomp "insteadof" "$pfx" "$cur"
+ return
+ ;;
esac
__gitcomp "
+ alias.
apply.whitespace
branch.autosetupmerge
branch.autosetuprebase
@@ -1410,11 +1540,15 @@ _git_config ()
color.diff.old
color.diff.plain
color.diff.whitespace
+ color.grep
+ color.grep.external
+ color.grep.match
color.interactive
color.interactive.header
color.interactive.help
color.interactive.prompt
color.pager
+ color.showbranch
color.status
color.status.added
color.status.changed
@@ -1427,6 +1561,7 @@ _git_config ()
core.autocrlf
core.bare
core.compression
+ core.createObject
core.deltaBaseCacheLimit
core.editor
core.excludesfile
@@ -1457,11 +1592,21 @@ _git_config ()
diff.renameLimit
diff.renameLimit.
diff.renames
+ diff.suppressBlankEmpty
+ diff.tool
+ diff.wordRegex
+ difftool.
+ difftool.prompt
fetch.unpackLimit
+ format.attach
+ format.cc
format.headers
format.numbered
format.pretty
+ format.signoff
+ format.subjectprefix
format.suffix
+ format.thread
gc.aggressiveWindow
gc.auto
gc.autopacklimit
@@ -1472,6 +1617,7 @@ _git_config ()
gc.rerereresolved
gc.rerereunresolved
gitcvs.allbinary
+ gitcvs.commitmsgannotation
gitcvs.dbTableNamePrefix
gitcvs.dbdriver
gitcvs.dbname
@@ -1480,6 +1626,7 @@ _git_config ()
gitcvs.enabled
gitcvs.logfile
gitcvs.usecrlfattr
+ guitool.
gui.blamehistoryctx
gui.commitmsgwidth
gui.copyblamethreshold
@@ -1506,13 +1653,24 @@ _git_config ()
http.sslVerify
i18n.commitEncoding
i18n.logOutputEncoding
+ imap.folder
+ imap.host
+ imap.pass
+ imap.port
+ imap.preformattedHTML
+ imap.sslverify
+ imap.tunnel
+ imap.user
instaweb.browser
instaweb.httpd
instaweb.local
instaweb.modulepath
instaweb.port
+ interactive.singlekey
log.date
log.showroot
+ mailmap.file
+ man.
man.viewer
merge.conflictstyle
merge.log
@@ -1520,7 +1678,9 @@ _git_config ()
merge.stat
merge.tool
merge.verbosity
+ mergetool.
mergetool.keepBackup
+ mergetool.prompt
pack.compression
pack.deltaCacheLimit
pack.deltaCacheSize
@@ -1530,8 +1690,11 @@ _git_config ()
pack.threads
pack.window
pack.windowMemory
+ pager.
pull.octopus
pull.twohead
+ push.default
+ rebase.stat
receive.denyCurrentBranch
receive.denyDeletes
receive.denyNonFastForwards
@@ -1540,11 +1703,32 @@ _git_config ()
repack.usedeltabaseoffset
rerere.autoupdate
rerere.enabled
+ sendemail.aliasesfile
+ sendemail.aliasesfiletype
+ sendemail.bcc
+ sendemail.cc
+ sendemail.cccmd
+ sendemail.chainreplyto
+ sendemail.confirm
+ sendemail.envelopesender
+ sendemail.multiedit
+ sendemail.signedoffbycc
+ sendemail.smtpencryption
+ sendemail.smtppass
+ sendemail.smtpserver
+ sendemail.smtpserverport
+ sendemail.smtpuser
+ sendemail.suppresscc
+ sendemail.suppressfrom
+ sendemail.thread
+ sendemail.to
+ sendemail.validate
showbranch.default
status.relativePaths
status.showUntrackedFiles
tar.umask
transfer.unpackLimit
+ url.
user.email
user.name
user.signingkey
@@ -1659,7 +1843,7 @@ _git_show ()
return
;;
--*)
- __gitcomp "--pretty= --format=
+ __gitcomp "--pretty= --format= --abbrev-commit --oneline
$__git_diff_common_options
"
return
@@ -1676,7 +1860,8 @@ _git_show_branch ()
__gitcomp "
--all --remotes --topo-order --current --more=
--list --independent --merge-base --no-name
- --sha1-name --topics --reflog
+ --color --no-color
+ --sha1-name --sparse --topics --reflog
"
return
;;
@@ -1696,10 +1881,10 @@ _git_stash ()
save,--*)
__gitcomp "--keep-index"
;;
- apply,--*)
+ apply,--*|pop,--*)
__gitcomp "--index"
;;
- show,--*|drop,--*|pop,--*|branch,--*)
+ show,--*|drop,--*|branch,--*)
COMPREPLY=()
;;
show,*|apply,*|drop,*|pop,*|branch,*)
diff --git a/contrib/convert-objects/convert-objects.c b/contrib/convert-objects/convert-objects.c
index 90e7900..f3b57bf 100644
--- a/contrib/convert-objects/convert-objects.c
+++ b/contrib/convert-objects/convert-objects.c
@@ -59,7 +59,7 @@ static void convert_ascii_sha1(void *buffer)
struct entry *entry;
if (get_sha1_hex(buffer, sha1))
- die("expected sha1, got '%s'", (char*) buffer);
+ die("expected sha1, got '%s'", (char *) buffer);
entry = convert_entry(sha1);
memcpy(buffer, sha1_to_hex(entry->new_sha1), 40);
}
@@ -100,7 +100,7 @@ static int write_subdirectory(void *buffer, unsigned long size, const char *base
if (!slash) {
newlen += sprintf(new + newlen, "%o %s", mode, path);
new[newlen++] = '\0';
- hashcpy((unsigned char*)new + newlen, (unsigned char *) buffer + len - 20);
+ hashcpy((unsigned char *)new + newlen, (unsigned char *) buffer + len - 20);
newlen += 20;
used += len;
@@ -271,7 +271,7 @@ static void convert_commit(void *buffer, unsigned long size, unsigned char *resu
unsigned long orig_size = size;
if (memcmp(buffer, "tree ", 5))
- die("Bad commit '%s'", (char*) buffer);
+ die("Bad commit '%s'", (char *) buffer);
convert_ascii_sha1((char *) buffer + 5);
buffer = (char *) buffer + 46; /* "tree " + "hex sha1" + "\n" */
while (!memcmp(buffer, "parent ", 7)) {
diff --git a/contrib/hooks/post-receive-email b/contrib/hooks/post-receive-email
index 60cbab6..2a66063 100644..100755
--- a/contrib/hooks/post-receive-email
+++ b/contrib/hooks/post-receive-email
@@ -44,6 +44,10 @@
# --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".
+# To list a gitweb/cgit URL *and* a full patch for each change set, use this:
+# "t=%s; printf 'http://.../?id=%%s' \$t; echo;echo; git show -C \$t; echo"
+# Be careful if "..." contains things that will be expanded by shell "eval"
+# or printf.
#
# Notes
# -----
diff --git a/ctype.c b/ctype.c
index b90ec00..7ee64c7 100644
--- a/ctype.c
+++ b/ctype.c
@@ -10,7 +10,7 @@ enum {
A = GIT_ALPHA,
D = GIT_DIGIT,
G = GIT_GLOB_SPECIAL, /* *, ?, [, \\ */
- R = GIT_REGEX_SPECIAL, /* $, (, ), +, ., ^, {, | * */
+ R = GIT_REGEX_SPECIAL, /* $, (, ), +, ., ^, {, | */
};
unsigned char sane_ctype[256] = {
diff --git a/daemon.c b/daemon.c
index 13401f1..b2babcc 100644
--- a/daemon.c
+++ b/daemon.c
@@ -406,15 +406,15 @@ static char *xstrdup_tolower(const char *str)
}
/*
- * Separate the "extra args" information as supplied by the client connection.
+ * Read the host as supplied by the client connection.
*/
-static void parse_extra_args(char *extra_args, int buflen)
+static void parse_host_arg(char *extra_args, int buflen)
{
char *val;
int vallen;
char *end = extra_args + buflen;
- while (extra_args < end && *extra_args) {
+ if (extra_args < end && *extra_args) {
saw_extended_args = 1;
if (strncasecmp("host=", extra_args, 5) == 0) {
val = extra_args + 5;
@@ -436,6 +436,8 @@ static void parse_extra_args(char *extra_args, int buflen)
/* On to the next one */
extra_args = val + vallen;
}
+ if (extra_args < end && *extra_args)
+ die("Invalid request");
}
/*
@@ -444,27 +446,27 @@ static void parse_extra_args(char *extra_args, int buflen)
if (hostname) {
#ifndef NO_IPV6
struct addrinfo hints;
- struct addrinfo *ai, *ai0;
+ struct addrinfo *ai;
int gai;
static char addrbuf[HOST_NAME_MAX + 1];
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME;
- gai = getaddrinfo(hostname, 0, &hints, &ai0);
+ gai = getaddrinfo(hostname, 0, &hints, &ai);
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));
- free(canon_hostname);
- canon_hostname = xstrdup(ai->ai_canonname);
- free(ip_address);
- ip_address = xstrdup(addrbuf);
- break;
- }
- freeaddrinfo(ai0);
+ struct sockaddr_in *sin_addr = (void *)ai->ai_addr;
+
+ inet_ntop(AF_INET, &sin_addr->sin_addr,
+ addrbuf, sizeof(addrbuf));
+ free(ip_address);
+ ip_address = xstrdup(addrbuf);
+
+ free(canon_hostname);
+ canon_hostname = xstrdup(ai->ai_canonname ?
+ ai->ai_canonname : ip_address);
+
+ freeaddrinfo(ai);
}
#else
struct hostent *hent;
@@ -545,7 +547,7 @@ static int execute(struct sockaddr *addr)
hostname = canon_hostname = ip_address = tcp_port = NULL;
if (len != pktlen)
- parse_extra_args(line + len + 1, pktlen - len - 1);
+ parse_host_arg(line + len + 1, pktlen - len - 1);
for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
struct daemon_service *s = &(daemon_service[i]);
diff --git a/date.c b/date.c
index 1165d30..409a17d 100644
--- a/date.c
+++ b/date.c
@@ -871,13 +871,15 @@ unsigned long approxidate(const char *date)
int number = 0;
struct tm tm, now;
struct timeval tv;
+ time_t time_sec;
char buffer[50];
if (parse_date(date, buffer, sizeof(buffer)) > 0)
return strtoul(buffer, NULL, 10);
gettimeofday(&tv, NULL);
- localtime_r(&tv.tv_sec, &tm);
+ time_sec = tv.tv_sec;
+ localtime_r(&time_sec, &tm);
now = tm;
for (;;) {
unsigned char c = *date;
diff --git a/decorate.c b/decorate.c
index 82d9e22..2f8a63e 100644
--- a/decorate.c
+++ b/decorate.c
@@ -8,7 +8,9 @@
static unsigned int hash_obj(const struct object *obj, unsigned int n)
{
- unsigned int hash = *(unsigned int *)obj->sha1;
+ unsigned int hash;
+
+ memcpy(&hash, obj->sha1, sizeof(unsigned int));
return hash % n;
}
@@ -16,7 +18,7 @@ static void *insert_decoration(struct decoration *n, const struct object *base,
{
int size = n->size;
struct object_decoration *hash = n->hash;
- int j = hash_obj(base, size);
+ unsigned int j = hash_obj(base, size);
while (hash[j].base) {
if (hash[j].base == base) {
@@ -68,7 +70,7 @@ void *add_decoration(struct decoration *n, const struct object *obj,
/* Lookup a decoration pointer */
void *lookup_decoration(struct decoration *n, const struct object *obj)
{
- int j;
+ unsigned int j;
/* nothing to lookup */
if (!n->size)
diff --git a/diff-lib.c b/diff-lib.c
index a310fb2..0aba6cd 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -214,7 +214,7 @@ static int get_stat_data(struct cache_entry *ce,
const unsigned char *sha1 = ce->sha1;
unsigned int mode = ce->ce_mode;
- if (!cached) {
+ if (!cached && !ce_uptodate(ce)) {
int changed;
struct stat st;
changed = check_removed(ce, &st);
diff --git a/diff-no-index.c b/diff-no-index.c
index 42c1dd8..4ebc1db 100644
--- a/diff-no-index.c
+++ b/diff-no-index.c
@@ -233,7 +233,7 @@ void diff_no_index(struct rev_info *revs,
if (prefix) {
int len = strlen(prefix);
- revs->diffopt.paths = xcalloc(2, sizeof(char*));
+ revs->diffopt.paths = xcalloc(2, sizeof(char *));
for (i = 0; i < 2; i++) {
const char *p = argv[argc - 2 + i];
/*
diff --git a/diff.c b/diff.c
index 3ac7168..43835d7 100644
--- a/diff.c
+++ b/diff.c
@@ -189,7 +189,7 @@ static void remove_tempfile(void)
int i;
for (i = 0; i < ARRAY_SIZE(diff_temp); i++) {
if (diff_temp[i].name == diff_temp[i].tmp_path)
- unlink(diff_temp[i].name);
+ unlink_or_warn(diff_temp[i].name);
diff_temp[i].name = NULL;
}
}
@@ -839,10 +839,9 @@ static int scale_linear(int it, int width, int max_change)
}
static void show_name(FILE *file,
- const char *prefix, const char *name, int len,
- const char *reset, const char *set)
+ const char *prefix, const char *name, int len)
{
- fprintf(file, " %s%s%-*s%s |", set, prefix, len, name, reset);
+ fprintf(file, " %s%-*s |", prefix, len, name);
}
static void show_graph(FILE *file, char ch, int cnt, const char *set, const char *reset)
@@ -876,7 +875,7 @@ static void fill_print_name(struct diffstat_file *file)
file->print_name = pname;
}
-static void show_stats(struct diffstat_t* data, struct diff_options *options)
+static void show_stats(struct diffstat_t *data, struct diff_options *options)
{
int i, len, add, del, adds = 0, dels = 0;
int max_change = 0, max_len = 0;
@@ -956,7 +955,7 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options)
}
if (data->files[i]->is_binary) {
- show_name(options->file, prefix, name, len, reset, set);
+ show_name(options->file, prefix, name, len);
fprintf(options->file, " Bin ");
fprintf(options->file, "%s%d%s", del_c, deleted, reset);
fprintf(options->file, " -> ");
@@ -966,7 +965,7 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options)
continue;
}
else if (data->files[i]->is_unmerged) {
- show_name(options->file, prefix, name, len, reset, set);
+ show_name(options->file, prefix, name, len);
fprintf(options->file, " Unmerged\n");
continue;
}
@@ -988,7 +987,7 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options)
add = scale_linear(add, width, max_change);
del = scale_linear(del, width, max_change);
}
- show_name(options->file, prefix, name, len, reset, set);
+ show_name(options->file, prefix, name, len);
fprintf(options->file, "%5d%s", added + deleted,
added + deleted ? " " : "");
show_graph(options->file, '+', add, add_c, reset);
@@ -996,8 +995,8 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options)
fprintf(options->file, "\n");
}
fprintf(options->file,
- "%s %d files changed, %d insertions(+), %d deletions(-)%s\n",
- set, total_files, adds, dels, reset);
+ " %d files changed, %d insertions(+), %d deletions(-)\n",
+ total_files, adds, dels);
}
static void show_shortstats(struct diffstat_t* data, struct diff_options *options)
@@ -1025,7 +1024,7 @@ static void show_shortstats(struct diffstat_t* data, struct diff_options *option
total_files, adds, dels);
}
-static void show_numstat(struct diffstat_t* data, struct diff_options *options)
+static void show_numstat(struct diffstat_t *data, struct diff_options *options)
{
int i;
@@ -1965,8 +1964,16 @@ static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
{
int fd;
struct strbuf buf = STRBUF_INIT;
+ struct strbuf template = STRBUF_INIT;
+ char *path_dup = xstrdup(path);
+ const char *base = basename(path_dup);
+
+ /* Generate "XXXXXX_basename.ext" */
+ strbuf_addstr(&template, "XXXXXX_");
+ strbuf_addstr(&template, base);
- fd = git_mkstemp(temp->tmp_path, PATH_MAX, ".diff_XXXXXX");
+ fd = git_mkstemps(temp->tmp_path, PATH_MAX, template.buf,
+ strlen(base) + 1);
if (fd < 0)
die("unable to create temp-file: %s", strerror(errno));
if (convert_to_working_tree(path,
@@ -1982,6 +1989,8 @@ static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
temp->hex[40] = 0;
sprintf(temp->mode, "%06o", mode);
strbuf_release(&buf);
+ strbuf_release(&template);
+ free(path_dup);
}
static struct diff_tempfile *prepare_temp_file(const char *name,
@@ -2015,18 +2024,15 @@ static struct diff_tempfile *prepare_temp_file(const char *name,
die("stat(%s): %s", name, strerror(errno));
}
if (S_ISLNK(st.st_mode)) {
- int ret;
- char buf[PATH_MAX + 1]; /* ought to be SYMLINK_MAX */
- ret = readlink(name, buf, sizeof(buf));
- if (ret < 0)
+ struct strbuf sb = STRBUF_INIT;
+ if (strbuf_readlink(&sb, name, st.st_size) < 0)
die("readlink(%s)", name);
- if (ret == sizeof(buf))
- die("symlink too long: %s", name);
- prep_temp_blob(name, temp, buf, ret,
+ prep_temp_blob(name, temp, sb.buf, sb.len,
(one->sha1_valid ?
one->sha1 : null_sha1),
(one->sha1_valid ?
one->mode : S_IFLNK));
+ strbuf_release(&sb);
}
else {
/* we can borrow from the file in the work tree */
@@ -3590,6 +3596,7 @@ static char *run_textconv(const char *pgm, struct diff_filespec *spec,
if (start_command(&child) != 0 ||
strbuf_read(&buf, child.out, 0) < 0 ||
finish_command(&child) != 0) {
+ strbuf_release(&buf);
remove_tempfile();
error("error running textconv command '%s'", pgm);
return NULL;
diff --git a/dir.c b/dir.c
index c91ebfb..bbfcb56 100644
--- a/dir.c
+++ b/dir.c
@@ -53,7 +53,7 @@ int common_prefix(const char **pathspec)
}
/*
- * Does 'match' matches the given name?
+ * Does 'match' match the given name?
* A match is found if
*
* (1) the 'match' string is leading directory of 'name', or
@@ -156,7 +156,7 @@ void add_exclude(const char *string, const char *base,
if (len && string[len - 1] == '/') {
char *s;
x = xmalloc(sizeof(*x) + len);
- s = (char*)(x+1);
+ s = (char *)(x+1);
memcpy(s, string, len - 1);
s[len - 1] = '\0';
string = s;
@@ -290,7 +290,7 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
dir->basebuf[baselen] = '\0';
}
-/* Scan the list and let the last match determines the fate.
+/* Scan the list and let the last match determine the fate.
* Return 1 for exclude, 0 for include and -1 for undecided.
*/
static int excluded_1(const char *pathname,
@@ -396,7 +396,7 @@ static struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathna
static struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname, int len)
{
- if (cache_name_pos(pathname, len) >= 0)
+ if (!cache_name_is_other(pathname, len))
return NULL;
ALLOC_GROW(dir->ignored, dir->ignored_nr+1, dir->ignored_alloc);
@@ -576,7 +576,7 @@ static int get_dtype(struct dirent *de, const char *path)
*/
static int read_directory_recursive(struct dir_struct *dir, const char *path, const char *base, int baselen, int check_only, const struct path_simplify *simplify)
{
- DIR *fdir = opendir(path);
+ DIR *fdir = opendir(*path ? path : ".");
int contents = 0;
if (fdir) {
diff --git a/entry.c b/entry.c
index 915514a..cc841ed 100644
--- a/entry.c
+++ b/entry.c
@@ -35,7 +35,7 @@ static void create_directories(const char *path, int path_len,
*/
if (mkdir(buf, 0777)) {
if (errno == EEXIST && state->force &&
- !unlink(buf) && !mkdir(buf, 0777))
+ !unlink_or_warn(buf) && !mkdir(buf, 0777))
continue;
die("cannot create directory at %s", buf);
}
diff --git a/environment.c b/environment.c
index 4696885..801a005 100644
--- a/environment.c
+++ b/environment.c
@@ -43,6 +43,10 @@ unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;
enum rebase_setup_type autorebase = AUTOREBASE_NEVER;
enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;
+#ifndef OBJECT_CREATION_MODE
+#define OBJECT_CREATION_MODE OBJECT_CREATION_USES_HARDLINKS
+#endif
+enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;
/* Parallel index stat data preload? */
int core_preload_index = 0;
diff --git a/fast-import.c b/fast-import.c
index 8d959af..a2a2458 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -212,7 +212,7 @@ struct tree_content;
struct tree_entry
{
struct tree_content *tree;
- struct atom_str* name;
+ struct atom_str *name;
struct tree_entry_ms
{
uint16_t mode;
@@ -313,7 +313,7 @@ static unsigned int object_entry_alloc = 5000;
static struct object_entry_pool *blocks;
static struct object_entry *object_table[1 << 16];
static struct mark_set *marks;
-static const char* mark_file;
+static const char *mark_file;
/* Our last blob */
static struct last_object last_blob = { STRBUF_INIT, 0, 0, 0 };
@@ -672,7 +672,7 @@ static struct branch *lookup_branch(const char *name)
static struct branch *new_branch(const char *name)
{
unsigned int hc = hc_str(name, strlen(name)) % branch_table_sz;
- struct branch* b = lookup_branch(name);
+ struct branch *b = lookup_branch(name);
if (b)
die("Invalid attempt to create duplicate branch: %s", name);
@@ -931,7 +931,7 @@ static void unkeep_all_packs(void)
struct packed_git *p = all_packs[k];
snprintf(name, sizeof(name), "%s/pack/pack-%s.keep",
get_object_directory(), sha1_to_hex(p->sha1));
- unlink(name);
+ unlink_or_warn(name);
}
}
@@ -981,7 +981,7 @@ static void end_packfile(void)
}
else {
close(old_p->pack_fd);
- unlink(old_p->pack_name);
+ unlink_or_warn(old_p->pack_name);
}
free(old_p);
@@ -1035,7 +1035,7 @@ static int store_object(
git_SHA_CTX c;
z_stream s;
- hdrlen = sprintf((char*)hdr,"%s %lu", typename(type),
+ hdrlen = sprintf((char *)hdr,"%s %lu", typename(type),
(unsigned long)dat->len) + 1;
git_SHA1_Init(&c);
git_SHA1_Update(&c, hdr, hdrlen);
@@ -1217,7 +1217,7 @@ static const char *get_mode(const char *str, uint16_t *modep)
static void load_tree(struct tree_entry *root)
{
- unsigned char* sha1 = root->versions[1].sha1;
+ unsigned char *sha1 = root->versions[1].sha1;
struct object_entry *myoe;
struct tree_content *t;
unsigned long size;
@@ -1258,8 +1258,8 @@ static void load_tree(struct tree_entry *root)
e->versions[0].mode = e->versions[1].mode;
e->name = to_atom(c, strlen(c));
c += e->name->str_len + 1;
- hashcpy(e->versions[0].sha1, (unsigned char*)c);
- hashcpy(e->versions[1].sha1, (unsigned char*)c);
+ hashcpy(e->versions[0].sha1, (unsigned char *)c);
+ hashcpy(e->versions[1].sha1, (unsigned char *)c);
c += 20;
}
free(buf);
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index f6e536e..df9f231 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -767,6 +767,96 @@ sub split_hunk {
return @split;
}
+sub find_last_o_ctx {
+ my ($it) = @_;
+ my $text = $it->{TEXT};
+ my ($o_ofs, $o_cnt) = parse_hunk_header($text->[0]);
+ my $i = @{$text};
+ my $last_o_ctx = $o_ofs + $o_cnt;
+ while (0 < --$i) {
+ my $line = $text->[$i];
+ if ($line =~ /^ /) {
+ $last_o_ctx--;
+ next;
+ }
+ last;
+ }
+ return $last_o_ctx;
+}
+
+sub merge_hunk {
+ my ($prev, $this) = @_;
+ my ($o0_ofs, $o0_cnt, $n0_ofs, $n0_cnt) =
+ parse_hunk_header($prev->{TEXT}[0]);
+ my ($o1_ofs, $o1_cnt, $n1_ofs, $n1_cnt) =
+ parse_hunk_header($this->{TEXT}[0]);
+
+ my (@line, $i, $ofs, $o_cnt, $n_cnt);
+ $ofs = $o0_ofs;
+ $o_cnt = $n_cnt = 0;
+ for ($i = 1; $i < @{$prev->{TEXT}}; $i++) {
+ my $line = $prev->{TEXT}[$i];
+ if ($line =~ /^\+/) {
+ $n_cnt++;
+ push @line, $line;
+ next;
+ }
+
+ last if ($o1_ofs <= $ofs);
+
+ $o_cnt++;
+ $ofs++;
+ if ($line =~ /^ /) {
+ $n_cnt++;
+ }
+ push @line, $line;
+ }
+
+ for ($i = 1; $i < @{$this->{TEXT}}; $i++) {
+ my $line = $this->{TEXT}[$i];
+ if ($line =~ /^\+/) {
+ $n_cnt++;
+ push @line, $line;
+ next;
+ }
+ $ofs++;
+ $o_cnt++;
+ if ($line =~ /^ /) {
+ $n_cnt++;
+ }
+ push @line, $line;
+ }
+ my $head = ("@@ -$o0_ofs" .
+ (($o_cnt != 1) ? ",$o_cnt" : '') .
+ " +$n0_ofs" .
+ (($n_cnt != 1) ? ",$n_cnt" : '') .
+ " @@\n");
+ @{$prev->{TEXT}} = ($head, @line);
+}
+
+sub coalesce_overlapping_hunks {
+ my (@in) = @_;
+ my @out = ();
+
+ my ($last_o_ctx, $last_was_dirty);
+
+ for (grep { $_->{USE} } @in) {
+ my $text = $_->{TEXT};
+ my ($o_ofs) = parse_hunk_header($text->[0]);
+ if (defined $last_o_ctx &&
+ $o_ofs <= $last_o_ctx &&
+ !$_->{DIRTY} &&
+ !$last_was_dirty) {
+ merge_hunk($out[-1], $_);
+ }
+ else {
+ push @out, $_;
+ }
+ $last_o_ctx = find_last_o_ctx($out[-1]);
+ $last_was_dirty = $_->{DIRTY};
+ }
+ return @out;
+}
sub color_diff {
return map {
@@ -878,7 +968,8 @@ sub edit_hunk_loop {
my $newhunk = {
TEXT => $text,
TYPE => $hunk->[$ix]->{TYPE},
- USE => 1
+ USE => 1,
+ DIRTY => 1,
};
if (diff_applies($head,
@{$hunk}[0..$ix-1],
@@ -1210,6 +1301,8 @@ sub patch_update_file {
}
}
+ @hunk = coalesce_overlapping_hunks(@hunk);
+
my $n_lofs = 0;
my @result = ();
for (@hunk) {
diff --git a/git-am.sh b/git-am.sh
index 6d1848b..578780b 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -44,11 +44,7 @@ else
fi
sq () {
- for sqarg
- do
- printf "%s" "$sqarg" |
- sed -e 's/'\''/'\''\\'\'''\''/g' -e 's/.*/ '\''&'\''/'
- done
+ git rev-parse --sq-quote "$@"
}
stop_here () {
diff --git a/git-bisect.sh b/git-bisect.sh
index 24712ff..8969553 100755
--- a/git-bisect.sh
+++ b/git-bisect.sh
@@ -33,16 +33,6 @@ require_work_tree
_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
-sq() {
- @@PERL@@ -e '
- for (@ARGV) {
- s/'\''/'\'\\\\\'\''/g;
- print " '\''$_'\''";
- }
- print "\n";
- ' "$@"
-}
-
bisect_autostart() {
test -s "$GIT_DIR/BISECT_START" || {
echo >&2 'You need to start by "git bisect start"'
@@ -107,7 +97,7 @@ bisect_start() {
for arg; do
case "$arg" in --) has_double_dash=1; break ;; esac
done
- orig_args=$(sq "$@")
+ orig_args=$(git rev-parse --sq-quote "$@")
bad_seen=0
eval=''
while [ $# -gt 0 ]; do
@@ -147,7 +137,7 @@ bisect_start() {
# Write new start state.
#
echo "$start_head" >"$GIT_DIR/BISECT_START" &&
- sq "$@" >"$GIT_DIR/BISECT_NAMES" &&
+ git rev-parse --sq-quote "$@" >"$GIT_DIR/BISECT_NAMES" &&
eval "$eval" &&
echo "git bisect start$orig_args" >>"$GIT_DIR/BISECT_LOG" || exit
#
@@ -177,10 +167,6 @@ is_expected_rev() {
test "$1" = $(cat "$GIT_DIR/BISECT_EXPECTED_REV")
}
-mark_expected_rev() {
- echo "$1" > "$GIT_DIR/BISECT_EXPECTED_REV"
-}
-
check_expected_revs() {
for _rev in "$@"; do
if ! is_expected_rev "$_rev"; then
@@ -199,7 +185,7 @@ bisect_skip() {
*..*)
revs=$(git rev-list "$arg") || die "Bad rev input: $arg" ;;
*)
- revs=$(sq "$arg") ;;
+ revs=$(git rev-parse --sq-quote "$arg") ;;
esac
all="$all $revs"
done
@@ -279,162 +265,22 @@ bisect_auto_next() {
bisect_next_check && bisect_next || :
}
-exit_if_skipped_commits () {
- _tried=$1
- _bad=$2
- if test -n "$_tried" ; then
- echo "There are only 'skip'ped commit left to test."
- echo "The first bad commit could be any of:"
- echo "$_tried" | tr '[|]' '[\012]'
- test -n "$_bad" && echo "$_bad"
- echo "We cannot bisect more!"
- exit 2
- fi
-}
-
-bisect_checkout() {
- _rev="$1"
- _msg="$2"
- echo "Bisecting: $_msg"
- mark_expected_rev "$_rev"
- git checkout -q "$_rev" -- || exit
- git show-branch "$_rev"
-}
-
-is_among() {
- _rev="$1"
- _list="$2"
- case "$_list" in *$_rev*) return 0 ;; esac
- return 1
-}
-
-handle_bad_merge_base() {
- _badmb="$1"
- _good="$2"
- if is_expected_rev "$_badmb"; then
- cat >&2 <<EOF
-The merge base $_badmb is bad.
-This means the bug has been fixed between $_badmb and [$_good].
-EOF
- exit 3
- else
- cat >&2 <<EOF
-Some good revs are not ancestor of the bad rev.
-git bisect cannot work properly in this case.
-Maybe you mistake good and bad revs?
-EOF
- exit 1
- fi
-}
-
-handle_skipped_merge_base() {
- _mb="$1"
- _bad="$2"
- _good="$3"
- cat >&2 <<EOF
-Warning: the merge base between $_bad and [$_good] must be skipped.
-So we cannot be sure the first bad commit is between $_mb and $_bad.
-We continue anyway.
-EOF
-}
-
-#
-# "check_merge_bases" checks that merge bases are not "bad".
-#
-# - If one is "good", that's good, we have nothing to do.
-# - If one is "bad", it means the user assumed something wrong
-# and we must exit.
-# - If one is "skipped", we can't know but we should warn.
-# - If we don't know, we should check it out and ask the user to test.
-#
-# In the last case we will return 1, and otherwise 0.
-#
-check_merge_bases() {
- _bad="$1"
- _good="$2"
- _skip="$3"
- for _mb in $(git merge-base --all $_bad $_good)
- do
- if is_among "$_mb" "$_good"; then
- continue
- elif test "$_mb" = "$_bad"; then
- handle_bad_merge_base "$_bad" "$_good"
- elif is_among "$_mb" "$_skip"; then
- handle_skipped_merge_base "$_mb" "$_bad" "$_good"
- else
- bisect_checkout "$_mb" "a merge base must be tested"
- return 1
- fi
- done
- return 0
-}
-
-#
-# "check_good_are_ancestors_of_bad" checks that all "good" revs are
-# ancestor of the "bad" rev.
-#
-# If that's not the case, we need to check the merge bases.
-# If a merge base must be tested by the user we return 1 and
-# otherwise 0.
-#
-check_good_are_ancestors_of_bad() {
- test -f "$GIT_DIR/BISECT_ANCESTORS_OK" &&
- return
-
- _bad="$1"
- _good=$(echo $2 | sed -e 's/\^//g')
- _skip="$3"
-
- # Bisecting with no good rev is ok
- test -z "$_good" && return
-
- _side=$(git rev-list $_good ^$_bad)
- if test -n "$_side"; then
- # Return if a checkout was done
- check_merge_bases "$_bad" "$_good" "$_skip" || return
- fi
-
- : > "$GIT_DIR/BISECT_ANCESTORS_OK"
-
- return 0
-}
-
bisect_next() {
case "$#" in 0) ;; *) usage ;; esac
bisect_autostart
bisect_next_check good
- # Get bad, good and skipped revs
- bad=$(git rev-parse --verify refs/bisect/bad) &&
- good=$(git for-each-ref --format='^%(objectname)' \
- "refs/bisect/good-*" | tr '\012' ' ') &&
- skip=$(git for-each-ref --format='%(objectname)' \
- "refs/bisect/skip-*" | tr '\012' ' ') || exit
-
- # Maybe some merge bases must be tested first
- check_good_are_ancestors_of_bad "$bad" "$good" "$skip"
- # Return now if a checkout has already been done
- test "$?" -eq "1" && return
-
- # Get bisection information
- eval=$(eval "git bisect--helper --next-vars") &&
- eval "$eval" || exit
-
- if [ -z "$bisect_rev" ]; then
- # We should exit here only if the "bad"
- # commit is also a "skip" commit (see above).
- exit_if_skipped_commits "$bisect_tried"
- echo "$bad was both good and bad"
- exit 1
- fi
- if [ "$bisect_rev" = "$bad" ]; then
- exit_if_skipped_commits "$bisect_tried" "$bad"
- echo "$bisect_rev is first bad commit"
- git diff-tree --pretty $bisect_rev
- exit 0
- fi
+ # Perform all bisection computation, display and checkout
+ git bisect--helper --next-all
+ res=$?
+
+ # Check if we should exit because bisection is finished
+ test $res -eq 10 && exit 0
- bisect_checkout "$bisect_rev" "$bisect_nr revisions left to test after this (roughly $bisect_steps steps)"
+ # Check for an error in the bisection process
+ test $res -ne 0 && exit $res
+
+ return 0
}
bisect_visualize() {
diff --git a/git-compat-util.h b/git-compat-util.h
index 785aa31..919b7f1 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -7,7 +7,7 @@
/*
* See if our compiler is known to support flexible array members.
*/
-#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && (!defined(__SUNPRO_C) || (__SUNPRO_C > 0x580))
# define FLEX_ARRAY /* empty */
#elif defined(__GNUC__)
# if (__GNUC__ >= 3)
@@ -39,13 +39,29 @@
/* Approximation of the length of the decimal representation of this type. */
#define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1)
-#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__USLC__) && !defined(_M_UNIX)
+#if defined(__sun__)
+ /*
+ * On Solaris, when _XOPEN_EXTENDED is set, its header file
+ * forces the programs to be XPG4v2, defeating any _XOPEN_SOURCE
+ * setting to say we are XPG5 or XPG6. Also on Solaris,
+ * XPG6 programs must be compiled with a c99 compiler, while
+ * non XPG6 programs must be compiled with a pre-c99 compiler.
+ */
+# if __STDC_VERSION__ - 0 >= 199901L
+# define _XOPEN_SOURCE 600
+# else
+# define _XOPEN_SOURCE 500
+# endif
+#elif !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__USLC__) && !defined(_M_UNIX)
#define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */
+#ifndef __sun__
#define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */
#endif
+#endif
#define _ALL_SOURCE 1
#define _GNU_SOURCE 1
#define _BSD_SOURCE 1
+#define _NETBSD_SOURCE 1
#include <unistd.h>
#include <stdio.h>
@@ -96,6 +112,13 @@
#include "compat/mingw.h"
#endif /* __MINGW32__ */
+#ifndef NO_LIBGEN_H
+#include <libgen.h>
+#else
+#define basename gitbasename
+extern char *gitbasename(char *);
+#endif
+
#ifndef NO_ICONV
#include <iconv.h>
#endif
@@ -231,6 +254,11 @@ extern int gitsetenv(const char *, const char *, int);
extern char *gitmkdtemp(char *);
#endif
+#ifdef NO_MKSTEMPS
+#define mkstemps gitmkstemps
+extern int gitmkstemps(char *, int);
+#endif
+
#ifdef NO_UNSETENV
#define unsetenv gitunsetenv
extern void gitunsetenv(const char *);
@@ -414,4 +442,10 @@ void git_qsort(void *base, size_t nmemb, size_t size,
#define fstat_is_reliable() 1
#endif
+/*
+ * Preserves errno, prints a message, but gives no warning for ENOENT.
+ * Always returns the return value of unlink(2).
+ */
+int unlink_or_warn(const char *path);
+
#endif
diff --git a/git-cvsexportcommit.perl b/git-cvsexportcommit.perl
index 6d9f0ef..9ec1df9 100755
--- a/git-cvsexportcommit.perl
+++ b/git-cvsexportcommit.perl
@@ -225,7 +225,14 @@ if (@canstatusfiles) {
foreach my $name (keys %todo) {
my $basename = basename($name);
- $basename = "no file " . $basename if (exists($added{$basename}));
+ # CVS reports files that don't exist in the current revision as
+ # "no file $basename" in its "status" output, so we should
+ # anticipate that. Totally unknown files will have a status
+ # "Unknown". However, if they exist in the Attic, their status
+ # will be "Up-to-date" (this means they were added once but have
+ # been removed).
+ $basename = "no file $basename" if $added{$basename};
+
$basename =~ s/^\s+//;
$basename =~ s/\s+$//;
@@ -233,31 +240,45 @@ if (@canstatusfiles) {
$fullname{$basename} = $name;
push (@canstatusfiles2, $name);
delete($todo{$name});
- }
+ }
}
my @cvsoutput;
@cvsoutput = xargs_safe_pipe_capture([@cvs, 'status'], @canstatusfiles2);
foreach my $l (@cvsoutput) {
- chomp $l;
- if ($l =~ /^File:\s+(.*\S)\s+Status: (.*)$/) {
- if (!exists($fullname{$1})) {
- print STDERR "Huh? Status reported for unexpected file '$1'\n";
- } else {
- $cvsstat{$fullname{$1}} = $2;
- }
- }
+ chomp $l;
+ next unless
+ my ($file, $status) = $l =~ /^File:\s+(.*\S)\s+Status: (.*)$/;
+
+ my $fullname = $fullname{$file};
+ print STDERR "Huh? Status '$status' reported for unexpected file '$file'\n"
+ unless defined $fullname;
+
+ # This response means the file does not exist except in
+ # CVS's attic, so set the status accordingly
+ $status = "In-attic"
+ if $file =~ /^no file /
+ && $status eq 'Up-to-date';
+
+ $cvsstat{$fullname{$file}} = $status;
}
}
}
-# ... validate new files,
+# ... Validate that new files have the correct status
foreach my $f (@afiles) {
- if (defined ($cvsstat{$f}) and $cvsstat{$f} ne "Unknown") {
- $dirty = 1;
+ next unless defined(my $stat = $cvsstat{$f});
+
+ # This means the file has never been seen before
+ next if $stat eq 'Unknown';
+
+ # This means the file has been seen before but was removed
+ next if $stat eq 'In-attic';
+
+ $dirty = 1;
warn "File $f is already known in your CVS checkout -- perhaps it has been added by another user. Or this may indicate that it exists on a different branch. If this is the case, use -f to force the merge.\n";
warn "Status was: $cvsstat{$f}\n";
- }
}
+
# ... validate known files.
foreach my $f (@files) {
next if grep { $_ eq $f } @afiles;
diff --git a/git-difftool.perl b/git-difftool.perl
index bd828c2..ba5e60a 100755
--- a/git-difftool.perl
+++ b/git-difftool.perl
@@ -82,5 +82,11 @@ sub generate_command
}
setup_environment();
+
+# ActiveState Perl for Win32 does not implement POSIX semantics of
+# exec* system call. It just spawns the given executable and finishes
+# the starting program, exiting with code 0.
+# system will at least catch the errors returned by git diff,
+# allowing the caller of git difftool better handling of failures.
my $rc = system(generate_command());
exit($rc | ($rc >> 8));
diff --git a/git-gui/Makefile b/git-gui/Makefile
index 3ad8a21..b3580e9 100644
--- a/git-gui/Makefile
+++ b/git-gui/Makefile
@@ -105,8 +105,11 @@ endif
ifeq ($(uname_S),Darwin)
TKFRAMEWORK = /Library/Frameworks/Tk.framework/Resources/Wish.app
- ifeq ($(shell expr "$(uname_R)" : '9\.'),2)
- TKFRAMEWORK = /System/Library/Frameworks/Tk.framework/Resources/Wish\ Shell.app
+ ifeq ($(shell echo "$(uname_R)" | awk -F. '{if ($$1 >= 9) print "y"}')_$(shell test -d $(TKFRAMEWORK) || echo n),y_n)
+ TKFRAMEWORK = /System/Library/Frameworks/Tk.framework/Resources/Wish.app
+ ifeq ($(shell test -d $(TKFRAMEWORK) || echo n),n)
+ TKFRAMEWORK = /System/Library/Frameworks/Tk.framework/Resources/Wish\ Shell.app
+ endif
endif
TKEXECUTABLE = $(shell basename "$(TKFRAMEWORK)" .app)
endif
diff --git a/git-gui/git-gui.sh b/git-gui/git-gui.sh
index e018e07..14b92ba 100755
--- a/git-gui/git-gui.sh
+++ b/git-gui/git-gui.sh
@@ -122,6 +122,7 @@ unset oguimsg
set _appname {Git Gui}
set _gitdir {}
set _gitexec {}
+set _githtmldir {}
set _reponame {}
set _iscygwin {}
set _search_path {}
@@ -168,6 +169,28 @@ proc gitexec {args} {
return [eval [list file join $_gitexec] $args]
}
+proc githtmldir {args} {
+ global _githtmldir
+ if {$_githtmldir eq {}} {
+ if {[catch {set _githtmldir [git --html-path]}]} {
+ # Git not installed or option not yet supported
+ return {}
+ }
+ if {[is_Cygwin]} {
+ set _githtmldir [exec cygpath \
+ --windows \
+ --absolute \
+ $_githtmldir]
+ } else {
+ set _githtmldir [file normalize $_githtmldir]
+ }
+ }
+ if {$args eq {}} {
+ return $_githtmldir
+ }
+ return [eval [list file join $_githtmldir] $args]
+}
+
proc reponame {} {
return $::_reponame
}
@@ -640,10 +663,13 @@ font create font_diffbold
font create font_diffitalic
foreach class {Button Checkbutton Entry Label
- Labelframe Listbox Menu Message
+ Labelframe Listbox Message
Radiobutton Spinbox Text} {
option add *$class.font font_ui
}
+if {![is_MacOSX]} {
+ option add *Menu.font font_ui
+}
unset class
if {[is_Windows] || [is_MacOSX]} {
@@ -699,7 +725,7 @@ proc apply_config {} {
set default_config(branch.autosetupmerge) true
set default_config(merge.tool) {}
-set default_config(merge.keepbackup) true
+set default_config(mergetool.keepbackup) true
set default_config(merge.diffstat) true
set default_config(merge.summary) false
set default_config(merge.verbosity) 2
@@ -769,9 +795,9 @@ if {![regsub {^git version } $_git_version {} _git_version]} {
set _real_git_version $_git_version
regsub -- {[\-\.]dirty$} $_git_version {} _git_version
regsub {\.[0-9]+\.g[0-9a-f]+$} $_git_version {} _git_version
-regsub {\.rc[0-9]+$} $_git_version {} _git_version
+regsub {\.[a-zA-Z]+\.?[0-9]+$} $_git_version {} _git_version
regsub {\.GIT$} $_git_version {} _git_version
-regsub {\.[a-zA-Z]+\.[0-9]+$} $_git_version {} _git_version
+regsub {\.[a-zA-Z]+\.?[0-9]+$} $_git_version {} _git_version
if {![regexp {^[1-9]+(\.[0-9]+)+$} $_git_version]} {
catch {wm withdraw .}
@@ -1108,6 +1134,7 @@ set current_diff_path {}
set is_3way_diff 0
set is_conflict_diff 0
set selected_commit_type new
+set diff_empty_count 0
set nullid "0000000000000000000000000000000000000000"
set nullid2 "0000000000000000000000000000000000000001"
@@ -1924,7 +1951,7 @@ proc do_explore {} {
# freedesktop.org-conforming system is our best shot
set explorer "xdg-open"
}
- eval exec $explorer [file dirname [gitdir]] &
+ eval exec $explorer [list [file nativename [file dirname [gitdir]]]] &
}
set is_quitting 0
@@ -2277,6 +2304,12 @@ set ui_comm {}
# -- Menu Bar
#
menu .mbar -tearoff 0
+if {[is_MacOSX]} {
+ # -- Apple Menu (Mac OS X only)
+ #
+ .mbar add cascade -label Apple -menu .mbar.apple
+ menu .mbar.apple
+}
.mbar add cascade -label [mc Repository] -menu .mbar.repository
.mbar add cascade -label [mc Edit] -menu .mbar.edit
if {[is_enabled branch]} {
@@ -2292,7 +2325,6 @@ if {[is_enabled transport]} {
if {[is_enabled multicommit] || [is_enabled singlecommit]} {
.mbar add cascade -label [mc Tools] -menu .mbar.tools
}
-. configure -menu .mbar
# -- Repository Menu
#
@@ -2545,19 +2577,7 @@ if {[is_enabled transport]} {
}
if {[is_MacOSX]} {
- # -- Apple Menu (Mac OS X only)
- #
- .mbar add cascade -label Apple -menu .mbar.apple
- menu .mbar.apple
-
- .mbar.apple add command -label [mc "About %s" [appname]] \
- -command do_about
- .mbar.apple add separator
- .mbar.apple add command \
- -label [mc "Preferences..."] \
- -command do_options \
- -accelerator $M1T-,
- bind . <$M1B-,> do_options
+ proc ::tk::mac::ShowPreferences {} {do_options}
} else {
# -- Edit Menu
#
@@ -2585,17 +2605,23 @@ if {[is_enabled multicommit] || [is_enabled singlecommit]} {
.mbar add cascade -label [mc Help] -menu .mbar.help
menu .mbar.help
-if {![is_MacOSX]} {
+if {[is_MacOSX]} {
+ .mbar.apple add command -label [mc "About %s" [appname]] \
+ -command do_about
+ .mbar.apple add separator
+} else {
.mbar.help add command -label [mc "About %s" [appname]] \
-command do_about
}
+. configure -menu .mbar
+set doc_path [githtmldir]
+if {$doc_path ne {}} {
+ set doc_path [file join $doc_path index.html]
-set doc_path [file dirname [gitexec]]
-set doc_path [file join $doc_path Documentation index.html]
-
-if {[is_Cygwin]} {
- set doc_path [exec cygpath --mixed $doc_path]
+ if {[is_Cygwin]} {
+ set doc_path [exec cygpath --mixed $doc_path]
+ }
}
if {[file isfile $doc_path]} {
@@ -2944,7 +2970,7 @@ $ctxm add command \
-command {tk_textPaste $ui_comm}
$ctxm add command \
-label [mc Delete] \
- -command {$ui_comm delete sel.first sel.last}
+ -command {catch {$ui_comm delete sel.first sel.last}}
$ctxm add separator
$ctxm add command \
-label [mc "Select All"] \
diff --git a/git-gui/lib/branch_delete.tcl b/git-gui/lib/branch_delete.tcl
index ef1930b..20d5e42 100644
--- a/git-gui/lib/branch_delete.tcl
+++ b/git-gui/lib/branch_delete.tcl
@@ -51,7 +51,7 @@ constructor dialog {} {
$w.check \
[mc "Delete Only If Merged Into"] \
]
- $w_check none [mc "Always (Do not perform merge test.)"]
+ $w_check none [mc "Always (Do not perform merge checks)"]
pack $w.check -anchor nw -fill x -pady 5 -padx 5
foreach h [load_all_heads] {
@@ -112,7 +112,7 @@ method _delete {} {
}
if {$to_delete eq {}} return
if {$check_cmt eq {}} {
- set msg [mc "Recovering deleted branches is difficult. \n\n Delete the selected branches?"]
+ set msg [mc "Recovering deleted branches is difficult.\n\nDelete the selected branches?"]
if {[tk_messageBox \
-icon warning \
-type yesno \
diff --git a/git-gui/lib/checkout_op.tcl b/git-gui/lib/checkout_op.tcl
index caca888..9e7412c 100644
--- a/git-gui/lib/checkout_op.tcl
+++ b/git-gui/lib/checkout_op.tcl
@@ -9,6 +9,7 @@ field w_cons {}; # embedded console window object
field new_expr ; # expression the user saw/thinks this is
field new_hash ; # commit SHA-1 we are switching to
field new_ref ; # ref we are updating/creating
+field old_hash ; # commit SHA-1 that was checked out when we started
field parent_w .; # window that started us
field merge_type none; # type of merge to apply to existing branch
@@ -280,11 +281,11 @@ method _start_checkout {} {
# -- Our in memory state should match the repository.
#
- repository_state curType curHEAD curMERGE_HEAD
+ repository_state curType old_hash curMERGE_HEAD
if {[string match amend* $commit_type]
&& $curType eq {normal}
- && $curHEAD eq $HEAD} {
- } elseif {$commit_type ne $curType || $HEAD ne $curHEAD} {
+ && $old_hash eq $HEAD} {
+ } elseif {$commit_type ne $curType || $HEAD ne $old_hash} {
info_popup [mc "Last scanned state does not match repository state.
Another Git program has modified this repository since the last scan. A rescan must be performed before the current branch can be changed.
@@ -297,7 +298,7 @@ The rescan will be automatically started now.
return
}
- if {$curHEAD eq $new_hash} {
+ if {$old_hash eq $new_hash} {
_after_readtree $this
} elseif {[is_config_true gui.trustmtime]} {
_readtree $this
@@ -453,13 +454,47 @@ method _after_readtree {} {
If you wanted to be on a branch, create one now starting from 'This Detached Checkout'."]
}
+ # -- Run the post-checkout hook.
+ #
+ set fd_ph [githook_read post-checkout $old_hash $new_hash 1]
+ if {$fd_ph ne {}} {
+ global pch_error
+ set pch_error {}
+ fconfigure $fd_ph -blocking 0 -translation binary -eofchar {}
+ fileevent $fd_ph readable [cb _postcheckout_wait $fd_ph]
+ } else {
+ _update_repo_state $this
+ }
+}
+
+method _postcheckout_wait {fd_ph} {
+ global pch_error
+
+ append pch_error [read $fd_ph]
+ fconfigure $fd_ph -blocking 1
+ if {[eof $fd_ph]} {
+ if {[catch {close $fd_ph}]} {
+ hook_failed_popup post-checkout $pch_error 0
+ }
+ unset pch_error
+ _update_repo_state $this
+ return
+ }
+ fconfigure $fd_ph -blocking 0
+}
+
+method _update_repo_state {} {
# -- Update our repository state. If we were previously in
# amend mode we need to toss the current buffer and do a
# full rescan to update our file lists. If we weren't in
# amend mode our file lists are accurate and we can avoid
# the rescan.
#
+ global selected_commit_type commit_type HEAD MERGE_HEAD PARENT
+ global ui_comm
+
unlock_index
+ set name [_name $this]
set selected_commit_type new
if {[string match amend* $commit_type]} {
$ui_comm delete 0.0 end
diff --git a/git-gui/lib/choose_repository.tcl b/git-gui/lib/choose_repository.tcl
index f9ff62a..633cc57 100644
--- a/git-gui/lib/choose_repository.tcl
+++ b/git-gui/lib/choose_repository.tcl
@@ -398,6 +398,8 @@ method _do_new {} {
grid $w_body.where.l $w_body.where.t $w_body.where.b -sticky ew
pack $w_body.where -fill x
+ grid columnconfigure $w_body.where 1 -weight 1
+
trace add variable @local_path write [cb _write_local_path]
bind $w_body.h <Destroy> [list trace remove variable @local_path write [cb _write_local_path]]
update
@@ -964,7 +966,34 @@ method _readtree_wait {fd} {
return
}
- set done 1
+ # -- Run the post-checkout hook.
+ #
+ set fd_ph [githook_read post-checkout [string repeat 0 40] \
+ [git rev-parse HEAD] 1]
+ if {$fd_ph ne {}} {
+ global pch_error
+ set pch_error {}
+ fconfigure $fd_ph -blocking 0 -translation binary -eofchar {}
+ fileevent $fd_ph readable [cb _postcheckout_wait $fd_ph]
+ } else {
+ set done 1
+ }
+}
+
+method _postcheckout_wait {fd_ph} {
+ global pch_error
+
+ append pch_error [read $fd_ph]
+ fconfigure $fd_ph -blocking 1
+ if {[eof $fd_ph]} {
+ if {[catch {close $fd_ph}]} {
+ hook_failed_popup post-checkout $pch_error 0
+ }
+ unset pch_error
+ set done 1
+ return
+ }
+ fconfigure $fd_ph -blocking 0
}
######################################################################
@@ -998,6 +1027,8 @@ method _do_open {} {
grid $w_body.where.l $w_body.where.t $w_body.where.b -sticky ew
pack $w_body.where -fill x
+ grid columnconfigure $w_body.where 1 -weight 1
+
trace add variable @local_path write [cb _write_local_path]
bind $w_body.h <Destroy> [list trace remove variable @local_path write [cb _write_local_path]]
update
diff --git a/git-gui/lib/commit.tcl b/git-gui/lib/commit.tcl
index 9cc8410..7f459cd 100644
--- a/git-gui/lib/commit.tcl
+++ b/git-gui/lib/commit.tcl
@@ -115,6 +115,23 @@ proc create_new_commit {} {
rescan ui_ready
}
+proc setup_commit_encoding {msg_wt {quiet 0}} {
+ global repo_config
+
+ if {[catch {set enc $repo_config(i18n.commitencoding)}]} {
+ set enc utf-8
+ }
+ set use_enc [tcl_encoding $enc]
+ if {$use_enc ne {}} {
+ fconfigure $msg_wt -encoding $use_enc
+ } else {
+ if {!$quiet} {
+ error_popup [mc "warning: Tcl does not support encoding '%s'." $enc]
+ }
+ fconfigure $msg_wt -encoding utf-8
+ }
+}
+
proc commit_tree {} {
global HEAD commit_type file_states ui_comm repo_config
global pch_error
@@ -200,16 +217,7 @@ A good commit message has the following format:
set msg_p [gitdir GITGUI_EDITMSG]
set msg_wt [open $msg_p w]
fconfigure $msg_wt -translation lf
- if {[catch {set enc $repo_config(i18n.commitencoding)}]} {
- set enc utf-8
- }
- set use_enc [tcl_encoding $enc]
- if {$use_enc ne {}} {
- fconfigure $msg_wt -encoding $use_enc
- } else {
- error_popup [mc "warning: Tcl does not support encoding '%s'." $enc]
- fconfigure $msg_wt -encoding utf-8
- }
+ setup_commit_encoding $msg_wt
puts $msg_wt $msg
close $msg_wt
@@ -362,6 +370,7 @@ A rescan will be automatically started now.
append reflogm " ($commit_type)"
}
set msg_fd [open $msg_p r]
+ setup_commit_encoding $msg_fd 1
gets $msg_fd subject
close $msg_fd
append reflogm {: } $subject
@@ -398,8 +407,8 @@ A rescan will be automatically started now.
#
set fd_ph [githook_read post-commit]
if {$fd_ph ne {}} {
- upvar #0 pch_error$cmt_id pc_err
- set pc_err {}
+ global pch_error
+ set pch_error {}
fconfigure $fd_ph -blocking 0 -translation binary -eofchar {}
fileevent $fd_ph readable \
[list commit_postcommit_wait $fd_ph $cmt_id]
@@ -461,7 +470,7 @@ A rescan will be automatically started now.
}
proc commit_postcommit_wait {fd_ph cmt_id} {
- upvar #0 pch_error$cmt_id pch_error
+ global pch_error
append pch_error [read $fd_ph]
fconfigure $fd_ph -blocking 1
diff --git a/git-gui/lib/diff.tcl b/git-gui/lib/diff.tcl
index bbbf15c..925b3f5 100644
--- a/git-gui/lib/diff.tcl
+++ b/git-gui/lib/diff.tcl
@@ -51,11 +51,16 @@ proc force_diff_encoding {enc} {
proc handle_empty_diff {} {
global current_diff_path file_states file_lists
+ global diff_empty_count
set path $current_diff_path
set s $file_states($path)
if {[lindex $s 0] ne {_M}} return
+ # Prevent infinite rescan loops
+ incr diff_empty_count
+ if {$diff_empty_count > 1} return
+
info_popup [mc "No differences detected.
%s has no changes.
@@ -310,6 +315,7 @@ proc read_diff {fd cont_info} {
global ui_diff diff_active
global is_3way_diff is_conflict_diff current_diff_header
global current_diff_queue
+ global diff_empty_count
$ui_diff conf -state normal
while {[gets $fd line] >= 0} {
@@ -415,7 +421,10 @@ proc read_diff {fd cont_info} {
if {[$ui_diff index end] eq {2.0}} {
handle_empty_diff
+ } else {
+ set diff_empty_count 0
}
+
set callback [lindex $cont_info 1]
if {$callback ne {}} {
eval $callback
diff --git a/git-gui/lib/mergetool.tcl b/git-gui/lib/mergetool.tcl
index eb2b4b5..3fe90e6 100644
--- a/git-gui/lib/mergetool.tcl
+++ b/git-gui/lib/mergetool.tcl
@@ -88,7 +88,7 @@ proc merge_load_stages {path cont} {
set merge_stages(3) {}
set merge_stages_buf {}
- set merge_stages_fd [eval git_read ls-files -u -z -- $path]
+ set merge_stages_fd [eval git_read ls-files -u -z -- {$path}]
fconfigure $merge_stages_fd -blocking 0 -translation binary -encoding binary
fileevent $merge_stages_fd readable [list read_merge_stages $merge_stages_fd $cont]
@@ -382,7 +382,7 @@ proc merge_tool_finish {fd} {
delete_temp_files $mtool_tmpfiles
ui_status [mc "Merge tool failed."]
} else {
- if {[is_config_true merge.keepbackup]} {
+ if {[is_config_true mergetool.keepbackup]} {
file rename -force -- $backup "$mtool_target.orig"
}
diff --git a/git-gui/lib/remote_branch_delete.tcl b/git-gui/lib/remote_branch_delete.tcl
index 89eb0f7..4e02fc0 100644
--- a/git-gui/lib/remote_branch_delete.tcl
+++ b/git-gui/lib/remote_branch_delete.tcl
@@ -213,9 +213,7 @@ method _delete {} {
-type yesno \
-title [wm title $w] \
-parent $w \
- -message [mc "Recovering deleted branches is difficult.
-
-Delete the selected branches?"]] ne yes} {
+ -message [mc "Recovering deleted branches is difficult.\n\nDelete the selected branches?"]] ne yes} {
return
}
diff --git a/git-gui/lib/shortcut.tcl b/git-gui/lib/shortcut.tcl
index 38c3151..2f20eb3 100644
--- a/git-gui/lib/shortcut.tcl
+++ b/git-gui/lib/shortcut.tcl
@@ -54,7 +54,7 @@ proc do_cygwin_shortcut {} {
$argv0]
win32_create_lnk $fn [list \
$sh -c \
- "CHERE_INVOKING=1 source /etc/profile;[sq $me]" \
+ "CHERE_INVOKING=1 source /etc/profile;[sq $me] &" \
] \
[file dirname [file normalize [gitdir]]]
} err]} {
diff --git a/git-gui/lib/tools.tcl b/git-gui/lib/tools.tcl
index 6ae63b6..95e6e55 100644
--- a/git-gui/lib/tools.tcl
+++ b/git-gui/lib/tools.tcl
@@ -146,7 +146,7 @@ proc tools_complete {fullname w {ok 1}} {
}
if {$ok} {
- set msg [mc "Tool completed succesfully: %s" $fullname]
+ set msg [mc "Tool completed successfully: %s" $fullname]
} else {
set msg [mc "Tool failed: %s" $fullname]
}
diff --git a/git-gui/po/de.po b/git-gui/po/de.po
index a6f730b..51abb50 100644
--- a/git-gui/po/de.po
+++ b/git-gui/po/de.po
@@ -773,16 +773,6 @@ msgstr "Immer (ohne Zusammenführungstest)"
msgid "The following branches are not completely merged into %s:"
msgstr "Folgende Zweige sind noch nicht mit »%s« zusammengeführt:"
-#: lib/branch_delete.tcl:115
-msgid ""
-"Recovering deleted branches is difficult. \n"
-"\n"
-" Delete the selected branches?"
-msgstr ""
-"Gelöschte Zweige können nur mit größerem Aufwand wiederhergestellt werden.\n"
-"\n"
-"Gewählte Zweige jetzt löschen?"
-
#: lib/branch_delete.tcl:141
#, tcl-format
msgid ""
@@ -2506,7 +2496,7 @@ msgstr "Starten: %s"
#: lib/tools.tcl:149
#, tcl-format
-msgid "Tool completed succesfully: %s"
+msgid "Tool completed successfully: %s"
msgstr "Werkzeug erfolgreich abgeschlossen: %s"
#: lib/tools.tcl:151
diff --git a/git-gui/po/fr.po b/git-gui/po/fr.po
index 45773ab..a944ace 100644
--- a/git-gui/po/fr.po
+++ b/git-gui/po/fr.po
@@ -62,7 +62,7 @@ msgstr ""
"\n"
"%s nécessite au moins Git 1.5.0.\n"
"\n"
-"Peut'on considérer que '%s' est en version 1.5.0 ?\n"
+"Peut-on considérer que '%s' est en version 1.5.0 ?\n"
#: git-gui.sh:1062
msgid "Git directory not found:"
@@ -82,7 +82,7 @@ msgstr "Aucun répertoire de travail"
#: git-gui.sh:1247 lib/checkout_op.tcl:305
msgid "Refreshing file status..."
-msgstr "Rafraichissement du status des fichiers..."
+msgstr "Rafraîchissement du statut des fichiers..."
#: git-gui.sh:1303
msgid "Scanning for modified files ..."
@@ -163,7 +163,7 @@ msgstr "Dépôt"
#: git-gui.sh:2281
msgid "Edit"
-msgstr "Edition"
+msgstr "Édition"
#: git-gui.sh:2283 lib/choose_rev.tcl:561
msgid "Branch"
@@ -199,7 +199,7 @@ msgstr "Naviguer dans la branche..."
#: git-gui.sh:2316
msgid "Visualize Current Branch's History"
-msgstr "Visualiser historique branche courante"
+msgstr "Visualiser l'historique de la branche courante"
#: git-gui.sh:2320
msgid "Visualize All Branch History"
@@ -208,12 +208,12 @@ msgstr "Voir l'historique de toutes les branches"
#: git-gui.sh:2327
#, tcl-format
msgid "Browse %s's Files"
-msgstr "Naviguer l'arborescence de %s"
+msgstr "Parcourir l'arborescence de %s"
#: git-gui.sh:2329
#, tcl-format
msgid "Visualize %s's History"
-msgstr "Voir l'historique de la branche: %s"
+msgstr "Voir l'historique de la branche : %s"
#: git-gui.sh:2334 lib/database.tcl:27 lib/database.tcl:67
msgid "Database Statistics"
@@ -230,7 +230,7 @@ msgstr "Vérifier le dépôt"
#: 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"
+msgstr "Créer une icône sur le bureau"
#: git-gui.sh:2363 lib/choose_repository.tcl:183 lib/choose_repository.tcl:191
msgid "Quit"
@@ -320,7 +320,7 @@ msgstr "Désindexer"
#: git-gui.sh:2484 lib/index.tcl:410
msgid "Revert Changes"
-msgstr "Annuler les modifications (revert)"
+msgstr "Annuler les modifications"
#: git-gui.sh:2491 git-gui.sh:3069
msgid "Show Less Context"
@@ -382,7 +382,7 @@ msgstr "Documentation en ligne"
#: git-gui.sh:2614 lib/choose_repository.tcl:47 lib/choose_repository.tcl:56
msgid "Show SSH Key"
-msgstr "Montrer clé SSH"
+msgstr "Montrer la clé SSH"
#: git-gui.sh:2707
#, tcl-format
@@ -445,7 +445,7 @@ msgstr "Fichier :"
#: git-gui.sh:3078
msgid "Refresh"
-msgstr "Rafraichir"
+msgstr "Rafraîchir"
#: git-gui.sh:3099
msgid "Decrease Font Size"
@@ -457,7 +457,7 @@ msgstr "Agrandir la police"
#: git-gui.sh:3111 lib/blame.tcl:281
msgid "Encoding"
-msgstr "Encodage"
+msgstr "Codage des caractères"
#: git-gui.sh:3122
msgid "Apply/Reverse Hunk"
@@ -469,7 +469,7 @@ msgstr "Appliquer/Inverser la ligne"
#: git-gui.sh:3137
msgid "Run Merge Tool"
-msgstr "Lancer outil de merge"
+msgstr "Lancer l'outil de fusion"
#: git-gui.sh:3142
msgid "Use Remote Version"
@@ -527,7 +527,7 @@ msgid ""
"Tcl binary distributed by Cygwin."
msgstr ""
"\n"
-"Ceci est du à un problème connu avec\n"
+"Ceci est dû à un problème connu avec\n"
"le binaire Tcl distribué par Cygwin."
#: git-gui.sh:3336
@@ -630,11 +630,11 @@ msgstr "Fichier original :"
#: lib/blame.tcl:1021
msgid "Cannot find HEAD commit:"
-msgstr "Impossible de trouver le commit HEAD:"
+msgstr "Impossible de trouver le commit HEAD :"
#: lib/blame.tcl:1076
msgid "Cannot find parent commit:"
-msgstr "Impossible de trouver le commit parent:"
+msgstr "Impossible de trouver le commit parent :"
#: lib/blame.tcl:1091
msgid "Unable to display parent"
@@ -646,7 +646,7 @@ msgstr "Erreur lors du chargement des différences :"
#: lib/blame.tcl:1232
msgid "Originally By:"
-msgstr "A l'origine par :"
+msgstr "À l'origine par :"
#: lib/blame.tcl:1238
msgid "In File:"
@@ -691,11 +691,11 @@ msgstr "Détacher de la branche locale"
#: lib/branch_create.tcl:22
msgid "Create Branch"
-msgstr "Créer branche"
+msgstr "Créer une branche"
#: lib/branch_create.tcl:27
msgid "Create New Branch"
-msgstr "Créer nouvelle branche"
+msgstr "Créer une nouvelle branche"
#: lib/branch_create.tcl:31 lib/choose_repository.tcl:377
msgid "Create"
@@ -719,7 +719,7 @@ msgstr "Révision initiale"
#: lib/branch_create.tcl:72
msgid "Update Existing Branch:"
-msgstr "Mettre à jour branche existante :"
+msgstr "Mettre à jour une branche existante :"
#: lib/branch_create.tcl:75
msgid "No"
@@ -727,7 +727,7 @@ msgstr "Non"
#: lib/branch_create.tcl:80
msgid "Fast Forward Only"
-msgstr "Mise-à-jour rectiligne seulement (fast-forward)"
+msgstr "Mise à jour rectiligne seulement (fast-forward)"
#: lib/branch_create.tcl:85 lib/checkout_op.tcl:536
msgid "Reset"
@@ -769,7 +769,7 @@ msgstr "Branches locales"
#: lib/branch_delete.tcl:52
msgid "Delete Only If Merged Into"
-msgstr "Supprimer seulement si fusionnée dans:"
+msgstr "Supprimer seulement si fusionnée dans :"
#: lib/branch_delete.tcl:54
msgid "Always (Do not perform merge test.)"
@@ -780,23 +780,13 @@ msgstr "Toujours (Ne pas faire de test de fusion.)"
msgid "The following branches are not completely merged into %s:"
msgstr "Les branches suivantes ne sont pas complètement fusionnées dans %s :"
-#: lib/branch_delete.tcl:115
-msgid ""
-"Recovering deleted branches is difficult. \n"
-"\n"
-" Delete the selected branches?"
-msgstr ""
-"Récupérer des branches supprimées est difficile.\n"
-"\n"
-"Supprimer les branches sélectionnées ?"
-
#: lib/branch_delete.tcl:141
#, tcl-format
msgid ""
"Failed to delete branches:\n"
"%s"
msgstr ""
-"La suppression des branches suivantes a échouée :\n"
+"La suppression des branches suivantes a échoué :\n"
"%s"
#: lib/branch_rename.tcl:14 lib/branch_rename.tcl:22
@@ -902,11 +892,11 @@ msgstr "La stratégie de fusion '%s' n'est pas supportée."
#: lib/checkout_op.tcl:261
#, tcl-format
msgid "Failed to update '%s'."
-msgstr "La mise à jour de '%s' a échouée."
+msgstr "La mise à jour de '%s' a échoué."
#: lib/checkout_op.tcl:273
msgid "Staging area (index) is already locked."
-msgstr "L'index (staging area) est déjà vérouillé"
+msgstr "L'index (staging area) est déjà verrouillé."
#: lib/checkout_op.tcl:288
msgid ""
@@ -918,7 +908,7 @@ msgid ""
"The rescan will be automatically started now.\n"
msgstr ""
"L'état lors de la dernière synchronisation ne correspond plus à l'état du "
-"dépôt\n"
+"dépôt.\n"
"\n"
"Un autre programme Git a modifié ce dépôt depuis la dernière "
"synchronisation. Une resynchronisation doit être effectuée avant de pouvoir "
@@ -956,9 +946,9 @@ msgid ""
"If you wanted to be on a branch, create one now starting from 'This Detached "
"Checkout'."
msgstr ""
-"Vous n'êtes plus ur une branche locale.\n"
+"Vous n'êtes plus sur une branche locale.\n"
"\n"
-"Si vous vouliez être sur une branche, créez en une maintenant en partant de "
+"Si vous vouliez être sur une branche, créez-en une maintenant en partant de "
"'Cet emprunt détaché'."
#: lib/checkout_op.tcl:468 lib/checkout_op.tcl:472
@@ -1000,7 +990,7 @@ msgstr ""
"mis à jour avec succès, mais la mise à jour d'un fichier interne à Git a "
"échouée.\n"
"\n"
-"Cela n'aurait pas du se produire. %s va abandonner et se terminer."
+"Cela n'aurait pas dû se produire. %s va abandonner et se terminer."
#: lib/choose_font.tcl:39
msgid "Select"
@@ -1023,8 +1013,8 @@ msgid ""
"This is example text.\n"
"If you like this text, it can be your font."
msgstr ""
-"C'est un texte d'exemple.\n"
-"Si vous aimez ce texte, vous pouvez choisir cette police"
+"Ceci est un texte d'exemple.\n"
+"Si vous aimez ce texte, vous pouvez choisir cette police."
#: lib/choose_repository.tcl:28
msgid "Git Gui"
@@ -1040,7 +1030,7 @@ msgstr "Nouveau..."
#: lib/choose_repository.tcl:100 lib/choose_repository.tcl:465
msgid "Clone Existing Repository"
-msgstr "Cloner dépôt existant"
+msgstr "Cloner un dépôt existant"
#: lib/choose_repository.tcl:106
msgid "Clone..."
@@ -1048,7 +1038,7 @@ msgstr "Cloner..."
#: lib/choose_repository.tcl:113 lib/choose_repository.tcl:983
msgid "Open Existing Repository"
-msgstr "Ouvrir dépôt existant"
+msgstr "Ouvrir un dépôt existant"
#: lib/choose_repository.tcl:119
msgid "Open..."
@@ -1056,17 +1046,17 @@ msgstr "Ouvrir..."
#: lib/choose_repository.tcl:132
msgid "Recent Repositories"
-msgstr "Dépôt récemment utilisés"
+msgstr "Dépôts récemment utilisés"
#: lib/choose_repository.tcl:138
msgid "Open Recent Repository:"
-msgstr "Ouvrir dépôt récent :"
+msgstr "Ouvrir un dépôt récent :"
#: 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 :"
+msgstr "La création du dépôt %s a échoué :"
#: lib/choose_repository.tcl:387
msgid "Directory:"
@@ -1093,11 +1083,11 @@ msgstr "Cloner"
#: lib/choose_repository.tcl:473
msgid "Source Location:"
-msgstr "Emplacement source:"
+msgstr "Emplacement source :"
#: lib/choose_repository.tcl:484
msgid "Target Directory:"
-msgstr "Répertoire cible:"
+msgstr "Répertoire cible :"
#: lib/choose_repository.tcl:496
msgid "Clone Type:"
@@ -1137,7 +1127,7 @@ msgstr "L'emplacement %s existe déjà."
#: lib/choose_repository.tcl:622
msgid "Failed to configure origin"
-msgstr "La configuration de l'origine a échouée."
+msgstr "La configuration de l'origine a échoué."
#: lib/choose_repository.tcl:634
msgid "Counting objects"
@@ -1242,7 +1232,7 @@ msgstr "fichiers"
#: lib/choose_repository.tcl:962
msgid "Initial file checkout failed."
-msgstr "Chargement initial du fichier échoué."
+msgstr "Le chargement initial du fichier a échoué."
#: lib/choose_repository.tcl:978
msgid "Open"
@@ -1284,7 +1274,7 @@ msgstr "Révision invalide : %s"
#: lib/choose_rev.tcl:338
msgid "No revision selected."
-msgstr "Pas de révision selectionnée."
+msgstr "Pas de révision sélectionnée."
#: lib/choose_rev.tcl:346
msgid "Revision expression is empty."
@@ -1292,7 +1282,7 @@ msgstr "L'expression de révision est vide."
#: lib/choose_rev.tcl:531
msgid "Updated"
-msgstr "Mise-à-jour:"
+msgstr "Mise à jour:"
#: lib/choose_rev.tcl:559
msgid "URL"
@@ -1320,8 +1310,8 @@ msgid ""
msgstr ""
"Impossible de corriger pendant une fusion.\n"
"\n"
-"Vous êtes actuellement au milieu d'une fusion qui n'a pas été completement "
-"terminée. Vous ne pouvez pas corriger le commit précédant sauf si vous "
+"Vous êtes actuellement au milieu d'une fusion qui n'a pas été complètement "
+"terminée. Vous ne pouvez pas corriger le commit précédent sauf si vous "
"abandonnez la fusion courante.\n"
#: lib/commit.tcl:49
@@ -1409,7 +1399,7 @@ msgstr ""
#: lib/commit.tcl:211
#, tcl-format
msgid "warning: Tcl does not support encoding '%s'."
-msgstr "attention : Tcl ne supporte pas l'encodage '%s'."
+msgstr "attention : Tcl ne supporte pas le codage '%s'."
#: lib/commit.tcl:227
msgid "Calling pre-commit hook..."
@@ -1469,12 +1459,12 @@ msgstr "commit-tree a échoué :"
#: lib/commit.tcl:373
msgid "update-ref failed:"
-msgstr "update-ref a échoué"
+msgstr "update-ref a échoué :"
#: lib/commit.tcl:461
#, tcl-format
msgid "Created commit %s: %s"
-msgstr "Commit créé %s : %s"
+msgstr "Commit %s créé : %s"
#: lib/console.tcl:59
msgid "Working... please wait..."
@@ -1581,24 +1571,24 @@ msgid ""
"LOCAL: deleted\n"
"REMOTE:\n"
msgstr ""
-"LOCAL: supprimé\n"
-"DISTANT:\n"
+"LOCAL : supprimé\n"
+"DISTANT :\n"
#: lib/diff.tcl:125
msgid ""
"REMOTE: deleted\n"
"LOCAL:\n"
msgstr ""
-"DISTANT: supprimé\n"
-"LOCAL:\n"
+"DISTANT : supprimé\n"
+"LOCAL :\n"
#: lib/diff.tcl:132
msgid "LOCAL:\n"
-msgstr "LOCAL:\n"
+msgstr "LOCAL :\n"
#: lib/diff.tcl:135
msgid "REMOTE:\n"
-msgstr "DISTANT:\n"
+msgstr "DISTANT :\n"
#: lib/diff.tcl:197 lib/diff.tcl:296
#, tcl-format
@@ -1624,7 +1614,7 @@ msgid ""
"* Showing only first %d bytes.\n"
msgstr ""
"* Le fichier non suivi fait %d octets.\n"
-"* On montre seulement les premiers %d octets.\n"
+"* Seuls les %d premiers octets sont montrés.\n"
#: lib/diff.tcl:228
#, tcl-format
@@ -1635,7 +1625,7 @@ msgid ""
msgstr ""
"\n"
"* Fichier suivi raccourcis ici de %s.\n"
-"* Pour voir le fichier entier, utiliser un éditeur externe.\n"
+"* Pour voir le fichier entier, utilisez un éditeur externe.\n"
#: lib/diff.tcl:436
msgid "Failed to unstage selected hunk."
@@ -1680,7 +1670,7 @@ msgstr "Vous devez corriger les erreurs suivantes avant de pouvoir commiter."
#: lib/index.tcl:6
msgid "Unable to unlock the index."
-msgstr "Impossible de dévérouiller l'index."
+msgstr "Impossible de déverrouiller l'index."
#: lib/index.tcl:15
msgid "Index Error"
@@ -1700,12 +1690,12 @@ msgstr "Continuer"
#: lib/index.tcl:31
msgid "Unlock Index"
-msgstr "Déverouiller l'index"
+msgstr "Déverrouiller l'index"
#: lib/index.tcl:287
#, tcl-format
msgid "Unstaging %s from commit"
-msgstr "Désindexation de: %s"
+msgstr "Désindexation de : %s"
#: lib/index.tcl:326
msgid "Ready to commit."
@@ -1804,11 +1794,11 @@ msgid ""
msgstr ""
"Vous êtes au milieu d'une modification.\n"
"\n"
-"Le fichier %s est modifié.\n"
+"Le fichier %s a été modifié.\n"
"\n"
"Vous devriez terminer le commit courant avant de lancer une fusion. En "
"faisait comme cela, vous éviterez de devoir éventuellement abandonner une "
-"fusion ayant échouée.\n"
+"fusion ayant échoué.\n"
#: lib/merge.tcl:107
#, tcl-format
@@ -1826,7 +1816,7 @@ msgstr "La fusion s'est faite avec succès."
#: 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."
+msgstr "La fusion a echoué. Il est nécessaire de résoudre les conflits."
#: lib/merge.tcl:158
#, tcl-format
@@ -1914,16 +1904,16 @@ msgid ""
"\n"
"This operation can be undone only by restarting the merge."
msgstr ""
-"Noter que le diff ne montre que les modifications en conflict.\n"
+"Noter que le diff ne montre que les modifications en conflit.\n"
"\n"
"%s sera écrasé.\n"
"\n"
-"Cette opération ne peut être défaite qu'en relançant la fusion."
+"Cette opération ne peut être inversée 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 ?"
+msgstr "Le fichier %s semble avoir des conflits non résolus, indexer quand même ?"
#: lib/mergetool.tcl:60
#, tcl-format
@@ -1932,11 +1922,11 @@ 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"
+msgstr "Impossible de résoudre la suppression ou de relier des conflits en utilisant un outil"
#: lib/mergetool.tcl:146
msgid "Conflict file does not exist"
-msgstr "Le fichier en conflict n'existe pas."
+msgstr "Le fichier en conflit n'existe pas."
#: lib/mergetool.tcl:264
#, tcl-format
@@ -1958,7 +1948,7 @@ msgid ""
"Error retrieving versions:\n"
"%s"
msgstr ""
-"Erreur lors de la récupération des versions:\n"
+"Erreur lors de la récupération des versions :\n"
"%s"
#: lib/mergetool.tcl:343
@@ -1968,7 +1958,7 @@ msgid ""
"\n"
"%s"
msgstr ""
-"Impossible de lancer l'outil de fusion:\n"
+"Impossible de lancer l'outil de fusion :\n"
"\n"
"%s"
@@ -1983,12 +1973,12 @@ msgstr "L'outil de fusion a échoué."
#: lib/option.tcl:11
#, tcl-format
msgid "Invalid global encoding '%s'"
-msgstr "Encodage global invalide '%s'"
+msgstr "Codage global '%s' invalide"
#: lib/option.tcl:19
#, tcl-format
msgid "Invalid repo encoding '%s'"
-msgstr "Encodage de dépôt invalide '%s'"
+msgstr "Codage de dépôt '%s' invalide"
#: lib/option.tcl:117
msgid "Restore Defaults"
@@ -2001,7 +1991,7 @@ msgstr "Sauvegarder"
#: lib/option.tcl:131
#, tcl-format
msgid "%s Repository"
-msgstr "Dépôt: %s"
+msgstr "Dépôt : %s"
#: lib/option.tcl:132
msgid "Global (All Repositories)"
@@ -2069,7 +2059,7 @@ msgstr "Nouveau modèle de nom de branche"
#: lib/option.tcl:155
msgid "Default File Contents Encoding"
-msgstr "Encodage du contenu des fichiers par défaut"
+msgstr "Codage du contenu des fichiers par défaut"
#: lib/option.tcl:203
msgid "Change"
@@ -2098,11 +2088,11 @@ msgstr "Préférences"
#: lib/option.tcl:314
msgid "Failed to completely save options:"
-msgstr "La sauvegarde complète des options a échouée :"
+msgstr "La sauvegarde complète des options a échoué :"
#: lib/remote.tcl:163
msgid "Remove Remote"
-msgstr "Supprimer dépôt distant"
+msgstr "Supprimer un dépôt distant"
#: lib/remote.tcl:168
msgid "Prune from"
@@ -2118,11 +2108,11 @@ msgstr "Pousser vers"
#: lib/remote_add.tcl:19
msgid "Add Remote"
-msgstr "Ajouter dépôt distant"
+msgstr "Ajouter un dépôt distant"
#: lib/remote_add.tcl:24
msgid "Add New Remote"
-msgstr "Ajouter nouveau dépôt distant"
+msgstr "Ajouter un nouveau dépôt distant"
#: lib/remote_add.tcl:28 lib/tools_dlg.tcl:36
msgid "Add"
@@ -2134,7 +2124,7 @@ msgstr "Détails des dépôts distants"
#: lib/remote_add.tcl:50
msgid "Location:"
-msgstr "Emplacement:"
+msgstr "Emplacement :"
#: lib/remote_add.tcl:62
msgid "Further Action"
@@ -2146,7 +2136,7 @@ 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"
+msgstr "Initialiser un dépôt distant et pousser"
#: lib/remote_add.tcl:77
msgid "Do Nothing Else Now"
@@ -2193,7 +2183,7 @@ msgstr "Mise en place de %s (à %s)"
#: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34
msgid "Delete Branch Remotely"
-msgstr "Supprimer branche à distance"
+msgstr "Supprimer une branche à distance"
#: lib/remote_branch_delete.tcl:47
msgid "From Repository"
@@ -2244,8 +2234,8 @@ msgid ""
"One or more of the merge tests failed because you have not fetched the "
"necessary commits. Try fetching from %s first."
msgstr ""
-"Une ou plusieurs des tests de fusion ont échoués parce que vous n'avez pas "
-"récupéré les commits nécessaires. Essayez de récupéré à partir de %s d'abord."
+"Un ou plusieurs des tests de fusion ont échoué parce que vous n'avez pas "
+"récupéré les commits nécessaires. Essayez de récupérer à partir de %s d'abord."
#: lib/remote_branch_delete.tcl:207
msgid "Please select one or more branches to delete."
@@ -2257,14 +2247,14 @@ msgid ""
"\n"
"Delete the selected branches?"
msgstr ""
-"Récupérer des branches supprimées est difficile.\n"
+"Il est difficile de récupérer des branches supprimées.\n"
"\n"
-"Souhaitez vous supprimer les branches sélectionnées ?"
+"Supprimer les branches sélectionnées ?"
#: lib/remote_branch_delete.tcl:226
#, tcl-format
msgid "Deleting branches from %s"
-msgstr "Supprimer les branches de %s"
+msgstr "Suppression des branches de %s"
#: lib/remote_branch_delete.tcl:286
msgid "No repository selected."
@@ -2285,7 +2275,7 @@ msgstr "Suivant"
#: lib/search.tcl:24
msgid "Prev"
-msgstr "Précédant"
+msgstr "Précédent"
#: lib/search.tcl:25
msgid "Case-Sensitive"
@@ -2293,7 +2283,7 @@ msgstr "Sensible à la casse"
#: lib/shortcut.tcl:20 lib/shortcut.tcl:61
msgid "Cannot write shortcut:"
-msgstr "Impossible d'écrire le raccourcis :"
+msgstr "Impossible d'écrire le raccourci :"
#: lib/shortcut.tcl:136
msgid "Cannot write icon:"
@@ -2318,7 +2308,7 @@ msgstr "Réinitialisation du dictionnaire à %s."
#: lib/spellcheck.tcl:73
msgid "Spell checker silently failed on startup"
-msgstr "La vérification d'orthographe a échouée silentieusement au démarrage"
+msgstr "La vérification d'orthographe a échoué silencieusement au démarrage"
#: lib/spellcheck.tcl:80
msgid "Unrecognized spell checker"
@@ -2351,11 +2341,11 @@ msgstr "Générer une clé"
#: lib/sshkey.tcl:56
msgid "Copy To Clipboard"
-msgstr "Copier dans le presse papier"
+msgstr "Copier dans le presse-papier"
#: lib/sshkey.tcl:70
msgid "Your OpenSSH Public Key"
-msgstr "Votre clé publique Open SSH"
+msgstr "Votre clé publique OpenSSH"
#: lib/sshkey.tcl:78
msgid "Generating..."
@@ -2368,7 +2358,7 @@ msgid ""
"\n"
"%s"
msgstr ""
-"Impossible de lancer ssh-keygen:\n"
+"Impossible de lancer ssh-keygen :\n"
"\n"
"%s"
@@ -2398,7 +2388,7 @@ 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 ?"
+msgstr "Êtes-vous sûr de vouloir lancer %s ?"
#: lib/tools.tcl:110
#, tcl-format
@@ -2412,7 +2402,7 @@ msgstr "Lancement de : %s"
#: lib/tools.tcl:149
#, tcl-format
-msgid "Tool completed succesfully: %s"
+msgid "Tool completed successfully: %s"
msgstr "L'outil a terminé avec succès : %s"
#: lib/tools.tcl:151
@@ -2422,11 +2412,11 @@ msgstr "L'outil a échoué : %s"
#: lib/tools_dlg.tcl:22
msgid "Add Tool"
-msgstr "Ajouter outil"
+msgstr "Ajouter un outil"
#: lib/tools_dlg.tcl:28
msgid "Add New Tool Command"
-msgstr "Ajouter nouvelle commande d'outil"
+msgstr "Ajouter une nouvelle commande d'outil"
#: lib/tools_dlg.tcl:33
msgid "Add globally"
@@ -2438,7 +2428,7 @@ 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 :"
+msgstr "Utiliser les séparateurs '/' pour créer un arbre de sous-menus :"
#: lib/tools_dlg.tcl:61
msgid "Command:"
@@ -2462,7 +2452,7 @@ 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)"
+msgstr "Lancer seulement si un diff est sélectionné ($FILENAME non vide)"
#: lib/tools_dlg.tcl:121
msgid "Please supply a name for the tool."
@@ -2479,7 +2469,7 @@ msgid ""
"Could not add tool:\n"
"%s"
msgstr ""
-"Impossible d'ajouter l'outil:\n"
+"Impossible d'ajouter l'outil :\n"
"%s"
#: lib/tools_dlg.tcl:190
diff --git a/git-gui/po/git-gui.pot b/git-gui/po/git-gui.pot
index 15aea0d..53b7d36 100644
--- a/git-gui/po/git-gui.pot
+++ b/git-gui/po/git-gui.pot
@@ -753,13 +753,6 @@ msgstr ""
msgid "The following branches are not completely merged into %s:"
msgstr ""
-#: lib/branch_delete.tcl:115
-msgid ""
-"Recovering deleted branches is difficult. \n"
-"\n"
-" Delete the selected branches?"
-msgstr ""
-
#: lib/branch_delete.tcl:141
#, tcl-format
msgid ""
@@ -2220,7 +2213,7 @@ msgstr ""
#: lib/tools.tcl:149
#, tcl-format
-msgid "Tool completed succesfully: %s"
+msgid "Tool completed successfully: %s"
msgstr ""
#: lib/tools.tcl:151
diff --git a/git-gui/po/hu.po b/git-gui/po/hu.po
index f761b64..0f87bc1 100644
--- a/git-gui/po/hu.po
+++ b/git-gui/po/hu.po
@@ -776,16 +776,6 @@ msgstr "Mindig (Ne legyen merge teszt.)"
msgid "The following branches are not completely merged into %s:"
msgstr "A következő branchek nem teljesen lettek merge-ölve ebbe: %s:"
-#: lib/branch_delete.tcl:115
-msgid ""
-"Recovering deleted branches is difficult. \n"
-"\n"
-" Delete the selected branches?"
-msgstr ""
-"A törölt branchek visszaállítása bonyolult. \n"
-"\n"
-" Biztosan törli a kiválasztott brancheket?"
-
#: lib/branch_delete.tcl:141
#, tcl-format
msgid ""
@@ -2399,7 +2389,7 @@ msgstr "Futtatás: %s..."
#: lib/tools.tcl:149
#, tcl-format
-msgid "Tool completed succesfully: %s"
+msgid "Tool completed successfully: %s"
msgstr "Az eszköz sikeresen befejeződött: %s"
#: lib/tools.tcl:151
diff --git a/git-gui/po/it.po b/git-gui/po/it.po
index 294e595..762632c 100644
--- a/git-gui/po/it.po
+++ b/git-gui/po/it.po
@@ -778,16 +778,6 @@ msgstr "Sempre (Non effettuare verifiche di fusione)."
msgid "The following branches are not completely merged into %s:"
msgstr "I rami seguenti non sono stati fusi completamente in %s:"
-#: lib/branch_delete.tcl:115
-msgid ""
-"Recovering deleted branches is difficult. \n"
-"\n"
-" Delete the selected branches?"
-msgstr ""
-"Ricomporre rami cancellati può essere complicato. \n"
-"\n"
-" Eliminare i rami selezionati?"
-
#: lib/branch_delete.tcl:141
#, tcl-format
msgid ""
@@ -2418,7 +2408,7 @@ msgstr "Eseguo: %s"
#: lib/tools.tcl:149
#, tcl-format
-msgid "Tool completed succesfully: %s"
+msgid "Tool completed successfully: %s"
msgstr "Il programma esterno è terminato con successo: %s"
#: lib/tools.tcl:151
diff --git a/git-gui/po/ja.po b/git-gui/po/ja.po
index 09d60be..63c4695 100644
--- a/git-gui/po/ja.po
+++ b/git-gui/po/ja.po
@@ -773,16 +773,6 @@ msgstr "無条件(マージテストしない)"
msgid "The following branches are not completely merged into %s:"
msgstr "以下のブランチは %s に完全にマージされていません:"
-#: lib/branch_delete.tcl:115
-msgid ""
-"Recovering deleted branches is difficult. \n"
-"\n"
-" Delete the selected branches?"
-msgstr ""
-"ブランチを削除すると元に戻すのは困難です。 \n"
-"\n"
-" 選択したブランチを削除しますか?"
-
#: lib/branch_delete.tcl:141
#, tcl-format
msgid ""
@@ -2382,7 +2372,7 @@ msgstr "実行中: %s"
#: lib/tools.tcl:149
#, tcl-format
-msgid "Tool completed succesfully: %s"
+msgid "Tool completed successfully: %s"
msgstr "ツールが完了しました: %s"
#: lib/tools.tcl:151
diff --git a/git-gui/po/nb.po b/git-gui/po/nb.po
index 1c5137d..6de93c2 100644
--- a/git-gui/po/nb.po
+++ b/git-gui/po/nb.po
@@ -761,16 +761,6 @@ msgstr "Alltid (Ikke utfør sammenslåingstest.)"
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 ""
@@ -2331,7 +2321,7 @@ msgstr "Kjører: %s"
#: lib/tools.tcl:149
#, tcl-format
-msgid "Tool completed succesfully: %s"
+msgid "Tool completed successfully: %s"
msgstr "Verktøyet ble fullført med suksess: %s"
#: lib/tools.tcl:151
diff --git a/git-gui/po/ru.po b/git-gui/po/ru.po
index db55b3e..0ffc4a4 100644
--- a/git-gui/po/ru.po
+++ b/git-gui/po/ru.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: git-gui\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-03-14 07:18+0100\n"
+"POT-Creation-Date: 2008-12-08 08:31-0800\n"
"PO-Revision-Date: 2007-10-22 22:30-0200\n"
"Last-Translator: Alex Riesen <raa.lkml@gmail.com>\n"
"Language-Team: Russian Translation <git@vger.kernel.org>\n"
@@ -15,33 +15,33 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\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: критическая ошибка"
-#: git-gui.sh:593
+#: git-gui.sh:689
#, tcl-format
msgid "Invalid font specified in %s:"
msgstr "В %s установлен неверный шрифт:"
-#: git-gui.sh:620
+#: git-gui.sh:723
msgid "Main Font"
msgstr "Шрифт интерфейса"
-#: git-gui.sh:621
+#: git-gui.sh:724
msgid "Diff/Console Font"
msgstr "Шрифт консоли и изменений (diff)"
-#: git-gui.sh:635
+#: git-gui.sh:738
msgid "Cannot find git in PATH."
msgstr "git не найден в PATH."
-#: git-gui.sh:662
+#: git-gui.sh:765
msgid "Cannot parse Git version string:"
msgstr "Невозможно распознать строку версии Git: "
-#: git-gui.sh:680
+#: git-gui.sh:783
#, tcl-format
msgid ""
"Git version cannot be determined.\n"
@@ -53,384 +53,451 @@ msgid ""
"Assume '%s' is version 1.5.0?\n"
msgstr ""
"Невозможно определить версию Git\n"
+"\n"
"%s указывает на версию '%s'.\n"
"\n"
"для %s требуется версия Git, начиная с 1.5.0\n"
"\n"
"Принять '%s' как версию 1.5.0?\n"
-#: git-gui.sh:918
+#: git-gui.sh:1062
msgid "Git directory not found:"
msgstr "Каталог Git не найден:"
-#: git-gui.sh:925
+#: git-gui.sh:1069
msgid "Cannot move to top of working directory:"
msgstr "Невозможно перейти к корню рабочего каталога репозитория: "
-#: git-gui.sh:932
+#: git-gui.sh:1076
msgid "Cannot use funny .git directory:"
-msgstr "Каталог.git испорчен: "
+msgstr "Каталог .git испорчен: "
-#: git-gui.sh:937
+#: git-gui.sh:1081
msgid "No working directory"
msgstr "Отсутствует рабочий каталог"
-#: git-gui.sh:1084 lib/checkout_op.tcl:283
+#: git-gui.sh:1247 lib/checkout_op.tcl:305
msgid "Refreshing file status..."
msgstr "Обновление информации о состоянии файлов..."
-#: git-gui.sh:1149
+#: git-gui.sh:1303
msgid "Scanning for modified files ..."
msgstr "Поиск измененных файлов..."
-#: git-gui.sh:1324 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:1590
+#: git-gui.sh:1819
msgid "Unmodified"
msgstr "Не изменено"
-#: git-gui.sh:1592
+#: git-gui.sh:1821
msgid "Modified, not staged"
msgstr "Изменено, не подготовлено"
-#: git-gui.sh:1593 git-gui.sh:1598
+#: git-gui.sh:1822 git-gui.sh:1830
msgid "Staged for commit"
msgstr "Подготовлено для сохранения"
-#: git-gui.sh:1594 git-gui.sh:1599
+#: git-gui.sh:1823 git-gui.sh:1831
msgid "Portions staged for commit"
msgstr "Части, подготовленные для сохранения"
-#: git-gui.sh:1595 git-gui.sh:1600
+#: git-gui.sh:1824 git-gui.sh:1832
msgid "Staged for commit, missing"
msgstr "Подготовлено для сохранения, отсутствует"
-#: git-gui.sh:1597
+#: 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:1602
+#: git-gui.sh:1834
msgid "Missing"
msgstr "Отсутствует"
-#: git-gui.sh:1603
+#: git-gui.sh:1835
msgid "Staged for removal"
msgstr "Подготовлено для удаления"
-#: git-gui.sh:1604
+#: git-gui.sh:1836
msgid "Staged for removal, still present"
msgstr "Подготовлено для удаления, еще не удалено"
-#: 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 "Требуется разрешение конфликта при объединении"
+msgstr "Требуется разрешение конфликта при слиянии"
-#: git-gui.sh:1644
+#: git-gui.sh:1878
msgid "Starting gitk... please wait..."
-msgstr "Запускается gitk... пожалуйста, ждите..."
+msgstr "Запускается gitk... Подождите, пожалуйста..."
-#: git-gui.sh:1653
-#, tcl-format
-msgid ""
-"Unable to start gitk:\n"
-"\n"
-"%s does not exist"
-msgstr ""
-"Не удалось запустить gitk:\n"
-"\n"
-"%s не существует"
+#: git-gui.sh:1887
+msgid "Couldn't find gitk in PATH"
+msgstr "gitk не найден в PATH."
-#: git-gui.sh:1860 lib/choose_repository.tcl:36
+#: git-gui.sh:2280 lib/choose_repository.tcl:36
msgid "Repository"
msgstr "Репозиторий"
-#: git-gui.sh:1861
+#: git-gui.sh:2281
msgid "Edit"
msgstr "Редактировать"
-#: git-gui.sh:1863 lib/choose_rev.tcl:561
+#: git-gui.sh:2283 lib/choose_rev.tcl:561
msgid "Branch"
msgstr "Ветвь"
-#: git-gui.sh:1866 lib/choose_rev.tcl:548
+#: git-gui.sh:2286 lib/choose_rev.tcl:548
msgid "Commit@@noun"
msgstr "Состояние"
-#: 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 "Объединить"
+msgstr "Слияние"
-#: git-gui.sh:1870 lib/choose_rev.tcl:557
+#: git-gui.sh:2290 lib/choose_rev.tcl:557
msgid "Remote"
msgstr "Внешние репозитории"
-#: git-gui.sh:1879
+#: 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:1883
+#: git-gui.sh:2311
msgid "Browse Branch Files..."
msgstr "Показать файлы ветви..."
-#: git-gui.sh:1888
+#: git-gui.sh:2316
msgid "Visualize Current Branch's History"
-msgstr "История текущей ветви наглядно"
+msgstr "Показать историю текущей ветви"
-#: git-gui.sh:1892
+#: git-gui.sh:2320
msgid "Visualize All Branch History"
-msgstr "История всех ветвей наглядно"
+msgstr "Показать историю всех ветвей"
-#: git-gui.sh:1899
+#: git-gui.sh:2327
#, tcl-format
msgid "Browse %s's Files"
msgstr "Показать файлы ветви %s"
-#: git-gui.sh:1901
+#: git-gui.sh:2329
#, tcl-format
msgid "Visualize %s's History"
-msgstr "История ветви %s наглядно"
+msgstr "Показать историю ветви %s"
-#: 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 "Статистика базы данных"
-#: git-gui.sh:1909 lib/database.tcl:34
+#: git-gui.sh:2337 lib/database.tcl:34
msgid "Compress Database"
msgstr "Сжать базу данных"
-#: git-gui.sh:1912
+#: git-gui.sh:2340
msgid "Verify Database"
msgstr "Проверить базу данных"
-#: 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 "Создать ярлык на рабочем столе"
-#: 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 "Выход"
-#: git-gui.sh:1939
+#: git-gui.sh:2371
msgid "Undo"
msgstr "Отменить"
-#: git-gui.sh:1942
+#: git-gui.sh:2374
msgid "Redo"
msgstr "Повторить"
-#: git-gui.sh:1946 git-gui.sh:2443
+#: git-gui.sh:2378 git-gui.sh:2937
msgid "Cut"
msgstr "Вырезать"
-#: 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 "Копировать"
-#: git-gui.sh:1952 git-gui.sh:2449
+#: git-gui.sh:2384 git-gui.sh:2943
msgid "Paste"
msgstr "Вставить"
-#: 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 "Удалить"
-#: 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 "Выделить все"
-#: git-gui.sh:1968
+#: git-gui.sh:2400
msgid "Create..."
msgstr "Создать..."
-#: git-gui.sh:1974
+#: git-gui.sh:2406
msgid "Checkout..."
msgstr "Перейти..."
-#: git-gui.sh:1980
+#: git-gui.sh:2412
msgid "Rename..."
msgstr "Переименовать..."
-#: git-gui.sh:1985 git-gui.sh:2085
+#: git-gui.sh:2417
msgid "Delete..."
msgstr "Удалить..."
-#: git-gui.sh:1990
+#: git-gui.sh:2422
msgid "Reset..."
msgstr "Сбросить..."
-#: git-gui.sh:2002 git-gui.sh:2389
+#: 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:2010 git-gui.sh:2396
+#: git-gui.sh:2451 git-gui.sh:2885
msgid "Amend Last Commit"
msgstr "Исправить последнее состояние"
-#: 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 "Перечитать"
-#: git-gui.sh:2025
+#: git-gui.sh:2467
msgid "Stage To Commit"
msgstr "Подготовить для сохранения"
-#: git-gui.sh:2031
+#: git-gui.sh:2473
msgid "Stage Changed Files To Commit"
msgstr "Подготовить измененные файлы для сохранения"
-#: git-gui.sh:2037
+#: git-gui.sh:2479
msgid "Unstage From Commit"
msgstr "Убрать из подготовленного"
-#: git-gui.sh:2042 lib/index.tcl:395
+#: git-gui.sh:2484 lib/index.tcl:410
msgid "Revert Changes"
msgstr "Отменить изменения"
-#: git-gui.sh:2049 git-gui.sh:2368 git-gui.sh:2467
-msgid "Sign Off"
-msgstr "Подписать"
+#: git-gui.sh:2491 git-gui.sh:3083
+msgid "Show Less Context"
+msgstr "Меньше контекста"
-#: git-gui.sh:2053 git-gui.sh:2372
-msgid "Commit@@verb"
-msgstr "Сохранить"
+#: git-gui.sh:2495 git-gui.sh:3087
+msgid "Show More Context"
+msgstr "Больше контекста"
+
+#: git-gui.sh:2502 git-gui.sh:2852 git-gui.sh:2961
+msgid "Sign Off"
+msgstr "Вставить Signed-off-by"
-#: git-gui.sh:2064
+#: git-gui.sh:2518
msgid "Local Merge..."
-msgstr "Локальное объединение..."
+msgstr "Локальное слияние..."
-#: git-gui.sh:2069
+#: git-gui.sh:2523
msgid "Abort Merge..."
-msgstr "Прервать объединение..."
+msgstr "Прервать слияние..."
+
+#: git-gui.sh:2535 git-gui.sh:2575
+msgid "Add..."
+msgstr "Добавить..."
-#: git-gui.sh:2081
+#: git-gui.sh:2539
msgid "Push..."
msgstr "Отправить..."
-#: git-gui.sh:2092 lib/choose_repository.tcl:41
-msgid "Apple"
-msgstr ""
+#: git-gui.sh:2543
+msgid "Delete Branch..."
+msgstr "Удалить ветвь..."
-#: 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 "О %s"
-#: git-gui.sh:2099
+#: git-gui.sh:2557
msgid "Preferences..."
msgstr "Настройки..."
-#: git-gui.sh:2107 git-gui.sh:2639
+#: git-gui.sh:2565 git-gui.sh:3129
msgid "Options..."
msgstr "Настройки..."
-#: git-gui.sh:2113 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:2154
+#: git-gui.sh:2611
msgid "Online Documentation"
msgstr "Документация в интернете"
-#: git-gui.sh:2238
+#: git-gui.sh:2614 lib/choose_repository.tcl:47 lib/choose_repository.tcl:56
+msgid "Show SSH Key"
+msgstr "Показать ключ SSH"
+
+#: git-gui.sh:2721
#, tcl-format
msgid "fatal: cannot stat path %s: No such file or directory"
msgstr "критическая ошибка: %s: нет такого файла или каталога"
-#: git-gui.sh:2271
+#: git-gui.sh:2754
msgid "Current Branch:"
msgstr "Текущая ветвь:"
-#: git-gui.sh:2292
+#: git-gui.sh:2775
msgid "Staged Changes (Will Commit)"
msgstr "Подготовлено (будет сохранено)"
-#: git-gui.sh:2312
+#: git-gui.sh:2795
msgid "Unstaged Changes"
msgstr "Изменено (не будет сохранено)"
-#: git-gui.sh:2362
+#: git-gui.sh:2845
msgid "Stage Changed"
msgstr "Подготовить все"
-#: 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 "Отправить"
-#: git-gui.sh:2408
+#: git-gui.sh:2899
msgid "Initial Commit Message:"
msgstr "Комментарий к первому состоянию:"
-#: git-gui.sh:2409
+#: git-gui.sh:2900
msgid "Amended Commit Message:"
msgstr "Комментарий к исправленному состоянию:"
-#: git-gui.sh:2410
+#: git-gui.sh:2901
msgid "Amended Initial Commit Message:"
msgstr "Комментарий к исправленному первоначальному состоянию:"
-#: git-gui.sh:2411
+#: git-gui.sh:2902
msgid "Amended Merge Commit Message:"
-msgstr "Комментарий к исправленному объединению:"
+msgstr "Комментарий к исправленному слиянию:"
-#: git-gui.sh:2412
+#: git-gui.sh:2903
msgid "Merge Commit Message:"
-msgstr "Комментарий к объединению:"
+msgstr "Комментарий к слиянию:"
-#: git-gui.sh:2413
+#: git-gui.sh:2904
msgid "Commit Message:"
msgstr "Комментарий к состоянию:"
-#: 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 "Копировать все"
-#: git-gui.sh:2483 lib/blame.tcl:107
+#: git-gui.sh:2977 lib/blame.tcl:104
msgid "File:"
msgstr "Файл:"
-#: git-gui.sh:2589
-msgid "Apply/Reverse Hunk"
-msgstr "Применить/Убрать изменение"
-
-#: git-gui.sh:2595
-msgid "Show Less Context"
-msgstr "Меньше контекста"
-
-#: git-gui.sh:2602
-msgid "Show More Context"
-msgstr "Больше контекста"
-
-#: git-gui.sh:2610
+#: git-gui.sh:3092
msgid "Refresh"
msgstr "Обновить"
-#: git-gui.sh:2631
+#: git-gui.sh:3113
msgid "Decrease Font Size"
msgstr "Уменьшить размер шрифта"
-#: git-gui.sh:2635
+#: git-gui.sh:3117
msgid "Increase Font Size"
msgstr "Увеличить размер шрифта"
-#: git-gui.sh:2646
+#: git-gui.sh:3125 lib/blame.tcl:281
+msgid "Encoding"
+msgstr "Кодировка"
+
+#: git-gui.sh:3136
+msgid "Apply/Reverse Hunk"
+msgstr "Применить/Убрать изменение"
+
+#: git-gui.sh:3141
+msgid "Apply/Reverse Line"
+msgstr "Применить/Убрать строку"
+
+#: git-gui.sh:3151
+msgid "Run Merge Tool"
+msgstr "Запустить программу слияния"
+
+#: git-gui.sh:3156
+msgid "Use Remote Version"
+msgstr "Взять внешнюю версию"
+
+#: git-gui.sh:3160
+msgid "Use Local Version"
+msgstr "Взять локальную версию"
+
+#: git-gui.sh:3164
+msgid "Revert To Base"
+msgstr "Отменить изменения"
+
+#: git-gui.sh:3183
msgid "Unstage Hunk From Commit"
msgstr "Не сохранять часть"
-#: git-gui.sh:2648
+#: git-gui.sh:3184
+msgid "Unstage Line From Commit"
+msgstr "Убрать строку из подготовленного"
+
+#: git-gui.sh:3186
msgid "Stage Hunk For Commit"
msgstr "Подготовить часть для сохранения"
-#: git-gui.sh:2667
+#: git-gui.sh:3187
+msgid "Stage Line For Commit"
+msgstr "Подготовить строку для сохранения"
+
+#: git-gui.sh:3210
msgid "Initializing..."
msgstr "Инициализация..."
-#: git-gui.sh:2762
+#: git-gui.sh:3315
#, tcl-format
msgid ""
"Possible environment issues exist.\n"
@@ -447,7 +514,7 @@ msgstr ""
"запущенными из %s\n"
"\n"
-#: git-gui.sh:2792
+#: git-gui.sh:3345
msgid ""
"\n"
"This is due to a known issue with the\n"
@@ -457,7 +524,7 @@ msgstr ""
"Это известная проблема с Tcl,\n"
"распространяемым Cygwin."
-#: git-gui.sh:2797
+#: git-gui.sh:3350
#, tcl-format
msgid ""
"\n"
@@ -478,64 +545,108 @@ msgstr ""
msgid "git-gui - a graphical user interface for Git."
msgstr "git-gui - графический пользовательский интерфейс к Git."
-#: lib/blame.tcl:77
+#: lib/blame.tcl:72
msgid "File Viewer"
msgstr "Просмотр файла"
-#: lib/blame.tcl:81
+#: lib/blame.tcl:78
msgid "Commit:"
msgstr "Сохраненное состояние:"
-#: lib/blame.tcl:264
+#: lib/blame.tcl:271
msgid "Copy Commit"
msgstr "Скопировать SHA-1"
-#: lib/blame.tcl:384
+#: lib/blame.tcl:275
+msgid "Find Text..."
+msgstr "Найти текст..."
+
+#: lib/blame.tcl:284
+msgid "Do Full Copy Detection"
+msgstr "Провести полный поиск копий"
+
+#: 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:488
+#: lib/blame.tcl:557
msgid "Loading copy/move tracking annotations..."
msgstr "Загрузка аннотации копирований/переименований..."
-#: lib/blame.tcl:508
+#: lib/blame.tcl:577
msgid "lines annotated"
msgstr "строк прокомментировано"
-#: lib/blame.tcl:689
+#: lib/blame.tcl:769
msgid "Loading original location annotations..."
msgstr "Загрузка аннотаций первоначального положения объекта..."
-#: lib/blame.tcl:692
+#: lib/blame.tcl:772
msgid "Annotation complete."
msgstr "Аннотация завершена."
-#: lib/blame.tcl:746
+#: lib/blame.tcl:802
+msgid "Busy"
+msgstr "Занят"
+
+#: lib/blame.tcl:803
+msgid "Annotation process is already running."
+msgstr "Аннотация уже запущена"
+
+#: lib/blame.tcl:842
+msgid "Running thorough copy detection..."
+msgstr "Выполнение полного поиска копий..."
+
+#: lib/blame.tcl:910
msgid "Loading annotation..."
msgstr "Загрузка аннотации..."
-#: lib/blame.tcl:802
+#: lib/blame.tcl:963
msgid "Author:"
msgstr "Автор:"
-#: lib/blame.tcl:806
+#: lib/blame.tcl:967
msgid "Committer:"
msgstr "Сохранил:"
-#: lib/blame.tcl:811
+#: lib/blame.tcl:972
msgid "Original File:"
msgstr "Исходный файл:"
-#: lib/blame.tcl:925
+#: 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:931
+#: lib/blame.tcl:1237
msgid "In File:"
msgstr "Файл:"
-#: lib/blame.tcl:936
+#: lib/blame.tcl:1242
msgid "Copied Or Moved Here By:"
msgstr "Скопировано/перемещено в:"
@@ -549,16 +660,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: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 "Отменить"
+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:242
+#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:280
msgid "Options"
msgstr "Настройки"
@@ -578,7 +691,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 "Создать"
@@ -586,7 +699,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 "Название:"
@@ -610,7 +723,7 @@ msgstr "Нет"
msgid "Fast Forward Only"
msgstr "Только 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 "Сброс"
@@ -650,26 +763,16 @@ msgstr "Локальные ветви"
#: lib/branch_delete.tcl:52
msgid "Delete Only If Merged Into"
-msgstr "Удалить только в случае, если было объединение с"
+msgstr "Удалить только в случае, если было слияние с"
#: lib/branch_delete.tcl:54
msgid "Always (Do not perform merge test.)"
-msgstr "Всегда (не выполнять проверку на объединение)"
+msgstr "Всегда (не выполнять проверку на слияние)"
#: lib/branch_delete.tcl:103
#, tcl-format
msgid "The following branches are not completely merged into %s:"
-msgstr "Следующие ветви объединены с %s не полностью:"
-
-#: lib/branch_delete.tcl:115
-msgid ""
-"Recovering deleted branches is difficult. \n"
-"\n"
-" Delete the selected branches?"
-msgstr ""
-"Восстанавливать удаленные ветви сложно. \n"
-"\n"
-" Удалить выбранные ветви?"
+msgstr "Ветви, которые не полностью сливаются с %s:"
#: lib/branch_delete.tcl:141
#, tcl-format
@@ -700,7 +803,7 @@ msgstr "Новое название:"
msgid "Please select a branch to rename."
msgstr "Укажите ветвь для переименования."
-#: 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 "Ветвь '%s' уже существует."
@@ -731,32 +834,38 @@ msgstr "[На уровень выше]"
msgid "Browse Branch Files"
msgstr "Показать файлы ветви"
-#: 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 "Показать"
-#: lib/checkout_op.tcl:79
+#: lib/checkout_op.tcl:84
#, tcl-format
msgid "Fetching %s from %s"
msgstr "Получение %s из %s "
-#: lib/checkout_op.tcl:127
+#: lib/checkout_op.tcl:132
#, tcl-format
msgid "fatal: Cannot resolve %s"
msgstr "критическая ошибка: невозможно разрешить %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 "Закрыть"
-#: lib/checkout_op.tcl:169
+#: lib/checkout_op.tcl:174
#, tcl-format
msgid "Branch '%s' does not exist."
msgstr "Ветвь '%s' не существует "
-#: lib/checkout_op.tcl:206
+#: lib/checkout_op.tcl:193
+#, tcl-format
+msgid "Failed to configure simplified git-pull for '%s'."
+msgstr "Ошибка создания упрощённой конфигурации git pull для '%s'."
+
+#: lib/checkout_op.tcl:228
#, tcl-format
msgid ""
"Branch '%s' already exists.\n"
@@ -767,23 +876,23 @@ msgstr ""
"Ветвь '%s' уже существует.\n"
"\n"
"Она не может быть прокручена(fast-forward) к %s.\n"
-"Требуется объединение."
+"Требуется слияние."
-#: lib/checkout_op.tcl:220
+#: lib/checkout_op.tcl:242
#, tcl-format
msgid "Merge strategy '%s' not supported."
-msgstr "Стратегия объединения '%s' не поддерживается."
+msgstr "Неизвестная стратегия слияния: '%s'."
-#: lib/checkout_op.tcl:239
+#: lib/checkout_op.tcl:261
#, tcl-format
msgid "Failed to update '%s'."
msgstr "Не удалось обновить '%s'."
-#: lib/checkout_op.tcl:251
+#: lib/checkout_op.tcl:273
msgid "Staging area (index) is already locked."
msgstr "Рабочая область заблокирована другим процессом."
-#: lib/checkout_op.tcl:266
+#: lib/checkout_op.tcl:288
msgid ""
"Last scanned state does not match repository state.\n"
"\n"
@@ -799,30 +908,30 @@ msgstr ""
"\n"
"Это будет сделано сейчас автоматически.\n"
-#: lib/checkout_op.tcl:322
+#: lib/checkout_op.tcl:344
#, tcl-format
msgid "Updating working directory to '%s'..."
msgstr "Обновление рабочего каталога из '%s'..."
-#: lib/checkout_op.tcl:323
+#: lib/checkout_op.tcl:345
msgid "files checked out"
msgstr "файлы извлечены"
-#: lib/checkout_op.tcl:353
+#: lib/checkout_op.tcl:375
#, tcl-format
msgid "Aborted checkout of '%s' (file level merging is required)."
-msgstr "Прерван переход на '%s' (требуется объединение на уровне файлов)"
+msgstr "Прерван переход на '%s' (требуется слияние содержания файлов)"
-#: lib/checkout_op.tcl:354
+#: lib/checkout_op.tcl:376
msgid "File level merge required."
-msgstr "Требуется объединение на уровне файлов."
+msgstr "Требуется слияние содержания файлов."
-#: lib/checkout_op.tcl:358
+#: lib/checkout_op.tcl:380
#, tcl-format
msgid "Staying on branch '%s'."
msgstr "Ветвь '%s' остается текущей."
-#: lib/checkout_op.tcl:429
+#: lib/checkout_op.tcl:451
msgid ""
"You are no longer on a local branch.\n"
"\n"
@@ -834,30 +943,30 @@ msgstr ""
"Если вы хотите снова вернуться к какой-нибудь ветви, создайте ее сейчас, "
"начиная с 'Текущего отсоединенного состояния'."
-#: 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' сделана текущей."
-#: lib/checkout_op.tcl:478
+#: lib/checkout_op.tcl:500
#, tcl-format
msgid "Resetting '%s' to '%s' will lose the following commits:"
msgstr "Сброс '%s' в '%s' приведет к потере следующих сохраненных состояний: "
-#: lib/checkout_op.tcl:500
+#: lib/checkout_op.tcl:522
msgid "Recovering lost commits may not be easy."
msgstr "Восстановить потерянные сохраненные состояния будет сложно."
-#: lib/checkout_op.tcl:505
+#: lib/checkout_op.tcl:527
#, tcl-format
msgid "Reset '%s'?"
msgstr "Сбросить '%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 "Наглядно"
-#: lib/checkout_op.tcl:578
+#: lib/checkout_op.tcl:600
#, tcl-format
msgid ""
"Failed to set current branch.\n"
@@ -900,224 +1009,228 @@ msgstr ""
#: lib/choose_repository.tcl:28
msgid "Git Gui"
-msgstr ""
+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:460
+#: 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:976
+#: 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:478
+#: lib/choose_repository.tcl:387
msgid "Directory:"
msgstr "Каталог:"
-#: 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 "Репозиторий"
-#: lib/choose_repository.tcl:437
+#: lib/choose_repository.tcl:442
#, tcl-format
msgid "Directory %s already exists."
msgstr "Каталог '%s' уже существует."
-#: lib/choose_repository.tcl:441
+#: lib/choose_repository.tcl:446
#, tcl-format
msgid "File %s already exists."
msgstr "Файл '%s' уже существует."
-#: lib/choose_repository.tcl:455
+#: lib/choose_repository.tcl:460
msgid "Clone"
msgstr "Склонировать"
-#: lib/choose_repository.tcl:468
-msgid "URL:"
-msgstr "Ссылка:"
+#: lib/choose_repository.tcl:473
+msgid "Source Location:"
+msgstr "Исходное положение:"
+
+#: lib/choose_repository.tcl:484
+msgid "Target Directory:"
+msgstr "Каталог назначения:"
-#: lib/choose_repository.tcl:489
+#: lib/choose_repository.tcl:496
msgid "Clone Type:"
msgstr "Тип клона:"
-#: lib/choose_repository.tcl:495
+#: lib/choose_repository.tcl:502
msgid "Standard (Fast, Semi-Redundant, Hardlinks)"
msgstr "Стандартный (Быстрый, полуизбыточный, \"жесткие\" ссылки)"
-#: lib/choose_repository.tcl:501
+#: lib/choose_repository.tcl:508
msgid "Full Copy (Slower, Redundant Backup)"
msgstr "Полная копия (Медленный, создает резервную копию)"
-#: lib/choose_repository.tcl:507
+#: lib/choose_repository.tcl:514
msgid "Shared (Fastest, Not Recommended, No Backup)"
msgstr "Общий (Самый быстрый, не рекомендуется, без резервной копии)"
-#: 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 "Каталог не является репозиторием: %s"
-#: lib/choose_repository.tcl:579
+#: lib/choose_repository.tcl:586
msgid "Standard only available for local repository."
msgstr "Стандартный клон возможен только для локального репозитория."
-#: lib/choose_repository.tcl:583
+#: lib/choose_repository.tcl:590
msgid "Shared only available for local repository."
msgstr "Общий клон возможен только для локального репозитория."
-#: lib/choose_repository.tcl:604
+#: lib/choose_repository.tcl:611
#, tcl-format
msgid "Location %s already exists."
msgstr "Путь '%s' уже существует."
-#: lib/choose_repository.tcl:615
+#: lib/choose_repository.tcl:622
msgid "Failed to configure origin"
msgstr "Не могу сконфигурировать исходный репозиторий."
-#: lib/choose_repository.tcl:627
+#: lib/choose_repository.tcl:634
msgid "Counting objects"
msgstr "Считаю объекты"
-#: lib/choose_repository.tcl:628
+#: lib/choose_repository.tcl:635
msgid "buckets"
msgstr ""
-#: lib/choose_repository.tcl:652
+#: lib/choose_repository.tcl:659
#, tcl-format
msgid "Unable to copy objects/info/alternates: %s"
msgstr "Не могу скопировать objects/info/alternates: %s"
-#: lib/choose_repository.tcl:688
+#: lib/choose_repository.tcl:695
#, tcl-format
msgid "Nothing to clone from %s."
msgstr "Нечего клонировать с %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 "Не инициализирована ветвь 'master'."
-#: lib/choose_repository.tcl:703
+#: lib/choose_repository.tcl:710
msgid "Hardlinks are unavailable. Falling back to copying."
-msgstr "\"Жесткие ссылки\" не доступны. Буду использовать копирование."
+msgstr "\"Жесткие ссылки\" недоступны. Будет использовано копирование."
-#: lib/choose_repository.tcl:715
+#: lib/choose_repository.tcl:722
#, tcl-format
msgid "Cloning from %s"
msgstr "Клонирование %s"
-#: lib/choose_repository.tcl:746
+#: lib/choose_repository.tcl:753
msgid "Copying objects"
msgstr "Копирование objects"
-#: lib/choose_repository.tcl:747
+#: lib/choose_repository.tcl:754
msgid "KiB"
msgstr "КБ"
-#: lib/choose_repository.tcl:771
+#: lib/choose_repository.tcl:778
#, tcl-format
msgid "Unable to copy object: %s"
msgstr "Не могу скопировать объект: %s"
-#: lib/choose_repository.tcl:781
+#: lib/choose_repository.tcl:788
msgid "Linking objects"
msgstr "Создание ссылок на objects"
-#: lib/choose_repository.tcl:782
+#: lib/choose_repository.tcl:789
msgid "objects"
msgstr "объекты"
-#: lib/choose_repository.tcl:790
+#: lib/choose_repository.tcl:797
#, tcl-format
msgid "Unable to hardlink object: %s"
msgstr "Не могу \"жестко связать\" объект: %s"
-#: lib/choose_repository.tcl:845
+#: lib/choose_repository.tcl:852
msgid "Cannot fetch branches and objects. See console output for details."
msgstr ""
"Не могу получить ветви и объекты. Дополнительная информация на консоли."
-#: lib/choose_repository.tcl:856
+#: lib/choose_repository.tcl:863
msgid "Cannot fetch tags. See console output for details."
msgstr "Не могу получить метки. Дополнительная информация на консоли."
-#: lib/choose_repository.tcl:880
+#: lib/choose_repository.tcl:887
msgid "Cannot determine HEAD. See console output for details."
msgstr "Не могу определить HEAD. Дополнительная информация на консоли."
-#: lib/choose_repository.tcl:889
+#: lib/choose_repository.tcl:896
#, tcl-format
msgid "Unable to cleanup %s"
msgstr "Не могу очистить %s"
-#: lib/choose_repository.tcl:895
+#: lib/choose_repository.tcl:902
msgid "Clone failed."
msgstr "Клонирование не удалось."
-#: lib/choose_repository.tcl:902
+#: lib/choose_repository.tcl:909
msgid "No default branch obtained."
msgstr "Не было получено ветви по умолчанию."
-#: lib/choose_repository.tcl:913
+#: lib/choose_repository.tcl:920
#, tcl-format
msgid "Cannot resolve %s as a commit."
msgstr "Не могу распознать %s как состояние."
-#: lib/choose_repository.tcl:925
+#: lib/choose_repository.tcl:932
msgid "Creating working directory"
msgstr "Создаю рабочий каталог"
-#: 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 "файлов"
-#: lib/choose_repository.tcl:955
+#: lib/choose_repository.tcl:962
msgid "Initial file checkout failed."
msgstr "Не удалось получить начальное состояние файлов репозитория."
-#: lib/choose_repository.tcl:971
+#: lib/choose_repository.tcl:978
msgid "Open"
msgstr "Открыть"
-#: lib/choose_repository.tcl:981
+#: lib/choose_repository.tcl:988
msgid "Repository:"
msgstr "Репозиторий:"
-#: lib/choose_repository.tcl:1031
+#: lib/choose_repository.tcl:1037
#, tcl-format
msgid "Failed to open repository %s:"
msgstr "Не удалось открыть репозиторий %s:"
@@ -1140,7 +1253,7 @@ msgstr "Ветвь слежения"
#: lib/choose_rev.tcl:84 lib/choose_rev.tcl:538
msgid "Tag"
-msgstr "Таг"
+msgstr "Метка"
#: lib/choose_rev.tcl:317
#, tcl-format
@@ -1182,24 +1295,24 @@ msgid ""
"completed. You cannot amend the prior commit unless you first abort the "
"current merge activity.\n"
msgstr ""
-"Невозможно исправить состояние во время объединения.\n"
+"Невозможно исправить состояние во время операции слияния.\n"
"\n"
-"Текущее объединение не завершено. Невозможно исправить предыдущее "
-"сохраненное состояние не прерывая текущее объединение.\n"
+"Текущее слияние не завершено. Невозможно исправить предыдущее "
+"сохраненное состояние, не прерывая эту операцию.\n"
-#: 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 "Неверный GIT_COMMITTER_IDENT:"
-#: lib/commit.tcl:133
+#: lib/commit.tcl:132
msgid ""
"Last scanned state does not match repository state.\n"
"\n"
@@ -1215,7 +1328,7 @@ msgstr ""
"\n"
"Это будет сделано сейчас автоматически.\n"
-#: lib/commit.tcl:154
+#: lib/commit.tcl:155
#, tcl-format
msgid ""
"Unmerged files cannot be committed.\n"
@@ -1223,12 +1336,12 @@ msgid ""
"File %s has merge conflicts. You must resolve them and stage the file "
"before committing.\n"
msgstr ""
-"Нельзя сохранить необъединенные файлы.\n"
+"Нельзя сохранить файлы с незавершённой операцей слияния.\n"
"\n"
-"Для файла %s возник конфликт объединения. Разрешите конфликт и добавьте к "
+"Для файла %s возник конфликт слияния. Разрешите конфликт и добавьте к "
"подготовленным файлам перед сохранением.\n"
-#: lib/commit.tcl:162
+#: lib/commit.tcl:163
#, tcl-format
msgid ""
"Unknown file state %s detected.\n"
@@ -1239,7 +1352,7 @@ msgstr ""
"\n"
"Файл %s не может быть сохранен данной программой.\n"
-#: lib/commit.tcl:170
+#: lib/commit.tcl:171
msgid ""
"No changes to commit.\n"
"\n"
@@ -1249,7 +1362,7 @@ msgstr ""
"\n"
"Подготовьте хотя бы один файл до создания сохраненного состояния.\n"
-#: lib/commit.tcl:183
+#: lib/commit.tcl:186
msgid ""
"Please supply a commit message.\n"
"\n"
@@ -1267,45 +1380,45 @@ msgstr ""
"- вторая строка пустая\n"
"- оставшиеся строки: опишите, что дают ваши изменения.\n"
-#: lib/commit.tcl:207
+#: lib/commit.tcl:210
#, tcl-format
msgid "warning: Tcl does not support encoding '%s'."
msgstr "предупреждение: Tcl не поддерживает кодировку '%s'."
-#: lib/commit.tcl:221
+#: lib/commit.tcl:226
msgid "Calling pre-commit hook..."
msgstr "Вызов программы поддержки репозитория pre-commit..."
-#: lib/commit.tcl:236
+#: lib/commit.tcl:241
msgid "Commit declined by pre-commit hook."
msgstr "Сохранение прервано программой поддержки репозитория pre-commit"
-#: lib/commit.tcl:259
+#: lib/commit.tcl:264
msgid "Calling commit-msg hook..."
msgstr "Вызов программы поддержки репозитория commit-msg..."
-#: lib/commit.tcl:274
+#: lib/commit.tcl:279
msgid "Commit declined by commit-msg hook."
msgstr "Сохранение прервано программой поддержки репозитория commit-msg"
-#: 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 "Программа write-tree завершилась с ошибкой:"
-#: 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 "Состояние %s выглядит поврежденным"
-#: lib/commit.tcl:326
+#: lib/commit.tcl:331
msgid ""
"No changes to commit.\n"
"\n"
@@ -1315,23 +1428,23 @@ msgid ""
msgstr ""
"Отсутствуют изменения для сохранения.\n"
"\n"
-"Ни один файл не был изменен и не было объединения.\n"
+"Ни один файл не был изменен и не было слияния.\n"
"\n"
"Сейчас автоматически запустится перечитывание репозитория.\n"
-#: 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 "Программа commit-tree завершилась с ошибкой:"
-#: lib/commit.tcl:367
+#: lib/commit.tcl:372
msgid "update-ref failed:"
msgstr "Программа update-ref завершилась с ошибкой:"
-#: lib/commit.tcl:454
+#: lib/commit.tcl:460
#, tcl-format
msgid "Created commit %s: %s"
msgstr "Создано состояние %s: %s "
@@ -1406,7 +1519,7 @@ msgstr ""
msgid "Invalid date from Git: %s"
msgstr "Неправильная дата в репозитории: %s"
-#: lib/diff.tcl:42
+#: lib/diff.tcl:59
#, tcl-format
msgid ""
"No differences detected.\n"
@@ -1428,40 +1541,101 @@ msgstr ""
"\n"
"Сейчас будет запущено перечитывание репозитория, чтобы найти подобные файлы."
-#: lib/diff.tcl:81
+#: lib/diff.tcl:99
#, tcl-format
msgid "Loading diff of %s..."
msgstr "Загрузка изменений в %s..."
-#: lib/diff.tcl:114 lib/diff.tcl:184
+#: lib/diff.tcl:120
+msgid ""
+"LOCAL: deleted\n"
+"REMOTE:\n"
+msgstr ""
+"ЛОКАЛЬНО: удалён\n"
+"ВНЕШНИЙ:\n"
+
+#: lib/diff.tcl:125
+msgid ""
+"REMOTE: deleted\n"
+"LOCAL:\n"
+msgstr ""
+"ВНЕШНИЙ: удалён\n"
+"ЛОКАЛЬНО:\n"
+
+#: lib/diff.tcl:132
+msgid "LOCAL:\n"
+msgstr "ЛОКАЛЬНО:\n"
+
+#: lib/diff.tcl:135
+msgid "REMOTE:\n"
+msgstr "ВНЕШНИЙ:\n"
+
+#: lib/diff.tcl:197 lib/diff.tcl:296
#, tcl-format
msgid "Unable to display %s"
msgstr "Не могу показать %s"
-#: lib/diff.tcl:115
+#: lib/diff.tcl:198
msgid "Error loading file:"
msgstr "Ошибка загрузки файла:"
-#: lib/diff.tcl:122
+#: lib/diff.tcl:205
msgid "Git Repository (subproject)"
msgstr "Репозиторий Git (подпроект)"
-#: lib/diff.tcl:134
+#: lib/diff.tcl:217
msgid "* Binary file (not showing content)."
msgstr "* Двоичный файл (содержимое не показано)"
-#: lib/diff.tcl:185
-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"
+"* Неподготовленый файл обрезан: %s.\n"
+"* Чтобы увидеть весь файл, используйте программу-редактор.\n"
-#: lib/diff.tcl:303
+#: lib/diff.tcl:436
msgid "Failed to unstage selected hunk."
msgstr "Не удалось исключить выбранную часть."
-#: lib/diff.tcl:310
+#: lib/diff.tcl:443
msgid "Failed to stage selected hunk."
msgstr "Не удалось подготовить к сохранению выбранную часть."
+#: lib/diff.tcl:509
+msgid "Failed to unstage selected line."
+msgstr "Не удалось исключить выбранную строку."
+
+#: 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 "ошибка"
@@ -1480,7 +1654,7 @@ msgstr "Не удалось разблокировать индекс"
#: lib/index.tcl:15
msgid "Index Error"
-msgstr "Ошибка индекса"
+msgstr "Ошибка в индексе"
#: lib/index.tcl:21
msgid ""
@@ -1498,50 +1672,59 @@ 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"
"\n"
"You must finish amending this commit before starting any type of merge.\n"
msgstr ""
-"Невозможно выполнить объединение во время исправления.\n"
+"Невозможно выполнить слияние во время исправления.\n"
"\n"
"Завершите исправление данного состояния перед выполнением операции "
-"объединения.\n"
+"слияния.\n"
#: lib/merge.tcl:27
msgid ""
@@ -1559,7 +1742,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"
@@ -1569,14 +1752,14 @@ msgid ""
"You must resolve them, stage the file, and commit to complete the current "
"merge. Only then can you begin another merge.\n"
msgstr ""
-"Предыдущее объединение не завершено из-за конфликта.\n"
+"Предыдущее слияние не завершено из-за конфликта.\n"
"\n"
-"Для файла %s возник конфликт объединения.\n"
+"Для файла %s возник конфликт слияния.\n"
"\n"
"Разрешите конфликт, подготовьте файл и сохраните. Только после этого можно "
-"начать следующее объединение.\n"
+"начать следующее слияние.\n"
-#: lib/merge.tcl:54
+#: lib/merge.tcl:55
#, tcl-format
msgid ""
"You are in the middle of a change.\n"
@@ -1590,36 +1773,37 @@ msgstr ""
"\n"
"Файл %s изменен.\n"
"\n"
-"Подготовьте и сохраните измения перед началом объединения. В случае "
-"необходимости это позволит прервать операцию объединения.\n"
+"Подготовьте и сохраните измения перед началом слияния. В случае "
+"необходимости это позволит прервать операцию слияния.\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..."
+msgstr "Слияние %s и %s..."
-#: lib/merge.tcl:130
+#: lib/merge.tcl:131
msgid "Merge completed successfully."
-msgstr "Объединение успешно завершено."
+msgstr "Слияние успешно завершено."
-#: lib/merge.tcl:132
+#: lib/merge.tcl:133
msgid "Merge failed. Conflict resolution is required."
-msgstr "Не удалось завершить объединение. Требуется разрешение конфликта."
+msgstr "Не удалось завершить слияние. Требуется разрешение конфликта."
-#: lib/merge.tcl:157
+#: lib/merge.tcl:158
#, tcl-format
msgid "Merge Into %s"
-msgstr "Объединить с %s"
+msgstr "Слияние с %s"
-#: lib/merge.tcl:176
+#: lib/merge.tcl:177
msgid "Revision To Merge"
-msgstr "Версия для объединения"
+msgstr "Версия, с которой провести слияние"
-#: lib/merge.tcl:211
+#: lib/merge.tcl:212
msgid ""
"Cannot abort while amending.\n"
"\n"
@@ -1629,7 +1813,7 @@ msgstr ""
"\n"
"Завершите текущее исправление сохраненного состояния.\n"
-#: lib/merge.tcl:221
+#: lib/merge.tcl:222
msgid ""
"Abort merge?\n"
"\n"
@@ -1637,13 +1821,13 @@ msgid ""
"\n"
"Continue with aborting the current merge?"
msgstr ""
-"Прервать объединение?\n"
+"Прервать операцию слияния?\n"
"\n"
-"Прерывание объединения приведет к потере *ВСЕХ* несохраненных изменений.\n"
+"Прерывание этой операции приведет к потере *ВСЕХ* несохраненных изменений.\n"
"\n"
"Продолжить?"
-#: lib/merge.tcl:227
+#: lib/merge.tcl:228
msgid ""
"Reset changes?\n"
"\n"
@@ -1651,130 +1835,346 @@ msgid ""
"\n"
"Continue with resetting the current changes?"
msgstr ""
-"Прервать объединение?\n"
+"Прервать операцию слияния?\n"
"\n"
-"Прерывание объединения приведет к потере *ВСЕХ* несохраненных изменений.\n"
+"Прерывание этой операции приведет к потере *ВСЕХ* несохраненных изменений.\n"
"\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:265
+#: lib/merge.tcl:267
msgid "Abort failed."
msgstr "Прервать не удалось."
-#: lib/merge.tcl:267
+#: 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 "'%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"
+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 "Суммарный комментарий при объединении"
+msgstr "Суммарный комментарий при слиянии"
-#: lib/option.tcl:120
+#: lib/option.tcl:142
msgid "Merge Verbosity"
-msgstr "Уровень детальности сообщений при объединении"
+msgstr "Уровень детальности сообщений при слиянии"
-#: lib/option.tcl:121
+#: lib/option.tcl:143
msgid "Show Diffstat After Merge"
-msgstr "Показать отчет об изменениях после объединения"
+msgstr "Показать отчет об изменениях после слияния"
+
+#: lib/option.tcl:144
+msgid "Use Merge Tool"
+msgstr "Использовать для слияния программу"
-#: lib/option.tcl:123
+#: 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: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 "Число строк в контексте diff"
-#: lib/option.tcl:127
+#: lib/option.tcl:153
msgid "Commit Message Text Width"
-msgstr "Ширина комментария к состоянию:"
+msgstr "Ширина текста комментария"
-#: lib/option.tcl:128
+#: lib/option.tcl:154
msgid "New Branch Name Template"
msgstr "Шаблон для имени новой ветви"
-#: lib/option.tcl:192
+#: 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:216
+#: lib/option.tcl:254
msgid "Change Font"
-msgstr "Изменить шрифт"
+msgstr "Изменить"
-#: lib/option.tcl:220
+#: lib/option.tcl:258
#, tcl-format
msgid "Choose %s"
msgstr "Выберите %s"
# carbon copy
-#: lib/option.tcl:226
+#: lib/option.tcl:264
msgid "pt."
-msgstr ""
+msgstr "pt."
-#: lib/option.tcl:240
+#: lib/option.tcl:278
msgid "Preferences"
msgstr "Настройки"
-#: lib/option.tcl:275
+#: lib/option.tcl:314
msgid "Failed to completely save options:"
msgstr "Не удалось полностью сохранить настройки:"
+#: lib/remote.tcl:163
+msgid "Remove Remote"
+msgstr "Удалить ссылку на внешний репозиторий"
+
+#: lib/remote.tcl:168
+msgid "Prune from"
+msgstr "Чистка"
+
+#: lib/remote.tcl:173
+msgid "Fetch from"
+msgstr "Получение из"
+
+#: 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 "Не удалось добавить '%s' из '%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:63
+#: lib/transport.tcl:81
+#, tcl-format
+msgid "push %s"
+msgstr "отправить %s"
+
+#: lib/remote_add.tcl:164
+#, tcl-format
+msgid "Setting up the %s (at %s)"
+msgstr "Настройка %s (в %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"
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:"
-msgstr "по указанному URL:"
+#: lib/remote_branch_delete.tcl:66 lib/transport.tcl:149
+msgid "Arbitrary Location:"
+msgstr "Указаное положение:"
#: lib/remote_branch_delete.tcl:84
msgid "Branches"
@@ -1786,15 +2186,15 @@ msgstr "Удалить только в случае, если"
#: lib/remote_branch_delete.tcl:111
msgid "Merged Into:"
-msgstr "Объединено с:"
+msgstr "Слияние с:"
#: lib/remote_branch_delete.tcl:119
msgid "Always (Do not perform merge checks)"
-msgstr "Всегда (не выполнять проверку объединений)"
+msgstr "Всегда (не выполнять проверку на слияние)"
#: lib/remote_branch_delete.tcl:152
msgid "A branch is required for 'Merged Into'."
-msgstr "Для опции 'Объединено с' требуется указать ветвь."
+msgstr "Для опции 'Слияние с' требуется указать ветвь."
#: lib/remote_branch_delete.tcl:184
#, tcl-format
@@ -1803,7 +2203,8 @@ msgid ""
"\n"
" - %s"
msgstr ""
-"Следующие ветви объединены с %s не полностью:\n"
+"Следующие ветви могут быть объединены с %s при помощи операции слияния:\n"
+"\n"
" - %s"
#: lib/remote_branch_delete.tcl:189
@@ -1812,7 +2213,7 @@ msgid ""
"One or more of the merge tests failed because you have not fetched the "
"necessary commits. Try fetching from %s first."
msgstr ""
-"Один или несколько тестов на объединение не прошли, потому что Вы не "
+"Некоторые тесты на слияние не прошли, потому что Вы не "
"получили необходимые состояния. Попытайтесь получить их из %s."
#: lib/remote_branch_delete.tcl:207
@@ -1843,17 +2244,21 @@ msgstr "Не указан репозиторий."
msgid "Scanning %s..."
msgstr "Перечитывание %s... "
-#: lib/remote.tcl:165
-msgid "Prune from"
-msgstr "Чистка"
+#: lib/search.tcl:21
+msgid "Find:"
+msgstr "Поиск:"
-#: lib/remote.tcl:170
-msgid "Fetch from"
-msgstr "Получение из"
+#: lib/search.tcl:23
+msgid "Next"
+msgstr "Дальше"
-#: lib/remote.tcl:213
-msgid "Push to"
-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:"
@@ -1888,27 +2293,192 @@ msgstr "Программа проверки правописания не смо
msgid "Unrecognized spell checker"
msgstr "Нераспознаная программа проверки правописания"
-#: lib/spellcheck.tcl:180
+#: lib/spellcheck.tcl:186
msgid "No Suggestions"
msgstr "Исправлений не найдено"
-#: lib/spellcheck.tcl:381
+#: lib/spellcheck.tcl:388
msgid "Unexpected EOF from spell checker"
msgstr "Программа проверки правописания прервала передачу данных"
-#: lib/spellcheck.tcl:385
+#: 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 "%s ... %*i из %*i %s (%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
@@ -1926,48 +2496,46 @@ 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 "Отправка %s %s в %s"
-#: 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 "Использовать thin pack (для медленных сетевых подключений)"
-#: lib/transport.tcl:168
+#: lib/transport.tcl:179
msgid "Include tags"
-msgstr "Передать таги"
+msgstr "Передать метки"
-#~ msgid "Next >"
-#~ msgstr "Дальше >"
diff --git a/git-gui/po/sv.po b/git-gui/po/sv.po
index 167654c..c1535f9 100644
--- a/git-gui/po/sv.po
+++ b/git-gui/po/sv.po
@@ -780,16 +780,6 @@ msgstr "Alltid (utför inte sammanslagningstest)."
msgid "The following branches are not completely merged into %s:"
msgstr "Följande grenar är inte till fullo sammanslagna med %s:"
-#: lib/branch_delete.tcl:115
-msgid ""
-"Recovering deleted branches is difficult. \n"
-"\n"
-" Delete the selected branches?"
-msgstr ""
-"Det är svårt att återställa borttagna grenar.\n"
-"\n"
-" Ta bort valda grenar?"
-
#: lib/branch_delete.tcl:141
#, tcl-format
msgid ""
@@ -2398,7 +2388,7 @@ msgstr "Exekverar: %s"
#: lib/tools.tcl:149
#, tcl-format
-msgid "Tool completed succesfully: %s"
+msgid "Tool completed successfully: %s"
msgstr "Verktyget avslutades framgångsrikt: %s"
#: lib/tools.tcl:151
diff --git a/git-gui/po/zh_cn.po b/git-gui/po/zh_cn.po
index d2c6866..91c1be2 100644
--- a/git-gui/po/zh_cn.po
+++ b/git-gui/po/zh_cn.po
@@ -676,16 +676,6 @@ msgstr "总是合并 (不作合并测试.)"
msgid "The following branches are not completely merged into %s:"
msgstr "下列分支没有完全被合并到 %s:"
-#: lib/branch_delete.tcl:115
-msgid ""
-"Recovering deleted branches is difficult. \n"
-"\n"
-" Delete the selected branches?"
-msgstr ""
-"恢复被删除的分支非常困难.\n"
-"\n"
-"是否要删除所选分支?"
-
#: lib/branch_delete.tcl:141
#, tcl-format
msgid ""
diff --git a/git-gui/windows/git-gui.sh b/git-gui/windows/git-gui.sh
index 53c3a94..66bbb2f 100644
--- a/git-gui/windows/git-gui.sh
+++ b/git-gui/windows/git-gui.sh
@@ -3,7 +3,12 @@
exec wish "$0" -- "$@"
if { $argc >=2 && [lindex $argv 0] == "--working-dir" } {
- cd [lindex $argv 1]
+ set workdir [lindex $argv 1]
+ cd $workdir
+ if {[lindex [file split $workdir] end] eq {.git}} {
+ # Workaround for Explorer right click "Git GUI Here" on .git/
+ cd ..
+ }
set argv [lrange $argv 2 end]
incr argc -2
}
diff --git a/git-merge-one-file.sh b/git-merge-one-file.sh
index e1eb963..9c2c1b7 100755
--- a/git-merge-one-file.sh
+++ b/git-merge-one-file.sh
@@ -113,6 +113,10 @@ case "${1:-.}${2:-.}${3:-.}" in
src1=`git-unpack-file $2`
git merge-file "$src1" "$orig" "$src2"
ret=$?
+ msg=
+ if [ $ret -ne 0 ]; then
+ msg='content conflict'
+ fi
# Create the working tree file, using "our tree" version from the
# index, and then store the result of the merge.
@@ -120,7 +124,10 @@ case "${1:-.}${2:-.}${3:-.}" in
rm -f -- "$orig" "$src1" "$src2"
if [ "$6" != "$7" ]; then
- echo "ERROR: Permissions conflict: $5->$6,$7."
+ if [ -n "$msg" ]; then
+ msg="$msg, "
+ fi
+ msg="${msg}permissions conflict: $5->$6,$7"
ret=1
fi
if [ "$1" = '' ]; then
@@ -128,7 +135,7 @@ case "${1:-.}${2:-.}${3:-.}" in
fi
if [ $ret -ne 0 ]; then
- echo "ERROR: Merge conflict in $4"
+ echo "ERROR: $msg in $4"
exit 1
fi
exec git update-index -- "$4"
diff --git a/git-mergetool--lib.sh b/git-mergetool--lib.sh
index a16a279..bfb01f7 100644
--- a/git-mergetool--lib.sh
+++ b/git-mergetool--lib.sh
@@ -18,6 +18,9 @@ translate_merge_tool_path () {
emerge)
echo emacs
;;
+ araxis)
+ echo compare
+ ;;
*)
echo "$1"
;;
@@ -43,7 +46,7 @@ check_unchanged () {
valid_tool () {
case "$1" in
kdiff3 | tkdiff | xxdiff | meld | opendiff | \
- emerge | vimdiff | gvimdiff | ecmerge | diffuse)
+ emerge | vimdiff | gvimdiff | ecmerge | diffuse | araxis)
;; # happy
tortoisemerge)
if ! merge_mode; then
@@ -228,8 +231,8 @@ run_merge_tool () {
fi
check_unchanged
else
- "$merge_tool_path" "$LOCAL" "$REMOTE" \
- --default --mode=merge2 --to="$MERGED"
+ "$merge_tool_path" --default --mode=diff2 \
+ "$LOCAL" "$REMOTE"
fi
;;
emerge)
@@ -248,7 +251,7 @@ run_merge_tool () {
status=$?
else
"$merge_tool_path" -f emerge-files-command \
- "$LOCAL" "$REMOTE" "$(basename "$MERGED")"
+ "$LOCAL" "$REMOTE"
fi
;;
tortoisemerge)
@@ -263,6 +266,24 @@ run_merge_tool () {
status=1
fi
;;
+ araxis)
+ if merge_mode; then
+ touch "$BACKUP"
+ if $base_present; then
+ "$merge_tool_path" -wait -merge -3 -a1 \
+ "$BASE" "$LOCAL" "$REMOTE" "$MERGED" \
+ >/dev/null 2>&1
+ else
+ "$merge_tool_path" -wait -2 \
+ "$LOCAL" "$REMOTE" "$MERGED" \
+ >/dev/null 2>&1
+ fi
+ check_unchanged
+ else
+ "$merge_tool_path" -wait -2 "$LOCAL" "$REMOTE" \
+ >/dev/null 2>&1
+ fi
+ ;;
*)
merge_tool_cmd="$(get_merge_tool_cmd "$1")"
if test -z "$merge_tool_cmd"; then
@@ -302,7 +323,7 @@ guess_merge_tool () {
else
tools="opendiff kdiff3 tkdiff xxdiff meld $tools"
fi
- tools="$tools gvimdiff diffuse ecmerge"
+ tools="$tools gvimdiff diffuse ecmerge araxis"
fi
if echo "${VISUAL:-$EDITOR}" | grep emacs > /dev/null 2>&1; then
# $EDITOR is emacs so add emerge as a candidate
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 314cd36..f96d887 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -420,7 +420,7 @@ do_next () {
NEWHEAD=$(git rev-parse HEAD) &&
case $HEADNAME in
refs/*)
- message="$GIT_REFLOG_ACTION: $HEADNAME onto $SHORTONTO)" &&
+ message="$GIT_REFLOG_ACTION: $HEADNAME onto $SHORTONTO" &&
git update-ref -m "$message" $HEADNAME $NEWHEAD $OLDHEAD &&
git symbolic-ref HEAD $HEADNAME
;;
diff --git a/git-send-email.perl b/git-send-email.perl
index cccbf45..4c795a4 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -210,6 +210,7 @@ my %config_settings = (
"envelopesender" => \$envelope_sender,
"multiedit" => \$multiedit,
"confirm" => \$confirm,
+ "from" => \$sender,
);
# Handle Uncouth Termination
@@ -409,7 +410,7 @@ my %parse_alias = (
mailrc => sub { my $fh = shift; while (<$fh>) {
if (/^alias\s+(\S+)\s+(.*)$/) {
# spaces delimit multiple addresses
- $aliases{$1} = [ split(/\s+/, $2) ];
+ $aliases{$1} = [ quotewords('\s+', 0, $2) ];
}}},
pine => sub { my $fh = shift; my $f='\t[^\t]*';
for (my $x = ''; defined($x); $x = $_) {
@@ -537,7 +538,7 @@ if ($compose) {
print C <<EOT;
From $tpl_sender # This line is ignored.
-GIT: Lines beginning in "GIT: " will be removed.
+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:
@@ -552,8 +553,6 @@ EOT
}
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 {
@@ -570,7 +569,7 @@ EOT
my $in_body = 0;
my $summary_empty = 1;
while(<C>) {
- next if m/^GIT: /;
+ next if m/^GIT:/;
if ($in_body) {
$summary_empty = 0 unless (/^\n$/);
} elsif (/^\n$/) {
@@ -578,7 +577,7 @@ EOT
if ($need_8bit_cte) {
print C2 "MIME-Version: 1.0\n",
"Content-Type: text/plain; ",
- "charset=utf-8\n",
+ "charset=UTF-8\n",
"Content-Transfer-Encoding: 8bit\n";
}
} elsif (/^MIME-Version:/i) {
@@ -767,12 +766,20 @@ sub unquote_rfc2047 {
sub quote_rfc2047 {
local $_ = shift;
- my $encoding = shift || 'utf-8';
+ my $encoding = shift || 'UTF-8';
s/([^-a-zA-Z0-9!*+\/])/sprintf("=%02X", ord($1))/eg;
s/(.*)/=\?$encoding\?q\?$1\?=/;
return $_;
}
+sub is_rfc2047_quoted {
+ my $s = shift;
+ my $token = '[^][()<>@,;:"\/?.= \000-\037\177-\377]+';
+ my $encoded_text = '[!->@-~]+';
+ length($s) <= 75 &&
+ $s =~ m/^(?:"[[:ascii:]]*"|=\?$token\?$token\?$encoded_text\?=)$/o;
+}
+
# use the simplest quoting being able to handle the recipient
sub sanitize_address
{
@@ -784,7 +791,7 @@ sub sanitize_address
}
# if recipient_name is already quoted, do nothing
- if ($recipient_name =~ /^("[[:ascii:]]*"|=\?utf-8\?q\?.*\?=)$/) {
+ if (is_rfc2047_quoted($recipient_name)) {
return $recipient;
}
@@ -804,6 +811,10 @@ sub sanitize_address
}
+# Returns 1 if the message was sent, and 0 otherwise.
+# In actuality, the whole program dies when a there
+# is an error sending a message.
+
sub send_message
{
my @recipients = unique_email_list(@to);
@@ -872,7 +883,7 @@ X-Mailer: git-send-email $gitversion
default => $ask_default);
die "Send this email reply required" unless defined $_;
if (/^n/i) {
- return;
+ return 0;
} elsif (/^q/i) {
cleanup_compose_files();
exit(0);
@@ -953,7 +964,7 @@ X-Mailer: git-send-email $gitversion
$smtp->data or die $smtp->message;
$smtp->datasend("$header\n$message") or die $smtp->message;
$smtp->dataend() or die $smtp->message;
- $smtp->ok or die "Failed to send $subject\n".$smtp->message;
+ $smtp->code =~ /250|200/ or die "Failed to send $subject\n".$smtp->message;
}
if ($quiet) {
printf (($dry_run ? "Dry-" : "")."Sent %s\n", $subject);
@@ -974,6 +985,8 @@ X-Mailer: git-send-email $gitversion
print "Result: OK\n";
}
}
+
+ return 1;
}
$reply_to = $initial_reply_to;
@@ -1134,10 +1147,10 @@ foreach my $t (@files) {
@cc = (@initial_cc, @cc);
- send_message();
+ my $message_was_sent = send_message();
# set up for the next message
- if ($chain_reply_to || !defined $reply_to || length($reply_to) == 0) {
+ if ($message_was_sent and $chain_reply_to || not defined $reply_to || length($reply_to) == 0) {
$reply_to = $message_id;
if (length $references > 0) {
$references .= "\n $message_id";
diff --git a/git-sh-setup.sh b/git-sh-setup.sh
index 8382339..80acb7d 100755
--- a/git-sh-setup.sh
+++ b/git-sh-setup.sh
@@ -11,6 +11,34 @@
# exporting it.
unset CDPATH
+git_broken_path_fix () {
+ case ":$PATH:" in
+ *:$1:*) : ok ;;
+ *)
+ PATH=$(
+ SANE_TOOL_PATH="$1"
+ IFS=: path= sep=
+ set x $PATH
+ shift
+ for elem
+ do
+ case "$SANE_TOOL_PATH:$elem" in
+ (?*:/bin | ?*:/usr/bin)
+ path="$path$sep$SANE_TOOL_PATH"
+ sep=:
+ SANE_TOOL_PATH=
+ esac
+ path="$path$sep$elem"
+ sep=:
+ done
+ echo "$path"
+ )
+ ;;
+ esac
+}
+
+# @@BROKEN_PATH_FIX@@
+
die() {
echo >&2 "$@"
exit 1
diff --git a/git-stash.sh b/git-stash.sh
index b9ace99..e6a5867 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -3,8 +3,8 @@
dashless=$(basename "$0" | sed -e 's/-/ /')
USAGE="list [<options>]
- or: $dashless (show | drop | pop ) [<stash>]
- or: $dashless apply [--index] [<stash>]
+ or: $dashless ( show | drop ) [<stash>]
+ or: $dashless ( pop | apply ) [--index] [<stash>]
or: $dashless branch <branchname> [<stash>]
or: $dashless [save [--keep-index] [<message>]]
or: $dashless clear"
diff --git a/git-submodule.sh b/git-submodule.sh
index f384c6b..19a3a84 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -15,6 +15,7 @@ require_work_tree
command=
branch=
quiet=
+reference=
cached=
nofetch=
update=
@@ -92,6 +93,7 @@ module_clone()
{
path=$1
url=$2
+ reference="$3"
# If there already is a directory at the submodule path,
# expect it to be empty (since that is the default checkout
@@ -107,7 +109,12 @@ module_clone()
test -e "$path" &&
die "A file already exist at path '$path'"
- git-clone -n "$url" "$path" ||
+ if test -n "$reference"
+ then
+ git-clone "$reference" -n "$url" "$path"
+ else
+ git-clone -n "$url" "$path"
+ fi ||
die "Clone of '$url' into submodule path '$path' failed"
}
@@ -132,6 +139,15 @@ cmd_add()
-q|--quiet)
quiet=1
;;
+ --reference)
+ case "$2" in '') usage ;; esac
+ reference="--reference=$2"
+ shift
+ ;;
+ --reference=*)
+ reference="$1"
+ shift
+ ;;
--)
shift
break
@@ -204,7 +220,7 @@ cmd_add()
git config submodule."$path".url "$url"
else
- module_clone "$path" "$realrepo" || exit
+ module_clone "$path" "$realrepo" "$reference" || exit
(
unset GIT_DIR
cd "$path" &&
@@ -320,8 +336,8 @@ cmd_update()
quiet=1
;;
-i|--init)
+ init=1
shift
- cmd_init "$@" || return
;;
-N|--no-fetch)
shift
@@ -331,6 +347,15 @@ cmd_update()
shift
update="rebase"
;;
+ --reference)
+ case "$2" in '') usage ;; esac
+ reference="--reference=$2"
+ shift 2
+ ;;
+ --reference=*)
+ reference="$1"
+ shift
+ ;;
--)
shift
break
@@ -344,6 +369,11 @@ cmd_update()
esac
done
+ if test -n "$init"
+ then
+ cmd_init "--" "$@" || return
+ fi
+
module_list "$@" |
while read mode sha1 stage path
do
@@ -362,7 +392,7 @@ cmd_update()
if ! test -d "$path"/.git -o -f "$path"/.git
then
- module_clone "$path" "$url" || exit
+ module_clone "$path" "$url" "$reference"|| exit
subsha1=
else
subsha1=$(unset GIT_DIR; cd "$path" &&
diff --git a/git-svn.perl b/git-svn.perl
index c5965c9..3301797 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -5,7 +5,7 @@ use warnings;
use strict;
use vars qw/ $AUTHOR $VERSION
$sha1 $sha1_short $_revision $_repository
- $_q $_authors %users/;
+ $_q $_authors $_authors_prog %users/;
$AUTHOR = 'Eric Wong <normalperson@yhbt.net>';
$VERSION = '@@GIT_VERSION@@';
@@ -39,6 +39,7 @@ use Digest::MD5;
use IO::File qw//;
use File::Basename qw/dirname basename/;
use File::Path qw/mkpath/;
+use File::Spec;
use Getopt::Long qw/:config gnu_getopt no_ignore_case auto_abbrev/;
use IPC::Open3;
use Git;
@@ -76,6 +77,7 @@ my %remote_opts = ( 'username=s' => \$Git::SVN::Prompt::_username,
'ignore-paths=s' => \$SVN::Git::Fetcher::_ignore_regex );
my %fc_opts = ( 'follow-parent|follow!' => \$Git::SVN::_follow_parent,
'authors-file|A=s' => \$_authors,
+ 'authors-prog=s' => \$_authors_prog,
'repack:i' => \$Git::SVN::_repack,
'noMetadata' => \$Git::SVN::_no_metadata,
'useSvmProps' => \$Git::SVN::_use_svm_props,
@@ -147,7 +149,7 @@ my %cmd = (
'dry-run|n' => \$_dry_run } ],
'set-tree' => [ \&cmd_set_tree,
"Set an SVN repository to a git tree-ish",
- { 'stdin|' => \$_stdin, %cmt_opts, %fc_opts, } ],
+ { 'stdin' => \$_stdin, %cmt_opts, %fc_opts, } ],
'create-ignore' => [ \&cmd_create_ignore,
'Create a .gitignore per svn:ignore',
{ 'revision|r=i' => \$_revision
@@ -263,6 +265,9 @@ usage(0) if $_help;
version() if $_version;
usage(1) unless defined $cmd;
load_authors() if $_authors;
+if (defined $_authors_prog) {
+ $_authors_prog = "'" . File::Spec->rel2abs($_authors_prog) . "'";
+}
unless ($cmd =~ /^(?:clone|init|multi-init|commit-diff)$/) {
Git::SVN::Migration::migration_check();
@@ -361,6 +366,7 @@ sub cmd_clone {
$path = basename($url) if !defined $path || !length $path;
cmd_init($url, $path);
Git::SVN::fetch_all($Git::SVN::default_repo_id);
+ command_oneline('config', 'svn.authorsfile', $_authors) if $_authors;
}
sub cmd_init {
@@ -1172,16 +1178,27 @@ sub get_commit_entry {
}
rename $commit_editmsg, $commit_msg or croak $!;
{
+ require Encode;
# 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');
+ my $enc = Git::config('i18n.commitencoding') || 'UTF-8';
+ my $msg = $log_entry{log};
+
+ eval { $msg = Encode::decode($enc, $msg, 1) };
+ if ($@) {
+ die "Could not decode as $enc:\n", $msg,
+ "\nPerhaps you need to set i18n.commitencoding\n";
}
+
+ eval { $msg = Encode::encode('UTF-8', $msg, 1) };
+ die "Could not encode as UTF-8:\n$msg\n" if $@;
+
+ $log_entry{log} = $msg;
+
close $log_fh or croak $!;
}
unlink $commit_msg;
@@ -2663,12 +2680,33 @@ sub other_gs {
$gs
}
+sub call_authors_prog {
+ my ($orig_author) = @_;
+ my $author = `$::_authors_prog $orig_author`;
+ if ($? != 0) {
+ die "$::_authors_prog failed with exit code $?\n"
+ }
+ if ($author =~ /^\s*(.+?)\s*<(.*)>\s*$/) {
+ my ($name, $email) = ($1, $2);
+ $email = undef if length $2 == 0;
+ return [$name, $email];
+ } else {
+ die "Author: $orig_author: $::_authors_prog returned "
+ . "invalid author format: $author\n";
+ }
+}
+
sub check_author {
my ($author) = @_;
if (!defined $author || length $author == 0) {
$author = '(no author)';
- } elsif (defined $::_authors && ! defined $::users{$author}) {
- die "Author: $author not defined in $::_authors file\n";
+ }
+ if (!defined $::users{$author}) {
+ if (defined $::_authors_prog) {
+ $::users{$author} = call_authors_prog($author);
+ } elsif (defined $::_authors) {
+ die "Author: $author not defined in $::_authors file\n";
+ }
}
$author;
}
@@ -4438,6 +4476,7 @@ sub gs_fetch_loop_common {
my ($min, $max) = ($base, $head < $base + $inc ? $head : $base + $inc);
my $longest_path = longest_common_path($gsv, $globs);
my $ra_url = $self->{url};
+ my $find_trailing_edge;
while (1) {
my %revs;
my $err;
@@ -4455,8 +4494,10 @@ sub gs_fetch_loop_common {
sub { $revs{$_[1]} = _cb(@_) });
if ($err) {
print "Checked through r$max\r";
+ } else {
+ $find_trailing_edge = 1;
}
- if ($err && $max >= $head) {
+ if ($err and $find_trailing_edge) {
print STDERR "Path '$longest_path' ",
"was probably deleted:\n",
$err->expanded_message,
@@ -4468,13 +4509,14 @@ sub gs_fetch_loop_common {
my $ok;
$self->get_log([$longest_path], $min, $hi,
0, 1, 1, sub {
- $ok ||= $_[1];
+ $ok = $_[1];
$revs{$_[1]} = _cb(@_) });
if ($ok) {
print STDERR "r$min .. r$ok OK\n";
last;
}
}
+ $find_trailing_edge = 0;
}
$SVN::Error::handler = $err_handler;
diff --git a/git.c b/git.c
index cc5aaa7..7d7f949 100644
--- a/git.c
+++ b/git.c
@@ -47,7 +47,7 @@ static void commit_pager_choice(void) {
}
}
-static int handle_options(const char*** argv, int* argc, int* envchanged)
+static int handle_options(const char ***argv, int *argc, int *envchanged)
{
int handled = 0;
@@ -136,7 +136,7 @@ static int handle_alias(int *argcp, const char ***argv)
int envchanged = 0, ret = 0, saved_errno = errno;
const char *subdir;
int count, option_count;
- const char** new_argv;
+ const char **new_argv;
const char *alias_command;
char *alias_string;
int unused_nongit;
@@ -187,10 +187,10 @@ static int handle_alias(int *argcp, const char ***argv)
"trace: alias expansion: %s =>",
alias_command);
- new_argv = xrealloc(new_argv, sizeof(char*) *
+ new_argv = xrealloc(new_argv, sizeof(char *) *
(count + *argcp + 1));
/* insert after command name */
- memcpy(new_argv + count, *argv + 1, sizeof(char*) * *argcp);
+ memcpy(new_argv + count, *argv + 1, sizeof(char *) * *argcp);
new_argv[count+*argcp] = NULL;
*argv = new_argv;
@@ -327,6 +327,7 @@ static void handle_internal_command(int argc, const char **argv)
{ "merge-ours", cmd_merge_ours, RUN_SETUP },
{ "merge-recursive", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
{ "merge-subtree", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
+ { "mktree", cmd_mktree, RUN_SETUP },
{ "mv", cmd_mv, RUN_SETUP | NEED_WORK_TREE },
{ "name-rev", cmd_name_rev, RUN_SETUP },
{ "pack-objects", cmd_pack_objects, RUN_SETUP },
diff --git a/gitk-git/gitk b/gitk-git/gitk
index 1773ae6..1a7887b 100644
--- a/gitk-git/gitk
+++ b/gitk-git/gitk
@@ -521,7 +521,7 @@ proc updatecommits {} {
incr viewactive($view)
set viewcomplete($view) 0
reset_pending_select {}
- nowbusy $view "Reading"
+ nowbusy $view [mc "Reading"]
if {$showneartags} {
getallcommits
}
@@ -1830,7 +1830,9 @@ proc setoptions {} {
option add *Button.font uifont startupFile
option add *Checkbutton.font uifont startupFile
option add *Radiobutton.font uifont startupFile
- option add *Menu.font uifont startupFile
+ if {[tk windowingsystem] ne "aqua"} {
+ option add *Menu.font uifont startupFile
+ }
option add *Menubutton.font uifont startupFile
option add *Label.font uifont startupFile
option add *Message.font uifont startupFile
@@ -1910,8 +1912,8 @@ proc makewindow {} {
# The "mc" arguments here are purely so that xgettext
# sees the following string as needing to be translated
- makemenu .bar {
- {mc "File" cascade {
+ set file {
+ mc "File" cascade {
{mc "Update" command updatecommits -accelerator F5}
{mc "Reload" command reloadcommits -accelerator Meta1-F5}
{mc "Reread references" command rereadrefs}
@@ -1921,21 +1923,41 @@ proc makewindow {} {
{xx "" separator}
{mc "Quit" command doquit -accelerator Meta1-Q}
}}
- {mc "Edit" cascade {
+ set edit {
+ mc "Edit" cascade {
{mc "Preferences" command doprefs}
}}
- {mc "View" cascade {
+ set view {
+ 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 {
+ if {[tk windowingsystem] ne "aqua"} {
+ set help {
+ mc "Help" cascade {
{mc "About gitk" command about}
{mc "Key bindings" command keys}
}}
+ set bar [list $file $edit $view $help]
+ } else {
+ proc ::tk::mac::ShowPreferences {} {doprefs}
+ proc ::tk::mac::Quit {} {doquit}
+ lset file end [lreplace [lindex $file end] end-1 end]
+ set apple {
+ xx "Apple" cascade {
+ {mc "About gitk" command about}
+ {xx "" separator}
+ }}
+ set help {
+ mc "Help" cascade {
+ {mc "Key bindings" command keys}
+ }}
+ set bar [list $apple $file $view $help]
}
+ makemenu .bar $bar
. configure -menu .bar
# the gui has upper and lower half, parts of a paned window.
@@ -2229,10 +2251,16 @@ proc makewindow {} {
}
}
+ if {[info exists geometry(state)] && $geometry(state) eq "zoomed"} {
+ wm state . $geometry(state)
+ }
+
if {[tk windowingsystem] eq {aqua}} {
set M1B M1
+ set ::BM "3"
} else {
set M1B Control
+ set ::BM "2"
}
bind .pwbottom <Configure> {resizecdetpanes %W %w}
@@ -2250,10 +2278,14 @@ proc makewindow {} {
set delta [expr {- (%D)}]
allcanvs yview scroll $delta units
}
+ bindall <Shift-MouseWheel> {
+ set delta [expr {- (%D)}]
+ $canv xview scroll $delta units
+ }
}
}
- bindall <2> "canvscan mark %W %x %y"
- bindall <B2-Motion> "canvscan dragto %W %x %y"
+ bindall <$::BM> "canvscan mark %W %x %y"
+ bindall <B$::BM-Motion> "canvscan dragto %W %x %y"
bindkey <Home> selfirstline
bindkey <End> sellastline
bind . <Key-Up> "selnextline -1"
@@ -2285,6 +2317,7 @@ proc makewindow {} {
bindkey d "$ctext yview scroll 18 units"
bindkey u "$ctext yview scroll -18 units"
bindkey / {focus $fstring}
+ bindkey <Key-KP_Divide> {focus $fstring}
bindkey <Key-Return> {dofind 1 1}
bindkey ? {dofind -1 1}
bindkey f nextfile
@@ -2331,6 +2364,10 @@ proc makewindow {} {
{mc "Create new branch" command mkbranch}
{mc "Cherry-pick this commit" command cherrypick}
{mc "Reset HEAD branch to here" command resethead}
+ {mc "Mark this commit" command markhere}
+ {mc "Return to mark" command gotomark}
+ {mc "Find descendant of this and mark" command find_common_desc}
+ {mc "Compare with marked commit" command compare_commits}
}
$rowctxmenu configure -tearoff 0
@@ -2487,6 +2524,9 @@ proc savestuff {w} {
if {![winfo viewable .]} return
catch {
set f [open "~/.gitk-new" w]
+ if {$::tcl_platform(platform) eq {windows}} {
+ file attributes "~/.gitk-new" -hidden true
+ }
puts $f [list set mainfont $mainfont]
puts $f [list set textfont $textfont]
puts $f [list set uifont $uifont]
@@ -2512,6 +2552,7 @@ proc savestuff {w} {
puts $f [list set perfile_attrs $perfile_attrs]
puts $f "set geometry(main) [wm geometry .]"
+ puts $f "set geometry(state) [wm state .]"
puts $f "set geometry(topwidth) [winfo width .tf]"
puts $f "set geometry(topheight) [winfo height .tf]"
puts $f "set geometry(pwsash0) \"[.tf.histframe.pwclist sash coord 0]\""
@@ -3204,9 +3245,8 @@ proc external_diff {} {
set difftofile [external_diff_get_one_file $diffidto $flist_menu_file $diffdir]
if {$difffromfile ne {} && $difftofile ne {}} {
- set cmd [concat | [shellsplit $extdifftool] \
- [list $difffromfile $difftofile]]
- if {[catch {set fl [open $cmd r]} err]} {
+ set cmd [list [shellsplit $extdifftool] $difffromfile $difftofile]
+ if {[catch {set fl [open |$cmd r]} err]} {
file delete -force $diffdir
error_popup "$extdifftool: [mc "command failed:"] $err"
} else {
@@ -3737,7 +3777,7 @@ proc editview {} {
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)"
+ vieweditor $top $curview "[mc "Gitk: edit view"] $viewname($curview)"
}
proc vieweditor {top n title} {
@@ -4046,7 +4086,7 @@ proc ishighlighted {id} {
}
proc bolden {id font} {
- global canv linehtag currentid boldids need_redisplay
+ global canv linehtag currentid boldids need_redisplay markedid
# need_redisplay = 1 means the display is stale and about to be redrawn
if {$need_redisplay} return
@@ -4059,6 +4099,9 @@ proc bolden {id font} {
-fill [$canv cget -selectbackground]]
$canv lower $t
}
+ if {[info exists markedid] && $id eq $markedid} {
+ make_idmark $id
+ }
}
proc bolden_name {id font} {
@@ -5563,7 +5606,7 @@ proc drawcmittext {id row col} {
global cmitlisted commitinfo rowidlist parentlist
global rowtextx idpos idtags idheads idotherrefs
global linehtag linentag linedtag selectedline
- global canvxmax boldids boldnameids fgcolor
+ global canvxmax boldids boldnameids fgcolor markedid
global mainheadid nullid nullid2 circleitem circlecolors ctxbut
# listed is 0 for boundary, 1 for normal, 2 for negative, 3 for left, 4 for right
@@ -5645,6 +5688,9 @@ proc drawcmittext {id row col} {
if {$selectedline == $row} {
make_secsel $id
}
+ if {[info exists markedid] && $markedid eq $id} {
+ make_idmark $id
+ }
set xr [expr {$xt + [font measure $font $headline]}]
if {$xr > $canvxmax} {
set canvxmax $xr
@@ -6443,6 +6489,17 @@ proc setlink {id lk} {
}
}
+proc appendshortlink {id {pre {}} {post {}}} {
+ global ctext linknum
+
+ $ctext insert end $pre
+ $ctext tag delete link$linknum
+ $ctext insert end [string range $id 0 7] link$linknum
+ $ctext insert end $post
+ setlink $id link$linknum
+ incr linknum
+}
+
proc makelink {id} {
global pendinglinks
@@ -6499,7 +6556,7 @@ proc appendrefs {pos ids var} {
}
}
if {[llength $tags] > $maxrefs} {
- $ctext insert $pos "many ([llength $tags])"
+ $ctext insert $pos "[mc "many"] ([llength $tags])"
} else {
set tags [lsort -index 0 -decreasing $tags]
set sep {}
@@ -6586,6 +6643,16 @@ proc make_secsel {id} {
$canv3 lower $t
}
+proc make_idmark {id} {
+ global linehtag canv fgcolor
+
+ if {![info exists linehtag($id)]} return
+ $canv delete markid
+ set t [eval $canv create rect [$canv bbox $linehtag($id)] \
+ -tags markid -outline $fgcolor]
+ $canv raise $t
+}
+
proc selectline {l isnew {desired_loc {}}} {
global canv ctext commitinfo selectedline
global canvy0 linespc parents children curview
@@ -7216,7 +7283,7 @@ proc getblobdiffs {ids} {
set diffnparents 0
set diffinhdr 0
set diffencoding [get_path_encoding {}]
- fconfigure $bdf -blocking 0 -encoding binary
+ fconfigure $bdf -blocking 0 -encoding binary -eofchar {}
set blobdifffd($ids) $bdf
filerun $bdf [list getblobdiffline $bdf $diffids]
}
@@ -7367,7 +7434,8 @@ proc getblobdiffline {bdf ids} {
$ctext insert end "$line\n" filesep
} else {
- set line [encoding convertfrom $diffencoding $line]
+ set line [string map {\x1A ^Z} \
+ [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"}]
@@ -7970,7 +8038,7 @@ proc mstime {} {
proc rowmenu {x y id} {
global rowctxmenu selectedline rowmenuid curview
- global nullid nullid2 fakerowmenu mainhead
+ global nullid nullid2 fakerowmenu mainhead markedid
stopfinding
set rowmenuid $id
@@ -7986,6 +8054,15 @@ proc rowmenu {x y id} {
} else {
$menu entryconfigure 7 -label [mc "Detached head: can't reset" $mainhead] -state disabled
}
+ if {[info exists markedid] && $markedid ne $id} {
+ $menu entryconfigure 9 -state normal
+ $menu entryconfigure 10 -state normal
+ $menu entryconfigure 11 -state normal
+ } else {
+ $menu entryconfigure 9 -state disabled
+ $menu entryconfigure 10 -state disabled
+ $menu entryconfigure 11 -state disabled
+ }
} else {
set menu $fakerowmenu
}
@@ -7995,6 +8072,162 @@ proc rowmenu {x y id} {
tk_popup $menu $x $y
}
+proc markhere {} {
+ global rowmenuid markedid canv
+
+ set markedid $rowmenuid
+ make_idmark $markedid
+}
+
+proc gotomark {} {
+ global markedid
+
+ if {[info exists markedid]} {
+ selbyid $markedid
+ }
+}
+
+proc replace_by_kids {l r} {
+ global curview children
+
+ set id [commitonrow $r]
+ set l [lreplace $l 0 0]
+ foreach kid $children($curview,$id) {
+ lappend l [rowofcommit $kid]
+ }
+ return [lsort -integer -decreasing -unique $l]
+}
+
+proc find_common_desc {} {
+ global markedid rowmenuid curview children
+
+ if {![info exists markedid]} return
+ if {![commitinview $markedid $curview] ||
+ ![commitinview $rowmenuid $curview]} return
+ #set t1 [clock clicks -milliseconds]
+ set l1 [list [rowofcommit $markedid]]
+ set l2 [list [rowofcommit $rowmenuid]]
+ while 1 {
+ set r1 [lindex $l1 0]
+ set r2 [lindex $l2 0]
+ if {$r1 eq {} || $r2 eq {}} break
+ if {$r1 == $r2} {
+ selectline $r1 1
+ break
+ }
+ if {$r1 > $r2} {
+ set l1 [replace_by_kids $l1 $r1]
+ } else {
+ set l2 [replace_by_kids $l2 $r2]
+ }
+ }
+ #set t2 [clock clicks -milliseconds]
+ #puts "took [expr {$t2-$t1}]ms"
+}
+
+proc compare_commits {} {
+ global markedid rowmenuid curview children
+
+ if {![info exists markedid]} return
+ if {![commitinview $markedid $curview]} return
+ addtohistory [list do_cmp_commits $markedid $rowmenuid]
+ do_cmp_commits $markedid $rowmenuid
+}
+
+proc getpatchid {id} {
+ global patchids
+
+ if {![info exists patchids($id)]} {
+ set cmd [diffcmd [list $id] {-p --root}]
+ # trim off the initial "|"
+ set cmd [lrange $cmd 1 end]
+ if {[catch {
+ set x [eval exec $cmd | git patch-id]
+ set patchids($id) [lindex $x 0]
+ }]} {
+ set patchids($id) "error"
+ }
+ }
+ return $patchids($id)
+}
+
+proc do_cmp_commits {a b} {
+ global ctext curview parents children patchids commitinfo
+
+ $ctext conf -state normal
+ clear_ctext
+ init_flist {}
+ for {set i 0} {$i < 100} {incr i} {
+ set skipa 0
+ set skipb 0
+ if {[llength $parents($curview,$a)] > 1} {
+ appendshortlink $a [mc "Skipping merge commit "] "\n"
+ set skipa 1
+ } else {
+ set patcha [getpatchid $a]
+ }
+ if {[llength $parents($curview,$b)] > 1} {
+ appendshortlink $b [mc "Skipping merge commit "] "\n"
+ set skipb 1
+ } else {
+ set patchb [getpatchid $b]
+ }
+ if {!$skipa && !$skipb} {
+ set heada [lindex $commitinfo($a) 0]
+ set headb [lindex $commitinfo($b) 0]
+ if {$patcha eq "error"} {
+ appendshortlink $a [mc "Error getting patch ID for "] \
+ [mc " - stopping\n"]
+ break
+ }
+ if {$patchb eq "error"} {
+ appendshortlink $b [mc "Error getting patch ID for "] \
+ [mc " - stopping\n"]
+ break
+ }
+ if {$patcha eq $patchb} {
+ if {$heada eq $headb} {
+ appendshortlink $a [mc "Commit "]
+ appendshortlink $b " == " " $heada\n"
+ } else {
+ appendshortlink $a [mc "Commit "] " $heada\n"
+ appendshortlink $b [mc " is the same patch as\n "] \
+ " $headb\n"
+ }
+ set skipa 1
+ set skipb 1
+ } else {
+ $ctext insert end "\n"
+ appendshortlink $a [mc "Commit "] " $heada\n"
+ appendshortlink $b [mc " differs from\n "] \
+ " $headb\n"
+ $ctext insert end [mc "- stopping\n"]
+ break
+ }
+ }
+ if {$skipa} {
+ if {[llength $children($curview,$a)] != 1} {
+ $ctext insert end "\n"
+ appendshortlink $a [mc "Commit "] \
+ [mc " has %s children - stopping\n" \
+ [llength $children($curview,$a)]]
+ break
+ }
+ set a [lindex $children($curview,$a) 0]
+ }
+ if {$skipb} {
+ if {[llength $children($curview,$b)] != 1} {
+ appendshortlink $b [mc "Commit "] \
+ [mc " has %s children - stopping\n" \
+ [llength $children($curview,$b)]]
+ break
+ }
+ set b [lindex $children($curview,$b) 0]
+ }
+ }
+ $ctext conf -state disabled
+}
+
proc diffvssel {dirn} {
global rowmenuid selectedline
@@ -8189,7 +8422,7 @@ proc domktag {} {
}
proc redrawtags {id} {
- global canv linehtag idpos currentid curview cmitlisted
+ global canv linehtag idpos currentid curview cmitlisted markedid
global canvxmax iddrawn circleitem mainheadid circlecolors
if {![commitinview $id $curview]} return
@@ -8214,6 +8447,9 @@ proc redrawtags {id} {
if {[info exists currentid] && $currentid == $id} {
make_secsel $id
}
+ if {[info exists markedid] && $markedid eq $id} {
+ make_idmark $id
+ }
}
proc mktagcan {} {
@@ -10197,7 +10433,7 @@ proc doprefs {} {
proc choose_extdiff {} {
global extdifftool
- set prog [tk_getOpenFile -title "External diff tool" -multiple false]
+ set prog [tk_getOpenFile -title [mc "External diff tool"] -multiple false]
if {$prog ne {}} {
set extdifftool $prog
}
@@ -10240,6 +10476,7 @@ proc setfg {c} {
}
allcanvs itemconf text -fill $c
$canv itemconf circle -outline $c
+ $canv itemconf markid -outline $c
}
proc prefscan {} {
@@ -10689,9 +10926,15 @@ catch {
}
}
-set mainfont {Helvetica 9}
-set textfont {Courier 9}
-set uifont {Helvetica 9 bold}
+if {[tk windowingsystem] eq "aqua"} {
+ set mainfont {{Lucida Grande} 9}
+ set textfont {Monaco 9}
+ set uifont {{Lucida Grande} 9 bold}
+} else {
+ set mainfont {Helvetica 9}
+ set textfont {Courier 9}
+ set uifont {Helvetica 9 bold}
+}
set tabstop 8
set findmergefiles 0
set maxgraphpct 50
@@ -10712,7 +10955,11 @@ set datetimeformat "%Y-%m-%d %H:%M:%S"
set autoselect 1
set perfile_attrs 0
-set extdifftool "meld"
+if {[tk windowingsystem] eq "aqua"} {
+ set extdifftool "opendiff"
+} else {
+ set extdifftool "meld"
+}
set colors {green red blue magenta darkgrey brown orange}
set bgcolor white
@@ -10883,9 +11130,33 @@ set lserial 0
set isworktree [expr {[exec git rev-parse --is-inside-work-tree] == "true"}]
setcoords
makewindow
+catch {
+ image create photo gitlogo -width 16 -height 16
+
+ image create photo gitlogominus -width 4 -height 2
+ gitlogominus put #C00000 -to 0 0 4 2
+ gitlogo copy gitlogominus -to 1 5
+ gitlogo copy gitlogominus -to 6 5
+ gitlogo copy gitlogominus -to 11 5
+ image delete gitlogominus
+
+ image create photo gitlogoplus -width 4 -height 4
+ gitlogoplus put #008000 -to 1 0 3 4
+ gitlogoplus put #008000 -to 0 1 4 3
+ gitlogo copy gitlogoplus -to 1 9
+ gitlogo copy gitlogoplus -to 6 9
+ gitlogo copy gitlogoplus -to 11 9
+ image delete gitlogoplus
+
+ image create photo gitlogo32 -width 32 -height 32
+ gitlogo32 copy gitlogo -zoom 2 2
+
+ wm iconphoto . -default gitlogo gitlogo32
+}
# wait for the window to become visible
tkwait visibility .
wm title . "[file tail $argv0]: [file tail [pwd]]"
+update
readrefs
if {$cmdline_files ne {} || $revtreeargs ne {} || $revtreeargscmd ne {}} {
diff --git a/gitk-git/po/ru.po b/gitk-git/po/ru.po
new file mode 100644
index 0000000..704eba8
--- /dev/null
+++ b/gitk-git/po/ru.po
@@ -0,0 +1,1085 @@
+#
+# Translation of gitk to Russian.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gitk\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-04-24 16:00+0200\n"
+"PO-Revision-Date: 2009-04-24 16:00+0200\n"
+"Last-Translator: Alex Riesen <raa.lkml@gmail.com>\n"
+"Language-Team: Russian\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: gitk:113
+msgid "Couldn't get list of unmerged files:"
+msgstr ""
+"Невозможно получить список файлов незавершённой операции слияния:"
+
+#: gitk:268
+msgid "Error parsing revisions:"
+msgstr "Ошибка в идентификаторе версии:"
+
+#: gitk:323
+msgid "Error executing --argscmd command:"
+msgstr "Ошибка выполнения команды заданой --argscmd:"
+
+#: gitk:336
+msgid "No files selected: --merge specified but no files are unmerged."
+msgstr ""
+"Файлы не выбраны: указан --merge, но не было найдено ни одного файла "
+"где эта операция должна быть завершена."
+
+#: gitk:339
+msgid ""
+"No files selected: --merge specified but no unmerged files are within file "
+"limit."
+msgstr ""
+"Файлы не выбраны: указан --merge, но в рамках указаного "
+"ограничения на имена файлов нет ни одного "
+"где эта операция должна быть завершена."
+
+#: gitk:361 gitk:508
+msgid "Error executing git log:"
+msgstr "Ошибка запуска git log:"
+
+#: gitk:379
+msgid "Reading"
+msgstr "Чтение"
+
+#: gitk:439 gitk:4021
+msgid "Reading commits..."
+msgstr "Чтение версий..."
+
+#: gitk:442 gitk:1560 gitk:4024
+msgid "No commits selected"
+msgstr "Ничего не выбрано"
+
+#: gitk:1436
+msgid "Can't parse git log output:"
+msgstr "Ошибка обработки вывода команды git log:"
+
+#: gitk:1656
+msgid "No commit information available"
+msgstr "Нет информации о состоянии"
+
+#: gitk:1791 gitk:1815 gitk:3814 gitk:8478 gitk:10014 gitk:10186
+msgid "OK"
+msgstr "Ok"
+
+#: gitk:1817 gitk:3816 gitk:8078 gitk:8152 gitk:8259 gitk:8308 gitk:8480
+#: gitk:10015 gitk:10187
+msgid "Cancel"
+msgstr "Отмена"
+
+#: gitk:1915
+msgid "Update"
+msgstr "Обновить"
+
+#: gitk:1916
+msgid "Reload"
+msgstr "Перечитать"
+
+#: gitk:1917
+msgid "Reread references"
+msgstr "Обновить список ссылок"
+
+#: gitk:1918
+msgid "List references"
+msgstr "Список ссылок"
+
+#: gitk:1920
+msgid "Start git gui"
+msgstr "Запустить git gui"
+
+#: gitk:1922
+msgid "Quit"
+msgstr "Завершить"
+
+#: gitk:1914
+msgid "File"
+msgstr "Файл"
+
+#: gitk:1925
+msgid "Preferences"
+msgstr "Настройки"
+
+#: gitk:1924
+msgid "Edit"
+msgstr "Редактировать"
+
+#: gitk:1928
+msgid "New view..."
+msgstr "Новое представление..."
+
+#: gitk:1929
+msgid "Edit view..."
+msgstr "Редактировать представление..."
+
+#: gitk:1930
+msgid "Delete view"
+msgstr "Удалить представление"
+
+#: gitk:1932
+msgid "All files"
+msgstr "Все файлы"
+
+#: gitk:1927 gitk:3626
+msgid "View"
+msgstr "Представление"
+
+#: gitk:1935 gitk:2609
+msgid "About gitk"
+msgstr "О gitk"
+
+#: gitk:1936
+msgid "Key bindings"
+msgstr "Назначения клавиатуры"
+
+#: gitk:1934
+msgid "Help"
+msgstr "Подсказка"
+
+#: gitk:1994
+msgid "SHA1 ID: "
+msgstr "SHA1:"
+
+#: gitk:2025
+msgid "Row"
+msgstr "Строка"
+
+#: gitk:2056
+msgid "Find"
+msgstr "Поиск"
+
+#: gitk:2057
+msgid "next"
+msgstr "След."
+
+#: gitk:2058
+msgid "prev"
+msgstr "Пред."
+
+#: gitk:2059
+msgid "commit"
+msgstr "состояние"
+
+#: gitk:2062 gitk:2064 gitk:4179 gitk:4202 gitk:4226 gitk:6164 gitk:6236
+#: gitk:6320
+msgid "containing:"
+msgstr "содержащее:"
+
+#: gitk:2065 gitk:3117 gitk:3122 gitk:4254
+msgid "touching paths:"
+msgstr "касательно файлов:"
+
+#: gitk:2066 gitk:4259
+msgid "adding/removing string:"
+msgstr "добавив/удалив строку:"
+
+#: gitk:2075 gitk:2077
+msgid "Exact"
+msgstr "Точно"
+
+#: gitk:2077 gitk:4334 gitk:6132
+msgid "IgnCase"
+msgstr "Игнорировать большие/маленькие"
+
+#: gitk:2077 gitk:4228 gitk:4332 gitk:6128
+msgid "Regexp"
+msgstr "Регулярные выражения"
+
+#: gitk:2079 gitk:2080 gitk:4353 gitk:4383 gitk:4390 gitk:6256 gitk:6324
+msgid "All fields"
+msgstr "Во всех полях"
+
+#: gitk:2080 gitk:4351 gitk:4383 gitk:6195
+msgid "Headline"
+msgstr "Заголовок"
+
+#: gitk:2081 gitk:4351 gitk:6195 gitk:6324 gitk:6737
+msgid "Comments"
+msgstr "Комментарии"
+
+#: gitk:2081 gitk:4351 gitk:4355 gitk:4390 gitk:6195 gitk:6672 gitk:7923
+#: gitk:7938
+msgid "Author"
+msgstr "Автор"
+
+#: gitk:2081 gitk:4351 gitk:6195 gitk:6674
+msgid "Committer"
+msgstr "Сохранивший состояние"
+
+#: gitk:2110
+msgid "Search"
+msgstr "Найти"
+
+#: gitk:2117
+msgid "Diff"
+msgstr "Сравнить"
+
+#: gitk:2119
+msgid "Old version"
+msgstr "Старая версия"
+
+#: gitk:2121
+msgid "New version"
+msgstr "Новая версия"
+
+#: gitk:2123
+msgid "Lines of context"
+msgstr "Строк контекста"
+
+#: gitk:2133
+msgid "Ignore space change"
+msgstr "Игнорировать пробелы"
+
+#: gitk:2191
+msgid "Patch"
+msgstr "Патч"
+
+#: gitk:2193
+msgid "Tree"
+msgstr "Файлы"
+
+#: gitk:2326 gitk:2339
+msgid "Diff this -> selected"
+msgstr "Сравнить это состояние с выделеным"
+
+#: gitk:2327 gitk:2340
+msgid "Diff selected -> this"
+msgstr "Сравнить выделеное с этим состоянием"
+
+#: gitk:2328 gitk:2341
+msgid "Make patch"
+msgstr "Создать патч"
+
+#: gitk:2329 gitk:8136
+msgid "Create tag"
+msgstr "Создать метку"
+
+#: gitk:2330 gitk:8239
+msgid "Write commit to file"
+msgstr "Сохранить изменения в файл"
+
+#: gitk:2331 gitk:8296
+msgid "Create new branch"
+msgstr "Создать ветвь"
+
+#: gitk:2332
+msgid "Cherry-pick this commit"
+msgstr "Скопировать это состояние"
+
+#: gitk:2333
+msgid "Reset HEAD branch to here"
+msgstr "Установить HEAD на это состояние"
+
+#: gitk:2347
+msgid "Check out this branch"
+msgstr "Перейти на эту ветвь"
+
+#: gitk:2348
+msgid "Remove this branch"
+msgstr "Удалить эту ветвь"
+
+#: gitk:2355
+msgid "Highlight this too"
+msgstr "Подсветить этот тоже"
+
+#: gitk:2356
+msgid "Highlight this only"
+msgstr "Подсветить только этот"
+
+#: gitk:2357
+msgid "External diff"
+msgstr "Программа сравнения"
+
+#: gitk:2358
+msgid "Blame parent commit"
+msgstr "Аннотировать родительское состояние"
+
+#: gitk:2365
+msgid "Show origin of this line"
+msgstr "Показать источник этой строки"
+
+#: gitk:2366
+msgid "Run git gui blame on this line"
+msgstr "Запустить git gui blame для этой строки"
+
+#: gitk:2611
+msgid ""
+"\n"
+"Gitk - a commit viewer for git\n"
+"\n"
+"Copyright © 2005-2008 Paul Mackerras\n"
+"\n"
+"Use and redistribute under the terms of the GNU General Public License"
+msgstr ""
+"\n"
+"Gitk - программа просмотра истории репозиториев Git\n"
+"\n"
+"Copyright (c) 2005-2008 Paul Mackerras\n"
+"\n"
+"Использование и распространение согласно условиям GNU General Public License"
+
+#: gitk:2619 gitk:2681 gitk:8661
+msgid "Close"
+msgstr "Закрыть"
+
+#: gitk:2638
+msgid "Gitk key bindings"
+msgstr "Назначения клавиатуры в Gitk"
+
+#: gitk:2641
+msgid "Gitk key bindings:"
+msgstr "Назначения клавиатуры в Gitk:"
+
+#: gitk:2643
+#, tcl-format
+msgid "<%s-Q>\t\tQuit"
+msgstr "<%s-Q>\t\tЗавершить"
+
+#: gitk:2644
+msgid "<Home>\t\tMove to first commit"
+msgstr "<Home>\t\tПерейти к первому состоянию"
+
+#: gitk:2645
+msgid "<End>\t\tMove to last commit"
+msgstr "<End>\t\tПерейти к последнему состоянию"
+
+#: gitk:2646
+msgid "<Up>, p, i\tMove up one commit"
+msgstr "<Up>, p, i\tПерейти к следующему состоянию"
+
+#: gitk:2647
+msgid "<Down>, n, k\tMove down one commit"
+msgstr "<Down>, n, k\tПерейти к предыдущему состоянию"
+
+#: gitk:2648
+msgid "<Left>, z, j\tGo back in history list"
+msgstr "<Left>, z, j\tПоказать ранее посещённое состояние"
+
+#: gitk:2649
+msgid "<Right>, x, l\tGo forward in history list"
+msgstr "<Right>, x, l\tПоказать следующее посещённое состояние"
+
+#: gitk:2650
+msgid "<PageUp>\tMove up one page in commit list"
+msgstr "<PageUp>\tПерейти на страницу выше в списке состояний"
+
+#: gitk:2651
+msgid "<PageDown>\tMove down one page in commit list"
+msgstr "<PageDown>\tПерейти на страницу ниже в списке состояний"
+
+#: gitk:2652
+#, tcl-format
+msgid "<%s-Home>\tScroll to top of commit list"
+msgstr "<%s-Home>\tПоказать начало списка состояний"
+
+#: gitk:2653
+#, tcl-format
+msgid "<%s-End>\tScroll to bottom of commit list"
+msgstr "<%s-End>\tПоказать конец списка состояний"
+
+#: gitk:2654
+#, tcl-format
+msgid "<%s-Up>\tScroll commit list up one line"
+msgstr "<%s-Up>\tПровернуть список состояний вверх"
+
+#: gitk:2655
+#, tcl-format
+msgid "<%s-Down>\tScroll commit list down one line"
+msgstr "<%s-Down>\tПровернуть список состояний вниз"
+
+#: gitk:2656
+#, tcl-format
+msgid "<%s-PageUp>\tScroll commit list up one page"
+msgstr "<%s-PageUp>\tПровернуть список состояний на страницу вверх"
+
+#: gitk:2657
+#, tcl-format
+msgid "<%s-PageDown>\tScroll commit list down one page"
+msgstr "<%s-PageDown>\tПровернуть список состояний на страницу вниз"
+
+#: gitk:2658
+msgid "<Shift-Up>\tFind backwards (upwards, later commits)"
+msgstr ""
+"<Shift-Up>\tПоиск в обратном порядке (вверх, среди новых состояний)"
+
+#: gitk:2659
+msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)"
+msgstr "<Shift-Down>\tПоиск (вниз, среди старых состояний)"
+
+#: gitk:2660
+msgid "<Delete>, b\tScroll diff view up one page"
+msgstr "<Delete>, b\tПрокрутить список изменений на страницу выше"
+
+#: gitk:2661
+msgid "<Backspace>\tScroll diff view up one page"
+msgstr "<Backspace>\tПрокрутить список изменений на страницу выше"
+
+#: gitk:2662
+msgid "<Space>\t\tScroll diff view down one page"
+msgstr "<Leertaste>\t\tПрокрутить список изменений на страницу ниже"
+
+#: gitk:2663
+msgid "u\t\tScroll diff view up 18 lines"
+msgstr "u\t\tПрокрутить список изменений на 18 строк вверх"
+
+#: gitk:2664
+msgid "d\t\tScroll diff view down 18 lines"
+msgstr "d\t\tПрокрутить список изменений на 18 строк вниз"
+
+#: gitk:2665
+#, tcl-format
+msgid "<%s-F>\t\tFind"
+msgstr "<%s-F>\t\tПоиск"
+
+#: gitk:2666
+#, tcl-format
+msgid "<%s-G>\t\tMove to next find hit"
+msgstr "<%s-G>\t\tПерейти к следующему найденому состоянию"
+
+#: gitk:2667
+msgid "<Return>\tMove to next find hit"
+msgstr "<Return>\tПерейти к следующему найденому состоянию"
+
+#: gitk:2668
+msgid "/\t\tFocus the search box"
+msgstr "/\t\tПерейти к полю поиска"
+
+#: gitk:2669
+msgid "?\t\tMove to previous find hit"
+msgstr "?\t\tПерейти к предыдущему найденому состоянию"
+
+#: gitk:2670
+msgid "f\t\tScroll diff view to next file"
+msgstr "f\t\tПрокрутить список изменений к следующему файлу"
+
+#: gitk:2671
+#, tcl-format
+msgid "<%s-S>\t\tSearch for next hit in diff view"
+msgstr "<%s-S>\t\tПродолжить поиск в списке изменений"
+
+#: gitk:2672
+#, tcl-format
+msgid "<%s-R>\t\tSearch for previous hit in diff view"
+msgstr "<%s-R>\t\tПерейти к предыдущему найденому тексту в списке изменений"
+
+#: gitk:2673
+#, tcl-format
+msgid "<%s-KP+>\tIncrease font size"
+msgstr "<%s-KP+>\tУвеличить размер шрифта"
+
+#: gitk:2674
+#, tcl-format
+msgid "<%s-plus>\tIncrease font size"
+msgstr "<%s-plus>\tУвеличить размер шрифта"
+
+#: gitk:2675
+#, tcl-format
+msgid "<%s-KP->\tDecrease font size"
+msgstr "<%s-KP->\tУменьшить размер шрифта"
+
+#: gitk:2676
+#, tcl-format
+msgid "<%s-minus>\tDecrease font size"
+msgstr "<%s-minus>\tУменьшить размер шрифта"
+
+#: gitk:2677
+msgid "<F5>\t\tUpdate"
+msgstr "<F5>\t\tОбновить"
+
+#: gitk:3132
+#, tcl-format
+msgid "Error getting \"%s\" from %s:"
+msgstr "Ошибка получения \"%s\" из %s:"
+
+#: gitk:3189 gitk:3198
+#, tcl-format
+msgid "Error creating temporary directory %s:"
+msgstr "Ошибка создания временного каталога %s:"
+
+#: gitk:3211
+msgid "command failed:"
+msgstr "ошибка выполнения команды:"
+
+#: gitk:3357
+msgid "No such commit"
+msgstr "Состояние не найдено"
+
+#: gitk:3371
+msgid "git gui blame: command failed:"
+msgstr "git gui blame: ошибка выполнения команды:"
+
+#: gitk:3402
+#, tcl-format
+msgid "Couldn't read merge head: %s"
+msgstr "Ошибка чтения MERGE_HEAD: %s"
+
+#: gitk:3410
+#, tcl-format
+msgid "Error reading index: %s"
+msgstr "Ошибка чтения индекса: %s"
+
+#: gitk:3435
+#, tcl-format
+msgid "Couldn't start git blame: %s"
+msgstr "Ошибка запуска git blame: %s"
+
+#: gitk:3438 gitk:6163
+msgid "Searching"
+msgstr "Поиск"
+
+#: gitk:3470
+#, tcl-format
+msgid "Error running git blame: %s"
+msgstr "Ошибка выполнения git blame: %s"
+
+#: gitk:3498
+#, tcl-format
+msgid "That line comes from commit %s, which is not in this view"
+msgstr ""
+"Эта строка принадлежит состоянию %s, которое не показано в этом "
+"представлении"
+
+#: gitk:3512
+msgid "External diff viewer failed:"
+msgstr "Ошибка выполнения программы сравнения:"
+
+#: gitk:3630
+msgid "Gitk view definition"
+msgstr "Gitk определение представлений"
+
+#: gitk:3634
+msgid "Remember this view"
+msgstr "Запомнить представление"
+
+#: gitk:3635
+msgid "Commits to include (arguments to git log):"
+msgstr "Включить состояния (аргументы для git-log):"
+
+#: gitk:3636
+msgid "Use all refs"
+msgstr "Использовать все ветви"
+
+#: gitk:3637
+msgid "Strictly sort by date"
+msgstr "Строгая сортировка по дате"
+
+#: gitk:3638
+msgid "Mark branch sides"
+msgstr "Отметить стороны ветвей"
+
+#: gitk:3639
+msgid "Since date:"
+msgstr "С даты:"
+
+#: gitk:3640
+msgid "Until date:"
+msgstr "По дату:"
+
+#: gitk:3641
+msgid "Max count:"
+msgstr "Макс. количество:"
+
+#: gitk:3642
+msgid "Skip:"
+msgstr "Пропустить:"
+
+#: gitk:3643
+msgid "Limit to first parent"
+msgstr "Ограничить первым предком"
+
+#: gitk:3644
+msgid "Command to generate more commits to include:"
+msgstr "Дополнительная команда для списка состояний:"
+
+#: gitk:3753
+msgid "Name"
+msgstr "Имя"
+
+#: gitk:3801
+msgid "Enter files and directories to include, one per line:"
+msgstr "Файлы и каталоги для ограничения истории, по одному на строку:"
+
+#: gitk:3815
+msgid "Apply (F5)"
+msgstr "Применить (F5)"
+
+#: gitk:3853
+msgid "Error in commit selection arguments:"
+msgstr "Ошибка в параметрах выбора состояний:"
+
+#: gitk:3906 gitk:3958 gitk:4403 gitk:4417 gitk:5675 gitk:10867 gitk:10868
+msgid "None"
+msgstr "Ни одного"
+
+#: gitk:4351 gitk:6195 gitk:7925 gitk:7940
+msgid "Date"
+msgstr "Дата"
+
+#: gitk:4351 gitk:6195
+msgid "CDate"
+msgstr "Дата ввода"
+
+#: gitk:4500 gitk:4505
+msgid "Descendant"
+msgstr "Порождённое"
+
+#: gitk:4501
+msgid "Not descendant"
+msgstr "Не порождённое"
+
+#: gitk:4508 gitk:4513
+msgid "Ancestor"
+msgstr "Предок"
+
+#: gitk:4509
+msgid "Not ancestor"
+msgstr "Не предок"
+
+#: gitk:4799
+msgid "Local changes checked in to index but not committed"
+msgstr "Изменения зарегистрированные в индексе, но не сохранённые"
+
+#: gitk:4835
+msgid "Local uncommitted changes, not checked in to index"
+msgstr "Изменения в рабочем каталоге, не зарегистрированные в индексе"
+
+#: gitk:6676
+msgid "Tags:"
+msgstr "Таги:"
+
+#: gitk:6693 gitk:6699 gitk:7918
+msgid "Parent"
+msgstr "Предок"
+
+#: gitk:6704
+msgid "Child"
+msgstr "Потомок"
+
+#: gitk:6713
+msgid "Branch"
+msgstr "Ветвь"
+
+#: gitk:6716
+msgid "Follows"
+msgstr "Следует за"
+
+#: gitk:6719
+msgid "Precedes"
+msgstr "Предшествует"
+
+#: gitk:7212
+#, tcl-format
+msgid "Error getting diffs: %s"
+msgstr "Ошибка получения изменений: %s"
+
+#: gitk:7751
+msgid "Goto:"
+msgstr "Перейти к:"
+
+#: gitk:7753
+msgid "SHA1 ID:"
+msgstr "SHA1 ID:"
+
+#: gitk:7772
+#, tcl-format
+msgid "Short SHA1 id %s is ambiguous"
+msgstr "Сокращённый SHA1 идентификатор %s неоднозначен"
+
+#: gitk:7784
+#, tcl-format
+msgid "SHA1 id %s is not known"
+msgstr "SHA1 идентификатор %s не найден"
+
+#: gitk:7786
+#, tcl-format
+msgid "Tag/Head %s is not known"
+msgstr "Метка или ветвь %s не найдена"
+
+#: gitk:7928
+msgid "Children"
+msgstr "Потомки"
+
+#: gitk:7985
+#, tcl-format
+msgid "Reset %s branch to here"
+msgstr "Установить ветвь %s на это состояние"
+
+#: gitk:7987
+msgid "Detached head: can't reset"
+msgstr "Состояние не принадлежит ни одной ветви, переход невозможен"
+
+#: gitk:8019
+msgid "Top"
+msgstr "Верх"
+
+#: gitk:8020
+msgid "From"
+msgstr "От"
+
+#: gitk:8025
+msgid "To"
+msgstr "До"
+
+#: gitk:8049
+msgid "Generate patch"
+msgstr "Создать патч"
+
+#: gitk:8051
+msgid "From:"
+msgstr "От:"
+
+#: gitk:8060
+msgid "To:"
+msgstr "До:"
+
+#: gitk:8069
+msgid "Reverse"
+msgstr "В обратном порядке"
+
+#: gitk:8071 gitk:8253
+msgid "Output file:"
+msgstr "Файл для сохранения:"
+
+#: gitk:8077
+msgid "Generate"
+msgstr "Создать"
+
+#: gitk:8115
+msgid "Error creating patch:"
+msgstr "Ошибка создания патча:"
+
+#: gitk:8138 gitk:8241 gitk:8298
+msgid "ID:"
+msgstr "ID:"
+
+#: gitk:8147
+msgid "Tag name:"
+msgstr "Имя метки:"
+
+#: gitk:8151 gitk:8307
+msgid "Create"
+msgstr "Создать"
+
+#: gitk:8168
+msgid "No tag name specified"
+msgstr "Не задано имя метки"
+
+#: gitk:8172
+#, tcl-format
+msgid "Tag \"%s\" already exists"
+msgstr "Метка \"%s\" уже существует"
+
+#: gitk:8178
+msgid "Error creating tag:"
+msgstr "Ошибка создания метки:"
+
+#: gitk:8250
+msgid "Command:"
+msgstr "Команда:"
+
+#: gitk:8258
+msgid "Write"
+msgstr "Запись"
+
+#: gitk:8276
+msgid "Error writing commit:"
+msgstr "Ошибка сохранения состояния:"
+
+#: gitk:8303
+msgid "Name:"
+msgstr "Имя:"
+
+#: gitk:8326
+msgid "Please specify a name for the new branch"
+msgstr "Укажите имя для новой ветви"
+
+#: gitk:8331
+#, tcl-format
+msgid "Branch '%s' already exists. Overwrite?"
+msgstr "Ветвь '%s' уже существует. Переписать?"
+
+#: gitk:8397
+#, tcl-format
+msgid "Commit %s is already included in branch %s -- really re-apply it?"
+msgstr ""
+"Состояние %s уже принадлежит ветви %s. Продолжить операцию?"
+
+#: gitk:8402
+msgid "Cherry-picking"
+msgstr "Копирование изменений"
+
+#: gitk:8411
+#, 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 ""
+"Копирование невозможно из-за изменений в файле '%s'.\n"
+"Сохраните или отмените изменения и повторите операцию."
+
+#: gitk:8417
+msgid ""
+"Cherry-pick failed because of merge conflict.\n"
+"Do you wish to run git citool to resolve it?"
+msgstr ""
+"Копирование изменений невозможно из-за незавершённой операции "
+"слияния.\nЗапустить git citool для завершения этой операции?"
+
+#: gitk:8433
+msgid "No changes committed"
+msgstr "Изменения не сохранены"
+
+#: gitk:8459
+msgid "Confirm reset"
+msgstr "Подтвердите операцию перехода"
+
+#: gitk:8461
+#, tcl-format
+msgid "Reset branch %s to %s?"
+msgstr "Установить ветвь %s на состояние %s?"
+
+#: gitk:8465
+msgid "Reset type:"
+msgstr "Тип операции перехода:"
+
+#: gitk:8469
+msgid "Soft: Leave working tree and index untouched"
+msgstr "Лёгкий: оставить рабочий каталог и индекс неизменными"
+
+#: gitk:8472
+msgid "Mixed: Leave working tree untouched, reset index"
+msgstr ""
+"Смешаный: оставить рабочий каталог неизменным, установить индекс"
+
+#: gitk:8475
+msgid ""
+"Hard: Reset working tree and index\n"
+"(discard ALL local changes)"
+msgstr ""
+"Жесткий: переписать индекс и рабочий каталог\n"
+"(все изменения в рабочем каталоги будут потеряны)"
+
+#: gitk:8492
+msgid "Resetting"
+msgstr "Установка"
+
+#: gitk:8549
+msgid "Checking out"
+msgstr "Переход"
+
+#: gitk:8602
+msgid "Cannot delete the currently checked-out branch"
+msgstr "Активная ветвь не может быть удалена"
+
+#: gitk:8608
+#, tcl-format
+msgid ""
+"The commits on branch %s aren't on any other branch.\n"
+"Really delete branch %s?"
+msgstr ""
+"Состояния ветви %s больше не принадлежат никакой другой ветви.\n"
+"Действительно удалить ветвь %s?"
+
+#: gitk:8639
+#, tcl-format
+msgid "Tags and heads: %s"
+msgstr "Метки и ветви: %s"
+
+#: gitk:8654
+msgid "Filter"
+msgstr "Фильтровать"
+
+#: gitk:8949
+msgid ""
+"Error reading commit topology information; branch and preceding/following "
+"tag information will be incomplete."
+msgstr ""
+"Ошибка чтения истории проекта; информация о ветвях и состояниях "
+"вокруг меток (до/после) может быть неполной."
+
+#: gitk:9935
+msgid "Tag"
+msgstr "Метка"
+
+#: gitk:9935
+msgid "Id"
+msgstr "Id"
+
+#: gitk:9983
+msgid "Gitk font chooser"
+msgstr "Шрифт Gitk"
+
+#: gitk:10000
+msgid "B"
+msgstr "Ж"
+
+#: gitk:10003
+msgid "I"
+msgstr "К"
+
+#: gitk:10098
+msgid "Gitk preferences"
+msgstr "Настройки Gitk"
+
+#: gitk:10100
+msgid "Commit list display options"
+msgstr "Параметры показа списка состояний"
+
+#: gitk:10103
+msgid "Maximum graph width (lines)"
+msgstr "Макс. ширина графа (строк)"
+
+#: gitk:10107
+#, tcl-format
+msgid "Maximum graph width (% of pane)"
+msgstr "Макс. ширина графа (% ширины панели)"
+
+#: gitk:10111
+msgid "Show local changes"
+msgstr "Показывать изменения в рабочем каталоге"
+
+#: gitk:10114
+msgid "Auto-select SHA1"
+msgstr "Выделить SHA1"
+
+#: gitk:10118
+msgid "Diff display options"
+msgstr "Параметры показа изменений"
+
+#: gitk:10120
+msgid "Tab spacing"
+msgstr "Ширина табуляции"
+
+#: gitk:10123
+msgid "Display nearby tags"
+msgstr "Показывать близкие метки"
+
+#: gitk:10126
+msgid "Limit diffs to listed paths"
+msgstr "Ограничить показ изменений выбраными файлами"
+
+#: gitk:10129
+msgid "Support per-file encodings"
+msgstr "Поддержка кодировок в отдельных файлах"
+
+#: gitk:10135
+msgid "External diff tool"
+msgstr "Программа для показа изменений"
+
+#: gitk:10137
+msgid "Choose..."
+msgstr "Выберите..."
+
+#: gitk:10142
+msgid "Colors: press to choose"
+msgstr "Цвета: нажмите для выбора"
+
+#: gitk:10145
+msgid "Background"
+msgstr "Фон"
+
+#: gitk:10146 gitk:10176
+msgid "background"
+msgstr "фон"
+
+#: gitk:10149
+msgid "Foreground"
+msgstr "Передний план"
+
+#: gitk:10150
+msgid "foreground"
+msgstr "передний план"
+
+#: gitk:10153
+msgid "Diff: old lines"
+msgstr "Изменения: старый текст"
+
+#: gitk:10154
+msgid "diff old lines"
+msgstr "старый текст изменения"
+
+#: gitk:10158
+msgid "Diff: new lines"
+msgstr "Изменения: новый текст"
+
+#: gitk:10159
+msgid "diff new lines"
+msgstr "новый текст изменения"
+
+#: gitk:10163
+msgid "Diff: hunk header"
+msgstr "Изменения: заголовок блока"
+
+#: gitk:10165
+msgid "diff hunk header"
+msgstr "заголовок блока изменений"
+
+#: gitk:10169
+msgid "Marked line bg"
+msgstr "Фон выбраной строки"
+
+#: gitk:10171
+msgid "marked line background"
+msgstr "фон выбраной строки"
+
+#: gitk:10175
+msgid "Select bg"
+msgstr "Выберите фон"
+
+#: gitk:10179
+msgid "Fonts: press to choose"
+msgstr "Шрифт: нажмите для выбора"
+
+#: gitk:10181
+msgid "Main font"
+msgstr "Основной шрифт"
+
+#: gitk:10182
+msgid "Diff display font"
+msgstr "Шрифт показа изменений"
+
+#: gitk:10183
+msgid "User interface font"
+msgstr "Шрифт интерфейса"
+
+#: gitk:10210
+#, tcl-format
+msgid "Gitk: choose color for %s"
+msgstr "Gitk: выберите цвет для %s"
+
+#: gitk:10656
+msgid ""
+"Sorry, gitk cannot run with this version of Tcl/Tk.\n"
+" Gitk requires at least Tcl/Tk 8.4."
+msgstr ""
+"К сожалению gitk не может работать с этой версий Tcl/Tk.\n"
+"Требуется как минимум Tcl/Tk 8.4."
+
+#: gitk:10773
+msgid "Cannot find a git repository here."
+msgstr "Git-репозитарий не найден в текущем каталоге."
+
+#: gitk:10777
+#, tcl-format
+msgid "Cannot find the git directory \"%s\"."
+msgstr "Git-репозитарий \"%s\" не найден."
+
+#: gitk:10824
+#, tcl-format
+msgid "Ambiguous argument '%s': both revision and filename"
+msgstr "Неоднозначный аргумент '%s': существует как версия и имя файла"
+
+#: gitk:10836
+msgid "Bad arguments to gitk:"
+msgstr "Неправильные аргументы для gitk:"
+
+#: gitk:10896
+msgid "Command line"
+msgstr "Командная строка"
+
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 3f99361..1e7e2d8 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -458,8 +458,8 @@ sub filter_snapshot_fmts {
@fmts = map {
exists $known_snapshot_format_aliases{$_} ?
$known_snapshot_format_aliases{$_} : $_} @fmts;
- @fmts = grep(exists $known_snapshot_formats{$_}, @fmts);
-
+ @fmts = grep {
+ exists $known_snapshot_formats{$_} } @fmts;
}
our $GITWEB_CONFIG = $ENV{'GITWEB_CONFIG'} || "++GITWEB_CONFIG++";
@@ -690,9 +690,10 @@ sub evaluate_path_info {
# 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;
+ unless ($hash =~ s/(\Q$opt->{'suffix'}\E|\Q.$fmt\E)$//) {
+ next;
+ }
+ my $sfx = $1;
# a valid suffix was found, so set the snapshot format
# and reset the hash parameter
$input_params{'snapshot_format'} = $fmt;
@@ -828,7 +829,7 @@ if (!defined $action) {
if (!defined($actions{$action})) {
die_error(400, "Unknown action");
}
-if ($action !~ m/^(opml|project_list|project_index)$/ &&
+if ($action !~ m/^(?:opml|project_list|project_index)$/ &&
!$project) {
die_error(400, "Project needed");
}
@@ -838,7 +839,7 @@ exit;
## ======================================================================
## action links
-sub href (%) {
+sub href {
my %params = @_;
# default is to use -absolute url() i.e. $my_uri
my $href = $params{-full} ? $my_url : $my_uri;
@@ -1036,7 +1037,7 @@ sub esc_url {
}
# replace invalid utf8 character with SUBSTITUTION sequence
-sub esc_html ($;%) {
+sub esc_html {
my $str = shift;
my %opts = @_;
@@ -1235,7 +1236,7 @@ sub chop_and_escape_str {
if ($chopped eq $str) {
return esc_html($chopped);
} else {
- $str =~ s/([[:cntrl:]])/?/g;
+ $str =~ s/[[:cntrl:]]/?/g;
return $cgi->span({-title=>$str}, esc_html($chopped));
}
}
@@ -1296,7 +1297,7 @@ use constant {
};
# submodule/subproject, a commit object reference
-sub S_ISGITLINK($) {
+sub S_ISGITLINK {
my $mode = shift;
return (($mode & S_IFMT) == S_IFGITLINK)
@@ -1458,6 +1459,7 @@ sub format_subject_html {
$extra = '' unless defined($extra);
if (length($short) < length($long)) {
+ $long =~ s/[[:cntrl:]]/?/g;
return $cgi->a({-href => $href, -class => "list subject",
-title => to_utf8($long)},
esc_html($short) . $extra);
@@ -1838,7 +1840,7 @@ sub git_cmd {
# Try to avoid using this function wherever possible.
sub quote_command {
return join(' ',
- map( { my $a = $_; $a =~ s/(['!])/'\\$1'/g; "'$a'" } @_ ));
+ map { my $a = $_; $a =~ s/(['!])/'\\$1'/g; "'$a'" } @_ );
}
# get HEAD ref of given project as hash
@@ -2050,7 +2052,7 @@ sub git_get_project_description {
my $path = shift;
$git_dir = "$projectroot/$path";
- open my $fd, "$git_dir/description"
+ open my $fd, '<', "$git_dir/description"
or return git_get_project_config('description');
my $descr = <$fd>;
close $fd;
@@ -2065,18 +2067,17 @@ sub git_get_project_ctags {
my $ctags = {};
$git_dir = "$projectroot/$path";
- unless (opendir D, "$git_dir/ctags") {
- return $ctags;
- }
- foreach (grep { -f $_ } map { "$git_dir/ctags/$_" } readdir(D)) {
- open CT, $_ or next;
- my $val = <CT>;
+ opendir my $dh, "$git_dir/ctags"
+ or return $ctags;
+ foreach (grep { -f $_ } map { "$git_dir/ctags/$_" } readdir($dh)) {
+ open my $ct, '<', $_ or next;
+ my $val = <$ct>;
chomp $val;
- close CT;
+ close $ct;
my $ctag = $_; $ctag =~ s#.*/##;
$ctags->{$ctag} = $val;
}
- closedir D;
+ closedir $dh;
$ctags;
}
@@ -2129,7 +2130,7 @@ sub git_get_project_url_list {
my $path = shift;
$git_dir = "$projectroot/$path";
- open my $fd, "$git_dir/cloneurl"
+ open my $fd, '<', "$git_dir/cloneurl"
or return wantarray ?
@{ config_to_multi(git_get_project_config('url')) } :
config_to_multi(git_get_project_config('url'));
@@ -2187,7 +2188,7 @@ sub git_get_projects_list {
# 'libs%2Fklibc%2Fklibc.git H.+Peter+Anvin'
# 'linux%2Fhotplug%2Fudev.git Greg+Kroah-Hartman'
my %paths;
- open my ($fd), $projects_list or return;
+ open my $fd, '<', $projects_list or return;
PROJECT:
while (my $line = <$fd>) {
chomp $line;
@@ -2250,7 +2251,7 @@ sub git_get_project_list_from_file {
# 'libs%2Fklibc%2Fklibc.git H.+Peter+Anvin'
# 'linux%2Fhotplug%2Fudev.git Greg+Kroah-Hartman'
if (-f $projects_list) {
- open (my $fd , $projects_list);
+ open(my $fd, '<', $projects_list);
while (my $line = <$fd>) {
chomp $line;
my ($pr, $ow) = split ' ', $line;
@@ -2615,7 +2616,7 @@ sub parsed_difftree_line {
}
# parse line of git-ls-tree output
-sub parse_ls_tree_line ($;%) {
+sub parse_ls_tree_line {
my $line = shift;
my %opts = @_;
my %res;
@@ -2804,18 +2805,18 @@ sub mimetype_guess_file {
-r $mimemap or return undef;
my %mimemap;
- open(MIME, $mimemap) or return undef;
- while (<MIME>) {
+ open(my $mh, '<', $mimemap) or return undef;
+ while (<$mh>) {
next if m/^#/; # skip comments
- my ($mime, $exts) = split(/\t+/);
+ my ($mimetype, $exts) = split(/\t+/);
if (defined $exts) {
my @exts = split(/\s+/, $exts);
foreach my $ext (@exts) {
- $mimemap{$ext} = $mime;
+ $mimemap{$ext} = $mimetype;
}
}
}
- close(MIME);
+ close($mh);
$filename =~ /\.([^.]*)$/;
return $mimemap{$1};
@@ -3213,7 +3214,6 @@ sub git_print_header_div {
"\n</div>\n";
}
-#sub git_print_authorship (\%) {
sub git_print_authorship {
my $co = shift;
@@ -3269,8 +3269,7 @@ sub git_print_page_path {
print "<br/></div>\n";
}
-# sub git_print_log (\@;%) {
-sub git_print_log ($;%) {
+sub git_print_log {
my $log = shift;
my %opts = @_;
@@ -3328,7 +3327,7 @@ sub git_get_link_target {
open my $fd, "-|", git_cmd(), "cat-file", "blob", $hash
or return;
{
- local $/;
+ local $/ = undef;
$link_target = <$fd>;
}
close $fd
@@ -3341,10 +3340,7 @@ sub git_get_link_target {
# return target of link relative to top directory (top tree);
# return undef if it is not possible (including absolute links).
sub normalize_link_target {
- my ($link_target, $basedir, $hash_base) = @_;
-
- # we can normalize symlink target only if $hash_base is provided
- return unless $hash_base;
+ my ($link_target, $basedir) = @_;
# absolute symlinks (beginning with '/') cannot be normalized
return if (substr($link_target, 0, 1) eq '/');
@@ -3400,7 +3396,7 @@ sub git_print_tree_entry {
if (S_ISLNK(oct $t->{'mode'})) {
my $link_target = git_get_link_target($t->{'hash'});
if ($link_target) {
- my $norm_target = normalize_link_target($link_target, $basedir, $hash_base);
+ my $norm_target = normalize_link_target($link_target, $basedir);
if (defined $norm_target) {
print " -> " .
$cgi->a({-href => href(action=>"object", hash_base=>$hash_base,
@@ -3993,7 +3989,7 @@ sub fill_project_list_info {
($pname !~ /\/$/) &&
(-d "$projectroot/$pname")) {
$pr->{'forks'} = "-d $projectroot/$pname";
- } else {
+ } else {
$pr->{'forks'} = 0;
}
}
@@ -4803,11 +4799,10 @@ sub git_blob_plain {
-content_disposition =>
($sandbox ? 'attachment' : 'inline')
. '; filename="' . $save_as . '"');
- undef $/;
+ local $/ = undef;
binmode STDOUT, ':raw';
print <$fd>;
binmode STDOUT, ':utf8'; # as set at the beginning of gitweb.cgi
- $/ = "\n";
close $fd;
}
@@ -4909,12 +4904,16 @@ sub git_tree {
}
}
die_error(404, "No such tree") unless defined($hash);
- $/ = "\0";
- open my $fd, "-|", git_cmd(), "ls-tree", '-z', $hash
- or die_error(500, "Open git-ls-tree failed");
- my @entries = map { chomp; $_ } <$fd>;
- close $fd or die_error(404, "Reading tree failed");
- $/ = "\n";
+
+ my @entries = ();
+ {
+ local $/ = "\0";
+ open my $fd, "-|", git_cmd(), "ls-tree", '-z', $hash
+ or die_error(500, "Open git-ls-tree failed");
+ @entries = map { chomp; $_ } <$fd>;
+ close $fd
+ or die_error(404, "Reading tree failed");
+ }
my $refs = git_get_references();
my $ref = format_ref_marker($refs, $hash_base);
@@ -5809,7 +5808,7 @@ sub git_search {
print "<table class=\"pickaxe search\">\n";
my $alternate = 1;
- $/ = "\n";
+ local $/ = "\n";
open my $fd, '-|', git_cmd(), '--no-pager', 'log', @diff_opts,
'--pretty=format:%H', '--no-abbrev', '--raw', "-S$searchtext",
($search_use_regexp ? '--pickaxe-regex' : ());
@@ -5879,7 +5878,7 @@ sub git_search {
print "<table class=\"grep_search\">\n";
my $alternate = 1;
my $matches = 0;
- $/ = "\n";
+ local $/ = "\n";
open my $fd, "-|", git_cmd(), 'grep', '-n',
$search_use_regexp ? ('-E', '-i') : '-F',
$searchtext, $co{'tree'};
@@ -6282,7 +6281,7 @@ XML
# end of feed
if ($format eq 'rss') {
print "</channel>\n</rss>\n";
- } elsif ($format eq 'atom') {
+ } elsif ($format eq 'atom') {
print "</feed>\n";
}
}
diff --git a/graph.c b/graph.c
index 06fbeb6..f8d7a5c 100644
--- a/graph.c
+++ b/graph.c
@@ -47,20 +47,6 @@ static void graph_show_strbuf(struct git_graph *graph, struct strbuf const *sb);
* - Limit the number of columns, similar to the way gitk does.
* If we reach more than a specified number of columns, omit
* sections of some columns.
- *
- * - The output during the GRAPH_PRE_COMMIT and GRAPH_COLLAPSING states
- * could be made more compact by printing horizontal lines, instead of
- * long diagonal lines. For example, during collapsing, something like
- * this: instead of this:
- * | | | | | | | | | |
- * | |_|_|/ | | | |/
- * |/| | | | | |/|
- * | | | | | |/| |
- * |/| | |
- * | | | |
- *
- * If there are several parallel diagonal lines, they will need to be
- * replaced with horizontal lines on subsequent rows.
*/
struct column {
@@ -982,6 +968,9 @@ static void graph_output_collapsing_line(struct git_graph *graph, struct strbuf
{
int i;
int *tmp_mapping;
+ short used_horizontal = 0;
+ int horizontal_edge = -1;
+ int horizontal_edge_target = -1;
/*
* Clear out the new_mapping array
@@ -1019,6 +1008,23 @@ static void graph_output_collapsing_line(struct git_graph *graph, struct strbuf
* Move to the left by one
*/
graph->new_mapping[i - 1] = target;
+ /*
+ * If there isn't already an edge moving horizontally
+ * select this one.
+ */
+ if (horizontal_edge == -1) {
+ int j;
+ horizontal_edge = i;
+ horizontal_edge_target = target;
+ /*
+ * The variable target is the index of the graph
+ * column, and therefore target*2+3 is the
+ * actual screen column of the first horizontal
+ * line.
+ */
+ for (j = (target * 2)+3; j < (i - 2); j += 2)
+ graph->new_mapping[j] = target;
+ }
} else if (graph->new_mapping[i - 1] == target) {
/*
* There is a branch line to our left
@@ -1039,10 +1045,21 @@ static void graph_output_collapsing_line(struct git_graph *graph, struct strbuf
*
* The space just to the left of this
* branch should always be empty.
+ *
+ * The branch to the left of that space
+ * should be our eventual target.
*/
assert(graph->new_mapping[i - 1] > target);
assert(graph->new_mapping[i - 2] < 0);
+ assert(graph->new_mapping[i - 3] == target);
graph->new_mapping[i - 2] = target;
+ /*
+ * Mark this branch as the horizontal edge to
+ * prevent any other edges from moving
+ * horizontally.
+ */
+ if (horizontal_edge == -1)
+ horizontal_edge = i;
}
}
@@ -1061,8 +1078,23 @@ static void graph_output_collapsing_line(struct git_graph *graph, struct strbuf
strbuf_addch(sb, ' ');
else if (target * 2 == i)
strbuf_write_column(sb, &graph->new_columns[target], '|');
- else
+ else if (target == horizontal_edge_target &&
+ i != horizontal_edge - 1) {
+ /*
+ * Set the mappings for all but the
+ * first segment to -1 so that they
+ * won't continue into the next line.
+ */
+ if (i != (target * 2)+3)
+ graph->new_mapping[i] = -1;
+ used_horizontal = 1;
+ strbuf_write_column(sb, &graph->new_columns[target], '_');
+ } else {
+ if (used_horizontal && i < horizontal_edge)
+ graph->new_mapping[i] = -1;
strbuf_write_column(sb, &graph->new_columns[target], '/');
+
+ }
}
graph_pad_horizontally(graph, sb, graph->mapping_size);
diff --git a/grep.c b/grep.c
index f3a27d7..92a47c7 100644
--- a/grep.c
+++ b/grep.c
@@ -72,6 +72,8 @@ static struct grep_expr *compile_pattern_atom(struct grep_pat **list)
struct grep_expr *x;
p = *list;
+ if (!p)
+ return NULL;
switch (p->token) {
case GREP_PATTERN: /* atom */
case GREP_PATTERN_HEAD:
@@ -84,8 +86,6 @@ static struct grep_expr *compile_pattern_atom(struct grep_pat **list)
case GREP_OPEN_PAREN:
*list = p->next;
x = compile_pattern_or(list);
- if (!x)
- return NULL;
if (!*list || (*list)->token != GREP_CLOSE_PAREN)
die("unmatched parenthesis");
*list = (*list)->next;
@@ -101,6 +101,8 @@ static struct grep_expr *compile_pattern_not(struct grep_pat **list)
struct grep_expr *x;
p = *list;
+ if (!p)
+ return NULL;
switch (p->token) {
case GREP_NOT:
if (!p->next)
@@ -303,6 +305,7 @@ static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
{
int hit = 0;
int saved_ch = 0;
+ const char *start = bol;
if ((p->token != GREP_PATTERN) &&
((p->token == GREP_PATTERN_HEAD) != (ctx == GREP_CONTEXT_HEAD)))
@@ -328,7 +331,7 @@ static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
if (hit && p->word_regexp) {
if ((pmatch[0].rm_so < 0) ||
- (eol - bol) <= pmatch[0].rm_so ||
+ (eol - bol) < pmatch[0].rm_so ||
(pmatch[0].rm_eo < 0) ||
(eol - bol) < pmatch[0].rm_eo)
die("regexp returned nonsense");
@@ -347,6 +350,10 @@ static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
else
hit = 0;
+ /* Words consist of at least one character. */
+ if (pmatch->rm_so == pmatch->rm_eo)
+ hit = 0;
+
if (!hit && pmatch[0].rm_so + bol + 1 < eol) {
/* There could be more than one match on the
* line, and the first match might not be
@@ -357,12 +364,17 @@ static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
bol = pmatch[0].rm_so + bol + 1;
while (word_char(bol[-1]) && bol < eol)
bol++;
+ eflags |= REG_NOTBOL;
if (bol < eol)
goto again;
}
}
if (p->token == GREP_PATTERN_HEAD && saved_ch)
*eol = saved_ch;
+ if (hit) {
+ pmatch[0].rm_so += bol - start;
+ pmatch[0].rm_eo += bol - start;
+ }
return hit;
}
@@ -372,6 +384,8 @@ static int match_expr_eval(struct grep_expr *x, char *bol, char *eol,
int h = 0;
regmatch_t match;
+ if (!x)
+ die("Not a valid grep expression");
switch (x->node) {
case GREP_NODE_ATOM:
h = match_one_pattern(x->u.atom, bol, eol, ctx, &match, 0);
@@ -490,6 +504,8 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
*eol = '\0';
while (next_match(opt, bol, eol, ctx, &match, eflags)) {
+ if (match.rm_so == match.rm_eo)
+ break;
printf("%.*s%s%.*s%s",
(int)match.rm_so, bol,
opt->color_match,
diff --git a/grep.h b/grep.h
index a67005d..464e272 100644
--- a/grep.h
+++ b/grep.h
@@ -61,23 +61,23 @@ struct grep_opt {
struct grep_expr *pattern_expression;
int prefix_length;
regex_t regexp;
- unsigned linenum:1;
- unsigned invert:1;
- unsigned status_only:1;
- unsigned name_only:1;
- unsigned unmatch_name_only:1;
- unsigned count:1;
- unsigned word_regexp:1;
- unsigned fixed:1;
- unsigned all_match:1;
+ int linenum;
+ int invert;
+ int status_only;
+ int name_only;
+ int unmatch_name_only;
+ int count;
+ int word_regexp;
+ int fixed;
+ int all_match;
#define GREP_BINARY_DEFAULT 0
#define GREP_BINARY_NOMATCH 1
#define GREP_BINARY_TEXT 2
- unsigned binary:2;
- unsigned extended:1;
- unsigned relative:1;
- unsigned pathname:1;
- unsigned null_following_name:1;
+ int binary;
+ int extended;
+ int relative;
+ int pathname;
+ int null_following_name;
int color;
char color_match[COLOR_MAXLEN];
const char *color_external;
diff --git a/hash-object.c b/hash-object.c
index ebb3bed..47cf43c 100644
--- a/hash-object.c
+++ b/hash-object.c
@@ -84,7 +84,8 @@ int main(int argc, const char **argv)
git_extract_argv0_path(argv[0]);
- argc = parse_options(argc, argv, hash_object_options, hash_object_usage, 0);
+ argc = parse_options(argc, argv, NULL, hash_object_options,
+ hash_object_usage, 0);
if (write_object) {
prefix = setup_git_directory();
diff --git a/http-push.c b/http-push.c
index 5138224..a7e28e3 100644
--- a/http-push.c
+++ b/http-push.c
@@ -315,9 +315,9 @@ static void start_fetch_loose(struct transfer_request *request)
"%s.temp", filename);
snprintf(prevfile, sizeof(prevfile), "%s.prev", request->filename);
- unlink(prevfile);
+ unlink_or_warn(prevfile);
rename(request->tmpfile, prevfile);
- unlink(request->tmpfile);
+ unlink_or_warn(request->tmpfile);
if (request->local_fileno != -1)
error("fd leakage in start: %d", request->local_fileno);
@@ -372,7 +372,7 @@ static void start_fetch_loose(struct transfer_request *request)
} while (prev_read > 0);
close(prevlocal);
}
- unlink(prevfile);
+ unlink_or_warn(prevfile);
/* Reset inflate/SHA1 if there was an error reading the previous temp
file; also rewind to the beginning of the local file. */
@@ -784,7 +784,7 @@ static void finish_request(struct transfer_request *request)
request->http_code != 416) {
if (stat(request->tmpfile, &st) == 0) {
if (st.st_size == 0)
- unlink(request->tmpfile);
+ unlink_or_warn(request->tmpfile);
}
} else {
if (request->http_code == 416)
@@ -793,9 +793,9 @@ static void finish_request(struct transfer_request *request)
git_inflate_end(&request->stream);
git_SHA1_Final(request->real_sha1, &request->c);
if (request->zret != Z_STREAM_END) {
- unlink(request->tmpfile);
+ unlink_or_warn(request->tmpfile);
} else if (hashcmp(request->obj->sha1, request->real_sha1)) {
- unlink(request->tmpfile);
+ unlink_or_warn(request->tmpfile);
} else {
request->rename =
move_temp_to_file(
@@ -1415,8 +1415,9 @@ static void remove_locks(void)
fprintf(stderr, "Removing remote locks...\n");
while (lock) {
+ struct remote_lock *next = lock->next;
unlock_remote(lock);
- lock = lock->next;
+ lock = next;
}
}
@@ -1843,7 +1844,7 @@ static int update_remote(unsigned char *sha1, struct remote_lock *lock)
return 1;
}
-static struct ref *remote_refs, **remote_tail;
+static struct ref *remote_refs;
static void one_remote_ref(char *refname)
{
@@ -1873,27 +1874,15 @@ static void one_remote_ref(char *refname)
}
}
- *remote_tail = ref;
- remote_tail = &ref->next;
+ ref->next = remote_refs;
+ remote_refs = ref;
}
static void get_dav_remote_heads(void)
{
- remote_tail = &remote_refs;
remote_ls("refs/", (PROCESS_FILES | PROCESS_DIRS | RECURSIVE), process_ls_ref, NULL);
}
-static int is_zero_sha1(const unsigned char *sha1)
-{
- int i;
-
- for (i = 0; i < 20; i++) {
- if (*sha1++)
- return 0;
- }
- return 1;
-}
-
static void add_remote_info_ref(struct remote_ls_ctx *ls)
{
struct strbuf *buf = (struct strbuf *)ls->userData;
@@ -2119,13 +2108,13 @@ static int delete_remote_branch(char *pattern, int force)
/* Remote HEAD must resolve to a known object */
if (symref)
return error("Remote HEAD symrefs too deep");
- if (is_zero_sha1(head_sha1))
+ if (is_null_sha1(head_sha1))
return error("Unable to resolve remote HEAD");
if (!has_sha1_file(head_sha1))
return error("Remote HEAD resolves to object %s\nwhich does not exist locally, perhaps you need to fetch?", sha1_to_hex(head_sha1));
/* Remote branch must resolve to a known object */
- if (is_zero_sha1(remote_ref->old_sha1))
+ if (is_null_sha1(remote_ref->old_sha1))
return error("Unable to resolve remote branch %s",
remote_ref->name);
if (!has_sha1_file(remote_ref->old_sha1))
@@ -2310,9 +2299,7 @@ int main(int argc, char **argv)
}
/* match them up */
- if (!remote_tail)
- remote_tail = &remote_refs;
- if (match_refs(local_refs, remote_refs, &remote_tail,
+ if (match_refs(local_refs, &remote_refs,
nr_refspec, (const char **) refspec, push_all)) {
rc = -1;
goto cleanup;
@@ -2326,14 +2313,14 @@ int main(int argc, char **argv)
new_refs = 0;
for (ref = remote_refs; ref; ref = ref->next) {
char old_hex[60], *new_hex;
- const char *commit_argv[4];
+ const char *commit_argv[5];
int commit_argc;
char *new_sha1_hex, *old_sha1_hex;
if (!ref->peer_ref)
continue;
- if (is_zero_sha1(ref->peer_ref->new_sha1)) {
+ if (is_null_sha1(ref->peer_ref->new_sha1)) {
if (delete_remote_branch(ref->name, 1) == -1) {
error("Could not remove %s", ref->name);
rc = -4;
@@ -2349,7 +2336,7 @@ int main(int argc, char **argv)
}
if (!force_all &&
- !is_zero_sha1(ref->old_sha1) &&
+ !is_null_sha1(ref->old_sha1) &&
!ref->force) {
if (!has_sha1_file(ref->old_sha1) ||
!ref_newer(ref->peer_ref->new_sha1,
@@ -2399,13 +2386,14 @@ int main(int argc, char **argv)
old_sha1_hex = NULL;
commit_argv[1] = "--objects";
commit_argv[2] = new_sha1_hex;
- if (!push_all && !is_zero_sha1(ref->old_sha1)) {
+ if (!push_all && !is_null_sha1(ref->old_sha1)) {
old_sha1_hex = xmalloc(42);
sprintf(old_sha1_hex, "^%s",
sha1_to_hex(ref->old_sha1));
commit_argv[3] = old_sha1_hex;
commit_argc++;
}
+ commit_argv[commit_argc] = NULL;
init_revisions(&revs, setup_git_directory());
setup_revisions(commit_argc, commit_argv, &revs, NULL);
revs.edge_hint = 0; /* just in case */
diff --git a/http-walker.c b/http-walker.c
index c5a3ea3..7321ccc9 100644
--- a/http-walker.c
+++ b/http-walker.c
@@ -111,9 +111,9 @@ static void start_object_request(struct walker *walker,
struct walker_data *data = walker->data;
snprintf(prevfile, sizeof(prevfile), "%s.prev", obj_req->filename);
- unlink(prevfile);
+ unlink_or_warn(prevfile);
rename(obj_req->tmpfile, prevfile);
- unlink(obj_req->tmpfile);
+ unlink_or_warn(obj_req->tmpfile);
if (obj_req->local != -1)
error("fd leakage in start: %d", obj_req->local);
@@ -177,7 +177,7 @@ static void start_object_request(struct walker *walker,
} while (prev_read > 0);
close(prevlocal);
}
- unlink(prevfile);
+ unlink_or_warn(prevfile);
/* Reset inflate/SHA1 if there was an error reading the previous temp
file; also rewind to the beginning of the local file. */
@@ -238,18 +238,18 @@ static void finish_object_request(struct object_request *obj_req)
} else if (obj_req->curl_result != CURLE_OK) {
if (stat(obj_req->tmpfile, &st) == 0)
if (st.st_size == 0)
- unlink(obj_req->tmpfile);
+ unlink_or_warn(obj_req->tmpfile);
return;
}
git_inflate_end(&obj_req->stream);
git_SHA1_Final(obj_req->real_sha1, &obj_req->c);
if (obj_req->zret != Z_STREAM_END) {
- unlink(obj_req->tmpfile);
+ unlink_or_warn(obj_req->tmpfile);
return;
}
if (hashcmp(obj_req->sha1, obj_req->real_sha1)) {
- unlink(obj_req->tmpfile);
+ unlink_or_warn(obj_req->tmpfile);
return;
}
obj_req->rename =
@@ -809,7 +809,7 @@ static void abort_object_request(struct object_request *obj_req)
close(obj_req->local);
obj_req->local = -1;
}
- unlink(obj_req->tmpfile);
+ unlink_or_warn(obj_req->tmpfile);
if (obj_req->slot) {
release_active_slot(obj_req->slot);
obj_req->slot = NULL;
diff --git a/imap-send.c b/imap-send.c
index 8154cb2..e4c83b9 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -982,9 +982,7 @@ static struct store *imap_open_store(struct imap_server_conf *srvc)
struct imap_store *ctx;
struct imap *imap;
char *arg, *rsp;
- struct hostent *he;
- struct sockaddr_in addr;
- int s, a[2], preauth;
+ int s = -1, a[2], preauth;
pid_t pid;
ctx = xcalloc(sizeof(*ctx), 1);
@@ -1021,6 +1019,51 @@ static struct store *imap_open_store(struct imap_server_conf *srvc)
imap_info("ok\n");
} else {
+#ifndef NO_IPV6
+ struct addrinfo hints, *ai0, *ai;
+ int gai;
+ char portstr[6];
+
+ snprintf(portstr, sizeof(portstr), "%hu", srvc->port);
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+
+ imap_info("Resolving %s... ", srvc->host);
+ gai = getaddrinfo(srvc->host, portstr, &hints, &ai);
+ if (gai) {
+ fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(gai));
+ goto bail;
+ }
+ imap_info("ok\n");
+
+ for (ai0 = ai; ai; ai = ai->ai_next) {
+ char addr[NI_MAXHOST];
+
+ s = socket(ai->ai_family, ai->ai_socktype,
+ ai->ai_protocol);
+ if (s < 0)
+ continue;
+
+ getnameinfo(ai->ai_addr, ai->ai_addrlen, addr,
+ sizeof(addr), NULL, 0, NI_NUMERICHOST);
+ imap_info("Connecting to [%s]:%s... ", addr, portstr);
+
+ if (connect(s, ai->ai_addr, ai->ai_addrlen) < 0) {
+ close(s);
+ s = -1;
+ perror("connect");
+ continue;
+ }
+
+ break;
+ }
+ freeaddrinfo(ai0);
+#else /* NO_IPV6 */
+ struct hostent *he;
+ struct sockaddr_in addr;
+
memset(&addr, 0, sizeof(addr));
addr.sin_port = htons(srvc->port);
addr.sin_family = AF_INET;
@@ -1040,7 +1083,12 @@ static struct store *imap_open_store(struct imap_server_conf *srvc)
imap_info("Connecting to %s:%hu... ", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
if (connect(s, (struct sockaddr *)&addr, sizeof(addr))) {
close(s);
+ s = -1;
perror("connect");
+ }
+#endif
+ if (s < 0) {
+ fputs("Error: unable to connect to server.\n", stderr);
goto bail;
}
diff --git a/ll-merge.c b/ll-merge.c
index fa2ca52..31d6f0a 100644
--- a/ll-merge.c
+++ b/ll-merge.c
@@ -175,8 +175,7 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
{ "B", temp[2] },
{ NULL }
};
- struct child_process child;
- const char *args[20];
+ const char *args[] = { "sh", "-c", NULL, NULL };
int status, fd, i;
struct stat st;
@@ -191,14 +190,8 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
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] = cmd.buf;
- args[3] = NULL;
-
- status = run_command(&child);
+ status = run_command_v_opt(args, 0);
if (status < -ERR_RUN_COMMAND_FORK)
; /* failure in run-command */
else
@@ -219,7 +212,7 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
close(fd);
bad:
for (i = 0; i < 3; i++)
- unlink(temp[i]);
+ unlink_or_warn(temp[i]);
strbuf_release(&cmd);
return status;
}
diff --git a/lockfile.c b/lockfile.c
index 3dbb2d1..eb931ed 100644
--- a/lockfile.c
+++ b/lockfile.c
@@ -16,7 +16,7 @@ static void remove_lock_file(void)
lock_file_list->filename[0]) {
if (lock_file_list->fd >= 0)
close(lock_file_list->fd);
- unlink(lock_file_list->filename);
+ unlink_or_warn(lock_file_list->filename);
}
lock_file_list = lock_file_list->next;
}
@@ -109,7 +109,7 @@ static char *resolve_symlink(char *p, size_t s)
* link is a relative path, so I must replace the
* last element of p with it.
*/
- char *r = (char*)last_path_elm(p);
+ char *r = (char *)last_path_elm(p);
if (r - p + link_len < s)
strcpy(r, link);
else {
@@ -259,7 +259,7 @@ void rollback_lock_file(struct lock_file *lk)
if (lk->filename[0]) {
if (lk->fd >= 0)
close(lk->fd);
- unlink(lk->filename);
+ unlink_or_warn(lk->filename);
}
lk->filename[0] = 0;
}
diff --git a/log-tree.c b/log-tree.c
index 5bd29e6..59d63eb 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -25,6 +25,7 @@ static int add_ref_decoration(const char *refname, const unsigned char *sha1, in
struct object *obj = parse_object(sha1);
if (!obj)
return 0;
+ refname = prettify_refname(refname);
add_name_decoration("", refname, obj);
while (obj->type == OBJ_TAG) {
obj = ((struct tag *)obj)->tagged;
diff --git a/merge-index.c b/merge-index.c
index aa9cf23..19ddd03 100644
--- a/merge-index.c
+++ b/merge-index.c
@@ -3,45 +3,20 @@
#include "exec_cmd.h"
static const char *pgm;
-static const char *arguments[9];
static int one_shot, quiet;
static int err;
-static void run_program(void)
-{
- struct child_process child;
- memset(&child, 0, sizeof(child));
- child.argv = arguments;
- if (run_command(&child)) {
- if (one_shot) {
- err++;
- } else {
- if (!quiet)
- die("merge program failed");
- exit(1);
- }
- }
-}
-
static int merge_entry(int pos, const char *path)
{
int found;
+ const char *arguments[] = { pgm, "", "", "", path, "", "", "", NULL };
+ char hexbuf[4][60];
+ char ownbuf[4][60];
if (pos >= active_nr)
die("git merge-index: %s not in the cache", path);
- arguments[0] = pgm;
- arguments[1] = "";
- arguments[2] = "";
- arguments[3] = "";
- arguments[4] = path;
- arguments[5] = "";
- arguments[6] = "";
- arguments[7] = "";
- arguments[8] = NULL;
found = 0;
do {
- static char hexbuf[4][60];
- static char ownbuf[4][60];
struct cache_entry *ce = active_cache[pos];
int stage = ce_stage(ce);
@@ -55,7 +30,16 @@ static int merge_entry(int pos, const char *path)
} while (++pos < active_nr);
if (!found)
die("git merge-index: %s not in the cache", path);
- run_program();
+
+ if (run_command_v_opt(arguments, 0)) {
+ if (one_shot)
+ err++;
+ else {
+ if (!quiet)
+ die("merge program failed");
+ exit(1);
+ }
+ }
return found;
}
diff --git a/merge-recursive.c b/merge-recursive.c
index d6f0582..f5df9b9 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -520,8 +520,12 @@ static void update_file_flags(struct merge_options *o,
unsigned long size;
if (S_ISGITLINK(mode))
- die("cannot read object %s '%s': It is a submodule!",
- sha1_to_hex(sha), path);
+ /*
+ * We may later decide to recursively descend into
+ * the submodule directory and update its index
+ * and/or work tree, but we do not do that now.
+ */
+ goto update_index;
buf = read_sha1_file(sha, &type, &size);
if (!buf)
@@ -929,11 +933,12 @@ 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);
+ if (!o->call_depth)
+ 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;
diff --git a/mktree.c b/mktree.c
deleted file mode 100644
index 137a095..0000000
--- a/mktree.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * GIT - the stupid content tracker
- *
- * Copyright (c) Junio C Hamano, 2006
- */
-#include "cache.h"
-#include "quote.h"
-#include "tree.h"
-#include "exec_cmd.h"
-
-static struct treeent {
- unsigned mode;
- unsigned char sha1[20];
- int len;
- char name[FLEX_ARRAY];
-} **entries;
-static int alloc, used;
-
-static void append_to_tree(unsigned mode, unsigned char *sha1, char *path)
-{
- struct treeent *ent;
- int len = strlen(path);
- if (strchr(path, '/'))
- die("path %s contains slash", path);
-
- if (alloc <= used) {
- alloc = alloc_nr(used);
- entries = xrealloc(entries, sizeof(*entries) * alloc);
- }
- ent = entries[used++] = xmalloc(sizeof(**entries) + len + 1);
- ent->mode = mode;
- ent->len = len;
- hashcpy(ent->sha1, sha1);
- memcpy(ent->name, path, len+1);
-}
-
-static int ent_compare(const void *a_, const void *b_)
-{
- struct treeent *a = *(struct treeent **)a_;
- struct treeent *b = *(struct treeent **)b_;
- return base_name_compare(a->name, a->len, a->mode,
- b->name, b->len, b->mode);
-}
-
-static void write_tree(unsigned char *sha1)
-{
- struct strbuf buf;
- size_t size;
- int i;
-
- qsort(entries, used, sizeof(*entries), ent_compare);
- for (size = i = 0; i < used; i++)
- size += 32 + entries[i]->len;
-
- strbuf_init(&buf, size);
- for (i = 0; i < used; i++) {
- struct treeent *ent = entries[i];
- strbuf_addf(&buf, "%o %s%c", ent->mode, ent->name, '\0');
- strbuf_add(&buf, ent->sha1, 20);
- }
-
- write_sha1_file(buf.buf, buf.len, tree_type, sha1);
-}
-
-static const char mktree_usage[] = "git mktree [-z]";
-
-int main(int ac, char **av)
-{
- struct strbuf sb = STRBUF_INIT;
- struct strbuf p_uq = STRBUF_INIT;
- unsigned char sha1[20];
- int line_termination = '\n';
-
- git_extract_argv0_path(av[0]);
-
- setup_git_directory();
-
- while ((1 < ac) && av[1][0] == '-') {
- char *arg = av[1];
- if (!strcmp("-z", arg))
- line_termination = 0;
- else
- usage(mktree_usage);
- ac--;
- av++;
- }
-
- while (strbuf_getline(&sb, stdin, line_termination) != EOF) {
- char *ptr, *ntr;
- unsigned mode;
- enum object_type type;
- char *path;
-
- ptr = sb.buf;
- /* Input is non-recursive ls-tree output format
- * mode SP type SP sha1 TAB name
- */
- mode = strtoul(ptr, &ntr, 8);
- if (ptr == ntr || !ntr || *ntr != ' ')
- die("input format error: %s", sb.buf);
- ptr = ntr + 1; /* type */
- ntr = strchr(ptr, ' ');
- if (!ntr || sb.buf + sb.len <= ntr + 40 ||
- ntr[41] != '\t' ||
- get_sha1_hex(ntr + 1, sha1))
- die("input format error: %s", sb.buf);
- type = sha1_object_info(sha1, NULL);
- if (type < 0)
- die("object %s unavailable", sha1_to_hex(sha1));
- *ntr++ = 0; /* now at the beginning of SHA1 */
- if (type != type_from_string(ptr))
- die("object type %s mismatch (%s)", ptr, typename(type));
-
- path = ntr + 41; /* at the beginning of name */
- if (line_termination && path[0] == '"') {
- strbuf_reset(&p_uq);
- if (unquote_c_style(&p_uq, path, NULL)) {
- die("invalid quoting");
- }
- path = p_uq.buf;
- }
-
- append_to_tree(mode, sha1, path);
- }
- strbuf_release(&p_uq);
- strbuf_release(&sb);
-
- write_tree(sha1);
- puts(sha1_to_hex(sha1));
- exit(0);
-}
diff --git a/object.c b/object.c
index 7e6a92c..a6ef439 100644
--- a/object.c
+++ b/object.c
@@ -45,13 +45,14 @@ int type_from_string(const char *str)
static unsigned int hash_obj(struct object *obj, unsigned int n)
{
- unsigned int hash = *(unsigned int *)obj->sha1;
+ unsigned int hash;
+ memcpy(&hash, obj->sha1, sizeof(unsigned int));
return hash % n;
}
static void insert_obj_hash(struct object *obj, struct object **hash, unsigned int size)
{
- int j = hash_obj(obj, size);
+ unsigned int j = hash_obj(obj, size);
while (hash[j]) {
j++;
@@ -61,16 +62,16 @@ static void insert_obj_hash(struct object *obj, struct object **hash, unsigned i
hash[j] = obj;
}
-static int hashtable_index(const unsigned char *sha1)
+static unsigned int hashtable_index(const unsigned char *sha1)
{
unsigned int i;
memcpy(&i, sha1, sizeof(unsigned int));
- return (int)(i % obj_hash_size);
+ return i % obj_hash_size;
}
struct object *lookup_object(const unsigned char *sha1)
{
- int i;
+ unsigned int i;
struct object *obj;
if (!obj_hash)
diff --git a/pack-refs.c b/pack-refs.c
index 2c76fb1..301fc60 100644
--- a/pack-refs.c
+++ b/pack-refs.c
@@ -66,7 +66,7 @@ static void prune_ref(struct ref_to_prune *r)
struct ref_lock *lock = lock_ref_sha1(r->name + 5, r->sha1);
if (lock) {
- unlink(git_path("%s", r->name));
+ unlink_or_warn(git_path("%s", r->name));
unlock_ref(lock);
}
}
diff --git a/parse-options.c b/parse-options.c
index cf71bcf..79de18b 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -31,11 +31,20 @@ static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,
return 0;
}
+static void fix_filename(const char *prefix, const char **file)
+{
+ if (!file || !*file || !prefix || is_absolute_path(*file)
+ || !strcmp("-", *file))
+ return;
+ *file = xstrdup(prefix_filename(prefix, strlen(prefix), *file));
+}
+
static int get_value(struct parse_opt_ctx_t *p,
const struct option *opt, int flags)
{
const char *s, *arg;
const int unset = flags & OPT_UNSET;
+ int err;
if (unset && p->opt)
return opterror(opt, "takes no value", flags);
@@ -50,6 +59,7 @@ static int get_value(struct parse_opt_ctx_t *p,
/* FALLTHROUGH */
case OPTION_BOOLEAN:
case OPTION_BIT:
+ case OPTION_NEGBIT:
case OPTION_SET_INT:
case OPTION_SET_PTR:
return opterror(opt, "takes no value", flags);
@@ -66,6 +76,13 @@ static int get_value(struct parse_opt_ctx_t *p,
*(int *)opt->value |= opt->defval;
return 0;
+ case OPTION_NEGBIT:
+ if (unset)
+ *(int *)opt->value |= opt->defval;
+ else
+ *(int *)opt->value &= ~opt->defval;
+ return 0;
+
case OPTION_BOOLEAN:
*(int *)opt->value = unset ? 0 : *(int *)opt->value + 1;
return 0;
@@ -87,6 +104,19 @@ static int get_value(struct parse_opt_ctx_t *p,
return get_arg(p, opt, flags, (const char **)opt->value);
return 0;
+ case OPTION_FILENAME:
+ err = 0;
+ if (unset)
+ *(const char **)opt->value = NULL;
+ else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
+ *(const char **)opt->value = (const char *)opt->defval;
+ else
+ err = get_arg(p, opt, flags, (const char **)opt->value);
+
+ if (!err)
+ fix_filename(p->prefix, (const char **)opt->value);
+ return err;
+
case OPTION_CALLBACK:
if (unset)
return (*opt->callback)(opt, NULL, 1) ? (-1) : 0;
@@ -121,11 +151,33 @@ static int get_value(struct parse_opt_ctx_t *p,
static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *options)
{
+ const struct option *numopt = NULL;
+
for (; options->type != OPTION_END; options++) {
if (options->short_name == *p->opt) {
p->opt = p->opt[1] ? p->opt + 1 : NULL;
return get_value(p, options, OPT_SHORT);
}
+
+ /*
+ * Handle the numerical option later, explicit one-digit
+ * options take precedence over it.
+ */
+ if (options->type == OPTION_NUMBER)
+ numopt = options;
+ }
+ if (numopt && isdigit(*p->opt)) {
+ size_t len = 1;
+ char *arg;
+ int rc;
+
+ while (isdigit(p->opt[len]))
+ len++;
+ arg = xmemdupz(p->opt, len);
+ p->opt = p->opt[len] ? p->opt + len : NULL;
+ rc = (*numopt->callback)(numopt, arg, 0) ? (-1) : 0;
+ free(arg);
+ return rc;
}
return -2;
}
@@ -215,6 +267,25 @@ is_abbreviated:
return -2;
}
+static int parse_nodash_opt(struct parse_opt_ctx_t *p, const char *arg,
+ const struct option *options)
+{
+ for (; options->type != OPTION_END; options++) {
+ if (!(options->flags & PARSE_OPT_NODASH))
+ continue;
+ if ((options->flags & PARSE_OPT_OPTARG) ||
+ !(options->flags & PARSE_OPT_NOARG))
+ die("BUG: dashless options don't support arguments");
+ if (!(options->flags & PARSE_OPT_NONEG))
+ die("BUG: dashless options don't support negation");
+ if (options->long_name)
+ die("BUG: dashless options can't be long");
+ if (options->short_name == arg[0] && arg[1] == '\0')
+ return get_value(p, options, OPT_SHORT);
+ }
+ return -2;
+}
+
static void check_typos(const char *arg, const struct option *options)
{
if (strlen(arg) < 3)
@@ -235,13 +306,37 @@ static void check_typos(const char *arg, const struct option *options)
}
}
+static void parse_options_check(const struct option *opts)
+{
+ int err = 0;
+
+ for (; opts->type != OPTION_END; opts++) {
+ if ((opts->flags & PARSE_OPT_LASTARG_DEFAULT) &&
+ (opts->flags & PARSE_OPT_OPTARG)) {
+ if (opts->long_name) {
+ error("`--%s` uses incompatible flags "
+ "LASTARG_DEFAULT and OPTARG", opts->long_name);
+ } else {
+ error("`-%c` uses incompatible flags "
+ "LASTARG_DEFAULT and OPTARG", opts->short_name);
+ }
+ err |= 1;
+ }
+ }
+
+ if (err)
+ exit(129);
+}
+
void parse_options_start(struct parse_opt_ctx_t *ctx,
- int argc, const char **argv, int flags)
+ int argc, const char **argv, const char *prefix,
+ int flags)
{
memset(ctx, 0, sizeof(*ctx));
ctx->argc = argc - 1;
ctx->argv = argv + 1;
ctx->out = argv;
+ ctx->prefix = prefix;
ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0);
ctx->flags = flags;
if ((flags & PARSE_OPT_KEEP_UNKNOWN) &&
@@ -258,6 +353,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
{
int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP);
+ parse_options_check(options);
+
/* we must reset ->opt, unknown short option leave it dangling */
ctx->opt = NULL;
@@ -265,6 +362,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
const char *arg = ctx->argv[0];
if (*arg != '-' || !arg[1]) {
+ if (parse_nodash_opt(ctx, arg, options) == 0)
+ continue;
if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION)
break;
ctx->out[ctx->cpidx++] = ctx->argv[0];
@@ -338,12 +437,13 @@ int parse_options_end(struct parse_opt_ctx_t *ctx)
return ctx->cpidx + ctx->argc;
}
-int parse_options(int argc, const char **argv, const struct option *options,
- const char * const usagestr[], int flags)
+int parse_options(int argc, const char **argv, const char *prefix,
+ const struct option *options, const char * const usagestr[],
+ int flags)
{
struct parse_opt_ctx_t ctx;
- parse_options_start(&ctx, argc, argv, flags);
+ parse_options_start(&ctx, argc, argv, prefix, flags);
switch (parse_options_step(&ctx, options, usagestr)) {
case PARSE_OPT_HELP:
exit(129);
@@ -361,6 +461,20 @@ int parse_options(int argc, const char **argv, const struct option *options,
return parse_options_end(&ctx);
}
+static int usage_argh(const struct option *opts)
+{
+ const char *s;
+ int literal = opts->flags & PARSE_OPT_LITERAL_ARGHELP;
+ if (opts->flags & PARSE_OPT_OPTARG)
+ if (opts->long_name)
+ s = literal ? "[=%s]" : "[=<%s>]";
+ else
+ s = literal ? "[%s]" : "[<%s>]";
+ else
+ s = literal ? " %s" : " <%s>";
+ return fprintf(stderr, s, opts->argh);
+}
+
#define USAGE_OPTS_WIDTH 24
#define USAGE_GAP 2
@@ -397,12 +511,18 @@ int usage_with_options_internal(const char * const *usagestr,
continue;
pos = fprintf(stderr, " ");
- if (opts->short_name)
- pos += fprintf(stderr, "-%c", opts->short_name);
+ if (opts->short_name) {
+ if (opts->flags & PARSE_OPT_NODASH)
+ pos += fprintf(stderr, "%c", opts->short_name);
+ else
+ pos += fprintf(stderr, "-%c", opts->short_name);
+ }
if (opts->long_name && opts->short_name)
pos += fprintf(stderr, ", ");
if (opts->long_name)
pos += fprintf(stderr, "--%s", opts->long_name);
+ if (opts->type == OPTION_NUMBER)
+ pos += fprintf(stderr, "-NUM");
switch (opts->type) {
case OPTION_ARGUMENT:
@@ -420,16 +540,12 @@ int usage_with_options_internal(const char * const *usagestr,
if (opts->flags & PARSE_OPT_NOARG)
break;
/* FALLTHROUGH */
+ case OPTION_FILENAME:
+ /* FALLTHROUGH */
case OPTION_STRING:
- if (opts->argh) {
- if (opts->flags & PARSE_OPT_OPTARG)
- if (opts->long_name)
- pos += fprintf(stderr, "[=<%s>]", opts->argh);
- else
- pos += fprintf(stderr, "[<%s>]", opts->argh);
- else
- pos += fprintf(stderr, " <%s>", opts->argh);
- } else {
+ if (opts->argh)
+ pos += usage_argh(opts);
+ else {
if (opts->flags & PARSE_OPT_OPTARG)
if (opts->long_name)
pos += fprintf(stderr, "[=...]");
@@ -439,7 +555,7 @@ int usage_with_options_internal(const char * const *usagestr,
pos += fprintf(stderr, " ...");
}
break;
- default: /* OPTION_{BIT,BOOLEAN,SET_INT,SET_PTR} */
+ default: /* OPTION_{BIT,BOOLEAN,NUMBER,SET_INT,SET_PTR} */
break;
}
@@ -536,15 +652,3 @@ int parse_opt_with_commit(const struct option *opt, const char *arg, int unset)
commit_list_insert(commit, opt->value);
return 0;
}
-
-/*
- * This should really be OPTION_FILENAME type as a part of
- * parse_options that take prefix to do this while parsing.
- */
-extern const char *parse_options_fix_filename(const char *prefix, const char *file)
-{
- if (!file || !prefix || is_absolute_path(file) || !strcmp("-", file))
- return file;
- return prefix_filename(prefix, strlen(prefix), file);
-}
-
diff --git a/parse-options.h b/parse-options.h
index b54eec1..5653dba 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -6,8 +6,10 @@ enum parse_opt_type {
OPTION_END,
OPTION_ARGUMENT,
OPTION_GROUP,
+ OPTION_NUMBER,
/* options with no arguments */
OPTION_BIT,
+ OPTION_NEGBIT,
OPTION_BOOLEAN, /* _INCR would have been a better name */
OPTION_SET_INT,
OPTION_SET_PTR,
@@ -15,6 +17,7 @@ enum parse_opt_type {
OPTION_STRING,
OPTION_INTEGER,
OPTION_CALLBACK,
+ OPTION_FILENAME
};
enum parse_opt_flags {
@@ -31,6 +34,8 @@ enum parse_opt_option_flags {
PARSE_OPT_NONEG = 4,
PARSE_OPT_HIDDEN = 8,
PARSE_OPT_LASTARG_DEFAULT = 16,
+ PARSE_OPT_NODASH = 32,
+ PARSE_OPT_LITERAL_ARGHELP = 64,
};
struct option;
@@ -64,8 +69,17 @@ typedef int parse_opt_cb(const struct option *, const char *arg, int unset);
* PARSE_OPT_OPTARG: says that the argument is optional (not for BOOLEANs)
* PARSE_OPT_NOARG: says that this option takes no argument, for CALLBACKs
* PARSE_OPT_NONEG: says that this option cannot be negated
- * PARSE_OPT_HIDDEN this option is skipped in the default usage, showed in
- * the long one.
+ * PARSE_OPT_HIDDEN: this option is skipped in the default usage, and
+ * shown only in the full usage.
+ * PARSE_OPT_LASTARG_DEFAULT: says that this option will take the default
+ * value if no argument is given when the option
+ * is last on the command line. If the option is
+ * not last it will require an argument.
+ * Should not be used with PARSE_OPT_OPTARG.
+ * PARSE_OPT_NODASH: this option doesn't start with a dash.
+ * PARSE_OPT_LITERAL_ARGHELP: says that argh shouldn't be enclosed in brackets
+ * (i.e. '<argh>') in the help message.
+ * Useful for options with multiple parameters.
*
* `callback`::
* pointer to the callback to use for OPTION_CALLBACK.
@@ -93,6 +107,7 @@ struct option {
#define OPT_ARGUMENT(l, h) { OPTION_ARGUMENT, 0, (l), NULL, NULL, (h) }
#define OPT_GROUP(h) { OPTION_GROUP, 0, NULL, NULL, NULL, (h) }
#define OPT_BIT(s, l, v, h, b) { OPTION_BIT, (s), (l), (v), NULL, (h), 0, NULL, (b) }
+#define OPT_NEGBIT(s, l, v, h, b) { OPTION_NEGBIT, (s), (l), (v), NULL, (h), 0, NULL, (b) }
#define OPT_BOOLEAN(s, l, v, h) { OPTION_BOOLEAN, (s), (l), (v), NULL, (h) }
#define OPT_SET_INT(s, l, v, h, i) { OPTION_SET_INT, (s), (l), (v), NULL, (h), 0, NULL, (i) }
#define OPT_SET_PTR(s, l, v, h, p) { OPTION_SET_PTR, (s), (l), (v), NULL, (h), 0, NULL, (p) }
@@ -103,12 +118,17 @@ struct option {
parse_opt_approxidate_cb }
#define OPT_CALLBACK(s, l, v, a, h, f) \
{ OPTION_CALLBACK, (s), (l), (v), (a), (h), 0, (f) }
+#define OPT_NUMBER_CALLBACK(v, h, f) \
+ { OPTION_NUMBER, 0, NULL, (v), NULL, (h), \
+ PARSE_OPT_NOARG | PARSE_OPT_NONEG, (f) }
+#define OPT_FILENAME(s, l, v, h) { OPTION_FILENAME, (s), (l), (v), \
+ "FILE", (h) }
/* parse_options() will filter out the processed options and leave the
* non-option arguments in argv[].
* Returns the number of arguments left in argv[].
*/
-extern int parse_options(int argc, const char **argv,
+extern int parse_options(int argc, const char **argv, const char *prefix,
const struct option *options,
const char * const usagestr[], int flags);
@@ -134,13 +154,15 @@ struct parse_opt_ctx_t {
int argc, cpidx;
const char *opt;
int flags;
+ const char *prefix;
};
extern int parse_options_usage(const char * const *usagestr,
const struct option *opts);
extern void parse_options_start(struct parse_opt_ctx_t *ctx,
- int argc, const char **argv, int flags);
+ int argc, const char **argv, const char *prefix,
+ int flags);
extern int parse_options_step(struct parse_opt_ctx_t *ctx,
const struct option *options,
@@ -168,6 +190,4 @@ extern int parse_opt_with_commit(const struct option *, const char *, int);
"use <n> digits to display SHA-1s", \
PARSE_OPT_OPTARG, &parse_opt_abbrev_cb, 0 }
-extern const char *parse_options_fix_filename(const char *prefix, const char *file);
-
#endif
diff --git a/path.c b/path.c
index 8a0a674..047fdb0 100644
--- a/path.c
+++ b/path.c
@@ -139,6 +139,22 @@ int git_mkstemp(char *path, size_t len, const char *template)
return mkstemp(path);
}
+/* git_mkstemps() - create tmp file with suffix honoring TMPDIR variable. */
+int git_mkstemps(char *path, size_t len, const char *template, int suffix_len)
+{
+ const char *tmp;
+ size_t n;
+
+ tmp = getenv("TMPDIR");
+ if (!tmp)
+ tmp = "/tmp";
+ n = snprintf(path, len, "%s/%s", tmp, template);
+ if (len <= n) {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+ return mkstemps(path, suffix_len);
+}
int validate_headref(const char *path)
{
diff --git a/perl/Git.pm b/perl/Git.pm
index 291ff5b..e8df55d 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -185,7 +185,7 @@ sub repository {
if ($dir) {
$dir =~ m#^/# or $dir = $opts{Directory} . '/' . $dir;
- $opts{Repository} = $dir;
+ $opts{Repository} = abs_path($dir);
# If --git-dir went ok, this shouldn't die either.
my $prefix = $search->command_oneline('rev-parse', '--show-prefix');
@@ -1280,6 +1280,8 @@ sub _cmd_exec {
my ($self, @args) = @_;
if ($self) {
$self->repo_path() and $ENV{'GIT_DIR'} = $self->repo_path();
+ $self->repo_path() and $self->wc_path()
+ and $ENV{'GIT_WORK_TREE'} = $self->wc_path();
$self->wc_path() and chdir($self->wc_path());
$self->wc_subdir() and chdir($self->wc_subdir());
}
diff --git a/pretty.c b/pretty.c
index a0ef356..e5328da 100644
--- a/pretty.c
+++ b/pretty.c
@@ -284,7 +284,7 @@ static char *replace_encoding_header(char *buf, const char *encoding)
static char *logmsg_reencode(const struct commit *commit,
const char *output_encoding)
{
- static const char *utf8 = "utf-8";
+ static const char *utf8 = "UTF-8";
const char *use_encoding;
char *encoding;
char *out;
@@ -881,7 +881,7 @@ char *reencode_commit_message(const struct commit *commit, const char **encoding
? git_log_output_encoding
: git_commit_encoding);
if (!encoding)
- encoding = "utf-8";
+ encoding = "UTF-8";
if (encoding_p)
*encoding_p = encoding;
return logmsg_reencode(commit, encoding);
diff --git a/progress.c b/progress.c
index 55a8687..621c34e 100644
--- a/progress.c
+++ b/progress.c
@@ -121,13 +121,13 @@ static void throughput_string(struct throughput *tp, off_t total,
(int)(total >> 30),
(int)(total & ((1 << 30) - 1)) / 10737419);
} else if (total > 1 << 20) {
+ int x = total + 5243; /* for rounding */
l -= snprintf(tp->display, l, ", %u.%2.2u MiB",
- (int)(total >> 20),
- ((int)(total & ((1 << 20) - 1)) * 100) >> 20);
+ x >> 20, ((x & ((1 << 20) - 1)) * 100) >> 20);
} else if (total > 1 << 10) {
+ int x = total + 5; /* for rounding */
l -= snprintf(tp->display, l, ", %u.%2.2u KiB",
- (int)(total >> 10),
- ((int)(total & ((1 << 10) - 1)) * 100) >> 10);
+ x >> 10, ((x & ((1 << 10) - 1)) * 100) >> 10);
} else {
l -= snprintf(tp->display, l, ", %u bytes", (int)total);
}
diff --git a/reflog-walk.c b/reflog-walk.c
index fd065f4..5623ea6 100644
--- a/reflog-walk.c
+++ b/reflog-walk.c
@@ -241,7 +241,7 @@ void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit)
commit->object.flags &= ~(ADDED | SEEN | SHOWN);
}
-void show_reflog_message(struct reflog_walk_info* info, int oneline,
+void show_reflog_message(struct reflog_walk_info *info, int oneline,
enum date_mode dmode)
{
if (info && info->last_commit_reflog) {
diff --git a/refs.c b/refs.c
index e65a3b4..24438c6 100644
--- a/refs.c
+++ b/refs.c
@@ -682,12 +682,13 @@ int for_each_rawref(each_ref_fn fn, void *cb_data)
* - it has ASCII control character, "~", "^", ":" or SP, anywhere, or
* - it ends with a "/".
* - it ends with ".lock"
+ * - it contains a "\" (backslash)
*/
static inline int bad_ref_char(int ch)
{
if (((unsigned) ch) <= ' ' ||
- ch == '~' || ch == '^' || ch == ':')
+ ch == '~' || ch == '^' || ch == ':' || ch == '\\')
return 1;
/* 2.13 Pattern Matching Notation */
if (ch == '?' || ch == '[') /* Unsupported */
@@ -750,9 +751,8 @@ int check_ref_format(const char *ref)
}
}
-const char *prettify_ref(const struct ref *ref)
+const char *prettify_refname(const char *name)
{
- const char *name = ref->name;
return name + (
!prefixcmp(name, "refs/heads/") ? 11 :
!prefixcmp(name, "refs/tags/") ? 10 :
@@ -893,8 +893,10 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char
* name is a proper prefix of our refname.
*/
if (missing &&
- !is_refname_available(ref, NULL, get_packed_refs(), 0))
+ !is_refname_available(ref, NULL, get_packed_refs(), 0)) {
+ last_errno = ENOTDIR;
goto error_return;
+ }
lock->lk = xcalloc(1, sizeof(struct lock_file));
@@ -1002,12 +1004,10 @@ int delete_ref(const char *refname, const unsigned char *sha1, int delopt)
} else {
path = git_path("%s", refname);
}
- err = unlink(path);
- if (err && errno != ENOENT) {
+ err = unlink_or_warn(path);
+ if (err && errno != ENOENT)
ret = 1;
- error("unlink(%s) failed: %s",
- path, strerror(errno));
- }
+
if (!(delopt & REF_NODEREF))
lock->lk->filename[i] = '.';
}
@@ -1017,10 +1017,7 @@ int delete_ref(const char *refname, const unsigned char *sha1, int delopt)
*/
ret |= repack_without_ref(refname);
- err = unlink(git_path("logs/%s", lock->ref_name));
- if (err && errno != ENOENT)
- warning("unlink(%s) failed: %s",
- git_path("logs/%s", lock->ref_name), strerror(errno));
+ unlink_or_warn(git_path("logs/%s", lock->ref_name));
invalidate_cached_refs();
unlock_ref(lock);
return ret;
@@ -1381,7 +1378,7 @@ int create_symref(const char *ref_target, const char *refs_heads_master,
if (adjust_shared_perm(git_HEAD)) {
error("Unable to fix permissions on %s", lockpath);
error_unlink_return:
- unlink(lockpath);
+ unlink_or_warn(lockpath);
error_free_return:
free(git_HEAD);
return -1;
diff --git a/refs.h b/refs.h
index 29d17a4..c11f6a6 100644
--- a/refs.h
+++ b/refs.h
@@ -80,7 +80,7 @@ extern int for_each_reflog(each_ref_fn, void *);
#define CHECK_REF_FORMAT_WILDCARD (-3)
extern int check_ref_format(const char *target);
-extern const char *prettify_ref(const struct ref *ref);
+extern const char *prettify_refname(const char *refname);
extern char *shorten_unambiguous_ref(const char *ref, int strict);
/** rename ref, return 0 on success **/
diff --git a/remote.c b/remote.c
index 91f7485..08a5964 100644
--- a/remote.c
+++ b/remote.c
@@ -366,7 +366,7 @@ static int handle_config(const char *key, const char *value, void *cb)
}
subkey = strrchr(name, '.');
if (!subkey)
- return error("Config with no key for remote %s", name);
+ return 0;
remote = make_remote(name, subkey - name);
remote->origin = REMOTE_CONFIG;
if (!strcmp(subkey, ".mirror"))
@@ -1085,12 +1085,20 @@ static const struct refspec *check_pattern_match(const struct refspec *rs,
return NULL;
}
+static struct ref **tail_ref(struct ref **head)
+{
+ struct ref **tail = head;
+ while (*tail)
+ tail = &((*tail)->next);
+ return tail;
+}
+
/*
* Note. This is used only by "push"; refspec matching rules for
* push and fetch are subtly different, so do not try to reuse it
* without thinking.
*/
-int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
+int match_refs(struct ref *src, struct ref **dst,
int nr_refspec, const char **refspec, int flags)
{
struct refspec *rs;
@@ -1098,13 +1106,14 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
int send_mirror = flags & MATCH_REFS_MIRROR;
int errs;
static const char *default_refspec[] = { ":", 0 };
+ struct ref **dst_tail = tail_ref(dst);
if (!nr_refspec) {
nr_refspec = 1;
refspec = default_refspec;
}
rs = parse_push_refspec(nr_refspec, (const char **) refspec);
- errs = match_explicit_refs(src, dst, dst_tail, rs, nr_refspec);
+ errs = match_explicit_refs(src, *dst, &dst_tail, rs, nr_refspec);
/* pick the remainder */
for ( ; src; src = src->next) {
@@ -1134,7 +1143,7 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
dst_side, &dst_name))
die("Didn't think it matches any more");
}
- dst_peer = find_ref_by_name(dst, dst_name);
+ dst_peer = find_ref_by_name(*dst, dst_name);
if (dst_peer) {
if (dst_peer->peer_ref)
/* We're already sending something to this ref. */
@@ -1150,7 +1159,7 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
goto free_name;
/* Create a new one and link it */
- dst_peer = make_linked_ref(dst_name, dst_tail);
+ dst_peer = make_linked_ref(dst_name, &dst_tail);
hashcpy(dst_peer->new_sha1, src->new_sha1);
}
dst_peer->peer_ref = copy_ref(src);
@@ -1399,13 +1408,13 @@ int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs)
base = branch->merge[0]->dst;
if (!resolve_ref(base, sha1, 1, NULL))
return 0;
- theirs = lookup_commit(sha1);
+ theirs = lookup_commit_reference(sha1);
if (!theirs)
return 0;
if (!resolve_ref(branch->refname, sha1, 1, NULL))
return 0;
- ours = lookup_commit(sha1);
+ ours = lookup_commit_reference(sha1);
if (!ours)
return 0;
diff --git a/remote.h b/remote.h
index 99706a8..257a555 100644
--- a/remote.h
+++ b/remote.h
@@ -85,7 +85,7 @@ void ref_remove_duplicates(struct ref *ref_map);
int valid_fetch_refspec(const char *refspec);
struct refspec *parse_fetch_refspec(int nr_refspec, const char **refspec);
-int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
+int match_refs(struct ref *src, struct ref **dst,
int nr_refspec, const char **refspec, int all);
/*
diff --git a/rerere.c b/rerere.c
index 713c6e1..87360dc 100644
--- a/rerere.c
+++ b/rerere.c
@@ -173,7 +173,7 @@ static int handle_file(const char *path,
git_SHA1_Final(sha1, &ctx);
if (hunk != RR_CONTEXT) {
if (output)
- unlink(output);
+ unlink_or_warn(output);
return error("Could not parse conflict hunks in %s", path);
}
if (wrerror)
diff --git a/revision.c b/revision.c
index 18b7ebb..bf58448 100644
--- a/revision.c
+++ b/revision.c
@@ -256,10 +256,12 @@ static int everybody_uninteresting(struct commit_list *orig)
/*
* The goal is to get REV_TREE_NEW as the result only if the
- * diff consists of all '+' (and no other changes), and
- * REV_TREE_DIFFERENT otherwise (of course if the trees are
- * the same we want REV_TREE_SAME). That means that once we
- * get to REV_TREE_DIFFERENT, we do not have to look any further.
+ * diff consists of all '+' (and no other changes), REV_TREE_OLD
+ * if the whole diff is removal of old data, and otherwise
+ * REV_TREE_DIFFERENT (of course if the trees are the same we
+ * want REV_TREE_SAME).
+ * That means that once we get to REV_TREE_DIFFERENT, we do not
+ * have to look any further.
*/
static int tree_difference = REV_TREE_SAME;
@@ -268,22 +270,9 @@ static void file_add_remove(struct diff_options *options,
const unsigned char *sha1,
const char *fullpath)
{
- int diff = REV_TREE_DIFFERENT;
+ int diff = addremove == '+' ? REV_TREE_NEW : REV_TREE_OLD;
- /*
- * Is it an add of a new file? It means that the old tree
- * didn't have it at all, so we will turn "REV_TREE_SAME" ->
- * "REV_TREE_NEW", but leave any "REV_TREE_DIFFERENT" alone
- * (and if it already was "REV_TREE_NEW", we'll keep it
- * "REV_TREE_NEW" of course).
- */
- if (addremove == '+') {
- diff = tree_difference;
- if (diff != REV_TREE_SAME)
- return;
- diff = REV_TREE_NEW;
- }
- tree_difference = diff;
+ tree_difference |= diff;
if (tree_difference == REV_TREE_DIFFERENT)
DIFF_OPT_SET(options, HAS_CHANGES);
}
@@ -305,6 +294,8 @@ static int rev_compare_tree(struct rev_info *revs, struct commit *parent, struct
if (!t1)
return REV_TREE_NEW;
+ if (!t2)
+ return REV_TREE_OLD;
if (revs->simplify_by_decoration) {
/*
@@ -323,8 +314,7 @@ static int rev_compare_tree(struct rev_info *revs, struct commit *parent, struct
if (!revs->prune_data)
return REV_TREE_SAME;
}
- if (!t2)
- return REV_TREE_DIFFERENT;
+
tree_difference = REV_TREE_SAME;
DIFF_OPT_CLR(&revs->pruning, HAS_CHANGES);
if (diff_tree_sha1(t1->object.sha1, t2->object.sha1, "",
@@ -429,6 +419,7 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
p->parents = NULL;
}
/* fallthrough */
+ case REV_TREE_OLD:
case REV_TREE_DIFFERENT:
tree_changed = 1;
pp = &parent->next;
diff --git a/revision.h b/revision.h
index be39e7d..227164c 100644
--- a/revision.h
+++ b/revision.h
@@ -118,8 +118,9 @@ struct rev_info {
};
#define REV_TREE_SAME 0
-#define REV_TREE_NEW 1
-#define REV_TREE_DIFFERENT 2
+#define REV_TREE_NEW 1 /* Only new files */
+#define REV_TREE_OLD 2 /* Only files removed */
+#define REV_TREE_DIFFERENT 3 /* Mixed changes */
/* revision.c */
void read_revisions_from_stdin(struct rev_info *revs);
diff --git a/run-command.c b/run-command.c
index b05c734..eb2efc3 100644
--- a/run-command.c
+++ b/run-command.c
@@ -106,7 +106,7 @@ int start_command(struct child_process *cmd)
if (cmd->env) {
for (; *cmd->env; cmd->env++) {
if (strchr(*cmd->env, '='))
- putenv((char*)*cmd->env);
+ putenv((char *)*cmd->env);
else
unsetenv(*cmd->env);
}
diff --git a/send-pack.h b/send-pack.h
index 83d76c7..1d7b1b3 100644
--- a/send-pack.h
+++ b/send-pack.h
@@ -6,6 +6,7 @@ struct send_pack_args {
send_mirror:1,
force_update:1,
use_thin_pack:1,
+ use_ofs_delta:1,
dry_run:1;
};
diff --git a/server-info.c b/server-info.c
index 66b0d9d..4098ca2 100644
--- a/server-info.c
+++ b/server-info.c
@@ -132,8 +132,8 @@ static int read_pack_info_file(const char *infofile)
static int compare_info(const void *a_, const void *b_)
{
- struct pack_info * const* a = a_;
- struct pack_info * const* b = b_;
+ struct pack_info *const *a = a_;
+ struct pack_info *const *b = b_;
if (0 <= (*a)->old_num && 0 <= (*b)->old_num)
/* Keep the order in the original */
@@ -246,7 +246,7 @@ int update_server_info(int force)
errs = errs | update_info_packs(force);
/* remove leftover rev-cache file if there is any */
- unlink(git_path("info/rev-cache"));
+ unlink_or_warn(git_path("info/rev-cache"));
return errs;
}
diff --git a/sha1_file.c b/sha1_file.c
index 8fe135d..e73cd4f 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -720,6 +720,8 @@ static int open_packed_git_1(struct packed_git *p)
return error("packfile %s index unavailable", p->pack_name);
p->pack_fd = open(p->pack_name, O_RDONLY);
+ while (p->pack_fd < 0 && errno == EMFILE && unuse_one_window(p, -1))
+ p->pack_fd = open(p->pack_name, O_RDONLY);
if (p->pack_fd < 0 || fstat(p->pack_fd, &st))
return -1;
@@ -791,7 +793,7 @@ static int in_window(struct pack_window *win, off_t offset)
&& (offset + 20) <= (win_off + win->len);
}
-unsigned char* use_pack(struct packed_git *p,
+unsigned char *use_pack(struct packed_git *p,
struct pack_window **w_cursor,
off_t offset,
unsigned int *left)
@@ -937,6 +939,8 @@ static void prepare_packed_git_one(char *objdir, int local)
sprintf(path, "%s/pack", objdir);
len = strlen(path);
dir = opendir(path);
+ while (!dir && errno == EMFILE && unuse_one_window(packed_git, -1))
+ dir = opendir(path);
if (!dir) {
if (errno != ENOENT)
error("unable to open object pack directory: %s: %s",
@@ -2225,7 +2229,9 @@ int move_temp_to_file(const char *tmpfile, const char *filename)
{
int ret = 0;
- if (link(tmpfile, filename))
+ if (object_creation_mode == OBJECT_CREATION_USES_RENAMES)
+ goto try_rename;
+ else if (link(tmpfile, filename))
ret = errno;
/*
@@ -2240,11 +2246,12 @@ int move_temp_to_file(const char *tmpfile, const char *filename)
* left to unlink.
*/
if (ret && ret != EEXIST) {
+ try_rename:
if (!rename(tmpfile, filename))
goto out;
ret = errno;
}
- unlink(tmpfile);
+ unlink_or_warn(tmpfile);
if (ret) {
if (ret != EEXIST) {